<commit_before>import UIKit
import MapKit
import WMF
import TUSafariActivity

enum PlaceSearchType {
    case text
    case location
    case top
    case saved
}

struct PlaceSearch {
    let type: PlaceSearchType
    let string: String?
    let region: CLCircularRegion
}


class PlacesViewController: UIViewController, MKMapViewDelegate, UISearchBarDelegate, UIPopoverPresentationControllerDelegate, ArticlePopoverViewControllerDelegate {

    @IBOutlet weak var redoSearchButton: UIButton!
    let nearbyFetcher = WMFLocationSearchFetcher()
    @IBOutlet weak var mapView: MKMapView!
    var searchBar: UISearchBar!
    var siteURL: URL = NSURL.wmf_URLWithDefaultSiteAndCurrentLocale()!
    var articles: [WMFArticle] = []
    var articleStore: WMFArticleDataStore!
    var dataStore: MWKDataStore!
    var segmentedControl: UISegmentedControl!
    
    var currentGroupingPrecision: QuadKeyPrecision = 1
    
    var currentSearch: PlaceSearch? {
        didSet {
            if let search = currentSearch {
                switch search.type {
                case .top:
                    searchBar.text = localizedStringForKeyFallingBackOnEnglish("places-search-top-articles-nearby")
                default:
                    break
                }
                performSearch(search)
            }
        }
    }
    
    

    override func viewDidLoad() {
        super.viewDidLoad()
        view.tintColor = UIColor.wmf_blueTint()
        redoSearchButton.backgroundColor = view.tintColor
        
        //Override UINavigationBar.appearance settings from WMFStyleManager
        navigationController?.navigationBar.isTranslucent = true
        navigationController?.navigationBar.tintColor = nil
        segmentedControl = UISegmentedControl(items: ["M", "L"])
        segmentedControl.selectedSegmentIndex = 0
        segmentedControl.addTarget(self, action: #selector(segmentedControlChanged), for: .valueChanged)
        segmentedControl.tintColor = UIColor.wmf_blueTint()
        
        navigationItem.rightBarButtonItem = UIBarButtonItem(customView: segmentedControl)
        
        mapView.showsPointsOfInterest = false
        mapView.setUserTrackingMode(.follow, animated: true)
        searchBar = UISearchBar(frame: CGRect(x: 0, y: 0, width: view.bounds.size.width, height: 32))
        //searchBar.keyboardType = .webSearch
        searchBar.text = localizedStringForKeyFallingBackOnEnglish("places-search-top-articles-nearby")
        searchBar.returnKeyType = .search
        navigationItem.titleView = searchBar
        searchBar.delegate = self
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        deselectAllAnnotations()
    }

    func mapView(_ mapView: MKMapView, regionWillChangeAnimated animated: Bool) {
        
    }
    
    func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
        regroupArticlesIfNecessary()
        
        let visibleRegion = currentlyVisibleCircularCoordinateRegion
        
        if let search = currentSearch {
            let distance = CLLocation(latitude: visibleRegion.center.latitude, longitude: visibleRegion.center.longitude).distance(from: CLLocation(latitude: search.region.center.latitude, longitude: search.region.center.longitude))
            let radiusRatio = visibleRegion.radius/search.region.radius
            redoSearchButton.isHidden = !(radiusRatio > 1.33 || radiusRatio < 0.67 || distance/search.region.radius > 0.33)
        } else {
            currentSearch = PlaceSearch(type: .top, string: nil, region: visibleRegion)
        }
        
        guard let _ = presentedViewController else {
            return
        }
        dismiss(animated: false, completion: nil)
    }
    
    func segmentedControlChanged() {
        redoSearch(self)
    }
    
    func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
        guard let place = view.annotation as? ArticlePlace else {
            return
        }
        
        guard place.articles.count == 1 else {
            var latitudeMin = CLLocationDegrees(90)
            var longitudeMin = CLLocationDegrees(180)
            var latitudeMax = CLLocationDegrees(-90)
            var longitudeMax = CLLocationDegrees(-180)
            for article in place.articles {
                guard let coordinate = article.coordinate else {
                    continue
                }
                latitudeMin = min(latitudeMin, coordinate.latitude)
                longitudeMin = min(longitudeMin, coordinate.longitude)
                latitudeMax = max(latitudeMax, coordinate.latitude)
                longitudeMax = max(longitudeMax, coordinate.longitude)
            }
            
            //TODO: handle the wrap condition
            let latitudeDelta = 1.3*(latitudeMax - latitudeMin)
            let longitudeDelta = 1.3*(longitudeMax - longitudeMin)
            
            let center = place.coordinate
            let span = MKCoordinateSpanMake(latitudeDelta, longitudeDelta)
            let region = MKCoordinateRegionMake(center , span)
            mapView.setRegion(region, animated: true)
            return
        }
        
        guard let article = place.articles.first,
            let url = article.url,
            let coordinate = article.coordinate else {
                return
        }
        
        let articleVC = ArticlePopoverViewController()
        articleVC.delegate = self
        articleVC.view.tintColor = view.tintColor
        
        articleVC.article = article
        articleVC.titleLabel.text = article.displayTitle
        articleVC.subtitleLabel.text = article.wikidataDescription
        
        let articleLocation = CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude)
        let userCoordinate = mapView.userLocation.coordinate
        let userLocation = CLLocation(latitude: userCoordinate.latitude, longitude: userCoordinate.longitude)
        
        let distance = articleLocation.distance(from: userLocation)
        let distanceString = MKDistanceFormatter().string(fromDistance: distance)
        articleVC.descriptionLabel.text = distanceString
        
        articleVC.preferredContentSize = articleVC.view.systemLayoutSizeFitting(UILayoutFittingCompressedSize)
        
        articleVC.edgesForExtendedLayout = []
        articleVC.modalPresentationStyle = .popover
        guard let presentationController = articleVC.popoverPresentationController else {
            wmf_pushArticle(with: url, dataStore: dataStore, previewStore: articleStore, animated: true)
            return
        }
        
        presentationController.sourceView = view
        presentationController.sourceRect = view.bounds
        presentationController.canOverlapSourceViewRect = false
        presentationController.permittedArrowDirections = .any
        presentationController.delegate = self
        presentationController.passthroughViews = [mapView]
        
        if let _ = presentedViewController {
            dismiss(animated: false, completion: {
                self.present(articleVC, animated: false) {
                    
                }
            })
        } else {
            present(articleVC, animated: false) {
                
            }
        }

    }<commit_msg>fix present & dismiss<commit_after>import UIKit
import MapKit
import WMF
import TUSafariActivity

enum PlaceSearchType {
    case text
    case location
    case top
    case saved
}

struct PlaceSearch {
    let type: PlaceSearchType
    let string: String?
    let region: CLCircularRegion
}


class PlacesViewController: UIViewController, MKMapViewDelegate, UISearchBarDelegate, UIPopoverPresentationControllerDelegate, ArticlePopoverViewControllerDelegate {

    @IBOutlet weak var redoSearchButton: UIButton!
    let nearbyFetcher = WMFLocationSearchFetcher()
    @IBOutlet weak var mapView: MKMapView!
    var searchBar: UISearchBar!
    var siteURL: URL = NSURL.wmf_URLWithDefaultSiteAndCurrentLocale()!
    var articles: [WMFArticle] = []
    var articleStore: WMFArticleDataStore!
    var dataStore: MWKDataStore!
    var segmentedControl: UISegmentedControl!
    
    var currentGroupingPrecision: QuadKeyPrecision = 1
    
    var currentSearch: PlaceSearch? {
        didSet {
            if let search = currentSearch {
                switch search.type {
                case .top:
                    searchBar.text = localizedStringForKeyFallingBackOnEnglish("places-search-top-articles-nearby")
                default:
                    break
                }
                performSearch(search)
            }
        }
    }
    
    

    override func viewDidLoad() {
        super.viewDidLoad()
        view.tintColor = UIColor.wmf_blueTint()
        redoSearchButton.backgroundColor = view.tintColor
        
        //Override UINavigationBar.appearance settings from WMFStyleManager
        navigationController?.navigationBar.isTranslucent = true
        navigationController?.navigationBar.tintColor = nil
        segmentedControl = UISegmentedControl(items: ["M", "L"])
        segmentedControl.selectedSegmentIndex = 0
        segmentedControl.addTarget(self, action: #selector(segmentedControlChanged), for: .valueChanged)
        segmentedControl.tintColor = UIColor.wmf_blueTint()
        
        navigationItem.rightBarButtonItem = UIBarButtonItem(customView: segmentedControl)
        
        mapView.showsPointsOfInterest = false
        mapView.setUserTrackingMode(.follow, animated: true)
        searchBar = UISearchBar(frame: CGRect(x: 0, y: 0, width: view.bounds.size.width, height: 32))
        //searchBar.keyboardType = .webSearch
        searchBar.text = localizedStringForKeyFallingBackOnEnglish("places-search-top-articles-nearby")
        searchBar.returnKeyType = .search
        navigationItem.titleView = searchBar
        searchBar.delegate = self
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        deselectAllAnnotations()
    }

    func mapView(_ mapView: MKMapView, regionWillChangeAnimated animated: Bool) {
        
    }
    
    func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
        regroupArticlesIfNecessary()
        
        let visibleRegion = currentlyVisibleCircularCoordinateRegion
        
        if let search = currentSearch {
            let distance = CLLocation(latitude: visibleRegion.center.latitude, longitude: visibleRegion.center.longitude).distance(from: CLLocation(latitude: search.region.center.latitude, longitude: search.region.center.longitude))
            let radiusRatio = visibleRegion.radius/search.region.radius
            redoSearchButton.isHidden = !(radiusRatio > 1.33 || radiusRatio < 0.67 || distance/search.region.radius > 0.33)
        } else {
            currentSearch = PlaceSearch(type: .top, string: nil, region: visibleRegion)
        }
        
        guard let _ = presentedViewController else {
            return
        }
        dismiss(animated: false, completion: nil)
    }
    
    func segmentedControlChanged() {
        redoSearch(self)
    }
    
    func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
        guard let place = view.annotation as? ArticlePlace else {
            return
        }
        
        guard place.articles.count == 1 else {
            var latitudeMin = CLLocationDegrees(90)
            var longitudeMin = CLLocationDegrees(180)
            var latitudeMax = CLLocationDegrees(-90)
            var longitudeMax = CLLocationDegrees(-180)
            for article in place.articles {
                guard let coordinate = article.coordinate else {
                    continue
                }
                latitudeMin = min(latitudeMin, coordinate.latitude)
                longitudeMin = min(longitudeMin, coordinate.longitude)
                latitudeMax = max(latitudeMax, coordinate.latitude)
                longitudeMax = max(longitudeMax, coordinate.longitude)
            }
            
            //TODO: handle the wrap condition
            let latitudeDelta = 1.3*(latitudeMax - latitudeMin)
            let longitudeDelta = 1.3*(longitudeMax - longitudeMin)
            
            let center = place.coordinate
            let span = MKCoordinateSpanMake(latitudeDelta, longitudeDelta)
            let region = MKCoordinateRegionMake(center , span)
            mapView.setRegion(region, animated: true)
            return
        }
        
        guard let article = place.articles.first,
            let url = article.url,
            let coordinate = article.coordinate else {
                return
        }
        
        let articleVC = ArticlePopoverViewController()
        articleVC.delegate = self
        articleVC.view.tintColor = view.tintColor
        
        articleVC.article = article
        articleVC.titleLabel.text = article.displayTitle
        articleVC.subtitleLabel.text = article.wikidataDescription
        
        let articleLocation = CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude)
        let userCoordinate = mapView.userLocation.coordinate
        let userLocation = CLLocation(latitude: userCoordinate.latitude, longitude: userCoordinate.longitude)
        
        let distance = articleLocation.distance(from: userLocation)
        let distanceString = MKDistanceFormatter().string(fromDistance: distance)
        articleVC.descriptionLabel.text = distanceString
        
        articleVC.preferredContentSize = articleVC.view.systemLayoutSizeFitting(UILayoutFittingCompressedSize)
        
        articleVC.edgesForExtendedLayout = []
        articleVC.modalPresentationStyle = .popover
        guard let presentationController = articleVC.popoverPresentationController else {
            wmf_pushArticle(with: url, dataStore: dataStore, previewStore: articleStore, animated: true)
            return
        }
        
        presentationController.sourceView = view
        presentationController.sourceRect = view.bounds
        presentationController.canOverlapSourceViewRect = false
        presentationController.permittedArrowDirections = .any
        presentationController.delegate = self
        presentationController.passthroughViews = [mapView]
        
        present(articleVC, animated: false) {
            
        }
    }
{'fraction_non_alphanumeric': 0.06853582554517133, 'fraction_numerical': 0.004153686396677051, 'mean_word_length': 2.385516756503398, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1998534', 'n_tokens_mistral': 3824, 'n_tokens_neox': 3635, 'n_words': 774}