// // LNOrderAcceptSettingsViewController.swift // Gami // // Created by OneeChan on 2026/1/23. // import Foundation import UIKit import SnapKit extension UIView { func pushToOrderAcceptSettings() { let vc = LNOrderAcceptSettingsViewController() navigationController?.pushViewController(vc, animated: true) } } class LNOrderAcceptSettingsViewController: LNViewController { private let timeLabel = UILabel() private var selectTime: (from: Int, to: Int) = (0, 1) { didSet { if selectTime.from + 24 == selectTime.to || selectTime.from == selectTime.to { timeLabel.text = .init(key: "B00100") return } let fromTime = String(format: "%02d:00", selectTime.from) let toTime: String = if selectTime.to > 23 { .init(key: "B00084") + String(format: "%02d:00", selectTime.to - 24) } else { String(format: "%02d:00", selectTime.to) } timeLabel.text = fromTime + "~" + toTime } } private let dateLabel = UILabel() private var selectDate: [LNOrderAcceptWeekDay] = [] { didSet { dateLabel.text = selectedDateDesc() } } private let autoReplySwitch = UISwitch() private var isAutoReply: Bool = false { didSet { autoReplySwitch.isOn = isAutoReply } } private var config: LNOrderAcceptConfig? override func viewDidLoad() { super.viewDidLoad() setupViews() loadConfig() } } extension LNOrderAcceptSettingsViewController { private func loadConfig() { showLoading() LNGameMateManager.shared.getOrderAccetpConfig { [weak self] config in dismissLoading() guard let self else { return } guard let config else { navigationController?.popViewController(animated: true) return } let components = config.timeRange.components(separatedBy: "-") if components.count == 2 { let from = extractHourFromTimeString(components[0]) var to = extractHourFromTimeString(components[1]) if to <= from { to += 24 } selectTime = (from, to) } else { selectTime = (0, 1) } selectDate = config.weekNums isAutoReply = config.autoWelcomeOpen self.config = config } } private func saveConfig() { let timeRange = String(format: "%02d:00", selectTime.from) + "-" + String(format: "%02d:00", selectTime.to >= 24 ? selectTime.to - 24 : selectTime.to) if let config, config.weekNums == selectDate, config.timeRange == timeRange { return } showLoading() let newConfig = LNOrderAcceptConfig() newConfig.weekNums = selectDate newConfig.timeRange = timeRange LNGameMateManager.shared.setOrderAcceptConfig(config: newConfig) { _ in dismissLoading() } } private func extractHourFromTimeString(_ timeString: String) -> Int { let components = timeString.components(separatedBy: ":") guard components.count == 2 else { return 0 } let hourString = components[0] guard let hour = Int(hourString) else { return 0 } guard hour >= 0 && hour <= 23 else { return 0 } return hour } private func selectedDateDesc() -> String { guard !selectDate.isEmpty else { return "" } var mergedSegments: [String] = [] var start = selectDate[0] var end = selectDate[0] for day in selectDate { if day == selectDate[0] { continue } // 如果当前星期与上一个连续,更新结束值 if day.rawValue == end.rawValue + 1 { end = day } else { // 不连续则保存当前段,并重置起始/结束 mergedSegments.append(mergeSegment(start: start, end: end)) start = day end = day } } mergedSegments.append(mergeSegment(start: start, end: end)) return mergedSegments.joined(separator: ",") } private func mergeSegment(start: LNOrderAcceptWeekDay, end: LNOrderAcceptWeekDay) -> String { let formatter = DateFormatter() formatter.locale = curLocal let symbols = formatter.weekdaySymbols! var segments: [String] = [] segments.append(symbols[start.rawValue - 1]) if start != end { segments.append(.init(key: "B00081")) segments.append(symbols[end.rawValue - 1]) } return segments.joined(separator: LNAppConfig.shared.curLang == .chiness ? "" : " ") } } extension LNOrderAcceptSettingsViewController { private func setupViews() { title = .init(key: "B00078") view.backgroundColor = .primary_1 let stackView = UIStackView() stackView.axis = .vertical stackView.spacing = 10 view.addSubview(stackView) stackView.snp.makeConstraints { make in make.horizontalEdges.equalToSuperview().inset(16) make.top.equalToSuperview().offset(12) } timeLabel.font = .body_s timeLabel.textColor = .text_4 let timeRangeView = buildItemView(title: .init(key: "B00079"), contentView: timeLabel) timeRangeView.onTap { [weak self] in guard let self else { return } let panel = LNHourRangePickerPanel() panel.setTitles(.init(key: "B00082"), desc: .init(key: "B00083")) panel.setDefault(from: selectTime.from, to: selectTime.to) panel.handler = { [weak self] from, to in guard let self else { return } selectTime = (from, to) saveConfig() } panel.popup() } stackView.addArrangedSubview(timeRangeView) dateLabel.font = .body_s dateLabel.textColor = .text_4 let weekdayView = buildItemView(title: .init(key: "B00080"), contentView: dateLabel) weekdayView.onTap { [weak self] in guard let self else { return } let formatter = DateFormatter() formatter.locale = curLocal let panel = LNMultiSelectionPanel() panel.setTitles(.init(key: "B00085"), desc: .init(key: "B00086")) panel.update(formatter.weekdaySymbols, curSelected: selectDate.map({ $0.text })) panel.handler = { [weak self] indexs in guard let self else { return } var dates: [LNOrderAcceptWeekDay] = [] for index in indexs { dates.append(LNOrderAcceptWeekDay.allCases[index]) } selectDate = dates saveConfig() } panel.popup() } stackView.addArrangedSubview(weekdayView) stackView.addArrangedSubview(buildWelcomeView()) } private func buildItemView(title: String, contentView: UIView) -> UIView { let container = UIView() container.layer.cornerRadius = 12 container.backgroundColor = .fill container.snp.makeConstraints { make in make.height.equalTo(60) } let arrow = UIImageView.arrowImageView(size: 14) arrow.tintColor = .text_4 container.addSubview(arrow) arrow.snp.makeConstraints { make in make.centerY.equalToSuperview() make.trailing.equalToSuperview().offset(-12) } contentView.setContentHuggingPriority(.defaultLow, for: .horizontal) contentView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) container.addSubview(contentView) contentView.snp.makeConstraints { make in make.centerY.equalToSuperview() make.trailing.equalTo(arrow.snp.leading).offset(-2) } let titleLabel = UILabel() titleLabel.font = .heading_h4 titleLabel.textColor = .text_5 titleLabel.text = title titleLabel.setContentHuggingPriority(.required, for: .horizontal) titleLabel.setContentCompressionResistancePriority(.required, for: .horizontal) container.addSubview(titleLabel) titleLabel.snp.makeConstraints { make in make.centerY.equalToSuperview() make.leading.equalToSuperview().offset(12) make.trailing.lessThanOrEqualTo(contentView.snp.leading).offset(-12) } return container } private func buildWelcomeView() -> UIView { let container = UIView() container.layer.cornerRadius = 12 container.backgroundColor = .fill container.onTap { [weak self] in guard let self else { return } view.pushToAutoReplyList() } let holder = UIView() container.addSubview(holder) holder.snp.makeConstraints { make in make.horizontalEdges.equalToSuperview() make.top.equalToSuperview() make.height.equalTo(53) } let arrow = UIImageView.arrowImageView(size: 14) arrow.tintColor = .text_4 holder.addSubview(arrow) arrow.snp.makeConstraints { make in make.centerY.equalToSuperview() make.trailing.equalToSuperview().offset(-12) } let titleLabel = UILabel() titleLabel.font = .heading_h4 titleLabel.textColor = .text_5 titleLabel.text = .init(key: "B00112") holder.addSubview(titleLabel) titleLabel.snp.makeConstraints { make in make.centerY.equalToSuperview() make.leading.equalToSuperview().offset(12) make.trailing.lessThanOrEqualTo(arrow.snp.leading).offset(-12) } let openView = UIView() container.addSubview(openView) openView.snp.makeConstraints { make in make.horizontalEdges.equalToSuperview() make.top.equalTo(holder.snp.bottom) make.bottom.equalToSuperview().offset(-8) } let tipsLabel = UILabel() tipsLabel.font = .body_s tipsLabel.textColor = .text_5 tipsLabel.text = .init(key: "B00113") openView.addSubview(tipsLabel) tipsLabel.snp.makeConstraints { make in make.centerY.equalToSuperview() make.leading.equalToSuperview().offset(12) } let scaleX: CGFloat = 40.0 / 51.0 let scaleY: CGFloat = 24.5 / 31.0 autoReplySwitch.onTintColor = .primary_5 autoReplySwitch.transform = CGAffineTransform(scaleX: scaleX, y: scaleY) autoReplySwitch.addAction(UIAction(handler: { [weak self] _ in guard let self else { return } showLoading() LNGameMateManager.shared.enableAutoReplay(on: autoReplySwitch.isOn) { [weak self] success in dismissLoading() guard let self else { return } guard success else { autoReplySwitch.isOn.toggle() return } isAutoReply = autoReplySwitch.isOn } }), for: .valueChanged) openView.addSubview(autoReplySwitch) autoReplySwitch.snp.makeConstraints { make in make.verticalEdges.equalToSuperview() make.trailing.equalToSuperview().offset(-12) } return container } }