diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7b0d62b --- /dev/null +++ b/.gitignore @@ -0,0 +1,78 @@ +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated +build/ +DerivedData/ + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata/ + +## Other +*.moved-aside +*.xccheckout +*.xcscmblueprint + +## Obj-C/Swift specific +*.hmap +*.ipa +*.dSYM.zip +*.dSYM + +## Playgrounds +timeline.xctimeline +playground.xcworkspace + +# Swift Package Manager +# +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +# Packages/ +# Package.pins +# Package.resolved +.build/ + +# CocoaPods +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# +# Pods/ +# +# Add this line if you want to avoid checking in source code from the Xcode workspace +# *.xcworkspace + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/#source-control + +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots/**/*.png +fastlane/test_output + +# Code Injection +# +# After new code Injection tools there's a generated folder /iOSInjectionProject +# https://github.com/johnno1962/injectionforxcode + +iOSInjectionProject/ diff --git a/Odeon.xcodeproj/project.pbxproj b/Odeon.xcodeproj/project.pbxproj index 47285f4..69b2225 100644 --- a/Odeon.xcodeproj/project.pbxproj +++ b/Odeon.xcodeproj/project.pbxproj @@ -3,10 +3,30 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 51; objects = { /* Begin PBXBuildFile section */ + 9885CE3421C6719B00900C9F /* Onboarding.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9885CE3321C6719B00900C9F /* Onboarding.storyboard */; }; + 9885CE3721C6784800900C9F /* OnboardingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9885CE3621C6784800900C9F /* OnboardingViewController.swift */; }; + 9885CE3A21C6785A00900C9F /* OnboardingCountryChooserViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9885CE3921C6785A00900C9F /* OnboardingCountryChooserViewController.swift */; }; + 9885CE3C21C6786400900C9F /* OnboardingLocationServicesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9885CE3B21C6786400900C9F /* OnboardingLocationServicesViewController.swift */; }; + 9885CE3E21C6786C00900C9F /* OnboardingLoadingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9885CE3D21C6786C00900C9F /* OnboardingLoadingViewController.swift */; }; + 9885CE4221C67A6500900C9F /* Storage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9885CE4121C67A6500900C9F /* Storage.swift */; }; + 9885CE4421C67B6B00900C9F /* OdeonStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9885CE4321C67B6B00900C9F /* OdeonStorage.swift */; }; + 9885CE4721C67D8F00900C9F /* Cinema.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9885CE4621C67D8F00900C9F /* Cinema.swift */; }; + 9885CE4A21C67EFF00900C9F /* ListCinemasResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9885CE4921C67EFF00900C9F /* ListCinemasResponse.swift */; }; + 9885CE4E21C67FCA00900C9F /* DictionaryStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9885CE4D21C67FCA00900C9F /* DictionaryStorage.swift */; }; + 9885CE5021C6824E00900C9F /* FilmAttributesResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9885CE4F21C6824E00900C9F /* FilmAttributesResponse.swift */; }; + 9885CE5221C6829400900C9F /* PerformanceAttributesResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9885CE5121C6829400900C9F /* PerformanceAttributesResponse.swift */; }; + 9885CE5421C682D700900C9F /* ListFilmsResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9885CE5321C682D700900C9F /* ListFilmsResponse.swift */; }; + 9885CE5621C682FB00900C9F /* Film.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9885CE5521C682FB00900C9F /* Film.swift */; }; + 9885CE5821C6840600900C9F /* Offer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9885CE5721C6840600900C9F /* Offer.swift */; }; + 9885CE5A21C684D100900C9F /* Certificate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9885CE5921C684D100900C9F /* Certificate.swift */; }; + 9885CE5C21C689F500900C9F /* FilmDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9885CE5B21C689F500900C9F /* FilmDetails.swift */; }; + 9885CE5E21C68A7900900C9F /* DataWrapperGenericResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9885CE5D21C68A7900900C9F /* DataWrapperGenericResponse.swift */; }; + 9885CE6021C68B7A00900C9F /* FilmTimes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9885CE5F21C68B7A00900C9F /* FilmTimes.swift */; }; + 9885CE6221C68BB200900C9F /* Performance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9885CE6121C68BB200900C9F /* Performance.swift */; }; 98F3708C21C6705A002D4E7C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98F3708B21C6705A002D4E7C /* AppDelegate.swift */; }; 98F3708E21C6705A002D4E7C /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98F3708D21C6705A002D4E7C /* ViewController.swift */; }; 98F3709121C6705A002D4E7C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 98F3708F21C6705A002D4E7C /* Main.storyboard */; }; @@ -26,6 +46,26 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 9885CE3321C6719B00900C9F /* Onboarding.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Onboarding.storyboard; sourceTree = ""; }; + 9885CE3621C6784800900C9F /* OnboardingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingViewController.swift; sourceTree = ""; }; + 9885CE3921C6785A00900C9F /* OnboardingCountryChooserViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingCountryChooserViewController.swift; sourceTree = ""; }; + 9885CE3B21C6786400900C9F /* OnboardingLocationServicesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingLocationServicesViewController.swift; sourceTree = ""; }; + 9885CE3D21C6786C00900C9F /* OnboardingLoadingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingLoadingViewController.swift; sourceTree = ""; }; + 9885CE4121C67A6500900C9F /* Storage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Storage.swift; sourceTree = ""; }; + 9885CE4321C67B6B00900C9F /* OdeonStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OdeonStorage.swift; sourceTree = ""; }; + 9885CE4621C67D8F00900C9F /* Cinema.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Cinema.swift; sourceTree = ""; }; + 9885CE4921C67EFF00900C9F /* ListCinemasResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListCinemasResponse.swift; sourceTree = ""; }; + 9885CE4D21C67FCA00900C9F /* DictionaryStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DictionaryStorage.swift; sourceTree = ""; }; + 9885CE4F21C6824E00900C9F /* FilmAttributesResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilmAttributesResponse.swift; sourceTree = ""; }; + 9885CE5121C6829400900C9F /* PerformanceAttributesResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PerformanceAttributesResponse.swift; sourceTree = ""; }; + 9885CE5321C682D700900C9F /* ListFilmsResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListFilmsResponse.swift; sourceTree = ""; }; + 9885CE5521C682FB00900C9F /* Film.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Film.swift; sourceTree = ""; }; + 9885CE5721C6840600900C9F /* Offer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Offer.swift; sourceTree = ""; }; + 9885CE5921C684D100900C9F /* Certificate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Certificate.swift; sourceTree = ""; }; + 9885CE5B21C689F500900C9F /* FilmDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilmDetails.swift; sourceTree = ""; }; + 9885CE5D21C68A7900900C9F /* DataWrapperGenericResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataWrapperGenericResponse.swift; sourceTree = ""; }; + 9885CE5F21C68B7A00900C9F /* FilmTimes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilmTimes.swift; sourceTree = ""; }; + 9885CE6121C68BB200900C9F /* Performance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Performance.swift; sourceTree = ""; }; 98F3708821C6705A002D4E7C /* Odeon.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Odeon.app; sourceTree = BUILT_PRODUCTS_DIR; }; 98F3708B21C6705A002D4E7C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 98F3708D21C6705A002D4E7C /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; @@ -56,6 +96,104 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 9885CE3121C6713A00900C9F /* Modules */ = { + isa = PBXGroup; + children = ( + 9885CE4021C67A5000900C9F /* Storage */, + 9885CE3F21C67A4A00900C9F /* Networking */, + 9885CE3221C6713F00900C9F /* Onboarding */, + ); + path = Modules; + sourceTree = ""; + }; + 9885CE3221C6713F00900C9F /* Onboarding */ = { + isa = PBXGroup; + children = ( + 9885CE3521C6783700900C9F /* View Controllers */, + 9885CE3321C6719B00900C9F /* Onboarding.storyboard */, + ); + path = Onboarding; + sourceTree = ""; + }; + 9885CE3521C6783700900C9F /* View Controllers */ = { + isa = PBXGroup; + children = ( + 9885CE3821C6784B00900C9F /* Pages */, + 9885CE3621C6784800900C9F /* OnboardingViewController.swift */, + ); + path = "View Controllers"; + sourceTree = ""; + }; + 9885CE3821C6784B00900C9F /* Pages */ = { + isa = PBXGroup; + children = ( + 9885CE3921C6785A00900C9F /* OnboardingCountryChooserViewController.swift */, + 9885CE3B21C6786400900C9F /* OnboardingLocationServicesViewController.swift */, + 9885CE3D21C6786C00900C9F /* OnboardingLoadingViewController.swift */, + ); + path = Pages; + sourceTree = ""; + }; + 9885CE3F21C67A4A00900C9F /* Networking */ = { + isa = PBXGroup; + children = ( + 9885CE4821C67EF500900C9F /* Responses */, + 9885CE4521C67D6F00900C9F /* Models */, + ); + path = Networking; + sourceTree = ""; + }; + 9885CE4021C67A5000900C9F /* Storage */ = { + isa = PBXGroup; + children = ( + 9885CE4121C67A6500900C9F /* Storage.swift */, + 9885CE4321C67B6B00900C9F /* OdeonStorage.swift */, + ); + path = Storage; + sourceTree = ""; + }; + 9885CE4521C67D6F00900C9F /* Models */ = { + isa = PBXGroup; + children = ( + 9885CE4621C67D8F00900C9F /* Cinema.swift */, + 9885CE5521C682FB00900C9F /* Film.swift */, + 9885CE5721C6840600900C9F /* Offer.swift */, + 9885CE5921C684D100900C9F /* Certificate.swift */, + 9885CE5B21C689F500900C9F /* FilmDetails.swift */, + 9885CE5F21C68B7A00900C9F /* FilmTimes.swift */, + 9885CE6121C68BB200900C9F /* Performance.swift */, + ); + path = Models; + sourceTree = ""; + }; + 9885CE4821C67EF500900C9F /* Responses */ = { + isa = PBXGroup; + children = ( + 9885CE4921C67EFF00900C9F /* ListCinemasResponse.swift */, + 9885CE4F21C6824E00900C9F /* FilmAttributesResponse.swift */, + 9885CE5121C6829400900C9F /* PerformanceAttributesResponse.swift */, + 9885CE5321C682D700900C9F /* ListFilmsResponse.swift */, + 9885CE5D21C68A7900900C9F /* DataWrapperGenericResponse.swift */, + ); + path = Responses; + sourceTree = ""; + }; + 9885CE4B21C67FA900900C9F /* Modules */ = { + isa = PBXGroup; + children = ( + 9885CE4C21C67FB100900C9F /* Storage */, + ); + path = Modules; + sourceTree = ""; + }; + 9885CE4C21C67FB100900C9F /* Storage */ = { + isa = PBXGroup; + children = ( + 9885CE4D21C67FCA00900C9F /* DictionaryStorage.swift */, + ); + path = Storage; + sourceTree = ""; + }; 98F3707F21C6705A002D4E7C = { isa = PBXGroup; children = ( @@ -77,6 +215,7 @@ 98F3708A21C6705A002D4E7C /* Odeon */ = { isa = PBXGroup; children = ( + 9885CE3121C6713A00900C9F /* Modules */, 98F3708B21C6705A002D4E7C /* AppDelegate.swift */, 98F3708D21C6705A002D4E7C /* ViewController.swift */, 98F3708F21C6705A002D4E7C /* Main.storyboard */, @@ -90,6 +229,7 @@ 98F3709F21C6705B002D4E7C /* OdeonTests */ = { isa = PBXGroup; children = ( + 9885CE4B21C67FA900900C9F /* Modules */, 98F370A021C6705B002D4E7C /* OdeonTests.swift */, 98F370A221C6705B002D4E7C /* Info.plist */, ); @@ -154,7 +294,7 @@ }; }; buildConfigurationList = 98F3708321C6705A002D4E7C /* Build configuration list for PBXProject "Odeon" */; - compatibilityVersion = "Xcode 9.3"; + compatibilityVersion = "Xcode 10.0"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( @@ -180,6 +320,7 @@ 98F3709621C6705B002D4E7C /* LaunchScreen.storyboard in Resources */, 98F3709321C6705B002D4E7C /* Assets.xcassets in Resources */, 98F3709121C6705A002D4E7C /* Main.storyboard in Resources */, + 9885CE3421C6719B00900C9F /* Onboarding.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -197,8 +338,26 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 9885CE3A21C6785A00900C9F /* OnboardingCountryChooserViewController.swift in Sources */, + 9885CE4221C67A6500900C9F /* Storage.swift in Sources */, + 9885CE6021C68B7A00900C9F /* FilmTimes.swift in Sources */, 98F3708E21C6705A002D4E7C /* ViewController.swift in Sources */, + 9885CE4721C67D8F00900C9F /* Cinema.swift in Sources */, + 9885CE3C21C6786400900C9F /* OnboardingLocationServicesViewController.swift in Sources */, + 9885CE6221C68BB200900C9F /* Performance.swift in Sources */, + 9885CE3721C6784800900C9F /* OnboardingViewController.swift in Sources */, + 9885CE5221C6829400900C9F /* PerformanceAttributesResponse.swift in Sources */, + 9885CE3E21C6786C00900C9F /* OnboardingLoadingViewController.swift in Sources */, 98F3708C21C6705A002D4E7C /* AppDelegate.swift in Sources */, + 9885CE5821C6840600900C9F /* Offer.swift in Sources */, + 9885CE4421C67B6B00900C9F /* OdeonStorage.swift in Sources */, + 9885CE4A21C67EFF00900C9F /* ListCinemasResponse.swift in Sources */, + 9885CE5021C6824E00900C9F /* FilmAttributesResponse.swift in Sources */, + 9885CE5421C682D700900C9F /* ListFilmsResponse.swift in Sources */, + 9885CE5C21C689F500900C9F /* FilmDetails.swift in Sources */, + 9885CE5621C682FB00900C9F /* Film.swift in Sources */, + 9885CE5E21C68A7900900C9F /* DataWrapperGenericResponse.swift in Sources */, + 9885CE5A21C684D100900C9F /* Certificate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -207,6 +366,7 @@ buildActionMask = 2147483647; files = ( 98F370A121C6705B002D4E7C /* OdeonTests.swift in Sources */, + 9885CE4E21C67FCA00900C9F /* DictionaryStorage.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -361,15 +521,17 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = Y7J92F92X4; INFOPLIST_FILE = Odeon/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = uk.sherlo.Odeon; + PRODUCT_BUNDLE_IDENTIFIER = uk.sherlo.odeon; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.2; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = 1; }; name = Debug; }; @@ -378,15 +540,17 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = Y7J92F92X4; INFOPLIST_FILE = Odeon/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = uk.sherlo.Odeon; + PRODUCT_BUNDLE_IDENTIFIER = uk.sherlo.odeon; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.2; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = 1; }; name = Release; }; diff --git a/Odeon.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/Odeon.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..0c67376 --- /dev/null +++ b/Odeon.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,5 @@ + + + + + diff --git a/Odeon/Assets.xcassets/Background/Contents.json b/Odeon/Assets.xcassets/Background/Contents.json new file mode 100644 index 0000000..38f0c81 --- /dev/null +++ b/Odeon/Assets.xcassets/Background/Contents.json @@ -0,0 +1,9 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "provides-namespace" : true + } +} \ No newline at end of file diff --git a/Odeon/Assets.xcassets/Background/odeon-o.imageset/Contents.json b/Odeon/Assets.xcassets/Background/odeon-o.imageset/Contents.json new file mode 100644 index 0000000..3cc2581 --- /dev/null +++ b/Odeon/Assets.xcassets/Background/odeon-o.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "odeon-o-background.jpg" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Odeon/Assets.xcassets/Background/odeon-o.imageset/odeon-o-background.jpg b/Odeon/Assets.xcassets/Background/odeon-o.imageset/odeon-o-background.jpg new file mode 100644 index 0000000..5447447 Binary files /dev/null and b/Odeon/Assets.xcassets/Background/odeon-o.imageset/odeon-o-background.jpg differ diff --git a/Odeon/Assets.xcassets/Modules/Contents.json b/Odeon/Assets.xcassets/Modules/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/Odeon/Assets.xcassets/Modules/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Odeon/Assets.xcassets/Modules/Shared/Colours/Contents.json b/Odeon/Assets.xcassets/Modules/Shared/Colours/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/Odeon/Assets.xcassets/Modules/Shared/Colours/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Odeon/Assets.xcassets/Modules/Shared/Colours/FlatButtonBackground.colorset/Contents.json b/Odeon/Assets.xcassets/Modules/Shared/Colours/FlatButtonBackground.colorset/Contents.json new file mode 100644 index 0000000..9d72108 --- /dev/null +++ b/Odeon/Assets.xcassets/Modules/Shared/Colours/FlatButtonBackground.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + }, + "colors" : [ + { + "idiom" : "universal", + "color" : { + "color-space" : "srgb", + "components" : { + "red" : "0xFE", + "alpha" : "1.000", + "blue" : "0x5C", + "green" : "0x84" + } + } + } + ] +} \ No newline at end of file diff --git a/Odeon/Assets.xcassets/Modules/Shared/Colours/PrimaryBackground.colorset/Contents.json b/Odeon/Assets.xcassets/Modules/Shared/Colours/PrimaryBackground.colorset/Contents.json new file mode 100644 index 0000000..dbb0a81 --- /dev/null +++ b/Odeon/Assets.xcassets/Modules/Shared/Colours/PrimaryBackground.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + }, + "colors" : [ + { + "idiom" : "universal", + "color" : { + "color-space" : "srgb", + "components" : { + "red" : "0x1D", + "alpha" : "1.000", + "blue" : "0x27", + "green" : "0x1D" + } + } + } + ] +} \ No newline at end of file diff --git a/Odeon/Assets.xcassets/Modules/Shared/Colours/PrimaryText.colorset/Contents.json b/Odeon/Assets.xcassets/Modules/Shared/Colours/PrimaryText.colorset/Contents.json new file mode 100644 index 0000000..c6e5d3d --- /dev/null +++ b/Odeon/Assets.xcassets/Modules/Shared/Colours/PrimaryText.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + }, + "colors" : [ + { + "idiom" : "universal", + "color" : { + "color-space" : "srgb", + "components" : { + "red" : "1.000", + "alpha" : "1.000", + "blue" : "1.000", + "green" : "1.000" + } + } + } + ] +} \ No newline at end of file diff --git a/Odeon/Assets.xcassets/Modules/Shared/Colours/SecondaryText.colorset/Contents.json b/Odeon/Assets.xcassets/Modules/Shared/Colours/SecondaryText.colorset/Contents.json new file mode 100644 index 0000000..caf3138 --- /dev/null +++ b/Odeon/Assets.xcassets/Modules/Shared/Colours/SecondaryText.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + }, + "colors" : [ + { + "idiom" : "universal", + "color" : { + "color-space" : "srgb", + "components" : { + "red" : "0xDF", + "alpha" : "1.000", + "blue" : "0xDF", + "green" : "0xDF" + } + } + } + ] +} \ No newline at end of file diff --git a/Odeon/Assets.xcassets/Modules/Shared/Contents.json b/Odeon/Assets.xcassets/Modules/Shared/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/Odeon/Assets.xcassets/Modules/Shared/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Odeon/Base.lproj/LaunchScreen.storyboard b/Odeon/Base.lproj/LaunchScreen.storyboard index bfa3612..20eec85 100644 --- a/Odeon/Base.lproj/LaunchScreen.storyboard +++ b/Odeon/Base.lproj/LaunchScreen.storyboard @@ -1,7 +1,11 @@ - - + + + + + - + + @@ -13,13 +17,27 @@ + + + + + + + + + + + - + + + + diff --git a/Odeon/Base.lproj/Main.storyboard b/Odeon/Base.lproj/Main.storyboard index f1bcf38..8fc65b4 100644 --- a/Odeon/Base.lproj/Main.storyboard +++ b/Odeon/Base.lproj/Main.storyboard @@ -1,7 +1,11 @@ - + + + + - + + @@ -9,7 +13,7 @@ - + diff --git a/Odeon/Info.plist b/Odeon/Info.plist index 16be3b6..8e12b75 100644 --- a/Odeon/Info.plist +++ b/Odeon/Info.plist @@ -4,6 +4,8 @@ CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + ODEON CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier @@ -15,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.0 + 1.0.0 CFBundleVersion 1 LSRequiresIPhoneOS @@ -28,18 +30,13 @@ armv7 + UIStatusBarStyle + UIStatusBarStyleLightContent UISupportedInterfaceOrientations UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight + UIViewControllerBasedStatusBarAppearance + diff --git a/Odeon/Modules/Networking/Models/Certificate.swift b/Odeon/Modules/Networking/Models/Certificate.swift new file mode 100644 index 0000000..ad93722 --- /dev/null +++ b/Odeon/Modules/Networking/Models/Certificate.swift @@ -0,0 +1,24 @@ +// +// Certificate.swift +// Odeon +// +// Created by Sherlock, James on 16/12/2018. +// Copyright © 2018 Sherlouk. All rights reserved. +// + +import Foundation + +enum Certificate: String, Codable { + + case toBeConfirmed = "TBC" + case universal = "U" + case parentalGuidance = "PG" + case twelveA = "12A" + case twelve = "12" + case fifteen = "15" + case eighteen = "18" + case unknown + + // TODO: Map to unknown rather than crashing + +} diff --git a/Odeon/Modules/Networking/Models/Cinema.swift b/Odeon/Modules/Networking/Models/Cinema.swift new file mode 100644 index 0000000..ec37675 --- /dev/null +++ b/Odeon/Modules/Networking/Models/Cinema.swift @@ -0,0 +1,47 @@ +// +// Cinema.swift +// Odeon +// +// Created by Sherlock, James on 16/12/2018. +// Copyright © 2018 Sherlouk. All rights reserved. +// + +import Foundation +import CoreLocation + +struct Cinema: Codable { + + enum CodingKeys: String, CodingKey { + case id = "siteId" + case name = "siteName" + case addressLineOne = "siteAddress1" + case addressLineTwo = "siteAddress2" + case addressLineThree = "siteAddress3" + case addressLineFour = "siteAddress4" + case postcode = "sitePostcode" + case telephoneNumber = "siteTelephone" + case longitude = "siteLongitude" + case latitude = "siteLatitude" + case isLuxe = "siteIsLuxe" + } + + let id: String + let name: String + let addressLineOne: String + let addressLineTwo: String + let addressLineThree: String? + let addressLineFour: String? + let postcode: String + let telephoneNumber: String + let longitude: String + let latitude: String + let isLuxe: Bool + + var coordinates: CLLocation? { + guard let latitude = CLLocationDegrees(latitude) else { return nil } + guard let longitude = CLLocationDegrees(longitude) else { return nil } + + return CLLocation(latitude: latitude, longitude: longitude) + } + +} diff --git a/Odeon/Modules/Networking/Models/Film.swift b/Odeon/Modules/Networking/Models/Film.swift new file mode 100644 index 0000000..b535232 --- /dev/null +++ b/Odeon/Modules/Networking/Models/Film.swift @@ -0,0 +1,51 @@ +// +// Film.swift +// Odeon +// +// Created by Sherlock, James on 16/12/2018. +// Copyright © 2018 Sherlouk. All rights reserved. +// + +import Foundation + +struct Film: Codable { + + enum CodingKeys: String, CodingKey { + case id = "filmMasterId" + case title + case rating = "halfRating" + case posterImageUrl = "posterUrl" + case imageUrl + case certificate + case releaseDate + case genre + case trailerUrl + case isRateable + case attributes + case offers + } + + let id: Int + let title: String + let rating: Int + let posterImageUrl: URL + let imageUrl: URL + let certificate: Certificate + let releaseDate: String // TODO: Make this date (20181214) + let genre: String? + let trailerUrl: URL? + let isRateable: Int // TODO: Turn this into bool (0/1) + let attributes: String? + let offers: [Offer] + + func convertAttributes(using response: FilmAttributesResponse) -> [FilmAttributesResponse.Attributes] { + guard let attributes = attributes?.components(separatedBy: ",") else { + return [] + } + + return attributes.compactMap({ attribute -> FilmAttributesResponse.Attributes? in + return response.data.first(where: { $0.id == Int(attribute) }) + }) + } + +} diff --git a/Odeon/Modules/Networking/Models/FilmDetails.swift b/Odeon/Modules/Networking/Models/FilmDetails.swift new file mode 100644 index 0000000..54bc125 --- /dev/null +++ b/Odeon/Modules/Networking/Models/FilmDetails.swift @@ -0,0 +1,22 @@ +// +// FilmDetails.swift +// Odeon +// +// Created by Sherlock, James on 16/12/2018. +// Copyright © 2018 Sherlouk. All rights reserved. +// + +import Foundation + +struct FilmDetails: Codable { + + let plot: String + let customerAdvice: String + let director: String + let casts: String + let runningTime: String + let language: String + let country: String + let sites: [Int] + +} diff --git a/Odeon/Modules/Networking/Models/FilmTimes.swift b/Odeon/Modules/Networking/Models/FilmTimes.swift new file mode 100644 index 0000000..73dd7ec --- /dev/null +++ b/Odeon/Modules/Networking/Models/FilmTimes.swift @@ -0,0 +1,21 @@ +// +// FilmTimes.swift +// Odeon +// +// Created by Sherlock, James on 16/12/2018. +// Copyright © 2018 Sherlouk. All rights reserved. +// + +import Foundation + +struct FilmTimes: Codable { + + struct Day: Codable { + let date: String // TODO: make this date + let performances: [Performance] + } + + let attribute: String + let days: [Day] + +} diff --git a/Odeon/Modules/Networking/Models/Offer.swift b/Odeon/Modules/Networking/Models/Offer.swift new file mode 100644 index 0000000..30fab52 --- /dev/null +++ b/Odeon/Modules/Networking/Models/Offer.swift @@ -0,0 +1,42 @@ +// +// Offer.swift +// Odeon +// +// Created by Sherlock, James on 16/12/2018. +// Copyright © 2018 Sherlouk. All rights reserved. +// + +import Foundation + +struct Offer: Codable { + + struct Images: Codable { + + enum CodingKeys: String, CodingKey { + case thumbnail = "140x140" + case medium = "300x170" + case large = "460x260" + } + + let thumbnail: String + let medium: String + let large: String + + } + + enum OfferType: String, Codable { + case offer + case competition + } + + let id: Int + let title: String + let teaser: String + let text: String + let terms: String + let validFrom: String // TODO: Make this date (2018-12-12 00:30:00) + let validTo: String // TODO: Make this date (2018-12-12 00:30:00) + let type: OfferType + let images: Images + +} diff --git a/Odeon/Modules/Networking/Models/Performance.swift b/Odeon/Modules/Networking/Models/Performance.swift new file mode 100644 index 0000000..35e8c6a --- /dev/null +++ b/Odeon/Modules/Networking/Models/Performance.swift @@ -0,0 +1,25 @@ +// +// Performance.swift +// Odeon +// +// Created by Sherlock, James on 16/12/2018. +// Copyright © 2018 Sherlouk. All rights reserved. +// + +import Foundation + +struct Performance: Codable { + + enum CodingKeys: String, CodingKey { + case id = "performanceId" + case time = "performanceTime" + case attributes + case status + } + + let id: String + let time: String + let attributes: String + let status: String // TODO: make this enum + +} diff --git a/Odeon/Modules/Networking/Responses/DataWrapperGenericResponse.swift b/Odeon/Modules/Networking/Responses/DataWrapperGenericResponse.swift new file mode 100644 index 0000000..9a18a5c --- /dev/null +++ b/Odeon/Modules/Networking/Responses/DataWrapperGenericResponse.swift @@ -0,0 +1,16 @@ +// +// DataWrapperGenericResponse.swift +// Odeon +// +// Created by Sherlock, James on 16/12/2018. +// Copyright © 2018 Sherlouk. All rights reserved. +// + +import Foundation + +struct DataWrapperGenericResponse: Codable { + let data: InnerData +} + +// e.g. DataWrapperGenericResponse.self +// TODO: Replace other responses with this? diff --git a/Odeon/Modules/Networking/Responses/FilmAttributesResponse.swift b/Odeon/Modules/Networking/Responses/FilmAttributesResponse.swift new file mode 100644 index 0000000..0eb0583 --- /dev/null +++ b/Odeon/Modules/Networking/Responses/FilmAttributesResponse.swift @@ -0,0 +1,20 @@ +// +// FilmAttributesResponse.swift +// Odeon +// +// Created by Sherlock, James on 16/12/2018. +// Copyright © 2018 Sherlouk. All rights reserved. +// + +import Foundation + +struct FilmAttributesResponse: Codable { + + struct Attributes: Codable { + let id: Int + let name: String + } + + let data: [Attributes] + +} diff --git a/Odeon/Modules/Networking/Responses/ListCinemasResponse.swift b/Odeon/Modules/Networking/Responses/ListCinemasResponse.swift new file mode 100644 index 0000000..f842553 --- /dev/null +++ b/Odeon/Modules/Networking/Responses/ListCinemasResponse.swift @@ -0,0 +1,23 @@ +// +// ListCinemasResponse.swift +// Odeon +// +// Created by Sherlock, James on 16/12/2018. +// Copyright © 2018 Sherlouk. All rights reserved. +// + +import Foundation + +struct ListCinemasResponse: Codable { + + struct Data: Codable { + let sites: [String: Cinema] + } + + let data: Data + + var cinema: [Cinema] { + return Array(data.sites.values) + } + +} diff --git a/Odeon/Modules/Networking/Responses/ListFilmsResponse.swift b/Odeon/Modules/Networking/Responses/ListFilmsResponse.swift new file mode 100644 index 0000000..2d07b44 --- /dev/null +++ b/Odeon/Modules/Networking/Responses/ListFilmsResponse.swift @@ -0,0 +1,19 @@ +// +// ListFilmsResponse.swift +// Odeon +// +// Created by Sherlock, James on 16/12/2018. +// Copyright © 2018 Sherlouk. All rights reserved. +// + +import Foundation + +struct ListFilmsResponse: Codable { + + struct Data: Codable { + let films: [Film] + } + + let data: Data + +} diff --git a/Odeon/Modules/Networking/Responses/PerformanceAttributesResponse.swift b/Odeon/Modules/Networking/Responses/PerformanceAttributesResponse.swift new file mode 100644 index 0000000..5a7ec8e --- /dev/null +++ b/Odeon/Modules/Networking/Responses/PerformanceAttributesResponse.swift @@ -0,0 +1,20 @@ +// +// PerformanceAttributesResponse.swift +// Odeon +// +// Created by Sherlock, James on 16/12/2018. +// Copyright © 2018 Sherlouk. All rights reserved. +// + +import Foundation + +struct PerformanceAttributesResponse: Codable { + + struct Attributes: Codable { + let id: Int + let name: String + } + + let data: [Attributes] + +} diff --git a/Odeon/Modules/Onboarding/Onboarding.storyboard b/Odeon/Modules/Onboarding/Onboarding.storyboard new file mode 100644 index 0000000..9e73e53 --- /dev/null +++ b/Odeon/Modules/Onboarding/Onboarding.storyboard @@ -0,0 +1,256 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Odeon/Modules/Onboarding/View Controllers/OnboardingViewController.swift b/Odeon/Modules/Onboarding/View Controllers/OnboardingViewController.swift new file mode 100644 index 0000000..6f4969b --- /dev/null +++ b/Odeon/Modules/Onboarding/View Controllers/OnboardingViewController.swift @@ -0,0 +1,30 @@ +// +// OnboardingViewController.swift +// Odeon +// +// Created by Sherlock, James on 16/12/2018. +// Copyright © 2018 Sherlouk. All rights reserved. +// + +import UIKit + +class OnboardingViewController: UIViewController { + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + } + + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ + +} diff --git a/Odeon/Modules/Onboarding/View Controllers/Pages/OnboardingCountryChooserViewController.swift b/Odeon/Modules/Onboarding/View Controllers/Pages/OnboardingCountryChooserViewController.swift new file mode 100644 index 0000000..cb317cb --- /dev/null +++ b/Odeon/Modules/Onboarding/View Controllers/Pages/OnboardingCountryChooserViewController.swift @@ -0,0 +1,30 @@ +// +// OnboardingCountryChooserViewController.swift +// Odeon +// +// Created by Sherlock, James on 16/12/2018. +// Copyright © 2018 Sherlouk. All rights reserved. +// + +import UIKit + +class OnboardingCountryChooserViewController: UIViewController { + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + } + + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ + +} diff --git a/Odeon/Modules/Onboarding/View Controllers/Pages/OnboardingLoadingViewController.swift b/Odeon/Modules/Onboarding/View Controllers/Pages/OnboardingLoadingViewController.swift new file mode 100644 index 0000000..1540d66 --- /dev/null +++ b/Odeon/Modules/Onboarding/View Controllers/Pages/OnboardingLoadingViewController.swift @@ -0,0 +1,30 @@ +// +// OnboardingLoadingViewController.swift +// Odeon +// +// Created by Sherlock, James on 16/12/2018. +// Copyright © 2018 Sherlouk. All rights reserved. +// + +import UIKit + +class OnboardingLoadingViewController: UIViewController { + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + } + + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ + +} diff --git a/Odeon/Modules/Onboarding/View Controllers/Pages/OnboardingLocationServicesViewController.swift b/Odeon/Modules/Onboarding/View Controllers/Pages/OnboardingLocationServicesViewController.swift new file mode 100644 index 0000000..2b47b6a --- /dev/null +++ b/Odeon/Modules/Onboarding/View Controllers/Pages/OnboardingLocationServicesViewController.swift @@ -0,0 +1,30 @@ +// +// OnboardingLocationServicesViewController.swift +// Odeon +// +// Created by Sherlock, James on 16/12/2018. +// Copyright © 2018 Sherlouk. All rights reserved. +// + +import UIKit + +class OnboardingLocationServicesViewController: UIViewController { + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + } + + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ + +} diff --git a/Odeon/Modules/Storage/OdeonStorage.swift b/Odeon/Modules/Storage/OdeonStorage.swift new file mode 100644 index 0000000..86ae687 --- /dev/null +++ b/Odeon/Modules/Storage/OdeonStorage.swift @@ -0,0 +1,30 @@ +// +// OdeonStorage.swift +// Odeon +// +// Created by Sherlock, James on 16/12/2018. +// Copyright © 2018 Sherlouk. All rights reserved. +// + +import Foundation + +class OdeonStorage { + + // MARK: - Variables + + let storage: Storage + + // MARK: - Initialiser + + init(storage: Storage = UserDefaults.standard) { + self.storage = storage + } + + // MARK: - Setters & Getters + + var userChosenCountry: String? { + get { return storage.string(forKey: #function) } + set { storage.set(newValue, forKey: #function) } + } + +} diff --git a/Odeon/Modules/Storage/Storage.swift b/Odeon/Modules/Storage/Storage.swift new file mode 100644 index 0000000..7fc046e --- /dev/null +++ b/Odeon/Modules/Storage/Storage.swift @@ -0,0 +1,22 @@ +// +// Storage.swift +// Odeon +// +// Created by Sherlock, James on 16/12/2018. +// Copyright © 2018 Sherlouk. All rights reserved. +// + +import Foundation + +protocol Storage { + func set(_ value: Any?, forKey defaultName: String) + func set(_ value: Int, forKey defaultName: String) + func set(_ value: Bool, forKey defaultName: String) + + func object(forKey defaultName: String) -> Any? + func string(forKey defaultName: String) -> String? + func integer(forKey defaultName: String) -> Int + func bool(forKey defaultName: String) -> Bool +} + +extension UserDefaults: Storage {} diff --git a/OdeonTests/Modules/Storage/DictionaryStorage.swift b/OdeonTests/Modules/Storage/DictionaryStorage.swift new file mode 100644 index 0000000..d060796 --- /dev/null +++ b/OdeonTests/Modules/Storage/DictionaryStorage.swift @@ -0,0 +1,50 @@ +// +// DictionaryStorage.swift +// OdeonTests +// +// Created by Sherlock, James on 16/12/2018. +// Copyright © 2018 Sherlouk. All rights reserved. +// + +import Foundation +@testable import Odeon + +class DictionaryStorage: Storage { + + var storage: [String: Any] + + init(initialStorage: [String: Any] = [:]) { + self.storage = initialStorage + } + + func set(_ value: Any?, forKey defaultName: String) { + storage[defaultName] = value + } + + func set(_ value: Int, forKey defaultName: String) { + storage[defaultName] = value + } + + func set(_ value: Bool, forKey defaultName: String) { + storage[defaultName] = value + } + + func object(forKey defaultName: String) -> Any? { + return storage[defaultName] + } + + func string(forKey defaultName: String) -> String? { + return storage[defaultName] as? String + } + + func integer(forKey defaultName: String) -> Int { + // UserDefaults will return zero if the value can not be found or formed + return (storage[defaultName] as? Int) ?? 0 + } + + func bool(forKey defaultName: String) -> Bool { + // UserDefaults will return false if the value can not be found or formed + return (storage[defaultName] as? Bool) ?? false + } + +}