├── .gitignore ├── Podfile ├── Podfile.lock ├── README.md ├── ScalaDays Notifications ├── Info.plist └── NotificationService.swift ├── ScalaDays.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ └── ScalaDays.xcscheme ├── ScalaDays.xcworkspace ├── contents.xcworkspacedata └── xcshareddata │ └── IDEWorkspaceChecks.plist └── ScalaDays ├── AppDelegate+PushNoticications.swift ├── AppDelegate.swift ├── Base.lproj ├── LaunchScreen.xib └── Main.storyboard ├── Bridging-Header.h ├── Controllers ├── SDAboutViewController.swift ├── SDAboutViewController.xib ├── SDContactViewController.swift ├── SDContactViewController.xib ├── SDNotificationViewController.swift ├── SDNotificationViewController.xib ├── SDPlacesViewController.swift ├── SDPlacesViewController.xib ├── SDScheduleDetailViewController.swift ├── SDScheduleDetailViewController.xib ├── SDScheduleViewController.swift ├── SDScheduleViewController.xib ├── SDSlideMenuViewController.swift ├── SDSlideMenuViewController.xib ├── SDSocialViewController.swift ├── SDSocialViewController.xib ├── SDSpeakersListViewController.swift ├── SDSpeakersListViewController.xib ├── SDSponsorViewController.swift ├── SDSponsorViewController.xib ├── SDVotesPopoverViewController.swift ├── SDVotesPopoverViewController.xib ├── SDWebViewController.swift ├── SDWebViewController.xib └── ScalaDayViewController.swift ├── Extension ├── Array+Extension.swift ├── Bundle+Extension.swift ├── SDColor.swift ├── SDFonts.swift ├── SDImageView-Circular.swift ├── SDMapView-ZoomOut.swift ├── SDString+RemoveWhiteSpaces.swift ├── SDUIViewControllerExtension.swift ├── SDView-NibLoading.swift ├── SDZBarSymbolSet-Enumeration.swift └── UIColor+Extension.swift ├── External └── SlideMenuController.swift ├── Helpers ├── Alerts │ └── SDAlertViewHelper.swift ├── Analytics │ ├── Analytics.swift │ └── FirebaseScalaDays.swift ├── Animation │ └── SDAnimationHelper.swift ├── Contacts │ ├── SDContactCreationHelper.h │ └── SDContactCreationHelper.m ├── Dates │ └── SDDateHandler.swift ├── Protocols │ └── SDMenuControllerItem.swift ├── SDConstants.swift ├── Social │ ├── SDSocialHandler.swift │ ├── TWTRTweet+SDTweet.swift │ └── TwitterSocialController.swift └── Storing │ ├── StoringHelper.swift │ └── UserDefaults+Extension.swift ├── Images.xcassets ├── AppIcon.appiconset │ ├── 1024x1024.png │ ├── Contents.json │ ├── icon-app-29x29.png │ ├── icon-app-29x29@2x-1.png │ ├── icon-app-29x29@2x.png │ ├── icon-app-29x29@3x.png │ ├── icon-app-40x40.png │ ├── icon-app-40x40@2x-1.png │ ├── icon-app-40x40@2x.png │ ├── icon-app-40x40@3x.png │ ├── icon-app-60x60@2x.png │ ├── icon-app-60x60@3x.png │ ├── icon-app-76x76.png │ ├── icon-app-76x76@2x.png │ └── icon-app-83.5x83.5@2x.png ├── Contents.json ├── LaunchImage.launchimage │ ├── Contents.json │ ├── splash-iphone4@2x.png │ ├── splash-iphone5.png │ ├── splash-iphone6-plus.png │ ├── splash-iphone6.png │ └── splash-iphonex.png ├── avatar.imageset │ ├── Contents.json │ ├── avatar.png │ ├── avatar@2x.png │ └── avatar@3x.png ├── empty_notifications.imageset │ ├── Contents.json │ ├── iconfinder_feature-available_4171950 (1).png │ ├── iconfinder_feature-available_4171950 (2)-1.png │ └── iconfinder_feature-available_4171950.png ├── list_icon_vote_like.imageset │ ├── Contents.json │ ├── list_icon_vote_like.png │ ├── list_icon_vote_like@2x.png │ └── list_icon_vote_like@3x.png ├── list_icon_vote_neutral.imageset │ ├── Contents.json │ ├── list_icon_vote_neutral.png │ ├── list_icon_vote_neutral@2x.png │ └── list_icon_vote_neutral@3x.png ├── list_icon_vote_unlike.imageset │ ├── Contents.json │ ├── list_icon_vote_unlike.png │ ├── list_icon_vote_unlike@2x.png │ └── list_icon_vote_unlike@3x.png ├── logo_47deg.imageset │ ├── Contents.json │ ├── logo_47deg.png │ ├── logo_47deg@2x.png │ └── logo_47deg@3x.png ├── map_popover.imageset │ ├── Contents.json │ ├── map_popover.png │ ├── map_popover@2x.png │ └── map_popover@3x.png ├── map_pushpin.imageset │ ├── Contents.json │ ├── map_pushpin.png │ ├── map_pushpin@2x.png │ └── map_pushpin@3x.png ├── menu_header_select_arrow.imageset │ ├── Contents.json │ ├── menu_header_select_arrow.png │ ├── menu_header_select_arrow@2x.png │ └── menu_header_select_arrow@3x.png ├── menu_icon_about.imageset │ ├── Contents.json │ ├── menu_icon_about.png │ ├── menu_icon_about@2x.png │ └── menu_icon_about@3x.png ├── menu_icon_contact.imageset │ ├── Contents.json │ ├── menu_icon_contact.png │ ├── menu_icon_contact@2x.png │ └── menu_icon_contact@3x.png ├── menu_icon_notification.imageset │ ├── Contents.json │ ├── bell@1x.png │ ├── bell@2x.png │ └── bell@3x.png ├── menu_icon_places.imageset │ ├── Contents.json │ ├── menu_icon_places.png │ ├── menu_icon_places@2x.png │ └── menu_icon_places@3x.png ├── menu_icon_schedule.imageset │ ├── Contents.json │ ├── menu_icon_schedule.png │ ├── menu_icon_schedule@2x.png │ └── menu_icon_schedule@3x.png ├── menu_icon_social.imageset │ ├── Contents.json │ ├── menu_icon_social.png │ ├── menu_icon_social@2x.png │ └── menu_icon_social@3x.png ├── menu_icon_speakers.imageset │ ├── Contents.json │ ├── menu_icon_speakers.png │ ├── menu_icon_speakers@2x.png │ └── menu_icon_speakers@3x.png ├── menu_icon_sponsors.imageset │ ├── Contents.json │ ├── menu_icon_sponsors.png │ ├── menu_icon_sponsors@2x.png │ └── menu_icon_sponsors@3x.png ├── menu_icon_ticket.imageset │ ├── Contents.json │ ├── menu_icon_ticket.png │ ├── menu_icon_ticket@2x.png │ └── menu_icon_ticket@3x.png ├── navigation_bar_icon_arrow.imageset │ ├── Contents.json │ ├── navigation_bar_icon_arrow.png │ ├── navigation_bar_icon_arrow@2x.png │ └── navigation_bar_icon_arrow@3x.png ├── navigation_bar_icon_clock.imageset │ ├── Contents.json │ ├── navigation_bar_icon_clock.png │ ├── navigation_bar_icon_clock@2x.png │ └── navigation_bar_icon_clock@3x.png ├── navigation_bar_icon_create.imageset │ ├── Contents.json │ ├── navigation_bar_icon_create.png │ ├── navigation_bar_icon_create@2x.png │ └── navigation_bar_icon_create@3x.png ├── navigation_bar_icon_favorite_default.imageset │ ├── Contents.json │ ├── navigation_bar_icon_favorite_default.png │ ├── navigation_bar_icon_favorite_default@2x.png │ └── navigation_bar_icon_favorite_default@3x.png ├── navigation_bar_icon_favorite_selected.imageset │ ├── Contents.json │ ├── navigation_bar_icon_favorite_selected.png │ ├── navigation_bar_icon_favorite_selected@2x.png │ └── navigation_bar_icon_favorite_selected@3x.png ├── navigation_bar_icon_filter.imageset │ ├── Contents.json │ ├── navigation_bar_icon_filter.png │ ├── navigation_bar_icon_filter@2x.png │ └── navigation_bar_icon_filter@3x.png ├── navigation_bar_icon_menu.imageset │ ├── Contents.json │ ├── navigation_bar_icon_menu.png │ ├── navigation_bar_icon_menu@2x.png │ └── navigation_bar_icon_menu@3x.png ├── navigation_bar_icon_options.imageset │ ├── Contents.json │ ├── navigation_bar_icon_options.png │ ├── navigation_bar_icon_options@2x.png │ └── navigation_bar_icon_options@3x.png ├── navigation_bar_post_tweet.imageset │ ├── Contents.json │ ├── iconfinder_Sed-17_2236318 (1).png │ └── iconfinder_Sed-17_2236318.png ├── placeholder_contact.imageset │ ├── Contents.json │ ├── placeholder_contact.png │ ├── placeholder_contact@2x.png │ └── placeholder_contact@3x.png ├── placeholder_error.imageset │ ├── Contents.json │ ├── placeholder_error.png │ ├── placeholder_error@2x.png │ └── placeholder_error@3x.png ├── placeholder_general.imageset │ ├── Contents.json │ ├── placeholder_general.png │ ├── placeholder_general@2x.png │ └── placeholder_general@3x.png ├── placeholder_menu.imageset │ ├── Contents.json │ ├── placeholder_menu.png │ ├── placeholder_menu@2x.png │ └── placeholder_menu@3x.png ├── placeholder_sponsors.imageset │ ├── Contents.json │ ├── placeholder_sponsors.png │ ├── placeholder_sponsors@2x.png │ └── placeholder_sponsors@3x.png ├── popup_icon_vote_like.imageset │ ├── Contents.json │ ├── popup_icon_vote_like.png │ ├── popup_icon_vote_like@2x.png │ └── popup_icon_vote_like@3x.png ├── popup_icon_vote_like_disabled.imageset │ ├── Contents.json │ ├── popup_icon_vote_like_disabled.png │ ├── popup_icon_vote_like_disabled@2x.png │ └── popup_icon_vote_like_disabled@3x.png ├── popup_icon_vote_neutral.imageset │ ├── Contents.json │ ├── popup_icon_vote_neutral.png │ ├── popup_icon_vote_neutral@2x.png │ └── popup_icon_vote_neutral@3x.png ├── popup_icon_vote_neutral_disabled.imageset │ ├── Contents.json │ ├── popup_icon_vote_neutral_disabled.png │ ├── popup_icon_vote_neutral_disabled@2x.png │ └── popup_icon_vote_neutral_disabled@3x.png ├── popup_icon_vote_unlike.imageset │ ├── Contents.json │ ├── popup_icon_vote_unlike.png │ ├── popup_icon_vote_unlike@2x.png │ └── popup_icon_vote_unlike@3x.png ├── popup_icon_vote_unlike_disabled.imageset │ ├── Contents.json │ ├── popup_icon_vote_unlike_disabled.png │ ├── popup_icon_vote_unlike_disabled@2x.png │ └── popup_icon_vote_unlike_disabled@3x.png ├── schedule_icon_details.imageset │ ├── Contents.json │ ├── calendar@1x-1.png │ ├── calendar@2x-1.png │ └── calendar@3x-1.png └── schedule_tag_favorite.imageset │ ├── Contents.json │ ├── schedule_tag_favorite.png │ ├── schedule_tag_favorite@2x.png │ └── schedule_tag_favorite@3x.png ├── Info.plist ├── Models ├── Conference.swift ├── Extensions │ └── DateFormatter+Decoders.swift ├── SDMapAnnotation.swift ├── SDNotifications.swift ├── SDTweet.swift └── Vote.swift ├── ScalaDays.entitlements ├── Service ├── DataManager.swift ├── FirebaseNotifications.swift ├── NotificationManager.swift ├── Response │ └── conferences_2020.json └── UserManager.swift ├── UI ├── CellPosition.swift ├── CustomViews │ ├── SDErrorPlaceholderView.swift │ ├── SDErrorPlaceholderView.xib │ ├── SDQRScannerOverlayView.swift │ ├── SDQRScannerOverlayView.xib │ ├── SDSpeakerDetailView.swift │ ├── SDSpeakerDetailView.xib │ ├── SDSpeakerScheduleView.swift │ └── SDSpeakerScheduleView.xib ├── TableViewCells │ ├── SDConferenceTableViewCell.swift │ ├── SDConferenceTableViewCell.xib │ ├── SDNotificationTableViewCell.swift │ ├── SDNotificationTableViewCell.xib │ ├── SDScheduleListTableViewCell.swift │ ├── SDScheduleListTableViewCell.xib │ ├── SDSocialTableViewCell.swift │ ├── SDSocialTableViewCell.xib │ ├── SDSpeakersTableViewCell.swift │ ├── SDSpeakersTableViewCell.xib │ ├── SDSponsorsTableViewCell.swift │ ├── SDSponsorsTableViewCell.xib │ └── SDTableHeaderView.swift └── Utils │ ├── UITableView+Cells.swift │ └── UITextView+HTML.swift └── en.lproj └── Localizable.strings /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | */build/* 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.moved-aside 14 | DerivedData 15 | .idea/ 16 | *.hmap 17 | *.xccheckout 18 | 19 | #CocoaPods 20 | Pods 21 | /ScalaDays/Podfile.lock 22 | 23 | #Local keys file 24 | SDExternalKeys.plist 25 | GoogleService-Info.plist 26 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | source 'https://github.com/CocoaPods/Specs.git' 2 | platform :ios, 10.0 3 | use_frameworks! 4 | use_modular_headers! 5 | inhibit_all_warnings! 6 | 7 | def firebase 8 | # enabled Analytics 9 | pod 'Firebase/Analytics' 10 | 11 | # enabled push notifications 12 | pod 'Firebase' 13 | pod 'Firebase/Messaging' 14 | pod 'Firebase/InAppMessaging' 15 | 16 | # enabled Crashlytics (Firebase) 17 | pod 'Fabric', '~> 1.10.2' 18 | pod 'Crashlytics', '~> 3.14.0' 19 | 20 | # enabled Performance Monitoring 21 | pod 'Firebase/Performance' 22 | end 23 | 24 | 25 | target 'ScalaDays' do 26 | firebase 27 | 28 | pod 'Alamofire', '~> 5.0' 29 | pod 'TwitterKit', '3.4.2' 30 | pod 'ZBarSDK', '~> 1.3.1' 31 | 32 | # UI 33 | pod 'SDWebImage', '~> 3.5' 34 | pod 'SVProgressHUD', '~> 1.0' 35 | pod 'UIView+AutoLayout', '~> 1.3' 36 | 37 | # Utils 38 | pod 'NSDate+TimeAgo', '~> 1.0.2' 39 | 40 | target 'ScalaDays Notifications' do 41 | inherit! :search_paths 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ScalaDays for iOS 2 | The official [Scala Days](http://www.scaladays.org) App for Android handcrafted by 47 Degrees. You can download Scala Days from the [App Store](https://itunes.apple.com/us/app/scaladays/id883566471?mt=8 ). If you enjoy the application, please take a moment and rate it in the App Store :-) 3 | 4 | ## Setup 5 | 6 | This project uses the Cocoapods dependency management system for managing all third party dependencies that are utilized as part of this application. For a list of all of the third party dependencies, view the Podfile. 7 | 8 | For setup instructions please see [cocoapods.org](http://cocoapods.org/) 9 | 10 | ## Project Installation 11 | 12 | To download all of the dependencies, run 'pod install' from the terminal in the folder with the 'Podfile' file. 13 | 14 | Once the dependencies are downloaded Cocoapods will create a workspace file. Use the workspace to open the project in Xcode instead of the project file. 15 | 16 | ## External Keys 17 | 18 | As this project uses TwitterKit and Firebase (Analytics + Crashlytics + Cloud Messaging) frameworks, you need to provide the whole API keys (not included in the repo for security reasons). They are distributed in two external `plist files`, located in the *External/Keys* folder. 19 | 20 | **SDExternalKeys.plist** 21 | 22 | 23 | TwitterConsumerKey 24 | *********** 25 | TwitterConsumerSecret 26 | *********** 27 | 28 | 29 | **GoogleService-Info.plist** 30 | 31 | You can find this plist in your [Firebase console](https://firebase.google.com/). 32 | 33 | ## Crash Reporting 34 | 35 | Crash reporting is handled through Crashlytics. All uncaught exceptions are sent to Firebase/Crashlytics. 36 | 37 | ## License 38 | Copyright (C) 2015-2020 47 Degrees, LLC http://47deg.com hello@47deg.com 39 | 40 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at 41 | 42 | http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 43 | -------------------------------------------------------------------------------- /ScalaDays Notifications/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | ScalaDays Notifications 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 19 | CFBundleShortVersionString 20 | $(MARKETING_VERSION) 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSExtension 24 | 25 | NSExtensionPointIdentifier 26 | com.apple.usernotifications.service 27 | NSExtensionPrincipalClass 28 | $(PRODUCT_MODULE_NAME).NotificationService 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /ScalaDays Notifications/NotificationService.swift: -------------------------------------------------------------------------------- 1 | import UserNotifications 2 | import FirebaseMessaging 3 | 4 | class NotificationService: UNNotificationServiceExtension { 5 | var contentHandler: ((UNNotificationContent) -> Void)? 6 | var bestAttemptContent: UNMutableNotificationContent? 7 | 8 | override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { 9 | guard let content = request.content.mutableCopy() as? UNMutableNotificationContent else { return } 10 | self.contentHandler = contentHandler 11 | self.bestAttemptContent = content 12 | 13 | FIRMessagingExtensionHelper().populateNotificationContent(content, withContentHandler: contentHandler) 14 | } 15 | 16 | override func serviceExtensionTimeWillExpire() { 17 | guard let contentHandler = contentHandler, 18 | let bestAttemptContent = bestAttemptContent else { return } 19 | 20 | contentHandler(bestAttemptContent) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ScalaDays.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ScalaDays.xcodeproj/xcshareddata/xcschemes/ScalaDays.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 53 | 55 | 61 | 62 | 63 | 64 | 70 | 72 | 78 | 79 | 80 | 81 | 83 | 84 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /ScalaDays.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ScalaDays.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ScalaDays/AppDelegate+PushNoticications.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Firebase 3 | import UserNotifications 4 | 5 | extension AppDelegate: UNUserNotificationCenterDelegate, MessagingDelegate { 6 | private static let SHOW_DEVICE_TOKEN = false 7 | 8 | // MARK: Registration 9 | func initializeNotifications(application: UIApplication) { 10 | registerPushNotifications(application: application) 11 | registerMessaging() 12 | } 13 | 14 | private func registerPushNotifications(application: UIApplication) { 15 | UNUserNotificationCenter.current().delegate = self 16 | UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { (_, _) in } 17 | application.registerForRemoteNotifications() 18 | } 19 | 20 | private func registerMessaging() { 21 | Messaging.messaging().delegate = self 22 | } 23 | 24 | // MARK: Push Notifications 25 | func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { 26 | let userInfo = notification.request.content.userInfo 27 | show(userInfo: userInfo) 28 | completionHandler(.alert) 29 | } 30 | 31 | func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { 32 | let userInfo = response.notification.request.content.userInfo 33 | show(userInfo: userInfo) 34 | didTapOnNotification(userInfo: userInfo) 35 | completionHandler() 36 | } 37 | 38 | private func didTapOnNotification(userInfo: [AnyHashable: Any]) { 39 | guard let conferenceId = userInfo["conferenceId"] as? String else { return } 40 | 41 | if let jsonReload = userInfo["jsonReload"] as? String, jsonReload.lowercased() == "true" { 42 | DataManager.sharedInstance.lastConnectionAttemptDate = nil 43 | menuViewController.askControllersToReload() 44 | } 45 | 46 | menuViewController.showNotifications(conferenceId: conferenceId) 47 | } 48 | 49 | // MARK: Messaging 50 | public func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) { 51 | if AppDelegate.SHOW_DEVICE_TOKEN { 52 | showDeviceToken() 53 | showRegistrationToken() 54 | } 55 | 56 | NotificationCenter.default.post(name: Notification.Name("FCMToken"), object: nil, userInfo: ["token": fcmToken]) 57 | // Note: This callback is fired at each app startup and whenever a new token is generated. 58 | // If necessary send token to application server. 59 | } 60 | 61 | // MARK: - Helpers 62 | private func show(userInfo: [AnyHashable : Any]) { 63 | if let messageID = userInfo[UserInfo.gcmMessageIDKey] { 64 | print("Message ID: \(messageID)") 65 | } 66 | 67 | print("User Info: \(userInfo)") 68 | } 69 | 70 | private func showRegistrationToken() { 71 | InstanceID.instanceID().instanceID { (result, error) in 72 | if let error = error { 73 | print("Error fetching remote instance ID: \(error)") 74 | } else if let result = result { 75 | print("Firebase registration token: \(result.token)") 76 | } 77 | } 78 | } 79 | 80 | private func showDeviceToken() { 81 | guard let deviceToken = Messaging.messaging().apnsToken else { return } 82 | let deviceTokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)}) 83 | print("DEVICE TOKEN\n------------------\n\(deviceTokenString)\n------------------") 84 | } 85 | 86 | // MARK: - Constants 87 | enum UserInfo { 88 | static let gcmMessageIDKey = "gcm.message_id" 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /ScalaDays/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import SVProgressHUD 3 | import TwitterKit 4 | import Firebase 5 | 6 | @UIApplicationMain 7 | class AppDelegate: UIResponder, UIApplicationDelegate { 8 | var window: UIWindow? 9 | var menuViewController: SDSlideMenuViewController! 10 | private var analytics: ScalaDaysAnalytics! 11 | 12 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 13 | setupThirdParties(application: application, launchOptions: launchOptions) 14 | initAppearence() 15 | createMenuView() 16 | 17 | return true 18 | } 19 | 20 | // MARK: setup 21 | private func createMenuView() { 22 | let scheduleViewController = SDScheduleViewController(analytics: analytics) 23 | menuViewController = SDSlideMenuViewController(analytics: analytics) 24 | let nvc: UINavigationController = UINavigationController(rootViewController: scheduleViewController) 25 | 26 | menuViewController.scheduleViewController = nvc 27 | let slideMenuController = SlideMenuController(mainViewController: nvc, leftMenuViewController: menuViewController) 28 | 29 | window = UIWindow(frame: UIScreen.main.bounds) 30 | if let window = window { 31 | window.backgroundColor = UIColor.appColor() 32 | window.rootViewController = slideMenuController 33 | window.makeKeyAndVisible() 34 | } 35 | } 36 | 37 | private func initAppearence() { 38 | UINavigationBar.appearance().barTintColor = UIColor.appColor() 39 | UINavigationBar.appearance().tintColor = UIColor.white 40 | UINavigationBar.appearance().titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white] 41 | UINavigationBar.appearance().backIndicatorImage = UIImage(named: "navigation_bar_icon_arrow") 42 | UINavigationBar.appearance().backIndicatorTransitionMaskImage = UIImage(named: "navigation_bar_icon_arrow") 43 | SVProgressHUD.setBackgroundColor(UIColor.clear) 44 | } 45 | } 46 | 47 | // MARK: Configure 3rd-party libraries 48 | extension AppDelegate { 49 | 50 | func setupThirdParties(application: UIApplication, launchOptions: [UIApplication.LaunchOptionsKey: Any]?) { 51 | firebase(application: application) 52 | twitter(application: application) 53 | } 54 | 55 | private func firebase(application: UIApplication) { 56 | FirebaseApp.configure() 57 | analytics = ScalaDaysAnalytics() 58 | initializeNotifications(application: application) 59 | } 60 | 61 | private func twitter(application: UIApplication) { 62 | guard let path = Bundle.main.path(forResource: kExternalKeysPlistFilename, ofType: "plist"), 63 | let keysDict = NSDictionary(contentsOfFile: path), 64 | let twitterConsumerKey = keysDict[kExternalKeysDKTwitterConsumerKey] as? String, 65 | let twitterConsumerSecret = keysDict[kExternalKeysDKTwitterConsumerSecret] as? String else { return } 66 | 67 | TWTRTwitter.sharedInstance().start(withConsumerKey: twitterConsumerKey, consumerSecret: twitterConsumerSecret) 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /ScalaDays/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /ScalaDays/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /ScalaDays/Bridging-Header.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 47 Degrees, LLC http://47deg.com hello@47deg.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | * not use this file except in compliance with the License. You may obtain 6 | * a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 18 | 19 | #ifndef ScalaDays_Bridging_Header_h 20 | #define ScalaDays_Bridging_Header_h 21 | 22 | #import 23 | #import 24 | #import "SDContactCreationHelper.h" 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /ScalaDays/Controllers/SDPlacesViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /ScalaDays/Controllers/SDSpeakersListViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /ScalaDays/Controllers/SDSponsorViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /ScalaDays/Controllers/SDVotesPopoverViewController.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 47 Degrees, LLC http://47deg.com hello@47deg.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | * not use this file except in compliance with the License. You may obtain 6 | * a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import UIKit 18 | 19 | protocol SDVotesPopoverViewControllerDelegate: class { 20 | func didSelectVoteValue(_ voteType: VoteType) 21 | } 22 | 23 | class SDVotesPopoverViewController: UIViewController, UIPopoverPresentationControllerDelegate { 24 | @IBOutlet weak var lblTalkTitle: UILabel! 25 | 26 | private let analytics: Analytics 27 | weak var delegate: SDVotesPopoverViewControllerDelegate? 28 | 29 | init(analytics: Analytics, delegate: SDVotesPopoverViewControllerDelegate) { 30 | self.analytics = analytics 31 | self.delegate = delegate 32 | super.init(nibName: String(describing: SDVotesPopoverViewController.self), bundle: nil) 33 | } 34 | 35 | required init?(coder: NSCoder) { 36 | fatalError("init(coder:) has not been implemented") 37 | } 38 | 39 | override func viewDidAppear(_ animated: Bool) { 40 | super.viewDidAppear(animated) 41 | analytics.logScreenName(.votes, class: SDVotesPopoverViewController.self) 42 | } 43 | 44 | @IBAction func didVoteLike(_ sender: AnyObject) { 45 | self.sendVoteElection(VoteType.like) 46 | } 47 | 48 | @IBAction func didVoteNeutral(_ sender: AnyObject) { 49 | self.sendVoteElection(VoteType.neutral) 50 | } 51 | 52 | @IBAction func didVoteDontLike(_ sender: AnyObject) { 53 | self.sendVoteElection(VoteType.unlike) 54 | } 55 | 56 | func sendVoteElection(_ vote: VoteType) { 57 | delegate?.didSelectVoteValue(vote) 58 | self.dismiss(animated: true, completion: nil) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /ScalaDays/Controllers/SDWebViewController.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 47 Degrees, LLC http://47deg.com hello@47deg.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | * not use this file except in compliance with the License. You may obtain 6 | * a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import UIKit 18 | 19 | class SDWebViewController: UIViewController { 20 | 21 | @IBOutlet weak var webView: UIWebView! 22 | var url: URL? 23 | private let analytics: Analytics 24 | 25 | init(analytics: Analytics) { 26 | self.analytics = analytics 27 | super.init(nibName: String(describing: SDWebViewController.self), bundle: nil) 28 | } 29 | 30 | required init?(coder: NSCoder) { 31 | fatalError("init(coder:) has not been implemented") 32 | } 33 | 34 | override func viewDidLoad() { 35 | super.viewDidLoad() 36 | webView.scalesPageToFit = true 37 | if let _url = url { 38 | loadUrl(_url) 39 | } 40 | } 41 | 42 | override func viewDidAppear(_ animated: Bool) { 43 | super.viewDidAppear(animated) 44 | analytics.logScreenName(.webView, class: SDWebViewController.self) 45 | } 46 | 47 | func loadUrl(_ url: URL) { 48 | webView.loadRequest(URLRequest(url: url)) 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /ScalaDays/Controllers/SDWebViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /ScalaDays/Controllers/ScalaDayViewController.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | protocol ScalaDayViewController: UIViewController { 4 | func updateConference(_ conference: Conference) 5 | } 6 | -------------------------------------------------------------------------------- /ScalaDays/Extension/Array+Extension.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | extension Array { 4 | 5 | public subscript(safe index: Int) -> Element? { 6 | guard index >= 0 && index < count else { return nil } 7 | return self[index] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /ScalaDays/Extension/Bundle+Extension.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | private class DummyBundle { } 4 | 5 | extension Bundle { 6 | static var local: Bundle { 7 | return Bundle(for: DummyBundle.self) 8 | } 9 | 10 | static var localModuleName: String { 11 | guard let dictionary = Bundle.local.infoDictionary else { return "" } 12 | return dictionary[kCFBundleNameKey as String] as? String ?? "" 13 | } 14 | 15 | static func loadView(nibName: String) -> UIView? { 16 | return Bundle.local.loadNibNamed(nibName, owner: self, options: nil)?.first as? UIView 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ScalaDays/Extension/SDColor.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 47 Degrees, LLC http://47deg.com hello@47deg.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | * not use this file except in compliance with the License. You may obtain 6 | * a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import UIKit 18 | 19 | extension UIColor { 20 | 21 | class func grayScaleColor(_ grayScale: CGFloat) -> UIColor { 22 | return UIColor(red: grayScale / 255.0, green: grayScale / 255.0, blue: grayScale / 255.0, alpha: 1.0) 23 | } 24 | 25 | class func appColor() -> UIColor { 26 | return UIColor(red: 54/255, green: 69/255, blue: 80/255, alpha: 255/255) 27 | } 28 | 29 | class func selectedCellMenu() -> UIColor { 30 | return UIColor(red: 43/255, green: 56/255, blue: 65/255, alpha: 255/255) 31 | } 32 | 33 | class func appRedColor() -> UIColor { 34 | return UIColor(red: 224/255, green: 95/255, blue: 94/255, alpha: 255/255) 35 | } 36 | 37 | class func appScheduleBlueBackgroundColor() -> UIColor { 38 | return UIColor(red: 108/255, green: 207/255, blue: 233/255, alpha: 255/255) 39 | } 40 | 41 | class func appScheduleTimeBlueBackgroundColor() -> UIColor { 42 | return UIColor(red: 108/255, green: 207/255, blue: 233/255, alpha: 255/255) 43 | } 44 | 45 | class func appSeparatorLineColor() -> UIColor { 46 | return UIColor(red: 54/255, green: 69/255, blue: 80/255, alpha: 0.3) 47 | } 48 | 49 | class func disabledButtonColor() -> UIColor { 50 | return grayScaleColor(190.0) 51 | } 52 | 53 | class func enabledSendVoteButtonColor() -> UIColor { 54 | return grayScaleColor(12.0) 55 | } 56 | 57 | class func grayButtonBorder() -> UIColor { 58 | return grayScaleColor(218.0) 59 | } 60 | 61 | class func grayCommentsPlaceholder() -> UIColor { 62 | return grayScaleColor(185.0) 63 | } 64 | 65 | class func blackForCommentsNormalText() -> UIColor { 66 | return UIColor(red: 41.0/255.0, green: 53.0/255.0, blue: 63.0/255.0, alpha: 1.0) 67 | } 68 | 69 | } 70 | 71 | 72 | -------------------------------------------------------------------------------- /ScalaDays/Extension/SDFonts.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 47 Degrees, LLC http://47deg.com hello@47deg.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | * not use this file except in compliance with the License. You may obtain 6 | * a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import UIKit 18 | 19 | extension UIFont { 20 | 21 | class func fontHelveticaNeue(_ fontSize: CGFloat) -> UIFont { 22 | return UIFont(name: "HelveticaNeue", size: fontSize)! 23 | } 24 | 25 | class func fontHelveticaNeueItalic(_ fontSize: CGFloat) -> UIFont { 26 | return UIFont(name: "HelveticaNeue-Italic", size: fontSize)! 27 | } 28 | 29 | class func fontHelveticaNeueBold(_ fontSize: CGFloat) -> UIFont { 30 | return UIFont(name: "HelveticaNeue-Bold", size: fontSize)! 31 | } 32 | 33 | class func fontHelveticaNeueMedium(_ fontSize: CGFloat) -> UIFont { 34 | return UIFont(name: "HelveticaNeue-Medium", size: fontSize)! 35 | } 36 | 37 | class func fontHelveticaNeueLight(_ fontSize: CGFloat) -> UIFont { 38 | return UIFont(name: "HelveticaNeue-Light", size: fontSize)! 39 | } 40 | 41 | } 42 | 43 | extension UILabel { 44 | 45 | @discardableResult 46 | func setCustomFont(_ typeFont: UIFont, colorFont: UIColor) -> UILabel { 47 | self.font = typeFont 48 | self.textColor = colorFont 49 | self.sizeToFit() 50 | return self 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /ScalaDays/Extension/SDImageView-Circular.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 47 Degrees, LLC http://47deg.com hello@47deg.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | * not use this file except in compliance with the License. You may obtain 6 | * a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import UIKit 18 | 19 | extension UIImageView { 20 | 21 | func circularImage() -> Void { 22 | self.layer.cornerRadius = self.frame.size.width / 2 23 | self.layer.masksToBounds = true 24 | self.clipsToBounds = true 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /ScalaDays/Extension/SDMapView-ZoomOut.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 47 Degrees, LLC http://47deg.com hello@47deg.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | * not use this file except in compliance with the License. You may obtain 6 | * a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 18 | import MapKit 19 | 20 | extension MKMapView { 21 | 22 | // TODO: the ideal approach to this would be to use a recursive function to calculate the middle point of 23 | // our map's annotations in order to avoid mutability. But sadly it seems that while Swift uses tail call 24 | // optimization *sometimes*, it won't guarantee that in any way. 25 | // 26 | // You can find more information about this in this blog post from Natasha The Robot: 27 | // http://natashatherobot.com/functional-swift-tail-recursion/ 28 | 29 | func zoomToFitMapAnnotations() { 30 | guard self.annotations.count != 0 else { return } 31 | 32 | let kZoomOutRatio = 50.0 33 | var topLeftCoord = CLLocationCoordinate2D(latitude: -90, longitude: 180) 34 | var bottomRightCoord = CLLocationCoordinate2D(latitude: 90, longitude: -180) 35 | for annotation in self.annotations { 36 | topLeftCoord.longitude = fmin(topLeftCoord.longitude, annotation.coordinate.longitude); 37 | topLeftCoord.latitude = fmax(topLeftCoord.latitude, annotation.coordinate.latitude); 38 | bottomRightCoord.longitude = fmax(bottomRightCoord.longitude, annotation.coordinate.longitude); 39 | bottomRightCoord.latitude = fmin(bottomRightCoord.latitude, annotation.coordinate.latitude); 40 | } 41 | let region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: topLeftCoord.latitude - (topLeftCoord.latitude - bottomRightCoord.latitude) * 0.5, 42 | longitude: topLeftCoord.longitude + (bottomRightCoord.longitude - topLeftCoord.longitude) * 0.5), 43 | span: MKCoordinateSpan(latitudeDelta: fabs(topLeftCoord.latitude - bottomRightCoord.latitude) * kZoomOutRatio, longitudeDelta: fabs(topLeftCoord.latitude - bottomRightCoord.latitude) * kZoomOutRatio)) 44 | 45 | let regionFits = self.regionThatFits(region) 46 | guard !regionFits.isInvalid else { return } 47 | self.setRegion(regionFits, animated: true) 48 | } 49 | } 50 | 51 | 52 | // MARK: - Helpers 53 | extension MKCoordinateRegion { 54 | var isInvalid: Bool { span.isInvalid } 55 | } 56 | 57 | extension MKCoordinateSpan { 58 | var isInvalid: Bool { latitudeDelta.isNaN || longitudeDelta.isNaN } 59 | } 60 | -------------------------------------------------------------------------------- /ScalaDays/Extension/SDString+RemoveWhiteSpaces.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 47 Degrees, LLC http://47deg.com hello@47deg.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | * not use this file except in compliance with the License. You may obtain 6 | * a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import Foundation 18 | 19 | extension String { 20 | func removeWhitespace() -> String { 21 | components(separatedBy: CharacterSet.whitespacesAndNewlines) 22 | .filter { !$0.isEmpty } 23 | .joined(separator: " ") 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /ScalaDays/Extension/SDUIViewControllerExtension.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 47 Degrees, LLC http://47deg.com hello@47deg.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | * not use this file except in compliance with the License. You may obtain 6 | * a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import UIKit 18 | 19 | extension UIViewController { 20 | 21 | func setNavigationBarItem() { 22 | self.addLeftBarButtonWithImage(UIImage(named: "navigation_bar_icon_menu")!) 23 | self.navigationController?.navigationBar.isTranslucent = false 24 | self.navigationController?.navigationBar.shadowImage = UIImage() 25 | self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ScalaDays/Extension/SDView-NibLoading.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 47 Degrees, LLC http://47deg.com hello@47deg.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | * not use this file except in compliance with the License. You may obtain 6 | * a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import UIKit 18 | // FIXME: comparison operators with optionals were removed from the Swift Standard Libary. 19 | // Consider refactoring the code to use the non-optional operators. 20 | fileprivate func < (lhs: T?, rhs: T?) -> Bool { 21 | switch (lhs, rhs) { 22 | case let (l?, r?): 23 | return l < r 24 | case (nil, _?): 25 | return true 26 | default: 27 | return false 28 | } 29 | } 30 | 31 | // FIXME: comparison operators with optionals were removed from the Swift Standard Libary. 32 | // Consider refactoring the code to use the non-optional operators. 33 | fileprivate func > (lhs: T?, rhs: T?) -> Bool { 34 | switch (lhs, rhs) { 35 | case let (l?, r?): 36 | return l > r 37 | default: 38 | return rhs < lhs 39 | } 40 | } 41 | 42 | 43 | extension UIView { 44 | 45 | func loadNibSubviewsFromNib(_ nibName: String) -> UIView? { 46 | let objects = Bundle.main.loadNibNamed(nibName, owner: self, options: nil) 47 | 48 | objects?.filter({$0 is UIView}) 49 | if objects?.count > 0 { 50 | let containerView = objects![0] as! UIView 51 | containerView.translatesAutoresizingMaskIntoConstraints = false 52 | addSubview(containerView) 53 | needsUpdateConstraints() 54 | 55 | return containerView 56 | } 57 | return nil 58 | } 59 | 60 | func updateCustomConstraints(_ customConstraints : NSMutableArray, containerView: UIView!) { 61 | 62 | for object in customConstraints { 63 | if let const = object as? NSLayoutConstraint { 64 | removeConstraint(const) 65 | } 66 | } 67 | customConstraints.removeAllObjects() 68 | 69 | if containerView != nil { 70 | let viewDictionary : NSDictionary = ["view" : containerView] 71 | customConstraints.addObjects(from: NSLayoutConstraint.constraints(withVisualFormat: "H:|[view]|", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: viewDictionary as! [String : AnyObject])) 72 | customConstraints.addObjects(from: NSLayoutConstraint.constraints(withVisualFormat: "V:|[view]|", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: viewDictionary as! [String:AnyObject])) 73 | 74 | for object in customConstraints { 75 | if let const = object as? NSLayoutConstraint { 76 | addConstraint(const) 77 | } 78 | } 79 | } 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /ScalaDays/Extension/SDZBarSymbolSet-Enumeration.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 47 Degrees, LLC http://47deg.com hello@47deg.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | * not use this file except in compliance with the License. You may obtain 6 | * a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import Foundation 18 | import ZBarSDK 19 | 20 | extension ZBarSymbolSet: Sequence { 21 | public func makeIterator() -> NSFastEnumerationIterator { 22 | return NSFastEnumerationIterator(self) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ScalaDays/Extension/UIColor+Extension.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | extension UIColor { 4 | 5 | var hex: String? { 6 | guard let components = cgColor.components, 7 | let r = components[safe: 0], 8 | let g = components[safe: 1], 9 | let b = components[safe: 2] else { return nil } 10 | 11 | let a = components[safe: 3] ?? 1.0 12 | 13 | return String(format: "%02X%02X%02X%02X", 14 | lroundf(Float(r) * 255.0), 15 | lroundf(Float(g) * 255.0), 16 | lroundf(Float(b) * 255.0), 17 | lroundf(Float(a) * 255.0)) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ScalaDays/Helpers/Alerts/SDAlertViewHelper.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 47 Degrees, LLC http://47deg.com hello@47deg.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | * not use this file except in compliance with the License. You may obtain 6 | * a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import UIKit 18 | 19 | class SDAlertViewHelper: NSObject { 20 | class func showSimpleAlertViewOnViewController(_ viewController: UIViewController!, title: String?, message: String?, cancelButtonTitle: String!, otherButtonTitle: String?, tag: Int?, delegate: UIAlertViewDelegate?, handler: ((UIAlertAction?) -> Void)?) { 21 | if isIOS8OrLater() { 22 | let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert) 23 | let actionCancel = UIAlertAction(title: cancelButtonTitle, style: .cancel, handler: handler) 24 | if let otherButton = otherButtonTitle { 25 | let actionOther = UIAlertAction(title: otherButton, style: .default, handler: handler) 26 | alertController.addAction(actionOther) 27 | } 28 | 29 | alertController.addAction(actionCancel) 30 | viewController.present(alertController, animated: true, completion: nil) 31 | } else { 32 | let alertView = UIAlertView() 33 | if let unwrappedTitle = title { 34 | alertView.title = unwrappedTitle 35 | } 36 | alertView.message = message 37 | alertView.delegate = delegate 38 | alertView.addButton(withTitle: cancelButtonTitle) 39 | alertView.cancelButtonIndex = 0 40 | if let unwrappedOtherButton = otherButtonTitle { 41 | alertView.addButton(withTitle: unwrappedOtherButton) 42 | } 43 | if let unwrappedTag = tag { 44 | alertView.tag = unwrappedTag 45 | } 46 | alertView.show() 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /ScalaDays/Helpers/Analytics/Analytics.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | enum AnalyticEvent { 4 | enum ScreenName: String { 5 | case slideMenu = "Slide Menu" 6 | case schedule = "Schedule" 7 | case social = "Social" 8 | case speakers = "Speakers" 9 | case tickets = "Tickets" 10 | case contact = "Contact" 11 | case sponsors = "Sponsors" 12 | case places = "Places" 13 | case about = "About" 14 | case menu = "Menu" 15 | case votes = "Votes" 16 | case webView = "Web View" 17 | case notification = "Notifications" 18 | } 19 | 20 | enum Category: String { 21 | case filter = "Filter" 22 | case favorites = "Favorites" 23 | case navigate = "Navigate" 24 | case vote = "Vote" 25 | } 26 | 27 | enum Action: String { 28 | case filterAll = "All" 29 | case filterFavorites = "Favorites" 30 | case goToDetail = "Go to Detail" 31 | case addToFavorite = "Add" 32 | case removeToFavorite = "Remove" 33 | case goToTweet = "Go to Tweet" 34 | case postTweet = "Post Tweet" 35 | case cancelTweet = "Cancel Tweet" 36 | case goToUser = "Go to User" 37 | case goToTicket = "Go to Ticket" 38 | case scanContact = "Scan Contact" 39 | case goToSponsor = "Go to Sponsor" 40 | case goToMap = "Go to Map" 41 | case goToSite = "Go to 47Deg Website" 42 | case goToFeedbackForm = "Go to anonymous feedback" 43 | case menuChangeConference = "Change Conference" 44 | case showVotingDialog = "Show Voting Dialog" 45 | case sendVote = "Send Vote" 46 | } 47 | } 48 | 49 | 50 | protocol Analytics { 51 | func logScreenName(_ screen: AnalyticEvent.ScreenName, class: UIViewController.Type) 52 | func logEvent(screenName: AnalyticEvent.ScreenName, category: AnalyticEvent.Category, action: AnalyticEvent.Action) 53 | func logEvent(screenName: AnalyticEvent.ScreenName, category: AnalyticEvent.Category, action: AnalyticEvent.Action, label: String) 54 | } 55 | -------------------------------------------------------------------------------- /ScalaDays/Helpers/Analytics/FirebaseScalaDays.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Firebase 3 | 4 | struct ScalaDaysAnalytics: Analytics { 5 | 6 | func logScreenName(_ screen: AnalyticEvent.ScreenName, class screenClass: UIViewController.Type) { 7 | Firebase.Analytics.setScreenName("\(screen)", screenClass: String(describing: screenClass)) 8 | } 9 | 10 | func logEvent(screenName: AnalyticEvent.ScreenName, category: AnalyticEvent.Category, action: AnalyticEvent.Action) { 11 | log(screenName: screenName, category: category, action: action, label: nil) 12 | } 13 | 14 | func logEvent(screenName: AnalyticEvent.ScreenName, category: AnalyticEvent.Category, action: AnalyticEvent.Action, label: String) { 15 | log(screenName: screenName, category: category, action: action, label: label) 16 | } 17 | 18 | // MARK: private methods 19 | func log(screenName: AnalyticEvent.ScreenName, category: AnalyticEvent.Category, action: AnalyticEvent.Action, label: String?) { 20 | Firebase.Analytics.logEvent("\(screenName)", parameters: [ 21 | "category": "\(category)" as NSObject, 22 | "action": "\(action)" as NSObject, 23 | "label": "\(label ?? "nil")" as NSObject 24 | ]) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ScalaDays/Helpers/Animation/SDAnimationHelper.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 47 Degrees, LLC http://47deg.com hello@47deg.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | * not use this file except in compliance with the License. You may obtain 6 | * a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import UIKit 18 | 19 | class SDAnimationHelper: NSObject { 20 | 21 | class func showViewWithFadeInAnimation(_ view: UIView) { 22 | SDAnimationHelper.showViewWithFadeInAnimation(view, maxAlphaValue: 1.0) 23 | } 24 | 25 | class func showViewWithFadeInAnimation(_ view: UIView, maxAlphaValue: CGFloat) { 26 | view.alpha = 0 27 | view.isHidden = false 28 | UIView.animate(withDuration: kAnimationShowHideTimeInterval, animations: { () -> Void in 29 | view.alpha = maxAlphaValue 30 | }) 31 | } 32 | 33 | class func hideViewWithFadeOutAnimation(_ view: UIView) { 34 | UIView.animate(withDuration: kAnimationShowHideTimeInterval, animations: { () -> Void in 35 | view.alpha = 0 36 | }, completion: { (animated) -> Void in 37 | view.isHidden = true 38 | }) 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /ScalaDays/Helpers/Contacts/SDContactCreationHelper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 47 Degrees, LLC http://47deg.com hello@47deg.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | * not use this file except in compliance with the License. You may obtain 6 | * a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #import 18 | 19 | @interface SDContactCreationHelper : NSObject 20 | 21 | typedef NS_ENUM(int, SDContactCreationHelperError) { 22 | SDContactCreationHelperErrorNoError, 23 | SDContactCreationHelperErrorInvalidVCardData, 24 | SDContactCreationHelperErrorUnknown 25 | }; 26 | typedef void (^SDContactCreationHelperCompletionHandler)(SDContactCreationHelperError error); 27 | 28 | + (void)createContactInAddressBookFromVCardString:(NSString *)vCardString completion:(SDContactCreationHelperCompletionHandler)completion; 29 | + (NSString *)contactNameFromVCardString:(NSString *)vCardString; 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /ScalaDays/Helpers/Contacts/SDContactCreationHelper.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 47 Degrees, LLC http://47deg.com hello@47deg.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | * not use this file except in compliance with the License. You may obtain 6 | * a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #import "SDContactCreationHelper.h" 18 | #import 19 | 20 | @implementation SDContactCreationHelper 21 | 22 | + (void)createContactInAddressBookFromVCardString:(NSString *)vCardString completion:(SDContactCreationHelperCompletionHandler)completion { 23 | CFDataRef vCardData = (__bridge CFDataRef)[vCardString dataUsingEncoding:NSUTF8StringEncoding]; 24 | ABAddressBookRef book = ABAddressBookCreateWithOptions(NULL, NULL); 25 | ABRecordRef defaultSource = ABAddressBookCopyDefaultSource(book); 26 | CFArrayRef vCardPeople = ABPersonCreatePeopleInSourceWithVCardRepresentation(defaultSource, vCardData); 27 | if (vCardPeople != nil && CFArrayGetCount(vCardPeople) > 0) { 28 | ABRecordRef person = CFArrayGetValueAtIndex(vCardPeople, 0); 29 | if (ABAddressBookAddRecord(book, person, NULL) && ABAddressBookSave(book, NULL)) { 30 | completion(SDContactCreationHelperErrorNoError); 31 | return; 32 | } else { 33 | completion(SDContactCreationHelperErrorUnknown); 34 | return; 35 | } 36 | } else { 37 | completion(SDContactCreationHelperErrorInvalidVCardData); 38 | return; 39 | } 40 | } 41 | 42 | + (NSString *)contactNameFromABRecord:(ABRecordRef)person { 43 | NSString *name = (__bridge NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty); 44 | NSString *lastName = (__bridge NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty); 45 | NSString *nameToReturn = nil; 46 | if(name != nil && lastName != nil) { 47 | nameToReturn = [NSString stringWithFormat:@"%@ %@", name, lastName]; 48 | } else if(name != nil) { 49 | nameToReturn = name; 50 | } else if(lastName != nil){ 51 | nameToReturn = lastName; 52 | } 53 | return nameToReturn; 54 | } 55 | 56 | + (NSString *)contactNameFromVCardString:(NSString *)vCardString { 57 | CFDataRef vCardData = (__bridge CFDataRef)[vCardString dataUsingEncoding:NSUTF8StringEncoding]; 58 | ABAddressBookRef book = ABAddressBookCreateWithOptions(NULL, NULL); 59 | ABRecordRef defaultSource = ABAddressBookCopyDefaultSource(book); 60 | CFArrayRef vCardPeople = ABPersonCreatePeopleInSourceWithVCardRepresentation(defaultSource, vCardData); 61 | if (vCardPeople != nil && CFArrayGetCount(vCardPeople) > 0) { 62 | ABRecordRef person = CFArrayGetValueAtIndex(vCardPeople, 0); 63 | return [SDContactCreationHelper contactNameFromABRecord:person]; 64 | } 65 | return nil; 66 | } 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /ScalaDays/Helpers/Protocols/SDMenuControllerItem.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 47 Degrees, LLC http://47deg.com hello@47deg.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | * not use this file except in compliance with the License. You may obtain 6 | * a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | @objc protocol SDMenuControllerItem { 18 | 19 | var isDataLoaded : Bool { get set } 20 | 21 | func loadData() 22 | 23 | } 24 | 25 | @objc protocol SDSliderMenuBar { 26 | 27 | func didCloseMenu() 28 | 29 | } -------------------------------------------------------------------------------- /ScalaDays/Helpers/SDConstants.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 47 Degrees, LLC http://47deg.com hello@47deg.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | * not use this file except in compliance with the License. You may obtain 6 | * a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import Foundation 18 | import UIKit 19 | 20 | let kExternalKeysPlistFilename = "SDExternalKeys" 21 | let kExternalKeysDKTwitterConsumerKey = "TwitterConsumerKey" 22 | let kExternalKeysDKTwitterConsumerSecret = "TwitterConsumerSecret" 23 | 24 | let IS_IPHONE5 = UIScreen.main.bounds.size.height == 480; 25 | 26 | let icon_menu_schedule = "menu_icon_schedule" 27 | let icon_menu_social = "menu_icon_social" 28 | let icon_menu_contact = "menu_icon_contact" 29 | let icon_menu_ticket = "menu_icon_ticket" 30 | let icon_menu_sponsors = "menu_icon_sponsors" 31 | let icon_menu_places = "menu_icon_places" 32 | let icon_menu_about = "menu_icon_about" 33 | let icon_menu_speakers = "menu_icon_speakers" 34 | 35 | let Height_Row_Menu: CGFloat = 50 36 | let Height_Header_Menu: CGFloat = 130 37 | let kEstimatedDynamicCellsRowHeightHigh : CGFloat = 160.0 38 | let kEstimatedDynamicCellsRowHeightLow : CGFloat = 132.0 39 | 40 | let kAnimationShowHideTimeInterval : TimeInterval = 0.3 41 | let kTweetCount = 100 42 | let kGlobalPadding : CGFloat = 15.0 43 | 44 | let kMinimumTimeToDownloadDataFromApiInSeconds : TimeInterval = 5*60 45 | 46 | let lastModifiedDate = "Last-Modified" 47 | let url47Website = "http://www.47deg.com" 48 | let kAlphaValueFull: CGFloat = 1.0 49 | 50 | let isIOS8OrLater = {() -> Bool in 51 | switch UIDevice.current.systemVersion.compare("8.0.0", options: NSString.CompareOptions.numeric) { 52 | case .orderedSame, .orderedDescending: 53 | return true 54 | case .orderedAscending: 55 | return false 56 | } 57 | } 58 | 59 | @discardableResult 60 | func launchSafariToUrl(_ url: URL) -> Bool { 61 | guard UIApplication.shared.canOpenURL(url) else { return false } 62 | UIApplication.shared.openURL(url) 63 | return true 64 | } 65 | 66 | let screenBounds = UIScreen.main.bounds 67 | let colorScheduleTime = UIColor(red: 70/255, green: 149/255, blue: 174/255, alpha: 1) 68 | let colorScheduleTimeActive = UIColor(red: 51/255, green: 116/255, blue: 136/255, alpha: 1) 69 | -------------------------------------------------------------------------------- /ScalaDays/Helpers/Social/SDSocialHandler.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 47 Degrees, LLC http://47deg.com hello@47deg.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | * not use this file except in compliance with the License. You may obtain 6 | * a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import Foundation 18 | import TwitterKit 19 | 20 | // MARK: Tweet dictionary keys 21 | 22 | private let kTweetDKStatus = "status" 23 | private let kTwitterBaseURL = "http://www.twitter.com/" 24 | private let kTwitterBaseAppURL = "twitter://status?id=" 25 | private let kTwitterBaseAppURLUser = "twitter://user?screen_name=" 26 | 27 | enum SDGetTweetsError: Int { 28 | case invalidRequest 29 | case unknown 30 | case unauthorized 31 | } 32 | 33 | enum SDGetTweetsResult { 34 | case success(tweets: [SDTweet]) 35 | case failure(error: SDGetTweetsError) 36 | } 37 | 38 | class SDSocialHandler { 39 | 40 | func fetchTweetList(withHashtag hashtag: String, count: Int, completion: @escaping (SDGetTweetsResult) -> Void) { 41 | guard let hashtag = hashtag.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) else { 42 | completion(.failure(error: .invalidRequest)) 43 | return 44 | } 45 | 46 | let userID = TWTRTwitter.sharedInstance().sessionStore.session()?.userID 47 | let apiClient = TWTRAPIClient(userID: userID) 48 | let searchTimelineDataSource = TWTRSearchTimelineDataSource(searchQuery: hashtag, 49 | apiClient: apiClient, 50 | languageCode: nil, 51 | maxTweetsPerRequest: UInt(max(count, 0)), 52 | resultType: nil) 53 | 54 | searchTimelineDataSource.loadPreviousTweets(beforePosition: nil) { (tweets, _, error) in 55 | if let tweets = tweets { 56 | completion(.success(tweets: tweets.map { $0.sdTweet() })) 57 | } else if let _ = error, let userId = userID { 58 | TWTRTwitter.sharedInstance().sessionStore.logOutUserID(userId) 59 | completion(.failure(error: .unauthorized)) 60 | } else { 61 | completion(.failure(error: .unknown)) 62 | } 63 | } 64 | } 65 | } 66 | 67 | // MARK: - Tweet detail URL creation 68 | 69 | extension SDSocialHandler { 70 | class func urlForTweetDetail(_ tweet: SDTweet) -> URL? { 71 | return URL(string: (((kTwitterBaseURL as NSString).appendingPathComponent(tweet.username) as NSString) 72 | .appendingPathComponent(kTweetDKStatus) as NSString) 73 | .appendingPathComponent(tweet.id)) 74 | } 75 | 76 | class func urlAppForTweetDetail(_ tweet: SDTweet) -> URL? { 77 | return URL(string: kTwitterBaseAppURL + tweet.id) 78 | } 79 | 80 | class func urlForTwitterAccount(_ twitterAccount: String) -> URL? { 81 | return URL(string: (kTwitterBaseURL as NSString).appendingPathComponent(twitterAccount)) 82 | } 83 | 84 | class func urlAppForTwitterAccount(_ twitterAccount: String) -> URL? { 85 | return URL(string: (kTwitterBaseAppURLUser as NSString).appendingPathComponent(twitterAccount)) 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /ScalaDays/Helpers/Social/TWTRTweet+SDTweet.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 47 Degrees, LLC http://47deg.com hello@47deg.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | * not use this file except in compliance with the License. You may obtain 6 | * a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import Foundation 18 | import TwitterKit 19 | 20 | extension TWTRTweet { 21 | func sdTweet() -> SDTweet { 22 | return SDTweet(username: author.name, 23 | fullName: author.screenName, 24 | tweetText: text, 25 | profileImage: author.profileImageURL, 26 | date: createdAt, 27 | id: tweetID) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ScalaDays/Helpers/Social/TwitterSocialController.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Social 3 | 4 | enum TwitterSocialController { 5 | static func present(in vc: UIViewController, text: String) { 6 | guard TwitterSocialController.installed, 7 | let composeViewController = SLComposeViewController(forServiceType: SLServiceTypeTwitter) else { return } 8 | 9 | composeViewController.title = "Scala Days" 10 | composeViewController.setInitialText("\(text) ") 11 | 12 | vc.present(composeViewController, animated: true) 13 | } 14 | 15 | static var installed: Bool { 16 | guard let url = URL(string: "twitter://") else { return false } 17 | return UIApplication.shared.canOpenURL(url) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ScalaDays/Helpers/Storing/StoringHelper.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 47 Degrees, LLC http://47deg.com hello@47deg.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | * not use this file except in compliance with the License. You may obtain 6 | * a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import Foundation 18 | 19 | class StoringHelper { 20 | 21 | let kMainConferenceStoringFilename = "sdConferencesNew.data" 22 | let kVotesFilename = "sdVotesNew.data" 23 | let kVotesFilenameOld = "sdVotes.data" 24 | 25 | class var sharedInstance: StoringHelper { 26 | struct Static { 27 | static let instance: StoringHelper = StoringHelper() 28 | } 29 | return Static.instance 30 | } 31 | 32 | // MARK: - Conference storing 33 | 34 | func storeConferenceData(_ conferences: Conferences) { 35 | storeDataToFileWithFilename(conferences, filename: kMainConferenceStoringFilename) 36 | } 37 | 38 | func loadConferenceData() -> Conferences? { 39 | return loadDataFromFileWithFilename(kMainConferenceStoringFilename) 40 | } 41 | 42 | // MARK: - Votes storing 43 | 44 | func storeVotesData(_ votes: [String: Vote]) { 45 | storeDataToFileWithFilename(votes, filename: kVotesFilename) 46 | } 47 | 48 | func loadVotesData() -> [String: Vote]? { 49 | return loadDataFromFileWithFilename(kVotesFilename) 50 | } 51 | 52 | func storedVoteForConferenceId(_ conferenceId: Int, talkId: Int) -> Vote? { 53 | if let votes = loadVotesData() { 54 | let key = "\(conferenceId)\(talkId)" 55 | return votes[key] 56 | } 57 | return nil 58 | } 59 | 60 | // MARK: - Utility functions 61 | 62 | class func documentsFolderPath() -> String { 63 | return NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] 64 | } 65 | 66 | func loadDataFromFileWithFilename(_ filename: String) -> T? { 67 | let fileManager = FileManager.default 68 | let dataPath = (StoringHelper.documentsFolderPath() as NSString).appendingPathComponent(filename) 69 | 70 | guard fileManager.fileExists(atPath: dataPath), 71 | let data = NSKeyedUnarchiver.unarchiveObject(withFile: dataPath) as? Data else { 72 | return nil 73 | } 74 | 75 | return try? JSONDecoder().decode(T.self, from: data) 76 | } 77 | 78 | func storeDataToFileWithFilename(_ value: T, filename: String) { 79 | let conferenceDataPath = (StoringHelper.documentsFolderPath() as NSString).appendingPathComponent(filename) 80 | guard let data = try? JSONEncoder().encode(value) else { return } 81 | 82 | NSKeyedArchiver.archiveRootObject(data, toFile: conferenceDataPath) 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /ScalaDays/Helpers/Storing/UserDefaults+Extension.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | @propertyWrapper 4 | struct UserDefault { 5 | let key: String 6 | let defaultValue: T 7 | 8 | init(_ key: String, defaultValue: T) { 9 | self.key = key 10 | self.defaultValue = defaultValue 11 | } 12 | 13 | var wrappedValue: T { 14 | get { 15 | guard let raw = UserDefaults.standard.data(forKey: key), 16 | let value = try? PropertyListDecoder().decode(T.self, from: raw) else { return defaultValue } 17 | return value 18 | } 19 | set { 20 | let valueRaw = try? PropertyListEncoder().encode(newValue) 21 | UserDefaults.standard.set(valueRaw, forKey: key) 22 | UserDefaults.standard.synchronize() 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/AppIcon.appiconset/1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/AppIcon.appiconset/1024x1024.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "size" : "29x29", 15 | "idiom" : "iphone", 16 | "filename" : "icon-app-29x29@2x.png", 17 | "scale" : "2x" 18 | }, 19 | { 20 | "size" : "29x29", 21 | "idiom" : "iphone", 22 | "filename" : "icon-app-29x29@3x.png", 23 | "scale" : "3x" 24 | }, 25 | { 26 | "size" : "40x40", 27 | "idiom" : "iphone", 28 | "filename" : "icon-app-40x40@2x-1.png", 29 | "scale" : "2x" 30 | }, 31 | { 32 | "size" : "40x40", 33 | "idiom" : "iphone", 34 | "filename" : "icon-app-40x40@3x.png", 35 | "scale" : "3x" 36 | }, 37 | { 38 | "size" : "60x60", 39 | "idiom" : "iphone", 40 | "filename" : "icon-app-60x60@2x.png", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "size" : "60x60", 45 | "idiom" : "iphone", 46 | "filename" : "icon-app-60x60@3x.png", 47 | "scale" : "3x" 48 | }, 49 | { 50 | "idiom" : "ipad", 51 | "size" : "20x20", 52 | "scale" : "1x" 53 | }, 54 | { 55 | "idiom" : "ipad", 56 | "size" : "20x20", 57 | "scale" : "2x" 58 | }, 59 | { 60 | "size" : "29x29", 61 | "idiom" : "ipad", 62 | "filename" : "icon-app-29x29.png", 63 | "scale" : "1x" 64 | }, 65 | { 66 | "size" : "29x29", 67 | "idiom" : "ipad", 68 | "filename" : "icon-app-29x29@2x-1.png", 69 | "scale" : "2x" 70 | }, 71 | { 72 | "size" : "40x40", 73 | "idiom" : "ipad", 74 | "filename" : "icon-app-40x40.png", 75 | "scale" : "1x" 76 | }, 77 | { 78 | "size" : "40x40", 79 | "idiom" : "ipad", 80 | "filename" : "icon-app-40x40@2x.png", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "size" : "76x76", 85 | "idiom" : "ipad", 86 | "filename" : "icon-app-76x76.png", 87 | "scale" : "1x" 88 | }, 89 | { 90 | "size" : "76x76", 91 | "idiom" : "ipad", 92 | "filename" : "icon-app-76x76@2x.png", 93 | "scale" : "2x" 94 | }, 95 | { 96 | "size" : "83.5x83.5", 97 | "idiom" : "ipad", 98 | "filename" : "icon-app-83.5x83.5@2x.png", 99 | "scale" : "2x" 100 | }, 101 | { 102 | "size" : "1024x1024", 103 | "idiom" : "ios-marketing", 104 | "filename" : "1024x1024.png", 105 | "scale" : "1x" 106 | } 107 | ], 108 | "info" : { 109 | "version" : 1, 110 | "author" : "xcode" 111 | } 112 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/AppIcon.appiconset/icon-app-29x29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/AppIcon.appiconset/icon-app-29x29.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/AppIcon.appiconset/icon-app-29x29@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/AppIcon.appiconset/icon-app-29x29@2x-1.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/AppIcon.appiconset/icon-app-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/AppIcon.appiconset/icon-app-29x29@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/AppIcon.appiconset/icon-app-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/AppIcon.appiconset/icon-app-29x29@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/AppIcon.appiconset/icon-app-40x40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/AppIcon.appiconset/icon-app-40x40.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/AppIcon.appiconset/icon-app-40x40@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/AppIcon.appiconset/icon-app-40x40@2x-1.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/AppIcon.appiconset/icon-app-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/AppIcon.appiconset/icon-app-40x40@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/AppIcon.appiconset/icon-app-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/AppIcon.appiconset/icon-app-40x40@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/AppIcon.appiconset/icon-app-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/AppIcon.appiconset/icon-app-60x60@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/AppIcon.appiconset/icon-app-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/AppIcon.appiconset/icon-app-60x60@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/AppIcon.appiconset/icon-app-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/AppIcon.appiconset/icon-app-76x76.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/AppIcon.appiconset/icon-app-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/AppIcon.appiconset/icon-app-76x76@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/AppIcon.appiconset/icon-app-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/AppIcon.appiconset/icon-app-83.5x83.5@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "extent" : "full-screen", 5 | "idiom" : "iphone", 6 | "subtype" : "2436h", 7 | "filename" : "splash-iphonex.png", 8 | "minimum-system-version" : "11.0", 9 | "orientation" : "portrait", 10 | "scale" : "3x" 11 | }, 12 | { 13 | "orientation" : "landscape", 14 | "idiom" : "iphone", 15 | "extent" : "full-screen", 16 | "minimum-system-version" : "11.0", 17 | "subtype" : "2436h", 18 | "scale" : "3x" 19 | }, 20 | { 21 | "extent" : "full-screen", 22 | "idiom" : "iphone", 23 | "subtype" : "736h", 24 | "filename" : "splash-iphone6-plus.png", 25 | "minimum-system-version" : "8.0", 26 | "orientation" : "portrait", 27 | "scale" : "3x" 28 | }, 29 | { 30 | "orientation" : "landscape", 31 | "idiom" : "iphone", 32 | "extent" : "full-screen", 33 | "minimum-system-version" : "8.0", 34 | "subtype" : "736h", 35 | "scale" : "3x" 36 | }, 37 | { 38 | "extent" : "full-screen", 39 | "idiom" : "iphone", 40 | "subtype" : "667h", 41 | "filename" : "splash-iphone6.png", 42 | "minimum-system-version" : "8.0", 43 | "orientation" : "portrait", 44 | "scale" : "2x" 45 | }, 46 | { 47 | "orientation" : "portrait", 48 | "idiom" : "iphone", 49 | "filename" : "splash-iphone4@2x.png", 50 | "extent" : "full-screen", 51 | "minimum-system-version" : "7.0", 52 | "scale" : "2x" 53 | }, 54 | { 55 | "extent" : "full-screen", 56 | "idiom" : "iphone", 57 | "subtype" : "retina4", 58 | "filename" : "splash-iphone5.png", 59 | "minimum-system-version" : "7.0", 60 | "orientation" : "portrait", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "orientation" : "portrait", 65 | "idiom" : "iphone", 66 | "extent" : "full-screen", 67 | "scale" : "1x" 68 | }, 69 | { 70 | "orientation" : "portrait", 71 | "idiom" : "iphone", 72 | "extent" : "full-screen", 73 | "scale" : "2x" 74 | }, 75 | { 76 | "orientation" : "portrait", 77 | "idiom" : "iphone", 78 | "extent" : "full-screen", 79 | "subtype" : "retina4", 80 | "scale" : "2x" 81 | } 82 | ], 83 | "info" : { 84 | "version" : 1, 85 | "author" : "xcode" 86 | } 87 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/LaunchImage.launchimage/splash-iphone4@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/LaunchImage.launchimage/splash-iphone4@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/LaunchImage.launchimage/splash-iphone5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/LaunchImage.launchimage/splash-iphone5.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/LaunchImage.launchimage/splash-iphone6-plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/LaunchImage.launchimage/splash-iphone6-plus.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/LaunchImage.launchimage/splash-iphone6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/LaunchImage.launchimage/splash-iphone6.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/LaunchImage.launchimage/splash-iphonex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/LaunchImage.launchimage/splash-iphonex.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/avatar.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "avatar.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "avatar@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x", 16 | "filename" : "avatar@3x.png" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/avatar.imageset/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/avatar.imageset/avatar.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/avatar.imageset/avatar@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/avatar.imageset/avatar@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/avatar.imageset/avatar@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/avatar.imageset/avatar@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/empty_notifications.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "iconfinder_feature-available_4171950 (1).png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "iconfinder_feature-available_4171950 (2)-1.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "iconfinder_feature-available_4171950.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "template" 25 | } 26 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/empty_notifications.imageset/iconfinder_feature-available_4171950 (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/empty_notifications.imageset/iconfinder_feature-available_4171950 (1).png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/empty_notifications.imageset/iconfinder_feature-available_4171950 (2)-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/empty_notifications.imageset/iconfinder_feature-available_4171950 (2)-1.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/empty_notifications.imageset/iconfinder_feature-available_4171950.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/empty_notifications.imageset/iconfinder_feature-available_4171950.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/list_icon_vote_like.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "list_icon_vote_like.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "list_icon_vote_like@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "list_icon_vote_like@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/list_icon_vote_like.imageset/list_icon_vote_like.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/list_icon_vote_like.imageset/list_icon_vote_like.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/list_icon_vote_like.imageset/list_icon_vote_like@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/list_icon_vote_like.imageset/list_icon_vote_like@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/list_icon_vote_like.imageset/list_icon_vote_like@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/list_icon_vote_like.imageset/list_icon_vote_like@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/list_icon_vote_neutral.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "list_icon_vote_neutral.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "list_icon_vote_neutral@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "list_icon_vote_neutral@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/list_icon_vote_neutral.imageset/list_icon_vote_neutral.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/list_icon_vote_neutral.imageset/list_icon_vote_neutral.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/list_icon_vote_neutral.imageset/list_icon_vote_neutral@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/list_icon_vote_neutral.imageset/list_icon_vote_neutral@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/list_icon_vote_neutral.imageset/list_icon_vote_neutral@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/list_icon_vote_neutral.imageset/list_icon_vote_neutral@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/list_icon_vote_unlike.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "list_icon_vote_unlike.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "list_icon_vote_unlike@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "list_icon_vote_unlike@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/list_icon_vote_unlike.imageset/list_icon_vote_unlike.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/list_icon_vote_unlike.imageset/list_icon_vote_unlike.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/list_icon_vote_unlike.imageset/list_icon_vote_unlike@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/list_icon_vote_unlike.imageset/list_icon_vote_unlike@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/list_icon_vote_unlike.imageset/list_icon_vote_unlike@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/list_icon_vote_unlike.imageset/list_icon_vote_unlike@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/logo_47deg.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "logo_47deg.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "logo_47deg@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x", 16 | "filename" : "logo_47deg@3x.png" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/logo_47deg.imageset/logo_47deg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/logo_47deg.imageset/logo_47deg.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/logo_47deg.imageset/logo_47deg@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/logo_47deg.imageset/logo_47deg@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/logo_47deg.imageset/logo_47deg@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/logo_47deg.imageset/logo_47deg@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/map_popover.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "map_popover.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "map_popover@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x", 16 | "filename" : "map_popover@3x.png" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/map_popover.imageset/map_popover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/map_popover.imageset/map_popover.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/map_popover.imageset/map_popover@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/map_popover.imageset/map_popover@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/map_popover.imageset/map_popover@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/map_popover.imageset/map_popover@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/map_pushpin.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "map_pushpin.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "map_pushpin@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x", 16 | "filename" : "map_pushpin@3x.png" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/map_pushpin.imageset/map_pushpin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/map_pushpin.imageset/map_pushpin.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/map_pushpin.imageset/map_pushpin@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/map_pushpin.imageset/map_pushpin@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/map_pushpin.imageset/map_pushpin@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/map_pushpin.imageset/map_pushpin@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_header_select_arrow.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "menu_header_select_arrow.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "menu_header_select_arrow@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x", 16 | "filename" : "menu_header_select_arrow@3x.png" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_header_select_arrow.imageset/menu_header_select_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/menu_header_select_arrow.imageset/menu_header_select_arrow.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_header_select_arrow.imageset/menu_header_select_arrow@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/menu_header_select_arrow.imageset/menu_header_select_arrow@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_header_select_arrow.imageset/menu_header_select_arrow@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/menu_header_select_arrow.imageset/menu_header_select_arrow@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_about.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "menu_icon_about.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "menu_icon_about@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x", 16 | "filename" : "menu_icon_about@3x.png" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_about.imageset/menu_icon_about.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/menu_icon_about.imageset/menu_icon_about.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_about.imageset/menu_icon_about@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/menu_icon_about.imageset/menu_icon_about@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_about.imageset/menu_icon_about@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/menu_icon_about.imageset/menu_icon_about@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_contact.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "menu_icon_contact.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "menu_icon_contact@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x", 16 | "filename" : "menu_icon_contact@3x.png" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_contact.imageset/menu_icon_contact.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/menu_icon_contact.imageset/menu_icon_contact.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_contact.imageset/menu_icon_contact@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/menu_icon_contact.imageset/menu_icon_contact@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_contact.imageset/menu_icon_contact@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/menu_icon_contact.imageset/menu_icon_contact@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_notification.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "bell@1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "bell@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "bell@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_notification.imageset/bell@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/menu_icon_notification.imageset/bell@1x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_notification.imageset/bell@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/menu_icon_notification.imageset/bell@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_notification.imageset/bell@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/menu_icon_notification.imageset/bell@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_places.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "menu_icon_places.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "menu_icon_places@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x", 16 | "filename" : "menu_icon_places@3x.png" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_places.imageset/menu_icon_places.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/menu_icon_places.imageset/menu_icon_places.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_places.imageset/menu_icon_places@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/menu_icon_places.imageset/menu_icon_places@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_places.imageset/menu_icon_places@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/menu_icon_places.imageset/menu_icon_places@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_schedule.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "menu_icon_schedule.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "menu_icon_schedule@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x", 16 | "filename" : "menu_icon_schedule@3x.png" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_schedule.imageset/menu_icon_schedule.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/menu_icon_schedule.imageset/menu_icon_schedule.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_schedule.imageset/menu_icon_schedule@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/menu_icon_schedule.imageset/menu_icon_schedule@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_schedule.imageset/menu_icon_schedule@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/menu_icon_schedule.imageset/menu_icon_schedule@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_social.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "menu_icon_social.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "menu_icon_social@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x", 16 | "filename" : "menu_icon_social@3x.png" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_social.imageset/menu_icon_social.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/menu_icon_social.imageset/menu_icon_social.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_social.imageset/menu_icon_social@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/menu_icon_social.imageset/menu_icon_social@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_social.imageset/menu_icon_social@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/menu_icon_social.imageset/menu_icon_social@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_speakers.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "menu_icon_speakers.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "menu_icon_speakers@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x", 16 | "filename" : "menu_icon_speakers@3x.png" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_speakers.imageset/menu_icon_speakers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/menu_icon_speakers.imageset/menu_icon_speakers.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_speakers.imageset/menu_icon_speakers@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/menu_icon_speakers.imageset/menu_icon_speakers@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_speakers.imageset/menu_icon_speakers@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/menu_icon_speakers.imageset/menu_icon_speakers@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_sponsors.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "menu_icon_sponsors.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "menu_icon_sponsors@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x", 16 | "filename" : "menu_icon_sponsors@3x.png" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_sponsors.imageset/menu_icon_sponsors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/menu_icon_sponsors.imageset/menu_icon_sponsors.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_sponsors.imageset/menu_icon_sponsors@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/menu_icon_sponsors.imageset/menu_icon_sponsors@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_sponsors.imageset/menu_icon_sponsors@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/menu_icon_sponsors.imageset/menu_icon_sponsors@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_ticket.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "menu_icon_ticket.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "menu_icon_ticket@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x", 16 | "filename" : "menu_icon_ticket@3x.png" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_ticket.imageset/menu_icon_ticket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/menu_icon_ticket.imageset/menu_icon_ticket.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_ticket.imageset/menu_icon_ticket@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/menu_icon_ticket.imageset/menu_icon_ticket@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/menu_icon_ticket.imageset/menu_icon_ticket@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/menu_icon_ticket.imageset/menu_icon_ticket@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/navigation_bar_icon_arrow.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "navigation_bar_icon_arrow.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "navigation_bar_icon_arrow@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x", 16 | "filename" : "navigation_bar_icon_arrow@3x.png" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/navigation_bar_icon_arrow.imageset/navigation_bar_icon_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/navigation_bar_icon_arrow.imageset/navigation_bar_icon_arrow.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/navigation_bar_icon_arrow.imageset/navigation_bar_icon_arrow@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/navigation_bar_icon_arrow.imageset/navigation_bar_icon_arrow@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/navigation_bar_icon_arrow.imageset/navigation_bar_icon_arrow@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/navigation_bar_icon_arrow.imageset/navigation_bar_icon_arrow@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/navigation_bar_icon_clock.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "navigation_bar_icon_clock.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "navigation_bar_icon_clock@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x", 16 | "filename" : "navigation_bar_icon_clock@3x.png" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/navigation_bar_icon_clock.imageset/navigation_bar_icon_clock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/navigation_bar_icon_clock.imageset/navigation_bar_icon_clock.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/navigation_bar_icon_clock.imageset/navigation_bar_icon_clock@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/navigation_bar_icon_clock.imageset/navigation_bar_icon_clock@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/navigation_bar_icon_clock.imageset/navigation_bar_icon_clock@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/navigation_bar_icon_clock.imageset/navigation_bar_icon_clock@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/navigation_bar_icon_create.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "navigation_bar_icon_create.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "navigation_bar_icon_create@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x", 16 | "filename" : "navigation_bar_icon_create@3x.png" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/navigation_bar_icon_create.imageset/navigation_bar_icon_create.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/navigation_bar_icon_create.imageset/navigation_bar_icon_create.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/navigation_bar_icon_create.imageset/navigation_bar_icon_create@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/navigation_bar_icon_create.imageset/navigation_bar_icon_create@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/navigation_bar_icon_create.imageset/navigation_bar_icon_create@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/navigation_bar_icon_create.imageset/navigation_bar_icon_create@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/navigation_bar_icon_favorite_default.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "navigation_bar_icon_favorite_default.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "navigation_bar_icon_favorite_default@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x", 16 | "filename" : "navigation_bar_icon_favorite_default@3x.png" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/navigation_bar_icon_favorite_default.imageset/navigation_bar_icon_favorite_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/navigation_bar_icon_favorite_default.imageset/navigation_bar_icon_favorite_default.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/navigation_bar_icon_favorite_default.imageset/navigation_bar_icon_favorite_default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/navigation_bar_icon_favorite_default.imageset/navigation_bar_icon_favorite_default@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/navigation_bar_icon_favorite_default.imageset/navigation_bar_icon_favorite_default@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/navigation_bar_icon_favorite_default.imageset/navigation_bar_icon_favorite_default@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/navigation_bar_icon_favorite_selected.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "navigation_bar_icon_favorite_selected.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "navigation_bar_icon_favorite_selected@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x", 16 | "filename" : "navigation_bar_icon_favorite_selected@3x.png" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/navigation_bar_icon_favorite_selected.imageset/navigation_bar_icon_favorite_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/navigation_bar_icon_favorite_selected.imageset/navigation_bar_icon_favorite_selected.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/navigation_bar_icon_favorite_selected.imageset/navigation_bar_icon_favorite_selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/navigation_bar_icon_favorite_selected.imageset/navigation_bar_icon_favorite_selected@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/navigation_bar_icon_favorite_selected.imageset/navigation_bar_icon_favorite_selected@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/navigation_bar_icon_favorite_selected.imageset/navigation_bar_icon_favorite_selected@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/navigation_bar_icon_filter.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "navigation_bar_icon_filter.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "navigation_bar_icon_filter@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x", 16 | "filename" : "navigation_bar_icon_filter@3x.png" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/navigation_bar_icon_filter.imageset/navigation_bar_icon_filter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/navigation_bar_icon_filter.imageset/navigation_bar_icon_filter.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/navigation_bar_icon_filter.imageset/navigation_bar_icon_filter@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/navigation_bar_icon_filter.imageset/navigation_bar_icon_filter@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/navigation_bar_icon_filter.imageset/navigation_bar_icon_filter@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/navigation_bar_icon_filter.imageset/navigation_bar_icon_filter@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/navigation_bar_icon_menu.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "navigation_bar_icon_menu.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "navigation_bar_icon_menu@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x", 16 | "filename" : "navigation_bar_icon_menu@3x.png" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/navigation_bar_icon_menu.imageset/navigation_bar_icon_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/navigation_bar_icon_menu.imageset/navigation_bar_icon_menu.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/navigation_bar_icon_menu.imageset/navigation_bar_icon_menu@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/navigation_bar_icon_menu.imageset/navigation_bar_icon_menu@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/navigation_bar_icon_menu.imageset/navigation_bar_icon_menu@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/navigation_bar_icon_menu.imageset/navigation_bar_icon_menu@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/navigation_bar_icon_options.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "navigation_bar_icon_options.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "navigation_bar_icon_options@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x", 16 | "filename" : "navigation_bar_icon_options@3x.png" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/navigation_bar_icon_options.imageset/navigation_bar_icon_options.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/navigation_bar_icon_options.imageset/navigation_bar_icon_options.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/navigation_bar_icon_options.imageset/navigation_bar_icon_options@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/navigation_bar_icon_options.imageset/navigation_bar_icon_options@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/navigation_bar_icon_options.imageset/navigation_bar_icon_options@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/navigation_bar_icon_options.imageset/navigation_bar_icon_options@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/navigation_bar_post_tweet.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "iconfinder_Sed-17_2236318 (1).png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "iconfinder_Sed-17_2236318.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | }, 22 | "properties" : { 23 | "template-rendering-intent" : "template" 24 | } 25 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/navigation_bar_post_tweet.imageset/iconfinder_Sed-17_2236318 (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/navigation_bar_post_tweet.imageset/iconfinder_Sed-17_2236318 (1).png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/navigation_bar_post_tweet.imageset/iconfinder_Sed-17_2236318.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/navigation_bar_post_tweet.imageset/iconfinder_Sed-17_2236318.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/placeholder_contact.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "placeholder_contact.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "placeholder_contact@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x", 16 | "filename" : "placeholder_contact@3x.png" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/placeholder_contact.imageset/placeholder_contact.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/placeholder_contact.imageset/placeholder_contact.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/placeholder_contact.imageset/placeholder_contact@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/placeholder_contact.imageset/placeholder_contact@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/placeholder_contact.imageset/placeholder_contact@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/placeholder_contact.imageset/placeholder_contact@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/placeholder_error.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "placeholder_error.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "placeholder_error@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x", 16 | "filename" : "placeholder_error@3x.png" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/placeholder_error.imageset/placeholder_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/placeholder_error.imageset/placeholder_error.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/placeholder_error.imageset/placeholder_error@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/placeholder_error.imageset/placeholder_error@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/placeholder_error.imageset/placeholder_error@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/placeholder_error.imageset/placeholder_error@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/placeholder_general.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "placeholder_general.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "placeholder_general@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x", 16 | "filename" : "placeholder_general@3x.png" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/placeholder_general.imageset/placeholder_general.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/placeholder_general.imageset/placeholder_general.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/placeholder_general.imageset/placeholder_general@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/placeholder_general.imageset/placeholder_general@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/placeholder_general.imageset/placeholder_general@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/placeholder_general.imageset/placeholder_general@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/placeholder_menu.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "placeholder_menu.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "placeholder_menu@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x", 16 | "filename" : "placeholder_menu@3x.png" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/placeholder_menu.imageset/placeholder_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/placeholder_menu.imageset/placeholder_menu.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/placeholder_menu.imageset/placeholder_menu@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/placeholder_menu.imageset/placeholder_menu@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/placeholder_menu.imageset/placeholder_menu@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/placeholder_menu.imageset/placeholder_menu@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/placeholder_sponsors.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "placeholder_sponsors.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "placeholder_sponsors@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x", 16 | "filename" : "placeholder_sponsors@3x.png" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/placeholder_sponsors.imageset/placeholder_sponsors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/placeholder_sponsors.imageset/placeholder_sponsors.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/placeholder_sponsors.imageset/placeholder_sponsors@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/placeholder_sponsors.imageset/placeholder_sponsors@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/placeholder_sponsors.imageset/placeholder_sponsors@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/placeholder_sponsors.imageset/placeholder_sponsors@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/popup_icon_vote_like.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "popup_icon_vote_like.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "popup_icon_vote_like@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "popup_icon_vote_like@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/popup_icon_vote_like.imageset/popup_icon_vote_like.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/popup_icon_vote_like.imageset/popup_icon_vote_like.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/popup_icon_vote_like.imageset/popup_icon_vote_like@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/popup_icon_vote_like.imageset/popup_icon_vote_like@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/popup_icon_vote_like.imageset/popup_icon_vote_like@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/popup_icon_vote_like.imageset/popup_icon_vote_like@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/popup_icon_vote_like_disabled.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "popup_icon_vote_like_disabled.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "popup_icon_vote_like_disabled@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "popup_icon_vote_like_disabled@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/popup_icon_vote_like_disabled.imageset/popup_icon_vote_like_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/popup_icon_vote_like_disabled.imageset/popup_icon_vote_like_disabled.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/popup_icon_vote_like_disabled.imageset/popup_icon_vote_like_disabled@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/popup_icon_vote_like_disabled.imageset/popup_icon_vote_like_disabled@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/popup_icon_vote_like_disabled.imageset/popup_icon_vote_like_disabled@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/popup_icon_vote_like_disabled.imageset/popup_icon_vote_like_disabled@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/popup_icon_vote_neutral.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "popup_icon_vote_neutral.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "popup_icon_vote_neutral@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "popup_icon_vote_neutral@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/popup_icon_vote_neutral.imageset/popup_icon_vote_neutral.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/popup_icon_vote_neutral.imageset/popup_icon_vote_neutral.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/popup_icon_vote_neutral.imageset/popup_icon_vote_neutral@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/popup_icon_vote_neutral.imageset/popup_icon_vote_neutral@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/popup_icon_vote_neutral.imageset/popup_icon_vote_neutral@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/popup_icon_vote_neutral.imageset/popup_icon_vote_neutral@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/popup_icon_vote_neutral_disabled.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "popup_icon_vote_neutral_disabled.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "popup_icon_vote_neutral_disabled@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "popup_icon_vote_neutral_disabled@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/popup_icon_vote_neutral_disabled.imageset/popup_icon_vote_neutral_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/popup_icon_vote_neutral_disabled.imageset/popup_icon_vote_neutral_disabled.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/popup_icon_vote_neutral_disabled.imageset/popup_icon_vote_neutral_disabled@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/popup_icon_vote_neutral_disabled.imageset/popup_icon_vote_neutral_disabled@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/popup_icon_vote_neutral_disabled.imageset/popup_icon_vote_neutral_disabled@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/popup_icon_vote_neutral_disabled.imageset/popup_icon_vote_neutral_disabled@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/popup_icon_vote_unlike.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "popup_icon_vote_unlike.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "popup_icon_vote_unlike@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "popup_icon_vote_unlike@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/popup_icon_vote_unlike.imageset/popup_icon_vote_unlike.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/popup_icon_vote_unlike.imageset/popup_icon_vote_unlike.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/popup_icon_vote_unlike.imageset/popup_icon_vote_unlike@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/popup_icon_vote_unlike.imageset/popup_icon_vote_unlike@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/popup_icon_vote_unlike.imageset/popup_icon_vote_unlike@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/popup_icon_vote_unlike.imageset/popup_icon_vote_unlike@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/popup_icon_vote_unlike_disabled.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "popup_icon_vote_unlike_disabled.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "popup_icon_vote_unlike_disabled@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "popup_icon_vote_unlike_disabled@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/popup_icon_vote_unlike_disabled.imageset/popup_icon_vote_unlike_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/popup_icon_vote_unlike_disabled.imageset/popup_icon_vote_unlike_disabled.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/popup_icon_vote_unlike_disabled.imageset/popup_icon_vote_unlike_disabled@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/popup_icon_vote_unlike_disabled.imageset/popup_icon_vote_unlike_disabled@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/popup_icon_vote_unlike_disabled.imageset/popup_icon_vote_unlike_disabled@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/popup_icon_vote_unlike_disabled.imageset/popup_icon_vote_unlike_disabled@3x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/schedule_icon_details.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "calendar@1x-1.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "calendar@2x-1.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "calendar@3x-1.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "template" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/schedule_icon_details.imageset/calendar@1x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/schedule_icon_details.imageset/calendar@1x-1.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/schedule_icon_details.imageset/calendar@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/schedule_icon_details.imageset/calendar@2x-1.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/schedule_icon_details.imageset/calendar@3x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/schedule_icon_details.imageset/calendar@3x-1.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/schedule_tag_favorite.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "schedule_tag_favorite.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "schedule_tag_favorite@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x", 16 | "filename" : "schedule_tag_favorite@3x.png" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/schedule_tag_favorite.imageset/schedule_tag_favorite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/schedule_tag_favorite.imageset/schedule_tag_favorite.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/schedule_tag_favorite.imageset/schedule_tag_favorite@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/schedule_tag_favorite.imageset/schedule_tag_favorite@2x.png -------------------------------------------------------------------------------- /ScalaDays/Images.xcassets/schedule_tag_favorite.imageset/schedule_tag_favorite@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xebia-functional/scala-days-ios/d4570914a8fc92d43935169e5668daf11f494779/ScalaDays/Images.xcassets/schedule_tag_favorite.imageset/schedule_tag_favorite@3x.png -------------------------------------------------------------------------------- /ScalaDays/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(MARKETING_VERSION) 19 | CFBundleSignature 20 | ???? 21 | CFBundleURLTypes 22 | 23 | 24 | CFBundleTypeRole 25 | Editor 26 | CFBundleURLSchemes 27 | 28 | ampf03c22cb2db72bc6c180ece-0741609a-b833-11e4-2cc5-004a77f8b47f 29 | 30 | 31 | 32 | CFBundleVersion 33 | $(CURRENT_PROJECT_VERSION) 34 | ITSAppUsesNonExemptEncryption 35 | 36 | LSApplicationCategoryType 37 | public.app-category.utilities 38 | LSApplicationQueriesSchemes 39 | 40 | twitter 41 | twitterauth 42 | 43 | LSRequiresIPhoneOS 44 | 45 | NSAppTransportSecurity 46 | 47 | NSAllowsArbitraryLoads 48 | 49 | NSExceptionDomains 50 | 51 | public.localytics.s3.amazonaws.com 52 | 53 | NSExceptionAllowsInsecureHTTPLoads 54 | 55 | 56 | pushapi.localytics.com 57 | 58 | NSExceptionAllowsInsecureHTTPLoads 59 | 60 | 61 | 62 | 63 | NSCameraUsageDescription 64 | for scanning QR codes. 65 | NSContactsUsageDescription 66 | for saving new scanned contacts. 67 | NSLocationAlwaysUsageDescription 68 | This app may use GPS to track your location for the use of Google Maps and directions to and from pertinent locations for the event. 69 | NSLocationWhenInUseUsageDescription 70 | This app may use GPS to track your location for the use of Google Maps and directions to and from pertinent locations for the event. 71 | NSPhotoLibraryUsageDescription 72 | This app needs access to your Photo Library. 73 | UIBackgroundModes 74 | 75 | fetch 76 | remote-notification 77 | 78 | UIRequiredDeviceCapabilities 79 | 80 | armv7 81 | 82 | UIStatusBarStyle 83 | UIStatusBarStyleLightContent 84 | UISupportedInterfaceOrientations 85 | 86 | UIInterfaceOrientationPortrait 87 | 88 | UISupportedInterfaceOrientations~ipad 89 | 90 | UIInterfaceOrientationPortrait 91 | UIInterfaceOrientationPortraitUpsideDown 92 | UIInterfaceOrientationLandscapeLeft 93 | UIInterfaceOrientationLandscapeRight 94 | 95 | UIUserInterfaceStyle 96 | Light 97 | UIViewControllerBasedStatusBarAppearance 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /ScalaDays/Models/Extensions/DateFormatter+Decoders.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | extension DateFormatter { 4 | 5 | static let notificationsDateFormatter: DateFormatter = { 6 | let formatter = DateFormatter() 7 | formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ" 8 | return formatter 9 | }() 10 | } 11 | 12 | 13 | // MARK - Decoders 14 | 15 | extension JSONDecoder { 16 | 17 | static func using(_ dateFormatter: DateFormatter) -> JSONDecoder { 18 | let jsonDecoder = JSONDecoder() 19 | jsonDecoder.dateDecodingStrategy = .formatted(dateFormatter) 20 | return jsonDecoder 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ScalaDays/Models/SDMapAnnotation.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 47 Degrees, LLC http://47deg.com hello@47deg.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | * not use this file except in compliance with the License. You may obtain 6 | * a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import UIKit 18 | import MapKit 19 | 20 | class SDMapAnnotation: NSObject, MKAnnotation { 21 | let coordinate : CLLocationCoordinate2D 22 | let title, subtitle : String? 23 | 24 | init(title: String, subtitle: String, coordinate: CLLocationCoordinate2D) { 25 | self.title = title 26 | self.subtitle = subtitle 27 | self.coordinate = coordinate 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ScalaDays/Models/SDNotifications.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | struct SDNotifications: Codable { 4 | let conferenceId: Int 5 | let notifications: [SDNotification] 6 | } 7 | 8 | struct SDNotification: Codable, Equatable { 9 | let date: Date 10 | let title: String 11 | let message: String 12 | let iosDelivered: Bool 13 | 14 | enum CodingKeys: String, CodingKey { 15 | case date = "timestamp" 16 | case title 17 | case message 18 | case iosDelivered 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ScalaDays/Models/SDTweet.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 47 Degrees, LLC http://47deg.com hello@47deg.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | * not use this file except in compliance with the License. You may obtain 6 | * a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import Foundation 18 | 19 | class SDTweet: NSObject { 20 | let username: String 21 | let fullName: String 22 | let tweetText: String 23 | let profileImage: String 24 | let date: Date 25 | let id: String 26 | 27 | init(username: String, fullName: String, tweetText: String, profileImage: String, date: Date, id: String) { 28 | self.username = username 29 | self.fullName = fullName 30 | self.tweetText = tweetText 31 | self.profileImage = profileImage 32 | self.date = date 33 | self.id = id 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ScalaDays/Models/Vote.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 47 Degrees, LLC http://47deg.com hello@47deg.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | * not use this file except in compliance with the License. You may obtain 6 | * a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import Foundation 18 | 19 | enum VoteType: Int { 20 | case unlike = 0 21 | case neutral = 1 22 | case like = 2 23 | 24 | func iconNameForVoteType() -> String { 25 | switch self { 26 | case .unlike: return "list_icon_vote_unlike.png" 27 | case .neutral: return "list_icon_vote_neutral.png" 28 | case .like: return "list_icon_vote_like.png" 29 | } 30 | } 31 | } 32 | 33 | class Vote: NSObject, Codable { 34 | let voteValue: Int 35 | let talkId: Int 36 | let conferenceId: Int 37 | let comments: String? 38 | 39 | init(_voteValue: Int, _talkId: Int, _conferenceId: Int, _comments: String?) { 40 | voteValue = _voteValue 41 | talkId = _talkId 42 | conferenceId = _conferenceId 43 | comments = _comments 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /ScalaDays/ScalaDays.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | aps-environment 6 | development 7 | 8 | 9 | -------------------------------------------------------------------------------- /ScalaDays/Service/FirebaseNotifications.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Firebase 3 | 4 | protocol SubscriberNotification { 5 | func subscribe(conferences: Conferences) 6 | } 7 | 8 | class FirebaseSubscriber: SubscriberNotification { 9 | func subscribe(conferences: Conferences) { 10 | conferences.conferences.map(\.info.id).forEach { conferenceId in 11 | Messaging.messaging().subscribe(toTopic: "\(conferenceId)_\(environment)_ios".lowercased()) 12 | } 13 | Messaging.messaging().subscribe(toTopic: "\(environment)_ios".lowercased()) 14 | } 15 | 16 | private var environment: String { 17 | #if DEBUG 18 | return "debug" 19 | #else 20 | return "release" 21 | #endif 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ScalaDays/Service/NotificationManager.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Alamofire 3 | 4 | enum NotificationManagerError: Error { 5 | case invalidEndpoint 6 | case empty 7 | } 8 | 9 | class NotificationManager { 10 | private let endpoint = "https://scaladays-backend.herokuapp.com/notifications" 11 | private var cached: [SDNotification] = [] 12 | 13 | func notifications(conference: Conference, callback: @escaping (Result<[SDNotification], NotificationManagerError>) -> Void) { 14 | guard let endpoint = endpoint(conferenceId: conference.info.id) else { 15 | callback(.failure(.invalidEndpoint)); return 16 | } 17 | 18 | if cached.count > 0 { callback(.success(cached)) } 19 | reloadNotifications(endpoint: endpoint, callback: callback) 20 | } 21 | 22 | func reset() { 23 | self.cached = [] 24 | } 25 | 26 | // MARK: GET 27 | private func reloadNotifications(endpoint: URL, callback: @escaping (Result<[SDNotification], NotificationManagerError>) -> Void) { 28 | AF.request(endpoint).responseJSON { response in 29 | guard let data = response.data, 30 | let res = try? JSONDecoder.using(.notificationsDateFormatter).decode(SDNotifications.self, from: data) else { 31 | callback(.failure(.empty)); return 32 | } 33 | 34 | let notifications = res.notifications.filter { $0.iosDelivered } 35 | .sorted { notification1, notification2 in notification1.date > notification2.date } 36 | 37 | self.cached = notifications 38 | callback(notifications.count == 0 ? .failure(.empty) : .success(notifications)) 39 | } 40 | } 41 | 42 | // MARK: helpers 43 | private func endpoint(conferenceId: Int) -> URL? { 44 | URL(string: "\(endpoint)?conferenceId=\(conferenceId)") 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /ScalaDays/Service/UserManager.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | class UserManager { 4 | @UserDefault("UserManager.SelectedConference", defaultValue: nil) private var selectedConference: Conference? 5 | 6 | var selectedConferenceId: Int { selectedConference?.info.id ?? -1 } 7 | 8 | func select(conference: Conference) { 9 | self.selectedConference = conference 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /ScalaDays/UI/CellPosition.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | enum CellPosition { 4 | case top 5 | case middle 6 | case bottom 7 | case only 8 | } 9 | -------------------------------------------------------------------------------- /ScalaDays/UI/CustomViews/SDErrorPlaceholderView.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 47 Degrees, LLC http://47deg.com hello@47deg.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | * not use this file except in compliance with the License. You may obtain 6 | * a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import UIKit 18 | 19 | @objc protocol SDErrorPlaceholderViewDelegate { 20 | 21 | @objc optional func didTapRefreshButtonInErrorPlaceholder() 22 | 23 | } 24 | 25 | class SDErrorPlaceholderView: UIView { 26 | 27 | @IBOutlet weak var lblErrorMessage: UILabel! 28 | @IBOutlet weak var imgIcon: UIImageView! 29 | @IBOutlet weak var btnRefresh: UIButton! 30 | @IBOutlet weak var constraintForImgIconTopSpace: NSLayoutConstraint! 31 | weak var delegate : SDErrorPlaceholderViewDelegate? 32 | 33 | let kTopSpaceForImgIconInSmallerIphones : CGFloat = 15.0 34 | 35 | let customConstraints : NSMutableArray = NSMutableArray() 36 | var containerView: UIView! 37 | 38 | required init?(coder aDecoder: NSCoder) { 39 | super.init(coder: aDecoder) 40 | commonInit() 41 | } 42 | 43 | override init(frame: CGRect) { 44 | super.init(frame: frame) 45 | commonInit() 46 | } 47 | 48 | func commonInit() { 49 | // This init function loads our custom view from the nib: 50 | if let container = loadNibSubviewsFromNib("SDErrorPlaceholderView") { 51 | containerView = container 52 | } 53 | self.isHidden = true 54 | 55 | if IS_IPHONE5 { 56 | constraintForImgIconTopSpace.constant = kTopSpaceForImgIconInSmallerIphones 57 | } 58 | } 59 | 60 | override func updateConstraints() { 61 | self.updateCustomConstraints(customConstraints, containerView: containerView) 62 | super.updateConstraints() 63 | } 64 | 65 | @IBAction func didTapRefreshButton() { 66 | delegate?.didTapRefreshButtonInErrorPlaceholder?() 67 | } 68 | 69 | func show(_ message: String) { 70 | show(message, isGeneralMessage: false) 71 | } 72 | 73 | func show(_ message: String, isGeneralMessage: Bool) { 74 | show(message, isGeneralMessage: isGeneralMessage, buttonTitle: NSLocalizedString("error_placeholder_button_refresh", comment: "")) 75 | } 76 | 77 | func show(_ message: String, isGeneralMessage: Bool, buttonTitle: String) { 78 | if self.isHidden { 79 | self.alpha = 0 80 | self.isHidden = false 81 | self.btnRefresh.setTitle(buttonTitle, for: UIControl.State()) 82 | self.lblErrorMessage.text = message 83 | self.imgIcon.image = isGeneralMessage ? UIImage(named: "placeholder_general") : UIImage(named: "placeholder_error") 84 | UIView.animate(withDuration: kAnimationShowHideTimeInterval, animations: { () -> Void in 85 | self.alpha = 1 86 | }) 87 | } 88 | } 89 | 90 | func hide() { 91 | if !self.isHidden { 92 | UIView.animate(withDuration: kAnimationShowHideTimeInterval, animations: { () -> Void in 93 | self.alpha = 0 94 | }, completion: { (completed) -> Void in 95 | self.isHidden = true 96 | self.alpha = 1 97 | }) 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /ScalaDays/UI/CustomViews/SDQRScannerOverlayView.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 47 Degrees, LLC http://47deg.com hello@47deg.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | * not use this file except in compliance with the License. You may obtain 6 | * a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import UIKit 18 | 19 | @objc protocol SDQRScannerOverlayViewDelegate { 20 | 21 | @objc optional func didTapCancelButtonInQRScanner() 22 | 23 | } 24 | 25 | class SDQRScannerOverlayView: UIView { 26 | 27 | @IBOutlet weak var btnCancel: UIBarButtonItem! 28 | 29 | let customConstraints : NSMutableArray = NSMutableArray() 30 | var containerView: UIView! 31 | weak var delegate : SDQRScannerOverlayViewDelegate? 32 | 33 | required init?(coder aDecoder: NSCoder) { 34 | super.init(coder: aDecoder) 35 | commonInit() 36 | } 37 | 38 | override init(frame: CGRect) { 39 | super.init(frame: frame) 40 | commonInit() 41 | } 42 | 43 | func commonInit() { 44 | // This init function loads our custom view from the nib: 45 | if let container = self.loadNibSubviewsFromNib("SDQRScannerOverlayView") { 46 | containerView = container 47 | } 48 | btnCancel.title = NSLocalizedString("common_cancel", comment: "Cancel") 49 | btnCancel.target = self 50 | btnCancel.action = #selector(SDQRScannerOverlayView.didTapCancelButton) 51 | } 52 | 53 | override func updateConstraints() { 54 | self.updateCustomConstraints(customConstraints, containerView: containerView) 55 | super.updateConstraints() 56 | } 57 | 58 | // MARK: - Cancel scanning handling 59 | 60 | @objc func didTapCancelButton() { 61 | delegate?.didTapCancelButtonInQRScanner?() 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /ScalaDays/UI/CustomViews/SDQRScannerOverlayView.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /ScalaDays/UI/CustomViews/SDSpeakerScheduleView.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 47 Degrees, LLC http://47deg.com hello@47deg.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | * not use this file except in compliance with the License. You may obtain 6 | * a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import UIKit 18 | 19 | 20 | class SDSpeakerScheduleView: UIView { 21 | 22 | let customConstraints: NSMutableArray = NSMutableArray() 23 | let tapTwitter = UITapGestureRecognizer() 24 | 25 | var containerView: UIView! 26 | @IBOutlet weak var imgView: UIImageView! 27 | @IBOutlet weak var lblName: UILabel! 28 | @IBOutlet weak var lblUsername: UILabel! 29 | 30 | let kCellHeight: CGFloat = 36.0 31 | let kborderWidth: CGFloat = 1.0 32 | 33 | 34 | required init?(coder aDecoder: NSCoder) { 35 | super.init(coder: aDecoder)! 36 | commonInit() 37 | } 38 | 39 | override init(frame: CGRect) { 40 | super.init(frame: frame) 41 | commonInit() 42 | } 43 | 44 | func commonInit() { 45 | // This init function loads our custom view from the nib: 46 | if let container = loadNibSubviewsFromNib("SDSpeakerScheduleView") { 47 | containerView = container 48 | imgView.circularImage() 49 | imgView.layer.borderColor = UIColor.white.cgColor 50 | imgView.layer.borderWidth = kborderWidth 51 | } 52 | } 53 | 54 | override func updateConstraints() { 55 | self.updateCustomConstraints(customConstraints, containerView: containerView) 56 | super.updateConstraints() 57 | } 58 | 59 | func drawSpeakerData(_ speaker: Speaker) { 60 | lblName.text = speaker.name 61 | if let twitterUsername = speaker.twitter { 62 | if twitterUsername.contains("@") { 63 | lblUsername.text = twitterUsername 64 | } else { 65 | lblUsername.text = "@\(twitterUsername)" 66 | } 67 | } else { 68 | lblUsername.text = "" 69 | } 70 | if let pictureUrlString = speaker.picture { 71 | if let pictureUrl = URL(string: pictureUrlString) { 72 | imgView.sd_setImage(with: pictureUrl, placeholderImage: UIImage(named: "avatar")!) 73 | } 74 | } 75 | layoutSubviews() 76 | } 77 | 78 | func contentHeight() -> CGFloat { 79 | return kCellHeight 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /ScalaDays/UI/TableViewCells/SDConferenceTableViewCell.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 47 Degrees, LLC http://47deg.com hello@47deg.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | * not use this file except in compliance with the License. You may obtain 6 | * a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import UIKit 18 | 19 | class SDConferenceTableViewCell: UITableViewCell { 20 | 21 | @IBOutlet weak var lblConferenceName: UILabel! 22 | @IBOutlet weak var conferenceImageView: UIImageView! 23 | 24 | override func awakeFromNib() { 25 | super.awakeFromNib() 26 | self.conferenceImageView.circularImage() 27 | self.lblConferenceName.numberOfLines = 0 28 | self.lblConferenceName.setCustomFont(UIFont.fontHelveticaNeue(15), colorFont: UIColor(white: 1, alpha: 0.9)) 29 | self.backgroundColor = UIColor.appColor() 30 | let bgColorView = UIView() 31 | bgColorView.backgroundColor = UIColor.selectedCellMenu() 32 | self.selectedBackgroundView = bgColorView 33 | } 34 | 35 | func drawConferenceData(_ conference: Conference) { 36 | self.lblConferenceName.text = conference.info.longName 37 | if let pictureUrl = URL(string: conference.info.pictures[0].url) { 38 | conferenceImageView.sd_setImage(with: pictureUrl, placeholderImage: UIImage(named: "menu_icon_places")) 39 | } 40 | layoutSubviews() 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /ScalaDays/UI/TableViewCells/SDConferenceTableViewCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /ScalaDays/UI/TableViewCells/SDNotificationTableViewCell.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | class SDNotificationTableViewCell: UITableViewCell { 4 | @IBOutlet weak var timelineTop: UIView! 5 | @IBOutlet weak var timelineMiddle: UIView! 6 | @IBOutlet weak var timelineBotton: UIView! 7 | 8 | @IBOutlet weak var bullet: UIView! 9 | 10 | @IBOutlet weak var time: UILabel! 11 | @IBOutlet weak var date: UILabel! 12 | @IBOutlet weak var title: UILabel! 13 | @IBOutlet weak var message: UILabel! 14 | 15 | private var position: CellPosition = .only { didSet { updateTimelineView() }} 16 | 17 | func draw(notification: SDNotification, position: CellPosition) { 18 | setupStyle() 19 | updateBulletState(isPending: Date() < notification.date) 20 | 21 | self.position = position 22 | self.time.text = time(date: notification.date) 23 | self.date.text = day(date: notification.date) 24 | self.title.text = notification.title 25 | self.message.text = notification.message 26 | } 27 | 28 | // MARK: setup appareance 29 | private func setupStyle() { 30 | timelineTop.backgroundColor = UIColor.appRedColor() 31 | timelineMiddle.backgroundColor = UIColor.appRedColor() 32 | timelineBotton.backgroundColor = UIColor.appRedColor() 33 | time.textColor = UIColor.appRedColor() 34 | date.textColor = UIColor.appRedColor() 35 | } 36 | 37 | private func updateBulletState(isPending: Bool) { 38 | bullet.layer.cornerRadius = bullet.frame.width * 0.5 39 | bullet.layer.borderColor = UIColor.appRedColor().cgColor 40 | bullet.layer.borderWidth = 1.25 41 | bullet.backgroundColor = isPending ? .white : UIColor.appRedColor() 42 | } 43 | 44 | private func updateTimelineView() { 45 | switch position { 46 | case .top: 47 | timelineTop.isHidden = false 48 | timelineMiddle.isHidden = true 49 | timelineBotton.isHidden = true 50 | case .middle: 51 | timelineTop.isHidden = true 52 | timelineMiddle.isHidden = false 53 | timelineBotton.isHidden = true 54 | case .bottom: 55 | timelineTop.isHidden = true 56 | timelineMiddle.isHidden = true 57 | timelineBotton.isHidden = false 58 | case .only: 59 | timelineTop.isHidden = true 60 | timelineMiddle.isHidden = true 61 | timelineBotton.isHidden = true 62 | } 63 | } 64 | 65 | // MARK: helpers 66 | private func time(date: Date) -> String { 67 | let formatter = DateFormatter() 68 | formatter.dateFormat = "hh:mm a" 69 | return formatter.string(from: date) 70 | } 71 | 72 | private func day(date: Date) -> String { 73 | let formatter = DateFormatter() 74 | formatter.timeStyle = .none 75 | formatter.dateStyle = .medium 76 | return formatter.string(from: date) 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /ScalaDays/UI/TableViewCells/SDSocialTableViewCell.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 47 Degrees, LLC http://47deg.com hello@47deg.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | * not use this file except in compliance with the License. You may obtain 6 | * a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import UIKit 18 | import NSDate_TimeAgo 19 | 20 | class SDSocialTableViewCell: UITableViewCell { 21 | @IBOutlet weak var imgView : UIImageView! 22 | @IBOutlet weak var lblFullName : UILabel! 23 | @IBOutlet weak var lblUsername : UILabel! 24 | @IBOutlet weak var lblContent : UILabel! 25 | @IBOutlet weak var lblDate : UILabel! 26 | 27 | let kWidthForImgView : CGFloat = 40.0 28 | 29 | override func awakeFromNib() { 30 | self.imgView.circularImage() 31 | self.lblContent.numberOfLines = 0 32 | self.lblContent.setCustomFont(UIFont.fontHelveticaNeueLight(15), colorFont: UIColor.appColor()) 33 | self.lblFullName.setCustomFont(UIFont.fontHelveticaNeueMedium(15), colorFont: UIColor.appColor()) 34 | self.lblDate.setCustomFont(UIFont.fontHelveticaNeue(12), colorFont: UIColor.appColor()) 35 | self.lblDate.alpha = 0.7 36 | self.lblUsername.setCustomFont(UIFont.fontHelveticaNeue(15), colorFont: UIColor.appRedColor()) 37 | } 38 | 39 | override func layoutSubviews() { 40 | super.layoutSubviews() 41 | lblContent?.preferredMaxLayoutWidth = self.frame.size.width - kWidthForImgView - (kGlobalPadding * 3) 42 | } 43 | 44 | internal func drawTweetData(_ tweet: SDTweet) { 45 | lblFullName.text = tweet.username 46 | lblUsername.text = "@\(tweet.fullName)" 47 | lblContent.attributedText = tweet.tweetText.tweetAttributedText 48 | lblDate.text = (tweet.date as NSDate).timeAgoSimple() 49 | let imageUrl = URL(string: tweet.profileImage) 50 | if let profileImageUrl = imageUrl { 51 | imgView.sd_setImage(with: profileImageUrl) 52 | } 53 | layoutSubviews() 54 | } 55 | } 56 | 57 | // MARK: - Tweets style 58 | 59 | private extension String { 60 | var tweetAttributedText: NSAttributedString { 61 | let attributedText = NSMutableAttributedString(string: self) 62 | guard let regexHastags = Regex.hastagsOrMentions.regularExpression, 63 | let regexURLs = NSTextCheckingResult.CheckingType.link.regularExpression else { 64 | return attributedText 65 | } 66 | 67 | regexHastags.matches(in: attributedText.string).forEach { range in 68 | attributedText.addAttribute(.foregroundColor, value: Color.highlight, range: range) 69 | } 70 | 71 | regexURLs.matches(in: attributedText.string).forEach { range in 72 | attributedText.addAttribute(.foregroundColor, value: Color.highlight, range: range) 73 | } 74 | 75 | return attributedText 76 | } 77 | 78 | enum Regex { 79 | static let hastagsOrMentions = "\\B([\\#|\\@][a-zA-Z0-9_]+\\b)(?!;)" 80 | } 81 | 82 | enum Color { 83 | static let highlight = UIColor.init(red: 27/255.0, green: 149/255.0, blue: 224/255.0, alpha: 1) 84 | } 85 | } 86 | 87 | private extension String { 88 | var regularExpression: NSRegularExpression? { 89 | try? NSRegularExpression(pattern: self, options: []) 90 | } 91 | } 92 | 93 | private extension NSTextCheckingResult.CheckingType { 94 | var regularExpression: NSRegularExpression? { 95 | try? NSDataDetector(types: rawValue) 96 | } 97 | } 98 | 99 | private extension NSRegularExpression { 100 | func matches(in input: String) -> [NSRange] { 101 | matches(in: input, options: [], range: NSMakeRange(0, input.utf16.count)).map(\.range) 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /ScalaDays/UI/TableViewCells/SDSpeakersTableViewCell.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 47 Degrees, LLC http://47deg.com hello@47deg.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | * not use this file except in compliance with the License. You may obtain 6 | * a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import UIKit 18 | 19 | class SDSpeakersTableViewCell: SDSocialTableViewCell { 20 | override func awakeFromNib() { 21 | self.imgView.circularImage() 22 | self.lblContent.numberOfLines = 0 23 | self.lblContent.setCustomFont(UIFont.fontHelveticaNeueLight(15), colorFont: UIColor.appColor()) 24 | self.lblFullName.setCustomFont(UIFont.fontHelveticaNeueMedium(15), colorFont: UIColor.appColor()) 25 | self.lblUsername.setCustomFont(UIFont.fontHelveticaNeue(15), colorFont: UIColor.appRedColor()) 26 | } 27 | 28 | func drawSpeakerData(_ speaker: Speaker) { 29 | lblFullName.text = speaker.name 30 | if let twitterUsername = speaker.twitter { 31 | if twitterUsername.contains("@") { 32 | lblUsername.text = twitterUsername 33 | } else { 34 | lblUsername.text = "@\(twitterUsername)" 35 | } 36 | } else { 37 | lblUsername.text = "" 38 | } 39 | lblContent.text = speaker.bio.trimmingCharacters(in: CharacterSet.whitespaces) 40 | 41 | if let pictureUrlString = speaker.picture { 42 | if let pictureUrl = URL(string: pictureUrlString) { 43 | imgView.sd_setImage(with: pictureUrl, placeholderImage: UIImage(named: "avatar")!) 44 | } 45 | } 46 | layoutSubviews() 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /ScalaDays/UI/TableViewCells/SDSponsorsTableViewCell.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 47 Degrees, LLC http://47deg.com hello@47deg.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | * not use this file except in compliance with the License. You may obtain 6 | * a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import UIKit 18 | 19 | class SDSponsorsTableViewCell: UITableViewCell { 20 | 21 | @IBOutlet weak var imgView: UIImageView! 22 | @IBOutlet weak var constraintForImageHeight: NSLayoutConstraint! 23 | 24 | func drawSponsorData(_ sponsor: Sponsor) { 25 | imgView.sd_setImage(with: URL(string: sponsor.logo), placeholderImage: UIImage(named: "placeholder_sponsors")) 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /ScalaDays/UI/TableViewCells/SDSponsorsTableViewCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /ScalaDays/UI/TableViewCells/SDTableHeaderView.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 47 Degrees, LLC http://47deg.com hello@47deg.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | * not use this file except in compliance with the License. You may obtain 6 | * a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import UIKit 18 | 19 | class SDTableHeaderView: UIView { 20 | 21 | let kHeaderTextPadding : CGPoint = CGPoint(x: 16, y: 11) 22 | let kHeaderTextInitialWidth : CGFloat = 300.0 23 | let kHeaderTextInitialHeight : CGFloat = 15.0 24 | 25 | var lblDate: UILabel! 26 | 27 | override init(frame: CGRect) { 28 | super.init(frame: frame) 29 | 30 | self.backgroundColor = UIColor.appScheduleTimeBlueBackgroundColor() 31 | lblDate = UILabel(frame: CGRect(x: kHeaderTextPadding.x, y: kHeaderTextPadding.y, width: kHeaderTextInitialWidth, height: kHeaderTextInitialHeight)) 32 | lblDate.backgroundColor = UIColor.clear 33 | lblDate.setCustomFont(UIFont.fontHelveticaNeue(15), colorFont: UIColor.white) 34 | self.addSubview(lblDate) 35 | } 36 | 37 | required init?(coder aDecoder: NSCoder) { 38 | super.init(coder: aDecoder)! 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /ScalaDays/UI/Utils/UITableView+Cells.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | extension UITableView { 4 | func registerCell(_: T.Type) { 5 | register(T.nib, forCellReuseIdentifier: T.reuseIdentifier) 6 | } 7 | 8 | func dequeueCell(for indexPath: IndexPath) -> T { 9 | guard let cell = dequeueReusableCell(withIdentifier: T.reuseIdentifier, for: indexPath) as? T else { 10 | fatalError() 11 | } 12 | return cell 13 | } 14 | } 15 | 16 | extension UIView { 17 | static var nib: UINib { 18 | return UINib(nibName: String(describing: self), bundle: Bundle.local) 19 | } 20 | } 21 | 22 | protocol ReusableCell { 23 | static var reuseIdentifier: String { get } 24 | } 25 | 26 | extension ReusableCell where Self: UIView { 27 | static var reuseIdentifier: String { 28 | return String(describing: self) 29 | } 30 | } 31 | 32 | extension UITableViewCell: ReusableCell {} 33 | -------------------------------------------------------------------------------- /ScalaDays/UI/Utils/UITextView+HTML.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | extension UITextView { 4 | var textHTML: String? { 5 | get { text } 6 | set(value) { 7 | setTextHTML(value ?? "", 8 | font: self.font ?? UIFont.systemFont(ofSize: UIFont.systemFontSize)) 9 | } 10 | } 11 | 12 | func setHTMLAppareance(_ appareance: [NSAttributedString.Key : Any], textColor: UIColor? = nil, font: UIFont? = nil) { 13 | self.textColor = textColor ?? self.textColor 14 | self.font = font ?? self.font 15 | self.linkTextAttributes = appareance 16 | } 17 | 18 | // MARK: - private 19 | private func setTextHTML(_ text: String, font: UIFont) { 20 | guard !text.isEmpty, 21 | let attributedText = "\(styleHTML(font: font))\(text.plain2HTML)".htmlAttributedString else { return } 22 | 23 | self.attributedText = attributedText 24 | } 25 | 26 | private func styleHTML(font: UIFont) -> String { 27 | """ 28 | 35 | """ 36 | } 37 | } 38 | 39 | // MARK: Helpers 40 | private extension String { 41 | 42 | var htmlAttributedString: NSAttributedString? { 43 | guard let data = data(using: .utf16) else { return nil } 44 | return try? NSAttributedString(data: data, 45 | options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding: String.Encoding.utf16.rawValue], 46 | documentAttributes: nil) 47 | } 48 | 49 | var plain2HTML: String { 50 | replacingOccurrences(of: "\n", with: "") 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /ScalaDays/en.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 47 Degrees, LLC http://47deg.com hello@47deg.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | * not use this file except in compliance with the License. You may obtain 6 | * a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // Common 18 | 19 | "common_ok" = "OK"; 20 | "common_cancel" = "Cancel"; 21 | "common_back" = "Back"; 22 | 23 | // Menu 24 | "schedule" = "Schedule"; 25 | "social" = "Social"; 26 | "contacts" = "Contacts"; 27 | "tickets" = "Tickets"; 28 | "sponsors" = "Sponsors"; 29 | "places" = "Places"; 30 | "about" = "About"; 31 | "speakers" = "Speakers"; 32 | "notification" = "Notifications"; 33 | "code_conduct" = "Code of conduct"; 34 | 35 | // Schedule 36 | 37 | "schedule_action_sheet_filter_title" = "Filter Events"; 38 | "schedule_action_sheet_filter_message_all" = "All Events"; 39 | "schedule_action_sheet_filter_message_favorites" = "Favorites"; 40 | "schedule_location_title" = "Room: "; 41 | "schedule_action_sheet_filter_message_favorites" = "My Favorites"; 42 | "schedule_error_vote_title" = "Error"; 43 | "schedule_error_vote_message" = "There was a problem while trying to send your vote. Please try again in a few moments."; 44 | "schedule_vote_comments_placeholder" = "Leave a comment on your opinion of this talk to help out the speaker."; 45 | "schedule_vote_comments_cancel_warning_title" = "Cancel vote"; 46 | "schedule_vote_comments_cancel_warning_message" = "Your vote and comments will be lost. Are you sure you want to exit?"; 47 | "schedule_vote_comments_cancel_warning_btn_exit" = "Exit"; 48 | 49 | // Social 50 | 51 | "social_error_no_valid_tweets" = "Something happened while trying to retrieve the latest Scala Days tweets. Please tap on this message to try again in a few minutes."; 52 | "social_error_no_tweets_for_current_hashtag" = "We haven't found any tweets about this conference yet. Please tap on this message to try again in a few minutes."; 53 | 54 | // Contacts 55 | 56 | "contacts_regular_feedback_message" = "You can add a contact by tapping on \"SCAN CONTACT\" and scanning the corresponding QR Code."; 57 | "contacts_regular_feedback_error_no_access" = "Scala Days needs permission to access your Address Book in order to create a new contact. You can grant access to this app in the \"Settings\" app of your device."; 58 | "contacts_regular_feedback_error_invalid_qr_code" = "The QR Code seems to be invalid. Please try again by tapping on \"SCAN CONTACT\"."; 59 | "contacts_regular_feedback_error_unknown" = "There was an error while scanning the QR Code. Please try again by tapping on \"SCAN CONTACT\"."; 60 | "contacts_add_contact_success_message" = "Contact was successfully added to your Address Book!"; 61 | "contacts_add_contact_request" = "Do you really want to add %@ to your Address Book?"; 62 | "contacts_add_contact_request_no_name" = "Scanned contact doesn't have a first or last name, do you really want to add it to your Address Book?"; 63 | 64 | // Error placeholder 65 | 66 | "error_placeholder_button_refresh" = "RELOAD"; 67 | "error_message_no_data_available" = "There was an error while trying to retrieve the latest Scala Days information. Please tap on the \"RELOAD\" button to try again."; 68 | "error_insufficient_content" = "We haven't found any data for this section yet. Please tap on the \"RELOAD\" button to try again."; 69 | "error_no_favorites" = "You haven't favorited any events yet. You can select an event and mark it as a favorite by tapping on the button at the upper-right part of the screen."; 70 | 71 | // About 72 | "feeback_button" = "Send anonymous feedback"; 73 | 74 | // Notifications 75 | "empty_notification_message" = "No notifications have been sent yet"; 76 | --------------------------------------------------------------------------------