diff --git a/libs/coding/url.hpp b/libs/coding/url.hpp index a514babf7..ef3f6a5a0 100644 --- a/libs/coding/url.hpp +++ b/libs/coding/url.hpp @@ -41,6 +41,7 @@ public: return &p.second; return nullptr; } + std::vector const & GetParams() const { return m_params; } private: bool Parse(std::string const & url); diff --git a/libs/map/mwm_url.cpp b/libs/map/mwm_url.cpp index ee7e3f32c..5d11bc75e 100644 --- a/libs/map/mwm_url.cpp +++ b/libs/map/mwm_url.cpp @@ -1,8 +1,19 @@ +#if defined(OMIM_OS_MAC) || defined(OMIM_OS_IPHONE) +#include "platform/preferred_languages.hpp" +#endif + #include "map/mwm_url.hpp" #include "map/api_mark_point.hpp" #include "map/bookmark_manager.hpp" #include "map/framework.hpp" +#if defined(OMIM_OS_MAC) || defined(OMIM_OS_IPHONE) +#include "map/everywhere_search_params.hpp" +#include "map/routing_manager.hpp" +#include "map/routing_mark.hpp" + +#include "search/result.hpp" +#endif #include "ge0/geo_url_parser.hpp" #include "ge0/parser.hpp" @@ -17,8 +28,9 @@ #include "base/scope_guard.hpp" #include "base/string_utils.hpp" -#include -#include +#if defined(OMIM_OS_MAC) || defined(OMIM_OS_IPHONE) +#include +#endif namespace url_scheme { @@ -238,6 +250,131 @@ ParsedMapApi::UrlType ParsedMapApi::SetUrlAndParse(std::string const & raw) UNREACHABLE(); } +#if defined(OMIM_OS_MAC) || defined(OMIM_OS_IPHONE) +ParsedMapApi::UrlType ParsedMapApi::ParseGeoNav(std::string const & raw, Framework & fm) +{ + Reset(); + SCOPE_GUARD(guard, [this] + { + if (m_requestType == UrlType::Incorrect) + Reset(); + }); + + url::Url const url(raw); + + if (url.GetHost() == "place") + { + auto const latLon = url.GetParamValue("coordinate"); + auto const addr = url.GetParamValue("address"); + + if (latLon) + { + auto const tokens = strings::Tokenize(*latLon, ","); + double lat; + double lon; + + if (tokens.size() != 2 || !strings::to_double(tokens[0], lat) || !strings::to_double(tokens[1], lon) || + !mercator::ValidLat(lat) || !mercator::ValidLon(lon)) + { + LOG(LWARNING, ("Invalid lat,lon in", raw)); + return m_requestType = UrlType::Incorrect; + } + + if (addr) + { + m_searchRequest = SearchRequest(); + m_searchRequest.m_query = *addr; + m_centerLatLon = {lat, lon}; + return m_requestType = UrlType::Search; + } + + else + { + m_centerLatLon = {lat, lon}; + m_mapPoints.push_back({lat /* m_lat */, lon /* m_lon */, "" /* m_label */, "" /* m_id */, "" /* m_style */}); + return m_requestType = UrlType::Map; + } + } + + else if (addr) + { + m_searchRequest = SearchRequest(); + m_searchRequest.m_query = *addr; + return m_requestType = UrlType::Search; + } + } + + else if (url.GetHost() == "directions") + { + auto const source = url.GetParamValue("source"); + auto const destination = url.GetParamValue("destination"); + + if (source) + SetRouteMark(*source, fm, RouteMarkType::Finish); + + if (url.GetParamValue("waypoint")) + for (auto const & param : url.GetParams()) + if (param.first == "waypoint") + SetRouteMark(param.second, fm, RouteMarkType::Intermediate); + + if (destination) + SetRouteMark(*destination, fm, RouteMarkType::Finish); + + if (source || destination) + { + m_routingType = routing::ToString(routing::GetLastUsedRouter()); + + return m_requestType = UrlType::Route; + } + + return m_requestType = UrlType::Incorrect; + } + + return m_requestType = UrlType::Incorrect; +} + +void ParsedMapApi::SetRouteMark(std::string_view const raw, Framework & fm, RouteMarkType const type) +{ + auto const tokens = strings::Tokenize(raw, ","); + double lat; + double lon; + + if (tokens.size() != 2 || !strings::to_double(tokens[0], lat) || !strings::to_double(tokens[1], lon) || + !mercator::ValidLat(lat) || !mercator::ValidLon(lon)) + { + std::promise signal; + std::future future = signal.get_future(); + + ::search::EverywhereSearchParams params{ + std::string(raw), + languages::GetMostPreferredLang(), + {} /* timeout */, + false, + // m_onResults + [this, type = std::move(type), &signal](::search::Results results, std::vector<::search::ProductInfo>) + { + auto const center = results[0].GetFeatureCenter(); + RoutePoint p; + p.m_type = type; + p.m_org = mercator::FromLatLon(mercator::YToLat(center.y), mercator::XToLon(center.x)); + p.m_name = results[0].GetString(); + m_routePoints.push_back(p); + signal.set_value(); + }}; + + fm.GetSearchAPI().SearchEverywhere(std::move(params)); + future.wait(); + } + else + { + RoutePoint p; + p.m_org = mercator::FromLatLon(lat, lon); + p.m_type = type; + m_routePoints.push_back(p); + } +} +#endif + void ParsedMapApi::ParseMapParam(std::string const & key, std::string const & value, bool & correctOrder) { using namespace map; diff --git a/libs/map/mwm_url.hpp b/libs/map/mwm_url.hpp index 0941ca242..eeba63e66 100644 --- a/libs/map/mwm_url.hpp +++ b/libs/map/mwm_url.hpp @@ -1,5 +1,10 @@ #pragma once +#if defined(OMIM_OS_MAC) || defined(OMIM_OS_IPHONE) +#include "map/everywhere_search_params.hpp" +#include "map/routing_mark.hpp" +#endif + #include "geometry/latlon.hpp" #include "geometry/point2d.hpp" @@ -22,9 +27,20 @@ struct MapPoint struct RoutePoint { RoutePoint() = default; +#if defined(OMIM_OS_MAC) || defined(OMIM_OS_IPHONE) + RoutePoint(m2::PointD const & org, std::string const & name, RouteMarkType type) + : m_org(org) + , m_name(name) + , m_type(type) + {} +#else RoutePoint(m2::PointD const & org, std::string const & name) : m_org(org), m_name(name) {} +#endif m2::PointD m_org = m2::PointD::Zero(); std::string m_name; +#if defined(OMIM_OS_MAC) || defined(OMIM_OS_IPHONE) + RouteMarkType m_type; +#endif }; struct SearchRequest @@ -66,6 +82,9 @@ public: explicit ParsedMapApi(std::string const & url) { SetUrlAndParse(url); } UrlType SetUrlAndParse(std::string const & url); +#if defined(OMIM_OS_MAC) || defined(OMIM_OS_IPHONE) + UrlType ParseGeoNav(std::string const & raw, Framework & fm); +#endif UrlType GetRequestType() const { return m_requestType; } std::string const & GetGlobalBackUrl() const { return m_globalBackUrl; } std::string const & GetAppName() const { return m_appName; } @@ -123,6 +142,9 @@ public: private: void ParseMapParam(std::string const & key, std::string const & value, bool & correctOrder); +#if defined(OMIM_OS_MAC) || defined(OMIM_OS_IPHONE) + void SetRouteMark(std::string_view const raw, Framework & fm, RouteMarkType const type); +#endif void ParseRouteParam(std::string const & key, std::string const & value, std::vector & pattern); void ParseSearchParam(std::string const & key, std::string const & value); void ParseInAppFeatureHighlightParam(std::string const & key, std::string const & value); diff --git a/libs/map/routing_manager.cpp b/libs/map/routing_manager.cpp index 5507debd4..8fd4a243a 100644 --- a/libs/map/routing_manager.cpp +++ b/libs/map/routing_manager.cpp @@ -470,10 +470,10 @@ void RoutingManager::OnLocationUpdate(location::GpsInfo const & info) RouterType RoutingManager::GetBestRouter(m2::PointD const & startPoint, m2::PointD const & finalPoint) const { // todo Implement something more sophisticated here (or delete the method). - return GetLastUsedRouter(); + return routing::GetLastUsedRouter(); } -RouterType RoutingManager::GetLastUsedRouter() const +RouterType routing::GetLastUsedRouter() { string routerTypeStr; if (!settings::Get(kRouterTypeKey, routerTypeStr)) diff --git a/libs/map/routing_manager.hpp b/libs/map/routing_manager.hpp index 59fc30e85..0ecf4e5a3 100644 --- a/libs/map/routing_manager.hpp +++ b/libs/map/routing_manager.hpp @@ -40,6 +40,7 @@ class CountryInfoGetter; namespace routing { class NumMwmIds; +RouterType GetLastUsedRouter(); } class DataSource; @@ -172,7 +173,6 @@ public: m2::PointD GetRouteEndPoint() const { return m_routingSession.GetEndPoint(); } /// Returns the most situable router engine type. routing::RouterType GetBestRouter(m2::PointD const & startPoint, m2::PointD const & finalPoint) const; - routing::RouterType GetLastUsedRouter() const; void SetLastUsedRouter(routing::RouterType type); // Sound notifications for turn instructions. void EnableTurnNotifications(bool enable) { m_routingSession.EnableTurnNotifications(enable); } diff --git a/libs/platform/preferred_languages.cpp b/libs/platform/preferred_languages.cpp index a2c28d73b..989a628f0 100644 --- a/libs/platform/preferred_languages.cpp +++ b/libs/platform/preferred_languages.cpp @@ -579,6 +579,11 @@ std::string GetCurrentMapLanguage() return languageCode; } +std::string GetMostPreferredLang() +{ + return std::string(StringUtf8Multilang::GetLangByCode(GetPreferredLangIndexes()[0])); +} + std::vector GetPreferredLangIndexes() { std::vector langs = {}; diff --git a/libs/platform/preferred_languages.hpp b/libs/platform/preferred_languages.hpp index 1ec78582e..03be5098d 100644 --- a/libs/platform/preferred_languages.hpp +++ b/libs/platform/preferred_languages.hpp @@ -25,6 +25,7 @@ std::string GetCurrentMapTwine(); std::string Normalize(std::string_view lang); std::string GetCurrentNorm(); std::string GetCurrentMapLanguage(); +std::string GetMostPreferredLang(); std::vector GetPreferredLangIndexes(); buffer_vector const & GetSystemPreferred(); diff --git a/libs/platform/settings.cpp b/libs/platform/settings.cpp index 500906c13..bb895fb2b 100644 --- a/libs/platform/settings.cpp +++ b/libs/platform/settings.cpp @@ -49,6 +49,13 @@ bool FromString(string const & strIn, string & strOut) return true; } +template <> +bool FromString(string const & strIn, std::string_view & strOut) +{ + strOut = strIn; + return true; +} + namespace impl { template diff --git a/libs/search/query_saver.cpp b/libs/search/query_saver.cpp index e2cea6974..19c585c89 100644 --- a/libs/search/query_saver.cpp +++ b/libs/search/query_saver.cpp @@ -130,11 +130,13 @@ void QuerySaver::Deserialize(string const & data) { Length localeLength = ReadPrimitiveFromSource(reader); vector locale(localeLength); - reader.Read(&locale[0], localeLength); - Length stringLength = ReadPrimitiveFromSource(reader); - vector str(stringLength); - reader.Read(&str[0], stringLength); - m_topQueries.emplace_back(make_pair(string(&locale[0], localeLength), string(&str[0], stringLength))); + if (locale.size() > 0) { + reader.Read(&locale[0], localeLength); + Length stringLength = ReadPrimitiveFromSource(reader); + vector str(stringLength); + reader.Read(&str[0], stringLength); + m_topQueries.emplace_back(make_pair(string(&locale[0], localeLength), string(&str[0], stringLength))); + } } }