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

refact(Android): allow for different fragment types inside ScreenContainer #1887

Merged
merged 30 commits into from
Sep 15, 2023

Conversation

kkafar
Copy link
Member

@kkafar kkafar commented Sep 13, 2023

Description

This PR is laying out ground work under not-so-distant Android modal & bottom sheet implementation.

Currently ScreenContainer<T: ScreenFragment>: ViewGroup (and thus ScreenStack: ScreenContainer<ScreenStackFragment>) operates on ScreenFragment: Fragment objects, making it impossible to use any other Fragment subclass with the stack (only single inheritance is possible on JVM).

This PR changes the situation by introducing ScreenFragmentWrapper interface which both:

  1. holds the reference to underlaying Fragment
  2. provides additional API previously directly attached to the ScreenFragment

Also introduced ScreenStackFragmentWrapper extends ScreenFragmentWrapper with API previously attached to ScreenStackFragment.

Thereafter by implementing such interface by the fragment subclass itself we can have both of worlds:

  1. Customized fragment behaviour
  2. Implementation of all methods required for fragment<->container communication.

Disclaimer: I have decided to split "Android modals PR" into few smaller ones to reduce its size and complexity. I won't use "stack PR" technique to spare myself whole bunch of rebasing & conflict resolving.

Changes

  1. ScreenContainer is no longer parameterized with T: ScreenFragment. It uses ScreenFragmentWrapper as screen-primitve base type now.
  2. Our fragment types ScreenFragment & ScreenStackFragment now implement ScreenFragmentWrapper & ScreenStackFragmentWrapper interfaces respectively.
  3. ScreenContainer has access to the fragments it operates on (fragment API) via ScreenFragmentWrapper.fragment property.
  4. Our custom methods previously implemented directly on Fragment subclass are exposed via the new interfaces so ScreenContainer still has access to them.

Test code and steps to reproduce

See that test examples build & CI passes.

I did some manual testing in our example apps & didn't notice any regression.

Checklist

  • Ensured that CI passes

…d of being parameterized with T: ScreenFragment
@kkafar kkafar force-pushed the @kkafar/partial-android-refactor branch from 956bcbb to 277fbd9 Compare September 13, 2023 15:47
Copy link
Member Author

@kkafar kkafar left a comment

Choose a reason for hiding this comment

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

Few remarks for the future & reviewers

Comment on lines +1 to +7
package com.swmansion.rnscreens

import androidx.fragment.app.Fragment

interface FragmentHolder {
val fragment: Fragment
}
Copy link
Member Author

Choose a reason for hiding this comment

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

Decided to split this property to separate interface as this is the key idea behind this PR.

Also in the future I plan to make ScreenFragmentWrapper interfaces much more granular (split those into number of fine-grained interfaces.

@@ -16,9 +16,9 @@ import com.facebook.react.modules.core.ChoreographerCompat
import com.facebook.react.modules.core.ReactChoreographer
import com.swmansion.rnscreens.Screen.ActivityState

open class ScreenContainer<T : ScreenFragment>(context: Context?) : ViewGroup(context) {
open class ScreenContainer(context: Context?) : ViewGroup(context) {
Copy link
Member Author

Choose a reason for hiding this comment

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

ScreenContainer type is no longer parameterized with ScreenFragment type. Instead whole fragment type variance is handled by ScreenFragmentWrapper interface.

Comment on lines +28 to +35
open class ScreenFragment : Fragment, ScreenFragmentWrapper {
enum class ScreenLifecycleEvent {
Appear, WillAppear, Disappear, WillDisappear
}

override val fragment: Fragment
get() = this

Copy link
Member Author

Choose a reason for hiding this comment

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

Fragment subclass itself implements the new interface.

Thanks to fragment property:

override val fragment: Fragment
    get() = this

we can refer to this specific Fragment instance inside ScreenContainer.

Please note also that we are not creating any strong-reference cycle here as this property is computed on-the-fly.

@kkafar kkafar requested review from WoLewicki and tboba September 13, 2023 16:35
Copy link
Member

@WoLewicki WoLewicki left a comment

Choose a reason for hiding this comment

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

I added some comments, other than them, LGTM 🚀

@kkafar kkafar merged commit 84ed791 into main Sep 15, 2023
@kkafar kkafar deleted the @kkafar/partial-android-refactor branch September 15, 2023 10:55
renovate bot referenced this pull request in valora-inc/wallet Nov 2, 2023
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[react-native-screens](https://togithub.com/software-mansion/react-native-screens)
| [`^3.25.0` ->
`^3.26.0`](https://renovatebot.com/diffs/npm/react-native-screens/3.25.0/3.26.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/react-native-screens/3.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/react-native-screens/3.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/react-native-screens/3.25.0/3.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/react-native-screens/3.25.0/3.26.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>software-mansion/react-native-screens
(react-native-screens)</summary>

###
[`v3.26.0`](https://togithub.com/software-mansion/react-native-screens/releases/tag/3.26.0)

[Compare
Source](https://togithub.com/software-mansion/react-native-screens/compare/3.25.0...3.26.0)

Minor release adding new useAnimatedHeaderHeight and
useReanimatedHeaderHeight hooks, providing fixes for search bar and
introducing internal changes. *Please note that new hooks introduced in
this release are fully functional on Paper, on Fabric there are few edge
cases we are still working on*.

#### What's Changed

#### 🐛 Bug fixes

- Change implementation of `headerConfig` prop on Android by
[@&#8203;tboba](https://togithub.com/tboba) in
[https://github.com/software-mansion/react-native-screens/pull/1883](https://togithub.com/software-mansion/react-native-screens/pull/1883)
- Change elements visibility on search bar open by
[@&#8203;tboba](https://togithub.com/tboba) in
[https://github.com/software-mansion/react-native-screens/pull/1903](https://togithub.com/software-mansion/react-native-screens/pull/1903)
- Fix positioning of large header and search bar by
[@&#8203;tboba](https://togithub.com/tboba) in
[https://github.com/software-mansion/react-native-screens/pull/1895](https://togithub.com/software-mansion/react-native-screens/pull/1895)
- Change implementation of calculating status bar, refactor methods used
on header height change by [@&#8203;tboba](https://togithub.com/tboba)
in
[https://github.com/software-mansion/react-native-screens/pull/1917](https://togithub.com/software-mansion/react-native-screens/pull/1917)
- Fix calculating header height when changing status/action bar
visibility by [@&#8203;tboba](https://togithub.com/tboba) in
[https://github.com/software-mansion/react-native-screens/pull/1922](https://togithub.com/software-mansion/react-native-screens/pull/1922)
- Allow Reanimated Screen to check large header by
[@&#8203;tboba](https://togithub.com/tboba) in
[https://github.com/software-mansion/react-native-screens/pull/1915](https://togithub.com/software-mansion/react-native-screens/pull/1915)
- Fix issue when emptying nav stack on Windows by
[@&#8203;chrisglein](https://togithub.com/chrisglein) in
[https://github.com/software-mansion/react-native-screens/pull/1890](https://togithub.com/software-mansion/react-native-screens/pull/1890)
- Update podspec to use install_modules_dependencies by
[@&#8203;cipolleschi](https://togithub.com/cipolleschi) in
[https://github.com/software-mansion/react-native-screens/pull/1920](https://togithub.com/software-mansion/react-native-screens/pull/1920)
- Remove MaxPerm args from JVM invocation by
[@&#8203;kkafar](https://togithub.com/kkafar) in
[https://github.com/software-mansion/react-native-screens/pull/1888](https://togithub.com/software-mansion/react-native-screens/pull/1888)

#### 👍 Improvements

- Calculate values of useHeaderHeight natively by
[@&#8203;tboba](https://togithub.com/tboba) in
[https://github.com/software-mansion/react-native-screens/pull/1802](https://togithub.com/software-mansion/react-native-screens/pull/1802)
- Allow for different fragment types inside ScreenContainer by
[@&#8203;kkafar](https://togithub.com/kkafar) in
[https://github.com/software-mansion/react-native-screens/pull/1887](https://togithub.com/software-mansion/react-native-screens/pull/1887)
- Add focused states on page transitions by
[@&#8203;tboba](https://togithub.com/tboba) in
[https://github.com/software-mansion/react-native-screens/pull/1894](https://togithub.com/software-mansion/react-native-screens/pull/1894)

#### 🔢 Miscellaneous

- **Create FUNDING.yml by
[@&#8203;aleqsio](https://togithub.com/aleqsio) in
[https://github.com/software-mansion/react-native-screens/pull/1886](https://togithub.com/software-mansion/react-native-screens/pull/1886)**
- Migrate from deprecated `RCTEventEmitter` by
[@&#8203;kkafar](https://togithub.com/kkafar) in
[https://github.com/software-mansion/react-native-screens/pull/1867](https://togithub.com/software-mansion/react-native-screens/pull/1867)
- Use `require` syntax for resolution of all native components by
[@&#8203;kkafar](https://togithub.com/kkafar) in
[https://github.com/software-mansion/react-native-screens/pull/1909](https://togithub.com/software-mansion/react-native-screens/pull/1909)
- Run Android e2e with JDK 17 by
[@&#8203;kkafar](https://togithub.com/kkafar) in
[https://github.com/software-mansion/react-native-screens/pull/1892](https://togithub.com/software-mansion/react-native-screens/pull/1892)
- Put timelimit on execution of each workflow by
[@&#8203;kkafar](https://togithub.com/kkafar) in
[https://github.com/software-mansion/react-native-screens/pull/1893](https://togithub.com/software-mansion/react-native-screens/pull/1893)
- Trigger e2e tests on JS-only changes by
[@&#8203;kkafar](https://togithub.com/kkafar) in
[https://github.com/software-mansion/react-native-screens/pull/1910](https://togithub.com/software-mansion/react-native-screens/pull/1910)
- Update deprecated expo install instructions to `npx expo install` by
[@&#8203;GabrieldosSantosOliveira](https://togithub.com/GabrieldosSantosOliveira)
in
[https://github.com/software-mansion/react-native-screens/pull/1899](https://togithub.com/software-mansion/react-native-screens/pull/1899)
- Bump activesupport from 6.1.7.3 to 7.0.7.2 in /TestsExample by
[@&#8203;dependabot](https://togithub.com/dependabot) in
[https://github.com/software-mansion/react-native-screens/pull/1877](https://togithub.com/software-mansion/react-native-screens/pull/1877)
- Update deps & RN in example apps after release by
[@&#8203;kkafar](https://togithub.com/kkafar) in
[https://github.com/software-mansion/react-native-screens/pull/1878](https://togithub.com/software-mansion/react-native-screens/pull/1878)
- Migrate `Example` app & e2e tests to RN 0.72.4 by
[@&#8203;kkafar](https://togithub.com/kkafar) in
[https://github.com/software-mansion/react-native-screens/pull/1880](https://togithub.com/software-mansion/react-native-screens/pull/1880)
- Bump library deps to recent versions (including RN) by
[@&#8203;kkafar](https://togithub.com/kkafar) in
[https://github.com/software-mansion/react-native-screens/pull/1881](https://togithub.com/software-mansion/react-native-screens/pull/1881)
- Bump library native Android deps & config by
[@&#8203;kkafar](https://togithub.com/kkafar) in
[https://github.com/software-mansion/react-native-screens/pull/1891](https://togithub.com/software-mansion/react-native-screens/pull/1891)

#### New Contributors

- [@&#8203;chrisglein](https://togithub.com/chrisglein) made their first
contribution in
[https://github.com/software-mansion/react-native-screens/pull/1890](https://togithub.com/software-mansion/react-native-screens/pull/1890)
-
[@&#8203;GabrieldosSantosOliveira](https://togithub.com/GabrieldosSantosOliveira)
made their first contribution in
[https://github.com/software-mansion/react-native-screens/pull/1899](https://togithub.com/software-mansion/react-native-screens/pull/1899)
- [@&#8203;cipolleschi](https://togithub.com/cipolleschi) made their
first contribution in
[https://github.com/software-mansion/react-native-screens/pull/1920](https://togithub.com/software-mansion/react-native-screens/pull/1920)

**Full Changelog**:
software-mansion/react-native-screens@3.25.0...3.26.0

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 5pm,every weekend" in timezone
America/Los_Angeles, Automerge - "after 5pm,every weekend" in timezone
America/Los_Angeles.

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log
[here](https://developer.mend.io/github/valora-inc/wallet).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4xOS4yIiwidXBkYXRlZEluVmVyIjoiMzcuMTkuMiIsInRhcmdldEJyYW5jaCI6Im1haW4ifQ==-->

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: valora-bot <[email protected]>
Co-authored-by: Silas Boyd-Wickizer <[email protected]>
Co-authored-by: Silas Boyd-Wickizer <[email protected]>
ja1ns pushed a commit to WiseOwlTech/react-native-screens that referenced this pull request Oct 9, 2024
…ainer (software-mansion#1887)

## Description

This PR is laying out ground work under not-so-distant Android modal &
bottom sheet implementation.

Currently `ScreenContainer<T: ScreenFragment>: ViewGroup` (and thus
`ScreenStack: ScreenContainer<ScreenStackFragment>`) operates on
`ScreenFragment: Fragment` objects, making it impossible to use any
other `Fragment` subclass with the stack (only single inheritance is
possible on JVM).

This PR changes the situation by introducing `ScreenFragmentWrapper`
interface which both:

1. holds the reference to underlaying `Fragment`
2. provides additional API previously directly attached to the
`ScreenFragment`

Also introduced `ScreenStackFragmentWrapper` extends
`ScreenFragmentWrapper` with API previously attached to
`ScreenStackFragment`.

Thereafter by implementing such interface by the fragment subclass
itself we can have both of worlds:

1. Customized fragment behaviour
2. Implementation of all methods required for fragment<->container
communication.

Disclaimer: *I have decided to split "Android modals PR" into few
smaller ones to reduce its size and complexity. I won't use "stack PR"
technique to spare myself whole bunch of rebasing & conflict resolving.*

## Changes

1. `ScreenContainer` is no longer parameterized with `T:
ScreenFragment`. It uses `ScreenFragmentWrapper` as screen-primitve base
type now.
2. Our fragment types `ScreenFragment` & `ScreenStackFragment` now
implement `ScreenFragmentWrapper` & `ScreenStackFragmentWrapper`
interfaces respectively.
3. `ScreenContainer` has access to the fragments it operates on
(fragment API) via `ScreenFragmentWrapper.fragment` property.
4. Our custom methods previously implemented directly on `Fragment`
subclass are exposed via the new interfaces so `ScreenContainer` still
has access to them.

## Test code and steps to reproduce

See that test examples build & CI passes.

I did some manual testing in our example apps & didn't notice any
regression.

## Checklist

- [x] Ensured that CI passes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants