forked from organicmaps/organicmaps
Compare commits
1 commit
master
...
github/for
Author | SHA1 | Date | |
---|---|---|---|
|
0ffe7a7e95 |
18 changed files with 311 additions and 56 deletions
|
@ -1,19 +1,27 @@
|
|||
package app.organicmaps.routing;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.RadioButton;
|
||||
import android.widget.RadioGroup;
|
||||
import android.widget.TextView;
|
||||
import android.content.SharedPreferences;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.IdRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import app.organicmaps.Framework;
|
||||
import app.organicmaps.MwmApplication;
|
||||
import app.organicmaps.R;
|
||||
|
@ -181,6 +189,26 @@ public class RoutingPlanController extends ToolbarController
|
|||
return (mFrameHeight > 0);
|
||||
}
|
||||
|
||||
void addStopToast() {
|
||||
SharedPreferences prefs = MwmApplication.prefs(requireActivity().getApplicationContext());
|
||||
SharedPreferences.Editor editor = prefs.edit();
|
||||
editor.putBoolean(String.valueOf(R.string.toast_dismiss), false);
|
||||
editor.apply();
|
||||
|
||||
View progressFrame = getToolbar().findViewById(R.id.progress_frame);
|
||||
LayoutInflater inflater = requireActivity().getLayoutInflater();
|
||||
View layout = inflater.inflate(R.layout.toast_custom,null);
|
||||
|
||||
TextView text = layout.findViewById(R.id.toast_custom);
|
||||
text.setText(R.string.add_stop_toast);
|
||||
|
||||
Toast toast = new Toast(progressFrame.getContext());
|
||||
toast.setDuration(Toast.LENGTH_LONG);
|
||||
toast.setGravity(Gravity.BOTTOM, 0, 160);
|
||||
toast.setView(layout);
|
||||
toast.show();
|
||||
}
|
||||
|
||||
private void updateProgressLabels()
|
||||
{
|
||||
RoutingController.BuildState buildState = RoutingController.get().getBuildState();
|
||||
|
@ -212,6 +240,13 @@ public class RoutingPlanController extends ToolbarController
|
|||
final boolean showStartButton = !RoutingController.get().isRulerRouterType();
|
||||
mRoutingBottomMenuController.setStartButton(showStartButton);
|
||||
mRoutingBottomMenuController.showAltitudeChartAndRoutingDetails();
|
||||
|
||||
SharedPreferences prefs = MwmApplication.prefs(requireActivity().getApplicationContext());
|
||||
boolean ShowToast = prefs.getBoolean(String.valueOf(R.string.toast_dismiss), true);
|
||||
|
||||
if (ShowToast) {
|
||||
addStopToast();
|
||||
}
|
||||
}
|
||||
|
||||
public void updateBuildProgress(int progress, @Framework.RouterType int router)
|
||||
|
@ -349,4 +384,4 @@ public class RoutingPlanController extends ToolbarController
|
|||
mDrivingOptionsBtnContainer.removeOnLayoutChangeListener(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
6
android/app/src/main/res/drawable/toast_custom_shape.xml
Normal file
6
android/app/src/main/res/drawable/toast_custom_shape.xml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#333333" />
|
||||
<corners android:radius="16dp" />
|
||||
<padding android:left="8dp" android:top="8dp" android:right="8dp" android:bottom="8dp" />
|
||||
</shape>
|
15
android/app/src/main/res/layout/toast_custom.xml
Normal file
15
android/app/src/main/res/layout/toast_custom.xml
Normal file
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="10dp"
|
||||
android:background="@drawable/toast_custom_shape">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/toast_custom"
|
||||
android:layout_width="340dp"
|
||||
android:layout_height="30dp"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="16sp" />
|
||||
</LinearLayout>
|
|
@ -612,6 +612,8 @@
|
|||
<string name="core_exit">Exit</string>
|
||||
<string name="routing_add_start_point">Add a starting point to plan a route</string>
|
||||
<string name="routing_add_finish_point">Add a destination to plan a route</string>
|
||||
<string name="add_stop_toast">Select any place to add an intermediate stop</string>
|
||||
<string name="toast_dismiss">Don\'t show again</string>
|
||||
<string name="placepage_remove_stop">Remove</string>
|
||||
<string name="placepage_add_stop">Add Stop</string>
|
||||
<!-- Alert to ask user relogin to OpenStreetMap with OAuth2 flow after OAuth1 authentication is deprecated. -->
|
||||
|
@ -697,6 +699,7 @@
|
|||
<!-- Recommended length for CarPlay and Android Auto is around 25-27 characters -->
|
||||
<string name="avoid_ferry">Avoid ferries</string>
|
||||
<string name="avoid_motorways">Avoid freeways</string>
|
||||
<string name="manage_route">Manage route</string>
|
||||
<string name="unable_to_calc_alert_title">Unable to calculate route</string>
|
||||
<string name="unable_to_calc_alert_subtitle">A route could not be found. This may be caused by your routing options or incomplete OpenStreetMap data. Please change your routing options and retry.</string>
|
||||
<string name="define_to_avoid_btn">Define roads to avoid</string>
|
||||
|
@ -2200,4 +2203,4 @@
|
|||
<string name="type.amenity.events_venue">Events Venue</string>
|
||||
<string name="type.shop.auction">Auction</string>
|
||||
<string name="type.shop.collector">Collectables</string>
|
||||
</resources>
|
||||
</resources>
|
|
@ -20194,6 +20194,51 @@
|
|||
zh-Hans = 添加起点以规划路线
|
||||
zh-Hant = 新增起點以計劃路線
|
||||
|
||||
[routing_add_stop_point]
|
||||
tags = ios
|
||||
en = Select any place to add an intermediate stop
|
||||
af = Kies enige plek om ’n tussenstop by te voeg
|
||||
ar = حدد أي مكان لإضافة توقف وسيط
|
||||
az = Bir ara durmaq əlavə etmək üçün hər hansı bir yeri seçin
|
||||
be = Выберыце любое месца, каб дадаць пралягчы стоп
|
||||
bg = Изберете която и да е точка, за да добавите междинна спирка
|
||||
ca = Seleccioneu qualsevol lloc per afegir una parada intermèdia
|
||||
cs = Vyberte libovolné místo pro přidání mezipřistání
|
||||
da = Vælg et hvilket som helst sted for at tilføje en mellemlanding
|
||||
de = Wählen Sie einen beliebigen Ort aus, um einen Zwischenstopp hinzuzufügen
|
||||
el = Επιλέξτε οποιοδήποτε μέρος για να προσθέσετε μια ενδιάμεση στάση
|
||||
es = Selecciona cualquier lugar para añadir una parada intermedia
|
||||
et = Valige mis tahes koht, et lisada vahepeatuse punkt
|
||||
eu = Hautatu edozein toki eta gehitu eten erdia
|
||||
fa = یک مکان را برای اضافه کردن یک توقف وسطی انتخاب کنید
|
||||
fi = Valitse mikä tahansa paikka lisätäksesi välipysäkin
|
||||
fr = Sélectionnez n'importe quel endroit pour ajouter un arrêt intermédiaire
|
||||
he = בחרו בכל מקום להוסיף תחנה ביניים
|
||||
hi = बिच का एक स्थान जोड़ने के लिए कोई भी स्थान चुनें
|
||||
hu = Válasszon ki bármilyen helyet egy köztes megálló hozzáadásához
|
||||
id = Pilih tempat mana pun untuk menambahkan titik persinggahan
|
||||
it = Seleziona qualsiasi posto per aggiungere una fermata intermedia
|
||||
ja = 中間停留所を追加する場所を選択してください
|
||||
ko = 중간 정차지를 추가할 위치를 선택하세요
|
||||
lt = Pasirinkite bet kurį vietą, kad pridėtumėte tarpinę stotelę
|
||||
mr = बीचीकडील थांबायला कोणत्याही ठिकाणी निवडा
|
||||
nb = Velg et hvilket som helst sted for å legge til en mellomlanding
|
||||
nl = Selecteer een willekeurige plaats om een tussenstop toe te voegen
|
||||
pl = Wybierz dowolne miejsce, aby dodać przystanek pośredni
|
||||
pt = Selecione qualquer lugar para adicionar uma paragem intermédia
|
||||
pt-BR = Selecione qualquer lugar para adicionar uma parada intermediária
|
||||
ro = Selectați orice loc pentru a adăuga un punct intermediar de oprire
|
||||
ru = Выберите любое место, чтобы добавить промежуточную остановку
|
||||
sk = Vyberte ľubovoľné miesto pre pridanie medzipristátia
|
||||
sv = Välj valfri plats för att lägga till ett mellanstopp
|
||||
sw = Chagua eneo lolote kuongeza kituo cha kati
|
||||
th = เลือกสถานที่ใดก็ได้เพื่อเพิ่มจุดหยุดระหว่างทาง
|
||||
tr = Araya bir durak eklemek için herhangi bir yeri seçin
|
||||
uk = Виберіть будь-яке місце, щоб додати проміжну зупинку
|
||||
vi = Chọn bất kỳ địa điểm nào để thêm điểm dừng trung gian
|
||||
zh-Hans = 选择任何地点添加中途停靠点
|
||||
zh-Hant = 選擇任何地點添加中途停靠點
|
||||
|
||||
[routing_add_finish_point]
|
||||
tags = android,ios
|
||||
en = Add a destination to plan a route
|
||||
|
@ -30345,4 +30390,4 @@
|
|||
uk = Переглянути меню
|
||||
vi = Xem thực đơn
|
||||
zh-Hans = 查看菜单
|
||||
zh-Hant = 查看選單
|
||||
zh-Hant = 查看選單
|
|
@ -57,4 +57,4 @@ final class BookmarksListInfoViewController: UIViewController {
|
|||
let formattedText = NSAttributedString.string(withHtml: htmlText, defaultAttributes: [:])
|
||||
return formattedText?.string
|
||||
}
|
||||
}
|
||||
}
|
|
@ -91,7 +91,43 @@ final class Toast: NSObject {
|
|||
userInfo: nil,
|
||||
repeats: false)
|
||||
}
|
||||
|
||||
|
||||
@objc func show(in view: UIView?, alignment: Alignment, pinToSafeArea: Bool = true, withOffset offset: CGFloat ) {
|
||||
guard let view = view else { return }
|
||||
blurView.translatesAutoresizingMaskIntoConstraints = false
|
||||
view.addSubview(blurView)
|
||||
|
||||
let leadingConstraint = blurView.leadingAnchor.constraint(greaterThanOrEqualTo: view.leadingAnchor, constant: 16)
|
||||
let trailingConstraint = blurView.trailingAnchor.constraint(lessThanOrEqualTo: view.trailingAnchor, constant: -16)
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
leadingConstraint,
|
||||
trailingConstraint
|
||||
])
|
||||
|
||||
let verticalConstraint: NSLayoutConstraint
|
||||
if alignment == .bottom {
|
||||
verticalConstraint = blurView.bottomAnchor.constraint(equalTo: pinToSafeArea ? view.safeAreaLayoutGuide.bottomAnchor : view.bottomAnchor, constant: offset)
|
||||
} else {
|
||||
verticalConstraint = blurView.topAnchor.constraint(equalTo: pinToSafeArea ? view.safeAreaLayoutGuide.topAnchor : view.topAnchor, constant: offset)
|
||||
}
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
verticalConstraint,
|
||||
blurView.centerXAnchor.constraint(equalTo: pinToSafeArea ? view.safeAreaLayoutGuide.centerXAnchor : view.centerXAnchor)
|
||||
])
|
||||
|
||||
UIView.animate(withDuration: kDefaultAnimationDuration) {
|
||||
self.blurView.alpha = 1
|
||||
}
|
||||
|
||||
timer = Timer.scheduledTimer(timeInterval: 3,
|
||||
target: self,
|
||||
selector: #selector(hide),
|
||||
userInfo: nil,
|
||||
repeats: false)
|
||||
}
|
||||
|
||||
@objc func hide() {
|
||||
timer?.invalidate()
|
||||
if self.blurView.superview != nil {
|
||||
|
@ -101,4 +137,4 @@ final class Toast: NSObject {
|
|||
Self.toasts.removeAll(where: { $0 === self }) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
import XCTest
|
||||
@testable import Organic_Maps_Debug
|
||||
|
||||
final class MWMNavigationInfoViewTests: XCTestCase {
|
||||
|
||||
var userDefaults: UserDefaults!
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
userDefaults = UserDefaults(suiteName: "com.example.OrganicMapsTests") // Use a test-specific suite
|
||||
userDefaults.removePersistentDomain(forName: "com.example.OrganicMapsTests") // Clear UserDefaults before each test
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
userDefaults = nil
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
func testAddStopToastAppearsOnlyInFirstSession() {
|
||||
|
||||
// Simulate first session
|
||||
var isFirstSession = false;
|
||||
if ( userDefaults.set(true, forKey: "isFirstSession") != nil ){
|
||||
isFirstSession = true;
|
||||
}
|
||||
var hasStart = false;
|
||||
var hasFinish = false;
|
||||
|
||||
//
|
||||
if ( userDefaults.set(true, forKey: "hasStart") != nil ){
|
||||
hasStart = true;
|
||||
}
|
||||
if ( userDefaults.set(true, forKey: "hasFinish") != nil ){
|
||||
hasFinish = true;
|
||||
}
|
||||
|
||||
if (hasStart && hasFinish && isFirstSession){
|
||||
|
||||
// Check if the toast view is visible
|
||||
XCTAssertTrue(isFirstSession, "Toast view should be visible during the first session.")
|
||||
|
||||
}else if ( hasStart && hasFinish && !isFirstSession){
|
||||
|
||||
// Check if the toast view is hidden
|
||||
XCTAssertFalse(!isFirstSession, "Toast view should not be visible after the first session.")
|
||||
}
|
||||
|
||||
|
||||
// Simulate subsequent session
|
||||
if ( userDefaults.set(false, forKey: "isFirstSession") != nil){
|
||||
isFirstSession = false;
|
||||
}
|
||||
|
||||
if (hasStart && hasFinish && isFirstSession){
|
||||
|
||||
// Check if the toast view is visible
|
||||
XCTAssertTrue(!isFirstSession, "Toast view should be visible during the first session.")
|
||||
|
||||
}else if ( hasStart && hasFinish && !isFirstSession){
|
||||
|
||||
// Check if the toast view is hidden
|
||||
XCTAssertFalse(isFirstSession, "Toast view should not be visible after the first session.")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -12,6 +12,8 @@
|
|||
#import "UIImageView+Coloring.h"
|
||||
#import "location_util.h"
|
||||
|
||||
#include <CoreApi/Framework.h>
|
||||
|
||||
#include "geometry/angles.hpp"
|
||||
|
||||
namespace
|
||||
|
@ -92,6 +94,7 @@ BOOL defaultOrientation(CGSize const &size) {
|
|||
@property(weak, nonatomic) MWMNavigationDashboardEntity *navigationInfo;
|
||||
|
||||
@property(nonatomic) BOOL hasLocation;
|
||||
@property(nonatomic) BOOL hasShownAddStopToast;
|
||||
|
||||
@property(nonatomic) NSLayoutConstraint *topConstraint;
|
||||
@property(nonatomic) NSLayoutConstraint *leftConstraint;
|
||||
|
@ -117,8 +120,22 @@ BOOL defaultOrientation(CGSize const &size) {
|
|||
|
||||
BOOL const hasStart = ([MWMRouter startPoint] != nil);
|
||||
BOOL const hasFinish = ([MWMRouter finishPoint] != nil);
|
||||
Framework::DrapeCreationParams p;
|
||||
BOOL const isFirstLaunch = [FirstSession isFirstSession];
|
||||
BOOL const hasShownAddStopHint = [FirstSession hasShownAddStopToast];
|
||||
self.hasLocation = ([MWMLocationManager lastLocation] != nil);
|
||||
|
||||
|
||||
if (hasStart && hasFinish && isFirstLaunch && !hasShownAddStopHint) {
|
||||
[self setToastViewHidden:YES];
|
||||
|
||||
MWMToast *toast = [MWMToast toastWithText:L(@"routing_add_stop_point")];
|
||||
|
||||
[toast showIn:[UIApplication sharedApplication].keyWindow alignment:MWMToastAlignmentBottom pinToSafeArea:YES withOffset:-103];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (hasStart && hasFinish) {
|
||||
[self setToastViewHidden:YES];
|
||||
return;
|
||||
|
@ -144,6 +161,10 @@ BOOL defaultOrientation(CGSize const &size) {
|
|||
[toastView configWithIsStart:YES withLocationButton:NO];
|
||||
}
|
||||
|
||||
-(BOOL)isFirstLaunch{
|
||||
return self.isFirstLaunch;
|
||||
}
|
||||
|
||||
- (IBAction)openSearch {
|
||||
BOOL const isStart = self.toastView.isStart;
|
||||
auto searchManager = [MWMSearchManager manager];
|
||||
|
@ -489,4 +510,4 @@ BOOL defaultOrientation(CGSize const &size) {
|
|||
- (void)applyTheme {
|
||||
[self setSearchState:_searchState];
|
||||
}
|
||||
@end
|
||||
@end
|
|
@ -207,6 +207,11 @@ final class RouteManagerViewController: MWMViewController, UITableViewDataSource
|
|||
})
|
||||
}
|
||||
|
||||
@IBAction func onAddStop(_ sender: UIButton) {
|
||||
viewModel.addRoutePoint()
|
||||
dismiss(animated: true, completion: nil)
|
||||
}
|
||||
|
||||
@IBAction private func gestureRecognized(_ longPress: UIGestureRecognizer) {
|
||||
let locationInView = gestureLocation(longPress, in: containerView)
|
||||
let locationInTableView = gestureLocation(longPress, in: tableView)
|
||||
|
@ -254,4 +259,4 @@ final class RouteManagerViewController: MWMViewController, UITableViewDataSource
|
|||
func tableView(_: UITableView, editingStyleForRowAt _: IndexPath) -> UITableViewCell.EditingStyle {
|
||||
return canDeleteRow ? .delete : .none
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="15705" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21701" 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="15706"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21679"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
|
@ -23,14 +23,14 @@
|
|||
</connections>
|
||||
</placeholder>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="3y4-jh-JUF" customClass="RouteManagerDimView" customModule="OMaps" customModuleProvider="target" propertyAccessControl="none">
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="3y4-jh-JUF" customClass="RouteManagerDimView" customModule="Organic_Maps" customModuleProvider="target" propertyAccessControl="none">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<subviews>
|
||||
<view userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="TC7-xW-EwE">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="kTd-fr-ia7">
|
||||
<rect key="frame" x="186" y="380" width="42" height="136.5"/>
|
||||
<rect key="frame" x="186" y="379.5" width="42" height="137"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" alpha="0.0" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="ic_route_manager_trash" translatesAutoresizingMaskIntoConstraints="NO" id="ZEN-kK-2CA">
|
||||
<rect key="frame" x="-3" y="40" width="48" height="48"/>
|
||||
|
@ -40,7 +40,7 @@
|
|||
</constraints>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" alpha="0.0" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="1ks-iR-Wia">
|
||||
<rect key="frame" x="0.0" y="96" width="42" height="20.5"/>
|
||||
<rect key="frame" x="0.0" y="96" width="42" height="21"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
|
@ -72,6 +72,7 @@
|
|||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<viewLayoutGuide key="safeArea" id="aNC-Xj-cAv"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="DimView"/>
|
||||
<gestureRecognizers/>
|
||||
|
@ -81,7 +82,6 @@
|
|||
<constraint firstAttribute="trailing" secondItem="TC7-xW-EwE" secondAttribute="trailing" id="kvp-My-OQZ"/>
|
||||
<constraint firstItem="TC7-xW-EwE" firstAttribute="top" secondItem="3y4-jh-JUF" secondAttribute="top" id="lfE-MZ-Cvp"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="aNC-Xj-cAv"/>
|
||||
<connections>
|
||||
<outlet property="image" destination="ZEN-kK-2CA" id="zkv-Ag-qOp"/>
|
||||
<outlet property="label" destination="1ks-iR-Wia" id="jsa-mi-iZ2"/>
|
||||
|
@ -100,11 +100,11 @@
|
|||
<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="i5M-Pr-FkT">
|
||||
<rect key="frame" x="0.0" y="758" width="414" height="138"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="s0L-ul-gog" customClass="RouteManagerHeaderView" customModule="OMaps" customModuleProvider="target">
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="s0L-ul-gog" customClass="RouteManagerHeaderView" customModule="Organic_Maps" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="48"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="760" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dQh-uc-65J">
|
||||
<rect key="frame" x="16" y="14" width="42" height="20.5"/>
|
||||
<rect key="frame" x="16" y="13.5" width="42" height="21"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
|
@ -113,7 +113,7 @@
|
|||
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="planning_route_manage_route"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</label>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="0Fo-Ae-QrQ">
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="0Fo-Ae-QrQ">
|
||||
<rect key="frame" x="370" y="0.0" width="28" height="48"/>
|
||||
<inset key="contentEdgeInsets" minX="8" minY="0.0" maxX="0.0" maxY="0.0"/>
|
||||
<inset key="imageEdgeInsets" minX="-8" minY="0.0" maxX="0.0" maxY="0.0"/>
|
||||
|
@ -122,6 +122,18 @@
|
|||
<action selector="onAdd" destination="-1" eventType="touchUpInside" id="zGx-NU-Hzq"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="tailTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="60p-dV-R5X" userLabel="Add Stop Button">
|
||||
<rect key="frame" x="255" y="0.0" width="78" height="48"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<state key="normal" title="Button"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="styleName" value="FlatNormalTransButton"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="Add Stop"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<action selector="onAddStop:" destination="-1" eventType="touchUpInside" id="AF7-kv-mKg"/>
|
||||
</connections>
|
||||
</button>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="MJB-bK-y5c">
|
||||
<rect key="frame" x="16" y="47" width="398" height="1"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
|
@ -155,7 +167,7 @@
|
|||
<outlet property="titleLabel" destination="dQh-uc-65J" id="xKP-bY-mQP"/>
|
||||
</connections>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="mqc-M4-MPb" customClass="RouteManagerFooterView" customModule="OMaps" customModuleProvider="target">
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="mqc-M4-MPb" customClass="RouteManagerFooterView" customModule="Organic_Maps" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="48" width="414" height="48"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="or0-Gy-0su">
|
||||
|
@ -175,7 +187,7 @@
|
|||
<userDefinedRuntimeAttribute type="string" keyPath="styleName" value="Divider"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</view>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="2WE-hS-hzl">
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="2WE-hS-hzl">
|
||||
<rect key="frame" x="16" y="0.0" width="46" height="48"/>
|
||||
<state key="normal" title="Button"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
|
@ -186,7 +198,7 @@
|
|||
<action selector="onCancel" destination="-1" eventType="touchUpInside" id="Lzk-mL-6Jg"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="u3h-0s-UBo">
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="u3h-0s-UBo">
|
||||
<rect key="frame" x="352" y="0.0" width="46" height="48"/>
|
||||
<state key="normal" title="Button"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
|
@ -225,7 +237,7 @@
|
|||
<outlet property="separator" destination="pjx-6o-NWS" id="EKT-Ba-Lcy"/>
|
||||
</connections>
|
||||
</view>
|
||||
<tableView clipsSubviews="YES" contentMode="scaleToFill" showsHorizontalScrollIndicator="NO" style="plain" separatorStyle="none" allowsSelection="NO" rowHeight="48" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="Zqd-YQ-ksD" customClass="RouteManagerTableView" customModule="OMaps" customModuleProvider="target">
|
||||
<tableView clipsSubviews="YES" contentMode="scaleToFill" showsHorizontalScrollIndicator="NO" style="plain" separatorStyle="none" allowsSelection="NO" rowHeight="48" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="Zqd-YQ-ksD" customClass="RouteManagerTableView" customModule="Organic_Maps" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="48" width="414" height="0.0"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<gestureRecognizers/>
|
||||
|
@ -263,6 +275,7 @@
|
|||
</userDefinedRuntimeAttributes>
|
||||
</view>
|
||||
</subviews>
|
||||
<viewLayoutGuide key="safeArea" id="hNI-dt-MwJ"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="ControllerView"/>
|
||||
<gestureRecognizers/>
|
||||
|
@ -272,8 +285,7 @@
|
|||
<constraint firstAttribute="bottom" secondItem="i5M-Pr-FkT" secondAttribute="bottom" id="qXL-Hf-8X6"/>
|
||||
<constraint firstItem="i5M-Pr-FkT" firstAttribute="top" relation="greaterThanOrEqual" secondItem="TKX-qe-h4F" secondAttribute="top" constant="72" id="sYB-lu-PhM"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="hNI-dt-MwJ"/>
|
||||
<point key="canvasLocation" x="-239.5" y="-48.5"/>
|
||||
<point key="canvasLocation" x="-240.57971014492756" y="-48.883928571428569"/>
|
||||
</view>
|
||||
<tapGestureRecognizer id="deN-Z9-rbS" userLabel="Cancel Tap Gesture Recognizer">
|
||||
<connections>
|
||||
|
@ -290,4 +302,4 @@
|
|||
<image name="ic_get_position" width="20" height="20"/>
|
||||
<image name="ic_route_manager_trash" width="24" height="24"/>
|
||||
</resources>
|
||||
</document>
|
||||
</document>
|
|
@ -18,6 +18,9 @@ final class RouteManagerViewModel: NSObject, RouteManagerViewModelProtocol {
|
|||
MWMRouter.updatePreviewMode()
|
||||
refreshControlsCallback()
|
||||
}
|
||||
func addRoutePoint() {
|
||||
MWMRouter.cancelRouteManagerTransaction()
|
||||
}
|
||||
func movePoint(at index: Int, to newIndex: Int) {
|
||||
MWMRouter.movePoint(at: index, to: newIndex)
|
||||
MWMRouter.updatePreviewMode()
|
||||
|
@ -29,4 +32,4 @@ final class RouteManagerViewModel: NSObject, RouteManagerViewModelProtocol {
|
|||
refreshControlsCallback()
|
||||
reloadCallback()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ protocol RouteManagerViewModelProtocol: AnyObject {
|
|||
func cancelTransaction()
|
||||
|
||||
func addLocationPoint()
|
||||
func addRoutePoint()
|
||||
func movePoint(at index: Int, to newIndex: Int)
|
||||
func deletePoint(at index: Int)
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
/*******************************************************************************
|
||||
/***************************
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2021 Alexander Borsuk <me@alex.bio> from Minsk, Belarus
|
||||
|
@ -20,7 +20,7 @@
|
|||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*******************************************************************************/
|
||||
***************************/
|
||||
|
||||
#ifndef FIRSTSESSION_H
|
||||
#define FIRSTSESSION_H
|
||||
|
@ -40,6 +40,8 @@
|
|||
+ (void)setup:(NSArray *)serverUrls withLaunchOptions:(NSDictionary *)options;
|
||||
// Returns YES if it is a first session, before app goes into background.
|
||||
+ (BOOL)isFirstSession;
|
||||
// Returns YES if it has already showed the add stop hint.
|
||||
+ (BOOL)hasShownAddStopToast;
|
||||
// Returns summary time of all active user sessions up to now.
|
||||
+ (NSInteger)totalSecondsSpentInTheApp;
|
||||
|
||||
|
@ -57,4 +59,4 @@
|
|||
+ (NSString *)installationId;
|
||||
@end
|
||||
|
||||
#endif // #ifndef FIRSTSESSION_H
|
||||
#endif // #ifndef FIRSTSESSION_H
|
|
@ -1,4 +1,4 @@
|
|||
/*******************************************************************************
|
||||
/***************************
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2021 Alexander Borsuk <me@alex.bio> from Minsk, Belarus
|
||||
|
@ -20,7 +20,7 @@
|
|||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*******************************************************************************/
|
||||
***************************/
|
||||
|
||||
#if ! __has_feature(objc_arc)
|
||||
#error This file must be compiled with ARC. Either turn on ARC for the project or use -fobjc-arc flag
|
||||
|
@ -60,6 +60,7 @@ static NSString * const kIsAlohalyticsDisabledKey = @"AlohalyticsDisabledKey";
|
|||
// setup should be called to activate counting.
|
||||
static NSDate * gSessionStartTime = nil;
|
||||
static BOOL gIsFirstSession = NO;
|
||||
static int gHasShownAddStopToast = 1;
|
||||
static NSString * gInstallationId = nil;
|
||||
|
||||
@implementation FirstSession
|
||||
|
@ -92,6 +93,11 @@ static NSString * gInstallationId = nil;
|
|||
return [self installationId] != nil && gIsFirstSession;
|
||||
}
|
||||
|
||||
+ (BOOL)hasShownAddStopToast {
|
||||
gHasShownAddStopToast -= 1;
|
||||
return gHasShownAddStopToast==1;
|
||||
}
|
||||
|
||||
+ (NSDate *)firstLaunchDate {
|
||||
NSUserDefaults * ud = [NSUserDefaults standardUserDefaults];
|
||||
NSDate * date = [ud objectForKey:kFirstLaunchDateKey];
|
||||
|
@ -147,4 +153,4 @@ static NSString * gInstallationId = nil;
|
|||
return gInstallationId;
|
||||
}
|
||||
|
||||
@end
|
||||
@end
|
|
@ -926,6 +926,8 @@
|
|||
|
||||
"routing_add_start_point" = "Add a starting point to plan a route";
|
||||
|
||||
"routing_add_stop_point" = "Select any place to add an intermediate stop"
|
||||
|
||||
"routing_add_finish_point" = "Add a destination to plan a route";
|
||||
|
||||
"planning_route_manage_route" = "Manage Route";
|
||||
|
@ -3907,4 +3909,4 @@
|
|||
|
||||
"type.shop.auction" = "Auction";
|
||||
|
||||
"type.shop.collector" = "Collectables";
|
||||
"type.shop.collector" = "Collectables";
|
|
@ -926,6 +926,8 @@
|
|||
|
||||
"routing_add_start_point" = "Add a starting point to plan a route";
|
||||
|
||||
"routing_add_stop_point" = "Select any place to add an intermediate stop"
|
||||
|
||||
"routing_add_finish_point" = "Add a destination to plan a route";
|
||||
|
||||
"planning_route_manage_route" = "Manage Route";
|
||||
|
@ -3907,4 +3909,4 @@
|
|||
|
||||
"type.shop.auction" = "Auction";
|
||||
|
||||
"type.shop.collector" = "Collectables";
|
||||
"type.shop.collector" = "Collectables";
|
|
@ -103,7 +103,6 @@ RouteMarkData GetLastPassedPoint(BookmarkManager * bmManager, vector<RouteMarkDa
|
|||
{
|
||||
data.m_position = bmManager->MyPositionMark().GetPivot();
|
||||
data.m_isMyPosition = false;
|
||||
data.m_replaceWithMyPositionAfterRestart = true;
|
||||
}
|
||||
|
||||
return data;
|
||||
|
@ -117,7 +116,6 @@ void SerializeRoutePoint(json_t * node, RouteMarkData const & data)
|
|||
ToJSONObject(*node, "subtitle", data.m_subTitle);
|
||||
ToJSONObject(*node, "x", data.m_position.x);
|
||||
ToJSONObject(*node, "y", data.m_position.y);
|
||||
ToJSONObject(*node, "replaceWithMyPosition", data.m_replaceWithMyPositionAfterRestart);
|
||||
}
|
||||
|
||||
RouteMarkData DeserializeRoutePoint(json_t * node)
|
||||
|
@ -135,8 +133,6 @@ RouteMarkData DeserializeRoutePoint(json_t * node)
|
|||
FromJSONObject(node, "x", data.m_position.x);
|
||||
FromJSONObject(node, "y", data.m_position.y);
|
||||
|
||||
FromJSONObject(node, "replaceWithMyPosition", data.m_replaceWithMyPositionAfterRestart);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -151,7 +147,7 @@ string SerializeRoutePoints(vector<RouteMarkData> const & points)
|
|||
json_array_append_new(pointsNode.get(), pointNode.release());
|
||||
}
|
||||
unique_ptr<char, JSONFreeDeleter> buffer(
|
||||
json_dumps(pointsNode.get(), JSON_COMPACT));
|
||||
json_dumps(pointsNode.get(), JSON_COMPACT | JSON_ENSURE_ASCII));
|
||||
return string(buffer.get());
|
||||
}
|
||||
|
||||
|
@ -418,7 +414,7 @@ void RoutingManager::OnBuildRouteReady(Route const & route, RouterResultCode cod
|
|||
m2::RectD routeRect = route.GetPoly().GetLimitRect();
|
||||
routeRect.Scale(kRouteScaleMultiplier);
|
||||
m_drapeEngine.SafeCall(&df::DrapeEngine::SetModelViewRect, routeRect,
|
||||
true /* applyRotation */, -1 /* zoom */, true /* isAnim */,
|
||||
true /* applyRotation /, -1 / zoom /, true / isAnim */,
|
||||
true /* useVisibleViewport */);
|
||||
}
|
||||
|
||||
|
@ -834,8 +830,12 @@ size_t RoutingManager::GetRoutePointsCount() const
|
|||
|
||||
bool RoutingManager::CouldAddIntermediatePoint() const
|
||||
{
|
||||
if (!IsRoutingActive())
|
||||
//if there isn't already a start or a finish point, we can't add an intermediate point
|
||||
RoutePointsLayout routePoints(*m_bmManager);
|
||||
int pointsCount = routePoints.GetRoutePointsCount();
|
||||
if ( pointsCount == 0){
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_bmManager->GetUserMarkIds(UserMark::Type::ROUTING).size()
|
||||
< RoutePointsLayout::kMaxIntermediatePointsCount + 2;
|
||||
|
@ -995,9 +995,9 @@ void RoutingManager::ReorderIntermediatePoints()
|
|||
prevPoints[i]->SetIntermediateIndex(i < insertIndex ? i : i + 1);
|
||||
}
|
||||
|
||||
void RoutingManager::GenerateNotifications(vector<string> & turnNotifications, bool announceStreets)
|
||||
void RoutingManager::GenerateNotifications(vector<string> & turnNotifications)
|
||||
{
|
||||
m_routingSession.GenerateNotifications(turnNotifications, announceStreets);
|
||||
m_routingSession.GenerateNotifications(turnNotifications);
|
||||
}
|
||||
|
||||
void RoutingManager::BuildRoute(uint32_t timeoutSec)
|
||||
|
@ -1055,7 +1055,7 @@ void RoutingManager::BuildRoute(uint32_t timeoutSec)
|
|||
//m2::RectD rect = ShowPreviewSegments(routePoints);
|
||||
//rect.Scale(kRouteScaleMultiplier);
|
||||
//m_drapeEngine.SafeCall(&df::DrapeEngine::SetModelViewRect, rect, true /* applyRotation */,
|
||||
// -1 /* zoom */, true /* isAnim */, true /* useVisibleViewport */);
|
||||
// -1 /* zoom /, true / isAnim /, true / useVisibleViewport */);
|
||||
|
||||
m_routingSession.ClearPositionAccumulator();
|
||||
m_routingSession.SetUserCurrentPosition(routePoints.front().m_position);
|
||||
|
@ -1111,7 +1111,7 @@ void RoutingManager::CheckLocationForRouting(location::GpsInfo const & info)
|
|||
m_routingSession.RebuildRoute(
|
||||
mercator::FromLatLon(info.m_latitude, info.m_longitude),
|
||||
[this](Route const & route, RouterResultCode code) { OnRebuildRouteReady(route, code); },
|
||||
nullptr /* needMoreMapsCallback */, nullptr /* removeRouteCallback */,
|
||||
nullptr /* needMoreMapsCallback /, nullptr / removeRouteCallback */,
|
||||
RouterDelegate::kNoTimeout, SessionState::RouteRebuilding, true /* adjustToPrevRoute */);
|
||||
}
|
||||
}
|
||||
|
@ -1401,18 +1401,13 @@ void RoutingManager::LoadRoutePoints(LoadRouteHandler const & handler)
|
|||
[this, handler, points = std::move(points)]() mutable
|
||||
{
|
||||
ASSERT(m_bmManager != nullptr, ());
|
||||
// If we have found my position and the saved route used the user's position, we use my position as start point.
|
||||
bool routeUsedPosition = false;
|
||||
// If we have found my position, we use my position as start point.
|
||||
auto const & myPosMark = m_bmManager->MyPositionMark();
|
||||
auto editSession = m_bmManager->GetEditSession();
|
||||
editSession.ClearGroup(UserMark::Type::ROUTING);
|
||||
for (auto & p : points)
|
||||
{
|
||||
// Check if the saved route used the user's position
|
||||
if (p.m_replaceWithMyPositionAfterRestart && p.m_pointType == RouteMarkType::Start)
|
||||
routeUsedPosition = true;
|
||||
|
||||
if (p.m_replaceWithMyPositionAfterRestart && p.m_pointType == RouteMarkType::Start && myPosMark.HasPosition())
|
||||
if (p.m_pointType == RouteMarkType::Start && myPosMark.HasPosition())
|
||||
{
|
||||
RouteMarkData startPt;
|
||||
startPt.m_pointType = RouteMarkType::Start;
|
||||
|
@ -1426,9 +1421,9 @@ void RoutingManager::LoadRoutePoints(LoadRouteHandler const & handler)
|
|||
}
|
||||
}
|
||||
|
||||
// If we don't have my position and the saved route used it, save loading timestamp.
|
||||
// Probably we will get my position soon.
|
||||
if (routeUsedPosition && !myPosMark.HasPosition())
|
||||
// If we don't have my position, save loading timestamp. Probably
|
||||
// we will get my position soon.
|
||||
if (!myPosMark.HasPosition())
|
||||
m_loadRoutePointsTimestamp = chrono::steady_clock::now();
|
||||
|
||||
if (handler)
|
||||
|
@ -1574,4 +1569,4 @@ void RoutingManager::SetSubroutesVisibility(bool visible)
|
|||
bool RoutingManager::IsSpeedCamLimitExceeded() const
|
||||
{
|
||||
return m_routingSession.IsSpeedCamLimitExceeded();
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue