Skip to content

Commit

Permalink
iOS: introduce refreshControlTopAnchor property (#203)
Browse files Browse the repository at this point in the history
  • Loading branch information
pklatka committed Apr 30, 2024
1 parent 8df0016 commit 547e0e0
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 15 deletions.
6 changes: 6 additions & 0 deletions packages/turbo/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@ The amount by which the web view content is inset from the edges of the scroll v

Note: available only on iOS.

### `refreshControlTopAnchor`

This property enables setting custom `topAnchor` for the native refresh control. If the value is set, the refresh control will be anchored to the top of the web view with the specified offset. By default, this value is set to the safe area top anchor.

Note: available only on iOS.

### `progressViewOffset`

The refresh indicator starting and resting position is always positioned near the top of the refreshing content. This position is a consistent location, but can be adjusted in either direction based on whether or not there is a header or other content that should be visible when the refresh indicator is shown.
Expand Down
5 changes: 5 additions & 0 deletions packages/turbo/ios/RNVisitableView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ class RNVisitableView: UIView, RNSessionSubscriber {
controller!.visitableView.allowsPullToRefresh = pullToRefreshEnabled
}
}
@objc var refreshControlTopAnchor: NSNumber = 0 {
didSet {
controller!.visitableView.refreshControlTopAnchor = refreshControlTopAnchor as! CGFloat
}
}
@objc var scrollEnabled: Bool = true {
didSet {
configureWebView()
Expand Down
1 change: 1 addition & 0 deletions packages/turbo/ios/RNVisitableViewManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ @interface RCT_EXTERN_MODULE(RNVisitableViewManager, NSObject)
RCT_EXPORT_VIEW_PROPERTY(pullToRefreshEnabled, BOOL)
RCT_EXPORT_VIEW_PROPERTY(scrollEnabled, BOOL)
RCT_EXPORT_VIEW_PROPERTY(contentInset, NSDictionary)
RCT_EXPORT_VIEW_PROPERTY(refreshControlTopAnchor, NSNumber)
RCT_EXPORT_VIEW_PROPERTY(webViewDebuggingEnabled, BOOL)
RCT_EXPORT_VIEW_PROPERTY(onVisitProposal, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onOpenExternalUrl, RCTDirectEventBlock)
Expand Down
41 changes: 26 additions & 15 deletions packages/turbo/patches/turbo-ios.patch
Original file line number Diff line number Diff line change
@@ -1,21 +1,32 @@
diff --git a/Source/Visitable/VisitableView.swift b/Source/Visitable/VisitableView.swift
index 12452b5..e9c37b8 100644
index 12452b5..49b932c 100644
--- a/Source/Visitable/VisitableView.swift
+++ b/Source/Visitable/VisitableView.swift
@@ -69,16 +69,6 @@ open class VisitableView: UIView {
@@ -16,6 +16,8 @@ open class VisitableView: UIView {
installActivityIndicatorView()
}

+ public var refreshControlTopAnchor: CGFloat = 0
+
// MARK: Web View

open var webView: WKWebView?
@@ -74,9 +76,17 @@ open class VisitableView: UIView {
/// Otherwise fallback to 60 (the default height).
let refreshControlHeight = refreshControl.frame.height > 0 ? refreshControl.frame.height : 60

#if !targetEnvironment(macCatalyst)
scrollView.addSubview(refreshControl)
-
- /// Infer refresh control's default height from its frame, if given.
- /// Otherwise fallback to 60 (the default height).
- let refreshControlHeight = refreshControl.frame.height > 0 ? refreshControl.frame.height : 60
-
- NSLayoutConstraint.activate([
- refreshControl.centerXAnchor.constraint(equalTo: centerXAnchor),
+ let topAnchorConstraint: NSLayoutConstraint
+
+ if (refreshControlTopAnchor > 0) {
+ topAnchorConstraint = refreshControl.topAnchor.constraint(equalTo: webView!.topAnchor, constant: refreshControlTopAnchor)
+ } else {
+ topAnchorConstraint = refreshControl.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor)
+ }
+
NSLayoutConstraint.activate([
+ topAnchorConstraint,
refreshControl.centerXAnchor.constraint(equalTo: centerXAnchor),
- refreshControl.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor),
- refreshControl.heightAnchor.constraint(equalToConstant: refreshControlHeight)
- ])
refreshControl.heightAnchor.constraint(equalToConstant: refreshControlHeight)
])
#endif
}

1 change: 1 addition & 0 deletions packages/turbo/src/RNVisitableView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export interface RNVisitableViewProps {
scrollEnabled: boolean;
contentInset: ContentInsetObject;
progressViewOffset?: ProgressViewOffsetObject;
refreshControlTopAnchor: number;
webViewDebuggingEnabled: boolean;
onLoad?: (e: NativeSyntheticEvent<LoadEvent>) => void;
onMessage?: (e: NativeSyntheticEvent<MessageEvent>) => void;
Expand Down
3 changes: 3 additions & 0 deletions packages/turbo/src/VisitableView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export interface Props {
scrollEnabled?: boolean;
contentInset?: ContentInsetObject;
progressViewOffset?: ProgressViewOffsetObject;
refreshControlTopAnchor?: number;
webViewDebuggingEnabled?: boolean;
renderLoading?: RenderLoading;
renderError?: RenderError;
Expand Down Expand Up @@ -87,6 +88,7 @@ const VisitableView = React.forwardRef<RefObject, React.PropsWithRef<Props>>(
scrollEnabled = true,
contentInset = { top: 0, left: 0, right: 0, bottom: 0 },
progressViewOffset,
refreshControlTopAnchor = 0,
webViewDebuggingEnabled = false,
renderLoading,
renderError,
Expand Down Expand Up @@ -227,6 +229,7 @@ const VisitableView = React.forwardRef<RefObject, React.PropsWithRef<Props>>(
scrollEnabled={scrollEnabled}
contentInset={contentInset}
progressViewOffset={progressViewOffset}
refreshControlTopAnchor={refreshControlTopAnchor}
webViewDebuggingEnabled={webViewDebuggingEnabled}
onError={onErrorCombinedHandlers}
onVisitProposal={handleVisitProposal}
Expand Down

0 comments on commit 547e0e0

Please sign in to comment.