Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: iOS custom detents & Android form sheets #2045

Merged
merged 319 commits into from
Aug 10, 2024
Merged
Show file tree
Hide file tree
Changes from 250 commits
Commits
Show all changes
319 commits
Select commit Hold shift + click to select a range
49b5ad6
sheetInitialDetent -> sheetInitialState
kkafar Jan 7, 2024
700d46e
Update ScreenNativeComponent spec
kkafar Jan 7, 2024
7b4ed40
Update view manager interfaces for paper
kkafar Jan 7, 2024
612ada8
Bring back functionality of setting sheet height based on fraction pa…
kkafar Jan 7, 2024
86307aa
Check against empty array on native side
kkafar Jan 7, 2024
00d50b2
Cleanup ScreenStackFragment a bit
kkafar Jan 7, 2024
c442b25
Bring back support for dimming view animation
kkafar Jan 7, 2024
426bee8
Remove unused function
kkafar Jan 8, 2024
c3abf7c
Update TestExample to use new API
kkafar Jan 8, 2024
20a7ae6
Add react-versioned files
kkafar Jan 8, 2024
1a0653d
Remove RNSModalRootView.kt from main source set
kkafar Jan 8, 2024
6bda77c
Revert "Add react-versioned files"
kkafar Jan 8, 2024
2fe8144
Revert "Remove RNSModalRootView.kt from main source set"
kkafar Jan 8, 2024
57f0b43
Temporarily remove modal functionality
kkafar Jan 8, 2024
f8e9baf
Fix 3-level detet
kkafar Jan 8, 2024
cadde6a
Update TE
kkafar Jan 8, 2024
dafca03
Make ScreensCoordinatorLayout transparent to gestures
kkafar Jan 8, 2024
4dea550
Improve dimming view behaviour a bit
kkafar Jan 8, 2024
4f47012
Small renaming
kkafar Jan 8, 2024
f604827
Use ViewOutlineProvider to set sheet shape instead of MaterialShapeDr…
kkafar Jan 9, 2024
087a938
Do not set cornerradius on MaterialShapeDrawable at all
kkafar Jan 9, 2024
d940324
Cleanup attachShapeToScreen a bit
kkafar Jan 9, 2024
1323f1a
Use GradientDrawable to achieve effect of only top corners being rounded
kkafar Jan 9, 2024
52e5839
Stash changes on rounded corners
kkafar Jan 12, 2024
7cab9c2
Restore content diplay
kkafar Feb 11, 2024
1ca4e3d
Callbacks for ime inset, set temporarily push presentation as transpa…
kkafar Feb 12, 2024
49caf0a
Improve sheet animation
kkafar Feb 12, 2024
ab835b8
Restore pre Android 30 keyboard behaviour
kkafar Feb 13, 2024
77b9670
Update example in TE
kkafar Feb 13, 2024
f8b3946
Merge branch 'main' into @kkafar/android-modal-refactor-4
kkafar Feb 13, 2024
4479c1a
Remove merge artifact: index.native.tsx
kkafar Feb 13, 2024
72b2631
Update yarn.lock
kkafar Feb 13, 2024
1acbdc6
Update default values for sheet props
kkafar Feb 13, 2024
a11db31
Find the right combination to get the shadows working
kkafar Feb 15, 2024
bbfb20f
Update example
kkafar Feb 16, 2024
3c7cddc
Add stub JS code for native footer
kkafar Feb 16, 2024
a214f19
Add stub for ScreenFooter
kkafar Feb 16, 2024
9d86a34
Add first stub code for footer
kkafar Feb 18, 2024
0550367
Fix type error
kkafar Feb 19, 2024
0753533
Add PoC
kkafar Aug 1, 2023
97c29ce
Reorganise native code & rename the prop to sheetCustomDetents
kkafar Aug 2, 2023
ed8874e
Set default for `sheetCustomDetents` in `InnerScreen`
kkafar Aug 2, 2023
9d3bdd5
Pass the new prop through NativeStackView
kkafar Aug 2, 2023
b6939fc
Remove debug logging
kkafar Aug 2, 2023
88d10d8
Add stubs for type documentation
kkafar Aug 2, 2023
3763cf3
Cleanup native code a bit
kkafar Aug 2, 2023
2f91223
Rename updatePresentationStyle to updateFormSheetPresentationStyle
kkafar Aug 2, 2023
b106b8b
Add dev dependency on `jotai`
kkafar Aug 2, 2023
9a4ff66
Refactor test example using `jotai`
kkafar Aug 2, 2023
a30f4ee
Indentation
kkafar Aug 2, 2023
d84f64c
Update example in FTE
kkafar Aug 2, 2023
6d1fff5
Start implementing Fabric
kkafar Aug 2, 2023
a40aae1
Add sheetCustomDetents to Screen codegen spec
kkafar Aug 2, 2023
9672ec1
Set sheetCustomDetents only when new array is different
kkafar Aug 2, 2023
75fe630
TOREVERT: temporarily remove updating shadow node state after layouti…
kkafar Aug 3, 2023
5248114
Start playing around with new API in NativeStackView
kkafar Aug 3, 2023
38b2fe8
Filter numbers
kkafar Aug 4, 2023
94e2686
Stash changes
kkafar Aug 7, 2023
42080f0
Change `sheetAllowedDetents` prop type to `SheetDetentTypes | number[]`
kkafar Aug 8, 2023
6db2b0a
Refactor native code
kkafar Aug 8, 2023
664852f
Update example in TE
kkafar Aug 8, 2023
38851a9
Cleanup logic in v5 impl a bit
kkafar Aug 8, 2023
8512a04
Do not declare properties on category
kkafar Aug 9, 2023
33a192c
custom largest undimmed detent
kkafar Aug 9, 2023
dc3db10
Improve native logic
kkafar Aug 9, 2023
5c35d5d
Split sheetLargestUndimmedDetent into two props on JS side
kkafar Aug 9, 2023
fba211f
Update example in TE
kkafar Aug 9, 2023
e709618
Add docs
kkafar Aug 9, 2023
8a29c55
Missing newline
kkafar Aug 9, 2023
6393124
Adjust Fabric implementations
kkafar Aug 9, 2023
e297812
Add missing docs
kkafar Aug 9, 2023
96003ba
Cleanup tests
kkafar Aug 9, 2023
44946ca
Rename arrayFromVector method to NSNumberMutableArrayFromFloatVector
kkafar Aug 9, 2023
a5d2c94
Refactor detentsFromSnapPoints method
kkafar Aug 9, 2023
33049fc
Stubs for Android
kkafar Aug 9, 2023
8e8e6f0
Spelling 1
kkafar Aug 9, 2023
22fddb7
Spelling 2
kkafar Aug 9, 2023
6f992f0
Improve example logic a bit
kkafar Aug 11, 2023
c877a53
Remove RNS Array utility
kkafar Aug 22, 2023
a0a7912
Restore initial `updateBounds` implementation on Fabric
kkafar Aug 22, 2023
b4a81d9
fix(iOS): modal view flickering (#1870)
kkafar Nov 15, 2023
dd641ec
Patch clipping with displaylink & background colour
kkafar Dec 13, 2023
c27ab79
Temporarily set background on NativeStackView
kkafar Dec 13, 2023
a68b907
Properly pause/unpause the displaylink
kkafar Dec 13, 2023
3920f2a
Start cleaning up
kkafar Dec 13, 2023
8e27264
Cleanup updateBounds, animationDidStart, animationDidStop
kkafar Dec 13, 2023
a63d768
Update jotai
kkafar Dec 13, 2023
25a9f70
Remove setFrame & setBounds methods
kkafar Dec 13, 2023
09c1143
Unify example between platforms
kkafar Dec 13, 2023
0c334a2
Remove fixed backgorund style from screen component
kkafar Dec 14, 2023
aac2cee
Do not use custom shadow view (yet)
kkafar Dec 14, 2023
5f6e12f
Properly call updateFormSheetPresentationStyle
kkafar Dec 14, 2023
4bbed13
Cleanup updateFormSheetPresentation code & animate prop value changes
kkafar Dec 15, 2023
6653171
REVERT: Stash debug setup
kkafar Dec 15, 2023
d08aba3
Flickering sheet fix v30 (partial)
kkafar Jan 26, 2024
413832b
Try to fix flickering with setting full height for view when dragging up
kkafar Jan 30, 2024
15820e2
iOS code for avoiding reactSetFrame on screens subviews
kkafar Feb 1, 2024
ed028ad
JS code to avoid reactSetFrame on screens content when formSheet is i…
kkafar Feb 1, 2024
1c8805b
Update example in TE
kkafar Feb 1, 2024
b1fa392
Allow for passing screen style (naively, NEED TO FILTER THIS)
kkafar Feb 1, 2024
0ce92a7
Patch for scrollview
kkafar Feb 1, 2024
5530b16
Cleanup 1
kkafar Feb 2, 2024
b0f20fe
Cleanup 2
kkafar Feb 2, 2024
e0b76be
Cleanup 3
kkafar Feb 2, 2024
768c2ca
Add important comments on the reasons why the code looks like it does
kkafar Feb 2, 2024
7aa835f
Remove custom shadow view code
kkafar Feb 2, 2024
78510bd
Improve KVO observer handling to balance out add/remove calls
kkafar Feb 2, 2024
4d8ce7e
Update TE
kkafar Feb 5, 2024
0e2c6c5
Remove merge artifacts v1
kkafar Feb 19, 2024
406eed2
TOREVERT: podfile lock
kkafar Feb 19, 2024
19704b1
Cleanup example a bit
kkafar Feb 19, 2024
dd75129
TOREVERT: yarn lock
kkafar Feb 19, 2024
8e8b5b4
Rebase artifacts
kkafar Feb 19, 2024
839b9d4
TOREVERT: podfile lock
kkafar Feb 19, 2024
4808e49
prettier
kkafar Feb 19, 2024
e509aa6
Stub code for ScreenFooter on iOS
kkafar Feb 20, 2024
d07156a
Fix many issues with iOS implementation after merging with Android
kkafar Feb 20, 2024
6eb4a3b
Fix scrollview behaviour on iOS
kkafar Feb 20, 2024
edb04f4
Small fixes in example
kkafar Feb 20, 2024
96a0abf
Stash partial changes in iOS footer layout
kkafar Feb 21, 2024
6bfb629
Restore footer visibility
kkafar Feb 21, 2024
2d923e4
Restore code for measuring keyboard size
kkafar Feb 21, 2024
75e0af8
Make footer follow keyboard
kkafar Feb 22, 2024
acc12ea
Expose sheet elevation as a prop on Android
kkafar Feb 22, 2024
c99b184
Expose sheet elevation as a prop in JS
kkafar Feb 22, 2024
55776cd
Land support for fitToContents on Android
kkafar Feb 23, 2024
6022759
Update example
kkafar Feb 23, 2024
00aac51
Add stub ScreenContentWrapper for iOS
kkafar Feb 23, 2024
c3eb4a9
Add PoC of fitToContents for iOS (see commit details!)
kkafar Feb 24, 2024
b7c262e
Disable AppContainer only for formSheet stack presentation
kkafar Feb 24, 2024
dfc95cd
Set alpha for DimmingView to 0.15 to make it more iOS-like
kkafar Feb 26, 2024
5ce40cd
Accept only backgroundColor prop to screen style
kkafar Feb 26, 2024
91cea41
Eslint
kkafar Feb 26, 2024
05a5085
Remove fitsSystemWindows option
kkafar Feb 26, 2024
2f0da1e
Make sure sheetElevation prop value correctly falls through
kkafar Feb 26, 2024
74dc5b0
Small adjustments in Android code
kkafar Feb 27, 2024
3744929
Just a result of running format-android
kkafar Feb 27, 2024
b1533ec
Stash changes on Android keyboard behaviour
kkafar Feb 27, 2024
d85cb17
Implement hook that allows the screen underneath to fetch async data
kkafar Feb 28, 2024
4c6ecdc
Add sheetInitialDetentProp mock (see details) (Android & JS)
kkafar Mar 1, 2024
692904f
Stash keyboard behaviour chnanges
kkafar Mar 5, 2024
eb5986a
Fix flickering on modal hiding
kkafar Apr 4, 2024
e4ebf84
Remove debug bottom sheet offset fraction logging
kkafar Apr 4, 2024
e484e8a
Attempt to patch resolving window height
kkafar Apr 4, 2024
eddcd8e
Fix flickering on keyboard hide
kkafar Apr 5, 2024
06a2167
Debugging setup 2
kkafar Apr 15, 2024
c4183aa
TOREVERT: build RN from source in TE
kkafar Apr 17, 2024
8fc1ecb
Push stashed changes
kkafar May 2, 2024
127efbb
Try to patch types & update footer layout
kkafar May 2, 2024
4cad0c2
Try to patch types & update footer layout 2
kkafar May 2, 2024
03e0633
Make it work on stable states (no keyboard handling yet)
kkafar May 2, 2024
f81d1b9
Improve footer handling when sheet is dragged (no keybaord)
kkafar May 2, 2024
b286c48
Possibly fix disappearing footer
kkafar May 6, 2024
b8e25b9
Update example
kkafar May 6, 2024
7b7fb41
Improve keyboard handling
kkafar May 6, 2024
c3aafbd
Update example
kkafar May 6, 2024
03c056e
Merge branch 'main' into @kkafar/custom-detents-pg-merge-2
kkafar May 6, 2024
e6c880e
Add jotai to dependencies (yarn.lock)
kkafar May 6, 2024
ad68762
Add few comments in ScreenFooter
kkafar May 6, 2024
0dd9b50
Mitigate footer floating up when hidding sheet
kkafar May 6, 2024
85e509b
Fix gap between keyboard and footer
kkafar May 6, 2024
da15cae
Try to enforce keyboard hiding
kkafar May 6, 2024
48779d4
Patch bad behaviour on keyboard show with two states
kkafar May 7, 2024
6aae2ca
Comments in ScreenFooter
kkafar May 7, 2024
b316f26
Cleanup Screen a lot
kkafar May 7, 2024
cca0279
Next round of cleanup
kkafar May 7, 2024
c566288
Restore modal code & cleanup
kkafar May 8, 2024
626319b
Unify examples
kkafar May 8, 2024
40c1abd
Setup onSheetDetentChangedEvent on Android
kkafar May 8, 2024
28efb25
Emit events on sheet detent change
kkafar May 8, 2024
b4698d0
Report detent change on iOS correctly
kkafar May 8, 2024
dcb97da
Unify examples
kkafar May 8, 2024
a6ccf8d
Add isStable info to sheet detent change event
kkafar May 8, 2024
458af30
Fix conversions on Fabric iOS
kkafar May 8, 2024
d056286
Fix event emitting on paper
kkafar May 8, 2024
5f14195
Add dependency on jotai in FTE
kkafar May 8, 2024
809aee5
Update TE
kkafar May 8, 2024
ed74c9f
Attempt to fix iOS compilation
kkafar May 10, 2024
ffefdfc
Add buttom for showing another sheet from current sheet
kkafar May 13, 2024
9289f24
Merge branch 'main' into @kkafar/custom-detents-pg
kkafar May 15, 2024
c03decb
Add missing import
kkafar May 15, 2024
e8b6824
cleanup registered callback on fragment removal
kkafar May 21, 2024
99f95a6
Change computation of maxHeight for sheet with keyboard visible
kkafar May 22, 2024
50adfc4
Update example
kkafar May 22, 2024
255e4c5
Update android layout
kkafar May 22, 2024
42e86bb
Use InsetsObserverProxy in place of regular onApplyWindowInsetsListener
kkafar May 22, 2024
14d960d
Use rolling insets in observer proxy
kkafar May 22, 2024
9d2bcda
Fix jumping navigationBar inset on Android
kkafar May 27, 2024
04803c5
Stash debugging setup
kkafar May 27, 2024
e77d467
Update ModalScreenNativeComponent spec
kkafar May 30, 2024
82bc8e9
prettier in src/native-stack
kkafar May 30, 2024
7ff2f6f
Prettier in src/types.tsx
kkafar May 30, 2024
97ee80a
Update examples
kkafar May 30, 2024
cf8c18a
Remove unused implementation
kkafar Jun 6, 2024
f1e9ad4
Merge branch 'main' into @kkafar/custom-detents-pg
kkafar Jun 16, 2024
5f936b6
Bump spottless & ktlint as in main
kkafar Jun 20, 2024
4825e2c
fix: bump gradle wrapper version to 7.5.1 & not use app node_modules …
kkafar Jun 17, 2024
7772707
Modifications before ktlint finally works - 1
kkafar Jun 20, 2024
384f3e0
Format Android code before merging main
kkafar Jun 20, 2024
aaee08d
Merge branch 'main' into @kkafar/custom-detents-pg
kkafar Jun 20, 2024
c474285
Fix missing node_modules path
kkafar Jun 20, 2024
cebb527
Bump react-navigation submodule to the same commit it is on main
kkafar Jun 20, 2024
e53f30b
Revert "Fix missing node_modules path"
kkafar Jun 20, 2024
24083ee
Add project node_modules to list of additional node modules in metro …
kkafar Jun 20, 2024
9157e31
Initialize dummy layout only on new architecture
kkafar Jun 20, 2024
fbbbc6b
Remove unused import
kkafar Jun 20, 2024
2eb3cf5
Set Test1649 as default temporarily
kkafar Jun 20, 2024
f35131c
Fix unregistering footer on view removal
kkafar Jun 21, 2024
7c5a1d5
Reorganise Test1649
kkafar Jun 21, 2024
cc8b06c
Example cleanup - part 1
kkafar Jun 21, 2024
6d919cd
Example cleanup - part 2
kkafar Jun 22, 2024
f7c7a86
Example cleanup - part 3
kkafar Jun 22, 2024
dc832d3
Attempt to use v7 API
kkafar Jun 22, 2024
e58c0b3
Do not use static v7 API (not working ;D)
kkafar Jun 24, 2024
c71061c
Fixup route names in example
kkafar Jun 24, 2024
8ad9968
Add SheetUtils + cleanup
kkafar Jun 24, 2024
ede0b5b
Apply review comments, Android, part 1
kkafar Jun 24, 2024
3cdecb7
Apply review comments, Android, part 2
kkafar Jun 25, 2024
495b3eb
Remove some comments on iOS
kkafar Jun 25, 2024
6b541b4
Remove keyboard & footer related code on iOS (RNSScreen)
kkafar Jun 25, 2024
c8ee412
Review commentn - Android / iOS - part 3
kkafar Jun 26, 2024
19e863f
Comments in DimmingFragments & move more methods to sheet utils & upd…
kkafar Jun 28, 2024
16b4145
Merge branch 'main' into @kkafar/custom-detents-pg
kkafar Jul 8, 2024
9bb8322
Merge branch 'main' into @kkafar/custom-detents-pg
kkafar Jul 12, 2024
e7d6e3d
Add dependency on jotai in example apps
kkafar Jul 16, 2024
fd01f5b
Remove merge artifact
kkafar Jul 16, 2024
79a2484
Migrate to navigation event pipeline from direct callback
kkafar Jul 17, 2024
5964f4d
Make Fabic build on iOS
kkafar Jul 17, 2024
600f818
Emit sheetDetentChange event on Fabric + iOS
kkafar Jul 18, 2024
a74598a
Refactor code for calculating dynamic detent values
kkafar Jul 18, 2024
1f8f411
Remove ScreenScrollableContentWrapper
kkafar Jul 18, 2024
c301f2b
Start working towards fixing fitToContents option on Fabric
kkafar Jul 18, 2024
3af9813
Update native-stack event types
kkafar Jul 18, 2024
b1965b6
Make fitToContents work on Fabric + iOS
kkafar Jul 18, 2024
d9fbce7
Cleanup detentIndexFromDetentIdentifier function
kkafar Jul 18, 2024
44be1b5
Document & improve code for setting largest undimmed detent a bit
kkafar Jul 18, 2024
1a64f41
Port fix for scrollview to Fabric & more cleanup
kkafar Jul 18, 2024
fe036cd
Cleanup iOS code
kkafar Jul 19, 2024
7f99c80
Update example
kkafar Jul 19, 2024
15e096d
Merge branch 'main' into @kkafar/custom-detents-pg-merge-6
kkafar Aug 8, 2024
0b3053f
Update isTransparent method
kkafar Aug 8, 2024
e2c997a
Review updates 1
kkafar Aug 9, 2024
ddff79e
Review updates 2
kkafar Aug 9, 2024
c46bbbe
Review updates 3
kkafar Aug 9, 2024
38655c2
Patch for tvOS & visionOS
kkafar Aug 9, 2024
a8c27ec
Self review changes - Android
kkafar Aug 9, 2024
62dc767
Mark footer & screenStyle as unstable
kkafar Aug 10, 2024
adc0d61
Update native stack v5 docs
kkafar Aug 10, 2024
3f752db
Bump react-navigation with patch for detents
kkafar Aug 10, 2024
74ac52e
patch for linter
kkafar Aug 10, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"@react-navigation/native-stack": "link:../react-navigation/packages/native-stack/",
"@react-navigation/routers": "link:../react-navigation/packages/routers/",
"@react-navigation/stack": "link:../react-navigation/packages/stack/",
"jotai": "^2.9.0",
"nanoid": "^4.0.2",
"react": "18.2.0",
"react-native": "0.74.1",
Expand Down
16 changes: 16 additions & 0 deletions Example/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3397,6 +3397,7 @@ __metadata:
eslint: "npm:^8.19.0"
glob-to-regexp: "npm:^0.4.1"
jest: "npm:^29.6.3"
jotai: "npm:^2.9.0"
metro-react-native-babel-preset: "npm:^0.76.8"
nanoid: "npm:^4.0.2"
react: "npm:18.2.0"
Expand Down Expand Up @@ -7585,6 +7586,21 @@ __metadata:
languageName: node
linkType: hard

"jotai@npm:^2.9.0":
version: 2.9.0
resolution: "jotai@npm:2.9.0"
peerDependencies:
"@types/react": ">=17.0.0"
react: ">=17.0.0"
peerDependenciesMeta:
"@types/react":
optional: true
react:
optional: true
checksum: 10c0/c5551fb90933bcbc28b11cdb4af681398a12f8eb39a4a49568ec6ce5062c2257dd84a85cbfd7ec7d970d56dfa5023d16a0ec7056bc2697fdf9b3ec94da67c9d1
languageName: node
linkType: hard

"js-message@npm:1.0.7":
version: 1.0.7
resolution: "js-message@npm:1.0.7"
Expand Down
1 change: 1 addition & 0 deletions FabricExample/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"@react-navigation/native-stack": "link:../react-navigation/packages/native-stack/",
"@react-navigation/routers": "link:../react-navigation/packages/routers/",
"@react-navigation/stack": "link:../react-navigation/packages/stack/",
"jotai": "^2.9.0",
"nanoid": "^4.0.2",
"react": "18.2.0",
"react-native": "0.74.1",
Expand Down
16 changes: 16 additions & 0 deletions FabricExample/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3154,6 +3154,7 @@ __metadata:
babel-jest: "npm:^29.6.3"
eslint: "npm:^8.19.0"
jest: "npm:^29.6.3"
jotai: "npm:^2.9.0"
nanoid: "npm:^4.0.2"
prettier: "npm:2.8.8"
react: "npm:18.2.0"
Expand Down Expand Up @@ -6579,6 +6580,21 @@ __metadata:
languageName: node
linkType: hard

"jotai@npm:^2.9.0":
version: 2.9.0
resolution: "jotai@npm:2.9.0"
peerDependencies:
"@types/react": ">=17.0.0"
react: ">=17.0.0"
peerDependenciesMeta:
"@types/react":
optional: true
react:
optional: true
checksum: 10c0/c5551fb90933bcbc28b11cdb4af681398a12f8eb39a4a49568ec6ce5062c2257dd84a85cbfd7ec7d970d56dfa5023d16a0ec7056bc2697fdf9b3ec94da67c9d1
languageName: node
linkType: hard

"js-tokens@npm:^3.0.0 || ^4.0.0, js-tokens@npm:^4.0.0":
version: 4.0.0
resolution: "js-tokens@npm:4.0.0"
Expand Down
4 changes: 2 additions & 2 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,8 @@ repositories {

dependencies {
implementation 'com.facebook.react:react-native:+'
implementation 'androidx.appcompat:appcompat:1.4.2'
implementation 'androidx.fragment:fragment:1.3.6'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'androidx.fragment:fragment-ktx:1.6.1'
kkafar marked this conversation as resolved.
Show resolved Hide resolved
implementation 'androidx.coordinatorlayout:coordinatorlayout:1.2.0'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation 'com.google.android.material:material:1.6.1'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.swmansion.rnscreens

import android.view.View
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import java.lang.ref.WeakReference

object InsetsObserverProxy : OnApplyWindowInsetsListener {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class is needed, because sheets do need to listen for keyboard appearance. Each sheet does need to register a listener to decor view, while Android allows for only single listener! Thus I've introduced a proxy, who can aggregate listeners and fan out the events.

private val listeners: ArrayList<OnApplyWindowInsetsListener> = arrayListOf()
private var eventSourceView: WeakReference<View> = WeakReference(null)

// Please note semantics of this property. This is not `isRegistered`, because somebody, could unregister
// us, without our knowledge, e.g. reanimated or different 3rd party library. This holds only information
// whether this observer has been initially registered.
private var hasBeenRegistered: Boolean = false

private var shouldForwardInsetsToView = true

override fun onApplyWindowInsets(
v: View,
insets: WindowInsetsCompat,
): WindowInsetsCompat {
var rollingInsets =
if (shouldForwardInsetsToView) {
WindowInsetsCompat.toWindowInsetsCompat(v.onApplyWindowInsets(insets.toWindowInsets()), v)
} else {
insets
}

listeners.forEach {
rollingInsets = it.onApplyWindowInsets(v, insets)
}
return rollingInsets
}

fun addOnApplyWindowInsetsListener(listener: OnApplyWindowInsetsListener) {
listeners.add(listener)
}

fun removeOnApplyWindowInsetsListener(listener: OnApplyWindowInsetsListener) {
listeners.remove(listener)
}

fun registerOnView(view: View) {
if (!hasBeenRegistered) {
ViewCompat.setOnApplyWindowInsetsListener(view, this)
eventSourceView = WeakReference(view)
hasBeenRegistered = true
} else if (getObservedView() != null) {
if (getObservedView() != view) {
kkafar marked this conversation as resolved.
Show resolved Hide resolved
throw IllegalStateException(
"Attempt to register InsetsObserverProxy on $view while it has been already registered on ${getObservedView()}",
)
}
}
}

fun unregister() {
eventSourceView.get()?.takeIf { hasBeenRegistered }?.let {
ViewCompat.setOnApplyWindowInsetsListener(it, null)
}
}

fun getObservedView(): View? = eventSourceView.get()
kkafar marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ class RNScreensPackage : TurboReactPackage() {
ScreenStackHeaderConfigViewManager(),
ScreenStackHeaderSubviewManager(),
SearchBarManager(),
ScreenFooterManager(),
ScreenContentWrapperManager(),
)
}

Expand Down
90 changes: 87 additions & 3 deletions android/src/main/java/com/swmansion/rnscreens/Screen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,33 @@ import android.util.TypedValue
import android.view.ViewGroup
import android.view.WindowManager
import android.webkit.WebView
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.view.children
import androidx.fragment.app.Fragment
import com.facebook.react.bridge.GuardedRunnable
import com.facebook.react.bridge.ReactContext
import com.facebook.react.uimanager.PixelUtil
import com.facebook.react.uimanager.UIManagerHelper
import com.facebook.react.uimanager.UIManagerModule
import com.facebook.react.uimanager.events.EventDispatcher
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.swmansion.rnscreens.events.HeaderHeightChangeEvent
import com.swmansion.rnscreens.events.SheetDetentChangedEvent

@SuppressLint("ViewConstructor") // Only we construct this view, it is never inflated.
class Screen(
context: ReactContext?,
) : FabricEnabledViewGroup(context) {
val reactContext: ReactContext,
) : FabricEnabledViewGroup(reactContext),
ScreenContentWrapper.OnLayoutCallback {
val fragment: Fragment?
get() = fragmentWrapper?.fragment

val sheetBehavior: BottomSheetBehavior<Screen>?
get() = (layoutParams as? CoordinatorLayout.LayoutParams)?.behavior as? BottomSheetBehavior<Screen>
kkafar marked this conversation as resolved.
Show resolved Hide resolved

val reactEventDispatcher: EventDispatcher?
get() = UIManagerHelper.getEventDispatcherForReactTag(reactContext, id)

var fragmentWrapper: ScreenFragmentWrapper? = null
var container: ScreenContainer? = null
var activityState: ActivityState? = null
Expand All @@ -38,6 +49,33 @@ class Screen(
private set
var isStatusBarAnimated: Boolean? = null

// Props for controlling modal presentation
var isSheetGrabberVisible: Boolean = false
var sheetCornerRadius: Float = 0F
set(value) {
field = value
(fragment as? ScreenStackFragment)?.onSheetCornerRadiusChange()
}
var sheetExpandsWhenScrolledToEdge: Boolean = true

// We want to make sure here that at least one value is present in this array all the time.
// TODO: Model this with custom data structure to guarantee that this invariant is not violated.
var sheetDetents = ArrayList<Double>().apply { add(1.0) }
kkafar marked this conversation as resolved.
Show resolved Hide resolved
var sheetLargestUndimmedDetentIndex: Int = -1
var sheetInitialDetentIndex: Int = 0
var sheetClosesOnTouchOutside = true
var sheetElevation: Float = 24F
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why 24?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No real reason here. I decided that it just looks nice. When looking at design guides material components do use 1dp as default. We could align here, or just leave 24 cause it looks better (IMO) (you can actually see some elavation). What do you think?


var footer: ScreenFooter? = null
set(value) {
if (value == null && field != null) {
sheetBehavior?.let { field!!.unregisterWithSheetBehavior(it) }
} else if (value != null) {
sheetBehavior?.let { value.registerWithSheetBehavior(it) }
}
field = value
}

init {
// we set layout params as WindowManager.LayoutParams to workaround the issue with TextInputs
// not displaying modal menus (e.g., copy/paste or selection). The missing menus are due to the
Expand All @@ -52,6 +90,34 @@ class Screen(
layoutParams = WindowManager.LayoutParams(WindowManager.LayoutParams.TYPE_APPLICATION)
}

/**
* ScreenContentWrapper notifies us here on it's layout. It is essential for implementing
* `fitToContents` for formSheets, as this is first entry point where we can acquire
* height of our content.
*/
override fun onLayoutCallback(
changed: Boolean,
left: Int,
top: Int,
right: Int,
bottom: Int,
) {
val width = right - left
kkafar marked this conversation as resolved.
Show resolved Hide resolved
val height = bottom - top

if (sheetDetents.count() == 1 && sheetDetents.first() == SHEET_FIT_TO_CONTENTS) {
sheetBehavior?.let {
if (it.maxHeight != height) {
it.maxHeight = height
}
}
}
}

fun registerLayoutCallbackForWrapper(wrapper: ScreenContentWrapper) {
wrapper.delegate = this
}

override fun dispatchSaveInstanceState(container: SparseArray<Parcelable>) {
// do nothing, react native will keep the view hierarchy so no need to serialize/deserialize
// view's states. The side effect of restoring is that TextInput components would trigger
Expand Down Expand Up @@ -82,6 +148,7 @@ class Screen(
updateScreenSizePaper(width, height)
}

footer?.onParentLayout(changed, l, t, r, b, container!!.height)
notifyHeaderHeightChange(totalHeight)
}
}
Expand All @@ -90,7 +157,6 @@ class Screen(
width: Int,
height: Int,
) {
val reactContext = context as ReactContext
reactContext.runOnNativeModulesQueueThread(
object : GuardedRunnable(reactContext.exceptionHandler) {
override fun runGuarded() {
Expand Down Expand Up @@ -313,10 +379,19 @@ class Screen(
?.dispatchEvent(HeaderHeightChangeEvent(surfaceId, id, headerHeight))
}

internal fun emitOnSheetDetentChanged(
kkafar marked this conversation as resolved.
Show resolved Hide resolved
detentIndex: Int,
isStable: Boolean,
) {
val surfaceId = UIManagerHelper.getSurfaceId(reactContext)
reactEventDispatcher?.dispatchEvent(SheetDetentChangedEvent(surfaceId, id, detentIndex, isStable))
}

enum class StackPresentation {
PUSH,
MODAL,
TRANSPARENT_MODAL,
FORM_SHEET,
}

enum class StackAnimation {
Expand Down Expand Up @@ -352,4 +427,13 @@ class Screen(
NAVIGATION_BAR_TRANSLUCENT,
NAVIGATION_BAR_HIDDEN,
}

companion object {
const val TAG = "Screen"

/**
* This value describes value in sheet detents array that will be treated as `fitToContents` option.
*/
const val SHEET_FIT_TO_CONTENTS = -1.0
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,12 @@ open class ScreenContainer(
onScreenChanged()
}

open fun removeScreen(wrapper: ScreenFragmentWrapper) {
wrapper.screen.container = null
screenWrappers.remove(wrapper)
onScreenChanged()
kkafar marked this conversation as resolved.
Show resolved Hide resolved
}

open fun removeAllScreens() {
for (screenFragment in screenWrappers) {
screenFragment.screen.container = null
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.swmansion.rnscreens

import android.annotation.SuppressLint
import com.facebook.react.bridge.ReactContext
import com.facebook.react.views.view.ReactViewGroup

@SuppressLint("ViewConstructor")
class ScreenContentWrapper(
kkafar marked this conversation as resolved.
Show resolved Hide resolved
reactContext: ReactContext,
) : ReactViewGroup(reactContext) {
internal var delegate: OnLayoutCallback? = null

interface OnLayoutCallback {
fun onLayoutCallback(
changed: Boolean,
left: Int,
top: Int,
right: Int,
bottom: Int,
)
}

override fun onLayout(
changed: Boolean,
left: Int,
top: Int,
right: Int,
bottom: Int,
) {
delegate?.onLayoutCallback(changed, left, top, right, bottom)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.swmansion.rnscreens

import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.uimanager.ThemedReactContext
import com.facebook.react.uimanager.ViewGroupManager
import com.facebook.react.uimanager.ViewManagerDelegate
import com.facebook.react.viewmanagers.RNSScreenContentWrapperManagerDelegate
import com.facebook.react.viewmanagers.RNSScreenContentWrapperManagerInterface

@ReactModule(name = ScreenContentWrapperManager.REACT_CLASS)
class ScreenContentWrapperManager :
ViewGroupManager<ScreenContentWrapper>(),
RNSScreenContentWrapperManagerInterface<ScreenContentWrapper> {
private val delegate: ViewManagerDelegate<ScreenContentWrapper> = RNSScreenContentWrapperManagerDelegate(this)

companion object {
const val REACT_CLASS = "RNSScreenContentWrapper"
}

override fun getName(): String = REACT_CLASS

override fun createViewInstance(reactContext: ThemedReactContext): ScreenContentWrapper = ScreenContentWrapper(reactContext)

override fun getDelegate(): ViewManagerDelegate<ScreenContentWrapper>? = delegate
kkafar marked this conversation as resolved.
Show resolved Hide resolved
}
Loading