// // HomeViewModel.swift // QuickLocation // // Created by 八条 on 2026/5/30. // import RxSwift import RxDataSources import ObjectMapper typealias GroupMemberListSectionModel = SectionModel class HomeViewModel { struct Output { var sectionedItems: Observable<[GroupMemberListSectionModel]> } let output: Output private var disposeBag = DisposeBag() private let sectionedItems = PublishSubject<[GroupMemberListSectionModel]>() lazy var cellAction: Action = { this in return Action { model in return .empty() } }(self) var targetUid: String = "" var groupModel: GroupModel? // 当前选中的圈子 var groupInfo: [String: Any] { get { guard let model = groupModel, let groupInfoModel = model.groups.first(where: { $0.group_key == model.default_group_key }) else { return [:] } return groupInfoModel.toJSON() } } // 圈子名字 var groupName: String { get { guard let model = groupModel else { return "我的圈子" } return model.groups.first(where: { $0.group_key == model.default_group_key })?.name ?? "" } } // 圈子成员数 var memberCount: Int { memberList.count } // 圈子成员在线数 var memberOnlineCount: Int { memberList.filter(\.is_online).count } // 是否当前用户 func isCurrentUser(id: String) -> Bool { id == AppContextManager.shared.userId } // 是否圈主 func isGroupOwn(id: String) -> Bool { guard let model = groupModel else { return false } return GroupOwnerMatcher.matches(userId: id, groupKey: model.default_group_key) } func getUserNickName(id: String) -> String { memberList.first { $0.user_id == id }?.nick_name ?? "" } private(set) var memberList: [GroupMemberModel] = [] func markMemberInBubble(userId: String) { updateMemberStatus(userId: userId, status: 2) } func isInBubble(userId: String) -> Bool { let ids = canonicalUserIds(userId) if let member = memberList.first(where: { ids.contains($0.user_id) }) { return member.status == 2 } if ids.contains(where: { $0 == "current" || isCurrentUser(id: $0) }) { return AppContextManager.shared.status == 2 } return false } func updateMembers(_ list: [GroupMemberModel]) { memberList = GroupMemberSorter.sorted( list, groupKey: groupModel?.default_group_key ?? "", currentUserId: AppContextManager.shared.userId ) sectionedItems.onNext(memberList.mapSection()) } func clearMembers() { updateMembers([]) } private func canonicalUserIds(_ userId: String) -> Set { var ids: Set = [userId] if userId == "current" || isCurrentUser(id: userId) { ids.insert("current") let mine = AppContextManager.shared.userId if !mine.isEmpty { ids.insert(mine) } } return ids } /// 标记成员离线(保留 last_active_time 用于显示"X分钟前") func setMemberOffline(userId: String) { guard let idx = memberList.firstIndex(where: { $0.user_id == userId }) else { return } var updated = memberList updated[idx].is_online = false updateMembers(updated) } /// MQTT 位置更新后刷新成员的地址、电量、在线状态 func updateMemberLocation(userId: String, lat: Double, lon: Double, address: String, battery: String, isOnline: Bool, lastUpdateTime: Int64) { guard let idx = memberList.firstIndex(where: { $0.user_id == userId }) else { return } var updated = memberList updated[idx].last_position = "\(lat):\(lon):\(address)" updated[idx].battery = battery updated[idx].is_online = isOnline updated[idx].last_active_time = lastUpdateTime updateMembers(updated) } /// 成员是否存在 func memberIsExist(userId: String) -> Bool { (memberList.first(where: { $0.user_id == userId }) != nil) } /// 移除成员 func removeMember(userId: String) { guard let idx = memberList.firstIndex(where: { $0.user_id == userId }) else { return } var updated = memberList updated.remove(at: idx) updateMembers(updated) } func updateMemberStatus(userId: String, status: Int) { guard let index = memberList.firstIndex(where: { $0.user_id == userId }) else { return } memberList[index].status = status sectionedItems.onNext(memberList.mapSection()) } // MARK: - Init init() { output = Output( sectionedItems: sectionedItems.asObservable() ) } }