Quellcode durchsuchen

Event extended info screen. Language fixes. Code cleanup.

Iñigo Valentin vor 9 Jahren
Ursprung
Commit
3b1d4eb554

+ 6 - 0
.gitignore

@@ -0,0 +1,6 @@
+GoogleMaps.framework/Versions/.DS_Store
+GoogleMaps.framework/Versions/A/.DS_Store
+app.xcodeproj/project.xcworkspace/xcuserdata/
+app.xcodeproj/xcuserdata/seavenois.xcuserdatad/xcdebugger/
+app/.DS_Store
+app/Assets.xcassets/.DS_Store

+ 5 - 1
app.xcodeproj/project.pbxproj

@@ -19,6 +19,7 @@
 		9326C4F61EA5279D007DF2A4 /* RowLablancaDay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9326C4F51EA5279D007DF2A4 /* RowLablancaDay.swift */; };
 		93294FF81E336FA000FDAF50 /* Entry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93294FF71E336FA000FDAF50 /* Entry.swift */; };
 		93294FFA1E337D0D00FDAF50 /* RowHomePastActivities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93294FF91E337D0D00FDAF50 /* RowHomePastActivities.swift */; };
+		93348A611EF4273F0093503A /* EventController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93348A601EF4273F0093503A /* EventController.swift */; };
 		935746101EE20B99005DED61 /* FetchLocation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9357460F1EE20B99005DED61 /* FetchLocation.swift */; };
 		935892D01E493C2300E1CD5F /* UIImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 935892CF1E493C2300E1CD5F /* UIImageView.swift */; };
 		935AE18A1EC6138D0055E71F /* SyncController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 935AE1891EC6138D0055E71F /* SyncController.swift */; };
@@ -107,6 +108,7 @@
 		9326C4F51EA5279D007DF2A4 /* RowLablancaDay.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RowLablancaDay.swift; sourceTree = "<group>"; };
 		93294FF71E336FA000FDAF50 /* Entry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Entry.swift; sourceTree = "<group>"; };
 		93294FF91E337D0D00FDAF50 /* RowHomePastActivities.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RowHomePastActivities.swift; sourceTree = "<group>"; };
+		93348A601EF4273F0093503A /* EventController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EventController.swift; sourceTree = "<group>"; };
 		9357460F1EE20B99005DED61 /* FetchLocation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FetchLocation.swift; sourceTree = "<group>"; };
 		935892CF1E493C2300E1CD5F /* UIImageView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIImageView.swift; sourceTree = "<group>"; };
 		935AE1891EC6138D0055E71F /* SyncController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SyncController.swift; sourceTree = "<group>"; };
@@ -233,9 +235,10 @@
 		93B84B981D9C31AB006C0F67 /* app */ = {
 			isa = PBXGroup;
 			children = (
-				93D8B0931EF1A64C008BD946 /* Notifications.swift */,
+				93348A601EF4273F0093503A /* EventController.swift */,
 				93B84BA81D9C31AB006C0F67 /* Info.plist */,
 				93B84BA31D9C31AB006C0F67 /* Assets.xcassets */,
+				93D8B0931EF1A64C008BD946 /* Notifications.swift */,
 				93B84BA01D9C31AB006C0F67 /* app.xcdatamodeld */,
 				93B84BA51D9C31AB006C0F67 /* LaunchScreen.storyboard */,
 				93B84B991D9C31AB006C0F67 /* AppDelegate.swift */,
@@ -460,6 +463,7 @@
 				93075C6C1E59CB6B00396389 /* BlogView.swift in Sources */,
 				93B84B9A1D9C31AB006C0F67 /* AppDelegate.swift in Sources */,
 				93D8B0961EF1B98E008BD946 /* FutureActivityViewController.swift in Sources */,
+				93348A611EF4273F0093503A /* EventController.swift in Sources */,
 				93B84BA21D9C31AB006C0F67 /* app.xcdatamodeld in Sources */,
 				935D6E331E867C7E00CED3A1 /* RowGallery.swift in Sources */,
 				93EB2F0C1EBF5AEB00F64186 /* RowSchedule.swift in Sources */,

+ 4 - 1
app/ActivitiesView.swift

@@ -23,7 +23,7 @@ import CoreData
 import UIKit
 
 /**
-Class to handle the home view.
+Class to handle the activities view.
 */
 class ActivitiesView: UIView {
 	
@@ -41,6 +41,9 @@ class ActivitiesView: UIView {
 	var context: NSManagedObjectContext? = nil
 	
 	
+	/**
+	Default contstructor for the interface builder.
+	*/
 	override init(frame: CGRect){
 		super.init(frame: frame)
 	}

+ 3 - 2
app/AlbumViewController.swift

@@ -22,7 +22,7 @@ import UIKit
 import CoreData
 
 /**
-The view controller of the app.
+The view controller to show albums.
 */
 class AlbumViewController: UIViewController, UIGestureRecognizerDelegate {
 	
@@ -209,7 +209,8 @@ class AlbumViewController: UIViewController, UIGestureRecognizerDelegate {
 	
 	/**
 	Shows a photo.
-	:param: id The album id.
+	:param: album The album id.
+	:param: photo The photo id.
 	*/
 	func showPhoto(album: Int, photo: Int){
 		self.passAlbum = album

+ 17 - 7
app/AppDelegate.swift

@@ -23,6 +23,9 @@ import CoreData
 import GoogleMaps
 import UserNotifications
 
+/**
+Application delegate.
+*/
 @UIApplicationMain
 class AppDelegate: UIResponder, UIApplicationDelegate {
 
@@ -30,37 +33,44 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
 	var controller: ViewController?
 	var albumController: AlbumViewController?
 	var syncController: SyncController?
-
+	var scheduleController: ScheduleViewController?
+	var futureActivityController: FutureActivityViewController?
+	
 	
+	/**
+	Application opened normally. Request permissions amd defines some settings.
+	*/
 	func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
-		// Override point for customization after application launch.
 		
 		// Google Mapas API KEY
 		GMSServices.provideAPIKey("AIzaSyBfIiBM_YSBlxybmI_Uz_fGoUFN4wacR80")
 		
-		// Background mode.
+		// Enable background mode.
 		UIApplication.shared.setMinimumBackgroundFetchInterval(UIApplicationBackgroundFetchIntervalMinimum)
 		
+		// Enable notifications (for iOS 10)
 		if #available(iOS 10.0, *) {
 			let center = UNUserNotificationCenter.current()
 			center.requestAuthorization(options: [.alert, .sound]) { (granted, error) in
-				// Enable or disable features based on authorization.
+				// Notification authorization granted
 			}
 		} else {
-			// Fallback on earlier versions
+			// No notifications for iOS < 10
 		}
 		
-		
 		return true
 	}
 	
 
+	/**
+	Application run in the background. Fectches notifications and syncs with the server.
+	*/
 	func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
 		NSLog(":BACKGROUND:LOG: Start bg sync...")
 		Notifications()
 		Sync()
 		
-		let when = DispatchTime.now() + 120 // 2 minutes to perform the sync.
+		let when = DispatchTime.now() + 180 // 3 minutes to perform the sync.
 		DispatchQueue.main.asyncAfter(deadline: when) {
 			completionHandler(UIBackgroundFetchResult.newData)
 		}

+ 206 - 3
app/Base.lproj/Main.storyboard

@@ -1,11 +1,11 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12120" systemVersion="16E195" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="3o1-ab-AT4">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16F73" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="3o1-ab-AT4">
     <device id="retina4_7" orientation="portrait">
         <adaptation id="fullscreen"/>
     </device>
     <dependencies>
         <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12088"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
         <capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
         <capability name="Constraints to layout margins" minToolsVersion="6.0"/>
         <capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
@@ -16,7 +16,7 @@
         <scene sceneID="e3W-6Z-Jyk">
             <objects>
                 <navigationController title="Gasteizko Margolariak" id="cgF-cq-ysf" sceneMemberID="viewController">
-                    <navigationBar key="navigationBar" contentMode="scaleToFill" id="lgI-h9-O0s">
+                    <navigationBar key="navigationBar" contentMode="scaleToFill" misplaced="YES" id="lgI-h9-O0s">
                         <rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
                         <autoresizingMask key="autoresizingMask"/>
                         <color key="backgroundColor" red="0.4079896717" green="1" blue="0.34807942549999998" alpha="1" colorSpace="calibratedRGB"/>
@@ -964,6 +964,7 @@
                         <outlet property="lbToolbarTitle" destination="RJE-Hu-oDM" id="nCW-fh-Pst"/>
                         <outlet property="lbWindowTitle" destination="663-n7-Jwn" id="0p7-02-Veb"/>
                         <outlet property="svScheduleList" destination="bHp-Km-KNL" id="aSi-lC-w6H"/>
+                        <segue destination="Uh5-wZ-ogP" kind="modal" identifier="SegueEvent" modalPresentationStyle="currentContext" modalTransitionStyle="coverVertical" id="0Qp-db-Qb0"/>
                     </connections>
                 </viewController>
                 <placeholder placeholderIdentifier="IBFirstResponder" id="rq0-MV-vyl" userLabel="First Responder" sceneMemberID="firstResponder"/>
@@ -1489,16 +1490,218 @@
                         <outlet property="barTitle" destination="v7W-BZ-qle" id="aQB-IA-P19"/>
                         <outlet property="itineraryContainer" destination="HZX-gN-1YI" id="1lZ-0m-TwZ"/>
                         <outlet property="itineraryList" destination="3lO-kN-Y0S" id="Vf3-t6-l0Y"/>
+                        <segue destination="Uh5-wZ-ogP" kind="popoverPresentation" identifier="SegueItinerary" popoverAnchorView="Tll-v9-w0T" id="zCO-aN-4xt">
+                            <popoverArrowDirection key="popoverArrowDirection" up="YES" down="YES" left="YES" right="YES"/>
+                        </segue>
                     </connections>
                 </viewController>
                 <placeholder placeholderIdentifier="IBFirstResponder" id="IHt-fO-2Q0" userLabel="First Responder" sceneMemberID="firstResponder"/>
             </objects>
             <point key="canvasLocation" x="1302" y="-403"/>
         </scene>
+        <!--Event-->
+        <scene sceneID="CJp-1C-D1Z">
+            <objects>
+                <viewController title="Event" id="Uh5-wZ-ogP" customClass="EventController" customModule="app" customModuleProvider="target" sceneMemberID="viewController">
+                    <layoutGuides>
+                        <viewControllerLayoutGuide type="top" id="oTc-Dn-jSp"/>
+                        <viewControllerLayoutGuide type="bottom" id="GQn-fc-wCY"/>
+                    </layoutGuides>
+                    <view key="view" contentMode="scaleAspectFill" id="Whe-r6-tkx" userLabel="Section">
+                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+                        <subviews>
+                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Pzh-mM-oRb">
+                                <rect key="frame" x="14.5" y="14.5" width="345" height="637"/>
+                                <subviews>
+                                    <textView clipsSubviews="YES" multipleTouchEnabled="YES" userInteractionEnabled="NO" contentMode="scaleToFill" bounces="NO" scrollEnabled="NO" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" editable="NO" text="Localizacion" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="TdI-Mq-pQ8" userLabel="Title">
+                                        <rect key="frame" x="0.0" y="0.0" width="345" height="33"/>
+                                        <color key="backgroundColor" red="0.0" green="0.47058823529999999" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                        <color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+                                        <fontDescription key="fontDescription" type="boldSystem" pointSize="14"/>
+                                        <textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
+                                    </textView>
+                                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="p9X-b1-qyz" userLabel="Entry">
+                                        <rect key="frame" x="10" y="43" width="325" height="584"/>
+                                        <subviews>
+                                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Time" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="uS1-ic-OaV" userLabel="Time">
+                                                <rect key="frame" x="10" y="10" width="305" height="22"/>
+                                                <constraints>
+                                                    <constraint firstAttribute="height" constant="22" id="d1L-1Q-VmO"/>
+                                                </constraints>
+                                                <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/>
+                                                <color key="textColor" red="0.1529411765" green="0.33333333329999998" blue="0.45098039220000002" alpha="1" colorSpace="calibratedRGB"/>
+                                                <nil key="highlightedColor"/>
+                                            </label>
+                                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Text" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="3" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="hVJ-CB-Hgq">
+                                                <rect key="frame" x="9.5" y="42" width="305" height="70"/>
+                                                <constraints>
+                                                    <constraint firstAttribute="height" constant="70" id="fcs-jf-hAG"/>
+                                                </constraints>
+                                                <fontDescription key="fontDescription" type="system" pointSize="17"/>
+                                                <nil key="textColor"/>
+                                                <nil key="highlightedColor"/>
+                                            </label>
+                                            <imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Pinpoint" translatesAutoresizingMaskIntoConstraints="NO" id="V1S-rW-K5b">
+                                                <rect key="frame" x="20" y="142" width="30" height="50"/>
+                                                <constraints>
+                                                    <constraint firstAttribute="width" constant="30" id="Vzh-tD-dAp"/>
+                                                    <constraint firstAttribute="height" constant="50" id="gsL-Ww-tn3"/>
+                                                </constraints>
+                                            </imageView>
+                                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Place asdaskldkjas  askjdhasjhk asdkjh" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Dae-xA-1hx" userLabel="Place">
+                                                <rect key="frame" x="70" y="122" width="235" height="40"/>
+                                                <constraints>
+                                                    <constraint firstAttribute="height" constant="40" id="Gbn-tP-CDH"/>
+                                                </constraints>
+                                                <fontDescription key="fontDescription" type="system" pointSize="15"/>
+                                                <nil key="textColor"/>
+                                                <nil key="highlightedColor"/>
+                                            </label>
+                                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Address dsajhfjkdsfkl asfdioadsjkfdsndsf djdsj" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="YgS-fT-YvY">
+                                                <rect key="frame" x="80" y="162" width="215" height="35"/>
+                                                <constraints>
+                                                    <constraint firstAttribute="height" constant="35" id="N0Q-U8-hfI"/>
+                                                </constraints>
+                                                <fontDescription key="fontDescription" type="italicSystem" pointSize="14"/>
+                                                <color key="textColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/>
+                                                <nil key="highlightedColor"/>
+                                            </label>
+                                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="LsE-aH-N1R" customClass="GMSMapView">
+                                                <rect key="frame" x="10" y="242" width="305" height="277"/>
+                                                <color key="backgroundColor" red="1" green="0.20334201390000001" blue="0.32001410590000001" alpha="1" colorSpace="calibratedRGB"/>
+                                                <userDefinedRuntimeAttributes>
+                                                    <userDefinedRuntimeAttribute type="color" keyPath="borderColor">
+                                                        <color key="value" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
+                                                    </userDefinedRuntimeAttribute>
+                                                    <userDefinedRuntimeAttribute type="number" keyPath="borderWidth">
+                                                        <real key="value" value="1"/>
+                                                    </userDefinedRuntimeAttribute>
+                                                    <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                                        <real key="value" value="3"/>
+                                                    </userDefinedRuntimeAttribute>
+                                                </userDefinedRuntimeAttributes>
+                                            </view>
+                                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="mGX-dR-mu2">
+                                                <rect key="frame" x="65" y="529" width="195" height="45"/>
+                                                <color key="backgroundColor" red="0.070588235289999995" green="0.27058823529999998" blue="0.4039215686" alpha="1" colorSpace="calibratedRGB"/>
+                                                <constraints>
+                                                    <constraint firstAttribute="height" constant="45" id="mty-PM-ITe"/>
+                                                </constraints>
+                                                <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
+                                                <state key="normal" title="Cerrar">
+                                                    <color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+                                                </state>
+                                                <userDefinedRuntimeAttributes>
+                                                    <userDefinedRuntimeAttribute type="color" keyPath="borderColor">
+                                                        <color key="value" red="0.0" green="0.47058823529999999" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                                    </userDefinedRuntimeAttribute>
+                                                    <userDefinedRuntimeAttribute type="number" keyPath="borderWidth">
+                                                        <real key="value" value="2"/>
+                                                    </userDefinedRuntimeAttribute>
+                                                    <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                                        <real key="value" value="4"/>
+                                                    </userDefinedRuntimeAttribute>
+                                                </userDefinedRuntimeAttributes>
+                                            </button>
+                                        </subviews>
+                                        <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+                                        <constraints>
+                                            <constraint firstItem="hVJ-CB-Hgq" firstAttribute="top" secondItem="uS1-ic-OaV" secondAttribute="bottom" constant="10" id="0Xx-dX-W67"/>
+                                            <constraint firstItem="YgS-fT-YvY" firstAttribute="top" secondItem="Dae-xA-1hx" secondAttribute="bottom" id="5F1-QH-ldA"/>
+                                            <constraint firstItem="Dae-xA-1hx" firstAttribute="top" secondItem="V1S-rW-K5b" secondAttribute="top" constant="-20" id="99i-3d-OrW"/>
+                                            <constraint firstItem="V1S-rW-K5b" firstAttribute="leading" secondItem="p9X-b1-qyz" secondAttribute="leading" constant="20" id="Ehc-g1-4vU"/>
+                                            <constraint firstItem="mGX-dR-mu2" firstAttribute="centerX" secondItem="p9X-b1-qyz" secondAttribute="centerX" id="FQH-JN-a4w"/>
+                                            <constraint firstItem="uS1-ic-OaV" firstAttribute="width" secondItem="p9X-b1-qyz" secondAttribute="width" constant="-20" id="KAS-74-SkE"/>
+                                            <constraint firstItem="mGX-dR-mu2" firstAttribute="width" secondItem="p9X-b1-qyz" secondAttribute="width" multiplier="0.6" id="LNw-p9-1Ps"/>
+                                            <constraint firstItem="Dae-xA-1hx" firstAttribute="trailing" secondItem="p9X-b1-qyz" secondAttribute="trailing" constant="-20" id="Le1-3C-kRK"/>
+                                            <constraint firstItem="LsE-aH-N1R" firstAttribute="top" secondItem="V1S-rW-K5b" secondAttribute="bottom" constant="50" id="MCp-6n-v4V"/>
+                                            <constraint firstItem="hVJ-CB-Hgq" firstAttribute="width" secondItem="uS1-ic-OaV" secondAttribute="width" id="NKz-Nb-pVn"/>
+                                            <constraint firstItem="LsE-aH-N1R" firstAttribute="centerX" secondItem="p9X-b1-qyz" secondAttribute="centerX" id="QgF-Lt-FhS"/>
+                                            <constraint firstItem="YgS-fT-YvY" firstAttribute="width" secondItem="Dae-xA-1hx" secondAttribute="width" constant="-20" id="RYS-JN-ifV"/>
+                                            <constraint firstItem="LsE-aH-N1R" firstAttribute="bottom" secondItem="mGX-dR-mu2" secondAttribute="top" constant="-10" id="Sn5-V9-5D9"/>
+                                            <constraint firstItem="hVJ-CB-Hgq" firstAttribute="centerX" secondItem="uS1-ic-OaV" secondAttribute="centerX" id="Uut-4g-fU7"/>
+                                            <constraint firstAttribute="bottom" secondItem="mGX-dR-mu2" secondAttribute="bottom" constant="10" id="c1g-0m-IAv"/>
+                                            <constraint firstItem="uS1-ic-OaV" firstAttribute="top" secondItem="p9X-b1-qyz" secondAttribute="top" constant="10" id="esJ-Dq-yAN"/>
+                                            <constraint firstItem="LsE-aH-N1R" firstAttribute="width" secondItem="p9X-b1-qyz" secondAttribute="width" constant="-20" id="mHY-j9-73b"/>
+                                            <constraint firstItem="uS1-ic-OaV" firstAttribute="centerX" secondItem="p9X-b1-qyz" secondAttribute="centerX" id="mbE-Hi-ycL"/>
+                                            <constraint firstItem="Dae-xA-1hx" firstAttribute="leading" secondItem="V1S-rW-K5b" secondAttribute="trailing" constant="20" id="nSZ-b4-vsW"/>
+                                            <constraint firstItem="YgS-fT-YvY" firstAttribute="centerX" secondItem="Dae-xA-1hx" secondAttribute="centerX" id="qoJ-AG-kYy"/>
+                                            <constraint firstItem="V1S-rW-K5b" firstAttribute="top" secondItem="hVJ-CB-Hgq" secondAttribute="bottom" constant="30" id="xld-5s-PKk"/>
+                                        </constraints>
+                                        <userDefinedRuntimeAttributes>
+                                            <userDefinedRuntimeAttribute type="color" keyPath="borderColor">
+                                                <color key="value" red="0.42745098040000001" green="0.41176470590000003" blue="0.56470588239999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                            </userDefinedRuntimeAttribute>
+                                            <userDefinedRuntimeAttribute type="number" keyPath="borderWidth">
+                                                <integer key="value" value="1"/>
+                                            </userDefinedRuntimeAttribute>
+                                            <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                                <integer key="value" value="3"/>
+                                            </userDefinedRuntimeAttribute>
+                                        </userDefinedRuntimeAttributes>
+                                    </view>
+                                </subviews>
+                                <color key="backgroundColor" red="0.70980392160000005" green="0.82745098039999998" blue="0.8980392157" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                <constraints>
+                                    <constraint firstAttribute="bottom" secondItem="p9X-b1-qyz" secondAttribute="bottom" constant="10" id="8Ft-cW-Vzq"/>
+                                    <constraint firstItem="p9X-b1-qyz" firstAttribute="width" secondItem="Pzh-mM-oRb" secondAttribute="width" constant="-20" id="8aS-wx-yQR"/>
+                                    <constraint firstItem="p9X-b1-qyz" firstAttribute="centerX" secondItem="Pzh-mM-oRb" secondAttribute="centerX" id="LUQ-uT-amE"/>
+                                    <constraint firstItem="TdI-Mq-pQ8" firstAttribute="width" secondItem="Pzh-mM-oRb" secondAttribute="width" id="ZZb-OS-ppR"/>
+                                    <constraint firstItem="TdI-Mq-pQ8" firstAttribute="top" secondItem="Pzh-mM-oRb" secondAttribute="top" id="Zwb-ch-MpX"/>
+                                    <constraint firstItem="TdI-Mq-pQ8" firstAttribute="centerX" secondItem="Pzh-mM-oRb" secondAttribute="centerX" id="eqQ-i9-kAX"/>
+                                    <constraint firstItem="p9X-b1-qyz" firstAttribute="top" secondItem="TdI-Mq-pQ8" secondAttribute="bottom" constant="10" id="ezI-gR-vy7"/>
+                                </constraints>
+                                <userDefinedRuntimeAttributes>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="borderWidth">
+                                        <real key="value" value="1"/>
+                                    </userDefinedRuntimeAttribute>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                        <real key="value" value="8"/>
+                                    </userDefinedRuntimeAttribute>
+                                    <userDefinedRuntimeAttribute type="color" keyPath="borderColor">
+                                        <color key="value" red="0.0" green="0.0" blue="0.066666666669999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                    </userDefinedRuntimeAttribute>
+                                </userDefinedRuntimeAttributes>
+                            </view>
+                        </subviews>
+                        <constraints>
+                            <constraint firstItem="Pzh-mM-oRb" firstAttribute="centerY" secondItem="Whe-r6-tkx" secondAttribute="centerY" id="JIZ-Dq-7XP"/>
+                            <constraint firstItem="Pzh-mM-oRb" firstAttribute="height" secondItem="Whe-r6-tkx" secondAttribute="height" constant="-30" id="ZqF-ZH-E1R"/>
+                            <constraint firstItem="Pzh-mM-oRb" firstAttribute="centerX" secondItem="Whe-r6-tkx" secondAttribute="centerX" id="cOh-nb-Sp4"/>
+                            <constraint firstItem="Pzh-mM-oRb" firstAttribute="width" secondItem="Whe-r6-tkx" secondAttribute="width" constant="-30" id="g05-vA-bat"/>
+                        </constraints>
+                        <userDefinedRuntimeAttributes>
+                            <userDefinedRuntimeAttribute type="number" keyPath="borderWidth">
+                                <real key="value" value="0.0"/>
+                            </userDefinedRuntimeAttribute>
+                            <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                <real key="value" value="0.0"/>
+                            </userDefinedRuntimeAttribute>
+                        </userDefinedRuntimeAttributes>
+                    </view>
+                    <connections>
+                        <outlet property="btClose" destination="mGX-dR-mu2" id="ldW-4y-Rkd"/>
+                        <outlet property="eventAddress" destination="YgS-fT-YvY" id="w0Y-CG-Cc5"/>
+                        <outlet property="eventLocation" destination="Dae-xA-1hx" id="iQo-Tg-jJ5"/>
+                        <outlet property="eventMap" destination="LsE-aH-N1R" id="3Hq-Ig-SmJ"/>
+                        <outlet property="eventText" destination="hVJ-CB-Hgq" id="Mx7-6n-d2u"/>
+                        <outlet property="eventTime" destination="uS1-ic-OaV" id="CyB-ua-P1g"/>
+                        <outlet property="eventTitle" destination="TdI-Mq-pQ8" id="Qjv-Cn-HLQ"/>
+                    </connections>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="iqH-Ju-whF" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="-1570" y="277"/>
+        </scene>
     </scenes>
     <resources>
         <image name="GM" width="120" height="120"/>
         <image name="Logo" width="83" height="83"/>
         <image name="PhotoPlaceholder" width="170" height="108"/>
+        <image name="Pinpoint" width="10" height="13"/>
     </resources>
+    <inferredMetricsTieBreakers>
+        <segue reference="0Qp-db-Qb0"/>
+    </inferredMetricsTieBreakers>
 </document>

+ 5 - 1
app/BlogView.swift

@@ -22,7 +22,7 @@ import Foundation
 import CoreData
 import UIKit
 /**
-Class to handle the home view.
+Class to handle the blog view.
 */
 class BlogView: UIView {
 	
@@ -39,6 +39,10 @@ class BlogView: UIView {
 	var context: NSManagedObjectContext? = nil;
 	var lang: String? = nil
 	
+
+	/**
+	Default constructor for the interface builder.
+	*/
 	override init(frame: CGRect){
 		super.init(frame: frame)
 	}

+ 1 - 1
app/Entry.swift

@@ -22,7 +22,7 @@ import Foundation
 import UIKit
 
 /**
-Extension of UIView to be formatted as sections.
+Extension of UIView to be formatted as entries or rows.
 */
 class Entry: UIView {
 	

+ 212 - 0
app/EventController.swift

@@ -0,0 +1,212 @@
+// Copyright (C) 2016 Inigo Valentin
+//
+// This file is part of the Gasteizko Margolariak IOS app.
+//
+// The Gasteizko Margolariak IOS app is free software: you can
+// redistribute it and/or modify it under the terms of the
+// GNU General Public License as published by the Free Software
+// Foundation, either version 3 of the License, or (at your
+// option) any later version.
+//
+// The Gasteizko Margolariak IOS app is distributed in the
+// hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
+// Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with the Gasteizko Margolariak IOS app.
+// If not, see <http://www.gnu.org/licenses/>.
+
+import UIKit
+import CoreData
+import GoogleMaps
+
+/**
+The view controller of the app.
+*/
+class EventController: UIViewController, UIGestureRecognizerDelegate {
+
+	@IBOutlet weak var eventTitle: UITextView!
+	@IBOutlet weak var eventText: UILabel!
+	@IBOutlet weak var eventTime: UILabel!
+	@IBOutlet weak var eventLocation: UILabel!
+	@IBOutlet weak var eventMap: GMSMapView!
+	@IBOutlet weak var btClose: UIButton!
+	@IBOutlet weak var eventAddress: UILabel!
+	
+	var id: Int = -1
+	var passId: Int = -1
+	var delegate: AppDelegate?
+	
+	
+	/**
+	Gets the application context.
+	:return: The application context.
+	*/
+	func getContext () -> NSManagedObjectContext {
+		return NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
+	}
+	
+	
+	/**
+	Run when the app loads. Sets everything up.
+	*/
+	override func viewDidLoad() {
+		
+		// Populate photo array.
+		let context = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
+		let appDelegate = UIApplication.shared.delegate as! AppDelegate
+		let lang : String = getLanguage()
+		context.persistentStoreCoordinator = appDelegate.persistentStoreCoordinator
+		let fetchRequest: NSFetchRequest<Festival_event> = Festival_event.fetchRequest()
+		fetchRequest.predicate = NSPredicate(format: "id = %i", id)
+		do {
+			let searchResults = try context.fetch(fetchRequest)
+			var name: String = ""
+			var text: String = ""
+			var start: NSDate
+			var placeId: Int = -1
+			var place: [Any]
+			var placeName: String = ""
+			var placeAddress: String = ""
+			var lat: Double = 0.0
+			var lon: Double = 0.0
+			if searchResults.count > 0{
+				let r = searchResults[0]
+				
+				name = r.value(forKey: "title_\(lang)")! as! String
+				text = r.value(forKey: "description_\(lang)")! as! String
+				start = r.value(forKey: "start")! as! NSDate
+				placeId = r.value(forKey: "place")! as! Int
+				place = getPlace(place: placeId, lang: getLanguage(), context: context)
+				placeName = place[0] as! String
+				placeAddress = place[1] as! String
+				lat = place[2] as! Double
+				lon = place[3] as! Double
+				
+				// Set labels
+				eventTitle.text = " \(name.decode().stripHtml())"
+				if text.length > 0{
+					eventText.text = " \(text.decode().stripHtml())"
+				}
+				else{
+					self.eventText.isHidden = true
+				}
+				self.eventTime.text = formatTime(date: start)
+				self.eventLocation.text = placeName.decode().stripHtml()
+				if placeAddress.length == 0 || placeAddress == placeName{
+					self.eventAddress.isHidden = true
+				}
+				else{
+					self.eventAddress.text = placeAddress.decode().stripHtml()
+				}
+				
+				// Set map marker
+				let marker = GMSMarker()
+				marker.position = CLLocationCoordinate2D(latitude: lat, longitude: lon)
+				marker.title = name
+				marker.map = self.eventMap
+				
+				// Center map
+				eventMap.isMyLocationEnabled = true
+				let camera: GMSCameraPosition = GMSCameraPosition.camera(withLatitude: lat, longitude: lon, zoom: 12.0)
+				self.eventMap.camera = camera
+				
+			}
+			
+		}
+		catch {
+			NSLog(":EVENT:ERROR: Error getting info from event \(id): \(error)")
+		}
+		
+		super.viewDidLoad()
+		
+		// Set button action
+		self.btClose.addTarget(self, action: #selector(self.back), for: .touchUpInside)
+	}
+	
+	
+	/**
+	Dismisses the controller.
+	*/
+	func back() {
+		self.dismiss(animated: true, completion: nil)
+	}
+	
+	
+	/**
+	Dispose of any resources that can be recreated.
+	*/
+	override func didReceiveMemoryWarning() {
+		super.didReceiveMemoryWarning()
+	}
+	
+	/**
+	Extracts the time from a date to a string.
+	:param: text The date.
+	:return: Time, in string format.
+	*/
+	func formatTime(date: NSDate) -> String{
+
+		let calendar = Calendar.current
+		let hour: Int = calendar.component(.hour, from: date as Date)
+		let minute: Int = calendar.component(.minute, from: date as Date)
+		
+		var strTime = ""
+		if minute <= 9{
+			strTime = "\(hour):0\(minute)"
+		}
+		else{
+			strTime = "\(hour):\(minute)"
+		}
+		
+		return strTime
+	}
+	
+	
+	/**
+	Gets info about a place in the device language.
+	:param: place Place id.
+	:param: lang Device language (only 'es', 'en', or 'eu').
+	:param: context Application context.
+	:return: String array. 0-index item contains the place name. The 1-index one contains the address.
+	*/
+	func getPlace(place: Int, lang: String, context: NSManagedObjectContext) -> [Any]{
+		var placeName: String = ""
+		var placeAddress: String = ""
+		var lat: Double = 0.0
+		var lon: Double = 0.0
+		let fetchRequest: NSFetchRequest<Place> = Place.fetchRequest()
+		fetchRequest.predicate = NSPredicate(format: "id = %i", place)
+		do {
+			let searchResults = try context.fetch(fetchRequest)
+			let r: NSManagedObject = searchResults[0]
+			placeName = r.value(forKey: "name_\(lang)")! as! String
+			placeAddress = r.value(forKey: "address_\(lang)")! as! String
+			lat = r.value(forKey: "lat")! as! Double
+			lon = r.value(forKey: "lon")! as! Double
+		}
+		catch{
+			NSLog(":FUTUREACTIVITY:ERROR: Error getting infor about place \(place): \(error)")
+		}
+		return [placeName, placeAddress, lat, lon]
+	}
+	
+	
+	/**
+	Gets the device language. The only recognized languages are Spanish, English and Basque.
+	If the device has another language, Spanish will be selected by default.
+	:return: Two-letter language code.
+	*/
+	func getLanguage() -> String{
+		let pre = NSLocale.preferredLanguages[0].subStr(start: 0, end: 1)
+		if(pre == "es" || pre == "en" || pre == "eu"){
+			return pre
+		}
+		else{
+			return "es"
+		}
+	}
+}
+

+ 4 - 1
app/FetchLocation.swift

@@ -28,13 +28,16 @@ class FetchLocation{
 	
 	
 	/**
-	Default constructor
+	Default constructor.
 	*/
 	init(){
 		fetch()
 	}
 	
 	
+	/**
+	Fetches location reports form the server in the background.
+	*/
 	func fetch(){
 		NSLog(":LOCATION:LOG: Fetching location...")
 		

+ 26 - 0
app/FutureActivityViewController.swift

@@ -88,6 +88,7 @@ class FutureActivityViewController: UIViewController, UIGestureRecognizerDelegat
 		
 		let context = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
 		let appDelegate = UIApplication.shared.delegate as! AppDelegate
+		appDelegate.futureActivityController = self
 		let lang : String = getLanguage()
 		context.persistentStoreCoordinator = appDelegate.persistentStoreCoordinator
 		let fetchRequest: NSFetchRequest<Activity> = Activity.fetchRequest()
@@ -289,6 +290,31 @@ class FutureActivityViewController: UIViewController, UIGestureRecognizerDelegat
 	}
 	
 	
+	/**
+	Shows an itinerary dialog.
+	:param: id The itinerary id.
+	*/
+	func showItinerary(id: Int){
+		self.passId = id
+		// TODO
+		NSLog(":FUTUREACTIVITY:TODO: Implement segue")
+		//performSegue(withIdentifier: "SegueItinerary", sender: nil)
+	}
+	
+	
+	/**
+	Run before performing a segue.
+	Assigns id if neccessary.
+	:param: segue The segue to perform.
+	:sender: The calling view.
+	*/
+	override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
+		if segue.identifier == "SegueItinerary"{
+			(segue.destination as! EventController).id = passId
+		}
+	}
+	
+	
 	/**
 	Gets the device language. The only recognized languages are Spanish, English and Basque.
 	If the device has another language, Spanish will be selected by default.

+ 7 - 13
app/GalleryView.swift

@@ -21,8 +21,10 @@
 import Foundation
 import CoreData
 import UIKit
+
+
 /**
-Class to handle the home view.
+Class to handle the gallery view.
 */
 class GalleryView: UIView {
 	
@@ -39,7 +41,7 @@ class GalleryView: UIView {
 	
 	
 	/**
-	Run when the view is started.
+	Default constructor for the interface builder.
 	*/
 	override init(frame: CGRect){
 		super.init(frame: frame)
@@ -139,19 +141,11 @@ class GalleryView: UIView {
 				// Add to the rows array
 				self.rows.append(row)
 			}
-		} catch {
-			NSLog(":GALLERY:ERROR: Error with request: \(error)")
 		}
-		
-		//Always at the end: update scrollview
-		var h: Int = 0
-		for view in scrollView.subviews {
-			//contentRect = contentRect.union(view.frame);
-			h = h + Int(view.frame.height) + 30 // TODO Why 30?
+		catch {
+			NSLog(":GALLERY:ERROR: Error with request: \(error)")
 		}
-		// TODO: Calculate at the end
-		self.scrollView.contentSize.height = 2500 //CGFloat(h);
-		
+				
 		self.setUpRowsTapRecognizers()
 	}
 	

+ 7 - 4
app/HomeView.swift

@@ -21,6 +21,8 @@
 import Foundation
 import CoreData
 import UIKit
+
+
 /**
  Class to handle the home view.
  */
@@ -63,7 +65,8 @@ class HomeView: UIView {
 	
 	
 	/**
-	 Run when the view is started.
+	Run when the view is started.
+	:param: coder Coder.
 	*/
 	required init?(coder aDecoder: NSCoder) {
 		
@@ -138,7 +141,6 @@ class HomeView: UIView {
 	If no location is reported, it hiddes the section.
 	*/
 	func setUpLocation(){
-		// TODO: Also set up tap recognizer.
 		let defaults = UserDefaults.standard
 		if (defaults.value(forKey: "GMLocLat") != nil && defaults.value(forKey: "GMLocLon") != nil){
 			let lat = defaults.value(forKey: "GMLocLat") as! Double
@@ -228,7 +230,7 @@ class HomeView: UIView {
 					
 				}
 				catch {
-					NSLog(":LABLANCA:ERROR: Error getting festivals info: \(error)")
+					NSLog(":HOME:ERROR: Error getting setting the La Blanca section up: \(error)")
 				}
 			}
 			else{
@@ -438,7 +440,8 @@ class HomeView: UIView {
 				parent.addArrangedSubview(row)
 				
 			}
-		} catch {
+		}
+		catch {
 			NSLog(":HOME:ERROR: Error loading past activities: \(error)")
 		}
 	}

+ 6 - 7
app/LablancaView.swift

@@ -21,8 +21,10 @@
 import Foundation
 import CoreData
 import UIKit
+
+
 /**
-Class to handle the home view.
+Class to handle the La Blanca view.
 */
 class LablancaView: UIView {
 
@@ -37,13 +39,13 @@ class LablancaView: UIView {
 	@IBOutlet weak var fOfferList: UIStackView!	// Stack view to hold the offer list.
 	@IBOutlet weak var fDayList: UIStackView!	// Stack view to hold the single days price list.
 	
-	
 	// App delegate
 	var delegate: AppDelegate? = nil
 	
 	
 	/**
-	Run when the view is started.
+	Default constructor for the interface builder.
+	:param: frame Window frame.
 	*/
 	override init(frame: CGRect){
 		super.init(frame: frame)
@@ -77,6 +79,7 @@ class LablancaView: UIView {
 		}
 	}
 
+
 	/**
 	Displays the section to be shown while (and near) the La Blanca festivals.
 	*/	
@@ -131,7 +134,6 @@ class LablancaView: UIView {
 		let tapRecognizerGMSchedule = UITapGestureRecognizer(target: self, action: #selector(openGMSchedule(_:)))
 		fBtGMSchedule.isUserInteractionEnabled = true
 		fBtGMSchedule.addGestureRecognizer(tapRecognizerGMSchedule)
-
 		
 		// Get info about the days and offers.
 		let dateFormatter = DateFormatter()
@@ -243,13 +245,11 @@ class LablancaView: UIView {
 	func showNoFestivals(){
 		NSLog(":LABLANCA:LOG: Showing no festivals section.")
 		self.fWindow.isHidden = true
-		// Nothing else to be done.
 	}
 	
 
 	/**
 	Commands the view controller to show the city schedule view.
-	:param: sender The view that triggered the event.
 	*/
 	func openSchedule(_ sender:UITapGestureRecognizer? = nil){
 		let delegate: AppDelegate = UIApplication.shared.delegate as! AppDelegate
@@ -259,7 +259,6 @@ class LablancaView: UIView {
 
 	/**
 	Commands the view controller to show the Gasteizko Margolariak schedule view.
-	:param: sender The view that triggered the event.
 	*/
 	func openGMSchedule(_ sender:UITapGestureRecognizer? = nil){
 		let delegate: AppDelegate = UIApplication.shared.delegate as! AppDelegate

+ 28 - 4
app/LocationView.swift

@@ -22,8 +22,10 @@ import Foundation
 import CoreData
 import UIKit
 import GoogleMaps
+
+
 /**
-Class to handle the home view.
+Class to handle the location view.
 */
 class LocationView: UIView {
 	
@@ -40,6 +42,11 @@ class LocationView: UIView {
 	
 	var locationTimer: Timer? = nil
 	
+
+	/**
+	Default constructor for the interface builder.
+	:param: frame View frame.
+	*/
 	override init(frame: CGRect){
 		
 		// Set controller
@@ -79,7 +86,9 @@ class LocationView: UIView {
 	
 	
 	/**
-	I am not sure what does this do...
+	Enables the user location dot in the map, checking for permission.
+	:param: manager Location manager used to get the location.
+	:param: didChangeAuthorizationStatus status Permission status
 	*/
 	func locationManager(manager: CLLocationManager!, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
 		if status == CLAuthorizationStatus.authorizedWhenInUse {
@@ -89,7 +98,7 @@ class LocationView: UIView {
 	
 	
 	/**
-	Get new location
+	Get new user location and recalculates distance to GM .
 	*/
 	func getNewLocation(){
 		let defaults = UserDefaults.standard
@@ -132,11 +141,24 @@ class LocationView: UIView {
 	}
 
 
+	/**
+	Converts degrees to radians.
+	:param: degrees Angle in degrees.
+	:return: Angle in radiands.
+	*/
 	func degreesToRadians(degrees: Double) -> Double {
 		return degrees * Double.pi / 180;
 	}
 
 
+	/**
+	Calculates the distance, in integer meters, between two coordinates.
+	:param: lat1 Latitude component of the first point.
+	:param: lon1 Longitude component of the first point.
+	:param: lat2 Latitude component of the second point.
+	:param: lon2 Longitude component of the second point.
+	:return: Distance, in integer meters, between the points.
+	*/
 	func calculateDistance(lat1: Double, lon1: Double, lat2: Double, lon2: Double) -> Int {
 		let eRadius: Double = 6371
 
@@ -152,7 +174,9 @@ class LocationView: UIView {
 		return Int(m)
 	}
 	
-	/*func observeValueForKeyPath(keyPath: String, ofObject object: AnyObject, change: [NSObject : AnyObject], context: UnsafeMutableRawPointer) {
+	/*
+	// TODO: Whato does this do?
+	func observeValueForKeyPath(keyPath: String, ofObject object: AnyObject, change: [NSObject : AnyObject], context: UnsafeMutableRawPointer) {
 		if !didFindMyLocation {
 			let myLocation: CLLocation = change[NSKeyValueChangeNewKey] as CLLocation
 			map.camera = GMSCameraPosition.camera(withTarget: myLocation.coordinate, zoom: 10.0)

+ 36 - 12
app/Notifications.swift

@@ -23,8 +23,9 @@ import CoreData
 import UIKit
 import UserNotifications
 
+
 /**
-Class to handle server sync.
+Class to fetch notifications from the server.
 */
 class Notifications{
 	
@@ -45,13 +46,12 @@ class Notifications{
 	func buildUrl() -> URL{
 		
 		let url = URL(string: "https://margolariak.com/API/v1/notifications.php")
-		
 		return url!
 	}
 	
 	
 	/**
-	Performs an asynchronous sync.
+	Performs an asynchronous request.
 	It fetches the info from the server and stores as Core Data
 	:param: url The url to sync.
 	*/
@@ -186,12 +186,23 @@ class Notifications{
 						if #available(iOS 10.0, *) {
 							let content = UNMutableNotificationContent()
 							
-							// TODO Select language.
-							content.title = title_es
-							content.body = text_es
+							let lang = getLanguage()
+							switch lang{
+								case "en":
+									content.title = title_en
+									content.body = text_en
+									break;
+								case "eu":
+									content.title = title_eu
+									content.body = text_eu
+									break;
+								default:
+									content.title = title_es
+									content.body = text_es
+							}
 							content.sound = UNNotificationSound.default()
 							let trigger = UNTimeIntervalNotificationTrigger.init(timeInterval: 1, repeats: false)
-							let request = UNNotificationRequest.init(identifier: "Not", content: content, trigger: trigger)
+							let request = UNNotificationRequest.init(identifier: "Not\(id)", content: content, trigger: trigger)
 							
 							// Schedule the notification.
 							let center = UNUserNotificationCenter.current()
@@ -199,10 +210,10 @@ class Notifications{
 								(error) in
 								NSLog(":NOTIFICATION:ERROR: Error showing notification \(String(describing: error))")
 							}
-						} else {
-							// Fallback on earlier versions
 						}
-						// TODO Get language
+						else {
+							NSLog(":NOTIFICATION:ERROR: Can't send notifications in iOS versions lower than 10. Not showing notification \(id)")
+						}
 						
 					}
 					catch let error as NSError  {
@@ -218,6 +229,19 @@ class Notifications{
 			}
 		}
 	}
-	
-	
+
+	/**
+	Gets the device language. The only recognized languages are Spanish, English and Basque.
+	If the device has another language, Spanish will be selected by default.
+	:return: Two-letter language code.}
+	*/
+	func getLanguage() -> String{
+		let pre = NSLocale.preferredLanguages[0].subStr(start: 0, end: 1)
+		if(pre == "es" || pre == "en" || pre == "eu"){
+			return pre
+		}
+		else{
+			return "es"
+		}
+	}
 }

+ 4 - 2
app/PastActivityViewController.swift

@@ -19,6 +19,7 @@
 // If not, see <http://www.gnu.org/licenses/>.
 
 import UIKit
+
 import CoreData
 
 /**
@@ -78,8 +79,8 @@ class PastActivityViewController: UIViewController, UIGestureRecognizerDelegate
 	
 	
 	/**
-	Loads the selected post.
-	:param: id Post id.
+	Loads the selected activity.
+	:param: id Activity id.
 	*/
 	public func loadActivity(id: Int){
 		
@@ -187,6 +188,7 @@ class PastActivityViewController: UIViewController, UIGestureRecognizerDelegate
 		
 		return strDate
 	}
+
 	
 	/**
 	Gets the device language. The only recognized languages are Spanish, English and Basque.

+ 5 - 4
app/PhotoViewController.swift

@@ -21,8 +21,9 @@
 import UIKit
 import CoreData
 
+
 /**
-The view controller of the app.
+The controller to show photos.
 */
 class PhotoViewController: UIViewController, UIGestureRecognizerDelegate {
 
@@ -90,7 +91,7 @@ class PhotoViewController: UIViewController, UIGestureRecognizerDelegate {
 				self.albumTitle = r.value(forKey: "title_\(lang)")! as! String
 			}
 			catch {
-				NSLog(":GALLERYCONTROLLER:ERROR: Error getting album info: \(error)")
+				NSLog(":PHOTO:ERROR: Error getting album info: \(error)")
 			}
 			
 		} catch {
@@ -149,7 +150,7 @@ class PhotoViewController: UIViewController, UIGestureRecognizerDelegate {
 	
 	/**
 	Loads a photo in the viewer.
-	:param: id
+	:param: id Photo id.
 	*/
 	public func loadPhoto(id: Int){
 		
@@ -217,12 +218,12 @@ class PhotoViewController: UIViewController, UIGestureRecognizerDelegate {
 		}
 	}
 	
-
 	
 	/**
 	Formats a date to the desired language.
 	:param: text The date.
 	:param: lang Device language (only 'es', 'en', or 'eu').
+	:return: Human readable string in the required language.
 	*/
 	func formatDate(date: NSDate, lang: String) -> String{
 		

+ 19 - 6
app/PostViewController.swift

@@ -21,8 +21,9 @@
 import UIKit
 import CoreData
 
+
 /**
-The view controller of the app.
+View controller to show a post.
 */
 class PostViewController: UIViewController, UIGestureRecognizerDelegate {
 	
@@ -37,6 +38,11 @@ class PostViewController: UIViewController, UIGestureRecognizerDelegate {
 	var passId: Int = -1
 	var delegate: AppDelegate?
 	
+
+	/**
+	Gets the application context.
+	:return: Application context.
+	*/
 	func getContext () -> NSManagedObjectContext {
 		return NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
 	}
@@ -55,6 +61,9 @@ class PostViewController: UIViewController, UIGestureRecognizerDelegate {
 	}
 		
 	
+	/**
+	Dismisses the controller, efectively going to the previous section.
+	*/
 	func back() {
 		self.dismiss(animated: true, completion: nil)
 	}
@@ -67,6 +76,11 @@ class PostViewController: UIViewController, UIGestureRecognizerDelegate {
 		super.didReceiveMemoryWarning()
 	}
 	
+
+	/**
+	Actually loads the post.
+	:param: id Post id.
+	*/
 	public func loadPost(id: Int){
 		
 		let context = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
@@ -77,14 +91,12 @@ class PostViewController: UIViewController, UIGestureRecognizerDelegate {
 		fetchRequest.predicate = NSPredicate(format: "id = %i", id)
 		
 		do {
-			//go get the results
 			let searchResults = try context.fetch(fetchRequest)
 			
 			var sTitle: String
 			var sText: String
 			var image: String
 			
-			//You need to convert to NSManagedObject to use 'for' loops
 			for r in searchResults as [NSManagedObject] {
 				
 				sTitle = r.value(forKey: "title_\(lang)")! as! String
@@ -100,7 +112,6 @@ class PostViewController: UIViewController, UIGestureRecognizerDelegate {
 				imgFetchRequest.sortDescriptors = imgSortDescriptors
 				imgFetchRequest.predicate = NSPredicate(format: "post == %i", id)
 				imgFetchRequest.fetchLimit = 1
-				//TODO get more images
 				do{
 					let imgSearchResults = try context.fetch(imgFetchRequest)
 					for imgR in imgSearchResults as [NSManagedObject]{
@@ -113,12 +124,14 @@ class PostViewController: UIViewController, UIGestureRecognizerDelegate {
 							self.postImage.setImage(localPath: path, remotePath: "https://margolariak.com/\(path)")
 						}
 					}
-				} catch {
+				}
+				catch {
 					NSLog(":POST:ERROR: Error getting image for post \(id): \(error)")
 				}
 				
 			}
-		} catch {
+		}
+		catch {
 			NSLog(":POST:ERROR: Error with request: \(error)")
 		}
 	}

+ 23 - 9
app/RowAlbum.swift

@@ -21,8 +21,9 @@
 import Foundation
 import UIKit
 
+
 /**
-Extension of UIView to be formatted as sections.
+Extension of UIView to be formatted as a row of an album.
 */
 @IBDesignable class RowAlbum: UIView {
 	
@@ -41,11 +42,13 @@ Extension of UIView to be formatted as sections.
 	var preview: [UIImageView] = []
 
 	/**
-	Default constructor
+	Default constructor.
+	:param: coder Coder.
 	*/
 	required init?(coder aDecoder: NSCoder) {
 		super.init(coder: aDecoder)
 	}
+
 	
 	/**
 	Loads the view from the xib with the same name as the class.
@@ -83,25 +86,30 @@ Extension of UIView to be formatted as sections.
 		//Populate review array
 		self.preview = [self.photo0, self.photo1]
 		
-		// Set tap recognizers
-		// TODO
-		//let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector (RowAlbum.openPhoto(_:)))
-		//tapRecognizer.delegate = (UIApplication.shared.delegate as! AppDelegate).controller
-		//self.addGestureRecognizer(tapRecognizer)
 	}
 	
+
 	/**
-	Default constructor for the interface builder
+	Default constructor for the interface builder.
+	:param: frame View frame.
 	*/
 	override init(frame: CGRect){
 		super.init(frame: frame)
 	}
 	
+
+	/**
+	Opens the photo in the left side in a new controller.
+	*/
 	func openLeftPhoto(_ sender:UITapGestureRecognizer? = nil){
 		let delegate: AppDelegate = UIApplication.shared.delegate as! AppDelegate
 		delegate.albumController?.showPhoto(album: self.id, photo: self.photoIds[0])
 	}
-	
+
+
+	/**
+	Opens the photo in the right side in a new controller.
+	*/
 	func openRightPhoto(_ sender:UITapGestureRecognizer? = nil){
 		let delegate: AppDelegate = UIApplication.shared.delegate as! AppDelegate
 		delegate.albumController?.showPhoto(album: self.id, photo: self.photoIds[1])
@@ -137,7 +145,13 @@ Extension of UIView to be formatted as sections.
 			}
 		}
 	}
+
 	
+	/**
+	Set the image id for both photos.
+	:param: left Id of the photo in the left.
+	:param: right Id of the photo on the right.
+	*/
 	func setIds(left: Int, right: Int){
 		self.photoIds[0] = left
 		self.photoIds[1] = right

+ 4 - 2
app/RowBlog.swift

@@ -38,7 +38,8 @@ Extension of UIView to be formatted as post rows.
 	
 	
 	/**
-	Default constructor
+	Default constructor.
+	:param: coder Coder.
 	*/
 	required init?(coder aDecoder: NSCoder) {
 		super.init(coder: aDecoder)
@@ -80,7 +81,8 @@ Extension of UIView to be formatted as post rows.
 	
 	
 	/**
-	Default constructor for the interface builder
+	Default constructor for the interface builder.
+	:param: frame View frame.
 	*/
 	override init(frame: CGRect){
 		super.init(frame: frame)

+ 6 - 4
app/RowFutureActivity.swift

@@ -21,6 +21,7 @@
 import Foundation
 import UIKit
 
+
 /**
 Extension of UIView to be formatted as future activity rows.
 */
@@ -40,7 +41,7 @@ Extension of UIView to be formatted as future activity rows.
 	
 	
 	/**
-	Default constructor
+	Default constructor.
 	:param: coder Coder.
 	*/
 	required init?(coder aDecoder: NSCoder) {
@@ -83,7 +84,8 @@ Extension of UIView to be formatted as future activity rows.
 	
 	
 	/**
-	Default constructor for the interface builder
+	Default constructor for the interface builder.
+	:param: frame View frame.
 	*/
 	override init(frame: CGRect){
 		super.init(frame: frame)
@@ -184,7 +186,7 @@ Extension of UIView to be formatted as future activity rows.
 	
 	/**
 	Changes the image of the activity.
-	If null or empty, the igage is hidden.
+	If null or empty, the image is hidden.
 	:param: path The new text.
 	*/
 	func setImage(filename: String){
@@ -200,7 +202,7 @@ Extension of UIView to be formatted as future activity rows.
 	
 	
 	/**
-	Opens an activity.
+	Opens an activity in a new controller.
 	*/
 	func openActivity(_ sender:UITapGestureRecognizer? = nil){
 		let delegate: AppDelegate = UIApplication.shared.delegate as! AppDelegate

+ 5 - 3
app/RowGallery.swift

@@ -42,7 +42,8 @@ Extension of UIView to be formatted as sections.
 	
 	
 	/**
-	Default constructor
+	Default constructor.
+	:param: coder Coder.
 	*/
 	required init?(coder aDecoder: NSCoder) {
 		super.init(coder: aDecoder)
@@ -89,7 +90,8 @@ Extension of UIView to be formatted as sections.
 	
 	
 	/**
-	Default constructor for the interface builder
+	Default constructor for the interface builder.
+	:param: frame View frame.
 	*/
 	override init(frame: CGRect){
 		super.init(frame: frame)
@@ -97,7 +99,7 @@ Extension of UIView to be formatted as sections.
 	
 	
 	/**
-	Opens an album.
+	Opens an album in other controller.
 	*/
 	func openAlbum(_ sender:UITapGestureRecognizer? = nil){
 		let delegate: AppDelegate = UIApplication.shared.delegate as! AppDelegate

+ 9 - 6
app/RowHomeBlog.swift

@@ -21,8 +21,9 @@
 import Foundation
 import UIKit
 
+
 /**
-Extension of UIView to be formatted as sections.
+Extension of UIView to be formatted as a row on the blog section of the home view.
 */
 @IBDesignable class RowHomeBlog: UIView {
 
@@ -38,7 +39,8 @@ Extension of UIView to be formatted as sections.
 	
 	
 	/**
-	Default constructor
+	Default constructor.
+	:param: coder Coder.
 	*/
 	required init?(coder aDecoder: NSCoder) {
 		super.init(coder: aDecoder)
@@ -80,7 +82,8 @@ Extension of UIView to be formatted as sections.
 	
 	
 	/**
-	Default constructor for the interface builder
+	Default constructor for the interface builder.
+	:param: frame View frame.
 	*/
 	override init(frame: CGRect){
 		super.init(frame: frame)
@@ -97,7 +100,7 @@ Extension of UIView to be formatted as sections.
 	
 	
 	/**
-	Changes the text of the text. Decodes HTML.
+	Changes the text of the post. Decodes HTML.
 	:param: text The new text.
 	*/
 	func setText(text: String){
@@ -106,7 +109,7 @@ Extension of UIView to be formatted as sections.
 	
 	
 	/**
-	Changes the image of the activity.
+	Changes the image of the post.
 	If null or empty, the igage is hidden.
 	:param: path The new text.
 	*/
@@ -123,7 +126,7 @@ Extension of UIView to be formatted as sections.
 	
 	
 	/**
-	Opens a post.
+	Opens a post in a controller.
 	*/
 	func openPost(_ sender:UITapGestureRecognizer? = nil){
 		let delegate: AppDelegate = UIApplication.shared.delegate as! AppDelegate

+ 7 - 4
app/RowHomeFutureActivities.swift

@@ -21,8 +21,9 @@
 import Foundation
 import UIKit
 
+
 /**
-Extension of UIView to be formatted as sections.
+Extension of UIView to be formatted as a future activity in the home screen.
 */
 @IBDesignable class RowHomeFutureActivities: UIView {
 	
@@ -38,7 +39,8 @@ Extension of UIView to be formatted as sections.
 	
 	
 	/**
-	Default constructor
+	Default constructor.
+	:param: coder Coder.
 	*/
 	required init?(coder aDecoder: NSCoder) {
 		super.init(coder: aDecoder)
@@ -80,7 +82,8 @@ Extension of UIView to be formatted as sections.
 	
 	
 	/**
-	Default constructor for the interface builder
+	Default constructor for the interface builder.
+	:param: fraom View frame.
 	*/
 	override init(frame: CGRect){
 		super.init(frame: frame)
@@ -123,7 +126,7 @@ Extension of UIView to be formatted as sections.
 	
 	
 	/**
-	Opens an activity.
+	Opens an activity in a controller.
 	*/
 	func openActivity(_ sender:UITapGestureRecognizer? = nil){
 		let delegate: AppDelegate = UIApplication.shared.delegate as! AppDelegate

+ 8 - 7
app/RowHomeGallery.swift

@@ -21,8 +21,9 @@
 import Foundation
 import UIKit
 
+
 /**
-Extension of UIView to be formatted as sections.
+Extension of UIView to be formatted as a the gallery section in the home view.
 */
 @IBDesignable class RowHomeGallery: UIView {
 	
@@ -39,7 +40,8 @@ Extension of UIView to be formatted as sections.
 	
 	
 	/**
-	Default constructor
+	Default constructor.
+	:param: coder Coder.
 	*/
 	required init?(coder aDecoder: NSCoder) {
 		super.init(coder: aDecoder)
@@ -74,9 +76,6 @@ Extension of UIView to be formatted as sections.
 		self.addSubview(container)
 		
 		self.photos = [photo0, photo1, photo2, photo3]
-		
-
-		//TODO Set click listeners
 	}
 	
 	
@@ -117,7 +116,8 @@ Extension of UIView to be formatted as sections.
 	
 	
 	/**
-	Default constructor for the interface builder
+	Default constructor for the interface builder.
+	:param: frame View frame.
 	*/
 	override init(frame: CGRect){
 		super.init(frame: frame)
@@ -127,7 +127,8 @@ Extension of UIView to be formatted as sections.
 	/**
 	Changes the preview image.
 	If null or empty, the igage is hidden.
-	:param: path The new text.
+	:param: path idx Index of the image (0-3).
+	:filename: path to the image.
 	*/
 	func setImage(idx: Int, filename: String){
 		if (filename == ""){

+ 8 - 0
app/RowItinerary.swift

@@ -35,6 +35,7 @@ Extension of UIView to be formatted an activity itinerary.
 	@IBOutlet weak var lbLocation: UILabel!
 	
 	var id: Int = -1
+	var type: String = ""
 	
 	/**
 	Default constructor
@@ -71,6 +72,11 @@ Extension of UIView to be formatted an activity itinerary.
 		
 		container.frame = self.bounds
 		self.addSubview(container)
+		
+		// Set tap recognizer
+		let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector (RowItinerary.openItinerary(_:)))
+		tapRecognizer.delegate = (UIApplication.shared.delegate as! AppDelegate).controller
+		self.addGestureRecognizer(tapRecognizer)
 	}
 	
 	
@@ -164,5 +170,7 @@ Extension of UIView to be formatted an activity itinerary.
 	func openItinerary(_ sender:UITapGestureRecognizer? = nil){
 		// TODO implement openItinerary.
 		NSLog(":ROWITINERARY:DEBUG: Open Itinerary")
+		let delegate: AppDelegate = UIApplication.shared.delegate as! AppDelegate
+		delegate.futureActivityController?.showItinerary(id: self.id)
 	}
 }

+ 13 - 4
app/RowSchedule.swift

@@ -34,6 +34,8 @@ Extension of UIView to be formatted as sections.
 	@IBOutlet weak var lbText: UILabel!
 	@IBOutlet weak var lbLocation: UILabel!
 	
+	var id: Int = -1
+	
 	
 	/**
 	Default constructor
@@ -70,6 +72,12 @@ Extension of UIView to be formatted as sections.
 		
 		container.frame = self.bounds
 		self.addSubview(container)
+		
+		// Set tap recognizer
+		let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector (RowSchedule.openSchedule(_:)))
+		tapRecognizer.delegate = (UIApplication.shared.delegate as! AppDelegate).controller
+		self.addGestureRecognizer(tapRecognizer)
+
 	}
 	
 	
@@ -154,10 +162,11 @@ Extension of UIView to be formatted as sections.
 	
 	
 	/**
-	Opens an event dialog.
+	Opens an schedule dialog.
 	*/
-	func openEvent(_ sender:UITapGestureRecognizer? = nil){
-		// TODO implement openEvent.
-		NSLog(":ROWSCHEDULE:DEBUG: Open Event")
+	func openSchedule(_ sender:UITapGestureRecognizer? = nil){
+		NSLog(":ROWSCHEDULE:DEBUG: Open schedule")
+		let delegate: AppDelegate = UIApplication.shared.delegate as! AppDelegate
+		delegate.scheduleController?.showEvent(id: self.id)
 	}
 }

+ 31 - 2
app/ScheduleViewController.swift

@@ -19,8 +19,6 @@
 // If not, see <http://www.gnu.org/licenses/>.
 
 
-// TODO: Barely working. City schedule not working, GM is shown but events times are mixed.
-
 import UIKit
 import CoreData
 
@@ -51,6 +49,8 @@ class ScheduleViewController: UIViewController, UIGestureRecognizerDelegate {
 	var days: [NSDate] = [NSDate]()
 	var selectedDay: Int = 0
 
+	// Id of event to open.
+	var passId: Int = -1
 	
 	/**
 	Gets the application context.
@@ -107,6 +107,7 @@ class ScheduleViewController: UIViewController, UIGestureRecognizerDelegate {
 		
 		self.context = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
 		self.delegate = UIApplication.shared.delegate as? AppDelegate
+		self.delegate?.scheduleController = self
 		self.lang = getLanguage()
 		self.context?.persistentStoreCoordinator = self.delegate?.persistentStoreCoordinator
 
@@ -233,6 +234,7 @@ class ScheduleViewController: UIViewController, UIGestureRecognizerDelegate {
 		
 		var rowcount = 0
 		var row: RowSchedule
+		var id: Int
 		var start: NSDate
 		var title: String
 		var text: String
@@ -258,6 +260,8 @@ class ScheduleViewController: UIViewController, UIGestureRecognizerDelegate {
 			
 			for r in searchResults! {
 				
+				id = r.value(forKey: "id") as! Int
+				
 				title = r.value(forKey: "title_\(lang!)") as! String
 				if r.value(forKey: "description_\(lang!)") != nil{
 					text = r.value(forKey: "description_\(lang!)") as! String
@@ -272,6 +276,7 @@ class ScheduleViewController: UIViewController, UIGestureRecognizerDelegate {
 				row.setTitle(text: title)
 				row.setText(text: text)
 				row.setTime(dtime: start)
+				row.id = id
 				
 				// Get location info from Place entity
 				let locationFetchRequest: NSFetchRequest<Place> = Place.fetchRequest()
@@ -336,6 +341,30 @@ class ScheduleViewController: UIViewController, UIGestureRecognizerDelegate {
 	}
 	
 	
+	/**
+	Shows an event dialog.
+	:param: id The event id.
+	*/
+	func showEvent(id: Int){
+		NSLog(":SCHEDULECONTROLLER:DEBUG: Show event \(id)")
+		self.passId = id
+		performSegue(withIdentifier: "SegueEvent", sender: nil)
+	}
+	
+	
+	/**
+	Run before performing a segue.
+	Assigns id if neccessary.
+	:param: segue The segue to perform.
+	:sender: The calling view.
+	*/
+	override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
+		if segue.identifier == "SegueEvent"{
+			(segue.destination as! EventController).id = passId
+		}
+	}
+	
+	
 	/**
 	Gets the device language. The only recognized languages are Spanish, English and Basque.
 	If the device has another language, Spanish will be selected by default.

+ 30 - 57
app/ViewController.swift

@@ -31,9 +31,6 @@ class ViewController: UIViewController, UICollectionViewDataSource, UICollection
 	
 	//The menu collection.
 	var sectionCollection: UICollectionView!
-	
-	// Need to save the sync segue.
-	var syncSegue: UIStoryboardSegue?
 
 	//Each of the sections of the app.
 	@IBOutlet var containerViewGallery: GalleryView!
@@ -43,6 +40,11 @@ class ViewController: UIViewController, UICollectionViewDataSource, UICollection
 	@IBOutlet var containerViewLocation: LocationView!
 	@IBOutlet var containerViewHome: HomeView!
 	
+	//Menu items.
+	let reuseIdentifier = "cell"
+	var selected = 0
+	var items = ["Inicio", "Localización", "La Blanca", "Actividades", "Blog", "Galería"]
+	
 	// Passed id to perform segues.
 	var passId: Int = -1
 	var passAlbum: Int = -1
@@ -50,8 +52,6 @@ class ViewController: UIViewController, UICollectionViewDataSource, UICollection
 	// Location-related variables.
 	var locationManager = CLLocationManager()
 	var didFindMyLocation = false
-	
-	
 	var locationTimer: Timer? = nil
 	
 	
@@ -65,6 +65,9 @@ class ViewController: UIViewController, UICollectionViewDataSource, UICollection
 		
 	}
 	
+	/**
+	Gets the device-reported location.
+	*/
 	func getLocation() -> CLLocationCoordinate2D {
 		return (locationManager.location?.coordinate)!
 	}
@@ -147,20 +150,6 @@ class ViewController: UIViewController, UICollectionViewDataSource, UICollection
 	}
 	
 	
-	/** 
-	Handles the initial sync process.
-	It can start it, showing the sync screen, or finish it, hidding the screen.
-	:param: showScreen True to start the sync, false to end it.
-	*/
-	func initialSync(showScreen: Bool){
-		if showScreen == true{
-			Sync(synchronous: true)
-		}
-		else{
-			syncSegue?.destination.dismiss(animated: true, completion: nil)
-		}
-	}
-	
 	/**
 	Run before performing a segue.
 	Assigns id if neccessary.
@@ -186,9 +175,6 @@ class ViewController: UIViewController, UICollectionViewDataSource, UICollection
 				(segue.destination as! ScheduleViewController).margolari = false
 			}
 		}
-		if segue.identifier == "SegueSync"{
-			self.syncSegue = segue
-		}
 		if segue.identifier == "SeguePastActivity"{
 			(segue.destination as! PastActivityViewController).id = passId
 		}
@@ -197,9 +183,6 @@ class ViewController: UIViewController, UICollectionViewDataSource, UICollection
 		}
 	}
 	
-	override func viewWillAppear(_ animated: Bool) {
-		super.viewWillAppear(animated)
-	}
 	
 	/**
 	Run when the app loads.
@@ -220,44 +203,22 @@ class ViewController: UIViewController, UICollectionViewDataSource, UICollection
 		// Start the location schedule
 		fetchLocation()
 		self.locationTimer = Timer.scheduledTimer(timeInterval: 90, target: self, selector: #selector(fetchLocation), userInfo: nil, repeats: true)
-				
-		NSLog(":CONTROLLER:DEBUG: Don't skyp sync")
-		//NSLog(":CONTROLLER:DEBUG: Skyp sync")
-		//Notifications()
-		//Sync()
-
 		
 		self.delegate = UIApplication.shared.delegate as? AppDelegate
 		self.delegate?.controller = self
 		
-		//self.sectionCollection.visibleCells[0].isSelected = true
-		
 		super.viewDidLoad()
 		
 	}
 	
+	/**
+	Asynchronously gets a location report from the server.
+	*/
 	func fetchLocation(){
 		FetchLocation()
 	}
 	
 	
-	/**
-	Executed when the view is actually shown.
-	Performs the initial sync in the first run.
-	It also generates a user id if none exists.
-	:param: animated Wether the controller appearance must be animated or not.
-	*/
-	override func viewDidAppear(_ animated: Bool) {
-		super.viewDidAppear(animated)
-		/*if UserDefaults.standard.object(forKey: "userId") == nil{
-			let newUid = randomString(length: 16)
-			let defaults = UserDefaults.standard
-			defaults.set(newUid, forKey: "userId")
-			initialSync(showScreen: true)
-		}*/
-		
-	}
-	
 	/**
 	Generates a random string to be used as a user identifier.
 	:param: length The length of the generated string.
@@ -278,7 +239,8 @@ class ViewController: UIViewController, UICollectionViewDataSource, UICollection
 		
 		return randomString
 	}
-
+	
+	
 	/**
 	Dispose of any resources that can be recreated.
 	*/
@@ -287,13 +249,9 @@ class ViewController: UIViewController, UICollectionViewDataSource, UICollection
 	}
 	
 	
-	//Menu items.
-	let reuseIdentifier = "cell"
-	var selected = 0
-	var items = ["Home", "Location", "La Blanca", "Actividades", "Blog", "Gallery"]
-	
 	// MARK: - UICollectionViewDataSource protocol
 	
+	
 	/**
 	Sets a collection of menu items.
 	:param: numberOfItemsInSection The number of entries of the menu.
@@ -303,7 +261,11 @@ class ViewController: UIViewController, UICollectionViewDataSource, UICollection
 		return self.items.count
 	}
 	
-	//Make a cell for each section
+	
+	/**
+	Sets up the menu bar.
+	:param: cellForItemAt indexPath One cell of the menu.
+	*/
 	func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
 		
 		//Get a reference to our storyboard cell
@@ -322,16 +284,27 @@ class ViewController: UIViewController, UICollectionViewDataSource, UICollection
 	
 	// MARK: - UICollectionViewDelegate protocol
 	
+	
+	/**
+	Inits items in the menu bar.
+	:paramm: didSelectItemAt item index
+	*/
 	func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
 		sectionCollection = collectionView
 		showComponent(selected: indexPath.item)
 	}
 	
+	
 	/**
 	Caled when an item of the menu bar is selected.
 	:param: selected Index of the selected item.
 	*/
 	@IBAction func showComponent(selected: Int) {
+	
+		// Reverts the style of the first tab.
+		if selected != 0{
+			self.sectionCollection.visibleCells[0].isSelected = false
+		}
 				
 		//Show the view
 		if selected == 0 {