664 lines
22 KiB
Swift
664 lines
22 KiB
Swift
//
|
|
// PrivacySettingsViewController.swift
|
|
// QuickLocation
|
|
//
|
|
|
|
import UIKit
|
|
import RxSwift
|
|
import Kingfisher
|
|
|
|
enum PrivacySettingItem: CaseIterable {
|
|
case phoneReport
|
|
case groupLock
|
|
case pigeonMessage
|
|
|
|
var title: String {
|
|
switch self {
|
|
case .phoneReport:
|
|
return "手机报告"
|
|
case .groupLock:
|
|
return "一键锁机"
|
|
case .pigeonMessage:
|
|
return "飞鸽传书"
|
|
}
|
|
}
|
|
|
|
var imageName: String {
|
|
switch self {
|
|
case .phoneReport:
|
|
return "PrivacySettings/phone_report"
|
|
case .groupLock:
|
|
return "PrivacySettings/group_lock"
|
|
case .pigeonMessage:
|
|
return "PrivacySettings/pigeon_message"
|
|
}
|
|
}
|
|
|
|
var apiKey: String {
|
|
switch self {
|
|
case .phoneReport:
|
|
return "phone_report"
|
|
case .groupLock:
|
|
return "app_lock"
|
|
case .pigeonMessage:
|
|
return "pigeon_mail"
|
|
}
|
|
}
|
|
}
|
|
|
|
final class PrivacySettingsViewController: BaseViewController {
|
|
|
|
private var rootView: PrivacySettingsView!
|
|
private var groups: [GroupInfoModel] = []
|
|
private var isSubmitting = false
|
|
|
|
override func loadView() {
|
|
rootView = PrivacySettingsView(frame: UIScreen.main.bounds)
|
|
view = rootView
|
|
}
|
|
|
|
override func viewDidLoad() {
|
|
super.viewDidLoad()
|
|
bind()
|
|
requestGroups()
|
|
}
|
|
|
|
private func bind() {
|
|
rootView.onGroupChanged = { [weak self] in
|
|
guard let self else { return }
|
|
self.loadPrivilege(for: self.rootView.selectedGroupKey)
|
|
}
|
|
rootView.onToggle = { [weak self] item, isOn in
|
|
self?.changePrivilege(item: item, isOn: isOn)
|
|
}
|
|
}
|
|
|
|
private func requestGroups() {
|
|
rootView.setSettingsEnabled(false)
|
|
GroupService.groupInfo()
|
|
.subscribe(onNext: { [weak self] response in
|
|
guard let self else { return }
|
|
guard let model = response.model else {
|
|
self.groups = []
|
|
self.rootView.configure(groups: [], selectedGroupKey: "")
|
|
DLToast.showError(text: response.message ?? "获取圈子信息失败")
|
|
return
|
|
}
|
|
self.groups = model.groups
|
|
self.rootView.configure(
|
|
groups: model.groups,
|
|
selectedGroupKey: model.default_group_key
|
|
)
|
|
self.loadPrivilege(for: self.rootView.selectedGroupKey)
|
|
}, onError: { [weak self] error in
|
|
self?.groups = []
|
|
self?.rootView.configure(groups: [], selectedGroupKey: "")
|
|
DLToast.showError(text: error.localizedDescription)
|
|
})
|
|
.disposed(by: disposeBag)
|
|
}
|
|
|
|
private func applySelectedPrivilege() {
|
|
let privilege = groups.first(where: { $0.group_key == rootView.selectedGroupKey })?.privilege
|
|
?? GroupPrivilege()
|
|
rootView.apply(privilege)
|
|
}
|
|
|
|
private func loadPrivilege(for groupKey: String) {
|
|
guard !groupKey.isEmpty else {
|
|
applySelectedPrivilege()
|
|
return
|
|
}
|
|
rootView.setSettingsEnabled(false)
|
|
GroupService.groupUsers(groupKey: groupKey)
|
|
.subscribe(onNext: { [weak self] response in
|
|
guard let self else { return }
|
|
self.rootView.setSettingsEnabled(!self.groups.isEmpty)
|
|
guard response.isValid(for: groupKey),
|
|
self.rootView.selectedGroupKey == groupKey else {
|
|
self.applySelectedPrivilege()
|
|
return
|
|
}
|
|
let mine = response.list.first { $0.user_id == AppContextManager.shared.userId }
|
|
if let index = self.groups.firstIndex(where: { $0.group_key == groupKey }) {
|
|
self.groups[index].privilege = mine?.extra.privilege ?? GroupPrivilege()
|
|
}
|
|
self.applySelectedPrivilege()
|
|
}, onError: { [weak self] error in
|
|
self?.rootView.setSettingsEnabled(!(self?.groups.isEmpty ?? true))
|
|
self?.applySelectedPrivilege()
|
|
DLToast.showError(text: error.localizedDescription)
|
|
})
|
|
.disposed(by: disposeBag)
|
|
}
|
|
|
|
private func changePrivilege(item: PrivacySettingItem, isOn: Bool) {
|
|
let groupKey = rootView.selectedGroupKey
|
|
guard !groupKey.isEmpty,
|
|
let index = groups.firstIndex(where: { $0.group_key == groupKey }) else {
|
|
applySelectedPrivilege()
|
|
return
|
|
}
|
|
guard !isSubmitting else {
|
|
applySelectedPrivilege()
|
|
return
|
|
}
|
|
|
|
if item == .groupLock, !isOn {
|
|
interceptTurnOffAppLock { [weak self] blocked in
|
|
guard let self else { return }
|
|
if blocked {
|
|
self.applySelectedPrivilege()
|
|
return
|
|
}
|
|
self.submitPrivilege(item: item, isOn: isOn, groupKey: groupKey, index: index)
|
|
}
|
|
return
|
|
}
|
|
|
|
submitPrivilege(item: item, isOn: isOn, groupKey: groupKey, index: index)
|
|
}
|
|
|
|
private func interceptTurnOffAppLock(completion: @escaping (Bool) -> Void) {
|
|
if let record = lockRecordForPopup(from: PhoneLockSession.currentLocks) {
|
|
LockedAppPopView.show(record)
|
|
completion(true)
|
|
return
|
|
}
|
|
|
|
let userId = AppContextManager.shared.userId.trimmed
|
|
let revision = AppUnlockCoordinator.shared.currentLockStateRevision()
|
|
isSubmitting = true
|
|
rootView.setSettingsEnabled(false)
|
|
UserService.phoneLocked(os: "ios")
|
|
.observe(on: MainScheduler.instance)
|
|
.subscribe(onNext: { [weak self] response in
|
|
guard let self else { return }
|
|
self.isSubmitting = false
|
|
self.rootView.setSettingsEnabled(!self.groups.isEmpty)
|
|
let locks = AppUnlockCoordinator.shared.locksForRestoration(
|
|
response.model?.locks ?? [],
|
|
startedAt: revision,
|
|
userId: userId
|
|
) ?? []
|
|
if !locks.isEmpty {
|
|
PhoneLockSession.currentLocks = locks
|
|
}
|
|
if let record = self.lockRecordForPopup(from: locks) {
|
|
LockedAppPopView.show(record)
|
|
completion(true)
|
|
} else {
|
|
completion(false)
|
|
}
|
|
}, onError: { [weak self] _ in
|
|
guard let self else { return }
|
|
self.isSubmitting = false
|
|
self.rootView.setSettingsEnabled(!self.groups.isEmpty)
|
|
completion(false)
|
|
})
|
|
.disposed(by: disposeBag)
|
|
}
|
|
|
|
private func lockRecordForPopup(from locks: [PhoneLockRecord]) -> PhoneLockRecord? {
|
|
let groupKey = rootView.selectedGroupKey
|
|
return locks.first { $0.groupKey == groupKey } ?? locks.first
|
|
}
|
|
|
|
private func submitPrivilege(item: PrivacySettingItem, isOn: Bool, groupKey: String, index: Int) {
|
|
let previous = groups[index].privilege
|
|
var updated = previous
|
|
switch item {
|
|
case .phoneReport:
|
|
updated.phone_report = isOn
|
|
case .groupLock:
|
|
updated.app_lock = isOn
|
|
case .pigeonMessage:
|
|
updated.pigeon_mail = isOn
|
|
}
|
|
groups[index].privilege = updated
|
|
rootView.apply(updated)
|
|
|
|
isSubmitting = true
|
|
rootView.setSettingsEnabled(false)
|
|
GroupService.operate(
|
|
opType: "changeprivilege",
|
|
requestData: [
|
|
"group_key": groupKey,
|
|
"privilege_code": item.apiKey,
|
|
"enable": isOn
|
|
]
|
|
)
|
|
.subscribe(onNext: { [weak self] response in
|
|
guard let self else { return }
|
|
self.isSubmitting = false
|
|
self.rootView.setSettingsEnabled(!self.groups.isEmpty)
|
|
guard response.code == "0" else {
|
|
self.revertPrivilege(groupKey: groupKey, previous: previous)
|
|
DLToast.showError(text: response.message ?? "设置失败")
|
|
return
|
|
}
|
|
}, onError: { [weak self] error in
|
|
guard let self else { return }
|
|
self.isSubmitting = false
|
|
self.rootView.setSettingsEnabled(!self.groups.isEmpty)
|
|
self.revertPrivilege(groupKey: groupKey, previous: previous)
|
|
DLToast.showError(text: error.localizedDescription)
|
|
})
|
|
.disposed(by: disposeBag)
|
|
}
|
|
|
|
private func revertPrivilege(groupKey: String, previous: GroupPrivilege) {
|
|
if let index = groups.firstIndex(where: { $0.group_key == groupKey }) {
|
|
groups[index].privilege = previous
|
|
}
|
|
applySelectedPrivilege()
|
|
}
|
|
}
|
|
|
|
final class PrivacySettingsView: UIView {
|
|
|
|
var onGroupChanged: (() -> Void)?
|
|
var onToggle: ((PrivacySettingItem, Bool) -> Void)?
|
|
var selectedGroupKey: String { groupSelectorView.selectedGroupKey }
|
|
|
|
private let navBackgroundView = UIImageView(image: UIImage(named: "Common/navBar_bg_2"))
|
|
private let navView = BaseNavigationView(title: "隐私设置")
|
|
private let scrollView = UIScrollView()
|
|
private let contentView = UIView()
|
|
private let groupSelectorView = PrivacyGroupSelectorView()
|
|
private let phoneReportRow = PrivacySettingRow(item: .phoneReport)
|
|
private let groupLockRow = PrivacySettingRow(item: .groupLock)
|
|
private let pigeonMessageRow = PrivacySettingRow(item: .pigeonMessage)
|
|
private let footerLabel = UILabel()
|
|
|
|
override init(frame: CGRect) {
|
|
super.init(frame: frame)
|
|
setupUI()
|
|
}
|
|
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
func configure(groups: [GroupInfoModel], selectedGroupKey: String) {
|
|
groupSelectorView.configure(groups: groups, selectedGroupKey: selectedGroupKey)
|
|
setSettingsEnabled(!groups.isEmpty)
|
|
}
|
|
|
|
func apply(_ privilege: GroupPrivilege) {
|
|
phoneReportRow.setOn(privilege.phone_report)
|
|
groupLockRow.setOn(privilege.app_lock)
|
|
pigeonMessageRow.setOn(privilege.pigeon_mail)
|
|
}
|
|
|
|
func setSettingsEnabled(_ enabled: Bool) {
|
|
[phoneReportRow, groupLockRow, pigeonMessageRow].forEach {
|
|
$0.setSwitchEnabled(enabled)
|
|
}
|
|
}
|
|
|
|
private func setupUI() {
|
|
backgroundColor = UIColor(hexStr: "#FAFAFA")
|
|
|
|
navBackgroundView.contentMode = .scaleAspectFill
|
|
navBackgroundView.clipsToBounds = true
|
|
addSubview(navBackgroundView)
|
|
addSubview(navView)
|
|
|
|
scrollView.showsVerticalScrollIndicator = false
|
|
scrollView.alwaysBounceVertical = false
|
|
addSubview(scrollView)
|
|
scrollView.addSubview(contentView)
|
|
|
|
footerLabel.text = "ⓘ 仅对当前选中圈子生效哟~"
|
|
footerLabel.textColor = UIColor(hexStr: "#536177")
|
|
footerLabel.font = .systemFont(ofSize: 13, weight: .regular)
|
|
footerLabel.textAlignment = .center
|
|
addSubview(footerLabel)
|
|
|
|
contentView.addSubview(groupSelectorView)
|
|
|
|
let shareHeader = makeSectionHeader(title: "圈子中可以共享的数据")
|
|
contentView.addSubview(shareHeader)
|
|
contentView.addSubview(phoneReportRow)
|
|
|
|
let ownerHeader = makeSectionHeader(title: "圈主可以对你使用的功能")
|
|
contentView.addSubview(ownerHeader)
|
|
contentView.addSubview(groupLockRow)
|
|
contentView.addSubview(pigeonMessageRow)
|
|
|
|
navBackgroundView.layoutChain
|
|
.edges(excludingEdge: .bottom)
|
|
.height(kNaviHeight)
|
|
|
|
navView.layoutChain
|
|
.edges(excludingEdge: .bottom)
|
|
.height(kNaviHeight)
|
|
|
|
footerLabel.layoutChain
|
|
.left(20)
|
|
.right(20)
|
|
.bottom(kSafeBottomMargin + 12)
|
|
.height(24)
|
|
|
|
scrollView.layoutChain
|
|
.topToBottomOfView(navView)
|
|
.left()
|
|
.right()
|
|
.bottomToTopOfView(footerLabel, offset: -8)
|
|
|
|
contentView.layoutChain
|
|
.edges()
|
|
.widthToView(scrollView)
|
|
|
|
groupSelectorView.layoutChain
|
|
.top(12)
|
|
.left(15)
|
|
.right(15)
|
|
.height(100)
|
|
|
|
shareHeader.layoutChain
|
|
.topToBottomOfView(groupSelectorView, offset: 20)
|
|
.left(17)
|
|
.right(15)
|
|
.height(24)
|
|
|
|
phoneReportRow.layoutChain
|
|
.topToBottomOfView(shareHeader, offset: 12)
|
|
.left(15)
|
|
.right(15)
|
|
.height(64)
|
|
|
|
ownerHeader.layoutChain
|
|
.topToBottomOfView(phoneReportRow, offset: 18)
|
|
.left(17)
|
|
.right(15)
|
|
.height(24)
|
|
|
|
groupLockRow.layoutChain
|
|
.topToBottomOfView(ownerHeader, offset: 12)
|
|
.left(15)
|
|
.right(15)
|
|
.height(64)
|
|
|
|
pigeonMessageRow.layoutChain
|
|
.topToBottomOfView(groupLockRow, offset: 12)
|
|
.left(15)
|
|
.right(15)
|
|
.height(64)
|
|
.bottom(20)
|
|
|
|
groupSelectorView.onSelectionChanged = { [weak self] in
|
|
self?.onGroupChanged?()
|
|
}
|
|
phoneReportRow.onToggle = { [weak self] isOn in
|
|
self?.onToggle?(.phoneReport, isOn)
|
|
}
|
|
groupLockRow.onToggle = { [weak self] isOn in
|
|
self?.onToggle?(.groupLock, isOn)
|
|
}
|
|
pigeonMessageRow.onToggle = { [weak self] isOn in
|
|
self?.onToggle?(.pigeonMessage, isOn)
|
|
}
|
|
}
|
|
|
|
private func makeSectionHeader(title: String) -> UIView {
|
|
let view = UIView()
|
|
|
|
let sparkleLabel = UILabel()
|
|
sparkleLabel.text = "✦"
|
|
sparkleLabel.textColor = UIColor(hexStr: "#08ADEF")
|
|
sparkleLabel.font = .systemFont(ofSize: 18, weight: .bold)
|
|
sparkleLabel.textAlignment = .center
|
|
view.addSubview(sparkleLabel)
|
|
|
|
let titleLabel = UILabel()
|
|
titleLabel.text = title
|
|
titleLabel.textColor = UIColor(hexStr: "#28364B")
|
|
titleLabel.font = .systemFont(ofSize: 16, weight: .regular)
|
|
view.addSubview(titleLabel)
|
|
|
|
sparkleLabel.layoutChain
|
|
.left()
|
|
.centerY()
|
|
.width(18)
|
|
.height(24)
|
|
|
|
titleLabel.layoutChain
|
|
.leftToRightOfView(sparkleLabel, offset: 3)
|
|
.right()
|
|
.centerY()
|
|
.height(24)
|
|
|
|
return view
|
|
}
|
|
}
|
|
|
|
private final class PrivacyGroupSelectorView: UIView,
|
|
UICollectionViewDataSource,
|
|
UICollectionViewDelegateFlowLayout {
|
|
|
|
var onSelectionChanged: (() -> Void)?
|
|
private(set) var selectedGroupKey = ""
|
|
|
|
private let layout = UICollectionViewFlowLayout()
|
|
private lazy var collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
|
|
private let emptyLabel = UILabel()
|
|
private var groups: [GroupInfoModel] = []
|
|
|
|
override init(frame: CGRect) {
|
|
super.init(frame: frame)
|
|
backgroundColor = .white
|
|
layer.cornerRadius = 20
|
|
clipsToBounds = true
|
|
|
|
layout.scrollDirection = .horizontal
|
|
layout.minimumLineSpacing = 4
|
|
layout.minimumInteritemSpacing = 4
|
|
layout.sectionInset = UIEdgeInsets(top: 4, left: 6, bottom: 4, right: 6)
|
|
|
|
collectionView.backgroundColor = .clear
|
|
collectionView.showsHorizontalScrollIndicator = false
|
|
collectionView.alwaysBounceHorizontal = true
|
|
collectionView.dataSource = self
|
|
collectionView.delegate = self
|
|
collectionView.register(PrivacyGroupCell.self)
|
|
addSubview(collectionView)
|
|
collectionView.layoutChain.edges()
|
|
|
|
emptyLabel.text = "暂无圈子"
|
|
emptyLabel.textColor = UIColor(hexStr: "#9BA3AF")
|
|
emptyLabel.font = .systemFont(ofSize: 15, weight: .regular)
|
|
emptyLabel.textAlignment = .center
|
|
emptyLabel.isHidden = true
|
|
addSubview(emptyLabel)
|
|
emptyLabel.layoutChain.edges()
|
|
}
|
|
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
func configure(groups: [GroupInfoModel], selectedGroupKey: String) {
|
|
self.groups = groups
|
|
if groups.contains(where: { $0.group_key == selectedGroupKey }) {
|
|
self.selectedGroupKey = selectedGroupKey
|
|
} else {
|
|
self.selectedGroupKey = groups.first?.group_key ?? ""
|
|
}
|
|
emptyLabel.isHidden = !groups.isEmpty
|
|
collectionView.isHidden = groups.isEmpty
|
|
collectionView.reloadData()
|
|
|
|
guard let index = groups.firstIndex(where: { $0.group_key == self.selectedGroupKey }) else {
|
|
return
|
|
}
|
|
collectionView.layoutIfNeeded()
|
|
collectionView.scrollToItem(
|
|
at: IndexPath(item: index, section: 0),
|
|
at: .centeredHorizontally,
|
|
animated: false
|
|
)
|
|
}
|
|
|
|
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
|
groups.count
|
|
}
|
|
|
|
func collectionView(_ collectionView: UICollectionView,
|
|
cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
|
let cell: PrivacyGroupCell = collectionView.dequeueReusableCell(for: indexPath)
|
|
let group = groups[indexPath.item]
|
|
cell.configure(group: group, selected: group.group_key == selectedGroupKey)
|
|
return cell
|
|
}
|
|
|
|
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
|
let groupKey = groups[indexPath.item].group_key
|
|
guard selectedGroupKey != groupKey else { return }
|
|
selectedGroupKey = groupKey
|
|
collectionView.reloadData()
|
|
collectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
|
|
onSelectionChanged?()
|
|
}
|
|
|
|
func collectionView(_ collectionView: UICollectionView,
|
|
layout collectionViewLayout: UICollectionViewLayout,
|
|
sizeForItemAt indexPath: IndexPath) -> CGSize {
|
|
CGSize(width: 76, height: 92)
|
|
}
|
|
}
|
|
|
|
private final class PrivacyGroupCell: UICollectionViewCell {
|
|
|
|
private let selectionView = UIView()
|
|
private let selectionPointer = UIView()
|
|
private let iconView = UIImageView()
|
|
private let nameLabel = UILabel()
|
|
|
|
override init(frame: CGRect) {
|
|
super.init(frame: frame)
|
|
|
|
selectionView.backgroundColor = UIColor(hexStr: "#C9F4FF")
|
|
selectionView.layer.cornerRadius = 13
|
|
selectionView.isHidden = true
|
|
contentView.addSubview(selectionView)
|
|
|
|
selectionPointer.backgroundColor = UIColor(hexStr: "#C9F4FF")
|
|
selectionPointer.transform = CGAffineTransform(rotationAngle: .pi / 4)
|
|
selectionPointer.isHidden = true
|
|
contentView.addSubview(selectionPointer)
|
|
|
|
iconView.contentMode = .scaleAspectFill
|
|
iconView.clipsToBounds = true
|
|
iconView.layer.cornerRadius = 25
|
|
contentView.addSubview(iconView)
|
|
|
|
nameLabel.textColor = UIColor(hexStr: "#26364B")
|
|
nameLabel.font = .systemFont(ofSize: 14, weight: .regular)
|
|
nameLabel.textAlignment = .center
|
|
nameLabel.lineBreakMode = .byTruncatingTail
|
|
contentView.addSubview(nameLabel)
|
|
|
|
selectionView.layoutChain
|
|
.top(1)
|
|
.left(2)
|
|
.right(2)
|
|
.bottom(4)
|
|
|
|
selectionPointer.layoutChain
|
|
.centerX()
|
|
.bottom(1)
|
|
.width(12)
|
|
.height(12)
|
|
|
|
iconView.layoutChain
|
|
.top(8)
|
|
.centerX()
|
|
.width(50)
|
|
.height(50)
|
|
|
|
nameLabel.layoutChain
|
|
.topToBottomOfView(iconView, offset: 5)
|
|
.left(5)
|
|
.right(5)
|
|
.height(20)
|
|
}
|
|
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
override func prepareForReuse() {
|
|
super.prepareForReuse()
|
|
iconView.kf.cancelDownloadTask()
|
|
iconView.image = nil
|
|
}
|
|
|
|
func configure(group: GroupInfoModel, selected: Bool) {
|
|
nameLabel.text = group.name
|
|
iconView.setGroupIcon(group)
|
|
selectionView.isHidden = !selected
|
|
selectionPointer.isHidden = !selected
|
|
}
|
|
}
|
|
|
|
private final class PrivacySettingRow: UIView {
|
|
|
|
var onToggle: ((Bool) -> Void)?
|
|
private let settingSwitch = UISwitch()
|
|
|
|
init(item: PrivacySettingItem) {
|
|
super.init(frame: .zero)
|
|
backgroundColor = .white
|
|
layer.cornerRadius = 20
|
|
|
|
let imageView = UIImageView(image: UIImage(named: item.imageName))
|
|
imageView.contentMode = .scaleAspectFit
|
|
addSubview(imageView)
|
|
|
|
let titleLabel = UILabel()
|
|
titleLabel.text = item.title
|
|
titleLabel.textColor = UIColor(hexStr: "#28364B")
|
|
titleLabel.font = .systemFont(ofSize: 17, weight: .regular)
|
|
addSubview(titleLabel)
|
|
|
|
settingSwitch.onTintColor = UIColor(hexStr: "#08ADEF")
|
|
settingSwitch.setOn(false, animated: false)
|
|
settingSwitch.addTarget(self, action: #selector(switchChanged), for: .valueChanged)
|
|
addSubview(settingSwitch)
|
|
|
|
imageView.layoutChain
|
|
.left(8)
|
|
.centerY()
|
|
.width(96)
|
|
.height(50)
|
|
|
|
settingSwitch.layoutChain
|
|
.right(13)
|
|
.centerY()
|
|
|
|
titleLabel.layoutChain
|
|
.leftToRightOfView(imageView, offset: 8)
|
|
.rightToLeftOfView(settingSwitch, offset: -8)
|
|
.centerY()
|
|
.height(26)
|
|
}
|
|
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
func setSwitchEnabled(_ enabled: Bool) {
|
|
settingSwitch.isEnabled = enabled
|
|
}
|
|
|
|
func setOn(_ on: Bool) {
|
|
settingSwitch.setOn(on, animated: false)
|
|
}
|
|
|
|
@objc private func switchChanged() {
|
|
onToggle?(settingSwitch.isOn)
|
|
}
|
|
}
|