d6201c59b4
Desktop: - Replace Remote checkbox with T: dest_spin (0=Off, 1-9=tablet) on all widgets - dest_id persisted in get_state/set_state, broadcast in tablet snapshot - dest_spin.valueChanged triggers save + broadcast to iPad - _on_widget_visibility_from_tablet updates dest_spin from iPad hide event - _broadcast_preset_update shared helper; ws_server.has_clients guard - label editingFinished triggers live label sync to iPad iOS: - VC-Arrange/VC-Logging/Widgets-Reusable-UI file reorganisation - ArrangeObjects/ArrangeView rename, 7-bucket Arrange-Functions split - myTabletId (UserDefaults) + tabletIdField next to port in toolbar - Preset filter: destId == myTabletId instead of visible bool - BaseWidget activity ring: long press gesture (touch) + final update() flash - Context menu long press (arrange mode): hide widget, save layout, send dest_id:0 - Same-UUID preset check skips Preset Switched alert on visibility/label updates - autoSwitchEnabled, toolbarStatusLabel, presetLabel, statusToken Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
55 lines
2.0 KiB
Swift
55 lines
2.0 KiB
Swift
import UIKit
|
|
|
|
extension ArrangeObjects {
|
|
|
|
// MARK: - Gestures
|
|
|
|
func addDragGesture(to view: UIView) {
|
|
let pan = UIPanGestureRecognizer(target: self, action: #selector(handleGesturePan(_:)))
|
|
view.addGestureRecognizer(pan)
|
|
}
|
|
|
|
@objc func handleGesturePan(_ gesture: UIPanGestureRecognizer) {
|
|
guard self.isLocked == false, let view = gesture.view else { return }
|
|
let translation = gesture.translation(in: self.containerView)
|
|
view.center = CGPoint(x: view.center.x + translation.x, y: view.center.y + translation.y)
|
|
gesture.setTranslation(.zero, in: self.containerView)
|
|
}
|
|
|
|
func addContextMenuGesture(to view: UIView) {
|
|
let press = UILongPressGestureRecognizer(target: self, action: #selector(handleGestureLongPress(_:)))
|
|
press.minimumPressDuration = 0.5
|
|
press.cancelsTouchesInView = false
|
|
view.addGestureRecognizer(press)
|
|
}
|
|
|
|
@objc func handleGestureLongPress(_ gesture: UILongPressGestureRecognizer) {
|
|
guard self.isLocked == false else { return }
|
|
guard gesture.state == .began else { return }
|
|
guard let widget = gesture.view as? BaseWidget else { return }
|
|
|
|
let alert = UIAlertController(title: widget.displayName, message: nil, preferredStyle: .actionSheet)
|
|
alert.overrideUserInterfaceStyle = .dark
|
|
|
|
alert.addAction(UIAlertAction(title: "Hide", style: .destructive) { [weak self] _ in
|
|
self?.hideWidget(widget)
|
|
})
|
|
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
|
|
|
|
if let popover = alert.popoverPresentationController {
|
|
popover.sourceView = widget
|
|
popover.sourceRect = widget.bounds
|
|
}
|
|
|
|
self.present(alert, animated: true)
|
|
}
|
|
|
|
func hideWidget(_ widget: BaseWidget) {
|
|
widget.removeFromSuperview()
|
|
self.widgets.removeValue(forKey: widget.uid)
|
|
self.saveLayout()
|
|
self.wsClientSendJSON(["event": "widget_visibility", "uid": widget.uid, "dest_id": 0])
|
|
}
|
|
|
|
}
|