jsdw_ios/QuickLocation/Section/Home/GroupMemberView2.swift

962 lines
30 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// GroupMemberView2.swift
// QuickLocation
//
// Created by on 2026/8/4.
//
import UIKit
import Network
import CoreLocation
import RxSwift
import RxCocoa
import SwiftyUserDefaults
class GroupMemberView2: UIView {
private var navBarHeightConstraint: NSLayoutConstraint?
private static let batteryNormalColor = UIColor(hexStr: "#47DD00")
private static let batteryLowColor = UIColor(hexStr: "#F85A5D")
private static let batteryDefaultTextColor = UIColor(hexStr: "#353B4F")
/// 24pt
private static let batteryFillMaxWidth: CGFloat = 18
/// kNaviHeight/dismiss 0
func setNavBarExpanded(_ expanded: Bool) {
navBarHeightConstraint?.constant = expanded ? kNaviHeight : 0
}
func setupMemberInfo(_ model: GroupMemberModel, isOwner: Bool) {
memberNameLab.text = model.nick_name
ownView.isHidden = !isOwner
statusDotView.backgroundColor = UIColor(hexStr: model.is_online ? "#67EA76" : "#D8D8D8")
statusLab.text = model.is_online ? "在线" : "离线"
locationLab.text = model.lastLocation
let isCurrentUser = model.user_id == AppContextManager.shared.userId
updateDistance(for: model, isCurrentUser: isCurrentUser)
if isCurrentUser {
setupCurrentUserDeviceInfo()
} else {
setupUnknownDeviceInfo(battery: model.battery)
}
}
private func updateDistance(for model: GroupMemberModel, isCurrentUser: Bool) {
guard !isCurrentUser else {
distanceView.isHidden = true
return
}
guard let lat = Defaults[\.currentLatitude],
let lon = Defaults[\.currentLongitude] else {
distanceView.isHidden = true
return
}
let meCoord = CLLocationCoordinate2D(latitude: lat, longitude: lon)
let (otherCoord, _) = CircleMember.parsePosition(model.last_position)
guard CLLocationCoordinate2DIsValid(meCoord),
CLLocationCoordinate2DIsValid(otherCoord) else {
distanceView.isHidden = true
return
}
let meters = CLLocation(latitude: meCoord.latitude, longitude: meCoord.longitude)
.distance(from: CLLocation(latitude: otherCoord.latitude, longitude: otherCoord.longitude))
distanceLab.text = Self.formatDistance(meters)
distanceView.isHidden = false
}
private static func formatDistance(_ meters: CLLocationDistance) -> String {
if meters < 1000 {
return "\(Int(meters.rounded()))M"
}
return String(format: "%.1fKM", meters / 1000.0)
}
private func setupCurrentUserDeviceInfo() {
phoneModelIcon.image = UIImage(named: "Home/member_phone")
phoneModelLab.text = Self.localPhoneModelName()
phoneModelLab.textColor = Self.batteryDefaultTextColor
networkIcon.image = UIImage(named: "Home/member_wifi")
networkLab.text = Self.localNetworkStatusText()
networkLab.textColor = Self.batteryDefaultTextColor
applyBatteryDisplay(percent: Self.localBatteryPercent())
}
private func setupUnknownDeviceInfo(battery: String) {
phoneModelIcon.image = UIImage(named: "Home/member_phone_unknown")
phoneModelLab.text = "***"
phoneModelLab.textColor = Self.batteryDefaultTextColor
networkIcon.image = UIImage(named: "Home/member_network_unknown")
networkLab.text = "***"
networkLab.textColor = Self.batteryDefaultTextColor
// MQTT / unknown
let percent = Int(battery.int)
if percent > 0 {
applyBatteryDisplay(percent: min(percent, 100))
} else {
applyBatteryUnknown()
}
}
private func applyBatteryUnknown() {
batteryIcon.image = UIImage(named: "Home/member_battery_unknown")
batteryFillView.isHidden = true
batteryFillView.layoutChain.width(0)
batteryLab.text = "***"
batteryLab.textColor = Self.batteryDefaultTextColor
}
private func applyBatteryDisplay(percent: Int?) {
guard let percent else {
applyBatteryUnknown()
return
}
let p = min(max(percent, 0), 100)
let isLow = p < 20
let color = isLow ? Self.batteryLowColor : Self.batteryNormalColor
batteryIcon.image = UIImage(named: isLow ? "Home/member_battery_low" : "Home/member_battery")
batteryFillView.isHidden = false
batteryFillView.backgroundColor = color
batteryFillView.layoutChain.width(Self.batteryFillMaxWidth * CGFloat(p) / 100.0)
batteryLab.text = "\(p)%"
batteryLab.textColor = color
}
// MARK: - Local device helpers
private static func localPhoneModelName() -> String {
var systemInfo = utsname()
uname(&systemInfo)
let identifier = withUnsafePointer(to: &systemInfo.machine.0) { ptr in
String(cString: ptr)
}
return deviceModelMap[identifier] ?? "iPhone"
}
private static func localBatteryPercent() -> Int? {
UIDevice.current.isBatteryMonitoringEnabled = true
let level = UIDevice.current.batteryLevel
guard level >= 0 else { return nil }
return Int((level * 100).rounded())
}
private static func localNetworkStatusText() -> String {
let path = NetworkStatusMonitor.shared.currentPath
if path.status != .satisfied {
return "无网络"
}
if path.usesInterfaceType(.wifi) {
return "Wi-Fi"
}
if path.usesInterfaceType(.cellular) {
return "蜂窝"
}
return "无网络"
}
private static let deviceModelMap: [String: String] = [
"iPhone10,1": "iPhone 8",
"iPhone10,4": "iPhone 8",
"iPhone10,2": "iPhone 8 Plus",
"iPhone10,5": "iPhone 8 Plus",
// iPhone X
"iPhone10,3": "iPhone X",
"iPhone10,6": "iPhone X",
"iPhone11,2": "iPhone XS",
"iPhone11,4": "iPhone XS Max",
"iPhone11,6": "iPhone XS Max",
"iPhone11,8": "iPhone XR",
// iPhone11
"iPhone12,1": "iPhone 11",
"iPhone12,3": "iPhone 11 Pro",
"iPhone12,5": "iPhone 11 Pro Max",
// iPhone12
"iPhone13,1": "iPhone 12 mini",
"iPhone13,2": "iPhone 12",
"iPhone13,3": "iPhone 12 Pro",
"iPhone13,4": "iPhone 12 Pro Max",
// iPhone13
"iPhone14,4": "iPhone 13 mini",
"iPhone14,5": "iPhone 13",
"iPhone14,2": "iPhone 13 Pro",
"iPhone14,3": "iPhone 13 Pro Max",
// iPhone14
"iPhone14,7": "iPhone 14",
"iPhone14,8": "iPhone 14 Plus",
"iPhone15,2": "iPhone 14 Pro",
"iPhone15,3": "iPhone 14 Pro Max",
// iPhone15
"iPhone15,4": "iPhone 15",
"iPhone15,5": "iPhone 15 Plus",
"iPhone16,1": "iPhone 15 Pro",
"iPhone16,2": "iPhone 15 Pro Max",
// iPhone16
"iPhone17,1": "iPhone 16 Pro",
"iPhone17,2": "iPhone 16 Pro Max",
"iPhone17,3": "iPhone 16",
"iPhone17,4": "iPhone 16 Plus",
"iPhone17,5": "iPhone 16e",
// iPhone17 2025
"iPhone18,1": "iPhone 17 Pro",
"iPhone18,2": "iPhone 17 Pro Max",
"iPhone18,3": "iPhone 17",
"iPhone18,4": "iPhone Air",
// Simulator
"i386": "Simulator",
"x86_64": "Simulator",
"arm64": "Simulator"
]
private func setupRx() {
}
private func setupUI() {
addSubview(headerBgView)
addSubview(navBarView)
addSubview(scrollView)
headerBgView.layoutChain
.edges(excludingEdge: .bottom)
.heightToWidth(160/375)
navBarView.layoutChain
.edges(excludingEdge: .bottom)
.height(0)
navBarHeightConstraint = navBarView.jh_constraint(
.height, toAttribute: .notAnAttribute, otherView: nil, relation: .equal
)
scrollView.layoutChain
.topToBottomOfView(navBarView)
.edges(excludingEdge: .top)
scrollView.isScrollEnabled = false
let lineView = UIView()
lineView.backgroundColor = .black.withAlphaComponent(0.2)
lineView.cornerRadius = 2
addSubview(lineView)
lineView.layoutChain
.top(9)
.centerX()
.width(40)
.height(4)
}
lazy var headerBgView: UIImageView = {
let view = UIImageView()
view.image = UIImage(named: "Home/group_member_bg2")
view.backgroundColor = .clear
view.contentMode = .scaleAspectFill
return view
}()
lazy var navBarView: UIView = {
let view = UIView()
view.backgroundColor = .clear
view.clipsToBounds = true
let icon = UIImageView(image: UIImage(named: "Home/member_logo"))
view.addSubview(icon)
icon.layoutChain
.top(kStatusBarHeight + 12)
.left(30)
view.addSubview(inviteBtn)
inviteBtn.layoutChain
.centerY(icon)
.right(15)
.width(32)
.heightToWidth(1)
return view
}()
lazy var inviteBtn: UIButton = {
let btn = UIButton(type: .custom)
btn.setImage(UIImage(named: "Home/member_invite"), for: .normal)
btn.extendEdgeInsets = UIEdgeInsets(top: 20, left: 20, bottom: 10, right: 15)
return btn
}()
lazy var scrollView: UIScrollView = {
let view = UIScrollView()
view.backgroundColor = .clear
view.showsHorizontalScrollIndicator = false
view.bounces = false
view.addSubview(scrollContentView)
scrollContentView.layoutChain.edges().widthToView(view)
scrollContentView.addSubview(memberView)
memberView.layoutChain
.edges(excludingEdge: .bottom)
scrollContentView.addSubview(todayTrackView)
todayTrackView.layoutChain
.topToBottomOfView(memberView, offset: 16)
.edges(excludingEdge: .top)
return view
}()
lazy var scrollContentView: UIView = {
let view = UIView()
view.backgroundColor = .clear
return view
}()
// MARK: -
lazy var memberView: UIView = {
let view = UIView()
view.backgroundColor = .clear
let icon = UIImageView()
icon.image = UIImage(named: "Home/group_name_icon")
view.addSubview(icon)
icon.layoutChain
.top(23)
.left(15)
.width(18)
.heightToWidth(1)
view.addSubview(groupNameLab)
groupNameLab.layoutChain
.leftToRightOfView(icon, offset: 6)
.centerY(icon)
view.addSubview(changeGroupBtn)
changeGroupBtn.layoutChain
.centerY(icon)
.right(15)
.height(20)
let memberView = UIView()
memberView.backgroundColor = .white
memberView.cornerRadius = 20
memberView.addSubview(memberCV)
view.addSubview(memberView)
memberView.layoutChain
.topToBottomOfView(icon, offset: 12)
.edgesHorzontal(15)
.height(100)
memberCV.layoutChain
.edges(all: 5, excludingEdge: .bottom)
.bottom()
view.addSubview(memberInfoView)
memberInfoView.layoutChain
.topToBottomOfView(memberView, offset: 12)
.edgesHorzontal(15)
.height(150)
.bottom()
return view
}()
lazy var groupNameLab: UILabel = {
let label = UILabel()
label.text = " "
label.font = .systemFont(ofSize: 16, weight: .bold)
label.textColor = UIColor(hexStr: "#353B4F")
return label
}()
lazy var changeGroupBtn: UIButton = {
let btn = UIButton(type: .custom)
btn.setTitle("切换圈子 ", for: .normal)
btn.setTitleColor(UIColor(hexStr: "#353B4F"), for: .normal)
btn.titleLabel?.font = .systemFont(ofSize: 12, weight: .medium)
btn.setImage(UIImage(named: "Common/arrow_right"), for: .normal)
btn.semanticContentAttribute = .forceRightToLeft
btn.extendEdgeInsets = UIEdgeInsets(top: 20, left: 20, bottom: 10, right: 15)
return btn
}()
///
lazy var memberCV: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.itemSize = CGSize(width: 61, height: 95)
layout.minimumLineSpacing = 15
layout.sectionInset = UIEdgeInsets(top: 0, left: 8, bottom: 0, right: 8)
layout.scrollDirection = .horizontal
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
cv.backgroundColor = .clear
cv.showsHorizontalScrollIndicator = false
cv.register(GroupMemberListCell.self)
return cv
}()
///
lazy var memberInfoView: UIView = {
let view = UIView()
view.backgroundColor = .white
view.cornerRadius = 20
view.addSubview(memberNameLab)
memberNameLab.layoutChain
.top(20)
.left(18)
view.addSubview(tagView)
tagView.layoutChain
.leftToRightOfView(memberNameLab, offset: 6)
.centerY(memberNameLab)
.height(20)
ownView.layoutChain.height(16)
let statusView = UIView()
statusView.backgroundColor = .clear
statusView.addSubview(statusDotView)
statusView.addSubview(statusLab)
view.addSubview(statusView)
statusView.layoutChain
.right(18)
.centerY(memberNameLab)
statusDotView.layoutChain
.left()
.width(8)
.heightToWidth(1)
.centerY()
statusLab.layoutChain
.leftToRightOfView(statusDotView, offset: 4)
.edgesVertical()
.right()
let locationIcon = UIImageView()
locationIcon.image = UIImage(named: "Home/member_location")
view.addSubview(locationIcon)
locationIcon.layoutChain
.topToBottomOfView(memberNameLab, offset: 17)
.left(20)
.width(16)
.heightToWidth(1)
view.addSubview(locationLab)
locationLab.layoutChain
.centerY(locationIcon)
.leftToRightOfView(locationIcon, offset: 7)
.compressionHorizontal(.defaultLow)
view.addSubview(distanceView)
distanceView.layoutChain
.right(18)
.centerY(locationLab)
.compressionHorizontal(.required)
locationLab.layoutChain.rightToLeftOfView(distanceView, offset: -30, relation: .lessThanOrEqual)
view.addSubview(phoneModelView)
view.addSubview(batteryView)
view.addSubview(networkView)
view.addSubview(weatherView)
phoneModelView.layoutChain
.topToBottomOfView(locationLab, offset: 20)
.left()
batteryView.layoutChain
.topToView(phoneModelView)
.leftToRightOfView(phoneModelView)
.widthToView(phoneModelView)
networkView.layoutChain
.topToView(phoneModelView)
.leftToRightOfView(batteryView)
.widthToView(phoneModelView)
weatherView.layoutChain
.topToView(phoneModelView)
.leftToRightOfView(networkView)
.right()
.widthToView(phoneModelView)
return view
}()
lazy var memberNameLab: UILabel = {
let label = UILabel()
label.text = " "
label.font = FontManager.youSheBiaoTiHei(12)
label.textColor = UIColor(hexStr: "#353B4F")
return label
}()
lazy var tagView: UIStackView = {
let view = UIStackView(arrangedSubviews: [ownView])
view.axis = .horizontal
view.alignment = .center
view.spacing = 5
view.backgroundColor = .clear
return view
}()
//
lazy var ownView: UIView = {
let view = UIView()
view.backgroundColor = UIColor(hexStr: "#E3F6FF")
view.cornerRadius = 6
view.isHidden = true
let label = UILabel()
label.textColor = UIColor(hexStr: "#128CC6")
label.font = .systemFont(ofSize: 10, weight: .bold)
label.text = "圈主"
view.addSubview(label)
label.layoutChain
.edgesVertical(2)
.edgesHorzontal(8)
return view
}()
/// 线
lazy var statusDotView: UIView = {
let view = UIView()
view.backgroundColor = UIColor(hexStr: "#D8D8D8")
view.cornerRadius = 4
return view
}()
lazy var statusLab: UILabel = {
let label = UILabel()
label.text = " "
label.font = .systemFont(ofSize: 10, weight: .medium)
label.textColor = UIColor(hexStr: "#353B4F")
return label
}()
//
lazy var locationLab: UILabel = {
let label = UILabel()
label.textColor = UIColor(hexStr: "#767676")
label.font = .systemFont(ofSize: 12, weight: .medium)
return label
}()
//
lazy var distanceView: UIView = {
let view = UIView()
view.backgroundColor = UIColor(hexStr: "#353B4F")
view.cornerRadius = 6
view.isHidden = true
let label = UILabel()
label.textColor = UIColor(hexStr: "#58EDFF")
label.font = FontManager.youSheBiaoTiHei(10)
label.text = "距离"
view.addSubview(label)
label.layoutChain
.left(5)
.edgesVertical(3)
view.addSubview(distanceLab)
distanceLab.layoutChain
.leftToRightOfView(label, offset: 2)
.right(5)
.centerY()
return view
}()
lazy var distanceLab: UILabel = {
let label = UILabel()
label.textColor = .white
label.font = FontManager.youSheBiaoTiHei(10)
return label
}()
///
lazy var phoneModelView: UIView = {
let view = UIView()
view.backgroundColor = .clear
view.addSubview(phoneModelIcon)
phoneModelIcon.layoutChain
.top()
.centerX()
.width(24)
.height(24)
view.addSubview(phoneModelLab)
phoneModelLab.layoutChain
.topToBottomOfView(phoneModelIcon, offset: 5)
.edgesHorzontal(5)
.bottom()
return view
}()
lazy var phoneModelIcon: UIImageView = {
let view = UIImageView(image: UIImage(named: "Home/member_phone_unknown"))
view.contentMode = .scaleAspectFit
return view
}()
lazy var phoneModelLab: UILabel = {
let label = UILabel()
label.text = "***"
label.textColor = UIColor(hexStr: "#353B4F")
label.font = .systemFont(ofSize: 12, weight: .medium)
label.textAlignment = .center
label.numberOfLines = 0
return label
}()
///
lazy var batteryView: UIView = {
let view = UIView()
view.backgroundColor = .clear
view.addSubview(batteryFillView)
view.addSubview(batteryIcon)
batteryIcon.layoutChain
.top()
.centerX()
.width(24)
.height(24)
//
batteryFillView.layoutChain
.centerY(batteryIcon)
.leftToView(batteryIcon, offset: 2)
.height(12)
.width(0)
view.addSubview(batteryLab)
batteryLab.layoutChain
.topToBottomOfView(batteryIcon, offset: 5)
.centerX()
.bottom()
return view
}()
lazy var batteryFillView: UIView = {
let view = UIView()
view.backgroundColor = Self.batteryNormalColor
view.isHidden = true
return view
}()
lazy var batteryIcon: UIImageView = {
let view = UIImageView(image: UIImage(named: "Home/member_battery_unknown"))
view.contentMode = .scaleAspectFit
return view
}()
lazy var batteryLab: UILabel = {
let label = UILabel()
label.text = "***"
label.textColor = UIColor(hexStr: "#353B4F")
label.font = .systemFont(ofSize: 12, weight: .medium)
return label
}()
///
lazy var networkView: UIView = {
let view = UIView()
view.backgroundColor = .clear
view.addSubview(networkIcon)
networkIcon.layoutChain
.top()
.centerX()
.width(24)
.height(24)
view.addSubview(networkLab)
networkLab.layoutChain
.topToBottomOfView(networkIcon, offset: 5)
.centerX()
.bottom()
return view
}()
lazy var networkIcon: UIImageView = {
let view = UIImageView(image: UIImage(named: "Home/member_network_unknown"))
view.contentMode = .scaleAspectFit
return view
}()
lazy var networkLab: UILabel = {
let label = UILabel()
label.text = "***"
label.textColor = UIColor(hexStr: "#353B4F")
label.font = .systemFont(ofSize: 12, weight: .medium)
return label
}()
///
lazy var weatherView: UIView = {
let view = UIView()
view.backgroundColor = .clear
let icon = UIImageView(image: UIImage(named: "Home/member_weather_unknown"))
view.addSubview(icon)
icon.layoutChain
.top()
.centerX()
.width(24)
.height(24)
view.addSubview(weatherLab)
weatherLab.layoutChain
.topToBottomOfView(icon, offset: 5)
.centerX()
.bottom()
return view
}()
lazy var weatherLab: UILabel = {
let label = UILabel()
label.text = "***"
label.textColor = UIColor(hexStr: "#353B4F")
label.font = .systemFont(ofSize: 12, weight: .medium)
return label
}()
// MARK: -
lazy var todayTrackView: UIView = {
let view = UIView()
view.backgroundColor = .clear
let icon = UIImageView()
icon.image = UIImage(named: "Home/member_today_track")
view.addSubview(icon)
icon.layoutChain
.top()
.left(15)
.width(18)
.heightToWidth(1)
let titleLab = UILabel()
titleLab.text = "今日轨迹"
titleLab.textColor = UIColor(hexStr: "#293445")
titleLab.font = .systemFont(ofSize: 16, weight: .bold)
view.addSubview(titleLab)
titleLab.layoutChain
.leftToRightOfView(icon, offset: 6)
.centerY(icon)
let infoView = UIView()
infoView.backgroundColor = .white
infoView.cornerRadius = 16
view.addSubview(infoView)
infoView.layoutChain
.topToBottomOfView(icon, offset: 12)
.edgesHorzontal(15)
.bottom()
let mapIcon = UIImageView(image: UIImage(named: "Home/member_map"))
infoView.addSubview(mapIcon)
mapIcon.layoutChain
.left(12)
.edgesVertical(15)
.width(80)
.heightToWidth(1)
let locationIcon = UIImageView(image: UIImage(named: "Home/member_location"))
infoView.addSubview(locationIcon)
locationIcon.layoutChain
.topToView(mapIcon, offset: 11)
.leftToRightOfView(mapIcon, offset: 14)
.width(16)
.heightToWidth(1)
let stayTxtLab = UILabel()
stayTxtLab.text = "今天停留了"
stayTxtLab.textColor = UIColor(hexStr: "#293445")
stayTxtLab.font = .systemFont(ofSize: 16, weight: .medium)
view.addSubview(stayTxtLab)
stayTxtLab.layoutChain
.leftToRightOfView(locationIcon, offset: 6)
.centerY(locationIcon)
let stayNumView = UIView()
stayNumView.backgroundColor = UIColor(hexStr: "#293445")
stayNumView.cornerRadius = 6
infoView.addSubview(stayNumView)
stayNumView.layoutChain
.leftToRightOfView(stayTxtLab)
.centerY(stayTxtLab)
stayNumView.addSubview(stayNumLab)
stayNumLab.layoutChain
.edgesHorzontal(5)
.edgesVertical()
let stayTxtLab1 = UILabel()
stayTxtLab1.text = "个地方"
stayTxtLab1.textColor = UIColor(hexStr: "#293445")
stayTxtLab1.font = .systemFont(ofSize: 16, weight: .medium)
view.addSubview(stayTxtLab1)
stayTxtLab1.layoutChain
.leftToRightOfView(stayNumView, offset: 0)
.centerY(stayTxtLab)
view.addSubview(stayLocationView)
stayLocationView.layoutChain
.topToBottomOfView(locationIcon, offset: 12)
.leftToRightOfView(mapIcon, offset: 14)
.right()
.bottomToView(mapIcon)
view.addSubview(stayNodataView)
stayNodataView.layoutChain
.topToBottomOfView(stayTxtLab, offset: 14)
.leftToView(stayTxtLab)
return view
}()
lazy var stayNumLab: UILabel = {
let label = UILabel()
label.text = "0"
label.textColor = UIColor(hexStr: "#58EDFF")
label.font = FontManager.youSheBiaoTiHei(14)
return label
}()
lazy var stayLocationView: UIView = {
let view = UIView()
view.backgroundColor = .clear
view.isHidden = true
let nowDotView = UIView()
nowDotView.backgroundColor = UIColor(hexStr: "#3DC0FF")
nowDotView.cornerRadius = 6
view.addSubview(nowDotView)
nowDotView.layoutChain
.top()
.left()
.width(12)
.heightToWidth(1)
let dotView = UIView()
dotView.backgroundColor = .white
dotView.cornerRadius = 3
nowDotView.addSubview(dotView)
dotView.layoutChain
.centerX()
.centerY()
.width(6)
.heightToWidth(1)
let dashLine = DashLineView()
dashLine.backgroundColor = .clear
view.addSubview(dashLine)
dashLine.layoutChain
.topToBottomOfView(nowDotView)
.centerX(nowDotView)
.width(1)
.bottom()
view.addSubview(stayLocationLab)
stayLocationLab.layoutChain
.leftToRightOfView(nowDotView, offset: 3)
.centerY(nowDotView)
.right(15)
let stayStatusView = UIView()
stayStatusView.backgroundColor = UIColor(hexStr: "#F2F2F2")
stayStatusView.cornerRadius = 6
view.addSubview(stayStatusView)
stayStatusView.layoutChain
.topToBottomOfView(stayLocationLab, offset: 9)
.leftToView(stayLocationLab)
let clockIcon = UIImageView(image: UIImage(named: "Home/member_clock"))
stayStatusView.addSubview(clockIcon)
clockIcon.layoutChain
.edges(all: 4, excludingEdge: .right)
.width(12)
.heightToWidth(1)
stayStatusView.addSubview(stayStatusLab)
stayStatusLab.layoutChain
.leftToRightOfView(clockIcon, offset: 2)
.right(7)
.centerY()
return view
}()
lazy var stayLocationLab: UILabel = {
let label = UILabel()
label.text = "当前 xxx 附近"
label.textColor = UIColor(hexStr: "#293445")
label.font = .systemFont(ofSize: 10, weight: .bold)
return label
}()
lazy var stayStatusLab: UILabel = {
let label = UILabel()
label.text = "停留中..." //
label.textColor = UIColor(hexStr: "#293445")
label.font = .systemFont(ofSize: 8, weight: .bold)
return label
}()
lazy var stayNodataView: UIView = {
let view = UIView()
view.backgroundColor = UIColor(hexStr: "#F2F2F2")
view.cornerRadius = 6
view.isHidden = false
let label = UILabel()
label.text = "暂时没有停留记录"
label.textColor = UIColor(hexStr: "#293445")
label.font = .systemFont(ofSize: 12, weight: .medium)
view.addSubview(label)
label.layoutChain
.edgesHorzontal(6)
.edgesVertical(9)
return view
}()
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = UIColor(hexStr: "#FAFAFA")
cornerRadius = 30
layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
_ = NetworkStatusMonitor.shared
setupUI()
setupRx()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
///
private final class NetworkStatusMonitor {
static let shared = NetworkStatusMonitor()
private let monitor = NWPathMonitor()
private(set) var currentPath: NWPath
private init() {
currentPath = monitor.currentPath
monitor.pathUpdateHandler = { [weak self] path in
self?.currentPath = path
}
monitor.start(queue: DispatchQueue(label: "com.quicklocation.networkstatus"))
}
}