Compare commits

..

1 Commits

Author SHA1 Message Date
Yannik Bloscheck
bff4b2348a [ios] WIP: Switching main/map buttons to SwiftUI
Signed-off-by: Yannik Bloscheck <git@yannikbloscheck.com>
2025-11-07 21:07:34 +01:00
98 changed files with 1166 additions and 1363 deletions

View File

@@ -1,31 +0,0 @@
Brezplačno in odprtokodno zemljevidno orodje, ki ga vodi skupnost, temelji na podatkih OpenStreetMap in je okrepljena s predanostjo transparentnosti, zasebnosti in nedobičkonosnosti. CoMaps je izpeljanka OrganicMaps, ta pa je izpeljanka Maps.ME.
Preverite si o razlogih za ta projekt in njegovi usmerjenosti na <b><i>codeberg.org/comaps</i></b>.
Pridružite se skupnosti in pomagajte narediti najboljše zemljevidno orodje
• Uporabljajte orodje in širite glas o njem
• Dajajte povratne informacije in poročajte o napakah
• Posodabljajte podatke zemljevida v tem orodju ali na spletni strani OpenStreetMap
‣ <b>Osredotočeno na uporabo brez povezave</b>: Načrtujte in se usmerjajte na vašem potovanju v tujini vrez potrebe po mobilnih podatkih, iščite vmesne točke potocanja ko ste na daljšem pohodu ipd. Vse zmogljivosti orodja so zasnovane za delo brez povezave.
‣ <b>Spoštovanje zasebnosti</b>: orodje je zasnovano z mislijo na zasebnost ne prepoznava oseb, ne sledi in ne zbira osebnih podatkov. Brez oglasov.
‣ <b>Preprosto in dodelano</b>: nujne zmogljivosti, enostavne za uporabo, ki preprosto delujejo.
‣ <b>Prihrani vašo baterijo in prostor.</b>: ne izčrpava vaše baterije kakor druga usmerjevalna orodja. Strnjeni zemljevidi prihranijo dragocen prostor na vašem telefonu.
‣ <b>Brezplačno in ustvarjeno v skupnosti</b>: ljudje kot ste vi pomagajo ustvarjati to orodje, tako da dodajajo kraje na OpenStreetMap, preizkušajo in dajejo povratne informacije o zmogljivostih in prispevajo svoje razvijalske sposobnosti in sredstva.
‣ <b>Odprto in transparentno odločanje in finance, nedobičkonosno in popolnoma odprtokodno.</b>
<b>Glavne zmogljivosti</b>:
• Prenosljivi podrobni zemljevidi s kraji, ki na Googlovoh zemljevidih niso na voljo.
• Prikaz za dejavnosti na prostem s poudarjenimi pohodniškimi potmi, tabornimi prostori, vodnimi viri, vrhovi, plastnicami itd.
• Pešpoti in kolesarke poti
• Kraji zanimanja, npr. restavracije, bencinske črpalke, hoteli, trgovine, znamenitosti in mnogo več
• Iščite po imenu, hišnemu naslovu ali po vrsti
• Usmerjanje z glasovnimi obvestili za hojo, kolesarjenje ali vožnjo avtomobila.
• Zaznamujte svoje najljubše kraje s preprostim dotikom
• Wikipedijini članki brez povezave
• Prometna plast podzemne železnice z usmerjanjem
• Izvozite ali uvozite zaznamke in sledi v oblikah KML, KMZ, GPX
• Temni prikaz za uporabo ponoči
• Izboljšajtw podatke zemljevida za vse z uporabo vgrajenega urejevalnika
<b>Svoboda je tu</b>
Odkijte več o vašem potovanju, usmerjajte se po svetu s poudarkom na zasebnosti in skupnostnem delovanju!

View File

@@ -1 +0,0 @@
Comaps- Vandra, Cykla, Kör Offline, Privat

View File

@@ -1 +0,0 @@
Comaps- Navigera Privat

View File

@@ -623,8 +623,7 @@
<string name="charge_socket_unknown_other">Outro ou descoñecido</string>
<string name="unknow_socket_type">engache descoñecido</string>
<string name="editor_place_doesnt_exist_description">Describe a aparencia do lugar para enviar unha nota co erro á comunidade OpenStreetMap</string>
<string name="avoid_steps">Evitar escaleiras</string>
<string name="avoid_steps">Evitar pasos</string>
<string name="offline_explanation_title">Mapas sen conexión</string>
<string name="offline_explanation_text">Hai que descargar un mapa para ver e navegar polo área.\nDescarga os mapas para as zonas polas que vas viaxar.</string>
<string name="list_description_empty">Editar a lista para engadir unha descrición</string>
</resources>

View File

@@ -1,3 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
</resources>

View File

@@ -27,7 +27,7 @@
<!-- A dialog title, that warns a user that Precise Location is disabled and suggests to turn it on -->
<string name="limited_accuracy">精度有限</string>
<!-- A dialog text, that warns a user that Precise Location is disabled and suggests to turn it on -->
<string name="precise_location_is_disabled_long_text">为确保导航准确,请在设置中启用 \"精确定位\"</string>
<string name="precise_location_is_disabled_long_text">为确保准确导航,请在设置中启用确切位置</string>
<!-- View and button titles for accessibility -->
<string name="zoom_to_country">在地图上显示</string>
<!-- Message to display at the center of the screen when the country download has failed -->

View File

@@ -975,7 +975,7 @@
<string name="type.shop.books">Bokhandel</string>
<string name="type.shop.butcher">Slakter</string>
<string name="type.shop.cannabis">Cannabisbutikk</string>
<string name="type.shop.car">Bilforhandler</string>
<string name="type.shop.car">Bil butikk</string>
<string name="type.shop.car_parts">Bildeler</string>
<string name="type.shop.car_repair">Bilverksted</string>
<string name="type.shop.car_repair.tyres">Dekkreparasjon</string>
@@ -1353,14 +1353,4 @@
<string name="type.railway.narrow_gauge.bridge">Smalsporet jernbanebru</string>
<string name="type.railway.narrow_gauge.tunnel">Smalsporet jernbanetunnel</string>
<string name="type.leisure.slipway">Slipp</string>
<string name="type.post_office.post_partner">Post i butikk</string>
<string name="type.amenity.pub">Pub</string>
<string name="type.historic.monument">Monument</string>
<string name="type.man_made.crane">Kran</string>
<string name="type.military.bunker">Bunker</string>
<string name="type.railway.construction">Jernbanebygging</string>
<string name="type.railway.funicular.bridge">Kabelbanebru</string>
<string name="type.railway.funicular.tunnel">Kabelbanetunnel</string>
<string name="type.military">Militært</string>
<string name="type.landuse.education">Utdanningsinstitusjon</string>
</resources>

View File

@@ -1180,7 +1180,7 @@
<string name="type.amenity.bar">Bar</string>
<string name="type.amenity.bicycle_parking.covered">Parcare acoperită pentru biciclete</string>
<string name="type.amenity.love_hotel">Hotel cu ora</string>
<string name="type.amenity.studio">Studio Media</string>
<string name="type.amenity.studio">Garsonieră</string>
<string name="type.amenity.bicycle_repair_station">Stație Reparații Biciclete</string>
<string name="type.amenity.car_sharing">Utilizare comună a mașinii</string>
<string name="type.amenity.dentist">Dentist</string>

View File

@@ -153,5 +153,4 @@
<string name="type.leisure.amusement_arcade">Arkadne igre</string>
<string name="type.amenity.charging_station.motorcar.small">Polnilno mesto za avtomobile</string>
<string name="type.amenity.childcare">Vrtec</string>
<string name="type.amenity.cinema">Kino</string>
</resources>

View File

@@ -1,3 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
</resources>

View File

@@ -19,13 +19,13 @@
"@category_recycling": "Recycling|Abfallverwertung|Recyclebares Material|Getrennte Müllsammlung|Müllsortierung|Wiederverwendung",
"amenity-bureau_de_change": "3Geldwechselstelle|Wechselstube|Geld|Geldumtausch",
"amenity-bar|amenity-pub|@category_eat|@category_nightlife": "2Bar|2Pub|4Kneipe|Bier|Trinken|4Gaststätte|4Bars und Kneipen|Brauhaus|Cocktail-Lounge",
"amenity-cafe|@category_eat": "3Café|6Kaffeehaus|Kaffeebar|Cafeteria",
"amenity-fast_food|@category_eat": "4Fast Food|Mitnahme|3Imbiss|Essen zum Mitnehmen|Junkfood|7Schnellimbiss",
"amenity-restaurant|@category_eat": "3Restaurant|4Gasthaus|Gaststube|6Speiselokal|Gastwirtschaft",
"amenity-cafe|@category_eat": "3Café|3Restaurant|4Kaffee|6Kaffeehaus|Kaffeebar|Cafeteria",
"amenity-fast_food|@category_eat": "4Fast-Food|Takeaway|Restaurant|Café|Pizzeria|3Imbiss|5Essen zum Mitnehmen|Junkfood|7Schnellimbiss",
"amenity-restaurant|@category_eat": "3Restaurant|3Café|4Gasthaus|Gaststube|6Speiselokal|Gastwirtschaft",
"amenity-fuel|@category_fuel": "Tankstation|3Tankstelle",
"@shop": "3Verbrauchermarkt|5Geschäft|5Laden",
"shop-bakery|shop-pastry|@category_eat|@category_food|@shop": "3Bäckerei|Bäckerladen|Bäcker|4Konditorei|Konditor",
"shop-cosmetics|@category_shopping|@shop": "4Kosmetikgeschäft|Kosmetik|Schönheitspflege|Make Up|Make-Up|Makeup",
"shop-bakery|shop-pastry|@category_eat|@category_food|@shop": "3Bäckerei|Bäckerladen|Bäcker|4Konditorei",
"shop-cosmetics|@category_shopping|@shop": "4Kosmetikgeschäft|Kosmetik|Schönheitspflege",
"shop-convenience|@category_food|@shop": "5Gemischtwarenladen|Lebensmittelhändler|Lebensmittelhandlung|Lebensmittelgeschäft|4Greißler|4Tante-Emma-Laden",
"shop-deli|@category_food|@shop": "4Feinkostladen|Feinkostgeschäft",
"shop-farm|@category_food|@shop": "4Hofladen|4Bauernhofladen",
@@ -484,7 +484,7 @@
"shop-craft|@shop": "Künstlerbedarf",
"shop-pasta|@shop": "Nudelgeschäft",
"amenity-luggage_locker": "Gepäckschließfach",
"amenity-studio": "Medienstudio|Studio",
"amenity-studio": "Studio",
"shop-cannabis|@shop": "Cannabis",
"man_made-cross": "Kreuz",
"leisure-dance|@category_entertainment": "4Tanz|Tanzschule",

View File

@@ -34,7 +34,7 @@
"Austria_Burgenland":"Burgenland",
"Austria_Carinthia":"Carintia",
"Austria_Lower Austria_West":"Austria Inferioară — Vest",
"Austria_Lower Austria_Wien":"Viena și Austria de Jos",
"Austria_Lower Austria_Wien":"Viena",
"Austria_Salzburg":"Salzburg",
"Austria_Styria":"Stiria",
"Austria_Tyrol":"Tirol",

View File

@@ -389,34 +389,6 @@
<type id="amenity-pharmacy" group="shop">
<include group="poi_internet" />
</type>
<!-- Can not be added because it is a complex type -->
<type id="amenity-place_of_worship-buddhist" can_add="no">
<include group="poi_internet" />
</type>
<!-- Can not be added because it is a complex type -->
<type id="amenity-place_of_worship-christian" can_add="no">
<include group="poi_internet" />
</type>
<!-- Can not be added because it is a complex type -->
<type id="amenity-place_of_worship-hindu" can_add="no">
<include group="poi_internet" />
</type>
<!-- Can not be added because it is a complex type -->
<type id="amenity-place_of_worship-jewish" can_add="no">
<include group="poi_internet" />
</type>
<!-- Can not be added because it is a complex type -->
<type id="amenity-place_of_worship-muslim" can_add="no">
<include group="poi_internet" />
</type>
<!-- Can not be added because it is a complex type -->
<type id="amenity-place_of_worship-shinto" can_add="no">
<include group="poi_internet" />
</type>
<!-- Can not be added because it is a complex type -->
<type id="amenity-place_of_worship-taoist" can_add="no">
<include group="poi_internet" />
</type>
<type id="amenity-place_of_worship">
<include group="poi_internet" />
</type>
@@ -1140,25 +1112,6 @@
<include group="poi_internet" />
<include field="self_service" />
</type>
<!-- Can not be added because it is a complex type -->
<type id="tourism-information-office" can_add="no">
<include group="poi_internet" />
</type>
<!-- Can not be added because it is a complex type -->
<type id="tourism-information-visitor_centre" can_add="no">
<include group="poi_internet" />
</type>
<!-- Can not be added because it is a complex type -->
<type id="tourism-information-board" can_add="no">
<include field="name" />
</type>
<!-- Can not be added because it is a complex type -->
<type id="tourism-information-map" can_add="no">
<include field="name" />
</type>
<!-- Can not be added because it is a complex type -->
<type id="tourism-information-guidepost" can_add="no">
</type>
<type id="tourism-information">
<include group="poi" />
</type>
@@ -1520,6 +1473,19 @@
<tag k="service" v="tyres" />
<include group="poi_internet" />
</type>
<type id="tourism-information-office">
<tag k="tourism" v="information" />
<tag k="information" v="board" />
<include group="poi_internet" />
</type>
<type id="tourism-information-board">
<tag k="tourism" v="information" />
<tag k="information" v="board" />
</type>
<type id="tourism-information-map">
<tag k="tourism" v="information" />
<tag k="information" v="board" />
</type>
<type id="leisure-sports_centre-climbing">
<tag k="leisure" v="sports_centre" />
<tag k="sport" v="climbing" />

View File

@@ -1,14 +1 @@
<svg
height="25"
viewBox="0 0 40 25"
width="40"
xmlns="http://www.w3.org/2000/svg">
<path
d="M 39.091407,18.544437 C 38.430061,19.172594 21.322691,24.588874 20,24.588874 c -1.322691,0 -18.4300616,-5.41628 -19.09140734,-6.044437 -0.6613457,-0.628156 -0.6613456,-11.4607175 10e-8,-12.0888738 C 1.5699385,5.8274068 18.677309,0.411126 20,0.411126 c 1.322691,0 18.430061,5.4162809 19.091407,6.0444372 0.661346,0.6281564 0.661346,11.4607178 0,12.0888738 z"
fill="#999999"
style="stroke-width:0.594311" />
<path
d="M 37.381413,17.569578 C 36.779304,18.096424 21.204219,22.639156 20,22.639156 18.79578,22.639156 3.2206952,18.096424 2.6185853,17.569577 2.0164755,17.042731 2.0164756,7.9572668 2.6185854,7.4304207 3.2206953,6.9035747 18.79578,2.3608422 20,2.3608422 c 1.204219,0 16.779304,4.5427325 17.381413,5.0695786 0.60211,0.5268461 0.60211,9.6123102 0,10.1391572 z"
fill="#294c88"
style="stroke-width:0.519333" />
</svg>
<svg height="26" viewBox="0 0 42 26" width="42" xmlns="http://www.w3.org/2000/svg"><path d="m49.367237 34.576282c-.82405 1.427297-22.140189 13.734175-23.78829 13.734175s-22.9642395-12.306878-23.7882901-13.734176c-.82405051-1.427297-.8240504-26.0410535.0000001-27.4683509.8240506-1.4272974 22.140189-13.7341756 23.78829-13.7341756s22.96424 12.3068784 23.78829 13.7341758c.824051 1.4272974.824051 26.0410537 0 27.4683517z" fill="#999" transform="matrix(.80255481 0 0 .44010193 .471493 3.853665)"/><path d="m49.367237 34.576282c-.82405 1.427297-22.140189 13.734175-23.78829 13.734175s-22.9642395-12.306878-23.7882901-13.734176c-.82405051-1.427297-.8240504-26.0410535.0000001-27.4683509.8240506-1.4272974 22.140189-13.7341756 23.78829-13.7341756s22.96424 12.3068784 23.78829 13.7341758c.824051 1.4272974.824051 26.0410537 0 27.4683517z" fill="#294c88" transform="matrix(.73067099 0 0 .36912143 2.310205 5.333047)"/></svg>

Before

Width:  |  Height:  |  Size: 973 B

After

Width:  |  Height:  |  Size: 917 B

View File

@@ -1,14 +1 @@
<svg
height="18"
viewBox="0 0 29 18"
width="29"
xmlns="http://www.w3.org/2000/svg">
<path
d="M 28.229757,13.346912 C 27.754145,13.798656 15.451225,17.693823 14.5,17.693823 c -0.951226,0 -13.2541449,-3.895167 -13.72975757,-4.346912 -0.4756127,-0.451744 -0.47561263,-8.2420781 10e-8,-8.6938224 C 1.2458552,4.2013443 13.548774,0.306177 14.5,0.306177 c 0.951225,0 13.254145,3.8951673 13.729757,4.3469117 0.475613,0.4517443 0.475613,8.2420783 0,8.6938233 z"
fill="#999999"
style="stroke-width:0.427404" />
<path
d="m 27,12.645834 c -0.433012,0.378886 -11.633974,3.645833 -12.5,3.645833 -0.866025,0 -12.0669874,-3.266947 -12.5000002,-3.645833 C 1.5669871,12.266948 1.5669872,5.7330535 1.9999999,5.3541673 2.4330126,4.9752812 13.633975,1.708334 14.5,1.708334 c 0.866026,0 12.066988,3.2669473 12.5,3.6458334 0.433013,0.3788861 0.433013,6.9127806 0,7.2916666 z"
fill="#294c88"
style="stroke-width:0.373483" />
</svg>
<svg height="19" viewBox="0 0 30 19" width="30" xmlns="http://www.w3.org/2000/svg"><path d="m49.367237 34.576282c-.82405 1.427297-22.140189 13.734175-23.78829 13.734175s-22.9642395-12.306878-23.7882901-13.734176c-.82405051-1.427297-.8240504-26.0410535.0000001-27.4683509.8240506-1.4272974 22.140189-13.7341756 23.78829-13.7341756s22.96424 12.3068784 23.78829 13.7341758c.824051 1.4272974.824051 26.0410537 0 27.4683517z" fill="#999" transform="matrix(.57716453 0 0 .31650328 .236739 2.944845)"/><path d="m49.367237 34.576282c-.82405 1.427297-22.140189 13.734175-23.78829 13.734175s-22.9642395-12.306878-23.7882901-13.734176c-.82405051-1.427297-.8240504-26.0410535.0000001-27.4683509.8240506-1.4272974 22.140189-13.7341756 23.78829-13.7341756s22.96424 12.3068784 23.78829 13.7341758c.824051 1.4272974.824051 26.0410537 0 27.4683517z" fill="#294c88" transform="matrix(.52546863 0 0 .26545702 1.559066 4.008757)"/></svg>

Before

Width:  |  Height:  |  Size: 965 B

After

Width:  |  Height:  |  Size: 917 B

View File

@@ -1,14 +1 @@
<svg
height="25"
viewBox="0 0 40 25"
width="40"
xmlns="http://www.w3.org/2000/svg">
<path
d="M 39.091407,18.544437 C 38.430061,19.172594 21.322691,24.588874 20,24.588874 c -1.322691,0 -18.4300616,-5.41628 -19.09140734,-6.044437 -0.6613457,-0.628156 -0.6613456,-11.4607175 10e-8,-12.0888738 C 1.5699385,5.8274068 18.677309,0.411126 20,0.411126 c 1.322691,0 18.430061,5.4162809 19.091407,6.0444372 0.661346,0.6281564 0.661346,11.4607178 0,12.0888738 z"
fill="#999999"
style="stroke-width:0.594311" />
<path
d="M 37.381413,17.569578 C 36.779304,18.096424 21.204219,22.639156 20,22.639156 18.79578,22.639156 3.2206952,18.096424 2.6185853,17.569577 2.0164755,17.042731 2.0164756,7.9572668 2.6185854,7.4304207 3.2206953,6.9035747 18.79578,2.3608422 20,2.3608422 c 1.204219,0 16.779304,4.5427325 17.381413,5.0695786 0.60211,0.5268461 0.60211,9.6123102 0,10.1391572 z"
fill="#136c30"
style="stroke-width:0.519333" />
</svg>
<svg height="26" viewBox="0 0 42 26" width="42" xmlns="http://www.w3.org/2000/svg"><path d="m49.367237 34.576282c-.82405 1.427297-22.140189 13.734175-23.78829 13.734175s-22.9642395-12.306878-23.7882901-13.734176c-.82405051-1.427297-.8240504-26.0410535.0000001-27.4683509.8240506-1.4272974 22.140189-13.7341756 23.78829-13.7341756s22.96424 12.3068784 23.78829 13.7341758c.824051 1.4272974.824051 26.0410537 0 27.4683517z" fill="#999" transform="matrix(.80255481 0 0 .44010193 .471493 3.853665)"/><path d="m49.367237 34.576282c-.82405 1.427297-22.140189 13.734175-23.78829 13.734175s-22.9642395-12.306878-23.7882901-13.734176c-.82405051-1.427297-.8240504-26.0410535.0000001-27.4683509.8240506-1.4272974 22.140189-13.7341756 23.78829-13.7341756s22.96424 12.3068784 23.78829 13.7341758c.824051 1.4272974.824051 26.0410537 0 27.4683517z" fill="#136c30" transform="matrix(.73067099 0 0 .36912143 2.310205 5.333047)"/></svg>

Before

Width:  |  Height:  |  Size: 992 B

After

Width:  |  Height:  |  Size: 917 B

View File

@@ -1,14 +1 @@
<svg
height="18"
viewBox="0 0 29 18"
width="29"
xmlns="http://www.w3.org/2000/svg">
<path
d="M 28.229757,13.346912 C 27.754145,13.798656 15.451225,17.693823 14.5,17.693823 c -0.951226,0 -13.2541449,-3.895167 -13.72975757,-4.346912 -0.4756127,-0.451744 -0.47561263,-8.2420781 10e-8,-8.6938224 C 1.2458552,4.2013443 13.548774,0.306177 14.5,0.306177 c 0.951225,0 13.254145,3.8951673 13.729757,4.3469117 0.475613,0.4517443 0.475613,8.2420783 0,8.6938233 z"
fill="#999999"
style="stroke-width:0.427404" />
<path
d="m 27,12.645834 c -0.433012,0.378886 -11.633974,3.645833 -12.5,3.645833 -0.866025,0 -12.0669874,-3.266947 -12.5000002,-3.645833 C 1.5669871,12.266948 1.5669872,5.7330535 1.9999999,5.3541673 2.4330126,4.9752812 13.633975,1.708334 14.5,1.708334 c 0.866026,0 12.066988,3.2669473 12.5,3.6458334 0.433013,0.3788861 0.433013,6.9127806 0,7.2916666 z"
fill="#136c30"
style="stroke-width:0.373483" />
</svg>
<svg height="19" viewBox="0 0 30 19" width="30" xmlns="http://www.w3.org/2000/svg"><path d="m49.367237 34.576282c-.82405 1.427297-22.140189 13.734175-23.78829 13.734175s-22.9642395-12.306878-23.7882901-13.734176c-.82405051-1.427297-.8240504-26.0410535.0000001-27.4683509.8240506-1.4272974 22.140189-13.7341756 23.78829-13.7341756s22.96424 12.3068784 23.78829 13.7341758c.824051 1.4272974.824051 26.0410537 0 27.4683517z" fill="#999" transform="matrix(.57716453 0 0 .31650328 .236739 2.944845)"/><path d="m49.367237 34.576282c-.82405 1.427297-22.140189 13.734175-23.78829 13.734175s-22.9642395-12.306878-23.7882901-13.734176c-.82405051-1.427297-.8240504-26.0410535.0000001-27.4683509.8240506-1.4272974 22.140189-13.7341756 23.78829-13.7341756s22.96424 12.3068784 23.78829 13.7341758c.824051 1.4272974.824051 26.0410537 0 27.4683517z" fill="#136c30" transform="matrix(.52546863 0 0 .26545702 1.559066 4.008757)"/></svg>

Before

Width:  |  Height:  |  Size: 984 B

After

Width:  |  Height:  |  Size: 917 B

View File

@@ -1,14 +1 @@
<svg
height="25"
viewBox="0 0 40 25"
width="40"
xmlns="http://www.w3.org/2000/svg">
<path
d="M 39.091407,18.544437 C 38.430061,19.172594 21.322691,24.588874 20,24.588874 c -1.322691,0 -18.4300616,-5.41628 -19.09140734,-6.044437 -0.6613457,-0.628156 -0.6613456,-11.4607175 10e-8,-12.0888738 C 1.5699385,5.8274068 18.677309,0.411126 20,0.411126 c 1.322691,0 18.430061,5.4162809 19.091407,6.0444372 0.661346,0.6281564 0.661346,11.4607178 0,12.0888738 z"
fill="#999999"
style="stroke-width:0.594311" />
<path
d="M 37.381413,17.569578 C 36.779304,18.096424 21.204219,22.639156 20,22.639156 18.79578,22.639156 3.2206952,18.096424 2.6185853,17.569577 2.0164755,17.042731 2.0164756,7.9572668 2.6185854,7.4304207 3.2206953,6.9035747 18.79578,2.3608422 20,2.3608422 c 1.204219,0 16.779304,4.5427325 17.381413,5.0695786 0.60211,0.5268461 0.60211,9.6123102 0,10.1391572 z"
fill="#9f1a17"
style="stroke-width:0.519333" />
</svg>
<svg height="26" viewBox="0 0 42 26" width="42" xmlns="http://www.w3.org/2000/svg"><path d="m49.367237 34.576282c-.82405 1.427297-22.140189 13.734175-23.78829 13.734175s-22.9642395-12.306878-23.7882901-13.734176c-.82405051-1.427297-.8240504-26.0410535.0000001-27.4683509.8240506-1.4272974 22.140189-13.7341756 23.78829-13.7341756s22.96424 12.3068784 23.78829 13.7341758c.824051 1.4272974.824051 26.0410537 0 27.4683517z" fill="#999" transform="matrix(.80255481 0 0 .44010193 .471493 3.853665)"/><path d="m49.367237 34.576282c-.82405 1.427297-22.140189 13.734175-23.78829 13.734175s-22.9642395-12.306878-23.7882901-13.734176c-.82405051-1.427297-.8240504-26.0410535.0000001-27.4683509.8240506-1.4272974 22.140189-13.7341756 23.78829-13.7341756s22.96424 12.3068784 23.78829 13.7341758c.824051 1.4272974.824051 26.0410537 0 27.4683517z" fill="#9f1a17" transform="matrix(.73067099 0 0 .36912143 2.310205 5.333047)"/></svg>

Before

Width:  |  Height:  |  Size: 992 B

After

Width:  |  Height:  |  Size: 917 B

View File

@@ -1,14 +1 @@
<svg
height="18"
viewBox="0 0 29 18"
width="29"
xmlns="http://www.w3.org/2000/svg">
<path
d="M 28.229757,13.346912 C 27.754145,13.798656 15.451225,17.693823 14.5,17.693823 c -0.951226,0 -13.2541449,-3.895167 -13.72975757,-4.346912 -0.4756127,-0.451744 -0.47561263,-8.2420781 10e-8,-8.6938224 C 1.2458552,4.2013443 13.548774,0.306177 14.5,0.306177 c 0.951225,0 13.254145,3.8951673 13.729757,4.3469117 0.475613,0.4517443 0.475613,8.2420783 0,8.6938233 z"
fill="#999999"
style="stroke-width:0.427404" />
<path
d="m 27,12.645834 c -0.433012,0.378886 -11.633974,3.645833 -12.5,3.645833 -0.866025,0 -12.0669874,-3.266947 -12.5000002,-3.645833 C 1.5669871,12.266948 1.5669872,5.7330535 1.9999999,5.3541673 2.4330126,4.9752812 13.633975,1.708334 14.5,1.708334 c 0.866026,0 12.066988,3.2669473 12.5,3.6458334 0.433013,0.3788861 0.433013,6.9127806 0,7.2916666 z"
fill="#9f1a17"
style="stroke-width:0.373483" />
</svg>
<svg height="19" viewBox="0 0 30 19" width="30" xmlns="http://www.w3.org/2000/svg"><path d="m49.367237 34.576282c-.82405 1.427297-22.140189 13.734175-23.78829 13.734175s-22.9642395-12.306878-23.7882901-13.734176c-.82405051-1.427297-.8240504-26.0410535.0000001-27.4683509.8240506-1.4272974 22.140189-13.7341756 23.78829-13.7341756s22.96424 12.3068784 23.78829 13.7341758c.824051 1.4272974.824051 26.0410537 0 27.4683517z" fill="#999" transform="matrix(.57716453 0 0 .31650328 .236739 2.944845)"/><path d="m49.367237 34.576282c-.82405 1.427297-22.140189 13.734175-23.78829 13.734175s-22.9642395-12.306878-23.7882901-13.734176c-.82405051-1.427297-.8240504-26.0410535.0000001-27.4683509.8240506-1.4272974 22.140189-13.7341756 23.78829-13.7341756s22.96424 12.3068784 23.78829 13.7341758c.824051 1.4272974.824051 26.0410537 0 27.4683517z" fill="#9f1a17" transform="matrix(.52546863 0 0 .26545702 1.559066 4.008757)"/></svg>

Before

Width:  |  Height:  |  Size: 984 B

After

Width:  |  Height:  |  Size: 917 B

View File

@@ -1,14 +1 @@
<svg
height="25"
viewBox="0 0 40 25"
width="40"
xmlns="http://www.w3.org/2000/svg">
<path
d="M 39.091407,18.544437 C 38.430061,19.172594 21.322691,24.588874 20,24.588874 c -1.322691,0 -18.4300616,-5.41628 -19.09140734,-6.044437 -0.6613457,-0.628156 -0.6613456,-11.4607175 10e-8,-12.0888738 C 1.5699385,5.8274068 18.677309,0.411126 20,0.411126 c 1.322691,0 18.430061,5.4162809 19.091407,6.0444372 0.661346,0.6281564 0.661346,11.4607178 0,12.0888738 z"
fill="#212121"
style="stroke-width:0.594311" />
<path
d="M 37.381413,17.569578 C 36.779304,18.096424 21.204219,22.639156 20,22.639156 18.79578,22.639156 3.2206952,18.096424 2.6185853,17.569577 2.0164755,17.042731 2.0164756,7.9572668 2.6185854,7.4304207 3.2206953,6.9035747 18.79578,2.3608422 20,2.3608422 c 1.204219,0 16.779304,4.5427325 17.381413,5.0695786 0.60211,0.5268461 0.60211,9.6123102 0,10.1391572 z"
fill="#9f5a17"
style="stroke-width:0.519333" />
</svg>
<svg height="26" viewBox="0 0 42 26" width="42" xmlns="http://www.w3.org/2000/svg"><path d="m49.367237 34.576282c-.82405 1.427297-22.140189 13.734175-23.78829 13.734175s-22.9642395-12.306878-23.7882901-13.734176c-.82405051-1.427297-.8240504-26.0410535.0000001-27.4683509.8240506-1.4272974 22.140189-13.7341756 23.78829-13.7341756s22.96424 12.3068784 23.78829 13.7341758c.824051 1.4272974.824051 26.0410537 0 27.4683517z" fill="#212121" transform="matrix(.80255481 0 0 .44010193 .471493 3.853665)"/><path d="m49.367237 34.576282c-.82405 1.427297-22.140189 13.734175-23.78829 13.734175s-22.9642395-12.306878-23.7882901-13.734176c-.82405051-1.427297-.8240504-26.0410535.0000001-27.4683509.8240506-1.4272974 22.140189-13.7341756 23.78829-13.7341756s22.96424 12.3068784 23.78829 13.7341758c.824051 1.4272974.824051 26.0410537 0 27.4683517z" fill="#9f5a17" transform="matrix(.73067099 0 0 .36912143 2.310205 5.333047)"/></svg>

Before

Width:  |  Height:  |  Size: 992 B

After

Width:  |  Height:  |  Size: 920 B

View File

@@ -1,14 +1 @@
<svg
height="18"
viewBox="0 0 29 18"
width="29"
xmlns="http://www.w3.org/2000/svg">
<path
d="M 28.229757,13.346912 C 27.754145,13.798656 15.451225,17.693823 14.5,17.693823 c -0.951226,0 -13.2541449,-3.895167 -13.72975757,-4.346912 -0.4756127,-0.451744 -0.47561263,-8.2420781 10e-8,-8.6938224 C 1.2458552,4.2013443 13.548774,0.306177 14.5,0.306177 c 0.951225,0 13.254145,3.8951673 13.729757,4.3469117 0.475613,0.4517443 0.475613,8.2420783 0,8.6938233 z"
fill="#212121"
style="stroke-width:0.427404" />
<path
d="m 27,12.645834 c -0.433012,0.378886 -11.633974,3.645833 -12.5,3.645833 -0.866025,0 -12.0669874,-3.266947 -12.5000002,-3.645833 C 1.5669871,12.266948 1.5669872,5.7330535 1.9999999,5.3541673 2.4330126,4.9752812 13.633975,1.708334 14.5,1.708334 c 0.866026,0 12.066988,3.2669473 12.5,3.6458334 0.433013,0.3788861 0.433013,6.9127806 0,7.2916666 z"
fill="#9f5a17"
style="stroke-width:0.373483" />
</svg>
<svg height="19" viewBox="0 0 30 19" width="30" xmlns="http://www.w3.org/2000/svg"><path d="m49.367237 34.576282c-.82405 1.427297-22.140189 13.734175-23.78829 13.734175s-22.9642395-12.306878-23.7882901-13.734176c-.82405051-1.427297-.8240504-26.0410535.0000001-27.4683509.8240506-1.4272974 22.140189-13.7341756 23.78829-13.7341756s22.96424 12.3068784 23.78829 13.7341758c.824051 1.4272974.824051 26.0410537 0 27.4683517z" fill="#212121" transform="matrix(.57716453 0 0 .31650328 .236739 2.944845)"/><path d="m49.367237 34.576282c-.82405 1.427297-22.140189 13.734175-23.78829 13.734175s-22.9642395-12.306878-23.7882901-13.734176c-.82405051-1.427297-.8240504-26.0410535.0000001-27.4683509.8240506-1.4272974 22.140189-13.7341756 23.78829-13.7341756s22.96424 12.3068784 23.78829 13.7341758c.824051 1.4272974.824051 26.0410537 0 27.4683517z" fill="#9f5a17" transform="matrix(.52546863 0 0 .26545702 1.559066 4.008757)"/></svg>

Before

Width:  |  Height:  |  Size: 984 B

After

Width:  |  Height:  |  Size: 920 B

View File

@@ -1,14 +0,0 @@
<svg
height="21"
viewBox="0 0 37 21"
width="37"
xmlns="http://www.w3.org/2000/svg">
<g transform="matrix(0.27138802,0,0,0.27138802,4.3878227,-0.11668148)">
<path
d="M 52,2.3036748 H -16.168078 V 54.476396 c -4.14e-4,6.304117 4.321485,11.786348 10.4515331,13.257534 L 52,77.809925 109.71665,67.73393 c 6.13001,-1.471227 10.45186,-6.953449 10.45143,-13.257534 V 2.3036748 Z"
style="fill:#999999;fill-opacity:1;stroke:#ffffff;stroke-width:0" />
<path
d="M 52,9.0567997 H -8.0025878 V 53.8068 c -0.1582841,3.383075 1.8308869,6.499251 4.9662002,7.7799 L 52,70.9148 105.86959,61.5867 c 3.59724,-0.863346 6.13337,-4.080505 6.133,-7.7799 V 9.0567997 Z"
style="fill:#294c88;fill-opacity:1;stroke:#00008b;stroke-width:0" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 774 B

View File

@@ -1,14 +0,0 @@
<svg
height="15"
viewBox="0 0 26 15"
width="26"
xmlns="http://www.w3.org/2000/svg">
<g transform="matrix(0.19044333,0,0,0.19044333,3.0791026,0.18161878)">
<path
d="M 52,2.3036748 H -16.168078 V 54.476396 c -4.14e-4,6.304117 4.321485,11.786348 10.4515331,13.257534 L 52,77.809925 109.71665,67.73393 c 6.13001,-1.471227 10.45186,-6.953449 10.45143,-13.257534 V 2.3036748 Z"
style="fill:#999999;fill-opacity:1;stroke:#ffffff;stroke-width:0" />
<path
d="M 52,9.0567997 H -8.0025878 V 53.8068 c -0.1582841,3.383075 1.8308869,6.499251 4.9662002,7.7799 L 52,70.9148 105.86959,61.5867 c 3.59724,-0.863346 6.13337,-4.080505 6.133,-7.7799 V 9.0567997 Z"
style="fill:#294c88;fill-opacity:1;stroke:#00008b;stroke-width:0" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 773 B

View File

@@ -1,14 +0,0 @@
<svg
height="21"
viewBox="0 0 37 21"
width="37"
xmlns="http://www.w3.org/2000/svg">
<g transform="matrix(0.27138802,0,0,0.27138802,4.3878227,-0.11668148)">
<path
d="M 52,2.3036748 H -16.168078 V 54.476396 c -4.14e-4,6.304117 4.321485,11.786348 10.4515331,13.257534 L 52,77.809925 109.71665,67.73393 c 6.13001,-1.471227 10.45186,-6.953449 10.45143,-13.257534 V 2.3036748 Z"
style="fill:#999999;fill-opacity:1;stroke:#ffffff;stroke-width:0" />
<path
d="M 52,9.0567997 H -8.0025878 V 53.8068 c -0.1582841,3.383075 1.8308869,6.499251 4.9662002,7.7799 L 52,70.9148 105.86959,61.5867 c 3.59724,-0.863346 6.13337,-4.080505 6.133,-7.7799 V 9.0567997 Z"
style="fill:#136c30;fill-opacity:1;stroke:#00008b;stroke-width:0" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 774 B

View File

@@ -1,14 +0,0 @@
<svg
height="15"
viewBox="0 0 26 15"
width="26"
xmlns="http://www.w3.org/2000/svg">
<g transform="matrix(0.19044333,0,0,0.19044333,3.0791026,0.18161878)">
<path
d="M 52,2.3036748 H -16.168078 V 54.476396 c -4.14e-4,6.304117 4.321485,11.786348 10.4515331,13.257534 L 52,77.809925 109.71665,67.73393 c 6.13001,-1.471227 10.45186,-6.953449 10.45143,-13.257534 V 2.3036748 Z"
style="fill:#999999;fill-opacity:1;stroke:#ffffff;stroke-width:0" />
<path
d="M 52,9.0567997 H -8.0025878 V 53.8068 c -0.1582841,3.383075 1.8308869,6.499251 4.9662002,7.7799 L 52,70.9148 105.86959,61.5867 c 3.59724,-0.863346 6.13337,-4.080505 6.133,-7.7799 V 9.0567997 Z"
style="fill:#136c30;fill-opacity:1;stroke:#00008b;stroke-width:0" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 773 B

View File

@@ -104,7 +104,6 @@ node[leisure=beach_resort],
node[leisure=marina],
node[leisure=sports_centre][sport=scuba_diving],
node[leisure=sports_centre][sport=swimming],
node[leisure=water_park],
{text-color: @water_label;text-halo-radius: 0.1;text-halo-opacity: 0.7;text-halo-color: @label_halo_light;}
area[amenity=university][name]

View File

@@ -1,14 +1 @@
<svg
height="25"
viewBox="0 0 40 25"
width="40"
xmlns="http://www.w3.org/2000/svg">
<path
d="M 39.091407,18.544437 C 38.430061,19.172594 21.322691,24.588874 20,24.588874 c -1.322691,0 -18.4300616,-5.41628 -19.09140734,-6.044437 -0.6613457,-0.628156 -0.6613456,-11.4607175 10e-8,-12.0888738 C 1.5699385,5.8274068 18.677309,0.411126 20,0.411126 c 1.322691,0 18.430061,5.4162809 19.091407,6.0444372 0.661346,0.6281564 0.661346,11.4607178 0,12.0888738 z"
fill="#ffffff"
style="stroke-width:0.594311" />
<path
d="M 37.381413,17.569578 C 36.779304,18.096424 21.204219,22.639156 20,22.639156 18.79578,22.639156 3.2206952,18.096424 2.6185853,17.569577 2.0164755,17.042731 2.0164756,7.9572668 2.6185854,7.4304207 3.2206953,6.9035747 18.79578,2.3608422 20,2.3608422 c 1.204219,0 16.779304,4.5427325 17.381413,5.0695786 0.60211,0.5268461 0.60211,9.6123102 0,10.1391572 z"
fill="#1a5ec1"
style="stroke-width:0.519333" />
</svg>
<svg height="26" viewBox="0 0 42 26" width="42" xmlns="http://www.w3.org/2000/svg"><path d="m49.367237 34.576282c-.82405 1.427297-22.140189 13.734175-23.78829 13.734175s-22.9642395-12.306878-23.7882901-13.734176c-.82405051-1.427297-.8240504-26.0410535.0000001-27.4683509.8240506-1.4272974 22.140189-13.7341756 23.78829-13.7341756s22.96424 12.3068784 23.78829 13.7341758c.824051 1.4272974.824051 26.0410537 0 27.4683517z" fill="#fff" transform="matrix(.80255481 0 0 .44010193 .471493 3.853665)"/><path d="m49.367237 34.576282c-.82405 1.427297-22.140189 13.734175-23.78829 13.734175s-22.9642395-12.306878-23.7882901-13.734176c-.82405051-1.427297-.8240504-26.0410535.0000001-27.4683509.8240506-1.4272974 22.140189-13.7341756 23.78829-13.7341756s22.96424 12.3068784 23.78829 13.7341758c.824051 1.4272974.824051 26.0410537 0 27.4683517z" fill="#1a5ec1" transform="matrix(.73067099 0 0 .36912143 2.310205 5.333047)"/></svg>

Before

Width:  |  Height:  |  Size: 973 B

After

Width:  |  Height:  |  Size: 917 B

View File

@@ -1,14 +1 @@
<svg
height="18"
viewBox="0 0 29 18"
width="29"
xmlns="http://www.w3.org/2000/svg">
<path
d="M 28.229757,13.346912 C 27.754145,13.798656 15.451225,17.693823 14.5,17.693823 c -0.951226,0 -13.2541449,-3.895167 -13.72975757,-4.346912 -0.4756127,-0.451744 -0.47561263,-8.2420781 10e-8,-8.6938224 C 1.2458552,4.2013443 13.548774,0.306177 14.5,0.306177 c 0.951225,0 13.254145,3.8951673 13.729757,4.3469117 0.475613,0.4517443 0.475613,8.2420783 0,8.6938233 z"
fill="#ffffff"
style="stroke-width:0.427404" />
<path
d="m 27,12.645834 c -0.433012,0.378886 -11.633974,3.645833 -12.5,3.645833 -0.866025,0 -12.0669874,-3.266947 -12.5000002,-3.645833 C 1.5669871,12.266948 1.5669872,5.7330535 1.9999999,5.3541673 2.4330126,4.9752812 13.633975,1.708334 14.5,1.708334 c 0.866026,0 12.066988,3.2669473 12.5,3.6458334 0.433013,0.3788861 0.433013,6.9127806 0,7.2916666 z"
fill="#1a5ec1"
style="stroke-width:0.373483" />
</svg>
<svg height="19" viewBox="0 0 30 19" width="30" xmlns="http://www.w3.org/2000/svg"><path d="m49.367237 34.576282c-.82405 1.427297-22.140189 13.734175-23.78829 13.734175s-22.9642395-12.306878-23.7882901-13.734176c-.82405051-1.427297-.8240504-26.0410535.0000001-27.4683509.8240506-1.4272974 22.140189-13.7341756 23.78829-13.7341756s22.96424 12.3068784 23.78829 13.7341758c.824051 1.4272974.824051 26.0410537 0 27.4683517z" fill="#fff" transform="matrix(.57716453 0 0 .31650328 .236739 2.944845)"/><path d="m49.367237 34.576282c-.82405 1.427297-22.140189 13.734175-23.78829 13.734175s-22.9642395-12.306878-23.7882901-13.734176c-.82405051-1.427297-.8240504-26.0410535.0000001-27.4683509.8240506-1.4272974 22.140189-13.7341756 23.78829-13.7341756s22.96424 12.3068784 23.78829 13.7341758c.824051 1.4272974.824051 26.0410537 0 27.4683517z" fill="#1a5ec1" transform="matrix(.52546863 0 0 .26545702 1.559066 4.008757)"/></svg>

Before

Width:  |  Height:  |  Size: 965 B

After

Width:  |  Height:  |  Size: 917 B

View File

@@ -1,14 +1 @@
<svg
height="25"
viewBox="0 0 40 25"
width="40"
xmlns="http://www.w3.org/2000/svg">
<path
d="M 39.091407,18.544437 C 38.430061,19.172594 21.322691,24.588874 20,24.588874 c -1.322691,0 -18.4300616,-5.41628 -19.09140734,-6.044437 -0.6613457,-0.628156 -0.6613456,-11.4607175 10e-8,-12.0888738 C 1.5699385,5.8274068 18.677309,0.411126 20,0.411126 c 1.322691,0 18.430061,5.4162809 19.091407,6.0444372 0.661346,0.6281564 0.661346,11.4607178 0,12.0888738 z"
fill="#ffffff"
style="stroke-width:0.594311" />
<path
d="M 37.381413,17.569578 C 36.779304,18.096424 21.204219,22.639156 20,22.639156 18.79578,22.639156 3.2206952,18.096424 2.6185853,17.569577 2.0164755,17.042731 2.0164756,7.9572668 2.6185854,7.4304207 3.2206953,6.9035747 18.79578,2.3608422 20,2.3608422 c 1.204219,0 16.779304,4.5427325 17.381413,5.0695786 0.60211,0.5268461 0.60211,9.6123102 0,10.1391572 z"
fill="#309302"
style="stroke-width:0.519333" />
</svg>
<svg height="26" viewBox="0 0 42 26" width="42" xmlns="http://www.w3.org/2000/svg"><path d="m49.367237 34.576282c-.82405 1.427297-22.140189 13.734175-23.78829 13.734175s-22.9642395-12.306878-23.7882901-13.734176c-.82405051-1.427297-.8240504-26.0410535.0000001-27.4683509.8240506-1.4272974 22.140189-13.7341756 23.78829-13.7341756s22.96424 12.3068784 23.78829 13.7341758c.824051 1.4272974.824051 26.0410537 0 27.4683517z" fill="#fff" transform="matrix(.80255481 0 0 .44010193 .471493 3.853665)"/><path d="m49.367237 34.576282c-.82405 1.427297-22.140189 13.734175-23.78829 13.734175s-22.9642395-12.306878-23.7882901-13.734176c-.82405051-1.427297-.8240504-26.0410535.0000001-27.4683509.8240506-1.4272974 22.140189-13.7341756 23.78829-13.7341756s22.96424 12.3068784 23.78829 13.7341758c.824051 1.4272974.824051 26.0410537 0 27.4683517z" fill="#309302" transform="matrix(.73067099 0 0 .36912143 2.310205 5.333047)"/></svg>

Before

Width:  |  Height:  |  Size: 992 B

After

Width:  |  Height:  |  Size: 917 B

View File

@@ -1,14 +1 @@
<svg
height="18"
viewBox="0 0 29 18"
width="29"
xmlns="http://www.w3.org/2000/svg">
<path
d="M 28.229757,13.346912 C 27.754145,13.798656 15.451225,17.693823 14.5,17.693823 c -0.951226,0 -13.2541449,-3.895167 -13.72975757,-4.346912 -0.4756127,-0.451744 -0.47561263,-8.2420781 10e-8,-8.6938224 C 1.2458552,4.2013443 13.548774,0.306177 14.5,0.306177 c 0.951225,0 13.254145,3.8951673 13.729757,4.3469117 0.475613,0.4517443 0.475613,8.2420783 0,8.6938233 z"
fill="#fff"
style="stroke-width:0.427404" />
<path
d="m 27,12.645834 c -0.433012,0.378886 -11.633974,3.645833 -12.5,3.645833 -0.866025,0 -12.0669874,-3.266947 -12.5000002,-3.645833 C 1.5669871,12.266948 1.5669872,5.7330535 1.9999999,5.3541673 2.4330126,4.9752812 13.633975,1.708334 14.5,1.708334 c 0.866026,0 12.066988,3.2669473 12.5,3.6458334 0.433013,0.3788861 0.433013,6.9127806 0,7.2916666 z"
fill="#309302"
style="stroke-width:0.373483" />
</svg>
<svg height="19" viewBox="0 0 30 19" width="30" xmlns="http://www.w3.org/2000/svg"><path d="m49.367237 34.576282c-.82405 1.427297-22.140189 13.734175-23.78829 13.734175s-22.9642395-12.306878-23.7882901-13.734176c-.82405051-1.427297-.8240504-26.0410535.0000001-27.4683509.8240506-1.4272974 22.140189-13.7341756 23.78829-13.7341756s22.96424 12.3068784 23.78829 13.7341758c.824051 1.4272974.824051 26.0410537 0 27.4683517z" fill="#fff" transform="matrix(.57716453 0 0 .31650328 .236739 2.944845)"/><path d="m49.367237 34.576282c-.82405 1.427297-22.140189 13.734175-23.78829 13.734175s-22.9642395-12.306878-23.7882901-13.734176c-.82405051-1.427297-.8240504-26.0410535.0000001-27.4683509.8240506-1.4272974 22.140189-13.7341756 23.78829-13.7341756s22.96424 12.3068784 23.78829 13.7341758c.824051 1.4272974.824051 26.0410537 0 27.4683517z" fill="#309302" transform="matrix(.52546863 0 0 .26545702 1.559066 4.008757)"/></svg>

Before

Width:  |  Height:  |  Size: 981 B

After

Width:  |  Height:  |  Size: 917 B

View File

@@ -1,14 +1 @@
<svg
height="25"
viewBox="0 0 40 25"
width="40"
xmlns="http://www.w3.org/2000/svg">
<path
d="M 39.091407,18.544437 C 38.430061,19.172594 21.322691,24.588874 20,24.588874 c -1.322691,0 -18.4300616,-5.41628 -19.09140734,-6.044437 -0.6613457,-0.628156 -0.6613456,-11.4607175 10e-8,-12.0888738 C 1.5699385,5.8274068 18.677309,0.411126 20,0.411126 c 1.322691,0 18.430061,5.4162809 19.091407,6.0444372 0.661346,0.6281564 0.661346,11.4607178 0,12.0888738 z"
fill="#ffffff"
style="stroke-width:0.594311" />
<path
d="M 37.381413,17.569578 C 36.779304,18.096424 21.204219,22.639156 20,22.639156 18.79578,22.639156 3.2206952,18.096424 2.6185853,17.569577 2.0164755,17.042731 2.0164756,7.9572668 2.6185854,7.4304207 3.2206953,6.9035747 18.79578,2.3608422 20,2.3608422 c 1.204219,0 16.779304,4.5427325 17.381413,5.0695786 0.60211,0.5268461 0.60211,9.6123102 0,10.1391572 z"
fill="#e63534"
style="stroke-width:0.519333" />
</svg>
<svg height="26" viewBox="0 0 42 26" width="42" xmlns="http://www.w3.org/2000/svg"><path d="m49.367237 34.576282c-.82405 1.427297-22.140189 13.734175-23.78829 13.734175s-22.9642395-12.306878-23.7882901-13.734176c-.82405051-1.427297-.8240504-26.0410535.0000001-27.4683509.8240506-1.4272974 22.140189-13.7341756 23.78829-13.7341756s22.96424 12.3068784 23.78829 13.7341758c.824051 1.4272974.824051 26.0410537 0 27.4683517z" fill="#fff" transform="matrix(.80255481 0 0 .44010193 .471493 3.853665)"/><path d="m49.367237 34.576282c-.82405 1.427297-22.140189 13.734175-23.78829 13.734175s-22.9642395-12.306878-23.7882901-13.734176c-.82405051-1.427297-.8240504-26.0410535.0000001-27.4683509.8240506-1.4272974 22.140189-13.7341756 23.78829-13.7341756s22.96424 12.3068784 23.78829 13.7341758c.824051 1.4272974.824051 26.0410537 0 27.4683517z" fill="#e63534" transform="matrix(.73067099 0 0 .36912143 2.310205 5.333047)"/></svg>

Before

Width:  |  Height:  |  Size: 992 B

After

Width:  |  Height:  |  Size: 917 B

View File

@@ -1,14 +1 @@
<svg
height="18"
viewBox="0 0 29 18"
width="29"
xmlns="http://www.w3.org/2000/svg">
<path
d="M 28.229757,13.346912 C 27.754145,13.798656 15.451225,17.693823 14.5,17.693823 c -0.951226,0 -13.2541449,-3.895167 -13.72975757,-4.346912 -0.4756127,-0.451744 -0.47561263,-8.2420781 10e-8,-8.6938224 C 1.2458552,4.2013443 13.548774,0.306177 14.5,0.306177 c 0.951225,0 13.254145,3.8951673 13.729757,4.3469117 0.475613,0.4517443 0.475613,8.2420783 0,8.6938233 z"
fill="#fff"
style="stroke-width:0.427404" />
<path
d="m 27,12.645834 c -0.433012,0.378886 -11.633974,3.645833 -12.5,3.645833 -0.866025,0 -12.0669874,-3.266947 -12.5000002,-3.645833 C 1.5669871,12.266948 1.5669872,5.7330535 1.9999999,5.3541673 2.4330126,4.9752812 13.633975,1.708334 14.5,1.708334 c 0.866026,0 12.066988,3.2669473 12.5,3.6458334 0.433013,0.3788861 0.433013,6.9127806 0,7.2916666 z"
fill="#e63534"
style="stroke-width:0.373483" />
</svg>
<svg height="19" viewBox="0 0 30 19" width="30" xmlns="http://www.w3.org/2000/svg"><path d="m49.367237 34.576282c-.82405 1.427297-22.140189 13.734175-23.78829 13.734175s-22.9642395-12.306878-23.7882901-13.734176c-.82405051-1.427297-.8240504-26.0410535.0000001-27.4683509.8240506-1.4272974 22.140189-13.7341756 23.78829-13.7341756s22.96424 12.3068784 23.78829 13.7341758c.824051 1.4272974.824051 26.0410537 0 27.4683517z" fill="#fff" transform="matrix(.57716453 0 0 .31650328 .236739 2.944845)"/><path d="m49.367237 34.576282c-.82405 1.427297-22.140189 13.734175-23.78829 13.734175s-22.9642395-12.306878-23.7882901-13.734176c-.82405051-1.427297-.8240504-26.0410535.0000001-27.4683509.8240506-1.4272974 22.140189-13.7341756 23.78829-13.7341756s22.96424 12.3068784 23.78829 13.7341758c.824051 1.4272974.824051 26.0410537 0 27.4683517z" fill="#e63534" transform="matrix(.52546863 0 0 .26545702 1.559066 4.008757)"/></svg>

Before

Width:  |  Height:  |  Size: 981 B

After

Width:  |  Height:  |  Size: 917 B

View File

@@ -1,14 +1 @@
<svg
height="25"
viewBox="0 0 40 25"
width="40"
xmlns="http://www.w3.org/2000/svg">
<path
d="M 39.091407,18.544437 C 38.430061,19.172594 21.322691,24.588874 20,24.588874 c -1.322691,0 -18.4300616,-5.41628 -19.09140734,-6.044437 -0.6613457,-0.628156 -0.6613456,-11.4607175 10e-8,-12.0888738 C 1.5699385,5.8274068 18.677309,0.411126 20,0.411126 c 1.322691,0 18.430061,5.4162809 19.091407,6.0444372 0.661346,0.6281564 0.661346,11.4607178 0,12.0888738 z"
fill=""
style="stroke-width:0.594311" />
<path
d="M 37.381413,17.569578 C 36.779304,18.096424 21.204219,22.639156 20,22.639156 18.79578,22.639156 3.2206952,18.096424 2.6185853,17.569577 2.0164755,17.042731 2.0164756,7.9572668 2.6185854,7.4304207 3.2206953,6.9035747 18.79578,2.3608422 20,2.3608422 c 1.204219,0 16.779304,4.5427325 17.381413,5.0695786 0.60211,0.5268461 0.60211,9.6123102 0,10.1391572 z"
fill="#c97600"
style="stroke-width:0.519333" />
</svg>
<svg height="26" viewBox="0 0 42 26" width="42" xmlns="http://www.w3.org/2000/svg"><path d="m49.367237 34.576282c-.82405 1.427297-22.140189 13.734175-23.78829 13.734175s-22.9642395-12.306878-23.7882901-13.734176c-.82405051-1.427297-.8240504-26.0410535.0000001-27.4683509.8240506-1.4272974 22.140189-13.7341756 23.78829-13.7341756s22.96424 12.3068784 23.78829 13.7341758c.824051 1.4272974.824051 26.0410537 0 27.4683517z" transform="matrix(.80255481 0 0 .44010193 .471493 3.853665)"/><path d="m49.367237 34.576282c-.82405 1.427297-22.140189 13.734175-23.78829 13.734175s-22.9642395-12.306878-23.7882901-13.734176c-.82405051-1.427297-.8240504-26.0410535.0000001-27.4683509.8240506-1.4272974 22.140189-13.7341756 23.78829-13.7341756s22.96424 12.3068784 23.78829 13.7341758c.824051 1.4272974.824051 26.0410537 0 27.4683517z" fill="#c97600" transform="matrix(.73067099 0 0 .36912143 2.310205 5.333047)"/></svg>

Before

Width:  |  Height:  |  Size: 985 B

After

Width:  |  Height:  |  Size: 905 B

View File

@@ -1,14 +1 @@
<svg
height="18"
viewBox="0 0 29 18"
width="29"
xmlns="http://www.w3.org/2000/svg">
<path
d="M 28.229757,13.346912 C 27.754145,13.798656 15.451225,17.693823 14.5,17.693823 c -0.951226,0 -13.2541449,-3.895167 -13.72975757,-4.346912 -0.4756127,-0.451744 -0.47561263,-8.2420781 10e-8,-8.6938224 C 1.2458552,4.2013443 13.548774,0.306177 14.5,0.306177 c 0.951225,0 13.254145,3.8951673 13.729757,4.3469117 0.475613,0.4517443 0.475613,8.2420783 0,8.6938233 z"
fill=""
style="stroke-width:0.427404" />
<path
d="m 27,12.645834 c -0.433012,0.378886 -11.633974,3.645833 -12.5,3.645833 -0.866025,0 -12.0669874,-3.266947 -12.5000002,-3.645833 C 1.5669871,12.266948 1.5669872,5.7330535 1.9999999,5.3541673 2.4330126,4.9752812 13.633975,1.708334 14.5,1.708334 c 0.866026,0 12.066988,3.2669473 12.5,3.6458334 0.433013,0.3788861 0.433013,6.9127806 0,7.2916666 z"
fill="#c97600"
style="stroke-width:0.373483" />
</svg>
<svg height="19" viewBox="0 0 30 19" width="30" xmlns="http://www.w3.org/2000/svg"><path d="m49.367237 34.576282c-.82405 1.427297-22.140189 13.734175-23.78829 13.734175s-22.9642395-12.306878-23.7882901-13.734176c-.82405051-1.427297-.8240504-26.0410535.0000001-27.4683509.8240506-1.4272974 22.140189-13.7341756 23.78829-13.7341756s22.96424 12.3068784 23.78829 13.7341758c.824051 1.4272974.824051 26.0410537 0 27.4683517z" transform="matrix(.57716453 0 0 .31650328 .236739 2.944845)"/><path d="m49.367237 34.576282c-.82405 1.427297-22.140189 13.734175-23.78829 13.734175s-22.9642395-12.306878-23.7882901-13.734176c-.82405051-1.427297-.8240504-26.0410535.0000001-27.4683509.8240506-1.4272974 22.140189-13.7341756 23.78829-13.7341756s22.96424 12.3068784 23.78829 13.7341758c.824051 1.4272974.824051 26.0410537 0 27.4683517z" fill="#c97600" transform="matrix(.52546863 0 0 .26545702 1.559066 4.008757)"/></svg>

Before

Width:  |  Height:  |  Size: 977 B

After

Width:  |  Height:  |  Size: 905 B

View File

@@ -1,14 +0,0 @@
<svg
height="21"
viewBox="0 0 37 21"
width="37"
xmlns="http://www.w3.org/2000/svg">
<g transform="matrix(0.27138802,0,0,0.27138802,4.3878227,-0.11668148)">
<path
d="M 52,2.3036748 H -16.168078 V 54.476396 c -4.14e-4,6.304117 4.321485,11.786348 10.4515331,13.257534 L 52,77.809925 109.71665,67.73393 c 6.13001,-1.471227 10.45186,-6.953449 10.45143,-13.257534 V 2.3036748 Z"
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0" />
<path
d="M 52,9.0567997 H -8.0025878 V 53.8068 c -0.1582841,3.383075 1.8308869,6.499251 4.9662002,7.7799 L 52,70.9148 105.86959,61.5867 c 3.59724,-0.863346 6.13337,-4.080505 6.133,-7.7799 V 9.0567997 Z"
style="fill:#1a5ec1;fill-opacity:1;stroke:#00008b;stroke-width:0" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 774 B

View File

@@ -1,14 +0,0 @@
<svg
height="15"
viewBox="0 0 26 15"
width="26"
xmlns="http://www.w3.org/2000/svg">
<g transform="matrix(0.19044333,0,0,0.19044333,3.0791026,0.18161878)">
<path
d="M 52,2.3036748 H -16.168078 V 54.476396 c -4.14e-4,6.304117 4.321485,11.786348 10.4515331,13.257534 L 52,77.809925 109.71665,67.73393 c 6.13001,-1.471227 10.45186,-6.953449 10.45143,-13.257534 V 2.3036748 Z"
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0" />
<path
d="M 52,9.0567997 H -8.0025878 V 53.8068 c -0.1582841,3.383075 1.8308869,6.499251 4.9662002,7.7799 L 52,70.9148 105.86959,61.5867 c 3.59724,-0.863346 6.13337,-4.080505 6.133,-7.7799 V 9.0567997 Z"
style="fill:#1a5ec1;fill-opacity:1;stroke:#00008b;stroke-width:0" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 773 B

View File

@@ -1,14 +0,0 @@
<svg
height="21"
viewBox="0 0 37 21"
width="37"
xmlns="http://www.w3.org/2000/svg">
<g transform="matrix(0.27138802,0,0,0.27138802,4.3878227,-0.11668148)">
<path
d="M 52,2.3036748 H -16.168078 V 54.476396 c -4.14e-4,6.304117 4.321485,11.786348 10.4515331,13.257534 L 52,77.809925 109.71665,67.73393 c 6.13001,-1.471227 10.45186,-6.953449 10.45143,-13.257534 V 2.3036748 Z"
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0" />
<path
d="M 52,9.0567997 H -8.0025878 V 53.8068 c -0.1582841,3.383075 1.8308869,6.499251 4.9662002,7.7799 L 52,70.9148 105.86959,61.5867 c 3.59724,-0.863346 6.13337,-4.080505 6.133,-7.7799 V 9.0567997 Z"
style="fill:#309302;fill-opacity:1;stroke:#00008b;stroke-width:0" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 774 B

View File

@@ -1,14 +0,0 @@
<svg
height="15"
viewBox="0 0 26 15"
width="26"
xmlns="http://www.w3.org/2000/svg">
<g transform="matrix(0.19044333,0,0,0.19044333,3.0791026,0.18161878)">
<path
d="M 52,2.3036748 H -16.168078 V 54.476396 c -4.14e-4,6.304117 4.321485,11.786348 10.4515331,13.257534 L 52,77.809925 109.71665,67.73393 c 6.13001,-1.471227 10.45186,-6.953449 10.45143,-13.257534 V 2.3036748 Z"
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0" />
<path
d="M 52,9.0567997 H -8.0025878 V 53.8068 c -0.1582841,3.383075 1.8308869,6.499251 4.9662002,7.7799 L 52,70.9148 105.86959,61.5867 c 3.59724,-0.863346 6.13337,-4.080505 6.133,-7.7799 V 9.0567997 Z"
style="fill:#309302;fill-opacity:1;stroke:#00008b;stroke-width:0" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 773 B

View File

@@ -29,6 +29,7 @@ static NSString *didChangeOutdoorMapStyle = @"didChangeOutdoorMapStyle";
if (self) {
_observers = [NSHashTable weakObjectsHashTable];
GetFramework().GetTrafficManager().SetStateListener([self](TrafficManager::TrafficState state) {
[NSNotificationCenter.defaultCenter postNotificationName:@"LayersChanged" object:nil];
for (id<MWMMapOverlayManagerObserver> observer in self.observers) {
if ([observer respondsToSelector:@selector(onTrafficStateUpdated)]) {
[observer onTrafficStateUpdated];
@@ -36,6 +37,7 @@ static NSString *didChangeOutdoorMapStyle = @"didChangeOutdoorMapStyle";
}
});
GetFramework().GetTransitManager().SetStateListener([self](TransitReadManager::TransitSchemeState state) {
[NSNotificationCenter.defaultCenter postNotificationName:@"LayersChanged" object:nil];
for (id<MWMMapOverlayManagerObserver> observer in self.observers) {
if ([observer respondsToSelector:@selector(onTransitStateUpdated)]) {
[observer onTransitStateUpdated];
@@ -43,6 +45,7 @@ static NSString *didChangeOutdoorMapStyle = @"didChangeOutdoorMapStyle";
}
});
GetFramework().GetIsolinesManager().SetStateListener([self](IsolinesManager::IsolinesState state) {
[NSNotificationCenter.defaultCenter postNotificationName:@"LayersChanged" object:nil];
for (id<MWMMapOverlayManagerObserver> observer in self.observers) {
if ([observer respondsToSelector:@selector(onIsoLinesStateUpdated)]) {
[observer onIsoLinesStateUpdated];
@@ -50,6 +53,7 @@ static NSString *didChangeOutdoorMapStyle = @"didChangeOutdoorMapStyle";
}
});
[NSNotificationCenter.defaultCenter addObserverForName:didChangeOutdoorMapStyle object:nil queue:nil usingBlock:^(NSNotification * _Nonnull notification) {
[NSNotificationCenter.defaultCenter postNotificationName:@"LayersChanged" object:nil];
for (id<MWMMapOverlayManagerObserver> observer in self.observers) {
if ([observer respondsToSelector:@selector(onOutdoorStateUpdated)]) {
[observer onOutdoorStateUpdated];

View File

@@ -10,6 +10,7 @@
#import <CoreApi/CoreApi.h>
#import "Controls.h"
#import "DeepLinkRouteStrategyAdapter.h"
#import "EAGLView.h"
#import "FirstSession.h"

View File

@@ -16,6 +16,13 @@ import UIKit
routinOptionsBridgeController.view.backgroundColor = .systemGroupedBackground
return routinOptionsBridgeController
}
/// The `ControlsView` for presentation in an alert
@objc static func mapControls() -> UIViewController {
let controlsBridgeController = UIHostingController(rootView: ControlsView())
controlsBridgeController.view.backgroundColor = .clear
return controlsBridgeController
}
}

View File

@@ -0,0 +1,11 @@
NS_SWIFT_NAME(Controls)
@interface Controls : NSObject
+ (void)zoomIn;
+ (void)zoomOut;
+ (void)switchToNextPositionMode;
+ (NSString *)positionModeRawValue;
+ (Controls *)shared;
- (bool)hasMainButtons;
@end

View File

@@ -0,0 +1,75 @@
#import "Controls.h"
#import "SwiftBridge.h"
#include <CoreApi/Framework.h>
@implementation Controls
static Controls *shared = nil;
+ (Controls *)shared
{
if (shared == nil)
{
shared = [[super allocWithZone:NULL] init];
}
return shared;
}
+ (id)allocWithZone:(NSZone *)zone
{
return [self shared];
}
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
- (id)init
{
self = [super init];
if (self != nil)
{
// Initialize instance variables here
}
return self;
}
+ (void)zoomIn;
{
GetFramework().Scale(Framework::SCALE_MAG, true);
}
+ (void)zoomOut;
{
GetFramework().Scale(Framework::SCALE_MIN, true);
}
+ (NSString *)positionModeRawValue;
{
location::EMyPositionMode mode = GetFramework().GetMyPositionMode();
switch (mode)
{
case location::EMyPositionMode::NotFollowNoPosition: return @"Locate";
case location::EMyPositionMode::NotFollow: return @"Locate";
case location::EMyPositionMode::PendingPosition: return @"Locating";
case location::EMyPositionMode::Follow: return @"Following";
case location::EMyPositionMode::FollowAndRotate: return @"FollowingAndRotated";
}
return @"Locate";
}
+ (void)switchToNextPositionMode;
{
[MWMLocationManager enableLocationAlert];
GetFramework().SwitchMyPositionNextMode();
}
- (bool)hasMainButtons;
{
return true;
}
@end

View File

@@ -0,0 +1,12 @@
extension Controls {
@objc static let changeChangeTrackRecordingNotificationName: Notification.Name = Notification.Name(rawValue: "ChangeTrackRecording")
/// The notification name for switching position mode
@objc static let switchPositionModeNotificationName: Notification.Name = Notification.Name(rawValue: "SwitchPositionMode")
@objc static let changeVisibilityMainButtonsNotificationName: Notification.Name = Notification.Name(rawValue: "ChangeVisibilityMainButtons")
static var positionMode: MapPositionButton.Mode {
return MapPositionButton.Mode(rawValue: Controls.positionModeRawValue()) ?? .locate
}
}

View File

@@ -3,7 +3,6 @@
#import "MWMNavigationDashboardManager.h"
@class MapViewController;
@class BottomTabBarViewController;
@class TrackRecordingButtonViewController;
@class SearchQuery;
@@ -26,7 +25,7 @@ typedef NS_ENUM(NSUInteger, TrackRecordingButtonState) {
@property(nonatomic) MWMBottomMenuState menuState;
@property(nonatomic) MWMBottomMenuState menuRestoreState;
@property(nonatomic) BOOL isDirectionViewHidden;
@property(nonatomic) BottomTabBarViewController * tabBarController;
@property(nonatomic) UIViewController * tabBarController;
@property(nonatomic) TrackRecordingButtonViewController * trackRecordingButton;
- (instancetype)init __attribute__((unavailable("init is not available")));

View File

@@ -64,6 +64,9 @@ NSString *const kMapToCategorySelectorSegue = @"MapToCategorySelectorSegue";
self.menuRestoreState = MWMBottomMenuStateInactive;
self.isAddingPlace = NO;
self.searchManager = controller.searchManager;
[self tabBarController];
return self;
}
@@ -220,13 +223,20 @@ NSString *const kMapToCategorySelectorSegue = @"MapToCategorySelectorSegue";
return _trafficButton;
}
- (BottomTabBarViewController *)tabBarController {
- (UIViewController *)tabBarController {
if (!_tabBarController) {
MapViewController * ownerController = _ownerController;
_tabBarController = [BottomTabBarBuilder buildWithMapViewController:ownerController controlsManager:self];
_tabBarController = [BridgeControllers mapControls];
[ownerController addChildViewController:_tabBarController];
UIView * tabBarViewSuperView = ownerController.controlsView;
[tabBarViewSuperView addSubview:_tabBarController.view];
_tabBarController.view.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[
[tabBarViewSuperView.topAnchor constraintEqualToAnchor:_tabBarController.view.topAnchor],
[tabBarViewSuperView.leadingAnchor constraintEqualToAnchor:_tabBarController.view.leadingAnchor],
[tabBarViewSuperView.bottomAnchor constraintEqualToAnchor:_tabBarController.view.bottomAnchor],
[tabBarViewSuperView.trailingAnchor constraintEqualToAnchor:_tabBarController.view.trailingAnchor]
]];
}
return _tabBarController;
@@ -289,7 +299,7 @@ NSString *const kMapToCategorySelectorSegue = @"MapToCategorySelectorSegue";
MapViewController * ownerController = _ownerController;
switch (_menuState) {
case MWMBottomMenuStateActive:
_tabBarController.isHidden = NO;
_tabBarController.view.hidden = NO;
if (_menuController == nil) {
_menuController = [BottomMenuBuilder buildMenuWithMapViewController:ownerController
controlsManager:self
@@ -298,7 +308,7 @@ NSString *const kMapToCategorySelectorSegue = @"MapToCategorySelectorSegue";
}
break;
case MWMBottomMenuStateLayers:
_tabBarController.isHidden = NO;
_tabBarController.view.hidden = NO;
if (_menuController == nil) {
_menuController = [BottomMenuBuilder buildLayersWithMapViewController:ownerController
controlsManager:self
@@ -307,14 +317,14 @@ NSString *const kMapToCategorySelectorSegue = @"MapToCategorySelectorSegue";
}
break;
case MWMBottomMenuStateInactive:
_tabBarController.isHidden = NO;
_tabBarController.view.hidden = NO;
if (_menuController != nil) {
[_menuController dismissViewControllerAnimated:YES completion:nil];
_menuController = nil;
}
break;
case MWMBottomMenuStateHidden:
_tabBarController.isHidden = YES;
_tabBarController.view.hidden = YES;
if (_menuController != nil) {
[_menuController dismissViewControllerAnimated:YES completion:nil];
_menuController = nil;

View File

@@ -1,11 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="23727" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23721"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
@@ -18,12 +16,12 @@
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="WVx-0E-RoH" customClass="MWMButton" propertyAccessControl="all">
<rect key="frame" x="0.0" y="0.0" width="56" height="56"/>
<viewLayoutGuide key="safeArea" id="iUc-A7-STp"/>
<accessibility key="accessibilityConfiguration" identifier="layers_button"/>
<constraints>
<constraint firstAttribute="height" constant="56" id="24f-V4-Vuf"/>
<constraint firstAttribute="width" constant="56" id="hko-xz-hRz"/>
</constraints>
<viewLayoutGuide key="safeArea" id="iUc-A7-STp"/>
<state key="normal" image="btn_traffic_on_light"/>
<connections>
<action selector="buttonTouchUpInside" destination="-1" eventType="touchUpInside" id="fKZ-g8-4ML"/>

View File

@@ -314,7 +314,7 @@ NSString *const kNavigationControlViewXibName = @"NavigationControlView";
[[MapViewController sharedController] updateStatusBarStyle];
// Restore bottom buttons only if they were not already hidden by tapping anywhere on an empty map.
if (!MWMMapViewControlsManager.manager.hidden)
BottomTabBarViewController.controller.isHidden = state != MWMNavigationDashboardStateHidden;
MWMMapViewControlsManager.manager.tabBarController.view.hidden = state != MWMNavigationDashboardStateHidden;
}
@synthesize routePreview = _routePreview;

View File

@@ -28,7 +28,6 @@
- (void)performAction:(NSString *_Nonnull)action;
- (void)openMenu;
- (void)openSettings;
- (void)openAbout;
- (void)openMapsDownloader:(MWMMapDownloaderMode)mode;

View File

@@ -574,10 +574,6 @@ NSString *const kAboutSegue = @"Map2About";
}
#pragma mark - Open controllers
- (void)openMenu {
[self.controlsManager.tabBarController onMenuButtonPressed:self];
}
- (void)openSettings {
[self performSegueWithIdentifier:kSettingsSegue sender:nil];
}
@@ -636,6 +632,7 @@ NSString *const kAboutSegue = @"Map2About";
self.disableStandbyOnLocationStateMode = YES;
break;
}
[NSNotificationCenter.defaultCenter postNotificationName:Controls.switchPositionModeNotificationName object:nil];
}
#pragma mark - MWMFrameworkDrapeObserver

View File

@@ -299,10 +299,8 @@ void InitLocalizedStrings() {
- (void)updateApplicationIconBadgeNumber {
auto const number = [self badgeNumber];
// Delay init because BottomTabBarViewController.controller is null here.
dispatch_async(dispatch_get_main_queue(), ^{
[UIApplication.sharedApplication setApplicationIconBadgeNumber:number];
BottomTabBarViewController.controller.isApplicationBadgeHidden = (number == 0);
});
}

View File

@@ -121,8 +121,8 @@
}
return true
case .menu:
MapsAppDelegate.theApp().mapViewController.openMenu()
return true
// Not supported on iOS.
return false
case .settings:
MapsAppDelegate.theApp().mapViewController.openSettings()
return true

View File

@@ -228,6 +228,7 @@ extension TrackRecordingManager: TrackRecordingObservable {
@objc
private func notifyObservers() {
NotificationCenter.default.post(name: Controls.changeChangeTrackRecordingNotificationName, object: nil)
observations.removeAll { $0.observer == nil }
observations.forEach {
$0.recordingStateDidChangeHandler?(recordingState, trackRecordingInfo, { self.trackRecordingElevationProfileData })

View File

@@ -288,6 +288,10 @@
"placepage_distance" = "Distance";
"search_show_on_map" = "View on map";
/* Button title */
"zoom_in" = "Zoom In";
"zoom_out" = "Zoom Out";
/* Text in menu */
"website" = "Website";

View File

@@ -591,5 +591,5 @@
"existence_confirmed_time_ago" = "Existence confirmed %@";
"offline_explanation_text" = "Hai que descargar un mapa para ver e navegar polo área.\nDescarga os mapas para as zonas polas que vas viaxar.";
"offline_explanation_title" = "Mapas sen conexión";
"avoid_steps" = "Evitar escaleiras";
"avoid_steps" = "Evitar pasos";
"editor_place_doesnt_exist_description" = "Describe a aparencia do lugar para enviar unha nota co erro á comunidade OpenStreetMap";

View File

@@ -662,7 +662,7 @@
"type.landuse.religious" = "Religiøst område";
"type.landuse.commercial" = "Næringsområde";
"type.landuse.construction" = "Byggeplass";
"type.landuse.education" = "Utdanningsinstitusjon";
"type.landuse.education" = "Educational Facility";
"type.landuse.farmland" = "Jordbruksområde";
"type.landuse.farmyard" = "Bondegård";
"type.landuse.field" = "Field";
@@ -760,7 +760,7 @@
"type.man_made.water_well.drinking_water_no" = "Brønn";
"type.man_made.windmill" = "Vindmølle";
"type.man_made.works" = "Industrial Works";
"type.military" = "Militært";
"type.military" = "Military";
"type.military.bunker" = "Bunker";
"type.mountain_pass" = "Fjellpass";
"type.natural" = "Natur";
@@ -892,12 +892,12 @@
"type.railway.abandoned" = "Nedlagt jernbane";
"type.railway.abandoned.bridge" = "Nedlagt jernbanebru";
"type.railway.abandoned.tunnel" = "Nedlagt jernbanetunnel";
"type.railway.construction" = "Jernbanebygging";
"type.railway.construction" = "Railway Construction";
"type.railway.crossing" = "Jernbaneovergang";
"type.railway.disused" = "Ubenyttet jernbane";
"type.railway.funicular" = "Kabelbane";
"type.railway.funicular.bridge" = "Kabelbanebru";
"type.railway.funicular.tunnel" = "Kabelbanetunnel";
"type.railway.funicular.bridge" = "Funicular Bridge";
"type.railway.funicular.tunnel" = "Funicular Tunnel";
"type.railway.halt" = "Togstasjon";
"type.railway.level_crossing" = "Planovergang";
"type.railway.light_rail" = "Light Rail";
@@ -1198,7 +1198,7 @@
"type.shop.books" = "Bokhandel";
"type.shop.butcher" = "Slakter";
"type.shop.cannabis" = "Cannabisbutikk";
"type.shop.car" = "Bilforhandler";
"type.shop.car" = "Bil butikk";
"type.shop.car_parts" = "Bildeler";
"type.shop.car_repair" = "Bilverksted";
"type.shop.car_repair.tyres" = "Dekkreparasjon";
@@ -1467,7 +1467,7 @@
"type.sport.diving" = "High Diving";
"type.highway.ladder" = "Stige";
"type.natural.wetland.swamp" = "Sumpskog";
"type.man_made.crane" = "Kran";
"type.man_made.crane" = "Crane";
"type.natural.wetland.saltmarsh" = "Salt Marsh";
"type.natural.wetland.mangrove" = "Mangrove";
"type.barrier.guard_rail" = "Autovern";
@@ -1482,7 +1482,7 @@
"type.amenity.luggage_locker" = "Bagasjeoppbevaring";
"type.amenity.ranger_station" = "Ranger Station";
"type.amenity.bicycle_parking.covered" = "Overbygd sykkelparkering";
"type.post_office.post_partner" = "Post i butikk";
"type.post_office.post_partner" = "Post Partner";
"type.barrier.wicket_gate" = "Wicket gate";
"type.amenity.animal_shelter" = "Dyrehjem";
"type.office.security" = "Security Guards Office";

View File

@@ -319,10 +319,10 @@
"report_incorrect_map_bug" = "Raportați sau remediați datele incorecte de pe hartă";
/* Button in the About screen */
"volunteer" = "Fii voluntar și îmbunătațește CoMaps";
"volunteer" = "Pentru a fi voluntar";
/* "Social media" section header in the About screen */
"follow_us" = "Conectează-te cu noi";
"follow_us" = "Urmăriți-ne și contactați-ne";
/* Alert text */
"email_error_body" = "Clientul de e-mail nu a fost configurat. Te rugăm să-l configurezi sau să ne contactezi la %@";
@@ -1090,6 +1090,6 @@
"pref_mapappearance_title" = "Map Appearance";
"pref_maplanguage_title" = "Map Language";
"transliteration_title_disabled_summary" = "Disabled when always using the local language for the map";
"pref_maplanguage_local" = "Limbă Locală";
"pref_maplanguage_local" = "Local Language";
"hours_confirmed_time_ago" = "Confirmed %@";
"existence_confirmed_time_ago" = "Existence confirmed %@";

View File

@@ -1471,7 +1471,7 @@
"type.natural.wetland.saltmarsh" = "Mlaștină sărată";
"type.natural.wetland.mangrove" = "Pădure de mangrove";
"type.barrier.guard_rail" = "Barieră de protecție";
"type.amenity.studio" = "Studio Media";
"type.amenity.studio" = "Garsonieră";
"type.natural.wetland.fen" = "Pajiște mlăștinoasă";
"type.natural.wetland.saltmarsh.tidal" = "Mlaștină sărată de maree";
"type.natural.wetland.reedbed" = "Stufăriș";

View File

@@ -377,4 +377,3 @@
"placepage_call_button" = "Klic";
"today" = "Danes";
"bookmark_sets" = "Seznami zaznamkov";
"about_proposition_3" = "Transparentno in nedobičkonosno";

View File

@@ -152,4 +152,3 @@
"type.aeroway" = "Infrastruktura zračnega prostora";
"type.amenity.love_hotel" = "Hotel za zaljubljence";
"type.amenity.charging_station.motorcar.small" = "Polnilno mesto za avtomobile";
"type.amenity.cinema" = "Kino";

View File

@@ -12,8 +12,6 @@
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>zero</key>
<string>Noll bokmärken</string>
<key>one</key>
<string>%d bokmärke</string>
<key>other</key>

View File

@@ -30,9 +30,10 @@
27697F902E257EDA00FBD913 /* AboutCoMapsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27697F8F2E257ED800FBD913 /* AboutCoMapsView.swift */; };
27697F922E257EED00FBD913 /* ApoutOpenStreetMapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27697F912E257EE600FBD913 /* ApoutOpenStreetMapView.swift */; };
27768FDB2E20199A0086784A /* RoutingOptionsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27768FD92E20199A0086784A /* RoutingOptionsView.swift */; };
27768FE02E201BE60086784A /* LeftButtonType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27768FDF2E201BE60086784A /* LeftButtonType.swift */; };
279367562E1BE16300AA5C3D /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279367552E1BE16300AA5C3D /* Settings.swift */; };
2793675A2E1BE17300AA5C3D /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279367592E1BE17300AA5C3D /* SettingsView.swift */; };
279387C42E4C8EB7009FDF8B /* MapPositionButtonMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279387C12E4C8EB6009FDF8B /* MapPositionButtonMode.swift */; };
279387C62E4C918A009FDF8B /* Controls.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279387C52E4C9187009FDF8B /* Controls.swift */; };
27AF184C2E1D5B2D00CD41E2 /* SettingsNavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27AF184B2E1D5A2700CD41E2 /* SettingsNavigationView.swift */; };
27AF18502E1DB61600CD41E2 /* VoiceRoutingLanguage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27AF184F2E1DB61500CD41E2 /* VoiceRoutingLanguage.swift */; };
27AF18522E1DB62000CD41E2 /* DistanceUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27AF18512E1DB61F00CD41E2 /* DistanceUnit.swift */; };
@@ -40,6 +41,18 @@
27AF18562E1DB63000CD41E2 /* PowerSavingMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27AF18552E1DB62F00CD41E2 /* PowerSavingMode.swift */; };
27AF18582E1DB63A00CD41E2 /* Appearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27AF18572E1DB63900CD41E2 /* Appearance.swift */; };
27AF185A2E1DB64500CD41E2 /* AnnouncingSpeedTrapsWhileVoiceRouting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27AF18592E1DB64400CD41E2 /* AnnouncingSpeedTrapsWhileVoiceRouting.swift */; };
27BDA4862E4366AC00C478B8 /* MapLayerButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27BDA4852E4366A600C478B8 /* MapLayerButton.swift */; };
27BDA4882E4366C600C478B8 /* MapPositionButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27BDA4872E4366B600C478B8 /* MapPositionButton.swift */; };
27BDA48A2E4366F400C478B8 /* MainButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27BDA4892E4366EC00C478B8 /* MainButton.swift */; };
27BDA48C2E43670300C478B8 /* MapZoomButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27BDA48B2E4366FB00C478B8 /* MapZoomButton.swift */; };
27BDA4902E436A1B00C478B8 /* MapZoomButtonKind.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27BDA48F2E436A1600C478B8 /* MapZoomButtonKind.swift */; };
27BDA4A22E436D1900C478B8 /* MainButtonType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27BDA4A12E436D1100C478B8 /* MainButtonType.swift */; };
27BDA4A62E437B5200C478B8 /* BottomTabBarButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27BDA4A52E437B5200C478B8 /* BottomTabBarButton.swift */; };
27BDA4A82E437F9800C478B8 /* ControlsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27BDA4A72E437F8E00C478B8 /* ControlsView.swift */; };
27BDA4AA2E437FEF00C478B8 /* MapTrackRecordingButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27BDA4A92E437FE400C478B8 /* MapTrackRecordingButton.swift */; };
27E5CAAD2E4B644100FA3597 /* FloatingButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27E5CAAA2E4B643A00FA3597 /* FloatingButtonStyle.swift */; };
27E5CAAF2E4B6CBC00FA3597 /* Controls.h in Sources */ = {isa = PBXBuildFile; fileRef = 27E5CAAE2E4B6CB800FA3597 /* Controls.h */; };
27E5CAB12E4B6D0300FA3597 /* Controls.mm in Sources */ = {isa = PBXBuildFile; fileRef = 27E5CAB02E4B6CFC00FA3597 /* Controls.mm */; };
3304306D21D4EAFB00317CA3 /* SearchCategoryCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3304306C21D4EAFB00317CA3 /* SearchCategoryCell.swift */; };
33046832219C57180041F3A8 /* CategorySettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33046831219C57180041F3A8 /* CategorySettingsViewController.swift */; };
337F98A621D37B7400C8AC27 /* SearchTabViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 337F98A521D37B7400C8AC27 /* SearchTabViewController.swift */; };
@@ -115,7 +128,6 @@
349A13831DEC138C00C7DB60 /* MWMMobileInternetAlert.m in Sources */ = {isa = PBXBuildFile; fileRef = 349A13801DEC138C00C7DB60 /* MWMMobileInternetAlert.m */; };
349A13851DEC138C00C7DB60 /* MWMMobileInternetAlert.xib in Resources */ = {isa = PBXBuildFile; fileRef = 349A13811DEC138C00C7DB60 /* MWMMobileInternetAlert.xib */; };
349D1AD51E2E325B004A2006 /* BottomMenuItemCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 349D1AC61E2E325B004A2006 /* BottomMenuItemCell.xib */; };
349D1AE11E2E325C004A2006 /* BottomTabBarViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 349D1ACD1E2E325B004A2006 /* BottomTabBarViewController.xib */; };
349D1CE41E3F836900A878FD /* UIViewController+Hierarchy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 349D1CE21E3F836900A878FD /* UIViewController+Hierarchy.swift */; };
34AB39C21D2BD8310021857D /* MWMStopButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 34AB39C01D2BD8310021857D /* MWMStopButton.m */; };
34AB66051FC5AA320078E451 /* MWMNavigationDashboardManager+Entity.mm in Sources */ = {isa = PBXBuildFile; fileRef = 34AB65C51FC5AA320078E451 /* MWMNavigationDashboardManager+Entity.mm */; };
@@ -326,11 +338,6 @@
8C4FB9C72BEFEFF400D44877 /* CarPlayWindowScaleAdjuster.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C4FB9C62BEFEFF400D44877 /* CarPlayWindowScaleAdjuster.swift */; };
8CB13C3B2BF1276A004288F2 /* CarplayPlaceholderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CB13C3A2BF1276A004288F2 /* CarplayPlaceholderView.swift */; };
99012847243F0D6900C72B10 /* UIViewController+alternative.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99012846243F0D6900C72B10 /* UIViewController+alternative.swift */; };
9901284F244732DB00C72B10 /* BottomTabBarPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99012849244732DB00C72B10 /* BottomTabBarPresenter.swift */; };
99012851244732DB00C72B10 /* BottomTabBarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9901284B244732DB00C72B10 /* BottomTabBarViewController.swift */; };
99012852244732DB00C72B10 /* BottomTabBarBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9901284C244732DB00C72B10 /* BottomTabBarBuilder.swift */; };
99012853244732DB00C72B10 /* BottomTabBarInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9901284D244732DB00C72B10 /* BottomTabBarInteractor.swift */; };
990128562449A82500C72B10 /* BottomTabBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 990128552449A82400C72B10 /* BottomTabBarView.swift */; };
9917D17F2397B1D600A7E06E /* IPadModalPresentationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9917D17E2397B1D600A7E06E /* IPadModalPresentationController.swift */; };
991FCA2423B11E61009AD684 /* BookmarksStyleSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 991FCA2323B11E61009AD684 /* BookmarksStyleSheet.swift */; };
993DF0B523F6B2EF00AC231A /* PlacePageTrackLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 993DF0B423F6B2EF00AC231A /* PlacePageTrackLayout.swift */; };
@@ -479,7 +486,6 @@
ED2D74662D1435A600660FBF /* LiveActivityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED2D742D2D14337500660FBF /* LiveActivityManager.swift */; };
ED2E328E2D10500900807A08 /* TrackRecordingButtonArea.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED46DD922D06F804007CACD6 /* TrackRecordingButtonArea.swift */; };
ED2E32912D10501700807A08 /* TrackRecordingButtonViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED49D76F2CF0E3A8004AF27E /* TrackRecordingButtonViewController.swift */; };
ED3EAC202B03C88100220A4A /* BottomTabBarButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3EAC1F2B03C88100220A4A /* BottomTabBarButton.swift */; };
ED43B8BD2C12063500D07BAA /* DocumentPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED43B8BC2C12063500D07BAA /* DocumentPicker.swift */; };
ED46DDCE2D098A0B007CACD6 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ED46DDCD2D098A0B007CACD6 /* WidgetKit.framework */; };
ED46DDD02D098A0B007CACD6 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ED46DDCF2D098A0B007CACD6 /* SwiftUI.framework */; };
@@ -779,9 +785,10 @@
27697F8F2E257ED800FBD913 /* AboutCoMapsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutCoMapsView.swift; sourceTree = "<group>"; };
27697F912E257EE600FBD913 /* ApoutOpenStreetMapView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApoutOpenStreetMapView.swift; sourceTree = "<group>"; };
27768FD92E20199A0086784A /* RoutingOptionsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoutingOptionsView.swift; sourceTree = "<group>"; };
27768FDF2E201BE60086784A /* LeftButtonType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LeftButtonType.swift; sourceTree = "<group>"; };
279367552E1BE16300AA5C3D /* Settings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Settings.swift; sourceTree = "<group>"; };
279367592E1BE17300AA5C3D /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SettingsView.swift; path = UI/Settings/SettingsView.swift; sourceTree = SOURCE_ROOT; };
279387C12E4C8EB6009FDF8B /* MapPositionButtonMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapPositionButtonMode.swift; sourceTree = "<group>"; };
279387C52E4C9187009FDF8B /* Controls.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Controls.swift; sourceTree = "<group>"; };
27AF184B2E1D5A2700CD41E2 /* SettingsNavigationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsNavigationView.swift; sourceTree = "<group>"; };
27AF184F2E1DB61500CD41E2 /* VoiceRoutingLanguage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceRoutingLanguage.swift; sourceTree = "<group>"; };
27AF18512E1DB61F00CD41E2 /* DistanceUnit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DistanceUnit.swift; sourceTree = "<group>"; };
@@ -789,6 +796,18 @@
27AF18552E1DB62F00CD41E2 /* PowerSavingMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PowerSavingMode.swift; sourceTree = "<group>"; };
27AF18572E1DB63900CD41E2 /* Appearance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Appearance.swift; sourceTree = "<group>"; };
27AF18592E1DB64400CD41E2 /* AnnouncingSpeedTrapsWhileVoiceRouting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnnouncingSpeedTrapsWhileVoiceRouting.swift; sourceTree = "<group>"; };
27BDA4852E4366A600C478B8 /* MapLayerButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapLayerButton.swift; sourceTree = "<group>"; };
27BDA4872E4366B600C478B8 /* MapPositionButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapPositionButton.swift; sourceTree = "<group>"; };
27BDA4892E4366EC00C478B8 /* MainButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainButton.swift; sourceTree = "<group>"; };
27BDA48B2E4366FB00C478B8 /* MapZoomButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapZoomButton.swift; sourceTree = "<group>"; };
27BDA48F2E436A1600C478B8 /* MapZoomButtonKind.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapZoomButtonKind.swift; sourceTree = "<group>"; };
27BDA4A12E436D1100C478B8 /* MainButtonType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainButtonType.swift; sourceTree = "<group>"; };
27BDA4A52E437B5200C478B8 /* BottomTabBarButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BottomTabBarButton.swift; sourceTree = "<group>"; };
27BDA4A72E437F8E00C478B8 /* ControlsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ControlsView.swift; sourceTree = "<group>"; };
27BDA4A92E437FE400C478B8 /* MapTrackRecordingButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTrackRecordingButton.swift; sourceTree = "<group>"; };
27E5CAAA2E4B643A00FA3597 /* FloatingButtonStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FloatingButtonStyle.swift; sourceTree = "<group>"; };
27E5CAAE2E4B6CB800FA3597 /* Controls.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Controls.h; sourceTree = "<group>"; };
27E5CAB02E4B6CFC00FA3597 /* Controls.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = Controls.mm; sourceTree = "<group>"; };
28A0AB4B0D9B1048005BE974 /* Maps_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = Maps_Prefix.pch; sourceTree = "<group>"; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
29B97316FDCFA39411CA2CEA /* main.mm */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 4; indentWidth = 2; path = main.mm; sourceTree = "<group>"; tabWidth = 2; };
30034C5C2B3F0B74005D961A /* az */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = az; path = az.lproj/Localizable.strings; sourceTree = "<group>"; };
@@ -929,7 +948,6 @@
349A35781B53D4C9009677EE /* MWMCircularProgressView.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = MWMCircularProgressView.h; sourceTree = "<group>"; tabWidth = 2; };
349A35791B53D4C9009677EE /* MWMCircularProgressView.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; path = MWMCircularProgressView.m; sourceTree = "<group>"; tabWidth = 2; };
349D1AC61E2E325B004A2006 /* BottomMenuItemCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = BottomMenuItemCell.xib; sourceTree = "<group>"; };
349D1ACD1E2E325B004A2006 /* BottomTabBarViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = BottomTabBarViewController.xib; sourceTree = "<group>"; };
349D1CE21E3F836900A878FD /* UIViewController+Hierarchy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIViewController+Hierarchy.swift"; sourceTree = "<group>"; };
34AB39BF1D2BD8310021857D /* MWMStopButton.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = MWMStopButton.h; sourceTree = "<group>"; tabWidth = 2; };
34AB39C01D2BD8310021857D /* MWMStopButton.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; path = MWMStopButton.m; sourceTree = "<group>"; tabWidth = 2; };
@@ -1218,11 +1236,6 @@
978D4A30199A11E600D72CA7 /* faq.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = faq.html; path = ../../data/faq.html; sourceTree = "<group>"; };
97A5967E19B9CD47007A963F /* copyright.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = copyright.html; path = ../../data/copyright.html; sourceTree = "<group>"; };
99012846243F0D6900C72B10 /* UIViewController+alternative.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+alternative.swift"; sourceTree = "<group>"; };
99012849244732DB00C72B10 /* BottomTabBarPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BottomTabBarPresenter.swift; sourceTree = "<group>"; };
9901284B244732DB00C72B10 /* BottomTabBarViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BottomTabBarViewController.swift; sourceTree = "<group>"; };
9901284C244732DB00C72B10 /* BottomTabBarBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BottomTabBarBuilder.swift; sourceTree = "<group>"; };
9901284D244732DB00C72B10 /* BottomTabBarInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BottomTabBarInteractor.swift; sourceTree = "<group>"; };
990128552449A82400C72B10 /* BottomTabBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BottomTabBarView.swift; sourceTree = "<group>"; };
9917D17E2397B1D600A7E06E /* IPadModalPresentationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IPadModalPresentationController.swift; sourceTree = "<group>"; };
991FCA2323B11E61009AD684 /* BookmarksStyleSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarksStyleSheet.swift; sourceTree = "<group>"; };
993DF0B423F6B2EF00AC231A /* PlacePageTrackLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlacePageTrackLayout.swift; sourceTree = "<group>"; };
@@ -1421,7 +1434,6 @@
ED2D74352D14337500660FBF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
ED2D74362D14337500660FBF /* CoMapsWidgetExtensionBundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoMapsWidgetExtensionBundle.swift; sourceTree = "<group>"; };
ED2D745D2D1433DE00660FBF /* TrackRecordingActivityManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrackRecordingActivityManager.swift; sourceTree = "<group>"; };
ED3EAC1F2B03C88100220A4A /* BottomTabBarButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BottomTabBarButton.swift; sourceTree = "<group>"; };
ED43B8BC2C12063500D07BAA /* DocumentPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentPicker.swift; sourceTree = "<group>"; };
ED46DD922D06F804007CACD6 /* TrackRecordingButtonArea.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrackRecordingButtonArea.swift; sourceTree = "<group>"; };
ED46DDCC2D098A0B007CACD6 /* CoMapsWidgetExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = CoMapsWidgetExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -1904,6 +1916,9 @@
27697F822E254A9900FBD913 /* EmbeddedSafariView.swift */,
27697F842E255B6300FBD913 /* EmbeddedSafariViewCoordinator.swift */,
27697F862E255B7C00FBD913 /* EmbeddedSafariViewContent.swift */,
27E5CAAE2E4B6CB800FA3597 /* Controls.h */,
27E5CAB02E4B6CFC00FA3597 /* Controls.mm */,
279387C52E4C9187009FDF8B /* Controls.swift */,
);
path = Bridging;
sourceTree = "<group>";
@@ -1963,7 +1978,6 @@
2752B6CD2E3121D800887CC4 /* Language.swift */,
2752B6C92E31197000887CC4 /* MapLanguage.swift */,
27AF184F2E1DB61500CD41E2 /* VoiceRoutingLanguage.swift */,
27768FDF2E201BE60086784A /* LeftButtonType.swift */,
27AF18512E1DB61F00CD41E2 /* DistanceUnit.swift */,
27AF18532E1DB62600CD41E2 /* MobileDataPolicy.swift */,
27AF18552E1DB62F00CD41E2 /* PowerSavingMode.swift */,
@@ -1973,6 +1987,19 @@
path = "Settings Types";
sourceTree = "<group>";
};
27BDA4952E436C2D00C478B8 /* New Group */ = {
isa = PBXGroup;
children = (
27BDA4852E4366A600C478B8 /* MapLayerButton.swift */,
27BDA4A92E437FE400C478B8 /* MapTrackRecordingButton.swift */,
27BDA4872E4366B600C478B8 /* MapPositionButton.swift */,
279387C12E4C8EB6009FDF8B /* MapPositionButtonMode.swift */,
27BDA48B2E4366FB00C478B8 /* MapZoomButton.swift */,
27BDA48F2E436A1600C478B8 /* MapZoomButtonKind.swift */,
);
path = "New Group";
sourceTree = "<group>";
};
29B97314FDCFA39411CA2CEA /* Maps */ = {
isa = PBXGroup;
children = (
@@ -2505,8 +2532,8 @@
children = (
99AAEA72244DA59E0039D110 /* Presentation */,
998927312449E5ED00260CE2 /* Menu */,
99012848244732C200C72B10 /* TabBar */,
995F1610244F07F90060631D /* MWMBottomMenuState.h */,
27BDA4A52E437B5200C478B8 /* BottomTabBarButton.swift */,
);
path = BottomMenu;
sourceTree = "<group>";
@@ -2847,20 +2874,6 @@
name = "Custom Views";
sourceTree = "<group>";
};
99012848244732C200C72B10 /* TabBar */ = {
isa = PBXGroup;
children = (
99012849244732DB00C72B10 /* BottomTabBarPresenter.swift */,
9901284B244732DB00C72B10 /* BottomTabBarViewController.swift */,
9901284C244732DB00C72B10 /* BottomTabBarBuilder.swift */,
9901284D244732DB00C72B10 /* BottomTabBarInteractor.swift */,
349D1ACD1E2E325B004A2006 /* BottomTabBarViewController.xib */,
990128552449A82400C72B10 /* BottomTabBarView.swift */,
ED3EAC1F2B03C88100220A4A /* BottomTabBarButton.swift */,
);
path = TabBar;
sourceTree = "<group>";
};
993DF0C223F6BD0600AC231A /* ElevationDetails */ = {
isa = PBXGroup;
children = (
@@ -3583,6 +3596,11 @@
F6E2FBFB1E097B9F0083EBEC /* UI */ = {
isa = PBXGroup;
children = (
27BDA4A72E437F8E00C478B8 /* ControlsView.swift */,
27BDA4892E4366EC00C478B8 /* MainButton.swift */,
27BDA4A12E436D1100C478B8 /* MainButtonType.swift */,
27BDA4952E436C2D00C478B8 /* New Group */,
27E5CAAA2E4B643A00FA3597 /* FloatingButtonStyle.swift */,
27768FDA2E20199A0086784A /* Routing */,
ED9857022C4ECFFC00694F6C /* MailComposer */,
ED43B8B92C12061600D07BAA /* DocumentPicker */,
@@ -4209,7 +4227,6 @@
4761BE2B252D3DB900EE2DE4 /* SubgroupCell.xib in Resources */,
99F9A0E72462CA1700AE21E0 /* DownloadAllView.xib in Resources */,
349D1AD51E2E325B004A2006 /* BottomMenuItemCell.xib in Resources */,
349D1AE11E2E325C004A2006 /* BottomTabBarViewController.xib in Resources */,
34D3B01E1E389D05004100F9 /* MWMButtonCell.xib in Resources */,
9959C75624582DA2008FD4FD /* DirectionView.xib in Resources */,
6741A98B1BF340DE002C974C /* MWMCircularProgress.xib in Resources */,
@@ -4348,7 +4365,6 @@
34845DB71E166084003D55B9 /* Common.swift in Sources */,
47F4F21323A6EC420022FD56 /* DownloadMapsViewController.swift in Sources */,
99A906F623FA9C010005872B /* InsetsLabelRenderer.swift in Sources */,
99012853244732DB00C72B10 /* BottomTabBarInteractor.swift in Sources */,
6741A9A31BF340DE002C974C /* main.mm in Sources */,
34D3B04F1E38A20C004100F9 /* Bundle+Init.swift in Sources */,
34AB666E1FC5AA330078E451 /* TransportTransitStepsCollectionView.swift in Sources */,
@@ -4422,6 +4438,8 @@
3D15ACEE2155117000F725D5 /* MWMObjectsCategorySelectorDataSource.mm in Sources */,
9977E6A32480F9BF0073780C /* BottomMenuLayerButtonRenderer.swift in Sources */,
272F1F392E0EE09000FA52EF /* ExistingProfileView.swift in Sources */,
27E5CAAD2E4B644100FA3597 /* FloatingButtonStyle.swift in Sources */,
27BDA4862E4366AC00C478B8 /* MapLayerButton.swift in Sources */,
3454D7D11E07F045004AF2AD /* UIImage+RGBAData.m in Sources */,
6741A9B71BF340DE002C974C /* EAGLView.mm in Sources */,
6741A9B81BF340DE002C974C /* MapViewController.mm in Sources */,
@@ -4449,6 +4467,7 @@
F6E2FEE51E097BA00083EBEC /* MWMSearchNoResults.m in Sources */,
ED5E02142D8B17B600A5CC7B /* ModalPresentationStepsController.swift in Sources */,
4715273524907F8200E91BBA /* BookmarkColorViewController.swift in Sources */,
279387C62E4C918A009FDF8B /* Controls.swift in Sources */,
47E3C7292111E614008B3B27 /* FadeInAnimatedTransitioning.swift in Sources */,
ED79A5D42BDF8D6100952D1F /* MetadataItem.swift in Sources */,
34AB667D1FC5AA330078E451 /* MWMRoutePreview.mm in Sources */,
@@ -4472,6 +4491,7 @@
F6E2FDA11E097BA00083EBEC /* MWMEditorAdditionalNamesTableViewController.mm in Sources */,
4767CDA620AB1F6200BD8166 /* LeftAlignedIconButton.swift in Sources */,
3454D7D41E07F045004AF2AD /* UIImageView+Coloring.m in Sources */,
27BDA4882E4366C600C478B8 /* MapPositionButton.swift in Sources */,
993DF11D23F6BDB100AC231A /* UIToolbarRenderer.swift in Sources */,
99A906E923F6F7030005872B /* WikiDescriptionViewController.swift in Sources */,
ED79A5D62BDF8D6100952D1F /* CloudDirectoryMonitor.swift in Sources */,
@@ -4505,6 +4525,7 @@
99C9642B2428C0F700E41723 /* PlacePageHeaderViewController.swift in Sources */,
F6FE3C391CC50FFD00A73196 /* MWMPlaceDoesntExistAlert.m in Sources */,
F6E2FDFE1E097BA00083EBEC /* MWMOpeningHoursClosedSpanTableViewCell.mm in Sources */,
27BDA4A62E437B5200C478B8 /* BottomTabBarButton.swift in Sources */,
34B846A12029DCC10081ECCD /* BMCCategoriesHeader.swift in Sources */,
99A906F123FA946E0005872B /* DifficultyViewRenderer.swift in Sources */,
F6E2FD5F1E097BA00083EBEC /* MWMMapDownloaderLargeCountryTableViewCell.m in Sources */,
@@ -4525,7 +4546,6 @@
EDB71E002D8B0338004A6A7F /* ModalPresentationAnimator.swift in Sources */,
F6E2FD8C1E097BA00083EBEC /* MWMNoMapsView.m in Sources */,
34D3B0361E389D05004100F9 /* MWMEditorSelectTableViewCell.m in Sources */,
990128562449A82500C72B10 /* BottomTabBarView.swift in Sources */,
F6E2FD711E097BA00083EBEC /* MWMMapDownloaderTableViewCell.m in Sources */,
F6E2FE4F1E097BA00083EBEC /* MWMActionBarButton.m in Sources */,
47F86CFF20C936FC00FEE291 /* TabView.swift in Sources */,
@@ -4554,9 +4574,9 @@
34AB66081FC5AA320078E451 /* MWMNavigationDashboardManager.mm in Sources */,
3404F490202898CC0090E401 /* BMCModels.swift in Sources */,
F6E2FD561E097BA00083EBEC /* MWMMapDownloaderButtonTableViewCell.m in Sources */,
9901284F244732DB00C72B10 /* BottomTabBarPresenter.swift in Sources */,
CDB4D5002231412900104869 /* MapTemplateBuilder.swift in Sources */,
34AB66171FC5AA320078E451 /* MWMiPhoneRoutePreview.m in Sources */,
27BDA4A82E437F9800C478B8 /* ControlsView.swift in Sources */,
99A906EA23F6F7030005872B /* PlacePageInfoViewController.swift in Sources */,
993DF11723F6BDB100AC231A /* UINavigationBarRenderer.swift in Sources */,
6741A9E71BF340DE002C974C /* MWMCircularProgressView.m in Sources */,
@@ -4607,8 +4627,9 @@
34AB66111FC5AA320078E451 /* NavigationTurnsView.swift in Sources */,
475ED78624C7C7300063ADC7 /* ValueStepperViewRenderer.swift in Sources */,
3490D2E11CE9DD2500D0B838 /* MWMSideButtonsView.mm in Sources */,
27BDA4AA2E437FEF00C478B8 /* MapTrackRecordingButton.swift in Sources */,
279387C42E4C8EB7009FDF8B /* MapPositionButtonMode.swift in Sources */,
47F4F21523A6F06F0022FD56 /* AvailableMapsDataSource.swift in Sources */,
99012852244732DB00C72B10 /* BottomTabBarBuilder.swift in Sources */,
99012847243F0D6900C72B10 /* UIViewController+alternative.swift in Sources */,
995739062355CAC40019AEE7 /* ImageViewCrossDisolve.swift in Sources */,
ED83880F2D54DEB3002A0536 /* UIImage+FilledWithColor.swift in Sources */,
@@ -4616,6 +4637,7 @@
47A13CAD24BE9AA500027D4F /* DatePickerViewRenderer.swift in Sources */,
ED2E328E2D10500900807A08 /* TrackRecordingButtonArea.swift in Sources */,
F6E2FE7C1E097BA00083EBEC /* MWMPlacePageOpeningHoursCell.mm in Sources */,
27BDA48C2E43670300C478B8 /* MapZoomButton.swift in Sources */,
340E1EFB1E2F614400CE49BF /* Storyboard.swift in Sources */,
34E776331F15FAC2003040B3 /* MWMPlacePageManagerHelper.mm in Sources */,
462452E92BD052C0004C85E1 /* MWMEditorSegmentedTableViewCell.mm in Sources */,
@@ -4647,6 +4669,7 @@
F6E2FE821E097BA00083EBEC /* MWMPlacePageOpeningHoursDayView.m in Sources */,
F6E2FD6B1E097BA00083EBEC /* MWMMapDownloaderSubplaceTableViewCell.m in Sources */,
CDCA27842245090900167D87 /* ListenerContainer.swift in Sources */,
27E5CAAF2E4B6CBC00FA3597 /* Controls.h in Sources */,
27AF18582E1DB63A00CD41E2 /* Appearance.swift in Sources */,
47E3C7252111E41B008B3B27 /* DimmedModalPresentationController.swift in Sources */,
3472B5CB200F43EF00DC6CD5 /* BackgroundFetchScheduler.swift in Sources */,
@@ -4725,12 +4748,12 @@
270C9C282E16AB6F00ABA688 /* Profile.swift in Sources */,
ED9857082C4ED02D00694F6C /* MailComposer.swift in Sources */,
99F8B4C623B644A6009FF0B4 /* MapStyleSheet.swift in Sources */,
99012851244732DB00C72B10 /* BottomTabBarViewController.swift in Sources */,
993DF10623F6BDB100AC231A /* UIColor+rgba.swift in Sources */,
EDC3573B2B7B5029001AE9CA /* CALayer+SetCorner.swift in Sources */,
ED914AB22D35063A00973C45 /* TextColorStyleSheet.swift in Sources */,
47E3C7332111F4D8008B3B27 /* CoverVerticalDismissalAnimator.swift in Sources */,
471AB99423ABA3BD00F56D49 /* SearchMapsDataSource.swift in Sources */,
27BDA4A22E436D1900C478B8 /* MainButtonType.swift in Sources */,
47CA68F1250B54AF00671019 /* BookmarksListCell.swift in Sources */,
471A7BC02481C82500A0D4C1 /* BookmarkTitleCell.swift in Sources */,
47F67D1521CAB21B0069754E /* MWMImageCoder.m in Sources */,
@@ -4763,7 +4786,6 @@
471A7BBE2481A3D000A0D4C1 /* EditBookmarkViewController.swift in Sources */,
993DF0C923F6BD0600AC231A /* ElevationDetailsBuilder.swift in Sources */,
674A7E301C0DB10B003D48E1 /* MWMMapWidgets.mm in Sources */,
27768FE02E201BE60086784A /* LeftButtonType.swift in Sources */,
34AB66291FC5AA330078E451 /* RouteManagerViewController.swift in Sources */,
3404754D1E081A4600C92850 /* MWMKeyboard.m in Sources */,
993DF10C23F6BDB100AC231A /* MWMTableViewCellRenderer.swift in Sources */,
@@ -4773,11 +4795,12 @@
47E3C7312111F4C2008B3B27 /* CoverVerticalPresentationAnimator.swift in Sources */,
99E2B0122368A8C700FFABC5 /* MWMCategory+PlacesCountTitle.swift in Sources */,
F6D67CDC2062B9C00032FD38 /* BCCreateCategoryAlert.swift in Sources */,
27E5CAB12E4B6D0300FA3597 /* Controls.mm in Sources */,
F6E2FE2B1E097BA00083EBEC /* MWMStreetEditorEditTableViewCell.m in Sources */,
34AB66891FC5AA330078E451 /* NavigationControlView.swift in Sources */,
27BDA48A2E4366F400C478B8 /* MainButton.swift in Sources */,
479EE94A2292FB03009DEBA6 /* ActivityIndicator.swift in Sources */,
27697F872E255B8500FBD913 /* EmbeddedSafariViewContent.swift in Sources */,
ED3EAC202B03C88100220A4A /* BottomTabBarButton.swift in Sources */,
47B9065321C7FA400079C85E /* MWMImageCache.m in Sources */,
F6FEA82E1C58F108007223CC /* MWMButton.m in Sources */,
34B924431DC8A29C0008D971 /* MWMMailViewController.m in Sources */,
@@ -4807,6 +4830,7 @@
F6A2184A1CA3F26800BE2CC6 /* MWMEditorViralActivityItem.mm in Sources */,
993DF10923F6BDB100AC231A /* IFonts.swift in Sources */,
47699A0821F08E37009E6585 /* NSDate+TimeDistance.m in Sources */,
27BDA4902E436A1B00C478B8 /* MapZoomButtonKind.swift in Sources */,
34845DB31E165E24003D55B9 /* SearchNoResultsViewController.swift in Sources */,
47E3C72B2111E62A008B3B27 /* FadeOutAnimatedTransitioning.swift in Sources */,
471A7BC4248471BE00A0D4C1 /* BookmarkUIUtils.swift in Sources */,

View File

@@ -1,52 +0,0 @@
extension Settings {
/// The type of the left bottom bar button
enum LeftButtonType: String, Codable, CaseIterable, Identifiable {
case hidden = "Hidden"
case addPlace = "AddPlace"
case recordTrack = "RecordTrack"
case settings = "Settings"
case help = "Help"
// MARK: Properties
/// The id
var id: Self { self }
/// The description text
var description: String {
switch self {
case .hidden:
return String(localized: "disabled")
case .addPlace:
return String(localized: "placepage_add_place_button")
case .recordTrack:
return String(localized: "start_track_recording")
case .settings:
return String(localized: "settings")
case .help:
return String(localized: "help")
}
}
/// The image
var image: UIImage {
let configuration = UIImage.SymbolConfiguration(pointSize: 24, weight: .semibold)
switch self {
case .addPlace:
return UIImage(systemName: "plus", withConfiguration: configuration)!
case .recordTrack:
return UIImage(named: "track", in: nil, with: configuration)!
case .settings:
return UIImage(systemName: "gearshape.fill", withConfiguration: UIImage.SymbolConfiguration(pointSize: 22, weight: .semibold))!
case .help:
return UIImage(systemName: "info.circle", withConfiguration: configuration)!
default:
return UIImage()
}
}
}
}

View File

@@ -14,7 +14,7 @@ import AVFoundation
/// Key for storing the type of action used for the bottom left main interface button in the user defaults
static private let userDefaultsKeyLeftButtonType = "LeftButtonType"
static private let userDefaultsKeyLeftMainButtonKind = "LeftMainButtonKind"
/// Key for storing the map appearance in the user defaults
@@ -52,16 +52,16 @@ import AVFoundation
/// The type of action used for the bottom left main interface button
static var leftButtonType: LeftButtonType {
static var leftMainButtonKind: MainButton.Kind {
get {
if let leftButtonTypeRawValue = UserDefaults.standard.string(forKey: userDefaultsKeyLeftButtonType), let leftButtonType = LeftButtonType(rawValue: leftButtonTypeRawValue) {
return leftButtonType
if let leftMainButtonKindRawValue = UserDefaults.standard.string(forKey: userDefaultsKeyLeftMainButtonKind), let leftMainButtonKind = MainButton.Kind(rawValue: leftMainButtonKindRawValue) {
return leftMainButtonKind
}
return .help
}
set {
UserDefaults.standard.set(newValue.rawValue, forKey: userDefaultsKeyLeftButtonType)
UserDefaults.standard.set(newValue.rawValue, forKey: userDefaultsKeyLeftMainButtonKind)
}
}

View File

@@ -16,10 +16,6 @@ final class TabBarArea: AvailableArea {
let directions = ov.tabBarAreaAffectDirections
addConstraints(otherView: ov, directions: directions)
}
override func notifyObserver() {
BottomTabBarViewController.updateAvailableArea(areaFrame)
}
}
extension UIView {

View File

@@ -1,6 +1,8 @@
import UIKit
class BottomTabBarButton: MWMButton {
let kExtendedTabBarTappableMargin: CGFloat = -15
@objc override func applyTheme() {
if styleName.isEmpty {
setStyle(.bottomTabBarButton)

View File

@@ -78,17 +78,17 @@ extension BottomMenuPresenter {
case .layers:
return 1
case .items:
let leftButtonType = Settings.leftButtonType
let leftMainButtonKind = Settings.leftMainButtonKind
menuCells = CellType.allCases.filter { cell in
if cell == .donate {
return false
} else if leftButtonType == .addPlace, cell == .addPlace {
} else if leftMainButtonKind == .addPlace, cell == .addPlace {
return false
} else if leftButtonType == .recordTrack, cell == .recordTrack {
} else if leftMainButtonKind == .recordTrack, cell == .recordTrack {
return false
} else if leftButtonType == .help, cell == .help {
} else if leftMainButtonKind == .help, cell == .help {
return false
} else if leftButtonType == .settings, cell == .settings {
} else if leftMainButtonKind == .settings, cell == .settings {
return false
}

View File

@@ -1,14 +0,0 @@
@objc class BottomTabBarBuilder: NSObject {
@objc static func build(mapViewController: MapViewController, controlsManager: MWMMapViewControlsManager) -> BottomTabBarViewController {
let viewController = BottomTabBarViewController(nibName: nil, bundle: nil)
let interactor = BottomTabBarInteractor(viewController: viewController,
mapViewController: mapViewController,
controlsManager: controlsManager)
let presenter = BottomTabBarPresenter(interactor: interactor)
interactor.presenter = presenter
viewController.presenter = presenter
return viewController
}
}

View File

@@ -1,75 +0,0 @@
protocol BottomTabBarInteractorProtocol: AnyObject {
func openSearch()
func openLeftButton()
func openBookmarks()
func openMenu()
}
class BottomTabBarInteractor {
weak var presenter: BottomTabBarPresenterProtocol?
private weak var viewController: UIViewController?
private weak var mapViewController: MapViewController?
private weak var controlsManager: MWMMapViewControlsManager?
private let searchManager: SearchOnMapManager
init(viewController: UIViewController, mapViewController: MapViewController, controlsManager: MWMMapViewControlsManager) {
self.viewController = viewController
self.mapViewController = mapViewController
self.controlsManager = controlsManager
self.searchManager = mapViewController.searchManager
}
}
extension BottomTabBarInteractor: BottomTabBarInteractorProtocol {
func openSearch() {
searchManager.isSearching ? searchManager.close() : searchManager.startSearching(isRouting: false)
}
func openLeftButton() {
switch Settings.leftButtonType {
case .addPlace:
if let delegate = controlsManager as? BottomMenuDelegate {
delegate.addPlace()
}
case .settings:
mapViewController?.openSettings()
case .recordTrack:
let mapViewController = MapViewController.shared()!
let trackRecorder: TrackRecordingManager = .shared
switch trackRecorder.recordingState {
case .active:
mapViewController.showTrackRecordingPlacePage()
case .inactive:
trackRecorder.start { result in
switch result {
case .success:
mapViewController.showTrackRecordingPlacePage()
case .failure:
break
}
}
}
default:
mapViewController?.openAbout()
}
}
func openBookmarks() {
mapViewController?.bookmarksCoordinator.open()
}
func openMenu() {
guard let state = controlsManager?.menuState else {
fatalError("ERROR: Failed to retrieve the current MapViewControlsManager's state.")
}
switch state {
case .inactive: controlsManager?.menuState = .active
case .active: controlsManager?.menuState = .inactive
case .hidden:
// When the current controls manager's state is hidden, accidental taps on the menu button during the hiding animation should be skipped.
break;
case .layers: fallthrough
@unknown default: fatalError("ERROR: Unexpected MapViewControlsManager's state: \(state)")
}
}
}

View File

@@ -1,37 +0,0 @@
protocol BottomTabBarPresenterProtocol: AnyObject {
func configure()
func onLeftButtonPressed()
func onSearchButtonPressed()
func onBookmarksButtonPressed()
func onMenuButtonPressed()
}
class BottomTabBarPresenter: NSObject {
private let interactor: BottomTabBarInteractorProtocol
init(interactor: BottomTabBarInteractorProtocol) {
self.interactor = interactor
}
}
extension BottomTabBarPresenter: BottomTabBarPresenterProtocol {
func configure() {
}
func onLeftButtonPressed() {
interactor.openLeftButton()
}
func onSearchButtonPressed() {
interactor.openSearch()
}
func onBookmarksButtonPressed() {
interactor.openBookmarks()
}
func onMenuButtonPressed() {
interactor.openMenu()
}
}

View File

@@ -1,28 +0,0 @@
let kExtendedTabBarTappableMargin: CGFloat = -15
final class BottomTabBarView: SolidTouchView {
@IBOutlet var mainButtonsView: ExtendedBottomTabBarContainerView!
override var placePageAreaAffectDirections: MWMAvailableAreaAffectDirections {
return alternative(iPhone: [], iPad: [.bottom])
}
override var widgetsAreaAffectDirections: MWMAvailableAreaAffectDirections {
return [.bottom]
}
override var sideButtonsAreaAffectDirections: MWMAvailableAreaAffectDirections {
return [.bottom]
}
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
return bounds.insetBy(dx: kExtendedTabBarTappableMargin, dy: kExtendedTabBarTappableMargin).contains(point)
}
}
final class ExtendedBottomTabBarContainerView: UIView {
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
return bounds.insetBy(dx: kExtendedTabBarTappableMargin, dy: kExtendedTabBarTappableMargin).contains(point)
}
}

View File

@@ -1,131 +0,0 @@
class BottomTabBarViewController: UIViewController {
var presenter: BottomTabBarPresenterProtocol!
@IBOutlet var leftButton: MWMButton?
@IBOutlet var searchButton: MWMButton?
@IBOutlet var searchConstraintWithLeftButton: NSLayoutConstraint?
@IBOutlet var searchConstraintWithoutLeftButton: NSLayoutConstraint?
@IBOutlet var bookmarksButton: MWMButton?
@IBOutlet var bookmarksConstraintWithLeftButton: NSLayoutConstraint?
@IBOutlet var bookmarksConstraintWithoutLeftButton: NSLayoutConstraint?
@IBOutlet var moreButton: MWMButton?
@IBOutlet var downloadBadge: UIView?
private var avaliableArea = CGRect.zero
@objc var isHidden: Bool = false {
didSet {
updateFrame(animated: true)
}
}
@objc var isApplicationBadgeHidden: Bool = true {
didSet {
updateBadge()
}
}
var tabBarView: BottomTabBarView {
return view as! BottomTabBarView
}
@objc static var controller: BottomTabBarViewController? {
return MWMMapViewControlsManager.manager()?.tabBarController
}
override func viewDidLoad() {
super.viewDidLoad()
presenter.configure()
NotificationCenter.default.addObserver(forName: UserDefaults.didChangeNotification, object: nil, queue: nil) { _ in
DispatchQueue.main.async {
self.updateLeftButton()
}
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
leftButton?.imageView?.contentMode = .scaleAspectFit
updateBadge()
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
updateLeftButton()
}
static func updateAvailableArea(_ frame: CGRect) {
BottomTabBarViewController.controller?.updateAvailableArea(frame)
}
@IBAction func onSearchButtonPressed(_ sender: Any) {
presenter.onSearchButtonPressed()
}
@IBAction func onLeftButtonPressed(_ sender: Any) {
presenter.onLeftButtonPressed()
}
@IBAction func onBookmarksButtonPressed(_ sender: Any) {
presenter.onBookmarksButtonPressed()
}
@IBAction func onMenuButtonPressed(_ sender: Any) {
presenter.onMenuButtonPressed()
}
private func updateAvailableArea(_ frame:CGRect) {
avaliableArea = frame
updateFrame(animated: false)
self.view.layoutIfNeeded()
}
private func updateFrame(animated: Bool) {
if avaliableArea == .zero {
return
}
let newFrame = CGRect(x: avaliableArea.minX,
y: isHidden ? avaliableArea.minY + avaliableArea.height : avaliableArea.minY,
width: avaliableArea.width,
height: avaliableArea.height)
let alpha:CGFloat = isHidden ? 0 : 1
if animated {
UIView.animate(withDuration: kDefaultAnimationDuration,
delay: 0,
options: [.beginFromCurrentState],
animations: {
self.view.frame = newFrame
self.view.alpha = alpha
}, completion: nil)
} else {
self.view.frame = newFrame
self.view.alpha = alpha
}
}
private func updateLeftButton() {
let leftButtonType = Settings.leftButtonType
if leftButtonType == .hidden {
leftButton?.isHidden = true
if let searchConstraintWithLeftButton, let searchConstraintWithoutLeftButton, let bookmarksConstraintWithLeftButton, let bookmarksConstraintWithoutLeftButton {
NSLayoutConstraint.activate([searchConstraintWithoutLeftButton, bookmarksConstraintWithoutLeftButton])
NSLayoutConstraint.deactivate([searchConstraintWithLeftButton, bookmarksConstraintWithLeftButton])
}
} else {
leftButton?.isHidden = false
leftButton?.setTitle(nil, for: .normal)
leftButton?.setImage(leftButtonType.image, for: .normal)
leftButton?.accessibilityLabel = leftButtonType.description;
if let searchConstraintWithLeftButton, let searchConstraintWithoutLeftButton, let bookmarksConstraintWithLeftButton, let bookmarksConstraintWithoutLeftButton {
NSLayoutConstraint.activate([searchConstraintWithLeftButton, bookmarksConstraintWithLeftButton])
NSLayoutConstraint.deactivate([searchConstraintWithoutLeftButton, bookmarksConstraintWithoutLeftButton])
}
}
}
private func updateBadge() {
downloadBadge?.isHidden = isApplicationBadgeHidden
}
}

View File

@@ -1,148 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="24128" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="24063"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="BottomTabBarViewController" customModule="CoMaps" customModuleProvider="target">
<connections>
<outlet property="bookmarksButton" destination="dgG-ki-3tB" id="md5-3T-9tb"/>
<outlet property="bookmarksConstraintWithLeftButton" destination="Jc7-nc-elY" id="gW7-8e-E6m"/>
<outlet property="bookmarksConstraintWithoutLeftButton" destination="NRb-vj-MFg" id="C3Z-Ia-D6i"/>
<outlet property="downloadBadge" destination="uDI-ZC-4wx" id="fAf-cy-Ozn"/>
<outlet property="leftButton" destination="dzf-7Z-N6a" id="LMZ-H7-ftQ"/>
<outlet property="moreButton" destination="svD-yi-GrZ" id="kjk-ZW-nZN"/>
<outlet property="searchButton" destination="No0-ld-JX3" id="m5F-UT-j94"/>
<outlet property="searchConstraintWithLeftButton" destination="tDb-w1-ueQ" id="WaI-Xb-1bu"/>
<outlet property="searchConstraintWithoutLeftButton" destination="cQg-jW-uSD" id="cMy-EC-G07"/>
<outlet property="view" destination="zuH-WU-hiP" id="eoa-4I-wKs"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="zuH-WU-hiP" customClass="BottomTabBarView" customModule="CoMaps" customModuleProvider="target" propertyAccessControl="none">
<rect key="frame" x="0.0" y="0.0" width="373" height="84"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<view opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="vum-s3-PHx" userLabel="MainButtons" customClass="ExtendedBottomTabBarContainerView" customModule="CoMaps" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="373" height="48"/>
<subviews>
<button opaque="NO" contentMode="scaleAspectFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="dzf-7Z-N6a" userLabel="LeftButton" customClass="BottomTabBarButton" customModule="CoMaps" customModuleProvider="target">
<rect key="frame" x="22.5" y="0.0" width="48" height="48"/>
<accessibility key="accessibilityConfiguration" identifier="helpButton"/>
<constraints>
<constraint firstAttribute="width" secondItem="dzf-7Z-N6a" secondAttribute="height" id="qNJ-0K-sK0"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="30"/>
<inset key="imageEdgeInsets" minX="9" minY="9" maxX="9" maxY="9"/>
<state key="normal" image="info.circle" catalog="system"/>
<connections>
<action selector="onLeftButtonPressed:" destination="-1" eventType="touchUpInside" id="1gx-P2-sRJ"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="249" horizontalCompressionResistancePriority="751" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="No0-ld-JX3" userLabel="Search" customClass="BottomTabBarButton" customModule="CoMaps" customModuleProvider="target">
<rect key="frame" x="116" y="0.0" width="48" height="48"/>
<accessibility key="accessibilityConfiguration" identifier="searchButton"/>
<constraints>
<constraint firstAttribute="width" secondItem="No0-ld-JX3" secondAttribute="height" id="2bW-fc-Hsh"/>
</constraints>
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
<state key="normal" image="ic_menu_search"/>
<connections>
<action selector="onSearchButtonPressed:" destination="-1" eventType="touchUpInside" id="0D5-RB-HBQ"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleAspectFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="dgG-ki-3tB" userLabel="Bookmarks" customClass="BottomTabBarButton" customModule="CoMaps" customModuleProvider="target">
<rect key="frame" x="209" y="0.0" width="48" height="48"/>
<accessibility key="accessibilityConfiguration" identifier="bookmarksButton"/>
<constraints>
<constraint firstAttribute="width" secondItem="dgG-ki-3tB" secondAttribute="height" id="o3b-it-lrV"/>
</constraints>
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
<state key="normal" image="ic_menu_bookmark_list"/>
<connections>
<action selector="onBookmarksButtonPressed:" destination="-1" eventType="touchUpInside" id="9Z1-eg-xth"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleAspectFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="svD-yi-GrZ" userLabel="Menu" customClass="BottomTabBarButton" customModule="CoMaps" customModuleProvider="target">
<rect key="frame" x="302.5" y="0.0" width="48" height="48"/>
<accessibility key="accessibilityConfiguration" identifier="menuButton"/>
<constraints>
<constraint firstAttribute="width" secondItem="svD-yi-GrZ" secondAttribute="height" id="gmG-3a-Mqe"/>
</constraints>
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
<state key="normal" image="ic_menu"/>
<connections>
<action selector="onMenuButtonPressed:" destination="-1" eventType="touchUpInside" id="rzb-y4-nR1"/>
</connections>
</button>
<view userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="uDI-ZC-4wx" userLabel="DownloadBadge">
<rect key="frame" x="329.5" y="11" width="10" height="10"/>
<color key="backgroundColor" red="1" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<accessibility key="accessibilityConfiguration">
<accessibilityTraits key="traits" notEnabled="YES"/>
</accessibility>
<constraints>
<constraint firstAttribute="width" constant="10" id="tEP-Xi-qnU"/>
<constraint firstAttribute="height" constant="10" id="wNg-5Z-7AO"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="styleName" value="Badge"/>
</userDefinedRuntimeAttributes>
</view>
</subviews>
<accessibility key="accessibilityConfiguration" identifier="MainButtons"/>
<constraints>
<constraint firstAttribute="height" constant="48" id="69A-eu-uLp"/>
<constraint firstItem="No0-ld-JX3" firstAttribute="centerY" secondItem="vum-s3-PHx" secondAttribute="centerY" id="8nL-zT-Y7b"/>
<constraint firstItem="No0-ld-JX3" firstAttribute="height" secondItem="vum-s3-PHx" secondAttribute="height" id="9eR-I7-7at"/>
<constraint firstItem="svD-yi-GrZ" firstAttribute="height" secondItem="vum-s3-PHx" secondAttribute="height" id="Fde-um-JL6"/>
<constraint firstItem="dgG-ki-3tB" firstAttribute="centerX" secondItem="vum-s3-PHx" secondAttribute="centerX" multiplier="1.25" id="Jc7-nc-elY"/>
<constraint firstItem="dgG-ki-3tB" firstAttribute="centerY" secondItem="vum-s3-PHx" secondAttribute="centerY" id="JjT-sc-hIY"/>
<constraint firstItem="dgG-ki-3tB" firstAttribute="centerX" secondItem="vum-s3-PHx" secondAttribute="centerX" priority="900" id="NRb-vj-MFg"/>
<constraint firstItem="svD-yi-GrZ" firstAttribute="centerX" secondItem="vum-s3-PHx" secondAttribute="centerX" multiplier="1.75" id="Q0b-gd-HwS"/>
<constraint firstItem="dgG-ki-3tB" firstAttribute="height" secondItem="vum-s3-PHx" secondAttribute="height" id="Rs8-Hl-CAc"/>
<constraint firstItem="uDI-ZC-4wx" firstAttribute="centerX" secondItem="svD-yi-GrZ" secondAttribute="centerX" constant="8" id="XNb-Ba-Hn7"/>
<constraint firstItem="dzf-7Z-N6a" firstAttribute="centerY" secondItem="vum-s3-PHx" secondAttribute="centerY" id="Zug-zY-KIX"/>
<constraint firstItem="No0-ld-JX3" firstAttribute="centerX" secondItem="vum-s3-PHx" secondAttribute="centerX" multiplier="0.25" priority="900" id="cQg-jW-uSD"/>
<constraint firstItem="svD-yi-GrZ" firstAttribute="centerY" secondItem="vum-s3-PHx" secondAttribute="centerY" id="sja-hO-YY3"/>
<constraint firstItem="No0-ld-JX3" firstAttribute="centerX" secondItem="vum-s3-PHx" secondAttribute="centerX" multiplier="0.75" id="tDb-w1-ueQ"/>
<constraint firstItem="dzf-7Z-N6a" firstAttribute="centerX" secondItem="vum-s3-PHx" secondAttribute="centerX" multiplier="0.25" id="u3G-gY-98J"/>
<constraint firstItem="dzf-7Z-N6a" firstAttribute="height" secondItem="vum-s3-PHx" secondAttribute="height" id="yTg-8g-H1p"/>
<constraint firstItem="uDI-ZC-4wx" firstAttribute="centerY" secondItem="svD-yi-GrZ" secondAttribute="centerY" constant="-8" id="yq3-ui-IaL"/>
</constraints>
<variation key="default">
<mask key="constraints">
<exclude reference="cQg-jW-uSD"/>
<exclude reference="NRb-vj-MFg"/>
</mask>
</variation>
</view>
</subviews>
<viewLayoutGuide key="safeArea" id="aaw-Hz-zma"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="vum-s3-PHx" firstAttribute="top" secondItem="zuH-WU-hiP" secondAttribute="top" id="PQS-ro-25e"/>
<constraint firstItem="vum-s3-PHx" firstAttribute="leading" secondItem="zuH-WU-hiP" secondAttribute="leading" id="kza-JN-Dul"/>
<constraint firstAttribute="trailing" secondItem="vum-s3-PHx" secondAttribute="trailing" id="sM6-P2-rN9"/>
</constraints>
<nil key="simulatedStatusBarMetrics"/>
<nil key="simulatedTopBarMetrics"/>
<nil key="simulatedBottomBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<connections>
<outlet property="mainButtonsView" destination="vum-s3-PHx" id="fBi-DA-orA"/>
</connections>
<point key="canvasLocation" x="72" y="254"/>
</view>
</objects>
<resources>
<image name="ic_menu" width="48" height="48"/>
<image name="ic_menu_bookmark_list" width="48" height="48"/>
<image name="ic_menu_search" width="48" height="48"/>
<image name="info.circle" catalog="system" width="128" height="123"/>
</resources>
</document>

View File

@@ -0,0 +1,144 @@
import SwiftUI
/// View for the interface button
struct ControlsView: View {
// MARK: Properties
/// The dismiss action of the environment
@Environment(\.verticalSizeClass) private var verticalSizeClass
@State private var hasZoomButtons: Bool = true
@State private var leftMainButtonKind: MainButton.Kind = .hidden
@State private var hasMainButtons: Bool = true
/// The publisher to know when settings changed
private let settingsPublisher = NotificationCenter.default.publisher(for: UserDefaults.didChangeNotification)
/// The publisher to know when settings changed
private let changeVisibilityMainButtonsPublisher = NotificationCenter.default.publisher(for: Controls.changeVisibilityMainButtonsNotificationName)
/// The actual view
var body: some View {
ZStack {
if verticalSizeClass != .compact {
VStack(alignment: .trailing) {
HStack {
MapLayerButton()
Spacer(minLength: 0)
VStack {
MapTrackRecordingButton()
}
}
Spacer(minLength: 0)
VStack(spacing: 72) {
if hasZoomButtons {
VStack(spacing: 36) {
MapZoomButton(kind: .in)
MapZoomButton(kind: .out)
}
}
MapPositionButton()
}
Spacer(minLength: 0)
if hasMainButtons {
HStack {
if leftMainButtonKind != .hidden {
MainButton(kind: leftMainButtonKind)
Spacer(minLength: 0)
}
MainButton(kind: .search)
Spacer(minLength: 0)
MainButton(kind: .bookmarks)
Spacer(minLength: 0)
MainButton(kind: .more)
}
.frame(maxWidth: .infinity)
}
}
.padding([.leading, .trailing], 10)
} else {
HStack {
VStack(alignment: .leading) {
MapLayerButton()
Spacer(minLength: 0)
if hasMainButtons {
HStack(spacing: 32) {
if leftMainButtonKind != .hidden {
MainButton(kind: leftMainButtonKind)
}
MainButton(kind: .search)
MainButton(kind: .bookmarks)
MainButton(kind: .more)
}
}
}
Spacer(minLength: 0)
VStack(alignment: .trailing) {
VStack {
MapTrackRecordingButton()
}
Spacer(minLength: 0)
if hasZoomButtons {
VStack(spacing: 36) {
MapZoomButton(kind: .in)
MapZoomButton(kind: .out)
}
}
Spacer(minLength: 0)
MapPositionButton()
}
}
}
}
.padding(.top, 14)
.padding(.bottom, 2)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.onAppear {
hasZoomButtons = Settings.hasZoomButtons
leftMainButtonKind = Settings.leftMainButtonKind
hasMainButtons = Controls.shared().hasMainButtons()
}
.onReceive(settingsPublisher) { _ in
hasZoomButtons = Settings.hasZoomButtons
leftMainButtonKind = Settings.leftMainButtonKind
}
.onReceive(changeVisibilityMainButtonsPublisher) { _ in
hasMainButtons = Controls.shared().hasMainButtons()
}
}
}

View File

@@ -0,0 +1,39 @@
import SwiftUI
struct FloatingButtonStyle: ButtonStyle {
/// If the button is round
var isRound: Bool = true
func makeBody(configuration: Configuration) -> some View {
configuration.label
.labelStyle(.iconOnly)
.padding(10)
.aspectRatio(1, contentMode: .fill)
.background {
if isRound {
Circle()
.stroke(Color.white.opacity(0.7), lineWidth: 1)
.background {
Color.white.opacity(configuration.isPressed ? 0.7 : 0.8)
.clipShape(Circle())
}
.aspectRatio(1, contentMode: .fill)
.shadow(radius: 2)
} else {
RoundedRectangle(cornerRadius: 8)
.stroke(Color.white.opacity(0.7), lineWidth: 1)
.background {
Color.white.opacity(configuration.isPressed ? 0.7 : 0.8)
.clipShape(RoundedRectangle(cornerRadius: 8))
}
.aspectRatio(1, contentMode: .fill)
.shadow(radius: 3)
}
}
.font(.title2)
.foregroundStyle(configuration.role == .destructive ? Color(.BaseColors.red) : Color.secondary)
.scaleEffect(configuration.isPressed ? (isRound ? 0.96 : 0.98) : 1)
.animation(.smooth, value: configuration.isPressed)
}
}

View File

@@ -0,0 +1,79 @@
import SwiftUI
/// View for a main button
struct MainButton: View {
// MARK: Properties
/// The kind
var kind: MainButton.Kind
/// The actual view
var body: some View {
if kind != .hidden {
Button {
if kind == .addPlace {
if let controlsManager = MWMMapViewControlsManager.manager() as? BottomMenuDelegate {
controlsManager.addPlace()
}
} else if kind == .recordTrack {
let trackRecorder: TrackRecordingManager = .shared
switch trackRecorder.recordingState {
case .active:
MapViewController.shared()?.showTrackRecordingPlacePage()
case .inactive:
trackRecorder.start { result in
switch result {
case .success:
MapViewController.shared()?.showTrackRecordingPlacePage()
case .failure:
break
}
}
}
} else if kind == .search {
if let searchManager = MapViewController.shared()?.searchManager {
if searchManager.isSearching {
searchManager.close()
} else {
searchManager.startSearching(isRouting: false)
}
}
} else if kind == .bookmarks {
MapViewController.shared()?.bookmarksCoordinator.open()
} else if kind == .settings {
MapViewController.shared()?.openSettings()
} else if kind == .help {
MapViewController.shared()?.openAbout()
} else if kind == .more {
if let controlsManager = MWMMapViewControlsManager.manager() {
if controlsManager.menuState == .active {
controlsManager.menuState = .inactive
} else if controlsManager.menuState == .inactive {
controlsManager.menuState = .active
}
}
} else if kind == .layers {
if MapOverlayManager.trafficEnabled() || MapOverlayManager.transitEnabled() || MapOverlayManager.isoLinesEnabled() || MapOverlayManager.outdoorEnabled() {
MapOverlayManager.setTrafficEnabled(false)
MapOverlayManager.setTransitEnabled(false)
MapOverlayManager.setIsoLinesEnabled(false)
MapOverlayManager.setOutdoorEnabled(false)
} else {
MWMMapViewControlsManager.manager()?.menuState = .layers
}
}
} label: {
Label {
Text(kind.description)
} icon: {
if kind != .layers, let image = kind.image {
image
}
}
}
.buttonStyle(FloatingButtonStyle(isRound: false))
.frame(minWidth: 44, idealWidth: 44, minHeight: 44, idealHeight: 44)
}
}
}

View File

@@ -0,0 +1,81 @@
import SwiftUI
extension MainButton {
/// The type of the left bottom bar button
enum Kind: String, Codable, CaseIterable, Identifiable {
case hidden = "Hidden"
case addPlace = "AddPlace"
case recordTrack = "RecordTrack"
case search = "Search"
case bookmarks = "Bookmarks"
case settings = "Settings"
case help = "Help"
case more = "More"
case layers = "Layers"
// MARK: Properties
/// The configurable cases
static var configurableCases: [MainButton.Kind] {
allCases.filter { kind in
return kind != .more && kind != .bookmarks && kind != .search
}
}
/// The id
var id: Self { self }
/// The description text
var description: String {
switch self {
case .hidden:
return String(localized: "disabled")
case .addPlace:
return String(localized: "placepage_add_place_button")
case .recordTrack:
return String(localized: "start_track_recording")
case .search:
return String(localized: "search")
case .bookmarks:
return String(localized: "bookmarks")
case .settings:
return String(localized: "settings")
case .help:
return String(localized: "help")
case .more:
return String(localized: "placepage_more_button")
case .layers:
return String(localized: "layers_title")
}
}
/// The image
var image: Image? {
switch self {
case .addPlace:
return Image(systemName: "plus")
case .recordTrack:
return Image(.MainButtons.LeftButton.recordTrack)
case .search:
return Image(systemName: "magnifyingglass")
case .bookmarks:
return Image(systemName: "list.star")
case .settings:
return Image(systemName: "gearshape.fill")
case .help:
return Image(systemName: "info.circle")
case .layers:
return Image(systemName: "square.stack.3d.up.fill")
case .more:
return Image(systemName: "ellipsis.circle")
default:
return nil
}
}
}
}

View File

@@ -0,0 +1,27 @@
import SwiftUI
/// View for a map layer button
struct MapLayerButton: View {
// MARK: Properties
/// The actual view
var body: some View {
Group {
if Settings.leftMainButtonKind != .layers {
Button {
if MapOverlayManager.trafficEnabled() || MapOverlayManager.transitEnabled() || MapOverlayManager.isoLinesEnabled() || MapOverlayManager.outdoorEnabled() {
MapOverlayManager.setTrafficEnabled(false)
MapOverlayManager.setTransitEnabled(false)
MapOverlayManager.setIsoLinesEnabled(false)
MapOverlayManager.setOutdoorEnabled(false)
} else {
MWMMapViewControlsManager.manager()?.menuState = .layers
}
} label: {
Label("Show Layers", systemImage: "square.stack.3d.up.fill")
}
.buttonStyle(FloatingButtonStyle())
}
}
}
}

View File

@@ -0,0 +1,39 @@
import SwiftUI
/// View for a map position mode button
struct MapPositionButton: View {
// MARK: Properties
/// The mode
@State private var mode: MapPositionButton.Mode = .locate
/// The publisher to know when to stop showing the Safari view for the login form
private let switchPositionModePublisher = NotificationCenter.default.publisher(for: Controls.switchPositionModeNotificationName)
/// The actual view
var body: some View {
Button {
Controls.switchToNextPositionMode()
} label: {
Label {
Text(mode.description)
} icon: {
if mode == .following || mode == .followingAndRotated {
mode.image
.foregroundStyle(Color.BaseColors.blue)
} else {
mode.image
}
}
}
.buttonStyle(FloatingButtonStyle())
.onAppear {
mode = Controls.positionMode
}
.onReceive(switchPositionModePublisher) { _ in
mode = Controls.positionMode
}
}
}

View File

@@ -0,0 +1,48 @@
import SwiftUI
extension MapPositionButton {
/// The mode of the map position button
enum Mode: String, Codable, CaseIterable, Identifiable {
case locate = "Locate"
case locating = "Locating"
case following = "Following"
case followingAndRotated = "FollowingAndRotated"
// MARK: Properties
/// The id
var id: Self { self }
/// The description text
var description: String {
switch self {
case .locate:
return String(localized: "Find own location")
case .locating:
return String(localized: "Finding own location...")
case .following:
return String(localized: "Rotate map towards own direction")
case .followingAndRotated:
return String(localized: "Rotate map towards North")
}
}
/// The image
var image: Image {
switch self {
case .locate:
return Image(systemName: "location")
case .locating:
return Image(systemName: "progress.indicator")
case .following:
return Image(systemName: "location.fill")
case .followingAndRotated:
return Image(systemName: "location.north.line.fill")
}
}
}
}

View File

@@ -0,0 +1,45 @@
import SwiftUI
/// View for a map track recording button
struct MapTrackRecordingButton: View {
// MARK: Properties
/// The mode
@State private var isRecording: Bool = false
/// The publisher to know when to stop showing the Safari view for the login form
private let changeChangeTrackRecordingPublisher = NotificationCenter.default.publisher(for: Controls.changeChangeTrackRecordingNotificationName)
/// The actual view
var body: some View {
ZStack {
if isRecording {
Button(role: .destructive) {
if isRecording {
MapViewController.shared()?.showTrackRecordingPlacePage()
} else {
TrackRecordingManager.shared.start { result in
switch result {
case .success:
MapViewController.shared()?.showTrackRecordingPlacePage()
case .failure:
break
}
}
}
} label: {
Label("Show Track Recording", systemImage: "record.circle")
}
.buttonStyle(FloatingButtonStyle())
}
}
.onAppear {
isRecording = (TrackRecordingManager.shared.recordingState == .active)
}
.onReceive(changeChangeTrackRecordingPublisher) { _ in
isRecording = (TrackRecordingManager.shared.recordingState == .active)
}
}
}

View File

@@ -0,0 +1,28 @@
import SwiftUI
/// View for a map zoom button
struct MapZoomButton: View {
// MARK: Properties
/// The kind
var kind: MapZoomButton.Kind
/// The actual view
var body: some View {
Button {
if kind == .in {
Controls.zoomIn()
} else if kind == .out {
Controls.zoomOut()
}
} label: {
Label {
Text(kind.description)
} icon: {
kind.image
}
}
.buttonStyle(FloatingButtonStyle())
}
}

View File

@@ -0,0 +1,38 @@
import SwiftUI
extension MapZoomButton {
/// The type of the map zoom button
enum Kind: String, Codable, CaseIterable, Identifiable {
case `in` = "In"
case out = "Out"
// MARK: Properties
/// The id
var id: Self { self }
/// The description text
var description: String {
switch self {
case .in:
return String(localized: "zoom_in")
case .out:
return String(localized: "zoom_out")
}
}
/// The image
var image: Image {
switch self {
case .in:
return Image(systemName: "plus")
case .out:
return Image(systemName: "minus")
}
}
}
}

View File

@@ -17,7 +17,7 @@ struct SettingsView: View {
/// The selected left button type
@State private var selectedLeftButtonType: Settings.LeftButtonType = .help
@State private var selectedLeftMainButtonKind: MainButton.Kind = .help
/// If 3D buildings should be displayed
@@ -112,9 +112,9 @@ struct SettingsView: View {
Toggle("pref_zoom_title", isOn: $hasZoomButtons)
.tint(.accent)
Picker(selection: $selectedLeftButtonType) {
ForEach(Settings.LeftButtonType.allCases) { leftButtonType in
Text(leftButtonType.description)
Picker(selection: $selectedLeftMainButtonKind) {
ForEach(MainButton.Kind.configurableCases) { leftMainButtonKind in
Text(leftMainButtonKind.description)
}
} label: {
Text("pref_left_button_type")
@@ -291,7 +291,7 @@ struct SettingsView: View {
.onAppear {
selectedDistanceUnit = Settings.distanceUnit
hasZoomButtons = Settings.hasZoomButtons
selectedLeftButtonType = Settings.leftButtonType
selectedLeftMainButtonKind = Settings.leftMainButtonKind
has3dBuildings = Settings.has3dBuildings
hasAutomaticDownload = Settings.hasAutomaticDownload
hasIncreasedFontsize = Settings.hasIncreasedFontsize
@@ -311,8 +311,8 @@ struct SettingsView: View {
.onChange(of: hasZoomButtons) { changedHasZoomButtons in
Settings.hasZoomButtons = changedHasZoomButtons
}
.onChange(of: selectedLeftButtonType) { changedSelectedLeftButtonType in
Settings.leftButtonType = changedSelectedLeftButtonType
.onChange(of: selectedLeftMainButtonKind) { changedSelectedLeftMainButtonKind in
Settings.leftMainButtonKind = changedSelectedLeftMainButtonKind
}
.onChange(of: has3dBuildings) { changedHas3dBuildings in
Settings.has3dBuildings = changedHas3dBuildings

View File

@@ -1 +0,0 @@
Navigera Privat

View File

@@ -196,7 +196,7 @@ m2::PointF GetOffset(int offsetX, int offsetY)
bool IsSymbolRoadShield(ftypes::RoadShield const & shield)
{
return shield.m_type == ftypes::RoadShieldType::Highway_Hexagon_Green || shield.m_type == ftypes::RoadShieldType::Highway_Hexagon_Blue || shield.m_type == ftypes::RoadShieldType::Highway_Hexagon_Red || shield.m_type == ftypes::RoadShieldType::Highway_Hexagon_Turkey || shield.m_type == ftypes::RoadShieldType::US_Interstate || shield.m_type == ftypes::RoadShieldType::US_Highway || shield.m_type == ftypes::RoadShieldType::Italy_Autostrada || shield.m_type == ftypes::RoadShieldType::Hungary_Green || shield.m_type == ftypes::RoadShieldType::Hungary_Blue;
return shield.m_type == ftypes::RoadShieldType::Highway_Hexagon_Green || shield.m_type == ftypes::RoadShieldType::Highway_Hexagon_Blue || shield.m_type == ftypes::RoadShieldType::Highway_Hexagon_Red || shield.m_type == ftypes::RoadShieldType::Highway_Hexagon_Turkey || shield.m_type == ftypes::RoadShieldType::US_Interstate || shield.m_type == ftypes::RoadShieldType::US_Highway || shield.m_type == ftypes::RoadShieldType::Italy_Autostrada;
}
std::string GetRoadShieldSymbolName(ftypes::RoadShield const & shield, double fontScale)
@@ -217,10 +217,6 @@ std::string GetRoadShieldSymbolName(ftypes::RoadShield const & shield, double fo
result = shield.m_name.size() <= 2 ? "shield-us-hw-thin" : "shield-us-hw-wide";
else if (shield.m_type == ftypes::RoadShieldType::Italy_Autostrada)
result = "shield-it-a";
else if (shield.m_type == ftypes::RoadShieldType::Hungary_Green)
result = "shield-hungary-green";
else if (shield.m_type == ftypes::RoadShieldType::Hungary_Blue)
result = "shield-hungary-blue";
else
ASSERT(false, ("This shield type doesn't support symbols:", shield.m_type));
@@ -325,9 +321,7 @@ dp::Color GetRoadShieldTextColor(dp::Color const & baseColor, ftypes::RoadShield
{RoadShieldType::US_Interstate, kRoadShieldWhiteTextColor},
{RoadShieldType::US_Highway, kRoadShieldBlackTextColor},
{RoadShieldType::UK_Highway, kRoadShieldUKYellowTextColor},
{RoadShieldType::Italy_Autostrada, kRoadShieldWhiteTextColor},
{RoadShieldType::Hungary_Green, kRoadShieldWhiteTextColor},
{RoadShieldType::Hungary_Blue, kRoadShieldWhiteTextColor}};
{RoadShieldType::Italy_Autostrada, kRoadShieldWhiteTextColor}};
if (auto const * cl = kColors.Find(shield.m_type); cl)
return df::GetColorConstant(*cl);

View File

@@ -142,7 +142,7 @@ void Notes::CreateNote(ms::LatLon const & latLon, std::string const & text)
return;
}
std::lock_guard<std::mutex> g(m_dataAccessMutex);
std::lock_guard<std::mutex> g(m_mu);
auto const it = std::find_if(m_notes.begin(), m_notes.end(), [&latLon, &text](Note const & note)
{ return latLon.EqualDxDy(note.m_point, kTolerance) && text == note.m_note; });
// No need to add the same note. It works in case when saved note are not uploaded yet.
@@ -155,56 +155,61 @@ void Notes::CreateNote(ms::LatLon const & latLon, std::string const & text)
void Notes::Upload(osm::OsmOAuth const & auth)
{
std::unique_lock<std::mutex> uploadingNotesLock(m_uploadingNotesMutex, std::defer_lock);
if (!uploadingNotesLock.try_lock()) {
// Do not run more than one uploading task at a time.
LOG(LDEBUG, ("OSM notes upload is already running"));
return;
}
std::unique_lock<std::mutex> dataAccessLock(m_dataAccessMutex);
// Capture self to keep it from destruction until this thread is done.
auto const self = shared_from_this();
// Size of m_notes is decreased only in this method.
size_t size = m_notes.size();
osm::ServerApi06 api(auth);
while (size > 0)
auto const doUpload = [self, auth]()
{
try
{
dataAccessLock.unlock();
auto const id = api.CreateNote(m_notes.front().m_point, m_notes.front().m_note);
dataAccessLock.lock();
LOG(LINFO, ("A note uploaded with id", id));
}
catch (osm::ServerApi06::ServerApi06Exception const & e)
{
LOG(LERROR, ("Can't upload note.", e.Msg()));
// Don't attempt upload for other notes as they will likely suffer from the same error.
return;
}
std::unique_lock<std::mutex> ulock(self->m_mu);
// Size of m_notes is decreased only in this method.
auto & notes = self->m_notes;
size_t size = notes.size();
osm::ServerApi06 api(auth);
m_notes.pop_front();
--size;
++m_uploadedNotesCount;
Save(m_fileName, m_notes, m_uploadedNotesCount);
}
while (size > 0)
{
try
{
ulock.unlock();
auto const id = api.CreateNote(notes.front().m_point, notes.front().m_note);
ulock.lock();
LOG(LINFO, ("A note uploaded with id", id));
}
catch (osm::ServerApi06::ServerApi06Exception const & e)
{
LOG(LERROR, ("Can't upload note.", e.Msg()));
// We believe that next iterations will suffer from the same error.
return;
}
notes.pop_front();
--size;
++self->m_uploadedNotesCount;
Save(self->m_fileName, self->m_notes, self->m_uploadedNotesCount);
}
};
static auto future = std::async(std::launch::async, doUpload);
auto const status = future.wait_for(std::chrono::milliseconds(0));
if (status == std::future_status::ready)
future = std::async(std::launch::async, doUpload);
}
std::list<Note> Notes::GetNotes() const
{
std::lock_guard<std::mutex> g(m_dataAccessMutex);
std::lock_guard<std::mutex> g(m_mu);
return m_notes;
}
size_t Notes::NotUploadedNotesCount() const
{
std::lock_guard<std::mutex> g(m_dataAccessMutex);
std::lock_guard<std::mutex> g(m_mu);
return m_notes.size();
}
size_t Notes::UploadedNotesCount() const
{
std::lock_guard<std::mutex> g(m_dataAccessMutex);
std::lock_guard<std::mutex> g(m_mu);
return m_uploadedNotesCount;
}
} // namespace editor

View File

@@ -46,8 +46,7 @@ private:
explicit Notes(std::string const & fileName);
std::string const m_fileName;
mutable std::mutex m_dataAccessMutex;
mutable std::mutex m_uploadingNotesMutex;
mutable std::mutex m_mu;
// m_notes keeps the notes that have not been uploaded yet.
// Once a note has been uploaded, it is removed from m_notes.

View File

@@ -126,7 +126,7 @@ bool IsObsolete(editor::XMLFeature const & xml, FeatureID const & fid)
}
} // namespace
Editor::Editor() : m_configLoader(m_config), m_notes(editor::Notes::MakeNotes())
Editor::Editor() : m_configLoader(m_config), m_notes(editor::Notes::MakeNotes()), m_isUploadingNow(false)
{
SetDefaultStorage();
}
@@ -576,165 +576,217 @@ void Editor::UploadChanges(string const & oauthToken, ChangesetTags tags, Finish
if (m_notes->NotUploadedNotesCount())
m_notes->Upload(OsmOAuth::ServerAuth(oauthToken));
if (!HaveMapEditsToUpload(*m_features.Get()))
auto const features = m_features.Get();
if (!HaveMapEditsToUpload(*features))
{
LOG(LDEBUG, ("There are no local edits to upload."));
return;
}
std::unique_lock<std::mutex> uploadingEditsLock(m_uploadingEditsMutex, std::defer_lock);
if (!uploadingEditsLock.try_lock()) {
// Do not run more than one uploading task at a time.
LOG(LDEBUG, ("OSM edits upload is already running"));
return;
}
int uploadedFeaturesCount = 0, errorsCount = 0;
ChangesetWrapper changeset(oauthToken, std::move(tags));
auto const features = m_features.Get();
for (auto const & id : *features)
auto upload = [this](string secret, ChangesetTags tags, FinishUploadCallback callback)
{
if (!id.first.IsAlive())
continue;
int uploadedFeaturesCount = 0, errorsCount = 0;
ChangesetWrapper changeset(secret, std::move(tags));
auto const features = m_features.Get();
for (auto const & index : id.second)
for (auto const & id : *features)
{
FeatureTypeInfo const & fti = index.second;
// Do not process already uploaded features or those failed permanently.
if (!NeedsUpload(fti.m_uploadStatus))
if (!id.first.IsAlive())
continue;
// TODO(a): Use UploadInfo as part of FeatureTypeInfo.
UploadInfo uploadInfo = {fti.m_uploadAttemptTimestamp, fti.m_uploadStatus, fti.m_uploadError};
LOG(LDEBUG, ("Content of editJournal:\n", fti.m_object.GetJournal().JournalToString()));
// Don't use new editor for Legacy Objects
auto const & journalHistory = fti.m_object.GetJournal().GetJournalHistory();
bool useNewEditor =
journalHistory.empty() || journalHistory.front().journalEntryType != JournalEntryType::LegacyObject;
try
for (auto const & index : id.second)
{
if (useNewEditor)
FeatureTypeInfo const & fti = index.second;
// Do not process already uploaded features or those failed permanently.
if (!NeedsUpload(fti.m_uploadStatus))
continue;
// TODO(a): Use UploadInfo as part of FeatureTypeInfo.
UploadInfo uploadInfo = {fti.m_uploadAttemptTimestamp, fti.m_uploadStatus, fti.m_uploadError};
LOG(LDEBUG, ("Content of editJournal:\n", fti.m_object.GetJournal().JournalToString()));
// Don't use new editor for Legacy Objects
auto const & journalHistory = fti.m_object.GetJournal().GetJournalHistory();
bool useNewEditor =
journalHistory.empty() || journalHistory.front().journalEntryType != JournalEntryType::LegacyObject;
try
{
LOG(LDEBUG, ("New Editor used\n"));
switch (fti.m_status)
if (useNewEditor)
{
case FeatureStatus::Untouched: CHECK(false, ("It's impossible.")); continue;
case FeatureStatus::Obsolete: continue; // Obsolete features will be deleted by OSMers.
case FeatureStatus::Created: // fallthrough
case FeatureStatus::Modified:
LOG(LDEBUG, ("New Editor used\n"));
switch (fti.m_status)
{
case FeatureStatus::Untouched: CHECK(false, ("It's impossible.")); continue;
case FeatureStatus::Obsolete: continue; // Obsolete features will be deleted by OSMers.
case FeatureStatus::Created: // fallthrough
case FeatureStatus::Modified:
{
std::list<JournalEntry> const & journal = fti.m_object.GetJournal().GetJournal();
switch (fti.m_object.GetEditingLifecycle())
{
case EditingLifecycle::CREATED:
{
// Generate XMLFeature for new object
JournalEntry const & createEntry = journal.front();
ASSERT(createEntry.journalEntryType == JournalEntryType::ObjectCreated,
("First item should have type ObjectCreated"));
ObjCreateData const & objCreateData = std::get<ObjCreateData>(createEntry.data);
XMLFeature feature =
editor::TypeToXML(objCreateData.type, objCreateData.geomType, objCreateData.mercator);
// Check if place already exists
bool mergeSameLocation = false;
try
{
XMLFeature osmFeature = changeset.GetMatchingNodeFeatureFromOSM(objCreateData.mercator);
if (objCreateData.mercator == osmFeature.GetMercatorCenter())
{
changeset.AddChangesetTag("info:merged_same_location", "yes");
feature = osmFeature;
mergeSameLocation = true;
}
else
{
changeset.AddChangesetTag("info:feature_close_by", "yes");
}
}
catch (ChangesetWrapper::OsmObjectWasDeletedException const &)
{}
catch (ChangesetWrapper::EmptyFeatureException const &)
{}
// Add tags to XMLFeature
UpdateXMLFeatureTags(feature, journal);
// Upload XMLFeature to OSM
LOG(LDEBUG, ("CREATE Feature (newEditor)", feature));
changeset.AddChangesetTag("info:new_editor", "yes");
if (!mergeSameLocation)
changeset.Create(feature);
else
changeset.Modify(feature);
break;
}
case EditingLifecycle::MODIFIED:
{
// Load existing OSM object (Throws, see catch below)
XMLFeature feature = GetMatchingFeatureFromOSM(changeset, fti.m_object);
// Update tags of XMLFeature
UpdateXMLFeatureTags(feature, journal);
// Upload XMLFeature to OSM
LOG(LDEBUG, ("MODIFIED Feature (newEditor)", feature));
changeset.AddChangesetTag("info:new_editor", "yes");
changeset.Modify(feature);
break;
}
case EditingLifecycle::IN_SYNC:
{
CHECK(false, ("Object already IN_SYNC should not be here"));
continue;
}
}
break;
}
case FeatureStatus::Deleted:
auto const originalObjectPtr = GetOriginalMapObject(fti.m_object.GetID());
if (!originalObjectPtr)
{
LOG(LERROR, ("A feature with id", fti.m_object.GetID(), "cannot be loaded."));
GetPlatform().RunTask(Platform::Thread::Gui,
[this, fid = fti.m_object.GetID()]() { RemoveFeatureIfExists(fid); });
continue;
}
changeset.Delete(GetMatchingFeatureFromOSM(changeset, *originalObjectPtr));
break;
}
}
else // Use old editor
{
std::list<JournalEntry> const & journal = fti.m_object.GetJournal().GetJournal();
switch (fti.m_object.GetEditingLifecycle())
// Todo: Remove old editor after transition period
switch (fti.m_status)
{
case EditingLifecycle::CREATED:
case FeatureStatus::Untouched: CHECK(false, ("It's impossible.")); continue;
case FeatureStatus::Obsolete: continue; // Obsolete features will be deleted by OSMers.
case FeatureStatus::Created:
{
// Generate XMLFeature for new object
JournalEntry const & createEntry = journal.front();
ASSERT(createEntry.journalEntryType == JournalEntryType::ObjectCreated,
("First item should have type ObjectCreated"));
ObjCreateData const & objCreateData = std::get<ObjCreateData>(createEntry.data);
XMLFeature feature =
editor::TypeToXML(objCreateData.type, objCreateData.geomType, objCreateData.mercator);
XMLFeature feature = editor::ToXML(fti.m_object, true);
if (!fti.m_street.empty())
feature.SetTagValue(kAddrStreetTag, fti.m_street);
// Check if place already exists
bool mergeSameLocation = false;
ASSERT_EQUAL(feature.GetType(), XMLFeature::Type::Node,
("Linear and area features creation is not supported yet."));
try
{
XMLFeature osmFeature = changeset.GetMatchingNodeFeatureFromOSM(objCreateData.mercator);
if (objCreateData.mercator == osmFeature.GetMercatorCenter())
auto const center = fti.m_object.GetMercator();
// Throws, see catch below.
XMLFeature osmFeature = changeset.GetMatchingNodeFeatureFromOSM(center);
// If we are here, it means that object already exists at the given point.
// To avoid nodes duplication, merge and apply changes to it instead of creating a new one.
XMLFeature const osmFeatureCopy = osmFeature;
osmFeature.ApplyPatch(feature);
// Check to avoid uploading duplicates into OSM.
if (osmFeature == osmFeatureCopy)
{
changeset.AddChangesetTag("info:merged_same_location", "yes");
feature = osmFeature;
mergeSameLocation = true;
LOG(LWARNING, ("Local changes are equal to OSM, feature has not been uploaded.", osmFeatureCopy));
// Don't delete this local change right now for user to see it in profile.
// It will be automatically deleted by migration code on the next maps update.
}
else
{
changeset.AddChangesetTag("info:feature_close_by", "yes");
LOG(LDEBUG, ("Create case: uploading patched feature", osmFeature));
changeset.AddChangesetTag("info:old_editor", "yes");
changeset.AddChangesetTag("info:features_merged", "yes");
changeset.Modify(osmFeature);
}
}
catch (ChangesetWrapper::OsmObjectWasDeletedException const &)
{}
catch (ChangesetWrapper::EmptyFeatureException const &)
{}
// Add tags to XMLFeature
UpdateXMLFeatureTags(feature, journal);
// Upload XMLFeature to OSM
LOG(LDEBUG, ("CREATE Feature (newEditor)", feature));
changeset.AddChangesetTag("info:new_editor", "yes");
if (!mergeSameLocation)
{
// Object was never created by anyone else - it's safe to create it.
changeset.AddChangesetTag("info:old_editor", "yes");
changeset.Create(feature);
else
changeset.Modify(feature);
break;
}
case EditingLifecycle::MODIFIED:
{
// Load existing OSM object (Throws, see catch below)
XMLFeature feature = GetMatchingFeatureFromOSM(changeset, fti.m_object);
// Update tags of XMLFeature
UpdateXMLFeatureTags(feature, journal);
// Upload XMLFeature to OSM
LOG(LDEBUG, ("MODIFIED Feature (newEditor)", feature));
changeset.AddChangesetTag("info:new_editor", "yes");
changeset.Modify(feature);
break;
}
case EditingLifecycle::IN_SYNC:
{
CHECK(false, ("Object already IN_SYNC should not be here"));
continue;
}
}
catch (ChangesetWrapper::EmptyFeatureException const &)
{
// There is another node nearby, but it should be safe to create a new one.
changeset.AddChangesetTag("info:old_editor", "yes");
changeset.Create(feature);
}
catch (...)
{
// Pass network or other errors to outside exception handler.
throw;
}
}
break;
}
case FeatureStatus::Deleted:
auto const originalObjectPtr = GetOriginalMapObject(fti.m_object.GetID());
if (!originalObjectPtr)
{
LOG(LERROR, ("A feature with id", fti.m_object.GetID(), "cannot be loaded."));
GetPlatform().RunTask(Platform::Thread::Gui,
[this, fid = fti.m_object.GetID()]() { RemoveFeatureIfExists(fid); });
continue;
}
changeset.Delete(GetMatchingFeatureFromOSM(changeset, *originalObjectPtr));
break;
}
}
else // Use old editor
{
// Todo: Remove old editor after transition period
switch (fti.m_status)
{
case FeatureStatus::Untouched: CHECK(false, ("It's impossible.")); continue;
case FeatureStatus::Obsolete: continue; // Obsolete features will be deleted by OSMers.
case FeatureStatus::Created:
{
XMLFeature feature = editor::ToXML(fti.m_object, true);
if (!fti.m_street.empty())
feature.SetTagValue(kAddrStreetTag, fti.m_street);
ASSERT_EQUAL(feature.GetType(), XMLFeature::Type::Node,
("Linear and area features creation is not supported yet."));
try
case FeatureStatus::Modified:
{
auto const center = fti.m_object.GetMercator();
// Throws, see catch below.
XMLFeature osmFeature = changeset.GetMatchingNodeFeatureFromOSM(center);
// Do not serialize feature's type to avoid breaking OSM data.
// TODO: Implement correct types matching when we support modifying existing feature types.
XMLFeature feature = editor::ToXML(fti.m_object, false);
if (!fti.m_street.empty())
feature.SetTagValue(kAddrStreetTag, fti.m_street);
// If we are here, it means that object already exists at the given point.
// To avoid nodes duplication, merge and apply changes to it instead of creating a new one.
auto const originalObjectPtr = GetOriginalMapObject(fti.m_object.GetID());
if (!originalObjectPtr)
{
LOG(LERROR, ("A feature with id", fti.m_object.GetID(), "cannot be loaded."));
GetPlatform().RunTask(Platform::Thread::Gui,
[this, fid = fti.m_object.GetID()]() { RemoveFeatureIfExists(fid); });
continue;
}
XMLFeature osmFeature = GetMatchingFeatureFromOSM(changeset, *originalObjectPtr);
XMLFeature const osmFeatureCopy = osmFeature;
osmFeature.ApplyPatch(feature);
// Check to avoid uploading duplicates into OSM.
@@ -746,129 +798,86 @@ void Editor::UploadChanges(string const & oauthToken, ChangesetTags tags, Finish
}
else
{
LOG(LDEBUG, ("Create case: uploading patched feature", osmFeature));
LOG(LDEBUG, ("Uploading patched feature", osmFeature));
changeset.AddChangesetTag("info:old_editor", "yes");
changeset.AddChangesetTag("info:features_merged", "yes");
changeset.Modify(osmFeature);
}
}
catch (ChangesetWrapper::OsmObjectWasDeletedException const &)
{
// Object was never created by anyone else - it's safe to create it.
changeset.AddChangesetTag("info:old_editor", "yes");
changeset.Create(feature);
}
catch (ChangesetWrapper::EmptyFeatureException const &)
{
// There is another node nearby, but it should be safe to create a new one.
changeset.AddChangesetTag("info:old_editor", "yes");
changeset.Create(feature);
}
catch (...)
{
// Pass network or other errors to outside exception handler.
throw;
}
}
break;
case FeatureStatus::Modified:
{
// Do not serialize feature's type to avoid breaking OSM data.
// TODO: Implement correct types matching when we support modifying existing feature types.
XMLFeature feature = editor::ToXML(fti.m_object, false);
if (!fti.m_street.empty())
feature.SetTagValue(kAddrStreetTag, fti.m_street);
auto const originalObjectPtr = GetOriginalMapObject(fti.m_object.GetID());
if (!originalObjectPtr)
{
LOG(LERROR, ("A feature with id", fti.m_object.GetID(), "cannot be loaded."));
GetPlatform().RunTask(Platform::Thread::Gui,
[this, fid = fti.m_object.GetID()]() { RemoveFeatureIfExists(fid); });
continue;
}
XMLFeature osmFeature = GetMatchingFeatureFromOSM(changeset, *originalObjectPtr);
XMLFeature const osmFeatureCopy = osmFeature;
osmFeature.ApplyPatch(feature);
// Check to avoid uploading duplicates into OSM.
if (osmFeature == osmFeatureCopy)
{
LOG(LWARNING, ("Local changes are equal to OSM, feature has not been uploaded.", osmFeatureCopy));
// Don't delete this local change right now for user to see it in profile.
// It will be automatically deleted by migration code on the next maps update.
}
else
{
LOG(LDEBUG, ("Uploading patched feature", osmFeature));
changeset.AddChangesetTag("info:old_editor", "yes");
changeset.Modify(osmFeature);
}
}
break;
case FeatureStatus::Deleted:
auto const originalObjectPtr = GetOriginalMapObject(fti.m_object.GetID());
if (!originalObjectPtr)
{
LOG(LERROR, ("A feature with id", fti.m_object.GetID(), "cannot be loaded."));
GetPlatform().RunTask(Platform::Thread::Gui,
[this, fid = fti.m_object.GetID()]() { RemoveFeatureIfExists(fid); });
continue;
}
changeset.AddChangesetTag("info:old_editor", "yes");
changeset.Delete(GetMatchingFeatureFromOSM(changeset, *originalObjectPtr));
break;
case FeatureStatus::Deleted:
auto const originalObjectPtr = GetOriginalMapObject(fti.m_object.GetID());
if (!originalObjectPtr)
{
LOG(LERROR, ("A feature with id", fti.m_object.GetID(), "cannot be loaded."));
GetPlatform().RunTask(Platform::Thread::Gui,
[this, fid = fti.m_object.GetID()]() { RemoveFeatureIfExists(fid); });
continue;
}
changeset.AddChangesetTag("info:old_editor", "yes");
changeset.Delete(GetMatchingFeatureFromOSM(changeset, *originalObjectPtr));
break;
}
}
uploadInfo.m_uploadStatus = kUploaded;
uploadInfo.m_uploadError.clear();
++uploadedFeaturesCount;
}
uploadInfo.m_uploadStatus = kUploaded;
uploadInfo.m_uploadError.clear();
++uploadedFeaturesCount;
}
catch (ChangesetWrapper::OsmObjectWasDeletedException const & ex)
{
uploadInfo.m_uploadStatus = kDeletedFromOSMServer;
uploadInfo.m_uploadError = ex.Msg();
++errorsCount;
LOG(LWARNING, (ex.what()));
changeset.AddToChangesetKeyList("upload_attempt_error", kDeletedFromOSMServer);
}
catch (ChangesetWrapper::EmptyFeatureException const & ex)
{
uploadInfo.m_uploadStatus = kMatchedFeatureIsEmpty;
uploadInfo.m_uploadError = ex.Msg();
++errorsCount;
LOG(LWARNING, (ex.what()));
changeset.AddToChangesetKeyList("upload_attempt_error", kMatchedFeatureIsEmpty);
}
catch (RootException const & ex)
{
uploadInfo.m_uploadStatus = kNeedsRetry;
uploadInfo.m_uploadError = ex.Msg();
++errorsCount;
LOG(LWARNING, (ex.what()));
changeset.AddToChangesetKeyList("upload_attempt_error", ex.Msg());
}
// TODO(AlexZ): Use timestamp from the server.
uploadInfo.m_uploadAttemptTimestamp = time(nullptr);
catch (ChangesetWrapper::OsmObjectWasDeletedException const & ex)
{
uploadInfo.m_uploadStatus = kDeletedFromOSMServer;
uploadInfo.m_uploadError = ex.Msg();
++errorsCount;
LOG(LWARNING, (ex.what()));
changeset.AddToChangesetKeyList("upload_attempt_error", kDeletedFromOSMServer);
}
catch (ChangesetWrapper::EmptyFeatureException const & ex)
{
uploadInfo.m_uploadStatus = kMatchedFeatureIsEmpty;
uploadInfo.m_uploadError = ex.Msg();
++errorsCount;
LOG(LWARNING, (ex.what()));
changeset.AddToChangesetKeyList("upload_attempt_error", kMatchedFeatureIsEmpty);
}
catch (RootException const & ex)
{
uploadInfo.m_uploadStatus = kNeedsRetry;
uploadInfo.m_uploadError = ex.Msg();
++errorsCount;
LOG(LWARNING, (ex.what()));
changeset.AddToChangesetKeyList("upload_attempt_error", ex.Msg());
}
// TODO(AlexZ): Use timestamp from the server.
uploadInfo.m_uploadAttemptTimestamp = time(nullptr);
GetPlatform().RunTask(Platform::Thread::Gui, [this, id = fti.m_object.GetID(), uploadInfo]()
{
// Call Save every time we modify each feature's information.
SaveUploadedInformation(id, uploadInfo);
});
GetPlatform().RunTask(Platform::Thread::Gui, [this, id = fti.m_object.GetID(), uploadInfo]()
{
// Call Save every time we modify each feature's information.
SaveUploadedInformation(id, uploadInfo);
});
}
}
}
if (callback)
if (callback)
{
UploadResult result = UploadResult::NothingToUpload;
if (uploadedFeaturesCount)
result = UploadResult::Success;
else if (errorsCount)
result = UploadResult::Error;
callback(result);
}
m_isUploadingNow = false;
};
// Do not run more than one uploading task at a time.
if (!m_isUploadingNow)
{
UploadResult result = UploadResult::NothingToUpload;
if (uploadedFeaturesCount)
result = UploadResult::Success;
else if (errorsCount)
result = UploadResult::Error;
callback(result);
m_isUploadingNow = true;
GetPlatform().RunTask(Platform::Thread::Network, [upload = std::move(upload), oauthToken, tags = std::move(tags),
callback = std::move(callback)]()
{ upload(std::move(oauthToken), std::move(tags), std::move(callback)); });
}
}

View File

@@ -260,7 +260,7 @@ private:
std::unique_ptr<editor::StorageBase> m_storage;
std::mutex m_uploadingEditsMutex;
std::atomic<bool> m_isUploadingNow;
DECLARE_THREAD_CHECKER(MainThreadChecker);
}; // class Editor

View File

@@ -558,14 +558,6 @@ public:
{}
};
class HungaryRoadShieldParser : public SimpleRoadShieldParser
{
public:
explicit HungaryRoadShieldParser(std::string const & baseRoadNumber)
: SimpleRoadShieldParser(baseRoadNumber, {{"M", RoadShieldType::Hungary_Blue}}, RoadShieldType::Hungary_Green)
{}
};
class LativaRoadShieldParser : public SimpleRoadShieldParser
{
public:
@@ -882,8 +874,6 @@ RoadShieldsSetT GetRoadShields(std::string const & mwmName, std::string const &
return ItalyRoadShieldParser(roadNumber).GetRoadShields();
if (mwmName == "Turkey")
return TurkeyRoadShieldParser(roadNumber).GetRoadShields();
if (mwmName == "Hungary")
return HungaryRoadShieldParser(roadNumber).GetRoadShields();
if (mwmName == "Lativa")
return LativaRoadShieldParser(roadNumber).GetRoadShields();
if (mwmName == "Moldova")
@@ -984,8 +974,6 @@ std::string DebugPrint(RoadShieldType shieldType)
case RoadShieldType::US_Highway: return "US highway";
case RoadShieldType::UK_Highway: return "UK highway";
case RoadShieldType::Italy_Autostrada: return "Italy autostrada";
case RoadShieldType::Hungary_Green: return "hungary green";
case RoadShieldType::Hungary_Blue: return "hungary blue";
case RoadShieldType::Hidden: return "hidden";
case RoadShieldType::Count: CHECK(false, ("RoadShieldType::Count is not to be used as a type"));
}

View File

@@ -42,8 +42,6 @@ enum class RoadShieldType
US_Highway,
UK_Highway,
Italy_Autostrada,
Hungary_Green,
Hungary_Blue,
Hidden,
Count
};

View File

@@ -11,7 +11,6 @@
#include "base/assert.hpp"
#include "base/buffer_vector.hpp"
#include <execution>
#include <string>
#include <unordered_map>
#include <vector>
@@ -118,31 +117,27 @@ public:
template <class FnT>
void ForEachEnter(FnT && fn) const
{
std::for_each(std::execution::par_unseq, m_transitions.begin(), m_transitions.end(), [&](auto const & pair)
for (auto const & [key, transit] : m_transitions)
{
auto const & [key, transit] = pair;
if (transit.m_forwardIsEnter)
fn(transit.m_enterIdx, Segment(m_mwmId, key.m_featureId, key.m_segmentIdx, true));
if (!transit.m_oneWay && !transit.m_forwardIsEnter)
fn(transit.m_enterIdx, Segment(m_mwmId, key.m_featureId, key.m_segmentIdx, false));
});
}
}
template <class FnT>
void ForEachExit(FnT && fn) const
{
std::for_each(std::execution::par_unseq, m_transitions.begin(), m_transitions.end(), [&](auto const & pair)
for (auto const & [key, transit] : m_transitions)
{
auto const & [key, transit] = pair;
if (!transit.m_forwardIsEnter)
fn(transit.m_exitIdx, Segment(m_mwmId, key.m_featureId, key.m_segmentIdx, true));
if (!transit.m_oneWay && transit.m_forwardIsEnter)
fn(transit.m_exitIdx, Segment(m_mwmId, key.m_featureId, key.m_segmentIdx, false));
});
}
}
void GetOutgoingEdgeList(Segment const & segment, EdgeListT & edges) const

View File

@@ -4,14 +4,16 @@
#include "routing/routing_options.hpp"
#include "routing/world_graph.hpp"
#include "platform/settings.hpp"
#include "base/assert.hpp"
#include "base/checked_cast.hpp"
#include "base/exception.hpp"
#include "base/timer.hpp"
#include "geometry/distance_on_sphere.hpp"
#include <algorithm>
#include <execution>
#include <limits>
#include <utility>
@@ -319,9 +321,7 @@ void IndexGraph::ReconstructJointSegment(astar::VertexData<JointSegment, RouteWe
auto const & weightTimeToParent = parentVertexData.m_realDistance;
auto const & parentJoint = parentVertexData.m_vertex;
auto const range = std::ranges::views::iota(0uz, firstChildren.size());
std::for_each(std::execution::par_unseq, range.begin(), range.end(), [&, this](auto const i)
for (size_t i = 0; i < firstChildren.size(); ++i)
{
auto const & firstChild = firstChildren[i];
auto const lastPointId = lastPointIds[i];
@@ -335,21 +335,22 @@ void IndexGraph::ReconstructJointSegment(astar::VertexData<JointSegment, RouteWe
{ return currentPointId < lastPointId ? pointId + 1 : pointId - 1; };
if (IsAccessNoForSure(firstChild.GetFeatureId(), weightTimeToParent, true /* useAccessConditional */))
return;
continue;
if (IsAccessNoForSure(parent.GetRoadPoint(isOutgoing), weightTimeToParent, true /* useAccessConditional */))
return;
continue;
if (IsUTurn(parent, firstChild) && IsUTurnAndRestricted(parent, firstChild, isOutgoing))
return;
continue;
if (IsRestricted(parentJoint, parent.GetFeatureId(), firstChild.GetFeatureId(), isOutgoing, parents))
return;
continue;
RouteWeight summaryWeight;
// Check current JointSegment for bad road access between segments.
RoadPoint rp = firstChild.GetRoadPoint(isOutgoing);
uint32_t start = currentPointId;
bool noRoadAccess = false;
do
{
// This is optimization: we calculate accesses of road points before calculating weight of
@@ -359,13 +360,19 @@ void IndexGraph::ReconstructJointSegment(astar::VertexData<JointSegment, RouteWe
// until this |rp|. But we assume that segments have small length and inaccuracy will not
// affect user.
if (IsAccessNoForSure(rp, weightTimeToParent, true /* useAccessConditional */))
return;
{
noRoadAccess = true;
break;
}
start = increment(start);
rp.SetPointId(start);
}
while (start != lastPointId);
if (noRoadAccess)
continue;
bool forward = currentPointId < lastPointId;
Segment current = firstChild;
Segment prev = parent;
@@ -389,7 +396,7 @@ void IndexGraph::ReconstructJointSegment(astar::VertexData<JointSegment, RouteWe
jointEdges.emplace_back(isOutgoing ? JointSegment(firstChild, prev) : JointSegment(prev, firstChild),
summaryWeight);
});
}
}
void IndexGraph::GetNeighboringEdge(astar::VertexData<Segment, RouteWeight> const & fromVertexData, Segment const & to,

View File

@@ -18,6 +18,8 @@
#include "indexer/feature_meta.hpp"
#include "geometry/point2d.hpp"
#include <memory>
#include <optional>
#include <unordered_map>

View File

@@ -13,7 +13,6 @@
#include "3party/skarupke/bytell_hash_map.hpp" // needed despite of IDE warning
#include <algorithm>
#include <execution>
#include <map>
#include <optional>
#include <queue>
@@ -475,8 +474,7 @@ void IndexGraphStarterJoints<Graph>::GetEdgeList(astar::VertexData<Vertex, Weigh
CHECK(it != m_savedWeight.cend(), ("Can not find weight for:", vertex));
Weight const weight = it->second;
auto const range = std::ranges::views::iota(0uz, edges.size());
std::for_each(std::execution::par_unseq, range.begin(), range.end(), [&, this](auto const i)
for (size_t i = 0; i < edges.size(); ++i)
{
// Saving weight of current edges for returning in the next iterations.
auto & w = edges[i].GetWeight();
@@ -492,7 +490,7 @@ void IndexGraphStarterJoints<Graph>::GetEdgeList(astar::VertexData<Vertex, Weigh
// |parentWeights[]|. So the weight of an ith edge is a cached "weight of parent JointSegment" +
// "parentWeight[i]".
w = weight + parentWeights[i];
});
}
// Delete useless weight of parent JointSegment.
m_savedWeight.erase(vertex);
@@ -500,9 +498,8 @@ void IndexGraphStarterJoints<Graph>::GetEdgeList(astar::VertexData<Vertex, Weigh
else
{
// This needs for correct weights calculation of FakeJointSegments during forward A* search.
auto const range = std::ranges::views::iota(firstFakeId, edges.size());
std::for_each(std::execution::par_unseq, range.begin(), range.end(),
[&edges, &parentWeights](auto const i) { edges[i].GetWeight() += parentWeights[i]; });
for (size_t i = firstFakeId; i < edges.size(); ++i)
edges[i].GetWeight() += parentWeights[i];
}
auto const vertexMwmId = vertex.GetMwmId();
@@ -513,12 +510,12 @@ void IndexGraphStarterJoints<Graph>::GetEdgeList(astar::VertexData<Vertex, Weigh
/// a weight of v1->v2 transition moving backward (v2 ingoing). This is impossible in current (m_savedWeight)
/// logic, so I moved Cross-MWM penalty into separate block here after _all_ weights calculations.
std::for_each(std::execution::par_unseq, edges.begin(), edges.end(), [&, this](auto & e)
for (auto & e : edges)
{
auto const targetMwmId = e.GetTarget().GetMwmId();
if (targetMwmId != kFakeNumMwmId && vertexMwmId != targetMwmId)
e.GetWeight() += m_graph.GetCrossBorderPenalty(vertexMwmId, targetMwmId);
});
}
}
}

View File

@@ -6,8 +6,6 @@ SKIP_MAP_DOWNLOAD="${SKIP_MAP_DOWNLOAD:-}"
SKIP_GENERATE_SYMBOLS="${SKIP_GENERATE_SYMBOLS:-}"
SKIP_GENERATE_DRULES="${SKIP_GENERATE_DRULES:-}"
CMAKE_CONFIG="${CMAKE_CONFIG:-} -U SKIP_QT_GUI -U GENERATOR_TOOL -U USE_PCH -U CMAKE_EXPORT_COMPILE_COMMANDS -U NJOBS -U SKIP_TESTS"
OPT_DEBUG=
OPT_RELEASE=
OPT_RELEASEDEBUGINFO=
@@ -65,6 +63,7 @@ done
OPT_TARGET=${@:$OPTIND}
CMAKE_CONFIG="${CMAKE_CONFIG:-} -U SKIP_QT_GUI -U GENERATOR_TOOL"
if [ "$OPT_TARGET" != "desktop" -a -z "$OPT_DESIGNER" -a -z "$OPT_STANDALONE"]; then
CMAKE_CONFIG="${CMAKE_CONFIG:-} -DSKIP_QT_GUI=ON"
fi