From 6b22c99c42392f825095975f9bc776ad984e870b Mon Sep 17 00:00:00 2001 From: hansemannn Date: Mon, 11 Mar 2019 23:49:12 +0100 Subject: [PATCH 01/44] =?UTF-8?q?feat(android):=20add=20=E2=80=9Epoiclick?= =?UTF-8?q?=E2=80=9C=20event?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- android/manifest | 2 +- android/src/ti/map/MapModule.java | 2 ++ android/src/ti/map/TiUIMapView.java | 23 ++++++++++++++++++++++- apidoc/View.yml | 25 +++++++++++++++++++++++++ 4 files changed, 50 insertions(+), 2 deletions(-) diff --git a/android/manifest b/android/manifest index 70b4ad76..f737ea55 100644 --- a/android/manifest +++ b/android/manifest @@ -2,7 +2,7 @@ # this is your module manifest and used by Titanium # during compilation, packaging, distribution, etc. # -version: 4.4.0 +version: 4.5.0 apiversion: 4 architectures: arm64-v8a armeabi-v7a x86 description: External version of Map module to support new Google Map v2 sdk diff --git a/android/src/ti/map/MapModule.java b/android/src/ti/map/MapModule.java index 07000275..b950f0a1 100644 --- a/android/src/ti/map/MapModule.java +++ b/android/src/ti/map/MapModule.java @@ -21,6 +21,7 @@ public class MapModule extends KrollModule { public static final String EVENT_MAP_CLICK = "mapclick"; + public static final String EVENT_POI_CLICK = "poiclick"; public static final String EVENT_PIN_CHANGE_DRAG_STATE = "pinchangedragstate"; public static final String EVENT_ON_SNAPSHOT_READY = "onsnapshotready"; public static final String EVENT_REGION_WILL_CHANGE = "regionwillchange"; @@ -68,6 +69,7 @@ public class MapModule extends KrollModule public static final String PROPERTY_CENTER = "center"; public static final String PROPERTY_RADIUS = "radius"; public static final String PROPERTY_INDOOR_ENABLED = "indoorEnabled"; + public static final String PROPERTY_PLACE_ID = "placeID"; @Kroll.constant public static final int NORMAL_TYPE = GoogleMap.MAP_TYPE_NORMAL; diff --git a/android/src/ti/map/TiUIMapView.java b/android/src/ti/map/TiUIMapView.java index 691b81b9..2cf25135 100644 --- a/android/src/ti/map/TiUIMapView.java +++ b/android/src/ti/map/TiUIMapView.java @@ -61,6 +61,7 @@ import com.google.android.gms.maps.model.LatLngBounds; import com.google.android.gms.maps.model.Marker; import com.google.android.gms.maps.model.MapStyleOptions; +import com.google.android.gms.maps.model.PointOfInterest; import com.google.maps.android.MarkerManager; import com.google.maps.android.clustering.ClusterManager; import com.google.maps.android.clustering.Cluster; @@ -70,7 +71,7 @@ public class TiUIMapView extends TiUIFragment GoogleMap.OnInfoWindowClickListener, GoogleMap.InfoWindowAdapter, GoogleMap.OnMapLongClickListener, GoogleMap.OnMapLoadedCallback, OnMapReadyCallback, GoogleMap.OnCameraMoveStartedListener, GoogleMap.OnCameraMoveListener, GoogleMap.OnCameraIdleListener, GoogleMap.OnMyLocationChangeListener, - ClusterManager.OnClusterClickListener, ClusterManager.OnClusterItemClickListener + GoogleMap.OnPoiClickListener, ClusterManager.OnClusterClickListener, ClusterManager.OnClusterItemClickListener { public static final String DEFAULT_COLLECTION_ID = "defaultCollection"; @@ -994,6 +995,20 @@ public void fireLongClickEvent(LatLng point) } } + public void firePOIClickEvent(PointOfInterest poi) + { + KrollDict d = new KrollDict(); + d.put(TiC.PROPERTY_LATITUDE, poi.latLng.latitude); + d.put(TiC.PROPERTY_LONGITUDE, poi.latLng.longitude); + d.put(TiC.PROPERTY_NAME, poi.name); + d.put(MapModule.PROPERTY_PLACE_ID, poi.placeId); + d.put(TiC.PROPERTY_TYPE, MapModule.EVENT_POI_CLICK); + d.put(TiC.PROPERTY_SOURCE, proxy); + if (proxy != null) { + proxy.fireEvent(MapModule.EVENT_POI_CLICK, d); + } + } + public void firePinChangeDragStateEvent(Marker marker, AnnotationProxy annoProxy, int dragState) { KrollDict d = new KrollDict(); @@ -1171,6 +1186,12 @@ public void onMapClick(LatLng point) } } + @Override + public void onPoiClick(PointOfInterest poi) + { + firePOIClickEvent(poi); + } + @Override public void onMapLongClick(LatLng point) { diff --git a/apidoc/View.yml b/apidoc/View.yml index 22421855..ca88c904 100644 --- a/apidoc/View.yml +++ b/apidoc/View.yml @@ -472,6 +472,31 @@ events: since: "6.2.0" platforms: [android, iphone, ipad] + - name: poiclick + summary: | + Fired when the user clicks on a point of interest on the map. + description: | + The `poiclick` event is fired when the user clicks on a point of interest of the map and returns + the longitude/latitude and name of that location. + properties: + - name: name + summary: The name of the point of interest. + type: String + + - name: placeID + summary: The Google place ID of the point of interest. + type: String + + - name: latitude + summary: The latitude of the clicked position. + type: Number + + - name: longitude + summary: The longitude of the clicked position. + type: Number + since: "8.1.0" + platforms: [android] + - name: regionwillchange since: { android: "6.2.0", iphone: "6.0.0", ipad: "6.0.0" } summary: | From 5e6f87040ea4829365e915c47e69a7d951fda318 Mon Sep 17 00:00:00 2001 From: hansemannn Date: Sat, 13 Jul 2019 15:50:15 +0200 Subject: [PATCH 02/44] fix: add poi-click listener to map instance --- android/src/ti/map/TiUIMapView.java | 33 ++++++++++++++++++++--------- android/src/ti/map/ViewProxy.java | 32 ++++++---------------------- 2 files changed, 30 insertions(+), 35 deletions(-) diff --git a/android/src/ti/map/TiUIMapView.java b/android/src/ti/map/TiUIMapView.java index 2cf25135..b8995139 100644 --- a/android/src/ti/map/TiUIMapView.java +++ b/android/src/ti/map/TiUIMapView.java @@ -225,6 +225,7 @@ public void onMapReady(GoogleMap gMap) map.setOnMapLongClickListener(this); map.setOnMapLoadedCallback(this); map.setOnMyLocationChangeListener(this); + map.setOnPoiClickListener(this); mClusterManager.setOnClusterClickListener(this); mClusterManager.setOnClusterItemClickListener(this); @@ -269,22 +270,18 @@ public void processMapProperties(KrollDict d) Object[] annotations = (Object[]) d.get(TiC.PROPERTY_ANNOTATIONS); addAnnotations(annotations); } - if (d.containsKey(MapModule.PROPERTY_POLYGONS)) { Object[] polygons = (Object[]) d.get(MapModule.PROPERTY_POLYGONS); addPolygons(polygons); } - if (d.containsKey(MapModule.PROPERTY_POLYLINES)) { Object[] polylines = (Object[]) d.get(MapModule.PROPERTY_POLYLINES); addPolylines(polylines); } - if (d.containsKey(MapModule.PROPERTY_CIRCLES)) { Object[] circles = (Object[]) d.get(MapModule.PROPERTY_CIRCLES); addCircles(circles); } - if (d.containsKey(TiC.PROPERTY_ENABLE_ZOOM_CONTROLS)) { setZoomControlsEnabled(TiConvert.toBoolean(d, TiC.PROPERTY_ENABLE_ZOOM_CONTROLS, true)); } @@ -303,6 +300,9 @@ public void processMapProperties(KrollDict d) if (d.containsKey(MapModule.PROPERTY_INDOOR_ENABLED)) { setIndoorEnabled(d.getBoolean(MapModule.PROPERTY_INDOOR_ENABLED)); } + if (d.containsKey(TiC.PROPERTY_PADDING)) { + setPadding(d.getKrollDict(TiC.PROPERTY_PADDING)); + } } @Override @@ -341,6 +341,8 @@ public void propertyChanged(String key, Object oldValue, Object newValue, KrollP setStyle(TiConvert.toString(newValue, "")); } else if (key.equals(MapModule.PROPERTY_INDOOR_ENABLED)) { setIndoorEnabled(TiConvert.toBoolean(newValue, true)); + } else if (key.equals(TiC.PROPERTY_PADDING)) { + setPadding(new KrollDict((HashMap) newValue)); } else { super.propertyChanged(key, oldValue, newValue, proxy); } @@ -454,14 +456,19 @@ protected void setTrafficEnabled(boolean enabled) } } - protected void setPadding(int left, int top, int right, int bottom) + protected void setPadding(KrollDict args) { + int left = TiConvert.toInt(args.getInt(TiC.PROPERTY_LEFT), 0); + int top = TiConvert.toInt(args.getInt(TiC.PROPERTY_TOP), 0); + int right = TiConvert.toInt(args.getInt(TiC.PROPERTY_RIGHT), 0); + int bottom = TiConvert.toInt(args.getInt(TiC.PROPERTY_BOTTOM), 0); + if (map != null) { map.setPadding(left, top, right, bottom); } } - protected void showAnnotations(Object[] annotations) { + protected void showAnnotations(Object[] annotations, int padding, boolean animated) { ArrayList markers = new ArrayList(); // Use supplied annotations first. If none available, select all (parity with iOS) @@ -478,13 +485,19 @@ protected void showAnnotations(Object[] annotations) { LatLngBounds.Builder builder = new LatLngBounds.Builder(); for (TiMarker marker : markers) { - builder.include(marker.getPosition()); + if (marker != null) { + builder.include(marker.getPosition()); + } } LatLngBounds bounds = builder.build(); - int padding = 30; - CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, padding); - map.animateCamera(cu); + CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngBounds(bounds, padding); + + if (animated) { + map.animateCamera(cameraUpdate); + } else { + map.moveCamera(cameraUpdate); + } } protected void setZoomControlsEnabled(boolean enabled) diff --git a/android/src/ti/map/ViewProxy.java b/android/src/ti/map/ViewProxy.java index e2b73048..ea8026a7 100644 --- a/android/src/ti/map/ViewProxy.java +++ b/android/src/ti/map/ViewProxy.java @@ -31,7 +31,7 @@ TiC.PROPERTY_REGION, TiC.PROPERTY_ANNOTATIONS, TiC.PROPERTY_ANIMATE, MapModule.PROPERTY_TRAFFIC, TiC.PROPERTY_STYLE, TiC.PROPERTY_ENABLE_ZOOM_CONTROLS, MapModule.PROPERTY_COMPASS_ENABLED, MapModule.PROPERTY_SCROLL_ENABLED, MapModule.PROPERTY_ZOOM_ENABLED, - MapModule.PROPERTY_POLYLINES }) + MapModule.PROPERTY_POLYLINES, TiC.PROPERTY_PADDING }) public class ViewProxy extends TiViewProxy implements AnnotationDelegate { private static final String TAG = "MapViewProxy"; @@ -310,7 +310,7 @@ public boolean handleMessage(Message msg) case MSG_SHOW_ANNOTATIONS: { result = ((AsyncResult) msg.obj); - handleShowAnnotations((Object[]) result.getArg()); + handleShowAnnotations((Object[]) result.getArg(), 30, false); result.setResult(null); return true; } @@ -416,15 +416,15 @@ private void handleSnapshot() } @Kroll.method - public void showAnnotations(Object annotations) { + public void showAnnotations(Object annotations, int padding, boolean animated) { if (TiApplication.isUIThread()) { - handleShowAnnotations(annotations); + handleShowAnnotations(annotations, padding, animated); } else { getMainHandler().obtainMessage(MSG_SHOW_ANNOTATIONS).sendToTarget(); } } - private void handleShowAnnotations(Object annotations) { + private void handleShowAnnotations(Object annotations, int padding, boolean animated) { if (!(annotations instanceof Object[])) { Log.e(TAG, "Invalid argument to addAnnotations", Log.DEBUG_MODE); return; @@ -433,7 +433,7 @@ private void handleShowAnnotations(Object annotations) { TiUIMapView mapView = (TiUIMapView) peekView(); if (mapView.getMap() != null) { - mapView.showAnnotations(annos); + mapView.showAnnotations(annos, padding, animated); } } @@ -1206,19 +1206,6 @@ public void refreshAnnotation(AnnotationProxy annotation) } } - // clang-format off - @Kroll.method - @Kroll.setProperty - public void setPadding(KrollDict padding) - // clang-format on - { - if (TiApplication.isUIThread()) { - handleSetPadding(padding); - } else { - getMainHandler().obtainMessage(MSG_SET_PADDING, padding).sendToTarget(); - } - } - private void addPreloadImageOverlay(ImageOverlayProxy proxy) { if (!(preloadOverlaysList.contains(proxy))) { @@ -1330,12 +1317,7 @@ public void handleSetPadding(KrollDict args) { TiUIView view = peekView(); if (view instanceof TiUIMapView) { - int left = TiConvert.toInt(args.getInt(TiC.PROPERTY_LEFT), 0); - int top = TiConvert.toInt(args.getInt(TiC.PROPERTY_TOP), 0); - int right = TiConvert.toInt(args.getInt(TiC.PROPERTY_RIGHT), 0); - int bottom = TiConvert.toInt(args.getInt(TiC.PROPERTY_BOTTOM), 0); - - ((TiUIMapView) view).setPadding(left, top, right, bottom); + ((TiUIMapView) view).setPadding(args); } } From bf2373e74191590327eda50aaed1ae3eafff0143 Mon Sep 17 00:00:00 2001 From: hansemannn Date: Fri, 2 Aug 2019 10:52:46 +0200 Subject: [PATCH 03/44] fix: fix null-check in MapView#zoom --- android/src/ti/map/ViewProxy.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/android/src/ti/map/ViewProxy.java b/android/src/ti/map/ViewProxy.java index ea8026a7..ba9ea89d 100644 --- a/android/src/ti/map/ViewProxy.java +++ b/android/src/ti/map/ViewProxy.java @@ -1149,11 +1149,16 @@ public float getZoom() private float handleGetZoom() { TiUIView view = peekView(); + if (view instanceof TiUIMapView) { - return ((TiUIMapView) view).getMap().getCameraPosition().zoom; - } else { - return 0; + GoogleMap mapView = ((TiUIMapView) view).getMap(); + + if (mapView != null) { + return mapView.getCameraPosition().zoom; + } } + + return 0; } @Kroll.method From 7cef29e85ec0a7086244e6eb3b687ba9b7e7c3f3 Mon Sep 17 00:00:00 2001 From: hansemannn Date: Sat, 3 Aug 2019 00:09:41 +0200 Subject: [PATCH 04/44] =?UTF-8?q?fix:=20add=20=E2=80=9EconatinsCoordinate?= =?UTF-8?q?=E2=80=9C=20method=20for=20parity?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- android/src/ti/map/TiUIMapView.java | 11 +++++++++++ android/src/ti/map/ViewProxy.java | 24 ++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/android/src/ti/map/TiUIMapView.java b/android/src/ti/map/TiUIMapView.java index b8995139..efc9b552 100644 --- a/android/src/ti/map/TiUIMapView.java +++ b/android/src/ti/map/TiUIMapView.java @@ -948,6 +948,17 @@ public void changeZoomLevel(int delta) moveCamera(camUpdate, animate); } + protected boolean containsCoordinate(KrollDict coordinate) { + if (map == null) { + return false; + } + + LatLngBounds mapBounds = map.getProjection().getVisibleRegion().latLngBounds; + LatLng nativeCoordinate = new LatLng(coordinate.getDouble("latitude").doubleValue(), coordinate.getDouble("longitude").doubleValue()); + + return mapBounds.contains(nativeCoordinate); + } + public void fireShapeClickEvent(LatLng clickPosition, IShape shapeProxy, String clickSource) { diff --git a/android/src/ti/map/ViewProxy.java b/android/src/ti/map/ViewProxy.java index ba9ea89d..2e5d79fa 100644 --- a/android/src/ti/map/ViewProxy.java +++ b/android/src/ti/map/ViewProxy.java @@ -25,6 +25,9 @@ import android.app.Activity; import android.os.Message; +import com.google.android.gms.maps.GoogleMap; +import com.google.android.gms.maps.model.LatLng; + @Kroll. proxy(creatableInModule = MapModule.class, propertyAccessors = { TiC.PROPERTY_USER_LOCATION, MapModule.PROPERTY_USER_LOCATION_BUTTON, TiC.PROPERTY_MAP_TYPE, @@ -55,6 +58,7 @@ public class ViewProxy extends TiViewProxy implements AnnotationDelegate private static final int MSG_SET_PADDING = MSG_FIRST_ID + 514; private static final int MSG_ZOOM = MSG_FIRST_ID + 515; private static final int MSG_SHOW_ANNOTATIONS = MSG_FIRST_ID + 516; + private static final int MSG_CONTAINS_COORDINATE = MSG_FIRST_ID + 517; private static final int MSG_ADD_POLYGON = MSG_FIRST_ID + 901; private static final int MSG_REMOVE_POLYGON = MSG_FIRST_ID + 902; @@ -315,6 +319,12 @@ public boolean handleMessage(Message msg) return true; } + case MSG_CONTAINS_COORDINATE: { + result = ((AsyncResult) msg.obj); + result.setResult(Boolean.valueOf(handleContainsCoordinate((KrollDict)result.getArg()))); + return true; + } + default: { return super.handleMessage(msg); } @@ -1133,6 +1143,20 @@ public void handleZoom(int delta) } } + @Kroll.method + public boolean containsCoordinate(KrollDict coordinate) + { + return handleContainsCoordinate(coordinate); + } + + private boolean handleContainsCoordinate(KrollDict coordinate) { + TiUIView view = peekView(); + if ((view instanceof TiUIMapView)) { + return ((TiUIMapView)view).containsCoordinate(coordinate); + } + return false; + } + // clang-format off @Kroll.method @Kroll.getProperty From 2a2ba17c0404995858ea35dc60aac56dd60ea3a1 Mon Sep 17 00:00:00 2001 From: hansemannn Date: Sat, 31 Aug 2019 17:00:15 +0200 Subject: [PATCH 05/44] refactor: remove old xcode version guards --- ios/Classes/TiMapAnnotationProxy.m | 20 ----- ios/Classes/TiMapCircleProxy.m | 4 +- ios/Classes/TiMapMarkerAnnotationView.h | 2 - ios/Classes/TiMapMarkerAnnotationView.m | 2 - ios/Classes/TiMapModule.h | 6 -- ios/Classes/TiMapModule.m | 19 ----- ios/Classes/TiMapPolygonProxy.m | 4 +- ios/Classes/TiMapPolylineProxy.m | 2 +- ios/Classes/TiMapRouteProxy.m | 12 +-- ios/Classes/TiMapView.h | 6 +- ios/Classes/TiMapView.m | 103 ++++++------------------ ios/Classes/TiMapViewProxy.h | 4 +- ios/Classes/TiMapViewProxy.m | 4 +- ios/TiMap_Prefix.pch | 6 -- 14 files changed, 34 insertions(+), 160 deletions(-) diff --git a/ios/Classes/TiMapAnnotationProxy.m b/ios/Classes/TiMapAnnotationProxy.m index 9de87efe..33ccfa56 100644 --- a/ios/Classes/TiMapAnnotationProxy.m +++ b/ios/Classes/TiMapAnnotationProxy.m @@ -234,29 +234,16 @@ - (id)nativePinColor id current = [self valueForUndefinedKey:@"pincolor"]; if ([current isKindOfClass:[NSString class]]) { -#ifdef __IPHONE_9_0 return [[TiUtils colorValue:current] color]; -#else - return MKPinAnnotationColorRed; -#endif } switch ([TiUtils intValue:current def:TiMapAnnotationPinColorRed]) { case TiMapAnnotationPinColorGreen: { -#ifdef __IPHONE_9_0 return [MKPinAnnotationView greenPinColor]; -#else - return MKPinAnnotationColorGreen; -#endif } case TiMapAnnotationPinColorPurple: { -#ifdef __IPHONE_9_0 return [MKPinAnnotationView purplePinColor]; -#else - return MKPinAnnotationColorPurple; -#endif } -#ifdef __IPHONE_9_0 case TiMapAnnotationPinColorBlue: return [UIColor blueColor]; case TiMapAnnotationPinColorCyan: @@ -275,14 +262,9 @@ - (id)nativePinColor return [UIColor roseColor]; case TiMapAnnotationPinColorViolet: return [UIColor violetColor]; -#endif case TiMapAnnotationPinColorRed: default: { -#ifdef __IPHONE_9_0 return [MKPinAnnotationView redPinColor]; -#else - return MKPinAnnotationColorRed; -#endif } } } @@ -493,7 +475,6 @@ - (void)setAnnotationDisplayPriority:(id)displayPriority } } -#if IS_IOS_11 - (void)setClusterIdentifier:(id)clusterIdentifier { id current = [self valueForUndefinedKey:@"clusterIdentifier"]; @@ -502,7 +483,6 @@ - (void)setClusterIdentifier:(id)clusterIdentifier [self setNeedsRefreshingWithSelection:YES]; } } -#endif - (void)setCustomView:(id)customView { diff --git a/ios/Classes/TiMapCircleProxy.m b/ios/Classes/TiMapCircleProxy.m index bffe2b38..f0563e7b 100644 --- a/ios/Classes/TiMapCircleProxy.m +++ b/ios/Classes/TiMapCircleProxy.m @@ -86,7 +86,7 @@ - (void)setFillColor:(id)value if (fillColor != nil) { RELEASE_TO_NIL(fillColor); } - fillColor = [[TiColor colorNamed:value] retain]; + fillColor = [[TiUtils colorValue:value] retain]; [[self circleRenderer] setFillColor:(fillColor == nil ? [UIColor blackColor] : [fillColor color])]; [self replaceValue:value forKey:@"fillColor" notification:NO]; } @@ -96,7 +96,7 @@ - (void)setStrokeColor:(id)value if (strokeColor != nil) { RELEASE_TO_NIL(strokeColor); } - strokeColor = [[TiColor colorNamed:value] retain]; + strokeColor = [[TiUtils colorValue:value] retain]; [[self circleRenderer] setStrokeColor:(strokeColor == nil ? [UIColor blackColor] : [strokeColor color])]; [self replaceValue:value forKey:@"strokeColor" notification:NO]; } diff --git a/ios/Classes/TiMapMarkerAnnotationView.h b/ios/Classes/TiMapMarkerAnnotationView.h index 79961cf9..e3b5fa06 100644 --- a/ios/Classes/TiMapMarkerAnnotationView.h +++ b/ios/Classes/TiMapMarkerAnnotationView.h @@ -4,7 +4,6 @@ * Licensed under the terms of the Apache Public License * Please see the LICENSE included with this distribution for details. */ -#if IS_IOS_11 #import "TiBase.h" #import "TiMapView.h" #import @@ -18,4 +17,3 @@ - (NSString *)lastHitName; @end -#endif diff --git a/ios/Classes/TiMapMarkerAnnotationView.m b/ios/Classes/TiMapMarkerAnnotationView.m index 1b51e8a3..fd27b006 100644 --- a/ios/Classes/TiMapMarkerAnnotationView.m +++ b/ios/Classes/TiMapMarkerAnnotationView.m @@ -4,7 +4,6 @@ * Licensed under the terms of the Apache Public License * Please see the LICENSE included with this distribution for details. */ -#if IS_IOS_11 #import "TiMapMarkerAnnotationView.h" #import "TiMapView.h" @@ -63,4 +62,3 @@ - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event return result; } @end -#endif diff --git a/ios/Classes/TiMapModule.h b/ios/Classes/TiMapModule.h index 6e1aa5ac..7b0d2d36 100644 --- a/ios/Classes/TiMapModule.h +++ b/ios/Classes/TiMapModule.h @@ -11,19 +11,13 @@ UIColor *colorRed; } -+ (void)logAddedIniOS7Warning:(NSString *)name; - @property (nonatomic, readonly) NSNumber *STANDARD_TYPE; @property (nonatomic, readonly) NSNumber *NORMAL_TYPE; // For parity with Android @property (nonatomic, readonly) NSNumber *SATELLITE_TYPE; @property (nonatomic, readonly) NSNumber *HYBRID_TYPE; -#ifdef __IPHONE_9_0 @property (nonatomic, readonly) NSNumber *HYBRID_FLYOVER_TYPE; @property (nonatomic, readonly) NSNumber *SATELLITE_FLYOVER_TYPE; -#endif -#if IS_IOS_11 @property (nonatomic, readonly) NSNumber *MUTED_STANDARD_TYPE; -#endif @property (nonatomic, readonly) NSNumber *ANNOTATION_RED; @property (nonatomic, readonly) NSNumber *ANNOTATION_GREEN; diff --git a/ios/Classes/TiMapModule.m b/ios/Classes/TiMapModule.m index a0da72cc..703b70ab 100644 --- a/ios/Classes/TiMapModule.m +++ b/ios/Classes/TiMapModule.m @@ -32,13 +32,6 @@ - (NSString *)apiName return @"Ti.Map"; } -#pragma mark Utils - -+ (void)logAddedIniOS7Warning:(NSString *)name -{ - NSLog(@"[WARN] `%@` is only supported on iOS 7 and greater.", name); -} - #pragma mark Public APIs - (TiMapViewProxy *)createView:(id)args @@ -48,10 +41,6 @@ - (TiMapViewProxy *)createView:(id)args - (TiMapCameraProxy *)createCamera:(id)args { - if (![TiUtils isIOS7OrGreater]) { - [TiMapModule logAddedIniOS7Warning:@"createCamera()"]; - return nil; - } return [[[TiMapCameraProxy alloc] _initWithPageContext:[self pageContext] args:args] autorelease]; } @@ -59,17 +48,12 @@ - (TiMapCameraProxy *)createCamera:(id)args MAKE_SYSTEM_PROP(NORMAL_TYPE, MKMapTypeStandard); // For parity with Android MAKE_SYSTEM_PROP(SATELLITE_TYPE, MKMapTypeSatellite); MAKE_SYSTEM_PROP(HYBRID_TYPE, MKMapTypeHybrid); -#ifdef __IPHONE_9_0 MAKE_SYSTEM_PROP(HYBRID_FLYOVER_TYPE, MKMapTypeHybridFlyover); MAKE_SYSTEM_PROP(SATELLITE_FLYOVER_TYPE, MKMapTypeSatelliteFlyover); -#endif -#if IS_IOS_11 MAKE_SYSTEM_PROP(MUTED_STANDARD_TYPE, MKMapTypeMutedStandard); -#endif MAKE_SYSTEM_PROP(ANNOTATION_RED, TiMapAnnotationPinColorRed); MAKE_SYSTEM_PROP(ANNOTATION_GREEN, TiMapAnnotationPinColorGreen); MAKE_SYSTEM_PROP(ANNOTATION_PURPLE, TiMapAnnotationPinColorPurple); -#ifdef __IPHONE_9_0 MAKE_SYSTEM_PROP(ANNOTATION_AZURE, TiMapAnnotationPinColorAzure); MAKE_SYSTEM_PROP(ANNOTATION_BLUE, TiMapAnnotationPinColorBlue); MAKE_SYSTEM_PROP(ANNOTATION_CYAN, TiMapAnnotationPinColorCyan); @@ -78,7 +62,6 @@ - (TiMapCameraProxy *)createCamera:(id)args MAKE_SYSTEM_PROP(ANNOTATION_ROSE, TiMapAnnotationPinColorRose); MAKE_SYSTEM_PROP(ANNOTATION_VIOLET, TiMapAnnotationPinColorViolet); MAKE_SYSTEM_PROP(ANNOTATION_YELLOW, TiMapAnnotationPinColorYellow); -#endif MAKE_SYSTEM_PROP(ANNOTATION_DRAG_STATE_NONE, MKAnnotationViewDragStateNone); MAKE_SYSTEM_PROP(ANNOTATION_DRAG_STATE_START, MKAnnotationViewDragStateStarting); @@ -92,7 +75,6 @@ - (TiMapCameraProxy *)createCamera:(id)args MAKE_SYSTEM_PROP(POLYLINE_PATTERN_DASHED, TiMapOverlyPatternTypeDashed); MAKE_SYSTEM_PROP(POLYLINE_PATTERN_DOTTED, TiMapOverlyPatternTypeDotted); -#if IS_IOS_11 MAKE_SYSTEM_PROP(FEATURE_VISIBILITY_ADAPTIVE, MKFeatureVisibilityAdaptive); MAKE_SYSTEM_PROP(FEATURE_VISIBILITY_HIDDEN, MKFeatureVisibilityHidden); MAKE_SYSTEM_PROP(FEATURE_VISIBILITY_VISIBLE, MKFeatureVisibilityVisible); @@ -103,6 +85,5 @@ - (TiMapCameraProxy *)createCamera:(id)args MAKE_SYSTEM_PROP_DBL(FEATURE_DISPLAY_PRIORITY_REQUIRED, MKFeatureDisplayPriorityRequired); MAKE_SYSTEM_PROP_DBL(FEATURE_DISPLAY_PRIORITY_DEFAULT_HIGH, MKFeatureDisplayPriorityDefaultHigh); MAKE_SYSTEM_PROP_DBL(FEATURE_DISPLAY_PRIORITY_DEFAULT_LOW, MKFeatureDisplayPriorityDefaultLow); -#endif @end diff --git a/ios/Classes/TiMapPolygonProxy.m b/ios/Classes/TiMapPolygonProxy.m index b9e64c98..3e3dc7c6 100644 --- a/ios/Classes/TiMapPolygonProxy.m +++ b/ios/Classes/TiMapPolygonProxy.m @@ -143,7 +143,7 @@ - (void)setFillColor:(id)value if (fillColor != nil) { RELEASE_TO_NIL(fillColor); } - fillColor = [[TiColor colorNamed:value] retain]; + fillColor = [[TiUtils colorValue:value] retain]; [self applyFillColor]; } @@ -152,7 +152,7 @@ - (void)setStrokeColor:(id)value if (strokeColor != nil) { RELEASE_TO_NIL(strokeColor); } - strokeColor = [[TiColor colorNamed:value] retain]; + strokeColor = [[TiUtils colorValue:value] retain]; [self applyStrokeColor]; } diff --git a/ios/Classes/TiMapPolylineProxy.m b/ios/Classes/TiMapPolylineProxy.m index 389323b3..d98dded3 100644 --- a/ios/Classes/TiMapPolylineProxy.m +++ b/ios/Classes/TiMapPolylineProxy.m @@ -129,7 +129,7 @@ - (void)setStrokeColor:(id)value if (strokeColor != nil) { RELEASE_TO_NIL(strokeColor); } - strokeColor = [[[TiColor colorNamed:value] _color] retain]; + strokeColor = [[[TiUtils colorValue:value] _color] retain]; [self applyStrokeColor]; } diff --git a/ios/Classes/TiMapRouteProxy.m b/ios/Classes/TiMapRouteProxy.m index cb53170b..02b5008a 100644 --- a/ios/Classes/TiMapRouteProxy.m +++ b/ios/Classes/TiMapRouteProxy.m @@ -65,11 +65,7 @@ - (void)processPoints:(NSArray *)points routeLine = [[MKPolyline polylineWithPoints:pointArray count:[points count]] retain]; free(pointArray); - // Using the TiMKOverlayPathUniversal protocol so Xcode can resolve methods - // MKPolylineView is deprecated in iOS 7, still here for backward compatibility. - // MKPolylineView can be removed when support is dropped for iOS 6 and below. - Class rendererClass = ([TiUtils isIOS7OrGreater]) ? [MKPolylineRenderer class] : [MKPolylineView class]; - routeRenderer = [(id)[[rendererClass alloc] initWithPolyline:routeLine] retain]; + routeRenderer = [(id)[[MKPolylineRenderer alloc] initWithPolyline:routeLine] retain]; [self applyColor]; [self applyWidth]; } @@ -105,7 +101,7 @@ - (void)setColor:(id)value if (color != nil) { RELEASE_TO_NIL(color); } - color = [[TiColor colorNamed:value] retain]; + color = [[TiUtils colorValue:value] retain]; [self applyColor]; } @@ -117,10 +113,6 @@ - (void)setWidth:(id)value - (void)setLevel:(id)value { - // level is not supported before iOS 7 but it doesn't hurt to capture it. - if (![TiUtils isIOS7OrGreater]) { - [TiMapModule logAddedIniOS7Warning:@"level"]; - } level = [[TiUtils numberFromObject:value] unsignedIntegerValue]; } diff --git a/ios/Classes/TiMapView.h b/ios/Classes/TiMapView.h index a57ec55d..540be488 100644 --- a/ios/Classes/TiMapView.h +++ b/ios/Classes/TiMapView.h @@ -32,10 +32,8 @@ NSMutableArray *circleProxies; NSMutableArray *polylineProxies; NSMutableArray *imageOverlayProxies; - -#if IS_IOS_11 NSMutableDictionary *clusterAnnotations; -#endif + //selected annotation MKAnnotationView *selectedAnnotation; @@ -95,9 +93,7 @@ - (void)removeAllImageOverlays; - (void)firePinChangeDragState:(MKAnnotationView *)pinview newState:(MKAnnotationViewDragState)newState fromOldState:(MKAnnotationViewDragState)oldState; -#if IS_IOS_11 - (void)setClusterAnnotation:(TiMapAnnotationProxy *)annotation forMembers:(NSArray *)members; -#endif #pragma mark Utils - (void)addOverlay:(MKPolyline *)polyline level:(MKOverlayLevel)level; diff --git a/ios/Classes/TiMapView.m b/ios/Classes/TiMapView.m index 4ed9bf25..0396997a 100644 --- a/ios/Classes/TiMapView.m +++ b/ios/Classes/TiMapView.m @@ -43,9 +43,8 @@ - (void)dealloc RELEASE_TO_NIL(polylineProxies); RELEASE_TO_NIL(circleProxies); RELEASE_TO_NIL(imageOverlayProxies); -#if IS_IOS_11 RELEASE_TO_NIL(clusterAnnotations); -#endif + [super dealloc]; } @@ -79,9 +78,6 @@ - (MKMapView *)map map.delegate = self; map.userInteractionEnabled = YES; map.autoresizingMask = UIViewAutoresizingNone; - if (![TiUtils isIOS8OrGreater]) { - map.showsUserLocation = [TiUtils boolValue:[self.proxy valueForKey:@"userLocation"] def:NO]; - } [self addSubview:map]; mapObjects2View = CFDictionaryCreateMutable(NULL, 10, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); [self registerTouchEvents]; @@ -456,25 +452,19 @@ - (void)setUserLocation_:(id)value // Release the locationManager in case it was already created RELEASE_TO_NIL(locationManager); BOOL userLocation = [TiUtils boolValue:value def:NO]; - // if userLocation is true and this is iOS 8 or greater, then ask for permission - if (userLocation && [TiUtils isIOS8OrGreater]) { - // the locationManager needs to be created to permissions - locationManager = [[CLLocationManager alloc] init]; - // set the "userLocation" on the delegate callback to avoid console warnings from the OS - locationManager.delegate = self; - if ([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"]) { - [locationManager requestAlwaysAuthorization]; - } else if ([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"]) { - [locationManager requestWhenInUseAuthorization]; - } else { - NSLog(@"[ERROR] The keys NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription are not defined in your tiapp.xml. Starting with iOS 8 this is required."); - } - // Create the map - [self map]; + // the locationManager needs to be created to permissions + locationManager = [[CLLocationManager alloc] init]; + // set the "userLocation" on the delegate callback to avoid console warnings from the OS + locationManager.delegate = self; + if ([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"]) { + [locationManager requestAlwaysAuthorization]; + } else if ([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"]) { + [locationManager requestWhenInUseAuthorization]; } else { - // else, just apply the userLocation - [self map].showsUserLocation = userLocation; + NSLog(@"[ERROR] The keys NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription are not defined in your tiapp.xml. Starting with iOS 8 this is required."); } + // Create the map + [self map]; } - (void)setLocation_:(id)location @@ -794,44 +784,26 @@ - (void)setShowsCompass_:(id)value - (void)setCompassEnabled_:(id)value { - if ([TiUtils isIOS9OrGreater] == YES) { -#ifdef __IPHONE_9_0 - TiThreadPerformOnMainThread(^{ - [[self map] setShowsCompass:[TiUtils boolValue:value]]; - }, - YES); -#endif - } else { - NSLog(@"[WARN] The property 'compassEnabled' is only available on iOS 9 and later."); - } + TiThreadPerformOnMainThread(^{ + [[self map] setShowsCompass:[TiUtils boolValue:value]]; + }, + YES); } - (void)setShowsScale_:(id)value { - if ([TiUtils isIOS9OrGreater] == YES) { -#ifdef __IPHONE_9_0 - TiThreadPerformOnMainThread(^{ - [self map].showsScale = [TiUtils boolValue:value]; - }, - YES); -#endif - } else { - NSLog(@"[WARN] The property 'showsScale' is only available on iOS 9 and later."); - } + TiThreadPerformOnMainThread(^{ + [self map].showsScale = [TiUtils boolValue:value]; + }, + YES); } - (void)setShowsTraffic_:(id)value { - if ([TiUtils isIOS9OrGreater] == YES) { -#ifdef __IPHONE_9_0 - TiThreadPerformOnMainThread(^{ - [self map].showsTraffic = [TiUtils boolValue:value]; - }, - YES); -#endif - } else { - NSLog(@"[WARN] The property 'showsTraffic' is only available on iOS 9 and later."); - } + TiThreadPerformOnMainThread(^{ + [self map].showsTraffic = [TiUtils boolValue:value]; + }, + YES); } - (void)showAllAnnotations:(id)value @@ -897,7 +869,6 @@ - (void)showAnnotations:(id)args NO); } -#if IS_IOS_11 - (void)setClusterAnnotation:(TiMapAnnotationProxy *)annotation forMembers:(NSArray *)members { if (!clusterAnnotations) { @@ -916,7 +887,6 @@ - (TiMapAnnotationProxy *)clusterAnnotationProxyForMembers:(NSArray *)members { return [clusterAnnotations objectForKey:members]; } -#endif #pragma mark Utils @@ -1146,10 +1116,8 @@ - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotationProxy:(TiMap if (annView == nil) { if ([identifier isEqualToString:@"timap-customView"]) { annView = [[[TiMapCustomAnnotationView alloc] initWithAnnotation:ann reuseIdentifier:identifier map:self] autorelease]; -#if IS_IOS_11 } else if ([TiMapView isiOS11OrGreater] && [identifier isEqualToString:@"timap-marker"]) { annView = [[[TiMapMarkerAnnotationView alloc] initWithAnnotation:ann reuseIdentifier:identifier map:self] autorelease]; -#endif } else if ([identifier isEqualToString:@"timap-image"]) { annView = [[[TiMapImageAnnotationView alloc] initWithAnnotation:ann reuseIdentifier:identifier map:self image:image] autorelease]; } else { @@ -1160,7 +1128,6 @@ - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotationProxy:(TiMap [((TiMapCustomAnnotationView *)annView) setProxy:customView]; } else if ([identifier isEqualToString:@"timap-image"]) { annView.image = image; -#if IS_IOS_11 } else if ([TiMapView isiOS11OrGreater] && [identifier isEqualToString:@"timap-marker"]) { MKMarkerAnnotationView *markerView = (MKMarkerAnnotationView *)annView; markerView.markerTintColor = [[TiUtils colorValue:[ann valueForUndefinedKey:@"markerColor"]] color]; @@ -1171,15 +1138,10 @@ - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotationProxy:(TiMap markerView.selectedGlyphImage = [TiUtils image:[ann valueForUndefinedKey:@"markerSelectedGlyphImage"] proxy:ann]; markerView.titleVisibility = [TiUtils intValue:[ann valueForUndefinedKey:@"markerTitleVisibility"]]; markerView.subtitleVisibility = [TiUtils intValue:[ann valueForUndefinedKey:@"markerSubtitleVisibility"]]; -#endif } else { MKPinAnnotationView *pinview = (MKPinAnnotationView *)annView; -#ifdef __IPHONE_9_0 pinview.pinTintColor = [ann nativePinColor]; -#else - pinview.pinColor = [ann nativePinColor]; -#endif pinview.animatesDrop = [ann animatesDrop] && ![ann placed]; annView.calloutOffset = CGPointMake(-8, 0); } @@ -1187,13 +1149,11 @@ - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotationProxy:(TiMap annView.enabled = YES; annView.centerOffset = ann.offset; -#if IS_IOS_11 if ([TiMapView isiOS11OrGreater]) { annView.clusteringIdentifier = [ann valueForUndefinedKey:@"clusterIdentifier"]; annView.collisionMode = [TiUtils intValue:[ann valueForUndefinedKey:@"collisionMode"]]; annView.displayPriority = [TiUtils floatValue:[ann valueForUndefinedKey:@"annotationDisplayPriority"] def:1000]; } -#endif UIView *left = [ann leftViewAccessory]; UIView *right = [ann rightViewAccessory]; @@ -1202,21 +1162,10 @@ - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotationProxy:(TiMap if (left != nil) { annView.leftCalloutAccessoryView = left; - } else { - //ios7 requires this to be explicitly set as nil if nil - if (![TiUtils isIOS8OrGreater]) { - annView.leftCalloutAccessoryView = nil; - } } if (right != nil) { annView.rightCalloutAccessoryView = right; - } else { - //ios7 requires this to be explicitly set as nil if nil - - if (![TiUtils isIOS8OrGreater]) { - annView.rightCalloutAccessoryView = nil; - } } [annView setDraggable:[TiUtils boolValue:[ann valueForUndefinedKey:@"draggable"]]]; @@ -1253,7 +1202,6 @@ - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id> *)memberAnnotations { MKClusterAnnotation *annotation = [[MKClusterAnnotation alloc] initWithMemberAnnotations:memberAnnotations]; @@ -1281,7 +1227,6 @@ - (MKClusterAnnotation *)mapView:(MKMapView *)mapView clusterAnnotationForMember } return annotation; } -#endif // mapView:didAddAnnotationViews: is called after the annotation views have been added and positioned in the map. // The delegate can implement this method to animate the adding of the annotations views. diff --git a/ios/Classes/TiMapViewProxy.h b/ios/Classes/TiMapViewProxy.h index 66a4ba0e..613b7eb2 100644 --- a/ios/Classes/TiMapViewProxy.h +++ b/ios/Classes/TiMapViewProxy.h @@ -64,8 +64,6 @@ - (void)addImageOverlays:(id)args; - (void)removeImageOverlay:(id)arg; - (void)removeAllImageOverlays:(id)args; - -#if IS_IOS_11 - (void)setClusterAnnotation:(id)args; -#endif + @end diff --git a/ios/Classes/TiMapViewProxy.m b/ios/Classes/TiMapViewProxy.m index 4113cba9..b34290b4 100644 --- a/ios/Classes/TiMapViewProxy.m +++ b/ios/Classes/TiMapViewProxy.m @@ -821,7 +821,6 @@ - (void)setImageOverlays:(id)args } } -#if IS_IOS_11 - (void)setClusterAnnotation:(id)args { ENSURE_DICT(args); @@ -834,9 +833,8 @@ - (void)setClusterAnnotation:(id)args [(TiMapView *)[self view] setClusterAnnotation:annotationProxy forMembers:memberAnnotations]; } } -#endif -#pragma mark Public APIs iOS 7 +#pragma mark Public API's - (TiMapCameraProxy *)camera { diff --git a/ios/TiMap_Prefix.pch b/ios/TiMap_Prefix.pch index b2bc9956..8bec24fa 100644 --- a/ios/TiMap_Prefix.pch +++ b/ios/TiMap_Prefix.pch @@ -2,9 +2,3 @@ #ifdef __OBJC__ #import #endif - -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 -#define IS_IOS_11 true -#else -#define IS_IOS_11 false -#endif From fd5a51c96336484c67a510552efdc1f51b27247e Mon Sep 17 00:00:00 2001 From: hansemannn Date: Sat, 31 Aug 2019 17:22:31 +0200 Subject: [PATCH 06/44] refactor: use TitaniumKit imports, fix all warnings and leaks --- ios/Classes/TiMapAnnotationProxy.h | 3 +- ios/Classes/TiMapAnnotationProxy.m | 8 +-- ios/Classes/TiMapCameraProxy.h | 2 +- ios/Classes/TiMapCameraProxy.m | 2 +- ios/Classes/TiMapCircleProxy.h | 3 +- ios/Classes/TiMapCustomAnnotationView.h | 5 +- ios/Classes/TiMapCustomAnnotationView.m | 3 +- ios/Classes/TiMapImageAnnotationView.h | 4 +- ios/Classes/TiMapImageAnnotationView.m | 1 - ios/Classes/TiMapImageOverlayProxy.h | 2 +- ios/Classes/TiMapImageOverlayProxy.m | 1 - ios/Classes/TiMapImageOverlayRenderer.h | 1 + ios/Classes/TiMapImageOverlayRenderer.m | 1 - ios/Classes/TiMapMarkerAnnotationView.h | 4 +- ios/Classes/TiMapModule.h | 2 +- ios/Classes/TiMapPinAnnotationView.h | 4 +- ios/Classes/TiMapPolygonProxy.h | 3 +- ios/Classes/TiMapPolygonProxy.m | 3 + ios/Classes/TiMapPolylineProxy.h | 11 +--- ios/Classes/TiMapPolylineProxy.m | 4 ++ ios/Classes/TiMapRouteProxy.h | 3 +- ios/Classes/TiMapRouteProxy.m | 2 - ios/Classes/TiMapSnapshotterProxy.h | 2 +- ios/Classes/TiMapSnapshotterProxy.m | 4 +- ios/Classes/TiMapView.h | 5 +- ios/Classes/TiMapView.m | 29 ++++------ ios/Classes/TiMapViewProxy.h | 2 +- ios/map.xcodeproj/project.pbxproj | 77 +++++++++++++++++++++---- ios/titanium.xcconfig | 9 +-- 29 files changed, 119 insertions(+), 81 deletions(-) diff --git a/ios/Classes/TiMapAnnotationProxy.h b/ios/Classes/TiMapAnnotationProxy.h index 2b385abb..51506345 100644 --- a/ios/Classes/TiMapAnnotationProxy.h +++ b/ios/Classes/TiMapAnnotationProxy.h @@ -5,8 +5,7 @@ * Please see the LICENSE included with this distribution for details. */ -#import "TiBase.h" -#import "TiViewProxy.h" +#import #import @class TiMapViewProxy; diff --git a/ios/Classes/TiMapAnnotationProxy.m b/ios/Classes/TiMapAnnotationProxy.m index 33ccfa56..4a78717c 100644 --- a/ios/Classes/TiMapAnnotationProxy.m +++ b/ios/Classes/TiMapAnnotationProxy.m @@ -6,14 +6,11 @@ */ #import "TiMapAnnotationProxy.h" -#import "ImageLoader.h" #import "TiButtonUtil.h" #import "TiMapConstants.h" #import "TiMapView.h" #import "TiMapViewProxy.h" #import "TiUIiOSPreviewContextProxy.h" -#import "TiUtils.h" -#import "TiViewProxy.h" #import "UIColor+AndroidHueParity.h" @implementation TiMapAnnotationProxy @@ -214,7 +211,7 @@ - (id)hidden - (id)pincolor { - return NUMINT([self valueForUndefinedKey:@"pincolor"]); + return NUMINT((int)[self valueForUndefinedKey:@"pincolor"]); } - (void)setPincolor:(id)color @@ -338,6 +335,8 @@ - (void)setLeftView:(id)leftview } } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wundeclared-selector" - (void)setPreviewContext:(id)previewContext { Class TiUIiOSPreviewContextProxy = NSClassFromString(@"TiUIiOSPreviewContextProxy"); @@ -366,6 +365,7 @@ - (void)setPreviewContext:(id)previewContext [self setNeedsRefreshingWithSelection:YES]; } } +#pragma clang diagnostic pop - (void)setImage:(id)image { diff --git a/ios/Classes/TiMapCameraProxy.h b/ios/Classes/TiMapCameraProxy.h index 3a5b3526..95eaf8dc 100644 --- a/ios/Classes/TiMapCameraProxy.h +++ b/ios/Classes/TiMapCameraProxy.h @@ -5,7 +5,7 @@ * Please see the LICENSE included with this distribution for details. */ -#import "TiProxy.h" +#import #import @interface TiMapCameraProxy : TiProxy { diff --git a/ios/Classes/TiMapCameraProxy.m b/ios/Classes/TiMapCameraProxy.m index be119926..d448609b 100644 --- a/ios/Classes/TiMapCameraProxy.m +++ b/ios/Classes/TiMapCameraProxy.m @@ -6,7 +6,7 @@ */ #import "TiMapCameraProxy.h" -#import "TiUtils.h" +#import @implementation TiMapCameraProxy diff --git a/ios/Classes/TiMapCircleProxy.h b/ios/Classes/TiMapCircleProxy.h index 8f3662f0..e83e2768 100644 --- a/ios/Classes/TiMapCircleProxy.h +++ b/ios/Classes/TiMapCircleProxy.h @@ -8,8 +8,7 @@ #ifndef map_TiMapCircleProxy_h #define map_TiMapCircleProxy_h -#import "TiBase.h" -#import "TiViewProxy.h" +#import #import @class TiMapViewProxy; diff --git a/ios/Classes/TiMapCustomAnnotationView.h b/ios/Classes/TiMapCustomAnnotationView.h index 29b68b08..8cfaefde 100644 --- a/ios/Classes/TiMapCustomAnnotationView.h +++ b/ios/Classes/TiMapCustomAnnotationView.h @@ -5,10 +5,9 @@ * Please see the LICENSE included with this distribution for details. */ -#import "TiBase.h" -#import "TiMapView.h" -#import "TiViewProxy.h" +#import #import +#import "TiMapView.h" @interface TiMapCustomAnnotationView : MKAnnotationView { @private diff --git a/ios/Classes/TiMapCustomAnnotationView.m b/ios/Classes/TiMapCustomAnnotationView.m index 6a21dfa8..feed14af 100644 --- a/ios/Classes/TiMapCustomAnnotationView.m +++ b/ios/Classes/TiMapCustomAnnotationView.m @@ -6,7 +6,6 @@ */ #import "TiMapCustomAnnotationView.h" -#import "TiBase.h" @implementation TiMapCustomAnnotationView @@ -15,7 +14,7 @@ - (id)initWithAnnotation:(id)annotation reuseIdentifier:(NSString if (self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier]) { self.backgroundColor = [UIColor clearColor]; wrapperView = [[UIView alloc] initWithFrame:CGRectZero]; - wrapperView.userInteractionEnabled = false; + wrapperView.userInteractionEnabled = NO; [self addSubview:wrapperView]; } return self; diff --git a/ios/Classes/TiMapImageAnnotationView.h b/ios/Classes/TiMapImageAnnotationView.h index feacb934..0844c4a7 100644 --- a/ios/Classes/TiMapImageAnnotationView.h +++ b/ios/Classes/TiMapImageAnnotationView.h @@ -5,9 +5,9 @@ * Please see the LICENSE included with this distribution for details. */ -#import "TiBase.h" -#import "TiMapView.h" +#import #import +#import "TiMapView.h" @interface TiMapImageAnnotationView : MKAnnotationView { @private diff --git a/ios/Classes/TiMapImageAnnotationView.m b/ios/Classes/TiMapImageAnnotationView.m index e032c723..b08b9199 100644 --- a/ios/Classes/TiMapImageAnnotationView.m +++ b/ios/Classes/TiMapImageAnnotationView.m @@ -6,7 +6,6 @@ */ #import "TiMapImageAnnotationView.h" -#import "TiBase.h" @implementation TiMapImageAnnotationView diff --git a/ios/Classes/TiMapImageOverlayProxy.h b/ios/Classes/TiMapImageOverlayProxy.h index 0d979486..16714edf 100644 --- a/ios/Classes/TiMapImageOverlayProxy.h +++ b/ios/Classes/TiMapImageOverlayProxy.h @@ -6,7 +6,7 @@ */ #import "TiMapImageOverlayRenderer.h" -#import "TiProxy.h" +#import @interface TiMapImageOverlay : NSObject diff --git a/ios/Classes/TiMapImageOverlayProxy.m b/ios/Classes/TiMapImageOverlayProxy.m index e2d5fe6d..a70fd88f 100644 --- a/ios/Classes/TiMapImageOverlayProxy.m +++ b/ios/Classes/TiMapImageOverlayProxy.m @@ -6,7 +6,6 @@ */ #import "TiMapImageOverlayProxy.h" -#import "TiUtils.h" @implementation TiMapImageOverlay @synthesize coordinate, boundingMapRect; diff --git a/ios/Classes/TiMapImageOverlayRenderer.h b/ios/Classes/TiMapImageOverlayRenderer.h index 6090e3bd..16656cde 100644 --- a/ios/Classes/TiMapImageOverlayRenderer.h +++ b/ios/Classes/TiMapImageOverlayRenderer.h @@ -6,6 +6,7 @@ */ #import +#import @interface TiMapImageOverlayRenderer : MKOverlayRenderer diff --git a/ios/Classes/TiMapImageOverlayRenderer.m b/ios/Classes/TiMapImageOverlayRenderer.m index 9d6ed633..c21662f1 100644 --- a/ios/Classes/TiMapImageOverlayRenderer.m +++ b/ios/Classes/TiMapImageOverlayRenderer.m @@ -6,7 +6,6 @@ */ #import "TiMapImageOverlayRenderer.h" -#import "TiProxy.h" @interface TiMapImageOverlayRenderer () diff --git a/ios/Classes/TiMapMarkerAnnotationView.h b/ios/Classes/TiMapMarkerAnnotationView.h index e3b5fa06..9a45c144 100644 --- a/ios/Classes/TiMapMarkerAnnotationView.h +++ b/ios/Classes/TiMapMarkerAnnotationView.h @@ -4,9 +4,9 @@ * Licensed under the terms of the Apache Public License * Please see the LICENSE included with this distribution for details. */ -#import "TiBase.h" -#import "TiMapView.h" +#import #import +#import "TiMapView.h" @interface TiMapMarkerAnnotationView : MKMarkerAnnotationView { @private diff --git a/ios/Classes/TiMapModule.h b/ios/Classes/TiMapModule.h index 7b0d2d36..c66b4a1c 100644 --- a/ios/Classes/TiMapModule.h +++ b/ios/Classes/TiMapModule.h @@ -5,7 +5,7 @@ * Please see the LICENSE included with this distribution for details. */ -#import "TiModule.h" +#import @interface TiMapModule : TiModule { UIColor *colorRed; diff --git a/ios/Classes/TiMapPinAnnotationView.h b/ios/Classes/TiMapPinAnnotationView.h index 7411cb52..3650207c 100644 --- a/ios/Classes/TiMapPinAnnotationView.h +++ b/ios/Classes/TiMapPinAnnotationView.h @@ -5,9 +5,9 @@ * Please see the LICENSE included with this distribution for details. */ -#import "TiBase.h" -#import "TiMapView.h" +#import #import +#import "TiMapView.h" @interface TiMapPinAnnotationView : MKPinAnnotationView { @private diff --git a/ios/Classes/TiMapPolygonProxy.h b/ios/Classes/TiMapPolygonProxy.h index 96866a55..2b0ca720 100644 --- a/ios/Classes/TiMapPolygonProxy.h +++ b/ios/Classes/TiMapPolygonProxy.h @@ -5,8 +5,7 @@ * Please see the LICENSE included with this distribution for details. */ -#import "TiBase.h" -#import "TiViewProxy.h" +#import #import @class TiMapViewProxy; diff --git a/ios/Classes/TiMapPolygonProxy.m b/ios/Classes/TiMapPolygonProxy.m index 3e3dc7c6..0cd5be6a 100644 --- a/ios/Classes/TiMapPolygonProxy.m +++ b/ios/Classes/TiMapPolygonProxy.m @@ -101,6 +101,9 @@ - (CLLocationCoordinate2D)processLocation:(id)locObj lat = [TiUtils doubleValue:[locObj objectAtIndex:1]]; lon = [TiUtils doubleValue:[locObj objectAtIndex:0]]; coord = CLLocationCoordinate2DMake(lat, lon); + } else { + [self throwException:@"Invalid coordinate tyoe" subreason:@"Use either a dictionary or array" location:CODELOCATION]; + coord = CLLocationCoordinate2DMake(0.0, 0.0); } return coord; diff --git a/ios/Classes/TiMapPolylineProxy.h b/ios/Classes/TiMapPolylineProxy.h index a641524f..d8f68b18 100644 --- a/ios/Classes/TiMapPolylineProxy.h +++ b/ios/Classes/TiMapPolylineProxy.h @@ -5,14 +5,9 @@ * Please see the LICENSE included with this distribution for details. */ -#ifndef map_TiMapPolylineProxy_h -#define map_TiMapPolylineProxy_h - -#import "TiBase.h" -#import "TiMapOverlayPattern.h" -#import "TiViewProxy.h" - +#import #import +#import "TiMapOverlayPattern.h" @class TiMapViewProxy; @@ -29,5 +24,3 @@ @property (nonatomic, readonly) MKPolylineRenderer *polylineRenderer; @end - -#endif diff --git a/ios/Classes/TiMapPolylineProxy.m b/ios/Classes/TiMapPolylineProxy.m index d98dded3..dcd178b4 100644 --- a/ios/Classes/TiMapPolylineProxy.m +++ b/ios/Classes/TiMapPolylineProxy.m @@ -76,7 +76,11 @@ - (CLLocationCoordinate2D)processLocation:(id)locObj lat = [TiUtils doubleValue:[locObj objectAtIndex:1]]; lon = [TiUtils doubleValue:[locObj objectAtIndex:0]]; coord = CLLocationCoordinate2DMake(lat, lon); + } else { + [self throwException:@"Invalid coordinate tyoe" subreason:@"Use either a dictionary or array" location:CODELOCATION]; + coord = CLLocationCoordinate2DMake(0.0, 0.0); } + return coord; } diff --git a/ios/Classes/TiMapRouteProxy.h b/ios/Classes/TiMapRouteProxy.h index 04250a8e..d952739b 100644 --- a/ios/Classes/TiMapRouteProxy.h +++ b/ios/Classes/TiMapRouteProxy.h @@ -6,8 +6,7 @@ */ #import "TiMKOverlayPathUniversal.h" -#import "TiProxy.h" -#import "TiUtils.h" +#import #import @interface TiMapRouteProxy : TiProxy { diff --git a/ios/Classes/TiMapRouteProxy.m b/ios/Classes/TiMapRouteProxy.m index 02b5008a..00acba0e 100644 --- a/ios/Classes/TiMapRouteProxy.m +++ b/ios/Classes/TiMapRouteProxy.m @@ -6,9 +6,7 @@ */ #import "TiMapRouteProxy.h" -#import "TiBase.h" #import "TiMapModule.h" -#import "TiUtils.h" @implementation TiMapRouteProxy diff --git a/ios/Classes/TiMapSnapshotterProxy.h b/ios/Classes/TiMapSnapshotterProxy.h index e4ba0947..38cc3173 100644 --- a/ios/Classes/TiMapSnapshotterProxy.h +++ b/ios/Classes/TiMapSnapshotterProxy.h @@ -5,7 +5,7 @@ * Please see the LICENSE included with this distribution for details. */ -#import "TiProxy.h" +#import #import @interface TiMapSnapshotterProxy : TiProxy { diff --git a/ios/Classes/TiMapSnapshotterProxy.m b/ios/Classes/TiMapSnapshotterProxy.m index bb78aeac..b091b101 100644 --- a/ios/Classes/TiMapSnapshotterProxy.m +++ b/ios/Classes/TiMapSnapshotterProxy.m @@ -91,12 +91,12 @@ - (void)takeSnapshot:(id)args return; } - TiBlob *blob = [[[TiBlob alloc] _initWithPageContext:[self pageContext]] autorelease]; - [blob setImage:[snapshot image]]; + TiBlob *blob = [[TiBlob alloc] initWithImage:snapshot.image]; [blob setMimeType:@"image/png" type:TiBlobTypeImage]; NSDictionary *event = [NSDictionary dictionaryWithObject:blob forKey:@"image"]; [self _fireEventToListener:@"blob" withObject:event listener:successCallback thisObject:nil]; + RELEASE_TO_NIL(blob); }]; } diff --git a/ios/Classes/TiMapView.h b/ios/Classes/TiMapView.h index 540be488..23080689 100644 --- a/ios/Classes/TiMapView.h +++ b/ios/Classes/TiMapView.h @@ -5,12 +5,11 @@ * Please see the LICENSE included with this distribution for details. */ -#import "TiBase.h" +#import +#import #import "TiMKOverlayPathUniversal.h" #import "TiMapCameraProxy.h" -#import "TiUIView.h" #import "WildcardGestureRecognizer.h" -#import @class TiMapAnnotationProxy; diff --git a/ios/Classes/TiMapView.m b/ios/Classes/TiMapView.m index 0396997a..1dc783dd 100644 --- a/ios/Classes/TiMapView.m +++ b/ios/Classes/TiMapView.m @@ -190,7 +190,7 @@ - (NSArray *)annotationsFromArgs:(id)value - (void)refreshAnnotation:(TiMapAnnotationProxy *)proxy readd:(BOOL)yn { NSArray *selected = map.selectedAnnotations; - BOOL wasSelected = [selected containsObject:proxy]; //If selected == nil, this still returns FALSE. + BOOL wasSelected = [selected containsObject:proxy]; //If selected == nil, this still returns NO. ignoreClicks = YES; if (yn == NO) { [map deselectAnnotation:proxy animated:NO]; @@ -451,7 +451,6 @@ - (void)setUserLocation_:(id)value // Release the locationManager in case it was already created RELEASE_TO_NIL(locationManager); - BOOL userLocation = [TiUtils boolValue:value def:NO]; // the locationManager needs to be created to permissions locationManager = [[CLLocationManager alloc] init]; // set the "userLocation" on the delegate callback to avoid console warnings from the OS @@ -1007,8 +1006,8 @@ - (void)firePinChangeDragState:(MKAnnotationView *)pinview newState:(MKAnnotatio ourProxy, @"map", title, @"title", [NSNumber numberWithInteger:[pinview tag]], @"index", - NUMINT(newState), @"newState", - NUMINT(oldState), @"oldState", + NUMINTEGER(newState), @"newState", + NUMINTEGER(oldState), @"oldState", nil]; if (parentWants) @@ -1038,7 +1037,7 @@ - (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView * selectedAnnotation = [ann retain]; - // If canShowCallout == true we will try to find calloutView to hadleTap on callout + // If canShowCallout is YES we will try to find calloutView to hadleTap on callout if ([ann canShowCallout]) { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.2 * NSEC_PER_SEC), dispatch_get_main_queue(), ^(void) { [self findCalloutView:ann]; @@ -1065,14 +1064,13 @@ - (void)findCalloutView:(UIView *)node - (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view { if ([view conformsToProtocol:@protocol(TiMapAnnotation)]) { - BOOL isSelected = [TiUtils boolValue:[view isSelected] def:NO]; MKAnnotationView *ann = (MKAnnotationView *)view; if (selectedAnnotation == ann) { RELEASE_TO_NIL(ann); } - [self fireClickEvent:view source:isSelected ? @"pin" : @"map"]; + [self fireClickEvent:view source:view.isSelected ? @"pin" : @"map"]; } } @@ -1172,6 +1170,8 @@ - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotationProxy:(TiMap annView.userInteractionEnabled = YES; annView.tag = [ann tag]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wundeclared-selector" id previewContext = [ann valueForUndefinedKey:@"previewContext"]; if (previewContext && [TiUtils forceTouchSupported] && [previewContext performSelector:@selector(preview)] != nil) { UIViewController *controller = [[[TiApp app] controller] topPresentedController]; @@ -1184,12 +1184,11 @@ - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotationProxy:(TiMap return nil; } -#ifndef __clang_analyzer__ // We can ignore this, as it's guarded above id previewingDelegate = [[TiPreviewingDelegate alloc] performSelector:@selector(initWithPreviewContext:) withObject:previewContext]; ann.controllerPreviewing = [controller registerForPreviewingWithDelegate:previewingDelegate sourceView:annView]; -#endif } +#pragma clang diagnostic pop return annView; } @@ -1225,7 +1224,8 @@ - (MKClusterAnnotation *)mapView:(MKMapView *)mapView clusterAnnotationForMember if ([mapProxy _hasListeners:@"clusterstart"]) { [mapProxy fireEvent:@"clusterstart" withObject:event]; } - return annotation; + + return [annotation autorelease]; } // mapView:didAddAnnotationViews: is called after the annotation views have been added and positioned in the map. @@ -1247,7 +1247,7 @@ - (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views thisView.frame = CGRectMake(viewFrame.origin.x, viewFrame.origin.y - self.frame.size.height, viewFrame.size.width, viewFrame.size.height); [UIView animateWithDuration:0.4 delay:0.0 - options:UIViewAnimationCurveEaseOut + options:UIViewAnimationOptionCurveEaseOut animations:^{ thisView.frame = viewFrame; } @@ -1430,12 +1430,7 @@ - (void)fireShapeClickEvent:(id)sourceProxy point:(MKMapPoint)point sourceType:( - (void)doClickEvent:(id)viewProxy mapProxy:(id)mapProxy event:(NSDictionary *)event { BOOL parentWants = [mapProxy _hasListeners:@"click"]; - BOOL viewWants; - if ([viewProxy respondsToSelector:@selector(_hasListeners)]) { - viewWants = [viewProxy _hasListeners:@"click"]; - } else { - viewWants = FALSE; - } + BOOL viewWants = [viewProxy _hasListeners:@"click"]; if (parentWants) { [mapProxy fireEvent:@"click" withObject:event]; diff --git a/ios/Classes/TiMapViewProxy.h b/ios/Classes/TiMapViewProxy.h index 613b7eb2..230ace40 100644 --- a/ios/Classes/TiMapViewProxy.h +++ b/ios/Classes/TiMapViewProxy.h @@ -5,12 +5,12 @@ * Please see the LICENSE included with this distribution for details. */ +#import #import "TiMapAnnotationProxy.h" #import "TiMapCameraProxy.h" #import "TiMapCircleProxy.h" #import "TiMapPolygonProxy.h" #import "TiMapPolylineProxy.h" -#import "TiViewProxy.h" @interface TiMapViewProxy : TiViewProxy { TiMapAnnotationProxy *selectedAnnotation; // Annotation to select on initial display diff --git a/ios/map.xcodeproj/project.pbxproj b/ios/map.xcodeproj/project.pbxproj index aee8aac7..9a9356f5 100644 --- a/ios/map.xcodeproj/project.pbxproj +++ b/ios/map.xcodeproj/project.pbxproj @@ -378,17 +378,18 @@ 0867D690FE84028FC02AAC07 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0600; + LastUpgradeCheck = 1100; }; buildConfigurationList = 1DEB922208733DC00010E9CD /* Build configuration list for PBXProject "map" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 1; knownRegions = ( - English, - Japanese, - French, - German, + en, + Base, + fr, + ja, + de, ); mainGroup = 0867D691FE84028FC02AAC07 /* map */; productRefGroup = 034768DFFF38A50411DB9C8B /* Products */; @@ -461,6 +462,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 24DD6D1B1134B66800162E58 /* titanium.xcconfig */; buildSettings = { + CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; DSTROOT = /tmp/TiMap.dst; @@ -506,6 +508,7 @@ baseConfigurationReference = 24DD6D1B1134B66800162E58 /* titanium.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ENABLE_OBJC_WEAK = YES; DSTROOT = /tmp/TiMap.dst; GCC_C_LANGUAGE_STANDARD = c99; GCC_MODEL_TUNING = G5; @@ -529,7 +532,7 @@ "$(TITANIUM_BASE_SDK4)", ); INSTALL_PATH = /usr/local/lib; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LIBRARY_SEARCH_PATHS = ""; OTHER_CFLAGS = "-DTI_POST_1_2"; OTHER_LDFLAGS = "-ObjC"; @@ -544,28 +547,54 @@ isa = XCBuildConfiguration; baseConfigurationReference = 24DD6D1B1134B66800162E58 /* titanium.xcconfig */; buildSettings = { + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = NO; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = NO; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = NO; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; DSTROOT = /tmp/TiMap.dst; ENABLE_BITCODE = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = TiMap_Prefix.pch; GCC_PREPROCESSOR_DEFINITIONS = "TI_VERSION=$(TI_VERSION)"; GCC_TREAT_WARNINGS_AS_ERRORS = NO; GCC_VERSION = ""; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = NO; GCC_WARN_MISSING_PARENTHESES = NO; GCC_WARN_SHADOW = NO; GCC_WARN_STRICT_SELECTOR_MATCH = NO; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_PARAMETER = NO; GCC_WARN_UNUSED_VALUE = NO; GCC_WARN_UNUSED_VARIABLE = NO; INSTALL_PATH = /usr/local/lib; - IPHONEOS_DEPLOYMENT_TARGET = 7.1; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = ( "-DDEBUG", @@ -578,6 +607,7 @@ RUN_CLANG_STATIC_ANALYZER = NO; SDKROOT = iphoneos; USER_HEADER_SEARCH_PATHS = ""; + USE_HEADERMAP = YES; }; name = Debug; }; @@ -586,32 +616,58 @@ baseConfigurationReference = 24DD6D1B1134B66800162E58 /* titanium.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = NO; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = NO; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = NO; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; DSTROOT = /tmp/TiMap.dst; ENABLE_BITCODE = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = c99; GCC_MODEL_TUNING = G5; + GCC_NO_COMMON_BLOCKS = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = TiMap_Prefix.pch; GCC_PREPROCESSOR_DEFINITIONS = "TI_VERSION=$(TI_VERSION)"; GCC_TREAT_WARNINGS_AS_ERRORS = NO; GCC_VERSION = ""; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = NO; GCC_WARN_MISSING_PARENTHESES = NO; GCC_WARN_SHADOW = NO; GCC_WARN_STRICT_SELECTOR_MATCH = NO; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_PARAMETER = NO; GCC_WARN_UNUSED_VALUE = NO; GCC_WARN_UNUSED_VARIABLE = NO; INSTALL_PATH = /usr/local/lib; - IPHONEOS_DEPLOYMENT_TARGET = 7.1; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; OTHER_CFLAGS = "-DTI_POST_1_2"; OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = TiMap; RUN_CLANG_STATIC_ANALYZER = NO; SDKROOT = iphoneos; USER_HEADER_SEARCH_PATHS = ""; + USE_HEADERMAP = YES; }; name = Release; }; @@ -619,6 +675,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 24DD6D1B1134B66800162E58 /* titanium.xcconfig */; buildSettings = { + CLANG_ENABLE_OBJC_WEAK = YES; COPY_PHASE_STRIP = NO; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; @@ -630,9 +687,9 @@ isa = XCBuildConfiguration; baseConfigurationReference = 24DD6D1B1134B66800162E58 /* titanium.xcconfig */; buildSettings = { + CLANG_ENABLE_OBJC_WEAK = YES; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_ENABLE_FIX_AND_CONTINUE = NO; PRODUCT_NAME = "Build & test"; ZERO_LINK = NO; }; diff --git a/ios/titanium.xcconfig b/ios/titanium.xcconfig index 926d9c33..50efa8b7 100644 --- a/ios/titanium.xcconfig +++ b/ios/titanium.xcconfig @@ -4,10 +4,9 @@ // OF YOUR TITANIUM SDK YOU'RE BUILDING FOR // // -TITANIUM_SDK_VERSION = 7.5.0.GA +TITANIUM_SDK_VERSION = 8.2.0 - -// +// // THESE SHOULD BE OK GENERALLY AS-IS // TITANIUM_SDK = ~/Library/Application Support/Titanium/mobilesdk/osx/$(TITANIUM_SDK_VERSION) @@ -16,6 +15,4 @@ TITANIUM_BASE_SDK2 = "$(TITANIUM_SDK)/iphone/include/TiCore" TITANIUM_BASE_SDK3 = "$(TITANIUM_SDK)/iphone/include/ASI" TITANIUM_BASE_SDK4 = "$(TITANIUM_SDK)/iphone/include/APSHTTPClient" HEADER_SEARCH_PATHS = $(TITANIUM_BASE_SDK) $(TITANIUM_BASE_SDK2) $(TITANIUM_BASE_SDK3) $(TITANIUM_BASE_SDK4) - - - +FRAMEWORK_SEARCH_PATHS = $(inherited) "$(TITANIUM_SDK)/iphone/Frameworks" From 8c0787034e24ec39b12434509d2dcb39fef5fac0 Mon Sep 17 00:00:00 2001 From: hansemannn Date: Sat, 31 Aug 2019 17:24:05 +0200 Subject: [PATCH 07/44] chore: remove old build scripts, require SDK 8 --- LICENSE | 2 +- ios/assets/README | 6 - ios/build.py | 223 --------------------------------- ios/documentation/changelog.md | 40 ------ ios/documentation/index.md | 47 ------- ios/hooks/README | 1 - ios/hooks/add.py | 35 ------ ios/hooks/install.py | 19 --- ios/hooks/remove.py | 34 ----- ios/hooks/uninstall.py | 18 --- ios/manifest | 4 +- 11 files changed, 3 insertions(+), 426 deletions(-) delete mode 100644 ios/assets/README delete mode 100755 ios/build.py delete mode 100644 ios/documentation/changelog.md delete mode 100644 ios/documentation/index.md delete mode 100644 ios/hooks/README delete mode 100644 ios/hooks/add.py delete mode 100644 ios/hooks/install.py delete mode 100644 ios/hooks/remove.py delete mode 100644 ios/hooks/uninstall.py diff --git a/LICENSE b/LICENSE index f52ddb7f..7e16a172 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright 2013 Appcelerator, Inc. +Copyright 2013-present Appcelerator, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/ios/assets/README b/ios/assets/README deleted file mode 100644 index 6355f5ff..00000000 --- a/ios/assets/README +++ /dev/null @@ -1,6 +0,0 @@ -Place your assets like PNG files in this directory and they will be packaged with your module. - -If you create a file named ti.map.js in this directory, it will be -compiled and used as your module. This allows you to run pure Javascript -modules that are pre-compiled. - diff --git a/ios/build.py b/ios/build.py deleted file mode 100755 index 4b4c1727..00000000 --- a/ios/build.py +++ /dev/null @@ -1,223 +0,0 @@ -#!/usr/bin/env python -# -# Appcelerator Titanium Module Packager -# -# -import os, subprocess, sys, glob, string -import zipfile -from datetime import date - -cwd = os.path.abspath(os.path.dirname(sys._getframe(0).f_code.co_filename)) -os.chdir(cwd) -required_module_keys = ['name','version','moduleid','description','copyright','license','copyright','platform','minsdk'] -module_defaults = { - 'description':'My module', - 'author': 'Your Name', - 'license' : 'Specify your license', - 'copyright' : 'Copyright (c) %s by Your Company' % str(date.today().year), -} -module_license_default = "TODO: place your license here and we'll include it in the module distribution" - -def find_sdk(config): - sdk = config['TITANIUM_SDK'] - return os.path.expandvars(os.path.expanduser(sdk)) - -def replace_vars(config,token): - idx = token.find('$(') - while idx != -1: - idx2 = token.find(')',idx+2) - if idx2 == -1: break - key = token[idx+2:idx2] - if not config.has_key(key): break - token = token.replace('$(%s)' % key, config[key]) - idx = token.find('$(') - return token - - -def read_ti_xcconfig(): - contents = open(os.path.join(cwd,'titanium.xcconfig')).read() - config = {} - for line in contents.splitlines(False): - line = line.strip() - if line[0:2]=='//': continue - idx = line.find('=') - if idx > 0: - key = line[0:idx].strip() - value = line[idx+1:].strip() - config[key] = replace_vars(config,value) - return config - -def generate_doc(config): - docdir = os.path.join(cwd,'documentation') - if not os.path.exists(docdir): - print "Couldn't find documentation file at: %s" % docdir - return None - - try: - import markdown2 as markdown - except ImportError: - import markdown - documentation = [] - for file in os.listdir(docdir): - if file in ignoreFiles or os.path.isdir(os.path.join(docdir, file)): - continue - md = open(os.path.join(docdir,file)).read() - html = markdown.markdown(md) - documentation.append({file:html}); - return documentation - -def compile_js(manifest,config): - js_file = os.path.join(cwd,'assets','ti.map.js') - if not os.path.exists(js_file): return - - from compiler import Compiler - try: - import json - except: - import simplejson as json - - compiler = Compiler(cwd, manifest['moduleid'], manifest['name'], 'commonjs') - root_asset, module_assets = compiler.compile_module() - - root_asset_content = """ -%s - - return filterDataInRange([NSData dataWithBytesNoCopy:data length:sizeof(data) freeWhenDone:NO], ranges[0]); -""" % root_asset - - module_asset_content = """ -%s - - NSNumber *index = [map objectForKey:path]; - if (index == nil) { - return nil; - } - return filterDataInRange([NSData dataWithBytesNoCopy:data length:sizeof(data) freeWhenDone:NO], ranges[index.integerValue]); -""" % module_assets - - from tools import splice_code - - assets_router = os.path.join(cwd,'Classes','TiMapModuleAssets.m') - splice_code(assets_router, 'asset', root_asset_content) - splice_code(assets_router, 'resolve_asset', module_asset_content) - - # Generate the exports after crawling all of the available JS source - exports = open('metadata.json','w') - json.dump({'exports':compiler.exports }, exports) - exports.close() - -def die(msg): - print msg - sys.exit(1) - -def warn(msg): - print "[WARN] %s" % msg - -def validate_license(): - c = open(os.path.join(cwd,'LICENSE')).read() - if c.find(module_license_default)!=-1: - warn('please update the LICENSE file with your license text before distributing') - -def validate_manifest(): - path = os.path.join(cwd,'manifest') - f = open(path) - if not os.path.exists(path): die("missing %s" % path) - manifest = {} - for line in f.readlines(): - line = line.strip() - if line[0:1]=='#': continue - if line.find(':') < 0: continue - key,value = line.split(':') - manifest[key.strip()]=value.strip() - for key in required_module_keys: - if not manifest.has_key(key): die("missing required manifest key '%s'" % key) - if module_defaults.has_key(key): - defvalue = module_defaults[key] - curvalue = manifest[key] - if curvalue==defvalue: warn("please update the manifest key: '%s' to a non-default value" % key) - return manifest,path - -ignoreFiles = ['.DS_Store','.gitignore','libTitanium.a','titanium.jar','README'] -ignoreDirs = ['.DS_Store','.svn','.git','CVSROOT'] - -def zip_dir(zf,dir,basepath,ignoreExt=[]): - if not os.path.exists(dir): return - for root, dirs, files in os.walk(dir): - for name in ignoreDirs: - if name in dirs: - dirs.remove(name) # don't visit ignored directories - for file in files: - if file in ignoreFiles: continue - e = os.path.splitext(file) - if len(e) == 2 and e[1] in ignoreExt: continue - from_ = os.path.join(root, file) - to_ = from_.replace(dir, '%s/%s'%(basepath,dir), 1) - zf.write(from_, to_) - -def glob_libfiles(): - files = [] - for libfile in glob.glob('build/**/*.a'): - if libfile.find('Release-')!=-1: - files.append(libfile) - return files - -def build_module(manifest,config): - from tools import ensure_dev_path - ensure_dev_path() - - rc = os.system("xcodebuild -sdk iphoneos -configuration Release OTHER_CFLAGS=\"-fembed-bitcode\" CLANG_ENABLE_MODULE_DEBUGGING=NO GCC_PRECOMPILE_PREFIX_HEADER=NO DEBUG_INFORMATION_FORMAT=\"DWARF with dSYM\"") - if rc != 0: - die("xcodebuild failed") - rc = os.system("xcodebuild -sdk iphonesimulator -configuration Release OTHER_CFLAGS=\"-fembed-bitcode\" CLANG_ENABLE_MODULE_DEBUGGING=NO GCC_PRECOMPILE_PREFIX_HEADER=NO DEBUG_INFORMATION_FORMAT=\"DWARF with dSYM\"") - if rc != 0: - die("xcodebuild failed") - # build the merged library using lipo - moduleid = manifest['moduleid'] - libpaths = '' - for libfile in glob_libfiles(): - libpaths+='%s ' % libfile - - os.system("lipo %s -create -output build/lib%s.a" %(libpaths,moduleid)) - -def package_module(manifest,mf,config): - name = manifest['name'].lower() - moduleid = manifest['moduleid'].lower() - version = manifest['version'] - modulezip = '%s-iphone-%s.zip' % (moduleid,version) - if os.path.exists(modulezip): os.remove(modulezip) - zf = zipfile.ZipFile(modulezip, 'w', zipfile.ZIP_DEFLATED) - modulepath = 'modules/iphone/%s/%s' % (moduleid,version) - zf.write(mf,'%s/manifest' % modulepath) - libname = 'lib%s.a' % moduleid - zf.write('build/%s' % libname, '%s/%s' % (modulepath,libname)) - docs = generate_doc(config) - if docs!=None: - for doc in docs: - for file, html in doc.iteritems(): - filename = string.replace(file,'.md','.html') - zf.writestr('%s/documentation/%s'%(modulepath,filename),html) - zip_dir(zf,'assets',modulepath,['.pyc','.js']) - zip_dir(zf,'example',modulepath,['.pyc']) - zip_dir(zf,'platform',modulepath,['.pyc','.js']) - zf.write('LICENSE','%s/LICENSE' % modulepath) - zf.write('module.xcconfig','%s/module.xcconfig' % modulepath) - exports_file = 'metadata.json' - if os.path.exists(exports_file): - zf.write(exports_file, '%s/%s' % (modulepath, exports_file)) - zf.close() - - -if __name__ == '__main__': - manifest,mf = validate_manifest() - validate_license() - config = read_ti_xcconfig() - - sdk = find_sdk(config) - sys.path.insert(0,os.path.join(sdk,'iphone')) - sys.path.append(os.path.join(sdk, "common")) - - compile_js(manifest,config) - build_module(manifest,config) - package_module(manifest,mf,config) - sys.exit(0) - diff --git a/ios/documentation/changelog.md b/ios/documentation/changelog.md deleted file mode 100644 index d9669209..00000000 --- a/ios/documentation/changelog.md +++ /dev/null @@ -1,40 +0,0 @@ -# Change Log - -⚠️ Important note: This changelog has been replaced by the official Github [releases tab](https://github.com/appcelerator-modules/ti.map/releases). - -``` -v2.12.0 Support peek-and-pop in annotations [TIMOB-24375] -v2.11.0 Support for overlay patterns [MOD-2346] -v2.10.0 Support "touchEnabled" for overlays, add "mapclick" event [MOD-2322], [MOD-2268] -v2.9.0 Support "opacity" for circles -v2.5.0 Add iOS 9 mapTypes 'HYBRID_FLYOVER_TYPE' and 'SATELLITE_FLYOVER_TYPE'. [MOD-2152] -v2.4.1 Fixed an issue where pins have not been draggable anymore. [MOD-2131] -v2.4.0 iOS 9: Upgrade map module to support bitcode. [TIMOB-19385] -v2.3.2 Fixed map crash with polygons when not setting mapType. [TIMOB-19102] -v2.3.1 Add drawing support. Includes polygons, polylines, and circles. [TIMOB-15410] - Fixes longclick event on iOS. [Github #41] -v2.2.2 Fixed map annotations showing undeclared buttons in iOS7 [TIMOB-17953] - -v2.2.1 Fixed map draggable map pins [TIMOB-18510] - -v2.2.0 Updated to build for 64-bit [TIMOB-17928] - Adding architectures to manifest [TIMOB-18065] - -v2.0.6 Fixed map not responding to touch after animating camera [TIMOB-17749] - -v2.0.5 Fixed exception when setting "centerCoordinate" on camera [TIMOB-17659] - -v2.0.4 Fixed "userLocation" permissions for iOS 8 [TIMOB-17665] - Bumping minsdk to 3.4.0 [MOD-1968] - -v2.0.2 Fixed ignoring userLocation property during view creation [TIMOB-12733] - -v2.0.1 Fixed annotation not showing leftButton rightButton [TC-3524] - -v2.0.0 Fixed methods deprecated in iOS 7 [MOD-1521] - Add Support for iOS7 MapCamera [MOD-1523] - Expose new iOS7 properties and methods of MapView [MOD-1522] - Fixed map view with percentage values become grayed when rotating the screen [MOD-1613] - -v1.0.0 Moved out of the Titanium SDK to a standalone module [MOD-1514] -``` diff --git a/ios/documentation/index.md b/ios/documentation/index.md deleted file mode 100644 index ef44f285..00000000 --- a/ios/documentation/index.md +++ /dev/null @@ -1,47 +0,0 @@ -# ti.map Module - -## Description - -The Map module allows you to access Apple's MapKit APIs - -## Accessing the map Module - -To access this module from JavaScript, you would do the following: - - var Map = require("ti.map"); - -The `Map` variable is a reference to the Module object. - -## Getting Started - -View the [Using Titanium Modules](http://docs.appcelerator.com/platform/latest/#!/guide/Using_Titanium_Modules) document for instructions on getting -started with using this module in your application. - -## Requirements - -Must be run using a Titanium SDK that has had Maps removed. Running against a version of the SDK that still has the Maps module will result in a build failure. - -Applications using this module must be built using Xcode 5 or later. - -## Usage - -See documentation - -## Documentation -* [Map Module API Reference Documentation](http://docs.appcelerator.com/platform/latest/#!/api/Modules.Map) - -## Author - -Jeff Haynie & Jon Alter - -## Module History - -View the [change log](changelog.html) for this module. - -## Feedback and Support - -Please direct all questions, feedback, and concerns to [info@appcelerator.com](mailto:info@appcelerator.com?subject=iOS%20Map%20Module). - -## License - -Copyright(c) 2013 by Appcelerator, Inc. All Rights Reserved. Please see the LICENSE file included in the distribution for further details. diff --git a/ios/hooks/README b/ios/hooks/README deleted file mode 100644 index 66b10a89..00000000 --- a/ios/hooks/README +++ /dev/null @@ -1 +0,0 @@ -These files are not yet supported as of 1.4.0 but will be in a near future release. diff --git a/ios/hooks/add.py b/ios/hooks/add.py deleted file mode 100644 index 04e1c1dc..00000000 --- a/ios/hooks/add.py +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env python -# -# This is the module project add hook that will be -# called when your module is added to a project -# -import os, sys - -def dequote(s): - if s[0:1] == '"': - return s[1:-1] - return s - -def main(args,argc): - # You will get the following command line arguments - # in the following order: - # - # project_dir = the full path to the project root directory - # project_type = the type of project (desktop, mobile, ipad) - # project_name = the name of the project - # - project_dir = dequote(os.path.expanduser(args[1])) - project_type = dequote(args[2]) - project_name = dequote(args[3]) - - # TODO: write your add hook here (optional) - - - # exit - sys.exit(0) - - - -if __name__ == '__main__': - main(sys.argv,len(sys.argv)) - diff --git a/ios/hooks/install.py b/ios/hooks/install.py deleted file mode 100644 index b423fe92..00000000 --- a/ios/hooks/install.py +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env python -# -# This is the module install hook that will be -# called when your module is first installed -# -import os, sys - -def main(args,argc): - - # TODO: write your install hook here (optional) - - # exit - sys.exit(0) - - - -if __name__ == '__main__': - main(sys.argv,len(sys.argv)) - diff --git a/ios/hooks/remove.py b/ios/hooks/remove.py deleted file mode 100644 index f92a234b..00000000 --- a/ios/hooks/remove.py +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env python -# -# This is the module project remove hook that will be -# called when your module is remove from a project -# -import os, sys - -def dequote(s): - if s[0:1] == '"': - return s[1:-1] - return s - -def main(args,argc): - # You will get the following command line arguments - # in the following order: - # - # project_dir = the full path to the project root directory - # project_type = the type of project (desktop, mobile, ipad) - # project_name = the name of the project - # - project_dir = dequote(os.path.expanduser(args[1])) - project_type = dequote(args[2]) - project_name = dequote(args[3]) - - # TODO: write your remove hook here (optional) - - # exit - sys.exit(0) - - - -if __name__ == '__main__': - main(sys.argv,len(sys.argv)) - diff --git a/ios/hooks/uninstall.py b/ios/hooks/uninstall.py deleted file mode 100644 index a7ffd912..00000000 --- a/ios/hooks/uninstall.py +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env python -# -# This is the module uninstall hook that will be -# called when your module is uninstalled -# -import os, sys - -def main(args,argc): - - # TODO: write your uninstall hook here (optional) - - # exit - sys.exit(0) - - -if __name__ == '__main__': - main(sys.argv,len(sys.argv)) - diff --git a/ios/manifest b/ios/manifest index 2cfd8da1..99dbbf2f 100644 --- a/ios/manifest +++ b/ios/manifest @@ -2,7 +2,7 @@ # this is your module manifest and used by Titanium # during compilation, packaging, distribution, etc. # -version: 3.2.0 +version: 4.0.0 apiversion: 2 architectures: armv7 arm64 i386 x86_64 description: External version of Map module @@ -15,4 +15,4 @@ name: map moduleid: ti.map guid: fee93b77-8eb3-418c-8f04-013664c4af83 platform: iphone -minsdk: 6.2.2.GA +minsdk: 8.0.0 From 67816d62f6fb358a7ec9b92c4767d807211d146a Mon Sep 17 00:00:00 2001 From: hansemannn Date: Sat, 2 Nov 2019 15:42:36 +0100 Subject: [PATCH 08/44] feat: add containsCoordinate method --- ios/Classes/TiMapView.h | 1 + ios/Classes/TiMapView.m | 12 ++++++++++++ ios/Classes/TiMapViewProxy.h | 1 + ios/Classes/TiMapViewProxy.m | 5 +++++ ios/map.xcodeproj/project.pbxproj | 4 ++-- ios/titanium.xcconfig | 2 +- 6 files changed, 22 insertions(+), 3 deletions(-) diff --git a/ios/Classes/TiMapView.h b/ios/Classes/TiMapView.h index 23080689..d26fa806 100644 --- a/ios/Classes/TiMapView.h +++ b/ios/Classes/TiMapView.h @@ -90,6 +90,7 @@ - (void)addImageOverlays:(id)args; - (void)removeImageOverlay:(id)arg; - (void)removeAllImageOverlays; +- (NSNumber *)containsCoordinate:(id)coordinate; - (void)firePinChangeDragState:(MKAnnotationView *)pinview newState:(MKAnnotationViewDragState)newState fromOldState:(MKAnnotationViewDragState)oldState; - (void)setClusterAnnotation:(TiMapAnnotationProxy *)annotation forMembers:(NSArray *)members; diff --git a/ios/Classes/TiMapView.m b/ios/Classes/TiMapView.m index 1dc783dd..2ba5b01e 100644 --- a/ios/Classes/TiMapView.m +++ b/ios/Classes/TiMapView.m @@ -1283,6 +1283,18 @@ - (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views return result; } +- (NSNumber *)containsCoordinate:(id)coordinate +{ + ENSURE_SINGLE_ARG(coordinate, NSDictionary); + + CLLocationDegrees latitude = [TiUtils doubleValue:coordinate[@"latitude"]]; + CLLocationDegrees longitude = [TiUtils doubleValue:coordinate[@"longitude"]]; + + CLLocationCoordinate2D nativeCoordinate = CLLocationCoordinate2DMake(latitude, longitude); + + return @(MKMapRectContainsPoint(map.visibleMapRect, MKMapPointForCoordinate(nativeCoordinate))); +} + #pragma mark Event generation - (void)handleCalloutTap:(UIGestureRecognizer *)sender diff --git a/ios/Classes/TiMapViewProxy.h b/ios/Classes/TiMapViewProxy.h index 230ace40..060aa579 100644 --- a/ios/Classes/TiMapViewProxy.h +++ b/ios/Classes/TiMapViewProxy.h @@ -65,5 +65,6 @@ - (void)removeImageOverlay:(id)arg; - (void)removeAllImageOverlays:(id)args; - (void)setClusterAnnotation:(id)args; +- (NSNumber *)containsCoordinate:(id)coordinate; @end diff --git a/ios/Classes/TiMapViewProxy.m b/ios/Classes/TiMapViewProxy.m index b34290b4..b80a835e 100644 --- a/ios/Classes/TiMapViewProxy.m +++ b/ios/Classes/TiMapViewProxy.m @@ -867,4 +867,9 @@ - (void)showAnnotations:(id)args NO); } +- (NSNumber *)containsCoordinate:(id)coordinate +{ + return [(TiMapView *)[self view] containsCoordinate:coordinate]; +} + @end diff --git a/ios/map.xcodeproj/project.pbxproj b/ios/map.xcodeproj/project.pbxproj index 113531f5..b1f6ce6b 100644 --- a/ios/map.xcodeproj/project.pbxproj +++ b/ios/map.xcodeproj/project.pbxproj @@ -462,8 +462,8 @@ isa = XCBuildConfiguration; baseConfigurationReference = 24DD6D1B1134B66800162E58 /* titanium.xcconfig */; buildSettings = { - CLANG_ENABLE_OBJC_WEAK = YES; CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_WEAK = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; DSTROOT = /tmp/TiMap.dst; @@ -509,8 +509,8 @@ baseConfigurationReference = 24DD6D1B1134B66800162E58 /* titanium.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ENABLE_OBJC_WEAK = YES; CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_WEAK = YES; DSTROOT = /tmp/TiMap.dst; GCC_C_LANGUAGE_STANDARD = c99; GCC_MODEL_TUNING = G5; diff --git a/ios/titanium.xcconfig b/ios/titanium.xcconfig index 50efa8b7..b51aef7a 100644 --- a/ios/titanium.xcconfig +++ b/ios/titanium.xcconfig @@ -4,7 +4,7 @@ // OF YOUR TITANIUM SDK YOU'RE BUILDING FOR // // -TITANIUM_SDK_VERSION = 8.2.0 +TITANIUM_SDK_VERSION = 8.2.0.GA // // THESE SHOULD BE OK GENERALLY AS-IS From 7888c77be23875d11b6bc4b5560561597f3c2457 Mon Sep 17 00:00:00 2001 From: hansemannn Date: Sat, 2 Nov 2019 15:42:59 +0100 Subject: [PATCH 09/44] build: replace maps utils with latest version --- android/build.gradle | 20 ++++++++++++++++++++ android/lib/android-maps-utils-0.5.aar | Bin 0 -> 181511 bytes android/lib/android-maps-utils-release.aar | Bin 181843 -> 0 bytes 3 files changed, 20 insertions(+) create mode 100644 android/build.gradle create mode 100644 android/lib/android-maps-utils-0.5.aar delete mode 100644 android/lib/android-maps-utils-release.aar diff --git a/android/build.gradle b/android/build.gradle new file mode 100644 index 00000000..35570ed2 --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,20 @@ +apply plugin: 'java' + +repositories { + google() + jcenter() + mavenCentral() +} + +dependencies { + implementation 'com.google.maps.android:android-maps-utils:0.5' +} + +configurations.all { + transitive = false +} + +task getDeps(type: Copy) { + from sourceSets.main.runtimeClasspath + into 'lib/' +} diff --git a/android/lib/android-maps-utils-0.5.aar b/android/lib/android-maps-utils-0.5.aar new file mode 100644 index 0000000000000000000000000000000000000000..259c1d3c13b25c15d4eda2eebc42ac57861f24b5 GIT binary patch literal 181511 zcmV(sK<&R!O9KQ7000OG0I^&_N)fMHt%O|y0Gp%&01E&B0Ap-nb8}^LE^1+Nth-Zm zC;iqnnxtdfwr$(SKTgNCt&VNmwr$(CosK*Ddhc<@IN!~F-m}Mf>!N;FRW~)~nsctT zN>SzqC@K&nBqR_J5E0P-eNh6T0U6oZFqqldnOU1K*cjM5F&NkyJK9+oGZ-5<8!*Tk zc$hfS8(AATIjO0_0YUuV4}VPn0TruTxudFM`BJQ3UD=Wc(UKCWTKmtPfa8Dw2=^08 z$P^uggzHty&F&TRe8hTS_9Zr5b6D$I$vhvMKJBxB^UJHq-@)$cMgr>s~ zI_~+B6~VH>get|~{3NcR6g9EC!1~s#I1)j!e0MjshCz9W>}& zO}E(%s?7G5lbDdzya*NeX|SRu>Vz33!b2lx&YX$ox zce>p2SoNZB?9RYQbOyQ%r}g-Vl&?dh9!G&JxvCnwgY3WoNg)oMl(7htLo?(CdRUIk zNR|rMq1M9q)iAPn4d%^U-3zRv8BFGdDO8jdq0$aY@n{!zv6+?;?B03A@h;?*8%yl{ zFg?q((g=kjxu`qV)lxP%=6OHycT(1zF<-X*&XWtL443vY@{bZK1r}wHFr=c!VBw{< zK5`SCyP#=7P$tDnH6EhDzSu>dSdg`$HUMKb3FkYdkN{j4wDM7bl zaV86C+(~xX;^K1PbWHsOTc^D zKs|B1KVHBHAc#yKj0g_9gKqJhm2YeVr9q7~Xy(59h*ayrb-_}%ob;0by2a8#jGRU5 zKv4X_zRd+Lh}RgKi;s=HI4y%$?hGQuUoT`BYhb7k!BfIZVtACox?TAAygm$820^O% zl?i{b-8u?7?(`&P@<@|N7FL2+FRr6xVQq!0c)Czq3b31pn_3Qy%c{DK-&)F+Bak|t z(qx!b6qs%gW2ThCsTGk{)fc;2QcNjM$fc zU-LtF$O$=Tl;K=B{*I=I^aHy${!Y7#@IVZzcTmQ8*1aD6-V4gFZ&Fq42eZ%s!F@xJ zk-OLcj}TL?zDPpAS2&#Chz+uQosful;LHlFF`0&SU3?;Au$vTTum$iXyy3zUaF|Lo^6*)Ceg3RS0yQ=CC%ygc%(1gC|M=-~t&@Cves=Hhh*bjR=b%z_I z^(53HxkqnkZ08yT*BFKbuV!%)nuQgS}1e9y<-2%+NmoK$Opql`){$(c=|As zs@fuS12r!TF??3m=op}5;^d=bq06O?ay?V_WGD>g6j3otFY#m*=M-V?TtJEou^t4D z!8M|l%lTf?HRWUPQx93`FKl%dO*yP&mI#7%K6sPS4b4J;XgeQ;Rmv?8+6|fI3b9ma zVF4YSNlG-0>^j;OeU{^ZI)WItYp&krA8;d?u^je;l zC1xFN7F$B!$gD7|tIjj|7r1&lV`H2mwvWYCaye!p3QE^Ae3@DgYbjTbHO!c-52jaS6k_ge zsP22hE=<7X9PrBhH*e?Y(@J@6auC`@tWM|$QFd$q>;fK}g+L4|(uk^Yo>7@6TsiFW=e_&GmQ!$mt= z81OapmW$?5RU{Dop`e04J#5eYXjgcT$+b^fQ^M1XQ_AI2`QvJ#vDBxC(5Jc}JBe2i zQmsnUN#qN9+Q1aLkvUfFbYA$==*6Q7o$;5RXPb22*$D4W9m$d~zXpn*5x)9tp2Hzo z(@mL0`T2y=HS7Q#TceqtpI+MW%Cp0*gn1W+l|8}Aq3`1!@I({@l{A9V6+ww4@4)i5 zbcC)1Kh7{FUp0ja`~h81Jvfd%8mPevk4e!BV*U<%(aT zW~;p$9$A(4xLVAvo5KUu51!5(L6`Y_rk+2P`@AE~mX59-T?Sp*@HmrcMs3qBy0w`? zNTV*7raq1a(n<=&WtY$a%?2=n&2Rbi z^w4OA(^)XbjkbfD1PhJ8E5Uj0ze9E24urH$@QSQv0J%>w3(WWj7?hw41xO6Zee9{Y zMAY!nL4I2gUxu%%GrvV?hy9Z8ev*9j(uLfLQpoXAP#;+2&OW#uyg}T5JpAUR?k=hg z(f4zEC3&d@@`I_GcRhyi&cA)6c)1LN)FAw*qG$B<$-i@Z8(qJ@Ajp8baoN_yj<)UU$tB6CZz&YI zaMC~XLj=V;y69zegudxKPNzFgGu>{keqVq7!1clAl${L)1&%YaqS2*Uia@ra%7!u( z?zKcPmJGBVZgd)KIbDA;;DIyvYKs5%{6o)bVHo=S|_!}TVzV++SHt_3(JxxI z;7q1c>QdQAZ{J);;ylhMpZ`5yRM&*CkE!Jf1N$k*E2B0@3vJe-G)zR)zUHo$WkGd^TtllAoAlRzfAcrQHE zh$w{M33a*4XA1eJ&~)m{CHXhU~mj`P@H1^o5bn z+m9sX0mA&)AlJW+E=2^Ye>i*o0(5}=S$Nk^CkVsOGvV3ki0ylEK7k3$J*z=eH^0u8 z{R>CT;@&~b{bERl=*pe!&;YA8c=t{m=h3)4AK0r_8p-~=Kq5!Rt)V&v0il$3REOij z(nS+!j~WXEE=Tuk5*D{2--?q`@WostYuTJ?8F+k(SiA>p-}UkzL9K@q{2K?BaMy3L zyuu@5RYV=h;Xex&0VN@8P(oSUK(vawk)U0oaqAuUMcxgV^Q7lP+~`tH9a2tkc+nXU z^2=HG1tZ@;|Dq81o6PPO2oTT$*gsK-`hTL3xQT(Yi=)YZAW^lNjMJtn>X$JUz;N8v zP&%(GBZag%xu_sX*h0j7F@g0+&0dPiZoP+7+GcXh(R8ZLY&rpM)3zgzW!f2p1-8;P zgaC~1MLNY=;@rJ|K;p$=#;wO`#%=Wb<9+le5Pe?K0B21sQ6$cmcab3(*sy@+vOS8` zmiN?jM+Ds0_K|61rj4y_`K#z~De}=DEiqwRquGttsf^{a46)f}oMjs1rayG67R;-S znli#GZWdmy(_2j$&H{j@O1Md@PT7Isug&2?cL{|QPH~@PE|-&bJSa1c3Hj|RZu#bs zsg7mqbU@(&x9f0~MvjRq9u;-FIfu2K)PSe&SlZ!h&@rkjDdlQ5^kMP_T+4DzYMR$3 z^)jYitV)X|Pm0xpkA0bYC;OAh^BXK6?F=z~#`l(?Fc5{knSc4p;YQwXJT@URT1t1 zG`M-s--@*l5{1wX3wSmmOe8^lWWK}%m*v-5)s+2_4p2RJ7NSlxh)Z?KauTlvgj@`F zXRHH@THRuL5&MkB>*u!XJb-Gsit)Cpo2y31OtXmJ*n`la3f@iFBgGN&n{3EW+)JwSGLjTqh@trNsOGKxgmpT4(QQ zJ7@36TW5_e8_%>;@xvHoyHu^I?U&v8DMc_9ig)}FOq?e|k64$8sltX1Lu7pCA+}L$ zRO*^z>Q*1iZTjo_hEa4ZZ@%;GV`2Bgv61VC0bx z;G^KuG{&zW#}_7X__(fEC8K~IgmIOAE8|^%Y1bIn2h2ebW=;t#IoW+))3e%Zmku^> zVaupYaYGlZ9uz|tu=PpzrhQWa=|zbaS}2#_l#)tJg@%A(O*D_0zS?rZFK~xD z8jny{UVal^;opcALA${iW|^oQ>Yy|NGSvFVB-4xQAVg9Ql7$lSwnKzcOTa9G8sv6* zx*;S}c!snAz46$h>&TReJ!Wggusa1i_TZ=YuKs4=QR0va_(AQ9BBrFIPC`ljzXV{% z%z?4!0w8`M0uWH>j0=Kg=?}Is$-{-nz3OFm28#*Z*&t`$qL;}&z}4Cj#C!>haEO{c z;~aq(ngr#dejXFvhUQHIn`f|iI>PQK@VTG+@X5sK!(iK0B+(?hsR-P;qu?|p3iN`!StXrso@ z53(BYd&BxyF-puBBP9g|0*ZnD|5c3s-Sr@4`47dYSnX0_Q4#ff+osAIm0c*^KX9+l zhEVK&SOmE-j0wvyFksegdz#Xj&Vq;d9_diP=zs&|{;5CK_b!$>$Lo9!3tw&XaqFR{ z*U8iN{c|+67Ra7g#MD_Q!~upNDGqRVw3fOWFeMB(tUpVG&L-w6Si`U#?&b!_-r_8`+WOq znXKJtt4Gh=FSJyl6G2tM2E-F3jjA#uF8H0#IdbF6E3o3)O4W6qg92lVgsd&|5lWCe zZo=UP7j}kN9jhR=wzYTJh(4avHl8IKElGKb@^<&S@|?FkCD(saRDL4$muN3C79L{P zT#g+?#n2l&KNU|L5&b!4ez(oMICTm;eIF-wE2H@C`huewNo_UX| zK;8W<{9oA1TlFdJe)zB<^@~PW;ND2MsrpnCS2?Vy_kl&{9gxBpA#cLRv*`4w3OnRc z#r!XAHeO7q3PNkp$&7y>#n)XxHA6|2= zK=$!sSuxr~fA*q6!WgbsWvTcBu(kdOkDQ&05opdLtCMrdTa~c3BLFfsB&r^f?%gKt zapy_7KosT`ntp(e!LTLgNfugJTfkR>6MOApkAaw~sG1LdCYm8p*_SxbFZucS5BaTH5xe@X+ zXBCPLR?Hw-VnV)9j?5J*kDmK6Mcfp9MC0mM$Qp2`|AG1!9in)zg-ZTvvl;k5(Lv~c zqJx=o-c5(8%I*K~tXfI5F^-8h6_gG$Wh1W2z#%bu9S+)ZxA_)uJy_wh;ijN)$>M%t@$LV$CQw$& z(kYWL5`8M^B!4rrh=D$GI5r#F#K2xk@~8M4wiGKQB@H^3DTNUVJTe&OKD29Nz8l=?)c?p zQA#8hqx_z-gJdhRWfnwN?Wr5@Dm5!vYGX0nN`YPO>?ADYh`md`!!% zEll*>LL`xJbNEUqrzyuBn?ugOFK7*R8UTQ4J8*1l}$x0 z#!vT z1Iov#9jx|cI!<|+RJvD=)K$r=Q*bKfdCCH%T%^keT@8|po8PUxJSwD)iHnXc&!dJI zymIs>?x_gGY^l?CvP>(AS-#REWm}b14!rw7HohhN5bJ*Ttjv_aA^e6OEg^E5-L@zs zXRa);E97UU5fRvaFdUPAFfTk|qOsdzgPzXkug<)fAMa5T8JDNj{Plj(y&B)CYD1f- zv|!w@Vl(JNU!hCLrLru{)40Ay+HEA4*W~gN9ixKQ_DXnY;=Pva!*EE_z3b?9Y*LlS za3rn>Q}~VCv-vpuk|@g;I6@(LDas}#C}NK-d`DkVuvpduH|vs7IRL;WD8S2OsDg+t z8zr_Tk!!J;i@AO*vLkTi{92h$T;=6ZbgJGfT*=VZGrXi)Q*Lyy=HPBIyhG>pSo%^n z?d=%Sqg}f#!nA(pYwC;$U-z}Z-!Xueri~>9C0HqpkvGjmOEuYdH=>HtMTc>*$Nj;iameMge*iZ|o4E08b*@xEYhR5(h z+G@Y>r90$4m}n+|zFqlnrFyqlO zex6oAR`x$t$s;XVa96UR%~+1@W7i}NwjXoxUQRs84&(mOZJ$9}^*HEI44|<*u8R9L147u>9GzE#sM|fKi$_0oefV@XCfJ3N$Qg7w z8*}2qm#CRE>W|WyJ>6BdW}pfG@ftE>$3(E354Br}CNTHzS9JM^lDslY7VyH8L=5(c z3$Gop;I^~>nOShCtKwGAcwv_{QXm=W=YTI$mcI?0eV4G0{>|(;mrpx;Xt01^-(12A zh-+C`0jzHnwmhd*SGP2?d4NhlbB=!-u{XS>K8aj zdXNEAghnx)Wwk+kTT)6#v%kI)sth9RUoD9;uulk22L@~I+}3Wc+}JLjg_k|SqdR@$pRGZ|5bq;}iSu#za%92=G=;^;+N4Q#%gPzey22K9 z4w8YTlVO#}74J<+9d5*26{g^Yh1^mgKH{_$2x2VQ55i~lBdjU|Cp~HLuw<|#`IY&` ztTrJ9Bb!^3zpn2T+TFwco)l*A*su^7? z;5fSZ)J5xs=bowgI9NFL3{cY^!U}b%gLio8C{jhotFj#=H5pn{?6~oY1{*KX=@gs; zu8zbM@sgzxwndlGg%x*dCg_mVQy!ySp9XZc(d+6@N7_*J6l;U6P)0;al8X}X;+`rF zPoUS+?LKdhRf;U3tSXI-w-mv+huK-%RODtYR#A?nBV1uuuI85{lNeZvi%2DAJ#LrfiRR4eeQ{(ogSQ zoEMAmd=MDud!=HJ^aJ|&!4@+W6<5C-Y2`g*y2qg5SMp#RX?~4l+@t5iFV1mbZ<*#t z4$>hNi@LLFYn3~^o|gj%u-ZL|3dP9Y0G?i=kx%nny^;{~`su5l78CU`l<}+^l#U0{ z(RLD><;taEQjF>5>HQKM)*JBy>Ce(nZ?~i=7?J!OR3^kAK9r8)c)H7HneVms_a#cY)ca>2<7pOY!5PrDrkC z{U7DG1ib$=Bj)i|0F7LRhMPRQ(wD9PODhU(SHlwws%1+kylkF zb!w|{Y^xZXw8fG5S+Appda!XFVWmK?9^8hiuJbF%N?;$GI?$?i48wREG)fm~na%t-r!ydYRRLTdJK~ zjZ}RQWHrFBySc0`#7xIQEaDl^hqkIY;1Xk>%@AlcbW@G|g-7^di`3>Vr%7A#O%_bg zF!#_c8ApE%{CEu16O@npGM;|ePCjy#6$bc?~7viv)_mEIa!l7dz;~4ZKx;X zVV9Rf3xEXQBQ=6X+posDhplyo0`|bdclxso%6A&ZTQDz)$|KZ%4L+&o1?09D70*g; zS45Yz&N{@mg$*LbtUfSgouI6A+TLkTNsE#y*5sbk0S>;EIZ|z?+O>@$tC0=<#TeZx z9EMw`uyFmzetJeT@|ru+#mRw9iRQ;@_?LX)J9uE5)Zsh&uybZXn@HI$aWE}8VK z8wmj|ZNR&V%R}9WDXy*Fy>o$^-S@cv16S{@GTh4Q z3@x_{xW|LbyblbKd#%yvp>XYC$nniPXmIyX8f4c&Ea@gqNfmj`fBlTt@WmZa7)pmB z`cVD&q7BNed<~9JSM93MzeHN(%5b}Kc(1c)3(n%QE=DmkJnypFFqIGBH+*ngWB%>I zGP^nzr&5<_!NYbmMcqb{V$VFEbXY{oV!1Y+l_)Q+lJ3oFWZcdvwHPr1%RwHKNGFg- z=uT);x-A6uB5ph8ExI5PeI+N}ptDjNzJ$Kfrbm}BT%HaxY82f%t9#9^22wTx%@(FNh#^Iz zBpK2vXsFDyk`iy&7RY35wB4wGp!O|4P={tGb#xxD0?9jw3ha>_9&AFvt8WBzTR5(t z5`0lU8=Le2&K0*7Z5m!cdSb@lxT)^|W67q{Sa=NX6bWuhPNF&{BB2tT*IZ;&P0KMI zNJMco^Us!Lum4&33a4T~n%F=b!&6v*?~R1SVYr_@4x&fT z7*t+xz;!@Xz?kmHc&>|sillv zi@d@OHrt2pO6ISfw0G7}m*OyMn7HzPiKk?^SFSBXDsf=W1q2-*4U?rmOji=xJ-Y6a zRy?WLsQ+N3txhH&>3ll|wxMu3rZ`5@B1Rei%CqlM-P9=2y4n$|dI=tyk_PTqi zv?H1qrQcNx>QZH_l#_dhI(V5 z+GlPVeveqw8yKyL+oZVOBt7IDm*pKoSW0xhGuUvC;PPmi+41$xXa}+#MqdyR@e-L@ zGP~!}S_;2rWEArt4s6Xo$Cjc-rcPKrkN62z`?-h)g0RF>OgNk*sl$980W0D!f2D!h zn>4lU%V5TPG^~L1Yc*23Nxtt|-4Y})AN&lAbY0qWXacH*||ZY7~p2t+MD;9f{`Qo@X@f*3}PZ}`cg!ZV~IN4JJr z?>DcSQ@+QKfZ%+Od;=Yi=KHk7oNOM@jg1bOv+$=DC>x7GFJ_`fp!jr318 zfcL+&0dg+Z&KCbPvd>mqSN_+?UM>a7U;vpgOa=&T93%>oIFpjNQYw!cJ*A6ne2Ed$ zv}}ARLE#?8dl`eWY2sj=;cgt^UZ|Uo#Q+MGY+U5!dh>M0>5u&GOsv4q-XEC5o|ts* zm;;iS)9$1pN=#8w?zrNJhjQ+L;pDQ0(y)ujrlh=RJdMaXQtmT|S@Uq)IVR=`#;&hk zHLBL#MaGW}eA!$2ce9yd$@yf3IF>aHoyA(UZ-8*#`6$i3VmRA#!)vb3=N3KFv@z5v zT`?B9>LTh+@7gN+Li2P_B`U{EnheXEBsmdHVK~YwqFSk5%O_LN%x z_Eh60LOj;%rZwx{rB7(}*w;!hn^*fYxFVNz)eQf1EU+`2E+N=Xk@H!EG;;1X*lG#CyVq+JPH)QC7R2fupoirm z$m&3{5=vLfW#E{nsGN(`sW$Bc^)SF!WRI9;2myfb%!MhU1*e7=sZWj)=Yw&Q8aM0H zPurzd=o)bBGpl&Q7Aap*Gr-8>xc$Eye;|qqjbgb$Zjl1V`sYJ*=d9(jLRjRK>Je=Rw3JIONQ69#b%OWZv zBNdHFCw2%$8HIi2gy2ybHB}48&On5GP_M0OjA|s+RxZ@~xmSGc}GZxBev4a)OFd1oVX)GBO4_qmdA|*o= zX(}*iDmXc9Xag!MDjq6Ub_?l+x+Yds%DcN@pEq~}KmX8|si@+3UU{2Egbt_K_S3GH zuG1Z_o8{wgem7u20$+>~%dJ+R$~$0-8;tv33%rB}p@FaVkOWX9VGx6_l>Fq=;fxaa z3H!03clMYRVm`-((!U~wys3g1LLK<v(-^CW0LCee-_gq6Y)p&e^6RE?Rq7lWZBA4) z7pG1hlK^8$vLuNUCzIt}0AnN5M;%MWM)2V*TNC1@o z{yZDZ?lfEL{N%nIBw&zNYV+uL7)fuqT(&+zg$aqW?k6wYD_?awH^u7rMsKUG(tgiA zV!FQcGG$Sz-F<^ctE7xCzY(HSH=r*d-16p!dup7D-9rpGeN&#*6aOif%WF=~t*_zHdOdN@<@r7e%ALZWo_(<+y4cri4ZTOC7@%uFtt^f54yKpAB)kVGdNnO5b*qY9 zWTGi&tMoR)f$A=32W#K;;aLh9I?7dTdj-7&e8&n zV@nTiaOf|KjT|GogY9G0_vK;x#K3!HR)QLld6xN0-KF!t2c4P``KK( zFB($YX{ynnOP1NH+|a1ov-SjVhBVPo(p2w7EMfvL;Pl;fm5I(M)_=Po9ArgAuNCcS zy_`+yKW9Zea26bRM3ucFiL2@KiJ>vG*KVt%_&H>QIvVFFJpre1Z2Kqi}lLX^3H^1gbglYw^ZDxN}pr?MLXTHM$?# zCgbircXX*9#gmO1#qTc5e|Eg-Hcv4t^xB>`yJIK_)bP$eYl}}BTe^OJk5-SR&UxRG z>k*`^yCXGgn+^seJ4IdChO{76>r__A@pZd#W85dn=aeVx?+p5a)fT2CR~IL+%l84Q zdCimBQ98Zg-&I)@@P}nDJXf?=y?$O!yzmZonwg9pSLG&3aN3~LP9uJ~c$ra4o)AuL zn!ZCOdydFQc4=ssN0A(=RN6Svp+AAZ0j4e-G&>;xuhX7jUhi@jZ=Lg+Zr`vPp5r|~ zUQgZ8zSSQ@3&9+yPCmW~Qaxwv1fknMO~#vht4cpc%zLp~6?cTsfms(ZG}0vLe=|%!#oN)laEGZ+?sHXS&=Ue@4?kgP2?t%Y?5t`2apovn0StQ2 z9z*GR>yPJ8?3Mx39?%f9lp!f!P>kdd8NGI{p^BufD+*>eDuh8{GASr?pxMMe0K3Kr z-;0hR-jC-VdilX9l0x+-fq}>ozhC5jjuc%7wG3mPJa-6mApA(v6*r%bC|jzm8B8+* zar1}l31UH%71Dm~VD=Kh$?vX2uLF97%pU4Ye%yl`MRTY>-~~$02#dblwUQ(Z+o`L% z?yFH<1@yIHgEYd_*8?;M(0G4ugOz=2vcIY0Q^oW~%LL^0jE>m&f7Euik6wCo<76Pz zYLL{v`*^^S@R8KEP12m)MZ`}C@1r>dR|ct1g|0%4JR^E!lh#U%T`FA=kkpQjUxs73 zo4A`^dYp3}gtTlNqb0nN*OkR@B;s4D@4?|jTMWAn;U zy94QPh#x*rpok2&L`NBOQsC0G4qTX|-}Sad^x7sYP)6!(&^cA#j^=R1UnPiO$R5gsNW8}(pQF=9(QuVu z_AQj0N+x;YG^&nSx|BqckmgjLicg3^-3wiCgfIzaaZRkw60AVC12Jgv(|?!Hi54)x z`kGq!#u)ilPr2-^2mQ#l`hzg?rJ!Irq9bo`(lfw9Th1w8J$PfgA$ffxsW%|4xqk$s zq3LE?@ci1VG5#Ix`Z20<%TpnBtIy|No81q;_3H&`QTNc5`nDOW>)Y>N4n}r023Pv8 zWx>Gs-&~CNcd+<>w>bb?>=)~IDMxCsS zimsy{F+DH1u5MI4s#x{S=ta*!Q@JV@G8UVWTdB#(W?0$Jq0_~@$mE(q?LunIr=)a` z$mGhKiADW8*n=wD5~J@htPn%SCzTD&iB4NA(>q}YPt7zP15ioTe}Q6!+@L(3$R*x( z;Fi*_v}*x7fK{3ucP$iyJE70^&fej@4@;(%hR5GU5&2Z~s#hG&Vxh6r(q9~CKIeQM zNQm)aU7zI%S>26m^f_TM%uyI2{a`IIa~2+=pT{!p8e+~C9)Z>ymn0cveEg|vn%1^O zWMW)D5!W%$$1*e<-LgL_D)Q7Sg5qGU(W08D9U|pJTM1wr!K%ACJAXqaSu0^9=8@L` zaI`G(qFKa1TSw~A%&EM{R|KDr6wB$&R1jpRx%?qdxsv70;gUvX!$gi zP_AWu!S8nZNTv?~YhgB!K$x4n2Kg#~z=lG~dJ*S{j4kdM4|Rs_ZO;1nQHV*!>NX%C zk5i&W5QTACKpCbEfr_7f%hi`hC8`r`5!xoA7yEAY>qbyO)AKRxhh9BEFiD^GNT8C~ zrsD3}Ph*g2M|m&3lQ>I-$w*2{e&r|0SBgV&TUt#B{EM6?=Y7a{f8#~!KgJ8T|F7f} zw)i(MfmdpV^AVFie^q{fiKnU69Rn{Bdb?zd*&Xe?m(#1$jGFHu-ekpeN zBs?ys>{VEU0cJXtx(69YB&!OBsy45&&2$Z|vFn09jmHEG0=+fLEJW{~R{JM&3k6zJ ztp?cW9W|LszvL^c`sPN6%G_<0UAl*zqljYuHwd15F!#PSMO3sZ7)>MOo$D|`#Xr*)6`6Tcjpn+0xuG|Xtm+MwuhuJj9}6s* zlf*WfG==H{;@@oV8 znp8{`Uhzs!=nInkZyxEB9<4<29Y2BRZ_6SNNPF>^JIwd8BeSpagzX_bH z(kz3bgm7RmTmB4FItR{;pF#b7i(Ywv&nrDIZJB{2qOqy0-NJ;=|Ban{Fv)N;HE60j`SEXV;UyW1NdF|7K_)V z$(Xr1=u^G3bmSgdKf`qlR>6mAs?DPy6@9q}(65JN5Nn&c!Bz|<5XQ)7QFKC~--1NC zBQ+kijIs`+%e~8=MBr+7vDIc;p=uO zcY~Os`9NP_RLH;&qn+dsk5s~?R#cuVyMU!e+{Orih}9H4f7Uw0wKn@P4T}D-V|;}U zWoCFOZtwq&ZOkgmWR|P8`1H+SFX@$%vM@LA&8>4~$Clm4E!MvJ2{*t;AgnxhSOq7h zsE`#mcFRsG3yvl~(LoIdo9H{BmGO3CaS!yKob^nDrO-RD{|V)Z1C3!vt+R!I^Ynv3 zU#UiBY{F{-BhfE{CH&d%-~ArUnKgAhFd(2Ln13qBqW`5^`g_=zI6HcX*jZbf7&%+m z+5RWPq}*@2D2V8jN$y~!v(RBfi3(jzS0rSJkfm4vS&p0>7a*dD&~1~Dygqghc*dsk z14|`#*!%HHIaHOMwoWsNi1af+@w1luCthPdRTnBryPqFU=?KGBsP|E0!`Pnqll&Q78!?z2Feq z4+ogB`WbT1zpQS+pR36n^sTB@x#x{J}^1&C`TV)vCq0#ef zA4Y;OYVPSCq#LsH{izf3+zh5?7O(Wc>gjPl%O@8ZeAATjVxhhRIXN{Ac66;T`-d~H z^|sHKM&H#`bx+w@s6}|iO5hE4<(WoZ<1MMtcFrS_wk`mho$7gCX^Hk#qg4Ay?-wR% z#=CXM>yb_T&wh3fo}^(%KKT_#%WE1{ffG;~)!F`TojgkAOen^!ft#xJ;Ug`sw>yq; zF^E>E&O|RSfq(x$M9j;uz5xsbL;(7~+2j8oU3j*#oWkZ`P~rR*3X~x%D#`WEk`y#V zNTwz&uotu}p0K1TKIo}eHznDOyn;jihNdTU*n@bKP@CG2Iu5Boeljq7ew+4UG5Y>+ z`3Bni;i_G>F9)O6)jZk>zQa*BtVmEMnocw*KARaP(_bnswxyEJb(71as^CJ1wUHxz zv}(bda*n_h19|Sgfia&hncV#sPF(6(gYl=AX`x!7@kjM-V{MXws+Il_|3=fe^MHWN zXK+C>e!42zKGR@CtqXRUD5jLKRU{o#o8KQj-KlN}m@T39@OD2;GcggSXfa*`-Uhq` zTc;vn$LtbPmxi_oGmG_Rw!fgVgWcBaMT`_h{=Mr|gS_9wYiTw^gTUhr!tYeEBB`MA z(^uJ5to2^>4|wNe z?uvdc8RI4?wMNONTLfCf)8{Xqy37xs#2G-0YxxP;vA=d*9SDVb`5_oUs$8yJq+W1^ zQoFP(5Z(kwb=DC>e%{gYy|ql|G{{uXu)lgM53zh27IVF$5q)x4CUV%zkBXjqjr2+_ zr`s3wU$}`p-m~idi<|Zz|C>$d|7RERKUE@tt_qGCrmsBm8e)o|NC0|W@oRG2LRfNy zU^ya4Nl1_|bdZ)qV%7P=wC$EP?)<&9UwHRj%M7KgiFmiu2*EyrgZQNvJIppMjEV`f z6aUWasn4v_%t@@D?-y8~93~MgF^N7|m^CE-5%*k-8t_Y?2F$!;Ho}|y)@X?TG$MEW zekNTHHRKw6K2AF!{@q(4A^z{TLqgZr52%;qSH&X{DM3yDsk!E?iRz-?R>9fc25iHK z<5$wTGEiy@)Zs3RicJ%+SY$5Mw$d5xMCEXf$dyvM91{`b>5kd?rRR%`Xl(IH7vvt! zRWxV|?63_p?Msagt%NEImEjRJ>Z)8s7A7L<697Cw!@uFu%{gV#Y}k(tvaSi~M6^zi zMr{ollc*_9>)BhM-j+5L>66uTC5;bnOY+>EX&Z+676LA)@RQE$mj>h2m?H001ym=v zB6dr<($>F-;z%K3x3R<$8>20i*ncZ4C3`eJCKTC9h77#4FzWLwmr*6o6jTYvP}9hi zB$bW*vDIBgo^0?jqTNbP@}_qo`%~%enpgU zgk54ydj?lci{(Y9520m0jT6#jMk4QN_4R*P`=%&Swk6x*F56YRY}>YN+qP}nwr$(C zZQI!I+|&I&@42tv=%37y`InI+V$GN_BLZo{+ZaES!-W=_2gG8 z8UpAruJ?YXigG(a`J+g&d@?iRv#@wgdPEI9GzYAH5s`U@O$_oeLUn!x*AyXwD*b@n zqwkh}2i=RrP-hw9eX0gLM${0(O^mnY`IH)jq{*`{@h#*MGjFmw1wjsM95YFjyr75tI*L$VSdC5l?Mi%P^*PAG85!A zq~|)YuGrf@LAt2tcp=y3cJZ0#<3wPsvP^EyV!>spnMdbr!fQ0yGwr`!WJb)bR+H+q zH%EMgGB@29_P0zpSs!~v8_Z+zKEXQzw|E%GrtA@B@UU<2B60Z9dl6ZHVuCIQe*6Ey z5a9U=k#S9`B9v$Yo%lU|^IOzYp!(ns5ee+PI-6e_#1_tpe{O!{J}30>yU82bB+o$R z?#J5e?4KxJXL`LznO;89KYnaY(kMJl08w&x@b%Z;2biY=K`_K(DvxS*cKPJu8(Q%D zpIG>Skyo@2RzR}xHs@`j5z}*P_#IFP`vBbWP@hk=Bsk~A;kfraG&UoI-c6fPw}pR% zLkU2BlOgU)I2lhQ@wv<~n+RT&P&P!t^?96>>nh@ivhLY)F-<3|EnR0|f-) zY9hu6h(ZX&0s8fIbw}0WB_aKEg3=@@@5p~;+ur^Hl~g(3K)GM=xO1C~NMb<3;wSqr z*`3*ot)DNmiMG4|QHRbT({Au1gWwr-G($n~iHIcx;QR8(i)rBm;Ysj~h&YmINI9g4 zITC56;L{f&Hna3iqYRy2z^V}~IjRgE{W8O>7(h@aGR9^zXCWOLTbnA?tX`b5DJ@ay z$M4cM=Lfrtzpk*m`{JgIrn!X~rKxKvJiU7J>MVJ5VVBW{vC9C-{~VO=N%(69oba zTJrQmi&xBOkV-?{SsqQb;WNOKha}FZDK9xg<2>&EH?0v>fvO1RH&Y7Ql@3u4(FH?F zoz#(Wmw?C!qzcBbKb4Kpht5~hBbX}~C70PYAw$LGGFKSGB^QTz@@$M$>;F|_FUZ?C z{_R@DVR%|90gcm5#T;LalG1#w%`A!clNJVZSqh-7j8+Iu6=D~Prm`GsGlSag6Y{9Y zy=Sb2gOReGEG!ecpSSOTu3-D7bqr^E*qTvq< zG9OOXAqFf?nnR^6!;P^zC(Z2nJKH_wvS=G`J2bOsTYy&FzjThmARrtVq=yX-tPXV)#WkfMOK7B;0bWa=NKRttDRcz-PjJajn#>~k5rx}-!2ac( z@RGA@_RGl>dJeutfj;Ap3ty?t)h4hL%$1j!wol|5hKH99u5~#19|x2eA7X z0D8^jc?3*nF2BN!z#xcZGshf@txf$A3y)8;^D#T+PW zm88A%)Y;+Hp#J!kQk%MGdK!hVrcyovWsaTe$nC84QusbR5qtrXQt`swLFI&>zw-|}uJO9% zzdo=E@ShCL_CLju`VNl&)|S;8P+pqH&b*^3-p0oqED{H6_4u&v>QfvOy(cFyWI)3RG_?wK5sjoJ)`e4@40_mdmbTlex{*xi3%`dILAbJX9+pKTSfjH z=2;28>AHXA0>}PYJwtQ(C=RqZSHLaGu-B1b?6z1#MbHyhSeBUHNSG2 z^UyIU1-t4(4!L9C^p;FQT|b9#r)_ntH=|G=qHI&bF~-z|QGCbbtW82VcF`fewY=`q z*s;9oQrWq@>eAUkaoNGMP379cRGsLY;Fs=_hb~VUCCMAiWbT>ax7I4Oua0Wp;rA3? zJII4|-^Gj8#9ksEU;%r!i=L`pbn6WKXd9W~G#ZL_sY!j6E^sXMVqR;Xm*H)8Ow7&% zjYo}kr8m!+SrP1psg{zNMY#3sTE@3^E9)S|fe8t1VLWCP9;k0){eAlwA_9!wQ(2tv zs_P1+nE&ov)?D1!UEJD<%P-E<%q*xaV0Q83rjg;X$-$Wxv4{o7?BvR-_Ye_;^W^Np z+Um^o)bd2ck*dZ~+MH};COtKW#rf*YCwZAaG6PIkUD?@KS=`xLT^veYTG?1#h!%bQ z$<=KQ(Z9Gdzp%I&O)dpmF}hLU?CkNOX{@}Rl?)%M2^`N|FXpC72jZ9FPB5Q;K^Ry0 z`sC!|1p6D}?Es*Gj-6^RI#vXj9-{&PHyTWE8D_rhwT%=#G2flLKfexh=xChDByjLjP8*Y6I& z(2UK53_IoxINu_c^(KBl4K*-i3%lQrPA67Q#puaN5I3Bk;=ET4+K|m9Hr! zB9CCbArU49gwP?s{u&~br;Ddy=w>$|xD|q9B=Yh_y{FGb= zlZ|kIkioJWYXXM@ql@1FXRvRliCztQ4&?imTKgDUxKREI7Fuhn$pR$L2tncf;3sgs zn<5b=tWdg^qmFnvYct=>0h2_?OUI^7o#lz>V?~H62D$ zTE0D&K&F9^Es=OF(DJRJ?Q7tQi~hjMYL$a zCiBkV67y;E$yDob51Civ-gdfv>+D30D|8=$VR(%g-EUKi%3BKtc0#h7Cv8C2h35>J@|6@hJvO|}Mg5ktrFH`{>jZZA>}M!D-gKuS zeL`hcVmPLf>{NHD3D}H$CKDWr8_BX6t#s6n1!ShFiyO{N5}e!IPK3uLt)zKtp>sZy zK+TzeH&F_;<{l9-=MG_`(I^-IIcmddPerq%?Kc>EGt9+C1R zSya;Da>6Rhb!k=u%x|DnSCU;WRNXgjh}MX=rtV2fnqy7Tlbm4MC{KQ_VxgWI1Hj|D zLQ)3IXV56lc*f(2Ci$u5a~co9QciFvs&TzunbGrZj&IoS8kyQftU7}qSH`TF3K=$f z?c}U99zfYCHW%46@;^b(ZtU?nSuZ-HsDr^TM`Hi7BtL@qLl&vt(LNVuC*>c-<;B2q70Og*Q3u#~1qclx04miB3&H!E6H|LFL#G0abq zp`B-S@(Au3Z*t#hu9ev>xdmqub>f-8-(Rnr(SKpER#)q%nIL$~vUYw`{-9ZWnJn`> z6(1prsvRHDMAP7#NEs4t_<5jUc~@tsXU8dm!{aW>CgSK8=AD0ciMeo+2&qD}UVA*<6+HJq9&wk$k=XpOhsGp=a+9AbTV*D|zHcB)pfP!&q z{N+u;ihjvAqNKXgw!8?_cq#TXlW~cS0TJ{qrR>PCCUul%7AuO_LsLC=rmhd92bxJ5 z5bp)H_#ws1RYV(I`KFEH*!4?GLVu!`;gK4uh$1PBMN}kuSDSK!g^6%eg^5*i^(Ufz zHQN!FJi`&VHP%D09)ov`1d{cg|E28XyNs+jP2wj2L?<8`+uzV$d2`~e4pCt+$%yY| zjEtkzM2&LrA{|+28W`eOmkb^!0#{|FS-g481tP%I^BeCZ0WvbRA_kdw*u0S{>E#p4 zNH*|QGptvdE3mLD3UraqtWiC#b2jIOtoV!M#0sO zcmuaAJB?3{!+bt>q0?6MDdfa(W1`iPu)7oE-E9ftMSf*@>W%zHGD}D5j%-nn5AMpC z?~ahRaZNjhA-e7K@l+<>XnE0t)^e9F`9d`Q6F?TB)F{1~)F~&OOq5#|w*sc@JV9FJ z>blm<7leja!taa1zC#C83U*y@E$5J|YnoHUWu+pX6dn@qH#L`#2o9~8;|kmM558T4 zXaAl9j!pFHno0Ybv;u`H<&!QCAV29ji7t||FX-xx*+WGqYv1I~Ar*G<%29m_KsV%H zEG)+xG#!w#xWAtZi2=ZV(G!Rb>+MR=RRL9Xz)qR}(&Xq1+w2P{_;< z5CYBcn8E>UfSU&+7xm+tr3XC_|EN0%i2m{82{1F&KPr5Z|3EL$^1FvyBs}w63R*RL zZ^M*clW#}UmxvMZEt?mQ##ubGkNyD{qM){1IzysF0MX*gQ#3#iJ+bOym6^}*Nwp4G z>1eo5D{{tJPN1Y_7m@r#uD*2zPK~%XDnqMWfAueho5KWo#WD6@5R;wDrT9siPka(z zYyU;b8(d5EfxKaDM$Qjq!%dR=gTT$;7&+O_4|MB7z+!{)CIQmp9Tl-_bMYmybPg;)@V4FW%z9tSbG3Jt^0`N8PIE4AVE-aL4Y|q65 z7%NNM0x*sWU%A@Rrxp82MUC{*zP<%Th3r&gXTy*d?jIs396=*{$PT-jlds^BqO$0i z65YANL<-gqzfs39CF7MN(GQ01?@7`Wj?gPaX61HEr}_-=Jbj& zGN^rAF%ZKcju{)T-2+8(_VI0q)_aPh3fQel3<)z!Ygk>2NA8RA;swLfCB{0Ziw}{b z%+f*E@|%tqhL3oUlW*5>qDRB+3A}2$)Z*SZo(8*T>JV=hvDK zc+C&E>Ez`SpDiBRH#)|bw9!@T8R`cF%p9*8*`BHw@iVa(v)?44wSCVAsWH-lh-F7N zXb5=zGr7eD7MM%O zJQY3;{?6Ck%wa<`Ulw8O?;G(A#%Yqkb6diX(>O7o=q?vnIW4ggjCWm&k~7-m!SEo% z(U3m@91NxHgw(oB_;ci!K7WL;??1CeXNjrn#dJvlJ~sd;vfM9#B9`p;BkT|&EQ zoRF;Q@@ELh9;O9yFvu)`!P9*DNOEQAD8Z?Va&GBA9xBK>`L-D@y+GRo1J>p)wTO+c z&Pw?1tLqY0rsMt{_~!#yic6$4SGg|x8dS1fNHk0X!6XzXCLJM~X3VV#P}Z4lu@0rE zP^f`-zJX0?(Mc7RL^grymkBgBg|_K5HYL5;`vpy3+2;m4#+fuVTwu*AxV_T5^xj+g zH&&(^7<7y~-YIUJj6So8QrI+`$G7>9}AAMfKf&hwRql4f?W?4*CZ5uG%A`qcl%4 zeaWmkCKX$hy-1t_I?p9ZEMi=w5)@+XvfJG2MY$+*z*PVWFPtUFCqC6cc(8tGC0A@P zlKeS}B6=>~>~cr$ z*b1)%qfszak~0nLZ4K{LK3vzdnzTxez=@wQUgP+@aFB37{vdf_CT8dBp=l+0r8-tk zKEk}y=JtlUKls6C1e=l^L$7YyQ801YwFJK9Q6dJd#V*wc&D#k_{OUg-(eh!26_UjdU>sYcHu`{vv#7i=7V@3VHmdQfY@gbiQ@)Y!9>f# zvI9kYk*s#-aIfczZqTJkXk;o+^SJ8UmB1CphpQLFo5kA=H~np)o4XplFd?y_}K|2 z77U;f1$kkvPt9*v7mOV$lss*B!(e{`Z9fQ=Qr@n|jS_T*7LG42#?!rD);~9Qd#1h~ zUg3Cw)`DvV+z_%GoW>WhMc`zD?>S^97b*{;A{z0T_Ohr>joa}ih39Xe@WUh3>5i^;z?s3 zs!m>LJbmgSpRJ+OgG&bm^`!LX@R5jF?5HMX3}M!)a~LlSaSrG$jn>*2!*U;ZQB?15 z0Tobz?=m=hQQOIzO@0K)%d;VwxSvN{_-VfY%Ykwhop*fHdeJ<0HLpz{XNQEmq2>Yo zgG)4StlVGM8ML=1fG|$Ie5}^LVp>Svu3A^Mx}vCR-iNO_3@+@!v0Wb9=tTtbAm7cF=lj{*H%d&Q5ixy5J7~#{3N&*K#dP8k48L z6q5%@F!vA&=Jmc9os_i`jd32?%KfCdLC45N!UQ6AQ$(kg8gdY0@aC>WN4lw=AhSDU z>c^N7M5^RmyCySVhhc*AB2MRw#b!;$ut5)q{ZwCB-1lTtm=Q{5vJC}wU&}scHXYP) zZYtx2jaull=r`7%LRpGVwkdPD7@y~@hEvV~a(jijoaq$xvTOtu_m9;n1csg{y9Q2tVBdDZgi3}RE*qks;GTzpLPL~yTOGXa z$3R%dOR9B*!I@Yz%E~V$s70+sVrBP9275-$h3te6fqm+!MJ^13O_sY(iT+Nu$OJAyA&MjE5>3Y@mj{I`ON*P^*$w~D}6&j+?Az0rF}%T(%bWfulj zDRu7a-m@${4HUt-`(o7eAobx4Ot*s7aB2CkBA5{lkekL!ds7i0&Gqgm1XJgC$M#$i z7i~OtPlWagsm}6{6JFcMxUHOFTb_l6^{)*&g_PxEz-=c%_CUt>Zyy>C!v?J=%h|<7 zt;_oHXY;dC#=_>F0aKxQlQ3;Gxe$9?#LdV*)_7TeU{LO53p>mqDSJevk)8CWgGI$8LGdxaWaSRw8;JSBs&NQACdInx z8Wi*pS1E9{bSz9C9sIkrj(XrK=XLufyGJFzrF2vt-||jx;DrltBEp|JQjP^nyC$a% z>K=yV$aNjXTT0vTp3L!^2ehwh7-0Qhu zrBS8nR}CpYWErm>Q+P1%x68KO7?WD>Q3|gK>2nfN5`07wjGBFsf{@0=G`4htY6qNw zUtyK`i-UZ50yq0Z2qD7u*-_C)KPRqHHoy>g`Y{(vA}SQ1FA%9L|H8@ZaHB*&tW}9I z;XDN3RZ#LNG($fv>kzMMRfD@l+_PSp#LhZB6_03wxla@-*pjZpWF)VDcRwV9J!B?b zEJ14zCp@zwV0G^qkLC&>mYvHxP|JJ(X`UG2RrBOuF)asO;biTz_yhY4q+rjd!ftS$ zf+TYy`vd&1^UFN=V@LEC000Wy|EALD??&Q(oL!~r?e^Ok;ZOHCajWY((R8!)0#opl zpriN(j`>1B6Zs3FIXQW`bVi(#|Md1r!};+`*Je?W0;KZ0f@OID9$A>090GZhYLUVv ztJ2qiE#UX0?=tT*F0QG|Zl@M)Cy#@B&J-u(=S){`dUm?&?SrpQH+UYDFN^`2%-elB z-h>^2A5WIi16^ckniq@M!D*Uj(D*5emp^lC!yS4eErWa3IFeM)(9xt+j?n{hVlAC} z#&plb7NbF(Ph^$mQ>I9!J|~q@hB8z5B3m6SJ@tPEiLFh!wd!6D5q>a zN#!0FR4kcWu&Tg2whr!LXe~us-@qYc&*Wtyq|V_pIVhUDw?_Y~o3}_mv5qX|8&B;l z`5WNopSf6E^0)ecT(Y-v+}h9k5ZqMI3fE`Yt845HUXRVWvmPD)VX)8ACUxqBxrF<% zykwSy`)QzL&8Q-MYZNlLRv4%^mo$3qyp~J#`B2 zm7;irwi;dw8PS6h4B4}IbL!-9vvIWzCWH7i6Z7~s8yVv%BcoKCn|$Y7bE0Z~OPc(} z`)2!Xg6}4q;?s~5g(FAvwrP|y0nS!pg~SY)=2+zPt^u?g!#k7=LP!tHqwDdrqI4cP zvbh>Q64E%~w%L{^%l7I7Lha=E_4Jhkdr~D1M=3tyO`u|0u8|f0wJwRd8VSP1)Hx~# zkxlFw)_pSYv1oZl@;dS@m9%E9frCX1(!j+h9K`tR5a9(GZX{_e@<}OM7cUN)8kp1r ze?ZlkO%4B>1v;vIx&)+?u=uF-&_{C@#YOW-MyO>V=Me!gD5o#Xv2&lr1*$;9nh9hH z369wZN*pQ7@+28^9f5IY@_fA#z1fAk0csa=BL_|a9b+~lwXceH0AfvjcFVpoXe^Au z8W0|8+BZ|jtc?AIU3zhyXLM#i2xQhTSm674^Zu%ob0kTh;N|yS8$2pS-ai{ zta{O5c-XQwP}_<(^bh5zdN+6_<_RH<$Ojh`-ceemEm#hk5Z#J2J(~n}U_}a_VBJc( zb(-NL>MxPt;VoPGf&;o6IeU;^Mf;?7!>R2-*qFw^-N$ray$4a2%;8KR7@YHbhHSV$ z;GsUHeFb`wTCg3cktEu&5xo1eK3&xZfL(&cjVx;hv$UW6ol0a?b)9*~e6uJAbm7ZH zC!;ae4`>r0!}{7XNzXMY~fhJ?$j#>awV; zC}2rlpuczKlDVQcQ3TyIzujmz&<0m*(_tpTwrskFCfwB&S&&2*3D(vp(qkZLr<^*w z_SJRkoViZ?b~4Y!>z`O+EHwoaW%~3~l~dxXRW5#&jG63{@KWW-z2?cmp-pFq5kA)9 zq>)KjTD?Coo8f;?PT_%uYqT{*d~)5HZrOiHudj`69iYr>Tz*Br9 z#^JzE`1%xogEr6ViECoE-!;U^xGmib<{IE)Ul7=0J`6BHY4q3U9li$Wi=o_yrYt4z zV|P#l+9MBz^>zf1rtVG(Nqf^ao^|p|!D->S=U0&p^MW9B4rp4~>Oore*+g1!NHvN$Z6)zd_GvoBEp2T}Id;Rz4-L8sR)4B0zeS-W znzd3WTK6)jQaXOQq)0sfzE_V`kUo`UCX`%$2vF07zAvC0O8-haODud5G<=Ch`JL!4sLx-VzlnfszzoqEJkrGq5qnL%{s!&Ru2U_xC~S|$9tH<7+fB);&wM_( zu>cEgXe3}tJ0Trv0p1H9PJRU0i$OOG;e+p>H)LY9&bx`L$qE@8 zQ8Waa#!Qu*7$@~J?MoUaLyq?JTFBz%$^%IHps7WQXnTM7L+)*7Zn6}tHUR{IpP9K? z!EpAPf?q_vo#Z$>Zdm6$|Hf}CWmMGte|^jg!2hP%{&9DU{G`MnA2PS%rqZSvu7&qf z^g+SOC>~9+4G1U%MUxY+bO;;qxEKe@7v(lt+a2&1**!_Mg3=I)o$1YfmgB7S&W^4Q z;BWmxzuzfPV+AQm$y_RrYKC<(N<~tU`n~&Y97jDXK6ve6U22rEpZk8H2PqLRMt#`& zS!29A=L|-&5c*{76bY$=b)<(eXP`k!*w+zxlm^L9hIE!TOMd%i4k8zy>|;nGcDffo ze4<}k7f>9v%@I@dg7eE9FG@sFM6oA-92t(h%{g9Mll02#51)p!_x!`Wc3A2qAfSZU zvYU1ZcaVW0t+}JL-AfXvDHHqQ63khsj;yN+tqNl(2KSe6{q!$or_+=QgvC%LkalBP zYNYT~yL+5qSk6~Zas}k$Uioc=?th)!U%Sh5eo`-O2}v|`2-dbnE3EHQ`Vl0 zF*2qZ=hYHXvOoCJ$cWNU|Ju%z!O4e`Fj`cgXfH*{fizlG;OgX%y+~J!KRegncIRfUe|-MYnEXr% z1zkP>^%H@`;wojR?vY|Blc2ccY>~j}ki6;KA6Isyy-KMGn_4h3w;Wb3ImrU4BCQ}a z+F+c}d=vkw6zN_e=Rg^9-cdpgeUrq!N`YlkY@+0r%wwY-_ZOt5;1(?3D5V-rV1(vQ zU*T9+4r$>6r6Yn$A;ejx6yC4CE1*^)wF%#>+-gkvO}2UD7zuAW2>;a}{o9zPJ>TKm z`bUg>%kp-n3TxTqWX5=0k~YC?%ozl8(0gql+CQWNjJgo_PY|IiUkMk5dS&e zI2!v=d*cqW1)1#@+zd2K4;gM&~(bG+1VHiaN)oB+f#b2RD<~cXDseT9sf$6ZFl=eLt-AeO#@t*0B9Jh0I)UYS}05X^J4Gosgb2VR3AxILo#Qn5!I`2)Y6cI42)rBW{#! zfz8+WEz=>Mgld@5^G(V4K00v>4~E7hR#A6R`;pdnb~{w_zSCdd8K+^g@YZG@;heHw zh*zxv75ZX>pu1&x+C-0Z#HKuT^aT`j84EmbCc*jJs?nd!Snh@V(j_WbPevg5_3^S{ z&A((r0u1@>3VmXn3Vkm%`}G=h5p-qEHP6J(GuafziV=mBPNbb`juk}3H72bI+O^4q z8G&x(avh0g4Z+{%k{bBuiLCXZQ~Nqj#7seqTkCBLDp5Ymx$8uMo>J|HOI81C+mEak zSQHH~006>2$`a}RlV|>|68^spVE-=os#rTBDI@!|K&)GL6xH$NQ!pP3ZxC4{-vyUc zw}3Zipw<;PgHMpCrv^{ktXb75_qXcy)8181iE)fYeN1EchA{p>q2zXEwuonNI5Bj4 z&a%(8pI)zbejo1U`U2Yh+8wq3t%~fm7Hy~&S6{Yg@mrp1TrEa$BpJsmC>cjp1@|*9$gahCajbiHH0FvlyItMO&NJB zd4If2LQZ;+8mp(ZrA>vN$n1UdgPYs(GA3R7j(d{c5z%9U5r2%~te!S#$!l`vq`E?u z?=`@fqeJ)6ZJ?dy(XHn!rLp8Pqa~jDGTB1KRU*eSxq*0lwJ|zz)gh6Kl*NWUg_nH4 zPtG%LpBQ5P(IyYIOp1P;&{&C9YX>>6&=EF=$JU0xMaZ?Kz8`F35M%AUgez zYg*-c&+-upYvxDd8lun%A}sSV!?F8^Mxo^fs@)1J*S0G+1XyMtmWIKn2IWx|rgBVk zD`$74kE{!LOC|6N&6~&lOqLEr0|eV~;s}EUBFTnnTV&#Jlc)4xt~vf`fBwGA)7CCX zmr|QG^17on@P^dl7R#~C*t(|m?CIRxixW`Jhrjy$ww!nX_;kpeGPT&*?g@u><5j}` zvC)<#EpwFwymf!IyYOKFN?lKINFh)SLGUbl3Tk8o5*zvc+KPK)i*;HD_i=i2!~PqZ zN~Fket5&GFb@%yr!3|qYE)}|XsmbQS8AeY!cH2~brP?s&Xw3nXSNQ?ulqB1`R=2V} zE}T+VfMSmyedf#XBvyPWpA>5%s);kc{JJ z<=R1;ysnX$oK!svy*G80O$XzVrib&6+B0yjWl=E_q(}ME$o8*Z5Hgdk>T{Ob`ZS$# zbl7;pY_%Rj&&@k5(%Z06yk3dXe)IfDUWR1caT;)z7#Jzs2_dGj!C~T8S z4qsBH;b9R+VVp1^os9hS;;42hINC`vbC=R7_o&z2OF?ChLcuNc8xBh^gbz{sokmfU zX#hX`0wYCHt+6Z~kFeTe>NQu;fr*`7H{#zxW3hmIOUO`3iTpVh;ATdo5IUjO*7h<@ zoU=}Lu#9bd+rk@z&?JH63zW$xYB<(8h;U7*=bprDqY20heyIdjhV||<0L|F zP0c%9WMZ4Dqd%cx<{D%;W?^80_i}<)lf1+G$x7IwEAzG8a-)%s82Rd>k{j|8=0D5y zeaUI5mtr)gP5cs*7#70Y@py;wPj=lB<`CU#At5NxcYo^nwMxH#jd~?!uePJ=6`(66 zLqA$8q4*1XWI>Z8o%lUgv7-hS6#b76U z@cAGJ0D#s%t|a=8D+d3OVN|+S*c3tLwltaqCx!=~W0Kwk5Vz7OB=Q;}eH!t<}>rv$7ri92Gq6>~1?R0(J@x0k?G<|;U?fnC) zhe!(peb5sF_6xCXH#*X->@eQns3~pnevOYqW2!Q(cKJ@obL@%<@>h-l|20)blC9EN zs|DGG+QPlmo|m=w$7V}!7ZRIJH@;n^+KYwC@?%Af^|;6IYgUAEHFH(Q*8ZNd)v5=n zu}WTT%R&2Rjbf`NU1F)9J8d{$H@@6*WviV{E@El6VA>LQ=?w@RNC(3@GoW>jJ_v2Y zO5^rM$aU=mOe*KMa4pp~^Esylwyi~f$>4yYC{*Y$Y^ACZUbRBq?FQAdVsqfB4xaLP zoeuw=z#uF^#0CzvqFi;+_ezYOkuIe}Ka>Qg4qn_eGUPDzyNE_jm8$xv>&5c=40bTd z%iHd$`>W1f7mRaW44cQRVQmkqDy^*tPxZIpr51VI@ilR~qZkCI0+;amr3~>Jve*yu zbfD9S(c-Q3W_@p|y%Y0X3t_ zFdB(Toyh^s3aH4Bt~LJcn#UvvhZ$ z^1VW|4nsM8%xZ60ohCtHmFW9aNo5BXt?ZP#9$&0x(obIt1Cqg?t}#cYn(wP&D95}e zP63Vi52BfLtDD#u`KJgS^k@ap!twMG4K{d4E3*b%BcF+-tL&#Av&V@hJjs{5yF$0K zV$mmwsZE2!YCOdkFr=Z1(oey}odXGkR)}N?LBs=9d9k-fezQlAD(eFr34DLBSr%vj$hL7s_LlJ(Y;hQ3zM99*KqY8zI8Bo|u zT?EVzAQmMC7A3L6jA5(0{-^M^mmpo~=(n&Bqx;%626@18Jb!msG+3$@yvilk*Gxb@>mSsqwQC!1VAVq|GkY->O|6s29V(yV{N6G?4Z6 zp`JkxNP?2AL>j{DYESyX?(&D$X$B0GLEsXPCa1o7@ZCLq-9h~%(@5;n`s9H|p=FvO zg`p>O4V@I;PJYcx9tz1Z2PUq&_n^)OjOtO%N@FYhI!vBViq)YXYk@p*4@X%I+n}Jy zdNLzgRi3827lM)yb|yHIDOKNi-{pJ_{PTeI#e1bOXz*jVOkZV}ffj429Ky8Oa}mf| zC)+i3~mS!!!~G7zj8F z`+cW3rU%|xBvKs^^rRyjOWv^v^1}Mr|F^{_(i;##|4JQy|6}UN_@69pX>CO-X>BEF zYvZJE{_neDhE@MdolqjqnCPUjfgGWnubkf^E(xL(QGBeBx0HfP-r^S_lSmIE&7jY~ zFE~u8BX>`;voDY97T0VgFPCEZeiD06+O}mnW5gg%$~0FIxt!Sen)UwDT5J0DczekT zXf=Ecuo3@I2xH!2W;I@SjI8O@Vzh1m5;thx@~>sv2<|Q1gDLF*ItQJN1Ue~q5&+U} z$^({Hug(y*b-Rv;J4tsbL9N7Hg!^4VuIV5D+F;d&mq+6)w#rapL$p-ocQT(iVNRUD zh&Vn5NX+RdH~s{1Crfl-K0J0_;ddP=d$m_lln^6I0?i#C^Gdw}{gmF4AfY5p{z0{# z;UpMgQ7)#ncp%Q4pun&mmJoBUL4X=g9)g%IO-x8wUIcT%#K_~V5RI9V&QEPk7T#2m zn9dB#*y*f29!t{jD|_R%q&CJ6#x_GU8FQgoi-W~SV>wYGN9yEusSz=c=ae#d@m?vV zH)p}XfZof74*JJ^>xrTP{Bl6>>Cy{QT4QXP0}(!!)ERm6ZUO@DO*rD_k|Pj-tA z1X$|)$sbM8PSrZz8qDAwoyGNIj^^05bJe`d#tQvXiN2i~W71T1C2dy}`LcYb$Loc5 zL;MA7Iq*1k@XrdE;LGOblsbt813>UJ$IGWAo|*wV&J zHgi&FVh%~A>T+FGu4Gg06NAW|1e4{jqJ$~+xiXF64QLhu^MF^-GrIrc?yyRA(MP3Jl5n_q;ruJeQSGDv5*n&!bnC=>OAN8Nl%Ax zqo~~lBn_F^icch}OX-<38w1+$wJ12FtAuqB+LNBUA zBrl4*%8MMtIW-xX5z{xV5n(U<14#_seM?LM6t29^K9Z?6A40yg#Cz(V!alH#$XvW{ zDfjRa5mxhSt0za{`^7-y>7u<{-0O^Fyvwxp&+92%1rSI`5;q`IUCbOuyM5&mZR~H%_c$(LU&EdWL1IkS7R*su#l9@7+eEkdvm9z#zi+3q9 zy*Vi}m-oHA%LtNT5XNmK23+xFRsAkG5HAUm!V>d_S0(1l2;sj{EZ^eO@{Y|j-a@}H zyhx-V2lsuyb3+mbfmIr!*hp z1*gy&e(>N^d8CWCJxN_A^OSgdp1G#PGzQdmb$H{?wK$5qP*!_MobN_yAW`5D8T53^HdSI)6p z4aZekj@))EJYAuyqHn+Ab7D`>CTSLp(CC(ak;{hpfhU^SSsD#jL%3K-VF|i=3qjug z&q8;<_DjZO?h;N0UcL4~{$J+Xk={>1{=bP9r`)jp-3GRy?qs!_^MObPt)Dh62bv!X zU7Rk$K7AI2utV(nxVWz-YFn~)`GkF97dZ|f2~q-~l|e9wxA~*gWjOeY9O49N@PJ0d zXLWakOVbS*pd8%*{deV6W9W?yn(iE3+>E&RLGjXzk56Jtf1d~m`;v&cg2;BrRqQ7n zIaH-XCXq->0Lk-MR;OI!e}a`kQJy>`}&U21l^F#W+R4GzVfbJ4J+QXUM6m3EAbJ4RCd)G1}5mX?7SNE$(b5ayZAKS#~(rp>c0- ziYX$mXnz*&`1+N1(9c{oILjpOoB!^aeKHDjQLaml)w@q*!(pM&xTP+vE<4AF8m5j! z`~Ejoni|0q=kp5ypx_^C3AF!@=iNV%;n8y3vV(N+-mv)oO~ux~T++-a@A}p%pb#Yq zgFr5BNL1+FfQxDVL_&o7zw>`|1v<9q2}o|}!s>mm%y(IzFcVl^gAcdMBT zJPafY&w)CzW_%6KlY3MzXA+7D}6&_YkddH ze+Mv>)fE@zkbi7e;RjTZhmxiJfkapk)RpAm$s<+daRoEOfn2%YO>|-FY(U)p=boSl( z+&OJUSY%dQUQMrr*!>FSX*;?I`BEeAQCEd*6x@WaC+3vRZ#6o@#3FVSbgm%#OX@w>(&4_4}OhswhLxcu)-bumNd3xL^%bjXav%3noXzP%O zZwl3l%r9hk=^n8EVr)Kf#8`g;jDW=#DSP8jI%7>Q5y&<7!}ySG)>R2?SNjZYe_Om7 z{ZqnbD|@k%-=UeX|D{LGd@4Z}9AI(m9vO~hhEM7g!fzk;q7!Y zYP=xzA*a=^+_$MM$U6V14aXks)~Vxw_3Yvu6uHlFUEEgz$129S2g)JVfnQ{P>_1M_ zF3sf~v}QW%7n*RFM4025ON7%_>KgmByjL5h5?CtGzw{00#svWN+bhhC*=HX_hwRYY zZs0!L;!A?eXKFBbFLC*;TJB4T-SIQYI_LfT7G9?mGX}2&6As@vL{XY3j7i|&*sfxo zH$D=TquFCZu<6@=bwBwPRHIJXMn}O%SKjXbu=Y)1nlMY6)rBtGwry8+*|u#PUB*|o zZQHhO+qS*u%+6lUzcbJ7U0!Eq#1j!OqK5Ycw>zTO8yeLv9%%xk=W4IS_doDO+Yqn{ z^M5sKu#o>x_~L&?_J3;Y|5*sG0j;gQl=g$4x~B`kh7b}LB%n{g(D!3JltDs5A|S-X z`*lySZc1)XY6QUKV%9HxyjnkZ)$=xQT3%ld-*RQugr=ydsAyVu*}8JAxN_~dxoU2@ zvF&i#82_GWOG)EqAWLBD$w_mX`S-T_msj7IKs}$YJMv%FXd^72QQ+iv@qnHu0(5%R zKf5=FGiuJCUEq2{{N}Ie(J7>7sJMD5g?8?-F}{m;GHnMr&R$Z}KN_;%A|pMXw|1{? zW8e5#-wS~zuk^S(%Xd5RXWU%d7kzGbytpkMw^ZFV2dWZ3{?Yj7uW{f>uXUeqVbS#C z4?g94W?b0|cci#8Qo}!Uw@&buchI;$6$dHtkLl4r2?sUKpPJDVX_^Z=|v+h0Z)>065 zWYXN_W@WyXQ!EWBa?&jfIm#p|*w^(3;we;zLBU5yB&Dm9%DdP8Z~69(v)e>pasu#n zFKpjjEnCXjP0P^SaNJ_&u#WQOIqk>9pBa6 zcAf1O1pK|Ms=Lu~Ppxk(&(G2}GFrG%AW5;n9H}d!p#u^&ukj~>e7N6q!|#s(1yb=duOr>=#JTLyq!Q0S-DxeRRFHIf z(O|%UI1$P-KGg6`GkC~YK79HdAu}R2@~Zn?1N?gAW};nmdYtghDg&uz`ZeUdwcVw* z`_6T6sJ6I8BE^*i=*Nsh2v{nc@tpgTZ>9;+Mbr?eO%f-(#V95vo1zg{U^rVA8{`3wy2TP4ZN&#IzKX-lf)Agw`n=w-P|Lc1UG4+(${hj{Hg(LoA^4 zOdOc!9Qh1He^2_G*1K{B7&^I*PeP{yb5{>Xry4Qk1pg+cO4HV?f;ln4MFDdK#A6_E zIGWTa@JO46f19(gA>?Bz=W|*4T^n*Dsar#$$y-QtTdGuMV7ITyUq^wL6M3 z-;+~Ub0bBOPCG_219P@d>SuDb+OizQ)|8T0+6}GcC-d^o#i{qKVa3DBpMBCb$U>3H zJ23WQV}RCB>&lbCI5e%Ahe|38Q76cdeh>*ML+A7sPuO~{<(ASVsB9sy-fvc@aAL?6 zZ8>loMU{Z15?YF6`NQuG1WA!_7)QgW-hHc!yBHsg9h>tkK}R)ciw*~ZfG{%S;p6jR zXIY)V?xC;L8ggGW_;cSP3RxpPvGiD)u-2_1Xbq|gStDbES<+YB6pIYGn$CMvj{_!*T@<7n~{FIA53@9f?LX=4pHC`Fd;bx9@?JdlJ`q|%Pgb~<>TK`27n zHL_Z+s?DaMk*uaDC$dTp8~_JRbZs{V5kWz(8>Wf+_EvUL;PGCMkZ455eS2%oI6_u_ z#El=8|G0HSBw=*8t%tWX6z%e+F# z(TBjd!9Y%v*|B5O*4M^%JJZ(B<_@Gbq6sS6=4E<541Mxt&BSefJQ}5B)*4pyxKCff zx2B;S(|Z{!th`NJ5NGLl`uZxGM}dvaJs7!0rSR8pZRx)B@%XG2sp#YK$SY`tvGz1b zhqONqHh>7a7Iq7p3H?4*i+)3>g~Z)5vsB`%o|~&t=L77f__JRsT4~-JCA73cI>UI_VE!)C2a6I9C+GA*iLT2REp2tBGb01E&eyqa-lHMKE(*a5Z#LT1K-A}GgN={$qlM>vAodcfJUHbjc zNTcm>j~*l4$u~cv>%C3q$rO8^E~9R^V4O9Nc%=Q5oPyoc>TJR3f$*c>-^Y}Ol+$-B zwHOG)2x7R1!ec{I`@imw;+~1596w+jKZ{bTu7-%3S}T{+HUE;=y$*tY zvWeAkHP<$KVr@$#O6!+()e6&|7N#^OG%7=JGXA}SNq$Od^I~mMQupzHZ%u^dlJDP< zS!~KqoN63EYd4}!HsJPJ?Mup9jriSYfG(@gKGg{h$+GWVxE<|%xt@ND@O+@qxJ&OK zzg9n2j}Ev)Gr6EAF3vpYe+YGI0UcGs=%aA-SV3+@JZWo&(d)$!*dNxi@m1GmkF&~5 zWSun|ODx&5!P>6g!^PSz+tYE@8XFI9n&`so)Ouq9zv-KL+`TzKn+W7=u}_wh%ce4? zGk0K}cWcJRzCY$;*~suLyS_C|yFYf5bn$#Z&1e?XSjlynDC)_sA43iATyrfMP@(lAKnqauT$in?DPU0tGq^Yff6}B z!9qU4vMgs5XxzA$CpYOi&T_Mqu=JYSjZQ{r=aEM@{=#HJxZvek80l1#`THDOFEM9EF&M3IS0I0d)#zBa|tu?Sck=#y~c6@Nbxcp)Afw z)#rHLdl%1_jIdHSM>u~j4&61~@W)-qV5S<5V(6q$+iC>=ehR?FutTu08lf%G>|fVS z+V-8Qjg)brz#z4BA2yYVBj7IR|B!{0iAt@Sn3PPv78@-WF%^ywA|Iy0LacsY7X5i`81~NyDlFy!uJUd|%ua`G!wB_9=ICvelh92x} zSsiZ>40Ym42IiG=rRaW23dJ zXP@}PZM%r%E(ZptYb|l2bl=?;aPPW)ubUukmqE8$_)cQ+fMX#Q-{=zENGq{!ThV4_ z`0N^zzEK<6gI@@YFNj&BH3Xw3n*jZ==ezKGE=krBpx9%E>tQ}@Q}?`EHtqskB?M|&%qwHf&`?gUd5HEuPHYO#f$ z!~)BDA+BpN;&xU{9wGV_vbq`lm7-J;>rCFNTEaL=e>FlBa>L7qqJp-Zg#QfETTX$o z?=*!+EQT+HN^9?_cWSbG5aXA}@OeSx0;TH2NFr)EZJQ1CX`}|G(xo@%klQ?7ePWL4 z^QereN5lmgHeJM?5AG0^=Qdqug<46aGxL>m3RFbQeP_oR2sCfZJ&nbO9|Xs((&e8C zozi3=suqcktS5J@zrYd2AnwrZfqbuS zy$LjK;E=KLOZeUn?ccYbu+s>yQMbdLt9b71@SEA_*VmnA^zprS5+zFBrOq4qWlBI4 zOO6xWXtTOSCweB|KcK4nSJDEz1tNVDT)ws7vf2}}d89La!?{pNT_oS+s=e2rbLQ*C z2fi>HGkZZ?cE4aE;@1x^85@uEtC8BtOn3ML2fXX0xZ>;811%|fq|$muaPFx7 z4&NA&`t(lT3Jnj$tbTl^YV46uLh+k`zcFi`o>X$xFvfgJYB)s{RoTd}8|^W_GHY5R zTJ@S?8gcU6sSdB5m_H>+H_rE08!y$h;z>L58oLP}jb@N`Xt@ZZv+zv*7!R%0HjgsT zJjO7n)B1T2{a%Fx?@gWtS!FY^>H%F%e>7c6Iaeh|5=fl(w_>8Xd-H$5n@jd>ZDz4M5LJpu~L6HXsp zW%kYg%7|ShY-qRD|D|{FMlxwCx_$@n=xN|R_$yzUwxp(hH4_t;BT*zPWuRUHk1LGP z6=om6)lsFrQF(muPC9x(F)n<@b1gBmOJ;Ry_r!cfDv`Ibp>tBlGE?i6r*C|)PTukh zxP8ZSj*S2H?R&`SO?WOi#_bd{)zWKf$)E!Bs`jj?vwAsN*TZE#J*!9)wxj)#*;@@Z zR@+O`5<#_6U=0tBxsr||_WxKN&rwYB;zjk$L?1_ARdP@7m`Kb23D;{wImRRtkxGSM zjVa{vD4=&Kux|SMZvL{3mC?I>*LsdyVoyXWmj@cKDxrY|k*E`GCXAbKy-;4b%=pAt z#g)rNwp*eyqaa2ur4fz^PS0@Go;nG`$H6yEfGj<8|B3$dAEXY!&C9MPcp#t_(*GZ$ zg8vR1E=zescH<8MZw7a@M8H5(aI&LSC^TIWJ5(WP;d9=#NPfWmDM_-G{pF|wRbKgz zuwH<2q0b-w^7BfY(O^Hxhg#;puE&{cYYsj?Z*S1ORIZ@Lcd_(R5;V}Ef)e|2elV(_ zgLfRkDz-U=w~2u>ug4xx^sPEl`zA;iFk!F@Y+XbH?z+5--IkII%(O*^?dx@xY@JU- zynxkcr6o+Ja*KzVu zhKgz<)ui%ci*bc1#qH%vH<=0Mol{wvmrWxoF$UnB#W2G{I}wWgFx{R|?&T1+3KVHsrW z&{gXz$xbltK2wKkmJI_ivqm$;mIzc7Dqb+j;BaQ#VWFwARRmO45q_(=Wh_wf%5ljh z(~{rA_I45dI6c8MgTNRBi|7_-Hu}_t%fC}tt)~zhN_6ZoN&Wj-W)MvhCa~Z6gOZK& zjn}7s3IVknn&_Berq=P`&6GkrV*xpH;^jFkW>J{D{XiYfW!%~Nhh~A%_Ol^3`-r{= zF-F?_soho$Gx;4%`@vJ^ZjW0BH|FDUBmwMaNFWDN&8J0$_pa z#UeI0fI(=-5=z8<+(5z*4Qbde(=E>S=Q@^M!Ut68aLy{2Dkm)Iqy)MowA3sVFIMxi zP|PNNv6yRdK2H+|B()g3aS7P?SkNY!Cml?)ZC#<1EQioX-ki`OyfD$y;7<~%Ka4<& zCc=w}MXc+GBlH<^4j_eyQ1k+($vk;HX8?GvSt@=Y9#EPH#sf5w{5lxY52djk&Y@7II> zy-?EgkR_FqruY4JtOZ1V8|J@<=4>=5j8x#sYP#!!yunZ%66wz_ElprWP;&C{n@mQ% zbvBY6R-0uGFlQ=#=AjACOlImZ20EbS*;*Mw?b%u$((+_K)tf2dy3J^>ICF!w`}-I( zJpxngo!Nh6HmnPf2l8xKqWbcUAs~n!td^;pKENO*B#&UIj#h!E@fVGU zO{>+O_0&Wp|6taTAi)G*+NGS1&90{Flsw^X5!edk6`>j;NWbBsc)jN!`uMcNO*>3D z5x)~7x90{T>5*j4B3A`fbt7}a)4gyQc&GUEm9>6~!AK&JBd2b-plFe(im2k5UThv# z7j0%e(Z`1pHqxSo#H5%Npey5bF0H(QpVL=}gNn=R)!(nuhKI_~Jk1fBPwmJLL#9eA zK93iJ?roX{9({)A+%U^Hc~Q=8^cF{hp~RTeelWG7qNIy% zjRz+`um0lbNmfpISfV=qeVb%Vd_K;EKIgGWaysJBMW;^!S_Gk9c&zs?TC_h7Y#vRb z!$LppW^--O3$2$QJgrwy%-H^K!WMg|8ueO%D3e2pO&)+wRCz!iWfAq2KUAd^m8n3f z!5Q@)wV*g_Wmh$<7sf$!d>;}iJ3Y?1%+etvOkq82eEXRQdj-VOKKFX)1zE_3WMO{( z1P`u#2m(^4GE(~i3t&AL3Zh(Nto(FOzmh%bnHA6E$kSC7?U8o-@w_T+N?xqcTv!7- zq^*I#Sg$Nc5pLD+G#^Nr5nJhi#x%a+Jz#i@Dtuxi&-w^C`qU2b6Gy4-?`*NxQ+KAAgAxR_h5~vySYJfEQR8ROE-buE>O=tdwe2^Di)LeGz7ZQD5xxdl&n>vT1_T?b`Q zTr4W-RI6>_Iw{?~8c2hUwJia%UDf(8W*nVlOAl1fmHTJlq<_`w<%YxYS-{NhQ0?uKcH7ucU%mzwO)+iN*s!h#c=8ZOV-6k0~=W38&@=YNVopt&nVaa z^x%+*gI!KQEY4dsDhojN4!4N{&8W^cef|I)PF2J$TVX^V6F!P4m?lC4bO*n|{+)#b zfB@KEpg=&%|7iC8f937}AJp<6K@GJFH)S={pRG<)rZxnK7$Ri|5gO3-I74b1A`>h! z5|ev#QwaDfcP6LQwnM(+mu*N$T>Pe2%OXuw+U`<0zSd+Z9YK}l`KHGVy$k$Z_MY_{ zo&B3l?u51k7#0F*>XYjc&c8PeFLpUj$M`>A4|+g2gHND%!Kb41rbeUWvv^Fw7{