Skip to content

Commit 88ea429

Browse files
committed
Make it run on tvOS, prefer beberkas solution on merge
textSelection is being ignored on tvOS
1 parent 7194cb7 commit 88ea429

File tree

4 files changed

+109
-91
lines changed

4 files changed

+109
-91
lines changed

Sources/SwiftCrossUI/Views/Modifiers/TextSelectionModifier.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
extension View {
22
/// Set selectability of contained text.
3+
/// ignored on tvOS
34
public func textSelectionEnabled(_ isEnabled: Bool = true) -> some View {
45
EnvironmentModifier(
56
self,

Sources/UIKitBackend/UIKitBackend+Control.swift

Lines changed: 41 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -170,34 +170,35 @@ final class TappableWidget: ContainerWidget {
170170
}
171171
}
172172

173-
@available(tvOS, unavailable)
174-
final class HoverableWidget: ContainerWidget {
175-
private var hoverGestureRecognizer: UIHoverGestureRecognizer?
176-
177-
var hoverChangesHandler: ((Bool) -> Void)? {
178-
didSet {
179-
if hoverChangesHandler != nil && hoverGestureRecognizer == nil {
180-
let gestureRecognizer = UIHoverGestureRecognizer(
181-
target: self,
182-
action: #selector(hoveringChanged(_:)))
183-
child.view.addGestureRecognizer(gestureRecognizer)
184-
self.hoverGestureRecognizer = gestureRecognizer
185-
} else if hoverChangesHandler == nil, let hoverGestureRecognizer {
186-
child.view.removeGestureRecognizer(hoverGestureRecognizer)
187-
self.hoverGestureRecognizer = nil
173+
#if !os(tvOS)
174+
final class HoverableWidget: ContainerWidget {
175+
private var hoverGestureRecognizer: UIHoverGestureRecognizer?
176+
177+
var hoverChangesHandler: ((Bool) -> Void)? {
178+
didSet {
179+
if hoverChangesHandler != nil && hoverGestureRecognizer == nil {
180+
let gestureRecognizer = UIHoverGestureRecognizer(
181+
target: self,
182+
action: #selector(hoveringChanged(_:)))
183+
child.view.addGestureRecognizer(gestureRecognizer)
184+
self.hoverGestureRecognizer = gestureRecognizer
185+
} else if hoverChangesHandler == nil, let hoverGestureRecognizer {
186+
child.view.removeGestureRecognizer(hoverGestureRecognizer)
187+
self.hoverGestureRecognizer = nil
188+
}
188189
}
189190
}
190-
}
191191

192-
@objc
193-
func hoveringChanged(_ recognizer: UIHoverGestureRecognizer) {
194-
switch recognizer.state {
195-
case .began: hoverChangesHandler?(true)
196-
case .ended: hoverChangesHandler?(false)
197-
default: break
192+
@objc
193+
func hoveringChanged(_ recognizer: UIHoverGestureRecognizer) {
194+
switch recognizer.state {
195+
case .began: hoverChangesHandler?(true)
196+
case .ended: hoverChangesHandler?(false)
197+
default: break
198+
}
198199
}
199200
}
200-
}
201+
#endif
201202
@available(tvOS, unavailable)
202203
final class SliderWidget: WrapperWidget<UISlider> {
203204
var onChange: ((Double) -> Void)?
@@ -331,8 +332,10 @@ extension UIKitBackend {
331332
onChange: @escaping (String) -> Void
332333
) {
333334
let textEditorWidget = textEditor as! TextEditorWidget
334-
335-
textEditorWidget.child.isEditable = environment.isEnabled
335+
//remove on merge, replace with beberka's solution
336+
#if !os(tvOS)
337+
textEditorWidget.child.isEditable = environment.isEnabled
338+
#endif
336339
textEditorWidget.child.font = environment.resolvedFont.uiFont
337340
textEditorWidget.child.textColor = UIColor(color: environment.suggestedForegroundColor)
338341
textEditorWidget.onChange = onChange
@@ -448,18 +451,20 @@ extension UIKitBackend {
448451
}
449452
}
450453

451-
public func createHoverTarget(wrapping child: Widget) -> Widget {
452-
HoverableWidget(child: child)
453-
}
454+
#if !os(tvOS)
455+
public func createHoverTarget(wrapping child: Widget) -> Widget {
456+
HoverableWidget(child: child)
457+
}
454458

455-
public func updateHoverTarget(
456-
_ hoverTarget: any WidgetProtocol,
457-
environment: EnvironmentValues,
458-
action: @escaping (Bool) -> Void
459-
) {
460-
let wrapper = hoverTarget as! HoverableWidget
461-
wrapper.hoverChangesHandler = action
462-
}
459+
public func updateHoverTarget(
460+
_ hoverTarget: any WidgetProtocol,
461+
environment: EnvironmentValues,
462+
action: @escaping (Bool) -> Void
463+
) {
464+
let wrapper = hoverTarget as! HoverableWidget
465+
wrapper.hoverChangesHandler = action
466+
}
467+
#endif
463468

464469
#if os(iOS) || os(visionOS) || targetEnvironment(macCatalyst)
465470
public func createSlider() -> Widget {

Sources/UIKitBackend/UIKitBackend+Passive.swift

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -126,27 +126,32 @@ final class OptionallySelectableLabel: UILabel {
126126
}
127127

128128
private func setupTextSelection() {
129-
let longPress = UILongPressGestureRecognizer(target: self, action: #selector(didLongPress))
130-
addGestureRecognizer(longPress)
131-
isUserInteractionEnabled = true
129+
#if !os(tvOS)
130+
let longPress = UILongPressGestureRecognizer(
131+
target: self, action: #selector(didLongPress))
132+
addGestureRecognizer(longPress)
133+
isUserInteractionEnabled = true
134+
#endif
132135
}
133136

134137
@objc private func didLongPress(_ gesture: UILongPressGestureRecognizer) {
135-
guard
136-
isSelectable,
137-
gesture.state == .began,
138-
let text = self.attributedText?.string,
139-
!text.isEmpty
140-
else {
141-
return
142-
}
143-
window?.endEditing(true)
144-
guard becomeFirstResponder() else { return }
145-
146-
let menu = UIMenuController.shared
147-
if !menu.isMenuVisible {
148-
menu.showMenu(from: self, rect: textRect())
149-
}
138+
#if !os(tvOS)
139+
guard
140+
isSelectable,
141+
gesture.state == .began,
142+
let text = self.attributedText?.string,
143+
!text.isEmpty
144+
else {
145+
return
146+
}
147+
window?.endEditing(true)
148+
guard becomeFirstResponder() else { return }
149+
150+
let menu = UIMenuController.shared
151+
if !menu.isMenuVisible {
152+
menu.showMenu(from: self, rect: textRect())
153+
}
154+
#endif
150155
}
151156

152157
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
@@ -160,13 +165,17 @@ final class OptionallySelectableLabel: UILabel {
160165
}
161166

162167
private func cancelSelection() {
163-
let menu = UIMenuController.shared
164-
menu.hideMenu(from: self)
168+
#if !os(tvOS)
169+
let menu = UIMenuController.shared
170+
menu.hideMenu(from: self)
171+
#endif
165172
}
166173

167174
@objc override func copy(_ sender: Any?) {
168-
cancelSelection()
169-
let board = UIPasteboard.general
170-
board.string = text
175+
#if !os(tvOS)
176+
cancelSelection()
177+
let board = UIPasteboard.general
178+
board.string = text
179+
#endif
171180
}
172181
}
Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,46 @@
11
import SwiftCrossUI
2-
import WebKit
32

4-
extension UIKitBackend {
5-
public func createWebView() -> Widget {
6-
WebViewWidget()
7-
}
3+
#if canImport(WebKit)
4+
import WebKit
85

9-
public func updateWebView(
10-
_ webView: Widget,
11-
environment: EnvironmentValues,
12-
onNavigate: @escaping (URL) -> Void
13-
) {
14-
let webView = webView as! WebViewWidget
15-
webView.onNavigate = onNavigate
16-
}
6+
extension UIKitBackend {
7+
public func createWebView() -> Widget {
8+
WebViewWidget()
9+
}
1710

18-
public func navigateWebView(_ webView: Widget, to url: URL) {
19-
let webView = webView as! WebViewWidget
20-
let request = URLRequest(url: url)
21-
webView.child.load(request)
22-
}
23-
}
11+
public func updateWebView(
12+
_ webView: Widget,
13+
environment: EnvironmentValues,
14+
onNavigate: @escaping (URL) -> Void
15+
) {
16+
let webView = webView as! WebViewWidget
17+
webView.onNavigate = onNavigate
18+
}
2419

25-
/// A wrapper for WKWebView. Acts as the web view's delegate as well.
26-
final class WebViewWidget: WrapperWidget<WKWebView>, WKNavigationDelegate {
27-
var onNavigate: ((URL) -> Void)?
20+
public func navigateWebView(_ webView: Widget, to url: URL) {
21+
let webView = webView as! WebViewWidget
22+
let request = URLRequest(url: url)
23+
webView.child.load(request)
24+
}
25+
}
2826

29-
init() {
30-
super.init(child: WKWebView())
27+
/// A wrapper for WKWebView. Acts as the web view's delegate as well.
28+
final class WebViewWidget: WrapperWidget<WKWebView>, WKNavigationDelegate {
29+
var onNavigate: ((URL) -> Void)?
3130

32-
child.navigationDelegate = self
33-
}
31+
init() {
32+
super.init(child: WKWebView())
3433

35-
func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
36-
guard let url = webView.url else {
37-
print("warning: Web view has no URL")
38-
return
34+
child.navigationDelegate = self
3935
}
4036

41-
onNavigate?(url)
37+
func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
38+
guard let url = webView.url else {
39+
print("warning: Web view has no URL")
40+
return
41+
}
42+
43+
onNavigate?(url)
44+
}
4245
}
43-
}
46+
#endif

0 commit comments

Comments
 (0)