[android] convert place page to fragment #4174

Merged
arnaudvergnet merged 30 commits from pp-refactor into master 2023-02-18 19:55:12 +00:00
arnaudvergnet commented 2022-12-31 15:54:45 +00:00 (Migrated from github.com)

Hello and happy new year (well nearly)! I am back with some more Android refactoring.

This PR aims to make the place page handling easier by moving the content and the buttons in their own fragments.

As a result, the place page view and buttons have less coupling with the rest of the app, making it easier to debug and maintain. Fragments are independent and have their own lifecycle methods. Interaction with those fragments is done using a ViewModel storing the pp buttons and map object to show. This viewmodel could be reused by other UI elements (such as the fullscreen compass view) if those were converted to fragment as well.

Thanks to this change, the app could gain performance/battery improvements as these UI elements are only rendered when needed.

The only UX change is concerning the place page buttons: I removed the phone number button as I always felt it was unnecessary and made buttons placement inconsistent (see #3157). I also removed some logic to change the button order depending on some complexe but IMO useless condition. Now the buttons placement is a lot easier to predict and understand.

The PlacePageButtons class has been fully rewritten. The PlacePageControllerComposite stuff has been fully removed as it added useless complexity. Instead the PlacePageController handles directly the place page. The PlacePageView has only been converted to a fragment without a full rewrite as it is way too complexe. I'll still try to simplify it when continuing work on this PR. I also want to convert the fullscreen compass view to a fragment so it uses the same viewmodel as the place page.

This is still a work in progress as I still have some unanswered questions.

  • Should we keep the place page fragment independent of the bottom sheet? For now the fragment is rendered inside a bottomsheet view. This makes it possible to reuse this fragment in another container for the tablet mode for example.
    • Edit: I think we should keep this approach, especially if we wrap both fragments in a parent fragment. This does not make the code much more complex and offers more modularity.
  • Should we create a fragment to hold both the place page view and the place page buttons fragments?
    • Edit: I think wrapping both in a fragment would be good as it would avoid making the place page callbacks go up to the main activity. This fragment could replace the current controller.
  • Should we split the place page view in smaller fragments? (eg: one for the bookmarks, one for the social links, ...). The current PlacePageView class is 1.5k lines long, which is too much for my liking.
    • Edit: Creating a fragment for the bookmarks, opening hours, phone, social, Wikipedia would make the codebase more manageable as well as reduce the impact of creating a place page with not much information.
  • Is creating the fragment when the user clicks on a feature too slow?
    • Edit: From my limited testing, it does not seem to impact much performance. I think it could even be improved when more sections are migrated to child fragments.

I'll try to find answers to those questions but in the meantime, feel free to help me test this PR and give your feedback!

Hello and happy new year (well nearly)! I am back with some more Android refactoring. This PR aims to make the place page handling easier by moving the content and the buttons in their own fragments. As a result, the place page view and buttons have less coupling with the rest of the app, making it easier to debug and maintain. Fragments are independent and have their own lifecycle methods. Interaction with those fragments is done using a ViewModel storing the pp buttons and map object to show. This viewmodel could be reused by other UI elements (such as the fullscreen compass view) if those were converted to fragment as well. Thanks to this change, the app could gain performance/battery improvements as these UI elements are only rendered when needed. **The only UX change is concerning the place page buttons**: I removed the phone number button as I always felt it was unnecessary and made buttons placement inconsistent (see #3157). I also removed some logic to change the button order depending on some complexe but IMO useless condition. Now the buttons placement is a lot easier to predict and understand. The `PlacePageButtons` class has been fully rewritten. The `PlacePageControllerComposite` stuff has been fully removed as it added useless complexity. Instead the `PlacePageController` handles directly the place page. The `PlacePageView` has only been converted to a fragment without a full rewrite as it is way too complexe. I'll still try to simplify it when continuing work on this PR. I also want to convert the fullscreen compass view to a fragment so it uses the same viewmodel as the place page. **This is still a work in progress as I still have some unanswered questions.** - Should we keep the place page fragment independent of the bottom sheet? For now the fragment is rendered inside a bottomsheet view. This makes it possible to reuse this fragment in another container for the tablet mode for example. - **Edit:** I think we should keep this approach, especially if we wrap both fragments in a parent fragment. This does not make the code much more complex and offers more modularity. - Should we create a fragment to hold both the place page view and the place page buttons fragments? - **Edit:** I think wrapping both in a fragment would be good as it would avoid making the place page callbacks go up to the main activity. This fragment could replace the current controller. - Should we split the place page view in smaller fragments? (eg: one for the bookmarks, one for the social links, ...). The current PlacePageView class is 1.5k lines long, which is too much for my liking. - **Edit:** Creating a fragment for the bookmarks, opening hours, phone, social, Wikipedia would make the codebase more manageable as well as reduce the impact of creating a place page with not much information. - Is creating the fragment when the user clicks on a feature too slow? - **Edit:** From my limited testing, it does not seem to impact much performance. I think it could even be improved when more sections are migrated to child fragments. I'll try to find answers to those questions but in the meantime, feel free to help me test this PR and give your feedback!
vng (Migrated from github.com) reviewed 2022-12-31 15:54:45 +00:00
biodranik commented 2022-12-31 18:40:03 +00:00 (Migrated from github.com)

Thank you, Arnaud! That's a great NY gift )

I and @rtsisyk comment later on your questions. At the moment the most important issue to fix is a lazy WebView initialization. We have a lot of strange crashes now when WebView is initialized at the app startup.

Regarding the recreation performance on POI selection, it would be easier/better to test on some low end device. I have Android 5 for example.

Thank you, Arnaud! That's a great NY gift ) I and @rtsisyk comment later on your questions. At the moment the most important issue to fix is a lazy WebView initialization. We have a lot of strange crashes now when WebView is initialized at the app startup. Regarding the recreation performance on POI selection, it would be easier/better to test on some low end device. I have Android 5 for example.
arnaudvergnet commented 2023-01-01 11:41:34 +00:00 (Migrated from github.com)

Regarding the webview, I can look into it and maybe move it to its own fragment so it is only initialized when needed.

For the performance, I do not have low end devices at hand, but I can try to compare the the master branch to see if we have any noticeable difference using the emulator.

Regarding the webview, I can look into it and maybe move it to its own fragment so it is only initialized when needed. For the performance, I do not have low end devices at hand, but I can try to compare the the master branch to see if we have any noticeable difference using the emulator.
Jean-BaptisteC commented 2023-01-01 12:18:09 +00:00 (Migrated from github.com)

Thanks, i have started to test on my Pixel 6:

  • I have see weird bug, when i select POI -> OM show place page in full size (top of place page + GPS coordinates and editor link) during 1 second before to show place page (only top of place page) on POI without informations (except name and adress)
    Examples:
  • Parking, picnic table, ...

I can doing video if necessary

Happy new year 🎉

Thanks, i have started to test on my Pixel 6: - I have see weird bug, when i select POI -> OM show place page in full size (top of place page + GPS coordinates and editor link) during 1 second before to show place page (only top of place page) on POI without informations (except name and adress) Examples: - Parking, picnic table, ... I can doing video if necessary Happy new year 🎉
arnaudvergnet commented 2023-01-01 17:30:36 +00:00 (Migrated from github.com)

I can't seem to reproduce your issue, could you share a video please?

I can't seem to reproduce your issue, could you share a video please?
Jean-BaptisteC commented 2023-01-01 17:44:27 +00:00 (Migrated from github.com)

https://user-images.githubusercontent.com/87148630/210180010-6ad25c98-b5b1-4a0b-b462-e922d2797d04.mp4

Other thing to reproduce, you need to have no POI selected, when you select POI

https://user-images.githubusercontent.com/87148630/210180010-6ad25c98-b5b1-4a0b-b462-e922d2797d04.mp4 Other thing to reproduce, you need to have no POI selected, when you select POI
arnaudvergnet commented 2023-01-01 18:29:48 +00:00 (Migrated from github.com)

Oh yes this bug I noticed and I am working on a fix. The bottom sheet remembers the last peek height from the previous content when opening. So if you open then close the place page for POIs with different preview sizes, you will see this bug. I have to find a way to pass the new peek height before it opens.

Oh yes this bug I noticed and I am working on a fix. The bottom sheet remembers the last peek height from the previous content when opening. So if you open then close the place page for POIs with different preview sizes, you will see this bug. I have to find a way to pass the new peek height before it opens.
arnaudvergnet commented 2023-01-01 20:01:31 +00:00 (Migrated from github.com)

@Jean-BaptisteC Can you please confirm my latest commit fixes the issue on your device as well?

@Jean-BaptisteC Can you please confirm my latest commit fixes the issue on your device as well?
Jean-BaptisteC commented 2023-01-01 20:54:26 +00:00 (Migrated from github.com)

Your correction is good, problem is fixed
But i have detect a crash :)

01-01 21:31:50.077 12097 12097 E PlacePageView: PlacePageView.java:636 refreshViews(): A place page views cannot be refreshed, mMapObject is null
01-01 21:31:51.183 12097 12149 E OMcore  : routing/directions_engine.cpp:104 GetSegmentRangeAndAdjacentEdges(): CHECK(highwayClass != HighwayClass::Error) [ Error ] [ Error ] { ms::LatLon(49.1182257, 6.16974731), ms::LatLon(49.118159, 6.16986533) }
01-01 21:31:51.183 12097 12149 F libc    : /home/runner/work/organicmaps/organicmaps/routing/directions_engine.cpp:104: void routing::DirectionsEngine::GetSegmentRangeAndAdjacentEdges(const IRoadGraph::EdgeListT &, const routing::Edge &, uint32_t, uint32_t, routing::SegmentRange &, routing::turns::TurnCandidates &): assertion "false" failed
01-01 21:31:51.361 12097 12149 F libc    : Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 12149 (Thread-7), pid 12097 (ganicmaps.debug)
01-01 21:31:51.729 12423 12423 F DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
01-01 21:31:51.729 12423 12423 F DEBUG   : Build fingerprint: 'google/oriole/oriole:13/TQ1A.221205.011/9244662:user/release-keys'
01-01 21:31:51.729 12423 12423 F DEBUG   : Revision: 'MP1.0'
01-01 21:31:51.729 12423 12423 F DEBUG   : ABI: 'arm64'
01-01 21:31:51.729 12423 12423 F DEBUG   : Timestamp: 2023-01-01 21:31:51.527989643+0100
01-01 21:31:51.729 12423 12423 F DEBUG   : Process uptime: 80s
01-01 21:31:51.729 12423 12423 F DEBUG   : Cmdline: app.organicmaps.debug
01-01 21:31:51.729 12423 12423 F DEBUG   : pid: 12097, tid: 12149, name: Thread-7  >>> app.organicmaps.debug <<<
01-01 21:31:51.729 12423 12423 F DEBUG   : uid: 10220
01-01 21:31:51.729 12423 12423 F DEBUG   : tagged_addr_ctrl: 0000000000000001 (PR_TAGGED_ADDR_ENABLE)
01-01 21:31:51.729 12423 12423 F DEBUG   : signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr --------
01-01 21:31:51.729 12423 12423 F DEBUG   : Abort message: '/home/runner/work/organicmaps/organicmaps/routing/directions_engine.cpp:104: void routing::DirectionsEngine::GetSegmentRangeAndAdjacentEdges(const IRoadGraph::EdgeListT &, const routing::Edge &, uint32_t, uint32_t, routing::SegmentRange &, routing::turns::TurnCandidates &): assertion "false" failed'
01-01 21:31:51.729 12423 12423 F DEBUG   :     x0  0000000000000000  x1  0000000000002f75  x2  0000000000000006  x3  00000076a6d74da0
01-01 21:31:51.729 12423 12423 F DEBUG   :     x4  0000008080808080  x5  0000008080808080  x6  0000008080808080  x7  8080808080808080
01-01 21:31:51.729 12423 12423 F DEBUG   :     x8  00000000000000f0  x9  00000079fe6909e0  x10 0000000000000001  x11 00000079fe6d16e0
01-01 21:31:51.729 12423 12423 F DEBUG   :     x12 0101010101010101  x13 000000007fffffff  x14 00000000009f62a2  x15 0000000000000020
01-01 21:31:51.729 12423 12423 F DEBUG   :     x16 00000079fe73ed50  x17 00000079fe71a220  x18 00000076a62f2000  x19 0000000000002f41
01-01 21:31:51.729 12423 12423 F DEBUG   :     x20 0000000000002f75  x21 00000000ffffffff  x22 0000000000002f41  x23 0000000000002f41
01-01 21:31:51.729 12423 12423 F DEBUG   :     x24 00000076a6d77cb0  x25 00000076a6d77cb0  x26 00000076a6d77ff8  x27 00000000000fc000
01-01 21:31:51.729 12423 12423 F DEBUG   :     x28 00000000000fe000  x29 00000076a6d74e20
01-01 21:31:51.729 12423 12423 F DEBUG   :     lr  00000079fe6c21c8  sp  00000076a6d74d80  pc  00000079fe6c21f4  pst 0000000000001000
01-01 21:31:51.729 12423 12423 F DEBUG   : backtrace:
01-01 21:31:51.729 12423 12423 F DEBUG   :       #00 pc 00000000000531f4  /apex/com.android.runtime/lib64/bionic/libc.so (abort+164) (BuildId: 1154186c46119a81daca3db1a6b68111)
01-01 21:31:51.729 12423 12423 F DEBUG   :       #01 pc 0000000000053604  /apex/com.android.runtime/lib64/bionic/libc.so (__assert2+36) (BuildId: 1154186c46119a81daca3db1a6b68111)
01-01 21:31:51.729 12423 12423 F DEBUG   :       #02 pc 0000000002484498  /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (routing::DirectionsEngine::GetSegmentRangeAndAdjacentEdges(routing::SmallList<routing::Edge> const&, routing::Edge const&, unsigned int, unsigned int, routing::SegmentRange&, routing::turns::TurnCandidates&)+988) (BuildId: 93396f046ca365a36ad68a200af0092240a3089a)
01-01 21:31:51.729 12423 12423 F DEBUG   :       #03 pc 00000000024858a8  /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (routing::DirectionsEngine::FillPathSegmentsAndAdjacentEdgesMap(routing::IndexRoadGraph const&, std::__ndk1::vector<geometry::PointWithAltitude, std::__ndk1::allocator<geometry::PointWithAltitude> > const&, std::__ndk1::vector<routing::Edge, std::__ndk1::allocator<routing::Edge> > const&, base::Cancellable const&)+1872) (BuildId: 93396f046ca365a36ad68a200af0092240a3089a)
01-01 21:31:51.729 12423 12423 F DEBUG   :       #04 pc 0000000002486954  /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (routing::DirectionsEngine::Generate(routing::IndexRoadGraph const&, std::__ndk1::vector<geometry::PointWithAltitude, std::__ndk1::allocator<geometry::PointWithAltitude> > const&, base::Cancellable const&, std::__ndk1::vector<routing::RouteSegment, std::__ndk1::allocator<routing::RouteSegment> >&)+1276) (BuildId: 93396f046ca365a36ad68a200af0092240a3089a)
01-01 21:31:51.729 12423 12423 F DEBUG   :       #05 pc 00000000023beb9c  /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (routing::ReconstructRoute(routing::DirectionsEngine&, routing::IndexRoadGraph const&, base::Cancellable const&, std::__ndk1::vector<geometry::PointWithAltitude, std::__ndk1::allocator<geometry::PointWithAltitude> > const&, std::__ndk1::vector<double, std::__ndk1::allocator<double> > const&, routing::Route&)+640) (BuildId: 93396f046ca365a36ad68a200af0092240a3089a)
01-01 21:31:51.729 12423 12423 F DEBUG   :       #06 pc 00000000024b492c  /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (routing::IndexRouter::RedressRoute(std::__ndk1::vector<routing::Segment, std::__ndk1::allocator<routing::Segment> > const&, base::Cancellable const&, routing::IndexGraphStarter&, routing::Route&)+920) (BuildId: 93396f046ca365a36ad68a200af0092240a3089a)
01-01 21:31:51.729 12423 12423 F DEBUG   :       #07 pc 00000000024b1264  /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (routing::IndexRouter::DoCalculateRoute(routing::Checkpoints const&, m2::Point<double> const&, routing::RouterDelegate const&, routing::Route&)+3400) (BuildId: 93396f046ca365a36ad68a200af0092240a3089a)
01-01 21:31:51.729 12423 12423 F DEBUG   :       #08 pc 00000000024aee1c  /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (routing::IndexRouter::CalculateRoute(routing::Checkpoints const&, m2::Point<double> const&, bool, routing::RouterDelegate const&, routing::Route&)+824) (BuildId: 93396f046ca365a36ad68a200af0092240a3089a)
01-01 21:31:51.729 12423 12423 F DEBUG   :       #09 pc 0000000002472e7c  /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (routing::AsyncRouter::CalculateRoute()+1076) (BuildId: 93396f046ca365a36ad68a200af0092240a3089a)
01-01 21:31:51.729 12423 12423 F DEBUG   :       #10 pc 0000000002470dc8  /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (routing::AsyncRouter::ThreadFunc()+308) (BuildId: 93396f046ca365a36ad68a200af0092240a3089a)
01-01 21:31:51.729 12423 12423 F DEBUG   :       #11 pc 000000000252b2d8  /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (BuildId: 93396f046ca365a36ad68a200af0092240a3089a)
01-01 21:31:51.729 12423 12423 F DEBUG   :       #12 pc 000000000252b25c  /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (BuildId: 93396f046ca365a36ad68a200af0092240a3089a)
01-01 21:31:51.729 12423 12423 F DEBUG   :       #13 pc 000000000252b1f4  /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (std::__ndk1::__bind_return<void (routing::AsyncRouter::*)(), std::__ndk1::tuple<routing::AsyncRouter*>, std::__ndk1::tuple<>, __is_valid_bind_return<void (routing::AsyncRouter::*)(), std::__ndk1::tuple<routing::AsyncRouter*>, std::__ndk1::tuple<> >::value>::type std::__ndk1::__bind<void (routing::AsyncRouter::*)(), routing::AsyncRouter*>::operator()<>()+48) (BuildId: 93396f046ca365a36ad68a200af0092240a3089a)
01-01 21:31:51.729 12423 12423 F DEBUG   :       #14 pc 000000000252b1a0  /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (BuildId: 93396f046ca365a36ad68a200af0092240a3089a)
01-01 21:31:51.729 12423 12423 F DEBUG   :       #15 pc 000000000252b154  /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (void std::__ndk1::__invoke_void_return_wrapper<void>::__call<std::__ndk1::__bind<void (routing::AsyncRouter::*)(), routing::AsyncRouter*>&>(std::__ndk1::__bind<void (routing::AsyncRouter::*)(), routing::AsyncRouter*>&)+24) (BuildId: 93396f046ca365a36ad68a200af0092240a3089a)
01-01 21:31:51.729 12423 12423 F DEBUG   :       #16 pc 000000000252b12c  /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (BuildId: 93396f046ca365a36ad68a200af0092240a3089a)
01-01 21:31:51.729 12423 12423 F DEBUG   :       #17 pc 0000000002529f6c  /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (std::__ndk1::__function::__func<std::__ndk1::__bind<void (routing::AsyncRouter::*)(), routing::AsyncRouter*>, std::__ndk1::allocator<std::__ndk1::__bind<void (routing::AsyncRouter::*)(), routing::AsyncRouter*> >, void ()>::operator()()+24) (BuildId: 93396f046ca365a36ad68a200af0092240a3089a)
01-01 21:31:51.729 12423 12423 F DEBUG   :       #18 pc 000000000209cb48  /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (BuildId: 93396f046ca365a36ad68a200af0092240a3089a)
01-01 21:31:51.729 12423 12423 F DEBUG   :       #19 pc 000000000201070c  /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (std::__ndk1::function<void ()>::operator()() const+20) (BuildId: 93396f046ca365a36ad68a200af0092240a3089a)
01-01 21:31:51.729 12423 12423 F DEBUG   :       #20 pc 00000000034a77b4  /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (threads::SimpleThread::ThreadFunc(std::__ndk1::function<void ()>&&)+24) (BuildId: 93396f046ca365a36ad68a200af0092240a3089a)
01-01 21:31:51.729 12423 12423 F DEBUG   :       #21 pc 000000000252993c  /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (BuildId: 93396f046ca365a36ad68a200af0092240a3089a)
01-01 21:31:51.729 12423 12423 F DEBUG   :       #22 pc 0000000002529894  /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (BuildId: 93396f046ca365a36ad68a200af0092240a3089a)
01-01 21:31:51.729 12423 12423 F DEBUG   :       #23 pc 0000000002529590  /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (BuildId: 93396f046ca365a36ad68a200af0092240a3089a)
01-01 21:31:51.729 12423 12423 F DEBUG   :       #24 pc 00000000000c15dc  /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*)+204) (BuildId: 1154186c46119a81daca3db1a6b68111)
01-01 21:31:51.729 12423 12423 F DEBUG   :       #25 pc 0000000000054a30  /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+64) (BuildId: 1154186c46119a81daca3db1a6b68111)
01-01 21:31:51.748   673   673 E tombstoned: Tombstone written to: tombstone_20
01-01 21:31:51.834  1468  1686 E ConnectivityService: [103 CELLULAR]: ignoring attempt to change owner from -1 to 10230
01-01 21:31:51.843  1468  6548 I ActivityManager: Process app.organicmaps.debug (pid 12097) has died: prcp TOP
01-01 21:31:51.843  1468  6548 I ActivityManager: Killing 12381:com.google.android.webview:sandboxed_process0:org.chromium.content.app.SandboxedProcessService0:0/u0a220i26 (adj 0): isolated not needed

To reproduce i search Gare de Metz(building=train_station, not POI public_station) and select velo routing from my position here

I am not able to reproduce with all objects in maps, you can try with most far hotels from your positon (use category hotel) and select pedestrian routing

Your correction is good, problem is fixed But i have detect a crash :) ``` 01-01 21:31:50.077 12097 12097 E PlacePageView: PlacePageView.java:636 refreshViews(): A place page views cannot be refreshed, mMapObject is null 01-01 21:31:51.183 12097 12149 E OMcore : routing/directions_engine.cpp:104 GetSegmentRangeAndAdjacentEdges(): CHECK(highwayClass != HighwayClass::Error) [ Error ] [ Error ] { ms::LatLon(49.1182257, 6.16974731), ms::LatLon(49.118159, 6.16986533) } 01-01 21:31:51.183 12097 12149 F libc : /home/runner/work/organicmaps/organicmaps/routing/directions_engine.cpp:104: void routing::DirectionsEngine::GetSegmentRangeAndAdjacentEdges(const IRoadGraph::EdgeListT &, const routing::Edge &, uint32_t, uint32_t, routing::SegmentRange &, routing::turns::TurnCandidates &): assertion "false" failed 01-01 21:31:51.361 12097 12149 F libc : Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 12149 (Thread-7), pid 12097 (ganicmaps.debug) 01-01 21:31:51.729 12423 12423 F DEBUG : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 01-01 21:31:51.729 12423 12423 F DEBUG : Build fingerprint: 'google/oriole/oriole:13/TQ1A.221205.011/9244662:user/release-keys' 01-01 21:31:51.729 12423 12423 F DEBUG : Revision: 'MP1.0' 01-01 21:31:51.729 12423 12423 F DEBUG : ABI: 'arm64' 01-01 21:31:51.729 12423 12423 F DEBUG : Timestamp: 2023-01-01 21:31:51.527989643+0100 01-01 21:31:51.729 12423 12423 F DEBUG : Process uptime: 80s 01-01 21:31:51.729 12423 12423 F DEBUG : Cmdline: app.organicmaps.debug 01-01 21:31:51.729 12423 12423 F DEBUG : pid: 12097, tid: 12149, name: Thread-7 >>> app.organicmaps.debug <<< 01-01 21:31:51.729 12423 12423 F DEBUG : uid: 10220 01-01 21:31:51.729 12423 12423 F DEBUG : tagged_addr_ctrl: 0000000000000001 (PR_TAGGED_ADDR_ENABLE) 01-01 21:31:51.729 12423 12423 F DEBUG : signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr -------- 01-01 21:31:51.729 12423 12423 F DEBUG : Abort message: '/home/runner/work/organicmaps/organicmaps/routing/directions_engine.cpp:104: void routing::DirectionsEngine::GetSegmentRangeAndAdjacentEdges(const IRoadGraph::EdgeListT &, const routing::Edge &, uint32_t, uint32_t, routing::SegmentRange &, routing::turns::TurnCandidates &): assertion "false" failed' 01-01 21:31:51.729 12423 12423 F DEBUG : x0 0000000000000000 x1 0000000000002f75 x2 0000000000000006 x3 00000076a6d74da0 01-01 21:31:51.729 12423 12423 F DEBUG : x4 0000008080808080 x5 0000008080808080 x6 0000008080808080 x7 8080808080808080 01-01 21:31:51.729 12423 12423 F DEBUG : x8 00000000000000f0 x9 00000079fe6909e0 x10 0000000000000001 x11 00000079fe6d16e0 01-01 21:31:51.729 12423 12423 F DEBUG : x12 0101010101010101 x13 000000007fffffff x14 00000000009f62a2 x15 0000000000000020 01-01 21:31:51.729 12423 12423 F DEBUG : x16 00000079fe73ed50 x17 00000079fe71a220 x18 00000076a62f2000 x19 0000000000002f41 01-01 21:31:51.729 12423 12423 F DEBUG : x20 0000000000002f75 x21 00000000ffffffff x22 0000000000002f41 x23 0000000000002f41 01-01 21:31:51.729 12423 12423 F DEBUG : x24 00000076a6d77cb0 x25 00000076a6d77cb0 x26 00000076a6d77ff8 x27 00000000000fc000 01-01 21:31:51.729 12423 12423 F DEBUG : x28 00000000000fe000 x29 00000076a6d74e20 01-01 21:31:51.729 12423 12423 F DEBUG : lr 00000079fe6c21c8 sp 00000076a6d74d80 pc 00000079fe6c21f4 pst 0000000000001000 01-01 21:31:51.729 12423 12423 F DEBUG : backtrace: 01-01 21:31:51.729 12423 12423 F DEBUG : #00 pc 00000000000531f4 /apex/com.android.runtime/lib64/bionic/libc.so (abort+164) (BuildId: 1154186c46119a81daca3db1a6b68111) 01-01 21:31:51.729 12423 12423 F DEBUG : #01 pc 0000000000053604 /apex/com.android.runtime/lib64/bionic/libc.so (__assert2+36) (BuildId: 1154186c46119a81daca3db1a6b68111) 01-01 21:31:51.729 12423 12423 F DEBUG : #02 pc 0000000002484498 /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (routing::DirectionsEngine::GetSegmentRangeAndAdjacentEdges(routing::SmallList<routing::Edge> const&, routing::Edge const&, unsigned int, unsigned int, routing::SegmentRange&, routing::turns::TurnCandidates&)+988) (BuildId: 93396f046ca365a36ad68a200af0092240a3089a) 01-01 21:31:51.729 12423 12423 F DEBUG : #03 pc 00000000024858a8 /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (routing::DirectionsEngine::FillPathSegmentsAndAdjacentEdgesMap(routing::IndexRoadGraph const&, std::__ndk1::vector<geometry::PointWithAltitude, std::__ndk1::allocator<geometry::PointWithAltitude> > const&, std::__ndk1::vector<routing::Edge, std::__ndk1::allocator<routing::Edge> > const&, base::Cancellable const&)+1872) (BuildId: 93396f046ca365a36ad68a200af0092240a3089a) 01-01 21:31:51.729 12423 12423 F DEBUG : #04 pc 0000000002486954 /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (routing::DirectionsEngine::Generate(routing::IndexRoadGraph const&, std::__ndk1::vector<geometry::PointWithAltitude, std::__ndk1::allocator<geometry::PointWithAltitude> > const&, base::Cancellable const&, std::__ndk1::vector<routing::RouteSegment, std::__ndk1::allocator<routing::RouteSegment> >&)+1276) (BuildId: 93396f046ca365a36ad68a200af0092240a3089a) 01-01 21:31:51.729 12423 12423 F DEBUG : #05 pc 00000000023beb9c /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (routing::ReconstructRoute(routing::DirectionsEngine&, routing::IndexRoadGraph const&, base::Cancellable const&, std::__ndk1::vector<geometry::PointWithAltitude, std::__ndk1::allocator<geometry::PointWithAltitude> > const&, std::__ndk1::vector<double, std::__ndk1::allocator<double> > const&, routing::Route&)+640) (BuildId: 93396f046ca365a36ad68a200af0092240a3089a) 01-01 21:31:51.729 12423 12423 F DEBUG : #06 pc 00000000024b492c /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (routing::IndexRouter::RedressRoute(std::__ndk1::vector<routing::Segment, std::__ndk1::allocator<routing::Segment> > const&, base::Cancellable const&, routing::IndexGraphStarter&, routing::Route&)+920) (BuildId: 93396f046ca365a36ad68a200af0092240a3089a) 01-01 21:31:51.729 12423 12423 F DEBUG : #07 pc 00000000024b1264 /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (routing::IndexRouter::DoCalculateRoute(routing::Checkpoints const&, m2::Point<double> const&, routing::RouterDelegate const&, routing::Route&)+3400) (BuildId: 93396f046ca365a36ad68a200af0092240a3089a) 01-01 21:31:51.729 12423 12423 F DEBUG : #08 pc 00000000024aee1c /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (routing::IndexRouter::CalculateRoute(routing::Checkpoints const&, m2::Point<double> const&, bool, routing::RouterDelegate const&, routing::Route&)+824) (BuildId: 93396f046ca365a36ad68a200af0092240a3089a) 01-01 21:31:51.729 12423 12423 F DEBUG : #09 pc 0000000002472e7c /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (routing::AsyncRouter::CalculateRoute()+1076) (BuildId: 93396f046ca365a36ad68a200af0092240a3089a) 01-01 21:31:51.729 12423 12423 F DEBUG : #10 pc 0000000002470dc8 /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (routing::AsyncRouter::ThreadFunc()+308) (BuildId: 93396f046ca365a36ad68a200af0092240a3089a) 01-01 21:31:51.729 12423 12423 F DEBUG : #11 pc 000000000252b2d8 /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (BuildId: 93396f046ca365a36ad68a200af0092240a3089a) 01-01 21:31:51.729 12423 12423 F DEBUG : #12 pc 000000000252b25c /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (BuildId: 93396f046ca365a36ad68a200af0092240a3089a) 01-01 21:31:51.729 12423 12423 F DEBUG : #13 pc 000000000252b1f4 /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (std::__ndk1::__bind_return<void (routing::AsyncRouter::*)(), std::__ndk1::tuple<routing::AsyncRouter*>, std::__ndk1::tuple<>, __is_valid_bind_return<void (routing::AsyncRouter::*)(), std::__ndk1::tuple<routing::AsyncRouter*>, std::__ndk1::tuple<> >::value>::type std::__ndk1::__bind<void (routing::AsyncRouter::*)(), routing::AsyncRouter*>::operator()<>()+48) (BuildId: 93396f046ca365a36ad68a200af0092240a3089a) 01-01 21:31:51.729 12423 12423 F DEBUG : #14 pc 000000000252b1a0 /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (BuildId: 93396f046ca365a36ad68a200af0092240a3089a) 01-01 21:31:51.729 12423 12423 F DEBUG : #15 pc 000000000252b154 /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (void std::__ndk1::__invoke_void_return_wrapper<void>::__call<std::__ndk1::__bind<void (routing::AsyncRouter::*)(), routing::AsyncRouter*>&>(std::__ndk1::__bind<void (routing::AsyncRouter::*)(), routing::AsyncRouter*>&)+24) (BuildId: 93396f046ca365a36ad68a200af0092240a3089a) 01-01 21:31:51.729 12423 12423 F DEBUG : #16 pc 000000000252b12c /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (BuildId: 93396f046ca365a36ad68a200af0092240a3089a) 01-01 21:31:51.729 12423 12423 F DEBUG : #17 pc 0000000002529f6c /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (std::__ndk1::__function::__func<std::__ndk1::__bind<void (routing::AsyncRouter::*)(), routing::AsyncRouter*>, std::__ndk1::allocator<std::__ndk1::__bind<void (routing::AsyncRouter::*)(), routing::AsyncRouter*> >, void ()>::operator()()+24) (BuildId: 93396f046ca365a36ad68a200af0092240a3089a) 01-01 21:31:51.729 12423 12423 F DEBUG : #18 pc 000000000209cb48 /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (BuildId: 93396f046ca365a36ad68a200af0092240a3089a) 01-01 21:31:51.729 12423 12423 F DEBUG : #19 pc 000000000201070c /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (std::__ndk1::function<void ()>::operator()() const+20) (BuildId: 93396f046ca365a36ad68a200af0092240a3089a) 01-01 21:31:51.729 12423 12423 F DEBUG : #20 pc 00000000034a77b4 /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (threads::SimpleThread::ThreadFunc(std::__ndk1::function<void ()>&&)+24) (BuildId: 93396f046ca365a36ad68a200af0092240a3089a) 01-01 21:31:51.729 12423 12423 F DEBUG : #21 pc 000000000252993c /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (BuildId: 93396f046ca365a36ad68a200af0092240a3089a) 01-01 21:31:51.729 12423 12423 F DEBUG : #22 pc 0000000002529894 /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (BuildId: 93396f046ca365a36ad68a200af0092240a3089a) 01-01 21:31:51.729 12423 12423 F DEBUG : #23 pc 0000000002529590 /data/app/~~61EQUY0rVN8Xw_DmZTJuyw==/app.organicmaps.debug-kwu1jgbphOWwu7r12NgeiA==/lib/arm64/liborganicmaps.so (BuildId: 93396f046ca365a36ad68a200af0092240a3089a) 01-01 21:31:51.729 12423 12423 F DEBUG : #24 pc 00000000000c15dc /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*)+204) (BuildId: 1154186c46119a81daca3db1a6b68111) 01-01 21:31:51.729 12423 12423 F DEBUG : #25 pc 0000000000054a30 /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+64) (BuildId: 1154186c46119a81daca3db1a6b68111) 01-01 21:31:51.748 673 673 E tombstoned: Tombstone written to: tombstone_20 01-01 21:31:51.834 1468 1686 E ConnectivityService: [103 CELLULAR]: ignoring attempt to change owner from -1 to 10230 01-01 21:31:51.843 1468 6548 I ActivityManager: Process app.organicmaps.debug (pid 12097) has died: prcp TOP 01-01 21:31:51.843 1468 6548 I ActivityManager: Killing 12381:com.google.android.webview:sandboxed_process0:org.chromium.content.app.SandboxedProcessService0:0/u0a220i26 (adj 0): isolated not needed ``` To reproduce i search `Gare de Metz`(building=train_station, not POI public_station) and select velo routing from my position [here](https://www.openstreetmap.org/#map=19/49.11931/6.17096) I am not able to reproduce with all objects in maps, you can try with most far hotels from your positon (use category hotel) and select pedestrian routing
arnaudvergnet commented 2023-01-01 21:03:38 +00:00 (Migrated from github.com)

Your crash does not seem to be related to be related to this PR, can you reproduce this on the master branch or with the version in the stores? I can't reproduce it.

Your crash does not seem to be related to be related to this PR, can you reproduce this on the master branch or with the version in the stores? I can't reproduce it.
arnaudvergnet commented 2023-01-02 17:49:15 +00:00 (Migrated from github.com)

Updated the main post with my answers to the questions. Please tell me what you think.

Updated the main post with my answers to the questions. Please tell me what you think.
biodranik commented 2023-01-02 23:36:13 +00:00 (Migrated from github.com)

The very first tap on the PP is visibly slower now than on the master branch. If PP is cached anyway after the first click, then we should consider caching PP like it was done on the master branch for a smoother first-click experience. OM should be fast ;-)

Another issue (not a critical one) is that for some reason any subsequent tap on the POI does not work instantly, there is a (small) delay. It would be great to profile it and make the real-time reaction feeling, if it is possible, of course.

The very first tap on the PP is visibly slower now than on the master branch. If PP is cached anyway after the first click, then we should consider caching PP like it was done on the master branch for a smoother first-click experience. OM should be _fast_ ;-) Another issue (not a critical one) is that for some reason any subsequent tap on the POI does not work instantly, there is a (small) delay. It would be great to profile it and make the _real-time reaction_ feeling, if it is possible, of course.
arnaudvergnet commented 2023-01-03 06:47:03 +00:00 (Migrated from github.com)

I moved the bookmark section in its own fragment and only add it when the selected POI is bookmarked (not committed yet, I need to check for regressions). Selecting POIs is now a lot faster, even for the first click. But the first click on a bookmark sees a little hang. My guess is Webview is slowing everything. I can try to dynamically add the webview component only when the bookmark has html content. This way only bookmarks with HTML would see this first click slowdown. Would that be acceptable?

I moved the bookmark section in its own fragment and only add it when the selected POI is bookmarked (not committed yet, I need to check for regressions). Selecting POIs is now a lot faster, even for the first click. But the first click on a bookmark sees a little hang. My guess is Webview is slowing everything. I can try to dynamically add the webview component only when the bookmark has html content. This way only bookmarks with HTML would see this first click slowdown. Would that be acceptable?
biodranik commented 2023-01-03 08:00:51 +00:00 (Migrated from github.com)

This way only bookmarks with HTML would see this first click slowdown. Would that be acceptable?

This is exactly what I had in mind! There is some method to detect if the text in the bookmark is HTML or not, so the real check should be something like this:

if (bookmark) {
  if (bookmark.HasDescription()) {
    if (bookmark.HasComplexHTMLDescription() {
      // render WebView
    } else {
      // render TextView
    }
  }
}

Maybe even some simple HTML can be rendered in the TextView (e.g. HTML with only bold/italic/headers/paragraphs, without tables, images etc.)

Also, what about Wiki articles? Are they rendered into the TextView or WebView?

> This way only bookmarks with HTML would see this first click slowdown. Would that be acceptable? This is exactly what I had in mind! There is some method to detect if the text in the bookmark is HTML or not, so the real check should be something like this: ``` if (bookmark) { if (bookmark.HasDescription()) { if (bookmark.HasComplexHTMLDescription() { // render WebView } else { // render TextView } } } ``` Maybe even some simple HTML can be rendered in the TextView (e.g. HTML with only bold/italic/headers/paragraphs, without tables, images etc.) Also, what about Wiki articles? Are they rendered into the TextView or WebView?
biodranik commented 2023-01-03 08:03:24 +00:00 (Migrated from github.com)

And if you refactor descriptions, then don't forget about the need to display:

  1. Wiki
  2. Bookmarks descriptions
  3. OSM descriptions that are already present in the maps data.

We discussed it somewhere already, right?

And if you refactor descriptions, then don't forget about the need to display: 1. Wiki 2. Bookmarks descriptions 3. OSM [descriptions](https://wiki.openstreetmap.org/wiki/Key:description) that are _already_ present in the maps data. We discussed it somewhere already, right?
arnaudvergnet commented 2023-01-04 21:24:56 +00:00 (Migrated from github.com)

I managed to get the conditional loading of the webview working, and indeed the place page is faster, but you can see the webview loading when opening a place page with an html description.

From what I could see, the Wikipedia article uses a simple text view.

I face an annoying issue: the animation when the peek view changes is not always played when switching from a bookmark to a regular feature.

I managed to get the conditional loading of the webview working, and indeed the place page is faster, but you can see the webview loading when opening a place page with an html description. From what I could see, the Wikipedia article uses a simple text view. I face an annoying issue: the animation when the peek view changes is not always played when switching from a bookmark to a regular feature.
arnaudvergnet commented 2023-01-04 21:26:55 +00:00 (Migrated from github.com)

And for the description, this is referenced in organicmaps/organicmaps#1953. This refactoring should make it easier to implement. I'm also working on a fix for organicmaps/organicmaps#2825.

And for the description, this is referenced in https://git.omaps.dev/organicmaps/organicmaps/issues/1953. This refactoring should make it easier to implement. I'm also working on a fix for https://git.omaps.dev/organicmaps/organicmaps/issues/2825.
biodranik commented 2023-01-05 13:45:16 +00:00 (Migrated from github.com)

Cool, you're the refactoring guru, Arnaud!

Slower/visible webview for bookmarks can be handled later/differently. For example, like this:

  • Check if the bookmark's description can be safely rendered in the TextView using fromHtml
  • Load WebView only if necessary (we need to discover which tags won't work in text view)
  • Cache WebView if it was already loaded once (if a user is checking some rich formatted bookmark with images and links, then he/she likely check some other similar bookmarks too).
Cool, you're the refactoring guru, Arnaud! Slower/visible webview for bookmarks can be handled later/differently. For example, like this: - Check if the bookmark's description can be safely rendered in the TextView using [fromHtml](https://developer.android.com/reference/android/text/Html.html#fromHtml(java.lang.String,%20int,%20android.text.Html.ImageGetter,%20android.text.Html.TagHandler)) - Load WebView only if necessary (we need to discover which tags won't work in text view) - Cache WebView if it was already loaded once (if a user is checking some rich formatted bookmark with images and links, then he/she likely check some other similar bookmarks too).
arnaudvergnet commented 2023-01-10 21:22:05 +00:00 (Migrated from github.com)

I think I finally found away to make the place page fast with smooth animations. But my solution will involve some UX changes!

TL;DR: Place page uses the half extend state for bookmarks with descriptions and wiki articles to show the extended preview. To use this I had to set the bottom sheet to not fit the content, so now it can always be extended fullscreen.

vvv Video at the end vvv

I had issues with the peek height not playing the resize animation when the content height changed because of the webview loading, fragment being added and other unknown factors annoying to debug. I won't get into details but each time I thought I fixed the issue, I found a new bug with it. One example of this was when a POI with a small HTML bookmark was opened, the place page was not tall enough to reach the extended peek height, so when the content finished loading it would snap to the correct position because it would be tall enough.

To make the place page behave in a more predictable way and fix all those bugs, I introduced a new state: half expanded. This state is already built in the standard bottom sheet component, but was not used here because the place page was set to automatically fit to the content. So now the place page can always be extended (fit to content = false), even if there is not enough data to fit the screen in order to enable this state.

The peek height now always follows the preview height no matter the POI type (before it would be set to an extended value for wiki and bookmarks). If the place page must be opened with a bigger peek height (wiki or bookmarks), then it is opened directly to the half expanded state. As the place page does not fit the content anymore, it will always be able to reach this height even if there is not enough content, and if the content changes the place page will not move. From this state, the user can then expand or collapse the sheet. The half expanded state can only be reached when first opening the POI, a user cannot go back to this state by dragging the place page. I don't thing this is an issue as if the user want to have the sheet opened and move on the map, the collapsed state is better.

Pros:

  • Expanding the place page is a lot smoother and feels less jumpy as it will not move the viewport anymore (no need as it goes fullscreen). This should also increase battery life by removing useless and frequent map movements.
  • Place page position should be more consistent. No need to wonder where the place page will end up when clicking on the preview to extend it.
  • Can collapse every POI. POIs with wiki articles and bookmark descriptions can be collapsed to move on the map more easily.

Cons:

  • Expanding items with limited information (eg: gates, fountains, ...) can feel weird as most of the page will be blank. We could mitigate this issue by adding a pretty graphic/information inciting the user to contribute to OSM.

This is still work in progress but I'm quite satisfied with how it turned out, please tell me what you think!

https://user-images.githubusercontent.com/80701113/211664050-3ca03d9b-892c-46ce-b601-a4db372e7542.mp4

I think I finally found away to make the place page fast with smooth animations. But my solution will involve some UX changes! **TL;DR:** Place page uses the half extend state for bookmarks with descriptions and wiki articles to show the extended preview. To use this I had to set the bottom sheet to not fit the content, so now it can always be extended fullscreen. **vvv Video at the end vvv** I had issues with the peek height not playing the resize animation when the content height changed because of the webview loading, fragment being added and other unknown factors annoying to debug. I won't get into details but each time I thought I fixed the issue, I found a new bug with it. One example of this was when a POI with a small HTML bookmark was opened, the place page was not tall enough to reach the extended peek height, so when the content finished loading it would snap to the correct position because it would be tall enough. To make the place page behave in a more predictable way and fix all those bugs, I introduced a new state: **half expanded**. This state is already built in the standard bottom sheet component, but was not used here because the place page was set to automatically fit to the content. So now the place page can always be extended (fit to content = false), even if there is not enough data to fit the screen in order to enable this state. The peek height now always follows the preview height no matter the POI type (before it would be set to an extended value for wiki and bookmarks). If the place page must be opened with a bigger peek height (wiki or bookmarks), then it is opened directly to the half expanded state. As the place page does not fit the content anymore, it will always be able to reach this height even if there is not enough content, and if the content changes the place page will not move. From this state, the user can then expand or collapse the sheet. The half expanded state can only be reached when first opening the POI, a user cannot go back to this state by dragging the place page. I don't thing this is an issue as if the user want to have the sheet opened and move on the map, the collapsed state is better. **Pros:** - Expanding the place page is a lot smoother and feels less jumpy as it will not move the viewport anymore (no need as it goes fullscreen). This should also increase battery life by removing useless and frequent map movements. - Place page position should be more consistent. No need to wonder where the place page will end up when clicking on the preview to extend it. - Can collapse every POI. POIs with wiki articles and bookmark descriptions can be collapsed to move on the map more easily. **Cons:** - Expanding items with limited information (eg: gates, fountains, ...) can feel weird as most of the page will be blank. We could mitigate this issue by adding a pretty graphic/information inciting the user to contribute to OSM. **This is still work in progress but I'm quite satisfied with how it turned out, please tell me what you think!** https://user-images.githubusercontent.com/80701113/211664050-3ca03d9b-892c-46ce-b601-a4db372e7542.mp4
Jean-BaptisteC commented 2023-01-11 17:17:42 +00:00 (Migrated from github.com)

That's really great !!!!

Just some commentaries:

  • Show place page in fullscreen is interesting for the future if we show wikimedia images about POI
  • Actually if i open place page in fullscreen and open editor and go back to place page, place page is reduced , can you fix it (keep latest position) ?
  • Idem when i add POI in bookmarks or go back from Wikipedia articles
  • Is it possible to add more spaces between Android top bar and Title POI in fullscreen ?
That's really great !!!! Just some commentaries: - Show place page in fullscreen is interesting for the future if we show wikimedia images about POI - Actually if i open place page in fullscreen and open editor and go back to place page, place page is reduced , can you fix it (keep latest position) ? - Idem when i add POI in bookmarks or go back from Wikipedia articles - Is it possible to add more spaces between Android top bar and Title POI in fullscreen ?
arnaudvergnet commented 2023-01-11 21:46:42 +00:00 (Migrated from github.com)

Thanks for the valuable feedback @Jean-BaptisteC! I added more padding to the place page so it is farther away from the status bar when fullscreen, and the place page should not collapse to its initial state when moving between screens or editing the POI.

Please tell me if your issues are not properly fixed or you find something else!

Thanks for the valuable feedback @Jean-BaptisteC! I added more padding to the place page so it is farther away from the status bar when fullscreen, and the place page should not collapse to its initial state when moving between screens or editing the POI. Please tell me if your issues are not properly fixed or you find something else!
biodranik commented 2023-01-12 08:00:01 +00:00 (Migrated from github.com)

I've tested this branch and found that the full-screen Place Page looks strange (especially for simple POIs without any additional info, a lot of empty space), and is less convenient to close/use (previously you can tap on the map to close). I'm not sure at the moment that it is the right way to go.

Other minor issues:

  1. "Description" gray header is not necessary IMO, removing it will help to see more useful info on the screen.
  2. The whole wiki text view should be tappable, not just "more" at the bottom.
I've tested this branch and found that the full-screen Place Page looks strange (especially for simple POIs without any additional info, a lot of empty space), and is less convenient to close/use (previously you can tap on the map to close). I'm not sure at the moment that it is the right way to go. Other minor issues: 1. "Description" gray header is not necessary IMO, removing it will help to see more useful info on the screen. 2. The whole wiki text view should be tappable, not just "more" at the bottom.
arnaudvergnet commented 2023-01-15 18:49:42 +00:00 (Migrated from github.com)

I've tested this branch and found that the full-screen Place Page looks strange (especially for simple POIs without any additional info, a lot of empty space), and is less convenient to close/use (previously you can tap on the map to close). I'm not sure at the moment that it is the right way to go.

To make the place page look less empty, we could add information about OSM and guide the user to add more information. This information could be displayed as text or using an image. For the closing issue, I don't think that's a big deal, I never was able to close the place page by clicking elsewhere on the map unless I was in the middle of nowhere. Users can still do a simple swipe down to close it.

"Description" gray header is not necessary IMO, removing it will help to see more useful info on the screen.

I plan an reworking the description stuff to better handle all the cases in #1953.

The whole wiki text view should be tappable, not just "more" at the bottom

Good idea, will work on that when refactoring descriptions

> I've tested this branch and found that the full-screen Place Page looks strange (especially for simple POIs without any additional info, a lot of empty space), and is less convenient to close/use (previously you can tap on the map to close). I'm not sure at the moment that it is the right way to go. To make the place page look less empty, we could add information about OSM and guide the user to add more information. This information could be displayed as text or using an image. For the closing issue, I don't think that's a big deal, I never was able to close the place page by clicking elsewhere on the map unless I was in the middle of nowhere. Users can still do a simple swipe down to close it. > "Description" gray header is not necessary IMO, removing it will help to see more useful info on the screen. I plan an reworking the description stuff to better handle all the cases in #1953. > The whole wiki text view should be tappable, not just "more" at the bottom Good idea, will work on that when refactoring descriptions
biodranik commented 2023-01-15 20:49:17 +00:00 (Migrated from github.com)

One of the main issues with that "unnecessary" full-screen PP is that it's way harder to press "Edit Place", coordinate, or some other button when it's in the upper part of the screen. Is it really a required UX change? Was the problem mostly in web views with dynamic/unpredicted height? Let's brainstorm on other ways to fix it.

Will showing the PP on the bookmark/wiki (later also on OSM description/wikidata photo) expanded to some fixed height help to fix the issue?

P.S. Now there is a small visual delay when PP is hidden, because the bottom buttons are not animated down, like the PP. Is it hard to implement?

One of the main issues with that "unnecessary" full-screen PP is that it's way harder to press "Edit Place", coordinate, or some other button when it's in the upper part of the screen. Is it really a required UX change? Was the problem mostly in web views with dynamic/unpredicted height? Let's brainstorm on other ways to fix it. Will showing the PP on the bookmark/wiki (later also on OSM description/wikidata photo) expanded to some fixed height help to fix the issue? P.S. Now there is a small visual delay when PP is hidden, because the bottom buttons are not animated down, like the PP. Is it hard to implement?
arnaudvergnet commented 2023-01-15 22:40:47 +00:00 (Migrated from github.com)

One of the main issues with that "unnecessary" full-screen PP is that it's way harder to press "Edit Place", coordinate, or some other button when it's in the upper part of the screen. Is it really a required UX change? Was the problem mostly in web views with dynamic/unpredicted height? Let's brainstorm on other ways to fix it. Will showing the PP on the bookmark/wiki (later also on OSM description/wikidata photo) expanded to some fixed height help to fix the issue?

The place page is already expanded to a fixed height when a bookmark note or wikipedia article are available. But in some cases, this height is bigger than the actual place page, and the late loading of the webview may change this height and you would see a snap. Another issue I had was that adding a fragment to the bottom sheet would cancel the peek height change animation (so using the half extended state would avoid that limitation).

Here are my ideas to fix those 2 issues without relying on a fullscreen place page:

  • Set the minHeight of the place page when we need to show an extended preview so we are sure we always reach the desired peek height
  • Use TransitionManager animations to animate the peek height instead of relying on the animate parameter of the setPeekHeight function. I still have to experiment with it but it seems to play the animation properly compared to the animate parameter. Or we could use a value animator to gradually change the peek height. I'll try to see which solution works best.

P.S. Now there is a small visual delay when PP is hidden, because the bottom buttons are not animated down, like the PP. Is it hard to implement?

I thought about animating the buttons to follow the place page when it moves out of screen. I don't think it would be that hard to implement, I might look into it when I finished reworking the place page view.

> One of the main issues with that "unnecessary" full-screen PP is that it's way harder to press "Edit Place", coordinate, or some other button when it's in the upper part of the screen. Is it really a required UX change? Was the problem mostly in web views with dynamic/unpredicted height? Let's brainstorm on other ways to fix it. Will showing the PP on the bookmark/wiki (later also on OSM description/wikidata photo) expanded to some fixed height help to fix the issue? The place page is already expanded to a fixed height when a bookmark note or wikipedia article are available. But in some cases, this height is bigger than the actual place page, and the late loading of the webview may change this height and you would see a snap. Another issue I had was that adding a fragment to the bottom sheet would cancel the peek height change animation (so using the half extended state would avoid that limitation). Here are my ideas to fix those 2 issues without relying on a fullscreen place page: - Set the minHeight of the place page when we need to show an extended preview so we are sure we always reach the desired peek height - Use `TransitionManager` animations to animate the peek height instead of relying on the `animate` parameter of the `setPeekHeight` function. I still have to experiment with it but it seems to play the animation properly compared to the `animate` parameter. Or we could use a value animator to gradually change the peek height. I'll try to see which solution works best. > P.S. Now there is a small visual delay when PP is hidden, because the bottom buttons are not animated down, like the PP. Is it hard to implement? I thought about animating the buttons to follow the place page when it moves out of screen. I don't think it would be that hard to implement, I might look into it when I finished reworking the place page view.
arnaudvergnet commented 2023-01-18 18:12:47 +00:00 (Migrated from github.com)

After some experimenting, the best way I found to properly animate the peek height is to use a value animator and set the peek height in its callback. Thanks to this I was able to use the peek height for bookmarks and Wikipedia instead of the half expanded state. So the UX is back to what it was, with the place page adapting to the content's height.

Something is still missing though: the place page will collapse when opening the editor and going back, or saving a bookmark. I'm still looking at how to fix this but it might be tricky as the c++ code is calling the same "open the place page" function whether we exit the editor, save a bookmark or click on a place on the map.

After some experimenting, the best way I found to properly animate the peek height is to use a value animator and set the peek height in its callback. Thanks to this I was able to use the peek height for bookmarks and Wikipedia instead of the half expanded state. So the UX is back to what it was, with the place page adapting to the content's height. Something is still missing though: the place page will collapse when opening the editor and going back, or saving a bookmark. I'm still looking at how to fix this but it might be tricky as the c++ code is calling the same "open the place page" function whether we exit the editor, save a bookmark or click on a place on the map.
arnaudvergnet commented 2023-01-18 18:36:39 +00:00 (Migrated from github.com)

Ok I think I found a way to stop the place page from collapsing. Now it collapses only when the map object in the place page changes. The comparison sees a POI and its bookmarked version as different objects, so the place page will still collapse.

Please test and tell me what you think now!

Ok I think I found a way to stop the place page from collapsing. Now it collapses only when the map object in the place page changes. The comparison sees a POI and its bookmarked version as different objects, so the place page will still collapse. Please test and tell me what you think now!
biodranik commented 2023-01-20 14:48:42 +00:00 (Migrated from github.com)

Awesome! Let's test it. We can help with the C++ part if necessary, just ask what is needed.

Awesome! Let's test it. We can help with the C++ part if necessary, just ask what is needed.
biodranik commented 2023-01-20 20:54:48 +00:00 (Migrated from github.com)

It works ok on my device. Let's beta-test it )

Other issues to fix in PP (maybe separate issues should be created):

  1. The margin at the top of the title is too big.
  2. It is hard to close PP by swiping it down. There is some resistance that returns it back, or in some cases even opens it full screen.
  3. Swiping down PP in a non-preview state should close it (now it is closed only if PP's preview is visible, e.g. the lowest possible height of the PP). Touching the top horizontal line likely also should close it for consistency.
  4. (Repeat here for consistency) Now there is a small visual delay when PP is hidden, because the bottom buttons are not animated down, like the PP.
It works ok on my device. Let's beta-test it ) Other issues to fix in PP (maybe separate issues should be created): 1. The margin at the top of the title is too big. 2. It is hard to close PP by swiping it down. There is some resistance that returns it back, or in some cases even opens it full screen. 3. Swiping down PP in a non-preview state should close it (now it is closed only if PP's preview is visible, e.g. the lowest possible height of the PP). Touching the top horizontal line likely also should close it for consistency. 4. (Repeat here for consistency) Now there is a small visual delay when PP is hidden, because the bottom buttons are not animated down, like the PP.
arnaudvergnet commented 2023-01-20 22:04:13 +00:00 (Migrated from github.com)

Awesome! Let's test it. We can help with the C++ part if necessary, just ask what is needed.

I think I got back to the initial behavior, so unless you want it to be changed, I think we are good.

The margin at the top of the title is too big.

This was increased to make the title farther away from the status bar when the PP is fullscreen. I don't really know how to fix both issues at the same time.

It is hard to close PP by swiping it down. There is some resistance that returns it back, or in some cases even opens it full screen.

I never noticed it, nothing in the code changes that and it uses Android's native components.

Swiping down PP in a non-preview state should close it (now it is closed only if PP's preview is visible, e.g. the lowest possible height of the PP). Touching the top horizontal line likely also should close it for consistency.

The current behavior when tapping on the PP preview is to toggle expanded/collapsed state. Do you want to make it always hide the PP, or expand when collapsed and hide when expanded?

Skipping the collapsed state when swiping down after first expanding the PP is easy to do and will be added in the next commit.

> Awesome! Let's test it. We can help with the C++ part if necessary, just ask what is needed. I think I got back to the initial behavior, so unless you want it to be changed, I think we are good. > The margin at the top of the title is too big. This was increased to make the title farther away from the status bar when the PP is fullscreen. I don't really know how to fix both issues at the same time. > It is hard to close PP by swiping it down. There is some resistance that returns it back, or in some cases even opens it full screen. I never noticed it, nothing in the code changes that and it uses Android's native components. > Swiping down PP in a non-preview state should close it (now it is closed only if PP's preview is visible, e.g. the lowest possible height of the PP). Touching the top horizontal line likely also should close it for consistency. The current behavior when tapping on the PP preview is to toggle expanded/collapsed state. Do you want to make it always hide the PP, or expand when collapsed and hide when expanded? Skipping the collapsed state when swiping down after first expanding the PP is easy to do and will be added in the next commit.
biodranik commented 2023-01-20 22:19:53 +00:00 (Migrated from github.com)

This was increased to make the title farther away from the status bar when the PP is fullscreen. I don't really know how to fix both issues at the same time.

PP rarely goes into a full-screen. What about if (fullscreen) then margin += statusbar_height? Or even better, hide the status bar?

I never noticed it, nothing in the code changes that and it uses Android's native components.

Try to expand PP and slightly drag it down. Then drag a bit more and more.

Do you want to make it always hide the PP, or expand when collapsed and hide when expanded?

The latter: expand when collapsed and hide when expanded.

> This was increased to make the title farther away from the status bar when the PP is fullscreen. I don't really know how to fix both issues at the same time. PP rarely goes into a full-screen. What about `if (fullscreen) then margin += statusbar_height`? Or even better, hide the status bar? > I never noticed it, nothing in the code changes that and it uses Android's native components. Try to expand PP and slightly drag it down. Then drag a bit more and more. > Do you want to make it always hide the PP, or expand when collapsed and hide when expanded? The latter: expand when collapsed and hide when expanded.
arnaudvergnet commented 2023-01-21 12:27:41 +00:00 (Migrated from github.com)

PP rarely goes into a full-screen. What about if (fullscreen) then margin += statusbar_height? Or even better, hide the status bar?

I'll experiment with it and see the best results.

Try to expand PP and slightly drag it down. Then drag a bit more and more.

Could you record a video please? I'm not sure I understand, everything works well on my end.

The latter: expand when collapsed and hide when expanded

Done! Please test and let me know what you think.

I pushed a new commit to make the peek height change animation smoother, especially when the place page is expanded and you select a new POI with a place page content smaller/bigger. This prevents the place page from jumping to a bigger/smaller height and then playing the animation.
It is not perfect, there are some edge cases I did not take into account (for example when you grab the sheet when it is resizing), I'll try to refine it but please give it a go and tell me your feedback.

This is one of the reasons I wanted to make the place page always full height. Handling those kind of issues is so complicated, I'm not even sure I'll be able to have a fully working fix. @biodranik I really think we should investigate the possibility of having the place page always full height, this makes everything so much easier and smoother. If closing the sheet is an issue for you, then we can make it so that pressing in an empty area of the sheet closes it. If it looks weird to you, I'm sure that we can find some info about OSM to fill the area.

> PP rarely goes into a full-screen. What about if (fullscreen) then margin += statusbar_height? Or even better, hide the status bar? I'll experiment with it and see the best results. > Try to expand PP and slightly drag it down. Then drag a bit more and more. Could you record a video please? I'm not sure I understand, everything works well on my end. > The latter: expand when collapsed and hide when expanded Done! Please test and let me know what you think. I pushed a new commit to make the peek height change animation smoother, especially when the place page is expanded and you select a new POI with a place page content smaller/bigger. This prevents the place page from jumping to a bigger/smaller height and then playing the animation. It is not perfect, there are some edge cases I did not take into account (for example when you grab the sheet when it is resizing), I'll try to refine it but please give it a go and tell me your feedback. This is one of the reasons I wanted to make the place page always full height. Handling those kind of issues is so complicated, I'm not even sure I'll be able to have a fully working fix. @biodranik I really think we should investigate the possibility of having the place page always full height, this makes everything so much easier and smoother. If closing the sheet is an issue for you, then we can make it so that pressing in an empty area of the sheet closes it. If it looks weird to you, I'm sure that we can find some info about OSM to fill the area.
biodranik (Migrated from github.com) requested changes 2023-01-21 15:14:03 +00:00
biodranik (Migrated from github.com) left a comment
  1. Add stop is displayed for all selected objects in the More... menu. It breaks the UX, as the user can't start the navigation. It's better to remove it.
  2. Removing the Call button is ok.
  3. Showing "add stop" button between from and to buttons in the routing mode is ok.
  4. If "Route from" is selected, or "Route to" is selected without current position, the routing toolbar appears. But "add stop" does not appear between From and To. It should be fixed. It will allow users to build routes in a different way: instead of optional "From", then "To", and then "Add Stop", they can select "From", "Add stop", "Add stop"..., "To".
1. Add stop is displayed for all selected objects in the More... menu. It breaks the UX, as the user can't start the navigation. It's better to remove it. 2. Removing the Call button is ok. 3. Showing "add stop" button between from and to buttons in the routing mode is ok. 4. If "Route from" is selected, or "Route to" is selected without current position, the routing toolbar appears. But "add stop" does not appear between From and To. It should be fixed. It will allow users to build routes in a different way: instead of optional "From", then "To", and then "Add Stop", they can select "From", "Add stop", "Add stop"..., "To".
@ -147,2 +145,4 @@
// if (mElevationInfo != null)
// render(mElevationInfo);
}
biodranik (Migrated from github.com) commented 2023-01-21 14:45:21 +00:00

What is this elevation info?

What is this elevation info?
biodranik (Migrated from github.com) commented 2023-01-21 14:45:53 +00:00

?

?
biodranik (Migrated from github.com) commented 2023-01-21 14:46:47 +00:00

This check should be done before calling initWebView() (it actually already exists there).

This check should be done before calling initWebView() (it actually already exists there).
biodranik (Migrated from github.com) commented 2023-01-21 14:53:15 +00:00

Let's crash here and fix it?

Let's crash here and fix it?
biodranik (Migrated from github.com) commented 2023-01-21 14:53:42 +00:00

nit: final here and in other places.

nit: final here and in other places.
biodranik (Migrated from github.com) commented 2023-01-21 14:54:22 +00:00

Activity a = requireActivity() ?

Activity a = requireActivity() ?
biodranik (Migrated from github.com) commented 2023-01-21 14:55:04 +00:00

When it can be null? Does crashing here help to debug wrong states?

When it can be null? Does crashing here help to debug wrong states?
biodranik (Migrated from github.com) commented 2023-01-21 14:58:42 +00:00

When it can be null? Does crashing here help to fix wrong code?

When it can be null? Does crashing here help to fix wrong code?
vng commented 2023-01-21 23:02:52 +00:00 (Migrated from github.com)

Tested this PR.
Is it possible to show somehow that PP is swipe-able up (expandable).

Here is the initial states for me:
Screenshot_20230121-200017_Organic Maps

But there is enough room to show full PP:
Screenshot_20230121-195523_Organic Maps

If the POI has wiki page, this initial state is like this:
Screenshot_20230121-195514_Organic Maps

Tested this PR. Is it possible to show somehow that PP is swipe-able up (expandable). Here is the initial states for me: ![Screenshot_20230121-200017_Organic Maps](https://user-images.githubusercontent.com/175612/213890436-c85064f3-f562-4cb7-b532-2b8c3f0df70e.jpg) But there is enough room to show full PP: ![Screenshot_20230121-195523_Organic Maps](https://user-images.githubusercontent.com/175612/213890448-3e5b81d4-4b31-4fc8-9dd4-e4d7269bd98b.jpg) If the POI has wiki page, this initial state is like this: ![Screenshot_20230121-195514_Organic Maps](https://user-images.githubusercontent.com/175612/213890456-6156f333-4081-44c2-817b-929d7ca57616.jpg)
Owner

The only UX change is concerning the place page buttons: I removed the phone number button as I always felt it was unnecessary and made buttons placement inconsistent (see #3157). I also removed some logic to change the button order depending on some complexe but IMO useless condition. Now the buttons placement is a lot easier to predict and understand.

This sounds ok to me. Consistent behaviour is better, IMHO. I personally never needed this "Call" button.

Should we keep the place page fragment independent of the bottom sheet? For now the fragment is rendered inside a bottomsheet view. This makes it possible to reuse this fragment in another container for the tablet mode for example.

  • Edit: I think we should keep this approach, especially if we wrap both fragments in a parent fragment. This does not make the code much more complex and offers more modularity.

I would be surprised if we found another place where the place page can be re-used, but it never hurts to reduce the code coupling.

Should we create a fragment to hold both the place page view and the place page buttons fragments?

  • Edit: I think wrapping both in a fragment would be good as it would avoid making the place page callbacks go up to the main activity. This fragment could replace the current controller.

Probably, but not nessasry. Let's finish with the current change first.

Should we split the place page view in smaller fragments? (eg: one for the bookmarks, one for the social links, ...). The current PlacePageView class is 1.5k lines long, which is too much for my liking.

  • Edit: Creating a fragment for the bookmarks, opening hours, phone, social, Wikipedia would make the codebase more manageable as well as reduce the impact of creating a place page with not much information.

Let's eat an elephant one bite at a time.

Is creating the fragment when the user clicks on a feature too slow?

  • Edit: From my limited testing, it does not seem to impact much performance. I think it could even be improved when more sections are migrated to child fragments.

All complex layouts in the original implementation that are created every time users starts the app - this is definitely too slow.

I managed to get the conditional loading of the webview working, and indeed the place page is faster, but you can see the webview loading when opening a place page with an html description.

This is perfect! Previously, the app crashed right on the first start, and we probably lost countless potential users who intentionally or not intentionally broken their system WebView.


I am still reviewing the code itself and trying to comprehend all changes. The PR is already too big to fit into the cache memory. Please don't start any new refactoring in this area until the current changeset is fully polished and merged. Don't spread yourself too thin. :)

> **The only UX change is concerning the place page buttons**: I removed the phone number button as I always felt it was unnecessary and made buttons placement inconsistent (see #3157). I also removed some logic to change the button order depending on some complexe but IMO useless condition. Now the buttons placement is a lot easier to predict and understand. This sounds ok to me. Consistent behaviour is better, IMHO. I personally never needed this "Call" button. > Should we keep the place page fragment independent of the bottom sheet? For now the fragment is rendered inside a bottomsheet view. This makes it possible to reuse this fragment in another container for the tablet mode for example. > > * **Edit:** I think we should keep this approach, especially if we wrap both fragments in a parent fragment. This does not make the code much more complex and offers more modularity. I would be surprised if we found another place where the place page can be re-used, but it never hurts to reduce the code coupling. > Should we create a fragment to hold both the place page view and the place page buttons fragments? > > * **Edit:** I think wrapping both in a fragment would be good as it would avoid making the place page callbacks go up to the main activity. This fragment could replace the current controller. Probably, but not nessasry. Let's finish with the current change first. > Should we split the place page view in smaller fragments? (eg: one for the bookmarks, one for the social links, ...). The current PlacePageView class is 1.5k lines long, which is too much for my liking. > > * **Edit:** Creating a fragment for the bookmarks, opening hours, phone, social, Wikipedia would make the codebase more manageable as well as reduce the impact of creating a place page with not much information. Let's eat an elephant one bite at a time. > Is creating the fragment when the user clicks on a feature too slow? > > * **Edit:** From my limited testing, it does not seem to impact much performance. I think it could even be improved when more sections are migrated to child fragments. All complex layouts in the original implementation that are created every time users starts the app - this is definitely too slow. > I managed to get the conditional loading of the webview working, and indeed the place page is faster, but you can see the webview loading when opening a place page with an html description. This is perfect! Previously, the app crashed right on the first start, and we probably lost countless potential users who intentionally or not intentionally broken their system WebView. -------- I am still reviewing the code itself and trying to comprehend all changes. The PR is already too big to fit into the cache memory. Please don't start any new refactoring in this area until the current changeset is fully polished and merged. Don't spread yourself too thin. :)
rtsisyk reviewed 2023-01-22 08:58:18 +00:00
rtsisyk left a comment
Owner
I found a subtle different in old and new implementation: https://user-images.githubusercontent.com/1799054/213907880-51a0712d-6f74-49bc-95af-673455953db1.mp4 https://user-images.githubusercontent.com/1799054/213907887-b531a304-2784-4471-9723-240c91ec963a.mp4

I also don't understand what is "description header". Could you please add a screenshot?

I also don't understand what is "description header". Could you please add a screenshot?

updateBookmarkDetails() also checks for if (mWvBookmarkNote != null)

`updateBookmarkDetails()` also checks for `if (mWvBookmarkNote != null)`
arnaudvergnet (Migrated from github.com) reviewed 2023-01-23 20:41:01 +00:00
@ -147,2 +145,4 @@
// if (mElevationInfo != null)
// render(mElevationInfo);
}
arnaudvergnet (Migrated from github.com) commented 2023-01-23 20:41:00 +00:00

I don't really know, but it is currently unused and linked to organicmaps/organicmaps#2829

I don't really know, but it is currently unused and linked to https://git.omaps.dev/organicmaps/organicmaps/issues/2829
arnaudvergnet (Migrated from github.com) reviewed 2023-01-23 20:45:44 +00:00
arnaudvergnet (Migrated from github.com) commented 2023-01-23 20:45:44 +00:00

Currently when a bookmark has a note or when a Wikipedia article is available, a grey rectangle with "Description" in it is shown above. With the current state of the refactoring, this header is not shown anymore for bookmark notes. This comment was a reminder for me of this change. I don't think bringing back this header is a good idea, but we should think of a better solution. For now I put the edit bookmark above the notes so we know the notes are linked with the bookmark.

Currently when a bookmark has a note or when a Wikipedia article is available, a grey rectangle with "Description" in it is shown above. With the current state of the refactoring, this header is not shown anymore for bookmark notes. This comment was a reminder for me of this change. I don't think bringing back this header is a good idea, but we should think of a better solution. For now I put the edit bookmark above the notes so we know the notes are linked with the bookmark.
arnaudvergnet (Migrated from github.com) reviewed 2023-01-23 20:49:43 +00:00
arnaudvergnet (Migrated from github.com) commented 2023-01-23 20:49:42 +00:00

I'll look more into this, but when the place page is closed, the mapobject is set to null. The fragment should be destroyed but to make sure I added this check. I can try to remove it and see if it works.

I'll look more into this, but when the place page is closed, the mapobject is set to null. The fragment should be destroyed but to make sure I added this check. I can try to remove it and see if it works.
arnaudvergnet commented 2023-01-23 20:55:49 +00:00 (Migrated from github.com)

Thanks everyone for the feedback!

@biodranik I'll rework the action buttons to take into account your feedback.

Is it possible to show somehow that PP is swipe-able up (expandable).

@vng do you have any idea on how to make the user more aware they can swipe up the place page? The current behavior has been there for quite some time already.

I found a subtle different in old and new implementation:

@rtsisyk this behavior was requested by organicmaps/organicmaps#4174 (comment)

Thanks everyone for the feedback! @biodranik I'll rework the action buttons to take into account your feedback. > Is it possible to show somehow that PP is swipe-able up (expandable). @vng do you have any idea on how to make the user more aware they can swipe up the place page? The current behavior has been there for quite some time already. > I found a subtle different in old and new implementation: @rtsisyk this behavior was requested by https://git.omaps.dev/organicmaps/organicmaps/pulls/4174#issuecomment-1398922207
arnaudvergnet commented 2023-01-23 21:26:24 +00:00 (Migrated from github.com)

@biodranik I fixed the add stop button always in the more menu, and I tried to implement this:

If "Route from" is selected, or "Route to" is selected without current position, the routing toolbar appears. But "add stop" does not appear between From and To. It should be fixed. It will allow users to build routes in a different way: instead of optional "From", then "To", and then "Add Stop", they can select "From", "Add stop", "Add stop"..., "To".

But to make it work, I need the function Framework.nativeCouldAddIntermediatePoint() to return true in the case you describe? For now it only returns true when a route is calculated.

@biodranik I fixed the `add stop` button always in the `more` menu, and I tried to implement this: > If "Route from" is selected, or "Route to" is selected without current position, the routing toolbar appears. But "add stop" does not appear between From and To. It should be fixed. It will allow users to build routes in a different way: instead of optional "From", then "To", and then "Add Stop", they can select "From", "Add stop", "Add stop"..., "To". But to make it work, I need the function `Framework.nativeCouldAddIntermediatePoint()` to return true in the case you describe? For now it only returns true when a route is calculated.
arnaudvergnet (Migrated from github.com) reviewed 2023-01-23 21:39:24 +00:00
arnaudvergnet (Migrated from github.com) commented 2023-01-23 21:39:24 +00:00

When the place page is closed, the mapObject is set to null. The controller detects when this value becomes null and destroys the fragments. But this means the fragments themselves could receive the event that the mapObject became null.

One way to fix this would be to destroy the fragments and then set the value to null, or never set it to null.

When the place page is closed, the mapObject is set to null. The controller detects when this value becomes null and destroys the fragments. But this means the fragments themselves could receive the event that the mapObject became null. One way to fix this would be to destroy the fragments and then set the value to null, or never set it to null.
vng commented 2023-01-23 22:09:01 +00:00 (Migrated from github.com)
  • I don't know, probably some arrow instead of grey line in the middle .. Can't say for sure. Maybe Android dev guide has some expandable elements with swipe up ...
  • Is it possible to show expanded PP if its size is <= 1/3 (1/2) of the device's height?
- I don't know, probably some arrow instead of grey line in the middle .. Can't say for sure. Maybe Android dev guide has some expandable elements with swipe up ... - Is it possible to show expanded PP if its size is <= 1/3 (1/2) of the device's height?
biodranik (Migrated from github.com) reviewed 2023-01-23 22:12:15 +00:00
biodranik (Migrated from github.com) commented 2023-01-23 22:12:15 +00:00

Does it mean that the "description" header is displayed now only for Wiki articles? Let's remove it completely. It occupies an important PP space.

Does it mean that the "description" header is displayed now only for Wiki articles? Let's remove it completely. It occupies an important PP space.
arnaudvergnet commented 2023-01-23 22:12:46 +00:00 (Migrated from github.com)

Is it possible to show expanded PP if its size is <= 1/3 of the device's height?

That would make it hard for users to predict where the place page will stop when clicking on a POI. Would it be better to always make the place page initially open to the same height, no matter the content? The current preview does not give much more information than what is already on the map so you often have to expand the place page to see useful information.

> Is it possible to show expanded PP if its size is <= 1/3 of the device's height? That would make it hard for users to predict where the place page will stop when clicking on a POI. Would it be better to always make the place page initially open to the same height, no matter the content? The current preview does not give much more information than what is already on the map so you often have to expand the place page to see useful information.
biodranik (Migrated from github.com) reviewed 2023-01-23 22:14:57 +00:00
biodranik (Migrated from github.com) commented 2023-01-23 22:14:57 +00:00

Is it possible to unsubscribe first, before setting a null map object?

If it's too complex to fix now, then please add your comment above to the code.

Is it possible to unsubscribe first, before setting a null map object? If it's too complex to fix now, then please add your comment above to the code.
vng commented 2023-01-23 22:17:56 +00:00 (Migrated from github.com)

And I think there is a lot of empty space between grey line and first bold text.
PP-height

And I think there is a lot of empty space between grey line and first bold text. ![PP-height](https://user-images.githubusercontent.com/175612/214162554-dd0087bf-a1eb-4950-99b6-6230b3e497d0.png)
arnaudvergnet commented 2023-01-23 22:19:49 +00:00 (Migrated from github.com)

And I think there is a lot of empty space between grey line and first bold text.

This was to avoid the title from being too close to the statusbar when expanding fullscreen. I'll try to find a better way to fix that.

> And I think there is a lot of empty space between grey line and first bold text. This was to avoid the title from being too close to the statusbar when expanding fullscreen. I'll try to find a better way to fix that.
vng commented 2023-01-23 22:19:59 +00:00 (Migrated from github.com)

Probably same height is ok, but with check on maximum content size. To avoid empty white space top or bottom.

Probably same height is ok, but with check on maximum content size. To avoid empty white space top or bottom.
vng commented 2023-01-23 22:21:21 +00:00 (Migrated from github.com)

All my comments are for discussion and may be controversial. Please, don't hurry to implement :)

All my comments are for discussion and may be controversial. Please, don't hurry to implement :)
biodranik commented 2023-01-23 22:27:52 +00:00 (Migrated from github.com)

I found a subtle different in old and new implementation:

It shouldn't be critical.

@vng do you have any idea on how to make the user more aware they can swipe up the place page? The current behavior has been there for quite some time already.

A simple trick is used on iOS. Instead of a horizontal line, when PP can be expanded, a > rotated to 90 degrees left is displayed. When PP can be closed, a > rotated 90 degrees right is displayed. These symbols have very small heights and big widths to take up less vertical space.

Would it be better to always make the place page initially open to the same height, no matter the content?

We need to rethink it carefully. After saving some important vertical space, we can try to expand some important info, e.g. up to 2 or 3 useful rows, while ignoring coordinates and edit buttons. Let's leave it for the next steps.

Showing a predictable height has it's advantages if it is consistent for specific conditions: e.g. only all features without wiki/bookmark description/osm description are not expanded, etc.

And I think there is a lot of empty space between grey line and first bold text.

I mentioned it before. We need to find a way to fix it to avoid overlapping with the system toolbar.

But to make it work, I need the function Framework.nativeCouldAddIntermediatePoint() to return true in the case you describe? For now it only returns true when a route is calculated.

Let's leave this change for the next PR. It will need some testing. I would suggest to create a checklist issue with all we mentioned here.

Let's focus on testing and merging this PR, it is important for the upcoming release (actually, it blocks the release).

> I found a subtle different in old and new implementation: It shouldn't be critical. > @vng do you have any idea on how to make the user more aware they can swipe up the place page? The current behavior has been there for quite some time already. A simple trick is used on iOS. Instead of a horizontal line, when PP can be expanded, a > rotated to 90 degrees left is displayed. When PP can be closed, a > rotated 90 degrees right is displayed. These symbols have very small heights and big widths to take up less vertical space. > Would it be better to always make the place page initially open to the same height, no matter the content? We need to rethink it carefully. After saving some important vertical space, we can try to expand some important info, e.g. up to 2 or 3 useful rows, while ignoring coordinates and edit buttons. Let's leave it for the next steps. Showing a predictable height has it's advantages if it is consistent for specific conditions: e.g. only all features without wiki/bookmark description/osm description are not expanded, etc. > And I think there is a lot of empty space between grey line and first bold text. I mentioned it before. We need to find a way to fix it to avoid overlapping with the system toolbar. > But to make it work, I need the function Framework.nativeCouldAddIntermediatePoint() to return true in the case you describe? For now it only returns true when a route is calculated. Let's leave this change for the next PR. It will need some testing. I would suggest to create a checklist issue with all we mentioned here. Let's focus on testing and merging this PR, it is important for the upcoming release (actually, it blocks the release).
arnaudvergnet commented 2023-01-23 23:20:49 +00:00 (Migrated from github.com)

A simple trick is used on iOS. Instead of a horizontal line, when PP can be expanded, a > rotated to 90 degrees left is displayed. When PP can be closed, a > rotated 90 degrees right is displayed. These symbols have very small heights and big widths to take up less vertical space.

The previous android version had a similar thing. I removed it in earlier refactoring (when I migrated the place page to Android's bottom sheet implementation) to make it more consistent with other bottom sheet and because it was ugly and blurry. I haven't seen many apps with arrows as bottom sheet handles, so I don't know if that would help the user much. IMO the users are more used to seeing a flat handle meaning they can grab and swipe it (see https://m3.material.io/components/bottom-sheets/overview). Maybe a small text saying "v expand to see more v" at the bottom of the preview would help?

I mentioned it before. We need to find a way to fix it to avoid overlapping with the system toolbar.

How about preventing the place page to expand fullscreen so it stops slightly before the statusbar?

I also noticed an issue, if you expand the place page, then select a new item which content is exactly the same height (eg: two address nodes), then the place page will stay expanded and not collapse. EDIT: this is now fixed

> A simple trick is used on iOS. Instead of a horizontal line, when PP can be expanded, a > rotated to 90 degrees left is displayed. When PP can be closed, a > rotated 90 degrees right is displayed. These symbols have very small heights and big widths to take up less vertical space. The previous android version had a similar thing. I removed it in earlier refactoring (when I migrated the place page to Android's bottom sheet implementation) to make it more consistent with other bottom sheet and because it was ugly and blurry. I haven't seen many apps with arrows as bottom sheet handles, so I don't know if that would help the user much. IMO the users are more used to seeing a flat handle meaning they can grab and swipe it (see https://m3.material.io/components/bottom-sheets/overview). Maybe a small text saying "v expand to see more v" at the bottom of the preview would help? > I mentioned it before. We need to find a way to fix it to avoid overlapping with the system toolbar. How about preventing the place page to expand fullscreen so it stops slightly before the statusbar? I also noticed an issue, if you expand the place page, then select a new item which content is exactly the same height (eg: two address nodes), then the place page will stay expanded and not collapse. **EDIT**: this is now fixed
arnaudvergnet commented 2023-01-24 21:26:46 +00:00 (Migrated from github.com)

I fixed all the issues I could find with the refactoring, so I'll start working on the description. I'll refer to organicmaps/organicmaps#1953 for design ideas.

I was also wondering if it would be better to move large or html bookmark descriptions in a new screen/activity the user can access with button like the "more" button on a wiki summary. In case imported bookmark notes are very large, it could be hard to reach useful information displayed after.

I fixed all the issues I could find with the refactoring, so I'll start working on the description. I'll refer to https://git.omaps.dev/organicmaps/organicmaps/issues/1953 for design ideas. I was also wondering if it would be better to move large or html bookmark descriptions in a new screen/activity the user can access with button like the "more" button on a wiki summary. In case imported bookmark notes are very large, it could be hard to reach useful information displayed after.
Member

it'd be good to keep image display (organicmaps/organicmaps#3171 organicmaps/organicmaps#2152 organicmaps/organicmaps#3252) in mind for refactoring too :)

it'd be good to keep image display (https://git.omaps.dev/organicmaps/organicmaps/issues/3171 https://git.omaps.dev/organicmaps/organicmaps/issues/2152 https://git.omaps.dev/organicmaps/organicmaps/issues/3252) in mind for refactoring too :)
arnaudvergnet commented 2023-01-25 17:19:53 +00:00 (Migrated from github.com)

it'd be good to keep image display (organicmaps/organicmaps#3171 organicmaps/organicmaps#2152 organicmaps/organicmaps#3252) in mind for refactoring too :)

Those kind of features are why I think we should try and make the place page always take the whole height. Content loading after the page is shown will change the place page size, and we will need to handle animating between the different sizes with the current implementation.

> it'd be good to keep image display (https://git.omaps.dev/organicmaps/organicmaps/issues/3171 https://git.omaps.dev/organicmaps/organicmaps/issues/2152 https://git.omaps.dev/organicmaps/organicmaps/issues/3252) in mind for refactoring too :) Those kind of features are why I think we should try and make the place page always take the whole height. Content loading after the page is shown will change the place page size, and we will need to handle animating between the different sizes with the current implementation.
vng commented 2023-01-25 17:43:32 +00:00 (Migrated from github.com)
01-25 19:09:27.951 E/AndroidRuntime(16091): FATAL EXCEPTION: main
01-25 19:09:27.951 E/AndroidRuntime(16091): Process: app.organicmaps.beta, PID: 16091
01-25 19:09:27.951 E/AndroidRuntime(16091): java.lang.NullPointerException: Attempt to invoke virtual method 'double app.organicmaps.bookmarks.data.MapObject.getLat()' on a null object reference
01-25 19:09:27.951 E/AndroidRuntime(16091): 	at app.organicmaps.widget.placepage.PlacePageView.refreshDistanceToObject(Unknown Source:15)
01-25 19:09:27.951 E/AndroidRuntime(16091): 	at app.organicmaps.widget.placepage.PlacePageView.onLocationUpdated(Unknown Source:13)
01-25 19:09:27.951 E/AndroidRuntime(16091): 	at app.organicmaps.location.LocationHelper.addListener(Unknown Source:45)
01-25 19:09:27.951 E/AndroidRuntime(16091): 	at app.organicmaps.widget.placepage.PlacePageView.onViewCreated(Unknown Source:928)
01-25 19:09:27.951 E/AndroidRuntime(16091): 	at androidx.fragment.app.Fragment.performViewCreated(Unknown Source:4)
01-25 19:09:27.951 E/AndroidRuntime(16091): 	at androidx.fragment.app.FragmentStateManager.createView(Unknown Source:272)

From beta tester: When starting pedestrian navigation.

``` 01-25 19:09:27.951 E/AndroidRuntime(16091): FATAL EXCEPTION: main 01-25 19:09:27.951 E/AndroidRuntime(16091): Process: app.organicmaps.beta, PID: 16091 01-25 19:09:27.951 E/AndroidRuntime(16091): java.lang.NullPointerException: Attempt to invoke virtual method 'double app.organicmaps.bookmarks.data.MapObject.getLat()' on a null object reference 01-25 19:09:27.951 E/AndroidRuntime(16091): at app.organicmaps.widget.placepage.PlacePageView.refreshDistanceToObject(Unknown Source:15) 01-25 19:09:27.951 E/AndroidRuntime(16091): at app.organicmaps.widget.placepage.PlacePageView.onLocationUpdated(Unknown Source:13) 01-25 19:09:27.951 E/AndroidRuntime(16091): at app.organicmaps.location.LocationHelper.addListener(Unknown Source:45) 01-25 19:09:27.951 E/AndroidRuntime(16091): at app.organicmaps.widget.placepage.PlacePageView.onViewCreated(Unknown Source:928) 01-25 19:09:27.951 E/AndroidRuntime(16091): at androidx.fragment.app.Fragment.performViewCreated(Unknown Source:4) 01-25 19:09:27.951 E/AndroidRuntime(16091): at androidx.fragment.app.FragmentStateManager.createView(Unknown Source:272) ``` From beta tester: When starting pedestrian navigation.
arnaudvergnet commented 2023-01-25 22:13:26 +00:00 (Migrated from github.com)

Could not reproduce the crash, is it possible to get more information on how it was triggered?

I moved the Wikipedia section to its own fragment, so now I can start working on the OSM description.

Could not reproduce the crash, is it possible to get more information on how it was triggered? I moved the Wikipedia section to its own fragment, so now I can start working on the OSM description.
vng commented 2023-01-25 22:16:00 +00:00 (Migrated from github.com)

Same crash with identical call stack (Pixel 6, android 13): "OM beta crashes when clicking on a poi and then rotating the phone."

Same crash with identical call stack (Pixel 6, android 13): "OM beta crashes when clicking on a poi and then rotating the phone."
arnaudvergnet commented 2023-01-25 22:52:16 +00:00 (Migrated from github.com)

Thanks, will investigate.

I also tried to add the OSM description but I don't understand how to retrieve it. I tried using mMapObject.getMetadata(Metadata.MetadataType.FMD_DESCRIPTION); but the resulting string is always empty, even on nodes I know have a description. Is there another way to get it?

Thanks, will investigate. I also tried to add the OSM description but I don't understand how to retrieve it. I tried using `mMapObject.getMetadata(Metadata.MetadataType.FMD_DESCRIPTION);` but the resulting string is always empty, even on nodes I know have a description. Is there another way to get it?
vng commented 2023-01-26 01:18:43 +00:00 (Migrated from github.com)

map_object.cpp, ForEachMetadataReadable

/// @todo Skip description for now, because it's not a valid UTF8 string.
/// @see EditableMapObject::ForEachMetadataItem.
case MetadataID::FMD_DESCRIPTION: break;

If you want to add description, we should invent some way to pass StringUtf8Multilang into Java. Leave it for separate PR.

map_object.cpp, ForEachMetadataReadable ``` /// @todo Skip description for now, because it's not a valid UTF8 string. /// @see EditableMapObject::ForEachMetadataItem. case MetadataID::FMD_DESCRIPTION: break; ``` If you want to add description, we should invent some way to pass StringUtf8Multilang into Java. Leave it for separate PR.
biodranik commented 2023-01-26 11:57:03 +00:00 (Migrated from github.com)

If you want to add description, we should invent some way to pass StringUtf8Multilang into Java. Leave it for separate PR.

+1 for the separate PR.

Let's think about the interface to query descriptions. Do we need them in all languages at once? Maybe there should be API like this:

  1. string GetOSMDescriptionForLanguage(lang);
  2. string GetOSMDescriptionLanguages(); // returns languages delimited by ;
  3. And for the editor in the future: SetOSMDescriptionForLanguage(lang, newDescription).
> If you want to add description, we should invent some way to pass StringUtf8Multilang into Java. Leave it for separate PR. +1 for the separate PR. Let's think about the interface to query descriptions. Do we need them in all languages at once? Maybe there should be API like this: 1. string GetOSMDescriptionForLanguage(lang); 2. string GetOSMDescriptionLanguages(); // returns languages delimited by ; 3. And for the editor in the future: SetOSMDescriptionForLanguage(lang, newDescription).
biodranik commented 2023-01-26 12:48:55 +00:00 (Migrated from github.com)

IMO the users are more used to seeing a flat handle meaning they can grab and swipe it (see https://m3.material.io/components/bottom-sheets/overview). Maybe a small text saying "v expand to see more v" at the bottom of the preview would help?

Most apps are now using the flat handle, Apple maps (and OM for iOS) also draw an X button on the top right. Let's discuss it later separately.

How about preventing the place page to expand fullscreen so it stops slightly before the statusbar?

I don't think that it will work with longer Place Pages. It is logical to drag/scroll everything, not just some content view.

Those kind of features are why I think we should try and make the place page always take the whole height. Content loading after the page is shown will change the place page size, and we will need to handle animating between the different sizes with the current implementation.

We can always pre-calculate max image heights and fit images there. Always full-screen PP makes UX worse if it's almost empty, so, unfortunately, it is not an option. Let's think what can we do in a different way to simplify the implementation.

> IMO the users are more used to seeing a flat handle meaning they can grab and swipe it (see https://m3.material.io/components/bottom-sheets/overview). Maybe a small text saying "v expand to see more v" at the bottom of the preview would help? Most apps are now using the flat handle, Apple maps (and OM for iOS) also draw an X button on the top right. Let's discuss it later separately. > How about preventing the place page to expand fullscreen so it stops slightly before the statusbar? I don't think that it will work with longer Place Pages. It is logical to drag/scroll everything, not just some content view. > Those kind of features are why I think we should try and make the place page always take the whole height. Content loading after the page is shown will change the place page size, and we will need to handle animating between the different sizes with the current implementation. We can always pre-calculate max image heights and fit images there. Always full-screen PP makes UX worse if it's almost empty, so, unfortunately, it is not an option. Let's think what can we do in a different way to simplify the implementation.
biodranik commented 2023-01-26 17:48:21 +00:00 (Migrated from github.com)
01-25 22:59:11.632 E/AndroidRuntime(12464): java.lang.NullPointerException: Attempt to invoke virtual method 'double app.organicmaps.bookmarks.data.MapObject.getLat()' on a null object reference
01-25 22:59:11.632 E/AndroidRuntime(12464): 	at app.organicmaps.widget.placepage.PlacePageView.refreshDistanceToObject(Unknown Source:15)
01-25 22:59:11.632 E/AndroidRuntime(12464): 	at app.organicmaps.widget.placepage.PlacePageView.onLocationUpdated(Unknown Source:13)
01-25 22:59:11.632 E/AndroidRuntime(12464): 	at app.organicmaps.location.LocationHelper.addListener(Unknown Source:45)
01-25 22:59:11.632 E/AndroidRuntime(12464): 	at app.organicmaps.widget.placepage.PlacePageView.onViewCreated(Unknown Source:928)
01-25 22:59:11.632 E/AndroidRuntime(12464): 	at androidx.fragment.app.Fragment.performViewCreated(Unknown Source:4)
01-25 22:59:11.632 E/AndroidRuntime(12464): 	at androidx.fragment.app.FragmentStateManager.createView(Unknown Source:272)
01-25 22:59:11.632 E/AndroidRuntime(12464): 	at androidx.fragment.app.FragmentStateManager.moveToExpectedState(Unknown Source:124)
01-25 22:59:11.632 E/AndroidRuntime(12464): 	at androidx.fragment.app.FragmentStore.moveToExpectedState(Unknown Source:30)
01-25 22:59:11.632 E/AndroidRuntime(12464): 	at androidx.fragment.app.FragmentManager.moveToState(Unknown Source:27)
01-25 22:59:11.632 E/AndroidRuntime(12464): 	at androidx.fragment.app.FragmentManager.dispatchStateChange(Unknown Source:9)
01-25 22:59:11.632 E/AndroidRuntime(12464): 	at androidx.fragment.app.FragmentManager.dispatchActivityCreated(Unknown Source:11)
01-25 22:59:11.632 E/AndroidRuntime(12464): 	at androidx.fragment.app.FragmentController.dispatchActivityCreated(Unknown Source:4)
01-25 22:59:11.632 E/AndroidRuntime(12464): 	at androidx.fragment.app.FragmentActivity.onStart(Unknown Source:20)
01-25 22:59:11.632 E/AndroidRuntime(12464): 	at androidx.appcompat.app.AppCompatActivity.onStart(Unknown Source:0)
01-25 22:59:11.632 E/AndroidRuntime(12464): 	at app.organicmaps.base.BaseMwmFragmentActivity.onStart(Unknown Source:0)
01-25 22:59:11.632 E/AndroidRuntime(12464): 	at app.organicmaps.MwmActivity.onStart(Unknown Source:0)
01-25 22:59:11.632 E/AndroidRuntime(12464): 	at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1543)
01-25 22:59:11.632 E/AndroidRuntime(12464): 	at android.app.Activity.performStart(Activity.java:8330)
01-25 22:59:11.632 E/AndroidRuntime(12464): 	at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3670)
01-25 22:59:11.632 E/AndroidRuntime(12464): 	at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:221)
01-25 22:59:11.632 E/AndroidRuntime(12464): 	at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:201)
01-25 22:59:11.632 E/AndroidRuntime(12464): 	at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:173)
01-25 22:59:11.632 E/AndroidRuntime(12464): 	at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
01-25 22:59:11.632 E/AndroidRuntime(12464): 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2307)
01-25 22:59:11.632 E/AndroidRuntime(12464): 	at android.os.Handler.dispatchMessage(Handler.java:106)
01-25 22:59:11.632 E/AndroidRuntime(12464): 	at android.os.Looper.loopOnce(Looper.java:201)
01-25 22:59:11.632 E/AndroidRuntime(12464): 	at android.os.Looper.loop(Looper.java:288)
01-25 22:59:11.632 E/AndroidRuntime(12464): 	at android.app.ActivityThread.main(ActivityThread.java:7872)
01-25 22:59:11.632 E/AndroidRuntime(12464): 	at java.lang.reflect.Method.invoke(Native Method)
01-25 22:59:11.632 E/AndroidRuntime(12464): 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
01-25 22:59:11.632 E/AndroidRuntime(12464): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
``` 01-25 22:59:11.632 E/AndroidRuntime(12464): java.lang.NullPointerException: Attempt to invoke virtual method 'double app.organicmaps.bookmarks.data.MapObject.getLat()' on a null object reference 01-25 22:59:11.632 E/AndroidRuntime(12464): at app.organicmaps.widget.placepage.PlacePageView.refreshDistanceToObject(Unknown Source:15) 01-25 22:59:11.632 E/AndroidRuntime(12464): at app.organicmaps.widget.placepage.PlacePageView.onLocationUpdated(Unknown Source:13) 01-25 22:59:11.632 E/AndroidRuntime(12464): at app.organicmaps.location.LocationHelper.addListener(Unknown Source:45) 01-25 22:59:11.632 E/AndroidRuntime(12464): at app.organicmaps.widget.placepage.PlacePageView.onViewCreated(Unknown Source:928) 01-25 22:59:11.632 E/AndroidRuntime(12464): at androidx.fragment.app.Fragment.performViewCreated(Unknown Source:4) 01-25 22:59:11.632 E/AndroidRuntime(12464): at androidx.fragment.app.FragmentStateManager.createView(Unknown Source:272) 01-25 22:59:11.632 E/AndroidRuntime(12464): at androidx.fragment.app.FragmentStateManager.moveToExpectedState(Unknown Source:124) 01-25 22:59:11.632 E/AndroidRuntime(12464): at androidx.fragment.app.FragmentStore.moveToExpectedState(Unknown Source:30) 01-25 22:59:11.632 E/AndroidRuntime(12464): at androidx.fragment.app.FragmentManager.moveToState(Unknown Source:27) 01-25 22:59:11.632 E/AndroidRuntime(12464): at androidx.fragment.app.FragmentManager.dispatchStateChange(Unknown Source:9) 01-25 22:59:11.632 E/AndroidRuntime(12464): at androidx.fragment.app.FragmentManager.dispatchActivityCreated(Unknown Source:11) 01-25 22:59:11.632 E/AndroidRuntime(12464): at androidx.fragment.app.FragmentController.dispatchActivityCreated(Unknown Source:4) 01-25 22:59:11.632 E/AndroidRuntime(12464): at androidx.fragment.app.FragmentActivity.onStart(Unknown Source:20) 01-25 22:59:11.632 E/AndroidRuntime(12464): at androidx.appcompat.app.AppCompatActivity.onStart(Unknown Source:0) 01-25 22:59:11.632 E/AndroidRuntime(12464): at app.organicmaps.base.BaseMwmFragmentActivity.onStart(Unknown Source:0) 01-25 22:59:11.632 E/AndroidRuntime(12464): at app.organicmaps.MwmActivity.onStart(Unknown Source:0) 01-25 22:59:11.632 E/AndroidRuntime(12464): at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1543) 01-25 22:59:11.632 E/AndroidRuntime(12464): at android.app.Activity.performStart(Activity.java:8330) 01-25 22:59:11.632 E/AndroidRuntime(12464): at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3670) 01-25 22:59:11.632 E/AndroidRuntime(12464): at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:221) 01-25 22:59:11.632 E/AndroidRuntime(12464): at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:201) 01-25 22:59:11.632 E/AndroidRuntime(12464): at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:173) 01-25 22:59:11.632 E/AndroidRuntime(12464): at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97) 01-25 22:59:11.632 E/AndroidRuntime(12464): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2307) 01-25 22:59:11.632 E/AndroidRuntime(12464): at android.os.Handler.dispatchMessage(Handler.java:106) 01-25 22:59:11.632 E/AndroidRuntime(12464): at android.os.Looper.loopOnce(Looper.java:201) 01-25 22:59:11.632 E/AndroidRuntime(12464): at android.os.Looper.loop(Looper.java:288) 01-25 22:59:11.632 E/AndroidRuntime(12464): at android.app.ActivityThread.main(ActivityThread.java:7872) 01-25 22:59:11.632 E/AndroidRuntime(12464): at java.lang.reflect.Method.invoke(Native Method) 01-25 22:59:11.632 E/AndroidRuntime(12464): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) 01-25 22:59:11.632 E/AndroidRuntime(12464): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936) ```
arnaudvergnet commented 2023-01-26 20:24:48 +00:00 (Migrated from github.com)

@vng @biodranik the reported crashes should be fixed.

If you want to add description, we should invent some way to pass StringUtf8Multilang into Java. Leave it for separate PR.

I'll continue with the refactoring by moving more parts of the place page in different fragments to make it more manageable.

Let's think about the interface to query descriptions. Do we need them in all languages at once?

Should we use the same logic as for the title? Device language first then fallback to local language.

I don't think that it will work with longer Place Pages. It is logical to drag/scroll everything, not just some content view.

We can set the max height of the bottom sheet to a value smaller than the screen height. When it reaches this value, then the user can scroll the content. But yeah it might not be the best UX wise.

@vng @biodranik the reported crashes should be fixed. > If you want to add description, we should invent some way to pass StringUtf8Multilang into Java. Leave it for separate PR. I'll continue with the refactoring by moving more parts of the place page in different fragments to make it more manageable. > Let's think about the interface to query descriptions. Do we need them in all languages at once? Should we use the same logic as for the title? Device language first then fallback to local language. > I don't think that it will work with longer Place Pages. It is logical to drag/scroll everything, not just some content view. We can set the max height of the bottom sheet to a value smaller than the screen height. When it reaches this value, then the user can scroll the content. But yeah it might not be the best UX wise.
biodranik (Migrated from github.com) reviewed 2023-01-26 20:34:56 +00:00
biodranik (Migrated from github.com) commented 2023-01-26 20:34:45 +00:00

Why is PP subscribed to location updates at this moment? Wouldn't it be wiser/better/faster/safer to subscribe to location updates when MapObject is set, and unsubscribe when it's cleared?

Why is PP subscribed to location updates at this moment? Wouldn't it be wiser/better/faster/safer to subscribe to location updates when MapObject is set, and unsubscribe when it's cleared?
arnaudvergnet (Migrated from github.com) reviewed 2023-01-26 20:40:07 +00:00
arnaudvergnet (Migrated from github.com) commented 2023-01-26 20:40:06 +00:00

We subscribe to location updates when the fragment is created, at the same time we subscribe to map object updates. But it seems that after an orientation change, the location is updated before the map object. I tried moving the subscription later in the lifecycle but it changed nothing.

A solution would be to subscribe to location change when the map object gets a value for the first time.

We subscribe to location updates when the fragment is created, at the same time we subscribe to map object updates. But it seems that after an orientation change, the location is updated before the map object. I tried moving the subscription later in the lifecycle but it changed nothing. A solution would be to subscribe to location change when the map object gets a value for the first time.
arnaudvergnet (Migrated from github.com) reviewed 2023-01-26 20:54:17 +00:00
arnaudvergnet (Migrated from github.com) commented 2023-01-26 20:54:17 +00:00

Found a better way, I simply initialize the mMapObjet value in onCreateView before registering for the location events

Found a better way, I simply initialize the mMapObjet value in onCreateView before registering for the location events
biodranik (Migrated from github.com) reviewed 2023-01-26 21:09:44 +00:00
biodranik (Migrated from github.com) commented 2023-01-26 21:09:44 +00:00

👍 then these checks are not necessary and can be removed, right?

👍 then these checks are not necessary and can be removed, right?
Jean-BaptisteC commented 2023-01-26 22:39:25 +00:00 (Migrated from github.com)

I have doing some tests, when i consult POI (without lot of informations), i open editor, i go back on place page -> location button is hide by place page and buttons zoom are down

I have detect crash but i don't know if it's caused by your rework (i don't able to reproduce on latest release):

  • Start OM without map data
  • Download world map
  • Click on location button -> to focus map on your position, dowload map around you
  • Click on your position -> cancel download from bottomsheet
  • Relaunch download from bottomsheet -> app crashed
I have doing some tests, when i consult POI (without lot of informations), i open editor, i go back on place page -> location button is hide by place page and buttons zoom are down I have detect crash but i don't know if it's caused by your rework (i don't able to reproduce on latest release): - Start OM without map data - Download world map - Click on location button -> to focus map on your position, dowload map around you - Click on your position -> cancel download from bottomsheet - Relaunch download from bottomsheet -> app crashed
biodranik commented 2023-01-28 09:22:02 +00:00 (Migrated from github.com)

The latest public release doesn't have these changes. They were only included in the beta version.
@rtsisyk @vng @arnaudvergnet @Jean-BaptisteC let's focus on testing and polishing this PR, it is very important to be appropriately finished, without introducing any new bugs.

The latest public release doesn't have these changes. They were only included in the beta version. @rtsisyk @vng @arnaudvergnet @Jean-BaptisteC let's focus on testing and polishing this PR, it is very important to be appropriately finished, without introducing any new bugs.
arnaudvergnet commented 2023-01-28 21:03:52 +00:00 (Migrated from github.com)

I have doing some tests, when i consult POI (without lot of informations), i open editor, i go back on place page -> location button is hide by place page and buttons zoom are down

This should now be fixed

I have detect crash but i don't know if it's caused by your rework (i don't able to reproduce on latest release):

Damn fine testing, thanks a lot! I was able to reproduce I'll work on a fix

> I have doing some tests, when i consult POI (without lot of informations), i open editor, i go back on place page -> location button is hide by place page and buttons zoom are down This should now be fixed > I have detect crash but i don't know if it's caused by your rework (i don't able to reproduce on latest release): Damn fine testing, thanks a lot! I was able to reproduce I'll work on a fix
arnaudvergnet commented 2023-01-28 22:01:48 +00:00 (Migrated from github.com)

I'll need some help on this one. The error comes from JNI but I do not have much experience with it.

JNI ERROR (app bug): attempt to use stale Global 0x2e1a (should be 0x2e12)
java_vm_ext.cc:577] JNI DETECTED ERROR IN APPLICATION: use of deleted global reference 0x2e1a
java_vm_ext.cc:577]     from void app.organicmaps.downloader.MapManager.nativeDownload(java.lang.String)
runtime.cc:655] Runtime aborting...

It occurs when calling the OnClick from mDownloadClickListener in PlacePageView. I don't really know why my changes make this crash.

I'll need some help on this one. The error comes from JNI but I do not have much experience with it. ``` JNI ERROR (app bug): attempt to use stale Global 0x2e1a (should be 0x2e12) java_vm_ext.cc:577] JNI DETECTED ERROR IN APPLICATION: use of deleted global reference 0x2e1a java_vm_ext.cc:577] from void app.organicmaps.downloader.MapManager.nativeDownload(java.lang.String) runtime.cc:655] Runtime aborting... ``` It occurs when calling the `OnClick` from `mDownloadClickListener` in `PlacePageView`. I don't really know why my changes make this crash.
biodranik commented 2023-01-28 22:21:23 +00:00 (Migrated from github.com)

Wow, thanks for the details. So now PP is recreated every time, right? Compared to the master branch, where it is created only once, correct?
I think there are some global variables in JNI that assume that PP is created only once, or not recreated on every new PP, or wrongly cleaned on PP destroy.

I, @vng, or @rtsisyk will take a look. @Jean-BaptisteC you're the God of the QA, thanks! :)

Wow, thanks for the details. So now PP is recreated every time, right? Compared to the master branch, where it is created only once, correct? I think there are some global variables in JNI that assume that PP is created only once, or not recreated on every new PP, or wrongly cleaned on PP destroy. I, @vng, or @rtsisyk will take a look. @Jean-BaptisteC you're the God of the QA, thanks! :)
arnaudvergnet commented 2023-01-28 22:32:16 +00:00 (Migrated from github.com)

I tried starting and canceling the download from the dialog shown on the map, and it works every time. But as soon as I open the place page, clicking on the same button in the dialog (which worked before) now crashes the app.

Right now the PP is destroyed when hidden, and recreated when shown. But I don't understand how that would be an issue.

I tried starting and canceling the download from the dialog shown on the map, and it works every time. But as soon as I open the place page, clicking on the same button in the dialog (which worked before) now crashes the app. Right now the PP is destroyed when hidden, and recreated when shown. But I don't understand how that would be an issue.
arnaudvergnet commented 2023-01-28 22:34:54 +00:00 (Migrated from github.com)

Here is a short example. Even when closing the PP, the button crashes.

https://user-images.githubusercontent.com/80701113/215294148-c5530b31-09af-4bd6-b74a-e69e7b6c76fb.mp4

Here is a short example. Even when closing the PP, the button crashes. https://user-images.githubusercontent.com/80701113/215294148-c5530b31-09af-4bd6-b74a-e69e7b6c76fb.mp4
biodranik (Migrated from github.com) reviewed 2023-02-02 17:43:41 +00:00
biodranik (Migrated from github.com) commented 2023-02-02 17:43:40 +00:00

@arnaudvergnet On the device I have this error:

02-02 18:18:25.200 30175 30175 F ganicmaps.debu: runtime.cc:590] Pending exception java.lang.IllegalStateException: Fragment PlacePageView{9d2b38f} (5086c6c7-c27c-4547-a594-a2e8249b8f4f) not attached to a context.
02-02 18:18:25.200 30175 30175 F ganicmaps.debu: runtime.cc:590]   at void app.organicmaps.widget.placepage.PlacePageView.updateDownloader(app.organicmaps.downloader.CountryItem) (PlacePageView.java:1167)
02-02 18:18:25.200 30175 30175 F ganicmaps.debu: runtime.cc:590]   at void app.organicmaps.widget.placepage.PlacePageView.updateDownloader() (PlacePageView.java:1181)

And 02-02 18:18:25.200 30175 30175 F ganicmaps.debu: runtime.cc:598] JNI DETECTED ERROR IN APPLICATION: JNI NewObjectV called with pending exception java.lang.IllegalStateException: Fragment PlacePageView{9d2b38f} (5086c6c7-c27c-4547-a594-a2e8249b8f4f) not attached to a context.

It looks like the downloader code does not work now as before.

Internally it is a complex jni/C++ implementation that downloads map files from C++, but notifies the subscribed Place Page by calling callbacks. Maybe these callbacks are incorrectly handled now.

@arnaudvergnet On the device I have this error: ``` 02-02 18:18:25.200 30175 30175 F ganicmaps.debu: runtime.cc:590] Pending exception java.lang.IllegalStateException: Fragment PlacePageView{9d2b38f} (5086c6c7-c27c-4547-a594-a2e8249b8f4f) not attached to a context. 02-02 18:18:25.200 30175 30175 F ganicmaps.debu: runtime.cc:590] at void app.organicmaps.widget.placepage.PlacePageView.updateDownloader(app.organicmaps.downloader.CountryItem) (PlacePageView.java:1167) 02-02 18:18:25.200 30175 30175 F ganicmaps.debu: runtime.cc:590] at void app.organicmaps.widget.placepage.PlacePageView.updateDownloader() (PlacePageView.java:1181) ``` And `02-02 18:18:25.200 30175 30175 F ganicmaps.debu: runtime.cc:598] JNI DETECTED ERROR IN APPLICATION: JNI NewObjectV called with pending exception java.lang.IllegalStateException: Fragment PlacePageView{9d2b38f} (5086c6c7-c27c-4547-a594-a2e8249b8f4f) not attached to a context.` It looks like the downloader code does not work now as before. Internally it is a complex jni/C++ implementation that downloads map files from C++, but notifies the subscribed Place Page by calling callbacks. Maybe these callbacks are incorrectly handled now.
arnaudvergnet (Migrated from github.com) reviewed 2023-02-07 21:05:11 +00:00
arnaudvergnet (Migrated from github.com) commented 2023-02-07 21:05:11 +00:00

What did you do to get this error?

What did you do to get this error?
biodranik (Migrated from github.com) reviewed 2023-02-07 21:12:44 +00:00
biodranik (Migrated from github.com) commented 2023-02-07 21:12:44 +00:00

Selected any object on the non-downloaded area, closed PP, selected it again, and pressed Download button in the PP.

Selected any object on the non-downloaded area, closed PP, selected it again, and pressed Download button in the PP.
biodranik (Migrated from github.com) approved these changes 2023-02-18 18:29:50 +00:00
biodranik (Migrated from github.com) left a comment

LGTM! Thank you, Arnaud!

I've found another minor but annoying issue, but I'm not sure if it is caused by your changes:

It is very hard to tap the "more..." button for a partially visible Wikipedia article in PP. I often miss it, and the PP closes. Would it be possible to make the whole Wikipedia article view clickable too?

LGTM! Thank you, Arnaud! I've found another minor but annoying issue, but I'm not sure if it is caused by your changes: It is very hard to tap the "more..." button for a partially visible Wikipedia article in PP. I often miss it, and the PP closes. Would it be possible to make the whole Wikipedia article view clickable too?
This repo is archived. You cannot comment on pull requests.
No reviewers
No labels
Accessibility
Accessibility
Address
Address
Android
Android
Android Auto
Android Auto
Android Automotive (AAOS)
Android Automotive (AAOS)
API
API
AppGallery
AppGallery
AppStore
AppStore
Battery and Performance
Battery and Performance
Blocker
Blocker
Bookmarks and Tracks
Bookmarks and Tracks
Borders
Borders
Bug
Bug
Build
Build
CarPlay
CarPlay
Classificator
Classificator
Community
Community
Core
Core
CrashReports
CrashReports
Cycling
Cycling
Desktop
Desktop
DevEx
DevEx
DevOps
DevOps
dev_sandbox
dev_sandbox
Directions
Directions
Documentation
Documentation
Downloader
Downloader
Drape
Drape
Driving
Driving
Duplicate
Duplicate
Editor
Editor
Elevation
Elevation
Enhancement
Enhancement
Epic
Epic
External Map Datasets
External Map Datasets
F-Droid
F-Droid
Fonts
Fonts
Frequently User Reported
Frequently User Reported
Fund
Fund
Generator
Generator
Good first issue
Good first issue
Google Play
Google Play
GPS
GPS
GSoC
GSoC
iCloud
iCloud
Icons
Icons
iOS
iOS
Legal
Legal
Linux Desktop
Linux Desktop
Linux packaging
Linux packaging
Linux Phone
Linux Phone
Mac OS
Mac OS
Map Data
Map Data
Metro
Metro
Navigation
Navigation
Need Feedback
Need Feedback
Night Mode
Night Mode
NLnet 2024-06-281
NLnet 2024-06-281
No Feature Parity
No Feature Parity
Opening Hours
Opening Hours
Outdoors
Outdoors
POI Info
POI Info
Privacy
Privacy
Public Transport
Public Transport
Raw Idea
Raw Idea
Refactoring
Refactoring
Regional
Regional
Regression
Regression
Releases
Releases
RoboTest
RoboTest
Route Planning
Route Planning
Routing
Routing
Ruler
Ruler
Search
Search
Security
Security
Styles
Styles
Tests
Tests
Track Recording
Track Recording
Translations
Translations
TTS
TTS
UI
UI
UX
UX
Walk Navigation
Walk Navigation
Watches
Watches
Web
Web
Wikipedia
Wikipedia
Windows
Windows
Won't fix
Won't fix
World Map
World Map
No milestone
No project
No assignees
3 participants
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: organicmaps/organicmaps-tmp#4174
No description provided.