修改了登录im的逻辑
This commit is contained in:
@@ -64,6 +64,15 @@
|
|||||||
E8D15AEA2B8CD77800369467 /* H5Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8D15AE92B8CD77800369467 /* H5Utils.swift */; };
|
E8D15AEA2B8CD77800369467 /* H5Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8D15AE92B8CD77800369467 /* H5Utils.swift */; };
|
||||||
E8E4AAB52B8F8E3A0096D77C /* AuthItmeButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8E4AAB42B8F8E3A0096D77C /* AuthItmeButton.swift */; };
|
E8E4AAB52B8F8E3A0096D77C /* AuthItmeButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8E4AAB42B8F8E3A0096D77C /* AuthItmeButton.swift */; };
|
||||||
E8E4AAB72B8F95CA0096D77C /* AuthAppleManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8E4AAB62B8F95CA0096D77C /* AuthAppleManager.swift */; };
|
E8E4AAB72B8F95CA0096D77C /* AuthAppleManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8E4AAB62B8F95CA0096D77C /* AuthAppleManager.swift */; };
|
||||||
|
E8E4AB182B9019E50096D77C /* ChatKeyboardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8E4AB172B9019E50096D77C /* ChatKeyboardView.swift */; };
|
||||||
|
E8E4AB1B2B901AF50096D77C /* UIView+.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8E4AB1A2B901AF50096D77C /* UIView+.swift */; };
|
||||||
|
E8E4AB1D2B901B9D0096D77C /* ChatKeyboard+.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8E4AB1C2B901B9D0096D77C /* ChatKeyboard+.swift */; };
|
||||||
|
E8E4AB1F2B901BFC0096D77C /* ChatGrowingTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8E4AB1E2B901BFC0096D77C /* ChatGrowingTextView.swift */; };
|
||||||
|
E8E4AB212B901CD50096D77C /* ChatMoreMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8E4AB202B901CD50096D77C /* ChatMoreMenuView.swift */; };
|
||||||
|
E8E4AB232B901E0C0096D77C /* ChatMoreMnueConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8E4AB222B901E0C0096D77C /* ChatMoreMnueConfig.swift */; };
|
||||||
|
E8E4AB252B901E400096D77C /* ChatMoreMenuCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8E4AB242B901E400096D77C /* ChatMoreMenuCell.swift */; };
|
||||||
|
E8E4AB282B902A9C0096D77C /* ChatListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8E4AB272B902A9C0096D77C /* ChatListCell.swift */; };
|
||||||
|
E8FF28B42B90ADBE005D2BE7 /* AppKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8FF28B32B90ADBE005D2BE7 /* AppKeys.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
@@ -132,6 +141,15 @@
|
|||||||
E8E4AAB42B8F8E3A0096D77C /* AuthItmeButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthItmeButton.swift; sourceTree = "<group>"; };
|
E8E4AAB42B8F8E3A0096D77C /* AuthItmeButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthItmeButton.swift; sourceTree = "<group>"; };
|
||||||
E8E4AAB62B8F95CA0096D77C /* AuthAppleManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthAppleManager.swift; sourceTree = "<group>"; };
|
E8E4AAB62B8F95CA0096D77C /* AuthAppleManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthAppleManager.swift; sourceTree = "<group>"; };
|
||||||
E8E4AAB82B8F99B90096D77C /* yinmeng-ios.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "yinmeng-ios.entitlements"; sourceTree = "<group>"; };
|
E8E4AAB82B8F99B90096D77C /* yinmeng-ios.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "yinmeng-ios.entitlements"; sourceTree = "<group>"; };
|
||||||
|
E8E4AB172B9019E50096D77C /* ChatKeyboardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatKeyboardView.swift; sourceTree = "<group>"; };
|
||||||
|
E8E4AB1A2B901AF50096D77C /* UIView+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+.swift"; sourceTree = "<group>"; };
|
||||||
|
E8E4AB1C2B901B9D0096D77C /* ChatKeyboard+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ChatKeyboard+.swift"; sourceTree = "<group>"; };
|
||||||
|
E8E4AB1E2B901BFC0096D77C /* ChatGrowingTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatGrowingTextView.swift; sourceTree = "<group>"; };
|
||||||
|
E8E4AB202B901CD50096D77C /* ChatMoreMenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatMoreMenuView.swift; sourceTree = "<group>"; };
|
||||||
|
E8E4AB222B901E0C0096D77C /* ChatMoreMnueConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatMoreMnueConfig.swift; sourceTree = "<group>"; };
|
||||||
|
E8E4AB242B901E400096D77C /* ChatMoreMenuCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatMoreMenuCell.swift; sourceTree = "<group>"; };
|
||||||
|
E8E4AB272B902A9C0096D77C /* ChatListCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatListCell.swift; sourceTree = "<group>"; };
|
||||||
|
E8FF28B32B90ADBE005D2BE7 /* AppKeys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppKeys.swift; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
@@ -182,6 +200,7 @@
|
|||||||
E8479E3E2B8DC624009AF878 /* View */ = {
|
E8479E3E2B8DC624009AF878 /* View */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
E8E4AB262B902A750096D77C /* ChatList */,
|
||||||
E8479E3C2B8DC61F009AF878 /* ChatBaseCell.swift */,
|
E8479E3C2B8DC61F009AF878 /* ChatBaseCell.swift */,
|
||||||
E8479E472B8DD6E1009AF878 /* ChatTextCell.swift */,
|
E8479E472B8DD6E1009AF878 /* ChatTextCell.swift */,
|
||||||
);
|
);
|
||||||
@@ -240,6 +259,7 @@
|
|||||||
E86A43AB2B85DFC20084C04D /* Extension */ = {
|
E86A43AB2B85DFC20084C04D /* Extension */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
E8E4AB192B901AEA0096D77C /* UIView */,
|
||||||
E8479E442B8DD5B5009AF878 /* Date */,
|
E8479E442B8DD5B5009AF878 /* Date */,
|
||||||
E8D15AA42B89B0BA00369467 /* List */,
|
E8D15AA42B89B0BA00369467 /* List */,
|
||||||
E86A43E62B884C520084C04D /* String */,
|
E86A43E62B884C520084C04D /* String */,
|
||||||
@@ -308,6 +328,7 @@
|
|||||||
E86A43BE2B8620C40084C04D /* Utils.swift */,
|
E86A43BE2B8620C40084C04D /* Utils.swift */,
|
||||||
E86A43D22B8773C90084C04D /* APPUtils.swift */,
|
E86A43D22B8773C90084C04D /* APPUtils.swift */,
|
||||||
E8D15AE92B8CD77800369467 /* H5Utils.swift */,
|
E8D15AE92B8CD77800369467 /* H5Utils.swift */,
|
||||||
|
E8FF28B32B90ADBE005D2BE7 /* AppKeys.swift */,
|
||||||
);
|
);
|
||||||
path = Utils;
|
path = Utils;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -423,6 +444,7 @@
|
|||||||
E8D15AB42B8B001900369467 /* Chat */ = {
|
E8D15AB42B8B001900369467 /* Chat */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
E8E4AB162B9019CE0096D77C /* Keyboard */,
|
||||||
E8479E492B8DDA3F009AF878 /* Tool */,
|
E8479E492B8DDA3F009AF878 /* Tool */,
|
||||||
E8479E3F2B8DC6A6009AF878 /* Model */,
|
E8479E3F2B8DC6A6009AF878 /* Model */,
|
||||||
E8479E3E2B8DC624009AF878 /* View */,
|
E8479E3E2B8DC624009AF878 /* View */,
|
||||||
@@ -477,6 +499,35 @@
|
|||||||
path = Web;
|
path = Web;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
E8E4AB162B9019CE0096D77C /* Keyboard */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
E8E4AB172B9019E50096D77C /* ChatKeyboardView.swift */,
|
||||||
|
E8E4AB1E2B901BFC0096D77C /* ChatGrowingTextView.swift */,
|
||||||
|
E8E4AB1C2B901B9D0096D77C /* ChatKeyboard+.swift */,
|
||||||
|
E8E4AB202B901CD50096D77C /* ChatMoreMenuView.swift */,
|
||||||
|
E8E4AB222B901E0C0096D77C /* ChatMoreMnueConfig.swift */,
|
||||||
|
E8E4AB242B901E400096D77C /* ChatMoreMenuCell.swift */,
|
||||||
|
);
|
||||||
|
path = Keyboard;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
E8E4AB192B901AEA0096D77C /* UIView */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
E8E4AB1A2B901AF50096D77C /* UIView+.swift */,
|
||||||
|
);
|
||||||
|
path = UIView;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
E8E4AB262B902A750096D77C /* ChatList */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
E8E4AB272B902A9C0096D77C /* ChatListCell.swift */,
|
||||||
|
);
|
||||||
|
path = ChatList;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
E8EE60802B8858A500D02F6E /* Security */ = {
|
E8EE60802B8858A500D02F6E /* Security */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -628,19 +679,25 @@
|
|||||||
E8479E3B2B8DC5FA009AF878 /* ChatViewModel.swift in Sources */,
|
E8479E3B2B8DC5FA009AF878 /* ChatViewModel.swift in Sources */,
|
||||||
E8479E412B8DC6BC009AF878 /* ChatBaseObject.swift in Sources */,
|
E8479E412B8DC6BC009AF878 /* ChatBaseObject.swift in Sources */,
|
||||||
E86A43AA2B85DFA90084C04D /* BaseViewController.swift in Sources */,
|
E86A43AA2B85DFA90084C04D /* BaseViewController.swift in Sources */,
|
||||||
|
E8E4AB1F2B901BFC0096D77C /* ChatGrowingTextView.swift in Sources */,
|
||||||
E884E85F2B6900C500ADE6EE /* AppDelegate.swift in Sources */,
|
E884E85F2B6900C500ADE6EE /* AppDelegate.swift in Sources */,
|
||||||
E8D15AEA2B8CD77800369467 /* H5Utils.swift in Sources */,
|
E8D15AEA2B8CD77800369467 /* H5Utils.swift in Sources */,
|
||||||
E8D15AAA2B8ACC6B00369467 /* YMNetworkFun.swift in Sources */,
|
E8D15AAA2B8ACC6B00369467 /* YMNetworkFun.swift in Sources */,
|
||||||
E8D15AB82B8B003C00369467 /* UserInfoVC.swift in Sources */,
|
E8D15AB82B8B003C00369467 /* UserInfoVC.swift in Sources */,
|
||||||
E86A43B82B85F0B80084C04D /* AuthLaunchVC.swift in Sources */,
|
E86A43B82B85F0B80084C04D /* AuthLaunchVC.swift in Sources */,
|
||||||
|
E8E4AB252B901E400096D77C /* ChatMoreMenuCell.swift in Sources */,
|
||||||
E86A43C82B8743EA0084C04D /* AuthFillDataVC.swift in Sources */,
|
E86A43C82B8743EA0084C04D /* AuthFillDataVC.swift in Sources */,
|
||||||
E86A43CD2B874C8E0084C04D /* BaseView.swift in Sources */,
|
E86A43CD2B874C8E0084C04D /* BaseView.swift in Sources */,
|
||||||
E8D15AE82B8CD47100369467 /* WebViewController.swift in Sources */,
|
E8D15AE82B8CD47100369467 /* WebViewController.swift in Sources */,
|
||||||
E8D15AA12B89AF4F00369467 /* UserTokenObject.swift in Sources */,
|
E8D15AA12B89AF4F00369467 /* UserTokenObject.swift in Sources */,
|
||||||
233E515B2B8C849600582F9C /* PlanetStarClickItemView.swift in Sources */,
|
233E515B2B8C849600582F9C /* PlanetStarClickItemView.swift in Sources */,
|
||||||
|
E8FF28B42B90ADBE005D2BE7 /* AppKeys.swift in Sources */,
|
||||||
2311D6A92B8F405F001C70AB /* HomeVoiceChooseTypeView.swift in Sources */,
|
2311D6A92B8F405F001C70AB /* HomeVoiceChooseTypeView.swift in Sources */,
|
||||||
E8D15AB62B8B002700369467 /* ChatVC.swift in Sources */,
|
E8D15AB62B8B002700369467 /* ChatVC.swift in Sources */,
|
||||||
|
E8E4AB182B9019E50096D77C /* ChatKeyboardView.swift in Sources */,
|
||||||
|
E8E4AB232B901E0C0096D77C /* ChatMoreMnueConfig.swift in Sources */,
|
||||||
E86A43C62B862CC70084C04D /* UIImage+.swift in Sources */,
|
E86A43C62B862CC70084C04D /* UIImage+.swift in Sources */,
|
||||||
|
E8E4AB212B901CD50096D77C /* ChatMoreMenuView.swift in Sources */,
|
||||||
E86A43D32B8773C90084C04D /* APPUtils.swift in Sources */,
|
E86A43D32B8773C90084C04D /* APPUtils.swift in Sources */,
|
||||||
E86A43CB2B874C6F0084C04D /* AuthPrivacyView.swift in Sources */,
|
E86A43CB2B874C6F0084C04D /* AuthPrivacyView.swift in Sources */,
|
||||||
E8D15AC52B8C90D400369467 /* AboutUsVC.swift in Sources */,
|
E8D15AC52B8C90D400369467 /* AboutUsVC.swift in Sources */,
|
||||||
@@ -652,11 +709,14 @@
|
|||||||
E8479E4D2B8DDBC5009AF878 /* ChatAttributeTool.swift in Sources */,
|
E8479E4D2B8DDBC5009AF878 /* ChatAttributeTool.swift in Sources */,
|
||||||
E81A7BAF2B885B20009E736E /* MAIDESEncryptTool.m in Sources */,
|
E81A7BAF2B885B20009E736E /* MAIDESEncryptTool.m in Sources */,
|
||||||
E8D15AA82B89B74700369467 /* YMRequestX.swift in Sources */,
|
E8D15AA82B89B74700369467 /* YMRequestX.swift in Sources */,
|
||||||
|
E8E4AB1D2B901B9D0096D77C /* ChatKeyboard+.swift in Sources */,
|
||||||
2311D6A72B8F2CFA001C70AB /* HomeVoiceChooseItemVeiw.swift in Sources */,
|
2311D6A72B8F2CFA001C70AB /* HomeVoiceChooseItemVeiw.swift in Sources */,
|
||||||
E8D15AB02B8AFFCE00369467 /* HomeVoiceVC.swift in Sources */,
|
E8D15AB02B8AFFCE00369467 /* HomeVoiceVC.swift in Sources */,
|
||||||
|
E8E4AB282B902A9C0096D77C /* ChatListCell.swift in Sources */,
|
||||||
E86A43D52B8774B70084C04D /* AuthViewModel.swift in Sources */,
|
E86A43D52B8774B70084C04D /* AuthViewModel.swift in Sources */,
|
||||||
E8D15AB32B8B000400369467 /* PlanetStarVC.swift in Sources */,
|
E8D15AB32B8B000400369467 /* PlanetStarVC.swift in Sources */,
|
||||||
E8D15A9D2B899E1500369467 /* YMNetworkHelper.swift in Sources */,
|
E8D15A9D2B899E1500369467 /* YMNetworkHelper.swift in Sources */,
|
||||||
|
E8E4AB1B2B901AF50096D77C /* UIView+.swift in Sources */,
|
||||||
2311D69D2B8DC311001C70AB /* PlanetStarModel.swift in Sources */,
|
2311D69D2B8DC311001C70AB /* PlanetStarModel.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
Binary file not shown.
@@ -8,6 +8,7 @@
|
|||||||
import UIKit
|
import UIKit
|
||||||
import DeviceKit
|
import DeviceKit
|
||||||
import NSObject_Rx
|
import NSObject_Rx
|
||||||
|
import NIMSDK
|
||||||
@main
|
@main
|
||||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||||
var window: UIWindow?
|
var window: UIWindow?
|
||||||
@@ -18,7 +19,9 @@ var window: UIWindow?
|
|||||||
self.window = UIWindow.init(frame: UIScreen.main.bounds)
|
self.window = UIWindow.init(frame: UIScreen.main.bounds)
|
||||||
self.window?.backgroundColor = UIColor.white
|
self.window?.backgroundColor = UIColor.white
|
||||||
self.window?.rootViewController = BaseNavigationViewController(rootViewController:AuthLaunchVC())
|
self.window?.rootViewController = BaseNavigationViewController(rootViewController:AuthLaunchVC())
|
||||||
|
loadNIMSDK()
|
||||||
loginStateListener()
|
loginStateListener()
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,13 +37,36 @@ var window: UIWindow?
|
|||||||
if let uid = LoginTokenConfig.config.getAccountInfo()?.uid {
|
if let uid = LoginTokenConfig.config.getAccountInfo()?.uid {
|
||||||
UserViewModel.userVM.getUserInfo(uid: uid)
|
UserViewModel.userVM.getUserInfo(uid: uid)
|
||||||
}
|
}
|
||||||
|
if NIMSDK.shared().loginManager.isLogined() == false {
|
||||||
|
if let uid = LoginTokenConfig.config.getAccountInfo()?.uid, let token = LoginTokenConfig.config.getAccountInfo()?.netEaseToken {
|
||||||
|
NIMSDK.shared().loginManager.login("\(uid)", token: token) { error in
|
||||||
|
print("aaa")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
///去登录
|
||||||
|
self.window?.rootViewController = BaseNavigationViewController(rootViewController:AuthLaunchVC())
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
///去登录
|
///去登录
|
||||||
self.window?.rootViewController = BaseNavigationViewController(rootViewController:AuthLaunchVC())
|
self.window?.rootViewController = BaseNavigationViewController(rootViewController:AuthLaunchVC())
|
||||||
}
|
}
|
||||||
}).disposed(by: rx.disposeBag)
|
}).disposed(by: rx.disposeBag)
|
||||||
|
|
||||||
|
UserViewModel.userVM.userInfo.subscribe(onNext: { result in
|
||||||
|
if result.nick?.count ?? 0 <= 0 || result.avatar?.count ?? 0 <= 0 {
|
||||||
|
let fillVC = AuthFillDataVC()
|
||||||
|
fillVC.modalPresentationStyle = .fullScreen
|
||||||
|
YMRequestX.topViewController()?.navigationController?.present(fillVC, animated: true)
|
||||||
|
}
|
||||||
|
}).disposed(by: rx.disposeBag)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func loadNIMSDK() {
|
||||||
|
let opt = NIMSDKOption(appKey: AppKeys.nimAppid)
|
||||||
|
opt.apnsCername = "yinmeng_anps"
|
||||||
|
NIMSDK.shared().register(with: opt)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
// YMNetworkAPI.swift
|
// YMNetworkAPI.swift
|
||||||
// yinmeng-ios
|
// yinmeng-ios
|
||||||
//
|
//
|
||||||
// Created by MaiMang on 2024/2/24.
|
// Created by Mang on 2024/2/24.
|
||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
@@ -37,7 +37,7 @@ class YMNetworkHelper: NSObject {
|
|||||||
|
|
||||||
func requestSend(type:HTTPMethod,path:String,params:Dictionary<String, Any>, succeed:SessionCallSucceed?,fail:SessionCallFail?) -> Void {
|
func requestSend(type:HTTPMethod,path:String,params:Dictionary<String, Any>, succeed:SessionCallSucceed?,fail:SessionCallFail?) -> Void {
|
||||||
getHttpRequestHeaders()
|
getHttpRequestHeaders()
|
||||||
requestSend(type: type,host: "https://api.ymlive.fun/", path: path, params: params, encoding: URLEncoding.queryString, header: headersSet, succeed: succeed, fail: fail)
|
requestSend(type: type,host: AppKeys.api, path: path, params: params, encoding: URLEncoding.queryString, header: headersSet, succeed: succeed, fail: fail)
|
||||||
}
|
}
|
||||||
|
|
||||||
func requestSend(type:HTTPMethod,
|
func requestSend(type:HTTPMethod,
|
||||||
@@ -74,50 +74,50 @@ class YMNetworkHelper: NSObject {
|
|||||||
func analyzeThe(response1:AFDataResponse<Any>,
|
func analyzeThe(response1:AFDataResponse<Any>,
|
||||||
succeed2:SessionCallSucceed?,
|
succeed2:SessionCallSucceed?,
|
||||||
fail3: SessionCallFail?,uuid4:String) -> Void {
|
fail3: SessionCallFail?,uuid4:String) -> Void {
|
||||||
let maiUrlSss = response1.request?.url?.absoluteString ?? "unkown"
|
let UrlSss = response1.request?.url?.absoluteString ?? "unkown"
|
||||||
switch response1.result {
|
switch response1.result {
|
||||||
case .success:
|
case .success:
|
||||||
let maiResponNk :Dictionary = response1.value as? Dictionary<String, Any> ?? Dictionary.init()
|
let ResponNk :Dictionary = response1.value as? Dictionary<String, Any> ?? Dictionary.init()
|
||||||
let maiResultMo = maiResponNk
|
let ResultMo = ResponNk
|
||||||
if maiResultMo.keys.contains("code") {
|
if ResultMo.keys.contains("code") {
|
||||||
let maicodeNum :Int = maiResultMo["code"] as? Int ?? 0
|
let codeNum :Int = ResultMo["code"] as? Int ?? 0
|
||||||
if maicodeNum == 200 {
|
if codeNum == 200 {
|
||||||
if maiResultMo.keys.contains("data") {
|
if ResultMo.keys.contains("data") {
|
||||||
let maiDDD = maiResultMo["data"] as Any
|
let DDD = ResultMo["data"] as Any
|
||||||
succeed2?(maiDDD)
|
succeed2?(DDD)
|
||||||
}else{
|
}else{
|
||||||
succeed2?(Dictionary<String, Any>.init())
|
succeed2?(Dictionary<String, Any>.init())
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
if maicodeNum == 401 && maiUrlSss.contains("auth-center/sso/logout") == false {
|
if codeNum == 401 && UrlSss.contains("auth-center/sso/logout") == false {
|
||||||
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "MAISessionTickValid"), object: nil)
|
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "SessionTickValid"), object: nil)
|
||||||
sessionNetMana.cancelAllRequests()
|
sessionNetMana.cancelAllRequests()
|
||||||
}
|
}
|
||||||
var messageIn = response1.error.debugDescription
|
var messageIn = response1.error.debugDescription
|
||||||
if maiResultMo.keys.contains("message") { messageIn = maiResultMo["message"] as? String ?? "" }
|
if ResultMo.keys.contains("message") { messageIn = ResultMo["message"] as? String ?? "" }
|
||||||
fail3?(maicodeNum,messageIn)
|
fail3?(codeNum,messageIn)
|
||||||
}
|
}
|
||||||
} else if maiResultMo.keys.contains("errno") {
|
} else if ResultMo.keys.contains("errno") {
|
||||||
let maiCodeNum :Int = maiResultMo["errno"] as? Int ?? 0
|
let CodeNum :Int = ResultMo["errno"] as? Int ?? 0
|
||||||
if maiCodeNum == 0 {
|
if CodeNum == 0 {
|
||||||
if maiResultMo.keys.contains("data") {
|
if ResultMo.keys.contains("data") {
|
||||||
let dataSc = maiResultMo["data"] as Any
|
let dataSc = ResultMo["data"] as Any
|
||||||
succeed2?(dataSc)
|
succeed2?(dataSc)
|
||||||
}else{
|
}else{
|
||||||
succeed2?(Dictionary<String, Any>.init())
|
succeed2?(Dictionary<String, Any>.init())
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
var majmessageStr = response1.error.debugDescription
|
var majmessageStr = response1.error.debugDescription
|
||||||
if maiResultMo.keys.contains("errmsg") { majmessageStr = maiResultMo["errmsg"] as? String ?? ""}
|
if ResultMo.keys.contains("errmsg") { majmessageStr = ResultMo["errmsg"] as? String ?? ""}
|
||||||
fail3?(maiCodeNum,majmessageStr)
|
fail3?(CodeNum,majmessageStr)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fail3?(10000,"请求失败")
|
fail3?(10000,"请求失败")
|
||||||
}
|
}
|
||||||
case let .failure(error):
|
case let .failure(error):
|
||||||
var maiErrorMssg = response1.error?.errorDescription ?? ""
|
var ErrorMssg = response1.error?.errorDescription ?? ""
|
||||||
var maicodeNum = response1.error?.responseCode ?? 0
|
var codeNum = response1.error?.responseCode ?? 0
|
||||||
fail3?(maicodeNum,maiErrorMssg)
|
fail3?(codeNum,ErrorMssg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
17
yinmeng-ios/Base/Utils/AppKeys.swift
Normal file
17
yinmeng-ios/Base/Utils/AppKeys.swift
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
//
|
||||||
|
// AppKeys.swift
|
||||||
|
// yinmeng-ios
|
||||||
|
//
|
||||||
|
// Created by MaiMang on 2024/2/29.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
enum AppKeys {
|
||||||
|
#if DEBUG
|
||||||
|
static let nimAppid = "5d5a833a2d0ff1304a5d8bed53d2af5b"
|
||||||
|
static let api = "http://beta.api.ymlive.fun/"
|
||||||
|
#else
|
||||||
|
static let nimAppid = "5e76ec47632d86c30ce18eabfa332b6a"
|
||||||
|
static let api = "https://api.ymlive.fun/"
|
||||||
|
#endif
|
||||||
|
}
|
@@ -9,5 +9,6 @@ import Foundation
|
|||||||
|
|
||||||
enum H5Utils:String {
|
enum H5Utils:String {
|
||||||
case privacy = "modules/rule/privacy-wap.html"
|
case privacy = "modules/rule/privacy-wap.html"
|
||||||
|
case user = "modules/rule/protocol.html"
|
||||||
case logoff = "modules/logout/index.html"
|
case logoff = "modules/logout/index.html"
|
||||||
}
|
}
|
||||||
|
@@ -31,6 +31,4 @@ let TabHeight = (49)
|
|||||||
|
|
||||||
let DesKey = "1ea53d260ecf11e7b56e00163e046a26"
|
let DesKey = "1ea53d260ecf11e7b56e00163e046a26"
|
||||||
|
|
||||||
let API_URL = "http://beta.api.ymlive.fun"
|
|
||||||
|
|
||||||
let H5_URL = "http://beta.h5.ymlive.fun"
|
let H5_URL = "http://beta.h5.ymlive.fun"
|
||||||
|
161
yinmeng-ios/Extension/UIView/UIView+.swift
Normal file
161
yinmeng-ios/Extension/UIView/UIView+.swift
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
//
|
||||||
|
// UIView+.swift
|
||||||
|
// yinmeng-ios
|
||||||
|
//
|
||||||
|
// Created by MaiMang on 2024/2/29.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
extension UIView {
|
||||||
|
/// x
|
||||||
|
public var x : CGFloat {
|
||||||
|
|
||||||
|
get {
|
||||||
|
return self.frame.origin.x
|
||||||
|
}
|
||||||
|
set (x) {
|
||||||
|
var frame = self.frame
|
||||||
|
frame.origin.x = x
|
||||||
|
self.frame = frame
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// y
|
||||||
|
public var y : CGFloat {
|
||||||
|
|
||||||
|
get {
|
||||||
|
return self.frame.origin.y
|
||||||
|
}
|
||||||
|
set (y) {
|
||||||
|
var frame = self.frame
|
||||||
|
frame.origin.y = y
|
||||||
|
self.frame = frame
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// maxX
|
||||||
|
public var maxX : CGFloat {
|
||||||
|
|
||||||
|
get {
|
||||||
|
return self.frame.maxX
|
||||||
|
}
|
||||||
|
set(maxX) {
|
||||||
|
self.frame.origin.x = maxX - self.frame.size.width
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// maxY
|
||||||
|
public var maxY : CGFloat {
|
||||||
|
|
||||||
|
get {
|
||||||
|
return self.frame.maxY
|
||||||
|
}
|
||||||
|
set(maxY) {
|
||||||
|
self.frame.origin.y = maxY - self.frame.size.height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// width
|
||||||
|
public var width : CGFloat {
|
||||||
|
|
||||||
|
get {
|
||||||
|
return self.frame.size.width
|
||||||
|
}
|
||||||
|
set (width) {
|
||||||
|
var frame = self.frame
|
||||||
|
frame.size.width = width
|
||||||
|
self.frame = frame
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// height
|
||||||
|
public var height : CGFloat {
|
||||||
|
|
||||||
|
get {
|
||||||
|
return self.frame.size.height
|
||||||
|
}
|
||||||
|
set (height) {
|
||||||
|
var frame = self.frame
|
||||||
|
frame.size.height = height
|
||||||
|
self.frame = frame
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// centerX
|
||||||
|
public var centerX : CGFloat {
|
||||||
|
|
||||||
|
get {
|
||||||
|
return self.center.x
|
||||||
|
}
|
||||||
|
set (centerX) {
|
||||||
|
var center = self.center
|
||||||
|
center.x = centerX
|
||||||
|
self.center = center
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// centerY
|
||||||
|
public var centerY : CGFloat {
|
||||||
|
|
||||||
|
get {
|
||||||
|
return self.center.y
|
||||||
|
}
|
||||||
|
set (centerY) {
|
||||||
|
var center = self.center
|
||||||
|
center.y = centerY
|
||||||
|
self.center = center
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// size
|
||||||
|
public var size : CGSize {
|
||||||
|
|
||||||
|
get {
|
||||||
|
return self.frame.size
|
||||||
|
}
|
||||||
|
set (size) {
|
||||||
|
var newSize = self.frame.size
|
||||||
|
newSize = CGSize(width: size.width, height: size.height)
|
||||||
|
self.frame.size = newSize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// origin
|
||||||
|
public var origin : CGPoint {
|
||||||
|
|
||||||
|
get {
|
||||||
|
return self.frame.origin
|
||||||
|
}
|
||||||
|
set (origin) {
|
||||||
|
var newOrigin = self.frame.origin
|
||||||
|
newOrigin = CGPoint(x: origin.x, y: origin.y)
|
||||||
|
self.frame.origin = newOrigin
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// borderWidth
|
||||||
|
public var borderWidth: CGFloat {
|
||||||
|
|
||||||
|
get {
|
||||||
|
return self.layer.borderWidth
|
||||||
|
}
|
||||||
|
set (borderWidth){
|
||||||
|
self.layer.borderWidth = borderWidth
|
||||||
|
|
||||||
|
guard self.layer.masksToBounds else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.layer.masksToBounds = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@@ -16,6 +16,7 @@ class AuthFillDataVC: BaseViewController, HiddenNavigationBarProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func loadSubViews() {
|
private func loadSubViews() {
|
||||||
|
randomNick()
|
||||||
view.addSubview(backImgView)
|
view.addSubview(backImgView)
|
||||||
view.addSubview(backBtn)
|
view.addSubview(backBtn)
|
||||||
view.addSubview(titleLb)
|
view.addSubview(titleLb)
|
||||||
@@ -144,6 +145,16 @@ class AuthFillDataVC: BaseViewController, HiddenNavigationBarProtocol {
|
|||||||
return button
|
return button
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
fileprivate func randomNick() {
|
||||||
|
RequestGet(path: "random/nick/get", parma: [:]) { text in
|
||||||
|
if let text = text as? String {
|
||||||
|
self.nickTextFiled.text = text
|
||||||
|
}
|
||||||
|
} fail: { code, msg in
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@objc func femaleBtnAction() {
|
@objc func femaleBtnAction() {
|
||||||
self.femaleBtn.isSelected = true
|
self.femaleBtn.isSelected = true
|
||||||
self.maleBtn.isSelected = false
|
self.maleBtn.isSelected = false
|
||||||
@@ -157,14 +168,36 @@ class AuthFillDataVC: BaseViewController, HiddenNavigationBarProtocol {
|
|||||||
|
|
||||||
|
|
||||||
@objc func backBtnAction() {
|
@objc func backBtnAction() {
|
||||||
self.navigationController?.popViewController(animated: true)
|
self.dismiss(animated: true, completion: nil)
|
||||||
|
AuthViewModel.authVM.logout()
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func nickTextFiledDidChange(_ textField: UITextField) {
|
@objc func nickTextFiledDidChange(_ textField: UITextField) {
|
||||||
|
if let text = textField.text {
|
||||||
|
if text.count > 15 {
|
||||||
|
textField.text = text.substring(start: 0, 15)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@objc func confirmBtnAction() {
|
@objc func confirmBtnAction() {
|
||||||
|
if maleBtn.isSelected == true || femaleBtn.isSelected == true {
|
||||||
|
if let nick = nickTextFiled.text, nick.count > 0 {
|
||||||
|
let gender = self.maleBtn.isSelected ? "1" : "2"
|
||||||
|
let params:[String: Any] = ["avatar":"https://image.ymlive.fun/default_avatar.png", "nick": nick, "gender":gender, "uid": AuthManager.userUid, "ticket":AuthManager.ticket]
|
||||||
|
RequestPost(path: "user/v2/update", parma: params) { data in
|
||||||
|
HUDTool.show(with: "更新成功")
|
||||||
|
self.dismiss(animated: true, completion: nil)
|
||||||
|
} fail: { code, message in
|
||||||
|
HUDTool.show(with: message)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
HUDTool.show(with: "请输入昵称")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
HUDTool.show(with: "请选择性别")
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -281,7 +281,7 @@ class AuthLaunchVC: BaseViewController, HiddenNavigationBarProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@objc func userProtocolBtnAction() {
|
@objc func userProtocolBtnAction() {
|
||||||
let web = WebViewController(url: "yinmeng/\(H5Utils.privacy.rawValue)")
|
let web = WebViewController(url: "yinmeng/\(H5Utils.user.rawValue)")
|
||||||
self.navigationController?.pushViewController(web, animated: true)
|
self.navigationController?.pushViewController(web, animated: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -22,6 +22,7 @@ class AuthManager: NSObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class LoginTokenConfig: NSObject {
|
class LoginTokenConfig: NSObject {
|
||||||
public static let config = LoginTokenConfig.init()
|
public static let config = LoginTokenConfig.init()
|
||||||
var tokenInfo: UserTokenObject?
|
var tokenInfo: UserTokenObject?
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
import RxSwift
|
import RxSwift
|
||||||
|
import NIMSDK
|
||||||
class AuthViewModel: NSObject {
|
class AuthViewModel: NSObject {
|
||||||
static let authVM = AuthViewModel.init()
|
static let authVM = AuthViewModel.init()
|
||||||
let data = PublishSubject<Bool>()
|
let data = PublishSubject<Bool>()
|
||||||
@@ -22,6 +23,24 @@ class AuthViewModel: NSObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func logout() {
|
||||||
|
if NIMSDK.shared().loginManager.isLogined() {
|
||||||
|
NIMSDK.shared().loginManager.logout()
|
||||||
|
}
|
||||||
|
let token = LoginTokenConfig.config.getAccountInfo()?.access_token
|
||||||
|
LoginTokenConfig.config.removeTicketFromLoaction()
|
||||||
|
LoginTokenConfig.config.removeTicketFromLoaction()
|
||||||
|
if let token = token {
|
||||||
|
let params = ["auaccess_token": token]
|
||||||
|
RequestPost(path: "acc/logout", parma: params) { data in
|
||||||
|
print("你好")
|
||||||
|
} fail: { code, msg in
|
||||||
|
print("de")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.loginSuccess.onNext(false)
|
||||||
|
}
|
||||||
|
|
||||||
///获取验证码
|
///获取验证码
|
||||||
func getSmsCode(phone:String, type:Int) {
|
func getSmsCode(phone:String, type:Int) {
|
||||||
if let phoneDes = phone.encrypt() {
|
if let phoneDes = phone.encrypt() {
|
||||||
@@ -106,14 +125,11 @@ class AuthViewModel: NSObject {
|
|||||||
if let dic = data as? [String: Any], let tickets = dic["tickets"] as? [[String: Any]], let ticket1 = tickets[safe: 0], let ticket = ticket1["ticket"] as? String{
|
if let dic = data as? [String: Any], let tickets = dic["tickets"] as? [[String: Any]], let ticket1 = tickets[safe: 0], let ticket = ticket1["ticket"] as? String{
|
||||||
LoginTokenConfig.config.saveTicketToLoaction(ticket: ticket)
|
LoginTokenConfig.config.saveTicketToLoaction(ticket: ticket)
|
||||||
self.loginSuccess.onNext(true)
|
self.loginSuccess.onNext(true)
|
||||||
self.loginSuccess.onCompleted()
|
|
||||||
} else {
|
} else {
|
||||||
self.loginSuccess.onNext(false)
|
self.loginSuccess.onNext(false)
|
||||||
self.loginSuccess.onCompleted()
|
|
||||||
}
|
}
|
||||||
} fail: { code, message in
|
} fail: { code, message in
|
||||||
self.loginSuccess.onNext(false)
|
self.loginSuccess.onNext(false)
|
||||||
self.loginSuccess.onCompleted()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -6,13 +6,136 @@
|
|||||||
// 回话列表
|
// 回话列表
|
||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
|
import NIMSDK
|
||||||
class ChatListVC: BaseViewController {
|
class ChatListVC: BaseViewController {
|
||||||
|
|
||||||
|
var list:NSMutableArray?
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
NIMSDK.shared().loginManager.remove(self)
|
||||||
|
NIMSDK.shared().conversationManager.remove(self)
|
||||||
|
}
|
||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
|
NIMSDK.shared().conversationManager.add(self)
|
||||||
// Do any additional setup after loading the view.
|
NIMSDK.shared().loginManager.add(self)
|
||||||
|
getList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private lazy var tableView: UITableView = {
|
||||||
|
let tableView = UITableView(frame: .zero, style: .plain)
|
||||||
|
tableView.delegate = self
|
||||||
|
tableView.dataSource = self
|
||||||
|
tableView.tableFooterView = UIView()
|
||||||
|
tableView.separatorStyle = .none
|
||||||
|
tableView.backgroundColor = .clear
|
||||||
|
if #available(iOS 11.0, *) {
|
||||||
|
tableView.contentInsetAdjustmentBehavior = .never
|
||||||
|
}
|
||||||
|
tableView.register(cellType: ChatListCell.self)
|
||||||
|
return tableView
|
||||||
|
}()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ChatListVC: UITableViewDelegate, UITableViewDataSource {
|
||||||
|
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||||
|
let cell = tableView.dequeueReusableCell(for: indexPath, cellType: ChatListCell.self)
|
||||||
|
return cell
|
||||||
|
}
|
||||||
|
|
||||||
|
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||||
|
return list?.count ?? 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
|
||||||
|
return 64
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ChatListVC: NIMConversationManagerDelegate, NIMLoginManagerDelegate {
|
||||||
|
func onLogin(_ step: NIMLoginStep) {
|
||||||
|
if (step == .syncOK) {
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func didLoadAllRecentSessionCompletion() {
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
|
||||||
|
func didAdd(_ recentSession: NIMRecentSession, totalUnreadCount: Int) {
|
||||||
|
var isInList = false
|
||||||
|
for index in 0..<(list?.count ?? 0) {
|
||||||
|
let recent = list?[index] as? NIMRecentSession
|
||||||
|
if recent?.session?.sessionId == recentSession.session?.sessionId{
|
||||||
|
isInList = true
|
||||||
|
list?.replaceObject(at: index, with: recentSession)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if isInList == false {
|
||||||
|
list?.add(recentSession)
|
||||||
|
}
|
||||||
|
mai_sortMessages()
|
||||||
|
updateItemBadge()
|
||||||
|
}
|
||||||
|
|
||||||
|
func didUpdate(_ recentSession: NIMRecentSession, totalUnreadCount: Int) {
|
||||||
|
var isInList = false
|
||||||
|
for index in 0..<(list?.count ?? 0) {
|
||||||
|
let session = list?[index] as? NIMRecentSession
|
||||||
|
if session?.session?.sessionId == recentSession.session?.sessionId{
|
||||||
|
isInList = true
|
||||||
|
list?.replaceObject(at: index, with: recentSession)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if isInList == false {
|
||||||
|
list?.add(recentSession)
|
||||||
|
}
|
||||||
|
mai_sortMessages()
|
||||||
|
updateItemBadge()
|
||||||
|
}
|
||||||
|
|
||||||
|
func didRemove(_ recentSession: NIMRecentSession, totalUnreadCount: Int) {
|
||||||
|
let arr = NSArray.init(object: recentSession.session as Any)
|
||||||
|
NIMSDK.shared().conversationManager.deleteRemoteSessions(arr as! [NIMSession], completion: nil)
|
||||||
|
tableView.reloadData()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ChatListVC {
|
||||||
|
|
||||||
|
fileprivate func getList() {
|
||||||
|
if let array = NIMSDK.shared().conversationManager.allRecentSessions() {
|
||||||
|
list = NSMutableArray.init(array: array)
|
||||||
|
mai_sortMessages()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate func mai_sortMessages() -> Void {
|
||||||
|
var arr = list?.sortedArray(options: NSSortOptions.stable, usingComparator: { obj1, obj2 in
|
||||||
|
let item1 = obj1 as? NIMRecentSession
|
||||||
|
let item2 = obj2 as? NIMRecentSession
|
||||||
|
let time1 = (item1?.lastMessage?.timestamp ?? 0) as Double
|
||||||
|
let time2 = (item2?.lastMessage?.timestamp ?? 0) as Double
|
||||||
|
if time1 < time2{
|
||||||
|
return .orderedDescending
|
||||||
|
}
|
||||||
|
return .orderedAscending
|
||||||
|
})
|
||||||
|
|
||||||
|
if let array = arr {
|
||||||
|
list = NSMutableArray(array: array)
|
||||||
|
}
|
||||||
|
tableView.reloadData()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private func updateItemBadge() {
|
||||||
|
let unreadCount = NIMSDK.shared().conversationManager.allUnreadCount()
|
||||||
|
self.tabBarItem.badgeValue = "\(unreadCount)"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,6 +9,13 @@ import UIKit
|
|||||||
import NIMSDK
|
import NIMSDK
|
||||||
class ChatVC: BaseViewController {
|
class ChatVC: BaseViewController {
|
||||||
|
|
||||||
|
// 键盘收起/弹出 滚动的时候收起输入栏
|
||||||
|
private var isBecome: Bool = false
|
||||||
|
/// 是否发送完成
|
||||||
|
private var isSended: Bool = true
|
||||||
|
/// 输入栏默认的高度
|
||||||
|
private let ToolBarLastH: CGFloat = 52
|
||||||
|
|
||||||
public init(session: NIMSession) {
|
public init(session: NIMSession) {
|
||||||
vm = ChatViewModel(session: session)
|
vm = ChatViewModel(session: session)
|
||||||
super.init(nibName: nil, bundle: nil)
|
super.init(nibName: nil, bundle: nil)
|
||||||
@@ -24,10 +31,17 @@ class ChatVC: BaseViewController {
|
|||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
|
view.backgroundColor = ThemeColor(hexStr: "#F6F6F6")
|
||||||
view.backgroundColor = .orange
|
let height = ScreenHeight - (ToolBarLastH + SafeAraeBottomHeight + NavHeight)
|
||||||
|
chatTableView.frame = CGRect(x: 0, y: 0, width: ScreenWidth, height: height)
|
||||||
|
view.addSubview(chatTableView)
|
||||||
|
view.addSubview(keyboardView)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///注册cell
|
||||||
|
private func registerChatCell() {
|
||||||
|
chatTableView.register(cellType: ChatTextCell.self)
|
||||||
|
}
|
||||||
|
|
||||||
private lazy var chatTableView: UITableView = {
|
private lazy var chatTableView: UITableView = {
|
||||||
let tableView = UITableView(frame: .zero, style: .plain)
|
let tableView = UITableView(frame: .zero, style: .plain)
|
||||||
@@ -42,20 +56,57 @@ class ChatVC: BaseViewController {
|
|||||||
return tableView
|
return tableView
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
private lazy var keyboardView: ChatKeyboardView = {
|
||||||
|
let toolBarY = ScreenHeight - NavHeight - ToolBarLastH - SafeAraeBottomHeight
|
||||||
|
let view = ChatKeyboardView(frame: CGRect(x: 0, y: toolBarY, width: ScreenWidth, height: ToolBarLastH))
|
||||||
|
view.delegate = self
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ChatVC: UITableViewDelegate, UITableViewDataSource {
|
// MARK: - ChatKeyboardViewDelegate
|
||||||
|
extension ChatVC: ChatKeyboardViewDelegate {
|
||||||
|
|
||||||
|
func keyboard(_ keyboard: ChatKeyboardView, DidFinish content: String) {
|
||||||
|
///发送消息
|
||||||
|
vm.sendTextMessage(text: content) { error in
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func keyboard(_ keyboard: ChatKeyboardView, DidBecome isBecome: Bool) {
|
||||||
|
self.isSended = true
|
||||||
|
self.isBecome = isBecome
|
||||||
|
}
|
||||||
|
|
||||||
|
func keyboard(_ keyboard: ChatKeyboardView, DidMoreMenu type: ChatMoreMenuType) {
|
||||||
|
|
||||||
|
//TODO: 点击更多
|
||||||
|
}
|
||||||
|
|
||||||
|
func keyboard(_ keyboard: ChatKeyboardView, DidObserver offsetY: CGFloat) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ChatVC: UITableViewDelegate, UITableViewDataSource, UIScrollViewDelegate {
|
||||||
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||||
return vm.messageObjects.count
|
return vm.messageObjects.count
|
||||||
}
|
}
|
||||||
|
|
||||||
public func tableView(_ tableView: UITableView,
|
public func tableView(_ tableView: UITableView,
|
||||||
cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||||
|
let model = vm.messageObjects[safe: indexPath.row]
|
||||||
|
if model?.type == .text {
|
||||||
|
let cell = tableView.dequeueReusableCell(for: indexPath, cellType: ChatTextCell.self)
|
||||||
|
cell.model = model
|
||||||
|
}
|
||||||
return UITableViewCell()
|
return UITableViewCell()
|
||||||
}
|
}
|
||||||
|
|
||||||
public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||||
|
tableView.deselectRow(at: indexPath, animated: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func tableView(_ tableView: UITableView,
|
public func tableView(_ tableView: UITableView,
|
||||||
@@ -63,4 +114,22 @@ extension ChatVC: UITableViewDelegate, UITableViewDataSource {
|
|||||||
let m = vm.messageObjects[safe:indexPath.row]
|
let m = vm.messageObjects[safe:indexPath.row]
|
||||||
return CGFloat(m?.height ?? 0)
|
return CGFloat(m?.height ?? 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
|
||||||
|
if isSended {
|
||||||
|
isSended = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||||
|
if isSended {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if chatTableView.y <= 0 && isBecome {
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
NotificationCenter.default.post(name: .kChatTextKeyboardNeedHide, object: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
153
yinmeng-ios/Modules/Chat/Keyboard/ChatGrowingTextView.swift
Normal file
153
yinmeng-ios/Modules/Chat/Keyboard/ChatGrowingTextView.swift
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
//
|
||||||
|
// ChatGrowingTextView.swift
|
||||||
|
// yinmeng-ios
|
||||||
|
//
|
||||||
|
// Created by MaiMang on 2024/2/29.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class ChatGrowingTextView: UITextView {
|
||||||
|
/// 行数部分间距调整
|
||||||
|
fileprivate let kEdgeInset: CGFloat = 12
|
||||||
|
/// 内容字体默认大小
|
||||||
|
fileprivate let kDefultSize: CGFloat = 15.0
|
||||||
|
|
||||||
|
// MARK: - var lazy
|
||||||
|
|
||||||
|
/// 默认3行的高度
|
||||||
|
fileprivate var maxTextViewHeight: CGFloat = 80
|
||||||
|
|
||||||
|
var placeholder: String? = "" {
|
||||||
|
didSet {
|
||||||
|
self.placeholderLabel.text = placeholder
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var placeholderColor: UIColor? = .black {
|
||||||
|
didSet {
|
||||||
|
self.placeholderLabel.textColor = placeholderColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var maxNumberOfLines: Int = 3 {
|
||||||
|
didSet {
|
||||||
|
let numberOfLines = CGFloat(maxNumberOfLines)
|
||||||
|
maxTextViewHeight = CGFloat(ceilf(Float(self.font!.lineHeight * numberOfLines + self.textContainerInset.top + self.textContainerInset.bottom))) - kEdgeInset
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// 输入框高度监听回调
|
||||||
|
var didTextChangedHeightClosure : ((CGFloat)->Void)?
|
||||||
|
|
||||||
|
/// 占位标签
|
||||||
|
fileprivate lazy var placeholderLabel: UILabel = {
|
||||||
|
let frame = CGRect(x: 5, y: 7, width: ScreenWidth - 10, height: 21)
|
||||||
|
let label = UILabel(frame: frame)
|
||||||
|
label.numberOfLines = 1
|
||||||
|
label.text = "请输入你要发送的消息"
|
||||||
|
label.textColor = ThemeColor(hexStr: "#F6F6F6")
|
||||||
|
label.font = UIFont.systemFont(ofSize: self.kDefultSize)
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
// MARK: - life cycle
|
||||||
|
|
||||||
|
override init(frame: CGRect, textContainer: NSTextContainer?) {
|
||||||
|
super.init(frame: frame, textContainer: textContainer)
|
||||||
|
|
||||||
|
setup()
|
||||||
|
}
|
||||||
|
|
||||||
|
required public init?(coder aDecoder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate func setup() {
|
||||||
|
backgroundColor = .white
|
||||||
|
|
||||||
|
self.isScrollEnabled = false
|
||||||
|
self.scrollsToTop = false
|
||||||
|
//self.contentInset = UIEdgeInsets(top: 1, left: 0, bottom: 1, right: 0)
|
||||||
|
self.showsHorizontalScrollIndicator = false
|
||||||
|
self.enablesReturnKeyAutomatically = true
|
||||||
|
self.font = UIFont.systemFont(ofSize: kDefultSize)
|
||||||
|
self.returnKeyType = .send
|
||||||
|
|
||||||
|
self.layer.cornerRadius = 4
|
||||||
|
self.layer.borderWidth = 1
|
||||||
|
self.layer.borderColor = ThemeColor(hexStr: "#2C363E").cgColor
|
||||||
|
self.layer.masksToBounds = true
|
||||||
|
// 添加占位控件
|
||||||
|
addSubview(self.placeholderLabel)
|
||||||
|
|
||||||
|
// register
|
||||||
|
registerChangeNotification()
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate func registerChangeNotification() {
|
||||||
|
// 实时监听输入值的改变
|
||||||
|
NotificationCenter.default.addObserver(self,
|
||||||
|
selector: #selector(textDidChanged),
|
||||||
|
name: UITextView.textDidChangeNotification,
|
||||||
|
object: self)
|
||||||
|
|
||||||
|
self.addObserver(self, forKeyPath: "attributedText", options: .new, context: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - KVO监听
|
||||||
|
|
||||||
|
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
|
||||||
|
if keyPath == "attributedText" {
|
||||||
|
textDidChanged()
|
||||||
|
}else {
|
||||||
|
|
||||||
|
super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
NotificationCenter.default.removeObserver(self)
|
||||||
|
self.removeObserver(self, forKeyPath: "attributedText")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Action
|
||||||
|
|
||||||
|
extension ChatGrowingTextView {
|
||||||
|
|
||||||
|
@objc func textDidChanged() {
|
||||||
|
placeholderLabel.isHidden = self.hasText
|
||||||
|
|
||||||
|
// 计算高度
|
||||||
|
let constrainSize = CGSize(width: self.frame.size.width, height: CGFloat(MAXFLOAT))
|
||||||
|
var size = self.sizeThatFits(constrainSize)
|
||||||
|
|
||||||
|
if size.height >= maxTextViewHeight {
|
||||||
|
self.isScrollEnabled = true
|
||||||
|
size.height = maxTextViewHeight
|
||||||
|
}else {
|
||||||
|
self.isScrollEnabled = false
|
||||||
|
if (didTextChangedHeightClosure != nil && !self.isScrollEnabled) {
|
||||||
|
didTextChangedHeightClosure?(size.height)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let nowFrame = self.frame
|
||||||
|
frame.size.height = size.height
|
||||||
|
self.frame = nowFrame
|
||||||
|
|
||||||
|
self.layoutIfNeeded()
|
||||||
|
|
||||||
|
sendChangedNoti()
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendChangedNoti() {
|
||||||
|
|
||||||
|
NotificationCenter.default.post(name: .kChatTextKeyboardChanged, object: self.text, userInfo: nil)
|
||||||
|
}
|
||||||
|
}
|
29
yinmeng-ios/Modules/Chat/Keyboard/ChatKeyboard+.swift
Normal file
29
yinmeng-ios/Modules/Chat/Keyboard/ChatKeyboard+.swift
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
//
|
||||||
|
// ChatKeyboard+.swift
|
||||||
|
// yinmeng-ios
|
||||||
|
//
|
||||||
|
// Created by MaiMang on 2024/2/29.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
// MARK: - NSNotificationName
|
||||||
|
|
||||||
|
public extension NSNotification.Name {
|
||||||
|
/// 获取点击空白处回收键盘的处理通知
|
||||||
|
static let kChatTextKeyboardNeedHide = Notification.Name("kChatTextKeyboardNeedHide")
|
||||||
|
/// 获取文本输入框值变化
|
||||||
|
static let kChatTextKeyboardChanged = Notification.Name("kChatTextKeyboardChanged")
|
||||||
|
}
|
||||||
|
|
||||||
|
protocol OptionalType {
|
||||||
|
associatedtype Wrapped
|
||||||
|
|
||||||
|
var value: Wrapped? { get }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extension Optional: OptionalType {
|
||||||
|
var value: Wrapped? {
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
}
|
371
yinmeng-ios/Modules/Chat/Keyboard/ChatKeyboardView.swift
Normal file
371
yinmeng-ios/Modules/Chat/Keyboard/ChatKeyboardView.swift
Normal file
@@ -0,0 +1,371 @@
|
|||||||
|
//
|
||||||
|
// ChatKeyboardView.swift
|
||||||
|
// yinmeng-ios
|
||||||
|
//
|
||||||
|
// Created by MaiMang on 2024/2/29.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
protocol ChatKeyboardViewDelegate: NSObjectProtocol {
|
||||||
|
/// 输入完消息
|
||||||
|
func keyboard(_ keyboard: ChatKeyboardView, DidFinish content: String)
|
||||||
|
/// 键盘收起/弹出
|
||||||
|
func keyboard(_ keyboard: ChatKeyboardView, DidBecome isBecome: Bool)
|
||||||
|
/// 键盘的y值
|
||||||
|
func keyboard(_ keyboard: ChatKeyboardView, DidObserver offsetY: CGFloat)
|
||||||
|
/// 菜单栏点击
|
||||||
|
func keyboard(_ keyboard: ChatKeyboardView, DidMoreMenu type: ChatMoreMenuType)
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ChatKeyboardViewDelegate {
|
||||||
|
func keyboard(_ keyboard: ChatKeyboardView, DidFinish content: String) {}
|
||||||
|
func keyboard(_ keyboard: ChatKeyboardView, DidBecome isBecome: Bool) {}
|
||||||
|
func keyboard(_ keyboard: ChatKeyboardView, DidObserver offsetY: CGFloat) {}
|
||||||
|
func keyboard(_ keyboard: ChatKeyboardView, DidMoreMenu type: ChatMoreMenuType) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class ChatKeyboardView: UIView {
|
||||||
|
|
||||||
|
private let kSpace: CGFloat = 8.0
|
||||||
|
private let kViewWH: CGFloat = 36.0
|
||||||
|
private let kLineHeight: CGFloat = 0.75
|
||||||
|
|
||||||
|
// MARK: - var lazy
|
||||||
|
|
||||||
|
weak var delegate: ChatKeyboardViewDelegate?
|
||||||
|
|
||||||
|
fileprivate var toolBarHeight: CGFloat = 52.0
|
||||||
|
fileprivate var lastTextHeight: CGFloat = 34.0
|
||||||
|
fileprivate var keyboardHeight: CGFloat = 0.0
|
||||||
|
|
||||||
|
/// 底部菜单容器高度
|
||||||
|
fileprivate var contentHeight: CGFloat = 0.0
|
||||||
|
fileprivate var isShowMore = false
|
||||||
|
|
||||||
|
/// 是否弹出了系统键盘
|
||||||
|
fileprivate var isShowKeyboard = false
|
||||||
|
|
||||||
|
/// 更多按钮
|
||||||
|
fileprivate lazy var moreButton : UIButton = {
|
||||||
|
let button = UIButton(type: .custom)
|
||||||
|
let x: CGFloat = ScreenWidth - self.kViewWH - self.kSpace
|
||||||
|
button.frame = CGRect(x: x, y: self.kSpace, width: self.kViewWH, height: self.kViewWH)
|
||||||
|
button.setImage(UIImage(named: "chat_more"), for: .normal)
|
||||||
|
button.setImage(UIImage(named: "chat_more"), for: .highlighted)
|
||||||
|
button.addTarget(self, action: #selector(moreDidAction(_:)), for: .touchUpInside)
|
||||||
|
return button
|
||||||
|
}()
|
||||||
|
|
||||||
|
/// 文本输入框
|
||||||
|
fileprivate lazy var chatTextView: ChatGrowingTextView = {
|
||||||
|
let w: CGFloat = ScreenWidth - self.kViewWH * 2 - self.kSpace * 3 - self.kSpace
|
||||||
|
let textView = ChatGrowingTextView(frame: CGRect(x: self.kSpace, y: self.kSpace, width: w, height: self.kViewWH))
|
||||||
|
textView.placeholder = "请输入..."
|
||||||
|
textView.textColor = ThemeColor(hexStr: "#000000")
|
||||||
|
textView.maxNumberOfLines = 5
|
||||||
|
textView.delegate = self
|
||||||
|
textView.didTextChangedHeightClosure = { [weak self] height in
|
||||||
|
self?.changeKeyboardHeight(height: height)
|
||||||
|
}
|
||||||
|
return textView
|
||||||
|
}()
|
||||||
|
|
||||||
|
fileprivate lazy var topLineView: UIView = {
|
||||||
|
let lineView1 = UIView(frame: CGRect(x: 0, y: 0, width: ScreenWidth, height: kLineHeight))
|
||||||
|
lineView1.backgroundColor = ThemeColor(hexStr: "#E5E5E5")
|
||||||
|
return lineView1
|
||||||
|
}()
|
||||||
|
|
||||||
|
fileprivate lazy var bottomLineView: UIView = {
|
||||||
|
let lineView2 = UIView(frame: CGRect(x: 0, y: self.toolBarHeight - kLineHeight, width: ScreenWidth, height: kLineHeight))
|
||||||
|
lineView2.backgroundColor = ThemeColor(hexStr: "#E5E5E5")
|
||||||
|
return lineView2
|
||||||
|
}()
|
||||||
|
|
||||||
|
fileprivate lazy var toolBarView: UIView = {
|
||||||
|
let view = UIView(frame: CGRect(x: 0, y: 0, width: ScreenWidth, height: self.toolBarHeight))
|
||||||
|
view.backgroundColor = ThemeColor(hexStr: "#F7F7F7")
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
|
/// 底部背景容器
|
||||||
|
fileprivate lazy var contentView: UIView = {
|
||||||
|
let y = self.toolBarView.maxY
|
||||||
|
let view = UIView(frame: CGRect(x: 0, y: y, width: ScreenWidth, height: self.contentHeight))
|
||||||
|
view.backgroundColor = ThemeColor(hexStr: "#F8F8F8")
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
|
/// 更多菜单
|
||||||
|
fileprivate lazy var moreMenuView: ChatMoreMenuView = {
|
||||||
|
let view = ChatMoreMenuView(frame: self.contentView.bounds)
|
||||||
|
view.isHidden = true
|
||||||
|
view.delegate = self
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
|
// MARK: - life cycle
|
||||||
|
|
||||||
|
override init(frame: CGRect) {
|
||||||
|
super.init(frame: frame)
|
||||||
|
|
||||||
|
setupKeyboardView()
|
||||||
|
registerNotification()
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder aDecoder: NSCoder) {
|
||||||
|
super.init(coder: aDecoder)
|
||||||
|
|
||||||
|
setupKeyboardView()
|
||||||
|
registerNotification()
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupKeyboardView() {
|
||||||
|
self.backgroundColor = ThemeColor(hexStr: "#F7F7F7")
|
||||||
|
self.isUserInteractionEnabled = true
|
||||||
|
|
||||||
|
addSubview(toolBarView)
|
||||||
|
toolBarView.addSubview(moreButton)
|
||||||
|
toolBarView.addSubview(chatTextView)
|
||||||
|
toolBarView.addSubview(topLineView)
|
||||||
|
toolBarView.addSubview(bottomLineView)
|
||||||
|
|
||||||
|
addSubview(contentView)
|
||||||
|
contentView.addSubview(moreMenuView)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - 监听键盘通知
|
||||||
|
private func registerNotification() {
|
||||||
|
// 监听键盘弹出通知
|
||||||
|
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)),
|
||||||
|
name:UIResponder.keyboardWillShowNotification,object: nil)
|
||||||
|
// 监听键盘隐藏通知
|
||||||
|
NotificationCenter.default.addObserver(self,selector: #selector(keyboardWillHide(_:)),
|
||||||
|
name: UIResponder.keyboardWillHideNotification, object: nil)
|
||||||
|
|
||||||
|
// 主要是为了获取点击空白处回收键盘的处理
|
||||||
|
NotificationCenter.default.addObserver(self,selector: #selector(keyboardNeedHide),
|
||||||
|
name: .kChatTextKeyboardNeedHide, object: nil)
|
||||||
|
// 添加KVO监听输入键盘y值
|
||||||
|
addObserver(self, forKeyPath: "frame", options: [.new, .old], context: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - KVO监听
|
||||||
|
|
||||||
|
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
|
||||||
|
if keyPath == "frame" && ((object as? UIView) != nil) {
|
||||||
|
if let changeObject = change.value {
|
||||||
|
if let newFrame = changeObject[.newKey] as? CGRect {
|
||||||
|
delegate?.keyboard(self, DidObserver: newFrame.origin.y)
|
||||||
|
print("y值发生改变\(newFrame.origin.y)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
|
||||||
|
super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
|
||||||
|
self.removeObserver(self, forKeyPath: "frame")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - ChatMoreMenuViewDelegate
|
||||||
|
|
||||||
|
extension ChatKeyboardView: ChatMoreMenuViewDelegate {
|
||||||
|
|
||||||
|
func menu(_ view: ChatMoreMenuView, DidSelected type: ChatMoreMenuType) {
|
||||||
|
|
||||||
|
delegate?.keyboard(self, DidMoreMenu: type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - UITextViewDelegate
|
||||||
|
|
||||||
|
extension ChatKeyboardView: UITextViewDelegate {
|
||||||
|
|
||||||
|
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
|
||||||
|
// 发送键&回车键处理
|
||||||
|
if (text == "\n") {
|
||||||
|
if (isShowKeyboard) {
|
||||||
|
isShowKeyboard = true
|
||||||
|
}
|
||||||
|
|
||||||
|
sendChatMessage()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// 发送消息内容
|
||||||
|
private func sendChatMessage() {
|
||||||
|
delegate?.keyboard(self, DidFinish: self.chatTextView.text ?? "")
|
||||||
|
|
||||||
|
changeKeyboardHeight(height: lastTextHeight)
|
||||||
|
chatTextView.text = ""
|
||||||
|
chatTextView.attributedText = NSAttributedString(string: "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - KeyBoard Manager
|
||||||
|
|
||||||
|
extension ChatKeyboardView {
|
||||||
|
|
||||||
|
/// 键盘将要显示
|
||||||
|
@objc func keyboardWillShow(_ noti: NSNotification) {
|
||||||
|
guard let userInfo = noti.userInfo else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
contentHeight = 0
|
||||||
|
delegate?.keyboard(self, DidBecome: true)
|
||||||
|
|
||||||
|
let duration = userInfo["UIKeyboardAnimationDurationUserInfoKey"] as! Double
|
||||||
|
let endFrame = (userInfo["UIKeyboardFrameEndUserInfoKey"] as! NSValue).cgRectValue
|
||||||
|
let y = endFrame.origin.y
|
||||||
|
// 获取键盘的高度
|
||||||
|
keyboardHeight = endFrame.height
|
||||||
|
// 键盘弹出状态
|
||||||
|
isShowKeyboard = true
|
||||||
|
|
||||||
|
let option = userInfo["UIKeyboardAnimationCurveUserInfoKey"] as! Int
|
||||||
|
|
||||||
|
var changedY = y - self.toolBarHeight - NavHeight - contentHeight
|
||||||
|
if (isShowMore) { //显示系统键盘
|
||||||
|
isShowMore = false
|
||||||
|
self.moreMenuView.isHidden = true
|
||||||
|
self.moreMenuView.hidePageController = true
|
||||||
|
changedY = y - self.toolBarHeight - NavHeight
|
||||||
|
}
|
||||||
|
|
||||||
|
UIView.animate(withDuration: duration, delay: 0, options: UIView.AnimationOptions(rawValue: UIView.AnimationOptions.RawValue(option)), animations: {
|
||||||
|
self.frame = CGRect(x: 0, y: changedY, width: ScreenWidth, height: self.toolBarHeight + self.contentHeight)
|
||||||
|
}, completion: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 键盘将要消失
|
||||||
|
@objc func keyboardWillHide(_ noti: NSNotification) {
|
||||||
|
guard let userInfo = noti.userInfo else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
delegate?.keyboard(self, DidBecome: false)
|
||||||
|
|
||||||
|
let duration = userInfo["UIKeyboardAnimationDurationUserInfoKey"] as! Double
|
||||||
|
let endFrame = (userInfo["UIKeyboardFrameEndUserInfoKey"] as! NSValue).cgRectValue
|
||||||
|
//let y = endFrame.origin.y
|
||||||
|
// 获取键盘的高度
|
||||||
|
keyboardHeight = endFrame.height
|
||||||
|
// 键盘弹出状态
|
||||||
|
isShowKeyboard = false
|
||||||
|
|
||||||
|
let option = userInfo["UIKeyboardAnimationCurveUserInfoKey"] as! Int
|
||||||
|
let changedY = ScreenHeight - NavHeight - self.toolBarHeight - SafeAraeBottomHeight - self.contentHeight
|
||||||
|
UIView.animate(withDuration: duration, delay: 0, options: UIView.AnimationOptions(rawValue: UIView.AnimationOptions.RawValue(option)), animations: {
|
||||||
|
self.frame = CGRect(x: 0, y: changedY, width: ScreenWidth, height: self.toolBarHeight + self.contentHeight)
|
||||||
|
}, completion: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func keyboardNeedHide(_ noti: NSNotification) {
|
||||||
|
|
||||||
|
chatTextView.resignFirstResponder()
|
||||||
|
moreMenuView.hidePageController = true
|
||||||
|
|
||||||
|
contentHeight = 0.0
|
||||||
|
restToolbarContentHeight(true)
|
||||||
|
|
||||||
|
delegate?.keyboard(self, DidBecome: false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - Action
|
||||||
|
|
||||||
|
extension ChatKeyboardView {
|
||||||
|
/// 更多按钮点击处理
|
||||||
|
@objc func moreDidAction(_ button: UIButton) {
|
||||||
|
// 如有弹出菜单
|
||||||
|
if isShowMore {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
isShowMore = true
|
||||||
|
contentHeight = 250
|
||||||
|
contentView.isHidden = false
|
||||||
|
moreMenuView.isHidden = false
|
||||||
|
chatTextView.resignFirstResponder()
|
||||||
|
|
||||||
|
restToolbarContentHeight()
|
||||||
|
moreMenuView.reloadData()
|
||||||
|
|
||||||
|
delegate?.keyboard(self, DidBecome: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 更改容器高度
|
||||||
|
func restToolbarContentHeight(_ isRest: Bool = false) {
|
||||||
|
var changedY = ScreenHeight - self.toolBarHeight - NavHeight - contentHeight
|
||||||
|
if (isRest) {
|
||||||
|
if (isShowMore) {
|
||||||
|
isShowMore = false
|
||||||
|
}
|
||||||
|
|
||||||
|
changedY = ScreenHeight - self.toolBarHeight - NavHeight - contentHeight - SafeAraeBottomHeight
|
||||||
|
}
|
||||||
|
|
||||||
|
UIView.animate(withDuration: 0.25, delay: 0, options: .curveEaseOut, animations: {
|
||||||
|
self.contentView.frame = CGRect(x: 0, y: self.toolBarView.maxY, width: ScreenWidth, height: self.contentHeight)
|
||||||
|
self.moreMenuView.frame = self.contentView.bounds
|
||||||
|
self.frame = CGRect(x: 0, y: changedY, width: ScreenWidth, height: self.toolBarHeight + self.contentHeight)
|
||||||
|
}, completion: nil)
|
||||||
|
|
||||||
|
self.layoutIfNeeded()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - 改变输入框高度位置
|
||||||
|
|
||||||
|
extension ChatKeyboardView {
|
||||||
|
|
||||||
|
func changeKeyboardHeight(_ isClear: Bool = false, height: CGFloat) {
|
||||||
|
let textHeight = height
|
||||||
|
|
||||||
|
toolBarHeight = textHeight + kSpace * 2
|
||||||
|
toolBarView.frame = CGRect(x: toolBarView.x, y: 0, width: toolBarView.width, height: toolBarHeight)
|
||||||
|
|
||||||
|
let spaceY = toolBarView.height - kSpace - kViewWH
|
||||||
|
chatTextView.frame = CGRect(x: chatTextView.x, y: chatTextView.x, width: chatTextView.width, height: textHeight)
|
||||||
|
moreButton.frame = CGRect(x: moreButton.x, y: spaceY, width: moreButton.width, height: moreButton.height)
|
||||||
|
contentView.frame = CGRect(x: contentView.x, y: toolBarView.maxY, width: contentView.width, height: contentHeight)
|
||||||
|
|
||||||
|
topLineView.frame = CGRect(x: 0, y: 0, width: ScreenWidth, height: kLineHeight)
|
||||||
|
bottomLineView.frame = CGRect(x: 0, y: toolBarView.height - kLineHeight, width: ScreenWidth, height: kLineHeight)
|
||||||
|
|
||||||
|
|
||||||
|
if (isShowKeyboard) {
|
||||||
|
if (isShowMore) {
|
||||||
|
isShowMore = false
|
||||||
|
}
|
||||||
|
|
||||||
|
let changedY = ScreenHeight - keyboardHeight - toolBarHeight - NavHeight
|
||||||
|
self.frame = CGRect(x: 0, y: changedY, width: ScreenWidth, height: toolBarView.height + contentView.height)
|
||||||
|
}else {
|
||||||
|
let changedY = ScreenHeight - NavHeight - (toolBarView.height + contentView.height)
|
||||||
|
self.frame = CGRect(x: 0, y: changedY, width: ScreenWidth, height: toolBarView.height + contentView.height)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.setNeedsLayout()
|
||||||
|
print("self y === \(self.frame.origin.y)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
67
yinmeng-ios/Modules/Chat/Keyboard/ChatMoreMenuCell.swift
Normal file
67
yinmeng-ios/Modules/Chat/Keyboard/ChatMoreMenuCell.swift
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
//
|
||||||
|
// ChatMoreMenuCell.swift
|
||||||
|
// yinmeng-ios
|
||||||
|
//
|
||||||
|
// Created by MaiMang on 2024/2/29.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import Reusable
|
||||||
|
class ChatMoreMenuCell: UICollectionViewCell, Reusable {
|
||||||
|
|
||||||
|
// MARK: - lazy var
|
||||||
|
|
||||||
|
var model: ChatMoreMnueConfig? {
|
||||||
|
didSet {
|
||||||
|
guard model != nil else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
self.imageView.image = UIImage(named: model!.image!)
|
||||||
|
self.titleLabel.text = model?.title ?? ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private lazy var titleLabel: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.textAlignment = .center
|
||||||
|
label.textColor = .white
|
||||||
|
label.font = UIFont.systemFont(ofSize: 14)
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var imageView: UIImageView = {
|
||||||
|
let imageView = UIImageView()
|
||||||
|
return imageView
|
||||||
|
}()
|
||||||
|
|
||||||
|
// MARK: - life cycle
|
||||||
|
|
||||||
|
override init(frame: CGRect) {
|
||||||
|
super.init(frame: frame)
|
||||||
|
|
||||||
|
contentView.addSubview(imageView)
|
||||||
|
contentView.addSubview(titleLabel)
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override func layoutSubviews() {
|
||||||
|
super.layoutSubviews()
|
||||||
|
|
||||||
|
imageView.snp.makeConstraints { (make) in
|
||||||
|
make.centerX.equalToSuperview()
|
||||||
|
make.centerY.equalToSuperview().offset(-10)
|
||||||
|
make.width.height.equalTo(36)
|
||||||
|
}
|
||||||
|
|
||||||
|
titleLabel.snp.makeConstraints { (make) in
|
||||||
|
make.left.right.equalToSuperview()
|
||||||
|
make.top.equalTo(imageView.snp.bottom)
|
||||||
|
make.height.equalTo(21)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
262
yinmeng-ios/Modules/Chat/Keyboard/ChatMoreMenuView.swift
Normal file
262
yinmeng-ios/Modules/Chat/Keyboard/ChatMoreMenuView.swift
Normal file
@@ -0,0 +1,262 @@
|
|||||||
|
//
|
||||||
|
// ChatMoreMenuView.swift
|
||||||
|
// yinmeng-ios
|
||||||
|
//
|
||||||
|
// Created by MaiMang on 2024/2/29.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
enum ChatMoreMenuType: Int {
|
||||||
|
case album = 1001
|
||||||
|
case camera = 1002
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 行数
|
||||||
|
fileprivate let kRowNumber = 2
|
||||||
|
/// 列数
|
||||||
|
fileprivate let kColumnNumber = 4
|
||||||
|
|
||||||
|
fileprivate let kMoreMenuCellNumberOfOnePage = kRowNumber * kColumnNumber
|
||||||
|
|
||||||
|
protocol ChatMoreMenuViewDelegate {
|
||||||
|
/// 获取选择的菜单
|
||||||
|
func menu(_ view: ChatMoreMenuView, DidSelected type: ChatMoreMenuType)
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ChatMoreMenuViewDelegate {
|
||||||
|
|
||||||
|
func menu(_ view: ChatMoreMenuView, DidSelected type: ChatMoreMenuType) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChatMoreMenuView: UIView {
|
||||||
|
|
||||||
|
// MARK: - lazy var
|
||||||
|
|
||||||
|
var delegate: ChatMoreMenuViewDelegate?
|
||||||
|
|
||||||
|
/// 隐藏分页指示器
|
||||||
|
var hidePageController: Bool = false {
|
||||||
|
didSet {
|
||||||
|
self.pageControl.alpha = self.hidePageController ? 0.0 : 1.0
|
||||||
|
UIView.animate(withDuration: 0.15, delay: 0, options: .curveEaseOut, animations: {
|
||||||
|
self.pageControl.isHidden = self.hidePageController
|
||||||
|
}, completion: nil)
|
||||||
|
|
||||||
|
self.collectionView.scrollToItem(at: IndexPath(row: 0, section: 0), at: .centeredHorizontally, animated: false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var pageIndicatorTintColor: UIColor? {
|
||||||
|
didSet {
|
||||||
|
guard pageIndicatorTintColor != nil else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
pageControl.pageIndicatorTintColor = pageIndicatorTintColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentPageIndicatorTintColor: UIColor? {
|
||||||
|
didSet {
|
||||||
|
guard currentPageIndicatorTintColor != nil else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
pageControl.currentPageIndicatorTintColor = currentPageIndicatorTintColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy var dataSource: [ChatMoreMnueConfig] = {
|
||||||
|
let configs = [
|
||||||
|
ChatMoreMnueConfig(title: "图片", image: "ic_more_album", type: .album),
|
||||||
|
ChatMoreMnueConfig(title: "拍照", image: "ic_more_camera", type: .camera)
|
||||||
|
]
|
||||||
|
return configs
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var collectionView: UICollectionView = {
|
||||||
|
let layout = ChatKeyboardFlowLayout(column: kColumnNumber, row: kRowNumber)
|
||||||
|
// collectionView
|
||||||
|
let collection = UICollectionView(frame: self.bounds, collectionViewLayout: layout)
|
||||||
|
collection.backgroundColor = ThemeColor(hexStr: "#F8F8F8")
|
||||||
|
collection.register(cellType: ChatMoreMenuCell.self)
|
||||||
|
collection.showsHorizontalScrollIndicator = true
|
||||||
|
collection.showsVerticalScrollIndicator = true
|
||||||
|
collection.dataSource = self
|
||||||
|
collection.delegate = self
|
||||||
|
collection.isPagingEnabled = true
|
||||||
|
return collection
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var pageControl: UIPageControl = {
|
||||||
|
let pager = UIPageControl()
|
||||||
|
pager.backgroundColor = .clear
|
||||||
|
pager.pageIndicatorTintColor = .white
|
||||||
|
pager.currentPageIndicatorTintColor = ThemeColor(hexStr: "#000000")
|
||||||
|
pager.currentPage = 0
|
||||||
|
pager.isHidden = true
|
||||||
|
pager.numberOfPages = self.dataSource.count / kMoreMenuCellNumberOfOnePage + (self.dataSource.count % kMoreMenuCellNumberOfOnePage == 0 ? 0 : 1)
|
||||||
|
return pager
|
||||||
|
}()
|
||||||
|
|
||||||
|
// MARK: - life cycle
|
||||||
|
|
||||||
|
override init(frame: CGRect) {
|
||||||
|
super.init(frame: frame)
|
||||||
|
|
||||||
|
makeUI()
|
||||||
|
reloadData()
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder aDecoder: NSCoder) {
|
||||||
|
super.init(coder: aDecoder)
|
||||||
|
|
||||||
|
makeUI()
|
||||||
|
reloadData()
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeUI() {
|
||||||
|
self.backgroundColor = ThemeColor(hexStr: "#F8F8F8")
|
||||||
|
|
||||||
|
addSubview(pageControl)
|
||||||
|
addSubview(collectionView)
|
||||||
|
|
||||||
|
pageControl.snp.makeConstraints { make in
|
||||||
|
make.bottom.equalToSuperview().offset(-SafeAraeBottomHeight)
|
||||||
|
make.centerX.equalToSuperview()
|
||||||
|
make.height.equalTo(30)
|
||||||
|
}
|
||||||
|
|
||||||
|
collectionView.snp.makeConstraints { make in
|
||||||
|
make.top.left.right.equalToSuperview()
|
||||||
|
make.bottom.equalTo(pageControl.snp.top)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open func reloadData() {
|
||||||
|
self.needsUpdateConstraints()
|
||||||
|
self.layoutIfNeeded()
|
||||||
|
|
||||||
|
UIView.animate(withDuration: 0.15, delay: 0, options: .curveEaseOut, animations: {
|
||||||
|
self.pageControl.alpha = 1.0
|
||||||
|
self.pageControl.isHidden = false
|
||||||
|
}, completion: nil)
|
||||||
|
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self.collectionView.reloadData()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - UICollectionViewDataSource
|
||||||
|
|
||||||
|
extension ChatMoreMenuView: UICollectionViewDataSource {
|
||||||
|
|
||||||
|
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||||
|
return dataSource.count
|
||||||
|
}
|
||||||
|
|
||||||
|
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
||||||
|
let cell = collectionView.dequeueReusableCell(for: indexPath, cellType: ChatMoreMenuCell.self)
|
||||||
|
if let model = dataSource[safe: indexPath.row] {
|
||||||
|
cell.model = model
|
||||||
|
}
|
||||||
|
return cell
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - UICollectionViewDelegate
|
||||||
|
|
||||||
|
extension ChatMoreMenuView: UICollectionViewDelegate {
|
||||||
|
|
||||||
|
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||||
|
if let model = dataSource[safe: indexPath.row] {
|
||||||
|
delegate?.menu(self, DidSelected: model.type!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ChatMoreMenuView {
|
||||||
|
|
||||||
|
func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||||
|
if scrollView == collectionView {
|
||||||
|
let offsetX = scrollView.contentOffset.x
|
||||||
|
let index = offsetX / ScreenWidth
|
||||||
|
pageControl.currentPage = Int(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChatKeyboardFlowLayout: UICollectionViewFlowLayout {
|
||||||
|
// 保存所有item
|
||||||
|
fileprivate var attributesArr: [UICollectionViewLayoutAttributes] = []
|
||||||
|
fileprivate var col: Int = 0
|
||||||
|
fileprivate var row: Int = 0
|
||||||
|
|
||||||
|
init(column: Int, row: Int) {
|
||||||
|
super.init()
|
||||||
|
self.col = column
|
||||||
|
self.row = row
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder aDecoder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - 重新布局
|
||||||
|
override func prepare() {
|
||||||
|
super.prepare()
|
||||||
|
|
||||||
|
let itemWH: CGFloat = ScreenWidth / CGFloat(col)
|
||||||
|
|
||||||
|
// 设置itemSize
|
||||||
|
itemSize = CGSize(width: itemWH, height: itemWH)
|
||||||
|
minimumLineSpacing = 0
|
||||||
|
minimumInteritemSpacing = 0
|
||||||
|
scrollDirection = .horizontal
|
||||||
|
|
||||||
|
// 设置collectionView属性
|
||||||
|
collectionView?.isPagingEnabled = true
|
||||||
|
collectionView?.showsHorizontalScrollIndicator = false
|
||||||
|
collectionView?.showsVerticalScrollIndicator = true
|
||||||
|
let insertMargin = (collectionView!.bounds.height - CGFloat(row) * itemWH) * 0.5
|
||||||
|
collectionView?.contentInset = UIEdgeInsets(top: insertMargin, left: 0, bottom: insertMargin, right: 0)
|
||||||
|
|
||||||
|
var page = 0
|
||||||
|
let itemsCount = collectionView?.numberOfItems(inSection: 0) ?? 0
|
||||||
|
for itemIndex in 0..<itemsCount {
|
||||||
|
let indexPath = IndexPath(item: itemIndex, section: 0)
|
||||||
|
let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
|
||||||
|
|
||||||
|
page = itemIndex / (col * row)
|
||||||
|
// 通过一系列计算, 得到x, y值
|
||||||
|
let x = itemSize.width * CGFloat(itemIndex % Int(col)) + (CGFloat(page) * ScreenWidth)
|
||||||
|
let y = itemSize.height * CGFloat((itemIndex - page * row * col) / col)
|
||||||
|
|
||||||
|
attributes.frame = CGRect(x: x, y: y, width: itemSize.width, height: itemSize.height)
|
||||||
|
// 把每一个新的属性保存起来
|
||||||
|
attributesArr.append(attributes)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
|
||||||
|
var rectAttributes: [UICollectionViewLayoutAttributes] = []
|
||||||
|
_ = attributesArr.map({
|
||||||
|
if rect.contains($0.frame) {
|
||||||
|
rectAttributes.append($0)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return rectAttributes
|
||||||
|
}
|
||||||
|
|
||||||
|
override var collectionViewContentSize: CGSize {
|
||||||
|
let size: CGSize = super.collectionViewContentSize
|
||||||
|
let collectionViewWidth: CGFloat = self.collectionView!.frame.size.width
|
||||||
|
let nbOfScreen: Int = Int(ceil(size.width / collectionViewWidth))
|
||||||
|
let newSize: CGSize = CGSize(width: collectionViewWidth * CGFloat(nbOfScreen), height: size.height)
|
||||||
|
return newSize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
25
yinmeng-ios/Modules/Chat/Keyboard/ChatMoreMnueConfig.swift
Normal file
25
yinmeng-ios/Modules/Chat/Keyboard/ChatMoreMnueConfig.swift
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
//
|
||||||
|
// ChatMoreMnueConfig.swift
|
||||||
|
// yinmeng-ios
|
||||||
|
//
|
||||||
|
// Created by MaiMang on 2024/2/29.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class ChatMoreMnueConfig: NSObject {
|
||||||
|
var title: String?
|
||||||
|
var image: String?
|
||||||
|
|
||||||
|
var type: ChatMoreMenuType?
|
||||||
|
|
||||||
|
init(title: String, image: String, type: ChatMoreMenuType) {
|
||||||
|
super.init()
|
||||||
|
|
||||||
|
self.title = title
|
||||||
|
self.image = image
|
||||||
|
self.type = type
|
||||||
|
}
|
||||||
|
|
||||||
|
required override init() { }
|
||||||
|
}
|
@@ -13,7 +13,7 @@ protocol ChatBaseCellProtocol: NSObjectProtocol {
|
|||||||
|
|
||||||
class ChatBaseCell: UITableViewCell, Reusable{
|
class ChatBaseCell: UITableViewCell, Reusable{
|
||||||
weak var delegate: ChatBaseCellProtocol?
|
weak var delegate: ChatBaseCellProtocol?
|
||||||
var model:ChatBaseObject? {
|
var model:ChatSessionProtocol? {
|
||||||
didSet {
|
didSet {
|
||||||
guard let _ = model else {return}
|
guard let _ = model else {return}
|
||||||
layoutMessageCell()
|
layoutMessageCell()
|
||||||
|
71
yinmeng-ios/Modules/Chat/View/ChatList/ChatListCell.swift
Normal file
71
yinmeng-ios/Modules/Chat/View/ChatList/ChatListCell.swift
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
//
|
||||||
|
// ChatListCell.swift
|
||||||
|
// yinmeng-ios
|
||||||
|
//
|
||||||
|
// Created by MaiMang on 2024/2/29.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import Reusable
|
||||||
|
class ChatListCell: UITableViewCell, Reusable {
|
||||||
|
|
||||||
|
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||||
|
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||||
|
contentView.addSubview(backView)
|
||||||
|
backView.addSubview(avatarImgView)
|
||||||
|
backView.addSubview(textLb)
|
||||||
|
backView.addSubview(nameLb)
|
||||||
|
backView.addSubview(dateLb)
|
||||||
|
}
|
||||||
|
|
||||||
|
private lazy var backView: UIView = {
|
||||||
|
let view = UIView()
|
||||||
|
view.backgroundColor = ThemeColor(hexStr: "#525566")
|
||||||
|
view.layer.masksToBounds = true
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var avatarImgView: UIImageView = {
|
||||||
|
let imageView = UIImageView()
|
||||||
|
imageView.isUserInteractionEnabled = true
|
||||||
|
imageView.layer.masksToBounds = true
|
||||||
|
imageView.contentMode = .scaleAspectFill
|
||||||
|
imageView.layer.cornerRadius = 30
|
||||||
|
return imageView
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var textLb: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.textColor = UIColor(white: 1, alpha: 0.8)
|
||||||
|
label.font = UIFont.systemFont(ofSize: 14)
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var nameLb: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.textColor = .white
|
||||||
|
label.font = UIFont.systemFont(ofSize: 15, weight: .medium)
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var dateLb: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.textColor = .red
|
||||||
|
label.font = UIFont.systemFont(ofSize: 12, weight: .light)
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var badgeLb: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.textColor = .white
|
||||||
|
label.backgroundColor = .red
|
||||||
|
label.textAlignment = .center
|
||||||
|
label.font = UIFont.systemFont(ofSize: 11)
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -85,8 +85,6 @@ class PlanetStarVC: BaseViewController,HiddenNavigationBarProtocol {
|
|||||||
self?.navigationController?.pushViewController(chatVC, animated: true)
|
self?.navigationController?.pushViewController(chatVC, animated: true)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var giftModel:PlanetStarModel?
|
var giftModel:PlanetStarModel?
|
||||||
|
@@ -62,7 +62,6 @@ make.size.equalTo(CGSize(width: 14, height: 14))
|
|||||||
}
|
}
|
||||||
|
|
||||||
@objc func privacyRecognizer() {
|
@objc func privacyRecognizer() {
|
||||||
//TODO: 跳转隐私政策的
|
|
||||||
let web = WebViewController(url: "yinmeng/\(H5Utils.privacy.rawValue)")
|
let web = WebViewController(url: "yinmeng/\(H5Utils.privacy.rawValue)")
|
||||||
self.navigationController?.pushViewController(web, animated: true)
|
self.navigationController?.pushViewController(web, animated: true)
|
||||||
}
|
}
|
||||||
|
@@ -71,7 +71,7 @@ class UserInfoVC: BaseViewController, HiddenNavigationBarProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@objc func logoutBtnAction() {
|
@objc func logoutBtnAction() {
|
||||||
//TODO: 退出登录
|
AuthViewModel.authVM.logout()
|
||||||
}
|
}
|
||||||
|
|
||||||
private lazy var backImgView: UIImageView = {
|
private lazy var backImgView: UIImageView = {
|
||||||
@@ -135,7 +135,7 @@ class UserInfoVC: BaseViewController, HiddenNavigationBarProtocol {
|
|||||||
|
|
||||||
private lazy var logoutBtn: UIButton = {
|
private lazy var logoutBtn: UIButton = {
|
||||||
let button = UIButton(type: .custom)
|
let button = UIButton(type: .custom)
|
||||||
button.setBackgroundImage(UIImage.gradient([ThemeColor(hexStr: "#FFC926"), ThemeColor(hexStr: "#FFE784")], radius: 0), for: .normal)
|
button.setBackgroundImage(UIImage.gradient([ThemeColor(hexStr: "#FF60FD"), ThemeColor(hexStr: "#8974FF"), ThemeColor(hexStr: "#69EBFF")], radius: 0), for: .normal)
|
||||||
button.setTitle("退出登录", for: .normal)
|
button.setTitle("退出登录", for: .normal)
|
||||||
button.setTitleColor(UIColor.white, for: .normal)
|
button.setTitleColor(UIColor.white, for: .normal)
|
||||||
button.titleLabel?.font = UIFont.systemFont(ofSize: 16, weight: .medium)
|
button.titleLabel?.font = UIFont.systemFont(ofSize: 16, weight: .medium)
|
||||||
|
@@ -6,15 +6,16 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import RxSwift
|
||||||
class UserViewModel: NSObject {
|
class UserViewModel: NSObject {
|
||||||
static let userVM = UserViewModel.init()
|
static let userVM = UserViewModel.init()
|
||||||
|
|
||||||
|
let userInfo = PublishSubject<UserObject>()
|
||||||
func getUserInfo(uid:Int) {
|
func getUserInfo(uid:Int) {
|
||||||
let params = ["uid":uid]
|
let params = ["uid":uid]
|
||||||
RequestGet(path: "user/get", parma: params) { data in
|
RequestGet(path: "user/get", parma: params) { data in
|
||||||
if let info = Deserialized<UserObject>.toModel(with: data) {
|
if var info = Deserialized<UserObject>.toModel(with: data) {
|
||||||
print("用户信息是")
|
self.userInfo.onNext(info)
|
||||||
}
|
}
|
||||||
} fail: { code, message in
|
} fail: { code, message in
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user