Skip to content

Commit 05ec176

Browse files
ggzgliAbySwifter
authored andcommitted
publish version 3.5.0
1 parent be85658 commit 05ec176

238 files changed

Lines changed: 10363 additions & 9207 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

application/App-UIKit/Live/VideoLiveViewController.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
//
77

88
import UIKit
9-
import TUICore
9+
import AtomicXCore
1010
import TUILiveKit
1111

1212
class VideoLiveViewController: UIViewController {
@@ -122,7 +122,7 @@ extension VideoLiveViewController {
122122
}
123123

124124
@objc private func goLiveClick() {
125-
let liveRoomId = LiveIdentityGenerator.shared.generateId(TUILogin.getUserID() ?? "", type: .live)
125+
let liveRoomId = LiveIdentityGenerator.shared.generateId(LoginStore.shared.state.value.loginUserInfo?.userID ?? "", type: .live)
126126
VideoLiveKit.createInstance().startLive(roomId: liveRoomId)
127127
}
128128
}

application/App-UIKit/Live/VoiceRoomViewController.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import UIKit
99
import TUICore
1010
import TUILiveKit
11+
import AtomicXCore
1112

1213
class VoiceRoomViewController: UIViewController {
1314

@@ -117,7 +118,8 @@ extension VoiceRoomViewController {
117118
}
118119

119120
@objc private func goLiveClick() {
120-
let voiceRoomId = LiveIdentityGenerator.shared.generateId(TUILogin.getUserID() ?? "", type: .voice)
121+
let userId = LoginStore.shared.state.value.loginUserInfo?.userID ?? ""
122+
let voiceRoomId = LiveIdentityGenerator.shared.generateId(userId, type: .voice)
121123
let params = CreateRoomParams()
122124
VoiceRoomKit.createInstance().createRoom(roomId: voiceRoomId, params: params)
123125
}

application/App-UIKit/Login/LoginViewController.swift

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,18 @@ import SnapKit
1010
import TUICore
1111
import RTCRoomEngine
1212
import RTCCommon
13-
import TIMCommon
1413
import TUICallKit_Swift
14+
import AtomicXCore
15+
import Combine
1516

1617
class LoginViewController: UIViewController {
1718
private let userIdKey = "UserIdKey"
1819
private let loading = UIActivityIndicatorView()
1920
private let rootView = LoginView()
2021
private var isTestEnvironment = false
2122
private var nickName: String = ""
23+
private var cancelableSet: Set<AnyCancellable> = []
24+
2225
override func viewDidLayoutSubviews() {
2326
super.viewDidLayoutSubviews()
2427
}
@@ -45,32 +48,33 @@ class LoginViewController: UIViewController {
4548

4649
private func login(userId: String) {
4750
loading.startAnimating()
48-
TUILogin.login(Int32(SDKAPPID),
49-
userID: userId,
50-
userSig: GenerateTestUserSig.genTestUserSig(identifier: userId)) { [weak self] in
51-
guard let self = self else { return }
52-
UserDefaults.standard.set(userId, forKey: self.userIdKey)
53-
V2TIMManager.sharedInstance()?.getUsersInfo([userId], succ: { [weak self] (infos) in
54-
guard let self = self else { return }
55-
if let info = infos?.first {
56-
nickName = info.nickName ?? ""
57-
let avatar = info.faceURL ?? DEFAULT_AVATAR
58-
TUICallKit.createInstance().setSelfInfo(nickname: nickName,avatar: avatar,
59-
succ: {},
60-
fail: { _, _ in })
61-
}
62-
self.loading.stopAnimating()
63-
self.loginSucc()
64-
}, fail: { [weak self] (code, error) in
65-
guard let self = self else { return }
66-
self.loading.stopAnimating()
67-
self.loginSucc()
68-
})
69-
70-
} fail: { [weak self] code, errorDes in
51+
LoginStore.shared.login(sdkAppID: Int32(SDKAPPID), userID: userId, userSig: GenerateTestUserSig.genTestUserSig(identifier: userId)) { [weak self] result in
7152
guard let self = self else { return }
72-
self.loading.stopAnimating()
73-
TUITool.makeToast("Login failed, code: \(code), error: \(errorDes ?? "nil")")
53+
loading.stopAnimating()
54+
switch result {
55+
case .success():
56+
UserDefaults.standard.set(userId, forKey: self.userIdKey)
57+
LoginStore.shared.state.subscribe(StatePublisherSelector(keyPath: \LoginState.loginUserInfo))
58+
.receive(on: RunLoop.main)
59+
.dropFirst()
60+
.sink { [weak self] user in
61+
guard let self = self, let user = user else {
62+
TUITool.makeToast("Login failed, user is null")
63+
if let self = self {
64+
cancelableSet.forEach { $0.cancel() }
65+
cancelableSet.removeAll()
66+
}
67+
return
68+
}
69+
nickName = user.nickname ?? ""
70+
loginSucc()
71+
cancelableSet.forEach { $0.cancel() }
72+
cancelableSet.removeAll()
73+
}
74+
.store(in: &cancelableSet)
75+
case .failure(let err):
76+
TUITool.makeToast("Login failed, code: \(err.code), error: \(err.message)")
77+
}
7478
}
7579
}
7680

application/App-UIKit/Mine/Log/LogUploadManager.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,17 @@ extension LogUploadManager {
101101
fileArray += liteAVSDKXlogFiles
102102
let imXlogFiles = getFilesFromDirectory(atPath: cachePath, withExtension: ".xlog")
103103
fileArray += imXlogFiles
104+
105+
// 按文件修改时间排序(最新的在前)
106+
fileArray.sort { file1, file2 in
107+
let fileManager = FileManager.default
108+
guard let date1 = try? fileManager.attributesOfItem(atPath: file1.filePath)[.modificationDate] as? Date,
109+
let date2 = try? fileManager.attributesOfItem(atPath: file2.filePath)[.modificationDate] as? Date else {
110+
return false
111+
}
112+
return date1 > date2
113+
}
114+
104115
fileModelArray = fileArray
105116
logUploadView.reloadAllComponents()
106117
logUploadView.alpha = 0.1

application/App-UIKit/Mine/MinePage/UI/MineViewController.swift

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import UIKit
1111
import ImSDK_Plus
1212
import RTCCommon
1313
import TUICore
14+
import AtomicXCore
1415

1516
@objc class MineViewController: UIViewController {
1617
private lazy var rootView: MineView = {
@@ -70,16 +71,19 @@ extension MineViewController: MineViewDelegate {
7071
let cancelAction = UIAlertAction(title: ("Cancel").localized, style: .cancel, handler: nil)
7172
let sureAction = UIAlertAction(title: ("Yes").localized, style: .default) { _ in
7273
UserDefaults.standard.removeObject(forKey: "UserIdKey")
73-
TUILogin.logout {
74-
DispatchQueue.main.async {
75-
if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
76-
appDelegate.showLoginViewController()
74+
LoginStore.shared.logout { result in
75+
switch result {
76+
case .success(()):
77+
DispatchQueue.main.async {
78+
if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
79+
appDelegate.showLoginViewController()
80+
}
7781
}
78-
}
79-
} fail: { _, _ in
80-
DispatchQueue.main.async {
81-
if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
82-
appDelegate.showLoginViewController()
82+
case .failure(_):
83+
DispatchQueue.main.async {
84+
if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
85+
appDelegate.showLoginViewController()
86+
}
8387
}
8488
}
8589
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//
2+
// AvatarCardItem.swift
3+
// TIMCommon
4+
//
5+
// Created by AI Assistant on 2025/10/10.
6+
// Copyright © 2025 Tencent. All rights reserved.
7+
//
8+
9+
import UIKit
10+
11+
class AvatarCardItem: NSObject {
12+
var posterUrlStr: String?
13+
var isSelect: Bool = false
14+
var fullUrlStr: String?
15+
var isDefaultBackgroundItem: Bool = false
16+
var isGroupGridAvatar: Bool = false
17+
var createGroupType: String?
18+
var cacheGroupGridAvatarImage: UIImage?
19+
20+
override init() {
21+
super.init()
22+
}
23+
}
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
//
2+
// AvatarCollectionCell.swift
3+
// TIMCommon
4+
//
5+
// Created by AI Assistant on 2025/10/10.
6+
// Copyright © 2025 Tencent. All rights reserved.
7+
//
8+
9+
import UIKit
10+
import SDWebImage
11+
12+
class AvatarCollectionCell: UICollectionViewCell {
13+
14+
// MARK: - Properties
15+
var cardItem: AvatarCardItem? {
16+
didSet {
17+
updateCellView()
18+
}
19+
}
20+
21+
private lazy var imageView = UIImageView(frame: bounds)
22+
private var selectedView: UIImageView!
23+
private lazy var bgView: UIView = UIView(frame: .zero)
24+
private var descLabel: UILabel!
25+
26+
// MARK: - Initialization
27+
override init(frame: CGRect) {
28+
super.init(frame: frame)
29+
setupViews()
30+
}
31+
32+
required init?(coder: NSCoder) {
33+
super.init(coder: coder)
34+
setupViews()
35+
}
36+
37+
// MARK: - Layout
38+
override func layoutSubviews() {
39+
super.layoutSubviews()
40+
updateCellView()
41+
selectedView.frame = CGRect(x: imageView.frame.width - 20, y: 4, width: 16, height: 16)
42+
}
43+
44+
// MARK: - Private Methods
45+
private func setupViews() {
46+
setupImageView()
47+
setupSelectedView()
48+
setupMaskView()
49+
}
50+
51+
private func setupImageView() {
52+
imageView.isUserInteractionEnabled = true
53+
imageView.layer.cornerRadius = 8.0 // TUIConfig.defaultConfig.avatarCornerRadius
54+
imageView.layer.borderWidth = 2
55+
imageView.layer.masksToBounds = true
56+
contentView.addSubview(imageView)
57+
}
58+
59+
private func setupSelectedView() {
60+
selectedView = UIImageView()
61+
selectedView.image = UIImage(named: "icon_avatar_selected") // TIMCommonImagePath
62+
selectedView.isHidden = true
63+
imageView.addSubview(selectedView)
64+
}
65+
66+
private func setupMaskView() {
67+
bgView.backgroundColor = UIColor(hex: "cccccc")
68+
bgView.isHidden = true
69+
imageView.addSubview(bgView)
70+
71+
descLabel = UILabel()
72+
descLabel.text = "默认背景" // TIMCommonLocalizableString
73+
descLabel.textColor = .white
74+
descLabel.font = UIFont.systemFont(ofSize: 13)
75+
descLabel.textAlignment = .center
76+
bgView.addSubview(descLabel)
77+
}
78+
79+
private func updateCellView() {
80+
updateSelectedUI()
81+
updateImageView()
82+
updateMaskView()
83+
}
84+
85+
func updateSelectedUI() {
86+
guard let cardItem = cardItem else { return }
87+
88+
if cardItem.isSelect {
89+
imageView.layer.borderColor = UIColor.systemBlue.cgColor
90+
selectedView.isHidden = false
91+
} else {
92+
if cardItem.isDefaultBackgroundItem {
93+
imageView.layer.borderColor = UIColor.gray.withAlphaComponent(0.1).cgColor
94+
} else {
95+
imageView.layer.borderColor = UIColor.clear.cgColor
96+
}
97+
selectedView.isHidden = true
98+
}
99+
}
100+
101+
private func updateImageView() {
102+
guard let cardItem = cardItem else { return }
103+
104+
if cardItem.isGroupGridAvatar {
105+
updateNormalGroupGridAvatar()
106+
} else {
107+
let placeholder = UIImage(named: "default_c2c_head_img")
108+
if let urlString = cardItem.posterUrlStr, let url = URL(string: urlString) {
109+
imageView.sd_setImage(with: url, placeholderImage: placeholder)
110+
} else {
111+
imageView.image = placeholder
112+
}
113+
}
114+
}
115+
116+
private func updateMaskView() {
117+
guard let cardItem = cardItem else { return }
118+
119+
if cardItem.isDefaultBackgroundItem {
120+
bgView.isHidden = false
121+
bgView.frame = CGRect(x: 0, y: imageView.frame.height - 28,
122+
width: imageView.frame.width, height: 28)
123+
descLabel.sizeToFit()
124+
descLabel.center = CGPoint(x: bgView.bounds.midX, y: bgView.bounds.midY)
125+
} else {
126+
bgView.isHidden = true
127+
}
128+
}
129+
130+
private func updateNormalGroupGridAvatar() {
131+
guard let cardItem = cardItem else { return }
132+
133+
if let cacheImage = cardItem.cacheGroupGridAvatarImage {
134+
imageView.image = cacheImage
135+
}
136+
}
137+
}
138+
139+
// MARK: - UIColor Extension
140+
extension UIColor {
141+
convenience init(hex: String) {
142+
let hex = hex.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
143+
var int: UInt64 = 0
144+
Scanner(string: hex).scanHexInt64(&int)
145+
let a, r, g, b: UInt64
146+
switch hex.count {
147+
case 3: // RGB (12-bit)
148+
(a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17)
149+
case 6: // RGB (24-bit)
150+
(a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF)
151+
case 8: // ARGB (32-bit)
152+
(a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF)
153+
default:
154+
(a, r, g, b) = (1, 1, 1, 0)
155+
}
156+
157+
self.init(
158+
red: Double(r) / 255,
159+
green: Double(g) / 255,
160+
blue: Double(b) / 255,
161+
alpha: Double(a) / 255
162+
)
163+
}
164+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//
2+
// AvatarSelectorType.swift
3+
// TIMCommon
4+
//
5+
// Created by AI Assistant on 2025/10/10.
6+
// Copyright © 2025 Tencent. All rights reserved.
7+
//
8+
9+
import Foundation
10+
11+
/// 头像选择类型枚举
12+
enum AvatarSelectorType: Int {
13+
case userAvatar = 0 // 用户头像
14+
case groupAvatar = 1 // 群组头像
15+
case cover = 2 // 封面
16+
case conversationBackgroundCover = 3 // 会话背景封面
17+
}

0 commit comments

Comments
 (0)