mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 14:17:12 +02:00
Resolve different addresses.
This commit is contained in:
parent
310837c9e1
commit
de52ac6b28
10 changed files with 159 additions and 23 deletions
|
@ -50,7 +50,7 @@ html.custom_scroll ::-webkit-scrollbar-thumb:hover {
|
|||
}
|
||||
#marker {
|
||||
pointer-events: none;
|
||||
display: flex;
|
||||
display: none;
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
|
@ -58,3 +58,13 @@ html.custom_scroll ::-webkit-scrollbar-thumb:hover {
|
|||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
#marker_drop {
|
||||
margin-bottom: 0px;
|
||||
transition: margin 160ms ease-in-out;
|
||||
}
|
||||
#marker_drop.moving {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
#marker_shadow {
|
||||
position: absolute;
|
||||
}
|
||||
|
|
|
@ -70,16 +70,41 @@ var LocationPicker = {
|
|||
center = [0, 0];
|
||||
}
|
||||
LocationPicker.map = new mapboxgl.Map(options);
|
||||
|
||||
const marker = new mapboxgl.Marker()
|
||||
.setLngLat(center)
|
||||
.addTo(LocationPicker.map);
|
||||
const drop = document.getElementById('marker_drop');
|
||||
const element = marker.getElement();
|
||||
drop.innerHTML = element.innerHTML;
|
||||
const offset = marker.getOffset();
|
||||
drop.style.transform = 'translate(' + offset.x + 'px, ' + offset.y + 'px)';
|
||||
marker.remove();
|
||||
LocationPicker.createMarker(center);
|
||||
LocationPicker.trackMovement();
|
||||
},
|
||||
marker: function() {
|
||||
return document.getElementById('marker_drop');
|
||||
},
|
||||
createMarker: function(center) {
|
||||
document.getElementById('marker').style.display = 'flex';
|
||||
},
|
||||
clearMovingTimer: function() {
|
||||
if (LocationPicker.clearMovingTimeoutId) {
|
||||
clearTimeout(LocationPicker.clearMovingTimeoutId);
|
||||
LocationPicker.clearMovingTimeoutId = 0;
|
||||
}
|
||||
},
|
||||
startMovingTimer: function(done) {
|
||||
LocationPicker.clearMovingTimer();
|
||||
LocationPicker.clearMovingTimeoutId = setTimeout(done, 500);
|
||||
},
|
||||
trackMovement: function() {
|
||||
LocationPicker.map.on('movestart', function() {
|
||||
LocationPicker.marker().classList.add('moving');
|
||||
LocationPicker.clearMovingTimer();
|
||||
LocationPicker.notify({ event: 'movestart' });
|
||||
});
|
||||
LocationPicker.map.on('moveend', function() {
|
||||
LocationPicker.startMovingTimer(function() {
|
||||
LocationPicker.marker().classList.remove('moving');
|
||||
LocationPicker.notify({
|
||||
event: 'moveend',
|
||||
latitude: LocationPicker.map.getCenter().lat,
|
||||
longitude: LocationPicker.map.getCenter().lng
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
narrowTo: function (point) {
|
||||
LocationPicker.map.flyTo({
|
||||
|
|
|
@ -27,14 +27,51 @@ namespace {
|
|||
|
||||
constexpr auto kDestroyManagerTimeout = 20 * crl::time(1000);
|
||||
|
||||
[[nodiscard]] QString ChooseLanguage(const QString &language) {
|
||||
// https://docs.mapbox.com/api/search/geocoding#language-coverage
|
||||
auto result = language.toLower().replace('-', '_');
|
||||
static const auto kGood = std::array{
|
||||
// Global coverage.
|
||||
u"de"_q, u"en"_q, u"es"_q, u"fr"_q, u"it"_q, u"nl"_q, u"pl"_q,
|
||||
|
||||
// Local coverage.
|
||||
u"az"_q, u"bn"_q, u"ca"_q, u"cs"_q, u"da"_q, u"el"_q, u"fa"_q,
|
||||
u"fi"_q, u"ga"_q, u"hu"_q, u"id"_q, u"is"_q, u"ja"_q, u"ka"_q,
|
||||
u"km"_q, u"ko"_q, u"lt"_q, u"lv"_q, u"mn"_q, u"pt"_q, u"ro"_q,
|
||||
u"sk"_q, u"sq"_q, u"sv"_q, u"th"_q, u"tl"_q, u"uk"_q, u"vi"_q,
|
||||
u"zh"_q, u"zh_Hans"_q, u"zh_TW"_q,
|
||||
|
||||
// Limited coverage.
|
||||
u"ar"_q, u"bs"_q, u"gu"_q, u"he"_q, u"hi"_q, u"kk"_q, u"lo"_q,
|
||||
u"my"_q, u"nb"_q, u"ru"_q, u"sr"_q, u"te"_q, u"tk"_q, u"tr"_q,
|
||||
u"zh_Hant"_q,
|
||||
};
|
||||
for (const auto &known : kGood) {
|
||||
if (known.toLower() == result) {
|
||||
return known;
|
||||
}
|
||||
}
|
||||
if (const auto delimeter = result.indexOf('_'); delimeter > 0) {
|
||||
result = result.mid(0, delimeter);
|
||||
for (const auto &known : kGood) {
|
||||
if (known == result) {
|
||||
return known;
|
||||
}
|
||||
}
|
||||
}
|
||||
return u"en"_q;
|
||||
}
|
||||
|
||||
void ResolveLocationAddressGeneric(
|
||||
const GeoLocation &location,
|
||||
const QString &language,
|
||||
const QString &token,
|
||||
Fn<void(GeoAddress)> callback) {
|
||||
const auto partialUrl = u"https://api.mapbox.com/search/geocode/v6"
|
||||
"/reverse?longitude=%1&latitude=%2&access_token=%3"_q
|
||||
"/reverse?longitude=%1&latitude=%2&language=%3&access_token=%4"_q
|
||||
.arg(location.point.y())
|
||||
.arg(location.point.x());
|
||||
.arg(location.point.x())
|
||||
.arg(ChooseLanguage(language));
|
||||
static auto Cache = base::flat_map<QString, GeoAddress>();
|
||||
const auto i = Cache.find(partialUrl);
|
||||
if (i != end(Cache)) {
|
||||
|
@ -161,16 +198,21 @@ void ResolveCurrentGeoLocation(Fn<void(GeoLocation)> callback) {
|
|||
|
||||
void ResolveLocationAddress(
|
||||
const GeoLocation &location,
|
||||
const QString &language,
|
||||
const QString &token,
|
||||
Fn<void(GeoAddress)> callback) {
|
||||
auto done = [=, done = std::move(callback)](GeoAddress result) mutable {
|
||||
if (!result && !token.isEmpty()) {
|
||||
ResolveLocationAddressGeneric(location, token, std::move(done));
|
||||
ResolveLocationAddressGeneric(
|
||||
location,
|
||||
language,
|
||||
token,
|
||||
std::move(done));
|
||||
} else {
|
||||
done(result);
|
||||
}
|
||||
};
|
||||
Platform::ResolveLocationAddress(location, std::move(done));
|
||||
Platform::ResolveLocationAddress(location, language, std::move(done));
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
|
|
|
@ -55,6 +55,7 @@ void ResolveCurrentGeoLocation(Fn<void(GeoLocation)> callback);
|
|||
|
||||
void ResolveLocationAddress(
|
||||
const GeoLocation &location,
|
||||
const QString &language,
|
||||
const QString &token,
|
||||
Fn<void(GeoAddress)> callback);
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ void ResolveCurrentExactLocation(Fn<void(Core::GeoLocation)> callback) {
|
|||
}
|
||||
void ResolveLocationAddress(
|
||||
const Core::GeoLocation &location,
|
||||
const QString &language,
|
||||
Fn<void(Core::GeoAddress)> callback) {
|
||||
callback({});
|
||||
}
|
||||
|
|
|
@ -118,6 +118,7 @@ void ResolveCurrentExactLocation(Fn<void(Core::GeoLocation)> callback) {
|
|||
|
||||
void ResolveLocationAddress(
|
||||
const Core::GeoLocation &location,
|
||||
const QString &language,
|
||||
Fn<void(Core::GeoAddress)> callback) {
|
||||
callback({});
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ namespace Platform {
|
|||
void ResolveCurrentExactLocation(Fn<void(Core::GeoLocation)> callback);
|
||||
void ResolveLocationAddress(
|
||||
const Core::GeoLocation &location,
|
||||
const QString &language,
|
||||
Fn<void(Core::GeoAddress)> callback);
|
||||
|
||||
} // namespace Platform
|
||||
|
|
|
@ -61,6 +61,7 @@ void ResolveCurrentExactLocation(Fn<void(Core::GeoLocation)> callback) {
|
|||
|
||||
void ResolveLocationAddress(
|
||||
const Core::GeoLocation &location,
|
||||
const QString &language,
|
||||
Fn<void(Core::GeoAddress)> callback) {
|
||||
callback({});
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_location.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_user.h"
|
||||
#include "lang/lang_instance.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "main/session/session_show.h"
|
||||
#include "main/main_session.h"
|
||||
|
@ -46,6 +47,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
namespace Ui {
|
||||
namespace {
|
||||
|
||||
constexpr auto kResolveAddressDelay = 3 * crl::time(1000);
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
const auto kProtocolOverride = "mapboxapihelper";
|
||||
#else // Q_OS_MAC
|
||||
|
@ -355,7 +358,30 @@ void LinksController::rowPaintIcon(
|
|||
<link href='https://api.mapbox.com/mapbox-gl-js/v3.4.0/mapbox-gl.css' rel='stylesheet' />
|
||||
</head>
|
||||
<body>
|
||||
<div id="marker"><div id="marker_drop"></div></div>
|
||||
<div id="marker">
|
||||
<div id="marker_shadow" style="transform: translate(0px, -14px);">
|
||||
<svg display="block" height="41px" width="27px" viewBox="0 0 27 41">
|
||||
<defs>
|
||||
<radialGradient id="shadowGradient">
|
||||
<stop offset="10%" stop-opacity="0.4"></stop>
|
||||
<stop offset="100%" stop-opacity="0.05"></stop>
|
||||
</radialGradient>
|
||||
</defs>
|
||||
<ellipse
|
||||
cx="13.5"
|
||||
cy="34.8"
|
||||
rx="10.5"
|
||||
ry="5.25"
|
||||
fill=")" + "url(#shadowGradient)" + R"("></ellipse>
|
||||
</svg>
|
||||
</div>
|
||||
<div id="marker_drop" style="transform: translate(0px, -14px);">
|
||||
<svg display="block" height="41px" width="27px" viewBox="0 0 27 41">
|
||||
<path fill="#3FB1CE" d="M27,13.5C27,19.07 20.25,27 14.75,34.5C14.02,35.5 12.98,35.5 12.25,34.5C6.75,27 0,19.22 0,13.5C0,6.04 6.04,0 13.5,0C20.96,0 27,6.04 27,13.5Z"></path><path opacity="0.25" d="M13.5,0C6.04,0 0,6.04 0,13.5C0,19.22 6.75,27 12.25,34.5C13,35.52 14.02,35.5 14.75,34.5C20.25,27 27,19.07 27,13.5C27,6.04 20.96,0 13.5,0ZM13.5,1C20.42,1 26,6.58 26,13.5C26,15.9 24.5,19.18 22.22,22.74C19.95,26.3 16.71,30.14 13.94,33.91C13.74,34.18 13.61,34.32 13.5,34.44C13.39,34.32 13.26,34.18 13.06,33.91C10.28,30.13 7.41,26.31 5.02,22.77C2.62,19.23 1,15.95 1,13.5C1,6.58 6.58,1 13.5,1Z"></path>
|
||||
<circle fill="white" cx="13.5" cy="13.5" r="5.5"></circle>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div id="map"></div>
|
||||
<script>LocationPicker.notify({ event: 'ready' });</script>
|
||||
</body>
|
||||
|
@ -408,26 +434,26 @@ void LinksController::rowPaintIcon(
|
|||
raw,
|
||||
rpl::duplicate(statusText),
|
||||
st::pickLocationButtonStatus);
|
||||
status->showOn(std::move(
|
||||
status->showOn(rpl::duplicate(
|
||||
statusText
|
||||
) | rpl::map([](const QString &text) {
|
||||
return !text.isEmpty();
|
||||
}) | rpl::distinct_until_changed());
|
||||
rpl::combine(
|
||||
result->widthValue(),
|
||||
status->shownValue()
|
||||
) | rpl::start_with_next([=](int width, bool statusShown) {
|
||||
std::move(statusText)
|
||||
) | rpl::start_with_next([=](int width, const QString &statusText) {
|
||||
const auto available = width
|
||||
- st->namePosition.x()
|
||||
- st->button.padding.right();
|
||||
const auto namePosition = st->namePosition;
|
||||
const auto statusPosition = st->statusPosition;
|
||||
name->resizeToWidth(available);
|
||||
const auto nameTop = statusShown
|
||||
? namePosition.y()
|
||||
: (st->height - name->height()) / 2;
|
||||
const auto nameTop = statusText.isEmpty()
|
||||
? ((st->height - name->height()) / 2)
|
||||
: namePosition.y();
|
||||
name->moveToLeft(namePosition.x(), nameTop, width);
|
||||
status->resizeToWidth(available);
|
||||
status->resizeToNaturalWidth(available);
|
||||
status->moveToLeft(statusPosition.x(), statusPosition.y(), width);
|
||||
}, name->lifetime());
|
||||
|
||||
|
@ -501,6 +527,7 @@ LocationPicker::LocationPicker(Descriptor &&descriptor)
|
|||
_webview->eval("LocationPicker.updateStyles('" + str + "');");
|
||||
}
|
||||
})
|
||||
, _geocoderResolveTimer([=] { resolveAddressByTimer(); })
|
||||
, _venueState(PickerVenueLoading())
|
||||
, _session(descriptor.session)
|
||||
, _api(&_session->mtp()) {
|
||||
|
@ -660,6 +687,17 @@ void LocationPicker::setupWebview(const Descriptor &descriptor) {
|
|||
const auto lon = object.value("longitude").toDouble();
|
||||
_callback({ lat, lon });
|
||||
close();
|
||||
} else if (event == u"movestart"_q) {
|
||||
_geocoderAddress = QString();
|
||||
_geocoderResolveTimer.cancel();
|
||||
} else if (event == u"moveend"_q) {
|
||||
const auto lat = object.value("latitude").toDouble();
|
||||
const auto lon = object.value("longitude").toDouble();
|
||||
_geocoderResolvePostponed = Core::GeoLocation{
|
||||
.point = { lat, lon },
|
||||
.accuracy = Core::GeoLocationAccuracy::Exact,
|
||||
};
|
||||
_geocoderResolveTimer.callOnce(kResolveAddressDelay);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -714,6 +752,12 @@ void LocationPicker::setupWebview(const Descriptor &descriptor) {
|
|||
raw->navigateToData("location/picker.html");
|
||||
}
|
||||
|
||||
void LocationPicker::resolveAddressByTimer() {
|
||||
if (const auto location = base::take(_geocoderResolvePostponed)) {
|
||||
resolveAddress(location);
|
||||
}
|
||||
}
|
||||
|
||||
void LocationPicker::resolveAddress(Core::GeoLocation location) {
|
||||
if (_geocoderResolvingFor == location) {
|
||||
return;
|
||||
|
@ -730,8 +774,14 @@ void LocationPicker::resolveAddress(Core::GeoLocation location) {
|
|||
.arg(location.point.y(), 0, 'f');
|
||||
}
|
||||
};
|
||||
const auto baseLangId = Lang::GetInstance().baseId();
|
||||
const auto langId = baseLangId.isEmpty()
|
||||
? Lang::GetInstance().id()
|
||||
: baseLangId;
|
||||
const auto nonEmptyId = langId.isEmpty() ? u"en"_q : langId;
|
||||
Core::ResolveLocationAddress(
|
||||
location,
|
||||
langId,
|
||||
GeocodingProviderToken,
|
||||
crl::guard(this, done));
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#pragma once
|
||||
|
||||
#include "base/invoke_queued.h"
|
||||
#include "base/timer.h"
|
||||
#include "base/weak_ptr.h"
|
||||
#include "core/current_geo_location.h"
|
||||
#include "mtproto/sender.h"
|
||||
|
@ -106,6 +107,7 @@ private:
|
|||
void setupWebview(const Descriptor &descriptor);
|
||||
void processKey(const QString &key, const QString &modifier);
|
||||
void resolveCurrentLocation();
|
||||
void resolveAddressByTimer();
|
||||
void resolveAddress(Core::GeoLocation location);
|
||||
void mapReady();
|
||||
|
||||
|
@ -124,6 +126,8 @@ private:
|
|||
SingleQueuedInvokation _updateStyles;
|
||||
bool _subscribedToColors = false;
|
||||
|
||||
base::Timer _geocoderResolveTimer;
|
||||
Core::GeoLocation _geocoderResolvePostponed;
|
||||
Core::GeoLocation _geocoderResolvingFor;
|
||||
rpl::variable<QString> _geocoderAddress;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue