diff --git a/.gitignore b/.gitignore index 330d167..ba45fbb 100644 --- a/.gitignore +++ b/.gitignore @@ -54,10 +54,10 @@ playground.xcworkspace # 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/ +Pods/ # # Add this line if you want to avoid checking in source code from the Xcode workspace -# *.xcworkspace +*.xcworkspace # Carthage # diff --git a/Lesson1/.keep b/less6/.keep similarity index 100% rename from Lesson1/.keep rename to less6/.keep diff --git a/less6/Podfile b/less6/Podfile new file mode 100644 index 0000000..6a82862 --- /dev/null +++ b/less6/Podfile @@ -0,0 +1,12 @@ +# Uncomment the next line to define a global platform for your project +# platform :ios, '9.0' + +target 'loginForm' do + # Comment the next line if you don't want to use dynamic frameworks + use_frameworks! + pod 'Alamofire', '~> 4.8' + pod 'RealmSwift' + pod 'SwiftyJSON' + # Pods for loginForm + +end diff --git a/less6/Podfile.lock b/less6/Podfile.lock new file mode 100644 index 0000000..b47b84c --- /dev/null +++ b/less6/Podfile.lock @@ -0,0 +1,30 @@ +PODS: + - Alamofire (4.9.1) + - Realm (4.3.2): + - Realm/Headers (= 4.3.2) + - Realm/Headers (4.3.2) + - RealmSwift (4.3.2): + - Realm (= 4.3.2) + - SwiftyJSON (5.0.0) + +DEPENDENCIES: + - Alamofire (~> 4.8) + - RealmSwift + - SwiftyJSON + +SPEC REPOS: + trunk: + - Alamofire + - Realm + - RealmSwift + - SwiftyJSON + +SPEC CHECKSUMS: + Alamofire: 85e8a02c69d6020a0d734f6054870d7ecb75cf18 + Realm: 5e92902e2875dff4bb0fd02f67bb737c3d5db2bc + RealmSwift: 9a360fc7bae04fc2e308a34fbd899d5faa2d6b22 + SwiftyJSON: 36413e04c44ee145039d332b4f4e2d3e8d6c4db7 + +PODFILE CHECKSUM: 9e4404f69107ecf09e634ce7ce8ed833388709b5 + +COCOAPODS: 1.9.1 diff --git a/less6/loginForm.xcodeproj/project.pbxproj b/less6/loginForm.xcodeproj/project.pbxproj new file mode 100644 index 0000000..b052923 --- /dev/null +++ b/less6/loginForm.xcodeproj/project.pbxproj @@ -0,0 +1,551 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 51; + objects = { + +/* Begin PBXBuildFile section */ + 0740F918240F904500444C42 /* CustomNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0740F917240F904500444C42 /* CustomNavigationController.swift */; }; + 0740F91A240F96DA00444C42 /* CustomPushAnimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0740F919240F96DA00444C42 /* CustomPushAnimator.swift */; }; + 076A9C512410EC6200B3CC72 /* CustomInteractiveTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 076A9C502410EC6200B3CC72 /* CustomInteractiveTransition.swift */; }; + 58B0A5D3BACCE25F85A6E6C8 /* Pods_loginForm.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9371F807C4727D91CD57979A /* Pods_loginForm.framework */; }; + 9C2E833923FFCCB000BD244F /* testTableViewHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C2E833823FFCCB000BD244F /* testTableViewHeader.swift */; }; + 9C2E833B23FFD83300BD244F /* TestTableViewHeader.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9C2E833A23FFD83300BD244F /* TestTableViewHeader.xib */; }; + 9C2E836024007D2F00BD244F /* NewsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C2E835F24007D2F00BD244F /* NewsViewController.swift */; }; + 9C2E836224007E5900BD244F /* NewsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C2E836124007E5900BD244F /* NewsCell.swift */; }; + 9C43514C23F2A79000FBFC58 /* Groups.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C43514B23F2A79000FBFC58 /* Groups.swift */; }; + 9C4AC87323F161CB00BFF5E7 /* LoginFormController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C4AC87223F161CB00BFF5E7 /* LoginFormController.swift */; }; + 9C4AC87723F165E300BFF5E7 /* FriendsTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C4AC87623F165E300BFF5E7 /* FriendsTableViewController.swift */; }; + 9C4AC87923F167FF00BFF5E7 /* SubscriptionTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C4AC87823F167FF00BFF5E7 /* SubscriptionTableViewController.swift */; }; + 9C4AC87D23F168BC00BFF5E7 /* AllGroupsTableController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C4AC87C23F168BC00BFF5E7 /* AllGroupsTableController.swift */; }; + 9C4AC88823F1855000BFF5E7 /* FriendsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C4AC88723F1855000BFF5E7 /* FriendsCell.swift */; }; + 9C4AC88A23F1858000BFF5E7 /* GroupsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C4AC88923F1858000BFF5E7 /* GroupsCell.swift */; }; + 9C4AC88C23F1864B00BFF5E7 /* FriendsCollectionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C4AC88B23F1864B00BFF5E7 /* FriendsCollectionCell.swift */; }; + 9C4AC88F23F1A0ED00BFF5E7 /* friendsStruct.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C4AC88E23F1A0ED00BFF5E7 /* friendsStruct.swift */; }; + 9C4AC89123F1B19B00BFF5E7 /* FriendCollectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C4AC89023F1B19B00BFF5E7 /* FriendCollectionController.swift */; }; + 9C5617092420B46800B791A2 /* Session.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C5617082420B46800B791A2 /* Session.swift */; }; + 9C56170B2420B5E500B791A2 /* VKAthorizationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C56170A2420B5E500B791A2 /* VKAthorizationViewController.swift */; }; + 9C56170D2420CA7800B791A2 /* FriendsRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C56170C2420CA7800B791A2 /* FriendsRequest.swift */; }; + 9C56170F2420D8C700B791A2 /* PhotoRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C56170E2420D8C700B791A2 /* PhotoRequest.swift */; }; + 9C5617112420DB2000B791A2 /* GroupsRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C5617102420DB2000B791A2 /* GroupsRequest.swift */; }; + 9C5617132420DC8300B791A2 /* SearchGroupsRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C5617122420DC8300B791A2 /* SearchGroupsRequest.swift */; }; + 9C5DD2C92409C97D00CADCA8 /* PictureViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C5DD2C82409C97D00CADCA8 /* PictureViewController.swift */; }; + 9C6C403D24052C7600460F66 /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C6C403C24052C7600460F66 /* SettingsViewController.swift */; }; + 9C761E7423E1EBE00090FB56 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C761E7323E1EBE00090FB56 /* AppDelegate.swift */; }; + 9C761E7623E1EBE00090FB56 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C761E7523E1EBE00090FB56 /* SceneDelegate.swift */; }; + 9C761E7B23E1EBE00090FB56 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9C761E7923E1EBE00090FB56 /* Main.storyboard */; }; + 9C761E7D23E1EBE10090FB56 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9C761E7C23E1EBE10090FB56 /* Assets.xcassets */; }; + 9C761E8023E1EBE10090FB56 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9C761E7E23E1EBE10090FB56 /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 0740F917240F904500444C42 /* CustomNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomNavigationController.swift; sourceTree = ""; }; + 0740F919240F96DA00444C42 /* CustomPushAnimator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomPushAnimator.swift; sourceTree = ""; }; + 076A9C502410EC6200B3CC72 /* CustomInteractiveTransition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomInteractiveTransition.swift; sourceTree = ""; }; + 6D654E798549DF491EB1B174 /* Pods-loginForm.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-loginForm.debug.xcconfig"; path = "Target Support Files/Pods-loginForm/Pods-loginForm.debug.xcconfig"; sourceTree = ""; }; + 9371F807C4727D91CD57979A /* Pods_loginForm.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_loginForm.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 9C2E833823FFCCB000BD244F /* testTableViewHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = testTableViewHeader.swift; sourceTree = ""; }; + 9C2E833A23FFD83300BD244F /* TestTableViewHeader.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TestTableViewHeader.xib; sourceTree = ""; }; + 9C2E835F24007D2F00BD244F /* NewsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewsViewController.swift; sourceTree = ""; }; + 9C2E836124007E5900BD244F /* NewsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewsCell.swift; sourceTree = ""; }; + 9C43514B23F2A79000FBFC58 /* Groups.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Groups.swift; sourceTree = ""; }; + 9C4AC87223F161CB00BFF5E7 /* LoginFormController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginFormController.swift; sourceTree = ""; }; + 9C4AC87623F165E300BFF5E7 /* FriendsTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FriendsTableViewController.swift; sourceTree = ""; }; + 9C4AC87823F167FF00BFF5E7 /* SubscriptionTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionTableViewController.swift; sourceTree = ""; }; + 9C4AC87C23F168BC00BFF5E7 /* AllGroupsTableController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AllGroupsTableController.swift; sourceTree = ""; }; + 9C4AC88723F1855000BFF5E7 /* FriendsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FriendsCell.swift; sourceTree = ""; }; + 9C4AC88923F1858000BFF5E7 /* GroupsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupsCell.swift; sourceTree = ""; }; + 9C4AC88B23F1864B00BFF5E7 /* FriendsCollectionCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FriendsCollectionCell.swift; sourceTree = ""; }; + 9C4AC88E23F1A0ED00BFF5E7 /* friendsStruct.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = friendsStruct.swift; sourceTree = ""; }; + 9C4AC89023F1B19B00BFF5E7 /* FriendCollectionController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FriendCollectionController.swift; sourceTree = ""; }; + 9C5617082420B46800B791A2 /* Session.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Session.swift; path = loginForm/Session.swift; sourceTree = SOURCE_ROOT; }; + 9C56170A2420B5E500B791A2 /* VKAthorizationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = VKAthorizationViewController.swift; path = loginForm/VKAthorizationViewController.swift; sourceTree = SOURCE_ROOT; }; + 9C56170C2420CA7800B791A2 /* FriendsRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FriendsRequest.swift; sourceTree = ""; }; + 9C56170E2420D8C700B791A2 /* PhotoRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoRequest.swift; sourceTree = ""; }; + 9C5617102420DB2000B791A2 /* GroupsRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupsRequest.swift; sourceTree = ""; }; + 9C5617122420DC8300B791A2 /* SearchGroupsRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchGroupsRequest.swift; sourceTree = ""; }; + 9C5DD2C82409C97D00CADCA8 /* PictureViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = PictureViewController.swift; path = loginForm/PictureViewController.swift; sourceTree = SOURCE_ROOT; }; + 9C6C403C24052C7600460F66 /* SettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = ""; }; + 9C761E7023E1EBE00090FB56 /* loginForm.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = loginForm.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 9C761E7323E1EBE00090FB56 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 9C761E7523E1EBE00090FB56 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; + 9C761E7A23E1EBE00090FB56 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 9C761E7C23E1EBE10090FB56 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 9C761E7F23E1EBE10090FB56 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 9C761E8123E1EBE10090FB56 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + ADFFE5F533C1DCD2E302E418 /* Pods-loginForm.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-loginForm.release.xcconfig"; path = "Target Support Files/Pods-loginForm/Pods-loginForm.release.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 9C761E6D23E1EBE00090FB56 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 58B0A5D3BACCE25F85A6E6C8 /* Pods_loginForm.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 076A9C522410F55700B3CC72 /* AnimateNavigationController */ = { + isa = PBXGroup; + children = ( + 0740F917240F904500444C42 /* CustomNavigationController.swift */, + 0740F919240F96DA00444C42 /* CustomPushAnimator.swift */, + 076A9C502410EC6200B3CC72 /* CustomInteractiveTransition.swift */, + ); + path = AnimateNavigationController; + sourceTree = ""; + }; + 874FF8A5DE980E3B5C54AFA5 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 9371F807C4727D91CD57979A /* Pods_loginForm.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 991BA3178F65CE1F21590C84 /* Pods */ = { + isa = PBXGroup; + children = ( + 6D654E798549DF491EB1B174 /* Pods-loginForm.debug.xcconfig */, + ADFFE5F533C1DCD2E302E418 /* Pods-loginForm.release.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + 9C43514D23F2C12100FBFC58 /* Model */ = { + isa = PBXGroup; + children = ( + 9C4AC88E23F1A0ED00BFF5E7 /* friendsStruct.swift */, + 9C43514B23F2A79000FBFC58 /* Groups.swift */, + ); + path = Model; + sourceTree = ""; + }; + 9C4AC87E23F1698B00BFF5E7 /* Controllers */ = { + isa = PBXGroup; + children = ( + 9C2E835F24007D2F00BD244F /* NewsViewController.swift */, + 9C5DD2C82409C97D00CADCA8 /* PictureViewController.swift */, + 9C4AC87623F165E300BFF5E7 /* FriendsTableViewController.swift */, + 9C4AC89023F1B19B00BFF5E7 /* FriendCollectionController.swift */, + 9C4AC87823F167FF00BFF5E7 /* SubscriptionTableViewController.swift */, + 9C4AC87C23F168BC00BFF5E7 /* AllGroupsTableController.swift */, + 9C4AC87223F161CB00BFF5E7 /* LoginFormController.swift */, + 9C6C403C24052C7600460F66 /* SettingsViewController.swift */, + ); + path = Controllers; + sourceTree = ""; + }; + 9C4AC88D23F1865800BFF5E7 /* Cell */ = { + isa = PBXGroup; + children = ( + 9C2E836124007E5900BD244F /* NewsCell.swift */, + 9C4AC88723F1855000BFF5E7 /* FriendsCell.swift */, + 9C4AC88923F1858000BFF5E7 /* GroupsCell.swift */, + 9C4AC88B23F1864B00BFF5E7 /* FriendsCollectionCell.swift */, + 9C2E833823FFCCB000BD244F /* testTableViewHeader.swift */, + 9C2E833A23FFD83300BD244F /* TestTableViewHeader.xib */, + ); + path = Cell; + sourceTree = ""; + }; + 9C761E6723E1EBE00090FB56 = { + isa = PBXGroup; + children = ( + 9C761E7223E1EBE00090FB56 /* loginForm */, + 9C761E7123E1EBE00090FB56 /* Products */, + 991BA3178F65CE1F21590C84 /* Pods */, + 874FF8A5DE980E3B5C54AFA5 /* Frameworks */, + ); + sourceTree = ""; + }; + 9C761E7123E1EBE00090FB56 /* Products */ = { + isa = PBXGroup; + children = ( + 9C761E7023E1EBE00090FB56 /* loginForm.app */, + ); + name = Products; + sourceTree = ""; + }; + 9C761E7223E1EBE00090FB56 /* loginForm */ = { + isa = PBXGroup; + children = ( + 9CCE2CD8241C72DB000EF13E /* Services */, + 076A9C522410F55700B3CC72 /* AnimateNavigationController */, + 9C4AC87E23F1698B00BFF5E7 /* Controllers */, + 9C4AC88D23F1865800BFF5E7 /* Cell */, + 9C43514D23F2C12100FBFC58 /* Model */, + 9C761E7923E1EBE00090FB56 /* Main.storyboard */, + 9C761E7C23E1EBE10090FB56 /* Assets.xcassets */, + 9C761E7E23E1EBE10090FB56 /* LaunchScreen.storyboard */, + 9C761E8123E1EBE10090FB56 /* Info.plist */, + 9C761E7323E1EBE00090FB56 /* AppDelegate.swift */, + 9C761E7523E1EBE00090FB56 /* SceneDelegate.swift */, + ); + path = loginForm; + sourceTree = ""; + }; + 9CCE2CD8241C72DB000EF13E /* Services */ = { + isa = PBXGroup; + children = ( + 9C56170A2420B5E500B791A2 /* VKAthorizationViewController.swift */, + 9C56170C2420CA7800B791A2 /* FriendsRequest.swift */, + 9C5617102420DB2000B791A2 /* GroupsRequest.swift */, + 9C5617122420DC8300B791A2 /* SearchGroupsRequest.swift */, + 9C56170E2420D8C700B791A2 /* PhotoRequest.swift */, + 9C5617082420B46800B791A2 /* Session.swift */, + ); + path = Services; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 9C761E6F23E1EBE00090FB56 /* loginForm */ = { + isa = PBXNativeTarget; + buildConfigurationList = 9C761E8423E1EBE10090FB56 /* Build configuration list for PBXNativeTarget "loginForm" */; + buildPhases = ( + 95F9256FE3FFA0D2267FAD3A /* [CP] Check Pods Manifest.lock */, + 9C761E6C23E1EBE00090FB56 /* Sources */, + 9C761E6D23E1EBE00090FB56 /* Frameworks */, + 9C761E6E23E1EBE00090FB56 /* Resources */, + 2194253889E0893C65FEF0CC /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = loginForm; + productName = loginForm; + productReference = 9C761E7023E1EBE00090FB56 /* loginForm.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 9C761E6823E1EBE00090FB56 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1130; + LastUpgradeCheck = 1130; + ORGANIZATIONNAME = prot; + TargetAttributes = { + 9C761E6F23E1EBE00090FB56 = { + CreatedOnToolsVersion = 11.3.1; + }; + }; + }; + buildConfigurationList = 9C761E6B23E1EBE00090FB56 /* Build configuration list for PBXProject "loginForm" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 9C761E6723E1EBE00090FB56; + productRefGroup = 9C761E7123E1EBE00090FB56 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 9C761E6F23E1EBE00090FB56 /* loginForm */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 9C761E6E23E1EBE00090FB56 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9C2E833B23FFD83300BD244F /* TestTableViewHeader.xib in Resources */, + 9C761E8023E1EBE10090FB56 /* LaunchScreen.storyboard in Resources */, + 9C761E7D23E1EBE10090FB56 /* Assets.xcassets in Resources */, + 9C761E7B23E1EBE00090FB56 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 2194253889E0893C65FEF0CC /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-loginForm/Pods-loginForm-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-loginForm/Pods-loginForm-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-loginForm/Pods-loginForm-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 95F9256FE3FFA0D2267FAD3A /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-loginForm-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 9C761E6C23E1EBE00090FB56 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9C2E833923FFCCB000BD244F /* testTableViewHeader.swift in Sources */, + 9C56170B2420B5E500B791A2 /* VKAthorizationViewController.swift in Sources */, + 9C4AC87323F161CB00BFF5E7 /* LoginFormController.swift in Sources */, + 9C4AC88C23F1864B00BFF5E7 /* FriendsCollectionCell.swift in Sources */, + 9C4AC89123F1B19B00BFF5E7 /* FriendCollectionController.swift in Sources */, + 9C2E836224007E5900BD244F /* NewsCell.swift in Sources */, + 9C761E7423E1EBE00090FB56 /* AppDelegate.swift in Sources */, + 9C4AC88A23F1858000BFF5E7 /* GroupsCell.swift in Sources */, + 9C5DD2C92409C97D00CADCA8 /* PictureViewController.swift in Sources */, + 076A9C512410EC6200B3CC72 /* CustomInteractiveTransition.swift in Sources */, + 0740F91A240F96DA00444C42 /* CustomPushAnimator.swift in Sources */, + 9C6C403D24052C7600460F66 /* SettingsViewController.swift in Sources */, + 9C4AC87723F165E300BFF5E7 /* FriendsTableViewController.swift in Sources */, + 9C761E7623E1EBE00090FB56 /* SceneDelegate.swift in Sources */, + 9C4AC87D23F168BC00BFF5E7 /* AllGroupsTableController.swift in Sources */, + 0740F918240F904500444C42 /* CustomNavigationController.swift in Sources */, + 9C56170F2420D8C700B791A2 /* PhotoRequest.swift in Sources */, + 9C5617132420DC8300B791A2 /* SearchGroupsRequest.swift in Sources */, + 9C4AC88F23F1A0ED00BFF5E7 /* friendsStruct.swift in Sources */, + 9C4AC87923F167FF00BFF5E7 /* SubscriptionTableViewController.swift in Sources */, + 9C5617092420B46800B791A2 /* Session.swift in Sources */, + 9C56170D2420CA7800B791A2 /* FriendsRequest.swift in Sources */, + 9C2E836024007D2F00BD244F /* NewsViewController.swift in Sources */, + 9C5617112420DB2000B791A2 /* GroupsRequest.swift in Sources */, + 9C4AC88823F1855000BFF5E7 /* FriendsCell.swift in Sources */, + 9C43514C23F2A79000FBFC58 /* Groups.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 9C761E7923E1EBE00090FB56 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 9C761E7A23E1EBE00090FB56 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 9C761E7E23E1EBE10090FB56 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 9C761E7F23E1EBE10090FB56 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 9C761E8223E1EBE10090FB56 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.2; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 9C761E8323E1EBE10090FB56 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.2; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 9C761E8523E1EBE10090FB56 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 6D654E798549DF491EB1B174 /* Pods-loginForm.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = X2648CBJ7V; + INFOPLIST_FILE = loginForm/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 13.1; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = prot.loginForm; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 9C761E8623E1EBE10090FB56 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = ADFFE5F533C1DCD2E302E418 /* Pods-loginForm.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = X2648CBJ7V; + INFOPLIST_FILE = loginForm/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 13.1; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = prot.loginForm; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 9C761E6B23E1EBE00090FB56 /* Build configuration list for PBXProject "loginForm" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9C761E8223E1EBE10090FB56 /* Debug */, + 9C761E8323E1EBE10090FB56 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 9C761E8423E1EBE10090FB56 /* Build configuration list for PBXNativeTarget "loginForm" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9C761E8523E1EBE10090FB56 /* Debug */, + 9C761E8623E1EBE10090FB56 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 9C761E6823E1EBE00090FB56 /* Project object */; +} diff --git a/less6/loginForm/AnimateNavigationController/CustomInteractiveTransition.swift b/less6/loginForm/AnimateNavigationController/CustomInteractiveTransition.swift new file mode 100644 index 0000000..d781158 --- /dev/null +++ b/less6/loginForm/AnimateNavigationController/CustomInteractiveTransition.swift @@ -0,0 +1,55 @@ +// +// CustomInteractiveTransition.swift +// loginForm +// +// Created by OSTO macOS on 05.03.2020. +// Copyright © 2020 prot. All rights reserved. +// + +import UIKit + +class CustomInteractiveTransition: UIPercentDrivenInteractiveTransition { + var viewController: UIViewController? { + didSet { + let recongizer = UIScreenEdgePanGestureRecognizer(target: self, action: #selector(handleScreenEdgeGesture(_:)) ) + recongizer.edges = [.left] + viewController?.view.addGestureRecognizer(recongizer) + } + } + + var hasStarted: Bool = false + var shouldFinish: Bool = false + + @objc func handleScreenEdgeGesture(_ gesture: UIScreenEdgePanGestureRecognizer) { + switch gesture.state { + case .began: + hasStarted = true + viewController?.navigationController?.popViewController(animated: true) + + case .changed: + let translation = gesture.translation(in: gesture.view) + let relativeTransition = translation.y / (gesture.view?.bounds.width ?? 1) + let progress = max(0, min(1, relativeTransition)) + shouldFinish = progress > 0.33 + update(progress) + + case .ended: + hasStarted = false + if shouldFinish { + finish() + } + else { + cancel() + } + + case .cancelled: + hasStarted = false + cancel() + + default: + return + } + + } +} + diff --git a/less6/loginForm/AnimateNavigationController/CustomNavigationController.swift b/less6/loginForm/AnimateNavigationController/CustomNavigationController.swift new file mode 100644 index 0000000..7fc41b8 --- /dev/null +++ b/less6/loginForm/AnimateNavigationController/CustomNavigationController.swift @@ -0,0 +1,43 @@ +// +// CustomNavigationController.swift +// loginForm +// +// Created by OSTO macOS on 04.03.2020. +// Copyright © 2020 prot. All rights reserved. +// + +import UIKit + +class CustomNavigationController: UINavigationController, UINavigationControllerDelegate { + + let interactiveTransition = CustomInteractiveTransition() + + override func viewDidLoad() { + super.viewDidLoad() + + delegate = self + } + + + func navigationController(_ navigationController: UINavigationController, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? { + return interactiveTransition.hasStarted ? interactiveTransition: nil + } + + func navigationController(_ navigationController: UINavigationController, + animationControllerFor operation: UINavigationController.Operation, + from fromVC: UIViewController, + to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? { + + if operation == .pop { + if navigationController.viewControllers.first != toVC { + interactiveTransition.viewController = toVC + } + return CustomPopAnimator() + }else if operation == .push { + interactiveTransition.viewController = toVC + return CustomPushAnimator() + } + return nil + + } +} diff --git a/less6/loginForm/AnimateNavigationController/CustomPushAnimator.swift b/less6/loginForm/AnimateNavigationController/CustomPushAnimator.swift new file mode 100644 index 0000000..d1cc96e --- /dev/null +++ b/less6/loginForm/AnimateNavigationController/CustomPushAnimator.swift @@ -0,0 +1,95 @@ +// +// CustomPushAnimator.swift +// loginForm +// +// Created by OSTO macOS on 04.03.2020. +// Copyright © 2020 prot. All rights reserved. +// + +import UIKit + +class CustomPushAnimator: NSObject, UIViewControllerAnimatedTransitioning { + func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { + return 0.6 + } + + func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { + guard let source = transitionContext.viewController(forKey: .from), + let destination = transitionContext.viewController(forKey: .to) else { return } + destination.view.frame = source.view.frame + transitionContext.containerView.addSubview(destination.view) + + destination.view.transform = CGAffineTransform(rotationAngle: -(.pi / 2)) + destination.view.layer.anchorPoint = CGPoint(x: 1, y: 0) + destination.view.layer.position = CGPoint(x: 414, y: 0) + + UIView.animateKeyframes(withDuration: self.transitionDuration(using: transitionContext), + delay: 0, + options: .calculationModePaced, + animations: { + UIView.addKeyframe(withRelativeStartTime: 0, + relativeDuration: 0.4, + animations: { + source.view.alpha = 0.7 + }) + + UIView.addKeyframe(withRelativeStartTime: 0.4, + relativeDuration: 0.4, + animations: { + destination.view.transform = .identity + }) + + }) { finished in + if finished && !transitionContext.transitionWasCancelled { + source.view.transform = .identity + } + + transitionContext.completeTransition(finished && !transitionContext.transitionWasCancelled) + } + } +} + + + + +class CustomPopAnimator : NSObject, UIViewControllerAnimatedTransitioning { + func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { + return 0.6 + } + + func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { + guard let source = transitionContext.viewController(forKey: .from), + let destination = transitionContext.viewController(forKey: .to) else { return } + + transitionContext.containerView.addSubview(destination.view) + transitionContext.containerView.sendSubviewToBack(destination.view) + + destination.view.frame = source.view.frame + + UIView.animateKeyframes(withDuration: self.transitionDuration(using: transitionContext), + delay: 0, + options: .calculationModePaced, + animations: { + + UIView.addKeyframe(withRelativeStartTime: 0, + relativeDuration: 0.4, + animations: { + source.view.transform = CGAffineTransform(rotationAngle: -(.pi / 2)) + destination.view.alpha = 1 + }) + UIView.addKeyframe(withRelativeStartTime: 0.4, + relativeDuration: 0.4, + animations: { + destination.view.transform = .identity + }) + + }) { finished in + if finished && !transitionContext.transitionWasCancelled { + source.removeFromParent() + } else if transitionContext.transitionWasCancelled { + destination.view.transform = .identity + } + transitionContext.completeTransition(finished && !transitionContext.transitionWasCancelled) + } + } +} diff --git a/less6/loginForm/AppDelegate.swift b/less6/loginForm/AppDelegate.swift new file mode 100644 index 0000000..3528e17 --- /dev/null +++ b/less6/loginForm/AppDelegate.swift @@ -0,0 +1,37 @@ +// +// AppDelegate.swift +// loginForm +// +// Created by prot on 30/01/2020. +// Copyright © 2020 prot. All rights reserved. +// + +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. + return true + } + + // MARK: UISceneSession Lifecycle + + func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { + // Called when a new scene session is being created. + // Use this method to select a configuration to create the new scene with. + return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) + } + + func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { + // Called when the user discards a scene session. + // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. + // Use this method to release any resources that were specific to the discarded scenes, as they will not return. + } + + +} + diff --git a/less6/loginForm/Assets.xcassets/AppIcon.appiconset/Contents.json b/less6/loginForm/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..d8db8d6 --- /dev/null +++ b/less6/loginForm/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/less6/loginForm/Assets.xcassets/Contents.json b/less6/loginForm/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/less6/loginForm/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/less6/loginForm/Assets.xcassets/Friends/1111.imageset/1111.jpg b/less6/loginForm/Assets.xcassets/Friends/1111.imageset/1111.jpg new file mode 100644 index 0000000..2065c1b Binary files /dev/null and b/less6/loginForm/Assets.xcassets/Friends/1111.imageset/1111.jpg differ diff --git a/less6/loginForm/Assets.xcassets/Friends/1111.imageset/Contents.json b/less6/loginForm/Assets.xcassets/Friends/1111.imageset/Contents.json new file mode 100644 index 0000000..43bd984 --- /dev/null +++ b/less6/loginForm/Assets.xcassets/Friends/1111.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "1111.jpg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/less6/loginForm/Assets.xcassets/Friends/Ben.imageset/Ben.jpg b/less6/loginForm/Assets.xcassets/Friends/Ben.imageset/Ben.jpg new file mode 100644 index 0000000..c604339 Binary files /dev/null and b/less6/loginForm/Assets.xcassets/Friends/Ben.imageset/Ben.jpg differ diff --git a/less6/loginForm/Assets.xcassets/Friends/Ben.imageset/Contents.json b/less6/loginForm/Assets.xcassets/Friends/Ben.imageset/Contents.json new file mode 100644 index 0000000..4e4ba40 --- /dev/null +++ b/less6/loginForm/Assets.xcassets/Friends/Ben.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "Ben.jpg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/less6/loginForm/Assets.xcassets/Friends/Cat.imageset/Cat.jpg b/less6/loginForm/Assets.xcassets/Friends/Cat.imageset/Cat.jpg new file mode 100644 index 0000000..ea8f406 Binary files /dev/null and b/less6/loginForm/Assets.xcassets/Friends/Cat.imageset/Cat.jpg differ diff --git a/less6/loginForm/Assets.xcassets/Friends/Cat.imageset/Contents.json b/less6/loginForm/Assets.xcassets/Friends/Cat.imageset/Contents.json new file mode 100644 index 0000000..3c64410 --- /dev/null +++ b/less6/loginForm/Assets.xcassets/Friends/Cat.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "Cat.jpg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/less6/loginForm/Assets.xcassets/Friends/Contents.json b/less6/loginForm/Assets.xcassets/Friends/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/less6/loginForm/Assets.xcassets/Friends/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/less6/loginForm/Assets.xcassets/Friends/Jessica.imageset/Contents.json b/less6/loginForm/Assets.xcassets/Friends/Jessica.imageset/Contents.json new file mode 100644 index 0000000..862740c --- /dev/null +++ b/less6/loginForm/Assets.xcassets/Friends/Jessica.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "Jessica.jpeg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/less6/loginForm/Assets.xcassets/Friends/Jessica.imageset/Jessica.jpeg b/less6/loginForm/Assets.xcassets/Friends/Jessica.imageset/Jessica.jpeg new file mode 100644 index 0000000..d11bad6 Binary files /dev/null and b/less6/loginForm/Assets.xcassets/Friends/Jessica.imageset/Jessica.jpeg differ diff --git a/less6/loginForm/Assets.xcassets/Friends/Jony.imageset/Contents.json b/less6/loginForm/Assets.xcassets/Friends/Jony.imageset/Contents.json new file mode 100644 index 0000000..69ade85 --- /dev/null +++ b/less6/loginForm/Assets.xcassets/Friends/Jony.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "Jony.jpg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/less6/loginForm/Assets.xcassets/Friends/Jony.imageset/Jony.jpg b/less6/loginForm/Assets.xcassets/Friends/Jony.imageset/Jony.jpg new file mode 100644 index 0000000..64a2546 Binary files /dev/null and b/less6/loginForm/Assets.xcassets/Friends/Jony.imageset/Jony.jpg differ diff --git a/less6/loginForm/Assets.xcassets/Friends/duck.imageset/Contents.json b/less6/loginForm/Assets.xcassets/Friends/duck.imageset/Contents.json new file mode 100644 index 0000000..61df0bd --- /dev/null +++ b/less6/loginForm/Assets.xcassets/Friends/duck.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "duck.jpg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/less6/loginForm/Assets.xcassets/Friends/duck.imageset/duck.jpg b/less6/loginForm/Assets.xcassets/Friends/duck.imageset/duck.jpg new file mode 100644 index 0000000..808e319 Binary files /dev/null and b/less6/loginForm/Assets.xcassets/Friends/duck.imageset/duck.jpg differ diff --git a/less6/loginForm/Assets.xcassets/Friends/man.imageset/Contents.json b/less6/loginForm/Assets.xcassets/Friends/man.imageset/Contents.json new file mode 100644 index 0000000..a0a50ef --- /dev/null +++ b/less6/loginForm/Assets.xcassets/Friends/man.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "man.jpg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/less6/loginForm/Assets.xcassets/Friends/man.imageset/man.jpg b/less6/loginForm/Assets.xcassets/Friends/man.imageset/man.jpg new file mode 100644 index 0000000..178ba49 Binary files /dev/null and b/less6/loginForm/Assets.xcassets/Friends/man.imageset/man.jpg differ diff --git a/less6/loginForm/Assets.xcassets/Friends/reneg.imageset/Contents.json b/less6/loginForm/Assets.xcassets/Friends/reneg.imageset/Contents.json new file mode 100644 index 0000000..be352ab --- /dev/null +++ b/less6/loginForm/Assets.xcassets/Friends/reneg.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "reneg.jpg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/less6/loginForm/Assets.xcassets/Friends/reneg.imageset/reneg.jpg b/less6/loginForm/Assets.xcassets/Friends/reneg.imageset/reneg.jpg new file mode 100644 index 0000000..3a90a1b Binary files /dev/null and b/less6/loginForm/Assets.xcassets/Friends/reneg.imageset/reneg.jpg differ diff --git a/less6/loginForm/Assets.xcassets/Friends/timon.imageset/Contents.json b/less6/loginForm/Assets.xcassets/Friends/timon.imageset/Contents.json new file mode 100644 index 0000000..fa96e70 --- /dev/null +++ b/less6/loginForm/Assets.xcassets/Friends/timon.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "timon.jpg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/less6/loginForm/Assets.xcassets/Friends/timon.imageset/timon.jpg b/less6/loginForm/Assets.xcassets/Friends/timon.imageset/timon.jpg new file mode 100644 index 0000000..d4188ca Binary files /dev/null and b/less6/loginForm/Assets.xcassets/Friends/timon.imageset/timon.jpg differ diff --git a/less6/loginForm/Assets.xcassets/Friends/wolf.imageset/Contents.json b/less6/loginForm/Assets.xcassets/Friends/wolf.imageset/Contents.json new file mode 100644 index 0000000..9a3d83d --- /dev/null +++ b/less6/loginForm/Assets.xcassets/Friends/wolf.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "wolf.jpg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/less6/loginForm/Assets.xcassets/Friends/wolf.imageset/wolf.jpg b/less6/loginForm/Assets.xcassets/Friends/wolf.imageset/wolf.jpg new file mode 100644 index 0000000..a2eb652 Binary files /dev/null and b/less6/loginForm/Assets.xcassets/Friends/wolf.imageset/wolf.jpg differ diff --git "a/less6/loginForm/Assets.xcassets/Friends/\320\223\320\273\320\260\320\267\320\2601.imageset/Contents.json" "b/less6/loginForm/Assets.xcassets/Friends/\320\223\320\273\320\260\320\267\320\2601.imageset/Contents.json" new file mode 100644 index 0000000..30703b0 --- /dev/null +++ "b/less6/loginForm/Assets.xcassets/Friends/\320\223\320\273\320\260\320\267\320\2601.imageset/Contents.json" @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "Глаза1.jpg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git "a/less6/loginForm/Assets.xcassets/Friends/\320\223\320\273\320\260\320\267\320\2601.imageset/\320\223\320\273\320\260\320\267\320\2601.jpg" "b/less6/loginForm/Assets.xcassets/Friends/\320\223\320\273\320\260\320\267\320\2601.imageset/\320\223\320\273\320\260\320\267\320\2601.jpg" new file mode 100644 index 0000000..c19ac09 Binary files /dev/null and "b/less6/loginForm/Assets.xcassets/Friends/\320\223\320\273\320\260\320\267\320\2601.imageset/\320\223\320\273\320\260\320\267\320\2601.jpg" differ diff --git a/less6/loginForm/Assets.xcassets/Groups/Contents.json b/less6/loginForm/Assets.xcassets/Groups/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/less6/loginForm/Assets.xcassets/Groups/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/less6/loginForm/Assets.xcassets/Groups/party.imageset/Contents.json b/less6/loginForm/Assets.xcassets/Groups/party.imageset/Contents.json new file mode 100644 index 0000000..0a8fb08 --- /dev/null +++ b/less6/loginForm/Assets.xcassets/Groups/party.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "party.jpg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/less6/loginForm/Assets.xcassets/Groups/party.imageset/party.jpg b/less6/loginForm/Assets.xcassets/Groups/party.imageset/party.jpg new file mode 100644 index 0000000..493f240 Binary files /dev/null and b/less6/loginForm/Assets.xcassets/Groups/party.imageset/party.jpg differ diff --git "a/less6/loginForm/Assets.xcassets/Groups/\320\263\320\265\320\277\320\260\321\200\320\264.imageset/Contents.json" "b/less6/loginForm/Assets.xcassets/Groups/\320\263\320\265\320\277\320\260\321\200\320\264.imageset/Contents.json" new file mode 100644 index 0000000..36f933f --- /dev/null +++ "b/less6/loginForm/Assets.xcassets/Groups/\320\263\320\265\320\277\320\260\321\200\320\264.imageset/Contents.json" @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "гепард.jpeg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git "a/less6/loginForm/Assets.xcassets/Groups/\320\263\320\265\320\277\320\260\321\200\320\264.imageset/\320\263\320\265\320\277\320\260\321\200\320\264.jpeg" "b/less6/loginForm/Assets.xcassets/Groups/\320\263\320\265\320\277\320\260\321\200\320\264.imageset/\320\263\320\265\320\277\320\260\321\200\320\264.jpeg" new file mode 100644 index 0000000..2e600f5 Binary files /dev/null and "b/less6/loginForm/Assets.xcassets/Groups/\320\263\320\265\320\277\320\260\321\200\320\264.imageset/\320\263\320\265\320\277\320\260\321\200\320\264.jpeg" differ diff --git "a/less6/loginForm/Assets.xcassets/Groups/\320\274\320\276\321\211\321\214.imageset/Contents.json" "b/less6/loginForm/Assets.xcassets/Groups/\320\274\320\276\321\211\321\214.imageset/Contents.json" new file mode 100644 index 0000000..57cc4e0 --- /dev/null +++ "b/less6/loginForm/Assets.xcassets/Groups/\320\274\320\276\321\211\321\214.imageset/Contents.json" @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "мощь.jpg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git "a/less6/loginForm/Assets.xcassets/Groups/\320\274\320\276\321\211\321\214.imageset/\320\274\320\276\321\211\321\214.jpg" "b/less6/loginForm/Assets.xcassets/Groups/\320\274\320\276\321\211\321\214.imageset/\320\274\320\276\321\211\321\214.jpg" new file mode 100644 index 0000000..f0dc418 Binary files /dev/null and "b/less6/loginForm/Assets.xcassets/Groups/\320\274\320\276\321\211\321\214.imageset/\320\274\320\276\321\211\321\214.jpg" differ diff --git "a/less6/loginForm/Assets.xcassets/Groups/\320\274\321\213\321\210\321\214.imageset/Contents.json" "b/less6/loginForm/Assets.xcassets/Groups/\320\274\321\213\321\210\321\214.imageset/Contents.json" new file mode 100644 index 0000000..0a552f3 --- /dev/null +++ "b/less6/loginForm/Assets.xcassets/Groups/\320\274\321\213\321\210\321\214.imageset/Contents.json" @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "мышь.jpg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git "a/less6/loginForm/Assets.xcassets/Groups/\320\274\321\213\321\210\321\214.imageset/\320\274\321\213\321\210\321\214.jpg" "b/less6/loginForm/Assets.xcassets/Groups/\320\274\321\213\321\210\321\214.imageset/\320\274\321\213\321\210\321\214.jpg" new file mode 100644 index 0000000..4e0f80b Binary files /dev/null and "b/less6/loginForm/Assets.xcassets/Groups/\320\274\321\213\321\210\321\214.imageset/\320\274\321\213\321\210\321\214.jpg" differ diff --git "a/less6/loginForm/Assets.xcassets/Groups/\321\201\320\277\321\200\320\260\320\262.imageset/Contents.json" "b/less6/loginForm/Assets.xcassets/Groups/\321\201\320\277\321\200\320\260\320\262.imageset/Contents.json" new file mode 100644 index 0000000..74a0851 --- /dev/null +++ "b/less6/loginForm/Assets.xcassets/Groups/\321\201\320\277\321\200\320\260\320\262.imageset/Contents.json" @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "справ.jpg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git "a/less6/loginForm/Assets.xcassets/Groups/\321\201\320\277\321\200\320\260\320\262.imageset/\321\201\320\277\321\200\320\260\320\262.jpg" "b/less6/loginForm/Assets.xcassets/Groups/\321\201\320\277\321\200\320\260\320\262.imageset/\321\201\320\277\321\200\320\260\320\262.jpg" new file mode 100644 index 0000000..126a81e Binary files /dev/null and "b/less6/loginForm/Assets.xcassets/Groups/\321\201\320\277\321\200\320\260\320\262.imageset/\321\201\320\277\321\200\320\260\320\262.jpg" differ diff --git "a/less6/loginForm/Assets.xcassets/Groups/\321\202\321\200\320\260\320\275\321\210\320\265\321\217.imageset/Contents.json" "b/less6/loginForm/Assets.xcassets/Groups/\321\202\321\200\320\260\320\275\321\210\320\265\321\217.imageset/Contents.json" new file mode 100644 index 0000000..92d45c8 --- /dev/null +++ "b/less6/loginForm/Assets.xcassets/Groups/\321\202\321\200\320\260\320\275\321\210\320\265\321\217.imageset/Contents.json" @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "траншея.jpg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git "a/less6/loginForm/Assets.xcassets/Groups/\321\202\321\200\320\260\320\275\321\210\320\265\321\217.imageset/\321\202\321\200\320\260\320\275\321\210\320\265\321\217.jpg" "b/less6/loginForm/Assets.xcassets/Groups/\321\202\321\200\320\260\320\275\321\210\320\265\321\217.imageset/\321\202\321\200\320\260\320\275\321\210\320\265\321\217.jpg" new file mode 100644 index 0000000..fe538f7 Binary files /dev/null and "b/less6/loginForm/Assets.xcassets/Groups/\321\202\321\200\320\260\320\275\321\210\320\265\321\217.imageset/\321\202\321\200\320\260\320\275\321\210\320\265\321\217.jpg" differ diff --git a/less6/loginForm/Assets.xcassets/space.imageset/Contents.json b/less6/loginForm/Assets.xcassets/space.imageset/Contents.json new file mode 100644 index 0000000..d0d6c72 --- /dev/null +++ b/less6/loginForm/Assets.xcassets/space.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "space.jpg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/less6/loginForm/Assets.xcassets/space.imageset/space.jpg b/less6/loginForm/Assets.xcassets/space.imageset/space.jpg new file mode 100644 index 0000000..8366f86 Binary files /dev/null and b/less6/loginForm/Assets.xcassets/space.imageset/space.jpg differ diff --git a/less6/loginForm/Base.lproj/LaunchScreen.storyboard b/less6/loginForm/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..865e932 --- /dev/null +++ b/less6/loginForm/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/less6/loginForm/Base.lproj/Main.storyboard b/less6/loginForm/Base.lproj/Main.storyboard new file mode 100644 index 0000000..464f174 --- /dev/null +++ b/less6/loginForm/Base.lproj/Main.storyboard @@ -0,0 +1,917 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/less6/loginForm/Cell/FriendsCell.swift b/less6/loginForm/Cell/FriendsCell.swift new file mode 100644 index 0000000..b9d58f6 --- /dev/null +++ b/less6/loginForm/Cell/FriendsCell.swift @@ -0,0 +1,90 @@ +// +// FriendsCell.swift +// loginForm +// +// Created by prot on 10/02/2020. +// Copyright © 2020 prot. All rights reserved. +// + +import UIKit + +class FriendsCell: UITableViewCell { + + @IBOutlet weak var shadowView:ShadowView! + @IBOutlet weak var nameLabel: UILabel! + @IBOutlet weak var imageFriendView: UIImageView! + + override func layoutSublayers(of layer: CALayer) { + imageFriendView.layer.cornerRadius = 35 + shadowView.backgroundColor = .white + shadowView.animation() + + + let tapGesture = UITapGestureRecognizer(target: self, action: #selector(onTap(_:))) + imageFriendView.isUserInteractionEnabled = true + imageFriendView.addGestureRecognizer(tapGesture) + + } + + @objc func onTap(_ sender: UITapGestureRecognizer){ + print("Сжимаем картинку") + + + UIView.animate(withDuration: 2, + delay: 0, + usingSpringWithDamping: 0.8, + initialSpringVelocity: 10, + animations: { + self.shadowView.transform = .init (scaleX: 0.85, y: 0.85) + self.shadowView.layer.shadowOpacity = 0 + self.shadowView.layer.shadowRadius = 0 + + }) + UIView.animate(withDuration: 0.7, + delay: 1, + usingSpringWithDamping: 0.2, + initialSpringVelocity: 10, + animations: { + self.shadowView.transform = .init(scaleX: 1.2, y: 1.2) + self.shadowView.layer.shadowOpacity = 1 + self.shadowView.layer.shadowRadius = 10 + + }) + + UIView.animate(withDuration: 0.7, + delay: 2, + animations: { + self.shadowView.transform = .init (scaleX: 1, y: 1) + self.shadowView.layer.shadowOpacity = 1 + self.shadowView.layer.shadowRadius = 6 + }) + } + + override func prepareForReuse() { + super.prepareForReuse() + nameLabel.text = nil + imageFriendView.image = nil + + } + +} + +@IBDesignable class ShadowView: UIView{ + + @IBInspectable var color:UIColor = .black + @IBInspectable var opacity:Float = 1 + @IBInspectable var radius:CGFloat = 7 + + func animation() { + layer.cornerRadius = 34 + layer.shadowColor = color.cgColor + layer.shadowOpacity = opacity + layer.shadowOffset = CGSize(width: 4, height: 4) + layer.shadowRadius = radius + backgroundColor = .white + + } + +} + + diff --git a/less6/loginForm/Cell/FriendsCollectionCell.swift b/less6/loginForm/Cell/FriendsCollectionCell.swift new file mode 100644 index 0000000..186d4df --- /dev/null +++ b/less6/loginForm/Cell/FriendsCollectionCell.swift @@ -0,0 +1,105 @@ +// +// FriendsCollectionCell.swift +// loginForm +// +// Created by prot on 10/02/2020. +// Copyright © 2020 prot. All rights reserved. +// + +import UIKit + +class FriendsCollectionCell: UICollectionViewCell { + + + @IBOutlet var friendImageView: UIImageView! + @IBOutlet var likeImage: UIImageView! + @IBOutlet var countLikeLabel: UILabel! + + var count = 0 + + override func layoutSublayers(of layer: CALayer) { + + let tapGesture = UITapGestureRecognizer(target: self, action: #selector(onTap(_:))) + + + + likeImage.isUserInteractionEnabled = true + likeImage.addGestureRecognizer(tapGesture) + + } + + @objc func onTap(_ sender: UITapGestureRecognizer){ + let like = likeImage + if count == 0 { + count+=1 + countLikeLabel.text = "\(count)" + print("Like") + //пружинка + UIView.animate(withDuration: 0.5, + delay: 0, + usingSpringWithDamping: 0.2, + initialSpringVelocity: 15, + animations: { + self.likeImage.transform = .init(scaleX: 0.8, y: 0.8) + }) + //возврат размера + UIView.animate(withDuration: 0.5, + delay: 0, + animations: { + self.likeImage.transform = .init(scaleX: 1, y: 1) + }) + //смена цвета + UIView.transition(with: likeImage, duration: 0.1, options: .transitionCrossDissolve, animations: { + self.likeImage.image = UIImage(systemName: "heart.fill") + like?.tintColor = .red + }) + //смена цвета лейбла + UIView.transition(with: countLikeLabel, duration: 0.1, options: .transitionCrossDissolve, animations: { + self.countLikeLabel.textColor = .red + }) + + + }else { + count = 0 + countLikeLabel.text = "\(count)" + print("- Like") + // + UIView.animate(withDuration: 0.5, + delay: 0, + usingSpringWithDamping: 0.2, + initialSpringVelocity: 15, + animations: { + self.likeImage.transform = .init(scaleX: 0.8, y: 0.8) + }) + // + UIView.animate(withDuration: 0.5, + delay: 0, + animations: { + self.likeImage.transform = .init(scaleX: 1, y: 1) + }) + // + UIView.transition(with: likeImage, duration: 0.1, options: .transitionCrossDissolve, animations: { + self.likeImage.image = UIImage(systemName: "heart") + like?.tintColor = .blue + }) + UIView.transition(with: countLikeLabel, duration: 0.1, options: .transitionCrossDissolve, animations: { + self.countLikeLabel.textColor = .black + }) + + } + } + + + + + // Стартовые значения аутлетов при переиспользовании ячейки + override func prepareForReuse() { + super.prepareForReuse() + + friendImageView.image = nil + likeImage.image = nil + countLikeLabel.text = nil + + } + +} diff --git a/less6/loginForm/Cell/GroupsCell.swift b/less6/loginForm/Cell/GroupsCell.swift new file mode 100644 index 0000000..d4075c4 --- /dev/null +++ b/less6/loginForm/Cell/GroupsCell.swift @@ -0,0 +1,54 @@ +// +// GroupsCell.swift +// loginForm +// +// Created by prot on 10/02/2020. +// Copyright © 2020 prot. All rights reserved. +// + +import UIKit + +class GroupsCell: UITableViewCell { + + @IBOutlet weak var groupNameLabel: UILabel! + @IBOutlet weak var groupImageView: UIImageView! + + override func layoutSubviews() { + groupImageView.layer.cornerRadius = 42 + + let tapGesture = UITapGestureRecognizer(target: self, action: #selector(onTap(_:))) + groupImageView.isUserInteractionEnabled = true + groupImageView.addGestureRecognizer(tapGesture) + + } + + override func prepareForReuse() { + super.prepareForReuse() + + groupNameLabel.text = nil + groupImageView.image = nil + + } + + @objc func onTap(_ sender: UITapGestureRecognizer){ + print("Сжимаем картинку") + + UIView.animate(withDuration: 1, + delay: 0, + usingSpringWithDamping: 0.8, + initialSpringVelocity: 10, + animations: { + self.groupImageView.transform = .init(scaleX: 0.9, y: 0.9) + }) + + UIView.animate(withDuration: 1, + delay: 0, + animations: { + self.groupImageView.transform = .init(scaleX: 1, y: 1) + }) + } + + + + +} diff --git a/less6/loginForm/Cell/NewsCell.swift b/less6/loginForm/Cell/NewsCell.swift new file mode 100644 index 0000000..9bf57e2 --- /dev/null +++ b/less6/loginForm/Cell/NewsCell.swift @@ -0,0 +1,15 @@ +// +// NewsCell.swift +// loginForm +// +// Created by prot on 22/02/2020. +// Copyright © 2020 prot. All rights reserved. +// + +import UIKit + +class NewsCell: UITableViewCell { + + + +} diff --git a/less6/loginForm/Cell/NewsCellTableViewCell.swift b/less6/loginForm/Cell/NewsCellTableViewCell.swift new file mode 100644 index 0000000..82d8110 --- /dev/null +++ b/less6/loginForm/Cell/NewsCellTableViewCell.swift @@ -0,0 +1,15 @@ +// +// NewsCellTableViewCell.swift +// loginForm +// +// Created by prot on 22/02/2020. +// Copyright © 2020 prot. All rights reserved. +// + +import UIKit + +class NewsCellTableViewCell: UITableViewCell { + + @IBOutlet weak var imageViewNews:UIImageView! + +} diff --git a/less6/loginForm/Cell/TestTableViewHeader.xib b/less6/loginForm/Cell/TestTableViewHeader.xib new file mode 100644 index 0000000..c14e9a9 --- /dev/null +++ b/less6/loginForm/Cell/TestTableViewHeader.xib @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/less6/loginForm/Cell/testTableViewHeader.swift b/less6/loginForm/Cell/testTableViewHeader.swift new file mode 100644 index 0000000..f2199ac --- /dev/null +++ b/less6/loginForm/Cell/testTableViewHeader.swift @@ -0,0 +1,17 @@ +// +// testTableViewHeader.swift +// loginForm +// +// Created by prot on 21/02/2020. +// Copyright © 2020 prot. All rights reserved. +// + +import UIKit + + + +class TestTableViewHeader: UITableViewHeaderFooterView { + @IBOutlet weak var someLabel : UILabel! + + +} diff --git a/less6/loginForm/Controllers/AboutFriendsCollectionController.swift b/less6/loginForm/Controllers/AboutFriendsCollectionController.swift new file mode 100644 index 0000000..f7cd08e --- /dev/null +++ b/less6/loginForm/Controllers/AboutFriendsCollectionController.swift @@ -0,0 +1,86 @@ +// +// AboutFriendsCollectionController.swift +// loginForm +// +// Created by prot on 10/02/2020. +// Copyright © 2020 prot. All rights reserved. +// + +import UIKit + + +class AboutFriendsCollectionController: UICollectionViewController { + + var aboutFriendName: String? + + + + override func viewDidLoad() { + super.viewDidLoad() + + } + + /* + // 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 destinationViewController]. + // Pass the selected object to the new view controller. + } + */ + + // MARK: UICollectionViewDataSource + + override func numberOfSections(in collectionView: UICollectionView) -> Int { + // #warning Incomplete implementation, return the number of sections + return 1 + } + + + override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + // #warning Incomplete implementation, return the number of items + return 20 + } + + override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "FriendsCollectionCell", for: indexPath) as! FriendsCollectionCell + + // Configure the cell + + return cell + } + + // MARK: UICollectionViewDelegate + + /* + // Uncomment this method to specify if the specified item should be highlighted during tracking + override func collectionView(_ collectionView: UICollectionView, shouldHighlightItemAt indexPath: IndexPath) -> Bool { + return true + } + */ + + /* + // Uncomment this method to specify if the specified item should be selected + override func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool { + return true + } + */ + + /* + // Uncomment these methods to specify if an action menu should be displayed for the specified item, and react to actions performed on the item + override func collectionView(_ collectionView: UICollectionView, shouldShowMenuForItemAt indexPath: IndexPath) -> Bool { + return false + } + + override func collectionView(_ collectionView: UICollectionView, canPerformAction action: Selector, forItemAt indexPath: IndexPath, withSender sender: Any?) -> Bool { + return false + } + + override func collectionView(_ collectionView: UICollectionView, performAction action: Selector, forItemAt indexPath: IndexPath, withSender sender: Any?) { + + } + */ + +} + diff --git a/less6/loginForm/Controllers/AllGroupsTableController.swift b/less6/loginForm/Controllers/AllGroupsTableController.swift new file mode 100644 index 0000000..a0d27e1 --- /dev/null +++ b/less6/loginForm/Controllers/AllGroupsTableController.swift @@ -0,0 +1,172 @@ +// +// AllGroupsTableController.swift +// loginForm +// +// Created by prot on 10/02/2020. +// Copyright © 2020 prot. All rights reserved. +// + +import UIKit + +class AllGroupsTableController: UITableViewController { + + let searchGroupsUserRequest = SearchGroupsRequest() + + @IBOutlet weak var searchBarAllGroup: UISearchBar! + + var allGroupsMassive = [ + + Group(name: "Party", imageGroups: UIImage(named: "party")!), + Group(name: "Мохнатая мышь", imageGroups: UIImage(named: "мышь")!), + Group(name: "Справедливый выбор", imageGroups: UIImage(named: "справ")!), + Group(name: "Мощные ребята", imageGroups: UIImage(named: "мощь")!), + Group(name: "Траншея моего отца", imageGroups: UIImage(named: "траншея")!), + Group(name: "Человек vs гепард", imageGroups: UIImage(named: "гепард")!), + Group(name: "Молодой", imageGroups: UIImage(named: "party")!), + Group(name: "Жарища", imageGroups: UIImage(named: "мышь")!), + Group(name: "Как сделать нормальный поиск?", imageGroups: UIImage(named: "справ")!), + Group(name: "Всю ночь делал", imageGroups: UIImage(named: "мощь")!), + Group(name: "Как не умереть за Xcodom?", imageGroups: UIImage(named: "траншея")!), + Group(name: "Пот и кровь", imageGroups: UIImage(named: "гепард")!), + Group(name: "Развивая бессоницу", imageGroups: UIImage(named: "party")!), + Group(name: "Подсел на героин", imageGroups: UIImage(named: "мышь")!), + Group(name: "Перегон авто", imageGroups: UIImage(named: "справ")!), + Group(name: "Не смотря на все остальное", imageGroups: UIImage(named: "мощь")!), + Group(name: "Я продолжаю это делать", imageGroups: UIImage(named: "траншея")!), + Group(name: "А на самом деле, все в порядке", imageGroups: UIImage(named: "гепард")!) + ] + + var searching = false + var searchAns = [String]() + + override func viewDidLoad() { + super.viewDidLoad() + + + searchGroupsUserRequest.request(group: "Music") + } + + // MARK: - Table view data source + +// override func numberOfSections(in tableView: UITableView) -> Int { +// // #warning Incomplete implementation, return the number of sections +// return 1 +// } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + // #warning Incomplete implementation, return the number of rows + if searching { + return searchAns.count + }else { + return allGroupsMassive.count + } + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + guard let cell = tableView.dequeueReusableCell(withIdentifier: "GroupsCell", for: indexPath) as? GroupsCell else { + preconditionFailure("Нет связи с GroupsCell") + } + + if searching { + let allGroup = searchAns[indexPath.row] + cell.groupNameLabel.text = allGroup + for i in allGroupsMassive{ + if allGroup == i.name{ + cell.groupImageView.image = i.imageGroups + } + } + + }else { + let allGroup = allGroupsMassive[indexPath.row] + cell.groupNameLabel.text = allGroup.name + cell.groupImageView.image = allGroup.imageGroups + } + + return cell + } + /* + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath) + + // Configure the cell... + + return cell + } + */ + + /* + // Override to support conditional editing of the table view. + override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { + // Return false if you do not want the specified item to be editable. + return true + } + */ + + /* + // Override to support editing the table view. + override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { + if editingStyle == .delete { + // Delete the row from the data source + tableView.deleteRows(at: [indexPath], with: .fade) + } else if editingStyle == .insert { + // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view + } + } + */ + + /* + // Override to support rearranging the table view. + override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) { + + } + */ + + /* + // Override to support conditional rearranging of the table view. + override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool { + // Return false if you do not want the item to be re-orderable. + return true + } + */ + + /* + // 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. + } + */ + +} +extension AllGroupsTableController: UISearchBarDelegate { + + func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String){ + + var searchMassive = [String]() + for i in allGroupsMassive{ + searchMassive.append(i.name) + } + searchAns = searchMassive.filter({$0.prefix(searchText.count) == searchText}) + + searching = true + print(searchAns) + tableView.reloadData() + + } + + + func searchBarCancelButtonClicked(_ searchBar: UISearchBar) { + + hideKeyboard() + searching = false + searchBarAllGroup.text = "" + tableView.reloadData() + } + + @objc func hideKeyboard() { + self.searchBarAllGroup.endEditing(true) + } + +} diff --git a/less6/loginForm/Controllers/FriendCollectionController.swift b/less6/loginForm/Controllers/FriendCollectionController.swift new file mode 100644 index 0000000..41eef7c --- /dev/null +++ b/less6/loginForm/Controllers/FriendCollectionController.swift @@ -0,0 +1,95 @@ +// +// FriendCollectionController.swift +// loginForm +// +// Created by prot on 11/02/2020. +// Copyright © 2020 prot. All rights reserved. +// + +import UIKit + + + +class FriendCollectionController: UICollectionViewController { + + var collectionFriendName: String? + var collectionFriendImage: String? + + override func viewDidLoad() { + super.viewDidLoad() + + title = collectionFriendName + } + + /* + // 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 destinationViewController]. + // Pass the selected object to the new view controller. + } + */ + + // MARK: UICollectionViewDataSource + + override func numberOfSections(in collectionView: UICollectionView) -> Int { + // #warning Incomplete implementation, return the number of sections + return 1 + } + + + override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + // #warning Incomplete implementation, return the number of items + return 1 + } + + override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "FriendsCollectionCell", for: indexPath) as! FriendsCollectionCell + + let image = collectionFriendImage ?? "" + cell.friendImageView.image = Session.shared.getImage(url: image) + return cell + } + + + @objc func onSwipe(_ sender: UISwipeGestureRecognizer){ + + + } + + + // MARK: UICollectionViewDelegate + + /* + // Uncomment this method to specify if the specified item should be highlighted during tracking + override func collectionView(_ collectionView: UICollectionView, shouldHighlightItemAt indexPath: IndexPath) -> Bool { + return true + } + */ + + /* + // Uncomment this method to specify if the specified item should be selected + override func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool { + return true + } + */ + + /* + // Uncomment these methods to specify if an action menu should be displayed for the specified item, and react to actions performed on the item + override func collectionView(_ collectionView: UICollectionView, shouldShowMenuForItemAt indexPath: IndexPath) -> Bool { + return false + } + + override func collectionView(_ collectionView: UICollectionView, canPerformAction action: Selector, forItemAt indexPath: IndexPath, withSender sender: Any?) -> Bool { + return false + } + + override func collectionView(_ collectionView: UICollectionView, performAction action: Selector, forItemAt indexPath: IndexPath, withSender sender: Any?) { + + } + */ + +} + + diff --git a/less6/loginForm/Controllers/FriendsTableViewController.swift b/less6/loginForm/Controllers/FriendsTableViewController.swift new file mode 100644 index 0000000..a68b51f --- /dev/null +++ b/less6/loginForm/Controllers/FriendsTableViewController.swift @@ -0,0 +1,339 @@ +// +// FriendsTableViewController.swift +// loginForm +// +// Created by prot on 10/02/2020. +// Copyright © 2020 prot. All rights reserved. +// + +import UIKit +import Alamofire +import RealmSwift + +class FriendsTableViewController: UITableViewController{ + + let friendService: FriendsServiceRequest = FriendRequest(parser: SwiftyJSONParserFriends()) + var friendsList: [Results] = [] + var token: [NotificationToken] = [] + + var cachedImaged = [String: UIImage]() + + @IBOutlet weak var searhBar: UISearchBar! + + var sections = [Section]() + var searchFriend = [Search]() + + + var searchAns = [String]() + var searching = false + + override func viewDidLoad() { + super.viewDidLoad() + tableView.register(UINib(nibName: "TestTableViewHeader", bundle: nil), forHeaderFooterViewReuseIdentifier: "HeaderView") + + friendService.loadData { +// self.loadData() + print(self.friendsList.count) + self.prepareSections() + } + } + + + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + } + + func prepareSections () { + do { + let realm = try Realm() + let friendsLetters = Array (Set (realm.objects(FriendsVK.self).compactMap{$0.name.first?.lowercased()})).sorted() + friendsList = friendsLetters.map {realm.objects(FriendsVK.self).filter("name BEGINSWITH[д] %s", $0)} + token.removeAll() + friendsList.enumerated().forEach {observeChangesFriends(section: $0.offset, results: $0.element)} + tableView.reloadData() + }catch { + print(error.localizedDescription) + } + } + + func observeChangesFriends (section: Int, results: Results) { + + token.append (results.observe { changes in + guard let tableView = self.tableView else { return } + switch changes { + case .initial: + tableView.reloadSections(IndexSet(integer: section), with: .automatic) + case .update(_, let deletions, let insertions, let modifications): + tableView.beginUpdates() + tableView.insertRows(at: insertions.map({IndexPath(row: $0, section: section)}), with: .automatic) + tableView.deleteRows(at: deletions.map({IndexPath(row: $0, section: section)}), with: .automatic) + tableView.reloadRows(at: modifications.map({IndexPath(row: $0, section: section)}), with: .automatic) + tableView.endUpdates() + case .error(let error): + print(error.localizedDescription) + } + + + }) + + } + + +// func loadData () { +// do{ +// let realm = try Realm() +// print(realm.configuration.fileURL ?? "Нет данных в БД") +// let friends = realm.objects(FriendsVK.self) +// friendsList = ( friends ) +// }catch{ +// print(error.localizedDescription) +// } +// } + + let queue = DispatchQueue(label: "download_url") + private func downloadImage (for url: String, indexPath: IndexPath) { + queue.async { + if let image = Session.shared.getImage(url: url){ + self.cachedImaged[url] = image + } + DispatchQueue.main.async { + self.tableView.reloadRows(at: [indexPath], with: .automatic) + } + } + } + // MARK: - Table view data source + + override func numberOfSections(in tableView: UITableView) -> Int { + +// if searching { +// return searchFriend.count +// }else { +// return sections.count +// } + return friendsList.count + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + +// if searching { +// return searchFriend[section].names.count +// }else { +// return sections[section].names.count +// } + friendsList[section].count + } + + override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { + guard let headerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: "HeaderView") as? TestTableViewHeader else { + preconditionFailure("нет связи HeaderView")} + +// if searching { +// headerView.someLabel.text = searchFriend[section].letter +// }else { +// headerView.someLabel.text = sections[section].letter +// } +// +// headerView.layer.backgroundColor = #colorLiteral(red: 0.1813154817, green: 0.5886535645, blue: 0.9971618056, alpha: 1) +// headerView.someLabel.text = sections[section].letter +// // + return headerView + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + guard let cell = tableView.dequeueReusableCell(withIdentifier: "FriendsCell", for: indexPath) as? FriendsCell else { + preconditionFailure("нет связи FriendsCell") + } + // Если есть буква в сеарч баре тогда +// if searching { +// let section = searchFriend[indexPath.section] +// let name = section.names[indexPath.row]//id +// cell.nameLabel.text = name// имя +// //картинка +// +// +// for i in self.friendsList!{ +// if "\(i.lastName) \(i.fisrtName)" == name{ +// let image = i.photo +// +// if let cached = cachedImaged[image] { +// cell.imageFriendView?.image = cached +// }else { +// downloadImage(for: image, indexPath: indexPath) +// } +// } +// } +// +// }else { +// let section = sections[indexPath.section] +// let name = section.names[indexPath.row]//id +// cell.nameLabel.text = name// имя +// //картинка +// +// for i in self.friendsList!{ +// if "\(i.lastName) \(i.fisrtName)" == name{ +// let image = i.photo +// if let cached = cachedImaged[image] { +// cell.imageFriendView?.image = cached +// }else { +// downloadImage(for: image, indexPath: indexPath) +// } +// } +// } +// } + print(friendsList) + let section = friendsList[indexPath.section] + let name = section[indexPath.row] + cell.nameLabel.text = name.name + print(name) + + return cell + } + + // override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + // return sections[section].letter + // } + // + // override func sectionIndexTitles(for tableView: UITableView) -> [String]? { + // if searching { + // return searchFriend.compactMap{$0.letter.uppercased()} + // }else { + // return sections.compactMap{$0.letter.uppercased()} + // } + // + // } + + + /* + // Override to support conditional editing of the table view. + override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { + // Return false if you do not want the specified item to be editable. + return true + } + */ + + + // Override to support editing the table view. + //функция удаления эллементов свайпом + // override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { + // var section = sections[indexPath.section] + // var nameFriend = section.names[indexPath.row] + // if editingStyle == .delete { + // // Delete the row from the data source + // + // sections.remove(at: indexPath.section) + // print("Удален друг: " + String(nameFriend) + " ((((") + // tableView.deleteRows(at: [IndexPath(row : indexPath.row, section : indexPath.section)], with: .fade) + // tableView.reloadData() + // } + // } + + /* + // Override to support rearranging the table view. + override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) { + + } + */ + + /* + // Override to support conditional rearranging of the table view. + override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool { + // Return false if you do not want the item to be re-orderable. + return true + } + */ + + + // 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. +// if segue.identifier == "Show Friends", +// let indexPath = tableView.indexPathForSelectedRow { +// +// if searching { +// let section = searchFriend[indexPath.section] // id элемента +// let titleFriendName = section.names[indexPath.row] +// let destinationViewController = segue.destination as? FriendCollectionController //определение куда передаем инфу +// destinationViewController?.collectionFriendName = titleFriendName +// //картинка +// for i in friendsList!{ +// if "\(i.lastName) \(i.fisrtName)" == titleFriendName{ +// destinationViewController?.collectionFriendImage = i.photoFull +// Session.shared.userId = i.id +// } +// } +// }else { +// let section = sections[indexPath.section] // id элемента +// let titleFriendName = section.names[indexPath.row] +// let destinationViewController = segue.destination as? FriendCollectionController //определение куда передаем инфу +// destinationViewController?.collectionFriendName = titleFriendName +// //картинка +// for i in friendsList!{ +// if "\(i.lastName) \(i.fisrtName)" == titleFriendName{ +// destinationViewController?.collectionFriendImage = i.photoFull +// Session.shared.userId = i.id +// } +// } +// } + + // let section = friendsList[indexPath.row] + // let firstFriendName = section.fisrtName + // let lasFriendName = section.lastName + // let image = section.photoFull + // let id = section.id + // let destinationViewController = segue.destination as? FriendCollectionController + // destinationViewController?.collectionFriendName = "\(firstFriendName) \(lasFriendName)" + // destinationViewController?.collectionFriendImage = image + // Session.shared.userId = id + } + } + + + +// Поиск +extension FriendsTableViewController : UISearchBarDelegate { + +// func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { +// +// var searchMassive = [String]() +// for i in friendsList!{ +// searchMassive.append("\(i.lastName) \(i.fisrtName)") +// } +// //Поиск +// searchAns = searchMassive.filter({$0.contains(searchText)}) +// //Сортировка под новую структуру +// let groupedDictionary = Dictionary(grouping: searchAns, by: {String($0.prefix(1))}) +// let keys = groupedDictionary.keys.sorted() +// searchFriend = keys.map{ Search(letter: $0, names: groupedDictionary[$0]!.sorted()) } +// +// +// searching = true +// print(searchAns) +// tableView.reloadData() +// +// } +// +// func searchBarCancelButtonClicked(_ searchBar: UISearchBar) { +// +// hideKeyboard() +// searching = false +// searchBar.text = "" +// tableView.reloadData() +// +// } +// //Закрыть клавиатуру +// @objc func hideKeyboard() { +// self.searhBar.endEditing(true) +// } + + + + + +} diff --git a/less6/loginForm/Controllers/LoginFormController.swift b/less6/loginForm/Controllers/LoginFormController.swift new file mode 100644 index 0000000..9198391 --- /dev/null +++ b/less6/loginForm/Controllers/LoginFormController.swift @@ -0,0 +1,107 @@ +// +// LoginFormController.swift +// loginForm +// +// Created by prot on 10/02/2020. +// Copyright © 2020 prot. All rights reserved. +// + +import UIKit + +class LoginFormController: UIViewController { + + @IBOutlet weak var scrollView: UIScrollView! + @IBOutlet weak var textFieldLogin: UITextField! + @IBOutlet weak var textFieldPass: UITextField! + @IBOutlet weak var labelLogin: UILabel! + @IBOutlet weak var buttonIn : UIButton! + + + + override func viewDidLoad() { + super.viewDidLoad() + // Do any additional setup after loading the view. + let tapGesture = UITapGestureRecognizer(target: self, action: #selector(hideKeyboard)) //переменная для закрытия клавитуры при тапе + scrollView.addGestureRecognizer(tapGesture) // закрытие клавитуры + + buttonIn.layer.cornerRadius = 20 + } + + // Ошибка авторизации + func showInError() { + + let alertVC = UIAlertController(title: "Ошибка", message: "Неверный логин или пароль", preferredStyle: .alert) + let action = UIAlertAction(title: "Ok", style: .default) { _ in + print("Ок clicked") + } + alertVC.addAction(action) + + present(alertVC, animated: true, completion: nil) + } + + + func checkLogin() -> Bool { + if let login = textFieldLogin.text, + let pass = textFieldPass.text { + + if login == "admin", pass == "admin" { + print("Успешная авторизация") + return true + }else { + print("Не успешная авторизация") + return false + } + };return false + } + + + override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool { + if checkLogin(){ + return true + }else{ + showInError() + return false + } + + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + //скрыть navigation bar + navigationController?.setNavigationBarHidden(true, animated: false) + + // Подписываемся на два уведомления: одно приходит при появлении клавиатуры + + NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShown(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil) + // Второе — когда она пропадает + NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil) + } + // Когда клавиатура появляется + @objc func keyboardWillShown ( notification : Notification) { + // Получаем размер клавиатуры + let info = notification.userInfo! as NSDictionary + let size = (info.value(forKey: UIResponder.keyboardFrameEndUserInfoKey) as! NSValue).cgRectValue.size + let contentInsents = UIEdgeInsets(top: 0, left: 0, bottom: size.height, right: 0) + // Добавляем отступ внизу UIScrollView, равный размеру клавиатуры + self.scrollView?.contentInset = contentInsents + self.scrollView.scrollIndicatorInsets = contentInsents + + } + //Когда клавиатура исчезает + @objc func keyboardWillHide ( notification : Notification) { + // Устанавливаем отступ внизу UIScrollView, равный 0 + scrollView.contentInset = .zero + + } + //клик по пустому месту на экране сворачивает клаву + @objc func hideKeyboard() { + self.scrollView.endEditing(true) + } + + //выход на начальный контроллер + @IBAction func exit(unwindSegue: UIStoryboardSegue) { + print("Welocme back") + } + +} diff --git a/less6/loginForm/Controllers/NewsTableViewController.swift b/less6/loginForm/Controllers/NewsTableViewController.swift new file mode 100644 index 0000000..1ea1b83 --- /dev/null +++ b/less6/loginForm/Controllers/NewsTableViewController.swift @@ -0,0 +1,102 @@ +// +// NewsTableViewController.swift +// loginForm +// +// Created by prot on 22/02/2020. +// Copyright © 2020 prot. All rights reserved. +// + +import UIKit + +class NewsTableViewController: UITableViewController { + + override func viewDidLoad() { + super.viewDidLoad() + + + tableView.register(UINib(nibName: "NewsHeaderClass", bundle: nil), forHeaderFooterViewReuseIdentifier: "HeaderNewsView") + // Uncomment the following line to preserve selection between presentations + // self.clearsSelectionOnViewWillAppear = false + + // Uncomment the following line to display an Edit button in the navigation bar for this view controller. + // self.navigationItem.rightBarButtonItem = self.editButtonItem + } + + // MARK: - Table view data source + + override func numberOfSections(in tableView: UITableView) -> Int { + // #warning Incomplete implementation, return the number of sections + return 1 + } + + + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + // #warning Incomplete implementation, return the number of rows + return 1 + } + + override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { + guard let headerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: "HeaderNewsView") as? NewsHeaderClass else { + preconditionFailure("нет связи HeaderView") + } + return headerView + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + guard let cell = tableView.dequeueReusableCell(withIdentifier: "NewsCell", for: indexPath) as? NewsCellTableViewCell else { + preconditionFailure("нет связи NewsCell") + } + + + + return cell + } + + + /* + // Override to support conditional editing of the table view. + override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { + // Return false if you do not want the specified item to be editable. + return true + } + */ + + /* + // Override to support editing the table view. + override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { + if editingStyle == .delete { + // Delete the row from the data source + tableView.deleteRows(at: [indexPath], with: .fade) + } else if editingStyle == .insert { + // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view + } + } + */ + + /* + // Override to support rearranging the table view. + override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) { + + } + */ + + /* + // Override to support conditional rearranging of the table view. + override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool { + // Return false if you do not want the item to be re-orderable. + return true + } + */ + + /* + // 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/less6/loginForm/Controllers/NewsViewController.swift b/less6/loginForm/Controllers/NewsViewController.swift new file mode 100644 index 0000000..413d640 --- /dev/null +++ b/less6/loginForm/Controllers/NewsViewController.swift @@ -0,0 +1,47 @@ +// +// NewsViewController.swift +// loginForm +// +// Created by prot on 22/02/2020. +// Copyright © 2020 prot. All rights reserved. +// + +import UIKit + +class NewsViewController: 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. + } + */ + +} +extension NewsViewController: UITableViewDelegate, UITableViewDataSource { + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return 1 + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + guard let cell = tableView.dequeueReusableCell(withIdentifier: "NewsCell", for: indexPath) as? NewsCell else { + preconditionFailure("нет связи FriendsCell") + } + return cell + } + + + + + + +} diff --git a/less6/loginForm/Controllers/SettingsViewController.swift b/less6/loginForm/Controllers/SettingsViewController.swift new file mode 100644 index 0000000..25ccce7 --- /dev/null +++ b/less6/loginForm/Controllers/SettingsViewController.swift @@ -0,0 +1,58 @@ +// +// SettingsViewController.swift +// loginForm +// +// Created by prot on 25/02/2020. +// Copyright © 2020 prot. All rights reserved. +// + +import UIKit + +class SettingsViewController: UIViewController { + + @IBOutlet weak var loadView1: UIView! + @IBOutlet weak var loadView2: UIView! + @IBOutlet weak var loadView3: UIView! + + override func viewDidLoad() { + super.viewDidLoad() + + downloadView() + + } + + func downloadView () { + loadView1.layer.cornerRadius = 10 + loadView2.layer.cornerRadius = 10 + loadView3.layer.cornerRadius = 10 + + UIView.animate(withDuration: 0.4, delay: 0, options: [.repeat, .autoreverse], animations: { + self.loadView1.alpha = 0.5 + + }) + UIView.animate(withDuration: 0.4, delay: 0.2, options: [.repeat, .autoreverse], animations: { + self.loadView2.alpha = 0.5 + + + }) + UIView.animate(withDuration: 0.4, delay: 0.3, options: [.repeat, .autoreverse], animations: { + self.loadView3.alpha = 0.5 + + + }) + } + + /* + // 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. + } + */ + @IBAction func exit(unwindSegue: UIStoryboardSegue) { + print("Welocme back") + } + +} diff --git a/less6/loginForm/Controllers/SubscriptionTableViewController.swift b/less6/loginForm/Controllers/SubscriptionTableViewController.swift new file mode 100644 index 0000000..95d7595 --- /dev/null +++ b/less6/loginForm/Controllers/SubscriptionTableViewController.swift @@ -0,0 +1,214 @@ +// +// SubscriptionTableViewController.swift +// loginForm +// +// Created by prot on 10/02/2020. +// Copyright © 2020 prot. All rights reserved. +// + +import UIKit +import RealmSwift + +class SubscriptionTableViewController: UITableViewController { + + let groupsService: GroupsServiceRequest = GroupsRequest(parser: SwiftyJSONParserGroups()) + var groupsList: [GroupsVK] = [] + var cachedImaged = [String: UIImage]() + + @IBOutlet weak var searBarGroup:UISearchBar! + + var groupsMassive = [ + Group(name: "Party", imageGroups: UIImage(named: "party")!) + ] + var searching = false + var searchAns = [String]() + + override func viewDidLoad() { + super.viewDidLoad() + + groupsService.loadData { + self.loadData() + self.tableView.reloadData() + } + + } + + func loadData () { + do{ + let realm = try Realm() + print(realm.configuration.fileURL) + let groups = realm.objects(GroupsVK.self) + groupsList = Array( groups ) + }catch{ + print(error.localizedDescription) + } + } + + //сигуэй при выходе с контроллера, добавление элементов на другой контролллер + @IBAction func addGroup(segue: UIStoryboardSegue) { + var nameGroups = [String]() //массив для перебора имен в массиве groupsMassive + for i in groupsMassive{ + nameGroups.append(i.name) + } + if segue.identifier == "addGroup" { + // Ссылка на контроллер с которого переход + guard let allGroupsController = segue.source as? AllGroupsTableController else { return } + //получаем индекс ячейки с массива + if let indexPath = allGroupsController.tableView.indexPathForSelectedRow { + //получаем группу по индексу + let addGroup = allGroupsController.allGroupsMassive[indexPath.row] + // добавляем в массив + let nameAllGroup = addGroup.name + if !nameGroups.contains(nameAllGroup) { + groupsMassive.append(addGroup) + print("Добавлен элемент: " + nameAllGroup) + } + } + //обновляем таблицу + tableView.reloadData() + } + } + + + private func downloadImage (for url: String, indexPath: IndexPath) { + DispatchQueue.global().async { + if let image = Session.shared.getImage(url: url){ + self.cachedImaged[url] = image + } + DispatchQueue.main.async { + self.tableView.reloadRows(at: [indexPath], with: .automatic) + } + } + } + + + + //функция удаления элементов + override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { + let nameGroup = groupsMassive[indexPath.row] + // Если была нажата кнопка «Удалить» + if editingStyle == .delete { + // Удаляем из массива + groupsMassive.remove(at: indexPath.row) + print("Удален элемент: " + nameGroup.name) + // И удаляем строку из таблицы + tableView.deleteRows(at: [indexPath], with: .fade) + } + } + // MARK: - Table view data source + + // override func numberOfSections(in tableView: UITableView) -> Int { + // // #warning Incomplete implementation, return the number of sections + // return 1 + // } + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + // #warning Incomplete implementation, return the number of rows +// if searching{ +// return searchAns.count +// }else{ +// return groupsMassive.count +// } + + groupsList.count + + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + guard let cell = tableView.dequeueReusableCell(withIdentifier: "GroupsCell", for: indexPath) as? GroupsCell else { + preconditionFailure("No connect GroupCell") + } +// if searching{ +// let subscriptionName = searchAns[indexPath.row] +// cell.groupNameLabel.text = subscriptionName +// for i in groupsMassive { +// if subscriptionName == i.name{ +// cell.groupImageView.image = i.imageGroups +// } +// } +// }else { +// let subscriptionName = groupsMassive[indexPath.row] +// cell.groupNameLabel.text = subscriptionName.name +// cell.groupImageView.image = subscriptionName.imageGroups +// } + cell.groupNameLabel.text = "\(groupsList[indexPath.row].name)" + let image = "\(groupsList[indexPath.row].photo)" + + if let cached = cachedImaged[image] { + cell.groupImageView.image = cached + }else { + downloadImage(for: image, indexPath: indexPath) + } + return cell + } + + /* + // Override to support conditional editing of the table view. + override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { + // Return false if you do not want the specified item to be editable. + return true + } + */ + + /* + // Override to support editing the table view. + override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { + if editingStyle == .delete { + // Delete the row from the data source + tableView.deleteRows(at: [indexPath], with: .fade) + } else if editingStyle == .insert { + // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view + } + } + */ + + /* + // Override to support rearranging the table view. + override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) { + + } + */ + + /* + // Override to support conditional rearranging of the table view. + override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool { + // Return false if you do not want the item to be re-orderable. + return true + } + */ + + /* + // 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. + } + */ + +} +extension SubscriptionTableViewController:UISearchBarDelegate{ + + func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String){ + + let searchMassive = groupsMassive.map {$0.name} + + searchAns = searchMassive.filter({$0.prefix(searchText.count) == searchText}) + + searching = true + print(searchAns) + tableView.reloadData() + } + + func searchBarCancelButtonClicked(_ searchBar: UISearchBar) { + + hideKeyboard() + searching = false + searBarGroup.text = "" + tableView.reloadData() + } + + @objc func hideKeyboard() { + self.searBarGroup.endEditing(true) + } +} diff --git a/less6/loginForm/FriendsAndGroupsCell.swift b/less6/loginForm/FriendsAndGroupsCell.swift new file mode 100644 index 0000000..4ca8d0c --- /dev/null +++ b/less6/loginForm/FriendsAndGroupsCell.swift @@ -0,0 +1,16 @@ +// +// FriendsAndGroupsCell.swift +// loginForm +// +// Created by prot on 10/02/2020. +// Copyright © 2020 prot. All rights reserved. +// + +import UIKit + +class FriendsAndGroupsCell: UITableViewCell { + + @IBOutlet weak var subscrNameLabel: UILabel! + @IBOutlet weak var friendsNameLabel: UILabel! + +} diff --git a/less6/loginForm/FriendsTableController.swift b/less6/loginForm/FriendsTableController.swift new file mode 100644 index 0000000..0e1d4d7 --- /dev/null +++ b/less6/loginForm/FriendsTableController.swift @@ -0,0 +1,96 @@ +// +// FriendsTableController.swift +// loginForm +// +// Created by prot on 10/02/2020. +// Copyright © 2020 prot. All rights reserved. +// + +import UIKit + +class FriendsTableController: UITableViewController { + + override func viewDidLoad() { + super.viewDidLoad() + + // Uncomment the following line to preserve selection between presentations + // self.clearsSelectionOnViewWillAppear = false + + // Uncomment the following line to display an Edit button in the navigation bar for this view controller. + // self.navigationItem.rightBarButtonItem = self.editButtonItem + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + + } + + // MARK: - Table view data source + + override func numberOfSections(in tableView: UITableView) -> Int { + // #warning Incomplete implementation, return the number of sections + return 0 + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + // #warning Incomplete implementation, return the number of rows + return 0 + } + + /* + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath) + + // Configure the cell... + + return cell + } + */ + + /* + // Override to support conditional editing of the table view. + override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { + // Return false if you do not want the specified item to be editable. + return true + } + */ + + /* + // Override to support editing the table view. + override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { + if editingStyle == .delete { + // Delete the row from the data source + tableView.deleteRows(at: [indexPath], with: .fade) + } else if editingStyle == .insert { + // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view + } + } + */ + + /* + // Override to support rearranging the table view. + override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) { + + } + */ + + /* + // Override to support conditional rearranging of the table view. + override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool { + // Return false if you do not want the item to be re-orderable. + return true + } + */ + + /* + // 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/less6/loginForm/FrindsAndGroupsCell.swift b/less6/loginForm/FrindsAndGroupsCell.swift new file mode 100644 index 0000000..a868756 --- /dev/null +++ b/less6/loginForm/FrindsAndGroupsCell.swift @@ -0,0 +1,24 @@ +// +// FrindsAndGroupsCell.swift +// loginForm +// +// Created by prot on 10/02/2020. +// Copyright © 2020 prot. All rights reserved. +// + +import UIKit + +class FrindsAndGroupsCell: UITableViewCell { + + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + } + +} diff --git a/less6/loginForm/Info.plist b/less6/loginForm/Info.plist new file mode 100644 index 0000000..2a3483c --- /dev/null +++ b/less6/loginForm/Info.plist @@ -0,0 +1,64 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + UISceneStoryboardFile + Main + + + + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/less6/loginForm/Model/Groups.swift b/less6/loginForm/Model/Groups.swift new file mode 100644 index 0000000..3aa129e --- /dev/null +++ b/less6/loginForm/Model/Groups.swift @@ -0,0 +1,15 @@ +// +// Groups.swift +// loginForm +// +// Created by prot on 11/02/2020. +// Copyright © 2020 prot. All rights reserved. +// + +import UIKit + + +struct Group { + let name: String + let imageGroups: UIImage +} diff --git a/less6/loginForm/Model/friendsStruct.swift b/less6/loginForm/Model/friendsStruct.swift new file mode 100644 index 0000000..91ff81e --- /dev/null +++ b/less6/loginForm/Model/friendsStruct.swift @@ -0,0 +1,23 @@ +// +// friendsStruct.swift +// loginForm +// +// Created by prot on 11/02/2020. +// Copyright © 2020 prot. All rights reserved. +// + +import UIKit + + +struct Friend { + let name: String + let imageFriends: UIImage +} +struct Section { + var letter: String + var names: [String] +} +struct Search { + var letter: String + var names: [String] +} diff --git a/less6/loginForm/MyViewController.swift b/less6/loginForm/MyViewController.swift new file mode 100644 index 0000000..a84c66b --- /dev/null +++ b/less6/loginForm/MyViewController.swift @@ -0,0 +1,30 @@ +// +// MyViewController.swift +// loginForm +// +// Created by prot on 31/01/2020. +// Copyright © 2020 prot. All rights reserved. +// + +import UIKit + +class MyViewController: 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/less6/loginForm/PictureViewController.swift b/less6/loginForm/PictureViewController.swift new file mode 100644 index 0000000..8161b67 --- /dev/null +++ b/less6/loginForm/PictureViewController.swift @@ -0,0 +1,314 @@ +// +// PictureViewController.swift +// loginForm +// +// Created by prot on 29.02.2020. +// Copyright © 2020 prot. All rights reserved. +// + +import UIKit +import RealmSwift +class PictureViewController: UIViewController { + + let photoService: PhotosServiceRequest = PhotosRequest(parser: SwiftyJSONParserPhotos()) + var photosList: [PhotosVK] = [] + var photosCached = [UIImage]() + + + @IBOutlet weak var imagesFriendOne: UIImageView! + @IBOutlet weak var imagesFriendTwo: UIImageView! + // + @IBOutlet weak var img2TopConstr: NSLayoutConstraint! + @IBOutlet weak var img2BottomConstr: NSLayoutConstraint! + // + @IBOutlet weak var img1TopConstr: NSLayoutConstraint! + @IBOutlet weak var img1BottomConstr: NSLayoutConstraint! + + override func viewDidLoad() { + super.viewDidLoad() + let recognizer = UIPanGestureRecognizer(target: self, action: #selector(onPanImg1(_:))) + imagesFriendOne.isUserInteractionEnabled = true + imagesFriendOne.addGestureRecognizer(recognizer) + let tapGesture = UITapGestureRecognizer(target: self, action: #selector(onTap(_:))) + imagesFriendOne.addGestureRecognizer(tapGesture) + + let recognizer2 = UIPanGestureRecognizer(target: self, action: #selector(onPanImg2(_:))) + imagesFriendTwo.isUserInteractionEnabled = true + imagesFriendTwo.addGestureRecognizer(recognizer2) + imagesFriendTwo.isHidden = true + + let tapGesture2 = UITapGestureRecognizer(target: self, action: #selector(onTap2(_:))) + imagesFriendTwo.addGestureRecognizer(tapGesture2) + + + photoService.loadData { + self.loadData() + for i in self.photosList { + let photo = Session.shared.getImage(url: i.photo) + self.photosCached.append(photo!) + } + let images = self.photosCached[self.count] + + self.imagesFriendOne.image = images + } + } + + override func viewWillAppear(_ animated: Bool) { + super .viewWillAppear(animated) + + } + + func loadData () { + do{ + let realm = try Realm() + print(realm.configuration.fileURL) + let photos = realm.objects(PhotosVK.self) + photosList = Array( photos ) + }catch{ + print(error.localizedDescription) + } + + } + + + var count = 0 + + var interactiveAnimate: UIViewPropertyAnimator! + + // Анимация первой картинки + @objc func onPanImg1 (_ recognizer: UIPanGestureRecognizer){ + + print(#function) + self.imagesFriendTwo.isHidden = true + self.imagesFriendTwo.transform = CGAffineTransform(scaleX: 0.8, y: 0.8) + self.imagesFriendTwo.alpha = 0.5 + self.img2TopConstr.constant = 50 + self.img2BottomConstr.constant = 146 + + switch recognizer.state { + case .began: + interactiveAnimate?.startAnimation() + + interactiveAnimate = UIViewPropertyAnimator(duration: 0.6, dampingRatio: 0.6, animations: { + }) + interactiveAnimate.pauseAnimation() + case .changed: + let translation = recognizer.translation(in: self.view) + imagesFriendOne.transform = CGAffineTransform(translationX: translation.x / 2, y: 0) + case .ended: + interactiveAnimate.stopAnimation(true) + + if imagesFriendOne.frame.minX >= 100 { + + count -= 1 + if count >= 0 && count < photosList.count { + let images = photosCached[self.count] + self.imagesFriendTwo.image = images + + self.imagesFriendTwo.isHidden = false + interactiveAnimate.addAnimations { + UIView.animateKeyframes(withDuration: 2, delay: 0, options: [], animations: { + UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0.5, animations: { + self.imagesFriendOne.transform = CGAffineTransform(translationX: self.view.frame.width, y: 0) + }) + UIView.addKeyframe(withRelativeStartTime: 0.5, relativeDuration: 0.5, animations: { + self.imagesFriendTwo.transform = .identity + self.imagesFriendTwo.alpha = 1 + }) + UIView.addKeyframe(withRelativeStartTime: 1, relativeDuration: 0.5, animations: { + self.imagesFriendOne.transform = CGAffineTransform(translationX: -(self.view.frame.width), y: 0) + }) + }) + + } + }else { + count = 0 + interactiveAnimate.addAnimations { + self.imagesFriendOne.transform = .identity + } + } + + }else if imagesFriendOne.frame.minX <= -100 { + count += 1 + if count < photosCached.count { + let images = photosCached[self.count] + self.imagesFriendTwo.image = images + + + self.imagesFriendTwo.isHidden = false + interactiveAnimate.addAnimations { + UIView.animateKeyframes(withDuration: 2, delay: 0, options: [], animations: { + UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0.5, animations: { + self.imagesFriendOne.transform = CGAffineTransform(translationX: -(self.view.frame.width), y: 0) + }) + UIView.addKeyframe(withRelativeStartTime: 0.5, relativeDuration: 0.5, animations: { + self.imagesFriendTwo.alpha = 1 + self.imagesFriendTwo.transform = CGAffineTransform(scaleX: 1, y: 1) + }) + UIView.addKeyframe(withRelativeStartTime: 1, relativeDuration: 0.5, animations: { + self.imagesFriendOne.transform = CGAffineTransform(translationX: self.view.frame.width, y: 0) + }) + }) + } + + }else{ + count = photosCached.count - 1 + self.imagesFriendOne.transform = .identity + } + + + }else{ + interactiveAnimate.addAnimations { + self.imagesFriendOne.transform = .identity + } + } + interactiveAnimate.startAnimation() + + default: + return + } + } + + + // Анимация второй картинки + @objc func onPanImg2 (_ recognizer: UIPanGestureRecognizer){ + + let images = photosCached[count] + imagesFriendOne.image = images + + + print(#function) + self.imagesFriendOne.transform = CGAffineTransform(scaleX: 0.8, y: 0.8) + self.imagesFriendOne.alpha = 0.5 + self.imagesFriendOne.isHidden = true + self.img1TopConstr.constant = 50 + self.img1BottomConstr.constant = 146 + + switch recognizer.state { + case .began: + interactiveAnimate?.startAnimation() + + interactiveAnimate = UIViewPropertyAnimator(duration: 0.6, dampingRatio: 0.6, animations: { + self.imagesFriendTwo.transform = .identity + }) + interactiveAnimate.pauseAnimation() + case .changed: + let translation = recognizer.translation(in: self.view) + imagesFriendTwo.transform = CGAffineTransform(translationX: translation.x / 2, y: 0) + case .ended: + + + + interactiveAnimate.stopAnimation(true) + + if imagesFriendTwo.frame.minX >= 100 { + count -= 1 + if count >= 0 && count < photosList.count { + let images = photosCached[self.count] + self.imagesFriendOne.image = images + + + self.imagesFriendOne.isHidden = false + + interactiveAnimate.addAnimations { + UIView.animateKeyframes(withDuration: 2, delay: 0, options: [], animations: { + UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0.5, animations: { + self.imagesFriendTwo.transform = CGAffineTransform(translationX: self.view.frame.width, y: 0) + }) + UIView.addKeyframe(withRelativeStartTime: 0.5, relativeDuration: 0.5, animations: { + self.imagesFriendOne.transform = .identity + self.imagesFriendOne.alpha = 1 + }) + UIView.addKeyframe(withRelativeStartTime: 1, relativeDuration: 0.5, animations: { + self.imagesFriendTwo.transform = CGAffineTransform(translationX: -(self.view.frame.width), y: 0) + }) + }) + } + }else { + count = 0 + interactiveAnimate.addAnimations { + self.imagesFriendTwo.transform = .identity + } + } + + // + + + }else if imagesFriendTwo.frame.minX <= -100 { + count += 1 + if count < photosList.count { + let images = photosCached[self.count] + self.imagesFriendOne.image = images + + self.imagesFriendOne.isHidden = false + + interactiveAnimate.addAnimations { + UIView.animateKeyframes(withDuration: 2, delay: 0, options: [], animations: { + UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0.5, animations: { + self.imagesFriendTwo.transform = CGAffineTransform(translationX: -(self.view.frame.width), y: 0) + }) + UIView.addKeyframe(withRelativeStartTime: 0.5, relativeDuration: 0.5, animations: { + self.imagesFriendOne.transform = .identity + self.imagesFriendOne.alpha = 1 + }) + + + }) + } + + }else{ + count = photosList.count - 1 + self.imagesFriendTwo.transform = .identity + } + + + }else{ + interactiveAnimate.addAnimations { + self.imagesFriendTwo.transform = .identity + } + } + interactiveAnimate.startAnimation() + + default: + return + } + + + } + + @objc func onTap (_ gesture: UITapGestureRecognizer){ + print(#function) + self.view.layoutIfNeeded() + if img1TopConstr.constant == 0 { + UIView.animate(withDuration: 1, animations: { + self.img1TopConstr.constant = 50 + self.img1BottomConstr.constant = 146 + self.view.layoutIfNeeded() + }) + }else { + UIView.animate(withDuration: 1, animations: { + self.img1TopConstr.constant = 0 + self.img1BottomConstr.constant = 0 + self.view.layoutIfNeeded() + }) + } + } + @objc func onTap2 (_ gesture: UITapGestureRecognizer){ + print(#function) + self.view.layoutIfNeeded() + if img2TopConstr.constant == 0 { + UIView.animate(withDuration: 1, animations: { + self.img2TopConstr.constant = 50 + self.img2BottomConstr.constant = 146 + self.view.layoutIfNeeded() + }) + }else { + UIView.animate(withDuration: 1, animations: { + self.img2TopConstr.constant = 0 + self.img2BottomConstr.constant = 0 + self.view.layoutIfNeeded() + }) + } + } + +} diff --git a/less6/loginForm/SceneDelegate.swift b/less6/loginForm/SceneDelegate.swift new file mode 100644 index 0000000..306c3b9 --- /dev/null +++ b/less6/loginForm/SceneDelegate.swift @@ -0,0 +1,53 @@ +// +// SceneDelegate.swift +// loginForm +// +// Created by prot on 30/01/2020. +// Copyright © 2020 prot. All rights reserved. +// + +import UIKit + +class SceneDelegate: UIResponder, UIWindowSceneDelegate { + + var window: UIWindow? + + + func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { + // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. + // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. + // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). + guard let _ = (scene as? UIWindowScene) else { return } + } + + func sceneDidDisconnect(_ scene: UIScene) { + // Called as the scene is being released by the system. + // This occurs shortly after the scene enters the background, or when its session is discarded. + // Release any resources associated with this scene that can be re-created the next time the scene connects. + // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). + } + + func sceneDidBecomeActive(_ scene: UIScene) { + // Called when the scene has moved from an inactive state to an active state. + // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. + } + + func sceneWillResignActive(_ scene: UIScene) { + // Called when the scene will move from an active state to an inactive state. + // This may occur due to temporary interruptions (ex. an incoming phone call). + } + + func sceneWillEnterForeground(_ scene: UIScene) { + // Called as the scene transitions from the background to the foreground. + // Use this method to undo the changes made on entering the background. + } + + func sceneDidEnterBackground(_ scene: UIScene) { + // Called as the scene transitions from the foreground to the background. + // Use this method to save data, release shared resources, and store enough scene-specific state information + // to restore the scene back to its current state. + } + + +} + diff --git a/less6/loginForm/Services/FriendsRequest.swift b/less6/loginForm/Services/FriendsRequest.swift new file mode 100644 index 0000000..89a3190 --- /dev/null +++ b/less6/loginForm/Services/FriendsRequest.swift @@ -0,0 +1,185 @@ +// +// FriendsRequest.swift +// loginForm +// +// Created by prot on 17.03.2020. +// Copyright © 2020 prot. All rights reserved. +// + +import Foundation +import Alamofire +import SwiftyJSON +import RealmSwift + +class FriendsVK: Object { + @objc dynamic var id = Int() +// @objc dynamic var firstName = String() +// @objc dynamic var lastName = String() + @objc dynamic var name = "" + @objc dynamic var photo = String() + @objc dynamic var photoFull = String() + + +} + +//class DataBaseFriends { +// func save( friends: [FriendsVK] ) throws { +// +// let realm = try Realm() +// print(realm.configuration.fileURL) +// realm.beginWrite() +// realm.add(friends) +// try realm.commitWrite() +// } +// +// func friends() -> [FriendsVK] { +// do { +// let realm = try Realm() +// let objects = realm.objects(FriendsVK.self) +// return Array(objects) +// } +// catch { +// return [] +// } +// } +//} + +protocol FriendsServiceRequest { + func loadData (completion: @escaping () -> Void) +} + +protocol FriendsParser { + func parse (data: Data) -> [FriendsVK] +} + +class SwiftyJSONParserFriends: FriendsParser { + func parse(data: Data) -> [FriendsVK] { + do{ + let json = try JSON(data:data) + let response = json["response"] + let items = response["items"].arrayValue + + let result = items.map{item -> FriendsVK in + let friends = FriendsVK() + friends.id = item["id"].intValue + let firstName = item["first_name"].stringValue + let lastName = item["last_name"].stringValue + friends.name = "\(firstName) \(lastName)" + friends.photo = item["photo_50"].stringValue + friends.photoFull = item["photo_100"].stringValue + + return friends + } + return result + }catch{ + print(error.localizedDescription) + return [] + } + } +} + +class FriendRequest: FriendsServiceRequest { + let parser: FriendsParser + func save( friends: [FriendsVK] ) { + do { + let realm = try Realm() + let oldFriends = realm.objects(FriendsVK.self) + realm.beginWrite() + realm.delete(oldFriends) + realm.add(friends) + try realm.commitWrite() + }catch{ + print(error.localizedDescription) + } + + } + + init (parser: FriendsParser) { + self.parser = parser + } + + func loadData(completion: @escaping () -> Void) { + + let baseURL = "https://api.vk.com/method" + let apiKey = Session.shared.token + + let path = "/friends.get" + let url = baseURL + path + + let parameters: Parameters = [ + "fields": "name, photo_50, photo_100", + "v": "5.52", + "access_token": apiKey + ] + + Alamofire.request(url, method: .get, parameters: parameters).responseJSON { [completion] (response) in + guard let data = response.data else { return } + + let friends: [FriendsVK] = self.parser.parse(data: data) + self.save(friends: friends) + completion() + } + + } + + // let baseURL = "https://api.vk.com/method" + // let apiKey = Session.shared.token + // + // func request () { + // let path = "/friends.get" + // let url = baseURL + path + // + // let parameters: Parameters = [ + // "fields": "name", + // "v": "5.52", + // "access_token": apiKey + // ] + + // Alamofire.request(url, method: .get, parameters: parameters).responseData { response in + // print("Запрос друзей \(response.value ?? "")") + // } + + + // Alamofire.request(url, method: .get, parameters: parameters).responseJSON { response in + // print("Запрос друзей \(response.value ?? "")") + // } + + // Alamofire.request("https://api.vk.com/method/friends.get?v=5.52&access_token=813c1c16e28b5c1ee4876f3b65e8260a8626dbd18a6f5d06faa9db78225b90b00594512ad33a92c3bf0a0").responseJSON { response in + // print(response.value) +} +//class SerializerParser: FriendsParser { +// func parse(data: Data) -> [FriendUrl] { +// do { +// let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) +// +// guard let jsonParsed = json as? [String: Any], +// let response = jsonParsed["response"] as? [String: Any], +// let items = response["items"] as? [Any] else {return []} +// +// let result = items.compactMap { raw -> FriendUrl? in +// guard let point = raw as? [String: Any], +// let id = point["id"] as? Int, +// let firstName = point["first_name"] as? String, +// let lastName = point["last_name"] as? String, +// let photo = point["photo_50"] as? String else {return nil} +// +// var friend = FriendUrl() +// +// friend.id = id +// friend.fisrtName = firstName +// friend.lastName = lastName +// friend.photo = photo +// +// return friend +// +// } +// return result +// }catch { +// print(error.localizedDescription) +// return [] +// } +// } +// +// +// +//} diff --git a/less6/loginForm/Services/GroupsRequest.swift b/less6/loginForm/Services/GroupsRequest.swift new file mode 100644 index 0000000..c2dbd31 --- /dev/null +++ b/less6/loginForm/Services/GroupsRequest.swift @@ -0,0 +1,118 @@ +// +// GroupsRequest.swift +// loginForm +// +// Created by prot on 17.03.2020. +// Copyright © 2020 prot. All rights reserved. +// + +import Foundation +import Alamofire +import SwiftyJSON +import RealmSwift + +class GroupsVK: Object { + @objc dynamic var id = Int() + @objc dynamic var name = String() + @objc dynamic var photo = String() +} + +//class DataBaseGroups { +// func save( groups: [GroupsVK] ) throws { +// let realm = try Realm() +// realm.beginWrite() +// realm.add(groups) +// try realm.commitWrite() +// } +// +// func groups() -> [GroupsVK] { +// do { +// let realm = try Realm() +// let objects = realm.objects(GroupsVK.self) +// return Array(objects) +// } +// catch { +// return [] +// } +// } +//} + +protocol GroupsServiceRequest { + func loadData (completion: @escaping () -> Void) +} + +protocol GroupsParser { + func parse (data: Data) -> [GroupsVK] +} + +class SwiftyJSONParserGroups: GroupsParser { + func parse(data: Data) -> [GroupsVK] { + do{ + let json = try JSON(data:data) + let response = json["response"] + let items = response["items"].arrayValue + + let result = items.map{item -> GroupsVK in + let groups = GroupsVK() + groups.id = item["id"].intValue + groups.name = item["name"].stringValue + groups.photo = item["photo_50"].stringValue + + return groups + } + return result + }catch{ + print(error.localizedDescription) + return [] + } + } +} + +class GroupsRequest: GroupsServiceRequest { + + let parser: GroupsParser + + func save( groups: [GroupsVK] ) { + do { + let realm = try Realm() + let oldGroups = realm.objects(GroupsVK.self) + realm.beginWrite() + realm.delete(oldGroups) + realm.add(groups) + try realm.commitWrite() + }catch{ + print(error.localizedDescription) + } + + } + + init(parser: GroupsParser) { + self.parser = parser + } + + func loadData(completion: @escaping () -> Void) { + let baseURL = "https://api.vk.com/method" + let apiKey = Session.shared.token + + let path = "/groups.get" + let url = baseURL + path + + let parameters: Parameters = [ + "v": "5.52", + "access_token": apiKey, + "extended": 1 + ] + + Alamofire.request(url, method: .get, parameters: parameters).responseJSON { [completion] (response) in + guard let data = response.data else { return } + + let groups: [GroupsVK] = self.parser.parse(data: data) + self.save(groups: groups) + + + completion() + } + + } + +} diff --git a/less6/loginForm/Services/PhotoRequest.swift b/less6/loginForm/Services/PhotoRequest.swift new file mode 100644 index 0000000..bf852a6 --- /dev/null +++ b/less6/loginForm/Services/PhotoRequest.swift @@ -0,0 +1,116 @@ +// +// PhotoRequest.swift +// loginForm +// +// Created by prot on 17.03.2020. +// Copyright © 2020 prot. All rights reserved. +// + +import Foundation +import Alamofire +import SwiftyJSON +import RealmSwift + +class PhotosVK: Object { + @objc dynamic var photo = String() +} + +//class DataBasePhotos { +// func save( photos: [PhotosVK] ) throws { +// let realm = try Realm() +// realm.beginWrite() +// realm.add(photos) +// try realm.commitWrite() +// } +// +// func photos() -> [PhotosVK] { +// do { +// let realm = try Realm() +// let objects = realm.objects(PhotosVK.self) +// return Array(objects) +// } +// catch { +// return [] +// } +// } +//} + +protocol PhotosServiceRequest { + func loadData (completion: @escaping () -> Void) +} + +protocol PhotosParser { + func parse (data: Data) -> [PhotosVK] +} + +class SwiftyJSONParserPhotos: PhotosParser { + func parse(data: Data) -> [PhotosVK] { + do{ + let json = try JSON(data:data) + let response = json["response"] + let items = response["items"].arrayValue + + let result = items.map{item -> PhotosVK in + let photos = PhotosVK() + let sizes = item["sizes"].arrayValue + if let first = sizes.first{ + photos.photo = first["url"].stringValue + } + + return photos + } + return result + }catch{ + print(error.localizedDescription) + return [] + } + } +} + +class PhotosRequest: PhotosServiceRequest { + + let parser: PhotosParser + + func save( photos: [PhotosVK] ) { + do { + let realm = try Realm() + let oldPhotos = realm.objects(PhotosVK.self) + realm.beginWrite() + realm.delete(oldPhotos) + realm.add(photos) + try realm.commitWrite() + }catch{ + print(error.localizedDescription) + } + + } + + init(parser: PhotosParser) { + self.parser = parser + } + + let userId = Session.shared.userId + let baseURL = "https://api.vk.com/method" + let apiKey = Session.shared.token + + func loadData (completion: @escaping () -> Void) { + let path = "/photos.getAll" + let url = baseURL + path + + let parameters: Parameters = [ + "owner_id": userId, + "v": "5.103", + "access_token": apiKey + ] + print("\(userId)") + Alamofire.request(url, method: .get, parameters: parameters).responseJSON { [completion] (response) in + guard let data = response.data else { return } + + let photos: [PhotosVK] = self.parser.parse(data: data) + self.save(photos: photos) + completion() + } + + } + +} diff --git a/less6/loginForm/Services/SearchGroupsRequest.swift b/less6/loginForm/Services/SearchGroupsRequest.swift new file mode 100644 index 0000000..85e8a9f --- /dev/null +++ b/less6/loginForm/Services/SearchGroupsRequest.swift @@ -0,0 +1,32 @@ +// +// SearchGroupsRequest.swift +// loginForm +// +// Created by prot on 17.03.2020. +// Copyright © 2020 prot. All rights reserved. +// + +import Foundation +import Alamofire + +class SearchGroupsRequest { + + let baseURL = "https://api.vk.com/method" + let apiKey = Session.shared.token + + func request (group: String) { + let path = "/groups.search" + let url = baseURL + path + + let parameters: Parameters = [ + "q": group, + "count": 5, + "v": "5.53", + "access_token": apiKey + ] + + Alamofire.request(url, method: .get, parameters: parameters).responseJSON { response in + print("Поиск групп \(response.value ?? "")") + } + } +} diff --git a/less6/loginForm/Services/Singleton.swift b/less6/loginForm/Services/Singleton.swift new file mode 100644 index 0000000..3b609eb --- /dev/null +++ b/less6/loginForm/Services/Singleton.swift @@ -0,0 +1,16 @@ +// +// Singleton.swift +// loginForm +// +// Created by prot on 14.03.2020. +// Copyright © 2020 prot. All rights reserved. +// + +import UIKit + +class Singleton { + private init() {} + static let shared: Singleton = .init() + var token: String? + var userId: Int? +} diff --git a/less6/loginForm/Session.swift b/less6/loginForm/Session.swift new file mode 100644 index 0000000..32f54e8 --- /dev/null +++ b/less6/loginForm/Session.swift @@ -0,0 +1,25 @@ +// +// Session.swift +// loginForm +// +// Created by prot on 17.03.2020. +// Copyright © 2020 prot. All rights reserved. +// + +import UIKit + +class Session { + private init() {} + static let shared: Session = .init() + var token = String() + var userId = Int() + + + func getImage (url:String?) -> UIImage?{ + guard let image = url else { return nil } + if let url = URL(string: image) { + return UIImage(data: try! Data(contentsOf: url)) + } + return nil + } +} diff --git a/less6/loginForm/TableCell.swift b/less6/loginForm/TableCell.swift new file mode 100644 index 0000000..d0b2dc6 --- /dev/null +++ b/less6/loginForm/TableCell.swift @@ -0,0 +1,24 @@ +// +// TableCell.swift +// loginForm +// +// Created by prot on 10/02/2020. +// Copyright © 2020 prot. All rights reserved. +// + +import UIKit + +class TableCell: UITableViewCell { + + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + } + +} diff --git a/less6/loginForm/VKAthorizationViewController.swift b/less6/loginForm/VKAthorizationViewController.swift new file mode 100644 index 0000000..5c238a8 --- /dev/null +++ b/less6/loginForm/VKAthorizationViewController.swift @@ -0,0 +1,65 @@ +// +// VKAthorizationViewController.swift +// loginForm +// +// Created by prot on 17.03.2020. +// Copyright © 2020 prot. All rights reserved. +// + +import UIKit +import WebKit + +class VKAthorizationViewController: UIViewController { + @IBOutlet weak var webView: WKWebView! + + override func viewDidLoad() { + super.viewDidLoad() + + var urlComponents = URLComponents() + urlComponents.scheme = "https" + urlComponents.host = "oauth.vk.com" + urlComponents.path = "/authorize" + urlComponents.queryItems = [ + URLQueryItem(name: "client_id", value: "7361851"), + URLQueryItem(name: "display", value: "mobile"), + URLQueryItem(name: "redirect_uri", value: "https://oauth.vk.com/blank.html"), + URLQueryItem(name: "scope", value: "262150"), + URLQueryItem(name: "response_type", value: "token"), + URLQueryItem(name: "v", value: "5.68") + ] + + let request = URLRequest(url: urlComponents.url!) + webView.navigationDelegate = self + webView.load(request) + + } +} + +extension VKAthorizationViewController: WKNavigationDelegate { + func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) { + + guard let url = navigationResponse.response.url, url.path == "/blank.html", let fragment = url.fragment else { + decisionHandler(.allow) + return + } + + let params = fragment + .components(separatedBy: "&") + .map { $0.components(separatedBy: "=") } + .reduce([String: String]()) { result, param in + var dict = result + let key = param[0] + let value = param[1] + dict[key] = value + return dict + } + + let token = params["access_token"] + + Session.shared.token = token ?? "" + print(token ?? "") + + + decisionHandler(.cancel) + } +} diff --git a/less6/loginForm/ViewController.swift b/less6/loginForm/ViewController.swift new file mode 100644 index 0000000..a57caf8 --- /dev/null +++ b/less6/loginForm/ViewController.swift @@ -0,0 +1,105 @@ +// +// ViewController.swift +// loginForm +// +// Created by prot on 30/01/2020. +// Copyright © 2020 prot. All rights reserved. +// + +import UIKit + +class LoginFormController: UIViewController { + + @IBOutlet weak var scrollView: UIScrollView! + @IBOutlet weak var textFieldLogin: UITextField! + @IBOutlet weak var textFieldPass: UITextField! + @IBOutlet weak var labelLogin: UILabel! + + + + + override func viewDidLoad() { + super.viewDidLoad() + // Do any additional setup after loading the view. + let tapGesture = UITapGestureRecognizer(target: self, action: #selector(hideKeyboard)) //переменная для закрытия клавитуры при тапе + scrollView.addGestureRecognizer(tapGesture) // закрытие клавитуры + } + + + func showInError() { + + let alertVC = UIAlertController(title: "Ошибка", message: "Неверный логин или пароль", preferredStyle: .alert) + let action = UIAlertAction(title: "Ok", style: .default) { _ in + print("Ок clicked") + } + alertVC.addAction(action) + + present(alertVC, animated: true, completion: nil) + } + + func checkLogin() -> Bool { + if let login = textFieldLogin.text, + let pass = textFieldPass.text { + + if login == "admin", pass == "admin" { + print("Успешная авторизация") + return true + }else { + print("Не успешная авторизация") + return false + } + };return false + } + + + override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool { + if checkLogin(){ + return true + }else{ + showInError() + return false + } + + } + + + + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + // Подписываемся на два уведомления: одно приходит при появлении клавиатуры + + NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShown(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil) + // Второе — когда она пропадает + NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil) + } + // Когда клавиатура появляется + @objc func keyboardWillShown ( notification : Notification) { + // Получаем размер клавиатуры + let info = notification.userInfo! as NSDictionary + let size = (info.value(forKey: UIResponder.keyboardFrameEndUserInfoKey) as! NSValue).cgRectValue.size + let contentInsents = UIEdgeInsets(top: 0, left: 0, bottom: size.height, right: 0) + // Добавляем отступ внизу UIScrollView, равный размеру клавиатуры + self.scrollView?.contentInset = contentInsents + self.scrollView.scrollIndicatorInsets = contentInsents + + } + //Когда клавиатура исчезает + @objc func keyboardWillHide ( notification : Notification) { + // Устанавливаем отступ внизу UIScrollView, равный 0 + scrollView.contentInset = .zero + + } + //клик по пустому месту на экране сворачивает клаву + @objc func hideKeyboard() { + self.scrollView.endEditing(true) + } + + @IBAction func exit( unwindSegue: UIStoryboardSegue) { + print("Welocme back") + } + + } + + diff --git a/less6/loginForm/test.xib b/less6/loginForm/test.xib new file mode 100644 index 0000000..75dea39 --- /dev/null +++ b/less6/loginForm/test.xib @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +