PavelPZ / riverpod_navigator

Simple but powerfull Flutter navigation with riverpod and Navigator 2.0
MIT License
27 stars 3 forks source link

Deeplink #20

Open Vermid opened 2 years ago

Vermid commented 2 years ago

Hello

My app consists of two main navigation “paths”, one for unauthenticated users (which includes the login screen, registration screen, etc.) and one for authenticated users (which includes content based on a Tabbar-navigation and is therefore a nested navigation).

Based on that, I have created the following routes:

AppNavigator: [landingPage, register, login, tabBar] AppNavigator.forPrivate: [home, details] -> Tab_1 AppNavigator.forProfile: [profile, editProfile] -> Tab_2 AppNavigator.forMore: [more, settings] -> Tab_3

I’m now trying to add Deeplinking into the app. However, any time I attempt to add a route (e.g. ‘profile’ or ‘editProfile’) to the AppNavigator, the Navigator pushes the route onto the AppNavigator stack and not onto the nested stack. For example, trying to parse with the AppNavigator.forMore(navigator.ref).pathParser.fromUrl and setting the route via AppNavigator.forMore(navigator.ref).routerDelegate.setNewRoutePath(segments) pushes the new screen onto he current stack instead of onto the AppNavigator.forMore stack.

My Deeplink follow the following scheme: deeplink://example_app/tabbar/profile/editProfile

What I want to archive is this:

User presses the Deeplink -> App Opens -> appNavigationLogic checks loginStatus. If the user is logged in, navigate to TabBar, select the correct tab and load the page. If not, redirect to login.

I’ve followed the examples in https://github.com/PavelPZ/riverpod_navigator/blob/main/features/login_flow.md and https://github.com/PavelPZ/riverpod_navigator/blob/main/features/nested_navigation.md and tried to combine them, but unfortunately, I’m now stuck with the aforementioned problems.

Any advice would be greatly appreciated, thanks!

PavelPZ commented 2 years ago

Sorry, this package does not support deeplink for nested navigators.

Your address (deeplink://example_app/tabbar/profile/editProfile) is not complete, it should contain the segments for all Tabs, something like

deeplink://example_app/tabbar/(profile*:editProfile/xxx/xxx,more:settings/xxx/xxx,private:home/xxx)

where * indicates the current Tab.

This is not impossible but it is a very unusual navigation solution.

PavelPZ commented 2 years ago

However, if it is only a matter of selecting the correct tab using deeplink, this can be addressed in the main navigator by e.g.

deeplink://example_app/home;tab=profile

Vermid commented 2 years ago

Thank you for the fast answer's. I'll try them out and tell how it went.

Vermid commented 2 years ago

I'm not sure how to change the AppNavigator that he can handle a deeplink like this: deeplink://example_app/tabbar/(profile*:editProfile/xxx/xxx,more:settings/xxx/xxx,private:home/xxx).

Or do you mean that the TabBarSegment should decode the last part "(profile*:editProfile/xxx/xxx,more:settings/xxx/xxx,private:home/xxx)"?

PavelPZ commented 2 years ago

Have a look at tab_init.dart.

  1. HomeSegment has three props for configuring the Tab index and nested navigator's stacks.
  2. HomeScreen propagate these props to initialIndex and to the nested provider scope (e.g. riverpodNavigatorOverrides(morePath ?? [MoreSegment()], ...
  3. I have prepared NestedNavigator.getDeepUrl method: it can give you an idea how to encode typed segments into a deeplink://...string....
PavelPZ commented 2 years ago

I use Remi Rousselet functional_widget package to generate Widgets from the functions

Vermid commented 2 years ago

Thank you for the tab_ini.dart example. It helped me a lot.

I can now open the deeplink and navigate to the wanted Tab and push the route.

But if the user select a different Tab and try to open the App again with the deeplink then the navigation won't change the Tab. Do you have any advice how this could be solved without changing the deeplink?

PavelPZ commented 2 years ago

You need to store deeplink URL in SharedPreferences (see modified example).

I fixed a small bug (upgrade to version 1.0.6).

I used Remi Rousselet flutter_hooks (useSingleTickerProvider and useMemoized) in modified example for listening to TabBar index change.

Vermid commented 2 years ago

Thank you for the nestedUrl example. I think that the navigatorProvider had a bug. Because when setting the initPathAsString the navigatorProvider load the segment that is inside the initPath and not the segments that are inside the initPathAsString .

Also I'm not sure if this solves the problem that the same deeplink can't be used multiple times.

PavelPZ commented 2 years ago

riverpod_navigator ^1.0.7 solves your problem.

What do you mean by Also I'm not sure if this solves the problem that the same deeplink can't be used multiple times.?

Vermid commented 2 years ago

Thank you for the update the initPathAsString works.

Assume you get an E-Mail that contains a deeplink. Now when you click on the deeplink the Navigator will load the TabBarSegment and set the path (more/settings/etc). But when you click on the same deeplink again, then the Navigator won't rebuild the TabBarSegment because it is identical to the last segment on the NavigationStack, therefore the TabBarSegment won't change the TabIndex and the path.

PavelPZ commented 2 years ago

I don't like the initPathAsString solution. This is because the main navigator does not know nested routes (and nested TypedSegments). Nobody is using this option yet, so I'm considering the breaking change: registration of all routes globally.

Vermid commented 2 years ago

Hi PavelPZ, I want to ask you kindly, if you have any updates for this issue.

PavelPZ commented 2 years ago

Hi @Vermid,

see tab_init2.dart example

Vermid commented 2 years ago

Thank you for the example. I've implemented it and the deeplink can be used multiple times now.

But when calling the changeMorePath or changeProfilePath you push the segment onto the current stack and because of that canPop is false and the AppBar does not show the backbutton.

And when changing the tab with changeTab you also push the segment onto the current stack which causes the TabBar to be rebuilt. I would like the TabBar to be persistent when changing tabs. Do you think there is way to archive this?