The above situation may happen when grandparent is unmounted from react. In such a case children are not removed from non direct ancestors but still get invalidated.
Reverting that change as it turned out not to be necessary. At the moment of attaching screen we already have the frame set on the child VC. Updating it there again was cauinsg some visual glitches with old react-navigation screen container based implementation.
After exaiming memory graph it turned out that screens for which we access presentationController property ends up leaking, likely because of some issue in UIKit. This turns out not to affect screens that are actually being presented as modals (when presentationController is required). This change updates presentation mode setter to avoid accessing presentationController for push screens and also warns if the prop ever switches from modal to push (in which case we cannot reverse the leak source).
This change fixes issue reported in #54. The issue was caused by the fragment transaction that run past the moment when container view is detached. This could happen when container is quickly added and removed as fragment transactions sometimes may take long time to execute. Unfortunately enqueued fragment transactions cannot be cancelled, so to make sure that transaction isn't run past container unmount we call executePendingTransactions right before the screen is detached.
This chnage fixes the way we'd managed parent<>child VC relation. With this change in we hook child VC to parent in didMoveToWindow to match Stack behavior. We also wait with updating child view frame untill the child screen is attached. Finally we utilize RCTInvalidating interface to spot moments when screen controller is unmounted from react such that we can break reference cycle between screen and screen view (we don't do it in invalidate directly as sometimes we need to wait till transition end).
This change fixes logic that we run when stack is moved to a window. Before we'd first attach stack to parent VC and then run updateContainer. This could've led to a buggy behavior in case the stack is mounted within other stack that is running a transition (e.g. dismissing a modal). In such a case setting initial push VCs would fail (because UIKit does not allow push to be modified while transitioning). Because of that stack would initialize with the dummy VC and the initial VC would get added to dismissedScreens (which is another side effect of the logic that keeps track of dismissed screens).
The fix was to add call to updateContainer before VC is added to parent. This makes it possible for push screens to be properly initialized (since VC is not yet added it does not know its parent is transitioning). Then, since updating modals handles gracefully the case when modals cannot be shown (and they wont be shown unless added to parent VC) we can safely run updateContainer yet another time after the VC is added to parent.
Howeer after the above fix was applied we observed another issue that was due to an invalida appear/disappear event management within view controllers. To address that fix we no longer allow navigaton VC's view to be added to the container view unless it starts transition to parent view controller. We also fixed missing calls to super in willMoveToParentViewController callback of RNSScreen controller and also fixed view reference management withing RNScreen to keep views as weak references while the view is not attached. The latter fixes the problem with screen view leaking under certain conditions.
This change fixes the problem of container view controllers not being detached properly from its parent container VC. We fix this by detaching VC from didMoveToWindow. On top of that we also added a check to ensure the update of containers won't run unless JS batch is complete. This is to prevent partially updated headers.
Since the config is only updated in the HeaderConfig view it will not get executed for stacks with no header. This fixes it by setting the prop directly in the Screen when the gestureEnabled prop is set.
Fixes#343
This change filters out non ScreenFragment instances when iterating through the list of installed fragments. The reason why other fragments can be added to the manager is that some libraries (e.g. glide) use fragment manager to store screen local data and attach to the screen lifecycle.
This change addresses two problem. First was related to header subviews that were not laid out properly before we installed them in the header. This was causing occasional bugs where the header subviews were misplaced. The fix was to enforce container update run after layout is done (we enqueue update on ui thread directly from didUpdateReactSubviews).
The second problem was related to UINavController nlifecycle methods not triggering correctly in case when updates are being made to the nav controller which isn't mounted. Previously we fixed similar issue for modal controllers where because of the fact container wasn't mounted we couldn't run modal screen updates. With push controllers the problem is very similar however the VC do update just stop getting proper lifecycle updates and warning "Unbalanced calls to begin/end appearance transitions" is displayed. The fix was similar as in the modal case, that is, we wait until container is installed in window.
This update changes the logic of how we present modals. Previously presentedModals array could get out of sync with the actual app state because in case when parent VC is not mounted, presenting a modal would silently fail. In order to handle that we added additional update trigger from where the screen stack is mounted to a window. Second change that we added here addresses a problem of concurrent calls to update modals. As we cannot update presentedModals array synchrounously (all presentation callbacks are async even when no animation is involved), we need to block future updates unless the previous batch of updates is done. To do that we added a flag that prevents method re-entry. The flag is reset when all the presentation animations are over.
After fragment library upgrade we observed a regression caused by the screens that we navigate back to being invisible. This turned out to be a problem with view restore mechanism that we don't rely on. On native android the detached view state is dumped and then view's visibility is change to GONE after screen animated away. However, since we don't rely on view state restore and instead just reuse the whole view object, when navigating back we'd move to a view with visibility set to GONE. This change workarounds this problem in the method responsible for recycling views where we reset visibility flag back to VISIBLE.
Allows you to choose additional modal presentation styles for iOS. It adds the ability to force a full screen modal or choose a "form sheet" style. This only affects iOS.
The previous condition was broken as under certain circumstances we would've receive a setReactFrame with no active screen rendered to only get the screen activate in a while. This resulted in the view dimention not being properly updated. This diff changes the condition and verifies whether a screen is mounted under UINavController or not. When not, we assume it is mounted under regular screen container and allow the frame to be adjusted from react.
This change makes navigation screen wrapper to set absolute fill style for screen items wrendered within native stack. We obvserved an issue where screens are rendered with a versy small height when the initial style is not set properly on iOS. This change makes the screen default to full screen and only then be resized down in case navigation bars are set.
This change fixes two crashes related to fragment library. The first issue was a crash caused by return transaction started while the previous transaction was ongoing (e.g., quickly adding new screen on top of the stack and immediately dismissing it). The main fix was applied in the fragment library and therefore as a part of this change we update the dependency to fragment:1.2.1 which is the current latest stable version. As a result of the fragment library change we started observing other issue. The second issue was caused by the fact that under certain circumstances the view associated with a fragment couldn't been added despite it still being attached to a parent. This was resulting in a crash. This change adds a cleanup code that properly detaches the view: we do it in onCreateView but also when the fragment destroys its view (in onViewDestroy callback). The latter is necessary because when fragments are restored the order of onCreateView calls is reversed which causes inner views to attach despite their fragment managers not being initialized.
This change adds new event that gets dispatched from native stack when screen transitioning is finished.
The new event is used by react-navigation to update the library internal state that the triggered action has been finished. Previously we were relying solely on onAppear and onDisappear events, however those does not get triggered when new iOS 13 modals are used or when transparent modals are displayed. This is because with transparent modals the view below is still visible. We therefore needed another way of notifying the library that screen transition have finished despite the fact that disappear event couldn't be triggered.
As a part of this change I also refactored invalid ref cycle-break code on iOS which was ought to remove reference cycle between view and view controller. This code have been moved to viewWillDisappear callback.
Also on Android part small refactoring has been done and we removed the necessity to keep mActiveScreens array which was occasionally getting out of sync with the list of active fragments.
The library would crash when the `mTopScreen` instance variable is null. This change checkes if it null before calling the `getScreen()` method. It also marks the method as having a nullable return value. The only place this method is used is already setup to handle `null` responses.
This fixes a problem when image attribute of image view would get reset and we wouldn't be able to access it even in release mode. This could happen when the app is backgrounded as at that point image views release their resources. Another case that was quite frequent was that the image would start loading before the image view frame was properly set. The solution is to trigger image reload in cases when image is missing and to force the image view frame to match the size of an image.
This change also fixes a problem on iOS pre 13 where we were updating back indicator inside of the method which would run during the transition. Turns out updating this property isn't supported during animation and so we moved it out such that it is updated before the transition starts.
We currently cannot take any adventage of saving and restoring fragment state because view hierarchy of the unmounted fragment is retained by RN core anyways. Skipping sabe/restore will allow us to avoid unnecessary serializiation/deserialization of the view hierarchy but will also help circumvent some bugs which comes from the side effects of restoring. One of the bugs have been reported in #162 and in that particular case restoring result in InputText change event being triggered with stale value. This was happening in the situation when we were going back to a screen with InputText component.
This change fixes the problem with missing text selection modals when text input component is rendered under screen container. The reason turned out to be a problem with Android TextView implementation which expect the component to be attached to window at the moment when layout happens (see Editor.java#prepareCursorControllers and TextView.java$makeNewLayout). Apparently, within screens container layout will happen before the component of a given screen are attached (because attaching is managed by the fragment manager which delays the moment at which the screen is attached). As a result the textView component does not get a chance to fetch proper window layout params such that it can tell whether it should support selection mode or not. We workaround this issue by providing window layout params directly from Screen class which is used instead of the DecorWindow in case TextView is not yet attached (it searches for the top-most parent when not attached).
This change fixes a problem with native stack on Android where we'd display a sw back button on screens that are nested stack navigatodespite the fact those screens were the initial screens in the whole container stack. In #306 we introuced a change that would allow for displaying sw back in nested stacks, however that change did not handle the case where screen is a root screen of a container that is nested and placed as an initial screen in another container.
This change allows for root screens of nested stack navigators on Android to display back button in the navigation bar. Navigating back is still possible using hw back because of the way hw back is handled by nested fragment containers. However, despite hw back functioning properly, before this change we would not allow for the soft back button to be rendered in the header. This change adds this possibility to keep software back consistent with the hw back button functionality. This behavior can still be disabled/adjusted using hideBackButton property of the header config component.
This change fixes the problem when navigation bar would not get properly updated for modal transitions. The problem was due to the fact that for modal transitions the animateAlongsideTransition block was not getting trriggered. This was noticeable on iOS versions before 13, as starting with iOS 13 we can use NavigationItem to specify most of the nav bar customization. On older versions however it is required that for a lot of navbar settings we need to update them durion animation. This wasn't the case for navigators presented modally. In case we show a modal we can update nav bar without animation because it actually renders a completely new navigation bar which isn't shared.
On top of that this PR fixes the problem with bridge not being set for header subviews.
This change removes ScreenStackHeaderTitleView component and code that used to handle title view scaling. There were multiple issues related to scaling toolbar title views and it is not a priority at the moment to us to work on addressing those. The most frequent usecase is to put a fixed-dimensions view (e.g. logo or text) which can be now handled w/o this extra code.
This change fixes a bug when header property updates happens during or at the same time of stack transition, e.g., when we both pop a screen and change parent VC header properties. When this happens we trigger header update code, but because we used to compare current VC to visibleViewController, which at that moment points to controller that we are transitioning away from, the update would've been prevented. With this change instead of using visibleViewController to compare with updated VC, we check if there is transition happening (using transitransitionCoordinator property), and in such case we use topController which points to the controller we are transitioning to.