From bc085ab4d509d4b3b8c3b7834a739147e96b8543 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E5=96=84=E6=A0=8B?= Date: Fri, 26 Aug 2022 14:25:53 +0800 Subject: [PATCH 1/3] =?UTF-8?q?pod=20=E4=BE=9D=E8=B5=96=E8=AE=BE=E7=BD=AE?= =?UTF-8?q?=E5=AE=8C=E6=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NEChatUIKit/NEKitChatUI.podspec | 6 +- .../Assets/en.lproj/Localizable.strings | 10 +- .../Assets/zh-Hans.lproj/Localizable.strings | 9 +- .../Classes/Base/BaseView/ChatBaseCell.swift | 28 +- .../BaseView/ChatBaseCollectionViewCell.swift | 9 +- .../Base/BaseView/ChatCenterTextCell.swift | 67 +- .../Base/BaseView/ChatCornerCell.swift | 11 +- .../Base/BaseView/ChatHeaderView.swift | 82 +- .../Base/BaseView/ChatImageTextCell.swift | 160 +- .../Base/BaseView/ChatSectionView.swift | 52 +- .../Classes/Base/BaseView/ChatStateCell.swift | 101 +- .../Base/BaseView/ChatTextArrowCell.swift | 21 +- .../Classes/Base/BaseView/ChatTextCell.swift | 117 +- .../Base/BaseView/ChatUnfoldCell.swift | 111 +- .../Base/BaseView/ChatUserHeaderView.swift | 68 +- .../ChatBaseViewController.swift | 35 +- .../ChatNavigationController.swift | 28 +- .../ChatTableViewController.swift | 106 +- .../Chat/Controller/ChatViewController.swift | 2460 +++++++++-------- .../Controller/GroupChatViewController.swift | 115 +- .../Controller/P2PChatViewController.swift | 73 +- .../Chat/Controller/ReadViewController.swift | 445 +-- .../Controller/SelectUserViewController.swift | 276 +- .../UserSettingViewController.swift | 415 +-- .../Classes/Chat/Emoji/EmojiPageView.swift | 449 +-- .../Emoji/InputEmoticonContainerView.swift | 593 ++-- .../Chat/Emoji/InputEmoticonTabView.swift | 150 +- .../Chat/Emoji/NEEmotionAttachment.swift | 27 +- .../Classes/Chat/Emoji/NEEmotionTool.swift | 90 +- .../Chat/Emoji/NIMInputEmoticonButton.swift | 81 +- .../Chat/Emoji/NIMInputEmoticonDefine.swift | 9 +- .../Chat/Emoji/NIMInputEmoticonManager.swift | 375 ++- .../Chat/Helper/ChatMessageHelper.swift | 54 +- .../Classes/Chat/Helper/MessageUtils.swift | 106 +- .../Helper/NotificationMessageUtils.swift | 357 +-- .../Chat/Helper/ReplyMessageUtil.swift | 59 +- .../Chat/Model/MessageAudioModel.swift | 37 +- .../Chat/Model/MessageContentModel.swift | 130 +- .../Chat/Model/MessageImageModel.swift | 40 +- .../Classes/Chat/Model/MessageModel.swift | 68 +- .../Chat/Model/MessageReplyModel.swift | 54 +- .../Classes/Chat/Model/MessageTextModel.swift | 47 +- .../Classes/Chat/Model/MessageTipsModel.swift | 60 +- .../Chat/Model/MessageVideoModel.swift | 41 +- .../Classes/Chat/Model/OperationItem.swift | 116 +- .../Chat/Model/UserSettingCellModel.swift | 23 +- .../Chat/View/Cell/ChatAudioLeftCell.swift | 121 +- .../Chat/View/Cell/ChatAudioRightCell.swift | 143 +- .../Chat/View/Cell/ChatBaseLeftCell.swift | 464 ++-- .../Chat/View/Cell/ChatBaseRightCell.swift | 576 ++-- .../Chat/View/Cell/ChatImageLeftCell.swift | 80 +- .../Chat/View/Cell/ChatImageRightCell.swift | 89 +- .../Chat/View/Cell/ChatReplyLeftCell.swift | 111 +- .../Chat/View/Cell/ChatReplyRightCell.swift | 112 +- .../Chat/View/Cell/ChatRevokeLeftCell.swift | 61 +- .../Chat/View/Cell/ChatRevokeRightCell.swift | 115 +- .../Chat/View/Cell/ChatTeamMemberCell.swift | 126 +- .../Chat/View/Cell/ChatTextLeftCell.swift | 69 +- .../Chat/View/Cell/ChatTextRightCell.swift | 67 +- .../View/Cell/ChatTimeTableViewCell.swift | 58 +- .../Chat/View/Cell/ChatVideoLeftCell.swift | 224 +- .../Chat/View/Cell/ChatVideoRightCell.swift | 230 +- .../Chat/View/Cell/OperationCell.swift | 86 +- .../Chat/View/Cell/UserSettingBaseCell.swift | 89 +- .../View/Cell/UserSettingSwitchCell.swift | 109 +- .../Chat/View/Cell/UserTableViewCell.swift | 164 +- .../Chat/View/ChatActivityIndicatorView.swift | 145 +- .../Chat/View/ChatBrokenNetworkView.swift | 60 +- .../Classes/Chat/View/ChatInputView.swift | 763 ++--- .../Classes/Chat/View/ChatRecordView.swift | 235 +- .../Classes/Chat/View/CirleProgressView.swift | 129 +- .../View/ForwardAlertViewController.swift | 606 ++-- .../Chat/View/MessageOperationView.swift | 130 +- .../Classes/Chat/View/ReplyView.swift | 97 +- .../Chat/ViewModel/ChatViewModel.swift | 2003 +++++++------- .../Chat/ViewModel/TeamChatViewModel.swift | 82 +- .../Chat/ViewModel/TeamMemberSelectVM.swift | 16 +- .../Chat/ViewModel/UserSettingViewModel.swift | 194 +- .../Classes/ChatConfig/ChatUIConfig.swift | 62 +- .../Classes/ChatConfig/NEKitChatConfig.swift | 25 +- .../Classes/ChatRouter/ChatRouter.swift | 72 +- .../Classes/Common/ChatConstantValue.swift | 27 +- .../Classes/Common/Constants.swift | 120 +- .../Classes/Common/IMCustomAttachment.swift | 107 +- .../Classes/Common/NEChatUITool.swift | 29 +- .../Classes/Common/NSBundleExtension.swift | 85 +- .../Classes/Extension/AlertVCExtention.swift | 38 +- .../Extension/ChatStringExtension.swift | 70 +- .../Classes/Extension/ColorExtension.swift | 44 +- .../Classes/Extension/ImageExtension.swift | 36 +- .../Classes/Extension/NEErrorExtension.swift | 15 +- NEContactUIKit/NEKitContactUI.podspec | 8 +- .../Assets/en.lproj/Localizable.strings | 9 +- .../Assets/zh-Hans.lproj/Localizable.strings | 9 +- .../Classes/Base/ContactBaseViewCell.swift | 148 +- .../BlackListViewController.swift | 233 +- .../ViewModel/BlackListViewModel.swift | 80 +- .../BlackList/Views/BlackListCell.swift | 157 +- .../Common/ContactCellDataProtrol.swift | 8 +- .../Classes/Common/ContactConst.swift | 25 +- .../Classes/Common/ContactDataProtrol.swift | 9 +- .../Classes/Common/ContactRouter.swift | 94 +- .../ContactConfig/ContactUIConfig.swift | 60 +- .../ContactConfig/NEKitContactConfig.swift | 23 +- .../Classes/Extension/ContactUI.swift | 7 +- .../Classes/Extension/ImageExtension.swift | 20 +- .../Classes/Extension/UIViewController.swift | 43 +- .../Classes/Model/ContactInfo.swift | 23 +- .../Classes/Model/ContactSection.swift | 19 +- .../TeamListViewController.swift | 145 +- .../Team/ViewModel/TeamListViewModel.swift | 18 +- .../Team/Views/TeamTableViewCell.swift | 160 +- .../Classes/UserInfo/Models/UserItem.swift | 17 +- .../Classes/UserInfo/UserInfoHeaderView.swift | 166 +- .../ContactRemakNameViewController.swift | 186 +- .../ContactUserViewController.swift | 512 ++-- .../UserInfo/Views/CenterTextCell.swift | 68 +- .../Classes/UserInfo/Views/TextBaseCell.swift | 81 +- .../Views/TextWithDetailTextCell.swift | 46 +- .../Views/TextWithRightArrowCell.swift | 46 +- .../UserInfo/Views/TextWithSwitchCell.swift | 59 +- .../ValidationMessageViewController.swift | 258 +- .../ValidationMessageViewModel.swift | 125 +- .../Validation/Views/BaseValidationCell.swift | 198 +- .../Views/SystemNotificationCell.swift | 347 ++- .../Classes/ViewModel/ContactGroup.swift | 10 +- .../ViewModel/ContactUserViewModel.swift | 64 +- .../Classes/ViewModel/ContactViewModel.swift | 229 +- .../ViewModel/FindFriendViewModel.swift | 18 +- .../Views/Cell/ContactSelectedCell.swift | 94 +- .../Views/Cell/ContactUnCheckCell.swift | 72 +- .../Views/ContactBaseViewController.swift | 72 +- .../Classes/Views/ContactHeadItem.swift | 28 +- .../Classes/Views/ContactSectionView.swift | 78 +- .../Classes/Views/ContactTableViewCell.swift | 207 +- .../ContactsSelectedViewController.swift | 528 ++-- .../Views/ContactsViewController.swift | 465 ++-- .../Views/FindFriendViewController.swift | 279 +- .../NEKitContactUI/NEKitContactUI.h | 15 +- .../NEKitConversationUI.podspec | 6 +- .../Assets/en.lproj/Localizable.strings | 10 +- .../Assets/zh-Hans.lproj/Localizable.strings | 9 +- .../Classes/Common/ColorExtension.swift | 53 +- .../Classes/Common/ConversationConstant.swift | 10 +- .../Classes/Common/ConversationUI.swift | 10 +- .../Classes/Common/ImageExtension.swift | 19 +- .../Controller/ConversationController.swift | 296 +- .../ConversationListViewController.swift | 614 ++-- .../ConversationSearchController.swift | 500 ++-- .../ConversationRouter.swift | 31 +- .../View/ConversationListCell.swift | 487 ++-- .../View/ConversationNavView.swift | 218 +- .../View/ConversationSearchCell.swift | 107 +- .../ConversationSearchViewModel.swift | 52 +- .../ViewModel/ConversationViewModel.swift | 464 ++-- .../ConversationUIConfig.swift | 86 +- .../NEKitConversationConfig.swift | 23 +- .../Classes/Util/NEMessageUtil.swift | 85 +- NEQChatUIKit/NEKitQChatUI.podspec | 8 +- .../Assets/en.lproj/Localizable.strings | 25 +- .../Assets/zh-Hans.lproj/Localizable.strings | 23 +- .../Classes/Base/BaseView/QChatBaseCell.swift | 22 +- .../QChatBaseCollectionViewCell.swift | 9 +- .../Base/BaseView/QChatCenterTextCell.swift | 67 +- .../Base/BaseView/QChatCornerCell.swift | 11 +- .../Base/BaseView/QChatHeaderView.swift | 82 +- .../Base/BaseView/QChatImageTextCell.swift | 160 +- .../Base/BaseView/QChatSectionView.swift | 52 +- .../Base/BaseView/QChatStateCell.swift | 101 +- .../Base/BaseView/QChatTextArrowCell.swift | 21 +- .../Classes/Base/BaseView/QChatTextCell.swift | 117 +- .../Base/BaseView/QChatUnfoldCell.swift | 111 +- .../QChatBaseViewController.swift | 32 +- .../QChatNavigationController.swift | 28 +- .../QChatTableViewController.swift | 106 +- .../Classes/Channel/Model/QChatRoles.swift | 30 +- .../Channel/Model/RoleStatusInfoExt.swift | 17 +- .../Channel/View/ChannelHeaderView.swift | 119 +- .../Classes/Channel/View/CornerButton.swift | 178 +- .../View/QChatImageTextOnlineCell.swift | 64 +- .../Channel/View/QChatMemberInfoView.swift | 518 ++-- .../View/QChatPermissionSettingCell.swift | 258 +- .../Channel/View/QChatTextEditCell.swift | 142 +- .../Channel/View/QChatTextSelectionCell.swift | 59 +- .../ViewController/QChatAddMemberVC.swift | 375 +-- .../ViewController/QChatAddRoleGroupVC.swift | 379 +-- .../QChatChannelAuthoritySettingVC.swift | 589 ++-- .../QChatChannelMembersVC.swift | 300 +- .../QChatChannelSettingVC.swift | 408 +-- .../ViewController/QChatChannelTypeVC.swift | 104 +- .../QChatChannelViewController.swift | 340 ++- .../QChatGroupPermissionSettingVC.swift | 241 +- .../QChatMemberPermissionSettingVC.swift | 302 +- .../ViewController/QChatSearchVC.swift | 99 +- .../QChatWhiteBlackListVC.swift | 402 +-- .../QChatAuthoritySettingViewModel.swift | 335 +-- .../ViewModel/QChatChannelViewModel.swift | 60 +- .../QChatUpdateChannelViewModel.swift | 50 +- .../Chat/Controller/QChatViewController.swift | 670 ++--- .../Chat/Helper/QChatMessageHelper.swift | 54 +- .../Chat/Model/QChatMessageFrame.swift | 176 +- .../View/Cell/QChatBaseTableViewCell.swift | 271 +- .../View/Cell/QChatImageTableViewCell.swift | 67 +- .../View/Cell/QChatTextTableViewCell.swift | 146 +- .../View/Cell/QChatTimeTableViewCell.swift | 62 +- .../View/QChatActivityIndicatorView.swift | 141 +- .../Classes/Chat/View/QChatInputView.swift | 137 +- .../Chat/ViewModel/QChatViewModel.swift | 469 ++-- .../Classes/Common/Constants.swift | 118 +- .../Classes/Common/NEAuthManager.swift | 82 +- .../Classes/Common/QChatConstantValue.swift | 28 +- .../Classes/Extension/AlertVCExtention.swift | 22 +- .../Classes/Extension/ColorExtension.swift | 38 +- .../Classes/Extension/ImageExtension.swift | 21 +- .../Classes/Extension/NEErrorExtension.swift | 15 +- .../Extension/QChatStringExtension.swift | 70 +- .../CreateServerViewController.swift | 141 +- .../JoinOtherServiceController.swift | 324 ++- .../Controller/MemberListViewController.swift | 236 +- .../MineCreateServerController.swift | 428 +-- .../Controller/QChatHomeViewController.swift | 642 ++--- .../QChatHomePage/Model/AllChannelData.swift | 84 +- .../Model/ServerMemberModel.swift | 15 +- .../QChatHomePage/View/EmptyDataView.swift | 124 +- .../QChatHomePage/View/InviteMemberView.swift | 107 +- .../View/NECreateServerCell.swift | 187 +- .../View/NEGroupIdentityMemberCell.swift | 493 ++-- .../View/NEHomeChannelCell.swift | 145 +- .../View/NEHomeChannelView.swift | 564 ++-- .../QChatHomePage/View/NEHomeServerCell.swift | 217 +- .../QChatHomePage/View/NEMemberListCell.swift | 149 +- .../View/NESearchServerCell.swift | 409 +-- .../ViewModel/CreateServerViewModel.swift | 401 +-- .../ViewModel/MemberListViewModel.swift | 97 +- .../Classes/QChatRouter/QChatRouter.swift | 11 +- .../Classes/Server/Model/IdGroupModel.swift | 49 +- .../Server/Model/PermissionCellModel.swift | 16 +- .../Server/Model/PermissionModel.swift | 182 +- .../Classes/Server/Model/SettingModel.swift | 10 +- .../Classes/Server/Model/UserInfo.swift | 80 +- .../Server/View/QChatDestructiveCell.swift | 79 +- .../Classes/Server/View/QChatHeaderCell.swift | 115 +- .../Server/View/QChatIdGroupCell.swift | 262 +- .../Server/View/QChatIdGroupMemberCell.swift | 174 +- .../Server/View/QChatIdGroupSelectCell.swift | 111 +- .../View/QChatIdGroupSortButtonCell.swift | 138 +- .../Server/View/QChatIdGroupTopCell.swift | 43 +- .../Server/View/QChatMemberManagerCell.swift | 35 +- .../Server/View/QChatPlainTextArrowCell.swift | 37 +- .../Server/View/QChatSelectedCell.swift | 164 +- .../Classes/Server/View/QChatSortCell.swift | 50 +- .../Classes/Server/View/QChatSwitchCell.swift | 153 +- .../Server/View/QChatUserUnCheckCell.swift | 97 +- .../QChatCreateGroupViewController.swift | 467 ++-- .../QChatEditMemberViewController.swift | 629 +++-- .../QChatIdGroupSortController.swift | 330 +-- .../QChatIdGroupViewController.swift | 401 +-- .../QChatMemberManagerController.swift | 343 +-- .../QChatMemberSelectController.swift | 460 +-- .../QChatPermissionViewController.swift | 524 ++-- .../QChatServerSettingViewController.swift | 877 +++--- .../ViewModel/CreateGroupViewModel.swift | 151 +- .../ViewModel/EditMemberViewModel.swift | 387 +-- .../ViewModel/IdGroupSortViewModel.swift | 234 +- .../Server/ViewModel/IdGroupViewModel.swift | 162 +- .../ViewModel/MemberManagerViewModel.swift | 174 +- .../ViewModel/MemberSelectViewModel.swift | 220 +- .../ViewModel/PermissionViewModel.swift | 112 +- .../Server/ViewModel/SettingViewModel.swift | 30 +- NETeamUIKit/NEKitTeamUI.podspec | 8 +- .../Assets/en.lproj/Localizable.strings | 9 +- .../Assets/zh-Hans.lproj/Localizable.strings | 10 +- .../Setting/Model/SettingCellModel.swift | 56 +- .../Setting/Model/SettingSectionModel.swift | 9 +- .../Setting/TeamAvatarViewController.swift | 501 ++-- .../TeamHistoryMessageController.swift | 332 +-- .../Setting/TeamInfoViewController.swift | 198 +- .../Setting/TeamIntroduceViewController.swift | 313 ++- .../Setting/TeamMembersController.swift | 369 +-- .../Setting/TeamNameViewController.swift | 395 +-- .../Setting/TeamSettingViewController.swift | 1301 ++++----- .../Setting/View/BaseTeamSettingCell.swift | 89 +- .../Setting/View/HistoryMessageCell.swift | 270 +- .../Setting/View/TeamArrowSettingCell.swift | 65 +- .../Setting/View/TeamDefaultIconCell.swift | 104 +- .../Classes/Setting/View/TeamMemberCell.swift | 180 +- .../Setting/View/TeamSettingHeaderCell.swift | 108 +- .../View/TeamSettingRightCustomCell.swift | 99 +- .../Setting/View/TeamSettingSelectCell.swift | 110 +- .../View/TeamSettingSubtitleCell.swift | 119 +- .../Setting/View/TeamSettingSwitchCell.swift | 111 +- .../Classes/Setting/View/TeamUserCell.swift | 88 +- .../Setting/ViewModel/TeamInfoViewModel.swift | 68 +- .../ViewModel/TeamSettingViewModel.swift | 621 ++--- .../NEKitTeamUI/Classes/TeamConstant.swift | 11 +- .../NEKitTeamUI/Classes/TeamRouter.swift | 156 +- Podfile | 44 +- app.xcodeproj/project.pbxproj | 18 - 298 files changed, 26412 insertions(+), 25052 deletions(-) diff --git a/NEChatUIKit/NEKitChatUI.podspec b/NEChatUIKit/NEKitChatUI.podspec index b2f4490f..4d74f8ff 100644 --- a/NEChatUIKit/NEKitChatUI.podspec +++ b/NEChatUIKit/NEKitChatUI.podspec @@ -16,7 +16,7 @@ Pod::Spec.new do |spec| # spec.name = "NEKitChatUI" - spec.version = "9.2.6-rc01" + spec.version = "9.2.7" spec.summary = "Chat Module of IM." # This description is used to generate tags and improve search results. @@ -34,6 +34,10 @@ TODO: Add long description of the pod here. spec.ios.deployment_target = '9.0' spec.source_files = 'NEKitChatUI/Classes/**/*' + spec.pod_target_xcconfig = { + 'BUILD_LIBRARY_FOR_DISTRIBUTION' => 'YES' + } + spec.user_target_xcconfig = { 'BUILD_LIBRARY_FOR_DISTRIBUTION' => 'YES' } spec.resource_bundles = { 'NEKitChatUI' => ['NEKitChatUI/Assets/*.png'] diff --git a/NEChatUIKit/NEKitChatUI/Assets/en.lproj/Localizable.strings b/NEChatUIKit/NEKitChatUI/Assets/en.lproj/Localizable.strings index ae17ed00..ca96635f 100644 --- a/NEChatUIKit/NEKitChatUI/Assets/en.lproj/Localizable.strings +++ b/NEChatUIKit/NEKitChatUI/Assets/en.lproj/Localizable.strings @@ -1,10 +1,8 @@ -/* - YXLogin.strings - Pods - Created by yu chen on 2021/12/24. - -*/ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + //MAKR:common "ok"="ok"; "send_to"="To "; diff --git a/NEChatUIKit/NEKitChatUI/Assets/zh-Hans.lproj/Localizable.strings b/NEChatUIKit/NEKitChatUI/Assets/zh-Hans.lproj/Localizable.strings index a59a5924..8a836d25 100644 --- a/NEChatUIKit/NEKitChatUI/Assets/zh-Hans.lproj/Localizable.strings +++ b/NEChatUIKit/NEKitChatUI/Assets/zh-Hans.lproj/Localizable.strings @@ -1,10 +1,7 @@ -/* - YXLogin.strings - Pods - Created by yu chen on 2021/12/24. - -*/ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. //MAKR:common "ok"="确认"; diff --git a/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatBaseCell.swift b/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatBaseCell.swift index 65b9e293..b1d89153 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatBaseCell.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatBaseCell.swift @@ -1,21 +1,21 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit public class ChatBaseCell: UITableViewCell { - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - self.selectionStyle = .none - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - public func uploadProgress(_ progress: Float){ - fatalError("override in sub class") - } + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + selectionStyle = .none + } + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + public func uploadProgress(_ progress: Float) { + fatalError("override in sub class") + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatBaseCollectionViewCell.swift b/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatBaseCollectionViewCell.swift index 3cc68139..9d38260d 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatBaseCollectionViewCell.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatBaseCollectionViewCell.swift @@ -1,9 +1,8 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit -class ChatBaseCollectionViewCell: UICollectionViewCell { - -} +class ChatBaseCollectionViewCell: UICollectionViewCell {} diff --git a/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatCenterTextCell.swift b/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatCenterTextCell.swift index 93dd8b50..1ccc3cf2 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatCenterTextCell.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatCenterTextCell.swift @@ -1,41 +1,40 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class ChatCenterTextCell: ChatCornerCell { + public var titleLabel: UILabel = .init() + public var line = UIView() + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) - public var titleLabel: UILabel = UILabel() - public var line = UIView() - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - - self.titleLabel.font = UIFont.systemFont(ofSize: 16) - self.titleLabel.translatesAutoresizingMaskIntoConstraints = false - self.titleLabel.textColor = .ne_redText - self.titleLabel.textAlignment = .center - self.contentView.addSubview(self.titleLabel) - NSLayoutConstraint.activate([ - self.titleLabel.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 36), - self.titleLabel.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -36), - self.titleLabel.topAnchor.constraint(equalTo: self.contentView.topAnchor), - self.titleLabel.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor) - ]) - self.titleLabel.text = "title" - self.line.backgroundColor = .ne_greyLine - self.line.translatesAutoresizingMaskIntoConstraints = false - self.contentView.addSubview(self.line) - NSLayoutConstraint.activate([ - self.line.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 20), - self.line.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -20), - self.line.heightAnchor.constraint(equalToConstant: 1.0), - self.line.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor) - ]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - + titleLabel.font = UIFont.systemFont(ofSize: 16) + titleLabel.translatesAutoresizingMaskIntoConstraints = false + titleLabel.textColor = .ne_redText + titleLabel.textAlignment = .center + contentView.addSubview(titleLabel) + NSLayoutConstraint.activate([ + titleLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 36), + titleLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -36), + titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor), + titleLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + ]) + titleLabel.text = "title" + line.backgroundColor = .ne_greyLine + line.translatesAutoresizingMaskIntoConstraints = false + contentView.addSubview(line) + NSLayoutConstraint.activate([ + line.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20), + line.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), + line.heightAnchor.constraint(equalToConstant: 1.0), + line.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + ]) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatCornerCell.swift b/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatCornerCell.swift index 790758eb..6f2b7216 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatCornerCell.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatCornerCell.swift @@ -1,11 +1,10 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. -//this cell has rounding corner style +// this cell has rounding corner style import UIKit import NEKitCommonUI -class ChatCornerCell: CornerCell { - -} +class ChatCornerCell: CornerCell {} diff --git a/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatHeaderView.swift b/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatHeaderView.swift index 0caf508c..5909d11a 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatHeaderView.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatHeaderView.swift @@ -1,48 +1,48 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit public class ChatHeaderView: UIView { - - public lazy var titleLabel: UILabel = { - let label = UILabel() - label.font = DefaultTextFont(12) - label.textColor = .ne_greyText - label.translatesAutoresizingMaskIntoConstraints = false - return label - }() - - /* - // Only override draw() if you perform custom drawing. - // An empty implementation adversely affects performance during animation. - override func draw(_ rect: CGRect) { - // Drawing code - } - */ - - override init(frame: CGRect) { - super.init(frame: frame) - setupUI() - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - } - - func setupUI(){ - clipsToBounds = false - addSubview(titleLabel) - NSLayoutConstraint.activate([ - titleLabel.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -8), - titleLabel.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 33) - ]) - backgroundColor = .clear - } - - public func setTitle(_ name: String){ - titleLabel.text = name.count > 2 ? String(name[name.index(name.endIndex, offsetBy: -2)...]) : name - } + public lazy var titleLabel: UILabel = { + let label = UILabel() + label.font = DefaultTextFont(12) + label.textColor = .ne_greyText + label.translatesAutoresizingMaskIntoConstraints = false + return label + }() + /* + // Only override draw() if you perform custom drawing. + // An empty implementation adversely affects performance during animation. + override func draw(_ rect: CGRect) { + // Drawing code + } + */ + + override init(frame: CGRect) { + super.init(frame: frame) + setupUI() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + func setupUI() { + clipsToBounds = false + addSubview(titleLabel) + NSLayoutConstraint.activate([ + titleLabel.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -8), + titleLabel.leftAnchor.constraint(equalTo: leftAnchor, constant: 33), + ]) + backgroundColor = .clear + } + + public func setTitle(_ name: String) { + titleLabel.text = name + .count > 2 ? String(name[name.index(name.endIndex, offsetBy: -2)...]) : name + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatImageTextCell.swift b/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatImageTextCell.swift index 8a8f3552..0fe2fe59 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatImageTextCell.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatImageTextCell.swift @@ -1,90 +1,90 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class ChatImageTextCell: ChatStateCell { - var circleView = UIImageView() - public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - //circle view - circleView.translatesAutoresizingMaskIntoConstraints = false - circleView.layer.cornerRadius = 16 - circleView.clipsToBounds = true - circleView.backgroundColor = .ne_defautAvatarColor - self.contentView.addSubview(circleView) - NSLayoutConstraint.activate([ - circleView.widthAnchor.constraint(equalToConstant: 36), - circleView.heightAnchor.constraint(equalToConstant: 36), - circleView.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 40), - circleView.centerYAnchor.constraint(equalTo: self.contentView.centerYAnchor, constant: 0) - ]) + var circleView = UIImageView() + override public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + // circle view + circleView.translatesAutoresizingMaskIntoConstraints = false + circleView.layer.cornerRadius = 16 + circleView.clipsToBounds = true + circleView.backgroundColor = .ne_defautAvatarColor + contentView.addSubview(circleView) + NSLayoutConstraint.activate([ + circleView.widthAnchor.constraint(equalToConstant: 36), + circleView.heightAnchor.constraint(equalToConstant: 36), + circleView.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 40), + circleView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor, constant: 0), + ]) // short name label - self.contentView.addSubview(self.shortNameLabel) - NSLayoutConstraint.activate([ - shortNameLabel.widthAnchor.constraint(equalTo: circleView.widthAnchor), - shortNameLabel.heightAnchor.constraint(equalTo: circleView.heightAnchor), - shortNameLabel.leftAnchor.constraint(equalTo: circleView.leftAnchor), - shortNameLabel.topAnchor.constraint(equalTo: circleView.topAnchor) - ]) + contentView.addSubview(shortNameLabel) + NSLayoutConstraint.activate([ + shortNameLabel.widthAnchor.constraint(equalTo: circleView.widthAnchor), + shortNameLabel.heightAnchor.constraint(equalTo: circleView.heightAnchor), + shortNameLabel.leftAnchor.constraint(equalTo: circleView.leftAnchor), + shortNameLabel.topAnchor.constraint(equalTo: circleView.topAnchor), + ]) // name label - self.contentView.addSubview(self.nameLabel) - NSLayoutConstraint.activate([ - nameLabel.leftAnchor.constraint(equalTo: circleView.rightAnchor, constant: 12), - nameLabel.topAnchor.constraint(equalTo: self.contentView.topAnchor), - nameLabel.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor), - ]) + contentView.addSubview(nameLabel) + NSLayoutConstraint.activate([ + nameLabel.leftAnchor.constraint(equalTo: circleView.rightAnchor, constant: 12), + nameLabel.topAnchor.constraint(equalTo: contentView.topAnchor), + nameLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + ]) // line - let line = UIView() - line.backgroundColor = .ne_greyLine - line.translatesAutoresizingMaskIntoConstraints = false - self.contentView.addSubview(line) - NSLayoutConstraint.activate([ - line.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 20), - line.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -20), - line.heightAnchor.constraint(equalToConstant: 1), - line.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: -1) - ]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - public lazy var avatarImage: UIImageView = { - let avatar = UIImageView() - avatar.translatesAutoresizingMaskIntoConstraints = false - avatar.clipsToBounds = true - avatar.backgroundColor = .ne_defautAvatarColor - return avatar - }() - - public lazy var shortNameLabel: UILabel = { - let name = UILabel() - name.translatesAutoresizingMaskIntoConstraints = false - name.textColor = .white - name.textAlignment = .center - name.font = UIFont.systemFont(ofSize: 14.0) - name.text = "果冻" - return name - }() - - public lazy var nameLabel: UILabel = { - let label = UILabel() - label.textAlignment = .left - label.translatesAutoresizingMaskIntoConstraints = false - label.font = UIFont.systemFont(ofSize: 14.0) - label.textColor = .ne_darkText - return label - }() - - public func setup(accid: String?, nickName: String?) { - let name = nickName?.count ?? 0 > 0 ? nickName : accid - self.nameLabel.text = name - guard let n = name else { return } - self.shortNameLabel.text = n.count > 2 ? String(n[n.index(n.endIndex, offsetBy: -2)...]) : n - self.circleView.backgroundColor = UIColor.colorWithString(string: accid) - } + let line = UIView() + line.backgroundColor = .ne_greyLine + line.translatesAutoresizingMaskIntoConstraints = false + contentView.addSubview(line) + NSLayoutConstraint.activate([ + line.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20), + line.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), + line.heightAnchor.constraint(equalToConstant: 1), + line.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -1), + ]) + } + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + public lazy var avatarImage: UIImageView = { + let avatar = UIImageView() + avatar.translatesAutoresizingMaskIntoConstraints = false + avatar.clipsToBounds = true + avatar.backgroundColor = .ne_defautAvatarColor + return avatar + }() + + public lazy var shortNameLabel: UILabel = { + let name = UILabel() + name.translatesAutoresizingMaskIntoConstraints = false + name.textColor = .white + name.textAlignment = .center + name.font = UIFont.systemFont(ofSize: 14.0) + name.text = "果冻" + return name + }() + + public lazy var nameLabel: UILabel = { + let label = UILabel() + label.textAlignment = .left + label.translatesAutoresizingMaskIntoConstraints = false + label.font = UIFont.systemFont(ofSize: 14.0) + label.textColor = .ne_darkText + return label + }() + + public func setup(accid: String?, nickName: String?) { + let name = nickName?.count ?? 0 > 0 ? nickName : accid + nameLabel.text = name + guard let n = name else { return } + shortNameLabel.text = n.count > 2 ? String(n[n.index(n.endIndex, offsetBy: -2)...]) : n + circleView.backgroundColor = UIColor.colorWithString(string: accid) + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatSectionView.swift b/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatSectionView.swift index 3b1c68fb..f0c84212 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatSectionView.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatSectionView.swift @@ -1,35 +1,33 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class ChatSectionView: UITableViewHeaderFooterView { - public var titleLable = UILabel() - override init(reuseIdentifier: String?) { - super.init(reuseIdentifier: reuseIdentifier) - self.commonUI() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func commonUI() { - self.contentView.backgroundColor = .ne_lightBackgroundColor - self.titleLable.font = UIFont.systemFont(ofSize: 12) - self.titleLable.textColor = .ne_greyText - self.titleLable.translatesAutoresizingMaskIntoConstraints = false - - self.contentView.addSubview(self.titleLable) - NSLayoutConstraint.activate([ - self.titleLable.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 33), - self.titleLable.topAnchor.constraint(equalTo: self.topAnchor, constant: 8), - self.titleLable.bottomAnchor.constraint(equalTo: self.bottomAnchor), - self.titleLable.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -33) - ]) - - } + public var titleLable = UILabel() + override init(reuseIdentifier: String?) { + super.init(reuseIdentifier: reuseIdentifier) + commonUI() + } + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + func commonUI() { + contentView.backgroundColor = .ne_lightBackgroundColor + titleLable.font = UIFont.systemFont(ofSize: 12) + titleLable.textColor = .ne_greyText + titleLable.translatesAutoresizingMaskIntoConstraints = false + + contentView.addSubview(titleLable) + NSLayoutConstraint.activate([ + titleLable.leftAnchor.constraint(equalTo: leftAnchor, constant: 33), + titleLable.topAnchor.constraint(equalTo: topAnchor, constant: 8), + titleLable.bottomAnchor.constraint(equalTo: bottomAnchor), + titleLable.rightAnchor.constraint(equalTo: rightAnchor, constant: -33), + ]) + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatStateCell.swift b/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatStateCell.swift index c425315f..8887de3a 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatStateCell.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatStateCell.swift @@ -1,63 +1,66 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit enum RightStyle { - case none - case indicate - case delete + case none + case indicate + case delete } class ChatStateCell: ChatCornerCell { - private var style: RightStyle = .none; - public var rightImage = UIImageView() - var rightImageMargin: NSLayoutConstraint? - public var rightStyle: RightStyle { - get { - return style - } - set { - style = newValue; - switch style { - case .none: - rightImage.image = nil - case .indicate: - rightImage.image = UIImage.ne_imageNamed(name: "arrowRight") - case .delete: - rightImage.image = UIImage.ne_imageNamed(name: "delete") - } - } + private var style: RightStyle = .none + public var rightImage = UIImageView() + var rightImageMargin: NSLayoutConstraint? + public var rightStyle: RightStyle { + get { + style } - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - self.rightImage.contentMode = .center - self.rightImage.translatesAutoresizingMaskIntoConstraints = false - self.contentView.addSubview(self.rightImage) - rightImageMargin = rightImage.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -36) - rightImageMargin?.isActive = true - NSLayoutConstraint.activate([ - self.rightImage.widthAnchor.constraint(equalToConstant: 20), - self.rightImage.heightAnchor.constraint(equalToConstant: 20), - self.rightImage.centerYAnchor.constraint(equalTo: self.contentView.centerYAnchor), - ]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code + set { + style = newValue + switch style { + case .none: + rightImage.image = nil + case .indicate: + rightImage.image = UIImage.ne_imageNamed(name: "arrowRight") + case .delete: + rightImage.image = UIImage.ne_imageNamed(name: "delete") + } } + } - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + rightImage.contentMode = .center + rightImage.translatesAutoresizingMaskIntoConstraints = false + contentView.addSubview(rightImage) + rightImageMargin = rightImage.rightAnchor.constraint( + equalTo: contentView.rightAnchor, + constant: -36 + ) + rightImageMargin?.isActive = true + NSLayoutConstraint.activate([ + rightImage.widthAnchor.constraint(equalToConstant: 20), + rightImage.heightAnchor.constraint(equalToConstant: 20), + rightImage.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + ]) + } - // Configure the view for the selected state - } + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + // Configure the view for the selected state + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatTextArrowCell.swift b/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatTextArrowCell.swift index 29a66840..d26b9ccb 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatTextArrowCell.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatTextArrowCell.swift @@ -1,18 +1,17 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class ChatTextArrowCell: ChatTextCell { - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - self.rightStyle = .indicate - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + rightStyle = .indicate + } + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatTextCell.swift b/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatTextCell.swift index 945e6af7..1c386288 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatTextCell.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatTextCell.swift @@ -1,63 +1,68 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class ChatTextCell: ChatStateCell { - public var titleLabel: UILabel = UILabel() - public var detailLabel: UILabel = UILabel() - public var line = UIView() - - var titleLeftMargin: NSLayoutConstraint? - - var detailRightMargin: NSLayoutConstraint? - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - - self.titleLabel.font = UIFont.systemFont(ofSize: 16) - self.titleLabel.translatesAutoresizingMaskIntoConstraints = false - self.titleLabel.textColor = .ne_darkText - self.contentView.addSubview(self.titleLabel) - titleLeftMargin = titleLabel.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 36) - titleLeftMargin?.isActive = true - NSLayoutConstraint.activate([ -// self.titleLabel.widthAnchor.constraint(lessThanOrEqualToConstant: 120), - self.titleLabel.topAnchor.constraint(equalTo: self.contentView.topAnchor), - self.titleLabel.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor) - ]) - self.titleLabel.text = "删除" - - self.detailLabel.font = UIFont.systemFont(ofSize: 16) - self.detailLabel.translatesAutoresizingMaskIntoConstraints = false - self.detailLabel.textColor = .ne_lightText - self.contentView.addSubview(self.detailLabel) - - detailRightMargin = detailLabel.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -60) - detailRightMargin?.isActive = true - NSLayoutConstraint.activate([ - self.detailLabel.leftAnchor.constraint(equalTo: self.titleLabel.rightAnchor, constant: 0), - self.detailLabel.widthAnchor.constraint(lessThanOrEqualToConstant: 40), - self.detailLabel.topAnchor.constraint(equalTo: self.contentView.topAnchor), - self.detailLabel.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor) - ]) - self.detailLabel.textAlignment = .right - - self.line.backgroundColor = .ne_greyLine - self.line.translatesAutoresizingMaskIntoConstraints = false - self.contentView.addSubview(self.line) - NSLayoutConstraint.activate([ - self.line.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 20), - self.line.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -20), - self.line.heightAnchor.constraint(equalToConstant: 1.0), - self.line.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor) - ]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - + public var titleLabel: UILabel = .init() + public var detailLabel: UILabel = .init() + public var line = UIView() + var titleLeftMargin: NSLayoutConstraint? + + var detailRightMargin: NSLayoutConstraint? + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + + titleLabel.font = UIFont.systemFont(ofSize: 16) + titleLabel.translatesAutoresizingMaskIntoConstraints = false + titleLabel.textColor = .ne_darkText + contentView.addSubview(titleLabel) + titleLeftMargin = titleLabel.leftAnchor.constraint( + equalTo: contentView.leftAnchor, + constant: 36 + ) + titleLeftMargin?.isActive = true + NSLayoutConstraint.activate([ + // self.titleLabel.widthAnchor.constraint(lessThanOrEqualToConstant: 120), + titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor), + titleLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + ]) + titleLabel.text = "删除" + + detailLabel.font = UIFont.systemFont(ofSize: 16) + detailLabel.translatesAutoresizingMaskIntoConstraints = false + detailLabel.textColor = .ne_lightText + contentView.addSubview(detailLabel) + + detailRightMargin = detailLabel.rightAnchor.constraint( + equalTo: contentView.rightAnchor, + constant: -60 + ) + detailRightMargin?.isActive = true + NSLayoutConstraint.activate([ + detailLabel.leftAnchor.constraint(equalTo: titleLabel.rightAnchor, constant: 0), + detailLabel.widthAnchor.constraint(lessThanOrEqualToConstant: 40), + detailLabel.topAnchor.constraint(equalTo: contentView.topAnchor), + detailLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + ]) + detailLabel.textAlignment = .right + + line.backgroundColor = .ne_greyLine + line.translatesAutoresizingMaskIntoConstraints = false + contentView.addSubview(line) + NSLayoutConstraint.activate([ + line.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20), + line.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), + line.heightAnchor.constraint(equalToConstant: 1.0), + line.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + ]) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatUnfoldCell.swift b/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatUnfoldCell.swift index 9a11f936..0f098f4d 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatUnfoldCell.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatUnfoldCell.swift @@ -1,66 +1,65 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class ChatUnfoldCell: ChatCornerCell { - - lazy var arrowImage: UIImageView = { - let arrow = UIImageView() - arrow.translatesAutoresizingMaskIntoConstraints = false - arrow.image = UIImage.ne_imageNamed(name: "arrowDown") - return arrow - }() - - lazy var contentLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.textColor = .ne_greyText - label.font = DefaultTextFont(14) - return label - }() + lazy var arrowImage: UIImageView = { + let arrow = UIImageView() + arrow.translatesAutoresizingMaskIntoConstraints = false + arrow.image = UIImage.ne_imageNamed(name: "arrowDown") + return arrow + }() - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } + lazy var contentLabel: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.textColor = .ne_greyText + label.font = DefaultTextFont(14) + return label + }() - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } - // Configure the view for the selected state - } - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - setupUI() - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - } - - func setupUI(){ - contentView.addSubview(contentLabel) - NSLayoutConstraint.activate([ - contentLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - contentLabel.centerXAnchor.constraint(equalTo: contentView.centerXAnchor) - ]) - - contentView.addSubview(arrowImage) - NSLayoutConstraint.activate([ - arrowImage.leftAnchor.constraint(equalTo: contentLabel.rightAnchor, constant: 5), - arrowImage.centerYAnchor.constraint(equalTo: contentLabel.centerYAnchor) - ]) - } - - func changeToArrowUp(){ - arrowImage.image = UIImage.ne_imageNamed(name: "arrowUp") - } - - func changeToArrowDown(){ - arrowImage.image = UIImage.ne_imageNamed(name: "arrowDown") - } + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + // Configure the view for the selected state + } + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + setupUI() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + func setupUI() { + contentView.addSubview(contentLabel) + NSLayoutConstraint.activate([ + contentLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + contentLabel.centerXAnchor.constraint(equalTo: contentView.centerXAnchor), + ]) + + contentView.addSubview(arrowImage) + NSLayoutConstraint.activate([ + arrowImage.leftAnchor.constraint(equalTo: contentLabel.rightAnchor, constant: 5), + arrowImage.centerYAnchor.constraint(equalTo: contentLabel.centerYAnchor), + ]) + } + + func changeToArrowUp() { + arrowImage.image = UIImage.ne_imageNamed(name: "arrowUp") + } + + func changeToArrowDown() { + arrowImage.image = UIImage.ne_imageNamed(name: "arrowDown") + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatUserHeaderView.swift b/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatUserHeaderView.swift index dff5728c..f28d2b98 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatUserHeaderView.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Base/BaseView/ChatUserHeaderView.swift @@ -1,42 +1,42 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit public class ChatUserHeaderView: UIImageView { + public lazy var titleLabel: UILabel = { + let label = UILabel() + label.font = DefaultTextFont(12) + label.textColor = .white + label.translatesAutoresizingMaskIntoConstraints = false + return label + }() - public lazy var titleLabel: UILabel = { - let label = UILabel() - label.font = DefaultTextFont(12) - label.textColor = .white - label.translatesAutoresizingMaskIntoConstraints = false - return label - }() - - public override init(frame: CGRect) { - super.init(frame: frame) - setupUI() - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - } - - func setupUI(){ - isUserInteractionEnabled = true - clipsToBounds = false - addSubview(titleLabel) - NSLayoutConstraint.activate([ - titleLabel.centerYAnchor - .constraint(equalTo: centerYAnchor), - titleLabel.centerXAnchor.constraint(equalTo: centerXAnchor) - ]) - backgroundColor = .clear - } - - public func setTitle(_ name: String) { - titleLabel.text = name.count > 2 ? String(name[name.index(name.endIndex, offsetBy: -2)...]) : name - } + override public init(frame: CGRect) { + super.init(frame: frame) + setupUI() + } + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + func setupUI() { + isUserInteractionEnabled = true + clipsToBounds = false + addSubview(titleLabel) + NSLayoutConstraint.activate([ + titleLabel.centerYAnchor + .constraint(equalTo: centerYAnchor), + titleLabel.centerXAnchor.constraint(equalTo: centerXAnchor), + ]) + backgroundColor = .clear + } + + public func setTitle(_ name: String) { + titleLabel.text = name + .count > 2 ? String(name[name.index(name.endIndex, offsetBy: -2)...]) : name + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Base/BaseViewController/ChatBaseViewController.swift b/NEChatUIKit/NEKitChatUI/Classes/Base/BaseViewController/ChatBaseViewController.swift index 2bba858b..c74ac360 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Base/BaseViewController/ChatBaseViewController.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Base/BaseViewController/ChatBaseViewController.swift @@ -1,26 +1,23 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCore class ChatBaseViewController: NEBaseViewController { - - override func viewDidLoad() { - super.viewDidLoad() - - } - - - /* - // MARK: - Navigation - - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. - } - */ - + override func viewDidLoad() { + super.viewDidLoad() + } + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Base/BaseViewController/ChatNavigationController.swift b/NEChatUIKit/NEKitChatUI/Classes/Base/BaseViewController/ChatNavigationController.swift index 625257eb..53418ac4 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Base/BaseViewController/ChatNavigationController.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Base/BaseViewController/ChatNavigationController.swift @@ -1,22 +1,22 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit public class QChatNavigationController: UINavigationController { + override public func viewDidLoad() { + super.viewDidLoad() + } - public override func viewDidLoad() { - super.viewDidLoad() - } - - public override func pushViewController(_ viewController: UIViewController, animated: Bool) { - if children.count > 0 { - viewController.hidesBottomBarWhenPushed = true - if children.count > 1 { - viewController.hidesBottomBarWhenPushed = false - } - } - super.pushViewController(viewController, animated: true) + override public func pushViewController(_ viewController: UIViewController, animated: Bool) { + if children.count > 0 { + viewController.hidesBottomBarWhenPushed = true + if children.count > 1 { + viewController.hidesBottomBarWhenPushed = false } + } + super.pushViewController(viewController, animated: true) + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Base/BaseViewController/ChatTableViewController.swift b/NEChatUIKit/NEKitChatUI/Classes/Base/BaseViewController/ChatTableViewController.swift index c8063cb8..aa14a49b 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Base/BaseViewController/ChatTableViewController.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Base/BaseViewController/ChatTableViewController.swift @@ -1,65 +1,67 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCore -public class ChatTableViewController: NEBaseViewController,UITableViewDelegate, UITableViewDataSource { - - public var tableView: UITableView = UITableView(frame: .zero, style: .grouped) - public var topConstraint: NSLayoutConstraint? - public var bottomConstraint: NSLayoutConstraint? +public class ChatTableViewController: NEBaseViewController, UITableViewDelegate, + UITableViewDataSource { + public var tableView: UITableView = .init(frame: .zero, style: .grouped) + public var topConstraint: NSLayoutConstraint? + public var bottomConstraint: NSLayoutConstraint? - public override func viewDidLoad() { - super.viewDidLoad() - self.tableView.separatorStyle = .none - self.tableView.delegate = self - self.tableView.dataSource = self - self.tableView.translatesAutoresizingMaskIntoConstraints = false - self.view.addSubview(self.tableView) - NSLayoutConstraint.activate([ - self.tableView.leftAnchor.constraint(equalTo: self.view.leftAnchor), - self.tableView.rightAnchor.constraint(equalTo: self.view.rightAnchor), - ]) - - if #available(iOS 11.0, *) { - self.topConstraint = self.tableView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor, constant: 0) - self.bottomConstraint = self.tableView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor) + override public func viewDidLoad() { + super.viewDidLoad() + tableView.separatorStyle = .none + tableView.delegate = self + tableView.dataSource = self + tableView.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(tableView) + NSLayoutConstraint.activate([ + tableView.leftAnchor.constraint(equalTo: view.leftAnchor), + tableView.rightAnchor.constraint(equalTo: view.rightAnchor), + ]) - } else { - // Fallback on earlier versions - self.topConstraint = self.tableView.topAnchor.constraint(equalTo: self.view.topAnchor) - self.bottomConstraint = self.tableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor) + if #available(iOS 11.0, *) { + self.topConstraint = self.tableView.topAnchor.constraint( + equalTo: self.view.safeAreaLayoutGuide.topAnchor, + constant: 0 + ) + self.bottomConstraint = self.tableView.bottomAnchor + .constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor) - } - self.topConstraint?.isActive = true - self.bottomConstraint?.isActive = true - - self.tableView.sectionHeaderHeight = 38 - self.tableView.sectionFooterHeight = 0 - self.tableView.rowHeight = 62 - self.tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.1)) - + } else { + // Fallback on earlier versions + topConstraint = tableView.topAnchor.constraint(equalTo: view.topAnchor) + bottomConstraint = tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor) } - - public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - return tableView.dequeueReusableCell(withIdentifier:"UITableViewCell" , for: indexPath) - } - - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return 0 - } - + topConstraint?.isActive = true + bottomConstraint?.isActive = true - /* - // MARK: - Navigation + tableView.sectionHeaderHeight = 38 + tableView.sectionFooterHeight = 0 + tableView.rowHeight = 62 + tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.1)) + } - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. - } - */ + public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + tableView.dequeueReusableCell(withIdentifier: "UITableViewCell", for: indexPath) + } + + public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + 0 + } + + /* + // MARK: - Navigation + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/Controller/ChatViewController.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/Controller/ChatViewController.swift index f156c8e9..1e6e071e 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/Controller/ChatViewController.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/Controller/ChatViewController.swift @@ -1,6 +1,7 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCoreIM @@ -14,173 +15,195 @@ import NEKitCommonUI import WebKit @objcMembers -open class ChatViewController: NEBaseViewController, UINavigationControllerDelegate, ChatInputViewDelegate, ChatViewModelDelegate, NIMMediaManagerDelegate,MessageOperationViewDelegate, UIGestureRecognizerDelegate { - - private let tag = "ChatViewController" - public var viewmodel:ChatViewModel - private var inputViewTopConstraint: NSLayoutConstraint? - private var tableViewBottomConstraint: NSLayoutConstraint? - public var menuView: ChatInputView = ChatInputView() - public var operationView: MessageOperationView? - private var playingCell: ChatAudioCell? - private var atUsers = [NSRange]() - private var timer: Timer? - var replyView = ReplyView() - - var titleContent = "" - - public init(session: NIMSession) { - self.viewmodel = ChatViewModel(session: session, anchor: nil) - super.init(nibName: nil, bundle: nil) - self.viewmodel.delegate = self - IQKeyboardManager.shared.enable = false - IQKeyboardManager.shared.enableAutoToolbar = false - NIMSDK.shared().mediaManager.add(self) - NIMSDK.shared().mediaManager.setNeedProximityMonitor(viewmodel.getHandSetEnable()) - //注册自定义消息的解析器 - NIMCustomObject.registerCustomDecoder(CustomAttachmentDecoder()) - } - - - required public init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - open override func viewDidLoad() { - super.viewDidLoad() - commonUI() - addObseve() - loadData() - } - - open override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - navigationController?.isNavigationBarHidden = false - } - - open override func viewWillDisappear(_ animated: Bool) { - if NIMSDK.shared().mediaManager.isPlaying() { - NIMSDK.shared().mediaManager.stopPlay() - } - } - //MARK: 子类可重写方法 - //load data的时候会调用 - open func getSessionInfo(session: NIMSession) {} +open class ChatViewController: NEBaseViewController, UINavigationControllerDelegate, + ChatInputViewDelegate, ChatViewModelDelegate, NIMMediaManagerDelegate, + MessageOperationViewDelegate, UIGestureRecognizerDelegate,UITableViewDataSource, UITableViewDelegate { + private let tag = "ChatViewController" + public var viewmodel: ChatViewModel + private var inputViewTopConstraint: NSLayoutConstraint? + private var tableViewBottomConstraint: NSLayoutConstraint? + public var menuView: ChatInputView = .init() + public var operationView: MessageOperationView? + private var playingCell: ChatAudioCell? + private var atUsers = [NSRange]() + private var timer: Timer? + var replyView = ReplyView() - - /// 点击头像回调 - /// - Parameter model: cell模型 - open func didTapHeadPortrait(model:MessageContentModel?){ - - if let isOut = model?.message?.isOutgoingMsg, isOut { - Router.shared.use(MeSettingRouter, parameters: ["nav": navigationController as Any], closure: nil) - return - } - if let uid = model?.message?.from { - UserInfoProvider.shared.fetchUserInfo([uid]) {[weak self] error, users in - if let u = users?.first { - Router.shared.use(ContactUserInfoPageRouter, parameters: ["nav": self?.navigationController as Any, "user" : u], closure: nil) - } - } - } + var titleContent = "" + + public init(session: NIMSession) { + viewmodel = ChatViewModel(session: session, anchor: nil) + super.init(nibName: nil, bundle: nil) + viewmodel.delegate = self + IQKeyboardManager.shared.enable = false + IQKeyboardManager.shared.enableAutoToolbar = false + NIMSDK.shared().mediaManager.add(self) + NIMSDK.shared().mediaManager.setNeedProximityMonitor(viewmodel.getHandSetEnable()) + // 注册自定义消息的解析器 + NIMCustomObject.registerCustomDecoder(CustomAttachmentDecoder()) + } + + public required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override open func viewDidLoad() { + super.viewDidLoad() + commonUI() + addObseve() + loadData() + } + + override open func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + navigationController?.isNavigationBarHidden = false + } + + override open func viewWillDisappear(_ animated: Bool) { + if NIMSDK.shared().mediaManager.isPlaying() { + NIMSDK.shared().mediaManager.stopPlay() } - - /// 长按消息内容 - /// - Parameters: - /// - cell: 长按cell - /// - model: cell模型 - open func didLongTouchMessageView(_ cell: UITableViewCell, _ model: MessageContentModel?) { - operationView?.removeFromSuperview() - // get operations - guard let items = viewmodel.avalibleOperationsForMessage(model) else { - return - } - self.viewmodel.operationModel = model - + } + + // MARK: 子类可重写方法 + + // load data的时候会调用 + open func getSessionInfo(session: NIMSession) {} + + /// 点击头像回调 + /// - Parameter model: cell模型 + open func didTapHeadPortrait(model: MessageContentModel?) { + if let isOut = model?.message?.isOutgoingMsg, isOut { + Router.shared.use( + MeSettingRouter, + parameters: ["nav": navigationController as Any], + closure: nil + ) + return + } + if let uid = model?.message?.from { + UserInfoProvider.shared.fetchUserInfo([uid]) { [weak self] error, users in + if let u = users?.first { + Router.shared.use( + ContactUserInfoPageRouter, + parameters: ["nav": self?.navigationController as Any, "user": u], + closure: nil + ) + } + } + } + } + + /// 长按消息内容 + /// - Parameters: + /// - cell: 长按cell + /// - model: cell模型 + open func didLongTouchMessageView(_ cell: UITableViewCell, _ model: MessageContentModel?) { + operationView?.removeFromSuperview() + // get operations + guard let items = viewmodel.avalibleOperationsForMessage(model) else { + return + } + viewmodel.operationModel = model + // size - let w = items.count <= 5 ? 60.0 * Double(items.count) + 16.0 : 60.0 * 5 + 16.0 - let h = items.count <= 5 ? 56.0 + 16.0 : 56.0 * 2 + 16.0 - - if let index = self.tableView.indexPath(for: cell) { - let rectInTableView = self.tableView.rectForRow(at: index) - let rectInView = self.tableView.convert(rectInTableView, to: self.tableView.superview) - let topOffset = UIApplication.shared.statusBarFrame.size.height + self.navigationController!.navigationBar.frame.size.height - var operationY = 0.0 - if topOffset + h > rectInView.origin.y { + let w = items.count <= 5 ? 60.0 * Double(items.count) + 16.0 : 60.0 * 5 + 16.0 + let h = items.count <= 5 ? 56.0 + 16.0 : 56.0 * 2 + 16.0 + + if let index = tableView.indexPath(for: cell) { + let rectInTableView = tableView.rectForRow(at: index) + let rectInView = tableView.convert(rectInTableView, to: tableView.superview) + let topOffset = UIApplication.shared.statusBarFrame.size.height + navigationController! + .navigationBar.frame.size.height + var operationY = 0.0 + if topOffset + h > rectInView.origin.y { // under the cell - operationY = rectInView.origin.y + rectInView.size.height - }else { - operationY = rectInView.origin.y - h - - } - let frame = CGRect(x: 0, y: operationY, width: w, height: h) - operationView = MessageOperationView(frame: frame) - operationView!.delegate = self - operationView!.items = items - self.view.addSubview(operationView!) - } - } - - //MARK: lazy Method - private lazy var brokenNetworkView:ChatBrokenNetworkView = { - let view = ChatBrokenNetworkView.init(frame: CGRect.init(x: 0, y: kNavigationHeight + KStatusBarHeight, width: kScreenWidth, height: 36)) - return view - }() - - private lazy var tableView:UITableView = { - let tableView = UITableView.init(frame: .zero, style: .plain) - tableView.translatesAutoresizingMaskIntoConstraints = false - tableView.separatorStyle = .none - tableView.showsVerticalScrollIndicator = false - tableView.delegate = self - tableView.dataSource = self - tableView.backgroundColor = .white - tableView.mj_header = MJRefreshNormalHeader(refreshingTarget: self, refreshingAction: #selector(loadMoreData)) - tableView.keyboardDismissMode = .onDrag - return tableView - }() - - //MARK: UIGestureRecognizerDelegate - public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { + operationY = rectInView.origin.y + rectInView.size.height + } else { + operationY = rectInView.origin.y - h + } + let frame = CGRect(x: 0, y: operationY, width: w, height: h) + operationView = MessageOperationView(frame: frame) + operationView!.delegate = self + operationView!.items = items + view.addSubview(operationView!) + } + } + + // MARK: lazy Method + + private lazy var brokenNetworkView: ChatBrokenNetworkView = { + let view = + ChatBrokenNetworkView(frame: CGRect(x: 0, y: kNavigationHeight + KStatusBarHeight, + width: kScreenWidth, height: 36)) + return view + }() + + private lazy var tableView: UITableView = { + let tableView = UITableView(frame: .zero, style: .plain) + tableView.translatesAutoresizingMaskIntoConstraints = false + tableView.separatorStyle = .none + tableView.showsVerticalScrollIndicator = false + tableView.delegate = self + tableView.dataSource = self + tableView.backgroundColor = .white + tableView.mj_header = MJRefreshNormalHeader( + refreshingTarget: self, + refreshingAction: #selector(loadMoreData) + ) + tableView.keyboardDismissMode = .onDrag + return tableView + }() + + // MARK: UIGestureRecognizerDelegate + + public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, + shouldReceive touch: UITouch) -> Bool { // print("touch.view:\(touch.view)") - guard let view = touch.view else { - return true - } - if view.bounds.size.width == 60 { - return false - } - // 点击重发按钮 - //点击撤回重新编辑按钮 - if view.isKind(of: UIButton.self) { - return false - } - if view.isKind(of: UIImageView.self) { - return false - } - return true + guard let view = touch.view else { + return true } - - public func remoteUserEditing() { - title = "正在输入中..." - trigerEndTimer() - } - - public func remoteUserEndEditing() { - title = titleContent + if view.bounds.size.width == 60 { + return false } - - @objc func timeoutEndEditing(){ - remoteUserEndEditing() + // 点击重发按钮 + // 点击撤回重新编辑按钮 + if view.isKind(of: UIButton.self) { + return false } - - func trigerEndTimer(){ - if let t = timer, t.isValid == true { - t.invalidate() - timer = nil - } - timer = Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(timeoutEndEditing), userInfo: nil, repeats: false) + if view.isKind(of: UIImageView.self) { + return false } - + return true + } + + public func remoteUserEditing() { + title = "正在输入中..." + trigerEndTimer() + } + + public func remoteUserEndEditing() { + title = titleContent + } + + func timeoutEndEditing() { + remoteUserEndEditing() + } + + func trigerEndTimer() { + if let t = timer, t.isValid == true { + t.invalidate() + timer = nil + } + timer = Timer.scheduledTimer( + timeInterval: 3, + target: self, + selector: #selector(timeoutEndEditing), + userInfo: nil, + repeats: false + ) + } + // public override func touchesBegan(_ touches: Set, with event: UIEvent?) { // self.operationView?.removeFromSuperview() // if self.menuView.textField.isFirstResponder { @@ -189,1188 +212,1255 @@ open class ChatViewController: NEBaseViewController, UINavigationControllerDeleg // self.layoutInputView(offset: 0) // } // } + + deinit { + print("will deinit") + } - deinit { - print("will deinit") - - } + + //MARK: objc 方法 + @objc func toSetting() { + if viewmodel.session.sessionType == .team { + Router.shared.use( + TeamSettingViewRouter, + parameters: ["nav": navigationController as Any, + "teamid": viewmodel.session.sessionId], + closure: nil + ) + } else if viewmodel.session.sessionType == .P2P { + let userSetting = UserSettingViewController() + userSetting.userId = viewmodel.session.sessionId + navigationController?.pushViewController(userSetting, animated: true) + } + } + //MARK: private 方法 + open func commonUI() { + title = viewmodel.session.sessionId + view.addSubview(tableView) + tableViewBottomConstraint = tableView.bottomAnchor.constraint( + equalTo: view.bottomAnchor, + constant: -100 + ) + tableViewBottomConstraint?.isActive = true + NSLayoutConstraint.activate([ + tableView.topAnchor.constraint( + equalTo: view.topAnchor, + constant: kNavigationHeight + KStatusBarHeight + ), + tableView.leftAnchor.constraint(equalTo: view.leftAnchor), + tableView.rightAnchor.constraint(equalTo: view.rightAnchor), + ]) + tableView.register( + ChatTimeTableViewCell.self, + forCellReuseIdentifier: "\(ChatTimeTableViewCell.self)" + ) -} + tableView.register( + ChatBaseLeftCell.self, + forCellReuseIdentifier: "\(ChatBaseLeftCell.self)" + ) + tableView.register( + ChatBaseRightCell.self, + forCellReuseIdentifier: "\(ChatBaseRightCell.self)" + ) + tableView.register( + ChatTextRightCell.self, + forCellReuseIdentifier: "\(ChatTextRightCell.self)" + ) + tableView.register( + ChatTextLeftCell.self, + forCellReuseIdentifier: "\(ChatTextLeftCell.self)" + ) + tableView.register( + ChatAudioLeftCell.self, + forCellReuseIdentifier: "\(ChatAudioLeftCell.self)" + ) + tableView.register( + ChatAudioRightCell.self, + forCellReuseIdentifier: "\(ChatAudioRightCell.self)" + ) + tableView.register( + ChatImageLeftCell.self, + forCellReuseIdentifier: "\(ChatImageLeftCell.self)" + ) + tableView.register( + ChatImageRightCell.self, + forCellReuseIdentifier: "\(ChatImageRightCell.self)" + ) -//MARK: ChatBaseCellDelegate + tableView.register( + ChatRevokeLeftCell.self, + forCellReuseIdentifier: "\(ChatRevokeLeftCell.self)" + ) + tableView.register( + ChatRevokeRightCell.self, + forCellReuseIdentifier: "\(ChatRevokeRightCell.self)" + ) -extension ChatViewController: ChatBaseCellDelegate { + tableView.register( + ChatVideoLeftCell.self, + forCellReuseIdentifier: "\(ChatVideoLeftCell.self)" + ) + tableView.register( + ChatVideoRightCell.self, + forCellReuseIdentifier: "\(ChatVideoRightCell.self)" + ) - func didTapAvatarView(_ cell: UITableViewCell, _ model: MessageContentModel?) { - didTapHeadPortrait(model: model) - } - - func didTapMessageView(_ cell: UITableViewCell, _ model: MessageContentModel?) { - if model?.type == .audio { - if let audio = model?.message?.messageObject as? NIMAudioObject { - self.startPlay(cell: cell as? ChatAudioCell, audio: audio) - } - }else if model?.type == .image { - if let imageObject = model?.message?.messageObject as? NIMImageObject { - var imageUrl = "" - - if let url = imageObject.url { - imageUrl = url - }else { - if let path = imageObject.path, FileManager.default.fileExists(atPath: path) { - imageUrl = path - } - } - if imageUrl.count > 0 { - let showController = PhotoBrowserController(urls: viewmodel.getUrls(), url: imageUrl) - showController.modalPresentationStyle = .overFullScreen - self.present(showController, animated: false, completion: nil) - } - -// if let url = imageObject.url { -// let showController = PhotoBrowserController(urls: viewmodel.getUrls(), url: url) -// showController.modalPresentationStyle = .overFullScreen -// self.present(showController, animated: false, completion: nil) -// } - } + tableView.register( + ChatReplyRightCell.self, + forCellReuseIdentifier: "\(ChatReplyRightCell.self)" + ) + tableView.register( + ChatReplyLeftCell.self, + forCellReuseIdentifier: "\(ChatReplyLeftCell.self)" + ) - }else if model?.type == .video, let object = model?.message?.messageObject as? NIMVideoObject { - print("video click") - weak var weakSelf = self - let videoPlayer = VideoPlayerViewController() - videoPlayer.modalPresentationStyle = .overFullScreen - if let path = object.path, FileManager.default.fileExists(atPath: path) == true { - let url = URL(fileURLWithPath: path) - videoPlayer.videoUrl = url - videoPlayer.totalTime = object.duration - print("video url : ", videoPlayer.videoUrl as Any) - present(videoPlayer, animated: true, completion: nil) - }else if let urlString = object.url, let path = object.path, let videoModel = model as? MessageVideoModel { - print("fetch message attachment") - - videoModel.state = .Downalod - if let left = cell as? ChatVideoLeftCell { - left.setModel(videoModel) - }else if let right = cell as? ChatVideoRightCell { - right.setModel(videoModel) - } - - viewmodel.downLoad(urlString, path) { progress in - videoModel.progress = progress - if progress >= 1.0 { - videoModel.state = .Success - } - videoModel.cell?.uploadProgress(progress) - } _: { error in - if let err = error as NSError? { - weakSelf?.showToast(err.localizedDescription) - } - } - } - }else if model?.type == .text { -// location at replied message - if model?.replyedModel != nil { - if model?.message?.repliedMessageId != nil { - var index = -1 - for (i, m) in self.viewmodel.messages.enumerated() { - if model?.message?.repliedMessageServerId == m.message?.serverID { - index = i - break - } - } - if index >= 0 { - self.tableView.scrollToRow(at: IndexPath(row: index, section: 0), at: .middle, animated: true) - } - } - } - }else { - print("else") - } - } - - func didLongPressMessageView(_ cell: UITableViewCell, _ model: MessageContentModel?) { - didLongTouchMessageView(cell, model) - } - - func didTapResendView(_ cell: UITableViewCell, _ model: MessageContentModel?) { - if let msg = model?.message { - viewmodel.resendMessage(message: msg) - } - } - - func didTapReeditButton(_ cell: UITableViewCell, _ model: MessageContentModel?) { - if model?.type == .revoke, model?.message?.messageType == .text { - self.menuView.textField.text = model?.message?.text - self.menuView.textField.becomeFirstResponder() - } - } - - func didTapReadView(_ cell: UITableViewCell, _ model: MessageContentModel?) { - if let msg = model?.message, msg.session?.sessionType == .team { - let readVC = ReadViewController(message: msg) - self.navigationController?.pushViewController(readVC, animated: true) + menuView.translatesAutoresizingMaskIntoConstraints = false + menuView.delegate = self + view.addSubview(menuView) + + inputViewTopConstraint = menuView.topAnchor.constraint( + equalTo: view.bottomAnchor, + constant: -100 + ) + NSLayoutConstraint.activate([ + menuView.leftAnchor.constraint(equalTo: view.leftAnchor), + menuView.rightAnchor.constraint(equalTo: view.rightAnchor), + menuView.heightAnchor.constraint(equalToConstant: 304), + ]) + inputViewTopConstraint?.isActive = true + + weak var weakSelf = self + NEChatDetectNetworkTool.shareInstance.netWorkReachability { status in + if status == .notReachable, let networkView = weakSelf?.brokenNetworkView { + weakSelf?.view.addSubview(networkView) + } else { + weakSelf?.brokenNetworkView.removeFromSuperview() } + } + addRightAction(UIImage.ne_imageNamed(name: "three_point"), #selector(toSetting), self) } -} -//MARK: UITableViewDataSource,UITableViewDelegate -extension ChatViewController:UITableViewDataSource,UITableViewDelegate { - - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return viewmodel.messages.count ?? 0 - } - - public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let model = viewmodel.messages[indexPath.row] - var reuseId = "" - if let isSend = model.message?.isOutgoingMsg, isSend { - if model.replyedModel != nil { - reuseId = "\(ChatReplyRightCell.self)" - }else { - switch model.type { - case .text: - reuseId = "\(ChatTextRightCell.self)" - case .image: - reuseId = "\(ChatImageRightCell.self)" - case .audio: - reuseId = "\(ChatAudioRightCell.self)" - case .video: - reuseId = "\(ChatVideoRightCell.self)" - case .time, .tip, .notification: - reuseId = "\(ChatTimeTableViewCell.self)" - case .revoke: - reuseId = "\(ChatRevokeRightCell.self)" - default: - reuseId = "\(ChatBaseRightCell.self)" - } - } - - let cell = tableView.dequeueReusableCell(withIdentifier: reuseId, for: indexPath) - if let c = cell as? ChatTimeTableViewCell { - if let m = model as? MessageTipsModel { - c.setModel(m) - } - return c - }else if let c = cell as? ChatBaseRightCell { - c.delegate = self - if let m = model as? MessageContentModel { - c.setModel(m) - } - return c - }else { - return ChatBaseRightCell() + func loadData() { + // title + getSessionInfo(session: viewmodel.session) + weak var weakSelf = self + + viewmodel.queryRoamMsgHasMoreTime_v2 { error, historyEnd, newEnd, models, index in + if let ms = models, ms.count > 0 { + if let messages = weakSelf?.viewmodel.messages { + for index in 0 ..< messages.count { + let message = messages[index] + if message.message?.messageId == weakSelf?.viewmodel.anchor?.messageId { + print("messages real index : ", index) + print("messages text : ", message.message?.text as Any) + } } - }else { - if model.replyedModel != nil { - reuseId = "\(ChatReplyLeftCell.self)" - }else { - switch model.type { - case .text: - reuseId = "\(ChatTextLeftCell.self)" - case .image: - reuseId = "\(ChatImageLeftCell.self)" - case .audio: - reuseId = "\(ChatAudioLeftCell.self)" - case .video: - reuseId = "\(ChatVideoLeftCell.self)" - case .time, .tip, .notification: - reuseId = "\(ChatTimeTableViewCell.self)" - case .revoke: - reuseId = "\(ChatRevokeLeftCell.self)" - default: - reuseId = "\(ChatBaseLeftCell.self)" - } + } + weakSelf?.tableView.reloadData() + if weakSelf?.viewmodel.isHistoryChat == true { + let indexPath = IndexPath(row: index, section: 0) + print("queryRoamMsgHasMoreTime_v2 index : ", index) + weakSelf?.tableView.scrollToRow(at: indexPath, at: .none, animated: false) + if newEnd <= 0 { + weakSelf?.addBottomLoadMore() } - - let cell = tableView.dequeueReusableCell(withIdentifier: reuseId, for: indexPath) - if let c = cell as? ChatTimeTableViewCell { - if let m = model as? MessageTipsModel { - c.setModel(m) - } - return c - }else if let c = cell as? ChatBaseLeftCell { - c.delegate = self - if let m = model as? MessageContentModel { - c.setModel(m) - } - return c - }else { - return ChatBaseLeftCell() + } else { + if let tempArray = weakSelf?.viewmodel.messages, tempArray.count > 0 { + weakSelf?.tableView.reloadData() + weakSelf?.tableView.scrollToRow( + at: IndexPath(row: tempArray.count - 1, section: 0), + at: .bottom, + animated: false + ) } + } + + } else if let err = error { + weakSelf?.showToast(err.localizedDescription) } - } - - public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - print("did select row ") - self.operationView?.removeFromSuperview() - if self.menuView.textField.isFirstResponder { - self.menuView.textField.resignFirstResponder() - }else { - self.layoutInputView(offset: 0) - } - } + } - public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - let m = viewmodel.messages[indexPath.row]; - print("text:\(m.message?.text) height:\(m.height)") - return CGFloat(m.height) + // if viewmodel.isHistoryChat == false { + // viewmodel.getMessageHistory({[weak self] error,isEmpty,messages in + // if let err = error { + // NELog.errorLog(self?.tag ?? "ChatViewController", desc: "❌getMessageHistory error, error:\(err)") + // }else { + // if let tempArray = weakSelf?.viewmodel.messages,tempArray.count > 0 { + // weakSelf?.tableView.reloadData() + // weakSelf?.tableView.scrollToRow(at: IndexPath(row: tempArray.count - 1, section: 0), at: .bottom, animated: false) + // } + // } + // }) + // }else { + // print("queryRoamMsgHasMoreTime") + // viewmodel.queryRoamMsgHasMoreTime_v2 { error, historyEnd, newEnd, models, index in + // if let ms = models, ms.count > 0 { + // if let messages = weakSelf?.viewmodel.messages { + // for index in 0.. 0 { - if let messages = weakSelf?.viewmodel.messages { - for index in 0.. 0 { - weakSelf?.tableView.reloadData() - weakSelf?.tableView.scrollToRow(at: IndexPath(row: tempArray.count - 1, section: 0), at: .bottom, animated: false) - } - } - - }else if let err = error { - weakSelf?.showToast(err.localizedDescription) - } - } - - -// if viewmodel.isHistoryChat == false { -// viewmodel.getMessageHistory({[weak self] error,isEmpty,messages in -// if let err = error { -// NELog.errorLog(self?.tag ?? "ChatViewController", desc: "❌getMessageHistory error, error:\(err)") -// }else { -// if let tempArray = weakSelf?.viewmodel.messages,tempArray.count > 0 { -// weakSelf?.tableView.reloadData() -// weakSelf?.tableView.scrollToRow(at: IndexPath(row: tempArray.count - 1, section: 0), at: .bottom, animated: false) -// } -// } -// }) -// }else { -// print("queryRoamMsgHasMoreTime") -// viewmodel.queryRoamMsgHasMoreTime_v2 { error, historyEnd, newEnd, models, index in -// if let ms = models, ms.count > 0 { -// if let messages = weakSelf?.viewmodel.messages { -// for index in 0..0 { - weakSelf?.tableView.scrollToRow(at: IndexPath(row:count, section: 0), at: .top, animated: false) - } - weakSelf?.tableView.mj_header?.endRefreshing() - } + weakSelf?.tableView.reloadData() + if count > 0 { + weakSelf?.tableView.scrollToRow( + at: IndexPath(row: count, section: 0), + at: .top, + animated: false + ) + } + weakSelf?.tableView.mj_header?.endRefreshing() + } -// viewmodel.getMoreMessageHistory { error, isEmpty, messageFrames in -// weakSelf?.tableView.reloadData() -// weakSelf?.tableView.mj_header?.endRefreshing() -// } - } - - @objc func loadFartherToNowData(){ - + // viewmodel.getMoreMessageHistory { error, isEmpty, messageFrames in + // weakSelf?.tableView.reloadData() + // weakSelf?.tableView.mj_header?.endRefreshing() + // } } - - @objc func loadCloserToNowData(){ - weak var weakSelf = self - viewmodel.pullRemoteRefresh { error, end, datas in - if end > 0 { - weakSelf?.removeBottomLoadMore() - }else { - weakSelf?.tableView.mj_footer?.endRefreshing() - weakSelf?.tableView.reloadData() - } + + @objc func loadFartherToNowData() {} + + @objc func loadCloserToNowData() { + weak var weakSelf = self + viewmodel.pullRemoteRefresh { error, end, datas in + if end > 0 { + weakSelf?.removeBottomLoadMore() + } else { + weakSelf?.tableView.mj_footer?.endRefreshing() + weakSelf?.tableView.reloadData() } + } } - - - + func addObseve() { - NotificationCenter.default.addObserver(self, - selector: #selector(keyBoardWillShow(_ :)), - name: UIResponder.keyboardWillShowNotification, - object: nil) - - NotificationCenter.default.addObserver(self, - selector: #selector(keyBoardWillHide(_ :)), - name: UIResponder.keyboardWillHideNotification, - object: nil) -// let tap = UITapGestureRecognizer(target: self, action: #selector(viewTap)) -// tap.delegate = self -// self.view.addGestureRecognizer(tap) + NotificationCenter.default.addObserver(self, + selector: #selector(keyBoardWillShow(_:)), + name: UIResponder.keyboardWillShowNotification, + object: nil) + + NotificationCenter.default.addObserver(self, + selector: #selector(keyBoardWillHide(_:)), + name: UIResponder.keyboardWillHideNotification, + object: nil) + // let tap = UITapGestureRecognizer(target: self, action: #selector(viewTap)) + // tap.delegate = self + // self.view.addGestureRecognizer(tap) } - - func addBottomLoadMore(){ - tableView.mj_footer = MJRefreshBackNormalFooter(refreshingTarget: self, refreshingAction: #selector(loadCloserToNowData)) + + func addBottomLoadMore() { + tableView.mj_footer = MJRefreshBackNormalFooter( + refreshingTarget: self, + refreshingAction: #selector(loadCloserToNowData) + ) } - - func removeBottomLoadMore(){ - tableView.mj_footer?.endRefreshingWithNoMoreData() - tableView.mj_footer = nil - viewmodel.isHistoryChat = false //转为普通聊天页面 + + func removeBottomLoadMore() { + tableView.mj_footer?.endRefreshingWithNoMoreData() + tableView.mj_footer = nil + viewmodel.isHistoryChat = false // 转为普通聊天页面 } - - -// MARK:键盘通知相关操作 - @objc func keyBoardWillShow(_ notification:Notification) { - if self.menuView.currentType != .text { - return - } - let keyboardRect = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue - self.layoutInputView(offset: keyboardRect.size.height) - - UIView.animate(withDuration: 0.25, animations: { - self.view.layoutIfNeeded() - }) - self.scrollTableViewToBottom() - } - - @objc func keyBoardWillHide(_ notification:Notification) { - if self.menuView.currentType != .text { - return - } - if operationView?.superview != nil { - operationView?.removeFromSuperview() - } - self.layoutInputView(offset: 0) - self.scrollTableViewToBottom() + // MARK: 键盘通知相关操作 + + @objc func keyBoardWillShow(_ notification: Notification) { + if menuView.currentType != .text { + return + } + let keyboardRect = (notification + .userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue + layoutInputView(offset: keyboardRect.size.height) + + UIView.animate(withDuration: 0.25, animations: { + self.view.layoutIfNeeded() + }) + scrollTableViewToBottom() } - + + @objc func keyBoardWillHide(_ notification: Notification) { + if menuView.currentType != .text { + return + } + if operationView?.superview != nil { + operationView?.removeFromSuperview() + } + layoutInputView(offset: 0) + scrollTableViewToBottom() + } + private func scrollTableViewToBottom() { - print("self.viewmodel.messages.count\(self.viewmodel.messages.count)") - print("self.tableView.numberOfRows(inSection: 0)\(self.tableView.numberOfRows(inSection: 0))") - if self.viewmodel.messages.count > 0 { - let indexPath = IndexPath(row: self.viewmodel.messages.count - 1, section: 0) - self.tableView.scrollToRow(at: indexPath, at: .bottom, animated: true) - } + print("self.viewmodel.messages.count\(viewmodel.messages.count)") + print("self.tableView.numberOfRows(inSection: 0)\(tableView.numberOfRows(inSection: 0))") + if viewmodel.messages.count > 0 { + let indexPath = IndexPath(row: viewmodel.messages.count - 1, section: 0) + tableView.scrollToRow(at: indexPath, at: .bottom, animated: true) + } } - -// offset:value which from self.view.bottom to inputView.bottom + + // offset:value which from self.view.bottom to inputView.bottom private func layoutInputView(offset: CGFloat) { - self.inputViewTopConstraint?.constant = -100 - offset - self.tableViewBottomConstraint?.constant = -100 - offset - UIView.animate(withDuration: 0.25, animations: { - self.view.layoutIfNeeded() - }) + inputViewTopConstraint?.constant = -100 - offset + tableViewBottomConstraint?.constant = -100 - offset + UIView.animate(withDuration: 0.25, animations: { + self.view.layoutIfNeeded() + }) } -// MARK:ChatInputViewDelegate + // MARK: ChatInputViewDelegate + public func sendText(text: String?) { - guard let content = text, content.count > 0 else { - self.showToast(localizable("text_is_nil")) - return - } - if viewmodel.isReplying, let msg = self.viewmodel.operationModel?.message { - - viewmodel.replyMessage(MessageUtils.textMessage(text: content), msg) {[weak self] error in - if error != nil { - self?.view.makeToast(error?.localizedDescription) - }else { - self?.viewmodel.isReplying = false - self?.replyView.removeFromSuperview() - } + guard let content = text, content.count > 0 else { + showToast(localizable("text_is_nil")) + return + } + if viewmodel.isReplying, let msg = viewmodel.operationModel?.message { + viewmodel + .replyMessage(MessageUtils.textMessage(text: content), msg) { [weak self] error in + if error != nil { + self?.view.makeToast(error?.localizedDescription) + } else { + self?.viewmodel.isReplying = false + self?.replyView.removeFromSuperview() } - - }else { - viewmodel.sendTextMessage(text: content, {[weak self] error in - if error != nil { - self?.view.makeToast(error?.localizedDescription) - } - }) + } + + } else { + viewmodel.sendTextMessage(text: content) { [weak self] error in + if error != nil { + self?.view.makeToast(error?.localizedDescription) + } } + } } - + public func textChanged(text: String) -> Bool { - if text == "@" { - //做p2p类型判断 - if self.viewmodel.session.sessionType == .P2P { - return true - }else { - showUserSelectVC(text: text) - return false - } - - }else { - return true + if text == "@" { + // 做p2p类型判断 + if viewmodel.session.sessionType == .P2P { + return true + } else { + showUserSelectVC(text: text) + return false } + + } else { + return true + } } - + public func textDelete(range: NSRange, text: String) -> Bool { - var index = -1 - var removeRange: NSRange? - for (i, r) in atUsers.enumerated() { - let rightIndex = r.location + r.length - 1 - if rightIndex == range.location { - index = i - removeRange = r - break - } - } - if index >= 0 { - atUsers.remove(at: index) - if let text = self.menuView.textField.text { - self.menuView.textField.text = text.substring(to: text.index(text.startIndex, offsetBy: removeRange!.location)) - } - return false - } - return true + var index = -1 + var removeRange: NSRange? + for (i, r) in atUsers.enumerated() { + let rightIndex = r.location + r.length - 1 + if rightIndex == range.location { + index = i + removeRange = r + break + } + } + if index >= 0 { + atUsers.remove(at: index) + if let text = menuView.textField.text { + menuView.textField.text = text + .substring(to: text.index(text.startIndex, offsetBy: removeRange!.location)) + } + return false + } + return true } - - public func textFieldDidChange(_ textField: UITextView){ - if let text = textField.text { - if text.count > 0 { - viewmodel.sendInputTypingState() - }else { - viewmodel.sendInputTypingEndState() - } + + public func textFieldDidChange(_ textField: UITextView) { + if let text = textField.text { + if text.count > 0 { + viewmodel.sendInputTypingState() + } else { + viewmodel.sendInputTypingEndState() } + } } - - public func textFieldDidEndEditing(_ textField: UITextView){ - viewmodel.sendInputTypingEndState() + public func textFieldDidEndEditing(_ textField: UITextView) { + viewmodel.sendInputTypingEndState() } - - public func textFieldDidBeginEditing(_ textField: UITextView){ - if let count = textField.text?.count, count > 0 { - viewmodel.sendInputTypingState() - } + + public func textFieldDidBeginEditing(_ textField: UITextView) { + if let count = textField.text?.count, count > 0 { + viewmodel.sendInputTypingState() + } } - + public func willSelectItem(button: UIButton, index: Int) { - if index == 0 { - self.layoutInputView(offset: 204) - self.scrollTableViewToBottom() - }else if index == 1 { - self.layoutInputView(offset: 204) - self.scrollTableViewToBottom() - }else if index == 2 { -// showMenue(sourceView: view) - //showBottomAlert(self, false) - goPhotoAlbumWithVideo(self) - }else if index == 3 { - showBottomVideoAction(self, false) - }else { - self.showToast(localizable("open_soon")) - } + if index == 0 { + layoutInputView(offset: 204) + scrollTableViewToBottom() + } else if index == 1 { + layoutInputView(offset: 204) + scrollTableViewToBottom() + } else if index == 2 { + // showMenue(sourceView: view) + // showBottomAlert(self, false) + goPhotoAlbumWithVideo(self) + } else if index == 3 { + showBottomVideoAction(self, false) + } else { + showToast(localizable("open_soon")) + } } - + func showMenue(sourceView: UIView) { - let alert = UIAlertController(title: localizable("请选择"), message: nil, preferredStyle: .actionSheet) - alert.modalPresentationStyle = .popover - let camera = UIAlertAction(title: localizable("拍照"), style: .default) { action in - self.takePhoto() - } - let photo = UIAlertAction(title: localizable("从相册选择"), style: .default) { action in - self.willSelectImage() - } - - let cancel = UIAlertAction(title: "取消", style: .cancel) { action in - - } - - alert.addAction(camera) - alert.addAction(photo) - alert.addAction(cancel) - let popover = alert.popoverPresentationController - if popover != nil { - popover?.sourceView = sourceView - popover?.permittedArrowDirections = .any - } - self.present(alert, animated: true, completion: nil) + let alert = UIAlertController( + title: localizable("请选择"), + message: nil, + preferredStyle: .actionSheet + ) + alert.modalPresentationStyle = .popover + let camera = UIAlertAction(title: localizable("拍照"), style: .default) { action in + self.takePhoto() + } + let photo = UIAlertAction(title: localizable("从相册选择"), style: .default) { action in + self.willSelectImage() + } + + let cancel = UIAlertAction(title: "取消", style: .cancel) { action in + } + + alert.addAction(camera) + alert.addAction(photo) + alert.addAction(cancel) + let popover = alert.popoverPresentationController + if popover != nil { + popover?.sourceView = sourceView + popover?.permittedArrowDirections = .any + } + present(alert, animated: true, completion: nil) } - + func willSelectImage() { - let imagePickerVC = UIImagePickerController() - imagePickerVC.delegate = self - imagePickerVC.allowsEditing = false - imagePickerVC.sourceType = .photoLibrary - self.present(imagePickerVC, animated: true) { - } + let imagePickerVC = UIImagePickerController() + imagePickerVC.delegate = self + imagePickerVC.allowsEditing = false + imagePickerVC.sourceType = .photoLibrary + present(imagePickerVC, animated: true) {} } - + func takePhoto() { - let imagePickerVC = UIImagePickerController() - imagePickerVC.delegate = self - imagePickerVC.allowsEditing = false - imagePickerVC.sourceType = .camera - self.present(imagePickerVC, animated: true) { - } + let imagePickerVC = UIImagePickerController() + imagePickerVC.delegate = self + imagePickerVC.allowsEditing = false + imagePickerVC.sourceType = .camera + present(imagePickerVC, animated: true) {} } - -// MARK:UIImagePickerControllerDelegate - public func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { -// send message - - picker.dismiss(animated: true, completion: nil) - - - if let url = info[.mediaURL] as? URL { - // video - print("image picker video : url", url) -// NELog.infoLog("send video message", desc: error?.localizedDescription ?? "no error") - weak var weakSelf = self - viewmodel.sendVideoMessage(url: url) { error in - - if let err = error { - NELog.errorLog("send video message", desc: err.localizedDescription) - weakSelf?.showToast(err.localizedDescription) - } - } - return - } - - guard let image = info[.originalImage] as? UIImage else { - self.showToast(localizable("image_is_nil")) - return + + // MARK: UIImagePickerControllerDelegate + + public func imagePickerController(_ picker: UIImagePickerController, + didFinishPickingMediaWithInfo info: [UIImagePickerController + .InfoKey: Any]) { + // send message + + picker.dismiss(animated: true, completion: nil) + + if let url = info[.mediaURL] as? URL { + // video + print("image picker video : url", url) + // NELog.infoLog("send video message", desc: error?.localizedDescription ?? "no error") + weak var weakSelf = self + viewmodel.sendVideoMessage(url: url) { error in + + if let err = error { + NELog.errorLog("send video message", desc: err.localizedDescription) + weakSelf?.showToast(err.localizedDescription) + } } - viewmodel.sendImageMessage(image: image, {[weak self] error in - NELog.infoLog("send image message", desc: error?.localizedDescription ?? "no error") - if error != nil { - self?.view.makeToast(error?.localizedDescription) - }else { - - } - }) + return + } + + guard let image = info[.originalImage] as? UIImage else { + showToast(localizable("image_is_nil")) + return + } + viewmodel.sendImageMessage(image: image) { [weak self] error in + NELog.infoLog("send image message", desc: error?.localizedDescription ?? "no error") + if error != nil { + self?.view.makeToast(error?.localizedDescription) + } else {} + } } - -// MARK: ChatViewModelDelegate + + // MARK: ChatViewModelDelegate + public func onRecvMessages(_ messages: [NIMMessage]) { - insertRows() - self.viewmodel.markRead(messages: messages) { error in - print("mark read \(error?.localizedDescription)") - } + insertRows() + viewmodel.markRead(messages: messages) { error in + print("mark read \(error?.localizedDescription)") + } } - + public func willSend(_ message: NIMMessage) { - insertRows() - } - - public func send(_ message: NIMMessage, progress: Float) { - + insertRows() } - + + public func send(_ message: NIMMessage, progress: Float) {} + public func send(_ message: NIMMessage, didCompleteWithError error: Error?) { - if self.indexPathsWithMessags([message]).count > 0 { - self.tableViewReloadIndexs(self.indexPathsWithMessags([message])) - } + if indexPathsWithMessags([message]).count > 0 { + tableViewReloadIndexs(indexPathsWithMessags([message])) + } } - - private func indexPathsWithMessags(_ messages:[NIMMessage]) -> [IndexPath] { - var indexPaths = [IndexPath]() - for messageModel in messages { - for (i, model) in self.viewmodel.messages.enumerated() { - if model.message?.messageId == messageModel.messageId { - indexPaths.append(IndexPath(row: i, section: 0)) - } - } + + private func indexPathsWithMessags(_ messages: [NIMMessage]) -> [IndexPath] { + var indexPaths = [IndexPath]() + for messageModel in messages { + for (i, model) in viewmodel.messages.enumerated() { + if model.message?.messageId == messageModel.messageId { + indexPaths.append(IndexPath(row: i, section: 0)) + } } - return indexPaths + } + return indexPaths } - public func onDeleteMessage(_ message: NIMMessage, atIndexs: [IndexPath]) { - if atIndexs.isEmpty { - return - } -// self.tableView.reloadData() - tableViewDeleteIndexs(atIndexs) + if atIndexs.isEmpty { + return + } + // self.tableView.reloadData() + tableViewDeleteIndexs(atIndexs) } - + public func updateDownloadProgress(_ message: NIMMessage, atIndex: IndexPath, progress: Float) { - tableViewUpdateDownload(atIndex) + tableViewUpdateDownload(atIndex) } - + public func onRevokeMessage(_ message: NIMMessage, atIndexs: [IndexPath]) { - if atIndexs.isEmpty { - return - } - tableViewReloadIndexs(atIndexs) + if atIndexs.isEmpty { + return + } + tableViewReloadIndexs(atIndexs) } - + public func onAddMessagePin(_ message: NIMMessage, atIndexs: [IndexPath]) { - tableViewReloadIndexs(atIndexs) + tableViewReloadIndexs(atIndexs) } - + public func onRemoveMessagePin(_ message: NIMMessage, atIndexs: [IndexPath]) { - tableViewReloadIndexs(atIndexs) + tableViewReloadIndexs(atIndexs) } - - public func tableViewDeleteIndexs(_ indexs:[IndexPath]) { - self.tableView.beginUpdates() - self.tableView.deleteRows(at: indexs, with: .none) - self.tableView.endUpdates() + + public func tableViewDeleteIndexs(_ indexs: [IndexPath]) { + tableView.beginUpdates() + tableView.deleteRows(at: indexs, with: .none) + tableView.endUpdates() } - - public func tableViewReloadIndexs(_ indexs:[IndexPath]) { - self.tableView.beginUpdates() - self.tableView.reloadRows(at: indexs, with: .none) - self.tableView.endUpdates() + + public func tableViewReloadIndexs(_ indexs: [IndexPath]) { + tableView.beginUpdates() + tableView.reloadRows(at: indexs, with: .none) + tableView.endUpdates() } - + public func didReadedMessageIndexs() { - if let indexPaths = self.tableView.indexPathsForVisibleRows, indexPaths.count > 0 { - self.tableView.beginUpdates() - // self.tableView.reloadRows(at: indexs, with: .none) - self.tableView.reloadRows(at: indexPaths, with: .none) - self.tableView.endUpdates() - } - } - - public func tableViewUpdateDownload(_ index: IndexPath){ + if let indexPaths = tableView.indexPathsForVisibleRows, indexPaths.count > 0 { tableView.beginUpdates() - tableView.reloadRows(at: [index], with: .none) + // self.tableView.reloadRows(at: indexs, with: .none) + tableView.reloadRows(at: indexPaths, with: .none) tableView.endUpdates() + } } - - + + public func tableViewUpdateDownload(_ index: IndexPath) { + tableView.beginUpdates() + tableView.reloadRows(at: [index], with: .none) + tableView.endUpdates() + } + // record audio public func startRecord() { - let dur = 60.0 - if NEAuthManager.hasAudioAuthoriztion() { - NIMSDK.shared().mediaManager.record(forDuration: dur) - }else { - NEAuthManager.requestAudioAuthorization { granted in - if granted { - }else { - DispatchQueue.main.async { - self.showToast(localizable("没有麦克风权限")) - } - } + let dur = 60.0 + if NEAuthManager.hasAudioAuthoriztion() { + NIMSDK.shared().mediaManager.record(forDuration: dur) + } else { + NEAuthManager.requestAudioAuthorization { granted in + if granted { + } else { + DispatchQueue.main.async { + self.showToast(localizable("没有麦克风权限")) } + } } + } } - - public func moveOutView() { - - } - - public func moveInView() { - - } - + + public func moveOutView() {} + + public func moveInView() {} + public func endRecord(insideView: Bool) { - print("[record] stop:\(insideView)") - if insideView { -// send - NIMSDK.shared().mediaManager.stopRecord() - }else { -// cancel - NIMSDK.shared().mediaManager.cancelRecord() - } + print("[record] stop:\(insideView)") + if insideView { + // send + NIMSDK.shared().mediaManager.stopRecord() + } else { + // cancel + NIMSDK.shared().mediaManager.cancelRecord() + } } - - @objc func viewTap(tap:UITapGestureRecognizer) { - self.operationView?.removeFromSuperview() - if self.menuView.textField.isFirstResponder { - self.menuView.textField.resignFirstResponder() - }else { - self.layoutInputView(offset: 0) - } + + @objc func viewTap(tap: UITapGestureRecognizer) { + operationView?.removeFromSuperview() + if menuView.textField.isFirstResponder { + menuView.textField.resignFirstResponder() + } else { + layoutInputView(offset: 0) + } } - - //MARK: audio play + + // MARK: audio play + private func startPlay(cell: ChatAudioCell?, audio: NIMAudioObject) { - if cell?.isPlaying == true { - self.stopPlay() - }else { - self.stopPlay() - self.playingCell = cell - self.playingCell?.startAnimation() - if let url = audio.path { - NIMSDK.shared().mediaManager.switch(.speaker) - NIMSDK.shared().mediaManager.play(url) - } - } + if cell?.isPlaying == true { + stopPlay() + } else { + stopPlay() + playingCell = cell + playingCell?.startAnimation() + if let url = audio.path { + NIMSDK.shared().mediaManager.switch(.speaker) + NIMSDK.shared().mediaManager.play(url) + } + } } - + private func stopPlay() { - if NIMSDK.shared().mediaManager.isPlaying() { - self.playingCell?.startAnimation() - NIMSDK.shared().mediaManager.stopPlay() - } + if NIMSDK.shared().mediaManager.isPlaying() { + playingCell?.startAnimation() + NIMSDK.shared().mediaManager.stopPlay() + } } -// private func startPlay() { -// if NIMSDK.shared().mediaManager.isPlaying() { -// self.playingCell?.startAnimation() -// NIMSDK.shared().mediaManager.stopPlay() -// } -// } -// MARK: NIMMediaManagerDelegate -// play + // private func startPlay() { + // if NIMSDK.shared().mediaManager.isPlaying() { + // self.playingCell?.startAnimation() + // NIMSDK.shared().mediaManager.stopPlay() + // } + // } + + // MARK: NIMMediaManagerDelegate + + // play public func playAudio(_ filePath: String, didBeganWithError error: Error?) { - print(#function + "\(error)") - if let e = error { - self.showToast(e.localizedDescription) - // stop - self.playingCell?.stopAnimation() - } + print(#function + "\(error)") + if let e = error { + showToast(e.localizedDescription) + // stop + playingCell?.stopAnimation() + } } - + public func playAudio(_ filePath: String, didCompletedWithError error: Error?) { - print(#function + "\(error)") - if let e = error { - self.showToast(e.localizedDescription) - } - // stop - self.playingCell?.stopAnimation() + print(#function + "\(error)") + if let e = error { + showToast(e.localizedDescription) + } + // stop + playingCell?.stopAnimation() } - + public func stopPlayAudio(_ filePath: String, didCompletedWithError error: Error?) { - print(#function + "\(error)") - if let e = error { - self.showToast(e.localizedDescription) - } - self.playingCell?.stopAnimation() - } - - public func playAudio(_ filePath: String, progress value: Float) { + print(#function + "\(error)") + if let e = error { + showToast(e.localizedDescription) + } + playingCell?.stopAnimation() } - + + public func playAudio(_ filePath: String, progress value: Float) {} + public func playAudioInterruptionEnd() { - print(#function ) + print(#function) } - + public func playAudioInterruptionBegin() { - print(#function ) - //stop play - self.playingCell?.stopAnimation() + print(#function) + // stop play + playingCell?.stopAnimation() } - -// record - public func recordAudio(_ filePath: String?, didBeganWithError error: Error?) { - print("[record] sdk Began error:\(error)") + // record + public func recordAudio(_ filePath: String?, didBeganWithError error: Error?) { + print("[record] sdk Began error:\(error)") } - + public func recordAudio(_ filePath: String?, didCompletedWithError error: Error?) { - print("[record] sdk Completed error:\(error)") - self.menuView.stopRecordAnimation() - guard let fp = filePath else { - self.showToast(error?.localizedDescription ?? "") - return - } - let dur = recordDuration(filePath: fp) - - print("dur:\(dur)") - if dur > 1 { - self.viewmodel.sendAudioMessage(filePath: fp, { error in - if let e = error { - self.showToast(e.localizedDescription) - }else { - - } - }) - }else { - self.showToast(localizable("录音时间太短")) + print("[record] sdk Completed error:\(error)") + menuView.stopRecordAnimation() + guard let fp = filePath else { + showToast(error?.localizedDescription ?? "") + return + } + let dur = recordDuration(filePath: fp) + + print("dur:\(dur)") + if dur > 1 { + viewmodel.sendAudioMessage(filePath: fp) { error in + if let e = error { + self.showToast(e.localizedDescription) + } else {} } + } else { + showToast(localizable("录音时间太短")) + } } - + public func recordAudioDidCancelled() { - print("[record] sdk cancel") - } - - public func recordAudioProgress(_ currentTime: TimeInterval) { - + print("[record] sdk cancel") } + + public func recordAudioProgress(_ currentTime: TimeInterval) {} + public func recordAudioInterruptionBegin() { - print(#function ) + print(#function) } - -// MARK: Private Method + + // MARK: Private Method + private func recordDuration(filePath: String) -> Float64 { - let avAsset = AVURLAsset(url: URL(fileURLWithPath: filePath)) - return CMTimeGetSeconds(avAsset.duration) + let avAsset = AVURLAsset(url: URL(fileURLWithPath: filePath)) + return CMTimeGetSeconds(avAsset.duration) } private func insertRows() { - let oldRows = self.tableView.numberOfRows(inSection: 0) - if oldRows == 0 { - self.tableView.reloadData() - return - } - if oldRows == self.viewmodel.messages.count { - self.tableView.reloadData() - return - } - var indexs = [IndexPath]() - for (i, model) in self.viewmodel.messages.enumerated() { - if i >= oldRows { - indexs.append(IndexPath(row: i, section: 0)) - } - } - - print("oo indexs:\(indexs)") - print("oo:\(self.viewmodel.messages.count)") - if !indexs.isEmpty { - self.tableView.insertRows(at: indexs, with: .none) - tableView.scrollToRow(at: IndexPath(row: viewmodel.messages.count - 1, section: 0), at: .bottom, animated: false) - } + let oldRows = tableView.numberOfRows(inSection: 0) + if oldRows == 0 { + tableView.reloadData() + return + } + if oldRows == viewmodel.messages.count { + tableView.reloadData() + return + } + var indexs = [IndexPath]() + for (i, model) in viewmodel.messages.enumerated() { + if i >= oldRows { + indexs.append(IndexPath(row: i, section: 0)) + } + } + print("oo indexs:\(indexs)") + print("oo:\(viewmodel.messages.count)") + if !indexs.isEmpty { + tableView.insertRows(at: indexs, with: .none) + tableView.scrollToRow( + at: IndexPath(row: viewmodel.messages.count - 1, section: 0), + at: .bottom, + animated: false + ) + } } - + private func showUserSelectVC(text: String) { - let selectVC = SelectUserViewController(sessionId: self.viewmodel.session.sessionId) - selectVC.modalPresentationStyle = .formSheet - selectVC.selectedBlock = { [weak self] index, model in - var resultText = "" - var location = 0 - var length = 0 - if let t = self?.menuView.textField.text, t.count > 0 { - resultText = t - location = t.count - } - if index == 0 { - let addText = text + localizable("user_select_all") + " " - resultText = resultText + addText - length = addText.count - let range = NSRange(location: location, length: length) - self?.atUsers.append(range) - }else { - if let m = model { - let addText = text + m.atNameInTeam() + " " - resultText = resultText + addText - length = addText.count - let range = NSRange(location: location, length: length) - self?.atUsers.append(range) - } - } - self?.menuView.textField.text = resultText + let selectVC = SelectUserViewController(sessionId: viewmodel.session.sessionId) + selectVC.modalPresentationStyle = .formSheet + selectVC.selectedBlock = { [weak self] index, model in + var resultText = "" + var location = 0 + var length = 0 + if let t = self?.menuView.textField.text, t.count > 0 { + resultText = t + location = t.count } - self.present(selectVC, animated: true, completion: nil) + if index == 0 { + let addText = text + localizable("user_select_all") + " " + resultText = resultText + addText + length = addText.count + let range = NSRange(location: location, length: length) + self?.atUsers.append(range) + } else { + if let m = model { + let addText = text + m.atNameInTeam() + " " + resultText = resultText + addText + length = addText.count + let range = NSRange(location: location, length: length) + self?.atUsers.append(range) + } + } + self?.menuView.textField.text = resultText + } + present(selectVC, animated: true, completion: nil) } -// MARK: MessageOperationViewDelegate + // MARK: MessageOperationViewDelegate + public func didSelectedItem(item: OperationItem) { - switch item.type { - case .copy: - copyMessage() - case .delete: - deleteMessage() - case .reply: - showReplyMessageView() - case .recall: - recallMessage() - case .collection: - collectionMessage() - case .forward: - forwardMessage() - case .pin: - pinMessage() - case .removePin: - removePinMessage() - default: - doNothing() - } + switch item.type { + case .copy: + copyMessage() + case .delete: + deleteMessage() + case .reply: + showReplyMessageView() + case .recall: + recallMessage() + case .collection: + collectionMessage() + case .forward: + forwardMessage() + case .pin: + pinMessage() + case .removePin: + removePinMessage() + default: + doNothing() + } } - - private func doNothing() { - - } - + + private func doNothing() {} + private func copyMessage() { - if let model = viewmodel.operationModel as? MessageTextModel, let text = model.attributeStr { - let pasteboard = UIPasteboard.general - pasteboard.string = text.string - self.showToast(localizable("copy_success")) - } + if let model = viewmodel.operationModel as? MessageTextModel, + let text = model.attributeStr { + let pasteboard = UIPasteboard.general + pasteboard.string = text.string + showToast(localizable("copy_success")) + } } - + private func deleteMessage() { - self.showAlert(message: localizable("message_delete_comfirm")) { - if let message = self.viewmodel.operationModel?.message { - self.viewmodel.deleteMessage(message: message) - } + showAlert(message: localizable("message_delete_comfirm")) { + if let message = self.viewmodel.operationModel?.message { + self.viewmodel.deleteMessage(message: message) } + } } - + private func showReplyMessageView() { - viewmodel.isReplying = true - self.view.addSubview(self.replyView) - self.replyView.closeButton.addTarget(self, action: #selector(cancelReply), for: .touchUpInside) - self.replyView.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - self.replyView.leadingAnchor.constraint(equalTo: self.menuView.leadingAnchor), - self.replyView.trailingAnchor.constraint(equalTo: self.menuView.trailingAnchor), - self.replyView.bottomAnchor.constraint(equalTo: self.menuView.topAnchor), - self.replyView.heightAnchor.constraint(equalToConstant: 36) - ]) - if let message = viewmodel.operationModel?.message { - var text = localizable("msg_reply") - if let name = viewmodel.operationModel?.shortName { - text = text + name - } - text = text + ":" - switch message.messageType { - case .text: - if let t = message.text { - text = text + t - } - case .image: - text = text + localizable("msg_image") - case .audio: - text = text + localizable("msg_audio") - case .video: - text = text + localizable("msg_video") - default: - text = text + "" - } - self.replyView.textLabel.text = text + viewmodel.isReplying = true + view.addSubview(replyView) + replyView.closeButton.addTarget(self, action: #selector(cancelReply), for: .touchUpInside) + replyView.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + replyView.leadingAnchor.constraint(equalTo: menuView.leadingAnchor), + replyView.trailingAnchor.constraint(equalTo: menuView.trailingAnchor), + replyView.bottomAnchor.constraint(equalTo: menuView.topAnchor), + replyView.heightAnchor.constraint(equalToConstant: 36), + ]) + if let message = viewmodel.operationModel?.message { + var text = localizable("msg_reply") + if let name = viewmodel.operationModel?.shortName { + text = text + name + } + text = text + ":" + switch message.messageType { + case .text: + if let t = message.text { + text = text + t + } + case .image: + text = text + localizable("msg_image") + case .audio: + text = text + localizable("msg_audio") + case .video: + text = text + localizable("msg_video") + default: + text = text + "" } + replyView.textLabel.text = text + } } - - @objc private func cancelReply(button: UIButton) { - self.replyView.removeFromSuperview() - self.viewmodel.isReplying = false + + @objc private func cancelReply(button: UIButton) { + replyView.removeFromSuperview() + viewmodel.isReplying = false } - + private func recallMessage() { - self.showAlert(message: localizable("message_revoke_confim")) { - if let message = self.viewmodel.operationModel?.message { - self.viewmodel.revokeMessage(message: message) { error in - if error != nil { - self.showToast(error!.localizedDescription) - }else { - // 自己撤回成功 & 收到对方撤回 都会走回调方法 onRevokeMessage - // 撤回成功的逻辑统一在代理方法中处理 onRevokeMessage - } - } + showAlert(message: localizable("message_revoke_confim")) { + if let message = self.viewmodel.operationModel?.message { + self.viewmodel.revokeMessage(message: message) { error in + if error != nil { + self.showToast(error!.localizedDescription) + } else { + // 自己撤回成功 & 收到对方撤回 都会走回调方法 onRevokeMessage + // 撤回成功的逻辑统一在代理方法中处理 onRevokeMessage } + } } - + } } - + private func collectionMessage() { - if let message = viewmodel.operationModel?.message { - viewmodel.addColletion(message) { error, info in - if error != nil { - self.showToast(error!.localizedDescription) - }else { - self.showToast(localizable("collection_success")) - } - } + if let message = viewmodel.operationModel?.message { + viewmodel.addColletion(message) { error, info in + if error != nil { + self.showToast(error!.localizedDescription) + } else { + self.showToast(localizable("collection_success")) + } } + } } - + private func forwardMessage() { - if let message = viewmodel.operationModel?.message { - weak var weakSelf = self - let userAction = UIAlertAction(title: localizable("contact_user"), style: .default) { action in - - Router.shared.register(ContactSelectedUsersRouter) { param in - print("user setting accids : ", param) - var items = [ForwardItem]() - - - if let users = param["im_user"] as? [NIMUser] { - users.forEach { user in - let item = ForwardItem() - item.uid = user.userId - item.avatar = user.userInfo?.avatarUrl - item.name = user.userInfo?.nickName - items.append(item) - } - - let forwardAlert = ForwardAlertViewController() - forwardAlert.setItems(items) - if let senderName = message.senderName{ - forwardAlert.context = senderName - } - weakSelf?.addChild(forwardAlert) - weakSelf?.view.addSubview(forwardAlert.view) - - forwardAlert.sureBlock = { - print("sure click ") - weakSelf?.viewmodel.forwardUserMessage(message, users) - } - } - - - } - var param = [String: Any]() - param["nav"] = weakSelf?.navigationController as Any - param["limit"] = 6 - if let session = weakSelf?.viewmodel.session, session.sessionType == .P2P { - var filters = Set() - filters.insert(session.sessionId) - param["filters"] = filters - } - Router.shared.use(ContactUserSelectRouter, parameters: param, closure: nil) + if let message = viewmodel.operationModel?.message { + weak var weakSelf = self + let userAction = UIAlertAction(title: localizable("contact_user"), + style: .default) { action in + Router.shared.register(ContactSelectedUsersRouter) { param in + print("user setting accids : ", param) + var items = [ForwardItem]() + + if let users = param["im_user"] as? [NIMUser] { + users.forEach { user in + let item = ForwardItem() + item.uid = user.userId + item.avatar = user.userInfo?.avatarUrl + item.name = user.userInfo?.nickName + items.append(item) + } + + let forwardAlert = ForwardAlertViewController() + forwardAlert.setItems(items) + if let senderName = message.senderName { + forwardAlert.context = senderName + } + weakSelf?.addChild(forwardAlert) + weakSelf?.view.addSubview(forwardAlert.view) + + forwardAlert.sureBlock = { + print("sure click ") + weakSelf?.viewmodel.forwardUserMessage(message, users) + } } - - let teamAction = UIAlertAction(title: localizable("team"), style: .default) { action in - - Router.shared.register(ContactTeamDataRouter) { param in - if let team = param["team"] as? NIMTeam { - let item = ForwardItem() - item.avatar = team.avatarUrl - item.name = team.getShowName() - item.uid = team.teamId - - let forwardAlert = ForwardAlertViewController() - forwardAlert.setItems([item]) - if let senderName = message.senderName{ - forwardAlert.context = senderName - } - weakSelf?.addChild(forwardAlert) - weakSelf?.view.addSubview(forwardAlert.view) - weakSelf?.viewmodel.forwardTeamMessage(message, team) - } - } - - Router.shared.use(ContactTeamListRouter, parameters: ["nav": weakSelf?.navigationController as Any], closure: nil) - } - - let cancelAction = UIAlertAction(title: localizable("cancel"), style: .cancel) { action in - + } + var param = [String: Any]() + param["nav"] = weakSelf?.navigationController as Any + param["limit"] = 6 + if let session = weakSelf?.viewmodel.session, session.sessionType == .P2P { + var filters = Set() + filters.insert(session.sessionId) + param["filters"] = filters + } + Router.shared.use(ContactUserSelectRouter, parameters: param, closure: nil) + } + + let teamAction = UIAlertAction(title: localizable("team"), style: .default) { action in + + Router.shared.register(ContactTeamDataRouter) { param in + if let team = param["team"] as? NIMTeam { + let item = ForwardItem() + item.avatar = team.avatarUrl + item.name = team.getShowName() + item.uid = team.teamId + + let forwardAlert = ForwardAlertViewController() + forwardAlert.setItems([item]) + if let senderName = message.senderName { + forwardAlert.context = senderName + } + weakSelf?.addChild(forwardAlert) + weakSelf?.view.addSubview(forwardAlert.view) + weakSelf?.viewmodel.forwardTeamMessage(message, team) } - - showActionSheet([userAction, teamAction, cancelAction]) + } + + Router.shared.use( + ContactTeamListRouter, + parameters: ["nav": weakSelf?.navigationController as Any], + closure: nil + ) } + + let cancelAction = UIAlertAction(title: localizable("cancel"), + style: .cancel) { action in + } + + showActionSheet([userAction, teamAction, cancelAction]) + } } - + private func pinMessage() { - if let message = self.viewmodel.operationModel?.message { - viewmodel.pinMessage(message) {[weak self] error, pinItem, index in - if error != nil { - self?.view.makeToast(error?.localizedDescription) - }else { -// update UI - if index >= 0 { - self?.tableViewReloadIndexs([IndexPath(row: index, section: 0)]) - } - } - + if let message = viewmodel.operationModel?.message { + viewmodel.pinMessage(message) { [weak self] error, pinItem, index in + if error != nil { + self?.view.makeToast(error?.localizedDescription) + } else { + // update UI + if index >= 0 { + self?.tableViewReloadIndexs([IndexPath(row: index, section: 0)]) } + } } + } } - + private func removePinMessage() { - if let message = self.viewmodel.operationModel?.message { - viewmodel.removePinMessage(message) { [weak self] error, pinItem, index in - if error != nil { - self?.view.makeToast(error?.localizedDescription) - }else { -// update UI - if index >= 0 { - self?.tableViewReloadIndexs([IndexPath(row: index, section: 0)]) - } - } + if let message = viewmodel.operationModel?.message { + viewmodel.removePinMessage(message) { [weak self] error, pinItem, index in + if error != nil { + self?.view.makeToast(error?.localizedDescription) + } else { + // update UI + if index >= 0 { + self?.tableViewReloadIndexs([IndexPath(row: index, section: 0)]) } + } } + } + } + + //MARK: UITableViewDataSource, UITableViewDelegate + public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + viewmodel.messages.count ?? 0 } + + public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let model = viewmodel.messages[indexPath.row] + var reuseId = "" + if let isSend = model.message?.isOutgoingMsg, isSend { + if model.replyedModel != nil { + reuseId = "\(ChatReplyRightCell.self)" + } else { + switch model.type { + case .text: + reuseId = "\(ChatTextRightCell.self)" + case .image: + reuseId = "\(ChatImageRightCell.self)" + case .audio: + reuseId = "\(ChatAudioRightCell.self)" + case .video: + reuseId = "\(ChatVideoRightCell.self)" + case .time, .tip, .notification: + reuseId = "\(ChatTimeTableViewCell.self)" + case .revoke: + reuseId = "\(ChatRevokeRightCell.self)" + default: + reuseId = "\(ChatBaseRightCell.self)" + } + } + + let cell = tableView.dequeueReusableCell(withIdentifier: reuseId, for: indexPath) + if let c = cell as? ChatTimeTableViewCell { + if let m = model as? MessageTipsModel { + c.setModel(m) + } + return c + } else if let c = cell as? ChatBaseRightCell { + c.delegate = self + if let m = model as? MessageContentModel { + c.setModel(m) + } + return c + } else { + return ChatBaseRightCell() + } + } else { + if model.replyedModel != nil { + reuseId = "\(ChatReplyLeftCell.self)" + } else { + switch model.type { + case .text: + reuseId = "\(ChatTextLeftCell.self)" + case .image: + reuseId = "\(ChatImageLeftCell.self)" + case .audio: + reuseId = "\(ChatAudioLeftCell.self)" + case .video: + reuseId = "\(ChatVideoLeftCell.self)" + case .time, .tip, .notification: + reuseId = "\(ChatTimeTableViewCell.self)" + case .revoke: + reuseId = "\(ChatRevokeLeftCell.self)" + default: + reuseId = "\(ChatBaseLeftCell.self)" + } + } + + let cell = tableView.dequeueReusableCell(withIdentifier: reuseId, for: indexPath) + if let c = cell as? ChatTimeTableViewCell { + if let m = model as? MessageTipsModel { + c.setModel(m) + } + return c + } else if let c = cell as? ChatBaseLeftCell { + c.delegate = self + if let m = model as? MessageContentModel { + c.setModel(m) + } + return c + } else { + return ChatBaseLeftCell() + } + } + } + + public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + print("did select row ") + operationView?.removeFromSuperview() + if menuView.textField.isFirstResponder { + menuView.textField.resignFirstResponder() + } else { + layoutInputView(offset: 0) + } + } + + public func tableView(_ tableView: UITableView, + heightForRowAt indexPath: IndexPath) -> CGFloat { + let m = viewmodel.messages[indexPath.row] + print("text:\(m.message?.text) height:\(m.height)") + return CGFloat(m.height) + } + } -extension ChatViewController { - @objc func toSetting() { - if viewmodel.session.sessionType == .team { - Router.shared.use(TeamSettingViewRouter, parameters: ["nav": navigationController as Any, "teamid": viewmodel.session.sessionId], closure: nil) - }else if viewmodel.session.sessionType == .P2P { - let userSetting = UserSettingViewController() - userSetting.userId = viewmodel.session.sessionId - navigationController?.pushViewController(userSetting, animated: true) +// MARK: ChatBaseCellDelegate + +extension ChatViewController: ChatBaseCellDelegate { + func didTapAvatarView(_ cell: UITableViewCell, _ model: MessageContentModel?) { + didTapHeadPortrait(model: model) + } + + func didTapMessageView(_ cell: UITableViewCell, _ model: MessageContentModel?) { + if model?.type == .audio { + if let audio = model?.message?.messageObject as? NIMAudioObject { + startPlay(cell: cell as? ChatAudioCell, audio: audio) + } + } else if model?.type == .image { + if let imageObject = model?.message?.messageObject as? NIMImageObject { + var imageUrl = "" + + if let url = imageObject.url { + imageUrl = url + } else { + if let path = imageObject.path, FileManager.default.fileExists(atPath: path) { + imageUrl = path + } + } + if imageUrl.count > 0 { + let showController = PhotoBrowserController( + urls: viewmodel.getUrls(), + url: imageUrl + ) + showController.modalPresentationStyle = .overFullScreen + present(showController, animated: false, completion: nil) } + +// if let url = imageObject.url { +// let showController = PhotoBrowserController(urls: viewmodel.getUrls(), url: url) +// showController.modalPresentationStyle = .overFullScreen +// self.present(showController, animated: false, completion: nil) +// } + } + + } else if model?.type == .video, + let object = model?.message?.messageObject as? NIMVideoObject { + print("video click") + weak var weakSelf = self + let videoPlayer = VideoPlayerViewController() + videoPlayer.modalPresentationStyle = .overFullScreen + if let path = object.path, FileManager.default.fileExists(atPath: path) == true { + let url = URL(fileURLWithPath: path) + videoPlayer.videoUrl = url + videoPlayer.totalTime = object.duration + print("video url : ", videoPlayer.videoUrl as Any) + present(videoPlayer, animated: true, completion: nil) + } else if let urlString = object.url, let path = object.path, + let videoModel = model as? MessageVideoModel { + print("fetch message attachment") + + videoModel.state = .Downalod + if let left = cell as? ChatVideoLeftCell { + left.setModel(videoModel) + } else if let right = cell as? ChatVideoRightCell { + right.setModel(videoModel) + } + + viewmodel.downLoad(urlString, path) { progress in + videoModel.progress = progress + if progress >= 1.0 { + videoModel.state = .Success + } + videoModel.cell?.uploadProgress(progress) + } _: { error in + if let err = error as NSError? { + weakSelf?.showToast(err.localizedDescription) + } + } + } + } else if model?.type == .text { +// location at replied message + if model?.replyedModel != nil { + if model?.message?.repliedMessageId != nil { + var index = -1 + for (i, m) in viewmodel.messages.enumerated() { + if model?.message?.repliedMessageServerId == m.message?.serverID { + index = i + break + } + } + if index >= 0 { + tableView.scrollToRow( + at: IndexPath(row: index, section: 0), + at: .middle, + animated: true + ) + } + } + } + } else { + print("else") + } + } + + func didLongPressMessageView(_ cell: UITableViewCell, _ model: MessageContentModel?) { + didLongTouchMessageView(cell, model) + } + + func didTapResendView(_ cell: UITableViewCell, _ model: MessageContentModel?) { + if let msg = model?.message { + viewmodel.resendMessage(message: msg) + } + } + + func didTapReeditButton(_ cell: UITableViewCell, _ model: MessageContentModel?) { + if model?.type == .revoke, model?.message?.messageType == .text { + menuView.textField.text = model?.message?.text + menuView.textField.becomeFirstResponder() } + } + + func didTapReadView(_ cell: UITableViewCell, _ model: MessageContentModel?) { + if let msg = model?.message, msg.session?.sessionType == .team { + let readVC = ReadViewController(message: msg) + navigationController?.pushViewController(readVC, animated: true) + } + } } + + + + diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/Controller/GroupChatViewController.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/Controller/GroupChatViewController.swift index 573a93a6..1e23898e 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/Controller/GroupChatViewController.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/Controller/GroupChatViewController.swift @@ -1,78 +1,71 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NIMSDK import NEKitCoreIM - @objcMembers open class GroupChatViewController: ChatViewController, TeamChatViewModelDelegate { - - - - public init(session: NIMSession,anchor:NIMMessage?) { + public init(session: NIMSession, anchor: NIMMessage?) { // self.viewmodel = ChatViewModel(session: session) - super.init(session: session) - self.viewmodel = TeamChatViewModel(session: session, anchor: anchor) - self.viewmodel.delegate = self - - } - - - /// 创建群的构造方法 - /// - Parameter sessionId: 会话id - public init(sessionId:String) { - let session = NIMSession(sessionId, type: .team) - super.init(session: session) - - } - - - required public init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - open override func viewDidLoad() { - super.viewDidLoad() + super.init(session: session) + viewmodel = TeamChatViewModel(session: session, anchor: anchor) + viewmodel.delegate = self + } + /// 创建群的构造方法 + /// - Parameter sessionId: 会话id + public init(sessionId: String) { + let session = NIMSession(sessionId, type: .team) + super.init(session: session) + } + + public required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override open func viewDidLoad() { + super.viewDidLoad() + } + + override open func getSessionInfo(session: NIMSession) { + if let vm = viewmodel as? TeamChatViewModel { + if let t = vm.getTeam(teamId: session.sessionId) { + updateTeamInfo(team: t) + } } - - open override func getSessionInfo(session: NIMSession) { - if let vm = self.viewmodel as? TeamChatViewModel { - if let t = vm.getTeam(teamId: session.sessionId) { - self.updateTeamInfo(team: t) - } - } - } - + } + // MARK: private method - private func updateTeamInfo(team: NIMTeam) { - self.title = team.getShowName() - if team.inAllMuteMode(),team.owner != NIMSDK.shared().loginManager.currentAccount() { - self.menuView.textField.isEditable = false - self.menuView.textField.placeholder = localizable("team_mute") as NSString - }else { - self.menuView.textField.isEditable = true - self.menuView.textField.placeholder = localizable("send_to") + team.getShowName() as NSString - } + + private func updateTeamInfo(team: NIMTeam) { + title = team.getShowName() + if team.inAllMuteMode(), team.owner != NIMSDK.shared().loginManager.currentAccount() { + menuView.textField.isEditable = false + menuView.textField.placeholder = localizable("team_mute") as NSString + } else { + menuView.textField.isEditable = true + menuView.textField.placeholder = localizable("send_to") + team.getShowName() as NSString } - + } + // MARK: TeamChatViewModelDelegate - public func onTeamRemoved(team: NIMTeam) { - //只有群创建者 才弹弹窗 - if team.owner == IMKitLoginManager.instance.imAccid { - showSingleAlert(message: localizable("team_has_been_removed")) { - self.navigationController?.popViewController(animated: true) - } - }else { - self.navigationController?.popViewController(animated: true) - } + public func onTeamRemoved(team: NIMTeam) { + // 只有群创建者 才弹弹窗 + if team.owner == IMKitLoginManager.instance.imAccid { + showSingleAlert(message: localizable("team_has_been_removed")) { + self.navigationController?.popViewController(animated: true) + } + } else { + navigationController?.popViewController(animated: true) } - - public func onTeamUpdate(team: NIMTeam) { - self.updateTeamInfo(team: team) - } + } + + public func onTeamUpdate(team: NIMTeam) { + updateTeamInfo(team: team) + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/Controller/P2PChatViewController.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/Controller/P2PChatViewController.swift index ed9a2027..17e13540 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/Controller/P2PChatViewController.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/Controller/P2PChatViewController.swift @@ -1,48 +1,43 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NIMSDK @objcMembers open class P2PChatViewController: ChatViewController { + override open func viewDidLoad() { + super.viewDidLoad() - open override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - } - - open override func getSessionInfo(session: NIMSession) { - viewmodel.getUserInfo(userId: session.sessionId) - let user = viewmodel.getUserInfo(userId: session.sessionId) - let title = user?.showName() ?? "" - self.title = title - titleContent = title - //self.menuView.textField.placeholder = localizable("send_to") + title - self.menuView.textField.placeholder = localizable("send_to") + title as NSString - } - - /// 创建个人聊天页构造方法 - /// - Parameter sessionId: 会话id - public init(sessionId:String) { - let session = NIMSession(sessionId, type: .P2P) - super.init(session: session) - - } - - /// 重写父类的构造方法 - /// - Parameter session: sessionId - public override init(session: NIMSession) { - super.init(session: session) - } - - required public init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - - - + // Do any additional setup after loading the view. + } + + override open func getSessionInfo(session: NIMSession) { + viewmodel.getUserInfo(userId: session.sessionId) + let user = viewmodel.getUserInfo(userId: session.sessionId) + let title = user?.showName() ?? "" + self.title = title + titleContent = title + // self.menuView.textField.placeholder = localizable("send_to") + title + menuView.textField.placeholder = localizable("send_to") + title as NSString + } + + /// 创建个人聊天页构造方法 + /// - Parameter sessionId: 会话id + public init(sessionId: String) { + let session = NIMSession(sessionId, type: .P2P) + super.init(session: session) + } + + /// 重写父类的构造方法 + /// - Parameter session: sessionId + override public init(session: NIMSession) { + super.init(session: session) + } + + public required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/Controller/ReadViewController.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/Controller/ReadViewController.swift index a07b776b..3d1da908 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/Controller/ReadViewController.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/Controller/ReadViewController.swift @@ -1,231 +1,252 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NIMSDK import NEKitCoreIM import NEKitCommonUI -public class ReadViewController: NEBaseViewController, UIScrollViewDelegate, UITableViewDelegate, UITableViewDataSource { - - public var read: Bool = true - public var line: UIView = UIView() - public var lineLeftCons: NSLayoutConstraint? - public var readTableView = UITableView.init(frame: .zero, style: .plain) - public var readUsers = [User]() - public var unReadUsers = [User]() - public let readButton = UIButton(type: .custom) - public let unreadButton = UIButton(type: .custom) - private var message: NIMMessage - init(message: NIMMessage) { - self.message = message - super.init(nibName: nil, bundle: nil) +public class ReadViewController: NEBaseViewController, UIScrollViewDelegate, UITableViewDelegate, + UITableViewDataSource { + public var read: Bool = true + public var line: UIView = .init() + public var lineLeftCons: NSLayoutConstraint? + public var readTableView = UITableView(frame: .zero, style: .plain) + public var readUsers = [User]() + public var unReadUsers = [User]() + public let readButton = UIButton(type: .custom) + public let unreadButton = UIButton(type: .custom) + private var message: NIMMessage + init(message: NIMMessage) { + self.message = message + super.init(nibName: nil, bundle: nil) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override public func viewDidLoad() { + super.viewDidLoad() + commonUI() + loadData(message: message) + } + + func commonUI() { + title = localizable("message_read") + readButton.titleLabel?.font = UIFont.systemFont(ofSize: 14) + readButton.setTitle("已读(0)", for: .normal) + readButton.setTitleColor(UIColor.ne_darkText, for: .normal) + readButton.translatesAutoresizingMaskIntoConstraints = false + readButton.addTarget(self, action: #selector(readButtonEvent), for: .touchUpInside) + view.addSubview(readButton) + + unreadButton.titleLabel?.font = UIFont.systemFont(ofSize: 14) + unreadButton.setTitleColor(UIColor.ne_darkText, for: .normal) + unreadButton.setTitle("未读(0)", for: .normal) + unreadButton.translatesAutoresizingMaskIntoConstraints = false + unreadButton.addTarget(self, action: #selector(unreadButtonEvent), for: .touchUpInside) + + view.addSubview(unreadButton) + + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + readButton.topAnchor.constraint( + equalTo: self.view.safeAreaLayoutGuide.topAnchor, + constant: 0 + ), + readButton.leadingAnchor.constraint(equalTo: self.view.leadingAnchor), + readButton.heightAnchor.constraint(equalToConstant: 48), + readButton.widthAnchor.constraint(equalTo: unreadButton.widthAnchor), + ]) + } else { + // Fallback on earlier versions + NSLayoutConstraint.activate([ + readButton.topAnchor.constraint(equalTo: view.topAnchor, constant: 0), + readButton.leadingAnchor.constraint(equalTo: view.leadingAnchor), + readButton.heightAnchor.constraint(equalToConstant: 48), + readButton.widthAnchor.constraint(equalTo: unreadButton.widthAnchor), + ]) } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") + + NSLayoutConstraint.activate([ + unreadButton.topAnchor.constraint(equalTo: readButton.topAnchor), + unreadButton.leadingAnchor.constraint(equalTo: readButton.trailingAnchor), + unreadButton.trailingAnchor.constraint(equalTo: view.trailingAnchor), + unreadButton.heightAnchor.constraint(equalToConstant: 48), + ]) + + line.translatesAutoresizingMaskIntoConstraints = false + line.backgroundColor = UIColor.ne_blueText + view.addSubview(line) + lineLeftCons = line.leadingAnchor.constraint(equalTo: view.leadingAnchor) + NSLayoutConstraint.activate([ + line.topAnchor.constraint(equalTo: readButton.bottomAnchor, constant: 0), + line.heightAnchor.constraint(equalToConstant: 1), + line.widthAnchor.constraint(equalTo: readButton.widthAnchor), + lineLeftCons!, + ]) + + view.addSubview(emptyView) + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + emptyView.topAnchor.constraint(equalTo: readButton.bottomAnchor, constant: 1), + emptyView.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 0), + emptyView.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: 0), + emptyView.bottomAnchor.constraint( + equalTo: self.view.safeAreaLayoutGuide.bottomAnchor, + constant: 0 + ), + ]) + } else { + NSLayoutConstraint.activate([ + emptyView.topAnchor.constraint(equalTo: readButton.bottomAnchor, constant: 1), + emptyView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0), + emptyView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0), + emptyView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0), + ]) } - - public override func viewDidLoad() { - super.viewDidLoad() - commonUI() - loadData(message: self.message) + readTableView.delegate = self + readTableView.dataSource = self + readTableView.sectionHeaderHeight = 0 + readTableView.sectionFooterHeight = 0 + readTableView.translatesAutoresizingMaskIntoConstraints = false + readTableView.register( + UserTableViewCell.self, + forCellReuseIdentifier: "\(UserTableViewCell.self)" + ) + readTableView.separatorStyle = .none + readTableView.rowHeight = 62 + readTableView.tableFooterView = UIView() + view.addSubview(readTableView) + + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + readTableView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor), + readTableView.topAnchor.constraint(equalTo: readButton.bottomAnchor, constant: 1), + readTableView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor), + readTableView.bottomAnchor + .constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor), + ]) + } else { + // Fallback on earlier versions + NSLayoutConstraint.activate([ + readTableView.leadingAnchor.constraint(equalTo: view.leadingAnchor), + readTableView.topAnchor.constraint(equalTo: readButton.bottomAnchor, constant: 1), + readTableView.trailingAnchor.constraint(equalTo: view.trailingAnchor), + readTableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), + ]) } - - func commonUI() { - self.title = localizable("message_read") - readButton.titleLabel?.font = UIFont.systemFont(ofSize: 14) - readButton.setTitle("已读(0)", for: .normal) - readButton.setTitleColor(UIColor.ne_darkText, for: .normal) - readButton.translatesAutoresizingMaskIntoConstraints = false - readButton.addTarget(self, action: #selector(readButtonEvent), for: .touchUpInside) - self.view.addSubview(readButton) - - unreadButton.titleLabel?.font = UIFont.systemFont(ofSize: 14) - unreadButton.setTitleColor(UIColor.ne_darkText, for: .normal) - unreadButton.setTitle("未读(0)", for: .normal) - unreadButton.translatesAutoresizingMaskIntoConstraints = false - unreadButton.addTarget(self, action: #selector(unreadButtonEvent), for: .touchUpInside) - - self.view.addSubview(unreadButton) - - if #available(iOS 11.0, *) { - NSLayoutConstraint.activate([ - readButton.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor, constant: 0), - readButton.leadingAnchor.constraint(equalTo: self.view.leadingAnchor), - readButton.heightAnchor.constraint(equalToConstant: 48), - readButton.widthAnchor.constraint(equalTo: unreadButton.widthAnchor), - ]) - } else { - // Fallback on earlier versions - NSLayoutConstraint.activate([ - readButton.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 0), - readButton.leadingAnchor.constraint(equalTo: self.view.leadingAnchor), - readButton.heightAnchor.constraint(equalToConstant: 48), - readButton.widthAnchor.constraint(equalTo: unreadButton.widthAnchor), - ]) - } - - NSLayoutConstraint.activate([ - unreadButton.topAnchor.constraint(equalTo: readButton.topAnchor), - unreadButton.leadingAnchor.constraint(equalTo: readButton.trailingAnchor), - unreadButton.trailingAnchor.constraint(equalTo: self.view.trailingAnchor), - unreadButton.heightAnchor.constraint(equalToConstant: 48), - ]) - - line.translatesAutoresizingMaskIntoConstraints = false - line.backgroundColor = UIColor.ne_blueText - self.view.addSubview(self.line) - lineLeftCons = line.leadingAnchor.constraint(equalTo: self.view.leadingAnchor) - NSLayoutConstraint.activate([ - line.topAnchor.constraint(equalTo: readButton.bottomAnchor, constant: 0), - line.heightAnchor.constraint(equalToConstant: 1), - line.widthAnchor.constraint(equalTo: readButton.widthAnchor), - lineLeftCons! - ]) - - self.view.addSubview(self.emptyView) - if #available(iOS 11.0, *) { - NSLayoutConstraint.activate([ - emptyView.topAnchor.constraint(equalTo: readButton.bottomAnchor, constant: 1), - emptyView.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 0), - emptyView.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: 0), - emptyView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor, constant: 0), - ]) - } else { - NSLayoutConstraint.activate([ - emptyView.topAnchor.constraint(equalTo: readButton.bottomAnchor, constant: 1), - emptyView.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 0), - emptyView.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: 0), - emptyView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 0), - ]) - } - readTableView.delegate = self - readTableView.dataSource = self - readTableView.sectionHeaderHeight = 0 - readTableView.sectionFooterHeight = 0 - readTableView.translatesAutoresizingMaskIntoConstraints = false - readTableView.register(UserTableViewCell.self, forCellReuseIdentifier: "\(UserTableViewCell.self)") - readTableView.separatorStyle = .none - readTableView.rowHeight = 62 - readTableView.tableFooterView = UIView() - self.view.addSubview(readTableView) - - if #available(iOS 11.0, *) { - NSLayoutConstraint.activate([ - readTableView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor), - readTableView.topAnchor.constraint(equalTo: readButton.bottomAnchor,constant: 1), - readTableView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor), - readTableView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor) - ]) - } else { - // Fallback on earlier versions - NSLayoutConstraint.activate([ - readTableView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor), - readTableView.topAnchor.constraint(equalTo: readButton.bottomAnchor,constant: 1), - readTableView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor), - readTableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor) - ]) - } + } + + @objc func readButtonEvent(button: UIButton) { + if read { + return } - - @objc func readButtonEvent(button: UIButton) { - if self.read { - return - } - self.read = true - lineLeftCons?.constant = 0 - UIView.animate(withDuration: 0.5) { - self.view.layoutIfNeeded() - } - if self.readUsers.count == 0 { - self.readTableView.isHidden = true - self.emptyView.isHidden = false - }else { - self.readTableView.isHidden = false - self.emptyView.isHidden = true - self.readTableView.reloadData() - } + read = true + lineLeftCons?.constant = 0 + UIView.animate(withDuration: 0.5) { + self.view.layoutIfNeeded() } - - @objc func unreadButtonEvent(button: UIButton) { - if !self.read { - return - } - self.read = false - lineLeftCons?.constant = button.width - UIView.animate(withDuration: 0.5) { - self.view.layoutIfNeeded() - } - if self.unReadUsers.count == 0 { - self.readTableView.isHidden = true - self.emptyView.isHidden = false - }else { - self.readTableView.isHidden = false - self.emptyView.isHidden = true - self.readTableView.reloadData() - } + if readUsers.count == 0 { + readTableView.isHidden = true + emptyView.isHidden = false + } else { + readTableView.isHidden = false + emptyView.isHidden = true + readTableView.reloadData() } - - func loadData(message: NIMMessage) { - NIMSDK.shared().chatManager.queryMessageReceiptDetail(message) { anError, receiptInfo in - print("anError:\(anError) receiptInfo:\(receiptInfo)") - if let error = anError { - self.showToast(error.localizedDescription) - return - } - - for userId in receiptInfo?.readUserIds ?? [] { - if let uId = userId as? String, let user = UserInfoProvider.shared.getUserInfo(userId: uId) { - self.readUsers.append(user) - } - } - - for userId in receiptInfo?.unreadUserIds ?? [] { - if let uId = userId as? String, let user = UserInfoProvider.shared.getUserInfo(userId: uId) { - self.unReadUsers.append(user) - } - } - self.readButton.setTitle("已读 (" + "\(self.readUsers.count)" + ")", for: .normal) - self.unreadButton.setTitle("未读 (" + "\(self.unReadUsers.count)" + ")", for: .normal) - self.readTableView.reloadData() - - if self.read && self.readUsers.count == 0 { - self.readTableView.isHidden = true - self.emptyView.isHidden = false - }else { - self.readTableView.isHidden = false - self.emptyView.isHidden = true - } - } + } + + @objc func unreadButtonEvent(button: UIButton) { + if !read { + return } + read = false + lineLeftCons?.constant = button.width + UIView.animate(withDuration: 0.5) { + self.view.layoutIfNeeded() + } + if unReadUsers.count == 0 { + readTableView.isHidden = true + emptyView.isHidden = false + } else { + readTableView.isHidden = false + emptyView.isHidden = true + readTableView.reloadData() + } + } - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - if self.read { - return self.readUsers.count - }else { - return self.unReadUsers.count + func loadData(message: NIMMessage) { + NIMSDK.shared().chatManager.queryMessageReceiptDetail(message) { anError, receiptInfo in + print("anError:\(anError) receiptInfo:\(receiptInfo)") + if let error = anError { + self.showToast(error.localizedDescription) + return + } + + for userId in receiptInfo?.readUserIds ?? [] { + if let uId = userId as? String, + let user = UserInfoProvider.shared.getUserInfo(userId: uId) { + self.readUsers.append(user) } - } - - public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(withIdentifier: "\(UserTableViewCell.self)", for: indexPath) as! UserTableViewCell - if self.read { - let model = self.readUsers[indexPath.row] - cell.setModel(model) - - }else { - let model = self.unReadUsers[indexPath.row] - cell.setModel(model) + } + + for userId in receiptInfo?.unreadUserIds ?? [] { + if let uId = userId as? String, + let user = UserInfoProvider.shared.getUserInfo(userId: uId) { + self.unReadUsers.append(user) } - return cell + } + self.readButton.setTitle("已读 (" + "\(self.readUsers.count)" + ")", for: .normal) + self.unreadButton.setTitle("未读 (" + "\(self.unReadUsers.count)" + ")", for: .normal) + self.readTableView.reloadData() + + if self.read, self.readUsers.count == 0 { + self.readTableView.isHidden = true + self.emptyView.isHidden = false + } else { + self.readTableView.isHidden = false + self.emptyView.isHidden = true + } + } + } + + public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + if read { + return readUsers.count + } else { + return unReadUsers.count } - - private lazy var emptyView: NEEmptyDataView = { - let view = NEEmptyDataView(imageName: "emptyView" , content: localizable("message_all_unread"), frame: .zero) - view.translatesAutoresizingMaskIntoConstraints = false - self.view.addSubview(view) - return view - }() + } + + public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(UserTableViewCell.self)", + for: indexPath + ) as! UserTableViewCell + if read { + let model = readUsers[indexPath.row] + cell.setModel(model) + + } else { + let model = unReadUsers[indexPath.row] + cell.setModel(model) + } + return cell + } + + private lazy var emptyView: NEEmptyDataView = { + let view = NEEmptyDataView( + imageName: "emptyView", + content: localizable("message_all_unread"), + frame: .zero + ) + view.translatesAutoresizingMaskIntoConstraints = false + self.view.addSubview(view) + return view + }() } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/Controller/SelectUserViewController.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/Controller/SelectUserViewController.swift index df066b79..721ce48e 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/Controller/SelectUserViewController.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/Controller/SelectUserViewController.swift @@ -1,151 +1,157 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitChat -public typealias didSelectedAtRow = ( _ index: Int, _ model: ChatTeamMemberInfoModel?) -> () +public typealias didSelectedAtRow = (_ index: Int, _ model: ChatTeamMemberInfoModel?) -> Void -public class SelectUserViewController: NEBaseViewController, UITableViewDelegate, UITableViewDataSource { +public class SelectUserViewController: NEBaseViewController, UITableViewDelegate, + UITableViewDataSource { + public var tableView = UITableView(frame: .zero, style: .plain) + public var sessionId: String + public var viewModel = TeamMemberSelectVM() + public var selectedBlock: didSelectedAtRow? + var teamInfo: ChatTeamInfoModel? - public var tableView = UITableView.init(frame: .zero, style: .plain) - public var sessionId: String - public var viewModel = TeamMemberSelectVM() - public var selectedBlock: didSelectedAtRow? - var teamInfo: ChatTeamInfoModel? - - init(sessionId: String) { - self.sessionId = sessionId - super.init(nibName: nil, bundle: nil) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - public override func viewDidLoad() { - super.viewDidLoad() - commonUI() - loadData() + init(sessionId: String) { + self.sessionId = sessionId + super.init(nibName: nil, bundle: nil) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override public func viewDidLoad() { + super.viewDidLoad() + commonUI() + loadData() + } + + func commonUI() { + let btn = UIButton(type: .custom) + btn.translatesAutoresizingMaskIntoConstraints = false + btn.setImage(UIImage.ne_imageNamed(name: "arrowDown"), for: .normal) + btn.addTarget(self, action: #selector(btnEvent), for: .touchUpInside) + view.addSubview(btn) + + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + btn.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 16), + btn.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor), + btn.widthAnchor.constraint(equalToConstant: 50), + btn.heightAnchor.constraint(equalToConstant: 50), + ]) + } else { + // Fallback on earlier versions + NSLayoutConstraint.activate([ + btn.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16), + btn.topAnchor.constraint(equalTo: view.topAnchor), + btn.widthAnchor.constraint(equalToConstant: 50), + btn.heightAnchor.constraint(equalToConstant: 50), + ]) } - - func commonUI() { - - let btn = UIButton(type: .custom) - btn.translatesAutoresizingMaskIntoConstraints = false - btn.setImage(UIImage.ne_imageNamed(name: "arrowDown"), for: .normal) - btn.addTarget(self, action: #selector(btnEvent), for: .touchUpInside) - self.view.addSubview(btn) - - if #available(iOS 11.0, *) { - NSLayoutConstraint.activate([ - btn.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 16), - btn.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor), - btn.widthAnchor.constraint(equalToConstant: 50), - btn.heightAnchor.constraint(equalToConstant: 50) - ]) - } else { - // Fallback on earlier versions - NSLayoutConstraint.activate([ - btn.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 16), - btn.topAnchor.constraint(equalTo: self.view.topAnchor), - btn.widthAnchor.constraint(equalToConstant: 50), - btn.heightAnchor.constraint(equalToConstant: 50) - ]) - } - - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.text = localizable("user_select") - label.font = UIFont.systemFont(ofSize: 16) - label.textAlignment = .center - label.textColor = UIColor.darkGray - self.view.addSubview(label) - NSLayoutConstraint.activate([ - label.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 16), - label.topAnchor.constraint(equalTo: self.view.topAnchor), - label.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: 0), - label.heightAnchor.constraint(equalToConstant: 50) - ]) - - tableView.delegate = self - tableView.dataSource = self - tableView.sectionHeaderHeight = 0 - tableView.sectionFooterHeight = 0 - tableView.translatesAutoresizingMaskIntoConstraints = false - tableView.register(ChatTeamMemberCell.self, forCellReuseIdentifier: "\(ChatTeamMemberCell.self)") - tableView.separatorStyle = .none - tableView.rowHeight = 62 - tableView.tableFooterView = UIView() - self.view.addSubview(tableView) - - if #available(iOS 11.0, *) { - NSLayoutConstraint.activate([ - tableView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor), - tableView.topAnchor.constraint(equalTo: label.bottomAnchor), - tableView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor), - tableView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor) - ]) - } else { - // Fallback on earlier versions - NSLayoutConstraint.activate([ - tableView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor), - tableView.topAnchor.constraint(equalTo: label.bottomAnchor,constant: 0), - tableView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor), - tableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor) - ]) - } + + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.text = localizable("user_select") + label.font = UIFont.systemFont(ofSize: 16) + label.textAlignment = .center + label.textColor = UIColor.darkGray + view.addSubview(label) + NSLayoutConstraint.activate([ + label.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16), + label.topAnchor.constraint(equalTo: view.topAnchor), + label.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0), + label.heightAnchor.constraint(equalToConstant: 50), + ]) + + tableView.delegate = self + tableView.dataSource = self + tableView.sectionHeaderHeight = 0 + tableView.sectionFooterHeight = 0 + tableView.translatesAutoresizingMaskIntoConstraints = false + tableView.register( + ChatTeamMemberCell.self, + forCellReuseIdentifier: "\(ChatTeamMemberCell.self)" + ) + tableView.separatorStyle = .none + tableView.rowHeight = 62 + tableView.tableFooterView = UIView() + view.addSubview(tableView) + + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + tableView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor), + tableView.topAnchor.constraint(equalTo: label.bottomAnchor), + tableView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor), + tableView.bottomAnchor + .constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor), + ]) + } else { + // Fallback on earlier versions + NSLayoutConstraint.activate([ + tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor), + tableView.topAnchor.constraint(equalTo: label.bottomAnchor, constant: 0), + tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor), + tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), + ]) } - - func loadData() { - viewModel.fetchTeamMembers(sessionId: sessionId) { [weak self] error, team in - if error != nil { - self?.view.makeToast(error?.localizedDescription) - return - } - self?.teamInfo = team - self?.tableView.reloadData() - } + } + + func loadData() { + viewModel.fetchTeamMembers(sessionId: sessionId) { [weak self] error, team in + if error != nil { + self?.view.makeToast(error?.localizedDescription) + return + } + self?.teamInfo = team + self?.tableView.reloadData() } - - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - if let count = self.teamInfo?.users.count { - return count + 1 - } - return 0 + } + + public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + if let count = teamInfo?.users.count { + return count + 1 } - - public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(withIdentifier: "\(ChatTeamMemberCell.self)", for: indexPath) as! ChatTeamMemberCell - if indexPath.row == 0 { - cell.headerView.image = UIImage.ne_imageNamed(name: "chat_team") - cell.nameLabel.text = localizable("user_select_all") - }else { - if let model = self.teamInfo?.users[indexPath.row - 1] { - cell.configure(model) - } - } - return cell + return 0 + } + + public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(ChatTeamMemberCell.self)", + for: indexPath + ) as! ChatTeamMemberCell + if indexPath.row == 0 { + cell.headerView.image = UIImage.ne_imageNamed(name: "chat_team") + cell.nameLabel.text = localizable("user_select_all") + } else { + if let model = teamInfo?.users[indexPath.row - 1] { + cell.configure(model) + } } - - public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - - if indexPath.row == 0 { - if let block = self.selectedBlock { - block(indexPath.row, nil) - } - self.dismiss(animated: true, completion: nil) - return - } - if let block = self.selectedBlock { - block(indexPath.row, self.teamInfo?.users[indexPath.row - 1]) - } - self.dismiss(animated: true, completion: nil) + return cell + } + + public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + if indexPath.row == 0 { + if let block = selectedBlock { + block(indexPath.row, nil) + } + dismiss(animated: true, completion: nil) + return } - - @objc func btnEvent(button: UIButton) { - self.dismiss(animated: true, completion: nil) + if let block = selectedBlock { + block(indexPath.row, teamInfo?.users[indexPath.row - 1]) } + dismiss(animated: true, completion: nil) + } + @objc func btnEvent(button: UIButton) { + dismiss(animated: true, completion: nil) + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/Controller/UserSettingViewController.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/Controller/UserSettingViewController.swift index 18e91e78..56bbc010 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/Controller/UserSettingViewController.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/Controller/UserSettingViewController.swift @@ -1,224 +1,235 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCommon import NIMSDK -public class UserSettingViewController: NEBaseViewController, UserSettingViewModelDelegate { - - var userId: String? - - let viewmodel = UserSettingViewModel() - - lazy var userHeader: NEUserHeaderView = { - let imageView = NEUserHeaderView(frame: .zero) - imageView.translatesAutoresizingMaskIntoConstraints = false - imageView.clipsToBounds = true - imageView.titleLabel.font = NEConstant.defaultTextFont(16.0) - imageView.layer.cornerRadius = 21.0 - imageView.isUserInteractionEnabled = true - return imageView - }() - - lazy var addBtn: ExpandButton = { - let button = ExpandButton() - button.translatesAutoresizingMaskIntoConstraints = false - button.setImage(coreLoader.loadImage("setting_add"), for: .normal) - return button - }() - - lazy var nameLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.font = NEConstant.defaultTextFont(12.0) - label.textColor = .ne_darkText - return label - }() - - lazy var contentTable: UITableView = { - let table = UITableView() - table.translatesAutoresizingMaskIntoConstraints = false - table.backgroundColor = NEConstant.hexRGB(0xF1F1F6) - table.dataSource = self - table.delegate = self - table.separatorColor = .clear - table.separatorStyle = .none - table.sectionHeaderHeight = 12.0 - table.tableFooterView = UIView(frame: CGRect(x: 0,y: 0,width: view.frame.size.width,height: 12)) - if #available(iOS 15.0, *) { - table.sectionHeaderTopPadding = 0.0 - } - return table - }() - - public override func viewDidLoad() { - super.viewDidLoad() - viewmodel.delegate = self - setupUI() - if let uid = userId { - viewmodel.getUserSettingModel(uid) - contentTable.tableHeaderView = headerView() - contentTable.reloadData() - } - } - - func setupUI(){ - view.backgroundColor = .ne_backcolor - view.addSubview(contentTable) - NSLayoutConstraint.activate([ - contentTable.leftAnchor.constraint(equalTo: view.leftAnchor), - contentTable.rightAnchor.constraint(equalTo: view.rightAnchor), - contentTable.topAnchor.constraint(equalTo: view.topAnchor), - contentTable.bottomAnchor.constraint(equalTo: view.bottomAnchor) - ]) - contentTable.register(UserSettingSwitchCell.self, forCellReuseIdentifier: "\(UserSettingSwitchCell.self)") - +public class UserSettingViewController: NEBaseViewController, UserSettingViewModelDelegate,UITableViewDataSource, UITableViewDelegate{ + var userId: String? + + let viewmodel = UserSettingViewModel() + + lazy var userHeader: NEUserHeaderView = { + let imageView = NEUserHeaderView(frame: .zero) + imageView.translatesAutoresizingMaskIntoConstraints = false + imageView.clipsToBounds = true + imageView.titleLabel.font = NEConstant.defaultTextFont(16.0) + imageView.layer.cornerRadius = 21.0 + imageView.isUserInteractionEnabled = true + return imageView + }() + + lazy var addBtn: ExpandButton = { + let button = ExpandButton() + button.translatesAutoresizingMaskIntoConstraints = false + button.setImage(coreLoader.loadImage("setting_add"), for: .normal) + return button + }() + + lazy var nameLabel: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.font = NEConstant.defaultTextFont(12.0) + label.textColor = .ne_darkText + return label + }() + + lazy var contentTable: UITableView = { + let table = UITableView() + table.translatesAutoresizingMaskIntoConstraints = false + table.backgroundColor = NEConstant.hexRGB(0xF1F1F6) + table.dataSource = self + table.delegate = self + table.separatorColor = .clear + table.separatorStyle = .none + table.sectionHeaderHeight = 12.0 + table + .tableFooterView = + UIView(frame: CGRect(x: 0, y: 0, width: view.frame.size.width, height: 12)) + if #available(iOS 15.0, *) { + table.sectionHeaderTopPadding = 0.0 } - - func headerView() -> UIView { - let header = UIView(frame: CGRect(x: 0, y: 0, width: view.width, height: 110)) - header.backgroundColor = .clear - let cornerBack = UIView() - cornerBack.layer.cornerRadius = 8.0 - cornerBack.backgroundColor = .white - cornerBack.translatesAutoresizingMaskIntoConstraints = false - header.addSubview(cornerBack) - NSLayoutConstraint.activate([ - cornerBack.bottomAnchor.constraint(equalTo: header.bottomAnchor, constant: -12), - cornerBack.leftAnchor.constraint(equalTo: header.leftAnchor, constant: 20), - cornerBack.rightAnchor.constraint(equalTo: header.rightAnchor, constant: -20), - cornerBack.heightAnchor.constraint(equalToConstant: 86.0) - ]) - - cornerBack.addSubview(userHeader) - NSLayoutConstraint.activate([ - userHeader.leftAnchor.constraint(equalTo: cornerBack.leftAnchor, constant: 16), - userHeader.topAnchor.constraint(equalTo: cornerBack.topAnchor, constant: 12), - userHeader.widthAnchor.constraint(equalToConstant: 42), - userHeader.heightAnchor.constraint(equalToConstant: 42) - ]) - let tap = UITapGestureRecognizer() - userHeader.addGestureRecognizer(tap) - tap.numberOfTapsRequired = 1 - tap.numberOfTouchesRequired = 1 - - if let url = viewmodel.userInfo?.userInfo?.avatarUrl { - userHeader.sd_setImage(with: URL(string: url), completed: nil) - }else if let name = viewmodel.userInfo?.showName() { - userHeader.setTitle(name) - userHeader.backgroundColor = UIColor.colorWithString(string: viewmodel.userInfo?.userId) - } - - cornerBack.addSubview(addBtn) - NSLayoutConstraint.activate([ - addBtn.leftAnchor.constraint(equalTo: userHeader.rightAnchor, constant: 20.0), - addBtn.topAnchor.constraint(equalTo: userHeader.topAnchor), - addBtn.widthAnchor.constraint(equalToConstant: 42.0), - addBtn.heightAnchor.constraint(equalToConstant: 42.0) - ]) - addBtn.addTarget(self, action: #selector(createDiscuss), for: .touchUpInside) - - cornerBack.addSubview(nameLabel) - NSLayoutConstraint.activate([ - nameLabel.leftAnchor.constraint(equalTo: userHeader.leftAnchor, constant: -12.0), - nameLabel.rightAnchor.constraint(equalTo: userHeader.rightAnchor, constant: 12.0), - nameLabel.topAnchor.constraint(equalTo: userHeader.bottomAnchor, constant: 6.0) - ]) - nameLabel.text = viewmodel.userInfo?.showName() - - return header + return table + }() + + override public func viewDidLoad() { + super.viewDidLoad() + viewmodel.delegate = self + setupUI() + if let uid = userId { + viewmodel.getUserSettingModel(uid) + contentTable.tableHeaderView = headerView() + contentTable.reloadData() } - - @objc func createDiscuss(){ - weak var weakSelf = self - Router.shared.register(ContactSelectedUsersRouter) { param in - print("user setting create disscuss : ", param) - var convertParam = [String: Any]() - param.forEach { (key: String, value: Any) in - if key == "names", let names = value as? String { - convertParam[key] = "\(weakSelf?.userId ?? "")、\(names)" - }else { - convertParam[key] = value - } - } - weakSelf?.view.makeToastActivity(.center) - Router.shared.use(TeamCreateDisuss, parameters: convertParam, closure: nil) - } - var filters = Set() - if let uid = userId { - filters.insert(uid) - } - - Router.shared.use(ContactUserSelectRouter, parameters: ["nav": navigationController as Any, "filters":filters, "limit": 199], closure: nil) - - Router.shared.register(TeamCreateDiscussResult) { param in - print("create discuss ", param) - weakSelf?.view.hideToastActivity() - if let code = param["code"] as? Int, let teamid = param["teamId"] as? String, code == 0 { - let session = NIMSession(teamid, type: .team) - - DispatchQueue.main.async { - if let allControllers = weakSelf?.navigationController?.viewControllers.filter({ - if $0.isKind(of: P2PChatViewController.self) || $0.isKind(of: UserSettingViewController.self) { - return false - } - return true - }){ - weakSelf?.navigationController?.viewControllers = allControllers - Router.shared.use(PushTeamChatVCRouter, parameters: ["nav": weakSelf?.navigationController as Any, "session" : session as Any], closure: nil) - } - } - }else if let error = param["msg"] as? String { - weakSelf?.showToast(error) - } - } + } + + func setupUI() { + view.backgroundColor = .ne_backcolor + view.addSubview(contentTable) + NSLayoutConstraint.activate([ + contentTable.leftAnchor.constraint(equalTo: view.leftAnchor), + contentTable.rightAnchor.constraint(equalTo: view.rightAnchor), + contentTable.topAnchor.constraint(equalTo: view.topAnchor), + contentTable.bottomAnchor.constraint(equalTo: view.bottomAnchor), + ]) + contentTable.register( + UserSettingSwitchCell.self, + forCellReuseIdentifier: "\(UserSettingSwitchCell.self)" + ) + } + + func headerView() -> UIView { + let header = UIView(frame: CGRect(x: 0, y: 0, width: view.width, height: 110)) + header.backgroundColor = .clear + let cornerBack = UIView() + cornerBack.layer.cornerRadius = 8.0 + cornerBack.backgroundColor = .white + cornerBack.translatesAutoresizingMaskIntoConstraints = false + header.addSubview(cornerBack) + NSLayoutConstraint.activate([ + cornerBack.bottomAnchor.constraint(equalTo: header.bottomAnchor, constant: -12), + cornerBack.leftAnchor.constraint(equalTo: header.leftAnchor, constant: 20), + cornerBack.rightAnchor.constraint(equalTo: header.rightAnchor, constant: -20), + cornerBack.heightAnchor.constraint(equalToConstant: 86.0), + ]) + + cornerBack.addSubview(userHeader) + NSLayoutConstraint.activate([ + userHeader.leftAnchor.constraint(equalTo: cornerBack.leftAnchor, constant: 16), + userHeader.topAnchor.constraint(equalTo: cornerBack.topAnchor, constant: 12), + userHeader.widthAnchor.constraint(equalToConstant: 42), + userHeader.heightAnchor.constraint(equalToConstant: 42), + ]) + let tap = UITapGestureRecognizer() + userHeader.addGestureRecognizer(tap) + tap.numberOfTapsRequired = 1 + tap.numberOfTouchesRequired = 1 + + if let url = viewmodel.userInfo?.userInfo?.avatarUrl { + userHeader.sd_setImage(with: URL(string: url), completed: nil) + } else if let name = viewmodel.userInfo?.showName() { + userHeader.setTitle(name) + userHeader.backgroundColor = UIColor.colorWithString(string: viewmodel.userInfo?.userId) } - - @objc func showUserInfo(){ - if let user = viewmodel.userInfo { - Router.shared.use(ContactUserInfoPageRouter, parameters: ["nav": navigationController as Any, "user" : user], closure: nil) + + cornerBack.addSubview(addBtn) + NSLayoutConstraint.activate([ + addBtn.leftAnchor.constraint(equalTo: userHeader.rightAnchor, constant: 20.0), + addBtn.topAnchor.constraint(equalTo: userHeader.topAnchor), + addBtn.widthAnchor.constraint(equalToConstant: 42.0), + addBtn.heightAnchor.constraint(equalToConstant: 42.0), + ]) + addBtn.addTarget(self, action: #selector(createDiscuss), for: .touchUpInside) + + cornerBack.addSubview(nameLabel) + NSLayoutConstraint.activate([ + nameLabel.leftAnchor.constraint(equalTo: userHeader.leftAnchor, constant: -12.0), + nameLabel.rightAnchor.constraint(equalTo: userHeader.rightAnchor, constant: 12.0), + nameLabel.topAnchor.constraint(equalTo: userHeader.bottomAnchor, constant: 6.0), + ]) + nameLabel.text = viewmodel.userInfo?.showName() + + return header + } + + @objc func createDiscuss() { + weak var weakSelf = self + Router.shared.register(ContactSelectedUsersRouter) { param in + print("user setting create disscuss : ", param) + var convertParam = [String: Any]() + param.forEach { (key: String, value: Any) in + if key == "names", let names = value as? String { + convertParam[key] = "\(weakSelf?.userId ?? "")、\(names)" + } else { + convertParam[key] = value } + } + weakSelf?.view.makeToastActivity(.center) + Router.shared.use(TeamCreateDisuss, parameters: convertParam, closure: nil) } - - func didNeedRefreshUI() { - contentTable.reloadData() + var filters = Set() + if let uid = userId { + filters.insert(uid) } - - func didError(_ error: Error) { - showToast(error.localizedDescription) + + Router.shared.use( + ContactUserSelectRouter, + parameters: ["nav": navigationController as Any, "filters": filters, "limit": 199], + closure: nil + ) + + Router.shared.register(TeamCreateDiscussResult) { param in + print("create discuss ", param) + weakSelf?.view.hideToastActivity() + if let code = param["code"] as? Int, let teamid = param["teamId"] as? String, + code == 0 { + let session = NIMSession(teamid, type: .team) + + DispatchQueue.main.async { + if let allControllers = weakSelf?.navigationController?.viewControllers.filter({ + if $0.isKind(of: P2PChatViewController.self) || $0 + .isKind(of: UserSettingViewController.self) { + return false + } + return true + }) { + weakSelf?.navigationController?.viewControllers = allControllers + Router.shared.use( + PushTeamChatVCRouter, + parameters: ["nav": weakSelf?.navigationController as Any, + "session": session as Any], + closure: nil + ) + } + } + } else if let error = param["msg"] as? String { + weakSelf?.showToast(error) + } } - - /* - // MARK: - Navigation - - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. + } + + @objc func showUserInfo() { + if let user = viewmodel.userInfo { + Router.shared.use( + ContactUserInfoPageRouter, + parameters: ["nav": navigationController as Any, "user": user], + closure: nil + ) } - */ + } -} + func didNeedRefreshUI() { + contentTable.reloadData() + } -extension UserSettingViewController: UITableViewDataSource, UITableViewDelegate { - + func didError(_ error: Error) { + showToast(error.localizedDescription) + } + + //MARK: UITableViewDataSource, UITableViewDelegate public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return viewmodel.cellDatas.count + viewmodel.cellDatas.count } - - public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let model = viewmodel.cellDatas[indexPath.row] - if let cell = tableView.dequeueReusableCell(withIdentifier: "\(UserSettingSwitchCell.self)", for: indexPath) as? UserSettingBaseCell { - cell.configure(model) - return cell - } - return UITableViewCell() + + public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let model = viewmodel.cellDatas[indexPath.row] + if let cell = tableView.dequeueReusableCell( + withIdentifier: "\(UserSettingSwitchCell.self)", + for: indexPath + ) as? UserSettingBaseCell { + cell.configure(model) + return cell + } + return UITableViewCell() } - + public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { -// let model = viewmodel.cellDatas[indexPath.row] - + // let model = viewmodel.cellDatas[indexPath.row] } } + + diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/Emoji/EmojiPageView.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/Emoji/EmojiPageView.swift index 6c29f914..60dd0a28 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/Emoji/EmojiPageView.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/Emoji/EmojiPageView.swift @@ -1,253 +1,272 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit @objc public protocol EmojiPageViewDataSource: AnyObject { - @objc optional func numberOfPages(pageView: EmojiPageView?) -> NSInteger - @objc optional func pageView(pageView: EmojiPageView?,index:NSInteger) ->UIView + @objc optional func numberOfPages(pageView: EmojiPageView?) -> NSInteger + @objc optional func pageView(pageView: EmojiPageView?, index: NSInteger) -> UIView } @objc public protocol EmojiPageViewDelegate: AnyObject { - - @objc optional func pageViewScrollEnd( - _ pageView: EmojiPageView?, - currentIndex: Int, - totolPages : Int) - - @objc optional func pageViewDidScroll(_ pageView: EmojiPageView?) - @objc optional func needScrollAnimation() -> Bool + @objc optional func pageViewScrollEnd(_ pageView: EmojiPageView?, + currentIndex: Int, + totolPages: Int) + + @objc optional func pageViewDidScroll(_ pageView: EmojiPageView?) + @objc optional func needScrollAnimation() -> Bool } public class EmojiPageView: UIView { - - public weak var dataSource: EmojiPageViewDataSource? - public weak var pageViewDelegate: EmojiPageViewDelegate? - private var currentPage:NSInteger = 0 - private var pages = [AnyObject]() - private let className = "EmojiPageView" - - public override init(frame: CGRect) { - super.init(frame: frame) - setupControls() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - public override var frame: CGRect { - set { - let originalWidth = self.width - super.frame = newValue - if originalWidth != frame.size.width { - self.reloadData() - } - } - get { - return super.frame - } + public weak var dataSource: EmojiPageViewDataSource? + public weak var pageViewDelegate: EmojiPageViewDelegate? + private var currentPage: NSInteger = 0 + private var pages = [AnyObject]() + private let className = "EmojiPageView" + + override public init(frame: CGRect) { + super.init(frame: frame) + setupControls() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override public var frame: CGRect { + set { + let originalWidth = width + super.frame = newValue + if originalWidth != frame.size.width { + reloadData() + } } - - func setupControls(){ - self.addSubview(scrollView) + get { + super.frame } - - - public func scrollToPage(page:NSInteger){ - if currentPage != page || page == 0 { - currentPage = page - reloadData() - } + } + + func setupControls() { + addSubview(scrollView) + } + + public func scrollToPage(page: NSInteger) { + if currentPage != page || page == 0 { + currentPage = page + reloadData() } + } - public func reloadData(){ - calculatePageNumbers() - setupInit() + public func reloadData() { + calculatePageNumbers() + setupInit() // reloadPage() + } + + func viewAtIndex(index: NSInteger) -> UIView? { + if index >= 0, index < pages.count { + let obj = pages[index] + if obj.isKind(of: UIView.self) { + return obj as? UIView + } } - - func viewAtIndex(index:NSInteger)->UIView?{ - - if index >= 0 && index < pages.count{ - let obj = pages[index] - if obj.isKind(of: UIView.self) { - return obj as? UIView - } - } - return nil - } + return nil + } - func reloadPage(){ - //reload时候记录上次位置 + func reloadPage() { + // reload时候记录上次位置 // guard let cPage = currentPage else { // NELog.errorLog(className, desc: "❌currentPage is nil") // return // } - if currentPage >= pages.count { - currentPage = pages.count - 1 - } - if currentPage < 0 { - currentPage = 0 - } - loadPages(currentPage: currentPage) - raisePageIndexChangedDelegate() - setNeedsLayout() - } - - func calculatePageNumbers(){ - - var numberOfPages = 0 - for obj in pages { - if obj.isKind(of: UIView.self) { - obj.removeFromSuperview() - } - } - numberOfPages = dataSource?.numberOfPages?(pageView: self) ?? 0 - - for _ in 0.. NSInteger { - - var maxUse = max - - if maxUse < min { - maxUse = min - } - var bounded = value - if bounded > maxUse { - bounded = maxUse - } - if bounded < min { - bounded = min - } - return bounded - } - - func setupInit(){ - let count = pages.count - for i in (0..= pages.count { + currentPage = pages.count - 1 } - - //page载入和销毁 - func loadPages(currentPage:NSInteger?){ - let count = pages.count - if count == 0 { - return - } - guard let curPage = currentPage else { - return + if currentPage < 0 { + currentPage = 0 + } + loadPages(currentPage: currentPage) + raisePageIndexChangedDelegate() + setNeedsLayout() + } + + func calculatePageNumbers() { + var numberOfPages = 0 + for obj in pages { + if obj.isKind(of: UIView.self) { + obj.removeFromSuperview() + } + } + numberOfPages = dataSource?.numberOfPages?(pageView: self) ?? 0 + + for _ in 0 ..< numberOfPages { + pages.append(NSNull()) + } + scrollView.delegate = nil + let size = bounds.size + scrollView.contentSize = CGSize( + width: size.width * CGFloat(numberOfPages), + height: size.height + ) + scrollView.delegate = nil + } + + func pageInBound(value: NSInteger, min: NSInteger, max: NSInteger) -> NSInteger { + var maxUse = max + + if maxUse < min { + maxUse = min + } + var bounded = value + if bounded > maxUse { + bounded = maxUse + } + if bounded < min { + bounded = min + } + return bounded + } + + func setupInit() { + let count = pages.count + for i in 0 ..< count { + if let targetView = dataSource?.pageView?(pageView: self, index: i) { + pages[i] = targetView + scrollView.addSubview(targetView) + let size = bounds.size + targetView.frame = CGRect( + x: size.width * CGFloat(i), + y: 0, + width: size.width, + height: size.height + ) + } + } + } + + // page载入和销毁 + func loadPages(currentPage: NSInteger?) { + let count = pages.count + if count == 0 { + return + } + guard let curPage = currentPage else { + return + } + + let first = pageInBound(value: curPage - 1, min: 0, max: count - 1) + let last = pageInBound(value: curPage + 1, min: 0, max: count - 1) + let range = NSRange(location: first, length: last - first + 1) + for i in 0 ..< count { + if NSLocationInRange(i, range) { + let obj = pages[i] + if !obj.isKind(of: UIView.self) { + if let targetView = dataSource?.pageView?(pageView: self, index: i) { + pages[i] = targetView + scrollView.addSubview(targetView) + let size = bounds.size + targetView.frame = CGRect( + x: size.width * CGFloat(i), + y: 0, + width: size.width, + height: size.height + ) + } else { + assertionFailure() + } } - - let first = pageInBound(value: curPage - 1 , min: 0, max: count - 1) - let last = pageInBound(value: curPage + 1, min: 0, max: count - 1) - let range = NSRange.init(location: first, length: last - first + 1) - for i in (0..= 0 && page < pages.count { - if currentPage == page { - return - } - currentPage = page - loadPages(currentPage: currentPage ) - } - - pageViewDelegate?.pageViewDidScroll?(self) - } - - public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { - pageViewDelegate?.pageViewScrollEnd?(self, currentIndex: currentPage, totolPages: pages.count) + // MARK: 辅助方法 + + func raisePageIndexChangedDelegate() { + pageViewDelegate?.pageViewScrollEnd?( + self, + currentIndex: currentPage, + totolPages: pages.count + ) + } +} + +extension EmojiPageView: UIScrollViewDelegate { + public func scrollViewDidScroll(_ scrollView: UIScrollView) { + let width = scrollView.bounds.size.width + let offsetX = scrollView.contentOffset.x + let page = Int(abs(offsetX / width)) + if page >= 0, page < pages.count { + if currentPage == page { + return + } + currentPage = page + loadPages(currentPage: currentPage) } + + pageViewDelegate?.pageViewDidScroll?(self) + } + + public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { + pageViewDelegate?.pageViewScrollEnd?( + self, + currentIndex: currentPage, + totolPages: pages.count + ) + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/Emoji/InputEmoticonContainerView.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/Emoji/InputEmoticonContainerView.swift index b9935808..c23bea98 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/Emoji/InputEmoticonContainerView.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/Emoji/InputEmoticonContainerView.swift @@ -1,342 +1,353 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit @objc public protocol InputEmoticonContainerViewDelegate: AnyObject { - - func selectedEmoticon(emoticonID:String,emotCatalogID:String,description:String) - func didPressSend(sender:UIButton) + func selectedEmoticon(emoticonID: String, emotCatalogID: String, description: String) + func didPressSend(sender: UIButton) } public class InputEmoticonContainerView: UIView { + private let classTag = "InputEmoticonContainerView" + public weak var delegate: InputEmoticonContainerViewDelegate? - private let classTag = "InputEmoticonContainerView" - public weak var delegate: InputEmoticonContainerViewDelegate? - - private var _totalCatalogData:[NIMInputEmoticonCatalog]? - private var totalCatalogData:[NIMInputEmoticonCatalog]? { - set { - _totalCatalogData = newValue - tabView.loadCatalogs(newValue) - } - get { - return _totalCatalogData - } - } - private var _currentCatalogData:NIMInputEmoticonCatalog? - private var currentCatalogData:NIMInputEmoticonCatalog? { - set { - _currentCatalogData = newValue - if let currentData = newValue { - emoticonPageView.scrollToPage(page: pageIndexWithEmoticon(emoticonCatalog: currentData)) - } - } - get { - return _currentCatalogData - } - } - - public override init(frame: CGRect) { - super.init(frame: frame) - setUpSubViews() - loadEmojiData() + private var _totalCatalogData: [NIMInputEmoticonCatalog]? + private var totalCatalogData: [NIMInputEmoticonCatalog]? { + set { + _totalCatalogData = newValue + tabView.loadCatalogs(newValue) } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") + get { + _totalCatalogData } + } - func setUpSubViews(){ - self.addSubview(emoticonPageView) - self.addSubview(tabView) - - NSLayoutConstraint.activate([ - emoticonPageView.topAnchor.constraint(equalTo: self.topAnchor), - emoticonPageView.rightAnchor.constraint(equalTo: self.rightAnchor), - emoticonPageView.leftAnchor.constraint(equalTo: self.leftAnchor), - emoticonPageView.heightAnchor.constraint(equalToConstant: 159) - ]) - - NSLayoutConstraint.activate([ - tabView.bottomAnchor.constraint(equalTo: self.bottomAnchor), - tabView.rightAnchor.constraint(equalTo: self.rightAnchor), - tabView.leftAnchor.constraint(equalTo: self.leftAnchor), - tabView.heightAnchor.constraint(equalToConstant: 35) - ]) + private var _currentCatalogData: NIMInputEmoticonCatalog? + private var currentCatalogData: NIMInputEmoticonCatalog? { + set { + _currentCatalogData = newValue + if let currentData = newValue { + emoticonPageView + .scrollToPage(page: pageIndexWithEmoticon(emoticonCatalog: currentData)) + } } - - func loadEmojiData() { - let data = loadCatalogAndChartlet() - totalCatalogData = data - currentCatalogData = data?.first + get { + _currentCatalogData } + } - - func loadCatalogAndChartlet() -> [NIMInputEmoticonCatalog]?{ - if let cataLog = loadDefaultCatalog() { - return [cataLog] - }else { - return nil - } - } - - //加载默认emoji - func loadDefaultCatalog() -> NIMInputEmoticonCatalog?{ - let emoticonCatalog = NIMInputEmoticonManager.shared.emoticonCatalog(catalogID: NIMKit_EmojiCatalog) - let layout = NIMInputEmoticonLayout.init(width: self.width) - emoticonCatalog?.layout = layout - emoticonCatalog?.pagesCount = numberOfPagesWithEmoticon(emoticonCatalog: emoticonCatalog) - return emoticonCatalog + override public init(frame: CGRect) { + super.init(frame: frame) + setUpSubViews() + loadEmojiData() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func setUpSubViews() { + addSubview(emoticonPageView) + addSubview(tabView) + + NSLayoutConstraint.activate([ + emoticonPageView.topAnchor.constraint(equalTo: topAnchor), + emoticonPageView.rightAnchor.constraint(equalTo: rightAnchor), + emoticonPageView.leftAnchor.constraint(equalTo: leftAnchor), + emoticonPageView.heightAnchor.constraint(equalToConstant: 159), + ]) + + NSLayoutConstraint.activate([ + tabView.bottomAnchor.constraint(equalTo: bottomAnchor), + tabView.rightAnchor.constraint(equalTo: rightAnchor), + tabView.leftAnchor.constraint(equalTo: leftAnchor), + tabView.heightAnchor.constraint(equalToConstant: 35), + ]) + } + + func loadEmojiData() { + let data = loadCatalogAndChartlet() + totalCatalogData = data + currentCatalogData = data?.first + } + + func loadCatalogAndChartlet() -> [NIMInputEmoticonCatalog]? { + if let cataLog = loadDefaultCatalog() { + return [cataLog] + } else { + return nil } - //找到某组表情的起始位置 - func pageIndexWithEmoticon(emoticonCatalog:NIMInputEmoticonCatalog) ->NSInteger{ - - var pageIndex = 0 - if let totalData = totalCatalogData { - for emoticon in totalData { - if emoticon == emoticonCatalog { - break - } - pageIndex += emoticon.pagesCount - } - return pageIndex + } + + // 加载默认emoji + func loadDefaultCatalog() -> NIMInputEmoticonCatalog? { + let emoticonCatalog = NIMInputEmoticonManager.shared + .emoticonCatalog(catalogID: NIMKit_EmojiCatalog) + let layout = NIMInputEmoticonLayout(width: width) + emoticonCatalog?.layout = layout + emoticonCatalog?.pagesCount = numberOfPagesWithEmoticon(emoticonCatalog: emoticonCatalog) + return emoticonCatalog + } + + // 找到某组表情的起始位置 + func pageIndexWithEmoticon(emoticonCatalog: NIMInputEmoticonCatalog) -> NSInteger { + var pageIndex = 0 + if let totalData = totalCatalogData { + for emoticon in totalData { + if emoticon == emoticonCatalog { + break } - return pageIndex + pageIndex += emoticon.pagesCount + } + return pageIndex } - - func pageIndexWithTotalIndex(index:NSInteger) -> NSInteger { - let cateLog = emoticonWithIndex(index: index) - let begin = pageIndexWithEmoticon(emoticonCatalog: cateLog) - return index - begin + return pageIndex + } + + func pageIndexWithTotalIndex(index: NSInteger) -> NSInteger { + let cateLog = emoticonWithIndex(index: index) + let begin = pageIndexWithEmoticon(emoticonCatalog: cateLog) + return index - begin + } + + func emoticonWithIndex(index: NSInteger) -> NIMInputEmoticonCatalog { + var page = 0 + var resultEmotion = NIMInputEmoticonCatalog() + + guard let totalData = totalCatalogData else { + return resultEmotion } - - func emoticonWithIndex(index:NSInteger) -> NIMInputEmoticonCatalog { - var page = 0 - var resultEmotion = NIMInputEmoticonCatalog() - - guard let totalData = totalCatalogData else { - return resultEmotion - } - - for emotion in totalData { - let newPage = page + emotion.pagesCount - if newPage > index{ - resultEmotion = emotion - break; - } - page = newPage - - } - return resultEmotion + + for emotion in totalData { + let newPage = page + emotion.pagesCount + if newPage > index { + resultEmotion = emotion + break + } + page = newPage } - - - func numberOfPagesWithEmoticon(emoticonCatalog:NIMInputEmoticonCatalog?) -> NSInteger { - - if let emotionsCount = emoticonCatalog?.emoticons?.count,let layoutCount = emoticonCatalog?.layout?.itemCountInPage{ - - if emotionsCount % layoutCount == 0 { - return emotionsCount / layoutCount - }else { - return emotionsCount / layoutCount + 1 - } - }else { - NELog.errorLog(classTag, desc: "❌count maybe nil") - return 0 - } + return resultEmotion + } + + func numberOfPagesWithEmoticon(emoticonCatalog: NIMInputEmoticonCatalog?) -> NSInteger { + if let emotionsCount = emoticonCatalog?.emoticons?.count, + let layoutCount = emoticonCatalog?.layout?.itemCountInPage { + if emotionsCount % layoutCount == 0 { + return emotionsCount / layoutCount + } else { + return emotionsCount / layoutCount + 1 + } + } else { + NELog.errorLog(classTag, desc: "❌count maybe nil") + return 0 } - - - //MAKR: lazy method - private lazy var emoticonPageView:EmojiPageView = { - let pageView = EmojiPageView(frame: self.bounds) - pageView.dataSource = self - pageView.pageViewDelegate = self - return pageView - }() - - private lazy var tabView:InputEmoticonTabView = { - let pageView = InputEmoticonTabView.init(frame:CGRect.zero) - pageView.translatesAutoresizingMaskIntoConstraints = false - pageView.delegate = self - pageView.sendButton.addTarget(self, action: #selector(didPressSend), for: .touchUpInside) - return pageView - }() - + } + + // MAKR: lazy method + private lazy var emoticonPageView: EmojiPageView = { + let pageView = EmojiPageView(frame: self.bounds) + pageView.dataSource = self + pageView.pageViewDelegate = self + return pageView + }() + + private lazy var tabView: InputEmoticonTabView = { + let pageView = InputEmoticonTabView(frame: CGRect.zero) + pageView.translatesAutoresizingMaskIntoConstraints = false + pageView.delegate = self + pageView.sendButton.addTarget(self, action: #selector(didPressSend), for: .touchUpInside) + return pageView + }() } +// MARK: ================= config data ================== -//MARK: ================= config data ================== extension InputEmoticonContainerView { - func sumPages() -> NSInteger { - var pagesCount = 0 - - guard let totalData = totalCatalogData else { - return pagesCount - } - for cataLogData in totalData { - pagesCount += cataLogData.pagesCount - } - return pagesCount + func sumPages() -> NSInteger { + var pagesCount = 0 + + guard let totalData = totalCatalogData else { + return pagesCount } - - - func emojiPageView(pageView:EmojiPageView,emoticon:NIMInputEmoticonCatalog,page:NSInteger) -> UIView { - let subView = UIView() - guard let layout = emoticon.layout else { - NELog.errorLog(classTag, desc: "layout is nil") - return UIView.init() - } + for cataLogData in totalData { + pagesCount += cataLogData.pagesCount + } + return pagesCount + } - guard let emotions = emoticon.emoticons else { - NELog.errorLog(classTag, desc: "emoticon.emoticons is nil") - return UIView.init() - } + func emojiPageView(pageView: EmojiPageView, emoticon: NIMInputEmoticonCatalog, + page: NSInteger) -> UIView { + let subView = UIView() + guard let layout = emoticon.layout else { + NELog.errorLog(classTag, desc: "layout is nil") + return UIView() + } - let iconHeight = layout.imageHeight - let iconWidth = layout.imageWidth - let startX = Int(layout.cellWidth - iconWidth)/2 + NIMKit_EmojiLeftMargin - let startY = Int(layout.cellHeight - iconHeight)/2 + NIMKit_EmojiTopMargin - var coloumnIndex = 0 - var rowIndex = 0 - var indexInPage = 0 - let begin = page * layout.itemCountInPage - var end = begin + layout.itemCountInPage - end = end > emotions.count ? emotions.count : end - for i in (begin.. emotions.count ? emotions.count : end + for i in begin ..< end { + let data = emotions[i] + if let id = emoticon.catalogID { + let button = NIMInputEmoticonButton.iconButtonWithData( + data: data, + catalogID: id, + delegate: self + ) + rowIndex = indexInPage / layout.columes + coloumnIndex = indexInPage % layout.columes + let x = coloumnIndex * Int(layout.cellWidth) + startX + let y = rowIndex * Int(layout.cellHeight) + startY + let iconRect = CGRect( + x: CGFloat(x), + y: CGFloat(y), + width: iconWidth, + height: iconHeight + ) + button.frame = iconRect + subView.addSubview(button) + indexInPage += 1 + } } - - - func addDeleteEmotButtonToView(view:UIView,coloumnIndex:NSInteger,rowIndex:NSInteger,startX:CGFloat,startY:CGFloat,iconWidth:CGFloat,iconHeight:CGFloat,emotion:NIMInputEmoticonCatalog) { - - guard let layout = emotion.layout else { - NELog.errorLog(classTag, desc: "❌emotion is nill") - return - } - - let deleteIcon = NIMInputEmoticonButton() - deleteIcon.isUserInteractionEnabled = true - deleteIcon.isExclusiveTouch = true - deleteIcon.contentMode = .center - deleteIcon.delegate = self - deleteIcon.setImage(UIImage.ne_imageNamed(name: "emoji_del_normal"), for: .normal) - deleteIcon.setImage(UIImage.ne_imageNamed(name: "emoji_del_pressed"), for: .highlighted) - deleteIcon.addTarget(self, action: #selector(onIconSelected), for: .touchUpInside) - let newX = CGFloat((coloumnIndex + 1)) * layout.cellWidth + startX - let newY = CGFloat(rowIndex) * layout.cellHeight + startY - let deleteIconRect = CGRect.init(x: newX, y: newY, width: NIMKit_DeleteIconWidth, height: NIMKit_DeleteIconHeight) - deleteIcon.frame = deleteIconRect - view.addSubview(deleteIcon) + + if coloumnIndex == layout.columes - 1 { + rowIndex = rowIndex + 1 + coloumnIndex = -1 // 设置成-1是因为显示在第0位,有加1 } - @objc func onIconSelected(sender:NIMInputEmoticonButton) { - delegate?.selectedEmoticon(emoticonID: "", emotCatalogID: "", description: "") + if emoticon.catalogID == NIMKit_EmojiCatalog { + addDeleteEmotButtonToView( + view: subView, + coloumnIndex: coloumnIndex, + rowIndex: rowIndex, + startX: CGFloat(startX), + startY: CGFloat(startY), + iconWidth: iconWidth, + iconHeight: iconHeight, + emotion: emoticon + ) } - - @objc func didPressSend(sender:UIButton) { - print("did press send") - delegate?.didPressSend(sender: sender) + return subView + } + func addDeleteEmotButtonToView(view: UIView, coloumnIndex: NSInteger, rowIndex: NSInteger, + startX: CGFloat, startY: CGFloat, iconWidth: CGFloat, + iconHeight: CGFloat, emotion: NIMInputEmoticonCatalog) { + guard let layout = emotion.layout else { + NELog.errorLog(classTag, desc: "❌emotion is nill") + return } -} + let deleteIcon = NIMInputEmoticonButton() + deleteIcon.isUserInteractionEnabled = true + deleteIcon.isExclusiveTouch = true + deleteIcon.contentMode = .center + deleteIcon.delegate = self + deleteIcon.setImage(UIImage.ne_imageNamed(name: "emoji_del_normal"), for: .normal) + deleteIcon.setImage(UIImage.ne_imageNamed(name: "emoji_del_pressed"), for: .highlighted) + deleteIcon.addTarget(self, action: #selector(onIconSelected), for: .touchUpInside) + let newX = CGFloat(coloumnIndex + 1) * layout.cellWidth + startX + let newY = CGFloat(rowIndex) * layout.cellHeight + startY + let deleteIconRect = CGRect( + x: newX, + y: newY, + width: NIMKit_DeleteIconWidth, + height: NIMKit_DeleteIconHeight + ) + deleteIcon.frame = deleteIconRect + view.addSubview(deleteIcon) + } + @objc func onIconSelected(sender: NIMInputEmoticonButton) { + delegate?.selectedEmoticon(emoticonID: "", emotCatalogID: "", description: "") + } + @objc func didPressSend(sender: UIButton) { + print("did press send") + delegate?.didPressSend(sender: sender) + } +} -//MARK: ====== EmojiPageViewDelegate,EmojiPageViewDataSource ============== -extension InputEmoticonContainerView:EmojiPageViewDelegate,EmojiPageViewDataSource { +// MARK: ====== EmojiPageViewDelegate,EmojiPageViewDataSource ============== - public func numberOfPages(pageView: EmojiPageView?) -> NSInteger { - return sumPages() - } - - public func pageView(pageView: EmojiPageView?, index: NSInteger) -> UIView { - - var page = 0 - var resultEmotion = NIMInputEmoticonCatalog() - - guard let totalData = totalCatalogData,let targetView = pageView else { - NELog.errorLog(classTag, desc: "❌totalCatalogData is nil") - return UIView.init() - } - - - for emotion in totalData { - let newPage = page + emotion.pagesCount - if newPage > index{ - resultEmotion = emotion - break; - } - page = newPage - } - return emojiPageView(pageView: targetView, emoticon: resultEmotion, page: index - page) - } - +extension InputEmoticonContainerView: EmojiPageViewDelegate, EmojiPageViewDataSource { + public func numberOfPages(pageView: EmojiPageView?) -> NSInteger { + sumPages() + } - public func needScrollAnimation() -> Bool { - return true - } - - public func pageViewDidScroll(_ pageView: EmojiPageView?) { - + public func pageView(pageView: EmojiPageView?, index: NSInteger) -> UIView { + var page = 0 + var resultEmotion = NIMInputEmoticonCatalog() + + guard let totalData = totalCatalogData, let targetView = pageView else { + NELog.errorLog(classTag, desc: "❌totalCatalogData is nil") + return UIView() } - - public func pageViewScrollEnd(_ pageView: EmojiPageView?, currentIndex: Int, totolPages: Int) { -// let emticon = emoticonWithIndex(index: currentIndex) - //补充pageController逻辑 - + + for emotion in totalData { + let newPage = page + emotion.pagesCount + if newPage > index { + resultEmotion = emotion + break + } + page = newPage } + return emojiPageView(pageView: targetView, emoticon: resultEmotion, page: index - page) + } -} + public func needScrollAnimation() -> Bool { + true + } -//MARK: =============== InputEmoticonTabViewDelegate =============== -extension InputEmoticonContainerView:InputEmoticonTabViewDelegate { - - public func tabView(_ tabView: InputEmoticonTabView?, didSelectTabIndex index: Int) { - - } + public func pageViewDidScroll(_ pageView: EmojiPageView?) {} + + public func pageViewScrollEnd(_ pageView: EmojiPageView?, currentIndex: Int, totolPages: Int) { +// let emticon = emoticonWithIndex(index: currentIndex) + // 补充pageController逻辑 + } } -//MARK: =============== InputEmoticonTabViewDelegate =============== -extension InputEmoticonContainerView:NIMInputEmoticonButtonDelegate { +// MARK: =============== InputEmoticonTabViewDelegate =============== - public func selectedEmoticon(emotion: NIMInputEmoticon, catalogID: String) { - - guard let emotionId = emotion.emoticonID else { - NELog.errorLog(classTag, desc: "❌emoticonID is nil") - return - } - if emotion.type == .unicode { - delegate?.selectedEmoticon(emoticonID: emotionId, emotCatalogID: catalogID, description: emotion.unicode ?? "") - }else { - delegate?.selectedEmoticon(emoticonID: emotionId, emotCatalogID: catalogID, description: emotion.tag ?? "") +extension InputEmoticonContainerView: InputEmoticonTabViewDelegate { + public func tabView(_ tabView: InputEmoticonTabView?, didSelectTabIndex index: Int) {} +} - } +// MARK: =============== InputEmoticonTabViewDelegate =============== + +extension InputEmoticonContainerView: NIMInputEmoticonButtonDelegate { + public func selectedEmoticon(emotion: NIMInputEmoticon, catalogID: String) { + guard let emotionId = emotion.emoticonID else { + NELog.errorLog(classTag, desc: "❌emoticonID is nil") + return + } + if emotion.type == .unicode { + delegate?.selectedEmoticon( + emoticonID: emotionId, + emotCatalogID: catalogID, + description: emotion.unicode ?? "" + ) + } else { + delegate?.selectedEmoticon( + emoticonID: emotionId, + emotCatalogID: catalogID, + description: emotion.tag ?? "" + ) } + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/Emoji/InputEmoticonTabView.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/Emoji/InputEmoticonTabView.swift index 54453e8a..398168de 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/Emoji/InputEmoticonTabView.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/Emoji/InputEmoticonTabView.swift @@ -1,95 +1,91 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit @objc public protocol InputEmoticonTabViewDelegate: AnyObject { - - @objc optional func tabView(_ tabView: InputEmoticonTabView?, didSelectTabIndex index: Int) + @objc optional func tabView(_ tabView: InputEmoticonTabView?, didSelectTabIndex index: Int) } - public class InputEmoticonTabView: UIControl { - - public weak var delegate: InputEmoticonTabViewDelegate? - private var tabs = [UIButton]() - private var seps = [UIView]() - private var className = "InputEmoticonTabView" + public weak var delegate: InputEmoticonTabViewDelegate? + private var tabs = [UIButton]() + private var seps = [UIView]() + private var className = "InputEmoticonTabView" + + override public init(frame: CGRect) { + super.init(frame: frame) + setUpSubViews() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func setUpSubViews() { + addSubview(sendButton) + + NSLayoutConstraint.activate([ + sendButton.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -10), + sendButton.rightAnchor.constraint(equalTo: rightAnchor), + sendButton.widthAnchor.constraint(equalToConstant: 60), + sendButton.heightAnchor.constraint(equalToConstant: 32), + ]) + } - public override init(frame: CGRect) { - super.init(frame: frame) - setUpSubViews() + public func selectTabIndex(_ index: Int) { + for i in 0 ..< tabs.count { + let btn = tabs[i] + btn.isSelected = i == index } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") + } + + public func loadCatalogs(_ emoticonCatalogs: [NIMInputEmoticonCatalog]?) { + tabs.forEach { btn in + btn.removeFromSuperview() } - - func setUpSubViews(){ - self.addSubview(sendButton) - - NSLayoutConstraint.activate([ - sendButton.bottomAnchor.constraint(equalTo: self.bottomAnchor,constant: -10), - sendButton.rightAnchor.constraint(equalTo: self.rightAnchor), - sendButton.widthAnchor.constraint(equalToConstant: 60), - sendButton.heightAnchor.constraint(equalToConstant: 32) - ]) + seps.forEach { view in + view.removeFromSuperview() } - - public func selectTabIndex(_ index: Int) { - for i in 0..NSMutableAttributedString { - let regular = "\\[[^\\[|^\\]]+\\]" - - var reExpression: NSRegularExpression? = nil - do { - reExpression = try NSRegularExpression(pattern: regular, options: .caseInsensitive) - } catch { - } - //找出所有符合正则的位置集合 - let regularArr = reExpression?.matches(in: str, options: .reportProgress, range: NSRange.init(location: 0, length: str.count)) - - let emoticons = NIMInputEmoticonManager.shared.emoticonCatalog(catalogID: NIMKit_EmojiCatalog)?.emoticons - let attStr = NSMutableAttributedString(string: str, attributes: [ - NSAttributedString.Key.font: font, - .foregroundColor:NEKitChatConfig.shared.ui.messageColor - ]) - - if let regArr = regularArr,regArr.count > 0,let targetEmotions = emoticons { - for i in (0...regArr.count - 1).reversed() { - let result = regArr[i] - - for (idx,obj) in targetEmotions.enumerated() { - let ocStr = str as NSString - if ocStr.substring(with: result.range) == obj.tag { - attStr.replaceCharacters(in: result.range, with: getAttWithEmotion(emotion: obj, font: font, offset: offset)) - break - } - } - } - + class func getAttWithStr(str: String, font: UIFont, + _ offset: CGPoint = CGPoint(x: 0, y: -3)) -> NSMutableAttributedString { + let regular = "\\[[^\\[|^\\]]+\\]" + + var reExpression: NSRegularExpression? + do { + reExpression = try NSRegularExpression(pattern: regular, options: .caseInsensitive) + } catch {} + // 找出所有符合正则的位置集合 + let regularArr = reExpression?.matches( + in: str, + options: .reportProgress, + range: NSRange(location: 0, length: str.count) + ) + + let emoticons = NIMInputEmoticonManager.shared + .emoticonCatalog(catalogID: NIMKit_EmojiCatalog)?.emoticons + let attStr = NSMutableAttributedString(string: str, attributes: [ + NSAttributedString.Key.font: font, + .foregroundColor: NEKitChatConfig.shared.ui.messageColor, + ]) + + if let regArr = regularArr, regArr.count > 0, let targetEmotions = emoticons { + for i in (0 ... regArr.count - 1).reversed() { + let result = regArr[i] + + for (idx, obj) in targetEmotions.enumerated() { + let ocStr = str as NSString + if ocStr.substring(with: result.range) == obj.tag { + attStr.replaceCharacters( + in: result.range, + with: getAttWithEmotion(emotion: obj, font: font, offset: offset) + ) + break + } } - return attStr - } - class func getAttWithEmotion(emotion:NIMInputEmoticon,font:UIFont,offset: CGPoint) ->NSAttributedString { - let textAttachment = NEEmotionAttachment() - textAttachment.emotion = emotion - let height = font.lineHeight - textAttachment.bounds = CGRect.init(x: offset.x, y: offset.y, width: height, height: height) - return NSAttributedString.init(attachment: textAttachment) + } } + return attStr + } + + class func getAttWithEmotion(emotion: NIMInputEmoticon, font: UIFont, + offset: CGPoint) -> NSAttributedString { + let textAttachment = NEEmotionAttachment() + textAttachment.emotion = emotion + let height = font.lineHeight + textAttachment.bounds = CGRect(x: offset.x, y: offset.y, width: height, height: height) + return NSAttributedString(attachment: textAttachment) + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/Emoji/NIMInputEmoticonButton.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/Emoji/NIMInputEmoticonButton.swift index ad781a93..b932bff4 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/Emoji/NIMInputEmoticonButton.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/Emoji/NIMInputEmoticonButton.swift @@ -1,54 +1,49 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit - - public protocol NIMInputEmoticonButtonDelegate: AnyObject { - - func selectedEmoticon(emotion:NIMInputEmoticon,catalogID:String) - +public protocol NIMInputEmoticonButtonDelegate: AnyObject { + func selectedEmoticon(emotion: NIMInputEmoticon, catalogID: String) } public class NIMInputEmoticonButton: UIButton { + public var emotionData: NIMInputEmoticon? + public var catalogID: String? + public weak var delegate: NIMInputEmoticonButtonDelegate? + private let classsTag = "NIMInputEmoticonButton" - public var emotionData:NIMInputEmoticon? - public var catalogID:String? - public weak var delegate:NIMInputEmoticonButtonDelegate? - private let classsTag = "NIMInputEmoticonButton" - - class public func iconButtonWithData(data:NIMInputEmoticon,catalogID:String,delegate:NIMInputEmoticonButtonDelegate) -> NIMInputEmoticonButton{ - let icon = NIMInputEmoticonButton.init() - icon.addTarget(icon, action: #selector(onIconSelected), for: .touchUpInside) - icon.emotionData = data - icon.catalogID = catalogID - icon.isUserInteractionEnabled = true - icon.isExclusiveTouch = true - icon.contentMode = .scaleToFill - icon.delegate = delegate - switch data.type { - case .unicode: - icon.setTitle(data.unicode, for: .normal) - icon.setTitle(data.unicode, for: .highlighted) - icon.titleLabel?.font = DefaultTextFont(32) - break - default: - let image = UIImage.ne_bundleImage(name: data.fileName ?? "") - icon.setImage(image, for: .normal) - icon.setImage(image, for: .highlighted) - break - } - return icon + public class func iconButtonWithData(data: NIMInputEmoticon, catalogID: String, + delegate: NIMInputEmoticonButtonDelegate) + -> NIMInputEmoticonButton { + let icon = NIMInputEmoticonButton() + icon.addTarget(icon, action: #selector(onIconSelected), for: .touchUpInside) + icon.emotionData = data + icon.catalogID = catalogID + icon.isUserInteractionEnabled = true + icon.isExclusiveTouch = true + icon.contentMode = .scaleToFill + icon.delegate = delegate + switch data.type { + case .unicode: + icon.setTitle(data.unicode, for: .normal) + icon.setTitle(data.unicode, for: .highlighted) + icon.titleLabel?.font = DefaultTextFont(32) + default: + let image = UIImage.ne_bundleImage(name: data.fileName ?? "") + icon.setImage(image, for: .normal) + icon.setImage(image, for: .highlighted) } - - @objc func onIconSelected(sender:NIMInputEmoticonButton) { - - guard let data = emotionData,let id = catalogID else { - NELog.errorLog(classsTag, desc: "emotionData or catalogID maybe nil") - return - } - delegate?.selectedEmoticon(emotion: data, catalogID: id) + return icon + } + + @objc func onIconSelected(sender: NIMInputEmoticonButton) { + guard let data = emotionData, let id = catalogID else { + NELog.errorLog(classsTag, desc: "emotionData or catalogID maybe nil") + return } - + delegate?.selectedEmoticon(emotion: data, catalogID: id) + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/Emoji/NIMInputEmoticonDefine.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/Emoji/NIMInputEmoticonDefine.swift index 429ee709..ae7ef323 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/Emoji/NIMInputEmoticonDefine.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/Emoji/NIMInputEmoticonDefine.swift @@ -1,10 +1,10 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation - public let NIMKit_EmojiCatalog = "default" public let NIMKit_EmojiPath = "Emoji" public let NIMKit_ChartletChartletCatalogPath = "Chartlet" @@ -13,7 +13,6 @@ public let NIMKit_ChartletChartletCatalogIconPath = "icon" public let NIMKit_ChartletChartletCatalogIconsSuffixNormal = "normal" public let NIMKit_ChartletChartletCatalogIconsSuffixHighLight = "highlighted" - public let NIMKit_EmojiLeftMargin = 8 public let NIMKit_EmojiRightMargin = 8 public let NIMKit_EmojiTopMargin = 14 @@ -24,7 +23,7 @@ public let NIMKit_EmojImageHeight = 43.0 public let NIMKit_EmojImageWidth = 43.0 public let NIMKit_EmojRows = 3 -//贴图 +// 贴图 public let NIMKit_PicCellHeight = 76.0 public let NIMKit_PicImageHeight = 70.0 public let NIMKit_PicImageWidth = 70.0 diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/Emoji/NIMInputEmoticonManager.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/Emoji/NIMInputEmoticonManager.swift index 45c4ac2c..08ea7fd6 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/Emoji/NIMInputEmoticonManager.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/Emoji/NIMInputEmoticonManager.swift @@ -1,225 +1,210 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit -public enum NIMEmoticonType:NSInteger { - case file = 0 - case unicode - +public enum NIMEmoticonType: NSInteger { + case file = 0 + case unicode } -public class NIMInputEmoticon:NSObject { - - public var type:NIMEmoticonType { - get { - if let ucode = unicode,ucode.count>0 { - return .unicode - }else { - return .file - } - } +public class NIMInputEmoticon: NSObject { + public var type: NIMEmoticonType { + if let ucode = unicode, ucode.count > 0 { + return .unicode + } else { + return .file } - public var emoticonID:String? - public var tag:String? - public var fileName:String? - public var unicode:String? -} + } + public var emoticonID: String? + public var tag: String? + public var fileName: String? + public var unicode: String? +} -public class NIMInputEmoticonLayout:NSObject { - public var rows:NSInteger = 0 //行数 - public var columes:NSInteger = 0 //列数 - public var itemCountInPage:NSInteger = 0 //每页显示几项 - public var cellWidth:CGFloat = 0 //单个单元格宽 - public var cellHeight:CGFloat = 0 //单个单元格高 - public var imageWidth:CGFloat = 0 //显示图片的宽 - public var imageHeight:CGFloat = 0 //显示图片的高 - public var emoji:Bool? - - public init(width:CGFloat) { - rows = NIMKit_EmojRows - columes = ((Int(width) - NIMKit_EmojiLeftMargin - NIMKit_EmojiRightMargin) / Int(NIMKit_EmojImageWidth)) - itemCountInPage = rows * columes - 1 - cellWidth = CGFloat((Int(width) - NIMKit_EmojiLeftMargin - NIMKit_EmojiRightMargin) / columes) - cellHeight = NIMKit_EmojCellHeight - imageWidth = NIMKit_EmojImageWidth - imageHeight = NIMKit_EmojImageHeight - emoji = true; - } - +public class NIMInputEmoticonLayout: NSObject { + public var rows: NSInteger = 0 // 行数 + public var columes: NSInteger = 0 // 列数 + public var itemCountInPage: NSInteger = 0 // 每页显示几项 + public var cellWidth: CGFloat = 0 // 单个单元格宽 + public var cellHeight: CGFloat = 0 // 单个单元格高 + public var imageWidth: CGFloat = 0 // 显示图片的宽 + public var imageHeight: CGFloat = 0 // 显示图片的高 + public var emoji: Bool? + + public init(width: CGFloat) { + rows = NIMKit_EmojRows + columes = + ((Int(width) - NIMKit_EmojiLeftMargin - NIMKit_EmojiRightMargin) / + Int(NIMKit_EmojImageWidth)) + itemCountInPage = rows * columes - 1 + cellWidth = + CGFloat((Int(width) - NIMKit_EmojiLeftMargin - NIMKit_EmojiRightMargin) / columes) + cellHeight = NIMKit_EmojCellHeight + imageWidth = NIMKit_EmojImageWidth + imageHeight = NIMKit_EmojImageHeight + emoji = true + } } public class NIMInputEmoticonCatalog: NSObject { - - public var layout:NIMInputEmoticonLayout? - public var catalogID:String? - public var title:String? - public var id2Emoticons:[String:NIMInputEmoticon]? - public var tag2Emoticons:[String:NIMInputEmoticon]? - public var emoticons:[NIMInputEmoticon]? - /// 图标 - public var icon:String? - /// 小图标按下效果 - public var iconPressed:String? - /// 分页数 - public var pagesCount:NSInteger = 0 - + public var layout: NIMInputEmoticonLayout? + public var catalogID: String? + public var title: String? + public var id2Emoticons: [String: NIMInputEmoticon]? + public var tag2Emoticons: [String: NIMInputEmoticon]? + public var emoticons: [NIMInputEmoticon]? + /// 图标 + public var icon: String? + /// 小图标按下效果 + public var iconPressed: String? + /// 分页数 + public var pagesCount: NSInteger = 0 } - public class NIMInputEmoticonManager: NSObject { - public static let shared = NIMInputEmoticonManager() - private var catalogs:[NIMInputEmoticonCatalog]? - private var classTag = "NIMInputEmoticonManager" - - public override init() { - super.init() - parsePlist() - preloadEmoticonResource() - } - - func parsePlist() { - var catalogs = [NIMInputEmoticonCatalog]() - let filePath = Bundle.nim_EmojiPlistFile() - if let path = filePath { - let array = NSArray.init(contentsOfFile: path) - array?.forEach({ dict in - if let convertDict = (dict as? NSDictionary) { - let info = convertDict["info"] as? Dictionary - let emotions = convertDict["data"] as? NSArray - let cataLog = catalogByInfo(info: info as NSDictionary?, emoticonsArray: emotions) - catalogs.append(cataLog) - } - }) + public static let shared = NIMInputEmoticonManager() + private var catalogs: [NIMInputEmoticonCatalog]? + private var classTag = "NIMInputEmoticonManager" + + override public init() { + super.init() + parsePlist() + preloadEmoticonResource() + } + + func parsePlist() { + var catalogs = [NIMInputEmoticonCatalog]() + let filePath = Bundle.nim_EmojiPlistFile() + if let path = filePath { + let array = NSArray(contentsOfFile: path) + array?.forEach { dict in + if let convertDict = (dict as? NSDictionary) { + let info = convertDict["info"] as? [String: Any] + let emotions = convertDict["data"] as? NSArray + let cataLog = catalogByInfo( + info: info as NSDictionary?, + emoticonsArray: emotions + ) + catalogs.append(cataLog) } - self.catalogs = catalogs + } } - - func catalogByInfo(info:NSDictionary?,emoticonsArray:NSArray?) -> NIMInputEmoticonCatalog { - - let cataLog = NIMInputEmoticonCatalog.init() - - guard let infoDict = info ,let emotions = emoticonsArray else { - NELog.errorLog(classTag, desc: "❌info or emoticonsArray is nil") - return cataLog + self.catalogs = catalogs + } + + func catalogByInfo(info: NSDictionary?, emoticonsArray: NSArray?) -> NIMInputEmoticonCatalog { + let cataLog = NIMInputEmoticonCatalog() + + guard let infoDict = info, let emotions = emoticonsArray else { + NELog.errorLog(classTag, desc: "❌info or emoticonsArray is nil") + return cataLog + } + cataLog.catalogID = infoDict["id"] as? String + cataLog.title = infoDict["title"] as? String + cataLog.icon = infoDict["normal"] as? String + cataLog.iconPressed = infoDict["pressed"] as? String + var tag2Emoticons = [String: NIMInputEmoticon]() + var id2Emoticons = [String: NIMInputEmoticon]() + var resultEmotions = [NIMInputEmoticon]() + + emotions.forEach { emoticonDict in + if let dict = (emoticonDict as? NSDictionary) { + let emotion = NIMInputEmoticon() + emotion.emoticonID = dict["id"] as? String + emotion.tag = dict["tag"] as? String + emotion.unicode = dict["unicode"] as? String + emotion.fileName = dict["file"] as? String + + if let id = emotion.emoticonID, id.count > 0 { + resultEmotions.append(emotion) + id2Emoticons[id] = emotion } - cataLog.catalogID = infoDict["id"] as? String - cataLog.title = infoDict["title"] as? String - cataLog.icon = infoDict["normal"] as? String - cataLog.iconPressed = infoDict["pressed"] as? String - var tag2Emoticons = [String:NIMInputEmoticon]() - var id2Emoticons = [String:NIMInputEmoticon]() - var resultEmotions = [NIMInputEmoticon]() - - emotions.forEach { emoticonDict in - if let dict = (emoticonDict as? NSDictionary ){ - let emotion = NIMInputEmoticon.init() - emotion.emoticonID = dict["id"] as? String - emotion.tag = dict["tag"] as? String - emotion.unicode = dict["unicode"] as? String - emotion.fileName = dict["file"] as? String - - if let id = emotion.emoticonID,id.count>0 { - resultEmotions.append(emotion) - id2Emoticons[id] = emotion - } - if let tag = emotion.tag,tag.count > 0 { - tag2Emoticons[tag] = emotion - } - } - + if let tag = emotion.tag, tag.count > 0 { + tag2Emoticons[tag] = emotion } - cataLog.emoticons = resultEmotions - cataLog.id2Emoticons = id2Emoticons - cataLog.tag2Emoticons = tag2Emoticons - return cataLog + } } - - func preloadEmoticonResource(){ - + cataLog.emoticons = resultEmotions + cataLog.id2Emoticons = id2Emoticons + cataLog.tag2Emoticons = tag2Emoticons + return cataLog + } + + func preloadEmoticonResource() {} + + public func emoticonCatalog(catalogID: String) -> NIMInputEmoticonCatalog? { + guard let infos = catalogs else { return nil } + + for catalog in infos { + if catalog.catalogID == catalogID { + return catalog + } } - - public func emoticonCatalog(catalogID:String) ->NIMInputEmoticonCatalog? { - - guard let infos = catalogs else { return nil} - - for catalog in infos { - if catalog.catalogID == catalogID { - return catalog - } - } - return nil + return nil + } + + public func emoticonByTag(tag: String) -> NIMInputEmoticon? { + var emotion: NIMInputEmoticon? + + guard let clogs = catalogs else { + NELog.errorLog(classTag, desc: "❌catalogs is nil") + return emotion } - - public func emoticonByTag(tag:String) ->NIMInputEmoticon? { - var emotion : NIMInputEmoticon? - - guard let clogs = catalogs else { - NELog.errorLog(classTag, desc: "❌catalogs is nil") - return emotion - } - - if tag.count > 0 { - for catalog in clogs { - if let tag2Emotions = catalog.tag2Emoticons { - emotion = tag2Emotions[tag] - if let _ = emotion { - break - } - } - } + + if tag.count > 0 { + for catalog in clogs { + if let tag2Emotions = catalog.tag2Emoticons { + emotion = tag2Emotions[tag] + if let _ = emotion { + break + } } - return emotion + } } - - - - public func emoticonByID(emoticonID:String) ->NIMInputEmoticon? { - - var emotion : NIMInputEmoticon? - guard let clogs = catalogs else { - NELog.errorLog(classTag, desc: "❌catalogs is nil") - return emotion - } - - if emoticonID.count > 0 { - for catalog in clogs { - if let id2Emoticons = catalog.id2Emoticons { - emotion = id2Emoticons[emoticonID] - if let _ = emotion { - break - } - } - } - } - return emotion + return emotion + } + + public func emoticonByID(emoticonID: String) -> NIMInputEmoticon? { + var emotion: NIMInputEmoticon? + guard let clogs = catalogs else { + NELog.errorLog(classTag, desc: "❌catalogs is nil") + return emotion } - - public func emoticonByCatalogID(catalogID:String,emoticonID:String) ->NIMInputEmoticon? { - var emotion : NIMInputEmoticon? - guard let clogs = catalogs else { - NELog.errorLog(classTag, desc: "❌catalogs is nil") - return emotion - } - - if catalogID.count > 0 && emoticonID.count > 0 { - for catalog in clogs { - if catalog.catalogID == catalogID { - - if let id2Emoticons = catalog.id2Emoticons { - emotion = id2Emoticons[emoticonID] - break - } - } - } + if emoticonID.count > 0 { + for catalog in clogs { + if let id2Emoticons = catalog.id2Emoticons { + emotion = id2Emoticons[emoticonID] + if let _ = emotion { + break + } } - return emotion - - + } + } + return emotion + } + + public func emoticonByCatalogID(catalogID: String, emoticonID: String) -> NIMInputEmoticon? { + var emotion: NIMInputEmoticon? + guard let clogs = catalogs else { + NELog.errorLog(classTag, desc: "❌catalogs is nil") + return emotion } - + if catalogID.count > 0, emoticonID.count > 0 { + for catalog in clogs { + if catalog.catalogID == catalogID { + if let id2Emoticons = catalog.id2Emoticons { + emotion = id2Emoticons[emoticonID] + break + } + } + } + } + return emotion + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/Helper/ChatMessageHelper.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/Helper/ChatMessageHelper.swift index 424ceed4..2b8dade0 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/Helper/ChatMessageHelper.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/Helper/ChatMessageHelper.swift @@ -1,35 +1,35 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation class ChatMessageHelper { - //获取图片合适尺寸 - class func getSizeWithMaxSize(_ maxSize: CGSize, size: CGSize,miniWH:CGFloat) -> CGSize { - - var realSize = CGSize.zero - - if min(size.width, size.height) > 0 { - if size.width > size.height { - //宽大 按照宽给高 - let width = CGFloat(min(maxSize.width, size.width)) - realSize = CGSize(width: width, height: width * size.height / size.width) - if realSize.height < miniWH { - realSize.height = miniWH - } - } else { - //高大 按照高给宽 - let height = CGFloat(min(maxSize.height, size.height)) - realSize = CGSize(width: height * size.width / size.height, height: height) - if realSize.width < miniWH { - realSize.width = miniWH - } - } - }else { - realSize = maxSize + // 获取图片合适尺寸 + class func getSizeWithMaxSize(_ maxSize: CGSize, size: CGSize, miniWH: CGFloat) -> CGSize { + var realSize = CGSize.zero + + if min(size.width, size.height) > 0 { + if size.width > size.height { + // 宽大 按照宽给高 + let width = CGFloat(min(maxSize.width, size.width)) + realSize = CGSize(width: width, height: width * size.height / size.width) + if realSize.height < miniWH { + realSize.height = miniWH + } + } else { + // 高大 按照高给宽 + let height = CGFloat(min(maxSize.height, size.height)) + realSize = CGSize(width: height * size.width / size.height, height: height) + if realSize.width < miniWH { + realSize.width = miniWH } - - return realSize + } + } else { + realSize = maxSize } + + return realSize + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/Helper/MessageUtils.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/Helper/MessageUtils.swift index 6e93716b..4d745f29 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/Helper/MessageUtils.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/Helper/MessageUtils.swift @@ -1,62 +1,62 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NIMSDK import NEKitCoreIM public class MessageUtils { - - public class func textMessage(text: String) -> NIMMessage { - let message = NIMMessage() - message.setting = self.messageSetting() - message.text = text - return message - } - - public class func imageMessage(image: UIImage) -> NIMMessage { - return imageMessage(imageObject: NIMImageObject(image: image)) - } - - public class func imageMessage(path: String) -> NIMMessage { - return imageMessage(imageObject: NIMImageObject(filepath: path)) - } - - public class func imageMessage(imageObject: NIMImageObject) -> NIMMessage { - let message = NIMMessage() - let option = NIMImageOption() - option.compressQuality = 0.8 - imageObject.option = option - message.messageObject = imageObject - message.apnsContent = localizable("发来了一张图片") - message.setting = self.messageSetting() - return message - } - - public class func audioMessage(filePath: String) -> NIMMessage { - let messageObject = NIMAudioObject(sourcePath: filePath) - let message = NIMMessage() - message.messageObject = messageObject - message.apnsContent = localizable("发来了一段语音") - message.setting = self.messageSetting() - return message - } - - public class func videoMessage(filePath: String) -> NIMMessage { - let messageObject = NIMVideoObject(sourcePath: filePath) - let message = NIMMessage() - message.messageObject = messageObject - message.apnsContent = localizable("发来了一段视频") - message.setting = self.messageSetting() - return message - } - - public class func messageSetting() -> NIMMessageSetting { - let setting = NIMMessageSetting() - print("getMessageRead: \(SettingProvider.shared.getMessageRead())") + public class func textMessage(text: String) -> NIMMessage { + let message = NIMMessage() + message.setting = messageSetting() + message.text = text + return message + } + + public class func imageMessage(image: UIImage) -> NIMMessage { + imageMessage(imageObject: NIMImageObject(image: image)) + } + + public class func imageMessage(path: String) -> NIMMessage { + imageMessage(imageObject: NIMImageObject(filepath: path)) + } + + public class func imageMessage(imageObject: NIMImageObject) -> NIMMessage { + let message = NIMMessage() + let option = NIMImageOption() + option.compressQuality = 0.8 + imageObject.option = option + message.messageObject = imageObject + message.apnsContent = localizable("发来了一张图片") + message.setting = messageSetting() + return message + } + + public class func audioMessage(filePath: String) -> NIMMessage { + let messageObject = NIMAudioObject(sourcePath: filePath) + let message = NIMMessage() + message.messageObject = messageObject + message.apnsContent = localizable("发来了一段语音") + message.setting = messageSetting() + return message + } + + public class func videoMessage(filePath: String) -> NIMMessage { + let messageObject = NIMVideoObject(sourcePath: filePath) + let message = NIMMessage() + message.messageObject = messageObject + message.apnsContent = localizable("发来了一段视频") + message.setting = messageSetting() + return message + } + + public class func messageSetting() -> NIMMessageSetting { + let setting = NIMMessageSetting() + print("getMessageRead: \(SettingProvider.shared.getMessageRead())") // FIXME: - setting.teamReceiptEnabled = SettingProvider.shared.getMessageRead() - return setting - } + setting.teamReceiptEnabled = SettingProvider.shared.getMessageRead() + return setting + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/Helper/NotificationMessageUtils.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/Helper/NotificationMessageUtils.swift index 1bc2571b..0e637c91 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/Helper/NotificationMessageUtils.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/Helper/NotificationMessageUtils.swift @@ -1,189 +1,206 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NIMSDK import NEKitCoreIM import NEKitCore public class NotificationMessageUtils { - public class func textForNotification(message: NIMMessage) -> String { - if message.messageType != .notification { - return "" - } - if let object = message.messageObject as? NIMNotificationObject { - switch object.notificationType { - case .team: - return self.textForTeamNotificationMessage(message: message) - case .superTeam: - return "" - case .netCall: - return "" - case .chatroom: - return "" - default: - return "" - } - } - return "" + public class func textForNotification(message: NIMMessage) -> String { + if message.messageType != .notification { + return "" } - - public class func textForTeamNotificationMessage(message: NIMMessage) -> String { - var text = localizable("unknown_system_message") - if let object = message.messageObject as? NIMNotificationObject { - if let content = object.content as? NIMTeamNotificationContent { - let fromName = self.fromName(message: message) - let toNames = self.toName(message: message) - let toFirstName = toNames.first ?? "" - let teamName = self.teamName(message: message) - var toNamestext = toNames.first ?? "" - if toNames.count > 1 { - toNamestext = toNames.joined(separator: ",") - } - switch content.operationType { - case .invite: - var str = fromName + localizable("invite") - if let first = toNames.first { - str = str + first - } - if toNames.count > 1 { - str = str + " " + String(toNames.count) + " " + localizable("humans") - } - str = str + localizable("enter") + teamName - text = str - case .dismiss: - text = fromName + localizable("dissolve") + teamName - case .kick: - var str = fromName + localizable("kick") - if let first = toNames.first { - str = str + first - } - if toNames.count > 1 { - str = str + " " + String(toNames.count) + " " + localizable("humans") - } - str = str + localizable("out") + teamName - text = str - - case .update: - text = textOfUpdateTeam(fromName: fromName, teamName: teamName, content: content) - case .leave: - text = fromName + localizable("leave") + teamName - case .applyPass: - if fromName == toNamestext { - text = fromName + localizable("join") + teamName - }else { - text = fromName + localizable("pass") + toNamestext - } - - case .transferOwner: - text = fromName + localizable("transfer") + toFirstName - case .addManager: - text = toFirstName + localizable("added_manager") - case .removeManager: - text = toFirstName + localizable("removed_mamager") - case .acceptInvitation: - text = fromName + localizable("accept") + toNamestext - case .mute: - var mute = false - if let atta = content.attachment as? NIMMuteTeamMemberAttachment { - mute = atta.flag - } - if let atta = content.attachment as? NIMMuteSuperTeamMemberAttachment { - mute = atta.flag - } - text = mute ? localizable("team_all_mute") : localizable("team_all_no_mute") - - default: - text = localizable("unknown_system_message") - } - - } - } - return text - } - - public class func fromName(message: NIMMessage) -> String { - if let object = message.messageObject as? NIMNotificationObject { - if let content = object.content as? NIMTeamNotificationContent { - if content.sourceID == NIMSDK.shared().loginManager.currentAccount() { - return localizable("You") - }else { - if let sourceId = content.sourceID { - let user = UserInfoProvider.shared.getUserInfo(userId: sourceId) - return user?.showName() ?? "" - } - } - } - } + if let object = message.messageObject as? NIMNotificationObject { + switch object.notificationType { + case .team: + return textForTeamNotificationMessage(message: message) + case .superTeam: return "" + case .netCall: + return "" + case .chatroom: + return "" + default: + return "" + } } - - public class func toName(message: NIMMessage) -> [String] { - var toNames = [String]() - guard let object = message.messageObject as? NIMNotificationObject, let content = object.content as? NIMTeamNotificationContent,let targetIDs = content.targetIDs else { - return toNames + return "" + } + + public class func textForTeamNotificationMessage(message: NIMMessage) -> String { + var text = localizable("unknown_system_message") + if let object = message.messageObject as? NIMNotificationObject { + if let content = object.content as? NIMTeamNotificationContent { + let fromName = fromName(message: message) + let toNames = toName(message: message) + let toFirstName = toNames.first ?? "" + let teamName = teamName(message: message) + var toNamestext = toNames.first ?? "" + if toNames.count > 1 { + toNamestext = toNames.joined(separator: ",") } - for targetID in targetIDs { - if targetID == NIMSDK.shared().loginManager.currentAccount() { - toNames.append(localizable("You")) - }else { - toNames.append(UserInfoProvider.shared.getUserInfo(userId: targetID)?.showName() ?? "") - } + switch content.operationType { + case .invite: + var str = fromName + localizable("invite") + if let first = toNames.first { + str = str + first + } + if toNames.count > 1 { + str = str + " " + String(toNames.count) + " " + localizable("humans") + } + str = str + localizable("enter") + teamName + text = str + case .dismiss: + text = fromName + localizable("dissolve") + teamName + case .kick: + var str = fromName + localizable("kick") + if let first = toNames.first { + str = str + first + } + if toNames.count > 1 { + str = str + " " + String(toNames.count) + " " + localizable("humans") + } + str = str + localizable("out") + teamName + text = str + + case .update: + text = textOfUpdateTeam( + fromName: fromName, + teamName: teamName, + content: content + ) + case .leave: + text = fromName + localizable("leave") + teamName + case .applyPass: + if fromName == toNamestext { + text = fromName + localizable("join") + teamName + } else { + text = fromName + localizable("pass") + toNamestext + } + + case .transferOwner: + text = fromName + localizable("transfer") + toFirstName + case .addManager: + text = toFirstName + localizable("added_manager") + case .removeManager: + text = toFirstName + localizable("removed_mamager") + case .acceptInvitation: + text = fromName + localizable("accept") + toNamestext + case .mute: + var mute = false + if let atta = content.attachment as? NIMMuteTeamMemberAttachment { + mute = atta.flag + } + if let atta = content.attachment as? NIMMuteSuperTeamMemberAttachment { + mute = atta.flag + } + text = mute ? localizable("team_all_mute") : localizable("team_all_no_mute") + + default: + text = localizable("unknown_system_message") } - return toNames + } } - - public class func teamName(message: NIMMessage) -> String { - let team = TeamProvider.shared.teamInfo(teamId: message.session?.sessionId) - if team?.type == .normalTeam { - return localizable("discussion_group") - }else { - return localizable("group") + return text + } + + public class func fromName(message: NIMMessage) -> String { + if let object = message.messageObject as? NIMNotificationObject { + if let content = object.content as? NIMTeamNotificationContent { + if content.sourceID == NIMSDK.shared().loginManager.currentAccount() { + return localizable("You") + } else { + if let sourceId = content.sourceID { + let user = UserInfoProvider.shared.getUserInfo(userId: sourceId) + return user?.showName() ?? "" + } } + } } - - private class func textOfUpdateTeam(fromName:String, teamName: String, content: NIMTeamNotificationContent) -> String { - var text = fromName + localizable("has_updated") + teamName - guard let attach = content.attachment as? NIMUpdateTeamInfoAttachment else { - return text - } - if attach.values?.count == 1 { - let tag = attach.values?.keys.first?.intValue - switch tag { - case 3: - text = fromName + localizable("has_updated") + teamName + " " + localizable("team_name") - case 14: - text = fromName + localizable("has_updated") + teamName + " " + localizable("team_intro") - case 15: - text = fromName + localizable("has_updated") + teamName + " " + localizable("team_anouncement") - case 16: - text = fromName + localizable("has_updated") + teamName + " " + localizable("team_join_mode") - case 18: - text = fromName + localizable("has_updated") + " " + localizable("team_custom_info") - case 19: - text = fromName + localizable("has_updated") + " " + localizable("team_custom_info") - case 20: - text = fromName + localizable("has_updated") + teamName + " " + localizable("team_avatar") - case 21: - text = fromName + localizable("has_updated") + " " + localizable("team_be_invited_author") - case 22: - text = fromName + localizable("has_updated") + " " + localizable("team_be_invited_permission") - case 23: - text = fromName + localizable("has_updated") + " " + localizable("team_update_info_permission") - case 24: - text = fromName + localizable("has_updated") + " " + localizable("team_update_client_custom") - case 100: - let muteState = attach.values?.values.first + return "" + } + + public class func toName(message: NIMMessage) -> [String] { + var toNames = [String]() + guard let object = message.messageObject as? NIMNotificationObject, + let content = object.content as? NIMTeamNotificationContent, + let targetIDs = content.targetIDs else { + return toNames + } + for targetID in targetIDs { + if targetID == NIMSDK.shared().loginManager.currentAccount() { + toNames.append(localizable("You")) + } else { + toNames + .append(UserInfoProvider.shared.getUserInfo(userId: targetID)?.showName() ?? "") + } + } + return toNames + } + + public class func teamName(message: NIMMessage) -> String { + let team = TeamProvider.shared.teamInfo(teamId: message.session?.sessionId) + if team?.type == .normalTeam { + return localizable("discussion_group") + } else { + return localizable("group") + } + } + + private class func textOfUpdateTeam(fromName: String, teamName: String, + content: NIMTeamNotificationContent) -> String { + var text = fromName + localizable("has_updated") + teamName + guard let attach = content.attachment as? NIMUpdateTeamInfoAttachment else { + return text + } + if attach.values?.count == 1 { + let tag = attach.values?.keys.first?.intValue + switch tag { + case 3: + text = fromName + localizable("has_updated") + teamName + " " + + localizable("team_name") + case 14: + text = fromName + localizable("has_updated") + teamName + " " + + localizable("team_intro") + case 15: + text = fromName + localizable("has_updated") + teamName + " " + + localizable("team_anouncement") + case 16: + text = fromName + localizable("has_updated") + teamName + " " + + localizable("team_join_mode") + case 18: + text = fromName + localizable("has_updated") + " " + localizable("team_custom_info") + case 19: + text = fromName + localizable("has_updated") + " " + localizable("team_custom_info") + case 20: + text = fromName + localizable("has_updated") + teamName + " " + + localizable("team_avatar") + case 21: + text = fromName + localizable("has_updated") + " " + + localizable("team_be_invited_author") + case 22: + text = fromName + localizable("has_updated") + " " + + localizable("team_be_invited_permission") + case 23: + text = fromName + localizable("has_updated") + " " + + localizable("team_update_info_permission") + case 24: + text = fromName + localizable("has_updated") + " " + + localizable("team_update_client_custom") + case 100: + let muteState = attach.values?.values.first - if muteState == "0" { - text = teamName + localizable("not_mute") - }else { - text = teamName + localizable("mute") - } - default: - text = fromName + localizable("has_updated") + teamName - } + if muteState == "0" { + text = teamName + localizable("not_mute") + } else { + text = teamName + localizable("mute") } - return text + default: + text = fromName + localizable("has_updated") + teamName + } } + return text + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/Helper/ReplyMessageUtil.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/Helper/ReplyMessageUtil.swift index f56d6126..27f71d30 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/Helper/ReplyMessageUtil.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/Helper/ReplyMessageUtil.swift @@ -1,37 +1,36 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import SVGKit -public class ReplyMessageUtil { - - public static func textForReplyModel(model: MessageContentModel) -> String { - var text = "|" - if let name = model.fullName { - text = text + name - } - text = text + ": " - switch model.type { - case .text: - if let t = model.message?.text { - text = text + t - } - case .image: - text = text + localizable("msg_image") - case .audio: - text = text + localizable("msg_audio") - case .video: - text = text + localizable("msg_video") - case .file: - text = text + localizable("msg_file") - case .custom: - text = text + localizable("msg_custom") - default: - text = text + localizable("msg_unknown") - } - return text +public enum ReplyMessageUtil { + public static func textForReplyModel(model: MessageContentModel) -> String { + var text = "|" + if let name = model.fullName { + text = text + name } - + text = text + ": " + switch model.type { + case .text: + if let t = model.message?.text { + text = text + t + } + case .image: + text = text + localizable("msg_image") + case .audio: + text = text + localizable("msg_audio") + case .video: + text = text + localizable("msg_video") + case .file: + text = text + localizable("msg_file") + case .custom: + text = text + localizable("msg_custom") + default: + text = text + localizable("msg_unknown") + } + return text + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/MessageAudioModel.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/MessageAudioModel.swift index bd7fd650..9884fe8f 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/MessageAudioModel.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/MessageAudioModel.swift @@ -1,26 +1,27 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NIMSDK class MessageAudioModel: MessageContentModel { - public var duration: Int = 0 - public var isPlaying = false - required init(message: NIMMessage?) { - super.init(message: message) - type = .audio - var audioW = 96.0 - let audioTotalWidth = 265.0 - // contentSize - if let obj = message?.messageObject as? NIMAudioObject { - duration = obj.duration / 1000 - if duration > 2 { - audioW = min(Double(duration) * 8 + audioW, audioTotalWidth) - } - } - contentSize = CGSize(width: audioW, height: qChat_min_h) - height = Float(contentSize.height + qChat_margin) + self.fullNameHeight + public var duration: Int = 0 + public var isPlaying = false + required init(message: NIMMessage?) { + super.init(message: message) + type = .audio + var audioW = 96.0 + let audioTotalWidth = 265.0 + // contentSize + if let obj = message?.messageObject as? NIMAudioObject { + duration = obj.duration / 1000 + if duration > 2 { + audioW = min(Double(duration) * 8 + audioW, audioTotalWidth) + } } + contentSize = CGSize(width: audioW, height: qChat_min_h) + height = Float(contentSize.height + qChat_margin) + fullNameHeight + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/MessageContentModel.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/MessageContentModel.swift index b096985f..6e7d4b6a 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/MessageContentModel.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/MessageContentModel.swift @@ -1,6 +1,7 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NIMSDK @@ -10,68 +11,77 @@ import NEKitCoreIM @objcMembers public class MessageContentModel: MessageModel { - - public var pinAccount: String? - public var pinShowName: String? - public var type: MessageType = .custom - public var message: NIMMessage? - public var contentSize: CGSize - public var height: Float - public var shortName: String? - public var fullName: String? - public var avatar: String? - public var replyText: String? - public var fullNameHeight: Float = 0 - public var replyedModel: MessageModel? { - didSet { - if let reply = replyedModel as? MessageContentModel { - replyText = ReplyMessageUtil.textForReplyModel(model: reply) - if let t = replyText { - let size = String.getTextRectSize(t, font: UIFont.systemFont(ofSize: 12.0), size: CGSize(width: qChat_content_maxW, height: CGFloat.greatestFiniteMagnitude)) - contentSize = CGSize(width: max(contentSize.width, size.width), height: contentSize.height + chat_reply_height) - height = Float(contentSize.height + qChat_margin) + self.fullNameHeight - } - } + public var pinAccount: String? + public var pinShowName: String? + public var type: MessageType = .custom + public var message: NIMMessage? + public var contentSize: CGSize + public var height: Float + public var shortName: String? + public var fullName: String? + public var avatar: String? + public var replyText: String? + public var fullNameHeight: Float = 0 + public var replyedModel: MessageModel? { + didSet { + if let reply = replyedModel as? MessageContentModel { + replyText = ReplyMessageUtil.textForReplyModel(model: reply) + if let t = replyText { + let size = String.getTextRectSize( + t, + font: UIFont.systemFont(ofSize: 12.0), + size: CGSize( + width: qChat_content_maxW, + height: CGFloat.greatestFiniteMagnitude + ) + ) + contentSize = CGSize( + width: max(contentSize.width, size.width), + height: contentSize.height + chat_reply_height + ) + height = Float(contentSize.height + qChat_margin) + fullNameHeight } + } } - - public var isRevoked: Bool = false { - didSet { - if isRevoked { - type = .revoke - //只有文本消息,才计算可编辑按钮的宽度 - if let isSend = self.message?.isOutgoingMsg, isSend,message?.messageType == .text { - contentSize = CGSize(width: 218, height: qChat_min_h) - }else { - contentSize = CGSize(width: 130, height: qChat_min_h) - } - height = Float(contentSize.height + qChat_margin) + self.fullNameHeight - }else { - type = .custom - contentSize = CGSize(width: 32.0, height: qChat_min_h) - height = Float(qChat_min_h + qChat_margin) + self.fullNameHeight - } - } - } - - public var isPined: Bool = false { - didSet { - if isPined { - height = Float(contentSize.height + qChat_margin + chat_pin_height) + self.fullNameHeight - }else { - height = Float(contentSize.height + qChat_margin) + self.fullNameHeight - } + } + + public var isRevoked: Bool = false { + didSet { + if isRevoked { + type = .revoke + // 只有文本消息,才计算可编辑按钮的宽度 + if let isSend = message?.isOutgoingMsg, isSend, message?.messageType == .text { + contentSize = CGSize(width: 218, height: qChat_min_h) + } else { + contentSize = CGSize(width: 130, height: qChat_min_h) } - } - - required public init(message: NIMMessage?) { - self.message = message + height = Float(contentSize.height + qChat_margin) + fullNameHeight + } else { + type = .custom contentSize = CGSize(width: 32.0, height: qChat_min_h) - if message?.session?.sessionType == .team && !IMKitLoginManager.instance.isMySelf(message?.from) { - self.fullNameHeight = 20 - } - print("self.fullNameHeight\(self.fullNameHeight)") - height = Float(qChat_min_h + qChat_margin) + self.fullNameHeight + height = Float(qChat_min_h + qChat_margin) + fullNameHeight + } + } + } + + public var isPined: Bool = false { + didSet { + if isPined { + height = Float(contentSize.height + qChat_margin + chat_pin_height) + fullNameHeight + } else { + height = Float(contentSize.height + qChat_margin) + fullNameHeight + } } + } + public required init(message: NIMMessage?) { + self.message = message + contentSize = CGSize(width: 32.0, height: qChat_min_h) + if message?.session?.sessionType == .team, + !IMKitLoginManager.instance.isMySelf(message?.from) { + fullNameHeight = 20 + } + print("self.fullNameHeight\(fullNameHeight)") + height = Float(qChat_min_h + qChat_margin) + fullNameHeight + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/MessageImageModel.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/MessageImageModel.swift index 6ff86fdb..c849fb6c 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/MessageImageModel.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/MessageImageModel.swift @@ -1,26 +1,30 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NIMSDK class MessageImageModel: MessageContentModel { - public var imageUrl: String? - required init(message: NIMMessage?) { - super.init(message: message) - type = .image - if let imageObject = message?.messageObject as? NIMImageObject { - if let path = imageObject.path, FileManager.default.fileExists(atPath: path) { - imageUrl = path - }else { - imageUrl = imageObject.url - } - contentSize = ChatMessageHelper.getSizeWithMaxSize(qChat_pic_size, size: imageObject.size, miniWH: qChat_min_h) - }else { - contentSize = qChat_pic_size - } - height = Float(contentSize.height + qChat_margin) + self.fullNameHeight + public var imageUrl: String? + required init(message: NIMMessage?) { + super.init(message: message) + type = .image + if let imageObject = message?.messageObject as? NIMImageObject { + if let path = imageObject.path, FileManager.default.fileExists(atPath: path) { + imageUrl = path + } else { + imageUrl = imageObject.url + } + contentSize = ChatMessageHelper.getSizeWithMaxSize( + qChat_pic_size, + size: imageObject.size, + miniWH: qChat_min_h + ) + } else { + contentSize = qChat_pic_size } - + height = Float(contentSize.height + qChat_margin) + fullNameHeight + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/MessageModel.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/MessageModel.swift index 93194edf..3dd6eb92 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/MessageModel.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/MessageModel.swift @@ -1,47 +1,47 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NIMSDK -public enum MessageType:Int { - case text - case image - case audio - case video - case location - case notification - case file - case tip - case robot - case rtcCallRecord - case custom - case time - case revoke - case reply +public enum MessageType: Int { + case text + case image + case audio + case video + case location + case notification + case file + case tip + case robot + case rtcCallRecord + case custom + case time + case revoke + case reply } public protocol MessageModel { - var message: NIMMessage? { get set } - // 气泡区域的大小 不包含气泡上下到cell上下的边距 - var contentSize: CGSize { get set } - var height: Float { get set } + var message: NIMMessage? { get set } + // 气泡区域的大小 不包含气泡上下到cell上下的边距 + var contentSize: CGSize { get set } + var height: Float { get set } // 名字后2位 - var shortName: String? { get set } + var shortName: String? { get set } // 名字全长 - var fullName: String? { get set } - var avatar: String? { get set } - var type: MessageType { get set } - var isRevoked: Bool { get set } - var isPined: Bool { get set } + var fullName: String? { get set } + var avatar: String? { get set } + var type: MessageType { get set } + var isRevoked: Bool { get set } + var isPined: Bool { get set } // userID - var pinAccount: String? { get set } - var pinShowName: String? { get set } + var pinAccount: String? { get set } + var pinShowName: String? { get set } // 被回复的消息 - var replyedModel: MessageModel? { get set } - var replyText: String? { get set } - - - init(message: NIMMessage?) + var replyedModel: MessageModel? { get set } + var replyText: String? { get set } + + init(message: NIMMessage?) } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/MessageReplyModel.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/MessageReplyModel.swift index 63f2498b..1e78fd0a 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/MessageReplyModel.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/MessageReplyModel.swift @@ -1,37 +1,39 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NIMSDK class MessageReplyModel: MessageContentModel { - let targetHeight = 26.0 - public var text: String? - public var targetText: String? - public var targetMessage: NIMMessage? - required init(message: NIMMessage?, targetMessage: NIMMessage?) { - super.init(message: message) - self.targetMessage = targetMessage - type = .reply - text = message?.text + let targetHeight = 26.0 + public var text: String? + public var targetText: String? + public var targetMessage: NIMMessage? + required init(message: NIMMessage?, targetMessage: NIMMessage?) { + super.init(message: message) + self.targetMessage = targetMessage + type = .reply + text = message?.text // targetText = "|" + targetMessage?.from + ": " - let textSize = String.getTextRectSize(text ?? "", font: DefaultTextFont(16), size: CGSize.init(width: qChat_content_maxW, height: CGFloat.greatestFiniteMagnitude)) - var h = qChat_min_h; - if textSize.height > qChat_min_h { - h = textSize.height + 32 + targetHeight - } - contentSize = CGSize(width: textSize.width + qChat_cell_margin * 2, height: h) - height = Float(contentSize.height + qChat_margin) + self.fullNameHeight - + let textSize = String.getTextRectSize( + text ?? "", + font: DefaultTextFont(16), + size: CGSize(width: qChat_content_maxW, height: CGFloat.greatestFiniteMagnitude) + ) + var h = qChat_min_h + if textSize.height > qChat_min_h { + h = textSize.height + 32 + targetHeight } - - required public init(message: NIMMessage?) { - fatalError("init(message:) has not been implemented") - } - + contentSize = CGSize(width: textSize.width + qChat_cell_margin * 2, height: h) + height = Float(contentSize.height + qChat_margin) + fullNameHeight + } + + public required init(message: NIMMessage?) { + fatalError("init(message:) has not been implemented") + } + // func replyTextWithMessage(_ message:) -> <#return type#> { // <#function body#> // } - - } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/MessageTextModel.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/MessageTextModel.swift index 451f0b44..cdb1a441 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/MessageTextModel.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/MessageTextModel.swift @@ -1,32 +1,39 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NIMSDK class MessageTextModel: MessageContentModel { // public var text: String? - public var attributeStr : NSAttributedString? - - required init(message: NIMMessage?) { - super.init(message: message) - type = .text + public var attributeStr: NSAttributedString? + + required init(message: NIMMessage?) { + super.init(message: message) + type = .text // text = message?.text - attributeStr = NEEmotionTool.getAttWithStr(str: message?.text ?? "", font: NEKitChatConfig.shared.ui.messageFont) - - let textSize = NEChatUITool.getSizeWithAtt(att: attributeStr ?? NSAttributedString.init(string: ""), font: DefaultTextFont(16), maxSize: CGSize.init(width: qChat_content_maxW, height: CGFloat.greatestFiniteMagnitude)) - - var h = qChat_min_h; + attributeStr = NEEmotionTool.getAttWithStr( + str: message?.text ?? "", + font: NEKitChatConfig.shared.ui.messageFont + ) + + let textSize = NEChatUITool.getSizeWithAtt( + att: attributeStr ?? NSAttributedString(string: ""), + font: DefaultTextFont(16), + maxSize: CGSize(width: qChat_content_maxW, height: CGFloat.greatestFiniteMagnitude) + ) + + var h = qChat_min_h // if textSize.height > qChat_min_h { // h = textSize.height + 32 // } - h = textSize.height + 24 - contentSize = CGSize(width: textSize.width + qChat_cell_margin * 2, height: h) - - height = Float(contentSize.height + qChat_margin) + self.fullNameHeight - - print(">>text:\(message?.text) height:\(height)") - } - + h = textSize.height + 24 + contentSize = CGSize(width: textSize.width + qChat_cell_margin * 2, height: h) + + height = Float(contentSize.height + qChat_margin) + fullNameHeight + + print(">>text:\(message?.text) height:\(height)") + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/MessageTipsModel.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/MessageTipsModel.swift index c7ab604b..ee142b0f 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/MessageTipsModel.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/MessageTipsModel.swift @@ -1,38 +1,38 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NIMSDK class MessageTipsModel: MessageModel { - var isPined: Bool = false - var pinAccount: String? - var pinShowName: String? - var replyText: String? - var type: MessageType = .tip - var message: NIMMessage? - var contentSize: CGSize - var height: Float - var shortName: String? - var fullName: String? - var avatar: String? - var text: String? - var isRevoked: Bool = false - var replyedModel: MessageModel? - - required init(message: NIMMessage?) { - if let msg = message { - if msg.messageType == .notification { - text = NotificationMessageUtils.textForNotification(message: msg) - type = .notification - }else if msg.messageType == .tip { - text = msg.text - type = .tip - } - } - contentSize = CGSize(width: kScreenWidth, height: 35) - height = 35 - } + var isPined: Bool = false + var pinAccount: String? + var pinShowName: String? + var replyText: String? + var type: MessageType = .tip + var message: NIMMessage? + var contentSize: CGSize + var height: Float + var shortName: String? + var fullName: String? + var avatar: String? + var text: String? + var isRevoked: Bool = false + var replyedModel: MessageModel? + required init(message: NIMMessage?) { + if let msg = message { + if msg.messageType == .notification { + text = NotificationMessageUtils.textForNotification(message: msg) + type = .notification + } else if msg.messageType == .tip { + text = msg.text + type = .tip + } + } + contentSize = CGSize(width: kScreenWidth, height: 35) + height = 35 + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/MessageVideoModel.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/MessageVideoModel.swift index 0f5b8e2b..52c8ae12 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/MessageVideoModel.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/MessageVideoModel.swift @@ -1,29 +1,34 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NIMSDK enum DownloadState { - case Success - case Downalod + case Success + case Downalod } class MessageVideoModel: MessageContentModel { - public var imageUrl: String? - public var state = DownloadState.Success - public var progress: Float = 0 - public weak var cell: ChatBaseCell? - required init(message: NIMMessage?) { - super.init(message: message) - type = .video - if let videoObject = message?.messageObject as? NIMVideoObject { - imageUrl = videoObject.url - contentSize = ChatMessageHelper.getSizeWithMaxSize(qChat_pic_size, size: videoObject.coverSize, miniWH: qChat_min_h) - }else { - contentSize = qChat_pic_size - } - height = Float(contentSize.height + qChat_margin) + self.fullNameHeight + public var imageUrl: String? + public var state = DownloadState.Success + public var progress: Float = 0 + public weak var cell: ChatBaseCell? + required init(message: NIMMessage?) { + super.init(message: message) + type = .video + if let videoObject = message?.messageObject as? NIMVideoObject { + imageUrl = videoObject.url + contentSize = ChatMessageHelper.getSizeWithMaxSize( + qChat_pic_size, + size: videoObject.coverSize, + miniWH: qChat_min_h + ) + } else { + contentSize = qChat_pic_size } + height = Float(contentSize.height + qChat_margin) + fullNameHeight + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/OperationItem.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/OperationItem.swift index 4327b610..936abcb0 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/OperationItem.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/OperationItem.swift @@ -1,60 +1,76 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation public enum OperationType { - case copy - case reply - case forward - case pin - case removePin - case multiSelect - case collection - case delete - case recall + case copy + case reply + case forward + case pin + case removePin + case multiSelect + case collection + case delete + case recall } public struct OperationItem { - public var text: String - public var imageName: String - public var type: OperationType - - static func copyItem() -> OperationItem { - return OperationItem(text: localizable("operation_copy"), imageName:"op_copy", type: .copy) - } - - static func replayItem() -> OperationItem { - return OperationItem(text: localizable("operation_replay"), imageName:"op_replay", type: .reply) - } - - static func forwardItem() -> OperationItem { - return OperationItem(text: localizable("operation_forward"), imageName:"op_forward", type: .forward) - } - - static func pinItem() -> OperationItem { - return OperationItem(text: localizable("operation_pin"), imageName:"op_pin", type: .pin) - } - - static func removePinItem() -> OperationItem { - return OperationItem(text: localizable("operation_cancel_pin"), imageName:"op_pin", type: .removePin) - } - - static func selectItem() -> OperationItem { - return OperationItem(text: localizable("operation_select"), imageName:"op_select", type: .multiSelect) - } - - static func collectionItem() -> OperationItem { - return OperationItem(text: localizable("operation_collection"), imageName:"op_collection", type: .collection) - } - - static func deleteItem() -> OperationItem { - return OperationItem(text: localizable("operation_delete"), imageName:"op_delete", type: .delete) - } - - static func recallItem() -> OperationItem { - return OperationItem(text: localizable("operation_recall"), imageName:"op_recall", type: .recall) - } + public var text: String + public var imageName: String + public var type: OperationType + static func copyItem() -> OperationItem { + OperationItem(text: localizable("operation_copy"), imageName: "op_copy", type: .copy) + } + + static func replayItem() -> OperationItem { + OperationItem(text: localizable("operation_replay"), imageName: "op_replay", type: .reply) + } + + static func forwardItem() -> OperationItem { + OperationItem( + text: localizable("operation_forward"), + imageName: "op_forward", + type: .forward + ) + } + + static func pinItem() -> OperationItem { + OperationItem(text: localizable("operation_pin"), imageName: "op_pin", type: .pin) + } + + static func removePinItem() -> OperationItem { + OperationItem( + text: localizable("operation_cancel_pin"), + imageName: "op_pin", + type: .removePin + ) + } + +// static func selectItem() -> OperationItem { +// OperationItem( +// text: localizable("operation_select"), +// imageName: "op_select", +// type: .multiSelect +// ) +// } + +// static func collectionItem() -> OperationItem { +// OperationItem( +// text: localizable("operation_collection"), +// imageName: "op_collection", +// type: .collection +// ) +// } + + static func deleteItem() -> OperationItem { + OperationItem(text: localizable("operation_delete"), imageName: "op_delete", type: .delete) + } + + static func recallItem() -> OperationItem { + OperationItem(text: localizable("operation_recall"), imageName: "op_recall", type: .recall) + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/UserSettingCellModel.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/UserSettingCellModel.swift index b6a6e64e..47053e23 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/UserSettingCellModel.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/Model/UserSettingCellModel.swift @@ -1,19 +1,20 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation class UserSettingCellModel { - typealias SwitchChangeCompletion = (Bool) -> Void - typealias CellClick = () -> Void - var cellName: String? - var subTitle: String? + typealias SwitchChangeCompletion = (Bool) -> Void + typealias CellClick = () -> Void + var cellName: String? + var subTitle: String? // var type = SettingCellType.SettingArrowCell.rawValue - var swichChange: SwitchChangeCompletion? - var rowHeight: CGFloat = 49 - var cornerType = CornerType.none + var swichChange: SwitchChangeCompletion? + var rowHeight: CGFloat = 49 + var cornerType = CornerType.none // var headerUrl: String? - var cellClick: CellClick? - var switchOpen = false + var cellClick: CellClick? + var switchOpen = false } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatAudioLeftCell.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatAudioLeftCell.swift index 73509a84..017f9f5a 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatAudioLeftCell.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatAudioLeftCell.swift @@ -1,70 +1,73 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit -class ChatAudioLeftCell: ChatBaseLeftCell,ChatAudioCell { - var isPlaying: Bool = false - var audioImageView = UIImageView(image: UIImage.ne_imageNamed(name: "left_play_3")) - var timeLabel = UILabel() - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - commonUI() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func commonUI() { - self.audioImageView.contentMode = .center - self.audioImageView.translatesAutoresizingMaskIntoConstraints = false - self.bubbleImage.addSubview(self.audioImageView) - NSLayoutConstraint.activate([ - self.audioImageView.leftAnchor.constraint(equalTo: bubbleImage.leftAnchor, constant: 16), - self.audioImageView.centerYAnchor.constraint(equalTo: bubbleImage.centerYAnchor), - self.audioImageView.widthAnchor.constraint(equalToConstant: 28), - self.audioImageView.heightAnchor.constraint(equalToConstant: 28) - ]) - - self.timeLabel.font = UIFont.systemFont(ofSize: 14) - self.timeLabel.textColor = UIColor.ne_darkText - self.timeLabel.textAlignment = .left - self.timeLabel.translatesAutoresizingMaskIntoConstraints = false - self.bubbleImage.addSubview(self.timeLabel) - NSLayoutConstraint.activate([ - self.timeLabel.leftAnchor.constraint(equalTo: audioImageView.rightAnchor, constant: 12), - self.timeLabel.centerYAnchor.constraint(equalTo: bubbleImage.centerYAnchor), - self.timeLabel.rightAnchor.constraint(equalTo: bubbleImage.rightAnchor, constant: -12), - self.timeLabel.heightAnchor.constraint(equalToConstant: 28) - ]) - self.audioImageView.animationDuration = 1 - if let leftImage1 = UIImage.ne_imageNamed(name: "left_play_1"), let leftmage2 = UIImage.ne_imageNamed(name: "left_play_2"), let leftmage3 = UIImage.ne_imageNamed(name: "left_play_3") { - self.audioImageView.animationImages = [leftImage1,leftmage2,leftmage3] - } +class ChatAudioLeftCell: ChatBaseLeftCell, ChatAudioCell { + var isPlaying: Bool = false + var audioImageView = UIImageView(image: UIImage.ne_imageNamed(name: "left_play_3")) + var timeLabel = UILabel() + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + commonUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func commonUI() { + audioImageView.contentMode = .center + audioImageView.translatesAutoresizingMaskIntoConstraints = false + bubbleImage.addSubview(audioImageView) + NSLayoutConstraint.activate([ + audioImageView.leftAnchor.constraint(equalTo: bubbleImage.leftAnchor, constant: 16), + audioImageView.centerYAnchor.constraint(equalTo: bubbleImage.centerYAnchor), + audioImageView.widthAnchor.constraint(equalToConstant: 28), + audioImageView.heightAnchor.constraint(equalToConstant: 28), + ]) + + timeLabel.font = UIFont.systemFont(ofSize: 14) + timeLabel.textColor = UIColor.ne_darkText + timeLabel.textAlignment = .left + timeLabel.translatesAutoresizingMaskIntoConstraints = false + bubbleImage.addSubview(timeLabel) + NSLayoutConstraint.activate([ + timeLabel.leftAnchor.constraint(equalTo: audioImageView.rightAnchor, constant: 12), + timeLabel.centerYAnchor.constraint(equalTo: bubbleImage.centerYAnchor), + timeLabel.rightAnchor.constraint(equalTo: bubbleImage.rightAnchor, constant: -12), + timeLabel.heightAnchor.constraint(equalToConstant: 28), + ]) + audioImageView.animationDuration = 1 + if let leftImage1 = UIImage.ne_imageNamed(name: "left_play_1"), + let leftmage2 = UIImage.ne_imageNamed(name: "left_play_2"), + let leftmage3 = UIImage.ne_imageNamed(name: "left_play_3") { + audioImageView.animationImages = [leftImage1, leftmage2, leftmage3] } - - func startAnimation() { - if !self.audioImageView.isAnimating { + } + + func startAnimation() { + if !audioImageView.isAnimating { // self.messageModel?.audioPlaying = true - self.audioImageView.startAnimating() - } + audioImageView.startAnimating() } - - func stopAnimation() { - if self.audioImageView.isAnimating { + } + + func stopAnimation() { + if audioImageView.isAnimating { // self.messageModel?.audioPlaying = false - self.audioImageView.stopAnimating() - } + audioImageView.stopAnimating() } - - override func setModel(_ model: MessageContentModel) { - super.setModel(model) - if let m = model as? MessageAudioModel { - self.timeLabel.text = "\(m.duration)" + "s" - m.isPlaying ? startAnimation() : stopAnimation() - } + } + + override func setModel(_ model: MessageContentModel) { + super.setModel(model) + if let m = model as? MessageAudioModel { + timeLabel.text = "\(m.duration)" + "s" + m.isPlaying ? startAnimation() : stopAnimation() } + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatAudioRightCell.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatAudioRightCell.swift index 189063fb..1a780f5b 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatAudioRightCell.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatAudioRightCell.swift @@ -1,82 +1,85 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit protocol ChatAudioCell { - var isPlaying: Bool { get set } - func startAnimation() - func stopAnimation() + var isPlaying: Bool { get set } + func startAnimation() + func stopAnimation() } -class ChatAudioRightCell: ChatBaseRightCell,ChatAudioCell { - var isPlaying: Bool = false - var audioImageView = UIImageView(image: UIImage.ne_imageNamed(name: "audio_play")) - var timeLabel = UILabel() - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - commonUI() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func commonUI() { - self.audioImageView.contentMode = .center - self.audioImageView.translatesAutoresizingMaskIntoConstraints = false - self.bubbleImage.addSubview(self.audioImageView) - NSLayoutConstraint.activate([ - self.audioImageView.rightAnchor.constraint(equalTo: bubbleImage.rightAnchor, constant: -16), - self.audioImageView.centerYAnchor.constraint(equalTo: bubbleImage.centerYAnchor), - self.audioImageView.widthAnchor.constraint(equalToConstant: 28), - self.audioImageView.heightAnchor.constraint(equalToConstant: 28) - ]) - - self.timeLabel.font = UIFont.systemFont(ofSize: 14) - self.timeLabel.textColor = UIColor.ne_darkText - self.timeLabel.textAlignment = .right - self.timeLabel.translatesAutoresizingMaskIntoConstraints = false - self.bubbleImage.addSubview(self.timeLabel) - NSLayoutConstraint.activate([ - self.timeLabel.rightAnchor.constraint(equalTo: audioImageView.leftAnchor, constant: -12), - self.timeLabel.centerYAnchor.constraint(equalTo: bubbleImage.centerYAnchor), - self.timeLabel.heightAnchor.constraint(equalToConstant: 28) - ]) - - self.audioImageView.animationDuration = 1 - if let image1 = UIImage.ne_imageNamed(name: "play_1"), let image2 = UIImage.ne_imageNamed(name: "play_2"), let image3 = UIImage.ne_imageNamed(name: "play_3") { - self.audioImageView.animationImages = [image1,image2,image3] - } +class ChatAudioRightCell: ChatBaseRightCell, ChatAudioCell { + var isPlaying: Bool = false + var audioImageView = UIImageView(image: UIImage.ne_imageNamed(name: "audio_play")) + var timeLabel = UILabel() + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + commonUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func commonUI() { + audioImageView.contentMode = .center + audioImageView.translatesAutoresizingMaskIntoConstraints = false + bubbleImage.addSubview(audioImageView) + NSLayoutConstraint.activate([ + audioImageView.rightAnchor.constraint(equalTo: bubbleImage.rightAnchor, constant: -16), + audioImageView.centerYAnchor.constraint(equalTo: bubbleImage.centerYAnchor), + audioImageView.widthAnchor.constraint(equalToConstant: 28), + audioImageView.heightAnchor.constraint(equalToConstant: 28), + ]) + + timeLabel.font = UIFont.systemFont(ofSize: 14) + timeLabel.textColor = UIColor.ne_darkText + timeLabel.textAlignment = .right + timeLabel.translatesAutoresizingMaskIntoConstraints = false + bubbleImage.addSubview(timeLabel) + NSLayoutConstraint.activate([ + timeLabel.rightAnchor.constraint(equalTo: audioImageView.leftAnchor, constant: -12), + timeLabel.centerYAnchor.constraint(equalTo: bubbleImage.centerYAnchor), + timeLabel.heightAnchor.constraint(equalToConstant: 28), + ]) + + audioImageView.animationDuration = 1 + if let image1 = UIImage.ne_imageNamed(name: "play_1"), + let image2 = UIImage.ne_imageNamed(name: "play_2"), + let image3 = UIImage.ne_imageNamed(name: "play_3") { + audioImageView.animationImages = [image1, image2, image3] } - - func startAnimation() { - if !self.audioImageView.isAnimating { - self.audioImageView.startAnimating() - if let m = model as? MessageAudioModel { - m.isPlaying = true - self.isPlaying = true - } - } + } + + func startAnimation() { + if !audioImageView.isAnimating { + audioImageView.startAnimating() + if let m = model as? MessageAudioModel { + m.isPlaying = true + isPlaying = true + } } - - func stopAnimation() { - if self.audioImageView.isAnimating { - self.audioImageView.stopAnimating() - if let m = model as? MessageAudioModel { - m.isPlaying = false - self.isPlaying = false - } - } + } + + func stopAnimation() { + if audioImageView.isAnimating { + audioImageView.stopAnimating() + if let m = model as? MessageAudioModel { + m.isPlaying = false + isPlaying = false + } } - - override func setModel(_ model: MessageContentModel) { - super.setModel(model) - if let m = model as? MessageAudioModel { - self.timeLabel.text = "\(m.duration)" + "s" - m.isPlaying ? startAnimation() : stopAnimation() - } + } + + override func setModel(_ model: MessageContentModel) { + super.setModel(model) + if let m = model as? MessageAudioModel { + timeLabel.text = "\(m.duration)" + "s" + m.isPlaying ? startAnimation() : stopAnimation() } + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatBaseLeftCell.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatBaseLeftCell.swift index 466b8e92..7ebf5a57 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatBaseLeftCell.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatBaseLeftCell.swift @@ -1,251 +1,259 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class ChatBaseLeftCell: ChatBaseCell { - public var avatarImage = UIImageView() - public var nameLabel = UILabel() - public var fullNameLabel = UILabel() - public var bubbleImage = UIImageView() - public var activityView = ChatActivityIndicatorView() - public var seletedBtn = UIButton(type: .custom) - public var pinImage = UIImageView() - public var pinLabel = UILabel() - public var bubbleW: NSLayoutConstraint? - public weak var delegate: ChatBaseCellDelegate? - private let bubbleWidth = 32.0 - public var model: MessageContentModel? - public var fullNameH: NSLayoutConstraint? - private var pinLabelH: NSLayoutConstraint? - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - baseCommonUI() - addGesture() - initSubviewsLayout() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func baseCommonUI() { - // avatar - self.selectionStyle = .none - self.backgroundColor = .white - self.avatarImage.layer.cornerRadius = 16 - self.avatarImage.backgroundColor = UIColor(hexString: "#537FF4") - self.avatarImage.translatesAutoresizingMaskIntoConstraints = false - self.avatarImage.clipsToBounds = true - self.avatarImage.isUserInteractionEnabled = true - self.avatarImage.contentMode = .scaleAspectFill - self.contentView.addSubview(self.avatarImage) - NSLayoutConstraint.activate([ - self.avatarImage.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 16), - self.avatarImage.widthAnchor.constraint(equalToConstant: 32), - self.avatarImage.heightAnchor.constraint(equalToConstant: 32), - self.avatarImage.topAnchor.constraint(equalTo: self.topAnchor, constant: 4) - ]) - - // name - self.nameLabel.textAlignment = .center - self.nameLabel.translatesAutoresizingMaskIntoConstraints = false - self.nameLabel.font = UIFont.systemFont(ofSize: 12) - self.nameLabel.textColor = .white - self.contentView.addSubview(self.nameLabel) - NSLayoutConstraint.activate([ - self.nameLabel.leftAnchor.constraint(equalTo: self.avatarImage.leftAnchor), - self.nameLabel.rightAnchor.constraint(equalTo: self.avatarImage.rightAnchor), - self.nameLabel.topAnchor.constraint(equalTo: self.avatarImage.topAnchor), - self.nameLabel.bottomAnchor.constraint(equalTo: self.avatarImage.bottomAnchor), - ]) - - // name - self.fullNameLabel.translatesAutoresizingMaskIntoConstraints = false - self.fullNameLabel.font = UIFont.systemFont(ofSize: 12) - self.fullNameLabel.textColor = UIColor.ne_lightText - self.contentView.addSubview(self.fullNameLabel) - fullNameH = self.fullNameLabel.heightAnchor.constraint(equalToConstant: 0) - NSLayoutConstraint.activate([ - self.fullNameLabel.leftAnchor.constraint(equalTo: self.avatarImage.rightAnchor, constant: 8), - self.fullNameLabel.rightAnchor.constraint(equalTo: self.contentView.rightAnchor,constant: -16), - self.fullNameLabel.topAnchor.constraint(equalTo: self.avatarImage.topAnchor), - fullNameH! - ]) - + public var avatarImage = UIImageView() + public var nameLabel = UILabel() + public var fullNameLabel = UILabel() + public var bubbleImage = UIImageView() + public var activityView = ChatActivityIndicatorView() + public var seletedBtn = UIButton(type: .custom) + public var pinImage = UIImageView() + public var pinLabel = UILabel() + public var bubbleW: NSLayoutConstraint? + public weak var delegate: ChatBaseCellDelegate? + private let bubbleWidth = 32.0 + public var model: MessageContentModel? + public var fullNameH: NSLayoutConstraint? + private var pinLabelH: NSLayoutConstraint? + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + baseCommonUI() + addGesture() + initSubviewsLayout() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func baseCommonUI() { + // avatar + selectionStyle = .none + backgroundColor = .white + avatarImage.layer.cornerRadius = 16 + avatarImage.backgroundColor = UIColor(hexString: "#537FF4") + avatarImage.translatesAutoresizingMaskIntoConstraints = false + avatarImage.clipsToBounds = true + avatarImage.isUserInteractionEnabled = true + avatarImage.contentMode = .scaleAspectFill + contentView.addSubview(avatarImage) + NSLayoutConstraint.activate([ + avatarImage.leftAnchor.constraint(equalTo: leftAnchor, constant: 16), + avatarImage.widthAnchor.constraint(equalToConstant: 32), + avatarImage.heightAnchor.constraint(equalToConstant: 32), + avatarImage.topAnchor.constraint(equalTo: topAnchor, constant: 4), + ]) + + // name + nameLabel.textAlignment = .center + nameLabel.translatesAutoresizingMaskIntoConstraints = false + nameLabel.font = UIFont.systemFont(ofSize: 12) + nameLabel.textColor = .white + contentView.addSubview(nameLabel) + NSLayoutConstraint.activate([ + nameLabel.leftAnchor.constraint(equalTo: avatarImage.leftAnchor), + nameLabel.rightAnchor.constraint(equalTo: avatarImage.rightAnchor), + nameLabel.topAnchor.constraint(equalTo: avatarImage.topAnchor), + nameLabel.bottomAnchor.constraint(equalTo: avatarImage.bottomAnchor), + ]) + + // name + fullNameLabel.translatesAutoresizingMaskIntoConstraints = false + fullNameLabel.font = UIFont.systemFont(ofSize: 12) + fullNameLabel.textColor = UIColor.ne_lightText + contentView.addSubview(fullNameLabel) + fullNameH = fullNameLabel.heightAnchor.constraint(equalToConstant: 0) + NSLayoutConstraint.activate([ + fullNameLabel.leftAnchor.constraint(equalTo: avatarImage.rightAnchor, constant: 8), + fullNameLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -16), + fullNameLabel.topAnchor.constraint(equalTo: avatarImage.topAnchor), + fullNameH!, + ]) + // bubbleImage - if let image = NEKitChatConfig.shared.ui.leftBubbleBg { - self.bubbleImage.image = image.resizableImage(withCapInsets: UIEdgeInsets.init(top: 35, left: 25, bottom: 10, right: 25)) - } - self.bubbleImage.translatesAutoresizingMaskIntoConstraints = false - self.bubbleImage.isUserInteractionEnabled = true - self.contentView.addSubview(self.bubbleImage) - bubbleW = self.bubbleImage.widthAnchor.constraint(equalToConstant: bubbleWidth) - NSLayoutConstraint.activate([ - bubbleW!, - self.bubbleImage.leftAnchor.constraint(equalTo: self.avatarImage.rightAnchor, constant: 8), - self.bubbleImage.topAnchor.constraint(equalTo: self.fullNameLabel.bottomAnchor, constant: 0), + if let image = NEKitChatConfig.shared.ui.leftBubbleBg { + bubbleImage.image = image + .resizableImage(withCapInsets: UIEdgeInsets(top: 35, left: 25, bottom: 10, right: 25)) + } + bubbleImage.translatesAutoresizingMaskIntoConstraints = false + bubbleImage.isUserInteractionEnabled = true + contentView.addSubview(bubbleImage) + bubbleW = bubbleImage.widthAnchor.constraint(equalToConstant: bubbleWidth) + NSLayoutConstraint.activate([ + bubbleW!, + bubbleImage.leftAnchor.constraint(equalTo: avatarImage.rightAnchor, constant: 8), + bubbleImage.topAnchor.constraint(equalTo: fullNameLabel.bottomAnchor, constant: 0), // self.bubbleImage.topAnchor.constraint(equalTo: self.topAnchor, constant: 4), - ]) + ]) // activityView - self.contentView.addSubview(activityView) - self.activityView.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - self.activityView.leftAnchor.constraint(equalTo: self.bubbleImage.rightAnchor, constant: 8), - self.activityView.centerYAnchor.constraint(equalTo: self.bubbleImage.centerYAnchor, constant: 0), - self.activityView.widthAnchor.constraint(equalToConstant: 25), - self.activityView.heightAnchor.constraint(equalToConstant: 25), - ]) - + contentView.addSubview(activityView) + activityView.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + activityView.leftAnchor.constraint(equalTo: bubbleImage.rightAnchor, constant: 8), + activityView.centerYAnchor.constraint(equalTo: bubbleImage.centerYAnchor, constant: 0), + activityView.widthAnchor.constraint(equalToConstant: 25), + activityView.heightAnchor.constraint(equalToConstant: 25), + ]) + // seletedBtn - self.contentView.addSubview(seletedBtn) - self.seletedBtn.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - self.seletedBtn.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 16), - self.seletedBtn.centerYAnchor.constraint(equalTo: self.centerYAnchor, constant: 0), - self.seletedBtn.widthAnchor.constraint(equalToConstant: 18), - self.seletedBtn.heightAnchor.constraint(equalToConstant: 18), - ]) - + contentView.addSubview(seletedBtn) + seletedBtn.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + seletedBtn.leftAnchor.constraint(equalTo: leftAnchor, constant: 16), + seletedBtn.centerYAnchor.constraint(equalTo: centerYAnchor, constant: 0), + seletedBtn.widthAnchor.constraint(equalToConstant: 18), + seletedBtn.heightAnchor.constraint(equalToConstant: 18), + ]) + // pinImage.image = UIImage.ne_imageNamed(name: "msg_pin") - pinImage.translatesAutoresizingMaskIntoConstraints = false - pinImage.contentMode = .scaleAspectFit - self.contentView.addSubview(pinImage) - NSLayoutConstraint.activate([ - pinImage.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 16), - pinImage.widthAnchor.constraint(equalToConstant: 10), - pinImage.topAnchor.constraint(equalTo: self.bubbleImage.bottomAnchor, constant: 4), - pinImage.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -4), - ]) - - self.contentView.addSubview(pinLabel) - self.pinLabel.translatesAutoresizingMaskIntoConstraints = false - pinLabel.textAlignment = .left + pinImage.translatesAutoresizingMaskIntoConstraints = false + pinImage.contentMode = .scaleAspectFit + contentView.addSubview(pinImage) + NSLayoutConstraint.activate([ + pinImage.leftAnchor.constraint(equalTo: leftAnchor, constant: 16), + pinImage.widthAnchor.constraint(equalToConstant: 10), + pinImage.topAnchor.constraint(equalTo: bubbleImage.bottomAnchor, constant: 4), + pinImage.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -4), + ]) + + contentView.addSubview(pinLabel) + pinLabel.translatesAutoresizingMaskIntoConstraints = false + pinLabel.textAlignment = .left // pinLabel.text = localizable("pin_text") - pinLabel.font = UIFont.systemFont(ofSize: 12) - pinLabel.textColor = UIColor.ne_greenText - pinLabel.isHidden = true - pinLabelH = self.pinLabel.heightAnchor.constraint(equalToConstant: 0) - - NSLayoutConstraint.activate([ - self.pinLabel.topAnchor.constraint(equalTo: self.bubbleImage.bottomAnchor, constant: 4), - self.pinLabel.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -16), - self.pinLabel.leftAnchor.constraint(equalTo: pinImage.rightAnchor, constant: 2), - pinLabelH!, - self.pinLabel.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -4), - ]) - } - - func addGesture() { + pinLabel.font = UIFont.systemFont(ofSize: 12) + pinLabel.textColor = UIColor.ne_greenText + pinLabel.isHidden = true + pinLabelH = pinLabel.heightAnchor.constraint(equalToConstant: 0) + + NSLayoutConstraint.activate([ + pinLabel.topAnchor.constraint(equalTo: bubbleImage.bottomAnchor, constant: 4), + pinLabel.rightAnchor.constraint(equalTo: rightAnchor, constant: -16), + pinLabel.leftAnchor.constraint(equalTo: pinImage.rightAnchor, constant: 2), + pinLabelH!, + pinLabel.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -4), + ]) + } + + func addGesture() { // avatar - let tap = UITapGestureRecognizer(target: self, action: #selector(tapAvatar)) - self.avatarImage.addGestureRecognizer(tap) - - let messageTap = UITapGestureRecognizer(target: self, action: #selector(tapMessage)) - self.bubbleImage.addGestureRecognizer(messageTap) - - let messageLongPress = UILongPressGestureRecognizer(target: self, action: #selector(longPress)) - self.bubbleImage.addGestureRecognizer(messageLongPress) - } - - func initSubviewsLayout(){ - if NEKitChatConfig.shared.ui.avatarType == .rectangle { - avatarImage.layer.cornerRadius = NEKitChatConfig.shared.ui.avatarCornerRadius - }else if NEKitChatConfig.shared.ui.avatarType == .cycle { - avatarImage.layer.cornerRadius = 16.0 - } + let tap = UITapGestureRecognizer(target: self, action: #selector(tapAvatar)) + avatarImage.addGestureRecognizer(tap) + + let messageTap = UITapGestureRecognizer(target: self, action: #selector(tapMessage)) + bubbleImage.addGestureRecognizer(messageTap) + + let messageLongPress = UILongPressGestureRecognizer( + target: self, + action: #selector(longPress) + ) + bubbleImage.addGestureRecognizer(messageLongPress) + } + + func initSubviewsLayout() { + if NEKitChatConfig.shared.ui.avatarType == .rectangle { + avatarImage.layer.cornerRadius = NEKitChatConfig.shared.ui.avatarCornerRadius + } else if NEKitChatConfig.shared.ui.avatarType == .cycle { + avatarImage.layer.cornerRadius = 16.0 } - - + } + // MARK: event - @objc func tapAvatar(tap: UITapGestureRecognizer) { - print(#function) - self.delegate?.didTapAvatarView(self, self.model) + + @objc func tapAvatar(tap: UITapGestureRecognizer) { + print(#function) + delegate?.didTapAvatarView(self, model) + } + + @objc func tapMessage(tap: UITapGestureRecognizer) { + print(#function) + delegate?.didTapMessageView(self, model) + } + + @objc func longPress(longPress: UILongPressGestureRecognizer) { + print(#function) + switch longPress.state { + case .began: + print("state:begin") + delegate?.didLongPressMessageView(self, model) + case .changed: + print("state:changed") + case .ended: + print("state:ended") + case .cancelled: + print("state:cancelled") + case .failed: + print("state:failed") + default: + print("state:default") } - - @objc func tapMessage(tap: UITapGestureRecognizer) { - print(#function) - self.delegate?.didTapMessageView(self, self.model) + } + +// MARK: set data + + func setModel(_ model: MessageContentModel) { + self.model = model + updatePinStatus(model) + bubbleW?.constant = model.contentSize.width + // avatar + nameLabel.text = model.shortName + if model.fullNameHeight > 0 { + fullNameLabel.text = model.fullName + fullNameLabel.isHidden = false + } else { + fullNameLabel.text = nil + fullNameLabel.isHidden = true } - - @objc func longPress(longPress: UILongPressGestureRecognizer) { - print(#function) - switch longPress.state { - case .began: - print("state:begin") - self.delegate?.didLongPressMessageView(self, self.model) - case .changed: - print("state:changed") - case .ended: - print("state:ended") - case .cancelled: - print("state:cancelled") - case .failed: - print("state:failed") - default: - print("state:default") + fullNameH?.constant = CGFloat(model.fullNameHeight) + avatarImage.backgroundColor = UIColor + .colorWithNumber(number: UInt64(model.message?.from ?? "0")) + if let avatarURL = model.avatar { + avatarImage + .sd_setImage(with: URL(string: avatarURL)) { [weak self] image, error, type, url in + if image != nil { + self?.avatarImage.image = image + self?.nameLabel.isHidden = true + } else { + self?.avatarImage.image = nil + self?.nameLabel.isHidden = false + } } + } else { + avatarImage.image = nil + nameLabel.isHidden = false } - -// MARK: set data - func setModel(_ model: MessageContentModel) { - self.model = model - self.updatePinStatus(model) - bubbleW?.constant = model.contentSize.width - //avatar - self.nameLabel.text = model.shortName - if model.fullNameHeight > 0 { - self.fullNameLabel.text = model.fullName - self.fullNameLabel.isHidden = false - }else { - self.fullNameLabel.text = nil - self.fullNameLabel.isHidden = true - } - fullNameH?.constant = CGFloat(model.fullNameHeight) - self.avatarImage.backgroundColor = UIColor.colorWithNumber(number: UInt64(model.message?.from ?? "0")) - if let avatarURL = model.avatar { - self.avatarImage.sd_setImage(with: URL(string: avatarURL)) { [weak self] image, error, type, url in - if image != nil { - self?.avatarImage.image = image - self?.nameLabel.isHidden = true - }else { - self?.avatarImage.image = nil - self?.nameLabel.isHidden = false - } - } - }else { - self.avatarImage.image = nil - self.nameLabel.isHidden = false - } - switch model.message?.deliveryState { - case .delivering: - self.activityView.messageStatus = .sending - case .deliveried: - self.activityView.messageStatus = .successed - case .failed: - self.activityView.messageStatus = .failed - default: break - } + switch model.message?.deliveryState { + case .delivering: + activityView.messageStatus = .sending + case .deliveried: + activityView.messageStatus = .successed + case .failed: + activityView.messageStatus = .failed + default: break } - - private func updatePinStatus(_ model: MessageContentModel) { - self.pinLabel.isHidden = !model.isPined - self.pinImage.isHidden = !model.isPined - self.contentView.backgroundColor = model.isPined ? NEKitChatConfig.shared.ui.chatPinColor : .white - if model.isPined { - if let text = model.pinShowName { - self.pinLabel.text = text + localizable("pin_text") - } - self.pinImage.image = UIImage.ne_imageNamed(name: "msg_pin") - pinLabelH?.constant = chat_pin_height - - }else { - self.pinImage.image = nil - pinLabelH?.constant = 0 + } - } + private func updatePinStatus(_ model: MessageContentModel) { + pinLabel.isHidden = !model.isPined + pinImage.isHidden = !model.isPined + contentView.backgroundColor = model.isPined ? NEKitChatConfig.shared.ui + .chatPinColor : .white + if model.isPined { + if let text = model.pinShowName { + pinLabel.text = text + localizable("pin_text") + } + pinImage.image = UIImage.ne_imageNamed(name: "msg_pin") + pinLabelH?.constant = chat_pin_height + + } else { + pinImage.image = nil + pinLabelH?.constant = 0 } + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatBaseRightCell.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatBaseRightCell.swift index 16232633..39fef35f 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatBaseRightCell.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatBaseRightCell.swift @@ -1,247 +1,278 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCoreIM import NEKitCore protocol ChatBaseCellDelegate: AnyObject { - func didTapAvatarView(_ cell: UITableViewCell, _ model: MessageContentModel?) - func didTapMessageView(_ cell: UITableViewCell, _ model: MessageContentModel?) - func didLongPressMessageView(_ cell: UITableViewCell, _ model: MessageContentModel?) - func didTapResendView(_ cell: UITableViewCell, _ model: MessageContentModel?) + func didTapAvatarView(_ cell: UITableViewCell, _ model: MessageContentModel?) + func didTapMessageView(_ cell: UITableViewCell, _ model: MessageContentModel?) + func didLongPressMessageView(_ cell: UITableViewCell, _ model: MessageContentModel?) + func didTapResendView(_ cell: UITableViewCell, _ model: MessageContentModel?) // reedit button event on revokecell - func didTapReeditButton(_ cell: UITableViewCell, _ model: MessageContentModel?) - func didTapReadView(_ cell: UITableViewCell, _ model: MessageContentModel?) - + func didTapReeditButton(_ cell: UITableViewCell, _ model: MessageContentModel?) + func didTapReadView(_ cell: UITableViewCell, _ model: MessageContentModel?) } class ChatBaseRightCell: ChatBaseCell { - public var pinImage = UIImageView() - public var avatarImage = UIImageView() - public var nameLabel = UILabel() - public var bubbleImage = UIImageView() - public var activityView = ChatActivityIndicatorView() - public var readView = CirleProgressView(frame: CGRect(x: 0, y: 0, width: 16, height: 16)) - public var seletedBtn = UIButton(type: .custom) - public var pinLabel = UILabel() - public var bubbleW: NSLayoutConstraint? - public weak var delegate: ChatBaseCellDelegate? - public var model: MessageContentModel? - private let bubbleWidth = 32.0 - private var pinLabelW: NSLayoutConstraint? - private var pinLabelH: NSLayoutConstraint? - - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - baseCommonUI() - addGesture() - initSubviewsLayout() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func baseCommonUI() { - // avatar - self.selectionStyle = .none - self.backgroundColor = .white - self.avatarImage.layer.cornerRadius = 16 - self.avatarImage.backgroundColor = UIColor(hexString: "#537FF4") - self.avatarImage.translatesAutoresizingMaskIntoConstraints = false - self.avatarImage.clipsToBounds = true - self.avatarImage.isUserInteractionEnabled = true - self.avatarImage.contentMode = .scaleAspectFill - self.contentView.addSubview(self.avatarImage) - NSLayoutConstraint.activate([ - self.avatarImage.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -16), - self.avatarImage.widthAnchor.constraint(equalToConstant: 32), - self.avatarImage.heightAnchor.constraint(equalToConstant: 32), - self.avatarImage.topAnchor.constraint(equalTo: self.topAnchor, constant: 4) - ]) - - // name - self.nameLabel.textAlignment = .center - self.nameLabel.translatesAutoresizingMaskIntoConstraints = false - self.nameLabel.font = UIFont.systemFont(ofSize: 12) - self.nameLabel.textColor = .white - self.contentView.addSubview(self.nameLabel) - NSLayoutConstraint.activate([ - self.nameLabel.leftAnchor.constraint(equalTo: self.avatarImage.leftAnchor), - self.nameLabel.rightAnchor.constraint(equalTo: self.avatarImage.rightAnchor), - self.nameLabel.topAnchor.constraint(equalTo: self.avatarImage.topAnchor), - self.nameLabel.bottomAnchor.constraint(equalTo: self.avatarImage.bottomAnchor), - ]) - + public var pinImage = UIImageView() + public var avatarImage = UIImageView() + public var nameLabel = UILabel() + public var bubbleImage = UIImageView() + public var activityView = ChatActivityIndicatorView() + public var readView = CirleProgressView(frame: CGRect(x: 0, y: 0, width: 16, height: 16)) + public var seletedBtn = UIButton(type: .custom) + public var pinLabel = UILabel() + public var bubbleW: NSLayoutConstraint? + public weak var delegate: ChatBaseCellDelegate? + public var model: MessageContentModel? + private let bubbleWidth = 32.0 + private var pinLabelW: NSLayoutConstraint? + private var pinLabelH: NSLayoutConstraint? + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + baseCommonUI() + addGesture() + initSubviewsLayout() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func baseCommonUI() { + // avatar + selectionStyle = .none + backgroundColor = .white + avatarImage.layer.cornerRadius = 16 + avatarImage.backgroundColor = UIColor(hexString: "#537FF4") + avatarImage.translatesAutoresizingMaskIntoConstraints = false + avatarImage.clipsToBounds = true + avatarImage.isUserInteractionEnabled = true + avatarImage.contentMode = .scaleAspectFill + contentView.addSubview(avatarImage) + NSLayoutConstraint.activate([ + avatarImage.rightAnchor.constraint(equalTo: rightAnchor, constant: -16), + avatarImage.widthAnchor.constraint(equalToConstant: 32), + avatarImage.heightAnchor.constraint(equalToConstant: 32), + avatarImage.topAnchor.constraint(equalTo: topAnchor, constant: 4), + ]) + + // name + nameLabel.textAlignment = .center + nameLabel.translatesAutoresizingMaskIntoConstraints = false + nameLabel.font = UIFont.systemFont(ofSize: 12) + nameLabel.textColor = .white + contentView.addSubview(nameLabel) + NSLayoutConstraint.activate([ + nameLabel.leftAnchor.constraint(equalTo: avatarImage.leftAnchor), + nameLabel.rightAnchor.constraint(equalTo: avatarImage.rightAnchor), + nameLabel.topAnchor.constraint(equalTo: avatarImage.topAnchor), + nameLabel.bottomAnchor.constraint(equalTo: avatarImage.bottomAnchor), + ]) + // bubbleImage - self.bubbleImage.translatesAutoresizingMaskIntoConstraints = false - if let image = NEKitChatConfig.shared.ui.rightBubbleBg { - self.bubbleImage.image = image.resizableImage(withCapInsets: UIEdgeInsets.init(top: 35, left: 25, bottom: 10, right: 25)) - } - self.bubbleImage.isUserInteractionEnabled = true - self.contentView.addSubview(self.bubbleImage) - let top = NSLayoutConstraint.init(item: self.bubbleImage, attribute: .top, relatedBy: .equal, toItem: self.contentView, attribute: .top, multiplier: 1.0, constant: 4) - let right = NSLayoutConstraint.init(item: self.bubbleImage, attribute: .right, relatedBy: .equal, toItem: self.avatarImage, attribute: .left, multiplier: 1.0, constant: -8) - bubbleW = NSLayoutConstraint.init(item: self.bubbleImage, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: bubbleWidth) - self.contentView.addConstraints([top, right]) - self.bubbleImage.addConstraint(bubbleW!) + bubbleImage.translatesAutoresizingMaskIntoConstraints = false + if let image = NEKitChatConfig.shared.ui.rightBubbleBg { + bubbleImage.image = image + .resizableImage(withCapInsets: UIEdgeInsets(top: 35, left: 25, bottom: 10, right: 25)) + } + bubbleImage.isUserInteractionEnabled = true + contentView.addSubview(bubbleImage) + let top = NSLayoutConstraint( + item: bubbleImage, + attribute: .top, + relatedBy: .equal, + toItem: contentView, + attribute: .top, + multiplier: 1.0, + constant: 4 + ) + let right = NSLayoutConstraint( + item: bubbleImage, + attribute: .right, + relatedBy: .equal, + toItem: avatarImage, + attribute: .left, + multiplier: 1.0, + constant: -8 + ) + bubbleW = NSLayoutConstraint( + item: bubbleImage, + attribute: .width, + relatedBy: .equal, + toItem: nil, + attribute: .notAnAttribute, + multiplier: 1.0, + constant: bubbleWidth + ) + contentView.addConstraints([top, right]) + bubbleImage.addConstraint(bubbleW!) // activityView - self.contentView.addSubview(activityView) - self.activityView.translatesAutoresizingMaskIntoConstraints = false - self.activityView.failBtn.addTarget(self, action: #selector(resend), for: .touchUpInside) - NSLayoutConstraint.activate([ - self.activityView.rightAnchor.constraint(equalTo: self.bubbleImage.leftAnchor, constant: -8), - self.activityView.centerYAnchor.constraint(equalTo: self.bubbleImage.centerYAnchor, constant: 0), - self.activityView.widthAnchor.constraint(equalToConstant: 25), - self.activityView.heightAnchor.constraint(equalToConstant: 25), - ]) - + contentView.addSubview(activityView) + activityView.translatesAutoresizingMaskIntoConstraints = false + activityView.failBtn.addTarget(self, action: #selector(resend), for: .touchUpInside) + NSLayoutConstraint.activate([ + activityView.rightAnchor.constraint(equalTo: bubbleImage.leftAnchor, constant: -8), + activityView.centerYAnchor.constraint(equalTo: bubbleImage.centerYAnchor, constant: 0), + activityView.widthAnchor.constraint(equalToConstant: 25), + activityView.heightAnchor.constraint(equalToConstant: 25), + ]) + // readView - self.contentView.addSubview(readView) - self.readView.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - self.readView.rightAnchor.constraint(equalTo: self.bubbleImage.leftAnchor, constant: -8), - self.readView.bottomAnchor.constraint(equalTo: self.bubbleImage.bottomAnchor, constant: 0), - self.readView.widthAnchor.constraint(equalToConstant: 16), - self.readView.heightAnchor.constraint(equalToConstant: 16), - ]) - + contentView.addSubview(readView) + readView.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + readView.rightAnchor.constraint(equalTo: bubbleImage.leftAnchor, constant: -8), + readView.bottomAnchor.constraint(equalTo: bubbleImage.bottomAnchor, constant: 0), + readView.widthAnchor.constraint(equalToConstant: 16), + readView.heightAnchor.constraint(equalToConstant: 16), + ]) + // seletedBtn - self.contentView.addSubview(seletedBtn) - self.seletedBtn.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - self.seletedBtn.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 16), - self.seletedBtn.centerYAnchor.constraint(equalTo: self.centerYAnchor, constant: 0), - self.seletedBtn.widthAnchor.constraint(equalToConstant: 18), - self.seletedBtn.heightAnchor.constraint(equalToConstant: 18), - ]) - - self.contentView.addSubview(pinLabel) - self.pinLabel.translatesAutoresizingMaskIntoConstraints = false - pinLabel.textColor = UIColor.ne_greenText - pinLabel.font = UIFont.systemFont(ofSize: 12) - pinLabel.textAlignment = .right - pinLabelW = self.pinLabel.widthAnchor.constraint(equalToConstant: 210) - pinLabelH = self.pinLabel.heightAnchor.constraint(equalToConstant: 0) - NSLayoutConstraint.activate([ - self.pinLabel.topAnchor.constraint(equalTo: self.bubbleImage.bottomAnchor, constant: 4), - self.pinLabel.rightAnchor.constraint(equalTo: self.bubbleImage.rightAnchor, constant: 0), - pinLabelW!, - pinLabelH!, - self.pinLabel.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -4), - ]) - - pinImage.translatesAutoresizingMaskIntoConstraints = false - pinImage.contentMode = .scaleAspectFit - self.contentView.addSubview(pinImage) - NSLayoutConstraint.activate([ - pinImage.topAnchor.constraint(equalTo: self.bubbleImage.bottomAnchor, constant: 4), - pinImage.widthAnchor.constraint(equalToConstant: 10), - pinImage.rightAnchor.constraint(equalTo: self.pinLabel.leftAnchor, constant: -2), - pinImage.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -4), - ]) - } - - func addGesture() { + contentView.addSubview(seletedBtn) + seletedBtn.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + seletedBtn.leftAnchor.constraint(equalTo: leftAnchor, constant: 16), + seletedBtn.centerYAnchor.constraint(equalTo: centerYAnchor, constant: 0), + seletedBtn.widthAnchor.constraint(equalToConstant: 18), + seletedBtn.heightAnchor.constraint(equalToConstant: 18), + ]) + + contentView.addSubview(pinLabel) + pinLabel.translatesAutoresizingMaskIntoConstraints = false + pinLabel.textColor = UIColor.ne_greenText + pinLabel.font = UIFont.systemFont(ofSize: 12) + pinLabel.textAlignment = .right + pinLabelW = pinLabel.widthAnchor.constraint(equalToConstant: 210) + pinLabelH = pinLabel.heightAnchor.constraint(equalToConstant: 0) + NSLayoutConstraint.activate([ + pinLabel.topAnchor.constraint(equalTo: bubbleImage.bottomAnchor, constant: 4), + pinLabel.rightAnchor.constraint(equalTo: bubbleImage.rightAnchor, constant: 0), + pinLabelW!, + pinLabelH!, + pinLabel.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -4), + ]) + + pinImage.translatesAutoresizingMaskIntoConstraints = false + pinImage.contentMode = .scaleAspectFit + contentView.addSubview(pinImage) + NSLayoutConstraint.activate([ + pinImage.topAnchor.constraint(equalTo: bubbleImage.bottomAnchor, constant: 4), + pinImage.widthAnchor.constraint(equalToConstant: 10), + pinImage.rightAnchor.constraint(equalTo: pinLabel.leftAnchor, constant: -2), + pinImage.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -4), + ]) + } + + func addGesture() { // avatar - let tap = UITapGestureRecognizer(target: self, action: #selector(tapAvatar)) - self.avatarImage.addGestureRecognizer(tap) - - let messageTap = UITapGestureRecognizer(target: self, action: #selector(tapMessage)) - self.bubbleImage.addGestureRecognizer(messageTap) - - let messageLongPress = UILongPressGestureRecognizer(target: self, action: #selector(longPress)) + let tap = UITapGestureRecognizer(target: self, action: #selector(tapAvatar)) + avatarImage.addGestureRecognizer(tap) + + let messageTap = UITapGestureRecognizer(target: self, action: #selector(tapMessage)) + bubbleImage.addGestureRecognizer(messageTap) + + let messageLongPress = UILongPressGestureRecognizer( + target: self, + action: #selector(longPress) + ) // messageLongPress.minimumPressDuration - self.bubbleImage.addGestureRecognizer(messageLongPress) - - let tapReadView = UITapGestureRecognizer(target: self, action: #selector(tapReadView)) - self.readView.addGestureRecognizer(tapReadView) - - } - - func initSubviewsLayout(){ - if NEKitChatConfig.shared.ui.avatarType == .rectangle { - avatarImage.layer.cornerRadius = NEKitChatConfig.shared.ui.avatarCornerRadius - }else if NEKitChatConfig.shared.ui.avatarType == .cycle { - avatarImage.layer.cornerRadius = 16.0 - } + bubbleImage.addGestureRecognizer(messageLongPress) + + let tapReadView = UITapGestureRecognizer(target: self, action: #selector(tapReadView)) + readView.addGestureRecognizer(tapReadView) + } + + func initSubviewsLayout() { + if NEKitChatConfig.shared.ui.avatarType == .rectangle { + avatarImage.layer.cornerRadius = NEKitChatConfig.shared.ui.avatarCornerRadius + } else if NEKitChatConfig.shared.ui.avatarType == .cycle { + avatarImage.layer.cornerRadius = 16.0 } - + } + // MARK: event - @objc func tapAvatar(tap: UITapGestureRecognizer) { - print(#function) - self.delegate?.didTapAvatarView(self, self.model) - } - - @objc func tapMessage(tap: UITapGestureRecognizer) { - print(#function) - self.delegate?.didTapMessageView(self, self.model) - } - - @objc func longPress(longPress: UILongPressGestureRecognizer) { - print(#function) - switch longPress.state { - case .began: - print("state:begin") - self.delegate?.didLongPressMessageView(self, self.model) - case .changed: - print("state:changed") - case .ended: - print("state:ended") - case .cancelled: - print("state:cancelled") - case .failed: - print("state:failed") - default: - print("state:default") - } - } - - @objc func resend(button: UIButton) { - print("state:default") - self.delegate?.didTapResendView(self, self.model) - } - - @objc func tapReadView(tap: UITapGestureRecognizer) { - print(#function) - self.delegate?.didTapReadView(self, self.model) + + @objc func tapAvatar(tap: UITapGestureRecognizer) { + print(#function) + delegate?.didTapAvatarView(self, model) + } + + @objc func tapMessage(tap: UITapGestureRecognizer) { + print(#function) + delegate?.didTapMessageView(self, model) + } + + @objc func longPress(longPress: UILongPressGestureRecognizer) { + print(#function) + switch longPress.state { + case .began: + print("state:begin") + delegate?.didLongPressMessageView(self, model) + case .changed: + print("state:changed") + case .ended: + print("state:ended") + case .cancelled: + print("state:cancelled") + case .failed: + print("state:failed") + default: + print("state:default") } + } + + @objc func resend(button: UIButton) { + print("state:default") + delegate?.didTapResendView(self, model) + } + + @objc func tapReadView(tap: UITapGestureRecognizer) { + print(#function) + delegate?.didTapReadView(self, model) + } + // MARK: set data - func setModel(_ model: MessageContentModel) { - self.model = model - self.updatePinStatus(model) - - bubbleW?.constant = model.contentSize.width + + func setModel(_ model: MessageContentModel) { + self.model = model + updatePinStatus(model) + + bubbleW?.constant = model.contentSize.width // print("set model width : ", model.contentSize.width) - //avatar - self.nameLabel.text = model.shortName - self.avatarImage.backgroundColor = UIColor.colorWithNumber(number: UInt64(model.message?.from ?? "0")) - if let avatarURL = model.avatar { - self.avatarImage.sd_setImage(with: URL(string: avatarURL)) { [weak self] image, error, type, url in - if error == nil { - self?.nameLabel.isHidden = true - }else { - self?.nameLabel.isHidden = false - } - } - }else { - self.avatarImage.image = nil - self.nameLabel.isHidden = false + // avatar + nameLabel.text = model.shortName + avatarImage.backgroundColor = UIColor + .colorWithNumber(number: UInt64(model.message?.from ?? "0")) + if let avatarURL = model.avatar { + avatarImage + .sd_setImage(with: URL(string: avatarURL)) { [weak self] image, error, type, url in + if error == nil { + self?.nameLabel.isHidden = true + } else { + self?.nameLabel.isHidden = false + } } - switch model.message?.deliveryState { - case .delivering: - self.activityView.messageStatus = .sending - case .deliveried: - self.activityView.messageStatus = .successed - case .failed: - self.activityView.messageStatus = .failed - default: break - } - + } else { + avatarImage.image = nil + nameLabel.isHidden = false + } + switch model.message?.deliveryState { + case .delivering: + activityView.messageStatus = .sending + case .deliveried: + activityView.messageStatus = .successed + case .failed: + activityView.messageStatus = .failed + default: break + } + // read status // if SettingProvider.shared.getMessageRead() && model.message?.deliveryState == .deliveried { // self.readView.isHidden = false @@ -264,59 +295,62 @@ class ChatBaseRightCell: ChatBaseCell { // }else { // readView.isHidden = true // } - - if model.message?.deliveryState == .deliveried { - if model.message?.session?.sessionType == .P2P { - let receiptEnable = model.message?.setting?.teamReceiptEnabled ?? false - if receiptEnable { - self.readView.isHidden = false - if let read = model.message?.isRemoteRead, read { - readView.progress = 1 - }else { - readView.progress = 0 - } - }else { - self.readView.isHidden = true - } - - }else if model.message?.session?.sessionType == .team { - let receiptEnable = model.message?.setting?.teamReceiptEnabled ?? false - if receiptEnable { - self.readView.isHidden = false - let readCount = model.message?.teamReceiptInfo?.readCount ?? 0 - let unreadCount = model.message?.teamReceiptInfo?.unreadCount ?? 0 - let total = Float(readCount + unreadCount) - if total > 0 { - readView.progress = Float(readCount)/total - }else { - readView.progress = 0 - } - }else { - readView.isHidden = true - } - } - }else { - readView.isHidden = true + + if model.message?.deliveryState == .deliveried { + if model.message?.session?.sessionType == .P2P { + let receiptEnable = model.message?.setting?.teamReceiptEnabled ?? false + if receiptEnable { + readView.isHidden = false + if let read = model.message?.isRemoteRead, read { + readView.progress = 1 + } else { + readView.progress = 0 + } + } else { + readView.isHidden = true } - - } - - private func updatePinStatus(_ model: MessageContentModel) { - self.pinLabel.isHidden = !model.isPined - self.pinImage.isHidden = !model.isPined - self.contentView.backgroundColor = model.isPined ? NEKitChatConfig.shared.ui.chatPinColor : .white - if model.isPined { - if let text = model.pinShowName { - self.pinLabel.text = text + localizable("pin_text") - } - self.pinImage.image = UIImage.ne_imageNamed(name: "msg_pin") - let size = String.getTextRectSize(self.pinLabel.text ?? localizable("pin_text"), font: UIFont.systemFont(ofSize: 11.0), size: CGSize(width: kScreenWidth - 56 - 22, height: CGFloat.greatestFiniteMagnitude)) - self.pinLabelW?.constant = size.width - pinLabelH?.constant = chat_pin_height - }else { - self.pinImage.image = nil - pinLabelH?.constant = 0 + + } else if model.message?.session?.sessionType == .team { + let receiptEnable = model.message?.setting?.teamReceiptEnabled ?? false + if receiptEnable { + readView.isHidden = false + let readCount = model.message?.teamReceiptInfo?.readCount ?? 0 + let unreadCount = model.message?.teamReceiptInfo?.unreadCount ?? 0 + let total = Float(readCount + unreadCount) + if total > 0 { + readView.progress = Float(readCount) / total + } else { + readView.progress = 0 + } + } else { + readView.isHidden = true } + } + } else { + readView.isHidden = true } + } + private func updatePinStatus(_ model: MessageContentModel) { + pinLabel.isHidden = !model.isPined + pinImage.isHidden = !model.isPined + contentView.backgroundColor = model.isPined ? NEKitChatConfig.shared.ui + .chatPinColor : .white + if model.isPined { + if let text = model.pinShowName { + pinLabel.text = text + localizable("pin_text") + } + pinImage.image = UIImage.ne_imageNamed(name: "msg_pin") + let size = String.getTextRectSize( + pinLabel.text ?? localizable("pin_text"), + font: UIFont.systemFont(ofSize: 11.0), + size: CGSize(width: kScreenWidth - 56 - 22, height: CGFloat.greatestFiniteMagnitude) + ) + pinLabelW?.constant = size.width + pinLabelH?.constant = chat_pin_height + } else { + pinImage.image = nil + pinLabelH?.constant = 0 + } + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatImageLeftCell.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatImageLeftCell.swift index dcfc36a3..4321f13a 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatImageLeftCell.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatImageLeftCell.swift @@ -1,41 +1,55 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NIMSDK class ChatImageLeftCell: ChatBaseLeftCell { - public let contentImageView = UIImageView() - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - commonUI() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func commonUI() { - contentImageView.translatesAutoresizingMaskIntoConstraints = false - contentImageView.contentMode = .scaleAspectFill - contentImageView.clipsToBounds = true - contentImageView.addCustomCorner(conrners: [.bottomLeft, .bottomRight, .topRight], radius: 8, backcolor: .white) - bubbleImage.addSubview(contentImageView) - NSLayoutConstraint.activate([ - self.contentImageView.rightAnchor.constraint(equalTo: bubbleImage.rightAnchor, constant: 0), - self.contentImageView.leftAnchor.constraint(equalTo: bubbleImage.leftAnchor, constant: 0), - self.contentImageView.topAnchor.constraint(equalTo: bubbleImage.topAnchor, constant: 0), - self.contentImageView.bottomAnchor.constraint(equalTo: bubbleImage.bottomAnchor, constant: 0) - ]) - } - - override func setModel(_ model: MessageContentModel) { - super.setModel(model) - if let m = model as? MessageImageModel,let url = m.imageUrl { - contentImageView.sd_setImage(with: URL.init(string: url), placeholderImage: nil, options: .retryFailed, progress: nil, completed: nil) - }else { - contentImageView.image = nil - } + public let contentImageView = UIImageView() + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + commonUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func commonUI() { + contentImageView.translatesAutoresizingMaskIntoConstraints = false + contentImageView.contentMode = .scaleAspectFill + contentImageView.clipsToBounds = true + contentImageView.addCustomCorner( + conrners: [.bottomLeft, .bottomRight, .topRight], + radius: 8, + backcolor: .white + ) + bubbleImage.addSubview(contentImageView) + NSLayoutConstraint.activate([ + contentImageView.rightAnchor.constraint(equalTo: bubbleImage.rightAnchor, constant: 0), + contentImageView.leftAnchor.constraint(equalTo: bubbleImage.leftAnchor, constant: 0), + contentImageView.topAnchor.constraint(equalTo: bubbleImage.topAnchor, constant: 0), + contentImageView.bottomAnchor.constraint( + equalTo: bubbleImage.bottomAnchor, + constant: 0 + ), + ]) + } + + override func setModel(_ model: MessageContentModel) { + super.setModel(model) + if let m = model as? MessageImageModel, let url = m.imageUrl { + contentImageView.sd_setImage( + with: URL(string: url), + placeholderImage: nil, + options: .retryFailed, + progress: nil, + completed: nil + ) + } else { + contentImageView.image = nil } + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatImageRightCell.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatImageRightCell.swift index 851691e3..b0ef0d55 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatImageRightCell.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatImageRightCell.swift @@ -1,46 +1,60 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NIMSDK class ChatImageRightCell: ChatBaseRightCell { - public let contentImageView = UIImageView() - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - commonUI() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func commonUI() { - contentImageView.translatesAutoresizingMaskIntoConstraints = false - contentImageView.contentMode = .scaleAspectFill - contentImageView.addCustomCorner(conrners: [.topLeft, .bottomLeft, .bottomRight], radius: 8, backcolor: .white) - contentImageView.clipsToBounds = true - - bubbleImage.addSubview(contentImageView) - NSLayoutConstraint.activate([ - self.contentImageView.rightAnchor.constraint(equalTo: bubbleImage.rightAnchor, constant: 0), - self.contentImageView.leftAnchor.constraint(equalTo: bubbleImage.leftAnchor, constant: 0), - self.contentImageView.topAnchor.constraint(equalTo: bubbleImage.topAnchor, constant: 0), - self.contentImageView.bottomAnchor.constraint(equalTo: bubbleImage.bottomAnchor, constant: 0) - ]) + public let contentImageView = UIImageView() + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + commonUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func commonUI() { + contentImageView.translatesAutoresizingMaskIntoConstraints = false + contentImageView.contentMode = .scaleAspectFill + contentImageView.addCustomCorner( + conrners: [.topLeft, .bottomLeft, .bottomRight], + radius: 8, + backcolor: .white + ) + contentImageView.clipsToBounds = true + + bubbleImage.addSubview(contentImageView) + NSLayoutConstraint.activate([ + contentImageView.rightAnchor.constraint(equalTo: bubbleImage.rightAnchor, constant: 0), + contentImageView.leftAnchor.constraint(equalTo: bubbleImage.leftAnchor, constant: 0), + contentImageView.topAnchor.constraint(equalTo: bubbleImage.topAnchor, constant: 0), + contentImageView.bottomAnchor.constraint( + equalTo: bubbleImage.bottomAnchor, + constant: 0 + ), + ]) + } + + override func setModel(_ model: MessageContentModel) { + super.setModel(model) + if let m = model as? MessageImageModel, let imageUrl = m.imageUrl { + if imageUrl.hasPrefix("http") { + contentImageView.sd_setImage( + with: URL(string: imageUrl), + placeholderImage: nil, + options: .retryFailed, + progress: nil, + completed: nil + ) + } else { + contentImageView.image = UIImage(contentsOfFile: imageUrl) + } } - - override func setModel(_ model: MessageContentModel) { - super.setModel(model) - if let m = model as? MessageImageModel,let imageUrl = m.imageUrl { - if imageUrl.hasPrefix("http") { - contentImageView.sd_setImage(with: URL.init(string: imageUrl), placeholderImage: nil, options: .retryFailed, progress: nil, completed: nil) - }else { - contentImageView.image = UIImage(contentsOfFile: imageUrl) - } - } - + // if let imageObject = model.message?.messageObject as? NIMImageObject { // if let filePath = imageObject.path { // contentImageView.image = UIImage.init(contentsOfFile: filePath) @@ -48,6 +62,5 @@ class ChatImageRightCell: ChatBaseRightCell { // contentImageView.sd_setImage(with: URL.init(string: imageObject.url ?? ""), placeholderImage: nil, options: .retryFailed, progress: nil, completed: nil) // } // } - } - + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatReplyLeftCell.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatReplyLeftCell.swift index ac2461f2..aaa8341a 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatReplyLeftCell.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatReplyLeftCell.swift @@ -1,62 +1,67 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class ChatReplyLeftCell: ChatBaseLeftCell { + public let replyLabel = UILabel() + public let textView = UITextView() + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + commonUI() + } - public let replyLabel = UILabel() - public let textView = UITextView() - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - commonUI() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func commonUI() { - replyLabel.font = UIFont.systemFont(ofSize: 12) - replyLabel.textColor = UIColor(hexString: "#929299") - replyLabel.translatesAutoresizingMaskIntoConstraints = false - self.addSubview(replyLabel) - NSLayoutConstraint.activate([ - replyLabel.leadingAnchor.constraint(equalTo: bubbleImage.leadingAnchor, constant: 8), - replyLabel.topAnchor.constraint(equalTo: bubbleImage.topAnchor, constant: qChat_margin), - replyLabel.heightAnchor.constraint(equalToConstant: 26.0), - replyLabel.trailingAnchor.constraint(equalTo: bubbleImage.trailingAnchor, constant: -8) - ]) - - textView.translatesAutoresizingMaskIntoConstraints = false - textView.isEditable = false - textView.isScrollEnabled = false - textView.showsVerticalScrollIndicator = false - textView.isUserInteractionEnabled = false - textView.textContainer.maximumNumberOfLines = 0 - textView.textContainerInset = .zero - textView.textContainer.lineFragmentPadding = 0 - textView.font = DefaultTextFont(16) - textView.backgroundColor = .red - textView.contentMode = .center - textView.backgroundColor = .clear - bubbleImage.addSubview(textView) - NSLayoutConstraint.activate([ - self.textView.rightAnchor.constraint(equalTo: bubbleImage.rightAnchor, constant: 0), - self.textView.leftAnchor.constraint(equalTo: bubbleImage.leftAnchor, constant: 8), - self.textView.topAnchor.constraint(equalTo: replyLabel.bottomAnchor, constant: -qChat_margin), - self.textView.bottomAnchor.constraint(equalTo: bubbleImage.bottomAnchor, constant: -qChat_margin) - ]) - } - - override func setModel(_ model: MessageContentModel) { - super.setModel(model) - if let m = model as? MessageTextModel { + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func commonUI() { + replyLabel.font = UIFont.systemFont(ofSize: 12) + replyLabel.textColor = UIColor(hexString: "#929299") + replyLabel.translatesAutoresizingMaskIntoConstraints = false + addSubview(replyLabel) + NSLayoutConstraint.activate([ + replyLabel.leadingAnchor.constraint(equalTo: bubbleImage.leadingAnchor, constant: 8), + replyLabel.topAnchor.constraint(equalTo: bubbleImage.topAnchor, constant: qChat_margin), + replyLabel.heightAnchor.constraint(equalToConstant: 26.0), + replyLabel.trailingAnchor.constraint(equalTo: bubbleImage.trailingAnchor, constant: -8), + ]) + + textView.translatesAutoresizingMaskIntoConstraints = false + textView.isEditable = false + textView.isScrollEnabled = false + textView.showsVerticalScrollIndicator = false + textView.isUserInteractionEnabled = false + textView.textContainer.maximumNumberOfLines = 0 + textView.textContainerInset = .zero + textView.textContainer.lineFragmentPadding = 0 + textView.font = DefaultTextFont(16) + textView.backgroundColor = .red + textView.contentMode = .center + textView.backgroundColor = .clear + bubbleImage.addSubview(textView) + NSLayoutConstraint.activate([ + textView.rightAnchor.constraint(equalTo: bubbleImage.rightAnchor, constant: 0), + textView.leftAnchor.constraint(equalTo: bubbleImage.leftAnchor, constant: 8), + textView.topAnchor.constraint( + equalTo: replyLabel.bottomAnchor, + constant: -qChat_margin + ), + textView.bottomAnchor.constraint( + equalTo: bubbleImage.bottomAnchor, + constant: -qChat_margin + ), + ]) + } + + override func setModel(_ model: MessageContentModel) { + super.setModel(model) + if let m = model as? MessageTextModel { // textView.text = m.text - textView.attributedText = m.attributeStr - } - replyLabel.text = model.replyText + textView.attributedText = m.attributeStr } - + replyLabel.text = model.replyText + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatReplyRightCell.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatReplyRightCell.swift index dc92eb42..8264b810 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatReplyRightCell.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatReplyRightCell.swift @@ -1,61 +1,67 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class ChatReplyRightCell: ChatBaseRightCell { - public let replyLabel = UILabel() - public let textView = UITextView() - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - commonUI() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func commonUI() { - replyLabel.font = UIFont.systemFont(ofSize: 12) - replyLabel.textColor = UIColor(hexString: "#929299") - replyLabel.translatesAutoresizingMaskIntoConstraints = false - self.addSubview(replyLabel) - NSLayoutConstraint.activate([ - replyLabel.leadingAnchor.constraint(equalTo: bubbleImage.leadingAnchor, constant: 8), - replyLabel.topAnchor.constraint(equalTo: bubbleImage.topAnchor, constant: qChat_margin), - replyLabel.heightAnchor.constraint(equalToConstant: 26.0), - replyLabel.trailingAnchor.constraint(equalTo: bubbleImage.trailingAnchor, constant: -8) - ]) - - textView.translatesAutoresizingMaskIntoConstraints = false - textView.isEditable = false - textView.isScrollEnabled = false - textView.showsVerticalScrollIndicator = false - textView.isUserInteractionEnabled = false - textView.textContainer.maximumNumberOfLines = 0 - textView.textContainerInset = .zero - textView.textContainer.lineFragmentPadding = 0 - textView.font = DefaultTextFont(16) - textView.backgroundColor = .red - textView.contentMode = .center - textView.backgroundColor = .clear - bubbleImage.addSubview(textView) - NSLayoutConstraint.activate([ - self.textView.rightAnchor.constraint(equalTo: bubbleImage.rightAnchor, constant: 0), - self.textView.leftAnchor.constraint(equalTo: bubbleImage.leftAnchor, constant: 8), - self.textView.topAnchor.constraint(equalTo: replyLabel.bottomAnchor, constant: -qChat_margin), - self.textView.bottomAnchor.constraint(equalTo: bubbleImage.bottomAnchor, constant: -qChat_margin) - ]) - } - - override func setModel(_ model: MessageContentModel) { - super.setModel(model) - if let m = model as? MessageTextModel { + public let replyLabel = UILabel() + public let textView = UITextView() + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + commonUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func commonUI() { + replyLabel.font = UIFont.systemFont(ofSize: 12) + replyLabel.textColor = UIColor(hexString: "#929299") + replyLabel.translatesAutoresizingMaskIntoConstraints = false + addSubview(replyLabel) + NSLayoutConstraint.activate([ + replyLabel.leadingAnchor.constraint(equalTo: bubbleImage.leadingAnchor, constant: 8), + replyLabel.topAnchor.constraint(equalTo: bubbleImage.topAnchor, constant: qChat_margin), + replyLabel.heightAnchor.constraint(equalToConstant: 26.0), + replyLabel.trailingAnchor.constraint(equalTo: bubbleImage.trailingAnchor, constant: -8), + ]) + + textView.translatesAutoresizingMaskIntoConstraints = false + textView.isEditable = false + textView.isScrollEnabled = false + textView.showsVerticalScrollIndicator = false + textView.isUserInteractionEnabled = false + textView.textContainer.maximumNumberOfLines = 0 + textView.textContainerInset = .zero + textView.textContainer.lineFragmentPadding = 0 + textView.font = DefaultTextFont(16) + textView.backgroundColor = .red + textView.contentMode = .center + textView.backgroundColor = .clear + bubbleImage.addSubview(textView) + NSLayoutConstraint.activate([ + textView.rightAnchor.constraint(equalTo: bubbleImage.rightAnchor, constant: 0), + textView.leftAnchor.constraint(equalTo: bubbleImage.leftAnchor, constant: 8), + textView.topAnchor.constraint( + equalTo: replyLabel.bottomAnchor, + constant: -qChat_margin + ), + textView.bottomAnchor.constraint( + equalTo: bubbleImage.bottomAnchor, + constant: -qChat_margin + ), + ]) + } + + override func setModel(_ model: MessageContentModel) { + super.setModel(model) + if let m = model as? MessageTextModel { // textView.text = m.text - textView.attributedText = m.attributeStr - } - replyLabel.text = model.replyText + textView.attributedText = m.attributeStr } - + replyLabel.text = model.replyText + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatRevokeLeftCell.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatRevokeLeftCell.swift index 39862d63..f07c8d58 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatRevokeLeftCell.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatRevokeLeftCell.swift @@ -1,36 +1,37 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class ChatRevokeLeftCell: ChatBaseLeftCell { - public var label = UILabel() - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - commonUI() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func commonUI() { - label.translatesAutoresizingMaskIntoConstraints = false - label.textColor = UIColor.ne_greyText - label.font = UIFont.systemFont(ofSize: 16.0) - self.bubbleImage.addSubview(label) - NSLayoutConstraint.activate([ - label.leftAnchor.constraint(equalTo: self.bubbleImage.leftAnchor, constant: 16), - label.topAnchor.constraint(equalTo: self.bubbleImage.topAnchor, constant: 0), - label.heightAnchor.constraint(equalToConstant: qChat_min_h), - label.rightAnchor.constraint(equalTo: self.bubbleImage.rightAnchor, constant: -16), - label.bottomAnchor.constraint(equalTo: self.bubbleImage.bottomAnchor, constant: 0), - ]) - } - - override func setModel(_ model: MessageContentModel) { - super.setModel(model) - label.text = localizable("message_has_be_withdrawn") - } + public var label = UILabel() + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + commonUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func commonUI() { + label.translatesAutoresizingMaskIntoConstraints = false + label.textColor = UIColor.ne_greyText + label.font = UIFont.systemFont(ofSize: 16.0) + bubbleImage.addSubview(label) + NSLayoutConstraint.activate([ + label.leftAnchor.constraint(equalTo: bubbleImage.leftAnchor, constant: 16), + label.topAnchor.constraint(equalTo: bubbleImage.topAnchor, constant: 0), + label.heightAnchor.constraint(equalToConstant: qChat_min_h), + label.rightAnchor.constraint(equalTo: bubbleImage.rightAnchor, constant: -16), + label.bottomAnchor.constraint(equalTo: bubbleImage.bottomAnchor, constant: 0), + ]) + } + + override func setModel(_ model: MessageContentModel) { + super.setModel(model) + label.text = localizable("message_has_be_withdrawn") + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatRevokeRightCell.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatRevokeRightCell.swift index d9ed3bc2..e9a094c4 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatRevokeRightCell.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatRevokeRightCell.swift @@ -1,69 +1,70 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit -//protocol ChatRevokeRightCellDelegate: ChatBaseCellDelegate { +// protocol ChatRevokeRightCellDelegate: ChatBaseCellDelegate { // func onReeditMessage(_ cell: UITableViewCell, _ model: MessageContentModel?) -//} +// } -//typealias ReeditBlock = (_ cell: ChatRevokeRightCell, _ model: MessageContentModel?) -> () +// typealias ReeditBlock = (_ cell: ChatRevokeRightCell, _ model: MessageContentModel?) -> () class ChatRevokeRightCell: ChatBaseRightCell { - public var label = UILabel() - public var reeditButton = UIButton(type: .custom) + public var label = UILabel() + public var reeditButton = UIButton(type: .custom) // public var reeditBlock: ReeditBlock? // public override var delegate: ChatBaseCellDelegate? - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - commonUI() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func commonUI() { - label.translatesAutoresizingMaskIntoConstraints = false - label.textColor = UIColor.ne_greyText - label.font = UIFont.systemFont(ofSize: 16.0) - self.bubbleImage.addSubview(label) - NSLayoutConstraint.activate([ - label.leftAnchor.constraint(equalTo: self.bubbleImage.leftAnchor, constant: 16), - label.widthAnchor.constraint(equalToConstant: 100), - label.heightAnchor.constraint(equalToConstant: qChat_min_h), - label.topAnchor.constraint(equalTo: self.bubbleImage.topAnchor, constant: 0), - label.bottomAnchor.constraint(equalTo: self.bubbleImage.bottomAnchor, constant: 0) - ]) - - reeditButton.translatesAutoresizingMaskIntoConstraints = false - reeditButton.setImage(UIImage.ne_imageNamed(name: "right_arrow"), for: .normal) - reeditButton.titleLabel?.font = UIFont.systemFont(ofSize: 16.0) - reeditButton.setTitleColor(UIColor.ne_blueText, for: .normal) - reeditButton.titleEdgeInsets = UIEdgeInsets(top: 0, left: -30, bottom: 0, right: 0) - reeditButton.imageEdgeInsets = UIEdgeInsets(top: 0, left: 70, bottom: 0, right: 0) + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + commonUI() + } - self.bubbleImage.addSubview(reeditButton) - NSLayoutConstraint.activate([ - reeditButton.leftAnchor.constraint(equalTo: self.label.rightAnchor, constant: 8), - reeditButton.rightAnchor.constraint(equalTo: self.bubbleImage.rightAnchor, constant: -8), - reeditButton.topAnchor.constraint(equalTo: self.bubbleImage.topAnchor, constant: 0), - reeditButton.bottomAnchor.constraint(equalTo: self.bubbleImage.bottomAnchor, constant: 0) - ]) - reeditButton.addTarget(self, action: #selector(reeditEvent), for: .touchUpInside) - } - - override func setModel(_ model: MessageContentModel) { - super.setModel(model) - label.text = localizable("message_has_be_withdrawn") - reeditButton.setTitle(localizable("message_reedit"), for: .normal) - //判断可编辑按钮的隐藏,只有文本才可以重新编辑 - reeditButton.isHidden = model.message?.messageType == .text ? false : true - } - - @objc func reeditEvent(button: UIButton) { - print(#function) - self.delegate?.didTapReeditButton(self, self.model) - } + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func commonUI() { + label.translatesAutoresizingMaskIntoConstraints = false + label.textColor = UIColor.ne_greyText + label.font = UIFont.systemFont(ofSize: 16.0) + bubbleImage.addSubview(label) + NSLayoutConstraint.activate([ + label.leftAnchor.constraint(equalTo: bubbleImage.leftAnchor, constant: 16), + label.widthAnchor.constraint(equalToConstant: 100), + label.heightAnchor.constraint(equalToConstant: qChat_min_h), + label.topAnchor.constraint(equalTo: bubbleImage.topAnchor, constant: 0), + label.bottomAnchor.constraint(equalTo: bubbleImage.bottomAnchor, constant: 0), + ]) + + reeditButton.translatesAutoresizingMaskIntoConstraints = false + reeditButton.setImage(UIImage.ne_imageNamed(name: "right_arrow"), for: .normal) + reeditButton.titleLabel?.font = UIFont.systemFont(ofSize: 16.0) + reeditButton.setTitleColor(UIColor.ne_blueText, for: .normal) + reeditButton.titleEdgeInsets = UIEdgeInsets(top: 0, left: -30, bottom: 0, right: 0) + reeditButton.imageEdgeInsets = UIEdgeInsets(top: 0, left: 70, bottom: 0, right: 0) + + bubbleImage.addSubview(reeditButton) + NSLayoutConstraint.activate([ + reeditButton.leftAnchor.constraint(equalTo: label.rightAnchor, constant: 8), + reeditButton.rightAnchor.constraint(equalTo: bubbleImage.rightAnchor, constant: -8), + reeditButton.topAnchor.constraint(equalTo: bubbleImage.topAnchor, constant: 0), + reeditButton.bottomAnchor.constraint(equalTo: bubbleImage.bottomAnchor, constant: 0), + ]) + reeditButton.addTarget(self, action: #selector(reeditEvent), for: .touchUpInside) + } + + override func setModel(_ model: MessageContentModel) { + super.setModel(model) + label.text = localizable("message_has_be_withdrawn") + reeditButton.setTitle(localizable("message_reedit"), for: .normal) + // 判断可编辑按钮的隐藏,只有文本才可以重新编辑 + reeditButton.isHidden = model.message?.messageType == .text ? false : true + } + + @objc func reeditEvent(button: UIButton) { + print(#function) + delegate?.didTapReeditButton(self, model) + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatTeamMemberCell.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatTeamMemberCell.swift index e0b2e123..f64e02fb 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatTeamMemberCell.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatTeamMemberCell.swift @@ -1,74 +1,72 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCommonUI import NEKitChat class ChatTeamMemberCell: UITableViewCell { - - lazy var headerView: NEUserHeaderView = { - let header = NEUserHeaderView(frame: .zero) - header.titleLabel.font = NEConstant.defaultTextFont(14) - header.titleLabel.textColor = UIColor.white - header.layer.cornerRadius = 21 - header.clipsToBounds = true - header.translatesAutoresizingMaskIntoConstraints = false - return header - }() - - lazy var nameLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.font = NEConstant.defaultTextFont(16.0) - label.textColor = .ne_darkText - return label - }() + lazy var headerView: NEUserHeaderView = { + let header = NEUserHeaderView(frame: .zero) + header.titleLabel.font = NEConstant.defaultTextFont(14) + header.titleLabel.textColor = UIColor.white + header.layer.cornerRadius = 21 + header.clipsToBounds = true + header.translatesAutoresizingMaskIntoConstraints = false + return header + }() - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) + lazy var nameLabel: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.font = NEConstant.defaultTextFont(16.0) + label.textColor = .ne_darkText + return label + }() - // Configure the view for the selected state - } - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - self.selectionStyle = .none - setupUI() - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - } - - func setupUI(){ - contentView.addSubview(headerView) - NSLayoutConstraint.activate([ - headerView.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 21), - headerView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - headerView.widthAnchor.constraint(equalToConstant: 42), - headerView.heightAnchor.constraint(equalToConstant: 42) - ]) - - contentView.addSubview(nameLabel) - NSLayoutConstraint.activate([ - nameLabel.leftAnchor.constraint(equalTo: headerView.rightAnchor, constant: 14.0), - nameLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - nameLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -70) - ]) - - } - - func configure(_ model: ChatTeamMemberInfoModel) { - if let url = model.nimUser?.userInfo?.avatarUrl { - headerView.sd_setImage(with: URL(string: url), completed: nil) - headerView.setTitle("") - }else { - headerView.image = nil - headerView.setTitle(model.showNameInTeam()) - headerView.backgroundColor = UIColor.colorWithString(string: model.nimUser?.userId) - } - nameLabel.text = model.showNameInTeam() + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + } + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + selectionStyle = .none + setupUI() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + func setupUI() { + contentView.addSubview(headerView) + NSLayoutConstraint.activate([ + headerView.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 21), + headerView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + headerView.widthAnchor.constraint(equalToConstant: 42), + headerView.heightAnchor.constraint(equalToConstant: 42), + ]) + + contentView.addSubview(nameLabel) + NSLayoutConstraint.activate([ + nameLabel.leftAnchor.constraint(equalTo: headerView.rightAnchor, constant: 14.0), + nameLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + nameLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -70), + ]) + } + + func configure(_ model: ChatTeamMemberInfoModel) { + if let url = model.nimUser?.userInfo?.avatarUrl { + headerView.sd_setImage(with: URL(string: url), completed: nil) + headerView.setTitle("") + } else { + headerView.image = nil + headerView.setTitle(model.showNameInTeam()) + headerView.backgroundColor = UIColor.colorWithString(string: model.nimUser?.userId) } - + nameLabel.text = model.showNameInTeam() + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatTextLeftCell.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatTextLeftCell.swift index 6b4ee278..a045aba2 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatTextLeftCell.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatTextLeftCell.swift @@ -1,50 +1,47 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class ChatTextLeftCell: ChatBaseLeftCell { + public let textLable = UILabel() + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + commonUI() + } - public let textLable = UILabel() - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - commonUI() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func commonUI() { - textLable.translatesAutoresizingMaskIntoConstraints = false - textLable.isEnabled = false + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func commonUI() { + textLable.translatesAutoresizingMaskIntoConstraints = false + textLable.isEnabled = false // textView.isScrollEnabled = false // textView.showsVerticalScrollIndicator = false - textLable.numberOfLines = 0 - textLable.isUserInteractionEnabled = false + textLable.numberOfLines = 0 + textLable.isUserInteractionEnabled = false // textView.textContainer.lineFragmentPadding = 0; // textView.textContainerInset = .zero; - textLable.font = DefaultTextFont(16) + textLable.font = DefaultTextFont(16) // textView.autoresizingMask = [.flexibleWidth, .flexibleHeight] - textLable.backgroundColor = .clear - bubbleImage.addSubview(textLable) - NSLayoutConstraint.activate([ - self.textLable.rightAnchor.constraint(equalTo: bubbleImage.rightAnchor, constant:0), - self.textLable.leftAnchor.constraint(equalTo: bubbleImage.leftAnchor, constant:8), - self.textLable.topAnchor.constraint(equalTo: bubbleImage.topAnchor, constant: 0), - self.textLable.bottomAnchor.constraint(equalTo: bubbleImage.bottomAnchor, constant: 0) - ]) - } - - override func setModel(_ model: MessageContentModel) { - super.setModel(model) - if let m = model as? MessageTextModel { + textLable.backgroundColor = .clear + bubbleImage.addSubview(textLable) + NSLayoutConstraint.activate([ + textLable.rightAnchor.constraint(equalTo: bubbleImage.rightAnchor, constant: 0), + textLable.leftAnchor.constraint(equalTo: bubbleImage.leftAnchor, constant: 8), + textLable.topAnchor.constraint(equalTo: bubbleImage.topAnchor, constant: 0), + textLable.bottomAnchor.constraint(equalTo: bubbleImage.bottomAnchor, constant: 0), + ]) + } + + override func setModel(_ model: MessageContentModel) { + super.setModel(model) + if let m = model as? MessageTextModel { // textView.text = m.text - textLable.attributedText = m.attributeStr - - - } + textLable.attributedText = m.attributeStr } - + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatTextRightCell.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatTextRightCell.swift index 9f4c6621..32905e70 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatTextRightCell.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatTextRightCell.swift @@ -1,42 +1,41 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class ChatTextRightCell: ChatBaseRightCell { - public let textLable = UILabel() - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - commonUI() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func commonUI() { - textLable.translatesAutoresizingMaskIntoConstraints = false - textLable.isEnabled = false - textLable.isUserInteractionEnabled = false - textLable.numberOfLines = 0 - textLable.font = DefaultTextFont(16) - bubbleImage.addSubview(textLable) - NSLayoutConstraint.activate([ - self.textLable.rightAnchor.constraint(equalTo: bubbleImage.rightAnchor, constant: 0), - self.textLable.leftAnchor.constraint(equalTo: bubbleImage.leftAnchor, constant: 8), - self.textLable.topAnchor.constraint(equalTo: bubbleImage.topAnchor, constant: 0), - self.textLable.bottomAnchor.constraint(equalTo: bubbleImage.bottomAnchor, constant: 0) - ]) - } - - override func setModel(_ model: MessageContentModel) { - super.setModel(model) - if let m = model as? MessageTextModel { + public let textLable = UILabel() + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + commonUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func commonUI() { + textLable.translatesAutoresizingMaskIntoConstraints = false + textLable.isEnabled = false + textLable.isUserInteractionEnabled = false + textLable.numberOfLines = 0 + textLable.font = DefaultTextFont(16) + bubbleImage.addSubview(textLable) + NSLayoutConstraint.activate([ + textLable.rightAnchor.constraint(equalTo: bubbleImage.rightAnchor, constant: 0), + textLable.leftAnchor.constraint(equalTo: bubbleImage.leftAnchor, constant: 8), + textLable.topAnchor.constraint(equalTo: bubbleImage.topAnchor, constant: 0), + textLable.bottomAnchor.constraint(equalTo: bubbleImage.bottomAnchor, constant: 0), + ]) + } + + override func setModel(_ model: MessageContentModel) { + super.setModel(model) + if let m = model as? MessageTextModel { // textView.text = m.text - textLable.attributedText = m.attributeStr - } + textLable.attributedText = m.attributeStr } + } } - - diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatTimeTableViewCell.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatTimeTableViewCell.swift index e935ec32..72ae48fb 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatTimeTableViewCell.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatTimeTableViewCell.swift @@ -1,39 +1,37 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class ChatTimeTableViewCell: UITableViewCell { + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + selectionStyle = .none + contentView.addSubview(timeLable) + NSLayoutConstraint.activate([ + timeLable.topAnchor.constraint(equalTo: contentView.topAnchor), + timeLable.leftAnchor.constraint(equalTo: contentView.leftAnchor), + timeLable.rightAnchor.constraint(equalTo: contentView.rightAnchor), + timeLable.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + ]) + } - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - self.selectionStyle = .none - self.contentView.addSubview(timeLable) - NSLayoutConstraint.activate([ - timeLable.topAnchor.constraint(equalTo: self.contentView.topAnchor), - timeLable.leftAnchor.constraint(equalTo: self.contentView.leftAnchor), - timeLable.rightAnchor.constraint(equalTo: self.contentView.rightAnchor), - timeLable.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor) - ]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func setModel(_ model: MessageTipsModel) { - timeLable.text = model.text - } + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } - private lazy var timeLable:UILabel = { - let label = UILabel() - label.font = DefaultTextFont(12) - label.textColor = NEKitChatConfig.shared.ui.timeColor - label.textAlignment = .center - label.translatesAutoresizingMaskIntoConstraints = false - return label - }() + func setModel(_ model: MessageTipsModel) { + timeLable.text = model.text + } - + private lazy var timeLable: UILabel = { + let label = UILabel() + label.font = DefaultTextFont(12) + label.textColor = NEKitChatConfig.shared.ui.timeColor + label.textAlignment = .center + label.translatesAutoresizingMaskIntoConstraints = false + return label + }() } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatVideoLeftCell.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatVideoLeftCell.swift index fbb058f1..46063252 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatVideoLeftCell.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatVideoLeftCell.swift @@ -1,119 +1,129 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NIMSDK class ChatVideoLeftCell: ChatImageLeftCell { - - weak var weakModel: MessageVideoModel? - - lazy var stateView: VideoStateView = { - let state = VideoStateView() - state.translatesAutoresizingMaskIntoConstraints = false - state.backgroundColor = .clear - return state - }() - - lazy var timeLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.textColor = .white - label.font = NEConstant.defaultTextFont(10.0) - label.textAlignment = .center - return label - }() - - lazy var timeView: UIView = { - let view = UIView() - view.translatesAutoresizingMaskIntoConstraints = false - view.addSubview(timeLabel) - NSLayoutConstraint.activate([ - timeLabel.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 4), - timeLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 2), - timeLabel.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -4), - timeLabel.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -2) - ]) - view.clipsToBounds = true - view.layer.cornerRadius = 4.0 - view.backgroundColor = NEConstant.hexRGB(0x000000).withAlphaComponent(0.6) - return view - }() - - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } + weak var weakModel: MessageVideoModel? - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) + lazy var stateView: VideoStateView = { + let state = VideoStateView() + state.translatesAutoresizingMaskIntoConstraints = false + state.backgroundColor = .clear + return state + }() - // Configure the view for the selected state - } - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - setupUI() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func setupUI() { - contentImageView.addSubview(stateView) - contentImageView.addCustomCorner(conrners: [.topLeft], radius: 8, backcolor: .white) - NSLayoutConstraint.activate([ - stateView.centerXAnchor.constraint(equalTo: contentImageView.centerXAnchor), - stateView.centerYAnchor.constraint(equalTo: contentImageView.centerYAnchor), - stateView.heightAnchor.constraint(equalToConstant: 60), - stateView.widthAnchor.constraint(equalToConstant: 60) - ]) - - contentImageView.addSubview(timeView) - NSLayoutConstraint.activate([ - timeView.rightAnchor.constraint(equalTo: contentImageView.rightAnchor, constant: -7), - timeView.bottomAnchor.constraint(equalTo: contentImageView.bottomAnchor, constant: -7) - ]) - } - - override func setModel(_ model: MessageContentModel) { - super.setModel(model) - if let videoObject = model.message?.messageObject as? NIMVideoObject { - if let path = videoObject.coverPath { - contentImageView.sd_setImage(with: URL(fileURLWithPath: path), placeholderImage: nil, options: .retryFailed, progress: nil, completed: nil) - }else { - contentImageView.sd_setImage(with: URL.init(string: videoObject.coverUrl ?? ""), placeholderImage: nil, options: .retryFailed, progress: nil, completed: nil) - } - - if videoObject.duration > 0 { - timeView.isHidden = false - timeLabel.text = Date.getFormatPlayTime(TimeInterval(videoObject.duration/1000)) - }else { - timeView.isHidden = true - } - - if let videoModel = model as? MessageVideoModel { - - weakModel?.cell = nil - weakModel = videoModel - videoModel.cell = self - if videoModel.state == .Success { - stateView.state = .VideoPlay - }else { - stateView.state = .VideoDownload - stateView.setProgress(videoModel.progress) - if videoModel.progress >= 1 { - videoModel.state = .Success - } - } - } + lazy var timeLabel: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.textColor = .white + label.font = NEConstant.defaultTextFont(10.0) + label.textAlignment = .center + return label + }() + + lazy var timeView: UIView = { + let view = UIView() + view.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(timeLabel) + NSLayoutConstraint.activate([ + timeLabel.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 4), + timeLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 2), + timeLabel.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -4), + timeLabel.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -2), + ]) + view.clipsToBounds = true + view.layer.cornerRadius = 4.0 + view.backgroundColor = NEConstant.hexRGB(0x000000).withAlphaComponent(0.6) + return view + }() + + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + } + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + setupUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func setupUI() { + contentImageView.addSubview(stateView) + contentImageView.addCustomCorner(conrners: [.topLeft], radius: 8, backcolor: .white) + NSLayoutConstraint.activate([ + stateView.centerXAnchor.constraint(equalTo: contentImageView.centerXAnchor), + stateView.centerYAnchor.constraint(equalTo: contentImageView.centerYAnchor), + stateView.heightAnchor.constraint(equalToConstant: 60), + stateView.widthAnchor.constraint(equalToConstant: 60), + ]) + + contentImageView.addSubview(timeView) + NSLayoutConstraint.activate([ + timeView.rightAnchor.constraint(equalTo: contentImageView.rightAnchor, constant: -7), + timeView.bottomAnchor.constraint(equalTo: contentImageView.bottomAnchor, constant: -7), + ]) + } + + override func setModel(_ model: MessageContentModel) { + super.setModel(model) + if let videoObject = model.message?.messageObject as? NIMVideoObject { + if let path = videoObject.coverPath { + contentImageView.sd_setImage( + with: URL(fileURLWithPath: path), + placeholderImage: nil, + options: .retryFailed, + progress: nil, + completed: nil + ) + } else { + contentImageView.sd_setImage( + with: URL(string: videoObject.coverUrl ?? ""), + placeholderImage: nil, + options: .retryFailed, + progress: nil, + completed: nil + ) + } + + if videoObject.duration > 0 { + timeView.isHidden = false + timeLabel.text = Date.getFormatPlayTime(TimeInterval(videoObject.duration / 1000)) + } else { + timeView.isHidden = true + } + + if let videoModel = model as? MessageVideoModel { + weakModel?.cell = nil + weakModel = videoModel + videoModel.cell = self + if videoModel.state == .Success { + stateView.state = .VideoPlay + } else { + stateView.state = .VideoDownload + stateView.setProgress(videoModel.progress) + if videoModel.progress >= 1 { + videoModel.state = .Success + } } + } } - - override func uploadProgress(_ progress: Float) { - stateView.setProgress(progress) - } + } + override func uploadProgress(_ progress: Float) { + stateView.setProgress(progress) + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatVideoRightCell.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatVideoRightCell.swift index c79eac5f..e7bf4534 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatVideoRightCell.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/ChatVideoRightCell.swift @@ -1,128 +1,136 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCommon import NIMSDK class ChatVideoRightCell: ChatImageRightCell { - - weak var weakModel: MessageVideoModel? - - lazy var stateView: VideoStateView = { - let state = VideoStateView() - state.translatesAutoresizingMaskIntoConstraints = false - state.backgroundColor = .clear - return state - }() - - lazy var timeLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.textColor = .white - label.font = NEConstant.defaultTextFont(10.0) - label.textAlignment = .center - return label - }() - - lazy var timeView: UIView = { - let view = UIView() - view.translatesAutoresizingMaskIntoConstraints = false - view.addSubview(timeLabel) - NSLayoutConstraint.activate([ - timeLabel.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 4), - timeLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 2), - timeLabel.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -4), - timeLabel.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -2) - ]) - view.clipsToBounds = true - view.layer.cornerRadius = 4.0 - view.backgroundColor = NEConstant.hexRGB(0x000000).withAlphaComponent(0.6) - return view - }() - - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } + weak var weakModel: MessageVideoModel? - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) + lazy var stateView: VideoStateView = { + let state = VideoStateView() + state.translatesAutoresizingMaskIntoConstraints = false + state.backgroundColor = .clear + return state + }() + + lazy var timeLabel: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.textColor = .white + label.font = NEConstant.defaultTextFont(10.0) + label.textAlignment = .center + return label + }() + + lazy var timeView: UIView = { + let view = UIView() + view.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(timeLabel) + NSLayoutConstraint.activate([ + timeLabel.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 4), + timeLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 2), + timeLabel.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -4), + timeLabel.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -2), + ]) + view.clipsToBounds = true + view.layer.cornerRadius = 4.0 + view.backgroundColor = NEConstant.hexRGB(0x000000).withAlphaComponent(0.6) + return view + }() + + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + } - // Configure the view for the selected state - } - // override func draw(_ rect: CGRect) { // super.draw(rect) // bubbleImage.addCorner(conrners: .allCorners ,radius: 8) // contentImageView.addCorner(conrners: .allCorners, radius: 8) // } - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - setupUI() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func setupUI() { - contentImageView.addSubview(stateView) - contentImageView.addCustomCorner(conrners: [.topRight], radius: 8, backcolor: .white) - NSLayoutConstraint.activate([ - stateView.centerXAnchor.constraint(equalTo: contentImageView.centerXAnchor), - stateView.centerYAnchor.constraint(equalTo: contentImageView.centerYAnchor), - stateView.heightAnchor.constraint(equalToConstant: 60), - stateView.widthAnchor.constraint(equalToConstant: 60) - ]) - - contentImageView.addSubview(timeView) - NSLayoutConstraint.activate([ - timeView.rightAnchor.constraint(equalTo: contentImageView.rightAnchor, constant: -7), - timeView.bottomAnchor.constraint(equalTo: contentImageView.bottomAnchor, constant: -7) - ]) - } - - override func setModel(_ model: MessageContentModel) { - super.setModel(model) - if let videoObject = model.message?.messageObject as? NIMVideoObject { - if let path = videoObject.coverPath { - contentImageView.sd_setImage(with: URL(fileURLWithPath: path), placeholderImage: nil, options: .retryFailed, progress: nil, completed: nil) - }else { - contentImageView.sd_setImage(with: URL.init(string: videoObject.coverUrl ?? ""), placeholderImage: nil, options: .retryFailed, progress: nil, completed: nil) - } - - - if videoObject.duration > 0 { - timeView.isHidden = false - timeLabel.text = Date.getFormatPlayTime(TimeInterval(videoObject.duration/1000)) - }else { - timeView.isHidden = true - } - - if let videoModel = model as? MessageVideoModel { - - weakModel?.cell = nil - weakModel = videoModel - videoModel.cell = self - if videoModel.state == .Success { - stateView.state = .VideoPlay - }else { - stateView.state = .VideoDownload - stateView.setProgress(videoModel.progress) - if videoModel.progress >= 1 { - videoModel.state = .Success - } - } - } + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + setupUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func setupUI() { + contentImageView.addSubview(stateView) + contentImageView.addCustomCorner(conrners: [.topRight], radius: 8, backcolor: .white) + NSLayoutConstraint.activate([ + stateView.centerXAnchor.constraint(equalTo: contentImageView.centerXAnchor), + stateView.centerYAnchor.constraint(equalTo: contentImageView.centerYAnchor), + stateView.heightAnchor.constraint(equalToConstant: 60), + stateView.widthAnchor.constraint(equalToConstant: 60), + ]) + + contentImageView.addSubview(timeView) + NSLayoutConstraint.activate([ + timeView.rightAnchor.constraint(equalTo: contentImageView.rightAnchor, constant: -7), + timeView.bottomAnchor.constraint(equalTo: contentImageView.bottomAnchor, constant: -7), + ]) + } + + override func setModel(_ model: MessageContentModel) { + super.setModel(model) + if let videoObject = model.message?.messageObject as? NIMVideoObject { + if let path = videoObject.coverPath { + contentImageView.sd_setImage( + with: URL(fileURLWithPath: path), + placeholderImage: nil, + options: .retryFailed, + progress: nil, + completed: nil + ) + } else { + contentImageView.sd_setImage( + with: URL(string: videoObject.coverUrl ?? ""), + placeholderImage: nil, + options: .retryFailed, + progress: nil, + completed: nil + ) + } + + if videoObject.duration > 0 { + timeView.isHidden = false + timeLabel.text = Date.getFormatPlayTime(TimeInterval(videoObject.duration / 1000)) + } else { + timeView.isHidden = true + } + + if let videoModel = model as? MessageVideoModel { + weakModel?.cell = nil + weakModel = videoModel + videoModel.cell = self + if videoModel.state == .Success { + stateView.state = .VideoPlay + } else { + stateView.state = .VideoDownload + stateView.setProgress(videoModel.progress) + if videoModel.progress >= 1 { + videoModel.state = .Success + } } + } } - - override func uploadProgress(_ progress: Float) { - stateView.setProgress(progress) - } - - + } + + override func uploadProgress(_ progress: Float) { + stateView.setProgress(progress) + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/OperationCell.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/OperationCell.swift index ae19b691..e5c34826 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/OperationCell.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/OperationCell.swift @@ -1,59 +1,57 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit -//protocol OperationCellDelegate: AnyObject { +// protocol OperationCellDelegate: AnyObject { // func didSelected(_ cell: OperationCell, _ model: OperationItem?) -//} +// } class OperationCell: UICollectionViewCell { - - public var imageView = UIImageView() - public var label = UILabel() + public var imageView = UIImageView() + public var label = UILabel() // public weak var delegate: OperationCellDelegate? - public var model: OperationItem? { - didSet { - imageView.image = UIImage.ne_imageNamed(name: model?.imageName) - label.text = model?.text - } + public var model: OperationItem? { + didSet { + imageView.image = UIImage.ne_imageNamed(name: model?.imageName) + label.text = model?.text } - - override init(frame: CGRect) { - super.init(frame: frame) - imageView.translatesAutoresizingMaskIntoConstraints = false - self.contentView.addSubview(imageView) - imageView.contentMode = .center - NSLayoutConstraint.activate([ - imageView.centerXAnchor.constraint(equalTo: self.contentView.centerXAnchor, constant: 0), - imageView.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 8), - imageView.widthAnchor.constraint(equalToConstant: 18), - imageView.heightAnchor.constraint(equalToConstant: 18) - ]) - - label.font = UIFont.systemFont(ofSize: 14) - label.translatesAutoresizingMaskIntoConstraints = false - label.textColor = UIColor.ne_darkText - label.textAlignment = .center - self.contentView.addSubview(label) - NSLayoutConstraint.activate([ - label.topAnchor.constraint(equalTo: imageView.bottomAnchor, constant: 8), - label.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 0), - label.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: 0), - label.heightAnchor.constraint(equalToConstant: 18) - ]) + } + + override init(frame: CGRect) { + super.init(frame: frame) + imageView.translatesAutoresizingMaskIntoConstraints = false + contentView.addSubview(imageView) + imageView.contentMode = .center + NSLayoutConstraint.activate([ + imageView.centerXAnchor.constraint(equalTo: contentView.centerXAnchor, constant: 0), + imageView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 8), + imageView.widthAnchor.constraint(equalToConstant: 18), + imageView.heightAnchor.constraint(equalToConstant: 18), + ]) + + label.font = UIFont.systemFont(ofSize: 14) + label.translatesAutoresizingMaskIntoConstraints = false + label.textColor = UIColor.ne_darkText + label.textAlignment = .center + contentView.addSubview(label) + NSLayoutConstraint.activate([ + label.topAnchor.constraint(equalTo: imageView.bottomAnchor, constant: 8), + label.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 0), + label.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: 0), + label.heightAnchor.constraint(equalToConstant: 18), + ]) // let tap = UITapGestureRecognizer(target: self, action: #selector(tapEvent)) // self.contentView.addGestureRecognizer(tap) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + // @objc func tapEvent(tap: UITapGestureRecognizer) { // self.delegate?.didSelected(self, model) // } - - } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/UserSettingBaseCell.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/UserSettingBaseCell.swift index 88065439..372459d3 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/UserSettingBaseCell.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/UserSettingBaseCell.swift @@ -1,52 +1,51 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. class UserSettingBaseCell: CornerCell { - - var model: UserSettingCellModel? - - lazy var titleLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.textColor = NEConstant.hexRGB(0x333333) - label.font = NEConstant.defaultTextFont(16.0) - return label - }() - - public lazy var arrow: UIImageView = { - let imageView = UIImageView(image: coreLoader.loadImage("arrowRight")) - imageView.translatesAutoresizingMaskIntoConstraints = false - return imageView - }() - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - self.selectionStyle = .none - showDefaultLine = true - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - } - - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } + var model: UserSettingCellModel? - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) + lazy var titleLabel: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.textColor = NEConstant.hexRGB(0x333333) + label.font = NEConstant.defaultTextFont(16.0) + return label + }() - // Configure the view for the selected state - } - - func configure(_ anyModel: Any){ - if let m = anyModel as? UserSettingCellModel { - model = m - cornerType = m.cornerType - titleLabel.text = m.cellName - } - } + public lazy var arrow: UIImageView = { + let imageView = UIImageView(image: coreLoader.loadImage("arrowRight")) + imageView.translatesAutoresizingMaskIntoConstraints = false + return imageView + }() + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + selectionStyle = .none + showDefaultLine = true + } + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + } + + func configure(_ anyModel: Any) { + if let m = anyModel as? UserSettingCellModel { + model = m + cornerType = m.cornerType + titleLabel.text = m.cellName + } + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/UserSettingSwitchCell.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/UserSettingSwitchCell.swift index 9e1adab1..a87c23fa 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/UserSettingSwitchCell.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/UserSettingSwitchCell.swift @@ -1,66 +1,65 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class UserSettingSwitchCell: UserSettingBaseCell { + var tSwitch: UISwitch = { + let q = UISwitch() + q.translatesAutoresizingMaskIntoConstraints = false + q.onTintColor = NEConstant.hexRGB(0x337EFF) + return q + }() - var tSwitch: UISwitch = { - let q = UISwitch() - q.translatesAutoresizingMaskIntoConstraints = false - q.onTintColor = NEConstant.hexRGB(0x337EFF) - return q - }() - - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) - // Configure the view for the selected state - } - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - self.selectionStyle = .none - setupUI() - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - } - - override func configure(_ anyModel: Any) { - super.configure(anyModel) - if let open = model?.switchOpen { - tSwitch.isOn = open - } - } - - func setupUI(){ - contentView.addSubview(titleLabel) - NSLayoutConstraint.activate([ - titleLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 36), - titleLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - titleLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -84) - ]) - - contentView.addSubview(tSwitch) - NSLayoutConstraint.activate([ - tSwitch.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - tSwitch.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -36) - ]) - tSwitch.addTarget(self, action: #selector(switchChange(_:)), for: .touchUpInside) - } - - @objc func switchChange(_ s: UISwitch) { - if let block = model?.swichChange { - block(s.isOn) - } + // Configure the view for the selected state + } + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + selectionStyle = .none + setupUI() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + override func configure(_ anyModel: Any) { + super.configure(anyModel) + if let open = model?.switchOpen { + tSwitch.isOn = open } + } + func setupUI() { + contentView.addSubview(titleLabel) + NSLayoutConstraint.activate([ + titleLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 36), + titleLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + titleLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -84), + ]) + + contentView.addSubview(tSwitch) + NSLayoutConstraint.activate([ + tSwitch.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + tSwitch.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -36), + ]) + tSwitch.addTarget(self, action: #selector(switchChange(_:)), for: .touchUpInside) + } + + @objc func switchChange(_ s: UISwitch) { + if let block = model?.swichChange { + block(s.isOn) + } + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/UserTableViewCell.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/UserTableViewCell.swift index a3ace87e..2173f6b1 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/UserTableViewCell.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/Cell/UserTableViewCell.swift @@ -1,89 +1,95 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCoreIM class UserTableViewCell: UITableViewCell { - public var avatarImage = UIImageView() - public var nameLabel = UILabel() - public var titleLabel = UILabel() - public var model: User? + public var avatarImage = UIImageView() + public var nameLabel = UILabel() + public var titleLabel = UILabel() + public var model: User? - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - baseCommonUI() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func baseCommonUI() { - - // avatar - self.selectionStyle = .none - self.backgroundColor = .white - self.avatarImage.layer.cornerRadius = 21 - self.avatarImage.backgroundColor = UIColor(hexString: "#537FF4") - self.avatarImage.translatesAutoresizingMaskIntoConstraints = false - self.avatarImage.clipsToBounds = true - self.avatarImage.isUserInteractionEnabled = true - self.contentView.addSubview(self.avatarImage) - NSLayoutConstraint.activate([ - self.avatarImage.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 16), - self.avatarImage.widthAnchor.constraint(equalToConstant: 42), - self.avatarImage.heightAnchor.constraint(equalToConstant: 42), - self.avatarImage.topAnchor.constraint(equalTo: self.topAnchor, constant: 10) - ]) - - // name - self.nameLabel.textAlignment = .center - self.nameLabel.translatesAutoresizingMaskIntoConstraints = false - self.nameLabel.font = UIFont.systemFont(ofSize: 12) - self.nameLabel.textColor = .white - self.nameLabel.text = "placeholder" - self.contentView.addSubview(self.nameLabel) - NSLayoutConstraint.activate([ - self.nameLabel.leftAnchor.constraint(equalTo: self.avatarImage.leftAnchor), - self.nameLabel.rightAnchor.constraint(equalTo: self.avatarImage.rightAnchor), - self.nameLabel.topAnchor.constraint(equalTo: self.avatarImage.topAnchor), - self.nameLabel.bottomAnchor.constraint(equalTo: self.avatarImage.bottomAnchor), - ]) - - self.titleLabel.translatesAutoresizingMaskIntoConstraints = false - self.titleLabel.text = "placeholder" - self.titleLabel.font = UIFont.systemFont(ofSize: 16) - self.titleLabel.textColor = UIColor(red: 51/255.0, green: 51/255.0, blue: 51/255.0, alpha: 1.0) - self.contentView.addSubview(self.titleLabel) - NSLayoutConstraint.activate([ - self.titleLabel.leftAnchor.constraint(equalTo: self.avatarImage.rightAnchor, constant: 12), - self.titleLabel.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -35), - self.titleLabel.centerYAnchor.constraint(equalTo: self.contentView.centerYAnchor, constant: 0), - self.titleLabel.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor) - ]) - } - - public func setModel(_ model: User) { - self.model = model - self.avatarImage.backgroundColor = UIColor.colorWithString(string:model.userId) - self.nameLabel.text = model.shortName(count: 2) - self.titleLabel.text = model.showName() - - if let avatarURL = model.userInfo?.avatarUrl { - self.avatarImage.sd_setImage(with: URL(string: avatarURL)) { [weak self] image, error, type, url in - if image != nil { - self?.avatarImage.image = image - self?.nameLabel.isHidden = true - }else { - self?.avatarImage.image = nil - self?.nameLabel.isHidden = false - } - } - }else { - self.avatarImage.image = nil - self.nameLabel.isHidden = false + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + baseCommonUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func baseCommonUI() { + // avatar + selectionStyle = .none + backgroundColor = .white + avatarImage.layer.cornerRadius = 21 + avatarImage.backgroundColor = UIColor(hexString: "#537FF4") + avatarImage.translatesAutoresizingMaskIntoConstraints = false + avatarImage.clipsToBounds = true + avatarImage.isUserInteractionEnabled = true + contentView.addSubview(avatarImage) + NSLayoutConstraint.activate([ + avatarImage.leftAnchor.constraint(equalTo: leftAnchor, constant: 16), + avatarImage.widthAnchor.constraint(equalToConstant: 42), + avatarImage.heightAnchor.constraint(equalToConstant: 42), + avatarImage.topAnchor.constraint(equalTo: topAnchor, constant: 10), + ]) + + // name + nameLabel.textAlignment = .center + nameLabel.translatesAutoresizingMaskIntoConstraints = false + nameLabel.font = UIFont.systemFont(ofSize: 12) + nameLabel.textColor = .white + nameLabel.text = "placeholder" + contentView.addSubview(nameLabel) + NSLayoutConstraint.activate([ + nameLabel.leftAnchor.constraint(equalTo: avatarImage.leftAnchor), + nameLabel.rightAnchor.constraint(equalTo: avatarImage.rightAnchor), + nameLabel.topAnchor.constraint(equalTo: avatarImage.topAnchor), + nameLabel.bottomAnchor.constraint(equalTo: avatarImage.bottomAnchor), + ]) + + titleLabel.translatesAutoresizingMaskIntoConstraints = false + titleLabel.text = "placeholder" + titleLabel.font = UIFont.systemFont(ofSize: 16) + titleLabel.textColor = UIColor( + red: 51 / 255.0, + green: 51 / 255.0, + blue: 51 / 255.0, + alpha: 1.0 + ) + contentView.addSubview(titleLabel) + NSLayoutConstraint.activate([ + titleLabel.leftAnchor.constraint(equalTo: avatarImage.rightAnchor, constant: 12), + titleLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -35), + titleLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor, constant: 0), + titleLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + ]) + } + + public func setModel(_ model: User) { + self.model = model + avatarImage.backgroundColor = UIColor.colorWithString(string: model.userId) + nameLabel.text = model.shortName(count: 2) + titleLabel.text = model.showName() + + if let avatarURL = model.userInfo?.avatarUrl { + avatarImage + .sd_setImage(with: URL(string: avatarURL)) { [weak self] image, error, type, url in + if image != nil { + self?.avatarImage.image = image + self?.nameLabel.isHidden = true + } else { + self?.avatarImage.image = nil + self?.nameLabel.isHidden = false + } } + } else { + avatarImage.image = nil + nameLabel.isHidden = false } + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/ChatActivityIndicatorView.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/ChatActivityIndicatorView.swift index e15e13dc..f03551f1 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/ChatActivityIndicatorView.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/ChatActivityIndicatorView.swift @@ -1,90 +1,85 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit enum QChatSendMessageStatus { - case successed - case sending - case failed + case successed + case sending + case failed } class ChatActivityIndicatorView: UIView { - - public var messageStatus:QChatSendMessageStatus? { - didSet { + public var messageStatus: QChatSendMessageStatus? { + didSet { // print("messageStatus:\(messageStatus)") - - failBtn.isHidden = true - activity.isHidden = true - activity.stopAnimating() - switch messageStatus { - case .sending: - self.isHidden = false - activity.isHidden = false - failBtn.isHidden = true - activity.startAnimating() - break - case .failed: - self.isHidden = false - activity.isHidden = true - failBtn.isHidden = false - break - case .successed: - self.isHidden = true - break - - default: - print("default") - } - } - } - + failBtn.isHidden = true + activity.isHidden = true + activity.stopAnimating() - override init(frame: CGRect) { - super.init(frame: frame) - commonUI() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } + switch messageStatus { + case .sending: + self.isHidden = false + activity.isHidden = false + failBtn.isHidden = true + activity.startAnimating() + case .failed: + self.isHidden = false + activity.isHidden = true + failBtn.isHidden = false + case .successed: + self.isHidden = true - func commonUI(){ - self.addSubview(failBtn) - self.addSubview(activity) - NSLayoutConstraint.activate([ - failBtn.topAnchor.constraint(equalTo: self.topAnchor), - failBtn.leftAnchor.constraint(equalTo: self.leftAnchor), - failBtn.bottomAnchor.constraint(equalTo: self.bottomAnchor), - failBtn.rightAnchor.constraint(equalTo: self.rightAnchor), - ]) - - NSLayoutConstraint.activate([ - activity.topAnchor.constraint(equalTo: self.topAnchor), - activity.leftAnchor.constraint(equalTo: self.leftAnchor), - activity.bottomAnchor.constraint(equalTo: self.bottomAnchor), - activity.rightAnchor.constraint(equalTo: self.rightAnchor), - ]) + default: + print("default") + } } - - //MARK: lazy Method - public lazy var failBtn:UIButton = { - let button = UIButton() - button.translatesAutoresizingMaskIntoConstraints = false - button.imageView?.contentMode = .center - button .setBackgroundImage(UIImage.ne_imageNamed(name: "sendMessage_failed"), for: .normal) - return button - }() - - private lazy var activity:UIActivityIndicatorView = { - let activity = UIActivityIndicatorView.init() - activity.translatesAutoresizingMaskIntoConstraints = false - activity.color = .gray - return activity - }() + } + + override init(frame: CGRect) { + super.init(frame: frame) + commonUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func commonUI() { + addSubview(failBtn) + addSubview(activity) + NSLayoutConstraint.activate([ + failBtn.topAnchor.constraint(equalTo: topAnchor), + failBtn.leftAnchor.constraint(equalTo: leftAnchor), + failBtn.bottomAnchor.constraint(equalTo: bottomAnchor), + failBtn.rightAnchor.constraint(equalTo: rightAnchor), + ]) + + NSLayoutConstraint.activate([ + activity.topAnchor.constraint(equalTo: topAnchor), + activity.leftAnchor.constraint(equalTo: leftAnchor), + activity.bottomAnchor.constraint(equalTo: bottomAnchor), + activity.rightAnchor.constraint(equalTo: rightAnchor), + ]) + } + + // MARK: lazy Method + + public lazy var failBtn: UIButton = { + let button = UIButton() + button.translatesAutoresizingMaskIntoConstraints = false + button.imageView?.contentMode = .center + button.setBackgroundImage(UIImage.ne_imageNamed(name: "sendMessage_failed"), for: .normal) + return button + }() - + private lazy var activity: UIActivityIndicatorView = { + let activity = UIActivityIndicatorView() + activity.translatesAutoresizingMaskIntoConstraints = false + activity.color = .gray + return activity + }() } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/ChatBrokenNetworkView.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/ChatBrokenNetworkView.swift index 57a4a340..dd489a16 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/ChatBrokenNetworkView.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/ChatBrokenNetworkView.swift @@ -1,39 +1,37 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit public class ChatBrokenNetworkView: UIView { + override init(frame: CGRect) { + super.init(frame: frame) + commonUI() + } - override init(frame: CGRect) { - super.init(frame: frame) - commonUI() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func commonUI(){ - self.backgroundColor = HexRGB(0xFEE3E6) - self.addSubview(content) - NSLayoutConstraint.activate([ - content.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 15), - content.centerYAnchor.constraint(equalTo: self.centerYAnchor), - content.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -15), - ]) - } - - private lazy var content:UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.font = DefaultTextFont(14) - label.textColor = HexRGB(0xFC596A) - label.textAlignment = .center - label.text = "当前网络不可用,请检查你当网络设置。" - return label - }() - + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + func commonUI() { + backgroundColor = HexRGB(0xFEE3E6) + addSubview(content) + NSLayoutConstraint.activate([ + content.leftAnchor.constraint(equalTo: leftAnchor, constant: 15), + content.centerYAnchor.constraint(equalTo: centerYAnchor), + content.rightAnchor.constraint(equalTo: rightAnchor, constant: -15), + ]) + } + + private lazy var content: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.font = DefaultTextFont(14) + label.textColor = HexRGB(0xFC596A) + label.textAlignment = .center + label.text = "当前网络不可用,请检查你当网络设置。" + return label + }() } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/ChatInputView.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/ChatInputView.swift index 7d3a5169..4bba0287 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/ChatInputView.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/ChatInputView.swift @@ -1,401 +1,416 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCommon import RSKPlaceholderTextView public enum ChatMenuType { - case text - case audio - case emoji - case image - case file + case text + case audio + case emoji + case image + case file } public protocol ChatInputViewDelegate: AnyObject { - func sendText(text: String?) - func willSelectItem(button: UIButton, index: Int) - @discardableResult - func textChanged(text: String) -> Bool - func textDelete(range: NSRange, text: String) -> Bool - func startRecord() - func moveOutView() - func moveInView() - func endRecord(insideView: Bool) - func textFieldDidChange(_ textField: UITextView) - func textFieldDidEndEditing(_ textField: UITextView) - func textFieldDidBeginEditing(_ textField: UITextView) + func sendText(text: String?) + func willSelectItem(button: UIButton, index: Int) + @discardableResult + func textChanged(text: String) -> Bool + func textDelete(range: NSRange, text: String) -> Bool + func startRecord() + func moveOutView() + func moveInView() + func endRecord(insideView: Bool) + func textFieldDidChange(_ textField: UITextView) + func textFieldDidEndEditing(_ textField: UITextView) + func textFieldDidBeginEditing(_ textField: UITextView) } -public class ChatInputView: UIView, UITextFieldDelegate, ChatRecordViewDelegate,InputEmoticonContainerViewDelegate, UITextViewDelegate { - - public weak var delegate: ChatInputViewDelegate? - public var currentType: ChatMenuType = .text - public var menuHeight = 100.0 - public var contentHeight = 204.0 - public var atCache:NIMInputAtCache? - - - var textField = RSKPlaceholderTextView() - var contentView = UIView() - public var contentSubView: UIView? - private var greyView = UIView() - private var recordView = ChatRecordView(frame: .zero) - override init(frame: CGRect) { - super.init(frame: frame) - commonUI() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - deinit { - NotificationCenter.default.removeObserver(self) - } - - func commonUI() { - self.backgroundColor = UIColor(hexString: "#EFF1F3") - textField.layer.cornerRadius = 8 - textField.clipsToBounds = true - textField.translatesAutoresizingMaskIntoConstraints = false - textField.backgroundColor = .white - // textField.leftViewMode = .always - textField.returnKeyType = .send - // textField.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 20, height: 40)) - textField.delegate = self - textField.allowsEditingTextAttributes = true - self.addSubview(textField) - NSLayoutConstraint.activate([ - textField.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 7), - textField.topAnchor.constraint(equalTo: self.topAnchor, constant: 6), - textField.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -7), - textField.heightAnchor.constraint(equalToConstant: 40) - ]) - NotificationCenter.default.addObserver(self, selector: #selector(textFieldChangeNoti), name: UITextField.textDidChangeNotification, object: nil) - - // let imageNames = ["mic","emoji","photo","file","add"] - let imageNames = ["mic","emoji","photo","chat_video","add"] - - var items = [UIButton]() - for i in 0...4 { - let button = UIButton(type: .custom) - button.setImage(UIImage.ne_imageNamed(name: imageNames[i]), for: .normal) - button.translatesAutoresizingMaskIntoConstraints = false - button.addTarget(self, action: #selector(buttonEvent), for: .touchUpInside) - button.tag = i + 5 - items.append(button) - if i == 4 { - button.alpha = 0.5 - } - - } - let stackView = UIStackView(arrangedSubviews: items) - stackView.translatesAutoresizingMaskIntoConstraints = false - stackView.distribution = .fillEqually - self.addSubview(stackView) - NSLayoutConstraint.activate([ - stackView.leftAnchor.constraint(equalTo: self.leftAnchor), - stackView.rightAnchor.constraint(equalTo: self.rightAnchor), - stackView.heightAnchor.constraint(equalToConstant: 54), - stackView.topAnchor.constraint(equalTo: self.textField.bottomAnchor, constant: 0) - ]) - - greyView.translatesAutoresizingMaskIntoConstraints = false - greyView.backgroundColor = UIColor(hexString: "#EFF1F3") - greyView.isHidden = true - self.addSubview(greyView) - NSLayoutConstraint.activate([ - greyView.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 0), - greyView.topAnchor.constraint(equalTo: self.topAnchor, constant: 0), - greyView.rightAnchor.constraint(equalTo: self.rightAnchor, constant: 0), - greyView.heightAnchor.constraint(equalToConstant: 100) - ]) - - self.addSubview(self.contentView); - self.contentView.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - contentView.leftAnchor.constraint(equalTo: self.leftAnchor), - contentView.rightAnchor.constraint(equalTo: self.rightAnchor), - contentView.heightAnchor.constraint(equalToConstant: contentHeight), - contentView.topAnchor.constraint(equalTo: stackView.bottomAnchor, constant: 0) - ]) - - self.recordView.isHidden = true - self.recordView.translatesAutoresizingMaskIntoConstraints = false - self.recordView.delegate = self - self.contentView.addSubview(recordView) - NSLayoutConstraint.activate([ - recordView.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 0), - recordView.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: 0), - recordView.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 0), - recordView.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: 0) - ]) - - self.contentView.addSubview(emojiView) - // NSLayoutConstraint.activate([ - // emojiView.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 0), - // emojiView.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: 0), - // emojiView.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 0), - // emojiView.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: -25) - // ]) - } - - func addRecordView() { - if self.currentType != .audio { - self.currentType = .audio - self.textField.resignFirstResponder() - self.contentSubView?.isHidden = true - self.contentSubView = self.recordView - self.contentSubView?.isHidden = false - } - } - - func addEmojiView(){ - if self.currentType != .emoji { - self.currentType = .emoji - self.textField.resignFirstResponder() - self.contentSubView?.isHidden = true - self.contentSubView = self.emojiView - self.contentSubView?.isHidden = false - } - } - - // func doButtonDeleteText(){ - // let range = delRangeForLastComponent() - // if range.count == 1 { - // - // } - // print("\(textField.selectedTextRange?.start)") - // textField.deleteBackward() - // } - - // func delRangeForLastComponent() -> NSRange{ - // let text = textField.text as? NSString - // let selectedRange = self.textField.selectedRange - // if selectedRange.location == 0 { - // return NSRange.init(location: 0, length: 0) - // } - // - // let range:NSRange? - // let subRange = - // if selectedRange?.start >= 2 { - // let subStr = text?.substring(with: NSRange.init(location: selectedRange?.start - 2, length: 2)) - // isEmoji = sub - // } - // } - - // func rangeForPrefix(prefix:String,suffix:String) ->NSRange { - // let text = textField.text as? NSString - // let range = textField.selectedRange - // var selectedText:String? - // if range.length > 0 { - // selectedText = text?.substring(with: range) - // }else { - // selectedText = text as? String - // } - // let endLocaiton = range.location - // if endLocaiton <= 0{ - // return NSMakeRange(NSNotFound, 0) - // } - // let index = -1 - // - // if let selectStr = selectedText,selectStr.hasSuffix(suffix) { - // let p = 20 - // for index = endLocaiton in - // - // - // - // }else { - // return NSMakeRange(NSNotFound, 0) - // - // } - // - // - // - // } - - - - - - - //MARK: ===================== lazy method ===================== - public lazy var emojiView:InputEmoticonContainerView = { - let view = InputEmoticonContainerView(frame: CGRect.init(x: 0, y: 0, width: kScreenWidth, height: 200)) - // view.translatesAutoresizingMaskIntoConstraints = false - view.isHidden = true - view.delegate = self - return view - }() - - public func textViewDidEndEditing(_ textView: UITextView) { - delegate?.textFieldDidEndEditing(textView) - } - - public func textFieldDidEndEditing(_ textField: UITextField) { - // delegate?.textFieldDidEndEditing(textField) - } - - public func textViewDidBeginEditing(_ textView: UITextView) { - delegate?.textFieldDidBeginEditing(textView) +public class ChatInputView: UIView, UITextFieldDelegate, ChatRecordViewDelegate, + InputEmoticonContainerViewDelegate, UITextViewDelegate { + public weak var delegate: ChatInputViewDelegate? + public var currentType: ChatMenuType = .text + public var menuHeight = 100.0 + public var contentHeight = 204.0 + public var atCache: NIMInputAtCache? + + var textField = RSKPlaceholderTextView() + var contentView = UIView() + public var contentSubView: UIView? + private var greyView = UIView() + private var recordView = ChatRecordView(frame: .zero) + override init(frame: CGRect) { + super.init(frame: frame) + commonUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + deinit { + NotificationCenter.default.removeObserver(self) + } + + func commonUI() { + backgroundColor = UIColor(hexString: "#EFF1F3") + textField.layer.cornerRadius = 8 + textField.clipsToBounds = true + textField.translatesAutoresizingMaskIntoConstraints = false + textField.backgroundColor = .white + // textField.leftViewMode = .always + textField.returnKeyType = .send + // textField.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 20, height: 40)) + textField.delegate = self + textField.allowsEditingTextAttributes = true + addSubview(textField) + NSLayoutConstraint.activate([ + textField.leftAnchor.constraint(equalTo: leftAnchor, constant: 7), + textField.topAnchor.constraint(equalTo: topAnchor, constant: 6), + textField.rightAnchor.constraint(equalTo: rightAnchor, constant: -7), + textField.heightAnchor.constraint(equalToConstant: 40), + ]) + NotificationCenter.default.addObserver( + self, + selector: #selector(textFieldChangeNoti), + name: UITextField.textDidChangeNotification, + object: nil + ) + + // let imageNames = ["mic","emoji","photo","file","add"] + let imageNames = ["mic", "emoji", "photo", "chat_video", "add"] + + var items = [UIButton]() + for i in 0 ... 4 { + let button = UIButton(type: .custom) + button.setImage(UIImage.ne_imageNamed(name: imageNames[i]), for: .normal) + button.translatesAutoresizingMaskIntoConstraints = false + button.addTarget(self, action: #selector(buttonEvent), for: .touchUpInside) + button.tag = i + 5 + items.append(button) + if i == 4 { + button.alpha = 0.5 + } } - - public func textFieldDidBeginEditing(_ textField: UITextField) { - // delegate?.textFieldDidBeginEditing(textField) + let stackView = UIStackView(arrangedSubviews: items) + stackView.translatesAutoresizingMaskIntoConstraints = false + stackView.distribution = .fillEqually + addSubview(stackView) + NSLayoutConstraint.activate([ + stackView.leftAnchor.constraint(equalTo: leftAnchor), + stackView.rightAnchor.constraint(equalTo: rightAnchor), + stackView.heightAnchor.constraint(equalToConstant: 54), + stackView.topAnchor.constraint(equalTo: textField.bottomAnchor, constant: 0), + ]) + + greyView.translatesAutoresizingMaskIntoConstraints = false + greyView.backgroundColor = UIColor(hexString: "#EFF1F3") + greyView.isHidden = true + addSubview(greyView) + NSLayoutConstraint.activate([ + greyView.leftAnchor.constraint(equalTo: leftAnchor, constant: 0), + greyView.topAnchor.constraint(equalTo: topAnchor, constant: 0), + greyView.rightAnchor.constraint(equalTo: rightAnchor, constant: 0), + greyView.heightAnchor.constraint(equalToConstant: 100), + ]) + + addSubview(contentView) + contentView.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + contentView.leftAnchor.constraint(equalTo: leftAnchor), + contentView.rightAnchor.constraint(equalTo: rightAnchor), + contentView.heightAnchor.constraint(equalToConstant: contentHeight), + contentView.topAnchor.constraint(equalTo: stackView.bottomAnchor, constant: 0), + ]) + + recordView.isHidden = true + recordView.translatesAutoresizingMaskIntoConstraints = false + recordView.delegate = self + contentView.addSubview(recordView) + NSLayoutConstraint.activate([ + recordView.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 0), + recordView.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: 0), + recordView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 0), + recordView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: 0), + ]) + + contentView.addSubview(emojiView) + // NSLayoutConstraint.activate([ + // emojiView.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 0), + // emojiView.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: 0), + // emojiView.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 0), + // emojiView.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: -25) + // ]) + } + + func addRecordView() { + if currentType != .audio { + currentType = .audio + textField.resignFirstResponder() + contentSubView?.isHidden = true + contentSubView = recordView + contentSubView?.isHidden = false } - - public func textViewShouldBeginEditing(_ textView: UITextView) -> Bool { - self.currentType = .text - return true + } + + func addEmojiView() { + if currentType != .emoji { + currentType = .emoji + textField.resignFirstResponder() + contentSubView?.isHidden = true + contentSubView = emojiView + contentSubView?.isHidden = false } - - public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { - self.currentType = .text + } + + // func doButtonDeleteText(){ + // let range = delRangeForLastComponent() + // if range.count == 1 { + // + // } + // print("\(textField.selectedTextRange?.start)") + // textField.deleteBackward() + // } + + // func delRangeForLastComponent() -> NSRange{ + // let text = textField.text as? NSString + // let selectedRange = self.textField.selectedRange + // if selectedRange.location == 0 { + // return NSRange.init(location: 0, length: 0) + // } + // + // let range:NSRange? + // let subRange = + // if selectedRange?.start >= 2 { + // let subStr = text?.substring(with: NSRange.init(location: selectedRange?.start - 2, length: 2)) + // isEmoji = sub + // } + // } + + // func rangeForPrefix(prefix:String,suffix:String) ->NSRange { + // let text = textField.text as? NSString + // let range = textField.selectedRange + // var selectedText:String? + // if range.length > 0 { + // selectedText = text?.substring(with: range) + // }else { + // selectedText = text as? String + // } + // let endLocaiton = range.location + // if endLocaiton <= 0{ + // return NSMakeRange(NSNotFound, 0) + // } + // let index = -1 + // + // if let selectStr = selectedText,selectStr.hasSuffix(suffix) { + // let p = 20 + // for index = endLocaiton in + // + // + // + // }else { + // return NSMakeRange(NSNotFound, 0) + // + // } + // + // + // + // } + + // MARK: ===================== lazy method ===================== + + public lazy var emojiView: InputEmoticonContainerView = { + let view = + InputEmoticonContainerView(frame: CGRect(x: 0, y: 0, width: kScreenWidth, height: 200)) + // view.translatesAutoresizingMaskIntoConstraints = false + view.isHidden = true + view.delegate = self + return view + }() + + public func textViewDidEndEditing(_ textView: UITextView) { + delegate?.textFieldDidEndEditing(textView) + } + + public func textFieldDidEndEditing(_ textField: UITextField) { + // delegate?.textFieldDidEndEditing(textField) + } + + public func textViewDidBeginEditing(_ textView: UITextView) { + delegate?.textFieldDidBeginEditing(textView) + } + + public func textFieldDidBeginEditing(_ textField: UITextField) { + // delegate?.textFieldDidBeginEditing(textField) + } + + public func textViewShouldBeginEditing(_ textView: UITextView) -> Bool { + currentType = .text + return true + } + + public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { + currentType = .text + return true + } + + public func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, + replacementText text: String) -> Bool { + if text == "\n" { + guard let text = getRealSendText(textField.attributedText)? + .trimmingCharacters(in: CharacterSet.whitespaces) else { return true - } - - public func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { - if text == "\n" { - guard let text = getRealSendText(textField.attributedText)?.trimmingCharacters(in: CharacterSet.whitespaces) else { - return true - } - self.delegate?.sendText(text: text) - textField.text = "" + } + delegate?.sendText(text: text) + textField.text = "" // textView.resignFirstResponder() - return false - } - - print("range:\(range) string:\(text)") - if text.count == 0 { - if let delegate = self.delegate { - return delegate.textDelete(range: range, text: text) - } - }else { - - self.delegate?.textChanged(text: text) - } - - return true + return false } - - public func textFieldShouldReturn(_ textField: UITextField) -> Bool { - guard let text = textField.text?.trimmingCharacters(in: CharacterSet.whitespaces) else { - return true - } - textField.text = "" - self.delegate?.sendText(text: text) - return true + + print("range:\(range) string:\(text)") + if text.count == 0 { + if let delegate = delegate { + return delegate.textDelete(range: range, text: text) + } + } else { + delegate?.textChanged(text: text) } - - - - public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { - print("range:\(range) string:\(string)") - if string.count == 0 { - if let delegate = self.delegate { - return delegate.textDelete(range: range, text: string) - } - }else { - self.delegate?.textChanged(text: string) - } - return true + + return true + } + + public func textFieldShouldReturn(_ textField: UITextField) -> Bool { + guard let text = textField.text?.trimmingCharacters(in: CharacterSet.whitespaces) else { + return true } - - @objc func buttonEvent(button: UIButton) { - switch button.tag - 5 { - case 0: - addRecordView() - case 1: - addEmojiView() - default: - print("default") - } - self.delegate?.willSelectItem(button: button, index: button.tag - 5) + textField.text = "" + delegate?.sendText(text: text) + return true + } + + public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, + replacementString string: String) -> Bool { + print("range:\(range) string:\(string)") + if string.count == 0 { + if let delegate = delegate { + return delegate.textDelete(range: range, text: string) + } + } else { + delegate?.textChanged(text: string) } - - //MARK: InputEmoticonContainerViewDelegate - public func selectedEmoticon(emoticonID: String, emotCatalogID: String, description: String) { - if emoticonID.isEmpty {//删除键 - // doButtonDeleteText() - textField.deleteBackward() - print("delete ward") - }else { - - if let font = textField.font{ - let attribute = NEEmotionTool.getAttWithStr(str: description, font: font, CGPoint(x: 0, y: -4)) - print("attribute : ", attribute) - let mutaAttribute = NSMutableAttributedString() - if let origin = textField.attributedText { - mutaAttribute.append(origin) - } - attribute.enumerateAttribute(NSAttributedString.Key.attachment, in: NSMakeRange(0, attribute.length)) { value, range, stop in - if let neAttachment = value as? NEEmotionAttachment { - print("ne attachment bounds ", neAttachment.bounds) - } - } - mutaAttribute.append(attribute) - mutaAttribute.addAttribute(NSAttributedString.Key.font, value: font, range: NSMakeRange(0, mutaAttribute.length)) - textField.attributedText = mutaAttribute - textField.scrollRangeToVisible(NSMakeRange(textField.attributedText.length, 1)) -// [_textView scrollRangeToVisible:NSMakeRange(_textView.text.length, 1)]; - } - } + return true + } + + @objc func buttonEvent(button: UIButton) { + switch button.tag - 5 { + case 0: + addRecordView() + case 1: + addEmojiView() + default: + print("default") } - - public func didPressSend(sender: UIButton) { - guard let text = getRealSendText(textField.attributedText) else { - return + delegate?.willSelectItem(button: button, index: button.tag - 5) + } + + // MARK: InputEmoticonContainerViewDelegate + + public func selectedEmoticon(emoticonID: String, emotCatalogID: String, description: String) { + if emoticonID.isEmpty { // 删除键 + // doButtonDeleteText() + textField.deleteBackward() + print("delete ward") + } else { + if let font = textField.font { + let attribute = NEEmotionTool.getAttWithStr( + str: description, + font: font, + CGPoint(x: 0, y: -4) + ) + print("attribute : ", attribute) + let mutaAttribute = NSMutableAttributedString() + if let origin = textField.attributedText { + mutaAttribute.append(origin) } - self.delegate?.sendText(text: text) - textField.text = "" - atCache?.clean() - } - - - public func stopRecordAnimation() { - greyView.isHidden = true - self.recordView.stopRecordAnimation() - } - - - // MARK: ChatRecordViewDelegate - func startRecord() { - greyView.isHidden = false - self.delegate?.startRecord() - } - - func moveOutView() { - self.delegate?.moveOutView() - } - - func moveInView() { - self.delegate?.moveInView() - } - - func endRecord(insideView: Bool) { - greyView.isHidden = true - self.delegate?.endRecord(insideView: insideView) + attribute.enumerateAttribute( + NSAttributedString.Key.attachment, + in: NSMakeRange(0, attribute.length) + ) { value, range, stop in + if let neAttachment = value as? NEEmotionAttachment { + print("ne attachment bounds ", neAttachment.bounds) + } + } + mutaAttribute.append(attribute) + mutaAttribute.addAttribute( + NSAttributedString.Key.font, + value: font, + range: NSMakeRange(0, mutaAttribute.length) + ) + textField.attributedText = mutaAttribute + textField.scrollRangeToVisible(NSMakeRange(textField.attributedText.length, 1)) +// [_textView scrollRangeToVisible:NSMakeRange(_textView.text.length, 1)]; + } } - - @objc func textFieldChangeNoti(){ - delegate?.textFieldDidChange(textField) + } + + public func didPressSend(sender: UIButton) { + guard let text = getRealSendText(textField.attributedText) else { + return } - - func getRealSendText(_ attribute: NSAttributedString) -> String? { - let muta = NSMutableString() - - attribute.enumerateAttributes(in: NSMakeRange(0, attribute.length), options: NSAttributedString.EnumerationOptions(rawValue: 0)) { dics, range, stop in - - if let neAttachment = dics[NSAttributedString.Key.attachment] as? NEEmotionAttachment, let des = neAttachment.emotion?.tag { - muta.append(des) - } else { - let sub = attribute.attributedSubstring(from: range).string - muta.append(sub) - } - } - return muta as String + delegate?.sendText(text: text) + textField.text = "" + atCache?.clean() + } + + public func stopRecordAnimation() { + greyView.isHidden = true + recordView.stopRecordAnimation() + } + + // MARK: ChatRecordViewDelegate + + func startRecord() { + greyView.isHidden = false + delegate?.startRecord() + } + + func moveOutView() { + delegate?.moveOutView() + } + + func moveInView() { + delegate?.moveInView() + } + + func endRecord(insideView: Bool) { + greyView.isHidden = true + delegate?.endRecord(insideView: insideView) + } + + @objc func textFieldChangeNoti() { + delegate?.textFieldDidChange(textField) + } + + func getRealSendText(_ attribute: NSAttributedString) -> String? { + let muta = NSMutableString() + + attribute.enumerateAttributes( + in: NSMakeRange(0, attribute.length), + options: NSAttributedString.EnumerationOptions(rawValue: 0) + ) { dics, range, stop in + + if let neAttachment = dics[NSAttributedString.Key.attachment] as? NEEmotionAttachment, + let des = neAttachment.emotion?.tag { + muta.append(des) + } else { + let sub = attribute.attributedSubstring(from: range).string + muta.append(sub) + } } + return muta as String + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/ChatRecordView.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/ChatRecordView.swift index 7afd70eb..07a39aa8 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/ChatRecordView.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/ChatRecordView.swift @@ -1,128 +1,131 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit protocol ChatRecordViewDelegate: AnyObject { - func startRecord() - func moveOutView() - func moveInView() - func endRecord(insideView: Bool) + func startRecord() + func moveOutView() + func moveInView() + func endRecord(insideView: Bool) } class ChatRecordView: UIView, UIGestureRecognizerDelegate { - var recordImageView = UIImageView() - var topTipLabel = UILabel() - var tipLabel = UILabel() - public weak var delegate: ChatRecordViewDelegate? - private var outView = false - override init(frame: CGRect) { - super.init(frame: frame) - commonUI() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func commonUI() { - topTipLabel.translatesAutoresizingMaskIntoConstraints = false - topTipLabel.text = localizable("send_after_let_go") - topTipLabel.font = UIFont.systemFont(ofSize: 12) - topTipLabel.textColor = .ne_lightText - topTipLabel.textAlignment = .center - self.addSubview(topTipLabel) - NSLayoutConstraint.activate([ - topTipLabel.topAnchor.constraint(equalTo: self.topAnchor, constant: 0), - topTipLabel.heightAnchor.constraint(equalToConstant: 23), - topTipLabel.leftAnchor.constraint(equalTo: self.leftAnchor), - topTipLabel.rightAnchor.constraint(equalTo: self.rightAnchor) - ]) - - recordImageView.translatesAutoresizingMaskIntoConstraints = false - recordImageView.image = UIImage.ne_imageNamed(name: "chat_record") - recordImageView.contentMode = .center - self.addSubview(recordImageView) - NSLayoutConstraint.activate([ - recordImageView.centerXAnchor.constraint(equalTo: self.centerXAnchor), - recordImageView.topAnchor.constraint(equalTo: self.topAnchor, constant: 40), - recordImageView.heightAnchor.constraint(equalToConstant: 103), - recordImageView.widthAnchor.constraint(equalToConstant: 103) - ]) - - if let image1 = UIImage.ne_imageNamed(name: "record_3"), let image2 = UIImage.ne_imageNamed(name: "record_2"), let image3 = UIImage.ne_imageNamed(name: "record_1") { - recordImageView.animationImages = [image1,image2,image3] - } - recordImageView.animationDuration = 0.8 - let guesture = UILongPressGestureRecognizer(target: self, action: #selector(clickLabel)) - recordImageView.isUserInteractionEnabled = true - recordImageView.addGestureRecognizer(guesture) - - tipLabel.translatesAutoresizingMaskIntoConstraints = false - tipLabel.text = localizable("按住说话") - tipLabel.font = UIFont.systemFont(ofSize: 12) - tipLabel.textColor = .ne_lightText - tipLabel.textAlignment = .center - self.addSubview(tipLabel) - NSLayoutConstraint.activate([ - tipLabel.topAnchor.constraint(equalTo: recordImageView.bottomAnchor, constant: 12), - tipLabel.heightAnchor.constraint(equalToConstant: 23), - tipLabel.leftAnchor.constraint(equalTo: self.leftAnchor), - tipLabel.rightAnchor.constraint(equalTo: self.rightAnchor) - ]) - } - - @objc func clickLabel(recognizer: UILongPressGestureRecognizer) { - print("location:\(recognizer.location(in: recognizer.view))") - switch recognizer.state { - case .began: - print("state:begin") - startRecord() - case .changed: - print("state:changed") - case .ended: - self.endRecord(recognizer: recognizer) - case .cancelled: - print("state:cancelled") - case .failed: - print("state:failed") - default: - print("state:default") - } - } - - public func stopRecordAnimation() { - topTipLabel.isHidden = true - self.recordImageView.stopAnimating() - } - - private func startRecord() { - topTipLabel.isHidden = false - self.recordImageView.startAnimating() - self.delegate?.startRecord() - } - - private func moveOutView() { - self.delegate?.moveOutView() - } - - private func moveInView() { - self.delegate?.moveInView() + var recordImageView = UIImageView() + var topTipLabel = UILabel() + var tipLabel = UILabel() + public weak var delegate: ChatRecordViewDelegate? + private var outView = false + override init(frame: CGRect) { + super.init(frame: frame) + commonUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func commonUI() { + topTipLabel.translatesAutoresizingMaskIntoConstraints = false + topTipLabel.text = localizable("send_after_let_go") + topTipLabel.font = UIFont.systemFont(ofSize: 12) + topTipLabel.textColor = .ne_lightText + topTipLabel.textAlignment = .center + addSubview(topTipLabel) + NSLayoutConstraint.activate([ + topTipLabel.topAnchor.constraint(equalTo: topAnchor, constant: 0), + topTipLabel.heightAnchor.constraint(equalToConstant: 23), + topTipLabel.leftAnchor.constraint(equalTo: leftAnchor), + topTipLabel.rightAnchor.constraint(equalTo: rightAnchor), + ]) + + recordImageView.translatesAutoresizingMaskIntoConstraints = false + recordImageView.image = UIImage.ne_imageNamed(name: "chat_record") + recordImageView.contentMode = .center + addSubview(recordImageView) + NSLayoutConstraint.activate([ + recordImageView.centerXAnchor.constraint(equalTo: centerXAnchor), + recordImageView.topAnchor.constraint(equalTo: topAnchor, constant: 40), + recordImageView.heightAnchor.constraint(equalToConstant: 103), + recordImageView.widthAnchor.constraint(equalToConstant: 103), + ]) + + if let image1 = UIImage.ne_imageNamed(name: "record_3"), + let image2 = UIImage.ne_imageNamed(name: "record_2"), + let image3 = UIImage.ne_imageNamed(name: "record_1") { + recordImageView.animationImages = [image1, image2, image3] } - - private func endRecord(recognizer: UILongPressGestureRecognizer) { - self.stopRecordAnimation() - let inView = isInRecordView(recognizer: recognizer) - self.delegate?.endRecord(insideView: inView) + recordImageView.animationDuration = 0.8 + let guesture = UILongPressGestureRecognizer(target: self, action: #selector(clickLabel)) + recordImageView.isUserInteractionEnabled = true + recordImageView.addGestureRecognizer(guesture) + + tipLabel.translatesAutoresizingMaskIntoConstraints = false + tipLabel.text = localizable("按住说话") + tipLabel.font = UIFont.systemFont(ofSize: 12) + tipLabel.textColor = .ne_lightText + tipLabel.textAlignment = .center + addSubview(tipLabel) + NSLayoutConstraint.activate([ + tipLabel.topAnchor.constraint(equalTo: recordImageView.bottomAnchor, constant: 12), + tipLabel.heightAnchor.constraint(equalToConstant: 23), + tipLabel.leftAnchor.constraint(equalTo: leftAnchor), + tipLabel.rightAnchor.constraint(equalTo: rightAnchor), + ]) + } + + @objc func clickLabel(recognizer: UILongPressGestureRecognizer) { + print("location:\(recognizer.location(in: recognizer.view))") + switch recognizer.state { + case .began: + print("state:begin") + startRecord() + case .changed: + print("state:changed") + case .ended: + endRecord(recognizer: recognizer) + case .cancelled: + print("state:cancelled") + case .failed: + print("state:failed") + default: + print("state:default") } - - - private func isInRecordView(recognizer: UILongPressGestureRecognizer) -> Bool { - let point = recognizer.location(in: recognizer.view) - if point.x < 0 || point.x > recognizer.view?.bounds.size.width ?? 0 || point.y < 0 || point.y > recognizer.view?.bounds.size.height ?? 0 { - return false - } - return true + } + + public func stopRecordAnimation() { + topTipLabel.isHidden = true + recordImageView.stopAnimating() + } + + private func startRecord() { + topTipLabel.isHidden = false + recordImageView.startAnimating() + delegate?.startRecord() + } + + private func moveOutView() { + delegate?.moveOutView() + } + + private func moveInView() { + delegate?.moveInView() + } + + private func endRecord(recognizer: UILongPressGestureRecognizer) { + stopRecordAnimation() + let inView = isInRecordView(recognizer: recognizer) + delegate?.endRecord(insideView: inView) + } + + private func isInRecordView(recognizer: UILongPressGestureRecognizer) -> Bool { + let point = recognizer.location(in: recognizer.view) + if point.x < 0 || point.x > recognizer.view?.bounds.size.width ?? 0 || point.y < 0 || point + .y > recognizer.view?.bounds.size.height ?? 0 { + return false } + return true + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/CirleProgressView.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/CirleProgressView.swift index 806b4379..ebd0be92 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/CirleProgressView.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/CirleProgressView.swift @@ -1,71 +1,84 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class CirleProgressView: UIView { // 0~1 - public var progress: Float = 0 { - didSet { - if progress == 0 { - self.borderLayer.isHidden = true - self.sectorLayer.isHidden = true - self.imageView.isHidden = false - self.imageView.image = UIImage.ne_imageNamed(name: "chat_unread") - }else if progress == 1.0 { - self.borderLayer.isHidden = true - self.sectorLayer.isHidden = true - self.imageView.isHidden = false - self.imageView.image = UIImage.ne_imageNamed(name: "chat_read_all") - }else { - self.imageView.isHidden = true - self.borderLayer.isHidden = false - self.sectorLayer.isHidden = false - drawCircle(progress: progress) - } - } + public var progress: Float = 0 { + didSet { + if progress == 0 { + borderLayer.isHidden = true + sectorLayer.isHidden = true + imageView.isHidden = false + imageView.image = UIImage.ne_imageNamed(name: "chat_unread") + } else if progress == 1.0 { + borderLayer.isHidden = true + sectorLayer.isHidden = true + imageView.isHidden = false + imageView.image = UIImage.ne_imageNamed(name: "chat_read_all") + } else { + imageView.isHidden = true + borderLayer.isHidden = false + sectorLayer.isHidden = false + drawCircle(progress: progress) + } } - private var borderLayer = CAShapeLayer() - private var sectorLayer = CAShapeLayer() - private var imageView = UIImageView.init(image: UIImage.ne_imageNamed(name: "chat_unread")) - + } + + private var borderLayer = CAShapeLayer() + private var sectorLayer = CAShapeLayer() + private var imageView = UIImageView(image: UIImage.ne_imageNamed(name: "chat_unread")) + // override func draw(_ rect: CGRect) { // drawCircle(progress: progress) // } - - override init(frame: CGRect) { - super.init(frame: frame) - self.backgroundColor = .white - imageView.frame = self.bounds - imageView.contentMode = .center - self.addSubview(imageView) - - let borderPath = UIBezierPath(arcCenter: CGPoint(x: frame.size.width / 2.0, y: frame.size.height / 2.0), radius: 8, startAngle:0, endAngle: 2 * Double.pi, clockwise: false) - borderLayer.path = borderPath.cgPath - borderLayer.strokeColor = UIColor.ne_blueText.cgColor - borderLayer.fillColor = UIColor.clear.cgColor - borderLayer.lineWidth = 2 - borderLayer.frame = self.bounds - layer.addSublayer(borderLayer) - - sectorLayer.frame = self.bounds - layer.addSublayer(sectorLayer) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - private func drawCircle(progress: Float) { - let center = CGPoint(x: frame.size.width / 2.0, y: frame.size.height / 2.0) - let start = -Float.pi / 2.0 - let end = start + (progress * 2 * Float.pi) - - let sectorPath = UIBezierPath(arcCenter: center, radius: 8, startAngle: CGFloat(start), endAngle: CGFloat(end), clockwise: true) - sectorPath.addLine(to: center) - sectorLayer.path = sectorPath.cgPath - sectorLayer.fillColor = UIColor.ne_blueText.cgColor - } + override init(frame: CGRect) { + super.init(frame: frame) + backgroundColor = .white + imageView.frame = bounds + imageView.contentMode = .center + addSubview(imageView) + + let borderPath = UIBezierPath( + arcCenter: CGPoint(x: frame.size.width / 2.0, y: frame.size.height / 2.0), + radius: 8, + startAngle: 0, + endAngle: 2 * Double.pi, + clockwise: false + ) + borderLayer.path = borderPath.cgPath + borderLayer.strokeColor = UIColor.ne_blueText.cgColor + borderLayer.fillColor = UIColor.clear.cgColor + borderLayer.lineWidth = 2 + borderLayer.frame = bounds + layer.addSublayer(borderLayer) + + sectorLayer.frame = bounds + layer.addSublayer(sectorLayer) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func drawCircle(progress: Float) { + let center = CGPoint(x: frame.size.width / 2.0, y: frame.size.height / 2.0) + let start = -Float.pi / 2.0 + let end = start + (progress * 2 * Float.pi) + let sectorPath = UIBezierPath( + arcCenter: center, + radius: 8, + startAngle: CGFloat(start), + endAngle: CGFloat(end), + clockwise: true + ) + sectorPath.addLine(to: center) + sectorLayer.path = sectorPath.cgPath + sectorLayer.fillColor = UIColor.ne_blueText.cgColor + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/ForwardAlertViewController.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/ForwardAlertViewController.swift index e222965f..e34457a1 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/ForwardAlertViewController.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/ForwardAlertViewController.swift @@ -1,324 +1,330 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCommon import NEKitCommonUI public class ForwardItem { - var name: String? - var uid: String? - var avatar: String? - public init(){} + var name: String? + var uid: String? + var avatar: String? + public init() {} } public class ForwardUserCell: UICollectionViewCell { - - lazy var userHeader: NEUserHeaderView = { - let header = NEUserHeaderView(frame: .zero) - header.translatesAutoresizingMaskIntoConstraints = false - header.titleLabel.font = NEConstant.defaultTextFont(11.0) - header.clipsToBounds = true - header.layer.cornerRadius = 16.0 - return header - }() - - public override init(frame: CGRect){ - super.init(frame: frame) - setupUI() - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - } - - func setupUI(){ - contentView.addSubview(userHeader) - NSLayoutConstraint.activate([ - userHeader.leftAnchor.constraint(equalTo: contentView.leftAnchor), - userHeader.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - userHeader.widthAnchor.constraint(equalToConstant: 32.0), - userHeader.heightAnchor.constraint(equalToConstant: 32.0) - ]) - } + lazy var userHeader: NEUserHeaderView = { + let header = NEUserHeaderView(frame: .zero) + header.translatesAutoresizingMaskIntoConstraints = false + header.titleLabel.font = NEConstant.defaultTextFont(11.0) + header.clipsToBounds = true + header.layer.cornerRadius = 16.0 + return header + }() + + override public init(frame: CGRect) { + super.init(frame: frame) + setupUI() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + func setupUI() { + contentView.addSubview(userHeader) + NSLayoutConstraint.activate([ + userHeader.leftAnchor.constraint(equalTo: contentView.leftAnchor), + userHeader.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + userHeader.widthAnchor.constraint(equalToConstant: 32.0), + userHeader.heightAnchor.constraint(equalToConstant: 32.0), + ]) + } } public class ForwardAlertViewController: UIViewController { - - var datas = [ForwardItem]() - - typealias ForwardCallBack = () -> Void - var cancelBlock: ForwardCallBack? - var sureBlock: ForwardCallBack? - var context = "" - - - lazy var userCollection: UICollectionView = { - let flow = UICollectionViewFlowLayout() - flow.scrollDirection = .horizontal - flow.minimumLineSpacing = 9.5 - flow.minimumInteritemSpacing = 9.5 - let collection = UICollectionView(frame: .zero, collectionViewLayout: flow) - collection.translatesAutoresizingMaskIntoConstraints = false - collection.delegate = self - collection.dataSource = self - collection.backgroundColor = .clear - collection.showsHorizontalScrollIndicator = false - return collection - }() - - lazy var contentView: UIView = { - let back = UIView() - back.backgroundColor = .white - back.translatesAutoresizingMaskIntoConstraints = false - back.clipsToBounds = true - back.layer.cornerRadius = 8.0 - return back - }() - - lazy var oneUserHead: NEUserHeaderView = { - let header = NEUserHeaderView(frame: .zero) - header.clipsToBounds = true - header.layer.cornerRadius = 16.0 - header.translatesAutoresizingMaskIntoConstraints = false - return header - }() - - lazy var oneUserName: UILabel = { - let name = UILabel() - name.textColor = .ne_darkText - name.font = NEConstant.defaultTextFont(14.0) - name.translatesAutoresizingMaskIntoConstraints = false - return name - }() - - lazy var contentText: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.font = NEConstant.defaultTextFont(14.0) - label.textColor = .ne_darkText - label.numberOfLines = 0 - return label - }() - - public override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - setupUI() - } - - public func setupUI(){ - view.backgroundColor = NEConstant.hexRGB(0x000000).withAlphaComponent(0.4) - view.addSubview(contentView) - NSLayoutConstraint.activate([ - contentView.centerXAnchor.constraint(equalTo: view.centerXAnchor), - contentView.centerYAnchor.constraint(equalTo: view.centerYAnchor), - contentView.widthAnchor.constraint(equalToConstant: 276) - ]) - - let tip = UILabel() - tip.translatesAutoresizingMaskIntoConstraints = false - tip.font = NEConstant.defaultTextFont(16.0) - tip.textColor = .ne_darkText - tip.text = localizable("send_to") - contentView.addSubview(tip) - NSLayoutConstraint.activate([ - tip.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 16.0), - tip.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 16), - tip.heightAnchor.constraint(equalToConstant: 18.0) - ]) - - contentView.addSubview(oneUserHead) - NSLayoutConstraint.activate([ - oneUserHead.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 16), - oneUserHead.topAnchor.constraint(equalTo: tip.bottomAnchor, constant: 16), - oneUserHead.widthAnchor.constraint(equalToConstant: 32.0), - oneUserHead.heightAnchor.constraint(equalToConstant: 32.0) - ]) - - contentView.addSubview(oneUserName) - NSLayoutConstraint.activate([ - oneUserName.leftAnchor.constraint(equalTo: oneUserHead.rightAnchor, constant: 8.0), - oneUserName.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -16.0), - oneUserName.centerYAnchor.constraint(equalTo: oneUserHead.centerYAnchor) - ]) - - contentView.addSubview(userCollection) - NSLayoutConstraint.activate([ - userCollection.leftAnchor.constraint(equalTo: contentView.leftAnchor,constant: 16.0), - userCollection.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -16.0), - userCollection.heightAnchor.constraint(equalToConstant: 32.0), - userCollection.topAnchor.constraint(equalTo: oneUserHead.topAnchor) - ]) - - let textBack = UIView() - textBack.translatesAutoresizingMaskIntoConstraints = false - textBack.backgroundColor = NEConstant.hexRGB(0xF2F4F5) - textBack.clipsToBounds = true - textBack.layer.cornerRadius = 4.0 - contentView.addSubview(textBack) - NSLayoutConstraint.activate([ - textBack.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 16.0), - textBack.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -16.0), - textBack.topAnchor.constraint(equalTo: oneUserHead.bottomAnchor, constant: 12.0) - ]) - - textBack.addSubview(contentText) - NSLayoutConstraint.activate([ - contentText.leftAnchor.constraint(equalTo: textBack.leftAnchor, constant: 12), - contentText.rightAnchor.constraint(equalTo: textBack.rightAnchor, constant: -12), - contentText.topAnchor.constraint(equalTo: textBack.topAnchor, constant: 7), - contentText.bottomAnchor.constraint(equalTo: textBack.bottomAnchor, constant: -7) - ]) - contentText.text = "[转发]\(context)的会话记录" - - let verticalLine = UIView() - verticalLine.translatesAutoresizingMaskIntoConstraints = false - contentView.addSubview(verticalLine) - verticalLine.backgroundColor = NEConstant.hexRGB(0xE1E6E8) - NSLayoutConstraint.activate([ - verticalLine.centerXAnchor.constraint(equalTo: contentView.centerXAnchor), - verticalLine.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), - verticalLine.widthAnchor.constraint(equalToConstant: 1.0), - verticalLine.heightAnchor.constraint(equalToConstant: 51), - verticalLine.topAnchor.constraint(equalTo: textBack.bottomAnchor, constant: 16.0) - ]) - - let horizontalLine = UIView() - horizontalLine.translatesAutoresizingMaskIntoConstraints = false - contentView.addSubview(horizontalLine) - horizontalLine.backgroundColor = NEConstant.hexRGB(0xE1E6E8) - NSLayoutConstraint.activate([ - horizontalLine.leftAnchor.constraint(equalTo: contentView.leftAnchor), - horizontalLine.rightAnchor.constraint(equalTo: contentView.rightAnchor), - horizontalLine.heightAnchor.constraint(equalToConstant: 1), - horizontalLine.bottomAnchor.constraint(equalTo: verticalLine.topAnchor) - ]) - - let canceBtn = UIButton() - canceBtn.translatesAutoresizingMaskIntoConstraints = false - canceBtn.addTarget(self, action: #selector(cancelClick), for: .touchUpInside) - canceBtn.setTitle("取消", for: .normal) - canceBtn.setTitleColor(.ne_greyText, for: .normal) - - let sureBtn = UIButton() - sureBtn.translatesAutoresizingMaskIntoConstraints = false - sureBtn.addTarget(self, action: #selector(sureClick), for: .touchUpInside) - sureBtn.setTitle("确定", for: .normal) - sureBtn.setTitleColor(.ne_blueText, for: .normal) - - contentView.addSubview(canceBtn) - NSLayoutConstraint.activate([ - canceBtn.leftAnchor.constraint(equalTo: contentView.leftAnchor), - canceBtn.bottomAnchor.constraint(equalTo: verticalLine.bottomAnchor), - canceBtn.topAnchor.constraint(equalTo: horizontalLine.bottomAnchor), - canceBtn.rightAnchor.constraint(equalTo: verticalLine.leftAnchor) - ]) - - contentView.addSubview(sureBtn) - NSLayoutConstraint.activate([ - sureBtn.bottomAnchor.constraint(equalTo: verticalLine.bottomAnchor), - sureBtn.rightAnchor.constraint(equalTo: contentView.rightAnchor), - sureBtn.topAnchor.constraint(equalTo: horizontalLine.bottomAnchor), - sureBtn.leftAnchor.constraint(equalTo: verticalLine.rightAnchor) - ]) - - userCollection.register(ForwardUserCell.self, forCellWithReuseIdentifier: "\(ForwardUserCell.self)") - - } - - public func setItems(_ items: [ForwardItem]){ - datas.append(contentsOf: items) - if datas.count == 1 { - let item = datas[0] - if let name = item.name { - oneUserHead.setTitle(name) - oneUserName.text = name - }else if let uid = item.uid { - oneUserHead.setTitle(uid) - oneUserName.text = uid - } - if let url = item.avatar { - oneUserHead.sd_setImage(with: URL(string: url), completed: nil) - oneUserHead.titleLabel.text = "" - }else { - oneUserHead.backgroundColor = UIColor.colorWithString(string: item.uid) - oneUserHead.image = nil - } - userCollection.isHidden = true - }else { - oneUserHead.isHidden = true - oneUserName.isHidden = true - } - } - + var datas = [ForwardItem]() - /* - // MARK: - Navigation + typealias ForwardCallBack = () -> Void + var cancelBlock: ForwardCallBack? + var sureBlock: ForwardCallBack? + var context = "" - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. - } - */ - - @objc func sureClick(){ - if let block = sureBlock { - block() - } - removeSelf() - } - - @objc func cancelClick(){ - if let block = cancelBlock { - block() - } - removeSelf() + lazy var userCollection: UICollectionView = { + let flow = UICollectionViewFlowLayout() + flow.scrollDirection = .horizontal + flow.minimumLineSpacing = 9.5 + flow.minimumInteritemSpacing = 9.5 + let collection = UICollectionView(frame: .zero, collectionViewLayout: flow) + collection.translatesAutoresizingMaskIntoConstraints = false + collection.delegate = self + collection.dataSource = self + collection.backgroundColor = .clear + collection.showsHorizontalScrollIndicator = false + return collection + }() + + lazy var contentView: UIView = { + let back = UIView() + back.backgroundColor = .white + back.translatesAutoresizingMaskIntoConstraints = false + back.clipsToBounds = true + back.layer.cornerRadius = 8.0 + return back + }() + + lazy var oneUserHead: NEUserHeaderView = { + let header = NEUserHeaderView(frame: .zero) + header.clipsToBounds = true + header.layer.cornerRadius = 16.0 + header.translatesAutoresizingMaskIntoConstraints = false + return header + }() + + lazy var oneUserName: UILabel = { + let name = UILabel() + name.textColor = .ne_darkText + name.font = NEConstant.defaultTextFont(14.0) + name.translatesAutoresizingMaskIntoConstraints = false + return name + }() + + lazy var contentText: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.font = NEConstant.defaultTextFont(14.0) + label.textColor = .ne_darkText + label.numberOfLines = 0 + return label + }() + + override public func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + setupUI() + } + + public func setupUI() { + view.backgroundColor = NEConstant.hexRGB(0x000000).withAlphaComponent(0.4) + view.addSubview(contentView) + NSLayoutConstraint.activate([ + contentView.centerXAnchor.constraint(equalTo: view.centerXAnchor), + contentView.centerYAnchor.constraint(equalTo: view.centerYAnchor), + contentView.widthAnchor.constraint(equalToConstant: 276), + ]) + + let tip = UILabel() + tip.translatesAutoresizingMaskIntoConstraints = false + tip.font = NEConstant.defaultTextFont(16.0) + tip.textColor = .ne_darkText + tip.text = localizable("send_to") + contentView.addSubview(tip) + NSLayoutConstraint.activate([ + tip.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 16.0), + tip.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 16), + tip.heightAnchor.constraint(equalToConstant: 18.0), + ]) + + contentView.addSubview(oneUserHead) + NSLayoutConstraint.activate([ + oneUserHead.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 16), + oneUserHead.topAnchor.constraint(equalTo: tip.bottomAnchor, constant: 16), + oneUserHead.widthAnchor.constraint(equalToConstant: 32.0), + oneUserHead.heightAnchor.constraint(equalToConstant: 32.0), + ]) + + contentView.addSubview(oneUserName) + NSLayoutConstraint.activate([ + oneUserName.leftAnchor.constraint(equalTo: oneUserHead.rightAnchor, constant: 8.0), + oneUserName.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -16.0), + oneUserName.centerYAnchor.constraint(equalTo: oneUserHead.centerYAnchor), + ]) + + contentView.addSubview(userCollection) + NSLayoutConstraint.activate([ + userCollection.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 16.0), + userCollection.rightAnchor.constraint( + equalTo: contentView.rightAnchor, + constant: -16.0 + ), + userCollection.heightAnchor.constraint(equalToConstant: 32.0), + userCollection.topAnchor.constraint(equalTo: oneUserHead.topAnchor), + ]) + + let textBack = UIView() + textBack.translatesAutoresizingMaskIntoConstraints = false + textBack.backgroundColor = NEConstant.hexRGB(0xF2F4F5) + textBack.clipsToBounds = true + textBack.layer.cornerRadius = 4.0 + contentView.addSubview(textBack) + NSLayoutConstraint.activate([ + textBack.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 16.0), + textBack.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -16.0), + textBack.topAnchor.constraint(equalTo: oneUserHead.bottomAnchor, constant: 12.0), + ]) + + textBack.addSubview(contentText) + NSLayoutConstraint.activate([ + contentText.leftAnchor.constraint(equalTo: textBack.leftAnchor, constant: 12), + contentText.rightAnchor.constraint(equalTo: textBack.rightAnchor, constant: -12), + contentText.topAnchor.constraint(equalTo: textBack.topAnchor, constant: 7), + contentText.bottomAnchor.constraint(equalTo: textBack.bottomAnchor, constant: -7), + ]) + contentText.text = "[转发]\(context)的会话记录" + + let verticalLine = UIView() + verticalLine.translatesAutoresizingMaskIntoConstraints = false + contentView.addSubview(verticalLine) + verticalLine.backgroundColor = NEConstant.hexRGB(0xE1E6E8) + NSLayoutConstraint.activate([ + verticalLine.centerXAnchor.constraint(equalTo: contentView.centerXAnchor), + verticalLine.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + verticalLine.widthAnchor.constraint(equalToConstant: 1.0), + verticalLine.heightAnchor.constraint(equalToConstant: 51), + verticalLine.topAnchor.constraint(equalTo: textBack.bottomAnchor, constant: 16.0), + ]) + + let horizontalLine = UIView() + horizontalLine.translatesAutoresizingMaskIntoConstraints = false + contentView.addSubview(horizontalLine) + horizontalLine.backgroundColor = NEConstant.hexRGB(0xE1E6E8) + NSLayoutConstraint.activate([ + horizontalLine.leftAnchor.constraint(equalTo: contentView.leftAnchor), + horizontalLine.rightAnchor.constraint(equalTo: contentView.rightAnchor), + horizontalLine.heightAnchor.constraint(equalToConstant: 1), + horizontalLine.bottomAnchor.constraint(equalTo: verticalLine.topAnchor), + ]) + + let canceBtn = UIButton() + canceBtn.translatesAutoresizingMaskIntoConstraints = false + canceBtn.addTarget(self, action: #selector(cancelClick), for: .touchUpInside) + canceBtn.setTitle("取消", for: .normal) + canceBtn.setTitleColor(.ne_greyText, for: .normal) + + let sureBtn = UIButton() + sureBtn.translatesAutoresizingMaskIntoConstraints = false + sureBtn.addTarget(self, action: #selector(sureClick), for: .touchUpInside) + sureBtn.setTitle("确定", for: .normal) + sureBtn.setTitleColor(.ne_blueText, for: .normal) + + contentView.addSubview(canceBtn) + NSLayoutConstraint.activate([ + canceBtn.leftAnchor.constraint(equalTo: contentView.leftAnchor), + canceBtn.bottomAnchor.constraint(equalTo: verticalLine.bottomAnchor), + canceBtn.topAnchor.constraint(equalTo: horizontalLine.bottomAnchor), + canceBtn.rightAnchor.constraint(equalTo: verticalLine.leftAnchor), + ]) + + contentView.addSubview(sureBtn) + NSLayoutConstraint.activate([ + sureBtn.bottomAnchor.constraint(equalTo: verticalLine.bottomAnchor), + sureBtn.rightAnchor.constraint(equalTo: contentView.rightAnchor), + sureBtn.topAnchor.constraint(equalTo: horizontalLine.bottomAnchor), + sureBtn.leftAnchor.constraint(equalTo: verticalLine.rightAnchor), + ]) + + userCollection.register( + ForwardUserCell.self, + forCellWithReuseIdentifier: "\(ForwardUserCell.self)" + ) + } + + public func setItems(_ items: [ForwardItem]) { + datas.append(contentsOf: items) + if datas.count == 1 { + let item = datas[0] + if let name = item.name { + oneUserHead.setTitle(name) + oneUserName.text = name + } else if let uid = item.uid { + oneUserHead.setTitle(uid) + oneUserName.text = uid + } + if let url = item.avatar { + oneUserHead.sd_setImage(with: URL(string: url), completed: nil) + oneUserHead.titleLabel.text = "" + } else { + oneUserHead.backgroundColor = UIColor.colorWithString(string: item.uid) + oneUserHead.image = nil + } + userCollection.isHidden = true + } else { + oneUserHead.isHidden = true + oneUserName.isHidden = true } - - public override func touchesBegan(_ touches: Set, with event: UIEvent?) { - removeSelf() + } + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ + + @objc func sureClick() { + if let block = sureBlock { + block() } - - func removeSelf(){ - self.view.removeFromSuperview() - self.removeFromParent() + removeSelf() + } + + @objc func cancelClick() { + if let block = cancelBlock { + block() } + removeSelf() + } + override public func touchesBegan(_ touches: Set, with event: UIEvent?) { + removeSelf() + } + + func removeSelf() { + view.removeFromSuperview() + removeFromParent() + } } -extension ForwardAlertViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { - - public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - return datas.count - } - - public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { - if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "\(ForwardUserCell.self)", for: indexPath) as? ForwardUserCell { - let item = datas[indexPath.row] - if let url = item.avatar { - cell.userHeader.sd_setImage(with: URL(string: url), completed: nil) - cell.userHeader.titleLabel.text = "" - }else { - cell.userHeader.backgroundColor = UIColor.colorWithString(string: item.uid) - cell.userHeader.image = nil - if let name = item.name { - cell.userHeader.setTitle(name) - }else if let uid = item.uid { - cell.userHeader.setTitle(uid) - } - } - return cell +extension ForwardAlertViewController: UICollectionViewDelegate, UICollectionViewDataSource, + UICollectionViewDelegateFlowLayout { + public func collectionView(_ collectionView: UICollectionView, + numberOfItemsInSection section: Int) -> Int { + datas.count + } + + public func collectionView(_ collectionView: UICollectionView, + cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + if let cell = collectionView.dequeueReusableCell( + withReuseIdentifier: "\(ForwardUserCell.self)", + for: indexPath + ) as? ForwardUserCell { + let item = datas[indexPath.row] + if let url = item.avatar { + cell.userHeader.sd_setImage(with: URL(string: url), completed: nil) + cell.userHeader.titleLabel.text = "" + } else { + cell.userHeader.backgroundColor = UIColor.colorWithString(string: item.uid) + cell.userHeader.image = nil + if let name = item.name { + cell.userHeader.setTitle(name) + } else if let uid = item.uid { + cell.userHeader.setTitle(uid) } - return UICollectionViewCell() + } + return cell } - - public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { - return CGSize(width: 32.0, height: 32) - } - - + return UICollectionViewCell() + } + + public func collectionView(_ collectionView: UICollectionView, + layout collectionViewLayout: UICollectionViewLayout, + sizeForItemAt indexPath: IndexPath) -> CGSize { + CGSize(width: 32.0, height: 32) + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/MessageOperationView.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/MessageOperationView.swift index a2242db4..fef55edc 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/MessageOperationView.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/MessageOperationView.swift @@ -1,82 +1,93 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit public protocol MessageOperationViewDelegate: AnyObject { - func didSelectedItem(item: OperationItem) + func didSelectedItem(item: OperationItem) } public class MessageOperationView: UIView, UICollectionViewDataSource, UICollectionViewDelegate { - - var collcetionView: UICollectionView - public weak var delegate: MessageOperationViewDelegate? - public var items = [OperationItem]() { - didSet { - collcetionView.reloadData() - } + var collcetionView: UICollectionView + public weak var delegate: MessageOperationViewDelegate? + public var items = [OperationItem]() { + didSet { + collcetionView.reloadData() } - - override init(frame: CGRect) { - let layout = UICollectionViewFlowLayout() - layout.itemSize = CGSize(width: 60, height: 56) - layout.minimumLineSpacing = 0 - layout.minimumInteritemSpacing = 0; - layout.scrollDirection = .vertical - collcetionView = UICollectionView(frame: .zero, collectionViewLayout: layout) - collcetionView.backgroundColor = .white - collcetionView.translatesAutoresizingMaskIntoConstraints = false - - super.init(frame: frame) - self.backgroundColor = .white + } + + override init(frame: CGRect) { + let layout = UICollectionViewFlowLayout() + layout.itemSize = CGSize(width: 60, height: 56) + layout.minimumLineSpacing = 0 + layout.minimumInteritemSpacing = 0 + layout.scrollDirection = .vertical + collcetionView = UICollectionView(frame: .zero, collectionViewLayout: layout) + collcetionView.backgroundColor = .white + collcetionView.translatesAutoresizingMaskIntoConstraints = false + + super.init(frame: frame) + backgroundColor = .white // self.layer.cornerRadius = 8 // self.layer.shadowRadius = 4 // self.layer.shadowColor = UIColor.black.cgColor // self.layer.shadowOffset = CGSize(width: 4.0, height: 4.0) -// +// // collcetionView.layer.shadowRadius = 4 // collcetionView.layer.shadowColor = UIColor.black.cgColor // collcetionView.layer.shadowOffset = CGSize(width: 4.0, height: 4.0) // collcetionView.layer.shadowOpacity = 0.8 -// - - collcetionView.dataSource = self - collcetionView.delegate = self - collcetionView.isUserInteractionEnabled = true - collcetionView.register(OperationCell.self, forCellWithReuseIdentifier: "\(OperationCell.self)") - self.addSubview(collcetionView) - NSLayoutConstraint.activate([ - collcetionView.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 8), - collcetionView.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -8), - collcetionView.topAnchor.constraint(equalTo: self.topAnchor, constant: 8), - collcetionView.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -8), - ]) - - self.addSubview(collcetionView) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - +// + + collcetionView.dataSource = self + collcetionView.delegate = self + collcetionView.isUserInteractionEnabled = true + collcetionView.register( + OperationCell.self, + forCellWithReuseIdentifier: "\(OperationCell.self)" + ) + addSubview(collcetionView) + NSLayoutConstraint.activate([ + collcetionView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 8), + collcetionView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -8), + collcetionView.topAnchor.constraint(equalTo: topAnchor, constant: 8), + collcetionView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -8), + ]) + + addSubview(collcetionView) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + // MARK: UICollectionViewDataSource - public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - return items.count - } - - public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { - let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "\(OperationCell.self)", for: indexPath) as? OperationCell - cell?.model = items[indexPath.row] + + public func collectionView(_ collectionView: UICollectionView, + numberOfItemsInSection section: Int) -> Int { + items.count + } + + public func collectionView(_ collectionView: UICollectionView, + cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + let cell = collectionView.dequeueReusableCell( + withReuseIdentifier: "\(OperationCell.self)", + for: indexPath + ) as? OperationCell + cell?.model = items[indexPath.row] // cell?.delegate = self - return cell ?? UICollectionViewCell() - } - + return cell ?? UICollectionViewCell() + } + // MARK: UICollectionViewDelegate - public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - self.removeFromSuperview() - self.delegate?.didSelectedItem(item: items[indexPath.row]) - } + + public func collectionView(_ collectionView: UICollectionView, + didSelectItemAt indexPath: IndexPath) { + removeFromSuperview() + delegate?.didSelectedItem(item: items[indexPath.row]) + } // func didSelected(_ cell: OperationCell, _ model: OperationItem?) { // self.removeFromSuperview() @@ -85,5 +96,4 @@ public class MessageOperationView: UIView, UICollectionViewDataSource, UICollect // } // // } - } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/ReplyView.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/ReplyView.swift index a9410d8a..43ed0161 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/View/ReplyView.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/View/ReplyView.swift @@ -1,61 +1,56 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class ReplyView: UIView { - var closeButton = UIButton(type: .custom) - var line = UIView() - var textLabel = UILabel() - - override init(frame: CGRect) { - super.init(frame: frame) - self.backgroundColor = UIColor(hexString: "#EFF1F2") - closeButton.setImage(UIImage.ne_imageNamed(name: "close"), for: .normal) - closeButton.translatesAutoresizingMaskIntoConstraints = false + var closeButton = UIButton(type: .custom) + var line = UIView() + var textLabel = UILabel() + + override init(frame: CGRect) { + super.init(frame: frame) + backgroundColor = UIColor(hexString: "#EFF1F2") + closeButton.setImage(UIImage.ne_imageNamed(name: "close"), for: .normal) + closeButton.translatesAutoresizingMaskIntoConstraints = false // closeButton.addTarget(self, action: #selector(closeButtonEvent), for: .touchUpInside) - self.addSubview(closeButton) - NSLayoutConstraint.activate([ - closeButton.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 0), - closeButton.topAnchor.constraint(equalTo: self.topAnchor, constant: 0), - closeButton.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 0), - closeButton.widthAnchor.constraint(equalToConstant: 34) - ]) - - line.backgroundColor = UIColor(hexString: "#D8DAE4") - line.translatesAutoresizingMaskIntoConstraints = false - self.addSubview(line) - NSLayoutConstraint.activate([ - line.leadingAnchor.constraint(equalTo: closeButton.trailingAnchor, constant: -3), - line.topAnchor.constraint(equalTo: self.topAnchor, constant: 8), - line.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -8), - line.widthAnchor.constraint(equalToConstant: 1) - ]) - - textLabel.font = UIFont.systemFont(ofSize: 12) - textLabel.textColor = UIColor(hexString: "#929299") - textLabel.translatesAutoresizingMaskIntoConstraints = false - self.addSubview(textLabel) - NSLayoutConstraint.activate([ - textLabel.leadingAnchor.constraint(equalTo: closeButton.trailingAnchor, constant: 8), - textLabel.topAnchor.constraint(equalTo: self.topAnchor, constant: 8), - textLabel.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -8), - textLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -8) - ]) - - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - + addSubview(closeButton) + NSLayoutConstraint.activate([ + closeButton.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 0), + closeButton.topAnchor.constraint(equalTo: topAnchor, constant: 0), + closeButton.bottomAnchor.constraint(equalTo: bottomAnchor, constant: 0), + closeButton.widthAnchor.constraint(equalToConstant: 34), + ]) + + line.backgroundColor = UIColor(hexString: "#D8DAE4") + line.translatesAutoresizingMaskIntoConstraints = false + addSubview(line) + NSLayoutConstraint.activate([ + line.leadingAnchor.constraint(equalTo: closeButton.trailingAnchor, constant: -3), + line.topAnchor.constraint(equalTo: topAnchor, constant: 8), + line.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -8), + line.widthAnchor.constraint(equalToConstant: 1), + ]) + + textLabel.font = UIFont.systemFont(ofSize: 12) + textLabel.textColor = UIColor(hexString: "#929299") + textLabel.translatesAutoresizingMaskIntoConstraints = false + addSubview(textLabel) + NSLayoutConstraint.activate([ + textLabel.leadingAnchor.constraint(equalTo: closeButton.trailingAnchor, constant: 8), + textLabel.topAnchor.constraint(equalTo: topAnchor, constant: 8), + textLabel.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -8), + textLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -8), + ]) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + // @objc func closeButtonEvent(button: UIButton) { // self.removeFromSuperview() // } - - - - - } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/ViewModel/ChatViewModel.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/ViewModel/ChatViewModel.swift index 66a14a98..d6efd781 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/ViewModel/ChatViewModel.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/ViewModel/ChatViewModel.swift @@ -1,6 +1,7 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NEKitCoreIM @@ -8,396 +9,443 @@ import NIMSDK import NEKitChat import NEKitCommon import NEKitCore -//import NEKitContact +// import NEKitContact -public enum LoadMessageDirection:Int { - case old = 0 - case new +public enum LoadMessageDirection: Int { + case old = 0 + case new } public protocol ChatViewModelDelegate: AnyObject { - func onRecvMessages(_ messages: [NIMMessage]) - func willSend(_ message: NIMMessage) - func send(_ message: NIMMessage, didCompleteWithError error: Error?) - func send(_ message: NIMMessage, progress: Float) - func didReadedMessageIndexs() - func onDeleteMessage(_ message: NIMMessage, atIndexs:[IndexPath]) - func onRevokeMessage(_ message: NIMMessage, atIndexs:[IndexPath]) - func onAddMessagePin(_ message: NIMMessage, atIndexs:[IndexPath]) - func onRemoveMessagePin(_ message: NIMMessage, atIndexs:[IndexPath]) - func updateDownloadProgress(_ message: NIMMessage, atIndex: IndexPath, progress: Float) - func remoteUserEditing() - func remoteUserEndEditing() + func onRecvMessages(_ messages: [NIMMessage]) + func willSend(_ message: NIMMessage) + func send(_ message: NIMMessage, didCompleteWithError error: Error?) + func send(_ message: NIMMessage, progress: Float) + func didReadedMessageIndexs() + func onDeleteMessage(_ message: NIMMessage, atIndexs: [IndexPath]) + func onRevokeMessage(_ message: NIMMessage, atIndexs: [IndexPath]) + func onAddMessagePin(_ message: NIMMessage, atIndexs: [IndexPath]) + func onRemoveMessagePin(_ message: NIMMessage, atIndexs: [IndexPath]) + func updateDownloadProgress(_ message: NIMMessage, atIndex: IndexPath, progress: Float) + func remoteUserEditing() + func remoteUserEndEditing() } -public class ChatViewModel: NSObject, ChatRepoMessageDelegate, NIMChatManagerDelegate, NIMConversationManagerDelegate, NIMSystemNotificationManagerDelegate,ChatExtendProviderDelegate { - - public var session: NIMSession - public var messages: [MessageModel] = [MessageModel]() - public weak var delegate: ChatViewModelDelegate? - //上拉时间戳 - private var newMsg: NIMMessage? - //下拉时间戳 - private var oldMsg: NIMMessage? - - - public var repo: ChatRepo = ChatRepo() - public var operationModel: MessageContentModel? - private var userInfo = [String : User]() - public var isReplying = false - public let messagPageNum: UInt = 100 - private let className = "ChatViewModel" - //可信时间戳 - public var credibleTimestamp:TimeInterval = 0 - public var anchor:NIMMessage? - - public var isHistoryChat = false - - - init(session:NIMSession) { - self.session = session - self.anchor = nil - super.init() - repo.addChatDelegate(delegate: self) - repo.addSessionDelegate(delegate: self) - repo.addSystemNotificationDelegate(delegate: self) - repo.addChatExtendDelegate(delegate: self) - } - - - init(session:NIMSession,anchor:NIMMessage?) { - self.session = session - self.anchor = anchor - super.init() - if anchor != nil { - isHistoryChat = true +public class ChatViewModel: NSObject, ChatRepoMessageDelegate, NIMChatManagerDelegate, + NIMConversationManagerDelegate, NIMSystemNotificationManagerDelegate, ChatExtendProviderDelegate { + public var session: NIMSession + public var messages: [MessageModel] = .init() + public weak var delegate: ChatViewModelDelegate? + // 上拉时间戳 + private var newMsg: NIMMessage? + // 下拉时间戳 + private var oldMsg: NIMMessage? + + public var repo: ChatRepo = .init() + public var operationModel: MessageContentModel? + private var userInfo = [String: User]() + public var isReplying = false + public let messagPageNum: UInt = 100 + private let className = "ChatViewModel" + // 可信时间戳 + public var credibleTimestamp: TimeInterval = 0 + public var anchor: NIMMessage? + + public var isHistoryChat = false + + init(session: NIMSession) { + self.session = session + anchor = nil + super.init() + repo.addChatDelegate(delegate: self) + repo.addSessionDelegate(delegate: self) + repo.addSystemNotificationDelegate(delegate: self) + repo.addChatExtendDelegate(delegate: self) + } + + init(session: NIMSession, anchor: NIMMessage?) { + self.session = session + self.anchor = anchor + super.init() + if anchor != nil { + isHistoryChat = true + } + repo.addChatDelegate(delegate: self) + repo.addSessionDelegate(delegate: self) + repo.addSystemNotificationDelegate(delegate: self) + repo.addChatExtendDelegate(delegate: self) + } + + public func sendTextMessage(text: String, _ completion: @escaping (Error?) -> Void) { + if text.count <= 0 { + return + } + repo.sendMessage( + message: MessageUtils.textMessage(text: text), + session: session, + completion + ) + } + + public func sendAudioMessage(filePath: String, _ completion: @escaping (Error?) -> Void) { + repo.sendMessage( + message: MessageUtils.audioMessage(filePath: filePath), + session: session, + completion + ) + } + + public func sendImageMessage(image: UIImage, _ completion: @escaping (Error?) -> Void) { + // TODO: + repo.sendMessage( + message: MessageUtils.imageMessage(image: image), + session: session, + completion + ) + } + + public func sendVideoMessage(url: URL, _ completion: @escaping (Error?) -> Void) { + weak var weakSelf = self + VideoFormatConvert + .convertToMP4(with: url, avQuality: AVAssetExportPresetHighestQuality) { path, image in + if let p = path, let s = weakSelf?.session { + weakSelf?.repo.sendMessage( + message: MessageUtils.videoMessage(filePath: p), + session: s, + completion + ) + } else { + NELog.errorLog("chat veiw model", desc: "convert mov to mp4 failed") } - repo.addChatDelegate(delegate: self) - repo.addSessionDelegate(delegate: self) - repo.addSystemNotificationDelegate(delegate: self) - repo.addChatExtendDelegate(delegate: self) - } - - public func sendTextMessage(text: String, _ completion: @escaping (Error?) -> Void) { - if text.count <= 0 { - return + } + } + + public func queryRoamMsgHasMoreTime(_ completion: @escaping (Error?, NSInteger, + [MessageModel]?) -> Void) { +// NIMIncompleteSessionInfo + weak var weakSelf = self + repo.getIncompleteSessionInfo(session: session) { error, sessionInfos in + if error == nil { + let sessionInfo = sessionInfos?.first + // 记录可信时间戳 + weakSelf?.credibleTimestamp = sessionInfo?.timestamp ?? 0 + if weakSelf?.anchor == nil { + weakSelf?.getMessageHistory(self.oldMsg, completion) + + } else { + // 有锚点消息,从两个方向拉去消息 + weakSelf?.newMsg = weakSelf?.anchor + weakSelf?.oldMsg = weakSelf?.anchor + weakSelf?.dropDownRemoteRefresh(completion) + weakSelf?.pullRemoteRefresh(completion) } - repo.sendMessage(message: MessageUtils.textMessage(text: text), session: self.session, completion) - } - - public func sendAudioMessage(filePath: String, _ completion: @escaping (Error?) -> Void) { - repo.sendMessage(message: MessageUtils.audioMessage(filePath: filePath), session: self.session, completion) - } - - public func sendImageMessage(image: UIImage, _ completion: @escaping (Error?) -> Void) { - // TODO: - repo.sendMessage(message: MessageUtils.imageMessage(image: image), session: session, completion) + } } - - public func sendVideoMessage(url: URL, _ completion: @escaping (Error?) -> Void){ - weak var weakSelf = self - VideoFormatConvert.convertToMP4(with: url,avQuality: AVAssetExportPresetHighestQuality) { path, image in - if let p = path, let s = weakSelf?.session { - weakSelf?.repo.sendMessage(message: MessageUtils.videoMessage(filePath: p), session: s, completion) - }else { - NELog.errorLog("chat veiw model", desc: "convert mov to mp4 failed") + } + + public func queryRoamMsgHasMoreTime_v2(_ completion: @escaping (Error?, NSInteger, NSInteger, + [MessageModel]?, Int) -> Void) { + weak var weakSelf = self + repo.getIncompleteSessionInfo(session: session) { error, sessionInfos in + if error == nil { + let sessionInfo = sessionInfos?.first + // 记录可信时间戳 + weakSelf?.credibleTimestamp = sessionInfo?.timestamp ?? 0 + if weakSelf?.anchor == nil { + weakSelf?.getMessageHistory(self.newMsg) { error, value, models in + completion(error, value, 0, models, 0) + } + } else { + // 有锚点消息,从两个方向拉去消息 + weakSelf?.newMsg = weakSelf?.anchor + weakSelf?.oldMsg = weakSelf?.anchor + + let group = DispatchGroup() + + var moreEnd = 0 + var newEnd = 0 + var historyDatas = [MessageModel]() + var newDatas = [MessageModel]() + + var err: Error? + + group.enter() + weakSelf?.dropDownRemoteRefresh { error, value, models in + + moreEnd = value + if error != nil { + err = error } - } - } - - - public func queryRoamMsgHasMoreTime(_ completion: @escaping (Error?,NSInteger,[MessageModel]?) -> Void){ -// NIMIncompleteSessionInfo - weak var weakSelf = self - repo.getIncompleteSessionInfo(session: session) { error, sessionInfos in - if error == nil { - let sessionInfo = sessionInfos?.first - //记录可信时间戳 - weakSelf?.credibleTimestamp = sessionInfo?.timestamp ?? 0 - if weakSelf?.anchor == nil { - weakSelf?.getMessageHistory(self.oldMsg, completion) - - }else { - //有锚点消息,从两个方向拉去消息 - weakSelf?.newMsg = weakSelf?.anchor - weakSelf?.oldMsg = weakSelf?.anchor - weakSelf?.dropDownRemoteRefresh(completion) - weakSelf?.pullRemoteRefresh(completion) - } - + if let ms = models { + historyDatas.append(contentsOf: ms) } - } - } - - public func queryRoamMsgHasMoreTime_v2(_ completion: @escaping (Error?,NSInteger,NSInteger,[MessageModel]?, Int) -> Void){ - weak var weakSelf = self - repo.getIncompleteSessionInfo(session: session) { error, sessionInfos in - if error == nil { - let sessionInfo = sessionInfos?.first - //记录可信时间戳 - weakSelf?.credibleTimestamp = sessionInfo?.timestamp ?? 0 - if weakSelf?.anchor == nil { - weakSelf?.getMessageHistory(self.newMsg, { error, value, models in - completion(error, value, 0, models, 0) - }) - }else { - //有锚点消息,从两个方向拉去消息 - weakSelf?.newMsg = weakSelf?.anchor - weakSelf?.oldMsg = weakSelf?.anchor - - let group = DispatchGroup() - - var moreEnd = 0 - var newEnd = 0 - var historyDatas = [MessageModel]() - var newDatas = [MessageModel]() - - var err: Error? - - group.enter() - weakSelf?.dropDownRemoteRefresh({ error, value, models in - - moreEnd = value - if error != nil { - err = error - } - if let ms = models { - historyDatas.append(contentsOf: ms) - } - print("drop down remote refresh : ", historyDatas.count) - group.leave() - }) - - group.enter() - weakSelf?.pullRemoteRefresh({ error, value, models in - newEnd = value - if err != nil { - err = error - } - if let ms = models { - newDatas.append(contentsOf: ms) - } - print("pull remote refresh : ", newDatas.count) - group.leave() - - }) - - group.notify(queue: DispatchQueue.main, execute: { - var finalDatas = [MessageModel]() - finalDatas.append(contentsOf: historyDatas) - if let anchorMessage = weakSelf?.anchor { - let model = self.modelFromMessage(message: anchorMessage) - weakSelf?.messages.insert(model, at: historyDatas.count) - finalDatas.append(model) - } - finalDatas.append(contentsOf: newDatas) - completion(err, moreEnd, newEnd, finalDatas, historyDatas.count) - }) - } + print("drop down remote refresh : ", historyDatas.count) + group.leave() + } + + group.enter() + weakSelf?.pullRemoteRefresh { error, value, models in + newEnd = value + if err != nil { + err = error } + if let ms = models { + newDatas.append(contentsOf: ms) + } + print("pull remote refresh : ", newDatas.count) + group.leave() + } + + group.notify(queue: DispatchQueue.main, execute: { + var finalDatas = [MessageModel]() + finalDatas.append(contentsOf: historyDatas) + if let anchorMessage = weakSelf?.anchor { + let model = self.modelFromMessage(message: anchorMessage) + weakSelf?.messages.insert(model, at: historyDatas.count) + finalDatas.append(model) + } + finalDatas.append(contentsOf: newDatas) + completion(err, moreEnd, newEnd, finalDatas, historyDatas.count) + }) } + } } - - //查询本地历史消息 - public func getMessageHistory(_ message:NIMMessage?, _ completion: @escaping (Error?, NSInteger,[MessageModel]?) -> Void) { - ChatProvider.shared.getMessageHistory(session: self.session, message: message, limit: messagPageNum) { [weak self] error, messages in - if let messageArray = messages, messageArray.count > 0 { - self?.oldMsg = messageArray.first - for msg in messageArray { - self?.addTimeMessage(msg) - if let model = self?.modelFromMessage(message: msg) { - self?.messages.append(model) - } - } - completion(error,messageArray.count, self?.messages) + } + + // 查询本地历史消息 + public func getMessageHistory(_ message: NIMMessage?, + _ completion: @escaping (Error?, NSInteger, [MessageModel]?) + -> Void) { + ChatProvider.shared.getMessageHistory( + session: session, + message: message, + limit: messagPageNum + ) { [weak self] error, messages in + if let messageArray = messages, messageArray.count > 0 { + self?.oldMsg = messageArray.first + for msg in messageArray { + self?.addTimeMessage(msg) + if let model = self?.modelFromMessage(message: msg) { + self?.messages.append(model) + } + } + completion(error, messageArray.count, self?.messages) // mark read - self?.markRead(messages: messageArray, { error in - print("mark read \(error?.localizedDescription)") - }) - - }else { - - completion(error,0,self?.messages) - } + self?.markRead(messages: messageArray) { error in + print("mark read \(error?.localizedDescription)") } + + } else { + completion(error, 0, self?.messages) + } } - - //查询更多本地历史消息 - public func getMoreMessageHistory(_ completion: @escaping (Error?,NSInteger, [MessageModel]?) -> Void) { - - weak var weakSelf = self - - let messageParam = self.oldMsg ?? self.newMsg - - ChatProvider.shared.getMessageHistory(session: self.session, message: messageParam, limit: messagPageNum) { [weak self] error, messages in - if let messageArray = messages, messageArray.count > 0 { - weakSelf?.oldMsg = messageArray.first - - //如果可信就使用本次请求数据,如果不可信就去远端拉去数据,并更新可信时间戳 - let isCredible = weakSelf?.isMessageCredible(message: messageArray.first ?? NIMMessage()) - if let isTrust = isCredible, isTrust{ - for msg in messageArray.reversed() { - self?.addTimeForHistoryMessage(msg) - if let model = self?.modelFromMessage(message: msg) { - self?.messages.insert(model, at: 0) - } - } - completion(error,messageArray.count, self?.messages) - }else { - let option = NIMHistoryMessageSearchOption() - option.startTime = 0 - option.endTime = self?.oldMsg?.timestamp ?? 0 - option.limit = self?.messagPageNum ?? 100 - option.sync = true - weakSelf?.getRemoteHistoryMessage(direction:.old,updateCredible:true,option: option, completion) - } + } - weakSelf?.markRead(messages: messageArray, { error in - print("mark read \(error?.localizedDescription)") - }) - - }else { - if let messageArray = messages,messageArray.isEmpty,weakSelf?.credibleTimestamp ?? 0 > 0 { - //如果远端拉倒了信息 就去更新可信时间戳,拉不到就不更新。 - let option = NIMHistoryMessageSearchOption() - option.startTime = 0 - option.endTime = self?.oldMsg?.timestamp ?? 0 - option.limit = self?.messagPageNum ?? 100 - weakSelf?.getRemoteHistoryMessage(direction:.old,updateCredible:true,option: option, completion) - }else { - completion(error,0,self?.messages) - } + // 查询更多本地历史消息 + public func getMoreMessageHistory(_ completion: @escaping (Error?, NSInteger, [MessageModel]?) + -> Void) { + weak var weakSelf = self - } - } - - } - - //查询远端历史消息 - public func getRemoteHistoryMessage(direction:LoadMessageDirection,updateCredible:Bool, option:NIMHistoryMessageSearchOption, _ completion: @escaping (Error?,NSInteger, [MessageModel]?) -> Void){ - weak var weakSelf = self - repo.getHistoryMessage(session: self.session, option: option) { error, messages in - if error == nil { - if let messageArray = messages, messageArray.count > 0 { - if direction == .old { - weakSelf?.oldMsg = messageArray.last - }else { - weakSelf?.newMsg = messageArray.first - } - for msg in messageArray { - weakSelf?.addTimeForHistoryMessage(msg) - if let model = weakSelf?.modelFromMessage(message: msg) { - weakSelf?.messages.insert(model, at: 0) - } - } - - if let updateMessage = messageArray.first,updateCredible { - //更新可信时间戳 - weakSelf?.credibleTimestamp = updateMessage.timestamp - weakSelf?.repo.updateIncompleteSessions(messages: [updateMessage], { error, recentSessions in - if error != nil { - NELog.errorLog(weakSelf?.className ?? "ChatViewModel", desc: "❌updateIncompleteSessions failed,error = \(error!)") - } - }) - } - completion(error,messageArray.count, weakSelf?.messages) - - }else { - completion(error,0, weakSelf?.messages) + let messageParam = oldMsg ?? newMsg - } + ChatProvider.shared.getMessageHistory( + session: session, + message: messageParam, + limit: messagPageNum + ) { [weak self] error, messages in + if let messageArray = messages, messageArray.count > 0 { + weakSelf?.oldMsg = messageArray.first - }else { - completion(error, 0,nil) + // 如果可信就使用本次请求数据,如果不可信就去远端拉去数据,并更新可信时间戳 + let isCredible = weakSelf? + .isMessageCredible(message: messageArray.first ?? NIMMessage()) + if let isTrust = isCredible, isTrust { + for msg in messageArray.reversed() { + self?.addTimeForHistoryMessage(msg) + if let model = self?.modelFromMessage(message: msg) { + self?.messages.insert(model, at: 0) } + } + completion(error, messageArray.count, self?.messages) + } else { + let option = NIMHistoryMessageSearchOption() + option.startTime = 0 + option.endTime = self?.oldMsg?.timestamp ?? 0 + option.limit = self?.messagPageNum ?? 100 + option.sync = true + weakSelf?.getRemoteHistoryMessage( + direction: .old, + updateCredible: true, + option: option, + completion + ) } - } - - //下拉获取历史消息 - public func dropDownRemoteRefresh( _ completion: @escaping (Error?,NSInteger,[MessageModel]?) -> Void){ - - //completion(nil, true, nil) - let option = NIMHistoryMessageSearchOption() - option.startTime = 0 - option.endTime = oldMsg?.timestamp ?? 0 - option.limit = messagPageNum - option.sync = true - let isCredible = isMessageCredible(message: oldMsg ?? NIMMessage()) - if isCredible {//继续拉去本地消息 - getMoreMessageHistory(completion) - }else { - //不可信拉去远端消息 - getRemoteHistoryMessage(direction:.old,updateCredible:false, option: option, completion) + + weakSelf?.markRead(messages: messageArray) { error in + print("mark read \(error?.localizedDescription)") + } + + } else { + if let messageArray = messages, messageArray.isEmpty, + weakSelf?.credibleTimestamp ?? 0 > 0 { + // 如果远端拉倒了信息 就去更新可信时间戳,拉不到就不更新。 + let option = NIMHistoryMessageSearchOption() + option.startTime = 0 + option.endTime = self?.oldMsg?.timestamp ?? 0 + option.limit = self?.messagPageNum ?? 100 + weakSelf?.getRemoteHistoryMessage( + direction: .old, + updateCredible: true, + option: option, + completion + ) + } else { + completion(error, 0, self?.messages) } - + } } - - //上拉获取最新消息 - public func pullRemoteRefresh(_ completion: @escaping (Error?,NSInteger, [MessageModel]?) -> Void){ - let option = NIMHistoryMessageSearchOption() - option.startTime = newMsg?.timestamp ?? 0 - option.endTime = 0 - option.limit = messagPageNum - let isCredible = isMessageCredible(message: newMsg ?? NIMMessage()) - if isCredible { - if anchor != nil { - //搜索历史记录进入 - searchMessageHistory(direction:.new,startTime: newMsg?.timestamp ?? 0, endTime: 0, completion) + } + + // 查询远端历史消息 + public func getRemoteHistoryMessage(direction: LoadMessageDirection, updateCredible: Bool, + option: NIMHistoryMessageSearchOption, + _ completion: @escaping (Error?, NSInteger, + [MessageModel]?) -> Void) { + weak var weakSelf = self + repo.getHistoryMessage(session: session, option: option) { error, messages in + if error == nil { + if let messageArray = messages, messageArray.count > 0 { + if direction == .old { + weakSelf?.oldMsg = messageArray.last + } else { + weakSelf?.newMsg = messageArray.first + } + for msg in messageArray { + weakSelf?.addTimeForHistoryMessage(msg) + if let model = weakSelf?.modelFromMessage(message: msg) { + weakSelf?.messages.insert(model, at: 0) } - - }else { - getRemoteHistoryMessage(direction:.new,updateCredible:false, option: option, completion) - + } + + if let updateMessage = messageArray.first, updateCredible { + // 更新可信时间戳 + weakSelf?.credibleTimestamp = updateMessage.timestamp + weakSelf?.repo + .updateIncompleteSessions(messages: [updateMessage]) { error, recentSessions in + if error != nil { + NELog.errorLog( + weakSelf?.className ?? "ChatViewModel", + desc: "❌updateIncompleteSessions failed,error = \(error!)" + ) + } + } + } + completion(error, messageArray.count, weakSelf?.messages) + + } else { + completion(error, 0, weakSelf?.messages) } + + } else { + completion(error, 0, nil) + } } - - //搜索历史记录查询的本地消息 - public func searchMessageHistory(direction:LoadMessageDirection,startTime:TimeInterval,endTime:TimeInterval, _ completion: @escaping (Error?, NSInteger,[MessageModel]?) -> Void) { - - let option = NIMMessageSearchOption() - option.startTime = startTime - option.endTime = endTime - option.order = .asc - option.limit = messagPageNum - weak var weakSelf = self - - repo.searchMessages(session, option: option) { error, messages in - if error == nil { - if let messageArray = messages, messageArray.count > 0 { - if direction == .old { - weakSelf?.oldMsg = messageArray.first - }else { - weakSelf?.newMsg = messageArray.last - } - for msg in messageArray { - weakSelf?.addTimeMessage(msg) - if let model = weakSelf?.modelFromMessage(message: msg) { - weakSelf?.messages.append(model) - } - } - completion(error,messageArray.count, weakSelf?.messages) - }else { - completion(error,0, weakSelf?.messages) + } - } - }else { - completion(error,0,nil) + // 下拉获取历史消息 + public func dropDownRemoteRefresh(_ completion: @escaping (Error?, NSInteger, [MessageModel]?) + -> Void) { + // completion(nil, true, nil) + let option = NIMHistoryMessageSearchOption() + option.startTime = 0 + option.endTime = oldMsg?.timestamp ?? 0 + option.limit = messagPageNum + option.sync = true + let isCredible = isMessageCredible(message: oldMsg ?? NIMMessage()) + if isCredible { // 继续拉去本地消息 + getMoreMessageHistory(completion) + } else { + // 不可信拉去远端消息 + getRemoteHistoryMessage( + direction: .old, + updateCredible: false, + option: option, + completion + ) + } + } + + // 上拉获取最新消息 + public func pullRemoteRefresh(_ completion: @escaping (Error?, NSInteger, [MessageModel]?) + -> Void) { + let option = NIMHistoryMessageSearchOption() + option.startTime = newMsg?.timestamp ?? 0 + option.endTime = 0 + option.limit = messagPageNum + let isCredible = isMessageCredible(message: newMsg ?? NIMMessage()) + if isCredible { + if anchor != nil { + // 搜索历史记录进入 + searchMessageHistory( + direction: .new, + startTime: newMsg?.timestamp ?? 0, + endTime: 0, + completion + ) + } + + } else { + getRemoteHistoryMessage( + direction: .new, + updateCredible: false, + option: option, + completion + ) + } + } + + // 搜索历史记录查询的本地消息 + public func searchMessageHistory(direction: LoadMessageDirection, startTime: TimeInterval, + endTime: TimeInterval, + _ completion: @escaping (Error?, NSInteger, [MessageModel]?) + -> Void) { + let option = NIMMessageSearchOption() + option.startTime = startTime + option.endTime = endTime + option.order = .asc + option.limit = messagPageNum + weak var weakSelf = self + + repo.searchMessages(session, option: option) { error, messages in + if error == nil { + if let messageArray = messages, messageArray.count > 0 { + if direction == .old { + weakSelf?.oldMsg = messageArray.first + } else { + weakSelf?.newMsg = messageArray.last + } + for msg in messageArray { + weakSelf?.addTimeMessage(msg) + if let model = weakSelf?.modelFromMessage(message: msg) { + weakSelf?.messages.append(model) } - + } + completion(error, messageArray.count, weakSelf?.messages) + } else { + completion(error, 0, weakSelf?.messages) } + } else { + completion(error, 0, nil) + } } + } + // 判断消息是否可信 + public func isMessageCredible(message: NIMMessage) -> Bool { + credibleTimestamp <= 0 || message.timestamp >= credibleTimestamp + } - - - //判断消息是否可信 - public func isMessageCredible(message:NIMMessage)->Bool { - return credibleTimestamp <= 0 || message.timestamp >= credibleTimestamp - } - - - - public func markRead(messages: [NIMMessage], _ completion: @escaping (Error?) -> Void) { + public func markRead(messages: [NIMMessage], _ completion: @escaping (Error?) -> Void) { // if self.getMessageRead() { // if self.session.sessionType == .P2P { // self.markReadInP2P(messages: messages, completion) @@ -405,662 +453,695 @@ public class ChatViewModel: NSObject, ChatRepoMessageDelegate, NIMChatManagerDel // self.markReadInTeam(messages: messages, completion) // } // } - if self.session.sessionType == .P2P { - self.markReadInP2P(messages: messages, completion) - }else if self.session.sessionType == .team { - self.markReadInTeam(messages: messages, completion) - } -// mark session read - weak var weakself = self - repo.markReadInSession(session) { error in - if error != nil { - NELog.errorLog(weakself?.className() ?? "ChatViewModel", desc: "❌markReadInSession failed,error = \(error!)") - } - } + if session.sessionType == .P2P { + markReadInP2P(messages: messages, completion) + } else if session.sessionType == .team { + markReadInTeam(messages: messages, completion) } +// mark session read + weak var weakself = self + repo.markReadInSession(session) { error in + if error != nil { + NELog.errorLog( + weakself?.className() ?? "ChatViewModel", + desc: "❌markReadInSession failed,error = \(error!)" + ) + } + } + } - private func markReadInP2P(messages: [NIMMessage], _ completion: @escaping (Error?) -> Void) { - for message in messages.reversed() { - if message.isReceivedMsg { - let param = NIMMessageReceipt(message: message) - repo.markP2pMessageRead(param: param, completion) - break - } - } - completion(nil) - } - - private func markReadInTeam(messages: [NIMMessage], _ completion: @escaping (Error?) -> Void) { - var receipts = [NIMMessageReceipt]() - for message in messages { - let receiptEnable = message.setting?.teamReceiptEnabled ?? false - if receiptEnable, !message.isTeamReceiptSended { - let receipt = NIMMessageReceipt.init(message: message) - receipts.append(receipt) - } - } - repo.markTeamMessageRead(param: receipts) { error, failedReceipts in - print("!! chatViewModel markReadInTeam error:\(error)") - completion(error) - } - } - - public func deleteMessage(message: NIMMessage) { - repo.deleteMessage(message: message) - deleteMessageUpdateUI(message) - } - - public func replyMessage(_ message: NIMMessage, _ target: NIMMessage, _ completion: @escaping (Error?)->()) { - repo.replyMessage(message, target) { error in - completion(error) - } - } - - public func revokeMessage(message: NIMMessage, _ completion: @escaping (Error?) -> ()) { - repo.revokeMessage(message: message) { error in - if error == nil { - self.revokeMessageUpdateUI(message) - } - completion(error) - } - } - - public func resendMessage(message: NIMMessage) -> NSError? { - return repo.resendMessage(message: message) - } - - public func getUserInfo(userId: String) -> User? { - return repo.getUserInfo(userId: userId) - } - - public func getTeamMember(userId: String, teamId: String) -> NIMTeamMember? { - return repo.getTeamMemberList(userId: userId, teamId: teamId) - } - - public func onReceive(_ notification: NIMCustomSystemNotification) { - print("on receive custom noti : ", notification) - if session.sessionType != .P2P { - return - } - if session.sessionId != notification.sender { - return - } - if let content = notification.content, let dic = getDictionaryFromJSONString(content) as? [String : Any], let typing = dic["typing"] as? Int { - if typing == 1 { - delegate?.remoteUserEditing() - }else { - delegate?.remoteUserEndEditing() - } - } - } - - // MARK: NIMChatManagerDelegate - //收到消息 - public func onRecvMessages(_ messages: [NIMMessage]) { - print("\(#function) 1messages:\(messages.count)") - - for msg in messages { - if msg.session?.sessionId == self.session.sessionId { - - //自定义消息处理 - if msg.messageType == .custom { - - }else { - self.newMsg = msg - self.addTimeMessage(msg) - self.messages.append(self.modelFromMessage(message: msg)) - } - - } - } - self.delegate?.onRecvMessages(messages) + private func markReadInP2P(messages: [NIMMessage], _ completion: @escaping (Error?) -> Void) { + for message in messages.reversed() { + if message.isReceivedMsg { + let param = NIMMessageReceipt(message: message) + repo.markP2pMessageRead(param: param, completion) + break + } + } + completion(nil) + } + + private func markReadInTeam(messages: [NIMMessage], _ completion: @escaping (Error?) -> Void) { + var receipts = [NIMMessageReceipt]() + for message in messages { + let receiptEnable = message.setting?.teamReceiptEnabled ?? false + if receiptEnable, !message.isTeamReceiptSended { + let receipt = NIMMessageReceipt(message: message) + receipts.append(receipt) + } + } + repo.markTeamMessageRead(param: receipts) { error, failedReceipts in + print("!! chatViewModel markReadInTeam error:\(error)") + completion(error) + } + } + public func deleteMessage(message: NIMMessage) { + repo.deleteMessage(message: message) + deleteMessageUpdateUI(message) + } + + public func replyMessage(_ message: NIMMessage, _ target: NIMMessage, + _ completion: @escaping (Error?) -> Void) { + repo.replyMessage(message, target) { error in + completion(error) } - + } - - public func willSend(_ message: NIMMessage) { - print("\(#function)") - if message.session?.sessionId != self.session.sessionId { - return - } - //自定义消息发送之前的处理 - if message.messageType == .custom { - - }else { - if self.newMsg == nil { - self.newMsg = message - } - - var isResend = false - for (i, msg) in self.messages.enumerated() { - if message.messageId == msg.message?.messageId { - self.messages[i].message = message - isResend = true - break - } - } - - if !isResend { - self.addTimeMessage(message) - self.messages.append(self.modelFromMessage(message: message)) - } - - self.delegate?.willSend(message) + public func revokeMessage(message: NIMMessage, _ completion: @escaping (Error?) -> Void) { + repo.revokeMessage(message: message) { error in + if error == nil { + self.revokeMessageUpdateUI(message) + } + completion(error) + } + } + + public func resendMessage(message: NIMMessage) -> NSError? { + repo.resendMessage(message: message) + } + + public func getUserInfo(userId: String) -> User? { + repo.getUserInfo(userId: userId) + } + + public func getTeamMember(userId: String, teamId: String) -> NIMTeamMember? { + repo.getTeamMemberList(userId: userId, teamId: teamId) + } + + public func onReceive(_ notification: NIMCustomSystemNotification) { + print("on receive custom noti : ", notification) + if session.sessionType != .P2P { + return + } + if session.sessionId != notification.sender { + return + } + if let content = notification.content, + let dic = getDictionaryFromJSONString(content) as? [String: Any], + let typing = dic["typing"] as? Int { + if typing == 1 { + delegate?.remoteUserEditing() + } else { + delegate?.remoteUserEndEditing() + } + } + } + + // MARK: NIMChatManagerDelegate + + // 收到消息 + public func onRecvMessages(_ messages: [NIMMessage]) { + print("\(#function) 1messages:\(messages.count)") + + for msg in messages { + if msg.session?.sessionId == session.sessionId { + // 自定义消息处理 + if msg.messageType == .custom { + } else { + newMsg = msg + addTimeMessage(msg) + self.messages.append(modelFromMessage(message: msg)) } + } } - - public func send(_ message: NIMMessage, progress: Float) { - print("\(#function) progress\(progress)") - self.delegate?.send(message, progress: progress) - } - - public func send(_ message: NIMMessage, didCompleteWithError error: Error?) { - print("\(#function) message deliveryState:\(message.deliveryState) error:\(error)") - for (i, msg) in self.messages.enumerated() { - if message.messageId == msg.message?.messageId { - self.messages[i].message = message - break - } + delegate?.onRecvMessages(messages) + } + + public func willSend(_ message: NIMMessage) { + print("\(#function)") + if message.session?.sessionId != session.sessionId { + return + } + // 自定义消息发送之前的处理 + if message.messageType == .custom { + } else { + if newMsg == nil { + newMsg = message + } + + var isResend = false + for (i, msg) in messages.enumerated() { + if message.messageId == msg.message?.messageId { + messages[i].message = message + isResend = true + break } - self.delegate?.send(message, didCompleteWithError: error) + } + + if !isResend { + addTimeMessage(message) + messages.append(modelFromMessage(message: message)) + } + + delegate?.willSend(message) } - + } + + public func send(_ message: NIMMessage, progress: Float) { + print("\(#function) progress\(progress)") + delegate?.send(message, progress: progress) + } + + public func send(_ message: NIMMessage, didCompleteWithError error: Error?) { + print("\(#function) message deliveryState:\(message.deliveryState) error:\(error)") + for (i, msg) in messages.enumerated() { + if message.messageId == msg.message?.messageId { + messages[i].message = message + break + } + } + delegate?.send(message, didCompleteWithError: error) + } + // MARK: ChatExtendProviderDelegate - public func onNotifyAddMessagePin(pinItem: NIMMessagePinItem) { - var index = -1 - for (i, model) in self.messages.enumerated() { - if pinItem.messageServerID == model.message?.serverID { - self.messages[i].isPined = true - let pinID = pinItem.accountID ?? NIMSDK.shared().loginManager.currentAccount() - self.messages[i].pinAccount = pinID - self.messages[i].pinShowName = self.getShowName(userId: pinID, teamId: session.sessionId) - index = i - break - } - } - if index >= 0, let msg = self.messages[index].message { - self.delegate?.onAddMessagePin(msg, atIndexs: [IndexPath(row: index, section: 0)]) - } - } - - public func onNotifyRemoveMessagePin(pinItem: NIMMessagePinItem) { - var index = -1 - for (i, model) in self.messages.enumerated() { - if pinItem.messageServerID == model.message?.serverID { - self.messages[i].isPined = false - self.messages[i].pinAccount = nil - self.messages[i].pinShowName = nil - index = i - break - } + + public func onNotifyAddMessagePin(pinItem: NIMMessagePinItem) { + var index = -1 + for (i, model) in messages.enumerated() { + if pinItem.messageServerID == model.message?.serverID { + messages[i].isPined = true + let pinID = pinItem.accountID ?? NIMSDK.shared().loginManager.currentAccount() + messages[i].pinAccount = pinID + messages[i].pinShowName = getShowName(userId: pinID, teamId: session.sessionId) + index = i + break + } + } + if index >= 0, let msg = messages[index].message { + delegate?.onAddMessagePin(msg, atIndexs: [IndexPath(row: index, section: 0)]) + } + } + + public func onNotifyRemoveMessagePin(pinItem: NIMMessagePinItem) { + var index = -1 + for (i, model) in messages.enumerated() { + if pinItem.messageServerID == model.message?.serverID { + messages[i].isPined = false + messages[i].pinAccount = nil + messages[i].pinShowName = nil + index = i + break + } + } + if index >= 0, let msg = messages[index].message { + delegate?.onRemoveMessagePin(msg, atIndexs: [IndexPath(row: index, section: 0)]) + } + } + + public func onNotifySyncStickTopSessions(_ response: NIMSyncStickTopSessionResponse) {} + + public func onNotifyAddStickTopSession(_ newInfo: NIMStickTopSessionInfo) {} + + public func onNotifyRemoveStickTopSession(_ removedInfo: NIMStickTopSessionInfo) {} + +// MARK: collection + + func addColletion(_ message: NIMMessage, + completion: @escaping (NSError?, NIMCollectInfo?) -> Void) { + let param = NIMAddCollectParams() + var string: String? + if message.messageType == .text { + string = message.text + param.type = 1024 + } else { + switch message.messageType { + case .audio: + if let obj = message.messageObject as? NIMAudioObject { + string = obj.url } - if index >= 0, let msg = self.messages[index].message { - self.delegate?.onRemoveMessagePin(msg, atIndexs: [IndexPath(row: index, section: 0)]) + param.type = message.messageType.rawValue + case .image: + if let obj = message.messageObject as? NIMImageObject { + string = obj.url } - } - - public func onNotifySyncStickTopSessions(_ response: NIMSyncStickTopSessionResponse) { - - } - - public func onNotifyAddStickTopSession(_ newInfo: NIMStickTopSessionInfo) { - - } - - public func onNotifyRemoveStickTopSession(_ removedInfo: NIMStickTopSessionInfo) { - - } - -// MARK: collection - func addColletion(_ message: NIMMessage, completion: @escaping (NSError?, NIMCollectInfo?) -> ()) { - let param = NIMAddCollectParams() - var string: String? - if message.messageType == .text { - string = message.text - param.type = 1024 - }else { - switch message.messageType { - case .audio: - if let obj = message.messageObject as? NIMAudioObject { - string = obj.url - } - param.type = message.messageType.rawValue - case .image: - if let obj = message.messageObject as? NIMImageObject { - string = obj.url - } - param.type = message.messageType.rawValue - case .video: - if let obj = message.messageObject as? NIMVideoObject { - string = obj.url - } - param.type = message.messageType.rawValue - default: - param.type = 0 - } - param.data = string ?? "" + param.type = message.messageType.rawValue + case .video: + if let obj = message.messageObject as? NIMVideoObject { + string = obj.url } - param.uniqueId = message.serverID - repo.collectMessage(param, completion) - } - + param.type = message.messageType.rawValue + default: + param.type = 0 + } + param.data = string ?? "" + } + param.uniqueId = message.serverID + repo.collectMessage(param, completion) + } + // MARK: revoke - public func onRecvRevokeMessageNotification(_ notification: NIMRevokeMessageNotification) { - guard let msg = notification.message else { - return - } - self.revokeMessageUpdateUI(msg) + public func onRecvRevokeMessageNotification(_ notification: NIMRevokeMessageNotification) { + guard let msg = notification.message else { + return } - - public func onRecvMessageReceipts(_ receipts: [NIMMessageReceipt]) { - print("chatViewModel: receipts:\(receipts.count) messageId:\(receipts.first?.messageId) messageId:\(receipts.first?.timestamp)") - self.delegate?.didReadedMessageIndexs() + revokeMessageUpdateUI(msg) + } + + public func onRecvMessageReceipts(_ receipts: [NIMMessageReceipt]) { + print( + "chatViewModel: receipts:\(receipts.count) messageId:\(receipts.first?.messageId) messageId:\(receipts.first?.timestamp)" + ) + delegate?.didReadedMessageIndexs() + } + + public func avalibleOperationsForMessage(_ model: MessageContentModel?) -> [OperationItem]? { + var pinItem = OperationItem.pinItem() + var items = [OperationItem]() + switch model?.message?.messageType { + case .text: + if let isPin = model?.isPined, isPin { + pinItem = OperationItem.removePinItem() + } + items = [ + OperationItem.copyItem(), + OperationItem.replayItem(), + OperationItem.forwardItem(), + pinItem, +// OperationItem.selectItem(), +// OperationItem.collectionItem(), + OperationItem.deleteItem(), + ] + case .image, .video: + if let isPin = model?.isPined, isPin { + pinItem = OperationItem.removePinItem() + } + items = [ + OperationItem.replayItem(), + OperationItem.forwardItem(), + pinItem, +// OperationItem.selectItem(), +// OperationItem.collectionItem(), + OperationItem.deleteItem(), + ] + case .audio: + if let isPin = model?.isPined, isPin { + pinItem = OperationItem.removePinItem() + } + items = [ + OperationItem.replayItem(), + pinItem, +// OperationItem.selectItem(), +// OperationItem.collectionItem(), + OperationItem.deleteItem(), + ] + + default: + if let isPin = model?.isPined, isPin { + pinItem = OperationItem.removePinItem() + } + items = [ + OperationItem.replayItem(), + pinItem, +// OperationItem.selectItem(), +// OperationItem.collectionItem(), + OperationItem.deleteItem(), + ] } - - public func avalibleOperationsForMessage(_ model: MessageContentModel?) -> [OperationItem]? { - var pinItem = OperationItem.pinItem() - var items = [OperationItem]() - switch model?.message?.messageType { - case .text: - if let isPin = model?.isPined, isPin { - pinItem = OperationItem.removePinItem() - } - items = [OperationItem.copyItem(),OperationItem.replayItem(),OperationItem.forwardItem(),pinItem,OperationItem.selectItem(),OperationItem.collectionItem(),OperationItem.deleteItem()] - - case .image, .video: - if let isPin = model?.isPined, isPin { - pinItem = OperationItem.removePinItem() - } - items = [OperationItem.replayItem(),OperationItem.forwardItem(),pinItem,OperationItem.selectItem(),OperationItem.collectionItem(),OperationItem.deleteItem()] - case .audio: - if let isPin = model?.isPined, isPin { - pinItem = OperationItem.removePinItem() - } - items = [OperationItem.replayItem(),pinItem,OperationItem.selectItem(),OperationItem.collectionItem(),OperationItem.deleteItem()] - - default: - if let isPin = model?.isPined, isPin { - pinItem = OperationItem.removePinItem() - } - items = [OperationItem.replayItem(),pinItem,OperationItem.selectItem(),OperationItem.collectionItem(),OperationItem.deleteItem()] - } - - if model?.message?.from == NIMSDK.shared().loginManager.currentAccount() { - items.append(OperationItem.recallItem()) - } - return items + + if model?.message?.from == NIMSDK.shared().loginManager.currentAccount() { + items.append(OperationItem.recallItem()) } - - private func indexPathsForTeamMarkRead(_ receipts:[NIMMessageReceipt]) -> [IndexPath] { - var indexs = [IndexPath]() + return items + } + + private func indexPathsForTeamMarkRead(_ receipts: [NIMMessageReceipt]) -> [IndexPath] { + var indexs = [IndexPath]() // find messages that need to update UI - for receipt in receipts { - for (i, model) in self.messages.enumerated() { - if model.message?.messageId == receipt.messageId { - indexs.append(IndexPath(row: i, section: 0)) - } - } + for receipt in receipts { + for (i, model) in messages.enumerated() { + if model.message?.messageId == receipt.messageId { + indexs.append(IndexPath(row: i, section: 0)) } - print("mark read indexs:\(indexs)"); - return indexs + } } - - private func indexPathsForP2PMarkRead(_ receipts:[NIMMessageReceipt]) -> [IndexPath] { - var updateIndexs = [IndexPath]() + print("mark read indexs:\(indexs)") + return indexs + } + + private func indexPathsForP2PMarkRead(_ receipts: [NIMMessageReceipt]) -> [IndexPath] { + var updateIndexs = [IndexPath]() // find messages that need to update UI - var i = self.messages.count - 1 - for model in self.messages.reversed() { - if let msg = model.message, msg.isRemoteRead { - updateIndexs.append(IndexPath(row: i, section: 0)) - break - }else { - updateIndexs.append(IndexPath(row: i, section: 0)) - i = i - 1 - } - } - return updateIndexs - } - - // history message insert message at first of messages, send message add last of messages - private func addTimeMessage(_ message: NIMMessage) { - let lastTs = self.messages.last?.message?.timestamp ?? 0.0 - let curTs = message.timestamp - let dur = curTs - lastTs - if (dur / 60) > 5 { - self.messages.append(self.timeModel(message)) - } - } - - private func addTimeForHistoryMessage(_ message: NIMMessage) { - let firstTs = self.messages.first?.message?.timestamp ?? 0.0 - let curTs = message.timestamp - let dur = firstTs - curTs - if (dur / 60) > 5 { - let model = MessageTipsModel(message: message) - model.type = .time - model.text = String.stringFromDate(date:Date(timeIntervalSince1970: firstTs)) - self.messages.insert(model, at: 0) - } - } - - private func timeModel(_ message: NIMMessage) -> MessageModel { - let curTs = message.timestamp - let model = MessageTipsModel(message: message) - model.type = .time - model.text = String.stringFromDate(date:Date(timeIntervalSince1970: curTs)) - return model - } - - private func tipsModel(_ message: NIMMessage) -> MessageModel { - let model = MessageTipsModel(message: message) - return model - } - - private func modelFromMessage(message: NIMMessage) -> MessageModel { - var model: MessageModel - switch message.messageType { - - case .video: - model = MessageVideoModel(message: message) - case .text: - model = MessageTextModel(message: message) - case .image: - model = MessageImageModel(message: message) - case .audio: - model = MessageAudioModel(message: message) + var i = messages.count - 1 + for model in messages.reversed() { + if let msg = model.message, msg.isRemoteRead { + updateIndexs.append(IndexPath(row: i, section: 0)) + break + } else { + updateIndexs.append(IndexPath(row: i, section: 0)) + i = i - 1 + } + } + return updateIndexs + } + + // history message insert message at first of messages, send message add last of messages + private func addTimeMessage(_ message: NIMMessage) { + let lastTs = messages.last?.message?.timestamp ?? 0.0 + let curTs = message.timestamp + let dur = curTs - lastTs + if (dur / 60) > 5 { + messages.append(timeModel(message)) + } + } + + private func addTimeForHistoryMessage(_ message: NIMMessage) { + let firstTs = messages.first?.message?.timestamp ?? 0.0 + let curTs = message.timestamp + let dur = firstTs - curTs + if (dur / 60) > 5 { + let model = MessageTipsModel(message: message) + model.type = .time + model.text = String.stringFromDate(date: Date(timeIntervalSince1970: firstTs)) + messages.insert(model, at: 0) + } + } + + private func timeModel(_ message: NIMMessage) -> MessageModel { + let curTs = message.timestamp + let model = MessageTipsModel(message: message) + model.type = .time + model.text = String.stringFromDate(date: Date(timeIntervalSince1970: curTs)) + return model + } + + private func tipsModel(_ message: NIMMessage) -> MessageModel { + let model = MessageTipsModel(message: message) + return model + } + + private func modelFromMessage(message: NIMMessage) -> MessageModel { + var model: MessageModel + switch message.messageType { + case .video: + model = MessageVideoModel(message: message) + case .text: + model = MessageTextModel(message: message) + case .image: + model = MessageImageModel(message: message) + case .audio: + model = MessageAudioModel(message: message) // case .video: // <#code#> // case .location: // <#code#> - case .notification: - model = MessageTipsModel(message: message) + case .notification: + model = MessageTipsModel(message: message) // case .file: // <#code#> - case .tip: - model = MessageTipsModel(message: message) + case .tip: + model = MessageTipsModel(message: message) // case .robot: // <#code#> // case .rtcCallRecord: // <#code#> // case .custom: // <#code#> - default: - model = MessageContentModel(message: message) + default: + model = MessageContentModel(message: message) + } + if let uid = message.from { + let user = getUserInfo(userId: uid) + var fullName = uid + if let nickName = user?.userInfo?.nickName { + fullName = nickName + } + model.avatar = user?.userInfo?.thumbAvatarUrl + if session.sessionType == .team { + // team + let teamMember = getTeamMember(userId: uid, teamId: session.sessionId) + if let teamNickname = teamMember?.nickname { + fullName = teamNickname } - if let uid = message.from { - let user = self.getUserInfo(userId: uid) - var fullName = uid - if let nickName = user?.userInfo?.nickName { - fullName = nickName - } - model.avatar = user?.userInfo?.thumbAvatarUrl - if session.sessionType == .team { - // team - let teamMember = self.getTeamMember(userId: uid, teamId: session.sessionId) - if let teamNickname = teamMember?.nickname { - fullName = teamNickname - } - } - if let alias = user?.alias { - fullName = alias - } - model.fullName = fullName - model.shortName = fullName.count > 2 ? String(fullName[fullName.index(fullName.endIndex, offsetBy: -2)...]) : fullName - } - model.replyedModel = getReplyMessage(message: message) - if let pin = repo.searchMessagePinHistory(message) { - model.isPined = true - model.pinAccount = pin.accountID - let pinID = pin.accountID ?? NIMSDK.shared().loginManager.currentAccount() - model.pinShowName = self.getShowName(userId: pinID, teamId: session.sessionId) - }else { - model.isPined = false - } - return model + } + if let alias = user?.alias { + fullName = alias + } + model.fullName = fullName + model.shortName = fullName + .count > 2 ? String(fullName[fullName.index(fullName.endIndex, offsetBy: -2)...]) : + fullName + } + model.replyedModel = getReplyMessage(message: message) + if let pin = repo.searchMessagePinHistory(message) { + model.isPined = true + model.pinAccount = pin.accountID + let pinID = pin.accountID ?? NIMSDK.shared().loginManager.currentAccount() + model.pinShowName = getShowName(userId: pinID, teamId: session.sessionId) + } else { + model.isPined = false + } + return model + } + + private func getReplyMessage(message: NIMMessage) -> MessageModel? { + guard let id = message.repliedMessageId else { + return nil } - - private func getReplyMessage(message: NIMMessage) -> MessageModel? { - guard let id = message.repliedMessageId else { - return nil - } - if let message = ConversationProvider.shared.messagesInSession(session, messageIds: [id])?.first { - return modelFromMessage(message: message) - } - return nil + if let message = ConversationProvider.shared.messagesInSession(session, messageIds: [id])? + .first { + return modelFromMessage(message: message) } - - - private func getUserInfo(_ userId: String,_ completion: @escaping (User?, NSError?)->()) { - if let user = userInfo[userId] { - completion(user, nil) - } - if let user = repo.getUserInfo(userId: userId) { - userInfo[userId] = user - completion(user, nil) - } - - UserInfoProvider.shared.fetchUserInfo([userId]) {[weak self] error, users in - if let user = users?.first { - self?.userInfo[userId] = user - completion(user, nil) - }else { - completion(nil, error) - } - } + return nil + } + + private func getUserInfo(_ userId: String, _ completion: @escaping (User?, NSError?) -> Void) { + if let user = userInfo[userId] { + completion(user, nil) + } + if let user = repo.getUserInfo(userId: userId) { + userInfo[userId] = user + completion(user, nil) } - + + UserInfoProvider.shared.fetchUserInfo([userId]) { [weak self] error, users in + if let user = users?.first { + self?.userInfo[userId] = user + completion(user, nil) + } else { + completion(nil, error) + } + } + } + // 获取展示的用户名字,p2p: 备注》昵称>ID team: 备注〉群昵称》 昵称〉 ID - private func getShowName(userId: String, teamId: String?) -> String { - let user = self.getUserInfo(userId: userId) - var fullName = userId - if let nickName = user?.userInfo?.nickName { - fullName = nickName - } -// model.avatar = user?.userInfo?.thumbAvatarUrl - if let tID = teamId, session.sessionType == .team { - // team - let teamMember = self.getTeamMember(userId: userId, teamId:tID) - if let teamNickname = teamMember?.nickname { - fullName = teamNickname - } - } - if let alias = user?.alias { - fullName = alias - } - return fullName + private func getShowName(userId: String, teamId: String?) -> String { + let user = getUserInfo(userId: userId) + var fullName = userId + if let nickName = user?.userInfo?.nickName { + fullName = nickName } - +// model.avatar = user?.userInfo?.thumbAvatarUrl + if let tID = teamId, session.sessionType == .team { + // team + let teamMember = getTeamMember(userId: userId, teamId: tID) + if let teamNickname = teamMember?.nickname { + fullName = teamNickname + } + } + if let alias = user?.alias { + fullName = alias + } + return fullName + } + // 全名后几位 - private func getShortName(name: String, length: Int) -> String { - return name.count > length ? String(name[name.index(name.endIndex, offsetBy: -length)...]) : name - } - - func deleteMessageUpdateUI(_ message: NIMMessage) { - var index = -1 - for (i, model) in self.messages.enumerated() { - if model.message?.serverID == message.serverID { - index = i - break - } - } - var indexs = [IndexPath]() - if index >= 0 { + private func getShortName(name: String, length: Int) -> String { + name.count > length ? String(name[name.index(name.endIndex, offsetBy: -length)...]) : name + } + + func deleteMessageUpdateUI(_ message: NIMMessage) { + var index = -1 + for (i, model) in messages.enumerated() { + if model.message?.serverID == message.serverID { + index = i + break + } + } + var indexs = [IndexPath]() + if index >= 0 { // remove time tip - let last = index - 1 - if last >= 0,let timeModel = self.messages[last] as? MessageTipsModel, timeModel.type == .time { - self.messages.removeSubrange(last...index) - indexs.append(IndexPath(row: last, section: 0)) - indexs.append(IndexPath(row: index, section: 0)) - }else { - self.messages.remove(at: index) - indexs.append(IndexPath(row: index, section: 0)) - } - - } - self.delegate?.onDeleteMessage(message, atIndexs: indexs) - } - - func revokeMessageUpdateUI(_ message: NIMMessage) { - var index = -1 - for (i, model) in self.messages.enumerated() { - if model.message?.serverID == message.serverID { - index = i - break - } - } - var indexs = [IndexPath]() - if index >= 0 { - self.messages[index].isRevoked = true - self.messages[index].replyedModel = nil - indexs.append(IndexPath(row: index, section: 0)) - } - self.delegate?.onRevokeMessage(message, atIndexs: indexs) - } - - public func fetchMessageAttachment(_ message: NIMMessage, didCompleteWithError error: Error?) { - print("featch message completion : ", error as Any) - } - - public func fetchMessageAttachment(_ message: NIMMessage, progress: Float) { - print("fetchMessageAttachment progress : ", progress) - /* - var index = -1 - for (i, model) in self.messages.enumerated() { - if model.message?.serverID == message.serverID { - index = i - break - } - } - if index >= 0 { - let indexPath = IndexPath(row: index, section: 0) - delegate?.updateDownloadProgress(message, atIndex: indexPath, progress: progress) - } */ - } - - public func fetchMessageAttachment(_ message: NIMMessage, _ completion: @escaping (Error?) -> Void) { - repo.downloadMessageAttachment(message, completion) - } - - public func downLoad(_ urlString: String, _ filePath: String, _ progress: NIMHttpProgressBlock?, _ completion: NIMDownloadCompleteBlock?){ - repo.downLoadSource(urlString, filePath, progress, completion) - } - - public func getUrls() -> [String] { - var urls = [String]() - messages.forEach { model in - if model.type == .image, let message = model.message?.messageObject as? NIMImageObject { - if let url = message.url { - urls.append(url) - }else { - if let path = message.path, FileManager.default.fileExists(atPath: path) { - urls.append(path) - } - } - } - } - print("urls:\(urls)") - return urls - } - - public func forwardUserMessage(_ message: NIMMessage, _ users: [NIMUser]){ - weak var weakSelf = self - users.forEach { user in - if let uid = user.userId { - let session = NIMSession(uid, type: .P2P) - weakSelf?.repo.makeForwardMessage(message, session) - } + let last = index - 1 + if last >= 0, let timeModel = messages[last] as? MessageTipsModel, + timeModel.type == .time { + messages.removeSubrange(last ... index) + indexs.append(IndexPath(row: last, section: 0)) + indexs.append(IndexPath(row: index, section: 0)) + } else { + messages.remove(at: index) + indexs.append(IndexPath(row: index, section: 0)) + } + } + delegate?.onDeleteMessage(message, atIndexs: indexs) + } + + func revokeMessageUpdateUI(_ message: NIMMessage) { + var index = -1 + for (i, model) in messages.enumerated() { + if model.message?.serverID == message.serverID { + index = i + break + } + } + var indexs = [IndexPath]() + if index >= 0 { + messages[index].isRevoked = true + messages[index].replyedModel = nil + indexs.append(IndexPath(row: index, section: 0)) + } + delegate?.onRevokeMessage(message, atIndexs: indexs) + } + + public func fetchMessageAttachment(_ message: NIMMessage, didCompleteWithError error: Error?) { + print("featch message completion : ", error as Any) + } + + public func fetchMessageAttachment(_ message: NIMMessage, progress: Float) { + print("fetchMessageAttachment progress : ", progress) + /* + var index = -1 + for (i, model) in self.messages.enumerated() { + if model.message?.serverID == message.serverID { + index = i + break + } + } + if index >= 0 { + let indexPath = IndexPath(row: index, section: 0) + delegate?.updateDownloadProgress(message, atIndex: indexPath, progress: progress) + } */ + } + + public func fetchMessageAttachment(_ message: NIMMessage, + _ completion: @escaping (Error?) -> Void) { + repo.downloadMessageAttachment(message, completion) + } + + public func downLoad(_ urlString: String, _ filePath: String, _ progress: NIMHttpProgressBlock?, + _ completion: NIMDownloadCompleteBlock?) { + repo.downLoadSource(urlString, filePath, progress, completion) + } + + public func getUrls() -> [String] { + var urls = [String]() + messages.forEach { model in + if model.type == .image, let message = model.message?.messageObject as? NIMImageObject { + if let url = message.url { + urls.append(url) + } else { + if let path = message.path, FileManager.default.fileExists(atPath: path) { + urls.append(path) + } } + } } - - public func forwardTeamMessage(_ message: NIMMessage, _ team: NIMTeam) { - if let tid = team.teamId { - let session = NIMSession(tid, type: .team) - repo.makeForwardMessage(message, session) - } + print("urls:\(urls)") + return urls + } + + public func forwardUserMessage(_ message: NIMMessage, _ users: [NIMUser]) { + weak var weakSelf = self + users.forEach { user in + if let uid = user.userId { + let session = NIMSession(uid, type: .P2P) + weakSelf?.repo.makeForwardMessage(message, session) + } + } + } + + public func forwardTeamMessage(_ message: NIMMessage, _ team: NIMTeam) { + if let tid = team.teamId { + let session = NIMSession(tid, type: .team) + repo.makeForwardMessage(message, session) } - - public func pinMessage(_ message: NIMMessage, _ completion: @escaping (Error?, NIMMessagePinItem?, Int)->()) { - let item = NIMMessagePinItem(message: message) - repo.addMessagePin(item) {[weak self] error, pinItem in - var index = -1 - if var messages = self?.messages { - for (i, model) in messages.enumerated() { - if message.messageId == model.message?.messageId { - messages[i].isPined = true - messages[i].pinAccount = NIMSDK.shared().loginManager.currentAccount() - messages[i].pinShowName = self?.getShowName(userId: NIMSDK.shared().loginManager.currentAccount(), teamId: message.session?.sessionId) - self?.messages = messages - index = i - break - } - } - } - completion(error, pinItem, index) + } + + public func pinMessage(_ message: NIMMessage, + _ completion: @escaping (Error?, NIMMessagePinItem?, Int) -> Void) { + let item = NIMMessagePinItem(message: message) + repo.addMessagePin(item) { [weak self] error, pinItem in + var index = -1 + if var messages = self?.messages { + for (i, model) in messages.enumerated() { + if message.messageId == model.message?.messageId { + messages[i].isPined = true + messages[i].pinAccount = NIMSDK.shared().loginManager.currentAccount() + messages[i].pinShowName = self?.getShowName( + userId: NIMSDK.shared().loginManager.currentAccount(), + teamId: message.session?.sessionId + ) + self?.messages = messages + index = i + break + } } + } + completion(error, pinItem, index) } - - public func removePinMessage(_ message: NIMMessage, _ completion: @escaping (Error?, NIMMessagePinItem?, Int)->()) { - let item = NIMMessagePinItem(message: message) - repo.removePin(item) { [weak self] error, pinItem in - var index = -1 - if var messages = self?.messages { - for (i, model) in messages.enumerated() { - if message.messageId == model.message?.messageId { - messages[i].isPined = false - messages[i].pinAccount = nil - self?.messages = messages - index = i - break - } - } - } - completion(error, pinItem, index) + } + + public func removePinMessage(_ message: NIMMessage, + _ completion: @escaping (Error?, NIMMessagePinItem?, Int) + -> Void) { + let item = NIMMessagePinItem(message: message) + repo.removePin(item) { [weak self] error, pinItem in + var index = -1 + if var messages = self?.messages { + for (i, model) in messages.enumerated() { + if message.messageId == model.message?.messageId { + messages[i].isPined = false + messages[i].pinAccount = nil + self?.messages = messages + index = i + break + } } + } + completion(error, pinItem, index) } - - public func sendInputTypingState(){ - - if session.sessionType == .P2P { - setTypingCustom(1) - } + } + + public func sendInputTypingState() { + if session.sessionType == .P2P { + setTypingCustom(1) } - - public func sendInputTypingEndState(){ - if self.session.sessionType == .P2P { - setTypingCustom(0) - } + } + + public func sendInputTypingEndState() { + if session.sessionType == .P2P { + setTypingCustom(0) } - - func setTypingCustom(_ typing: Int){ + } - let message = NIMMessage() - if message.setting == nil { - message.setting = NIMMessageSetting() - } - message.setting?.apnsEnabled = false - message.setting?.shouldBeCounted = false - let noti = NIMCustomSystemNotification(content: getJSONStringFromDictionary(["typing":typing])) - - repo.sendCustomNotification(noti, session) { error in - if let err = error { - print("send noti success :", err) - } - } + func setTypingCustom(_ typing: Int) { + let message = NIMMessage() + if message.setting == nil { + message.setting = NIMMessageSetting() + } + message.setting?.apnsEnabled = false + message.setting?.shouldBeCounted = false + let noti = + NIMCustomSystemNotification(content: getJSONStringFromDictionary(["typing": typing])) + repo.sendCustomNotification(noti, session) { error in + if let err = error { + print("send noti success :", err) + } } - - public func getHandSetEnable() -> Bool{ - return repo.getEarState() - } - - public func getMessageRead() -> Bool { - return repo.getMessageRead() - } - + } + + public func getHandSetEnable() -> Bool { + repo.getEarState() + } + + public func getMessageRead() -> Bool { + repo.getMessageRead() + } + // MARK: NIMConversationManagerDelegate + // remote // public func onRecvMessagesDeleted(_ messages: [NIMMessage], exts: [String : String]?) { // if let message = messages.first { @@ -1082,7 +1163,7 @@ public class ChatViewModel: NSObject, ChatRepoMessageDelegate, NIMChatManagerDel // public func onRecvMessageDeleted(_ message: NIMMessage, ext: String?) { // print("onRecvMessagesDeleted: \(message) exts:\(ext)") // } - deinit { - print("deinit") - } + deinit { + print("deinit") + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/ViewModel/TeamChatViewModel.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/ViewModel/TeamChatViewModel.swift index 9cb57a37..b450a0a2 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/ViewModel/TeamChatViewModel.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/ViewModel/TeamChatViewModel.swift @@ -1,27 +1,28 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NIMSDK import CoreText public protocol TeamChatViewModelDelegate: ChatViewModelDelegate { - func onTeamRemoved(team: NIMTeam) - func onTeamUpdate(team: NIMTeam) + func onTeamRemoved(team: NIMTeam) + func onTeamUpdate(team: NIMTeam) } -public class TeamChatViewModel:ChatViewModel, NIMTeamManagerDelegate { - public var team: NIMTeam? +public class TeamChatViewModel: ChatViewModel, NIMTeamManagerDelegate { + public var team: NIMTeam? // override init(session: NIMSession) { // super.init(session: session) // repo.addTeamDelegate(delegate: self) -// +// // } - - override init(session:NIMSession,anchor:NIMMessage?) { - super.init(session: session, anchor: anchor) - repo.addTeamDelegate(delegate: self) + + override init(session: NIMSession, anchor: NIMMessage?) { + super.init(session: session, anchor: anchor) + repo.addTeamDelegate(delegate: self) // self.session = session // self.anchor = anchor // super.init() @@ -32,37 +33,38 @@ public class TeamChatViewModel:ChatViewModel, NIMTeamManagerDelegate { // repo.addConversationDelegate(delegate: self) // repo.addSystemNotiDelegate(delegate: self) // repo.addChatExtDelegate(delegate: self) + } + + public func getTeam(teamId: String) -> NIMTeam? { + repo.getTeamInfo(teamId: teamId) + } + + public func fetchTeamInfo(teamId: String, + _ completion: @escaping (NSError?, NIMTeam?) -> Void) { + repo.getTeamInfo(teamId: teamId) { [weak self] error, team in + if error == nil { + self?.team = team + } + completion(error, team) } - - public func getTeam(teamId: String) -> NIMTeam? { - return repo.getTeamInfo(teamId: teamId) - } - - public func fetchTeamInfo(teamId: String, _ completion: @escaping (NSError?, NIMTeam?)->()) { - repo.getTeamInfo(teamId: teamId) {[weak self] error, team in - if error == nil { - self?.team = team - } - completion(error, team) - } - } - + } + // MARK: NIMTeamManagerDelegate - public func onTeamRemoved(_ team: NIMTeam) { - if session.sessionId == team.teamId { - if let delegate = self.delegate as? TeamChatViewModelDelegate { - delegate.onTeamRemoved(team: team) - } - } - } - - public func onTeamUpdated(_ team: NIMTeam) { - if session.sessionId == team.teamId { - self.team = team - if let delegate = self.delegate as? TeamChatViewModelDelegate { - delegate.onTeamUpdate(team: team) - } - } + + public func onTeamRemoved(_ team: NIMTeam) { + if session.sessionId == team.teamId { + if let delegate = delegate as? TeamChatViewModelDelegate { + delegate.onTeamRemoved(team: team) + } } + } + public func onTeamUpdated(_ team: NIMTeam) { + if session.sessionId == team.teamId { + self.team = team + if let delegate = delegate as? TeamChatViewModelDelegate { + delegate.onTeamUpdate(team: team) + } + } + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/ViewModel/TeamMemberSelectVM.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/ViewModel/TeamMemberSelectVM.swift index b3b3c6b7..9eac4bb9 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/ViewModel/TeamMemberSelectVM.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/ViewModel/TeamMemberSelectVM.swift @@ -1,15 +1,17 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NIMSDK import NEKitChat public class TeamMemberSelectVM { - public var chatRepo: ChatRepo = ChatRepo() - - func fetchTeamMembers(sessionId: String, _ completion: @escaping (Error?, ChatTeamInfoModel?) -> Void ) { - chatRepo.getTeamInfo(sessionId, completion) - } + public var chatRepo: ChatRepo = .init() + + func fetchTeamMembers(sessionId: String, + _ completion: @escaping (Error?, ChatTeamInfoModel?) -> Void) { + chatRepo.getTeamInfo(sessionId, completion) + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Chat/ViewModel/UserSettingViewModel.swift b/NEChatUIKit/NEKitChatUI/Classes/Chat/ViewModel/UserSettingViewModel.swift index a7436532..da1aaa72 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Chat/ViewModel/UserSettingViewModel.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Chat/ViewModel/UserSettingViewModel.swift @@ -1,6 +1,7 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NEKitChat @@ -8,108 +9,107 @@ import NEKitCoreIM import NIMSDK protocol UserSettingViewModelDelegate: AnyObject { - - func didNeedRefreshUI() - func didError(_ error: Error) + func didNeedRefreshUI() + func didError(_ error: Error) } public class UserSettingViewModel { - - var repo = ChatRepo() - - var userInfo: User? - - var cellDatas = [UserSettingCellModel]() - - var delegate: UserSettingViewModelDelegate? - - func getUserSettingModel(_ userId: String) { - guard let user = repo.getUserInfo(userId: userId) else { - return - } - userInfo = user - weak var weakSelf = self - let remind = UserSettingCellModel() - remind.cellName = localizable("message_remind") - remind.cornerType = .topLeft.union(.topRight) - if let isNotiMsg = user.imUser?.notifyForNewMsg() { - remind.switchOpen = isNotiMsg - } - - remind.swichChange = { isOpen in - if let uid = weakSelf?.userInfo?.userId { - weakSelf?.repo.updateNotifyState(uid, isOpen, { error in - if let err = error { - weakSelf?.delegate?.didNeedRefreshUI() - weakSelf?.delegate?.didError(err) - }else { - remind.switchOpen = isOpen - } - }) - } - } - - let setTop = UserSettingCellModel() - setTop.cellName = localizable("session_set_top") - setTop.cornerType = .bottomRight.union(.bottomLeft) + var repo = ChatRepo() + + var userInfo: User? + + var cellDatas = [UserSettingCellModel]() + + var delegate: UserSettingViewModelDelegate? + + func getUserSettingModel(_ userId: String) { + guard let user = repo.getUserInfo(userId: userId) else { + return + } + userInfo = user + weak var weakSelf = self + let remind = UserSettingCellModel() + remind.cellName = localizable("message_remind") + remind.cornerType = .topLeft.union(.topRight) + if let isNotiMsg = user.imUser?.notifyForNewMsg() { + remind.switchOpen = isNotiMsg + } - if let uid = user.userId { - let session = NIMSession(uid, type: .P2P) - setTop.switchOpen = repo.isStickTop(session) + remind.swichChange = { isOpen in + if let uid = weakSelf?.userInfo?.userId { + weakSelf?.repo.updateNotifyState(uid, isOpen) { error in + if let err = error { + weakSelf?.delegate?.didNeedRefreshUI() + weakSelf?.delegate?.didError(err) + } else { + remind.switchOpen = isOpen + } } - - setTop.swichChange = { isOpen in - if let uid = weakSelf?.userInfo?.userId { - let session = NIMSession(uid, type: .P2P) - if isOpen { - let params = NIMAddStickTopSessionParams.init(session: session) - weakSelf?.repo.chatExtendProvider.addStickTopSession(params: params) { error, info in - print("add stick : ",error as Any) - if let err = error { - weakSelf?.delegate?.didNeedRefreshUI() - weakSelf?.delegate?.didError(err) - }else { - setTop.switchOpen = false - } - } - }else { - if let info = weakSelf?.repo.chatExtendProvider.getTopSessionInfo(session) { - weakSelf?.repo.chatExtendProvider.removeStickTopSession(params: info) { error, info in - print("remote stick : ",error as Any) - if let err = error { - weakSelf?.delegate?.didNeedRefreshUI() - weakSelf?.delegate?.didError(err) - }else { - setTop.switchOpen = true - } - } - } - } + } + } + + let setTop = UserSettingCellModel() + setTop.cellName = localizable("session_set_top") + setTop.cornerType = .bottomRight.union(.bottomLeft) + + if let uid = user.userId { + let session = NIMSession(uid, type: .P2P) + setTop.switchOpen = repo.isStickTop(session) + } + + setTop.swichChange = { isOpen in + if let uid = weakSelf?.userInfo?.userId { + let session = NIMSession(uid, type: .P2P) + if isOpen { + let params = NIMAddStickTopSessionParams(session: session) + weakSelf?.repo.chatExtendProvider + .addStickTopSession(params: params) { error, info in + print("add stick : ", error as Any) + if let err = error { + weakSelf?.delegate?.didNeedRefreshUI() + weakSelf?.delegate?.didError(err) + } else { + setTop.switchOpen = false + } } - } - - /* - let blackList = UserSettingCellModel() - blackList.cornerType = .bottomRight.union(.bottomLeft) - blackList.cellName = "加入黑名单" - if let isBlack = user.imUser?.isInMyBlackList() { - blackList.switchOpen = isBlack - } - blackList.swichChange = { isOpen in - if let uid = weakSelf?.userInfo?.userId { - if isOpen { - weakSelf?.repo.addBlackList(account: uid, { error in - print("add black list : ", error as Any) - }) - }else { - weakSelf?.repo.removeFromBlackList(account: uid, { error in - print("remo black list : ", error as Any) - }) + } else { + if let info = weakSelf?.repo.chatExtendProvider.getTopSessionInfo(session) { + weakSelf?.repo.chatExtendProvider + .removeStickTopSession(params: info) { error, info in + print("remote stick : ", error as Any) + if let err = error { + weakSelf?.delegate?.didNeedRefreshUI() + weakSelf?.delegate?.didError(err) + } else { + setTop.switchOpen = true } - } + } + } } - */ - cellDatas.append(contentsOf: [remind, setTop]) - + } } + + /* + let blackList = UserSettingCellModel() + blackList.cornerType = .bottomRight.union(.bottomLeft) + blackList.cellName = "加入黑名单" + if let isBlack = user.imUser?.isInMyBlackList() { + blackList.switchOpen = isBlack + } + blackList.swichChange = { isOpen in + if let uid = weakSelf?.userInfo?.userId { + if isOpen { + weakSelf?.repo.addBlackList(account: uid, { error in + print("add black list : ", error as Any) + }) + }else { + weakSelf?.repo.removeFromBlackList(account: uid, { error in + print("remo black list : ", error as Any) + }) + } + } + } + */ + cellDatas.append(contentsOf: [remind, setTop]) + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/ChatConfig/ChatUIConfig.swift b/NEChatUIKit/NEKitChatUI/Classes/ChatConfig/ChatUIConfig.swift index a6e47b3c..7882f159 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/ChatConfig/ChatUIConfig.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/ChatConfig/ChatUIConfig.swift @@ -1,44 +1,38 @@ -// -// ChatUIConfig.swift -// NEKitConversationUI -// -// Created by vvj on 2022/6/13. -// -import UIKit +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. +import UIKit /// 头像枚举类型 public enum NEChatAvatarType { - case rectangle //矩形 - case cycle //圆形 + case rectangle // 矩形 + case cycle // 圆形 } - public class ChatUIConfig: NSObject { - - /// 头像圆角大小 - public var avatarCornerRadius = 4.0 - - /// 头像类型 - public var avatarType:NEChatAvatarType = .cycle - - /// 设置聊天消息标记的背景色 - public var chatPinColor = UIColor.ne_yellowBackgroundColor - - //时间颜色 - public var timeColor = UIColor.ne_emptyTitleColor - - //右侧聊天背景气泡 - public var rightBubbleBg = UIImage.ne_imageNamed(name: "chat_message_send") - - //左侧聊天背景气泡 - public var leftBubbleBg = UIImage.ne_imageNamed(name: "chat_message_receive") - - /// 聊天字体大小(文本类型) - public var messageFont = UIFont.systemFont(ofSize: 16) - - /// 聊天字体颜色(文本类型) - public var messageColor = UIColor.ne_darkText + /// 头像圆角大小 + public var avatarCornerRadius = 4.0 + + /// 头像类型 + public var avatarType: NEChatAvatarType = .cycle + + /// 设置聊天消息标记的背景色 + public var chatPinColor = UIColor.ne_yellowBackgroundColor + + // 时间颜色 + public var timeColor = UIColor.ne_emptyTitleColor + + // 右侧聊天背景气泡 + public var rightBubbleBg = UIImage.ne_imageNamed(name: "chat_message_send") + + // 左侧聊天背景气泡 + public var leftBubbleBg = UIImage.ne_imageNamed(name: "chat_message_receive") + + /// 聊天字体大小(文本类型) + public var messageFont = UIFont.systemFont(ofSize: 16) + /// 聊天字体颜色(文本类型) + public var messageColor = UIColor.ne_darkText } diff --git a/NEChatUIKit/NEKitChatUI/Classes/ChatConfig/NEKitChatConfig.swift b/NEChatUIKit/NEKitChatUI/Classes/ChatConfig/NEKitChatConfig.swift index 8bed909d..b11bae19 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/ChatConfig/NEKitChatConfig.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/ChatConfig/NEKitChatConfig.swift @@ -1,21 +1,16 @@ -// -// NEKitChatConfig.swift -// NEKitChatUI -// -// Created by vvj on 2022/6/15. -// + +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit @objcMembers public class NEKitChatConfig: NSObject { - - - public static let shared = NEKitChatConfig() - - - //chat UI配置相关 - public var ui = ChatUIConfig() - - //chat 其他配置 待扩展 + public static let shared = NEKitChatConfig() + + // chat UI配置相关 + public var ui = ChatUIConfig() + + // chat 其他配置 待扩展 } diff --git a/NEChatUIKit/NEKitChatUI/Classes/ChatRouter/ChatRouter.swift b/NEChatUIKit/NEKitChatUI/Classes/ChatRouter/ChatRouter.swift index b44df113..ad31045d 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/ChatRouter/ChatRouter.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/ChatRouter/ChatRouter.swift @@ -1,46 +1,44 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NIMSDK import NEKitCommon -public struct ChatRouter { - public static func register() { - - - // p2p - Router.shared.register(PushP2pChatVCRouter) { param in - print("param:\(param)") - let nav = param["nav"] as? UINavigationController - guard let session = param["session"] as? NIMSession else { - return - } - let p2pChatVC = P2PChatViewController(session: session) - nav?.pushViewController(p2pChatVC, animated: true) - } - - // group - Router.shared.register(PushTeamChatVCRouter) { param in - print("param:\(param)") - let nav = param["nav"] as? UINavigationController - guard let session = param["session"] as? NIMSession else { - return - } - if let anchor = param["anchor"] as? NIMMessage { - let groupVC = GroupChatViewController(session: session, anchor: anchor) - nav?.pushViewController(groupVC, animated: true) - }else { - let groupVC = GroupChatViewController(session: session, anchor: nil) - nav?.pushViewController(groupVC, animated: true) - } - - } +public enum ChatRouter { + public static func register() { + // p2p + Router.shared.register(PushP2pChatVCRouter) { param in + print("param:\(param)") + let nav = param["nav"] as? UINavigationController + guard let session = param["session"] as? NIMSession else { + return + } + let p2pChatVC = P2PChatViewController(session: session) + nav?.pushViewController(p2pChatVC, animated: true) } - - public static func setupInit(){ - NIMKitFileLocationHelper.setStaticAppkey(NIMSDK.shared().appKey()) - NIMKitFileLocationHelper.setStaticUserId(NIMSDK.shared().loginManager.currentAccount()) + + // group + Router.shared.register(PushTeamChatVCRouter) { param in + print("param:\(param)") + let nav = param["nav"] as? UINavigationController + guard let session = param["session"] as? NIMSession else { + return + } + if let anchor = param["anchor"] as? NIMMessage { + let groupVC = GroupChatViewController(session: session, anchor: anchor) + nav?.pushViewController(groupVC, animated: true) + } else { + let groupVC = GroupChatViewController(session: session, anchor: nil) + nav?.pushViewController(groupVC, animated: true) + } } + } + + public static func setupInit() { + NIMKitFileLocationHelper.setStaticAppkey(NIMSDK.shared().appKey()) + NIMKitFileLocationHelper.setStaticUserId(NIMSDK.shared().loginManager.currentAccount()) + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Common/ChatConstantValue.swift b/NEChatUIKit/NEKitChatUI/Classes/Common/ChatConstantValue.swift index bd75f9d6..25c5e4ed 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Common/ChatConstantValue.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Common/ChatConstantValue.swift @@ -1,32 +1,33 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation -//距离cell边缘的距离 +// 距离cell边缘的距离 public let qChat_cell_margin = 16.0 -//控件之间的间距 +// 控件之间的间距 public let qChat_margin = 8.0 -//头像宽高 +// 头像宽高 public let qChat_headWH = 32.0 -//时间cell的高度(固定) +// 时间cell的高度(固定) public let qChat_timeCellH = 21.0 -//图片最大宽高 -public let qChat_pic_size = CGSize.init(width: 150, height: 200) +// 图片最大宽高 +public let qChat_pic_size = CGSize(width: 150, height: 200) -//单行气泡高度 +// 单行气泡高度 public let qChat_min_h = 40.0 -//内容尾部距离cell边框的间距 +// 内容尾部距离cell边框的间距 public let chat_reply_height = 34.0 -//内容最大宽度 +// 内容最大宽度 public let qChat_content_maxW = (kScreenWidth - 136) -//pin消息需要增加的高度 +// pin消息需要增加的高度 public let chat_pin_height = 16.0 -//群聊起泡上方用户名lable高度,p2p无此展示,高度为0 +// 群聊起泡上方用户名lable高度,p2p无此展示,高度为0 public let chat_full_name_height = 16.0 diff --git a/NEChatUIKit/NEKitChatUI/Classes/Common/Constants.swift b/NEChatUIKit/NEKitChatUI/Classes/Common/Constants.swift index 5e2539f5..5ff06bec 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Common/Constants.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Common/Constants.swift @@ -1,98 +1,104 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation @_exported import NEKitCore @_exported import NEKitCommonUI @_exported import NEKitCommon @_exported import SDWebImage -//@_exported +// @_exported let coreLoader = CoreLoader() -func localizable(_ key: String) -> String{ - return coreLoader.localizable(key) +func localizable(_ key: String) -> String { + coreLoader.localizable(key) } func getJSONStringFromDictionary(_ dictionary: [String: Any]) -> String { - if (!JSONSerialization.isValidJSONObject(dictionary)) { - print("not parse to json string") - return "" - } - if let data = try? JSONSerialization.data(withJSONObject: dictionary, options: []), - let JSONString = String(data: data, encoding: .utf8){ - return JSONString - } + if !JSONSerialization.isValidJSONObject(dictionary) { + print("not parse to json string") return "" + } + if let data = try? JSONSerialization.data(withJSONObject: dictionary, options: []), + let JSONString = String(data: data, encoding: .utf8) { + return JSONString + } + return "" } func getDictionaryFromJSONString(_ jsonString: String) -> NSDictionary? { - if let jsonData = jsonString.data(using: .utf8), - let dict = try? JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers) as? NSDictionary{ - return dict - } - return nil + if let jsonData = jsonString.data(using: .utf8), + let dict = try? JSONSerialization.jsonObject( + with: jsonData, + options: .mutableContainers + ) as? NSDictionary { + return dict + } + return nil } @objc public protocol ViewModelDelegate: AnyObject { - func dataDidChange() - func dataDidError(_ error: Error) - @objc optional func dataNoMore() + func dataDidChange() + func dataDidError(_ error: Error) + @objc optional func dataNoMore() } // MARK: 常量 -public let kScreenWidth:CGFloat = UIScreen.main.bounds.size.width -public let kScreenHeight:CGFloat = UIScreen.main.bounds.size.height + +public let kScreenWidth: CGFloat = UIScreen.main.bounds.size.width +public let kScreenHeight: CGFloat = UIScreen.main.bounds.size.height public let kUISreenWidthScale = kScreenWidth / 375.0 public let kUISreenHeightScale = kScreenHeight / 667.0 -public let kNavigationHeight = 44.0 -public let KStatusBarHeight = UIApplication.shared.statusBarFrame.height //获取statusBar的高度 +public let kNavigationHeight = 44.0 +public let KStatusBarHeight = UIApplication.shared.statusBarFrame.height // 获取statusBar的高度 /// 屏幕间隔 -public let kScreenInterval:CGFloat = 20 - +public let kScreenInterval: CGFloat = 20 // MARK: 字体 -let TextFont:((String ,Float ) -> UIFont) = { - (fontName:String ,fontSize:Float ) -> UIFont in - if #available(iOS 9.0, macOS 10,*) { - return UIFont.init(name: fontName, size: CGFloat(fontSize))! - }else { - return UIFont.systemFont(ofSize: CGFloat(fontSize)) - } -} -let DefaultTextFont:((Float) -> UIFont) = { - (fontSize:Float ) -> UIFont in - return TextFont("PingFangSC-Regular",fontSize) +let TextFont: ((String, Float) -> UIFont) = { + (fontName: String, fontSize: Float) -> UIFont in + if #available(iOS 9.0, macOS 10,*) { + return UIFont(name: fontName, size: CGFloat(fontSize))! + } else { + return UIFont.systemFont(ofSize: CGFloat(fontSize)) + } } - - +let DefaultTextFont: ((Float) -> UIFont) = { + (fontSize: Float) -> UIFont in + TextFont("PingFangSC-Regular", fontSize) +} // MARK: 颜色 -let TextNormalColor:UIColor = HexRGB(0x333333) -let SubTextColor:UIColor = HexRGB(0x666666) -let PlaceholderTextColor:UIColor = HexRGB(0xA6ADB6) +let TextNormalColor: UIColor = HexRGB(0x333333) +let SubTextColor: UIColor = HexRGB(0x666666) +let PlaceholderTextColor: UIColor = HexRGB(0xA6ADB6) -let HexRGB:((Int) -> UIColor) = { (rgbValue : Int) -> UIColor in - return HexRGBAlpha(rgbValue,1.0) +let HexRGB: ((Int) -> UIColor) = { (rgbValue: Int) -> UIColor in + HexRGBAlpha(rgbValue, 1.0) } -let HexRGBAlpha:((Int,Float) -> UIColor) = { (rgbValue : Int, alpha : Float) -> UIColor in - return UIColor(red: CGFloat(CGFloat((rgbValue & 0xFF0000) >> 16)/255), green: CGFloat(CGFloat((rgbValue & 0xFF00) >> 8)/255), blue: CGFloat(CGFloat(rgbValue & 0xFF)/255), alpha: CGFloat(alpha)) +let HexRGBAlpha: ((Int, Float) -> UIColor) = { (rgbValue: Int, alpha: Float) -> UIColor in + UIColor( + red: CGFloat(CGFloat((rgbValue & 0xFF0000) >> 16) / 255), + green: CGFloat(CGFloat((rgbValue & 0xFF00) >> 8) / 255), + blue: CGFloat(CGFloat(rgbValue & 0xFF) / 255), + alpha: CGFloat(alpha) + ) } // MARK: notificationkey -struct NotificationName { - // 参数 serverId: string - static let createServer = Notification.Name(rawValue:"qchat.createServer") - //param channel: ChatChannel - static let createChannel = Notification.Name(rawValue:"qchat.createChannel") - static let updateChannel = Notification.Name(rawValue:"qchat.updateChannel") - static let deleteChannel = Notification.Name(rawValue:"qchat.deleteChannel") - -// static let login = Notification.Name(rawValue:"qchat.login") - static let logout = Notification.Name(rawValue:"qchat.logout") +enum NotificationName { + // 参数 serverId: string + static let createServer = Notification.Name(rawValue: "qchat.createServer") + // param channel: ChatChannel + static let createChannel = Notification.Name(rawValue: "qchat.createChannel") + static let updateChannel = Notification.Name(rawValue: "qchat.updateChannel") + static let deleteChannel = Notification.Name(rawValue: "qchat.deleteChannel") +// static let login = Notification.Name(rawValue:"qchat.login") + static let logout = Notification.Name(rawValue: "qchat.logout") } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Common/IMCustomAttachment.swift b/NEChatUIKit/NEKitChatUI/Classes/Common/IMCustomAttachment.swift index 581b7b97..a61594eb 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Common/IMCustomAttachment.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Common/IMCustomAttachment.swift @@ -1,69 +1,64 @@ -// -// CustomerSampleAttachment.swift -// NEKitChatUI -// -// Created by vvj on 2022/6/17. -// + +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NIMSDK -public class CustomAttachment: NSObject,NIMCustomAttachment { - - public var type = 0 - - public var goodsName = "name" - - public var goodsURL = "url" - - public func encode() -> String { +public class CustomAttachment: NSObject, NIMCustomAttachment { + public var type = 0 - let info = ["goodsName":goodsName,"goodsURL":goodsURL,"type":type] as [String : Any] - - let jsonData = try? JSONSerialization.data(withJSONObject: info, options: .prettyPrinted) - var content = "" - if let data = jsonData { - content = String.init(data: data, encoding: .utf8) ?? "" - } - return content - } + public var goodsName = "name" + + public var goodsURL = "url" + public func encode() -> String { + let info = ["goodsName": goodsName, "goodsURL": goodsURL, "type": type] as [String: Any] + + let jsonData = try? JSONSerialization.data(withJSONObject: info, options: .prettyPrinted) + var content = "" + if let data = jsonData { + content = String(data: data, encoding: .utf8) ?? "" + } + return content + } } +public class CustomAttachmentDecoder: NSObject, NIMCustomAttachmentCoding { + public func decodeAttachment(_ content: String?) -> NIMCustomAttachment? { + var attachment: NIMCustomAttachment? + let data = content?.data(using: .utf8) + guard let dataInfo = data else { + return attachment + } + + let infoDict = try? JSONSerialization.jsonObject( + with: dataInfo, + options: .mutableContainers + ) + let infoResult = infoDict as? [String: Any] + let type = infoResult?["type"] as? Int -public class CustomAttachmentDecoder:NSObject, NIMCustomAttachmentCoding { - - public func decodeAttachment(_ content: String?) -> NIMCustomAttachment? { - - var attachment: NIMCustomAttachment? = nil - let data = content?.data(using: .utf8) - guard let dataInfo = data else { - return attachment - } - - let infoDict = try? JSONSerialization.jsonObject(with: dataInfo, options: .mutableContainers) - let infoResult = infoDict as? [String:Any] - let type = infoResult?["type"] as? Int - - switch type { - case 0: - attachment = decodeCustomMessage(info: infoDict as? [String : Any] ?? [String():String()]) - default: - print("test") - } - - return attachment + switch type { + case 0: + attachment = + decodeCustomMessage(info: infoDict as? [String: Any] ?? [String(): String()]) + default: + print("test") } - - - func decodeCustomMessage(info:[String:Any]) -> CustomAttachment{ - let customAttachment = CustomAttachment() - customAttachment.goodsName = info["goodsName"] as? String ?? "" - customAttachment.goodsURL = info["goodsURL"] as? String ?? "" - if let type = info["type"] as? Int{ - customAttachment.type = type - } - return customAttachment + return attachment + } + + func decodeCustomMessage(info: [String: Any]) -> CustomAttachment { + let customAttachment = CustomAttachment() + customAttachment.goodsName = info["goodsName"] as? String ?? "" + customAttachment.goodsURL = info["goodsURL"] as? String ?? "" + if let type = info["type"] as? Int { + customAttachment.type = type } + + return customAttachment + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Common/NEChatUITool.swift b/NEChatUIKit/NEKitChatUI/Classes/Common/NEChatUITool.swift index 3ce96fd1..992ed786 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Common/NEChatUITool.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Common/NEChatUITool.swift @@ -1,20 +1,25 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation public class NEChatUITool { - //计算富文本size - class func getSizeWithAtt(att:NSAttributedString,font:UIFont,maxSize:CGSize) -> CGSize { - if att.length == 0 { - return CGSize.zero - } - var size = att.boundingRect(with: maxSize, options: [.usesLineFragmentOrigin, .usesFontLeading], context: nil).size + // 计算富文本size + class func getSizeWithAtt(att: NSAttributedString, font: UIFont, maxSize: CGSize) -> CGSize { + if att.length == 0 { + return CGSize.zero + } + var size = att.boundingRect( + with: maxSize, + options: [.usesLineFragmentOrigin, .usesFontLeading], + context: nil + ).size - if att.length > 0 && size.width == 0 && size.height == 0 { - size = maxSize - } - return CGSize(width: ceil(size.width), height: ceil(size.height)) + if att.length > 0, size.width == 0, size.height == 0 { + size = maxSize } + return CGSize(width: ceil(size.width), height: ceil(size.height)) + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Common/NSBundleExtension.swift b/NEChatUIKit/NEKitChatUI/Classes/Common/NSBundleExtension.swift index 4ddda3d4..c3932ff2 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Common/NSBundleExtension.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Common/NSBundleExtension.swift @@ -1,47 +1,56 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation public extension Bundle { - class func nim_defaultEmojiBundle() -> Bundle? { - let bundle = Bundle(for: NIMInputEmoticonManager.self) - let url = bundle.url(forResource: "NIMKitEmoticon", withExtension: "bundle") - var emojiBundle: Bundle? = nil - if let url = url { - emojiBundle = Bundle(url: url) - } - return emojiBundle + class func nim_defaultEmojiBundle() -> Bundle? { + let bundle = Bundle(for: NIMInputEmoticonManager.self) + let url = bundle.url(forResource: "NIMKitEmoticon", withExtension: "bundle") + var emojiBundle: Bundle? + if let url = url { + emojiBundle = Bundle(url: url) } - - - class func nim_EmojiPlistFile() -> String? { - let bundle = Bundle.nim_defaultEmojiBundle() - let filepath = bundle?.path(forResource: "emoji_ios_new", ofType: "plist", inDirectory: NIMKit_EmojiPath) - return filepath + return emojiBundle + } + + class func nim_EmojiPlistFile() -> String? { + let bundle = Bundle.nim_defaultEmojiBundle() + let filepath = bundle?.path( + forResource: "emoji_ios_new", + ofType: "plist", + inDirectory: NIMKit_EmojiPath + ) + return filepath + } + + class func nim_EmojiImage(imageName: String) -> String? { + let bundle = Bundle.nim_defaultEmojiBundle() + var ext = URL(fileURLWithPath: imageName).pathExtension + if ext.count == 0 { + ext = "png" + } + let name = URL(fileURLWithPath: imageName).deletingPathExtension().path + let doubleImage = name + "@2x" + let tribleImage = name + "@3x" + var path: String? + if UIScreen.main.scale == 3.0 { + path = bundle?.path( + forResource: tribleImage, + ofType: ext, + inDirectory: NIMKit_EmojiPath + ) } - - class func nim_EmojiImage(imageName:String) -> String? { - let bundle = Bundle.nim_defaultEmojiBundle() - var ext = URL(fileURLWithPath: imageName).pathExtension - if ext.count == 0 { - ext = "png" - } - let name = URL(fileURLWithPath: imageName).deletingPathExtension().path - let doubleImage = name + "@2x" - let tribleImage = name + "@3x" - var path: String? = nil - if UIScreen.main.scale == 3.0 { - path = bundle?.path(forResource: tribleImage, ofType: ext, inDirectory: NIMKit_EmojiPath) - } - if let imagePath = path,imagePath.count>0 { - - }else { - path = bundle?.path(forResource: doubleImage, ofType: ext, inDirectory: NIMKit_EmojiPath) - } - return path + if let imagePath = path, imagePath.count > 0 { + } else { + path = bundle?.path( + forResource: doubleImage, + ofType: ext, + inDirectory: NIMKit_EmojiPath + ) } - - + return path + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Extension/AlertVCExtention.swift b/NEChatUIKit/NEKitChatUI/Classes/Extension/AlertVCExtention.swift index 02b8f597..44452703 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Extension/AlertVCExtention.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Extension/AlertVCExtention.swift @@ -1,24 +1,26 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation extension UIAlertController { - class func reconfimAlertView(title: String?, message: String?, confirm: @escaping () -> Void) -> UIAlertController { - let alert = UIAlertController(title: title, message: message, preferredStyle: .alert) - alert.addAction( UIAlertAction(title: localizable("cancel"), style: .cancel, handler: nil)) - alert.addAction(UIAlertAction(title: localizable("ok"), style: .default) { action in - confirm() - }) - return alert - } - - class func singleAlertView(title: String?, message: String?, confirm: @escaping () -> Void) -> UIAlertController { - let alert = UIAlertController(title: title, message: message, preferredStyle: .alert) - alert.addAction(UIAlertAction(title: localizable("ok"), style: .default) { action in - confirm() - }) - return alert - } + class func reconfimAlertView(title: String?, message: String?, + confirm: @escaping () -> Void) -> UIAlertController { + let alert = UIAlertController(title: title, message: message, preferredStyle: .alert) + alert.addAction(UIAlertAction(title: localizable("cancel"), style: .cancel, handler: nil)) + alert.addAction(UIAlertAction(title: localizable("ok"), style: .default) { action in + confirm() + }) + return alert + } + class func singleAlertView(title: String?, message: String?, + confirm: @escaping () -> Void) -> UIAlertController { + let alert = UIAlertController(title: title, message: message, preferredStyle: .alert) + alert.addAction(UIAlertAction(title: localizable("ok"), style: .default) { action in + confirm() + }) + return alert + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Extension/ChatStringExtension.swift b/NEChatUIKit/NEKitChatUI/Classes/Extension/ChatStringExtension.swift index b15c0959..f8d0a42e 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Extension/ChatStringExtension.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Extension/ChatStringExtension.swift @@ -1,45 +1,43 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation extension String { - - //计算文字size - static func getTextRectSize(_ text:String,font:UIFont,size:CGSize) -> CGSize { - - let attributes = [NSAttributedString.Key.font: font] - let option = NSStringDrawingOptions.usesLineFragmentOrigin - let rect:CGRect = text.boundingRect(with: size, options: option, - attributes: attributes, context: nil) - return rect.size; - } - - static func stringFromDate(date: Date) -> String { - let fmt = DateFormatter() - if Calendar.current.isDateInToday(date) { - fmt.dateFormat = "HH:mm" - }else { - if let firstDayYear = firstDayInYear() { - let dur = date.timeIntervalSince(firstDayYear) - if dur > 0 { - fmt.dateFormat = "MM月dd日 HH:mm" - }else { - fmt.dateFormat = "yyyy年MM月dd日 HH:mm" - } - }else { - fmt.dateFormat = "yyyy年MM月dd日 HH:mm" - } + // 计算文字size + static func getTextRectSize(_ text: String, font: UIFont, size: CGSize) -> CGSize { + let attributes = [NSAttributedString.Key.font: font] + let option = NSStringDrawingOptions.usesLineFragmentOrigin + let rect: CGRect = text.boundingRect(with: size, options: option, + attributes: attributes, context: nil) + return rect.size + } + + static func stringFromDate(date: Date) -> String { + let fmt = DateFormatter() + if Calendar.current.isDateInToday(date) { + fmt.dateFormat = "HH:mm" + } else { + if let firstDayYear = firstDayInYear() { + let dur = date.timeIntervalSince(firstDayYear) + if dur > 0 { + fmt.dateFormat = "MM月dd日 HH:mm" + } else { + fmt.dateFormat = "yyyy年MM月dd日 HH:mm" } - return fmt.string(from: date) - } - - static func firstDayInYear() -> Date? { - let format = DateFormatter() - format.dateFormat = "yyyy-MM-dd" - let year = Calendar.current.component(.year, from: Date()) - return format.date(from: "\(year)-01-01") + } else { + fmt.dateFormat = "yyyy年MM月dd日 HH:mm" + } } + return fmt.string(from: date) + } + static func firstDayInYear() -> Date? { + let format = DateFormatter() + format.dateFormat = "yyyy-MM-dd" + let year = Calendar.current.component(.year, from: Date()) + return format.date(from: "\(year)-01-01") + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Extension/ColorExtension.swift b/NEChatUIKit/NEKitChatUI/Classes/Extension/ColorExtension.swift index 9ecddbf7..cef9466d 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Extension/ColorExtension.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Extension/ColorExtension.swift @@ -1,36 +1,34 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import UIKit public extension UIColor { // MARK: text color - static let ne_darkText = UIColor(hexString: "#333333") - static let ne_greyText = UIColor(hexString: "#666666") - static let ne_lightText = UIColor(hexString: "#999999") - static let ne_blueText = UIColor(hexString: "#337EFF") - static let ne_redText = UIColor(hexString: "#E6605C") - static let ne_disableRedText = UIColor(hexString: "#E6605C", 0.5) - static let ne_backcolor = UIColor(hexString: "F2F4F5") - static let ne_emptyTitleColor = UIColor(hexString: "B3B7BC") - static let ne_greenText = UIColor(hexString: "3EAF96") + + static let ne_darkText = UIColor(hexString: "#333333") + static let ne_greyText = UIColor(hexString: "#666666") + static let ne_lightText = UIColor(hexString: "#999999") + static let ne_blueText = UIColor(hexString: "#337EFF") + static let ne_redText = UIColor(hexString: "#E6605C") + static let ne_disableRedText = UIColor(hexString: "#E6605C", 0.5) + static let ne_backcolor = UIColor(hexString: "F2F4F5") + static let ne_emptyTitleColor = UIColor(hexString: "B3B7BC") + static let ne_greenText = UIColor(hexString: "3EAF96") // MARK: view background color - static let ne_lightBackgroundColor = UIColor(hexString: "#F1F1F6") - static let ne_defautAvatarColor = UIColor(hexString: "#537FF4") - static let ne_greenColor = UIColor(hexString: "#42C294") - static let ne_yellowBackgroundColor = UIColor(hexString: "FFFBEA") - + static let ne_lightBackgroundColor = UIColor(hexString: "#F1F1F6") + static let ne_defautAvatarColor = UIColor(hexString: "#537FF4") + static let ne_greenColor = UIColor(hexString: "#42C294") + static let ne_yellowBackgroundColor = UIColor(hexString: "FFFBEA") + // MARK: border color - static let ne_borderColor = UIColor(hexString: "#DBDDE4") + static let ne_borderColor = UIColor(hexString: "#DBDDE4") // MARK: line color - static let ne_greyLine = UIColor(hexString: "#F5F8FC") - - static let ne_redColor = UIColor(hexString: "#F24957") - + static let ne_greyLine = UIColor(hexString: "#F5F8FC") + static let ne_redColor = UIColor(hexString: "#F24957") } - - diff --git a/NEChatUIKit/NEKitChatUI/Classes/Extension/ImageExtension.swift b/NEChatUIKit/NEKitChatUI/Classes/Extension/ImageExtension.swift index f91701ef..07ee5a48 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Extension/ImageExtension.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Extension/ImageExtension.swift @@ -1,16 +1,17 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import CoreGraphics import UIKit -extension UIImage { - public class func ne_imageNamed(name: String?) -> UIImage? { - guard let imageName = name else { - return nil - } - return coreLoader.loadImage(imageName) +public extension UIImage { + class func ne_imageNamed(name: String?) -> UIImage? { + guard let imageName = name else { + return nil + } + return coreLoader.loadImage(imageName) // guard let path = Bundle(for: ChatBaseCell.self).resourcePath?.appending("/NEKitQChatUI.bundle") else { // print("Image:\(imageName) path: nil") // return nil @@ -19,15 +20,14 @@ extension UIImage { // print("Bundle:\(Bundle(path: path))") // print("imageName:\(imageName) image:\(image)") // return image - } - - public class func ne_bundleImage(name: String) -> UIImage { - //图片放到 framework 的 bundle 中可使用 - let bundleName = "NIMKitEmoticon.bundle/Emoji/\(name)" - if let image = UIImage.ne_imageNamed(name: bundleName) { - return image - } - return UIImage() - } + } + class func ne_bundleImage(name: String) -> UIImage { + // 图片放到 framework 的 bundle 中可使用 + let bundleName = "NIMKitEmoticon.bundle/Emoji/\(name)" + if let image = UIImage.ne_imageNamed(name: bundleName) { + return image + } + return UIImage() + } } diff --git a/NEChatUIKit/NEKitChatUI/Classes/Extension/NEErrorExtension.swift b/NEChatUIKit/NEKitChatUI/Classes/Extension/NEErrorExtension.swift index 54c01e4a..25e9ae94 100644 --- a/NEChatUIKit/NEKitChatUI/Classes/Extension/NEErrorExtension.swift +++ b/NEChatUIKit/NEKitChatUI/Classes/Extension/NEErrorExtension.swift @@ -1,10 +1,15 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation extension NSError { - class func paramError() -> NSError { - return NSError(domain: "com.qchat.doamin", code: 600, userInfo: ["message":localizable("param_error")]) - } + class func paramError() -> NSError { + NSError( + domain: "com.qchat.doamin", + code: 600, + userInfo: ["message": localizable("param_error")] + ) + } } diff --git a/NEContactUIKit/NEKitContactUI.podspec b/NEContactUIKit/NEKitContactUI.podspec index 4d0f6a84..5517d963 100644 --- a/NEContactUIKit/NEKitContactUI.podspec +++ b/NEContactUIKit/NEKitContactUI.podspec @@ -8,7 +8,7 @@ Pod::Spec.new do |s| s.name = 'NEKitContactUI' - s.version = '9.2.6-rc01' + s.version = '9.2.7' s.summary = 'Netease XKit' # This description is used to generate tags and improve search results. @@ -24,7 +24,11 @@ Pod::Spec.new do |s| # s.source = { :git => 'https://github.com/chenyu-home/ContactKitUI.git', :tag => s.version.to_s } # s.social_media_url = 'https://twitter.com/' - + s.pod_target_xcconfig = { + 'BUILD_LIBRARY_FOR_DISTRIBUTION' => 'YES' + } + s.user_target_xcconfig = { 'BUILD_LIBRARY_FOR_DISTRIBUTION' => 'YES' } + s.ios.deployment_target = '9.0' s.source_files = 'NEKitContactUI/Classes/**/*' diff --git a/NEContactUIKit/NEKitContactUI/Assets/en.lproj/Localizable.strings b/NEContactUIKit/NEKitContactUI/Assets/en.lproj/Localizable.strings index 36c3ea25..a75d7def 100644 --- a/NEContactUIKit/NEKitContactUI/Assets/en.lproj/Localizable.strings +++ b/NEContactUIKit/NEKitContactUI/Assets/en.lproj/Localizable.strings @@ -1,10 +1,7 @@ -/* - YXLogin.strings - Pods - Created by yu chen on 2021/12/24. - -*/ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. "验证消息"="验证消息"; diff --git a/NEContactUIKit/NEKitContactUI/Assets/zh-Hans.lproj/Localizable.strings b/NEContactUIKit/NEKitContactUI/Assets/zh-Hans.lproj/Localizable.strings index 800cc18f..a6a97b9c 100644 --- a/NEContactUIKit/NEKitContactUI/Assets/zh-Hans.lproj/Localizable.strings +++ b/NEContactUIKit/NEKitContactUI/Assets/zh-Hans.lproj/Localizable.strings @@ -1,10 +1,7 @@ -/* - YXLogin.strings - Pods - Created by yu chen on 2021/12/24. - -*/ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. "验证消息"="验证消息"; diff --git a/NEContactUIKit/NEKitContactUI/Classes/Base/ContactBaseViewCell.swift b/NEContactUIKit/NEKitContactUI/Classes/Base/ContactBaseViewCell.swift index 4bf30c68..6cf4d695 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/Base/ContactBaseViewCell.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/Base/ContactBaseViewCell.swift @@ -1,83 +1,85 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit open class ContactBaseViewCell: UITableViewCell { - - public lazy var avatarImage: UIImageView = { - let avatar = UIImageView() - avatar.translatesAutoresizingMaskIntoConstraints = false - avatar.addSubview(nameLabel) - avatar.clipsToBounds = true - avatar.contentMode = .scaleAspectFill - avatar.backgroundColor = UIColor.colorWithNumber(number: 0) - NSLayoutConstraint.activate([ - nameLabel.leftAnchor.constraint(equalTo: avatar.leftAnchor, constant: 1), - nameLabel.rightAnchor.constraint(equalTo: avatar.rightAnchor, constant: -1), - nameLabel.centerXAnchor.constraint(equalTo: avatar.centerXAnchor), - nameLabel.centerYAnchor.constraint(equalTo: avatar.centerYAnchor) - ]) - return avatar - }() - - public lazy var nameLabel: UILabel = { - let name = UILabel() - name.translatesAutoresizingMaskIntoConstraints = false - name.textColor = .white - name.textAlignment = .center - name.font = UIFont.systemFont(ofSize: 14.0) - return name - }() - - public lazy var titleLabel: UILabel = { - let label = UILabel() - label.textAlignment = .left - label.translatesAutoresizingMaskIntoConstraints = false - label.font = UIFont.systemFont(ofSize: 14.0) - label.textColor = UIColor(hexString: "333333") - return label - }() - - var leftConstraint: NSLayoutConstraint? + public lazy var avatarImage: UIImageView = { + let avatar = UIImageView() + avatar.translatesAutoresizingMaskIntoConstraints = false + avatar.addSubview(nameLabel) + avatar.clipsToBounds = true + avatar.contentMode = .scaleAspectFill + avatar.backgroundColor = UIColor.colorWithNumber(number: 0) + NSLayoutConstraint.activate([ + nameLabel.leftAnchor.constraint(equalTo: avatar.leftAnchor, constant: 1), + nameLabel.rightAnchor.constraint(equalTo: avatar.rightAnchor, constant: -1), + nameLabel.centerXAnchor.constraint(equalTo: avatar.centerXAnchor), + nameLabel.centerYAnchor.constraint(equalTo: avatar.centerYAnchor), + ]) + return avatar + }() + + public lazy var nameLabel: UILabel = { + let name = UILabel() + name.translatesAutoresizingMaskIntoConstraints = false + name.textColor = .white + name.textAlignment = .center + name.font = UIFont.systemFont(ofSize: 14.0) + return name + }() + + public lazy var titleLabel: UILabel = { + let label = UILabel() + label.textAlignment = .left + label.translatesAutoresizingMaskIntoConstraints = false + label.font = UIFont.systemFont(ofSize: 14.0) + label.textColor = UIColor(hexString: "333333") + return label + }() + + var leftConstraint: NSLayoutConstraint? + + override public func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + + override public func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + } - public override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } + override public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + selectionStyle = .none + } - public override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) + public required init?(coder: NSCoder) { + super.init(coder: coder) + } - // Configure the view for the selected state - } - - public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - selectionStyle = .none - } - - required public init?(coder: NSCoder) { - super.init(coder: coder) - } - - func setupCommonCircleHeader(){ - avatarImage.layer.cornerRadius = 18 - avatarImage.translatesAutoresizingMaskIntoConstraints = false - contentView.addSubview(avatarImage) - leftConstraint = avatarImage.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 20) - leftConstraint?.isActive = true - NSLayoutConstraint.activate([ - avatarImage.widthAnchor.constraint(equalToConstant: 36), - avatarImage.heightAnchor.constraint(equalToConstant: 36), - avatarImage.centerYAnchor.constraint(equalTo: contentView.centerYAnchor, constant: 0) - ]) - } - - func showNameOnCircleHeader(_ name: String) { - nameLabel.text = name.count > 2 ? String(name[name.index(name.endIndex, offsetBy: -2)...]) : name - } + func setupCommonCircleHeader() { + avatarImage.layer.cornerRadius = 18 + avatarImage.translatesAutoresizingMaskIntoConstraints = false + contentView.addSubview(avatarImage) + leftConstraint = avatarImage.leftAnchor.constraint( + equalTo: contentView.leftAnchor, + constant: 20 + ) + leftConstraint?.isActive = true + NSLayoutConstraint.activate([ + avatarImage.widthAnchor.constraint(equalToConstant: 36), + avatarImage.heightAnchor.constraint(equalToConstant: 36), + avatarImage.centerYAnchor.constraint(equalTo: contentView.centerYAnchor, constant: 0), + ]) + } + func showNameOnCircleHeader(_ name: String) { + nameLabel.text = name + .count > 2 ? String(name[name.index(name.endIndex, offsetBy: -2)...]) : name + } } diff --git a/NEContactUIKit/NEKitContactUI/Classes/BlackList/ViewController/BlackListViewController.swift b/NEContactUIKit/NEKitContactUI/Classes/BlackList/ViewController/BlackListViewController.swift index b1e98280..4d6579d1 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/BlackList/ViewController/BlackListViewController.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/BlackList/ViewController/BlackListViewController.swift @@ -1,117 +1,138 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCoreIM import NEKitCommon -public class BlackListViewController: UIViewController, UITableViewDelegate, UITableViewDataSource,TeamTableViewCellDelegate { - var tableView = UITableView(frame: .zero, style: .plain) - var viewModel = BlackListViewModel() - public var blackList: [User]? - - public override func viewDidLoad() { - super.viewDidLoad() - commonUI() - loadData() - } - - func commonUI() { - self.title = "黑名单" - let image = UIImage.ne_imageNamed(name: "backArrow")?.withRenderingMode(.alwaysOriginal) - self.navigationItem.leftBarButtonItem = UIBarButtonItem(image: image, style: .plain, target: self, action: #selector(backEvent)) - let addImage = UIImage.ne_imageNamed(name: "add")?.withRenderingMode(.alwaysOriginal) - self.navigationItem.rightBarButtonItem = UIBarButtonItem(image: addImage, style: .plain, target: self, action: #selector(addBlack)) - - self.tableView.separatorStyle = .none - self.tableView.delegate = self - self.tableView.dataSource = self - self.tableView.translatesAutoresizingMaskIntoConstraints = false - self.view.addSubview(self.tableView) - NSLayoutConstraint.activate([ - self.tableView.topAnchor.constraint(equalTo: self.view.topAnchor), - self.tableView.leftAnchor.constraint(equalTo: self.view.leftAnchor), - self.tableView.rightAnchor.constraint(equalTo: self.view.rightAnchor), - self.tableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor), - ]) - self.tableView.register(BlackListCell.self, forCellReuseIdentifier: "\(NSStringFromClass(TeamTableViewCell.self))") - self.tableView.rowHeight = 62 - let headView = UIView.init(frame: CGRect.init(x: 0, y: 0, width: Int(NEConstant.screenWidth), height: 40)) - let contentLabel = UILabel.init(frame: CGRect.init(x: 20, y: 0, width: Int(NEConstant.screenWidth)-20, height: 40)) - contentLabel.text = " 你不会收到列表中任何联系人的消息" - contentLabel.textColor = UIColor.ne_emptyTitleColor - contentLabel.font = UIFont.systemFont(ofSize: 14) - headView.addSubview(contentLabel) - self.tableView.tableHeaderView = headView - } - - func loadData() { - blackList = viewModel.getBlackList() - self.tableView.reloadData() - } - - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return blackList?.count ?? 0 - } - - public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(withIdentifier: "\(NSStringFromClass(TeamTableViewCell.self))", for: indexPath) as! BlackListCell - cell.delegate = self - cell.index = indexPath.row - cell.setModel(blackList?[indexPath.row] as Any) - return cell - } - - @objc func backEvent() { - self.navigationController?.popViewController(animated: true) - } - - @objc func addBlack() { - let contactSelectVC = ContactsSelectedViewController() - self.navigationController?.pushViewController(contactSelectVC, animated: true) - contactSelectVC.callBack = {[weak self] selectMemberarray in - var users = [User]() - selectMemberarray.forEach { memberInfo in - if let u = memberInfo.user { - users.append(u) - } - } - return self?.addBlackUsers(users: users) - } - } - - func addBlackUsers(users: [User]) { - var num = users.count - var suc = [User]() - for user in users { - viewModel.addBlackList(account: user.userId ?? "") {[weak self] error in - if error == nil { - suc.append(user) - } - num = num - 1 - if num == 0 { - print("add black finished") - self?.blackList?.append(contentsOf: suc) - self?.tableView.reloadData() - } - } +public class BlackListViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, + TeamTableViewCellDelegate { + var tableView = UITableView(frame: .zero, style: .plain) + var viewModel = BlackListViewModel() + public var blackList: [User]? + + override public func viewDidLoad() { + super.viewDidLoad() + commonUI() + loadData() + } + + func commonUI() { + title = "黑名单" + let image = UIImage.ne_imageNamed(name: "backArrow")?.withRenderingMode(.alwaysOriginal) + navigationItem.leftBarButtonItem = UIBarButtonItem( + image: image, + style: .plain, + target: self, + action: #selector(backEvent) + ) + let addImage = UIImage.ne_imageNamed(name: "add")?.withRenderingMode(.alwaysOriginal) + navigationItem.rightBarButtonItem = UIBarButtonItem( + image: addImage, + style: .plain, + target: self, + action: #selector(addBlack) + ) + + tableView.separatorStyle = .none + tableView.delegate = self + tableView.dataSource = self + tableView.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(tableView) + NSLayoutConstraint.activate([ + tableView.topAnchor.constraint(equalTo: view.topAnchor), + tableView.leftAnchor.constraint(equalTo: view.leftAnchor), + tableView.rightAnchor.constraint(equalTo: view.rightAnchor), + tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), + ]) + tableView.register( + BlackListCell.self, + forCellReuseIdentifier: "\(NSStringFromClass(TeamTableViewCell.self))" + ) + tableView.rowHeight = 62 + let headView = + UIView(frame: CGRect(x: 0, y: 0, width: Int(NEConstant.screenWidth), height: 40)) + let contentLabel = + UILabel(frame: CGRect(x: 20, y: 0, width: Int(NEConstant.screenWidth) - 20, height: 40)) + contentLabel.text = " 你不会收到列表中任何联系人的消息" + contentLabel.textColor = UIColor.ne_emptyTitleColor + contentLabel.font = UIFont.systemFont(ofSize: 14) + headView.addSubview(contentLabel) + tableView.tableHeaderView = headView + } + + func loadData() { + blackList = viewModel.getBlackList() + tableView.reloadData() + } + + public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + blackList?.count ?? 0 + } + + public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(NSStringFromClass(TeamTableViewCell.self))", + for: indexPath + ) as! BlackListCell + cell.delegate = self + cell.index = indexPath.row + cell.setModel(blackList?[indexPath.row] as Any) + return cell + } + + @objc func backEvent() { + navigationController?.popViewController(animated: true) + } + + @objc func addBlack() { + let contactSelectVC = ContactsSelectedViewController() + navigationController?.pushViewController(contactSelectVC, animated: true) + contactSelectVC.callBack = { [weak self] selectMemberarray in + var users = [User]() + selectMemberarray.forEach { memberInfo in + if let u = memberInfo.user { + users.append(u) } + } + return self?.addBlackUsers(users: users) } - -//MARK:TeamTableViewCellDelegate - func removeUser(account: String?, index: Int) { - guard let acc = account else { - return + } + + func addBlackUsers(users: [User]) { + var num = users.count + var suc = [User]() + for user in users { + viewModel.addBlackList(account: user.userId ?? "") { [weak self] error in + if error == nil { + suc.append(user) } - viewModel.removeFromBlackList(account: acc) { error in - //1.当前页面刷新 - if error == nil { - self.blackList?.remove(at: index) - self.tableView.reloadData() - }else { - print("removeFromBlackList error:\(error!)"); - } + num = num - 1 + if num == 0 { + print("add black finished") + self?.blackList?.append(contentsOf: suc) + self?.tableView.reloadData() } + } + } + } + + // MARK: TeamTableViewCellDelegate + + func removeUser(account: String?, index: Int) { + guard let acc = account else { + return + } + viewModel.removeFromBlackList(account: acc) { error in + // 1.当前页面刷新 + if error == nil { + self.blackList?.remove(at: index) + self.tableView.reloadData() + } else { + print("removeFromBlackList error:\(error!)") + } } + } } diff --git a/NEContactUIKit/NEKitContactUI/Classes/BlackList/ViewModel/BlackListViewModel.swift b/NEContactUIKit/NEKitContactUI/Classes/BlackList/ViewModel/BlackListViewModel.swift index 26c81ddf..e9e6955f 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/BlackList/ViewModel/BlackListViewModel.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/BlackList/ViewModel/BlackListViewModel.swift @@ -1,47 +1,49 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NEKitContact import NEKitCoreIM public class BlackListViewModel: FriendProviderDelegate { - var contactRepo = ContactRepo() - init(){ - contactRepo.addContactDelegate(delegate: self) - } - func getBlackList() -> [User]? { - return contactRepo.getBlackList() - } - - func removeFromBlackList(account: String, _ completion: @escaping (NSError?)->()) { - contactRepo.removeBlackList(account: account, completion) - } - - func addBlackList(account: String, _ completion: @escaping (NSError?)->()) { - contactRepo.addBlackList(account: account, completion) - } - -//MARK: callback - public func onFriendChanged(user: User) { - print(#file + #function ) - } - - public func onUserInfoChanged(user: User) { - print(#file + #function) - } - - public func onBlackListChanged() { - print(#file + #function) - } - - public func onRecieveNotification(notification: XNotification) { - print(#file + #function) - } - - public func onNotificationUnreadCountChanged(count: Int) { - print(#file + #function) - } + var contactRepo = ContactRepo() + init() { + contactRepo.addContactDelegate(delegate: self) + } + + func getBlackList() -> [User]? { + contactRepo.getBlackList() + } + + func removeFromBlackList(account: String, _ completion: @escaping (NSError?) -> Void) { + contactRepo.removeBlackList(account: account, completion) + } + + func addBlackList(account: String, _ completion: @escaping (NSError?) -> Void) { + contactRepo.addBlackList(account: account, completion) + } + + // MARK: callback + + public func onFriendChanged(user: User) { + print(#file + #function) + } + + public func onUserInfoChanged(user: User) { + print(#file + #function) + } + + public func onBlackListChanged() { + print(#file + #function) + } + + public func onRecieveNotification(notification: XNotification) { + print(#file + #function) + } + + public func onNotificationUnreadCountChanged(count: Int) { + print(#file + #function) + } } diff --git a/NEContactUIKit/NEKitContactUI/Classes/BlackList/Views/BlackListCell.swift b/NEContactUIKit/NEKitContactUI/Classes/BlackList/Views/BlackListCell.swift index 68c89895..b5e4494a 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/BlackList/Views/BlackListCell.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/BlackList/Views/BlackListCell.swift @@ -1,95 +1,92 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCoreIM protocol TeamTableViewCellDelegate: AnyObject { - - func removeUser(account: String?, index: Int) + func removeUser(account: String?, index: Int) } class BlackListCell: TeamTableViewCell { - weak var delegate: TeamTableViewCellDelegate? - var index = 0 - private var model: User? - var button = UIButton() - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - self.commonUI() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") + weak var delegate: TeamTableViewCellDelegate? + var index = 0 + private var model: User? + var button = UIButton() + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + commonUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func commonUI() { + super.commonUI() + + button.layer.borderWidth = 1 + button.layer.borderColor = UIColor(red: 0.2, green: 0.494, blue: 1, alpha: 1).cgColor + button.layer.cornerRadius = 4 + button.setTitleColor(UIColor(red: 0.2, green: 0.494, blue: 1, alpha: 1), for: .normal) + button.titleLabel?.font = UIFont.systemFont(ofSize: 14) + button.translatesAutoresizingMaskIntoConstraints = false + button.contentMode = .center + button.clipsToBounds = true + button.addTarget(self, action: #selector(buttonEvent), for: .touchUpInside) + button.setTitle(localizable("remove_black"), for: .normal) + contentView.addSubview(button) + NSLayoutConstraint.activate([ + button.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), + button.widthAnchor.constraint(equalToConstant: 60), + button.heightAnchor.constraint(equalToConstant: 32), + button.centerYAnchor.constraint(equalTo: contentView.centerYAnchor, constant: 0), + ]) + + contentView.addSubview(bottomLine) + NSLayoutConstraint.activate([ + bottomLine.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20), + bottomLine.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), + bottomLine.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + bottomLine.heightAnchor.constraint(equalToConstant: 1), + ]) + } + + @objc func buttonEvent(sender: UIButton) { + delegate?.removeUser(account: model?.userId, index: index) + } + + override public func setModel(_ model: Any) { + guard let user = model as? User else { + return } - - override func commonUI() { - super.commonUI() - - self.button.layer.borderWidth = 1 - self.button.layer.borderColor = UIColor(red: 0.2, green: 0.494, blue: 1, alpha: 1).cgColor - self.button.layer.cornerRadius = 4 - self.button.setTitleColor(UIColor(red: 0.2, green: 0.494, blue: 1, alpha: 1), for: .normal) - self.button.titleLabel?.font = UIFont.systemFont(ofSize: 14) - self.button.translatesAutoresizingMaskIntoConstraints = false - self.button.contentMode = .center - self.button.clipsToBounds = true - self.button.addTarget(self, action: #selector(buttonEvent), for: .touchUpInside) - self.button.setTitle(localizable("remove_black"), for: .normal) - self.contentView.addSubview(self.button) - NSLayoutConstraint.activate([ - self.button.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -20), - self.button.widthAnchor.constraint(equalToConstant: 60), - self.button.heightAnchor.constraint(equalToConstant: 32), - self.button.centerYAnchor.constraint(equalTo: self.contentView.centerYAnchor, constant: 0) - ]) - - contentView.addSubview(bottomLine) - NSLayoutConstraint.activate([ - bottomLine.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20), - bottomLine.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), - bottomLine.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), - bottomLine.heightAnchor.constraint(equalToConstant: 1) - ]) + self.model = user + avatarImage.backgroundColor = UIColor.colorWithString(string: user.userId) + // title + var showName = user.alias?.count ?? 0 > 0 ? user.alias : user.userInfo?.nickName + if showName == nil || showName?.count == 0 { + showName = user.userId } - - @objc func buttonEvent(sender: UIButton) { - delegate?.removeUser(account: self.model?.userId, index: self.index) + if let name = showName { + titleLabel.text = name + if avatarImage.image == nil { + nameLabel.text = name + .count > 2 ? String(name[name.index(name.endIndex, offsetBy: -2)...]) : name + } } - - public override func setModel(_ model: Any) { - guard let user = model as? User else { - return - } - self.model = user - self.avatarImage.backgroundColor = UIColor.colorWithString(string: user.userId) - // title - var showName = user.alias?.count ?? 0 > 0 ? user.alias : user.userInfo?.nickName - if showName == nil || showName?.count == 0 { - showName = user.userId - } - if let name = showName { - self.titleLabel.text = name - if self.avatarImage.image == nil { - self.nameLabel.text = name.count > 2 ? String(name[name.index(name.endIndex, offsetBy: -2)...]) : name - } - } - // avatar - if let imageUrl = user.userInfo?.thumbAvatarUrl { - self.nameLabel.text = "" - self.avatarImage.sd_setImage(with: URL(string: imageUrl), completed: nil) - } - + // avatar + if let imageUrl = user.userInfo?.thumbAvatarUrl { + nameLabel.text = "" + avatarImage.sd_setImage(with: URL(string: imageUrl), completed: nil) } - - - private lazy var bottomLine:UIView = { - let view = UIView() - view.translatesAutoresizingMaskIntoConstraints = false - view.backgroundColor = UIColor.ne_greyLine - return view - }() + } + private lazy var bottomLine: UIView = { + let view = UIView() + view.translatesAutoresizingMaskIntoConstraints = false + view.backgroundColor = UIColor.ne_greyLine + return view + }() } diff --git a/NEContactUIKit/NEKitContactUI/Classes/Common/ContactCellDataProtrol.swift b/NEContactUIKit/NEKitContactUI/Classes/Common/ContactCellDataProtrol.swift index 0fe0fa62..3f9b8221 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/Common/ContactCellDataProtrol.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/Common/ContactCellDataProtrol.swift @@ -1,11 +1,11 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import UIKit public protocol ContactCellDataProtrol { - func setModel(_ model: ContactInfo) + func setModel(_ model: ContactInfo) } diff --git a/NEContactUIKit/NEKitContactUI/Classes/Common/ContactConst.swift b/NEContactUIKit/NEKitContactUI/Classes/Common/ContactConst.swift index 17912c7d..403ef485 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/Common/ContactConst.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/Common/ContactConst.swift @@ -1,27 +1,24 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import CoreText import NEKitCore - public enum ContactCellType: Int { - case ContactOthers = 1 // blacklist groups computer and so on - case ContactPerson = 2 // contact person - case ContactCutom = 50 // custom type start with 50 + case ContactOthers = 1 // blacklist groups computer and so on + case ContactPerson = 2 // contact person + case ContactCutom = 50 // custom type start with 50 } -public typealias ConttactClickCallBack = (_ index: Int, _ section: Int?) -> Void // parameter type contain ContactCellType and custom type - -public typealias ContactsSelectCompletion = ([ContactInfo])->()? +public typealias ConttactClickCallBack = (_ index: Int, _ section: Int?) + -> Void // parameter type contain ContactCellType and custom type +public typealias ContactsSelectCompletion = ([ContactInfo]) -> Void? let coreLoader = CoreLoader() -func localizable(_ key: String) -> String{ - return coreLoader.localizable(key) +func localizable(_ key: String) -> String { + coreLoader.localizable(key) } - - diff --git a/NEContactUIKit/NEKitContactUI/Classes/Common/ContactDataProtrol.swift b/NEContactUIKit/NEKitContactUI/Classes/Common/ContactDataProtrol.swift index dc798e2e..d362243b 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/Common/ContactDataProtrol.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/Common/ContactDataProtrol.swift @@ -1,10 +1,11 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation protocol ContactDataProtrol { - func getName() -> String - func getRowHeight() -> CGFloat? + func getName() -> String + func getRowHeight() -> CGFloat? } diff --git a/NEContactUIKit/NEKitContactUI/Classes/Common/ContactRouter.swift b/NEContactUIKit/NEKitContactUI/Classes/Common/ContactRouter.swift index 4e8b807b..a003a280 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/Common/ContactRouter.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/Common/ContactRouter.swift @@ -1,58 +1,56 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NEKitCore import NEKitCoreIM import NIMSDK -public struct ContactRouter { - public static func register() { - Router.shared.register(ContactUserSelectRouter) { param in - print("param:\(param)") - let nav = param["nav"] as? UINavigationController - let contactSelectVC = ContactsSelectedViewController() - if let fiters = param["filters"] as? Set { - contactSelectVC.filterUsers = fiters - } - if let limit = param["limit"] as? Int, limit > 0 { - contactSelectVC.limit = limit - } - nav?.pushViewController(contactSelectVC, animated: true) - } - - Router.shared.register(ContactAddFriendRouter) { param in - let nav = param["nav"] as? UINavigationController - let findFrined = FindFriendViewController() - nav?.pushViewController(findFrined, animated: true) - } - - Router.shared.register(ContactUserInfoPageRouter){ param in - if let nav = param["nav"] as? UINavigationController{ - if let user = param["user"] as? User { - let userInfoVC = ContactUserViewController(user: user) - nav.pushViewController(userInfoVC, animated: true) - }else if let nimUser = param["nim_user"] as? NIMUser { - let user = User(user: nimUser) - let userInfoVC = ContactUserViewController(user: user) - nav.pushViewController(userInfoVC, animated: true) - }else if let uid = param["uid"] as? String { - let userInfoVC = ContactUserViewController(uid: uid) - nav.pushViewController(userInfoVC, animated: true) - } - } - } - - Router.shared.register(ContactTeamListRouter) { param in - if let nav = param["nav"] as? UINavigationController { - let team = TeamListViewController() - team.isClickCallBack = true - nav.pushViewController(team, animated: true) - } +public enum ContactRouter { + public static func register() { + Router.shared.register(ContactUserSelectRouter) { param in + print("param:\(param)") + let nav = param["nav"] as? UINavigationController + let contactSelectVC = ContactsSelectedViewController() + if let fiters = param["filters"] as? Set { + contactSelectVC.filterUsers = fiters + } + if let limit = param["limit"] as? Int, limit > 0 { + contactSelectVC.limit = limit + } + nav?.pushViewController(contactSelectVC, animated: true) + } + + Router.shared.register(ContactAddFriendRouter) { param in + let nav = param["nav"] as? UINavigationController + let findFrined = FindFriendViewController() + nav?.pushViewController(findFrined, animated: true) + } + + Router.shared.register(ContactUserInfoPageRouter) { param in + if let nav = param["nav"] as? UINavigationController { + if let user = param["user"] as? User { + let userInfoVC = ContactUserViewController(user: user) + nav.pushViewController(userInfoVC, animated: true) + } else if let nimUser = param["nim_user"] as? NIMUser { + let user = User(user: nimUser) + let userInfoVC = ContactUserViewController(user: user) + nav.pushViewController(userInfoVC, animated: true) + } else if let uid = param["uid"] as? String { + let userInfoVC = ContactUserViewController(uid: uid) + nav.pushViewController(userInfoVC, animated: true) } - + } + } + + Router.shared.register(ContactTeamListRouter) { param in + if let nav = param["nav"] as? UINavigationController { + let team = TeamListViewController() + team.isClickCallBack = true + nav.pushViewController(team, animated: true) + } } - + } } diff --git a/NEContactUIKit/NEKitContactUI/Classes/ContactConfig/ContactUIConfig.swift b/NEContactUIKit/NEKitContactUI/Classes/ContactConfig/ContactUIConfig.swift index 2b931d5b..4fe540a7 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/ContactConfig/ContactUIConfig.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/ContactConfig/ContactUIConfig.swift @@ -1,41 +1,37 @@ -// -// ContactUIConfig.swift -// NEKitContactUI -// -// Created by vvj on 2022/6/13. -// + +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit /// 头像枚举类型 public enum NEContactAvatarType { - case rectangle //矩形 - case cycle //圆形 + case rectangle // 矩形 + case cycle // 圆形 } - public class ContactUIConfig: NSObject { + /// 头像圆角大小 + public var avatarCornerRadius = 4.0 + + /// 头像类型 + public var avatarType: NEContactAvatarType = .cycle + + // 通讯录标题大小 + public var titleFont = UIFont.systemFont(ofSize: 14) + + /// 通讯录标题颜色 + public var titleColor = UIColor.ne_darkText + + /// 是否隐藏通讯录搜索按钮 + public var hiddenSearchBtn = false + + /// 是否把顶部添加好友和搜索按钮都隐藏 + public var hiddenRightBtns = false + + /// 通讯录间隔线颜色 + public var divideLineColor = UIColor.ne_borderColor - /// 头像圆角大小 - public var avatarCornerRadius = 4.0 - - /// 头像类型 - public var avatarType:NEContactAvatarType = .cycle - - //通讯录标题大小 - public var titleFont = UIFont.systemFont(ofSize: 14) - - /// 通讯录标题颜色 - public var titleColor = UIColor.ne_darkText - - /// 是否隐藏通讯录搜索按钮 - public var hiddenSearchBtn = false - - /// 是否把顶部添加好友和搜索按钮都隐藏 - public var hiddenRightBtns = false - - /// 通讯录间隔线颜色 - public var divideLineColor = UIColor.ne_borderColor - - /// 检索标题字体颜色 - public var indexTitleColor = UIColor.ne_emptyTitleColor + /// 检索标题字体颜色 + public var indexTitleColor = UIColor.ne_emptyTitleColor } diff --git a/NEContactUIKit/NEKitContactUI/Classes/ContactConfig/NEKitContactConfig.swift b/NEContactUIKit/NEKitContactUI/Classes/ContactConfig/NEKitContactConfig.swift index d352eb14..5083ba6c 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/ContactConfig/NEKitContactConfig.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/ContactConfig/NEKitContactConfig.swift @@ -1,21 +1,14 @@ -// -// NEKitContactConfig.swift -// NEKitChatUI -// -// Created by vvj on 2022/6/15. -// + +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit @objcMembers public class NEKitContactConfig: NSObject { - - public static let shared = NEKitContactConfig() - - - //contact UI配置相关 - public var ui = ContactUIConfig() - - - + public static let shared = NEKitContactConfig() + + // contact UI配置相关 + public var ui = ContactUIConfig() } diff --git a/NEContactUIKit/NEKitContactUI/Classes/Extension/ContactUI.swift b/NEContactUIKit/NEKitContactUI/Classes/Extension/ContactUI.swift index 6d29991f..a117f69b 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/Extension/ContactUI.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/Extension/ContactUI.swift @@ -1,11 +1,10 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation @_exported import NEKitCommon @_exported import NEKitCommonUI @_exported import NIMSDK - diff --git a/NEContactUIKit/NEKitContactUI/Classes/Extension/ImageExtension.swift b/NEContactUIKit/NEKitContactUI/Classes/Extension/ImageExtension.swift index 4b84cc9f..d73cae60 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/Extension/ImageExtension.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/Extension/ImageExtension.swift @@ -1,20 +1,20 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation -extension UIImage { - public class func ne_imageNamed(name: String?) -> UIImage? { - guard let imageName = name else { - return nil - } - return coreLoader.loadImage(imageName) +public extension UIImage { + class func ne_imageNamed(name: String?) -> UIImage? { + guard let imageName = name else { + return nil + } + return coreLoader.loadImage(imageName) // guard let path = Bundle(for: ContactsViewController.self).resourcePath?.appending("/ContactKit_UIBundle.bundle") else { // print("Image:\(imageName) path: nil") // return nil // } // var bundle = Bundle(path: path) // return UIImage(named: imageName, in: bundle, compatibleWith: nil) - } + } } diff --git a/NEContactUIKit/NEKitContactUI/Classes/Extension/UIViewController.swift b/NEContactUIKit/NEKitContactUI/Classes/Extension/UIViewController.swift index 194dd15c..ea185d43 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/Extension/UIViewController.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/Extension/UIViewController.swift @@ -1,25 +1,32 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation extension UIViewController { - typealias AlertCallBack = () -> Void - func showAlert(title: String = localizable("alert_tip"), message: String?, sureText: String = localizable("alert_sure"), cancelText: String = localizable("alert_cancel"), _ sureBack: @escaping AlertCallBack, cancelBack: AlertCallBack? = nil ) { - let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert) - - let cancelAction = UIAlertAction(title: cancelText, style: .default) { action in - if let block = cancelBack { - block() - } - } - alertController.addAction(cancelAction) - let sureAction = UIAlertAction(title: sureText, style: .default) { action in - sureBack() - } - alertController.addAction(sureAction) - present(alertController, animated: true, completion: nil) + typealias AlertCallBack = () -> Void + func showAlert(title: String = localizable("alert_tip"), message: String?, + sureText: String = localizable("alert_sure"), + cancelText: String = localizable("alert_cancel"), + _ sureBack: @escaping AlertCallBack, cancelBack: AlertCallBack? = nil) { + let alertController = UIAlertController( + title: title, + message: message, + preferredStyle: .alert + ) + + let cancelAction = UIAlertAction(title: cancelText, style: .default) { action in + if let block = cancelBack { + block() + } + } + alertController.addAction(cancelAction) + let sureAction = UIAlertAction(title: sureText, style: .default) { action in + sureBack() } + alertController.addAction(sureAction) + present(alertController, animated: true, completion: nil) + } } diff --git a/NEContactUIKit/NEKitContactUI/Classes/Model/ContactInfo.swift b/NEContactUIKit/NEKitContactUI/Classes/Model/ContactInfo.swift index c8ebb376..4369ef9a 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/Model/ContactInfo.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/Model/ContactInfo.swift @@ -1,7 +1,7 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NEKitCoreIM @@ -9,12 +9,13 @@ import UIKit import NEKitCore public class ContactInfo { - func getRowHeight() -> CGFloat? { - return nil - } - public var user: User? - public var contactCellType = ContactCellType.ContactPerson.rawValue - public var router = ContactPersonRouter - public var isSelected = false - public var headerBackColor: UIColor? + func getRowHeight() -> CGFloat? { + nil + } + + public var user: User? + public var contactCellType = ContactCellType.ContactPerson.rawValue + public var router = ContactPersonRouter + public var isSelected = false + public var headerBackColor: UIColor? } diff --git a/NEContactUIKit/NEKitContactUI/Classes/Model/ContactSection.swift b/NEContactUIKit/NEKitContactUI/Classes/Model/ContactSection.swift index 24664d55..779f3a5a 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/Model/ContactSection.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/Model/ContactSection.swift @@ -1,18 +1,17 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NEKitContact import NEKitCoreIM public class ContactSection { - public var initial: String - public var contacts: Array = [ContactInfo]() - init(initial: String, contacts: [ContactInfo]) { - self.initial = initial - self.contacts = contacts - } - + public var initial: String + public var contacts: Array = [ContactInfo]() + init(initial: String, contacts: [ContactInfo]) { + self.initial = initial + self.contacts = contacts + } } diff --git a/NEContactUIKit/NEKitContactUI/Classes/Team/ViewController/TeamListViewController.swift b/NEContactUIKit/NEKitContactUI/Classes/Team/ViewController/TeamListViewController.swift index df48c801..e7478f9f 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/Team/ViewController/TeamListViewController.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/Team/ViewController/TeamListViewController.swift @@ -1,75 +1,92 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NIMSDK import NEKitCore public class TeamListViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { - var tableView = UITableView(frame: .zero, style: .plain) - var viewModel = TeamListViewModel() - var isClickCallBack = false - - public override func viewDidLoad() { - super.viewDidLoad() - commonUI() - loadData() - } - - func commonUI() { - self.title = "我的群聊" - let image = UIImage.ne_imageNamed(name: "backArrow")?.withRenderingMode(.alwaysOriginal) - self.navigationItem.leftBarButtonItem = UIBarButtonItem(image: image, style: .plain, target: self, action: #selector(backEvent)) - self.tableView.separatorStyle = .none - self.tableView.delegate = self - self.tableView.dataSource = self - self.tableView.translatesAutoresizingMaskIntoConstraints = false - self.view.addSubview(self.tableView) - NSLayoutConstraint.activate([ - self.tableView.topAnchor.constraint(equalTo: self.view.topAnchor), - self.tableView.leftAnchor.constraint(equalTo: self.view.leftAnchor), - self.tableView.rightAnchor.constraint(equalTo: self.view.rightAnchor), - self.tableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor), - ]) - self.tableView.register(TeamTableViewCell.self, forCellReuseIdentifier: "\(NSStringFromClass(TeamTableViewCell.self))") - self.tableView.rowHeight = 62 - self.tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.1)) - } - - func loadData() { - viewModel.getTeamList() - self.tableView.reloadData() - - } - - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return viewModel.teamList.count - } - - public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(withIdentifier: "\(NSStringFromClass(TeamTableViewCell.self))", for: indexPath) as! TeamTableViewCell - cell.setModel(viewModel.teamList[indexPath.row]) - return cell - } - - public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - let model = viewModel.teamList[indexPath.row] - if isClickCallBack == true { - Router.shared.use(ContactTeamDataRouter, parameters: ["team": model.nimTeam as Any], closure: nil) - navigationController?.popViewController(animated: true) - return - } - if let teamid = model.teamId { - let session = NIMSession(teamid, type: .team) - Router.shared.use(PushTeamChatVCRouter, parameters: ["nav": navigationController as Any, "session" : session as Any], closure: nil) - } - + var tableView = UITableView(frame: .zero, style: .plain) + var viewModel = TeamListViewModel() + var isClickCallBack = false + + override public func viewDidLoad() { + super.viewDidLoad() + commonUI() + loadData() + } + + func commonUI() { + title = "我的群聊" + let image = UIImage.ne_imageNamed(name: "backArrow")?.withRenderingMode(.alwaysOriginal) + navigationItem.leftBarButtonItem = UIBarButtonItem( + image: image, + style: .plain, + target: self, + action: #selector(backEvent) + ) + tableView.separatorStyle = .none + tableView.delegate = self + tableView.dataSource = self + tableView.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(tableView) + NSLayoutConstraint.activate([ + tableView.topAnchor.constraint(equalTo: view.topAnchor), + tableView.leftAnchor.constraint(equalTo: view.leftAnchor), + tableView.rightAnchor.constraint(equalTo: view.rightAnchor), + tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), + ]) + tableView.register( + TeamTableViewCell.self, + forCellReuseIdentifier: "\(NSStringFromClass(TeamTableViewCell.self))" + ) + tableView.rowHeight = 62 + tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.1)) + } + + func loadData() { + viewModel.getTeamList() + tableView.reloadData() + } + + public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + viewModel.teamList.count + } + + public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(NSStringFromClass(TeamTableViewCell.self))", + for: indexPath + ) as! TeamTableViewCell + cell.setModel(viewModel.teamList[indexPath.row]) + return cell + } + + public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + let model = viewModel.teamList[indexPath.row] + if isClickCallBack == true { + Router.shared.use( + ContactTeamDataRouter, + parameters: ["team": model.nimTeam as Any], + closure: nil + ) + navigationController?.popViewController(animated: true) + return } - - @objc func backEvent() { - self.navigationController?.popViewController(animated: true) + if let teamid = model.teamId { + let session = NIMSession(teamid, type: .team) + Router.shared.use( + PushTeamChatVCRouter, + parameters: ["nav": navigationController as Any, "session": session as Any], + closure: nil + ) } + } + @objc func backEvent() { + navigationController?.popViewController(animated: true) + } } diff --git a/NEContactUIKit/NEKitContactUI/Classes/Team/ViewModel/TeamListViewModel.swift b/NEContactUIKit/NEKitContactUI/Classes/Team/ViewModel/TeamListViewModel.swift index 295a832c..cd26b55a 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/Team/ViewModel/TeamListViewModel.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/Team/ViewModel/TeamListViewModel.swift @@ -1,17 +1,17 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NEKitContact import NEKitCoreIM public class TeamListViewModel { - var contactRepo = ContactRepo() - public var teamList = [Team]() - func getTeamList() -> [Team]? { - teamList = contactRepo.getTeamList() - return teamList - } + var contactRepo = ContactRepo() + public var teamList = [Team]() + func getTeamList() -> [Team]? { + teamList = contactRepo.getTeamList() + return teamList + } } diff --git a/NEContactUIKit/NEKitContactUI/Classes/Team/Views/TeamTableViewCell.swift b/NEContactUIKit/NEKitContactUI/Classes/Team/Views/TeamTableViewCell.swift index 5c70e8f0..04ed482d 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/Team/Views/TeamTableViewCell.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/Team/Views/TeamTableViewCell.swift @@ -1,63 +1,68 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCoreIM class TeamTableViewCell: UITableViewCell { - public var avatarImage = UIImageView() - public var nameLabel = UILabel() - public var titleLabel = UILabel() + public var avatarImage = UIImageView() + public var nameLabel = UILabel() + public var titleLabel = UILabel() // public var arrow = UIImageView(image:UIImage.ne_imageNamed(name: "arrowRight")) - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - self.commonUI() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func commonUI() { - self.selectionStyle = .none - self.avatarImage.backgroundColor = UIColor.colorWithNumber(number: 0) - self.avatarImage.layer.cornerRadius = 21 - self.avatarImage.translatesAutoresizingMaskIntoConstraints = false - self.avatarImage.clipsToBounds = true - self.contentView.addSubview(self.avatarImage) - NSLayoutConstraint.activate([ - self.avatarImage.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 20), - self.avatarImage.widthAnchor.constraint(equalToConstant: 42), - self.avatarImage.heightAnchor.constraint(equalToConstant: 42), - self.avatarImage.centerYAnchor.constraint(equalTo: self.contentView.centerYAnchor, constant: 0) - ]) - - self.nameLabel.textAlignment = .center - self.nameLabel.font = UIFont.systemFont(ofSize: 16) - self.nameLabel.textColor = .white - self.nameLabel.translatesAutoresizingMaskIntoConstraints = false - self.contentView.addSubview(self.nameLabel) - NSLayoutConstraint.activate([ - self.nameLabel.leftAnchor.constraint(equalTo: self.avatarImage.leftAnchor), - self.nameLabel.rightAnchor.constraint(equalTo: self.avatarImage.rightAnchor), - self.nameLabel.topAnchor.constraint(equalTo: self.avatarImage.topAnchor), - self.nameLabel.bottomAnchor.constraint(equalTo: self.avatarImage.bottomAnchor), - ]) - - self.titleLabel.translatesAutoresizingMaskIntoConstraints = false - self.titleLabel.font = UIFont.systemFont(ofSize: 16) - self.titleLabel.textColor = UIColor(red: 51/255.0, green: 51/255.0, blue: 51/255.0, alpha: 1.0) - self.contentView.addSubview(self.titleLabel) - NSLayoutConstraint.activate([ - self.titleLabel.leftAnchor.constraint(equalTo: self.avatarImage.rightAnchor, constant: 12), - self.titleLabel.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -35), - self.titleLabel.topAnchor.constraint(equalTo: self.contentView.topAnchor), - self.titleLabel.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor) - ]) - + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + commonUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func commonUI() { + selectionStyle = .none + avatarImage.backgroundColor = UIColor.colorWithNumber(number: 0) + avatarImage.layer.cornerRadius = 21 + avatarImage.translatesAutoresizingMaskIntoConstraints = false + avatarImage.clipsToBounds = true + contentView.addSubview(avatarImage) + NSLayoutConstraint.activate([ + avatarImage.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20), + avatarImage.widthAnchor.constraint(equalToConstant: 42), + avatarImage.heightAnchor.constraint(equalToConstant: 42), + avatarImage.centerYAnchor.constraint(equalTo: contentView.centerYAnchor, constant: 0), + ]) + + nameLabel.textAlignment = .center + nameLabel.font = UIFont.systemFont(ofSize: 16) + nameLabel.textColor = .white + nameLabel.translatesAutoresizingMaskIntoConstraints = false + contentView.addSubview(nameLabel) + NSLayoutConstraint.activate([ + nameLabel.leftAnchor.constraint(equalTo: avatarImage.leftAnchor), + nameLabel.rightAnchor.constraint(equalTo: avatarImage.rightAnchor), + nameLabel.topAnchor.constraint(equalTo: avatarImage.topAnchor), + nameLabel.bottomAnchor.constraint(equalTo: avatarImage.bottomAnchor), + ]) + + titleLabel.translatesAutoresizingMaskIntoConstraints = false + titleLabel.font = UIFont.systemFont(ofSize: 16) + titleLabel.textColor = UIColor( + red: 51 / 255.0, + green: 51 / 255.0, + blue: 51 / 255.0, + alpha: 1.0 + ) + contentView.addSubview(titleLabel) + NSLayoutConstraint.activate([ + titleLabel.leftAnchor.constraint(equalTo: avatarImage.rightAnchor, constant: 12), + titleLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -35), + titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor), + titleLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + ]) + // self.arrow.translatesAutoresizingMaskIntoConstraints = false // self.arrow.isHidden = true // self.arrow.contentMode = .center @@ -68,33 +73,32 @@ class TeamTableViewCell: UITableViewCell { // self.arrow.topAnchor.constraint(equalTo: self.contentView.topAnchor), // self.arrow.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor) // ]) - + } + + public func setModel(_ model: Any) { + guard let team = model as? Team else { + return + } + guard let name = team.teamName else { + return } - public func setModel(_ model: Any) { - guard let team = model as? Team else { - return - } - guard let name = team.teamName else { - return - } - self.titleLabel.text = name + titleLabel.text = name // self.nameLabel.text = name.count > 2 ? String(name[name.index(name.endIndex, offsetBy: -2)...]) : name - if let url = team.thumbAvatarUrl { - self.avatarImage.sd_setImage(with: URL(string: url), completed: nil) - }else { - // random avatar - self.avatarImage.image = randomAvatar(teamId: team.teamId) - } + if let url = team.thumbAvatarUrl { + avatarImage.sd_setImage(with: URL(string: url), completed: nil) + } else { + // random avatar + avatarImage.image = randomAvatar(teamId: team.teamId) } - - private func randomAvatar(teamId: String?) -> UIImage? { - guard let tid = teamId else { - return nil - } - // mod: 0 1 2 3 4 - let mod = Int(tid) ?? 0 % 5 - let name = "icon_" + String(mod) - return UIImage.ne_imageNamed(name: name) + } + + private func randomAvatar(teamId: String?) -> UIImage? { + guard let tid = teamId else { + return nil } - + // mod: 0 1 2 3 4 + let mod = Int(tid) ?? 0 % 5 + let name = "icon_" + String(mod) + return UIImage.ne_imageNamed(name: name) + } } diff --git a/NEContactUIKit/NEKitContactUI/Classes/UserInfo/Models/UserItem.swift b/NEContactUIKit/NEKitContactUI/Classes/UserInfo/Models/UserItem.swift index 95dcd9f5..23b76c4e 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/UserInfo/Models/UserItem.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/UserInfo/Models/UserItem.swift @@ -1,15 +1,14 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation struct UserItem { - var title = "" - var detailTitle: String? - var value = false - var textColor = UIColor.darkText - var cellClass = UITableViewCell.self - + var title = "" + var detailTitle: String? + var value = false + var textColor = UIColor.darkText + var cellClass = UITableViewCell.self } diff --git a/NEContactUIKit/NEKitContactUI/Classes/UserInfo/UserInfoHeaderView.swift b/NEContactUIKit/NEKitContactUI/Classes/UserInfo/UserInfoHeaderView.swift index 2267043c..a5f16f28 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/UserInfo/UserInfoHeaderView.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/UserInfo/UserInfoHeaderView.swift @@ -1,94 +1,94 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCoreIM import SDWebImage - class UserInfoHeaderView: UIView { - public var avatarImage = UIImageView() - public var nameLabel = UILabel() - public var titleLabel = UILabel() - public var detailLabel = UILabel() - override init(frame: CGRect) { - super.init(frame: frame) - self.backgroundColor = .white - self.avatarImage.layer.cornerRadius = 30 - self.avatarImage.backgroundColor = UIColor(hexString: "#537FF4") - self.avatarImage.translatesAutoresizingMaskIntoConstraints = false - self.avatarImage.contentMode = .scaleAspectFill - self.avatarImage.clipsToBounds = true - self.addSubview(self.avatarImage) - NSLayoutConstraint.activate([ - self.avatarImage.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 20), - self.avatarImage.widthAnchor.constraint(equalToConstant: 60), - self.avatarImage.heightAnchor.constraint(equalToConstant: 60), - self.avatarImage.centerYAnchor.constraint(equalTo: self.centerYAnchor, constant: 0) - ]) - - self.nameLabel.textAlignment = .center - self.nameLabel.translatesAutoresizingMaskIntoConstraints = false - self.nameLabel.font = UIFont.systemFont(ofSize: 22) - self.nameLabel.textColor = .white - self.addSubview(self.nameLabel) - NSLayoutConstraint.activate([ - self.nameLabel.leftAnchor.constraint(equalTo: self.avatarImage.leftAnchor), - self.nameLabel.rightAnchor.constraint(equalTo: self.avatarImage.rightAnchor), - self.nameLabel.topAnchor.constraint(equalTo: self.avatarImage.topAnchor), - self.nameLabel.bottomAnchor.constraint(equalTo: self.avatarImage.bottomAnchor), - ]) - - self.titleLabel.translatesAutoresizingMaskIntoConstraints = false - self.titleLabel.font = UIFont.boldSystemFont(ofSize: 22) - self.titleLabel.textColor = UIColor(red: 0.2, green: 0.2, blue: 0.2, alpha: 1.0) - self.addSubview(self.titleLabel) - NSLayoutConstraint.activate([ - self.titleLabel.leftAnchor.constraint(equalTo: self.avatarImage.rightAnchor, constant: 20), - self.titleLabel.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -35), - self.titleLabel.topAnchor.constraint(equalTo: self.avatarImage.topAnchor), - self.titleLabel.heightAnchor.constraint(equalToConstant: 25) - ]) - - self.detailLabel.translatesAutoresizingMaskIntoConstraints = false - self.detailLabel.font = UIFont.boldSystemFont(ofSize: 16) - self.detailLabel.textColor = UIColor(red: 0.2, green: 0.2, blue: 0.2, alpha: 1.0) - self.addSubview(self.detailLabel) - NSLayoutConstraint.activate([ - self.detailLabel.leftAnchor.constraint(equalTo: self.titleLabel.leftAnchor), - self.detailLabel.rightAnchor.constraint(equalTo: self.titleLabel.rightAnchor), - self.detailLabel.topAnchor.constraint(equalTo: self.titleLabel.bottomAnchor,constant: 8), - self.detailLabel.heightAnchor.constraint(equalToConstant: 22) - ]) + public var avatarImage = UIImageView() + public var nameLabel = UILabel() + public var titleLabel = UILabel() + public var detailLabel = UILabel() + override init(frame: CGRect) { + super.init(frame: frame) + backgroundColor = .white + avatarImage.layer.cornerRadius = 30 + avatarImage.backgroundColor = UIColor(hexString: "#537FF4") + avatarImage.translatesAutoresizingMaskIntoConstraints = false + avatarImage.contentMode = .scaleAspectFill + avatarImage.clipsToBounds = true + addSubview(avatarImage) + NSLayoutConstraint.activate([ + avatarImage.leftAnchor.constraint(equalTo: leftAnchor, constant: 20), + avatarImage.widthAnchor.constraint(equalToConstant: 60), + avatarImage.heightAnchor.constraint(equalToConstant: 60), + avatarImage.centerYAnchor.constraint(equalTo: centerYAnchor, constant: 0), + ]) + + nameLabel.textAlignment = .center + nameLabel.translatesAutoresizingMaskIntoConstraints = false + nameLabel.font = UIFont.systemFont(ofSize: 22) + nameLabel.textColor = .white + addSubview(nameLabel) + NSLayoutConstraint.activate([ + nameLabel.leftAnchor.constraint(equalTo: avatarImage.leftAnchor), + nameLabel.rightAnchor.constraint(equalTo: avatarImage.rightAnchor), + nameLabel.topAnchor.constraint(equalTo: avatarImage.topAnchor), + nameLabel.bottomAnchor.constraint(equalTo: avatarImage.bottomAnchor), + ]) + + titleLabel.translatesAutoresizingMaskIntoConstraints = false + titleLabel.font = UIFont.boldSystemFont(ofSize: 22) + titleLabel.textColor = UIColor(red: 0.2, green: 0.2, blue: 0.2, alpha: 1.0) + addSubview(titleLabel) + NSLayoutConstraint.activate([ + titleLabel.leftAnchor.constraint(equalTo: avatarImage.rightAnchor, constant: 20), + titleLabel.rightAnchor.constraint(equalTo: rightAnchor, constant: -35), + titleLabel.topAnchor.constraint(equalTo: avatarImage.topAnchor), + titleLabel.heightAnchor.constraint(equalToConstant: 25), + ]) + + detailLabel.translatesAutoresizingMaskIntoConstraints = false + detailLabel.font = UIFont.boldSystemFont(ofSize: 16) + detailLabel.textColor = UIColor(red: 0.2, green: 0.2, blue: 0.2, alpha: 1.0) + addSubview(detailLabel) + NSLayoutConstraint.activate([ + detailLabel.leftAnchor.constraint(equalTo: titleLabel.leftAnchor), + detailLabel.rightAnchor.constraint(equalTo: titleLabel.rightAnchor), + detailLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 8), + detailLabel.heightAnchor.constraint(equalToConstant: 22), + ]) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + public func setData(user: User?) { + guard let user = user else { + return + } + avatarImage.backgroundColor = UIColor.colorWithString(string: user.userId) + // avatar + if let imageUrl = user.userInfo?.thumbAvatarUrl { + avatarImage.sd_setImage(with: URL(string: imageUrl), completed: nil) + nameLabel.isHidden = true } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") + detailLabel.text = user.userId + // title + var showName = user.alias?.count ?? 0 > 0 ? user.alias : user.userInfo?.nickName + if showName == nil || showName?.count == 0 { + showName = user.userId } - - public func setData(user: User?) { - guard let user = user else { - return - } - self.avatarImage.backgroundColor = UIColor.colorWithString(string: user.userId) - // avatar - if let imageUrl = user.userInfo?.thumbAvatarUrl { - self.avatarImage.sd_setImage(with: URL(string: imageUrl), completed: nil) - self.nameLabel.isHidden = true - } - self.detailLabel.text = user.userId - // title - var showName = user.alias?.count ?? 0 > 0 ? user.alias : user.userInfo?.nickName - if showName == nil || showName?.count == 0 { - showName = user.userId - } - if let name = showName { - self.titleLabel.text = name - if self.avatarImage.image == nil { - self.nameLabel.text = name.count > 2 ? String(name[name.index(name.endIndex, offsetBy: -2)...]) : name - } - } + if let name = showName { + titleLabel.text = name + if avatarImage.image == nil { + nameLabel.text = name + .count > 2 ? String(name[name.index(name.endIndex, offsetBy: -2)...]) : name + } } + } } diff --git a/NEContactUIKit/NEKitContactUI/Classes/UserInfo/ViewController/ContactRemakNameViewController.swift b/NEContactUIKit/NEKitContactUI/Classes/UserInfo/ViewController/ContactRemakNameViewController.swift index d1c589e6..a3188ed2 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/UserInfo/ViewController/ContactRemakNameViewController.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/UserInfo/ViewController/ContactRemakNameViewController.swift @@ -1,26 +1,23 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCoreIM import NEKitCore public class ContactRemakNameViewController: ContactBaseViewController, UITextFieldDelegate { - - typealias ModifyBlock = (_ user: User) -> Void - - var completion: ModifyBlock? - - var user: User? - - let viewmodel = ContactUserViewModel() - - lazy var aliasInput: UITextField = { - return getInput() - }() - + typealias ModifyBlock = (_ user: User) -> Void + + var completion: ModifyBlock? + + var user: User? + + let viewmodel = ContactUserViewModel() + + lazy var aliasInput: UITextField = getInput() + // lazy var rightBtn: ExpandButton = { // let btn = ExpandButton(frame: CGRect(x: 0, y: 0, width: 60, height: 44)) // btn.setTitleColor(UIColor(hexString: "#337EFF"), for: .normal) @@ -29,90 +26,97 @@ public class ContactRemakNameViewController: ContactBaseViewController, UITextFi // return btn // }() - public override func viewDidLoad() { - super.viewDidLoad() + override public func viewDidLoad() { + super.viewDidLoad() - // Do any additional setup after loading the view. - - setupUI() - } - - func setupUI(){ - - view.backgroundColor = UIColor(hexString: "F2F4F5") - let clearItem = UIBarButtonItem(title: "保存", style: .done, target: self, action: #selector(saveAlias)) - clearItem.tintColor = UIColor(hexString: "337EFF") - navigationItem.rightBarButtonItem = clearItem - self.title = localizable("备注名") - view.addSubview(aliasInput) - aliasInput.placeholder = "输入备注名" - NSLayoutConstraint.activate([ - aliasInput.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20), - aliasInput.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20), - aliasInput.topAnchor.constraint(equalTo: view.topAnchor, constant: 10), - aliasInput.heightAnchor.constraint(equalToConstant: 50) - ]) - if let alias = user?.alias { - aliasInput.text = alias - } - } - - - func getInput() -> UITextField { - let textField = UITextField() - textField.backgroundColor = .white - textField.clipsToBounds = true - textField.layer.cornerRadius = 8 - textField.font = UIFont.systemFont(ofSize: 16.0) - textField.translatesAutoresizingMaskIntoConstraints = false - let leftSpace = UIView(frame: CGRect(x: 0, y: 0, width: 16, height: 0)) - textField.leftView = leftSpace - textField.leftViewMode = .always - textField.delegate = self - textField.clearButtonMode = .whileEditing - return textField + // Do any additional setup after loading the view. + + setupUI() + } + + func setupUI() { + view.backgroundColor = UIColor(hexString: "F2F4F5") + let clearItem = UIBarButtonItem( + title: "保存", + style: .done, + target: self, + action: #selector(saveAlias) + ) + clearItem.tintColor = UIColor(hexString: "337EFF") + navigationItem.rightBarButtonItem = clearItem + title = localizable("备注名") + view.addSubview(aliasInput) + aliasInput.placeholder = "输入备注名" + NSLayoutConstraint.activate([ + aliasInput.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20), + aliasInput.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20), + aliasInput.topAnchor.constraint(equalTo: view.topAnchor, constant: 10), + aliasInput.heightAnchor.constraint(equalToConstant: 50), + ]) + if let alias = user?.alias { + aliasInput.text = alias } - - @objc func saveAlias(){ + } + + func getInput() -> UITextField { + let textField = UITextField() + textField.backgroundColor = .white + textField.clipsToBounds = true + textField.layer.cornerRadius = 8 + textField.font = UIFont.systemFont(ofSize: 16.0) + textField.translatesAutoresizingMaskIntoConstraints = false + let leftSpace = UIView(frame: CGRect(x: 0, y: 0, width: 16, height: 0)) + textField.leftView = leftSpace + textField.leftViewMode = .always + textField.delegate = self + textField.clearButtonMode = .whileEditing + return textField + } + + @objc func saveAlias() { // guard let alais = aliasInput.text, alais.count > 0 else { // view.makeToast("请填写备注名", duration: 2, position: .center) // return // } - user?.alias = aliasInput.text - if let u = user { - view.makeToastActivity(.center) - weak var weakSelf = self - viewmodel.update(u) { error in - weakSelf?.view.hideToastActivity() - if let err = error { - weakSelf?.view.makeToast(err.localizedDescription, duration: 2, position: .center) - }else { - if let block = weakSelf?.completion { - block(u) - } - weakSelf?.navigationController?.popViewController(animated: true) - } - } + user?.alias = aliasInput.text + if let u = user { + view.makeToastActivity(.center) + weak var weakSelf = self + viewmodel.update(u) { error in + weakSelf?.view.hideToastActivity() + if let err = error { + weakSelf?.view.makeToast( + err.localizedDescription, + duration: 2, + position: .center + ) + } else { + if let block = weakSelf?.completion { + block(u) + } + weakSelf?.navigationController?.popViewController(animated: true) } + } } + } - /* - // MARK: - Navigation + /* + // MARK: - Navigation - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. - } - */ - - public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { - let text = "\(textField.text ?? "")\(string)" - print("text count : ", text.count) - if text.count > 30 { - return false - } - return true - } + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ + public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, + replacementString string: String) -> Bool { + let text = "\(textField.text ?? "")\(string)" + print("text count : ", text.count) + if text.count > 30 { + return false + } + return true + } } diff --git a/NEContactUIKit/NEKitContactUI/Classes/UserInfo/ViewController/ContactUserViewController.swift b/NEContactUIKit/NEKitContactUI/Classes/UserInfo/ViewController/ContactUserViewController.swift index a6d31169..057ca4da 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/UserInfo/ViewController/ContactUserViewController.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/UserInfo/ViewController/ContactUserViewController.swift @@ -1,264 +1,320 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCoreIM import NEKitCore import NIMSDK -public class ContactUserViewController: ContactBaseViewController, UITableViewDelegate, UITableViewDataSource { - private var user: User? - private var uid: String? - public var isBlack: Bool = false - - let viewModel = ContactUserViewModel() - var tableView = UITableView(frame: .zero, style: .grouped) - var data = [[UserItem]]() - var headerView: UserInfoHeaderView? - +public class ContactUserViewController: ContactBaseViewController, UITableViewDelegate, + UITableViewDataSource { + private var user: User? + private var uid: String? + public var isBlack: Bool = false - init(user:User?) { - super.init(nibName: nil, bundle: nil) - self.user = user - } - - init(uid: String){ - super.init(nibName: nil, bundle: nil) - self.uid = uid + let viewModel = ContactUserViewModel() + var tableView = UITableView(frame: .zero, style: .grouped) + var data = [[UserItem]]() + var headerView: UserInfoHeaderView? + + init(user: User?) { + super.init(nibName: nil, bundle: nil) + self.user = user + } + + init(uid: String) { + super.init(nibName: nil, bundle: nil) + self.uid = uid + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override public func viewDidLoad() { + super.viewDidLoad() + if user != nil { + commonUI() + loadData() + } else if let userId = uid { + weak var weakSelf = self + viewModel.getUserInfo(userId) { error, user in + if let err = error { + weakSelf?.showToast(err.localizedDescription) + } else if let u = user { + weakSelf?.user = u + weakSelf?.commonUI() + weakSelf?.loadData() + } + } } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") + } + + func commonUI() { + tableView.separatorStyle = .none + tableView.delegate = self + tableView.dataSource = self + tableView.translatesAutoresizingMaskIntoConstraints = false + tableView.sectionHeaderHeight = 6 + view.addSubview(tableView) + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + self.tableView.topAnchor + .constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor), + self.tableView.leftAnchor.constraint(equalTo: self.view.leftAnchor), + self.tableView.rightAnchor.constraint(equalTo: self.view.rightAnchor), + self.tableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor), + ]) + } else { + // Fallback on earlier versions + NSLayoutConstraint.activate([ + tableView.topAnchor.constraint(equalTo: view.topAnchor), + tableView.leftAnchor.constraint(equalTo: view.leftAnchor), + tableView.rightAnchor.constraint(equalTo: view.rightAnchor), + tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), + ]) } - - public override func viewDidLoad() { - super.viewDidLoad() - if user != nil { - commonUI() - loadData() - }else if let userId = uid { - weak var weakSelf = self - viewModel.getUserInfo(userId) { error, user in - if let err = error { - weakSelf?.showToast(err.localizedDescription) - }else if let u = user { - weakSelf?.user = u - weakSelf?.commonUI() - weakSelf?.loadData() - } - } - } + tableView.register( + TextWithRightArrowCell.self, + forCellReuseIdentifier: "\(TextWithRightArrowCell.self)" + ) + tableView.register( + TextWithDetailTextCell.self, + forCellReuseIdentifier: "\(TextWithDetailTextCell.self)" + ) + tableView.register( + TextWithSwitchCell.self, + forCellReuseIdentifier: "\(TextWithSwitchCell.self)" + ) + tableView.register(CenterTextCell.self, forCellReuseIdentifier: "\(CenterTextCell.self)") + tableView.register(UITableViewCell.self, forCellReuseIdentifier: "\(UITableViewCell.self)") + + tableView.rowHeight = 62 + headerView = + UserInfoHeaderView(frame: CGRect(x: 0, y: 0, width: tableView.frame.size.width, + height: 113)) + headerView?.setData(user: user) + tableView.tableHeaderView = headerView + } + + func loadData() { + let isFriend = viewModel.contactRepo.isFriend(account: user?.userId ?? "") + isBlack = viewModel.contactRepo.isBlackList(account: user?.userId ?? "") + + if isFriend { + data = [ + [UserItem( + title: localizable("备注名"), + detailTitle: user?.alias, + value: false, + textColor: UIColor.darkText, + cellClass: TextWithRightArrowCell.self + )], + [ + UserItem(title: localizable("手机"), detailTitle: user?.userInfo?.mobile, + value: false, + textColor: UIColor.darkText, cellClass: TextWithDetailTextCell.self), + UserItem( + title: localizable("邮箱"), + detailTitle: user?.userInfo?.email, + value: false, + textColor: UIColor.darkText, + cellClass: TextWithDetailTextCell.self + ), + UserItem( + title: localizable("个性签名"), + detailTitle: user?.userInfo?.sign, + value: false, + textColor: UIColor.darkText, + cellClass: TextWithDetailTextCell.self + ), + ], + // UserItem(title: localizable("消息提醒"), detailTitle: "", value: false, textColor: UIColor.darkText, cellClass: TextWithSwitchCell.self) 隐藏消息提醒 + [UserItem( + title: localizable("加入黑名单"), + detailTitle: "", + value: isBlack, + textColor: UIColor.darkText, + cellClass: TextWithSwitchCell.self + )], + [ + UserItem(title: localizable("聊天"), detailTitle: "", value: false, + textColor: UIColor(hexString: "#337EFF"), cellClass: CenterTextCell.self), + UserItem( + title: localizable("删除好友"), + detailTitle: "", + value: false, + textColor: UIColor.red, + cellClass: CenterTextCell.self + ), + ], + ] + } else { + data = [[UserItem( + title: localizable("添加好友"), + detailTitle: user?.alias, + value: false, + textColor: UIColor(hexString: "#337EFF"), + cellClass: CenterTextCell.self + )]] } - - func commonUI() { - self.tableView.separatorStyle = .none - self.tableView.delegate = self - self.tableView.dataSource = self - self.tableView.translatesAutoresizingMaskIntoConstraints = false - self.tableView.sectionHeaderHeight = 6 - self.view.addSubview(self.tableView) - if #available(iOS 11.0, *) { - NSLayoutConstraint.activate([ - self.tableView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor), - self.tableView.leftAnchor.constraint(equalTo: self.view.leftAnchor), - self.tableView.rightAnchor.constraint(equalTo: self.view.rightAnchor), - self.tableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor), - ]) - } else { - // Fallback on earlier versions - NSLayoutConstraint.activate([ - self.tableView.topAnchor.constraint(equalTo: self.view.topAnchor), - self.tableView.leftAnchor.constraint(equalTo: self.view.leftAnchor), - self.tableView.rightAnchor.constraint(equalTo: self.view.rightAnchor), - self.tableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor), - ]) - } - self.tableView.register(TextWithRightArrowCell.self, forCellReuseIdentifier: "\(TextWithRightArrowCell.self)") - self.tableView.register(TextWithDetailTextCell.self, forCellReuseIdentifier: "\(TextWithDetailTextCell.self)") - self.tableView.register(TextWithSwitchCell.self, forCellReuseIdentifier: "\(TextWithSwitchCell.self)") - self.tableView.register(CenterTextCell.self, forCellReuseIdentifier: "\(CenterTextCell.self)") - self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "\(UITableViewCell.self)") + tableView.reloadData() + } + + public func numberOfSections(in tableView: UITableView) -> Int { + data.count + } - self.tableView.rowHeight = 62 - headerView = UserInfoHeaderView(frame: CGRect(x: 0, y: 0, width: self.tableView.frame.size.width, height: 113)) - headerView?.setData(user:user) - self.tableView.tableHeaderView = headerView + public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + data[section].count + } + + public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let item = data[indexPath.section][indexPath.row] + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(item.cellClass)", + for: indexPath + ) + + if let c = cell as? TextWithRightArrowCell { + c.titleLabel.text = item.title + return c } - - func loadData() { - - let isFriend = viewModel.contactRepo.isFriend(account: self.user?.userId ?? "") - self.isBlack = viewModel.contactRepo.isBlackList(account: self.user?.userId ?? "") - - if isFriend { - data = [[UserItem(title: localizable("备注名"), detailTitle: user?.alias, value: false, textColor: UIColor.darkText, cellClass: TextWithRightArrowCell.self)], - [UserItem(title: localizable("手机"), detailTitle: user?.userInfo?.mobile, value: false, textColor: UIColor.darkText, cellClass: TextWithDetailTextCell.self), - UserItem(title: localizable("邮箱"), detailTitle: user?.userInfo?.email, value: false, textColor: UIColor.darkText, cellClass: TextWithDetailTextCell.self), - UserItem(title: localizable("个性签名"), detailTitle: user?.userInfo?.sign, value: false, textColor: UIColor.darkText, cellClass: TextWithDetailTextCell.self)], - //UserItem(title: localizable("消息提醒"), detailTitle: "", value: false, textColor: UIColor.darkText, cellClass: TextWithSwitchCell.self) 隐藏消息提醒 - [UserItem(title: localizable("加入黑名单"), detailTitle: "", value: self.isBlack, textColor: UIColor.darkText, cellClass: TextWithSwitchCell.self)], - [UserItem(title: localizable("聊天"), detailTitle: "", value: false, textColor: UIColor(hexString: "#337EFF"), cellClass: CenterTextCell.self), - UserItem(title: localizable("删除好友"), detailTitle: "", value: false, textColor: UIColor.red, cellClass: CenterTextCell.self)]] - }else { - data = [[UserItem(title: localizable("添加好友"), detailTitle: user?.alias, value: false, textColor: UIColor(hexString: "#337EFF"), cellClass: CenterTextCell.self)]] - } - self.tableView.reloadData() + + if let c = cell as? TextWithDetailTextCell { + c.titleLabel.text = item.title + c.detailTitleLabel.text = item.detailTitle + return c } - - public func numberOfSections(in tableView: UITableView) -> Int { - return data.count + + if let c = cell as? TextWithSwitchCell { + c.titleLabel.text = item.title + c.switchButton.isOn = item.value + c.block = { [weak self] title, value in + print("title:\(title) value\(value)") + if title == localizable("加入黑名单") { + self?.blackList(isBlack: value) + } else if title == localizable("消息提醒") {} + } + + return c } - - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return data[section].count + + if let c = cell as? CenterTextCell { + c.titleLabel.text = item.title + c.titleLabel.textColor = item.textColor + return c } - - public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let item = data[indexPath.section][indexPath.row] - let cell = tableView.dequeueReusableCell(withIdentifier: "\(item.cellClass)", for: indexPath) - - if let c = cell as? TextWithRightArrowCell { - c.titleLabel.text = item.title - return c - } - - if let c = cell as? TextWithDetailTextCell { - c.titleLabel.text = item.title - c.detailTitleLabel.text = item.detailTitle - return c - } - - if let c = cell as? TextWithSwitchCell { - c.titleLabel.text = item.title - c.switchButton.isOn = item.value - c.block = {[weak self] title, value in - print("title:\(title) value\(value)") - if title == localizable("加入黑名单") { - self?.blackList(isBlack: value) - }else if title == localizable("消息提醒") { - - } - } - - return c - } - - if let c = cell as? CenterTextCell { - c.titleLabel.text = item.title - c.titleLabel.textColor = item.textColor - return c - } - return cell + return cell + } + + public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + let item = data[indexPath.section][indexPath.row] + if item.title == localizable("备注名") { + toEditRemarks() } - - public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - let item = data[indexPath.section][indexPath.row] - if item.title == localizable("备注名") { - toEditRemarks() - } // if item.title == localizable("消息提醒") { // allowNotify(allow: item.value) // } // if item.title == localizable("加入黑名单") { // blackList(isBlack: item.value) // } - if item.title == localizable("聊天") { - chat(user: self.user) - } - if item.title == localizable("删除好友") { - deleteFriend(user: self.user) - } - if item.title == localizable("添加好友") { - addFriend() - } + if item.title == localizable("聊天") { + chat(user: user) } + if item.title == localizable("删除好友") { + deleteFriend(user: user) + } + if item.title == localizable("添加好友") { + addFriend() + } + } - func toEditRemarks(){ - let remark = ContactRemakNameViewController() - remark.user = user - remark.completion = { u in - self.user = u - self.headerView?.setData(user: u) - - } - navigationController?.pushViewController(remark, animated: true) - - print("edit remarks") + func toEditRemarks() { + let remark = ContactRemakNameViewController() + remark.user = user + remark.completion = { u in + self.user = u + self.headerView?.setData(user: u) } - - func allowNotify(allow: Bool){ - print("edit remarks") + navigationController?.pushViewController(remark, animated: true) + + print("edit remarks") + } + + func allowNotify(allow: Bool) { + print("edit remarks") + } + + func blackList(isBlack: Bool) { + guard let userId = user?.userId else { + return } - - func blackList(isBlack: Bool){ - guard let userId = self.user?.userId else { - return + if isBlack { + // add + viewModel.contactRepo.addBlackList(account: userId) { [weak self] error in + if error != nil { + self?.view.makeToast(error?.localizedDescription) + } else { + // success + self?.isBlack = true + self?.loadData() } - if isBlack { - // add - viewModel.contactRepo.addBlackList(account: userId) {[weak self] error in - if error != nil { - self?.view.makeToast(error?.localizedDescription) - }else { - // success - self?.isBlack = true - self?.loadData() - } - } - - }else { - // remove - viewModel.contactRepo.removeBlackList(account: userId) {[weak self] error in - if error != nil { - self?.view.makeToast(error?.localizedDescription) - }else { - // success - self?.isBlack = false - self?.loadData() - } - } + } + + } else { + // remove + viewModel.contactRepo.removeBlackList(account: userId) { [weak self] error in + if error != nil { + self?.view.makeToast(error?.localizedDescription) + } else { + // success + self?.isBlack = false + self?.loadData() } + } } - - func chat(user: User?) { - print("edit remarks") - guard let accid = self.user?.userId else { - return - } - let session = NIMSession(accid, type: .P2P) - Router.shared.use(PushP2pChatVCRouter, parameters: ["nav": self.navigationController,"session": session]) { obj, routerState, str in - print("obj:\(obj) routerState:\(routerState) str:\(str)") - } + } + + func chat(user: User?) { + print("edit remarks") + guard let accid = self.user?.userId else { + return + } + let session = NIMSession(accid, type: .P2P) + Router.shared.use( + PushP2pChatVCRouter, + parameters: ["nav": navigationController, "session": session] + ) { obj, routerState, str in + print("obj:\(obj) routerState:\(routerState) str:\(str)") } + } - - func deleteFriend(user: User?){ - print("edit remarks") - if let userId = user?.userId { - viewModel.deleteFriend(account: userId) { error in - if error != nil { - self.showToast(error?.localizedDescription ?? "") - }else { - self.navigationController?.popViewController(animated: true) - } - } + func deleteFriend(user: User?) { + print("edit remarks") + if let userId = user?.userId { + viewModel.deleteFriend(account: userId) { error in + if error != nil { + self.showToast(error?.localizedDescription ?? "") + } else { + self.navigationController?.popViewController(animated: true) } - + } } - - @objc func addFriend(){ - - - weak var weakSelf = self - if let account = user?.userId { - viewModel.addFriend(account) { error in - if let err = error { - NELog.errorLog("ContactUserViewController", desc: "❌add friend failed :\(err)") - }else { - weakSelf?.showToast("好友申请已发送") - } - } + } + + @objc func addFriend() { + weak var weakSelf = self + if let account = user?.userId { + viewModel.addFriend(account) { error in + if let err = error { + NELog.errorLog("ContactUserViewController", desc: "❌add friend failed :\(err)") + } else { + weakSelf?.showToast("好友申请已发送") } + } } + } } diff --git a/NEContactUIKit/NEKitContactUI/Classes/UserInfo/Views/CenterTextCell.swift b/NEContactUIKit/NEKitContactUI/Classes/UserInfo/Views/CenterTextCell.swift index 88a32a1c..034dbace 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/UserInfo/Views/CenterTextCell.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/UserInfo/Views/CenterTextCell.swift @@ -1,42 +1,40 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class CenterTextCell: UITableViewCell { + public var titleLabel: UILabel = .init() + public var line = UIView() + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + selectionStyle = .none + titleLabel.font = UIFont.systemFont(ofSize: 16) + titleLabel.translatesAutoresizingMaskIntoConstraints = false + titleLabel.textColor = .red + titleLabel.textAlignment = .center + contentView.addSubview(titleLabel) + NSLayoutConstraint.activate([ + titleLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 36), + titleLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -36), + titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor), + titleLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + ]) + titleLabel.text = "title" + line.backgroundColor = UIColor(hexString: "#F5F8FC") + line.translatesAutoresizingMaskIntoConstraints = false + contentView.addSubview(line) + NSLayoutConstraint.activate([ + line.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20), + line.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), + line.heightAnchor.constraint(equalToConstant: 1.0), + line.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + ]) + } - public var titleLabel: UILabel = UILabel() - public var line = UIView() - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - self.selectionStyle = .none - self.titleLabel.font = UIFont.systemFont(ofSize: 16) - self.titleLabel.translatesAutoresizingMaskIntoConstraints = false - self.titleLabel.textColor = .red - self.titleLabel.textAlignment = .center - self.contentView.addSubview(self.titleLabel) - NSLayoutConstraint.activate([ - self.titleLabel.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 36), - self.titleLabel.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -36), - self.titleLabel.topAnchor.constraint(equalTo: self.contentView.topAnchor), - self.titleLabel.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor) - ]) - self.titleLabel.text = "title" - self.line.backgroundColor = UIColor(hexString: "#F5F8FC") - self.line.translatesAutoresizingMaskIntoConstraints = false - self.contentView.addSubview(self.line) - NSLayoutConstraint.activate([ - self.line.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 20), - self.line.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -20), - self.line.heightAnchor.constraint(equalToConstant: 1.0), - self.line.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor) - ]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } } diff --git a/NEContactUIKit/NEKitContactUI/Classes/UserInfo/Views/TextBaseCell.swift b/NEContactUIKit/NEKitContactUI/Classes/UserInfo/Views/TextBaseCell.swift index 5212f66d..a4689031 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/UserInfo/Views/TextBaseCell.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/UserInfo/Views/TextBaseCell.swift @@ -1,47 +1,46 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class TextBaseCell: UITableViewCell { - public var titleLabel: UILabel = UILabel() - public var line = UIView() - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - self.selectionStyle = .none - self.titleLabel.translatesAutoresizingMaskIntoConstraints = false - - self.titleLabel.font = UIFont.systemFont(ofSize: 16) - self.titleLabel.textColor = UIColor(hexString: "#333333") - self.contentView.addSubview(self.titleLabel) - NSLayoutConstraint.activate([ - self.titleLabel.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 20), - self.titleLabel.widthAnchor.constraint(equalToConstant: 100), - self.titleLabel.topAnchor.constraint(equalTo: self.contentView.topAnchor), - self.titleLabel.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor) - ]) - self.titleLabel.text = "" - - self.line.backgroundColor = UIColor(hexString: "#F5F8FC") - self.line.translatesAutoresizingMaskIntoConstraints = false - self.contentView.addSubview(self.line) - NSLayoutConstraint.activate([ - self.line.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 20), - self.line.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -20), - self.line.heightAnchor.constraint(equalToConstant: 1.0), - self.line.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor) - ]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func setModel(model: UserItem) { - self.titleLabel.text = model.title - } - + public var titleLabel: UILabel = .init() + public var line = UIView() + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + selectionStyle = .none + titleLabel.translatesAutoresizingMaskIntoConstraints = false + + titleLabel.font = UIFont.systemFont(ofSize: 16) + titleLabel.textColor = UIColor(hexString: "#333333") + contentView.addSubview(titleLabel) + NSLayoutConstraint.activate([ + titleLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20), + titleLabel.widthAnchor.constraint(equalToConstant: 100), + titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor), + titleLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + ]) + titleLabel.text = "" + + line.backgroundColor = UIColor(hexString: "#F5F8FC") + line.translatesAutoresizingMaskIntoConstraints = false + contentView.addSubview(line) + NSLayoutConstraint.activate([ + line.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20), + line.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), + line.heightAnchor.constraint(equalToConstant: 1.0), + line.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + ]) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func setModel(model: UserItem) { + titleLabel.text = model.title + } } diff --git a/NEContactUIKit/NEKitContactUI/Classes/UserInfo/Views/TextWithDetailTextCell.swift b/NEContactUIKit/NEKitContactUI/Classes/UserInfo/Views/TextWithDetailTextCell.swift index da1f6847..f8b5c31c 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/UserInfo/Views/TextWithDetailTextCell.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/UserInfo/Views/TextWithDetailTextCell.swift @@ -1,29 +1,31 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class TextWithDetailTextCell: TextBaseCell { - public var detailTitleLabel = UILabel() - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - self.detailTitleLabel.translatesAutoresizingMaskIntoConstraints = false - self.detailTitleLabel.font = UIFont.systemFont(ofSize: 12) - self.detailTitleLabel.textColor = UIColor(hexString: "#A6ADB6") - self.contentView.addSubview(self.detailTitleLabel) - NSLayoutConstraint.activate([ - self.detailTitleLabel.leftAnchor.constraint(equalTo: self.titleLabel.rightAnchor, constant: 20), - self.detailTitleLabel.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -20), - self.detailTitleLabel.topAnchor.constraint(equalTo: self.contentView.topAnchor), - self.detailTitleLabel.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor) - ]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } + public var detailTitleLabel = UILabel() + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + detailTitleLabel.translatesAutoresizingMaskIntoConstraints = false + detailTitleLabel.font = UIFont.systemFont(ofSize: 12) + detailTitleLabel.textColor = UIColor(hexString: "#A6ADB6") + contentView.addSubview(detailTitleLabel) + NSLayoutConstraint.activate([ + detailTitleLabel.leftAnchor.constraint(equalTo: titleLabel.rightAnchor, constant: 20), + detailTitleLabel.rightAnchor.constraint( + equalTo: contentView.rightAnchor, + constant: -20 + ), + detailTitleLabel.topAnchor.constraint(equalTo: contentView.topAnchor), + detailTitleLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + ]) + } + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } } diff --git a/NEContactUIKit/NEKitContactUI/Classes/UserInfo/Views/TextWithRightArrowCell.swift b/NEContactUIKit/NEKitContactUI/Classes/UserInfo/Views/TextWithRightArrowCell.swift index fffd2a8a..4959d008 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/UserInfo/Views/TextWithRightArrowCell.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/UserInfo/Views/TextWithRightArrowCell.swift @@ -1,32 +1,32 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class TextWithRightArrowCell: TextBaseCell { - public var arrowImage = UIImageView(image: UIImage.ne_imageNamed(name: "arrowRight")) + public var arrowImage = UIImageView(image: UIImage.ne_imageNamed(name: "arrowRight")) + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + arrowImage.translatesAutoresizingMaskIntoConstraints = false + arrowImage.contentMode = .center + contentView.addSubview(arrowImage) + NSLayoutConstraint.activate([ + arrowImage.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), + arrowImage.widthAnchor.constraint(equalToConstant: 20), + arrowImage.heightAnchor.constraint(equalToConstant: 20), + arrowImage.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + ]) + } - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - self.arrowImage.translatesAutoresizingMaskIntoConstraints = false - self.arrowImage.contentMode = .center - self.contentView.addSubview(self.arrowImage) - NSLayoutConstraint.activate([ - self.arrowImage.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -20), - self.arrowImage.widthAnchor.constraint(equalToConstant: 20), - self.arrowImage.heightAnchor.constraint(equalToConstant: 20), - self.arrowImage.centerYAnchor.constraint(equalTo: self.contentView.centerYAnchor), - ]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } - override func setModel(model: UserItem) { - super.setModel(model: model) + override func setModel(model: UserItem) { + super.setModel(model: model) // self.detailTitleLabel.text = model.detailTitle - } + } } diff --git a/NEContactUIKit/NEKitContactUI/Classes/UserInfo/Views/TextWithSwitchCell.swift b/NEContactUIKit/NEKitContactUI/Classes/UserInfo/Views/TextWithSwitchCell.swift index 432aedbf..2d5daee3 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/UserInfo/Views/TextWithSwitchCell.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/UserInfo/Views/TextWithSwitchCell.swift @@ -1,37 +1,36 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit typealias ValueChangeBlock = (_ title: String?, _ value: Bool) -> Void class TextWithSwitchCell: TextBaseCell { - public var block: ValueChangeBlock?; - public var switchButton = UISwitch() - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - self.switchButton.translatesAutoresizingMaskIntoConstraints = false - self.switchButton.onTintColor = UIColor(hexString: "#337EFF") - self.switchButton.addTarget(self, action: #selector(valueChanged), for: .touchUpInside) - - self.contentView.addSubview(self.switchButton) - NSLayoutConstraint.activate([ - self.switchButton.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -20), - self.switchButton.widthAnchor.constraint(equalToConstant: 46), - self.switchButton.heightAnchor.constraint(equalToConstant: 28), - self.switchButton.centerYAnchor.constraint(equalTo: self.contentView.centerYAnchor), - ]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - @objc func valueChanged(switchBtn: UISwitch) { - print("switchBtn:\(switchBtn.isOn)") - if let block = self.block { - block(self.titleLabel.text, switchBtn.isOn) - } - + public var block: ValueChangeBlock? + public var switchButton = UISwitch() + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + switchButton.translatesAutoresizingMaskIntoConstraints = false + switchButton.onTintColor = UIColor(hexString: "#337EFF") + switchButton.addTarget(self, action: #selector(valueChanged), for: .touchUpInside) + + contentView.addSubview(switchButton) + NSLayoutConstraint.activate([ + switchButton.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), + switchButton.widthAnchor.constraint(equalToConstant: 46), + switchButton.heightAnchor.constraint(equalToConstant: 28), + switchButton.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + ]) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc func valueChanged(switchBtn: UISwitch) { + print("switchBtn:\(switchBtn.isOn)") + if let block = block { + block(titleLabel.text, switchBtn.isOn) } + } } diff --git a/NEContactUIKit/NEKitContactUI/Classes/Validation/ViewController/ValidationMessageViewController.swift b/NEContactUIKit/NEKitContactUI/Classes/Validation/ViewController/ValidationMessageViewController.swift index 6a4fbe4a..2f3cb736 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/Validation/ViewController/ValidationMessageViewController.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/Validation/ViewController/ValidationMessageViewController.swift @@ -1,152 +1,156 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCore import NEKitCoreIM -public class ValiationMessageConfig { - -} +public class ValiationMessageConfig {} public class ValidationMessageViewController: ContactBaseViewController { + let viewModel = ValidationMessageViewModel() - let viewModel = ValidationMessageViewModel() - - let tableView = UITableView() - private let tag = "ValidationMessageViewController" - - public override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - self.title = localizable("验证消息") - //viewModel.getValidationMessage() - setupUI() - weak var weakSelf = self - viewModel.getValidationMessage { - weakSelf?.tableView.reloadData() - } - - viewModel.dataRefresh = { - weakSelf?.tableView.reloadData() - } + let tableView = UITableView() + private let tag = "ValidationMessageViewController" + + override public func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + title = localizable("验证消息") + // viewModel.getValidationMessage() + setupUI() + weak var weakSelf = self + viewModel.getValidationMessage { + weakSelf?.tableView.reloadData() } - - func setupUI(){ - let clearItem = UIBarButtonItem(title: "清空", style: .done, target: self, action: #selector(clearMessage)) - clearItem.tintColor = UIColor(hexString: "666666") - navigationItem.rightBarButtonItem = clearItem - - tableView.translatesAutoresizingMaskIntoConstraints = false - view.addSubview(tableView) - tableView.dataSource = self - tableView.delegate = self - tableView.separatorStyle = .none - - NSLayoutConstraint.activate([ - tableView.topAnchor.constraint(equalTo: view.topAnchor), - tableView.leftAnchor.constraint(equalTo: view.leftAnchor), - tableView.rightAnchor.constraint(equalTo: view.rightAnchor), - tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor) - ]) - - tableView.register(SystemNotificationCell.self, forCellReuseIdentifier: "\(SystemNotificationCell.self)") + + viewModel.dataRefresh = { + weakSelf?.tableView.reloadData() } - - @objc func clearMessage(){ - weak var weakSelf = self - showAlert(message: "是否要清除所有验证消息?") { - weakSelf?.viewModel.clearAllNoti { - weakSelf?.tableView.reloadData() - } - } + } + + func setupUI() { + let clearItem = UIBarButtonItem( + title: "清空", + style: .done, + target: self, + action: #selector(clearMessage) + ) + clearItem.tintColor = UIColor(hexString: "666666") + navigationItem.rightBarButtonItem = clearItem + + tableView.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(tableView) + tableView.dataSource = self + tableView.delegate = self + tableView.separatorStyle = .none + + NSLayoutConstraint.activate([ + tableView.topAnchor.constraint(equalTo: view.topAnchor), + tableView.leftAnchor.constraint(equalTo: view.leftAnchor), + tableView.rightAnchor.constraint(equalTo: view.rightAnchor), + tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), + ]) + + tableView.register( + SystemNotificationCell.self, + forCellReuseIdentifier: "\(SystemNotificationCell.self)" + ) + } + + @objc func clearMessage() { + weak var weakSelf = self + showAlert(message: "是否要清除所有验证消息?") { + weakSelf?.viewModel.clearAllNoti { + weakSelf?.tableView.reloadData() + } } + } } extension ValidationMessageViewController: UITableViewDelegate, UITableViewDataSource { - - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return viewModel.datas.count - } - - public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - - let noti = viewModel.datas[indexPath.row] - let reuseIdentifier = "\(SystemNotificationCell.self)" - let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) as! SystemNotificationCell - cell.delegate = self - cell.confige(noti) - return cell - } - - public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - return 60 - } + public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + viewModel.datas.count + } + + public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let noti = viewModel.datas[indexPath.row] + let reuseIdentifier = "\(SystemNotificationCell.self)" + let cell = tableView.dequeueReusableCell( + withIdentifier: reuseIdentifier, + for: indexPath + ) as! SystemNotificationCell + cell.delegate = self + cell.confige(noti) + return cell + } + public func tableView(_ tableView: UITableView, + heightForRowAt indexPath: IndexPath) -> CGFloat { + 60 + } } -extension ValidationMessageViewController:SystemNotificationCellDelegate{ - - func onAccept(_ notifiModel: XNotification) { - weak var weakSelf = self - guard let teamId = notifiModel.targetID,let invitorId = notifiModel.sourceID else { - return +extension ValidationMessageViewController: SystemNotificationCellDelegate { + func onAccept(_ notifiModel: XNotification) { + weak var weakSelf = self + guard let teamId = notifiModel.targetID, let invitorId = notifiModel.sourceID else { + return + } + + if notifiModel.type == .teamInvite { + viewModel.acceptInviteWithTeam(teamId, invitorId) { error in + if error != nil { + NELog.infoLog(self.tag, desc: "❌acceptInviteWithTeam failed,error = \(error!)") + } else { + notifiModel.handleStatus = .HandleTypeOk + notifiModel.imNotification?.handleStatus = 1 + weakSelf?.tableView.reloadData() } - - if notifiModel.type == .teamInvite { - viewModel.acceptInviteWithTeam(teamId, invitorId) { error in - if error != nil { - NELog.infoLog(self.tag, desc: "❌acceptInviteWithTeam failed,error = \(error!)") - }else { - notifiModel.handleStatus = .HandleTypeOk - notifiModel.imNotification?.handleStatus = 1 - weakSelf?.tableView.reloadData() - } - } - }else if notifiModel.type == .addFriendRequest { - viewModel.agreeRequest(invitorId) { error in - if error != nil { - NELog.infoLog(self.tag, desc: "❌agreeRequest failed,error = \(error!)") - }else { - notifiModel.handleStatus = .HandleTypeOk - notifiModel.imNotification?.handleStatus = 1 - weakSelf?.tableView.reloadData() - } - } + } + } else if notifiModel.type == .addFriendRequest { + viewModel.agreeRequest(invitorId) { error in + if error != nil { + NELog.infoLog(self.tag, desc: "❌agreeRequest failed,error = \(error!)") + } else { + notifiModel.handleStatus = .HandleTypeOk + notifiModel.imNotification?.handleStatus = 1 + weakSelf?.tableView.reloadData() } + } } - - func onRefuse(_ notifiModel: XNotification) { - weak var weakSelf = self - guard let teamId = notifiModel.targetID,let invitorId = notifiModel.sourceID else { - return + } + + func onRefuse(_ notifiModel: XNotification) { + weak var weakSelf = self + guard let teamId = notifiModel.targetID, let invitorId = notifiModel.sourceID else { + return + } + + if notifiModel.type == .teamInvite { + weakSelf?.viewModel.rejectInviteWithTeam(teamId, invitorId) { error in + if error != nil { + NELog.infoLog(self.tag, desc: "❌rejectInviteWithTeam failed,error = \(error!)") + } else { + notifiModel.handleStatus = .HandleTypeNo + notifiModel.imNotification?.handleStatus = 2 + weakSelf?.tableView.reloadData() } - - if notifiModel.type == .teamInvite { - weakSelf?.viewModel.rejectInviteWithTeam(teamId, invitorId, { error in - if error != nil { - NELog.infoLog(self.tag, desc: "❌rejectInviteWithTeam failed,error = \(error!)") - }else { - notifiModel.handleStatus = .HandleTypeNo - notifiModel.imNotification?.handleStatus = 2 - weakSelf?.tableView.reloadData() - } - }) - }else if notifiModel.type == .addFriendRequest { - viewModel.refuseRequest(invitorId) { error in - if error != nil { - NELog.infoLog(self.tag, desc: "❌agreeRequest failed,error = \(error!)") - }else { - notifiModel.handleStatus = .HandleTypeNo - notifiModel.imNotification?.handleStatus = 2 - weakSelf?.tableView.reloadData() - } - } + } + } else if notifiModel.type == .addFriendRequest { + viewModel.refuseRequest(invitorId) { error in + if error != nil { + NELog.infoLog(self.tag, desc: "❌agreeRequest failed,error = \(error!)") + } else { + notifiModel.handleStatus = .HandleTypeNo + notifiModel.imNotification?.handleStatus = 2 + weakSelf?.tableView.reloadData() } + } } - - + } } diff --git a/NEContactUIKit/NEKitContactUI/Classes/Validation/ViewModel/ValidationMessageViewModel.swift b/NEContactUIKit/NEKitContactUI/Classes/Validation/ViewModel/ValidationMessageViewModel.swift index 3aa2de76..2fbc8d8a 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/Validation/ViewModel/ValidationMessageViewModel.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/Validation/ViewModel/ValidationMessageViewModel.swift @@ -1,7 +1,7 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NEKitContact @@ -9,71 +9,68 @@ import NEKitCoreIM import NEKitCore public class ValidationMessageViewModel: ContactRepoSystemNotiDelegate { - - typealias DataRefresh = () -> Void - - var dataRefresh: DataRefresh? - private let className = "ValidationMessageViewModel" - let contactRepo = ContactRepo() - var datas = [XNotification]() - - init(){ - contactRepo.notiDelegate = self - } - - public func onNotificationUnreadCountChanged(_ count: Int) { - - } - - public func onRecieveNotification(_ notification: XNotification) { + typealias DataRefresh = () -> Void + + var dataRefresh: DataRefresh? + private let className = "ValidationMessageViewModel" + let contactRepo = ContactRepo() + var datas = [XNotification]() + + init() { + contactRepo.notiDelegate = self + } + + public func onNotificationUnreadCountChanged(_ count: Int) {} + + public func onRecieveNotification(_ notification: XNotification) { // if notification.type == .addFriendDirectly { // datas.insert(notification, at: 0) // } - datas.insert(notification, at: 0) - contactRepo.clearNotificationUnreadCount() - if let block = dataRefresh { - block() - } - } - - func getValidationMessage(_ completin: () -> Void ){ - let data = contactRepo.getNotificationList(limit: 500) - datas = data - if datas.count > 0 { - completin() - }else { - NELog.warn(className, desc: "⚠️NotificationList is empty") - } - } - - func clearAllNoti(_ completion: () -> Void){ - contactRepo.clearNotification() - datas.removeAll() - completion() - } - - public func acceptInviteWithTeam(_ teamId:String,_ invitorId:String,_ completion: @escaping (Error?) -> Void){ - contactRepo.acceptTeamInvite(teamId, invitorId, completion) + datas.insert(notification, at: 0) + contactRepo.clearNotificationUnreadCount() + if let block = dataRefresh { + block() } + } - public func rejectInviteWithTeam(_ teamId:String,_ invitorId:String,_ completion: @escaping (Error?) -> Void){ - contactRepo.rejectTeamInvite(teamId, invitorId, completion) - } - - func agreeRequest(_ account: String, _ completion: @escaping (NSError?)->()){ - let request = AddFriendRequest() - request.account = account - request.operationType = .verify - contactRepo.addFriend(request: request, completion) - + func getValidationMessage(_ completin: () -> Void) { + let data = contactRepo.getNotificationList(limit: 500) + datas = data + if datas.count > 0 { + completin() + } else { + NELog.warn(className, desc: "⚠️NotificationList is empty") } - - func refuseRequest(_ account: String, _ completion: @escaping (NSError?)->()){ - print("account : ", account) - let request = AddFriendRequest() - request.account = account - request.operationType = .reject - contactRepo.addFriend(request: request, completion) - } - + } + + func clearAllNoti(_ completion: () -> Void) { + contactRepo.clearNotification() + datas.removeAll() + completion() + } + + public func acceptInviteWithTeam(_ teamId: String, _ invitorId: String, + _ completion: @escaping (Error?) -> Void) { + contactRepo.acceptTeamInvite(teamId, invitorId, completion) + } + + public func rejectInviteWithTeam(_ teamId: String, _ invitorId: String, + _ completion: @escaping (Error?) -> Void) { + contactRepo.rejectTeamInvite(teamId, invitorId, completion) + } + + func agreeRequest(_ account: String, _ completion: @escaping (NSError?) -> Void) { + let request = AddFriendRequest() + request.account = account + request.operationType = .verify + contactRepo.addFriend(request: request, completion) + } + + func refuseRequest(_ account: String, _ completion: @escaping (NSError?) -> Void) { + print("account : ", account) + let request = AddFriendRequest() + request.account = account + request.operationType = .reject + contactRepo.addFriend(request: request, completion) + } } diff --git a/NEContactUIKit/NEKitContactUI/Classes/Validation/Views/BaseValidationCell.swift b/NEContactUIKit/NEKitContactUI/Classes/Validation/Views/BaseValidationCell.swift index 6ff90005..ac13ea84 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/Validation/Views/BaseValidationCell.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/Validation/Views/BaseValidationCell.swift @@ -1,125 +1,109 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCoreIM class BaseValidationCell: ContactBaseViewCell { - - public var titleLabelRightMargin: NSLayoutConstraint? + public var titleLabelRightMargin: NSLayoutConstraint? + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } + // Configure the view for the selected state + } + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + setupUI() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + func setupUI() { + setupCommonCircleHeader() + + addSubview(titleLabel) + NSLayoutConstraint.activate([ + titleLabel.leftAnchor.constraint(equalTo: avatarImage.rightAnchor, constant: 10), + titleLabel.centerYAnchor.constraint(equalTo: avatarImage.centerYAnchor), + ]) + titleLabelRightMargin = titleLabel.rightAnchor.constraint( + equalTo: contentView.rightAnchor, + constant: -10 + ) + titleLabelRightMargin?.isActive = true - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) + let line = UIView() + addSubview(line) + line.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + line.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20), + line.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), + line.heightAnchor.constraint(equalToConstant: 1), + line.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + ]) + line.backgroundColor = UIColor(hexString: "#F5F8FC") + } - // Configure the view for the selected state + public func confige(_ model: XNotification) { + if let id = model.sourceID { + showNameOnCircleHeader(id) } - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - setupUI() + + if let name = model.sourceName { + showNameOnCircleHeader(name) } - - required init?(coder: NSCoder) { - super.init(coder: coder) + + var titleLabelContent = "" + var nickName = "" + var teamName = "" + if let nick = model.sourceName { + nickName = nick } - - func setupUI(){ - setupCommonCircleHeader() - - addSubview(titleLabel) - NSLayoutConstraint.activate([ - titleLabel.leftAnchor.constraint(equalTo:avatarImage.rightAnchor , constant: 10), - titleLabel.centerYAnchor.constraint(equalTo: avatarImage.centerYAnchor), - ]) - titleLabelRightMargin = titleLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -10) - titleLabelRightMargin?.isActive = true - - - let line = UIView() - addSubview(line) - line.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - line.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20), - line.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), - line.heightAnchor.constraint(equalToConstant: 1), - line.bottomAnchor.constraint(equalTo: contentView.bottomAnchor) - ]) - line.backgroundColor = UIColor(hexString: "#F5F8FC") - + if let t = model.targetName { + teamName = t } - - public func confige(_ model: XNotification){ - - if let id = model.sourceID { - showNameOnCircleHeader(id) - } - - if let name = model.sourceName { - showNameOnCircleHeader(name) - } - - var titleLabelContent = "" - var nickName = "" - var teamName = "" - if let nick = model.sourceName { - nickName = nick - } - if let t = model.targetName { - teamName = t - } - if let type = model.type { - switch type { - case .teamApply: - titleLabelContent = "\(nickName) 申请入群" - break - case .teamApplyReject: - titleLabelContent = "\(nickName) 拒绝入群" - break - case .teamInvite: - titleLabelContent = "\(nickName) 邀请你加入 \(teamName)" - break - case .teamInviteReject: - titleLabelContent = "\(nickName) 拒绝入群邀请" - - break - case .superTeamApply: - titleLabelContent = "\(nickName) 申请加入超大群" - break - case .superTeamApplyReject: - titleLabelContent = "\(nickName) 拒绝加入超大群" - - break - case .superTeamInvite: - titleLabelContent = "\(nickName) 邀请加入 \(teamName) 群" - break - case .superTeamInviteReject: - titleLabelContent = "\(nickName) 拒绝加入 \(teamName) 群" - break - case .addFriendDirectly: - titleLabelContent = "\(nickName) 添加你为好友" - break - case .addFriendRequest: - titleLabelContent = "\(nickName) 好友申请" - break - case .addFriendVerify: - titleLabelContent = "\(nickName) 通过好友申请" - break - case .addFriendReject: - titleLabelContent = "\(nickName) 拒绝好友申请" - break - } - } - - titleLabel.text = titleLabelContent - + if let type = model.type { + switch type { + case .teamApply: + titleLabelContent = "\(nickName) 申请入群" + case .teamApplyReject: + titleLabelContent = "\(nickName) 拒绝入群" + case .teamInvite: + titleLabelContent = "\(nickName) 邀请你加入 \(teamName)" + case .teamInviteReject: + titleLabelContent = "\(nickName) 拒绝入群邀请" + + case .superTeamApply: + titleLabelContent = "\(nickName) 申请加入超大群" + case .superTeamApplyReject: + titleLabelContent = "\(nickName) 拒绝加入超大群" + + case .superTeamInvite: + titleLabelContent = "\(nickName) 邀请加入 \(teamName) 群" + case .superTeamInviteReject: + titleLabelContent = "\(nickName) 拒绝加入 \(teamName) 群" + case .addFriendDirectly: + titleLabelContent = "\(nickName) 添加你为好友" + case .addFriendRequest: + titleLabelContent = "\(nickName) 好友申请" + case .addFriendVerify: + titleLabelContent = "\(nickName) 通过好友申请" + case .addFriendReject: + titleLabelContent = "\(nickName) 拒绝好友申请" + } } + titleLabel.text = titleLabelContent + } } diff --git a/NEContactUIKit/NEKitContactUI/Classes/Validation/Views/SystemNotificationCell.swift b/NEContactUIKit/NEKitContactUI/Classes/Validation/Views/SystemNotificationCell.swift index 2e211c08..11638cd3 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/Validation/Views/SystemNotificationCell.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/Validation/Views/SystemNotificationCell.swift @@ -1,7 +1,7 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCore @@ -10,191 +10,182 @@ import NEKitCoreIM import NIMSDK protocol SystemNotificationCellDelegate: AnyObject { - func onAccept(_ notifiModel:XNotification) - func onRefuse(_ notifiModel:XNotification) + func onAccept(_ notifiModel: XNotification) + func onRefuse(_ notifiModel: XNotification) } -enum NotificationHandleType:Int { - case Pending = 0 - case agree - case refuse - case OutOfDate +enum NotificationHandleType: Int { + case Pending = 0 + case agree + case refuse + case OutOfDate } + class SystemNotificationCell: BaseValidationCell { - private var notifModel:XNotification? - weak var delegate: SystemNotificationCellDelegate? + private var notifModel: XNotification? + weak var delegate: SystemNotificationCellDelegate? - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - } - - override func setupUI() { - super.setupUI() - titleLabel.numberOfLines = 1 - contentView.addSubview(agreeBtn) - contentView.addSubview(rejectBtn) - contentView.addSubview(resultImage) - contentView.addSubview(resultLabel) - resultLabel.text = "asdasdsadsa" - NSLayoutConstraint.activate([ - agreeBtn.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - agreeBtn.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), - agreeBtn.widthAnchor.constraint(equalToConstant: 60), - agreeBtn.heightAnchor.constraint(equalToConstant: 32) - ]) - agreeBtn.addTarget(self, action: #selector(agreeClick(_:)), for: .touchUpInside) - - - NSLayoutConstraint.activate([ - rejectBtn.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - rejectBtn.rightAnchor.constraint(equalTo: agreeBtn.leftAnchor, constant: -16), - rejectBtn.widthAnchor.constraint(equalToConstant: 60), - rejectBtn.heightAnchor.constraint(equalToConstant: 32) - ]) - rejectBtn.addTarget(self, action: #selector(rejectClick(_:)), for: .touchUpInside) - - NSLayoutConstraint.activate([ - resultLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), - resultLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - ]) - - NSLayoutConstraint.activate([ - resultImage.rightAnchor.constraint(equalTo: resultLabel.leftAnchor, constant: -6), - resultImage.centerYAnchor.constraint(equalTo: resultLabel.centerYAnchor), - resultImage.widthAnchor.constraint(equalToConstant: 16), - resultImage.heightAnchor.constraint(equalToConstant: 16) - ]) - - } - - override func confige(_ model: XNotification) { - super.confige(model) - notifModel = model - let hideActionButton = shouldHideActionButton() - agreeBtn.isHidden = hideActionButton - rejectBtn.isHidden = hideActionButton - - if hideActionButton { - let hidden = shouldHideResultStatus() - - resultLabel.isHidden = hidden - resultImage.isHidden = hidden - - switch notifModel?.handleStatus { - case .HandleTypeOk: - resultLabel.text = "已同意" - break - case .HandleTypeNo: - resultLabel.text = "已拒绝" - break - case .HandleTypeOutOfDate: - resultLabel.text = "已过期" - break - default: - resultLabel.text = "" - } - titleLabelRightMargin?.constant = hidden ? -20 : -90 - }else { - resultLabel.isHidden = true - resultImage.isHidden = true - titleLabelRightMargin?.constant = -180 - } + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + override func setupUI() { + super.setupUI() + titleLabel.numberOfLines = 1 + contentView.addSubview(agreeBtn) + contentView.addSubview(rejectBtn) + contentView.addSubview(resultImage) + contentView.addSubview(resultLabel) + resultLabel.text = "asdasdsadsa" + NSLayoutConstraint.activate([ + agreeBtn.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + agreeBtn.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), + agreeBtn.widthAnchor.constraint(equalToConstant: 60), + agreeBtn.heightAnchor.constraint(equalToConstant: 32), + ]) + agreeBtn.addTarget(self, action: #selector(agreeClick(_:)), for: .touchUpInside) + + NSLayoutConstraint.activate([ + rejectBtn.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + rejectBtn.rightAnchor.constraint(equalTo: agreeBtn.leftAnchor, constant: -16), + rejectBtn.widthAnchor.constraint(equalToConstant: 60), + rejectBtn.heightAnchor.constraint(equalToConstant: 32), + ]) + rejectBtn.addTarget(self, action: #selector(rejectClick(_:)), for: .touchUpInside) + + NSLayoutConstraint.activate([ + resultLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), + resultLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + ]) + + NSLayoutConstraint.activate([ + resultImage.rightAnchor.constraint(equalTo: resultLabel.leftAnchor, constant: -6), + resultImage.centerYAnchor.constraint(equalTo: resultLabel.centerYAnchor), + resultImage.widthAnchor.constraint(equalToConstant: 16), + resultImage.heightAnchor.constraint(equalToConstant: 16), + ]) + } + + override func confige(_ model: XNotification) { + super.confige(model) + notifModel = model + let hideActionButton = shouldHideActionButton() + agreeBtn.isHidden = hideActionButton + rejectBtn.isHidden = hideActionButton + + if hideActionButton { + let hidden = shouldHideResultStatus() + + resultLabel.isHidden = hidden + resultImage.isHidden = hidden + + switch notifModel?.handleStatus { + case .HandleTypeOk: + resultLabel.text = "已同意" + case .HandleTypeNo: + resultLabel.text = "已拒绝" + case .HandleTypeOutOfDate: + resultLabel.text = "已过期" + default: + resultLabel.text = "" + } + titleLabelRightMargin?.constant = hidden ? -20 : -90 + } else { + resultLabel.isHidden = true + resultImage.isHidden = true + titleLabelRightMargin?.constant = -180 } - - func shouldHideActionButton() -> Bool{ - - let type = notifModel?.type - let handled = notifModel?.handleStatus != .HandleTypePending - var needHandel = false - if type == .teamApply || - type == .teamInvite || - type == .superTeamInvite || - type == .superTeamApply { - needHandel = true - } - - if type == .addFriendRequest { - if let obj = notifModel?.attachment { - if obj.isKind(of: NIMUserAddAttachment.self) { - let operation = (obj as NIMUserAddAttachment).operationType - needHandel = operation == .request - } - } - } - return !(!handled && needHandel) + } + + func shouldHideActionButton() -> Bool { + let type = notifModel?.type + let handled = notifModel?.handleStatus != .HandleTypePending + var needHandel = false + if type == .teamApply || + type == .teamInvite || + type == .superTeamInvite || + type == .superTeamApply { + needHandel = true } - - func shouldHideResultStatus() -> Bool { - let type = notifModel?.type - if type == .addFriendVerify || - type == .addFriendReject || - type == .teamInviteReject { - return true - }else { - return false + + if type == .addFriendRequest { + if let obj = notifModel?.attachment { + if obj.isKind(of: NIMUserAddAttachment.self) { + let operation = (obj as NIMUserAddAttachment).operationType + needHandel = operation == .request } - + } } - - - var rejectBtn: ExpandButton = { - let button = ExpandButton() - button.translatesAutoresizingMaskIntoConstraints = false - button.setTitle("拒绝", for: .normal) - button.setTitleColor(UIColor(hexString: "333333"), for: .normal) - button.titleLabel?.font = UIFont.systemFont(ofSize: 14.0) - button.clipsToBounds = false - button.layer.cornerRadius = 4 - button.layer.borderColor = UIColor(hexString: "D9D9D9").cgColor - button.layer.borderWidth = 1 - return button - }() - - var agreeBtn: ExpandButton = { - let button = ExpandButton() - button.translatesAutoresizingMaskIntoConstraints = false - button.setTitle("同意", for: .normal) - let blue = UIColor(hexString: "337EFF") - button.setTitleColor(blue, for: .normal) - button.titleLabel?.font = UIFont.systemFont(ofSize: 14) - button.clipsToBounds = true - button.layer.cornerRadius = 4 - button.layer.borderWidth = 1 - button.layer.borderColor = blue.cgColor - return button - }() - - private lazy var resultImage:UIImageView = { - let rightImage = UIImageView() - rightImage.translatesAutoresizingMaskIntoConstraints = false - rightImage.image = UIImage.ne_imageNamed(name: "finishFlag") - return rightImage - }() - - private lazy var resultLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.textColor = UIColor(hexString: "B3B7BC") - label.font = UIFont.systemFont(ofSize: 14.0) - label.textAlignment = .right - return label - }() - - - @objc func rejectClick(_ sender: UIButton){ - if let model = notifModel { - delegate?.onRefuse(model) - } + return !(!handled && needHandel) + } + + func shouldHideResultStatus() -> Bool { + let type = notifModel?.type + if type == .addFriendVerify || + type == .addFriendReject || + type == .teamInviteReject { + return true + } else { + return false } - - @objc func agreeClick(_ sender: UIButton) { - if let model = notifModel { - delegate?.onAccept(model) - } + } + + var rejectBtn: ExpandButton = { + let button = ExpandButton() + button.translatesAutoresizingMaskIntoConstraints = false + button.setTitle("拒绝", for: .normal) + button.setTitleColor(UIColor(hexString: "333333"), for: .normal) + button.titleLabel?.font = UIFont.systemFont(ofSize: 14.0) + button.clipsToBounds = false + button.layer.cornerRadius = 4 + button.layer.borderColor = UIColor(hexString: "D9D9D9").cgColor + button.layer.borderWidth = 1 + return button + }() + + var agreeBtn: ExpandButton = { + let button = ExpandButton() + button.translatesAutoresizingMaskIntoConstraints = false + button.setTitle("同意", for: .normal) + let blue = UIColor(hexString: "337EFF") + button.setTitleColor(blue, for: .normal) + button.titleLabel?.font = UIFont.systemFont(ofSize: 14) + button.clipsToBounds = true + button.layer.cornerRadius = 4 + button.layer.borderWidth = 1 + button.layer.borderColor = blue.cgColor + return button + }() + + private lazy var resultImage: UIImageView = { + let rightImage = UIImageView() + rightImage.translatesAutoresizingMaskIntoConstraints = false + rightImage.image = UIImage.ne_imageNamed(name: "finishFlag") + return rightImage + }() + + private lazy var resultLabel: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.textColor = UIColor(hexString: "B3B7BC") + label.font = UIFont.systemFont(ofSize: 14.0) + label.textAlignment = .right + return label + }() + + @objc func rejectClick(_ sender: UIButton) { + if let model = notifModel { + delegate?.onRefuse(model) } + } + @objc func agreeClick(_ sender: UIButton) { + if let model = notifModel { + delegate?.onAccept(model) + } + } } diff --git a/NEContactUIKit/NEKitContactUI/Classes/ViewModel/ContactGroup.swift b/NEContactUIKit/NEKitContactUI/Classes/ViewModel/ContactGroup.swift index e6db615d..ce67ca0c 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/ViewModel/ContactGroup.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/ViewModel/ContactGroup.swift @@ -1,10 +1,8 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation -public class ContactGroup { - -} +public class ContactGroup {} diff --git a/NEContactUIKit/NEKitContactUI/Classes/ViewModel/ContactUserViewModel.swift b/NEContactUIKit/NEKitContactUI/Classes/ViewModel/ContactUserViewModel.swift index 487734d3..9347eddc 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/ViewModel/ContactUserViewModel.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/ViewModel/ContactUserViewModel.swift @@ -1,43 +1,41 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NEKitContact import NEKitCoreIM import CoreMedia class ContactUserViewModel { - - let contactRepo = ContactRepo() - - func addFriend(_ account: String, _ completion: @escaping (NSError?)->()){ - let request = AddFriendRequest() - request.account = account - request.operationType = .addRequest - contactRepo.addFriend(request: request, completion) - } - - public func deleteFriend(account: String ,_ completion: @escaping (NSError?)->()) { - return contactRepo.deleteFriend(account: account, completion) - } + let contactRepo = ContactRepo() - public func isFriend(account: String) -> Bool { - return contactRepo.isFriend(account: account) - } - - public func isBlack(account: String) -> Bool { - return contactRepo.isBlackList(account: account) - } - - public func update(_ user: User, _ completion: @escaping (Error?) -> Void){ - contactRepo.updateUser(user, completion) - } - - public func getUserInfo(_ uid: String, _ completion: @escaping (Error?, User?) -> Void){ - contactRepo.getUserInfo(uid) { error, users in - completion(error, users.first) - } + func addFriend(_ account: String, _ completion: @escaping (NSError?) -> Void) { + let request = AddFriendRequest() + request.account = account + request.operationType = .addRequest + contactRepo.addFriend(request: request, completion) + } + + public func deleteFriend(account: String, _ completion: @escaping (NSError?) -> Void) { + contactRepo.deleteFriend(account: account, completion) + } + + public func isFriend(account: String) -> Bool { + contactRepo.isFriend(account: account) + } + + public func isBlack(account: String) -> Bool { + contactRepo.isBlackList(account: account) + } + + public func update(_ user: User, _ completion: @escaping (Error?) -> Void) { + contactRepo.updateUser(user, completion) + } + + public func getUserInfo(_ uid: String, _ completion: @escaping (Error?, User?) -> Void) { + contactRepo.getUserInfo(uid) { error, users in + completion(error, users.first) } - + } } diff --git a/NEContactUIKit/NEKitContactUI/Classes/ViewModel/ContactViewModel.swift b/NEContactUIKit/NEKitContactUI/Classes/ViewModel/ContactViewModel.swift index a960bed6..ae51e947 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/ViewModel/ContactViewModel.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/ViewModel/ContactViewModel.swift @@ -1,7 +1,7 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NEKitContact @@ -9,127 +9,122 @@ import NEKitCoreIM import UIKit public class ContactViewModel: ContactRepoSystemNotiDelegate { - - typealias RefreshBlock = () -> Void - public var contacts: [ContactSection] = [] - public var indexs: [String]? - private var contactHeaders: [ContactHeadItem]? - public var contactRepo = ContactRepo() - private var initalDict: [String: [ContactInfo]] = ["#":[]] - - var unreadCount = 0 - - var refresh: RefreshBlock? - init(contactHeaders: [ContactHeadItem]?) { - contactRepo.notiDelegate = self - unreadCount = contactRepo.getNotificationUnreadCount() - self.contactHeaders = contactHeaders + typealias RefreshBlock = () -> Void + public var contacts: [ContactSection] = [] + public var indexs: [String]? + private var contactHeaders: [ContactHeadItem]? + public var contactRepo = ContactRepo() + private var initalDict: [String: [ContactInfo]] = ["#": []] + + var unreadCount = 0 + + var refresh: RefreshBlock? + init(contactHeaders: [ContactHeadItem]?) { + contactRepo.notiDelegate = self + unreadCount = contactRepo.getNotificationUnreadCount() + self.contactHeaders = contactHeaders + } + + public func onNotificationUnreadCountChanged(_ count: Int) { + print("onNotificationUnreadCountChanged : ", count) + unreadCount = count + if let block = refresh { + block() + } + } + + public func onRecieveNotification(_ notification: XNotification) {} + + func loadData(_ filters: Set? = nil) { + initalDict = ["#": []] + contacts = getContactList(filters) + indexs = getIndexs(contactSections: contacts) + guard let headSection = headerSection(headerItem: contactHeaders) else { + return } - - public func onNotificationUnreadCountChanged(_ count: Int) { - print("onNotificationUnreadCountChanged : ", count) - unreadCount = count - if let block = refresh { - block() + contacts.insert(headSection, at: 0) + } + + func getContactList(_ filters: Set? = nil) -> [ContactSection] { + var contactList: [ContactSection] = [] + var users = contactRepo.getFriendList() + + if let filterUsers = filters { + users = users.filter { user in + if let uid = user.userId, filterUsers.contains(uid) { + return false } + return true + } } - - public func onRecieveNotification(_ notification: XNotification) { - + + if users.isEmpty { + return contactList } - - func loadData(_ filters: Set? = nil) { - initalDict = ["#":[]] - contacts = getContactList(filters) - indexs = getIndexs(contactSections: contacts) - guard let headSection = headerSection(headerItem: self.contactHeaders) else { - return - } - contacts.insert(headSection, at: 0) + for contact: User in users { + // get inital of name + var name = contact.alias != nil ? contact.alias : contact.userInfo?.nickName + if name == nil { + name = contact.userId + } + let inital = name?.initalLetter() + let contactInfo = ContactInfo() + contactInfo.user = contact + contactInfo.headerBackColor = UIColor.colorWithString(string: contact.showName() ?? "") + + var contactsTemp = initalDict[inital!] + if contactsTemp == nil { + contactsTemp = [contactInfo] + initalDict[inital!] = contactsTemp + } else { + initalDict[inital!]?.append(contactInfo) + } } - - func getContactList(_ filters: Set? = nil) -> [ContactSection] { - var contactList: [ContactSection] = [] - var users = contactRepo.getFriendList() - - if let filterUsers = filters { - users = users.filter({ user in - if let uid = user.userId, filterUsers.contains(uid) { - return false - } - return true - }) - } - - if users.isEmpty { - return contactList - } - for contact: User in users { - // get inital of name - var name = contact.alias != nil ? contact.alias : contact.userInfo?.nickName - if name == nil { - name = contact.userId - } - let inital = name?.initalLetter() - let contactInfo = ContactInfo() - contactInfo.user = contact - contactInfo.headerBackColor = UIColor.colorWithString(string: contact.showName() ?? "") - - var contactsTemp = initalDict[inital!] - if contactsTemp == nil { - contactsTemp = [contactInfo] - initalDict[inital!] = contactsTemp - }else { - initalDict[inital!]?.append(contactInfo) - } - } - - for key in initalDict.keys { - contactList.append(ContactSection(initial: key, contacts: initalDict[key]!)) - } - - // sort by inital - return contactList.sorted { s1, s2 in - return s1.initial < s2.initial - } + + for key in initalDict.keys { + contactList.append(ContactSection(initial: key, contacts: initalDict[key]!)) } - - func headerSection(headerItem: [ContactHeadItem]?) -> ContactSection? { - guard let header = headerItem else { - return nil - } - var infos: [ContactInfo] = [] - for item in header { - let user = User() - user.alias = item.name - let userInfo = UserInfo(nickName: "", avatar: item.imageName) - user.userInfo = userInfo - - let info = ContactInfo() - info.user = user - info.contactCellType = ContactCellType.ContactOthers.rawValue - info.router = item.router - info.headerBackColor = item.color - if let _ = user.userId { - info.headerBackColor = UIColor.colorWithString(string: user.userId) - } - infos.append(info) - } - return ContactSection(initial: "", contacts: infos) + + // sort by inital + return contactList.sorted { s1, s2 in + s1.initial < s2.initial } - - func getIndexs(contactSections: [ContactSection]?) -> [String]? { - guard let sections = contactSections else { - return nil - } - var indexs: [String] = [] - for section in sections { - if section.initial.count > 0 { - indexs.append(section.initial) - } - } - return indexs + } + + func headerSection(headerItem: [ContactHeadItem]?) -> ContactSection? { + guard let header = headerItem else { + return nil } - + var infos: [ContactInfo] = [] + for item in header { + let user = User() + user.alias = item.name + let userInfo = UserInfo(nickName: "", avatar: item.imageName) + user.userInfo = userInfo + let info = ContactInfo() + info.user = user + info.contactCellType = ContactCellType.ContactOthers.rawValue + info.router = item.router + info.headerBackColor = item.color + if let _ = user.userId { + info.headerBackColor = UIColor.colorWithString(string: user.userId) + } + infos.append(info) + } + return ContactSection(initial: "", contacts: infos) + } + + func getIndexs(contactSections: [ContactSection]?) -> [String]? { + guard let sections = contactSections else { + return nil + } + var indexs: [String] = [] + for section in sections { + if section.initial.count > 0 { + indexs.append(section.initial) + } + } + return indexs + } } diff --git a/NEContactUIKit/NEKitContactUI/Classes/ViewModel/FindFriendViewModel.swift b/NEContactUIKit/NEKitContactUI/Classes/ViewModel/FindFriendViewModel.swift index afb80e9b..f8a4a4f0 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/ViewModel/FindFriendViewModel.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/ViewModel/FindFriendViewModel.swift @@ -1,18 +1,16 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NEKitContact import NEKitCoreIM class FindFriendViewModel { - - let contactRepo = ContactRepo() - - func searchFriend(_ text: String, _ completion: @escaping ([User]?, NSError?)->()){ - contactRepo.fetchUserInfo(accountList: [text], completion) - } - + let contactRepo = ContactRepo() + + func searchFriend(_ text: String, _ completion: @escaping ([User]?, NSError?) -> Void) { + contactRepo.fetchUserInfo(accountList: [text], completion) + } } diff --git a/NEContactUIKit/NEKitContactUI/Classes/Views/Cell/ContactSelectedCell.swift b/NEContactUIKit/NEKitContactUI/Classes/Views/Cell/ContactSelectedCell.swift index fe964457..406294f5 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/Views/Cell/ContactSelectedCell.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/Views/Cell/ContactSelectedCell.swift @@ -1,57 +1,55 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class ContactSelectedCell: ContactTableViewCell { - - let sImage = UIImageView() - - var sModel: ContactInfo? - - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code + let sImage = UIImageView() + + var sModel: ContactInfo? + + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + } + + override func commonUI() { + super.commonUI() + leftConstraint?.constant = 50 + contentView.addSubview(sImage) + sImage.image = UIImage.ne_imageNamed(name: "unselect") + sImage.highlightedImage = UIImage.ne_imageNamed(name: "select") + sImage.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + sImage.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + sImage.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20), + ]) + } + + override func setModel(_ model: ContactInfo) { + super.setModel(model) + if model.isSelected == false { + sImage.isHighlighted = false + } else { + sImage.isHighlighted = true } + } - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) - - // Configure the view for the selected state - } - - override func commonUI() { - super.commonUI() - leftConstraint?.constant = 50 - contentView.addSubview(sImage) - sImage.image = UIImage.ne_imageNamed(name: "unselect") - sImage.highlightedImage = UIImage.ne_imageNamed(name: "select") - sImage.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - sImage.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - sImage.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20) - ]) - } - - override func setModel(_ model: ContactInfo) { - super.setModel(model) - if model.isSelected == false { - sImage.isHighlighted = false - }else { - sImage.isHighlighted = true - } - } - - func setSelect(){ - sModel?.isSelected = true - sImage.isHighlighted = true - } - - func setUnselect(){ - sModel?.isSelected = false - sImage.isHighlighted = false - } + func setSelect() { + sModel?.isSelected = true + sImage.isHighlighted = true + } + func setUnselect() { + sModel?.isSelected = false + sImage.isHighlighted = false + } } diff --git a/NEContactUIKit/NEKitContactUI/Classes/Views/Cell/ContactUnCheckCell.swift b/NEContactUIKit/NEKitContactUI/Classes/Views/Cell/ContactUnCheckCell.swift index c618f4fe..eb0349ba 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/Views/Cell/ContactUnCheckCell.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/Views/Cell/ContactUnCheckCell.swift @@ -1,43 +1,43 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCommonUI class ContactUnCheckCell: UICollectionViewCell { - - override init(frame: CGRect) { - super.init(frame: frame) - setupUI() - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - } - - func setupUI(){ - contentView.addSubview(avatarImage) - NSLayoutConstraint.activate([ - avatarImage.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - avatarImage.centerXAnchor.constraint(equalTo: contentView.centerXAnchor), - avatarImage.widthAnchor.constraint(equalToConstant: 36), - avatarImage.heightAnchor.constraint(equalToConstant: 36) - ]) - } - - - lazy var avatarImage: NEUserHeaderView = { - let view = NEUserHeaderView(frame: .zero) - view.titleLabel.font = UIFont.systemFont(ofSize: 16.0) - view.layer.cornerRadius = 18 - view.clipsToBounds = true - view.translatesAutoresizingMaskIntoConstraints = false - return view - }() - - func configure(_ model: ContactInfo){ - avatarImage.configHeadData(headUrl: model.user?.userInfo?.avatarUrl, name: model.user?.showName() ?? "") + override init(frame: CGRect) { + super.init(frame: frame) + setupUI() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + func setupUI() { + contentView.addSubview(avatarImage) + NSLayoutConstraint.activate([ + avatarImage.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + avatarImage.centerXAnchor.constraint(equalTo: contentView.centerXAnchor), + avatarImage.widthAnchor.constraint(equalToConstant: 36), + avatarImage.heightAnchor.constraint(equalToConstant: 36), + ]) + } + + lazy var avatarImage: NEUserHeaderView = { + let view = NEUserHeaderView(frame: .zero) + view.titleLabel.font = UIFont.systemFont(ofSize: 16.0) + view.layer.cornerRadius = 18 + view.clipsToBounds = true + view.translatesAutoresizingMaskIntoConstraints = false + return view + }() - } + func configure(_ model: ContactInfo) { + avatarImage.configHeadData( + headUrl: model.user?.userInfo?.avatarUrl, + name: model.user?.showName() ?? "" + ) + } } diff --git a/NEContactUIKit/NEKitContactUI/Classes/Views/ContactBaseViewController.swift b/NEContactUIKit/NEKitContactUI/Classes/Views/ContactBaseViewController.swift index 9ce8af76..78ed154e 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/Views/ContactBaseViewController.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/Views/ContactBaseViewController.swift @@ -1,41 +1,43 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit open class ContactBaseViewController: UIViewController { - - public override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - self.view.backgroundColor = .white - edgesForExtendedLayout = [] - - setupBackUI() - } - - private func setupBackUI(){ - self.navigationController?.navigationBar.tintColor = .white - let backItem = UIBarButtonItem(image: UIImage.ne_imageNamed(name: "backArrow"), style: .plain, target: self, action: #selector(backToPrevious)) - backItem.tintColor = UIColor(hexString: "333333") - self.navigationItem.leftBarButtonItem = backItem - } - - - @objc func backToPrevious(){ - self.navigationController?.popViewController(animated: true) - } - /* - // MARK: - Navigation - - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. - } - */ - + override public func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + view.backgroundColor = .white + edgesForExtendedLayout = [] + + setupBackUI() + } + + private func setupBackUI() { + navigationController?.navigationBar.tintColor = .white + let backItem = UIBarButtonItem( + image: UIImage.ne_imageNamed(name: "backArrow"), + style: .plain, + target: self, + action: #selector(backToPrevious) + ) + backItem.tintColor = UIColor(hexString: "333333") + navigationItem.leftBarButtonItem = backItem + } + + @objc func backToPrevious() { + navigationController?.popViewController(animated: true) + } + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ } diff --git a/NEContactUIKit/NEKitContactUI/Classes/Views/ContactHeadItem.swift b/NEContactUIKit/NEKitContactUI/Classes/Views/ContactHeadItem.swift index 2862179e..9e325ef0 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/Views/ContactHeadItem.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/Views/ContactHeadItem.swift @@ -1,20 +1,20 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation public class ContactHeadItem { - public var name: String? - public var imageName: String? - public var color = UIColor(hexString: "#60CFA7") - public var router: String - - init(name: String, imageName: String?, router: String, color: UIColor) { - self.name = name - self.imageName = imageName - self.router = router - self.color = color - } + public var name: String? + public var imageName: String? + public var color = UIColor(hexString: "#60CFA7") + public var router: String + + init(name: String, imageName: String?, router: String, color: UIColor) { + self.name = name + self.imageName = imageName + self.router = router + self.color = color + } } diff --git a/NEContactUIKit/NEKitContactUI/Classes/Views/ContactSectionView.swift b/NEContactUIKit/NEKitContactUI/Classes/Views/ContactSectionView.swift index 18c32095..8c38e027 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/Views/ContactSectionView.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/Views/ContactSectionView.swift @@ -1,45 +1,45 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit public class ContactSectionView: UITableViewHeaderFooterView { - public var titleLabel = UILabel() - var line = UIView() - - override init(reuseIdentifier: String?) { - super.init(reuseIdentifier: reuseIdentifier) - commonUI() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func commonUI() { - self.contentView.backgroundColor = .white - self.titleLabel.translatesAutoresizingMaskIntoConstraints = false - - self.titleLabel.textColor = NEKitContactConfig.shared.ui.indexTitleColor - self.titleLabel.font = UIFont.systemFont(ofSize: 14.0) - self.addSubview(self.titleLabel) - NSLayoutConstraint.activate([ - self.titleLabel.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 20), - self.titleLabel.topAnchor.constraint(equalTo: self.topAnchor), - self.titleLabel.bottomAnchor.constraint(equalTo: self.bottomAnchor), - self.titleLabel.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -20) - ]) - - self.line.translatesAutoresizingMaskIntoConstraints = false - self.line.backgroundColor = NEKitContactConfig.shared.ui.divideLineColor - self.addSubview(self.line) - NSLayoutConstraint.activate([ - self.line.leftAnchor.constraint(equalTo: self.titleLabel.leftAnchor), - self.line.heightAnchor.constraint(equalToConstant: 1.0), - self.line.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -1.0), - self.line.rightAnchor.constraint(equalTo: self.rightAnchor) - ]) - } + public var titleLabel = UILabel() + var line = UIView() + + override init(reuseIdentifier: String?) { + super.init(reuseIdentifier: reuseIdentifier) + commonUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func commonUI() { + contentView.backgroundColor = .white + titleLabel.translatesAutoresizingMaskIntoConstraints = false + + titleLabel.textColor = NEKitContactConfig.shared.ui.indexTitleColor + titleLabel.font = UIFont.systemFont(ofSize: 14.0) + addSubview(titleLabel) + NSLayoutConstraint.activate([ + titleLabel.leftAnchor.constraint(equalTo: leftAnchor, constant: 20), + titleLabel.topAnchor.constraint(equalTo: topAnchor), + titleLabel.bottomAnchor.constraint(equalTo: bottomAnchor), + titleLabel.rightAnchor.constraint(equalTo: rightAnchor, constant: -20), + ]) + + line.translatesAutoresizingMaskIntoConstraints = false + line.backgroundColor = NEKitContactConfig.shared.ui.divideLineColor + addSubview(line) + NSLayoutConstraint.activate([ + line.leftAnchor.constraint(equalTo: titleLabel.leftAnchor), + line.heightAnchor.constraint(equalToConstant: 1.0), + line.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -1.0), + line.rightAnchor.constraint(equalTo: rightAnchor), + ]) + } } diff --git a/NEContactUIKit/NEKitContactUI/Classes/Views/ContactTableViewCell.swift b/NEContactUIKit/NEKitContactUI/Classes/Views/ContactTableViewCell.swift index 62267fa0..bc8db4ee 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/Views/ContactTableViewCell.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/Views/ContactTableViewCell.swift @@ -1,121 +1,114 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCoreIM import Foundation import NEKitCore - public class ContactTableViewCell: ContactBaseViewCell, ContactCellDataProtrol { - - - - public lazy var arrow: UIImageView = { - let imageView = UIImageView(image:UIImage.ne_imageNamed(name: "arrowRight")) - imageView.translatesAutoresizingMaskIntoConstraints = false - imageView.contentMode = .center - return imageView - }() - - lazy var redAngleView: RedAngleLabel = { - let label = RedAngleLabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.font = UIFont.systemFont(ofSize: 12.0) - label.textColor = .white - label.text = "1" - label.backgroundColor = UIColor(hexString: "F24957") - label.textInsets = UIEdgeInsets(top: 3, left: 7, bottom: 3, right: 7) - label.layer.cornerRadius = 9 - label.clipsToBounds = true - label.isHidden = true - return label - }() - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - self.commonUI() - initSubviewsLayout() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func commonUI() { - - //circle avatar head image with name suffix string - setupCommonCircleHeader() - - self.contentView.addSubview(self.titleLabel) - NSLayoutConstraint.activate([ - self.titleLabel.leftAnchor.constraint(equalTo: self.avatarImage.rightAnchor, constant: 12), - self.titleLabel.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -35), - self.titleLabel.topAnchor.constraint(equalTo: self.contentView.topAnchor), - self.titleLabel.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor) - ]) - - self.contentView.addSubview(self.arrow) - NSLayoutConstraint.activate([ - self.arrow.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -20), - self.arrow.widthAnchor.constraint(equalToConstant: 15), - self.arrow.topAnchor.constraint(equalTo: self.contentView.topAnchor), - self.arrow.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor) - ]) - - contentView.addSubview(redAngleView) - NSLayoutConstraint.activate([ - redAngleView.centerYAnchor.constraint(equalTo: arrow.centerYAnchor), - redAngleView.rightAnchor.constraint(equalTo: arrow.leftAnchor, constant: -10) - ]) - } - - func initSubviewsLayout(){ - if NEKitContactConfig.shared.ui.avatarType == .rectangle { - avatarImage.layer.cornerRadius = NEKitContactConfig.shared.ui.avatarCornerRadius - }else if NEKitContactConfig.shared.ui.avatarType == .cycle { - avatarImage.layer.cornerRadius = 18.0 - } + public lazy var arrow: UIImageView = { + let imageView = UIImageView(image: UIImage.ne_imageNamed(name: "arrowRight")) + imageView.translatesAutoresizingMaskIntoConstraints = false + imageView.contentMode = .center + return imageView + }() + + lazy var redAngleView: RedAngleLabel = { + let label = RedAngleLabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.font = UIFont.systemFont(ofSize: 12.0) + label.textColor = .white + label.text = "1" + label.backgroundColor = UIColor(hexString: "F24957") + label.textInsets = UIEdgeInsets(top: 3, left: 7, bottom: 3, right: 7) + label.layer.cornerRadius = 9 + label.clipsToBounds = true + label.isHidden = true + return label + }() + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + commonUI() + initSubviewsLayout() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func commonUI() { + // circle avatar head image with name suffix string + setupCommonCircleHeader() + + contentView.addSubview(titleLabel) + NSLayoutConstraint.activate([ + titleLabel.leftAnchor.constraint(equalTo: avatarImage.rightAnchor, constant: 12), + titleLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -35), + titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor), + titleLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + ]) + + contentView.addSubview(arrow) + NSLayoutConstraint.activate([ + arrow.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), + arrow.widthAnchor.constraint(equalToConstant: 15), + arrow.topAnchor.constraint(equalTo: contentView.topAnchor), + arrow.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + ]) + + contentView.addSubview(redAngleView) + NSLayoutConstraint.activate([ + redAngleView.centerYAnchor.constraint(equalTo: arrow.centerYAnchor), + redAngleView.rightAnchor.constraint(equalTo: arrow.leftAnchor, constant: -10), + ]) + } + + func initSubviewsLayout() { + if NEKitContactConfig.shared.ui.avatarType == .rectangle { + avatarImage.layer.cornerRadius = NEKitContactConfig.shared.ui.avatarCornerRadius + } else if NEKitContactConfig.shared.ui.avatarType == .cycle { + avatarImage.layer.cornerRadius = 18.0 } - - - - func setConfig(){ - self.titleLabel.font = NEKitContactConfig.shared.ui.titleFont - self.titleLabel.textColor = NEKitContactConfig.shared.ui.titleColor - self.nameLabel.font = UIFont.systemFont(ofSize: 14.0) - self.nameLabel.textColor = UIColor.white + } + + func setConfig() { + titleLabel.font = NEKitContactConfig.shared.ui.titleFont + titleLabel.textColor = NEKitContactConfig.shared.ui.titleColor + nameLabel.font = UIFont.systemFont(ofSize: 14.0) + nameLabel.textColor = UIColor.white + } + + public func setModel(_ model: ContactInfo) { + guard let user = model.user else { + return } - - public func setModel(_ model: ContactInfo) { - guard let user = model.user else { - return - } - setConfig() - - if model.contactCellType == 2 { - // person - self.titleLabel.text = user.showName() - self.nameLabel.text = user.shortName(count: 2) + setConfig() + + if model.contactCellType == 2 { + // person + titleLabel.text = user.showName() + nameLabel.text = user.shortName(count: 2) // self.nameLabel.backgroundColor = UIColor(hexString: user.userId!) - if let imageUrl = user.userInfo?.avatarUrl { - self.nameLabel.isHidden = true - self.avatarImage.sd_setImage(with: URL(string: imageUrl), completed: nil) - }else { - self.nameLabel.isHidden = false - self.avatarImage.image = nil - } - self.arrow.isHidden = true - - }else { - self.nameLabel.text = "" - self.titleLabel.text = user.alias - self.avatarImage.image = UIImage.ne_imageNamed(name: user.userInfo?.avatarUrl) - self.avatarImage.backgroundColor = model.headerBackColor - self.arrow.isHidden = false - } + if let imageUrl = user.userInfo?.avatarUrl { + nameLabel.isHidden = true + avatarImage.sd_setImage(with: URL(string: imageUrl), completed: nil) + } else { + nameLabel.isHidden = false + avatarImage.image = nil + } + arrow.isHidden = true + + } else { + nameLabel.text = "" + titleLabel.text = user.alias + avatarImage.image = UIImage.ne_imageNamed(name: user.userInfo?.avatarUrl) + avatarImage.backgroundColor = model.headerBackColor + arrow.isHidden = false } + } } diff --git a/NEContactUIKit/NEKitContactUI/Classes/Views/ContactsSelectedViewController.swift b/NEContactUIKit/NEKitContactUI/Classes/Views/ContactsSelectedViewController.swift index 8e1ae564..3ed22f17 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/Views/ContactsSelectedViewController.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/Views/ContactsSelectedViewController.swift @@ -1,9 +1,7 @@ -// -// ContactsSelectedViewController.swift -// NEKitContactUI -// -// Created by yu chen on 2022/1/17. -// + +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import Toast_Swift @@ -11,271 +9,291 @@ import NEKitCore import NIMSDK open class ContactsSelectedViewController: ContactBaseViewController { - - public var callBack: ContactsSelectCompletion? - - public var filterUsers: Set? - - public var limit = 10 //max select count - - var selectArray = [ContactInfo]() - let selectDic = [String : ContactInfo]() - lazy var collection : UICollectionView = { - let layout = UICollectionViewFlowLayout() - layout.scrollDirection = .horizontal - layout.minimumLineSpacing = 0 - layout.minimumInteritemSpacing = 0 - let collect = UICollectionView(frame: CGRect.zero, collectionViewLayout: layout) - collect.contentInset = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5) - return collect - }() - - let sureBtn = UIButton(frame: CGRect(x: 0, y: 0, width: 80, height: 44)) - - var collectionHeight: NSLayoutConstraint? - - public var customCells:[Int : ContactTableViewCell.Type] = [ContactCellType.ContactPerson.rawValue : ContactSelectedCell.self] // custom ui cell - - let viewModel = ContactViewModel(contactHeaders: nil) - - let tableView = UITableView() - - public override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - self.title = "选择" - setupUI() - setupNavRightItem() - - viewModel.loadData(filterUsers) - self.tableView.reloadData() - - } - - public override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - navigationController?.isNavigationBarHidden = false - } - - func setupUI(){ - - view.addSubview(collection) - collection.delegate = self - collection.dataSource = self - collection.allowsMultipleSelection = false - collection.translatesAutoresizingMaskIntoConstraints = false - collectionHeight = collection.heightAnchor.constraint(equalToConstant: 0) - collectionHeight?.isActive = true - collection.backgroundColor = UIColor(hexString: "F2F4F5") - NSLayoutConstraint.activate([ - collection.topAnchor.constraint(equalTo: view.topAnchor), - collection.leftAnchor.constraint(equalTo: view.leftAnchor), - collection.rightAnchor.constraint(equalTo: view.rightAnchor) - ]) - collection.register(ContactUnCheckCell.self, forCellWithReuseIdentifier: "\(NSStringFromClass(ContactUnCheckCell.self))") - - view.addSubview(tableView) - tableView.delegate = self - tableView.dataSource = self - tableView.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - tableView.leftAnchor.constraint(equalTo: view.leftAnchor), - tableView.rightAnchor.constraint(equalTo: view.rightAnchor), - tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), - tableView.topAnchor.constraint(equalTo: collection.bottomAnchor) - ]) - - customCells.forEach { (key: Int, value: AnyClass) in - if value is ContactCellDataProtrol.Type { - self.tableView.register(value, forCellReuseIdentifier: "\(NSStringFromClass(value))") - } - } - tableView.register(ContactSectionView.self, forHeaderFooterViewReuseIdentifier: "\(NSStringFromClass(ContactSectionView.self))") - tableView.rowHeight = 52 - tableView.sectionHeaderHeight = 40 - tableView.sectionFooterHeight = 0 - tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.1)) - tableView.separatorStyle = .none - - } - - func setupNavRightItem(){ - let rightItem = UIBarButtonItem(customView: sureBtn) - self.navigationItem.rightBarButtonItem = rightItem - sureBtn.addTarget(self, action: #selector(sureClick(_:)), for: .touchUpInside) - sureBtn.setTitle("确定", for: .normal) - sureBtn.setTitleColor(UIColor(hexString: "337EFF"), for: .normal) - sureBtn.titleLabel?.font = UIFont.systemFont(ofSize: 16.0) - sureBtn.contentHorizontalAlignment = .right - } - + public var callBack: ContactsSelectCompletion? - /* - // MARK: - Navigation + public var filterUsers: Set? - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. - } - */ + public var limit = 10 // max select count -} + var selectArray = [ContactInfo]() + let selectDic = [String: ContactInfo]() + lazy var collection: UICollectionView = { + let layout = UICollectionViewFlowLayout() + layout.scrollDirection = .horizontal + layout.minimumLineSpacing = 0 + layout.minimumInteritemSpacing = 0 + let collect = UICollectionView(frame: CGRect.zero, collectionViewLayout: layout) + collect.contentInset = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5) + return collect + }() -//action -extension ContactsSelectedViewController { - - @objc func sureClick(_ sender: UIButton){ - if selectArray.count <= 0 { - view.makeToast("请选择联系人") - return - } - if let completion = callBack { - completion(selectArray) - } - var accids = [String]() - var names = [String]() - - names.append(viewModel.contactRepo.getUserName()) - - var users = [NIMUser]() - for c in selectArray { - accids.append(c.user?.userId ?? "") - if let name = c.user?.userInfo?.nickName { - names.append(name) - }else if let accid = c.user?.userId{ - names.append(accid) - } - if let user = c.user?.imUser { - users.append(user) - } - } - - - let nameString = names.joined(separator: "、") - print("name string : ", nameString) - Router.shared.use(ContactSelectedUsersRouter, parameters: ["accids":accids, "names":nameString, "im_user": users], closure: nil) - self.navigationController?.popViewController(animated: true) + let sureBtn = UIButton(frame: CGRect(x: 0, y: 0, width: 80, height: 44)) + + var collectionHeight: NSLayoutConstraint? + + public var customCells: [Int: ContactTableViewCell.Type] = + [ContactCellType.ContactPerson.rawValue: ContactSelectedCell.self] // custom ui cell + + let viewModel = ContactViewModel(contactHeaders: nil) + + let tableView = UITableView() + + override public func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + title = "选择" + setupUI() + setupNavRightItem() + + viewModel.loadData(filterUsers) + tableView.reloadData() + } + + override public func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + navigationController?.isNavigationBarHidden = false + } + + func setupUI() { + view.addSubview(collection) + collection.delegate = self + collection.dataSource = self + collection.allowsMultipleSelection = false + collection.translatesAutoresizingMaskIntoConstraints = false + collectionHeight = collection.heightAnchor.constraint(equalToConstant: 0) + collectionHeight?.isActive = true + collection.backgroundColor = UIColor(hexString: "F2F4F5") + NSLayoutConstraint.activate([ + collection.topAnchor.constraint(equalTo: view.topAnchor), + collection.leftAnchor.constraint(equalTo: view.leftAnchor), + collection.rightAnchor.constraint(equalTo: view.rightAnchor), + ]) + collection.register( + ContactUnCheckCell.self, + forCellWithReuseIdentifier: "\(NSStringFromClass(ContactUnCheckCell.self))" + ) + + view.addSubview(tableView) + tableView.delegate = self + tableView.dataSource = self + tableView.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + tableView.leftAnchor.constraint(equalTo: view.leftAnchor), + tableView.rightAnchor.constraint(equalTo: view.rightAnchor), + tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), + tableView.topAnchor.constraint(equalTo: collection.bottomAnchor), + ]) + + customCells.forEach { (key: Int, value: AnyClass) in + if value is ContactCellDataProtrol.Type { + self.tableView.register( + value, + forCellReuseIdentifier: "\(NSStringFromClass(value))" + ) + } } + tableView.register( + ContactSectionView.self, + forHeaderFooterViewReuseIdentifier: "\(NSStringFromClass(ContactSectionView.self))" + ) + tableView.rowHeight = 52 + tableView.sectionHeaderHeight = 40 + tableView.sectionFooterHeight = 0 + tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.1)) + tableView.separatorStyle = .none + } + + func setupNavRightItem() { + let rightItem = UIBarButtonItem(customView: sureBtn) + navigationItem.rightBarButtonItem = rightItem + sureBtn.addTarget(self, action: #selector(sureClick(_:)), for: .touchUpInside) + sureBtn.setTitle("确定", for: .normal) + sureBtn.setTitleColor(UIColor(hexString: "337EFF"), for: .normal) + sureBtn.titleLabel?.font = UIFont.systemFont(ofSize: 16.0) + sureBtn.contentHorizontalAlignment = .right + } + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ } -extension ContactsSelectedViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, UITableViewDelegate, UITableViewDataSource { - - // MARK: - Table View DataSource And Delegate - - public func numberOfSections(in tableView: UITableView) -> Int { - return viewModel.contacts.count - } - - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return viewModel.contacts[section].contacts.count - } - - public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let info = viewModel.contacts[indexPath.section].contacts[indexPath.row] - if let cellClass = customCells[info.contactCellType]{ - let anyCell = tableView.dequeueReusableCell(withIdentifier: "\(NSStringFromClass(cellClass))", for: indexPath) as? ContactTableViewCell - anyCell?.setModel(info) - if let cell = anyCell { - return cell - } - } - return UITableViewCell() - } - - public func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { - let sectionView: ContactSectionView = tableView.dequeueReusableHeaderFooterView(withIdentifier: "\(NSStringFromClass(ContactSectionView.self))") as! ContactSectionView - sectionView.titleLabel.text = viewModel.contacts[section].initial - return sectionView - } - - public func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { - if viewModel.contacts[section].initial.count > 0 { - return 40 - } - return 0 +// action +extension ContactsSelectedViewController { + @objc func sureClick(_ sender: UIButton) { + if selectArray.count <= 0 { + view.makeToast("请选择联系人") + return } - - public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - - let info = viewModel.contacts[indexPath.section].contacts[indexPath.row] - let cell = tableView.cellForRow(at: indexPath) as? ContactSelectedCell - if info.isSelected == true { - didUnselectContact(info) - cell?.setSelect() - }else { - - if selectArray.count >= limit { - view.makeToast("超出\(limit)人限制") - return - } - didSelectContact(info) - cell?.setUnselect() - } + if let completion = callBack { + completion(selectArray) } - - public func sectionIndexTitles(for tableView: UITableView) -> [String]? { - return viewModel.indexs + var accids = [String]() + var names = [String]() + + names.append(viewModel.contactRepo.getUserName()) + + var users = [NIMUser]() + for c in selectArray { + accids.append(c.user?.userId ?? "") + if let name = c.user?.userInfo?.nickName { + names.append(name) + } else if let accid = c.user?.userId { + names.append(accid) + } + if let user = c.user?.imUser { + users.append(user) + } } - - // MARK: Collection View DataSource And Delegate - - public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - return selectArray.count + + let nameString = names.joined(separator: "、") + print("name string : ", nameString) + Router.shared.use( + ContactSelectedUsersRouter, + parameters: ["accids": accids, "names": nameString, "im_user": users], + closure: nil + ) + navigationController?.popViewController(animated: true) + } +} + +extension ContactsSelectedViewController: UICollectionViewDelegate, UICollectionViewDataSource, + UICollectionViewDelegateFlowLayout, UITableViewDelegate, UITableViewDataSource { + // MARK: - Table View DataSource And Delegate + + public func numberOfSections(in tableView: UITableView) -> Int { + viewModel.contacts.count + } + + public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + viewModel.contacts[section].contacts.count + } + + public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let info = viewModel.contacts[indexPath.section].contacts[indexPath.row] + if let cellClass = customCells[info.contactCellType] { + let anyCell = tableView.dequeueReusableCell( + withIdentifier: "\(NSStringFromClass(cellClass))", + for: indexPath + ) as? ContactTableViewCell + anyCell?.setModel(info) + if let cell = anyCell { + return cell + } } - - public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - let contactInfo = selectArray[indexPath.row] - didUnselectContact(contactInfo) + return UITableViewCell() + } + + public func tableView(_ tableView: UITableView, + viewForHeaderInSection section: Int) -> UIView? { + let sectionView: ContactSectionView = tableView + .dequeueReusableHeaderFooterView( + withIdentifier: "\(NSStringFromClass(ContactSectionView.self))" + ) as! ContactSectionView + sectionView.titleLabel.text = viewModel.contacts[section].initial + return sectionView + } + + public func tableView(_ tableView: UITableView, + heightForHeaderInSection section: Int) -> CGFloat { + if viewModel.contacts[section].initial.count > 0 { + return 40 } - - public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { - let contactInfo = selectArray[indexPath.row] - let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "\(NSStringFromClass(ContactUnCheckCell.self))", for: indexPath) as? ContactUnCheckCell - cell?.configure(contactInfo) - return cell ?? UICollectionViewCell() + return 0 + } + + public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + let info = viewModel.contacts[indexPath.section].contacts[indexPath.row] + let cell = tableView.cellForRow(at: indexPath) as? ContactSelectedCell + if info.isSelected == true { + didUnselectContact(info) + cell?.setSelect() + } else { + if selectArray.count >= limit { + view.makeToast("超出\(limit)人限制") + return + } + didSelectContact(info) + cell?.setUnselect() } - - public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { - return CGSize(width: 46, height: 52) + } + + public func sectionIndexTitles(for tableView: UITableView) -> [String]? { + viewModel.indexs + } + + // MARK: Collection View DataSource And Delegate + + public func collectionView(_ collectionView: UICollectionView, + numberOfItemsInSection section: Int) -> Int { + selectArray.count + } + + public func collectionView(_ collectionView: UICollectionView, + didSelectItemAt indexPath: IndexPath) { + let contactInfo = selectArray[indexPath.row] + didUnselectContact(contactInfo) + } + + public func collectionView(_ collectionView: UICollectionView, + cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + let contactInfo = selectArray[indexPath.row] + let cell = collectionView.dequeueReusableCell( + withReuseIdentifier: "\(NSStringFromClass(ContactUnCheckCell.self))", + for: indexPath + ) as? ContactUnCheckCell + cell?.configure(contactInfo) + return cell ?? UICollectionViewCell() + } + + public func collectionView(_ collectionView: UICollectionView, + layout collectionViewLayout: UICollectionViewLayout, + sizeForItemAt indexPath: IndexPath) -> CGSize { + CGSize(width: 46, height: 52) + } + + func didSelectContact(_ contact: ContactInfo) { + contact.isSelected = true + if selectArray.contains(where: { c in + contact === c + }) == false { + selectArray.append(contact) + if let height = collectionHeight?.constant, height <= 0 { + collectionHeight?.constant = 52 + } } + collection.reloadData() + tableView.reloadData() + refreshSelectCount() + } - func didSelectContact(_ contact: ContactInfo){ - contact.isSelected = true - if selectArray.contains(where: { c in - return contact === c - }) == false { - selectArray.append(contact) - if let height = collectionHeight?.constant, height <= 0 { - collectionHeight?.constant = 52 - } - } - collection.reloadData() - tableView.reloadData() - refreshSelectCount() + func didUnselectContact(_ contact: ContactInfo) { + contact.isSelected = false + selectArray.removeAll { c in + contact === c } - - func didUnselectContact(_ contact: ContactInfo){ - contact.isSelected = false - selectArray.removeAll { c in - return contact === c - } - if selectArray.count <= 0 { - collection.reloadData() - collectionHeight?.constant = 0 - } - collection.reloadData() - tableView.reloadData() - refreshSelectCount() + if selectArray.count <= 0 { + collection.reloadData() + collectionHeight?.constant = 0 } - - func refreshSelectCount(){ - if selectArray.count > 0 { - sureBtn.setTitle("确定(\(selectArray.count))", for: .normal) - }else { - sureBtn.setTitle("确定", for: .normal) - } + collection.reloadData() + tableView.reloadData() + refreshSelectCount() + } + + func refreshSelectCount() { + if selectArray.count > 0 { + sureBtn.setTitle("确定(\(selectArray.count))", for: .normal) + } else { + sureBtn.setTitle("确定", for: .normal) } - + } } diff --git a/NEContactUIKit/NEKitContactUI/Classes/Views/ContactsViewController.swift b/NEContactUIKit/NEKitContactUI/Classes/Views/ContactsViewController.swift index c65df355..e282266f 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/Views/ContactsViewController.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/Views/ContactsViewController.swift @@ -1,242 +1,277 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCoreIM import NEKitCore +open class ContactsViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, + SystemMessageProviderDelegate, FriendProviderDelegate { + public var customCells: [Int: ContactTableViewCell.Type] = [ + ContactCellType.ContactPerson.rawValue: ContactTableViewCell.self, + ContactCellType.ContactOthers.rawValue: ContactTableViewCell.self, + ] // custom ui cell -open class ContactsViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, SystemMessageProviderDelegate,FriendProviderDelegate { - - - - public var customCells:[Int : ContactTableViewCell.Type] = [ContactCellType.ContactPerson.rawValue : ContactTableViewCell.self, ContactCellType.ContactOthers.rawValue : ContactTableViewCell.self] // custom ui cell - - public var clickCallBacks = [Int : ConttactClickCallBack]() - - var tableView = UITableView(frame: .zero, style: .grouped) - var viewModel = ContactViewModel(contactHeaders: [ - ContactHeadItem(name: "验证消息", imageName: "valid", router: ValidationMessageRouter, color: UIColor(hexString: "#60CFA7")), - ContactHeadItem(name: "黑名单", imageName: "blackName", router: ContactBlackListRouter, color: UIColor(hexString: "#53C3F3")), - ContactHeadItem(name: "我的群聊", imageName: "group", router: ContactGroupRouter, color: UIColor(hexString: "#BE65D9"))] - ) - - @objc - public init(){ - super.init(nibName: nil, bundle: nil) - viewModel.contactRepo.addNotificationDelegate(delegate: self) - viewModel.contactRepo.addContactDelegate(delegate: self) - } - - required public init?(coder: NSCoder) { - super.init(coder: coder) - } - - @objc - public override func viewDidLoad() { - super.viewDidLoad() - weak var weakSelf = self - viewModel.refresh = { - weakSelf?.tableView.reloadData() - } - addNavbarAction() - commonUI() - } - - public override func viewWillAppear(_ animated: Bool) { - loadData() - } - - @objc - func commonUI() { - self.tableView.separatorStyle = .none - self.tableView.delegate = self - self.tableView.dataSource = self - self.tableView.translatesAutoresizingMaskIntoConstraints = false - self.view.addSubview(self.tableView) - NSLayoutConstraint.activate([ - self.tableView.topAnchor.constraint(equalTo: self.view.topAnchor), - self.tableView.leftAnchor.constraint(equalTo: self.view.leftAnchor), - self.tableView.rightAnchor.constraint(equalTo: self.view.rightAnchor), - self.tableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor), - ]) - self.tableView.register(ContactTableViewCell.self, forCellReuseIdentifier: "\(ContactTableViewCell.self)") - self.tableView.register(ContactSectionView.self, forHeaderFooterViewReuseIdentifier: "\(NSStringFromClass(ContactSectionView.self))") - self.tableView.rowHeight = 52 - self.tableView.sectionHeaderHeight = 40 - self.tableView.sectionFooterHeight = 0 - self.tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.1)) - } - - func loadData() { - viewModel.loadData() - self.tableView.reloadData() - } - - // UITableViewDataSource - public func numberOfSections(in tableView: UITableView) -> Int { - return viewModel.contacts.count - } - - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return viewModel.contacts[section].contacts.count - } - - public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let info = viewModel.contacts[indexPath.section].contacts[indexPath.row] - let cell = tableView.dequeueReusableCell(withIdentifier: "\(ContactTableViewCell.self)", for: indexPath) as! ContactTableViewCell - cell.setModel(info) - if indexPath.section == 0 && indexPath.row == 0 && viewModel.unreadCount > 0 { - cell.redAngleView.isHidden = false - cell.redAngleView.text = "\(viewModel.unreadCount)" - }else { - cell.redAngleView.isHidden = true - } - return cell - } - - public func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { - let sectionView: ContactSectionView = tableView.dequeueReusableHeaderFooterView(withIdentifier: "\(NSStringFromClass(ContactSectionView.self))") as! ContactSectionView - sectionView.titleLabel.text = viewModel.contacts[section].initial - return sectionView - } - - public func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { - if viewModel.contacts[section].initial.count > 0 { - return 40 - } - return 0 + public var clickCallBacks = [Int: ConttactClickCallBack]() + + var tableView = UITableView(frame: .zero, style: .grouped) + var viewModel = ContactViewModel(contactHeaders: [ + ContactHeadItem( + name: "验证消息", + imageName: "valid", + router: ValidationMessageRouter, + color: UIColor(hexString: "#60CFA7") + ), + ContactHeadItem( + name: "黑名单", + imageName: "blackName", + router: ContactBlackListRouter, + color: UIColor(hexString: "#53C3F3") + ), + ContactHeadItem( + name: "我的群聊", + imageName: "group", + router: ContactGroupRouter, + color: UIColor(hexString: "#BE65D9") + ), + ]) + + @objc + public init() { + super.init(nibName: nil, bundle: nil) + viewModel.contactRepo.addNotificationDelegate(delegate: self) + viewModel.contactRepo.addContactDelegate(delegate: self) + } + + public required init?(coder: NSCoder) { + super.init(coder: coder) + } + + @objc + override public func viewDidLoad() { + super.viewDidLoad() + weak var weakSelf = self + viewModel.refresh = { + weakSelf?.tableView.reloadData() } - public func sectionIndexTitles(for tableView: UITableView) -> [String]? { - return viewModel.indexs + addNavbarAction() + commonUI() + } + + override public func viewWillAppear(_ animated: Bool) { + loadData() + } + + @objc + func commonUI() { + tableView.separatorStyle = .none + tableView.delegate = self + tableView.dataSource = self + tableView.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(tableView) + NSLayoutConstraint.activate([ + tableView.topAnchor.constraint(equalTo: view.topAnchor), + tableView.leftAnchor.constraint(equalTo: view.leftAnchor), + tableView.rightAnchor.constraint(equalTo: view.rightAnchor), + tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), + ]) + tableView.register( + ContactTableViewCell.self, + forCellReuseIdentifier: "\(ContactTableViewCell.self)" + ) + tableView.register( + ContactSectionView.self, + forHeaderFooterViewReuseIdentifier: "\(NSStringFromClass(ContactSectionView.self))" + ) + tableView.rowHeight = 52 + tableView.sectionHeaderHeight = 40 + tableView.sectionFooterHeight = 0 + tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.1)) + } + + func loadData() { + viewModel.loadData() + tableView.reloadData() + } + + // UITableViewDataSource + public func numberOfSections(in tableView: UITableView) -> Int { + viewModel.contacts.count + } + + public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + viewModel.contacts[section].contacts.count + } + + public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let info = viewModel.contacts[indexPath.section].contacts[indexPath.row] + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(ContactTableViewCell.self)", + for: indexPath + ) as! ContactTableViewCell + cell.setModel(info) + if indexPath.section == 0, indexPath.row == 0, viewModel.unreadCount > 0 { + cell.redAngleView.isHidden = false + cell.redAngleView.text = "\(viewModel.unreadCount)" + } else { + cell.redAngleView.isHidden = true } - - public func tableView(_ tableView: UITableView, sectionForSectionIndexTitle title: String, at index: Int) -> Int { - return index + return cell + } + + public func tableView(_ tableView: UITableView, + viewForHeaderInSection section: Int) -> UIView? { + let sectionView: ContactSectionView = tableView + .dequeueReusableHeaderFooterView( + withIdentifier: "\(NSStringFromClass(ContactSectionView.self))" + ) as! ContactSectionView + sectionView.titleLabel.text = viewModel.contacts[section].initial + return sectionView + } + + public func tableView(_ tableView: UITableView, + heightForHeaderInSection section: Int) -> CGFloat { + if viewModel.contacts[section].initial.count > 0 { + return 40 } - - public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - return 52 + return 0 + } + + public func sectionIndexTitles(for tableView: UITableView) -> [String]? { + viewModel.indexs + } + + public func tableView(_ tableView: UITableView, sectionForSectionIndexTitle title: String, + at index: Int) -> Int { + index + } + + public func tableView(_ tableView: UITableView, + heightForRowAt indexPath: IndexPath) -> CGFloat { + 52 + } + + public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + let info = viewModel.contacts[indexPath.section].contacts[indexPath.row] + if let callBack = clickCallBacks[info.contactCellType] { + callBack(indexPath.row, indexPath.section) + return } - - public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - let info = viewModel.contacts[indexPath.section].contacts[indexPath.row] - if let callBack = clickCallBacks[info.contactCellType] { - callBack(indexPath.row, indexPath.section) - return - } - if info.contactCellType == ContactCellType.ContactOthers.rawValue { - switch info.router { - case ValidationMessageRouter: - viewModel.contactRepo.clearNotificationUnreadCount() - let validationController = ValidationMessageViewController() - validationController.hidesBottomBarWhenPushed = true - self.navigationController?.pushViewController(validationController, animated: true) - break - case ContactBlackListRouter: - let blackVC = BlackListViewController() - blackVC.hidesBottomBarWhenPushed = true - self.navigationController?.pushViewController(blackVC, animated: true) - - break - case ContactGroupRouter: - // My Team - let teamVC = TeamListViewController() - teamVC.hidesBottomBarWhenPushed = true - self.navigationController?.pushViewController(teamVC, animated: true) - - break - case ContactPersonRouter: - - break - - case ContactComputerRouter: + if info.contactCellType == ContactCellType.ContactOthers.rawValue { + switch info.router { + case ValidationMessageRouter: + viewModel.contactRepo.clearNotificationUnreadCount() + let validationController = ValidationMessageViewController() + validationController.hidesBottomBarWhenPushed = true + navigationController?.pushViewController(validationController, animated: true) + case ContactBlackListRouter: + let blackVC = BlackListViewController() + blackVC.hidesBottomBarWhenPushed = true + navigationController?.pushViewController(blackVC, animated: true) + + case ContactGroupRouter: + // My Team + let teamVC = TeamListViewController() + teamVC.hidesBottomBarWhenPushed = true + navigationController?.pushViewController(teamVC, animated: true) + + case ContactPersonRouter: + + break + + case ContactComputerRouter: // let select = ContactsSelectedViewController() // select.callBack = { contacts in // print("select contacs : ", contacts) // } // select.hidesBottomBarWhenPushed = true // self.navigationController?.pushViewController(select, animated: true) - break - default: - break - } - }else { - let userInfoVC = ContactUserViewController(user: info.user) - userInfoVC.hidesBottomBarWhenPushed = true - self.navigationController?.pushViewController(userInfoVC, animated: true) - } + break + default: + break + } + } else { + let userInfoVC = ContactUserViewController(user: info.user) + userInfoVC.hidesBottomBarWhenPushed = true + navigationController?.pushViewController(userInfoVC, animated: true) } - + } + // MARK: SystemMessageProviderDelegate - public func onRecieveNotification(notification: XNotification) { - print("onRecieveNotification type:\(notification.type)") - if notification.type == .addFriendDirectly { - self.loadData() - } - } - - - public func onNotificationUnreadCountChanged(count: Int) { - print("unread count:\(count)") + + public func onRecieveNotification(notification: XNotification) { + print("onRecieveNotification type:\(notification.type)") + if notification.type == .addFriendDirectly { + loadData() } - + } + + public func onNotificationUnreadCountChanged(count: Int) { + print("unread count:\(count)") + } + // MARK: FriendProviderDelegate - public func onFriendChanged(user: User) { - print("onFriendChanged:\(user.userId)") - self.loadData() - } - public func onBlackListChanged() { - print("onBlackListChanged") - } - - public func onUserInfoChanged(user: User) { - print("onUserInfoChanged:\(user.userId)") - self.loadData() - } - - public func onReceive(_ notification: NIMCustomSystemNotification) { - - } -} + public func onFriendChanged(user: User) { + print("onFriendChanged:\(user.userId)") + loadData() + } + public func onBlackListChanged() { + print("onBlackListChanged") + } + + public func onUserInfoChanged(user: User) { + print("onUserInfoChanged:\(user.userId)") + loadData() + } + + public func onReceive(_ notification: NIMCustomSystemNotification) {} +} extension ContactsViewController { - private func addNavbarAction(){ - - edgesForExtendedLayout = [] - let addItem = UIBarButtonItem(image: UIImage.ne_imageNamed(name: "add"), style: .plain, target: self, action: #selector(goToFindFriend)) - addItem.tintColor = UIColor(hexString: "333333") - let searchItem = UIBarButtonItem(image: UIImage.ne_imageNamed(name: "contact_search"), style: .plain, target: self, action: #selector(searchContact)) - searchItem.imageInsets = UIEdgeInsets.init(top: 0, left: 35, bottom: 0, right: 0) - searchItem.tintColor = UIColor(hexString: "333333") - if NEKitContactConfig.shared.ui.hiddenRightBtns { - return - }else { - if NEKitContactConfig.shared.ui.hiddenSearchBtn { - self.navigationItem.rightBarButtonItems = [addItem] - }else { - self.navigationItem.rightBarButtonItems = [addItem,searchItem] - } - } - - - - } - - @objc private func goToFindFriend(){ - let findFriendController = FindFriendViewController() - findFriendController.hidesBottomBarWhenPushed = true - self.navigationController?.pushViewController(findFriendController, animated: true) - } - - @objc private func searchContact(){ - Router.shared.use(SearchContactPageRouter, parameters: ["nav": self.navigationController as Any], closure: nil) + private func addNavbarAction() { + edgesForExtendedLayout = [] + let addItem = UIBarButtonItem( + image: UIImage.ne_imageNamed(name: "add"), + style: .plain, + target: self, + action: #selector(goToFindFriend) + ) + addItem.tintColor = UIColor(hexString: "333333") + let searchItem = UIBarButtonItem( + image: UIImage.ne_imageNamed(name: "contact_search"), + style: .plain, + target: self, + action: #selector(searchContact) + ) + searchItem.imageInsets = UIEdgeInsets(top: 0, left: 35, bottom: 0, right: 0) + searchItem.tintColor = UIColor(hexString: "333333") + if NEKitContactConfig.shared.ui.hiddenRightBtns { + return + } else { + if NEKitContactConfig.shared.ui.hiddenSearchBtn { + navigationItem.rightBarButtonItems = [addItem] + } else { + navigationItem.rightBarButtonItems = [addItem, searchItem] + } } - -} - + } + @objc private func goToFindFriend() { + let findFriendController = FindFriendViewController() + findFriendController.hidesBottomBarWhenPushed = true + navigationController?.pushViewController(findFriendController, animated: true) + } + + @objc private func searchContact() { + Router.shared.use( + SearchContactPageRouter, + parameters: ["nav": navigationController as Any], + closure: nil + ) + } +} diff --git a/NEContactUIKit/NEKitContactUI/Classes/Views/FindFriendViewController.swift b/NEContactUIKit/NEKitContactUI/Classes/Views/FindFriendViewController.swift index c5874b58..606dbbb1 100644 --- a/NEContactUIKit/NEKitContactUI/Classes/Views/FindFriendViewController.swift +++ b/NEContactUIKit/NEKitContactUI/Classes/Views/FindFriendViewController.swift @@ -1,154 +1,153 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit public class FindFriendViewController: ContactBaseViewController, UITextFieldDelegate { - - let viewModel = FindFriendViewModel() - let noResultView = UIView() - let hasRequest = false - - let searchInput = UITextField() - - - lazy var emptyView: UIImageView = { - let empty = UIImageView() - empty.translatesAutoresizingMaskIntoConstraints = false - empty.image = coreLoader.loadImage("user_empty") - return empty - }() - - lazy var userLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.text = "该用户不存在" - label.textColor = .ne_emptyTitleColor - label.font = UIFont.systemFont(ofSize: 14.0) - return label - }() - - public override func viewDidLoad() { - super.viewDidLoad() - self.title = "添加好友" - setupUI() - } - - public override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - navigationController?.isNavigationBarHidden = false + let viewModel = FindFriendViewModel() + let noResultView = UIView() + let hasRequest = false + + let searchInput = UITextField() + + lazy var emptyView: UIImageView = { + let empty = UIImageView() + empty.translatesAutoresizingMaskIntoConstraints = false + empty.image = coreLoader.loadImage("user_empty") + return empty + }() + + lazy var userLabel: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.text = "该用户不存在" + label.textColor = .ne_emptyTitleColor + label.font = UIFont.systemFont(ofSize: 14.0) + return label + }() + + override public func viewDidLoad() { + super.viewDidLoad() + title = "添加好友" + setupUI() + } + + override public func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + navigationController?.isNavigationBarHidden = false + } + + func setupUI() { + let searchBack = UIView() + view.addSubview(searchBack) + searchBack.backgroundColor = UIColor(hexString: "F2F4F5") + searchBack.translatesAutoresizingMaskIntoConstraints = false + searchBack.clipsToBounds = true + searchBack.layer.cornerRadius = 4.0 + NSLayoutConstraint.activate([ + searchBack.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20), + searchBack.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20), + searchBack.topAnchor.constraint(equalTo: view.topAnchor, constant: 20), + searchBack.heightAnchor.constraint(equalToConstant: 32), + ]) + + let searchImage = UIImageView() + searchBack.addSubview(searchImage) + searchImage.image = UIImage.ne_imageNamed(name: "search") + searchImage.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + searchImage.centerYAnchor.constraint(equalTo: searchBack.centerYAnchor), + searchImage.leftAnchor.constraint(equalTo: searchBack.leftAnchor, constant: 18), + searchImage.widthAnchor.constraint(equalToConstant: 13), + searchImage.heightAnchor.constraint(equalToConstant: 13), + ]) + + searchBack.addSubview(searchInput) + searchInput.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + searchInput.leftAnchor.constraint(equalTo: searchImage.rightAnchor, constant: 5), + searchInput.rightAnchor.constraint(equalTo: searchBack.rightAnchor, constant: -18), + searchInput.topAnchor.constraint(equalTo: searchBack.topAnchor), + searchInput.bottomAnchor.constraint(equalTo: searchBack.bottomAnchor), + ]) + searchInput.textColor = UIColor(hexString: "333333") + searchInput.placeholder = "输入查找用户id" + searchInput.font = UIFont.systemFont(ofSize: 14.0) + searchInput.returnKeyType = .search + searchInput.delegate = self + + NotificationCenter.default.addObserver( + self, + selector: #selector(textFieldChange), + name: UITextField.textDidChangeNotification, + object: nil + ) + + view.addSubview(emptyView) + NSLayoutConstraint.activate([ + emptyView.centerXAnchor.constraint(equalTo: view.centerXAnchor), + emptyView.topAnchor.constraint(equalTo: searchInput.bottomAnchor, constant: 74), + // emptyView.centerYAnchor.constraint(equalTo: view.centerYAnchor) + ]) + emptyView.isHidden = true + + view.addSubview(userLabel) + NSLayoutConstraint.activate([ + userLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor), + userLabel.topAnchor.constraint(equalTo: emptyView.bottomAnchor, constant: 9), + ]) + userLabel.isHidden = true + } + + public func textFieldShouldReturn(_ textField: UITextField) -> Bool { + guard let text = textField.text else { + return false } - - func setupUI(){ - let searchBack = UIView() - view.addSubview(searchBack) - searchBack.backgroundColor = UIColor(hexString: "F2F4F5") - searchBack.translatesAutoresizingMaskIntoConstraints = false - searchBack.clipsToBounds = true - searchBack.layer.cornerRadius = 4.0 - NSLayoutConstraint.activate([ - searchBack.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20), - searchBack.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20), - searchBack.topAnchor.constraint(equalTo: view.topAnchor, constant: 20), - searchBack.heightAnchor.constraint(equalToConstant: 32) - ]) - - let searchImage = UIImageView() - searchBack.addSubview(searchImage) - searchImage.image = UIImage.ne_imageNamed(name: "search") - searchImage.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - searchImage.centerYAnchor.constraint(equalTo: searchBack.centerYAnchor), - searchImage.leftAnchor.constraint(equalTo: searchBack.leftAnchor, constant: 18), - searchImage.widthAnchor.constraint(equalToConstant: 13), - searchImage.heightAnchor.constraint(equalToConstant: 13) - ]) - - searchBack.addSubview(searchInput) - searchInput.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - searchInput.leftAnchor.constraint(equalTo: searchImage.rightAnchor, constant: 5), - searchInput.rightAnchor.constraint(equalTo: searchBack.rightAnchor, constant: -18), - searchInput.topAnchor.constraint(equalTo: searchBack.topAnchor), - searchInput.bottomAnchor.constraint(equalTo: searchBack.bottomAnchor) - ]) - searchInput.textColor = UIColor(hexString: "333333") - searchInput.placeholder = "输入查找用户id" - searchInput.font = UIFont.systemFont(ofSize: 14.0) - searchInput.returnKeyType = .search - searchInput.delegate = self - - - NotificationCenter.default.addObserver(self, selector: #selector(textFieldChange), name: UITextField.textDidChangeNotification, object: nil) - - view.addSubview(emptyView) - NSLayoutConstraint.activate([ - emptyView.centerXAnchor.constraint(equalTo: view.centerXAnchor), - emptyView.topAnchor.constraint(equalTo: searchInput.bottomAnchor, constant: 74) - //emptyView.centerYAnchor.constraint(equalTo: view.centerYAnchor) - ]) - emptyView.isHidden = true - - view.addSubview(userLabel) - NSLayoutConstraint.activate([ - userLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor), - userLabel.topAnchor.constraint(equalTo: emptyView.bottomAnchor, constant: 9) - ]) - userLabel.isHidden = true + if text.count <= 0 { + return false } - - public func textFieldShouldReturn(_ textField: UITextField) -> Bool { - - guard let text = textField.text else { - return false - } - if text.count <= 0 { - return false - } - if self.hasRequest == false { - startSearch(text) - } - return true + if hasRequest == false { + startSearch(text) } - - @objc func textFieldChange(){ - if let text = searchInput.text, text.count <= 0 { - emptyView.isHidden = true - userLabel.isHidden = true - } + return true + } + + @objc func textFieldChange() { + if let text = searchInput.text, text.count <= 0 { + emptyView.isHidden = true + userLabel.isHidden = true } - - func startSearch(_ text: String){ - weak var weakSelf = self - viewModel.searchFriend(text) { users, error in - if error == nil { - if let user = users?.first { - // go to detail - let userController = ContactUserViewController(user: user) - self.navigationController?.pushViewController(userController, animated: true) - weakSelf?.emptyView.isHidden = true - weakSelf?.userLabel.isHidden = true - }else { - weakSelf?.emptyView.isHidden = false - weakSelf?.userLabel.isHidden = false - } - }else { - self.showToast(error?.localizedDescription ?? "") - } + } + + func startSearch(_ text: String) { + weak var weakSelf = self + viewModel.searchFriend(text) { users, error in + if error == nil { + if let user = users?.first { + // go to detail + let userController = ContactUserViewController(user: user) + self.navigationController?.pushViewController(userController, animated: true) + weakSelf?.emptyView.isHidden = true + weakSelf?.userLabel.isHidden = true + } else { + weakSelf?.emptyView.isHidden = false + weakSelf?.userLabel.isHidden = false } + } else { + self.showToast(error?.localizedDescription ?? "") + } } - + } - /* - // MARK: - Navigation - - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. - } - */ + /* + // MARK: - Navigation + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ } diff --git a/NEContactUIKit/NEKitContactUI/NEKitContactUI.h b/NEContactUIKit/NEKitContactUI/NEKitContactUI.h index bad7217d..7a1b45c2 100644 --- a/NEContactUIKit/NEKitContactUI/NEKitContactUI.h +++ b/NEContactUIKit/NEKitContactUI/NEKitContactUI.h @@ -1,9 +1,7 @@ -// -// contactkit_ui.h -// contactkit-ui -// -// Created by yu chen on 2021/12/28. -// + +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. #import @@ -13,6 +11,5 @@ FOUNDATION_EXPORT double contactkit_uiVersionNumber; //! Project version string for contactkit_ui. FOUNDATION_EXPORT const unsigned char contactkit_uiVersionString[]; -// In this header, you should import all the public headers of your framework using statements like #import - - +// In this header, you should import all the public headers of your framework +// using statements like #import diff --git a/NEConversationUIKit/NEKitConversationUI.podspec b/NEConversationUIKit/NEKitConversationUI.podspec index d2f6de28..e3a18ef4 100644 --- a/NEConversationUIKit/NEKitConversationUI.podspec +++ b/NEConversationUIKit/NEKitConversationUI.podspec @@ -8,7 +8,7 @@ Pod::Spec.new do |s| s.name = 'NEKitConversationUI' - s.version = '9.2.6-rc01' + s.version = '9.2.7' s.summary = 'Netease XKit' # This description is used to generate tags and improve search results. @@ -34,6 +34,10 @@ TODO: Add long description of the pod here. s.resource = 'NEKitConversationUI/Assets/**/*' # s.public_header_files = 'Pod/Classes/**/*.h' + s.pod_target_xcconfig = { + 'BUILD_LIBRARY_FOR_DISTRIBUTION' => 'YES' + } + s.user_target_xcconfig = { 'BUILD_LIBRARY_FOR_DISTRIBUTION' => 'YES' } s.dependency 'NECommonUIKit' s.dependency 'NEConversationKit' diff --git a/NEConversationUIKit/NEKitConversationUI/Assets/en.lproj/Localizable.strings b/NEConversationUIKit/NEKitConversationUI/Assets/en.lproj/Localizable.strings index 5fd53ca3..eec66e03 100644 --- a/NEConversationUIKit/NEKitConversationUI/Assets/en.lproj/Localizable.strings +++ b/NEConversationUIKit/NEKitConversationUI/Assets/en.lproj/Localizable.strings @@ -1,10 +1,8 @@ -/* - YXLogin.strings - Pods - Created by yu chen on 2021/12/24. - -*/ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + //MAKR:common "add_friend"="添加好友"; diff --git a/NEConversationUIKit/NEKitConversationUI/Assets/zh-Hans.lproj/Localizable.strings b/NEConversationUIKit/NEKitConversationUI/Assets/zh-Hans.lproj/Localizable.strings index 2ea4a7e0..e2514171 100644 --- a/NEConversationUIKit/NEKitConversationUI/Assets/zh-Hans.lproj/Localizable.strings +++ b/NEConversationUIKit/NEKitConversationUI/Assets/zh-Hans.lproj/Localizable.strings @@ -1,10 +1,7 @@ -/* - YXLogin.strings - Pods - Created by yu chen on 2021/12/24. - -*/ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. //MAKR:common "add_friend"="添加好友"; diff --git a/NEConversationUIKit/NEKitConversationUI/Classes/Common/ColorExtension.swift b/NEConversationUIKit/NEKitConversationUI/Classes/Common/ColorExtension.swift index 40e51f38..5708dc7e 100644 --- a/NEConversationUIKit/NEKitConversationUI/Classes/Common/ColorExtension.swift +++ b/NEConversationUIKit/NEKitConversationUI/Classes/Common/ColorExtension.swift @@ -1,33 +1,32 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation public extension UIColor { - - // MARK: text color - static let ne_darkText = UIColor(hexString: "#333333") - static let ne_greyText = UIColor(hexString: "#666666") - static let ne_lightText = UIColor(hexString: "#999999") - static let ne_blueText = UIColor(hexString: "#337EFF") - static let ne_redText = UIColor(hexString: "#E6605C") - static let ne_disableRedText = UIColor(hexString: "#E6605C", 0.5) - static let ne_backcolor = UIColor(hexString: "F2F4F5") - static let ne_emptyTitleColor = UIColor(hexString: "B3B7BC") - - // MARK: view background color - static let ne_lightBackgroundColor = UIColor(hexString: "#F1F1F6") - static let ne_defautAvatarColor = UIColor(hexString: "#537FF4") - static let ne_greenColor = UIColor(hexString: "#42C294") - - - // MARK: border color - static let ne_borderColor = UIColor(hexString: "#DBDDE4") - - // MARK: line color - static let ne_greyLine = UIColor(hexString: "#F5F8FC") - - static let ne_redColor = UIColor(hexString: "#F24957") + // MARK: text color + + static let ne_darkText = UIColor(hexString: "#333333") + static let ne_greyText = UIColor(hexString: "#666666") + static let ne_lightText = UIColor(hexString: "#999999") + static let ne_blueText = UIColor(hexString: "#337EFF") + static let ne_redText = UIColor(hexString: "#E6605C") + static let ne_disableRedText = UIColor(hexString: "#E6605C", 0.5) + static let ne_backcolor = UIColor(hexString: "F2F4F5") + static let ne_emptyTitleColor = UIColor(hexString: "B3B7BC") + + // MARK: view background color + static let ne_lightBackgroundColor = UIColor(hexString: "#F1F1F6") + static let ne_defautAvatarColor = UIColor(hexString: "#537FF4") + static let ne_greenColor = UIColor(hexString: "#42C294") + + // MARK: border color + static let ne_borderColor = UIColor(hexString: "#DBDDE4") + + // MARK: line color + static let ne_greyLine = UIColor(hexString: "#F5F8FC") + + static let ne_redColor = UIColor(hexString: "#F24957") } diff --git a/NEConversationUIKit/NEKitConversationUI/Classes/Common/ConversationConstant.swift b/NEConversationUIKit/NEKitConversationUI/Classes/Common/ConversationConstant.swift index c1650e3c..b5e30c5f 100644 --- a/NEConversationUIKit/NEKitConversationUI/Classes/Common/ConversationConstant.swift +++ b/NEConversationUIKit/NEKitConversationUI/Classes/Common/ConversationConstant.swift @@ -1,12 +1,12 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NEKitCore let coreLoader = CoreLoader() -func localizable(_ key: String) -> String{ - return coreLoader.localizable(key) +func localizable(_ key: String) -> String { + coreLoader.localizable(key) } diff --git a/NEConversationUIKit/NEKitConversationUI/Classes/Common/ConversationUI.swift b/NEConversationUIKit/NEKitConversationUI/Classes/Common/ConversationUI.swift index e0b2bce2..0d9fb545 100644 --- a/NEConversationUIKit/NEKitConversationUI/Classes/Common/ConversationUI.swift +++ b/NEConversationUIKit/NEKitConversationUI/Classes/Common/ConversationUI.swift @@ -1,9 +1,9 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. - -import Foundation +import Foundation @_exported import NEKitCommon @_exported import NEKitCommonUI @@ -11,5 +11,5 @@ import Foundation @_exported import NIMSDK @_exported import NEKitCore @_exported import SDWebImage -//@_exported +// @_exported @_exported import NEKitCoreIM diff --git a/NEConversationUIKit/NEKitConversationUI/Classes/Common/ImageExtension.swift b/NEConversationUIKit/NEKitConversationUI/Classes/Common/ImageExtension.swift index 93abe712..4c73860d 100644 --- a/NEConversationUIKit/NEKitConversationUI/Classes/Common/ImageExtension.swift +++ b/NEConversationUIKit/NEKitConversationUI/Classes/Common/ImageExtension.swift @@ -1,16 +1,15 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation -extension UIImage { - public class func ne_imageNamed(name: String?) -> UIImage? { - guard let imageName = name else { - return nil - } - return coreLoader.loadImage(imageName) +public extension UIImage { + class func ne_imageNamed(name: String?) -> UIImage? { + guard let imageName = name else { + return nil } - + return coreLoader.loadImage(imageName) + } } diff --git a/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/Controller/ConversationController.swift b/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/Controller/ConversationController.swift index c0bb7f97..2b6337af 100644 --- a/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/Controller/ConversationController.swift +++ b/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/Controller/ConversationController.swift @@ -1,156 +1,180 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCommonUI import NEKitCore - @objcMembers open class ConversationController: UIViewController { - - let viewmodel = ConversationViewModel() - private var listCtrl = ConversationListViewController() + let viewmodel = ConversationViewModel() + private var listCtrl = ConversationListViewController() - public override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - self.navigationController?.isNavigationBarHidden = true - } - - public override func viewDidLoad() { - super.viewDidLoad() - setupSubviews() - } - - func setupSubviews(){ - + override public func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + navigationController?.isNavigationBarHidden = true + } + + override public func viewDidLoad() { + super.viewDidLoad() + setupSubviews() + } + + func setupSubviews() { // NEKitConversationConfig.shared.ui.avatarType = .rectangle - - listCtrl.view.translatesAutoresizingMaskIntoConstraints = false - self.addChild(listCtrl) - self.view.addSubview(navView) - self.view.addSubview(listCtrl.view) - - NSLayoutConstraint.activate([ - navView.topAnchor.constraint(equalTo: self.view.topAnchor), - navView.leftAnchor.constraint(equalTo: self.view.leftAnchor), - navView.rightAnchor.constraint(equalTo: self.view.rightAnchor), - navView.heightAnchor.constraint(equalToConstant:NEConstant.navigationHeight + NEConstant.statusBarHeight + 16) - ]) - - NSLayoutConstraint.activate([ - listCtrl.view.topAnchor.constraint(equalTo: navView.bottomAnchor), - listCtrl.view.leftAnchor.constraint(equalTo: self.view.leftAnchor), - listCtrl.view.rightAnchor.constraint(equalTo: self.view.rightAnchor), - listCtrl.view.bottomAnchor.constraint(equalTo: self.view.bottomAnchor) - ]) - } - - //MARK: lazyMethod - private lazy var navView:ConversationNavView = { - let nav = ConversationNavView.init(frame: CGRect.zero) - nav.translatesAutoresizingMaskIntoConstraints = false - nav.backgroundColor = .white - nav.delegate = self - - nav.isHidden = NEKitConversationConfig.shared.ui.hiddenNav - return nav - }() - - public lazy var popListController: PopListViewController = { - let popController = PopListViewController() - return popController - }() + listCtrl.view.translatesAutoresizingMaskIntoConstraints = false + addChild(listCtrl) + view.addSubview(navView) + view.addSubview(listCtrl.view) + + NSLayoutConstraint.activate([ + navView.topAnchor.constraint(equalTo: view.topAnchor), + navView.leftAnchor.constraint(equalTo: view.leftAnchor), + navView.rightAnchor.constraint(equalTo: view.rightAnchor), + navView.heightAnchor + .constraint(equalToConstant: NEConstant.navigationHeight + NEConstant + .statusBarHeight + 16), + ]) + + NSLayoutConstraint.activate([ + listCtrl.view.topAnchor.constraint(equalTo: navView.bottomAnchor), + listCtrl.view.leftAnchor.constraint(equalTo: view.leftAnchor), + listCtrl.view.rightAnchor.constraint(equalTo: view.rightAnchor), + listCtrl.view.bottomAnchor.constraint(equalTo: view.bottomAnchor), + ]) + } + + // MARK: lazyMethod + + private lazy var navView: ConversationNavView = { + let nav = ConversationNavView(frame: CGRect.zero) + nav.translatesAutoresizingMaskIntoConstraints = false + nav.backgroundColor = .white + nav.delegate = self + + nav.isHidden = NEKitConversationConfig.shared.ui.hiddenNav + return nav + }() + + public lazy var popListController: PopListViewController = { + let popController = PopListViewController() + return popController + }() } extension ConversationController: ConversationNavViewDelegate { - - func searchAction(){ - Router.shared.use(SearchContactPageRouter, parameters: ["nav": self.navigationController as Any], closure: nil) + func searchAction() { + Router.shared.use( + SearchContactPageRouter, + parameters: ["nav": navigationController as Any], + closure: nil + ) + } + + func didClickAddBtn() { + print("add click") + + if children.contains(popListController) == false { + popListController.itemDatas = getPopListItems() + addChild(popListController) + popListController.view.frame = listCtrl.view.frame + } + if popListController.view.superview != nil { + popListController.removeSelf() + } else { + view.addSubview(popListController.view) + } + } + + func getPopListItems() -> [PopListItem] { + weak var weakSelf = self + var items = [PopListItem]() + let addFriend = PopListItem() + addFriend.showName = localizable("add_friend") + addFriend.image = UIImage.ne_imageNamed(name: "add_friend") + addFriend.completion = { + Router.shared.use( + ContactAddFriendRouter, + parameters: ["nav": self.navigationController as Any] + ) { obj, routerState, str in + } + } + items.append(addFriend) + + let createGroup = PopListItem() + createGroup.showName = localizable("create_discussion_group") + createGroup.image = UIImage.ne_imageNamed(name: "create_discussion") + createGroup.completion = { + weakSelf?.createDiscussGroup() + } + items.append(createGroup) + + let createDicuss = PopListItem() + createDicuss.showName = localizable("create_senior_group") + createDicuss.image = UIImage.ne_imageNamed(name: "create_group") + createDicuss.completion = { + weakSelf?.createSeniorGroup() } - - func didClickAddBtn() { - print("add click") - - if self.children.contains(popListController) == false { - popListController.itemDatas = getPopListItems() - self.addChild(popListController) - popListController.view.frame = listCtrl.view.frame - } - if popListController.view.superview != nil { - popListController.removeSelf() - }else { - view.addSubview(popListController.view) - } + items.append(createDicuss) + + return items + } + + func createDiscussGroup() { + Router.shared.register(ContactSelectedUsersRouter) { param in + print("user setting accids : ", param) + Router.shared.use(TeamCreateDisuss, parameters: param, closure: nil) } - - func getPopListItems() -> [PopListItem]{ - - weak var weakSelf = self - var items = [PopListItem]() - let addFriend = PopListItem() - addFriend.showName = localizable("add_friend") - addFriend.image = UIImage.ne_imageNamed(name: "add_friend") - addFriend.completion = { - Router.shared.use(ContactAddFriendRouter, parameters: ["nav": self.navigationController as Any]) { obj, routerState, str in - } - } - items.append(addFriend) - - let createGroup = PopListItem() - createGroup.showName = localizable("create_discussion_group") - createGroup.image = UIImage.ne_imageNamed(name: "create_discussion") - createGroup.completion = { - weakSelf?.createDiscussGroup() - } - items.append(createGroup) - - let createDicuss = PopListItem() - createDicuss.showName = localizable("create_senior_group") - createDicuss.image = UIImage.ne_imageNamed(name: "create_group") - createDicuss.completion = { - weakSelf?.createSeniorGroup() - } - items.append(createDicuss) - - return items + Router.shared.use( + ContactUserSelectRouter, + parameters: ["nav": navigationController as Any, "limit": 200], + closure: nil + ) + weak var weakSelf = self + Router.shared.register(TeamCreateDiscussResult) { param in + print("create discuss ", param) + if let code = param["code"] as? Int, let teamid = param["teamId"] as? String, + code == 0 { + let session = weakSelf?.viewmodel.repo.createTeamSession(teamid) + Router.shared.use( + PushTeamChatVCRouter, + parameters: ["nav": weakSelf?.navigationController as Any, + "session": session as Any], + closure: nil + ) + } else if let msg = param["msg"] as? String { + weakSelf?.showToast(msg) + } } - - func createDiscussGroup(){ - Router.shared.register(ContactSelectedUsersRouter) { param in - print("user setting accids : ", param) - Router.shared.use(TeamCreateDisuss, parameters: param, closure: nil) - } - Router.shared.use(ContactUserSelectRouter, parameters: ["nav": navigationController as Any, "limit": 200], closure: nil) - weak var weakSelf = self - Router.shared.register(TeamCreateDiscussResult) { param in - print("create discuss ", param) - if let code = param["code"] as? Int, let teamid = param["teamId"] as? String, code == 0 { - let session = weakSelf?.viewmodel.repo.createTeamSession(teamid) - Router.shared.use(PushTeamChatVCRouter, parameters: ["nav": weakSelf?.navigationController as Any, "session" : session as Any], closure: nil) - }else if let msg = param["msg"] as? String { - weakSelf?.showToast(msg) - } - } + } + + func createSeniorGroup() { + Router.shared.register(ContactSelectedUsersRouter) { param in + Router.shared.use(TeamCreateSenior, parameters: param, closure: nil) } - - func createSeniorGroup(){ - Router.shared.register(ContactSelectedUsersRouter) { param in - Router.shared.use(TeamCreateSenior, parameters: param, closure: nil) - } - Router.shared.use(ContactUserSelectRouter, parameters: ["nav": navigationController as Any, "limit": 200], closure: nil) - weak var weakSelf = self - Router.shared.register(TeamCreateSeniorResult) { param in - print("create senior : ", param) - if let code = param["code"] as? Int, let teamid = param["teamId"] as? String, code == 0 { - let session = weakSelf?.viewmodel.repo.createTeamSession(teamid) - Router.shared.use(PushTeamChatVCRouter, parameters: ["nav": weakSelf?.navigationController as Any, "session" : session as Any], closure: nil) - }else if let msg = param["msg"] as? String { - weakSelf?.showToast(msg) - } - } + Router.shared.use( + ContactUserSelectRouter, + parameters: ["nav": navigationController as Any, "limit": 200], + closure: nil + ) + weak var weakSelf = self + Router.shared.register(TeamCreateSeniorResult) { param in + print("create senior : ", param) + if let code = param["code"] as? Int, let teamid = param["teamId"] as? String, + code == 0 { + let session = weakSelf?.viewmodel.repo.createTeamSession(teamid) + Router.shared.use( + PushTeamChatVCRouter, + parameters: ["nav": weakSelf?.navigationController as Any, + "session": session as Any], + closure: nil + ) + } else if let msg = param["msg"] as? String { + weakSelf?.showToast(msg) + } } + } } diff --git a/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/Controller/ConversationListViewController.swift b/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/Controller/ConversationListViewController.swift index be43fe08..63fe16ec 100644 --- a/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/Controller/ConversationListViewController.swift +++ b/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/Controller/ConversationListViewController.swift @@ -1,331 +1,355 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NIMSDK @objcMembers open class ConversationListViewController: UIViewController { + private var viewModel = ConversationViewModel() + private let className = "ConversationListViewController" + private var tableViewTopConstraint: NSLayoutConstraint? - private var viewModel = ConversationViewModel() - private let className = "ConversationListViewController" - private var tableViewTopConstraint:NSLayoutConstraint? - - - open override func viewDidLoad() { - super.viewDidLoad() - setupSubviews() - requestData() - initialConfig() - } + override open func viewDidLoad() { + super.viewDidLoad() + setupSubviews() + requestData() + initialConfig() + } - open override func viewWillAppear(_ animated: Bool) { - weak var weakSelf = self - viewModel.loadStickTopSessionInfos { error, sessionInfos in - if let infos = sessionInfos { - weakSelf?.viewModel.stickTopInfos = infos - weakSelf?.reloadTableView() - } - } - NEChatDetectNetworkTool.shareInstance.netWorkReachability() { status in - if status == .notReachable{ - weakSelf?.brokenNetworkView.isHidden = false - weakSelf?.tableViewTopConstraint?.constant = 36 - }else { - weakSelf?.brokenNetworkView.isHidden = true - weakSelf?.tableViewTopConstraint?.constant = 0 - } - } + override open func viewWillAppear(_ animated: Bool) { + weak var weakSelf = self + viewModel.loadStickTopSessionInfos { error, sessionInfos in + if let infos = sessionInfos { + weakSelf?.viewModel.stickTopInfos = infos + weakSelf?.reloadTableView() + } } - - open func initialConfig(){ - viewModel.delegate = self + NEChatDetectNetworkTool.shareInstance.netWorkReachability { status in + if status == .notReachable { + weakSelf?.brokenNetworkView.isHidden = false + weakSelf?.tableViewTopConstraint?.constant = 36 + } else { + weakSelf?.brokenNetworkView.isHidden = true + weakSelf?.tableViewTopConstraint?.constant = 0 + } } - - - open func setupSubviews(){ - self.view.addSubview(tableView) - self.view.addSubview(brokenNetworkView) - - NSLayoutConstraint.activate([ - tableView.rightAnchor.constraint(equalTo: self.view.rightAnchor), - tableView.leftAnchor.constraint(equalTo: self.view.leftAnchor), - tableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor) - ]) - tableViewTopConstraint = tableView.topAnchor.constraint(equalTo: self.view.topAnchor) - tableViewTopConstraint?.isActive = true - } - - func requestData(){ - let params = NIMFetchServerSessionOption() - params.minTimestamp = 0 - params.maxTimestamp = Date().timeIntervalSince1970*1000 - params.limit = 50 - weak var weakSelf = self - viewModel.fetchServerSessions(option: params) { error, recentSessions in - if error == nil { - DispatchQueue.main.async{ - weakSelf?.tableView.reloadData() - } - - }else { - NELog.errorLog(self.className, desc: "❌fetchServerSessions failed,error = \(error!)") - } + } + + open func initialConfig() { + viewModel.delegate = self + } + + open func setupSubviews() { + view.addSubview(tableView) + view.addSubview(brokenNetworkView) + + NSLayoutConstraint.activate([ + tableView.rightAnchor.constraint(equalTo: view.rightAnchor), + tableView.leftAnchor.constraint(equalTo: view.leftAnchor), + tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), + ]) + tableViewTopConstraint = tableView.topAnchor.constraint(equalTo: view.topAnchor) + tableViewTopConstraint?.isActive = true + } + + func requestData() { + let params = NIMFetchServerSessionOption() + params.minTimestamp = 0 + params.maxTimestamp = Date().timeIntervalSince1970 * 1000 + params.limit = 50 + weak var weakSelf = self + viewModel.fetchServerSessions(option: params) { error, recentSessions in + if error == nil { + DispatchQueue.main.async { + weakSelf?.tableView.reloadData() } + + } else { + NELog.errorLog( + self.className, + desc: "❌fetchServerSessions failed,error = \(error!)" + ) + } } - - //MARK: lazy method - private lazy var tableView:UITableView = { - let tableView = UITableView.init(frame: .zero, style: .plain) - tableView.translatesAutoresizingMaskIntoConstraints = false - tableView.separatorStyle = .none - tableView.delegate = self - tableView.dataSource = self - tableView.register(ConversationListCell.self, forCellReuseIdentifier: "\(NSStringFromClass(ConversationListCell.self))") - tableView.rowHeight = 62 - tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.1)) - tableView.backgroundColor = .white - return tableView - }() - - private lazy var brokenNetworkView:NEBrokenNetworkView = { - let view = NEBrokenNetworkView.init(frame: CGRect.init(x: 0, y: 0, width: NEConstant.screenWidth, height: 36)) - view.isHidden = true - return view - }() - + } + + // MARK: lazy method + + private lazy var tableView: UITableView = { + let tableView = UITableView(frame: .zero, style: .plain) + tableView.translatesAutoresizingMaskIntoConstraints = false + tableView.separatorStyle = .none + tableView.delegate = self + tableView.dataSource = self + tableView.register( + ConversationListCell.self, + forCellReuseIdentifier: "\(NSStringFromClass(ConversationListCell.self))" + ) + tableView.rowHeight = 62 + tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.1)) + tableView.backgroundColor = .white + return tableView + }() + + private lazy var brokenNetworkView: NEBrokenNetworkView = { + let view = + NEBrokenNetworkView(frame: CGRect(x: 0, y: 0, width: NEConstant.screenWidth, height: 36)) + view.isHidden = true + return view + }() } -//MARK: ====================== private method=========================== -extension ConversationListViewController{ - - - private func onTopRecentAtIndexPath(rencent:NIMRecentSession,indexPath:IndexPath,isTop:Bool,_ completion:@escaping (NSError?,NIMStickTopSessionInfo?)->()){ - - guard let session = rencent.session else { - NELog.errorLog(className , desc: "❌session is nil") - return +// MARK: ====================== private method=========================== + +extension ConversationListViewController { + private func onTopRecentAtIndexPath(rencent: NIMRecentSession, indexPath: IndexPath, + isTop: Bool, + _ completion: @escaping (NSError?, NIMStickTopSessionInfo?) + -> Void) { + guard let session = rencent.session else { + NELog.errorLog(className, desc: "❌session is nil") + return + } + weak var weakSelf = self + if isTop { + guard let params = viewModel.stickTopInfos[session] else { + return + } + + viewModel.removeStickTopSession(params: params) { error, topSessionInfo in + if let err = error { + NELog.errorLog( + weakSelf?.className ?? "ConversationListViewController", + desc: "❌removeStickTopSession failed,error = \(err)" + ) + completion(error as NSError?, nil) + + return + } else { + weakSelf?.viewModel.stickTopInfos[session] = nil + weakSelf?.viewModel.sortRecentSession() + weakSelf?.tableView.reloadData() + completion(nil, topSessionInfo) } - weak var weakSelf = self - if isTop { - guard let params = viewModel.stickTopInfos[session] else { - return - } - - viewModel.removeStickTopSession(params: params) { error, topSessionInfo in - if let err = error { - NELog.errorLog(weakSelf?.className ?? "ConversationListViewController", desc: "❌removeStickTopSession failed,error = \(err)") - completion(error as NSError?,nil) - - return - }else { - weakSelf?.viewModel.stickTopInfos[session] = nil - weakSelf?.viewModel.sortRecentSession() - weakSelf?.tableView.reloadData() - completion(nil,topSessionInfo) - } - - } - - }else { - - viewModel.addStickTopSession(session: session, { error, newInfo in - if let err = error { - NELog.errorLog(weakSelf?.className ?? "ConversationListViewController", desc: "❌addStickTopSession failed,error = \(err)") - completion(error as NSError?,nil) - return - }else { - weakSelf?.viewModel.stickTopInfos[session] = newInfo - weakSelf?.viewModel.sortRecentSession() - weakSelf?.tableView.reloadData() - completion(nil,newInfo) - - } - - }) + } + + } else { + viewModel.addStickTopSession(session: session) { error, newInfo in + if let err = error { + NELog.errorLog( + weakSelf?.className ?? "ConversationListViewController", + desc: "❌addStickTopSession failed,error = \(err)" + ) + completion(error as NSError?, nil) + return + } else { + weakSelf?.viewModel.stickTopInfos[session] = newInfo + weakSelf?.viewModel.sortRecentSession() + weakSelf?.tableView.reloadData() + completion(nil, newInfo) } + } } + } } -extension ConversationListViewController:UITableViewDelegate,UITableViewDataSource { - - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return viewModel.conversationListArray?.count ?? 0 - +extension ConversationListViewController: UITableViewDelegate, UITableViewDataSource { + public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + viewModel.conversationListArray?.count ?? 0 + } + + public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(NSStringFromClass(ConversationListCell.self))", + for: indexPath + ) as! ConversationListCell + let conversationModel = viewModel.conversationListArray?[indexPath.row] + cell.topStickInfos = viewModel.stickTopInfos + cell.configData(sessionModel: conversationModel) + return cell + } + + public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + let conversationModel = viewModel.conversationListArray?[indexPath.row] + + guard let sid = conversationModel?.recentSession?.session?.sessionId else { + return } - - public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(withIdentifier: "\(NSStringFromClass(ConversationListCell.self))", for: indexPath) as! ConversationListCell - let conversationModel = self.viewModel.conversationListArray?[indexPath.row] - cell.topStickInfos = viewModel.stickTopInfos - cell.configData(sessionModel: conversationModel) - return cell + guard let sessionType = conversationModel?.recentSession?.session?.sessionType else { + return } - - public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - let conversationModel = viewModel.conversationListArray?[indexPath.row] + onselectedTableRow(sessionType: sessionType, sessionId: sid, indexPath: indexPath) + } - guard let sid = conversationModel?.recentSession?.session?.sessionId else { - return - } - guard let sessionType = conversationModel?.recentSession?.session?.sessionType else { - return - } - onselectedTableRow(sessionType: sessionType, sessionId: sid, indexPath: indexPath) + public func tableView(_ tableView: UITableView, + editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? { + weak var weakSelf = self + var rowActions = [UITableViewRowAction]() + + let conversationModel = weakSelf?.viewModel.conversationListArray?[indexPath.row] + guard let recentSession = conversationModel?.recentSession, + let session = recentSession.session else { + return rowActions } - - public func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? { - - weak var weakSelf = self - var rowActions = [UITableViewRowAction]() - - let conversationModel = weakSelf?.viewModel.conversationListArray?[indexPath.row] - guard let recentSession = conversationModel?.recentSession,let session = recentSession.session else { - return rowActions - } - - let deleteAction = UITableViewRowAction.init(style: .destructive, title: "删除") { action, indexPath in - - weakSelf?.viewModel.deleteRecentSession(recentSession: recentSession) - weakSelf?.didDeleteConversationCell(model: conversationModel ?? ConversationListModel(), indexPath: indexPath) - - //删除cell - if let stickTopInfo = weakSelf?.viewModel.stickTopInfoForSession(session: session) { - weakSelf?.viewModel.removeStickTopSession(params: stickTopInfo) { error, topSessionInfo in - if let err = error { - NELog.errorLog(weakSelf?.className ?? "ConversationListViewController", desc: "❌removeStickTopSession failed,error = \(err)") - return - } - weakSelf?.viewModel.stickTopInfos[session] = nil - } + + let deleteAction = UITableViewRowAction(style: .destructive, + title: "删除") { action, indexPath in + + weakSelf?.viewModel.deleteRecentSession(recentSession: recentSession) + weakSelf?.didDeleteConversationCell( + model: conversationModel ?? ConversationListModel(), + indexPath: indexPath + ) + + // 删除cell + if let stickTopInfo = weakSelf?.viewModel.stickTopInfoForSession(session: session) { + weakSelf?.viewModel + .removeStickTopSession(params: stickTopInfo) { error, topSessionInfo in + if let err = error { + NELog.errorLog( + weakSelf?.className ?? "ConversationListViewController", + desc: "❌removeStickTopSession failed,error = \(err)" + ) + return } + weakSelf?.viewModel.stickTopInfos[session] = nil + } + } + } - } - - //置顶和取消置顶 - let isTop = viewModel.stickTopInfos[session] != nil - let topAction = UITableViewRowAction.init(style: .destructive, title: isTop ? "取消置顶":"置顶") { action, indexPath in - if let recentSesstion = conversationModel?.recentSession { - weakSelf?.onTopRecentAtIndexPath(rencent: recentSesstion, indexPath: indexPath, isTop: isTop, { error, sessionInfo in - if error == nil { - if isTop { - weakSelf?.didRemoveStickTopSession(model: conversationModel ?? ConversationListModel(), indexPath: indexPath) - }else { - weakSelf?.didAddStickTopSession(model: conversationModel ?? ConversationListModel(), indexPath: indexPath) - } - } - }) + // 置顶和取消置顶 + let isTop = viewModel.stickTopInfos[session] != nil + let topAction = UITableViewRowAction(style: .destructive, + title: isTop ? "取消置顶" : "置顶") { action, indexPath in + if let recentSesstion = conversationModel?.recentSession { + weakSelf?.onTopRecentAtIndexPath( + rencent: recentSesstion, + indexPath: indexPath, + isTop: isTop + ) { error, sessionInfo in + if error == nil { + if isTop { + weakSelf?.didRemoveStickTopSession( + model: conversationModel ?? ConversationListModel(), + indexPath: indexPath + ) + } else { + weakSelf?.didAddStickTopSession( + model: conversationModel ?? ConversationListModel(), + indexPath: indexPath + ) } + } } - deleteAction.backgroundColor = NEConstant.hexRGB(0xA8ABB6) - topAction.backgroundColor = NEConstant.hexRGB(0x337EFF) - rowActions.append(deleteAction) - rowActions.append(topAction) - - return rowActions + } } - - - /* - @available(iOS 11.0, *) - public func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { - - var rowActions = [UIContextualAction]() - - let deleteAction = UIContextualAction(style: .normal, title: "删除") { (action, sourceView, completionHandler) in - - // self.dataSource.remove(at: indexPath.row) - // tableView.deleteRows(at: [indexPath], with: .automatic) - // 需要返回true,否则没有反应 - completionHandler(true) - } - deleteAction.backgroundColor = NEConstant.hexRGB(0xA8ABB6) - rowActions.append(deleteAction) - - - let topAction = UIContextualAction(style: .normal, title: "置顶") { (action, sourceView, completionHandler) in - - // self.dataSource.remove(at: indexPath.row) - // tableView.deleteRows(at: [indexPath], with: .automatic) - // 需要返回true,否则没有反应 - completionHandler(true) - } - topAction.backgroundColor = NEConstant.hexRGB(0x337EFF) - rowActions.append(topAction) - - let actionConfig = UISwipeActionsConfiguration.init(actions: rowActions) - actionConfig.performsFirstActionWithFullSwipe = false - - return actionConfig - } - */ + deleteAction.backgroundColor = NEConstant.hexRGB(0xA8ABB6) + topAction.backgroundColor = NEConstant.hexRGB(0x337EFF) + rowActions.append(deleteAction) + rowActions.append(topAction) + + return rowActions + } + + /* + @available(iOS 11.0, *) + public func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { + + var rowActions = [UIContextualAction]() + + let deleteAction = UIContextualAction(style: .normal, title: "删除") { (action, sourceView, completionHandler) in + + // self.dataSource.remove(at: indexPath.row) + // tableView.deleteRows(at: [indexPath], with: .automatic) + // 需要返回true,否则没有反应 + completionHandler(true) + } + deleteAction.backgroundColor = NEConstant.hexRGB(0xA8ABB6) + rowActions.append(deleteAction) + + let topAction = UIContextualAction(style: .normal, title: "置顶") { (action, sourceView, completionHandler) in + + // self.dataSource.remove(at: indexPath.row) + // tableView.deleteRows(at: [indexPath], with: .automatic) + // 需要返回true,否则没有反应 + completionHandler(true) + } + topAction.backgroundColor = NEConstant.hexRGB(0x337EFF) + rowActions.append(topAction) + + let actionConfig = UISwipeActionsConfiguration.init(actions: rowActions) + actionConfig.performsFirstActionWithFullSwipe = false + + return actionConfig + } + */ } -//MARK: UI UIKit提供的重写方法 +// MARK: UI UIKit提供的重写方法 + extension ConversationListViewController { - - - /// cell点击事件,可重写该事件处理自己的逻辑业务,例如跳转到指定的会话页面 - /// - Parameters: - /// - sessionType: 会话类型 - /// - sessionId: 会话id - /// - indexPath: indexpath - open func onselectedTableRow(sessionType:NIMSessionType,sessionId:String,indexPath:IndexPath) { - if sessionType == .P2P { - let session = NIMSession(sessionId, type: .P2P) - Router.shared.use(PushP2pChatVCRouter, parameters: ["nav": self.navigationController as Any, "session" : session as Any], closure: nil) - }else if sessionType == .team { - - let session = NIMSession(sessionId, type: .team) - Router.shared.use(PushTeamChatVCRouter, parameters: ["nav": self.navigationController as Any, "session" : session as Any], closure: nil) - } - } - - - /// 删除会话 - /// - Parameters: - /// - model: 会话模型 - /// - indexPath: indexpath - open func didDeleteConversationCell(model:ConversationListModel,indexPath:IndexPath){ - - } - - /// 删除一条置顶记录 - /// - Parameters: - /// - model: 会话模型 - /// - indexPath: indexpath - open func didRemoveStickTopSession(model:ConversationListModel,indexPath:IndexPath){ - + /// cell点击事件,可重写该事件处理自己的逻辑业务,例如跳转到指定的会话页面 + /// - Parameters: + /// - sessionType: 会话类型 + /// - sessionId: 会话id + /// - indexPath: indexpath + open func onselectedTableRow(sessionType: NIMSessionType, sessionId: String, + indexPath: IndexPath) { + if sessionType == .P2P { + let session = NIMSession(sessionId, type: .P2P) + Router.shared.use( + PushP2pChatVCRouter, + parameters: ["nav": navigationController as Any, "session": session as Any], + closure: nil + ) + } else if sessionType == .team { + let session = NIMSession(sessionId, type: .team) + Router.shared.use( + PushTeamChatVCRouter, + parameters: ["nav": navigationController as Any, "session": session as Any], + closure: nil + ) } - - /// 添加一条置顶记录 - /// - Parameters: - /// - model: 会话模型 - /// - indexPath: indexpath - open func didAddStickTopSession(model:ConversationListModel,indexPath:IndexPath){ - - } - - + } + + /// 删除会话 + /// - Parameters: + /// - model: 会话模型 + /// - indexPath: indexpath + open func didDeleteConversationCell(model: ConversationListModel, indexPath: IndexPath) {} + + /// 删除一条置顶记录 + /// - Parameters: + /// - model: 会话模型 + /// - indexPath: indexpath + open func didRemoveStickTopSession(model: ConversationListModel, indexPath: IndexPath) {} + + /// 添加一条置顶记录 + /// - Parameters: + /// - model: 会话模型 + /// - indexPath: indexpath + open func didAddStickTopSession(model: ConversationListModel, indexPath: IndexPath) {} } -//MARK: ================= ConversationViewModelDelegate=================== -extension ConversationListViewController:ConversationViewModelDelegate{ - - public func didAddRecentSession() { - viewModel.sortRecentSession() - tableView.reloadData() - } - - public func didUpdateRecentSession(index: Int) { - let indexPath = IndexPath(row: index, section: 0) - tableView.reloadRows(at: [indexPath], with: .none) - } - - public func reloadTableView() { - viewModel.sortRecentSession() - tableView.reloadData() - } +// MARK: ================= ConversationViewModelDelegate=================== + +extension ConversationListViewController: ConversationViewModelDelegate { + public func didAddRecentSession() { + viewModel.sortRecentSession() + tableView.reloadData() + } + + public func didUpdateRecentSession(index: Int) { + let indexPath = IndexPath(row: index, section: 0) + tableView.reloadRows(at: [indexPath], with: .none) + } + + public func reloadTableView() { + viewModel.sortRecentSession() + tableView.reloadData() + } } diff --git a/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/Controller/ConversationSearchController.swift b/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/Controller/ConversationSearchController.swift index b4ef58ba..64a5ceb5 100644 --- a/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/Controller/ConversationSearchController.swift +++ b/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/Controller/ConversationSearchController.swift @@ -1,272 +1,290 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NIMSDK @objcMembers -open class SearchSessionHeaderView:UITableViewHeaderFooterView { - - override init(reuseIdentifier: String?) { - super.init(reuseIdentifier: reuseIdentifier) - - self.addSubview(title) - self.addSubview(bottomLine) - - NSLayoutConstraint.activate([ - title.topAnchor.constraint(equalTo: self.topAnchor), - title.leftAnchor.constraint(equalTo: self.leftAnchor,constant: 20), - - ]) - - NSLayoutConstraint.activate([ - bottomLine.rightAnchor.constraint(equalTo: self.rightAnchor,constant: -20), - bottomLine.leftAnchor.constraint(equalTo: title.leftAnchor), - bottomLine.bottomAnchor.constraint(equalTo: self.bottomAnchor), - bottomLine.heightAnchor.constraint(equalToConstant: 1) - ]) - } +open class SearchSessionHeaderView: UITableViewHeaderFooterView { + override init(reuseIdentifier: String?) { + super.init(reuseIdentifier: reuseIdentifier) - - required public init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - - func setUpTitle(title:String) { - self.title.text = title - } - - private lazy var title:UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.textColor = UIColor.ne_emptyTitleColor - label.font = NEConstant.defaultTextFont(14) - label.textAlignment = .left - return label - }() - - private lazy var bottomLine:UIView = { - let view = UIView() - view.translatesAutoresizingMaskIntoConstraints = false - view.backgroundColor = UIColor.init(hexString: "0xDBE0E8") - return view - }() + addSubview(title) + addSubview(bottomLine) + + NSLayoutConstraint.activate([ + title.topAnchor.constraint(equalTo: topAnchor), + title.leftAnchor.constraint(equalTo: leftAnchor, constant: 20), + + ]) + + NSLayoutConstraint.activate([ + bottomLine.rightAnchor.constraint(equalTo: rightAnchor, constant: -20), + bottomLine.leftAnchor.constraint(equalTo: title.leftAnchor), + bottomLine.bottomAnchor.constraint(equalTo: bottomAnchor), + bottomLine.heightAnchor.constraint(equalToConstant: 1), + ]) + } + + public required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func setUpTitle(title: String) { + self.title.text = title + } + private lazy var title: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.textColor = UIColor.ne_emptyTitleColor + label.font = NEConstant.defaultTextFont(14) + label.textAlignment = .left + return label + }() + + private lazy var bottomLine: UIView = { + let view = UIView() + view.translatesAutoresizingMaskIntoConstraints = false + view.backgroundColor = UIColor(hexString: "0xDBE0E8") + return view + }() } -public class ConversationSearchController: NEBaseViewController { - private var viewModel = ConversationSearchViewModel() - private let tag = "ConversationSearchController" - private var searchStr = "" - private let headTitleArr = ["好友","讨论组","高级群"] - - - public override func viewDidLoad() { - super.viewDidLoad() - setupSubviews() - initialConfig() - } - - public override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - self.navigationController?.isNavigationBarHidden = false - } - - func setupSubviews(){ - self.view.addSubview(tableView) - self.view.addSubview(searchTextField) - self.view.addSubview(emptyView) - - NSLayoutConstraint.activate([ - searchTextField.topAnchor.constraint(equalTo: self.view.topAnchor, constant: NEConstant.navigationHeight + NEConstant.statusBarHeight + 20), - searchTextField.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 20), - searchTextField.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: -20), - searchTextField.heightAnchor.constraint(equalToConstant: 32) - ]) - - NSLayoutConstraint.activate([ - tableView.rightAnchor.constraint(equalTo: self.view.rightAnchor), - tableView.leftAnchor.constraint(equalTo: self.view.leftAnchor), - tableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor), - tableView.topAnchor.constraint(equalTo: searchTextField.bottomAnchor,constant: 20) - ]) - - NSLayoutConstraint.activate([ - emptyView.rightAnchor.constraint(equalTo: tableView.rightAnchor), - emptyView.leftAnchor.constraint(equalTo: tableView.leftAnchor), - emptyView.bottomAnchor.constraint(equalTo: tableView.bottomAnchor), - emptyView.topAnchor.constraint(equalTo: tableView.topAnchor) - ]) +public class ConversationSearchController: NEBaseViewController,UITableViewDelegate, UITableViewDataSource { + private var viewModel = ConversationSearchViewModel() + private let tag = "ConversationSearchController" + private var searchStr = "" + private let headTitleArr = ["好友", "讨论组", "高级群"] + + override public func viewDidLoad() { + super.viewDidLoad() + setupSubviews() + initialConfig() + } + + override public func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + navigationController?.isNavigationBarHidden = false + } + + func setupSubviews() { + view.addSubview(tableView) + view.addSubview(searchTextField) + view.addSubview(emptyView) + + NSLayoutConstraint.activate([ + searchTextField.topAnchor.constraint( + equalTo: view.topAnchor, + constant: NEConstant.navigationHeight + NEConstant.statusBarHeight + 20 + ), + searchTextField.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20), + searchTextField.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20), + searchTextField.heightAnchor.constraint(equalToConstant: 32), + ]) + + NSLayoutConstraint.activate([ + tableView.rightAnchor.constraint(equalTo: view.rightAnchor), + tableView.leftAnchor.constraint(equalTo: view.leftAnchor), + tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), + tableView.topAnchor.constraint(equalTo: searchTextField.bottomAnchor, constant: 20), + ]) + + NSLayoutConstraint.activate([ + emptyView.rightAnchor.constraint(equalTo: tableView.rightAnchor), + emptyView.leftAnchor.constraint(equalTo: tableView.leftAnchor), + emptyView.bottomAnchor.constraint(equalTo: tableView.bottomAnchor), + emptyView.topAnchor.constraint(equalTo: tableView.topAnchor), + ]) + } + + func initialConfig() { + title = "搜索" + } + + // MARK: private method + + @objc func searchTextFieldChange(textfield: SearchTextField) { + guard let searchText = textfield.text else { + return } - - func initialConfig(){ - self.title = "搜索" + if searchText.count <= 0 { + emptyView.isHidden = true + viewModel.searchResult?.friend = [ConversationSearchListModel]() + viewModel.searchResult?.contactGroup = [ConversationSearchListModel]() + viewModel.searchResult?.seniorGroup = [ConversationSearchListModel]() + tableView.reloadData() + return } - - //MARK: private method - @objc func searchTextFieldChange(textfield:SearchTextField){ - - guard let searchText = textfield.text else { - return - } - if searchText.count <= 0 { - emptyView.isHidden = true - viewModel.searchResult?.friend = [ConversationSearchListModel]() - viewModel.searchResult?.contactGroup = [ConversationSearchListModel]() - viewModel.searchResult?.seniorGroup = [ConversationSearchListModel]() - tableView.reloadData() - return + let textRange = textfield.markedTextRange + if textRange == nil || ((textRange?.isEmpty) == nil) { + weak var weakSelf = self + searchStr = searchText + viewModel.doSearch(searchStr: searchText) { error, tupleInfo in + if let err = error { + NELog.errorLog(self.tag, desc: "❌doSearch failed,error = \(err)") + } else { + if tupleInfo?.friend.count == 0, tupleInfo?.contactGroup.count == 0, + tupleInfo?.seniorGroup.count == 0 { + weakSelf?.emptyView.isHidden = false + } else { + weakSelf?.emptyView.isHidden = true + } + weakSelf?.tableView.reloadData() } - - let textRange = textfield.markedTextRange - if textRange == nil || ((textRange?.isEmpty) == nil) { - weak var weakSelf = self - searchStr = searchText - viewModel.doSearch(searchStr: searchText) { error, tupleInfo in - if let err = error { - NELog.errorLog(self.tag, desc: "❌doSearch failed,error = \(err)") - }else { - if tupleInfo?.friend.count == 0 && tupleInfo?.contactGroup.count == 0 && tupleInfo?.seniorGroup.count == 0{ - weakSelf?.emptyView.isHidden = false - }else { - weakSelf?.emptyView.isHidden = true - } - weakSelf?.tableView.reloadData() - } - } - } - + } } + } - //MARK: lazy method - private lazy var tableView:UITableView = { - let tableView = UITableView.init(frame: .zero, style: .plain) - tableView.translatesAutoresizingMaskIntoConstraints = false - tableView.separatorStyle = .none - tableView.delegate = self - tableView.dataSource = self - tableView.register(ConversationSearchCell.self, forCellReuseIdentifier: "\(NSStringFromClass(ConversationSearchCell.self))") - tableView.rowHeight = 60 - tableView.backgroundColor = .white - tableView.register(SearchSessionHeaderView.self, forHeaderFooterViewReuseIdentifier: "\(NSStringFromClass(SearchSessionHeaderView.self))") - tableView.sectionHeaderHeight = 30 - tableView.sectionFooterHeight = 0 - tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.1)) - return tableView - }() - - private lazy var searchTextField:SearchTextField = { - let textField = SearchTextField() - let leftImageView = UIImageView.init(image: UIImage.ne_imageNamed(name: "conversation_search_icon")) - textField.contentMode = .center - textField.leftView = leftImageView - textField.leftViewMode = .always - textField.placeholder = localizable("搜索") - textField.font = UIFont.systemFont(ofSize: 14) - textField.textColor = UIColor.ne_greyText - textField.translatesAutoresizingMaskIntoConstraints = false - textField.layer.cornerRadius = 8 - textField.backgroundColor = UIColor.init(hexString: "0xEFF1F4") - textField.clearButtonMode = .whileEditing - textField.returnKeyType = .search - textField.addTarget(self, action: #selector(searchTextFieldChange), for: .editingChanged) - textField.placeholder = "请输入你要搜索的关键字" - return textField - }() - - private lazy var emptyView:NEEmptyDataView = { - let view = NEEmptyDataView(imageName: "user_empty", content: "该用户不存在",frame: CGRect.zero) - view.translatesAutoresizingMaskIntoConstraints = false - view.isHidden = true - return view - - }() -} + // MARK: lazy method -extension ConversationSearchController:UITableViewDelegate,UITableViewDataSource { + private lazy var tableView: UITableView = { + let tableView = UITableView(frame: .zero, style: .plain) + tableView.translatesAutoresizingMaskIntoConstraints = false + tableView.separatorStyle = .none + tableView.delegate = self + tableView.dataSource = self + tableView.register( + ConversationSearchCell.self, + forCellReuseIdentifier: "\(NSStringFromClass(ConversationSearchCell.self))" + ) + tableView.rowHeight = 60 + tableView.backgroundColor = .white + tableView.register( + SearchSessionHeaderView.self, + forHeaderFooterViewReuseIdentifier: "\(NSStringFromClass(SearchSessionHeaderView.self))" + ) + tableView.sectionHeaderHeight = 30 + tableView.sectionFooterHeight = 0 + tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.1)) + return tableView + }() + private lazy var searchTextField: SearchTextField = { + let textField = SearchTextField() + let leftImageView = UIImageView(image: UIImage + .ne_imageNamed(name: "conversation_search_icon")) + textField.contentMode = .center + textField.leftView = leftImageView + textField.leftViewMode = .always + textField.placeholder = localizable("搜索") + textField.font = UIFont.systemFont(ofSize: 14) + textField.textColor = UIColor.ne_greyText + textField.translatesAutoresizingMaskIntoConstraints = false + textField.layer.cornerRadius = 8 + textField.backgroundColor = UIColor(hexString: "0xEFF1F4") + textField.clearButtonMode = .whileEditing + textField.returnKeyType = .search + textField.addTarget(self, action: #selector(searchTextFieldChange), for: .editingChanged) + textField.placeholder = "请输入你要搜索的关键字" + return textField + }() + + private lazy var emptyView: NEEmptyDataView = { + let view = NEEmptyDataView(imageName: "user_empty", content: "该用户不存在", frame: CGRect.zero) + view.translatesAutoresizingMaskIntoConstraints = false + view.isHidden = true + return view + + }() + + //MARK: UITableViewDelegate, UITableViewDataSource public func numberOfSections(in tableView: UITableView) -> Int { - return 3 + return 3 } - - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - - if let friend = viewModel.searchResult?.friend,section == 0 { - return friend.count - }else if let contactGroup = viewModel.searchResult?.contactGroup,section == 1 { - return contactGroup.count - }else if let seniorGroup = viewModel.searchResult?.seniorGroup,section == 2 { - return seniorGroup.count - }else { - return 0 - } + public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + if let friend = viewModel.searchResult?.friend, section == 0 { + return friend.count + } else if let contactGroup = viewModel.searchResult?.contactGroup, section == 1 { + return contactGroup.count + } else if let seniorGroup = viewModel.searchResult?.seniorGroup, section == 2 { + return seniorGroup.count + } else { + return 0 + } } - - public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - - let cell = tableView.dequeueReusableCell(withIdentifier: "\(NSStringFromClass(ConversationSearchCell.self))", for: indexPath) as! ConversationSearchCell - if indexPath.section == 0 { - cell.searchModel = viewModel.searchResult?.friend[indexPath.row] - }else if indexPath.section == 1 { - cell.searchModel = viewModel.searchResult?.contactGroup[indexPath.row] - }else { - cell.searchModel = viewModel.searchResult?.seniorGroup[indexPath.row] - } - cell.searchText = searchStr - return cell + + public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(NSStringFromClass(ConversationSearchCell.self))", + for: indexPath + ) as! ConversationSearchCell + if indexPath.section == 0 { + cell.searchModel = viewModel.searchResult?.friend[indexPath.row] + } else if indexPath.section == 1 { + cell.searchModel = viewModel.searchResult?.contactGroup[indexPath.row] + } else { + cell.searchModel = viewModel.searchResult?.seniorGroup[indexPath.row] + } + cell.searchText = searchStr + return cell } - - + public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - - - if indexPath.section == 0 { - let searchModel = viewModel.searchResult?.friend[indexPath.row] - if let userId = searchModel?.userInfo?.userId { - let session = NIMSession(userId, type: .P2P) - Router.shared.use(PushP2pChatVCRouter, parameters: ["nav": self.navigationController as Any, "session" : session as Any], closure: nil) - } - - }else if indexPath.section == 1 { - let searchModel = viewModel.searchResult?.contactGroup[indexPath.row] - if let teamId = searchModel?.teamInfo?.teamId { - let session = NIMSession(teamId, type: .team) - Router.shared.use(PushTeamChatVCRouter, parameters: ["nav": self.navigationController as Any, "session" : session as Any], closure: nil) - } - }else { - let searchModel = viewModel.searchResult?.seniorGroup[indexPath.row] - if let teamId = searchModel?.teamInfo?.teamId { - let session = NIMSession(teamId, type: .team) - Router.shared.use(PushTeamChatVCRouter, parameters: ["nav": self.navigationController as Any, "session" : session as Any], closure: nil) - } + if indexPath.section == 0 { + let searchModel = viewModel.searchResult?.friend[indexPath.row] + if let userId = searchModel?.userInfo?.userId { + let session = NIMSession(userId, type: .P2P) + Router.shared.use( + PushP2pChatVCRouter, + parameters: ["nav": navigationController as Any, "session": session as Any], + closure: nil + ) } + } else if indexPath.section == 1 { + let searchModel = viewModel.searchResult?.contactGroup[indexPath.row] + if let teamId = searchModel?.teamInfo?.teamId { + let session = NIMSession(teamId, type: .team) + Router.shared.use( + PushTeamChatVCRouter, + parameters: ["nav": navigationController as Any, "session": session as Any], + closure: nil + ) + } + } else { + let searchModel = viewModel.searchResult?.seniorGroup[indexPath.row] + if let teamId = searchModel?.teamInfo?.teamId { + let session = NIMSession(teamId, type: .team) + Router.shared.use( + PushTeamChatVCRouter, + parameters: ["nav": navigationController as Any, "session": session as Any], + closure: nil + ) + } + } } - - public func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { - let sectionView = tableView.dequeueReusableHeaderFooterView(withIdentifier: "\(NSStringFromClass(SearchSessionHeaderView.self))") as! SearchSessionHeaderView - sectionView.setUpTitle(title: headTitleArr[section]) - sectionView.backgroundView = UIView.init() - return sectionView + public func tableView(_ tableView: UITableView, + viewForHeaderInSection section: Int) -> UIView? { + let sectionView = tableView + .dequeueReusableHeaderFooterView( + withIdentifier: "\(NSStringFromClass(SearchSessionHeaderView.self))" + ) as! SearchSessionHeaderView + sectionView.setUpTitle(title: headTitleArr[section]) + sectionView.backgroundView = UIView() + return sectionView } - - public func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { - - if let friend = viewModel.searchResult?.friend,friend.count > 0,section == 0 { - return 30 - - }else if let contactGroup = viewModel.searchResult?.contactGroup,contactGroup.count > 0, section == 1 { - return 30 - }else if let seniorGroup = viewModel.searchResult?.seniorGroup,seniorGroup.count > 0,section == 2 { - return 30 - }else { - return 0 - } + + public func tableView(_ tableView: UITableView, + heightForHeaderInSection section: Int) -> CGFloat { + if let friend = viewModel.searchResult?.friend, friend.count > 0, section == 0 { + return 30 + + } else if let contactGroup = viewModel.searchResult?.contactGroup, contactGroup.count > 0, + section == 1 { + return 30 + } else if let seniorGroup = viewModel.searchResult?.seniorGroup, seniorGroup.count > 0, + section == 2 { + return 30 + } else { + return 0 + } } } + diff --git a/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/ConversationRouter/ConversationRouter.swift b/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/ConversationRouter/ConversationRouter.swift index bf38a088..31a1b4f2 100644 --- a/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/ConversationRouter/ConversationRouter.swift +++ b/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/ConversationRouter/ConversationRouter.swift @@ -1,23 +1,22 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation -public struct ConversationRouter { - - public static func register() { - Router.shared.register(SearchContactPageRouter) { param in - let nav = param["nav"] as? UINavigationController - let searchCtrl = ConversationSearchController() - nav?.pushViewController(searchCtrl, animated: true) - } +public enum ConversationRouter { + public static func register() { + Router.shared.register(SearchContactPageRouter) { param in + let nav = param["nav"] as? UINavigationController + let searchCtrl = ConversationSearchController() + nav?.pushViewController(searchCtrl, animated: true) + } - Router.shared.register(ConversationPageRouter) { param in - let nav = param["nav"] as? UINavigationController - let conversation = ConversationController() - nav?.pushViewController(conversation, animated: true) - } + Router.shared.register(ConversationPageRouter) { param in + let nav = param["nav"] as? UINavigationController + let conversation = ConversationController() + nav?.pushViewController(conversation, animated: true) } + } } diff --git a/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/View/ConversationListCell.swift b/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/View/ConversationListCell.swift index 909c2a7c..41ed31be 100644 --- a/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/View/ConversationListCell.swift +++ b/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/View/ConversationListCell.swift @@ -1,263 +1,266 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NIMSDK - open class ConversationListCell: UITableViewCell { - - private var viewModel = ConversationViewModel() - public var topStickInfos = [NIMSession:NIMStickTopSessionInfo]() + private var viewModel = ConversationViewModel() + public var topStickInfos = [NIMSession: NIMStickTopSessionInfo]() - open override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } + override open func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } - open override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) + override open func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) - // Configure the view for the selected state - } + // Configure the view for the selected state + } + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + setupSubviews() + initSubviewsLayout() + } + + public required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc + func setupSubviews() { + selectionStyle = .none + contentView.addSubview(headImge) + contentView.addSubview(redAngleView) + contentView.addSubview(title) + contentView.addSubview(subTitle) + contentView.addSubview(timeLabel) + contentView.addSubview(notifyMsg) + + NSLayoutConstraint.activate([ + headImge.leftAnchor.constraint( + equalTo: contentView.leftAnchor, + constant: NEConstant.screenInterval + ), + headImge.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + headImge.widthAnchor.constraint(equalToConstant: 42), + headImge.heightAnchor.constraint(equalToConstant: 42), + ]) + + NSLayoutConstraint.activate([ + redAngleView.centerXAnchor.constraint(equalTo: headImge.rightAnchor, constant: -3), + redAngleView.centerYAnchor.constraint(equalTo: headImge.topAnchor, constant: 3), + redAngleView.heightAnchor.constraint(equalToConstant: 18), + ]) + + NSLayoutConstraint.activate([ + timeLabel.rightAnchor.constraint( + equalTo: contentView.rightAnchor, + constant: -NEConstant.screenInterval + ), + timeLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 17), + ]) + + NSLayoutConstraint.activate([ + title.leftAnchor.constraint(equalTo: headImge.rightAnchor, constant: 12), + title.rightAnchor.constraint(equalTo: timeLabel.leftAnchor, constant: -5), + title.topAnchor.constraint(equalTo: headImge.topAnchor), + ]) - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - setupSubviews() - initSubviewsLayout() + NSLayoutConstraint.activate([ + subTitle.leftAnchor.constraint(equalTo: headImge.rightAnchor, constant: 12), + subTitle.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -50), + subTitle.topAnchor.constraint(equalTo: title.bottomAnchor, constant: 6), + ]) + + NSLayoutConstraint.activate([ + notifyMsg.rightAnchor.constraint(equalTo: timeLabel.rightAnchor), + notifyMsg.topAnchor.constraint(equalTo: timeLabel.bottomAnchor, constant: 5), + notifyMsg.widthAnchor.constraint(equalToConstant: 13), + notifyMsg.heightAnchor.constraint(equalToConstant: 13), + ]) + } + + func initSubviewsLayout() { + if NEKitConversationConfig.shared.ui.avatarType == .rectangle { + headImge.layer.cornerRadius = NEKitConversationConfig.shared.ui.avatarCornerRadius + } else if NEKitConversationConfig.shared.ui.avatarType == .cycle { + headImge.layer.cornerRadius = 21.0 } - - required public init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") + } + + func configData(sessionModel: ConversationListModel?) { + guard let conversationModel = sessionModel else { return } + + if conversationModel.recentSession?.session?.sessionType == .P2P { + // p2p head image + if let imageName = conversationModel.userInfo?.userInfo?.avatarUrl { + headImge.setTitle("") + headImge.sd_setImage(with: URL(string: imageName), completed: nil) + } else { + headImge.setTitle(conversationModel.userInfo?.showName() ?? "") + headImge.sd_setImage(with: nil, completed: nil) + headImge.backgroundColor = UIColor + .colorWithString(string: conversationModel.userInfo?.userId) + } + + // p2p nickName + title.text = conversationModel.userInfo?.showName() + + // notifyForNewMsg + notifyMsg.isHidden = viewModel + .notifyForNewMsg(userId: conversationModel.userInfo?.userId) + + } else if conversationModel.recentSession?.session?.sessionType == .team { + // team head image + if let imageName = conversationModel.teamInfo?.avatarUrl { + headImge.setTitle("") + headImge.sd_setImage(with: URL(string: imageName), completed: nil) + } else { + headImge.setTitle(conversationModel.teamInfo?.getShowName() ?? "") + headImge.sd_setImage(with: nil, completed: nil) + headImge.backgroundColor = UIColor + .colorWithString(string: conversationModel.teamInfo?.teamId) + } + title.text = conversationModel.teamInfo?.getShowName() + + // notifyForNewMsg + let teamNotifyState = viewModel + .notifyStateForNewMsg(teamId: conversationModel.teamInfo?.teamId) + notifyMsg.isHidden = teamNotifyState == .none ? false : true } - - @objc - func setupSubviews(){ - self.selectionStyle = .none - self.contentView.addSubview(headImge) - self.contentView.addSubview(redAngleView) - self.contentView.addSubview(title) - self.contentView.addSubview(subTitle) - self.contentView.addSubview(timeLabel) - self.contentView.addSubview(notifyMsg) - - NSLayoutConstraint.activate([ - headImge.leftAnchor.constraint(equalTo: self.contentView.leftAnchor,constant: NEConstant.screenInterval), - headImge.centerYAnchor.constraint(equalTo: self.contentView.centerYAnchor), - headImge.widthAnchor.constraint(equalToConstant: 42), - headImge.heightAnchor.constraint(equalToConstant: 42) - ]) - - NSLayoutConstraint.activate([ - redAngleView.centerXAnchor.constraint(equalTo: headImge.rightAnchor,constant: -3), - redAngleView.centerYAnchor.constraint(equalTo: headImge.topAnchor,constant: 3), - redAngleView.heightAnchor.constraint(equalToConstant: 18) - ]) - - NSLayoutConstraint.activate([ - timeLabel.rightAnchor.constraint(equalTo: self.contentView.rightAnchor,constant: -NEConstant.screenInterval), - timeLabel.topAnchor.constraint(equalTo: self.contentView.topAnchor,constant: 17), - ]) - - NSLayoutConstraint.activate([ - title.leftAnchor.constraint(equalTo: headImge.rightAnchor,constant: 12), - title.rightAnchor.constraint(equalTo: timeLabel.leftAnchor,constant: -5), - title.topAnchor.constraint(equalTo: headImge.topAnchor) - ]) - - NSLayoutConstraint.activate([ - subTitle.leftAnchor.constraint(equalTo: headImge.rightAnchor,constant: 12), - subTitle.rightAnchor.constraint(equalTo: self.contentView.rightAnchor,constant: -50), - subTitle.topAnchor.constraint(equalTo: title.bottomAnchor,constant: 6) - ]) - - NSLayoutConstraint.activate([ - notifyMsg.rightAnchor.constraint(equalTo: self.timeLabel.rightAnchor), - notifyMsg.topAnchor.constraint(equalTo: self.timeLabel.bottomAnchor,constant: 5), - notifyMsg.widthAnchor.constraint(equalToConstant: 13), - notifyMsg.heightAnchor.constraint(equalToConstant: 13) - ]) + + // last message + if let lastMessage = conversationModel.recentSession?.lastMessage { + subTitle.text = contentForRecentSession(message: lastMessage) } - - func initSubviewsLayout (){ - if NEKitConversationConfig.shared.ui.avatarType == .rectangle { - headImge.layer.cornerRadius = NEKitConversationConfig.shared.ui.avatarCornerRadius - }else if NEKitConversationConfig.shared.ui.avatarType == .cycle { - headImge.layer.cornerRadius = 21.0 + + // unRead message count + if let unReadCount = conversationModel.recentSession?.unreadCount { + if unReadCount <= 0 { + redAngleView.isHidden = true + } else { + redAngleView.isHidden = notifyMsg.isHidden ? false : true + if unReadCount <= 99 { + redAngleView.text = "\(unReadCount)" + } else { + redAngleView.text = "99+" } + } } - - - func configData(sessionModel:ConversationListModel?){ - - guard let conversationModel = sessionModel else { return } - - if conversationModel.recentSession?.session?.sessionType == .P2P { - //p2p head image - if let imageName = conversationModel.userInfo?.userInfo?.avatarUrl { - headImge.setTitle("") - headImge.sd_setImage(with: URL.init(string: imageName), completed: nil) - }else { - headImge.setTitle(conversationModel.userInfo?.showName() ?? "") - headImge.sd_setImage(with:nil, completed: nil) - headImge.backgroundColor = UIColor.colorWithString(string: conversationModel.userInfo?.userId) - } - - //p2p nickName - title.text = conversationModel.userInfo?.showName() - - //notifyForNewMsg - notifyMsg.isHidden = viewModel.notifyForNewMsg(userId: conversationModel.userInfo?.userId) - - }else if conversationModel.recentSession?.session?.sessionType == .team { - //team head image - if let imageName = conversationModel.teamInfo?.avatarUrl { - headImge.setTitle("") - headImge.sd_setImage(with: URL.init(string: imageName), completed: nil) - }else { - headImge.setTitle(conversationModel.teamInfo?.getShowName() ?? "") - headImge.sd_setImage(with:nil, completed: nil) - headImge.backgroundColor = UIColor.colorWithString(string: conversationModel.teamInfo?.teamId) - } - title.text = conversationModel.teamInfo?.getShowName() - - //notifyForNewMsg - let teamNotifyState = viewModel.notifyStateForNewMsg(teamId: conversationModel.teamInfo?.teamId) - notifyMsg.isHidden = teamNotifyState == .none ? false : true - } - - //last message - if let lastMessage = conversationModel.recentSession?.lastMessage { - subTitle.text = contentForRecentSession(message: lastMessage) - } - - //unRead message count - if let unReadCount = conversationModel.recentSession?.unreadCount { - if unReadCount <= 0 { - redAngleView.isHidden = true - }else { - redAngleView.isHidden = notifyMsg.isHidden ? false : true - if unReadCount <= 99 { - redAngleView.text = "\(unReadCount)" - }else { - redAngleView.text = "99+" - } - } - } - - //time - if let rencentSession = conversationModel.recentSession { - timeLabel.text = dealTime(time: timestampDescriptionForRecentSession(recentSession: rencentSession)) - } - - //backgroundColor - if let session = conversationModel.recentSession?.session{ - let isTop = topStickInfos[session] != nil - if isTop { - self.contentView.backgroundColor = UIColor.init(hexString: "0xF3F5F7") - }else { - self.contentView.backgroundColor = .white - } - } + // time + if let rencentSession = conversationModel.recentSession { + timeLabel + .text = + dealTime(time: timestampDescriptionForRecentSession(recentSession: rencentSession)) } - - func timestampDescriptionForRecentSession(recentSession:NIMRecentSession) -> TimeInterval { - - if let lastMessage = recentSession.lastMessage { - return lastMessage.timestamp - } - // 服务端时间戳以毫秒为单位,需要转化 - return recentSession.updateTime/1000 + + // backgroundColor + if let session = conversationModel.recentSession?.session { + let isTop = topStickInfos[session] != nil + if isTop { + contentView.backgroundColor = UIColor(hexString: "0xF3F5F7") + } else { + contentView.backgroundColor = .white + } } - - func dealTime(time:TimeInterval) -> String { - - let targetDate = Date(timeIntervalSince1970: time) - let fmt = DateFormatter() - - if targetDate.isToday() { - fmt.dateFormat = "HH:mm" - return fmt.string(from: targetDate) - - }else { - if targetDate.isThisYear() { - fmt.dateFormat = "MM月dd日 HH:mm" - return fmt.string(from: targetDate) - - }else { - fmt.dateFormat = "yyyy年MM月dd日 HH:mm" - return fmt.string(from: targetDate) - - } - } + } + + func timestampDescriptionForRecentSession(recentSession: NIMRecentSession) -> TimeInterval { + if let lastMessage = recentSession.lastMessage { + return lastMessage.timestamp } - - func contentForRecentSession(message:NIMMessage)->String { - let text = NEMessageUtil.messageContent(message: message) - return text + // 服务端时间戳以毫秒为单位,需要转化 + return recentSession.updateTime / 1000 + } + + func dealTime(time: TimeInterval) -> String { + let targetDate = Date(timeIntervalSince1970: time) + let fmt = DateFormatter() + + if targetDate.isToday() { + fmt.dateFormat = "HH:mm" + return fmt.string(from: targetDate) + + } else { + if targetDate.isThisYear() { + fmt.dateFormat = "MM月dd日 HH:mm" + return fmt.string(from: targetDate) + + } else { + fmt.dateFormat = "yyyy年MM月dd日 HH:mm" + return fmt.string(from: targetDate) + } } - - //MARK: lazy Method - - lazy var headImge: NEUserHeaderView = { - let headView = NEUserHeaderView(frame: .zero) - headView.titleLabel.textColor = .white - headView.titleLabel.font = NEConstant.defaultTextFont(14) - headView.translatesAutoresizingMaskIntoConstraints = false - headView.layer.cornerRadius = 21 - headView.clipsToBounds = true - return headView - }() - - private lazy var redAngleView:RedAngleLabel = { - let label = RedAngleLabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.font = NEConstant.defaultTextFont(12) - label.textColor = .white - label.text = "99+" - label.backgroundColor = NEConstant.hexRGB(0xF24957) - label.textInsets = UIEdgeInsets(top: 3, left: 7, bottom: 3, right: 7) - label.layer.cornerRadius = 9 - label.clipsToBounds = true - label.isHidden = true - return label - }() - - private lazy var title:UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.textColor = NEKitConversationConfig.shared.ui.titleColor - label.font = NEKitConversationConfig.shared.ui.titleFont - label.text = "Oliver" - return label - }() - - private lazy var subTitle:UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.textColor = NEKitConversationConfig.shared.ui.subTitleColor - label.font = NEKitConversationConfig.shared.ui.subTitleFont - return label - }() - - private lazy var timeLabel:UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.textColor = NEKitConversationConfig.shared.ui.timeColor - label.font = NEKitConversationConfig.shared.ui.timeFont - label.textAlignment = .right - return label - }() - - private lazy var notifyMsg:UIImageView = { - let notify = UIImageView() - notify.translatesAutoresizingMaskIntoConstraints = false - notify.image = UIImage.ne_imageNamed(name: "noNeed_notify") - notify.isHidden = true - return notify - }() - + } + + func contentForRecentSession(message: NIMMessage) -> String { + let text = NEMessageUtil.messageContent(message: message) + return text + } + + // MARK: lazy Method + + lazy var headImge: NEUserHeaderView = { + let headView = NEUserHeaderView(frame: .zero) + headView.titleLabel.textColor = .white + headView.titleLabel.font = NEConstant.defaultTextFont(14) + headView.translatesAutoresizingMaskIntoConstraints = false + headView.layer.cornerRadius = 21 + headView.clipsToBounds = true + return headView + }() + + private lazy var redAngleView: RedAngleLabel = { + let label = RedAngleLabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.font = NEConstant.defaultTextFont(12) + label.textColor = .white + label.text = "99+" + label.backgroundColor = NEConstant.hexRGB(0xF24957) + label.textInsets = UIEdgeInsets(top: 3, left: 7, bottom: 3, right: 7) + label.layer.cornerRadius = 9 + label.clipsToBounds = true + label.isHidden = true + return label + }() + + private lazy var title: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.textColor = NEKitConversationConfig.shared.ui.titleColor + label.font = NEKitConversationConfig.shared.ui.titleFont + label.text = "Oliver" + return label + }() + + private lazy var subTitle: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.textColor = NEKitConversationConfig.shared.ui.subTitleColor + label.font = NEKitConversationConfig.shared.ui.subTitleFont + return label + }() + + private lazy var timeLabel: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.textColor = NEKitConversationConfig.shared.ui.timeColor + label.font = NEKitConversationConfig.shared.ui.timeFont + label.textAlignment = .right + return label + }() + + private lazy var notifyMsg: UIImageView = { + let notify = UIImageView() + notify.translatesAutoresizingMaskIntoConstraints = false + notify.image = UIImage.ne_imageNamed(name: "noNeed_notify") + notify.isHidden = true + return notify + }() } diff --git a/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/View/ConversationNavView.swift b/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/View/ConversationNavView.swift index 5c2f4cf1..e2492e0a 100644 --- a/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/View/ConversationNavView.swift +++ b/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/View/ConversationNavView.swift @@ -1,121 +1,125 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCore protocol ConversationNavViewDelegate: AnyObject { - func didClickAddBtn() - func searchAction() + func didClickAddBtn() + func searchAction() } class ConversationNavView: UIView { - - weak var delegate: ConversationNavViewDelegate? - - override init(frame: CGRect) { - super.init(frame: frame) - setupSubviews() - initSubviewsLayout() - - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func setupSubviews(){ - self.addSubview(brandBtn) - self.addSubview(searchBtn) - self.addSubview(addBtn) - self.addSubview(bottomLine) - - NSLayoutConstraint.activate([ - brandBtn.bottomAnchor.constraint(equalTo: self.bottomAnchor,constant: -8), - brandBtn.leftAnchor.constraint(equalTo: self.leftAnchor,constant: NEConstant.screenInterval), - ]) - - NSLayoutConstraint.activate([ - addBtn.centerYAnchor.constraint(equalTo: brandBtn.centerYAnchor), - addBtn.rightAnchor.constraint(equalTo: self.rightAnchor,constant: -NEConstant.screenInterval), - addBtn.widthAnchor.constraint(equalToConstant: 20), - addBtn.heightAnchor.constraint(equalToConstant: 20) - ]) - - NSLayoutConstraint.activate([ - searchBtn.centerYAnchor.constraint(equalTo: brandBtn.centerYAnchor), - searchBtn.rightAnchor.constraint(equalTo: addBtn.leftAnchor,constant: -NEConstant.screenInterval), - searchBtn.widthAnchor.constraint(equalToConstant: 20), - searchBtn.heightAnchor.constraint(equalToConstant: 20) - ]) - - - NSLayoutConstraint.activate([ - bottomLine.leftAnchor.constraint(equalTo: self.leftAnchor), - bottomLine.rightAnchor.constraint(equalTo: self.rightAnchor), - bottomLine.bottomAnchor.constraint(equalTo: self.bottomAnchor), - bottomLine.heightAnchor.constraint(equalToConstant: 0.5) - ]) - } - - func initSubviewsLayout(){ - if NEKitConversationConfig.shared.ui.hiddenRightBtns { - searchBtn.isHidden = true - addBtn.isHidden = true - }else { - if NEKitConversationConfig.shared.ui.hiddenSearchBtn { - searchBtn.isHidden = true - } - } + weak var delegate: ConversationNavViewDelegate? + + override init(frame: CGRect) { + super.init(frame: frame) + setupSubviews() + initSubviewsLayout() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func setupSubviews() { + addSubview(brandBtn) + addSubview(searchBtn) + addSubview(addBtn) + addSubview(bottomLine) + + NSLayoutConstraint.activate([ + brandBtn.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -8), + brandBtn.leftAnchor.constraint( + equalTo: leftAnchor, + constant: NEConstant.screenInterval + ), + ]) + + NSLayoutConstraint.activate([ + addBtn.centerYAnchor.constraint(equalTo: brandBtn.centerYAnchor), + addBtn.rightAnchor.constraint( + equalTo: rightAnchor, + constant: -NEConstant.screenInterval + ), + addBtn.widthAnchor.constraint(equalToConstant: 20), + addBtn.heightAnchor.constraint(equalToConstant: 20), + ]) + + NSLayoutConstraint.activate([ + searchBtn.centerYAnchor.constraint(equalTo: brandBtn.centerYAnchor), + searchBtn.rightAnchor.constraint( + equalTo: addBtn.leftAnchor, + constant: -NEConstant.screenInterval + ), + searchBtn.widthAnchor.constraint(equalToConstant: 20), + searchBtn.heightAnchor.constraint(equalToConstant: 20), + ]) + + NSLayoutConstraint.activate([ + bottomLine.leftAnchor.constraint(equalTo: leftAnchor), + bottomLine.rightAnchor.constraint(equalTo: rightAnchor), + bottomLine.bottomAnchor.constraint(equalTo: bottomAnchor), + bottomLine.heightAnchor.constraint(equalToConstant: 0.5), + ]) + } + + func initSubviewsLayout() { + if NEKitConversationConfig.shared.ui.hiddenRightBtns { + searchBtn.isHidden = true + addBtn.isHidden = true + } else { + if NEKitConversationConfig.shared.ui.hiddenSearchBtn { + searchBtn.isHidden = true + } } - //MARK: lazy method - private lazy var brandBtn:UIButton = { - let button = UIButton() - button.setTitle(localizable("云信IM"), for: .normal) - button.setImage(UIImage.ne_imageNamed(name: "brand_yunxin"), for: .normal) - button.layoutButtonImage(style: .left, space: 12) - button.translatesAutoresizingMaskIntoConstraints = false - button.setTitleColor(UIColor.black, for: .normal) - button.titleLabel?.font = NEConstant.textFont("PingFangSC-Medium",20) - return button - }() - - private lazy var searchBtn:UIButton = { - let button = UIButton() - button.setImage(UIImage.ne_imageNamed(name: "chat_search"), for: .normal) - button.translatesAutoresizingMaskIntoConstraints = false - button.addTarget(self, action: #selector(searchBtnClick), for: .touchUpInside) - return button - }() - - - private lazy var addBtn: ExpandButton = { - let button = ExpandButton() - button.setImage(UIImage.ne_imageNamed(name: "chat_add"), for: .normal) - button.translatesAutoresizingMaskIntoConstraints = false - button.addTarget(self, action: #selector(addBtnClick), for: .touchUpInside) - return button - }() - - private lazy var bottomLine:UIView = { - let view = UIView() - view.translatesAutoresizingMaskIntoConstraints = false - view.backgroundColor = UIColor.init(hexString: "0xDBE0E8") - return view - }() - + } + + // MARK: lazy method + + private lazy var brandBtn: UIButton = { + let button = UIButton() + button.setTitle(localizable("云信IM"), for: .normal) + button.setImage(UIImage.ne_imageNamed(name: "brand_yunxin"), for: .normal) + button.layoutButtonImage(style: .left, space: 12) + button.translatesAutoresizingMaskIntoConstraints = false + button.setTitleColor(UIColor.black, for: .normal) + button.titleLabel?.font = NEConstant.textFont("PingFangSC-Medium", 20) + return button + }() + + private lazy var searchBtn: UIButton = { + let button = UIButton() + button.setImage(UIImage.ne_imageNamed(name: "chat_search"), for: .normal) + button.translatesAutoresizingMaskIntoConstraints = false + button.addTarget(self, action: #selector(searchBtnClick), for: .touchUpInside) + return button + }() + + private lazy var addBtn: ExpandButton = { + let button = ExpandButton() + button.setImage(UIImage.ne_imageNamed(name: "chat_add"), for: .normal) + button.translatesAutoresizingMaskIntoConstraints = false + button.addTarget(self, action: #selector(addBtnClick), for: .touchUpInside) + return button + }() + + private lazy var bottomLine: UIView = { + let view = UIView() + view.translatesAutoresizingMaskIntoConstraints = false + view.backgroundColor = UIColor(hexString: "0xDBE0E8") + return view + }() } extension ConversationNavView { - - @objc func searchBtnClick(sender:UIButton) { - delegate?.searchAction() - } - - @objc func addBtnClick(sender:UIButton) { - delegate?.didClickAddBtn() - } - + @objc func searchBtnClick(sender: UIButton) { + delegate?.searchAction() + } + + @objc func addBtnClick(sender: UIButton) { + delegate?.didClickAddBtn() + } } diff --git a/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/View/ConversationSearchCell.swift b/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/View/ConversationSearchCell.swift index c8c4efb6..e30ed3be 100644 --- a/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/View/ConversationSearchCell.swift +++ b/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/View/ConversationSearchCell.swift @@ -1,69 +1,62 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class ConversationSearchCell: TextBaseCell { + public var searchModel: ConversationSearchListModel? { + didSet { + if let _ = searchModel { + if let userInfo = searchModel?.userInfo { + titleLabel.text = userInfo.getShowName() - - public var searchModel:ConversationSearchListModel?{ - didSet { - if let _ = searchModel { - if let userInfo = searchModel?.userInfo { - - titleLabel.text = userInfo.getShowName() - - if let imageName = userInfo.userInfo?.avatarUrl { - headImge.setTitle("") - headImge.sd_setImage(with: URL.init(string: imageName), completed: nil) - }else { - headImge.setTitle(userInfo.getShowName() ?? "") - headImge.sd_setImage(with:nil, completed: nil) - headImge.backgroundColor = UIColor.colorWithString(string: userInfo.userId) - } - } - if let teamInfo = searchModel?.teamInfo { - titleLabel.text = teamInfo.getShowName() - if let imageName = teamInfo.avatarUrl { - headImge.setTitle("") - headImge.sd_setImage(with: URL.init(string: imageName), completed: nil) - }else { - headImge.setTitle(teamInfo.getShowName()) - headImge.sd_setImage(with:nil, completed: nil) - headImge.backgroundColor = UIColor.colorWithString(string: teamInfo.teamId) - } - } - } + if let imageName = userInfo.userInfo?.avatarUrl { + headImge.setTitle("") + headImge.sd_setImage(with: URL(string: imageName), completed: nil) + } else { + headImge.setTitle(userInfo.getShowName() ?? "") + headImge.sd_setImage(with: nil, completed: nil) + headImge.backgroundColor = UIColor.colorWithString(string: userInfo.userId) + } } - } - - public var searchText:String = "" { - didSet { - if let titleText = titleLabel.text,let range = titleText.findAllIndex(searchText).first { - - let attributedStr = NSMutableAttributedString(string: titleText) - //range必须要加,参数分别表示从索引几开始取几个字符 - attributedStr.addAttribute( - .foregroundColor, - value: UIColor.ne_blueText, - range: range - ) - titleLabel.attributedText = attributedStr - } - + if let teamInfo = searchModel?.teamInfo { + titleLabel.text = teamInfo.getShowName() + if let imageName = teamInfo.avatarUrl { + headImge.setTitle("") + headImge.sd_setImage(with: URL(string: imageName), completed: nil) + } else { + headImge.setTitle(teamInfo.getShowName()) + headImge.sd_setImage(with: nil, completed: nil) + headImge.backgroundColor = UIColor.colorWithString(string: teamInfo.teamId) + } } + } } - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - } - - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") + } + + public var searchText: String = "" { + didSet { + if let titleText = titleLabel.text, + let range = titleText.findAllIndex(searchText).first { + let attributedStr = NSMutableAttributedString(string: titleText) + // range必须要加,参数分别表示从索引几开始取几个字符 + attributedStr.addAttribute( + .foregroundColor, + value: UIColor.ne_blueText, + range: range + ) + titleLabel.attributedText = attributedStr + } } + } + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + } - + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } } diff --git a/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/ViewModel/ConversationSearchViewModel.swift b/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/ViewModel/ConversationSearchViewModel.swift index 12ceee76..cc899bd5 100644 --- a/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/ViewModel/ConversationSearchViewModel.swift +++ b/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/ViewModel/ConversationSearchViewModel.swift @@ -1,33 +1,37 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NIMSDK - class ConversationSearchViewModel: NSObject { - let repo = ConversationRepo() - public var searchResult:(friend:[ConversationSearchListModel], contactGroup:[ConversationSearchListModel],seniorGroup:[ConversationSearchListModel])? - - public override init() { - super.init() - } + let repo = ConversationRepo() + public var searchResult: ( + friend: [ConversationSearchListModel], + contactGroup: [ConversationSearchListModel], + seniorGroup: [ConversationSearchListModel] + )? + + override public init() { + super.init() + } - - - /// 请求接口 - /// - Parameters: - /// - searchStr: 搜索的内容 - /// - completion: 回调结果 - public func doSearch(searchStr:String,_ completion:@escaping (NSError?,(friend:[ConversationSearchListModel], contactGroup:[ConversationSearchListModel],seniorGroup:[ConversationSearchListModel])?)->()) { - weak var weakSelf = self - repo.searchContact(searchStr: searchStr) { error, searchResult in - weakSelf?.searchResult = searchResult - completion(error,searchResult) - } - + /// 请求接口 + /// - Parameters: + /// - searchStr: 搜索的内容 + /// - completion: 回调结果 + public func doSearch(searchStr: String, + _ completion: @escaping (NSError?, ( + friend: [ConversationSearchListModel], + contactGroup: [ConversationSearchListModel], + seniorGroup: [ConversationSearchListModel] + )?) -> Void) { + weak var weakSelf = self + repo.searchContact(searchStr: searchStr) { error, searchResult in + weakSelf?.searchResult = searchResult + completion(error, searchResult) } - + } } diff --git a/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/ViewModel/ConversationViewModel.swift b/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/ViewModel/ConversationViewModel.swift index 45af9d46..d36dc923 100644 --- a/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/ViewModel/ConversationViewModel.swift +++ b/NEConversationUIKit/NEKitConversationUI/Classes/Conversation/ViewModel/ConversationViewModel.swift @@ -1,272 +1,264 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. - +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NEKitConversation import NIMSDK -public protocol ConversationViewModelDelegate: AnyObject{ - func didAddRecentSession() - func didUpdateRecentSession(index:Int) - func reloadTableView() +public protocol ConversationViewModelDelegate: AnyObject { + func didAddRecentSession() + func didUpdateRecentSession(index: Int) + func reloadTableView() } -public class ConversationViewModel:NSObject,ConversationRepoDelegate,NIMConversationManagerDelegate,NIMTeamManagerDelegate,NIMUserManagerDelegate { - - public var conversationListArray:[ConversationListModel]? - public var stickTopInfos = [NIMSession:NIMStickTopSessionInfo]() - public weak var delegate: ConversationViewModelDelegate? - private let className = "ConversationViewModel" - let repo = ConversationRepo() - - public override init() { - super.init() - repo.delegate = self - repo.addSessionDelegate(delegate: self) - repo.addTeamDelegate(delegate: self) - stickTopInfos = repo.getStickTopInfos() - NIMSDK.shared().userManager.add(self) - } - - public func fetchServerSessions(option:NIMFetchServerSessionOption,_ completion:@escaping (NSError?,[ConversationListModel]?)->()) { - - weak var weakSelf = self - repo.getSessionList(option: option) { error, conversaitonList in - weakSelf?.conversationListArray = conversaitonList - completion(error,weakSelf?.conversationListArray) - } +public class ConversationViewModel: NSObject, ConversationRepoDelegate, + NIMConversationManagerDelegate, NIMTeamManagerDelegate, NIMUserManagerDelegate { + public var conversationListArray: [ConversationListModel]? + public var stickTopInfos = [NIMSession: NIMStickTopSessionInfo]() + public weak var delegate: ConversationViewModelDelegate? + private let className = "ConversationViewModel" + let repo = ConversationRepo() + + override public init() { + super.init() + repo.delegate = self + repo.addSessionDelegate(delegate: self) + repo.addTeamDelegate(delegate: self) + stickTopInfos = repo.getStickTopInfos() + NIMSDK.shared().userManager.add(self) + } + + public func fetchServerSessions(option: NIMFetchServerSessionOption, + _ completion: @escaping (NSError?, [ConversationListModel]?) + -> Void) { + weak var weakSelf = self + repo.getSessionList(option: option) { error, conversaitonList in + weakSelf?.conversationListArray = conversaitonList + completion(error, weakSelf?.conversationListArray) } - - public func deleteRecentSession(recentSession:NIMRecentSession){ - repo.deleteLocalSession(recentSession: recentSession) + } + + public func deleteRecentSession(recentSession: NIMRecentSession) { + repo.deleteLocalSession(recentSession: recentSession) + } + + public func stickTopInfoForSession(session: NIMSession) -> NIMStickTopSessionInfo? { + repo.getStickTopSessionInfo(session: session) + } + + public func addStickTopSession(session: NIMSession, + _ completion: @escaping (NSError?, NIMStickTopSessionInfo?) + -> Void) { + let params = NIMAddStickTopSessionParams(session: session) + repo.addStickTop(params: params) { error, stickTopSessionInfo in + completion(error as NSError?, stickTopSessionInfo) } - - public func stickTopInfoForSession(session:NIMSession) -> NIMStickTopSessionInfo?{ - return repo.getStickTopSessionInfo(session: session) + } + + public func removeStickTopSession(params: NIMStickTopSessionInfo, + _ completion: @escaping (NSError?, NIMStickTopSessionInfo?) + -> Void) { + repo.removeStickTop(params: params) { error, stickTopSessionInfo in + completion(error as NSError?, stickTopSessionInfo) } - - public func addStickTopSession(session:NIMSession,_ completion:@escaping (NSError?,NIMStickTopSessionInfo?)->()){ - let params = NIMAddStickTopSessionParams.init(session: session) - repo.addStickTop(params: params) { error, stickTopSessionInfo in - completion(error as NSError?,stickTopSessionInfo) + } + + public func loadStickTopSessionInfos(_ completion: + @escaping (NSError?, [NIMSession: NIMStickTopSessionInfo]?) + -> Void) { + repo.getStickTopSessions(completion) + } + + public func notifyForNewMsg(userId: String?) -> Bool { + repo.notifyForNewMsg(userId: userId) + } + + public func notifyStateForNewMsg(teamId: String?) -> NIMTeamNotifyState { + repo.getNotifyStateForNewMsg(teamId: teamId) + } + + deinit { + NIMSDK.shared().userManager.remove(self) + repo.removeSessionDelegate(delegate: self) + repo.removeTeamDelegate(delegate: self) + } + + // MARK: ======================== private method ============================== + + public func sortRecentSession() { + var tempArr = [NIMRecentSession]() + var dic = [String: ConversationListModel]() + conversationListArray?.forEach { listModel in + if let session = listModel.recentSession { + tempArr.append(session) + if let sessionId = session.session?.sessionId { + dic[sessionId] = listModel } + } } - - public func removeStickTopSession(params:NIMStickTopSessionInfo,_ completion:@escaping (NSError?,NIMStickTopSessionInfo?)->()) { - repo.removeStickTop(params: params) { error, stickTopSessionInfo in - completion(error as NSError?,stickTopSessionInfo) + + let resultArr = repo.sortSessionList(recentSessions: tempArr, stickTopInfo: stickTopInfos) + var sortResultArr = [ConversationListModel]() + resultArr.forEach { recentSession in + let listModel = ConversationListModel() + listModel.recentSession = recentSession + if recentSession.session?.sessionType == .P2P { + if let sessionId = recentSession.session?.sessionId, + let userInfo = dic[sessionId]?.userInfo { + listModel.userInfo = userInfo } - } - - public func loadStickTopSessionInfos(_ completion:@escaping (NSError?,[NIMSession:NIMStickTopSessionInfo]?)->()){ - repo.getStickTopSessions(completion) - } - - public func notifyForNewMsg(userId:String?) -> Bool{ - return repo.notifyForNewMsg(userId: userId) - } - - - public func notifyStateForNewMsg(teamId:String?) -> NIMTeamNotifyState{ - return repo.getNotifyStateForNewMsg(teamId: teamId) - } - - deinit { - NIMSDK.shared().userManager.remove(self) - repo.removeSessionDelegate(delegate: self) - repo.removeTeamDelegate(delegate: self) - } - - //MARK: ======================== private method ============================== - public func sortRecentSession(){ - - var tempArr = [NIMRecentSession]() - var dic = [String:ConversationListModel]() - conversationListArray?.forEach({ listModel in - if let session = listModel.recentSession { - tempArr.append(session) - if let sessionId = session.session?.sessionId { - dic[sessionId] = listModel - } - } - }) - - let resultArr = repo.sortSessionList(recentSessions: tempArr, stickTopInfo: stickTopInfos) - var sortResultArr = [ConversationListModel]() - resultArr.forEach { recentSession in - let listModel = ConversationListModel() - listModel.recentSession = recentSession - if recentSession.session?.sessionType == .P2P { - if let sessionId = recentSession.session?.sessionId,let userInfo = dic[sessionId]?.userInfo { - listModel.userInfo = userInfo - } - - }else if recentSession.session?.sessionType == .team { - - if let sessionId = recentSession.session?.sessionId,let teamInfo = dic[sessionId]?.teamInfo { - listModel.teamInfo = teamInfo - } - } - sortResultArr.append(listModel) + + } else if recentSession.session?.sessionType == .team { + if let sessionId = recentSession.session?.sessionId, + let teamInfo = dic[sessionId]?.teamInfo { + listModel.teamInfo = teamInfo } - conversationListArray = sortResultArr - + } + sortResultArr.append(listModel) } - - //本地排序 在didUpdate的时候如有需要在打开 - func findInsertPlace(recentSession:NIMRecentSession) -> NSInteger{ - var matchIndex = 0 - var find = false - if let conversationArr = conversationListArray{ - for (i, listModel) in conversationArr.enumerated() { - if let enumTime = listModel.recentSession?.lastMessage?.timestamp,let targetTime = recentSession.lastMessage?.timestamp { - if enumTime <= targetTime { - find = true - matchIndex = i - break - } - } - } - } - - if find { - return matchIndex - }else { - return conversationListArray?.count ?? 0 + conversationListArray = sortResultArr + } + + // 本地排序 在didUpdate的时候如有需要在打开 + func findInsertPlace(recentSession: NIMRecentSession) -> NSInteger { + var matchIndex = 0 + var find = false + if let conversationArr = conversationListArray { + for (i, listModel) in conversationArr.enumerated() { + if let enumTime = listModel.recentSession?.lastMessage?.timestamp, + let targetTime = recentSession.lastMessage?.timestamp { + if enumTime <= targetTime { + find = true + matchIndex = i + break + } } - - + } } - - //MARK: ==================== ConversationRepoDelegate ========================== - public func onNotifyAddStickTopSession(_ newInfo: NIMStickTopSessionInfo) { - stickTopInfos[newInfo.session] = newInfo - delegate?.reloadTableView() - + + if find { + return matchIndex + } else { + return conversationListArray?.count ?? 0 } - - public func onNotifyRemoveStickTopSession(_ removedInfo: NIMStickTopSessionInfo) { - stickTopInfos[removedInfo.session] = nil - delegate?.reloadTableView() + } + + // MARK: ==================== ConversationRepoDelegate ========================== + + public func onNotifyAddStickTopSession(_ newInfo: NIMStickTopSessionInfo) { + stickTopInfos[newInfo.session] = newInfo + delegate?.reloadTableView() + } + + public func onNotifyRemoveStickTopSession(_ removedInfo: NIMStickTopSessionInfo) { + stickTopInfos[removedInfo.session] = nil + delegate?.reloadTableView() + } + + public func didServerSessionUpdated(_ recentSession: NIMRecentSession?) {} + + // MARK: ====================NIMConversationManagerDelegate===================== + + public func didAdd(_ recentSession: NIMRecentSession, totalUnreadCount: Int) { + guard let targetId = recentSession.session?.sessionId else { + NELog.errorLog(className, desc: "❌sessionId is nil") + return } - - - public func didServerSessionUpdated(_ recentSession: NIMRecentSession?) { - + weak var weakSelf = self + let listModel = ConversationListModel() + listModel.recentSession = recentSession + if recentSession.session?.sessionType == .P2P { + listModel.userInfo = repo.getUserInfo(userId: targetId) + conversationListArray?.append(listModel) + delegate?.didAddRecentSession() + } else if recentSession.session?.sessionType == .team { + repo.getTeamInfo(teamId: targetId) { error, teamInfo in + listModel.teamInfo = teamInfo + weakSelf?.conversationListArray?.append(listModel) + weakSelf?.delegate?.didAddRecentSession() + } } - - //MARK: ====================NIMConversationManagerDelegate===================== - public func didAdd(_ recentSession: NIMRecentSession, totalUnreadCount: Int) { - - guard let targetId = recentSession.session?.sessionId else { - NELog.errorLog(className, desc: "❌sessionId is nil") - return - } - weak var weakSelf = self - let listModel = ConversationListModel() - listModel.recentSession = recentSession - if recentSession.session?.sessionType == .P2P { - listModel.userInfo = repo.getUserInfo(userId: targetId) - conversationListArray?.append(listModel) - delegate?.didAddRecentSession() - }else if recentSession.session?.sessionType == .team { - repo.getTeamInfo(teamId: targetId, { error, teamInfo in - listModel.teamInfo = teamInfo - weakSelf?.conversationListArray?.append(listModel) - weakSelf?.delegate?.didAddRecentSession() - }) - } + } - } - - public func didUpdate(_ recentSession: NIMRecentSession, totalUnreadCount: Int) { - if let _ = conversationListArray { - for i in 0..String { - var text = "" - switch message.messageType { - case .text: - if let messageText = message.text { - text = messageText - } - break - case .audio: - text = "[语音]" - break - case .image: - text = "[图片]" - break - case .video: - text = "[视频]" - break - case .location: - text = "[位置]" - break - case .notification: - text = "[通知]" - break - case .file: - text = "[文件]" - break - case .tip: - if let messageText = message.text { - text = messageText - } - break - case .rtcCallRecord: - let record = message.messageObject as? NIMRtcCallRecordObject - text = (record?.callType == .audio) ? "[网络通话]":"[视频聊天]" - break - default: - text = "[未知消息]" - } - - return text + /// last message + /// - Parameter message: message + /// - Returns: result + class func messageContent(message: NIMMessage) -> String { + var text = "" + switch message.messageType { + case .text: + if let messageText = message.text { + text = messageText + } + case .audio: + text = "[语音]" + case .image: + text = "[图片]" + case .video: + text = "[视频]" + case .location: + text = "[位置]" + case .notification: + text = "[通知]" + case .file: + text = "[文件]" + case .tip: + if let messageText = message.text { + text = messageText + } + case .rtcCallRecord: + let record = message.messageObject as? NIMRtcCallRecordObject + text = (record?.callType == .audio) ? "[网络通话]" : "[视频聊天]" + default: + text = "[未知消息]" } + + return text + } } - diff --git a/NEQChatUIKit/NEKitQChatUI.podspec b/NEQChatUIKit/NEKitQChatUI.podspec index 7e609281..78f14b2e 100644 --- a/NEQChatUIKit/NEKitQChatUI.podspec +++ b/NEQChatUIKit/NEKitQChatUI.podspec @@ -8,7 +8,7 @@ Pod::Spec.new do |s| s.name = 'NEKitQChatUI' - s.version = '9.2.6-rc01' + s.version = '9.2.7' s.summary = 'Netease XKit' # This description is used to generate tags and improve search results. @@ -24,7 +24,11 @@ TODO: Add long description of the pod here. s.license = { :'type' => 'Copyright', :'text' => ' Copyright 2022 Netease '} s.author = 'yunxin engineering department' s.source = { :git => 'ssh://git@g.hz.netease.com:22222/yunxin-app/xkit-ios.git', :tag => s.version.to_s } - + s.pod_target_xcconfig = { + 'BUILD_LIBRARY_FOR_DISTRIBUTION' => 'YES' + } + s.user_target_xcconfig = { 'BUILD_LIBRARY_FOR_DISTRIBUTION' => 'YES' } + s.ios.deployment_target = '9.0' s.source_files = 'NEKitQChatUI/Classes/**/*' diff --git a/NEQChatUIKit/NEKitQChatUI/Assets/en.lproj/Localizable.strings b/NEQChatUIKit/NEKitQChatUI/Assets/en.lproj/Localizable.strings index eea082fe..3f93e4d3 100644 --- a/NEQChatUIKit/NEKitQChatUI/Assets/en.lproj/Localizable.strings +++ b/NEQChatUIKit/NEKitQChatUI/Assets/en.lproj/Localizable.strings @@ -1,10 +1,8 @@ -/* - YXLogin.strings - Pods - Created by yu chen on 2021/12/24. - -*/ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + //MAKR:common "ok"="ok"; "exceed"="超出"; @@ -163,7 +161,20 @@ "finish"="完成"; "removeMember"="移除成员"; "removeRole"="移除身份组"; - +//MARK:身份组权限设置 +"auth1"="ManageServer"; +"auth2"="管理频道属性"; +"auth3"="管理频道权限"; +"auth4"="发送消息"; +"auth5"="ModifySelfInfo"; +"auth6"="InviteToServer"; +"auth7"="KickOthersInServer"; +"auth8"="ModifyOthersInfoInServer"; +"auth9"="频道中撤回他人消息"; +"auth10"="频道中删除他人消息"; +"auth11"="RemindOther"; +"auth12"="RemindAll"; +"auth13"="管理频道名单"; //MARK:error toast "param_error"="Parameter error"; diff --git a/NEQChatUIKit/NEKitQChatUI/Assets/zh-Hans.lproj/Localizable.strings b/NEQChatUIKit/NEKitQChatUI/Assets/zh-Hans.lproj/Localizable.strings index 49c64347..76f672f2 100644 --- a/NEQChatUIKit/NEKitQChatUI/Assets/zh-Hans.lproj/Localizable.strings +++ b/NEQChatUIKit/NEKitQChatUI/Assets/zh-Hans.lproj/Localizable.strings @@ -1,10 +1,7 @@ -/* - YXLogin.strings - Pods - Created by yu chen on 2021/12/24. - -*/ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. //MAKR:common "ok"="确认"; @@ -118,6 +115,20 @@ "removeMember"="移除成员"; "removeRole"="移除身份组"; +//MARK:身份组权限设置 +"auth1"="ManageServer"; +"auth2"="管理频道属性"; +"auth3"="管理频道权限"; +"auth4"="发送消息"; +"auth5"="ModifySelfInfo"; +"auth6"="InviteToServer"; +"auth7"="KickOthersInServer"; +"auth8"="ModifyOthersInfoInServer"; +"auth9"="频道中撤回他人消息"; +"auth10"="频道中删除他人消息"; +"auth11"="RemindOther"; +"auth12"="RemindAll"; +"auth13"="管理频道名单"; //MARK:error toast "param_error"="Parameter error"; diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatBaseCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatBaseCell.swift index ede9274a..21d370da 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatBaseCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatBaseCell.swift @@ -1,19 +1,17 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class QChatBaseCell: UITableViewCell { - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - self.selectionStyle = .none - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + selectionStyle = .none + } + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatBaseCollectionViewCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatBaseCollectionViewCell.swift index 62a8f790..c64290c5 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatBaseCollectionViewCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatBaseCollectionViewCell.swift @@ -1,9 +1,8 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit -class QChatBaseCollectionViewCell: UICollectionViewCell { - -} +class QChatBaseCollectionViewCell: UICollectionViewCell {} diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatCenterTextCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatCenterTextCell.swift index e107e8aa..7d80e99d 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatCenterTextCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatCenterTextCell.swift @@ -1,41 +1,40 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class QChatCenterTextCell: QChatCornerCell { + public var titleLabel: UILabel = .init() + public var line = UIView() + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) - public var titleLabel: UILabel = UILabel() - public var line = UIView() - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - - self.titleLabel.font = UIFont.systemFont(ofSize: 16) - self.titleLabel.translatesAutoresizingMaskIntoConstraints = false - self.titleLabel.textColor = .ne_redText - self.titleLabel.textAlignment = .center - self.contentView.addSubview(self.titleLabel) - NSLayoutConstraint.activate([ - self.titleLabel.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 36), - self.titleLabel.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -36), - self.titleLabel.topAnchor.constraint(equalTo: self.contentView.topAnchor), - self.titleLabel.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor) - ]) - self.titleLabel.text = "title" - self.line.backgroundColor = .ne_greyLine - self.line.translatesAutoresizingMaskIntoConstraints = false - self.contentView.addSubview(self.line) - NSLayoutConstraint.activate([ - self.line.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 20), - self.line.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -20), - self.line.heightAnchor.constraint(equalToConstant: 1.0), - self.line.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor) - ]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - + titleLabel.font = UIFont.systemFont(ofSize: 16) + titleLabel.translatesAutoresizingMaskIntoConstraints = false + titleLabel.textColor = .ne_redText + titleLabel.textAlignment = .center + contentView.addSubview(titleLabel) + NSLayoutConstraint.activate([ + titleLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 36), + titleLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -36), + titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor), + titleLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + ]) + titleLabel.text = "title" + line.backgroundColor = .ne_greyLine + line.translatesAutoresizingMaskIntoConstraints = false + contentView.addSubview(line) + NSLayoutConstraint.activate([ + line.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20), + line.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), + line.heightAnchor.constraint(equalToConstant: 1.0), + line.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + ]) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatCornerCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatCornerCell.swift index f4f898fa..b9f5dd80 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatCornerCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatCornerCell.swift @@ -1,11 +1,10 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. -//this cell has rounding corner style +// this cell has rounding corner style import UIKit import NEKitCommonUI -class QChatCornerCell: CornerCell { - -} +class QChatCornerCell: CornerCell {} diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatHeaderView.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatHeaderView.swift index c3d7e2bd..2b56daa1 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatHeaderView.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatHeaderView.swift @@ -1,48 +1,48 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit public class QChatHeaderView: UIView { - - public lazy var titleLabel: UILabel = { - let label = UILabel() - label.font = DefaultTextFont(12) - label.textColor = .ne_greyText - label.translatesAutoresizingMaskIntoConstraints = false - return label - }() - - /* - // Only override draw() if you perform custom drawing. - // An empty implementation adversely affects performance during animation. - override func draw(_ rect: CGRect) { - // Drawing code - } - */ - - override init(frame: CGRect) { - super.init(frame: frame) - setupUI() - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - } - - func setupUI(){ - clipsToBounds = false - addSubview(titleLabel) - NSLayoutConstraint.activate([ - titleLabel.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -8), - titleLabel.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 33) - ]) - backgroundColor = .clear - } - - public func setTitle(_ name: String){ - titleLabel.text = name.count > 2 ? String(name[name.index(name.endIndex, offsetBy: -2)...]) : name - } + public lazy var titleLabel: UILabel = { + let label = UILabel() + label.font = DefaultTextFont(12) + label.textColor = .ne_greyText + label.translatesAutoresizingMaskIntoConstraints = false + return label + }() + /* + // Only override draw() if you perform custom drawing. + // An empty implementation adversely affects performance during animation. + override func draw(_ rect: CGRect) { + // Drawing code + } + */ + + override init(frame: CGRect) { + super.init(frame: frame) + setupUI() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + func setupUI() { + clipsToBounds = false + addSubview(titleLabel) + NSLayoutConstraint.activate([ + titleLabel.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -8), + titleLabel.leftAnchor.constraint(equalTo: leftAnchor, constant: 33), + ]) + backgroundColor = .clear + } + + public func setTitle(_ name: String) { + titleLabel.text = name + .count > 2 ? String(name[name.index(name.endIndex, offsetBy: -2)...]) : name + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatImageTextCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatImageTextCell.swift index 2dd6c033..bbd832b0 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatImageTextCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatImageTextCell.swift @@ -1,90 +1,90 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class QChatImageTextCell: QChatStateCell { - var circleView = UIImageView() - public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - //circle view - circleView.translatesAutoresizingMaskIntoConstraints = false - circleView.layer.cornerRadius = 16 - circleView.clipsToBounds = true - circleView.backgroundColor = .ne_defautAvatarColor - self.contentView.addSubview(circleView) - NSLayoutConstraint.activate([ - circleView.widthAnchor.constraint(equalToConstant: 36), - circleView.heightAnchor.constraint(equalToConstant: 36), - circleView.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 40), - circleView.centerYAnchor.constraint(equalTo: self.contentView.centerYAnchor, constant: 0) - ]) + var circleView = UIImageView() + override public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + // circle view + circleView.translatesAutoresizingMaskIntoConstraints = false + circleView.layer.cornerRadius = 16 + circleView.clipsToBounds = true + circleView.backgroundColor = .ne_defautAvatarColor + contentView.addSubview(circleView) + NSLayoutConstraint.activate([ + circleView.widthAnchor.constraint(equalToConstant: 36), + circleView.heightAnchor.constraint(equalToConstant: 36), + circleView.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 40), + circleView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor, constant: 0), + ]) // short name label - self.contentView.addSubview(self.shortNameLabel) - NSLayoutConstraint.activate([ - shortNameLabel.widthAnchor.constraint(equalTo: circleView.widthAnchor), - shortNameLabel.heightAnchor.constraint(equalTo: circleView.heightAnchor), - shortNameLabel.leftAnchor.constraint(equalTo: circleView.leftAnchor), - shortNameLabel.topAnchor.constraint(equalTo: circleView.topAnchor) - ]) + contentView.addSubview(shortNameLabel) + NSLayoutConstraint.activate([ + shortNameLabel.widthAnchor.constraint(equalTo: circleView.widthAnchor), + shortNameLabel.heightAnchor.constraint(equalTo: circleView.heightAnchor), + shortNameLabel.leftAnchor.constraint(equalTo: circleView.leftAnchor), + shortNameLabel.topAnchor.constraint(equalTo: circleView.topAnchor), + ]) // name label - self.contentView.addSubview(self.nameLabel) - NSLayoutConstraint.activate([ - nameLabel.leftAnchor.constraint(equalTo: circleView.rightAnchor, constant: 12), - nameLabel.topAnchor.constraint(equalTo: self.contentView.topAnchor), - nameLabel.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor), - ]) + contentView.addSubview(nameLabel) + NSLayoutConstraint.activate([ + nameLabel.leftAnchor.constraint(equalTo: circleView.rightAnchor, constant: 12), + nameLabel.topAnchor.constraint(equalTo: contentView.topAnchor), + nameLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + ]) // line - let line = UIView() - line.backgroundColor = .ne_greyLine - line.translatesAutoresizingMaskIntoConstraints = false - self.contentView.addSubview(line) - NSLayoutConstraint.activate([ - line.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 20), - line.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -20), - line.heightAnchor.constraint(equalToConstant: 1), - line.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: -1) - ]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - public lazy var avatarImage: UIImageView = { - let avatar = UIImageView() - avatar.translatesAutoresizingMaskIntoConstraints = false - avatar.clipsToBounds = true - avatar.backgroundColor = .ne_defautAvatarColor - return avatar - }() - - public lazy var shortNameLabel: UILabel = { - let name = UILabel() - name.translatesAutoresizingMaskIntoConstraints = false - name.textColor = .white - name.textAlignment = .center - name.font = UIFont.systemFont(ofSize: 14.0) - name.text = "果冻" - return name - }() - - public lazy var nameLabel: UILabel = { - let label = UILabel() - label.textAlignment = .left - label.translatesAutoresizingMaskIntoConstraints = false - label.font = UIFont.systemFont(ofSize: 14.0) - label.textColor = .ne_darkText - return label - }() - - public func setup(accid: String?, nickName: String?) { - let name = nickName?.count ?? 0 > 0 ? nickName : accid - self.nameLabel.text = name - guard let n = name else { return } - self.shortNameLabel.text = n.count > 2 ? String(n[n.index(n.endIndex, offsetBy: -2)...]) : n - self.circleView.backgroundColor = UIColor.colorWithString(string: accid) - } + let line = UIView() + line.backgroundColor = .ne_greyLine + line.translatesAutoresizingMaskIntoConstraints = false + contentView.addSubview(line) + NSLayoutConstraint.activate([ + line.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20), + line.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), + line.heightAnchor.constraint(equalToConstant: 1), + line.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -1), + ]) + } + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + public lazy var avatarImage: UIImageView = { + let avatar = UIImageView() + avatar.translatesAutoresizingMaskIntoConstraints = false + avatar.clipsToBounds = true + avatar.backgroundColor = .ne_defautAvatarColor + return avatar + }() + + public lazy var shortNameLabel: UILabel = { + let name = UILabel() + name.translatesAutoresizingMaskIntoConstraints = false + name.textColor = .white + name.textAlignment = .center + name.font = UIFont.systemFont(ofSize: 14.0) + name.text = "果冻" + return name + }() + + public lazy var nameLabel: UILabel = { + let label = UILabel() + label.textAlignment = .left + label.translatesAutoresizingMaskIntoConstraints = false + label.font = UIFont.systemFont(ofSize: 14.0) + label.textColor = .ne_darkText + return label + }() + + public func setup(accid: String?, nickName: String?) { + let name = nickName?.count ?? 0 > 0 ? nickName : accid + nameLabel.text = name + guard let n = name else { return } + shortNameLabel.text = n.count > 2 ? String(n[n.index(n.endIndex, offsetBy: -2)...]) : n + circleView.backgroundColor = UIColor.colorWithString(string: accid) + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatSectionView.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatSectionView.swift index 19c1cc2d..ad96fcd7 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatSectionView.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatSectionView.swift @@ -1,35 +1,33 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class QChatSectionView: UITableViewHeaderFooterView { - public var titleLable = UILabel() - override init(reuseIdentifier: String?) { - super.init(reuseIdentifier: reuseIdentifier) - self.commonUI() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func commonUI() { - self.contentView.backgroundColor = .ne_lightBackgroundColor - self.titleLable.font = UIFont.systemFont(ofSize: 12) - self.titleLable.textColor = .ne_greyText - self.titleLable.translatesAutoresizingMaskIntoConstraints = false - - self.contentView.addSubview(self.titleLable) - NSLayoutConstraint.activate([ - self.titleLable.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 33), - self.titleLable.topAnchor.constraint(equalTo: self.topAnchor, constant: 8), - self.titleLable.bottomAnchor.constraint(equalTo: self.bottomAnchor), - self.titleLable.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -33) - ]) - - } + public var titleLable = UILabel() + override init(reuseIdentifier: String?) { + super.init(reuseIdentifier: reuseIdentifier) + commonUI() + } + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + func commonUI() { + contentView.backgroundColor = .ne_lightBackgroundColor + titleLable.font = UIFont.systemFont(ofSize: 12) + titleLable.textColor = .ne_greyText + titleLable.translatesAutoresizingMaskIntoConstraints = false + + contentView.addSubview(titleLable) + NSLayoutConstraint.activate([ + titleLable.leftAnchor.constraint(equalTo: leftAnchor, constant: 33), + titleLable.topAnchor.constraint(equalTo: topAnchor, constant: 8), + titleLable.bottomAnchor.constraint(equalTo: bottomAnchor), + titleLable.rightAnchor.constraint(equalTo: rightAnchor, constant: -33), + ]) + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatStateCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatStateCell.swift index cf0d1fa0..f0fdc076 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatStateCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatStateCell.swift @@ -1,63 +1,66 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit enum RightStyle { - case none - case indicate - case delete + case none + case indicate + case delete } class QChatStateCell: QChatCornerCell { - private var style: RightStyle = .none; - public var rightImage = UIImageView() - var rightImageMargin: NSLayoutConstraint? - public var rightStyle: RightStyle { - get { - return style - } - set { - style = newValue; - switch style { - case .none: - rightImage.image = nil - case .indicate: - rightImage.image = UIImage.ne_imageNamed(name: "arrowRight") - case .delete: - rightImage.image = UIImage.ne_imageNamed(name: "delete") - } - } + private var style: RightStyle = .none + public var rightImage = UIImageView() + var rightImageMargin: NSLayoutConstraint? + public var rightStyle: RightStyle { + get { + style } - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - self.rightImage.contentMode = .center - self.rightImage.translatesAutoresizingMaskIntoConstraints = false - self.contentView.addSubview(self.rightImage) - rightImageMargin = rightImage.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -36) - rightImageMargin?.isActive = true - NSLayoutConstraint.activate([ - self.rightImage.widthAnchor.constraint(equalToConstant: 20), - self.rightImage.heightAnchor.constraint(equalToConstant: 20), - self.rightImage.centerYAnchor.constraint(equalTo: self.contentView.centerYAnchor), - ]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code + set { + style = newValue + switch style { + case .none: + rightImage.image = nil + case .indicate: + rightImage.image = UIImage.ne_imageNamed(name: "arrowRight") + case .delete: + rightImage.image = UIImage.ne_imageNamed(name: "delete") + } } + } - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + rightImage.contentMode = .center + rightImage.translatesAutoresizingMaskIntoConstraints = false + contentView.addSubview(rightImage) + rightImageMargin = rightImage.rightAnchor.constraint( + equalTo: contentView.rightAnchor, + constant: -36 + ) + rightImageMargin?.isActive = true + NSLayoutConstraint.activate([ + rightImage.widthAnchor.constraint(equalToConstant: 20), + rightImage.heightAnchor.constraint(equalToConstant: 20), + rightImage.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + ]) + } - // Configure the view for the selected state - } + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + // Configure the view for the selected state + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatTextArrowCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatTextArrowCell.swift index 8ee0e67e..a4dcc855 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatTextArrowCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatTextArrowCell.swift @@ -1,18 +1,17 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class QChatTextArrowCell: QChatTextCell { - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - self.rightStyle = .indicate - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + rightStyle = .indicate + } + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatTextCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatTextCell.swift index 72a50c0a..731a2465 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatTextCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatTextCell.swift @@ -1,63 +1,68 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class QChatTextCell: QChatStateCell { - public var titleLabel: UILabel = UILabel() - public var detailLabel: UILabel = UILabel() - public var line = UIView() - - var titleLeftMargin: NSLayoutConstraint? - - var detailRightMargin: NSLayoutConstraint? - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - - self.titleLabel.font = UIFont.systemFont(ofSize: 16) - self.titleLabel.translatesAutoresizingMaskIntoConstraints = false - self.titleLabel.textColor = .ne_darkText - self.contentView.addSubview(self.titleLabel) - titleLeftMargin = titleLabel.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 36) - titleLeftMargin?.isActive = true - NSLayoutConstraint.activate([ -// self.titleLabel.widthAnchor.constraint(lessThanOrEqualToConstant: 120), - self.titleLabel.topAnchor.constraint(equalTo: self.contentView.topAnchor), - self.titleLabel.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor) - ]) - self.titleLabel.text = "删除" - - self.detailLabel.font = UIFont.systemFont(ofSize: 16) - self.detailLabel.translatesAutoresizingMaskIntoConstraints = false - self.detailLabel.textColor = .ne_lightText - self.contentView.addSubview(self.detailLabel) - - detailRightMargin = detailLabel.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -60) - detailRightMargin?.isActive = true - NSLayoutConstraint.activate([ - self.detailLabel.leftAnchor.constraint(equalTo: self.titleLabel.rightAnchor, constant: 0), - self.detailLabel.widthAnchor.constraint(lessThanOrEqualToConstant: 40), - self.detailLabel.topAnchor.constraint(equalTo: self.contentView.topAnchor), - self.detailLabel.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor) - ]) - self.detailLabel.textAlignment = .right - - self.line.backgroundColor = .ne_greyLine - self.line.translatesAutoresizingMaskIntoConstraints = false - self.contentView.addSubview(self.line) - NSLayoutConstraint.activate([ - self.line.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 20), - self.line.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -20), - self.line.heightAnchor.constraint(equalToConstant: 1.0), - self.line.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor) - ]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - + public var titleLabel: UILabel = .init() + public var detailLabel: UILabel = .init() + public var line = UIView() + var titleLeftMargin: NSLayoutConstraint? + + var detailRightMargin: NSLayoutConstraint? + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + + titleLabel.font = UIFont.systemFont(ofSize: 16) + titleLabel.translatesAutoresizingMaskIntoConstraints = false + titleLabel.textColor = .ne_darkText + contentView.addSubview(titleLabel) + titleLeftMargin = titleLabel.leftAnchor.constraint( + equalTo: contentView.leftAnchor, + constant: 36 + ) + titleLeftMargin?.isActive = true + NSLayoutConstraint.activate([ + // self.titleLabel.widthAnchor.constraint(lessThanOrEqualToConstant: 120), + titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor), + titleLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + ]) + titleLabel.text = "删除" + + detailLabel.font = UIFont.systemFont(ofSize: 16) + detailLabel.translatesAutoresizingMaskIntoConstraints = false + detailLabel.textColor = .ne_lightText + contentView.addSubview(detailLabel) + + detailRightMargin = detailLabel.rightAnchor.constraint( + equalTo: contentView.rightAnchor, + constant: -60 + ) + detailRightMargin?.isActive = true + NSLayoutConstraint.activate([ + detailLabel.leftAnchor.constraint(equalTo: titleLabel.rightAnchor, constant: 0), + detailLabel.widthAnchor.constraint(lessThanOrEqualToConstant: 40), + detailLabel.topAnchor.constraint(equalTo: contentView.topAnchor), + detailLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + ]) + detailLabel.textAlignment = .right + + line.backgroundColor = .ne_greyLine + line.translatesAutoresizingMaskIntoConstraints = false + contentView.addSubview(line) + NSLayoutConstraint.activate([ + line.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20), + line.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), + line.heightAnchor.constraint(equalToConstant: 1.0), + line.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + ]) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatUnfoldCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatUnfoldCell.swift index 0ec471af..39eed2b4 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatUnfoldCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseView/QChatUnfoldCell.swift @@ -1,66 +1,65 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class QChatUnfoldCell: QChatCornerCell { - - lazy var arrowImage: UIImageView = { - let arrow = UIImageView() - arrow.translatesAutoresizingMaskIntoConstraints = false - arrow.image = UIImage.ne_imageNamed(name: "arrowDown") - return arrow - }() - - lazy var contentLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.textColor = .ne_greyText - label.font = DefaultTextFont(14) - return label - }() + lazy var arrowImage: UIImageView = { + let arrow = UIImageView() + arrow.translatesAutoresizingMaskIntoConstraints = false + arrow.image = UIImage.ne_imageNamed(name: "arrowDown") + return arrow + }() - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } + lazy var contentLabel: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.textColor = .ne_greyText + label.font = DefaultTextFont(14) + return label + }() - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } - // Configure the view for the selected state - } - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - setupUI() - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - } - - func setupUI(){ - contentView.addSubview(contentLabel) - NSLayoutConstraint.activate([ - contentLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - contentLabel.centerXAnchor.constraint(equalTo: contentView.centerXAnchor) - ]) - - contentView.addSubview(arrowImage) - NSLayoutConstraint.activate([ - arrowImage.leftAnchor.constraint(equalTo: contentLabel.rightAnchor, constant: 5), - arrowImage.centerYAnchor.constraint(equalTo: contentLabel.centerYAnchor) - ]) - } - - func changeToArrowUp(){ - arrowImage.image = UIImage.ne_imageNamed(name: "arrowUp") - } - - func changeToArrowDown(){ - arrowImage.image = UIImage.ne_imageNamed(name: "arrowDown") - } + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + // Configure the view for the selected state + } + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + setupUI() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + func setupUI() { + contentView.addSubview(contentLabel) + NSLayoutConstraint.activate([ + contentLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + contentLabel.centerXAnchor.constraint(equalTo: contentView.centerXAnchor), + ]) + + contentView.addSubview(arrowImage) + NSLayoutConstraint.activate([ + arrowImage.leftAnchor.constraint(equalTo: contentLabel.rightAnchor, constant: 5), + arrowImage.centerYAnchor.constraint(equalTo: contentLabel.centerYAnchor), + ]) + } + + func changeToArrowUp() { + arrowImage.image = UIImage.ne_imageNamed(name: "arrowUp") + } + + func changeToArrowDown() { + arrowImage.image = UIImage.ne_imageNamed(name: "arrowDown") + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseViewController/QChatBaseViewController.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseViewController/QChatBaseViewController.swift index 0290be27..7eb8fa20 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseViewController/QChatBaseViewController.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseViewController/QChatBaseViewController.swift @@ -1,27 +1,25 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCore class QChatBaseViewController: NEBaseViewController { + override func viewDidLoad() { + super.viewDidLoad() - override func viewDidLoad() { - super.viewDidLoad() + // Do any additional setup after loading the view. + } - // Do any additional setup after loading the view. - } - - - /* - // MARK: - Navigation - - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. - } - */ + /* + // MARK: - Navigation + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseViewController/QChatNavigationController.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseViewController/QChatNavigationController.swift index 625257eb..53418ac4 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseViewController/QChatNavigationController.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseViewController/QChatNavigationController.swift @@ -1,22 +1,22 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit public class QChatNavigationController: UINavigationController { + override public func viewDidLoad() { + super.viewDidLoad() + } - public override func viewDidLoad() { - super.viewDidLoad() - } - - public override func pushViewController(_ viewController: UIViewController, animated: Bool) { - if children.count > 0 { - viewController.hidesBottomBarWhenPushed = true - if children.count > 1 { - viewController.hidesBottomBarWhenPushed = false - } - } - super.pushViewController(viewController, animated: true) + override public func pushViewController(_ viewController: UIViewController, animated: Bool) { + if children.count > 0 { + viewController.hidesBottomBarWhenPushed = true + if children.count > 1 { + viewController.hidesBottomBarWhenPushed = false } + } + super.pushViewController(viewController, animated: true) + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseViewController/QChatTableViewController.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseViewController/QChatTableViewController.swift index abe60ab8..9b736c31 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseViewController/QChatTableViewController.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Base/BaseViewController/QChatTableViewController.swift @@ -1,65 +1,67 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCore -public class QChatTableViewController: NEBaseViewController,UITableViewDelegate, UITableViewDataSource { - - public var tableView: UITableView = UITableView(frame: .zero, style: .grouped) - public var topConstraint: NSLayoutConstraint? - public var bottomConstraint: NSLayoutConstraint? +public class QChatTableViewController: NEBaseViewController, UITableViewDelegate, + UITableViewDataSource { + public var tableView: UITableView = .init(frame: .zero, style: .grouped) + public var topConstraint: NSLayoutConstraint? + public var bottomConstraint: NSLayoutConstraint? - public override func viewDidLoad() { - super.viewDidLoad() - self.tableView.separatorStyle = .none - self.tableView.delegate = self - self.tableView.dataSource = self - self.tableView.translatesAutoresizingMaskIntoConstraints = false - self.view.addSubview(self.tableView) - NSLayoutConstraint.activate([ - self.tableView.leftAnchor.constraint(equalTo: self.view.leftAnchor), - self.tableView.rightAnchor.constraint(equalTo: self.view.rightAnchor), - ]) - - if #available(iOS 11.0, *) { - self.topConstraint = self.tableView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor, constant: 0) - self.bottomConstraint = self.tableView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor) + override public func viewDidLoad() { + super.viewDidLoad() + tableView.separatorStyle = .none + tableView.delegate = self + tableView.dataSource = self + tableView.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(tableView) + NSLayoutConstraint.activate([ + tableView.leftAnchor.constraint(equalTo: view.leftAnchor), + tableView.rightAnchor.constraint(equalTo: view.rightAnchor), + ]) - } else { - // Fallback on earlier versions - self.topConstraint = self.tableView.topAnchor.constraint(equalTo: self.view.topAnchor) - self.bottomConstraint = self.tableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor) + if #available(iOS 11.0, *) { + self.topConstraint = self.tableView.topAnchor.constraint( + equalTo: self.view.safeAreaLayoutGuide.topAnchor, + constant: 0 + ) + self.bottomConstraint = self.tableView.bottomAnchor + .constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor) - } - self.topConstraint?.isActive = true - self.bottomConstraint?.isActive = true - - self.tableView.sectionHeaderHeight = 38 - self.tableView.sectionFooterHeight = 0 - self.tableView.rowHeight = 62 - self.tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.1)) - + } else { + // Fallback on earlier versions + topConstraint = tableView.topAnchor.constraint(equalTo: view.topAnchor) + bottomConstraint = tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor) } - - public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - return tableView.dequeueReusableCell(withIdentifier:"UITableViewCell" , for: indexPath) - } - - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return 0 - } - + topConstraint?.isActive = true + bottomConstraint?.isActive = true - /* - // MARK: - Navigation + tableView.sectionHeaderHeight = 38 + tableView.sectionFooterHeight = 0 + tableView.rowHeight = 62 + tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.1)) + } - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. - } - */ + public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + tableView.dequeueReusableCell(withIdentifier: "UITableViewCell", for: indexPath) + } + + public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + 0 + } + + /* + // MARK: - Navigation + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/Model/QChatRoles.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/Model/QChatRoles.swift index 9e14f993..a8347b3a 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/Model/QChatRoles.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/Model/QChatRoles.swift @@ -1,28 +1,28 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NEKitCoreIM public enum roundedType { - case none - case top - case bottom - case all + case none + case top + case bottom + case all } public struct RoleModel { - public var role: ChannelRole? - public var member: MemberRole? - public var title: String? - public var corner: roundedType? - public var isPlacehold: Bool = false + public var role: ChannelRole? + public var member: MemberRole? + public var title: String? + public var corner: roundedType? + public var isPlacehold: Bool = false } public struct QChatRoles { - public var roles: [RoleModel] = [RoleModel]() - public var timeTag: TimeInterval? - public var pageSize: Int = 5 - + public var roles: [RoleModel] = .init() + public var timeTag: TimeInterval? + public var pageSize: Int = 5 } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/Model/RoleStatusInfoExt.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/Model/RoleStatusInfoExt.swift index efce49a1..a1e45352 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/Model/RoleStatusInfoExt.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/Model/RoleStatusInfoExt.swift @@ -1,15 +1,16 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NEKitCoreIM public struct RoleStatusInfoExt { - public var status: RoleStatusInfo? - public var title: String? - - public init(status: RoleStatusInfo?) { - self.status = status - } + public var status: RoleStatusInfo? + public var title: String? + + public init(status: RoleStatusInfo?) { + self.status = status + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/View/ChannelHeaderView.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/View/ChannelHeaderView.swift index 25b4e64a..c0125df6 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/View/ChannelHeaderView.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/View/ChannelHeaderView.swift @@ -1,65 +1,66 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class ChannelHeaderView: UIView { - var titleLabel = UILabel() - var detailLabel = UILabel() - var settingButton = UIButton() - private var prefixLabel = UILabel() - - override init(frame: CGRect) { - super.init(frame: frame) - prefixLabel.font = .systemFont(ofSize: 16) - prefixLabel.textColor = .ne_lightText - prefixLabel.text = "#" - prefixLabel.translatesAutoresizingMaskIntoConstraints = false - self.addSubview(prefixLabel) - NSLayoutConstraint.activate([ - prefixLabel.topAnchor.constraint(equalTo: self.topAnchor, constant: 20), - prefixLabel.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 20), - prefixLabel.widthAnchor.constraint(equalToConstant: 20), - prefixLabel.heightAnchor.constraint(equalToConstant: 26) - ]) - - titleLabel.font = .systemFont(ofSize: 18) - titleLabel.textColor = .ne_darkText - titleLabel.text = "频道1" - titleLabel.translatesAutoresizingMaskIntoConstraints = false - self.addSubview(titleLabel) - NSLayoutConstraint.activate([ - titleLabel.topAnchor.constraint(equalTo: self.topAnchor, constant: 20), - titleLabel.leftAnchor.constraint(equalTo: prefixLabel.rightAnchor, constant: 0), - titleLabel.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -81), - titleLabel.heightAnchor.constraint(equalToConstant: 26) - ]) - - detailLabel.textColor = .ne_greyText - detailLabel.font = .systemFont(ofSize: 14) - detailLabel.text = "分享心得" - detailLabel.translatesAutoresizingMaskIntoConstraints = false - self.addSubview(detailLabel) - NSLayoutConstraint.activate([ - detailLabel.leftAnchor.constraint(equalTo: prefixLabel.leftAnchor), - detailLabel.topAnchor.constraint(equalTo: prefixLabel.bottomAnchor, constant: 0), - detailLabel.heightAnchor.constraint(equalToConstant: 20), - detailLabel.rightAnchor.constraint(equalTo: titleLabel.rightAnchor) - ]) - - settingButton.setImage(UIImage.ne_imageNamed(name: "Setting"), for: .normal) - settingButton.translatesAutoresizingMaskIntoConstraints = false - self.addSubview(settingButton) - NSLayoutConstraint.activate([ - settingButton.topAnchor.constraint(equalTo: self.topAnchor, constant: 10), - settingButton.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -16), - settingButton.widthAnchor.constraint(equalToConstant: 40), - settingButton.heightAnchor.constraint(equalToConstant: 32) - ]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } + var titleLabel = UILabel() + var detailLabel = UILabel() + var settingButton = UIButton() + private var prefixLabel = UILabel() + + override init(frame: CGRect) { + super.init(frame: frame) + prefixLabel.font = .systemFont(ofSize: 16) + prefixLabel.textColor = .ne_lightText + prefixLabel.text = "#" + prefixLabel.translatesAutoresizingMaskIntoConstraints = false + addSubview(prefixLabel) + NSLayoutConstraint.activate([ + prefixLabel.topAnchor.constraint(equalTo: topAnchor, constant: 20), + prefixLabel.leftAnchor.constraint(equalTo: leftAnchor, constant: 20), + prefixLabel.widthAnchor.constraint(equalToConstant: 20), + prefixLabel.heightAnchor.constraint(equalToConstant: 26), + ]) + + titleLabel.font = .systemFont(ofSize: 18) + titleLabel.textColor = .ne_darkText + titleLabel.text = "频道1" + titleLabel.translatesAutoresizingMaskIntoConstraints = false + addSubview(titleLabel) + NSLayoutConstraint.activate([ + titleLabel.topAnchor.constraint(equalTo: topAnchor, constant: 20), + titleLabel.leftAnchor.constraint(equalTo: prefixLabel.rightAnchor, constant: 0), + titleLabel.rightAnchor.constraint(equalTo: rightAnchor, constant: -81), + titleLabel.heightAnchor.constraint(equalToConstant: 26), + ]) + + detailLabel.textColor = .ne_greyText + detailLabel.font = .systemFont(ofSize: 14) + detailLabel.text = "分享心得" + detailLabel.translatesAutoresizingMaskIntoConstraints = false + addSubview(detailLabel) + NSLayoutConstraint.activate([ + detailLabel.leftAnchor.constraint(equalTo: prefixLabel.leftAnchor), + detailLabel.topAnchor.constraint(equalTo: prefixLabel.bottomAnchor, constant: 0), + detailLabel.heightAnchor.constraint(equalToConstant: 20), + detailLabel.rightAnchor.constraint(equalTo: titleLabel.rightAnchor), + ]) + + settingButton.setImage(UIImage.ne_imageNamed(name: "Setting"), for: .normal) + settingButton.translatesAutoresizingMaskIntoConstraints = false + addSubview(settingButton) + NSLayoutConstraint.activate([ + settingButton.topAnchor.constraint(equalTo: topAnchor, constant: 10), + settingButton.rightAnchor.constraint(equalTo: rightAnchor, constant: -16), + settingButton.widthAnchor.constraint(equalToConstant: 40), + settingButton.heightAnchor.constraint(equalToConstant: 32), + ]) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/View/CornerButton.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/View/CornerButton.swift index 043205d6..7dc01feb 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/View/CornerButton.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/View/CornerButton.swift @@ -1,115 +1,123 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class CornerButton: UIButton { - var cornerLayer = CAShapeLayer() - override var isSelected: Bool { - get { - return super.isSelected - } - set { - cornerLayer.fillColor = newValue ? selectedColor.cgColor : color.cgColor - super.isSelected = newValue - } - + var cornerLayer = CAShapeLayer() + override var isSelected: Bool { + get { + super.isSelected } - override var isUserInteractionEnabled: Bool { - get { - return super.isUserInteractionEnabled - } - set { - super.isUserInteractionEnabled = newValue - self.alpha = newValue ? 1.0 : 0.5 - } + set { + cornerLayer.fillColor = newValue ? selectedColor.cgColor : color.cgColor + super.isSelected = newValue } + } + + override var isUserInteractionEnabled: Bool { + get { + super.isUserInteractionEnabled + } + set { + super.isUserInteractionEnabled = newValue + alpha = newValue ? 1.0 : 0.5 + } + } + // public var ne_selected: Bool { // get { // return self.isSelected // } // set { // if newValue { -//// cornerLayer.fillColor = UIColor.purple.cgColor + //// cornerLayer.fillColor = UIColor.purple.cgColor // }else { -//// cornerLayer.fillColor = color.cgColor + //// cornerLayer.fillColor = color.cgColor // } // self.isSelected = newValue // } // } - - + // public var fillColor: UIColor = .white - public var color: UIColor = .white - public var selectedColor: UIColor = .white - private var type : CornerType = .none - public var edgeInset: UIEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) - public var cornerType: CornerType { - get { return type } - set { - if type != newValue { - type = newValue - sizeToFit() - } - } - } - - override init(frame: CGRect) { - super.init(frame: frame) - self.translatesAutoresizingMaskIntoConstraints = false - self.clipsToBounds = true - cornerLayer.fillColor = color.cgColor - cornerLayer.strokeColor = UIColor.ne_borderColor.cgColor -// self.backgroundColor = .ne_lightBackgroundColor - self.layer.insertSublayer(cornerLayer, below: self.imageView?.layer) - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - } - - override func layoutSublayers(of layer: CALayer) { - super.layoutSublayers(of: layer) - drawRoundedCorner(rect: self.bounds) - - print(#function) + public var color: UIColor = .white + public var selectedColor: UIColor = .white + private var type: CornerType = .none + public var edgeInset: UIEdgeInsets = .init(top: 0, left: 0, bottom: 0, right: 0) + public var cornerType: CornerType { + get { type } + set { + if type != newValue { + type = newValue + sizeToFit() + } } + } + + override init(frame: CGRect) { + super.init(frame: frame) + translatesAutoresizingMaskIntoConstraints = false + clipsToBounds = true + cornerLayer.fillColor = color.cgColor + cornerLayer.strokeColor = UIColor.ne_borderColor.cgColor +// self.backgroundColor = .ne_lightBackgroundColor + layer.insertSublayer(cornerLayer, below: imageView?.layer) + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + override func layoutSublayers(of layer: CALayer) { + super.layoutSublayers(of: layer) + drawRoundedCorner(rect: bounds) + + print(#function) + } + // public override func draw(_ rect: CGRect) { // drawRoundedCorner(rect: rect) // } - - public func drawRoundedCorner(rect: CGRect) { - var path: UIBezierPath = UIBezierPath() - let roundRect = CGRect(x: rect.origin.x + edgeInset.left, y: rect.origin.y + edgeInset.top, width: rect.width - (edgeInset.left + edgeInset.right), height: rect.height - (edgeInset.top + edgeInset.bottom)) - if type == .none { - path = UIBezierPath(rect: roundRect) - } - var corners = UIRectCorner() - if type.contains(CornerType.topLeft) { - corners = corners.union(.topLeft) - } - if type.contains(CornerType.topRight) { - corners = corners.union(.topRight) - } - if type.contains(CornerType.bottomLeft) { - corners = corners.union(.bottomLeft) - } - if type.contains(CornerType.bottomRight) { - corners = corners.union(.bottomRight) - } - - path = UIBezierPath(roundedRect:roundRect, byRoundingCorners: corners, cornerRadii: CGSize(width: 10, height: 10)) - cornerLayer.path = path.cgPath + + public func drawRoundedCorner(rect: CGRect) { + var path = UIBezierPath() + let roundRect = CGRect( + x: rect.origin.x + edgeInset.left, + y: rect.origin.y + edgeInset.top, + width: rect.width - (edgeInset.left + edgeInset.right), + height: rect.height - (edgeInset.top + edgeInset.bottom) + ) + if type == .none { + path = UIBezierPath(rect: roundRect) + } + var corners = UIRectCorner() + if type.contains(CornerType.topLeft) { + corners = corners.union(.topLeft) + } + if type.contains(CornerType.topRight) { + corners = corners.union(.topRight) + } + if type.contains(CornerType.bottomLeft) { + corners = corners.union(.bottomLeft) + } + if type.contains(CornerType.bottomRight) { + corners = corners.union(.bottomRight) + } + + path = UIBezierPath( + roundedRect: roundRect, + byRoundingCorners: corners, + cornerRadii: CGSize(width: 10, height: 10) + ) + cornerLayer.path = path.cgPath // cornerLayer.fillColor = self.isSelected ? selectedColor.cgColor : color.cgColor // cornerLayer.strokeColor = UIColor.ne_borderColor.cgColor - } - + } + // @objc // private func didSelect(sender: AnyObject) { // self.isSelected = !self.isSelected // } - - - } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/View/QChatImageTextOnlineCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/View/QChatImageTextOnlineCell.swift index 362de549..2b53f906 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/View/QChatImageTextOnlineCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/View/QChatImageTextOnlineCell.swift @@ -1,41 +1,41 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class QChatImageTextOnlineCell: QChatImageTextCell { - var online:Bool { - get { - return onlineView.isHidden - } - set { - onlineView.isHidden = !newValue - self.alpha = newValue ? 1.0 : 0.5 - } - + var online: Bool { + get { + onlineView.isHidden } - private var onlineView = UIView() - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - onlineView.backgroundColor = .ne_greenColor - onlineView.layer.borderColor = UIColor.white.cgColor - onlineView.layer.borderWidth = 2 - onlineView.clipsToBounds = true - onlineView.layer.cornerRadius = 6 - onlineView.translatesAutoresizingMaskIntoConstraints = false - self.contentView.addSubview(onlineView) - NSLayoutConstraint.activate([ - onlineView.centerXAnchor.constraint(equalTo: circleView.centerXAnchor, constant: 16), - onlineView.centerYAnchor.constraint(equalTo: circleView.centerYAnchor, constant: 16), - onlineView.widthAnchor.constraint(equalToConstant: 12), - onlineView.heightAnchor.constraint(equalToConstant: 12) - ]) + set { + onlineView.isHidden = !newValue + alpha = newValue ? 1.0 : 0.5 } - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - + } + + private var onlineView = UIView() + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + onlineView.backgroundColor = .ne_greenColor + onlineView.layer.borderColor = UIColor.white.cgColor + onlineView.layer.borderWidth = 2 + onlineView.clipsToBounds = true + onlineView.layer.cornerRadius = 6 + onlineView.translatesAutoresizingMaskIntoConstraints = false + contentView.addSubview(onlineView) + NSLayoutConstraint.activate([ + onlineView.centerXAnchor.constraint(equalTo: circleView.centerXAnchor, constant: 16), + onlineView.centerYAnchor.constraint(equalTo: circleView.centerYAnchor, constant: 16), + onlineView.widthAnchor.constraint(equalToConstant: 12), + onlineView.heightAnchor.constraint(equalToConstant: 12), + ]) + } + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/View/QChatMemberInfoView.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/View/QChatMemberInfoView.swift index 7db14fe0..bc76c60f 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/View/QChatMemberInfoView.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/View/QChatMemberInfoView.swift @@ -1,24 +1,25 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit protocol QChatMemberInfoViewDelegate: AnyObject { - func didClickUserHeader(_ accid: String?) + func didClickUserHeader(_ accid: String?) } class QChatMemberInfoView: UIView { - var contentView: UIView = UIView() - public var avatar = UIImageView() - public var shortName = UILabel() - public var name = UILabel() - public var groupView = UIView() + var contentView: UIView = .init() + public var avatar = UIImageView() + public var shortName = UILabel() + public var name = UILabel() + public var groupView = UIView() // private var onlineView = UIView() - private var originY: CGFloat = 0 - private var originMaxY: CGFloat = 0 - private var topConstaint: NSLayoutConstraint = NSLayoutConstraint() + private var originY: CGFloat = 0 + private var originMaxY: CGFloat = 0 + private var topConstaint: NSLayoutConstraint = .init() // var online:Bool { // get { // return onlineView.backgroundColor == .ne_greenColor @@ -27,101 +28,101 @@ class QChatMemberInfoView: UIView { // onlineView.backgroundColor = newValue ? .ne_greenColor : .ne_greyText // } // } - - public var labelsWidth:CGFloat = 0 - public var maxWidth:CGFloat = kScreenWidth-2*kScreenInterval - public var labelMargin:CGFloat = 6 - public var labelHeight:CGFloat = 25 - public var isFirstRow = true - public weak var delegate: QChatMemberInfoViewDelegate? - - public var accid: String? - - init(inView: UIView) { - super.init(frame: inView.bounds) - self.translatesAutoresizingMaskIntoConstraints = false - self.backgroundColor = UIColor(white: 0, alpha: 0.4) - inView.addSubview(self) - NSLayoutConstraint.activate([ - self.topAnchor.constraint(equalTo: inView.topAnchor), - self.leftAnchor.constraint(equalTo: inView.leftAnchor), - self.rightAnchor.constraint(equalTo: inView.rightAnchor), - self.bottomAnchor.constraint(equalTo: inView.bottomAnchor), - ]) - commonUI() - addPanGesture() - originMaxY = inView.frame.size.height - 360 - } - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func commonUI() { - self.addSubview(contentView) - contentView.translatesAutoresizingMaskIntoConstraints = false - topConstaint = contentView.topAnchor.constraint(equalTo: self.bottomAnchor, constant: 0) + public var labelsWidth: CGFloat = 0 + public var maxWidth: CGFloat = kScreenWidth - 2 * kScreenInterval + public var labelMargin: CGFloat = 6 + public var labelHeight: CGFloat = 25 + public var isFirstRow = true + public weak var delegate: QChatMemberInfoViewDelegate? + + public var accid: String? + + init(inView: UIView) { + super.init(frame: inView.bounds) + translatesAutoresizingMaskIntoConstraints = false + backgroundColor = UIColor(white: 0, alpha: 0.4) + inView.addSubview(self) + NSLayoutConstraint.activate([ + topAnchor.constraint(equalTo: inView.topAnchor), + leftAnchor.constraint(equalTo: inView.leftAnchor), + rightAnchor.constraint(equalTo: inView.rightAnchor), + bottomAnchor.constraint(equalTo: inView.bottomAnchor), + ]) + commonUI() + addPanGesture() + originMaxY = inView.frame.size.height - 360 + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func commonUI() { + addSubview(contentView) + contentView.translatesAutoresizingMaskIntoConstraints = false + topConstaint = contentView.topAnchor.constraint(equalTo: bottomAnchor, constant: 0) // topConstaint = contentView.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 360) - NSLayoutConstraint.activate([ - topConstaint, - contentView.leftAnchor.constraint(equalTo: self.leftAnchor), - contentView.rightAnchor.constraint(equalTo: self.rightAnchor), - contentView.heightAnchor.constraint(equalToConstant: 360) - ]) - - let indicatorView = UIView() - indicatorView.translatesAutoresizingMaskIntoConstraints = false - indicatorView.backgroundColor = .white - indicatorView.layer.cornerRadius = 4 - contentView.addSubview(indicatorView) - NSLayoutConstraint.activate([ - indicatorView.topAnchor.constraint(equalTo: contentView.topAnchor), - indicatorView.centerXAnchor.constraint(equalTo: contentView.centerXAnchor), - indicatorView.widthAnchor.constraint(equalToConstant: 41), - indicatorView.heightAnchor.constraint(equalToConstant: 4) - ]) + NSLayoutConstraint.activate([ + topConstaint, + contentView.leftAnchor.constraint(equalTo: leftAnchor), + contentView.rightAnchor.constraint(equalTo: rightAnchor), + contentView.heightAnchor.constraint(equalToConstant: 360), + ]) - let imageView = UIImageView(image: UIImage.ne_imageNamed(name: "bgImage")) - imageView.translatesAutoresizingMaskIntoConstraints = false - imageView.layer.cornerRadius = 10 - imageView.clipsToBounds = true - contentView.addSubview(imageView) - NSLayoutConstraint.activate([ - imageView.topAnchor.constraint(equalTo: indicatorView.bottomAnchor, constant: 5), - imageView.leftAnchor.constraint(equalTo: contentView.leftAnchor), - imageView.rightAnchor.constraint(equalTo: contentView.rightAnchor), - imageView.heightAnchor.constraint(equalToConstant: 70) - ]) - let whiteBgView = UIView() - whiteBgView.backgroundColor = .white - whiteBgView.translatesAutoresizingMaskIntoConstraints = false - contentView.addSubview(whiteBgView) - NSLayoutConstraint.activate([ - whiteBgView.topAnchor.constraint(equalTo: imageView.bottomAnchor, constant: -5), - whiteBgView.leftAnchor.constraint(equalTo: contentView.leftAnchor), - whiteBgView.rightAnchor.constraint(equalTo: contentView.rightAnchor), - whiteBgView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor) - ]) + let indicatorView = UIView() + indicatorView.translatesAutoresizingMaskIntoConstraints = false + indicatorView.backgroundColor = .white + indicatorView.layer.cornerRadius = 4 + contentView.addSubview(indicatorView) + NSLayoutConstraint.activate([ + indicatorView.topAnchor.constraint(equalTo: contentView.topAnchor), + indicatorView.centerXAnchor.constraint(equalTo: contentView.centerXAnchor), + indicatorView.widthAnchor.constraint(equalToConstant: 41), + indicatorView.heightAnchor.constraint(equalToConstant: 4), + ]) - avatar.translatesAutoresizingMaskIntoConstraints = false - avatar.backgroundColor = .ne_defautAvatarColor - avatar.layer.borderWidth = 2 - avatar.layer.borderColor = UIColor.white.cgColor - avatar.layer.cornerRadius = 30 - avatar.clipsToBounds = true - contentView.addSubview(avatar) - NSLayoutConstraint.activate([ - avatar.topAnchor.constraint(equalTo: indicatorView.bottomAnchor, constant: 50), - avatar.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20), - avatar.heightAnchor.constraint(equalToConstant: 60), - avatar.widthAnchor.constraint(equalToConstant: 60) - ]) - avatar.isUserInteractionEnabled = true - let tap = UITapGestureRecognizer() - tap.numberOfTapsRequired = 1 - tap.numberOfTouchesRequired = 1 - avatar.addGestureRecognizer(tap) - tap.addTarget(self, action: #selector(headerClick)) + let imageView = UIImageView(image: UIImage.ne_imageNamed(name: "bgImage")) + imageView.translatesAutoresizingMaskIntoConstraints = false + imageView.layer.cornerRadius = 10 + imageView.clipsToBounds = true + contentView.addSubview(imageView) + NSLayoutConstraint.activate([ + imageView.topAnchor.constraint(equalTo: indicatorView.bottomAnchor, constant: 5), + imageView.leftAnchor.constraint(equalTo: contentView.leftAnchor), + imageView.rightAnchor.constraint(equalTo: contentView.rightAnchor), + imageView.heightAnchor.constraint(equalToConstant: 70), + ]) + let whiteBgView = UIView() + whiteBgView.backgroundColor = .white + whiteBgView.translatesAutoresizingMaskIntoConstraints = false + contentView.addSubview(whiteBgView) + NSLayoutConstraint.activate([ + whiteBgView.topAnchor.constraint(equalTo: imageView.bottomAnchor, constant: -5), + whiteBgView.leftAnchor.constraint(equalTo: contentView.leftAnchor), + whiteBgView.rightAnchor.constraint(equalTo: contentView.rightAnchor), + whiteBgView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + ]) + + avatar.translatesAutoresizingMaskIntoConstraints = false + avatar.backgroundColor = .ne_defautAvatarColor + avatar.layer.borderWidth = 2 + avatar.layer.borderColor = UIColor.white.cgColor + avatar.layer.cornerRadius = 30 + avatar.clipsToBounds = true + contentView.addSubview(avatar) + NSLayoutConstraint.activate([ + avatar.topAnchor.constraint(equalTo: indicatorView.bottomAnchor, constant: 50), + avatar.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20), + avatar.heightAnchor.constraint(equalToConstant: 60), + avatar.widthAnchor.constraint(equalToConstant: 60), + ]) + avatar.isUserInteractionEnabled = true + let tap = UITapGestureRecognizer() + tap.numberOfTapsRequired = 1 + tap.numberOfTouchesRequired = 1 + avatar.addGestureRecognizer(tap) + tap.addTarget(self, action: #selector(headerClick)) // onlineView.translatesAutoresizingMaskIntoConstraints = false // onlineView.backgroundColor = .ne_greenColor @@ -137,175 +138,182 @@ class QChatMemberInfoView: UIView { // onlineView.widthAnchor.constraint(equalToConstant: 14) // ]) - shortName.translatesAutoresizingMaskIntoConstraints = false - shortName.font = .systemFont(ofSize: 22) - shortName.textColor = .white - shortName.textAlignment = .center - contentView.addSubview(shortName) - NSLayoutConstraint.activate([ - shortName.topAnchor.constraint(equalTo: avatar.topAnchor), - shortName.leftAnchor.constraint(equalTo: avatar.leftAnchor), - shortName.rightAnchor.constraint(equalTo: avatar.rightAnchor), - shortName.bottomAnchor.constraint(equalTo: avatar.bottomAnchor) - ]) + shortName.translatesAutoresizingMaskIntoConstraints = false + shortName.font = .systemFont(ofSize: 22) + shortName.textColor = .white + shortName.textAlignment = .center + contentView.addSubview(shortName) + NSLayoutConstraint.activate([ + shortName.topAnchor.constraint(equalTo: avatar.topAnchor), + shortName.leftAnchor.constraint(equalTo: avatar.leftAnchor), + shortName.rightAnchor.constraint(equalTo: avatar.rightAnchor), + shortName.bottomAnchor.constraint(equalTo: avatar.bottomAnchor), + ]) - name.translatesAutoresizingMaskIntoConstraints = false - name.font = .boldSystemFont(ofSize: 24) - name.textColor = .ne_darkText - contentView.addSubview(name) - NSLayoutConstraint.activate([ - name.topAnchor.constraint(equalTo: avatar.bottomAnchor,constant: 14), - name.leftAnchor.constraint(equalTo: avatar.leftAnchor), - name.rightAnchor.constraint(equalTo: contentView.rightAnchor,constant: -20), - name.heightAnchor.constraint(equalToConstant: 30) - ]) + name.translatesAutoresizingMaskIntoConstraints = false + name.font = .boldSystemFont(ofSize: 24) + name.textColor = .ne_darkText + contentView.addSubview(name) + NSLayoutConstraint.activate([ + name.topAnchor.constraint(equalTo: avatar.bottomAnchor, constant: 14), + name.leftAnchor.constraint(equalTo: avatar.leftAnchor), + name.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), + name.heightAnchor.constraint(equalToConstant: 30), + ]) - let groupName = UILabel() - groupName.translatesAutoresizingMaskIntoConstraints = false - groupName.font = .systemFont(ofSize: 14) - groupName.text = localizable("qchat_id_group") - groupName.textColor = .ne_darkText - contentView.addSubview(groupName) - NSLayoutConstraint.activate([ - groupName.topAnchor.constraint(equalTo: name.bottomAnchor,constant: 30), - groupName.leftAnchor.constraint(equalTo: name.leftAnchor), - groupName.rightAnchor.constraint(equalTo: contentView.rightAnchor,constant: -20), - groupName.heightAnchor.constraint(equalToConstant: 20) - ]) + let groupName = UILabel() + groupName.translatesAutoresizingMaskIntoConstraints = false + groupName.font = .systemFont(ofSize: 14) + groupName.text = localizable("qchat_id_group") + groupName.textColor = .ne_darkText + contentView.addSubview(groupName) + NSLayoutConstraint.activate([ + groupName.topAnchor.constraint(equalTo: name.bottomAnchor, constant: 30), + groupName.leftAnchor.constraint(equalTo: name.leftAnchor), + groupName.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), + groupName.heightAnchor.constraint(equalToConstant: 20), + ]) - let line = UIView() - line.translatesAutoresizingMaskIntoConstraints = false - line.backgroundColor = .ne_greyLine - contentView.addSubview(line) + let line = UIView() + line.translatesAutoresizingMaskIntoConstraints = false + line.backgroundColor = .ne_greyLine + contentView.addSubview(line) + NSLayoutConstraint.activate([ + line.topAnchor.constraint(equalTo: groupName.bottomAnchor, constant: 8), + line.leftAnchor.constraint(equalTo: name.leftAnchor), + line.rightAnchor.constraint(equalTo: name.rightAnchor), + line.heightAnchor.constraint(equalToConstant: 1), + ]) + + groupView.translatesAutoresizingMaskIntoConstraints = false + groupView.backgroundColor = .white + contentView.addSubview(groupView) + NSLayoutConstraint.activate([ + groupView.topAnchor.constraint(equalTo: line.bottomAnchor, constant: 2), + groupView.leftAnchor.constraint(equalTo: name.leftAnchor), + groupView.rightAnchor.constraint(equalTo: name.rightAnchor), + groupView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + ]) + } + + public func setupRoles(dataArray: [String]) { + for i in 0 ..< dataArray.count { + let label = IDGroupLable(content: dataArray[i]) + label.textInsets = UIEdgeInsets(top: 4, left: 8, bottom: 4, right: 8) + label.translatesAutoresizingMaskIntoConstraints = false + groupView.addSubview(label) + let labelSize = label.sizeThatFits(CGSize(width: maxWidth, height: labelHeight)) + + // 剩余宽度是否满足,下一个lable的宽度,如不满足则换行 + if (maxWidth - labelsWidth) >= labelSize.width, isFirstRow { NSLayoutConstraint.activate([ - line.topAnchor.constraint(equalTo: groupName.bottomAnchor,constant: 8), - line.leftAnchor.constraint(equalTo: name.leftAnchor), - line.rightAnchor.constraint(equalTo: name.rightAnchor), - line.heightAnchor.constraint(equalToConstant: 1) + i == 0 ? label.leftAnchor.constraint( + equalTo: groupView.leftAnchor, + constant: kScreenInterval + ) : label.leftAnchor.constraint( + equalTo: groupView.leftAnchor, + constant: kScreenInterval + labelsWidth + ), + label.topAnchor.constraint(equalTo: groupView.topAnchor, constant: 8), + label.widthAnchor.constraint(equalToConstant: labelSize.width), + label.heightAnchor.constraint(equalToConstant: labelSize.height), ]) - - groupView.translatesAutoresizingMaskIntoConstraints = false - groupView.backgroundColor = .white - contentView.addSubview(groupView) + } else { + // 换行重置,labels总宽度 + if isFirstRow { + labelsWidth = kScreenInterval + } + isFirstRow = false NSLayoutConstraint.activate([ - groupView.topAnchor.constraint(equalTo: line.bottomAnchor,constant: 2), - groupView.leftAnchor.constraint(equalTo: name.leftAnchor), - groupView.rightAnchor.constraint(equalTo: name.rightAnchor), - groupView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor) + label.leftAnchor.constraint( + equalTo: groupView.leftAnchor, + constant: labelsWidth + ), + label.topAnchor.constraint( + equalTo: groupView.topAnchor, + constant: 8 + labelHeight + labelMargin + ), + label.widthAnchor.constraint(equalToConstant: labelSize.width), + label.heightAnchor.constraint(equalToConstant: labelSize.height), ]) - - - } - - - public func setupRoles(dataArray: [String]) { - for i in (0 ..< dataArray.count) { - let label = IDGroupLable(content: dataArray[i]) - label.textInsets = UIEdgeInsets(top: 4, left: 8, bottom: 4, right: 8) - label.translatesAutoresizingMaskIntoConstraints = false - groupView.addSubview(label) - let labelSize = label.sizeThatFits(CGSize.init(width: maxWidth, height: labelHeight)) - - //剩余宽度是否满足,下一个lable的宽度,如不满足则换行 - if (maxWidth-labelsWidth) >= labelSize.width && isFirstRow{ - NSLayoutConstraint.activate([ - i == 0 ? label.leftAnchor.constraint(equalTo: groupView.leftAnchor,constant: kScreenInterval) : label.leftAnchor.constraint(equalTo: groupView.leftAnchor,constant: kScreenInterval+labelsWidth), - label.topAnchor.constraint(equalTo: groupView.topAnchor,constant: 8), - label.widthAnchor.constraint(equalToConstant: labelSize.width), - label.heightAnchor.constraint(equalToConstant:labelSize.height), - ]) - }else { - - //换行重置,labels总宽度 - if isFirstRow { - labelsWidth = kScreenInterval - } - isFirstRow = false - NSLayoutConstraint.activate([ - label.leftAnchor.constraint(equalTo: groupView.leftAnchor,constant: labelsWidth), - label.topAnchor.constraint(equalTo: groupView.topAnchor,constant: 8+labelHeight+labelMargin), - label.widthAnchor.constraint(equalToConstant: labelSize.width), - label.heightAnchor.constraint(equalToConstant:labelSize.height) - ]) - } - + } + // if i == dataArray.count - 1 { // NSLayoutConstraint.activate([ // label.bottomAnchor.constraint(equalTo: groupView.bottomAnchor) // ]) // } - labelsWidth+=(labelSize.width + labelMargin) - } - } - - func addPanGesture() { - self.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(pan))) - self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tap))) + labelsWidth += (labelSize.width + labelMargin) } - - @objc func tap(pan:UIPanGestureRecognizer) { + } + + func addPanGesture() { + addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(pan))) + addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tap))) + } + + @objc func tap(pan: UIPanGestureRecognizer) { + dismiss() + } + + @objc func pan(pan: UIPanGestureRecognizer) { + let position = pan.translation(in: superview) + let velocity = pan.velocity(in: superview) + print("velocity:\(velocity) position:\(position)") + switch pan.state { + case .began: + print("start pan") + originY = contentView.frame.origin.y + + case .changed: + if (originY + position.y) > originMaxY { + contentView.frame.origin.y = originY + position.y + } + + case .ended: + print("ended pan") + if velocity.y > 600 || contentView.frame.origin.y > originMaxY + 160 { dismiss() + } + + default: + print("default pan") } - - @objc func pan(pan:UIPanGestureRecognizer) { - let position = pan.translation(in: self.superview) - let velocity = pan.velocity(in: self.superview) - print("velocity:\(velocity) position:\(position)") - switch pan.state { - case .began: - print("start pan") - originY = self.contentView.frame.origin.y - - case .changed: - if (originY + position.y) > originMaxY { - self.contentView.frame.origin.y = originY + position.y - } - - case .ended: - print("ended pan") - if velocity.y > 600 || self.contentView.frame.origin.y > originMaxY + 160 { - dismiss() - } - - default: - print("default pan") - } - } - - func present() { - DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { - self.topConstaint.constant = -360 - UIView.animate(withDuration: 0.3) { - self.layoutIfNeeded() - } completion: { result in - - } - } - } - - func dismiss() { - if (self.superview == nil) { - return - } - topConstaint.constant = 0 - UIView.animate(withDuration: 0.3) { - self.layoutIfNeeded() - } completion: { result in - self.removeFromSuperview() - } + } + + func present() { + DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { + self.topConstaint.constant = -360 + UIView.animate(withDuration: 0.3) { + self.layoutIfNeeded() + } completion: { result in + } } - - public func setup(accid: String?, nickName: String?) { - let name = nickName?.count ?? 0 > 0 ? nickName : accid - self.name.text = name - self.accid = accid - guard let n = name else { return } - self.shortName.text = n.count > 2 ? String(n[n.index(n.endIndex, offsetBy: -2)...]) : n - self.avatar.backgroundColor = UIColor.colorWithString(string: accid) + } + + func dismiss() { + if superview == nil { + return } - - @objc func headerClick(){ - delegate?.didClickUserHeader(accid) - self.removeFromSuperview() + topConstaint.constant = 0 + UIView.animate(withDuration: 0.3) { + self.layoutIfNeeded() + } completion: { result in + self.removeFromSuperview() } + } + + public func setup(accid: String?, nickName: String?) { + let name = nickName?.count ?? 0 > 0 ? nickName : accid + self.name.text = name + self.accid = accid + guard let n = name else { return } + shortName.text = n.count > 2 ? String(n[n.index(n.endIndex, offsetBy: -2)...]) : n + avatar.backgroundColor = UIColor.colorWithString(string: accid) + } + + @objc func headerClick() { + delegate?.didClickUserHeader(accid) + removeFromSuperview() + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/View/QChatPermissionSettingCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/View/QChatPermissionSettingCell.swift index 611cf413..976fb3f5 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/View/QChatPermissionSettingCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/View/QChatPermissionSettingCell.swift @@ -1,148 +1,148 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCoreIM protocol QChatPermissionSettingCellDelegate: AnyObject { - func didSelected(cell: QChatPermissionSettingCell?, model:RoleStatusInfo?) + func didSelected(cell: QChatPermissionSettingCell?, model: RoleStatusInfo?) } class QChatPermissionSettingCell: QChatCornerCell { - - public weak var delegate: QChatPermissionSettingCellDelegate? - private var model:RoleStatusInfoExt? - private var button: UIButton? - private var titleLabel = UILabel() - private var enable: Bool { - get { - return ((buttons.first?.isUserInteractionEnabled) != nil) - } - set { - for button in buttons { - button.isUserInteractionEnabled = newValue - } - } + public weak var delegate: QChatPermissionSettingCellDelegate? + private var model: RoleStatusInfoExt? + private var button: UIButton? + private var titleLabel = UILabel() + private var enable: Bool { + get { + (buttons.first?.isUserInteractionEnabled) != nil } - private var index: Int { - get { - return selectedIndex - } - set { - selectedIndex = newValue - self.button = buttons[selectedIndex] - self.button?.isSelected = true - } + set { + for button in buttons { + button.isUserInteractionEnabled = newValue + } } - - private var selectedIndex = -1; - private var buttons = [CornerButton]() - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - self.titleLabel.font = UIFont.systemFont(ofSize: 16) - self.titleLabel.translatesAutoresizingMaskIntoConstraints = false - self.titleLabel.textColor = .ne_darkText - self.titleLabel.text = "删除" - self.contentView.addSubview(self.titleLabel) - NSLayoutConstraint.activate([ - self.titleLabel.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 35), - self.titleLabel.topAnchor.constraint(equalTo: self.contentView.topAnchor), - self.titleLabel.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor) - ]) - - let denyButton = CornerButton(frame: .zero) - denyButton.color = .white - denyButton.selectedColor = UIColor.red - denyButton.tag = 0 + 10 - denyButton.setImage(UIImage.ne_imageNamed(name: "deny"), for: .normal) - denyButton.setImage(UIImage.ne_imageNamed(name: "denySelected"), for: .selected) - denyButton.addTarget(self, action: #selector(buttonEvent), for: .touchUpInside) - denyButton.cornerType = CornerType.topLeft.union(CornerType.bottomLeft) - buttons.append(denyButton) - - let midButton = CornerButton(frame: .zero) - midButton.tag = 1 + 10 - midButton.color = .white - midButton.selectedColor = UIColor.ne_borderColor - midButton.setImage(UIImage.ne_imageNamed(name: "extend"), for: .normal) - midButton.setImage(UIImage.ne_imageNamed(name: "extendSelected"), for: .selected) - midButton.addTarget(self, action: #selector(buttonEvent), for: .touchUpInside) - buttons.append(midButton) - - let allowButton = CornerButton(frame: .zero) - allowButton.tag = 2 + 10 - allowButton.color = .white - allowButton.selectedColor = UIColor.ne_greenColor - allowButton.setImage(UIImage.ne_imageNamed(name: "allow"), for: .normal) - allowButton.setImage(UIImage.ne_imageNamed(name: "allowSeleted"), for: .selected) - allowButton.cornerType = CornerType.topRight.union(CornerType.bottomRight) - allowButton.addTarget(self, action: #selector(buttonEvent), for: .touchUpInside) - buttons.append(allowButton) - - self.contentView.addSubview(allowButton) - NSLayoutConstraint.activate([ - allowButton.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -35), - allowButton.widthAnchor.constraint(equalToConstant: 32), - allowButton.heightAnchor.constraint(equalToConstant: 26), - allowButton.centerYAnchor.constraint(equalTo: self.contentView.centerYAnchor) - ]) - - self.contentView.addSubview(midButton) - NSLayoutConstraint.activate([ - midButton.rightAnchor.constraint(equalTo: allowButton.leftAnchor, constant: 0), - midButton.widthAnchor.constraint(equalToConstant: 32), - midButton.heightAnchor.constraint(equalToConstant: 26), - midButton.centerYAnchor.constraint(equalTo: self.contentView.centerYAnchor) - ]) - - self.contentView.addSubview(denyButton) - NSLayoutConstraint.activate([ - denyButton.rightAnchor.constraint(equalTo: midButton.leftAnchor, constant: 0), - denyButton.widthAnchor.constraint(equalToConstant: 32), - denyButton.heightAnchor.constraint(equalToConstant: 26), - denyButton.centerYAnchor.constraint(equalTo: self.contentView.centerYAnchor), - denyButton.leftAnchor.constraint(equalTo: self.titleLabel.rightAnchor) - ]) + } + + private var index: Int { + get { + selectedIndex } - - public func updateModel(model:RoleStatusInfoExt?) { - self.model = model - self.titleLabel.text = model?.title - self.index = (model?.status?.status.rawValue ?? 0) + 1 + set { + selectedIndex = newValue + button = buttons[selectedIndex] + button?.isSelected = true } - - @objc func buttonEvent(sender: CornerButton) { - if sender.tag - 10 == selectedIndex { - return - } - selectedIndex = sender.tag - 10 - if let type = self.model?.status?.type { - let update = RoleStatusInfo(type: type, status: status(rawValue: selectedIndex - 1) ?? .Extend) - self.delegate?.didSelected(cell: self, model: update) - } + } + + private var selectedIndex = -1 + private var buttons = [CornerButton]() + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + titleLabel.font = UIFont.systemFont(ofSize: 16) + titleLabel.translatesAutoresizingMaskIntoConstraints = false + titleLabel.textColor = .ne_darkText + titleLabel.text = "删除" + contentView.addSubview(titleLabel) + NSLayoutConstraint.activate([ + titleLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 35), + titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor), + titleLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + ]) + + let denyButton = CornerButton(frame: .zero) + denyButton.color = .white + denyButton.selectedColor = UIColor.red + denyButton.tag = 0 + 10 + denyButton.setImage(UIImage.ne_imageNamed(name: "deny"), for: .normal) + denyButton.setImage(UIImage.ne_imageNamed(name: "denySelected"), for: .selected) + denyButton.addTarget(self, action: #selector(buttonEvent), for: .touchUpInside) + denyButton.cornerType = CornerType.topLeft.union(CornerType.bottomLeft) + buttons.append(denyButton) + + let midButton = CornerButton(frame: .zero) + midButton.tag = 1 + 10 + midButton.color = .white + midButton.selectedColor = UIColor.ne_borderColor + midButton.setImage(UIImage.ne_imageNamed(name: "extend"), for: .normal) + midButton.setImage(UIImage.ne_imageNamed(name: "extendSelected"), for: .selected) + midButton.addTarget(self, action: #selector(buttonEvent), for: .touchUpInside) + buttons.append(midButton) + + let allowButton = CornerButton(frame: .zero) + allowButton.tag = 2 + 10 + allowButton.color = .white + allowButton.selectedColor = UIColor.ne_greenColor + allowButton.setImage(UIImage.ne_imageNamed(name: "allow"), for: .normal) + allowButton.setImage(UIImage.ne_imageNamed(name: "allowSeleted"), for: .selected) + allowButton.cornerType = CornerType.topRight.union(CornerType.bottomRight) + allowButton.addTarget(self, action: #selector(buttonEvent), for: .touchUpInside) + buttons.append(allowButton) + contentView.addSubview(allowButton) + NSLayoutConstraint.activate([ + allowButton.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -35), + allowButton.widthAnchor.constraint(equalToConstant: 32), + allowButton.heightAnchor.constraint(equalToConstant: 26), + allowButton.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + ]) + + contentView.addSubview(midButton) + NSLayoutConstraint.activate([ + midButton.rightAnchor.constraint(equalTo: allowButton.leftAnchor, constant: 0), + midButton.widthAnchor.constraint(equalToConstant: 32), + midButton.heightAnchor.constraint(equalToConstant: 26), + midButton.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + ]) + + contentView.addSubview(denyButton) + NSLayoutConstraint.activate([ + denyButton.rightAnchor.constraint(equalTo: midButton.leftAnchor, constant: 0), + denyButton.widthAnchor.constraint(equalToConstant: 32), + denyButton.heightAnchor.constraint(equalToConstant: 26), + denyButton.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + denyButton.leftAnchor.constraint(equalTo: titleLabel.rightAnchor), + ]) + } + + public func updateModel(model: RoleStatusInfoExt?) { + self.model = model + titleLabel.text = model?.title + index = (model?.status?.status.rawValue ?? 0) + 1 + } + + @objc func buttonEvent(sender: CornerButton) { + if sender.tag - 10 == selectedIndex { + return } - - public func selectedSuccess(success: Bool) { - if success { - if let button = self.button { - button.isSelected = !button.isSelected - } - if selectedIndex >= 0 && selectedIndex < buttons.count { - let new = buttons[selectedIndex] - new.isSelected = !new.isSelected - self.button = new - } - self.model?.status?.status = status(rawValue: selectedIndex - 1) ?? .Extend - } + selectedIndex = sender.tag - 10 + if let type = model?.status?.type { + let update = RoleStatusInfo( + type: type, + status: status(rawValue: selectedIndex - 1) ?? .Extend + ) + delegate?.didSelected(cell: self, model: update) } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") + } + + public func selectedSuccess(success: Bool) { + if success { + if let button = button { + button.isSelected = !button.isSelected + } + if selectedIndex >= 0, selectedIndex < buttons.count { + let new = buttons[selectedIndex] + new.isSelected = !new.isSelected + button = new + } + model?.status?.status = status(rawValue: selectedIndex - 1) ?? .Extend } - - + } + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/View/QChatTextEditCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/View/QChatTextEditCell.swift index 46d08992..588a376b 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/View/QChatTextEditCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/View/QChatTextEditCell.swift @@ -1,75 +1,87 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit -@objc protocol QChatTextEditCellDelegate { - @objc optional func textFieldDidChangeSelection(cell: QChatTextEditCell, _ textField: UITextField) - @objc optional func textDidChange(_ textField: UITextField) + +@objc protocol QChatTextEditCellDelegate:AnyObject { +// @objc optional func textFieldDidChangeSelection(cell: QChatTextEditCell, +// _ textField: UITextField) + @objc optional func textDidChange(_ textField: UITextField) } + class QChatTextEditCell: QChatCornerCell, UITextFieldDelegate { - - var limit: Int? - var canEdit = true - var editTotast = "" - public var textFied = UITextField() - public weak var delegate: QChatTextEditCellDelegate? - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - textFied.textColor = .ne_darkText - textFied.font = UIFont.systemFont(ofSize: 16) - textFied.clearButtonMode = .whileEditing - textFied.translatesAutoresizingMaskIntoConstraints = false - NotificationCenter.default.addObserver(self, selector: #selector(textFieldDidChangeValue(_:)), name: UITextField.textDidChangeNotification, object: textFied) - self.contentView.addSubview(textFied) - NSLayoutConstraint.activate([ - textFied.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 36), - textFied.topAnchor.constraint(equalTo: self.topAnchor), - textFied.bottomAnchor.constraint(equalTo: self.bottomAnchor), - textFied.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -36), - ]) - textFied.delegate = self - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - -// MAKR: UITextFieldDelegate - func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { - if let l = limit { - let text = "\(textField.text ?? "")\(string)" - if text.count > l { - return false - } - } - return true - } - func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { - print("1 textFieldShouldEndEditing") - return true - } - func textFieldDidEndEditing(_ textField: UITextField) { - print("2 textFieldDidEndEditing") - } - func textFieldDidChangeSelection(_ textField: UITextField) { - print("3 textFieldDidChangeSelection:\(textField.text)") - if let d = delegate { - d.textFieldDidChangeSelection?(cell: self, textField) - } + var limit: Int? + var canEdit = true + var editTotast = "" + public var textFied = UITextField() + public weak var delegate: QChatTextEditCellDelegate? + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + textFied.textColor = .ne_darkText + textFied.font = UIFont.systemFont(ofSize: 16) + textFied.clearButtonMode = .whileEditing + textFied.translatesAutoresizingMaskIntoConstraints = false + NotificationCenter.default.addObserver( + self, + selector: #selector(textFieldDidChangeValue(_:)), + name: UITextField.textDidChangeNotification, + object: textFied + ) + contentView.addSubview(textFied) + NSLayoutConstraint.activate([ + textFied.leftAnchor.constraint(equalTo: leftAnchor, constant: 36), + textFied.topAnchor.constraint(equalTo: topAnchor), + textFied.bottomAnchor.constraint(equalTo: bottomAnchor), + textFied.rightAnchor.constraint(equalTo: rightAnchor, constant: -36), + ]) + textFied.delegate = self + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + // MAKR: UITextFieldDelegate + func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, + replacementString string: String) -> Bool { + if let l = limit { + let text = "\(textField.text ?? "")\(string)" + if text.count > l { + return false + } } - - func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { - if canEdit == false, editTotast.count > 0 { - UIApplication.shared.keyWindow?.makeToast(editTotast) - } - return canEdit + return true + } + + func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { + print("1 textFieldShouldEndEditing") + return true + } + + func textFieldDidEndEditing(_ textField: UITextField) { + print("2 textFieldDidEndEditing") + } + + func textFieldDidChangeSelection(_ textField: UITextField) { + print("3 textFieldDidChangeSelection:\(textField.text)") +// if let d = delegate { +// d.textFieldDidChangeSelection?(cell: self, textField) +// } + } + + func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { + if canEdit == false, editTotast.count > 0 { + UIApplication.shared.keyWindow?.makeToast(editTotast) } - - @objc func textFieldDidChangeValue(_ noti: Notification) { - if let d = delegate, let text = noti.object as? UITextField { - d.textDidChange?(text) - } + return canEdit + } + + @objc func textFieldDidChangeValue(_ noti: Notification) { + if let d = delegate, let text = noti.object as? UITextField { + d.textDidChange?(text) } + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/View/QChatTextSelectionCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/View/QChatTextSelectionCell.swift index 4f4f54ef..5b1ab2cc 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/View/QChatTextSelectionCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/View/QChatTextSelectionCell.swift @@ -1,34 +1,41 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class QChatTextSelectionCell: QChatTextCell { - var selectedImageView = UIImageView(image: UIImage.ne_imageNamed(name: "selection")) - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - selectedImageView.contentMode = .center - selectedImageView.translatesAutoresizingMaskIntoConstraints = false - selectedImageView.image = UIImage.ne_imageNamed(name: "Selection") - self.contentView.addSubview(selectedImageView) - NSLayoutConstraint.activate([ - selectedImageView.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -36), - selectedImageView.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 0), - selectedImageView.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: 0), - selectedImageView.widthAnchor.constraint(equalToConstant: 15) - ]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - public func selected(selected: Bool) { - selectedImageView.isHidden = !selected - } - + var selectedImageView = UIImageView(image: UIImage.ne_imageNamed(name: "selection")) + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + selectedImageView.contentMode = .center + selectedImageView.translatesAutoresizingMaskIntoConstraints = false + selectedImageView.image = UIImage.ne_imageNamed(name: "Selection") + contentView.addSubview(selectedImageView) + NSLayoutConstraint.activate([ + selectedImageView.rightAnchor.constraint( + equalTo: contentView.rightAnchor, + constant: -36 + ), + selectedImageView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 0), + selectedImageView.bottomAnchor.constraint( + equalTo: contentView.bottomAnchor, + constant: 0 + ), + selectedImageView.widthAnchor.constraint(equalToConstant: 15), + ]) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + public func selected(selected: Bool) { + selectedImageView.isHidden = !selected + } + // override func setSelected(_ selected: Bool, animated: Bool) { // super.setSelected(selected, animated: animated) // selectedImageView.isHidden = !selected diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatAddMemberVC.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatAddMemberVC.swift index dc333441..d1a23325 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatAddMemberVC.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatAddMemberVC.swift @@ -1,6 +1,7 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCoreIM @@ -9,184 +10,224 @@ import MJRefresh typealias AddMemberRoleBlock = (_ memberRole: MemberRole?) -> Void public class QChatAddMemberVC: QChatSearchVC { - public var channel: ChatChannel? - private var serverMembers:[ServerMemeber]? - private var channelMembers:[ServerMemeber]? - private var lastTimeTag: Double? + public var channel: ChatChannel? + private var serverMembers: [ServerMemeber]? + private var channelMembers: [ServerMemeber]? + private var lastTimeTag: Double? // public var didAddMemberRole: AddMemberRoleBlock? - - public init(channel: ChatChannel?) { - super.init(nibName: nil, bundle: nil) - self.channel = channel - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - } - - public override func viewDidLoad() { - super.viewDidLoad() - self.title = localizable("add_member") - self.tableView.register(QChatImageTextCell.self, forCellReuseIdentifier: "\(QChatImageTextCell.self)") - self.tableView.rowHeight = 60 - tableView.mj_header = MJRefreshNormalHeader(refreshingTarget: self, refreshingAction: #selector(loadData)) - tableView.mj_footer = MJRefreshBackNormalFooter(refreshingTarget: self, refreshingAction: #selector(loadMore)) - loadData() - } - - @objc func loadData() { - self.lastTimeTag = 0 - var param = GetServerMembersByPageParam() - param.serverId = self.channel?.serverId - param.limit = 50 - param.timeTag = self.lastTimeTag - QChatServerProvider.shared.getServerMembers(param) {[weak self] error, sMembers in - print("sMembers:\(sMembers) error:\(error)") - if error != nil { - self?.view.makeToast(error?.localizedDescription) - self?.emptyView.isHidden = false - - }else { - if !sMembers.isEmpty { - self?.lastTimeTag = sMembers.last?.createTime -// var filteredMemberArray = sMembers - if let sid = self?.channel?.serverId, let cid = self?.channel?.channelId { - // 过滤掉已经存在在channel中的成员 - var ids = [String]() - for member in sMembers { - if let id = member.accid { - ids.append(id) - } - } - let param = GetExistingAccidsOfMemberRolesParam(serverId: sid, channelId: cid, accids: ids) - QChatRoleProvider.shared.getExistingMemberRoles(param: param) { error, existMemberArray in - var filterMembers = [ServerMemeber]() - if let existMembers = existMemberArray, !existMembers.isEmpty { - for m in sMembers { - if existMembers.contains(where: { existMember in - return m.accid == existMember.accid - }) { - - }else { - filterMembers.append(m) - } - } - self?.serverMembers = filterMembers - self?.emptyView.isHidden = !filterMembers.isEmpty - }else { - self?.serverMembers = sMembers - self?.emptyView.isHidden = !sMembers.isEmpty - } - self?.tableView.mj_footer?.resetNoMoreData() - self?.tableView.mj_header?.endRefreshing() - self?.tableView.reloadData() - } - }else { - self?.emptyView.isHidden = !sMembers.isEmpty - self?.serverMembers = sMembers - self?.tableView.mj_footer?.resetNoMoreData() - self?.tableView.mj_header?.endRefreshing() - self?.tableView.reloadData() + public init(channel: ChatChannel?) { + super.init(nibName: nil, bundle: nil) + self.channel = channel + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + override public func viewDidLoad() { + super.viewDidLoad() + title = localizable("add_member") + tableView.register( + QChatImageTextCell.self, + forCellReuseIdentifier: "\(QChatImageTextCell.self)" + ) + tableView.rowHeight = 60 + tableView.mj_header = MJRefreshNormalHeader( + refreshingTarget: self, + refreshingAction: #selector(loadData) + ) + tableView.mj_footer = MJRefreshBackNormalFooter( + refreshingTarget: self, + refreshingAction: #selector(loadMore) + ) + loadData() + } + + @objc func loadData() { + lastTimeTag = 0 + var param = GetServerMembersByPageParam() + param.serverId = channel?.serverId + param.limit = 50 + param.timeTag = lastTimeTag + QChatServerProvider.shared.getServerMembers(param) { [weak self] error, sMembers in + print("sMembers:\(sMembers) error:\(error)") + if error != nil { + self?.view.makeToast(error?.localizedDescription) + self?.emptyView.isHidden = false + + } else { + if !sMembers.isEmpty { + self?.lastTimeTag = sMembers.last?.createTime +// var filteredMemberArray = sMembers + if let sid = self?.channel?.serverId, let cid = self?.channel?.channelId { + // 过滤掉已经存在在channel中的成员 + var ids = [String]() + for member in sMembers { + if let id = member.accid { + ids.append(id) + } + } + let param = GetExistingAccidsOfMemberRolesParam( + serverId: sid, + channelId: cid, + accids: ids + ) + QChatRoleProvider.shared + .getExistingMemberRoles(param: param) { error, existMemberArray in + var filterMembers = [ServerMemeber]() + if let existMembers = existMemberArray, !existMembers.isEmpty { + for m in sMembers { + if existMembers.contains(where: { existMember in + m.accid == existMember.accid + }) { + } else { + filterMembers.append(m) } - }else { - // 空白页 - self?.emptyView.isHidden = false + } + self?.serverMembers = filterMembers + self?.emptyView.isHidden = !filterMembers.isEmpty + + } else { + self?.serverMembers = sMembers + self?.emptyView.isHidden = !sMembers.isEmpty } - } + self?.tableView.mj_footer?.resetNoMoreData() + self?.tableView.mj_header?.endRefreshing() + self?.tableView.reloadData() + } + } else { + self?.emptyView.isHidden = !sMembers.isEmpty + self?.serverMembers = sMembers + self?.tableView.mj_footer?.resetNoMoreData() + self?.tableView.mj_header?.endRefreshing() + self?.tableView.reloadData() + } + } else { + // 空白页 + self?.emptyView.isHidden = false } + } } - - @objc func loadMore() { - var param = GetServerMembersByPageParam() - param.serverId = self.channel?.serverId - param.limit = 50 - param.timeTag = self.lastTimeTag - QChatServerProvider.shared.getServerMembers(param) {[weak self] error, sMembers in - print("sMembers:\(sMembers) error:\(error)") - if error != nil { - self?.view.makeToast(error?.localizedDescription) - }else { - if !sMembers.isEmpty { - self?.lastTimeTag = sMembers.last?.createTime - if let sid = self?.channel?.serverId, let cid = self?.channel?.channelId { - // 过滤掉已经存在在channel中的成员 - var ids = [String]() - for member in sMembers { - if let id = member.accid { - ids.append(id) - } - } - let param = GetExistingAccidsOfMemberRolesParam(serverId: sid, channelId: cid, accids: ids) - QChatRoleProvider.shared.getExistingMemberRoles(param: param) { error, existMemberArray in - if let existMembers = existMemberArray, !existMembers.isEmpty { - for m in sMembers { - if existMembers.contains(where: { existMember in - return m.accid == existMember.accid - }) { - }else { - self?.serverMembers?.append(m) - } - } - } - self?.emptyView.removeFromSuperview() - self?.tableView.mj_footer?.endRefreshing() - self?.tableView.reloadData() - } - }else { - for m in sMembers { - self?.serverMembers?.append(m) - } - self?.emptyView.isHidden = true - self?.tableView.mj_footer?.endRefreshing() - self?.tableView.reloadData() + } + + @objc func loadMore() { + var param = GetServerMembersByPageParam() + param.serverId = channel?.serverId + param.limit = 50 + param.timeTag = lastTimeTag + QChatServerProvider.shared.getServerMembers(param) { [weak self] error, sMembers in + print("sMembers:\(sMembers) error:\(error)") + if error != nil { + self?.view.makeToast(error?.localizedDescription) + } else { + if !sMembers.isEmpty { + self?.lastTimeTag = sMembers.last?.createTime + if let sid = self?.channel?.serverId, let cid = self?.channel?.channelId { + // 过滤掉已经存在在channel中的成员 + var ids = [String]() + for member in sMembers { + if let id = member.accid { + ids.append(id) + } + } + let param = GetExistingAccidsOfMemberRolesParam( + serverId: sid, + channelId: cid, + accids: ids + ) + QChatRoleProvider.shared + .getExistingMemberRoles(param: param) { error, existMemberArray in + if let existMembers = existMemberArray, !existMembers.isEmpty { + for m in sMembers { + if existMembers.contains(where: { existMember in + m.accid == existMember.accid + }) { + } else { + self?.serverMembers?.append(m) } - }else { - self?.emptyView.isHidden = true - self?.tableView.mj_footer?.endRefreshingWithNoMoreData() + } } + self?.emptyView.removeFromSuperview() + self?.tableView.mj_footer?.endRefreshing() + self?.tableView.reloadData() + } + } else { + for m in sMembers { + self?.serverMembers?.append(m) } + self?.emptyView.isHidden = true + self?.tableView.mj_footer?.endRefreshing() + self?.tableView.reloadData() + } + } else { + self?.emptyView.isHidden = true + self?.tableView.mj_footer?.endRefreshingWithNoMoreData() } + } } - - public override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return self.serverMembers?.count ?? 0 - } - - public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(withIdentifier: "\(QChatImageTextCell.self)", for: indexPath) as! QChatImageTextCell - cell.backgroundColor = .white - cell.rightStyle = .indicate - let member = self.serverMembers?[indexPath.row] - cell.setup(accid: member?.accid, nickName: member?.nick) - return cell - } - - func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - // 成员权限设置 - let member = self.serverMembers?[indexPath.row] - self.addMemberInChannel(member: member, index: indexPath.row) - } - - private func addMemberInChannel(member: ServerMemeber?, index: Int) { - let param = AddMemberRoleParam(serverId: self.channel?.serverId, channelId: self.channel?.channelId, accid: member?.accid) - QChatRoleProvider.shared.addMemberRole(param) { error, memberRole in - if error != nil { - self.showToast(error?.localizedDescription ?? "") - }else { - self.serverMembers?.remove(at: index) - self.tableView.reloadData() - let settingVC = QChatMemberPermissionSettingVC(channel: self.channel, memberRole: memberRole) - self.navigationController?.pushViewController(settingVC, animated: true) + } + + override public func tableView(_ tableView: UITableView, + numberOfRowsInSection section: Int) -> Int { + serverMembers?.count ?? 0 + } + + override public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatImageTextCell.self)", + for: indexPath + ) as! QChatImageTextCell + cell.backgroundColor = .white + cell.rightStyle = .indicate + let member = serverMembers?[indexPath.row] + cell.setup(accid: member?.accid, nickName: member?.nick) + return cell + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + // 成员权限设置 + let member = serverMembers?[indexPath.row] + addMemberInChannel(member: member, index: indexPath.row) + } + + private func addMemberInChannel(member: ServerMemeber?, index: Int) { + let param = AddMemberRoleParam( + serverId: channel?.serverId, + channelId: channel?.channelId, + accid: member?.accid + ) + QChatRoleProvider.shared.addMemberRole(param) { error, memberRole in + if error != nil { + self.showToast(error?.localizedDescription ?? "") + } else { + self.serverMembers?.remove(at: index) + self.tableView.reloadData() + let settingVC = QChatMemberPermissionSettingVC( + channel: self.channel, + memberRole: memberRole + ) + self.navigationController?.pushViewController(settingVC, animated: true) // if let block = self.didAddMemberRole { // block(memberRole) // } - } - } + } } - private lazy var emptyView:EmptyDataView = { - let view = EmptyDataView(imageName: "memberPlaceholder", content: "无成员可添加",frame: CGRect(x: 0, y: 60, width: self.view.bounds.size.width, height: self.view.bounds.size.height)) - self.view.addSubview(view) - return view - }() + } + + private lazy var emptyView: EmptyDataView = { + let view = EmptyDataView( + imageName: "memberPlaceholder", + content: "无成员可添加", + frame: CGRect( + x: 0, + y: 60, + width: self.view.bounds.size.width, + height: self.view.bounds.size.height + ) + ) + self.view.addSubview(view) + return view + }() } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatAddRoleGroupVC.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatAddRoleGroupVC.swift index 176cc233..29b1cf66 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatAddRoleGroupVC.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatAddRoleGroupVC.swift @@ -1,6 +1,7 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCoreIM @@ -8,192 +9,226 @@ import MJRefresh typealias AddChannelRoleBlock = (_ role: ChannelRole?) -> Void public class QChatAddRoleGroupVC: QChatSearchVC { - public var channel: ChatChannel? - private var serverRoles:[ServerRole]? - private var channelRoles:[ChannelRole]? + public var channel: ChatChannel? + private var serverRoles: [ServerRole]? + private var channelRoles: [ChannelRole]? // public var didAddChannelRole: AddChannelRoleBlock? - private var priority: Int? - private lazy var placeholderView: EmptyDataView = EmptyDataView(imageName: "rolePlaceholder", content: localizable("has_no_role"), frame: CGRect(x: 0, y: 60, width: self.view.bounds.size.width, height: self.view.bounds.size.height)) + private var priority: Int? + private lazy var placeholderView: EmptyDataView = .init( + imageName: "rolePlaceholder", + content: localizable("has_no_role"), + frame: CGRect( + x: 0, + y: 60, + width: self.view.bounds.size.width, + height: self.view.bounds.size.height + ) + ) - public override func viewDidLoad() { - super.viewDidLoad() - self.title = localizable("add_group") - self.tableView.register(QChatTextArrowCell.self, forCellReuseIdentifier: "\(QChatTextArrowCell.self)") - tableView.mj_header = MJRefreshNormalHeader(refreshingTarget: self, refreshingAction: #selector(loadData)) - tableView.mj_footer = MJRefreshBackNormalFooter(refreshingTarget: self, refreshingAction: #selector(loadMore)) - self.view.addSubview(self.placeholderView) - loadData() - } - - init(channel:ChatChannel?) { - super.init(nibName: nil, bundle: nil) - self.channel = channel - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - @objc func loadData() { - self.priority = 0 - //加载server的身份组 - var param = GetServerRoleParam() - param.serverId = self.channel?.serverId - param.limit = 50 - param.priority = self.priority - print("thread:\(Thread.current)") - QChatRoleProvider.shared.getRoles(param) {[weak self] error, roles, sets in - print("sRoles:\(roles) error:\(error)") - if error != nil { - self?.view.makeToast(error?.localizedDescription) - // 空白页 - self?.placeholderView.isHidden = false - }else { - if let roleArray = roles, !roleArray.isEmpty { - self?.priority = roleArray.last?.priority - if let sid = self?.channel?.serverId, let cid = self?.channel?.channelId { - // 过滤掉已经存在在channel中的身份组 - var ids = [UInt64]() - for role in roleArray { - if let id = role.roleId { - ids.append(id) - } - } - let param = GetExistingChannelRolesByServerRoleIdsParam(serverId: sid, channelId: cid, roleIds: ids) - QChatRoleProvider.shared.getExistingChannelRoles(param: param) {error, channelRoles in - if let existRoles = channelRoles, !existRoles.isEmpty { - var tmp = [ServerRole]() - print("roleArray: \(roleArray)") - for role in roleArray { - if existRoles.contains(where: { existRole in - return role.roleId == existRole.parentRoleId - }) { - - }else { - tmp.append(role) - - } - } - self?.serverRoles = tmp - self?.placeholderView.isHidden = !tmp.isEmpty - - }else { - self?.serverRoles = roleArray - self?.placeholderView.isHidden = !roleArray.isEmpty - } - self?.tableView.mj_footer?.resetNoMoreData() - self?.tableView.mj_header?.endRefreshing() - self?.tableView.reloadData() - } - }else { - self?.serverRoles = roleArray - self?.tableView.mj_footer?.resetNoMoreData() - self?.tableView.mj_header?.endRefreshing() - self?.tableView.reloadData() + override public func viewDidLoad() { + super.viewDidLoad() + title = localizable("add_group") + tableView.register( + QChatTextArrowCell.self, + forCellReuseIdentifier: "\(QChatTextArrowCell.self)" + ) + tableView.mj_header = MJRefreshNormalHeader( + refreshingTarget: self, + refreshingAction: #selector(loadData) + ) + tableView.mj_footer = MJRefreshBackNormalFooter( + refreshingTarget: self, + refreshingAction: #selector(loadMore) + ) + view.addSubview(placeholderView) + loadData() + } + + init(channel: ChatChannel?) { + super.init(nibName: nil, bundle: nil) + self.channel = channel + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc func loadData() { + priority = 0 + // 加载server的身份组 + var param = GetServerRoleParam() + param.serverId = channel?.serverId + param.limit = 50 + param.priority = priority + print("thread:\(Thread.current)") + QChatRoleProvider.shared.getRoles(param) { [weak self] error, roles, sets in + print("sRoles:\(roles) error:\(error)") + if error != nil { + self?.view.makeToast(error?.localizedDescription) + // 空白页 + self?.placeholderView.isHidden = false + } else { + if let roleArray = roles, !roleArray.isEmpty { + self?.priority = roleArray.last?.priority + if let sid = self?.channel?.serverId, let cid = self?.channel?.channelId { + // 过滤掉已经存在在channel中的身份组 + var ids = [UInt64]() + for role in roleArray { + if let id = role.roleId { + ids.append(id) + } + } + let param = GetExistingChannelRolesByServerRoleIdsParam( + serverId: sid, + channelId: cid, + roleIds: ids + ) + QChatRoleProvider.shared + .getExistingChannelRoles(param: param) { error, channelRoles in + if let existRoles = channelRoles, !existRoles.isEmpty { + var tmp = [ServerRole]() + print("roleArray: \(roleArray)") + for role in roleArray { + if existRoles.contains(where: { existRole in + role.roleId == existRole.parentRoleId + }) { + } else { + tmp.append(role) } - }else { - // 空白页 - self?.placeholderView.isHidden = false + } + self?.serverRoles = tmp + self?.placeholderView.isHidden = !tmp.isEmpty + + } else { + self?.serverRoles = roleArray + self?.placeholderView.isHidden = !roleArray.isEmpty } - } + self?.tableView.mj_footer?.resetNoMoreData() + self?.tableView.mj_header?.endRefreshing() + self?.tableView.reloadData() + } + } else { + self?.serverRoles = roleArray + self?.tableView.mj_footer?.resetNoMoreData() + self?.tableView.mj_header?.endRefreshing() + self?.tableView.reloadData() + } + } else { + // 空白页 + self?.placeholderView.isHidden = false } + } } - - @objc func loadMore() { - //加载server的身份组 - var param = GetServerRoleParam() - param.serverId = self.channel?.serverId - param.limit = 50 - param.priority = self.priority - QChatRoleProvider.shared.getRoles(param) {[weak self] error, roles, sets in - print("sRoles:\(roles) error:\(error)") - if error != nil { - self?.view.makeToast(error?.localizedDescription) - }else { - if let roleArray = roles, !roleArray.isEmpty { - self?.priority = roleArray.last?.priority - if let sid = self?.channel?.serverId, let cid = self?.channel?.channelId { - // 过滤掉已经存在在channel中的身份组 - var ids = [UInt64]() - for role in roleArray { - if let id = role.roleId { - ids.append(id) - } - } - let param = GetExistingChannelRolesByServerRoleIdsParam(serverId: sid, channelId: cid, roleIds: ids) - QChatRoleProvider.shared.getExistingChannelRoles(param: param) {error, channelRoles in - if let existRoles = channelRoles, !existRoles.isEmpty { - for role in roleArray { - if existRoles.contains(where: { existRole in - return role.roleId == existRole.parentRoleId - }) { - - }else { - self?.serverRoles?.append(role) - } - } - }else { - for role in roleArray { - self?.serverRoles?.append(role) - } - } + } - self?.placeholderView.isHidden = true - self?.tableView.mj_footer?.endRefreshing() - self?.tableView.reloadData() - } - }else { - for role in roleArray { - self?.serverRoles?.append(role) - } - self?.placeholderView.isHidden = true - self?.tableView.mj_footer?.endRefreshing() - self?.tableView.reloadData() + @objc func loadMore() { + // 加载server的身份组 + var param = GetServerRoleParam() + param.serverId = channel?.serverId + param.limit = 50 + param.priority = priority + QChatRoleProvider.shared.getRoles(param) { [weak self] error, roles, sets in + print("sRoles:\(roles) error:\(error)") + if error != nil { + self?.view.makeToast(error?.localizedDescription) + } else { + if let roleArray = roles, !roleArray.isEmpty { + self?.priority = roleArray.last?.priority + if let sid = self?.channel?.serverId, let cid = self?.channel?.channelId { + // 过滤掉已经存在在channel中的身份组 + var ids = [UInt64]() + for role in roleArray { + if let id = role.roleId { + ids.append(id) + } + } + let param = GetExistingChannelRolesByServerRoleIdsParam( + serverId: sid, + channelId: cid, + roleIds: ids + ) + QChatRoleProvider.shared + .getExistingChannelRoles(param: param) { error, channelRoles in + if let existRoles = channelRoles, !existRoles.isEmpty { + for role in roleArray { + if existRoles.contains(where: { existRole in + role.roleId == existRole.parentRoleId + }) { + } else { + self?.serverRoles?.append(role) } - - }else { - self?.tableView.mj_footer?.endRefreshingWithNoMoreData() + } + } else { + for role in roleArray { + self?.serverRoles?.append(role) + } } + + self?.placeholderView.isHidden = true + self?.tableView.mj_footer?.endRefreshing() + self?.tableView.reloadData() + } + } else { + for role in roleArray { + self?.serverRoles?.append(role) } + self?.placeholderView.isHidden = true + self?.tableView.mj_footer?.endRefreshing() + self?.tableView.reloadData() + } + + } else { + self?.tableView.mj_footer?.endRefreshingWithNoMoreData() } + } } - - public override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return self.serverRoles?.count ?? 0 - } - - public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(withIdentifier: "\(QChatTextArrowCell.self)", for: indexPath) as! QChatTextArrowCell - cell.backgroundColor = .white - cell.titleLabel.text = self.serverRoles?[indexPath.row].name - return cell + } + + override public func tableView(_ tableView: UITableView, + numberOfRowsInSection section: Int) -> Int { + serverRoles?.count ?? 0 + } + + override public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatTextArrowCell.self)", + for: indexPath + ) as! QChatTextArrowCell + cell.backgroundColor = .white + cell.titleLabel.text = serverRoles?[indexPath.row].name + return cell + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + let role = serverRoles?[indexPath.row] + guard let sId = channel?.serverId, let cId = channel?.channelId, + let roleId = role?.roleId else { + return } - - func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - let role = self.serverRoles?[indexPath.row] - guard let sId = self.channel?.serverId, let cId = self.channel?.channelId, let roleId = role?.roleId else { - return + // 1.添加到频道下 + let param = AddChannelRoleParam(serverId: sId, channelId: cId, parentRoleId: roleId) + QChatRoleProvider.shared.addChannelRole(param: param) { [weak self] error, cRole in + if error == nil { + // 2.跳转到身份组权限设置 + self?.navigationController?.pushViewController( + QChatGroupPermissionSettingVC(cRole: cRole), + animated: true + ) + // 3.此页面移除该数据并刷新 + self?.serverRoles?.remove(at: indexPath.row) + if self?.serverRoles?.count ?? 0 > 0 { + self?.placeholderView.isHidden = true + self?.tableView.reloadData() + } else { + self?.placeholderView.isHidden = false } - //1.添加到频道下 - let param = AddChannelRoleParam(serverId: sId, channelId: cId, parentRoleId: roleId) - QChatRoleProvider.shared.addChannelRole(param: param) { [weak self] error, cRole in - if error == nil { - //2.跳转到身份组权限设置 - self?.navigationController?.pushViewController(QChatGroupPermissionSettingVC(cRole: cRole), animated: true) - //3.此页面移除该数据并刷新 - self?.serverRoles?.remove(at: indexPath.row) - if self?.serverRoles?.count ?? 0 > 0 { - self?.placeholderView.isHidden = true - self?.tableView.reloadData() - }else { - self?.placeholderView.isHidden = false - } // if let block = self?.didAddChannelRole { // block(cRole) // } - }else { - self?.view.makeToast(error?.localizedDescription) - } - } + } else { + self?.view.makeToast(error?.localizedDescription) + } } + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatChannelAuthoritySettingVC.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatChannelAuthoritySettingVC.swift index f7fec7e7..0beffa1a 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatChannelAuthoritySettingVC.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatChannelAuthoritySettingVC.swift @@ -1,295 +1,352 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCoreIM public class QChatChannelAuthoritySettingVC: QChatTableViewController { - var channel: ChatChannel? - var viewModel: QChatAuthoritySettingViewModel? - var sectionTitle: [String] = ["",localizable("qchat_id_group"),localizable("qchat_member")] - var staticData: [String] = [localizable("add_group"),localizable("add_member")] - var memberData: [String] = [localizable("add_member"),localizable("add_group")] - var isEdit = false + var channel: ChatChannel? + var viewModel: QChatAuthoritySettingViewModel? + var sectionTitle: [String] = ["", localizable("qchat_id_group"), localizable("qchat_member")] + var staticData: [String] = [localizable("add_group"), localizable("add_member")] + var memberData: [String] = [localizable("add_member"), localizable("add_group")] + var isEdit = false - init(channel: ChatChannel?) { - super.init(nibName: nil, bundle: nil) - self.channel = channel - self.viewModel = QChatAuthoritySettingViewModel(channel: self.channel) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - public override func viewWillAppear(_ animated: Bool) { - print("viewWillAppear") - loadData() - } - + init(channel: ChatChannel?) { + super.init(nibName: nil, bundle: nil) + self.channel = channel + viewModel = QChatAuthoritySettingViewModel(channel: self.channel) + } - - public override func viewDidLoad() { - super.viewDidLoad() - commonUI() - } - - func commonUI() { - self.title = localizable("authority_setting") - self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: localizable("qchat_edit"), style: .plain, target: self, action: #selector(edit)) - self.tableView.rowHeight = 50 - self.tableView.register(QChatTextArrowCell.self, forCellReuseIdentifier: "\(QChatTextArrowCell.self)") - self.tableView.register(QChatImageTextCell.self, forCellReuseIdentifier: "\(QChatImageTextCell.self)") - self.tableView.register(QChatCenterTextCell.self, forCellReuseIdentifier: "\(QChatCenterTextCell.self)") - self.tableView.register(QChatSectionView.self, forHeaderFooterViewReuseIdentifier: "\(QChatSectionView.self)") - } - - func loadData() { - //获取频道下的身份组 - viewModel?.firstGetChannelRoles({[weak self] error, roles in - if error != nil { - self?.view.makeToast(error?.localizedDescription) - }else { - self?.tableView.reloadData() - } - }) - - //获取频道下的成员 - viewModel?.firstGetMembers({[weak self] error, members in - if error != nil { - self?.view.makeToast(error?.localizedDescription) - }else { - self?.tableView.reloadData() - } - }) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override public func viewWillAppear(_ animated: Bool) { + print("viewWillAppear") + loadData() + } + + override public func viewDidLoad() { + super.viewDidLoad() + commonUI() + } + + func commonUI() { + title = localizable("authority_setting") + navigationItem.rightBarButtonItem = UIBarButtonItem( + title: localizable("qchat_edit"), + style: .plain, + target: self, + action: #selector(edit) + ) + tableView.rowHeight = 50 + tableView.register( + QChatTextArrowCell.self, + forCellReuseIdentifier: "\(QChatTextArrowCell.self)" + ) + tableView.register( + QChatImageTextCell.self, + forCellReuseIdentifier: "\(QChatImageTextCell.self)" + ) + tableView.register( + QChatCenterTextCell.self, + forCellReuseIdentifier: "\(QChatCenterTextCell.self)" + ) + tableView.register( + QChatSectionView.self, + forHeaderFooterViewReuseIdentifier: "\(QChatSectionView.self)" + ) + } + + func loadData() { + // 获取频道下的身份组 + viewModel?.firstGetChannelRoles { [weak self] error, roles in + if error != nil { + self?.view.makeToast(error?.localizedDescription) + } else { + self?.tableView.reloadData() + } } - // MARK: - event - @objc func edit() { - self.isEdit = !self.isEdit - let title = self.isEdit ? localizable("finish") : localizable("qchat_edit") - self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: title, style: .plain, target: self, action: #selector(edit)) - self.tableView.reloadData() + // 获取频道下的成员 + viewModel?.firstGetMembers { [weak self] error, members in + if error != nil { + self?.view.makeToast(error?.localizedDescription) + } else { + self?.tableView.reloadData() + } } - - // MARK: - delegate - func numberOfSections(in tableView: UITableView) -> Int { - return sectionTitle.count + } + + // MARK: - event + + @objc func edit() { + isEdit = !isEdit + let title = isEdit ? localizable("finish") : localizable("qchat_edit") + navigationItem.rightBarButtonItem = UIBarButtonItem( + title: title, + style: .plain, + target: self, + action: #selector(edit) + ) + tableView.reloadData() + } + + // MARK: - delegate + + func numberOfSections(in tableView: UITableView) -> Int { + sectionTitle.count + } + + override public func tableView(_ tableView: UITableView, + numberOfRowsInSection section: Int) -> Int { + switch section { + case 0: + return staticData.count + case 1: + return viewModel?.rolesData.roles.count ?? 0 + case 2: + return viewModel?.membersData.roles.count ?? 0 + default: + return 0 } - - public override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - switch section { - case 0: - return staticData.count - case 1: - return viewModel?.rolesData.roles.count ?? 0 - case 2: - return viewModel?.membersData.roles.count ?? 0 + } + + override public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + switch indexPath.section { + case 0: + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatTextArrowCell.self)", + for: indexPath + ) as! QChatTextArrowCell + if indexPath.row == 0 { + cell.cornerType = CornerType.topLeft.union(CornerType.topRight) + } else { + cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) + } + cell.titleLabel.text = staticData[indexPath.row] + cell.rightStyle = .indicate + return cell + case 1: + let role = viewModel?.rolesData.roles[indexPath.row] + if role!.isPlacehold { + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatCenterTextCell.self)", + for: indexPath + ) as! QChatCenterTextCell + cell.titleLabel.text = role?.title + cell.titleLabel.textColor = .ne_greyText + cell.titleLabel.font = .systemFont(ofSize: 14) + switch role?.corner { + case .top: + cell.cornerType = CornerType.topLeft.union(CornerType.topRight) + case .bottom: + cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) + case .all: + cell.cornerType = CornerType.topLeft.union(CornerType.topRight) + .union(CornerType.bottomLeft).union(CornerType.bottomRight) default: - return 0 + cell.cornerType = .none } - } - - public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - switch indexPath.section { - case 0: - let cell = tableView.dequeueReusableCell(withIdentifier: "\(QChatTextArrowCell.self)", for: indexPath) as! QChatTextArrowCell - if indexPath.row == 0 { - cell.cornerType = CornerType.topLeft.union(CornerType.topRight) - }else { - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) - } - cell.titleLabel.text = staticData[indexPath.row] - cell.rightStyle = .indicate - return cell - case 1: - let role = viewModel?.rolesData.roles[indexPath.row] - if (role!.isPlacehold) { - let cell = tableView.dequeueReusableCell(withIdentifier: "\(QChatCenterTextCell.self)", for: indexPath) as! QChatCenterTextCell - cell.titleLabel.text = role?.title - cell.titleLabel.textColor = .ne_greyText - cell.titleLabel.font = .systemFont(ofSize: 14) - switch role?.corner { - case .top: - cell.cornerType = CornerType.topLeft.union(CornerType.topRight) - case .bottom: - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) - case .all: - cell.cornerType = CornerType.topLeft.union(CornerType.topRight).union(CornerType.bottomLeft).union(CornerType.bottomRight) - default: - cell.cornerType = .none - } - return cell - }else { - let cell = tableView.dequeueReusableCell(withIdentifier: "\(QChatTextArrowCell.self)", for: indexPath) as! QChatTextArrowCell - cell.titleLabel.text = role?.role?.name - if role?.role?.type == .everyone { - cell.rightStyle = .none - }else { - cell.rightStyle = self.isEdit ? .delete : .none - } - switch role?.corner { - case .top: - cell.cornerType = CornerType.topLeft.union(CornerType.topRight) - case .bottom: - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) - case .all: - cell.cornerType = CornerType.topLeft.union(CornerType.topRight).union(CornerType.bottomLeft).union(CornerType.bottomRight) - default: - cell.cornerType = .none - } - return cell - } + return cell + } else { + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatTextArrowCell.self)", + for: indexPath + ) as! QChatTextArrowCell + cell.titleLabel.text = role?.role?.name + if role?.role?.type == .everyone { + cell.rightStyle = .none + } else { + cell.rightStyle = isEdit ? .delete : .none + } + switch role?.corner { + case .top: + cell.cornerType = CornerType.topLeft.union(CornerType.topRight) + case .bottom: + cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) + case .all: + cell.cornerType = CornerType.topLeft.union(CornerType.topRight) + .union(CornerType.bottomLeft).union(CornerType.bottomRight) + default: + cell.cornerType = .none + } + return cell + } - case 2: - let role = viewModel?.membersData.roles[indexPath.row] - if (role!.isPlacehold) { - let cell = tableView.dequeueReusableCell(withIdentifier: "\(QChatCenterTextCell.self)", for: indexPath) as! QChatCenterTextCell - cell.titleLabel.textColor = .ne_greyText - cell.titleLabel.font = .systemFont(ofSize: 14) - cell.titleLabel.text = role?.title - switch role?.corner { - case .top: - cell.cornerType = CornerType.topLeft.union(CornerType.topRight) - case .bottom: - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) - case .all: - cell.cornerType = CornerType.topLeft.union(CornerType.topRight).union(CornerType.bottomLeft).union(CornerType.bottomRight) - default: - cell.cornerType = .none - } - return cell - }else { - let cell = tableView.dequeueReusableCell(withIdentifier: "\(QChatImageTextCell.self)", for: indexPath) as! QChatImageTextCell - cell.rightStyle = self.isEdit ? .delete : .none - let member = viewModel?.membersData.roles[indexPath.row].member - cell.setup(accid: member?.accid, nickName: member?.nick) - switch role?.corner { - case .top: - cell.cornerType = CornerType.topLeft.union(CornerType.topRight) - case .bottom: - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) - case .all: - cell.cornerType = CornerType.topLeft.union(CornerType.topRight).union(CornerType.bottomLeft).union(CornerType.bottomRight) - default: - cell.cornerType = .none - } - return cell - } + case 2: + let role = viewModel?.membersData.roles[indexPath.row] + if role!.isPlacehold { + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatCenterTextCell.self)", + for: indexPath + ) as! QChatCenterTextCell + cell.titleLabel.textColor = .ne_greyText + cell.titleLabel.font = .systemFont(ofSize: 14) + cell.titleLabel.text = role?.title + switch role?.corner { + case .top: + cell.cornerType = CornerType.topLeft.union(CornerType.topRight) + case .bottom: + cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) + case .all: + cell.cornerType = CornerType.topLeft.union(CornerType.topRight) + .union(CornerType.bottomLeft).union(CornerType.bottomRight) default: - return UITableViewCell() + cell.cornerType = .none } - } - - func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { - let head = tableView.dequeueReusableHeaderFooterView(withIdentifier: "\(QChatSectionView.self)") as! QChatSectionView - head.titleLable.text = sectionTitle[section] - if section == 2, self.viewModel?.membersData.roles.count == 0 { - head.titleLable.text = "" + return cell + } else { + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatImageTextCell.self)", + for: indexPath + ) as! QChatImageTextCell + cell.rightStyle = isEdit ? .delete : .none + let member = viewModel?.membersData.roles[indexPath.row].member + cell.setup(accid: member?.accid, nickName: member?.nick) + switch role?.corner { + case .top: + cell.cornerType = CornerType.topLeft.union(CornerType.topRight) + case .bottom: + cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) + case .all: + cell.cornerType = CornerType.topLeft.union(CornerType.topRight) + .union(CornerType.bottomLeft).union(CornerType.bottomRight) + default: + cell.cornerType = .none } - return head + return cell + } + default: + return UITableViewCell() } - - func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - switch indexPath.section { - case 0: - if indexPath.row == 0 { - // add group - let addRoleVC = QChatAddRoleGroupVC(channel: viewModel?.channel) - self.navigationController?.pushViewController(addRoleVC, animated: true) - - }else { - // add member - let addMemberVC = QChatAddMemberVC(channel: viewModel?.channel) - self.navigationController?.pushViewController(addMemberVC, animated: true) - } - - case 1: + } + + func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { + let head = tableView + .dequeueReusableHeaderFooterView( + withIdentifier: "\(QChatSectionView.self)" + ) as! QChatSectionView + head.titleLable.text = sectionTitle[section] + if section == 2, viewModel?.membersData.roles.count == 0 { + head.titleLable.text = "" + } + return head + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + switch indexPath.section { + case 0: + if indexPath.row == 0 { + // add group + let addRoleVC = QChatAddRoleGroupVC(channel: viewModel?.channel) + navigationController?.pushViewController(addRoleVC, animated: true) + + } else { + // add member + let addMemberVC = QChatAddMemberVC(channel: viewModel?.channel) + navigationController?.pushViewController(addMemberVC, animated: true) + } + + case 1: // group - guard let model = viewModel?.rolesData.roles[indexPath.row] else { - return - } - if model.isPlacehold { - //加载更多 - viewModel?.getChannelRoles({[weak self] error, roles in - if error != nil { - self?.view.makeToast(error?.localizedDescription) - }else { - self?.tableView.reloadData() - } - }) - }else { - if self.isEdit { - //delete role - deleteRole(role: model.role, index: indexPath.row) - }else { - // enter authority setting - let settingVC = QChatGroupPermissionSettingVC(cRole: model.role) - self.navigationController?.pushViewController(settingVC, animated: true) - } - } + guard let model = viewModel?.rolesData.roles[indexPath.row] else { + return + } + if model.isPlacehold { + // 加载更多 + viewModel?.getChannelRoles { [weak self] error, roles in + if error != nil { + self?.view.makeToast(error?.localizedDescription) + } else { + self?.tableView.reloadData() + } + } + } else { + if isEdit { + // delete role + deleteRole(role: model.role, index: indexPath.row) + } else { + // enter authority setting + let settingVC = QChatGroupPermissionSettingVC(cRole: model.role) + navigationController?.pushViewController(settingVC, animated: true) + } + } - case 2: + case 2: // member - guard let model = viewModel?.membersData.roles[indexPath.row] else { - return - } - if model.isPlacehold { - //加载更多 - viewModel?.getMembers({[weak self] error, members in - if error != nil { - self?.view.makeToast(error?.localizedDescription) - }else { - self?.tableView.reloadData() - } - }) - }else { - if self.isEdit { - //delete member - deleteMember(member: model.member, index: indexPath.row) - }else { - // enter member authority setting - let settingVC = QChatMemberPermissionSettingVC(channel: self.channel, memberRole: model.member) - self.navigationController?.pushViewController(settingVC, animated: true) - } - } - default: - break + guard let model = viewModel?.membersData.roles[indexPath.row] else { + return + } + if model.isPlacehold { + // 加载更多 + viewModel?.getMembers { [weak self] error, members in + if error != nil { + self?.view.makeToast(error?.localizedDescription) + } else { + self?.tableView.reloadData() + } } - } - - private func deleteRole(role: ChannelRole?, index: Int) { - let name = role?.name ?? "" - let message = localizable("confirm_delete_channel") + name + localizable("qchat_id_group") + "?" - let alertVC = UIAlertController.reconfimAlertView(title: localizable("removeRole"), message: message) { - self.viewModel?.removeChannelRole(role: role, index: index, { [weak self] error in - if error != nil { - self?.view.makeToast(error?.localizedDescription) - }else { - self?.tableView.reloadData() - } - }) - + } else { + if isEdit { + // delete member + deleteMember(member: model.member, index: indexPath.row) + } else { + // enter member authority setting + let settingVC = QChatMemberPermissionSettingVC( + channel: channel, + memberRole: model.member + ) + navigationController?.pushViewController(settingVC, animated: true) } - self.present(alertVC, animated: true, completion: nil) + } + default: + break } - - private func deleteMember(member: MemberRole?, index: Int) { - var name = member?.accid ?? "" - if let n = member?.nick, n.count > 0 { - name = n + } + + private func deleteRole(role: ChannelRole?, index: Int) { + let name = role?.name ?? "" + let message = localizable("confirm_delete_channel") + name + localizable("qchat_id_group") + + "?" + let alertVC = UIAlertController.reconfimAlertView( + title: localizable("removeRole"), + message: message + ) { + self.viewModel?.removeChannelRole(role: role, index: index) { [weak self] error in + if error != nil { + self?.view.makeToast(error?.localizedDescription) + } else { + self?.tableView.reloadData() } - let message = localizable("confirm_delete_channel") + name + localizable("qchat_member") + "?" - let alertVC = UIAlertController.reconfimAlertView(title: localizable("removeMember"), message: message) { - self.viewModel?.removeMemberRole(member: member, index: index, { [weak self] error in - if error != nil { - self?.view.makeToast(error?.localizedDescription) - }else { - self?.tableView.reloadData() - } - }) + } + } + present(alertVC, animated: true, completion: nil) + } + + private func deleteMember(member: MemberRole?, index: Int) { + var name = member?.accid ?? "" + if let n = member?.nick, n.count > 0 { + name = n + } + let message = localizable("confirm_delete_channel") + name + localizable("qchat_member") + + "?" + let alertVC = UIAlertController.reconfimAlertView( + title: localizable("removeMember"), + message: message + ) { + self.viewModel?.removeMemberRole(member: member, index: index) { [weak self] error in + if error != nil { + self?.view.makeToast(error?.localizedDescription) + } else { + self?.tableView.reloadData() } - self.present(alertVC, animated: true, completion: nil) + } } + present(alertVC, animated: true, completion: nil) + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatChannelMembersVC.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatChannelMembersVC.swift index e06140a8..4f250781 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatChannelMembersVC.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatChannelMembersVC.swift @@ -1,148 +1,186 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCoreIM import MJRefresh public class QChatChannelMembersVC: QChatTableViewController, QChatMemberInfoViewDelegate { - - public var channel: ChatChannel? - private var channelMembers:[ServerMemeber]? - var memberInfoView: QChatMemberInfoView? - var lastMember: ServerMemeber? - - public override func viewDidLoad() { - super.viewDidLoad() - commonUI() - loadData() - } - func commonUI() { - self.title = localizable("channel_member") - let header = ChannelHeaderView(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 78)) - header.settingButton.addTarget(self, action: #selector(enterChannelSetting), for: .touchUpInside) - header.titleLabel.text = self.channel?.name - header.detailLabel.text = self.channel?.topic - tableView.tableHeaderView = header - tableView.register(QChatImageTextOnlineCell.self, forCellReuseIdentifier: "\(QChatImageTextOnlineCell.self)") - tableView.mj_footer = MJRefreshBackNormalFooter(refreshingTarget: self, refreshingAction: #selector(loadMoreData)) - tableView.mj_header = MJRefreshNormalHeader(refreshingTarget: self, refreshingAction: #selector(loadData)) - } - - @objc func loadData() { - var param = ChannelMembersParam(serverId: self.channel?.serverId ?? 0, channelId: self.channel?.channelId ?? 0) - param.limit = 50 - QChatChannelProvider.shared.getChannelMembers(param: param) { [weak self] error, cMembersResult in - print("cMembersResult.memberArray:\(cMembersResult?.memberArray) thread:\(Thread.current) ") - self?.channelMembers = cMembersResult?.memberArray - self?.lastMember = cMembersResult?.memberArray?.last - self?.tableView.reloadData() - self?.tableView.mj_footer?.resetNoMoreData() - self?.tableView.mj_header?.endRefreshing() + public var channel: ChatChannel? + private var channelMembers: [ServerMemeber]? + var memberInfoView: QChatMemberInfoView? + var lastMember: ServerMemeber? + + override public func viewDidLoad() { + super.viewDidLoad() + commonUI() + loadData() + } + + func commonUI() { + title = localizable("channel_member") + let header = + ChannelHeaderView(frame: CGRect(x: 0, y: 0, width: view.frame.size.width, height: 78)) + header.settingButton.addTarget( + self, + action: #selector(enterChannelSetting), + for: .touchUpInside + ) + header.titleLabel.text = channel?.name + header.detailLabel.text = channel?.topic + tableView.tableHeaderView = header + tableView.register( + QChatImageTextOnlineCell.self, + forCellReuseIdentifier: "\(QChatImageTextOnlineCell.self)" + ) + tableView.mj_footer = MJRefreshBackNormalFooter( + refreshingTarget: self, + refreshingAction: #selector(loadMoreData) + ) + tableView.mj_header = MJRefreshNormalHeader( + refreshingTarget: self, + refreshingAction: #selector(loadData) + ) + } + + @objc func loadData() { + var param = ChannelMembersParam( + serverId: channel?.serverId ?? 0, + channelId: channel?.channelId ?? 0 + ) + param.limit = 50 + QChatChannelProvider.shared + .getChannelMembers(param: param) { [weak self] error, cMembersResult in + print( + "cMembersResult.memberArray:\(cMembersResult?.memberArray) thread:\(Thread.current) " + ) + self?.channelMembers = cMembersResult?.memberArray + self?.lastMember = cMembersResult?.memberArray?.last + self?.tableView.reloadData() + self?.tableView.mj_footer?.resetNoMoreData() + self?.tableView.mj_header?.endRefreshing() + } + } + + @objc func loadMoreData() { + var param = ChannelMembersParam( + serverId: channel?.serverId ?? 0, + channelId: channel?.channelId ?? 0 + ) + param.timeTag = lastMember?.createTime + param.limit = 50 + QChatChannelProvider.shared + .getChannelMembers(param: param) { [weak self] error, cMembersResult in + print( + "more cMembersResult.memberArray:\(cMembersResult?.memberArray) thread:\(Thread.current) " + ) + if error != nil { + self?.view.makeToast(error?.localizedDescription) + return } - } - @objc func loadMoreData() { - var param = ChannelMembersParam(serverId: self.channel?.serverId ?? 0, channelId: self.channel?.channelId ?? 0) - param.timeTag = self.lastMember?.createTime - param.limit = 50 - QChatChannelProvider.shared.getChannelMembers(param: param) { [weak self] error, cMembersResult in - print("more cMembersResult.memberArray:\(cMembersResult?.memberArray) thread:\(Thread.current) ") - if error != nil { - self?.view.makeToast(error?.localizedDescription) - return - } - if let members = cMembersResult?.memberArray, members.count > 0 { - for m in members { - self?.channelMembers?.append(m) - } - self?.lastMember = members.last - self?.tableView.reloadData() - }else { + if let members = cMembersResult?.memberArray, members.count > 0 { + for m in members { + self?.channelMembers?.append(m) + } + self?.lastMember = members.last + self?.tableView.reloadData() + } else { // end - self?.tableView.mj_footer?.endRefreshingWithNoMoreData() - } + self?.tableView.mj_footer?.endRefreshingWithNoMoreData() } + } + } + + override public func tableView(_ tableView: UITableView, + numberOfRowsInSection section: Int) -> Int { + channelMembers?.count ?? 0 + } + + override public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatImageTextOnlineCell.self)", + for: indexPath + ) as! QChatImageTextOnlineCell + let member = channelMembers![indexPath.row] as ServerMemeber + cell.setup(accid: member.accid, nickName: member.nick) + cell.online = false + if channelMembers?.count == 1 { + cell.cornerType = CornerType.topLeft.union(CornerType.topRight) + .union(CornerType.bottomLeft).union(CornerType.bottomRight) + } else { + if indexPath.row == 0 { + cell.cornerType = CornerType.topLeft.union(CornerType.topRight) + } else if indexPath.row == channelMembers!.count - 1 { + cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) + } } - - public override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return self.channelMembers?.count ?? 0 - } - - public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(withIdentifier: "\(QChatImageTextOnlineCell.self)", for: indexPath) as! QChatImageTextOnlineCell - let member = self.channelMembers![indexPath.row] as ServerMemeber - cell.setup(accid: member.accid, nickName: member.nick) - cell.online = false - if self.channelMembers?.count == 1 { - cell.cornerType = CornerType.topLeft.union(CornerType.topRight).union(CornerType.bottomLeft).union(CornerType.bottomRight) - }else { - if indexPath.row == 0 { - cell.cornerType = CornerType.topLeft.union(CornerType.topRight) - }else if indexPath.row == self.channelMembers!.count - 1 { - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) - } - } - return cell - } - - func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - let m = self.channelMembers![indexPath.row] - memberInfoView = QChatMemberInfoView(inView: UIApplication.shared.keyWindow!) - memberInfoView?.setup(accid: m.accid, nickName: m.nick) - memberInfoView?.delegate = self - self.memberInfoView?.present() - self.loadRolesOfMember(member: m) - + return cell + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + let m = channelMembers![indexPath.row] + memberInfoView = QChatMemberInfoView(inView: UIApplication.shared.keyWindow!) + memberInfoView?.setup(accid: m.accid, nickName: m.nick) + memberInfoView?.delegate = self + memberInfoView?.present() + loadRolesOfMember(member: m) + } + + func loadRolesOfMember(member: ServerMemeber) { + let param = GetServerRolesByAccIdParam(serverId: channel?.serverId, accid: member.accid) + QChatRoleProvider.shared.getServerRolesByAccId(param: param) { [weak self] error, roles in + print("roles:\(roles?.count) error: \(error)") + guard let roleList = roles else { + return + } + var names = [String]() + + for r in roleList { + names.append(r.name ?? "") + } + self?.memberInfoView?.setupRoles(dataArray: names) } - - func loadRolesOfMember(member: ServerMemeber) { - let param = GetServerRolesByAccIdParam(serverId: self.channel?.serverId, accid: member.accid) - QChatRoleProvider.shared.getServerRolesByAccId(param: param) {[weak self] error , roles in - print("roles:\(roles?.count) error: \(error)") - guard let roleList = roles else { - return - } - var names = [String]() - - for r in roleList { - names.append(r.name ?? "") - } - self?.memberInfoView?.setupRoles(dataArray: names) - - } + } + + @objc func enterChannelSetting() { + let settingVC = QChatChannelSettingVC() + settingVC.didUpdateChannel = { [weak self] channel in + self?.channel = channel + guard let head = self?.tableView.tableHeaderView as? ChannelHeaderView else { + return + } + head.titleLabel.text = channel?.name + head.detailLabel.text = channel?.topic } - - @objc func enterChannelSetting() { - let settingVC = QChatChannelSettingVC() - settingVC.didUpdateChannel = { [weak self] channel in - self?.channel = channel - guard let head = self?.tableView.tableHeaderView as? ChannelHeaderView else { - return - } - head.titleLabel.text = channel?.name - head.detailLabel.text = channel?.topic - } - - settingVC.didDeleteChannel = { [weak self] channel in - self?.navigationController?.popViewController(animated: true) - } - settingVC.viewModel = QChatUpdateChannelViewModel(channel: self.channel) - let nav = UINavigationController(rootViewController: settingVC) - nav.modalPresentationStyle = .fullScreen - self.present(nav, animated: true, completion: nil) + settingVC.didDeleteChannel = { [weak self] channel in + self?.navigationController?.popViewController(animated: true) } - - func didClickUserHeader(_ accid: String?) { - if let uid = accid { - if IMKitLoginManager.instance.isMySelf(uid){ - Router.shared.use(MeSettingRouter, parameters: ["nav": navigationController as Any], closure: nil) - }else { - Router.shared.use(ContactUserInfoPageRouter, parameters: ["nav": navigationController as Any, "uid": uid as Any], closure: nil) - } - } - + + settingVC.viewModel = QChatUpdateChannelViewModel(channel: channel) + let nav = UINavigationController(rootViewController: settingVC) + nav.modalPresentationStyle = .fullScreen + present(nav, animated: true, completion: nil) + } + + func didClickUserHeader(_ accid: String?) { + if let uid = accid { + if IMKitLoginManager.instance.isMySelf(uid) { + Router.shared.use( + MeSettingRouter, + parameters: ["nav": navigationController as Any], + closure: nil + ) + } else { + Router.shared.use( + ContactUserInfoPageRouter, + parameters: ["nav": navigationController as Any, "uid": uid as Any], + closure: nil + ) + } } - + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatChannelSettingVC.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatChannelSettingVC.swift index 4017e75c..88a3d2a2 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatChannelSettingVC.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatChannelSettingVC.swift @@ -1,6 +1,7 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCoreIM @@ -8,182 +9,259 @@ import NEKitCoreIM typealias updateChannelSuccess = (_ channel: ChatChannel?) -> Void public class QChatChannelSettingVC: QChatTableViewController, QChatTextEditCellDelegate { - var viewModel: QChatUpdateChannelViewModel? - var didUpdateChannel: updateChannelSuccess? - var didDeleteChannel: updateChannelSuccess? - - var sections: [String]? - var cells = [String]() - - public override func viewDidLoad() { - super.viewDidLoad() - loadData() - commonUI() - } + var viewModel: QChatUpdateChannelViewModel? + var didUpdateChannel: updateChannelSuccess? + var didDeleteChannel: updateChannelSuccess? + + var sections: [String]? + var cells = [String]() + + override public func viewDidLoad() { + super.viewDidLoad() + loadData() + commonUI() + } + + func loadData() { + sections = [ + localizable("channel_name"), + localizable("channel_topic"), + localizable("authority"), + localizable("list"), + "", + ] + + let listName = viewModel?.channel? + .visibleType == .isPublic ? localizable("black_list") : localizable("white_list") + + cells = [ + viewModel?.channel?.name ?? "", + viewModel?.channel?.topic ?? "", + localizable("authority_setting"), + listName, + localizable("delete_channel"), + ] + } + + func commonUI() { + title = localizable("channel_setting") + navigationItem.rightBarButtonItem = UIBarButtonItem( + title: localizable("save"), + style: .plain, + target: self, + action: #selector(save) + ) + navigationItem.leftBarButtonItem = UIBarButtonItem( + title: localizable("close"), + style: .plain, + target: self, + action: #selector(close) + ) + navigationItem.rightBarButtonItem?.tintColor = .ne_blueText + tableView.rowHeight = 50 + tableView.register( + QChatTextEditCell.self, + forCellReuseIdentifier: "\(QChatTextEditCell.self)" + ) + tableView.register( + QChatTextArrowCell.self, + forCellReuseIdentifier: "\(QChatTextArrowCell.self)" + ) + tableView.register( + QChatCenterTextCell.self, + forCellReuseIdentifier: "\(QChatCenterTextCell.self)" + ) + tableView.register( + QChatSectionView.self, + forHeaderFooterViewReuseIdentifier: "\(QChatSectionView.self)" + ) + } - func loadData() { - sections = [localizable("channel_name"),localizable("channel_topic"),localizable("authority"),localizable("list"),""] - - let listName = viewModel?.channel?.visibleType == .isPublic ? localizable("black_list") : localizable("white_list") - - cells = [viewModel?.channel?.name ?? "",viewModel?.channel?.topic ?? "",localizable("authority_setting"),listName, localizable("delete_channel")] - } - - func commonUI() { - self.title = localizable("channel_setting") - self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: localizable("save"), style: .plain, target: self, action: #selector(save)) - self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: localizable("close"), style: .plain, target: self, action: #selector(close)) - self.navigationItem.rightBarButtonItem?.tintColor = .ne_blueText - self.tableView.rowHeight = 50 - self.tableView.register(QChatTextEditCell.self, forCellReuseIdentifier: "\(QChatTextEditCell.self)") - self.tableView.register(QChatTextArrowCell.self, forCellReuseIdentifier: "\(QChatTextArrowCell.self)") - self.tableView.register(QChatCenterTextCell.self, forCellReuseIdentifier: "\(QChatCenterTextCell.self)") - self.tableView.register(QChatSectionView.self, forHeaderFooterViewReuseIdentifier: "\(QChatSectionView.self)") - - } // MARK: deletgate - func numberOfSections(in tableView: UITableView) -> Int { - return sections?.count ?? 0 - } - - public override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return 1 - } - - public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - switch indexPath.section { - case 0: - let cell = tableView.dequeueReusableCell(withIdentifier: "\(QChatTextEditCell.self)", for: indexPath) as! QChatTextEditCell - cell.cornerType = CornerType.topLeft.union(CornerType.topRight).union(CornerType.bottomLeft).union(CornerType.bottomRight) - cell.textFied.text = cells[indexPath.section] - cell.textFied.tag = 20 - cell.delegate = self - return cell - case 1: - let cell = tableView.dequeueReusableCell(withIdentifier: "\(QChatTextEditCell.self)", for: indexPath) as! QChatTextEditCell - cell.cornerType = CornerType.topLeft.union(CornerType.topRight).union(CornerType.bottomLeft).union(CornerType.bottomRight) - cell.textFied.text = cells[indexPath.section] - cell.textFied.tag = 21 - cell.delegate = self - return cell - case 2,3: - let cell = tableView.dequeueReusableCell(withIdentifier: "\(QChatTextArrowCell.self)", for: indexPath) as! QChatTextArrowCell - cell.cornerType = CornerType.topLeft.union(CornerType.topRight).union(CornerType.bottomLeft).union(CornerType.bottomRight) - cell.titleLabel.text = cells[indexPath.section] - return cell - case 4: - let cell = tableView.dequeueReusableCell(withIdentifier: "\(QChatCenterTextCell.self)", for: indexPath) as! QChatCenterTextCell - cell.cornerType = CornerType.topLeft.union(CornerType.topRight).union(CornerType.bottomLeft).union(CornerType.bottomRight) - cell.titleLabel.text = cells[indexPath.section] - return cell - default: - return UITableViewCell() - } - } - - func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { - let head = tableView.dequeueReusableHeaderFooterView(withIdentifier: "\(QChatSectionView.self)") as! QChatSectionView - head.titleLable.text = sections?[section] - return head + + func numberOfSections(in tableView: UITableView) -> Int { + sections?.count ?? 0 + } + + override public func tableView(_ tableView: UITableView, + numberOfRowsInSection section: Int) -> Int { + 1 + } + + override public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + switch indexPath.section { + case 0: + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatTextEditCell.self)", + for: indexPath + ) as! QChatTextEditCell + cell.cornerType = CornerType.topLeft.union(CornerType.topRight) + .union(CornerType.bottomLeft).union(CornerType.bottomRight) + cell.textFied.text = cells[indexPath.section] + cell.textFied.tag = 20 + cell.delegate = self + return cell + case 1: + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatTextEditCell.self)", + for: indexPath + ) as! QChatTextEditCell + cell.cornerType = CornerType.topLeft.union(CornerType.topRight) + .union(CornerType.bottomLeft).union(CornerType.bottomRight) + cell.textFied.text = cells[indexPath.section] + cell.textFied.tag = 21 + cell.delegate = self + return cell + case 2, 3: + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatTextArrowCell.self)", + for: indexPath + ) as! QChatTextArrowCell + cell.cornerType = CornerType.topLeft.union(CornerType.topRight) + .union(CornerType.bottomLeft).union(CornerType.bottomRight) + cell.titleLabel.text = cells[indexPath.section] + return cell + case 4: + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatCenterTextCell.self)", + for: indexPath + ) as! QChatCenterTextCell + cell.cornerType = CornerType.topLeft.union(CornerType.topRight) + .union(CornerType.bottomLeft).union(CornerType.bottomRight) + cell.titleLabel.text = cells[indexPath.section] + return cell + default: + return UITableViewCell() } - - func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - switch indexPath.section { - case 2: - // authority - enterAuthoritySettingVC() - case 3: - // name list - enterListVC() - case 4: + } + + func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { + let head = tableView + .dequeueReusableHeaderFooterView( + withIdentifier: "\(QChatSectionView.self)" + ) as! QChatSectionView + head.titleLable.text = sections?[section] + return head + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + switch indexPath.section { + case 2: + // authority + enterAuthoritySettingVC() + case 3: + // name list + enterListVC() + case 4: // delete - deleteChannel() - default: - break - } + deleteChannel() + default: + break } - + } + // MARK: private method - private func enterAuthoritySettingVC() { - self.navigationController?.pushViewController(QChatChannelAuthoritySettingVC(channel: viewModel?.channel), animated: true) - } - - private func enterListVC() { - let listVC = QChatWhiteBlackListVC() - listVC.channel = self.viewModel?.channel - listVC.type = viewModel?.channel?.visibleType == .isPublic ? .black : .white - self.navigationController?.pushViewController(listVC, animated: true) + + private func enterAuthoritySettingVC() { + navigationController?.pushViewController( + QChatChannelAuthoritySettingVC(channel: viewModel?.channel), + animated: true + ) + } + + private func enterListVC() { + let listVC = QChatWhiteBlackListVC() + listVC.channel = viewModel?.channel + listVC.type = viewModel?.channel?.visibleType == .isPublic ? .black : .white + navigationController?.pushViewController(listVC, animated: true) + } + + private func deleteChannel() { + let message: String? + if let name = viewModel?.channel?.name { + message = localizable("confirm_delete_channel") + name + "?" + } else { + message = localizable("confirm_delete_channel") + "?" } - - private func deleteChannel() { - let message: String? - if let name = viewModel?.channel?.name { - message = localizable("confirm_delete_channel") + name + "?" - }else { - message = localizable("confirm_delete_channel") + "?" - } - let alertVC = UIAlertController.reconfimAlertView(title: localizable("delete_channel"), message: message) { - self.viewModel?.deleteChannel(completion: { [weak self] error in - - if error != nil { - self?.view.makeToast(error?.localizedDescription) - }else { - self?.view.makeToast(localizable("delete_channel_suscess"), duration: 1, completion: { didTap in - //通知上级页面 - NotificationCenter.default.post(name: NotificationName.deleteChannel, object: self?.viewModel?.channel) - self?.didDeleteChannel?(self?.viewModel?.channel) - self?.close() - }) - } - }) + let alertVC = UIAlertController.reconfimAlertView( + title: localizable("delete_channel"), + message: message + ) { + self.viewModel?.deleteChannel(completion: { [weak self] error in + + if error != nil { + self?.view.makeToast(error?.localizedDescription) + } else { + self?.view.makeToast( + localizable("delete_channel_suscess"), + duration: 1, + completion: { didTap in + // 通知上级页面 + NotificationCenter.default.post( + name: NotificationName.deleteChannel, + object: self?.viewModel?.channel + ) + self?.didDeleteChannel?(self?.viewModel?.channel) + self?.close() + } + ) } - self.present(alertVC, animated: true, completion: nil) + }) } - + present(alertVC, animated: true, completion: nil) + } + // MARK: QChatTextEditCellDelegate - func textDidChange(_ textField: UITextField) { - if textField.tag == 20 { - if textField.text?.count == 0 { - self.navigationItem.rightBarButtonItem?.tintColor = .ne_greyText - }else { - if var str = textField.text, str.count > 50 { - str = str.substring(to: str.index(str.startIndex, offsetBy: 50)) - print("str:\(str)") - textField.text = str - } - self.navigationItem.rightBarButtonItem?.tintColor = .ne_blueText - } - viewModel?.channelTmp?.name = textField.text - }else if textField.tag == 21 { - if var str = textField.text, str.count > 64 { - str = str.substring(to: str.index(str.startIndex, offsetBy: 64)) - print("str:\(str)") - textField.text = str - } - viewModel?.channelTmp?.topic = textField.text + + func textDidChange(_ textField: UITextField) { + if textField.tag == 20 { + if textField.text?.count == 0 { + navigationItem.rightBarButtonItem?.tintColor = .ne_greyText + } else { + if var str = textField.text, str.count > 50 { + str = str.substring(to: str.index(str.startIndex, offsetBy: 50)) + print("str:\(str)") + textField.text = str } + navigationItem.rightBarButtonItem?.tintColor = .ne_blueText + } + viewModel?.channelTmp?.name = textField.text + } else if textField.tag == 21 { + if var str = textField.text, str.count > 64 { + str = str.substring(to: str.index(str.startIndex, offsetBy: 64)) + print("str:\(str)") + textField.text = str + } + viewModel?.channelTmp?.topic = textField.text } - + } + // MARK: event - @objc func save() { - viewModel?.updateChannelInfo(completion: {[weak self] error, channel in - if error != nil { - self?.view.makeToast(error?.localizedDescription) - return - } - self?.view.makeToast(localizable("update_channel_suscess"), duration: 2, completion: { didTap in - self?.didUpdateChannel?(channel) - NotificationCenter.default.post(name: NotificationName.updateChannel, object: channel) - //通知上级页面 - self?.close() - }) - }) - } - - @objc func close() { - self.navigationController?.dismiss(animated: true, completion: nil) - } - + @objc func save() { + viewModel?.updateChannelInfo(completion: { [weak self] error, channel in + if error != nil { + self?.view.makeToast(error?.localizedDescription) + return + } + self?.view.makeToast( + localizable("update_channel_suscess"), + duration: 2, + completion: { didTap in + self?.didUpdateChannel?(channel) + NotificationCenter.default.post( + name: NotificationName.updateChannel, + object: channel + ) + // 通知上级页面 + self?.close() + } + ) + }) + } + @objc func close() { + navigationController?.dismiss(animated: true, completion: nil) + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatChannelTypeVC.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatChannelTypeVC.swift index f80abd9c..82dc789e 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatChannelTypeVC.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatChannelTypeVC.swift @@ -1,60 +1,74 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCoreIM struct ChannelSelection { - var sectionName = "" - var isSeleted = false + var sectionName = "" + var isSeleted = false } protocol QChatChannelTypeVCDelegate: AnyObject { - func didSelected(type: Int) + func didSelected(type: Int) } public class QChatChannelTypeVC: QChatTableViewController { - var dataList = [ChannelSelection]() - weak var delegate: QChatChannelTypeVCDelegate? - var isPrivate: Bool = false - - public override func viewDidLoad() { - super.viewDidLoad() - loadData() - commonUI() - } - - func commonUI() { - self.title = localizable("channel_type") - self.tableView.register(QChatTextSelectionCell.self, forCellReuseIdentifier: "\(QChatTextSelectionCell.self)") - self.tableView.selectRow(at: IndexPath(row: 0, section: 0), animated: false, scrollPosition: .top) - } - func loadData() { - dataList.append(ChannelSelection(sectionName: localizable("public"), isSeleted: !isPrivate)) - dataList.append(ChannelSelection(sectionName: localizable("private"), isSeleted: isPrivate)) - } + var dataList = [ChannelSelection]() + weak var delegate: QChatChannelTypeVCDelegate? + var isPrivate: Bool = false - public override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return dataList.count - } - public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell: QChatTextSelectionCell = tableView.dequeueReusableCell(withIdentifier: "\(QChatTextSelectionCell.self)", for: indexPath) as! QChatTextSelectionCell - let item = dataList[indexPath.row] - cell.titleLabel.text = item.sectionName - if indexPath.row == 0 { - cell.cornerType = CornerType.topLeft.union(CornerType.topRight) - }else { - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) - cell.setSelected(true, animated: true) - } - cell.selected(selected: item.isSeleted) - return cell - } - - public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - delegate?.didSelected(type: indexPath.row) - self.navigationController?.popViewController(animated: true) + override public func viewDidLoad() { + super.viewDidLoad() + loadData() + commonUI() + } + + func commonUI() { + title = localizable("channel_type") + tableView.register( + QChatTextSelectionCell.self, + forCellReuseIdentifier: "\(QChatTextSelectionCell.self)" + ) + tableView.selectRow( + at: IndexPath(row: 0, section: 0), + animated: false, + scrollPosition: .top + ) + } + + func loadData() { + dataList.append(ChannelSelection(sectionName: localizable("public"), isSeleted: !isPrivate)) + dataList.append(ChannelSelection(sectionName: localizable("private"), isSeleted: isPrivate)) + } + + override public func tableView(_ tableView: UITableView, + numberOfRowsInSection section: Int) -> Int { + dataList.count + } + + override public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell: QChatTextSelectionCell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatTextSelectionCell.self)", + for: indexPath + ) as! QChatTextSelectionCell + let item = dataList[indexPath.row] + cell.titleLabel.text = item.sectionName + if indexPath.row == 0 { + cell.cornerType = CornerType.topLeft.union(CornerType.topRight) + } else { + cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) + cell.setSelected(true, animated: true) } - + cell.selected(selected: item.isSeleted) + return cell + } + + public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + delegate?.didSelected(type: indexPath.row) + navigationController?.popViewController(animated: true) + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatChannelViewController.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatChannelViewController.swift index f85a0046..fcea1056 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatChannelViewController.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatChannelViewController.swift @@ -1,162 +1,220 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import Toast_Swift import NEKitCoreIM struct Channel { - var sectionName = "" - var contentName = "" + var sectionName = "" + var contentName = "" } -public class QChatChannelViewController: QChatTableViewController, QChatTextEditCellDelegate, QChatChannelTypeVCDelegate { +public class QChatChannelViewController: QChatTableViewController, QChatTextEditCellDelegate, + QChatChannelTypeVCDelegate { + var viewModel: QChatChannelViewModel? + var dataList = [Channel]() + // 防重点击创建频道 + var isCreatedChannel = false - var viewModel: QChatChannelViewModel? - var dataList = [Channel]() - //防重点击创建频道 - var isCreatedChannel = false - - public init(serverId: UInt64) { - self.viewModel = QChatChannelViewModel(serverId: serverId) - super.init(nibName: nil, bundle: nil) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - public override func viewDidLoad() { - super.viewDidLoad() - commonUI() - loadData() - } - - func commonUI() { - self.title = localizable("create_channel") - self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: localizable("create"), style: .plain, target: self, action: #selector(createChannel)) - self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: localizable("cancel"), style: .plain, target: self, action: #selector(cancelEvent)) - self.navigationItem.rightBarButtonItem?.tintColor = .ne_greyText - self.tableView.register(QChatTextEditCell.self, forCellReuseIdentifier: "\(QChatTextEditCell.self)") - self.tableView.register(QChatTextArrowCell.self, forCellReuseIdentifier: "\(QChatTextArrowCell.self)") - self.tableView.register(QChatSectionView.self, forHeaderFooterViewReuseIdentifier: "\(QChatSectionView.self)") - } - - func loadData() { - dataList.append(Channel(sectionName: localizable("channel_name"), contentName: localizable("input_channel_name"))) - dataList.append(Channel(sectionName: localizable("channel_topic"), contentName: localizable("input_channel_topic"))) - dataList.append(Channel(sectionName: localizable("channel_type"), contentName: localizable("public"))) - } - - func numberOfSections(in tableView: UITableView) -> Int { - return dataList.count - } - - public override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return 1 - } - - public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - if (indexPath.section == 0) { - let cell = tableView.dequeueReusableCell(withIdentifier: "\(QChatTextEditCell.self)", for: indexPath) as! QChatTextEditCell - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight).union(CornerType.topLeft).union(CornerType.topRight) - cell.textFied.placeholder = dataList[indexPath.section].contentName - cell.delegate = self - cell.textFied.tag = 11 - return cell - }else if(indexPath.section == 1){ - let cell = tableView.dequeueReusableCell(withIdentifier: "\(QChatTextEditCell.self)", for: indexPath) as! QChatTextEditCell - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight).union(CornerType.topLeft).union(CornerType.topRight) - cell.textFied.placeholder = dataList[indexPath.section].contentName - cell.delegate = self - cell.textFied.tag = 12 - return cell - }else { - let cell = tableView.dequeueReusableCell(withIdentifier: "\(QChatTextArrowCell.self)", for: indexPath) as! QChatTextArrowCell - cell.titleLabel.text = dataList[indexPath.section].contentName - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight).union(CornerType.topLeft).union(CornerType.topRight) - return cell - } - } - - func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { - let sectionView = tableView.dequeueReusableHeaderFooterView(withIdentifier: "\(QChatSectionView.self)") as! QChatSectionView - sectionView.titleLable.text = dataList[section].sectionName - return sectionView + public init(serverId: UInt64) { + viewModel = QChatChannelViewModel(serverId: serverId) + super.init(nibName: nil, bundle: nil) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override public func viewDidLoad() { + super.viewDidLoad() + commonUI() + loadData() + } + + func commonUI() { + title = localizable("create_channel") + navigationItem.rightBarButtonItem = UIBarButtonItem( + title: localizable("create"), + style: .plain, + target: self, + action: #selector(createChannel) + ) + navigationItem.leftBarButtonItem = UIBarButtonItem( + title: localizable("cancel"), + style: .plain, + target: self, + action: #selector(cancelEvent) + ) + navigationItem.rightBarButtonItem?.tintColor = .ne_greyText + tableView.register( + QChatTextEditCell.self, + forCellReuseIdentifier: "\(QChatTextEditCell.self)" + ) + tableView.register( + QChatTextArrowCell.self, + forCellReuseIdentifier: "\(QChatTextArrowCell.self)" + ) + tableView.register( + QChatSectionView.self, + forHeaderFooterViewReuseIdentifier: "\(QChatSectionView.self)" + ) + } + + func loadData() { + dataList + .append(Channel(sectionName: localizable("channel_name"), + contentName: localizable("input_channel_name"))) + dataList.append(Channel( + sectionName: localizable("channel_topic"), + contentName: localizable("input_channel_topic") + )) + dataList + .append(Channel(sectionName: localizable("channel_type"), + contentName: localizable("public"))) + } + + func numberOfSections(in tableView: UITableView) -> Int { + dataList.count + } + + override public func tableView(_ tableView: UITableView, + numberOfRowsInSection section: Int) -> Int { + 1 + } + + override public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + if indexPath.section == 0 { + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatTextEditCell.self)", + for: indexPath + ) as! QChatTextEditCell + cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) + .union(CornerType.topLeft).union(CornerType.topRight) + cell.textFied.placeholder = dataList[indexPath.section].contentName + cell.delegate = self + cell.textFied.tag = 11 + return cell + } else if indexPath.section == 1 { + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatTextEditCell.self)", + for: indexPath + ) as! QChatTextEditCell + cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) + .union(CornerType.topLeft).union(CornerType.topRight) + cell.textFied.placeholder = dataList[indexPath.section].contentName + cell.delegate = self + cell.textFied.tag = 12 + return cell + } else { + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatTextArrowCell.self)", + for: indexPath + ) as! QChatTextArrowCell + cell.titleLabel.text = dataList[indexPath.section].contentName + cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) + .union(CornerType.topLeft).union(CornerType.topRight) + return cell } - - func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - if indexPath.section == 2 { - // select channel type - let vc = QChatChannelTypeVC() - vc.delegate = self - vc.isPrivate = viewModel?.isPrivate ?? false - self.navigationController?.pushViewController(vc, animated: true) - } + } + + func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { + let sectionView = tableView + .dequeueReusableHeaderFooterView( + withIdentifier: "\(QChatSectionView.self)" + ) as! QChatSectionView + sectionView.titleLable.text = dataList[section].sectionName + return sectionView + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + if indexPath.section == 2 { + // select channel type + let vc = QChatChannelTypeVC() + vc.delegate = self + vc.isPrivate = viewModel?.isPrivate ?? false + navigationController?.pushViewController(vc, animated: true) } - + } + // MARK: event - @objc func createChannel() { - - if !isCreatedChannel { - isCreatedChannel = true - weak var weakSelf = self - viewModel?.createChannel({ error, channel in - NELog.errorLog("QChatChannelViewController", desc: "error:\(error?.localizedDescription) channel:\(channel)") - if error == nil { - // success to chatVC - self.navigationController?.dismiss(animated: true, completion: { - NotificationCenter.default.post(name: NotificationName.createChannel, object: channel) - }) - }else { - self.view.makeToast(error?.localizedDescription) { didTap in - self.navigationController?.dismiss(animated: true, completion: nil) - } - } - }) - } + @objc func createChannel() { + + guard let name = viewModel?.name,name.count > 0 else { + self.showToast("频道名称不能为空") + return + } + + if !isCreatedChannel { + isCreatedChannel = true + viewModel?.createChannel { error, channel in + NELog.errorLog( + "QChatChannelViewController", + desc: "error:\(error?.localizedDescription) channel:\(channel)" + ) + if error == nil { + // success to chatVC + self.navigationController?.dismiss(animated: true, completion: { + NotificationCenter.default.post( + name: NotificationName.createChannel, + object: channel + ) + }) + } else { + self.view.makeToast(error?.localizedDescription) { didTap in + self.navigationController?.dismiss(animated: true, completion: nil) + } + } + } } - - @objc func cancelEvent() { - print(#function) - self.dismiss(animated: true, completion: nil) - } - + } + + @objc func cancelEvent() { + print(#function) + dismiss(animated: true, completion: nil) + } + // MARK: QChatTextEditCellDelegate - func textDidChange(_ textField: UITextField) { - print("textFieldDidChangeSelection textField:\(textField.text)") - if textField.tag == 11 { - if textField.text?.count == 0 { - self.navigationItem.rightBarButtonItem?.tintColor = .ne_greyText - }else { - if var str = textField.text, str.count > 50 { - str = str.substring(to: str.index(str.startIndex, offsetBy: 50)) - print("str:\(str)") - textField.text = str - } - self.navigationItem.rightBarButtonItem?.tintColor = .ne_blueText - } - viewModel?.name = textField.text - }else if textField.tag == 12 { - if var str = textField.text, str.count > 64 { - str = str.substring(to: str.index(str.startIndex, offsetBy: 64)) - print("str:\(str)") - textField.text = str - } - viewModel?.topic = textField.text + + func textDidChange(_ textField: UITextField) { + print("textFieldDidChangeSelection textField:\(textField.text)") + if textField.tag == 11 { + if textField.text?.count == 0 { + navigationItem.rightBarButtonItem?.tintColor = .ne_greyText + } else { + if var str = textField.text, str.count > 50 { + str = str.substring(to: str.index(str.startIndex, offsetBy: 50)) + print("str:\(str)") + textField.text = str } + navigationItem.rightBarButtonItem?.tintColor = .ne_blueText + } + viewModel?.name = textField.text + } else if textField.tag == 12 { + if var str = textField.text, str.count > 64 { + str = str.substring(to: str.index(str.startIndex, offsetBy: 64)) + print("str:\(str)") + textField.text = str + } + viewModel?.topic = textField.text } - + } + // MARK: QChatChannelTypeVCDelegate - func didSelected(type: Int) { - viewModel?.isPrivate = type == 0 ? false : true - if dataList.count >= 3 { - dataList.removeLast() - dataList.append(Channel(sectionName: localizable("channel_type"), contentName: type == 0 ? localizable("public") : localizable("private"))) - self.tableView.reloadData() - } + + func didSelected(type: Int) { + viewModel?.isPrivate = type == 0 ? false : true + if dataList.count >= 3 { + dataList.removeLast() + dataList.append(Channel( + sectionName: localizable("channel_type"), + contentName: type == 0 ? localizable("public") : localizable("private") + )) + tableView.reloadData() } - + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatGroupPermissionSettingVC.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatGroupPermissionSettingVC.swift index de8f8475..da057a5b 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatGroupPermissionSettingVC.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatGroupPermissionSettingVC.swift @@ -1,132 +1,155 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCoreIM -typealias channelUpdateSettingBlock = (_ channelRole: ChannelRole?) -> () +typealias channelUpdateSettingBlock = (_ channelRole: ChannelRole?) -> Void -public class QChatGroupPermissionSettingVC: QChatTableViewController, QChatPermissionSettingCellDelegate { +public class QChatGroupPermissionSettingVC: QChatTableViewController, + QChatPermissionSettingCellDelegate { // public var didUpdateBlock: channelUpdateSettingBlock? - public var cRole: ChannelRole? - private var commonAuths = [RoleStatusInfoExt]() - private var messageAuths = [RoleStatusInfoExt]() - private var memberAuths = [RoleStatusInfoExt]() - private var auths = [[RoleStatusInfoExt]]() + public var cRole: ChannelRole? + private var commonAuths = [RoleStatusInfoExt]() + private var messageAuths = [RoleStatusInfoExt]() + private var memberAuths = [RoleStatusInfoExt]() + private var auths = [[RoleStatusInfoExt]]() - public init(cRole:ChannelRole?) { - super.init(nibName: nil, bundle: nil) - self.cRole = cRole - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - public override func viewDidLoad() { - super.viewDidLoad() - if let name = self.cRole?.name { - self.title = name + localizable("authority_setting") - }else { - self.title = localizable("authority_setting") - } - self.tableView.register(QChatPermissionSettingCell.self, forCellReuseIdentifier: "\(QChatPermissionSettingCell.self)") - self.tableView.register(QChatSectionView.self, forHeaderFooterViewReuseIdentifier: "\(QChatSectionView.self)") - self.tableView.sectionHeaderHeight = 42 - self.tableView.rowHeight = 48 - reloadData() + public init(cRole: ChannelRole?) { + super.init(nibName: nil, bundle: nil) + self.cRole = cRole + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override public func viewDidLoad() { + super.viewDidLoad() + if let name = cRole?.name { + title = name + localizable("authority_setting") + } else { + title = localizable("authority_setting") } - - private func reloadData() { - if let auths = self.cRole?.auths { - for auth in auths { - var authExt = RoleStatusInfoExt(status: auth) - let key = "auth" + String(auth.type.rawValue) - authExt.title = localizable(key) - switch auth.type { - case .ManageChannel: - commonAuths.insert(authExt, at: 0) - case .ManageRole: - commonAuths.append(authExt) - case .SendMsg: - messageAuths.append(authExt) + tableView.register( + QChatPermissionSettingCell.self, + forCellReuseIdentifier: "\(QChatPermissionSettingCell.self)" + ) + tableView.register( + QChatSectionView.self, + forHeaderFooterViewReuseIdentifier: "\(QChatSectionView.self)" + ) + tableView.sectionHeaderHeight = 42 + tableView.rowHeight = 48 + reloadData() + } + + private func reloadData() { + if let auths = cRole?.auths { + for auth in auths { + var authExt = RoleStatusInfoExt(status: auth) + let key = "auth" + String(auth.type.rawValue) + authExt.title = localizable(key) + switch auth.type { + case .ManageChannel: + commonAuths.insert(authExt, at: 0) + case .ManageRole: + commonAuths.append(authExt) + case .SendMsg: + messageAuths.append(authExt) // case .DeleteOtherMsg: // messageAuths.append(authExt) // case .RevokeMsg: // messageAuths.append(authExt) - case .BlackWhiteList: - memberAuths.append(authExt) - default: - break - } - } - if !commonAuths.isEmpty { - self.auths.append(commonAuths) - } - if !messageAuths.isEmpty { - self.auths.append(messageAuths) - } - if !memberAuths.isEmpty { - self.auths.append(memberAuths) - } - self.tableView.reloadData() - } - } - - func numberOfSections(in tableView: UITableView) -> Int { - return self.auths.count - } - - public override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return self.auths[section].count - } - - public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(withIdentifier: "\(QChatPermissionSettingCell.self)", for: indexPath) as! QChatPermissionSettingCell - let auths = self.auths[indexPath.section] - let authExt = auths[indexPath.row] - cell.updateModel(model: authExt) - cell.delegate = self - if indexPath.row == 0 { - cell.cornerType = CornerType.topLeft.union(CornerType.topRight) - }else if indexPath.row == auths.count - 1 { - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) + case .BlackWhiteList: + memberAuths.append(authExt) + default: + break } - return cell + } + if !commonAuths.isEmpty { + self.auths.append(commonAuths) + } + if !messageAuths.isEmpty { + self.auths.append(messageAuths) + } + if !memberAuths.isEmpty { + self.auths.append(memberAuths) + } + tableView.reloadData() } - - func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { - let view = tableView.dequeueReusableHeaderFooterView(withIdentifier: "\(QChatSectionView.self)") as? QChatSectionView - if section == 0 { - view?.titleLable.text = localizable("qchat_common_permission") - }else if section == 1 { - view?.titleLable.text = localizable("qchat_message_permission") - }else { - view?.titleLable.text = localizable("qchat_member_permission") - } - return view + } + + func numberOfSections(in tableView: UITableView) -> Int { + auths.count + } + + override public func tableView(_ tableView: UITableView, + numberOfRowsInSection section: Int) -> Int { + auths[section].count + } + + override public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatPermissionSettingCell.self)", + for: indexPath + ) as! QChatPermissionSettingCell + let auths = auths[indexPath.section] + let authExt = auths[indexPath.row] + cell.updateModel(model: authExt) + cell.delegate = self + if indexPath.row == 0 { + cell.cornerType = CornerType.topLeft.union(CornerType.topRight) + } else if indexPath.row == auths.count - 1 { + cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) } - - func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { - return 42 + return cell + } + + func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { + let view = tableView + .dequeueReusableHeaderFooterView( + withIdentifier: "\(QChatSectionView.self)" + ) as? QChatSectionView + if section == 0 { + view?.titleLable.text = localizable("qchat_common_permission") + } else if section == 1 { + view?.titleLable.text = localizable("qchat_message_permission") + } else { + view?.titleLable.text = localizable("qchat_member_permission") } - - // MARK:QChatPermissionSettingCellDelegate - func didSelected(cell: QChatPermissionSettingCell?, model: RoleStatusInfo?) { - if let auth = model { - let param = UpdateChannelRoleParam(serverId: self.cRole?.serverId, channelId: self.cRole?.channelId, roleId: self.cRole?.roleId, commands: [auth]) - QChatRoleProvider.shared.updateChannelRole(param: param) {[weak self] error, channelRole in - if error != nil { - self?.view.makeToast(error?.localizedDescription) - cell?.selectedSuccess(success: false) - }else { - cell?.selectedSuccess(success: true) + return view + } + + func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { + 42 + } + + // MARK: QChatPermissionSettingCellDelegate + + func didSelected(cell: QChatPermissionSettingCell?, model: RoleStatusInfo?) { + if let auth = model { + let param = UpdateChannelRoleParam( + serverId: cRole?.serverId, + channelId: cRole?.channelId, + roleId: cRole?.roleId, + commands: [auth] + ) + QChatRoleProvider.shared + .updateChannelRole(param: param) { [weak self] error, channelRole in + if error != nil { + self?.view.makeToast(error?.localizedDescription) + cell?.selectedSuccess(success: false) + } else { + cell?.selectedSuccess(success: true) // if let block = self?.didUpdateBlock { // block(channelRole) // } - } - } + } } } + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatMemberPermissionSettingVC.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatMemberPermissionSettingVC.swift index 81eb5048..6f8a8b97 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatMemberPermissionSettingVC.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatMemberPermissionSettingVC.swift @@ -1,161 +1,189 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCoreIM -typealias updateSettingBlock = (_ memberRole: MemberRole?) -> () -public class QChatMemberPermissionSettingVC: QChatTableViewController, QChatPermissionSettingCellDelegate { - public var channel: ChatChannel? - public var memberRole: MemberRole? +typealias updateSettingBlock = (_ memberRole: MemberRole?) -> Void +public class QChatMemberPermissionSettingVC: QChatTableViewController, + QChatPermissionSettingCellDelegate { + public var channel: ChatChannel? + public var memberRole: MemberRole? // public var didUpdateBlock: updateSettingBlock? - private var commonAuths = [RoleStatusInfoExt]() - private var messageAuths = [RoleStatusInfoExt]() - private var memberAuths = [RoleStatusInfoExt]() + private var commonAuths = [RoleStatusInfoExt]() + private var messageAuths = [RoleStatusInfoExt]() + private var memberAuths = [RoleStatusInfoExt]() - private var auths = [[Any]]() + private var auths = [[Any]]() - init(channel: ChatChannel?, memberRole: MemberRole?) { - super.init(nibName: nil, bundle: nil) - self.channel = channel - self.memberRole = memberRole - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - public override func viewDidLoad() { - super.viewDidLoad() - self.title = localizable("member_permission_setting") - self.tableView.register(QChatPermissionSettingCell.self, forCellReuseIdentifier: "\(QChatPermissionSettingCell.self)") - self.tableView.register(QChatImageTextCell.self, forCellReuseIdentifier: "\(QChatImageTextCell.self)") - self.tableView.register(QChatSectionView.self, forHeaderFooterViewReuseIdentifier: "\(QChatSectionView.self)") - self.tableView.sectionHeaderHeight = 42 - self.tableView.rowHeight = 48 - reloadData() - - } - - private func reloadData() { - let members = [self.memberRole] - self.auths.append(members as [Any]) - - if let auths = self.memberRole?.auths { - for auth in auths { - var authExt = RoleStatusInfoExt(status: auth) - let key = "auth" + String(auth.type.rawValue) - authExt.title = localizable(key) - switch auth.type { - case .ManageChannel: - commonAuths.insert(authExt, at: 0) - case .ManageRole: - commonAuths.append(authExt) - case .SendMsg: - messageAuths.append(authExt) + init(channel: ChatChannel?, memberRole: MemberRole?) { + super.init(nibName: nil, bundle: nil) + self.channel = channel + self.memberRole = memberRole + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override public func viewDidLoad() { + super.viewDidLoad() + title = localizable("member_permission_setting") + tableView.register( + QChatPermissionSettingCell.self, + forCellReuseIdentifier: "\(QChatPermissionSettingCell.self)" + ) + tableView.register( + QChatImageTextCell.self, + forCellReuseIdentifier: "\(QChatImageTextCell.self)" + ) + tableView.register( + QChatSectionView.self, + forHeaderFooterViewReuseIdentifier: "\(QChatSectionView.self)" + ) + tableView.sectionHeaderHeight = 42 + tableView.rowHeight = 48 + reloadData() + } + + private func reloadData() { + let members = [memberRole] + auths.append(members as [Any]) + + if let auths = memberRole?.auths { + for auth in auths { + var authExt = RoleStatusInfoExt(status: auth) + let key = "auth" + String(auth.type.rawValue) + authExt.title = localizable(key) + switch auth.type { + case .ManageChannel: + commonAuths.insert(authExt, at: 0) + case .ManageRole: + commonAuths.append(authExt) + case .SendMsg: + messageAuths.append(authExt) // case .DeleteOtherMsg: // messageAuths.append(authExt) // case .RevokeMsg: // messageAuths.append(authExt) - case .BlackWhiteList: - memberAuths.append(authExt) - default: - break - } - } - - if !commonAuths.isEmpty { - self.auths.append(commonAuths) - } - if !messageAuths.isEmpty { - self.auths.append(messageAuths) - } - if !memberAuths.isEmpty { - self.auths.append(memberAuths) - } + case .BlackWhiteList: + memberAuths.append(authExt) + default: + break } - self.tableView.reloadData() - } - - func numberOfSections(in tableView: UITableView) -> Int { - return self.auths.count - } - - public override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return self.auths[section].count + } + + if !commonAuths.isEmpty { + self.auths.append(commonAuths) + } + if !messageAuths.isEmpty { + self.auths.append(messageAuths) + } + if !memberAuths.isEmpty { + self.auths.append(memberAuths) + } } - - public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - if indexPath.section == 0 { - //用户 - let cell = tableView.dequeueReusableCell(withIdentifier: "\(QChatImageTextCell.self)", for: indexPath) as! QChatImageTextCell - let members = self.auths[indexPath.section] - let m = members[indexPath.row] as? MemberRole - cell.setup(accid: m?.accid, nickName: m?.nick) - if indexPath.row == 0 { - cell.cornerType = CornerType.topLeft.union(CornerType.topRight) - }else if indexPath.row == auths.count - 1 { - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) - } - return cell - }else { - let cell = tableView.dequeueReusableCell(withIdentifier: "\(QChatPermissionSettingCell.self)", for: indexPath) as! QChatPermissionSettingCell - let auths = self.auths[indexPath.section] - let authExt = auths[indexPath.row] as? RoleStatusInfoExt - cell.updateModel(model: authExt) - cell.delegate = self - if indexPath.row == 0 { - cell.cornerType = CornerType.topLeft.union(CornerType.topRight) - }else if indexPath.row == auths.count - 1 { - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) - } - return cell - } + tableView.reloadData() + } + + func numberOfSections(in tableView: UITableView) -> Int { + auths.count + } + + override public func tableView(_ tableView: UITableView, + numberOfRowsInSection section: Int) -> Int { + auths[section].count + } + + override public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + if indexPath.section == 0 { + // 用户 + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatImageTextCell.self)", + for: indexPath + ) as! QChatImageTextCell + let members = auths[indexPath.section] + let m = members[indexPath.row] as? MemberRole + cell.setup(accid: m?.accid, nickName: m?.nick) + if indexPath.row == 0 { + cell.cornerType = CornerType.topLeft.union(CornerType.topRight) + } else if indexPath.row == auths.count - 1 { + cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) + } + return cell + } else { + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatPermissionSettingCell.self)", + for: indexPath + ) as! QChatPermissionSettingCell + let auths = auths[indexPath.section] + let authExt = auths[indexPath.row] as? RoleStatusInfoExt + cell.updateModel(model: authExt) + cell.delegate = self + if indexPath.row == 0 { + cell.cornerType = CornerType.topLeft.union(CornerType.topRight) + } else if indexPath.row == auths.count - 1 { + cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) + } + return cell } - - func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { - let view = tableView.dequeueReusableHeaderFooterView(withIdentifier: "\(QChatSectionView.self)") as? QChatSectionView - if section == 1 { - view?.titleLable.text = localizable("qchat_common_permission") - }else if section == 2 { - view?.titleLable.text = localizable("qchat_message_permission") - }else if section == 3 { - view?.titleLable.text = localizable("qchat_member_permission") - } - return view + } + + func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { + let view = tableView + .dequeueReusableHeaderFooterView( + withIdentifier: "\(QChatSectionView.self)" + ) as? QChatSectionView + if section == 1 { + view?.titleLable.text = localizable("qchat_common_permission") + } else if section == 2 { + view?.titleLable.text = localizable("qchat_message_permission") + } else if section == 3 { + view?.titleLable.text = localizable("qchat_member_permission") } - - func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - if indexPath.section == 0 { - return 56 - }else { - return 48 - } + return view + } + + func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { + if indexPath.section == 0 { + return 56 + } else { + return 48 } - - func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { - if section == 0 { - return 0 - } - return 42 + } + + func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { + if section == 0 { + return 0 } - -// MARK:QChatPermissionSettingCellDelegate - func didSelected(cell: QChatPermissionSettingCell?, model: RoleStatusInfo?) { - if let auth = model { - let param = UpdateMemberRoleParam(serverId: self.channel?.serverId, channelId: self.channel?.channelId, accid: self.memberRole?.accid, commands: [auth]) - QChatRoleProvider.shared.updateMemberRole(param: param) {[weak self] error, memberRole in - if error != nil { - self?.view.makeToast(error?.localizedDescription) - cell?.selectedSuccess(success: false) - }else { - cell?.selectedSuccess(success: true) + return 42 + } + +// MARK: QChatPermissionSettingCellDelegate + + func didSelected(cell: QChatPermissionSettingCell?, model: RoleStatusInfo?) { + if let auth = model { + let param = UpdateMemberRoleParam( + serverId: channel?.serverId, + channelId: channel?.channelId, + accid: memberRole?.accid, + commands: [auth] + ) + QChatRoleProvider.shared + .updateMemberRole(param: param) { [weak self] error, memberRole in + if error != nil { + self?.view.makeToast(error?.localizedDescription) + cell?.selectedSuccess(success: false) + } else { + cell?.selectedSuccess(success: true) // if let block = self?.didUpdateBlock { // block(memberRole) // } - } - } + } } } + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatSearchVC.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatSearchVC.swift index b88c00eb..f12f898f 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatSearchVC.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatSearchVC.swift @@ -1,19 +1,20 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit public class QChatSearchVC: NEBaseViewController, UITableViewDelegate, UITableViewDataSource { - var textField = UITextField() - var tableView = UITableView(frame: .zero, style: .plain) - - public override func viewDidLoad() { - super.viewDidLoad() - commonUI() - } - - func commonUI() { + var textField = UITextField() + var tableView = UITableView(frame: .zero, style: .plain) + + override public func viewDidLoad() { + super.viewDidLoad() + commonUI() + } + + func commonUI() { // textField.placeholder = "ddd"; // textField.leftView = UIImageView(image: UIImage.ne_imageNamed(name: "search")) // textField.leftViewMode = .always @@ -37,41 +38,47 @@ public class QChatSearchVC: NEBaseViewController, UITableViewDelegate, UITableVi // textField.heightAnchor.constraint(equalToConstant: 32), // ]) // } - self.tableView.separatorStyle = .none - self.tableView.delegate = self - self.tableView.dataSource = self - self.tableView.translatesAutoresizingMaskIntoConstraints = false - self.view.addSubview(self.tableView) - if #available(iOS 11.0, *) { - NSLayoutConstraint.activate([ - self.tableView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor), - self.tableView.leftAnchor.constraint(equalTo: self.view.leftAnchor), - self.tableView.rightAnchor.constraint(equalTo: self.view.rightAnchor), - self.tableView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor), - ]) - }else { - NSLayoutConstraint.activate([ - self.tableView.topAnchor.constraint(equalTo: self.textField.bottomAnchor), - self.tableView.leftAnchor.constraint(equalTo: self.view.leftAnchor), - self.tableView.rightAnchor.constraint(equalTo: self.view.rightAnchor), - self.tableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor), - ]) - } - self.tableView.sectionHeaderHeight = 0 - self.tableView.sectionFooterHeight = 0 - self.tableView.rowHeight = 40 - self.tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.1)) - self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "\(UITableViewCell.self)") - } - -// MARK:UITableViewDataSource - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return 0; - } - - public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(withIdentifier: "\(UITableViewCell.self)", for: indexPath) - return cell + tableView.separatorStyle = .none + tableView.delegate = self + tableView.dataSource = self + tableView.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(tableView) + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + self.tableView.topAnchor + .constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor), + self.tableView.leftAnchor.constraint(equalTo: self.view.leftAnchor), + self.tableView.rightAnchor.constraint(equalTo: self.view.rightAnchor), + self.tableView.bottomAnchor + .constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor), + ]) + } else { + NSLayoutConstraint.activate([ + tableView.topAnchor.constraint(equalTo: textField.bottomAnchor), + tableView.leftAnchor.constraint(equalTo: view.leftAnchor), + tableView.rightAnchor.constraint(equalTo: view.rightAnchor), + tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), + ]) } + tableView.sectionHeaderHeight = 0 + tableView.sectionFooterHeight = 0 + tableView.rowHeight = 40 + tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.1)) + tableView.register(UITableViewCell.self, forCellReuseIdentifier: "\(UITableViewCell.self)") + } + +// MARK: UITableViewDataSource + + public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + 0 + } + public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(UITableViewCell.self)", + for: indexPath + ) + return cell + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatWhiteBlackListVC.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatWhiteBlackListVC.swift index 8a0d3375..b9824d1c 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatWhiteBlackListVC.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewController/QChatWhiteBlackListVC.swift @@ -1,207 +1,255 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCoreIM import NEKitCore public class QChatWhiteBlackListVC: QChatTableViewController, QChatMemberSelectControllerDelegate { - public var type: RoleType = .white - public var channel: ChatChannel? - private var memberArray: [ServerMemeber]? - private var isEdited: Bool = false - - public override func viewDidLoad() { - super.viewDidLoad() - self.isEdited = false - self.title = self.type == .white ? localizable("white_list") : localizable("black_list") - self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: localizable("qchat_edit"), style: .plain, target: self, action: #selector(edit)) - - tableView.backgroundColor = .white - tableView.sectionHeaderHeight = 0 - tableView.sectionFooterHeight = 0 - tableView.register(QChatTextCell.self, forCellReuseIdentifier: "\(QChatTextCell.self)") - tableView.register(QChatImageTextCell.self, forCellReuseIdentifier: "\(QChatImageTextCell.self)") - loadData() - } - - func loadData() { - let type: ChannelMemberRoleType = self.type == .white ? .white : .black - let param = GetChannelBlackWhiteMembers(serverId: self.channel?.serverId, channelId: self.channel?.channelId, timeTag: 0, limit: 50, type: type) - QChatChannelProvider.shared.getBlackWhiteMembersByPage(param: param) {[weak self] error, result in - self?.memberArray = result?.memberArray - self?.tableView.reloadData() - } - } - func numberOfSections(in tableView: UITableView) -> Int { - return 2 - } + public var type: RoleType = .white + public var channel: ChatChannel? + private var memberArray: [ServerMemeber]? + private var isEdited: Bool = false - public override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - if section == 0 { - return 1 - }else { - return self.memberArray?.count ?? 0 - } + override public func viewDidLoad() { + super.viewDidLoad() + isEdited = false + title = type == .white ? localizable("white_list") : localizable("black_list") + navigationItem.rightBarButtonItem = UIBarButtonItem( + title: localizable("qchat_edit"), + style: .plain, + target: self, + action: #selector(edit) + ) + + tableView.backgroundColor = .white + tableView.sectionHeaderHeight = 0 + tableView.sectionFooterHeight = 0 + tableView.register(QChatTextCell.self, forCellReuseIdentifier: "\(QChatTextCell.self)") + tableView.register( + QChatImageTextCell.self, + forCellReuseIdentifier: "\(QChatImageTextCell.self)" + ) + loadData() + } + + func loadData() { + let type: ChannelMemberRoleType = type == .white ? .white : .black + let param = GetChannelBlackWhiteMembers( + serverId: channel?.serverId, + channelId: channel?.channelId, + timeTag: 0, + limit: 50, + type: type + ) + QChatChannelProvider.shared + .getBlackWhiteMembersByPage(param: param) { [weak self] error, result in + self?.memberArray = result?.memberArray + self?.tableView.reloadData() + } + } + + func numberOfSections(in tableView: UITableView) -> Int { + 2 + } + + override public func tableView(_ tableView: UITableView, + numberOfRowsInSection section: Int) -> Int { + if section == 0 { + return 1 + } else { + return memberArray?.count ?? 0 } - - public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - if indexPath.section == 0 { - let cell = tableView.dequeueReusableCell(withIdentifier: "\(QChatTextCell.self)", for: indexPath) as! QChatTextCell - cell.backgroundColor = .white - cell.rightStyle = .indicate - cell.titleLabel.text = localizable("qchat_add_member") - return cell - }else { - let cell = tableView.dequeueReusableCell(withIdentifier: "\(QChatImageTextCell.self)", for: indexPath) as! QChatImageTextCell - cell.backgroundColor = .white - let member = self.memberArray?[indexPath.row] - cell.setup(accid: member?.accid, nickName: member?.nick) - cell.rightStyle = self.isEdited ? .delete : .none + } + + override public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + if indexPath.section == 0 { + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatTextCell.self)", + for: indexPath + ) as! QChatTextCell + cell.backgroundColor = .white + cell.rightStyle = .indicate + cell.titleLabel.text = localizable("qchat_add_member") + return cell + } else { + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatImageTextCell.self)", + for: indexPath + ) as! QChatImageTextCell + cell.backgroundColor = .white + let member = memberArray?[indexPath.row] + cell.setup(accid: member?.accid, nickName: member?.nick) + cell.rightStyle = isEdited ? .delete : .none // if CoreKitEngine.instance.imAccid == member?.accid, self.type == .white { // cell.rightStyle = .none // } - if IMKitLoginManager.instance.imAccid == member?.accid,self.type == .white { - cell.rightStyle = .none - } - return cell - } + if IMKitLoginManager.instance.imAccid == member?.accid, type == .white { + cell.rightStyle = .none + } + return cell } - - func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - if indexPath.section == 0 { - //present add memeber VC - let memberSelect = QChatMemberSelectController() - memberSelect.serverId = self.channel?.serverId + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + if indexPath.section == 0 { + // present add memeber VC + let memberSelect = QChatMemberSelectController() + memberSelect.serverId = channel?.serverId // memberSelect.selectType = .ServerMember - memberSelect.delegate = self - memberSelect.completion = {[weak self] datas in - // 选中成员 - print("选中成员:datas:\(datas)") - if datas.count > 0 { - var seletedMembers = [ServerMemeber]() - for data in datas { - if let m = data.serverMember { - seletedMembers.append(m) - } - } - self?.addMemberList(members: seletedMembers, type:self?.type ?? .white, { error in - if error != nil { - self?.view.makeToast(error?.localizedDescription) - }else { - for m in seletedMembers { - self?.memberArray?.append(m) - } - self?.tableView.reloadData() - } - }) - } + memberSelect.delegate = self + memberSelect.completion = { [weak self] datas in + // 选中成员 + print("选中成员:datas:\(datas)") + if datas.count > 0 { + var seletedMembers = [ServerMemeber]() + for data in datas { + if let m = data.serverMember { + seletedMembers.append(m) } - navigationController?.pushViewController(memberSelect, animated: true) - }else { - if self.isEdited { - guard let member = self.memberArray?[indexPath.row] else { - return + } + self? + .addMemberList(members: seletedMembers, type: self?.type ?? .white) { error in + if error != nil { + self?.view.makeToast(error?.localizedDescription) + } else { + for m in seletedMembers { + self?.memberArray?.append(m) } - + self?.tableView.reloadData() + } + } + } + } + navigationController?.pushViewController(memberSelect, animated: true) + } else { + if isEdited { + guard let member = memberArray?[indexPath.row] else { + return + } + // if CoreKitEngine.instance.imAccid == member.accid, self.type == .white { // return // } - - if IMKitLoginManager.instance.imAccid == member.accid,self.type == .white { - return + + if IMKitLoginManager.instance.imAccid == member.accid, type == .white { + return + } + + let name = (member.nick != nil ? member.nick : member.accid) ?? "" + let message = localizable("confirm_delete_channel") + name + + localizable("qchat_member") + "?" + let alertVC = UIAlertController.reconfimAlertView( + title: localizable("removeMember"), + message: message + ) { + let members = [member] + self.removeMemberList(members: members, type: self.type) { [weak self] error in + if error != nil { + self?.view.makeToast(error?.localizedDescription) + } else { + if var members = self?.memberArray { + var index = -1 + for (i, m) in members.enumerated() { + if m.accid == member.accid { + index = i + break + } } - - let name = (member.nick != nil ? member.nick : member.accid) ?? "" - let message = localizable("confirm_delete_channel") + name + localizable("qchat_member") + "?" - let alertVC = UIAlertController.reconfimAlertView(title: localizable("removeMember"), message: message) { - let members = [member] - self.removeMemberList(members: members, type: self.type) {[weak self] error in - if error != nil { - self?.view.makeToast(error?.localizedDescription) - }else { - if var members = self?.memberArray { - var index = -1 - for (i, m) in members.enumerated() { - if m.accid == member.accid { - index = i - break - } - } - if index >= 0 { - members.remove(at: index) - self?.memberArray = members - self?.tableView.reloadData() - } - - } - } - } + if index >= 0 { + members.remove(at: index) + self?.memberArray = members + self?.tableView.reloadData() } - self.present(alertVC, animated: true, completion: nil) + } } + } } + present(alertVC, animated: true, completion: nil) + } } - - // 添加黑白名单 - private func addMemberList(members:[ServerMemeber]?, type: RoleType, _ completion: @escaping (NSError?)-> ()) { - guard let ms = members else { - return - } - var accids = [String]() - for m in ms { - accids.append(m.accid ?? "") - } - let param = UpdateChannelBlackWhiteMembersParam(serverId: self.channel?.serverId, channelId: self.channel?.channelId, type: type == .white ? .white : .black, opeType: .add, accids: accids) - QChatChannelProvider.shared.updateBlackWhiteMembers(param: param, completion) + } + + // 添加黑白名单 + private func addMemberList(members: [ServerMemeber]?, type: RoleType, + _ completion: @escaping (NSError?) -> Void) { + guard let ms = members else { + return } - - // 移除黑白名单 - private func removeMemberList(members:[ServerMemeber]?, type: RoleType, _ completion: @escaping (NSError?)-> ()) { - guard let ms = members else { - return - } - var accids = [String]() - for m in ms { - if let id = m.accid { - accids.append(id) - } - } - let param = UpdateChannelBlackWhiteMembersParam(serverId: self.channel?.serverId, channelId: self.channel?.channelId, type: type == .white ? .white : .black, opeType: .remove, accids: accids) - QChatChannelProvider.shared.updateBlackWhiteMembers(param: param, completion) + var accids = [String]() + for m in ms { + accids.append(m.accid ?? "") } - - - // MARK: - event - @objc func edit() { - self.isEdited = !self.isEdited - if self.isEdited { - self.navigationItem.rightBarButtonItem?.title = localizable("qchat_save") - // TODO: reload data - }else { - self.navigationItem.rightBarButtonItem?.title = localizable("qchat_edit") - // TODO: reload data - } - self.tableView.reloadData() + let param = UpdateChannelBlackWhiteMembersParam( + serverId: channel?.serverId, + channelId: channel?.channelId, + type: type == .white ? .white : .black, + opeType: .add, + accids: accids + ) + QChatChannelProvider.shared.updateBlackWhiteMembers(param: param, completion) + } + + // 移除黑白名单 + private func removeMemberList(members: [ServerMemeber]?, type: RoleType, + _ completion: @escaping (NSError?) -> Void) { + guard let ms = members else { + return } - - public func filterMembers(accid: [String]?, _ filterMembers: @escaping ([String]?) -> ()) { - let type: ChannelMemberRoleType = self.type == .white ? .white : .black - let param = GetExistingChannelBlackWhiteMembersParam(serverId: self.channel?.serverId, channelId: self.channel?.channelId, type: type, accIds: accid) - QChatChannelProvider.shared.getExistingChannelBlackWhiteMembers(param: param) { error, result in - if let members = result?.memberArray, !members.isEmpty { - var accidArray = [String]() - for member in members { - if let id = member.accid { - accidArray.append(id) - } - } - filterMembers(accidArray) - }else { - filterMembers(nil) - } - } + var accids = [String]() + for m in ms { + if let id = m.accid { + accids.append(id) + } } + let param = UpdateChannelBlackWhiteMembersParam( + serverId: channel?.serverId, + channelId: channel?.channelId, + type: type == .white ? .white : .black, + opeType: .remove, + accids: accids + ) + QChatChannelProvider.shared.updateBlackWhiteMembers(param: param, completion) + } + + // MARK: - event + @objc func edit() { + isEdited = !isEdited + if isEdited { + navigationItem.rightBarButtonItem?.title = localizable("qchat_save") + // TODO: reload data + } else { + navigationItem.rightBarButtonItem?.title = localizable("qchat_edit") + // TODO: reload data + } + tableView.reloadData() + } + + public func filterMembers(accid: [String]?, _ filterMembers: @escaping ([String]?) -> Void) { + let type: ChannelMemberRoleType = type == .white ? .white : .black + let param = GetExistingChannelBlackWhiteMembersParam( + serverId: channel?.serverId, + channelId: channel?.channelId, + type: type, + accIds: accid + ) + QChatChannelProvider.shared + .getExistingChannelBlackWhiteMembers(param: param) { error, result in + if let members = result?.memberArray, !members.isEmpty { + var accidArray = [String]() + for member in members { + if let id = member.accid { + accidArray.append(id) + } + } + filterMembers(accidArray) + } else { + filterMembers(nil) + } + } + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewModel/QChatAuthoritySettingViewModel.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewModel/QChatAuthoritySettingViewModel.swift index 8c538a4c..f6592b13 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewModel/QChatAuthoritySettingViewModel.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewModel/QChatAuthoritySettingViewModel.swift @@ -1,187 +1,192 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NEKitCoreIM import NEKitQChat public class QChatAuthoritySettingViewModel { - public var channel: ChatChannel? - public var rolesData = QChatRoles() - public var membersData = QChatRoles() - - private var repo = QChatRepo() - - init(channel:ChatChannel?) { - self.channel = channel - } - - func firstGetChannelRoles(_ completion: @escaping (Error?, [RoleModel]?) -> Void) { - self.rolesData.timeTag = 0 - self.rolesData.roles = [RoleModel]() - getChannelRoles(completion) - } + public var channel: ChatChannel? + public var rolesData = QChatRoles() + public var membersData = QChatRoles() + + private var repo = QChatRepo() - func getChannelRoles(_ completion: @escaping (Error?, [RoleModel]?) -> Void) { - guard let sid = channel?.serverId, let cid = channel?.channelId else { - completion(NSError.paramError(), nil) - return + init(channel: ChatChannel?) { + self.channel = channel + } + + func firstGetChannelRoles(_ completion: @escaping (Error?, [RoleModel]?) -> Void) { + rolesData.timeTag = 0 + rolesData.roles = [RoleModel]() + getChannelRoles(completion) + } + + func getChannelRoles(_ completion: @escaping (Error?, [RoleModel]?) -> Void) { + guard let sid = channel?.serverId, let cid = channel?.channelId else { + completion(NSError.paramError(), nil) + return + } + var param = ChannelRoleParam(serverId: sid, channelId: cid) + param.limit = rolesData.pageSize + param.timeTag = rolesData.timeTag + repo.getChannelRoles(param) { [weak self] error, roleList in + print("error:\(error) roleList:\(roleList)") + if error != nil { + completion(error, self?.rolesData.roles) + } else { + // 移除占位 + if let last = self?.rolesData.roles.last, last.isPlacehold { + self?.rolesData.roles.removeLast() } - var param: ChannelRoleParam = ChannelRoleParam(serverId: sid, channelId: cid) - param.limit = self.rolesData.pageSize - param.timeTag = self.rolesData.timeTag - repo.getChannelRoles(param) {[weak self] error, roleList in - print("error:\(error) roleList:\(roleList)") - if error != nil { - completion(error, self?.rolesData.roles) - }else { - // 移除占位 - if let last = self?.rolesData.roles.last, last.isPlacehold { - self?.rolesData.roles.removeLast() - } - - if let roles = roleList, roles.count > 0 { - // 添加身份组 - for role in roles { - var model = RoleModel() - model.role = role - self?.rolesData.roles.append(model) - } - //记录最后一个身份组的时间戳 用于下页请求 - self?.rolesData.timeTag = self?.rolesData.roles.last?.role?.createTime - - //添加占位 - if roles.count >= self?.rolesData.pageSize ?? 5 { - var placeholdModel = RoleModel() - placeholdModel.title = localizable("more") - placeholdModel.isPlacehold = true - self?.rolesData.roles.append(placeholdModel) - } - self?.setRoundedCorner() - //设置圆角 - completion(error, self?.rolesData.roles) - }else { - //设置圆角 - self?.setRoundedCorner() - completion(error, self?.rolesData.roles) - } - } + + if let roles = roleList, roles.count > 0 { + // 添加身份组 + for role in roles { + var model = RoleModel() + model.role = role + self?.rolesData.roles.append(model) + } + // 记录最后一个身份组的时间戳 用于下页请求 + self?.rolesData.timeTag = self?.rolesData.roles.last?.role?.createTime + + // 添加占位 + if roles.count >= self?.rolesData.pageSize ?? 5 { + var placeholdModel = RoleModel() + placeholdModel.title = localizable("more") + placeholdModel.isPlacehold = true + self?.rolesData.roles.append(placeholdModel) + } + self?.setRoundedCorner() + // 设置圆角 + completion(error, self?.rolesData.roles) + } else { + // 设置圆角 + self?.setRoundedCorner() + completion(error, self?.rolesData.roles) } + } } - - func firstGetMembers(_ completion: @escaping (Error?, [RoleModel]?) -> Void) { - self.membersData.pageSize = 50 - self.membersData.timeTag = 0 - self.membersData.roles = [RoleModel]() - getMembers(completion) + } + + func firstGetMembers(_ completion: @escaping (Error?, [RoleModel]?) -> Void) { + membersData.pageSize = 50 + membersData.timeTag = 0 + membersData.roles = [RoleModel]() + getMembers(completion) + } + + func getMembers(_ completion: @escaping (Error?, [RoleModel]?) -> Void) { + guard let sid = channel?.serverId, let cid = channel?.channelId else { + completion(NSError.paramError(), nil) + return } - - func getMembers(_ completion: @escaping (Error?, [RoleModel]?) -> Void) { - guard let sid = channel?.serverId, let cid = channel?.channelId else { - completion(NSError.paramError(), nil) - return + var param = GetMemberRolesParam() + param.serverId = sid + param.channelId = cid + param.limit = membersData.pageSize + param.timeTag = membersData.timeTag + + repo.getMemberRoles(param: param) { [weak self] error, memberRoles in + print("error:\(error) memberArray:\(memberRoles)") + if error != nil { + completion(error, self?.membersData.roles) + } else { + // 移除占位 + if let last = self?.membersData.roles.last, last.isPlacehold { + self?.membersData.roles.removeLast() } - var param = GetMemberRolesParam() - param.serverId = sid - param.channelId = cid - param.limit = self.membersData.pageSize - param.timeTag = self.membersData.timeTag - - repo.getMemberRoles(param: param) {[weak self] error , memberRoles in - print("error:\(error) memberArray:\(memberRoles)") - if error != nil { - completion(error, self?.membersData.roles) - }else { - // 移除占位 - if let last = self?.membersData.roles.last, last.isPlacehold { - self?.membersData.roles.removeLast() - } - if let members = memberRoles, members.count > 0 { - // 添加成员 - for member in members { - var model = RoleModel() - model.member = member - self?.membersData.roles.append(model) - } - //记录最后一个身份组的时间戳 用于下页请求 - self?.membersData.timeTag = self?.membersData.roles.last?.member?.createTime - - //添加占位 - if members.count == self?.rolesData.pageSize { - var placeholdModel = RoleModel() - placeholdModel.title = localizable("more") - placeholdModel.isPlacehold = true - self?.membersData.roles.append(placeholdModel) - } - self?.setRoundedCorner() - //设置圆角 - completion(error, self?.membersData.roles) - }else { - //设置圆角 - self?.setRoundedCorner() - completion(error, self?.membersData.roles) - } - } + if let members = memberRoles, members.count > 0 { + // 添加成员 + for member in members { + var model = RoleModel() + model.member = member + self?.membersData.roles.append(model) + } + // 记录最后一个身份组的时间戳 用于下页请求 + self?.membersData.timeTag = self?.membersData.roles.last?.member?.createTime + + // 添加占位 + if members.count == self?.rolesData.pageSize { + var placeholdModel = RoleModel() + placeholdModel.title = localizable("more") + placeholdModel.isPlacehold = true + self?.membersData.roles.append(placeholdModel) + } + self?.setRoundedCorner() + // 设置圆角 + completion(error, self?.membersData.roles) + } else { + // 设置圆角 + self?.setRoundedCorner() + completion(error, self?.membersData.roles) } + } } - - public func removeChannelRole(role: ChannelRole?, index: Int, _ completion: @escaping (NSError?)->()) { - var param = RemoveChannelRoleParam() - param.serverId = role?.serverId - param.roleId = UInt64(role?.roleId ?? 0) - param.channelId = role?.channelId - repo.removeChannelRole(param: param) {[weak self] anError in - if anError == nil { - self?.rolesData.roles.remove(at: index) - completion(anError) - } - completion(anError) - } + } + + public func removeChannelRole(role: ChannelRole?, index: Int, + _ completion: @escaping (NSError?) -> Void) { + var param = RemoveChannelRoleParam() + param.serverId = role?.serverId + param.roleId = UInt64(role?.roleId ?? 0) + param.channelId = role?.channelId + repo.removeChannelRole(param: param) { [weak self] anError in + if anError == nil { + self?.rolesData.roles.remove(at: index) + completion(anError) + } + completion(anError) } - - public func removeMemberRole(member: MemberRole?, index: Int, _ completion: @escaping (NSError?)->()) { - let param = RemoveMemberRoleParam(serverId: self.channel?.serverId, channelId: self.channel?.channelId, accid: member?.accid) - repo.removeMemberRole(param: param) { [weak self] anError in - if anError == nil { - self?.membersData.roles.remove(at: index) - } - completion(anError) - } + } + + public func removeMemberRole(member: MemberRole?, index: Int, + _ completion: @escaping (NSError?) -> Void) { + let param = RemoveMemberRoleParam( + serverId: channel?.serverId, + channelId: channel?.channelId, + accid: member?.accid + ) + repo.removeMemberRole(param: param) { [weak self] anError in + if anError == nil { + self?.membersData.roles.remove(at: index) + } + completion(anError) } - + } + // 本地插入成员 - public func insertLocalMemberAtHead(member: MemberRole) { - let model = RoleModel(member: member, isPlacehold: false) - self.membersData.roles.insert(model, at: 0) - setRoundedCorner() - } + public func insertLocalMemberAtHead(member: MemberRole) { + let model = RoleModel(member: member, isPlacehold: false) + membersData.roles.insert(model, at: 0) + setRoundedCorner() + } + // 本地插入身份组 - public func insertLocalRoleAtHead(role: ChannelRole) { - let model = RoleModel(role:role, isPlacehold: false) - self.rolesData.roles.insert(model, at: 0) - setRoundedCorner() + public func insertLocalRoleAtHead(role: ChannelRole) { + let model = RoleModel(role: role, isPlacehold: false) + rolesData.roles.insert(model, at: 0) + setRoundedCorner() + } + + private func setRoundedCorner() { + if rolesData.roles.count > 0 { + if rolesData.roles.count == 1 { + rolesData.roles[0].corner = .all + } else { + rolesData.roles[0].corner = .top + rolesData.roles[rolesData.roles.count - 1].corner = .bottom + } } - - private func setRoundedCorner() { - if self.rolesData.roles.count > 0 { - if self.rolesData.roles.count == 1 { - self.rolesData.roles[0].corner = .all - }else { - self.rolesData.roles[0].corner = .top - self.rolesData.roles[self.rolesData.roles.count - 1].corner = .bottom - } - } - if self.membersData.roles.count > 0 { - if self.membersData.roles.count == 1 { - self.membersData.roles[0].corner = .all - }else { - self.membersData.roles[0].corner = .top - self.membersData.roles[self.membersData.roles.count - 1].corner = .bottom - } - } + if membersData.roles.count > 0 { + if membersData.roles.count == 1 { + membersData.roles[0].corner = .all + } else { + membersData.roles[0].corner = .top + membersData.roles[membersData.roles.count - 1].corner = .bottom + } } - - + } } - diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewModel/QChatChannelViewModel.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewModel/QChatChannelViewModel.swift index 594f862e..a8e3dc99 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewModel/QChatChannelViewModel.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewModel/QChatChannelViewModel.swift @@ -1,35 +1,43 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NEKitCoreIM public class QChatChannelViewModel { - public var serverId: UInt64 - public var name: String? - public var topic: String? - public var type: ChannelType = .messageType - public var isPrivate: Bool = false - public init(serverId: UInt64) { - self.serverId = serverId - } - - public init() { - self.serverId = 0 - } - - public func createChannel(_ completion: @escaping (NSError?, ChatChannel?)->()) { - let visibleType: ChannelVisibleType = self.isPrivate ? .isPrivate : .isPublic - let param = CreatChannelParam(serverId: serverId, name: name ?? "", topic: topic, visibleType: visibleType) - QChatChannelProvider.shared.createChannel(param: param) { error, channel in - completion(error, channel) - } + public var serverId: UInt64 + public var name: String? + public var topic: String? + public var type: ChannelType = .messageType + public var isPrivate: Bool = false + public init(serverId: UInt64) { + self.serverId = serverId + } + + public init() { + serverId = 0 + } + + public func createChannel(_ completion: @escaping (NSError?, ChatChannel?) -> Void) { + let visibleType: ChannelVisibleType = isPrivate ? .isPrivate : .isPublic + let param = CreatChannelParam( + serverId: serverId, + name: name ?? "", + topic: topic, + visibleType: visibleType + ) + QChatChannelProvider.shared.createChannel(param: param) { error, channel in + completion(error, channel) } - - public func getChannelsByPage(parameter:QChatGetChannelsByPageParam,_ completion: @escaping (NSError?, QChatGetChannelsByPageResult?)->()){ - QChatChannelProvider.shared.getChannelsByPage(param: parameter) { error, channelResult in - completion(error,channelResult) - } + } + + public func getChannelsByPage(parameter: QChatGetChannelsByPageParam, + _ completion: @escaping (NSError?, QChatGetChannelsByPageResult?) + -> Void) { + QChatChannelProvider.shared.getChannelsByPage(param: parameter) { error, channelResult in + completion(error, channelResult) } + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewModel/QChatUpdateChannelViewModel.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewModel/QChatUpdateChannelViewModel.swift index f1a19e73..574133c8 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewModel/QChatUpdateChannelViewModel.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Channel/ViewModel/QChatUpdateChannelViewModel.swift @@ -1,35 +1,35 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NEKitCoreIM import NEKitQChat public class QChatUpdateChannelViewModel { - public var channel: ChatChannel? - //临时记录修改的值 - public var channelTmp: ChatChannel? - init(channel:ChatChannel?) { - self.channel = channel - self.channelTmp = channel - } - - func updateChannelInfo(completion: @escaping (NSError?, ChatChannel?) -> Void) { - var param = UpdateChannelParam(channelId: channel?.channelId) - param.name = channelTmp?.name - param.topic = channelTmp?.topic - param.custom = channelTmp?.custom - QChatRepo().updateChannelInfo(param) { [weak self] error, channel in - if error == nil { - self?.channel = channel - } - completion(error, channel) - } - } - - func deleteChannel(completion: @escaping (NSError?) -> Void) { - QChatChannelProvider.shared.deleteChannel(channelId: channel?.channelId, completion) + public var channel: ChatChannel? + // 临时记录修改的值 + public var channelTmp: ChatChannel? + init(channel: ChatChannel?) { + self.channel = channel + channelTmp = channel + } + + func updateChannelInfo(completion: @escaping (NSError?, ChatChannel?) -> Void) { + var param = UpdateChannelParam(channelId: channel?.channelId) + param.name = channelTmp?.name + param.topic = channelTmp?.topic + param.custom = channelTmp?.custom + QChatRepo().updateChannelInfo(param) { [weak self] error, channel in + if error == nil { + self?.channel = channel + } + completion(error, channel) } + } + func deleteChannel(completion: @escaping (NSError?) -> Void) { + QChatChannelProvider.shared.deleteChannel(channelId: channel?.channelId, completion) + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Chat/Controller/QChatViewController.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Chat/Controller/QChatViewController.swift index ee00b817..1a1284a1 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Chat/Controller/QChatViewController.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Chat/Controller/QChatViewController.swift @@ -1,6 +1,7 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCoreIM @@ -11,361 +12,412 @@ import NEKitCommonUI import NEKitCommon import NEKitCore -public class QChatViewController: NEBaseViewController, UINavigationControllerDelegate, QChatInputViewDelegate, QChatViewModelDelegate{ - - private let tag = "QChatViewController" - private var viewmodel: QChatViewModel? - private var inputViewBottomConstraint: NSLayoutConstraint? - - public init(channel:ChatChannel?) { - super.init(nibName: nil, bundle: nil) - self.viewmodel = QChatViewModel(channel: channel) - self.viewmodel?.delegate = self - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - public override func viewDidLoad() { - super.viewDidLoad() - commonUI() - addObseve() - loadData() - } +public class QChatViewController: NEBaseViewController, UINavigationControllerDelegate, + QChatInputViewDelegate, QChatViewModelDelegate,UITableViewDataSource, UITableViewDelegate { + private let tag = "QChatViewController" + private var viewmodel: QChatViewModel? + private var inputViewBottomConstraint: NSLayoutConstraint? - - //MARK: lazy Method - private lazy var brokenNetworkView:NEBrokenNetworkView = { - let view = NEBrokenNetworkView.init(frame: CGRect.init(x: 0, y: kNavigationHeight + KStatusBarHeight, width: kScreenWidth, height: 36)) - return view - }() - - private lazy var tableView:UITableView = { - let tableView = UITableView.init(frame: .zero, style: .plain) - tableView.translatesAutoresizingMaskIntoConstraints = false - tableView.separatorStyle = .none - tableView.showsVerticalScrollIndicator = false - tableView.delegate = self - tableView.dataSource = self - tableView.backgroundColor = .white - tableView.mj_header = MJRefreshNormalHeader(refreshingTarget: self, refreshingAction: #selector(loadMoreData)) - return tableView - }() - - deinit { - NELog.infoLog(className(), desc: "✅ QChatViewController release") - } -} + public init(channel: ChatChannel?) { + super.init(nibName: nil, bundle: nil) + viewmodel = QChatViewModel(channel: channel) + viewmodel?.delegate = self + } + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + override public func viewDidLoad() { + super.viewDidLoad() + commonUI() + addObseve() + loadData() + } -//MARK: =============== QChatBaseCellDelegate ================ -extension QChatViewController:QChatBaseCellDelegate { - func didSelectWithCell(cell: QChatBaseTableViewCell, type: QChatMessageClickType, message: NIMQChatMessage) { - if type == .message { - self.didClickMessage(messgae: message) - }else if type == .LongPressMessage { - - } - } - - func didClickHeader(_ message: NIMQChatMessage) { - if IMKitLoginManager.instance.isMySelf(message.from) == true { - Router.shared.use(MeSettingRouter, parameters: ["nav": navigationController as Any], closure: nil) - }else { - Router.shared.use(ContactUserInfoPageRouter, parameters: ["nav": navigationController as Any, "uid": message.from as Any], closure: nil) - } - } - - // click action - func didClickMessage(messgae:NIMQChatMessage) { - if messgae.messageType == .image { - let imageObject = messgae.messageObject as! NIMImageObject - if let imageUrl = imageObject.url { - let showController = PhotoBrowserController(urls: [imageUrl], url: imageUrl) - showController.modalPresentationStyle = .overFullScreen - self.present(showController, animated: false, completion: nil) - } + // MARK: lazy Method - }else if messgae.messageType == .audio { - - } - } - -} + private lazy var brokenNetworkView: NEBrokenNetworkView = { + let view = + NEBrokenNetworkView(frame: CGRect(x: 0, y: kNavigationHeight + KStatusBarHeight, + width: kScreenWidth, height: 36)) + return view + }() -//MARK: UITableViewDataSource,UITableViewDelegate -extension QChatViewController:UITableViewDataSource,UITableViewDelegate { + private lazy var tableView: UITableView = { + let tableView = UITableView(frame: .zero, style: .plain) + tableView.translatesAutoresizingMaskIntoConstraints = false + tableView.separatorStyle = .none + tableView.showsVerticalScrollIndicator = false + tableView.delegate = self + tableView.dataSource = self + tableView.backgroundColor = .white + tableView.mj_header = MJRefreshNormalHeader( + refreshingTarget: self, + refreshingAction: #selector(loadMoreData) + ) + return tableView + }() + + deinit { + NELog.infoLog(className(), desc: "✅ QChatViewController release") + } - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return viewmodel?.messages.count ?? 0 - } + func commonUI() { + title = viewmodel?.channel?.name + addLeftAction(UIImage.ne_imageNamed(name: "server_menu"), #selector(enterServerVC), self) + addRightAction( + UIImage.ne_imageNamed(name: "channel_member"), + #selector(enterChannelMemberVC), + self + ) - public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let messageFrame = viewmodel?.messages[indexPath.row] - var reuseIdentifier = "\(QChatBaseTableViewCell.self)" - - guard let msgFrame = messageFrame else { - return tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) - } - - if msgFrame.showTime { - reuseIdentifier = "\(QChatTimeTableViewCell.self)" - }else { - //根据cell类型区分identify - switch msgFrame.message?.messageType { - case .text: - reuseIdentifier = "\(QChatTextTableViewCell.self)" - break - case .image: - reuseIdentifier = "\(QChatImageTableViewCell.self)" - break - default: - reuseIdentifier = "\(QChatBaseTableViewCell.self)" - } - } - - if msgFrame.showTime { - let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) as! QChatTimeTableViewCell - cell.messageFrame = messageFrame - return cell - }else { - let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) as! QChatBaseTableViewCell - cell.messageFrame = messageFrame - cell.delegate = self - return cell - } - } + view.addSubview(tableView) + NSLayoutConstraint.activate([ + tableView.topAnchor.constraint( + equalTo: view.topAnchor, + constant: kNavigationHeight + KStatusBarHeight + ), + tableView.leftAnchor.constraint(equalTo: view.leftAnchor), + tableView.rightAnchor.constraint(equalTo: view.rightAnchor), + tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -130), + ]) - public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - let messageFrame = viewmodel?.messages[indexPath.row] - return messageFrame?.cellHeight ?? 0 - } -} + tableView.register( + QChatBaseTableViewCell.self, + forCellReuseIdentifier: "\(QChatBaseTableViewCell.self)" + ) + tableView.register( + QChatTextTableViewCell.self, + forCellReuseIdentifier: "\(QChatTextTableViewCell.self)" + ) + tableView.register( + QChatImageTableViewCell.self, + forCellReuseIdentifier: "\(QChatImageTableViewCell.self)" + ) + tableView.register( + QChatTimeTableViewCell.self, + forCellReuseIdentifier: "\(QChatTimeTableViewCell.self)" + ) -//MARK: private method -extension QChatViewController { + // IQKeyboardManager.shared.enable = false + IQKeyboardManager.shared.keyboardDistanceFromTextField = 60 + IQKeyboardManager.shared.enable = true + IQKeyboardManager.shared.enableAutoToolbar = false + let inputView = QChatInputView() + var tip = localizable("send_to") + if let cName = viewmodel?.channel?.name { + tip = tip + cName + } + inputView.textField.placeholder = tip - func commonUI() { - self.title = viewmodel?.channel?.name - self.addLeftAction(UIImage.ne_imageNamed(name: "server_menu"), #selector(enterServerVC), self) - self.addRightAction(UIImage.ne_imageNamed(name: "channel_member"), #selector(enterChannelMemberVC), self) - - self.view.addSubview(tableView) + inputView.translatesAutoresizingMaskIntoConstraints = false + inputView.delegate = self + view.addSubview(inputView) + if #available(iOS 11.0, *) { + self.inputViewBottomConstraint = inputView.bottomAnchor + .constraint(equalTo: self.view.bottomAnchor) + // self.inputViewBottomConstraint = inputView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor) + NSLayoutConstraint.activate([ + inputView.leftAnchor.constraint(equalTo: self.view.leftAnchor), + inputView.rightAnchor.constraint(equalTo: self.view.rightAnchor), + inputView.heightAnchor.constraint(equalToConstant: 100), + ]) + } else { + // Fallback on earlier versions + inputViewBottomConstraint = inputView.bottomAnchor + .constraint(equalTo: view.bottomAnchor) NSLayoutConstraint.activate([ - tableView.topAnchor.constraint(equalTo: self.view.topAnchor,constant: kNavigationHeight + KStatusBarHeight), - tableView.leftAnchor.constraint(equalTo: self.view.leftAnchor), - tableView.rightAnchor.constraint(equalTo: self.view.rightAnchor), - tableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor,constant: -130) + inputView.leftAnchor.constraint(equalTo: view.leftAnchor), + inputView.rightAnchor.constraint(equalTo: view.rightAnchor), + inputView.heightAnchor.constraint(equalToConstant: 100), ]) + } + inputViewBottomConstraint?.isActive = true - tableView.register(QChatBaseTableViewCell.self, forCellReuseIdentifier: "\(QChatBaseTableViewCell.self)") - tableView.register(QChatTextTableViewCell.self, forCellReuseIdentifier: "\(QChatTextTableViewCell.self)") - tableView.register(QChatImageTableViewCell.self, forCellReuseIdentifier: "\(QChatImageTableViewCell.self)") - tableView.register(QChatTimeTableViewCell.self, forCellReuseIdentifier: "\(QChatTimeTableViewCell.self)") - -// IQKeyboardManager.shared.enable = false - IQKeyboardManager.shared.keyboardDistanceFromTextField = 60 - IQKeyboardManager.shared.enable = true - IQKeyboardManager.shared.enableAutoToolbar = false - let inputView = QChatInputView() - var tip = localizable("send_to") - if let cName = viewmodel?.channel?.name { - tip = tip + cName - } - inputView.textField.placeholder = tip - - inputView.translatesAutoresizingMaskIntoConstraints = false - inputView.delegate = self - self.view.addSubview(inputView) - if #available(iOS 11.0, *) { - self.inputViewBottomConstraint = inputView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor) -// self.inputViewBottomConstraint = inputView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor) - NSLayoutConstraint.activate([ - inputView.leftAnchor.constraint(equalTo: self.view.leftAnchor), - inputView.rightAnchor.constraint(equalTo: self.view.rightAnchor), - inputView.heightAnchor.constraint(equalToConstant: 100) - ]) + weak var weakSelf = self + NEChatDetectNetworkTool.shareInstance.netWorkReachability { status in + if status == .notReachable, let networkView = weakSelf?.brokenNetworkView { + weakSelf?.view.addSubview(networkView) } else { - // Fallback on earlier versions - self.inputViewBottomConstraint = inputView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor) - NSLayoutConstraint.activate([ - inputView.leftAnchor.constraint(equalTo: self.view.leftAnchor), - inputView.rightAnchor.constraint(equalTo: self.view.rightAnchor), - inputView.heightAnchor.constraint(equalToConstant: 100) - ]) - } - self.inputViewBottomConstraint?.isActive = true - - - weak var weakSelf = self - NEChatDetectNetworkTool.shareInstance.netWorkReachability() { status in - if status == .notReachable,let networkView = weakSelf?.brokenNetworkView{ - weakSelf?.view.addSubview(networkView) - }else { - weakSelf?.brokenNetworkView.removeFromSuperview() - } + weakSelf?.brokenNetworkView.removeFromSuperview() } + } } -// MARK: event + // MARK: event + @objc func enterChannelMemberVC() { - let memberVC = QChatChannelMembersVC() - memberVC.channel = viewmodel?.channel - self.navigationController?.pushViewController(memberVC, animated: true) + let memberVC = QChatChannelMembersVC() + memberVC.channel = viewmodel?.channel + navigationController?.pushViewController(memberVC, animated: true) } - + @objc func enterServerVC() { - self.navigationController?.popViewController(animated: true) + navigationController?.popViewController(animated: true) } - + func loadData() { - weak var weakSelf = self - viewmodel?.getMessageHistory({ error, messages in - - if let err = error { - NELog.errorLog(self.tag, desc: "❌getMessageHistory error, error:\(err)") - }else { - if let tempArray = weakSelf?.viewmodel?.messages,tempArray.count > 0 { - weakSelf?.tableView.reloadData() - weakSelf?.tableView.scrollToRow(at: IndexPath(row: tempArray.count - 1, section: 0), at: .bottom, animated: false) - if let time = messages?.first?.message?.timestamp { - weakSelf?.viewmodel?.markMessageRead(time: time) - } - } + weak var weakSelf = self + viewmodel?.getMessageHistory { error, messages in + + if let err = error { + NELog.errorLog(self.tag, desc: "❌getMessageHistory error, error:\(err)") + } else { + if let tempArray = weakSelf?.viewmodel?.messages, tempArray.count > 0 { + weakSelf?.tableView.reloadData() + weakSelf?.tableView.scrollToRow( + at: IndexPath(row: tempArray.count - 1, section: 0), + at: .bottom, + animated: false + ) + if let time = messages?.first?.message?.timestamp { + weakSelf?.viewmodel?.markMessageRead(time: time) } - }) + } + } + } } - - @objc func loadMoreData(){ - weak var weakSelf = self - viewmodel?.getMoreMessageHistory({ error, messageFrames in - weakSelf?.tableView.reloadData() - weakSelf?.tableView.mj_header?.endRefreshing() - }) - + + @objc func loadMoreData() { + weak var weakSelf = self + viewmodel?.getMoreMessageHistory { error, messageFrames in + weakSelf?.tableView.reloadData() + weakSelf?.tableView.mj_header?.endRefreshing() + } } - + func addObseve() { - NotificationCenter.default.addObserver(self, selector: #selector(onUpdateChannel), name:NotificationName.updateChannel, object: nil) - NotificationCenter.default.addObserver(self, selector: #selector(onDeleteChannel), name:NotificationName.deleteChannel, object: nil) -// 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(onUpdateChannel), + name: NotificationName.updateChannel, + object: nil + ) + NotificationCenter.default.addObserver( + self, + selector: #selector(onDeleteChannel), + name: NotificationName.deleteChannel, + object: nil + ) + // NotificationCenter.default.addObserver(self, + // selector: #selector(keyBoardWillShow(_ :)), + // name: UIResponder.keyboardWillShowNotification, + // object: nil) + // + // NotificationCenter.default.addObserver(self, + // selector: #selector(keyBoardWillHide(_ :)), + // name: UIResponder.keyboardWillHideNotification, + // object: nil) } - + @objc func onUpdateChannel(noti: Notification) { - // enter ChatVC - guard let channel = noti.object as? ChatChannel else { - return - } - viewmodel?.channel = channel - self.title = viewmodel?.channel?.name + // enter ChatVC + guard let channel = noti.object as? ChatChannel else { + return + } + viewmodel?.channel = channel + title = viewmodel?.channel?.name } - + @objc func onDeleteChannel(noti: Notification) { - self.navigationController?.popToRootViewController(animated: true) + navigationController?.popToRootViewController(animated: true) } - - - //MARK:键盘通知相关操作 -// @objc func keyBoardWillShow(_ notification:Notification) { -// let keyboardRect = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue -// self.inputViewBottomConstraint?.constant = -keyboardRect.size.height -// UIView.animate(withDuration: 0.25, animations: { -// self.view.layoutIfNeeded() -// }) -// } -// -// @objc func keyBoardWillHide(_ notification:Notification) { -// self.inputViewBottomConstraint?.constant = 0 -// UIView.animate(withDuration: 0.25, animations: { -// self.view.layoutIfNeeded() -// }) -// } - -//MARK: QChatInputViewDelegate + // MARK: 键盘通知相关操作 + + // @objc func keyBoardWillShow(_ notification:Notification) { + // let keyboardRect = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue + // self.inputViewBottomConstraint?.constant = -keyboardRect.size.height + // UIView.animate(withDuration: 0.25, animations: { + // self.view.layoutIfNeeded() + // }) + // } + // + // @objc func keyBoardWillHide(_ notification:Notification) { + // self.inputViewBottomConstraint?.constant = 0 + // UIView.animate(withDuration: 0.25, animations: { + // self.view.layoutIfNeeded() + // }) + // } + + // MARK: QChatInputViewDelegate + func sendText(text: String?) { - NELog.infoLog(tag, desc: "sendText:\(text ?? "")") - guard let content = text, content.count > 0 else { - self.showToast(localizable("text_is_nil")) - - return - } - viewmodel?.sendTextMessage(text: content, {[weak self] error in - if error != nil { - self?.view.makeToast(error?.localizedDescription) - }else { - - } - }) + NELog.infoLog(tag, desc: "sendText:\(text ?? "")") + guard let content = text, content.count > 0 else { + showToast(localizable("text_is_nil")) + + return + } + viewmodel?.sendTextMessage(text: content) { [weak self] error in + if error != nil { + self?.view.makeToast(error?.localizedDescription) + } else {} + } } - + func willSelectItem(button: UIButton, index: Int) { - if index == 2 { - showBottomAlert(self) - }else { - self.showToast(localizable("open_soon")) - } + if index == 2 { + showBottomAlert(self, false) + } else { + showToast(localizable("open_soon")) + } } - -// MARK:UIImagePickerControllerDelegate - public func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { + // MARK: UIImagePickerControllerDelegate - picker.dismiss(animated: true, completion: nil) - guard let image = info[.originalImage] as? UIImage else { - self.showToast(localizable("image_is_nil")) - return + public func imagePickerController(_ picker: UIImagePickerController, + didFinishPickingMediaWithInfo info: [UIImagePickerController + .InfoKey: Any]) { + picker.dismiss(animated: true, completion: nil) + guard let image = info[.originalImage] as? UIImage else { + showToast(localizable("image_is_nil")) + return + } + // 发送消息 + viewmodel?.sendImageMessage(image: image) { [weak self] error in + if error != nil { + self?.view.makeToast(error?.localizedDescription) } - //发送消息 - viewmodel?.sendImageMessage(image: image, {[weak self] error in - if error != nil { - self?.view.makeToast(error?.localizedDescription) - } - }) + } } - -// MARK:QChatViewModelDelegate + + // MARK: QChatViewModelDelegate + public func onRecvMessages(_ messages: [NIMQChatMessage]) { - - tableView.reloadData() - if let messageCount = viewmodel?.messages.count,messageCount>1 { - self.tableView.scrollToRow(at: IndexPath(row: messageCount - 1, section: 0), at: .bottom, animated: false) - if let time = viewmodel?.messages.last?.message?.timestamp { - viewmodel?.markMessageRead(time: time) - } + tableView.reloadData() + if let messageCount = viewmodel?.messages.count, messageCount > 1 { + tableView.scrollToRow( + at: IndexPath(row: messageCount - 1, section: 0), + at: .bottom, + animated: false + ) + if let time = viewmodel?.messages.last?.message?.timestamp { + viewmodel?.markMessageRead(time: time) } + } } - - public func send(_ message: NIMQChatMessage, progress: Float) { - - } - + + public func send(_ message: NIMQChatMessage, progress: Float) {} + public func send(_ message: NIMQChatMessage, didCompleteWithError error: Error?) { - if let e = error as NSError? { - if e.code == 403 { - showAlert(message: localizable("no_Permession")) {} - } - } - tableView.reloadData() - if let messageCount = viewmodel?.messages.count,messageCount>1 { - self.tableView.scrollToRow(at: IndexPath(row: messageCount - 1, section: 0), at: .bottom, animated: false) + if let e = error as NSError? { + if e.code == 403 { + showAlert(message: localizable("no_Permession")) {} } + } + tableView.reloadData() + if let messageCount = viewmodel?.messages.count, messageCount > 1 { + tableView.scrollToRow( + at: IndexPath(row: messageCount - 1, section: 0), + at: .bottom, + animated: false + ) + } } - + public func willSend(_ message: NIMQChatMessage) { - tableView.reloadData() - if let messageCount = viewmodel?.messages.count,messageCount>1 { - self.tableView.scrollToRow(at: IndexPath(row: messageCount - 1, section: 0), at: .bottom, animated: false) + tableView.reloadData() + if let messageCount = viewmodel?.messages.count, messageCount > 1 { + tableView.scrollToRow( + at: IndexPath(row: messageCount - 1, section: 0), + at: .bottom, + animated: false + ) + } + } + + //MARK: UITableViewDataSource, UITableViewDelegate + public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + viewmodel?.messages.count ?? 0 + } + + public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let messageFrame = viewmodel?.messages[indexPath.row] + var reuseIdentifier = "\(QChatBaseTableViewCell.self)" + + guard let msgFrame = messageFrame else { + return tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) + } + + if msgFrame.showTime { + reuseIdentifier = "\(QChatTimeTableViewCell.self)" + } else { + // 根据cell类型区分identify + switch msgFrame.message?.messageType { + case .text: + reuseIdentifier = "\(QChatTextTableViewCell.self)" + case .image: + reuseIdentifier = "\(QChatImageTableViewCell.self)" + default: + reuseIdentifier = "\(QChatBaseTableViewCell.self)" } + } + + if msgFrame.showTime { + let cell = tableView.dequeueReusableCell( + withIdentifier: reuseIdentifier, + for: indexPath + ) as! QChatTimeTableViewCell + cell.messageFrame = messageFrame + return cell + } else { + let cell = tableView.dequeueReusableCell( + withIdentifier: reuseIdentifier, + for: indexPath + ) as! QChatBaseTableViewCell + cell.messageFrame = messageFrame + cell.delegate = self + return cell + } + } + + public func tableView(_ tableView: UITableView, + heightForRowAt indexPath: IndexPath) -> CGFloat { + let messageFrame = viewmodel?.messages[indexPath.row] + return messageFrame?.cellHeight ?? 0 } } + +// MARK: =============== QChatBaseCellDelegate ================ + +extension QChatViewController: QChatBaseCellDelegate { + func didSelectWithCell(cell: QChatBaseTableViewCell, type: QChatMessageClickType, + message: NIMQChatMessage) { + if type == .message { + didClickMessage(messgae: message) + } else if type == .LongPressMessage {} + } + + func didClickHeader(_ message: NIMQChatMessage) { + if IMKitLoginManager.instance.isMySelf(message.from) == true { + Router.shared.use( + MeSettingRouter, + parameters: ["nav": navigationController as Any], + closure: nil + ) + } else { + Router.shared.use( + ContactUserInfoPageRouter, + parameters: ["nav": navigationController as Any, "uid": message.from as Any], + closure: nil + ) + } + } + + // click action + func didClickMessage(messgae: NIMQChatMessage) { + if messgae.messageType == .image { + let imageObject = messgae.messageObject as! NIMImageObject + if let imageUrl = imageObject.url { + let showController = PhotoBrowserController(urls: [imageUrl], url: imageUrl) + showController.modalPresentationStyle = .overFullScreen + present(showController, animated: false, completion: nil) + } + + } else if messgae.messageType == .audio {} + } +} + diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Chat/Helper/QChatMessageHelper.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Chat/Helper/QChatMessageHelper.swift index 4585b82b..ca13a866 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Chat/Helper/QChatMessageHelper.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Chat/Helper/QChatMessageHelper.swift @@ -1,35 +1,35 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation class QChatMessageHelper { - //获取图片合适尺寸 - class func getSizeWithMaxSize(_ maxSize: CGSize, size: CGSize,miniWH:CGFloat) -> CGSize { - - var realSize = CGSize.zero - - if min(size.width, size.height) > 0 { - if size.width > size.height { - //宽大 按照宽给高 - let width = CGFloat(min(maxSize.width, size.width)) - realSize = CGSize(width: width, height: width * size.height / size.width) - if realSize.height < miniWH { - realSize.height = miniWH - } - } else { - //高大 按照高给宽 - let height = CGFloat(min(maxSize.height, size.height)) - realSize = CGSize(width: height * size.width / size.height, height: height) - if realSize.width < miniWH { - realSize.width = miniWH - } - } - }else { - realSize = maxSize + // 获取图片合适尺寸 + class func getSizeWithMaxSize(_ maxSize: CGSize, size: CGSize, miniWH: CGFloat) -> CGSize { + var realSize = CGSize.zero + + if min(size.width, size.height) > 0 { + if size.width > size.height { + // 宽大 按照宽给高 + let width = CGFloat(min(maxSize.width, size.width)) + realSize = CGSize(width: width, height: width * size.height / size.width) + if realSize.height < miniWH { + realSize.height = miniWH + } + } else { + // 高大 按照高给宽 + let height = CGFloat(min(maxSize.height, size.height)) + realSize = CGSize(width: height * size.width / size.height, height: height) + if realSize.width < miniWH { + realSize.width = miniWH } - - return realSize + } + } else { + realSize = maxSize } + + return realSize + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Chat/Model/QChatMessageFrame.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Chat/Model/QChatMessageFrame.swift index 31ebb33a..9ce4b819 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Chat/Model/QChatMessageFrame.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Chat/Model/QChatMessageFrame.swift @@ -1,98 +1,110 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NIMSDK public class QChatMessageFrame: NSObject { - //是否显示时间 - public var showTime:Bool = false - //具体时间 - public var time:String? - //是否显示头像 - public var showAvatar:Bool = true - //用户头像地址 - public var avatar: String? - //nickname - public var nickname: String? - //发送者是否为自己 + // 是否显示时间 + public var showTime: Bool = false + // 具体时间 + public var time: String? + // 是否显示头像 + public var showAvatar: Bool = true + // 用户头像地址 + public var avatar: String? + // nickname + public var nickname: String? + // 发送者是否为自己 // public var isSender:Bool? - //头像frame - public var headFrame:CGRect? - //内容frame - public var contentFrame:CGRect? - //cell整体高度 - public var cellHeight:CGFloat = 0.0 - //X初始位置 - public var startX:CGFloat = 0.0 - + // 头像frame + public var headFrame: CGRect? + // 内容frame + public var contentFrame: CGRect? + // cell整体高度 + public var cellHeight: CGFloat = 0.0 + // X初始位置 + public var startX: CGFloat = 0.0 + // public init(isSender:Bool) { // self.isSender = isSender // } - - public var message:NIMQChatMessage?{ - didSet { - var contentSize = CGSize.zero - - switch message?.messageType { - case .text://计算文本 - - contentSize = String.getTextRectSize(message?.text ?? "", font: DefaultTextFont(16), size: CGSize.init(width: qChat_content_maxW, height: CGFloat.greatestFiniteMagnitude)) - if contentSize.height < qChat_min_h {//小于一行高度,就保持一行 - contentSize.height = qChat_min_h - } - contentSize.width += 2*qChat_margin; - break - case .image://计算图片类型 - if let imageObject = message?.messageObject,imageObject.isKind(of: NIMImageObject.self) { - let obj = (imageObject as! NIMImageObject) - contentSize = QChatMessageHelper.getSizeWithMaxSize(qChat_pic_size, size: obj.size, miniWH: qChat_min_h) - }else { - contentSize = qChat_pic_size - } - - break - default: - print("others") - } + public var message: NIMQChatMessage? { + didSet { + var contentSize = CGSize.zero + + switch message?.messageType { + case .text: // 计算文本 + + contentSize = String.getTextRectSize( + message?.text ?? "", + font: DefaultTextFont(16), + size: CGSize(width: qChat_content_maxW, height: CGFloat.greatestFiniteMagnitude) + ) + if contentSize.height < qChat_min_h { // 小于一行高度,就保持一行 + contentSize.height = qChat_min_h + } + contentSize.width += 2 * qChat_margin + case .image: // 计算图片类型 + if let imageObject = message?.messageObject, + imageObject.isKind(of: NIMImageObject.self) { + let obj = (imageObject as! NIMImageObject) + contentSize = QChatMessageHelper.getSizeWithMaxSize( + qChat_pic_size, + size: obj.size, + miniWH: qChat_min_h + ) + } else { + contentSize = qChat_pic_size + } + + default: + print("others") + } + + // 计算头像 + var headFrameX = qChat_cell_margin + let headFrameY = qChat_margin - //计算头像 - var headFrameX = qChat_cell_margin - let headFrameY = qChat_margin - - guard let msg = message else { - return - } - - if (msg.isOutgoingMsg) {//消息发送者 - headFrameX = kScreenWidth - headFrameX - qChat_headWH - } - headFrame = CGRect.init(x: headFrameX, y: headFrameY, width: qChat_headWH, height: qChat_headWH) - - let viewY = qChat_margin + guard let msg = message else { + return + } - //聊天气泡的frame - var viewX = 0.0 - - viewX = headFrame!.maxX + qChat_margin; - if (msg.isOutgoingMsg) {//消息发送者 - viewX = kScreenWidth - contentSize.width - qChat_margin - qChat_headWH - qChat_cell_margin - } - contentFrame = CGRect.init(x: viewX, y: viewY, width: contentSize.width, height: contentSize.height) + if msg.isOutgoingMsg { // 消息发送者 + headFrameX = kScreenWidth - headFrameX - qChat_headWH + } + headFrame = CGRect( + x: headFrameX, + y: headFrameY, + width: qChat_headWH, + height: qChat_headWH + ) - //cell 高度 - cellHeight = contentSize.height + qChat_margin - - // 起始位置 + let viewY = qChat_margin + + // 聊天气泡的frame + var viewX = 0.0 + + viewX = headFrame!.maxX + qChat_margin + if msg.isOutgoingMsg { // 消息发送者 + viewX = kScreenWidth - contentSize + .width - qChat_margin - qChat_headWH - qChat_cell_margin + } + contentFrame = CGRect( + x: viewX, + y: viewY, + width: contentSize.width, + height: contentSize.height + ) + + // cell 高度 + cellHeight = contentSize.height + qChat_margin + + // 起始位置 // _startX = isSend ? 0 : kChat_angle_w; - startX = 0 - - - - } + startX = 0 } - - - + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Chat/View/Cell/QChatBaseTableViewCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Chat/View/Cell/QChatBaseTableViewCell.swift index 8b4f6ab9..b05f854c 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Chat/View/Cell/QChatBaseTableViewCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Chat/View/Cell/QChatBaseTableViewCell.swift @@ -1,27 +1,29 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NIMSDK import NEKitCore -@objc class QChatBubbleButton:UIButton { - //设置气泡背景图片 - public func setBubbleImage(image:UIImage){ - let image = image.resizableImage(withCapInsets: UIEdgeInsets.init(top: 35, left: 25, bottom: 10, right: 25)) - self.setBackgroundImage(image, for: .normal) - self.setBackgroundImage(image, for: .highlighted) - } - - override init(frame: CGRect) { - super.init(frame: frame) - self.imageView?.contentMode = .scaleAspectFill - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - } +@objc class QChatBubbleButton: UIButton { + // 设置气泡背景图片 + public func setBubbleImage(image: UIImage) { + let image = image + .resizableImage(withCapInsets: UIEdgeInsets(top: 35, left: 25, bottom: 10, right: 25)) + setBackgroundImage(image, for: .normal) + setBackgroundImage(image, for: .highlighted) + } + + override init(frame: CGRect) { + super.init(frame: frame) + imageView?.contentMode = .scaleAspectFill + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + } // //设置气泡背景色 // public func setBubbleImage(color:UIColor){ // let image = self.currentBackgroundImage @@ -29,133 +31,136 @@ import NEKitCore } enum QChatMessageClickType: String { - case message - case LongPressMessage - case head - case retry + case message + case LongPressMessage + case head + case retry } -protocol QChatBaseCellDelegate: NSObjectProtocol{ - // click action - func didSelectWithCell(cell:QChatBaseTableViewCell,type:QChatMessageClickType,message:NIMQChatMessage) - - func didClickHeader(_ message: NIMQChatMessage) +protocol QChatBaseCellDelegate: NSObjectProtocol { + // click action + func didSelectWithCell(cell: QChatBaseTableViewCell, type: QChatMessageClickType, + message: NIMQChatMessage) + + func didClickHeader(_ message: NIMQChatMessage) } class QChatBaseTableViewCell: UITableViewCell { - - weak var delegate: QChatBaseCellDelegate? - - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } + weak var delegate: QChatBaseCellDelegate? - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } - // Configure the view for the selected state - } - - public var messageFrame:QChatMessageFrame? { - didSet { - - self.btnHeadImage.frame = messageFrame?.headFrame ?? CGRect.zero - self.contentBtn.frame = messageFrame?.contentFrame ?? CGRect.zero - - //TODO: 头像赋值 - if let icon = messageFrame?.avatar { - btnHeadImage.setTitle("") - btnHeadImage.sd_setImage(with: URL.init(string: icon), completed: nil) - }else { - if let sendName = messageFrame?.message?.senderName { - btnHeadImage.setTitle(sendName) - }else { - btnHeadImage.setTitle(messageFrame?.message?.from ?? "") - } - btnHeadImage.sd_setImage(with:nil, completed: nil) - btnHeadImage.backgroundColor = UIColor.colorWithNumber(number: 0) - } - - - guard let msg = messageFrame?.message else { - return - } - if (msg.isOutgoingMsg){ - self.contentBtn.setBubbleImage(image: UIImage.ne_imageNamed(name: "chat_message_send")!) - // 设置消息状态 判断消息发送是否成功 - if msg.deliveryState == NIMMessageDeliveryState.delivering{ - self.activityView.frame = CGRect.init(x: contentBtn.left - (5+20), y: contentBtn.top + (contentBtn.height - 20)/2, width: 20, height: 20) - self.activityView.messageStatus = .sending - }else if msg.deliveryState == NIMMessageDeliveryState.deliveried { - self.activityView.messageStatus = .successed - }else { - self.activityView.messageStatus = .failed - } - - }else { - self.contentBtn.setBubbleImage(image: UIImage.ne_imageNamed(name: "chat_message_receive")!) - } + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + } + + public var messageFrame: QChatMessageFrame? { + didSet { + self.btnHeadImage.frame = messageFrame?.headFrame ?? CGRect.zero + self.contentBtn.frame = messageFrame?.contentFrame ?? CGRect.zero + + // TODO: 头像赋值 + if let icon = messageFrame?.avatar { + btnHeadImage.setTitle("") + btnHeadImage.sd_setImage(with: URL(string: icon), completed: nil) + } else { + if let sendName = messageFrame?.message?.senderName { + btnHeadImage.setTitle(sendName) + } else { + btnHeadImage.setTitle(messageFrame?.message?.from ?? "") } + btnHeadImage.sd_setImage(with: nil, completed: nil) + btnHeadImage.backgroundColor = UIColor.colorWithNumber(number: 0) + } + + guard let msg = messageFrame?.message else { + return + } + if msg.isOutgoingMsg { + self.contentBtn + .setBubbleImage(image: UIImage.ne_imageNamed(name: "chat_message_send")!) + // 设置消息状态 判断消息发送是否成功 + if msg.deliveryState == NIMMessageDeliveryState.delivering { + self.activityView.frame = CGRect( + x: contentBtn.left - (5 + 20), + y: contentBtn.top + (contentBtn.height - 20) / 2, + width: 20, + height: 20 + ) + self.activityView.messageStatus = .sending + } else if msg.deliveryState == NIMMessageDeliveryState.deliveried { + self.activityView.messageStatus = .successed + } else { + self.activityView.messageStatus = .failed + } + + } else { + self.contentBtn + .setBubbleImage(image: UIImage.ne_imageNamed(name: "chat_message_receive")!) + } } - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - self.selectionStyle = .none - self.contentView.backgroundColor = .white - addContentSubviews() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - public func addContentSubviews(){ - contentView.addSubview(btnHeadImage) - contentView.addSubview(contentBtn) - contentView.addSubview(activityView) - } - - override func draw(_ rect: CGRect) { - btnHeadImage.addCorner(conrners: .allCorners, radius: 16) - } - - private lazy var btnHeadImage:NEUserHeaderView = { - let view = NEUserHeaderView(frame: .zero) - let tap = UITapGestureRecognizer() - view.addGestureRecognizer(tap) - tap.numberOfTapsRequired = 1 - tap.numberOfTouchesRequired = 1 - tap.addTarget(self, action: #selector(headerClick)) - return view - }() - - public lazy var contentBtn:QChatBubbleButton = { - let btn = QChatBubbleButton.init(frame: .zero) - btn.addTarget(self, action: #selector(bubbleClick), for: .touchUpInside) - return btn - }() - - public lazy var activityView:QChatActivityIndicatorView = { - let activityView = QChatActivityIndicatorView.init() - activityView.isHidden = true - return activityView - }() - + } + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + selectionStyle = .none + contentView.backgroundColor = .white + addContentSubviews() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + public func addContentSubviews() { + contentView.addSubview(btnHeadImage) + contentView.addSubview(contentBtn) + contentView.addSubview(activityView) + } + + override func draw(_ rect: CGRect) { + btnHeadImage.addCorner(conrners: .allCorners, radius: 16) + } + + private lazy var btnHeadImage: NEUserHeaderView = { + let view = NEUserHeaderView(frame: .zero) + let tap = UITapGestureRecognizer() + view.addGestureRecognizer(tap) + tap.numberOfTapsRequired = 1 + tap.numberOfTouchesRequired = 1 + tap.addTarget(self, action: #selector(headerClick)) + return view + }() + + public lazy var contentBtn: QChatBubbleButton = { + let btn = QChatBubbleButton(frame: .zero) + btn.addTarget(self, action: #selector(bubbleClick), for: .touchUpInside) + return btn + }() + + public lazy var activityView: QChatActivityIndicatorView = { + let activityView = QChatActivityIndicatorView() + activityView.isHidden = true + return activityView + }() } extension QChatBaseTableViewCell { - - @objc func bubbleClick(sender:UIButton){ - if let message = messageFrame?.message { - delegate?.didSelectWithCell(cell: self, type: .message, message: message) - } + @objc func bubbleClick(sender: UIButton) { + if let message = messageFrame?.message { + delegate?.didSelectWithCell(cell: self, type: .message, message: message) } - - @objc func headerClick(){ - NELog.infoLog("chat base cell", desc: "header click") - if let message = messageFrame?.message { - delegate?.didClickHeader(message) - } + } + + @objc func headerClick() { + NELog.infoLog("chat base cell", desc: "header click") + if let message = messageFrame?.message { + delegate?.didClickHeader(message) } + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Chat/View/Cell/QChatImageTableViewCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Chat/View/Cell/QChatImageTableViewCell.swift index 3f7164e1..3284d0d7 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Chat/View/Cell/QChatImageTableViewCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Chat/View/Cell/QChatImageTableViewCell.swift @@ -1,39 +1,48 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import UIKit import NIMSDK class QChatImageTableViewCell: QChatBaseTableViewCell { - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - private lazy var contentImageView:UIImageView = { - let imageView = UIImageView() - imageView.contentMode = .scaleAspectFill - self.contentBtn.addSubview(imageView) - return imageView - }() - - override public var messageFrame:QChatMessageFrame? { - didSet { - - let imageObject = messageFrame?.message?.messageObject as! NIMImageObject - contentImageView.frame = CGRect.init(x: qChat_margin, y: qChat_margin, width: contentBtn.width - 2*qChat_margin, height: contentBtn.height - 2*qChat_margin) + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private lazy var contentImageView: UIImageView = { + let imageView = UIImageView() + imageView.contentMode = .scaleAspectFill + self.contentBtn.addSubview(imageView) + return imageView + }() - if let imageUrl = imageObject.url { - contentImageView.sd_setImage(with: URL.init(string: imageUrl), placeholderImage: nil, options: .retryFailed, progress: nil, completed: nil) - }else { - contentImageView.image = UIImage() - } + override public var messageFrame: QChatMessageFrame? { + didSet { + let imageObject = messageFrame?.message?.messageObject as! NIMImageObject + contentImageView.frame = CGRect( + x: qChat_margin, + y: qChat_margin, + width: contentBtn.width - 2 * qChat_margin, + height: contentBtn.height - 2 * qChat_margin + ) - } + if let imageUrl = imageObject.url { + contentImageView.sd_setImage( + with: URL(string: imageUrl), + placeholderImage: nil, + options: .retryFailed, + progress: nil, + completed: nil + ) + } else { + contentImageView.image = UIImage() + } } + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Chat/View/Cell/QChatTextTableViewCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Chat/View/Cell/QChatTextTableViewCell.swift index 13872a8b..b57484fd 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Chat/View/Cell/QChatTextTableViewCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Chat/View/Cell/QChatTextTableViewCell.swift @@ -1,86 +1,92 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class QChatTextTableViewCell: QChatBaseTableViewCell { + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) + // Configure the view for the selected state + } - // Configure the view for the selected state - } - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - } - - - override public var messageFrame:QChatMessageFrame? { - didSet { - + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + } + + override public var messageFrame: QChatMessageFrame? { + didSet { // // SHMessage *message = messageFrame.message; - self.textView.text = messageFrame?.message?.text - var viewY = qChat_margin - if self.contentBtn.height == qChat_min_h { - viewY = (qChat_min_h - DefaultTextFont(16).lineHeight)/2 - } - - //此处要根据发送者还是接收者判断起始x值 - let leftStartMargin = messageFrame?.startX - self.textView.frame = CGRect.init(x: (leftStartMargin ?? 0) + qChat_margin, y: viewY, width: contentBtn.width - 2*qChat_margin - qChat_angle_w, height: contentBtn.height - 2*viewY) - - } - } - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") + textView.text = messageFrame?.message?.text + var viewY = qChat_margin + if contentBtn.height == qChat_min_h { + viewY = (qChat_min_h - DefaultTextFont(16).lineHeight) / 2 + } + + // 此处要根据发送者还是接收者判断起始x值 + let leftStartMargin = messageFrame?.startX + textView.frame = CGRect( + x: (leftStartMargin ?? 0) + qChat_margin, + y: viewY, + width: contentBtn.width - 2 * qChat_margin - qChat_angle_w, + height: contentBtn.height - 2 * viewY + ) } - - private lazy var textView:QChatTextView = { - let textview = QChatTextView() - textview.isEditable = false - textview.isScrollEnabled = false - textview.showsVerticalScrollIndicator = false - textview.textContainer.maximumNumberOfLines = 0 - self.contentBtn.addSubview(textview) - return textview - }() - + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private lazy var textView: QChatTextView = { + let textview = QChatTextView() + textview.isEditable = false + textview.isScrollEnabled = false + textview.showsVerticalScrollIndicator = false + textview.textContainer.maximumNumberOfLines = 0 + self.contentBtn.addSubview(textview) + return textview + }() } +class QChatTextView: UITextView { + override init(frame: CGRect, textContainer: NSTextContainer?) { + super.init(frame: frame, textContainer: textContainer) + setupUI() + } -class QChatTextView:UITextView { - override init(frame: CGRect, textContainer: NSTextContainer?) { - super.init(frame: frame, textContainer: textContainer) - setupUI() - } - - required public init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func setupUI(){ - self.backgroundColor = .clear - self.textContainer.lineFragmentPadding = 0; - self.textContainerInset = .zero; - self.dataDetectorTypes = .all - self.autoresizingMask = [.flexibleWidth, .flexibleHeight] - self.font = DefaultTextFont(16) + public required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func setupUI() { + backgroundColor = .clear + textContainer.lineFragmentPadding = 0 + textContainerInset = .zero + dataDetectorTypes = .all + autoresizingMask = [.flexibleWidth, .flexibleHeight] + font = DefaultTextFont(16) + } + + override var textContainerInset: UIEdgeInsets { + set { + let padding = textContainer.lineFragmentPadding + super.textContainerInset = UIEdgeInsets( + top: newValue.top, + left: newValue.left - padding, + bottom: newValue.bottom, + right: newValue.right - padding + ) } - - override var textContainerInset: UIEdgeInsets { - set { - let padding = self.textContainer.lineFragmentPadding - super.textContainerInset = UIEdgeInsets(top: newValue.top, left: newValue.left - padding, bottom: newValue.bottom, right: newValue.right - padding) - } - get { - return super.textContainerInset - } + get { + super.textContainerInset } + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Chat/View/Cell/QChatTimeTableViewCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Chat/View/Cell/QChatTimeTableViewCell.swift index a83c9e9f..095e1004 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Chat/View/Cell/QChatTimeTableViewCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Chat/View/Cell/QChatTimeTableViewCell.swift @@ -1,41 +1,39 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class QChatTimeTableViewCell: UITableViewCell { + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + selectionStyle = .none + contentView.addSubview(timeLable) + NSLayoutConstraint.activate([ + timeLable.topAnchor.constraint(equalTo: contentView.topAnchor), + timeLable.leftAnchor.constraint(equalTo: contentView.leftAnchor), + timeLable.rightAnchor.constraint(equalTo: contentView.rightAnchor), + timeLable.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + ]) + } - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - self.selectionStyle = .none - self.contentView.addSubview(timeLable) - NSLayoutConstraint.activate([ - timeLable.topAnchor.constraint(equalTo: self.contentView.topAnchor), - timeLable.leftAnchor.constraint(equalTo: self.contentView.leftAnchor), - timeLable.rightAnchor.constraint(equalTo: self.contentView.rightAnchor), - timeLable.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor) - ]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - public var messageFrame:QChatMessageFrame? { - didSet { - timeLable.text = messageFrame?.time - } - } + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } - private lazy var timeLable:UILabel = { - let label = UILabel() - label.font = DefaultTextFont(12) - label.textColor = UIColor.ne_emptyTitleColor - label.textAlignment = .center - label.translatesAutoresizingMaskIntoConstraints = false - return label - }() + public var messageFrame: QChatMessageFrame? { + didSet { + timeLable.text = messageFrame?.time + } + } - + private lazy var timeLable: UILabel = { + let label = UILabel() + label.font = DefaultTextFont(12) + label.textColor = UIColor.ne_emptyTitleColor + label.textAlignment = .center + label.translatesAutoresizingMaskIntoConstraints = false + return label + }() } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Chat/View/QChatActivityIndicatorView.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Chat/View/QChatActivityIndicatorView.swift index 01137c76..8ee76554 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Chat/View/QChatActivityIndicatorView.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Chat/View/QChatActivityIndicatorView.swift @@ -1,88 +1,81 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit enum QChatSendMessageStatus { - case successed - case sending - case failed + case successed + case sending + case failed } class QChatActivityIndicatorView: UIButton { + public var messageStatus: QChatSendMessageStatus? { + didSet { + failBtn.isHidden = true + activity.isHidden = true + activity.stopAnimating() - public var messageStatus:QChatSendMessageStatus? { - didSet { - - failBtn.isHidden = true - activity.isHidden = true - activity.stopAnimating() + switch messageStatus { + case .sending: + self.isHidden = false + activity.isHidden = false + activity.startAnimating() + case .failed: + self.isHidden = false + failBtn.isHidden = false + case .successed: + self.isHidden = true - switch messageStatus { - case .sending: - self.isHidden = false - activity.isHidden = false - activity.startAnimating() - break - case .failed: - self.isHidden = false - failBtn.isHidden = false - break - case .successed: - self.isHidden = true - break - - default: - print("") - } - } + default: + print("") + } } - + } - override init(frame: CGRect) { - super.init(frame: frame) - commonUI() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } + override init(frame: CGRect) { + super.init(frame: frame) + commonUI() + } - func commonUI(){ - self.addSubview(failBtn) - self.addSubview(activity) - NSLayoutConstraint.activate([ - failBtn.topAnchor.constraint(equalTo: self.topAnchor), - failBtn.leftAnchor.constraint(equalTo: self.leftAnchor), - failBtn.bottomAnchor.constraint(equalTo: self.bottomAnchor), - failBtn.rightAnchor.constraint(equalTo: self.rightAnchor), - ]) - - NSLayoutConstraint.activate([ - activity.topAnchor.constraint(equalTo: self.topAnchor), - activity.leftAnchor.constraint(equalTo: self.leftAnchor), - activity.bottomAnchor.constraint(equalTo: self.bottomAnchor), - activity.rightAnchor.constraint(equalTo: self.rightAnchor), - ]) - } - - //MARK: lazy Method - private lazy var failBtn:UIButton = { - let button = UIButton() - button.translatesAutoresizingMaskIntoConstraints = false - button.isUserInteractionEnabled = false - button .setBackgroundImage(UIImage.ne_imageNamed(name: "sendMessage_failed"), for: .normal) - return button - }() - - private lazy var activity:UIActivityIndicatorView = { - let activity = UIActivityIndicatorView.init() - activity.translatesAutoresizingMaskIntoConstraints = false - activity.color = .gray - return activity - }() - - - + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func commonUI() { + addSubview(failBtn) + addSubview(activity) + NSLayoutConstraint.activate([ + failBtn.topAnchor.constraint(equalTo: topAnchor), + failBtn.leftAnchor.constraint(equalTo: leftAnchor), + failBtn.bottomAnchor.constraint(equalTo: bottomAnchor), + failBtn.rightAnchor.constraint(equalTo: rightAnchor), + ]) + + NSLayoutConstraint.activate([ + activity.topAnchor.constraint(equalTo: topAnchor), + activity.leftAnchor.constraint(equalTo: leftAnchor), + activity.bottomAnchor.constraint(equalTo: bottomAnchor), + activity.rightAnchor.constraint(equalTo: rightAnchor), + ]) + } + + // MARK: lazy Method + + private lazy var failBtn: UIButton = { + let button = UIButton() + button.translatesAutoresizingMaskIntoConstraints = false + button.isUserInteractionEnabled = false + button.setBackgroundImage(UIImage.ne_imageNamed(name: "sendMessage_failed"), for: .normal) + return button + }() + + private lazy var activity: UIActivityIndicatorView = { + let activity = UIActivityIndicatorView() + activity.translatesAutoresizingMaskIntoConstraints = false + activity.color = .gray + return activity + }() } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Chat/View/QChatInputView.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Chat/View/QChatInputView.swift index fdc7f0ae..03cc6bd7 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Chat/View/QChatInputView.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Chat/View/QChatInputView.swift @@ -1,81 +1,80 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit protocol QChatInputViewDelegate: AnyObject { - func sendText(text: String?) - func willSelectItem(button: UIButton, index: Int) + func sendText(text: String?) + func willSelectItem(button: UIButton, index: Int) } class QChatInputView: UIView, UITextFieldDelegate { - public weak var delegate: QChatInputViewDelegate? - var textField = UITextField() - override init(frame: CGRect) { - super.init(frame: frame) - commonUI() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func commonUI() { - - self.backgroundColor = UIColor(hexString: "#EFF1F3") - textField.layer.cornerRadius = 8 - textField.clipsToBounds = true - textField.translatesAutoresizingMaskIntoConstraints = false - textField.backgroundColor = .white - textField.leftViewMode = .always - textField.returnKeyType = .send - textField.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 20, height: 40)) - textField.delegate = self - self.addSubview(textField) - NSLayoutConstraint.activate([ - textField.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 7), - textField.topAnchor.constraint(equalTo: self.topAnchor, constant: 6), - textField.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -7), - textField.heightAnchor.constraint(equalToConstant: 40) - ]) - let imageNames = ["mic","emoji","photo","file","add"] - var items = [UIButton]() - for i in 0...4 { - let button = UIButton(type: .custom) - button.setImage(UIImage.ne_imageNamed(name: imageNames[i]), for: .normal) - button.translatesAutoresizingMaskIntoConstraints = false - button.addTarget(self, action: #selector(buttonEvent), for: .touchUpInside) - button.tag = i + 5 - items.append(button) - if i != 2 { - button.alpha = 0.5 - } - } - let stackView = UIStackView(arrangedSubviews: items) - stackView.translatesAutoresizingMaskIntoConstraints = false - stackView.distribution = .fillEqually - self.addSubview(stackView) - NSLayoutConstraint.activate([ - stackView.leftAnchor.constraint(equalTo: self.leftAnchor), - stackView.rightAnchor.constraint(equalTo: self.rightAnchor), - stackView.heightAnchor.constraint(equalToConstant: 54), - stackView.topAnchor.constraint(equalTo: self.textField.bottomAnchor, constant: 0) - ]) - } - - func textFieldShouldReturn(_ textField: UITextField) -> Bool { - guard let text = textField.text?.trimmingCharacters(in: CharacterSet.whitespaces) else { - return true - } - textField.text = "" - self.delegate?.sendText(text: text) - textField.resignFirstResponder() - return true + public weak var delegate: QChatInputViewDelegate? + var textField = UITextField() + override init(frame: CGRect) { + super.init(frame: frame) + commonUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func commonUI() { + backgroundColor = UIColor(hexString: "#EFF1F3") + textField.layer.cornerRadius = 8 + textField.clipsToBounds = true + textField.translatesAutoresizingMaskIntoConstraints = false + textField.backgroundColor = .white + textField.leftViewMode = .always + textField.returnKeyType = .send + textField.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 20, height: 40)) + textField.delegate = self + addSubview(textField) + NSLayoutConstraint.activate([ + textField.leftAnchor.constraint(equalTo: leftAnchor, constant: 7), + textField.topAnchor.constraint(equalTo: topAnchor, constant: 6), + textField.rightAnchor.constraint(equalTo: rightAnchor, constant: -7), + textField.heightAnchor.constraint(equalToConstant: 40), + ]) + let imageNames = ["mic", "emoji", "photo", "file", "add"] + var items = [UIButton]() + for i in 0 ... 4 { + let button = UIButton(type: .custom) + button.setImage(UIImage.ne_imageNamed(name: imageNames[i]), for: .normal) + button.translatesAutoresizingMaskIntoConstraints = false + button.addTarget(self, action: #selector(buttonEvent), for: .touchUpInside) + button.tag = i + 5 + items.append(button) + if i != 2 { + button.alpha = 0.5 + } } - - @objc func buttonEvent(button: UIButton) { - self.delegate?.willSelectItem(button: button, index: button.tag - 5) + let stackView = UIStackView(arrangedSubviews: items) + stackView.translatesAutoresizingMaskIntoConstraints = false + stackView.distribution = .fillEqually + addSubview(stackView) + NSLayoutConstraint.activate([ + stackView.leftAnchor.constraint(equalTo: leftAnchor), + stackView.rightAnchor.constraint(equalTo: rightAnchor), + stackView.heightAnchor.constraint(equalToConstant: 54), + stackView.topAnchor.constraint(equalTo: textField.bottomAnchor, constant: 0), + ]) + } + + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + guard let text = textField.text?.trimmingCharacters(in: CharacterSet.whitespaces) else { + return true } + textField.text = "" + delegate?.sendText(text: text) + textField.resignFirstResponder() + return true + } + @objc func buttonEvent(button: UIButton) { + delegate?.willSelectItem(button: button, index: button.tag - 5) + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Chat/ViewModel/QChatViewModel.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Chat/ViewModel/QChatViewModel.swift index 1170cfc6..846fd9e0 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Chat/ViewModel/QChatViewModel.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Chat/ViewModel/QChatViewModel.swift @@ -1,265 +1,278 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NEKitCoreIM import NIMSDK public protocol QChatViewModelDelegate: AnyObject { - func onRecvMessages(_ messages: [NIMQChatMessage]) - func willSend(_ message: NIMQChatMessage) - func send(_ message: NIMQChatMessage, didCompleteWithError error: Error?) - func send(_ message: NIMQChatMessage, progress: Float) + func onRecvMessages(_ messages: [NIMQChatMessage]) + func willSend(_ message: NIMQChatMessage) + func send(_ message: NIMQChatMessage, didCompleteWithError error: Error?) + func send(_ message: NIMQChatMessage, progress: Float) } public class QChatViewModel: NSObject, NIMQChatMessageManagerDelegate { - public var channel: ChatChannel? - public var messages: [QChatMessageFrame] = [QChatMessageFrame]() - public weak var delegate: QChatViewModelDelegate? - private var lastMsg: NIMQChatMessage? - private let Tag = "QChatViewModel" - - init(channel:ChatChannel?) { - super.init() - self.channel = channel - QChatSystemMessageProvider.shared.addDelegate(delegate: self) + public var channel: ChatChannel? + public var messages: [QChatMessageFrame] = .init() + public weak var delegate: QChatViewModelDelegate? + private var lastMsg: NIMQChatMessage? + private let Tag = "QChatViewModel" + + init(channel: ChatChannel?) { + super.init() + self.channel = channel + QChatSystemMessageProvider.shared.addDelegate(delegate: self) + } + + public func sendTextMessage(text: String, _ completion: @escaping (Error?) -> Void) { + if text.count <= 0 { + return } - - public func sendTextMessage(text: String, _ completion: @escaping (Error?) -> Void) { - if text.count <= 0 { - return - } - if let cid = self.channel?.channelId, let sid = self.channel?.serverId { - let message = NIMQChatMessage() - message.text = text - message.from = IMKitLoginManager.instance.imAccid - QChatSystemMessageProvider.shared.sendMessage(message: message, session: NIMSession(forQChat: Int64(cid), qchatServerId: Int64(sid))) { error in - print("sendText error:\(error) ") - completion(error) - } - } + if let cid = channel?.channelId, let sid = channel?.serverId { + let message = NIMQChatMessage() + message.text = text + message.from = IMKitLoginManager.instance.imAccid + QChatSystemMessageProvider.shared.sendMessage( + message: message, + session: NIMSession(forQChat: Int64(cid), qchatServerId: Int64(sid)) + ) { error in + print("sendText error:\(error) ") + completion(error) + } } - - public func sendImageMessage(image: UIImage, _ completion: @escaping (Error?) -> Void) { - if let cid = self.channel?.channelId, let sid = self.channel?.serverId { - let message = NIMQChatMessage() - message.messageObject = NIMImageObject(image: image) - message.from = IMKitLoginManager.instance.imAccid - QChatSystemMessageProvider.shared.sendMessage(message: message, session: NIMSession(forQChat: Int64(cid), qchatServerId: Int64(sid))) { error in - print("sendImage error:\(error) ") - completion(error) - } - } + } + + public func sendImageMessage(image: UIImage, _ completion: @escaping (Error?) -> Void) { + if let cid = channel?.channelId, let sid = channel?.serverId { + let message = NIMQChatMessage() + message.messageObject = NIMImageObject(image: image) + message.from = IMKitLoginManager.instance.imAccid + QChatSystemMessageProvider.shared.sendMessage( + message: message, + session: NIMSession(forQChat: Int64(cid), qchatServerId: Int64(sid)) + ) { error in + print("sendImage error:\(error) ") + completion(error) + } } - - public func getMessageHistory(_ completion: @escaping (Error?, [QChatMessageFrame]?) -> Void) { - if let cid = self.channel?.channelId, let sid = self.channel?.serverId { - self.lastMsg = nil - var param = GetMessageHistoryParam(serverId: sid, channelId: cid) - param.lastMsg = self.lastMsg - QChatSystemMessageProvider.shared.getMessageHistory(param: param) { [weak self] error, messages in - if let messageArray = messages, messageArray.count > 0 { - self?.lastMsg = messageArray.last - self?.getUserInfo(messages: messageArray, { error, messageExts in - for msgExt in messageExts { - self?.addTimeForHistoryMessage(msgExt) - self?.messages.insert(msgExt, at: 0) - } - if let last = messageExts.last, let msg = self?.timeModel(last) { - self?.messages.insert(msg, at: 0) - } - completion(error, messageExts) - }) - }else { - completion(error, nil) - } + } + + public func getMessageHistory(_ completion: @escaping (Error?, [QChatMessageFrame]?) -> Void) { + if let cid = channel?.channelId, let sid = channel?.serverId { + lastMsg = nil + var param = GetMessageHistoryParam(serverId: sid, channelId: cid) + param.lastMsg = lastMsg + QChatSystemMessageProvider.shared + .getMessageHistory(param: param) { [weak self] error, messages in + if let messageArray = messages, messageArray.count > 0 { + self?.lastMsg = messageArray.last + self?.getUserInfo(messages: messageArray) { error, messageExts in + for msgExt in messageExts { + self?.addTimeForHistoryMessage(msgExt) + self?.messages.insert(msgExt, at: 0) + } + if let last = messageExts.last, let msg = self?.timeModel(last) { + self?.messages.insert(msg, at: 0) + } + completion(error, messageExts) } - }else { - completion(NSError.paramError(), nil) + } else { + completion(error, nil) + } } + } else { + completion(NSError.paramError(), nil) } - - public func getMoreMessageHistory(_ completion: @escaping (Error?, [QChatMessageFrame]?) -> Void) { - if let cid = self.channel?.channelId, let sid = self.channel?.serverId { - var param = GetMessageHistoryParam(serverId: sid, channelId: cid) - param.lastMsg = self.lastMsg - QChatSystemMessageProvider.shared.getMessageHistory(param: param) { [weak self] error, messages in - if let messageArray = messages, messageArray.count > 0 { - self?.lastMsg = messageArray.last - self?.getUserInfo(messages: messageArray, { error, messageExts in - for msgExt in messageExts { - self?.addTimeForHistoryMessage(msgExt) - self?.messages.insert(msgExt, at: 0) - } - if let last = messageExts.last, let msg = self?.timeModel(last) { - self?.messages.insert(msg, at: 0) - } - completion(error, messageExts) - }) - }else { - completion(error, nil) - } + } + + public func getMoreMessageHistory(_ completion: @escaping (Error?, [QChatMessageFrame]?) + -> Void) { + if let cid = channel?.channelId, let sid = channel?.serverId { + var param = GetMessageHistoryParam(serverId: sid, channelId: cid) + param.lastMsg = lastMsg + QChatSystemMessageProvider.shared + .getMessageHistory(param: param) { [weak self] error, messages in + if let messageArray = messages, messageArray.count > 0 { + self?.lastMsg = messageArray.last + self?.getUserInfo(messages: messageArray) { error, messageExts in + for msgExt in messageExts { + self?.addTimeForHistoryMessage(msgExt) + self?.messages.insert(msgExt, at: 0) + } + if let last = messageExts.last, let msg = self?.timeModel(last) { + self?.messages.insert(msg, at: 0) + } + completion(error, messageExts) } - }else { - completion(NSError.paramError(), nil) + } else { + completion(error, nil) + } } + } else { + completion(NSError.paramError(), nil) } + } + + public func getUserInfo(messages: [NIMQChatMessage], + _ completion: @escaping (Error?, [QChatMessageFrame]) -> Void) { + var userIds = [String]() + var lastMsg: NIMQChatMessage? + var tmp = [QChatMessageFrame]() - public func getUserInfo(messages: [NIMQChatMessage], _ completion: @escaping (Error?, [QChatMessageFrame]) -> Void) { - var userIds = [String]() - var lastMsg: NIMQChatMessage? - var tmp = [QChatMessageFrame]() - - for message in messages { + for message in messages { // let isSend = message.from == CoreKitIMEngine.instance.imAccid - let msgExt = QChatMessageFrame() - msgExt.message = message - msgExt.showAvatar = lastMsg?.from != message.from - tmp.append(msgExt) - lastMsg = message - if let userId = message.from, msgExt.showAvatar { - userIds.append(userId) - } - } - if userIds.isEmpty { - completion(nil, tmp) - }else { - FriendProvider.shared.getUserInfoAdvanced(userIds: userIds) { userInfoList, error in - var result = [QChatMessageFrame]() - for msg in tmp { - for u in userInfoList { - if msg.message?.from == u.userId { - msg.avatar = u.userInfo?.thumbAvatarUrl - msg.nickname = u.userInfo?.nickName - } - } - result.append(msg) - } - completion(error, result) - } - } + let msgExt = QChatMessageFrame() + msgExt.message = message + msgExt.showAvatar = lastMsg?.from != message.from + tmp.append(msgExt) + lastMsg = message + if let userId = message.from, msgExt.showAvatar { + userIds.append(userId) + } } - - public func markMessageRead(time: TimeInterval) { - if let cid = self.channel?.channelId, let sid = self.channel?.serverId { - var param = MarkMessageReadParam(serverId: sid, channelId: cid) - param.ackTimestamp = time - weak var weakSelf = self - QChatSystemMessageProvider.shared.markMessageRead(param: param) { error in - if error != nil { - NELog.errorLog(weakSelf?.Tag ?? "QChatViewModel", desc: "❌markMessageRead failed,error = \(error!)") - } - + if userIds.isEmpty { + completion(nil, tmp) + } else { + FriendProvider.shared.getUserInfoAdvanced(userIds: userIds) { userInfoList, error in + var result = [QChatMessageFrame]() + for msg in tmp { + for u in userInfoList { + if msg.message?.from == u.userId { + msg.avatar = u.userInfo?.thumbAvatarUrl + msg.nickname = u.userInfo?.nickName } + } + result.append(msg) } + completion(error, result) + } } - - // MARK: NIMChatManagerDelegate - public func onRecvMessages(_ messages: [NIMQChatMessage]) { - print("\(#function) messages:\(messages.count)") - var channelMsgs = [NIMQChatMessage]() - for msg in messages { - if msg.qchatChannelId == self.channel?.channelId { - channelMsgs.append(msg) - } - } - self.getUserInfo(messages: channelMsgs) { error, msgExts in - for msgExt in msgExts { - self.addTimeMessage(msgExt) - self.messages.append(msgExt) - } - } - self.delegate?.onRecvMessages(channelMsgs) - } - - public func willSend(_ message: NIMQChatMessage) { - print("\(#function)") - if self.lastMsg == nil { - self.lastMsg = message - } - self.getUserInfo(messages: [message]) { error, msgExts in - for msgExt in msgExts { - self.addTimeMessage(msgExt) - self.messages.append(msgExt) - } - } - self.delegate?.willSend(message) + } + + public func markMessageRead(time: TimeInterval) { + if let cid = channel?.channelId, let sid = channel?.serverId { + var param = MarkMessageReadParam(serverId: sid, channelId: cid) + param.ackTimestamp = time + weak var weakSelf = self + QChatSystemMessageProvider.shared.markMessageRead(param: param) { error in + if error != nil { + NELog.errorLog( + weakSelf?.Tag ?? "QChatViewModel", + desc: "❌markMessageRead failed,error = \(error!)" + ) } - - public func send(_ message: NIMQChatMessage, progress: Float) { - print("\(#function) progress\(progress)") - self.delegate?.send(message, progress: progress) + } + } + } + + // MARK: NIMChatManagerDelegate + + public func onRecvMessages(_ messages: [NIMQChatMessage]) { + print("\(#function) messages:\(messages.count)") + var channelMsgs = [NIMQChatMessage]() + for msg in messages { + if msg.qchatChannelId == channel?.channelId { + channelMsgs.append(msg) + } + } + getUserInfo(messages: channelMsgs) { error, msgExts in + for msgExt in msgExts { + self.addTimeMessage(msgExt) + self.messages.append(msgExt) + } + } + delegate?.onRecvMessages(channelMsgs) + } + + public func willSend(_ message: NIMQChatMessage) { + print("\(#function)") + if lastMsg == nil { + lastMsg = message + } + getUserInfo(messages: [message]) { error, msgExts in + for msgExt in msgExts { + self.addTimeMessage(msgExt) + self.messages.append(msgExt) + } + } + delegate?.willSend(message) + } + + public func send(_ message: NIMQChatMessage, progress: Float) { + print("\(#function) progress\(progress)") + delegate?.send(message, progress: progress) + } + + public func send(_ message: NIMQChatMessage, didCompleteWithError error: Error?) { + print("\(#function) message deliveryState:\(message.deliveryState) error:\(error)") + if let e = error as NSError? { + if e.code == 403 { + var index = 0 + for (i, msg) in messages.enumerated() { + if message.messageId == msg.message?.messageId { + index = i + } } - - public func send(_ message: NIMQChatMessage, didCompleteWithError error: Error?) { - print("\(#function) message deliveryState:\(message.deliveryState) error:\(error)") - if let e = error as NSError? { - if e.code == 403 { - var index = 0 - for (i, msg) in self.messages.enumerated() { - if message.messageId == msg.message?.messageId { - index = i - } - } - self.messages.remove(at: index) - } - }else { - for (i, msg) in self.messages.enumerated() { - if message.messageId == msg.message?.messageId { - self.messages[i].message = message - break - } - } - } - self.delegate?.send(message, didCompleteWithError: error) + messages.remove(at: index) + } + } else { + for (i, msg) in messages.enumerated() { + if message.messageId == msg.message?.messageId { + messages[i].message = message + break } - - private func modelFromMessage(_ message: NIMQChatMessage) -> QChatMessageFrame { - -// let isSend = message.from == CoreKitIMEngine.instance.imAccid - let model = QChatMessageFrame() - model.showAvatar = message.from != self.messages.last?.message?.from - model.message = message - return model + } } - - // history message insert message at first of messages, send message add last of messages - private func addTimeMessage(_ message: QChatMessageFrame) { - let lastTs = self.messages.last?.message?.timestamp ?? 0.0 - let curTs = message.message?.timestamp ?? 0.0 - let dur = curTs - lastTs - if (dur / 60) > 5 { + delegate?.send(message, didCompleteWithError: error) + } + + private func modelFromMessage(_ message: NIMQChatMessage) -> QChatMessageFrame { +// let isSend = message.from == CoreKitIMEngine.instance.imAccid + let model = QChatMessageFrame() + model.showAvatar = message.from != messages.last?.message?.from + model.message = message + return model + } + + // history message insert message at first of messages, send message add last of messages + private func addTimeMessage(_ message: QChatMessageFrame) { + let lastTs = messages.last?.message?.timestamp ?? 0.0 + let curTs = message.message?.timestamp ?? 0.0 + let dur = curTs - lastTs + if (dur / 60) > 5 { // let model = QChatMessageFrame(isSender: true) // model.showTime = true // model.time = String.stringFromDate(date:Date(timeIntervalSince1970: curTs)) // model.showAvatar = false // model.cellHeight = 35 - self.messages.append(self.timeModel(message)) - } - } - - private func addTimeForHistoryMessage(_ message: QChatMessageFrame) { - let firstTs = self.messages.first?.message?.timestamp ?? 0.0 - let curTs = message.message?.timestamp ?? 0.0 - let dur = firstTs - curTs - if (dur / 60) > 5 { - let model = QChatMessageFrame() - model.showTime = true - model.time = String.stringFromDate(date:Date(timeIntervalSince1970: firstTs)) - model.showAvatar = false - model.cellHeight = 35 - self.messages.insert(model, at: 0) - } + messages.append(timeModel(message)) } - - private func timeModel(_ message: QChatMessageFrame) -> QChatMessageFrame { - let curTs = message.message?.timestamp ?? 0.0 - let model = QChatMessageFrame() - model.showTime = true - model.time = String.stringFromDate(date:Date(timeIntervalSince1970: curTs)) - model.showAvatar = false - model.cellHeight = 35 - return model + } + + private func addTimeForHistoryMessage(_ message: QChatMessageFrame) { + let firstTs = messages.first?.message?.timestamp ?? 0.0 + let curTs = message.message?.timestamp ?? 0.0 + let dur = firstTs - curTs + if (dur / 60) > 5 { + let model = QChatMessageFrame() + model.showTime = true + model.time = String.stringFromDate(date: Date(timeIntervalSince1970: firstTs)) + model.showAvatar = false + model.cellHeight = 35 + messages.insert(model, at: 0) } + } + + private func timeModel(_ message: QChatMessageFrame) -> QChatMessageFrame { + let curTs = message.message?.timestamp ?? 0.0 + let model = QChatMessageFrame() + model.showTime = true + model.time = String.stringFromDate(date: Date(timeIntervalSince1970: curTs)) + model.showAvatar = false + model.cellHeight = 35 + return model + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Common/Constants.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Common/Constants.swift index b57971d0..debeea66 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Common/Constants.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Common/Constants.swift @@ -1,96 +1,102 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation @_exported import NEKitCore @_exported import NEKitCommonUI let coreLoader = CoreLoader() -func localizable(_ key: String) -> String{ - return coreLoader.localizable(key) +func localizable(_ key: String) -> String { + coreLoader.localizable(key) } func getJSONStringFromDictionary(_ dictionary: [String: Any]) -> String { - if (!JSONSerialization.isValidJSONObject(dictionary)) { - print("not parse to json string") - return "" - } - if let data = try? JSONSerialization.data(withJSONObject: dictionary, options: []), - let JSONString = String(data: data, encoding: .utf8){ - return JSONString - } + if !JSONSerialization.isValidJSONObject(dictionary) { + print("not parse to json string") return "" + } + if let data = try? JSONSerialization.data(withJSONObject: dictionary, options: []), + let JSONString = String(data: data, encoding: .utf8) { + return JSONString + } + return "" } func getDictionaryFromJSONString(_ jsonString: String) -> NSDictionary? { - if let jsonData = jsonString.data(using: .utf8), - let dict = try? JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers) as? NSDictionary{ - return dict - } - return nil + if let jsonData = jsonString.data(using: .utf8), + let dict = try? JSONSerialization.jsonObject( + with: jsonData, + options: .mutableContainers + ) as? NSDictionary { + return dict + } + return nil } @objc public protocol ViewModelDelegate: AnyObject { - func dataDidChange() - func dataDidError(_ error: Error) - @objc optional func dataNoMore() + func dataDidChange() + func dataDidError(_ error: Error) + @objc optional func dataNoMore() } // MARK: 常量 -let kScreenWidth:CGFloat = UIScreen.main.bounds.size.width -let kScreenHeight:CGFloat = UIScreen.main.bounds.size.height + +let kScreenWidth: CGFloat = UIScreen.main.bounds.size.width +let kScreenHeight: CGFloat = UIScreen.main.bounds.size.height let kUISreenWidthScale = kScreenWidth / 375.0 let kUISreenHeightScale = kScreenHeight / 667.0 -let kNavigationHeight = 44.0 -let KStatusBarHeight = UIApplication.shared.statusBarFrame.height //获取statusBar的高度 +let kNavigationHeight = 44.0 +let KStatusBarHeight = UIApplication.shared.statusBarFrame.height // 获取statusBar的高度 /// 屏幕间隔 -let kScreenInterval:CGFloat = 20 - +let kScreenInterval: CGFloat = 20 // MARK: 字体 -let TextFont:((String ,Float ) -> UIFont) = { - (fontName:String ,fontSize:Float ) -> UIFont in - if #available(iOS 9.0, macOS 10,*) { - return UIFont.init(name: fontName, size: CGFloat(fontSize))! - }else { - return UIFont.systemFont(ofSize: CGFloat(fontSize)) - } -} -let DefaultTextFont:((Float) -> UIFont) = { - (fontSize:Float ) -> UIFont in - return TextFont("PingFangSC-Regular",fontSize) +let TextFont: ((String, Float) -> UIFont) = { + (fontName: String, fontSize: Float) -> UIFont in + if #available(iOS 9.0, macOS 10,*) { + return UIFont(name: fontName, size: CGFloat(fontSize))! + } else { + return UIFont.systemFont(ofSize: CGFloat(fontSize)) + } } - - +let DefaultTextFont: ((Float) -> UIFont) = { + (fontSize: Float) -> UIFont in + TextFont("PingFangSC-Regular", fontSize) +} // MARK: 颜色 -let TextNormalColor:UIColor = HexRGB(0x333333) -let SubTextColor:UIColor = HexRGB(0x666666) -let PlaceholderTextColor:UIColor = HexRGB(0xA6ADB6) +let TextNormalColor: UIColor = HexRGB(0x333333) +let SubTextColor: UIColor = HexRGB(0x666666) +let PlaceholderTextColor: UIColor = HexRGB(0xA6ADB6) -let HexRGB:((Int) -> UIColor) = { (rgbValue : Int) -> UIColor in - return HexRGBAlpha(rgbValue,1.0) +let HexRGB: ((Int) -> UIColor) = { (rgbValue: Int) -> UIColor in + HexRGBAlpha(rgbValue, 1.0) } -let HexRGBAlpha:((Int,Float) -> UIColor) = { (rgbValue : Int, alpha : Float) -> UIColor in - return UIColor(red: CGFloat(CGFloat((rgbValue & 0xFF0000) >> 16)/255), green: CGFloat(CGFloat((rgbValue & 0xFF00) >> 8)/255), blue: CGFloat(CGFloat(rgbValue & 0xFF)/255), alpha: CGFloat(alpha)) +let HexRGBAlpha: ((Int, Float) -> UIColor) = { (rgbValue: Int, alpha: Float) -> UIColor in + UIColor( + red: CGFloat(CGFloat((rgbValue & 0xFF0000) >> 16) / 255), + green: CGFloat(CGFloat((rgbValue & 0xFF00) >> 8) / 255), + blue: CGFloat(CGFloat(rgbValue & 0xFF) / 255), + alpha: CGFloat(alpha) + ) } // MARK: notificationkey -struct NotificationName { - // 参数 serverId: string - static let createServer = Notification.Name(rawValue:"qchat.createServer") - //param channel: ChatChannel - static let createChannel = Notification.Name(rawValue:"qchat.createChannel") - static let updateChannel = Notification.Name(rawValue:"qchat.updateChannel") - static let deleteChannel = Notification.Name(rawValue:"qchat.deleteChannel") - -// static let login = Notification.Name(rawValue:"qchat.login") - static let logout = Notification.Name(rawValue:"qchat.logout") +enum NotificationName { + // 参数 serverId: string + static let createServer = Notification.Name(rawValue: "qchat.createServer") + // param channel: ChatChannel + static let createChannel = Notification.Name(rawValue: "qchat.createChannel") + static let updateChannel = Notification.Name(rawValue: "qchat.updateChannel") + static let deleteChannel = Notification.Name(rawValue: "qchat.deleteChannel") +// static let login = Notification.Name(rawValue:"qchat.login") + static let logout = Notification.Name(rawValue: "qchat.logout") } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Common/NEAuthManager.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Common/NEAuthManager.swift index f7f2b4dd..c44cb17b 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Common/NEAuthManager.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Common/NEAuthManager.swift @@ -1,6 +1,7 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import AVFoundation import Photos @@ -9,47 +10,42 @@ public typealias NEAuthCompletion = (_ granted: Bool) -> Void @objc public class YXAuthManager: NSObject { - - - /// 查询相机授权 - @objc - public class func hasCameraAuthorization() -> Bool { - let state = AVCaptureDevice.authorizationStatus(for: .video) - return state == .authorized - } - - /// 请求相机权限 - /// @param completion 结果 - @objc - public class func requestCameraAuthorization(_ completion: NEAuthCompletion?) { - AVCaptureDevice.requestAccess(for: .video) { granted in - DispatchQueue.main.async { - completion?(granted) - } - } + /// 查询相机授权 + @objc + public class func hasCameraAuthorization() -> Bool { + let state = AVCaptureDevice.authorizationStatus(for: .video) + return state == .authorized + } + + /// 请求相机权限 + /// @param completion 结果 + @objc + public class func requestCameraAuthorization(_ completion: NEAuthCompletion?) { + AVCaptureDevice.requestAccess(for: .video) { granted in + DispatchQueue.main.async { + completion?(granted) + } } - - - ///相册权限 - /// - Parameter completion: 结果 - class func photoAlbumPermissions(_ completion:NEAuthCompletion?) { - let authStatus = PHPhotoLibrary.authorizationStatus() - // .notDetermined .authorized .restricted .denied - if authStatus == .notDetermined { - // 第一次触发授权 alert - PHPhotoLibrary.requestAuthorization { (status:PHAuthorizationStatus) -> Void in - self.photoAlbumPermissions(completion) - } - } else if authStatus == .authorized { - if completion != nil { - completion!(true) - } - } else { - if completion != nil { - completion!(false) - } - } + } + + /// 相册权限 + /// - Parameter completion: 结果 + class func photoAlbumPermissions(_ completion: NEAuthCompletion?) { + let authStatus = PHPhotoLibrary.authorizationStatus() + // .notDetermined .authorized .restricted .denied + if authStatus == .notDetermined { + // 第一次触发授权 alert + PHPhotoLibrary.requestAuthorization { (status: PHAuthorizationStatus) in + self.photoAlbumPermissions(completion) + } + } else if authStatus == .authorized { + if completion != nil { + completion!(true) + } + } else { + if completion != nil { + completion!(false) + } } - - + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Common/QChatConstantValue.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Common/QChatConstantValue.swift index 628b126f..895acfab 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Common/QChatConstantValue.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Common/QChatConstantValue.swift @@ -1,29 +1,31 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation -//距离cell边缘的距离 +// 距离cell边缘的距离 public let qChat_cell_margin = 16.0 -//控件之间的间距 +// 控件之间的间距 public let qChat_margin = 8.0 -//头像宽高 +// 头像宽高 public let qChat_headWH = 32.0 -//时间cell的高度(固定) +// 时间cell的高度(固定) public let qChat_timeCellH = 21.0 -//图片最大宽高 -public let qChat_pic_size = CGSize.init(width: 150, height: 200) +// 图片最大宽高 +public let qChat_pic_size = CGSize(width: 150, height: 200) -//聊天小气泡角的宽度(后期扩展使用,目前默认为 0) +// 聊天小气泡角的宽度(后期扩展使用,目前默认为 0) public let qChat_angle_w = 0.0 -//单行气泡高度 +// 单行气泡高度 public let qChat_min_h = 46.0 -//内容尾部距离cell边框的间距 +// 内容尾部距离cell边框的间距 public let qChat_content_margin = 48.0 -//内容最大宽度 -public let qChat_content_maxW = (kScreenWidth - qChat_headWH - qChat_cell_margin - qChat_content_margin - qChat_margin) +// 内容最大宽度 +public let qChat_content_maxW = + (kScreenWidth - qChat_headWH - qChat_cell_margin - qChat_content_margin - qChat_margin) diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Extension/AlertVCExtention.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Extension/AlertVCExtention.swift index 13ef401b..be30513b 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Extension/AlertVCExtention.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Extension/AlertVCExtention.swift @@ -1,15 +1,17 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation extension UIAlertController { - class func reconfimAlertView(title: String?, message: String?, confirm: @escaping () -> Void) -> UIAlertController { - let alert = UIAlertController(title: title, message: message, preferredStyle: .alert) - alert.addAction( UIAlertAction(title: localizable("cancel"), style: .cancel, handler: nil)) - alert.addAction(UIAlertAction(title: localizable("ok"), style: .default) { action in - confirm() - }) - return alert - } + class func reconfimAlertView(title: String?, message: String?, + confirm: @escaping () -> Void) -> UIAlertController { + let alert = UIAlertController(title: title, message: message, preferredStyle: .alert) + alert.addAction(UIAlertAction(title: localizable("cancel"), style: .cancel, handler: nil)) + alert.addAction(UIAlertAction(title: localizable("ok"), style: .default) { action in + confirm() + }) + return alert + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Extension/ColorExtension.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Extension/ColorExtension.swift index 404f7252..46bae3db 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Extension/ColorExtension.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Extension/ColorExtension.swift @@ -1,34 +1,32 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import UIKit public extension UIColor { // MARK: text color - static let ne_darkText = UIColor(hexString: "#333333") - static let ne_greyText = UIColor(hexString: "#666666") - static let ne_lightText = UIColor(hexString: "#999999") - static let ne_blueText = UIColor(hexString: "#337EFF") - static let ne_redText = UIColor(hexString: "#E6605C") - static let ne_disableRedText = UIColor(hexString: "#E6605C", 0.5) - static let ne_backcolor = UIColor(hexString: "F2F4F5") - static let ne_emptyTitleColor = UIColor(hexString: "B3B7BC") + + static let ne_darkText = UIColor(hexString: "#333333") + static let ne_greyText = UIColor(hexString: "#666666") + static let ne_lightText = UIColor(hexString: "#999999") + static let ne_blueText = UIColor(hexString: "#337EFF") + static let ne_redText = UIColor(hexString: "#E6605C") + static let ne_disableRedText = UIColor(hexString: "#E6605C", 0.5) + static let ne_backcolor = UIColor(hexString: "F2F4F5") + static let ne_emptyTitleColor = UIColor(hexString: "B3B7BC") // MARK: view background color - static let ne_lightBackgroundColor = UIColor(hexString: "#F1F1F6") - static let ne_defautAvatarColor = UIColor(hexString: "#537FF4") - static let ne_greenColor = UIColor(hexString: "#42C294") + static let ne_lightBackgroundColor = UIColor(hexString: "#F1F1F6") + static let ne_defautAvatarColor = UIColor(hexString: "#537FF4") + static let ne_greenColor = UIColor(hexString: "#42C294") - // MARK: border color - static let ne_borderColor = UIColor(hexString: "#DBDDE4") + static let ne_borderColor = UIColor(hexString: "#DBDDE4") // MARK: line color - static let ne_greyLine = UIColor(hexString: "#F5F8FC") - - static let ne_redColor = UIColor(hexString: "#F24957") + static let ne_greyLine = UIColor(hexString: "#F5F8FC") + static let ne_redColor = UIColor(hexString: "#F24957") } - - diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Extension/ImageExtension.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Extension/ImageExtension.swift index 547526bf..91e5c65e 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Extension/ImageExtension.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Extension/ImageExtension.swift @@ -1,16 +1,17 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import CoreGraphics import UIKit -extension UIImage { - public class func ne_imageNamed(name: String?) -> UIImage? { - guard let imageName = name else { - return nil - } - return coreLoader.loadImage(imageName) +public extension UIImage { + class func ne_imageNamed(name: String?) -> UIImage? { + guard let imageName = name else { + return nil + } + return coreLoader.loadImage(imageName) // guard let path = Bundle(for: QChatBaseCell.self).resourcePath?.appending("/NEKitQChatUI.bundle") else { // print("Image:\(imageName) path: nil") // return nil @@ -19,7 +20,5 @@ extension UIImage { // print("Bundle:\(Bundle(path: path))") // print("imageName:\(imageName) image:\(image)") // return image - } - - + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Extension/NEErrorExtension.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Extension/NEErrorExtension.swift index 54c01e4a..25e9ae94 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Extension/NEErrorExtension.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Extension/NEErrorExtension.swift @@ -1,10 +1,15 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation extension NSError { - class func paramError() -> NSError { - return NSError(domain: "com.qchat.doamin", code: 600, userInfo: ["message":localizable("param_error")]) - } + class func paramError() -> NSError { + NSError( + domain: "com.qchat.doamin", + code: 600, + userInfo: ["message": localizable("param_error")] + ) + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Extension/QChatStringExtension.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Extension/QChatStringExtension.swift index b15c0959..f8d0a42e 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Extension/QChatStringExtension.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Extension/QChatStringExtension.swift @@ -1,45 +1,43 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation extension String { - - //计算文字size - static func getTextRectSize(_ text:String,font:UIFont,size:CGSize) -> CGSize { - - let attributes = [NSAttributedString.Key.font: font] - let option = NSStringDrawingOptions.usesLineFragmentOrigin - let rect:CGRect = text.boundingRect(with: size, options: option, - attributes: attributes, context: nil) - return rect.size; - } - - static func stringFromDate(date: Date) -> String { - let fmt = DateFormatter() - if Calendar.current.isDateInToday(date) { - fmt.dateFormat = "HH:mm" - }else { - if let firstDayYear = firstDayInYear() { - let dur = date.timeIntervalSince(firstDayYear) - if dur > 0 { - fmt.dateFormat = "MM月dd日 HH:mm" - }else { - fmt.dateFormat = "yyyy年MM月dd日 HH:mm" - } - }else { - fmt.dateFormat = "yyyy年MM月dd日 HH:mm" - } + // 计算文字size + static func getTextRectSize(_ text: String, font: UIFont, size: CGSize) -> CGSize { + let attributes = [NSAttributedString.Key.font: font] + let option = NSStringDrawingOptions.usesLineFragmentOrigin + let rect: CGRect = text.boundingRect(with: size, options: option, + attributes: attributes, context: nil) + return rect.size + } + + static func stringFromDate(date: Date) -> String { + let fmt = DateFormatter() + if Calendar.current.isDateInToday(date) { + fmt.dateFormat = "HH:mm" + } else { + if let firstDayYear = firstDayInYear() { + let dur = date.timeIntervalSince(firstDayYear) + if dur > 0 { + fmt.dateFormat = "MM月dd日 HH:mm" + } else { + fmt.dateFormat = "yyyy年MM月dd日 HH:mm" } - return fmt.string(from: date) - } - - static func firstDayInYear() -> Date? { - let format = DateFormatter() - format.dateFormat = "yyyy-MM-dd" - let year = Calendar.current.component(.year, from: Date()) - return format.date(from: "\(year)-01-01") + } else { + fmt.dateFormat = "yyyy年MM月dd日 HH:mm" + } } + return fmt.string(from: date) + } + static func firstDayInYear() -> Date? { + let format = DateFormatter() + format.dateFormat = "yyyy-MM-dd" + let year = Calendar.current.component(.year, from: Date()) + return format.date(from: "\(year)-01-01") + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/Controller/CreateServerViewController.swift b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/Controller/CreateServerViewController.swift index a828bbd6..99b4ad8c 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/Controller/CreateServerViewController.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/Controller/CreateServerViewController.swift @@ -1,86 +1,89 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit - public class CreateServerViewController: NEBaseViewController { - - public var serverViewModel = CreateServerViewModel() - - - public override func viewDidLoad() { - super.viewDidLoad() - initializeConfig() - setupSubviews() - } - - func initializeConfig() { - self.title = localizable("qchat_add_Server") - addLeftAction(localizable("close"), #selector(closeAction), self) - } - - func setupSubviews() { +public class CreateServerViewController: NEBaseViewController,UITableViewDelegate, UITableViewDataSource { + public var serverViewModel = CreateServerViewModel() - self.view.addSubview(tableView) - NSLayoutConstraint.activate([ - tableView.topAnchor.constraint(equalTo: self.view.topAnchor,constant: KStatusBarHeight+CGFloat(kNavigationHeight)+52), - tableView.leftAnchor.constraint(equalTo: self.view.leftAnchor), - tableView.rightAnchor.constraint(equalTo: self.view.rightAnchor), - tableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor), - ]) - } + override public func viewDidLoad() { + super.viewDidLoad() + initializeConfig() + setupSubviews() + } + func initializeConfig() { + title = localizable("qchat_add_Server") + addLeftAction(localizable("close"), #selector(closeAction), self) + } + func setupSubviews() { + view.addSubview(tableView) + NSLayoutConstraint.activate([ + tableView.topAnchor.constraint( + equalTo: view.topAnchor, + constant: KStatusBarHeight + CGFloat(kNavigationHeight) + 52 + ), + tableView.leftAnchor.constraint(equalTo: view.leftAnchor), + tableView.rightAnchor.constraint(equalTo: view.rightAnchor), + tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), + ]) + } - private lazy var tableView:UITableView = { - let tableView = UITableView.init(frame: .zero, style: .plain) - tableView.translatesAutoresizingMaskIntoConstraints = false - tableView.separatorStyle = .none - tableView.delegate = self - tableView.dataSource = self - tableView.register(NECreateServerCell.self, forCellReuseIdentifier: "\(NSStringFromClass(NECreateServerCell.self))") - tableView.rowHeight = 60 - tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.1)) - return tableView - }() -} - -extension CreateServerViewController { - - @objc func closeAction(sender:UIButton) { - self.navigationController?.dismiss(animated: true, completion: nil) + private lazy var tableView: UITableView = { + let tableView = UITableView(frame: .zero, style: .plain) + tableView.translatesAutoresizingMaskIntoConstraints = false + tableView.separatorStyle = .none + tableView.delegate = self + tableView.dataSource = self + tableView.register( + NECreateServerCell.self, + forCellReuseIdentifier: "\(NSStringFromClass(NECreateServerCell.self))" + ) + tableView.rowHeight = 60 + tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.1)) + return tableView + }() + + @objc func closeAction(sender: UIButton) { + navigationController?.dismiss(animated: true, completion: nil) } -} - -extension CreateServerViewController:UITableViewDelegate,UITableViewDataSource { - + + //MARK: UITableViewDelegate, UITableViewDataSource public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return serverViewModel.dataArray.count + serverViewModel.dataArray.count } - - public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(withIdentifier: "\(NSStringFromClass(NECreateServerCell.self))", for: indexPath) as! NECreateServerCell - let model = serverViewModel.dataArray[indexPath.row] - cell.model = model - return cell + + public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(NSStringFromClass(NECreateServerCell.self))", + for: indexPath + ) as! NECreateServerCell + let model = serverViewModel.dataArray[indexPath.row] + cell.model = model + return cell } - + public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - - if indexPath.row == 0 { - let mineCreateCtrl = MineCreateServerController() - self.navigationController?.pushViewController(mineCreateCtrl, animated: true) - }else if indexPath.row == 1{ - let otherCtrl = JoinOtherServiceController() - self.navigationController?.pushViewController(otherCtrl, animated: true) - } + if indexPath.row == 0 { + let mineCreateCtrl = MineCreateServerController() + navigationController?.pushViewController(mineCreateCtrl, animated: true) + } else if indexPath.row == 1 { + let otherCtrl = JoinOtherServiceController() + navigationController?.pushViewController(otherCtrl, animated: true) + } } - - public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - return 76 + + public func tableView(_ tableView: UITableView, + heightForRowAt indexPath: IndexPath) -> CGFloat { + 76 } - - } + + + + diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/Controller/JoinOtherServiceController.swift b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/Controller/JoinOtherServiceController.swift index 158d227d..9fd1c86d 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/Controller/JoinOtherServiceController.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/Controller/JoinOtherServiceController.swift @@ -1,6 +1,7 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCore @@ -8,173 +9,192 @@ import NEKitCoreIM import NEKitCommon import IQKeyboardManagerSwift -public class JoinOtherServiceController: NEBaseViewController { +public class JoinOtherServiceController: NEBaseViewController,UITableViewDelegate, UITableViewDataSource { + private let tag = "JoinOtherServiceController" + public var serversArray = [QChatServer]() + public var serverViewModel = CreateServerViewModel() + public var channelViewModel = QChatChannelViewModel() - private let tag = "JoinOtherServiceController" - public var serversArray = [QChatServer]() - public var serverViewModel = CreateServerViewModel() - public var channelViewModel = QChatChannelViewModel() + override public func viewDidLoad() { + super.viewDidLoad() + initializeConfig() + setupSubviews() + } - public override func viewDidLoad() { - super.viewDidLoad() - initializeConfig() - setupSubviews() - } - - func initializeConfig(){ - self.title = localizable("qchat_join_otherServer") - IQKeyboardManager.shared.enableAutoToolbar = true - } - - func setupSubviews(){ - self.view.addSubview(searchTextField) - self.view.addSubview(tableView) - NSLayoutConstraint.activate([ - searchTextField.topAnchor.constraint(equalTo: self.view.topAnchor, constant: CGFloat(kNavigationHeight) + KStatusBarHeight + 20), - searchTextField.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: kScreenInterval), - searchTextField.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: -kScreenInterval), - searchTextField.heightAnchor.constraint(equalToConstant: 32) - ]) - - NSLayoutConstraint.activate([ - tableView.topAnchor.constraint(equalTo: searchTextField.bottomAnchor,constant: 20), - tableView.leftAnchor.constraint(equalTo: self.view.leftAnchor), - tableView.rightAnchor.constraint(equalTo: self.view.rightAnchor), - tableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor), - ]) - } - + func initializeConfig() { + title = localizable("qchat_join_otherServer") + IQKeyboardManager.shared.enableAutoToolbar = true + } - // MARK: lazyMethod - private lazy var searchTextField:SearchTextField = { - let textField = SearchTextField() - - let image = UIImage(named:"otherService_search_icon", - in: Bundle(for: type(of:self)), - compatibleWith: nil) - let leftImageView = UIImageView.init(image: image) - textField.contentMode = .center - textField.leftView = leftImageView - textField.leftViewMode = .always - textField.placeholder = localizable("搜索服务器ID") - textField.font = DefaultTextFont(14) - textField.textColor = TextNormalColor - textField.translatesAutoresizingMaskIntoConstraints = false - textField.layer.cornerRadius = 8 - textField.backgroundColor = HexRGB(0xEFF1F4) - textField.clearButtonMode = .whileEditing - textField.addTarget(self, action: #selector(searchTextFieldChange), for: .editingDidEnd) - textField.keyboardType = .numberPad - return textField - }() - - - private lazy var tableView:UITableView = { - let tableView = UITableView.init(frame: .zero, style: .plain) - tableView.translatesAutoresizingMaskIntoConstraints = false - tableView.separatorStyle = .none - tableView.delegate = self - tableView.dataSource = self - tableView.register(NESearchServerCell.self, forCellReuseIdentifier: "\(NSStringFromClass(NESearchServerCell.self))") - tableView.rowHeight = 60 - tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.1)) - return tableView - }() + func setupSubviews() { + view.addSubview(searchTextField) + view.addSubview(tableView) + NSLayoutConstraint.activate([ + searchTextField.topAnchor.constraint( + equalTo: view.topAnchor, + constant: CGFloat(kNavigationHeight) + KStatusBarHeight + 20 + ), + searchTextField.leftAnchor.constraint( + equalTo: view.leftAnchor, + constant: kScreenInterval + ), + searchTextField.rightAnchor.constraint( + equalTo: view.rightAnchor, + constant: -kScreenInterval + ), + searchTextField.heightAnchor.constraint(equalToConstant: 32), + ]) + + NSLayoutConstraint.activate([ + tableView.topAnchor.constraint(equalTo: searchTextField.bottomAnchor, constant: 20), + tableView.leftAnchor.constraint(equalTo: view.leftAnchor), + tableView.rightAnchor.constraint(equalTo: view.rightAnchor), + tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), + ]) + } + + // MARK: lazyMethod + + private lazy var searchTextField: SearchTextField = { + let textField = SearchTextField() + + let image = UIImage(named: "otherService_search_icon", + in: Bundle(for: type(of: self)), + compatibleWith: nil) + let leftImageView = UIImageView(image: image) + textField.contentMode = .center + textField.leftView = leftImageView + textField.leftViewMode = .always + textField.placeholder = localizable("搜索服务器ID") + textField.font = DefaultTextFont(14) + textField.textColor = TextNormalColor + textField.translatesAutoresizingMaskIntoConstraints = false + textField.layer.cornerRadius = 8 + textField.backgroundColor = HexRGB(0xEFF1F4) + textField.clearButtonMode = .whileEditing + textField.addTarget(self, action: #selector(searchTextFieldChange), for: .editingDidEnd) + textField.keyboardType = .numberPad + return textField + }() + + private lazy var tableView: UITableView = { + let tableView = UITableView(frame: .zero, style: .plain) + tableView.translatesAutoresizingMaskIntoConstraints = false + tableView.separatorStyle = .none + tableView.delegate = self + tableView.dataSource = self + tableView.register( + NESearchServerCell.self, + forCellReuseIdentifier: "\(NSStringFromClass(NESearchServerCell.self))" + ) + tableView.rowHeight = 60 + tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.1)) + return tableView + }() + + private lazy var emptyView: EmptyDataView = { + let view = EmptyDataView( + imageName: "searchServer_noMoreData", + content: "暂无你要的服务器ID", + frame: tableView.bounds + ) + return view + }() - private lazy var emptyView:EmptyDataView = { - let view = EmptyDataView(imageName: "searchServer_noMoreData", content: "暂无你要的服务器ID",frame: tableView.bounds) - return view - }() -} + @objc func searchTextFieldChange(textfield: SearchTextField) { + // 选择高亮文本在进行搜索 + // let textRange = textfield.markedTextRange + // if textRange == nil || ((textRange?.isEmpty) == nil) { + // print("111") + // } -//MARK: UITableViewDelegate UITableViewDataSource -extension JoinOtherServiceController:UITableViewDelegate,UITableViewDataSource { + if !NEChatDetectNetworkTool.shareInstance.isNetworkRecahability() { + showToast("当前网络错误") + return + } + + guard let content = textfield.text else { + return + } + // 空字符串判断 + if content.isBlank { + emptyView.removeFromSuperview() + return + } + + let param = QChatGetServersParam(serverIds: [NSNumber(value: UInt64(content)!)]) + serverViewModel.getServers(parameter: param) { error, serversArray in + if error == nil { + self.serversArray = serversArray?.servers ?? Array() + if self.serversArray.isEmpty { + self.tableView.addSubview(self.emptyView) + return + } else { + self.emptyView.removeFromSuperview() + } + self.tableView.reloadData() + } else { + NELog.errorLog(self.tag, desc: "❌getServers failed,error = \(error!)") + } + } + } + // MARK: UITableViewDelegate UITableViewDataSource public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return serversArray.count + serversArray.count } - - public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(withIdentifier: "\(NSStringFromClass(NESearchServerCell.self))", for: indexPath) as! NESearchServerCell - cell.serverModel = serversArray[indexPath.row] - weak var weakSelf = self - cell.joinServerCallBack = { - - let successView = InviteMemberView(frame: CGRect.init(x: (kScreenWidth-176)/2, y: KStatusBarHeight, width: 176, height: 55)) - successView.showSuccessView() - } - return cell + + public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(NSStringFromClass(NESearchServerCell.self))", + for: indexPath + ) as! NESearchServerCell + cell.serverModel = serversArray[indexPath.row] + weak var weakSelf = self + cell.joinServerCallBack = { + let successView = + InviteMemberView(frame: CGRect(x: (kScreenWidth - 176) / 2, y: KStatusBarHeight, + width: 176, height: 55)) + successView.showSuccessView() + } + return cell } - - public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - guard let serverId = serversArray[indexPath.row].serverId else { return } - let param = QChatGetChannelsByPageParam(timeTag: 0, serverId: serverId) - weak var weakSelf = self - channelViewModel.getChannelsByPage(parameter: param) {error, result in - if error == nil { - guard let dataArray = result?.channels else { return } - let chatVC = QChatViewController(channel: dataArray.first) - weakSelf?.navigationController?.pushViewController(chatVC, animated: true) - }else { - print("getChannelsByPage failed,error = \(error!)") - } + public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + guard let serverId = serversArray[indexPath.row].serverId else { return } + let param = QChatGetChannelsByPageParam(timeTag: 0, serverId: serverId) + weak var weakSelf = self + channelViewModel.getChannelsByPage(parameter: param) { error, result in + if error == nil { + guard let dataArray = result?.channels else { return } + let chatVC = QChatViewController(channel: dataArray.first) + weakSelf?.navigationController?.pushViewController(chatVC, animated: true) + } else { + print("getChannelsByPage failed,error = \(error!)") } + } } } -//MARK: private Method -extension JoinOtherServiceController { - func showAlert(){ - let alertCtrl = UIAlertController.init(title: localizable("无法加入?"), message: localizable("你被该服务器封禁,无法加入。"), preferredStyle: .alert) - let okAction = UIAlertAction.init(title: localizable("知道了"), style: .default, handler: nil) - alertCtrl.addAction(okAction) - self.present(alertCtrl, animated: true, completion: nil) - } - - @objc func searchTextFieldChange(textfield:SearchTextField){ - - //选择高亮文本在进行搜索 -// let textRange = textfield.markedTextRange -// if textRange == nil || ((textRange?.isEmpty) == nil) { -// print("111") -// } - - if !NEChatDetectNetworkTool.shareInstance.isNetworkRecahability() { - showToast("当前网络错误") - return - } - - guard let content = textfield.text else { - return - } - //空字符串判断 - if content.isBlank { - self.emptyView.removeFromSuperview() - return - } - - let param = QChatGetServersParam(serverIds: [NSNumber.init(value: UInt64(content)!)]) - serverViewModel.getServers(parameter: param) { error, serversArray in - if error == nil{ - self.serversArray = serversArray?.servers ?? Array() - if self.serversArray.isEmpty { - self.tableView.addSubview(self.emptyView) - return - }else { - self.emptyView.removeFromSuperview() - } - self.tableView.reloadData() - }else { - NELog.errorLog(self.tag, desc: "❌getServers failed,error = \(error!)") - } - } - } +// MARK: private Method + +extension JoinOtherServiceController { + func showAlert() { + let alertCtrl = UIAlertController( + title: localizable("无法加入?"), + message: localizable("你被该服务器封禁,无法加入。"), + preferredStyle: .alert + ) + let okAction = UIAlertAction(title: localizable("知道了"), style: .default, handler: nil) + alertCtrl.addAction(okAction) + present(alertCtrl, animated: true, completion: nil) + } } +// MARK: SearchTextField -//MARK: SearchTextField // class SearchTextField:UITextField { // // override func leftViewRect(forBounds bounds: CGRect) -> CGRect { @@ -202,4 +222,4 @@ extension JoinOtherServiceController { // rect.origin.x += 5 // return rect // } -//} +// } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/Controller/MemberListViewController.swift b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/Controller/MemberListViewController.swift index 8f99ba38..d5ccf03d 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/Controller/MemberListViewController.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/Controller/MemberListViewController.swift @@ -1,144 +1,144 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCoreIM import NEKitCore -public class MemberListViewController: NEBaseViewController { +public class MemberListViewController: NEBaseViewController,UITableViewDelegate, UITableViewDataSource { + public var serverViewModel = CreateServerViewModel() + public var memberViewModel = MemberListViewModel() - public var serverViewModel = CreateServerViewModel() - public var memberViewModel = MemberListViewModel() - - var dataArray:Array? - var serverId: UInt64? - - public override func viewDidLoad() { - super.viewDidLoad() - initializeConfig() - requestData() - addSubviews() - // Do any additional setup after loading the view. - } - - func requestData(){ - guard let id = serverId else { - print("serverId is nil") - return - } - let param = QChatGetServerMembersByPageParam(timeTag: 0, serverId: id) - weak var weakSelf = self - memberViewModel.requestServerMemebersByPage(param: param) { error, serverMemberArray in - if error == nil { - weakSelf?.dataArray = serverMemberArray - weakSelf?.tableView.reloadData() - }else { - - } - } + var dataArray: [ServerMemeber]? + var serverId: UInt64? + + override public func viewDidLoad() { + super.viewDidLoad() + initializeConfig() + requestData() + addSubviews() + // Do any additional setup after loading the view. + } + + func requestData() { + guard let id = serverId else { + print("serverId is nil") + return } - - func initializeConfig() { - self.title = "成员" - addRightAction(UIImage.ne_imageNamed(name: "sign_add"), #selector(addMemberClick), self) - } - - func addSubviews(){ - self.view.addSubview(tableView) - NSLayoutConstraint.activate([ - tableView.topAnchor.constraint(equalTo: self.view.topAnchor), - tableView.leftAnchor.constraint(equalTo: self.view.leftAnchor), - tableView.rightAnchor.constraint(equalTo: self.view.rightAnchor), - tableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor) - ]) + let param = QChatGetServerMembersByPageParam(timeTag: 0, serverId: id) + weak var weakSelf = self + memberViewModel.requestServerMemebersByPage(param: param) { error, serverMemberArray in + if error == nil { + weakSelf?.dataArray = serverMemberArray + weakSelf?.tableView.reloadData() + } else {} } + } - //MARK: lazy method - private lazy var tableView:UITableView = { - let tableView = UITableView.init(frame: .zero, style: .plain) - tableView.translatesAutoresizingMaskIntoConstraints = false - tableView.separatorStyle = .none - tableView.delegate = self - tableView.dataSource = self - tableView.register(NEGroupIdentityMemberCell.self, forCellReuseIdentifier: "\(NSStringFromClass(NEGroupIdentityMemberCell.self))") - tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.1)) - tableView.estimatedRowHeight = 125 - return tableView - }() -} + func initializeConfig() { + title = "成员" + addRightAction(UIImage.ne_imageNamed(name: "sign_add"), #selector(addMemberClick), self) + } + + func addSubviews() { + view.addSubview(tableView) + NSLayoutConstraint.activate([ + tableView.topAnchor.constraint(equalTo: view.topAnchor), + tableView.leftAnchor.constraint(equalTo: view.leftAnchor), + tableView.rightAnchor.constraint(equalTo: view.rightAnchor), + tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), + ]) + } + // MARK: lazy method -extension MemberListViewController:UITableViewDelegate,UITableViewDataSource { + private lazy var tableView: UITableView = { + let tableView = UITableView(frame: .zero, style: .plain) + tableView.translatesAutoresizingMaskIntoConstraints = false + tableView.separatorStyle = .none + tableView.delegate = self + tableView.dataSource = self + tableView.register( + NEGroupIdentityMemberCell.self, + forCellReuseIdentifier: "\(NSStringFromClass(NEGroupIdentityMemberCell.self))" + ) + tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.1)) + tableView.estimatedRowHeight = 125 + return tableView + }() - @objc func addMemberClick(sender:UIButton) { - - Router.shared.register(ContactSelectedUsersRouter) {[weak self] param in - print("param\(param)") - if let userIds = param["accids"] as? [String] { - print("userIds:\(userIds)") - guard let serverId = self?.serverId else { return } - self?.serverViewModel.inviteMembersToServer(serverId: serverId, accids: userIds) { error in - if error == nil{ - self?.requestData() - } - } + //MAKR: UITableViewDelegate, UITableViewDataSource + @objc func addMemberClick(sender: UIButton) { + Router.shared.register(ContactSelectedUsersRouter) { [weak self] param in + print("param\(param)") + if let userIds = param["accids"] as? [String] { + print("userIds:\(userIds)") + guard let serverId = self?.serverId else { return } + self?.serverViewModel + .inviteMembersToServer(serverId: serverId, accids: userIds) { error in + if error == nil { + self?.requestData() + } } } + } - Router.shared.use(ContactUserSelectRouter, parameters: ["nav": self.navigationController]) { obj, routerState, str in - print("obj:\(obj) routerState:\(routerState) str:\(str)") + Router.shared + .use(ContactUserSelectRouter, + parameters: ["nav": navigationController]) { obj, routerState, str in + print("obj:\(obj) routerState:\(routerState) str:\(str)") } - -// FIXME:router -// let contactCtrl = ContactsSelectedViewController() -// self.navigationController?.pushViewController(contactCtrl, animated: true) -// weak var weakSelf = self -// -// contactCtrl.callBack = {(selectMemberarray)->Void in -// -// guard let serverId = weakSelf?.serverId else { return } -// var accidArray = [String]() -// selectMemberarray.forEach { memberInfo in -// accidArray.append(memberInfo.user?.userId ?? "") -// } -// weakSelf?.serverViewModel.inviteMembersToServer(serverId: serverId, accids: accidArray) { error in -// if error == nil{ -// weakSelf?.requestData() -// } -// } -// } + + // FIXME: router + // let contactCtrl = ContactsSelectedViewController() + // self.navigationController?.pushViewController(contactCtrl, animated: true) + // weak var weakSelf = self + // + // contactCtrl.callBack = {(selectMemberarray)->Void in + // + // guard let serverId = weakSelf?.serverId else { return } + // var accidArray = [String]() + // selectMemberarray.forEach { memberInfo in + // accidArray.append(memberInfo.user?.userId ?? "") + // } + // weakSelf?.serverViewModel.inviteMembersToServer(serverId: serverId, accids: accidArray) { error in + // if error == nil{ + // weakSelf?.requestData() + // } + // } + // } } - - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return dataArray?.count ?? 0 + public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + dataArray?.count ?? 0 } - - public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - - let cell = tableView.dequeueReusableCell(withIdentifier: "\(NSStringFromClass(NEGroupIdentityMemberCell.self))", for: indexPath) as! NEGroupIdentityMemberCell - cell.memberModel = dataArray?[indexPath.row] - return cell + + public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(NSStringFromClass(NEGroupIdentityMemberCell.self))", + for: indexPath + ) as! NEGroupIdentityMemberCell + cell.memberModel = dataArray?[indexPath.row] + return cell } - + public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - -// let user = viewModel.limitUsers[indexPath.row] - if let member = dataArray?[indexPath.row] { - let editMember = QChatEditMemberViewController() - editMember.deleteCompletion = { - self.requestData() - } - editMember.changeCompletion = { - self.requestData() - } - let user = UserInfo(member) - editMember.user = user - navigationController?.pushViewController(editMember, animated: true) + // let user = viewModel.limitUsers[indexPath.row] + if let member = dataArray?[indexPath.row] { + let editMember = QChatEditMemberViewController() + editMember.deleteCompletion = { + self.requestData() } + editMember.changeCompletion = { + self.requestData() + } + let user = UserInfo(member) + editMember.user = user + navigationController?.pushViewController(editMember, animated: true) + } } - - } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/Controller/MineCreateServerController.swift b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/Controller/MineCreateServerController.swift index 9bf4e622..c1169132 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/Controller/MineCreateServerController.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/Controller/MineCreateServerController.swift @@ -1,6 +1,7 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import Toast_Swift @@ -8,230 +9,233 @@ import NEKitCoreIM import NIMSDK import NEKitCommon -public class MineCreateServerController: NEBaseViewController, UINavigationControllerDelegate { - - private let tag = "MineCreateServerController" - public var serverViewModel = CreateServerViewModel() - var headImageUrl:String? - - public override func viewDidLoad() { - super.viewDidLoad() - initializeConfig() - setupSubviews() - } - - func initializeConfig(){ - self.title = localizable("qchat_mine_add") - } - - func setupSubviews(){ - self.view.addSubview(uploadBgView) - uploadBgView.addSubview(cameraImageView) - uploadBgView.addSubview(uploadDesLabel) - self.view.addSubview(selectHeadImage) - self.view.addSubview(textField) - self.view.addSubview(bottomBtn) - - NSLayoutConstraint.activate([ - uploadBgView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor), - uploadBgView.topAnchor.constraint(equalTo: self.view.topAnchor,constant: CGFloat(kNavigationHeight)+KStatusBarHeight + 40), - uploadBgView.widthAnchor.constraint(equalToConstant: 80), - uploadBgView.heightAnchor.constraint(equalToConstant: 80), - ]) - - NSLayoutConstraint.activate([ - selectHeadImage.centerXAnchor.constraint(equalTo: self.view.centerXAnchor), - selectHeadImage.topAnchor.constraint(equalTo: self.view.topAnchor,constant: CGFloat(kNavigationHeight)+KStatusBarHeight + 40), - selectHeadImage.widthAnchor.constraint(equalToConstant: 80), - selectHeadImage.heightAnchor.constraint(equalToConstant: 80), - ]) - NSLayoutConstraint.activate([ - cameraImageView.centerXAnchor.constraint(equalTo: uploadBgView.centerXAnchor), - cameraImageView.topAnchor.constraint(equalTo: uploadBgView.topAnchor,constant: 18), - ]) - - NSLayoutConstraint.activate([ - uploadDesLabel.centerXAnchor.constraint(equalTo: uploadBgView.centerXAnchor), - uploadDesLabel.topAnchor.constraint(equalTo: cameraImageView.bottomAnchor,constant: 9), - ]) - - NSLayoutConstraint.activate([ - textField.leftAnchor.constraint(equalTo: self.view.leftAnchor,constant: kScreenInterval), - textField.rightAnchor.constraint(equalTo: self.view.rightAnchor,constant: -kScreenInterval), - textField.topAnchor.constraint(equalTo: uploadBgView.bottomAnchor, constant: 40), - textField.heightAnchor.constraint(equalToConstant: 40) - ]) - - NSLayoutConstraint.activate([ - bottomBtn.leftAnchor.constraint(equalTo: self.view.leftAnchor,constant: kScreenInterval), - bottomBtn.rightAnchor.constraint(equalTo: self.view.rightAnchor,constant: -kScreenInterval), - bottomBtn.topAnchor.constraint(equalTo: textField.bottomAnchor, constant: 40), - bottomBtn.heightAnchor.constraint(equalToConstant: 40) - ]) - - - } +public class MineCreateServerController: NEBaseViewController, UINavigationControllerDelegate,UITextFieldDelegate { + private let tag = "MineCreateServerController" + public var serverViewModel = CreateServerViewModel() + var headImageUrl: String? - // MARK : lazyMethod - private lazy var uploadBgView:UIButton = { - let button = UIButton() - button.setBackgroundImage(UIImage.ne_imageNamed(name: "uploadPic_bg_icon"), for: .normal) - button.setBackgroundImage(UIImage.ne_imageNamed(name: "uploadPic_bg_icon"), for: .highlighted) - button.translatesAutoresizingMaskIntoConstraints = false - button.addTarget(self, action: #selector(uploadBgViewClick), for: .touchUpInside) - return button - - }() - - - private lazy var selectHeadImage:UIImageView = { - let imageView = UIImageView.init() - imageView.translatesAutoresizingMaskIntoConstraints = false - imageView.layer.cornerRadius = 40 - imageView.clipsToBounds = true - return imageView - }() - - private lazy var cameraImageView:UIImageView = { - let imageView = UIImageView.init(image: UIImage.ne_imageNamed(name: "upload_camera")) - imageView.translatesAutoresizingMaskIntoConstraints = false - return imageView - }() - - private lazy var uploadDesLabel:UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.text = localizable("上传头像") - label.textColor = HexRGB(0x656A72) - label.font = DefaultTextFont(12) - return label - }() - - private lazy var textField:UITextField = { - let textField = UITextField() - textField.setValue(NSNumber.init(value:10), forKey: "paddingLeft") - textField.placeholder = localizable(" 请输入服务器名称") - textField.font = DefaultTextFont(16) - textField.textColor = TextNormalColor - textField.translatesAutoresizingMaskIntoConstraints = false - textField.layer.cornerRadius = 8 - textField.backgroundColor = HexRGB(0xEFF1F4) - textField.delegate = self - textField.addTarget(self, action: #selector(textContentChanged), for: .editingChanged) - textField.clearButtonMode = .whileEditing - return textField - }() - - private lazy var bottomBtn:UIButton = { - let button = UIButton() - button.translatesAutoresizingMaskIntoConstraints = false - button.setTitle(localizable("create"), for: .normal) - button.setTitleColor(UIColor.white, for: .normal) - button.titleLabel?.font = DefaultTextFont(16) - button.backgroundColor = HexRGBAlpha(0x337EFF,0.5) - button.layer.cornerRadius = 8 - button.addTarget(self, action: #selector(createServerBtnClick), for: .touchUpInside) - return button - }() + override public func viewDidLoad() { + super.viewDidLoad() + initializeConfig() + setupSubviews() + } -} + func initializeConfig() { + title = localizable("qchat_mine_add") + } + func setupSubviews() { + view.addSubview(uploadBgView) + uploadBgView.addSubview(cameraImageView) + uploadBgView.addSubview(uploadDesLabel) + view.addSubview(selectHeadImage) + view.addSubview(textField) + view.addSubview(bottomBtn) -extension MineCreateServerController:UITextFieldDelegate{ - - //Bottom button click - - @objc func createServerBtnClick(sender:UIButton) { - - guard let serverName = textField.text,serverName.count>0 else { return } - - if NEChatDetectNetworkTool.shareInstance.isNetworkRecahability() { - sender.isEnabled = false - }else { - showToast("当前网络错误") + NSLayoutConstraint.activate([ + uploadBgView.centerXAnchor.constraint(equalTo: view.centerXAnchor), + uploadBgView.topAnchor.constraint( + equalTo: view.topAnchor, + constant: CGFloat(kNavigationHeight) + KStatusBarHeight + 40 + ), + uploadBgView.widthAnchor.constraint(equalToConstant: 80), + uploadBgView.heightAnchor.constraint(equalToConstant: 80), + ]) + + NSLayoutConstraint.activate([ + selectHeadImage.centerXAnchor.constraint(equalTo: view.centerXAnchor), + selectHeadImage.topAnchor.constraint( + equalTo: view.topAnchor, + constant: CGFloat(kNavigationHeight) + KStatusBarHeight + 40 + ), + selectHeadImage.widthAnchor.constraint(equalToConstant: 80), + selectHeadImage.heightAnchor.constraint(equalToConstant: 80), + ]) + NSLayoutConstraint.activate([ + cameraImageView.centerXAnchor.constraint(equalTo: uploadBgView.centerXAnchor), + cameraImageView.topAnchor.constraint(equalTo: uploadBgView.topAnchor, constant: 18), + ]) + + NSLayoutConstraint.activate([ + uploadDesLabel.centerXAnchor.constraint(equalTo: uploadBgView.centerXAnchor), + uploadDesLabel.topAnchor.constraint(equalTo: cameraImageView.bottomAnchor, constant: 9), + ]) + + NSLayoutConstraint.activate([ + textField.leftAnchor.constraint(equalTo: view.leftAnchor, constant: kScreenInterval), + textField.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -kScreenInterval), + textField.topAnchor.constraint(equalTo: uploadBgView.bottomAnchor, constant: 40), + textField.heightAnchor.constraint(equalToConstant: 40), + ]) + + NSLayoutConstraint.activate([ + bottomBtn.leftAnchor.constraint(equalTo: view.leftAnchor, constant: kScreenInterval), + bottomBtn.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -kScreenInterval), + bottomBtn.topAnchor.constraint(equalTo: textField.bottomAnchor, constant: 40), + bottomBtn.heightAnchor.constraint(equalToConstant: 40), + ]) + } + + // MARK: lazyMethod + + private lazy var uploadBgView: UIButton = { + let button = UIButton() + button.setBackgroundImage(UIImage.ne_imageNamed(name: "uploadPic_bg_icon"), for: .normal) + button.setBackgroundImage( + UIImage.ne_imageNamed(name: "uploadPic_bg_icon"), + for: .highlighted + ) + button.translatesAutoresizingMaskIntoConstraints = false + button.addTarget(self, action: #selector(uploadBgViewClick), for: .touchUpInside) + return button + + }() + + private lazy var selectHeadImage: UIImageView = { + let imageView = UIImageView() + imageView.translatesAutoresizingMaskIntoConstraints = false + imageView.layer.cornerRadius = 40 + imageView.clipsToBounds = true + return imageView + }() + + private lazy var cameraImageView: UIImageView = { + let imageView = UIImageView(image: UIImage.ne_imageNamed(name: "upload_camera")) + imageView.translatesAutoresizingMaskIntoConstraints = false + return imageView + }() + + private lazy var uploadDesLabel: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.text = localizable("上传头像") + label.textColor = HexRGB(0x656A72) + label.font = DefaultTextFont(12) + return label + }() + + private lazy var textField: UITextField = { + let textField = UITextField() + textField.setValue(NSNumber(value: 10), forKey: "paddingLeft") + textField.placeholder = localizable(" 请输入服务器名称") + textField.font = DefaultTextFont(16) + textField.textColor = TextNormalColor + textField.translatesAutoresizingMaskIntoConstraints = false + textField.layer.cornerRadius = 8 + textField.backgroundColor = HexRGB(0xEFF1F4) + textField.delegate = self + textField.addTarget(self, action: #selector(textContentChanged), for: .editingChanged) + textField.clearButtonMode = .whileEditing + return textField + }() + + private lazy var bottomBtn: UIButton = { + let button = UIButton() + button.translatesAutoresizingMaskIntoConstraints = false + button.setTitle(localizable("create"), for: .normal) + button.setTitleColor(UIColor.white, for: .normal) + button.titleLabel?.font = DefaultTextFont(16) + button.backgroundColor = HexRGBAlpha(0x337EFF, 0.5) + button.layer.cornerRadius = 8 + button.addTarget(self, action: #selector(createServerBtnClick), for: .touchUpInside) + return button + }() + + + @objc func createServerBtnClick(sender: UIButton) { + guard let serverName = textField.text, serverName.count > 0 else { return } + + if NEChatDetectNetworkTool.shareInstance.isNetworkRecahability() { + sender.isEnabled = false + } else { + showToast("当前网络错误") + return + } + + let param = CreateServerParam(name: textField.text!, icon: headImageUrl ?? "") + serverViewModel.createServer(parameter: param) { error, result in + + if error != nil { + NELog.errorLog(self.tag, desc: "❌createServer failed,error = \(error!)") + } else { + // 创建服务器成功后,默认创建好两个频道 + if let serverId = result?.server?.serverId { + NotificationCenter.default.post( + name: NotificationName.createServer, + object: serverId + ) + self.navigationController?.dismiss(animated: true, completion: nil) + } else { + print("serverId is nil") return + } } - - let param = CreateServerParam(name: textField.text!, icon: self.headImageUrl ?? "") - serverViewModel.createServer(parameter: param) { error, result in - - if error != nil { - NELog.errorLog(self.tag, desc: "❌createServer failed,error = \(error!)") - }else { - //创建服务器成功后,默认创建好两个频道 - if let serverId = result?.server?.serverId { - NotificationCenter.default.post(name: NotificationName.createServer, object: serverId) - self.navigationController?.dismiss(animated: true, completion: nil) - }else { - print("serverId is nil") - return - } - } - } - //应对wifi切换4G请求没有回调的处理结果 - DispatchQueue.main.asyncAfter(deadline: .now() + 1) { - sender.isEnabled = true - } - + } + // 应对wifi切换4G请求没有回调的处理结果 + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + sender.isEnabled = true + } } - - public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { - - let text = "\(textField.text ?? "")\(string)" - if text.count > 50 { - showToast("服务器命名不超过50个字符") - return false - } - - return true + //MARK : UITextFieldDelegate + public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, + replacementString string: String) -> Bool { + let text = "\(textField.text ?? "")\(string)" + if text.count > 50 { + showToast("服务器命名不超过50个字符") + return false + } + + return true } - - //Upload the picture - @objc func uploadBgViewClick(sender:UIButton){ - showBottomAlert(self) + + // Upload the picture + @objc func uploadBgViewClick(sender: UIButton) { + showBottomAlert(self) } - + @objc func textContentChanged() { - if textField.text?.count != 0 { - bottomBtn.isEnabled = true - bottomBtn.backgroundColor = HexRGB(0x337EFF) - }else { - bottomBtn.isEnabled = false - bottomBtn.backgroundColor = HexRGBAlpha(0x337EFF,0.5) - } + if textField.text?.count != 0 { + bottomBtn.isEnabled = true + bottomBtn.backgroundColor = HexRGB(0x337EFF) + } else { + bottomBtn.isEnabled = false + bottomBtn.backgroundColor = HexRGBAlpha(0x337EFF, 0.5) + } } - - //MARK: UIImagePickerControllerDelegate - func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info:[UIImagePickerController.InfoKey : Any]) { - let image : UIImage = info[UIImagePickerController.InfoKey.editedImage] as! UIImage - uploadHeadImage(image: image) - self.dismiss(animated: true, completion: nil) + + // MARK: UIImagePickerControllerDelegate + + func imagePickerController(_ picker: UIImagePickerController, + didFinishPickingMediaWithInfo info: [UIImagePickerController + .InfoKey: Any]) { + let image: UIImage = info[UIImagePickerController.InfoKey.editedImage] as! UIImage + uploadHeadImage(image: image) + dismiss(animated: true, completion: nil) } - - public func uploadHeadImage(image:UIImage){ - - self.view.makeToastActivity(.center) - if let imageData = image.jpegData(compressionQuality: 0.6) as NSData? { - let filePath = NSHomeDirectory().appending("/Documents/").appending(IMKitLoginManager.instance.imAccid) - let succcess = imageData.write(toFile: filePath, atomically: true) - - if succcess { - NIMSDK.shared().resourceManager.upload(filePath, progress: nil) { urlString, error in - if error == nil { - //显示设置的照片 - self.selectHeadImage.image = image - self.headImageUrl = urlString - print("upload image success") - }else { - print("upload image failed,error = \(error!)") - } - self.view.hideToastActivity() - - } + + public func uploadHeadImage(image: UIImage) { + view.makeToastActivity(.center) + if let imageData = image.jpegData(compressionQuality: 0.6) as NSData? { + let filePath = NSHomeDirectory().appending("/Documents/") + .appending(IMKitLoginManager.instance.imAccid) + let succcess = imageData.write(toFile: filePath, atomically: true) + + if succcess { + NIMSDK.shared().resourceManager + .upload(filePath, progress: nil) { urlString, error in + if error == nil { + // 显示设置的照片 + self.selectHeadImage.image = image + self.headImageUrl = urlString + print("upload image success") + } else { + print("upload image failed,error = \(error!)") + } + self.view.hideToastActivity() } } + } } - - } + diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/Controller/QChatHomeViewController.swift b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/Controller/QChatHomeViewController.swift index b1a25127..87ce1cef 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/Controller/QChatHomeViewController.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/Controller/QChatHomeViewController.swift @@ -1,6 +1,7 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import UIKit @@ -12,346 +13,359 @@ import NEKitCommonUI import NEKitCommon public class QChatHomeViewController: UIViewController, ViewModelDelegate { - - public var serverViewModel = CreateServerViewModel() - public var serverListArray = [QChatServer]() - fileprivate var selectIndex = 0 - - public override func viewWillAppear(_ animated: Bool) { - self.navigationController?.navigationBar.isHidden = true - } + public var serverViewModel = CreateServerViewModel() + public var serverListArray = [QChatServer]() + fileprivate var selectIndex = 0 + + override public func viewWillAppear(_ animated: Bool) { + navigationController?.navigationBar.isHidden = true + } - public override func viewWillDisappear(_ animated: Bool) { - self.navigationController?.navigationBar.isHidden = false + override public func viewWillDisappear(_ animated: Bool) { + navigationController?.navigationBar.isHidden = false + } + override public func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + weak var weakSelf = self + NEChatDetectNetworkTool.shareInstance.netWorkReachability { status in + if status == .notReachable, let networkView = weakSelf?.brokenNetworkView { + weakSelf?.qChatBgView.addSubview(networkView) + } else { + weakSelf?.brokenNetworkView.removeFromSuperview() + } } - - public override func viewDidAppear(_ animated: Bool) { - super.viewDidAppear(animated) - weak var weakSelf = self - NEChatDetectNetworkTool.shareInstance.netWorkReachability() { status in - if status == .notReachable,let networkView = weakSelf?.brokenNetworkView{ - weakSelf?.qChatBgView.addSubview(networkView) - }else { - weakSelf?.brokenNetworkView.removeFromSuperview() - } - } + } + + override public func viewDidLoad() { + super.viewDidLoad() + serverViewModel.delegate = self + qChatBgView.viewmodel = serverViewModel + weak var weakSelf = self + serverViewModel.updateServerList = { + weakSelf?.tableView.reloadData() } - - public override func viewDidLoad() { - super.viewDidLoad() - serverViewModel.delegate = self - qChatBgView.viewmodel = serverViewModel - weak var weakSelf = self - serverViewModel.updateServerList = { - weakSelf?.tableView.reloadData() + initializeConfig() + addSubviews() + requestData(timeTag: 0) + addObserve() + } + + func initializeConfig() { + QChatSystemMessageProvider.shared.addDelegate(delegate: self) + } + + func addSubviews() { + view.addSubview(addServiceBtn) + view.addSubview(qChatBgView) + view.addSubview(tableView) + + NSLayoutConstraint.activate([ + addServiceBtn.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 12), + addServiceBtn.widthAnchor.constraint(equalToConstant: 42), + addServiceBtn.heightAnchor.constraint(equalToConstant: 42), + addServiceBtn.topAnchor.constraint(equalTo: view.topAnchor, constant: 46), + ]) + NSLayoutConstraint.activate([ + qChatBgView.leftAnchor.constraint(equalTo: addServiceBtn.rightAnchor, constant: 12), + qChatBgView.topAnchor.constraint(equalTo: addServiceBtn.topAnchor), + qChatBgView.rightAnchor.constraint(equalTo: view.rightAnchor), + qChatBgView.bottomAnchor.constraint(equalTo: view.bottomAnchor), + ]) + + NSLayoutConstraint.activate([ + tableView.topAnchor.constraint(equalTo: addServiceBtn.bottomAnchor, constant: 7), + tableView.leftAnchor.constraint(equalTo: view.leftAnchor), + tableView.rightAnchor.constraint(equalTo: qChatBgView.leftAnchor), + tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), + ]) + } + + func requestData(timeTag: TimeInterval) { + let param = GetServersByPageParam(timeTag: timeTag, limit: 20) + weak var weakSelf = self + serverViewModel.getServerList(parameter: param) { error, response in + + if error == nil { + guard let dataArray = response?.servers else { return } + if timeTag == 0 { + self.serverListArray.removeAll() + self.serverListArray = dataArray + if let first = dataArray.first { + self.qChatBgView.qchatServerModel = first + self.qChatBgView.dismissEmptyView() + } else { + // 服务器列表为空 + self.qChatBgView.showEmptyServerView() + } + } else { + self.serverListArray += dataArray } - initializeConfig() - addSubviews() - self.requestData(timeTag: 0) - addObserve() - } - func initializeConfig(){ - QChatSystemMessageProvider.shared.addDelegate(delegate: self) + + // 未读数入口 + weakSelf?.serverViewModel.getUnread(dataArray) + + self.tableView.reloadData() + } else { + print("getServerList failed,error = \(error!)") + } } - - - func addSubviews(){ - self.view.addSubview(addServiceBtn) - self.view.addSubview(qChatBgView) - self.view.addSubview(tableView) - - NSLayoutConstraint.activate([ - addServiceBtn.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 12), - addServiceBtn.widthAnchor.constraint(equalToConstant: 42), - addServiceBtn.heightAnchor.constraint(equalToConstant: 42), - addServiceBtn.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 46), - ]) - NSLayoutConstraint.activate([ - qChatBgView.leftAnchor.constraint(equalTo: addServiceBtn.rightAnchor, constant: 12), - qChatBgView.topAnchor.constraint(equalTo: addServiceBtn.topAnchor), - qChatBgView.rightAnchor.constraint(equalTo: self.view.rightAnchor), - qChatBgView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor) - ]) - - NSLayoutConstraint.activate([ - tableView.topAnchor.constraint(equalTo: addServiceBtn.bottomAnchor,constant: 7), - tableView.leftAnchor.constraint(equalTo: self.view.leftAnchor), - tableView.rightAnchor.constraint(equalTo: qChatBgView.leftAnchor), - tableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor) - ]) + } + + func addObserve() { + NotificationCenter.default.addObserver( + self, + selector: #selector(onCreateServer), + name: NotificationName.createServer, + object: nil + ) + NotificationCenter.default.addObserver( + self, + selector: #selector(onCreateChannel), + name: NotificationName.createChannel, + object: nil + ) + } + + // MARK: lazy method + + private lazy var addServiceBtn: UIButton = { + let btn = UIButton() + btn.setBackgroundImage(UIImage.ne_imageNamed(name: "addService_icon"), for: .normal) + btn.translatesAutoresizingMaskIntoConstraints = false + btn.addTarget(self, action: #selector(addServiceBtnClick), for: .touchUpInside) + return btn + }() + + private lazy var qChatBgView: NEHomeChannelView = { + let view = NEHomeChannelView() + view.translatesAutoresizingMaskIntoConstraints = false + weak var weakSelf = self + view.viewmodel = serverViewModel + view.setUpBlock = { () in + print("设置服务器") + if weakSelf?.serverListArray.count == 0 { + return + } + if let index = weakSelf?.selectIndex, + let server = weakSelf?.serverListArray[index] { + let setting = QChatServerSettingViewController() + setting.server = server + setting.hidesBottomBarWhenPushed = true + weakSelf?.navigationController?.pushViewController(setting, animated: true) + } } - - func requestData (timeTag:TimeInterval){ - let param = GetServersByPageParam(timeTag: timeTag, limit: 20) - weak var weakSelf = self - serverViewModel.getServerList(parameter: param) { error, response in - - if error == nil { - guard let dataArray = response?.servers else { return } - if timeTag == 0 { - self.serverListArray.removeAll() - self.serverListArray = dataArray - if let first = dataArray.first { - self.qChatBgView.qchatServerModel = first - self.qChatBgView.dismissEmptyView() - }else { - //服务器列表为空 - self.qChatBgView.showEmptyServerView() - } - }else { - self.serverListArray+=dataArray - } - - // 未读数入口 - weakSelf?.serverViewModel.getUnread(dataArray) - - self.tableView.reloadData() - }else { - print("getServerList failed,error = \(error!)") - } + + view.addChannelBlock = { [weak self] in + if self?.serverListArray.count ?? 0 > 0 { + let server = self?.serverListArray[self?.selectIndex ?? 0] + guard let serverId = server?.serverId, serverId > 0 else { + print("error: serverId:\(server?.serverId ?? 0)") + return } + let nav = + QChatNavigationController( + rootViewController: QChatChannelViewController(serverId: serverId) + ) + nav.modalPresentationStyle = .fullScreen + weakSelf?.present(nav, animated: true, completion: nil) + } } - - func addObserve() { - NotificationCenter.default.addObserver(self, selector: #selector(onCreateServer), name:NotificationName.createServer, object: nil) - NotificationCenter.default.addObserver(self, selector: #selector(onCreateChannel), name:NotificationName.createChannel, object: nil) + + view.selectedChannelBlock = { [weak self] channel in + self?.enterChatVC(channel: channel) } - - //MARK: lazy method - private lazy var addServiceBtn:UIButton = { - let btn = UIButton() - btn.setBackgroundImage(UIImage.ne_imageNamed(name: "addService_icon"), for: .normal) - btn.translatesAutoresizingMaskIntoConstraints = false - btn.addTarget(self, action: #selector(addServiceBtnClick), for: .touchUpInside) - return btn - }() - - private lazy var qChatBgView:NEHomeChannelView = { - let view = NEHomeChannelView() - view.translatesAutoresizingMaskIntoConstraints = false - weak var weakSelf = self - view.viewmodel = serverViewModel - view.setUpBlock = {()in - print("设置服务器") - if weakSelf?.serverListArray.count == 0 { - return - } - if let index = weakSelf?.selectIndex, - let server = weakSelf?.serverListArray[index]{ - let setting = QChatServerSettingViewController() - setting.server = server - setting.hidesBottomBarWhenPushed = true - weakSelf?.navigationController?.pushViewController(setting, animated: true) - } - } - - view.addChannelBlock = {[weak self] in - if self?.serverListArray.count ?? 0 > 0 { - let server = self?.serverListArray[self?.selectIndex ?? 0] - guard let serverId = server?.serverId, serverId > 0 else { - print("error: serverId:\(server?.serverId ?? 0)") - return - } - let nav = QChatNavigationController(rootViewController: QChatChannelViewController(serverId: serverId)) - nav.modalPresentationStyle = .fullScreen - weakSelf?.present(nav, animated: true, completion: nil) - } - } - - view.selectedChannelBlock = {[weak self] channel in - self?.enterChatVC(channel: channel) - - } - return view - }() - - private lazy var tableView:UITableView = { - let tableView = UITableView.init(frame: .zero, style: .plain) - tableView.translatesAutoresizingMaskIntoConstraints = false - tableView.separatorStyle = .none - tableView.showsVerticalScrollIndicator = false - tableView.delegate = self - tableView.dataSource = self - tableView.register(NEHomeServerCell.self, forCellReuseIdentifier: "\(NSStringFromClass(NEHomeServerCell.self))") - tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.1)) - tableView.backgroundColor = HexRGB(0xe9eff5) - let mjfooter = MJRefreshBackNormalFooter(refreshingTarget: self, refreshingAction: #selector(loadMoreData)) - mjfooter.stateLabel?.isHidden = true - tableView.mj_footer = mjfooter - return tableView - }() - - private lazy var brokenNetworkView:NEBrokenNetworkView = { - let view = NEBrokenNetworkView.init(frame: CGRect.init(x: 0, y: 38, width: qChatBgView.width, height: 33)) - return view - }() -} + return view + }() + private lazy var tableView: UITableView = { + let tableView = UITableView(frame: .zero, style: .plain) + tableView.translatesAutoresizingMaskIntoConstraints = false + tableView.separatorStyle = .none + tableView.showsVerticalScrollIndicator = false + tableView.delegate = self + tableView.dataSource = self + tableView.register( + NEHomeServerCell.self, + forCellReuseIdentifier: "\(NSStringFromClass(NEHomeServerCell.self))" + ) + tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.1)) + tableView.backgroundColor = HexRGB(0xE9EFF5) + let mjfooter = MJRefreshBackNormalFooter( + refreshingTarget: self, + refreshingAction: #selector(loadMoreData) + ) + mjfooter.stateLabel?.isHidden = true + tableView.mj_footer = mjfooter + return tableView + }() + + private lazy var brokenNetworkView: NEBrokenNetworkView = { + let view = + NEBrokenNetworkView(frame: CGRect(x: 0, y: 38, width: qChatBgView.width, height: 33)) + return view + }() +} extension QChatHomeViewController { - - @objc func addServiceBtnClick(sender:UIButton) { - let nav = UINavigationController(rootViewController: CreateServerViewController()) - nav.modalPresentationStyle = .fullScreen - self.present(nav, animated: true, completion: nil) - } + @objc func addServiceBtnClick(sender: UIButton) { + let nav = UINavigationController(rootViewController: CreateServerViewController()) + nav.modalPresentationStyle = .fullScreen + present(nav, animated: true, completion: nil) + } - @objc func loadMoreData(){ - if let time = self.serverListArray.last?.createTime { - self.requestData(timeTag: time) - } - self.tableView.mj_footer?.endRefreshing() + @objc func loadMoreData() { + if let time = serverListArray.last?.createTime { + requestData(timeTag: time) } - + tableView.mj_footer?.endRefreshing() + } } // MARK: tableviewDelegate dataSource -extension QChatHomeViewController:UITableViewDelegate,UITableViewDataSource { - - - public func dataDidChange() { - qChatBgView.tableView.reloadData() - } - - public func dataDidError(_ error: Error) { - - } - - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return self.serverListArray.count - } - - public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(withIdentifier: "\(NSStringFromClass(NEHomeServerCell.self))", for: indexPath) as! NEHomeServerCell - cell.showSelectState(isShow: indexPath.row == selectIndex ? true :false) - cell.serverModel = serverListArray[indexPath.row] - return cell - } - - public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - - let serverModel = self.serverListArray[indexPath.row] - self.qChatBgView.qchatServerModel = serverModel - serverViewModel.currentServerId = serverModel.serverId - selectIndex = indexPath.row - tableView.reloadData() - } - - public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - return 50 - } - + +extension QChatHomeViewController: UITableViewDelegate, UITableViewDataSource { + public func dataDidChange() { + qChatBgView.tableView.reloadData() + } + + public func dataDidError(_ error: Error) {} + + public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + serverListArray.count + } + + public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(NSStringFromClass(NEHomeServerCell.self))", + for: indexPath + ) as! NEHomeServerCell + cell.showSelectState(isShow: indexPath.row == selectIndex ? true : false) + cell.serverModel = serverListArray[indexPath.row] + return cell + } + + public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + let serverModel = serverListArray[indexPath.row] + qChatBgView.qchatServerModel = serverModel + serverViewModel.currentServerId = serverModel.serverId + selectIndex = indexPath.row + tableView.reloadData() + } + + public func tableView(_ tableView: UITableView, + heightForRowAt indexPath: IndexPath) -> CGFloat { + 50 + } + // MARK: action - @objc func onCreateServer(noti: Notification) { - print("noti create server id:\(String(describing: noti.object))") - guard let serverId: UInt64 = noti.object as? UInt64 else { - return - } - - weak var weakSelf = self - let viewModel = QChatChannelViewModel(serverId: serverId) - viewModel.name = localizable("second_channel") - let className = className() - viewModel.createChannel { error, channel in - if error == nil { - NELog.infoLog(className, desc: "✅second_channel create success") - viewModel.name = localizable("first_channel") - - viewModel.createChannel { error, channel in - if let err = error { - NELog.errorLog(className, desc: "❌createChannel first_channel failed,error = \(err)") - }else { - NELog.infoLog(className, desc: "✅enter first channel success") - weakSelf?.enterChatVC(channel: channel) - } - } - } - } + + @objc func onCreateServer(noti: Notification) { + print("noti create server id:\(String(describing: noti.object))") + guard let serverId: UInt64 = noti.object as? UInt64 else { + return } - - @objc func onCreateChannel(noti: Notification) { - // enter ChatVC - guard let channel = noti.object as? ChatChannel else { - return + + weak var weakSelf = self + let viewModel = QChatChannelViewModel(serverId: serverId) + viewModel.name = localizable("second_channel") + let className = className() + viewModel.createChannel { error, channel in + if error == nil { + NELog.infoLog(className, desc: "✅second_channel create success") + viewModel.name = localizable("first_channel") + + viewModel.createChannel { error, channel in + if let err = error { + NELog.errorLog( + className, + desc: "❌createChannel first_channel failed,error = \(err)" + ) + } else { + NELog.infoLog(className, desc: "✅enter first channel success") + weakSelf?.enterChatVC(channel: channel) + } } - enterChatVC(channel:channel) + } } - - private func enterChatVC(channel:ChatChannel?) { - let chatVC = QChatViewController(channel: channel) - self.navigationController?.pushViewController(chatVC, animated: true) + } + + @objc func onCreateChannel(noti: Notification) { + // enter ChatVC + guard let channel = noti.object as? ChatChannel else { + return } + enterChatVC(channel: channel) + } + + private func enterChatVC(channel: ChatChannel?) { + let chatVC = QChatViewController(channel: channel) + navigationController?.pushViewController(chatVC, animated: true) + } } -extension QChatHomeViewController:NIMQChatMessageManagerDelegate { - - public func onRecvSystemNotification(_ result: NIMQChatReceiveSystemNotificationResult) { - result.systemNotifications?.forEach({ systemNotification in - - switch systemNotification.type { - - case .channelCreate,.channelRemove,.updateChannelCategoryBlackWhiteRole,.channelUpdate: - self.channelChange(notificationInfo: systemNotification) - break - case .serverMemberKick,.serverMemberInviteDone: - - if systemNotification.fromAccount != IMKitLoginManager.instance.imAccid,((systemNotification.toAccids?.contains(IMKitLoginManager.instance.imAccid)) != nil){ - self.requestData(timeTag: 0) - } - break - case .serverMemberApplyDone,.serverCreate,.serverRemove,.serverMemberLeave: - - if systemNotification.type == .serverRemove { - selectIndex = 0 - self.requestData(timeTag: 0) - }else { - if systemNotification.fromAccount == IMKitLoginManager.instance.imAccid { - selectIndex = 0 - self.requestData(timeTag: 0) - } - } - - break - - case .serverUpdate: - //刷新发生更新的cell - self.reloadUpdateCell(targetServerId: systemNotification.serverId) - break - default: - print("") - } - - }) - } - - - private func reloadUpdateCell(targetServerId:UInt64){ - var targetIndex = 0 - for (index, serverModel) in serverListArray.enumerated() { - if targetServerId == serverModel.serverId{ - targetIndex = index - break - } +extension QChatHomeViewController: NIMQChatMessageManagerDelegate { + public func onRecvSystemNotification(_ result: NIMQChatReceiveSystemNotificationResult) { + result.systemNotifications?.forEach { systemNotification in + + switch systemNotification.type { + case .channelCreate, .channelRemove, .updateChannelCategoryBlackWhiteRole, + .channelUpdate: + self.channelChange(notificationInfo: systemNotification) + case .serverMemberKick, .serverMemberInviteDone: + + if systemNotification.fromAccount != IMKitLoginManager.instance.imAccid, + (systemNotification.toAccids?.contains(IMKitLoginManager.instance.imAccid)) != + nil { + self.requestData(timeTag: 0) } + case .serverMemberApplyDone, .serverCreate, .serverRemove, .serverMemberLeave: - let indexPath = IndexPath(row: targetIndex, section: 0) - let param = QChatGetServersParam(serverIds: [NSNumber.init(value: targetServerId)]) - weak var weakSelf = self - serverViewModel.getServers(parameter: param) { erorr, result in - if let serverArray = result?.servers,!serverArray.isEmpty { - weakSelf?.serverListArray[targetIndex] = serverArray.first! - weakSelf?.tableView.reloadRows(at: [indexPath], with: .none) - - if targetIndex == weakSelf?.selectIndex { - weakSelf?.qChatBgView.qchatServerModel = serverArray.first! - } - } + if systemNotification.type == .serverRemove { + selectIndex = 0 + self.requestData(timeTag: 0) + } else { + if systemNotification.fromAccount == IMKitLoginManager.instance.imAccid { + selectIndex = 0 + self.requestData(timeTag: 0) + } } + + case .serverUpdate: + // 刷新发生更新的cell + self.reloadUpdateCell(targetServerId: systemNotification.serverId) + default: + print("") + } } - - private func channelChange(notificationInfo:NIMQChatSystemNotification){ - self.qChatBgView.channelChange(noticeInfo: notificationInfo) + } + + private func reloadUpdateCell(targetServerId: UInt64) { + var targetIndex = 0 + for (index, serverModel) in serverListArray.enumerated() { + if targetServerId == serverModel.serverId { + targetIndex = index + break + } } - + + let indexPath = IndexPath(row: targetIndex, section: 0) + let param = QChatGetServersParam(serverIds: [NSNumber(value: targetServerId)]) + weak var weakSelf = self + serverViewModel.getServers(parameter: param) { erorr, result in + if let serverArray = result?.servers,!serverArray.isEmpty { + weakSelf?.serverListArray[targetIndex] = serverArray.first! + weakSelf?.tableView.reloadRows(at: [indexPath], with: .none) + + if targetIndex == weakSelf?.selectIndex { + weakSelf?.qChatBgView.qchatServerModel = serverArray.first! + } + } + } + } + + private func channelChange(notificationInfo: NIMQChatSystemNotification) { + qChatBgView.channelChange(noticeInfo: notificationInfo) + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/Model/AllChannelData.swift b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/Model/AllChannelData.swift index 53c8f176..5f53aac0 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/Model/AllChannelData.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/Model/AllChannelData.swift @@ -1,57 +1,55 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NEKitQChat import NEKitCoreIM protocol AllChannelDataDelegate: AnyObject { - func dataGetSuccess(_ serverId: UInt64, _ channels: [ChatChannel]) - func dataGetError(_ serverId: UInt64, _ error: Error) + func dataGetSuccess(_ serverId: UInt64, _ channels: [ChatChannel]) + func dataGetError(_ serverId: UInt64, _ error: Error) } public class AllChannelData { - - var repo = QChatRepo() - let limit = 200 - weak var delegate: AllChannelDataDelegate? - var serverId: UInt64 - var channelInfos = [ChatChannel]() - public var nextTimetag: TimeInterval = 0 + var repo = QChatRepo() + let limit = 200 + weak var delegate: AllChannelDataDelegate? + var serverId: UInt64 + var channelInfos = [ChatChannel]() + public var nextTimetag: TimeInterval = 0 - init(sid: UInt64){ - serverId = sid - getChannelData() - } - - func getChannelData(){ - var param = QChatGetChannelsByPageParam(timeTag: nextTimetag, serverId: serverId) - param.limit = 200 - weak var weakSelf = self - repo.getChannelsByPage(param: param) { error, result in - if let err = error { - if let sid = weakSelf?.serverId { - weakSelf?.delegate?.dataGetError(sid, err) - } - }else { - if let datas = result?.channels { - weakSelf?.channelInfos.append(contentsOf: datas) - } - if let nextTimeTag = result?.nextTimetag { - weakSelf?.nextTimetag = nextTimeTag - } - if let hasMore = result?.hasMore, hasMore == true { - weakSelf?.getChannelData() - }else { - print("getChannelData finish : ", weakSelf?.serverId as Any) - if let sid = weakSelf?.serverId, let channels = weakSelf?.channelInfos { - weakSelf?.delegate?.dataGetSuccess(sid, channels) - } - } - } + init(sid: UInt64) { + serverId = sid + getChannelData() + } + + func getChannelData() { + var param = QChatGetChannelsByPageParam(timeTag: nextTimetag, serverId: serverId) + param.limit = 200 + weak var weakSelf = self + repo.getChannelsByPage(param: param) { error, result in + if let err = error { + if let sid = weakSelf?.serverId { + weakSelf?.delegate?.dataGetError(sid, err) + } + } else { + if let datas = result?.channels { + weakSelf?.channelInfos.append(contentsOf: datas) + } + if let nextTimeTag = result?.nextTimetag { + weakSelf?.nextTimetag = nextTimeTag + } + if let hasMore = result?.hasMore, hasMore == true { + weakSelf?.getChannelData() + } else { + print("getChannelData finish : ", weakSelf?.serverId as Any) + if let sid = weakSelf?.serverId, let channels = weakSelf?.channelInfos { + weakSelf?.delegate?.dataGetSuccess(sid, channels) + } } + } } - - + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/Model/ServerMemberModel.swift b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/Model/ServerMemberModel.swift index a80f30d1..ab6b34b7 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/Model/ServerMemberModel.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/Model/ServerMemberModel.swift @@ -1,15 +1,14 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NEKitCoreIM -//服务器下成员列表数据模型 +// 服务器下成员列表数据模型 public struct ServerMemberModel { - public var serverMemberModel:ServerMemeber? - public var imName:String? - public var idGroupData:[String]? - - + public var serverMemberModel: ServerMemeber? + public var imName: String? + public var idGroupData: [String]? } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/EmptyDataView.swift b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/EmptyDataView.swift index af19780e..a8479b8c 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/EmptyDataView.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/EmptyDataView.swift @@ -1,71 +1,69 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class EmptyDataView: UIView { - - private var imageName:String? - private var content:String? + private var imageName: String? + private var content: String? - public init(imageName:String,content:String,frame:CGRect){ - self.imageName = imageName - self.content = content - super.init(frame: frame) - setupSubviews() - setupSubviewStyle() - } + public init(imageName: String, content: String, frame: CGRect) { + self.imageName = imageName + self.content = content + super.init(frame: frame) + setupSubviews() + setupSubviewStyle() + } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func setupSubviews(){ - self.backgroundColor = .white - self.addSubview(emptyImageView) - self.addSubview(contentLabel) - - NSLayoutConstraint.activate([ - emptyImageView.topAnchor.constraint(equalTo: self.topAnchor, constant: 60), - emptyImageView.centerXAnchor.constraint(equalTo: self.centerXAnchor), - emptyImageView.widthAnchor.constraint(equalToConstant: 122), - emptyImageView.heightAnchor.constraint(equalToConstant: 91), - ]) - - NSLayoutConstraint.activate([ - contentLabel.topAnchor.constraint(equalTo: emptyImageView.bottomAnchor, constant: 8), - contentLabel.centerXAnchor.constraint(equalTo: self.centerXAnchor), - ]) - } + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } - func setupSubviewStyle(){ - emptyImageView.image = UIImage.ne_imageNamed(name: imageName) - contentLabel.text = content - } - - private lazy var emptyImageView: UIImageView = { - let avatar = UIImageView() - avatar.translatesAutoresizingMaskIntoConstraints = false - return avatar - }() - - private lazy var contentLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.textColor = UIColor.ne_emptyTitleColor - label.font = DefaultTextFont(14) - label.numberOfLines = 0 - label.textAlignment = .center - return label - }() - - public func setttingContent(content:String) { - self.contentLabel.text = content - } - - public func setEmptyImage(name:String) { - emptyImageView.image = UIImage.ne_imageNamed(name: name) - } - + func setupSubviews() { + backgroundColor = .white + addSubview(emptyImageView) + addSubview(contentLabel) + + NSLayoutConstraint.activate([ + emptyImageView.topAnchor.constraint(equalTo: topAnchor, constant: 60), + emptyImageView.centerXAnchor.constraint(equalTo: centerXAnchor), + emptyImageView.widthAnchor.constraint(equalToConstant: 122), + emptyImageView.heightAnchor.constraint(equalToConstant: 91), + ]) + + NSLayoutConstraint.activate([ + contentLabel.topAnchor.constraint(equalTo: emptyImageView.bottomAnchor, constant: 8), + contentLabel.centerXAnchor.constraint(equalTo: centerXAnchor), + ]) + } + + func setupSubviewStyle() { + emptyImageView.image = UIImage.ne_imageNamed(name: imageName) + contentLabel.text = content + } + + private lazy var emptyImageView: UIImageView = { + let avatar = UIImageView() + avatar.translatesAutoresizingMaskIntoConstraints = false + return avatar + }() + + private lazy var contentLabel: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.textColor = UIColor.ne_emptyTitleColor + label.font = DefaultTextFont(14) + label.numberOfLines = 0 + label.textAlignment = .center + return label + }() + + public func setttingContent(content: String) { + contentLabel.text = content + } + + public func setEmptyImage(name: String) { + emptyImageView.image = UIImage.ne_imageNamed(name: name) + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/InviteMemberView.swift b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/InviteMemberView.swift index bcb42887..17def387 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/InviteMemberView.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/InviteMemberView.swift @@ -1,61 +1,60 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class InviteMemberView: UIView { - - override init(frame: CGRect) { - super.init(frame: frame) - self.addSubview(content) - self.addSubview(successImageView) - self.layer.cornerRadius = 26 - self.layer.borderWidth = 1 - self.layer.borderColor = HexRGB(0xE3E3E3).cgColor - self.layer.masksToBounds = true - self.backgroundColor = .white - - NSLayoutConstraint.activate([ - successImageView.leftAnchor.constraint(equalTo: self.leftAnchor, constant: kScreenInterval), - successImageView.centerYAnchor.constraint(equalTo: self.centerYAnchor), - successImageView.widthAnchor.constraint(equalToConstant: kScreenInterval), - successImageView.heightAnchor.constraint(equalToConstant: kScreenInterval), - ]) - - NSLayoutConstraint.activate([ - content.leftAnchor.constraint(equalTo: successImageView.rightAnchor, constant: 6), - content.centerYAnchor.constraint(equalTo: successImageView.centerYAnchor), - ]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - - public func showSuccessView(){ - let window = UIApplication.shared.keyWindow - window?.addSubview(self) - DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { - self.removeFromSuperview() - } + override init(frame: CGRect) { + super.init(frame: frame) + addSubview(content) + addSubview(successImageView) + layer.cornerRadius = 26 + layer.borderWidth = 1 + layer.borderColor = HexRGB(0xE3E3E3).cgColor + layer.masksToBounds = true + backgroundColor = .white + + NSLayoutConstraint.activate([ + successImageView.leftAnchor.constraint(equalTo: leftAnchor, constant: kScreenInterval), + successImageView.centerYAnchor.constraint(equalTo: centerYAnchor), + successImageView.widthAnchor.constraint(equalToConstant: kScreenInterval), + successImageView.heightAnchor.constraint(equalToConstant: kScreenInterval), + ]) + + NSLayoutConstraint.activate([ + content.leftAnchor.constraint(equalTo: successImageView.rightAnchor, constant: 6), + content.centerYAnchor.constraint(equalTo: successImageView.centerYAnchor), + ]) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + public func showSuccessView() { + let window = UIApplication.shared.keyWindow + window?.addSubview(self) + DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { + self.removeFromSuperview() } - - //MARK: lazyMethod - private lazy var content:UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.text = localizable("请求已发送") - label.font = DefaultTextFont(16) - label.textColor = UIColor.ne_darkText - return label - }() - - private lazy var successImageView:UIImageView = { - let imageView = UIImageView.init(image: UIImage.ne_imageNamed(name: "invitemember_success")) - imageView.translatesAutoresizingMaskIntoConstraints = false - return imageView - }() - + } + + // MARK: lazyMethod + + private lazy var content: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.text = localizable("请求已发送") + label.font = DefaultTextFont(16) + label.textColor = UIColor.ne_darkText + return label + }() + + private lazy var successImageView: UIImageView = { + let imageView = UIImageView(image: UIImage.ne_imageNamed(name: "invitemember_success")) + imageView.translatesAutoresizingMaskIntoConstraints = false + return imageView + }() } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/NECreateServerCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/NECreateServerCell.swift index 0b40b8e8..bd667bd6 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/NECreateServerCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/NECreateServerCell.swift @@ -1,103 +1,108 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class NECreateServerCell: UITableViewCell { + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - self.selectionStyle = .none - self.setupSubviews() + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + selectionStyle = .none + setupSubviews() + } + + var model: (image: String, title: String)? { + didSet { + headImageView.image = UIImage.ne_imageNamed(name: model?.image) + content.text = model?.title } + } + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } - var model:(image:String,title:String)? { - didSet { - self.headImageView.image = UIImage.ne_imageNamed(name: model?.image) - self.content.text = model?.title - } - - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func setupSubviews() { - self.contentView.addSubview(serviceBgView) - serviceBgView.addSubview(headImageView) - serviceBgView.addSubview(content) - serviceBgView.addSubview(arrowImageView) - - NSLayoutConstraint.activate([ - serviceBgView.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: kScreenInterval), - serviceBgView.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -kScreenInterval), - serviceBgView.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 8), - serviceBgView.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: -8), - ]) - - NSLayoutConstraint.activate([ - headImageView.leftAnchor.constraint(equalTo: serviceBgView.leftAnchor, constant: 16), - headImageView.centerYAnchor.constraint(equalTo: serviceBgView.centerYAnchor), - headImageView.widthAnchor.constraint(equalToConstant: 36), - headImageView.heightAnchor.constraint(equalToConstant: 36) - ]) - - - NSLayoutConstraint.activate([ - arrowImageView.centerYAnchor.constraint(equalTo: serviceBgView.centerYAnchor), - arrowImageView.rightAnchor.constraint(equalTo: serviceBgView.rightAnchor, constant: -kScreenInterval), - arrowImageView.widthAnchor.constraint(equalToConstant: 5) - ]) - - NSLayoutConstraint.activate([ - content.leftAnchor.constraint(equalTo: headImageView.rightAnchor, constant: 16), - content.centerYAnchor.constraint(equalTo: headImageView.centerYAnchor), - content.rightAnchor.constraint(equalTo: arrowImageView.leftAnchor, constant: -16), - ]) - - } - - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) + func setupSubviews() { + contentView.addSubview(serviceBgView) + serviceBgView.addSubview(headImageView) + serviceBgView.addSubview(content) + serviceBgView.addSubview(arrowImageView) - // Configure the view for the selected state - } + NSLayoutConstraint.activate([ + serviceBgView.leftAnchor.constraint( + equalTo: contentView.leftAnchor, + constant: kScreenInterval + ), + serviceBgView.rightAnchor.constraint( + equalTo: contentView.rightAnchor, + constant: -kScreenInterval + ), + serviceBgView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 8), + serviceBgView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -8), + ]) + + NSLayoutConstraint.activate([ + headImageView.leftAnchor.constraint(equalTo: serviceBgView.leftAnchor, constant: 16), + headImageView.centerYAnchor.constraint(equalTo: serviceBgView.centerYAnchor), + headImageView.widthAnchor.constraint(equalToConstant: 36), + headImageView.heightAnchor.constraint(equalToConstant: 36), + ]) + + NSLayoutConstraint.activate([ + arrowImageView.centerYAnchor.constraint(equalTo: serviceBgView.centerYAnchor), + arrowImageView.rightAnchor.constraint( + equalTo: serviceBgView.rightAnchor, + constant: -kScreenInterval + ), + arrowImageView.widthAnchor.constraint(equalToConstant: 5), + ]) + + NSLayoutConstraint.activate([ + content.leftAnchor.constraint(equalTo: headImageView.rightAnchor, constant: 16), + content.centerYAnchor.constraint(equalTo: headImageView.centerYAnchor), + content.rightAnchor.constraint(equalTo: arrowImageView.leftAnchor, constant: -16), + ]) + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + } + + // MARK: lazyMethod + + private lazy var serviceBgView: UIView = { + let view = UIView() + view.translatesAutoresizingMaskIntoConstraints = false + view.backgroundColor = HexRGB(0xEFF1F4) + view.layer.cornerRadius = 8 + return view + }() + + private lazy var headImageView: UIImageView = { + let imageView = UIImageView() + imageView.translatesAutoresizingMaskIntoConstraints = false + return imageView + }() + + private lazy var content: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.font = DefaultTextFont(16) + label.textColor = TextNormalColor + return label + }() - // MARK: lazyMethod - - private lazy var serviceBgView:UIView = { - let view = UIView() - view.translatesAutoresizingMaskIntoConstraints = false - view.backgroundColor = HexRGB(0xEFF1F4) - view.layer.cornerRadius = 8 - return view - }() - - private lazy var headImageView:UIImageView = { - let imageView = UIImageView.init() - imageView.translatesAutoresizingMaskIntoConstraints = false - return imageView - }() - - private lazy var content:UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.font = DefaultTextFont(16) - label.textColor = TextNormalColor - return label - }() - - private lazy var arrowImageView:UIImageView = { - let imageView = UIImageView.init(image: UIImage.ne_imageNamed(name: "arrowRight")) - imageView.translatesAutoresizingMaskIntoConstraints = false - return imageView - }() - + private lazy var arrowImageView: UIImageView = { + let imageView = UIImageView(image: UIImage.ne_imageNamed(name: "arrowRight")) + imageView.translatesAutoresizingMaskIntoConstraints = false + return imageView + }() } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/NEGroupIdentityMemberCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/NEGroupIdentityMemberCell.swift index de1a6ee7..2958c6c6 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/NEGroupIdentityMemberCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/NEGroupIdentityMemberCell.swift @@ -1,263 +1,282 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import MapKit import NEKitCoreIM class NEGroupIdentityMemberCell: UITableViewCell { + var dataArray = [String]() - var dataArray = [String]() - - - var maxWidth:CGFloat = kScreenWidth-2*kScreenInterval - var labelMargin:CGFloat = 6 - var labelHeight:CGFloat = 25 - var isFirstRow = true - var titleTopConstraint: NSLayoutConstraint? - - - public var memberModel:ServerMemeber?{ - didSet { - guard let model = memberModel else { return } - - if let imageName = model.avatar,!imageName.isEmpty { - avatarImage.sd_setImage(with: URL.init(string: imageName), completed: nil) - avatarImage.setTitle("") - }else { - if let name = model.nick,!name.isEmpty { - avatarImage.setTitle(name) - }else { - avatarImage.setTitle(model.accid ?? "") - } - avatarImage.backgroundColor = .colorWithString(string: memberModel?.accid) - } - var labelContentArray = [String]() - memberModel?.roles?.forEach({ roleModel in - labelContentArray.append(roleModel.name ?? "") - }) - self.dataArray = labelContentArray - setupSubviews() - - if let nick = model.nick,!nick.isEmpty { - titleLable.text = nick - subTitleLable.text = model.accid - titleTopConstraint?.constant = 14 - }else { - titleLable.text = model.accid - subTitleLable.text = "" - titleTopConstraint?.constant = 22 - } + var maxWidth: CGFloat = kScreenWidth - 2 * kScreenInterval + var labelMargin: CGFloat = 6 + var labelHeight: CGFloat = 25 + var isFirstRow = true + var titleTopConstraint: NSLayoutConstraint? + + public var memberModel: ServerMemeber? { + didSet { + guard let model = memberModel else { return } + + if let imageName = model.avatar,!imageName.isEmpty { + avatarImage.sd_setImage(with: URL(string: imageName), completed: nil) + avatarImage.setTitle("") + } else { + if let name = model.nick,!name.isEmpty { + avatarImage.setTitle(name) + } else { + avatarImage.setTitle(model.accid ?? "") } - } - - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } + avatarImage.backgroundColor = .colorWithString(string: memberModel?.accid) + } + var labelContentArray = [String]() + memberModel?.roles?.forEach { roleModel in + labelContentArray.append(roleModel.name ?? "") + } + self.dataArray = labelContentArray + setupSubviews() - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) + if let nick = model.nick,!nick.isEmpty { + titleLable.text = nick + subTitleLable.text = model.accid + titleTopConstraint?.constant = 14 + } else { + titleLable.text = model.accid + subTitleLable.text = "" + titleTopConstraint?.constant = 22 + } } + } - public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - self.selectionStyle = .none - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - override func draw(_ rect: CGRect) { - avatarImage.addCorner(conrners: .allCorners, radius: 18) - } - - func setupSubviews(){ - - self.contentView.addSubview(avatarImage) - self.contentView.addSubview(titleLable) - self.contentView.addSubview(subTitleLable) - self.contentView.addSubview(arrowImageView) - self.contentView.addSubview(labelContainerView) - self.contentView.addSubview(lineView) + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } - NSLayoutConstraint.activate([ - avatarImage.topAnchor.constraint(equalTo: self.contentView.topAnchor,constant: 12), - avatarImage.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: kScreenInterval), - avatarImage.widthAnchor.constraint(equalToConstant: 36), - avatarImage.heightAnchor.constraint(equalToConstant: 36), - ]) + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + } - titleTopConstraint = titleLable.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 14) - titleTopConstraint?.isActive = true - NSLayoutConstraint.activate([ - titleLable.leftAnchor.constraint(equalTo:avatarImage.rightAnchor, constant: 12), - ]) - + override public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + selectionStyle = .none + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func draw(_ rect: CGRect) { + avatarImage.addCorner(conrners: .allCorners, radius: 18) + } + + func setupSubviews() { + contentView.addSubview(avatarImage) + contentView.addSubview(titleLable) + contentView.addSubview(subTitleLable) + contentView.addSubview(arrowImageView) + contentView.addSubview(labelContainerView) + contentView.addSubview(lineView) + + NSLayoutConstraint.activate([ + avatarImage.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 12), + avatarImage.leftAnchor.constraint( + equalTo: contentView.leftAnchor, + constant: kScreenInterval + ), + avatarImage.widthAnchor.constraint(equalToConstant: 36), + avatarImage.heightAnchor.constraint(equalToConstant: 36), + ]) + + titleTopConstraint = titleLable.topAnchor.constraint( + equalTo: contentView.topAnchor, + constant: 14 + ) + titleTopConstraint?.isActive = true + NSLayoutConstraint.activate([ + titleLable.leftAnchor.constraint(equalTo: avatarImage.rightAnchor, constant: 12), + ]) + + NSLayoutConstraint.activate([ + subTitleLable.topAnchor.constraint(equalTo: titleLable.bottomAnchor), + subTitleLable.leftAnchor.constraint(equalTo: titleLable.leftAnchor), + ]) + + NSLayoutConstraint.activate([ + arrowImageView.centerYAnchor.constraint(equalTo: avatarImage.centerYAnchor), + arrowImageView.rightAnchor.constraint( + equalTo: contentView.rightAnchor, + constant: -labelHeight + ), + ]) + + NSLayoutConstraint.activate([ + labelContainerView.topAnchor.constraint(equalTo: avatarImage.bottomAnchor, constant: 8), + labelContainerView.leftAnchor.constraint(equalTo: contentView.leftAnchor), + labelContainerView.rightAnchor.constraint(equalTo: contentView.rightAnchor), + labelContainerView.bottomAnchor.constraint( + equalTo: contentView.bottomAnchor, + constant: -10 + ), + ]) + + // 移除contentview上复用的lable + labelContainerView.subviews.forEach { label in + label.removeFromSuperview() + } + var labelsWidth: CGFloat = 0 + for i in 0 ..< dataArray.count { + let label = IDGroupLable(content: dataArray[i]) + label.textInsets = UIEdgeInsets(top: 4, left: 8, bottom: 4, right: 8) + label.translatesAutoresizingMaskIntoConstraints = false + labelContainerView.addSubview(label) + let labelSize = label.sizeThatFits(CGSize(width: maxWidth, height: labelHeight)) + + // 剩余宽度是否满足,下一个lable的宽度,如不满足则换行 + if (maxWidth - labelsWidth) >= labelSize.width, isFirstRow { NSLayoutConstraint.activate([ - subTitleLable.topAnchor.constraint(equalTo: titleLable.bottomAnchor), - subTitleLable.leftAnchor.constraint(equalTo:titleLable.leftAnchor) + i == 0 ? label.leftAnchor.constraint( + equalTo: labelContainerView.leftAnchor, + constant: kScreenInterval + ) : label.leftAnchor.constraint( + equalTo: labelContainerView.leftAnchor, + constant: kScreenInterval + labelsWidth + ), + label.topAnchor.constraint(equalTo: labelContainerView.topAnchor, constant: 8), + label.widthAnchor.constraint(equalToConstant: labelSize.width), + label.heightAnchor.constraint(equalToConstant: labelSize.height), ]) - + } else { + // 换行重置,labels总宽度 + if isFirstRow { + labelsWidth = kScreenInterval + } + isFirstRow = false NSLayoutConstraint.activate([ - arrowImageView.centerYAnchor.constraint(equalTo: avatarImage.centerYAnchor), - arrowImageView.rightAnchor.constraint(equalTo:self.contentView.rightAnchor,constant: -labelHeight) + label.leftAnchor.constraint( + equalTo: labelContainerView.leftAnchor, + constant: labelsWidth + ), + label.topAnchor.constraint( + equalTo: labelContainerView.topAnchor, + constant: 8 + labelHeight + labelMargin + ), + label.widthAnchor.constraint(equalToConstant: labelSize.width), + label.heightAnchor.constraint(equalToConstant: labelSize.height), ]) + } - + if i == dataArray.count - 1 { NSLayoutConstraint.activate([ - labelContainerView.topAnchor.constraint(equalTo: avatarImage.bottomAnchor, constant: 8), - labelContainerView.leftAnchor.constraint(equalTo: self.contentView.leftAnchor), - labelContainerView.rightAnchor.constraint(equalTo: self.contentView.rightAnchor), - labelContainerView.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: -10) - ]) - - //移除contentview上复用的lable - self.labelContainerView.subviews.forEach { label in - label.removeFromSuperview() - } - var labelsWidth:CGFloat = 0 - for i in (0..= labelSize.width && isFirstRow{ - NSLayoutConstraint.activate([ - i == 0 ? label.leftAnchor.constraint(equalTo: labelContainerView.leftAnchor,constant: kScreenInterval) : label.leftAnchor.constraint(equalTo: labelContainerView.leftAnchor,constant: kScreenInterval+labelsWidth), - label.topAnchor.constraint(equalTo: labelContainerView.topAnchor,constant: 8), - label.widthAnchor.constraint(equalToConstant: labelSize.width), - label.heightAnchor.constraint(equalToConstant:labelSize.height), - ]) - }else { - - //换行重置,labels总宽度 - if isFirstRow { - labelsWidth = kScreenInterval - } - isFirstRow = false - NSLayoutConstraint.activate([ - label.leftAnchor.constraint(equalTo: labelContainerView.leftAnchor,constant: labelsWidth), - label.topAnchor.constraint(equalTo: labelContainerView.topAnchor,constant: 8+labelHeight+labelMargin), - label.widthAnchor.constraint(equalToConstant: labelSize.width), - label.heightAnchor.constraint(equalToConstant:labelSize.height) - ]) - } - - if i == dataArray.count - 1 { - NSLayoutConstraint.activate([ - label.bottomAnchor.constraint(equalTo: labelContainerView.bottomAnchor) - ]) - } - labelsWidth+=(labelSize.width + labelMargin) - } - - NSLayoutConstraint.activate([ - lineView.topAnchor.constraint(equalTo: labelContainerView.bottomAnchor, constant: 12), - lineView.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor), - lineView.rightAnchor.constraint(equalTo: self.contentView.rightAnchor), - lineView.heightAnchor.constraint(equalToConstant: 1), - lineView.leftAnchor.constraint(equalTo:self.contentView.leftAnchor,constant:kScreenInterval) + label.bottomAnchor.constraint(equalTo: labelContainerView.bottomAnchor), ]) + } + labelsWidth += (labelSize.width + labelMargin) } - - lazy var avatarImage: NEUserHeaderView = { - let view = NEUserHeaderView(frame: .zero) - view.titleLabel.textColor = .white - view.titleLabel.font = DefaultTextFont(14) - view.translatesAutoresizingMaskIntoConstraints = false - return view - }() - - private lazy var titleLable: UILabel = { - let name = UILabel() - name.translatesAutoresizingMaskIntoConstraints = false - name.textColor = .ne_darkText - name.font = DefaultTextFont(14) - return name - }() - - private lazy var subTitleLable: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.font = DefaultTextFont(12) - label.textColor = UIColor.ne_emptyTitleColor - return label - }() - - private lazy var labelContainerView:UIView = { - let view = UIView() - view.translatesAutoresizingMaskIntoConstraints = false - return view - }() - - private lazy var lineView:UIView = { - let view = UIView() - view.backgroundColor = .ne_greyLine - view.translatesAutoresizingMaskIntoConstraints = false - return view - }() - - private lazy var arrowImageView:UIImageView = { - let arrow = UIImageView.init(image: UIImage.ne_imageNamed(name: "arrowRight")) - arrow.translatesAutoresizingMaskIntoConstraints = false - return arrow - }() + NSLayoutConstraint.activate([ + lineView.topAnchor.constraint(equalTo: labelContainerView.bottomAnchor, constant: 12), + lineView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + lineView.rightAnchor.constraint(equalTo: contentView.rightAnchor), + lineView.heightAnchor.constraint(equalToConstant: 1), + lineView.leftAnchor.constraint( + equalTo: contentView.leftAnchor, + constant: kScreenInterval + ), + ]) + } + + lazy var avatarImage: NEUserHeaderView = { + let view = NEUserHeaderView(frame: .zero) + view.titleLabel.textColor = .white + view.titleLabel.font = DefaultTextFont(14) + view.translatesAutoresizingMaskIntoConstraints = false + return view + }() + + private lazy var titleLable: UILabel = { + let name = UILabel() + name.translatesAutoresizingMaskIntoConstraints = false + name.textColor = .ne_darkText + name.font = DefaultTextFont(14) + return name + }() + + private lazy var subTitleLable: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.font = DefaultTextFont(12) + label.textColor = UIColor.ne_emptyTitleColor + return label + }() + + private lazy var labelContainerView: UIView = { + let view = UIView() + view.translatesAutoresizingMaskIntoConstraints = false + return view + }() + + private lazy var lineView: UIView = { + let view = UIView() + view.backgroundColor = .ne_greyLine + view.translatesAutoresizingMaskIntoConstraints = false + return view + }() + + private lazy var arrowImageView: UIImageView = { + let arrow = UIImageView(image: UIImage.ne_imageNamed(name: "arrowRight")) + arrow.translatesAutoresizingMaskIntoConstraints = false + return arrow + }() } -class IDGroupLable:UILabel { - - private var content:String? - - init(content:String) { - super.init(frame: CGRect.zero) - self.content = content - setupStyle() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - - override func draw(_ rect: CGRect) { - super.draw(rect) - self.addCorner(conrners: .allCorners, radius: 4) - } - - func setupStyle(){ - self.font = DefaultTextFont(12) - self.textColor = HexRGB(0x656A72) - self.backgroundColor = HexRGB(0xF2F4F5) - self.text = content - } - - - // 定义一个接受间距的属性 - var textInsets = UIEdgeInsets.zero - - //返回 label 重新计算过 text 的 rectangle - override func textRect(forBounds bounds: CGRect, limitedToNumberOfLines numberOfLines: Int) -> CGRect { - guard text != nil else { - return super.textRect(forBounds: bounds, limitedToNumberOfLines: numberOfLines) - } - - let insetRect = bounds.inset(by: textInsets) - let textRect = super.textRect(forBounds: insetRect, limitedToNumberOfLines: numberOfLines) - let invertedInsets = UIEdgeInsets(top: -textInsets.top, - left: -textInsets.left, - bottom: -textInsets.bottom, - right: -textInsets.right) - return textRect.inset(by: invertedInsets) - } - - //3. 绘制文本时,对当前 rectangle 添加间距 - override func drawText(in rect: CGRect) { - super.drawText(in: rect.inset(by: textInsets)) +class IDGroupLable: UILabel { + private var content: String? + + init(content: String) { + super.init(frame: CGRect.zero) + self.content = content + setupStyle() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func draw(_ rect: CGRect) { + super.draw(rect) + addCorner(conrners: .allCorners, radius: 4) + } + + func setupStyle() { + font = DefaultTextFont(12) + textColor = HexRGB(0x656A72) + backgroundColor = HexRGB(0xF2F4F5) + text = content + } + + // 定义一个接受间距的属性 + var textInsets = UIEdgeInsets.zero + + // 返回 label 重新计算过 text 的 rectangle + override func textRect(forBounds bounds: CGRect, + limitedToNumberOfLines numberOfLines: Int) -> CGRect { + guard text != nil else { + return super.textRect(forBounds: bounds, limitedToNumberOfLines: numberOfLines) } - + + let insetRect = bounds.inset(by: textInsets) + let textRect = super.textRect(forBounds: insetRect, limitedToNumberOfLines: numberOfLines) + let invertedInsets = UIEdgeInsets(top: -textInsets.top, + left: -textInsets.left, + bottom: -textInsets.bottom, + right: -textInsets.right) + return textRect.inset(by: invertedInsets) + } + + // 3. 绘制文本时,对当前 rectangle 添加间距 + override func drawText(in rect: CGRect) { + super.drawText(in: rect.inset(by: textInsets)) + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/NEHomeChannelCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/NEHomeChannelCell.swift index cc84ecc8..6bc18f59 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/NEHomeChannelCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/NEHomeChannelCell.swift @@ -1,89 +1,92 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCoreIM class NEHomeChannelCell: UITableViewCell { + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) + // Configure the view for the selected state + } - // Configure the view for the selected state + public var channelModel: ChatChannel? { + didSet { + guard var name = channelModel?.name else { return } + name = "# \(name)" + let attrStr = NSMutableAttributedString(string: name) + attrStr.addAttribute( + NSAttributedString.Key.foregroundColor, + value: PlaceholderTextColor, + range: NSRange(location: 0, length: 1) + ) + attrStr.addAttribute( + NSAttributedString.Key.foregroundColor, + value: TextNormalColor, + range: NSRange(location: 1, length: name.count - 1) + ) + channelNameLable.attributedText = attrStr } + } - public var channelModel:ChatChannel? { - didSet { - - guard var name = channelModel?.name else { return } - name = "# \(name)" - let attrStr = NSMutableAttributedString.init(string: name) - attrStr.addAttribute(NSAttributedString.Key.foregroundColor, value:PlaceholderTextColor, range:NSRange.init(location:0, length: 1)) - attrStr.addAttribute(NSAttributedString.Key.foregroundColor, value:TextNormalColor, range:NSRange.init(location:1, length: name.count-1)) - channelNameLable.attributedText = attrStr - - } - } - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - self.selectionStyle = .none - setupSubviews() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + selectionStyle = .none + setupSubviews() + } - - func setupSubviews() { - self.contentView.addSubview(channelNameLable) - self.contentView.addSubview(redAngleView) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } - NSLayoutConstraint.activate([ - channelNameLable.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 18), - channelNameLable.centerYAnchor.constraint(equalTo: self.contentView.centerYAnchor), - channelNameLable.rightAnchor.constraint(equalTo: self.contentView.rightAnchor,constant: -50), + func setupSubviews() { + contentView.addSubview(channelNameLable) + contentView.addSubview(redAngleView) - ]) - - NSLayoutConstraint.activate([ - redAngleView.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -18), - redAngleView.centerYAnchor.constraint(equalTo: self.contentView.centerYAnchor), - redAngleView.heightAnchor.constraint(equalToConstant: 18) - ]) - } - + NSLayoutConstraint.activate([ + channelNameLable.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 18), + channelNameLable.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + channelNameLable.rightAnchor.constraint( + equalTo: contentView.rightAnchor, + constant: -50 + ), + ]) - private lazy var channelNameLable:UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.font = DefaultTextFont(16) - label.textColor = TextNormalColor - return label - }() - + NSLayoutConstraint.activate([ + redAngleView.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -18), + redAngleView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + redAngleView.heightAnchor.constraint(equalToConstant: 18), + ]) + } - lazy var redAngleView:RedAngleLabel = { - let label = RedAngleLabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.font = DefaultTextFont(12) - label.textColor = .white - label.text = "99+" - label.backgroundColor = HexRGB(0xF24957) - label.textInsets = UIEdgeInsets(top: 3, left: 7, bottom: 3, right: 7) - label.layer.cornerRadius = 9 - label.clipsToBounds = true - label.isHidden = true - return label - }() -} + private lazy var channelNameLable: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.font = DefaultTextFont(16) + label.textColor = TextNormalColor + return label + }() + lazy var redAngleView: RedAngleLabel = { + let label = RedAngleLabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.font = DefaultTextFont(12) + label.textColor = .white + label.text = "99+" + label.backgroundColor = HexRGB(0xF24957) + label.textInsets = UIEdgeInsets(top: 3, left: 7, bottom: 3, right: 7) + label.layer.cornerRadius = 9 + label.clipsToBounds = true + label.isHidden = true + return label + }() +} diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/NEHomeChannelView.swift b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/NEHomeChannelView.swift index 19c8ecae..3d7987c9 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/NEHomeChannelView.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/NEHomeChannelView.swift @@ -1,6 +1,7 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCoreIM @@ -8,297 +9,310 @@ import MJRefresh import NIMSDK class NEHomeChannelView: UIView { + private let className = "NEHomeChannelView" + typealias CallBack = () -> Void + typealias SelectedChannelBlock = (_ channel: ChatChannel?) -> Void + public var channelViewModel = QChatChannelViewModel() + public var channelArray = [ChatChannel]() - private let className = "NEHomeChannelView" - typealias CallBack = ()->Void - typealias SelectedChannelBlock = (_ channel: ChatChannel?) -> () - public var channelViewModel = QChatChannelViewModel() - public var channelArray = [ChatChannel]() - - public var setUpBlock:CallBack? - public var addChannelBlock:CallBack? - public var selectedChannelBlock:SelectedChannelBlock? - public var hasMore = true - public var nextTimeTag:TimeInterval = 0 - - public var viewmodel: CreateServerViewModel? - - public var qchatServerModel:QChatServer?{ - didSet { - hasMore = true - nextTimeTag = 0 - self.titleLable.text = qchatServerModel?.name - channelArray.removeAll() - requestData(timeTag: 0) - } - } - - override init(frame: CGRect) { - super.init(frame: frame) - setupSubviews() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func draw(_ rect: CGRect) { - self.addCorner(conrners: [.topLeft,.topRight], radius: 8) - } - - func setupSubviews(){ - self.backgroundColor = .white - - self.addSubview(titleLable) - self.addSubview(setUpBtn) - self.addSubview(divideLineView) - self.addSubview(addChannelBtn) - self.addSubview(subTitleLable) - self.addSubview(tableView) - self.addSubview(emptyView) - - NSLayoutConstraint.activate([ - titleLable.topAnchor.constraint(equalTo: self.topAnchor, constant: 16), - titleLable.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 12), - titleLable.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -30), - - ]) - - NSLayoutConstraint.activate([ - setUpBtn.centerYAnchor.constraint(equalTo: titleLable.centerYAnchor), - setUpBtn.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -16), - ]) - - NSLayoutConstraint.activate([ - divideLineView.topAnchor.constraint(equalTo: titleLable.bottomAnchor,constant: 16), - divideLineView.leftAnchor.constraint(equalTo: self.leftAnchor,constant: 12), - divideLineView.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -12), - divideLineView.heightAnchor.constraint(equalToConstant: 1) - ]) - - NSLayoutConstraint.activate([ - subTitleLable.topAnchor.constraint(equalTo: divideLineView.bottomAnchor,constant: 16), - subTitleLable.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 18), - ]) - - NSLayoutConstraint.activate([ - addChannelBtn.centerYAnchor.constraint(equalTo: subTitleLable.centerYAnchor), - addChannelBtn.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -15), - ]) - - NSLayoutConstraint.activate([ - tableView.topAnchor.constraint(equalTo: subTitleLable.bottomAnchor,constant: 8), - tableView.leftAnchor.constraint(equalTo: self.leftAnchor), - tableView.rightAnchor.constraint(equalTo: self.rightAnchor), - tableView.bottomAnchor.constraint(equalTo: self.bottomAnchor) - ]) - - NSLayoutConstraint.activate([ - emptyView.topAnchor.constraint(equalTo: subTitleLable.bottomAnchor,constant: 8), - emptyView.leftAnchor.constraint(equalTo: self.leftAnchor), - emptyView.rightAnchor.constraint(equalTo: self.rightAnchor), - emptyView.bottomAnchor.constraint(equalTo: self.bottomAnchor) - ]) + public var setUpBlock: CallBack? + public var addChannelBlock: CallBack? + public var selectedChannelBlock: SelectedChannelBlock? + public var hasMore = true + public var nextTimeTag: TimeInterval = 0 + + public var viewmodel: CreateServerViewModel? + + public var qchatServerModel: QChatServer? { + didSet { + hasMore = true + nextTimeTag = 0 + self.titleLable.text = qchatServerModel?.name + channelArray.removeAll() + requestData(timeTag: 0) } + } + + override init(frame: CGRect) { + super.init(frame: frame) + setupSubviews() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func draw(_ rect: CGRect) { + addCorner(conrners: [.topLeft, .topRight], radius: 8) + } + + func setupSubviews() { + backgroundColor = .white + + addSubview(titleLable) + addSubview(setUpBtn) + addSubview(divideLineView) + addSubview(addChannelBtn) + addSubview(subTitleLable) + addSubview(tableView) + addSubview(emptyView) + + NSLayoutConstraint.activate([ + titleLable.topAnchor.constraint(equalTo: topAnchor, constant: 16), + titleLable.leftAnchor.constraint(equalTo: leftAnchor, constant: 12), + titleLable.rightAnchor.constraint(equalTo: rightAnchor, constant: -30), - - @objc func updateChannelList(){ + ]) + + NSLayoutConstraint.activate([ + setUpBtn.centerYAnchor.constraint(equalTo: titleLable.centerYAnchor), + setUpBtn.rightAnchor.constraint(equalTo: rightAnchor, constant: -16), + ]) + + NSLayoutConstraint.activate([ + divideLineView.topAnchor.constraint(equalTo: titleLable.bottomAnchor, constant: 16), + divideLineView.leftAnchor.constraint(equalTo: leftAnchor, constant: 12), + divideLineView.rightAnchor.constraint(equalTo: rightAnchor, constant: -12), + divideLineView.heightAnchor.constraint(equalToConstant: 1), + ]) + + NSLayoutConstraint.activate([ + subTitleLable.topAnchor.constraint(equalTo: divideLineView.bottomAnchor, constant: 16), + subTitleLable.leftAnchor.constraint(equalTo: leftAnchor, constant: 18), + ]) + + NSLayoutConstraint.activate([ + addChannelBtn.centerYAnchor.constraint(equalTo: subTitleLable.centerYAnchor), + addChannelBtn.rightAnchor.constraint(equalTo: rightAnchor, constant: -15), + ]) + + NSLayoutConstraint.activate([ + tableView.topAnchor.constraint(equalTo: subTitleLable.bottomAnchor, constant: 8), + tableView.leftAnchor.constraint(equalTo: leftAnchor), + tableView.rightAnchor.constraint(equalTo: rightAnchor), + tableView.bottomAnchor.constraint(equalTo: bottomAnchor), + ]) + + NSLayoutConstraint.activate([ + emptyView.topAnchor.constraint(equalTo: subTitleLable.bottomAnchor, constant: 8), + emptyView.leftAnchor.constraint(equalTo: leftAnchor), + emptyView.rightAnchor.constraint(equalTo: rightAnchor), + emptyView.bottomAnchor.constraint(equalTo: bottomAnchor), + ]) + } + + @objc func updateChannelList() { + requestData(timeTag: 0) + } + + public func channelChange(noticeInfo: NIMQChatSystemNotification) { + switch noticeInfo.type { + case .channelRemove, .channelCreate, .channelUpdate: + if noticeInfo.serverId == qchatServerModel?.serverId { requestData(timeTag: 0) - } - - public func channelChange(noticeInfo:NIMQChatSystemNotification) { - - switch noticeInfo.type { - case .channelRemove,.channelCreate,.channelUpdate: - if noticeInfo.serverId == self.qchatServerModel?.serverId { - requestData(timeTag: 0) - } - break - case .updateChannelCategoryBlackWhiteRole: - if noticeInfo.serverId == self.qchatServerModel?.serverId,((noticeInfo.toAccids?.contains(IMKitLoginManager.instance.imAccid)) != nil){ - requestData(timeTag: 0) - } - break - - default: - print("") - } + } + case .updateChannelCategoryBlackWhiteRole: + if noticeInfo.serverId == qchatServerModel?.serverId, + (noticeInfo.toAccids?.contains(IMKitLoginManager.instance.imAccid)) != nil { + requestData(timeTag: 0) + } + default: + print("") } - - //MARK: lazy method - private lazy var titleLable:UILabel = { - let title = UILabel() - title.translatesAutoresizingMaskIntoConstraints = false - title.textColor = UIColor.ne_darkText - title.font = DefaultTextFont(16) - return title - }() - - private lazy var setUpBtn:ExpandButton = { - let button = ExpandButton() - button.translatesAutoresizingMaskIntoConstraints = false - button.setImage(UIImage.ne_imageNamed(name: "home_setupServer"), for: .normal) - button.setImage(UIImage.ne_imageNamed(name: "home_setupServer"), for: .highlighted) - button.addTarget(self, action: #selector(setupBtnClick), for: .touchUpInside) - return button - }() - - private lazy var divideLineView:UIView = { - let view = UIView() - view.translatesAutoresizingMaskIntoConstraints = false - view.backgroundColor = UIColor.ne_greyLine - return view - }() - - private lazy var subTitleLable:UILabel = { - let title = UILabel() - title.translatesAutoresizingMaskIntoConstraints = false - title.text = "消息频道" - title.textColor = PlaceholderTextColor - title.font = DefaultTextFont(14) - return title - }() - - private lazy var addChannelBtn:UIButton = { - let button = UIButton() - button.translatesAutoresizingMaskIntoConstraints = false - button.setImage(UIImage.ne_imageNamed(name: "home_addChannel"), for: .normal) - button.setImage(UIImage.ne_imageNamed(name: "home_addChannel"), for: .highlighted) - button.addTarget(self, action: #selector(addChannelBtnClick), for: .touchUpInside) - return button - }() - - lazy var tableView:UITableView = { - let tableView = UITableView.init(frame: .zero, style: .plain) - tableView.translatesAutoresizingMaskIntoConstraints = false - tableView.separatorStyle = .none - tableView.delegate = self - tableView.dataSource = self - tableView.register(NEHomeChannelCell.self, forCellReuseIdentifier: "\(NSStringFromClass(NEHomeChannelCell.self))") - tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.1)) - let mjfooter = MJRefreshBackNormalFooter(refreshingTarget: self, refreshingAction: #selector(loadMoreData)) - mjfooter.stateLabel?.isHidden = true - tableView.mj_footer = mjfooter - return tableView - }() - - private lazy var emptyView:EmptyDataView = { - let view = EmptyDataView(imageName: "channel_noMoreData", content: "该服务器下暂无频道",frame: tableView.bounds) - view.translatesAutoresizingMaskIntoConstraints = false - view.isHidden = true - return view - }() + } + + // MARK: lazy method + + private lazy var titleLable: UILabel = { + let title = UILabel() + title.translatesAutoresizingMaskIntoConstraints = false + title.textColor = UIColor.ne_darkText + title.font = DefaultTextFont(16) + return title + }() + + private lazy var setUpBtn: ExpandButton = { + let button = ExpandButton() + button.translatesAutoresizingMaskIntoConstraints = false + button.setImage(UIImage.ne_imageNamed(name: "home_setupServer"), for: .normal) + button.setImage(UIImage.ne_imageNamed(name: "home_setupServer"), for: .highlighted) + button.addTarget(self, action: #selector(setupBtnClick), for: .touchUpInside) + return button + }() + + private lazy var divideLineView: UIView = { + let view = UIView() + view.translatesAutoresizingMaskIntoConstraints = false + view.backgroundColor = UIColor.ne_greyLine + return view + }() + + private lazy var subTitleLable: UILabel = { + let title = UILabel() + title.translatesAutoresizingMaskIntoConstraints = false + title.text = "消息频道" + title.textColor = PlaceholderTextColor + title.font = DefaultTextFont(14) + return title + }() + + private lazy var addChannelBtn: UIButton = { + let button = UIButton() + button.translatesAutoresizingMaskIntoConstraints = false + button.setImage(UIImage.ne_imageNamed(name: "home_addChannel"), for: .normal) + button.setImage(UIImage.ne_imageNamed(name: "home_addChannel"), for: .highlighted) + button.addTarget(self, action: #selector(addChannelBtnClick), for: .touchUpInside) + return button + }() + + lazy var tableView: UITableView = { + let tableView = UITableView(frame: .zero, style: .plain) + tableView.translatesAutoresizingMaskIntoConstraints = false + tableView.separatorStyle = .none + tableView.delegate = self + tableView.dataSource = self + tableView.register( + NEHomeChannelCell.self, + forCellReuseIdentifier: "\(NSStringFromClass(NEHomeChannelCell.self))" + ) + tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.1)) + let mjfooter = MJRefreshBackNormalFooter( + refreshingTarget: self, + refreshingAction: #selector(loadMoreData) + ) + mjfooter.stateLabel?.isHidden = true + tableView.mj_footer = mjfooter + return tableView + }() + + private lazy var emptyView: EmptyDataView = { + let view = EmptyDataView( + imageName: "channel_noMoreData", + content: "该服务器下暂无频道", + frame: tableView.bounds + ) + view.translatesAutoresizingMaskIntoConstraints = false + view.isHidden = true + return view + }() } extension NEHomeChannelView { - @objc func setupBtnClick(sender:UIButton) { - if setUpBlock != nil { - setUpBlock!() - } + @objc func setupBtnClick(sender: UIButton) { + if setUpBlock != nil { + setUpBlock!() } - - @objc func addChannelBtnClick(sender:UIButton) { - if addChannelBlock != nil { - addChannelBlock!() - } + } + + @objc func addChannelBtnClick(sender: UIButton) { + if addChannelBlock != nil { + addChannelBlock!() } - - @objc func loadMoreData(){ - self.requestData(timeTag: self.nextTimeTag) - self.tableView.mj_footer?.endRefreshing() + } + + @objc func loadMoreData() { + requestData(timeTag: nextTimeTag) + tableView.mj_footer?.endRefreshing() + } + + public func requestData(timeTag: TimeInterval) { + if timeTag != 0, !hasMore { + // 上拉加载无多余数据,无需请求 + return } - - - public func requestData(timeTag:TimeInterval){ - if timeTag != 0 && !self.hasMore{ - //上拉加载无多余数据,无需请求 - return - } - - guard let serverId = qchatServerModel?.serverId else { return } - let param = QChatGetChannelsByPageParam(timeTag: timeTag, serverId: serverId) - channelViewModel.getChannelsByPage(parameter: param) { [self] error, result in - if error == nil { - guard let dataArray = result?.channels else { return } - if timeTag == 0{ - self.channelArray.removeAll() - self.channelArray = dataArray - if dataArray.isEmpty{ - emptyView.setttingContent(content: "该服务器下暂无频道") - emptyView.setEmptyImage(name: "channel_noMoreData") - emptyView.isHidden = false - }else { - emptyView.isHidden = true - } - - }else { - self.channelArray += dataArray - } - self.hasMore = result?.hasMore ?? false - self.nextTimeTag = result?.nextTimetag ?? 0 - tableView.reloadData() - }else { - NELog.errorLog(self.className, desc: "❌getChannelsByPage failed,error = \(error!)") - } + guard let serverId = qchatServerModel?.serverId else { return } + let param = QChatGetChannelsByPageParam(timeTag: timeTag, serverId: serverId) + channelViewModel.getChannelsByPage(parameter: param) { [self] error, result in + if error == nil { + guard let dataArray = result?.channels else { return } + if timeTag == 0 { + self.channelArray.removeAll() + self.channelArray = dataArray + if dataArray.isEmpty { + emptyView.setttingContent(content: "该服务器下暂无频道") + emptyView.setEmptyImage(name: "channel_noMoreData") + emptyView.isHidden = false + } else { + emptyView.isHidden = true + } + + } else { + self.channelArray += dataArray } + self.hasMore = result?.hasMore ?? false + self.nextTimeTag = result?.nextTimetag ?? 0 + tableView.reloadData() + } else { + NELog.errorLog(self.className, desc: "❌getChannelsByPage failed,error = \(error!)") + } } - - public func showEmptyServerView(){ - titleLable.isHidden = true - setUpBtn.isHidden = true - divideLineView.isHidden = true - subTitleLable.isHidden = true - addChannelBtn.isHidden = true - emptyView.isHidden = false - emptyView.setttingContent(content: "暂无服务器,\n赶紧去添加心仪的服务器吧") - emptyView.setEmptyImage(name: "servers_noMore") - } - - public func dismissEmptyView(){ - titleLable.isHidden = false - setUpBtn.isHidden = false - divideLineView.isHidden = false - subTitleLable.isHidden = false - addChannelBtn.isHidden = false - emptyView.isHidden = true - } + } + + public func showEmptyServerView() { + titleLable.isHidden = true + setUpBtn.isHidden = true + divideLineView.isHidden = true + subTitleLable.isHidden = true + addChannelBtn.isHidden = true + emptyView.isHidden = false + emptyView.setttingContent(content: "暂无服务器,\n赶紧去添加心仪的服务器吧") + emptyView.setEmptyImage(name: "servers_noMore") + } + + public func dismissEmptyView() { + titleLable.isHidden = false + setUpBtn.isHidden = false + divideLineView.isHidden = false + subTitleLable.isHidden = false + addChannelBtn.isHidden = false + emptyView.isHidden = true + } } -extension NEHomeChannelView:UITableViewDataSource,UITableViewDelegate { - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return channelArray.count - } - - public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(withIdentifier: "\(NSStringFromClass(NEHomeChannelCell.self))", for: indexPath) as! NEHomeChannelCell - if indexPath.row < channelArray.count { - let channel = channelArray[indexPath.row] - cell.channelModel = channel - if let sid = qchatServerModel?.serverId, let cid = channel.channelId, let unreadCount = viewmodel?.getChannelUnreadCount(sid, cid) { - cell.redAngleView.isHidden = false - if unreadCount <= 0 { - cell.redAngleView.isHidden = true - }else if unreadCount <= 99 { - cell.redAngleView.text = "\(unreadCount)" - }else { - cell.redAngleView.text = "99+" - } - }else { - cell.redAngleView.isHidden = true - } - } - return cell - } - - public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - if let block = self.selectedChannelBlock,channelArray.count>0{ - block(channelArray[indexPath.row]) +extension NEHomeChannelView: UITableViewDataSource, UITableViewDelegate { + public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + channelArray.count + } + + public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(NSStringFromClass(NEHomeChannelCell.self))", + for: indexPath + ) as! NEHomeChannelCell + if indexPath.row < channelArray.count { + let channel = channelArray[indexPath.row] + cell.channelModel = channel + if let sid = qchatServerModel?.serverId, let cid = channel.channelId, + let unreadCount = viewmodel?.getChannelUnreadCount( + sid, + cid + ) { + cell.redAngleView.isHidden = false + if unreadCount <= 0 { + cell.redAngleView.isHidden = true + } else if unreadCount <= 99 { + cell.redAngleView.text = "\(unreadCount)" + } else { + cell.redAngleView.text = "99+" } + } else { + cell.redAngleView.isHidden = true + } } - - public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - return 32 + return cell + } + + public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + if let block = selectedChannelBlock, channelArray.count > 0 { + block(channelArray[indexPath.row]) } + } + + public func tableView(_ tableView: UITableView, + heightForRowAt indexPath: IndexPath) -> CGFloat { + 32 + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/NEHomeServerCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/NEHomeServerCell.swift index bcdede5a..65dfd2a0 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/NEHomeServerCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/NEHomeServerCell.swift @@ -1,121 +1,120 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCoreIM import NEKitCore class NEHomeServerCell: UITableViewCell { - - lazy var redDot: UIView = { - let view = UIView() - view.translatesAutoresizingMaskIntoConstraints = false - view.backgroundColor = .ne_redColor - view.clipsToBounds = true - view.layer.cornerRadius = 4.0 - view.layer.borderColor = UIColor.white.cgColor - view.layer.borderWidth = 1 - view.isHidden = true - return view - }() - - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } + lazy var redDot: UIView = { + let view = UIView() + view.translatesAutoresizingMaskIntoConstraints = false + view.backgroundColor = .ne_redColor + view.clipsToBounds = true + view.layer.cornerRadius = 4.0 + view.layer.borderColor = UIColor.white.cgColor + view.layer.borderWidth = 1 + view.isHidden = true + return view + }() - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } - // Configure the view for the selected state - } + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + } - public var serverModel:QChatServer? { - didSet { - if let imageUrl = serverModel?.icon { - headView.sd_setImage(with: URL.init(string: imageUrl), completed: nil) - headView.setTitle("") - }else { - if let name = serverModel?.name { - headView.setTitle(name) - } - headView.sd_setImage(with: URL.init(string: ""), completed: nil) - headView.backgroundColor = .colorWithNumber(number: serverModel?.serverId) - } - - if let hasUnread = serverModel?.hasUnread { - redDot.isHidden = !hasUnread - } - + public var serverModel: QChatServer? { + didSet { + if let imageUrl = serverModel?.icon { + headView.sd_setImage(with: URL(string: imageUrl), completed: nil) + headView.setTitle("") + } else { + if let name = serverModel?.name { + headView.setTitle(name) } + headView.sd_setImage(with: URL(string: ""), completed: nil) + headView.backgroundColor = .colorWithNumber(number: serverModel?.serverId) + } + + if let hasUnread = serverModel?.hasUnread { + redDot.isHidden = !hasUnread + } } - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - self.selectionStyle = .none - self.contentView.backgroundColor = HexRGB(0xe9eff5) - setupSubviews() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func setupSubviews() { - self.contentView.addSubview(leftSelectView) - self.contentView.addSubview(headView) - - NSLayoutConstraint.activate([ - headView.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 12), - headView.topAnchor.constraint(equalTo: self.contentView.topAnchor), - headView.widthAnchor.constraint(equalToConstant: 42), - headView.heightAnchor.constraint(equalToConstant: 42), - ]) - - NSLayoutConstraint.activate([ - leftSelectView.leftAnchor.constraint(equalTo: self.contentView.leftAnchor,constant: -4), - leftSelectView.topAnchor.constraint(equalTo: self.contentView.topAnchor), - leftSelectView.widthAnchor.constraint(equalToConstant: 8), - leftSelectView.heightAnchor.constraint(equalToConstant: 36), - ]) - - contentView.addSubview(redDot) - let factor = cos(45 * Double.pi / 180) - let x = 12 + 21 * factor + 21 - let y = 21 - 21 * factor - NSLayoutConstraint.activate([ - redDot.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: x), - redDot.topAnchor.constraint(equalTo: contentView.topAnchor, constant: y), - redDot.widthAnchor.constraint(equalToConstant: 8), - redDot.heightAnchor.constraint(equalToConstant: 8) - ]) - } - - override func draw(_ rect: CGRect) { - super.draw(rect) - headView.addCorner(conrners: .allCorners, radius: 21) - } - - //MARK: lazy method - private lazy var leftSelectView:UIView = { - let view = UIView.init() - view.translatesAutoresizingMaskIntoConstraints = false - view.backgroundColor = HexRGB(0x337EFF) - view.layer.cornerRadius = 4 - view.isHidden = true - return view - }() - - lazy var headView: NEUserHeaderView = { - let view = NEUserHeaderView(frame: .zero) - view.titleLabel.textColor = .white - view.titleLabel.font = DefaultTextFont(14) - view.translatesAutoresizingMaskIntoConstraints = false - return view - }() - - public func showSelectState(isShow:Bool) { - self.leftSelectView.isHidden = isShow ? false : true - } - + } + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + selectionStyle = .none + contentView.backgroundColor = HexRGB(0xE9EFF5) + setupSubviews() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func setupSubviews() { + contentView.addSubview(leftSelectView) + contentView.addSubview(headView) + + NSLayoutConstraint.activate([ + headView.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 12), + headView.topAnchor.constraint(equalTo: contentView.topAnchor), + headView.widthAnchor.constraint(equalToConstant: 42), + headView.heightAnchor.constraint(equalToConstant: 42), + ]) + + NSLayoutConstraint.activate([ + leftSelectView.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: -4), + leftSelectView.topAnchor.constraint(equalTo: contentView.topAnchor), + leftSelectView.widthAnchor.constraint(equalToConstant: 8), + leftSelectView.heightAnchor.constraint(equalToConstant: 36), + ]) + + contentView.addSubview(redDot) + let factor = cos(45 * Double.pi / 180) + let x = 12 + 21 * factor + 21 + let y = 21 - 21 * factor + NSLayoutConstraint.activate([ + redDot.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: x), + redDot.topAnchor.constraint(equalTo: contentView.topAnchor, constant: y), + redDot.widthAnchor.constraint(equalToConstant: 8), + redDot.heightAnchor.constraint(equalToConstant: 8), + ]) + } + + override func draw(_ rect: CGRect) { + super.draw(rect) + headView.addCorner(conrners: .allCorners, radius: 21) + } + + // MARK: lazy method + + private lazy var leftSelectView: UIView = { + let view = UIView() + view.translatesAutoresizingMaskIntoConstraints = false + view.backgroundColor = HexRGB(0x337EFF) + view.layer.cornerRadius = 4 + view.isHidden = true + return view + }() + + lazy var headView: NEUserHeaderView = { + let view = NEUserHeaderView(frame: .zero) + view.titleLabel.textColor = .white + view.titleLabel.font = DefaultTextFont(14) + view.translatesAutoresizingMaskIntoConstraints = false + return view + }() + + public func showSelectState(isShow: Bool) { + leftSelectView.isHidden = isShow ? false : true + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/NEMemberListCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/NEMemberListCell.swift index f7adbdec..d0b6cfdf 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/NEMemberListCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/NEMemberListCell.swift @@ -1,86 +1,87 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit -class NEMemberListCell: UITableViewCell{ +class NEMemberListCell: UITableViewCell { + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) + // Configure the view for the selected state + } - // Configure the view for the selected state - } - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - self.selectionStyle = .none - setupSubviews() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func setupSubviews() { - self.contentView.addSubview(avatarImage) - self.contentView.addSubview(contentLabel) - self.contentView.addSubview(arrowImage) - self.contentView.addSubview(lineView) + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + selectionStyle = .none + setupSubviews() + } + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } - NSLayoutConstraint.activate([ - avatarImage.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: kScreenInterval), - avatarImage.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: -12), - avatarImage.widthAnchor.constraint(equalToConstant: 36), - avatarImage.heightAnchor.constraint(equalToConstant: 36), - ]) - - - NSLayoutConstraint.activate([ - self.lineView.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 20), - self.lineView.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -20), - self.lineView.heightAnchor.constraint(equalToConstant: 1.0), - self.lineView.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor) - ]) + func setupSubviews() { + contentView.addSubview(avatarImage) + contentView.addSubview(contentLabel) + contentView.addSubview(arrowImage) + contentView.addSubview(lineView) + NSLayoutConstraint.activate([ + avatarImage.leftAnchor.constraint( + equalTo: contentView.leftAnchor, + constant: kScreenInterval + ), + avatarImage.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -12), + avatarImage.widthAnchor.constraint(equalToConstant: 36), + avatarImage.heightAnchor.constraint(equalToConstant: 36), + ]) - NSLayoutConstraint.activate([ - self.arrowImage.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -32), - self.arrowImage.centerYAnchor.constraint(equalTo: self.contentView.centerYAnchor), - ]) - } - - private lazy var avatarImage: UIImageView = { - let avatar = UIImageView() - avatar.translatesAutoresizingMaskIntoConstraints = false - avatar.backgroundColor = .ne_defautAvatarColor - return avatar - }() - - private lazy var contentLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.textColor = TextNormalColor - label.font = DefaultTextFont(14) - return label - }() - - private lazy var lineView: UIView = { - let line = UIView() - line.translatesAutoresizingMaskIntoConstraints = false - line.backgroundColor = .ne_greyLine - return line - }() - - private lazy var arrowImage: UIImageView = { - let arrow = UIImageView() - arrow.translatesAutoresizingMaskIntoConstraints = false - arrow.image = UIImage.ne_imageNamed(name: "") - return arrow - }() + NSLayoutConstraint.activate([ + lineView.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20), + lineView.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), + lineView.heightAnchor.constraint(equalToConstant: 1.0), + lineView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + ]) + + NSLayoutConstraint.activate([ + arrowImage.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -32), + arrowImage.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + ]) + } + + private lazy var avatarImage: UIImageView = { + let avatar = UIImageView() + avatar.translatesAutoresizingMaskIntoConstraints = false + avatar.backgroundColor = .ne_defautAvatarColor + return avatar + }() + + private lazy var contentLabel: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.textColor = TextNormalColor + label.font = DefaultTextFont(14) + return label + }() + + private lazy var lineView: UIView = { + let line = UIView() + line.translatesAutoresizingMaskIntoConstraints = false + line.backgroundColor = .ne_greyLine + return line + }() + + private lazy var arrowImage: UIImageView = { + let arrow = UIImageView() + arrow.translatesAutoresizingMaskIntoConstraints = false + arrow.image = UIImage.ne_imageNamed(name: "") + return arrow + }() } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/NESearchServerCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/NESearchServerCell.swift index 27530df6..97ac73d4 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/NESearchServerCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/View/NESearchServerCell.swift @@ -1,221 +1,228 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCoreIM import SDWebImage class NESearchServerCell: UITableViewCell { + typealias callBack = (() -> Void)? + @objc var joinServerCallBack: callBack = nil + public var serverViewModel = CreateServerViewModel() - typealias callBack = (()->Void)? - @objc var joinServerCallBack:callBack = nil - public var serverViewModel = CreateServerViewModel() - - - public var serverModel:QChatServer? { - didSet { - if let imageUrl = serverModel?.icon { - headImageView.sd_setImage(with: URL.init(string: imageUrl), completed: nil) - headImageView.setTitle("") - }else { - if let name = serverModel?.name { - headImageView.setTitle(name) - } - headImageView.sd_setImage(with: URL.init(string: ""), completed: nil) - headImageView.backgroundColor = .colorWithNumber(number: serverModel?.serverId) - } - - self.content.text = serverModel?.name - - guard let serverId = serverModel?.serverId else { - return - } - self.subContent.text = "\(serverId)" - - let item = QChatGetServerMemberItem(serverId: serverId, accid: IMKitLoginManager.instance.imAccid) - let param = QChatGetServerMembersParam(serverAccIds: [item]) - - serverViewModel.getServerMemberList(parameter: param) { error, membersResult in - if error == nil { - guard let dataArray = membersResult?.memberArray else { return } - if (dataArray.isEmpty) { - self.rightContent.isHidden = true - self.joinBtn.isHidden = false - }else { - self.rightContent.isHidden = false - self.joinBtn.isHidden = true - } - }else { - print("getServerMemberList failed,error = \(error!)") - } - } + public var serverModel: QChatServer? { + didSet { + if let imageUrl = serverModel?.icon { + headImageView.sd_setImage(with: URL(string: imageUrl), completed: nil) + headImageView.setTitle("") + } else { + if let name = serverModel?.name { + headImageView.setTitle(name) } - } - - - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } + headImageView.sd_setImage(with: URL(string: ""), completed: nil) + headImageView.backgroundColor = .colorWithNumber(number: serverModel?.serverId) + } - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) - // Configure the view for the selected state - } + self.content.text = serverModel?.name - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - self.selectionStyle = .none - setupSubviews() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func draw(_ rect: CGRect) { - serviceBgView.addCorner(conrners: .allCorners, radius: 8) - headImageView.addCorner(conrners: .allCorners, radius: 18) - } - - func setupSubviews() { - self.contentView.addSubview(serviceBgView) - serviceBgView.addSubview(headImageView) - serviceBgView.addSubview(content) - serviceBgView.addSubview(subContent) - serviceBgView.addSubview(rightContent) - serviceBgView.addSubview(rightContentImageView) - serviceBgView.addSubview(joinBtn) - - NSLayoutConstraint.activate([ - serviceBgView.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: kScreenInterval), - serviceBgView.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -kScreenInterval), - serviceBgView.topAnchor.constraint(equalTo: self.contentView.topAnchor), - serviceBgView.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: -6), - ]) - - NSLayoutConstraint.activate([ - headImageView.leftAnchor.constraint(equalTo: serviceBgView.leftAnchor, constant: 16), - headImageView.centerYAnchor.constraint(equalTo: serviceBgView.centerYAnchor), - headImageView.widthAnchor.constraint(equalToConstant: 36), - headImageView.heightAnchor.constraint(equalToConstant: 36) - ]) - - NSLayoutConstraint.activate([ - subContent.leftAnchor.constraint(equalTo: content.leftAnchor), - subContent.bottomAnchor.constraint(equalTo: headImageView.bottomAnchor), - ]) - - NSLayoutConstraint.activate([ - rightContent.centerYAnchor.constraint(equalTo: serviceBgView.centerYAnchor), - rightContent.rightAnchor.constraint(equalTo: serviceBgView.rightAnchor,constant: -16), - ]) - - NSLayoutConstraint.activate([ - rightContentImageView.centerYAnchor.constraint(equalTo: rightContent.centerYAnchor), - rightContentImageView.rightAnchor.constraint(equalTo: serviceBgView.rightAnchor,constant: 16), - ]) - - NSLayoutConstraint.activate([ - joinBtn.centerYAnchor.constraint(equalTo: serviceBgView.centerYAnchor), - joinBtn.widthAnchor.constraint(equalToConstant: 56), - joinBtn.heightAnchor.constraint(equalToConstant:24), - joinBtn.rightAnchor.constraint(equalTo: serviceBgView.rightAnchor, constant: -16) - ]) - - NSLayoutConstraint.activate([ - content.topAnchor.constraint(equalTo: headImageView.topAnchor), - content.leftAnchor.constraint(equalTo: headImageView.rightAnchor,constant: 12), - content.rightAnchor.constraint(equalTo: joinBtn.leftAnchor) - ]) + guard let serverId = serverModel?.serverId else { + return + } + self.subContent.text = "\(serverId)" + + let item = QChatGetServerMemberItem( + serverId: serverId, + accid: IMKitLoginManager.instance.imAccid + ) + let param = QChatGetServerMembersParam(serverAccIds: [item]) + + serverViewModel.getServerMemberList(parameter: param) { error, membersResult in + if error == nil { + guard let dataArray = membersResult?.memberArray else { return } + if dataArray.isEmpty { + self.rightContent.isHidden = true + self.joinBtn.isHidden = false + } else { + self.rightContent.isHidden = false + self.joinBtn.isHidden = true + } + } else { + print("getServerMemberList failed,error = \(error!)") + } + } } + } + + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + // Configure the view for the selected state + } + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + selectionStyle = .none + setupSubviews() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func draw(_ rect: CGRect) { + serviceBgView.addCorner(conrners: .allCorners, radius: 8) + headImageView.addCorner(conrners: .allCorners, radius: 18) + } + + func setupSubviews() { + contentView.addSubview(serviceBgView) + serviceBgView.addSubview(headImageView) + serviceBgView.addSubview(content) + serviceBgView.addSubview(subContent) + serviceBgView.addSubview(rightContent) + serviceBgView.addSubview(rightContentImageView) + serviceBgView.addSubview(joinBtn) + + NSLayoutConstraint.activate([ + serviceBgView.leftAnchor.constraint( + equalTo: contentView.leftAnchor, + constant: kScreenInterval + ), + serviceBgView.rightAnchor.constraint( + equalTo: contentView.rightAnchor, + constant: -kScreenInterval + ), + serviceBgView.topAnchor.constraint(equalTo: contentView.topAnchor), + serviceBgView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -6), + ]) - - //MARK: lazyMethod - private lazy var serviceBgView:UIView = { - let view = UIView() - view.translatesAutoresizingMaskIntoConstraints = false - view.backgroundColor = HexRGB(0xEFF1F4) - return view - }() - - lazy var headImageView: NEUserHeaderView = { - let view = NEUserHeaderView(frame: .zero) - view.titleLabel.textColor = .white - view.titleLabel.font = DefaultTextFont(14) - view.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + headImageView.leftAnchor.constraint(equalTo: serviceBgView.leftAnchor, constant: 16), + headImageView.centerYAnchor.constraint(equalTo: serviceBgView.centerYAnchor), + headImageView.widthAnchor.constraint(equalToConstant: 36), + headImageView.heightAnchor.constraint(equalToConstant: 36), + ]) + + NSLayoutConstraint.activate([ + subContent.leftAnchor.constraint(equalTo: content.leftAnchor), + subContent.bottomAnchor.constraint(equalTo: headImageView.bottomAnchor), + ]) + + NSLayoutConstraint.activate([ + rightContent.centerYAnchor.constraint(equalTo: serviceBgView.centerYAnchor), + rightContent.rightAnchor.constraint(equalTo: serviceBgView.rightAnchor, constant: -16), + ]) + + NSLayoutConstraint.activate([ + rightContentImageView.centerYAnchor.constraint(equalTo: rightContent.centerYAnchor), + rightContentImageView.rightAnchor.constraint( + equalTo: serviceBgView.rightAnchor, + constant: 16 + ), + ]) + + NSLayoutConstraint.activate([ + joinBtn.centerYAnchor.constraint(equalTo: serviceBgView.centerYAnchor), + joinBtn.widthAnchor.constraint(equalToConstant: 56), + joinBtn.heightAnchor.constraint(equalToConstant: 24), + joinBtn.rightAnchor.constraint(equalTo: serviceBgView.rightAnchor, constant: -16), + ]) + + NSLayoutConstraint.activate([ + content.topAnchor.constraint(equalTo: headImageView.topAnchor), + content.leftAnchor.constraint(equalTo: headImageView.rightAnchor, constant: 12), + content.rightAnchor.constraint(equalTo: joinBtn.leftAnchor), + ]) + } + + // MARK: lazyMethod + + private lazy var serviceBgView: UIView = { + let view = UIView() + view.translatesAutoresizingMaskIntoConstraints = false + view.backgroundColor = HexRGB(0xEFF1F4) + return view + }() + + lazy var headImageView: NEUserHeaderView = { + let view = NEUserHeaderView(frame: .zero) + view.titleLabel.textColor = .white + view.titleLabel.font = DefaultTextFont(14) + view.translatesAutoresizingMaskIntoConstraints = false // view.clipsToBounds = true - return view - }() - - private lazy var content:UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.font = DefaultTextFont(14) - label.textColor = TextNormalColor - return label - }() - - private lazy var subContent:UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.font = DefaultTextFont(12) - label.textColor = .ne_blueText - return label - }() - - private lazy var rightContent:UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.text = localizable("已申请") - label.font = DefaultTextFont(12) - label.textColor = UIColor.ne_emptyTitleColor - label.isHidden = true - return label - }() - - private lazy var rightContentImageView:UIImageView = { - let imageView = UIImageView.init(image: UIImage.ne_imageNamed(name: "addOther_icon")) - imageView.translatesAutoresizingMaskIntoConstraints = false - imageView.isHidden = true - return imageView - }() - - - private lazy var joinBtn:UIButton = { - let button = UIButton() - button.translatesAutoresizingMaskIntoConstraints = false - button.setTitle(localizable("加入"), for: .normal) - button.setTitleColor(UIColor.white, for: .normal) - button.titleLabel?.font = DefaultTextFont(12) - button.backgroundColor = HexRGB(0x337EFF) - button.layer.cornerRadius = 4 - button.addTarget(self, action: #selector(bottomBtnClick), for: .touchUpInside) - button.isHidden = true - return button - }() + return view + }() + + private lazy var content: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.font = DefaultTextFont(14) + label.textColor = TextNormalColor + return label + }() + + private lazy var subContent: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.font = DefaultTextFont(12) + label.textColor = .ne_blueText + return label + }() + + private lazy var rightContent: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.text = localizable("已申请") + label.font = DefaultTextFont(12) + label.textColor = UIColor.ne_emptyTitleColor + label.isHidden = true + return label + }() + + private lazy var rightContentImageView: UIImageView = { + let imageView = UIImageView(image: UIImage.ne_imageNamed(name: "addOther_icon")) + imageView.translatesAutoresizingMaskIntoConstraints = false + imageView.isHidden = true + return imageView + }() + + private lazy var joinBtn: UIButton = { + let button = UIButton() + button.translatesAutoresizingMaskIntoConstraints = false + button.setTitle(localizable("加入"), for: .normal) + button.setTitleColor(UIColor.white, for: .normal) + button.titleLabel?.font = DefaultTextFont(12) + button.backgroundColor = HexRGB(0x337EFF) + button.layer.cornerRadius = 4 + button.addTarget(self, action: #selector(bottomBtnClick), for: .touchUpInside) + button.isHidden = true + return button + }() } extension NESearchServerCell { - - @objc func bottomBtnClick(sender:UIButton){ - - guard let serverId = serverModel?.serverId else { - return - } - let param = QChatApplyServerJoinParam(serverId: serverId ) - - serverViewModel.applyServerJoin(parameter: param) { [self] error in - if error == nil { - self.joinBtn.isHidden = true - self.rightContent.isHidden = false - if self.joinServerCallBack != nil { - joinServerCallBack!() - } - }else { - print("applyServerJoin failed,error = \(error!)") - } + @objc func bottomBtnClick(sender: UIButton) { + guard let serverId = serverModel?.serverId else { + return + } + let param = QChatApplyServerJoinParam(serverId: serverId) + + serverViewModel.applyServerJoin(parameter: param) { [self] error in + if error == nil { + self.joinBtn.isHidden = true + self.rightContent.isHidden = false + if self.joinServerCallBack != nil { + joinServerCallBack!() } + } else { + print("applyServerJoin failed,error = \(error!)") + } } + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/ViewModel/CreateServerViewModel.swift b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/ViewModel/CreateServerViewModel.swift index 0cd73735..954b16e9 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/ViewModel/CreateServerViewModel.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/ViewModel/CreateServerViewModel.swift @@ -1,6 +1,7 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NEKitCoreIM @@ -13,217 +14,217 @@ import SDWebImageWebPCoder import SDWebImageSVGKitPlugin public class CreateServerViewModel: QChatRepoMessageDelegate, AllChannelDataDelegate { - - typealias ServerListRefresh = () -> Void - - var dataDic = WeakDictionary() - - var channelUnreadCountDic = [UInt64: Int]() - - var requestFlag = [UInt64: AllChannelData]() - - var channelDataDic = [UInt64 : [UInt64: UInt]]() - - let repo = QChatRepo() - - var currentServerId: UInt64? - - var delegate: ViewModelDelegate? - - var updateServerList: ServerListRefresh? - - public init(){ - repo.delegate = self - let webpCoder = SDImageWebPCoder() - SDImageCodersManager.shared.addCoder(webpCoder) - let svgCoder = SDImageSVGKCoder.shared - SDImageCodersManager.shared.addCoder(svgCoder) - } - - public func onUnReadChange(_ unreads: [NIMQChatUnreadInfo]?, _ lastUnreads: [NIMQChatUnreadInfo]?) { - - print("onUnReadChange: ", unreads as Any) - weak var weakSelf = self - var set = Set() - - unreads?.forEach({ unread in - set.insert(unread.serverId) - if weakSelf?.channelDataDic[unread.serverId] != nil { - weakSelf?.channelDataDic[unread.serverId]?[unread.channelId] = unread.unreadCount - }else { - var channelDic = [UInt64: UInt]() - channelDic[unread.channelId] = unread.unreadCount - weakSelf?.channelDataDic[unread.serverId] = channelDic - } - }) - - set.forEach { sid in - let hasUnread = checkServerExistUnread(sid) - print("hasUnread : ", hasUnread) - let model = weakSelf?.dataDic[sid] - print("server model : ", model?.name as Any) - model?.hasUnread = hasUnread - if let cSid = weakSelf?.currentServerId, cSid == sid { - weakSelf?.delegate?.dataDidChange() - } - } - - if let block = updateServerList { - block() - } - + typealias ServerListRefresh = () -> Void + + var dataDic = WeakDictionary() + + var channelUnreadCountDic = [UInt64: Int]() + + var requestFlag = [UInt64: AllChannelData]() + + var channelDataDic = [UInt64: [UInt64: UInt]]() + + let repo = QChatRepo() + + var currentServerId: UInt64? + + var delegate: ViewModelDelegate? + + var updateServerList: ServerListRefresh? + + public init() { + repo.delegate = self + let webpCoder = SDImageWebPCoder() + SDImageCodersManager.shared.addCoder(webpCoder) + let svgCoder = SDImageSVGKCoder.shared + SDImageCodersManager.shared.addCoder(svgCoder) + } + + public func onUnReadChange(_ unreads: [NIMQChatUnreadInfo]?, + _ lastUnreads: [NIMQChatUnreadInfo]?) { + print("onUnReadChange: ", unreads as Any) + weak var weakSelf = self + var set = Set() + + unreads?.forEach { unread in + set.insert(unread.serverId) + if weakSelf?.channelDataDic[unread.serverId] != nil { + weakSelf?.channelDataDic[unread.serverId]?[unread.channelId] = unread.unreadCount + } else { + var channelDic = [UInt64: UInt]() + channelDic[unread.channelId] = unread.unreadCount + weakSelf?.channelDataDic[unread.serverId] = channelDic + } } - - func checkServerExistUnread(_ serverId: UInt64) -> Bool{ - if let channelDic = channelDataDic[serverId] { - for key in channelDic.keys { - if let unreadCount = channelDic[key], unreadCount > 0 { - return true - } - } - } - return false - } - - public lazy var dataArray:[(String,String)] = { - let array = [("mine_create",localizable("qchat_mine_add")),("addOther_icon",localizable("qchat_join_otherServer"))] - return array - }() - - - public func createServer(parameter:CreateServerParam,_ completion:@escaping (NSError?,CreateServerResult?) ->()) { - QChatServerProvider.shared.createServer(param: parameter) { error, serverResult in - completion(error,serverResult) - } - + set.forEach { sid in + let hasUnread = checkServerExistUnread(sid) + print("hasUnread : ", hasUnread) + let model = weakSelf?.dataDic[sid] + print("server model : ", model?.name as Any) + model?.hasUnread = hasUnread + if let cSid = weakSelf?.currentServerId, cSid == sid { + weakSelf?.delegate?.dataDidChange() + } } - - - public func getServers(parameter:QChatGetServersParam,_ completion:@escaping(NSError?,QChatGetServersResult?)->() ){ - repo.getServers(parameter) { error, serverResult in - completion(error,serverResult) - } + + if let block = updateServerList { + block() } - - public func getServerList(parameter:GetServersByPageParam,_ completion:@escaping (NSError?,GetServersByPageResult?)->()){ - QChatServerProvider.shared.getServerCount(param: parameter) { error, result in - completion(error,result) + } + + func checkServerExistUnread(_ serverId: UInt64) -> Bool { + if let channelDic = channelDataDic[serverId] { + for key in channelDic.keys { + if let unreadCount = channelDic[key], unreadCount > 0 { + return true } + } } - - public func getServerMemberList(parameter:QChatGetServerMembersParam,_ completion:@escaping (NSError?,QChatGetServerMembersResult?)->()) { - QChatServerProvider.shared.getServerMembers(param: parameter) { error, result in - completion(error,result) - } + return false + } + + public lazy var dataArray: [(String, String)] = { + let array = [ + ("mine_create", localizable("qchat_mine_add")), + ("addOther_icon", localizable("qchat_join_otherServer")), + ] + return array + }() + + public func createServer(parameter: CreateServerParam, + _ completion: @escaping (NSError?, CreateServerResult?) -> Void) { + QChatServerProvider.shared.createServer(param: parameter) { error, serverResult in + completion(error, serverResult) + } + } + + public func getServers(parameter: QChatGetServersParam, + _ completion: @escaping (NSError?, QChatGetServersResult?) -> Void) { + repo.getServers(parameter) { error, serverResult in + completion(error, serverResult) + } + } + + public func getServerList(parameter: GetServersByPageParam, + _ completion: @escaping (NSError?, GetServersByPageResult?) -> Void) { + QChatServerProvider.shared.getServerCount(param: parameter) { error, result in + completion(error, result) + } + } + + public func getServerMemberList(parameter: QChatGetServerMembersParam, + _ completion: @escaping (NSError?, + QChatGetServerMembersResult?) -> Void) { + QChatServerProvider.shared.getServerMembers(param: parameter) { error, result in + completion(error, result) + } + } + + public func getServerMembersByPage(parameter: QChatGetServerMembersByPageParam, + _ completion: @escaping (NSError?, + QChatGetServerMembersResult?) + -> Void) { + QChatServerProvider.shared.getServerMembersByPage(param: parameter) { error, result in + completion(error, result) } - - - public func getServerMembersByPage(parameter:QChatGetServerMembersByPageParam,_ completion:@escaping (NSError?,QChatGetServerMembersResult?)->()) { - QChatServerProvider.shared.getServerMembersByPage(param: parameter) { error, result in - completion(error,result) - } // repo.getServerMembersByPage(parameter, completion) + } + + public func applyServerJoin(parameter: QChatApplyServerJoinParam, + _ completion: @escaping (NSError?) -> Void) { + QChatServerProvider.shared.applyServerJoin(param: parameter) { error in + completion(error) } - - - public func applyServerJoin(parameter:QChatApplyServerJoinParam,_ completion:@escaping (NSError?)->()) { - QChatServerProvider.shared.applyServerJoin(param: parameter) { error in - completion(error) - } + } + + public func inviteMembersToServer(serverId: UInt64, accids: [String], + _ completion: @escaping (NSError?) -> Void) { + let param = QChatInviteServerMembersParam(serverId: serverId, accids: accids) + repo.inviteMembersToServer(param) { error in + completion(error) } - - - public func inviteMembersToServer(serverId:UInt64,accids:[String],_ completion:@escaping (NSError?)->()) { - let param = QChatInviteServerMembersParam(serverId: serverId, accids: accids) - repo.inviteMembersToServer(param) { error in - completion(error) - } + } + + public func getUnread(_ servers: [QChatServer]) { + print("server model get unread servers : ", servers.count) + + if currentServerId == nil { + currentServerId = servers.first?.serverId } - - public func getUnread(_ servers: [QChatServer]){ - print("server model get unread servers : ", servers.count) - - if currentServerId == nil { - currentServerId = servers.first?.serverId - } - weak var weakSelf = self - servers.forEach { server in - if let sid = server.serverId { - weakSelf?.dataDic[sid] = server - } - weakSelf?.getAllChannel(server) - } + weak var weakSelf = self + servers.forEach { server in + if let sid = server.serverId { + weakSelf?.dataDic[sid] = server + } + weakSelf?.getAllChannel(server) } - - func getAllChannel(_ server: QChatServer){ - if let sid = server.serverId, requestFlag[sid] == nil { - let allChannelData = AllChannelData(sid: sid) - allChannelData.delegate = self - requestFlag[sid] = allChannelData - } + } + + func getAllChannel(_ server: QChatServer) { + if let sid = server.serverId, requestFlag[sid] == nil { + let allChannelData = AllChannelData(sid: sid) + allChannelData.delegate = self + requestFlag[sid] = allChannelData } - - func getChannelUnread(_ serverId: UInt64, _ channels: [ChatChannel]){ - - print("getChannelUnread channel count : ", channels.count) - var param = GetChannelUnreadInfosParam() - var targets = [ChannelIdInfo]() - - channels.forEach { channel in - var channelIdInfo = ChannelIdInfo() - channelIdInfo.serverId = serverId - channelIdInfo.channelId = channel.channelId - targets.append(channelIdInfo) - } - param.targets = targets + } + + func getChannelUnread(_ serverId: UInt64, _ channels: [ChatChannel]) { + print("getChannelUnread channel count : ", channels.count) + var param = GetChannelUnreadInfosParam() + var targets = [ChannelIdInfo]() + + channels.forEach { channel in + var channelIdInfo = ChannelIdInfo() + channelIdInfo.serverId = serverId + channelIdInfo.channelId = channel.channelId + targets.append(channelIdInfo) + } + param.targets = targets // weak var weakSelf = self - repo.getChannelUnReadInfo(param) { error, infos in - - print("get channel unread info : ", error as Any) - /* - infos?.forEach({ info in - if weakSelf?.channelDataDic[info.serverId] != nil { - weakSelf?.channelDataDic[info.serverId]?[info.channelId] = info.unreadCount - }else { - var channelDic = [UInt64: UInt]() - channelDic[info.channelId] = info.unreadCount - weakSelf?.channelDataDic[info.serverId] = channelDic - } - }) - if let last = infos?.last, let sid = weakSelf?.currentServerId { - if last.serverId == sid { - weakSelf?.delegate?.dataDidChange() - } - } - if let server = weakSelf?.dataDic[serverId], let block = weakSelf?.updateServerList, let hasUnread = weakSelf?.checkServerExistUnread(serverId){ - server.hasUnread = hasUnread - block() - if let cSid = weakSelf?.currentServerId, cSid == serverId { - weakSelf?.delegate?.dataDidChange() - } - }*/ - } - - } - - func dataGetSuccess(_ serverId: UInt64, _ channels: [ChatChannel]) { - print("get unread channel success : ", channels.count) - requestFlag.removeValue(forKey: serverId) - getChannelUnread(serverId, channels) - } - - func dataGetError(_ serverId: UInt64, _ error: Error) { - requestFlag.removeValue(forKey: serverId) - print("get all channels error : ", error) - } - - func getChannelUnreadCount(_ serverId: UInt64, _ channelId: UInt64) -> UInt{ - if let channelDic = channelDataDic[serverId], let count = channelDic[channelId] { - return count - } - return 0 + repo.getChannelUnReadInfo(param) { error, infos in + + print("get channel unread info : ", error as Any) + /* + infos?.forEach({ info in + if weakSelf?.channelDataDic[info.serverId] != nil { + weakSelf?.channelDataDic[info.serverId]?[info.channelId] = info.unreadCount + }else { + var channelDic = [UInt64: UInt]() + channelDic[info.channelId] = info.unreadCount + weakSelf?.channelDataDic[info.serverId] = channelDic + } + }) + if let last = infos?.last, let sid = weakSelf?.currentServerId { + if last.serverId == sid { + weakSelf?.delegate?.dataDidChange() + } + } + if let server = weakSelf?.dataDic[serverId], let block = weakSelf?.updateServerList, let hasUnread = weakSelf?.checkServerExistUnread(serverId){ + server.hasUnread = hasUnread + block() + if let cSid = weakSelf?.currentServerId, cSid == serverId { + weakSelf?.delegate?.dataDidChange() + } + }*/ + } + } + + func dataGetSuccess(_ serverId: UInt64, _ channels: [ChatChannel]) { + print("get unread channel success : ", channels.count) + requestFlag.removeValue(forKey: serverId) + getChannelUnread(serverId, channels) + } + + func dataGetError(_ serverId: UInt64, _ error: Error) { + requestFlag.removeValue(forKey: serverId) + print("get all channels error : ", error) + } + + func getChannelUnreadCount(_ serverId: UInt64, _ channelId: UInt64) -> UInt { + if let channelDic = channelDataDic[serverId], let count = channelDic[channelId] { + return count } - - + return 0 + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/ViewModel/MemberListViewModel.swift b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/ViewModel/MemberListViewModel.swift index c937fa37..1ae89f94 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/ViewModel/MemberListViewModel.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/QChatHomePage/ViewModel/MemberListViewModel.swift @@ -1,61 +1,60 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NEKitQChat import NEKitCoreIM public class MemberListViewModel { - - let repo = QChatRepo() - public var memberInfomationArray:[QChatMember]? - weak var delegate: ViewModelDelegate? - - init(){} - - func requestServerMemebersByPage(param:QChatGetServerMembersByPageParam,_ completion: @escaping (NSError?,[ServerMemeber]?)->()){ - repo.getServerMembersByPage(param) { error, memberResult in - - if error == nil { - guard let memberArr = memberResult?.memberArray else { return } - var accidList = [String]() - var dic = [String: ServerMemeber]() - - for memberModel in memberArr { - accidList.append(memberModel.accid ?? "") - if let accid = memberModel.accid { - dic[accid] = memberModel - } - } - - let roleParam = QChatGetExistingAccidsInServerRoleParam(serverId: param.serverId!, accids: accidList) - self.repo.getExistingServerRolesByAccids(roleParam) { error, serverRolesDict in - serverRolesDict?.forEach({ key,roleArray in - dic[key]?.roles = roleArray - }) - var tempServerArray = [ServerMemeber]() - for var memberModel in memberArr { - if let accid = memberModel.accid,let dicMember = dic[accid] { - memberModel.roles = dicMember.roles - memberModel.imName = dicMember.imName - tempServerArray.append(memberModel) - } - } - completion(nil,tempServerArray) - } - - }else { - completion(error,nil) - print("getServerMembersByPage failed,error = \(error!)") + let repo = QChatRepo() + public var memberInfomationArray: [QChatMember]? + weak var delegate: ViewModelDelegate? + + init() {} + + func requestServerMemebersByPage(param: QChatGetServerMembersByPageParam, + _ completion: @escaping (NSError?, [ServerMemeber]?) -> Void) { + repo.getServerMembersByPage(param) { error, memberResult in + + if error == nil { + guard let memberArr = memberResult?.memberArray else { return } + var accidList = [String]() + var dic = [String: ServerMemeber]() + + for memberModel in memberArr { + accidList.append(memberModel.accid ?? "") + if let accid = memberModel.accid { + dic[accid] = memberModel + } + } + + let roleParam = QChatGetExistingAccidsInServerRoleParam( + serverId: param.serverId!, + accids: accidList + ) + self.repo.getExistingServerRolesByAccids(roleParam) { error, serverRolesDict in + serverRolesDict?.forEach { key, roleArray in + dic[key]?.roles = roleArray + } + var tempServerArray = [ServerMemeber]() + for var memberModel in memberArr { + if let accid = memberModel.accid, let dicMember = dic[accid] { + memberModel.roles = dicMember.roles + memberModel.imName = dicMember.imName + tempServerArray.append(memberModel) } + } + completion(nil, tempServerArray) } - } - - - func getRoles(){ - + } else { + completion(error, nil) + print("getServerMembersByPage failed,error = \(error!)") + } } - + } + + func getRoles() {} } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/QChatRouter/QChatRouter.swift b/NEQChatUIKit/NEKitQChatUI/Classes/QChatRouter/QChatRouter.swift index 561c9d52..bc9d74c5 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/QChatRouter/QChatRouter.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/QChatRouter/QChatRouter.swift @@ -1,11 +1,10 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation -public struct QChatRouter { - public static func register() { - - } +public enum QChatRouter { + public static func register() {} } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Server/Model/IdGroupModel.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Server/Model/IdGroupModel.swift index aa31b740..c40eaa31 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Server/Model/IdGroupModel.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Server/Model/IdGroupModel.swift @@ -1,39 +1,40 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NEKitCoreIM class IdGroupModel { - var idName: String? - var subTitle: String? + var idName: String? + var subTitle: String? // { // didSet { // if let s = subTitle, s == "0人" { -// +// // } // } // } - var uid: Int? - var isSelect = false - var cornerType: CornerType = .none - var role: ServerRole? - var hasPermission = false - - public init(){} - - public init(_ serverRole: ServerRole){ - role = serverRole - idName = serverRole.name - if let type = serverRole.type, type == .everyone { - subTitle = localizable("qchat_group_default_permission") - }else if let type = serverRole.type, type == .custom { - subTitle = "\(serverRole.memberCount ?? 0)人" - } - + var uid: Int? + var isSelect = false + var cornerType: CornerType = .none + var role: ServerRole? + var hasPermission = false + + public init() {} + + public init(_ serverRole: ServerRole) { + role = serverRole + idName = serverRole.name + if let type = serverRole.type, type == .everyone { + subTitle = localizable("qchat_group_default_permission") + } else if let type = serverRole.type, type == .custom { + subTitle = "\(serverRole.memberCount ?? 0)人" + } + // if let s = subTitle, s == "0人" { -// +// // } - } + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Server/Model/PermissionCellModel.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Server/Model/PermissionCellModel.swift index d603f59d..65a1cc6d 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Server/Model/PermissionCellModel.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Server/Model/PermissionCellModel.swift @@ -1,14 +1,14 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation class PermissionCellModel { - - weak var permission: PermissionModel? - var permissionKey: String? - var showName: String? - var cornerType = CornerType.none - var hasPermission = false + weak var permission: PermissionModel? + var permissionKey: String? + var showName: String? + var cornerType = CornerType.none + var hasPermission = false } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Server/Model/PermissionModel.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Server/Model/PermissionModel.swift index 89529fb9..63abac2f 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Server/Model/PermissionModel.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Server/Model/PermissionModel.swift @@ -1,99 +1,107 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NEKitCoreIM class PermissionModel: NSObject { - - let commonPermission = [#keyPath(PermissionModel.managerServer),#keyPath(PermissionModel.allChannelProperty), #keyPath(PermissionModel.role)] - - let commonPermissionDic = [#keyPath(PermissionModel.managerServer):localizable("qchat_manager_server"),#keyPath(PermissionModel.allChannelProperty):localizable("qchat_manager_channel"), - #keyPath(PermissionModel.role):localizable("qchat_manager_role")] - - @objc var allChannelProperty = ChatPermissionType.manageChannel.rawValue - - @objc var role = ChatPermissionType.manageRole.rawValue - - @objc var managerServer = ChatPermissionType.manageServer.rawValue - - let messagePermission = [#keyPath(PermissionModel.sendMessage)] - - let messagePermissionDic = [#keyPath(PermissionModel.sendMessage):localizable("qchat_send_message")] - - @objc var sendMessage = ChatPermissionType.sendMsg.rawValue - + let commonPermission = [ + #keyPath(PermissionModel.managerServer), + #keyPath(PermissionModel.allChannelProperty), + #keyPath(PermissionModel.role), + ] + + let commonPermissionDic = [ + #keyPath(PermissionModel.managerServer): localizable("qchat_manager_server"), + #keyPath(PermissionModel.allChannelProperty): localizable("qchat_manager_channel"), + #keyPath(PermissionModel.role): localizable("qchat_manager_role"), + ] + + @objc var allChannelProperty = ChatPermissionType.manageChannel.rawValue + + @objc var role = ChatPermissionType.manageRole.rawValue + + @objc var managerServer = ChatPermissionType.manageServer.rawValue + + let messagePermission = [#keyPath(PermissionModel.sendMessage)] + + let messagePermissionDic = + [#keyPath(PermissionModel.sendMessage): localizable("qchat_send_message")] + + @objc var sendMessage = ChatPermissionType.sendMsg.rawValue + // @objc var deleteOtherMemberMessage = ChatPermissionType.deleteOtherMsg.rawValue -// +// // @objc var recallMessage = ChatPermissionType.revokeMsg.rawValue -// +// // @objc var atAnyMember = ChatPermissionType.remindOther.rawValue -// +// // @objc var atAllMember = ChatPermissionType.remindAll.rawValue - - /* - let messagePermission = [#keyPath(PermissionModel.sendMessage), - #keyPath(PermissionModel.deleteOtherMemberMessage), - #keyPath(PermissionModel.recallMessage), - #keyPath(PermissionModel.atAnyMember), - #keyPath(PermissionModel.atAllMember)] - - let messagePermissionDic = [#keyPath(PermissionModel.sendMessage):localizable("qchat_send_message"), - #keyPath(PermissionModel.deleteOtherMemberMessage):localizable("qchat_delete_message"), - #keyPath(PermissionModel.recallMessage):localizable("qchat_recall_message"), - #keyPath(PermissionModel.atAnyMember):localizable("qchat_at_any"), - #keyPath(PermissionModel.atAllMember):localizable("qchat_at_all")] - - @objc var sendMessage = ChatPermissionType.sendMsg.rawValue - - @objc var deleteOtherMemberMessage = ChatPermissionType.deleteOtherMsg.rawValue - - @objc var recallMessage = ChatPermissionType.revokeMsg.rawValue - - @objc var atAnyMember = ChatPermissionType.remindOther.rawValue - - @objc var atAllMember = ChatPermissionType.remindAll.rawValue - */ - - let memberPermission = [#keyPath(PermissionModel.modifyOwnServer), - #keyPath(PermissionModel.modifyOthersServer), - #keyPath(PermissionModel.inviteMember), - #keyPath(PermissionModel.kickout), - #keyPath(PermissionModel.managerBlackAndWhite)] - - let memberPermissionDic = [#keyPath(PermissionModel.modifyOwnServer):localizable("qchat_modify_own_server"), - #keyPath(PermissionModel.modifyOthersServer):localizable("qchat_modify_other_server"), - #keyPath(PermissionModel.inviteMember): localizable("qchat_invite_member"), - #keyPath(PermissionModel.kickout): localizable("qchat_kickout_member"), - #keyPath(PermissionModel.managerBlackAndWhite): localizable("qchat_manager_channel_list")] - - @objc var modifyOwnServer = ChatPermissionType.manageServer.rawValue - - @objc var modifyOthersServer = ChatPermissionType.modifyOthersInfoInServer.rawValue - - @objc var inviteMember = ChatPermissionType.inviteToServer.rawValue - - @objc var kickout = ChatPermissionType.kickOthersInServer.rawValue - - @objc var managerBlackAndWhite = ChatPermissionType.manageBlackWhiteList.rawValue - - - var changeMap = [String : Bool]() - - override init() { - super.init() - } - - func getChangePermission() -> [ChatPermissionType: Bool] { - var permissions = [ChatPermissionType: Bool]() - changeMap.forEach { (key: String, v: Bool) in - if let permissionKey = value(forKey: key) as? String, let type = ChatPermissionType(rawValue: permissionKey) { - permissions[type] = v - } - } - return permissions + + /* + let messagePermission = [#keyPath(PermissionModel.sendMessage), + #keyPath(PermissionModel.deleteOtherMemberMessage), + #keyPath(PermissionModel.recallMessage), + #keyPath(PermissionModel.atAnyMember), + #keyPath(PermissionModel.atAllMember)] + + let messagePermissionDic = [#keyPath(PermissionModel.sendMessage):localizable("qchat_send_message"), + #keyPath(PermissionModel.deleteOtherMemberMessage):localizable("qchat_delete_message"), + #keyPath(PermissionModel.recallMessage):localizable("qchat_recall_message"), + #keyPath(PermissionModel.atAnyMember):localizable("qchat_at_any"), + #keyPath(PermissionModel.atAllMember):localizable("qchat_at_all")] + + @objc var sendMessage = ChatPermissionType.sendMsg.rawValue + + @objc var deleteOtherMemberMessage = ChatPermissionType.deleteOtherMsg.rawValue + + @objc var recallMessage = ChatPermissionType.revokeMsg.rawValue + + @objc var atAnyMember = ChatPermissionType.remindOther.rawValue + + @objc var atAllMember = ChatPermissionType.remindAll.rawValue + */ + + let memberPermission = [#keyPath(PermissionModel.modifyOwnServer), + #keyPath(PermissionModel.modifyOthersServer), + #keyPath(PermissionModel.inviteMember), + #keyPath(PermissionModel.kickout), + #keyPath(PermissionModel.managerBlackAndWhite)] + + let memberPermissionDic = [ + #keyPath(PermissionModel.modifyOwnServer): localizable("qchat_modify_own_server"), + #keyPath(PermissionModel.modifyOthersServer): localizable("qchat_modify_other_server"), + #keyPath(PermissionModel.inviteMember): localizable("qchat_invite_member"), + #keyPath(PermissionModel.kickout): localizable("qchat_kickout_member"), + #keyPath(PermissionModel.managerBlackAndWhite): localizable("qchat_manager_channel_list"), + ] + + @objc var modifyOwnServer = ChatPermissionType.manageServer.rawValue + + @objc var modifyOthersServer = ChatPermissionType.modifyOthersInfoInServer.rawValue + + @objc var inviteMember = ChatPermissionType.inviteToServer.rawValue + + @objc var kickout = ChatPermissionType.kickOthersInServer.rawValue + + @objc var managerBlackAndWhite = ChatPermissionType.manageBlackWhiteList.rawValue + + var changeMap = [String: Bool]() + + override init() { + super.init() + } + + func getChangePermission() -> [ChatPermissionType: Bool] { + var permissions = [ChatPermissionType: Bool]() + changeMap.forEach { (key: String, v: Bool) in + if let permissionKey = value(forKey: key) as? String, + let type = ChatPermissionType(rawValue: permissionKey) { + permissions[type] = v + } } - - + return permissions + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Server/Model/SettingModel.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Server/Model/SettingModel.swift index e662b600..828e2268 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Server/Model/SettingModel.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Server/Model/SettingModel.swift @@ -1,10 +1,12 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation class SettingModel { - var title: String? - var cornerType: CornerType = CornerType.bottomLeft.union(CornerType.bottomRight).union(CornerType.topLeft).union(CornerType.topRight) + var title: String? + var cornerType: CornerType = CornerType.bottomLeft.union(CornerType.bottomRight) + .union(CornerType.topLeft).union(CornerType.topRight) } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Server/Model/UserInfo.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Server/Model/UserInfo.swift index 3dd7a6c9..4cc9c297 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Server/Model/UserInfo.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Server/Model/UserInfo.swift @@ -1,49 +1,49 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NEKitCoreIM class UserInfo { - var nickName: String? - var cornerType: CornerType = .none - var color = UIColor.colorWithNumber(number: 0) - var select = false - var accid: String? - var serverId: UInt64? - var createTime: Double? - - - var serverMember: ServerMemeber? - - var roleMember: RoleMember? - - init(){} - - init(_ member: ServerMemeber){ - serverMember = member - if let n = member.nick, n.count > 0 { - nickName = n - }else { - nickName = member.accid - } - accid = member.accid - serverId = member.serverId - createTime = member.createTime - color = UIColor.colorWithString(string: accid) + var nickName: String? + var cornerType: CornerType = .none + var color = UIColor.colorWithNumber(number: 0) + var select = false + var accid: String? + var serverId: UInt64? + var createTime: Double? + + var serverMember: ServerMemeber? + + var roleMember: RoleMember? + + init() {} + + init(_ member: ServerMemeber) { + serverMember = member + if let n = member.nick, n.count > 0 { + nickName = n + } else { + nickName = member.accid } - - init(_ member: RoleMember){ - roleMember = member - if let n = member.nick, n.count > 0 { - nickName = n - }else { - nickName = member.accid - } - accid = member.accid - serverId = member.serverId - createTime = member.createTime - color = UIColor.colorWithString(string: accid) + accid = member.accid + serverId = member.serverId + createTime = member.createTime + color = UIColor.colorWithString(string: accid) + } + + init(_ member: RoleMember) { + roleMember = member + if let n = member.nick, n.count > 0 { + nickName = n + } else { + nickName = member.accid } + accid = member.accid + serverId = member.serverId + createTime = member.createTime + color = UIColor.colorWithString(string: accid) + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatDestructiveCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatDestructiveCell.swift index 2fedf8e3..38a54c94 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatDestructiveCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatDestructiveCell.swift @@ -1,47 +1,46 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class QChatDestructiveCell: QChatCornerCell { - - lazy var redTextLabel: UILabel = { - let label = UILabel() - label.textColor = .ne_redText - label.font = DefaultTextFont(16) - label.translatesAutoresizingMaskIntoConstraints = false - return label - }() - - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } - - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) - - // Configure the view for the selected state - setupUI() - } - - func setupUI(){ - contentView.backgroundColor = .clear - backgroundColor = .clear - contentView.addSubview(redTextLabel) - NSLayoutConstraint.activate([ - redTextLabel.centerXAnchor.constraint(equalTo: contentView.centerXAnchor), - redTextLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor) - ]) - } - - func changeDisableTextColor(){ - redTextLabel.textColor = .ne_disableRedText - } - - func changeEnableTextColor(){ - redTextLabel.textColor = .ne_redText - } + lazy var redTextLabel: UILabel = { + let label = UILabel() + label.textColor = .ne_redText + label.font = DefaultTextFont(16) + label.translatesAutoresizingMaskIntoConstraints = false + return label + }() + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + setupUI() + } + + func setupUI() { + contentView.backgroundColor = .clear + backgroundColor = .clear + contentView.addSubview(redTextLabel) + NSLayoutConstraint.activate([ + redTextLabel.centerXAnchor.constraint(equalTo: contentView.centerXAnchor), + redTextLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + ]) + } + + func changeDisableTextColor() { + redTextLabel.textColor = .ne_disableRedText + } + + func changeEnableTextColor() { + redTextLabel.textColor = .ne_redText + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatHeaderCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatHeaderCell.swift index de408644..61ea3353 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatHeaderCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatHeaderCell.swift @@ -1,70 +1,69 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class QChatHeaderCell: QChatCornerCell { - - var user: UserInfo? { - didSet { - if let name = user?.nickName { - headerView.setTitle(name) - nameLabel.text = name - }else if let aid = user?.accid { - headerView.setTitle(aid) - nameLabel.text = aid - } - headerView.backgroundColor = user?.color - } + var user: UserInfo? { + didSet { + if let name = user?.nickName { + headerView.setTitle(name) + nameLabel.text = name + } else if let aid = user?.accid { + headerView.setTitle(aid) + nameLabel.text = aid + } + headerView.backgroundColor = user?.color } - - let headerView: NEUserHeaderView = { - let header = NEUserHeaderView(frame: .zero) - header.titleLabel.font = DefaultTextFont(20) - header.titleLabel.textColor = UIColor.white - header.layer.cornerRadius = 30 - header.translatesAutoresizingMaskIntoConstraints = false + } + + let headerView: NEUserHeaderView = { + let header = NEUserHeaderView(frame: .zero) + header.titleLabel.font = DefaultTextFont(20) + header.titleLabel.textColor = UIColor.white + header.layer.cornerRadius = 30 + header.translatesAutoresizingMaskIntoConstraints = false // header.backgroundColor = UIColor.randomColor() - - return header - }() - - let nameLabel: UILabel = { - let label = UILabel() - label.textColor = .ne_darkText - label.font = DefaultTextFont(16) - label.translatesAutoresizingMaskIntoConstraints = false - return label - }() - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } + return header + }() - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) + let nameLabel: UILabel = { + let label = UILabel() + label.textColor = .ne_darkText + label.font = DefaultTextFont(16) + label.translatesAutoresizingMaskIntoConstraints = false + return label + }() - // Configure the view for the selected state - setupUI() - } - - func setupUI(){ - contentView.addSubview(headerView) - NSLayoutConstraint.activate([ - headerView.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 36), - headerView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - headerView.widthAnchor.constraint(equalToConstant: 60), - headerView.heightAnchor.constraint(equalToConstant: 60) - ]) - - contentView.addSubview(nameLabel) - NSLayoutConstraint.activate([ - nameLabel.leftAnchor.constraint(equalTo: headerView.rightAnchor, constant: 16), - nameLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -36), - nameLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor) - ]) - } + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + setupUI() + } + + func setupUI() { + contentView.addSubview(headerView) + NSLayoutConstraint.activate([ + headerView.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 36), + headerView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + headerView.widthAnchor.constraint(equalToConstant: 60), + headerView.heightAnchor.constraint(equalToConstant: 60), + ]) + contentView.addSubview(nameLabel) + NSLayoutConstraint.activate([ + nameLabel.leftAnchor.constraint(equalTo: headerView.rightAnchor, constant: 16), + nameLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -36), + nameLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + ]) + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatIdGroupCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatIdGroupCell.swift index a5e60ae9..e0415913 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatIdGroupCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatIdGroupCell.swift @@ -1,138 +1,138 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class QChatIdGroupCell: QChatBaseCell { - - lazy var headImage: UIImageView = { - let image = UIImageView() - image.translatesAutoresizingMaskIntoConstraints = false - image.image = UIImage.ne_imageNamed(name: "id_group_header") - return image - }() - - lazy var titleLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.textColor = UIColor.ne_darkText - label.font = DefaultTextFont(14) - label.textAlignment = .left - return label - }() - - lazy var subTitleLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.textColor = UIColor.ne_greyText - label.font = DefaultTextFont(12) - label.textAlignment = .left - return label - }() - - lazy var countHeadImage: UIImageView = { - let image = UIImageView() - image.translatesAutoresizingMaskIntoConstraints = false - image.image = UIImage.ne_imageNamed(name: "count_header") - return image - }() - - lazy var tailImage: UIImageView = { - let image = UIImageView() - image.translatesAutoresizingMaskIntoConstraints = false - image.highlightedImage = UIImage.ne_imageNamed(name: "lock") - image.image = UIImage.ne_imageNamed(name: "arrowRight") - return image - }() - - lazy var dividerLine: UIView = { - let line = UIView() - line.backgroundColor = .ne_greyLine - line.translatesAutoresizingMaskIntoConstraints = false - return line - }() - - var leftSpace: NSLayoutConstraint? - - var titleLeftSpace: NSLayoutConstraint? - - var countHeadWidth: NSLayoutConstraint? - - var headWidth: NSLayoutConstraint? - - var headHeight: NSLayoutConstraint? - - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } - - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) - - // Configure the view for the selected state - setupUI() - } - - func setupUI(){ - - contentView.addSubview(headImage) - leftSpace = headImage.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 24) - leftSpace?.isActive = true - - headWidth = headImage.widthAnchor.constraint(equalToConstant: 29) - headWidth?.isActive = true - headHeight = headImage.heightAnchor.constraint(equalToConstant: 33) - headHeight?.isActive = true - - NSLayoutConstraint.activate([ - headImage.centerYAnchor.constraint(equalTo: contentView.centerYAnchor) - ]) - - contentView.addSubview(tailImage) - NSLayoutConstraint.activate([ - tailImage.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - tailImage.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), - ]) - - contentView.addSubview(titleLabel) - titleLeftSpace = titleLabel.leftAnchor.constraint(equalTo: headImage.rightAnchor, constant: 15.5) - titleLeftSpace?.isActive = true - NSLayoutConstraint.activate([ - titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 13.0), - titleLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -36.0) - ]) - - contentView.addSubview(countHeadImage) - countHeadWidth = countHeadImage.widthAnchor.constraint(equalToConstant: 10) - countHeadWidth?.isActive = true - NSLayoutConstraint.activate([ - countHeadImage.leftAnchor.constraint(equalTo: titleLabel.leftAnchor), - countHeadImage.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 6), - countHeadImage.heightAnchor.constraint(equalToConstant: 10) - ]) - - contentView.addSubview(subTitleLabel) - NSLayoutConstraint.activate([ - subTitleLabel.leftAnchor.constraint(equalTo: countHeadImage.rightAnchor, constant: 6), - subTitleLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 4), - subTitleLabel.rightAnchor.constraint(equalTo: titleLabel.rightAnchor) - ]) - - contentView.addSubview(dividerLine) - NSLayoutConstraint.activate([ - dividerLine.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20), - dividerLine.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), - dividerLine.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), - dividerLine.heightAnchor.constraint(equalToConstant: 1) - ]) - - } - - func configure(_ model: IdGroupModel){ - titleLabel.text = model.idName - subTitleLabel.text = model.subTitle - } + lazy var headImage: UIImageView = { + let image = UIImageView() + image.translatesAutoresizingMaskIntoConstraints = false + image.image = UIImage.ne_imageNamed(name: "id_group_header") + return image + }() + lazy var titleLabel: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.textColor = UIColor.ne_darkText + label.font = DefaultTextFont(14) + label.textAlignment = .left + return label + }() + + lazy var subTitleLabel: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.textColor = UIColor.ne_greyText + label.font = DefaultTextFont(12) + label.textAlignment = .left + return label + }() + + lazy var countHeadImage: UIImageView = { + let image = UIImageView() + image.translatesAutoresizingMaskIntoConstraints = false + image.image = UIImage.ne_imageNamed(name: "count_header") + return image + }() + + lazy var tailImage: UIImageView = { + let image = UIImageView() + image.translatesAutoresizingMaskIntoConstraints = false + image.highlightedImage = UIImage.ne_imageNamed(name: "lock") + image.image = UIImage.ne_imageNamed(name: "arrowRight") + return image + }() + + lazy var dividerLine: UIView = { + let line = UIView() + line.backgroundColor = .ne_greyLine + line.translatesAutoresizingMaskIntoConstraints = false + return line + }() + + var leftSpace: NSLayoutConstraint? + + var titleLeftSpace: NSLayoutConstraint? + + var countHeadWidth: NSLayoutConstraint? + + var headWidth: NSLayoutConstraint? + + var headHeight: NSLayoutConstraint? + + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + setupUI() + } + + func setupUI() { + contentView.addSubview(headImage) + leftSpace = headImage.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 24) + leftSpace?.isActive = true + + headWidth = headImage.widthAnchor.constraint(equalToConstant: 29) + headWidth?.isActive = true + headHeight = headImage.heightAnchor.constraint(equalToConstant: 33) + headHeight?.isActive = true + + NSLayoutConstraint.activate([ + headImage.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + ]) + + contentView.addSubview(tailImage) + NSLayoutConstraint.activate([ + tailImage.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + tailImage.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), + ]) + + contentView.addSubview(titleLabel) + titleLeftSpace = titleLabel.leftAnchor.constraint( + equalTo: headImage.rightAnchor, + constant: 15.5 + ) + titleLeftSpace?.isActive = true + NSLayoutConstraint.activate([ + titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 13.0), + titleLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -36.0), + ]) + + contentView.addSubview(countHeadImage) + countHeadWidth = countHeadImage.widthAnchor.constraint(equalToConstant: 10) + countHeadWidth?.isActive = true + NSLayoutConstraint.activate([ + countHeadImage.leftAnchor.constraint(equalTo: titleLabel.leftAnchor), + countHeadImage.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 6), + countHeadImage.heightAnchor.constraint(equalToConstant: 10), + ]) + + contentView.addSubview(subTitleLabel) + NSLayoutConstraint.activate([ + subTitleLabel.leftAnchor.constraint(equalTo: countHeadImage.rightAnchor, constant: 6), + subTitleLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 4), + subTitleLabel.rightAnchor.constraint(equalTo: titleLabel.rightAnchor), + ]) + + contentView.addSubview(dividerLine) + NSLayoutConstraint.activate([ + dividerLine.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20), + dividerLine.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), + dividerLine.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + dividerLine.heightAnchor.constraint(equalToConstant: 1), + ]) + } + + func configure(_ model: IdGroupModel) { + titleLabel.text = model.idName + subTitleLabel.text = model.subTitle + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatIdGroupMemberCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatIdGroupMemberCell.swift index 790fc6b6..dce6e98d 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatIdGroupMemberCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatIdGroupMemberCell.swift @@ -1,96 +1,98 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class QChatIdGroupMemberCell: QChatCornerCell { - - lazy var headView: NEUserHeaderView = { - let view = NEUserHeaderView(frame: .zero) - view.titleLabel.textColor = .white - view.titleLabel.font = DefaultTextFont(11) - view.translatesAutoresizingMaskIntoConstraints = false - view.clipsToBounds = true - view.layer.cornerRadius = 16.0 - return view - }() - - lazy var tailorImage: UIImageView = { - let image = UIImageView() - image.image = UIImage.ne_imageNamed(name: "delete") - image.translatesAutoresizingMaskIntoConstraints = false - return image - }() - - lazy var nameLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.textColor = .ne_darkText - label.font = DefaultTextFont(14) - return label - }() - - var user: UserInfo? { - didSet { - if let name = user?.nickName { - headView.setTitle(name) - } - headView.backgroundColor = user?.color - nameLabel.text = user?.nickName - } - } - - var leftSpace: NSLayoutConstraint? - - var rightSpace: NSLayoutConstraint? - - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } + lazy var headView: NEUserHeaderView = { + let view = NEUserHeaderView(frame: .zero) + view.titleLabel.textColor = .white + view.titleLabel.font = DefaultTextFont(11) + view.translatesAutoresizingMaskIntoConstraints = false + view.clipsToBounds = true + view.layer.cornerRadius = 16.0 + return view + }() - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) + lazy var tailorImage: UIImageView = { + let image = UIImageView() + image.image = UIImage.ne_imageNamed(name: "delete") + image.translatesAutoresizingMaskIntoConstraints = false + return image + }() - // Configure the view for the selected state - } - - public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - setupUI() - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - } - - func setupUI(){ - contentView.addSubview(headView) - - leftSpace = headView.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 36) - leftSpace?.isActive = true - NSLayoutConstraint.activate([ - headView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - headView.widthAnchor.constraint(equalToConstant: 32), - headView.heightAnchor.constraint(equalToConstant: 32) - ]) - - contentView.addSubview(tailorImage) - rightSpace = tailorImage.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -36) - rightSpace?.isActive = true - NSLayoutConstraint.activate([ - tailorImage.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - tailorImage.widthAnchor.constraint(equalToConstant: 16.0), - tailorImage.heightAnchor.constraint(equalToConstant: 16.0) - ]) - - contentView.addSubview(nameLabel) - NSLayoutConstraint.activate([ - nameLabel.leftAnchor.constraint(equalTo: headView.rightAnchor, constant: 12), - nameLabel.rightAnchor.constraint(equalTo: tailorImage.leftAnchor, constant: -10), - nameLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor) - ]) + lazy var nameLabel: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.textColor = .ne_darkText + label.font = DefaultTextFont(14) + return label + }() + + var user: UserInfo? { + didSet { + if let name = user?.nickName { + headView.setTitle(name) + } + headView.backgroundColor = user?.color + nameLabel.text = user?.nickName } + } + + var leftSpace: NSLayoutConstraint? + + var rightSpace: NSLayoutConstraint? + + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + } + + override public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + setupUI() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + func setupUI() { + contentView.addSubview(headView) + + leftSpace = headView.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 36) + leftSpace?.isActive = true + NSLayoutConstraint.activate([ + headView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + headView.widthAnchor.constraint(equalToConstant: 32), + headView.heightAnchor.constraint(equalToConstant: 32), + ]) + + contentView.addSubview(tailorImage) + rightSpace = tailorImage.rightAnchor.constraint( + equalTo: contentView.rightAnchor, + constant: -36 + ) + rightSpace?.isActive = true + NSLayoutConstraint.activate([ + tailorImage.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + tailorImage.widthAnchor.constraint(equalToConstant: 16.0), + tailorImage.heightAnchor.constraint(equalToConstant: 16.0), + ]) + contentView.addSubview(nameLabel) + NSLayoutConstraint.activate([ + nameLabel.leftAnchor.constraint(equalTo: headView.rightAnchor, constant: 12), + nameLabel.rightAnchor.constraint(equalTo: tailorImage.leftAnchor, constant: -10), + nameLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + ]) + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatIdGroupSelectCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatIdGroupSelectCell.swift index 5db147eb..86514861 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatIdGroupSelectCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatIdGroupSelectCell.swift @@ -1,66 +1,67 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class QChatIdGroupSelectCell: QChatCornerCell { - - var group: IdGroupModel? { - didSet { - if let select = group?.isSelect { - tailImage.isHighlighted = select - } - nameLabel.text = group?.idName - if let type = group?.cornerType { - cornerType = type - } - } + var group: IdGroupModel? { + didSet { + if let select = group?.isSelect { + tailImage.isHighlighted = select + } + nameLabel.text = group?.idName + if let type = group?.cornerType { + cornerType = type + } } - - let tailImage: UIImageView = { - let image = UIImageView() - image.image = UIImage.ne_imageNamed(name: "unselect") - image.highlightedImage = UIImage.ne_imageNamed(name: "select") - image.translatesAutoresizingMaskIntoConstraints = false - image.isHidden = true - return image - }() - - let nameLabel: UILabel = { - let label = UILabel() - label.textColor = .ne_darkText - label.font = DefaultTextFont(14) - label.translatesAutoresizingMaskIntoConstraints = false - return label - }() + } - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } + let tailImage: UIImageView = { + let image = UIImageView() + image.image = UIImage.ne_imageNamed(name: "unselect") + image.highlightedImage = UIImage.ne_imageNamed(name: "select") + image.translatesAutoresizingMaskIntoConstraints = false + image.isHidden = true + return image + }() - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) + let nameLabel: UILabel = { + let label = UILabel() + label.textColor = .ne_darkText + label.font = DefaultTextFont(14) + label.translatesAutoresizingMaskIntoConstraints = false + return label + }() - // Configure the view for the selected state - setupUI() - } - - func setupUI(){ - contentView.addSubview(tailImage) - NSLayoutConstraint.activate([ - tailImage.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -36), - tailImage.centerYAnchor.constraint(equalTo: contentView.centerYAnchor) - ]) - - contentView.addSubview(nameLabel) - NSLayoutConstraint.activate([ - nameLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 36), - nameLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -(36 + 23)), - nameLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor) - ]) - - } + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + setupUI() + } + + func setupUI() { + contentView.addSubview(tailImage) + NSLayoutConstraint.activate([ + tailImage.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -36), + tailImage.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + ]) + contentView.addSubview(nameLabel) + NSLayoutConstraint.activate([ + nameLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 36), + nameLabel.rightAnchor.constraint( + equalTo: contentView.rightAnchor, + constant: -(36 + 23) + ), + nameLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + ]) + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatIdGroupSortButtonCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatIdGroupSortButtonCell.swift index 4cc281b4..7629ddc4 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatIdGroupSortButtonCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatIdGroupSortButtonCell.swift @@ -1,80 +1,78 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class QChatIdGroupSortButtonCell: QChatBaseCell { - - lazy var titleLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.textColor = .ne_greyText - label.font = DefaultTextFont(12) - return label - }() - - lazy var sortImage: UIImageView = { - let image = UIImageView() - image.translatesAutoresizingMaskIntoConstraints = false - image.image = UIImage.ne_imageNamed(name: "id_group_sort") - return image - }() - - lazy var sortBtn: ExpandButton = { - let btn = ExpandButton() - btn.translatesAutoresizingMaskIntoConstraints = false - return btn - }() - - lazy var sortLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.font = DefaultTextFont(12) - label.textColor = .ne_blueText - label.text = localizable("qchat_sort") - return label - }() + lazy var titleLabel: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.textColor = .ne_greyText + label.font = DefaultTextFont(12) + return label + }() - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } + lazy var sortImage: UIImageView = { + let image = UIImageView() + image.translatesAutoresizingMaskIntoConstraints = false + image.image = UIImage.ne_imageNamed(name: "id_group_sort") + return image + }() - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) + lazy var sortBtn: ExpandButton = { + let btn = ExpandButton() + btn.translatesAutoresizingMaskIntoConstraints = false + return btn + }() - // Configure the view for the selected state - setupUI() - } - - func setupUI(){ - contentView.addSubview(titleLabel) - NSLayoutConstraint.activate([ - titleLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), - titleLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20) - ]) - - contentView.addSubview(sortLabel) - NSLayoutConstraint.activate([ - sortLabel.centerYAnchor.constraint(equalTo:titleLabel.centerYAnchor), - sortLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20) - ]) - - contentView.addSubview(sortImage) - NSLayoutConstraint.activate([ - sortImage.centerYAnchor.constraint(equalTo: sortLabel.centerYAnchor), - sortImage.rightAnchor.constraint(equalTo: sortLabel.leftAnchor, constant: -6) - ]) - - contentView.addSubview(sortBtn) - NSLayoutConstraint.activate([ - sortBtn.rightAnchor.constraint(equalTo: contentView.rightAnchor), - sortBtn.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), - sortBtn.topAnchor.constraint(equalTo: contentView.topAnchor), - sortBtn.leftAnchor.constraint(equalTo: sortImage.leftAnchor, constant: -10) - ]) - - } + lazy var sortLabel: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.font = DefaultTextFont(12) + label.textColor = .ne_blueText + label.text = localizable("qchat_sort") + return label + }() + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + setupUI() + } + + func setupUI() { + contentView.addSubview(titleLabel) + NSLayoutConstraint.activate([ + titleLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + titleLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20), + ]) + + contentView.addSubview(sortLabel) + NSLayoutConstraint.activate([ + sortLabel.centerYAnchor.constraint(equalTo: titleLabel.centerYAnchor), + sortLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), + ]) + + contentView.addSubview(sortImage) + NSLayoutConstraint.activate([ + sortImage.centerYAnchor.constraint(equalTo: sortLabel.centerYAnchor), + sortImage.rightAnchor.constraint(equalTo: sortLabel.leftAnchor, constant: -6), + ]) + + contentView.addSubview(sortBtn) + NSLayoutConstraint.activate([ + sortBtn.rightAnchor.constraint(equalTo: contentView.rightAnchor), + sortBtn.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + sortBtn.topAnchor.constraint(equalTo: contentView.topAnchor), + sortBtn.leftAnchor.constraint(equalTo: sortImage.leftAnchor, constant: -10), + ]) + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatIdGroupTopCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatIdGroupTopCell.swift index 3a797772..3e0c3bb2 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatIdGroupTopCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatIdGroupTopCell.swift @@ -1,31 +1,30 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class QChatIdGroupTopCell: QChatIdGroupCell { + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) - - // Configure the view for the selected state - } - - override func setupUI() { - super.setupUI() - leftSpace?.constant = 20.0 - headImage.image = UIImage.ne_imageNamed(name: "member_header") - titleLeftSpace?.constant = 12.0 - countHeadWidth?.constant = 0 - countHeadImage.isHidden = true - headWidth?.constant = 36.0 - headHeight?.constant = 36.0 - } + // Configure the view for the selected state + } + override func setupUI() { + super.setupUI() + leftSpace?.constant = 20.0 + headImage.image = UIImage.ne_imageNamed(name: "member_header") + titleLeftSpace?.constant = 12.0 + countHeadWidth?.constant = 0 + countHeadImage.isHidden = true + headWidth?.constant = 36.0 + headHeight?.constant = 36.0 + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatMemberManagerCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatMemberManagerCell.swift index 24807a2c..ec712139 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatMemberManagerCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatMemberManagerCell.swift @@ -1,27 +1,26 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class QChatMemberManagerCell: QChatIdGroupMemberCell { + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) - - // Configure the view for the selected state - } - - override func setupUI() { - super.setupUI() - contentView.backgroundColor = .white - leftSpace?.constant = 20 - rightSpace?.constant = -20 - } + // Configure the view for the selected state + } + override func setupUI() { + super.setupUI() + contentView.backgroundColor = .white + leftSpace?.constant = 20 + rightSpace?.constant = -20 + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatPlainTextArrowCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatPlainTextArrowCell.swift index a63fc486..c5cd2e17 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatPlainTextArrowCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatPlainTextArrowCell.swift @@ -1,28 +1,27 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class QChatPlainTextArrowCell: QChatTextArrowCell { + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) - - // Configure the view for the selected state - setupUI() - } - - func setupUI(){ - contentView.backgroundColor = .white - titleLeftMargin?.constant = 20 - detailRightMargin?.constant = -42 - rightImageMargin?.constant = -20 - } + // Configure the view for the selected state + setupUI() + } + func setupUI() { + contentView.backgroundColor = .white + titleLeftMargin?.constant = 20 + detailRightMargin?.constant = -42 + rightImageMargin?.constant = -20 + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatSelectedCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatSelectedCell.swift index 1ab21cfe..434af2e1 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatSelectedCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatSelectedCell.swift @@ -1,94 +1,92 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class QChatSelectedCell: QChatBaseCell { - - var user: UserInfo? { - didSet { - if let name = user?.nickName { - headerView.setTitle(name) - } - titleLabel.text = user?.nickName - headerView.backgroundColor = user?.color - if let value = user?.select { - checkBox.isHighlighted = value - } - - } + var user: UserInfo? { + didSet { + if let name = user?.nickName { + headerView.setTitle(name) + } + titleLabel.text = user?.nickName + headerView.backgroundColor = user?.color + if let value = user?.select { + checkBox.isHighlighted = value + } } - - public lazy var titleLabel: UILabel = { - let label = UILabel() - label.textAlignment = .left - label.translatesAutoresizingMaskIntoConstraints = false - label.font = UIFont.systemFont(ofSize: 14.0) - label.textColor = .ne_darkText - return label - }() - - let headerView: NEUserHeaderView = { - let header = NEUserHeaderView(frame: .zero) - header.titleLabel.font = DefaultTextFont(14) - header.titleLabel.textColor = UIColor.white - header.layer.cornerRadius = 18 - header.translatesAutoresizingMaskIntoConstraints = false - return header - }() - - let checkBox: UIImageView = { - let image = UIImageView() - image.translatesAutoresizingMaskIntoConstraints = false - image.image = UIImage.ne_imageNamed(name: "unselect") - image.highlightedImage = UIImage.ne_imageNamed(name: "select") - return image - }() + } - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } + public lazy var titleLabel: UILabel = { + let label = UILabel() + label.textAlignment = .left + label.translatesAutoresizingMaskIntoConstraints = false + label.font = UIFont.systemFont(ofSize: 14.0) + label.textColor = .ne_darkText + return label + }() - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) + let headerView: NEUserHeaderView = { + let header = NEUserHeaderView(frame: .zero) + header.titleLabel.font = DefaultTextFont(14) + header.titleLabel.textColor = UIColor.white + header.layer.cornerRadius = 18 + header.translatesAutoresizingMaskIntoConstraints = false + return header + }() - // Configure the view for the selected state - setupUI() - } - - func setupUI(){ - contentView.addSubview(checkBox) - NSLayoutConstraint.activate([ - checkBox.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20), - checkBox.centerYAnchor.constraint(equalTo: contentView.centerYAnchor) - ]) - - contentView.addSubview(headerView) - NSLayoutConstraint.activate([ - headerView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - headerView.leftAnchor.constraint(equalTo: checkBox.rightAnchor, constant: 12), - headerView.widthAnchor.constraint(equalToConstant: 36), - headerView.heightAnchor.constraint(equalToConstant: 36) - ]) - - contentView.addSubview(titleLabel) - NSLayoutConstraint.activate([ - titleLabel.leftAnchor.constraint(equalTo:contentView.leftAnchor, constant: 98), - titleLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -35), - titleLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor) - ]) - } - - func setSelect(){ - user?.select = true - checkBox.isHighlighted = true - } - - func setUnselect(){ - user?.select = false - checkBox.isHighlighted = false - } + let checkBox: UIImageView = { + let image = UIImageView() + image.translatesAutoresizingMaskIntoConstraints = false + image.image = UIImage.ne_imageNamed(name: "unselect") + image.highlightedImage = UIImage.ne_imageNamed(name: "select") + return image + }() + + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + setupUI() + } + + func setupUI() { + contentView.addSubview(checkBox) + NSLayoutConstraint.activate([ + checkBox.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20), + checkBox.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + ]) + + contentView.addSubview(headerView) + NSLayoutConstraint.activate([ + headerView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + headerView.leftAnchor.constraint(equalTo: checkBox.rightAnchor, constant: 12), + headerView.widthAnchor.constraint(equalToConstant: 36), + headerView.heightAnchor.constraint(equalToConstant: 36), + ]) + + contentView.addSubview(titleLabel) + NSLayoutConstraint.activate([ + titleLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 98), + titleLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -35), + titleLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + ]) + } + + func setSelect() { + user?.select = true + checkBox.isHighlighted = true + } + func setUnselect() { + user?.select = false + checkBox.isHighlighted = false + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatSortCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatSortCell.swift index cb9e6e6c..5b7d7fd5 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatSortCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatSortCell.swift @@ -1,41 +1,39 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class QChatSortCell: QChatIdGroupCell { - - lazy var dotImage: UIImageView = { - let image = UIImageView() - image.translatesAutoresizingMaskIntoConstraints = false - image.image = UIImage.ne_imageNamed(name: "dot_image") - image.highlightedImage = UIImage.ne_imageNamed(name: "dot_image_disable") - return image - }() + lazy var dotImage: UIImageView = { + let image = UIImageView() + image.translatesAutoresizingMaskIntoConstraints = false + image.image = UIImage.ne_imageNamed(name: "dot_image") + image.highlightedImage = UIImage.ne_imageNamed(name: "dot_image_disable") + return image + }() - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) - // Configure the view for the selected state - } - - override func setupUI() { - super.setupUI() + // Configure the view for the selected state + } + + override func setupUI() { + super.setupUI() // self.leftSpace?.constant = 72 - tailImage.image = UIImage.ne_imageNamed(name: "delete") - tailImage.highlightedImage = UIImage.ne_imageNamed(name: "lock") + tailImage.image = UIImage.ne_imageNamed(name: "delete") + tailImage.highlightedImage = UIImage.ne_imageNamed(name: "lock") // contentView.addSubview(dotImage) // NSLayoutConstraint.activate([ // dotImage.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 31), // dotImage.centerYAnchor.constraint(equalTo: contentView.centerYAnchor) // ]) - - } - + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatSwitchCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatSwitchCell.swift index e138c76b..c639e2dc 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatSwitchCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatSwitchCell.swift @@ -1,93 +1,88 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit protocol QChatSwitchCellDelegate: AnyObject { - func didChangeSwitchValue(_ cell: QChatSwitchCell) + func didChangeSwitchValue(_ cell: QChatSwitchCell) } class QChatSwitchCell: QChatCornerCell { - - weak var delegate: QChatSwitchCellDelegate? - - var qSwitch: UISwitch = { - let q = UISwitch() - q.translatesAutoresizingMaskIntoConstraints = false - q.onTintColor = .ne_blueText - return q - }() - - var permissionLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.textColor = .ne_darkText - label.font = DefaultTextFont(16) - return label - }() - - var model: PermissionCellModel? { - didSet { - permissionLabel.text = model?.showName - - if let type = model?.cornerType { - cornerType = type - } - if let value = model?.hasPermission { - qSwitch.isOn = value - } - } - } + weak var delegate: QChatSwitchCellDelegate? - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } + var qSwitch: UISwitch = { + let q = UISwitch() + q.translatesAutoresizingMaskIntoConstraints = false + q.onTintColor = .ne_blueText + return q + }() - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) + var permissionLabel: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.textColor = .ne_darkText + label.font = DefaultTextFont(16) + return label + }() - // Configure the view for the selected state - setupUI() - } - - func setupUI(){ - - contentView.addSubview(qSwitch) - NSLayoutConstraint.activate([ - qSwitch.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - qSwitch.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -36) - ]) - qSwitch.addTarget(self, action: #selector(valueChange(_:)), for: .valueChanged) - - contentView.addSubview(permissionLabel) - NSLayoutConstraint.activate([ - permissionLabel.leftAnchor.constraint(equalTo:contentView.leftAnchor, constant: 36), - permissionLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -95), - permissionLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor) - ]) - - } - - @objc func valueChange(_ s: UISwitch){ - model?.hasPermission = s.isOn - delegate?.didChangeSwitchValue(self) - /* - if s.isOn == true { - if let key = model?.permissionKey { - print("add key : ", key) - model?.permission?.changeMap[key] = true - } - }else { - if let key = model?.permissionKey { - print("rm key : ", key) - model?.permission?.changeMap[key] = false - } - }*/ - print("change maps : ", model?.permission?.changeMap as Any) + var model: PermissionCellModel? { + didSet { + permissionLabel.text = model?.showName + + if let type = model?.cornerType { + cornerType = type + } + if let value = model?.hasPermission { + qSwitch.isOn = value + } } - - + } + + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + setupUI() + } + + func setupUI() { + contentView.addSubview(qSwitch) + NSLayoutConstraint.activate([ + qSwitch.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + qSwitch.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -36), + ]) + qSwitch.addTarget(self, action: #selector(valueChange(_:)), for: .valueChanged) + + contentView.addSubview(permissionLabel) + NSLayoutConstraint.activate([ + permissionLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 36), + permissionLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -95), + permissionLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + ]) + } + @objc func valueChange(_ s: UISwitch) { + model?.hasPermission = s.isOn + delegate?.didChangeSwitchValue(self) + /* + if s.isOn == true { + if let key = model?.permissionKey { + print("add key : ", key) + model?.permission?.changeMap[key] = true + } + }else { + if let key = model?.permissionKey { + print("rm key : ", key) + model?.permission?.changeMap[key] = false + } + }*/ + print("change maps : ", model?.permission?.changeMap as Any) + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatUserUnCheckCell.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatUserUnCheckCell.swift index 137cbbe0..223f91c0 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatUserUnCheckCell.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Server/View/QChatUserUnCheckCell.swift @@ -1,56 +1,57 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class QChatUserUnCheckCell: QChatBaseCollectionViewCell { - - public var avatarImage = UIView() - public var nameTailLabel = UILabel() + public var avatarImage = UIView() + public var nameTailLabel = UILabel() - override init(frame: CGRect) { - super.init(frame: frame) - setupUI() - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - } - - func setupUI(){ - contentView.addSubview(avatarImage) - avatarImage.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - avatarImage.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - avatarImage.centerXAnchor.constraint(equalTo: contentView.centerXAnchor), - avatarImage.widthAnchor.constraint(equalToConstant: 36), - avatarImage.heightAnchor.constraint(equalToConstant: 36) - ]) - avatarImage.layer.cornerRadius = 18.0 - avatarImage.clipsToBounds = true - - avatarImage.addSubview(nameTailLabel) - nameTailLabel.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - nameTailLabel.centerXAnchor.constraint(equalTo: avatarImage.centerXAnchor), - nameTailLabel.centerYAnchor.constraint(equalTo: avatarImage.centerYAnchor), - nameTailLabel.leftAnchor.constraint(equalTo: avatarImage.leftAnchor, constant: 1), - nameTailLabel.rightAnchor.constraint(equalTo: avatarImage.rightAnchor, constant: -1) - ]) - self.nameTailLabel.font = UIFont.systemFont(ofSize: 16.0) - self.nameTailLabel.textAlignment = .center - self.nameTailLabel.textColor = .white - - contentView.backgroundColor = .clear - } - - func configure(_ model: UserInfo){ - avatarImage.backgroundColor = model.color - // title - guard let name = model.nickName else { - return - } - self.nameTailLabel.text = name.count > 2 ? String(name[name.index(name.endIndex, offsetBy: -2)...]) : name + override init(frame: CGRect) { + super.init(frame: frame) + setupUI() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + func setupUI() { + contentView.addSubview(avatarImage) + avatarImage.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + avatarImage.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + avatarImage.centerXAnchor.constraint(equalTo: contentView.centerXAnchor), + avatarImage.widthAnchor.constraint(equalToConstant: 36), + avatarImage.heightAnchor.constraint(equalToConstant: 36), + ]) + avatarImage.layer.cornerRadius = 18.0 + avatarImage.clipsToBounds = true + + avatarImage.addSubview(nameTailLabel) + nameTailLabel.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + nameTailLabel.centerXAnchor.constraint(equalTo: avatarImage.centerXAnchor), + nameTailLabel.centerYAnchor.constraint(equalTo: avatarImage.centerYAnchor), + nameTailLabel.leftAnchor.constraint(equalTo: avatarImage.leftAnchor, constant: 1), + nameTailLabel.rightAnchor.constraint(equalTo: avatarImage.rightAnchor, constant: -1), + ]) + nameTailLabel.font = UIFont.systemFont(ofSize: 16.0) + nameTailLabel.textAlignment = .center + nameTailLabel.textColor = .white + + contentView.backgroundColor = .clear + } + + func configure(_ model: UserInfo) { + avatarImage.backgroundColor = model.color + // title + guard let name = model.nickName else { + return } + nameTailLabel.text = name + .count > 2 ? String(name[name.index(name.endIndex, offsetBy: -2)...]) : name + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewController/QChatCreateGroupViewController.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewController/QChatCreateGroupViewController.swift index 09a74d4f..fbf41547 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewController/QChatCreateGroupViewController.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewController/QChatCreateGroupViewController.swift @@ -1,275 +1,272 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCoreIM typealias CreateCompletion = () -> Void -public class QChatCreateGroupViewController: NEBaseTableViewController, QChatMemberSelectControllerDelegate { - - let viewModel = CreateGroupViewModel() - - var serverId: UInt64? - - var serverName = "" - - var completion: CreateCompletion? - - public override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - viewModel.delegate = self - setupUI() - } - - func setupUI(){ - addRightAction(localizable("create"), #selector(createClick), self) - title = localizable("qchat_create_new_id_group") - setupTable() - tableView.delegate = self - tableView.backgroundColor = .ne_backcolor - - tableView.dataSource = self - tableView.register(QChatTextArrowCell.self, forCellReuseIdentifier: "\(QChatTextArrowCell.self)") - tableView.register(QChatTextEditCell.self, forCellReuseIdentifier: "\(QChatTextEditCell.self)") - tableView.register(QChatUnfoldCell.self, forCellReuseIdentifier: "\(QChatUnfoldCell.self)") - tableView.register(QChatIdGroupMemberCell.self, forCellReuseIdentifier: "\(QChatIdGroupMemberCell.self)") - } - +public class QChatCreateGroupViewController: NEBaseTableViewController, + QChatMemberSelectControllerDelegate,UITableViewDataSource, UITableViewDelegate,ViewModelDelegate, QChatTextEditCellDelegate { + let viewModel = CreateGroupViewModel() - /* - // MARK: - Navigation + var serverId: UInt64? - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. - } - */ + var serverName = "" -} + var completion: CreateCompletion? -extension QChatCreateGroupViewController { - - @objc func createClick(){ - - if serverName.count <= 0 { - view.makeToast(localizable("qchat_please_input_role_name")) - return - } - var param = ServerRoleParam() - param.serverId = serverId - param.type = .custom - param.name = serverName - weak var weakSelf = self - print("create role param : ", param) - - viewModel.repo.createRole(param) { error, role in - print("create role : ", error as Any, role) - if let err = error { - weakSelf?.dataDidError(err) - }else { - if let rid = role.roleId, let addMemebers = weakSelf?.viewModel.allUsers, addMemebers.count > 0 { - weakSelf?.addMember(rid) - }else { - if let block = weakSelf?.completion { - block() - } - weakSelf?.navigationController?.popViewController(animated: true) - } - } - } - } - - func addMember(_ roleId: UInt64){ - weak var weakSelf = self - if viewModel.allUsers.count > 0 { - var accids = [String]() - viewModel.allUsers.forEach { user in - if let accid = user.serverMember?.accid { - accids.append(accid) - } - } - var param = AddServerRoleMemberParam() - param.accountArray = accids - param.serverId = serverId - param.roleId = roleId - viewModel.repo.addRoleMember(param) { error, sAccids, fAccids in - if let err = error { - weakSelf?.showToast(err.localizedDescription) - } - if let block = weakSelf?.completion { - block() - } - weakSelf?.navigationController?.popViewController(animated: true) + override public func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + viewModel.delegate = self + setupUI() + } + + func setupUI() { + addRightAction(localizable("create"), #selector(createClick), self) + title = localizable("qchat_create_new_id_group") + setupTable() + tableView.delegate = self + tableView.backgroundColor = .ne_backcolor + + tableView.dataSource = self + tableView.register( + QChatTextArrowCell.self, + forCellReuseIdentifier: "\(QChatTextArrowCell.self)" + ) + tableView.register( + QChatTextEditCell.self, + forCellReuseIdentifier: "\(QChatTextEditCell.self)" + ) + tableView.register(QChatUnfoldCell.self, forCellReuseIdentifier: "\(QChatUnfoldCell.self)") + tableView.register( + QChatIdGroupMemberCell.self, + forCellReuseIdentifier: "\(QChatIdGroupMemberCell.self)" + ) + } + + //MAKR: objc 方法 + @objc func createClick() { + if serverName.count <= 0 { + view.makeToast(localizable("qchat_please_input_role_name")) + return + } + var param = ServerRoleParam() + param.serverId = serverId + param.type = .custom + param.name = serverName + weak var weakSelf = self + print("create role param : ", param) + + viewModel.repo.createRole(param) { error, role in + print("create role : ", error as Any, role) + if let err = error { + weakSelf?.dataDidError(err) + } else { + if let rid = role.roleId, let addMemebers = weakSelf?.viewModel.allUsers, + addMemebers.count > 0 { + weakSelf?.addMember(rid) + } else { + if let block = weakSelf?.completion { + block() } + weakSelf?.navigationController?.popViewController(animated: true) + } } + } } -} -extension QChatCreateGroupViewController: UITextFieldDelegate { - -} - -extension QChatCreateGroupViewController: UITableViewDataSource, UITableViewDelegate, ViewModelDelegate, QChatTextEditCellDelegate { - - public func filterMembers(accid: [String]?, _ filterMembers: @escaping ([String]?) -> ()) { - - var dic = [String : String]() + func addMember(_ roleId: UInt64) { + weak var weakSelf = self + if viewModel.allUsers.count > 0 { + var accids = [String]() viewModel.allUsers.forEach { user in - if let aid = user.accid { - dic[aid] = aid - } + if let accid = user.serverMember?.accid { + accids.append(accid) + } } - var retArray = [String]() - accid?.forEach({ aid in - if dic[aid] != nil { - retArray.append(aid) - } - }) - filterMembers(retArray) - -// filterMembers(accid) + var param = AddServerRoleMemberParam() + param.accountArray = accids + param.serverId = serverId + param.roleId = roleId + viewModel.repo.addRoleMember(param) { error, sAccids, fAccids in + if let err = error { + weakSelf?.showToast(err.localizedDescription) + } + if let block = weakSelf?.completion { + block() + } + weakSelf?.navigationController?.popViewController(animated: true) + } + } } - - func textFieldDidChangeSelection(cell: QChatTextEditCell, _ textField: UITextField) { - print("text change: ", textField.text as Any) - // +//MARK : + public func filterMembers(accid: [String]?, _ filterMembers: @escaping ([String]?) -> Void) { + var dic = [String: String]() + viewModel.allUsers.forEach { user in + if let aid = user.accid { + dic[aid] = aid + } + } + var retArray = [String]() + accid?.forEach { aid in + if dic[aid] != nil { + retArray.append(aid) + } + } + filterMembers(retArray) + + // filterMembers(accid) } - + + func textDidChange(_ textField: UITextField) { - if let text = textField.text { - serverName = text - } - print("text change: ", textField.text as Any) + if let text = textField.text { + serverName = text + } + print("text change: ", textField.text as Any) } - - + public func dataDidError(_ error: Error) { - UIApplication.shared.keyWindow?.endEditing(true) - view.makeToast(error.localizedDescription) + UIApplication.shared.keyWindow?.endEditing(true) + view.makeToast(error.localizedDescription) } - + public func dataDidChange() { - tableView.reloadData() + tableView.reloadData() } - + public func numberOfSections(in tableView: UITableView) -> Int { - let count = 3 -// if viewModel.limitUsers.count < viewModel.allUsers.count { -// count = count + 1 -// } - return count + let count = 3 + // if viewModel.limitUsers.count < viewModel.allUsers.count { + // count = count + 1 + // } + return count } - + public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - if section == 0 || section == 1 { - return 1 - }else if section == 2 { - return viewModel.allUsers.count - }else if section == 3 { - return 0 - } + if section == 0 || section == 1 { + return 1 + } else if section == 2 { + return viewModel.allUsers.count + } else if section == 3 { return 0 + } + return 0 } - - public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - - if indexPath.section == 0 { - let cell: QChatTextEditCell = tableView.dequeueReusableCell(withIdentifier: "\(QChatTextEditCell.self)", for: indexPath) as! QChatTextEditCell - cell.textFied.placeholder = localizable("qchat_please_input_role_name") - cell.delegate = self - cell.limit = 20 - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight).union(CornerType.topLeft).union(CornerType.topRight) - return cell - }else if indexPath.section == 1 { - let cell: QChatTextArrowCell = tableView.dequeueReusableCell(withIdentifier: "\(QChatTextArrowCell.self)", for: indexPath) as! QChatTextArrowCell - cell.titleLabel.text = localizable("qchat_add_member") - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight).union(CornerType.topLeft).union(CornerType.topRight) - return cell - }else if indexPath.section == 2 { - let cell: QChatIdGroupMemberCell = tableView.dequeueReusableCell(withIdentifier: "\(QChatIdGroupMemberCell.self)", for: indexPath) as! QChatIdGroupMemberCell - let user = viewModel.allUsers[indexPath.row] - cell.cornerType = user.cornerType - cell.user = user - return cell - }else if indexPath.section == 3 { - let cell: QChatUnfoldCell = tableView.dequeueReusableCell(withIdentifier: "\(QChatUnfoldCell.self)", for: indexPath) as! QChatUnfoldCell - cell.contentLabel.text = "更多(共\(viewModel.allUsers.count))人" - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) - return cell - } - return UITableViewCell() + + public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + if indexPath.section == 0 { + let cell: QChatTextEditCell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatTextEditCell.self)", + for: indexPath + ) as! QChatTextEditCell + cell.textFied.placeholder = localizable("qchat_please_input_role_name") + cell.delegate = self + cell.limit = 20 + cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) + .union(CornerType.topLeft).union(CornerType.topRight) + return cell + } else if indexPath.section == 1 { + let cell: QChatTextArrowCell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatTextArrowCell.self)", + for: indexPath + ) as! QChatTextArrowCell + cell.titleLabel.text = localizable("qchat_add_member") + cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) + .union(CornerType.topLeft).union(CornerType.topRight) + return cell + } else if indexPath.section == 2 { + let cell: QChatIdGroupMemberCell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatIdGroupMemberCell.self)", + for: indexPath + ) as! QChatIdGroupMemberCell + let user = viewModel.allUsers[indexPath.row] + cell.cornerType = user.cornerType + cell.user = user + return cell + } else if indexPath.section == 3 { + let cell: QChatUnfoldCell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatUnfoldCell.self)", + for: indexPath + ) as! QChatUnfoldCell + cell.contentLabel.text = "更多(共\(viewModel.allUsers.count))人" + cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) + return cell + } + return UITableViewCell() } - + public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - if indexPath.section == 1 { - - let memberSelect = QChatMemberSelectController() - memberSelect.serverId = serverId - memberSelect.delegate = self -// memberSelect.selectType = .ServerMember - weak var weakSelf = self - memberSelect.completion = { datas in - if datas.count > 0 { - weakSelf?.viewModel.addMembers(datas) - } - } - navigationController?.pushViewController(memberSelect, animated: true) - - }else if indexPath.section == 2 { - // 编辑成员临时入口 - -// let user = viewModel.limitUsers[indexPath.row] -// let editMember = QChatEditMemberViewController() -// editMember.user = user -// navigationController?.pushViewController(editMember, animated: true) - - viewModel.removeData(indexPath.row) - }else if indexPath.section == 3 { - viewModel.loadAllData() - tableView.reloadData() + if indexPath.section == 1 { + let memberSelect = QChatMemberSelectController() + memberSelect.serverId = serverId + memberSelect.delegate = self + // memberSelect.selectType = .ServerMember + weak var weakSelf = self + memberSelect.completion = { datas in + if datas.count > 0 { + weakSelf?.viewModel.addMembers(datas) + } } + navigationController?.pushViewController(memberSelect, animated: true) + + } else if indexPath.section == 2 { + // 编辑成员临时入口 + + // let user = viewModel.limitUsers[indexPath.row] + // let editMember = QChatEditMemberViewController() + // editMember.user = user + // navigationController?.pushViewController(editMember, animated: true) + + viewModel.removeData(indexPath.row) + } else if indexPath.section == 3 { + viewModel.loadAllData() + tableView.reloadData() + } } - - public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - return 50 + + public func tableView(_ tableView: UITableView, + heightForRowAt indexPath: IndexPath) -> CGFloat { + 50 } - - public func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { - if section == 0 || section == 1 { - return 40.0 - }else if section == 2 { - return 16 - } - return 0 + + public func tableView(_ tableView: UITableView, + heightForHeaderInSection section: Int) -> CGFloat { + if section == 0 || section == 1 { + return 40.0 + } else if section == 2 { + return 16 + } + return 0 } - - public func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { - - let header = QChatHeaderView() - if section == 0 { - header.titleLabel.text = localizable("qchat_group_name") - return header - } - - if section == 1 { - header.titleLabel.text = localizable("qchat_manager_member") - return header - } - - if section == 2 { - let space = UIView() - space.backgroundColor = .clear - return space - } - - return nil + + public func tableView(_ tableView: UITableView, + viewForHeaderInSection section: Int) -> UIView? { + let header = QChatHeaderView() + if section == 0 { + header.titleLabel.text = localizable("qchat_group_name") + return header + } + + if section == 1 { + header.titleLabel.text = localizable("qchat_manager_member") + return header + } + + if section == 2 { + let space = UIView() + space.backgroundColor = .clear + return space + } + + return nil } - } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewController/QChatEditMemberViewController.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewController/QChatEditMemberViewController.swift index 42a9063b..251cdaf9 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewController/QChatEditMemberViewController.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewController/QChatEditMemberViewController.swift @@ -1,362 +1,383 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCore import NEKitCoreIM -//typealias EditMemberCompletion = (_ member: ServerMemeber) -> Void +// typealias EditMemberCompletion = (_ member: ServerMemeber) -> Void typealias EditMemberChange = () -> Void typealias EditMemberDelete = () -> Void -public class QChatEditMemberViewController: NEBaseTableViewController { - - var user: UserInfo? - var editAble = false - var showAll = false - let viewModel = EditMemberViewModel() - +public class QChatEditMemberViewController: NEBaseTableViewController,UITableViewDataSource, UITableViewDelegate,ViewModelDelegate, QChatTextEditCellDelegate { + var user: UserInfo? + var editAble = false + var showAll = false + let viewModel = EditMemberViewModel() + // var completion: EditMemberCompletion? - var changeCompletion: EditMemberChange? - var deleteCompletion: EditMemberDelete? - var nickName = "" - - var didChange = false - - public override func viewDidLoad() { - super.viewDidLoad() + var changeCompletion: EditMemberChange? + var deleteCompletion: EditMemberDelete? + var nickName = "" - // Do any additional setup after loading the view. - if let nick = user?.nickName { - nickName = nick - } + var didChange = false + + override public func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + if let nick = user?.nickName { + nickName = nick + } // else if let acid = user?.accid { // nickName = acid // } - viewModel.delegate = self - viewModel.getData(user?.serverId, user?.accid) - setupUI() + viewModel.delegate = self + viewModel.getData(user?.serverId, user?.accid) + setupUI() + } + + func setupUI() { + setupTable() + if let name = user?.nickName { + title = name } - - func setupUI(){ - setupTable() - if let name = user?.nickName { - self.title = name - } - addRightAction(localizable("qchat_edit"), #selector(rightBtnClick(_:)), self) - tableView.register(QChatTextEditCell.self, forCellReuseIdentifier: "\(QChatTextEditCell.self)") - tableView.register(QChatHeaderCell.self, forCellReuseIdentifier: "\(QChatHeaderCell.self)") - tableView.register(QChatDestructiveCell.self, forCellReuseIdentifier: "\(QChatDestructiveCell.self)") - tableView.register(QChatIdGroupSelectCell.self, forCellReuseIdentifier: "\(QChatIdGroupSelectCell.self)") - tableView.register(QChatUnfoldCell.self, forCellReuseIdentifier: "\(QChatUnfoldCell.self)") - tableView.dataSource = self - tableView.delegate = self - tableView.backgroundColor = .ne_backcolor - + addRightAction(localizable("qchat_edit"), #selector(rightBtnClick(_:)), self) + tableView.register( + QChatTextEditCell.self, + forCellReuseIdentifier: "\(QChatTextEditCell.self)" + ) + tableView.register(QChatHeaderCell.self, forCellReuseIdentifier: "\(QChatHeaderCell.self)") + tableView.register( + QChatDestructiveCell.self, + forCellReuseIdentifier: "\(QChatDestructiveCell.self)" + ) + tableView.register( + QChatIdGroupSelectCell.self, + forCellReuseIdentifier: "\(QChatIdGroupSelectCell.self)" + ) + tableView.register(QChatUnfoldCell.self, forCellReuseIdentifier: "\(QChatUnfoldCell.self)") + tableView.dataSource = self + tableView.delegate = self + tableView.backgroundColor = .ne_backcolor + // let image = UIImage.ne_imageNamed(name: "backArrow")?.withRenderingMode(.alwaysOriginal) // self.navigationItem.leftBarButtonItem = UIBarButtonItem(image: image, style: .plain, target: self, action: #selector(back)) - addLeftAction(UIImage.ne_imageNamed(name: "backArrow"), #selector(back), self) - } - - @objc func back(){ - - didChangeRole() - navigationController?.popViewController(animated: true) - } - + addLeftAction(UIImage.ne_imageNamed(name: "backArrow"), #selector(back), self) + } - /* - // MARK: - Navigation + @objc func back() { + didChangeRole() + navigationController?.popViewController(animated: true) + } - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. - } - */ + /* + // MARK: - Navigation -} + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ + //MARK: objc 方法 + @objc func rightBtnClick(_ btn: ExpandButton) { + if btn.isSelected == true { + print("to save") + if nickName.count <= 0 { + showToast("昵称不能为空") + return + } -extension QChatEditMemberViewController: UITableViewDataSource, UITableViewDelegate, ViewModelDelegate, QChatTextEditCellDelegate { - - func textDidChange(_ textField: UITextField) { - print("edit mebmer name change : ",textField.text as Any) - if let text = textField.text { - nickName = text + guard let accid = user?.accid else { + showToast("accid 不能为空") + return + } + + weak var weakSelf = self + + if IMKitLoginManager.instance.isMySelf(accid) == true { + viewModel.updateMyMember(user?.serverMember?.serverId, nickName) { error, member in + if let err = error { + weakSelf?.showToast(err.localizedDescription) + } else { + weakSelf?.navigationController?.popViewController(animated: true) + if let block = weakSelf?.changeCompletion { + block() + } + } + } + } else { + viewModel + .updateMember(user?.serverMember?.serverId, nickName, + user?.accid) { error, member in + if let err = error { + weakSelf?.showToast(err.localizedDescription) + } else { + weakSelf?.navigationController?.popViewController(animated: true) + if let block = weakSelf?.changeCompletion { + block() + } + } + } } + + } else { + btn.isSelected = true + editAble = true + btn.setTitle(localizable("qchat_save"), for: .normal) + viewModel.showServerData() + } } + //MARK: UITableViewDataSource, UITableViewDelegate,ViewModelDelegate, QChatTextEditCellDelegate + func textDidChange(_ textField: UITextField) { + print("edit mebmer name change : ", textField.text as Any) + if let text = textField.text { + nickName = text + } + } + public func dataDidChange() { - tableView.reloadData() + tableView.reloadData() } - + public func dataDidError(_ error: Error) { - showToast(error.localizedDescription) + showToast(error.localizedDescription) } - + public func numberOfSections(in tableView: UITableView) -> Int { - return 5 + 5 } - + public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - if section == 0 || section == 1 { - return 1 - }else if section == 2 { - return showAll ? viewModel.allIdGroups.count : viewModel.limitIdGroups.count - }else if section == 3 { - if viewModel.limitIdGroups.count < viewModel.allIdGroups.count { - return 1 - } - }else if section == 4 { - return 1 + if section == 0 || section == 1 { + return 1 + } else if section == 2 { + return showAll ? viewModel.allIdGroups.count : viewModel.limitIdGroups.count + } else if section == 3 { + if viewModel.limitIdGroups.count < viewModel.allIdGroups.count { + return 1 } - return 0 + } else if section == 4 { + return 1 + } + return 0 } - - public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - - if indexPath.section == 0 { - let cell: QChatHeaderCell = tableView.dequeueReusableCell(withIdentifier: "\(QChatHeaderCell.self)", for: indexPath) as! QChatHeaderCell - cell.cornerType = CornerType.topLeft.union(CornerType.topRight).union(CornerType.bottomLeft).union(CornerType.bottomRight) - cell.user = user - return cell - }else if indexPath.section == 1 { - let cell: QChatTextEditCell = tableView.dequeueReusableCell(withIdentifier: "\(QChatTextEditCell.self)", for: indexPath) as! QChatTextEditCell - cell.cornerType = CornerType.topLeft.union(CornerType.topRight).union(CornerType.bottomLeft).union(CornerType.bottomRight) - cell.delegate = self - cell.editTotast = "请点击编辑后修改昵称" - cell.canEdit = editAble - if nickName.count > 0 { - cell.textFied.text = nickName - }else { - cell.textFied.text = nil - } - cell.textFied.placeholder = localizable("qcaht_edit_nickname") - return cell - }else if indexPath.section == 2 { - let cell: QChatIdGroupSelectCell = tableView.dequeueReusableCell(withIdentifier: "\(QChatIdGroupSelectCell.self)", for: indexPath) as! QChatIdGroupSelectCell - let group = showAll ? viewModel.allIdGroups[indexPath.row] : viewModel.limitIdGroups[indexPath.row] - cell.tailImage.isHidden = !editAble - if let type = group.role?.type, type == .everyone { - cell.tailImage.isHidden = true - } - let exist = viewModel.checkoutCurrentUserRole(group.role?.roleId) - print("checkoutCurrentUserRole name : \(group.idName ?? "") exist : \(exist)") - group.isSelect = exist - cell.group = group - return cell - }else if indexPath.section == 3 { - let cell: QChatUnfoldCell = tableView.dequeueReusableCell(withIdentifier: "\(QChatUnfoldCell.self)", for: indexPath) as! QChatUnfoldCell - cell.contentLabel.text = showAll ? "收起(共\(viewModel.allIdGroups.count)个)" : "更多(共\(viewModel.allIdGroups.count)个)" - if showAll { - cell.changeToArrowUp() - }else { - cell.changeToArrowDown() - } - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) - return cell - }else if indexPath.section == 4 { - let cell: QChatDestructiveCell = tableView.dequeueReusableCell(withIdentifier: "\(QChatDestructiveCell.self)", for: indexPath) as! QChatDestructiveCell - if indexPath.row == 0 { - cell.cornerType = CornerType.topLeft.union(CornerType.topRight).union(CornerType.bottomLeft).union(CornerType.bottomRight) - cell.redTextLabel.text = "\(localizable("qchat_kick_out")) \(user?.nickName ?? "")" - if getKickDisable() { - cell.changeDisableTextColor() - } - }else if indexPath.row == 1 { - cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) - cell.redTextLabel.text = "\(localizable("qchat_prohibit")) \(user?.nickName ?? "")" - cell.changeEnableTextColor() - } - return cell + + public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + if indexPath.section == 0 { + let cell: QChatHeaderCell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatHeaderCell.self)", + for: indexPath + ) as! QChatHeaderCell + cell.cornerType = CornerType.topLeft.union(CornerType.topRight) + .union(CornerType.bottomLeft).union(CornerType.bottomRight) + cell.user = user + return cell + } else if indexPath.section == 1 { + let cell: QChatTextEditCell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatTextEditCell.self)", + for: indexPath + ) as! QChatTextEditCell + cell.cornerType = CornerType.topLeft.union(CornerType.topRight) + .union(CornerType.bottomLeft).union(CornerType.bottomRight) + cell.delegate = self + cell.editTotast = "请点击编辑后修改昵称" + cell.canEdit = editAble + if nickName.count > 0 { + cell.textFied.text = nickName + } else { + cell.textFied.text = nil } - - return UITableViewCell() - } - - public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - if indexPath.section == 0 { - return 92 + cell.textFied.placeholder = localizable("qcaht_edit_nickname") + return cell + } else if indexPath.section == 2 { + let cell: QChatIdGroupSelectCell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatIdGroupSelectCell.self)", + for: indexPath + ) as! QChatIdGroupSelectCell + let group = showAll ? viewModel.allIdGroups[indexPath.row] : viewModel + .limitIdGroups[indexPath.row] + cell.tailImage.isHidden = !editAble + if let type = group.role?.type, type == .everyone { + cell.tailImage.isHidden = true } - return 50 - } - - public func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { - let header = QChatHeaderView() - if section == 1 { - header.titleLabel.text = localizable("qchat_nickname") - return header + let exist = viewModel.checkoutCurrentUserRole(group.role?.roleId) + print("checkoutCurrentUserRole name : \(group.idName ?? "") exist : \(exist)") + group.isSelect = exist + cell.group = group + return cell + } else if indexPath.section == 3 { + let cell: QChatUnfoldCell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatUnfoldCell.self)", + for: indexPath + ) as! QChatUnfoldCell + cell.contentLabel + .text = showAll ? "收起(共\(viewModel.allIdGroups.count)个)" : + "更多(共\(viewModel.allIdGroups.count)个)" + if showAll { + cell.changeToArrowUp() + } else { + cell.changeToArrowDown() } - - if section == 2 && viewModel.allIdGroups.count > 0 { - header.titleLabel.text = localizable("qchat_id_group") - return header + cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) + return cell + } else if indexPath.section == 4 { + let cell: QChatDestructiveCell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatDestructiveCell.self)", + for: indexPath + ) as! QChatDestructiveCell + if indexPath.row == 0 { + cell.cornerType = CornerType.topLeft.union(CornerType.topRight) + .union(CornerType.bottomLeft).union(CornerType.bottomRight) + cell.redTextLabel.text = "\(localizable("qchat_kick_out")) \(user?.nickName ?? "")" + if getKickDisable() { + cell.changeDisableTextColor() + } + } else if indexPath.row == 1 { + cell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) + cell.redTextLabel.text = "\(localizable("qchat_prohibit")) \(user?.nickName ?? "")" + cell.changeEnableTextColor() } - return nil + return cell + } + + return UITableViewCell() } - - public func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { - - if section == 0 { - return 22 + + public func tableView(_ tableView: UITableView, + heightForRowAt indexPath: IndexPath) -> CGFloat { + if indexPath.section == 0 { + return 92 + } + return 50 + } + + public func tableView(_ tableView: UITableView, + viewForHeaderInSection section: Int) -> UIView? { + let header = QChatHeaderView() + if section == 1 { + header.titleLabel.text = localizable("qchat_nickname") + return header + } + + if section == 2, viewModel.allIdGroups.count > 0 { + header.titleLabel.text = localizable("qchat_id_group") + return header + } + return nil + } + + public func tableView(_ tableView: UITableView, + heightForHeaderInSection section: Int) -> CGFloat { + if section == 0 { + return 22 + } + + if section == 1 { + return 38 + } + + if section == 2, viewModel.allIdGroups.count > 0 { + return 38 + } + + if section == 4 { + return 20 + } + return 0 + } + + public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + if indexPath.section == 1 { + // showToast("请点击编辑后修改昵称") + } else if indexPath.section == 2 { + if editAble == false { + return } - - if section == 1{ - return 38 + + let group = showAll == true ? viewModel.allIdGroups[indexPath.row] : viewModel + .limitIdGroups[indexPath.row] + + if let type = group.role?.type, type == .everyone { + return } - - if section == 2 && viewModel.allIdGroups.count > 0 { - return 38 + let select = viewModel.checkoutCurrentUserRole(group.role?.roleId) + weak var weakSelf = self + if select == false { + view.makeToastActivity(.center) + viewModel.addMembers(user?.accid, user?.serverId, group.role?.roleId) { + weakSelf?.view.hideToastActivity() + weakSelf?.didChange = true + } + } else { + view.makeToastActivity(.center) + viewModel.remove(user?.accid, user?.serverId, group.role?.roleId) { + weakSelf?.view.hideToastActivity() + weakSelf?.didChange = true + } } - - if section == 4 { - return 20 + } else if indexPath.section == 3 { + showAll = !showAll + tableView.reloadData() + } else if indexPath.section == 4 { + weak var weakSelf = self + if getKickDisable() == true { + return } - return 0 - } - - public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - - if indexPath.section == 1 { - //showToast("请点击编辑后修改昵称") - }else if indexPath.section == 2 { - if editAble == false { - return - } - - let group = showAll == true ? viewModel.allIdGroups[indexPath.row] : viewModel.limitIdGroups[indexPath.row] - - if let type = group.role?.type, type == .everyone { - return - } - let select = viewModel.checkoutCurrentUserRole(group.role?.roleId) - weak var weakSelf = self - if select == false { - view.makeToastActivity(.center) - viewModel.addMembers(user?.accid, user?.serverId, group.role?.roleId) { - weakSelf?.view.hideToastActivity() - weakSelf?.didChange = true - } - }else { - view.makeToastActivity(.center) - viewModel.remove(user?.accid, user?.serverId, group.role?.roleId) { - weakSelf?.view.hideToastActivity() - weakSelf?.didChange = true - } - } - }else if indexPath.section == 3 { - showAll = !showAll - tableView.reloadData() - }else if indexPath.section == 4 { - weak var weakSelf = self - if getKickDisable() == true { - return - } - showAlert(message: "确定踢出当前成员?") { - weakSelf?.kickOutMember() - } + showAlert(message: "确定踢出当前成员?") { + weakSelf?.kickOutMember() } + } } - - func didChangeRole(){ - if didChange == true { - if let block = changeCompletion { - block() - } + + func didChangeRole() { + if didChange == true { + if let block = changeCompletion { + block() } + } } - + func getKickDisable() -> Bool { - if let accid = user?.serverMember?.accid { -// if CoreKitEngine.instance.imAccid == accid { -// return true -// } - - if IMKitLoginManager.instance.imAccid == accid { - return true - } - if let type = user?.serverMember?.type, type == .owner { - return true - } + if let accid = user?.serverMember?.accid { + // if CoreKitEngine.instance.imAccid == accid { + // return true + // } + + if IMKitLoginManager.instance.imAccid == accid { + return true + } + if let type = user?.serverMember?.type, type == .owner { + return true } - return false + } + return false } - - func kickOutMember(){ - view.makeToastActivity(.center) - weak var weakSelf = self - viewModel.kickoutMember(user?.serverId, user?.accid) { error in - weakSelf?.view.hideToastActivity() - if let err = error { - weakSelf?.showToast(err.localizedDescription) - }else { - if let block = weakSelf?.deleteCompletion { - block() - } - weakSelf?.navigationController?.popViewController(animated: true) - } + + func kickOutMember() { + view.makeToastActivity(.center) + weak var weakSelf = self + viewModel.kickoutMember(user?.serverId, user?.accid) { error in + weakSelf?.view.hideToastActivity() + if let err = error { + weakSelf?.showToast(err.localizedDescription) + } else { + if let block = weakSelf?.deleteCompletion { + block() + } + weakSelf?.navigationController?.popViewController(animated: true) } + } } -// func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { -// if section == 1 || section == 2 { -// -// } -// } - - } -extension QChatEditMemberViewController { - - @objc func rightBtnClick(_ btn: ExpandButton){ - if btn.isSelected == true { - print("to save") - if nickName.count <= 0 { - showToast("昵称不能为空") - return - } - guard let accid = user?.accid else { - showToast("accid 不能为空") - return - } - - weak var weakSelf = self - - if IMKitLoginManager.instance.isMySelf(accid) == true { - viewModel.updateMyMember(user?.serverMember?.serverId, nickName ) { error, member in - if let err = error { - weakSelf?.showToast(err.localizedDescription) - }else { - weakSelf?.navigationController?.popViewController(animated: true) - if let block = weakSelf?.changeCompletion { - block() - } - } - } - }else { - viewModel.updateMember(user?.serverMember?.serverId, nickName , user?.accid) { error, member in - if let err = error { - weakSelf?.showToast(err.localizedDescription) - }else { - weakSelf?.navigationController?.popViewController(animated: true) - if let block = weakSelf?.changeCompletion { - block() - } - } - } - } - - }else { - btn.isSelected = true - editAble = true - btn.setTitle(localizable("qchat_save"), for: .normal) - viewModel.showServerData() - } - } -} diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewController/QChatIdGroupSortController.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewController/QChatIdGroupSortController.swift index 9ac7bd03..725abc19 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewController/QChatIdGroupSortController.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewController/QChatIdGroupSortController.swift @@ -1,205 +1,205 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCoreIM -//typealias SortCompletion = (_ array: NSMutableArray) -> Void +// typealias SortCompletion = (_ array: NSMutableArray) -> Void typealias SortChange = () -> Void -public class QChatIdGroupSortController: NEBaseTableViewController { - - var serverId: UInt64? - - var isOwer = false - - let viewmodel = IdGroupSortViewModel() - +public class QChatIdGroupSortController: NEBaseTableViewController,UITableViewDelegate, UITableViewDataSource,ViewModelDelegate { + var serverId: UInt64? + + var isOwer = false + + let viewmodel = IdGroupSortViewModel() + // let dataArray = NSMutableArray() - - var didDelete = false - - var completion: SortChange? - - public override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - let image = UIImage.ne_imageNamed(name: "backArrow")?.withRenderingMode(.alwaysOriginal) - self.navigationItem.leftBarButtonItem = UIBarButtonItem(image: image, style: .plain, target: self, action: #selector(back)) - viewmodel.isOwner = isOwer - viewmodel.delegate = self - viewmodel.getData(serverId) - setupUI() - } - - func setupUI(){ - setupTable() - self.title = localizable("qchat_id_group_sort") - addRightAction(localizable("qchat_save"), #selector(saveSort), self) - tableView.backgroundColor = .white - tableView.delegate = self - tableView.dataSource = self - tableView.register(QChatSortCell.self, forCellReuseIdentifier: "\(QChatSortCell.self)") - tableView.isEditing = true - tableView.allowsSelectionDuringEditing = true - } - - @objc func saveSort(){ - view.makeToastActivity(.center) - weak var weakSelf = self - viewmodel.saveSort(serverId) { - weakSelf?.view.hideToastActivity() - if let block = weakSelf?.completion { - block() - } - print("save success") - weakSelf?.navigationController?.popViewController(animated: true) - } - } - - @objc func back(){ - - if didDelete == true, let block = completion { - block() - } - navigationController?.popViewController(animated: true) - } - - /* - // MARK: - Navigation + var didDelete = false - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. - } - */ + var completion: SortChange? -} + override public func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + let image = UIImage.ne_imageNamed(name: "backArrow")?.withRenderingMode(.alwaysOriginal) + navigationItem.leftBarButtonItem = UIBarButtonItem( + image: image, + style: .plain, + target: self, + action: #selector(back) + ) + viewmodel.isOwner = isOwer + viewmodel.delegate = self + viewmodel.getData(serverId) + setupUI() + } + + func setupUI() { + setupTable() + title = localizable("qchat_id_group_sort") + addRightAction(localizable("qchat_save"), #selector(saveSort), self) + tableView.backgroundColor = .white + tableView.delegate = self + tableView.dataSource = self + tableView.register(QChatSortCell.self, forCellReuseIdentifier: "\(QChatSortCell.self)") + tableView.isEditing = true + tableView.allowsSelectionDuringEditing = true + } + + @objc func saveSort() { + view.makeToastActivity(.center) + weak var weakSelf = self + viewmodel.saveSort(serverId) { + weakSelf?.view.hideToastActivity() + if let block = weakSelf?.completion { + block() + } + print("save success") + weakSelf?.navigationController?.popViewController(animated: true) + } + } -extension QChatIdGroupSortController: UITableViewDelegate, UITableViewDataSource, ViewModelDelegate { - + @objc func back() { + if didDelete == true, let block = completion { + block() + } + navigationController?.popViewController(animated: true) + } + + //MARK: UITableViewDelegate, UITableViewDataSource, ViewModelDelegate public func dataDidChange() { - tableView.reloadData() + tableView.reloadData() } - + public func dataDidError(_ error: Error) { - view.hideToastActivity() - showToast(error.localizedDescription) + view.hideToastActivity() + showToast(error.localizedDescription) } - + public func numberOfSections(in tableView: UITableView) -> Int { - return 1 + 1 } - + public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { -// if section == 0 { -// return viewmodel.lockData.count -// }else if section == 1 { -// return viewmodel.datas.count -// } - return viewmodel.datas.count + // if section == 0 { + // return viewmodel.lockData.count + // }else if section == 1 { + // return viewmodel.datas.count + // } + viewmodel.datas.count } - - public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - - let cell: QChatSortCell = tableView.dequeueReusableCell(withIdentifier: "\(QChatSortCell.self)", for: indexPath) as! QChatSortCell -// if indexPath.section == 0 { -// let model = viewmodel.lockData[indexPath.row] -// cell.configure(model) -// cell.tailImage.isHighlighted = true -// }else if indexPath.section == 1 { -// if let model = viewmodel.datas[indexPath.row] as? IdGroupModel { -// cell.configure(model) -// cell.tailImage.isHighlighted = !model.hasPermission -// } -// } - if let model = viewmodel.datas[indexPath.row] as? IdGroupModel { - cell.configure(model) - cell.tailImage.isHighlighted = !model.hasPermission - } - - return cell + + public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell: QChatSortCell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatSortCell.self)", + for: indexPath + ) as! QChatSortCell + // if indexPath.section == 0 { + // let model = viewmodel.lockData[indexPath.row] + // cell.configure(model) + // cell.tailImage.isHighlighted = true + // }else if indexPath.section == 1 { + // if let model = viewmodel.datas[indexPath.row] as? IdGroupModel { + // cell.configure(model) + // cell.tailImage.isHighlighted = !model.hasPermission + // } + // } + if let model = viewmodel.datas[indexPath.row] as? IdGroupModel { + cell.configure(model) + cell.tailImage.isHighlighted = !model.hasPermission + } + + return cell } - - public func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) { - print("source :" , sourceIndexPath.row , " destionation :" ,destinationIndexPath.row) - - if sourceIndexPath.row > destinationIndexPath.row { - let src_model = viewmodel.datas.object(at: sourceIndexPath.row) - viewmodel.datas.remove(src_model) - viewmodel.datas.insert(src_model, at: destinationIndexPath.row) - }else { - let src_model = viewmodel.datas.object(at: sourceIndexPath.row) - viewmodel.datas.insert(src_model, at: destinationIndexPath.row + 1) - viewmodel.datas.removeObject(at: sourceIndexPath.row) - } - - viewmodel.datas.forEach { user in - if let u = user as? IdGroupModel { - print("change name : ", u.idName as Any) - print("change p: ", u.role?.priority as Any) - } + + public func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, + to destinationIndexPath: IndexPath) { + print("source :", sourceIndexPath.row, " destionation :", destinationIndexPath.row) + + if sourceIndexPath.row > destinationIndexPath.row { + let src_model = viewmodel.datas.object(at: sourceIndexPath.row) + viewmodel.datas.remove(src_model) + viewmodel.datas.insert(src_model, at: destinationIndexPath.row) + } else { + let src_model = viewmodel.datas.object(at: sourceIndexPath.row) + viewmodel.datas.insert(src_model, at: destinationIndexPath.row + 1) + viewmodel.datas.removeObject(at: sourceIndexPath.row) + } + + viewmodel.datas.forEach { user in + if let u = user as? IdGroupModel { + print("change name : ", u.idName as Any) + print("change p: ", u.role?.priority as Any) } + } } - - public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - return 60 + + public func tableView(_ tableView: UITableView, + heightForRowAt indexPath: IndexPath) -> CGFloat { + 60 } - - public func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool { - return false + + public func tableView(_ tableView: UITableView, + shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool { + false } - + public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - if let model = viewmodel.datas[indexPath.row] as? IdGroupModel { - weak var weakSelf = self - if model.hasPermission == true { - showAlert(message: "确定删除 \(model.idName ?? "当前身份组")?") { - weakSelf?.view.makeToastActivity(.center) - weakSelf?.viewmodel.removeRole(weakSelf?.serverId, model.role?.roleId, model) { - weakSelf?.didDelete = true - weakSelf?.view.hideToastActivity() - } - } + if let model = viewmodel.datas[indexPath.row] as? IdGroupModel { + weak var weakSelf = self + if model.hasPermission == true { + showAlert(message: "确定删除 \(model.idName ?? "当前身份组")?") { + weakSelf?.view.makeToastActivity(.center) + weakSelf?.viewmodel.removeRole(weakSelf?.serverId, model.role?.roleId, model) { + weakSelf?.didDelete = true + weakSelf?.view.hideToastActivity() } + } } + } } - - public func tableView(_ tableView: UITableView, targetIndexPathForMoveFromRowAt sourceIndexPath: IndexPath, toProposedIndexPath proposedDestinationIndexPath: IndexPath) -> IndexPath { - if isOwer == true { + + public func tableView(_ tableView: UITableView, + targetIndexPathForMoveFromRowAt sourceIndexPath: IndexPath, + toProposedIndexPath proposedDestinationIndexPath: IndexPath) + -> IndexPath { + if isOwer == true { + return proposedDestinationIndexPath + } else { + if let model = viewmodel.datas[proposedDestinationIndexPath.row] as? IdGroupModel { + if model.hasPermission == true { return proposedDestinationIndexPath - }else { - if let model = viewmodel.datas[proposedDestinationIndexPath.row] as? IdGroupModel { - if model.hasPermission == true { - return proposedDestinationIndexPath - } - } + } } - return sourceIndexPath + } + return sourceIndexPath } - + public func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { - if let model = viewmodel.datas[indexPath.row] as? IdGroupModel { - return model.hasPermission - } - return true + if let model = viewmodel.datas[indexPath.row] as? IdGroupModel { + return model.hasPermission + } + return true } - + public func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool { - if let model = viewmodel.datas[indexPath.row] as? IdGroupModel { - return model.hasPermission - } - return true + if let model = viewmodel.datas[indexPath.row] as? IdGroupModel { + return model.hasPermission + } + return true } - public func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle { - return UITableViewCell.EditingStyle.none + public func tableView(_ tableView: UITableView, + editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle { + UITableViewCell.EditingStyle.none } - - } + + diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewController/QChatIdGroupViewController.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewController/QChatIdGroupViewController.swift index 9a399e65..89e2f36e 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewController/QChatIdGroupViewController.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewController/QChatIdGroupViewController.swift @@ -1,226 +1,245 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import MJRefresh -public class QChatIdGroupViewController: NEBaseTableViewController { - - let viewModel = IdGroupViewModel() - var isOwner = false - var serverid: UInt64? - - public override func viewDidLoad() { - super.viewDidLoad() +public class QChatIdGroupViewController: NEBaseTableViewController,UITableViewDelegate, UITableViewDataSource,ViewModelDelegate { + let viewModel = IdGroupViewModel() + var isOwner = false + var serverid: UInt64? - // Do any additional setup after loading the view. - viewModel.delegate = self - loadMoreData() - setupUI() - } - - func setupUI(){ - self.title = localizable("qchat_id_group") - NELog.infoLog(className(), desc: "serverid : \(serverid ?? 0)") - addRightAction(UIImage.ne_imageNamed(name: "sign_add"), #selector(addClick), self) - setupTable() - tableView.delegate = self - tableView.dataSource = self - tableView.register(QChatIdGroupCell.self, forCellReuseIdentifier: "\(QChatIdGroupCell.self)") - tableView.register(QChatIdGroupTopCell.self, forCellReuseIdentifier: "\(QChatIdGroupTopCell.self)") - tableView.register(QChatIdGroupSortButtonCell.self, forCellReuseIdentifier: "\(QChatIdGroupSortButtonCell.self)") - let mjFooter = MJRefreshBackNormalFooter(refreshingTarget: self, refreshingAction: #selector(loadMoreData)) - mjFooter.stateLabel?.isHidden = true - tableView.mj_footer = mjFooter - } - - @objc func loadMoreData(){ - if let sid = serverid { - viewModel.getRoles(sid, false, nil) - }else { - fatalError("serverid must not be nil") - } - } - - @objc func refreshData(){ - weak var weakSelf = self - view.makeToastActivity(.center) - print("refresh data") - viewModel.getRoles(weakSelf?.serverid, true , { - weakSelf?.view.hideToastActivity() - weakSelf?.tableView.mj_footer?.state = .idle - weakSelf?.tableView.mj_footer?.isHidden = false - }) + override public func viewDidLoad() { + super.viewDidLoad() - } - + // Do any additional setup after loading the view. + viewModel.delegate = self + loadMoreData() + setupUI() + } - /* - // MARK: - Navigation + func setupUI() { + title = localizable("qchat_id_group") + NELog.infoLog(className(), desc: "serverid : \(serverid ?? 0)") + addRightAction(UIImage.ne_imageNamed(name: "sign_add"), #selector(addClick), self) + setupTable() + tableView.delegate = self + tableView.dataSource = self + tableView.register( + QChatIdGroupCell.self, + forCellReuseIdentifier: "\(QChatIdGroupCell.self)" + ) + tableView.register( + QChatIdGroupTopCell.self, + forCellReuseIdentifier: "\(QChatIdGroupTopCell.self)" + ) + tableView.register( + QChatIdGroupSortButtonCell.self, + forCellReuseIdentifier: "\(QChatIdGroupSortButtonCell.self)" + ) + let mjFooter = MJRefreshBackNormalFooter( + refreshingTarget: self, + refreshingAction: #selector(loadMoreData) + ) + mjFooter.stateLabel?.isHidden = true + tableView.mj_footer = mjFooter + } - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. + @objc func loadMoreData() { + if let sid = serverid { + viewModel.getRoles(sid, false, nil) + } else { + fatalError("serverid must not be nil") } - */ + } -} + @objc func refreshData() { + weak var weakSelf = self + view.makeToastActivity(.center) + print("refresh data") + viewModel.getRoles(weakSelf?.serverid, true) { + weakSelf?.view.hideToastActivity() + weakSelf?.tableView.mj_footer?.state = .idle + weakSelf?.tableView.mj_footer?.isHidden = false + } + } -extension QChatIdGroupViewController: UITableViewDelegate, UITableViewDataSource, ViewModelDelegate { - + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ + //MARK: UITableViewDelegate, UITableViewDataSource,ViewModelDelegate public func dataDidError(_ error: Error) { - print("get roles error : ", error) - NELog.errorLog(className(), desc: "error : \(error)") - view.makeToast(error.localizedDescription) + print("get roles error : ", error) + NELog.errorLog(className(), desc: "error : \(error)") + view.makeToast(error.localizedDescription) } - + public func dataDidChange() { - tableView.mj_footer?.endRefreshing() - tableView.reloadData() + tableView.mj_footer?.endRefreshing() + tableView.reloadData() } - + public func dataNoMore() { - tableView.mj_footer?.endRefreshingWithNoMoreData() - tableView.mj_footer?.isHidden = true + tableView.mj_footer?.endRefreshingWithNoMoreData() + tableView.mj_footer?.isHidden = true } - + public func numberOfSections(in tableView: UITableView) -> Int { - return 3 + 3 } - + public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - if section == 0 { - return viewModel.topDatas.count - }else if section == 1 { - if viewModel.datas.count > 0 { - return viewModel.sortBtnCellDatas.count - } - }else if section == 2 { - return viewModel.datas.count + if section == 0 { + return viewModel.topDatas.count + } else if section == 1 { + if viewModel.datas.count > 0 { + return viewModel.sortBtnCellDatas.count } - return 0 + } else if section == 2 { + return viewModel.datas.count + } + return 0 } - - public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - if indexPath.section == 0 { - let model = viewModel.topDatas[indexPath.row] - let cell: QChatIdGroupTopCell = tableView.dequeueReusableCell(withIdentifier: "\(QChatIdGroupTopCell.self)", for: indexPath) as! QChatIdGroupTopCell - cell.configure(model) - return cell - }else if indexPath.section == 1 { - let model = viewModel.sortBtnCellDatas[indexPath.row] - let cell: QChatIdGroupSortButtonCell = tableView.dequeueReusableCell(withIdentifier: "\(QChatIdGroupSortButtonCell.self)", for: indexPath) as! QChatIdGroupSortButtonCell - cell.titleLabel.text = model.idName - cell.sortBtn.addTarget(self, action: #selector(toSort), for: .touchUpInside) - return cell - }else if indexPath.section == 2 { - let model = viewModel.datas[indexPath.row] - let cell: QChatIdGroupCell = tableView.dequeueReusableCell(withIdentifier: "\(QChatIdGroupCell.self)", for: indexPath) as! QChatIdGroupCell - cell.configure(model) - return cell - } - return UITableViewCell() + + public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + if indexPath.section == 0 { + let model = viewModel.topDatas[indexPath.row] + let cell: QChatIdGroupTopCell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatIdGroupTopCell.self)", + for: indexPath + ) as! QChatIdGroupTopCell + cell.configure(model) + return cell + } else if indexPath.section == 1 { + let model = viewModel.sortBtnCellDatas[indexPath.row] + let cell: QChatIdGroupSortButtonCell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatIdGroupSortButtonCell.self)", + for: indexPath + ) as! QChatIdGroupSortButtonCell + cell.titleLabel.text = model.idName + cell.sortBtn.addTarget(self, action: #selector(toSort), for: .touchUpInside) + return cell + } else if indexPath.section == 2 { + let model = viewModel.datas[indexPath.row] + let cell: QChatIdGroupCell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatIdGroupCell.self)", + for: indexPath + ) as! QChatIdGroupCell + cell.configure(model) + return cell + } + return UITableViewCell() } - - public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - if indexPath.section == 0 { - return 68 - }else if indexPath.section == 1 { - return 30 - }else if indexPath.section == 2 { - return 60 - } - return 0 + + public func tableView(_ tableView: UITableView, + heightForRowAt indexPath: IndexPath) -> CGFloat { + if indexPath.section == 0 { + return 68 + } else if indexPath.section == 1 { + return 30 + } else if indexPath.section == 2 { + return 60 + } + return 0 } - - public func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { - if section == 1 { - return 6 - } - return 0 + + public func tableView(_ tableView: UITableView, + heightForHeaderInSection section: Int) -> CGFloat { + if section == 1 { + return 6 + } + return 0 } - - public func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { - if section == 1 { - let view = UIView(frame: CGRect.zero) - view.backgroundColor = UIColor(hexString: "EFF1F4") - return view - } - return nil + + public func tableView(_ tableView: UITableView, + viewForHeaderInSection section: Int) -> UIView? { + if section == 1 { + let view = UIView(frame: CGRect.zero) + view.backgroundColor = UIColor(hexString: "EFF1F4") + return view + } + return nil } - - public func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { - return 0 + + public func tableView(_ tableView: UITableView, + heightForFooterInSection section: Int) -> CGFloat { + 0 } - - public func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { - return nil + + public func tableView(_ tableView: UITableView, + viewForFooterInSection section: Int) -> UIView? { + nil } - + public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - - if indexPath.section == 1 { - return - } - - if indexPath.section == 0 { - let model = viewModel.topDatas[indexPath.row] - toPermission(model) - }else if indexPath.section == 2 { - let model = viewModel.datas[indexPath.row] - toPermission(model) - } - } -} + if indexPath.section == 1 { + return + } -extension QChatIdGroupViewController { - - @objc func addClick(){ - let create = QChatCreateGroupViewController() - create.serverId = serverid - weak var weakSelf = self - create.completion = { - weakSelf?.refreshData() - } - navigationController?.pushViewController(create, animated: true) + if indexPath.section == 0 { + let model = viewModel.topDatas[indexPath.row] + toPermission(model) + } else if indexPath.section == 2 { + let model = viewModel.datas[indexPath.row] + toPermission(model) + } + } + + //MARK: objc 方法 + @objc func addClick() { + let create = QChatCreateGroupViewController() + create.serverId = serverid + weak var weakSelf = self + create.completion = { + weakSelf?.refreshData() + } + navigationController?.pushViewController(create, animated: true) } - - @objc func toSort(){ - let sort = QChatIdGroupSortController() - sort.serverId = serverid - sort.isOwer = isOwner - weak var weakSelf = self - sort.completion = { - - weakSelf?.refreshData() -// weakSelf?.viewModel.datas.removeAll() -// for index in 0.. Void -public class QChatMemberManagerController: NEBaseTableViewController { - - let viewmodel = MemberManagerViewModel() - - var memberCount = 0 - - var serverId: UInt64? - - var roleId: UInt64? - - var countChangeBlock: MemberCountChange? +public class QChatMemberManagerController: NEBaseTableViewController,UITableViewDelegate, UITableViewDataSource,ViewModelDelegate,QChatMemberSelectControllerDelegate { + let viewmodel = MemberManagerViewModel() - public override func viewDidLoad() { - super.viewDidLoad() + var memberCount = 0 - // Do any additional setup after loading the view. - viewmodel.delegate = self - loadMoreData() - setupUI() - } - - func setupUI(){ - self.title = localizable("qchat_manager_member") - view.backgroundColor = .white - setupTable() - tableView.delegate = self - tableView.dataSource = self - tableView.register(QChatMemberManagerCell.self, forCellReuseIdentifier: "\(QChatMemberManagerCell.self)") - tableView.register(QChatPlainTextArrowCell.self, forCellReuseIdentifier: "\(QChatPlainTextArrowCell.self)") - - let mjfooter = MJRefreshBackNormalFooter(refreshingTarget: self, refreshingAction: #selector(loadMoreData)) - mjfooter.stateLabel?.isHidden = true - tableView.mj_footer = mjfooter - - } - - @objc func loadMoreData(){ - if let rid = roleId, let sid = serverId { - viewmodel.getData(sid, rid) - }else { - fatalError("serverId or roleId is nil") - } - } + var serverId: UInt64? + + var roleId: UInt64? + + var countChangeBlock: MemberCountChange? + + override public func viewDidLoad() { + super.viewDidLoad() - /* - // MARK: - Navigation + // Do any additional setup after loading the view. + viewmodel.delegate = self + loadMoreData() + setupUI() + } - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. + func setupUI() { + title = localizable("qchat_manager_member") + view.backgroundColor = .white + setupTable() + tableView.delegate = self + tableView.dataSource = self + tableView.register( + QChatMemberManagerCell.self, + forCellReuseIdentifier: "\(QChatMemberManagerCell.self)" + ) + tableView.register( + QChatPlainTextArrowCell.self, + forCellReuseIdentifier: "\(QChatPlainTextArrowCell.self)" + ) + + let mjfooter = MJRefreshBackNormalFooter( + refreshingTarget: self, + refreshingAction: #selector(loadMoreData) + ) + mjfooter.stateLabel?.isHidden = true + tableView.mj_footer = mjfooter + } + + @objc func loadMoreData() { + if let rid = roleId, let sid = serverId { + viewmodel.getData(sid, rid) + } else { + fatalError("serverId or roleId is nil") } - */ + } -} + /* + // MARK: - Navigation -extension QChatMemberManagerController: UITableViewDelegate, UITableViewDataSource, ViewModelDelegate, QChatMemberSelectControllerDelegate { - - public func filterMembers(accid: [String]?, _ filterMembers: @escaping ([String]?) -> ()) { - var param = GetExistingServerRoleMembersByAccidsParam() - param.serverId = serverId - param.accids = accid - param.roleId = roleId - print("param existing accid : ", accid as Any) - viewmodel.repo.getExistingServerRoleMembersByAccids(param) { error, accids in - print("getExistingServerRoleMembersByAccids : ", accids) - var dic = [String: String]() - var retAccids = [String]() - accids.forEach { aid in - dic[aid] = aid - } - accid?.forEach({ aid in - if dic[aid] != nil { - retAccids.append(aid) - } - }) - print("filter members : ", retAccids) - filterMembers(retAccids) + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ + //MARK: UITableViewDelegate, UITableViewDataSource,ViewModelDelegate,QChatMemberSelectControllerDelegate + + public func filterMembers(accid: [String]?, _ filterMembers: @escaping ([String]?) -> Void) { + var param = GetExistingServerRoleMembersByAccidsParam() + param.serverId = serverId + param.accids = accid + param.roleId = roleId + print("param existing accid : ", accid as Any) + viewmodel.repo.getExistingServerRoleMembersByAccids(param) { error, accids in + print("getExistingServerRoleMembersByAccids : ", accids) + var dic = [String: String]() + var retAccids = [String]() + accids.forEach { aid in + dic[aid] = aid + } + accid?.forEach { aid in + if dic[aid] != nil { + retAccids.append(aid) + } } + print("filter members : ", retAccids) + filterMembers(retAccids) + } } - + public func dataDidChange() { - view.hideToastActivity() - tableView.mj_footer?.endRefreshing() - tableView.reloadData() + view.hideToastActivity() + tableView.mj_footer?.endRefreshing() + tableView.reloadData() } - + public func dataNoMore() { - view.hideToastActivity() - tableView.mj_footer?.endRefreshingWithNoMoreData() - tableView.mj_footer?.isHidden = true + view.hideToastActivity() + tableView.mj_footer?.endRefreshingWithNoMoreData() + tableView.mj_footer?.isHidden = true } - + public func dataDidError(_ error: Error) { - showToast(error.localizedDescription) + showToast(error.localizedDescription) } - + public func numberOfSections(in tableView: UITableView) -> Int { - return 2 + 2 } - + public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - if section == 0 { - return 1 - } - if section == 1 { - return viewmodel.datas.count - } - return 0 + if section == 0 { + return 1 + } + if section == 1 { + return viewmodel.datas.count + } + return 0 } - - public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - - if indexPath.section == 0 { - let cell: QChatPlainTextArrowCell = tableView.dequeueReusableCell(withIdentifier: "\(QChatPlainTextArrowCell.self)", for: indexPath) as! QChatPlainTextArrowCell - cell.titleLabel.text = localizable("qchat_add_member") - cell.detailLabel.text = "\(memberCount)" - return cell - } - - if indexPath.section == 1 { - let cell: QChatMemberManagerCell = tableView.dequeueReusableCell(withIdentifier: "\(QChatMemberManagerCell.self)", for: indexPath) as! QChatMemberManagerCell - let user = viewmodel.datas[indexPath.row] - cell.user = user - return cell - } - - return UITableViewCell() + + public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + if indexPath.section == 0 { + let cell: QChatPlainTextArrowCell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatPlainTextArrowCell.self)", + for: indexPath + ) as! QChatPlainTextArrowCell + cell.titleLabel.text = localizable("qchat_add_member") + cell.detailLabel.text = "\(memberCount)" + return cell + } + + if indexPath.section == 1 { + let cell: QChatMemberManagerCell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatMemberManagerCell.self)", + for: indexPath + ) as! QChatMemberManagerCell + let user = viewmodel.datas[indexPath.row] + cell.user = user + return cell + } + + return UITableViewCell() } - - public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - return 50 + + public func tableView(_ tableView: UITableView, + heightForRowAt indexPath: IndexPath) -> CGFloat { + 50 } - - public func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { - return 0 + + public func tableView(_ tableView: UITableView, + heightForHeaderInSection section: Int) -> CGFloat { + 0 } - - public func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { - return 0 + + public func tableView(_ tableView: UITableView, + heightForFooterInSection section: Int) -> CGFloat { + 0 } - - public func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { - return nil + + public func tableView(_ tableView: UITableView, + viewForHeaderInSection section: Int) -> UIView? { + nil } - - public func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { - return nil + + public func tableView(_ tableView: UITableView, + viewForFooterInSection section: Int) -> UIView? { + nil } - + public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - weak var weakSelf = self - if indexPath.section == 0 { - let memberSelect = QChatMemberSelectController() - memberSelect.delegate = self - memberSelect.serverId = serverId - memberSelect.completion = { users in - print("member manager select: ", users) - weakSelf?.view.makeToastActivity(.center) - weakSelf?.viewmodel.addMembers(users, weakSelf?.serverId, weakSelf?.roleId) { successCount in -// weakSelf?.view.hideToastActivity() - weakSelf?.showToast(localizable("qchat_add_success")) - if let block = weakSelf?.countChangeBlock, var count = weakSelf?.memberCount { - count = count + successCount - weakSelf?.memberCount = count - block(count) - } - } + weak var weakSelf = self + if indexPath.section == 0 { + let memberSelect = QChatMemberSelectController() + memberSelect.delegate = self + memberSelect.serverId = serverId + memberSelect.completion = { users in + print("member manager select: ", users) + weakSelf?.view.makeToastActivity(.center) + weakSelf?.viewmodel + .addMembers(users, weakSelf?.serverId, weakSelf?.roleId) { successCount in + // weakSelf?.view.hideToastActivity() + weakSelf?.showToast(localizable("qchat_add_success")) + if let block = weakSelf?.countChangeBlock, var count = weakSelf?.memberCount { + count = count + successCount + weakSelf?.memberCount = count + block(count) + } } - navigationController?.pushViewController(memberSelect, animated: true) - }else { - let user = viewmodel.datas[indexPath.row] - showAlert(message: localizable("qchat_sure_delete_user")) { - if let rid = weakSelf?.roleId, let sid = weakSelf?.serverId { - weakSelf?.view.makeToastActivity(.center) - weakSelf?.viewmodel.remove(user, sid, rid, { - weakSelf?.view.hideToastActivity() - weakSelf?.viewmodel.datas.remove(at: indexPath.row) - weakSelf?.tableView.reloadData() - if var count = weakSelf?.memberCount, let block = weakSelf?.countChangeBlock { - count = count - 1 - weakSelf?.memberCount = count - block(count) - } - }) - } + } + navigationController?.pushViewController(memberSelect, animated: true) + } else { + let user = viewmodel.datas[indexPath.row] + showAlert(message: localizable("qchat_sure_delete_user")) { + if let rid = weakSelf?.roleId, let sid = weakSelf?.serverId { + weakSelf?.view.makeToastActivity(.center) + weakSelf?.viewmodel.remove(user, sid, rid) { + weakSelf?.view.hideToastActivity() + weakSelf?.viewmodel.datas.remove(at: indexPath.row) + weakSelf?.tableView.reloadData() + if var count = weakSelf?.memberCount, + let block = weakSelf?.countChangeBlock { + count = count - 1 + weakSelf?.memberCount = count + block(count) + } } + } } + } } - } + + diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewController/QChatMemberSelectController.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewController/QChatMemberSelectController.swift index ac82353d..f7ccaaad 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewController/QChatMemberSelectController.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewController/QChatMemberSelectController.swift @@ -1,254 +1,276 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import MJRefresh -typealias SelectMemeberCompletion = ([UserInfo])->Void -typealias FilterMembersBlock = ([UserInfo])-> [UserInfo]? +typealias SelectMemeberCompletion = ([UserInfo]) -> Void +typealias FilterMembersBlock = ([UserInfo]) -> [UserInfo]? public protocol QChatMemberSelectControllerDelegate: AnyObject { - func filterMembers(accid:[String]?, _ filterMembers: @escaping ([String]?) -> ()) + func filterMembers(accid: [String]?, _ filterMembers: @escaping ([String]?) -> Void) } -//enum SelectType { +// enum SelectType { // case ServerMember // case ChannelMember -//} - -public class QChatMemberSelectController: NEBaseTableViewController,MemberSelectViewModelDelegate { - - let viewmodel = MemberSelectViewModel() - var filterBlock: FilterMembersBlock? - var completion: SelectMemeberCompletion? - +// } + +public class QChatMemberSelectController: NEBaseTableViewController, MemberSelectViewModelDelegate,UICollectionViewDelegate, UICollectionViewDataSource, + UICollectionViewDelegateFlowLayout,UITableViewDelegate,UITableViewDataSource,ViewModelDelegate { + let viewmodel = MemberSelectViewModel() + var filterBlock: FilterMembersBlock? + var completion: SelectMemeberCompletion? + // var selectType = SelectType.ServerMember - - var serverId: UInt64? - - var limit = 10 - - public weak var delegate: QChatMemberSelectControllerDelegate? - - lazy var collection : UICollectionView = { - let layout = UICollectionViewFlowLayout() - layout.scrollDirection = .horizontal - layout.minimumLineSpacing = 0 - layout.minimumInteritemSpacing = 0 - let collect = UICollectionView(frame: CGRect.zero, collectionViewLayout: layout) - collect.contentInset = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5) - return collect - }() - - var collectionHeight: NSLayoutConstraint? - - var selectArray = [UserInfo]() - - public override func viewDidLoad() { - super.viewDidLoad() - viewmodel.delegate = self - loadData() - setupUI() - } - - func setupUI(){ - edgesForExtendedLayout = [] - addRightAction(localizable("qchat_sure"), #selector(sureClick), self) - self.title = localizable("qchat_select") - view.addSubview(collection) - collection.delegate = self - collection.dataSource = self - collection.allowsMultipleSelection = false - collection.translatesAutoresizingMaskIntoConstraints = false - collectionHeight = collection.heightAnchor.constraint(equalToConstant: 0) - collectionHeight?.isActive = true - collection.backgroundColor = UIColor(hexString: "F2F4F5") - NSLayoutConstraint.activate([ - collection.topAnchor.constraint(equalTo: view.topAnchor), - collection.leftAnchor.constraint(equalTo: view.leftAnchor), - collection.rightAnchor.constraint(equalTo: view.rightAnchor) - ]) - - collection.register(QChatUserUnCheckCell.self, forCellWithReuseIdentifier: "\(NSStringFromClass(QChatUserUnCheckCell.self))") - - view.addSubview(tableView) - NSLayoutConstraint.activate([ - tableView.leftAnchor.constraint(equalTo: view.leftAnchor), - tableView.rightAnchor.constraint(equalTo: view.rightAnchor), - tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), - tableView.topAnchor.constraint(equalTo: collection.bottomAnchor) - ]) - if #available(iOS 13.0, *) { - tableView.automaticallyAdjustsScrollIndicatorInsets = false - } else { - // Fallback on earlier versions - } - tableView.delegate = self - tableView.dataSource = self - tableView.register(QChatSelectedCell.self, forCellReuseIdentifier: "\(QChatSelectedCell.self)") - - if #available(iOS 11.0,*) { - tableView.contentInsetAdjustmentBehavior = UIScrollView.ContentInsetAdjustmentBehavior.never - } else { - automaticallyAdjustsScrollViewInsets = false - } - tableView.mj_footer = MJRefreshBackNormalFooter(refreshingTarget: self, refreshingAction: #selector(loadMoreData)) + + var serverId: UInt64? + + var limit = 10 + + public weak var delegate: QChatMemberSelectControllerDelegate? + + lazy var collection: UICollectionView = { + let layout = UICollectionViewFlowLayout() + layout.scrollDirection = .horizontal + layout.minimumLineSpacing = 0 + layout.minimumInteritemSpacing = 0 + let collect = UICollectionView(frame: CGRect.zero, collectionViewLayout: layout) + collect.contentInset = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5) + return collect + }() + + var collectionHeight: NSLayoutConstraint? + + var selectArray = [UserInfo]() + + override public func viewDidLoad() { + super.viewDidLoad() + viewmodel.delegate = self + loadData() + setupUI() + } + + func setupUI() { + edgesForExtendedLayout = [] + addRightAction(localizable("qchat_sure"), #selector(sureClick), self) + title = localizable("qchat_select") + view.addSubview(collection) + collection.delegate = self + collection.dataSource = self + collection.allowsMultipleSelection = false + collection.translatesAutoresizingMaskIntoConstraints = false + collectionHeight = collection.heightAnchor.constraint(equalToConstant: 0) + collectionHeight?.isActive = true + collection.backgroundColor = UIColor(hexString: "F2F4F5") + NSLayoutConstraint.activate([ + collection.topAnchor.constraint(equalTo: view.topAnchor), + collection.leftAnchor.constraint(equalTo: view.leftAnchor), + collection.rightAnchor.constraint(equalTo: view.rightAnchor), + ]) + + collection.register( + QChatUserUnCheckCell.self, + forCellWithReuseIdentifier: "\(NSStringFromClass(QChatUserUnCheckCell.self))" + ) + + view.addSubview(tableView) + NSLayoutConstraint.activate([ + tableView.leftAnchor.constraint(equalTo: view.leftAnchor), + tableView.rightAnchor.constraint(equalTo: view.rightAnchor), + tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), + tableView.topAnchor.constraint(equalTo: collection.bottomAnchor), + ]) + if #available(iOS 13.0, *) { + tableView.automaticallyAdjustsScrollIndicatorInsets = false + } else { + // Fallback on earlier versions + } + tableView.delegate = self + tableView.dataSource = self + tableView.register( + QChatSelectedCell.self, + forCellReuseIdentifier: "\(QChatSelectedCell.self)" + ) + + if #available(iOS 11.0,*) { + tableView.contentInsetAdjustmentBehavior = UIScrollView.ContentInsetAdjustmentBehavior + .never + } else { + automaticallyAdjustsScrollViewInsets = false + } + tableView.mj_footer = MJRefreshBackNormalFooter( + refreshingTarget: self, + refreshingAction: #selector(loadMoreData) + ) // tableView.mj_header = MJRefreshNormalHeader(refreshingTarget: self, refreshingAction: #selector(loadData)) - - - } - - @objc func sureClick(){ - if selectArray.count <= 0 { - view.makeToast(localizable("qchat_not_empty_select_memeber")) - return - } - if let block = completion { - block(selectArray) - } - navigationController?.popViewController(animated: true) - } - - @objc func loadData() { - viewmodel.loadFirst(serverId: serverId) { [weak self] error, users in - if error != nil { - self?.view.makeToast(error?.localizedDescription) - }else { - self?.tableView.reloadData() - self?.tableView.mj_footer?.resetNoMoreData() - self?.tableView.mj_header?.endRefreshing() - } - } + } + + @objc func sureClick() { + if selectArray.count <= 0 { + view.makeToast(localizable("qchat_not_empty_select_memeber")) + return } - - @objc func loadMoreData() { - viewmodel.loadMore(serverId: serverId) { [weak self] error, users in - if error != nil { - self?.view.makeToast(error?.localizedDescription) - }else { - if users?.count ?? 0 > 0 { - self?.tableView.reloadData() - self?.tableView.mj_footer?.endRefreshing() - }else { - self?.tableView.mj_footer?.endRefreshingWithNoMoreData() - } - } - } + if let block = completion { + block(selectArray) } -} + navigationController?.popViewController(animated: true) + } -extension QChatMemberSelectController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, UITableViewDelegate, UITableViewDataSource, ViewModelDelegate { - + @objc func loadData() { + viewmodel.loadFirst(serverId: serverId) { [weak self] error, users in + if error != nil { + self?.view.makeToast(error?.localizedDescription) + } else { + self?.tableView.reloadData() + self?.tableView.mj_footer?.resetNoMoreData() + self?.tableView.mj_header?.endRefreshing() + } + } + } + + @objc func loadMoreData() { + viewmodel.loadMore(serverId: serverId) { [weak self] error, users in + if error != nil { + self?.view.makeToast(error?.localizedDescription) + } else { + if users?.count ?? 0 > 0 { + self?.tableView.reloadData() + self?.tableView.mj_footer?.endRefreshing() + } else { + self?.tableView.mj_footer?.endRefreshingWithNoMoreData() + } + } + } + } + //MARK: public func dataDidError(_ error: Error) { - view.makeToast(error.localizedDescription) + view.makeToast(error.localizedDescription) } - + public func dataDidChange() { - tableView.reloadData() - } - - public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - return selectArray.count - } - - public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { - let user = selectArray[indexPath.row] - let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "\(NSStringFromClass(QChatUserUnCheckCell.self))", for: indexPath) as? QChatUserUnCheckCell - cell?.configure(user) - return cell ?? UICollectionViewCell() - } - - public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - let user = selectArray[indexPath.row] - didUnselectContact(user) + tableView.reloadData() + } + + public func collectionView(_ collectionView: UICollectionView, + numberOfItemsInSection section: Int) -> Int { + selectArray.count + } + + public func collectionView(_ collectionView: UICollectionView, + cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + let user = selectArray[indexPath.row] + let cell = collectionView.dequeueReusableCell( + withReuseIdentifier: "\(NSStringFromClass(QChatUserUnCheckCell.self))", + for: indexPath + ) as? QChatUserUnCheckCell + cell?.configure(user) + return cell ?? UICollectionViewCell() } - - public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { - return CGSize(width: 46, height: 52) + + public func collectionView(_ collectionView: UICollectionView, + didSelectItemAt indexPath: IndexPath) { + let user = selectArray[indexPath.row] + didUnselectContact(user) + } + + public func collectionView(_ collectionView: UICollectionView, + layout collectionViewLayout: UICollectionViewLayout, + sizeForItemAt indexPath: IndexPath) -> CGSize { + CGSize(width: 46, height: 52) } - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return viewmodel.datas.count + viewmodel.datas.count } - - public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell: QChatSelectedCell = tableView.dequeueReusableCell(withIdentifier: "\(QChatSelectedCell.self)", for: indexPath) as! QChatSelectedCell - let user = viewmodel.datas[indexPath.row] - cell.user = user - return cell + + public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell: QChatSelectedCell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatSelectedCell.self)", + for: indexPath + ) as! QChatSelectedCell + let user = viewmodel.datas[indexPath.row] + cell.user = user + return cell } - - public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - return 62 + + public func tableView(_ tableView: UITableView, + heightForRowAt indexPath: IndexPath) -> CGFloat { + 62 } - + public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - - let user = viewmodel.datas[indexPath.row] - let cell = tableView.cellForRow(at: indexPath) as? QChatSelectedCell - - if user.select == true { - cell?.setUnselect() - didUnselectContact(user) - }else { - if selectArray.count >= limit { - //view.makeToast("超出\(limit)人限制") - showToast("\(localizable("exceed"))\(limit)\(localizable("person"))\(localizable("limit"))") - return - } - cell?.setSelect() - didSelectContact(user) - } -// tableView.reloadRows(at: [indexPath], with: .none) - } - - func didSelectContact(_ user: UserInfo){ - user.select = true - if selectArray.contains(where: { c in - return user === c - }) == false { - selectArray.append(user) - if let height = collectionHeight?.constant, height <= 0 { - collectionHeight?.constant = 52 - } - } - collection.reloadData() - tableView.reloadData() - refreshSelectCount() - } - - func didUnselectContact(_ user: UserInfo){ - user.select = false - selectArray.removeAll { c in - return user === c + let user = viewmodel.datas[indexPath.row] + let cell = tableView.cellForRow(at: indexPath) as? QChatSelectedCell + + if user.select == true { + cell?.setUnselect() + didUnselectContact(user) + } else { + if selectArray.count >= limit { + // view.makeToast("超出\(limit)人限制") + showToast( + "\(localizable("exceed"))\(limit)\(localizable("person"))\(localizable("limit"))" + ) + return } - if selectArray.count <= 0 { - collection.reloadData() - collectionHeight?.constant = 0 + cell?.setSelect() + didSelectContact(user) + } + // tableView.reloadRows(at: [indexPath], with: .none) + } + + func didSelectContact(_ user: UserInfo) { + user.select = true + if selectArray.contains(where: { c in + user === c + }) == false { + selectArray.append(user) + if let height = collectionHeight?.constant, height <= 0 { + collectionHeight?.constant = 52 } + } + collection.reloadData() + tableView.reloadData() + refreshSelectCount() + } + + func didUnselectContact(_ user: UserInfo) { + user.select = false + selectArray.removeAll { c in + user === c + } + if selectArray.count <= 0 { collection.reloadData() - tableView.reloadData() - refreshSelectCount() - } - - func refreshSelectCount(){ - if selectArray.count > 0 { - rightNavBtn.setTitle("\(localizable("qchat_sure"))(\(selectArray.count))", for: .normal) - }else { - rightNavBtn.setTitle(localizable("qchat_sure"), for: .normal) - } + collectionHeight?.constant = 0 + } + collection.reloadData() + tableView.reloadData() + refreshSelectCount() } - - public func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { - return 0 + + func refreshSelectCount() { + if selectArray.count > 0 { + rightNavBtn.setTitle("\(localizable("qchat_sure"))(\(selectArray.count))", for: .normal) + } else { + rightNavBtn.setTitle(localizable("qchat_sure"), for: .normal) + } } - -// MARK: MemberSelectViewModelDelegate - func filterMembers(accid: [String]?, _ filterMembers: @escaping ([String]?) -> ()) { -// 查询需要筛选的用户 - self.delegate?.filterMembers(accid: accid, filterMembers) + + public func tableView(_ tableView: UITableView, + heightForHeaderInSection section: Int) -> CGFloat { + 0 } + // MARK: MemberSelectViewModelDelegate + + func filterMembers(accid: [String]?, _ filterMembers: @escaping ([String]?) -> Void) { + // 查询需要筛选的用户 + delegate?.filterMembers(accid: accid, filterMembers) + } } + + diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewController/QChatPermissionViewController.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewController/QChatPermissionViewController.swift index f5e67aa1..061953d4 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewController/QChatPermissionViewController.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewController/QChatPermissionViewController.swift @@ -1,296 +1,310 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCoreIM typealias RoleUpdateCompletion = (_ role: ServerRole) -> Void -public class QChatPermissionViewController: NEBaseTableViewController { - - var idGroup: IdGroupModel? - - let viewmodel = PermissionViewModel() - - var serverName = "" - - var completion: RoleUpdateCompletion? - - public override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - viewmodel.delegate = self - if let name = idGroup?.role?.name { - serverName = name - } - if let serverRole = idGroup?.role { - viewmodel.getData(serverRole) - }else { - fatalError("permission server role is nil ") - } - setupUI() +public class QChatPermissionViewController: NEBaseTableViewController,UITableViewDelegate, UITableViewDataSource, QChatTextEditCellDelegate, ViewModelDelegate, QChatSwitchCellDelegate { + var idGroup: IdGroupModel? + + let viewmodel = PermissionViewModel() + + var serverName = "" + + var completion: RoleUpdateCompletion? + + override public func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + viewmodel.delegate = self + if let name = idGroup?.role?.name { + serverName = name } - - func setupUI(){ - - if let type = idGroup?.role?.type, type != .everyone { - addRightAction(localizable("qchat_save"), #selector(savePermission), self) - } - - setupTable() - self.title = idGroup?.idName - tableView.backgroundColor = .ne_backcolor - tableView.delegate = self - tableView.dataSource = self - tableView.register(QChatTextEditCell.self, forCellReuseIdentifier: "\(QChatTextEditCell.self)") - tableView.register(QChatSwitchCell.self, forCellReuseIdentifier: "\(QChatSwitchCell.self)") - tableView.register(QChatTextArrowCell.self, forCellReuseIdentifier: "\(QChatTextArrowCell.self)") + if let serverRole = idGroup?.role { + viewmodel.getData(serverRole) + } else { + fatalError("permission server role is nil ") } - - - /* - // MARK: - Navigation - - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. - } - */ - -} + setupUI() + } -extension QChatPermissionViewController: UITableViewDelegate, UITableViewDataSource, QChatTextEditCellDelegate, ViewModelDelegate, QChatSwitchCellDelegate { + func setupUI() { + if let type = idGroup?.role?.type, type != .everyone { + addRightAction(localizable("qchat_save"), #selector(savePermission), self) + } + + setupTable() + title = idGroup?.idName + tableView.backgroundColor = .ne_backcolor + tableView.delegate = self + tableView.dataSource = self + tableView.register( + QChatTextEditCell.self, + forCellReuseIdentifier: "\(QChatTextEditCell.self)" + ) + tableView.register(QChatSwitchCell.self, forCellReuseIdentifier: "\(QChatSwitchCell.self)") + tableView.register( + QChatTextArrowCell.self, + forCellReuseIdentifier: "\(QChatTextArrowCell.self)" + ) + } + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ + //MARK: UITableViewDelegate, UITableViewDataSource, QChatTextEditCellDelegate, ViewModelDelegate, QChatSwitchCellDelegate func didChangeSwitchValue(_ cell: QChatSwitchCell) { - print("did change switch value : ", cell) - if let key = cell.model?.permissionKey, let value = cell.model?.permission?.value(forKey: key) as? String, let type = ChatPermissionType(rawValue: value) { - updatePermission(type, cell.qSwitch.isOn) { success in - if success == false { - cell.qSwitch.isOn = !cell.qSwitch.isOn - } - } + print("did change switch value : ", cell) + if let key = cell.model?.permissionKey, + let value = cell.model?.permission?.value(forKey: key) as? String, + let type = ChatPermissionType(rawValue: value) { + updatePermission(type, cell.qSwitch.isOn) { success in + if success == false { + cell.qSwitch.isOn = !cell.qSwitch.isOn + } } + } } - + public func dataDidChange() { - tableView.reloadData() + tableView.reloadData() } - + public func dataDidError(_ error: Error) { - showToast(error.localizedDescription) + showToast(error.localizedDescription) } - - + func textDidChange(_ textField: UITextField) { - if let text = textField.text { - serverName = text - } + if let text = textField.text { + serverName = text + } } - + public func numberOfSections(in tableView: UITableView) -> Int { - return 5 + 5 } - + public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - if section == 0 { - return 1 - } - if section == 1 { - if let type = idGroup?.role?.type, type == .everyone { - return 0 - } - return 1 - } - if section == 2 { - return viewmodel.commons.count - } - if section == 3 { - return viewmodel.messages.count + if section == 0 { + return 1 + } + if section == 1 { + if let type = idGroup?.role?.type, type == .everyone { + return 0 } - if section == 4 { - return viewmodel.members.count - } - return 0 + return 1 + } + if section == 2 { + return viewmodel.commons.count + } + if section == 3 { + return viewmodel.messages.count + } + if section == 4 { + return viewmodel.members.count + } + return 0 } - - public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - - if indexPath.section == 0 { - let cell: QChatTextEditCell = tableView.dequeueReusableCell(withIdentifier: "\(QChatTextEditCell.self)", for: indexPath) as! QChatTextEditCell - if serverName.count > 0 { - cell.textFied.text = serverName - }else { - cell.textFied.text = nil - } - cell.textFied.placeholder = localizable("qchat_please_input_role_name") - cell.delegate = self - cell.limit = 20 - cell.cornerType = CornerType.topLeft.union(CornerType.topRight).union(CornerType.bottomLeft).union(CornerType.bottomRight) - return cell - } - - if indexPath.section == 1 { - let cell: QChatTextArrowCell = tableView.dequeueReusableCell(withIdentifier: "\(QChatTextArrowCell.self)", for: indexPath) as! QChatTextArrowCell - cell.titleLabel.text = localizable("qchat_member") - cell.detailLabel.text = "\(idGroup?.role?.memberCount ?? 0)" - cell.cornerType = CornerType.topLeft.union(CornerType.topRight).union(CornerType.bottomLeft).union(CornerType.bottomRight) - return cell + + public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + if indexPath.section == 0 { + let cell: QChatTextEditCell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatTextEditCell.self)", + for: indexPath + ) as! QChatTextEditCell + if serverName.count > 0 { + cell.textFied.text = serverName + } else { + cell.textFied.text = nil } - - if indexPath.section == 2 || indexPath.section == 3 || indexPath.section == 4 { - let cell: QChatSwitchCell = tableView.dequeueReusableCell(withIdentifier: "\(QChatSwitchCell.self)", for: indexPath) as! QChatSwitchCell - var model: PermissionCellModel? - if indexPath.section == 2 { - model = viewmodel.commons[indexPath.row] - }else if indexPath.section == 3 { - model = viewmodel.messages[indexPath.row] - }else if indexPath.section == 4 { - model = viewmodel.members[indexPath.row] - } - cell.delegate = self - cell.model = model - return cell + cell.textFied.placeholder = localizable("qchat_please_input_role_name") + cell.delegate = self + cell.limit = 20 + cell.cornerType = CornerType.topLeft.union(CornerType.topRight) + .union(CornerType.bottomLeft).union(CornerType.bottomRight) + return cell + } + + if indexPath.section == 1 { + let cell: QChatTextArrowCell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatTextArrowCell.self)", + for: indexPath + ) as! QChatTextArrowCell + cell.titleLabel.text = localizable("qchat_member") + cell.detailLabel.text = "\(idGroup?.role?.memberCount ?? 0)" + cell.cornerType = CornerType.topLeft.union(CornerType.topRight) + .union(CornerType.bottomLeft).union(CornerType.bottomRight) + return cell + } + + if indexPath.section == 2 || indexPath.section == 3 || indexPath.section == 4 { + let cell: QChatSwitchCell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatSwitchCell.self)", + for: indexPath + ) as! QChatSwitchCell + var model: PermissionCellModel? + if indexPath.section == 2 { + model = viewmodel.commons[indexPath.row] + } else if indexPath.section == 3 { + model = viewmodel.messages[indexPath.row] + } else if indexPath.section == 4 { + model = viewmodel.members[indexPath.row] } - - return UITableViewCell() + cell.delegate = self + cell.model = model + return cell + } + + return UITableViewCell() } - - public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - return 50 + + public func tableView(_ tableView: UITableView, + heightForRowAt indexPath: IndexPath) -> CGFloat { + 50 } - - public func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { - let header = QChatHeaderView() - switch section { - case 0: - header.titleLabel.text = localizable("qchat_group_name") - break - case 1: - if let type = idGroup?.role?.type, type == .everyone { - return nil - } - header.titleLabel.text = localizable("qchat_manager_member") - break - case 2: - header.titleLabel.text = localizable("qchat_common_permission") - break - case 3: - header.titleLabel.text = localizable("qchat_message_permission") - break - case 4: - header.titleLabel.text = localizable("qchat_member_permission") - break - default: - break + + public func tableView(_ tableView: UITableView, + viewForHeaderInSection section: Int) -> UIView? { + let header = QChatHeaderView() + switch section { + case 0: + header.titleLabel.text = localizable("qchat_group_name") + case 1: + if let type = idGroup?.role?.type, type == .everyone { + return nil } - return header + header.titleLabel.text = localizable("qchat_manager_member") + case 2: + header.titleLabel.text = localizable("qchat_common_permission") + case 3: + header.titleLabel.text = localizable("qchat_message_permission") + case 4: + header.titleLabel.text = localizable("qchat_member_permission") + default: + break + } + return header } - - public func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { - if let type = idGroup?.role?.type, type == .everyone, section == 1 { - return 0 + + public func tableView(_ tableView: UITableView, + heightForHeaderInSection section: Int) -> CGFloat { + if let type = idGroup?.role?.type, type == .everyone, section == 1 { + return 0 + } + return 40 + } + + public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + if indexPath.section == 1 { + let memberManager = QChatMemberManagerController() + memberManager.serverId = idGroup?.role?.serverId + memberManager.roleId = idGroup?.role?.roleId + memberManager.memberCount = idGroup?.role?.memberCount ?? 0 + weak var weakSelf = self + memberManager.countChangeBlock = { count in + weakSelf?.idGroup?.role?.memberCount = count + if let role = weakSelf?.idGroup?.role, let block = weakSelf?.completion { + block(role) + } + tableView.reloadData() } - return 40 + navigationController?.pushViewController(memberManager, animated: true) + } } - public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - - if indexPath.section == 1 { - let memberManager = QChatMemberManagerController() - memberManager.serverId = idGroup?.role?.serverId - memberManager.roleId = idGroup?.role?.roleId - memberManager.memberCount = idGroup?.role?.memberCount ?? 0 - weak var weakSelf = self - memberManager.countChangeBlock = { count in - weakSelf?.idGroup?.role?.memberCount = count - if let role = weakSelf?.idGroup?.role , let block = weakSelf?.completion{ - block(role) - } - tableView.reloadData() - } - navigationController?.pushViewController(memberManager, animated: true) + //MAKR: objc 方法 + @objc func savePermission() { + if serverName.count <= 0 { + showToast(localizable("qchat_please_input_role_name")) + return + } + var param = UpdateServerRoleParam() + param.serverId = idGroup?.role?.serverId + if let rid = idGroup?.role?.roleId { + param.roleId = UInt64(rid) + } + param.name = serverName + + /* 批量逻辑,暂时不用 + let permissions = viewmodel.permission.getChangePermission() + var commonds = [StatusInfo]() + + permissions.forEach { (type: ChatPermissionType, value: Bool) in + var info = StatusInfo() + info.permissionType = type + if value == true { + info.status = .Allow + }else { + info.status = .Deny + } + commonds.append(info) + } + if commonds.count > 0 { + print("commonds : ", commonds) + print("commonds count :", commonds.count) + param.commands = commonds + } */ + + weak var weakSelf = self + viewmodel.repo.updateRole(param) { error, role in + if let err = error { + weakSelf?.showToast(err.localizedDescription) + } else { + if let block = weakSelf?.completion { + block(role) + } + weakSelf?.showToastInWindow(localizable("update_channel_suscess")) + weakSelf?.navigationController?.popViewController(animated: true) } + } } } -extension QChatPermissionViewController{ - - func updatePermission(_ type: ChatPermissionType, _ open: Bool, _ completion: @escaping (Bool) -> Void){ - var param = UpdateServerRoleParam() - param.serverId = idGroup?.role?.serverId - if let rid = idGroup?.role?.roleId { - param.roleId = UInt64(rid) - } - - var commonds = [StatusInfo]() - var info = StatusInfo() - info.permissionType = type - info.status = open == true ? .Allow : .Deny - commonds.append(info) - param.commands = commonds - - weak var weakSelf = self - view.makeToastActivity(.center) - viewmodel.repo.updateRole(param) { error, role in - weakSelf?.view.hideToastActivity() - if let err = error { - weakSelf?.showToast(err.localizedDescription) - completion(false) - }else { - if let block = weakSelf?.completion { - completion(true) - block(role) - } - } - } + + +extension QChatPermissionViewController { + func updatePermission(_ type: ChatPermissionType, _ open: Bool, + _ completion: @escaping (Bool) -> Void) { + var param = UpdateServerRoleParam() + param.serverId = idGroup?.role?.serverId + if let rid = idGroup?.role?.roleId { + param.roleId = UInt64(rid) } - - @objc func savePermission(){ - - if serverName.count <= 0 { - showToast(localizable("qchat_please_input_role_name")) - return - } - var param = UpdateServerRoleParam() - param.serverId = idGroup?.role?.serverId - if let rid = idGroup?.role?.roleId { - param.roleId = UInt64(rid) - } - param.name = serverName - - /* 批量逻辑,暂时不用 - let permissions = viewmodel.permission.getChangePermission() - var commonds = [StatusInfo]() - - permissions.forEach { (type: ChatPermissionType, value: Bool) in - var info = StatusInfo() - info.permissionType = type - if value == true { - info.status = .Allow - }else { - info.status = .Deny - } - commonds.append(info) - } - if commonds.count > 0 { - print("commonds : ", commonds) - print("commonds count :", commonds.count) - param.commands = commonds - } */ - - weak var weakSelf = self - viewmodel.repo.updateRole(param) { error, role in - if let err = error { - weakSelf?.showToast(err.localizedDescription) - }else { - if let block = weakSelf?.completion { - block(role) - } - weakSelf?.showToastInWindow(localizable("update_channel_suscess")) - weakSelf?.navigationController?.popViewController(animated: true) - } + + var commonds = [StatusInfo]() + var info = StatusInfo() + info.permissionType = type + info.status = open == true ? .Allow : .Deny + commonds.append(info) + param.commands = commonds + + weak var weakSelf = self + view.makeToastActivity(.center) + viewmodel.repo.updateRole(param) { error, role in + weakSelf?.view.hideToastActivity() + if let err = error { + weakSelf?.showToast(err.localizedDescription) + completion(false) + } else { + if let block = weakSelf?.completion { + completion(true) + block(role) } + } } + } + + } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewController/QChatServerSettingViewController.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewController/QChatServerSettingViewController.swift index c14f3ba3..5af9670b 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewController/QChatServerSettingViewController.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewController/QChatServerSettingViewController.swift @@ -1,482 +1,493 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCore import NEKitCoreIM import NIMSDK - typealias SaveSuccessBlock = (_ server: QChatServer?) -> Void -public class QChatServerSettingViewController: NEBaseTableViewController { - - let viewModel = SettingViewModel() - var server: QChatServer? - - var headerImageUrl: String? - - var headerImage: NEUserHeaderView? - - lazy var serverNameInput: UITextField = { - return getInput() - }() - - lazy var serverThemeInput: UITextField = { - return getInput() - }() - - var topicInput: UITextField? - - lazy var serverName: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.font = UIFont.systemFont(ofSize: 16.0) - label.textColor = .ne_darkText - return label - }() - - public override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - navigationController?.navigationBar.isHidden = false - } - - - public override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - - NELog.infoLog(className(), desc: "server id : \(server?.serverId ?? 0)" ) - - setupUI() - addRightAction(localizable("save"), #selector(saveClick), self) - - } - - func setupUI(){ - title = localizable("qchat_setting") - view.backgroundColor = .ne_backcolor - setupTable() - tableView.bounces = false - tableView.tableHeaderView = headerView() - tableView.register(QChatTextArrowCell.self, forCellReuseIdentifier: "\(QChatTextArrowCell.self)") - tableView.register(QChatDestructiveCell.self, forCellReuseIdentifier: "\(QChatDestructiveCell.self)") - tableView.delegate = self - tableView.dataSource = self - } - - func headerView() -> UIView { - let headerBack = UIView() - headerBack.frame = CGRect(x: 0, y: 0, width: view.frame.size.width, height: 334) - headerBack.backgroundColor = .clear - - let cornerView = UIView() - cornerView.translatesAutoresizingMaskIntoConstraints = false - headerBack.addSubview(cornerView) - NSLayoutConstraint.activate([ - cornerView.topAnchor.constraint(equalTo: headerBack.topAnchor, constant: 22), - cornerView.leftAnchor.constraint(equalTo: headerBack.leftAnchor, constant: 20), - cornerView.rightAnchor.constraint(equalTo: headerBack.rightAnchor, constant: -20), - cornerView.heightAnchor.constraint(equalToConstant: 98) - ]) - cornerView.clipsToBounds = true - cornerView.layer.cornerRadius = 8 - cornerView.backgroundColor = .white - - let header = NEUserHeaderView(frame: .zero) - header.translatesAutoresizingMaskIntoConstraints = false - cornerView.addSubview(header) - NSLayoutConstraint.activate([ - header.widthAnchor.constraint(equalToConstant: 60), - header.heightAnchor.constraint(equalToConstant: 60), - header.leftAnchor.constraint(equalTo: cornerView.leftAnchor, constant: 16), - header.topAnchor.constraint(equalTo: cornerView.topAnchor, constant: 16) - ]) - header.isUserInteractionEnabled = true - header.clipsToBounds = true - header.backgroundColor = UIColor.colorWithNumber(number: server?.serverId) - header.layer.cornerRadius = 30 - headerImage = header - if let icon = server?.icon { - header.sd_setImage(with: URL(string: icon), completed: nil) - }else { - if let name = server?.name { - header.setTitle(name) - } - } - - let cameraBtn = ExpandButton() - cornerView.addSubview(cameraBtn) - cameraBtn.translatesAutoresizingMaskIntoConstraints = false - cameraBtn.backgroundColor = .ne_backcolor - NSLayoutConstraint.activate([ - cameraBtn.leftAnchor.constraint(equalTo: cornerView.leftAnchor, constant: 58), - cameraBtn.topAnchor.constraint(equalTo: cornerView.topAnchor, constant: 58), - cameraBtn.widthAnchor.constraint(equalToConstant: 26), - cameraBtn.heightAnchor.constraint(equalToConstant: 26) - ]) - cameraBtn.layer.cornerRadius = 12 - cameraBtn.clipsToBounds = true - cameraBtn.layer.borderColor = UIColor.white.cgColor - cameraBtn.layer.borderWidth = 2 - cameraBtn.addTarget(self, action: #selector(cameraClick), for: .touchUpInside) - - let camera = UIImageView() - camera.translatesAutoresizingMaskIntoConstraints = false - cornerView.addSubview(camera) - camera.backgroundColor = .clear - camera.image = coreLoader.loadImage("camera") - NSLayoutConstraint.activate([ - camera.centerXAnchor.constraint(equalTo: cameraBtn.centerXAnchor), - camera.centerYAnchor.constraint(equalTo: cameraBtn.centerYAnchor, constant: -2) - ]) - - cornerView.addSubview(serverName) - NSLayoutConstraint.activate([ - serverName.leftAnchor.constraint(equalTo: header.rightAnchor, constant: 16), - serverName.rightAnchor.constraint(equalTo: cornerView.rightAnchor, constant: -16), - serverName.topAnchor.constraint(equalTo: cornerView.topAnchor, constant: 30) - ]) - serverName.text = server?.name - - let account = UILabel() - account.translatesAutoresizingMaskIntoConstraints = false - account.textColor = UIColor.ne_emptyTitleColor - account.font = UIFont.systemFont(ofSize: 12) - cornerView.addSubview(account) - NSLayoutConstraint.activate([ - account.leftAnchor.constraint(equalTo: serverName.leftAnchor), - account.rightAnchor.constraint(equalTo: serverName.rightAnchor), - account.topAnchor.constraint(equalTo: serverName.bottomAnchor, constant: 6) - ]) - account.text = "ID: \(server?.serverId ?? 0)" - - addInputView(headerBack, cornerView) - - return headerBack - } - - func addInputView(_ back: UIView, _ topView: UIView){ - - let serverNameLabel = getTagLabel() - back.addSubview(serverNameLabel) - NSLayoutConstraint.activate([ - serverNameLabel.leftAnchor.constraint(equalTo: back.leftAnchor, constant: 33), - serverNameLabel.topAnchor.constraint(equalTo: topView.bottomAnchor, constant: 16.0), - ]) - serverNameLabel.text = localizable("qchat_server_name") - - - back.addSubview(serverNameInput) - NSLayoutConstraint.activate([ - serverNameInput.leftAnchor.constraint(equalTo: back.leftAnchor, constant: 20), - serverNameInput.rightAnchor.constraint(equalTo: back.rightAnchor, constant: -20), - serverNameInput.topAnchor.constraint(equalTo: topView.bottomAnchor, constant: 38), - serverNameInput.heightAnchor.constraint(equalToConstant: 50) - ]) - serverNameInput.placeholder = "输入名称" - serverNameInput.tag = 50 - if let name = server?.name { - serverNameInput.text = name - } - - let serverThemeLabel = getTagLabel() - back.addSubview(serverThemeLabel) - NSLayoutConstraint.activate([ - serverThemeLabel.leftAnchor.constraint(equalTo: serverNameLabel.leftAnchor), - serverThemeLabel.topAnchor.constraint(equalTo: serverNameInput.bottomAnchor, constant: 16), - ]) - serverThemeLabel.text = localizable("qchat_server_theme") - - back.addSubview(serverThemeInput) - NSLayoutConstraint.activate([ - serverThemeInput.leftAnchor.constraint(equalTo: back.leftAnchor, constant: 20), - serverThemeInput.rightAnchor.constraint(equalTo: back.rightAnchor, constant: -20), - serverThemeInput.topAnchor.constraint(equalTo: serverNameInput.bottomAnchor, constant: 38), - serverThemeInput.heightAnchor.constraint(equalToConstant: 50) - ]) - serverThemeInput.placeholder = localizable("qchat_please_input_topic") - if let custom = server?.custom, let dic = getDictionaryFromJSONString(custom), let topic = dic["topic"] as? String{ - serverThemeInput.text = topic - } - serverThemeInput.tag = 64 - - let permissionLabel = getTagLabel() - back.addSubview(permissionLabel) - NSLayoutConstraint.activate([ - permissionLabel.leftAnchor.constraint(equalTo: serverThemeLabel.leftAnchor), - permissionLabel.topAnchor.constraint(equalTo: serverThemeInput.bottomAnchor, constant: 16) - ]) - permissionLabel.text = localizable("qchat_permisssion") - +public class QChatServerSettingViewController: NEBaseTableViewController,UITableViewDelegate, UITableViewDataSource,UITextFieldDelegate,UINavigationControllerDelegate { + let viewModel = SettingViewModel() + var server: QChatServer? + + var headerImageUrl: String? + + var headerImage: NEUserHeaderView? + + lazy var serverNameInput: UITextField = getInput() + + lazy var serverThemeInput: UITextField = getInput() + + var topicInput: UITextField? + + lazy var serverName: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.font = UIFont.systemFont(ofSize: 16.0) + label.textColor = .ne_darkText + return label + }() + + override public func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + navigationController?.navigationBar.isHidden = false + } + + override public func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + + NELog.infoLog(className(), desc: "server id : \(server?.serverId ?? 0)") + + setupUI() + addRightAction(localizable("save"), #selector(saveClick), self) + } + + func setupUI() { + title = localizable("qchat_setting") + view.backgroundColor = .ne_backcolor + setupTable() + tableView.bounces = false + tableView.tableHeaderView = headerView() + tableView.register( + QChatTextArrowCell.self, + forCellReuseIdentifier: "\(QChatTextArrowCell.self)" + ) + tableView.register( + QChatDestructiveCell.self, + forCellReuseIdentifier: "\(QChatDestructiveCell.self)" + ) + tableView.delegate = self + tableView.dataSource = self + } + + func headerView() -> UIView { + let headerBack = UIView() + headerBack.frame = CGRect(x: 0, y: 0, width: view.frame.size.width, height: 334) + headerBack.backgroundColor = .clear + + let cornerView = UIView() + cornerView.translatesAutoresizingMaskIntoConstraints = false + headerBack.addSubview(cornerView) + NSLayoutConstraint.activate([ + cornerView.topAnchor.constraint(equalTo: headerBack.topAnchor, constant: 22), + cornerView.leftAnchor.constraint(equalTo: headerBack.leftAnchor, constant: 20), + cornerView.rightAnchor.constraint(equalTo: headerBack.rightAnchor, constant: -20), + cornerView.heightAnchor.constraint(equalToConstant: 98), + ]) + cornerView.clipsToBounds = true + cornerView.layer.cornerRadius = 8 + cornerView.backgroundColor = .white + + let header = NEUserHeaderView(frame: .zero) + header.translatesAutoresizingMaskIntoConstraints = false + cornerView.addSubview(header) + NSLayoutConstraint.activate([ + header.widthAnchor.constraint(equalToConstant: 60), + header.heightAnchor.constraint(equalToConstant: 60), + header.leftAnchor.constraint(equalTo: cornerView.leftAnchor, constant: 16), + header.topAnchor.constraint(equalTo: cornerView.topAnchor, constant: 16), + ]) + header.isUserInteractionEnabled = true + header.clipsToBounds = true + header.backgroundColor = UIColor.colorWithNumber(number: server?.serverId) + header.layer.cornerRadius = 30 + headerImage = header + if let icon = server?.icon { + header.sd_setImage(with: URL(string: icon), completed: nil) + } else { + if let name = server?.name { + header.setTitle(name) + } } - - func getTagLabel() -> UILabel { - let label = UILabel() - label.textColor = UIColor(hexString: "666666") - label.font = UIFont.systemFont(ofSize: 12.0) - label.translatesAutoresizingMaskIntoConstraints = false - label.textAlignment = .left - return label + + let cameraBtn = ExpandButton() + cornerView.addSubview(cameraBtn) + cameraBtn.translatesAutoresizingMaskIntoConstraints = false + cameraBtn.backgroundColor = .ne_backcolor + NSLayoutConstraint.activate([ + cameraBtn.leftAnchor.constraint(equalTo: cornerView.leftAnchor, constant: 58), + cameraBtn.topAnchor.constraint(equalTo: cornerView.topAnchor, constant: 58), + cameraBtn.widthAnchor.constraint(equalToConstant: 26), + cameraBtn.heightAnchor.constraint(equalToConstant: 26), + ]) + cameraBtn.layer.cornerRadius = 12 + cameraBtn.clipsToBounds = true + cameraBtn.layer.borderColor = UIColor.white.cgColor + cameraBtn.layer.borderWidth = 2 + cameraBtn.addTarget(self, action: #selector(cameraClick), for: .touchUpInside) + + let camera = UIImageView() + camera.translatesAutoresizingMaskIntoConstraints = false + cornerView.addSubview(camera) + camera.backgroundColor = .clear + camera.image = coreLoader.loadImage("camera") + NSLayoutConstraint.activate([ + camera.centerXAnchor.constraint(equalTo: cameraBtn.centerXAnchor), + camera.centerYAnchor.constraint(equalTo: cameraBtn.centerYAnchor, constant: -2), + ]) + + cornerView.addSubview(serverName) + NSLayoutConstraint.activate([ + serverName.leftAnchor.constraint(equalTo: header.rightAnchor, constant: 16), + serverName.rightAnchor.constraint(equalTo: cornerView.rightAnchor, constant: -16), + serverName.topAnchor.constraint(equalTo: cornerView.topAnchor, constant: 30), + ]) + serverName.text = server?.name + + let account = UILabel() + account.translatesAutoresizingMaskIntoConstraints = false + account.textColor = UIColor.ne_emptyTitleColor + account.font = UIFont.systemFont(ofSize: 12) + cornerView.addSubview(account) + NSLayoutConstraint.activate([ + account.leftAnchor.constraint(equalTo: serverName.leftAnchor), + account.rightAnchor.constraint(equalTo: serverName.rightAnchor), + account.topAnchor.constraint(equalTo: serverName.bottomAnchor, constant: 6), + ]) + account.text = "ID: \(server?.serverId ?? 0)" + + addInputView(headerBack, cornerView) + + return headerBack + } + + func addInputView(_ back: UIView, _ topView: UIView) { + let serverNameLabel = getTagLabel() + back.addSubview(serverNameLabel) + NSLayoutConstraint.activate([ + serverNameLabel.leftAnchor.constraint(equalTo: back.leftAnchor, constant: 33), + serverNameLabel.topAnchor.constraint(equalTo: topView.bottomAnchor, constant: 16.0), + ]) + serverNameLabel.text = localizable("qchat_server_name") + + back.addSubview(serverNameInput) + NSLayoutConstraint.activate([ + serverNameInput.leftAnchor.constraint(equalTo: back.leftAnchor, constant: 20), + serverNameInput.rightAnchor.constraint(equalTo: back.rightAnchor, constant: -20), + serverNameInput.topAnchor.constraint(equalTo: topView.bottomAnchor, constant: 38), + serverNameInput.heightAnchor.constraint(equalToConstant: 50), + ]) + serverNameInput.placeholder = "输入名称" + serverNameInput.tag = 50 + if let name = server?.name { + serverNameInput.text = name } - - func getInput() -> UITextField { - let textField = UITextField() - textField.backgroundColor = .white - textField.clipsToBounds = true - textField.layer.cornerRadius = 8 - textField.font = UIFont.systemFont(ofSize: 16.0) - textField.translatesAutoresizingMaskIntoConstraints = false - let leftSpace = UIView(frame: CGRect(x: 0, y: 0, width: 20, height: 0)) - textField.leftView = leftSpace - textField.leftViewMode = .always - textField.delegate = self - return textField + + let serverThemeLabel = getTagLabel() + back.addSubview(serverThemeLabel) + NSLayoutConstraint.activate([ + serverThemeLabel.leftAnchor.constraint(equalTo: serverNameLabel.leftAnchor), + serverThemeLabel.topAnchor.constraint( + equalTo: serverNameInput.bottomAnchor, + constant: 16 + ), + ]) + serverThemeLabel.text = localizable("qchat_server_theme") + + back.addSubview(serverThemeInput) + NSLayoutConstraint.activate([ + serverThemeInput.leftAnchor.constraint(equalTo: back.leftAnchor, constant: 20), + serverThemeInput.rightAnchor.constraint(equalTo: back.rightAnchor, constant: -20), + serverThemeInput.topAnchor.constraint( + equalTo: serverNameInput.bottomAnchor, + constant: 38 + ), + serverThemeInput.heightAnchor.constraint(equalToConstant: 50), + ]) + serverThemeInput.placeholder = localizable("qchat_please_input_topic") + if let custom = server?.custom, let dic = getDictionaryFromJSONString(custom), + let topic = dic["topic"] as? String { + serverThemeInput.text = topic } -} + serverThemeInput.tag = 64 + let permissionLabel = getTagLabel() + back.addSubview(permissionLabel) + NSLayoutConstraint.activate([ + permissionLabel.leftAnchor.constraint(equalTo: serverThemeLabel.leftAnchor), + permissionLabel.topAnchor.constraint( + equalTo: serverThemeInput.bottomAnchor, + constant: 16 + ), + ]) + permissionLabel.text = localizable("qchat_permisssion") + } -extension QChatServerSettingViewController { + func getTagLabel() -> UILabel { + let label = UILabel() + label.textColor = UIColor(hexString: "666666") + label.font = UIFont.systemFont(ofSize: 12.0) + label.translatesAutoresizingMaskIntoConstraints = false + label.textAlignment = .left + return label + } + + func getInput() -> UITextField { + let textField = UITextField() + textField.backgroundColor = .white + textField.clipsToBounds = true + textField.layer.cornerRadius = 8 + textField.font = UIFont.systemFont(ofSize: 16.0) + textField.translatesAutoresizingMaskIntoConstraints = false + let leftSpace = UIView(frame: CGRect(x: 0, y: 0, width: 20, height: 0)) + textField.leftView = leftSpace + textField.leftViewMode = .always + textField.delegate = self + return textField + } // MARK: action - @objc func cameraClick(){ - //print("camera click") - showBottomAlert(self) + @objc func cameraClick() { + // print("camera click") + showBottomAlert(self) } - - @objc func saveClick(){ - print("save click") - - var name = "" - - if let currentName = serverNameInput.text, currentName.count > 0 { - name = currentName - }else if let originServerName = server?.name, originServerName.count > 0 { - name = originServerName - } - - if name.count <= 0 { - showToast(localizable("qchat_not_empty_servername")) - return - } - if let icon = headerImageUrl { - server?.icon = icon - } + @objc func saveClick() { + print("save click") - var serverParam = UpdateServerParam(name: name, icon: headerImageUrl) - - guard let sid = server?.serverId else { - showToast("服务器id不能为空") - return - } - serverParam.serverId = sid - - if let topic = serverThemeInput.text, topic.count > 0 { - serverParam.custom = getJSONStringFromDictionary(["topic":topic]) + var name = "" + + if let currentName = serverNameInput.text, currentName.count > 0 { + name = currentName + } else if let originServerName = server?.name, originServerName.count > 0 { + name = originServerName + } + + if name.count <= 0 { + showToast(localizable("qchat_not_empty_servername")) + return + } + + if let icon = headerImageUrl { + server?.icon = icon + } + + var serverParam = UpdateServerParam(name: name, icon: headerImageUrl) + + guard let sid = server?.serverId else { + showToast("服务器id不能为空") + return + } + serverParam.serverId = sid + + if let topic = serverThemeInput.text, topic.count > 0 { + serverParam.custom = getJSONStringFromDictionary(["topic": topic]) + } + weak var weakSelf = self + + view.makeToastActivity(.center) + print("update param : ", serverParam) + QChatServerProvider.shared.updateServer(serverParam) { error in + print("update finish : ", error as Any) + weakSelf?.view.hideToastActivity() + if let err = error { + weakSelf?.showToast(err.localizedDescription) + } else { + weakSelf?.navigationController?.popViewController(animated: true) } + } + } + + func leaveServer() { + if let serverid = server?.serverId { weak var weakSelf = self - - view.makeToastActivity(.center) - print("update param : ", serverParam) - QChatServerProvider.shared.updateServer(serverParam) { error in - print("update finish : ", error as Any) - weakSelf?.view.hideToastActivity() - if let err = error { - weakSelf?.showToast(err.localizedDescription) - }else { - weakSelf?.navigationController?.popViewController(animated: true) - } + let className = className() + viewModel.repo.leaveServer(serverid) { error in + weakSelf?.view.hideToastActivity() + if let err = error { + NELog.errorLog(className, desc: "leave server error : \(err)") + weakSelf?.view.makeToast(err.localizedDescription) + } else { + weakSelf?.navigationController?.popViewController(animated: true) + } } + } } - - func leaveServer(){ - if let serverid = server?.serverId { - weak var weakSelf = self - view.makeToastActivity(.center) - let className = className() - viewModel.repo.leaveServer(serverid) { error in - weakSelf?.view.hideToastActivity() - if let err = error { - NELog.errorLog(className, desc: "leave server error : \(err)") - weakSelf?.view.makeToast(err.localizedDescription) - }else { - weakSelf?.navigationController?.popViewController(animated: true) - } - } + + func deleteServer() { + if let serverid = server?.serverId { + weak var weakSelf = self + view.makeToastActivity(.center) + QChatServerProvider.shared.deleteServer(serverid) { error in + print("delete result : ", error as Any) + weakSelf?.view.hideToastActivity() + if let err = error { + weakSelf?.view.makeToast(err.localizedDescription) + } else { + weakSelf?.navigationController?.popViewController(animated: true) + } } + } } + //MARK: UITableViewDelegate, UITableViewDataSource,UITextFieldDelegate - func deleteServer(){ - - if let serverid = server?.serverId { - weak var weakSelf = self - view.makeToastActivity(.center) - QChatServerProvider.shared.deleteServer(serverid) { error in - print("delete result : ", error as Any) - weakSelf?.view.hideToastActivity() - if let err = error { - weakSelf?.view.makeToast(err.localizedDescription) - }else { - weakSelf?.navigationController?.popViewController(animated: true) - } - } - } - + public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, + replacementString string: String) -> Bool { + let l = textField.tag + let text = "\(textField.text ?? "")\(string)" + print("count : ", text.count) + if text.count > l { + return false + } + return true } - -} -extension QChatServerSettingViewController: UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate { - - public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { - let l = textField.tag - let text = "\(textField.text ?? "")\(string)" - print("count : ", text.count) - if text.count > l { - return false - } - return true - } - public func numberOfSections(in tableView: UITableView) -> Int { - return 2 + 2 } - + public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - print("count section : ", section) - if section == 0 { - return viewModel.permissions.count - } else if section == 1 { - return 1 - } - return 0 + print("count section : ", section) + if section == 0 { + return viewModel.permissions.count + } else if section == 1 { + return 1 + } + return 0 } - - public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - - if indexPath.section == 0 { - let textCell: QChatTextArrowCell = tableView.dequeueReusableCell(withIdentifier: "\(QChatTextArrowCell.self)", for: indexPath) as! QChatTextArrowCell - let model = viewModel.permissions[indexPath.row] - textCell.titleLabel.text = model.title - textCell.backgroundColor = .clear - textCell.cornerType = model.cornerType - return textCell - }else if indexPath.section == 1 { - let destructiveCell: QChatDestructiveCell = tableView.dequeueReusableCell(withIdentifier: "\(QChatDestructiveCell.self)", for: indexPath) as! QChatDestructiveCell - - destructiveCell.redTextLabel.text = isMyServer() ? localizable("qchat_delete_server") : localizable("qchat_leave_server") - destructiveCell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight).union(CornerType.topLeft).union(CornerType.topRight) - return destructiveCell - } - - return UITableViewCell() + + public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + if indexPath.section == 0 { + let textCell: QChatTextArrowCell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatTextArrowCell.self)", + for: indexPath + ) as! QChatTextArrowCell + let model = viewModel.permissions[indexPath.row] + textCell.titleLabel.text = model.title + textCell.backgroundColor = .clear + textCell.cornerType = model.cornerType + return textCell + } else if indexPath.section == 1 { + let destructiveCell: QChatDestructiveCell = tableView.dequeueReusableCell( + withIdentifier: "\(QChatDestructiveCell.self)", + for: indexPath + ) as! QChatDestructiveCell + + destructiveCell.redTextLabel + .text = isMyServer() ? localizable("qchat_delete_server") : + localizable("qchat_leave_server") + destructiveCell.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) + .union(CornerType.topLeft).union(CornerType.topRight) + return destructiveCell + } + + return UITableViewCell() } - + public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - if indexPath.section == 0 { - - if indexPath.row == 1 { - - let idGroupController = QChatIdGroupViewController() - idGroupController.serverid = server?.serverId - if let owner = server?.owner, owner == IMKitLoginManager.instance.imAccid { - idGroupController.isOwner = true - } - navigationController?.pushViewController(idGroupController, animated: true) - - }else if indexPath.row == 0 { - let memberCtrl = MemberListViewController() - memberCtrl.serverId = server?.serverId - navigationController?.pushViewController(memberCtrl, animated: true) - } - - }else if indexPath.section == 1 { - print("click delete") - weak var weakSelf = self - if isMyServer() == true { - showAlert(message:"确定删除当前服务器?") { - weakSelf?.deleteServer() - } - }else { - showAlert(message: "确定退出当前服务器?") { - weakSelf?.leaveServer() - } - } + if indexPath.section == 0 { + if indexPath.row == 1 { + let idGroupController = QChatIdGroupViewController() + idGroupController.serverid = server?.serverId + if let owner = server?.owner, owner == IMKitLoginManager.instance.imAccid { + idGroupController.isOwner = true + } + navigationController?.pushViewController(idGroupController, animated: true) + + } else if indexPath.row == 0 { + let memberCtrl = MemberListViewController() + memberCtrl.serverId = server?.serverId + navigationController?.pushViewController(memberCtrl, animated: true) } - } - - public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - if indexPath.section == 0 { - return 48 - }else if indexPath.section == 1 { - return 40 + + } else if indexPath.section == 1 { + print("click delete") + weak var weakSelf = self + if isMyServer() == true { + showAlert(message: "确定删除当前服务器?") { + weakSelf?.deleteServer() + } + } else { + showAlert(message: "确定退出当前服务器?") { + weakSelf?.leaveServer() + } } - return 0 + } } - - public func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { - if section == 1 { - return UIView(frame: CGRect(x: 0, y: 0, width: view.frame.size.width, height: 24)) - } - return nil + + public func tableView(_ tableView: UITableView, + heightForRowAt indexPath: IndexPath) -> CGFloat { + if indexPath.section == 0 { + return 48 + } else if indexPath.section == 1 { + return 40 + } + return 0 } - - public func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { - if section == 1 { - return 24 - } - return 0 + + public func tableView(_ tableView: UITableView, + viewForHeaderInSection section: Int) -> UIView? { + if section == 1 { + return UIView(frame: CGRect(x: 0, y: 0, width: view.frame.size.width, height: 24)) + } + return nil } - - public func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { - return 0 + + public func tableView(_ tableView: UITableView, + heightForHeaderInSection section: Int) -> CGFloat { + if section == 1 { + return 24 + } + return 0 } - - func isMyServer() -> Bool{ - if let owner = server?.owner { - let accid = IMKitLoginManager.instance.imAccid - if owner == accid { - return true - } - } - return false + + public func tableView(_ tableView: UITableView, + heightForFooterInSection section: Int) -> CGFloat { + 0 } -} -extension QChatServerSettingViewController: UINavigationControllerDelegate { - - func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info:[UIImagePickerController.InfoKey : Any]) { - let image : UIImage = info[UIImagePickerController.InfoKey.editedImage] as! UIImage - uploadHeadImage(image: image) - picker.dismiss(animated: true, completion: nil) + func isMyServer() -> Bool { + if let owner = server?.owner { + let accid = IMKitLoginManager.instance.imAccid + if owner == accid { + return true + } + } + return false } - public func uploadHeadImage(image:UIImage){ - - view.makeToastActivity(.center) - if let imageData = image.jpegData(compressionQuality: 0.6) as NSData? { - let filePath = NSHomeDirectory().appending("/Documents/").appending(IMKitLoginManager.instance.imAccid) - let succcess = imageData.write(toFile: filePath, atomically: true) - weak var weakSelf = self - if succcess { - NIMSDK.shared().resourceManager.upload(filePath, progress: nil) { urlString, error in - if error == nil { - //显示设置的照片 - weakSelf?.headerImage?.image = image - weakSelf?.headerImageUrl = urlString - weakSelf?.headerImage?.titleLabel.isHidden = true - print("upload image success") - }else { - print("upload image failed,error = \(error!)") - } - weakSelf?.view.hideToastActivity() - - } + //UINavigationControllerDelegate + func imagePickerController(_ picker: UIImagePickerController, + didFinishPickingMediaWithInfo info: [UIImagePickerController + .InfoKey: Any]) { + let image: UIImage = info[UIImagePickerController.InfoKey.editedImage] as! UIImage + uploadHeadImage(image: image) + picker.dismiss(animated: true, completion: nil) + } + + public func uploadHeadImage(image: UIImage) { + view.makeToastActivity(.center) + if let imageData = image.jpegData(compressionQuality: 0.6) as NSData? { + let filePath = NSHomeDirectory().appending("/Documents/") + .appending(IMKitLoginManager.instance.imAccid) + let succcess = imageData.write(toFile: filePath, atomically: true) + weak var weakSelf = self + if succcess { + NIMSDK.shared().resourceManager + .upload(filePath, progress: nil) { urlString, error in + if error == nil { + // 显示设置的照片 + weakSelf?.headerImage?.image = image + weakSelf?.headerImageUrl = urlString + weakSelf?.headerImage?.titleLabel.isHidden = true + print("upload image success") + } else { + print("upload image failed,error = \(error!)") + } + weakSelf?.view.hideToastActivity() } } + } } } + + + diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewModel/CreateGroupViewModel.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewModel/CreateGroupViewModel.swift index 47b235e5..ebc04013 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewModel/CreateGroupViewModel.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewModel/CreateGroupViewModel.swift @@ -1,96 +1,95 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NEKitQChat import NEKitCoreIM class CreateGroupViewModel { - // var limit = 7 - + // var limitUsers = [UserInfo]() - var allUsers = [UserInfo]() - let repo = QChatRepo() - - weak var delegate: ViewModelDelegate? - - init(){} - - func loadAllData(){ + var allUsers = [UserInfo]() + let repo = QChatRepo() + + weak var delegate: ViewModelDelegate? + + init() {} + + func loadAllData() { // limitUsers.removeAll() // limitUsers.append(contentsOf: allUsers) - } - - private func addUser(_ user: UserInfo){ - allUsers.append(user) + } + + private func addUser(_ user: UserInfo) { + allUsers.append(user) // if limitUsers.count <= limit { // limitUsers.append(user) // } + } + + func addNewUser(_ user: UserInfo) { + addUser(user) + filterData() + } + + func filterData() { + allUsers.forEach { user in + user.cornerType = .none } - - func addNewUser(_ user: UserInfo){ - addUser(user) - filterData() + if allUsers.count == 1, let first = allUsers.first { + first.cornerType = CornerType.topLeft.union(CornerType.topRight).union(.bottomLeft) + .union(.bottomRight) } - - func filterData(){ - allUsers.forEach { user in - user.cornerType = .none - } - if allUsers.count == 1, let first = allUsers.first { - first.cornerType = CornerType.topLeft.union(CornerType.topRight).union(.bottomLeft).union(.bottomRight) - } - - if allUsers.count > 1 , let first = allUsers.first, let last = allUsers.last { - first.cornerType = .topLeft.union(.topRight) - last.cornerType = .bottomLeft.union(.bottomRight) - } - - /* - if limitUsers.count < limit { - if let last = limitUsers.last { - if limitUsers.count == 1 { - last.cornerType = CornerType.topLeft.union(CornerType.topRight).union(CornerType.bottomLeft).union(CornerType.bottomRight) - }else { - last.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) - } - } - }else { - if let last = limitUsers.last { - last.cornerType = .none - } - } */ - - delegate?.dataDidChange() - } - - func removeData(_ index: Int){ - allUsers.remove(at: index) - filterData() - delegate?.dataDidChange() + + if allUsers.count > 1, let first = allUsers.first, let last = allUsers.last { + first.cornerType = .topLeft.union(.topRight) + last.cornerType = .bottomLeft.union(.bottomRight) } - - func addMembers(_ members: [UserInfo]){ - - members.forEach { user in - if allUsers.contains(where: { lUser in - if let cid = lUser.serverMember?.accid, let mid = user.serverMember?.accid { - if cid == mid { - return true - } - } - return false - }) == false { - addUser(user) - } + + /* + if limitUsers.count < limit { + if let last = limitUsers.last { + if limitUsers.count == 1 { + last.cornerType = CornerType.topLeft.union(CornerType.topRight).union(CornerType.bottomLeft).union(CornerType.bottomRight) + }else { + last.cornerType = CornerType.bottomLeft.union(CornerType.bottomRight) + } + } + }else { + if let last = limitUsers.last { + last.cornerType = .none + } + } */ + + delegate?.dataDidChange() + } + + func removeData(_ index: Int) { + allUsers.remove(at: index) + filterData() + delegate?.dataDidChange() + } + + func addMembers(_ members: [UserInfo]) { + members.forEach { user in + if allUsers.contains(where: { lUser in + if let cid = lUser.serverMember?.accid, let mid = user.serverMember?.accid { + if cid == mid { + return true + } } - filterData() - } - - func removeMember(_ member: UserInfo){ - - delegate?.dataDidChange() + return false + }) == false { + addUser(user) + } } + filterData() + } + + func removeMember(_ member: UserInfo) { + delegate?.dataDidChange() + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewModel/EditMemberViewModel.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewModel/EditMemberViewModel.swift index cd121a23..0d134c7a 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewModel/EditMemberViewModel.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewModel/EditMemberViewModel.swift @@ -1,215 +1,218 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NEKitCoreIM import NEKitQChat -class EditMemberViewModel { - - var limitIdGroups = [IdGroupModel]() - var allIdGroups = [IdGroupModel]() - - var serverRoles = [ServerRole]() - var userRoles = [ServerRole]() - - var userDic = [UInt64 : IdGroupModel]() - var serverDic = [UInt64 : IdGroupModel]() - - var delegate: ViewModelDelegate? - - let repo = QChatRepo() - - var limit = 5 - - init(){} - - func checkoutCurrentUserRole(_ roleId: UInt64? ) -> Bool { - if let rid = roleId { - if userDic[rid] != nil { - return true - } - } - return false +class EditMemberViewModel { + var limitIdGroups = [IdGroupModel]() + var allIdGroups = [IdGroupModel]() + + var serverRoles = [ServerRole]() + var userRoles = [ServerRole]() + + var userDic = [UInt64: IdGroupModel]() + var serverDic = [UInt64: IdGroupModel]() + + var delegate: ViewModelDelegate? + + let repo = QChatRepo() + + var limit = 5 + + init() {} + + func checkoutCurrentUserRole(_ roleId: UInt64?) -> Bool { + if let rid = roleId { + if userDic[rid] != nil { + return true + } } - - func showServerData(){ - limitIdGroups.removeAll() - allIdGroups.removeAll() - serverRoles.forEach { role in - if let roleId = role.roleId { - if let model = self.serverDic[roleId] { - self.allIdGroups.append(model) - } - } - } - allIdGroups.first?.cornerType = .topLeft.union(.topRight) - if allIdGroups.count > limit { - limitIdGroups.append(contentsOf: allIdGroups.prefix(limit)) - }else { - limitIdGroups.append(contentsOf: allIdGroups) - if let last = limitIdGroups.last { - last.cornerType = last.cornerType.union(.bottomLeft).union(.bottomRight) - } + return false + } + + func showServerData() { + limitIdGroups.removeAll() + allIdGroups.removeAll() + serverRoles.forEach { role in + if let roleId = role.roleId { + if let model = self.serverDic[roleId] { + self.allIdGroups.append(model) } - delegate?.dataDidChange() + } } - - func filterAllRoles(){ - let serverModels = getRoleModel(serverRoles, nil) - serverModels.forEach { idModel in - if let roleId = idModel.role?.roleId { - self.serverDic[roleId] = idModel - } - } + allIdGroups.first?.cornerType = .topLeft.union(.topRight) + if allIdGroups.count > limit { + limitIdGroups.append(contentsOf: allIdGroups.prefix(limit)) + } else { + limitIdGroups.append(contentsOf: allIdGroups) + if let last = limitIdGroups.last { + last.cornerType = last.cornerType.union(.bottomLeft).union(.bottomRight) + } } - - func filterUserRoles(){ - allIdGroups.append(contentsOf: getRoleModel(userRoles, true)) - allIdGroups.first?.cornerType = .topLeft.union(.topRight) - if allIdGroups.count > limit { - limitIdGroups.append(contentsOf: allIdGroups.prefix(limit)) - }else { - limitIdGroups.append(contentsOf: allIdGroups) - if let last = limitIdGroups.last { - last.cornerType = last.cornerType.union(.bottomLeft).union(.bottomRight) - } - } - allIdGroups.forEach { idModel in - if let roleId = idModel.role?.roleId { - self.userDic[roleId] = idModel - } - } - delegate?.dataDidChange() + delegate?.dataDidChange() + } + + func filterAllRoles() { + let serverModels = getRoleModel(serverRoles, nil) + serverModels.forEach { idModel in + if let roleId = idModel.role?.roleId { + self.serverDic[roleId] = idModel + } + } + } + + func filterUserRoles() { + allIdGroups.append(contentsOf: getRoleModel(userRoles, true)) + allIdGroups.first?.cornerType = .topLeft.union(.topRight) + if allIdGroups.count > limit { + limitIdGroups.append(contentsOf: allIdGroups.prefix(limit)) + } else { + limitIdGroups.append(contentsOf: allIdGroups) + if let last = limitIdGroups.last { + last.cornerType = last.cornerType.union(.bottomLeft).union(.bottomRight) + } + } + allIdGroups.forEach { idModel in + if let roleId = idModel.role?.roleId { + self.userDic[roleId] = idModel + } } - - func getData(_ serverId: UInt64?, _ accid: String?){ - - weak var weakSelf = self - - var accidParam = GetServerRolesByAccIdParam(serverId: serverId, accid: accid) - accidParam.limit = 200 - accidParam.timeTag = 0 - repo.getServerRolesByAccId(param: accidParam) { error, roles in - if let err = error { - weakSelf?.delegate?.dataDidError(err) - }else { - print("edit member member role : ", roles as Any) - if let datas = roles { - weakSelf?.userRoles.append(contentsOf: datas) - weakSelf?.delegate?.dataDidChange() - weakSelf?.filterUserRoles() - } - } + delegate?.dataDidChange() + } + + func getData(_ serverId: UInt64?, _ accid: String?) { + weak var weakSelf = self + + var accidParam = GetServerRolesByAccIdParam(serverId: serverId, accid: accid) + accidParam.limit = 200 + accidParam.timeTag = 0 + repo.getServerRolesByAccId(param: accidParam) { error, roles in + if let err = error { + weakSelf?.delegate?.dataDidError(err) + } else { + print("edit member member role : ", roles as Any) + if let datas = roles { + weakSelf?.userRoles.append(contentsOf: datas) + weakSelf?.delegate?.dataDidChange() + weakSelf?.filterUserRoles() } - - var param = GetServerRoleParam() - param.limit = 200 - param.serverId = serverId - - repo.getRoles(param) { error, roles, sets in - if let err = error { - weakSelf?.delegate?.dataDidError(err) - }else { - print("edit member server roles : ", roles as Any) - if let datas = roles { - weakSelf?.serverRoles.append(contentsOf: datas) - weakSelf?.filterAllRoles() - } - } + } + } + + var param = GetServerRoleParam() + param.limit = 200 + param.serverId = serverId + + repo.getRoles(param) { error, roles, sets in + if let err = error { + weakSelf?.delegate?.dataDidError(err) + } else { + print("edit member server roles : ", roles as Any) + if let datas = roles { + weakSelf?.serverRoles.append(contentsOf: datas) + weakSelf?.filterAllRoles() } + } } - - func getRoleModel(_ roles: [ServerRole]?, _ select: Bool?) -> [IdGroupModel] { - var models = [IdGroupModel]() - roles?.forEach({ role in - let model = IdGroupModel(role) - if let s = select { - model.isSelect = s - } - models.append(model) - }) - return models + } + + func getRoleModel(_ roles: [ServerRole]?, _ select: Bool?) -> [IdGroupModel] { + var models = [IdGroupModel]() + roles?.forEach { role in + let model = IdGroupModel(role) + if let s = select { + model.isSelect = s + } + models.append(model) } - - func updateMyMember(_ serverId: UInt64?, _ nick: String?, _ completion: @escaping (Error?, ServerMemeber) -> Void){ - var param = UpdateMyMemberInfoParam() - param.serverId = serverId - param.nick = nick - repo.updateMyServerMember(param, completion) + return models + } + + func updateMyMember(_ serverId: UInt64?, _ nick: String?, + _ completion: @escaping (Error?, ServerMemeber) -> Void) { + var param = UpdateMyMemberInfoParam() + param.serverId = serverId + param.nick = nick + repo.updateMyServerMember(param, completion) + } + + func updateMember(_ serverId: UInt64?, _ nick: String?, _ accid: String?, + _ completion: @escaping (Error?, ServerMemeber) -> Void) { + var param = UpdateServerMemberInfoParam() + param.serverId = serverId + param.nick = nick + param.accid = accid + repo.updateServerMember(param, completion) + } + + func kickoutMember(_ serverId: UInt64?, _ accid: String?, + _ completion: @escaping (Error?) -> Void) { + var param = KickServerMembersParam() + param.serverId = serverId + var accids = [String]() + if let acc = accid { + accids.append(acc) + param.accounts = accids } - - func updateMember(_ serverId: UInt64?, _ nick: String?, _ accid: String?, _ completion: @escaping (Error?, ServerMemeber) -> Void){ - var param = UpdateServerMemberInfoParam() - param.serverId = serverId - param.nick = nick - param.accid = accid - repo.updateServerMember(param, completion) + repo.kickoutServerMembers(param) { error in + completion(error) } - - func kickoutMember(_ serverId: UInt64?, _ accid: String?, _ completion: @escaping (Error?)->Void){ - var param = KickServerMembersParam() - param.serverId = serverId - var accids = [String]() - if let acc = accid { - accids.append(acc) - param.accounts = accids - } - repo.kickoutServerMembers(param) { error in - completion(error) - } + } + + func addMembers(_ accid: String?, _ serverId: UInt64?, _ roleId: UInt64?, + _ completion: @escaping () -> Void) { + var param = AddServerRoleMemberParam() + param.serverId = serverId + param.roleId = roleId + var accids = [String]() + if let aid = accid { + accids.append(aid) } - - func addMembers(_ accid: String?, _ serverId: UInt64?, _ roleId: UInt64?, _ completion: @escaping () -> Void){ - - var param = AddServerRoleMemberParam() - param.serverId = serverId - param.roleId = roleId - var accids = [String]() - if let aid = accid { - accids.append(aid) - } - param.accountArray = accids - weak var weakSelf = self - - repo.addRoleMember(param) { error, successAccids, failedAccids in - print("add role member result : ", error as Any) - completion() - if let err = error { - weakSelf?.delegate?.dataDidError(err) - }else { - print("add members success accids : ", successAccids) - - if let rid = roleId, let model = weakSelf?.serverDic[rid] { - weakSelf?.userDic[rid] = model - } - weakSelf?.delegate?.dataDidChange() - } + param.accountArray = accids + weak var weakSelf = self + + repo.addRoleMember(param) { error, successAccids, failedAccids in + print("add role member result : ", error as Any) + completion() + if let err = error { + weakSelf?.delegate?.dataDidError(err) + } else { + print("add members success accids : ", successAccids) + + if let rid = roleId, let model = weakSelf?.serverDic[rid] { + weakSelf?.userDic[rid] = model } + weakSelf?.delegate?.dataDidChange() + } } - - func remove(_ accid: String?, _ serverId: UInt64?, _ rid: UInt64?, _ completion: @escaping () -> Void){ - var param = RemoveServerRoleMemberParam() - param.serverId = serverId - param.roleId = rid - weak var weakSelf = self - if let accid = accid { - param.accountArray = [accid] - repo.deleateRoleMember(param) { error, successAccids, failedAccids in - if let err = error { - weakSelf?.delegate?.dataDidError(err) - }else { - if let roleId = rid { - print("add role id : ", roleId) - weakSelf?.userDic.removeValue(forKey: roleId) - } - weakSelf?.delegate?.dataDidChange() - } - completion() - } - }else { - completion() + } + + func remove(_ accid: String?, _ serverId: UInt64?, _ rid: UInt64?, + _ completion: @escaping () -> Void) { + var param = RemoveServerRoleMemberParam() + param.serverId = serverId + param.roleId = rid + weak var weakSelf = self + if let accid = accid { + param.accountArray = [accid] + repo.deleateRoleMember(param) { error, successAccids, failedAccids in + if let err = error { + weakSelf?.delegate?.dataDidError(err) + } else { + if let roleId = rid { + print("add role id : ", roleId) + weakSelf?.userDic.removeValue(forKey: roleId) + } + weakSelf?.delegate?.dataDidChange() } + completion() + } + } else { + completion() } + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewModel/IdGroupSortViewModel.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewModel/IdGroupSortViewModel.swift index 9eb04859..41ad603c 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewModel/IdGroupSortViewModel.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewModel/IdGroupSortViewModel.swift @@ -1,141 +1,137 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NEKitQChat import NEKitCoreIM import AVFoundation public class IdGroupSortViewModel { - - let repo = QChatRepo() - - var datas = NSMutableArray() - + let repo = QChatRepo() + + var datas = NSMutableArray() + // var lockData = [IdGroupModel]() - - weak var delegate: ViewModelDelegate? - - var isOwner = false - - func getData(_ serverId: UInt64?){ - var param = GetServerRoleParam() - param.limit = 200 - param.serverId = serverId - weak var weakSelf = self - - repo.getRoles(param) { error, roles, sets in - if let err = error { - weakSelf?.delegate?.dataDidError(err) - }else { - weakSelf?.filterData(roles, sets) - } - } + + weak var delegate: ViewModelDelegate? + + var isOwner = false + + func getData(_ serverId: UInt64?) { + var param = GetServerRoleParam() + param.limit = 200 + param.serverId = serverId + weak var weakSelf = self + + repo.getRoles(param) { error, roles, sets in + if let err = error { + weakSelf?.delegate?.dataDidError(err) + } else { + weakSelf?.filterData(roles, sets) + } } - - func filterData(_ roles: [ServerRole]?, _ sets: Set?){ - weak var weakSelf = self - roles?.forEach({ role in - if role.type == .everyone { - return - } - let model = IdGroupModel(role) - model.hasPermission = isOwner - if let rid = role.roleId, let s = sets, s.contains(NSNumber(value: rid)) == true { - isOwner = true - } - weakSelf?.datas.add(model) + } + + func filterData(_ roles: [ServerRole]?, _ sets: Set?) { + weak var weakSelf = self + roles?.forEach { role in + if role.type == .everyone { + return + } + let model = IdGroupModel(role) + model.hasPermission = isOwner + if let rid = role.roleId, let s = sets, s.contains(NSNumber(value: rid)) == true { + isOwner = true + } + weakSelf?.datas.add(model) // if model.hasPermission == true { // weakSelf?.datas.add(model) // }else { // weakSelf?.lockData.append(model) // } - }) + } + weakSelf?.delegate?.dataDidChange() + } + + func removeRole(_ serverId: UInt64?, _ roleId: UInt64?, _ model: IdGroupModel, + _ completion: @escaping () -> Void) { + var param = DeleteServerRoleParam() + param.serverId = serverId + param.roleId = roleId + weak var weakSelf = self + repo.deleteRoles(param) { error in + if let err = error { + weakSelf?.delegate?.dataDidError(err) + } else { + weakSelf?.datas.remove(model) weakSelf?.delegate?.dataDidChange() + completion() + } } - - func removeRole(_ serverId: UInt64?, _ roleId: UInt64?, _ model: IdGroupModel, _ completion: @escaping () -> Void){ - - var param = DeleteServerRoleParam() - param.serverId = serverId - param.roleId = roleId - weak var weakSelf = self - repo.deleteRoles(param) { error in - if let err = error { - weakSelf?.delegate?.dataDidError(err) - }else { - weakSelf?.datas.remove(model) - weakSelf?.delegate?.dataDidChange() - completion() - } + } + + func saveSort(_ serverId: UInt64?, _ completion: @escaping () -> Void) { + var startIndex = 0 + + var startSort = false + var last: IdGroupModel? + var items = [UpdateServerRolePriorityItem]() + + var min: Int? + + datas.forEach { data in + + if let model = data as? IdGroupModel, model.hasPermission == true { + print("model p : ", model.role?.priority as Any) + if let m = min, let p = model.role?.priority { + if m > p { + min = p + } + } else { + min = model.role?.priority } + } } - - func saveSort(_ serverId: UInt64?, _ completion: @escaping () -> Void){ - - var startIndex = 0 - - var startSort = false - var last: IdGroupModel? - var items = [UpdateServerRolePriorityItem]() - - var min: Int? - - datas.forEach { data in - - if let model = data as? IdGroupModel, model.hasPermission == true { - print("model p : ", model.role?.priority as Any) - if let m = min, let p = model.role?.priority { - if m > p { - min = p - } - }else { - min = model.role?.priority - } - } - } - - print("print min : ", min as Any) - - for index in 0.. Void public class IdGroupViewModel { - - let repo = QChatRepo() - var topDatas = [IdGroupModel]() - var datas = [IdGroupModel]() - var sortBtnCellDatas = [IdGroupModel]() // only one - weak var delegate: ViewModelDelegate? - - var limitCount = 20 - - init(){} - - func getRoles(_ serverId: UInt64?, _ refresh: Bool = false, _ block: IdGroupViewModelBlock? ){ - var param = GetServerRoleParam() - param.serverId = serverId - param.limit = limitCount - if let last = datas.last, let pri = last.role?.priority, refresh == false { - param.priority = pri - } - weak var weakSelf = self - print("param : ", param) - - repo.getRoles(param) { error, roles, sets in - if let err = error { - weakSelf?.delegate?.dataDidError(err) - }else if let rs = roles { - print("get roles success : ", rs.count) - weakSelf?.parseData(rs, refresh) - } - if let completion = block { - completion() - } - } + let repo = QChatRepo() + var topDatas = [IdGroupModel]() + var datas = [IdGroupModel]() + var sortBtnCellDatas = [IdGroupModel]() // only one + weak var delegate: ViewModelDelegate? + + var limitCount = 20 + + init() {} + + func getRoles(_ serverId: UInt64?, _ refresh: Bool = false, _ block: IdGroupViewModelBlock?) { + var param = GetServerRoleParam() + param.serverId = serverId + param.limit = limitCount + if let last = datas.last, let pri = last.role?.priority, refresh == false { + param.priority = pri } - - func parseData(_ roles: [ServerRole], _ refresh: Bool){ - - var models = [IdGroupModel]() - roles.forEach { role in - print("get data proprity : ", role.priority as Any) - let model = IdGroupModel(role) - models.append(model) - } - filterData(models, refresh) - if roles.count < limitCount { - delegate?.dataNoMore?() - } + weak var weakSelf = self + print("param : ", param) + + repo.getRoles(param) { error, roles, sets in + if let err = error { + weakSelf?.delegate?.dataDidError(err) + } else if let rs = roles { + print("get roles success : ", rs.count) + weakSelf?.parseData(rs, refresh) + } + if let completion = block { + completion() + } } - - func filterData(_ models: [IdGroupModel], _ refresh: Bool){ - - if refresh == true { - topDatas.removeAll() - datas.removeAll() - sortBtnCellDatas.removeAll() - } - - if let first = models.first { - topDatas.append(first) - } - if models.count >= 2 { - datas.append(contentsOf: models.suffix(models.count - 1)) - } - - if datas.count > 0 { - if let first = sortBtnCellDatas.first { - first.idName = "身份组(\(datas.count))" - }else { - let data = IdGroupModel() - data.idName = "身份组(\(datas.count))" - sortBtnCellDatas.append(data) - } - } - delegate?.dataDidChange() + } + + func parseData(_ roles: [ServerRole], _ refresh: Bool) { + var models = [IdGroupModel]() + roles.forEach { role in + print("get data proprity : ", role.priority as Any) + let model = IdGroupModel(role) + models.append(model) + } + filterData(models, refresh) + if roles.count < limitCount { + delegate?.dataNoMore?() } - - func addRole(_ role: ServerRole){ - var models = [IdGroupModel]() - models.append(contentsOf: topDatas) - models.append(contentsOf: datas) - models.append(IdGroupModel(role)) - topDatas.removeAll() - datas.removeAll() - filterData(models, false) + } + + func filterData(_ models: [IdGroupModel], _ refresh: Bool) { + if refresh == true { + topDatas.removeAll() + datas.removeAll() + sortBtnCellDatas.removeAll() } + + if let first = models.first { + topDatas.append(first) + } + if models.count >= 2 { + datas.append(contentsOf: models.suffix(models.count - 1)) + } + + if datas.count > 0 { + if let first = sortBtnCellDatas.first { + first.idName = "身份组(\(datas.count))" + } else { + let data = IdGroupModel() + data.idName = "身份组(\(datas.count))" + sortBtnCellDatas.append(data) + } + } + delegate?.dataDidChange() + } + + func addRole(_ role: ServerRole) { + var models = [IdGroupModel]() + models.append(contentsOf: topDatas) + models.append(contentsOf: datas) + models.append(IdGroupModel(role)) + topDatas.removeAll() + datas.removeAll() + filterData(models, false) + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewModel/MemberManagerViewModel.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewModel/MemberManagerViewModel.swift index 7dd65c43..ec994345 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewModel/MemberManagerViewModel.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewModel/MemberManagerViewModel.swift @@ -1,6 +1,7 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NEKitCoreIM @@ -8,74 +9,72 @@ import NEKitQChat import CoreMedia class MemberManagerViewModel { - - var datas = [UserInfo]() - - var delegate: ViewModelDelegate? - - let repo = QChatRepo() - - let limit = 20 - - init(){ } - - func getData(_ sid: UInt64?, _ rid: UInt64?, _ refresh: Bool = false){ - var param = GetServerRoleMembersParam() - param.limit = limit - param.serverId = sid - param.roleId = rid - if let last = datas.last, let accid = last.accid, let createTime = last.createTime, refresh == false { - param.accid = accid - param.timeTag = createTime - print("load more : ", param) - }else { - param.accid = "" - param.timeTag = 0 - print("first refresh : ", param) + var datas = [UserInfo]() + + var delegate: ViewModelDelegate? + + let repo = QChatRepo() + + let limit = 20 + + init() {} + + func getData(_ sid: UInt64?, _ rid: UInt64?, _ refresh: Bool = false) { + var param = GetServerRoleMembersParam() + param.limit = limit + param.serverId = sid + param.roleId = rid + if let last = datas.last, let accid = last.accid, let createTime = last.createTime, + refresh == false { + param.accid = accid + param.timeTag = createTime + print("load more : ", param) + } else { + param.accid = "" + param.timeTag = 0 + print("first refresh : ", param) + } + weak var weakSelf = self + repo.getServerRoleMembers(param) { error, members in + if let err = error { + weakSelf?.delegate?.dataDidError(err) + } else { + if refresh == true { + weakSelf?.datas.removeAll() } - weak var weakSelf = self - repo.getServerRoleMembers(param) { error, members in - if let err = error { - weakSelf?.delegate?.dataDidError(err) - }else { - if refresh == true { - weakSelf?.datas.removeAll() - } - members.forEach { member in - let user = UserInfo(member) - weakSelf?.datas.append(user) - } - weakSelf?.delegate?.dataDidChange() - if let count = weakSelf?.limit, members.count < count { - weakSelf?.delegate?.dataNoMore?() - } - } + members.forEach { member in + let user = UserInfo(member) + weakSelf?.datas.append(user) } - } - - func addMembers(_ users: [UserInfo], _ serverId: UInt64?, _ roleId: UInt64?, _ completion: @escaping (Int) -> Void){ - - var param = AddServerRoleMemberParam() - param.serverId = serverId - param.roleId = roleId - var accids = [String]() - users.forEach { user in - if let accid = user.serverMember?.accid { - accids.append(accid) - } + weakSelf?.delegate?.dataDidChange() + if let count = weakSelf?.limit, members.count < count { + weakSelf?.delegate?.dataNoMore?() } - param.accountArray = accids - weak var weakSelf = self - - repo.addRoleMember(param) { error, successAccids, failedAccids in - print("add role member result : ", error as Any) - if let err = error { - weakSelf?.delegate?.dataDidError(err) - }else { - - weakSelf?.getData(serverId, roleId, true) - - + } + } + } + + func addMembers(_ users: [UserInfo], _ serverId: UInt64?, _ roleId: UInt64?, + _ completion: @escaping (Int) -> Void) { + var param = AddServerRoleMemberParam() + param.serverId = serverId + param.roleId = roleId + var accids = [String]() + users.forEach { user in + if let accid = user.serverMember?.accid { + accids.append(accid) + } + } + param.accountArray = accids + weak var weakSelf = self + + repo.addRoleMember(param) { error, successAccids, failedAccids in + print("add role member result : ", error as Any) + if let err = error { + weakSelf?.delegate?.dataDidError(err) + } else { + weakSelf?.getData(serverId, roleId, true) + // print("add members success accids : ", successAccids) // var dic = [String: UserInfo]() // users.forEach { user in @@ -91,27 +90,26 @@ class MemberManagerViewModel { // } // } // weakSelf?.delegate?.dataDidChange() - completion(successAccids.count) - } - } + completion(successAccids.count) + } } - - func remove(_ user: UserInfo, _ serverId: UInt64?, _ rid: UInt64?, _ completion: @escaping () -> Void){ - var param = RemoveServerRoleMemberParam() - param.serverId = serverId - param.roleId = rid - weak var weakSelf = self - if let accid = user.accid { - param.accountArray = [accid] - repo.deleateRoleMember(param) { error, successAccids, failedAccids in - if let err = error { - weakSelf?.delegate?.dataDidError(err) - }else { - completion() - } - } - }else { - + } + + func remove(_ user: UserInfo, _ serverId: UInt64?, _ rid: UInt64?, + _ completion: @escaping () -> Void) { + var param = RemoveServerRoleMemberParam() + param.serverId = serverId + param.roleId = rid + weak var weakSelf = self + if let accid = user.accid { + param.accountArray = [accid] + repo.deleateRoleMember(param) { error, successAccids, failedAccids in + if let err = error { + weakSelf?.delegate?.dataDidError(err) + } else { + completion() } - } + } + } else {} + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewModel/MemberSelectViewModel.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewModel/MemberSelectViewModel.swift index 7292a9e0..4dd984a6 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewModel/MemberSelectViewModel.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewModel/MemberSelectViewModel.swift @@ -1,132 +1,130 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NEKitQChat import NEKitCoreIM protocol MemberSelectViewModelDelegate: AnyObject { - func filterMembers(accid:[String]?, _ filterMembers: @escaping ([String]?) -> ()) + func filterMembers(accid: [String]?, _ filterMembers: @escaping ([String]?) -> Void) } class MemberSelectViewModel { - - let repo = QChatRepo() - - var datas = [UserInfo]() - - weak var delegate: MemberSelectViewModelDelegate? - - var lastTimeTag: TimeInterval = 0 - - let pageSize = 50 - - - init(){} - - func loadFirst(serverId: UInt64?, completion: @escaping (NSError?, [UserInfo]?) -> ()) { - self.lastTimeTag = 0 - self.datas.removeAll() - print("self?.datas:\(self.datas.count)") - getServerMebers(serverId) {[weak self] error , userInfos in - if error != nil { - completion(error as NSError?, userInfos) - }else { - if let userArray = userInfos, !userArray.isEmpty { + let repo = QChatRepo() + + var datas = [UserInfo]() + + weak var delegate: MemberSelectViewModelDelegate? + + var lastTimeTag: TimeInterval = 0 + + let pageSize = 50 + + init() {} + + func loadFirst(serverId: UInt64?, completion: @escaping (NSError?, [UserInfo]?) -> Void) { + lastTimeTag = 0 + datas.removeAll() + print("self?.datas:\(datas.count)") + getServerMebers(serverId) { [weak self] error, userInfos in + if error != nil { + completion(error as NSError?, userInfos) + } else { + if let userArray = userInfos, !userArray.isEmpty { // 判断有没设置delegate - if let del = self?.delegate { - self?.lastTimeTag = userArray.last?.serverMember?.createTime ?? 0 - var accids = [String]() - for user in userArray { - if let accid = user.serverMember?.accid { - accids.append(accid) - } - } - del.filterMembers(accid: accids, { filterAccids in - if let filterIds = filterAccids { - var tmp = [UserInfo]() - for user in userArray { - if filterIds.contains(user.serverMember?.accid ?? "") { - }else { - tmp.append(user) - self?.datas.append(user) - } - } - completion(error as NSError?, tmp) - }else { - self?.datas = userArray - completion(error as NSError?, userArray) - } - - }) - } else { - // 未设置 - self?.datas = userArray - completion(error as NSError?, userArray) - } - - }else { - // 结果为空 - completion(error as NSError?, userInfos) + if let del = self?.delegate { + self?.lastTimeTag = userArray.last?.serverMember?.createTime ?? 0 + var accids = [String]() + for user in userArray { + if let accid = user.serverMember?.accid { + accids.append(accid) + } + } + del.filterMembers(accid: accids) { filterAccids in + if let filterIds = filterAccids { + var tmp = [UserInfo]() + for user in userArray { + if filterIds.contains(user.serverMember?.accid ?? "") { + } else { + tmp.append(user) + self?.datas.append(user) + } } + completion(error as NSError?, tmp) + } else { + self?.datas = userArray + completion(error as NSError?, userArray) + } } + } else { + // 未设置 + self?.datas = userArray + completion(error as NSError?, userArray) + } + + } else { + // 结果为空 + completion(error as NSError?, userInfos) } + } } - - func loadMore(serverId: UInt64?, completion: @escaping (NSError?, [UserInfo]?) -> ()) { - getServerMebers(serverId) {[weak self] error , userInfos in - if error != nil { - completion(error as NSError?, userInfos) - }else { - if var userArray = userInfos, userArray.count > 0 { - if let del = self?.delegate { - self?.lastTimeTag = userArray.last?.serverMember?.createTime ?? 0 - var accids = [String]() - for user in userArray { - if let accid = user.serverMember?.accid { - accids.append(accid) - } - } - - del.filterMembers(accid: accids, { filterAccids in - var tmp = [UserInfo]() - for user in userArray { - if accids.contains(user.serverMember?.accid ?? "") { - }else { - tmp.append(user) - self?.datas.append(user) - } - } - completion(error as NSError?, tmp) - }) - }else { - for u in userArray { - self?.datas.append(u) - } - completion(error as NSError?, userArray) - } - - }else { - // 结果为空 - completion(error as NSError?, userInfos) + } + + func loadMore(serverId: UInt64?, completion: @escaping (NSError?, [UserInfo]?) -> Void) { + getServerMebers(serverId) { [weak self] error, userInfos in + if error != nil { + completion(error as NSError?, userInfos) + } else { + if var userArray = userInfos, userArray.count > 0 { + if let del = self?.delegate { + self?.lastTimeTag = userArray.last?.serverMember?.createTime ?? 0 + var accids = [String]() + for user in userArray { + if let accid = user.serverMember?.accid { + accids.append(accid) + } + } + + del.filterMembers(accid: accids) { filterAccids in + var tmp = [UserInfo]() + for user in userArray { + if accids.contains(user.serverMember?.accid ?? "") { + } else { + tmp.append(user) + self?.datas.append(user) } + } + completion(error as NSError?, tmp) } - } - } - - func getServerMebers(_ serverId: UInt64?, completion: @escaping (NSError?, [UserInfo]?) -> ()){ - var param = GetServerMembersByPageParam() - param.serverId = serverId - param.timeTag = self.lastTimeTag - param.limit = self.pageSize - repo.getServerMembers(param) { error, members in - var memberArray = [UserInfo]() - members.forEach { member in - memberArray.append(UserInfo(member)) + } else { + for u in userArray { + self?.datas.append(u) } - completion(error as NSError?, memberArray) + completion(error as NSError?, userArray) + } + + } else { + // 结果为空 + completion(error as NSError?, userInfos) } + } + } + } + + func getServerMebers(_ serverId: UInt64?, + completion: @escaping (NSError?, [UserInfo]?) -> Void) { + var param = GetServerMembersByPageParam() + param.serverId = serverId + param.timeTag = lastTimeTag + param.limit = pageSize + repo.getServerMembers(param) { error, members in + var memberArray = [UserInfo]() + members.forEach { member in + memberArray.append(UserInfo(member)) + } + completion(error as NSError?, memberArray) } - + } } diff --git a/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewModel/PermissionViewModel.swift b/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewModel/PermissionViewModel.swift index 00ff6afa..b6be940f 100644 --- a/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewModel/PermissionViewModel.swift +++ b/NEQChatUIKit/NEKitQChatUI/Classes/Server/ViewModel/PermissionViewModel.swift @@ -1,6 +1,7 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NEKitQChat @@ -8,63 +9,60 @@ import UIKit import NEKitCoreIM class PermissionViewModel { - - let permission = PermissionModel() - - var commons = [PermissionCellModel]() - - var messages = [PermissionCellModel]() - - var members = [PermissionCellModel]() - - let repo = QChatRepo() - - var delegate: ViewModelDelegate? - - var hasPermissionKey = [String: String]() - - init(){ - - } - - func getData(_ serverRole: ServerRole){ - weak var weakSelf = self + let permission = PermissionModel() + + var commons = [PermissionCellModel]() + + var messages = [PermissionCellModel]() + + var members = [PermissionCellModel]() + + let repo = QChatRepo() + + var delegate: ViewModelDelegate? + + var hasPermissionKey = [String: String]() + + init() {} + + func getData(_ serverRole: ServerRole) { + weak var weakSelf = self // print("get data authors : ", serverRole.auths as Any) - serverRole.auths?.forEach({ info in - if info.status == .Allow { - if let key = info.permissionType?.rawValue { - weakSelf?.hasPermissionKey[key] = key - } - } - }) - loadData(permission.commonPermission, permission.commonPermissionDic, &commons) - loadData(permission.messagePermission, permission.messagePermissionDic, &messages) - loadData(permission.memberPermission, permission.memberPermissionDic, &members) - -// delegate?.dataDidChange() + serverRole.auths?.forEach { info in + if info.status == .Allow { + if let key = info.permissionType?.rawValue { + weakSelf?.hasPermissionKey[key] = key + } + } } - - func loadData(_ keys:[String], _ keyValues: [String: String], _ datas: inout [PermissionCellModel] ){ - - for index in 0.. 'https://github.com/netease/NEKitGroupUI.git', :tag => s.version.to_s } # s.social_media_url = 'https://twitter.com/' - + s.pod_target_xcconfig = { + 'BUILD_LIBRARY_FOR_DISTRIBUTION' => 'YES' + } + s.user_target_xcconfig = { 'BUILD_LIBRARY_FOR_DISTRIBUTION' => 'YES' } + s.ios.deployment_target = '9.0' s.source_files = 'NEKitTeamUI/Classes/**/*' diff --git a/NETeamUIKit/NEKitTeamUI/Assets/en.lproj/Localizable.strings b/NETeamUIKit/NEKitTeamUI/Assets/en.lproj/Localizable.strings index c9d6caf3..840c4890 100644 --- a/NETeamUIKit/NEKitTeamUI/Assets/en.lproj/Localizable.strings +++ b/NETeamUIKit/NEKitTeamUI/Assets/en.lproj/Localizable.strings @@ -1,10 +1,7 @@ -/* - YXLogin.strings - Pods - Created by yu chen on 2021/12/24. - -*/ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. "mark"="标记"; "history"="历史记录"; diff --git a/NETeamUIKit/NEKitTeamUI/Assets/zh-Hans.lproj/Localizable.strings b/NETeamUIKit/NEKitTeamUI/Assets/zh-Hans.lproj/Localizable.strings index b12c0af0..cf30978c 100644 --- a/NETeamUIKit/NEKitTeamUI/Assets/zh-Hans.lproj/Localizable.strings +++ b/NETeamUIKit/NEKitTeamUI/Assets/zh-Hans.lproj/Localizable.strings @@ -1,10 +1,8 @@ -/* - YXLogin.strings - Pods - Created by yu chen on 2021/12/24. - -*/ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + "mark"="标记"; "history"="历史记录"; "message_remind"="开启消息提醒"; diff --git a/NETeamUIKit/NEKitTeamUI/Classes/Setting/Model/SettingCellModel.swift b/NETeamUIKit/NEKitTeamUI/Classes/Setting/Model/SettingCellModel.swift index 0da982f7..0be9edd0 100644 --- a/NETeamUIKit/NEKitTeamUI/Classes/Setting/Model/SettingCellModel.swift +++ b/NETeamUIKit/NEKitTeamUI/Classes/Setting/Model/SettingCellModel.swift @@ -1,38 +1,38 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation public enum SettingCellType: Int { - case SettingArrowCell = 0 - case SettingSwitchCell - case SettingSelectCell - case SettingHeaderCell - case SettingTeamUserCell - case SettingSubtitleCell - case SettingSubtitleCustomCell + case SettingArrowCell = 0 + case SettingSwitchCell + case SettingSelectCell + case SettingHeaderCell + case SettingTeamUserCell + case SettingSubtitleCell + case SettingSubtitleCustomCell } public class SettingCellModel { - - public typealias SwitchChangeCompletion = (Bool) -> Void - public typealias CellClick = () -> Void - public var cellName: String? - public var subTitle: String? - public var type = SettingCellType.SettingArrowCell.rawValue - public var swichChange: SwitchChangeCompletion? - public var rowHeight: CGFloat = 49 - public var cornerType = CornerType.none - public var headerUrl: String? - public var cellClick: CellClick? - public var switchOpen = false - //头像扩展字段 - public var defaultHeadData:String? - //自定义视图的icon - public var rightCustomViewIcon:String? - //自定义视图的点击事件 - public var customViewClick: CellClick? + public typealias SwitchChangeCompletion = (Bool) -> Void + public typealias CellClick = () -> Void + public var cellName: String? + public var subTitle: String? + public var type = SettingCellType.SettingArrowCell.rawValue + public var swichChange: SwitchChangeCompletion? + public var rowHeight: CGFloat = 49 + public var cornerType = CornerType.none + public var headerUrl: String? + public var cellClick: CellClick? + public var switchOpen = false + // 头像扩展字段 + public var defaultHeadData: String? + // 自定义视图的icon + public var rightCustomViewIcon: String? + // 自定义视图的点击事件 + public var customViewClick: CellClick? - public init(){} + public init() {} } diff --git a/NETeamUIKit/NEKitTeamUI/Classes/Setting/Model/SettingSectionModel.swift b/NETeamUIKit/NEKitTeamUI/Classes/Setting/Model/SettingSectionModel.swift index 6889365e..83494c37 100644 --- a/NETeamUIKit/NEKitTeamUI/Classes/Setting/Model/SettingSectionModel.swift +++ b/NETeamUIKit/NEKitTeamUI/Classes/Setting/Model/SettingSectionModel.swift @@ -1,10 +1,11 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation public class SettingSectionModel { - public var cellModels = [SettingCellModel]() - public init(){} + public var cellModels = [SettingCellModel]() + public init() {} } diff --git a/NETeamUIKit/NEKitTeamUI/Classes/Setting/TeamAvatarViewController.swift b/NETeamUIKit/NEKitTeamUI/Classes/Setting/TeamAvatarViewController.swift index 73e6b1af..31c112b3 100644 --- a/NETeamUIKit/NEKitTeamUI/Classes/Setting/TeamAvatarViewController.swift +++ b/NETeamUIKit/NEKitTeamUI/Classes/Setting/TeamAvatarViewController.swift @@ -1,276 +1,291 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCommonUI import NIMSDK import NEKitTeam -public class TeamAvatarViewController: NEBaseViewController { - - typealias SaveCompletion = () -> Void - - var block: SaveCompletion? - - var team: NIMTeam? - - let repo = TeamRepo() - - lazy var headerView: NEUserHeaderView = { - let header = NEUserHeaderView(frame: .zero) - header.translatesAutoresizingMaskIntoConstraints = false - header.clipsToBounds = true - header.layer.cornerRadius = 40 - header.isUserInteractionEnabled = true - return header - }() - - var headerUrl = "" - - lazy var iconCollection: UICollectionView = { - let flow = UICollectionViewFlowLayout() - flow.scrollDirection = .horizontal - flow.minimumLineSpacing = 0 - let collection = UICollectionView(frame: .zero, collectionViewLayout: flow) - collection.translatesAutoresizingMaskIntoConstraints = false - collection.delegate = self - collection.dataSource = self - collection.backgroundColor = .clear - collection.showsHorizontalScrollIndicator = false - collection.clipsToBounds = false - collection.isScrollEnabled = false - return collection - }() - - public override func viewDidLoad() { - super.viewDidLoad() - setupUI() - } - - func setupUI(){ - - title = "修改头像" - addRightAction("保存", #selector(savePhoto), self) - - view.backgroundColor = NEConstant.hexRGB(0xF1F1F6) - let headerBack = UIView() - headerBack.backgroundColor = .white - headerBack.clipsToBounds = true - headerBack.layer.cornerRadius = 8.0 - headerBack.translatesAutoresizingMaskIntoConstraints = false - view.addSubview(headerBack) - - if #available(iOS 11.0, *) { - NSLayoutConstraint.activate([ - headerBack.topAnchor.constraint(equalTo:view.safeAreaLayoutGuide.topAnchor, constant: 12.0), - headerBack.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20), - headerBack.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20), - headerBack.heightAnchor.constraint(equalToConstant: 128.0) - ]) - } else { - NSLayoutConstraint.activate([ - headerBack.topAnchor.constraint(equalTo: view.topAnchor, constant: 12.0), - headerBack.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20), - headerBack.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20), - headerBack.heightAnchor.constraint(equalToConstant: 128.0) - ]) - } - - headerBack.addSubview(headerView) - NSLayoutConstraint.activate([ - headerView.centerXAnchor.constraint(equalTo: headerBack.centerXAnchor), - headerView.centerYAnchor.constraint(equalTo: headerBack.centerYAnchor), - headerView.heightAnchor.constraint(equalToConstant: 80.0), - headerView.widthAnchor.constraint(equalToConstant: 80.0) - ]) - if let url = team?.avatarUrl { - headerView.sd_setImage(with: URL(string: url), completed: nil) - headerUrl = url - } - - let photoImage = UIImageView() - photoImage.translatesAutoresizingMaskIntoConstraints = false - headerBack.addSubview(photoImage) - NSLayoutConstraint.activate([ - photoImage.rightAnchor.constraint(equalTo: headerView.rightAnchor), - photoImage.bottomAnchor.constraint(equalTo: headerView.bottomAnchor), - ]) - photoImage.image = coreLoader.loadImage("photo") - - let gesture = UITapGestureRecognizer() - headerView.addGestureRecognizer(gesture) - gesture.addTarget(self, action: #selector(uploadPhoto)) - - let defaultHeaderBack = UIView() - defaultHeaderBack.translatesAutoresizingMaskIntoConstraints = false - view.addSubview(defaultHeaderBack) - defaultHeaderBack.clipsToBounds = true - defaultHeaderBack.layer.cornerRadius = 8.0 - defaultHeaderBack.backgroundColor = .white - NSLayoutConstraint.activate([ - defaultHeaderBack.leftAnchor.constraint(equalTo: headerBack.leftAnchor), - defaultHeaderBack.rightAnchor.constraint(equalTo: headerBack.rightAnchor), - defaultHeaderBack.topAnchor.constraint(equalTo: headerBack.bottomAnchor, constant: 12.0), - defaultHeaderBack.heightAnchor.constraint(equalToConstant: 114.0) - ]) - - let tag = UILabel() - tag.translatesAutoresizingMaskIntoConstraints = false - tag.text = localizable("default_icon") - tag.font = NEConstant.defaultTextFont(16.0) - tag.textColor = NEConstant.hexRGB(0x333333) - defaultHeaderBack.addSubview(tag) - NSLayoutConstraint.activate([ - tag.leftAnchor.constraint(equalTo: defaultHeaderBack.leftAnchor, constant: 16.0), - tag.topAnchor.constraint(equalTo: defaultHeaderBack.topAnchor, constant: 15.0) - ]) - - defaultHeaderBack.addSubview(iconCollection) - iconCollection.register(TeamDefaultIconCell.self, forCellWithReuseIdentifier: "\(TeamDefaultIconCell.self)") - NSLayoutConstraint.activate([ - iconCollection.topAnchor.constraint(equalTo: tag.bottomAnchor, constant: 16.0), - iconCollection.leftAnchor.constraint(equalTo: defaultHeaderBack.leftAnchor, constant: 18), - iconCollection.rightAnchor.constraint(equalTo: defaultHeaderBack.rightAnchor, constant: -18.0), - iconCollection.heightAnchor.constraint(equalToConstant: 48.0) - ]) - - for index in 0.. Void + + var block: SaveCompletion? + + var team: NIMTeam? + + let repo = TeamRepo() + + lazy var headerView: NEUserHeaderView = { + let header = NEUserHeaderView(frame: .zero) + header.translatesAutoresizingMaskIntoConstraints = false + header.clipsToBounds = true + header.layer.cornerRadius = 40 + header.isUserInteractionEnabled = true + return header + }() + + var headerUrl = "" + + lazy var iconCollection: UICollectionView = { + let flow = UICollectionViewFlowLayout() + flow.scrollDirection = .horizontal + flow.minimumLineSpacing = 0 + let collection = UICollectionView(frame: .zero, collectionViewLayout: flow) + collection.translatesAutoresizingMaskIntoConstraints = false + collection.delegate = self + collection.dataSource = self + collection.backgroundColor = .clear + collection.showsHorizontalScrollIndicator = false + collection.clipsToBounds = false + collection.isScrollEnabled = false + return collection + }() + + override public func viewDidLoad() { + super.viewDidLoad() + setupUI() + } + + func setupUI() { + title = "修改头像" + addRightAction("保存", #selector(savePhoto), self) + + view.backgroundColor = NEConstant.hexRGB(0xF1F1F6) + let headerBack = UIView() + headerBack.backgroundColor = .white + headerBack.clipsToBounds = true + headerBack.layer.cornerRadius = 8.0 + headerBack.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(headerBack) + + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + headerBack.topAnchor.constraint( + equalTo: view.safeAreaLayoutGuide.topAnchor, + constant: 12.0 + ), + headerBack.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20), + headerBack.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20), + headerBack.heightAnchor.constraint(equalToConstant: 128.0), + ]) + } else { + NSLayoutConstraint.activate([ + headerBack.topAnchor.constraint(equalTo: view.topAnchor, constant: 12.0), + headerBack.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20), + headerBack.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20), + headerBack.heightAnchor.constraint(equalToConstant: 128.0), + ]) } - - func changePermission() -> Bool { - - if let type = team?.type, type == .normal { - return true - } - if let ownerId = team?.owner, IMKitLoginManager.instance.isMySelf(ownerId) { - return true - } - if let mode = team?.updateInfoMode, mode == .all { - return true - } - return false + + headerBack.addSubview(headerView) + NSLayoutConstraint.activate([ + headerView.centerXAnchor.constraint(equalTo: headerBack.centerXAnchor), + headerView.centerYAnchor.constraint(equalTo: headerBack.centerYAnchor), + headerView.heightAnchor.constraint(equalToConstant: 80.0), + headerView.widthAnchor.constraint(equalToConstant: 80.0), + ]) + if let url = team?.avatarUrl { + headerView.sd_setImage(with: URL(string: url), completed: nil) + headerUrl = url } - - /* - // MARK: - Navigation + let photoImage = UIImageView() + photoImage.translatesAutoresizingMaskIntoConstraints = false + headerBack.addSubview(photoImage) + NSLayoutConstraint.activate([ + photoImage.rightAnchor.constraint(equalTo: headerView.rightAnchor), + photoImage.bottomAnchor.constraint(equalTo: headerView.bottomAnchor), + ]) + photoImage.image = coreLoader.loadImage("photo") - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. - } - */ + let gesture = UITapGestureRecognizer() + headerView.addGestureRecognizer(gesture) + gesture.addTarget(self, action: #selector(uploadPhoto)) -} + let defaultHeaderBack = UIView() + defaultHeaderBack.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(defaultHeaderBack) + defaultHeaderBack.clipsToBounds = true + defaultHeaderBack.layer.cornerRadius = 8.0 + defaultHeaderBack.backgroundColor = .white + NSLayoutConstraint.activate([ + defaultHeaderBack.leftAnchor.constraint(equalTo: headerBack.leftAnchor), + defaultHeaderBack.rightAnchor.constraint(equalTo: headerBack.rightAnchor), + defaultHeaderBack.topAnchor.constraint( + equalTo: headerBack.bottomAnchor, + constant: 12.0 + ), + defaultHeaderBack.heightAnchor.constraint(equalToConstant: 114.0), + ]) -extension TeamAvatarViewController { - @objc func uploadPhoto(){ - print("upload photo") - showBottomAlert(self) + let tag = UILabel() + tag.translatesAutoresizingMaskIntoConstraints = false + tag.text = localizable("default_icon") + tag.font = NEConstant.defaultTextFont(16.0) + tag.textColor = NEConstant.hexRGB(0x333333) + defaultHeaderBack.addSubview(tag) + NSLayoutConstraint.activate([ + tag.leftAnchor.constraint(equalTo: defaultHeaderBack.leftAnchor, constant: 16.0), + tag.topAnchor.constraint(equalTo: defaultHeaderBack.topAnchor, constant: 15.0), + ]) + + defaultHeaderBack.addSubview(iconCollection) + iconCollection.register( + TeamDefaultIconCell.self, + forCellWithReuseIdentifier: "\(TeamDefaultIconCell.self)" + ) + NSLayoutConstraint.activate([ + iconCollection.topAnchor.constraint(equalTo: tag.bottomAnchor, constant: 16.0), + iconCollection.leftAnchor.constraint( + equalTo: defaultHeaderBack.leftAnchor, + constant: 18 + ), + iconCollection.rightAnchor.constraint( + equalTo: defaultHeaderBack.rightAnchor, + constant: -18.0 + ), + iconCollection.heightAnchor.constraint(equalToConstant: 48.0), + ]) + + for index in 0 ..< TeamRouter.iconUrls.count { + let url = TeamRouter.iconUrls[index] + if url == headerUrl { + let indexPath = IndexPath(row: index, section: 0) + iconCollection.selectItem(at: indexPath, animated: false, scrollPosition: .right) + } } - - @objc func savePhoto(){ - print("save photo") - if let tid = team?.teamId { - view.makeToastActivity(.center) - weak var weakSelf = self - - repo.fetchNOSURL(url: headerUrl) { error, urlStr in - if error == nil { - weakSelf?.repo.updateTeamIcon(urlStr ?? "", tid) { error in - weakSelf?.view.hideToastActivity() - if let err = error { - weakSelf?.showToast(err.localizedDescription) - }else { - weakSelf?.team?.avatarUrl = weakSelf?.headerUrl - if let completion = weakSelf?.block { - completion() - } - weakSelf?.navigationController?.popViewController(animated: true) - } - } - } - } - } + if changePermission() == false { + rightNavBtn.isHidden = true } -} + } -extension TeamAvatarViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { - - public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - return 5 + func changePermission() -> Bool { + if let type = team?.type, type == .normal { + return true } - - public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { - if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "\(TeamDefaultIconCell.self)", for: indexPath) as? TeamDefaultIconCell { - cell.iconImage.image = coreLoader.loadImage("icon_\(indexPath.row)") - - return cell - } - return UICollectionViewCell() + if let ownerId = team?.owner, IMKitLoginManager.instance.isMySelf(ownerId) { + return true } - - public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { - let space = (self.view.width - 297.0)/4.0 - print("mini inter : ", space) - return space + if let mode = team?.updateInfoMode, mode == .all { + return true } + return false + } + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ + //MARK: objc 方法 - - public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - if TeamRouter.iconUrls.count > indexPath.row { - headerUrl = TeamRouter.iconUrls[indexPath.row] - //headerView.image = coreLoader.loadImage("icon_\(indexPath.row)") - headerView.sd_setImage(with: URL(string: headerUrl), completed: nil) + @objc func uploadPhoto() { + print("upload photo") + showBottomAlert(self) + } + + @objc func savePhoto() { + print("save photo") + if let tid = team?.teamId { + view.makeToastActivity(.center) + weak var weakSelf = self + + repo.fetchNOSURL(url: headerUrl) { error, urlStr in + if error == nil { + weakSelf?.repo.updateTeamIcon(urlStr ?? "", tid) { error in + weakSelf?.view.hideToastActivity() + if let err = error { + weakSelf?.showToast(err.localizedDescription) + } else { + weakSelf?.team?.avatarUrl = weakSelf?.headerUrl + if let completion = weakSelf?.block { + completion() + } + weakSelf?.navigationController?.popViewController(animated: true) + } + } + } } + } } -} + //MAKR: UICollectionViewDelegate, UICollectionViewDataSource,UICollectionViewDelegateFlowLayout + public func collectionView(_ collectionView: UICollectionView, + numberOfItemsInSection section: Int) -> Int { + 5 + } -extension TeamAvatarViewController: UINavigationControllerDelegate { - + public func collectionView(_ collectionView: UICollectionView, + cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + if let cell = collectionView.dequeueReusableCell( + withReuseIdentifier: "\(TeamDefaultIconCell.self)", + for: indexPath + ) as? TeamDefaultIconCell { + cell.iconImage.image = coreLoader.loadImage("icon_\(indexPath.row)") + + return cell + } + return UICollectionViewCell() + } + + public func collectionView(_ collectionView: UICollectionView, + layout collectionViewLayout: UICollectionViewLayout, + minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { + let space = (view.width - 297.0) / 4.0 + print("mini inter : ", space) + return space + } - func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info:[UIImagePickerController.InfoKey : Any]) { - let image : UIImage = info[UIImagePickerController.InfoKey.editedImage] as! UIImage - uploadHeadImage(image: image) - picker.dismiss(animated: true, completion: nil) + public func collectionView(_ collectionView: UICollectionView, + didSelectItemAt indexPath: IndexPath) { + if TeamRouter.iconUrls.count > indexPath.row { + headerUrl = TeamRouter.iconUrls[indexPath.row] + // headerView.image = coreLoader.loadImage("icon_\(indexPath.row)") + headerView.sd_setImage(with: URL(string: headerUrl), completed: nil) + } } - public func uploadHeadImage(image:UIImage){ - - view.makeToastActivity(.center) - if let imageData = image.jpegData(compressionQuality: 0.6) as NSData? { - let filePath = NSHomeDirectory().appending("/Documents/").appending(IMKitLoginManager.instance.imAccid) - let succcess = imageData.write(toFile: filePath, atomically: true) - weak var weakSelf = self - if succcess { - NIMSDK.shared().resourceManager.upload(filePath, progress: nil) { urlString, error in - if error == nil { - //显示设置的照片 - weakSelf?.headerView.image = image - if let url = urlString { - weakSelf?.headerUrl = url - } - print("upload image success") - }else { - print("upload image failed,error = \(error!)") - } - weakSelf?.view.hideToastActivity() + //MARK: UINavigationControllerDelegate + + func imagePickerController(_ picker: UIImagePickerController, + didFinishPickingMediaWithInfo info: [UIImagePickerController + .InfoKey: Any]) { + let image: UIImage = info[UIImagePickerController.InfoKey.editedImage] as! UIImage + uploadHeadImage(image: image) + picker.dismiss(animated: true, completion: nil) + } + + public func uploadHeadImage(image: UIImage) { + view.makeToastActivity(.center) + if let imageData = image.jpegData(compressionQuality: 0.6) as NSData? { + let filePath = NSHomeDirectory().appending("/Documents/") + .appending(IMKitLoginManager.instance.imAccid) + let succcess = imageData.write(toFile: filePath, atomically: true) + weak var weakSelf = self + if succcess { + NIMSDK.shared().resourceManager + .upload(filePath, progress: nil) { urlString, error in + if error == nil { + // 显示设置的照片 + weakSelf?.headerView.image = image + if let url = urlString { + weakSelf?.headerUrl = url } + print("upload image success") + } else { + print("upload image failed,error = \(error!)") + } + weakSelf?.view.hideToastActivity() } } + } } } + diff --git a/NETeamUIKit/NEKitTeamUI/Classes/Setting/TeamHistoryMessageController.swift b/NETeamUIKit/NEKitTeamUI/Classes/Setting/TeamHistoryMessageController.swift index 3293e58e..4d144958 100644 --- a/NETeamUIKit/NEKitTeamUI/Classes/Setting/TeamHistoryMessageController.swift +++ b/NETeamUIKit/NEKitTeamUI/Classes/Setting/TeamHistoryMessageController.swift @@ -1,184 +1,190 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NIMSDK -public class TeamHistoryMessageController: NEBaseViewController { - - private let viewmodel = TeamSettingViewModel() - private var teamSession :NIMSession? - private var searchStr = "" - private var tag = "TeamHistoryMessageController" - - public init(session:NIMSession?) { - super.init(nibName: nil, bundle: nil) - self.teamSession = session - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - public override func viewDidLoad() { - super.viewDidLoad() - setupSubviews() - initialConfig() +public class TeamHistoryMessageController: NEBaseViewController,UITextFieldDelegate,UITableViewDelegate, UITableViewDataSource { + private let viewmodel = TeamSettingViewModel() + private var teamSession: NIMSession? + private var searchStr = "" + private var tag = "TeamHistoryMessageController" + + public init(session: NIMSession?) { + super.init(nibName: nil, bundle: nil) + teamSession = session + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override public func viewDidLoad() { + super.viewDidLoad() + setupSubviews() + initialConfig() + } + + func setupSubviews() { + view.addSubview(tableView) + view.addSubview(searchTextField) + view.addSubview(emptyView) + + NSLayoutConstraint.activate([ + searchTextField.topAnchor.constraint( + equalTo: view.topAnchor, + constant: NEConstant.navigationHeight + NEConstant.statusBarHeight + 20 + ), + searchTextField.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20), + searchTextField.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20), + searchTextField.heightAnchor.constraint(equalToConstant: 32), + ]) + + NSLayoutConstraint.activate([ + tableView.rightAnchor.constraint(equalTo: view.rightAnchor), + tableView.leftAnchor.constraint(equalTo: view.leftAnchor), + tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), + tableView.topAnchor.constraint(equalTo: searchTextField.bottomAnchor, constant: 20), + ]) + + NSLayoutConstraint.activate([ + emptyView.rightAnchor.constraint(equalTo: tableView.rightAnchor), + emptyView.leftAnchor.constraint(equalTo: tableView.leftAnchor), + emptyView.bottomAnchor.constraint(equalTo: tableView.bottomAnchor), + emptyView.topAnchor.constraint(equalTo: tableView.topAnchor), + ]) + } + + func initialConfig() { + title = "历史记录" + } + + // MARK: lazy method + + private lazy var tableView: UITableView = { + let tableView = UITableView(frame: .zero, style: .plain) + tableView.translatesAutoresizingMaskIntoConstraints = false + tableView.separatorStyle = .none + tableView.delegate = self + tableView.dataSource = self + tableView.register( + HistoryMessageCell.self, + forCellReuseIdentifier: "\(NSStringFromClass(HistoryMessageCell.self))" + ) + tableView.rowHeight = 65 + tableView.backgroundColor = .white + tableView.sectionHeaderHeight = 30 + tableView.sectionFooterHeight = 0 + return tableView + }() + + private lazy var searchTextField: SearchTextField = { + let textField = SearchTextField() + let leftImageView = UIImageView(image: coreLoader.loadImage("search_icon")) + textField.contentMode = .center + textField.leftView = leftImageView + textField.leftViewMode = .always + textField.placeholder = localizable("搜索") + textField.font = UIFont.systemFont(ofSize: 14) + textField.textColor = UIColor.ne_greyText + textField.translatesAutoresizingMaskIntoConstraints = false + textField.layer.cornerRadius = 8 + textField.backgroundColor = UIColor(hexString: "0xF2F4F5") + textField.clearButtonMode = .whileEditing + textField.returnKeyType = .search + textField.addTarget(self, action: #selector(searchTextFieldChange), for: .editingChanged) + textField.delegate = self + return textField + + }() + + private lazy var emptyView: NEEmptyDataView = { + let view = NEEmptyDataView(imageName: "emptyView", content: "暂无搜索结果", frame: CGRect.zero) + view.translatesAutoresizingMaskIntoConstraints = false + view.isHidden = true + return view + + }() + + // MARK: private method + + @objc func searchTextFieldChange(textfield: SearchTextField) { + if textfield.text?.count == 0 { + viewmodel.searchResultInfos?.removeAll() + tableView.reloadData() } + } + //MARK: UITextFieldDelegate + public func textFieldShouldReturn(_ textField: UITextField) -> Bool { + guard let searchText = textField.text else { + return false + } + if searchText.count <= 0 { + return false + } + guard let session = teamSession else { + return false + } + weak var weakSelf = self + searchStr = searchText + let option = NIMMessageSearchOption() + option.searchContent = searchText + weakSelf?.viewmodel.searchMessages(session, option: option) { error, messages in + if error == nil { + if let msg = messages, msg.count > 0 { + weakSelf?.emptyView.isHidden = true + } else { + weakSelf?.emptyView.isHidden = false + } + weakSelf?.tableView.reloadData() + } else { + NELog.errorLog( + weakSelf?.tag ?? "TeamHistoryMessageController", + desc: "❌searchMessages failed, error = \(error!)" + ) + } + } - func setupSubviews(){ - self.view.addSubview(tableView) - self.view.addSubview(searchTextField) - self.view.addSubview(emptyView) - - NSLayoutConstraint.activate([ - searchTextField.topAnchor.constraint(equalTo: self.view.topAnchor, constant: NEConstant.navigationHeight + NEConstant.statusBarHeight + 20), - searchTextField.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 20), - searchTextField.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: -20), - searchTextField.heightAnchor.constraint(equalToConstant: 32) - ]) - - NSLayoutConstraint.activate([ - tableView.rightAnchor.constraint(equalTo: self.view.rightAnchor), - tableView.leftAnchor.constraint(equalTo: self.view.leftAnchor), - tableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor), - tableView.topAnchor.constraint(equalTo: searchTextField.bottomAnchor,constant: 20) - ]) - - NSLayoutConstraint.activate([ - emptyView.rightAnchor.constraint(equalTo: tableView.rightAnchor), - emptyView.leftAnchor.constraint(equalTo: tableView.leftAnchor), - emptyView.bottomAnchor.constraint(equalTo: tableView.bottomAnchor), - emptyView.topAnchor.constraint(equalTo: tableView.topAnchor) - ]) - + return true } - func initialConfig() { - self.title = "历史记录" + //MARK: UITableViewDelegate, UITableViewDataSource + public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + viewmodel.searchResultInfos?.count ?? 0 } - - - //MARK: lazy method - private lazy var tableView:UITableView = { - let tableView = UITableView.init(frame: .zero, style: .plain) - tableView.translatesAutoresizingMaskIntoConstraints = false - tableView.separatorStyle = .none - tableView.delegate = self - tableView.dataSource = self - tableView.register(HistoryMessageCell.self, forCellReuseIdentifier: "\(NSStringFromClass(HistoryMessageCell.self))") - tableView.rowHeight = 65 - tableView.backgroundColor = .white - tableView.sectionHeaderHeight = 30 - tableView.sectionFooterHeight = 0 - return tableView - }() - - private lazy var searchTextField:SearchTextField = { - let textField = SearchTextField() - let leftImageView = UIImageView.init(image: coreLoader.loadImage("search_icon")) - textField.contentMode = .center - textField.leftView = leftImageView - textField.leftViewMode = .always - textField.placeholder = localizable("搜索") - textField.font = UIFont.systemFont(ofSize: 14) - textField.textColor = UIColor.ne_greyText - textField.translatesAutoresizingMaskIntoConstraints = false - textField.layer.cornerRadius = 8 - textField.backgroundColor = UIColor.init(hexString: "0xF2F4F5") - textField.clearButtonMode = .whileEditing - textField.returnKeyType = .search - textField.addTarget(self, action: #selector(searchTextFieldChange), for: .editingChanged) - textField.delegate = self - return textField - - }() - - private lazy var emptyView:NEEmptyDataView = { - let view = NEEmptyDataView(imageName: "emptyView", content: "暂无搜索结果",frame: CGRect.zero) - view.translatesAutoresizingMaskIntoConstraints = false - view.isHidden = true - return view - - }() - - //MARK: private method - @objc func searchTextFieldChange(textfield:SearchTextField){ - - if textfield.text?.count == 0 { - viewmodel.searchResultInfos?.removeAll() - tableView.reloadData() - } + public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell( + withIdentifier: "\(NSStringFromClass(HistoryMessageCell.self))", + for: indexPath + ) as! HistoryMessageCell + let cellModel = viewmodel.searchResultInfos?[indexPath.row] + cell.searchText = searchStr + cell.configData(message: cellModel) + return cell } -} - -extension TeamHistoryMessageController:UITextFieldDelegate { - public func textFieldShouldReturn(_ textField: UITextField) -> Bool { - - guard let searchText = textField.text else { - return false - } - if searchText.count <= 0 { - return false - } - guard let session = teamSession else { - return false + public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + let cellModel = viewmodel.searchResultInfos?[indexPath.row] + if cellModel?.imMessage?.session?.sessionType == .team { + if let sid = cellModel?.imMessage?.session?.sessionId, + let message = cellModel?.imMessage { + let session = NIMSession(sid, type: .team) + Router.shared.use( + PushTeamChatVCRouter, + parameters: ["nav": navigationController as Any, "session": session as Any, + "anchor": message], + closure: nil + ) } - weak var weakSelf = self - searchStr = searchText - let option = NIMMessageSearchOption() - option.searchContent = searchText - weakSelf?.viewmodel.searchMessages(session, option: option, { error, messages in - if error == nil { - if let msg = messages,msg.count > 0 { - weakSelf?.emptyView.isHidden = true - }else { - weakSelf?.emptyView.isHidden = false - } - weakSelf?.tableView.reloadData() - }else { - NELog.errorLog(weakSelf?.tag ?? "TeamHistoryMessageController", desc: "❌searchMessages failed, error = \(error!)") - } - }) - - return true + } } - } -extension TeamHistoryMessageController:UITableViewDelegate,UITableViewDataSource { - - public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return viewmodel.searchResultInfos?.count ?? 0 - } - - public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(withIdentifier: "\(NSStringFromClass(HistoryMessageCell.self))", for: indexPath) as! HistoryMessageCell - let cellModel = viewmodel.searchResultInfos?[indexPath.row] - cell.searchText = searchStr - cell.configData(message: cellModel) - return cell - - } - - public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - - let cellModel = viewmodel.searchResultInfos?[indexPath.row] - if cellModel?.imMessage?.session?.sessionType == .team { - - if let sid = cellModel?.imMessage?.session?.sessionId, let message = cellModel?.imMessage { - let session = NIMSession(sid, type: .team) - Router.shared.use(PushTeamChatVCRouter, parameters: ["nav": self.navigationController as Any, "session" : session as Any, "anchor": message], closure: nil) - } - - } - - } -} diff --git a/NETeamUIKit/NEKitTeamUI/Classes/Setting/TeamInfoViewController.swift b/NETeamUIKit/NEKitTeamUI/Classes/Setting/TeamInfoViewController.swift index b432c586..b8fbfa6e 100644 --- a/NETeamUIKit/NEKitTeamUI/Classes/Setting/TeamInfoViewController.swift +++ b/NETeamUIKit/NEKitTeamUI/Classes/Setting/TeamInfoViewController.swift @@ -1,118 +1,124 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NIMSDK -public class TeamInfoViewController: NEBaseViewController { +public class TeamInfoViewController: NEBaseViewController,UITableViewDelegate, UITableViewDataSource { + let viewmodel = TeamInfoViewModel() - let viewmodel = TeamInfoViewModel() - - var team: NIMTeam? - - public var cellClassDic = [SettingCellType.SettingArrowCell.rawValue: TeamArrowSettingCell.self, SettingCellType.SettingHeaderCell.rawValue: TeamSettingHeaderCell.self] - - lazy var contentTable: UITableView = { - let table = UITableView() - table.translatesAutoresizingMaskIntoConstraints = false - table.backgroundColor = NEConstant.hexRGB(0xF1F1F6) - table.dataSource = self - table.delegate = self - table.separatorColor = .clear - table.separatorStyle = .none - table.sectionHeaderHeight = 12.0 - table.tableFooterView = UIView(frame: CGRect(x: 0,y: 0,width: view.frame.size.width,height: 12)) - return table - }() - - public override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - if let type = team?.type, type == .normal { - title = "讨论组信息" - }else { - title = "群信息" - } - viewmodel.getData(team) - setupUI() - } - - func setupUI(){ - view.backgroundColor = NEConstant.hexRGB(0xF1F1F6) - view.addSubview(contentTable) - NSLayoutConstraint.activate([ - contentTable.leftAnchor.constraint(equalTo: view.leftAnchor), - contentTable.rightAnchor.constraint(equalTo: view.rightAnchor), - contentTable.topAnchor.constraint(equalTo: view.topAnchor), - contentTable.bottomAnchor.constraint(equalTo: view.bottomAnchor) - ]) - cellClassDic.forEach { (key: Int, value: BaseTeamSettingCell.Type) in - contentTable.register(value, forCellReuseIdentifier: "\(key)") - } - } - + var team: NIMTeam? - /* - // MARK: - Navigation + public var cellClassDic = [ + SettingCellType.SettingArrowCell.rawValue: TeamArrowSettingCell.self, + SettingCellType.SettingHeaderCell.rawValue: TeamSettingHeaderCell.self, + ] - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. + lazy var contentTable: UITableView = { + let table = UITableView() + table.translatesAutoresizingMaskIntoConstraints = false + table.backgroundColor = NEConstant.hexRGB(0xF1F1F6) + table.dataSource = self + table.delegate = self + table.separatorColor = .clear + table.separatorStyle = .none + table.sectionHeaderHeight = 12.0 + table + .tableFooterView = + UIView(frame: CGRect(x: 0, y: 0, width: view.frame.size.width, height: 12)) + return table + }() + + override public func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + if let type = team?.type, type == .normal { + title = "讨论组信息" + } else { + title = "群信息" } - */ + viewmodel.getData(team) + setupUI() + } -} + func setupUI() { + view.backgroundColor = NEConstant.hexRGB(0xF1F1F6) + view.addSubview(contentTable) + NSLayoutConstraint.activate([ + contentTable.leftAnchor.constraint(equalTo: view.leftAnchor), + contentTable.rightAnchor.constraint(equalTo: view.rightAnchor), + contentTable.topAnchor.constraint(equalTo: view.topAnchor), + contentTable.bottomAnchor.constraint(equalTo: view.bottomAnchor), + ]) + cellClassDic.forEach { (key: Int, value: BaseTeamSettingCell.Type) in + contentTable.register(value, forCellReuseIdentifier: "\(key)") + } + } -extension TeamInfoViewController: UITableViewDelegate, UITableViewDataSource { - + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ + //MARK: UITableViewDelegate, UITableViewDataSource public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return viewmodel.cellDatas.count + viewmodel.cellDatas.count } - - public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let model = viewmodel.cellDatas[indexPath.row] - if let cell = tableView.dequeueReusableCell(withIdentifier: "\(model.type)", for: indexPath) as? BaseTeamSettingCell { - cell.configure(model) - return cell - } - return UITableViewCell() + + public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let model = viewmodel.cellDatas[indexPath.row] + if let cell = tableView.dequeueReusableCell( + withIdentifier: "\(model.type)", + for: indexPath + ) as? BaseTeamSettingCell { + cell.configure(model) + return cell + } + return UITableViewCell() } public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - if indexPath.row == 0 { - let avatar = TeamAvatarViewController() - avatar.team = team - weak var weakSelf = self - avatar.block = { - if let t = weakSelf?.team { - weakSelf?.viewmodel.getData(t) - weakSelf?.contentTable.reloadData() - } - } - navigationController?.pushViewController(avatar, animated: true) - - }else if indexPath.row == 1 { - let nameController = TeamNameViewController() - nameController.team = team - navigationController?.pushViewController(nameController, animated: true) - }else if indexPath.row == 2 { - let intr = TeamIntroduceViewController() - intr.team = team - navigationController?.pushViewController(intr, animated: true) + if indexPath.row == 0 { + let avatar = TeamAvatarViewController() + avatar.team = team + weak var weakSelf = self + avatar.block = { + if let t = weakSelf?.team { + weakSelf?.viewmodel.getData(t) + weakSelf?.contentTable.reloadData() + } } + navigationController?.pushViewController(avatar, animated: true) + + } else if indexPath.row == 1 { + let nameController = TeamNameViewController() + nameController.team = team + navigationController?.pushViewController(nameController, animated: true) + } else if indexPath.row == 2 { + let intr = TeamIntroduceViewController() + intr.team = team + navigationController?.pushViewController(intr, animated: true) + } } - - public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - let model = viewmodel.cellDatas[indexPath.row] - return model.rowHeight + + public func tableView(_ tableView: UITableView, + heightForRowAt indexPath: IndexPath) -> CGFloat { + let model = viewmodel.cellDatas[indexPath.row] + return model.rowHeight } - - public func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { - return 12.0 + + public func tableView(_ tableView: UITableView, + heightForHeaderInSection section: Int) -> CGFloat { + 12.0 } - } + diff --git a/NETeamUIKit/NEKitTeamUI/Classes/Setting/TeamIntroduceViewController.swift b/NETeamUIKit/NEKitTeamUI/Classes/Setting/TeamIntroduceViewController.swift index e59a6284..cd5e7473 100644 --- a/NETeamUIKit/NEKitTeamUI/Classes/Setting/TeamIntroduceViewController.swift +++ b/NETeamUIKit/NEKitTeamUI/Classes/Setting/TeamIntroduceViewController.swift @@ -1,184 +1,183 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCommon import NIMSDK import NEKitTeam -public class TeamIntroduceViewController: NEBaseViewController { - +public class TeamIntroduceViewController: NEBaseViewController,UITextViewDelegate { // typealias SaveCompletion = () -> Void -// +// // var block: SaveCompletion? - var team: NIMTeam? - - let repo = TeamRepo() - - lazy var textView: UITextView = { - let text = UITextView() - text.translatesAutoresizingMaskIntoConstraints = false - text.textColor = NEConstant.hexRGB(0x333333) - text.font = NEConstant.defaultTextFont(14.0) - text.delegate = self - text.textContainerInset = UIEdgeInsets.zero - text.layoutManager.allowsNonContiguousLayout = false - return text - }() - - lazy var countLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.textColor = NEConstant.hexRGB(0xB3B7BC) - label.font = NEConstant.defaultTextFont(12.0) - return label - }() - - public override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - setupUI() - } - - func setupUI(){ - - addRightAction("保存", #selector(saveIntr), self) - - if let type = team?.type, type == .advanced { - title = "群介绍" - }else { - title = "讨论组介绍" - } - - view.backgroundColor = NEConstant.hexRGB(0xF1F1F6) - let backView = UIView() - backView.backgroundColor = .white - backView.translatesAutoresizingMaskIntoConstraints = false - view.addSubview(backView) - backView.clipsToBounds = false - backView.layer.cornerRadius = 8.0 - if #available(iOS 11.0, *) { - NSLayoutConstraint.activate([ - backView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20), - backView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 12.0), - backView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20), - backView.heightAnchor.constraint(equalToConstant: 170) - ]) - } else { - NSLayoutConstraint.activate([ - backView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20), - backView.topAnchor.constraint(equalTo: view.topAnchor, constant: 12.0), - backView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20), - backView.heightAnchor.constraint(equalToConstant: 170) - ]) - } + var team: NIMTeam? - backView.addSubview(textView) - NSLayoutConstraint.activate([ - textView.leftAnchor.constraint(equalTo: backView.leftAnchor, constant: 16.0), - textView.rightAnchor.constraint(equalTo: backView.rightAnchor, constant: -16.0), - textView.topAnchor.constraint(equalTo: backView.topAnchor, constant: 16.0), - textView.heightAnchor.constraint(equalToConstant: 120) - ]) - - textView.text = team?.intro - - backView.addSubview(countLabel) - NSLayoutConstraint.activate([ - countLabel.rightAnchor.constraint(equalTo: backView.rightAnchor, constant: -16), - countLabel.bottomAnchor.constraint(equalTo: backView.bottomAnchor, constant: -8.0) - ]) - - if let intr = team?.intro { - countLabel.text = "\(intr.count)/100" - }else { - countLabel.text = "0/100" - } - - if changePermission() == false { - textView.isEditable = false - rightNavBtn.isHidden = true - } - } - - func disableSubmit(){ - rightNavBtn.setTitleColor(NEConstant.hexRGBAlpha(0x337EFF,0.5), for: .normal) - rightNavBtn.isEnabled = false + let repo = TeamRepo() + + lazy var textView: UITextView = { + let text = UITextView() + text.translatesAutoresizingMaskIntoConstraints = false + text.textColor = NEConstant.hexRGB(0x333333) + text.font = NEConstant.defaultTextFont(14.0) + text.delegate = self + text.textContainerInset = UIEdgeInsets.zero + text.layoutManager.allowsNonContiguousLayout = false + return text + }() + + lazy var countLabel: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.textColor = NEConstant.hexRGB(0xB3B7BC) + label.font = NEConstant.defaultTextFont(12.0) + return label + }() + + override public func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + setupUI() + } + + func setupUI() { + addRightAction("保存", #selector(saveIntr), self) + + if let type = team?.type, type == .advanced { + title = "群介绍" + } else { + title = "讨论组介绍" } - - func enableSubmit(){ - rightNavBtn.setTitleColor(NEConstant.hexRGB(0x337EFF), for: .normal) - rightNavBtn.isEnabled = true + + view.backgroundColor = NEConstant.hexRGB(0xF1F1F6) + let backView = UIView() + backView.backgroundColor = .white + backView.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(backView) + backView.clipsToBounds = false + backView.layer.cornerRadius = 8.0 + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + backView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20), + backView.topAnchor.constraint( + equalTo: view.safeAreaLayoutGuide.topAnchor, + constant: 12.0 + ), + backView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20), + backView.heightAnchor.constraint(equalToConstant: 170), + ]) + } else { + NSLayoutConstraint.activate([ + backView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20), + backView.topAnchor.constraint(equalTo: view.topAnchor, constant: 12.0), + backView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20), + backView.heightAnchor.constraint(equalToConstant: 170), + ]) } - - /* - // MARK: - Navigation + backView.addSubview(textView) + NSLayoutConstraint.activate([ + textView.leftAnchor.constraint(equalTo: backView.leftAnchor, constant: 16.0), + textView.rightAnchor.constraint(equalTo: backView.rightAnchor, constant: -16.0), + textView.topAnchor.constraint(equalTo: backView.topAnchor, constant: 16.0), + textView.heightAnchor.constraint(equalToConstant: 120), + ]) + + textView.text = team?.intro + + backView.addSubview(countLabel) + NSLayoutConstraint.activate([ + countLabel.rightAnchor.constraint(equalTo: backView.rightAnchor, constant: -16), + countLabel.bottomAnchor.constraint(equalTo: backView.bottomAnchor, constant: -8.0), + ]) - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. + if let intr = team?.intro { + countLabel.text = "\(intr.count)/100" + } else { + countLabel.text = "0/100" } - */ - - func changePermission() -> Bool { - if let ownerId = team?.owner, IMKitLoginManager.instance.isMySelf(ownerId) { - return true - } - if let mode = team?.updateInfoMode, mode == .all { - return true - } - return false + + if changePermission() == false { + textView.isEditable = false + rightNavBtn.isHidden = true } + } -} + func disableSubmit() { + rightNavBtn.setTitleColor(NEConstant.hexRGBAlpha(0x337EFF, 0.5), for: .normal) + rightNavBtn.isEnabled = false + } -extension TeamIntroduceViewController: UITextViewDelegate { - - public func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { - let currentText = textView.text ?? "" - guard let stringRange = Range(range, in: currentText) else { return false } - let updatedText = currentText.replacingCharacters(in: stringRange, with: text) - return updatedText.count <= 100 + func enableSubmit() { + rightNavBtn.setTitleColor(NEConstant.hexRGB(0x337EFF), for: .normal) + rightNavBtn.isEnabled = true + } + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ + + func changePermission() -> Bool { + if let ownerId = team?.owner, IMKitLoginManager.instance.isMySelf(ownerId) { + return true + } + if let mode = team?.updateInfoMode, mode == .all { + return true } + return false + } - public func textViewDidChange(_ textView: UITextView) { - if var text = textView.text { - if let lang = textView.textInputMode?.primaryLanguage, lang == "zh-Hans", let selectRange = textView.markedTextRange { - let position = textView.position(from: selectRange.start, offset: 0) - if position == nil{ - if text.count > 30 { - text = String(text.prefix(30)) - textView.text = String(text.prefix(30)) - } - countLabel.text = "\(text.count)/100" - } - }else { - countLabel.text = "\(text.count)/100" - } + @objc func saveIntr() { + textView.resignFirstResponder() + if let teamid = team?.teamId { + let text = textView.text ?? "" + weak var weakSelf = self + view.makeToastActivity(.center) + repo.updateTeamIntroduce(text, teamid) { error in + weakSelf?.view.hideToastActivity() + if let err = error { + weakSelf?.showToast(err.localizedDescription) + } else { + weakSelf?.team?.intro = text + weakSelf?.navigationController?.popViewController(animated: true) + } } + } } - - @objc func saveIntr(){ - - textView.resignFirstResponder() - if let teamid = team?.teamId { - let text = textView.text ?? "" - weak var weakSelf = self - view.makeToastActivity(.center) - repo.updateTeamIntroduce(text, teamid) { error in - weakSelf?.view.hideToastActivity() - if let err = error { - weakSelf?.showToast(err.localizedDescription) - }else { - weakSelf?.team?.intro = text - weakSelf?.navigationController?.popViewController(animated: true) - } + //MARK: UITextViewDelegate + public func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, + replacementText text: String) -> Bool { + let currentText = textView.text ?? "" + guard let stringRange = Range(range, in: currentText) else { return false } + let updatedText = currentText.replacingCharacters(in: stringRange, with: text) + return updatedText.count <= 100 + } + + public func textViewDidChange(_ textView: UITextView) { + if var text = textView.text { + if let lang = textView.textInputMode?.primaryLanguage, lang == "zh-Hans", + let selectRange = textView.markedTextRange { + let position = textView.position(from: selectRange.start, offset: 0) + if position == nil { + if text.count > 30 { + text = String(text.prefix(30)) + textView.text = String(text.prefix(30)) } + countLabel.text = "\(text.count)/100" + } + } else { + countLabel.text = "\(text.count)/100" } + } } } + diff --git a/NETeamUIKit/NEKitTeamUI/Classes/Setting/TeamMembersController.swift b/NETeamUIKit/NEKitTeamUI/Classes/Setting/TeamMembersController.swift index 74dfe567..058e85f0 100644 --- a/NETeamUIKit/NEKitTeamUI/Classes/Setting/TeamMembersController.swift +++ b/NETeamUIKit/NEKitTeamUI/Classes/Setting/TeamMembersController.swift @@ -1,209 +1,224 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitTeam import NEKitCore // +public class TeamMembersController: NEBaseViewController,UITableViewDelegate, UITableViewDataSource { + var datas: [TeamMemberInfoModel]? -public class TeamMembersController: NEBaseViewController { - - var datas: [TeamMemberInfoModel]? - - var ownerId: String? - - var isSenior = false - - var searchDatas = [TeamMemberInfoModel]() - - lazy var searchTextField: UITextField = { - let field = UITextField() - field.translatesAutoresizingMaskIntoConstraints = false - field.placeholder = "搜索好友" - field.textColor = .ne_greyText - field.font = UIFont.systemFont(ofSize: 14.0) - field.backgroundColor = UIColor.ne_backcolor - return field - }() - - lazy var contentTable: UITableView = { - let table = UITableView() - table.translatesAutoresizingMaskIntoConstraints = false + var ownerId: String? + + var isSenior = false + + var searchDatas = [TeamMemberInfoModel]() + + lazy var searchTextField: UITextField = { + let field = UITextField() + field.translatesAutoresizingMaskIntoConstraints = false + field.placeholder = "搜索好友" + field.textColor = .ne_greyText + field.font = UIFont.systemFont(ofSize: 14.0) + field.backgroundColor = UIColor.ne_backcolor + return field + }() + + lazy var contentTable: UITableView = { + let table = UITableView() + table.translatesAutoresizingMaskIntoConstraints = false // table.backgroundColor = NEConstant.hexRGB(0xF1F1F6) - table.backgroundColor = .white - table.dataSource = self - table.delegate = self - table.separatorColor = .clear - table.separatorStyle = .none - table.sectionHeaderHeight = 12.0 - table.tableFooterView = UIView(frame: CGRect(x: 0,y: 0,width: view.frame.size.width,height: 12)) - if #available(iOS 15.0, *) { - table.sectionHeaderTopPadding = 0.0 - } - table.keyboardDismissMode = .onDrag + table.backgroundColor = .white + table.dataSource = self + table.delegate = self + table.separatorColor = .clear + table.separatorStyle = .none + table.sectionHeaderHeight = 12.0 + table + .tableFooterView = + UIView(frame: CGRect(x: 0, y: 0, width: view.frame.size.width, height: 12)) + if #available(iOS 15.0, *) { + table.sectionHeaderTopPadding = 0.0 + } + table.keyboardDismissMode = .onDrag // table.bounces = false - return table - }() + return table + }() + + override public func viewDidLoad() { + super.viewDidLoad() - public override func viewDidLoad() { - super.viewDidLoad() + // Do any additional setup after loading the view. + setupUI() + } - // Do any additional setup after loading the view. - setupUI() + func setupUI() { + if isSenior { + title = "群成员" + } else { + title = "讨论组成员" } - - func setupUI(){ - - if isSenior { - title = "群成员" - }else { - title = "讨论组成员" - } - - let back = UIView() - back.backgroundColor = .ne_backcolor - back.translatesAutoresizingMaskIntoConstraints = false - back.clipsToBounds = true - back.layer.cornerRadius = 4.0 - - view.addSubview(back) - - if #available(iOS 11.0, *) { - NSLayoutConstraint.activate([ - back.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 4.0), - back.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20), - back.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20), - back.heightAnchor.constraint(equalToConstant: 32) - ]) - } else { - // Fallback on earlier versions - NSLayoutConstraint.activate([ - back.topAnchor.constraint(equalTo: view.topAnchor, constant: 4.0), - back.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20), - back.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20), - back.heightAnchor.constraint(equalToConstant: 32) - ]) - } - - let searchIcon = UIImageView() - searchIcon.image = coreLoader.loadImage("search_icon") - searchIcon.translatesAutoresizingMaskIntoConstraints = false - back.addSubview(searchIcon) - NSLayoutConstraint.activate([ - searchIcon.centerYAnchor.constraint(equalTo: back.centerYAnchor), - searchIcon.leftAnchor.constraint(equalTo: back.leftAnchor, constant: 16.0) - ]) - - back.addSubview(searchTextField) - NSLayoutConstraint.activate([ - searchTextField.leftAnchor.constraint(equalTo: back.leftAnchor, constant: 36.0), - searchTextField.rightAnchor.constraint(equalTo: back.rightAnchor, constant: -16.0), - searchTextField.topAnchor.constraint(equalTo: back.topAnchor), - searchTextField.bottomAnchor.constraint(equalTo: back.bottomAnchor) - ]) - - - view.addSubview(contentTable) - NSLayoutConstraint.activate([ - contentTable.leftAnchor.constraint(equalTo: view.leftAnchor), - contentTable.rightAnchor.constraint(equalTo: view.rightAnchor), - contentTable.topAnchor.constraint(equalTo: back.bottomAnchor, constant: 10), - contentTable.bottomAnchor.constraint(equalTo: view.bottomAnchor) - ]) - - contentTable.register(TeamMemberCell.self, forCellReuseIdentifier: "\(TeamMemberCell.self)") - - NotificationCenter.default.addObserver(self, selector: #selector(textChange), name: UITextField.textDidChangeNotification, object: nil) + + let back = UIView() + back.backgroundColor = .ne_backcolor + back.translatesAutoresizingMaskIntoConstraints = false + back.clipsToBounds = true + back.layer.cornerRadius = 4.0 + + view.addSubview(back) + + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + back.topAnchor.constraint( + equalTo: view.safeAreaLayoutGuide.topAnchor, + constant: 4.0 + ), + back.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20), + back.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20), + back.heightAnchor.constraint(equalToConstant: 32), + ]) + } else { + // Fallback on earlier versions + NSLayoutConstraint.activate([ + back.topAnchor.constraint(equalTo: view.topAnchor, constant: 4.0), + back.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20), + back.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20), + back.heightAnchor.constraint(equalToConstant: 32), + ]) } - - /* - // MARK: - Navigation + let searchIcon = UIImageView() + searchIcon.image = coreLoader.loadImage("search_icon") + searchIcon.translatesAutoresizingMaskIntoConstraints = false + back.addSubview(searchIcon) + NSLayoutConstraint.activate([ + searchIcon.centerYAnchor.constraint(equalTo: back.centerYAnchor), + searchIcon.leftAnchor.constraint(equalTo: back.leftAnchor, constant: 16.0), + ]) + + back.addSubview(searchTextField) + NSLayoutConstraint.activate([ + searchTextField.leftAnchor.constraint(equalTo: back.leftAnchor, constant: 36.0), + searchTextField.rightAnchor.constraint(equalTo: back.rightAnchor, constant: -16.0), + searchTextField.topAnchor.constraint(equalTo: back.topAnchor), + searchTextField.bottomAnchor.constraint(equalTo: back.bottomAnchor), + ]) + + view.addSubview(contentTable) + NSLayoutConstraint.activate([ + contentTable.leftAnchor.constraint(equalTo: view.leftAnchor), + contentTable.rightAnchor.constraint(equalTo: view.rightAnchor), + contentTable.topAnchor.constraint(equalTo: back.bottomAnchor, constant: 10), + contentTable.bottomAnchor.constraint(equalTo: view.bottomAnchor), + ]) + + contentTable.register(TeamMemberCell.self, forCellReuseIdentifier: "\(TeamMemberCell.self)") + + NotificationCenter.default.addObserver( + self, + selector: #selector(textChange), + name: UITextField.textDidChangeNotification, + object: nil + ) + } - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ + + func isOwner(_ userId: String?) -> Bool { + if isSenior == false { + return false } - */ - - func isOwner(_ userId: String?) -> Bool { - - if isSenior == false { - return false - } - if let uid = userId, let oid = ownerId, uid == oid { - return true - } - return false + if let uid = userId, let oid = ownerId, uid == oid { + return true } - - @objc func textChange(){ - searchDatas.removeAll() - if let text = searchTextField.text, text.count > 0 { - datas?.forEach({ model in - if let uid = model.nimUser?.userId, uid.contains(text) { - searchDatas.append(model) - }else if let nick = model.nimUser?.userInfo?.nickName, nick.contains(text){ - searchDatas.append(model) - }else if let alias = model.nimUser?.alias, alias.contains(text) { - searchDatas.append(model) - }else if let tNick = model.teamMember?.nickname, tNick.contains(text) { - searchDatas.append(model) - } - }) + return false + } + + @objc func textChange() { + searchDatas.removeAll() + if let text = searchTextField.text, text.count > 0 { + datas?.forEach { model in + if let uid = model.nimUser?.userId, uid.contains(text) { + searchDatas.append(model) + } else if let nick = model.nimUser?.userInfo?.nickName, nick.contains(text) { + searchDatas.append(model) + } else if let alias = model.nimUser?.alias, alias.contains(text) { + searchDatas.append(model) + } else if let tNick = model.teamMember?.nickname, tNick.contains(text) { + searchDatas.append(model) } - contentTable.reloadData() + } } - - deinit{ - NotificationCenter.default.removeObserver(self) + contentTable.reloadData() + } + func getRealModel(_ index: Int) -> TeamMemberInfoModel? { + if let text = searchTextField.text, text.count > 0 { + return searchDatas[index] + } + return datas?[index] } - - -} - -extension TeamMembersController: UITableViewDelegate, UITableViewDataSource { - func getRealModel(_ index: Int) -> TeamMemberInfoModel?{ - if let text = searchTextField.text, text.count > 0 { - return searchDatas[index] - } - return datas?[index] - } + deinit { + NotificationCenter.default.removeObserver(self) + } + + + //MARK: UITableViewDelegate, UITableViewDataSource + public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - if let text = searchTextField.text, text.count > 0 { - return searchDatas.count - } - return datas?.count ?? 0 + if let text = searchTextField.text, text.count > 0 { + return searchDatas.count + } + return datas?.count ?? 0 } - - public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - if let cell = tableView.dequeueReusableCell(withIdentifier: "\(TeamMemberCell.self)", for: indexPath) as? TeamMemberCell { - if let model = getRealModel(indexPath.row){ - cell.configure(model) - cell.ownerLabel.isHidden = !isOwner(model.nimUser?.userId) - } - return cell + + public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + if let cell = tableView.dequeueReusableCell( + withIdentifier: "\(TeamMemberCell.self)", + for: indexPath + ) as? TeamMemberCell { + if let model = getRealModel(indexPath.row) { + cell.configure(model) + cell.ownerLabel.isHidden = !isOwner(model.nimUser?.userId) } - return UITableViewCell() + return cell + } + return UITableViewCell() } - - public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - return 62.0 + + public func tableView(_ tableView: UITableView, + heightForRowAt indexPath: IndexPath) -> CGFloat { + 62.0 } - + public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - if let model = getRealModel(indexPath.row), let user = model.nimUser { - if IMKitLoginManager.instance.isMySelf(user.userId) { - Router.shared.use(MeSettingRouter, parameters: ["nav": navigationController as Any], closure: nil) - }else { - Router.shared.use(ContactUserInfoPageRouter, parameters: ["nav": navigationController as Any, "nim_user": user], closure: nil) - } - + if let model = getRealModel(indexPath.row), let user = model.nimUser { + if IMKitLoginManager.instance.isMySelf(user.userId) { + Router.shared.use( + MeSettingRouter, + parameters: ["nav": navigationController as Any], + closure: nil + ) + } else { + Router.shared.use( + ContactUserInfoPageRouter, + parameters: ["nav": navigationController as Any, "nim_user": user], + closure: nil + ) } + } } } diff --git a/NETeamUIKit/NEKitTeamUI/Classes/Setting/TeamNameViewController.swift b/NETeamUIKit/NEKitTeamUI/Classes/Setting/TeamNameViewController.swift index b7d8e92b..2d253601 100644 --- a/NETeamUIKit/NEKitTeamUI/Classes/Setting/TeamNameViewController.swift +++ b/NETeamUIKit/NEKitTeamUI/Classes/Setting/TeamNameViewController.swift @@ -1,6 +1,7 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NIMSDK @@ -8,221 +9,229 @@ import NEKitCommon import NEKitTeam enum ChangeType { - case TeamName - case NickName + case TeamName + case NickName } -public class TeamNameViewController: NEBaseViewController { - - var team: NIMTeam? + +public class TeamNameViewController: NEBaseViewController,UITextFieldDelegate { + var team: NIMTeam? // var user: NIMUser? - var type = ChangeType.TeamName - var teamMember: NIMTeamMember? - var repo = TeamRepo() - - lazy var countLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.textColor = NEConstant.hexRGB(0xB3B7BC) - label.font = NEConstant.defaultTextFont(12.0) - return label - }() - - lazy var textField: UITextField = { - let text = UITextField() - text.translatesAutoresizingMaskIntoConstraints = false - text.textColor = NEConstant.hexRGB(0x333333) - text.font = NEConstant.defaultTextFont(14.0) - text.delegate = self - text.clearButtonMode = .always - - return text - }() - - public override func viewDidLoad() { - super.viewDidLoad() - setupUI() + var type = ChangeType.TeamName + var teamMember: NIMTeamMember? + var repo = TeamRepo() + + lazy var countLabel: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.textColor = NEConstant.hexRGB(0xB3B7BC) + label.font = NEConstant.defaultTextFont(12.0) + return label + }() + + lazy var textField: UITextField = { + let text = UITextField() + text.translatesAutoresizingMaskIntoConstraints = false + text.textColor = NEConstant.hexRGB(0x333333) + text.font = NEConstant.defaultTextFont(14.0) + text.delegate = self + text.clearButtonMode = .always + + return text + }() + + override public func viewDidLoad() { + super.viewDidLoad() + setupUI() + } + + func setupUI() { + view.backgroundColor = NEConstant.hexRGB(0xF1F1F6) + let backView = UIView() + backView.backgroundColor = .white + backView.clipsToBounds = true + backView.layer.cornerRadius = 8.0 + backView.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(backView) + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + backView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20.0), + backView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20), + backView.topAnchor.constraint( + equalTo: view.safeAreaLayoutGuide.topAnchor, + constant: 12 + ), + backView.heightAnchor.constraint(equalToConstant: 60), + ]) + } else { + NSLayoutConstraint.activate([ + backView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20.0), + backView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20), + backView.topAnchor.constraint(equalTo: view.topAnchor, constant: 12), + backView.heightAnchor.constraint(equalToConstant: 60), + ]) } - - func setupUI(){ - view.backgroundColor = NEConstant.hexRGB(0xF1F1F6) - let backView = UIView() - backView.backgroundColor = .white - backView.clipsToBounds = true - backView.layer.cornerRadius = 8.0 - backView.translatesAutoresizingMaskIntoConstraints = false - view.addSubview(backView) - if #available(iOS 11.0, *) { - NSLayoutConstraint.activate([ - backView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20.0), - backView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20), - backView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 12), - backView.heightAnchor.constraint(equalToConstant: 60) - ]) - }else { - NSLayoutConstraint.activate([ - backView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20.0), - backView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20), - backView.topAnchor.constraint(equalTo: view.topAnchor, constant: 12), - backView.heightAnchor.constraint(equalToConstant: 60) - ]) - } - - backView.addSubview(textField) - NSLayoutConstraint.activate([ - textField.leftAnchor.constraint(equalTo: backView.leftAnchor, constant: 16), - textField.rightAnchor.constraint(equalTo: backView.rightAnchor, constant: -12), - textField.topAnchor.constraint(equalTo: backView.topAnchor, constant: 0), - textField.heightAnchor.constraint(equalToConstant: 44) + + backView.addSubview(textField) + NSLayoutConstraint.activate([ + textField.leftAnchor.constraint(equalTo: backView.leftAnchor, constant: 16), + textField.rightAnchor.constraint(equalTo: backView.rightAnchor, constant: -12), + textField.topAnchor.constraint(equalTo: backView.topAnchor, constant: 0), + textField.heightAnchor.constraint(equalToConstant: 44), // textField.bottomAnchor.constraint(equalTo: backView.bottomAnchor, constant: 0) - ]) - - backView.addSubview(countLabel) - NSLayoutConstraint.activate([ - countLabel.rightAnchor.constraint(equalTo: backView.rightAnchor, constant: -16), - countLabel.bottomAnchor.constraint(equalTo: backView.bottomAnchor, constant: -8.0) - ]) - - var name = "" - if type == .TeamName, let n = team?.teamName { - name = n - - if changePermission() == false { + ]) + + backView.addSubview(countLabel) + NSLayoutConstraint.activate([ + countLabel.rightAnchor.constraint(equalTo: backView.rightAnchor, constant: -16), + countLabel.bottomAnchor.constraint(equalTo: backView.bottomAnchor, constant: -8.0), + ]) + + var name = "" + if type == .TeamName, let n = team?.teamName { + name = n + + if changePermission() == false { // disableSubmit() - rightNavBtn.isHidden = true - textField.clearButtonMode = .never - textField.isEnabled = false - } - if let teamType = team?.type, teamType == .normal { - title = "讨论组名称" - }else { - title = "群名称" - } - - }else if type == .NickName, let n = teamMember?.nickname { - title = "我在群里的昵称" - name = n - } - - countLabel.text = "\(name.count)/30" - textField.text = name - - if name.count <= 0, type != .NickName { - disableSubmit() - } - - NotificationCenter.default.addObserver(self, selector: #selector(textFieldChange), name: UITextField.textDidChangeNotification, object: textField) - - addRightAction("保存", #selector(saveName), self) - - - + rightNavBtn.isHidden = true + textField.clearButtonMode = .never + textField.isEnabled = false + } + if let teamType = team?.type, teamType == .normal { + title = "讨论组名称" + } else { + title = "群名称" + } + + } else if type == .NickName, let n = teamMember?.nickname { + title = "我在群里的昵称" + name = n } - - /* - // MARK: - Navigation + countLabel.text = "\(name.count)/30" + textField.text = name - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. + if name.count <= 0, type != .NickName { + disableSubmit() } - */ - - func changePermission() -> Bool { - - if let type = team?.type, type == .normal { - return true - } - - if let ownerId = team?.owner, IMKitLoginManager.instance.isMySelf(ownerId) { - return true - } - if let mode = team?.updateInfoMode, mode == .all { - return true - } - return false + + NotificationCenter.default.addObserver( + self, + selector: #selector(textFieldChange), + name: UITextField.textDidChangeNotification, + object: textField + ) + + addRightAction("保存", #selector(saveName), self) + } + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ + + func changePermission() -> Bool { + if let type = team?.type, type == .normal { + return true } - - func disableSubmit(){ - rightNavBtn.setTitleColor(NEConstant.hexRGBAlpha(0x337EFF,0.5), for: .normal) - rightNavBtn.isEnabled = false + + if let ownerId = team?.owner, IMKitLoginManager.instance.isMySelf(ownerId) { + return true } - - func enableSubmit(){ - rightNavBtn.setTitleColor(NEConstant.hexRGB(0x337EFF), for: .normal) - rightNavBtn.isEnabled = true + if let mode = team?.updateInfoMode, mode == .all { + return true } + return false + } -} + func disableSubmit() { + rightNavBtn.setTitleColor(NEConstant.hexRGBAlpha(0x337EFF, 0.5), for: .normal) + rightNavBtn.isEnabled = false + } -extension TeamNameViewController: UITextFieldDelegate { + func enableSubmit() { + rightNavBtn.setTitleColor(NEConstant.hexRGB(0x337EFF), for: .normal) + rightNavBtn.isEnabled = true + } - public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { - - if let text = (textField.text as NSString?)?.replacingCharacters(in: range, with: string), text.count > 30 { - return false - } - return true - } + //MARK: objc 方法 @objc func textFieldChange() { - if var text = textField.text { - if let lang = textField.textInputMode?.primaryLanguage, lang == "zh-Hans", let selectRange = textField.markedTextRange { - let position = textField.position(from: selectRange.start, offset: 0) - if position == nil{ - if text.count > 30 { - text = String(text.prefix(30)) - textField.text = String(text.prefix(30)) - } - figureTextCount(text) - } - }else { - figureTextCount(text) + if var text = textField.text { + if let lang = textField.textInputMode?.primaryLanguage, lang == "zh-Hans", + let selectRange = textField.markedTextRange { + let position = textField.position(from: selectRange.start, offset: 0) + if position == nil { + if text.count > 30 { + text = String(text.prefix(30)) + textField.text = String(text.prefix(30)) } + figureTextCount(text) + } + } else { + figureTextCount(text) } + } } - func figureTextCount(_ text: String){ - countLabel.text = "\(text.count)/30" - if type == .NickName { - return + @objc func saveName() { + weak var weakSelf = self + textField.resignFirstResponder() + if type == .TeamName, let tid = team?.teamId { + let n = textField.text ?? "" + view.makeToastActivity(.center) + repo.updateTeamName(n, tid) { error in + weakSelf?.view.hideToastActivity() + if let err = error { + weakSelf?.showToast(err.localizedDescription) + } else { + weakSelf?.team?.teamName = n + weakSelf?.navigationController?.popViewController(animated: true) + } } - if text.count > 0 { - enableSubmit() - }else { - disableSubmit() + } else if type == .NickName, let tid = team?.teamId, let uid = teamMember?.userId { + let n = textField.text ?? "" + view.makeToastActivity(.center) + repo.updateMemberNick(uid, n, tid) { error in + + weakSelf?.view.hideToastActivity() + if let err = error { + weakSelf?.showToast(err.localizedDescription) + } else { + weakSelf?.navigationController?.popViewController(animated: true) + } } + } } - - @objc func saveName(){ - weak var weakSelf = self - textField.resignFirstResponder() - if type == .TeamName, let tid = team?.teamId { - let n = textField.text ?? "" - view.makeToastActivity(.center) - repo.updateTeamName(n, tid) { error in - weakSelf?.view.hideToastActivity() - if let err = error { - weakSelf?.showToast(err.localizedDescription) - }else { - weakSelf?.team?.teamName = n - weakSelf?.navigationController?.popViewController(animated: true) - } - } - }else if type == .NickName, let tid = team?.teamId, let uid = teamMember?.userId{ - let n = textField.text ?? "" - view.makeToastActivity(.center) - repo.updateMemberNick(uid, n, tid) { error in - - weakSelf?.view.hideToastActivity() - if let err = error { - weakSelf?.showToast(err.localizedDescription) - }else { - weakSelf?.navigationController?.popViewController(animated: true) - } - } - } + //MAKR: UITextFieldDelegate + public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, + replacementString string: String) -> Bool { + if let text = (textField.text as NSString?)?.replacingCharacters(in: range, with: string), + text.count > 30 { + return false + } + return true } } + +extension TeamNameViewController { + + func figureTextCount(_ text: String) { + countLabel.text = "\(text.count)/30" + if type == .NickName { + return + } + if text.count > 0 { + enableSubmit() + } else { + disableSubmit() + } + } + + +} diff --git a/NETeamUIKit/NEKitTeamUI/Classes/Setting/TeamSettingViewController.swift b/NETeamUIKit/NEKitTeamUI/Classes/Setting/TeamSettingViewController.swift index 6d65152f..b170c709 100644 --- a/NETeamUIKit/NEKitTeamUI/Classes/Setting/TeamSettingViewController.swift +++ b/NETeamUIKit/NEKitTeamUI/Classes/Setting/TeamSettingViewController.swift @@ -1,687 +1,714 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCommonUI import NEKitCoreIM import NIMSDK -public class TeamSettingViewController: NEBaseViewController { - - let viewmodel = TeamSettingViewModel() - - var teamId: String? - - var addBtnWidth: NSLayoutConstraint? - - public var cellClassDic = [SettingCellType.SettingArrowCell.rawValue: TeamArrowSettingCell.self, SettingCellType.SettingSwitchCell.rawValue: TeamSettingSwitchCell.self, SettingCellType.SettingSelectCell.rawValue: TeamSettingSelectCell.self] - - lazy var contentTable: UITableView = { - let table = UITableView() - table.translatesAutoresizingMaskIntoConstraints = false - table.backgroundColor = NEConstant.hexRGB(0xF1F1F6) - table.dataSource = self - table.delegate = self - table.separatorColor = .clear - table.separatorStyle = .none - table.sectionHeaderHeight = 12.0 - table.tableFooterView = UIView(frame: CGRect(x: 0,y: 0,width: view.frame.size.width,height: 12)) - if #available(iOS 15.0, *) { - table.sectionHeaderTopPadding = 0.0 - } - return table - }() - - lazy var teamHeader: NEUserHeaderView = { - let imageView = NEUserHeaderView(frame: .zero) - imageView.translatesAutoresizingMaskIntoConstraints = false - imageView.clipsToBounds = true - imageView.titleLabel.font = NEConstant.defaultTextFont(16.0) - imageView.layer.cornerRadius = 21.0 - return imageView - }() - - lazy var teamNameLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.font = NEConstant.defaultTextFont(16.0) - label.textColor = NEConstant.hexRGB(0x333333) - return label - }() - - lazy var memberCountLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.font = NEConstant.defaultTextFont(16.0) - label.textColor = NEConstant.hexRGB(0x999999) - return label - }() - - lazy var userinfoCollection: UICollectionView = { - let flow = UICollectionViewFlowLayout() - flow.scrollDirection = .horizontal - flow.minimumLineSpacing = 0 - flow.minimumInteritemSpacing = 0 - let collection = UICollectionView(frame: .zero, collectionViewLayout: flow) - collection.translatesAutoresizingMaskIntoConstraints = false - collection.delegate = self - collection.dataSource = self - collection.backgroundColor = .clear - collection.showsHorizontalScrollIndicator = false - return collection - }() - - lazy var addBtn: ExpandButton = { - let button = ExpandButton() - button.translatesAutoresizingMaskIntoConstraints = false - button.setImage(coreLoader.loadImage("add"), for: .normal) - return button - }() - - public override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - if let model = viewmodel.teamInfoModel { - if let url = model.team?.avatarUrl { - teamHeader.sd_setImage(with: URL(string: url)) - } - if let name = model.team?.teamName { - teamNameLabel.text = name - } - } - } - - public override func viewDidLoad() { - super.viewDidLoad() - title = localizable("setting") - weak var weakSelf = self - viewmodel.delegate = self - if let tid = teamId { - viewmodel.getTeamInfo(tid) { error in - if let err = error { - weakSelf?.showToast(err.localizedDescription) - }else { - weakSelf?.contentTable.tableHeaderView = weakSelf?.getHeaderView() - weakSelf?.contentTable.tableFooterView = weakSelf?.getFooterView() - weakSelf?.contentTable.reloadData() - weakSelf?.userinfoCollection.reloadData() - } - } - } - // Do any additional setup after loading the view. - setupUI() - } - - func setupUI(){ - view.backgroundColor = NEConstant.hexRGB(0xF1F1F6) - view.addSubview(contentTable) - NSLayoutConstraint.activate([ - contentTable.leftAnchor.constraint(equalTo: view.leftAnchor), - contentTable.rightAnchor.constraint(equalTo: view.rightAnchor), - contentTable.topAnchor.constraint(equalTo: view.topAnchor), - contentTable.bottomAnchor.constraint(equalTo: view.bottomAnchor) - ]) - cellClassDic.forEach { (key: Int, value: BaseTeamSettingCell.Type) in - contentTable.register(value, forCellReuseIdentifier: "\(key)") - } - } - - func getHeaderView() -> UIView { - let back = UIView() - back.frame = CGRect(x: 0, y: 0, width:view.frame.size.width , height: 172) - let cornerView = UIView() - back.addSubview(cornerView) - cornerView.backgroundColor = .white - cornerView.clipsToBounds = true - cornerView.translatesAutoresizingMaskIntoConstraints = false - cornerView.layer.cornerRadius = 8.0 - NSLayoutConstraint.activate([ - cornerView.leftAnchor.constraint(equalTo: back.leftAnchor, constant: 20), - cornerView.rightAnchor.constraint(equalTo: back.rightAnchor, constant: -20), - cornerView.bottomAnchor.constraint(equalTo: back.bottomAnchor), - cornerView.heightAnchor.constraint(equalToConstant: 160) - ]) - - cornerView.addSubview(teamHeader) - NSLayoutConstraint.activate([ - teamHeader.leftAnchor.constraint(equalTo: cornerView.leftAnchor, constant: 16), - teamHeader.topAnchor.constraint(equalTo: cornerView.topAnchor, constant: 16), - teamHeader.widthAnchor.constraint(equalToConstant: 42), - teamHeader.heightAnchor.constraint(equalToConstant: 42) - ]) - if let url = viewmodel.teamInfoModel?.team?.avatarUrl { - print("icon url : ", url) - teamHeader.sd_setImage(with: URL(string: url), completed: nil) - }else { - if let tid = teamId { - if let name = viewmodel.teamInfoModel?.team?.getShowName() { - teamHeader.setTitle(name) - } - teamHeader.backgroundColor = UIColor.colorWithString(string: "\(tid)") - } - } - - teamNameLabel.text = viewmodel.teamInfoModel?.team?.getShowName() - - - cornerView.addSubview(teamNameLabel) - NSLayoutConstraint.activate([ - teamNameLabel.leftAnchor.constraint(equalTo: teamHeader.rightAnchor, constant: 11), - teamNameLabel.centerYAnchor.constraint(equalTo: teamHeader.centerYAnchor), - teamNameLabel.rightAnchor.constraint(equalTo: cornerView.rightAnchor, constant: -34) - ]) - - let arrow = UIImageView() - arrow.translatesAutoresizingMaskIntoConstraints = false - arrow.image = coreLoader.loadImage("arrowRight") - cornerView.addSubview(arrow) - NSLayoutConstraint.activate([ - arrow.centerYAnchor.constraint(equalTo: teamHeader.centerYAnchor), - arrow.rightAnchor.constraint(equalTo: cornerView.rightAnchor, constant: -16) - ]) - - let line = UIView() - line.translatesAutoresizingMaskIntoConstraints = false - line.backgroundColor = NEConstant.hexRGB(0xF5F8FC) - cornerView.addSubview(line) - NSLayoutConstraint.activate([ - line.heightAnchor.constraint(equalToConstant: 1.0), - line.rightAnchor.constraint(equalTo: cornerView.rightAnchor), - line.leftAnchor.constraint(equalTo: cornerView.leftAnchor, constant: 16.0), - line.topAnchor.constraint(equalTo: teamHeader.bottomAnchor, constant: 12.0) - ]) - - let memberLabel = UILabel() - cornerView.addSubview(memberLabel) - memberLabel.translatesAutoresizingMaskIntoConstraints = false - memberLabel.textColor = NEConstant.hexRGB(0x333333) - memberLabel.font = NEConstant.defaultTextFont(16.0) - cornerView.addSubview(memberLabel) - NSLayoutConstraint.activate([ - memberLabel.leftAnchor.constraint(equalTo: line.leftAnchor), - memberLabel.topAnchor.constraint(equalTo: line.bottomAnchor, constant: 12) - ]) - - if let type = viewmodel.teamInfoModel?.team?.type, type == .advanced { - memberLabel.text = localizable("group_memmber") - }else { - memberLabel.text = localizable("discuss_mebmer") - } - - let memberArrow = UIImageView() - cornerView.addSubview(memberArrow) - memberArrow.translatesAutoresizingMaskIntoConstraints = false - memberArrow.image = coreLoader.loadImage("arrowRight") - NSLayoutConstraint.activate([ - memberArrow.rightAnchor.constraint(equalTo: arrow.rightAnchor), - memberArrow.centerYAnchor.constraint(equalTo: memberLabel.centerYAnchor) - ]) - - let memberListBtn = UIButton() - cornerView.addSubview(memberListBtn) - memberListBtn.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - memberListBtn.leftAnchor.constraint(equalTo: memberLabel.leftAnchor), - memberListBtn.rightAnchor.constraint(equalTo: memberArrow.rightAnchor), - memberListBtn.centerYAnchor.constraint(equalTo: memberLabel.centerYAnchor), - memberListBtn.heightAnchor.constraint(equalToConstant: 40) - ]) - memberListBtn.addTarget(self, action: #selector(toMemberList), for: .touchUpInside) - - cornerView.addSubview(memberCountLabel) - NSLayoutConstraint.activate([ - memberCountLabel.rightAnchor.constraint(equalTo: memberArrow.leftAnchor, constant: -2), - memberCountLabel.centerYAnchor.constraint(equalTo: memberArrow.centerYAnchor) - ]) - memberCountLabel.text = "\(viewmodel.teamInfoModel?.team?.memberNumber ?? 0)" - - - cornerView.addSubview(addBtn) - addBtnWidth = addBtn.widthAnchor.constraint(equalToConstant: 32) - addBtnWidth?.isActive = true - NSLayoutConstraint.activate([ - addBtn.leftAnchor.constraint(equalTo: line.leftAnchor), - addBtn.topAnchor.constraint(equalTo: memberLabel.bottomAnchor, constant: 12) - ]) - addBtn.addTarget(self, action: #selector(addUser), for: .touchUpInside) - - if viewmodel.isNormalTeam() == false , viewmodel.isOwner() == false , let inviteMode = viewmodel.teamInfoModel?.team?.inviteMode, inviteMode == .manager { - addBtnWidth?.constant = 0 - addBtn.isHidden = true - } - - setupUserInfoCollection(cornerView) - - let infoBtn = UIButton() - infoBtn.translatesAutoresizingMaskIntoConstraints = false - cornerView.addSubview(infoBtn) - NSLayoutConstraint.activate([ - infoBtn.leftAnchor.constraint(equalTo: teamHeader.leftAnchor), - infoBtn.topAnchor.constraint(equalTo: teamHeader.topAnchor), - infoBtn.bottomAnchor.constraint(equalTo: teamHeader.bottomAnchor), - infoBtn.rightAnchor.constraint(equalTo: arrow.rightAnchor) - ]) - infoBtn.addTarget(self, action: #selector(toInfoView), for: .touchUpInside) - - - return back - } - - func getFooterView() -> UIView? { - - guard let title = getBottomText() else { - return nil - } - let footer = UIView(frame: CGRect(x: 0, y: 0, width: view.frame.size.width, height: 64.0)) - let button = UIButton() - button.translatesAutoresizingMaskIntoConstraints = false - footer.addSubview(button) - button.backgroundColor = .white - button.clipsToBounds = true - button.setTitleColor(NEConstant.hexRGB(0xE6605C), for: .normal) - button.titleLabel?.font = NEConstant.defaultTextFont(16.0) - button.setTitle(title, for: .normal) - button.addTarget(self, action: #selector(removeTeamForMyself), for: .touchUpInside) - button.layer.cornerRadius = 8.0 - NSLayoutConstraint.activate([ - button.leftAnchor.constraint(equalTo: footer.leftAnchor, constant: 20), - button.rightAnchor.constraint(equalTo: footer.rightAnchor, constant: -20), - button.topAnchor.constraint(equalTo: footer.topAnchor, constant: 12), - button.heightAnchor.constraint(equalToConstant: 40) - ]) - return footer - } - - func getBottomText() -> String? { - if let type = viewmodel.teamInfoModel?.team?.type, type == .normal { - return localizable("leave_discuss") - }else if let type = viewmodel.teamInfoModel?.team?.type, type == .advanced { - return viewmodel.isOwner() ? localizable("dismiss_team") : localizable("leave_team") - } - return nil - } - - func setupUserInfoCollection(_ cornerView: UIView) { - cornerView.addSubview(userinfoCollection) - NSLayoutConstraint.activate([ - userinfoCollection.leftAnchor.constraint(equalTo: addBtn.rightAnchor, constant: 15), - userinfoCollection.centerYAnchor.constraint(equalTo: addBtn.centerYAnchor), - userinfoCollection.rightAnchor.constraint(equalTo: cornerView.rightAnchor, constant: -15), - userinfoCollection.heightAnchor.constraint(equalToConstant: 32) - ]) - - userinfoCollection.register(TeamUserCell.self, forCellWithReuseIdentifier: "\(TeamUserCell.self)") - +public class TeamSettingViewController: NEBaseViewController,UICollectionViewDelegate, UICollectionViewDataSource,UICollectionViewDelegateFlowLayout,UITableViewDataSource, UITableViewDelegate { + let viewmodel = TeamSettingViewModel() + + var teamId: String? + + var addBtnWidth: NSLayoutConstraint? + + public var cellClassDic = [ + SettingCellType.SettingArrowCell.rawValue: TeamArrowSettingCell.self, + SettingCellType.SettingSwitchCell.rawValue: TeamSettingSwitchCell.self, + SettingCellType.SettingSelectCell.rawValue: TeamSettingSelectCell.self, + ] + + lazy var contentTable: UITableView = { + let table = UITableView() + table.translatesAutoresizingMaskIntoConstraints = false + table.backgroundColor = NEConstant.hexRGB(0xF1F1F6) + table.dataSource = self + table.delegate = self + table.separatorColor = .clear + table.separatorStyle = .none + table.sectionHeaderHeight = 12.0 + table + .tableFooterView = + UIView(frame: CGRect(x: 0, y: 0, width: view.frame.size.width, height: 12)) + if #available(iOS 15.0, *) { + table.sectionHeaderTopPadding = 0.0 + } + return table + }() + + lazy var teamHeader: NEUserHeaderView = { + let imageView = NEUserHeaderView(frame: .zero) + imageView.translatesAutoresizingMaskIntoConstraints = false + imageView.clipsToBounds = true + imageView.titleLabel.font = NEConstant.defaultTextFont(16.0) + imageView.layer.cornerRadius = 21.0 + return imageView + }() + + lazy var teamNameLabel: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.font = NEConstant.defaultTextFont(16.0) + label.textColor = NEConstant.hexRGB(0x333333) + return label + }() + + lazy var memberCountLabel: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.font = NEConstant.defaultTextFont(16.0) + label.textColor = NEConstant.hexRGB(0x999999) + return label + }() + + lazy var userinfoCollection: UICollectionView = { + let flow = UICollectionViewFlowLayout() + flow.scrollDirection = .horizontal + flow.minimumLineSpacing = 0 + flow.minimumInteritemSpacing = 0 + let collection = UICollectionView(frame: .zero, collectionViewLayout: flow) + collection.translatesAutoresizingMaskIntoConstraints = false + collection.delegate = self + collection.dataSource = self + collection.backgroundColor = .clear + collection.showsHorizontalScrollIndicator = false + return collection + }() + + lazy var addBtn: ExpandButton = { + let button = ExpandButton() + button.translatesAutoresizingMaskIntoConstraints = false + button.setImage(coreLoader.loadImage("add"), for: .normal) + return button + }() + + override public func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + if let model = viewmodel.teamInfoModel { + if let url = model.team?.avatarUrl { + teamHeader.sd_setImage(with: URL(string: url)) + } + if let name = model.team?.teamName { + teamNameLabel.text = name + } + } + } + + override public func viewDidLoad() { + super.viewDidLoad() + title = localizable("setting") + weak var weakSelf = self + viewmodel.delegate = self + if let tid = teamId { + viewmodel.getTeamInfo(tid) { error in + if let err = error { + weakSelf?.showToast(err.localizedDescription) + } else { + weakSelf?.contentTable.tableHeaderView = weakSelf?.getHeaderView() + weakSelf?.contentTable.tableFooterView = weakSelf?.getFooterView() + weakSelf?.contentTable.reloadData() + weakSelf?.userinfoCollection.reloadData() + } + } + } + // Do any additional setup after loading the view. + setupUI() + } + + func setupUI() { + view.backgroundColor = NEConstant.hexRGB(0xF1F1F6) + view.addSubview(contentTable) + NSLayoutConstraint.activate([ + contentTable.leftAnchor.constraint(equalTo: view.leftAnchor), + contentTable.rightAnchor.constraint(equalTo: view.rightAnchor), + contentTable.topAnchor.constraint(equalTo: view.topAnchor), + contentTable.bottomAnchor.constraint(equalTo: view.bottomAnchor), + ]) + cellClassDic.forEach { (key: Int, value: BaseTeamSettingCell.Type) in + contentTable.register(value, forCellReuseIdentifier: "\(key)") + } + } + + func getHeaderView() -> UIView { + let back = UIView() + back.frame = CGRect(x: 0, y: 0, width: view.frame.size.width, height: 172) + let cornerView = UIView() + back.addSubview(cornerView) + cornerView.backgroundColor = .white + cornerView.clipsToBounds = true + cornerView.translatesAutoresizingMaskIntoConstraints = false + cornerView.layer.cornerRadius = 8.0 + NSLayoutConstraint.activate([ + cornerView.leftAnchor.constraint(equalTo: back.leftAnchor, constant: 20), + cornerView.rightAnchor.constraint(equalTo: back.rightAnchor, constant: -20), + cornerView.bottomAnchor.constraint(equalTo: back.bottomAnchor), + cornerView.heightAnchor.constraint(equalToConstant: 160), + ]) + + cornerView.addSubview(teamHeader) + NSLayoutConstraint.activate([ + teamHeader.leftAnchor.constraint(equalTo: cornerView.leftAnchor, constant: 16), + teamHeader.topAnchor.constraint(equalTo: cornerView.topAnchor, constant: 16), + teamHeader.widthAnchor.constraint(equalToConstant: 42), + teamHeader.heightAnchor.constraint(equalToConstant: 42), + ]) + if let url = viewmodel.teamInfoModel?.team?.avatarUrl { + print("icon url : ", url) + teamHeader.sd_setImage(with: URL(string: url), completed: nil) + } else { + if let tid = teamId { + if let name = viewmodel.teamInfoModel?.team?.getShowName() { + teamHeader.setTitle(name) + } + teamHeader.backgroundColor = UIColor.colorWithString(string: "\(tid)") + } } - - - /* - // MARK: - Navigation - - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. - } - */ - -} -extension TeamSettingViewController { - - func didAddUserAndRefreshUI(_ accids: [String], _ tid: String){ - weak var weakSelf = self - view.makeToastActivity(.center) - viewmodel.repo.inviteUser(accids, tid, nil, nil) { error, members in - if let err = error { - weakSelf?.view.hideToastActivity() - weakSelf?.showToast(err.localizedDescription) - }else { - print("add users success : ", members as Any) - if let ms = members, let model = weakSelf?.viewmodel.teamInfoModel { - weakSelf?.viewmodel.repo.splitGroupMember(ms, model) { error, team in - weakSelf?.view.hideToastActivity() - if let e = error { - weakSelf?.showToast(e.localizedDescription) - }else { - weakSelf?.refreshMemberCount() - weakSelf?.userinfoCollection.reloadData() - } - } - }else { - weakSelf?.view.hideToastActivity() - } - } - } + teamNameLabel.text = viewmodel.teamInfoModel?.team?.getShowName() + + cornerView.addSubview(teamNameLabel) + NSLayoutConstraint.activate([ + teamNameLabel.leftAnchor.constraint(equalTo: teamHeader.rightAnchor, constant: 11), + teamNameLabel.centerYAnchor.constraint(equalTo: teamHeader.centerYAnchor), + teamNameLabel.rightAnchor.constraint(equalTo: cornerView.rightAnchor, constant: -34), + ]) + + let arrow = UIImageView() + arrow.translatesAutoresizingMaskIntoConstraints = false + arrow.image = coreLoader.loadImage("arrowRight") + cornerView.addSubview(arrow) + NSLayoutConstraint.activate([ + arrow.centerYAnchor.constraint(equalTo: teamHeader.centerYAnchor), + arrow.rightAnchor.constraint(equalTo: cornerView.rightAnchor, constant: -16), + ]) + + let line = UIView() + line.translatesAutoresizingMaskIntoConstraints = false + line.backgroundColor = NEConstant.hexRGB(0xF5F8FC) + cornerView.addSubview(line) + NSLayoutConstraint.activate([ + line.heightAnchor.constraint(equalToConstant: 1.0), + line.rightAnchor.constraint(equalTo: cornerView.rightAnchor), + line.leftAnchor.constraint(equalTo: cornerView.leftAnchor, constant: 16.0), + line.topAnchor.constraint(equalTo: teamHeader.bottomAnchor, constant: 12.0), + ]) + + let memberLabel = UILabel() + cornerView.addSubview(memberLabel) + memberLabel.translatesAutoresizingMaskIntoConstraints = false + memberLabel.textColor = NEConstant.hexRGB(0x333333) + memberLabel.font = NEConstant.defaultTextFont(16.0) + cornerView.addSubview(memberLabel) + NSLayoutConstraint.activate([ + memberLabel.leftAnchor.constraint(equalTo: line.leftAnchor), + memberLabel.topAnchor.constraint(equalTo: line.bottomAnchor, constant: 12), + ]) + + if let type = viewmodel.teamInfoModel?.team?.type, type == .advanced { + memberLabel.text = localizable("group_memmber") + } else { + memberLabel.text = localizable("discuss_mebmer") } - - func didAddUser(_ accids: [String], _ tid: String){ - weak var weakSelf = self - view.makeToastActivity(.center) - viewmodel.repo.inviteUser(accids, tid, nil, nil) { error, members in - weakSelf?.view.hideToastActivity() - if let err = error { - weakSelf?.showToast(err.localizedDescription) - }else { - weakSelf?.showToast("邀请已发送") - } - } + + let memberArrow = UIImageView() + cornerView.addSubview(memberArrow) + memberArrow.translatesAutoresizingMaskIntoConstraints = false + memberArrow.image = coreLoader.loadImage("arrowRight") + NSLayoutConstraint.activate([ + memberArrow.rightAnchor.constraint(equalTo: arrow.rightAnchor), + memberArrow.centerYAnchor.constraint(equalTo: memberLabel.centerYAnchor), + ]) + + let memberListBtn = UIButton() + cornerView.addSubview(memberListBtn) + memberListBtn.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + memberListBtn.leftAnchor.constraint(equalTo: memberLabel.leftAnchor), + memberListBtn.rightAnchor.constraint(equalTo: memberArrow.rightAnchor), + memberListBtn.centerYAnchor.constraint(equalTo: memberLabel.centerYAnchor), + memberListBtn.heightAnchor.constraint(equalToConstant: 40), + ]) + memberListBtn.addTarget(self, action: #selector(toMemberList), for: .touchUpInside) + + cornerView.addSubview(memberCountLabel) + NSLayoutConstraint.activate([ + memberCountLabel.rightAnchor.constraint(equalTo: memberArrow.leftAnchor, constant: -2), + memberCountLabel.centerYAnchor.constraint(equalTo: memberArrow.centerYAnchor), + ]) + memberCountLabel.text = "\(viewmodel.teamInfoModel?.team?.memberNumber ?? 0)" + + cornerView.addSubview(addBtn) + addBtnWidth = addBtn.widthAnchor.constraint(equalToConstant: 32) + addBtnWidth?.isActive = true + NSLayoutConstraint.activate([ + addBtn.leftAnchor.constraint(equalTo: line.leftAnchor), + addBtn.topAnchor.constraint(equalTo: memberLabel.bottomAnchor, constant: 12), + ]) + addBtn.addTarget(self, action: #selector(addUser), for: .touchUpInside) + + if viewmodel.isNormalTeam() == false, viewmodel.isOwner() == false, + let inviteMode = viewmodel.teamInfoModel?.team?.inviteMode, inviteMode == .manager { + addBtnWidth?.constant = 0 + addBtn.isHidden = true } - - @objc func addUser(){ - - weak var weakSelf = self - Router.shared.register(ContactSelectedUsersRouter) { param in - print("addUser weak self ", weakSelf as Any) - if let accids = param["accids"] as? [String], let tid = self.viewmodel.teamInfoModel?.team?.teamId, let beInviteMode = self.viewmodel.teamInfoModel?.team?.beInviteMode, let type = self.viewmodel.teamInfoModel?.team?.type { - if beInviteMode == .noAuth || type == .normal { - self.didAddUserAndRefreshUI(accids, tid) - }else { - self.didAddUser(accids, tid) - } - } - } - var param = [String: Any]() - param["nav"] = navigationController as Any - var filters = Set() - viewmodel.teamInfoModel?.users.forEach({ model in - if let uid = model.nimUser?.userId { - filters.insert(uid) - } - }) - if filters.count > 0 { - param["filters"] = filters - } - param["limit"] = 200 - filters.count - Router.shared.use(ContactUserSelectRouter, parameters: param, closure: nil) + setupUserInfoCollection(cornerView) + + let infoBtn = UIButton() + infoBtn.translatesAutoresizingMaskIntoConstraints = false + cornerView.addSubview(infoBtn) + NSLayoutConstraint.activate([ + infoBtn.leftAnchor.constraint(equalTo: teamHeader.leftAnchor), + infoBtn.topAnchor.constraint(equalTo: teamHeader.topAnchor), + infoBtn.bottomAnchor.constraint(equalTo: teamHeader.bottomAnchor), + infoBtn.rightAnchor.constraint(equalTo: arrow.rightAnchor), + ]) + infoBtn.addTarget(self, action: #selector(toInfoView), for: .touchUpInside) + + return back + } + + func getFooterView() -> UIView? { + guard let title = getBottomText() else { + return nil + } + let footer = UIView(frame: CGRect(x: 0, y: 0, width: view.frame.size.width, height: 64.0)) + let button = UIButton() + button.translatesAutoresizingMaskIntoConstraints = false + footer.addSubview(button) + button.backgroundColor = .white + button.clipsToBounds = true + button.setTitleColor(NEConstant.hexRGB(0xE6605C), for: .normal) + button.titleLabel?.font = NEConstant.defaultTextFont(16.0) + button.setTitle(title, for: .normal) + button.addTarget(self, action: #selector(removeTeamForMyself), for: .touchUpInside) + button.layer.cornerRadius = 8.0 + NSLayoutConstraint.activate([ + button.leftAnchor.constraint(equalTo: footer.leftAnchor, constant: 20), + button.rightAnchor.constraint(equalTo: footer.rightAnchor, constant: -20), + button.topAnchor.constraint(equalTo: footer.topAnchor, constant: 12), + button.heightAnchor.constraint(equalToConstant: 40), + ]) + return footer + } + + func getBottomText() -> String? { + if let type = viewmodel.teamInfoModel?.team?.type, type == .normal { + return localizable("leave_discuss") + } else if let type = viewmodel.teamInfoModel?.team?.type, type == .advanced { + return viewmodel.isOwner() ? localizable("dismiss_team") : localizable("leave_team") + } + return nil + } + + func setupUserInfoCollection(_ cornerView: UIView) { + cornerView.addSubview(userinfoCollection) + NSLayoutConstraint.activate([ + userinfoCollection.leftAnchor.constraint(equalTo: addBtn.rightAnchor, constant: 15), + userinfoCollection.centerYAnchor.constraint(equalTo: addBtn.centerYAnchor), + userinfoCollection.rightAnchor.constraint( + equalTo: cornerView.rightAnchor, + constant: -15 + ), + userinfoCollection.heightAnchor.constraint(equalToConstant: 32), + ]) + + userinfoCollection.register( + TeamUserCell.self, + forCellWithReuseIdentifier: "\(TeamUserCell.self)" + ) + } +//MARK: objc 方法 + @objc func addUser() { + weak var weakSelf = self + Router.shared.register(ContactSelectedUsersRouter) { param in + print("addUser weak self ", weakSelf as Any) + if let accids = param["accids"] as? [String], + let tid = self.viewmodel.teamInfoModel?.team?.teamId, + let beInviteMode = self.viewmodel.teamInfoModel?.team?.beInviteMode, + let type = self.viewmodel.teamInfoModel?.team?.type { + if beInviteMode == .noAuth || type == .normal { + self.didAddUserAndRefreshUI(accids, tid) + } else { + self.didAddUser(accids, tid) + } + } + } + var param = [String: Any]() + param["nav"] = navigationController as Any + var filters = Set() + viewmodel.teamInfoModel?.users.forEach { model in + if let uid = model.nimUser?.userId { + filters.insert(uid) + } + } + if filters.count > 0 { + param["filters"] = filters + } + + param["limit"] = 200 - filters.count + Router.shared.use(ContactUserSelectRouter, parameters: param, closure: nil) } - - @objc func removeTeamForMyself(){ - weak var weakSelf = self - if viewmodel.isOwner(), let type = viewmodel.teamInfoModel?.team?.type, type == .advanced { - showAlert(message: "是否解散群聊?") { - weakSelf?.dismissTeam() - } - }else { - if let type = viewmodel.teamInfoModel?.team?.type { - if type == .advanced { - showAlert(message: "是否退出群聊?") { - weakSelf?.leveaTeam() - } - }else if type == .normal { - showAlert(message: "是否退出讨论组?") { - weakSelf?.leveaTeam() - } - } + + @objc func removeTeamForMyself() { + weak var weakSelf = self + if viewmodel.isOwner(), let type = viewmodel.teamInfoModel?.team?.type, type == .advanced { + showAlert(message: "是否解散群聊?") { + weakSelf?.dismissTeam() + } + } else { + if let type = viewmodel.teamInfoModel?.team?.type { + if type == .advanced { + showAlert(message: "是否退出群聊?") { + weakSelf?.leveaTeam() } - } - } - - func dismissTeam(){ - if let tid = teamId { - weak var weakSelf = self - view.makeToastActivity(.center) - viewmodel.dismissTeam(tid) { error in - weakSelf?.view.hideToastActivity() - if let err = error { - weakSelf?.showToast(err.localizedDescription) - }else { - weakSelf?.navigationController?.popViewController(animated: true) - } + } else if type == .normal { + showAlert(message: "是否退出讨论组?") { + weakSelf?.leveaTeam() } + } } + } } - func refreshMemberCount(){ - if let count = viewmodel.teamInfoModel?.users.count { - memberCountLabel.text = "\(count)" - } + @objc func toInfoView() { + let info = TeamInfoViewController() + info.team = viewmodel.teamInfoModel?.team + navigationController?.pushViewController(info, animated: true) } - - func leveaTeam(){ - if let tid = teamId { - weak var weakSelf = self - view.makeToastActivity(.center) - viewmodel.quitTeam(tid) { error in - weakSelf?.view.hideToastActivity() - if let err = error { - weakSelf?.showToast(err.localizedDescription) - }else { - weakSelf?.navigationController?.popViewController(animated: true) - } - } - } + + @objc func toMemberList() { + let memberController = TeamMembersController() + memberController.datas = viewmodel.teamInfoModel?.users + if let type = viewmodel.teamInfoModel?.team?.type, type == .advanced { + memberController.isSenior = true + } + memberController.ownerId = viewmodel.teamInfoModel?.team?.owner + navigationController?.pushViewController(memberController, animated: true) } - @objc func toInfoView(){ - let info = TeamInfoViewController() - info.team = viewmodel.teamInfoModel?.team - navigationController?.pushViewController(info, animated: true) - } - @objc func toMemberList(){ - let memberController = TeamMembersController() - memberController.datas = viewmodel.teamInfoModel?.users - if let type = viewmodel.teamInfoModel?.team?.type, type == .advanced { - memberController.isSenior = true - } - memberController.ownerId = viewmodel.teamInfoModel?.team?.owner - navigationController?.pushViewController(memberController, animated: true) + //MARK: UICollectionViewDelegate, UICollectionViewDataSource,UICollectionViewDelegateFlowLayout + public func collectionView(_ collectionView: UICollectionView, + numberOfItemsInSection section: Int) -> Int { + print("numberOfItemsInSection ", viewmodel.teamInfoModel?.users.count as Any) + return viewmodel.teamInfoModel?.users.count ?? 0 } -} -extension TeamSettingViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { - - public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - print("numberOfItemsInSection ",viewmodel.teamInfoModel?.users.count as Any) - return viewmodel.teamInfoModel?.users.count ?? 0 + public func collectionView(_ collectionView: UICollectionView, + cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + if let cell = collectionView.dequeueReusableCell( + withReuseIdentifier: "\(TeamUserCell.self)", + for: indexPath + ) as? TeamUserCell { + if let user = viewmodel.teamInfoModel?.users[indexPath.row] { + cell.user = user + } + return cell + } + return UICollectionViewCell() } - - public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { - if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "\(TeamUserCell.self)", for: indexPath) as? TeamUserCell { - if let user = viewmodel.teamInfoModel?.users[indexPath.row] { - cell.user = user - } - return cell - } - return UICollectionViewCell() - } - - public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { - return CGSize(width: 47.0, height: 32) - } - - public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - if let member = viewmodel.teamInfoModel?.users[indexPath.row], let nimUser = member.nimUser{ - let user = User(user:nimUser) - if IMKitLoginManager.instance.isMySelf(user.userId) { - Router.shared.use(MeSettingRouter, parameters: ["nav": navigationController as Any], closure: nil) - }else { - Router.shared.use(ContactUserInfoPageRouter, parameters: ["nav": navigationController as Any, "user" : user], closure: nil) - } - } + + public func collectionView(_ collectionView: UICollectionView, + layout collectionViewLayout: UICollectionViewLayout, + sizeForItemAt indexPath: IndexPath) -> CGSize { + CGSize(width: 47.0, height: 32) } - - -} -extension TeamSettingViewController: UITableViewDataSource, UITableViewDelegate { - + public func collectionView(_ collectionView: UICollectionView, + didSelectItemAt indexPath: IndexPath) { + if let member = viewmodel.teamInfoModel?.users[indexPath.row], + let nimUser = member.nimUser { + let user = User(user: nimUser) + if IMKitLoginManager.instance.isMySelf(user.userId) { + Router.shared.use( + MeSettingRouter, + parameters: ["nav": navigationController as Any], + closure: nil + ) + } else { + Router.shared.use( + ContactUserInfoPageRouter, + parameters: ["nav": navigationController as Any, "user": user], + closure: nil + ) + } + } + } + + //MARK: UITableViewDataSource, UITableViewDelegate public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - if viewmodel.sectionData.count > section { - let model = viewmodel.sectionData[section] - return model.cellModels.count - } - return 0 + if viewmodel.sectionData.count > section { + let model = viewmodel.sectionData[section] + return model.cellModels.count + } + return 0 } - + public func numberOfSections(in tableView: UITableView) -> Int { - return viewmodel.sectionData.count + viewmodel.sectionData.count } - - public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let model = viewmodel.sectionData[indexPath.section].cellModels[indexPath.row] - if let cell = tableView.dequeueReusableCell(withIdentifier: "\(model.type)", for: indexPath) as? BaseTeamSettingCell { - cell.configure(model) - return cell - } - return UITableViewCell() + + public func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let model = viewmodel.sectionData[indexPath.section].cellModels[indexPath.row] + if let cell = tableView.dequeueReusableCell( + withIdentifier: "\(model.type)", + for: indexPath + ) as? BaseTeamSettingCell { + cell.configure(model) + return cell + } + return UITableViewCell() } - + public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - - let model = viewmodel.sectionData[indexPath.section].cellModels[indexPath.row] - if let block = model.cellClick { - block() - } - + let model = viewmodel.sectionData[indexPath.section].cellModels[indexPath.row] + if let block = model.cellClick { + block() + } } - - public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - let model = viewmodel.sectionData[indexPath.section].cellModels[indexPath.row] - return model.rowHeight + + public func tableView(_ tableView: UITableView, + heightForRowAt indexPath: IndexPath) -> CGFloat { + let model = viewmodel.sectionData[indexPath.section].cellModels[indexPath.row] + return model.rowHeight } - - public func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { - - if viewmodel.sectionData.count > section { - let model = viewmodel.sectionData[section] - if model.cellModels.count > 0 { - return 12.0 - } + + public func tableView(_ tableView: UITableView, + heightForHeaderInSection section: Int) -> CGFloat { + if viewmodel.sectionData.count > section { + let model = viewmodel.sectionData[section] + if model.cellModels.count > 0 { + return 12.0 } - return 0 + } + return 0 } - - public func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { - let header = UIView() - header.backgroundColor = NEConstant.hexRGB(0xF1F1F6) - return header + + public func tableView(_ tableView: UITableView, + viewForHeaderInSection section: Int) -> UIView? { + let header = UIView() + header.backgroundColor = NEConstant.hexRGB(0xF1F1F6) + return header } - - public func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { - if section == viewmodel.sectionData.count - 1 { - return 12.0 - } - return 0 + + public func tableView(_ tableView: UITableView, + heightForFooterInSection section: Int) -> CGFloat { + if section == viewmodel.sectionData.count - 1 { + return 12.0 + } + return 0 } } -extension TeamSettingViewController: TeamSettingViewModelDelegate { - - func didError(_ error: Error) { - showToast(error.localizedDescription) - } - - func didNeedRefreshUI() { - contentTable.reloadData() - } - - func didChangeInviteModeClick(_ model: SettingCellModel) { - - weak var weakSelf = self - - let actionSheetController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) - - let cancelActionButton = UIAlertAction(title: "取消", style: .cancel) { _ in - print("Cancel") - } - cancelActionButton.setValue(UIColor.ne_darkText, forKey: "_titleTextColor") - actionSheetController.addAction(cancelActionButton) - - let manager = UIAlertAction(title: "群主", style: .default){ _ in - weakSelf?.view.makeToastActivity(.center) - weakSelf?.viewmodel.repo.updateInviteMode(.manager, weakSelf?.teamId ?? "") { error in - weakSelf?.view.hideToastActivity() - if let err = error { - weakSelf?.showToast(err.localizedDescription) - }else { - weakSelf?.viewmodel.teamInfoModel?.team?.inviteMode = .manager - model.subTitle = "群主" - weakSelf?.contentTable.reloadData() - } - } - } - manager.setValue(UIColor.ne_darkText, forKey: "_titleTextColor") - actionSheetController.addAction(manager) - - let deleteActionButton = UIAlertAction(title: "所有人", style: .default){ _ in - weakSelf?.view.makeToastActivity(.center) - weakSelf?.viewmodel.repo.updateInviteMode(.all, weakSelf?.teamId ?? "") { error in - weakSelf?.view.hideToastActivity() - if let err = error { - weakSelf?.showToast(err.localizedDescription) - }else { - weakSelf?.viewmodel.teamInfoModel?.team?.inviteMode = .all - model.subTitle = "所有人" - weakSelf?.contentTable.reloadData() - } +extension TeamSettingViewController { + func didAddUserAndRefreshUI(_ accids: [String], _ tid: String) { + weak var weakSelf = self + view.makeToastActivity(.center) + viewmodel.repo.inviteUser(accids, tid, nil, nil) { error, members in + if let err = error { + weakSelf?.view.hideToastActivity() + weakSelf?.showToast(err.localizedDescription) + } else { + print("add users success : ", members as Any) + if let ms = members, let model = weakSelf?.viewmodel.teamInfoModel { + weakSelf?.viewmodel.repo.splitGroupMember(ms, model) { error, team in + weakSelf?.view.hideToastActivity() + if let e = error { + weakSelf?.showToast(e.localizedDescription) + } else { + weakSelf?.refreshMemberCount() + weakSelf?.userinfoCollection.reloadData() } + } + } else { + weakSelf?.view.hideToastActivity() } - - deleteActionButton.setValue(UIColor.ne_darkText, forKey: "_titleTextColor") - actionSheetController.addAction(deleteActionButton) - - navigationController?.present(actionSheetController, animated: true, completion: nil) + } } - - func didUpdateTeamInfoClick(_ model: SettingCellModel) { - let actionSheetController = UIAlertController(title: "提示", message: nil, preferredStyle: .actionSheet) - weak var weakSelf = self - let cancelActionButton = UIAlertAction(title: "取消", style: .cancel) { _ in - print("Cancel") - } - actionSheetController.addAction(cancelActionButton) - - let manager = UIAlertAction(title: "群主", style: .default){ _ in - weakSelf?.view.makeToastActivity(.center) - weakSelf?.viewmodel.repo.updateTeamInfoPrivilege(.manager, weakSelf?.teamId ?? "") { error in - weakSelf?.view.hideToastActivity() - if let err = error { - weakSelf?.showToast(err.localizedDescription) - }else { - weakSelf?.viewmodel.teamInfoModel?.team?.updateInfoMode = .manager - model.subTitle = "群主" - weakSelf?.contentTable.reloadData() - } - } - } - actionSheetController.addAction(manager) - - let all = UIAlertAction(title: "所有人", style: .default){ _ in - weakSelf?.view.makeToastActivity(.center) - weakSelf?.viewmodel.repo.updateTeamInfoPrivilege(.all, weakSelf?.teamId ?? "") { error in - weakSelf?.view.hideToastActivity() - if let err = error { - weakSelf?.showToast(err.localizedDescription) - }else { - weakSelf?.viewmodel.teamInfoModel?.team?.updateInfoMode = .all - model.subTitle = "所有人" - weakSelf?.contentTable.reloadData() - } - } - } - actionSheetController.addAction(all) - - navigationController?.present(actionSheetController, animated: true, completion: nil) + } + + func didAddUser(_ accids: [String], _ tid: String) { + weak var weakSelf = self + view.makeToastActivity(.center) + viewmodel.repo.inviteUser(accids, tid, nil, nil) { error, members in + weakSelf?.view.hideToastActivity() + if let err = error { + weakSelf?.showToast(err.localizedDescription) + } else { + weakSelf?.showToast("邀请已发送") + } + } + } + + + + func dismissTeam() { + if let tid = teamId { + weak var weakSelf = self + view.makeToastActivity(.center) + viewmodel.dismissTeam(tid) { error in + weakSelf?.view.hideToastActivity() + if let err = error { + weakSelf?.showToast(err.localizedDescription) + } else { + weakSelf?.navigationController?.popViewController(animated: true) + } + } + } + } + + func refreshMemberCount() { + if let count = viewmodel.teamInfoModel?.users.count { + memberCountLabel.text = "\(count)" } - - - func didClickChangeNick() { - let nick = TeamNameViewController() - nick.type = .NickName - nick.team = viewmodel.teamInfoModel?.team - nick.teamMember = viewmodel.memberInTeam - navigationController?.pushViewController(nick, animated: true) + } + + func leveaTeam() { + if let tid = teamId { + weak var weakSelf = self + view.makeToastActivity(.center) + viewmodel.quitTeam(tid) { error in + weakSelf?.view.hideToastActivity() + if let err = error { + weakSelf?.showToast(err.localizedDescription) + } else { + weakSelf?.navigationController?.popViewController(animated: true) + } + } + } + } + +} + +extension TeamSettingViewController: TeamSettingViewModelDelegate { + func didError(_ error: Error) { + showToast(error.localizedDescription) + } + + func didNeedRefreshUI() { + contentTable.reloadData() + } + + func didChangeInviteModeClick(_ model: SettingCellModel) { + weak var weakSelf = self + + let actionSheetController = UIAlertController( + title: nil, + message: nil, + preferredStyle: .actionSheet + ) + + let cancelActionButton = UIAlertAction(title: "取消", style: .cancel) { _ in + print("Cancel") } - - func didClickHistoryMessage() { + cancelActionButton.setValue(UIColor.ne_darkText, forKey: "_titleTextColor") + actionSheetController.addAction(cancelActionButton) - guard let tid = teamId else { - return - } - Router.shared.use(SearchMessageRouter, parameters: ["nav": navigationController as Any, "teamId": tid], closure: nil) + let manager = UIAlertAction(title: "群主", style: .default) { _ in + weakSelf?.view.makeToastActivity(.center) + weakSelf?.viewmodel.repo.updateInviteMode(.manager, weakSelf?.teamId ?? "") { error in + weakSelf?.view.hideToastActivity() + if let err = error { + weakSelf?.showToast(err.localizedDescription) + } else { + weakSelf?.viewmodel.teamInfoModel?.team?.inviteMode = .manager + model.subTitle = "群主" + weakSelf?.contentTable.reloadData() + } + } + } + manager.setValue(UIColor.ne_darkText, forKey: "_titleTextColor") + actionSheetController.addAction(manager) + + let deleteActionButton = UIAlertAction(title: "所有人", style: .default) { _ in + weakSelf?.view.makeToastActivity(.center) + weakSelf?.viewmodel.repo.updateInviteMode(.all, weakSelf?.teamId ?? "") { error in + weakSelf?.view.hideToastActivity() + if let err = error { + weakSelf?.showToast(err.localizedDescription) + } else { + weakSelf?.viewmodel.teamInfoModel?.team?.inviteMode = .all + model.subTitle = "所有人" + weakSelf?.contentTable.reloadData() + } + } } + + deleteActionButton.setValue(UIColor.ne_darkText, forKey: "_titleTextColor") + actionSheetController.addAction(deleteActionButton) + + navigationController?.present(actionSheetController, animated: true, completion: nil) + } + + func didUpdateTeamInfoClick(_ model: SettingCellModel) { + let actionSheetController = UIAlertController( + title: "提示", + message: nil, + preferredStyle: .actionSheet + ) + weak var weakSelf = self + let cancelActionButton = UIAlertAction(title: "取消", style: .cancel) { _ in + print("Cancel") + } + actionSheetController.addAction(cancelActionButton) + + let manager = UIAlertAction(title: "群主", style: .default) { _ in + weakSelf?.view.makeToastActivity(.center) + weakSelf?.viewmodel.repo + .updateTeamInfoPrivilege(.manager, weakSelf?.teamId ?? "") { error in + weakSelf?.view.hideToastActivity() + if let err = error { + weakSelf?.showToast(err.localizedDescription) + } else { + weakSelf?.viewmodel.teamInfoModel?.team?.updateInfoMode = .manager + model.subTitle = "群主" + weakSelf?.contentTable.reloadData() + } + } + } + actionSheetController.addAction(manager) + + let all = UIAlertAction(title: "所有人", style: .default) { _ in + weakSelf?.view.makeToastActivity(.center) + weakSelf?.viewmodel.repo + .updateTeamInfoPrivilege(.all, weakSelf?.teamId ?? "") { error in + weakSelf?.view.hideToastActivity() + if let err = error { + weakSelf?.showToast(err.localizedDescription) + } else { + weakSelf?.viewmodel.teamInfoModel?.team?.updateInfoMode = .all + model.subTitle = "所有人" + weakSelf?.contentTable.reloadData() + } + } + } + actionSheetController.addAction(all) + + navigationController?.present(actionSheetController, animated: true, completion: nil) + } + + func didClickChangeNick() { + let nick = TeamNameViewController() + nick.type = .NickName + nick.team = viewmodel.teamInfoModel?.team + nick.teamMember = viewmodel.memberInTeam + navigationController?.pushViewController(nick, animated: true) + } + + func didClickHistoryMessage() { + guard let tid = teamId else { + return + } + Router.shared.use( + SearchMessageRouter, + parameters: ["nav": navigationController as Any, "teamId": tid], + closure: nil + ) + } } diff --git a/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/BaseTeamSettingCell.swift b/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/BaseTeamSettingCell.swift index 2c41d016..cda16460 100644 --- a/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/BaseTeamSettingCell.swift +++ b/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/BaseTeamSettingCell.swift @@ -1,54 +1,53 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit public class BaseTeamSettingCell: CornerCell { - - var model: SettingCellModel? - - lazy var titleLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.textColor = NEConstant.hexRGB(0x333333) - label.font = NEConstant.defaultTextFont(16.0) - return label - }() - - public lazy var arrow: UIImageView = { - let imageView = UIImageView(image: coreLoader.loadImage("arrowRight")) - imageView.translatesAutoresizingMaskIntoConstraints = false - return imageView - }() - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - self.selectionStyle = .none - showDefaultLine = true - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - } - - public override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } + var model: SettingCellModel? - public override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) + lazy var titleLabel: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.textColor = NEConstant.hexRGB(0x333333) + label.font = NEConstant.defaultTextFont(16.0) + return label + }() - // Configure the view for the selected state - } - - public func configure(_ anyModel: Any){ - if let m = anyModel as? SettingCellModel { - model = m - cornerType = m.cornerType - titleLabel.text = m.cellName - } - } + public lazy var arrow: UIImageView = { + let imageView = UIImageView(image: coreLoader.loadImage("arrowRight")) + imageView.translatesAutoresizingMaskIntoConstraints = false + return imageView + }() + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + selectionStyle = .none + showDefaultLine = true + } + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + override public func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + + override public func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + } + + public func configure(_ anyModel: Any) { + if let m = anyModel as? SettingCellModel { + model = m + cornerType = m.cornerType + titleLabel.text = m.cellName + } + } } diff --git a/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/HistoryMessageCell.swift b/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/HistoryMessageCell.swift index d910394f..799a58fb 100644 --- a/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/HistoryMessageCell.swift +++ b/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/HistoryMessageCell.swift @@ -1,149 +1,149 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NIMSDK class HistoryMessageCell: UITableViewCell { + public var searchText: String? - public var searchText:String? - - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) - // Configure the view for the selected state - } + // Configure the view for the selected state + } - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - setupSubviews() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func setupSubviews(){ - self.selectionStyle = .none - self.contentView.addSubview(headImge) - self.contentView.addSubview(title) - self.contentView.addSubview(subTitle) - self.contentView.addSubview(bottomLine) - self.contentView.addSubview(timeLabel) - - NSLayoutConstraint.activate([ - headImge.leftAnchor.constraint(equalTo: self.contentView.leftAnchor,constant: NEConstant.screenInterval), - headImge.centerYAnchor.constraint(equalTo: self.contentView.centerYAnchor,constant: -5), - headImge.widthAnchor.constraint(equalToConstant: 36), - headImge.heightAnchor.constraint(equalToConstant: 36) - ]) - - NSLayoutConstraint.activate([ - title.leftAnchor.constraint(equalTo: headImge.rightAnchor,constant: 12), - title.rightAnchor.constraint(equalTo: self.contentView.rightAnchor,constant: -20), - title.topAnchor.constraint(equalTo: headImge.topAnchor) - ]) - - NSLayoutConstraint.activate([ - subTitle.leftAnchor.constraint(equalTo: headImge.rightAnchor,constant: 12), - subTitle.rightAnchor.constraint(equalTo: self.contentView.rightAnchor,constant: -50), - subTitle.topAnchor.constraint(equalTo: title.bottomAnchor,constant: 6) - ]) - - NSLayoutConstraint.activate([ - bottomLine.rightAnchor.constraint(equalTo: self.contentView.rightAnchor), - bottomLine.leftAnchor.constraint(equalTo: headImge.leftAnchor), - bottomLine.bottomAnchor.constraint(equalTo: self.bottomAnchor), - bottomLine.heightAnchor.constraint(equalToConstant: 0.5) - ]) - - NSLayoutConstraint.activate([ - timeLabel.rightAnchor.constraint(equalTo: self.contentView.rightAnchor,constant: -NEConstant.screenInterval), - timeLabel.centerYAnchor.constraint(equalTo: self.contentView.centerYAnchor) - ]) + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + setupSubviews() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func setupSubviews() { + selectionStyle = .none + contentView.addSubview(headImge) + contentView.addSubview(title) + contentView.addSubview(subTitle) + contentView.addSubview(bottomLine) + contentView.addSubview(timeLabel) + + NSLayoutConstraint.activate([ + headImge.leftAnchor.constraint( + equalTo: contentView.leftAnchor, + constant: NEConstant.screenInterval + ), + headImge.centerYAnchor.constraint(equalTo: contentView.centerYAnchor, constant: -5), + headImge.widthAnchor.constraint(equalToConstant: 36), + headImge.heightAnchor.constraint(equalToConstant: 36), + ]) + + NSLayoutConstraint.activate([ + title.leftAnchor.constraint(equalTo: headImge.rightAnchor, constant: 12), + title.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), + title.topAnchor.constraint(equalTo: headImge.topAnchor), + ]) + + NSLayoutConstraint.activate([ + subTitle.leftAnchor.constraint(equalTo: headImge.rightAnchor, constant: 12), + subTitle.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -50), + subTitle.topAnchor.constraint(equalTo: title.bottomAnchor, constant: 6), + ]) + + NSLayoutConstraint.activate([ + bottomLine.rightAnchor.constraint(equalTo: contentView.rightAnchor), + bottomLine.leftAnchor.constraint(equalTo: headImge.leftAnchor), + bottomLine.bottomAnchor.constraint(equalTo: bottomAnchor), + bottomLine.heightAnchor.constraint(equalToConstant: 0.5), + ]) + + NSLayoutConstraint.activate([ + timeLabel.rightAnchor.constraint( + equalTo: contentView.rightAnchor, + constant: -NEConstant.screenInterval + ), + timeLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + ]) + } + + func configData(message: HistoryMessageModel?) { + guard let resultText = message?.content else { return } + + guard let searchStr = searchText else { return } + + if let range = resultText.findAllIndex(searchStr).first { + let attributedStr = NSMutableAttributedString(string: resultText) + // range必须要加,参数分别表示从索引几开始取几个字符 + attributedStr.addAttribute( + .foregroundColor, + value: UIColor.ne_blueText, + range: range + ) + subTitle.attributedText = attributedStr } - func configData(message:HistoryMessageModel?) { - guard let resultText = message?.content else { return } - - guard let searchStr = searchText else { return } - - if let range = resultText.findAllIndex(searchStr).first { - - let attributedStr = NSMutableAttributedString(string: resultText) - //range必须要加,参数分别表示从索引几开始取几个字符 - attributedStr.addAttribute( - .foregroundColor, - value: UIColor.ne_blueText, - range: range - ) - subTitle.attributedText = attributedStr - } - - title.text = message?.name - timeLabel.text = message?.time - - if let imageName = message?.avatar { - headImge.setTitle("") - headImge.sd_setImage(with: URL.init(string: imageName), completed: nil) - }else { - headImge.setTitle(message?.name ?? "") - headImge.sd_setImage(with:nil, completed: nil) - headImge.backgroundColor = UIColor.colorWithString(string: message?.imMessage?.from) - } - + title.text = message?.name + timeLabel.text = message?.time + + if let imageName = message?.avatar { + headImge.setTitle("") + headImge.sd_setImage(with: URL(string: imageName), completed: nil) + } else { + headImge.setTitle(message?.name ?? "") + headImge.sd_setImage(with: nil, completed: nil) + headImge.backgroundColor = UIColor.colorWithString(string: message?.imMessage?.from) } + } - - //MARK: lazy Method - - lazy var headImge: NEUserHeaderView = { - let headView = NEUserHeaderView(frame: .zero) - headView.titleLabel.textColor = .white - headView.titleLabel.font = NEConstant.defaultTextFont(14) - headView.translatesAutoresizingMaskIntoConstraints = false - headView.layer.cornerRadius = 18 - headView.clipsToBounds = true - return headView - }() - - private lazy var title:UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.textColor = UIColor.ne_darkText - label.font = NEConstant.defaultTextFont(14) - return label - }() - - private lazy var subTitle:UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.textColor = UIColor.ne_lightText - label.font = NEConstant.defaultTextFont(12) - return label - }() - - private lazy var bottomLine:UIView = { - let view = UIView() - view.translatesAutoresizingMaskIntoConstraints = false - view.backgroundColor = UIColor.init(hexString: "0xDBE0E8") - return view - }() - - private lazy var timeLabel:UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.textColor = NEConstant.hexRGB(0xcccccc) - label.font = NEConstant.defaultTextFont(12) - label.textAlignment = .right - return label - }() - - -} + // MARK: lazy Method + lazy var headImge: NEUserHeaderView = { + let headView = NEUserHeaderView(frame: .zero) + headView.titleLabel.textColor = .white + headView.titleLabel.font = NEConstant.defaultTextFont(14) + headView.translatesAutoresizingMaskIntoConstraints = false + headView.layer.cornerRadius = 18 + headView.clipsToBounds = true + return headView + }() + + private lazy var title: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.textColor = UIColor.ne_darkText + label.font = NEConstant.defaultTextFont(14) + return label + }() + + private lazy var subTitle: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.textColor = UIColor.ne_lightText + label.font = NEConstant.defaultTextFont(12) + return label + }() + + private lazy var bottomLine: UIView = { + let view = UIView() + view.translatesAutoresizingMaskIntoConstraints = false + view.backgroundColor = UIColor(hexString: "0xDBE0E8") + return view + }() + + private lazy var timeLabel: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.textColor = NEConstant.hexRGB(0xCCCCCC) + label.font = NEConstant.defaultTextFont(12) + label.textAlignment = .right + return label + }() +} diff --git a/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamArrowSettingCell.swift b/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamArrowSettingCell.swift index c3be791f..9da37b8f 100644 --- a/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamArrowSettingCell.swift +++ b/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamArrowSettingCell.swift @@ -1,40 +1,37 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit public class TeamArrowSettingCell: BaseTeamSettingCell { - - - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - self.selectionStyle = .none - setupUI() - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - } - - public override func configure(_ anyModel: Any) { - super.configure(anyModel) - - } - - func setupUI(){ - contentView.addSubview(titleLabel) - NSLayoutConstraint.activate([ - titleLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 36), - titleLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - titleLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -84) - ]) - - contentView.addSubview(arrow) - NSLayoutConstraint.activate([ - arrow.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - arrow.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -36) - ]) - } + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + selectionStyle = .none + setupUI() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + override public func configure(_ anyModel: Any) { + super.configure(anyModel) + } + + func setupUI() { + contentView.addSubview(titleLabel) + NSLayoutConstraint.activate([ + titleLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 36), + titleLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + titleLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -84), + ]) + + contentView.addSubview(arrow) + NSLayoutConstraint.activate([ + arrow.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + arrow.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -36), + ]) + } } diff --git a/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamDefaultIconCell.swift b/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamDefaultIconCell.swift index 600f71da..cc0d69c8 100644 --- a/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamDefaultIconCell.swift +++ b/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamDefaultIconCell.swift @@ -1,61 +1,59 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCommon class TeamDefaultIconCell: UICollectionViewCell { - - public override init(frame: CGRect){ - super.init(frame: frame) - setupUI() - } - - override var isSelected: Bool { - didSet { - print("default icon select ", isSelected) - selectBack.isHidden = !isSelected - } - } - - lazy var iconImage: UIImageView = { - let image = UIImageView() - image.translatesAutoresizingMaskIntoConstraints = false - return image - }() - - lazy var selectBack: UIView = { - let view = UIView() - view.translatesAutoresizingMaskIntoConstraints = false - view.backgroundColor = NEConstant.hexRGB(0xF4F4F4) - view.clipsToBounds = true - view.layer.cornerRadius = 8.0 - view.isHidden = true - return view - }() - - required init?(coder: NSCoder) { - super.init(coder: coder) - } - - func setupUI(){ - - contentView.addSubview(selectBack) - NSLayoutConstraint.activate([ - selectBack.centerXAnchor.constraint(equalTo: contentView.centerXAnchor), - selectBack.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - selectBack.widthAnchor.constraint(equalToConstant: 48.0), - selectBack.heightAnchor.constraint(equalToConstant: 48.0) - ]) - - contentView.addSubview(iconImage) - NSLayoutConstraint.activate([ - iconImage.centerXAnchor.constraint(equalTo: contentView.centerXAnchor), - iconImage.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - iconImage.heightAnchor.constraint(equalToConstant: 32), - iconImage.widthAnchor.constraint(equalToConstant: 32) - ]) + override public init(frame: CGRect) { + super.init(frame: frame) + setupUI() + } + + override var isSelected: Bool { + didSet { + print("default icon select ", isSelected) + selectBack.isHidden = !isSelected } - + } + + lazy var iconImage: UIImageView = { + let image = UIImageView() + image.translatesAutoresizingMaskIntoConstraints = false + return image + }() + + lazy var selectBack: UIView = { + let view = UIView() + view.translatesAutoresizingMaskIntoConstraints = false + view.backgroundColor = NEConstant.hexRGB(0xF4F4F4) + view.clipsToBounds = true + view.layer.cornerRadius = 8.0 + view.isHidden = true + return view + }() + + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + func setupUI() { + contentView.addSubview(selectBack) + NSLayoutConstraint.activate([ + selectBack.centerXAnchor.constraint(equalTo: contentView.centerXAnchor), + selectBack.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + selectBack.widthAnchor.constraint(equalToConstant: 48.0), + selectBack.heightAnchor.constraint(equalToConstant: 48.0), + ]) + + contentView.addSubview(iconImage) + NSLayoutConstraint.activate([ + iconImage.centerXAnchor.constraint(equalTo: contentView.centerXAnchor), + iconImage.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + iconImage.heightAnchor.constraint(equalToConstant: 32), + iconImage.widthAnchor.constraint(equalToConstant: 32), + ]) + } } diff --git a/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamMemberCell.swift b/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamMemberCell.swift index 9eac4eeb..777bfc6b 100644 --- a/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamMemberCell.swift +++ b/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamMemberCell.swift @@ -1,104 +1,102 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitTeam import NEKitCommonUI class TeamMemberCell: UITableViewCell { - - lazy var headerView: NEUserHeaderView = { - let header = NEUserHeaderView(frame: .zero) - header.titleLabel.font = NEConstant.defaultTextFont(14) - header.titleLabel.textColor = UIColor.white - header.layer.cornerRadius = 21 - header.clipsToBounds = true - header.translatesAutoresizingMaskIntoConstraints = false - return header - }() - - lazy var ownerLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.font = NEConstant.defaultTextFont(12.0) - label.textColor = NEConstant.hexRGB(0x337EFF) - label.backgroundColor = NEConstant.hexRGB(0xE0ECFF) - label.clipsToBounds = true - label.layer.cornerRadius = 4.0 - label.layer.borderColor = NEConstant.hexRGB(0xB9D3FF).cgColor - label.layer.borderWidth = 1.0 - label.text = "群主" - label.textAlignment = .center - return label - }() - - lazy var nameLabel: UILabel = { - let label = UILabel() - label.translatesAutoresizingMaskIntoConstraints = false - label.font = NEConstant.defaultTextFont(16.0) - label.textColor = .ne_darkText - return label - }() + lazy var headerView: NEUserHeaderView = { + let header = NEUserHeaderView(frame: .zero) + header.titleLabel.font = NEConstant.defaultTextFont(14) + header.titleLabel.textColor = UIColor.white + header.layer.cornerRadius = 21 + header.clipsToBounds = true + header.translatesAutoresizingMaskIntoConstraints = false + return header + }() - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } + lazy var ownerLabel: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.font = NEConstant.defaultTextFont(12.0) + label.textColor = NEConstant.hexRGB(0x337EFF) + label.backgroundColor = NEConstant.hexRGB(0xE0ECFF) + label.clipsToBounds = true + label.layer.cornerRadius = 4.0 + label.layer.borderColor = NEConstant.hexRGB(0xB9D3FF).cgColor + label.layer.borderWidth = 1.0 + label.text = "群主" + label.textAlignment = .center + return label + }() - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) + lazy var nameLabel: UILabel = { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.font = NEConstant.defaultTextFont(16.0) + label.textColor = .ne_darkText + return label + }() - // Configure the view for the selected state - } - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - self.selectionStyle = .none - setupUI() - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - } - - func setupUI(){ - contentView.addSubview(headerView) - NSLayoutConstraint.activate([ - headerView.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 21), - headerView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - headerView.widthAnchor.constraint(equalToConstant: 42), - headerView.heightAnchor.constraint(equalToConstant: 42) - ]) - - contentView.addSubview(ownerLabel) - NSLayoutConstraint.activate([ - ownerLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), - ownerLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - ownerLabel.heightAnchor.constraint(equalToConstant: 25.0), - ownerLabel.widthAnchor.constraint(equalToConstant: 48.0) - ]) - - contentView.addSubview(nameLabel) - NSLayoutConstraint.activate([ - nameLabel.leftAnchor.constraint(equalTo: headerView.rightAnchor, constant: 14.0), - nameLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - nameLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -70) - ]) - - } - - func configure(_ model: TeamMemberInfoModel) { + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + } + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + selectionStyle = .none + setupUI() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + func setupUI() { + contentView.addSubview(headerView) + NSLayoutConstraint.activate([ + headerView.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 21), + headerView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + headerView.widthAnchor.constraint(equalToConstant: 42), + headerView.heightAnchor.constraint(equalToConstant: 42), + ]) + + contentView.addSubview(ownerLabel) + NSLayoutConstraint.activate([ + ownerLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), + ownerLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + ownerLabel.heightAnchor.constraint(equalToConstant: 25.0), + ownerLabel.widthAnchor.constraint(equalToConstant: 48.0), + ]) + + contentView.addSubview(nameLabel) + NSLayoutConstraint.activate([ + nameLabel.leftAnchor.constraint(equalTo: headerView.rightAnchor, constant: 14.0), + nameLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + nameLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -70), + ]) + } + + func configure(_ model: TeamMemberInfoModel) { // ownerLabel.isHidden = !isOwner(model.nimUser?.userId) - if let url = model.nimUser?.userInfo?.avatarUrl { - headerView.sd_setImage(with: URL(string: url), completed: nil) - headerView.setTitle("") - }else { - headerView.image = nil - headerView.setTitle(model.showNameInTeam()) - headerView.backgroundColor = UIColor.colorWithString(string: model.nimUser?.userId) - } - nameLabel.text = model.showNameInTeam() + if let url = model.nimUser?.userInfo?.avatarUrl { + headerView.sd_setImage(with: URL(string: url), completed: nil) + headerView.setTitle("") + } else { + headerView.image = nil + headerView.setTitle(model.showNameInTeam()) + headerView.backgroundColor = UIColor.colorWithString(string: model.nimUser?.userId) } - + nameLabel.text = model.showNameInTeam() + } } diff --git a/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamSettingHeaderCell.swift b/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamSettingHeaderCell.swift index 4063fe00..eee01d26 100644 --- a/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamSettingHeaderCell.swift +++ b/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamSettingHeaderCell.swift @@ -1,62 +1,62 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCommonUI public class TeamSettingHeaderCell: BaseTeamSettingCell { - - lazy var headerView: NEUserHeaderView = { - let header = NEUserHeaderView(frame: .zero) - header.translatesAutoresizingMaskIntoConstraints = false - header.clipsToBounds = true - header.layer.cornerRadius = 21.0 - return header - }() - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - self.selectionStyle = .none - setupUI() - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - setupUI() - } - - public override func configure(_ anyModel: Any) { - super.configure(anyModel) - if let url = model?.headerUrl { - headerView.sd_setImage(with: URL(string: url), completed: nil) - headerView.setTitle("") - }else { - headerView.setTitle(model?.defaultHeadData ?? "") - headerView.backgroundColor = UIColor.colorWithString(string: model?.defaultHeadData) - } - } - - func setupUI(){ - contentView.addSubview(titleLabel) - NSLayoutConstraint.activate([ - titleLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 36), - titleLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - titleLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -84) - ]) - - contentView.addSubview(arrow) - NSLayoutConstraint.activate([ - arrow.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - arrow.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -36) - ]) - - contentView.addSubview(headerView) - NSLayoutConstraint.activate([ - headerView.centerYAnchor.constraint(equalTo: arrow.centerYAnchor), - headerView.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -64.0), - headerView.widthAnchor.constraint(equalToConstant: 42.0), - headerView.heightAnchor.constraint(equalToConstant: 42.0) - ]) + lazy var headerView: NEUserHeaderView = { + let header = NEUserHeaderView(frame: .zero) + header.translatesAutoresizingMaskIntoConstraints = false + header.clipsToBounds = true + header.layer.cornerRadius = 21.0 + return header + }() + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + selectionStyle = .none + setupUI() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + setupUI() + } + + override public func configure(_ anyModel: Any) { + super.configure(anyModel) + if let url = model?.headerUrl { + headerView.sd_setImage(with: URL(string: url), completed: nil) + headerView.setTitle("") + } else { + headerView.setTitle(model?.defaultHeadData ?? "") + headerView.backgroundColor = UIColor.colorWithString(string: model?.defaultHeadData) } + } + + func setupUI() { + contentView.addSubview(titleLabel) + NSLayoutConstraint.activate([ + titleLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 36), + titleLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + titleLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -84), + ]) + + contentView.addSubview(arrow) + NSLayoutConstraint.activate([ + arrow.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + arrow.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -36), + ]) + + contentView.addSubview(headerView) + NSLayoutConstraint.activate([ + headerView.centerYAnchor.constraint(equalTo: arrow.centerYAnchor), + headerView.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -64.0), + headerView.widthAnchor.constraint(equalToConstant: 42.0), + headerView.heightAnchor.constraint(equalToConstant: 42.0), + ]) + } } diff --git a/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamSettingRightCustomCell.swift b/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamSettingRightCustomCell.swift index 0d25d18d..8755d6e6 100644 --- a/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamSettingRightCustomCell.swift +++ b/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamSettingRightCustomCell.swift @@ -1,61 +1,60 @@ -// -// TeamSettingRightCustomCell.swift -// NEKitTeamUI -// -// Created by vvj on 2022/5/16. -// + +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit public class TeamSettingRightCustomCell: TeamSettingSubtitleCell { + override public func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } - public override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } + override public func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) - public override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) + // Configure the view for the selected state + } - // Configure the view for the selected state + override public func configure(_ anyModel: Any) { + super.configure(anyModel) + if let icon = model?.rightCustomViewIcon, icon.count > 0 { + customRightView.isHidden = false + customRightView.setImage(coreLoader.loadImage(icon), for: .normal) + arrow.isHidden = true + } else { + customRightView.isHidden = true + arrow.isHidden = false } + } - - public override func configure(_ anyModel: Any) { - super.configure(anyModel) - if let icon = model?.rightCustomViewIcon,icon.count > 0 { - customRightView.isHidden = false - customRightView.setImage(coreLoader.loadImage(icon), for: .normal) - arrow.isHidden = true - }else { - customRightView.isHidden = true - arrow.isHidden = false - } - } - - override func setupUI() { - super.setupUI() - - contentView.addSubview(customRightView) - NSLayoutConstraint.activate([ - customRightView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - customRightView.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -36), - customRightView.widthAnchor.constraint(equalToConstant: 15), - customRightView.heightAnchor.constraint(equalToConstant: 15) - ]) - customRightView.addTarget(self, action: #selector(customRightViewClick), for: .touchUpInside) - } - - lazy var customRightView: UIButton = { - let btn = UIButton() - btn.translatesAutoresizingMaskIntoConstraints = false - return btn - }() - - @objc func customRightViewClick() { - if let block = model?.customViewClick { - block() - } + override func setupUI() { + super.setupUI() + + contentView.addSubview(customRightView) + NSLayoutConstraint.activate([ + customRightView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + customRightView.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -36), + customRightView.widthAnchor.constraint(equalToConstant: 15), + customRightView.heightAnchor.constraint(equalToConstant: 15), + ]) + customRightView.addTarget( + self, + action: #selector(customRightViewClick), + for: .touchUpInside + ) + } + + lazy var customRightView: UIButton = { + let btn = UIButton() + btn.translatesAutoresizingMaskIntoConstraints = false + return btn + }() + + @objc func customRightViewClick() { + if let block = model?.customViewClick { + block() } - + } } diff --git a/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamSettingSelectCell.swift b/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamSettingSelectCell.swift index 23d55529..c0443161 100644 --- a/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamSettingSelectCell.swift +++ b/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamSettingSelectCell.swift @@ -1,66 +1,64 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit class TeamSettingSelectCell: BaseTeamSettingCell { - - lazy var subTitleLabel: UILabel = { - let label = UILabel() - label.textColor = NEConstant.hexRGB(0x999999) - label.font = NEConstant.defaultTextFont(14.0) - label.translatesAutoresizingMaskIntoConstraints = false - return label - }() + lazy var subTitleLabel: UILabel = { + let label = UILabel() + label.textColor = NEConstant.hexRGB(0x999999) + label.font = NEConstant.defaultTextFont(14.0) + label.translatesAutoresizingMaskIntoConstraints = false + return label + }() - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) - // Configure the view for the selected state - } - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - self.selectionStyle = .none - setupUI() - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - } - - override func configure(_ anyModel: Any) { - super.configure(anyModel) - self.subTitleLabel.text = model?.subTitle - } - - func setupUI(){ - - contentView.addSubview(titleLabel) - NSLayoutConstraint.activate([ - titleLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 36), - titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 16), - titleLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -84) - ]) - - contentView.addSubview(subTitleLabel) - NSLayoutConstraint.activate([ - subTitleLabel.leftAnchor.constraint(equalTo: titleLabel.leftAnchor), - subTitleLabel.rightAnchor.constraint(equalTo: titleLabel.rightAnchor), - subTitleLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 6.0) - ]) - - contentView.addSubview(arrow) - NSLayoutConstraint.activate([ - arrow.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - arrow.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -36) - ]) - } + // Configure the view for the selected state + } + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + selectionStyle = .none + setupUI() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + override func configure(_ anyModel: Any) { + super.configure(anyModel) + subTitleLabel.text = model?.subTitle + } + + func setupUI() { + contentView.addSubview(titleLabel) + NSLayoutConstraint.activate([ + titleLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 36), + titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 16), + titleLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -84), + ]) + + contentView.addSubview(subTitleLabel) + NSLayoutConstraint.activate([ + subTitleLabel.leftAnchor.constraint(equalTo: titleLabel.leftAnchor), + subTitleLabel.rightAnchor.constraint(equalTo: titleLabel.rightAnchor), + subTitleLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 6.0), + ]) + + contentView.addSubview(arrow) + NSLayoutConstraint.activate([ + arrow.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + arrow.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -36), + ]) + } } diff --git a/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamSettingSubtitleCell.swift b/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamSettingSubtitleCell.swift index 57d2eacc..71f7a4cd 100644 --- a/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamSettingSubtitleCell.swift +++ b/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamSettingSubtitleCell.swift @@ -1,71 +1,68 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit public class TeamSettingSubtitleCell: BaseTeamSettingCell { + override public func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } - public override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } + override public func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) - public override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) + // Configure the view for the selected state + } - // Configure the view for the selected state - } - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - self.selectionStyle = .none - setupUI() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func setupUI(){ - - contentView.addSubview(titleLabel) - contentView.addSubview(subTitleLabel) - contentView.addSubview(arrow) + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + selectionStyle = .none + setupUI() + } - NSLayoutConstraint.activate([ - titleLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 36), - titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 16), - titleLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -84) - ]) - - - NSLayoutConstraint.activate([ - arrow.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - arrow.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -36) - ]) - - NSLayoutConstraint.activate([ - subTitleLabel.rightAnchor.constraint(equalTo: arrow.leftAnchor,constant: -10), - subTitleLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - subTitleLabel.widthAnchor.constraint(equalToConstant: 200) - ]) - - titleLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true - } - - - public override func configure(_ anyModel: Any) { - super.configure(anyModel) - self.subTitleLabel.text = model?.subTitle - } - - - lazy var subTitleLabel: UILabel = { - let label = UILabel() - label.textColor = UIColor.init(hexString: "0xA6ADB6") - label.font = NEConstant.defaultTextFont(12.0) - label.translatesAutoresizingMaskIntoConstraints = false - label.textAlignment = .right - return label - }() + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func setupUI() { + contentView.addSubview(titleLabel) + contentView.addSubview(subTitleLabel) + contentView.addSubview(arrow) + + NSLayoutConstraint.activate([ + titleLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 36), + titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 16), + titleLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -84), + ]) + + NSLayoutConstraint.activate([ + arrow.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + arrow.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -36), + ]) + + NSLayoutConstraint.activate([ + subTitleLabel.rightAnchor.constraint(equalTo: arrow.leftAnchor, constant: -10), + subTitleLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + subTitleLabel.widthAnchor.constraint(equalToConstant: 200), + ]) + + titleLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true + } + + override public func configure(_ anyModel: Any) { + super.configure(anyModel) + subTitleLabel.text = model?.subTitle + } + + lazy var subTitleLabel: UILabel = { + let label = UILabel() + label.textColor = UIColor(hexString: "0xA6ADB6") + label.font = NEConstant.defaultTextFont(12.0) + label.translatesAutoresizingMaskIntoConstraints = false + label.textAlignment = .right + return label + }() } diff --git a/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamSettingSwitchCell.swift b/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamSettingSwitchCell.swift index 751136b0..957a61c5 100644 --- a/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamSettingSwitchCell.swift +++ b/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamSettingSwitchCell.swift @@ -1,66 +1,65 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit public class TeamSettingSwitchCell: BaseTeamSettingCell { - - var tSwitch: UISwitch = { - let q = UISwitch() - q.translatesAutoresizingMaskIntoConstraints = false - q.onTintColor = NEConstant.hexRGB(0x337EFF) - return q - }() - - public override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } + var tSwitch: UISwitch = { + let q = UISwitch() + q.translatesAutoresizingMaskIntoConstraints = false + q.onTintColor = NEConstant.hexRGB(0x337EFF) + return q + }() - public override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) + override public func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } - // Configure the view for the selected state - } - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - self.selectionStyle = .none - setupUI() - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - } - - public override func configure(_ anyModel: Any) { - super.configure(anyModel) - if let open = model?.switchOpen { - tSwitch.isOn = open - } - } - - func setupUI(){ - contentView.addSubview(titleLabel) - NSLayoutConstraint.activate([ - titleLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 36), - titleLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - titleLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -84) - ]) - - contentView.addSubview(tSwitch) - NSLayoutConstraint.activate([ - tSwitch.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - tSwitch.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -36) - ]) - tSwitch.addTarget(self, action: #selector(switchChange(_:)), for: .touchUpInside) - } - - @objc func switchChange(_ s: UISwitch) { - if let block = model?.swichChange { - block(s.isOn) - } + override public func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + } + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + selectionStyle = .none + setupUI() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + override public func configure(_ anyModel: Any) { + super.configure(anyModel) + if let open = model?.switchOpen { + tSwitch.isOn = open } + } + func setupUI() { + contentView.addSubview(titleLabel) + NSLayoutConstraint.activate([ + titleLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 36), + titleLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + titleLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -84), + ]) + + contentView.addSubview(tSwitch) + NSLayoutConstraint.activate([ + tSwitch.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + tSwitch.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -36), + ]) + tSwitch.addTarget(self, action: #selector(switchChange(_:)), for: .touchUpInside) + } + + @objc func switchChange(_ s: UISwitch) { + if let block = model?.swichChange { + block(s.isOn) + } + } } diff --git a/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamUserCell.swift b/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamUserCell.swift index 76e29bc9..561c0617 100644 --- a/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamUserCell.swift +++ b/NETeamUIKit/NEKitTeamUI/Classes/Setting/View/TeamUserCell.swift @@ -1,6 +1,7 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCommon @@ -10,47 +11,46 @@ import NEKitCore import NEKitTeam public class TeamUserCell: UICollectionViewCell { - - var user: TeamMemberInfoModel? { - didSet { - if let name = user?.showNameInTeam() { - userHeader.setTitle(name) - } - if let url = user?.nimUser?.userInfo?.avatarUrl { - userHeader.sd_setImage(with: URL(string: url), completed: nil) - userHeader.setTitle("") - }else if let id = user?.nimUser?.userId { - userHeader.image = nil - userHeader.backgroundColor = UIColor.colorWithString(string: "\(id)") - } - } - } - - lazy var userHeader: NEUserHeaderView = { - let header = NEUserHeaderView(frame: .zero) - header.translatesAutoresizingMaskIntoConstraints = false - header.titleLabel.font = NEConstant.defaultTextFont(11.0) - header.clipsToBounds = true - header.layer.cornerRadius = 16.0 - return header - }() - - public override init(frame: CGRect){ - super.init(frame: frame) - setupUI() - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - } - - func setupUI(){ - contentView.addSubview(userHeader) - NSLayoutConstraint.activate([ - userHeader.leftAnchor.constraint(equalTo: contentView.leftAnchor), - userHeader.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), - userHeader.widthAnchor.constraint(equalToConstant: 32.0), - userHeader.heightAnchor.constraint(equalToConstant: 32.0) - ]) + var user: TeamMemberInfoModel? { + didSet { + if let name = user?.showNameInTeam() { + userHeader.setTitle(name) + } + if let url = user?.nimUser?.userInfo?.avatarUrl { + userHeader.sd_setImage(with: URL(string: url), completed: nil) + userHeader.setTitle("") + } else if let id = user?.nimUser?.userId { + userHeader.image = nil + userHeader.backgroundColor = UIColor.colorWithString(string: "\(id)") + } } + } + + lazy var userHeader: NEUserHeaderView = { + let header = NEUserHeaderView(frame: .zero) + header.translatesAutoresizingMaskIntoConstraints = false + header.titleLabel.font = NEConstant.defaultTextFont(11.0) + header.clipsToBounds = true + header.layer.cornerRadius = 16.0 + return header + }() + + override public init(frame: CGRect) { + super.init(frame: frame) + setupUI() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + func setupUI() { + contentView.addSubview(userHeader) + NSLayoutConstraint.activate([ + userHeader.leftAnchor.constraint(equalTo: contentView.leftAnchor), + userHeader.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + userHeader.widthAnchor.constraint(equalToConstant: 32.0), + userHeader.heightAnchor.constraint(equalToConstant: 32.0), + ]) + } } diff --git a/NETeamUIKit/NEKitTeamUI/Classes/Setting/ViewModel/TeamInfoViewModel.swift b/NETeamUIKit/NEKitTeamUI/Classes/Setting/ViewModel/TeamInfoViewModel.swift index 0d89253c..31245dd2 100644 --- a/NETeamUIKit/NEKitTeamUI/Classes/Setting/ViewModel/TeamInfoViewModel.swift +++ b/NETeamUIKit/NEKitTeamUI/Classes/Setting/ViewModel/TeamInfoViewModel.swift @@ -1,43 +1,41 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NEKitTeam import NIMSDK class TeamInfoViewModel { - - var cellDatas = [SettingCellModel]() - - func getData(_ team: NIMTeam?){ - - cellDatas.removeAll() - - let headerCell = SettingCellModel() - headerCell.cornerType = .topLeft.union(.topRight) - headerCell.type = SettingCellType.SettingHeaderCell.rawValue - headerCell.headerUrl = team?.avatarUrl - headerCell.rowHeight = 74.0 - - let nameCell = SettingCellModel() - nameCell.type = SettingCellType.SettingArrowCell.rawValue - - let intrCell = SettingCellModel() - intrCell.type = SettingCellType.SettingArrowCell.rawValue - intrCell.cornerType = .bottomLeft.union(.bottomRight) - - if let type = team?.type, type == .normal { - headerCell.cellName = "讨论组头像" - nameCell.cellName = "讨论组名称" - intrCell.cellName = "讨论组介绍" - cellDatas.append(contentsOf: [headerCell, nameCell]) - nameCell.cornerType = .bottomLeft.union(.bottomRight) - }else { - cellDatas.append(contentsOf: [headerCell, nameCell, intrCell]) - headerCell.cellName = localizable("team_header") - nameCell.cellName = localizable("team_name") - intrCell.cellName = localizable("team_intr") - } - + var cellDatas = [SettingCellModel]() + + func getData(_ team: NIMTeam?) { + cellDatas.removeAll() + + let headerCell = SettingCellModel() + headerCell.cornerType = .topLeft.union(.topRight) + headerCell.type = SettingCellType.SettingHeaderCell.rawValue + headerCell.headerUrl = team?.avatarUrl + headerCell.rowHeight = 74.0 + + let nameCell = SettingCellModel() + nameCell.type = SettingCellType.SettingArrowCell.rawValue + + let intrCell = SettingCellModel() + intrCell.type = SettingCellType.SettingArrowCell.rawValue + intrCell.cornerType = .bottomLeft.union(.bottomRight) + + if let type = team?.type, type == .normal { + headerCell.cellName = "讨论组头像" + nameCell.cellName = "讨论组名称" + intrCell.cellName = "讨论组介绍" + cellDatas.append(contentsOf: [headerCell, nameCell]) + nameCell.cornerType = .bottomLeft.union(.bottomRight) + } else { + cellDatas.append(contentsOf: [headerCell, nameCell, intrCell]) + headerCell.cellName = localizable("team_header") + nameCell.cellName = localizable("team_name") + intrCell.cellName = localizable("team_intr") } + } } diff --git a/NETeamUIKit/NEKitTeamUI/Classes/Setting/ViewModel/TeamSettingViewModel.swift b/NETeamUIKit/NEKitTeamUI/Classes/Setting/ViewModel/TeamSettingViewModel.swift index 3cc12d2c..203480e3 100644 --- a/NETeamUIKit/NEKitTeamUI/Classes/Setting/ViewModel/TeamSettingViewModel.swift +++ b/NETeamUIKit/NEKitTeamUI/Classes/Setting/ViewModel/TeamSettingViewModel.swift @@ -1,6 +1,7 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NEKitTeam @@ -8,338 +9,338 @@ import NIMSDK import UIKit protocol TeamSettingViewModelDelegate: AnyObject { - func didClickChangeNick() - func didChangeInviteModeClick(_ model: SettingCellModel) - func didUpdateTeamInfoClick(_ model: SettingCellModel) - func didClickHistoryMessage() - func didNeedRefreshUI() - func didError(_ error: Error) + func didClickChangeNick() + func didChangeInviteModeClick(_ model: SettingCellModel) + func didUpdateTeamInfoClick(_ model: SettingCellModel) + func didClickHistoryMessage() + func didNeedRefreshUI() + func didError(_ error: Error) } public class TeamSettingViewModel { - - var sectionData = [SettingSectionModel]() - - var searchResultInfos:[HistoryMessageModel]? - - var teamInfoModel: TeamInfoModel? - - let repo = TeamRepo() - - var memberInTeam: NIMTeamMember? - - weak var delegate: TeamSettingViewModelDelegate? - - public init(){} - - func getData(){ - sectionData.removeAll() - sectionData.append(getTwoSection()) - print("current team type : ", teamInfoModel?.team?.type.rawValue as Any) - if let type = teamInfoModel?.team?.type, type == .advanced { - sectionData.append(getThreeSection()) - sectionData.append(getFourSection()) - } + var sectionData = [SettingSectionModel]() + + var searchResultInfos: [HistoryMessageModel]? + + var teamInfoModel: TeamInfoModel? + + let repo = TeamRepo() + + var memberInTeam: NIMTeamMember? + + weak var delegate: TeamSettingViewModelDelegate? + + public init() {} + + func getData() { + sectionData.removeAll() + sectionData.append(getTwoSection()) + print("current team type : ", teamInfoModel?.team?.type.rawValue as Any) + if let type = teamInfoModel?.team?.type, type == .advanced { + sectionData.append(getThreeSection()) + sectionData.append(getFourSection()) } - - private func getOneSection() -> SettingSectionModel { - let model = SettingSectionModel() - let cellModel = SettingCellModel() - cellModel.type = SettingCellType.SettingHeaderCell.rawValue - cellModel.rowHeight = 160 - cellModel.cornerType = .topLeft.union(.topRight).union(.bottomLeft).union(.bottomRight) - model.cellModels.append(cellModel) - return model + } + + private func getOneSection() -> SettingSectionModel { + let model = SettingSectionModel() + let cellModel = SettingCellModel() + cellModel.type = SettingCellType.SettingHeaderCell.rawValue + cellModel.rowHeight = 160 + cellModel.cornerType = .topLeft.union(.topRight).union(.bottomLeft).union(.bottomRight) + model.cellModels.append(cellModel) + return model + } + + private func getTwoSection() -> SettingSectionModel { + let model = SettingSectionModel() + + /* + let mark = SettingCellModel() + mark.cellName = localizable("mark") + mark.type = SettingCellType.SettingArrowCell.rawValue + mark.cornerType = .topLeft.union(.topRight) + */ + weak var weakSelf = self + let history = SettingCellModel() + history.cellName = localizable("history") + history.type = SettingCellType.SettingArrowCell.rawValue + history.cornerType = .topLeft.union(.topRight) + history.cellClick = { + weakSelf?.delegate?.didClickHistoryMessage() } - - private func getTwoSection() -> SettingSectionModel { - let model = SettingSectionModel() - - /* - let mark = SettingCellModel() - mark.cellName = localizable("mark") - mark.type = SettingCellType.SettingArrowCell.rawValue - mark.cornerType = .topLeft.union(.topRight) - */ - weak var weakSelf = self - let history = SettingCellModel() - history.cellName = localizable("history") - history.type = SettingCellType.SettingArrowCell.rawValue - history.cornerType = .topLeft.union(.topRight) - history.cellClick = { - weakSelf?.delegate?.didClickHistoryMessage() - } - let remind = SettingCellModel() - remind.cellName = localizable("message_remind") - remind.type = SettingCellType.SettingSwitchCell.rawValue - - if let noti = teamInfoModel?.team?.notifyStateForNewMsg, noti == .all { - remind.switchOpen = true - } - remind.swichChange = { isOpen in - if let tid = weakSelf?.teamInfoModel?.team?.teamId { - if isOpen == true { - //weakSelf?.repo.updateNoti(.all, tid) - weakSelf?.repo.updateTeamNotify(.all, tid, { error in - if let err = error { - weakSelf?.delegate?.didNeedRefreshUI() - weakSelf?.delegate?.didError(err) - }else { - remind.switchOpen = false - } - }) - }else { -// weakSelf?.repo.updateNoti(.none, tid) - weakSelf?.repo.updateTeamNotify(.none, tid, { error in - if let err = error { - weakSelf?.delegate?.didNeedRefreshUI() - weakSelf?.delegate?.didError(err) - }else { - remind.switchOpen = true - } - }) - } + let remind = SettingCellModel() + remind.cellName = localizable("message_remind") + remind.type = SettingCellType.SettingSwitchCell.rawValue + + if let noti = teamInfoModel?.team?.notifyStateForNewMsg, noti == .all { + remind.switchOpen = true + } + remind.swichChange = { isOpen in + if let tid = weakSelf?.teamInfoModel?.team?.teamId { + if isOpen == true { + // weakSelf?.repo.updateNoti(.all, tid) + weakSelf?.repo.updateTeamNotify(.all, tid) { error in + if let err = error { + weakSelf?.delegate?.didNeedRefreshUI() + weakSelf?.delegate?.didError(err) + } else { + remind.switchOpen = false } - } - - let setTop = SettingCellModel() - setTop.cellName = localizable("session_set_top") - setTop.type = SettingCellType.SettingSwitchCell.rawValue - setTop.cornerType = .bottomLeft.union(.bottomRight) - - if let tid = teamInfoModel?.team?.teamId { - let session = NIMSession(tid, type: .team) - setTop.switchOpen = repo.isStickTop(session) - } - - setTop.swichChange = { isOpen in - if let tid = weakSelf?.teamInfoModel?.team?.teamId { - let session = NIMSession(tid, type: .team) - if isOpen { - let params = NIMAddStickTopSessionParams.init(session: session) - weakSelf?.repo.addStickTop(params: params) { error, info in - print("add stick : ",error as Any) - if let err = error { - weakSelf?.delegate?.didNeedRefreshUI() - weakSelf?.delegate?.didError(err) - }else { - setTop.switchOpen = true - } - } - }else { - if let info = weakSelf?.repo.getTopSessionInfo(session) { - weakSelf?.repo.removeStickTop(params: info) { error, info in - print("remote stick : ",error as Any) - if let err = error { - weakSelf?.delegate?.didNeedRefreshUI() - weakSelf?.delegate?.didError(err) - }else { - setTop.switchOpen = false - } - } - } - } + } + } else { +// weakSelf?.repo.updateNoti(.none, tid) + weakSelf?.repo.updateTeamNotify(.none, tid) { error in + if let err = error { + weakSelf?.delegate?.didNeedRefreshUI() + weakSelf?.delegate?.didError(err) + } else { + remind.switchOpen = true } + } } - - model.cellModels.append(contentsOf: [history,remind, setTop]) - - return model + } } - - private func getThreeSection() -> SettingSectionModel { - let model = SettingSectionModel() - - weak var weakSelf = self - let nick = SettingCellModel() - nick.cellName = localizable("team_nick") - nick.type = SettingCellType.SettingArrowCell.rawValue - nick.cellClick = { - weakSelf?.delegate?.didClickChangeNick() - } - - let forbiddenWords = SettingCellModel() - forbiddenWords.cellName = localizable("team_no_speak") - forbiddenWords.type = SettingCellType.SettingSwitchCell.rawValue - - if let mute = teamInfoModel?.team?.inAllMuteMode() { - forbiddenWords.switchOpen = mute - } - forbiddenWords.swichChange = { isOpen in - if let tid = weakSelf?.teamInfoModel?.team?.teamId { - weakSelf?.repo.muteAllMembers(isOpen, tid, { error in - print("update mute error : ", error as Any) - if let err = error { - forbiddenWords.switchOpen = !isOpen - weakSelf?.delegate?.didNeedRefreshUI() - weakSelf?.delegate?.didError(err) - }else { - forbiddenWords.switchOpen = isOpen - } - }) - } - } - - if isOwner() { - nick.cornerType = .topLeft.union(.topRight) - forbiddenWords.cornerType = .bottomLeft.union(.bottomRight) - model.cellModels.append(contentsOf: [nick, forbiddenWords]) - }else { - nick.cornerType = .topLeft.union(.topRight).union(.bottomLeft).union(.topRight) - model.cellModels.append(contentsOf: [nick]) - } - - return model + + let setTop = SettingCellModel() + setTop.cellName = localizable("session_set_top") + setTop.type = SettingCellType.SettingSwitchCell.rawValue + setTop.cornerType = .bottomLeft.union(.bottomRight) + + if let tid = teamInfoModel?.team?.teamId { + let session = NIMSession(tid, type: .team) + setTop.switchOpen = repo.isStickTop(session) } - - private func getFourSection() -> SettingSectionModel{ - - weak var weakSelf = self - let model = SettingSectionModel() - - let invitePermission = SettingCellModel() - invitePermission.cellName = localizable("invite_permission") - invitePermission.type = SettingCellType.SettingSelectCell.rawValue - invitePermission.rowHeight = 73 - - if let inviteMode = teamInfoModel?.team?.inviteMode, inviteMode == .all { - invitePermission.subTitle = localizable("team_all") - }else { - invitePermission.subTitle = localizable("team_owner") - } - - invitePermission.cellClick = { - weakSelf?.delegate?.didChangeInviteModeClick(invitePermission) - } - - invitePermission.cornerType = .topLeft.union(.topRight) - - let modifyPermission = SettingCellModel() - modifyPermission.cellName = localizable("modify_team_info_permission") - modifyPermission.type = SettingCellType.SettingSelectCell.rawValue - modifyPermission.rowHeight = 73 - if let updateMode = teamInfoModel?.team?.updateInfoMode, updateMode == .all { - modifyPermission.subTitle = localizable("team_all") - }else { - modifyPermission.subTitle = localizable("team_owner") - } - - modifyPermission.cellClick = { - weakSelf?.delegate?.didUpdateTeamInfoClick(modifyPermission) - } - - let agree = SettingCellModel() - agree.cellName = localizable("agree") - agree.type = SettingCellType.SettingSwitchCell.rawValue - agree.cornerType = .bottomLeft.union(.bottomRight) - if let inviteMode = teamInfoModel?.team?.beInviteMode, inviteMode == .needAuth { - agree.switchOpen = true - } - agree.swichChange = { isOpen in - if let tid = weakSelf?.teamInfoModel?.team?.teamId { - if isOpen == true { - weakSelf?.repo.updateBeInviteMode(.needAuth, tid, { error in - print("join mode : ", error as Any) - if let err = error { - agree.switchOpen = false - weakSelf?.delegate?.didNeedRefreshUI() - weakSelf?.delegate?.didError(err) - }else { - weakSelf?.teamInfoModel?.team?.joinMode = .needAuth - agree.switchOpen = true - } - }) - - }else { - weakSelf?.repo.updateBeInviteMode(.noAuth, tid, { error in - print("join mode : ", error as Any) - if let err = error { - agree.switchOpen = true - weakSelf?.delegate?.didNeedRefreshUI() - weakSelf?.delegate?.didError(err) - }else { - weakSelf?.teamInfoModel?.team?.joinMode = .noAuth - agree.switchOpen = false - } - }) - } + + setTop.swichChange = { isOpen in + if let tid = weakSelf?.teamInfoModel?.team?.teamId { + let session = NIMSession(tid, type: .team) + if isOpen { + let params = NIMAddStickTopSessionParams(session: session) + weakSelf?.repo.addStickTop(params: params) { error, info in + print("add stick : ", error as Any) + if let err = error { + weakSelf?.delegate?.didNeedRefreshUI() + weakSelf?.delegate?.didError(err) + } else { + setTop.switchOpen = true } - } - - if isOwner() { - model.cellModels.append(contentsOf: [invitePermission, modifyPermission, agree]) - } - - return model - } - - func getTeamInfo(_ teamId: String, _ completion: @escaping (Error?) -> Void){ - weak var weakSelf = self - repo.fetchTeamInfo(teamId) { error, teamInfo in - weakSelf?.teamInfoModel = teamInfo - print("get team info user: ", teamInfo?.users as Any) - print("get team info team: ", teamInfo?.team as Any) - print("get team info error: ", error as Any) - - if error == nil { - weakSelf?.getData() - weakSelf?.getCurrentMember(IMKitLoginManager.instance.imAccid, teamId) + } + } else { + if let info = weakSelf?.repo.getTopSessionInfo(session) { + weakSelf?.repo.removeStickTop(params: info) { error, info in + print("remote stick : ", error as Any) + if let err = error { + weakSelf?.delegate?.didNeedRefreshUI() + weakSelf?.delegate?.didError(err) + } else { + setTop.switchOpen = false + } } - completion(error) + } } + } } - - public func dismissTeam(_ teamId: String, _ completion: @escaping (Error?) -> Void) { - repo.dismissTeam(teamId, completion) + + model.cellModels.append(contentsOf: [history, remind, setTop]) + + return model + } + + private func getThreeSection() -> SettingSectionModel { + let model = SettingSectionModel() + + weak var weakSelf = self + let nick = SettingCellModel() + nick.cellName = localizable("team_nick") + nick.type = SettingCellType.SettingArrowCell.rawValue + nick.cellClick = { + weakSelf?.delegate?.didClickChangeNick() } - - public func quitTeam(_ teamId: String, _ completion: @escaping (Error?) -> Void) { - repo.quitTeam(teamId, completion) + + let forbiddenWords = SettingCellModel() + forbiddenWords.cellName = localizable("team_no_speak") + forbiddenWords.type = SettingCellType.SettingSwitchCell.rawValue + + if let mute = teamInfoModel?.team?.inAllMuteMode() { + forbiddenWords.switchOpen = mute } - - @discardableResult - func getCurrentMember(_ userId: String, _ teamId: String?) -> NIMTeamMember? { - if memberInTeam == nil, let tid = teamId { - memberInTeam = repo.teamMember(userId, tid) + forbiddenWords.swichChange = { isOpen in + if let tid = weakSelf?.teamInfoModel?.team?.teamId { + weakSelf?.repo.muteAllMembers(isOpen, tid) { error in + print("update mute error : ", error as Any) + if let err = error { + forbiddenWords.switchOpen = !isOpen + weakSelf?.delegate?.didNeedRefreshUI() + weakSelf?.delegate?.didError(err) + } else { + forbiddenWords.switchOpen = isOpen + } } - return memberInTeam + } } - - func isOwner() -> Bool { - if let accid = teamInfoModel?.team?.owner { - if IMKitLoginManager.instance.isMySelf(accid) { - return true - } - } - return false + + if isOwner() { + nick.cornerType = .topLeft.union(.topRight) + forbiddenWords.cornerType = .bottomLeft.union(.bottomRight) + model.cellModels.append(contentsOf: [nick, forbiddenWords]) + } else { + nick.cornerType = .topLeft.union(.topRight).union(.bottomLeft).union(.topRight) + model.cellModels.append(contentsOf: [nick]) } - - public func updateInfoMode(_ mode: NIMTeamUpdateInfoMode, _ teamId: String, _ completion: @escaping (Error?) -> Void){ - repo.updateTeamInfoPrivilege(mode, teamId, completion) + + return model + } + + private func getFourSection() -> SettingSectionModel { + weak var weakSelf = self + let model = SettingSectionModel() + + let invitePermission = SettingCellModel() + invitePermission.cellName = localizable("invite_permission") + invitePermission.type = SettingCellType.SettingSelectCell.rawValue + invitePermission.rowHeight = 73 + + if let inviteMode = teamInfoModel?.team?.inviteMode, inviteMode == .all { + invitePermission.subTitle = localizable("team_all") + } else { + invitePermission.subTitle = localizable("team_owner") } - - public func updateInviteMode(_ mode: NIMTeamInviteMode, _ teamId: String, _ completion: @escaping (Error?) -> Void){ - repo.updateInviteMode(mode, teamId, completion) + + invitePermission.cellClick = { + weakSelf?.delegate?.didChangeInviteModeClick(invitePermission) } - - public func isNormalTeam() -> Bool { - - if let type = teamInfoModel?.team?.type, type == .normal { - return true - } - return false + + invitePermission.cornerType = .topLeft.union(.topRight) + + let modifyPermission = SettingCellModel() + modifyPermission.cellName = localizable("modify_team_info_permission") + modifyPermission.type = SettingCellType.SettingSelectCell.rawValue + modifyPermission.rowHeight = 73 + if let updateMode = teamInfoModel?.team?.updateInfoMode, updateMode == .all { + modifyPermission.subTitle = localizable("team_all") + } else { + modifyPermission.subTitle = localizable("team_owner") } - - public func searchMessages(_ session:NIMSession,option:NIMMessageSearchOption,_ completion:@escaping (NSError?,[HistoryMessageModel]?)->()) { - weak var weakSelf = self - repo.searchMessages(session, option: option) { error, messages in - if error == nil { - weakSelf?.searchResultInfos = messages - completion(nil,weakSelf?.searchResultInfos) - }else { - completion(error,nil) + + modifyPermission.cellClick = { + weakSelf?.delegate?.didUpdateTeamInfoClick(modifyPermission) + } + + let agree = SettingCellModel() + agree.cellName = localizable("agree") + agree.type = SettingCellType.SettingSwitchCell.rawValue + agree.cornerType = .bottomLeft.union(.bottomRight) + if let inviteMode = teamInfoModel?.team?.beInviteMode, inviteMode == .needAuth { + agree.switchOpen = true + } + agree.swichChange = { isOpen in + if let tid = weakSelf?.teamInfoModel?.team?.teamId { + if isOpen == true { + weakSelf?.repo.updateBeInviteMode(.needAuth, tid) { error in + print("join mode : ", error as Any) + if let err = error { + agree.switchOpen = false + weakSelf?.delegate?.didNeedRefreshUI() + weakSelf?.delegate?.didError(err) + } else { + weakSelf?.teamInfoModel?.team?.joinMode = .needAuth + agree.switchOpen = true + } + } + + } else { + weakSelf?.repo.updateBeInviteMode(.noAuth, tid) { error in + print("join mode : ", error as Any) + if let err = error { + agree.switchOpen = true + weakSelf?.delegate?.didNeedRefreshUI() + weakSelf?.delegate?.didError(err) + } else { + weakSelf?.teamInfoModel?.team?.joinMode = .noAuth + agree.switchOpen = false } + } } + } + } + + if isOwner() { + model.cellModels.append(contentsOf: [invitePermission, modifyPermission, agree]) + } + + return model + } + + func getTeamInfo(_ teamId: String, _ completion: @escaping (Error?) -> Void) { + weak var weakSelf = self + repo.fetchTeamInfo(teamId) { error, teamInfo in + weakSelf?.teamInfoModel = teamInfo + print("get team info user: ", teamInfo?.users as Any) + print("get team info team: ", teamInfo?.team as Any) + print("get team info error: ", error as Any) + + if error == nil { + weakSelf?.getData() + weakSelf?.getCurrentMember(IMKitLoginManager.instance.imAccid, teamId) + } + completion(error) + } + } + + public func dismissTeam(_ teamId: String, _ completion: @escaping (Error?) -> Void) { + repo.dismissTeam(teamId, completion) + } + + public func quitTeam(_ teamId: String, _ completion: @escaping (Error?) -> Void) { + repo.quitTeam(teamId, completion) + } + + @discardableResult + func getCurrentMember(_ userId: String, _ teamId: String?) -> NIMTeamMember? { + if memberInTeam == nil, let tid = teamId { + memberInTeam = repo.teamMember(userId, tid) + } + return memberInTeam + } + + func isOwner() -> Bool { + if let accid = teamInfoModel?.team?.owner { + if IMKitLoginManager.instance.isMySelf(accid) { + return true + } + } + return false + } + + public func updateInfoMode(_ mode: NIMTeamUpdateInfoMode, _ teamId: String, + _ completion: @escaping (Error?) -> Void) { + repo.updateTeamInfoPrivilege(mode, teamId, completion) + } + + public func updateInviteMode(_ mode: NIMTeamInviteMode, _ teamId: String, + _ completion: @escaping (Error?) -> Void) { + repo.updateInviteMode(mode, teamId, completion) + } + + public func isNormalTeam() -> Bool { + if let type = teamInfoModel?.team?.type, type == .normal { + return true + } + return false + } + + public func searchMessages(_ session: NIMSession, option: NIMMessageSearchOption, + _ completion: @escaping (NSError?, [HistoryMessageModel]?) -> Void) { + weak var weakSelf = self + repo.searchMessages(session, option: option) { error, messages in + if error == nil { + weakSelf?.searchResultInfos = messages + completion(nil, weakSelf?.searchResultInfos) + } else { + completion(error, nil) + } } + } } diff --git a/NETeamUIKit/NEKitTeamUI/Classes/TeamConstant.swift b/NETeamUIKit/NEKitTeamUI/Classes/TeamConstant.swift index bf8a5c07..37de746e 100644 --- a/NETeamUIKit/NEKitTeamUI/Classes/TeamConstant.swift +++ b/NETeamUIKit/NEKitTeamUI/Classes/TeamConstant.swift @@ -1,16 +1,17 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation @_exported import NEKitCore @_exported import NEKitCommonUI -//@_exported +// @_exported @_exported import NEKitCommon @_exported import NEKitTeam @_exported import SDWebImage @_exported import NEKitCoreIM let coreLoader = CoreLoader() -func localizable(_ key: String) -> String{ - return coreLoader.localizable(key) +func localizable(_ key: String) -> String { + coreLoader.localizable(key) } diff --git a/NETeamUIKit/NEKitTeamUI/Classes/TeamRouter.swift b/NETeamUIKit/NEKitTeamUI/Classes/TeamRouter.swift index 9e86db5f..a5245736 100644 --- a/NETeamUIKit/NEKitTeamUI/Classes/TeamRouter.swift +++ b/NETeamUIKit/NEKitTeamUI/Classes/TeamRouter.swift @@ -1,92 +1,94 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import Foundation import NEKitTeam import NEKitCore import NEKitCoreIM import NIMSDK -public class TeamRouter { - - public static var iconUrls = ["https://s.netease.im/safe/ABg8YjWQWvcqO6sAAAAAAAAAAAA?_im_url=1", - "https://s.netease.im/safe/ABg8YjmQWvcqO6sAAAAAAAABAAA?_im_url=1", - "https://s.netease.im/safe/ABg8YjyQWvcqO6sAAAAAAAABAAA?_im_url=1", - "https://s.netease.im/safe/ABg8YkCQWvcqO6sAAAAAAAABAAA?_im_url=1", - "https://s.netease.im/safe/ABg8YkSQWvcqO6sAAAAAAAABAAA?_im_url=1"] - - public static let repo = TeamRepo() - - public static func register(){ - - Router.shared.register(TeamSettingViewRouter){ param in - let nav = param["nav"] as? UINavigationController - let teamId = param["teamid"] as? String - let teamSetting = TeamSettingViewController() - teamSetting.teamId = teamId - nav?.pushViewController(teamSetting, animated: true) +public enum TeamRouter { + public static var iconUrls = ["https://s.netease.im/safe/ABg8YjWQWvcqO6sAAAAAAAAAAAA?_im_url=1", + "https://s.netease.im/safe/ABg8YjmQWvcqO6sAAAAAAAABAAA?_im_url=1", + "https://s.netease.im/safe/ABg8YjyQWvcqO6sAAAAAAAABAAA?_im_url=1", + "https://s.netease.im/safe/ABg8YkCQWvcqO6sAAAAAAAABAAA?_im_url=1", + "https://s.netease.im/safe/ABg8YkSQWvcqO6sAAAAAAAABAAA?_im_url=1"] + + public static let repo = TeamRepo() + + public static func register() { + Router.shared.register(TeamSettingViewRouter) { param in + let nav = param["nav"] as? UINavigationController + let teamId = param["teamid"] as? String + let teamSetting = TeamSettingViewController() + teamSetting.teamId = teamId + nav?.pushViewController(teamSetting, animated: true) + } + + Router.shared.register(TeamCreateDisuss) { param in + if let accids = param["accids"] as? [String] { + var name = (param["names"] as? String) ?? localizable("normal_team") + if name.count > 30 { + name = String(name.prefix(30)) } - - Router.shared.register(TeamCreateDisuss){ param in - if let accids = param["accids"] as? [String] { - var name = (param["names"] as? String) ?? localizable("normal_team") - if name.count > 30 { - name = String(name.prefix(30)) - } - let iconUrl = (param["url"] as? String) ?? iconUrls[Int(arc4random()) % iconUrls.count] - repo.createNormalTeam(accids, iconUrl, name) { error, teamid, failedIds in - var result = [String : Any]() - if let err = error { - result["code"] = err.code - result["msg"] = err.localizedDescription - }else { - result["code"] = 0 - result["msg"] = "ok" - result["teamId"] = teamid - } - Router.shared.use(TeamCreateDiscussResult, parameters: result, closure: nil) - } - } + let iconUrl = (param["url"] as? String) ?? + iconUrls[Int(arc4random()) % iconUrls.count] + repo.createNormalTeam(accids, iconUrl, name) { error, teamid, failedIds in + var result = [String: Any]() + if let err = error { + result["code"] = err.code + result["msg"] = err.localizedDescription + } else { + result["code"] = 0 + result["msg"] = "ok" + result["teamId"] = teamid + } + Router.shared.use(TeamCreateDiscussResult, parameters: result, closure: nil) } - - Router.shared.register(TeamCreateSenior){ param in - - if let accids = param["accids"] as? [String] { - var name = (param["names"] as? String) ?? localizable("senior_team") - if name.count > 30 { - name = String(name.prefix(30)) - } - let iconUrl = (param["url"] as? String) ?? iconUrls[Int(arc4random()) % iconUrls.count] - repo.createAdvanceTeam(accids, iconUrl, name) { error, teamid, failedIds in - var result = [String : Any]() - if let err = error { - result["code"] = err.code - result["msg"] = err.localizedDescription - }else { - result["code"] = 0 - result["msg"] = "ok" - result["teamId"] = teamid - - repo.sendCreateAdavanceNoti(teamid ?? "", localizable("create_senior_team_noti")) { error in - print("send noti message : ", error as Any) - } - } - Router.shared.use(TeamCreateSeniorResult, parameters: result, closure: nil) - print("creat senior reuslt : ", result) - } - } + } + } + + Router.shared.register(TeamCreateSenior) { param in + + if let accids = param["accids"] as? [String] { + var name = (param["names"] as? String) ?? localizable("senior_team") + if name.count > 30 { + name = String(name.prefix(30)) } - - Router.shared.register(SearchMessageRouter){ param in + let iconUrl = (param["url"] as? String) ?? + iconUrls[Int(arc4random()) % iconUrls.count] + repo.createAdvanceTeam(accids, iconUrl, name) { error, teamid, failedIds in + var result = [String: Any]() + if let err = error { + result["code"] = err.code + result["msg"] = err.localizedDescription + } else { + result["code"] = 0 + result["msg"] = "ok" + result["teamId"] = teamid - let nav = param["nav"] as? UINavigationController - if let tid = param["teamId"] as? String { - let session = NIMSession(tid, type: .team) - let searchMsgCtrl = TeamHistoryMessageController(session: session) - nav?.pushViewController(searchMsgCtrl, animated: true) + repo.sendCreateAdavanceNoti( + teamid ?? "", + localizable("create_senior_team_noti") + ) { error in + print("send noti message : ", error as Any) } - + } + Router.shared.use(TeamCreateSeniorResult, parameters: result, closure: nil) + print("creat senior reuslt : ", result) } - + } + } + + Router.shared.register(SearchMessageRouter) { param in + + let nav = param["nav"] as? UINavigationController + if let tid = param["teamId"] as? String { + let session = NIMSession(tid, type: .team) + let searchMsgCtrl = TeamHistoryMessageController(session: session) + nav?.pushViewController(searchMsgCtrl, animated: true) + } } + } } diff --git a/Podfile b/Podfile index 30784b8f..7ae8f3fe 100644 --- a/Podfile +++ b/Podfile @@ -9,35 +9,28 @@ target 'app' do pod 'YXLogin', '1.0.0' #可选UI库 - pod 'NEContactUIKit', '9.2.6-rc01' - pod 'NEQChatUIKit', '9.2.6-rc01' - pod 'NEConversationUIKit', '9.2.6-rc01' - pod 'NEChatUIKit', '9.2.6-rc01' - pod 'NETeamUIKit', '9.2.6-rc01' + pod 'NEContactUIKit', '9.2.7' + pod 'NEQChatUIKit', '9.2.7' + pod 'NEConversationUIKit', '9.2.7' + pod 'NEChatUIKit', '9.2.7' + pod 'NETeamUIKit', '9.2.7' #可选Kit库(和UIKit对应) - pod 'NEContactKit', '9.2.6-rc01' - pod 'NEQChatKit', '9.2.6-rc01' - pod 'NEConversationKit', '9.2.6-rc01' - pod 'NEChatKit', '9.2.6-rc01' - pod 'NETeamKit', '9.2.6-rc01' + pod 'NEContactKit', '9.2.7' + pod 'NEQChatKit', '9.2.7' + pod 'NEConversationKit', '9.2.7' + pod 'NEChatKit', '9.2.7' + pod 'NETeamKit', '9.2.7' #基础kit库 - pod 'NECommonUIKit', '9.2.6-rc01' - pod 'NECommonKit', '9.2.6-rc01' - pod 'NECoreIMKit', '9.2.6-rc01' - pod 'NECoreKit', '9.2.6-rc01' + pod 'NECommonUIKit', '9.2.7' + pod 'NECommonKit', '9.2.7' + pod 'NECoreIMKit', '9.2.7' + pod 'NECoreKit', '9.2.7' # 如果需要查看UI部分源码请注释掉以上在线依赖,打开下面的本地依赖 -# pod 'NEChatKit', '9.2.6-rc01' -# pod 'NEConversationKit', '9.2.6-rc01' -# pod 'NEContactKit', '9.2.6-rc01' -# pod 'NETeamKit', '9.2.6-rc01' -# pod 'NEQChatKit','9.2.6-rc01' -# -# # pod 'NEKitQChatUI', :path => 'NEQChatUIKit/NEKitQChatUI.podspec' # pod 'NEKitContactUI', :path => 'NEContactUIKit/NEKitContactUI.podspec' # pod 'NEKitConversationUI', :path => 'NEConversationUIKit/NEKitConversationUI.podspec' @@ -45,3 +38,12 @@ target 'app' do # pod 'NEKitChatUI', :path => 'NEChatUIKit/NEKitChatUI.podspec' # end + +#⚠️如果pod依赖报错,可打开以下注释 +#post_install do |installer| +# installer.pods_project.targets.each do |target| +# target.build_configurations.each do |config| +# config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES' +# end +# end +#end diff --git a/app.xcodeproj/project.pbxproj b/app.xcodeproj/project.pbxproj index c96e6b34..3eb75dac 100644 --- a/app.xcodeproj/project.pbxproj +++ b/app.xcodeproj/project.pbxproj @@ -179,7 +179,6 @@ 4B3B9BD9277AFEE50091A74E /* Resources */, 8293FFD3DEA5F5A02EBCD9D8 /* [CP] Embed Pods Frameworks */, 39722F9327998A14007BFC8B /* Embed Frameworks */, - CFE776A1DA8AEF96EB45958E /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -278,23 +277,6 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-app/Pods-app-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - CFE776A1DA8AEF96EB45958E /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-app/Pods-app-resources-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Copy Pods Resources"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-app/Pods-app-resources-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-app/Pods-app-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ From 46e488d190395ade71f6d15e4dc2404f5df2a6f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E5=96=84=E6=A0=8B?= Date: Fri, 26 Aug 2022 14:29:38 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=A3=B3=E5=B7=A5?= =?UTF-8?q?=E7=A8=8B=E6=94=B9=E5=8A=A8=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Mine/InputPersonInfoController.swift | 221 +++++---- app/Mine/IntroduceBrandViewController.swift | 154 +++--- app/Mine/MessageRemindViewController.swift | 166 ++++--- app/Mine/MineSettingViewController.swift | 256 +++++----- app/Mine/PersonInfoViewController.swift | 488 ++++++++++---------- 5 files changed, 629 insertions(+), 656 deletions(-) diff --git a/app/Mine/InputPersonInfoController.swift b/app/Mine/InputPersonInfoController.swift index de29e695..73b51556 100644 --- a/app/Mine/InputPersonInfoController.swift +++ b/app/Mine/InputPersonInfoController.swift @@ -1,134 +1,125 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCore import NEKitChatUI -public enum EditType:Int { - case nickName = 0 - case cellphone - case email - case specialSign +public enum EditType: Int { + case nickName = 0 + case cellphone + case email + case specialSign } -class InputPersonInfoController: NEBaseViewController { - - - typealias ResultCallBack = (String) -> Void - public var contentText:String? { - didSet { - self.textField.text = contentText - } - } - public var callBack:ResultCallBack? - private var limitNumberCount = 0 - override func viewDidLoad() { - super.viewDidLoad() - setupSubviews() - initialConfig() +class InputPersonInfoController: NEBaseViewController,UITextFieldDelegate { + typealias ResultCallBack = (String) -> Void + public var contentText: String? { + didSet { + textField.text = contentText } - - func setupSubviews(){ + } - view.addSubview(textfieldBgView) - if #available(iOS 11.0, *) { - NSLayoutConstraint.activate([ - textfieldBgView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20.0), - textfieldBgView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20), - textfieldBgView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 12), - textfieldBgView.heightAnchor.constraint(equalToConstant: 50) - ]) - }else { - NSLayoutConstraint.activate([ - textfieldBgView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20.0), - textfieldBgView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20), - textfieldBgView.topAnchor.constraint(equalTo: view.topAnchor, constant: 12), - textfieldBgView.heightAnchor.constraint(equalToConstant: 50) - ]) - } - - textfieldBgView.addSubview(textField) - NSLayoutConstraint.activate([ - textField.leftAnchor.constraint(equalTo: textfieldBgView.leftAnchor, constant: 16), - textField.rightAnchor.constraint(equalTo: textfieldBgView.rightAnchor, constant: -12), - textField.topAnchor.constraint(equalTo: textfieldBgView.topAnchor, constant: 0), - textField.heightAnchor.constraint(equalToConstant: 44) - ]) - - - - } - - func initialConfig(){ - addRightAction("保存", #selector(saveName), self) - view.backgroundColor = UIColor.init(hexString: "0xF1F1F6") + public var callBack: ResultCallBack? + private var limitNumberCount = 0 + override func viewDidLoad() { + super.viewDidLoad() + setupSubviews() + initialConfig() + } + + func setupSubviews() { + view.addSubview(textfieldBgView) + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + textfieldBgView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20.0), + textfieldBgView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20), + textfieldBgView.topAnchor.constraint( + equalTo: view.safeAreaLayoutGuide.topAnchor, + constant: 12 + ), + textfieldBgView.heightAnchor.constraint(equalToConstant: 50), + ]) + } else { + NSLayoutConstraint.activate([ + textfieldBgView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20.0), + textfieldBgView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20), + textfieldBgView.topAnchor.constraint(equalTo: view.topAnchor, constant: 12), + textfieldBgView.heightAnchor.constraint(equalToConstant: 50), + ]) } - @objc func saveName(){ - weak var weakSelf = self - if let block = callBack { - block(textField.text ?? "") - weakSelf?.navigationController?.popViewController(animated: true) - } + textfieldBgView.addSubview(textField) + NSLayoutConstraint.activate([ + textField.leftAnchor.constraint(equalTo: textfieldBgView.leftAnchor, constant: 16), + textField.rightAnchor.constraint(equalTo: textfieldBgView.rightAnchor, constant: -12), + textField.topAnchor.constraint(equalTo: textfieldBgView.topAnchor, constant: 0), + textField.heightAnchor.constraint(equalToConstant: 44), + ]) + } + + func initialConfig() { + addRightAction("保存", #selector(saveName), self) + view.backgroundColor = UIColor(hexString: "0xF1F1F6") + } + + @objc func saveName() { + weak var weakSelf = self + if let block = callBack { + block(textField.text ?? "") + weakSelf?.navigationController?.popViewController(animated: true) } + } - func configTitle(editType:EditType) { - switch editType { - case .nickName: - self.title = "昵称" - limitNumberCount = 30 - break - case .cellphone: - self.title = "手机" - limitNumberCount = 11 - break - case .email: - self.title = "邮箱" - limitNumberCount = 30 - break - case .specialSign: - self.title = "个性签名" - limitNumberCount = 50 - break - } + func configTitle(editType: EditType) { + switch editType { + case .nickName: + title = "昵称" + limitNumberCount = 30 + case .cellphone: + title = "手机" + limitNumberCount = 11 + case .email: + title = "邮箱" + limitNumberCount = 30 + case .specialSign: + title = "个性签名" + limitNumberCount = 50 } - - - - //MARK: lazy Method - - lazy var textField: UITextField = { - let text = UITextField() - text.translatesAutoresizingMaskIntoConstraints = false - text.textColor = UIColor.init(hexString: "0x333333") - text.font = UIFont.systemFont(ofSize: 14) - text.delegate = self - text.clearButtonMode = .always - text.becomeFirstResponder() - return text - }() - - lazy var textfieldBgView:UIView = { - let backView = UIView() - backView.backgroundColor = .white - backView.clipsToBounds = true - backView.layer.cornerRadius = 8.0 - backView.translatesAutoresizingMaskIntoConstraints = false - return backView - }() + } -} + // MARK: lazy Method -extension InputPersonInfoController: UITextFieldDelegate { - - func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { - - if let text = (textField.text as NSString?)?.replacingCharacters(in: range, with: string), text.count > limitNumberCount { - showToast("最多只能输入\(limitNumberCount)个字符哦") - return false - } - return true + lazy var textField: UITextField = { + let text = UITextField() + text.translatesAutoresizingMaskIntoConstraints = false + text.textColor = UIColor(hexString: "0x333333") + text.font = UIFont.systemFont(ofSize: 14) + text.delegate = self + text.clearButtonMode = .always + text.becomeFirstResponder() + return text + }() + + lazy var textfieldBgView: UIView = { + let backView = UIView() + backView.backgroundColor = .white + backView.clipsToBounds = true + backView.layer.cornerRadius = 8.0 + backView.translatesAutoresizingMaskIntoConstraints = false + return backView + }() + //MARK: UITextFieldDelegate + func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, + replacementString string: String) -> Bool { + if let text = (textField.text as NSString?)?.replacingCharacters(in: range, with: string), + text.count > limitNumberCount { + showToast("最多只能输入\(limitNumberCount)个字符哦") + return false + } + return true } } + diff --git a/app/Mine/IntroduceBrandViewController.swift b/app/Mine/IntroduceBrandViewController.swift index 79b62346..7706c586 100644 --- a/app/Mine/IntroduceBrandViewController.swift +++ b/app/Mine/IntroduceBrandViewController.swift @@ -1,97 +1,99 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCore import NEKitTeamUI import NEKitChatUI -class IntroduceBrandViewController: NEBaseViewController { +class IntroduceBrandViewController: NEBaseViewController,UITableViewDelegate, UITableViewDataSource { + private var viewModel = IntroduceViewModel() - private var viewModel = IntroduceViewModel() - - override func viewDidLoad() { - super.viewDidLoad() - viewModel.getData() - setupSubviews() - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - navigationController?.setNavigationBarHidden(false, animated: false) - } - - func setupSubviews(){ - view.addSubview(headImage) - view.addSubview(tableView) - - NSLayoutConstraint.activate([ - headImage.centerXAnchor.constraint(equalTo: view.centerXAnchor), - headImage.topAnchor.constraint(equalTo: view.topAnchor,constant: (kNavigationHeight + KStatusBarHeight + 20)), - headImage.widthAnchor.constraint(equalToConstant: 94), - headImage.heightAnchor.constraint(equalToConstant: 66) + override func viewDidLoad() { + super.viewDidLoad() + viewModel.getData() + setupSubviews() + } - ]) - - NSLayoutConstraint.activate([ - tableView.leftAnchor.constraint(equalTo: view.leftAnchor), - tableView.rightAnchor.constraint(equalTo: view.rightAnchor), - tableView.topAnchor.constraint(equalTo: headImage.bottomAnchor,constant: 45), - tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor) - ]) - } + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + navigationController?.setNavigationBarHidden(false, animated: false) + } - - //MARK: lazy method - private lazy var headImage:UIImageView = { - let image = UIImageView.init(image: UIImage.init(named: "yunxin_logo")) - image.translatesAutoresizingMaskIntoConstraints = false - return image - }() - - lazy var tableView: UITableView = { - let table = UITableView() - table.translatesAutoresizingMaskIntoConstraints = false - table.backgroundColor = .white - table.dataSource = self - table.delegate = self - table.separatorStyle = .none - table.register(VersionCell.self, forCellReuseIdentifier: "VersionCell") - if #available(iOS 15.0, *) { - table.sectionHeaderTopPadding = 0.0 - } - return table - }() -} + func setupSubviews() { + view.addSubview(headImage) + view.addSubview(tableView) -extension IntroduceBrandViewController:UITableViewDelegate,UITableViewDataSource { - func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return viewModel.sectionData.count - } + NSLayoutConstraint.activate([ + headImage.centerXAnchor.constraint(equalTo: view.centerXAnchor), + headImage.topAnchor.constraint( + equalTo: view.topAnchor, + constant: kNavigationHeight + KStatusBarHeight + 20 + ), + headImage.widthAnchor.constraint(equalToConstant: 94), + headImage.heightAnchor.constraint(equalToConstant: 66), + ]) + NSLayoutConstraint.activate([ + tableView.leftAnchor.constraint(equalTo: view.leftAnchor), + tableView.rightAnchor.constraint(equalTo: view.rightAnchor), + tableView.topAnchor.constraint(equalTo: headImage.bottomAnchor, constant: 45), + tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), + ]) + } + + // MARK: lazy method + + private lazy var headImage: UIImageView = { + let image = UIImageView(image: UIImage(named: "yunxin_logo")) + image.translatesAutoresizingMaskIntoConstraints = false + return image + }() + + lazy var tableView: UITableView = { + let table = UITableView() + table.translatesAutoresizingMaskIntoConstraints = false + table.backgroundColor = .white + table.dataSource = self + table.delegate = self + table.separatorStyle = .none + table.register(VersionCell.self, forCellReuseIdentifier: "VersionCell") + if #available(iOS 15.0, *) { + table.sectionHeaderTopPadding = 0.0 + } + return table + }() + + //MARK: UITableViewDelegate, UITableViewDataSource + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + viewModel.sectionData.count + } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let model = viewModel.sectionData[indexPath.row] - if let cell = tableView.dequeueReusableCell(withIdentifier: "VersionCell", for: indexPath) as? VersionCell { - cell.configData(model: model) - if indexPath.row == 0 { - cell.cellType = .version - }else { - cell.cellType = .productIntroduce - } - return cell + let model = viewModel.sectionData[indexPath.row] + if let cell = tableView.dequeueReusableCell( + withIdentifier: "VersionCell", + for: indexPath + ) as? VersionCell { + cell.configData(model: model) + if indexPath.row == 0 { + cell.cellType = .version + } else { + cell.cellType = .productIntroduce } - return UITableViewCell() + return cell + } + return UITableViewCell() } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - - if indexPath.row == 1 { - let ctrl = NEAboutWebViewController.init(url: "https://netease.im/m/") - navigationController?.pushViewController(ctrl, animated: true) - } - + if indexPath.row == 1 { + let ctrl = NEAboutWebViewController(url: "https://netease.im/m/") + navigationController?.pushViewController(ctrl, animated: true) + } } } + diff --git a/app/Mine/MessageRemindViewController.swift b/app/Mine/MessageRemindViewController.swift index ca2acc09..8add738c 100644 --- a/app/Mine/MessageRemindViewController.swift +++ b/app/Mine/MessageRemindViewController.swift @@ -1,114 +1,110 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCore import NEKitTeamUI import NEKitChatUI +class MessageRemindViewController: NEBaseViewController,UITableViewDelegate, UITableViewDataSource { + public var cellClassDic = + [SettingCellType.SettingSwitchCell.rawValue: TeamSettingSwitchCell.self] + private var viewModel = MessageRemindViewModel() -class MessageRemindViewController: NEBaseViewController { - - public var cellClassDic = [SettingCellType.SettingSwitchCell.rawValue: TeamSettingSwitchCell.self] - private var viewModel = MessageRemindViewModel() - - - - override func viewDidLoad() { - super.viewDidLoad() - viewModel.getData() - setupSubviews() - initialConfig() - } - - func initialConfig(){ - self.title = "消息提醒" - } - - func setupSubviews(){ - view.addSubview(tableView) - NSLayoutConstraint.activate([ - tableView.leftAnchor.constraint(equalTo: view.leftAnchor), - tableView.rightAnchor.constraint(equalTo: view.rightAnchor), - tableView.topAnchor.constraint(equalTo: view.topAnchor), - tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor) - ]) - - cellClassDic.forEach { (key: Int, value: BaseTeamSettingCell.Type) in - tableView.register(value, forCellReuseIdentifier: "\(key)") - } + override func viewDidLoad() { + super.viewDidLoad() + viewModel.getData() + setupSubviews() + initialConfig() + } + + func initialConfig() { + title = "消息提醒" + } + + func setupSubviews() { + view.addSubview(tableView) + NSLayoutConstraint.activate([ + tableView.leftAnchor.constraint(equalTo: view.leftAnchor), + tableView.rightAnchor.constraint(equalTo: view.rightAnchor), + tableView.topAnchor.constraint(equalTo: view.topAnchor), + tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), + ]) + + cellClassDic.forEach { (key: Int, value: BaseTeamSettingCell.Type) in + tableView.register(value, forCellReuseIdentifier: "\(key)") } - lazy var tableView: UITableView = { - let table = UITableView() - table.translatesAutoresizingMaskIntoConstraints = false - table.backgroundColor = UIColor.init(hexString: "0xF1F1F6") - table.dataSource = self - table.delegate = self - table.separatorColor = .clear - table.separatorStyle = .none - table.sectionHeaderHeight = 12.0 - if #available(iOS 15.0, *) { - table.sectionHeaderTopPadding = 0.0 - } - return table - }() -} + } -extension MessageRemindViewController:UITableViewDelegate,UITableViewDataSource { - + lazy var tableView: UITableView = { + let table = UITableView() + table.translatesAutoresizingMaskIntoConstraints = false + table.backgroundColor = UIColor(hexString: "0xF1F1F6") + table.dataSource = self + table.delegate = self + table.separatorColor = .clear + table.separatorStyle = .none + table.sectionHeaderHeight = 12.0 + if #available(iOS 15.0, *) { + table.sectionHeaderTopPadding = 0.0 + } + return table + }() + //MARK: UITableViewDelegate, UITableViewDataSource func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - if viewModel.sectionData.count > section { - let model = viewModel.sectionData[section] - return model.cellModels.count - } - return 0 + if viewModel.sectionData.count > section { + let model = viewModel.sectionData[section] + return model.cellModels.count + } + return 0 } - + func numberOfSections(in tableView: UITableView) -> Int { - return viewModel.sectionData.count + viewModel.sectionData.count } - - func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let model = viewModel.sectionData[indexPath.section].cellModels[indexPath.row] - if let cell = tableView.dequeueReusableCell(withIdentifier: "\(model.type)", for: indexPath) as? BaseTeamSettingCell { - cell.configure(model) - return cell - } - return UITableViewCell() + let model = viewModel.sectionData[indexPath.section].cellModels[indexPath.row] + if let cell = tableView.dequeueReusableCell( + withIdentifier: "\(model.type)", + for: indexPath + ) as? BaseTeamSettingCell { + cell.configure(model) + return cell + } + return UITableViewCell() } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - -// let model = viewModel.sectionData[indexPath.section].cellModels[indexPath.row] -// if let block = model.cellClick { -// block() -// } - + // let model = viewModel.sectionData[indexPath.section].cellModels[indexPath.row] + // if let block = model.cellClick { + // block() + // } } - + func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - let model = viewModel.sectionData[indexPath.section].cellModels[indexPath.row] - return model.rowHeight + let model = viewModel.sectionData[indexPath.section].cellModels[indexPath.row] + return model.rowHeight } - - func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { - if viewModel.sectionData.count > section { - let model = viewModel.sectionData[section] - if model.cellModels.count > 0 { - return 12.0 - } + func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { + if viewModel.sectionData.count > section { + let model = viewModel.sectionData[section] + if model.cellModels.count > 0 { + return 12.0 } - return 0 + } + return 0 } - + func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { - let header = UIView() - header.backgroundColor = UIColor.init(hexString: "0xF1F1F6") - return header + let header = UIView() + header.backgroundColor = UIColor(hexString: "0xF1F1F6") + return header } } + + diff --git a/app/Mine/MineSettingViewController.swift b/app/Mine/MineSettingViewController.swift index 2b9dd456..e1e12123 100644 --- a/app/Mine/MineSettingViewController.swift +++ b/app/Mine/MineSettingViewController.swift @@ -1,6 +1,7 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCore @@ -8,86 +9,86 @@ import NEKitTeamUI import YXLogin import NIMSDK -class MineSettingViewController: NEBaseViewController { - - private var viewModel = MineSettingViewModel() - public var cellClassDic = [SettingCellType.SettingArrowCell.rawValue: TeamArrowSettingCell.self, SettingCellType.SettingSwitchCell.rawValue: TeamSettingSwitchCell.self] - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - navigationController?.setNavigationBarHidden(false, animated: false) - } - - override func viewDidLoad() { - super.viewDidLoad() - viewModel.getData() - setupSubviews() - initialConfig() - } - - func initialConfig(){ - self.title = "设置" - viewModel.delegate = self - } - - func setupSubviews(){ - view.addSubview(tableView) - NSLayoutConstraint.activate([ - tableView.leftAnchor.constraint(equalTo: view.leftAnchor), - tableView.rightAnchor.constraint(equalTo: view.rightAnchor), - tableView.topAnchor.constraint(equalTo: view.topAnchor), - tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor) - ]) - - cellClassDic.forEach { (key: Int, value: BaseTeamSettingCell.Type) in - tableView.register(value, forCellReuseIdentifier: "\(key)") - } - } - - - lazy var tableView: UITableView = { - let table = UITableView() - table.translatesAutoresizingMaskIntoConstraints = false - table.backgroundColor = UIColor.init(hexString: "0xF1F1F6") - table.dataSource = self - table.delegate = self - table.separatorColor = .clear - table.separatorStyle = .none - table.sectionHeaderHeight = 12.0 - table.tableFooterView = getFooterView() - if #available(iOS 15.0, *) { - table.sectionHeaderTopPadding = 0.0 - } - return table - }() - - - func getFooterView() -> UIView? { - +class MineSettingViewController: NEBaseViewController,UITableViewDataSource, UITableViewDelegate { + private var viewModel = MineSettingViewModel() + public var cellClassDic = [ + SettingCellType.SettingArrowCell.rawValue: TeamArrowSettingCell.self, + SettingCellType.SettingSwitchCell.rawValue: TeamSettingSwitchCell.self, + ] + private var tag = "MineSettingViewController" + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + navigationController?.setNavigationBarHidden(false, animated: false) + } + + override func viewDidLoad() { + super.viewDidLoad() + viewModel.getData() + setupSubviews() + initialConfig() + } + + func initialConfig() { + title = "设置" + viewModel.delegate = self + } + + func setupSubviews() { + view.addSubview(tableView) + NSLayoutConstraint.activate([ + tableView.leftAnchor.constraint(equalTo: view.leftAnchor), + tableView.rightAnchor.constraint(equalTo: view.rightAnchor), + tableView.topAnchor.constraint(equalTo: view.topAnchor), + tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), + ]) + + cellClassDic.forEach { (key: Int, value: BaseTeamSettingCell.Type) in + tableView.register(value, forCellReuseIdentifier: "\(key)") + } + } + + lazy var tableView: UITableView = { + let table = UITableView() + table.translatesAutoresizingMaskIntoConstraints = false + table.backgroundColor = UIColor(hexString: "0xF1F1F6") + table.dataSource = self + table.delegate = self + table.separatorColor = .clear + table.separatorStyle = .none + table.sectionHeaderHeight = 12.0 + table.tableFooterView = getFooterView() + if #available(iOS 15.0, *) { + table.sectionHeaderTopPadding = 0.0 + } + return table + }() + + func getFooterView() -> UIView? { // guard let title = getBottomText() else { // return nil // } - let footer = UIView(frame: CGRect(x: 0, y: 0, width: view.frame.size.width, height: 64.0)) - let button = UIButton() - button.translatesAutoresizingMaskIntoConstraints = false - footer.addSubview(button) - button.backgroundColor = .white - button.clipsToBounds = true - button.setTitleColor(UIColor.init(hexString: "0xE6605C"), for: .normal) - button.titleLabel?.font = UIFont.systemFont(ofSize: 16) - button.setTitle(title, for: .normal) - button.addTarget(self, action: #selector(loginOutAction), for: .touchUpInside) - button.layer.cornerRadius = 8.0 - button.setTitle("退出登录", for: .normal) - NSLayoutConstraint.activate([ - button.leftAnchor.constraint(equalTo: footer.leftAnchor, constant: 20), - button.rightAnchor.constraint(equalTo: footer.rightAnchor, constant: -20), - button.topAnchor.constraint(equalTo: footer.topAnchor, constant: 12), - button.heightAnchor.constraint(equalToConstant: 40) - ]) - return footer - } - + let footer = UIView(frame: CGRect(x: 0, y: 0, width: view.frame.size.width, height: 64.0)) + let button = UIButton() + button.translatesAutoresizingMaskIntoConstraints = false + footer.addSubview(button) + button.backgroundColor = .white + button.clipsToBounds = true + button.setTitleColor(UIColor(hexString: "0xE6605C"), for: .normal) + button.titleLabel?.font = UIFont.systemFont(ofSize: 16) + button.setTitle(title, for: .normal) + button.addTarget(self, action: #selector(loginOutAction), for: .touchUpInside) + button.layer.cornerRadius = 8.0 + button.setTitle("退出登录", for: .normal) + NSLayoutConstraint.activate([ + button.leftAnchor.constraint(equalTo: footer.leftAnchor, constant: 20), + button.rightAnchor.constraint(equalTo: footer.rightAnchor, constant: -20), + button.topAnchor.constraint(equalTo: footer.topAnchor, constant: 12), + button.heightAnchor.constraint(equalToConstant: 40), + ]) + return footer + } + //logout action @objc func loginOutAction(){ @@ -104,81 +105,74 @@ class MineSettingViewController: NEBaseViewController { } -} - -extension MineSettingViewController:MineSettingViewModelDelegate { - - func didMessageRemindClick() { - let messageRemindCtrl = MessageRemindViewController() - navigationController?.pushViewController(messageRemindCtrl, animated: true) - } - - func didClickCleanCache() { - - } - - -} - -extension MineSettingViewController: UITableViewDataSource, UITableViewDelegate { + //MARK: UITableViewDataSource, UITableViewDelegate func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - if viewModel.sectionData.count > section { - let model = viewModel.sectionData[section] - return model.cellModels.count - } - return 0 + if viewModel.sectionData.count > section { + let model = viewModel.sectionData[section] + return model.cellModels.count + } + return 0 } func numberOfSections(in tableView: UITableView) -> Int { - return viewModel.sectionData.count + viewModel.sectionData.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let model = viewModel.sectionData[indexPath.section].cellModels[indexPath.row] - if let cell = tableView.dequeueReusableCell(withIdentifier: "\(model.type)", for: indexPath) as? BaseTeamSettingCell { - cell.configure(model) - return cell - } - return UITableViewCell() + let model = viewModel.sectionData[indexPath.section].cellModels[indexPath.row] + if let cell = tableView.dequeueReusableCell( + withIdentifier: "\(model.type)", + for: indexPath + ) as? BaseTeamSettingCell { + cell.configure(model) + return cell + } + return UITableViewCell() } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - - let model = viewModel.sectionData[indexPath.section].cellModels[indexPath.row] - if let block = model.cellClick { - block() - } - + let model = viewModel.sectionData[indexPath.section].cellModels[indexPath.row] + if let block = model.cellClick { + block() + } } func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - let model = viewModel.sectionData[indexPath.section].cellModels[indexPath.row] - return model.rowHeight + let model = viewModel.sectionData[indexPath.section].cellModels[indexPath.row] + return model.rowHeight } func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { - - if viewModel.sectionData.count > section { - let model = viewModel.sectionData[section] - if model.cellModels.count > 0 { - return 12.0 - } + if viewModel.sectionData.count > section { + let model = viewModel.sectionData[section] + if model.cellModels.count > 0 { + return 12.0 } - return 0 + } + return 0 } func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { - let header = UIView() - header.backgroundColor = UIColor.init(hexString: "0xF1F1F6") - return header + let header = UIView() + header.backgroundColor = UIColor(hexString: "0xF1F1F6") + return header } func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { - if section == viewModel.sectionData.count - 1 { - return 12.0 - } - return 0 + if section == viewModel.sectionData.count - 1 { + return 12.0 + } + return 0 } - } + +extension MineSettingViewController: MineSettingViewModelDelegate { + func didMessageRemindClick() { + let messageRemindCtrl = MessageRemindViewController() + navigationController?.pushViewController(messageRemindCtrl, animated: true) + } + + func didClickCleanCache() {} +} + diff --git a/app/Mine/PersonInfoViewController.swift b/app/Mine/PersonInfoViewController.swift index 7ee3f75e..4884eb6e 100644 --- a/app/Mine/PersonInfoViewController.swift +++ b/app/Mine/PersonInfoViewController.swift @@ -1,6 +1,7 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. import UIKit import NEKitCore @@ -8,316 +9,305 @@ import NEKitTeamUI import NEKitChatUI import NIMSDK -class PersonInfoViewController: NEBaseViewController { - - public var cellClassDic = [SettingCellType.SettingSubtitleCell.rawValue: TeamSettingSubtitleCell.self, SettingCellType.SettingHeaderCell.rawValue: TeamSettingHeaderCell.self, - SettingCellType.SettingSubtitleCustomCell.rawValue: TeamSettingRightCustomCell.self] - private var viewModel = PersonInfoViewModel() - private var className = "PersonInfoViewController" +class PersonInfoViewController: NEBaseViewController,NIMUserManagerDelegate,UINavigationControllerDelegate,PersonInfoViewModelDelegate,UITableViewDelegate, UITableViewDataSource { + public var cellClassDic = [ + SettingCellType.SettingSubtitleCell.rawValue: TeamSettingSubtitleCell.self, + SettingCellType.SettingHeaderCell.rawValue: TeamSettingHeaderCell.self, + SettingCellType.SettingSubtitleCustomCell.rawValue: TeamSettingRightCustomCell.self, + ] + private var viewModel = PersonInfoViewModel() + private var className = "PersonInfoViewController" - override func viewDidLoad() { - super.viewDidLoad() - viewModel.getData() - setupSubviews() - initialConfig() + override func viewDidLoad() { + super.viewDidLoad() + viewModel.getData() + setupSubviews() + initialConfig() + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + navigationController?.setNavigationBarHidden(false, animated: false) + } + + func initialConfig() { + title = "个人信息" + view.backgroundColor = UIColor(hexString: "0xF1F1F6") + viewModel.delegate = self + NIMSDK.shared().userManager.add(self) + } + + func setupSubviews() { + view.addSubview(tableView) + NSLayoutConstraint.activate([ + tableView.leftAnchor.constraint(equalTo: view.leftAnchor), + tableView.rightAnchor.constraint(equalTo: view.rightAnchor), + tableView.topAnchor.constraint(equalTo: view.topAnchor), + tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), + ]) + + cellClassDic.forEach { (key: Int, value: BaseTeamSettingCell.Type) in + tableView.register(value, forCellReuseIdentifier: "\(key)") } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - navigationController?.setNavigationBarHidden(false, animated: false) + } + + func showAlert(firstContent: String, secondContent: String, + selectValue: @escaping ((_ value: NSInteger) -> Void)) { + let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) + alert.modalPresentationStyle = .popover + + let first = UIAlertAction(title: firstContent, style: .default) { action in + selectValue(0) } - - func initialConfig(){ - self.title = "个人信息" - view.backgroundColor = UIColor.init(hexString: "0xF1F1F6") - viewModel.delegate = self - NIMSDK.shared().userManager.add(self) + first.setValue(UIColor(hexString: "0x333333"), forKey: "_titleTextColor") + + let second = UIAlertAction(title: secondContent, style: .default) { action in + selectValue(1) } - - func setupSubviews(){ - view.addSubview(tableView) - NSLayoutConstraint.activate([ - tableView.leftAnchor.constraint(equalTo: view.leftAnchor), - tableView.rightAnchor.constraint(equalTo: view.rightAnchor), - tableView.topAnchor.constraint(equalTo: view.topAnchor), - tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor) - ]) - - cellClassDic.forEach { (key: Int, value: BaseTeamSettingCell.Type) in - tableView.register(value, forCellReuseIdentifier: "\(key)") - } + second.setValue(UIColor(hexString: "0x333333"), forKey: "_titleTextColor") + + let cancel = UIAlertAction(title: "取消", style: .cancel) { action in } - - func showAlert(firstContent:String,secondContent:String,selectValue:@escaping ((_ value:NSInteger)->Void)) { - let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) - alert.modalPresentationStyle = .popover - - let first = UIAlertAction.init(title: firstContent, style: .default) { action in - selectValue(0) - } - first.setValue(UIColor.init(hexString: "0x333333"), forKey: "_titleTextColor") + cancel.setValue(UIColor(hexString: "0x333333"), forKey: "_titleTextColor") - let second = UIAlertAction.init(title: secondContent, style: .default) { action in - selectValue(1) - } - second.setValue(UIColor.init(hexString: "0x333333"), forKey: "_titleTextColor") + alert.addAction(first) + alert.addAction(second) + alert.addAction(cancel) - let cancel = UIAlertAction(title: "取消", style: .cancel) { action in - - } - cancel.setValue(UIColor.init(hexString: "0x333333"), forKey: "_titleTextColor") + present(alert, animated: true, completion: nil) + } - alert.addAction(first) - alert.addAction(second) - alert.addAction(cancel) - - self.present(alert, animated: true, completion: nil) - } - - func showDatePicker() { - self.view.addSubview(pickerView) - - weak var weakSelf = self - pickerView.timeCallBack = {time in - if let t = time { - weakSelf?.viewModel.updateBirthday(birthDay: t, { error in - if error != nil { - weakSelf?.showToast("设置生日失败") - } - }) - } + func showDatePicker() { + view.addSubview(pickerView) + weak var weakSelf = self + pickerView.timeCallBack = { time in + if let t = time { + weakSelf?.viewModel.updateBirthday(birthDay: t) { error in + if error != nil { + weakSelf?.showToast("设置生日失败") + } } - NSLayoutConstraint.activate([ - pickerView.leftAnchor.constraint(equalTo: view.leftAnchor), - pickerView.rightAnchor.constraint(equalTo: view.rightAnchor), - pickerView.heightAnchor.constraint(equalToConstant: 229), - pickerView.bottomAnchor.constraint(equalTo: view.bottomAnchor) - ]) - + } } - - lazy var tableView: UITableView = { - let table = UITableView() - table.translatesAutoresizingMaskIntoConstraints = false - table.backgroundColor = UIColor.init(hexString: "0xF1F1F6") - table.dataSource = self - table.delegate = self - table.separatorColor = .clear - table.separatorStyle = .none - table.sectionHeaderHeight = 12.0 - if #available(iOS 15.0, *) { - table.sectionHeaderTopPadding = 0.0 - } - return table - }() - - private lazy var pickerView:BirthdayDatePickerView = { - let picker = BirthdayDatePickerView() - picker.backgroundColor = .white - picker.translatesAutoresizingMaskIntoConstraints = false - return picker - }() - - deinit { - NIMSDK.shared().userManager.remove(self) + NSLayoutConstraint.activate([ + pickerView.leftAnchor.constraint(equalTo: view.leftAnchor), + pickerView.rightAnchor.constraint(equalTo: view.rightAnchor), + pickerView.heightAnchor.constraint(equalToConstant: 229), + pickerView.bottomAnchor.constraint(equalTo: view.bottomAnchor), + ]) + } + + lazy var tableView: UITableView = { + let table = UITableView() + table.translatesAutoresizingMaskIntoConstraints = false + table.backgroundColor = UIColor(hexString: "0xF1F1F6") + table.dataSource = self + table.delegate = self + table.separatorColor = .clear + table.separatorStyle = .none + table.sectionHeaderHeight = 12.0 + if #available(iOS 15.0, *) { + table.sectionHeaderTopPadding = 0.0 } -} + return table + }() + private lazy var pickerView: BirthdayDatePickerView = { + let picker = BirthdayDatePickerView() + picker.backgroundColor = .white + picker.translatesAutoresizingMaskIntoConstraints = false + return picker + }() -extension PersonInfoViewController:NIMUserManagerDelegate { - + deinit { + NIMSDK.shared().userManager.remove(self) + } + //MARK: NIMUserManagerDelegate func onUserInfoChanged(_ user: NIMUser) { - if user.userId == IMKitLoginManager.instance.imAccid { - viewModel.getData() - tableView.reloadData() - } + if user.userId == IMKitLoginManager.instance.imAccid { + viewModel.getData() + tableView.reloadData() + } } -} - - -extension PersonInfoViewController:UINavigationControllerDelegate { + //MARK: UIImagePickerControllerDelegate - func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info:[UIImagePickerController.InfoKey : Any]) { - let image : UIImage = info[UIImagePickerController.InfoKey.editedImage] as! UIImage - uploadHeadImage(image: image) - self.dismiss(animated: true, completion: nil) + + func imagePickerController(_ picker: UIImagePickerController, + didFinishPickingMediaWithInfo info: [UIImagePickerController + .InfoKey: Any]) { + let image: UIImage = info[UIImagePickerController.InfoKey.editedImage] as! UIImage + uploadHeadImage(image: image) + dismiss(animated: true, completion: nil) } - - public func uploadHeadImage(image:UIImage){ - - self.view.makeToastActivity(.center) - weak var weakSelf = self - if let imageData = image.jpegData(compressionQuality: 0.6) as NSData? { - let filePath = NSHomeDirectory().appending("/Documents/").appending(IMKitLoginManager.instance.imAccid) - let succcess = imageData.write(toFile: filePath, atomically: true) - if succcess { - NIMSDK.shared().resourceManager.upload(filePath, scene: NIMNOSSceneTypeAvatar, progress: nil) { urlString, error in - if error == nil { - weakSelf?.viewModel.updateAvatar(avatar: urlString ?? "", { error in - if error != nil { - weakSelf?.showToast("修改头像失败失败") - } - }) - - }else { - NELog.errorLog(weakSelf?.className ?? "", desc: "❌upload image failed,error = \(error!)") - } - self.view.hideToastActivity() + + public func uploadHeadImage(image: UIImage) { + view.makeToastActivity(.center) + weak var weakSelf = self + if let imageData = image.jpegData(compressionQuality: 0.6) as NSData? { + let filePath = NSHomeDirectory().appending("/Documents/") + .appending(IMKitLoginManager.instance.imAccid) + let succcess = imageData.write(toFile: filePath, atomically: true) + if succcess { + NIMSDK.shared().resourceManager + .upload(filePath, scene: NIMNOSSceneTypeAvatar, + progress: nil) { urlString, error in + if error == nil { + weakSelf?.viewModel.updateAvatar(avatar: urlString ?? "") { error in + if error != nil { + weakSelf?.showToast("修改头像失败失败") + } } - + + } else { + NELog.errorLog( + weakSelf?.className ?? "", + desc: "❌upload image failed,error = \(error!)" + ) + } + self.view.hideToastActivity() } } + } } -} - -extension PersonInfoViewController:PersonInfoViewModelDelegate { - - + //MARK: PersonInfoViewModelDelegate func didClickHeadImage() { - showBottomAlert(self) + showBottomAlert(self) } - + func didClickNickName(name: String) { - let ctrl = InputPersonInfoController() - ctrl.configTitle(editType: .nickName) - ctrl.contentText = name - weak var weakSelf = self - ctrl.callBack = {editText in - weakSelf?.viewModel.updateNickName(name: editText, { error in - if error != nil { - weakSelf?.showToast("修改昵称失败") - } - }) + let ctrl = InputPersonInfoController() + ctrl.configTitle(editType: .nickName) + ctrl.contentText = name + weak var weakSelf = self + ctrl.callBack = { editText in + weakSelf?.viewModel.updateNickName(name: editText) { error in + if error != nil { + weakSelf?.showToast("修改昵称失败") + } } - navigationController?.pushViewController(ctrl, animated: true) + } + navigationController?.pushViewController(ctrl, animated: true) } func didClickGender() { - var sex = NIMUserGender.unknown - weak var weakSelf = self - showAlert(firstContent: "男", secondContent: "女") { value in - sex = value == 0 ? .male : .female - weakSelf?.viewModel.updateSex(sex: sex) { error in - if error != nil { - weakSelf?.showToast("修改性别失败") - } - } + var sex = NIMUserGender.unknown + weak var weakSelf = self + showAlert(firstContent: "男", secondContent: "女") { value in + sex = value == 0 ? .male : .female + weakSelf?.viewModel.updateSex(sex: sex) { error in + if error != nil { + weakSelf?.showToast("修改性别失败") + } } + } } - + func didClickBirthday() { - showDatePicker() + showDatePicker() } - + func didClickMobile(mobile: String) { - let ctrl = InputPersonInfoController() - ctrl.configTitle(editType: .cellphone) - ctrl.contentText = mobile - weak var weakSelf = self - ctrl.callBack = {editText in - weakSelf?.viewModel.updateMobile(mobile: editText, { error in - if error != nil { - weakSelf?.showToast("修改手机号失败") - } - }) + let ctrl = InputPersonInfoController() + ctrl.configTitle(editType: .cellphone) + ctrl.contentText = mobile + weak var weakSelf = self + ctrl.callBack = { editText in + weakSelf?.viewModel.updateMobile(mobile: editText) { error in + if error != nil { + weakSelf?.showToast("修改手机号失败") + } } - navigationController?.pushViewController(ctrl, animated: true) + } + navigationController?.pushViewController(ctrl, animated: true) } func didClickEmail(email: String) { - let ctrl = InputPersonInfoController() - ctrl.configTitle(editType: .email) - ctrl.contentText = email - weak var weakSelf = self - ctrl.callBack = {editText in - weakSelf?.viewModel.updateEmail(email: editText, { error in - if error != nil { - weakSelf?.showToast("修改邮箱失败") - } - }) + let ctrl = InputPersonInfoController() + ctrl.configTitle(editType: .email) + ctrl.contentText = email + weak var weakSelf = self + ctrl.callBack = { editText in + weakSelf?.viewModel.updateEmail(email: editText) { error in + if error != nil { + weakSelf?.showToast("修改邮箱失败") + } } - navigationController?.pushViewController(ctrl, animated: true) + } + navigationController?.pushViewController(ctrl, animated: true) } func didClickSign(sign: String) { - let ctrl = InputPersonInfoController() - ctrl.configTitle(editType: .specialSign) - ctrl.contentText = sign - weak var weakSelf = self - ctrl.callBack = {editText in - weakSelf?.viewModel.updateSign(sign: editText, { error in - if error != nil { - weakSelf?.showToast("修改签名失败") - } - }) + let ctrl = InputPersonInfoController() + ctrl.configTitle(editType: .specialSign) + ctrl.contentText = sign + weak var weakSelf = self + ctrl.callBack = { editText in + weakSelf?.viewModel.updateSign(sign: editText) { error in + if error != nil { + weakSelf?.showToast("修改签名失败") + } } - navigationController?.pushViewController(ctrl, animated: true) + } + navigationController?.pushViewController(ctrl, animated: true) } func didCopyAccount(account: String) { - showToast("复制成功") - UIPasteboard.general.string = account + showToast("复制成功") + UIPasteboard.general.string = account } -} - - - -extension PersonInfoViewController:UITableViewDelegate,UITableViewDataSource { - - + //MARK: UITableViewDelegate, UITableViewDataSource func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - if viewModel.sectionData.count > section { - let model = viewModel.sectionData[section] - return model.cellModels.count - } - return 0 + if viewModel.sectionData.count > section { + let model = viewModel.sectionData[section] + return model.cellModels.count + } + return 0 } - + func numberOfSections(in tableView: UITableView) -> Int { - return viewModel.sectionData.count + viewModel.sectionData.count } - - func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let model = viewModel.sectionData[indexPath.section].cellModels[indexPath.row] - if let cell = tableView.dequeueReusableCell(withIdentifier: "\(model.type)", for: indexPath) as? BaseTeamSettingCell { - cell.configure(model) - return cell - } - return UITableViewCell() + let model = viewModel.sectionData[indexPath.section].cellModels[indexPath.row] + if let cell = tableView.dequeueReusableCell( + withIdentifier: "\(model.type)", + for: indexPath + ) as? BaseTeamSettingCell { + cell.configure(model) + return cell + } + return UITableViewCell() } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - - let model = viewModel.sectionData[indexPath.section].cellModels[indexPath.row] - if let block = model.cellClick { - block() - } - + let model = viewModel.sectionData[indexPath.section].cellModels[indexPath.row] + if let block = model.cellClick { + block() + } } - + func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - let model = viewModel.sectionData[indexPath.section].cellModels[indexPath.row] - return model.rowHeight + let model = viewModel.sectionData[indexPath.section].cellModels[indexPath.row] + return model.rowHeight } - - func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { - if viewModel.sectionData.count > section { - let model = viewModel.sectionData[section] - if model.cellModels.count > 0 { - return 12.0 - } + func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { + if viewModel.sectionData.count > section { + let model = viewModel.sectionData[section] + if model.cellModels.count > 0 { + return 12.0 } - return 0 + } + return 0 } - + func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { - let header = UIView() - header.backgroundColor = UIColor.init(hexString: "0xF1F1F6") - return header + let header = UIView() + header.backgroundColor = UIColor(hexString: "0xF1F1F6") + return header } } + From 1140245977c94b92cf48117695b31241ebb05ab2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E5=96=84=E6=A0=8B?= Date: Fri, 26 Aug 2022 14:33:37 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.xcodeproj/project.pbxproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app.xcodeproj/project.pbxproj b/app.xcodeproj/project.pbxproj index 3eb75dac..ec3d51ba 100644 --- a/app.xcodeproj/project.pbxproj +++ b/app.xcodeproj/project.pbxproj @@ -484,7 +484,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 9.0.1; + MARKETING_VERSION = 9.2.7; PRODUCT_BUNDLE_IDENTIFIER = com.netease.yunxin.app.im; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -527,7 +527,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 9.0.1; + MARKETING_VERSION = 9.2.7; PRODUCT_BUNDLE_IDENTIFIER = com.netease.yunxin.app.im; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = inHouseYunxin;