diff --git a/Apps/Wikipedia/Wikipedia/Code/NSUserActivity+WMFExtensions.h b/Apps/Wikipedia/Wikipedia/Code/NSUserActivity+WMFExtensions.h index b50d03f..cdfc5ba 100644 --- a/Apps/Wikipedia/Wikipedia/Code/NSUserActivity+WMFExtensions.h +++ b/Apps/Wikipedia/Wikipedia/Code/NSUserActivity+WMFExtensions.h @@ -1,3 +1,4 @@ +@import CoreLocation; @import Foundation; NS_ASSUME_NONNULL_BEGIN @@ -46,6 +47,8 @@ extern NSString *const WMFNavigateToActivityNotification; - (nullable NSURL *)wmf_linkURL; +- (nullable CLLocation *)wmf_locationFromURL; + - (NSURL *)wmf_contentURL; + (NSURL *)wmf_baseURLForActivityOfType:(WMFUserActivityType)type; diff --git a/Apps/Wikipedia/Wikipedia/Code/NSUserActivity+WMFExtensions.m b/Apps/Wikipedia/Wikipedia/Code/NSUserActivity+WMFExtensions.m index a1db457..b547216 100644 --- a/Apps/Wikipedia/Wikipedia/Code/NSUserActivity+WMFExtensions.m +++ b/Apps/Wikipedia/Wikipedia/Code/NSUserActivity+WMFExtensions.m @@ -62,15 +62,42 @@ __attribute__((annotate("returns_localized_nsstring"))) static inline NSString * + (instancetype)wmf_placesActivityWithURL:(NSURL *)activityURL { NSURLComponents *components = [NSURLComponents componentsWithURL:activityURL resolvingAgainstBaseURL:NO]; NSURL *articleURL = nil; + NSNumber *latitude = nil; + NSNumber *longitude = nil; + for (NSURLQueryItem *item in components.queryItems) { if ([item.name isEqualToString:@"WMFArticleURL"]) { NSString *articleURLString = item.value; articleURL = [NSURL URLWithString:articleURLString]; break; } + + if ([item.name isEqualToString:@"coordinates"]) { + NSArray *numbers = [item.value componentsSeparatedByString:@","]; + + if (numbers.count == 2) { + NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init]; + + latitude = [formatter numberFromString:numbers.firstObject]; + longitude = [formatter numberFromString:numbers.lastObject]; + } + + break; + } } + NSUserActivity *activity = [self wmf_pageActivityWithName:@"Places"]; activity.webpageURL = articleURL; + + if (latitude != nil && longitude != nil) { + NSMutableDictionary *userInfo = [activity.userInfo mutableCopy]; + + userInfo[@"WMFCoordinatesLatitude"] = latitude; + userInfo[@"WMFCoordinatesLongitude"] = longitude; + + activity.userInfo = [userInfo copy]; + } + return activity; } @@ -264,6 +291,18 @@ __attribute__((annotate("returns_localized_nsstring"))) static inline NSString * } } +- (CLLocation *)wmf_locationFromURL { + NSNumber *latitude = self.userInfo[@"WMFCoordinatesLatitude"]; + NSNumber *longitude = self.userInfo[@"WMFCoordinatesLongitude"]; + + if (latitude != nil && longitude != nil) { + return [[CLLocation alloc] initWithLatitude:(CLLocationDegrees)[latitude floatValue] + longitude:(CLLocationDegrees)[longitude floatValue]]; + } else { + return nil; + } +} + - (NSURL *)wmf_contentURL { return self.userInfo[@"WMFURL"]; } diff --git a/Apps/Wikipedia/Wikipedia/Code/PlacesViewController.swift b/Apps/Wikipedia/Wikipedia/Code/PlacesViewController.swift index c095c27..ff0b01d 100644 --- a/Apps/Wikipedia/Wikipedia/Code/PlacesViewController.swift +++ b/Apps/Wikipedia/Wikipedia/Code/PlacesViewController.swift @@ -1126,6 +1126,10 @@ class PlacesViewController: ViewController, UISearchBarDelegate, ArticlePopoverV viewMode = .map } + @objc func centerMap(onLocation location: CLLocation) { + zoomAndPanMapView(toLocation: location) + } + func selectArticlePlace(_ articlePlace: ArticlePlace) { mapView.selectAnnotation(articlePlace, animated: articlePlace.identifier != previouslySelectedArticlePlaceIdentifier) previouslySelectedArticlePlaceIdentifier = articlePlace.identifier diff --git a/Apps/Wikipedia/Wikipedia/Code/WMFAppViewController.m b/Apps/Wikipedia/Wikipedia/Code/WMFAppViewController.m index 4fa02b8..3a5fb6c 100644 --- a/Apps/Wikipedia/Wikipedia/Code/WMFAppViewController.m +++ b/Apps/Wikipedia/Wikipedia/Code/WMFAppViewController.m @@ -1187,10 +1187,16 @@ NSString *const WMFLanguageVariantAlertsLibraryVersion = @"WMFLanguageVariantAle [self setSelectedIndex:WMFAppTabTypePlaces]; [self.navigationController popToRootViewControllerAnimated:animated]; NSURL *articleURL = activity.wmf_linkURL; - if (articleURL) { + CLLocation *locationFromURL = activity.wmf_locationFromURL; + if (articleURL || locationFromURL) { // For "View on a map" action to succeed, view mode has to be set to map. [[self placesViewController] updateViewModeToMap]; - [[self placesViewController] showArticleURL:articleURL]; + if (locationFromURL) { + [[self placesViewController] centerMapOnLocation:locationFromURL]; + } + else if (articleURL) { + [[self placesViewController] showArticleURL:articleURL]; + } } } break; case WMFUserActivityTypeContent: { diff --git a/Apps/Wikipedia/Wikipedia/Code/WikimediaProject.swift b/Apps/Wikipedia/Wikipedia/Code/WikimediaProject.swift index 44b1920..6200fed 100644 --- a/Apps/Wikipedia/Wikipedia/Code/WikimediaProject.swift +++ b/Apps/Wikipedia/Wikipedia/Code/WikimediaProject.swift @@ -113,8 +113,6 @@ public enum WikimediaProject: Hashable { self = .wikibooks(languageCode, localizedLanguageName) } else if siteURLString.contains(Configuration.Domain.wiktionary) { self = .wiktionary(languageCode, localizedLanguageName) - } else if siteURLString.contains(Configuration.Domain.wiktionary) { - self = .wiktionary(languageCode, localizedLanguageName) } else if siteURLString.contains(Configuration.Domain.wikisource) { self = .wikisource(languageCode, localizedLanguageName) } else if siteURLString.contains(Configuration.Domain.wikinews) { diff --git a/Apps/Wikipedia/WikipediaUnitTests/Code/NSUserActivity+WMFExtensionsTest.m b/Apps/Wikipedia/WikipediaUnitTests/Code/NSUserActivity+WMFExtensionsTest.m index f6ab751..66ae5a0 100644 --- a/Apps/Wikipedia/WikipediaUnitTests/Code/NSUserActivity+WMFExtensionsTest.m +++ b/Apps/Wikipedia/WikipediaUnitTests/Code/NSUserActivity+WMFExtensionsTest.m @@ -44,6 +44,76 @@ XCTAssertEqual(activity.wmf_type, WMFUserActivityTypeSavedPages); } +- (void)testPlacesURL { + NSURL *url = [NSURL URLWithString:@"wikipedia://places"]; + NSUserActivity *activity = [NSUserActivity wmf_activityForWikipediaScheme:url]; + + XCTAssertEqual(activity.wmf_type, WMFUserActivityTypePlaces); + XCTAssertNil(activity.webpageURL); + XCTAssertNil(activity.userInfo[@"WMFCoordinatesLatitude"]); + XCTAssertNil(activity.userInfo[@"WMFCoordinatesLongitude"]); +} + +- (void)testPlacesURLWithCoordinates { + NSURL *url = [NSURL URLWithString:@"wikipedia://places?coordinates=52.370216,4.895168"]; + NSUserActivity *activity = [NSUserActivity wmf_activityForWikipediaScheme:url]; + + XCTAssertEqual(activity.wmf_type, WMFUserActivityTypePlaces); + XCTAssertNil(activity.webpageURL); + XCTAssert([activity.userInfo[@"WMFCoordinatesLatitude"] isEqualToNumber:@52.370216]); + XCTAssert([activity.userInfo[@"WMFCoordinatesLongitude"] isEqualToNumber:@4.895168]); +} + +- (void)testPlacesURLWithCoordinatesButNegatives { + NSURL *url = [NSURL URLWithString:@"wikipedia://places?coordinates=-34.603722,-58.381592"]; + NSUserActivity *activity = [NSUserActivity wmf_activityForWikipediaScheme:url]; + + XCTAssertEqual(activity.wmf_type, WMFUserActivityTypePlaces); + XCTAssertNil(activity.webpageURL); + XCTAssert([activity.userInfo[@"WMFCoordinatesLatitude"] isEqualToNumber:@-34.603722]); + XCTAssert([activity.userInfo[@"WMFCoordinatesLongitude"] isEqualToNumber:@-58.381592]); +} + +- (void)testPlacesURLWithCoordinatesButNoLongitude { + NSURL *url = [NSURL URLWithString:@"wikipedia://places?coordinates=52.370216,"]; + NSUserActivity *activity = [NSUserActivity wmf_activityForWikipediaScheme:url]; + + XCTAssertEqual(activity.wmf_type, WMFUserActivityTypePlaces); + XCTAssertNil(activity.webpageURL); + XCTAssertNil(activity.userInfo[@"WMFCoordinatesLatitude"]); + XCTAssertNil(activity.userInfo[@"WMFCoordinatesLongitude"]); +} + +- (void)testPlacesURLWithCoordinatesButNoLatitude { + NSURL *url = [NSURL URLWithString:@"wikipedia://places?coordinates=,4.895168"]; + NSUserActivity *activity = [NSUserActivity wmf_activityForWikipediaScheme:url]; + + XCTAssertEqual(activity.wmf_type, WMFUserActivityTypePlaces); + XCTAssertNil(activity.webpageURL); + XCTAssertNil(activity.userInfo[@"WMFCoordinatesLatitude"]); + XCTAssertNil(activity.userInfo[@"WMFCoordinatesLongitude"]); +} + +- (void)testPlacesURLWithCoordinatesButNoCoordinates { + NSURL *url = [NSURL URLWithString:@"wikipedia://places?coordinates=,"]; + NSUserActivity *activity = [NSUserActivity wmf_activityForWikipediaScheme:url]; + + XCTAssertEqual(activity.wmf_type, WMFUserActivityTypePlaces); + XCTAssertNil(activity.webpageURL); + XCTAssertNil(activity.userInfo[@"WMFCoordinatesLatitude"]); + XCTAssertNil(activity.userInfo[@"WMFCoordinatesLongitude"]); +} + +- (void)testPlacesURLWithCoordinatesButEmpty { + NSURL *url = [NSURL URLWithString:@"wikipedia://places?coordinates="]; + NSUserActivity *activity = [NSUserActivity wmf_activityForWikipediaScheme:url]; + + XCTAssertEqual(activity.wmf_type, WMFUserActivityTypePlaces); + XCTAssertNil(activity.webpageURL); + XCTAssertNil(activity.userInfo[@"WMFCoordinatesLatitude"]); + XCTAssertNil(activity.userInfo[@"WMFCoordinatesLongitude"]); +} + - (void)testSearchURL { NSURL *url = [NSURL URLWithString:@"wikipedia://en.wikipedia.org/w/index.php?search=dog"]; NSUserActivity *activity = [NSUserActivity wmf_activityForWikipediaScheme:url];