From 7711564cddf0c2d1fea4a7c9fc3d37f639dcc83f Mon Sep 17 00:00:00 2001 From: CMK Date: Tue, 28 Dec 2021 16:15:44 +0800 Subject: [PATCH 01/12] chore: remove Texture pod --- Mastodon.xcodeproj/project.pbxproj | 690 ------------------ .../xcschemes/xcschememanagement.plist | 14 +- Mastodon/Coordinator/SceneCoordinator.swift | 10 - .../Diffiable/DataSource/ASTableNode.swift | 85 --- .../TableNodeDiffableDataSource.swift | 115 --- .../Section/Status/StatusSection.swift | 31 - .../StatusProvider+StatusNodeDelegate.swift | 17 - .../StatusProvider/StatusProvider.swift | 16 - .../StatusProvider/StatusProviderFacade.swift | 11 - ...meTimelineViewController+DebugAction.swift | 384 ---------- ...cHomeTimelineViewController+Provider.swift | 123 ---- .../AsyncHomeTimelineViewController.swift | 573 --------------- .../AsyncHomeTimelineViewModel+Diffable.swift | 159 ---- ...omeTimelineViewModel+LoadLatestState.swift | 134 ---- ...omeTimelineViewModel+LoadMiddleState.swift | 112 --- ...omeTimelineViewModel+LoadOldestState.swift | 117 --- .../AsyncHomeTimelineViewModel.swift | 151 ---- .../Root/MainTab/MainTabBarController.swift | 34 - .../View/Node/ASMetaEditableTextNode.swift | 25 - .../Share/View/Node/Status/StatusNode.swift | 234 ------ .../Status/TimelineBottomLoaderNode.swift | 41 -- .../Status/TimelineMiddleLoaderNode.swift | 54 -- Mastodon/Supporting Files/AppDelegate.swift | 11 - Mastodon/Vender/ActivityIndicatorNode.swift | 75 -- Podfile | 5 +- Podfile.lock | 46 +- 26 files changed, 10 insertions(+), 3257 deletions(-) delete mode 100644 Mastodon/Diffiable/DataSource/ASTableNode.swift delete mode 100644 Mastodon/Diffiable/DataSource/TableNodeDiffableDataSource.swift delete mode 100644 Mastodon/Protocol/StatusProvider/StatusProvider+StatusNodeDelegate.swift delete mode 100644 Mastodon/Scene/HomeTimeline/AsyncHomeTimeline/AsyncHomeTimelineViewController+DebugAction.swift delete mode 100644 Mastodon/Scene/HomeTimeline/AsyncHomeTimeline/AsyncHomeTimelineViewController+Provider.swift delete mode 100644 Mastodon/Scene/HomeTimeline/AsyncHomeTimeline/AsyncHomeTimelineViewController.swift delete mode 100644 Mastodon/Scene/HomeTimeline/AsyncHomeTimeline/AsyncHomeTimelineViewModel+Diffable.swift delete mode 100644 Mastodon/Scene/HomeTimeline/AsyncHomeTimeline/AsyncHomeTimelineViewModel+LoadLatestState.swift delete mode 100644 Mastodon/Scene/HomeTimeline/AsyncHomeTimeline/AsyncHomeTimelineViewModel+LoadMiddleState.swift delete mode 100644 Mastodon/Scene/HomeTimeline/AsyncHomeTimeline/AsyncHomeTimelineViewModel+LoadOldestState.swift delete mode 100644 Mastodon/Scene/HomeTimeline/AsyncHomeTimeline/AsyncHomeTimelineViewModel.swift delete mode 100644 Mastodon/Scene/Share/View/Node/ASMetaEditableTextNode.swift delete mode 100644 Mastodon/Scene/Share/View/Node/Status/StatusNode.swift delete mode 100644 Mastodon/Scene/Share/View/Node/Status/TimelineBottomLoaderNode.swift delete mode 100644 Mastodon/Scene/Share/View/Node/Status/TimelineMiddleLoaderNode.swift delete mode 100644 Mastodon/Vender/ActivityIndicatorNode.swift diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index 6b7644e3..895b4aca 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -183,7 +183,6 @@ DB0140CF25C42AEE00F9F3CF /* OSLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0140CE25C42AEE00F9F3CF /* OSLog.swift */; }; DB01E23326A98F0900C3965B /* MastodonMeta in Frameworks */ = {isa = PBXBuildFile; productRef = DB01E23226A98F0900C3965B /* MastodonMeta */; }; DB01E23526A98F0900C3965B /* MetaTextKit in Frameworks */ = {isa = PBXBuildFile; productRef = DB01E23426A98F0900C3965B /* MetaTextKit */; }; - DB023295267F0AB800031745 /* ASMetaEditableTextNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB023294267F0AB800031745 /* ASMetaEditableTextNode.swift */; }; DB029E95266A20430062874E /* MastodonAuthenticationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB029E94266A20430062874E /* MastodonAuthenticationController.swift */; }; DB02CDAB26256A9500D0A2AF /* ThreadReplyLoaderTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB02CDAA26256A9500D0A2AF /* ThreadReplyLoaderTableViewCell.swift */; }; DB02CDBF2625AE5000D0A2AF /* AdaptiveUserInterfaceStyleBarButtonItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB02CDBE2625AE5000D0A2AF /* AdaptiveUserInterfaceStyleBarButtonItem.swift */; }; @@ -215,7 +214,6 @@ DB1D84382657B275000346B3 /* SegmentedControlNavigateable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB1D84372657B275000346B3 /* SegmentedControlNavigateable.swift */; }; DB1E346825F518E20079D7DF /* CategoryPickerSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB1E346725F518E20079D7DF /* CategoryPickerSection.swift */; }; DB1E347825F519300079D7DF /* PickServerItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB1E347725F519300079D7DF /* PickServerItem.swift */; }; - DB1EE7B2267F9525000CC337 /* StatusProvider+StatusNodeDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB1EE7B1267F9525000CC337 /* StatusProvider+StatusNodeDelegate.swift */; }; DB1FD43625F26899004CFCFC /* MastodonPickServerViewModel+LoadIndexedServerState.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB1FD43525F26899004CFCFC /* MastodonPickServerViewModel+LoadIndexedServerState.swift */; }; DB1FD44425F26CCC004CFCFC /* PickServerSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB1FD44325F26CCC004CFCFC /* PickServerSection.swift */; }; DB1FD45025F26FA1004CFCFC /* MastodonPickServerViewModel+Diffable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB1FD44F25F26FA1004CFCFC /* MastodonPickServerViewModel+Diffable.swift */; }; @@ -482,12 +480,6 @@ DBA94440265D137600C537E1 /* Mastodon+Entity+Field.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBA9443F265D137600C537E1 /* Mastodon+Entity+Field.swift */; }; DBABE3EC25ECAC4B00879EE5 /* WelcomeIllustrationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBABE3EB25ECAC4B00879EE5 /* WelcomeIllustrationView.swift */; }; DBAC6483267D0B21007FE9FD /* DifferenceKit in Frameworks */ = {isa = PBXBuildFile; productRef = DBAC6482267D0B21007FE9FD /* DifferenceKit */; }; - DBAC6485267D0F9E007FE9FD /* StatusNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBAC6484267D0F9E007FE9FD /* StatusNode.swift */; }; - DBAC6488267D388B007FE9FD /* ASTableNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBAC6487267D388B007FE9FD /* ASTableNode.swift */; }; - DBAC648F267DC84D007FE9FD /* TableNodeDiffableDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBAC648E267DC84D007FE9FD /* TableNodeDiffableDataSource.swift */; }; - DBAC6497267DECCB007FE9FD /* TimelineMiddleLoaderNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBAC6496267DECCB007FE9FD /* TimelineMiddleLoaderNode.swift */; }; - DBAC6499267DF2C4007FE9FD /* TimelineBottomLoaderNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBAC6498267DF2C4007FE9FD /* TimelineBottomLoaderNode.swift */; }; - DBAC649B267DF8C8007FE9FD /* ActivityIndicatorNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBAC649A267DF8C8007FE9FD /* ActivityIndicatorNode.swift */; }; DBAC649E267DFE43007FE9FD /* DiffableDataSources in Frameworks */ = {isa = PBXBuildFile; productRef = DBAC649D267DFE43007FE9FD /* DiffableDataSources */; }; DBAC64A1267E6D02007FE9FD /* Fuzi in Frameworks */ = {isa = PBXBuildFile; productRef = DBAC64A0267E6D02007FE9FD /* Fuzi */; }; DBAE3F682615DD60004B8251 /* UserProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBAE3F672615DD60004B8251 /* UserProvider.swift */; }; @@ -569,14 +561,6 @@ DBC7A672260C897100E57475 /* StatusContentWarningEditorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC7A671260C897100E57475 /* StatusContentWarningEditorView.swift */; }; DBC7A67C260DFADE00E57475 /* StatusPublishService.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC7A67B260DFADE00E57475 /* StatusPublishService.swift */; }; DBCBCBF4267CB070000F5B51 /* Decode85.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBCBCBF3267CB070000F5B51 /* Decode85.swift */; }; - DBCBCBFC2680ADB7000F5B51 /* AsyncHomeTimelineViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBCBCBFB2680ADB7000F5B51 /* AsyncHomeTimelineViewController.swift */; }; - DBCBCBFF2680AE98000F5B51 /* AsyncHomeTimelineViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBCBCBFE2680AE98000F5B51 /* AsyncHomeTimelineViewModel.swift */; }; - DBCBCC012680AF2A000F5B51 /* AsyncHomeTimelineViewModel+Diffable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBCBCC002680AF2A000F5B51 /* AsyncHomeTimelineViewModel+Diffable.swift */; }; - DBCBCC032680AF6E000F5B51 /* AsyncHomeTimelineViewController+DebugAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBCBCC022680AF6E000F5B51 /* AsyncHomeTimelineViewController+DebugAction.swift */; }; - DBCBCC052680AFB9000F5B51 /* AsyncHomeTimelineViewController+Provider.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBCBCC042680AFB9000F5B51 /* AsyncHomeTimelineViewController+Provider.swift */; }; - DBCBCC072680AFEC000F5B51 /* AsyncHomeTimelineViewModel+LoadLatestState.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBCBCC062680AFEC000F5B51 /* AsyncHomeTimelineViewModel+LoadLatestState.swift */; }; - DBCBCC092680B01B000F5B51 /* AsyncHomeTimelineViewModel+LoadMiddleState.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBCBCC082680B01B000F5B51 /* AsyncHomeTimelineViewModel+LoadMiddleState.swift */; }; - DBCBCC0B2680B03F000F5B51 /* AsyncHomeTimelineViewModel+LoadOldestState.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBCBCC0A2680B03F000F5B51 /* AsyncHomeTimelineViewModel+LoadOldestState.swift */; }; DBCBCC0D2680B908000F5B51 /* HomeTimelinePreference.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBCBCC0C2680B908000F5B51 /* HomeTimelinePreference.swift */; }; DBCBED1726132DB500B49291 /* UserTimelineViewModel+Diffable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBCBED1626132DB500B49291 /* UserTimelineViewModel+Diffable.swift */; }; DBCBED1D26132E1A00B49291 /* StatusFetchedResultsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBCBED1C26132E1A00B49291 /* StatusFetchedResultsController.swift */; }; @@ -977,7 +961,6 @@ DB0009A826AEE5DC009B9D2D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.intentdefinition; name = Base; path = Base.lproj/Intents.intentdefinition; sourceTree = ""; }; DB0009AD26AEE5E4009B9D2D /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/Intents.strings; sourceTree = ""; }; DB0140CE25C42AEE00F9F3CF /* OSLog.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OSLog.swift; sourceTree = ""; }; - DB023294267F0AB800031745 /* ASMetaEditableTextNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASMetaEditableTextNode.swift; sourceTree = ""; }; DB029E94266A20430062874E /* MastodonAuthenticationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonAuthenticationController.swift; sourceTree = ""; }; DB02CDAA26256A9500D0A2AF /* ThreadReplyLoaderTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadReplyLoaderTableViewCell.swift; sourceTree = ""; }; DB02CDBE2625AE5000D0A2AF /* AdaptiveUserInterfaceStyleBarButtonItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdaptiveUserInterfaceStyleBarButtonItem.swift; sourceTree = ""; }; @@ -1009,7 +992,6 @@ DB1D84372657B275000346B3 /* SegmentedControlNavigateable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SegmentedControlNavigateable.swift; sourceTree = ""; }; DB1E346725F518E20079D7DF /* CategoryPickerSection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CategoryPickerSection.swift; sourceTree = ""; }; DB1E347725F519300079D7DF /* PickServerItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PickServerItem.swift; sourceTree = ""; }; - DB1EE7B1267F9525000CC337 /* StatusProvider+StatusNodeDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "StatusProvider+StatusNodeDelegate.swift"; sourceTree = ""; }; DB1FD43525F26899004CFCFC /* MastodonPickServerViewModel+LoadIndexedServerState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MastodonPickServerViewModel+LoadIndexedServerState.swift"; sourceTree = ""; }; DB1FD44325F26CCC004CFCFC /* PickServerSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PickServerSection.swift; sourceTree = ""; }; DB1FD44F25F26FA1004CFCFC /* MastodonPickServerViewModel+Diffable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MastodonPickServerViewModel+Diffable.swift"; sourceTree = ""; }; @@ -1329,12 +1311,6 @@ DBA9443D265CFA6400C537E1 /* ProfileFieldCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileFieldCollectionViewCell.swift; sourceTree = ""; }; DBA9443F265D137600C537E1 /* Mastodon+Entity+Field.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Mastodon+Entity+Field.swift"; sourceTree = ""; }; DBABE3EB25ECAC4B00879EE5 /* WelcomeIllustrationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeIllustrationView.swift; sourceTree = ""; }; - DBAC6484267D0F9E007FE9FD /* StatusNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusNode.swift; sourceTree = ""; }; - DBAC6487267D388B007FE9FD /* ASTableNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASTableNode.swift; sourceTree = ""; }; - DBAC648E267DC84D007FE9FD /* TableNodeDiffableDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableNodeDiffableDataSource.swift; sourceTree = ""; }; - DBAC6496267DECCB007FE9FD /* TimelineMiddleLoaderNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineMiddleLoaderNode.swift; sourceTree = ""; }; - DBAC6498267DF2C4007FE9FD /* TimelineBottomLoaderNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineBottomLoaderNode.swift; sourceTree = ""; }; - DBAC649A267DF8C8007FE9FD /* ActivityIndicatorNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityIndicatorNode.swift; sourceTree = ""; }; DBAE3F672615DD60004B8251 /* UserProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProvider.swift; sourceTree = ""; }; DBAE3F812615DDA3004B8251 /* ProfileViewController+UserProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ProfileViewController+UserProvider.swift"; sourceTree = ""; }; DBAE3F872615DDF4004B8251 /* UserProviderFacade.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProviderFacade.swift; sourceTree = ""; }; @@ -1385,14 +1361,6 @@ DBC7A671260C897100E57475 /* StatusContentWarningEditorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusContentWarningEditorView.swift; sourceTree = ""; }; DBC7A67B260DFADE00E57475 /* StatusPublishService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusPublishService.swift; sourceTree = ""; }; DBCBCBF3267CB070000F5B51 /* Decode85.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Decode85.swift; sourceTree = ""; }; - DBCBCBFB2680ADB7000F5B51 /* AsyncHomeTimelineViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncHomeTimelineViewController.swift; sourceTree = ""; }; - DBCBCBFE2680AE98000F5B51 /* AsyncHomeTimelineViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncHomeTimelineViewModel.swift; sourceTree = ""; }; - DBCBCC002680AF2A000F5B51 /* AsyncHomeTimelineViewModel+Diffable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AsyncHomeTimelineViewModel+Diffable.swift"; sourceTree = ""; }; - DBCBCC022680AF6E000F5B51 /* AsyncHomeTimelineViewController+DebugAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AsyncHomeTimelineViewController+DebugAction.swift"; sourceTree = ""; }; - DBCBCC042680AFB9000F5B51 /* AsyncHomeTimelineViewController+Provider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AsyncHomeTimelineViewController+Provider.swift"; sourceTree = ""; }; - DBCBCC062680AFEC000F5B51 /* AsyncHomeTimelineViewModel+LoadLatestState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AsyncHomeTimelineViewModel+LoadLatestState.swift"; sourceTree = ""; }; - DBCBCC082680B01B000F5B51 /* AsyncHomeTimelineViewModel+LoadMiddleState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AsyncHomeTimelineViewModel+LoadMiddleState.swift"; sourceTree = ""; }; - DBCBCC0A2680B03F000F5B51 /* AsyncHomeTimelineViewModel+LoadOldestState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AsyncHomeTimelineViewModel+LoadOldestState.swift"; sourceTree = ""; }; DBCBCC0C2680B908000F5B51 /* HomeTimelinePreference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeTimelinePreference.swift; sourceTree = ""; }; DBCBED1626132DB500B49291 /* UserTimelineViewModel+Diffable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserTimelineViewModel+Diffable.swift"; sourceTree = ""; }; DBCBED1C26132E1A00B49291 /* StatusFetchedResultsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusFetchedResultsController.swift; sourceTree = ""; }; @@ -1737,7 +1705,6 @@ isa = PBXGroup; children = ( DB1F239626117C360057430E /* View */, - DBCBCBFD2680ADBA000F5B51 /* AsyncHomeTimeline */, 2D38F1D425CD465300561493 /* HomeTimelineViewController.swift */, 2D38F1DE25CD46A400561493 /* HomeTimelineViewController+Provider.swift */, 2D5A3D6125CFD9CB002347D6 /* HomeTimelineViewController+DebugAction.swift */, @@ -1756,7 +1723,6 @@ 2D38F1FD25CD481700561493 /* StatusProvider.swift */, 2DF75B9A25D0E27500694EC8 /* StatusProviderFacade.swift */, 2DF75BA025D0E29D00694EC8 /* StatusProvider+StatusTableViewCellDelegate.swift */, - DB1EE7B1267F9525000CC337 /* StatusProvider+StatusNodeDelegate.swift */, DB59F0FD25EF5D96001F1DAB /* StatusProvider+UITableViewDelegate.swift */, DB71FD4525F8C6D200512AE1 /* StatusProvider+UITableViewDataSourcePrefetching.swift */, DB1D843526579DB5000346B3 /* StatusProvider+TableViewControllerNavigateable.swift */, @@ -1811,7 +1777,6 @@ DB51D171262832380062B7A1 /* BlurHashEncode.swift */, DB6180EC26391C6C0018D199 /* TransitioningMath.swift */, DB75BF1D263C1C1B00EDBF1F /* CustomScheduler.swift */, - DBAC649A267DF8C8007FE9FD /* ActivityIndicatorNode.swift */, DBF156E32702DB3F00EC00B7 /* HandleTapAction.swift */, DBF156E12702DA6900EC00B7 /* UIStatusBarManager+HandleTapAction.m */, DBF156E02702DA6800EC00B7 /* Mastodon-Bridging-Header.h */, @@ -1893,7 +1858,6 @@ 2D76319D25C151F600929FB9 /* Section */, 2D7631B125C159E700929FB9 /* Item */, DBCBED2226132E1D00B49291 /* FetchedResultsController */, - DBAC6490267DC84F007FE9FD /* DataSource */, ); path = Diffiable; sourceTree = ""; @@ -1938,7 +1902,6 @@ DB87D45C2609DE6600D12C0D /* TextField */, DB1D187125EF5BBD003F1F23 /* TableView */, 2D7631A625C1533800929FB9 /* TableviewCell */, - DBAC6486267D0FAC007FE9FD /* Node */, ); path = View; sourceTree = ""; @@ -2120,16 +2083,6 @@ path = Onboarding; sourceTree = ""; }; - DB023296267F0ABE00031745 /* Status */ = { - isa = PBXGroup; - children = ( - DBAC6484267D0F9E007FE9FD /* StatusNode.swift */, - DBAC6496267DECCB007FE9FD /* TimelineMiddleLoaderNode.swift */, - DBAC6498267DF2C4007FE9FD /* TimelineBottomLoaderNode.swift */, - ); - path = Status; - sourceTree = ""; - }; DB03F7F1268990A2007B274C /* TableViewCell */ = { isa = PBXGroup; children = ( @@ -3044,24 +2997,6 @@ path = View; sourceTree = ""; }; - DBAC6486267D0FAC007FE9FD /* Node */ = { - isa = PBXGroup; - children = ( - DB023296267F0ABE00031745 /* Status */, - DB023294267F0AB800031745 /* ASMetaEditableTextNode.swift */, - ); - path = Node; - sourceTree = ""; - }; - DBAC6490267DC84F007FE9FD /* DataSource */ = { - isa = PBXGroup; - children = ( - DBAC6487267D388B007FE9FD /* ASTableNode.swift */, - DBAC648E267DC84D007FE9FD /* TableNodeDiffableDataSource.swift */, - ); - path = DataSource; - sourceTree = ""; - }; DBAE3F742615DD63004B8251 /* UserProvider */ = { isa = PBXGroup; children = ( @@ -3187,21 +3122,6 @@ path = ShareActionExtension; sourceTree = ""; }; - DBCBCBFD2680ADBA000F5B51 /* AsyncHomeTimeline */ = { - isa = PBXGroup; - children = ( - DBCBCBFB2680ADB7000F5B51 /* AsyncHomeTimelineViewController.swift */, - DBCBCC022680AF6E000F5B51 /* AsyncHomeTimelineViewController+DebugAction.swift */, - DBCBCC042680AFB9000F5B51 /* AsyncHomeTimelineViewController+Provider.swift */, - DBCBCBFE2680AE98000F5B51 /* AsyncHomeTimelineViewModel.swift */, - DBCBCC002680AF2A000F5B51 /* AsyncHomeTimelineViewModel+Diffable.swift */, - DBCBCC062680AFEC000F5B51 /* AsyncHomeTimelineViewModel+LoadLatestState.swift */, - DBCBCC082680B01B000F5B51 /* AsyncHomeTimelineViewModel+LoadMiddleState.swift */, - DBCBCC0A2680B03F000F5B51 /* AsyncHomeTimelineViewModel+LoadOldestState.swift */, - ); - path = AsyncHomeTimeline; - sourceTree = ""; - }; DBCBED2226132E1D00B49291 /* FetchedResultsController */ = { isa = PBXGroup; children = ( @@ -3969,7 +3889,6 @@ 0FAA0FDF25E0B57E0017CCDE /* WelcomeViewController.swift in Sources */, 2D206B8C25F6015000143C56 /* AudioPlaybackService.swift in Sources */, 2D59819B25E4A581000FB903 /* MastodonConfirmEmailViewController.swift in Sources */, - DBCBCBFC2680ADB7000F5B51 /* AsyncHomeTimelineViewController.swift in Sources */, DB45FB1D25CA9D23005A8AC7 /* APIService+HomeTimeline.swift in Sources */, DBA94440265D137600C537E1 /* Mastodon+Entity+Field.swift in Sources */, DB49A61425FF2C5600B98345 /* EmojiService.swift in Sources */, @@ -4016,12 +3935,10 @@ DB02CDAB26256A9500D0A2AF /* ThreadReplyLoaderTableViewCell.swift in Sources */, DB63BE7F268DD1070011D3F9 /* NotificationViewController+StatusProvider.swift in Sources */, DBB5255E2611F07A002F1F29 /* ProfileViewModel.swift in Sources */, - DBAC648F267DC84D007FE9FD /* TableNodeDiffableDataSource.swift in Sources */, 2D8434FB25FF46B300EECE90 /* HomeTimelineNavigationBarTitleView.swift in Sources */, 0F1E2D0B2615C39400C38565 /* DoubleTitleLabelNavigationBarTitleView.swift in Sources */, DBA1DB80268F84F80052DB59 /* NotificationType.swift in Sources */, DB9A488A26034D40008B817C /* ComposeViewModel+PublishState.swift in Sources */, - DBAC649B267DF8C8007FE9FD /* ActivityIndicatorNode.swift in Sources */, DB45FAD725CA6C76005A8AC7 /* UIBarButtonItem.swift in Sources */, 2DA504692601ADE7008F4E6C /* SawToothView.swift in Sources */, DBA465952696E387002B41DB /* AppPreference.swift in Sources */, @@ -4091,12 +4008,9 @@ 2D939AB525EDD8A90076FA61 /* String.swift in Sources */, DB4481B925EE289600BEFB67 /* UITableView.swift in Sources */, DBE3CDBB261C427900430CC6 /* TimelineHeaderTableViewCell.swift in Sources */, - DBCBCBFF2680AE98000F5B51 /* AsyncHomeTimelineViewModel.swift in Sources */, 0FAA101C25E10E760017CCDE /* UIFont.swift in Sources */, 2D38F1D525CD465300561493 /* HomeTimelineViewController.swift in Sources */, - DBAC6497267DECCB007FE9FD /* TimelineMiddleLoaderNode.swift in Sources */, DB97131F2666078B00BD1E90 /* Date.swift in Sources */, - DBAC6485267D0F9E007FE9FD /* StatusNode.swift in Sources */, DB98338825C945ED00AD9700 /* Assets.swift in Sources */, DB6180E926391BDF0018D199 /* MediaHostToMediaPreviewViewControllerAnimatedTransitioning.swift in Sources */, DB6B351E2601FAEE00DC1E11 /* ComposeStatusAttachmentCollectionViewCell.swift in Sources */, @@ -4156,7 +4070,6 @@ DBA5E7A5263BD28C004598BB /* ContextMenuImagePreviewViewModel.swift in Sources */, DB9D7C21269824B80054B3DF /* APIService+Filter.swift in Sources */, 2D38F1E525CD46C100561493 /* HomeTimelineViewModel.swift in Sources */, - DBCBCC012680AF2A000F5B51 /* AsyncHomeTimelineViewModel+Diffable.swift in Sources */, DBCC3B36261440BA0045B23D /* UINavigationController.swift in Sources */, DBB525852612D6DD002F1F29 /* ProfileStatusDashboardMeterView.swift in Sources */, 2D84350525FF858100EECE90 /* UIScrollView.swift in Sources */, @@ -4185,7 +4098,6 @@ 2D694A7425F9EB4E0038ADDC /* ContentWarningOverlayView.swift in Sources */, DB4932B126F1FB5300EF46D4 /* WizardCardView.swift in Sources */, DBAE3F682615DD60004B8251 /* UserProvider.swift in Sources */, - DBAC6488267D388B007FE9FD /* ASTableNode.swift in Sources */, DB6D9F76263587C7008423CD /* SettingFetchedResultController.swift in Sources */, DB9A486C26032AC1008B817C /* AttachmentContainerView+EmptyStateView.swift in Sources */, 5D0393902612D259007FE196 /* WebViewController.swift in Sources */, @@ -4220,7 +4132,6 @@ DB1D186C25EF5BA7003F1F23 /* PollTableView.swift in Sources */, DBA94434265CBB5300C537E1 /* ProfileFieldSection.swift in Sources */, DBF156E42702DB3F00EC00B7 /* HandleTapAction.swift in Sources */, - DB023295267F0AB800031745 /* ASMetaEditableTextNode.swift in Sources */, 2D5981A125E4A593000FB903 /* MastodonConfirmEmailViewModel.swift in Sources */, DB6B74F6272FBCDB00C70B6E /* FollowerListViewModel+State.swift in Sources */, DB4F096C269EFA2000D62E92 /* SearchResultViewController+StatusProvider.swift in Sources */, @@ -4248,7 +4159,6 @@ DB938EED2623F79B00E5B6C1 /* ThreadViewModel.swift in Sources */, DBBC24AC26A53D9300398BB9 /* ComposeStatusContentTableViewCell.swift in Sources */, DBC7A67C260DFADE00E57475 /* StatusPublishService.swift in Sources */, - DBCBCC092680B01B000F5B51 /* AsyncHomeTimelineViewModel+LoadMiddleState.swift in Sources */, 2DCB73FD2615C13900EC03D4 /* SearchRecommendCollectionHeader.swift in Sources */, DB852D1C26FB021500FC9D81 /* RootSplitViewController.swift in Sources */, DB02CDBF2625AE5000D0A2AF /* AdaptiveUserInterfaceStyleBarButtonItem.swift in Sources */, @@ -4264,7 +4174,6 @@ 0FB3D33825E6401400AAD544 /* PickServerCell.swift in Sources */, DB6D9F8426358EEC008423CD /* SettingsItem.swift in Sources */, 2D364F7825E66D8300204FDC /* MastodonResendEmailViewModel.swift in Sources */, - DBCBCC052680AFB9000F5B51 /* AsyncHomeTimelineViewController+Provider.swift in Sources */, DBA465932696B495002B41DB /* APIService+WebFinger.swift in Sources */, DB8AF54525C13647002E6C99 /* NeedsDependency.swift in Sources */, DB9D6BF825E4F5690051B173 /* NotificationViewController.swift in Sources */, @@ -4301,7 +4210,6 @@ 2DB72C8C262D764300CE6173 /* Mastodon+Entity+Notification+Type.swift in Sources */, 2D35237A26256D920031AF25 /* NotificationSection.swift in Sources */, DB084B5725CBC56C00F898ED /* Status.swift in Sources */, - DBCBCC072680AFEC000F5B51 /* AsyncHomeTimelineViewModel+LoadLatestState.swift in Sources */, 2D4AD89C263165B500613EFC /* SuggestionAccountCollectionViewCell.swift in Sources */, DB447691260B406600B66B82 /* CustomEmojiPickerItemCollectionViewCell.swift in Sources */, DB9282B225F3222800823B15 /* PickServerEmptyStateView.swift in Sources */, @@ -4326,7 +4234,6 @@ DB0C947226A7D2D70088FB11 /* AvatarButton.swift in Sources */, DB98336B25C9420100AD9700 /* APIService+App.swift in Sources */, DBFEF07B26A6BCE8006D7ED1 /* APIService+Status+Publish.swift in Sources */, - DBCBCC032680AF6E000F5B51 /* AsyncHomeTimelineViewController+DebugAction.swift in Sources */, DBA0A11325FB3FC10079C110 /* ComposeToolbarView.swift in Sources */, 2D32EADA25CBCC3300C9ED86 /* PublicTimelineViewModel+LoadMiddleState.swift in Sources */, 5B90C48526259BF10002E742 /* APIService+Subscriptions.swift in Sources */, @@ -4359,7 +4266,6 @@ DB71C7CD271D7F4300BE3819 /* CurveAlgorithm.swift in Sources */, DBD376B2269302A4007FEC24 /* UITableViewCell.swift in Sources */, DB4F0966269ED52200D62E92 /* SearchResultViewModel.swift in Sources */, - DBAC6499267DF2C4007FE9FD /* TimelineBottomLoaderNode.swift in Sources */, 2D76318325C14E8F00929FB9 /* PublicTimelineViewModel+Diffable.swift in Sources */, DBBF1DBF2652401B00E5B703 /* AutoCompleteViewModel.swift in Sources */, DB6180FA26391F2E0018D199 /* MediaPreviewViewModel.swift in Sources */, @@ -4390,7 +4296,6 @@ DB4F097B26A039FF00D62E92 /* SearchHistorySection.swift in Sources */, DBB525302611EBF3002F1F29 /* ProfilePagingViewModel.swift in Sources */, DB9F58EC26EF435000E7BBE9 /* AccountViewController.swift in Sources */, - DBCBCC0B2680B03F000F5B51 /* AsyncHomeTimelineViewModel+LoadOldestState.swift in Sources */, 2D5A3D6225CFD9CB002347D6 /* HomeTimelineViewController+DebugAction.swift in Sources */, DB49A62525FF334C00B98345 /* EmojiService+CustomEmojiViewModel+LoadState.swift in Sources */, DB4924E226312AB200E9DB22 /* NotificationService.swift in Sources */, @@ -4409,7 +4314,6 @@ DB3667A4268AE2370027D07F /* ComposeStatusPollTableViewCell.swift in Sources */, DBBF1DC226524D2900E5B703 /* AutoCompleteTableViewCell.swift in Sources */, 2D38F1FE25CD481700561493 /* StatusProvider.swift in Sources */, - DB1EE7B2267F9525000CC337 /* StatusProvider+StatusNodeDelegate.swift in Sources */, 5B24BBE2262DB19100A9381B /* APIService+Report.swift in Sources */, DBF3B7412733EB9400E21627 /* MastodonLocalCode.swift in Sources */, DB4F096A269EDAD200D62E92 /* SearchResultViewModel+State.swift in Sources */, @@ -5232,56 +5136,6 @@ }; name = Debug; }; - DB8FABD126AEC7B2008E5AF4 /* ASDK - Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = C3789232A52F43529CA67E95 /* Pods-MastodonIntent.asdk - debug.xcconfig */; - buildSettings = { - CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 88; - DEVELOPMENT_TEAM = 5Z4GVSS33P; - INFOPLIST_FILE = MastodonIntent/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@executable_path/../../Frameworks", - ); - MARKETING_VERSION = 1.0.7; - PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.MastodonIntent; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "APP_EXTENSION $(inherited)"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 1; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = "ASDK - Debug"; - }; - DB8FABD226AEC7B2008E5AF4 /* ASDK - Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = F920AD4EC23B0D00F5CCA58E /* Pods-MastodonIntent.asdk - release.xcconfig */; - buildSettings = { - CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 88; - DEVELOPMENT_TEAM = 5Z4GVSS33P; - INFOPLIST_FILE = MastodonIntent/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@executable_path/../../Frameworks", - ); - MARKETING_VERSION = 1.0.7; - PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.MastodonIntent; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "APP_EXTENSION $(inherited)"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 1; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = "ASDK - Release"; - }; DB8FABD326AEC7B2008E5AF4 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 159AC43EFE0A1F95FCB358A4 /* Pods-MastodonIntent.release.xcconfig */; @@ -5332,56 +5186,6 @@ }; name = Debug; }; - DBC6461E26A170AB00B0E31B /* ASDK - Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 6130CBE4B26E3C976ACC1688 /* Pods-ShareActionExtension.asdk - debug.xcconfig */; - buildSettings = { - CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 88; - DEVELOPMENT_TEAM = 5Z4GVSS33P; - INFOPLIST_FILE = ShareActionExtension/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@executable_path/../../Frameworks", - ); - MARKETING_VERSION = 1.0.7; - PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.ShareActionExtension; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "APP_EXTENSION $(inherited)"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 1; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = "ASDK - Debug"; - }; - DBC6461F26A170AB00B0E31B /* ASDK - Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 5CE45680252519F42FEA2D13 /* Pods-ShareActionExtension.asdk - release.xcconfig */; - buildSettings = { - CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 88; - DEVELOPMENT_TEAM = 5Z4GVSS33P; - INFOPLIST_FILE = ShareActionExtension/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@executable_path/../../Frameworks", - ); - MARKETING_VERSION = 1.0.7; - PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.ShareActionExtension; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "APP_EXTENSION $(inherited)"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 1; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = "ASDK - Release"; - }; DBC6462026A170AB00B0E31B /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 95AD0663479892A2109EEFD0 /* Pods-ShareActionExtension.release.xcconfig */; @@ -5407,480 +5211,6 @@ }; name = Release; }; - DBCBCC0E2680BE3E000F5B51 /* ASDK - Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - 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_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - 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; - INTENTS_CODEGEN_LANGUAGE = Swift; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = ASDK; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = "ASDK - Release"; - }; - DBCBCC0F2680BE3E000F5B51 /* ASDK - Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = BD7598A87F4497045EDEF252 /* Pods-Mastodon.asdk - release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 88; - DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; - DEVELOPMENT_TEAM = 5Z4GVSS33P; - INFOPLIST_FILE = Mastodon/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - MARKETING_VERSION = 1.0.7; - PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_OBJC_BRIDGING_HEADER = "Mastodon/Vender/Mastodon-Bridging-Header.h"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 1; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = "ASDK - Release"; - }; - DBCBCC102680BE3E000F5B51 /* ASDK - Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 46DAB0EBDDFB678347CD96FF /* Pods-MastodonTests.asdk - release.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 5Z4GVSS33P; - INFOPLIST_FILE = MastodonTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.MastodonTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Mastodon.app/Mastodon"; - }; - name = "ASDK - Release"; - }; - DBCBCC112680BE3E000F5B51 /* ASDK - Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 8850E70A1D5FF51432E43653 /* Pods-Mastodon-MastodonUITests.asdk - release.xcconfig */; - buildSettings = { - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 5Z4GVSS33P; - INFOPLIST_FILE = MastodonUITests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.MastodonUITests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - TEST_TARGET_NAME = Mastodon; - }; - name = "ASDK - Release"; - }; - DBCBCC122680BE3E000F5B51 /* ASDK - Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - APPLICATION_EXTENSION_API_ONLY = YES; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 88; - DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = 5Z4GVSS33P; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 88; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = CoreDataStack/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.CoreDataStack; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = "ASDK - Release"; - }; - DBCBCC132680BE3E000F5B51 /* ASDK - Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 5Z4GVSS33P; - INFOPLIST_FILE = CoreDataStackTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.CoreDataStackTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Mastodon.app/Mastodon"; - }; - name = "ASDK - Release"; - }; - DBCBCC142680BE3E000F5B51 /* ASDK - Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9CFF58FD900AC059428700E7 /* Pods-NotificationService.asdk - release.xcconfig */; - buildSettings = { - CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 88; - DEVELOPMENT_TEAM = 5Z4GVSS33P; - INFOPLIST_FILE = NotificationService/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@executable_path/../../Frameworks", - ); - MARKETING_VERSION = 1.0.7; - PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.NotificationService; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 1; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = "ASDK - Release"; - }; - DBCBCC152680BE3E000F5B51 /* ASDK - Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = DDB1B139FA8EA26F510D58B6 /* Pods-AppShared.asdk - release.xcconfig */; - buildSettings = { - APPLICATION_EXTENSION_API_ONLY = YES; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 88; - DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = 5Z4GVSS33P; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 88; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = AppShared/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.AppShared; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = "ASDK - Release"; - }; - DBCBCC1E26818F6F000F5B51 /* ASDK - Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - 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_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - 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; - INTENTS_CODEGEN_LANGUAGE = Swift; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG ASDK"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = "ASDK - Debug"; - }; - DBCBCC1F26818F6F000F5B51 /* ASDK - Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 1D6D967E77A5357E2C6110D9 /* Pods-Mastodon.asdk - debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 88; - DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; - DEVELOPMENT_TEAM = 5Z4GVSS33P; - INFOPLIST_FILE = Mastodon/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - MARKETING_VERSION = 1.0.7; - PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_OBJC_BRIDGING_HEADER = "Mastodon/Vender/Mastodon-Bridging-Header.h"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 1; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = "ASDK - Debug"; - }; - DBCBCC2026818F6F000F5B51 /* ASDK - Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7CEFFAE9AF9284B13C0A758D /* Pods-MastodonTests.asdk - debug.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 5Z4GVSS33P; - INFOPLIST_FILE = MastodonTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.MastodonTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Mastodon.app/Mastodon"; - }; - name = "ASDK - Debug"; - }; - DBCBCC2126818F6F000F5B51 /* ASDK - Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = E5C7236E58D14A0322FE00F2 /* Pods-Mastodon-MastodonUITests.asdk - debug.xcconfig */; - buildSettings = { - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 5Z4GVSS33P; - INFOPLIST_FILE = MastodonUITests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.MastodonUITests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - TEST_TARGET_NAME = Mastodon; - }; - name = "ASDK - Debug"; - }; - DBCBCC2226818F6F000F5B51 /* ASDK - Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - APPLICATION_EXTENSION_API_ONLY = YES; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 88; - DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = 5Z4GVSS33P; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 88; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = CoreDataStack/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.CoreDataStack; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = "ASDK - Debug"; - }; - DBCBCC2326818F6F000F5B51 /* ASDK - Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 5Z4GVSS33P; - INFOPLIST_FILE = CoreDataStackTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.CoreDataStackTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Mastodon.app/Mastodon"; - }; - name = "ASDK - Debug"; - }; - DBCBCC2426818F6F000F5B51 /* ASDK - Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 3B7FD8F28DDA8FBCE5562B78 /* Pods-NotificationService.asdk - debug.xcconfig */; - buildSettings = { - CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 88; - DEVELOPMENT_TEAM = 5Z4GVSS33P; - INFOPLIST_FILE = NotificationService/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@executable_path/../../Frameworks", - ); - MARKETING_VERSION = 1.0.7; - PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.NotificationService; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 1; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = "ASDK - Debug"; - }; - DBCBCC2526818F6F000F5B51 /* ASDK - Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = A9B1FB898DFD6063B044298C /* Pods-AppShared.asdk - debug.xcconfig */; - buildSettings = { - APPLICATION_EXTENSION_API_ONLY = YES; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 88; - DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = 5Z4GVSS33P; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 88; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = AppShared/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.AppShared; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = "ASDK - Debug"; - }; DBF8AE1C263293E400C9C23C /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 9553C689FFA9EBC880CAB78D /* Pods-NotificationService.debug.xcconfig */; @@ -5936,8 +5266,6 @@ isa = XCConfigurationList; buildConfigurations = ( DB427DFA25BAA00100D1B89D /* Debug */, - DBCBCC1E26818F6F000F5B51 /* ASDK - Debug */, - DBCBCC0E2680BE3E000F5B51 /* ASDK - Release */, DB427DFB25BAA00100D1B89D /* Release */, ); defaultConfigurationIsVisible = 0; @@ -5947,8 +5275,6 @@ isa = XCConfigurationList; buildConfigurations = ( DB427DFD25BAA00100D1B89D /* Debug */, - DBCBCC1F26818F6F000F5B51 /* ASDK - Debug */, - DBCBCC0F2680BE3E000F5B51 /* ASDK - Release */, DB427DFE25BAA00100D1B89D /* Release */, ); defaultConfigurationIsVisible = 0; @@ -5958,8 +5284,6 @@ isa = XCConfigurationList; buildConfigurations = ( DB427E0025BAA00100D1B89D /* Debug */, - DBCBCC2026818F6F000F5B51 /* ASDK - Debug */, - DBCBCC102680BE3E000F5B51 /* ASDK - Release */, DB427E0125BAA00100D1B89D /* Release */, ); defaultConfigurationIsVisible = 0; @@ -5969,8 +5293,6 @@ isa = XCConfigurationList; buildConfigurations = ( DB427E0325BAA00100D1B89D /* Debug */, - DBCBCC2126818F6F000F5B51 /* ASDK - Debug */, - DBCBCC112680BE3E000F5B51 /* ASDK - Release */, DB427E0425BAA00100D1B89D /* Release */, ); defaultConfigurationIsVisible = 0; @@ -5980,8 +5302,6 @@ isa = XCConfigurationList; buildConfigurations = ( DB6804892637CD4C00430867 /* Debug */, - DBCBCC2526818F6F000F5B51 /* ASDK - Debug */, - DBCBCC152680BE3E000F5B51 /* ASDK - Release */, DB68048A2637CD4C00430867 /* Release */, ); defaultConfigurationIsVisible = 0; @@ -5991,8 +5311,6 @@ isa = XCConfigurationList; buildConfigurations = ( DB89BA0625C10FD0008580ED /* Debug */, - DBCBCC2226818F6F000F5B51 /* ASDK - Debug */, - DBCBCC122680BE3E000F5B51 /* ASDK - Release */, DB89BA0725C10FD0008580ED /* Release */, ); defaultConfigurationIsVisible = 0; @@ -6002,8 +5320,6 @@ isa = XCConfigurationList; buildConfigurations = ( DB89BA0A25C10FD0008580ED /* Debug */, - DBCBCC2326818F6F000F5B51 /* ASDK - Debug */, - DBCBCC132680BE3E000F5B51 /* ASDK - Release */, DB89BA0B25C10FD0008580ED /* Release */, ); defaultConfigurationIsVisible = 0; @@ -6013,8 +5329,6 @@ isa = XCConfigurationList; buildConfigurations = ( DB8FABD026AEC7B2008E5AF4 /* Debug */, - DB8FABD126AEC7B2008E5AF4 /* ASDK - Debug */, - DB8FABD226AEC7B2008E5AF4 /* ASDK - Release */, DB8FABD326AEC7B2008E5AF4 /* Release */, ); defaultConfigurationIsVisible = 0; @@ -6024,8 +5338,6 @@ isa = XCConfigurationList; buildConfigurations = ( DBC6461D26A170AB00B0E31B /* Debug */, - DBC6461E26A170AB00B0E31B /* ASDK - Debug */, - DBC6461F26A170AB00B0E31B /* ASDK - Release */, DBC6462026A170AB00B0E31B /* Release */, ); defaultConfigurationIsVisible = 0; @@ -6035,8 +5347,6 @@ isa = XCConfigurationList; buildConfigurations = ( DBF8AE1C263293E400C9C23C /* Debug */, - DBCBCC2426818F6F000F5B51 /* ASDK - Debug */, - DBCBCC142680BE3E000F5B51 /* ASDK - Release */, DBF8AE1D263293E400C9C23C /* Release */, ); defaultConfigurationIsVisible = 0; diff --git a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist index 5c99e944..55e94fa7 100644 --- a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist @@ -7,17 +7,17 @@ AppShared.xcscheme_^#shared#^_ orderHint - 44 + 24 CoreDataStack.xcscheme_^#shared#^_ orderHint - 45 + 26 Mastodon - ASDK.xcscheme_^#shared#^_ orderHint - 4 + 2 Mastodon - RTL.xcscheme_^#shared#^_ @@ -27,7 +27,7 @@ Mastodon - Release.xcscheme_^#shared#^_ orderHint - 3 + 1 Mastodon - ar.xcscheme_^#shared#^_ @@ -102,7 +102,7 @@ MastodonIntent.xcscheme_^#shared#^_ orderHint - 43 + 27 MastodonIntents.xcscheme_^#shared#^_ @@ -117,12 +117,12 @@ NotificationService.xcscheme_^#shared#^_ orderHint - 7 + 3 ShareActionExtension.xcscheme_^#shared#^_ orderHint - 42 + 25 SuppressBuildableAutocreation diff --git a/Mastodon/Coordinator/SceneCoordinator.swift b/Mastodon/Coordinator/SceneCoordinator.swift index 9fbb2b77..c10b60d4 100644 --- a/Mastodon/Coordinator/SceneCoordinator.swift +++ b/Mastodon/Coordinator/SceneCoordinator.swift @@ -157,11 +157,6 @@ extension SceneCoordinator { case mastodonConfirmEmail(viewModel: MastodonConfirmEmailViewModel) case mastodonResendEmail(viewModel: MastodonResendEmailViewModel) case mastodonWebView(viewModel:WebViewModel) - - #if ASDK - // ASDK - case asyncHome - #endif // search case searchDetail(viewModel: SearchDetailViewModel) @@ -412,11 +407,6 @@ private extension SceneCoordinator { let _viewController = WebViewController() _viewController.viewModel = viewModel viewController = _viewController - #if ASDK - case .asyncHome: - let _viewController = AsyncHomeTimelineViewController() - viewController = _viewController - #endif case .searchDetail(let viewModel): let _viewController = SearchDetailViewController() _viewController.viewModel = viewModel diff --git a/Mastodon/Diffiable/DataSource/ASTableNode.swift b/Mastodon/Diffiable/DataSource/ASTableNode.swift deleted file mode 100644 index 36ff1fb0..00000000 --- a/Mastodon/Diffiable/DataSource/ASTableNode.swift +++ /dev/null @@ -1,85 +0,0 @@ -// -// ASTableNode.swift -// Mastodon -// -// Created by Cirno MainasuK on 2021-6-19. -// - -#if ASDK - -import UIKit -import AsyncDisplayKit -import DifferenceKit -import DiffableDataSources - -extension ASTableNode: ReloadableTableView { - public func reload( - using stagedChangeset: StagedChangeset, - deleteSectionsAnimation: @autoclosure () -> UITableView.RowAnimation, - insertSectionsAnimation: @autoclosure () -> UITableView.RowAnimation, - reloadSectionsAnimation: @autoclosure () -> UITableView.RowAnimation, - deleteRowsAnimation: @autoclosure () -> UITableView.RowAnimation, - insertRowsAnimation: @autoclosure () -> UITableView.RowAnimation, - reloadRowsAnimation: @autoclosure () -> UITableView.RowAnimation, - interrupt: ((Changeset) -> Bool)? = nil, - setData: (C) -> Void - ) { - if case .none = view.window, let data = stagedChangeset.last?.data { - setData(data) - return reloadData() - } - - for changeset in stagedChangeset { - if let interrupt = interrupt, interrupt(changeset), let data = stagedChangeset.last?.data { - setData(data) - return reloadData() - } - - func updates() { - setData(changeset.data) - - if !changeset.sectionDeleted.isEmpty { - deleteSections(IndexSet(changeset.sectionDeleted), with: deleteSectionsAnimation()) - } - - if !changeset.sectionInserted.isEmpty { - insertSections(IndexSet(changeset.sectionInserted), with: insertSectionsAnimation()) - } - - if !changeset.sectionUpdated.isEmpty { - reloadSections(IndexSet(changeset.sectionUpdated), with: reloadSectionsAnimation()) - } - - for (source, target) in changeset.sectionMoved { - moveSection(source, toSection: target) - } - - if !changeset.elementDeleted.isEmpty { - deleteRows(at: changeset.elementDeleted.map { IndexPath(row: $0.element, section: $0.section) }, with: deleteRowsAnimation()) - } - - if !changeset.elementInserted.isEmpty { - insertRows(at: changeset.elementInserted.map { IndexPath(row: $0.element, section: $0.section) }, with: insertRowsAnimation()) - } - - if !changeset.elementUpdated.isEmpty { - reloadRows(at: changeset.elementUpdated.map { IndexPath(row: $0.element, section: $0.section) }, with: reloadRowsAnimation()) - } - - for (source, target) in changeset.elementMoved { - moveRow(at: IndexPath(row: source.element, section: source.section), to: IndexPath(row: target.element, section: target.section)) - } - } - - if isNodeLoaded { - view.beginUpdates() - updates() - view.endUpdates(animated: false, completion: nil) - } else { - updates() - } - } - } -} - -#endif diff --git a/Mastodon/Diffiable/DataSource/TableNodeDiffableDataSource.swift b/Mastodon/Diffiable/DataSource/TableNodeDiffableDataSource.swift deleted file mode 100644 index 54ab22a4..00000000 --- a/Mastodon/Diffiable/DataSource/TableNodeDiffableDataSource.swift +++ /dev/null @@ -1,115 +0,0 @@ -// -// TableNodeDiffableDataSource.swift -// Mastodon -// -// Created by Cirno MainasuK on 2021-6-19. -// - -#if ASDK - -import UIKit -import AsyncDisplayKit -import DiffableDataSources - -open class TableNodeDiffableDataSource: NSObject, ASTableDataSource { - /// The type of closure providing the cell. - public typealias CellProvider = (ASTableNode, IndexPath, ItemIdentifierType) -> ASCellNodeBlock? - - /// The default animation to updating the views. - public var defaultRowAnimation: UITableView.RowAnimation = .automatic - - private weak var tableNode: ASTableNode? - private let cellProvider: CellProvider - private let core = DiffableDataSourceCore() - - /// Creates a new data source. - /// - /// - Parameters: - /// - tableView: A table view instance to be managed. - /// - cellProvider: A closure to dequeue the cell for rows. - public init(tableNode: ASTableNode, cellProvider: @escaping CellProvider) { - self.tableNode = tableNode - self.cellProvider = cellProvider - super.init() - - tableNode.delegate = self - } - - /// Applies given snapshot to perform automatic diffing update. - /// - /// - Parameters: - /// - snapshot: A snapshot object to be applied to data model. - /// - animatingDifferences: A Boolean value indicating whether to update with - /// diffing animation. - /// - completion: An optional completion block which is called when the complete - /// performing updates. - public func apply(_ snapshot: DiffableDataSourceSnapshot, animatingDifferences: Bool = true, completion: (() -> Void)? = nil) { - core.apply(snapshot, view: tableNode, animatingDifferences: animatingDifferences, completion: completion) - } - - /// Returns a new snapshot object of current state. - /// - /// - Returns: A new snapshot object of current state. - public func snapshot() -> DiffableDataSourceSnapshot { - return core.snapshot() - } - - /// Returns an item identifier for given index path. - /// - /// - Parameters: - /// - indexPath: An index path for the item identifier. - /// - /// - Returns: An item identifier for given index path. - public func itemIdentifier(for indexPath: IndexPath) -> ItemIdentifierType? { - return core.itemIdentifier(for: indexPath) - } - - /// Returns an index path for given item identifier. - /// - /// - Parameters: - /// - itemIdentifier: An identifier of item. - /// - /// - Returns: An index path for given item identifier. - public func indexPath(for itemIdentifier: ItemIdentifierType) -> IndexPath? { - return core.indexPath(for: itemIdentifier) - } - - /// Returns the number of sections in the data source. - /// - /// - Parameters: - /// - tableNode: A table node instance managed by `self`. - /// - /// - Returns: The number of sections in the data source. - public func numberOfSections(in tableNode: ASTableNode) -> Int { - return core.numberOfSections() - } - - /// Returns the number of items in the specified section. - /// - /// - Parameters: - /// - tableNode: A table node instance managed by `self`. - /// - section: An index of section. - /// - /// - Returns: The number of items in the specified section. - public func tableNode(_ tableNode: ASTableNode, numberOfRowsInSection section: Int) -> Int { - return core.numberOfItems(inSection: section) - } - - /// Returns a cell for row at specified index path. - /// - /// - Parameters: - /// - tableView: A table view instance managed by `self`. - /// - indexPath: An index path for cell. - /// - /// - Returns: A cell for row at specified index path. - open func tableNode(_ tableNode: ASTableNode, nodeBlockForRowAt indexPath: IndexPath) -> ASCellNodeBlock { - let itemIdentifier = core.unsafeItemIdentifier(for: indexPath) - guard let block = cellProvider(tableNode, indexPath, itemIdentifier) else { - fatalError("UITableView dataSource returned a nil cell for row at index path: \(indexPath), tableNode: \(tableNode), itemIdentifier: \(itemIdentifier)") - } - - return block - } -} - -#endif diff --git a/Mastodon/Diffiable/Section/Status/StatusSection.swift b/Mastodon/Diffiable/Section/Status/StatusSection.swift index 61217c79..918b8b45 100644 --- a/Mastodon/Diffiable/Section/Status/StatusSection.swift +++ b/Mastodon/Diffiable/Section/Status/StatusSection.swift @@ -18,10 +18,6 @@ import NaturalLanguage // import LinkPresentation -#if ASDK -import AsyncDisplayKit -#endif - protocol StatusCell: DisposeBagCollectable { var statusView: StatusView { get } var isFiltered: Bool { get set } @@ -32,33 +28,6 @@ enum StatusSection: Equatable, Hashable { } extension StatusSection { - #if ASDK - static func tableNodeDiffableDataSource( - tableNode: ASTableNode, - managedObjectContext: NSManagedObjectContext - ) -> TableNodeDiffableDataSource { - TableNodeDiffableDataSource(tableNode: tableNode) { tableNode, indexPath, item in - switch item { - case .homeTimelineIndex(let objectID, let attribute): - guard let homeTimelineIndex = try? managedObjectContext.existingObject(with: objectID) as? HomeTimelineIndex else { - return { ASCellNode() } - } - let status = homeTimelineIndex.status - - return { () -> ASCellNode in - let cellNode = StatusNode(status: status) - return cellNode - } - case .homeMiddleLoader: - return { TimelineMiddleLoaderNode() } - case .bottomLoader: - return { TimelineBottomLoaderNode() } - default: - return { ASCellNode() } - } - } - } - #endif static let logger = Logger(subsystem: "StatusSection", category: "logic") diff --git a/Mastodon/Protocol/StatusProvider/StatusProvider+StatusNodeDelegate.swift b/Mastodon/Protocol/StatusProvider/StatusProvider+StatusNodeDelegate.swift deleted file mode 100644 index 3c6d7da1..00000000 --- a/Mastodon/Protocol/StatusProvider/StatusProvider+StatusNodeDelegate.swift +++ /dev/null @@ -1,17 +0,0 @@ -// -// StatusProvider+StatusNodeDelegate.swift -// Mastodon -// -// Created by Cirno MainasuK on 2021-6-20. -// - -#if ASDK - -import Foundation - -// MARK: - StatusViewDelegate -extension StatusNodeDelegate where Self: StatusProvider { - -} - -#endif diff --git a/Mastodon/Protocol/StatusProvider/StatusProvider.swift b/Mastodon/Protocol/StatusProvider/StatusProvider.swift index 3497fd7a..2f13b8d5 100644 --- a/Mastodon/Protocol/StatusProvider/StatusProvider.swift +++ b/Mastodon/Protocol/StatusProvider/StatusProvider.swift @@ -10,10 +10,6 @@ import Combine import CoreData import CoreDataStack -#if ASDK -import AsyncDisplayKit -#endif - protocol StatusProvider: NeedsDependency & DisposeBagCollectable & UIViewController { // async func status() -> Future @@ -31,20 +27,8 @@ protocol StatusProvider: NeedsDependency & DisposeBagCollectable & UIViewControl func items(indexPaths: [IndexPath]) -> [Item] func statusObjectItems(indexPaths: [IndexPath]) -> [StatusObjectItem] - - #if ASDK - func status(node: ASCellNode?, indexPath: IndexPath?) -> Status? - #endif } -#if ASDK -extension StatusProvider { - func status(node: ASCellNode?, indexPath: IndexPath?) -> Status? { - fatalError("Needs implement this") - } -} -#endif - enum StatusObjectItem { case status(objectID: NSManagedObjectID) case homeTimelineIndex(objectID: NSManagedObjectID) diff --git a/Mastodon/Protocol/StatusProvider/StatusProviderFacade.swift b/Mastodon/Protocol/StatusProvider/StatusProviderFacade.swift index d11870ed..68987c30 100644 --- a/Mastodon/Protocol/StatusProvider/StatusProviderFacade.swift +++ b/Mastodon/Protocol/StatusProvider/StatusProviderFacade.swift @@ -14,10 +14,6 @@ import MastodonSDK import Meta import MetaTextKit -#if ASDK -import AsyncDisplayKit -#endif - enum StatusProviderFacade { } extension StatusProviderFacade { @@ -154,13 +150,6 @@ extension StatusProviderFacade { } } - #if ASDK - private static func coordinateToStatusMentionProfileScene(for target: Target, provider: StatusProvider, node: ASCellNode, mention: String) { - guard let status = provider.status(node: node, indexPath: nil) else { return } - coordinateToStatusMentionProfileScene(for: target, provider: provider, status: status, mention: mention, href: nil) - } - #endif - private static func coordinateToStatusMentionProfileScene(for target: Target, provider: StatusProvider, cell: UITableViewCell, mention: String, href: String?) { provider.status(for: cell, indexPath: nil) .sink { [weak provider] status in diff --git a/Mastodon/Scene/HomeTimeline/AsyncHomeTimeline/AsyncHomeTimelineViewController+DebugAction.swift b/Mastodon/Scene/HomeTimeline/AsyncHomeTimeline/AsyncHomeTimelineViewController+DebugAction.swift deleted file mode 100644 index 19c3244c..00000000 --- a/Mastodon/Scene/HomeTimeline/AsyncHomeTimeline/AsyncHomeTimelineViewController+DebugAction.swift +++ /dev/null @@ -1,384 +0,0 @@ -// -// AsyncHomeTimelineViewController+DebugAction.swift -// Mastodon -// -// Created by MainasuK Cirno on 2021-6-21. -// - -#if ASDK && DEBUG - -import os.log -import UIKit -import CoreData -import CoreDataStack -import FLEX - -extension AsyncHomeTimelineViewController { - var debugMenu: UIMenu { - let menu = UIMenu( - title: "Debug Tools", - image: nil, - identifier: nil, - options: .displayInline, - children: [ - UIAction(title: "Show FLEX", image: nil, attributes: [], handler: { [weak self] action in - guard let self = self else { return } - self.showFLEXAction(action) - }), - moveMenu, - dropMenu, - UIAction(title: "Show Welcome", image: UIImage(systemName: "figure.walk"), attributes: []) { [weak self] action in - guard let self = self else { return } - self.showWelcomeAction(action) - }, - UIAction(title: "Show Or Remove EmptyView", image: UIImage(systemName: "clear"), attributes: []) { [weak self] action in - guard let self = self else { return } - if self.emptyView.superview != nil { - self.emptyView.removeFromSuperview() - } else { - self.showEmptyView() - } - }, - UIAction(title: "Show Public Timeline", image: UIImage(systemName: "list.dash"), attributes: []) { [weak self] action in - guard let self = self else { return } - self.showPublicTimelineAction(action) - }, - UIAction(title: "Show Profile", image: UIImage(systemName: "person.crop.circle"), attributes: []) { [weak self] action in - guard let self = self else { return } - self.showProfileAction(action) - }, - UIAction(title: "Show Thread", image: UIImage(systemName: "bubble.left.and.bubble.right"), attributes: []) { [weak self] action in - guard let self = self else { return } - self.showThreadAction(action) - }, - UIAction(title: "Settings", image: UIImage(systemName: "gear"), attributes: []) { [weak self] action in - guard let self = self else { return } - self.showSettings(action) - }, - UIAction(title: "Sign Out", image: UIImage(systemName: "escape"), attributes: .destructive) { [weak self] action in - guard let self = self else { return } - self.signOutAction(action) - } - ] - ) - return menu - } - - var moveMenu: UIMenu { - return UIMenu( - title: "Move to…", - image: UIImage(systemName: "arrow.forward.circle"), - identifier: nil, - options: [], - children: [ - UIAction(title: "First Gap", image: nil, attributes: [], handler: { [weak self] action in - guard let self = self else { return } - self.moveToTopGapAction(action) - }), - UIAction(title: "First Replied Status", image: nil, attributes: [], handler: { [weak self] action in - guard let self = self else { return } - self.moveToFirstRepliedStatus(action) - }), - UIAction(title: "First Reblog Status", image: nil, attributes: [], handler: { [weak self] action in - guard let self = self else { return } - self.moveToFirstReblogStatus(action) - }), - UIAction(title: "First Poll Status", image: nil, attributes: [], handler: { [weak self] action in - guard let self = self else { return } - self.moveToFirstPollStatus(action) - }), - UIAction(title: "First Audio Status", image: nil, attributes: [], handler: { [weak self] action in - guard let self = self else { return } - self.moveToFirstAudioStatus(action) - }), - UIAction(title: "First Video Status", image: nil, attributes: [], handler: { [weak self] action in - guard let self = self else { return } - self.moveToFirstVideoStatus(action) - }), - UIAction(title: "First GIF status", image: nil, attributes: [], handler: { [weak self] action in - guard let self = self else { return } - self.moveToFirstGIFStatus(action) - }), - ] - ) - } - - var dropMenu: UIMenu { - return UIMenu( - title: "Drop…", - image: UIImage(systemName: "minus.circle"), - identifier: nil, - options: [], - children: [10, 50, 100, 150, 200, 250, 300].map { count in - UIAction(title: "Drop Recent \(count) Statuses", image: nil, attributes: [], handler: { [weak self] action in - guard let self = self else { return } - self.dropRecentStatusAction(action, count: count) - }) - } - ) - } -} - -extension AsyncHomeTimelineViewController { - - @objc private func showFLEXAction(_ sender: UIAction) { - FLEXManager.shared.showExplorer() - } - - @objc private func moveToTopGapAction(_ sender: UIAction) { - guard let diffableDataSource = viewModel.diffableDataSource else { return } - let snapshotTransitioning = diffableDataSource.snapshot() - let item = snapshotTransitioning.itemIdentifiers.first(where: { item in - switch item { - case .homeMiddleLoader: return true - default: return false - } - }) - if let targetItem = item, let index = snapshotTransitioning.indexOfItem(targetItem) { - tableView.scrollToRow(at: IndexPath(row: index, section: 0), at: .middle, animated: true) - } - } - - @objc private func moveToFirstReblogStatus(_ sender: UIAction) { - guard let diffableDataSource = viewModel.diffableDataSource else { return } - let snapshotTransitioning = diffableDataSource.snapshot() - let item = snapshotTransitioning.itemIdentifiers.first(where: { item in - switch item { - case .homeTimelineIndex(let objectID, _): - let homeTimelineIndex = viewModel.fetchedResultsController.managedObjectContext.object(with: objectID) as! HomeTimelineIndex - return homeTimelineIndex.status.reblog != nil - default: - return false - } - }) - if let targetItem = item, let index = snapshotTransitioning.indexOfItem(targetItem) { - tableView.scrollToRow(at: IndexPath(row: index, section: 0), at: .middle, animated: true) - tableView.blinkRow(at: IndexPath(row: index, section: 0)) - } else { - print("Not found reblog status") - } - } - - @objc private func moveToFirstPollStatus(_ sender: UIAction) { - guard let diffableDataSource = viewModel.diffableDataSource else { return } - let snapshotTransitioning = diffableDataSource.snapshot() - let item = snapshotTransitioning.itemIdentifiers.first(where: { item in - switch item { - case .homeTimelineIndex(let objectID, _): - let homeTimelineIndex = viewModel.fetchedResultsController.managedObjectContext.object(with: objectID) as! HomeTimelineIndex - let post = homeTimelineIndex.status.reblog ?? homeTimelineIndex.status - return post.poll != nil - default: - return false - } - }) - if let targetItem = item, let index = snapshotTransitioning.indexOfItem(targetItem) { - tableView.scrollToRow(at: IndexPath(row: index, section: 0), at: .middle, animated: true) - tableView.blinkRow(at: IndexPath(row: index, section: 0)) - } else { - print("Not found poll status") - } - } - - @objc private func moveToFirstRepliedStatus(_ sender: UIAction) { - guard let diffableDataSource = viewModel.diffableDataSource else { return } - let snapshotTransitioning = diffableDataSource.snapshot() - let item = snapshotTransitioning.itemIdentifiers.first(where: { item in - switch item { - case .homeTimelineIndex(let objectID, _): - let homeTimelineIndex = viewModel.fetchedResultsController.managedObjectContext.object(with: objectID) as! HomeTimelineIndex - guard homeTimelineIndex.status.inReplyToID != nil else { - return false - } - return true - default: - return false - } - }) - if let targetItem = item, let index = snapshotTransitioning.indexOfItem(targetItem) { - tableView.scrollToRow(at: IndexPath(row: index, section: 0), at: .middle, animated: true) - tableView.blinkRow(at: IndexPath(row: index, section: 0)) - } else { - print("Not found replied status") - } - } - - @objc private func moveToFirstAudioStatus(_ sender: UIAction) { - guard let diffableDataSource = viewModel.diffableDataSource else { return } - let snapshotTransitioning = diffableDataSource.snapshot() - let item = snapshotTransitioning.itemIdentifiers.first(where: { item in - switch item { - case .homeTimelineIndex(let objectID, _): - let homeTimelineIndex = viewModel.fetchedResultsController.managedObjectContext.object(with: objectID) as! HomeTimelineIndex - let status = homeTimelineIndex.status.reblog ?? homeTimelineIndex.status - return status.mediaAttachments?.contains(where: { $0.type == .audio }) ?? false - default: - return false - } - }) - if let targetItem = item, let index = snapshotTransitioning.indexOfItem(targetItem) { - tableView.scrollToRow(at: IndexPath(row: index, section: 0), at: .middle, animated: true) - tableView.blinkRow(at: IndexPath(row: index, section: 0)) - } else { - print("Not found audio status") - } - } - - @objc private func moveToFirstVideoStatus(_ sender: UIAction) { - guard let diffableDataSource = viewModel.diffableDataSource else { return } - let snapshotTransitioning = diffableDataSource.snapshot() - let item = snapshotTransitioning.itemIdentifiers.first(where: { item in - switch item { - case .homeTimelineIndex(let objectID, _): - let homeTimelineIndex = viewModel.fetchedResultsController.managedObjectContext.object(with: objectID) as! HomeTimelineIndex - let status = homeTimelineIndex.status.reblog ?? homeTimelineIndex.status - return status.mediaAttachments?.contains(where: { $0.type == .video }) ?? false - default: - return false - } - }) - if let targetItem = item, let index = snapshotTransitioning.indexOfItem(targetItem) { - tableView.scrollToRow(at: IndexPath(row: index, section: 0), at: .middle, animated: true) - tableView.blinkRow(at: IndexPath(row: index, section: 0)) - } else { - print("Not found video status") - } - } - - @objc private func moveToFirstGIFStatus(_ sender: UIAction) { - guard let diffableDataSource = viewModel.diffableDataSource else { return } - let snapshotTransitioning = diffableDataSource.snapshot() - let item = snapshotTransitioning.itemIdentifiers.first(where: { item in - switch item { - case .homeTimelineIndex(let objectID, _): - let homeTimelineIndex = viewModel.fetchedResultsController.managedObjectContext.object(with: objectID) as! HomeTimelineIndex - let status = homeTimelineIndex.status.reblog ?? homeTimelineIndex.status - return status.mediaAttachments?.contains(where: { $0.type == .gifv }) ?? false - default: - return false - } - }) - if let targetItem = item, let index = snapshotTransitioning.indexOfItem(targetItem) { - tableView.scrollToRow(at: IndexPath(row: index, section: 0), at: .middle, animated: true) - tableView.blinkRow(at: IndexPath(row: index, section: 0)) - } else { - print("Not found GIF status") - } - } - - @objc private func dropRecentStatusAction(_ sender: UIAction, count: Int) { - guard let diffableDataSource = viewModel.diffableDataSource else { return } - let snapshotTransitioning = diffableDataSource.snapshot() - - let droppingObjectIDs = snapshotTransitioning.itemIdentifiers.prefix(count).compactMap { item -> NSManagedObjectID? in - switch item { - case .homeTimelineIndex(let objectID, _): return objectID - default: return nil - } - } - var droppingStatusObjectIDs: [NSManagedObjectID] = [] - context.apiService.backgroundManagedObjectContext.performChanges { [weak self] in - guard let self = self else { return } - for objectID in droppingObjectIDs { - guard let homeTimelineIndex = try? self.context.apiService.backgroundManagedObjectContext.existingObject(with: objectID) as? HomeTimelineIndex else { continue } - droppingStatusObjectIDs.append(homeTimelineIndex.status.objectID) - self.context.apiService.backgroundManagedObjectContext.delete(homeTimelineIndex) - } - } - .sink { [weak self] result in - guard let self = self else { return } - switch result { - case .success: - self.context.apiService.backgroundManagedObjectContext.performChanges { [weak self] in - guard let self = self else { return } - for objectID in droppingStatusObjectIDs { - guard let post = try? self.context.apiService.backgroundManagedObjectContext.existingObject(with: objectID) as? Status else { continue } - self.context.apiService.backgroundManagedObjectContext.delete(post) - } - } - .sink { _ in - // do nothing - } - .store(in: &self.disposeBag) - case .failure(let error): - assertionFailure(error.localizedDescription) - } - } - .store(in: &disposeBag) - } - - @objc private func showWelcomeAction(_ sender: UIAction) { - coordinator.present(scene: .welcome, from: self, transition: .modal(animated: true, completion: nil)) - } - - @objc private func showPublicTimelineAction(_ sender: UIAction) { - coordinator.present(scene: .publicTimeline, from: self, transition: .show) - } - - @objc private func showProfileAction(_ sender: UIAction) { - let alertController = UIAlertController(title: "Enter User ID", message: nil, preferredStyle: .alert) - alertController.addTextField() - let showAction = UIAlertAction(title: "Show", style: .default) { [weak self, weak alertController] _ in - guard let self = self else { return } - guard let textField = alertController?.textFields?.first else { return } - let profileViewModel = RemoteProfileViewModel(context: self.context, userID: textField.text ?? "") - self.coordinator.present(scene: .profile(viewModel: profileViewModel), from: self, transition: .show) - } - alertController.addAction(showAction) - let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil) - alertController.addAction(cancelAction) - coordinator.present(scene: .alertController(alertController: alertController), from: self, transition: .alertController(animated: true, completion: nil)) - } - - @objc private func showThreadAction(_ sender: UIAction) { - let alertController = UIAlertController(title: "Enter Status ID", message: nil, preferredStyle: .alert) - alertController.addTextField() - let showAction = UIAlertAction(title: "Show", style: .default) { [weak self, weak alertController] _ in - guard let self = self else { return } - guard let textField = alertController?.textFields?.first else { return } - let threadViewModel = RemoteThreadViewModel(context: self.context, statusID: textField.text ?? "") - self.coordinator.present(scene: .thread(viewModel: threadViewModel), from: self, transition: .show) - } - alertController.addAction(showAction) - let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil) - alertController.addAction(cancelAction) - coordinator.present(scene: .alertController(alertController: alertController), from: self, transition: .alertController(animated: true, completion: nil)) - } - - @objc private func showSettings(_ sender: UIAction) { - guard let currentSetting = context.settingService.currentSetting.value else { return } - let settingsViewModel = SettingsViewModel(context: context, setting: currentSetting) - coordinator.present( - scene: .settings(viewModel: settingsViewModel), - from: self, - transition: .modal(animated: true, completion: nil) - ) - } - - @objc func signOutAction(_ sender: UIAction) { - guard let activeMastodonAuthenticationBox = context.authenticationService.activeMastodonAuthenticationBox.value else { - return - } - - context.authenticationService.signOutMastodonUser( - domain: activeMastodonAuthenticationBox.domain, - userID: activeMastodonAuthenticationBox.userID - ) - .receive(on: DispatchQueue.main) - .sink { [weak self] result in - guard let self = self else { return } - switch result { - case .failure(let error): - assertionFailure(error.localizedDescription) - case .success(let isSignOut): - os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: sign out %s", ((#file as NSString).lastPathComponent), #line, #function, isSignOut ? "success" : "fail") - guard isSignOut else { return } - self.coordinator.setup() - self.coordinator.setupOnboardingIfNeeds(animated: true) - } - } - .store(in: &disposeBag) - } -} - -#endif diff --git a/Mastodon/Scene/HomeTimeline/AsyncHomeTimeline/AsyncHomeTimelineViewController+Provider.swift b/Mastodon/Scene/HomeTimeline/AsyncHomeTimeline/AsyncHomeTimelineViewController+Provider.swift deleted file mode 100644 index 5f97ebea..00000000 --- a/Mastodon/Scene/HomeTimeline/AsyncHomeTimeline/AsyncHomeTimelineViewController+Provider.swift +++ /dev/null @@ -1,123 +0,0 @@ -// -// AsyncHomeTimelineViewController+Provider.swift -// Mastodon -// -// Created by MainasuK Cirno on 2021-6-21. -// - -#if ASDK - -import os.log -import UIKit -import Combine -import CoreData -import CoreDataStack -import AsyncDisplayKit - -// MARK: - StatusProvider -extension AsyncHomeTimelineViewController: StatusProvider { - - func status() -> Future { - return Future { promise in promise(.success(nil)) } - } - - func status(for cell: UITableViewCell?, indexPath: IndexPath?) -> Future { - return Future { promise in - guard let diffableDataSource = self.viewModel.diffableDataSource else { - assertionFailure() - promise(.success(nil)) - return - } - guard let indexPath = indexPath ?? cell.flatMap({ self.tableView.indexPath(for: $0) }), - let item = diffableDataSource.itemIdentifier(for: indexPath) else { - promise(.success(nil)) - return - } - - switch item { - case .homeTimelineIndex(let objectID, _): - let managedObjectContext = self.viewModel.fetchedResultsController.managedObjectContext - managedObjectContext.perform { - let timelineIndex = managedObjectContext.object(with: objectID) as? HomeTimelineIndex - promise(.success(timelineIndex?.status)) - } - default: - promise(.success(nil)) - } - } - } - - func status(for cell: UICollectionViewCell) -> Future { - return Future { promise in promise(.success(nil)) } - } - - var managedObjectContext: NSManagedObjectContext { - return viewModel.fetchedResultsController.managedObjectContext - } - - var tableViewDiffableDataSource: UITableViewDiffableDataSource? { - return nil - } - - func item(for cell: UITableViewCell?, indexPath: IndexPath?) -> Item? { - guard let diffableDataSource = self.viewModel.diffableDataSource else { - assertionFailure() - return nil - } - - guard let indexPath = indexPath ?? cell.flatMap({ self.tableView.indexPath(for: $0) }), - let item = diffableDataSource.itemIdentifier(for: indexPath) else { - return nil - } - - return item - } - - func items(indexPaths: [IndexPath]) -> [Item] { - guard let diffableDataSource = self.viewModel.diffableDataSource else { - assertionFailure() - return [] - } - - var items: [Item] = [] - for indexPath in indexPaths { - guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { continue } - items.append(item) - } - return items - } - - func status(node: ASCellNode?, indexPath: IndexPath?) -> Status? { - guard let diffableDataSource = self.viewModel.diffableDataSource else { - assertionFailure() - return nil - } - - guard let indexPath = indexPath ?? node.flatMap({ self.node.indexPath(for: $0) }), - let item = diffableDataSource.itemIdentifier(for: indexPath) else { - return nil - } - - switch item { - case .homeTimelineIndex(let objectID, _): - guard let homeTimelineIndex = try? viewModel.fetchedResultsController.managedObjectContext.existingObject(with: objectID) as? HomeTimelineIndex else { - assertionFailure() - return nil - } - return homeTimelineIndex.status - default: - return nil - } - } - - func statusObjectItems(indexPaths: [IndexPath]) -> [StatusObjectItem] { - guard let diffableDataSource = self.viewModel.diffableDataSource else { return [] } - let items = indexPaths.compactMap { diffableDataSource.itemIdentifier(for: $0)?.statusObjectItem } - return items - } - -} - -extension AsyncHomeTimelineViewController: UserProvider {} - -#endif diff --git a/Mastodon/Scene/HomeTimeline/AsyncHomeTimeline/AsyncHomeTimelineViewController.swift b/Mastodon/Scene/HomeTimeline/AsyncHomeTimeline/AsyncHomeTimelineViewController.swift deleted file mode 100644 index c90b703e..00000000 --- a/Mastodon/Scene/HomeTimeline/AsyncHomeTimeline/AsyncHomeTimelineViewController.swift +++ /dev/null @@ -1,573 +0,0 @@ -// -// AsyncHomeTimelineViewController.swift -// Mastodon -// -// Created by MainasuK Cirno on 2021-6-21. -// - -#if ASDK - -import os.log -import UIKit -import AVKit -import Combine -import CoreData -import CoreDataStack -import GameplayKit -import MastodonSDK -import AlamofireImage -import AsyncDisplayKit - -final class AsyncHomeTimelineViewController: ASDKViewController, NeedsDependency, MediaPreviewableViewController { - - weak var context: AppContext! { willSet { precondition(!isViewLoaded) } } - weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } } - - var disposeBag = Set() - private(set) lazy var viewModel = AsyncHomeTimelineViewModel(context: context) - - let mediaPreviewTransitionController = MediaPreviewTransitionController() - - lazy var emptyView: UIStackView = { - let emptyView = UIStackView() - emptyView.axis = .vertical - emptyView.distribution = .fill - emptyView.layoutMargins = UIEdgeInsets(top: 0, left: 20, bottom: 54, right: 20) - emptyView.isLayoutMarginsRelativeArrangement = true - return emptyView - }() - - let titleView = HomeTimelineNavigationBarTitleView() - - let settingBarButtonItem: UIBarButtonItem = { - let barButtonItem = UIBarButtonItem() - barButtonItem.tintColor = Asset.Colors.brandBlue.color - barButtonItem.image = UIImage(systemName: "gear")?.withRenderingMode(.alwaysTemplate) - return barButtonItem - }() - - let composeBarButtonItem: UIBarButtonItem = { - let barButtonItem = UIBarButtonItem() - barButtonItem.tintColor = Asset.Colors.brandBlue.color - barButtonItem.image = UIImage(systemName: "square.and.pencil")?.withRenderingMode(.alwaysTemplate) - return barButtonItem - }() - - var tableView: UITableView { node.view } - - let publishProgressView: UIProgressView = { - let progressView = UIProgressView(progressViewStyle: .bar) - progressView.alpha = 0 - return progressView - }() - - let refreshControl = UIRefreshControl() - - - override init() { - super.init(node: ASTableNode()) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - deinit { - os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s:", ((#file as NSString).lastPathComponent), #line, #function) - } - -} - -extension AsyncHomeTimelineViewController { - - override func viewDidLoad() { - super.viewDidLoad() - - node.allowsSelection = true - - title = L10n.Scene.HomeTimeline.title - view.backgroundColor = ThemeService.shared.currentTheme.value.secondarySystemBackgroundColor - navigationItem.leftBarButtonItem = settingBarButtonItem - navigationItem.titleView = titleView - titleView.delegate = self - - viewModel.homeTimelineNavigationBarTitleViewModel.state - .removeDuplicates() - .receive(on: DispatchQueue.main) - .sink { [weak self] state in - guard let self = self else { return } - self.titleView.configure(state: state) - } - .store(in: &disposeBag) - - #if DEBUG - // long press to trigger debug menu - settingBarButtonItem.menu = debugMenu - #else - settingBarButtonItem.target = self - settingBarButtonItem.action = #selector(AsyncHomeTimelineViewController.settingBarButtonItemPressed(_:)) - #endif - - navigationItem.rightBarButtonItem = composeBarButtonItem - composeBarButtonItem.target = self - composeBarButtonItem.action = #selector(AsyncHomeTimelineViewController.composeBarButtonItemPressed(_:)) - - node.view.refreshControl = refreshControl - refreshControl.addTarget(self, action: #selector(AsyncHomeTimelineViewController.refreshControlValueChanged(_:)), for: .valueChanged) -// -// tableView.translatesAutoresizingMaskIntoConstraints = false -// view.addSubview(tableView) -// NSLayoutConstraint.activate([ -// tableView.topAnchor.constraint(equalTo: view.topAnchor), -// tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor), -// tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor), -// tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), -// ]) -// -// publishProgressView.translatesAutoresizingMaskIntoConstraints = false -// view.addSubview(publishProgressView) -// NSLayoutConstraint.activate([ -// publishProgressView.topAnchor.constraint(equalTo: view.layoutMarginsGuide.topAnchor), -// publishProgressView.leadingAnchor.constraint(equalTo: view.leadingAnchor), -// publishProgressView.trailingAnchor.constraint(equalTo: view.trailingAnchor), -// ]) -// -// viewModel.tableView = tableView - viewModel.tableNode = node - viewModel.contentOffsetAdjustableTimelineViewControllerDelegate = self - node.delegate = self - viewModel.setupDiffableDataSource( - tableNode: node, - dependency: self, - statusTableViewCellDelegate: self, - timelineMiddleLoaderTableViewCellDelegate: self - ) - - -// tableView.delegate = self -// tableView.prefetchDataSource = self - - // bind refresh control - viewModel.isFetchingLatestTimeline - .receive(on: DispatchQueue.main) - .sink { [weak self] isFetching in - guard let self = self else { return } - if !isFetching { - UIView.animate(withDuration: 0.5) { [weak self] in - guard let self = self else { return } - self.refreshControl.endRefreshing() - } completion: { _ in } - } - } - .store(in: &disposeBag) - -// viewModel.homeTimelineNavigationBarTitleViewModel.publishingProgress -// .receive(on: DispatchQueue.main) -// .sink { [weak self] progress in -// guard let self = self else { return } -// guard progress > 0 else { -// let dismissAnimator = UIViewPropertyAnimator(duration: 0.1, curve: .easeInOut) -// dismissAnimator.addAnimations { -// self.publishProgressView.alpha = 0 -// } -// dismissAnimator.addCompletion { _ in -// self.publishProgressView.setProgress(0, animated: false) -// } -// dismissAnimator.startAnimation() -// return -// } -// if self.publishProgressView.alpha == 0 { -// let progressAnimator = UIViewPropertyAnimator(duration: 0.1, curve: .easeOut) -// progressAnimator.addAnimations { -// self.publishProgressView.alpha = 1 -// } -// progressAnimator.startAnimation() -// } -// -// self.publishProgressView.setProgress(progress, animated: true) -// } -// .store(in: &disposeBag) -// -// viewModel.timelineIsEmpty -// .receive(on: DispatchQueue.main) -// .sink { [weak self] isEmpty in -// if isEmpty { -// self?.showEmptyView() -// } else { -// self?.emptyView.removeFromSuperview() -// } -// } -// .store(in: &disposeBag) - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - -// aspectViewWillAppear(animated) -// -// // needs trigger manually after onboarding dismiss -// setNeedsStatusBarAppearanceUpdate() -// -// if (viewModel.fetchedResultsController.fetchedObjects ?? []).isEmpty { -// viewModel.loadLatestStateMachine.enter(HomeTimelineViewModel.LoadLatestState.Loading.self) -// } - } - - override func viewDidAppear(_ animated: Bool) { - super.viewDidAppear(animated) - -// viewModel.viewDidAppear.send() -// -// DispatchQueue.main.async { [weak self] in -// guard let self = self else { return } -// if (self.viewModel.fetchedResultsController.fetchedObjects ?? []).count == 0 { -// self.viewModel.loadLatestStateMachine.enter(HomeTimelineViewModel.LoadLatestState.Loading.self) -// } -// } - } - - override func viewDidDisappear(_ animated: Bool) { - super.viewDidDisappear(animated) - -// aspectViewDidDisappear(animated) - } - - override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { - super.viewWillTransition(to: size, with: coordinator) - -// coordinator.animate { _ in -// // do nothing -// } completion: { _ in -// // fix AutoLayout cell height not update after rotate issue -// self.viewModel.cellFrameCache.removeAllObjects() -// self.tableView.reloadData() -// } - } -} - -extension AsyncHomeTimelineViewController { - func showEmptyView() { - if emptyView.superview != nil { - return - } - view.addSubview(emptyView) - emptyView.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - emptyView.leadingAnchor.constraint(equalTo: view.readableContentGuide.leadingAnchor), - emptyView.trailingAnchor.constraint(equalTo: view.readableContentGuide.trailingAnchor), - emptyView.bottomAnchor.constraint(equalTo: view.readableContentGuide.bottomAnchor) - ]) - - if emptyView.arrangedSubviews.count > 0 { - return - } - let findPeopleButton: PrimaryActionButton = { - let button = PrimaryActionButton() - button.setTitle(L10n.Common.Controls.Actions.findPeople, for: .normal) - button.addTarget(self, action: #selector(AsyncHomeTimelineViewController.findPeopleButtonPressed(_:)), for: .touchUpInside) - return button - }() - NSLayoutConstraint.activate([ - findPeopleButton.heightAnchor.constraint(equalToConstant: 46) - ]) - - let manuallySearchButton: HighlightDimmableButton = { - let button = HighlightDimmableButton() - button.titleLabel?.font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 15, weight: .semibold)) - button.setTitle(L10n.Common.Controls.Actions.manuallySearch, for: .normal) - button.setTitleColor(Asset.Colors.brandBlue.color, for: .normal) - button.addTarget(self, action: #selector(AsyncHomeTimelineViewController.manuallySearchButtonPressed(_:)), for: .touchUpInside) - return button - }() - - emptyView.addArrangedSubview(findPeopleButton) - emptyView.setCustomSpacing(17, after: findPeopleButton) - emptyView.addArrangedSubview(manuallySearchButton) - - } -} - -extension AsyncHomeTimelineViewController { - - @objc private func findPeopleButtonPressed(_ sender: PrimaryActionButton) { - let viewModel = SuggestionAccountViewModel(context: context) - viewModel.delegate = self.viewModel - coordinator.present(scene: .suggestionAccount(viewModel: viewModel), from: self, transition: .modal(animated: true, completion: nil)) - } - - @objc private func manuallySearchButtonPressed(_ sender: UIButton) { - coordinator.switchToTabBar(tab: .search) - } - - @objc private func settingBarButtonItemPressed(_ sender: UIBarButtonItem) { - os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function) - guard let setting = context.settingService.currentSetting.value else { return } - let settingsViewModel = SettingsViewModel(context: context, setting: setting) - coordinator.present(scene: .settings(viewModel: settingsViewModel), from: self, transition: .modal(animated: true, completion: nil)) - } - - @objc private func composeBarButtonItemPressed(_ sender: UIBarButtonItem) { - os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function) - let composeViewModel = ComposeViewModel(context: context, composeKind: .post) - coordinator.present(scene: .compose(viewModel: composeViewModel), from: self, transition: .modal(animated: true, completion: nil)) - } - - @objc private func refreshControlValueChanged(_ sender: UIRefreshControl) { - guard viewModel.loadLatestStateMachine.enter(HomeTimelineViewModel.LoadLatestState.Loading.self) else { - sender.endRefreshing() - return - } - } - -} - -// MARK: - StatusTableViewControllerAspect -//extension AsyncHomeTimelineViewController: StatusTableViewControllerAspect { } - -//extension AsyncHomeTimelineViewController: TableViewCellHeightCacheableContainer { -// var cellFrameCache: NSCache { return viewModel.cellFrameCache } -//} - -// MARK: - UIScrollViewDelegate -extension AsyncHomeTimelineViewController { - func scrollViewDidScroll(_ scrollView: UIScrollView) { - - //aspectScrollViewDidScroll(scrollView) - viewModel.homeTimelineNavigationBarTitleViewModel.handleScrollViewDidScroll(scrollView) - } -} - -//extension AsyncHomeTimelineViewController: LoadMoreConfigurableTableViewContainer { -// typealias BottomLoaderTableViewCell = TimelineBottomLoaderTableViewCell -// typealias LoadingState = HomeTimelineViewModel.LoadOldestState.Loading -// var loadMoreConfigurableTableView: UITableView { return tableView } -// var loadMoreConfigurableStateMachine: GKStateMachine { return viewModel.loadOldestStateMachine } -//} - -// MARK: - UITableViewDelegate -//extension AsyncHomeTimelineViewController: UITableViewDelegate { -// -// func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { -// aspectTableView(tableView, estimatedHeightForRowAt: indexPath) -// } -// -// func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { -// aspectTableView(tableView, willDisplay: cell, forRowAt: indexPath) -// } -// -// func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) { -// aspectTableView(tableView, didEndDisplaying: cell, forRowAt: indexPath) -// } -// -// func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { -// aspectTableView(tableView, didSelectRowAt: indexPath) -// } -// -// func tableView(_ tableView: UITableView, contextMenuConfigurationForRowAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? { -// return aspectTableView(tableView, contextMenuConfigurationForRowAt: indexPath, point: point) -// } -// -// func tableView(_ tableView: UITableView, previewForHighlightingContextMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? { -// return aspectTableView(tableView, previewForHighlightingContextMenuWithConfiguration: configuration) -// } -// -// func tableView(_ tableView: UITableView, previewForDismissingContextMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? { -// return aspectTableView(tableView, previewForDismissingContextMenuWithConfiguration: configuration) -// } -// -// func tableView(_ tableView: UITableView, willPerformPreviewActionForMenuWith configuration: UIContextMenuConfiguration, animator: UIContextMenuInteractionCommitAnimating) { -// aspectTableView(tableView, willPerformPreviewActionForMenuWith: configuration, animator: animator) -// } -// -//} - -// MARK: - UITableViewDataSourcePrefetching -//extension AsyncHomeTimelineViewController: UITableViewDataSourcePrefetching { -// func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) { -// aspectTableView(tableView, prefetchRowsAt: indexPaths) -// } -//} - -// MARK: - ContentOffsetAdjustableTimelineViewControllerDelegate -extension AsyncHomeTimelineViewController: ContentOffsetAdjustableTimelineViewControllerDelegate { - func navigationBar() -> UINavigationBar? { - return navigationController?.navigationBar - } -} - -// MARK: - TimelineMiddleLoaderTableViewCellDelegate -extension AsyncHomeTimelineViewController: TimelineMiddleLoaderTableViewCellDelegate { - func configure(cell: TimelineMiddleLoaderTableViewCell, upperTimelineStatusID: String?, timelineIndexobjectID: NSManagedObjectID?) { - guard let upperTimelineIndexObjectID = timelineIndexobjectID else { - return - } - viewModel.loadMiddleSateMachineList - .receive(on: DispatchQueue.main) - .sink { [weak self] ids in - guard let _ = self else { return } - if let stateMachine = ids[upperTimelineIndexObjectID] { - guard let state = stateMachine.currentState else { - assertionFailure() - return - } - - // make success state same as loading due to snapshot updating delay - let isLoading = state is HomeTimelineViewModel.LoadMiddleState.Loading || state is HomeTimelineViewModel.LoadMiddleState.Success - if isLoading { - cell.startAnimating() - } else { - cell.stopAnimating() - } - } else { - cell.stopAnimating() - } - } - .store(in: &cell.disposeBag) - - var dict = viewModel.loadMiddleSateMachineList.value - if let _ = dict[upperTimelineIndexObjectID] { - // do nothing - } else { - let stateMachine = GKStateMachine(states: [ - AsyncHomeTimelineViewModel.LoadMiddleState.Initial(viewModel: viewModel, upperTimelineIndexObjectID: upperTimelineIndexObjectID), - AsyncHomeTimelineViewModel.LoadMiddleState.Loading(viewModel: viewModel, upperTimelineIndexObjectID: upperTimelineIndexObjectID), - AsyncHomeTimelineViewModel.LoadMiddleState.Fail(viewModel: viewModel, upperTimelineIndexObjectID: upperTimelineIndexObjectID), - AsyncHomeTimelineViewModel.LoadMiddleState.Success(viewModel: viewModel, upperTimelineIndexObjectID: upperTimelineIndexObjectID), - ]) - stateMachine.enter(HomeTimelineViewModel.LoadMiddleState.Initial.self) - dict[upperTimelineIndexObjectID] = stateMachine - viewModel.loadMiddleSateMachineList.value = dict - } - } - - func timelineMiddleLoaderTableViewCell(_ cell: TimelineMiddleLoaderTableViewCell, loadMoreButtonDidPressed button: UIButton) { - guard let diffableDataSource = viewModel.diffableDataSource else { return } - guard let indexPath = tableView.indexPath(for: cell) else { return } - guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return } - - switch item { - case .homeMiddleLoader(let upper): - guard let stateMachine = viewModel.loadMiddleSateMachineList.value[upper] else { - assertionFailure() - return - } - stateMachine.enter(HomeTimelineViewModel.LoadMiddleState.Loading.self) - default: - assertionFailure() - } - } -} - -// MARK: - ScrollViewContainer -extension AsyncHomeTimelineViewController: ScrollViewContainer { - - var scrollView: UIScrollView { return tableView } - - func scrollToTop(animated: Bool) { - if scrollView.contentOffset.y < scrollView.frame.height, - viewModel.loadLatestStateMachine.canEnterState(HomeTimelineViewModel.LoadLatestState.Loading.self), - (scrollView.contentOffset.y + scrollView.adjustedContentInset.top) == 0.0, - !refreshControl.isRefreshing { - scrollView.scrollRectToVisible(CGRect(origin: CGPoint(x: 0, y: -refreshControl.frame.height), size: CGSize(width: 1, height: 1)), animated: animated) - DispatchQueue.main.async { [weak self] in - guard let self = self else { return } - self.refreshControl.beginRefreshing() - self.refreshControl.sendActions(for: .valueChanged) - } - } else { - let indexPath = IndexPath(row: 0, section: 0) - guard viewModel.diffableDataSource?.itemIdentifier(for: indexPath) != nil else { return } - node.scrollToRow(at: indexPath, at: .top, animated: true) - } - } - -} - -// MARK: - AVPlayerViewControllerDelegate -extension AsyncHomeTimelineViewController: AVPlayerViewControllerDelegate { - - func playerViewController(_ playerViewController: AVPlayerViewController, willBeginFullScreenPresentationWithAnimationCoordinator coordinator: UIViewControllerTransitionCoordinator) { - handlePlayerViewController(playerViewController, willBeginFullScreenPresentationWithAnimationCoordinator: coordinator) - } - - func playerViewController(_ playerViewController: AVPlayerViewController, willEndFullScreenPresentationWithAnimationCoordinator coordinator: UIViewControllerTransitionCoordinator) { - handlePlayerViewController(playerViewController, willEndFullScreenPresentationWithAnimationCoordinator: coordinator) - } - -} - -// MARK: - StatusTableViewCellDelegate -extension AsyncHomeTimelineViewController: StatusTableViewCellDelegate { - weak var playerViewControllerDelegate: AVPlayerViewControllerDelegate? { return self } - func parent() -> UIViewController { return self } -} - -// MARK: - HomeTimelineNavigationBarTitleViewDelegate -extension AsyncHomeTimelineViewController: HomeTimelineNavigationBarTitleViewDelegate { - func homeTimelineNavigationBarTitleView(_ titleView: HomeTimelineNavigationBarTitleView, logoButtonDidPressed sender: UIButton) { - scrollToTop(animated: true) - } - - func homeTimelineNavigationBarTitleView(_ titleView: HomeTimelineNavigationBarTitleView, buttonDidPressed sender: UIButton) { - switch titleView.state { - case .newPostButton: - guard let diffableDataSource = viewModel.diffableDataSource else { return } - let indexPath = IndexPath(row: 0, section: 0) - guard diffableDataSource.itemIdentifier(for: indexPath) != nil else { return } - node.scrollToRow(at: indexPath, at: .top, animated: true) - case .offlineButton: - // TODO: retry - break - case .publishedButton: - break - default: - break - } - } -} - -extension AsyncHomeTimelineViewController { - override var keyCommands: [UIKeyCommand]? { - return navigationKeyCommands + statusNavigationKeyCommands - } -} - -// MARK: - StatusTableViewControllerNavigateable -extension AsyncHomeTimelineViewController: StatusTableViewControllerNavigateable { - @objc func navigateKeyCommandHandlerRelay(_ sender: UIKeyCommand) { - navigateKeyCommandHandler(sender) - } - - @objc func statusKeyCommandHandlerRelay(_ sender: UIKeyCommand) { - statusKeyCommandHandler(sender) - } -} - - -// MARK: - ASTableDelegate -extension AsyncHomeTimelineViewController: ASTableDelegate { - func shouldBatchFetch(for tableNode: ASTableNode) -> Bool { - switch viewModel.loadLatestStateMachine.currentState { - case is HomeTimelineViewModel.LoadOldestState.NoMore: - return false - default: - return true - } - } - - func tableNode(_ tableNode: ASTableNode, willBeginBatchFetchWith context: ASBatchContext) { - viewModel.loadLatestStateMachine.enter(HomeTimelineViewModel.LoadOldestState.Loading.self) - context.completeBatchFetching(true) - } - - func tableNode(_ tableNode: ASTableNode, willDisplayRowWith node: ASCellNode) { - if let statusNode = node as? StatusNode { - statusNode.delegate = self - } - } -} - -// MARK: - StatusNodeDelegate -extension AsyncHomeTimelineViewController: StatusNodeDelegate { } - -#endif diff --git a/Mastodon/Scene/HomeTimeline/AsyncHomeTimeline/AsyncHomeTimelineViewModel+Diffable.swift b/Mastodon/Scene/HomeTimeline/AsyncHomeTimeline/AsyncHomeTimelineViewModel+Diffable.swift deleted file mode 100644 index 7799c216..00000000 --- a/Mastodon/Scene/HomeTimeline/AsyncHomeTimeline/AsyncHomeTimelineViewModel+Diffable.swift +++ /dev/null @@ -1,159 +0,0 @@ -// -// AsyncHomeTimelineViewModel+Diffable.swift -// Mastodon -// -// Created by MainasuK Cirno on 2021-6-21. -// - -#if ASDK - -import os.log -import UIKit -import CoreData -import CoreDataStack -import AsyncDisplayKit -import DifferenceKit -import DiffableDataSources - -extension AsyncHomeTimelineViewModel { - - func setupDiffableDataSource( - tableNode: ASTableNode, - dependency: NeedsDependency, - statusTableViewCellDelegate: StatusTableViewCellDelegate, - timelineMiddleLoaderTableViewCellDelegate: TimelineMiddleLoaderTableViewCellDelegate - ) { - tableNode.automaticallyAdjustsContentOffset = true - - diffableDataSource = StatusSection.tableNodeDiffableDataSource( - tableNode: tableNode, - managedObjectContext: fetchedResultsController.managedObjectContext - ) - - var snapshot = DiffableDataSourceSnapshot() - snapshot.appendSections([.main]) - diffableDataSource?.apply(snapshot) - } - -} - -// MARK: - NSFetchedResultsControllerDelegate -extension AsyncHomeTimelineViewModel: NSFetchedResultsControllerDelegate { - - func controllerWillChangeContent(_ controller: NSFetchedResultsController) { - os_log("%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function) - } - - func controller(_ controller: NSFetchedResultsController, didChangeContentWith snapshot: NSDiffableDataSourceSnapshotReference) { - os_log("%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function) - - guard let diffableDataSource = self.diffableDataSource else { return } - let oldSnapshot = diffableDataSource.snapshot() - - let predicate = fetchedResultsController.fetchRequest.predicate - let parentManagedObjectContext = fetchedResultsController.managedObjectContext - let managedObjectContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType) - managedObjectContext.parent = parentManagedObjectContext - - managedObjectContext.perform { - var shouldAddBottomLoader = false - - let timelineIndexes: [HomeTimelineIndex] = { - let request = HomeTimelineIndex.sortedFetchRequest - request.returnsObjectsAsFaults = false - request.predicate = predicate - do { - return try managedObjectContext.fetch(request) - } catch { - assertionFailure(error.localizedDescription) - return [] - } - }() - - // that's will be the most fastest fetch because of upstream just update and no modify needs consider - - var oldSnapshotAttributeDict: [NSManagedObjectID : Item.StatusAttribute] = [:] - - for item in oldSnapshot.itemIdentifiers { - guard case let .homeTimelineIndex(objectID, attribute) = item else { continue } - oldSnapshotAttributeDict[objectID] = attribute - } - - var newTimelineItems: [Item] = [] - - for (i, timelineIndex) in timelineIndexes.enumerated() { - let attribute = oldSnapshotAttributeDict[timelineIndex.objectID] ?? Item.StatusAttribute() - attribute.isSeparatorLineHidden = false - - // append new item into snapshot - newTimelineItems.append(.homeTimelineIndex(objectID: timelineIndex.objectID, attribute: attribute)) - - let isLast = i == timelineIndexes.count - 1 - switch (isLast, timelineIndex.hasMore) { - case (false, true): - newTimelineItems.append(.homeMiddleLoader(upperTimelineIndexAnchorObjectID: timelineIndex.objectID)) - attribute.isSeparatorLineHidden = true - case (true, true): - shouldAddBottomLoader = true - default: - break - } - } // end for - - var newSnapshot = DiffableDataSourceSnapshot() - newSnapshot.appendSections([.main]) - newSnapshot.appendItems(newTimelineItems, toSection: .main) - - let endSnapshot = CACurrentMediaTime() - - if shouldAddBottomLoader, !(self.loadLatestStateMachine.currentState is LoadOldestState.NoMore) { - newSnapshot.appendItems([.bottomLoader], toSection: .main) - } - - diffableDataSource.apply(newSnapshot, animatingDifferences: false) { - DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { - self.isFetchingLatestTimeline.value = false - } - - let end = CACurrentMediaTime() - os_log("%{public}s[%{public}ld], %{public}s: calculate home timeline layout cost %.2fs", ((#file as NSString).lastPathComponent), #line, #function, end - endSnapshot) - } - } // end perform - } - - private struct Difference { - let item: T - let sourceIndexPath: IndexPath - let targetIndexPath: IndexPath - let offset: CGFloat - } - - private func calculateReloadSnapshotDifference( - navigationBar: UINavigationBar, - tableView: UITableView, - oldSnapshot: DiffableDataSourceSnapshot, - newSnapshot: DiffableDataSourceSnapshot - ) -> Difference? { - guard oldSnapshot.numberOfItems != 0 else { return nil } - - // old snapshot not empty. set source index path to first item if not match - let sourceIndexPath = UIViewController.topVisibleTableViewCellIndexPath(in: tableView, navigationBar: navigationBar) ?? IndexPath(row: 0, section: 0) - - guard sourceIndexPath.row < oldSnapshot.itemIdentifiers(inSection: .main).count else { return nil } - - let timelineItem = oldSnapshot.itemIdentifiers(inSection: .main)[sourceIndexPath.row] - guard let itemIndex = newSnapshot.itemIdentifiers(inSection: .main).firstIndex(of: timelineItem) else { return nil } - let targetIndexPath = IndexPath(row: itemIndex, section: 0) - - let offset = UIViewController.tableViewCellOriginOffsetToWindowTop(in: tableView, at: sourceIndexPath, navigationBar: navigationBar) - return Difference( - item: timelineItem, - sourceIndexPath: sourceIndexPath, - targetIndexPath: targetIndexPath, - offset: offset - ) - } - -} - -#endif diff --git a/Mastodon/Scene/HomeTimeline/AsyncHomeTimeline/AsyncHomeTimelineViewModel+LoadLatestState.swift b/Mastodon/Scene/HomeTimeline/AsyncHomeTimeline/AsyncHomeTimelineViewModel+LoadLatestState.swift deleted file mode 100644 index 4d73eae5..00000000 --- a/Mastodon/Scene/HomeTimeline/AsyncHomeTimeline/AsyncHomeTimelineViewModel+LoadLatestState.swift +++ /dev/null @@ -1,134 +0,0 @@ -// -// AsyncHomeTimelineViewModel+LoadLatestState.swift -// Mastodon -// -// Created by MainasuK Cirno on 2021-6-21. -// -// - -#if ASDK - -import os.log -import func QuartzCore.CACurrentMediaTime -import Foundation -import CoreData -import CoreDataStack -import GameplayKit - -extension AsyncHomeTimelineViewModel { - class LoadLatestState: GKState { - weak var viewModel: AsyncHomeTimelineViewModel? - - init(viewModel: AsyncHomeTimelineViewModel) { - self.viewModel = viewModel - } - - override func didEnter(from previousState: GKState?) { - os_log("%{public}s[%{public}ld], %{public}s: enter %s, previous: %s", ((#file as NSString).lastPathComponent), #line, #function, self.debugDescription, previousState.debugDescription) - viewModel?.loadLatestStateMachinePublisher.send(self) - } - } -} - -extension AsyncHomeTimelineViewModel.LoadLatestState { - class Initial: AsyncHomeTimelineViewModel.LoadLatestState { - override func isValidNextState(_ stateClass: AnyClass) -> Bool { - return stateClass == Loading.self - } - } - - class Loading: AsyncHomeTimelineViewModel.LoadLatestState { - override func isValidNextState(_ stateClass: AnyClass) -> Bool { - return stateClass == Fail.self || stateClass == Idle.self - } - - override func didEnter(from previousState: GKState?) { - super.didEnter(from: previousState) - guard let viewModel = viewModel, let stateMachine = stateMachine else { return } - guard let activeMastodonAuthenticationBox = viewModel.context.authenticationService.activeMastodonAuthenticationBox.value else { - // sign out when loading will enter here - stateMachine.enter(Fail.self) - return - } - - let predicate = viewModel.fetchedResultsController.fetchRequest.predicate - let parentManagedObjectContext = viewModel.fetchedResultsController.managedObjectContext - let managedObjectContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType) - managedObjectContext.parent = parentManagedObjectContext - - managedObjectContext.perform { - let start = CACurrentMediaTime() - let latestStatusIDs: [Status.ID] - let request = HomeTimelineIndex.sortedFetchRequest - request.returnsObjectsAsFaults = false - request.predicate = predicate - - do { - let timelineIndexes = try managedObjectContext.fetch(request) - let endFetch = CACurrentMediaTime() - os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: collect timelineIndexes cost: %.2fs", ((#file as NSString).lastPathComponent), #line, #function, endFetch - start) - latestStatusIDs = timelineIndexes - .prefix(APIService.onceRequestStatusMaxCount) // avoid performance issue - .compactMap { timelineIndex in - timelineIndex.value(forKeyPath: #keyPath(HomeTimelineIndex.status.id)) as? Status.ID - } - } catch { - stateMachine.enter(Fail.self) - return - } - - let end = CACurrentMediaTime() - os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: collect statuses id cost: %.2fs", ((#file as NSString).lastPathComponent), #line, #function, end - start) - - // TODO: only set large count when using Wi-Fi - viewModel.context.apiService.homeTimeline(domain: activeMastodonAuthenticationBox.domain, authorizationBox: activeMastodonAuthenticationBox) - .receive(on: DispatchQueue.main) - .sink { completion in - viewModel.homeTimelineNavigationBarTitleViewModel.receiveLoadingStateCompletion(completion) - switch completion { - case .failure(let error): - // TODO: handle error - viewModel.isFetchingLatestTimeline.value = false - os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: fetch statuses failed. %s", ((#file as NSString).lastPathComponent), #line, #function, error.localizedDescription) - case .finished: - // handle isFetchingLatestTimeline in fetch controller delegate - break - } - - stateMachine.enter(Idle.self) - - } receiveValue: { response in - // stop refresher if no new statuses - let statuses = response.value - let newStatuses = statuses.filter { !latestStatusIDs.contains($0.id) } - os_log("%{public}s[%{public}ld], %{public}s: load %{public}ld new statuses", ((#file as NSString).lastPathComponent), #line, #function, newStatuses.count) - - if newStatuses.isEmpty { - viewModel.isFetchingLatestTimeline.value = false - } else { - if !latestStatusIDs.isEmpty { - viewModel.homeTimelineNavigationBarTitleViewModel.newPostsIncoming() - } - } - viewModel.timelineIsEmpty.value = latestStatusIDs.isEmpty && statuses.isEmpty - } - .store(in: &viewModel.disposeBag) - } - } - } - - class Fail: AsyncHomeTimelineViewModel.LoadLatestState { - override func isValidNextState(_ stateClass: AnyClass) -> Bool { - return stateClass == Loading.self || stateClass == Idle.self - } - } - - class Idle: AsyncHomeTimelineViewModel.LoadLatestState { - override func isValidNextState(_ stateClass: AnyClass) -> Bool { - return stateClass == Loading.self - } - } - -} - -#endif diff --git a/Mastodon/Scene/HomeTimeline/AsyncHomeTimeline/AsyncHomeTimelineViewModel+LoadMiddleState.swift b/Mastodon/Scene/HomeTimeline/AsyncHomeTimeline/AsyncHomeTimelineViewModel+LoadMiddleState.swift deleted file mode 100644 index f568a6aa..00000000 --- a/Mastodon/Scene/HomeTimeline/AsyncHomeTimeline/AsyncHomeTimelineViewModel+LoadMiddleState.swift +++ /dev/null @@ -1,112 +0,0 @@ -// -// AsyncHomeTimelineViewModel+LoadMiddleState.swift -// Mastodon -// -// Created by MainasuK Cirno on 2021-6-21. -// - -#if ASDK - -import os.log -import Foundation -import GameplayKit -import CoreData -import CoreDataStack - -extension AsyncHomeTimelineViewModel { - class LoadMiddleState: GKState { - weak var viewModel: AsyncHomeTimelineViewModel? - let upperTimelineIndexObjectID: NSManagedObjectID - - init(viewModel: AsyncHomeTimelineViewModel, upperTimelineIndexObjectID: NSManagedObjectID) { - self.viewModel = viewModel - self.upperTimelineIndexObjectID = upperTimelineIndexObjectID - } - - override func didEnter(from previousState: GKState?) { - os_log("%{public}s[%{public}ld], %{public}s: enter %s, previous: %s", ((#file as NSString).lastPathComponent), #line, #function, self.debugDescription, previousState.debugDescription) - guard let viewModel = viewModel, let stateMachine = stateMachine else { return } - var dict = viewModel.loadMiddleSateMachineList.value - dict[upperTimelineIndexObjectID] = stateMachine - viewModel.loadMiddleSateMachineList.value = dict // trigger value change - } - } -} - -extension AsyncHomeTimelineViewModel.LoadMiddleState { - - class Initial: AsyncHomeTimelineViewModel.LoadMiddleState { - override func isValidNextState(_ stateClass: AnyClass) -> Bool { - return stateClass == Loading.self - } - } - - class Loading: AsyncHomeTimelineViewModel.LoadMiddleState { - override func isValidNextState(_ stateClass: AnyClass) -> Bool { - // guard let viewModel = viewModel else { return false } - return stateClass == Success.self || stateClass == Fail.self - } - - override func didEnter(from previousState: GKState?) { - super.didEnter(from: previousState) - - guard let viewModel = viewModel, let stateMachine = stateMachine else { return } - guard let activeMastodonAuthenticationBox = viewModel.context.authenticationService.activeMastodonAuthenticationBox.value else { - stateMachine.enter(Fail.self) - return - } - - guard let timelineIndex = (viewModel.fetchedResultsController.fetchedObjects ?? []).first(where: { $0.objectID == upperTimelineIndexObjectID }) else { - stateMachine.enter(Fail.self) - return - } - let statusIDs = (viewModel.fetchedResultsController.fetchedObjects ?? []).compactMap { timelineIndex in - timelineIndex.status.id - } - - // TODO: only set large count when using Wi-Fi - let maxID = timelineIndex.status.id - viewModel.context.apiService.homeTimeline(domain: activeMastodonAuthenticationBox.domain,maxID: maxID, authorizationBox: activeMastodonAuthenticationBox) - .delay(for: .seconds(1), scheduler: DispatchQueue.main) - .receive(on: DispatchQueue.main) - .sink { completion in - viewModel.homeTimelineNavigationBarTitleViewModel.receiveLoadingStateCompletion(completion) - switch completion { - case .failure(let error): - // TODO: handle error - os_log("%{public}s[%{public}ld], %{public}s: fetch statuses failed. %s", ((#file as NSString).lastPathComponent), #line, #function, error.localizedDescription) - stateMachine.enter(Fail.self) - case .finished: - break - } - } receiveValue: { response in - let statuses = response.value - let newStatuses = statuses.filter { !statusIDs.contains($0.id) } - os_log("%{public}s[%{public}ld], %{public}s: load %{public}ld statuses, %{public}%ld new statuses", ((#file as NSString).lastPathComponent), #line, #function, statuses.count, newStatuses.count) - if newStatuses.isEmpty { - stateMachine.enter(Fail.self) - } else { - stateMachine.enter(Success.self) - } - } - .store(in: &viewModel.disposeBag) - } - } - - class Fail: AsyncHomeTimelineViewModel.LoadMiddleState { - override func isValidNextState(_ stateClass: AnyClass) -> Bool { - // guard let viewModel = viewModel else { return false } - return stateClass == Loading.self - } - } - - class Success: AsyncHomeTimelineViewModel.LoadMiddleState { - override func isValidNextState(_ stateClass: AnyClass) -> Bool { - // guard let viewModel = viewModel else { return false } - return false - } - } - -} - -#endif diff --git a/Mastodon/Scene/HomeTimeline/AsyncHomeTimeline/AsyncHomeTimelineViewModel+LoadOldestState.swift b/Mastodon/Scene/HomeTimeline/AsyncHomeTimeline/AsyncHomeTimelineViewModel+LoadOldestState.swift deleted file mode 100644 index 5743ab29..00000000 --- a/Mastodon/Scene/HomeTimeline/AsyncHomeTimeline/AsyncHomeTimelineViewModel+LoadOldestState.swift +++ /dev/null @@ -1,117 +0,0 @@ -// -// AsyncHomeTimelineViewModel+LoadOldestState.swift -// Mastodon -// -// Created by MainasuK Cirno on 2021-6-21. -// - -#if ASDK - -import os.log -import Foundation -import GameplayKit - -extension AsyncHomeTimelineViewModel { - class LoadOldestState: GKState { - weak var viewModel: AsyncHomeTimelineViewModel? - - init(viewModel: AsyncHomeTimelineViewModel) { - self.viewModel = viewModel - } - - override func didEnter(from previousState: GKState?) { - os_log("%{public}s[%{public}ld], %{public}s: enter %s, previous: %s", ((#file as NSString).lastPathComponent), #line, #function, self.debugDescription, previousState.debugDescription) - viewModel?.loadOldestStateMachinePublisher.send(self) - } - } -} - -extension AsyncHomeTimelineViewModel.LoadOldestState { - class Initial: AsyncHomeTimelineViewModel.LoadOldestState { - override func isValidNextState(_ stateClass: AnyClass) -> Bool { - guard let viewModel = viewModel else { return false } - guard !(viewModel.fetchedResultsController.fetchedObjects ?? []).isEmpty else { return false } - return stateClass == Loading.self - } - } - - class Loading: AsyncHomeTimelineViewModel.LoadOldestState { - override func isValidNextState(_ stateClass: AnyClass) -> Bool { - return stateClass == Fail.self || stateClass == Idle.self || stateClass == NoMore.self - } - - override func didEnter(from previousState: GKState?) { - super.didEnter(from: previousState) - guard let viewModel = viewModel, let stateMachine = stateMachine else { return } - guard let activeMastodonAuthenticationBox = viewModel.context.authenticationService.activeMastodonAuthenticationBox.value else { - assertionFailure() - stateMachine.enter(Fail.self) - return - } - - guard let last = viewModel.fetchedResultsController.fetchedObjects?.last else { - stateMachine.enter(Idle.self) - return - } - - // TODO: only set large count when using Wi-Fi - let maxID = last.status.id - viewModel.context.apiService.homeTimeline(domain: activeMastodonAuthenticationBox.domain, maxID: maxID, authorizationBox: activeMastodonAuthenticationBox) - .delay(for: .seconds(1), scheduler: DispatchQueue.main) - .receive(on: DispatchQueue.main) - .sink { completion in - viewModel.homeTimelineNavigationBarTitleViewModel.receiveLoadingStateCompletion(completion) - switch completion { - case .failure(let error): - os_log("%{public}s[%{public}ld], %{public}s: fetch statuses failed. %s", ((#file as NSString).lastPathComponent), #line, #function, error.localizedDescription) - case .finished: - // handle isFetchingLatestTimeline in fetch controller delegate - break - } - } receiveValue: { response in - let statuses = response.value - // enter no more state when no new statuses - if statuses.isEmpty || (statuses.count == 1 && statuses[0].id == maxID) { - stateMachine.enter(NoMore.self) - } else { - stateMachine.enter(Idle.self) - } - } - .store(in: &viewModel.disposeBag) - } - } - - class Fail: AsyncHomeTimelineViewModel.LoadOldestState { - override func isValidNextState(_ stateClass: AnyClass) -> Bool { - return stateClass == Loading.self || stateClass == Idle.self - } - } - - class Idle: AsyncHomeTimelineViewModel.LoadOldestState { - override func isValidNextState(_ stateClass: AnyClass) -> Bool { - return stateClass == Loading.self - } - } - - class NoMore: AsyncHomeTimelineViewModel.LoadOldestState { - override func isValidNextState(_ stateClass: AnyClass) -> Bool { - // reset state if needs - return stateClass == Idle.self - } - - override func didEnter(from previousState: GKState?) { - guard let viewModel = viewModel else { return } - guard let diffableDataSource = viewModel.diffableDataSource else { - assertionFailure() - return - } - DispatchQueue.main.async { - var snapshot = diffableDataSource.snapshot() - snapshot.deleteItems([.bottomLoader]) - diffableDataSource.apply(snapshot) - } - } - } -} - -#endif diff --git a/Mastodon/Scene/HomeTimeline/AsyncHomeTimeline/AsyncHomeTimelineViewModel.swift b/Mastodon/Scene/HomeTimeline/AsyncHomeTimeline/AsyncHomeTimelineViewModel.swift deleted file mode 100644 index d7ed0b10..00000000 --- a/Mastodon/Scene/HomeTimeline/AsyncHomeTimeline/AsyncHomeTimelineViewModel.swift +++ /dev/null @@ -1,151 +0,0 @@ -// -// AsyncHomeTimelineViewModel.swift -// Mastodon -// -// Created by MainasuK Cirno on 2021-6-21. -// -// - -#if ASDK - -import os.log -import func AVFoundation.AVMakeRect -import UIKit -import AVKit -import Combine -import CoreData -import CoreDataStack -import GameplayKit -import AlamofireImage -import DateToolsSwift -import AsyncDisplayKit - -final class AsyncHomeTimelineViewModel: NSObject { - - var disposeBag = Set() - var observations = Set() - - // input - let context: AppContext - let timelinePredicate = CurrentValueSubject(nil) - let fetchedResultsController: NSFetchedResultsController - let isFetchingLatestTimeline = CurrentValueSubject(false) - let viewDidAppear = PassthroughSubject() - let homeTimelineNavigationBarTitleViewModel: HomeTimelineNavigationBarTitleViewModel - - weak var tableNode: ASTableNode? - weak var contentOffsetAdjustableTimelineViewControllerDelegate: ContentOffsetAdjustableTimelineViewControllerDelegate? - //weak var tableView: UITableView? - weak var timelineMiddleLoaderTableViewCellDelegate: TimelineMiddleLoaderTableViewCellDelegate? - - let timelineIsEmpty = CurrentValueSubject(false) - let homeTimelineNeedRefresh = PassthroughSubject() - - // output - var diffableDataSource: TableNodeDiffableDataSource? - - // top loader - private(set) lazy var loadLatestStateMachine: GKStateMachine = { - // exclude timeline middle fetcher state - let stateMachine = GKStateMachine(states: [ - LoadLatestState.Initial(viewModel: self), - LoadLatestState.Loading(viewModel: self), - LoadLatestState.Fail(viewModel: self), - LoadLatestState.Idle(viewModel: self), - ]) - stateMachine.enter(LoadLatestState.Initial.self) - return stateMachine - }() - lazy var loadLatestStateMachinePublisher = CurrentValueSubject(nil) - // bottom loader - private(set) lazy var loadOldestStateMachine: GKStateMachine = { - // exclude timeline middle fetcher state - let stateMachine = GKStateMachine(states: [ - LoadOldestState.Initial(viewModel: self), - LoadOldestState.Loading(viewModel: self), - LoadOldestState.Fail(viewModel: self), - LoadOldestState.Idle(viewModel: self), - LoadOldestState.NoMore(viewModel: self), - ]) - stateMachine.enter(LoadOldestState.Initial.self) - return stateMachine - }() - lazy var loadOldestStateMachinePublisher = CurrentValueSubject(nil) - // middle loader - let loadMiddleSateMachineList = CurrentValueSubject<[NSManagedObjectID: GKStateMachine], Never>([:]) // TimelineIndex.objectID : middle loading state machine - // var diffableDataSource: UITableViewDiffableDataSource? - var cellFrameCache = NSCache() - - - init(context: AppContext) { - self.context = context - self.fetchedResultsController = { - let fetchRequest = HomeTimelineIndex.sortedFetchRequest - fetchRequest.fetchBatchSize = 20 - fetchRequest.returnsObjectsAsFaults = false - fetchRequest.relationshipKeyPathsForPrefetching = [#keyPath(HomeTimelineIndex.status)] - let controller = NSFetchedResultsController( - fetchRequest: fetchRequest, - managedObjectContext: context.managedObjectContext, - sectionNameKeyPath: nil, - cacheName: nil - ) - - return controller - }() - self.homeTimelineNavigationBarTitleViewModel = HomeTimelineNavigationBarTitleViewModel(context: context) - super.init() - - fetchedResultsController.delegate = self - - timelinePredicate - .receive(on: DispatchQueue.main) - .compactMap { $0 } - .first() // set once - .sink { [weak self] predicate in - guard let self = self else { return } - self.fetchedResultsController.fetchRequest.predicate = predicate - do { - try self.fetchedResultsController.performFetch() - } catch { - assertionFailure(error.localizedDescription) - } - } - .store(in: &disposeBag) - - context.authenticationService.activeMastodonAuthentication - .sink { [weak self] activeMastodonAuthentication in - guard let self = self else { return } - guard let mastodonAuthentication = activeMastodonAuthentication else { return } - let activeMastodonUserID = mastodonAuthentication.userID - let predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [ - HomeTimelineIndex.predicate(userID: activeMastodonUserID), - HomeTimelineIndex.notDeleted() - ]) - self.timelinePredicate.value = predicate - } - .store(in: &disposeBag) - - homeTimelineNeedRefresh - .sink { [weak self] _ in - self?.loadLatestStateMachine.enter(LoadLatestState.Loading.self) - } - .store(in: &disposeBag) - - homeTimelineNavigationBarTitleViewModel.isPublished - .sink { [weak self] isPublished in - guard let self = self else { return } - self.homeTimelineNeedRefresh.send() - } - .store(in: &disposeBag) - } - - deinit { - os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s:", ((#file as NSString).lastPathComponent), #line, #function) - } - -} - -extension AsyncHomeTimelineViewModel: SuggestionAccountViewModelDelegate { } - -#endif diff --git a/Mastodon/Scene/Root/MainTab/MainTabBarController.swift b/Mastodon/Scene/Root/MainTab/MainTabBarController.swift index 4b803bc4..058a0fc3 100644 --- a/Mastodon/Scene/Root/MainTab/MainTabBarController.swift +++ b/Mastodon/Scene/Root/MainTab/MainTabBarController.swift @@ -74,11 +74,7 @@ class MainTabBarController: UITabBarController { let viewController: UIViewController switch self { case .home: - #if ASDK - let _viewController: NeedsDependency & UIViewController = UserDefaults.shared.preferAsyncHomeTimeline ? AsyncHomeTimelineViewController() : HomeTimelineViewController() - #else let _viewController = HomeTimelineViewController() - #endif _viewController.context = context _viewController.coordinator = coordinator viewController = _viewController @@ -596,33 +592,3 @@ extension MainTabBarController { } } - -#if ASDK -extension MainTabBarController { - override func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) { - guard let event = event else { return } - switch event.subtype { - case .motionShake: - let alertController = UIAlertController(title: "ASDK Debug Panel", message: nil, preferredStyle: .alert) - let toggleHomeAction = UIAlertAction(title: "Toggle Home", style: .default) { [weak self] _ in - guard let self = self else { return } - MainTabBarController.toggleAsyncHome() - let okAlertController = UIAlertController(title: "Success", message: "Please restart the app", preferredStyle: .alert) - let okAction = UIAlertAction(title: "OK", style: .default, handler: nil) - okAlertController.addAction(okAction) - self.coordinator.present(scene: .alertController(alertController: okAlertController), from: nil, transition: .alertController(animated: true, completion: nil)) - } - alertController.addAction(toggleHomeAction) - let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil) - alertController.addAction(cancelAction) - self.coordinator.present(scene: .alertController(alertController: alertController), from: nil, transition: .alertController(animated: true, completion: nil)) - default: - break - } - } - - static func toggleAsyncHome() { - UserDefaults.shared.preferAsyncHomeTimeline.toggle() - } -} -#endif diff --git a/Mastodon/Scene/Share/View/Node/ASMetaEditableTextNode.swift b/Mastodon/Scene/Share/View/Node/ASMetaEditableTextNode.swift deleted file mode 100644 index e5037fdf..00000000 --- a/Mastodon/Scene/Share/View/Node/ASMetaEditableTextNode.swift +++ /dev/null @@ -1,25 +0,0 @@ -// -// ASMetaEditableTextNode.swift -// Mastodon -// -// Created by Cirno MainasuK on 2021-6-20. -// - -#if ASDK - -import UIKit -import AsyncDisplayKit - -protocol ASMetaEditableTextNodeDelegate: AnyObject { - func metaEditableTextNode(_ textNode: ASMetaEditableTextNode, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool -} - -final class ASMetaEditableTextNode: ASEditableTextNode, UITextViewDelegate { - weak var metaEditableTextNodeDelegate: ASMetaEditableTextNodeDelegate? - - func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool { - return metaEditableTextNodeDelegate?.metaEditableTextNode(self, shouldInteractWith: URL, in: characterRange, interaction: interaction) ?? false - } -} - -#endif diff --git a/Mastodon/Scene/Share/View/Node/Status/StatusNode.swift b/Mastodon/Scene/Share/View/Node/Status/StatusNode.swift deleted file mode 100644 index 17054348..00000000 --- a/Mastodon/Scene/Share/View/Node/Status/StatusNode.swift +++ /dev/null @@ -1,234 +0,0 @@ -// -// StatusNNode.swift -// Mastodon -// -// Created by Cirno MainasuK on 2021-6-19. -// - -#if ASDK - -import UIKit -import Combine -import AsyncDisplayKit -import CoreDataStack -import func AVFoundation.AVMakeRect - -protocol StatusNodeDelegate: AnyObject { - //func statusNode(_ node: StatusNode, statusContentTextNode: ASMetaEditableTextNode, didSelectActiveEntityType type: ActiveEntityType) -} - -final class StatusNode: ASCellNode { - - var disposeBag = Set() - var timestamp: Date - var timestampSubscription: AnyCancellable? - - weak var delegate: StatusNodeDelegate? // needs assign on main queue - - static let avatarImageSize = CGSize(width: 42, height: 42) - static let avatarImageCornerRadius: CGFloat = 4 - -// static let statusContentAppearance: MastodonStatusContent.Appearance = { -// let linkAttributes: [NSAttributedString.Key: Any] = [ -// .font: UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 17, weight: .semibold)), -// .foregroundColor: Asset.Colors.brandBlue.color -// ] -// return MastodonStatusContent.Appearance( -// attributes: [ -// .font: UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 17, weight: .regular)), -// .foregroundColor: Asset.Colors.Label.primary.color -// ], -// urlAttributes: linkAttributes, -// hashtagAttributes: linkAttributes, -// mentionAttributes: linkAttributes -// ) -// }() - - let avatarImageNode: ASNetworkImageNode = { - let node = ASNetworkImageNode() - node.contentMode = .scaleAspectFill - node.defaultImage = UIImage.placeholder(color: .systemFill) - node.forcedSize = StatusNode.avatarImageSize - node.cornerRadius = StatusNode.avatarImageCornerRadius - // node.cornerRoundingType = .precomposited - // node.shouldRenderProgressImages = true - return node - }() - let nameTextNode = ASTextNode() - let nameDotTextNode = ASTextNode() - let dateTextNode = ASTextNode() - let usernameTextNode = ASTextNode() - let statusContentTextNode: ASMetaEditableTextNode = { - let node = ASMetaEditableTextNode() - node.scrollEnabled = false - return node - }() - - let mosaicImageViewModel: MosaicImageViewModel - let mediaMultiplexImageNodes: [ASMultiplexImageNode] - - init(status: Status) { - timestamp = (status.reblog ?? status).createdAt - let _mosaicImageViewModel: MosaicImageViewModel = { - let mediaAttachments = Array((status.reblog ?? status).mediaAttachments ?? []).sorted { $0.index.compare($1.index) == .orderedAscending } - return MosaicImageViewModel(mediaAttachments: mediaAttachments) - }() - mosaicImageViewModel = _mosaicImageViewModel - mediaMultiplexImageNodes = { - var imageNodes: [ASMultiplexImageNode] = [] - for _ in 0..<_mosaicImageViewModel.metas.count { - let imageNode = ASMultiplexImageNode() // TODO: adapt downloader - imageNode.downloadsIntermediateImages = true - imageNode.imageIdentifiers = ["url", "previewURL"].map { $0 as NSString } // quality in descending order - imageNodes.append(imageNode) - } - return imageNodes - }() - super.init() - - automaticallyManagesSubnodes = true - - if let url = (status.reblog ?? status).author.avatarImageURL() { - avatarImageNode.url = url - } - - nameTextNode.attributedText = NSAttributedString(string: status.author.displayNameWithFallback, attributes: [ - .foregroundColor: Asset.Colors.Label.primary.color, - .font: UIFont.systemFont(ofSize: 17, weight: .semibold) - ]) - nameDotTextNode.attributedText = NSAttributedString(string: "·", attributes: [ - .foregroundColor: Asset.Colors.Label.secondary.color, - .font: UIFont.systemFont(ofSize: 13, weight: .regular) - ]) - // set date - dateTextNode.attributedText = NSAttributedString(string: timestamp.localizedSlowedTimeAgoSinceNow, attributes: [ - .foregroundColor: Asset.Colors.Label.secondary.color, - .font: UIFont.systemFont(ofSize: 13, weight: .regular) - ]) - - usernameTextNode.attributedText = NSAttributedString(string: "@" + status.author.acct, attributes: [ - .foregroundColor: Asset.Colors.Label.secondary.color, - .font: UIFont.systemFont(ofSize: 15, weight: .regular) - ]) - - // FIXME: - // statusContentTextNode.metaEditableTextNodeDelegate = self -// if let parseResult = try? MastodonStatusContent.parse( -// content: (status.reblog ?? status).content, -// emojiDict: (status.reblog ?? status).emojiDict -// ) { -// statusContentTextNode.attributedText = parseResult.trimmedAttributedString(appearance: StatusNode.statusContentAppearance) -// } - - for imageNode in mediaMultiplexImageNodes { - imageNode.delegate = self - } - } - - override func didEnterDisplayState() { - super.didEnterDisplayState() - - timestampSubscription = AppContext.shared.timestampUpdatePublisher - .sink { [weak self] _ in - guard let self = self else { return } - self.dateTextNode.attributedText = NSAttributedString(string: self.timestamp.localizedSlowedTimeAgoSinceNow, attributes: [ - .foregroundColor: Asset.Colors.Label.secondary.color, - .font: UIFont.systemFont(ofSize: 13, weight: .regular) - ]) - } - - // FIXME: needs move to other only once called callback in life cycle like: `viewDidLoad` - statusContentTextNode.textView.isEditable = false - statusContentTextNode.textView.textDragInteraction?.isEnabled = false - statusContentTextNode.textView.linkTextAttributes = [ - .foregroundColor: Asset.Colors.brandBlue.color - ] - } - - override func didExitVisibleState() { - super.didExitVisibleState() - timestampSubscription = nil - } - - override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec { - let headerStack = ASStackLayoutSpec.horizontal() - headerStack.alignItems = .center - headerStack.spacing = 5 - var headerStackChildren: [ASLayoutElement] = [] - - avatarImageNode.style.preferredSize = StatusNode.avatarImageSize - headerStackChildren.append(avatarImageNode) - - let authorMetaHeaderStack = ASStackLayoutSpec.horizontal() - authorMetaHeaderStack.alignItems = .center - authorMetaHeaderStack.spacing = 4 - authorMetaHeaderStack.children = [ - nameTextNode, - nameDotTextNode, - dateTextNode, - ] - let authorMetaStack = ASStackLayoutSpec.vertical() - authorMetaStack.children = [ - authorMetaHeaderStack, - usernameTextNode, - ] - - headerStackChildren.append(authorMetaStack) - - headerStack.children = headerStackChildren - - let verticalStack = ASStackLayoutSpec.vertical() - verticalStack.spacing = 10 - var verticalStackChildren: [ASLayoutElement] = [ - headerStack, - statusContentTextNode, - ] - if !mediaMultiplexImageNodes.isEmpty { - for (imageNode, meta) in zip(mediaMultiplexImageNodes, mosaicImageViewModel.metas) { - imageNode.style.preferredSize = AVMakeRect(aspectRatio: meta.size, insideRect: CGRect(origin: .zero, size: constrainedSize.max)).size - let layout = ASRatioLayoutSpec(ratio: meta.size.height / meta.size.width, child: imageNode) - verticalStackChildren.append(layout) - } - } - verticalStack.children = verticalStackChildren - - return ASInsetLayoutSpec( - insets: UIEdgeInsets(top: 12, left: 16, bottom: 12, right: 16), - child: verticalStack - ) - } - -} - -// MARK: - ASEditableTextNodeDelegate -//extension StatusNode: ASMetaEditableTextNodeDelegate { -// func metaEditableTextNode(_ textNode: ASMetaEditableTextNode, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool { -// guard let activityEntityType = ActiveEntityType(url: URL) else { -// return false -// } -// defer { -// delegate?.statusNode(self, statusContentTextNode: textNode, didSelectActiveEntityType: activityEntityType) -// } -// return false -// } -//} - -// MARK: - ASMultiplexImageNodeDataSource -extension StatusNode: ASMultiplexImageNodeDataSource { - func multiplexImageNode(_ imageNode: ASMultiplexImageNode, urlForImageIdentifier imageIdentifier: ASImageIdentifier) -> URL? { - guard let imageNodeIndex = mediaMultiplexImageNodes.firstIndex(of: imageNode) else { return nil } - guard imageNodeIndex < mosaicImageViewModel.metas.count else { return nil } - let meta = mosaicImageViewModel.metas[imageNodeIndex] - switch imageIdentifier { - case "url" as NSString: - return meta.url - case "previewURL" as NSString: - return meta.previewURL - default: - assertionFailure() - return nil - } - } -} - -#endif diff --git a/Mastodon/Scene/Share/View/Node/Status/TimelineBottomLoaderNode.swift b/Mastodon/Scene/Share/View/Node/Status/TimelineBottomLoaderNode.swift deleted file mode 100644 index 0ec83dfe..00000000 --- a/Mastodon/Scene/Share/View/Node/Status/TimelineBottomLoaderNode.swift +++ /dev/null @@ -1,41 +0,0 @@ -// -// TimelineBottomLoaderNode.swift -// Mastodon -// -// Created by Cirno MainasuK on 2021-6-19. -// - -#if ASDK - -import UIKit -import AsyncDisplayKit - -final class TimelineBottomLoaderNode: ASCellNode { - - let activityIndicatorNode = ActivityIndicatorNode() - - override init() { - super.init() - - automaticallyManagesSubnodes = true - activityIndicatorNode.bounds = CGRect(x: 0, y: 0, width: 40, height: 40) - } - - override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec { - let contentStack = ASStackLayoutSpec.horizontal() - contentStack.alignItems = .center - contentStack.spacing = 7 - - contentStack.children = [activityIndicatorNode] - - return contentStack - } - - override func didEnterDisplayState() { - super.didEnterDisplayState() - activityIndicatorNode.animating = true - } - -} - -#endif diff --git a/Mastodon/Scene/Share/View/Node/Status/TimelineMiddleLoaderNode.swift b/Mastodon/Scene/Share/View/Node/Status/TimelineMiddleLoaderNode.swift deleted file mode 100644 index bd662ad7..00000000 --- a/Mastodon/Scene/Share/View/Node/Status/TimelineMiddleLoaderNode.swift +++ /dev/null @@ -1,54 +0,0 @@ -// -// TimelineMiddleLoaderNode.swift -// Mastodon -// -// Created by Cirno MainasuK on 2021-6-19. -// - -#if ASDK - -import UIKit -import AsyncDisplayKit - -final class TimelineMiddleLoaderNode: ASCellNode { - - static let loadButtonFont = UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 17, weight: .medium)) - - let activityIndicatorNode = ASDisplayNode(viewBlock: { - let view = UIActivityIndicatorView(style: .medium) - view.hidesWhenStopped = true - return view - }) - - let loadButtonNode = ASButtonNode() - - override init() { - super.init() - - automaticallyManagesSubnodes = true - - loadButtonNode.setAttributedTitle( - NSAttributedString( - string: L10n.Common.Controls.Timeline.Loader.loadMissingPosts, - attributes: [ - .foregroundColor: Asset.Colors.brandBlue.color, - .font: TimelineMiddleLoaderNode.loadButtonFont - ]), - for: .normal - ) - } - - override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec { - let contentStack = ASStackLayoutSpec.horizontal() - contentStack.alignItems = .center - contentStack.spacing = 7 - - contentStack.children = [loadButtonNode] - - - return contentStack - } - -} - -#endif diff --git a/Mastodon/Supporting Files/AppDelegate.swift b/Mastodon/Supporting Files/AppDelegate.swift index e2cb7c41..6d7919c6 100644 --- a/Mastodon/Supporting Files/AppDelegate.swift +++ b/Mastodon/Supporting Files/AppDelegate.swift @@ -12,10 +12,6 @@ import AppShared import AVFoundation @_exported import MastodonUI -#if ASDK -import AsyncDisplayKit -#endif - @main class AppDelegate: UIResponder, UIApplicationDelegate { @@ -41,13 +37,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate { count += 1 // Int64. could ignore overflow here UserDefaults.shared.processCompletedCount = count - #if ASDK && DEBUG - // PerformanceMonitor.shared().start() - // ASDisplayNode.shouldShowRangeDebugOverlay = true - // ASControlNode.enableHitTestDebug = true - // ASImageNode.shouldShowImageScalingOverlay = true - #endif - return true } diff --git a/Mastodon/Vender/ActivityIndicatorNode.swift b/Mastodon/Vender/ActivityIndicatorNode.swift deleted file mode 100644 index 8778f5ec..00000000 --- a/Mastodon/Vender/ActivityIndicatorNode.swift +++ /dev/null @@ -1,75 +0,0 @@ -// ref: https://github.com/Adlai-Holler/ASDKPlaceholderTest/blob/eea9fa7cff2d16a57efb47d208422ea9b49a630a/ASDKPlaceholderTest/ASDisplayNodeSubclasses.swift - -#if ASDK - -import Foundation -import AsyncDisplayKit -import UIKit - -/** - A node that shows a `UIActivityIndicatorView`. Does not support layer backing. - Note: You must not change the style to or from `.WhiteLarge` after init, or the node's size will not update. - */ -class ActivityIndicatorNode: ASDisplayNode { - - private static let defaultSize = CGSize(width: 20, height: 20) - private static let largeSize = CGSize(width: 37, height: 37) - - init(style: UIActivityIndicatorView.Style = .medium) { - super.init() - setViewBlock { - UIActivityIndicatorView(style: style) - } - - self.style.preferredSize = style == .large ? ActivityIndicatorNode.defaultSize : ActivityIndicatorNode.largeSize - } - - var activityIndicatorView: UIActivityIndicatorView { - return view as! UIActivityIndicatorView - } - - override func didLoad() { - super.didLoad() - if animating { - activityIndicatorView.startAnimating() - } - activityIndicatorView.color = color - activityIndicatorView.hidesWhenStopped = hidesWhenStopped - } - - /// Wrapper for `UIActivityIndicatorView.hidesWhenStopped`. NOTE: You must respect thread affinity. - var hidesWhenStopped = true { - didSet { - if isNodeLoaded { - assert(Thread.isMainThread) - activityIndicatorView.hidesWhenStopped = hidesWhenStopped - } - } - } - - /// Wrapper for `UIActivityIndicatorView.color`. NOTE: You must respect thread affinity. - var color: UIColor? { - didSet { - if isNodeLoaded { - assert(Thread.isMainThread) - activityIndicatorView.color = color - } - } - } - - /// Wrapper for `UIActivityIndicatorView.animating`. NOTE: You must respect thread affinity. - var animating = false { - didSet { - if isNodeLoaded { - assert(Thread.isMainThread) - if animating { - activityIndicatorView.startAnimating() - } else { - activityIndicatorView.stopAnimating() - } - } - } - } -} - -#endif diff --git a/Podfile b/Podfile index 868af1a9..4a2e7bc6 100644 --- a/Podfile +++ b/Podfile @@ -8,7 +8,6 @@ target 'Mastodon' do # UI pod 'UITextField+Shake', '~> 1.2' - pod 'Texture', '~> 3.0.0', :configurations => ['ASDK - Debug', 'ASDK - Release'] # misc pod 'SwiftGen', '~> 6.4.0' @@ -16,7 +15,7 @@ target 'Mastodon' do pod 'Kanna', '~> 5.2.2' # DEBUG - pod 'FLEX', '~> 4.4.0', :configurations => ['Debug', 'ASDK - Debug'] + pod 'FLEX', '~> 4.4.0', :configurations => ['Debug'] target 'MastodonTests' do inherit! :search_paths @@ -63,4 +62,4 @@ post_install do |installer| config.build_settings.delete 'IPHONEOS_DEPLOYMENT_TARGET' end end -end \ No newline at end of file +end diff --git a/Podfile.lock b/Podfile.lock index 3541289d..ea4ef823 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -3,42 +3,7 @@ PODS: - FLEX (4.4.1) - Kanna (5.2.7) - Keys (1.0.1) - - PINCache (3.0.3): - - PINCache/Arc-exception-safe (= 3.0.3) - - PINCache/Core (= 3.0.3) - - PINCache/Arc-exception-safe (3.0.3): - - PINCache/Core - - PINCache/Core (3.0.3): - - PINOperation (~> 1.2.1) - - PINOperation (1.2.1) - - PINRemoteImage/Core (3.0.3): - - PINOperation - - PINRemoteImage/iOS (3.0.3): - - PINRemoteImage/Core - - PINRemoteImage/PINCache (3.0.3): - - PINCache (~> 3.0.3) - - PINRemoteImage/Core - SwiftGen (6.4.0) - - Texture (3.0.0): - - Texture/AssetsLibrary (= 3.0.0) - - Texture/Core (= 3.0.0) - - Texture/MapKit (= 3.0.0) - - Texture/Photos (= 3.0.0) - - Texture/PINRemoteImage (= 3.0.0) - - Texture/Video (= 3.0.0) - - Texture/AssetsLibrary (3.0.0): - - Texture/Core - - Texture/Core (3.0.0) - - Texture/MapKit (3.0.0): - - Texture/Core - - Texture/Photos (3.0.0): - - Texture/Core - - Texture/PINRemoteImage (3.0.0): - - PINRemoteImage/iOS (~> 3.0.0) - - PINRemoteImage/PINCache - - Texture/Core - - Texture/Video (3.0.0): - - Texture/Core - "UITextField+Shake (1.2.1)" DEPENDENCIES: @@ -47,7 +12,6 @@ DEPENDENCIES: - Kanna (~> 5.2.2) - Keys (from `Pods/CocoaPodsKeys`) - SwiftGen (~> 6.4.0) - - Texture (~> 3.0.0) - "UITextField+Shake (~> 1.2)" SPEC REPOS: @@ -55,11 +19,7 @@ SPEC REPOS: - DateToolsSwift - FLEX - Kanna - - PINCache - - PINOperation - - PINRemoteImage - SwiftGen - - Texture - "UITextField+Shake" EXTERNAL SOURCES: @@ -71,13 +31,9 @@ SPEC CHECKSUMS: FLEX: 7ca2c8cd3a435ff501ff6d2f2141e9bdc934eaab Kanna: 01cfbddc127f5ff0963692f285fcbc8a9d62d234 Keys: a576f4c9c1c641ca913a959a9c62ed3f215a8de9 - PINCache: 7a8fc1a691173d21dbddbf86cd515de6efa55086 - PINOperation: 00c935935f1e8cf0d1e2d6b542e75b88fc3e5e20 - PINRemoteImage: f1295b29f8c5e640e25335a1b2bd9d805171bd01 SwiftGen: 67860cc7c3cfc2ed25b9b74cfd55495fc89f9108 - Texture: 2f109e937850d94d1d07232041c9c7313ccddb81 "UITextField+Shake": 298ac5a0f239d731bdab999b19b628c956ca0ac3 -PODFILE CHECKSUM: 4db0bdf969729c5758bd923e33d9e097cb892086 +PODFILE CHECKSUM: 37aa3ed14a767c806ece40b6c99ab3c59b9f8475 COCOAPODS: 1.11.2 From 4a38daa345df4fab6d006e5aea4f5f61fc96b9c3 Mon Sep 17 00:00:00 2001 From: CMK Date: Fri, 31 Dec 2021 16:47:13 +0800 Subject: [PATCH 02/12] feat: update Welcome scene UI --- Localization/app.json | 6 +- Mastodon.xcodeproj/project.pbxproj | 20 ++- .../xcschemes/xcschememanagement.plist | 8 +- Mastodon/Coordinator/SceneCoordinator.swift | 24 +-- Mastodon/Generated/Assets.swift | 3 + .../cloud.base.extend.imageset/Contents.json | 23 +++ .../cloud.base.extend.png | Bin 0 -> 19225 bytes .../cloud.base.extend@2x.png | Bin 0 -> 53758 bytes .../cloud.base.extend@3x.png | Bin 0 -> 74552 bytes .../Contents.json | 23 +++ .../elephant.three.on.grass.extend.png | Bin 0 -> 55254 bytes .../elephant.three.on.grass.extend@2x.png | Bin 0 -> 155322 bytes .../elephant.three.on.grass.extend@3x.png | Bin 0 -> 286348 bytes .../Contents.json | 20 +++ .../OnboardingViewControllerAppearance.swift | 4 +- .../Welcome/View/GradientBorderView.swift | 59 +++++++ .../View/WelcomeIllustrationView.swift | 103 ++++++++++-- .../Welcome/WelcomeViewController.swift | 147 +++++++++++++----- .../Scene/Wizard/WizardViewController.swift | 2 +- 19 files changed, 363 insertions(+), 79 deletions(-) create mode 100644 Mastodon/Resources/Assets.xcassets/Scene/Welcome/illustration/cloud.base.extend.imageset/Contents.json create mode 100644 Mastodon/Resources/Assets.xcassets/Scene/Welcome/illustration/cloud.base.extend.imageset/cloud.base.extend.png create mode 100644 Mastodon/Resources/Assets.xcassets/Scene/Welcome/illustration/cloud.base.extend.imageset/cloud.base.extend@2x.png create mode 100644 Mastodon/Resources/Assets.xcassets/Scene/Welcome/illustration/cloud.base.extend.imageset/cloud.base.extend@3x.png create mode 100644 Mastodon/Resources/Assets.xcassets/Scene/Welcome/illustration/elephant.three.on.grass.extend.imageset/Contents.json create mode 100644 Mastodon/Resources/Assets.xcassets/Scene/Welcome/illustration/elephant.three.on.grass.extend.imageset/elephant.three.on.grass.extend.png create mode 100644 Mastodon/Resources/Assets.xcassets/Scene/Welcome/illustration/elephant.three.on.grass.extend.imageset/elephant.three.on.grass.extend@2x.png create mode 100644 Mastodon/Resources/Assets.xcassets/Scene/Welcome/illustration/elephant.three.on.grass.extend.imageset/elephant.three.on.grass.extend@3x.png create mode 100644 Mastodon/Resources/Assets.xcassets/Scene/Welcome/sign.in.button.background.colorset/Contents.json create mode 100644 Mastodon/Scene/Onboarding/Welcome/View/GradientBorderView.swift diff --git a/Localization/app.json b/Localization/app.json index 6d3b2fcc..3b39a713 100644 --- a/Localization/app.json +++ b/Localization/app.json @@ -193,7 +193,9 @@ }, "scene": { "welcome": { - "slogan": "Social networking\nback in your hands." + "slogan": "Social networking\nback in your hands.", + "get_started": "Get Started", + "log_in": "Log In" }, "server_picker": { "title": "Pick a server,\nany server.", @@ -554,4 +556,4 @@ "accessibility_hint": "Double tap to dismiss this wizard" } } -} \ No newline at end of file +} diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index 895b4aca..bb7a8a4f 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -191,6 +191,7 @@ DB03F7F32689AEA3007B274C /* ComposeRepliedToStatusContentTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB03F7F22689AEA3007B274C /* ComposeRepliedToStatusContentTableViewCell.swift */; }; DB03F7F52689B782007B274C /* ComposeTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB03F7F42689B782007B274C /* ComposeTableView.swift */; }; DB040ED126538E3D00BEE9D8 /* Trie.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB040ED026538E3C00BEE9D8 /* Trie.swift */; }; + DB0617EB277EF3820030EE79 /* GradientBorderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0617EA277EF3820030EE79 /* GradientBorderView.swift */; }; DB084B5725CBC56C00F898ED /* Status.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB084B5625CBC56C00F898ED /* Status.swift */; }; DB0AC6FC25CD02E600D75117 /* APIService+Instance.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0AC6FB25CD02E600D75117 /* APIService+Instance.swift */; }; DB0C946526A6FD4D0088FB11 /* AlamofireImage in Frameworks */ = {isa = PBXBuildFile; productRef = DB0C946426A6FD4D0088FB11 /* AlamofireImage */; }; @@ -969,6 +970,7 @@ DB03F7F22689AEA3007B274C /* ComposeRepliedToStatusContentTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeRepliedToStatusContentTableViewCell.swift; sourceTree = ""; }; DB03F7F42689B782007B274C /* ComposeTableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeTableView.swift; sourceTree = ""; }; DB040ED026538E3C00BEE9D8 /* Trie.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Trie.swift; sourceTree = ""; }; + DB0617EA277EF3820030EE79 /* GradientBorderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GradientBorderView.swift; sourceTree = ""; }; DB084B5625CBC56C00F898ED /* Status.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Status.swift; sourceTree = ""; }; DB0AC6FB25CD02E600D75117 /* APIService+Instance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+Instance.swift"; sourceTree = ""; }; DB0C946A26A700AB0088FB11 /* MastodonUser+Property.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MastodonUser+Property.swift"; sourceTree = ""; }; @@ -2993,6 +2995,7 @@ children = ( DBABE3EB25ECAC4B00879EE5 /* WelcomeIllustrationView.swift */, DB4932B026F1FB5300EF46D4 /* WizardCardView.swift */, + DB0617EA277EF3820030EE79 /* GradientBorderView.swift */, ); path = View; sourceTree = ""; @@ -4307,6 +4310,7 @@ DB4932B326F2054200EF46D4 /* CircleAvatarButton.swift in Sources */, 0FB3D30825E524C600AAD544 /* PickServerCategoriesCell.swift in Sources */, 2D4AD8A226316CD200613EFC /* SelectedAccountSection.swift in Sources */, + DB0617EB277EF3820030EE79 /* GradientBorderView.swift in Sources */, DB789A1225F9F2CC0071ACA0 /* ComposeViewModel.swift in Sources */, DBB525362611ECEB002F1F29 /* UserTimelineViewController.swift in Sources */, DB6D1B3D2636857500ACB481 /* AppearancePreference.swift in Sources */, @@ -4838,7 +4842,7 @@ SWIFT_OBJC_BRIDGING_HEADER = "Mastodon/Vender/Mastodon-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 1; + TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; }; name = Debug; @@ -4866,7 +4870,7 @@ PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = "Mastodon/Vender/Mastodon-Bridging-Header.h"; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 1; + TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; }; name = Release; @@ -5131,7 +5135,7 @@ SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "APP_EXTENSION $(inherited)"; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 1; + TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; }; name = Debug; @@ -5156,7 +5160,7 @@ SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "APP_EXTENSION $(inherited)"; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 1; + TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; }; name = Release; @@ -5181,7 +5185,7 @@ SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "APP_EXTENSION $(inherited)"; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 1; + TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; }; name = Debug; @@ -5206,7 +5210,7 @@ SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "APP_EXTENSION $(inherited)"; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 1; + TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; }; name = Release; @@ -5230,7 +5234,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 1; + TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; }; name = Debug; @@ -5254,7 +5258,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 1; + TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; }; name = Release; diff --git a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist index 55e94fa7..8bd09ebc 100644 --- a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist @@ -7,12 +7,12 @@ AppShared.xcscheme_^#shared#^_ orderHint - 24 + 18 CoreDataStack.xcscheme_^#shared#^_ orderHint - 26 + 19 Mastodon - ASDK.xcscheme_^#shared#^_ @@ -102,7 +102,7 @@ MastodonIntent.xcscheme_^#shared#^_ orderHint - 27 + 21 MastodonIntents.xcscheme_^#shared#^_ @@ -122,7 +122,7 @@ ShareActionExtension.xcscheme_^#shared#^_ orderHint - 25 + 20 SuppressBuildableAutocreation diff --git a/Mastodon/Coordinator/SceneCoordinator.swift b/Mastodon/Coordinator/SceneCoordinator.swift index c10b60d4..d3591ab4 100644 --- a/Mastodon/Coordinator/SceneCoordinator.swift +++ b/Mastodon/Coordinator/SceneCoordinator.swift @@ -255,7 +255,7 @@ extension SceneCoordinator { DispatchQueue.main.async { self.present( scene: .welcome, - from: nil, + from: self.sceneDelegate.window?.rootViewController, transition: .modal(animated: animated, completion: nil) ) } @@ -304,14 +304,20 @@ extension SceneCoordinator { presentingViewController.showDetailViewController(navigationController, sender: sender) case .modal(let animated, let completion): - let modalNavigationController: UINavigationController = { - if scene.isOnboarding { - return AdaptiveStatusBarStyleNavigationController(rootViewController: viewController) - } else { - return UINavigationController(rootViewController: viewController) - } - }() - modalNavigationController.modalPresentationCapturesStatusBarAppearance = true +// let modalNavigationController: UINavigationController = { +// if scene.isOnboarding { +// return AdaptiveStatusBarStyleNavigationController(rootViewController: viewController) +// } else { +// return UINavigationController(rootViewController: viewController) +// } +// }() +// modalNavigationController.modalPresentationCapturesStatusBarAppearance = true +// if let adaptivePresentationControllerDelegate = viewController as? UIAdaptivePresentationControllerDelegate { +// modalNavigationController.presentationController?.delegate = adaptivePresentationControllerDelegate +// } +// presentingViewController.present(modalNavigationController, animated: animated, completion: completion) + + let modalNavigationController = UINavigationController(rootViewController: viewController) if let adaptivePresentationControllerDelegate = viewController as? UIAdaptivePresentationControllerDelegate { modalNavigationController.presentationController?.delegate = adaptivePresentationControllerDelegate } diff --git a/Mastodon/Generated/Assets.swift b/Mastodon/Generated/Assets.swift index 906dd74e..5098d05f 100644 --- a/Mastodon/Generated/Assets.swift +++ b/Mastodon/Generated/Assets.swift @@ -102,8 +102,10 @@ internal enum Asset { internal enum Welcome { internal enum Illustration { internal static let backgroundCyan = ColorAsset(name: "Scene/Welcome/illustration/background.cyan") + internal static let cloudBaseExtend = ImageAsset(name: "Scene/Welcome/illustration/cloud.base.extend") internal static let cloudBase = ImageAsset(name: "Scene/Welcome/illustration/cloud.base") internal static let elephantOnAirplaneWithContrail = ImageAsset(name: "Scene/Welcome/illustration/elephant.on.airplane.with.contrail") + internal static let elephantThreeOnGrassExtend = ImageAsset(name: "Scene/Welcome/illustration/elephant.three.on.grass.extend") internal static let elephantThreeOnGrass = ImageAsset(name: "Scene/Welcome/illustration/elephant.three.on.grass") internal static let elephantThreeOnGrassWithTreeThree = ImageAsset(name: "Scene/Welcome/illustration/elephant.three.on.grass.with.tree.three") internal static let elephantThreeOnGrassWithTreeTwo = ImageAsset(name: "Scene/Welcome/illustration/elephant.three.on.grass.with.tree.two") @@ -112,6 +114,7 @@ internal enum Asset { internal static let mastodonLogoBlackLarge = ImageAsset(name: "Scene/Welcome/mastodon.logo.black.large") internal static let mastodonLogo = ImageAsset(name: "Scene/Welcome/mastodon.logo") internal static let mastodonLogoLarge = ImageAsset(name: "Scene/Welcome/mastodon.logo.large") + internal static let signInButtonBackground = ColorAsset(name: "Scene/Welcome/sign.in.button.background") } } internal enum Settings { diff --git a/Mastodon/Resources/Assets.xcassets/Scene/Welcome/illustration/cloud.base.extend.imageset/Contents.json b/Mastodon/Resources/Assets.xcassets/Scene/Welcome/illustration/cloud.base.extend.imageset/Contents.json new file mode 100644 index 00000000..421e01a3 --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Scene/Welcome/illustration/cloud.base.extend.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "cloud.base.extend.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "cloud.base.extend@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "cloud.base.extend@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Scene/Welcome/illustration/cloud.base.extend.imageset/cloud.base.extend.png b/Mastodon/Resources/Assets.xcassets/Scene/Welcome/illustration/cloud.base.extend.imageset/cloud.base.extend.png new file mode 100644 index 0000000000000000000000000000000000000000..3c8443c9fc99c3f6dbfacf15da4c57dab6f91bb0 GIT binary patch literal 19225 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 literal 0 HcmV?d00001 diff --git a/Mastodon/Resources/Assets.xcassets/Scene/Welcome/illustration/cloud.base.extend.imageset/cloud.base.extend@2x.png b/Mastodon/Resources/Assets.xcassets/Scene/Welcome/illustration/cloud.base.extend.imageset/cloud.base.extend@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b03b6720aeb5d0e3bc76caf24759e5689b32e2e2 GIT binary patch literal 53758 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 GBmM_D$$rHE literal 0 HcmV?d00001 diff --git a/Mastodon/Resources/Assets.xcassets/Scene/Welcome/illustration/cloud.base.extend.imageset/cloud.base.extend@3x.png b/Mastodon/Resources/Assets.xcassets/Scene/Welcome/illustration/cloud.base.extend.imageset/cloud.base.extend@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..f77476855f0efacc14dc02c43b2e427bcafbb951 GIT binary patch literal 74552 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 literal 0 HcmV?d00001 diff --git a/Mastodon/Resources/Assets.xcassets/Scene/Welcome/illustration/elephant.three.on.grass.extend.imageset/elephant.three.on.grass.extend@2x.png b/Mastodon/Resources/Assets.xcassets/Scene/Welcome/illustration/elephant.three.on.grass.extend.imageset/elephant.three.on.grass.extend@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..63580f3ce643cc461e20a5b192f16caa2ca7a141 GIT binary patch literal 155322 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 literal 0 HcmV?d00001 diff --git a/Mastodon/Resources/Assets.xcassets/Scene/Welcome/illustration/elephant.three.on.grass.extend.imageset/elephant.three.on.grass.extend@3x.png b/Mastodon/Resources/Assets.xcassets/Scene/Welcome/illustration/elephant.three.on.grass.extend.imageset/elephant.three.on.grass.extend@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..8799a731301e7c8c15b7f2d45bcf729b301d4d9e GIT binary patch literal 286348 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 z }Ze6#?Tzv@T*UvoMxs<%H*7fRy1`m5+)?7C_2K;hbl4-wZ=T7FH@8rS3%n-T`` zj8nLg(T2J8f_qa=_=u8%Mi2SFV+I7rQ_oiV{l{nc+gYY@`LXBZDtYQybwa&UwOrX{ z(+_Y>snlk;?X?scj76a6BhN-ldhSvI)z^JrSO6;L700U!cE`a zrA%`ym2k>Uc_`#jFU1i~mhhVN+1x8BATo zK~-j~R9&)?D#k(*V9Ok($3nUMo?XN{msaC7Spn~VUF}Jf`kS__!&J#j)K*>;|41mN zoG=j6PK=T*ptv}_&pD0VYRzHgXcIKxq_sU$^tDp1?HN>JuSt!` z_~F-O8s6pr2qO#@LWW)_ozHDsm;M|`l)>~@v71u0S90A+v{Ox3Acf=*_*2e-9f1q{ zA`u{C3oACs;h9P3Tm%Oye~a#KSLhc;HI5{k9hF{s@JW(!1vSsUabo3y)?KcyILpIr zBfc~ABvT5FgY!gZSIsa8t2UJ_$QsVzfR8*j$UhiHokMKm23`?w$`fLonh{&sx!BG= z{G{)cn>INol7Yky>&(J0EF1o%DIPa(|6O5JGtGY*RDAJW;iwrl9cVOBcFJFgO?ib&xXsy-Am}2})(9efTE0TT zeUB6P;(FQ8G$+xt#~!;&;j_fOOtqI7KmF=W@=80rJ&W12f*n)ciyLeHyR$9~-{t^L z`P{3V?Br~<^KVsSc`gd|xFvOzN`gNp=WmH4rauvIk@3RfWvn^7^!^)F8}Ao6?d7wo+kemgL- zd){Vi9vv1sCH13y?l>>8R!jV@7=}(7osrc1?9KA3a-?zq#CxNb9mOl*4v3A$z&CV%2>cE-{v$c)-$f{W%fFzscT{l;OX@4F+vVB7Ai zS!M_>xjwvRc{WcWEms8Rz3 zHX%7&wH!Bmi3jKZy;}*y>?QdXvKc7`2$H-)$Ov~7@UE@WqePv|-xN&~6iy(O)~9XG z^g9Mztr6>A3-beqg)%<2epUo>mry`z+|3eQ36`rG#pkp#Rs@JE z9P8NF?(b1g9E-cZyNV*Nyrq2PBknYnI2|Cp5p(v)RCR)uU=EaZHa;ijKGwJVIq?g_!VNgwn z%zrrIMoYf&&kHZ{g)(F@k&0j`R#!UCo!ov|U>K>VMGfr@s+k)c z@$5+Gr7;)G-bJ_dM1w%tXXD42T4z@4LmvnNIhs7<_LcYB;GI z4^_;rY)`M!zQgP~sWRdN$^BZ;tm1;A9D3DU&n?Q{!luR?c&on}p{MRYTjqG$A+_z&LDk)w~u8(n6mBoH!jO+}kTax?5oGFVAePuts zFDrnq2E1+AkiK~VnX5G=^#6_{?ueMj^4+n=<2!R3AgLIK$-rxtOcRQ2bnY~QmA)Tf z=_>@s3o86~Ipx3r2H3gR1y!il>EEM~geYCI@s6 zC7RSjhNz?YxKKDgc0lE&^5Shqip)!E;bWe@!~tTs%P!LD!MsRAd$~jlh#FjX-guUzN{0dtMI{No9|NilpsY<)N&cF2Q z_Ip;VV%;uVG5IRC94-bd)iVrz5lv!i#?nkiXr>pw?$NA$Cif~}Nf?>@1zGpW1aLyV z+3rmRQ4DRB?pK{>f|Jt@vgWkbgH(Ej(B`s4ULp41!;nkbPDJ`&okEoF4*n3fe2U#e z^wTYNHuPMsFcJvQ*n3!2$K6bg6Chbn7{;+=TI7y5wFaTt#!A8g)j!UHgfeGHKb3ve z7D30OMuzTI+K;gXXJlBf(a^dX+GTlVX5S_~X#+WK;@zRa z1sUPprV-cpdwe#p<$2@?RYccU%HBCvm^$!(++GH|5ZN_y%5BqVXe^drEQMRUMfg$i zpXV?<2}`!6&e%y?sntTy^mWK+9xna!@r748ux@#(mVWfE3&mBv`?vjjE(-C8(;CB) ze55UgneNI)S2O|iMmT3Es_YH~r+6%2iGEP{wR1ut_T3Mk^3CivYKOm4Q#&<2A1@)sH^~Ys>PlE#?m0F1RB(EdPu}IMvKbE`j<> z9+c*Bh5anr@v53Kq-Dq@an+EBLCF9;QDWcOfht00jj1kD6_ae?;13wFe42LQ1QI54 z&<-#M2-*$EJsx@;bCj%5mUx=j@t8X7KG&~5AWr<`^q__A*>DDTpH(rc@o#PdD?1ez zR3U~IT3=cr_JN7naU^*x0@&78QHFr=;l@t0zJW7N$+gl*sdF^e{>2Q~wEZ(8AuM4` zD2i{G?cpb}6qM(-)!=H9@7IddCv=7dmr#Nu%&;8Gk4L93MGIMDki&O1!BNMbNi+eH zF8f@W#z5_-y9*d7IRt5h3z~IE`G#MsrLHLQ-cH3ZPFkMEgd+iQ*AVQ~Yn;Yuy+lPW z?QXpV8+!Twjv*(HY-7oQ)jGL~irYo^8L^u@ehXH$_L}@}pKey417=G2TS@trPi8gJ zLLDWC=`j<)oWFh%Ta_9_^K&|13mVKX~jMg_}-R`|f@o_5Y80 zAWP%dV3Rg98r!1qFDe*W#(9c4^zkjs^pnaA@L*T12?WM81#Mc$WO(BUPnDQvwl7}6 zr|d?N`E4O)$0~9HK5&&m;n6G*MZBKxch;4oZ!3VYR%Do{cK{y3t#VTd8kKc!yM|s~vI_?M6 zba3B)0P2xCz3SKCz%&b=WmdR#odg}s{$V!b?1~vMesz6Izp%7GGX!p>Dm{$Ow<~Dt zrhSVQ6^Z3gBAh#*zg?e-+d8-av2u*8awI5vt%X?W+pSO!>8fNlTHvPVM&Fe9f&Q1W zWr}~-DHF<&;@JA$h3DK2*~87(1=tB=pQHos0}YfGJnQ|LQR^@cJsSiGY{=+^^ktkr z+J(5}*nJ}Ay0LZ(UWEBk9tI70HAq|0yG$3mg`1PoW)CTq?nLDGj}I8Et^Zyx`4Fzz$njjRJ&a#pR#@Qy)hz}tB(AT7x;ocyOIpFRNMu1Embjw;IguEh z0^?Yz!eI)+d`cjqA^8L!Hi(n+VU1DkBPR|P`847VeLV#>T_>fb_j}Z>KFcJo*fYJz z@$i&z4iNoqr|#l*CNrn>qZw+y!GILaQy&Y`$L{K}%l6P=9;~z=rf&dSoC1%$*AXeO zlMYt*_4h_CbLDSZld4i1XlO1<(Lo zYo%Bjm3OJ2i9MSLPDKy{8{E1c(-?tJFq;4?sqHUx{Qln^#OWxtajGEBd~3WGHeXKI zupvp)m7jEk^kRy8C8vm1GT&*cEnDu*kVqAOnw#pv()U3hI9CcnTskhE?~*L=5CAt< z)mUL^O|zle;^>VXli#QFEHI>`{LFc(Y-EzI^?;DSr|0Btb;7~IucR``RSb^}(a-B5 z$7dr7zmPD9N#Bp1^D+SS0ML-g2EGdD46r%X@_LuN<I%8uF`x?&{3aZEsU1OZ{b#6U@ODaDh#V)WESsC8x z%ZMt8_TM_V#hEqx5ou$EWeXG3M%oE9PlD*q7g10TQBu}FIUU%h?Hi=_x~q1EtgW>7 zrvbbM%5H0l?(jlg@qBsL!Y=D@7H2UvRaOmYDtGExoEksdD9%{K{tT^vOwZNj3{_pVJJ%0_zjy!EY zw^6vHM>BbjIXV1H%K3ST`6q*yDhZ^dT0l08a4IGDd|y&zC~UMv{|LRGL+f+d*q8ee zx?S4hR*?D*Y#9y8pem&T`N25lXmR>aUSVE>Dbj0kOTMW+qWSioRo?;nPxrrvgMCTB z=J#ywxQ=WeTf!7>o5gQ+I)`o(Wm~Grr{S^v&Vr$r_6py1U}2X(>=#y}*!!n!yGiGF znf>J`83&$I^$odE4>>z7TZ>Yt>z!+_IGg(etTAT7+RH)~im%~q`dk@&$C?9Aj?G0* zfK`K!@9ylc5^AU>$$A|4_J~RZv~F5HEb`D*{w8l|EC`HEr<&Ke|>Um~2af4XtpXPkO@UDN_~4eC0i5IoR~= zefAla|E89~tu2~5fAS+e>LJS3_4=#s{AmSQzCXAod@tN-nE>Czqj|X7&JtQgp;S1_ z*sj(_E0U%3A$v&@R%bnkDNQ*a7?R_GOd~==W7lJCM6xY-uNKw>IDNC>BH{bze*Rm) zZ4%vK{K*{W55!)WpO`VR75r)#{5~N9g#h(8&_gJUe?+jjCYHw5(@fDE>E(z1^ zfg9-5=ZWs#klAq6DT5hO^fxj90d+7uHuO@I^#|XS^CIz%dlq32#=N2W`)T@U>S!}A#n?I}D?;tw$_w>y+){2wU+dEw3O=b!UJzfK z<`e6kgC{mS^9I#e4onWG*9BM2lL7bN_2R8Qv|EO?ZahmSZ1n4j_|X zW^e4%ReK^nf4=@z??OvMSG@Jiu!g-14{>LGJD{GiXfd>M&6N{DGnZZ1JJ==SGciXi zY_2nBcOA^ziAn+oYc_-at5h<+^0~*hXSAurZK=YlCCquZLK*V&s$K!xck#pKyqM=>Xefzif3%^S6O2HL4JS_! zIOV6-u*Sw$!?XUU}9~ z!=-4x8+*W=Bk7=Xo7zK5i2?Oc1uR1z8BVGk4ahAWwonK=52wh{ipqnWvgXj(63?R&jL9SDm?7ie+95v?owGvztD9?Zn3 z!_mpM9?LxCVaUDDI7bMT>E8H0>+T3p6d{_*sC!tNzBm2T{()d}w4Nr8M^$Rs1mD5_ z&!N*yWm*zY&_d@e3;&C*L9S@_A1ES?B<^Nh@|k$Mo{=d##y(>-54l*R#Y}$aowd)_ zqx_MlGb}@E-aqBZz!!LP)=`H^9*AS$JvNN7d$HlJ*SG!F7q?I33KVxQ zLt}x{o2mEBo)H|rx2@6bZ)%rMt%a_`!f2A&xX3_Pz*YsQ+4QqNt>G`@wuE0U6KS|M zdZ9dY4Au_ecPH?5)E0{j#3A;+2BLdIqnk5lkKkt)7kT zPH=D7zlw|m$*JQ1L$m;y(=9cM04S)^7{}alR{(O{v3N*m@5x0v6i8+Dy|GK8b!I#1 z{!3BH8mu7@Ax8Jt4V^Rq$l6Cv3d^>K-;si9`kOT=Y)29r^`5np4w@VhA5}Azs-P{s z(U7XKXQ-tS;5@+vz?kYe{8yIwr23&6^D~3DWxd9AU`v9Vi1wrvY*ly%otzk?kGP&N zvW)fFgB_JcUNsuvXIvpF_lZQD0_;^?+ZAT|CLmIWVj}$ZGE~f~TS_h|7z`^Jot9>u zYf_>ds=C`FQ{JU0q87wsL^7uV`rQZIA|g|$P+cO{_d_r7U1`A|w-uA9tVJ-kFrT`H zVVH`x;k$ngLVl`ik|SPB1Aq84k;waHBJ6i=N00I`=P^rIbzkh-vTIHSJBs@FxQ}Qk_t(J}QY)sH>(j{n$W3WEGHrJv+eC8W{+uog{Prb9O+ z1zuE*b40&SDoNm~rGoIG14R-ACD+3yWD|-5wmWGSeF3=Ym*$Op7kV(lh+=Q6c0Tdt z2puy5P0!m$b=OPZ@LZW3=L=;2E~B>Ye{`JXvVA}TW$CkTvsn|Hq4k(EkMS_!MWX!E zzLHyhqec{AzBt8oRfPwBCuu4YI49?FR@8B1y=jq5XK6t)MtgSD4~mI$><*1i3&2F} zl)@>RL=QRNWV%ZRLW5{SgD_c1`B?Zq2!J)1OUWP(%>@&qsr=c zyADFUTn3CEO`0kc!vH<05NQg9CH{qo2FN(g;rC@6c~2Zc?jyp02n>_#2J{bbdR9PD zbY+p;GkSS5yEW>m0rclN5jL(#hkTz>#P@mY1QcUih-&RReexgsCAq&~Af zKUIr~d|d!Sb29uWP76=ATqY7)L;yqfw$V{7Kdj`c8W6Snj~4X#zgpHb2{4@m`UWLW zGN013sA^(WO4ZQ*jU?PhecQ#IQQB}QE5qyc?PF1@;jJVTFDN5*@B2^a`>a~j;KH!wD^27R%=~LstjVTXa7>}r3NL65Xl9JSauRpWk zWoTqXmFca1T;Vs>Qr7#2`|I8^a6&4>s{ke$6Y}2?i(!;i%el35reLIGQPtYNFpLJ2 z+2qyz`?-lI1{nd>|+$YR&5V(Ok;82R|qbt9v z6r8V7>o3thaD^A>iL+2CQ6oLvPwL)|o(K@?s>G_iSl#RS+v;rvRb5O-2ESCP6a-kB zu{V>hYL?tk1BBM=uqH(;E_!FgS9Zv+01HcR?;W>c9GHb=ZEgCh z_0G^scE`o1pJSBjkSAO-{TzF~9XolEo3I04;! zo5I76ONEMtjEcTP*-(xa7|!8KKr9L(#;W}kS2!x`ReM=LKly(&ePvjbUDx(acSv_h zgGdZ1-K})Dbf-uv-CYjdICOUoA>Ew=(k&_ZT|V#e{hwcZ_OkMY33kH{^$02v*z(cSn0Y8t}dtS-cvNO%Fkk&;g%2PW~FX})9OCpKaxlYP}>c?GTA>C ze+yP8jZHL^z-K_?#&f_Vd#^GXv`b2dnS~(S{AgQLF?oN1iIQUr{j8^PB2@ifF~n)7 zTSP|*Cz+)HB#~8$NAM;@gZ`s?NIhbEJWlPaN7VGyw?V_;pr4eW%*CzwN6zsF^@-?4 zeM@RKFYBP1j+#$}iNDHc+a^4f>Ggm%+l7P<+%Jy@-dD0d+!1t`*8b%ttt%;ACaCwX zCtvKDqzefMDmm-{{A0H{J|#r+>APmpU9csFHIU9ZlBb#dgEaP$WUvGx#HCUZU(+M# zE!4gZDv|N<;I*ho1ur&iHBg}LLt~`LM6nB57CNyPZaBs*_&jVSzYPEUoB^7|P1Ys; z&6V>JM~nI&B#x#9GdQJua{cy5Eiy2%j}Vh1tC(WT$6wR*LM2QV?Fk*^?z3l;VkkJg zx=9_w52}f=0b@ZgrY73H&rnJ+Fsw_%*EX_W=2(M1uhT#v|aP!Rp{JDt{(#=G4P;eH*XTt z8=rI#cvst&$X^D@OwTNTFqf$v?f+&&a0=vy1A02&{ccAuRLdmK-NLO&*y0#ol#uMX zUN`Ui@3hW0z_~b!d%pTNHirSzJWkGs7HXA*X+|#9xy|ngA`ZQ#D~ulQ!y139P`QxK z1idG<2-#hZkS8sLL`+&xM!xyMn9E(`<3|Q#k{#XpJ>KtG#@Uid0xt(`=~vE4H)U*p zWo)aA6FFwQ9300v1&S|O*zE1!EkhSI!Lshbiqaa@Tf!^~HhaNCtzhlSxBUso1(EA=7RzuqjTN9@IJ-7h{eAMdjf8`Qc zIG55q3DLXTz21&9ro5AcqYhqA5-y%uD--doHjmY||L7!EO^F+j7A}g%DtlneY)D)B zLKMl=Y$ihMD#!v=`w%CGL`6j?l5jueO*hoKR)%_YV>i=!S&zbRG8#5*)=*RkIQm?h z&hBkYW6pgR?{d+!pvK@K?ILkzvHwtu{RVh1liToC*pyL3MgIa>L%+ZHqGFeVh^ru? zpv+8a*6)M5>X|%5Htcw3DngjSNQqau7Xj6g@XSoXRLoM&UH5-)!|8P;Cm9 z+c2PHQ*7ZGp)7;Jq_#kUe()K8r4~;pv;w&h};2mc7I7>}a)%exA=fhU(%vS0^27CqV0}`NK=36y>#|k0J zl@JonIe*KD^+Rs%YVh#9P-R`&`Yn#ufU@izg^r>Y=}+Ksv+o%DKBz;vM(h9DyS>Y% zrVzre$E;`W{S}|E&j3;ipLaL&HviHT^O@kkoflA{cNi@iuWMpb3**&`%(qur_A!@u z(%WAf7)(c86Zl;I1R?GPd0*dSYhd0fhu1vd11<8qp^eQZIMyCvA^W3w{%VbmG;=XANEsG1H~5SBJ z$%I)e!uEFbquKJ;Qg?*DW7my*OF z%uyn&-!N(iHo!HXa(EKuin|Ap!IFEE3x5Yw-#S5OFqb?Iz?d`pG79@fXx3#XV|Zjc z0^j$prg>0#RidDH-(M2FoCQ81LLGA#7 H=qv>z6Uqw9G>q9n*??O zGMj8!F_y0yI)9^sGo-Bpo8qT?O=wk0f5~UnuJd*HPzTYB!HU#keP;}%s@J868aXkr zaaGMv{P=oozQlmlq&ho0T(e?M^=*xk30NG~TmJAp_POmGFfOcN-}b!;(fPM!^_FT$ z3Jc~-r0Y49mxC*DWY3bxczK!9Q8wQ%&w2kX7J5oG+y(^uYW@rK$* zZP(ZB)>}U%DbzEpOhbi9*gTO@@xoiUmoqB$Mz3_IV79z)`cl)~2WDQA@%Z)1Y$|JV zC~7ryczK@pd87(%BFyfIHO12+A7aTZ)G`wpOpKw#Q_F)NvKxd17JgTAb&nf9$%Kln zF{g+SH!t4qPZ>9BY?sMHHQzePI5|Jc*}wlaiv22aus!4NTMjiz0J$mDTexBd@Xymw zOcc-RNY!#FXX>eE4O1dUdbbIiTt~ATtMvY?T|zN$oFVgABnjPs1rY%AMETc+A#REH zfY4GXM{XXXd{oMfI!z7qSU}9S_$A|x6A+OY#PW?0_G;RQ?`@+Z0YDdns59we&Fo~W znMt0j1*eQ^JbrBfNC8;3)l9HO70r}uFQe%v!G z(%Ucw#VC5`U#@G?shqAg^MB2m{#zkU7RVQ3wsasU^6=O2L6BkWE$R@=cY)J!?pP(o zR<1K`52*w$8l)lMXn;1XUumdV?q%$r=8mC5=$^<>QuABh8N4WE1-Sas5^Y=;f>r2bgKaEd*zpyI%rrCPHPM7Ejo8OAz#3##A*9g62d3RRopv3HD zZH>Iy*zv|sc6*HJ5y4Lp4#GK{lIwpC<@MM!ktjTdY{k1=>S{WyQ9JeK{|y{JhHwW; z&6?Gt2u+42yf{=x)p2TwyrO%49+|+5_(M{-G?amzO3s~2JkY0xn?_8o^MHZx=Ca%^UDEN@L;A%`Qj{S=w-;aW`-;X$GO*DXexG> zBHa63zdcR*0@$aqE`)}i=hz9*9O_5|UyA_k$lq6gz&+o7y=ZuIre>~dgef*EUNZ{* zrADjuf>HiJ!Q03i(fn9KBXcv>l7Ykp`VeZFe4#~D;OkWpStcqLxWcwVb0Mfr`l=VE zmSVby^Jb9L+wQ^;BQ_OzElx>-y7NynF$cZhfXjP=-@NyF@)4qR8D#|Gwq}=7ri9in<^SVK;|ZwOC2myFXBt*l zZ~5;!izw!>O0faY82d*r5-emHOi8mljyw)7*)7mlG>IkknEstJ4a_eSf$!Y~nQ3n| z`|NwcLB;kiSQ}z6mWN zhz*vaAow+W`KFg*Ua2#r-yAo7SDjzK{M{)k9cD>G3p4fQyC1R7yb*2llG0jqshRvF zV(+0~_FtUO=*9D(B2Lb_vD}wzBJG7A_ogk$}~$zl+I}uxfij6yR6)AvHs6>v7Nmn&HVgR4%I#OhQTFD zL+BFsjNYe~dj5DH*ekq*m2DlVLRfC8V@(rmcmy-@H|X9B8BcJs7_^_ESa>MJG=enP zCqs(EjgTI^@Y`oH_lp0`=&Eo{Tc~v;U&xMKY-fA*8XDP5HMGXaZy+ar8+~&`w;Xjr zz!*57z)+R+n<! z?{!u4v`sre$OyKHa^0rZ%eizNKb~Fb`IJdqSn~7k9jhb9D6@%He~R6U`6bd7q%I3b zvtW!l#~d6ok8W!$Q7CHv(#nNI7aARVv?KAIOY5Dyv(jcB8}cULd~*DV?;s-3lis~9 ztKgg&SN<>sGHB5G)22J<>RcOKYtzMVLuq+I(uvq*R#fAychbQC{F7%Hrtsjk7JX*q6Lif7|8C$0DUM{=o9H?SfO z3nj%yG-#^|vK--H9tG6TU=x+MoiaFYu!*i(BMz2+{LM&YzH&IRzzrvmA4{=;k~a8l z(BU;4l|(YDnq`tj8mIZ>=4%Bt+%}TCUy97oh37IJ9aB%h-WsjvXR3#d07FN}lBT@!DDHt>h-c<5FDTFLD z_j`2zDdESAMhqoFQWgOtq=WQ|Zu|C97S$aTd^U(`g-iB;2NvUvtc4F%`B$i$jw#rI zeCY0n13>Fr{d9+lrR-UaW3PA@Z!DGMVyPcAyn$&eeW#P7k>`OX18$XZ(6;hm_uJbI zAWkE15{7zX^o`O21iLIeVN21Ble}Y)OL;4@PO}yx%(AMCC5kx5FuG??vgXZ3mYb{3 zZU}nye>&6NY2Vv=;mlOtU4%=7sF7GuFdocT8xzWjP9AJh{q+|9u|51bsC#n*3Q{~+ z>xZ<--Xsl=wpv=Kpq)K*upVZoa%c;qP*+uKd6h<{hCRk=@ji*%me7idk-!3dF9_ms z1|t-n{$Bc$w>%aew>(-q_u2~nbMClb@ey8s9IEVx zd=jy&nJTO$y2e076 zLIq(*3D$y==m7zj(;5!`d_DIHWj-Y>PB_Qp=g_M*&aqtwk8WHW2Yso_7QYvfCmT@l zmMa(&H~ewwgTOZ#`=ohegxG~umk!?l>T+;H&iiQ8mhxJZ3-2&M1)II@XBK-p{;R)CCG2X1RqoLh*DdSPyOJ#{F*mo+^isa+Kb$O6J#<*_kAfrk-r82NcUGZCTm5E1 zidhp(F==rBE;X;>{?VohNGmbLd)gmqZu>QFRq4h>&?E= zv29J~{JH@I=N|dTdoy9gsq$6tPcmK4E;uvQUHD>=D(RCba}Dt;iD z{jfFg1d0w21rPiIuvl9HdYgVibv@C%4$?1(*tKUR=9 za@mb-d*+3GNXzVvu$3=Q6+Jj%>(BAJzeBv$QUR1fqGY|s)!Kqm%=?&1Xq?gK6#I{` zP7}&quJGW7OT_ye!j@MDC9PHA+`l9PZ=6sXh6}|N7TqkG~EbYjCX1LQ~+Pe+ou<^K7@d0>qh{}ZF3@z zTUG0{(Jj)`Zum-A$=59O!P)ysWfoCE9oPmMi}ULiwIYXy__`~wB_W#q%@awSm+0J3 zqZ_|k=UO))y~Xjzyk)x3UjO=M*bTM8gy|QZ<=f2ijA-wCjM0y)RS5O|sQ;u`fLfjX z0nblxBdnPGKF=2;&B|D@)@nLg_IX0F_%Box3m_usjKGwGWeRVtK9aFuREJ3%iO)9G zEL?H^k`(q6?R#PGi3{}P*4Ith7Uju3!MeEn&_1$vGP+LtaLTvQ?T`Pu|9UUhySG9X z;C=46bQQoe^!F7=;b$_TN|dp;Tu;Jg)54SH_sL94 zo9*$_TkalUZ2eQLx%Te7Z|)X9k={$_0!Hv;fg`KpFXuaVI4^>L_k+NA?M?Z+-%wQN z=L1HE#iE;sKg&6_l@3^>jJDsx4tsldo92i)L_MXFP>qTHU0_Vu*s%miX2^;84HRO; zaa`|Qk;7uy>*6*SCoLx7P3V2-l=x}q2O|Yklix1GnuO_cn%DEi__!3heV56=GN`89 zdy0nrEPs>R>h6fZzp&uy?oY{oV8fruYJZzK5mFaZ=&o~TxVEwsa@>+}FDm-=8qqhH zHnNP?tK+}PHNdT`M*^3b)&`FrVxj|Woa$H*zw*H-aTK2gI5faAmV-(7+|o9meS#51 zbfn@_X9H+G=oDlMK2x_2EZ+dHta-Vi1x(O=OqEY&au_9`%{O%`Uk=*=rHZ@jExH7` z=+}r>9AaaZmqQNg+10(KdIbtx*`!JOr!cYj((s9#mZKIH!4i+C{$O%{PA3poA4$3?bG30`W^b*jlR zby!Fh?<66ihmdM?yE#Dr;#>gzt=9SHbR7r0ic2ph-rWA=BLlc!Yhk8@&vmx$*I`D#+F7* z=^O60?40KSa%Gy{=2U>8tTc3liIiF1#+%Wee0%h3vg@h??$B5>G`YZ#;!1<{$9>;u-(8VHFLHViHrA;6_i)fC z7aCwlVQ%LT>cy3g2q7k7{h&~l0qf!clrM2WG8T~{qic{JxZq45$f#M(^2~gfLEq95 zB@Uh2lOR7cnswr>t*r~1cOo9{g}arr5Edn|_;T=;UgFmkdt>kM#!22rX>88BoJ-(} z_3aiHwF*q4k1@XKQ;2aHyk#T_TQ3VHdR@m(EhlfpyC`i;4Q=Z#*CsjQzq)BZ_W zAaw0vB8hYCt@D{02eh?87vMRY*Fthev|mO-R!3d?{xYhMVWyjMes5*Lzm)(6f+FrD z&prK&M`hbero5P`nO<$N^NP~{T26f7pBvPU`9RBAUmMltB(?u(MyFX%0I$lMS z;sfH}=Q!+aKJ8sjliW|lQaL@lAbfc}!6u_$$hh4-l41P!IS#=BKx>m`$1u3TN4O+g z+1`(op4IUiBb0ddEpP7JI6muT0KXViiw}3ND$H+GN-O@gEz;jhgdMKovFbS2ir(TW zw>*Rvbm3#;k!w(b-FySL_A6-T3C}f))pv0E{Fckek=8GB8&tX5IoYzwb?R3mA&Gy! z4*~*W7>dm}N`ls(aJG5jY7##4!MsFiWYfG0So$6eWB&vUmsUN zF#Us>lC#0?FO=lxRrwoUX8Ls}fSMMUgI^)ToDaSB*_2vTB(1^AGYgrb8Ef*?;>W4C zK(g`v(TZga!)~W$4qcR=ezl0)mY9^RJ^8AhOkq77zyVIs!wp$1R^)6v!9Kd-;CoPU zIE_8*VsoweAobca^%j%rKI*n34vQfn|4*#2oJT&6UbxZ}AJ)SEy zeK;22c{m&9Y62l9*M9E_`H-Ffsv0x|=#qdHu@nZ%0DOO*# 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 Xu34(sI}yXdelCN1CVJ&}pS<`Vwc|h7 literal 0 HcmV?d00001 diff --git a/Mastodon/Resources/Assets.xcassets/Scene/Welcome/sign.in.button.background.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Scene/Welcome/sign.in.button.background.colorset/Contents.json new file mode 100644 index 00000000..7bf1f1e4 --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Scene/Welcome/sign.in.button.background.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x81", + "green" : "0xAC", + "red" : "0x58" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Scene/Onboarding/Share/OnboardingViewControllerAppearance.swift b/Mastodon/Scene/Onboarding/Share/OnboardingViewControllerAppearance.swift index 17c4699e..2405f2a8 100644 --- a/Mastodon/Scene/Onboarding/Share/OnboardingViewControllerAppearance.swift +++ b/Mastodon/Scene/Onboarding/Share/OnboardingViewControllerAppearance.swift @@ -15,9 +15,11 @@ protocol OnboardingViewControllerAppearance: UIViewController { extension OnboardingViewControllerAppearance { - static var actionButtonHeight: CGFloat { return 46 } + static var actionButtonHeight: CGFloat { return 50 } static var actionButtonMargin: CGFloat { return 12 } + static var actionButtonMarginExtend: CGFloat { return 80 } static var viewBottomPaddingHeight: CGFloat { return 11 } + static var viewBottomPaddingHeightExtend: CGFloat { return 22 } func setupOnboardingAppearance() { view.backgroundColor = Asset.Theme.Mastodon.systemGroupedBackground.color diff --git a/Mastodon/Scene/Onboarding/Welcome/View/GradientBorderView.swift b/Mastodon/Scene/Onboarding/Welcome/View/GradientBorderView.swift new file mode 100644 index 00000000..c9a4a0d7 --- /dev/null +++ b/Mastodon/Scene/Onboarding/Welcome/View/GradientBorderView.swift @@ -0,0 +1,59 @@ +// +// GradientBorderView.swift +// Mastodon +// +// Created by MainasuK on 2021-12-31. +// + +import UIKit + +final class GradientBorderView: UIView { + + let gradientLayer = CAGradientLayer() + let maskLayer = CAShapeLayer() + + override init(frame: CGRect) { + super.init(frame: frame) + _init() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + _init() + } + +} + +extension GradientBorderView { + private func _init() { + isUserInteractionEnabled = false + + gradientLayer.frame = bounds + + gradientLayer.colors = [ + UIColor.white.cgColor, + UIColor.white.withAlphaComponent(0.0).cgColor, + ] + + gradientLayer.startPoint = CGPoint(x: 0.5, y: 0) + gradientLayer.endPoint = CGPoint(x: 0.5, y: 1) + + layer.addSublayer(gradientLayer) + + // set blend mode to "Soft Light" + layer.compositingFilter = "softLightBlendMode" + } + + override func layoutSubviews() { + super.layoutSubviews() + + let bezierPath = UIBezierPath(rect: bounds) + bezierPath.append(UIBezierPath(roundedRect: bounds.insetBy(dx: 3, dy: 3), cornerRadius: 10)) + + maskLayer.fillRule = .evenOdd + maskLayer.path = bezierPath.cgPath + + gradientLayer.frame = bounds + gradientLayer.mask = maskLayer + } +} diff --git a/Mastodon/Scene/Onboarding/Welcome/View/WelcomeIllustrationView.swift b/Mastodon/Scene/Onboarding/Welcome/View/WelcomeIllustrationView.swift index f5d8c41c..cb7ac768 100644 --- a/Mastodon/Scene/Onboarding/Welcome/View/WelcomeIllustrationView.swift +++ b/Mastodon/Scene/Onboarding/Welcome/View/WelcomeIllustrationView.swift @@ -8,18 +8,18 @@ import UIKit final class WelcomeIllustrationView: UIView { - - static let artworkImageSize = CGSize(width: 375, height: 1500) - + let cloudBaseImageView = UIImageView() let rightHillImageView = UIImageView() let leftHillImageView = UIImageView() let centerHillImageView = UIImageView() private let cloudBaseImage = Asset.Scene.Welcome.Illustration.cloudBase.image + private let cloudBaseExtendImage = Asset.Scene.Welcome.Illustration.cloudBaseExtend.image private let elephantThreeOnGrassWithTreeTwoImage = Asset.Scene.Welcome.Illustration.elephantThreeOnGrassWithTreeTwo.image private let elephantThreeOnGrassWithTreeThreeImage = Asset.Scene.Welcome.Illustration.elephantThreeOnGrassWithTreeThree.image private let elephantThreeOnGrassImage = Asset.Scene.Welcome.Illustration.elephantThreeOnGrass.image + private let elephantThreeOnGrassExtendImage = Asset.Scene.Welcome.Illustration.elephantThreeOnGrassExtend.image // layout outside let elephantOnAirplaneWithContrailImageView: UIImageView = { @@ -27,6 +27,13 @@ final class WelcomeIllustrationView: UIView { imageView.contentMode = .scaleAspectFill return imageView }() + + var layout: Layout = .compact { + didSet { + setNeedsLayout() + } + } + var aspectLayoutConstraint: NSLayoutConstraint! override init(frame: CGRect) { super.init(frame: frame) @@ -40,6 +47,20 @@ final class WelcomeIllustrationView: UIView { } +extension WelcomeIllustrationView { + enum Layout { + case compact + case regular + + var artworkImageSize: CGSize { + switch self { + case .compact: return CGSize(width: 375, height: 1500) + case .regular: return CGSize(width: 547, height: 1500) + } + } + } +} + extension WelcomeIllustrationView { private func _init() { @@ -62,7 +83,6 @@ extension WelcomeIllustrationView { cloudBaseImageView.leadingAnchor.constraint(equalTo: leadingAnchor), cloudBaseImageView.trailingAnchor.constraint(equalTo: trailingAnchor), cloudBaseImageView.bottomAnchor.constraint(equalTo: bottomAnchor), - cloudBaseImageView.widthAnchor.constraint(equalTo: cloudBaseImageView.heightAnchor, multiplier: WelcomeIllustrationView.artworkImageSize.width / WelcomeIllustrationView.artworkImageSize.height), ]) [ @@ -79,15 +99,28 @@ extension WelcomeIllustrationView { imageView.bottomAnchor.constraint(equalTo: cloudBaseImageView.bottomAnchor), ]) } + + aspectLayoutConstraint = cloudBaseImageView.widthAnchor.constraint(equalTo: cloudBaseImageView.heightAnchor, multiplier: layout.artworkImageSize.width / layout.artworkImageSize.height) + aspectLayoutConstraint.isActive = true } override func layoutSubviews() { super.layoutSubviews() - updateImage() + + switch layout { + case .compact: + layoutCompact() + case .regular: + layoutRegular() + } + + aspectLayoutConstraint.isActive = false + aspectLayoutConstraint = cloudBaseImageView.widthAnchor.constraint(equalTo: cloudBaseImageView.heightAnchor, multiplier: layout.artworkImageSize.width / layout.artworkImageSize.height) + aspectLayoutConstraint.isActive = true } - private func updateImage() { - let size = WelcomeIllustrationView.artworkImageSize + private func layoutCompact() { + let size = layout.artworkImageSize let width = size.width let height = size.height @@ -130,6 +163,50 @@ extension WelcomeIllustrationView { } } + private func layoutRegular() { + let size = layout.artworkImageSize + let width = size.width + let height = size.height + + cloudBaseImageView.image = UIGraphicsImageRenderer(size: size).image { context in + // clear background + UIColor.clear.setFill() + context.fill(CGRect(origin: .zero, size: size)) + + // draw cloud + cloudBaseExtendImage.draw(at: CGPoint(x: 0, y: height - cloudBaseExtendImage.size.height)) + + rightHillImageView.image = UIGraphicsImageRenderer(size: size).image { context in + // clear background + UIColor.clear.setFill() + context.fill(CGRect(origin: .zero, size: size)) + + // draw elephantThreeOnGrassWithTreeTwoImage + // elephantThreeOnGrassWithTreeTwo.bottomY - 25 align to elephantThreeOnGrassImage.centerY + elephantThreeOnGrassWithTreeTwoImage.draw(at: CGPoint(x: width - elephantThreeOnGrassWithTreeTwoImage.size.width, y: height - 0.5 * elephantThreeOnGrassImage.size.height - elephantThreeOnGrassWithTreeTwoImage.size.height - 20)) + } + + leftHillImageView.image = UIGraphicsImageRenderer(size: size).image { context in + // clear background + UIColor.clear.setFill() + context.fill(CGRect(origin: .zero, size: size)) + + // draw elephantThreeOnGrassWithTreeThree + // elephantThreeOnGrassWithTreeThree.bottomY + 30 align to elephantThreeOnGrassImage.centerY + elephantThreeOnGrassWithTreeThreeImage.draw(at: CGPoint(x: -160, y: height - 0.5 * elephantThreeOnGrassImage.size.height - elephantThreeOnGrassWithTreeThreeImage.size.height - 80)) + } + + centerHillImageView.image = UIGraphicsImageRenderer(size: size).image { context in + // clear background + UIColor.clear.setFill() + context.fill(CGRect(origin: .zero, size: size)) + + // draw elephantThreeOnGrass + elephantThreeOnGrassExtendImage.draw(at: CGPoint(x: 0, y: height - elephantThreeOnGrassExtendImage.size.height)) + } + } + } + } #if canImport(SwiftUI) && DEBUG @@ -140,13 +217,17 @@ struct WelcomeIllustrationView_Previews: PreviewProvider { static var previews: some View { Group { UIViewPreview(width: 375) { - WelcomeIllustrationView() + let view = WelcomeIllustrationView() + view.layout = .compact + return view } .previewLayout(.fixed(width: 375, height: 1500)) - UIViewPreview(width: 1125) { - WelcomeIllustrationView() + UIViewPreview(width: 547) { + let view = WelcomeIllustrationView() + view.layout = .regular + return view } - .previewLayout(.fixed(width: 1125, height: 5000)) + .previewLayout(.fixed(width: 547, height: 1500)) } } diff --git a/Mastodon/Scene/Onboarding/Welcome/WelcomeViewController.swift b/Mastodon/Scene/Onboarding/Welcome/WelcomeViewController.swift index bf33ea13..d450764e 100644 --- a/Mastodon/Scene/Onboarding/Welcome/WelcomeViewController.swift +++ b/Mastodon/Scene/Onboarding/Welcome/WelcomeViewController.swift @@ -11,6 +11,8 @@ import Combine final class WelcomeViewController: UIViewController, NeedsDependency { + let logger = Logger(subsystem: "WelcomeViewController", category: "ViewController") + weak var context: AppContext! { willSet { precondition(!isViewLoaded) } } weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } } @@ -41,30 +43,36 @@ final class WelcomeViewController: UIViewController, NeedsDependency { return label }() + let buttonContainer = UIStackView() + private(set) lazy var signUpButton: PrimaryActionButton = { let button = PrimaryActionButton() button.adjustsBackgroundImageWhenUserInterfaceStyleChanges = false - button.setTitle(L10n.Common.Controls.Actions.signUp, for: .normal) + button.setTitle("Get Started", for: .normal) // TODO: i18n let backgroundImageColor: UIColor = .white let backgroundImageHighlightedColor: UIColor = UIColor(white: 0.8, alpha: 1.0) button.setBackgroundImage(.placeholder(color: backgroundImageColor), for: .normal) button.setBackgroundImage(.placeholder(color: backgroundImageHighlightedColor), for: .highlighted) - let titleColor: UIColor = Asset.Colors.brandBlue.color - button.setTitleColor(titleColor, for: .normal) - button.translatesAutoresizingMaskIntoConstraints = false + button.setTitleColor(.black, for: .normal) return button }() private(set) lazy var signInButton: UIButton = { - let button = UIButton(type: .system) + let button = PrimaryActionButton() + button.adjustsBackgroundImageWhenUserInterfaceStyleChanges = false button.titleLabel?.font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 15, weight: .semibold)) - button.setTitle(L10n.Common.Controls.Actions.signIn, for: .normal) + button.setTitle("Log In", for: .normal) + let backgroundImageColor = Asset.Scene.Welcome.signInButtonBackground.color + let backgroundImageHighlightedColor = Asset.Scene.Welcome.signInButtonBackground.color.withAlphaComponent(0.8) + button.setBackgroundImage(.placeholder(color: backgroundImageColor), for: .normal) + button.setBackgroundImage(.placeholder(color: backgroundImageHighlightedColor), for: .highlighted) let titleColor: UIColor = UIColor.white.withAlphaComponent(0.8) button.setTitleColor(titleColor, for: .normal) - button.translatesAutoresizingMaskIntoConstraints = false return button }() + private(set) lazy var gradientBorderView = GradientBorderView(frame: view.bounds) + deinit { os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function) } @@ -76,7 +84,8 @@ extension WelcomeViewController { override func viewDidLoad() { super.viewDidLoad() - // preferredContentSize = CGSize(width: 547, height: 678) + definesPresentationContext = true + preferredContentSize = CGSize(width: 547, height: 678) navigationController?.navigationBar.prefersLargeTitles = true navigationItem.largeTitleDisplayMode = .never @@ -84,19 +93,37 @@ extension WelcomeViewController { setupOnboardingAppearance() setupIllustrationLayout() - - view.addSubview(signInButton) - view.addSubview(signUpButton) + + buttonContainer.axis = .vertical + buttonContainer.spacing = 12 + buttonContainer.isLayoutMarginsRelativeArrangement = true + + buttonContainer.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(buttonContainer) NSLayoutConstraint.activate([ - signInButton.leadingAnchor.constraint(equalTo: view.readableContentGuide.leadingAnchor, constant: WelcomeViewController.actionButtonMargin), - view.readableContentGuide.trailingAnchor.constraint(equalTo: signInButton.trailingAnchor, constant: WelcomeViewController.actionButtonMargin), - view.layoutMarginsGuide.bottomAnchor.constraint(equalTo: signInButton.bottomAnchor, constant: WelcomeViewController.viewBottomPaddingHeight), - signInButton.heightAnchor.constraint(equalToConstant: WelcomeViewController.actionButtonHeight).priority(.defaultHigh), - - signInButton.topAnchor.constraint(equalTo: signUpButton.bottomAnchor, constant: 9), - signUpButton.leadingAnchor.constraint(equalTo: view.readableContentGuide.leadingAnchor, constant: WelcomeViewController.actionButtonMargin), - view.readableContentGuide.trailingAnchor.constraint(equalTo: signUpButton.trailingAnchor, constant: WelcomeViewController.actionButtonMargin), - signUpButton.heightAnchor.constraint(equalToConstant: WelcomeViewController.actionButtonHeight).priority(.defaultHigh), + buttonContainer.leadingAnchor.constraint(equalTo: view.readableContentGuide.leadingAnchor), + buttonContainer.trailingAnchor.constraint(equalTo: view.readableContentGuide.trailingAnchor), + view.layoutMarginsGuide.bottomAnchor.constraint(equalTo: buttonContainer.bottomAnchor), + ]) + + signUpButton.translatesAutoresizingMaskIntoConstraints = false + buttonContainer.addArrangedSubview(signUpButton) + NSLayoutConstraint.activate([ + signUpButton.heightAnchor.constraint(equalToConstant: WelcomeViewController.actionButtonHeight).priority(.required - 1), + ]) + signInButton.translatesAutoresizingMaskIntoConstraints = false + buttonContainer.addArrangedSubview(signInButton) + NSLayoutConstraint.activate([ + signInButton.heightAnchor.constraint(equalToConstant: WelcomeViewController.actionButtonHeight).priority(.required - 1), + ]) + + gradientBorderView.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(gradientBorderView) + NSLayoutConstraint.activate([ + gradientBorderView.topAnchor.constraint(equalTo: view.topAnchor), + gradientBorderView.leadingAnchor.constraint(equalTo: view.leadingAnchor), + gradientBorderView.trailingAnchor.constraint(equalTo: view.trailingAnchor), + gradientBorderView.bottomAnchor.constraint(equalTo: view.bottomAnchor), ]) signUpButton.addTarget(self, action: #selector(signUpButtonDidClicked(_:)), for: .touchUpInside) @@ -109,17 +136,6 @@ extension WelcomeViewController { self.navigationItem.leftBarButtonItem = needsShowDismissEntry ? self.dismissBarButtonItem : nil } .store(in: &disposeBag) - - view.observe(\.frame, options: [.initial, .new]) { [weak self] view, _ in - guard let self = self else { return } - switch view.traitCollection.userInterfaceIdiom { - case .phone: - break - default: - self.welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.isHidden = view.frame.height < 800 - } - } - .store(in: &observations) } override func viewSafeAreaInsetsDidChange() { @@ -130,18 +146,49 @@ extension WelcomeViewController { if view.safeAreaInsets.bottom == 0 { overlap += 56 } - // shift illustration down for iPad modal - if UIDevice.current.userInterfaceIdiom != .phone { - overlap += 20 - } welcomeIllustrationViewBottomAnchorLayoutConstraint?.constant = overlap } + + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + + setupIllustrationLayout() + } } extension WelcomeViewController { + private func updateButtonContainerLayoutMargins(traitCollection: UITraitCollection) { + switch traitCollection.userInterfaceIdiom { + case .phone: + buttonContainer.layoutMargins = UIEdgeInsets( + top: 0, + left: WelcomeViewController.actionButtonMargin, + bottom: WelcomeViewController.viewBottomPaddingHeight, + right: WelcomeViewController.actionButtonMargin + ) + default: + let margin = traitCollection.horizontalSizeClass == .regular ? WelcomeViewController.actionButtonMarginExtend : WelcomeViewController.actionButtonMargin + buttonContainer.layoutMargins = UIEdgeInsets( + top: 0, + left: margin, + bottom: WelcomeViewController.viewBottomPaddingHeightExtend, + right: margin + ) + } + } + private func setupIllustrationLayout() { + welcomeIllustrationView.layout = { + switch traitCollection.userInterfaceIdiom { + case .phone: + return .compact + default: + return .regular + } + }() + // set logo if logoImageView.superview == nil { view.addSubview(logoImageView) @@ -154,10 +201,11 @@ extension WelcomeViewController { logoImageView.setContentHuggingPriority(.defaultHigh, for: .vertical) } - // set illustration for phone + // set illustration guard welcomeIllustrationView.superview == nil else { return } + welcomeIllustrationView.contentMode = .scaleAspectFit welcomeIllustrationView.translatesAutoresizingMaskIntoConstraints = false welcomeIllustrationViewBottomAnchorLayoutConstraint = welcomeIllustrationView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 5) @@ -166,7 +214,7 @@ extension WelcomeViewController { NSLayoutConstraint.activate([ view.leftAnchor.constraint(equalTo: welcomeIllustrationView.leftAnchor, constant: 15), welcomeIllustrationView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 15), - welcomeIllustrationViewBottomAnchorLayoutConstraint! + welcomeIllustrationViewBottomAnchorLayoutConstraint!.priority(.required - 1), ]) welcomeIllustrationView.cloudBaseImageView.addMotionEffect( @@ -268,21 +316,34 @@ extension WelcomeViewController: OnboardingViewControllerAppearance { // MARK: - UIAdaptivePresentationControllerDelegate extension WelcomeViewController: UIAdaptivePresentationControllerDelegate { + func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle { + logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public)") + + updateButtonContainerLayoutMargins(traitCollection: traitCollection) + switch traitCollection.userInterfaceIdiom { case .phone: // make underneath view controller alive to fix layout issue due to view life cycle return .fullScreen default: - return .formSheet -// switch traitCollection.horizontalSizeClass { -// case .regular: -// default: -// return .fullScreen -// } + switch traitCollection.horizontalSizeClass { + case .compact: + return .fullScreen + case .regular: + return .formSheet + case .unspecified: + return .formSheet + @unknown default: + return .formSheet + } } } + func presentationController(_ controller: UIPresentationController, viewControllerForAdaptivePresentationStyle style: UIModalPresentationStyle) -> UIViewController? { + return nil + } + func presentationControllerShouldDismiss(_ presentationController: UIPresentationController) -> Bool { return false } diff --git a/Mastodon/Scene/Wizard/WizardViewController.swift b/Mastodon/Scene/Wizard/WizardViewController.swift index 2678c712..9152e64f 100644 --- a/Mastodon/Scene/Wizard/WizardViewController.swift +++ b/Mastodon/Scene/Wizard/WizardViewController.swift @@ -35,7 +35,7 @@ class WizardViewController: UIViewController { let backgroundView: UIView = { let view = UIView() - view.backgroundColor = UIColor.black.withAlphaComponent(0.7) + view.backgroundColor = UIColor.black.withAlphaComponent(0.5) return view }() From cff048c2a3271d8eaf9c5dcd0348c02ab8d0f82b Mon Sep 17 00:00:00 2001 From: CMK Date: Fri, 31 Dec 2021 17:31:13 +0800 Subject: [PATCH 03/12] feat: add shadow and fix modal transition issue --- Mastodon.xcodeproj/project.pbxproj | 4 ++ Mastodon/Coordinator/SceneCoordinator.swift | 22 +++----- .../OnboardingNavigationController.swift | 50 +++++++++++++++++ .../View/WelcomeIllustrationView.swift | 2 +- .../Welcome/WelcomeViewController.swift | 54 +++++++++++++------ ...veStatusBarStyleNavigationController.swift | 2 +- 6 files changed, 103 insertions(+), 31 deletions(-) create mode 100644 Mastodon/Scene/Onboarding/Share/OnboardingNavigationController.swift diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index bb7a8a4f..8f0bfafa 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -192,6 +192,7 @@ DB03F7F52689B782007B274C /* ComposeTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB03F7F42689B782007B274C /* ComposeTableView.swift */; }; DB040ED126538E3D00BEE9D8 /* Trie.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB040ED026538E3C00BEE9D8 /* Trie.swift */; }; DB0617EB277EF3820030EE79 /* GradientBorderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0617EA277EF3820030EE79 /* GradientBorderView.swift */; }; + DB0617ED277F02C50030EE79 /* OnboardingNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0617EC277F02C50030EE79 /* OnboardingNavigationController.swift */; }; DB084B5725CBC56C00F898ED /* Status.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB084B5625CBC56C00F898ED /* Status.swift */; }; DB0AC6FC25CD02E600D75117 /* APIService+Instance.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0AC6FB25CD02E600D75117 /* APIService+Instance.swift */; }; DB0C946526A6FD4D0088FB11 /* AlamofireImage in Frameworks */ = {isa = PBXBuildFile; productRef = DB0C946426A6FD4D0088FB11 /* AlamofireImage */; }; @@ -971,6 +972,7 @@ DB03F7F42689B782007B274C /* ComposeTableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeTableView.swift; sourceTree = ""; }; DB040ED026538E3C00BEE9D8 /* Trie.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Trie.swift; sourceTree = ""; }; DB0617EA277EF3820030EE79 /* GradientBorderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GradientBorderView.swift; sourceTree = ""; }; + DB0617EC277F02C50030EE79 /* OnboardingNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingNavigationController.swift; sourceTree = ""; }; DB084B5625CBC56C00F898ED /* Status.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Status.swift; sourceTree = ""; }; DB0AC6FB25CD02E600D75117 /* APIService+Instance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+Instance.swift"; sourceTree = ""; }; DB0C946A26A700AB0088FB11 /* MastodonUser+Property.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MastodonUser+Property.swift"; sourceTree = ""; }; @@ -2521,6 +2523,7 @@ 2D82B9FE25E7863200E36F0F /* OnboardingViewControllerAppearance.swift */, DB2F073325E8ECF000957B2D /* AuthenticationViewModel.swift */, DB029E94266A20430062874E /* MastodonAuthenticationController.swift */, + DB0617EC277F02C50030EE79 /* OnboardingNavigationController.swift */, ); path = Share; sourceTree = ""; @@ -3971,6 +3974,7 @@ DBF156DF2701B17600EC00B7 /* SidebarAddAccountCollectionViewCell.swift in Sources */, DB789A0B25F9F2950071ACA0 /* ComposeViewController.swift in Sources */, DB938F0926240F3C00E5B6C1 /* RemoteThreadViewModel.swift in Sources */, + DB0617ED277F02C50030EE79 /* OnboardingNavigationController.swift in Sources */, DBBC24AE26A53DC100398BB9 /* ReplicaStatusView.swift in Sources */, DB75BF1E263C1C1B00EDBF1F /* CustomScheduler.swift in Sources */, 0FAA102725E1126A0017CCDE /* MastodonPickServerViewController.swift in Sources */, diff --git a/Mastodon/Coordinator/SceneCoordinator.swift b/Mastodon/Coordinator/SceneCoordinator.swift index d3591ab4..49504fd1 100644 --- a/Mastodon/Coordinator/SceneCoordinator.swift +++ b/Mastodon/Coordinator/SceneCoordinator.swift @@ -304,20 +304,14 @@ extension SceneCoordinator { presentingViewController.showDetailViewController(navigationController, sender: sender) case .modal(let animated, let completion): -// let modalNavigationController: UINavigationController = { -// if scene.isOnboarding { -// return AdaptiveStatusBarStyleNavigationController(rootViewController: viewController) -// } else { -// return UINavigationController(rootViewController: viewController) -// } -// }() -// modalNavigationController.modalPresentationCapturesStatusBarAppearance = true -// if let adaptivePresentationControllerDelegate = viewController as? UIAdaptivePresentationControllerDelegate { -// modalNavigationController.presentationController?.delegate = adaptivePresentationControllerDelegate -// } -// presentingViewController.present(modalNavigationController, animated: animated, completion: completion) - - let modalNavigationController = UINavigationController(rootViewController: viewController) + let modalNavigationController: UINavigationController = { + if scene.isOnboarding { + return OnboardingNavigationController(rootViewController: viewController) + } else { + return UINavigationController(rootViewController: viewController) + } + }() + modalNavigationController.modalPresentationCapturesStatusBarAppearance = true if let adaptivePresentationControllerDelegate = viewController as? UIAdaptivePresentationControllerDelegate { modalNavigationController.presentationController?.delegate = adaptivePresentationControllerDelegate } diff --git a/Mastodon/Scene/Onboarding/Share/OnboardingNavigationController.swift b/Mastodon/Scene/Onboarding/Share/OnboardingNavigationController.swift new file mode 100644 index 00000000..07e58b58 --- /dev/null +++ b/Mastodon/Scene/Onboarding/Share/OnboardingNavigationController.swift @@ -0,0 +1,50 @@ +// +// OnboardingNavigationController.swift +// Mastodon +// +// Created by MainasuK on 2021-12-31. +// + +import UIKit + +final class OnboardingNavigationController: AdaptiveStatusBarStyleNavigationController { + + private(set) lazy var gradientBorderView = GradientBorderView(frame: view.bounds) + +} + +extension OnboardingNavigationController { + + override func viewDidLoad() { + super.viewDidLoad() + + gradientBorderView.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(gradientBorderView) + NSLayoutConstraint.activate([ + gradientBorderView.topAnchor.constraint(equalTo: view.topAnchor), + gradientBorderView.leadingAnchor.constraint(equalTo: view.leadingAnchor), + gradientBorderView.trailingAnchor.constraint(equalTo: view.trailingAnchor), + gradientBorderView.bottomAnchor.constraint(equalTo: view.bottomAnchor), + ]) + + updateBorderViewDisplay() + } + + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + + } + +} + +extension OnboardingNavigationController { + + private func updateBorderViewDisplay() { + switch traitCollection.userInterfaceIdiom { + case .phone: + gradientBorderView.isHidden = true + default: + gradientBorderView.isHidden = false + } + } +} diff --git a/Mastodon/Scene/Onboarding/Welcome/View/WelcomeIllustrationView.swift b/Mastodon/Scene/Onboarding/Welcome/View/WelcomeIllustrationView.swift index cb7ac768..23fa1505 100644 --- a/Mastodon/Scene/Onboarding/Welcome/View/WelcomeIllustrationView.swift +++ b/Mastodon/Scene/Onboarding/Welcome/View/WelcomeIllustrationView.swift @@ -55,7 +55,7 @@ extension WelcomeIllustrationView { var artworkImageSize: CGSize { switch self { case .compact: return CGSize(width: 375, height: 1500) - case .regular: return CGSize(width: 547, height: 1500) + case .regular: return CGSize(width: 547, height: 3000) } } } diff --git a/Mastodon/Scene/Onboarding/Welcome/WelcomeViewController.swift b/Mastodon/Scene/Onboarding/Welcome/WelcomeViewController.swift index d450764e..c86b059b 100644 --- a/Mastodon/Scene/Onboarding/Welcome/WelcomeViewController.swift +++ b/Mastodon/Scene/Onboarding/Welcome/WelcomeViewController.swift @@ -57,7 +57,7 @@ final class WelcomeViewController: UIViewController, NeedsDependency { return button }() - private(set) lazy var signInButton: UIButton = { + private(set) lazy var signInButton: PrimaryActionButton = { let button = PrimaryActionButton() button.adjustsBackgroundImageWhenUserInterfaceStyleChanges = false button.titleLabel?.font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 15, weight: .semibold)) @@ -66,12 +66,12 @@ final class WelcomeViewController: UIViewController, NeedsDependency { let backgroundImageHighlightedColor = Asset.Scene.Welcome.signInButtonBackground.color.withAlphaComponent(0.8) button.setBackgroundImage(.placeholder(color: backgroundImageColor), for: .normal) button.setBackgroundImage(.placeholder(color: backgroundImageHighlightedColor), for: .highlighted) - let titleColor: UIColor = UIColor.white.withAlphaComponent(0.8) + let titleColor: UIColor = UIColor.white.withAlphaComponent(0.9) button.setTitleColor(titleColor, for: .normal) return button }() + let signInButtonShadowView = UIView() - private(set) lazy var gradientBorderView = GradientBorderView(frame: view.bounds) deinit { os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function) @@ -117,13 +117,14 @@ extension WelcomeViewController { signInButton.heightAnchor.constraint(equalToConstant: WelcomeViewController.actionButtonHeight).priority(.required - 1), ]) - gradientBorderView.translatesAutoresizingMaskIntoConstraints = false - view.addSubview(gradientBorderView) + signInButtonShadowView.translatesAutoresizingMaskIntoConstraints = false + buttonContainer.addSubview(signInButtonShadowView) + buttonContainer.sendSubviewToBack(signInButtonShadowView) NSLayoutConstraint.activate([ - gradientBorderView.topAnchor.constraint(equalTo: view.topAnchor), - gradientBorderView.leadingAnchor.constraint(equalTo: view.leadingAnchor), - gradientBorderView.trailingAnchor.constraint(equalTo: view.trailingAnchor), - gradientBorderView.bottomAnchor.constraint(equalTo: view.bottomAnchor), + signInButtonShadowView.topAnchor.constraint(equalTo: signInButton.topAnchor), + signInButtonShadowView.leadingAnchor.constraint(equalTo: signInButton.leadingAnchor), + signInButtonShadowView.trailingAnchor.constraint(equalTo: signInButton.trailingAnchor), + signInButtonShadowView.bottomAnchor.constraint(equalTo: signInButton.bottomAnchor), ]) signUpButton.addTarget(self, action: #selector(signUpButtonDidClicked(_:)), for: .touchUpInside) @@ -138,6 +139,12 @@ extension WelcomeViewController { .store(in: &disposeBag) } + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + + setupButtonShadowView() + } + override func viewSafeAreaInsetsDidChange() { super.viewSafeAreaInsetsDidChange() @@ -153,12 +160,27 @@ extension WelcomeViewController { super.traitCollectionDidChange(previousTraitCollection) setupIllustrationLayout() + setupButtonShadowView() } } extension WelcomeViewController { + private func setupButtonShadowView() { + signInButtonShadowView.layer.setupShadow( + color: .black, + alpha: 0.25, + x: 0, + y: 1, + blur: 2, + spread: 0, + roundedRect: signInButtonShadowView.bounds, + byRoundingCorners: .allCorners, + cornerRadii: CGSize(width: 10, height: 10) + ) + } + private func updateButtonContainerLayoutMargins(traitCollection: UITraitCollection) { switch traitCollection.userInterfaceIdiom { case .phone: @@ -320,21 +342,23 @@ extension WelcomeViewController: UIAdaptivePresentationControllerDelegate { func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle { logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public)") + // update button layout updateButtonContainerLayoutMargins(traitCollection: traitCollection) - + + let navigationController = navigationController as? OnboardingNavigationController + switch traitCollection.userInterfaceIdiom { case .phone: + navigationController?.gradientBorderView.isHidden = true // make underneath view controller alive to fix layout issue due to view life cycle return .fullScreen default: switch traitCollection.horizontalSizeClass { case .compact: + navigationController?.gradientBorderView.isHidden = true return .fullScreen - case .regular: - return .formSheet - case .unspecified: - return .formSheet - @unknown default: + default: + navigationController?.gradientBorderView.isHidden = false return .formSheet } } diff --git a/Mastodon/Scene/Share/NavigationController/AdaptiveStatusBarStyleNavigationController.swift b/Mastodon/Scene/Share/NavigationController/AdaptiveStatusBarStyleNavigationController.swift index eb260853..aac23285 100644 --- a/Mastodon/Scene/Share/NavigationController/AdaptiveStatusBarStyleNavigationController.swift +++ b/Mastodon/Scene/Share/NavigationController/AdaptiveStatusBarStyleNavigationController.swift @@ -9,7 +9,7 @@ import UIKit // Make status bar style adaptive for child view controller // SeeAlso: `modalPresentationCapturesStatusBarAppearance` -final class AdaptiveStatusBarStyleNavigationController: UINavigationController { +class AdaptiveStatusBarStyleNavigationController: UINavigationController { override var childForStatusBarStyle: UIViewController? { visibleViewController } From 223049a3f538bff612df66cbfaa0418d9d0ef65b Mon Sep 17 00:00:00 2001 From: CMK Date: Tue, 4 Jan 2022 18:30:21 +0800 Subject: [PATCH 04/12] feat: update server pick scene UI --- Localization/app.json | 12 +- Mastodon.xcodeproj/project.pbxproj | 20 +- .../xcshareddata/swiftpm/Package.resolved | 9 + .../Deprecated/PickServerCategoriesCell.swift | 145 ++++++++ .../Deprecated/PickServerSearchCell.swift | 171 ++++++++++ .../Diffiable/Item/CategoryPickerItem.swift | 44 ++- Mastodon/Diffiable/Item/PickServerItem.swift | 10 - .../Onboarding/CategoryPickerSection.swift | 22 +- .../Onboarding/PickServerSection.swift | 123 +++---- Mastodon/Generated/Assets.swift | 9 + .../Label/primary.colorset/Contents.json | 12 +- .../primary.reverse.colorset/Contents.json | 38 +++ .../Label/secondary.colorset/Contents.json | 8 +- .../Scene/Onboarding/Contents.json | 9 + .../Contents.json | 38 +++ .../Contents.json | 38 +++ .../Contents.json | 38 +++ .../Contents.json | 38 +++ .../Contents.json | 38 +++ .../Contents.json | 38 +++ .../Contents.json | 6 +- .../Contents.json | 6 +- .../Contents.json | 6 +- ...PickServerCategoryCollectionViewCell.swift | 16 +- .../MastodonPickServerViewController.swift | 314 +++++++----------- ...MastodonPickServerViewModel+Diffable.swift | 83 ++++- .../MastodonPickServerViewModel.swift | 74 +---- .../PickServerCategoriesCell.swift | 145 -------- .../TableViewCell/PickServerCell.swift | 292 +++------------- .../PickServerLoaderTableViewCell.swift | 47 +-- .../TableViewCell/PickServerSearchCell.swift | 171 ---------- .../TableViewCell/PickServerTitleCell.swift | 47 +-- .../View/PickServerCategoryView.swift | 57 ++-- .../View/PickServerEmptyStateView.swift | 10 +- ...ckServerServerSectionTableHeaderView.swift | 204 ++++++++++++ .../Share/NavigationActionView.swift | 69 ++++ .../OnboardingNavigationController.swift | 3 +- .../OnboardingViewControllerAppearance.swift | 31 +- .../Welcome/View/GradientBorderView.swift | 6 +- .../View/Button/PrimaryActionButton.swift | 36 +- .../View/Container/TouchBlockingView.swift | 2 +- .../View/Content/TimelineHeaderView.swift | 8 +- 42 files changed, 1390 insertions(+), 1103 deletions(-) create mode 100644 Mastodon/Deprecated/PickServerCategoriesCell.swift create mode 100644 Mastodon/Deprecated/PickServerSearchCell.swift create mode 100644 Mastodon/Resources/Assets.xcassets/Colors/Label/primary.reverse.colorset/Contents.json create mode 100644 Mastodon/Resources/Assets.xcassets/Scene/Onboarding/Contents.json create mode 100644 Mastodon/Resources/Assets.xcassets/Scene/Onboarding/navigation.back.button.background.colorset/Contents.json create mode 100644 Mastodon/Resources/Assets.xcassets/Scene/Onboarding/navigation.back.button.background.highlighted.colorset/Contents.json create mode 100644 Mastodon/Resources/Assets.xcassets/Scene/Onboarding/navigation.next.button.background.colorset/Contents.json create mode 100644 Mastodon/Resources/Assets.xcassets/Scene/Onboarding/navigation.next.button.background.highlighted.colorset/Contents.json create mode 100644 Mastodon/Resources/Assets.xcassets/Scene/Onboarding/onboarding.background.colorset/Contents.json create mode 100644 Mastodon/Resources/Assets.xcassets/Scene/Onboarding/search.bar.background.colorset/Contents.json delete mode 100644 Mastodon/Scene/Onboarding/PickServer/TableViewCell/PickServerCategoriesCell.swift delete mode 100644 Mastodon/Scene/Onboarding/PickServer/TableViewCell/PickServerSearchCell.swift create mode 100644 Mastodon/Scene/Onboarding/PickServer/View/PickServerServerSectionTableHeaderView.swift create mode 100644 Mastodon/Scene/Onboarding/Share/NavigationActionView.swift diff --git a/Localization/app.json b/Localization/app.json index 3b39a713..5e74bc69 100644 --- a/Localization/app.json +++ b/Localization/app.json @@ -198,7 +198,9 @@ "log_in": "Log In" }, "server_picker": { - "title": "Pick a server,\nany server.", + "title": "Mastodon is made of users in different communities.", + "subtitle": "Pick a community based on your interests, region, or a general purpose one.", + "subtitle_extend": "Pick a community based on your interests, region, or a general purpose one. Each community is operated by an entirely independent organization or individual.", "button": { "category": { "all": "All", @@ -225,7 +227,7 @@ "category": "CATEGORY" }, "input": { - "placeholder": "Find a server or join your own..." + "placeholder": "Search communities" }, "empty_state": { "finding_servers": "Finding available servers...", @@ -234,7 +236,7 @@ } }, "register": { - "title": "Tell us about you.", + "title": "Let’s get you set up on %s", "input": { "avatar": { "delete": "Delete" @@ -288,7 +290,7 @@ }, "server_rules": { "title": "Some ground rules.", - "subtitle": "These rules are set by the admins of %s.", + "subtitle": "These are set and enforced by the %s moderators.", "prompt": "By continuing, you’re subject to the terms of service and privacy policy for %s.", "terms_of_service": "terms of service", "privacy_policy": "privacy policy", @@ -298,7 +300,7 @@ }, "confirm_email": { "title": "One last thing.", - "subtitle": "We just sent an email to %s,\ntap the link to confirm your account.", + "subtitle": "Tap the link we emailed to you to verify your account.", "button": { "open_email_app": "Open Email App", "dont_receive_email": "I never got an email" diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index 8f0bfafa..79bd6777 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -193,6 +193,8 @@ DB040ED126538E3D00BEE9D8 /* Trie.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB040ED026538E3C00BEE9D8 /* Trie.swift */; }; DB0617EB277EF3820030EE79 /* GradientBorderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0617EA277EF3820030EE79 /* GradientBorderView.swift */; }; DB0617ED277F02C50030EE79 /* OnboardingNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0617EC277F02C50030EE79 /* OnboardingNavigationController.swift */; }; + DB0617EF277F12720030EE79 /* NavigationActionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0617EE277F12720030EE79 /* NavigationActionView.swift */; }; + DB0617F1278413D00030EE79 /* PickServerServerSectionTableHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0617F0278413D00030EE79 /* PickServerServerSectionTableHeaderView.swift */; }; DB084B5725CBC56C00F898ED /* Status.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB084B5625CBC56C00F898ED /* Status.swift */; }; DB0AC6FC25CD02E600D75117 /* APIService+Instance.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0AC6FB25CD02E600D75117 /* APIService+Instance.swift */; }; DB0C946526A6FD4D0088FB11 /* AlamofireImage in Frameworks */ = {isa = PBXBuildFile; productRef = DB0C946426A6FD4D0088FB11 /* AlamofireImage */; }; @@ -973,6 +975,8 @@ DB040ED026538E3C00BEE9D8 /* Trie.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Trie.swift; sourceTree = ""; }; DB0617EA277EF3820030EE79 /* GradientBorderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GradientBorderView.swift; sourceTree = ""; }; DB0617EC277F02C50030EE79 /* OnboardingNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingNavigationController.swift; sourceTree = ""; }; + DB0617EE277F12720030EE79 /* NavigationActionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationActionView.swift; sourceTree = ""; }; + DB0617F0278413D00030EE79 /* PickServerServerSectionTableHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PickServerServerSectionTableHeaderView.swift; sourceTree = ""; }; DB084B5625CBC56C00F898ED /* Status.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Status.swift; sourceTree = ""; }; DB0AC6FB25CD02E600D75117 /* APIService+Instance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+Instance.swift"; sourceTree = ""; }; DB0C946A26A700AB0088FB11 /* MastodonUser+Property.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MastodonUser+Property.swift"; sourceTree = ""; }; @@ -1595,8 +1599,6 @@ isa = PBXGroup; children = ( 0FB3D2FD25E4CB6400AAD544 /* PickServerTitleCell.swift */, - 0FB3D30725E524C600AAD544 /* PickServerCategoriesCell.swift */, - 0FB3D33125E5F50E00AAD544 /* PickServerSearchCell.swift */, 0FB3D33725E6401400AAD544 /* PickServerCell.swift */, DB0F814F264D1E2500F2A12B /* PickServerLoaderTableViewCell.swift */, ); @@ -1608,6 +1610,7 @@ children = ( 0FB3D30E25E525CD00AAD544 /* PickServerCategoryView.swift */, DB9282B125F3222800823B15 /* PickServerEmptyStateView.swift */, + DB0617F0278413D00030EE79 /* PickServerServerSectionTableHeaderView.swift */, ); path = View; sourceTree = ""; @@ -2097,6 +2100,15 @@ path = TableViewCell; sourceTree = ""; }; + DB0617F3278436360030EE79 /* Deprecated */ = { + isa = PBXGroup; + children = ( + 0FB3D33125E5F50E00AAD544 /* PickServerSearchCell.swift */, + 0FB3D30725E524C600AAD544 /* PickServerCategoriesCell.swift */, + ); + path = Deprecated; + sourceTree = ""; + }; DB084B5125CBC56300F898ED /* CoreDataStack */ = { isa = PBXGroup; children = ( @@ -2228,6 +2240,7 @@ children = ( DB427DE325BAA00100D1B89D /* Info.plist */, DB89BA1025C10FF5008580ED /* Mastodon.entitlements */, + DB0617F3278436360030EE79 /* Deprecated */, 2D76319C25C151DE00929FB9 /* Diffiable */, DB8AF52A25C13561002E6C99 /* State */, 2D61335525C1886800CAE157 /* Service */, @@ -2524,6 +2537,7 @@ DB2F073325E8ECF000957B2D /* AuthenticationViewModel.swift */, DB029E94266A20430062874E /* MastodonAuthenticationController.swift */, DB0617EC277F02C50030EE79 /* OnboardingNavigationController.swift */, + DB0617EE277F12720030EE79 /* NavigationActionView.swift */, ); path = Share; sourceTree = ""; @@ -3972,6 +3986,7 @@ DBB5250E2611EBAF002F1F29 /* ProfileSegmentedViewController.swift in Sources */, 2D42FF8F25C8228A004A627A /* UIButton.swift in Sources */, DBF156DF2701B17600EC00B7 /* SidebarAddAccountCollectionViewCell.swift in Sources */, + DB0617F1278413D00030EE79 /* PickServerServerSectionTableHeaderView.swift in Sources */, DB789A0B25F9F2950071ACA0 /* ComposeViewController.swift in Sources */, DB938F0926240F3C00E5B6C1 /* RemoteThreadViewModel.swift in Sources */, DB0617ED277F02C50030EE79 /* OnboardingNavigationController.swift in Sources */, @@ -4132,6 +4147,7 @@ DBB525562611EDCA002F1F29 /* UserTimelineViewModel.swift in Sources */, 2D42FF7E25C82218004A627A /* ActionToolBarContainer.swift in Sources */, DB221B16260C395900AEFE46 /* CustomEmojiPickerInputViewModel.swift in Sources */, + DB0617EF277F12720030EE79 /* NavigationActionView.swift in Sources */, DB1FD43625F26899004CFCFC /* MastodonPickServerViewModel+LoadIndexedServerState.swift in Sources */, 2D939AE825EE1CF80076FA61 /* MastodonRegisterViewController+Avatar.swift in Sources */, 2D084B8D26258EA3003AA3AF /* NotificationViewModel+Diffable.swift in Sources */, diff --git a/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved index 11dde726..d933b5cd 100644 --- a/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -216,6 +216,15 @@ "revision": "dad97167bf1be16aeecd109130900995dd01c515", "version": "2.6.0" } + }, + { + "package": "UITextView+Placeholder", + "repositoryURL": "https://github.com/MainasuK/UITextView-Placeholder", + "state": { + "branch": null, + "revision": "20f513ded04a040cdf5467f0891849b1763ede3b", + "version": "1.4.1" + } } ] }, diff --git a/Mastodon/Deprecated/PickServerCategoriesCell.swift b/Mastodon/Deprecated/PickServerCategoriesCell.swift new file mode 100644 index 00000000..b2ca1cc7 --- /dev/null +++ b/Mastodon/Deprecated/PickServerCategoriesCell.swift @@ -0,0 +1,145 @@ +// +// PickServerCategoriesCell.swift +// Mastodon +// +// Created by BradGao on 2021/2/23. +// + +//import os.log +//import UIKit +//import MastodonSDK +// +//protocol PickServerCategoriesCellDelegate: AnyObject { +// func pickServerCategoriesCell(_ cell: PickServerCategoriesCell, collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) +//} +// +//final class PickServerCategoriesCell: UITableViewCell { +// +// weak var delegate: PickServerCategoriesCellDelegate? +// +// var diffableDataSource: UICollectionViewDiffableDataSource? +// +// let metricView = UIView() +// +// let collectionView: UICollectionView = { +// let flowLayout = UICollectionViewFlowLayout() +// flowLayout.scrollDirection = .horizontal +// let view = ControlContainableCollectionView(frame: .zero, collectionViewLayout: flowLayout) +// view.register(PickServerCategoryCollectionViewCell.self, forCellWithReuseIdentifier: String(describing: PickServerCategoryCollectionViewCell.self)) +// view.backgroundColor = .clear +// view.showsHorizontalScrollIndicator = false +// view.showsVerticalScrollIndicator = false +// view.layer.masksToBounds = false +// view.translatesAutoresizingMaskIntoConstraints = false +// return view +// }() +// +// override func prepareForReuse() { +// super.prepareForReuse() +// +// delegate = nil +// } +// +// override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { +// super.init(style: style, reuseIdentifier: reuseIdentifier) +// _init() +// } +// +// required init?(coder: NSCoder) { +// super.init(coder: coder) +// _init() +// } +//} +// +//extension PickServerCategoriesCell { +// +// private func _init() { +// selectionStyle = .none +// backgroundColor = Asset.Theme.Mastodon.systemGroupedBackground.color +// configureMargin() +// +// metricView.translatesAutoresizingMaskIntoConstraints = false +// contentView.addSubview(metricView) +// NSLayoutConstraint.activate([ +// metricView.leadingAnchor.constraint(equalTo: contentView.layoutMarginsGuide.leadingAnchor), +// metricView.trailingAnchor.constraint(equalTo: contentView.layoutMarginsGuide.trailingAnchor), +// metricView.topAnchor.constraint(equalTo: contentView.topAnchor), +// metricView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), +// metricView.heightAnchor.constraint(equalToConstant: 80).priority(.defaultHigh), +// ]) +// +// contentView.addSubview(collectionView) +// NSLayoutConstraint.activate([ +// collectionView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor), +// collectionView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor), +// collectionView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 10), +// contentView.bottomAnchor.constraint(equalTo: collectionView.bottomAnchor, constant: 20), +// collectionView.heightAnchor.constraint(equalToConstant: 80).priority(.defaultHigh), +// ]) +// +// collectionView.delegate = self +// } +// +// override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { +// super.traitCollectionDidChange(previousTraitCollection) +// +// configureMargin() +// } +// +// override func layoutSubviews() { +// super.layoutSubviews() +// +// collectionView.collectionViewLayout.invalidateLayout() +// } +// +//} +// +//extension PickServerCategoriesCell { +// private func configureMargin() { +// switch traitCollection.horizontalSizeClass { +// case .regular: +// let margin = MastodonPickServerViewController.viewEdgeMargin +// contentView.layoutMargins = UIEdgeInsets(top: 0, left: margin, bottom: 0, right: margin) +// default: +// contentView.layoutMargins = .zero +// } +// } +//} +// +//// MARK: - UICollectionViewDelegateFlowLayout +//extension PickServerCategoriesCell: UICollectionViewDelegateFlowLayout { +// +// func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { +// os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: indexPath: %s", ((#file as NSString).lastPathComponent), #line, #function, indexPath.debugDescription) +// collectionView.selectItem(at: indexPath, animated: true, scrollPosition: .centeredHorizontally) +// delegate?.pickServerCategoriesCell(self, collectionView: collectionView, didSelectItemAt: indexPath) +// } +// +// func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { +// layoutIfNeeded() +// return UIEdgeInsets(top: 0, left: metricView.frame.minX - collectionView.frame.minX, bottom: 0, right: collectionView.frame.maxX - metricView.frame.maxX) +// } +// +// func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { +// return 16 +// } +// +// func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { +// return CGSize(width: 60, height: 80) +// } +// +//} +// +//extension PickServerCategoriesCell { +// +// override func accessibilityElementCount() -> Int { +// guard let diffableDataSource = diffableDataSource else { return 0 } +// return diffableDataSource.snapshot().itemIdentifiers.count +// } +// +// override func accessibilityElement(at index: Int) -> Any? { +// guard let item = collectionView.cellForItem(at: IndexPath(item: index, section: 0)) else { return nil } +// return item +// } +// +//} diff --git a/Mastodon/Deprecated/PickServerSearchCell.swift b/Mastodon/Deprecated/PickServerSearchCell.swift new file mode 100644 index 00000000..465e7ae2 --- /dev/null +++ b/Mastodon/Deprecated/PickServerSearchCell.swift @@ -0,0 +1,171 @@ +// +// PickServerSearchCell.swift +// Mastodon +// +// Created by BradGao on 2021/2/24. +// + +import UIKit + +//protocol PickServerSearchCellDelegate: AnyObject { +// func pickServerSearchCell(_ cell: PickServerSearchCell, searchTextDidChange searchText: String?) +//} +// +//class PickServerSearchCell: UITableViewCell { +// +// weak var delegate: PickServerSearchCellDelegate? +// +// private var bgView: UIView = { +// let view = UIView() +// view.backgroundColor = Asset.Theme.Mastodon.secondaryGroupedSystemBackground.color +// view.translatesAutoresizingMaskIntoConstraints = false +// view.layer.maskedCorners = [ +// .layerMinXMinYCorner, +// .layerMaxXMinYCorner +// ] +// view.layer.cornerCurve = .continuous +// view.layer.cornerRadius = MastodonPickServerAppearance.tableViewCornerRadius +// return view +// }() +// +// private var textFieldBgView: UIView = { +// let view = UIView() +// view.backgroundColor = Asset.Colors.TextField.background.color +// view.translatesAutoresizingMaskIntoConstraints = false +// view.layer.masksToBounds = true +// view.layer.cornerRadius = 6 +// view.layer.cornerCurve = .continuous +// return view +// }() +// +// let searchTextField: UITextField = { +// let textField = UITextField() +// textField.translatesAutoresizingMaskIntoConstraints = false +// textField.leftView = { +// let imageView = UIImageView( +// image: UIImage( +// systemName: "magnifyingglass", +// withConfiguration: UIImage.SymbolConfiguration(pointSize: 15, weight: .regular) +// ) +// ) +// imageView.tintColor = Asset.Colors.Label.secondary.color.withAlphaComponent(0.6) +// +// let containerView = UIView() +// imageView.translatesAutoresizingMaskIntoConstraints = false +// containerView.addSubview(imageView) +// NSLayoutConstraint.activate([ +// imageView.topAnchor.constraint(equalTo: containerView.topAnchor), +// imageView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor), +// imageView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor), +// ]) +// +// let paddingView = UIView() +// paddingView.translatesAutoresizingMaskIntoConstraints = false +// containerView.addSubview(paddingView) +// NSLayoutConstraint.activate([ +// paddingView.topAnchor.constraint(equalTo: containerView.topAnchor), +// paddingView.leadingAnchor.constraint(equalTo: imageView.trailingAnchor), +// paddingView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor), +// paddingView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor), +// paddingView.widthAnchor.constraint(equalToConstant: 4).priority(.defaultHigh), +// ]) +// return containerView +// }() +// textField.leftViewMode = .always +// textField.font = .systemFont(ofSize: 15, weight: .regular) +// textField.tintColor = Asset.Colors.Label.primary.color +// textField.textColor = Asset.Colors.Label.primary.color +// textField.adjustsFontForContentSizeCategory = true +// textField.attributedPlaceholder = +// NSAttributedString(string: L10n.Scene.ServerPicker.Input.placeholder, +// attributes: [.font: UIFont.systemFont(ofSize: 15, weight: .regular), +// .foregroundColor: Asset.Colors.Label.secondary.color.withAlphaComponent(0.6)]) +// textField.clearButtonMode = .whileEditing +// textField.autocapitalizationType = .none +// textField.autocorrectionType = .no +// textField.returnKeyType = .done +// textField.keyboardType = .URL +// return textField +// }() +// +// override func prepareForReuse() { +// super.prepareForReuse() +// +// delegate = nil +// } +// +// override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { +// super.init(style: style, reuseIdentifier: reuseIdentifier) +// _init() +// } +// +// required init?(coder: NSCoder) { +// super.init(coder: coder) +// _init() +// } +//} +// +//extension PickServerSearchCell { +// private func _init() { +// selectionStyle = .none +// backgroundColor = Asset.Theme.Mastodon.systemGroupedBackground.color +// configureMargin() +// +// searchTextField.addTarget(self, action: #selector(textFieldDidChange(_:)), for: .editingChanged) +// searchTextField.delegate = self +// +// contentView.addSubview(bgView) +// contentView.addSubview(textFieldBgView) +// contentView.addSubview(searchTextField) +// +// NSLayoutConstraint.activate([ +// bgView.leadingAnchor.constraint(equalTo: contentView.layoutMarginsGuide.leadingAnchor), +// bgView.topAnchor.constraint(equalTo: contentView.topAnchor), +// bgView.trailingAnchor.constraint(equalTo: contentView.layoutMarginsGuide.trailingAnchor), +// bgView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), +// +// textFieldBgView.leadingAnchor.constraint(equalTo: bgView.leadingAnchor, constant: 14), +// textFieldBgView.topAnchor.constraint(equalTo: bgView.topAnchor, constant: 12), +// bgView.trailingAnchor.constraint(equalTo: textFieldBgView.trailingAnchor, constant: 14), +// bgView.bottomAnchor.constraint(equalTo: textFieldBgView.bottomAnchor, constant: 13), +// +// searchTextField.leadingAnchor.constraint(equalTo: textFieldBgView.leadingAnchor, constant: 11), +// searchTextField.topAnchor.constraint(equalTo: textFieldBgView.topAnchor, constant: 4), +// textFieldBgView.trailingAnchor.constraint(equalTo: searchTextField.trailingAnchor, constant: 11), +// textFieldBgView.bottomAnchor.constraint(equalTo: searchTextField.bottomAnchor, constant: 4), +// ]) +// } +// +// override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { +// super.traitCollectionDidChange(previousTraitCollection) +// +// configureMargin() +// } +//} +// +//extension PickServerSearchCell { +// private func configureMargin() { +// switch traitCollection.horizontalSizeClass { +// case .regular: +// let margin = MastodonPickServerViewController.viewEdgeMargin +// contentView.layoutMargins = UIEdgeInsets(top: 0, left: margin, bottom: 0, right: margin) +// default: +// contentView.layoutMargins = .zero +// } +// } +//} +// +//extension PickServerSearchCell { +// @objc private func textFieldDidChange(_ textField: UITextField) { +// delegate?.pickServerSearchCell(self, searchTextDidChange: textField.text) +// } +//} +// +//// MARK: - UITextFieldDelegate +//extension PickServerSearchCell: UITextFieldDelegate { +// +// func textFieldShouldReturn(_ textField: UITextField) -> Bool { +// textField.resignFirstResponder() +// return false +// } +//} diff --git a/Mastodon/Diffiable/Item/CategoryPickerItem.swift b/Mastodon/Diffiable/Item/CategoryPickerItem.swift index 0f2cdcc2..53f9c9ab 100644 --- a/Mastodon/Diffiable/Item/CategoryPickerItem.swift +++ b/Mastodon/Diffiable/Item/CategoryPickerItem.swift @@ -15,10 +15,11 @@ enum CategoryPickerItem { } extension CategoryPickerItem { - var title: String { + + var emoji: String { switch self { case .all: - return L10n.Scene.ServerPicker.Button.Category.all + return "💬" case .category(let category): switch category.category { case .academia: @@ -32,7 +33,7 @@ extension CategoryPickerItem { case .games: return "🕹" case .general: - return "💬" + return "🐘" case .journalism: return "📰" case .lgbt: @@ -50,6 +51,41 @@ extension CategoryPickerItem { } } } + var title: String { + switch self { + case .all: + return L10n.Scene.ServerPicker.Button.Category.all + case .category(let category): + switch category.category { + case .academia: + return L10n.Scene.ServerPicker.Button.Category.academia + case .activism: + return L10n.Scene.ServerPicker.Button.Category.activism + case .food: + return L10n.Scene.ServerPicker.Button.Category.food + case .furry: + return L10n.Scene.ServerPicker.Button.Category.furry + case .games: + return L10n.Scene.ServerPicker.Button.Category.games + case .general: + return L10n.Scene.ServerPicker.Button.Category.general + case .journalism: + return L10n.Scene.ServerPicker.Button.Category.journalism + case .lgbt: + return L10n.Scene.ServerPicker.Button.Category.lgbt + case .regional: + return L10n.Scene.ServerPicker.Button.Category.regional + case .art: + return L10n.Scene.ServerPicker.Button.Category.art + case .music: + return L10n.Scene.ServerPicker.Button.Category.music + case .tech: + return L10n.Scene.ServerPicker.Button.Category.tech + case ._other: + return "-" // FIXME: + } + } + } var accessibilityDescription: String { switch self { @@ -82,7 +118,7 @@ extension CategoryPickerItem { case .tech: return L10n.Scene.ServerPicker.Button.Category.tech case ._other: - return "❓" // FIXME: + return "-" // FIXME: } } } diff --git a/Mastodon/Diffiable/Item/PickServerItem.swift b/Mastodon/Diffiable/Item/PickServerItem.swift index 7db2c958..ba693ad7 100644 --- a/Mastodon/Diffiable/Item/PickServerItem.swift +++ b/Mastodon/Diffiable/Item/PickServerItem.swift @@ -12,8 +12,6 @@ import MastodonSDK /// Note: update Equatable when change case enum PickServerItem { case header - case categoryPicker(items: [CategoryPickerItem]) - case search case server(server: Mastodon.Entity.Server, attribute: ServerItemAttribute) case loader(attribute: LoaderItemAttribute) } @@ -63,10 +61,6 @@ extension PickServerItem: Equatable { switch (lhs, rhs) { case (.header, .header): return true - case (.categoryPicker(let itemsLeft), .categoryPicker(let itemsRight)): - return itemsLeft == itemsRight - case (.search, .search): - return true case (.server(let serverLeft, _), .server(let serverRight, _)): return serverLeft.domain == serverRight.domain case (.loader(let attributeLeft), loader(let attributeRight)): @@ -82,10 +76,6 @@ extension PickServerItem: Hashable { switch self { case .header: hasher.combine(String(describing: PickServerItem.header.self)) - case .categoryPicker(let items): - hasher.combine(items) - case .search: - hasher.combine(String(describing: PickServerItem.search.self)) case .server(let server, _): hasher.combine(server.domain) case .loader(let attribute): diff --git a/Mastodon/Diffiable/Section/Onboarding/CategoryPickerSection.swift b/Mastodon/Diffiable/Section/Onboarding/CategoryPickerSection.swift index 732813c0..525d7720 100644 --- a/Mastodon/Diffiable/Section/Onboarding/CategoryPickerSection.swift +++ b/Mastodon/Diffiable/Section/Onboarding/CategoryPickerSection.swift @@ -19,27 +19,11 @@ extension CategoryPickerSection { UICollectionViewDiffableDataSource(collectionView: collectionView) { [weak dependency] collectionView, indexPath, item -> UICollectionViewCell? in guard let _ = dependency else { return nil } let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: PickServerCategoryCollectionViewCell.self), for: indexPath) as! PickServerCategoryCollectionViewCell - switch item { - case .all: - cell.categoryView.titleLabel.font = .systemFont(ofSize: 17) - case .category: - cell.categoryView.titleLabel.font = .systemFont(ofSize: 28) - } + cell.categoryView.emojiLabel.text = item.emoji cell.categoryView.titleLabel.text = item.title cell.observe(\.isSelected, options: [.initial, .new]) { cell, _ in - if cell.isSelected { - cell.categoryView.bgView.backgroundColor = Asset.Colors.brandBlue.color - cell.categoryView.bgView.applyShadow(color: Asset.Colors.brandBlue.color, alpha: 1, x: 0, y: 0, blur: 4.0) - if case .all = item { - cell.categoryView.titleLabel.textColor = .white - } - } else { - cell.categoryView.bgView.backgroundColor = Asset.Theme.Mastodon.secondaryGroupedSystemBackground.color - cell.categoryView.bgView.applyShadow(color: Asset.Colors.brandBlue.color, alpha: 0, x: 0, y: 0, blur: 0.0) - if case .all = item { - cell.categoryView.titleLabel.textColor = Asset.Colors.brandBlue.color - } - } + cell.categoryView.highlightedIndicatorView.alpha = cell.isSelected ? 1 : 0 + cell.categoryView.titleLabel.textColor = cell.isSelected ? Asset.Colors.Label.primary.color : Asset.Colors.Label.secondary.color } .store(in: &cell.observations) diff --git a/Mastodon/Diffiable/Section/Onboarding/PickServerSection.swift b/Mastodon/Diffiable/Section/Onboarding/PickServerSection.swift index 28b1ded3..b2079aab 100644 --- a/Mastodon/Diffiable/Section/Onboarding/PickServerSection.swift +++ b/Mastodon/Diffiable/Section/Onboarding/PickServerSection.swift @@ -12,8 +12,6 @@ import AlamofireImage enum PickServerSection: Equatable, Hashable { case header - case category - case search case servers } @@ -21,14 +19,10 @@ extension PickServerSection { static func tableViewDiffableDataSource( for tableView: UITableView, dependency: NeedsDependency, - pickServerCategoriesCellDelegate: PickServerCategoriesCellDelegate, - pickServerSearchCellDelegate: PickServerSearchCellDelegate, pickServerCellDelegate: PickServerCellDelegate ) -> UITableViewDiffableDataSource { UITableViewDiffableDataSource(tableView: tableView) { [ weak dependency, - weak pickServerCategoriesCellDelegate, - weak pickServerSearchCellDelegate, weak pickServerCellDelegate ] tableView, indexPath, item -> UITableViewCell? in guard let dependency = dependency else { return nil } @@ -36,22 +30,6 @@ extension PickServerSection { case .header: let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: PickServerTitleCell.self), for: indexPath) as! PickServerTitleCell return cell - case .categoryPicker(let items): - let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: PickServerCategoriesCell.self), for: indexPath) as! PickServerCategoriesCell - cell.delegate = pickServerCategoriesCellDelegate - cell.diffableDataSource = CategoryPickerSection.collectionViewDiffableDataSource( - for: cell.collectionView, - dependency: dependency - ) - var snapshot = NSDiffableDataSourceSnapshot() - snapshot.appendSections([.main]) - snapshot.appendItems(items, toSection: .main) - cell.diffableDataSource?.apply(snapshot, animatingDifferences: false, completion: nil) - return cell - case .search: - let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: PickServerSearchCell.self), for: indexPath) as! PickServerSearchCell - cell.delegate = pickServerSearchCellDelegate - return cell case .server(let server, let attribute): let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: PickServerCell.self), for: indexPath) as! PickServerCell PickServerSection.configure(cell: cell, server: server, attribute: attribute) @@ -70,19 +48,63 @@ extension PickServerSection { static func configure(cell: PickServerCell, server: Mastodon.Entity.Server, attribute: PickServerItem.ServerItemAttribute) { cell.domainLabel.text = server.domain - cell.descriptionLabel.text = { - guard let html = try? HTML(html: server.description, encoding: .utf8) else { - return server.description - } + cell.descriptionLabel.attributedText = { + let content: String = { + guard let html = try? HTML(html: server.description, encoding: .utf8) else { + return server.description + } + return html.text ?? server.description + }() - return html.text ?? server.description + let paragraphStyle = NSMutableParagraphStyle() + paragraphStyle.lineHeightMultiple = 1.16 + + return NSAttributedString( + string: content, + attributes: [ + .paragraphStyle: paragraphStyle + ] + ) }() - cell.langValueLabel.text = server.language.uppercased() - cell.usersValueLabel.text = parseUsersCount(server.totalUsers) - cell.categoryValueLabel.text = server.category.uppercased() - - cell.updateExpandMode(mode: attribute.isExpand ? .expand : .collapse) - + cell.usersValueLabel.attributedText = { + let attributedString = NSMutableAttributedString() + let attachment = NSTextAttachment(image: UIImage(systemName: "person.2.fill")!) + let attachmentAttributedString = NSAttributedString(attachment: attachment) + attributedString.append(attachmentAttributedString) + attributedString.append(NSAttributedString(string: " ")) + + let paragraphStyle = NSMutableParagraphStyle() + paragraphStyle.lineHeightMultiple = 1.12 + let valueAttributedString = NSAttributedString( + string: parseUsersCount(server.totalUsers), + attributes: [ + .paragraphStyle: paragraphStyle + ] + ) + attributedString.append(valueAttributedString) + + return attributedString + }() + cell.langValueLabel.attributedText = { + let attributedString = NSMutableAttributedString() + let attachment = NSTextAttachment(image: UIImage(systemName: "text.bubble.fill")!) + let attachmentAttributedString = NSAttributedString(attachment: attachment) + attributedString.append(attachmentAttributedString) + attributedString.append(NSAttributedString(string: " ")) + + let paragraphStyle = NSMutableParagraphStyle() + paragraphStyle.lineHeightMultiple = 1.12 + let valueAttributedString = NSAttributedString( + string: server.language.uppercased(), + attributes: [ + .paragraphStyle: paragraphStyle + ] + ) + attributedString.append(valueAttributedString) + + return attributedString + }() + attribute.isLast .receive(on: DispatchQueue.main) .sink { [weak cell] isLast in @@ -101,41 +123,6 @@ extension PickServerSection { } } .store(in: &cell.disposeBag) - - cell.expandMode - .receive(on: DispatchQueue.main) - .sink { mode in - switch mode { - case .collapse: - // do nothing - break - case .expand: - let placeholderImage = UIImage.placeholder(size: cell.thumbnailImageView.frame.size, color: .systemFill) - .af.imageRounded(withCornerRadius: 3.0, divideRadiusByImageScale: false) - guard let proxiedThumbnail = server.proxiedThumbnail, - let url = URL(string: proxiedThumbnail) else { - cell.thumbnailImageView.image = placeholderImage - cell.thumbnailActivityIndicator.stopAnimating() - return - } - cell.thumbnailImageView.isHidden = false - cell.thumbnailActivityIndicator.startAnimating() - - cell.thumbnailImageView.af.setImage( - withURL: url, - placeholderImage: placeholderImage, - filter: AspectScaledToFillSizeWithRoundedCornersFilter(size: cell.thumbnailImageView.frame.size, radius: 3), - imageTransition: .crossDissolve(0.33), - completion: { [weak cell] response in - switch response.result { - case .success, .failure: - cell?.thumbnailActivityIndicator.stopAnimating() - } - } - ) - } - } - .store(in: &cell.disposeBag) } private static func parseUsersCount(_ usersCount: Int) -> String { diff --git a/Mastodon/Generated/Assets.swift b/Mastodon/Generated/Assets.swift index 5098d05f..0761780c 100644 --- a/Mastodon/Generated/Assets.swift +++ b/Mastodon/Generated/Assets.swift @@ -47,6 +47,7 @@ internal enum Asset { } internal enum Label { internal static let primary = ColorAsset(name: "Colors/Label/primary") + internal static let primaryReverse = ColorAsset(name: "Colors/Label/primary.reverse") internal static let secondary = ColorAsset(name: "Colors/Label/secondary") internal static let tertiary = ColorAsset(name: "Colors/Label/tertiary") } @@ -89,6 +90,14 @@ internal enum Asset { internal static let faceSmilingAdaptive = ImageAsset(name: "Human/face.smiling.adaptive") } internal enum Scene { + internal enum Onboarding { + internal static let navigationBackButtonBackground = ColorAsset(name: "Scene/Onboarding/navigation.back.button.background") + internal static let navigationBackButtonBackgroundHighlighted = ColorAsset(name: "Scene/Onboarding/navigation.back.button.background.highlighted") + internal static let navigationNextButtonBackground = ColorAsset(name: "Scene/Onboarding/navigation.next.button.background") + internal static let navigationNextButtonBackgroundHighlighted = ColorAsset(name: "Scene/Onboarding/navigation.next.button.background.highlighted") + internal static let onboardingBackground = ColorAsset(name: "Scene/Onboarding/onboarding.background") + internal static let searchBarBackground = ColorAsset(name: "Scene/Onboarding/search.bar.background") + } internal enum Profile { internal enum Banner { internal static let bioEditBackgroundGray = ColorAsset(name: "Scene/Profile/Banner/bio.edit.background.gray") diff --git a/Mastodon/Resources/Assets.xcassets/Colors/Label/primary.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Colors/Label/primary.colorset/Contents.json index 202a1c04..ee70bcc1 100644 --- a/Mastodon/Resources/Assets.xcassets/Colors/Label/primary.colorset/Contents.json +++ b/Mastodon/Resources/Assets.xcassets/Colors/Label/primary.colorset/Contents.json @@ -5,9 +5,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "0x00", - "green" : "0x00", - "red" : "0x00" + "blue" : "0.216", + "green" : "0.173", + "red" : "0.157" } }, "idiom" : "universal" @@ -23,9 +23,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "1.000", - "green" : "1.000", - "red" : "1.000" + "blue" : "0xEE", + "green" : "0xEE", + "red" : "0xEE" } }, "idiom" : "universal" diff --git a/Mastodon/Resources/Assets.xcassets/Colors/Label/primary.reverse.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Colors/Label/primary.reverse.colorset/Contents.json new file mode 100644 index 00000000..8f42a585 --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Colors/Label/primary.reverse.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.933", + "green" : "0.933", + "red" : "0.933" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.216", + "green" : "0.173", + "red" : "0.157" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Colors/Label/secondary.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Colors/Label/secondary.colorset/Contents.json index 70b1446d..104dfd02 100644 --- a/Mastodon/Resources/Assets.xcassets/Colors/Label/secondary.colorset/Contents.json +++ b/Mastodon/Resources/Assets.xcassets/Colors/Label/secondary.colorset/Contents.json @@ -22,10 +22,10 @@ "color" : { "color-space" : "srgb", "components" : { - "alpha" : "0.600", - "blue" : "0xF5", - "green" : "0xEB", - "red" : "0xEB" + "alpha" : "1.000", + "blue" : "0xAD", + "green" : "0x9D", + "red" : "0x97" } }, "idiom" : "universal" diff --git a/Mastodon/Resources/Assets.xcassets/Scene/Onboarding/Contents.json b/Mastodon/Resources/Assets.xcassets/Scene/Onboarding/Contents.json new file mode 100644 index 00000000..6e965652 --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Scene/Onboarding/Contents.json @@ -0,0 +1,9 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "provides-namespace" : true + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Scene/Onboarding/navigation.back.button.background.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Scene/Onboarding/navigation.back.button.background.colorset/Contents.json new file mode 100644 index 00000000..b7d63ece --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Scene/Onboarding/navigation.back.button.background.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xFF", + "green" : "0xFF", + "red" : "0xFF" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "0.200", + "blue" : "0x80", + "green" : "0x78", + "red" : "0x78" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Scene/Onboarding/navigation.back.button.background.highlighted.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Scene/Onboarding/navigation.back.button.background.highlighted.colorset/Contents.json new file mode 100644 index 00000000..7136040b --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Scene/Onboarding/navigation.back.button.background.highlighted.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xE5", + "green" : "0xE5", + "red" : "0xE5" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "0.400", + "blue" : "0x80", + "green" : "0x78", + "red" : "0x78" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Scene/Onboarding/navigation.next.button.background.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Scene/Onboarding/navigation.next.button.background.colorset/Contents.json new file mode 100644 index 00000000..17ed9364 --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Scene/Onboarding/navigation.next.button.background.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x37", + "green" : "0x2C", + "red" : "0x28" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xEE", + "green" : "0xEE", + "red" : "0xEE" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Scene/Onboarding/navigation.next.button.background.highlighted.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Scene/Onboarding/navigation.next.button.background.highlighted.colorset/Contents.json new file mode 100644 index 00000000..706cd755 --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Scene/Onboarding/navigation.next.button.background.highlighted.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x1B", + "green" : "0x15", + "red" : "0x13" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xBA", + "green" : "0xBA", + "red" : "0xBA" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Scene/Onboarding/onboarding.background.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Scene/Onboarding/onboarding.background.colorset/Contents.json new file mode 100644 index 00000000..0b219c90 --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Scene/Onboarding/onboarding.background.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xF7", + "green" : "0xF2", + "red" : "0xF2" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x21", + "green" : "0x1B", + "red" : "0x19" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Scene/Onboarding/search.bar.background.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Scene/Onboarding/search.bar.background.colorset/Contents.json new file mode 100644 index 00000000..f16bb02f --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Scene/Onboarding/search.bar.background.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "0.200", + "blue" : "0x80", + "green" : "0x78", + "red" : "0x78" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "0.240", + "blue" : "0x80", + "green" : "0x76", + "red" : "0x76" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Theme/system/Background/content.warning.overlay.background.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/system/Background/content.warning.overlay.background.colorset/Contents.json index d211d7df..c8aa45b5 100644 --- a/Mastodon/Resources/Assets.xcassets/Theme/system/Background/content.warning.overlay.background.colorset/Contents.json +++ b/Mastodon/Resources/Assets.xcassets/Theme/system/Background/content.warning.overlay.background.colorset/Contents.json @@ -5,9 +5,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "0.922", - "green" : "0.898", - "red" : "0.867" + "blue" : "0xEB", + "green" : "0xE4", + "red" : "0xDD" } }, "idiom" : "universal" diff --git a/Mastodon/Resources/Assets.xcassets/Theme/system/Background/secondary.system.background.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/system/Background/secondary.system.background.colorset/Contents.json index 77d24b11..14441ef0 100644 --- a/Mastodon/Resources/Assets.xcassets/Theme/system/Background/secondary.system.background.colorset/Contents.json +++ b/Mastodon/Resources/Assets.xcassets/Theme/system/Background/secondary.system.background.colorset/Contents.json @@ -5,9 +5,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "0.910", - "green" : "0.882", - "red" : "0.851" + "blue" : "0xE8", + "green" : "0xE0", + "red" : "0xD9" } }, "idiom" : "universal" diff --git a/Mastodon/Resources/Assets.xcassets/Theme/system/Background/system.grouped.background.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Theme/system/Background/system.grouped.background.colorset/Contents.json index 370a745e..daac70e0 100644 --- a/Mastodon/Resources/Assets.xcassets/Theme/system/Background/system.grouped.background.colorset/Contents.json +++ b/Mastodon/Resources/Assets.xcassets/Theme/system/Background/system.grouped.background.colorset/Contents.json @@ -5,9 +5,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "0.910", - "green" : "0.882", - "red" : "0.851" + "blue" : "0xE8", + "green" : "0xE0", + "red" : "0xD9" } }, "idiom" : "universal" diff --git a/Mastodon/Scene/Onboarding/PickServer/CollectionViewCell/PickServerCategoryCollectionViewCell.swift b/Mastodon/Scene/Onboarding/PickServer/CollectionViewCell/PickServerCategoryCollectionViewCell.swift index 9793d40f..89ca8267 100644 --- a/Mastodon/Scene/Onboarding/PickServer/CollectionViewCell/PickServerCategoryCollectionViewCell.swift +++ b/Mastodon/Scene/Onboarding/PickServer/CollectionViewCell/PickServerCategoryCollectionViewCell.swift @@ -8,14 +8,10 @@ import UIKit class PickServerCategoryCollectionViewCell: UICollectionViewCell { - + var observations = Set() - var categoryView: PickServerCategoryView = { - let view = PickServerCategoryView() - view.translatesAutoresizingMaskIntoConstraints = false - return view - }() + var categoryView = PickServerCategoryView() override func prepareForReuse() { super.prepareForReuse() @@ -35,13 +31,15 @@ class PickServerCategoryCollectionViewCell: UICollectionViewCell { extension PickServerCategoryCollectionViewCell { private func configure() { - contentView.addSubview(categoryView) + backgroundColor = .clear + categoryView.translatesAutoresizingMaskIntoConstraints = false + contentView.addSubview(categoryView) NSLayoutConstraint.activate([ + categoryView.topAnchor.constraint(equalTo: contentView.topAnchor), categoryView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor), categoryView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor), - categoryView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 10), - contentView.bottomAnchor.constraint(equalTo: categoryView.bottomAnchor, constant: 10), + contentView.bottomAnchor.constraint(equalTo: categoryView.bottomAnchor), ]) } } diff --git a/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewController.swift b/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewController.swift index f3570c6c..1fbf204f 100644 --- a/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewController.swift +++ b/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewController.swift @@ -14,6 +14,7 @@ import AuthenticationServices final class MastodonPickServerViewController: UIViewController, NeedsDependency { private var disposeBag = Set() + private var observations = Set() private var tableViewObservation: NSKeyValueObservation? weak var context: AppContext! { willSet { precondition(!isViewLoaded) } } @@ -31,21 +32,16 @@ final class MastodonPickServerViewController: UIViewController, NeedsDependency private let emptyStateView = PickServerEmptyStateView() private var emptyStateViewLeadingLayoutConstraint: NSLayoutConstraint! private var emptyStateViewTrailingLayoutConstraint: NSLayoutConstraint! - let tableViewTopPaddingView = UIView() // fix empty state view background display when tableView bounce scrolling - var tableViewTopPaddingViewHeightLayoutConstraint: NSLayoutConstraint! let tableView: UITableView = { let tableView = ControlContainableTableView() tableView.register(PickServerTitleCell.self, forCellReuseIdentifier: String(describing: PickServerTitleCell.self)) - tableView.register(PickServerCategoriesCell.self, forCellReuseIdentifier: String(describing: PickServerCategoriesCell.self)) - tableView.register(PickServerSearchCell.self, forCellReuseIdentifier: String(describing: PickServerSearchCell.self)) tableView.register(PickServerCell.self, forCellReuseIdentifier: String(describing: PickServerCell.self)) tableView.register(PickServerLoaderTableViewCell.self, forCellReuseIdentifier: String(describing: PickServerLoaderTableViewCell.self)) tableView.rowHeight = UITableView.automaticDimension tableView.separatorStyle = .none tableView.backgroundColor = .clear tableView.keyboardDismissMode = .onDrag - tableView.translatesAutoresizingMaskIntoConstraints = false if #available(iOS 15.0, *) { tableView.sectionHeaderTopPadding = .leastNonzeroMagnitude } else { @@ -54,14 +50,11 @@ final class MastodonPickServerViewController: UIViewController, NeedsDependency return tableView }() - let buttonContainer = UIView() - let nextStepButton: PrimaryActionButton = { - let button = PrimaryActionButton() - button.setTitle(L10n.Common.Controls.Actions.signUp, for: .normal) - button.translatesAutoresizingMaskIntoConstraints = false - return button + let navigationActionView: NavigationActionView = { + let navigationActionView = NavigationActionView() + navigationActionView.backgroundColor = Asset.Scene.Onboarding.onboardingBackground.color + return navigationActionView }() - var buttonContainerBottomLayoutConstraint: NSLayoutConstraint! var mastodonAuthenticationController: MastodonAuthenticationController? @@ -72,16 +65,15 @@ final class MastodonPickServerViewController: UIViewController, NeedsDependency } -extension MastodonPickServerViewController { - +extension MastodonPickServerViewController { override func viewDidLoad() { super.viewDidLoad() + navigationItem.leftBarButtonItem = UIBarButtonItem() + setupOnboardingAppearance() defer { setupNavigationBarBackgroundView() } - configureTitleLabel() - configureMargin() #if DEBUG navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(systemName: "ellipsis.circle"), style: .plain, target: nil, action: nil) @@ -94,26 +86,36 @@ extension MastodonPickServerViewController { navigationItem.rightBarButtonItem?.menu = UIMenu(title: "Debug Tool", image: nil, identifier: nil, options: [], children: children) #endif - buttonContainer.translatesAutoresizingMaskIntoConstraints = false - buttonContainer.preservesSuperviewLayoutMargins = true - view.addSubview(buttonContainer) - buttonContainerBottomLayoutConstraint = view.bottomAnchor.constraint(equalTo: buttonContainer.bottomAnchor, constant: 0).priority(.defaultHigh) + tableView.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(tableView) NSLayoutConstraint.activate([ - buttonContainer.leadingAnchor.constraint(equalTo: view.leadingAnchor), - buttonContainer.trailingAnchor.constraint(equalTo: view.trailingAnchor), - view.safeAreaLayoutGuide.bottomAnchor.constraint(greaterThanOrEqualTo: buttonContainer.bottomAnchor, constant: WelcomeViewController.viewBottomPaddingHeight), - buttonContainerBottomLayoutConstraint, + tableView.topAnchor.constraint(equalTo: view.topAnchor), + tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor), + tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor), + tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), ]) - view.addSubview(nextStepButton) + navigationActionView.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(navigationActionView) + defer { + view.bringSubviewToFront(navigationActionView) + } NSLayoutConstraint.activate([ - nextStepButton.topAnchor.constraint(equalTo: buttonContainer.topAnchor), - nextStepButton.leadingAnchor.constraint(equalTo: buttonContainer.layoutMarginsGuide.leadingAnchor), - buttonContainer.layoutMarginsGuide.trailingAnchor.constraint(equalTo: nextStepButton.trailingAnchor), - nextStepButton.bottomAnchor.constraint(equalTo: buttonContainer.bottomAnchor), - nextStepButton.heightAnchor.constraint(equalToConstant: MastodonPickServerViewController.actionButtonHeight).priority(.defaultHigh), + navigationActionView.leadingAnchor.constraint(equalTo: view.leadingAnchor), + navigationActionView.trailingAnchor.constraint(equalTo: view.trailingAnchor), + view.bottomAnchor.constraint(equalTo: navigationActionView.bottomAnchor), ]) - + + navigationActionView + .observe(\.bounds, options: [.initial, .new]) { [weak self] navigationActionView, _ in + guard let self = self else { return } + let inset = navigationActionView.frame.height + print("*** \(inset) ***") + self.tableView.contentInset.bottom = inset + } + .store(in: &observations) + + // fix AutoLayout warning when observe before view appear viewModel.viewWillAppear .receive(on: DispatchQueue.main) @@ -125,26 +127,7 @@ extension MastodonPickServerViewController { } } .store(in: &disposeBag) - - tableViewTopPaddingView.translatesAutoresizingMaskIntoConstraints = false - view.addSubview(tableViewTopPaddingView) - tableViewTopPaddingViewHeightLayoutConstraint = tableViewTopPaddingView.heightAnchor.constraint(equalToConstant: 0.0).priority(.defaultHigh) - NSLayoutConstraint.activate([ - tableViewTopPaddingView.topAnchor.constraint(equalTo: view.layoutMarginsGuide.topAnchor), - tableViewTopPaddingView.leadingAnchor.constraint(equalTo: view.leadingAnchor), - tableViewTopPaddingView.trailingAnchor.constraint(equalTo: view.trailingAnchor), - tableViewTopPaddingViewHeightLayoutConstraint, - ]) - tableViewTopPaddingView.backgroundColor = Asset.Theme.Mastodon.systemGroupedBackground.color - - view.addSubview(tableView) - NSLayoutConstraint.activate([ - tableView.topAnchor.constraint(equalTo: view.topAnchor), - tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor), - tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor), - buttonContainer.topAnchor.constraint(equalTo: tableView.bottomAnchor, constant: 7), - ]) - + emptyStateView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(emptyStateView) emptyStateViewLeadingLayoutConstraint = emptyStateView.leadingAnchor.constraint(equalTo: tableView.leadingAnchor) @@ -153,64 +136,24 @@ extension MastodonPickServerViewController { emptyStateView.topAnchor.constraint(equalTo: view.topAnchor), emptyStateViewLeadingLayoutConstraint, emptyStateViewTrailingLayoutConstraint, - buttonContainer.topAnchor.constraint(equalTo: emptyStateView.bottomAnchor, constant: 21), + navigationActionView.topAnchor.constraint(equalTo: emptyStateView.bottomAnchor, constant: 21), ]) view.sendSubviewToBack(emptyStateView) - - // update layout when keyboard show/dismiss - let keyboardEventPublishers = Publishers.CombineLatest3( - KeyboardResponderService.shared.isShow, - KeyboardResponderService.shared.state, - KeyboardResponderService.shared.endFrame - ) - - keyboardEventPublishers - .sink { [weak self] keyboardEvents in - guard let self = self else { return } - let (isShow, state, endFrame) = keyboardEvents - - // guard external keyboard connected - guard isShow, state == .dock, GCKeyboard.coalesced != nil else { - self.buttonContainerBottomLayoutConstraint.constant = WelcomeViewController.viewBottomPaddingHeight - return - } - - let externalKeyboardToolbarHeight = self.view.frame.maxY - endFrame.minY - guard externalKeyboardToolbarHeight > 0 else { - self.buttonContainerBottomLayoutConstraint.constant = WelcomeViewController.viewBottomPaddingHeight - return - } - - UIView.animate(withDuration: 0.3) { - self.buttonContainerBottomLayoutConstraint.constant = externalKeyboardToolbarHeight + 16 - self.view.layoutIfNeeded() - } - } - .store(in: &disposeBag) - - switch viewModel.mode { - case .signIn: - nextStepButton.setTitle(L10n.Common.Controls.Actions.signIn, for: .normal) - case .signUp: - nextStepButton.setTitle(L10n.Common.Controls.Actions.continue, for: .normal) - } - nextStepButton.addTarget(self, action: #selector(nextStepButtonDidClicked(_:)), for: .touchUpInside) - + tableView.delegate = self viewModel.setupDiffableDataSource( for: tableView, dependency: self, - pickServerCategoriesCellDelegate: self, - pickServerSearchCellDelegate: self, + pickServerServerSectionTableHeaderViewDelegate: self, pickServerCellDelegate: self ) - + viewModel .selectedServer .map { $0 != nil } - .assign(to: \.isEnabled, on: nextStepButton) + .assign(to: \.isEnabled, on: navigationActionView.nextButton) .store(in: &disposeBag) - + Publishers.Merge( viewModel.error, authenticationViewModel.error @@ -229,7 +172,7 @@ extension MastodonPickServerViewController { ) } .store(in: &disposeBag) - + authenticationViewModel .authenticated .flatMap { [weak self] (domain, user) -> AnyPublisher, Never> in @@ -249,17 +192,17 @@ extension MastodonPickServerViewController { } } .store(in: &disposeBag) - + authenticationViewModel.isAuthenticating .receive(on: DispatchQueue.main) .sink { [weak self] isAuthenticating in guard let self = self else { return } - isAuthenticating ? self.nextStepButton.showLoading() : self.nextStepButton.stopLoading() + isAuthenticating ? self.navigationActionView.nextButton.showLoading() : self.navigationActionView.nextButton.stopLoading() } .store(in: &disposeBag) - + viewModel.emptyStateViewState - .receive(on: RunLoop.main) + .receive(on: DispatchQueue.main) .sink { [weak self] state in guard let self = self else { return } switch state { @@ -284,6 +227,9 @@ extension MastodonPickServerViewController { } } .store(in: &disposeBag) + + navigationActionView.backButton.addTarget(self, action: #selector(MastodonPickServerViewController.backButtonDidPressed(_:)), for: .touchUpInside) + navigationActionView.nextButton.addTarget(self, action: #selector(MastodonPickServerViewController.nextButtonDidPressed(_:)), for: .touchUpInside) } override func viewWillAppear(_ animated: Bool) { @@ -296,38 +242,20 @@ extension MastodonPickServerViewController { setupNavigationBarAppearance() updateEmptyStateViewLayout() - configureTitleLabel() - configureMargin() } } -extension MastodonPickServerViewController { - private func configureTitleLabel() { - guard UIDevice.current.userInterfaceIdiom == .pad else { - return - } - - switch traitCollection.horizontalSizeClass { - case .regular: - navigationItem.largeTitleDisplayMode = .always - navigationItem.title = L10n.Scene.ServerPicker.title.replacingOccurrences(of: "\n", with: " ") - default: - navigationItem.largeTitleDisplayMode = .never - navigationItem.title = nil - } - } -} - extension MastodonPickServerViewController { - @objc - private func nextStepButtonDidClicked(_ sender: UIButton) { + @objc private func backButtonDidPressed(_ sender: UIButton) { + navigationController?.popViewController(animated: true) + } + + @objc private func nextButtonDidPressed(_ sender: UIButton) { switch viewModel.mode { - case .signIn: - doSignIn() - case .signUp: - doSignUp() + case .signIn: doSignIn() + case .signUp: doSignUp() } } @@ -458,16 +386,6 @@ extension MastodonPickServerViewController { // MARK: - UITableViewDelegate extension MastodonPickServerViewController: UITableViewDelegate { - func scrollViewDidScroll(_ scrollView: UIScrollView) { - guard scrollView === tableView else { return } - let offsetY = scrollView.contentOffset.y + scrollView.safeAreaInsets.top - if offsetY < 0 { - tableViewTopPaddingViewHeightLayoutConstraint.constant = abs(offsetY) - } else { - tableViewTopPaddingViewHeightLayoutConstraint.constant = 0 - } - } - func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? { guard let diffableDataSource = viewModel.diffableDataSource else { return nil } guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return nil } @@ -500,87 +418,89 @@ extension MastodonPickServerViewController: UITableViewDelegate { guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return } switch item { - case .categoryPicker: - guard let cell = cell as? PickServerCategoriesCell else { return } - guard let diffableDataSource = cell.diffableDataSource else { return } - let snapshot = diffableDataSource.snapshot() - - let item = viewModel.selectCategoryItem.value - guard let section = snapshot.indexOfSection(.main), - let row = snapshot.indexOfItem(item) else { return } - cell.collectionView.selectItem(at: IndexPath(item: row, section: section), animated: false, scrollPosition: .centeredHorizontally) - case .search: - guard let cell = cell as? PickServerSearchCell else { return } - cell.searchTextField.text = viewModel.searchText.value +// case .categoryPicker: +// guard let cell = cell as? PickServerCategoriesCell else { return } +// guard let diffableDataSource = cell.diffableDataSource else { return } +// let snapshot = diffableDataSource.snapshot() +// +// let item = viewModel.selectCategoryItem.value +// guard let section = snapshot.indexOfSection(.main), +// let row = snapshot.indexOfItem(item) else { return } +// cell.collectionView.selectItem(at: IndexPath(item: row, section: section), animated: false, scrollPosition: .centeredHorizontally) +// case .search: +// guard let cell = cell as? PickServerSearchCell else { return } +// cell.searchTextField.text = viewModel.searchText.value default: break } } + func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { + guard let diffableDataSource = viewModel.diffableDataSource else { return nil } + let snapshot = diffableDataSource.snapshot() + guard section < snapshot.numberOfSections else { return nil } + let section = snapshot.sectionIdentifiers[section] + + switch section { + case .servers: + return viewModel.serverSectionHeaderView + default: + return UIView() + } + } + + func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { + guard let diffableDataSource = viewModel.diffableDataSource else { return .leastNonzeroMagnitude } + let snapshot = diffableDataSource.snapshot() + guard section < snapshot.numberOfSections else { return .leastNonzeroMagnitude } + let section = snapshot.sectionIdentifiers[section] + + switch section { + case .servers: + return PickServerServerSectionTableHeaderView.height + default: + return .leastNonzeroMagnitude + } + } + } extension MastodonPickServerViewController { private func updateEmptyStateViewLayout() { - guard let diffableDataSource = self.viewModel.diffableDataSource else { return } - guard let indexPath = diffableDataSource.indexPath(for: .search) else { return } - let rectInTableView = tableView.rectForRow(at: indexPath) - - emptyStateView.topPaddingViewTopLayoutConstraint.constant = rectInTableView.maxY - - switch traitCollection.horizontalSizeClass { - case .regular: - emptyStateViewLeadingLayoutConstraint.constant = MastodonPickServerViewController.viewEdgeMargin - emptyStateViewTrailingLayoutConstraint.constant = MastodonPickServerViewController.viewEdgeMargin - default: - let margin = tableView.layoutMarginsGuide.layoutFrame.origin.x - emptyStateViewLeadingLayoutConstraint.constant = margin - emptyStateViewTrailingLayoutConstraint.constant = margin - } - } - - private func configureMargin() { - switch traitCollection.horizontalSizeClass { - case .regular: - let margin = MastodonPickServerViewController.viewEdgeMargin - buttonContainer.layoutMargins = UIEdgeInsets(top: 0, left: margin, bottom: 0, right: margin) - default: - buttonContainer.layoutMargins = .zero - } +// guard let diffableDataSource = self.viewModel.diffableDataSource else { return } +// guard let indexPath = diffableDataSource.indexPath(for: .search) else { return } +// let rectInTableView = tableView.rectForRow(at: indexPath) +// +// emptyStateView.topPaddingViewTopLayoutConstraint.constant = rectInTableView.maxY +// +// switch traitCollection.horizontalSizeClass { +// case .regular: +// emptyStateViewLeadingLayoutConstraint.constant = MastodonPickServerViewController.viewEdgeMargin +// emptyStateViewTrailingLayoutConstraint.constant = MastodonPickServerViewController.viewEdgeMargin +// default: +// let margin = tableView.layoutMarginsGuide.layoutFrame.origin.x +// emptyStateViewLeadingLayoutConstraint.constant = margin +// emptyStateViewTrailingLayoutConstraint.constant = margin +// } } } -// MARK: - PickServerCategoriesCellDelegate -extension MastodonPickServerViewController: PickServerCategoriesCellDelegate { - func pickServerCategoriesCell(_ cell: PickServerCategoriesCell, collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - guard let diffableDataSource = cell.diffableDataSource else { return } +// MARK: - PickServerServerSectionTableHeaderViewDelegate +extension MastodonPickServerViewController: PickServerServerSectionTableHeaderViewDelegate { + func pickServerServerSectionTableHeaderView(_ headerView: PickServerServerSectionTableHeaderView, collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + guard let diffableDataSource = headerView.diffableDataSource else { return } let item = diffableDataSource.itemIdentifier(for: indexPath) viewModel.selectCategoryItem.value = item ?? .all } -} - -// MARK: - PickServerSearchCellDelegate -extension MastodonPickServerViewController: PickServerSearchCellDelegate { - func pickServerSearchCell(_ cell: PickServerSearchCell, searchTextDidChange searchText: String?) { + + func pickServerServerSectionTableHeaderView(_ headerView: PickServerServerSectionTableHeaderView, searchTextDidChange searchText: String?) { viewModel.searchText.send(searchText ?? "") } } // MARK: - PickServerCellDelegate extension MastodonPickServerViewController: PickServerCellDelegate { - func pickServerCell(_ cell: PickServerCell, expandButtonPressed button: UIButton) { - guard let diffableDataSource = viewModel.diffableDataSource else { return } - guard let indexPath = tableView.indexPath(for: cell) else { return } - guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return } - guard case let .server(_, attribute) = item else { return } - - attribute.isExpand.toggle() - tableView.beginUpdates() - cell.updateExpandMode(mode: attribute.isExpand ? .expand : .collapse) - tableView.endUpdates() - - // expand attribute change do not needs apply snapshot to diffable data source - // but should I block the viewModel data binding during tableView.beginUpdates/endUpdates? - } + } // MARK: - OnboardingViewControllerAppearance diff --git a/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewModel+Diffable.swift b/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewModel+Diffable.swift index 9da0399e..15278672 100644 --- a/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewModel+Diffable.swift +++ b/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewModel+Diffable.swift @@ -6,32 +6,101 @@ // import UIKit +import Combine extension MastodonPickServerViewModel { func setupDiffableDataSource( for tableView: UITableView, dependency: NeedsDependency, - pickServerCategoriesCellDelegate: PickServerCategoriesCellDelegate, - pickServerSearchCellDelegate: PickServerSearchCellDelegate, + pickServerServerSectionTableHeaderViewDelegate: PickServerServerSectionTableHeaderViewDelegate, pickServerCellDelegate: PickServerCellDelegate ) { + // set section header + serverSectionHeaderView.diffableDataSource = CategoryPickerSection.collectionViewDiffableDataSource( + for: serverSectionHeaderView.collectionView, + dependency: dependency + ) + var sectionHeaderSnapshot = NSDiffableDataSourceSnapshot() + sectionHeaderSnapshot.appendSections([.main]) + sectionHeaderSnapshot.appendItems(categoryPickerItems, toSection: .main) + serverSectionHeaderView.delegate = pickServerServerSectionTableHeaderViewDelegate + serverSectionHeaderView.diffableDataSource?.applySnapshot(sectionHeaderSnapshot, animated: false) + + // set tableView diffableDataSource = PickServerSection.tableViewDiffableDataSource( for: tableView, dependency: dependency, - pickServerCategoriesCellDelegate: pickServerCategoriesCellDelegate, - pickServerSearchCellDelegate: pickServerSearchCellDelegate, pickServerCellDelegate: pickServerCellDelegate ) var snapshot = NSDiffableDataSourceSnapshot() - snapshot.appendSections([.header, .category, .search, .servers]) + snapshot.appendSections([.header, .servers]) snapshot.appendItems([.header], toSection: .header) - snapshot.appendItems([.categoryPicker(items: categoryPickerItems)], toSection: .category) - snapshot.appendItems([.search], toSection: .search) diffableDataSource?.apply(snapshot, animatingDifferences: false, completion: nil) loadIndexedServerStateMachine.enter(LoadIndexedServerState.Loading.self) + + Publishers.CombineLatest( + filteredIndexedServers, + unindexedServers + ) + .receive(on: DispatchQueue.main) + .sink(receiveValue: { [weak self] indexedServers, unindexedServers in + guard let self = self else { return } + guard let diffableDataSource = self.diffableDataSource else { return } + + let oldSnapshot = diffableDataSource.snapshot() + var oldSnapshotServerItemAttributeDict: [String : PickServerItem.ServerItemAttribute] = [:] + for item in oldSnapshot.itemIdentifiers { + guard case let .server(server, attribute) = item else { continue } + oldSnapshotServerItemAttributeDict[server.domain] = attribute + } + + var snapshot = NSDiffableDataSourceSnapshot() + snapshot.appendSections([.header, .servers]) + snapshot.appendItems([.header], toSection: .header) + + // TODO: handle filter + var serverItems: [PickServerItem] = [] + for server in indexedServers { + let attribute = oldSnapshotServerItemAttributeDict[server.domain] ?? PickServerItem.ServerItemAttribute(isLast: false, isExpand: false) + attribute.isLast.value = false + let item = PickServerItem.server(server: server, attribute: attribute) + guard !serverItems.contains(item) else { continue } + serverItems.append(item) + } + + if let unindexedServers = unindexedServers { + if !unindexedServers.isEmpty { + for server in unindexedServers { + let attribute = oldSnapshotServerItemAttributeDict[server.domain] ?? PickServerItem.ServerItemAttribute(isLast: false, isExpand: false) + attribute.isLast.value = false + let item = PickServerItem.server(server: server, attribute: attribute) + guard !serverItems.contains(item) else { continue } + serverItems.append(item) + } + } else { + if indexedServers.isEmpty && !self.isLoadingIndexedServers.value { + serverItems.append(.loader(attribute: PickServerItem.LoaderItemAttribute(isLast: false, isEmptyResult: true))) + } + } + } else { + serverItems.append(.loader(attribute: PickServerItem.LoaderItemAttribute(isLast: false, isEmptyResult: false))) + } + + if case let .server(_, attribute) = serverItems.last { + attribute.isLast.value = true + } + if case let .loader(attribute) = serverItems.last { + attribute.isLast = true + } + snapshot.appendItems(serverItems, toSection: .servers) + + diffableDataSource.defaultRowAnimation = .fade + diffableDataSource.apply(snapshot, animatingDifferences: true, completion: nil) + }) + .store(in: &disposeBag) } } diff --git a/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewModel.swift b/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewModel.swift index 7a648011..af38b110 100644 --- a/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewModel.swift +++ b/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewModel.swift @@ -12,6 +12,7 @@ import GameplayKit import MastodonSDK import CoreDataStack import OrderedCollections +import Tabman class MastodonPickServerViewModel: NSObject { @@ -27,6 +28,8 @@ class MastodonPickServerViewModel: NSObject { } var disposeBag = Set() + + let serverSectionHeaderView = PickServerServerSectionTableHeaderView() // input let mode: PickServerMode @@ -82,68 +85,6 @@ class MastodonPickServerViewModel: NSObject { extension MastodonPickServerViewModel { private func configure() { - Publishers.CombineLatest( - filteredIndexedServers, - unindexedServers - ) - .receive(on: DispatchQueue.main) - .sink(receiveValue: { [weak self] indexedServers, unindexedServers in - guard let self = self else { return } - guard let diffableDataSource = self.diffableDataSource else { return } - - let oldSnapshot = diffableDataSource.snapshot() - var oldSnapshotServerItemAttributeDict: [String : PickServerItem.ServerItemAttribute] = [:] - for item in oldSnapshot.itemIdentifiers { - guard case let .server(server, attribute) = item else { continue } - oldSnapshotServerItemAttributeDict[server.domain] = attribute - } - - var snapshot = NSDiffableDataSourceSnapshot() - snapshot.appendSections([.header, .category, .search, .servers]) - snapshot.appendItems([.header], toSection: .header) - snapshot.appendItems([.categoryPicker(items: self.categoryPickerItems)], toSection: .category) - snapshot.appendItems([.search], toSection: .search) - // TODO: handle filter - var serverItems: [PickServerItem] = [] - for server in indexedServers { - let attribute = oldSnapshotServerItemAttributeDict[server.domain] ?? PickServerItem.ServerItemAttribute(isLast: false, isExpand: false) - attribute.isLast.value = false - let item = PickServerItem.server(server: server, attribute: attribute) - guard !serverItems.contains(item) else { continue } - serverItems.append(item) - } - - if let unindexedServers = unindexedServers { - if !unindexedServers.isEmpty { - for server in unindexedServers { - let attribute = oldSnapshotServerItemAttributeDict[server.domain] ?? PickServerItem.ServerItemAttribute(isLast: false, isExpand: false) - attribute.isLast.value = false - let item = PickServerItem.server(server: server, attribute: attribute) - guard !serverItems.contains(item) else { continue } - serverItems.append(item) - } - } else { - if indexedServers.isEmpty && !self.isLoadingIndexedServers.value { - serverItems.append(.loader(attribute: PickServerItem.LoaderItemAttribute(isLast: false, isEmptyResult: true))) - } - } - } else { - serverItems.append(.loader(attribute: PickServerItem.LoaderItemAttribute(isLast: false, isEmptyResult: false))) - } - - if case let .server(_, attribute) = serverItems.last { - attribute.isLast.value = true - } - if case let .loader(attribute) = serverItems.last { - attribute.isLast = true - } - snapshot.appendItems(serverItems, toSection: .servers) - - diffableDataSource.defaultRowAnimation = .fade - diffableDataSource.apply(snapshot, animatingDifferences: true, completion: nil) - }) - .store(in: &disposeBag) - Publishers.CombineLatest( isLoadingIndexedServers, loadingIndexedServersError @@ -301,3 +242,12 @@ extension MastodonPickServerViewModel { let applicationToken: Mastodon.Response.Content } } + +// MARK: - TMBarDataSource +extension MastodonPickServerViewModel: TMBarDataSource { + func barItem(for bar: TMBar, at index: Int) -> TMBarItemable { + let item = categoryPickerItems[index] + let barItem = TMBarItem(title: item.title) + return barItem + } +} diff --git a/Mastodon/Scene/Onboarding/PickServer/TableViewCell/PickServerCategoriesCell.swift b/Mastodon/Scene/Onboarding/PickServer/TableViewCell/PickServerCategoriesCell.swift deleted file mode 100644 index 65931775..00000000 --- a/Mastodon/Scene/Onboarding/PickServer/TableViewCell/PickServerCategoriesCell.swift +++ /dev/null @@ -1,145 +0,0 @@ -// -// PickServerCategoriesCell.swift -// Mastodon -// -// Created by BradGao on 2021/2/23. -// - -import os.log -import UIKit -import MastodonSDK - -protocol PickServerCategoriesCellDelegate: AnyObject { - func pickServerCategoriesCell(_ cell: PickServerCategoriesCell, collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) -} - -final class PickServerCategoriesCell: UITableViewCell { - - weak var delegate: PickServerCategoriesCellDelegate? - - var diffableDataSource: UICollectionViewDiffableDataSource? - - let metricView = UIView() - - let collectionView: UICollectionView = { - let flowLayout = UICollectionViewFlowLayout() - flowLayout.scrollDirection = .horizontal - let view = ControlContainableCollectionView(frame: .zero, collectionViewLayout: flowLayout) - view.register(PickServerCategoryCollectionViewCell.self, forCellWithReuseIdentifier: String(describing: PickServerCategoryCollectionViewCell.self)) - view.backgroundColor = .clear - view.showsHorizontalScrollIndicator = false - view.showsVerticalScrollIndicator = false - view.layer.masksToBounds = false - view.translatesAutoresizingMaskIntoConstraints = false - return view - }() - - override func prepareForReuse() { - super.prepareForReuse() - - delegate = nil - } - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - _init() - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - _init() - } -} - -extension PickServerCategoriesCell { - - private func _init() { - selectionStyle = .none - backgroundColor = Asset.Theme.Mastodon.systemGroupedBackground.color - configureMargin() - - metricView.translatesAutoresizingMaskIntoConstraints = false - contentView.addSubview(metricView) - NSLayoutConstraint.activate([ - metricView.leadingAnchor.constraint(equalTo: contentView.layoutMarginsGuide.leadingAnchor), - metricView.trailingAnchor.constraint(equalTo: contentView.layoutMarginsGuide.trailingAnchor), - metricView.topAnchor.constraint(equalTo: contentView.topAnchor), - metricView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), - metricView.heightAnchor.constraint(equalToConstant: 80).priority(.defaultHigh), - ]) - - contentView.addSubview(collectionView) - NSLayoutConstraint.activate([ - collectionView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor), - collectionView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor), - collectionView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 10), - contentView.bottomAnchor.constraint(equalTo: collectionView.bottomAnchor, constant: 20), - collectionView.heightAnchor.constraint(equalToConstant: 80).priority(.defaultHigh), - ]) - - collectionView.delegate = self - } - - override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { - super.traitCollectionDidChange(previousTraitCollection) - - configureMargin() - } - - override func layoutSubviews() { - super.layoutSubviews() - - collectionView.collectionViewLayout.invalidateLayout() - } - -} - -extension PickServerCategoriesCell { - private func configureMargin() { - switch traitCollection.horizontalSizeClass { - case .regular: - let margin = MastodonPickServerViewController.viewEdgeMargin - contentView.layoutMargins = UIEdgeInsets(top: 0, left: margin, bottom: 0, right: margin) - default: - contentView.layoutMargins = .zero - } - } -} - -// MARK: - UICollectionViewDelegateFlowLayout -extension PickServerCategoriesCell: UICollectionViewDelegateFlowLayout { - - func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: indexPath: %s", ((#file as NSString).lastPathComponent), #line, #function, indexPath.debugDescription) - collectionView.selectItem(at: indexPath, animated: true, scrollPosition: .centeredHorizontally) - delegate?.pickServerCategoriesCell(self, collectionView: collectionView, didSelectItemAt: indexPath) - } - - func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { - layoutIfNeeded() - return UIEdgeInsets(top: 0, left: metricView.frame.minX - collectionView.frame.minX, bottom: 0, right: collectionView.frame.maxX - metricView.frame.maxX) - } - - func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { - return 16 - } - - func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { - return CGSize(width: 60, height: 80) - } - -} - -extension PickServerCategoriesCell { - - override func accessibilityElementCount() -> Int { - guard let diffableDataSource = diffableDataSource else { return 0 } - return diffableDataSource.snapshot().itemIdentifiers.count - } - - override func accessibilityElement(at index: Int) -> Any? { - guard let item = collectionView.cellForItem(at: IndexPath(item: index, section: 0)) else { return nil } - return item - } - -} diff --git a/Mastodon/Scene/Onboarding/PickServer/TableViewCell/PickServerCell.swift b/Mastodon/Scene/Onboarding/PickServer/TableViewCell/PickServerCell.swift index 2f60a520..6dd0f197 100644 --- a/Mastodon/Scene/Onboarding/PickServer/TableViewCell/PickServerCell.swift +++ b/Mastodon/Scene/Onboarding/PickServer/TableViewCell/PickServerCell.swift @@ -13,7 +13,7 @@ import AlamofireImage import Kanna protocol PickServerCellDelegate: AnyObject { - func pickServerCell(_ cell: PickServerCell, expandButtonPressed button: UIButton) +// func pickServerCell(_ cell: PickServerCell, expandButtonPressed button: UIButton) } class PickServerCell: UITableViewCell { @@ -21,20 +21,17 @@ class PickServerCell: UITableViewCell { weak var delegate: PickServerCellDelegate? var disposeBag = Set() - - let expandMode = CurrentValueSubject(.collapse) - - let containerView: UIView = { - let view = UIView() - view.layoutMargins = UIEdgeInsets(top: 16, left: 16, bottom: 10, right: 16) - view.backgroundColor = Asset.Theme.Mastodon.secondaryGroupedSystemBackground.color - view.translatesAutoresizingMaskIntoConstraints = false + + let containerView: UIStackView = { + let view = UIStackView() + view.axis = .vertical + view.spacing = 4 return view }() let domainLabel: UILabel = { let label = UILabel() - label.font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 17, weight: .semibold), maximumPointSize: 22) + label.font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 20, weight: .semibold)) label.textColor = Asset.Colors.Label.primary.color label.adjustsFontForContentSizeCategory = true label.translatesAutoresizingMaskIntoConstraints = false @@ -52,7 +49,7 @@ class PickServerCell: UITableViewCell { let descriptionLabel: UILabel = { let label = UILabel() - label.font = UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 15, weight: .regular)) + label.font = UIFontMetrics(forTextStyle: .caption1).scaledFont(for: .systemFont(ofSize: 13, weight: .regular)) label.numberOfLines = 0 label.textColor = Asset.Colors.Label.primary.color label.adjustsFontForContentSizeCategory = true @@ -60,112 +57,33 @@ class PickServerCell: UITableViewCell { return label }() - let thumbnailActivityIndicator = UIActivityIndicatorView(style: .medium) - - let thumbnailImageView: UIImageView = { - let imageView = UIImageView() - imageView.clipsToBounds = true - imageView.contentMode = .scaleAspectFill - imageView.translatesAutoresizingMaskIntoConstraints = false - return imageView - }() - let infoStackView: UIStackView = { let stackView = UIStackView() stackView.axis = .horizontal - stackView.alignment = .fill - stackView.distribution = .fillEqually - stackView.translatesAutoresizingMaskIntoConstraints = false + stackView.spacing = 16 return stackView }() - let expandBox: UIView = { - let view = UIView() - view.backgroundColor = .clear - view.translatesAutoresizingMaskIntoConstraints = false - return view - }() - - let expandButton: UIButton = { - let button = HitTestExpandedButton(type: .custom) - button.setImage(UIImage(systemName: "chevron.down", withConfiguration: UIImage.SymbolConfiguration(pointSize: 13)), for: .normal) - button.setTitle(L10n.Scene.ServerPicker.Button.seeMore, for: .normal) - button.setTitleColor(Asset.Colors.brandBlue.color, for: .normal) - button.titleLabel?.font = .systemFont(ofSize: 13, weight: .regular) - button.translatesAutoresizingMaskIntoConstraints = false - button.imageView?.transform = CGAffineTransform(scaleX: -1, y: 1) - button.titleLabel?.transform = CGAffineTransform(scaleX: -1, y: 1) - button.transform = CGAffineTransform(scaleX: -1, y: 1) - return button - }() - let separator: UIView = { let view = UIView() - view.backgroundColor = Asset.Theme.Mastodon.systemGroupedBackground.color - view.translatesAutoresizingMaskIntoConstraints = false + view.backgroundColor = Asset.Theme.System.separator.color return view }() let langValueLabel: UILabel = { let label = UILabel() label.textColor = Asset.Colors.Label.primary.color - label.font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 22, weight: .semibold), maximumPointSize: 27) + label.font = UIFontMetrics(forTextStyle: .caption1).scaledFont(for: .systemFont(ofSize: 12, weight: .regular)) label.textAlignment = .center label.adjustsFontForContentSizeCategory = true - label.translatesAutoresizingMaskIntoConstraints = false return label }() let usersValueLabel: UILabel = { let label = UILabel() label.textColor = Asset.Colors.Label.primary.color - label.font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 22, weight: .semibold), maximumPointSize: 27) - label.textAlignment = .center + label.font = UIFontMetrics(forTextStyle: .caption1).scaledFont(for: .systemFont(ofSize: 12, weight: .regular)) label.adjustsFontForContentSizeCategory = true - label.translatesAutoresizingMaskIntoConstraints = false - return label - }() - - let categoryValueLabel: UILabel = { - let label = UILabel() - label.textColor = Asset.Colors.Label.primary.color - label.font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 22, weight: .semibold), maximumPointSize: 27) - label.textAlignment = .center - label.adjustsFontForContentSizeCategory = true - label.translatesAutoresizingMaskIntoConstraints = false - return label - }() - - let langTitleLabel: UILabel = { - let label = UILabel() - label.textColor = Asset.Colors.Label.primary.color - label.font = UIFontMetrics(forTextStyle: .subheadline).scaledFont(for: .systemFont(ofSize: 11, weight: .regular), maximumPointSize: 16) - label.text = L10n.Scene.ServerPicker.Label.language - label.textAlignment = .center - label.adjustsFontForContentSizeCategory = true - label.translatesAutoresizingMaskIntoConstraints = false - return label - }() - - let usersTitleLabel: UILabel = { - let label = UILabel() - label.textColor = Asset.Colors.Label.primary.color - label.font = UIFontMetrics(forTextStyle: .subheadline).scaledFont(for: .systemFont(ofSize: 11, weight: .regular), maximumPointSize: 16) - label.text = L10n.Scene.ServerPicker.Label.users - label.textAlignment = .center - label.adjustsFontForContentSizeCategory = true - label.translatesAutoresizingMaskIntoConstraints = false - return label - }() - - let categoryTitleLabel: UILabel = { - let label = UILabel() - label.textColor = Asset.Colors.Label.primary.color - label.font = UIFontMetrics(forTextStyle: .subheadline).scaledFont(for: .systemFont(ofSize: 11, weight: .regular), maximumPointSize: 16) - label.text = L10n.Scene.ServerPicker.Label.category - label.textAlignment = .center - label.adjustsFontForContentSizeCategory = true - label.translatesAutoresizingMaskIntoConstraints = false return label }() @@ -175,9 +93,6 @@ class PickServerCell: UITableViewCell { override func prepareForReuse() { super.prepareForReuse() - thumbnailImageView.isHidden = false - thumbnailImageView.af.cancelImageRequest() - thumbnailActivityIndicator.stopAnimating() disposeBag.removeAll() } @@ -197,172 +112,55 @@ class PickServerCell: UITableViewCell { extension PickServerCell { private func _init() { selectionStyle = .none - backgroundColor = .clear - configureMargin() + backgroundColor = Asset.Scene.Onboarding.onboardingBackground.color + + checkbox.translatesAutoresizingMaskIntoConstraints = false + contentView.addSubview(checkbox) + NSLayoutConstraint.activate([ + checkbox.leadingAnchor.constraint(equalTo: contentView.readableContentGuide.leadingAnchor, constant: 1), + checkbox.heightAnchor.constraint(equalToConstant: 32).priority(.required - 1), + checkbox.widthAnchor.constraint(equalToConstant: 32).priority(.required - 1), + ]) + containerView.translatesAutoresizingMaskIntoConstraints = false contentView.addSubview(containerView) - containerView.addSubview(domainLabel) - containerView.addSubview(checkbox) - containerView.addSubview(descriptionLabel) - containerView.addSubview(separator) - - containerView.addSubview(expandButton) - - // Always add the expandbox which contains elements only visible in expand mode - containerView.addSubview(expandBox) - expandBox.addSubview(thumbnailImageView) - expandBox.addSubview(infoStackView) - expandBox.isHidden = true - - let verticalInfoStackViewLang = makeVerticalInfoStackView(arrangedView: langValueLabel, langTitleLabel) - let verticalInfoStackViewUsers = makeVerticalInfoStackView(arrangedView: usersValueLabel, usersTitleLabel) - let verticalInfoStackViewCategory = makeVerticalInfoStackView(arrangedView: categoryValueLabel, categoryTitleLabel) - infoStackView.addArrangedSubview(verticalInfoStackViewLang) - infoStackView.addArrangedSubview(verticalInfoStackViewUsers) - infoStackView.addArrangedSubview(verticalInfoStackViewCategory) - - let expandButtonTopConstraintInCollapse = expandButton.topAnchor.constraint(equalTo: descriptionLabel.lastBaselineAnchor, constant: 12).priority(.required - 1) - collapseConstraints.append(expandButtonTopConstraintInCollapse) - - let expandButtonTopConstraintInExpand = expandButton.topAnchor.constraint(equalTo: expandBox.bottomAnchor, constant: 8).priority(.defaultHigh) - expandConstraints.append(expandButtonTopConstraintInExpand) - NSLayoutConstraint.activate([ - // Set background view - containerView.topAnchor.constraint(equalTo: contentView.topAnchor), - containerView.leadingAnchor.constraint(equalTo: contentView.layoutMarginsGuide.leadingAnchor), - contentView.layoutMarginsGuide.trailingAnchor.constraint(equalTo: containerView.trailingAnchor), - contentView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor), - - // Set bottom separator - separator.leadingAnchor.constraint(equalTo: containerView.leadingAnchor), - containerView.trailingAnchor.constraint(equalTo: separator.trailingAnchor), - containerView.topAnchor.constraint(equalTo: separator.topAnchor), - separator.heightAnchor.constraint(equalToConstant: 1).priority(.defaultHigh), - - domainLabel.topAnchor.constraint(equalTo: containerView.layoutMarginsGuide.topAnchor), - domainLabel.leadingAnchor.constraint(equalTo: containerView.layoutMarginsGuide.leadingAnchor), - - checkbox.widthAnchor.constraint(equalToConstant: 23), - checkbox.heightAnchor.constraint(equalToConstant: 22), - containerView.layoutMarginsGuide.trailingAnchor.constraint(equalTo: checkbox.trailingAnchor), - checkbox.leadingAnchor.constraint(equalTo: domainLabel.trailingAnchor, constant: 16), - checkbox.centerYAnchor.constraint(equalTo: domainLabel.centerYAnchor), - - descriptionLabel.leadingAnchor.constraint(equalTo: containerView.layoutMarginsGuide.leadingAnchor), - descriptionLabel.topAnchor.constraint(equalTo: domainLabel.bottomAnchor, constant: 8), - containerView.layoutMarginsGuide.trailingAnchor.constraint(equalTo: descriptionLabel.trailingAnchor), - - // Set expandBox constraints - expandBox.leadingAnchor.constraint(equalTo: containerView.layoutMarginsGuide.leadingAnchor), - containerView.layoutMarginsGuide.trailingAnchor.constraint(equalTo: expandBox.trailingAnchor), - expandBox.topAnchor.constraint(equalTo: descriptionLabel.bottomAnchor, constant: 8), - expandBox.bottomAnchor.constraint(equalTo: infoStackView.bottomAnchor).priority(.defaultHigh), - - thumbnailImageView.topAnchor.constraint(equalTo: expandBox.topAnchor), - thumbnailImageView.leadingAnchor.constraint(equalTo: expandBox.leadingAnchor), - expandBox.trailingAnchor.constraint(equalTo: thumbnailImageView.trailingAnchor), - thumbnailImageView.heightAnchor.constraint(equalTo: thumbnailImageView.widthAnchor, multiplier: 151.0 / 303.0).priority(.defaultHigh), - - infoStackView.leadingAnchor.constraint(equalTo: expandBox.leadingAnchor), - expandBox.trailingAnchor.constraint(equalTo: infoStackView.trailingAnchor), - infoStackView.topAnchor.constraint(equalTo: thumbnailImageView.bottomAnchor, constant: 16), - - expandButton.leadingAnchor.constraint(equalTo: containerView.layoutMarginsGuide.leadingAnchor), - containerView.layoutMarginsGuide.trailingAnchor.constraint(equalTo: expandButton.trailingAnchor), - containerView.layoutMarginsGuide.bottomAnchor.constraint(equalTo: expandButton.bottomAnchor), + containerView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 11), + containerView.leadingAnchor.constraint(equalTo: checkbox.trailingAnchor, constant: 22), + containerView.trailingAnchor.constraint(equalTo: contentView.readableContentGuide.trailingAnchor), + contentView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor, constant: 11), + checkbox.centerYAnchor.constraint(equalTo: containerView.centerYAnchor), ]) - thumbnailActivityIndicator.translatesAutoresizingMaskIntoConstraints = false - thumbnailImageView.addSubview(thumbnailActivityIndicator) + containerView.addArrangedSubview(domainLabel) + containerView.addArrangedSubview(descriptionLabel) + containerView.setCustomSpacing(6, after: descriptionLabel) + containerView.addArrangedSubview(infoStackView) + + infoStackView.addArrangedSubview(usersValueLabel) + infoStackView.addArrangedSubview(langValueLabel) + infoStackView.addArrangedSubview(UIView()) + + separator.translatesAutoresizingMaskIntoConstraints = false + contentView.addSubview(separator) NSLayoutConstraint.activate([ - thumbnailActivityIndicator.centerXAnchor.constraint(equalTo: thumbnailImageView.centerXAnchor), - thumbnailActivityIndicator.centerYAnchor.constraint(equalTo: thumbnailImageView.centerYAnchor), + separator.leadingAnchor.constraint(equalTo: contentView.readableContentGuide.leadingAnchor), + contentView.readableContentGuide.trailingAnchor.constraint(equalTo: separator.trailingAnchor), + separator.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + separator.heightAnchor.constraint(equalToConstant: UIView.separatorLineHeight(of: contentView)).priority(.required - 1), ]) - thumbnailActivityIndicator.hidesWhenStopped = true - thumbnailActivityIndicator.stopAnimating() - - NSLayoutConstraint.activate(collapseConstraints) - - domainLabel.setContentHuggingPriority(.required - 1, for: .vertical) - domainLabel.setContentCompressionResistancePriority(.required - 1, for: .vertical) - descriptionLabel.setContentHuggingPriority(.required - 2, for: .vertical) - descriptionLabel.setContentCompressionResistancePriority(.required - 2, for: .vertical) - - expandButton.addTarget(self, action: #selector(expandButtonDidPressed(_:)), for: .touchUpInside) } - override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { - super.traitCollectionDidChange(previousTraitCollection) - - configureMargin() - } - - private func makeVerticalInfoStackView(arrangedView: UIView...) -> UIStackView { - let stackView = UIStackView() - stackView.translatesAutoresizingMaskIntoConstraints = false - stackView.axis = .vertical - stackView.alignment = .center - stackView.distribution = .equalCentering - stackView.spacing = 2 - arrangedView.forEach { stackView.addArrangedSubview($0) } - return stackView - } - override func setSelected(_ selected: Bool, animated: Bool) { super.setSelected(selected, animated: animated) if selected { checkbox.image = UIImage(systemName: "checkmark.circle.fill") + checkbox.tintColor = Asset.Colors.Label.primary.color } else { checkbox.image = UIImage(systemName: "circle") + checkbox.tintColor = Asset.Colors.Label.secondary.color } } - - @objc - private func expandButtonDidPressed(_ sender: UIButton) { - os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function) - delegate?.pickServerCell(self, expandButtonPressed: sender) - } + } -extension PickServerCell { - private func configureMargin() { - switch traitCollection.horizontalSizeClass { - case .regular: - let margin = MastodonPickServerViewController.viewEdgeMargin - contentView.layoutMargins = UIEdgeInsets(top: 0, left: margin, bottom: 0, right: margin) - default: - contentView.layoutMargins = .zero - } - } -} - -extension PickServerCell { - - enum ExpandMode { - case collapse - case expand - } - - func updateExpandMode(mode: ExpandMode) { - switch mode { - case .collapse: - expandButton.setImage(UIImage(systemName: "chevron.down", withConfiguration: UIImage.SymbolConfiguration(pointSize: 13)), for: .normal) - expandButton.setTitle(L10n.Scene.ServerPicker.Button.seeMore, for: .normal) - expandBox.isHidden = true - expandButton.isSelected = false - NSLayoutConstraint.deactivate(expandConstraints) - NSLayoutConstraint.activate(collapseConstraints) - case .expand: - expandButton.setImage(UIImage(systemName: "chevron.up", withConfiguration: UIImage.SymbolConfiguration(pointSize: 13)), for: .normal) - expandButton.setTitle(L10n.Scene.ServerPicker.Button.seeLess, for: .normal) - expandBox.isHidden = false - expandButton.isSelected = true - NSLayoutConstraint.activate(expandConstraints) - NSLayoutConstraint.deactivate(collapseConstraints) - } - - expandMode.value = mode - } - -} diff --git a/Mastodon/Scene/Onboarding/PickServer/TableViewCell/PickServerLoaderTableViewCell.swift b/Mastodon/Scene/Onboarding/PickServer/TableViewCell/PickServerLoaderTableViewCell.swift index 945ecac6..eb0b619d 100644 --- a/Mastodon/Scene/Onboarding/PickServer/TableViewCell/PickServerLoaderTableViewCell.swift +++ b/Mastodon/Scene/Onboarding/PickServer/TableViewCell/PickServerLoaderTableViewCell.swift @@ -13,15 +13,7 @@ final class PickServerLoaderTableViewCell: TimelineLoaderTableViewCell { let containerView: UIView = { let view = UIView() view.layoutMargins = UIEdgeInsets(top: 16, left: 16, bottom: 10, right: 16) - view.backgroundColor = Asset.Theme.Mastodon.secondaryGroupedSystemBackground.color - view.translatesAutoresizingMaskIntoConstraints = false - return view - }() - - let seperator: UIView = { - let view = UIView() - view.backgroundColor = Asset.Theme.Mastodon.systemGroupedBackground.color - view.translatesAutoresizingMaskIntoConstraints = false + view.backgroundColor = .clear return view }() @@ -30,30 +22,22 @@ final class PickServerLoaderTableViewCell: TimelineLoaderTableViewCell { label.text = L10n.Scene.ServerPicker.EmptyState.noResults label.textColor = Asset.Colors.Label.secondary.color label.textAlignment = .center - label.font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 14, weight: .semibold), maximumPointSize: 19) + label.font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 14, weight: .semibold)) return label }() override func _init() { super._init() - - configureMargin() - - contentView.addSubview(containerView) - contentView.addSubview(seperator) + + // Set background view + containerView.translatesAutoresizingMaskIntoConstraints = false + contentView.addSubview(containerView) NSLayoutConstraint.activate([ - // Set background view containerView.topAnchor.constraint(equalTo: contentView.topAnchor), containerView.leadingAnchor.constraint(equalTo: contentView.layoutMarginsGuide.leadingAnchor), contentView.layoutMarginsGuide.trailingAnchor.constraint(equalTo: containerView.trailingAnchor), - contentView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor, constant: 1), - - // Set bottom separator - seperator.leadingAnchor.constraint(equalTo: containerView.leadingAnchor), - containerView.trailingAnchor.constraint(equalTo: seperator.trailingAnchor), - containerView.topAnchor.constraint(equalTo: seperator.topAnchor), - seperator.heightAnchor.constraint(equalToConstant: 1).priority(.defaultHigh), + contentView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor), ]) emptyStatusLabel.translatesAutoresizingMaskIntoConstraints = false @@ -69,24 +53,7 @@ final class PickServerLoaderTableViewCell: TimelineLoaderTableViewCell { activityIndicatorView.isHidden = false startAnimating() } - - override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { - super.traitCollectionDidChange(previousTraitCollection) - - configureMargin() - } -} -extension PickServerLoaderTableViewCell { - private func configureMargin() { - switch traitCollection.horizontalSizeClass { - case .regular: - let margin = MastodonPickServerViewController.viewEdgeMargin - contentView.layoutMargins = UIEdgeInsets(top: 0, left: margin, bottom: 0, right: margin) - default: - contentView.layoutMargins = .zero - } - } } #if canImport(SwiftUI) && DEBUG diff --git a/Mastodon/Scene/Onboarding/PickServer/TableViewCell/PickServerSearchCell.swift b/Mastodon/Scene/Onboarding/PickServer/TableViewCell/PickServerSearchCell.swift deleted file mode 100644 index 0a64103d..00000000 --- a/Mastodon/Scene/Onboarding/PickServer/TableViewCell/PickServerSearchCell.swift +++ /dev/null @@ -1,171 +0,0 @@ -// -// PickServerSearchCell.swift -// Mastodon -// -// Created by BradGao on 2021/2/24. -// - -import UIKit - -protocol PickServerSearchCellDelegate: AnyObject { - func pickServerSearchCell(_ cell: PickServerSearchCell, searchTextDidChange searchText: String?) -} - -class PickServerSearchCell: UITableViewCell { - - weak var delegate: PickServerSearchCellDelegate? - - private var bgView: UIView = { - let view = UIView() - view.backgroundColor = Asset.Theme.Mastodon.secondaryGroupedSystemBackground.color - view.translatesAutoresizingMaskIntoConstraints = false - view.layer.maskedCorners = [ - .layerMinXMinYCorner, - .layerMaxXMinYCorner - ] - view.layer.cornerCurve = .continuous - view.layer.cornerRadius = MastodonPickServerAppearance.tableViewCornerRadius - return view - }() - - private var textFieldBgView: UIView = { - let view = UIView() - view.backgroundColor = Asset.Colors.TextField.background.color - view.translatesAutoresizingMaskIntoConstraints = false - view.layer.masksToBounds = true - view.layer.cornerRadius = 6 - view.layer.cornerCurve = .continuous - return view - }() - - let searchTextField: UITextField = { - let textField = UITextField() - textField.translatesAutoresizingMaskIntoConstraints = false - textField.leftView = { - let imageView = UIImageView( - image: UIImage( - systemName: "magnifyingglass", - withConfiguration: UIImage.SymbolConfiguration(pointSize: 15, weight: .regular) - ) - ) - imageView.tintColor = Asset.Colors.Label.secondary.color.withAlphaComponent(0.6) - - let containerView = UIView() - imageView.translatesAutoresizingMaskIntoConstraints = false - containerView.addSubview(imageView) - NSLayoutConstraint.activate([ - imageView.topAnchor.constraint(equalTo: containerView.topAnchor), - imageView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor), - imageView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor), - ]) - - let paddingView = UIView() - paddingView.translatesAutoresizingMaskIntoConstraints = false - containerView.addSubview(paddingView) - NSLayoutConstraint.activate([ - paddingView.topAnchor.constraint(equalTo: containerView.topAnchor), - paddingView.leadingAnchor.constraint(equalTo: imageView.trailingAnchor), - paddingView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor), - paddingView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor), - paddingView.widthAnchor.constraint(equalToConstant: 4).priority(.defaultHigh), - ]) - return containerView - }() - textField.leftViewMode = .always - textField.font = .systemFont(ofSize: 15, weight: .regular) - textField.tintColor = Asset.Colors.Label.primary.color - textField.textColor = Asset.Colors.Label.primary.color - textField.adjustsFontForContentSizeCategory = true - textField.attributedPlaceholder = - NSAttributedString(string: L10n.Scene.ServerPicker.Input.placeholder, - attributes: [.font: UIFont.systemFont(ofSize: 15, weight: .regular), - .foregroundColor: Asset.Colors.Label.secondary.color.withAlphaComponent(0.6)]) - textField.clearButtonMode = .whileEditing - textField.autocapitalizationType = .none - textField.autocorrectionType = .no - textField.returnKeyType = .done - textField.keyboardType = .URL - return textField - }() - - override func prepareForReuse() { - super.prepareForReuse() - - delegate = nil - } - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - _init() - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - _init() - } -} - -extension PickServerSearchCell { - private func _init() { - selectionStyle = .none - backgroundColor = Asset.Theme.Mastodon.systemGroupedBackground.color - configureMargin() - - searchTextField.addTarget(self, action: #selector(textFieldDidChange(_:)), for: .editingChanged) - searchTextField.delegate = self - - contentView.addSubview(bgView) - contentView.addSubview(textFieldBgView) - contentView.addSubview(searchTextField) - - NSLayoutConstraint.activate([ - bgView.leadingAnchor.constraint(equalTo: contentView.layoutMarginsGuide.leadingAnchor), - bgView.topAnchor.constraint(equalTo: contentView.topAnchor), - bgView.trailingAnchor.constraint(equalTo: contentView.layoutMarginsGuide.trailingAnchor), - bgView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), - - textFieldBgView.leadingAnchor.constraint(equalTo: bgView.leadingAnchor, constant: 14), - textFieldBgView.topAnchor.constraint(equalTo: bgView.topAnchor, constant: 12), - bgView.trailingAnchor.constraint(equalTo: textFieldBgView.trailingAnchor, constant: 14), - bgView.bottomAnchor.constraint(equalTo: textFieldBgView.bottomAnchor, constant: 13), - - searchTextField.leadingAnchor.constraint(equalTo: textFieldBgView.leadingAnchor, constant: 11), - searchTextField.topAnchor.constraint(equalTo: textFieldBgView.topAnchor, constant: 4), - textFieldBgView.trailingAnchor.constraint(equalTo: searchTextField.trailingAnchor, constant: 11), - textFieldBgView.bottomAnchor.constraint(equalTo: searchTextField.bottomAnchor, constant: 4), - ]) - } - - override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { - super.traitCollectionDidChange(previousTraitCollection) - - configureMargin() - } -} - -extension PickServerSearchCell { - private func configureMargin() { - switch traitCollection.horizontalSizeClass { - case .regular: - let margin = MastodonPickServerViewController.viewEdgeMargin - contentView.layoutMargins = UIEdgeInsets(top: 0, left: margin, bottom: 0, right: margin) - default: - contentView.layoutMargins = .zero - } - } -} - -extension PickServerSearchCell { - @objc private func textFieldDidChange(_ textField: UITextField) { - delegate?.pickServerSearchCell(self, searchTextDidChange: textField.text) - } -} - -// MARK: - UITextFieldDelegate -extension PickServerSearchCell: UITextFieldDelegate { - - func textFieldShouldReturn(_ textField: UITextField) -> Bool { - textField.resignFirstResponder() - return false - } -} diff --git a/Mastodon/Scene/Onboarding/PickServer/TableViewCell/PickServerTitleCell.swift b/Mastodon/Scene/Onboarding/PickServer/TableViewCell/PickServerTitleCell.swift index f0d78eb4..161b15d0 100644 --- a/Mastodon/Scene/Onboarding/PickServer/TableViewCell/PickServerTitleCell.swift +++ b/Mastodon/Scene/Onboarding/PickServer/TableViewCell/PickServerTitleCell.swift @@ -11,17 +11,24 @@ final class PickServerTitleCell: UITableViewCell { let titleLabel: UILabel = { let label = UILabel() - label.font = UIFontMetrics(forTextStyle: .largeTitle).scaledFont(for: .systemFont(ofSize: 34, weight: .bold)) + label.font = UIFontMetrics(forTextStyle: .largeTitle).scaledFont(for: .systemFont(ofSize: 28, weight: .bold)) label.textColor = Asset.Colors.Label.primary.color label.text = L10n.Scene.ServerPicker.title label.adjustsFontForContentSizeCategory = true - label.translatesAutoresizingMaskIntoConstraints = false label.numberOfLines = 0 return label }() - var containerHeightLayoutConstraint: NSLayoutConstraint! - + let subTitleLabel: UILabel = { + let label = UILabel() + label.font = UIFontMetrics(forTextStyle: .largeTitle).scaledFont(for: .systemFont(ofSize: 17, weight: .regular)) + label.textColor = Asset.Colors.Label.secondary.color + label.text = "Pick a community based on your interests, region, or a general purpose one. Each community is operated by an entirely independent organization or individual." + label.adjustsFontForContentSizeCategory = true + label.numberOfLines = 0 + return label + }() + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) _init() @@ -37,46 +44,22 @@ extension PickServerTitleCell { private func _init() { selectionStyle = .none - backgroundColor = Asset.Theme.Mastodon.systemGroupedBackground.color + backgroundColor = Asset.Scene.Onboarding.onboardingBackground.color let container = UIStackView() container.axis = .vertical + container.spacing = 16 container.translatesAutoresizingMaskIntoConstraints = false - containerHeightLayoutConstraint = container.heightAnchor.constraint(equalToConstant: .leastNonzeroMagnitude) contentView.addSubview(container) NSLayoutConstraint.activate([ container.topAnchor.constraint(equalTo: contentView.topAnchor), container.leadingAnchor.constraint(equalTo: contentView.readableContentGuide.leadingAnchor), container.trailingAnchor.constraint(equalTo: contentView.readableContentGuide.trailingAnchor), - container.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + contentView.bottomAnchor.constraint(equalTo: container.bottomAnchor, constant: 11), ]) container.addArrangedSubview(titleLabel) - - configureTitleLabelDisplay() + container.addArrangedSubview(subTitleLabel) } - - override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { - super.traitCollectionDidChange(previousTraitCollection) - - configureTitleLabelDisplay() - } -} -extension PickServerTitleCell { - private func configureTitleLabelDisplay() { - guard traitCollection.userInterfaceIdiom == .pad else { - titleLabel.isHidden = false - return - } - - switch traitCollection.horizontalSizeClass { - case .regular: - titleLabel.isHidden = true - containerHeightLayoutConstraint.isActive = true - default: - titleLabel.isHidden = false - containerHeightLayoutConstraint.isActive = false - } - } } diff --git a/Mastodon/Scene/Onboarding/PickServer/View/PickServerCategoryView.swift b/Mastodon/Scene/Onboarding/PickServer/View/PickServerCategoryView.swift index 6565fbcf..f3bc3994 100644 --- a/Mastodon/Scene/Onboarding/PickServer/View/PickServerCategoryView.swift +++ b/Mastodon/Scene/Onboarding/PickServer/View/PickServerCategoryView.swift @@ -10,24 +10,24 @@ import MastodonSDK class PickServerCategoryView: UIView { - var bgShadowView: UIView = { + let highlightedIndicatorView: UIView = { let view = UIView() - view.translatesAutoresizingMaskIntoConstraints = false + view.backgroundColor = Asset.Colors.Label.primary.color return view }() - - var bgView: UIView = { - let view = UIView() - view.translatesAutoresizingMaskIntoConstraints = false - view.layer.masksToBounds = true - view.layer.cornerRadius = 30 - return view - }() - - var titleLabel: UILabel = { + + let emojiLabel: UILabel = { let label = UILabel() label.textAlignment = .center - label.translatesAutoresizingMaskIntoConstraints = false + label.font = .systemFont(ofSize: 34, weight: .regular) + return label + }() + + let titleLabel: UILabel = { + let label = UILabel() + label.textAlignment = .center + label.font = .systemFont(ofSize: 17, weight: .semibold) + label.textColor = Asset.Colors.Label.secondary.color return label }() @@ -45,20 +45,27 @@ class PickServerCategoryView: UIView { extension PickServerCategoryView { private func configure() { - addSubview(bgView) - addSubview(titleLabel) - - bgView.backgroundColor = Asset.Theme.Mastodon.secondaryGroupedSystemBackground.color - + let container = UIStackView() + container.axis = .vertical + container.distribution = .fillProportionally + + container.translatesAutoresizingMaskIntoConstraints = false + addSubview(container) NSLayoutConstraint.activate([ - bgView.leadingAnchor.constraint(equalTo: self.leadingAnchor), - bgView.trailingAnchor.constraint(equalTo: self.trailingAnchor), - bgView.topAnchor.constraint(equalTo: self.topAnchor), - bgView.bottomAnchor.constraint(equalTo: self.bottomAnchor), - - titleLabel.centerXAnchor.constraint(equalTo: self.centerXAnchor), - titleLabel.centerYAnchor.constraint(equalTo: self.centerYAnchor), + container.topAnchor.constraint(equalTo: topAnchor), + container.leadingAnchor.constraint(equalTo: leadingAnchor), + container.trailingAnchor.constraint(equalTo: trailingAnchor), + container.bottomAnchor.constraint(equalTo: bottomAnchor), ]) + + container.addArrangedSubview(emojiLabel) + container.addArrangedSubview(titleLabel) + highlightedIndicatorView.translatesAutoresizingMaskIntoConstraints = false + container.addArrangedSubview(highlightedIndicatorView) + NSLayoutConstraint.activate([ + highlightedIndicatorView.heightAnchor.constraint(equalToConstant: UIView.separatorLineHeight(of: self) * 3).priority(.required - 1), + ]) + titleLabel.setContentHuggingPriority(.required - 1, for: .vertical) } } diff --git a/Mastodon/Scene/Onboarding/PickServer/View/PickServerEmptyStateView.swift b/Mastodon/Scene/Onboarding/PickServer/View/PickServerEmptyStateView.swift index 1d2c17c7..c5682143 100644 --- a/Mastodon/Scene/Onboarding/PickServer/View/PickServerEmptyStateView.swift +++ b/Mastodon/Scene/Onboarding/PickServer/View/PickServerEmptyStateView.swift @@ -44,13 +44,7 @@ final class PickServerEmptyStateView: UIView { extension PickServerEmptyStateView { private func _init() { - backgroundColor = Asset.Theme.Mastodon.secondaryGroupedSystemBackground.color - layer.maskedCorners = [ - .layerMinXMaxYCorner, - .layerMaxXMaxYCorner - ] - layer.cornerCurve = .continuous - layer.cornerRadius = MastodonPickServerAppearance.tableViewCornerRadius + backgroundColor = .clear let topPaddingView = UIView() topPaddingView.translatesAutoresizingMaskIntoConstraints = false @@ -101,7 +95,7 @@ extension PickServerEmptyStateView { ]) NSLayoutConstraint.activate([ - bottomPaddingView.heightAnchor.constraint(equalTo: topPaddingView.heightAnchor, multiplier: 1.0).priority(.defaultHigh), + topPaddingView.heightAnchor.constraint(equalTo: bottomPaddingView.heightAnchor, multiplier: 2.5).priority(.defaultHigh), // magic scale ]) activityIndicatorView.hidesWhenStopped = true diff --git a/Mastodon/Scene/Onboarding/PickServer/View/PickServerServerSectionTableHeaderView.swift b/Mastodon/Scene/Onboarding/PickServer/View/PickServerServerSectionTableHeaderView.swift new file mode 100644 index 00000000..4afa31aa --- /dev/null +++ b/Mastodon/Scene/Onboarding/PickServer/View/PickServerServerSectionTableHeaderView.swift @@ -0,0 +1,204 @@ +// +// PickServerServerSectionTableHeaderView.swift +// Mastodon +// +// Created by MainasuK on 2022-1-4. +// + +import os.log +import UIKit +import Tabman + +protocol PickServerServerSectionTableHeaderViewDelegate: AnyObject { + func pickServerServerSectionTableHeaderView(_ headerView: PickServerServerSectionTableHeaderView, collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) + func pickServerServerSectionTableHeaderView(_ headerView: PickServerServerSectionTableHeaderView, searchTextDidChange searchText: String?) +} + +final class PickServerServerSectionTableHeaderView: UIView { + + static let collectionViewHeight: CGFloat = 88 + static let searchTextFieldHeight: CGFloat = 38 + static let spacing: CGFloat = 11 + + static let height: CGFloat = collectionViewHeight + spacing + searchTextFieldHeight + spacing + + weak var delegate: PickServerServerSectionTableHeaderViewDelegate? + + var diffableDataSource: UICollectionViewDiffableDataSource? + + static func createCollectionViewLayout() -> UICollectionViewLayout { + let itemSize = NSCollectionLayoutSize(widthDimension: .estimated(88), heightDimension: .absolute(PickServerServerSectionTableHeaderView.collectionViewHeight)) + let item = NSCollectionLayoutItem(layoutSize: itemSize) + + let groupSize = NSCollectionLayoutSize(widthDimension: itemSize.widthDimension, heightDimension: itemSize.heightDimension) + let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item]) + + let section = NSCollectionLayoutSection(group: group) + section.orthogonalScrollingBehavior = .continuous + section.contentInsetsReference = .readableContent + section.interGroupSpacing = 16 + + return UICollectionViewCompositionalLayout(section: section) + } + + let collectionView: UICollectionView = { + let collectionViewLayout = PickServerServerSectionTableHeaderView.createCollectionViewLayout() + let view = ControlContainableCollectionView( + frame: CGRect(origin: .zero, size: CGSize(width: 100, height: PickServerServerSectionTableHeaderView.collectionViewHeight)), + collectionViewLayout: collectionViewLayout + ) + view.register(PickServerCategoryCollectionViewCell.self, forCellWithReuseIdentifier: String(describing: PickServerCategoryCollectionViewCell.self)) + view.backgroundColor = .clear + view.alwaysBounceVertical = false + view.showsHorizontalScrollIndicator = false + view.showsVerticalScrollIndicator = false + view.layer.masksToBounds = false + return view + }() + + let searchTextField: UITextField = { + let textField = UITextField() + textField.backgroundColor = Asset.Scene.Onboarding.searchBarBackground.color + textField.leftView = { + let imageView = UIImageView( + image: UIImage( + systemName: "magnifyingglass", + withConfiguration: UIImage.SymbolConfiguration(pointSize: 15, weight: .regular) + ) + ) + imageView.tintColor = Asset.Colors.Label.secondary.color.withAlphaComponent(0.6) + + let containerView = UIView() + imageView.translatesAutoresizingMaskIntoConstraints = false + containerView.addSubview(imageView) + NSLayoutConstraint.activate([ + imageView.topAnchor.constraint(equalTo: containerView.topAnchor), + imageView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: 8), + imageView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor), + ]) + + let paddingView = UIView() + paddingView.translatesAutoresizingMaskIntoConstraints = false + containerView.addSubview(paddingView) + NSLayoutConstraint.activate([ + paddingView.topAnchor.constraint(equalTo: containerView.topAnchor), + paddingView.leadingAnchor.constraint(equalTo: imageView.trailingAnchor), + paddingView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor), + paddingView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor), + paddingView.widthAnchor.constraint(equalToConstant: 4).priority(.defaultHigh), + ]) + return containerView + }() + textField.leftViewMode = .always + textField.font = .systemFont(ofSize: 15, weight: .regular) + textField.tintColor = Asset.Colors.Label.primary.color + textField.textColor = Asset.Colors.Label.primary.color + textField.adjustsFontForContentSizeCategory = true + textField.attributedPlaceholder = + NSAttributedString( + string: L10n.Scene.ServerPicker.Input.placeholder, + attributes: [.font: UIFont.systemFont(ofSize: 15, weight: .regular), + .foregroundColor: Asset.Colors.Label.secondary.color.withAlphaComponent(0.6)]) + textField.clearButtonMode = .whileEditing + textField.autocapitalizationType = .none + textField.autocorrectionType = .no + textField.returnKeyType = .done + textField.keyboardType = .URL + textField.borderStyle = .none + + textField.layer.masksToBounds = true + textField.layer.cornerRadius = 10 + textField.layer.cornerCurve = .continuous + + return textField + }() + + override init(frame: CGRect) { + super.init(frame: frame) + _init() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + _init() + } + + override func layoutSubviews() { + super.layoutSubviews() + + collectionView.invalidateIntrinsicContentSize() + } + +} + +extension PickServerServerSectionTableHeaderView { + private func _init() { + preservesSuperviewLayoutMargins = true + backgroundColor = Asset.Scene.Onboarding.onboardingBackground.color + + collectionView.translatesAutoresizingMaskIntoConstraints = false + collectionView.preservesSuperviewLayoutMargins = true + addSubview(collectionView) + NSLayoutConstraint.activate([ + collectionView.topAnchor.constraint(equalTo: topAnchor), + collectionView.leadingAnchor.constraint(equalTo: leadingAnchor), + collectionView.trailingAnchor.constraint(equalTo: trailingAnchor), + collectionView.heightAnchor.constraint(equalToConstant: PickServerServerSectionTableHeaderView.collectionViewHeight).priority(.required - 1), + ]) + + searchTextField.translatesAutoresizingMaskIntoConstraints = false + addSubview(searchTextField) + NSLayoutConstraint.activate([ + searchTextField.topAnchor.constraint(equalTo: collectionView.bottomAnchor, constant: PickServerServerSectionTableHeaderView.spacing), + searchTextField.leadingAnchor.constraint(equalTo: readableContentGuide.leadingAnchor), + searchTextField.trailingAnchor.constraint(equalTo: readableContentGuide.trailingAnchor), + bottomAnchor.constraint(equalTo: searchTextField.bottomAnchor, constant: PickServerServerSectionTableHeaderView.spacing), + searchTextField.heightAnchor.constraint(equalToConstant: PickServerServerSectionTableHeaderView.searchTextFieldHeight).priority(.required - 1), + ]) + + collectionView.delegate = self + searchTextField.delegate = self + searchTextField.addTarget(self, action: #selector(PickServerServerSectionTableHeaderView.textFieldDidChange(_:)), for: .editingChanged) + } +} + +extension PickServerServerSectionTableHeaderView { + @objc private func textFieldDidChange(_ textField: UITextField) { + delegate?.pickServerServerSectionTableHeaderView(self, searchTextDidChange: textField.text) + } +} + +// MARK: - UICollectionViewDelegate +extension PickServerServerSectionTableHeaderView: UICollectionViewDelegate { + + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: indexPath: %s", ((#file as NSString).lastPathComponent), #line, #function, indexPath.debugDescription) + collectionView.selectItem(at: indexPath, animated: true, scrollPosition: .centeredHorizontally) + delegate?.pickServerServerSectionTableHeaderView(self, collectionView: collectionView, didSelectItemAt: indexPath) + } + +} + +extension PickServerServerSectionTableHeaderView { + + override func accessibilityElementCount() -> Int { + guard let diffableDataSource = diffableDataSource else { return 0 } + return diffableDataSource.snapshot().itemIdentifiers.count + } + + override func accessibilityElement(at index: Int) -> Any? { + guard let item = collectionView.cellForItem(at: IndexPath(item: index, section: 0)) else { return nil } + return item + } + +} + +// MARK: - UITextFieldDelegate +extension PickServerServerSectionTableHeaderView: UITextFieldDelegate { + + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + textField.resignFirstResponder() + return false + } + +} diff --git a/Mastodon/Scene/Onboarding/Share/NavigationActionView.swift b/Mastodon/Scene/Onboarding/Share/NavigationActionView.swift new file mode 100644 index 00000000..4b5bb124 --- /dev/null +++ b/Mastodon/Scene/Onboarding/Share/NavigationActionView.swift @@ -0,0 +1,69 @@ +// +// NavigationActionView.swift +// Mastodon +// +// Created by MainasuK on 2021-12-31. +// + +import UIKit + +final class NavigationActionView: UIView { + + static let buttonHeight: CGFloat = 50 + + let buttonContainer: UIStackView = { + let stackView = UIStackView() + stackView.axis = .horizontal + stackView.spacing = 18 + return stackView + }() + + let backButton: PrimaryActionButton = { + let button = PrimaryActionButton() + button.action = .back + button.setTitle(L10n.Common.Controls.Actions.back, for: .normal) + return button + }() + + let nextButton: PrimaryActionButton = { + let button = PrimaryActionButton() + button.action = .next + button.setTitle(L10n.Common.Controls.Actions.next, for: .normal) + return button + }() + + override init(frame: CGRect) { + super.init(frame: frame) + _init() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + _init() + } + +} + +extension NavigationActionView { + private func _init() { + buttonContainer.translatesAutoresizingMaskIntoConstraints = false + buttonContainer.preservesSuperviewLayoutMargins = true + addSubview(buttonContainer) + NSLayoutConstraint.activate([ + buttonContainer.topAnchor.constraint(equalTo: topAnchor, constant: 16), + buttonContainer.leadingAnchor.constraint(equalTo: readableContentGuide.leadingAnchor), + buttonContainer.trailingAnchor.constraint(equalTo: readableContentGuide.trailingAnchor), + safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: buttonContainer.bottomAnchor, constant: 8), + ]) + + backButton.translatesAutoresizingMaskIntoConstraints = false + buttonContainer.addArrangedSubview(backButton) + nextButton.translatesAutoresizingMaskIntoConstraints = false + buttonContainer.addArrangedSubview(nextButton) + NSLayoutConstraint.activate([ + backButton.heightAnchor.constraint(equalToConstant: NavigationActionView.buttonHeight).priority(.required - 1), + nextButton.heightAnchor.constraint(equalToConstant: NavigationActionView.buttonHeight).priority(.required - 1), + nextButton.widthAnchor.constraint(equalTo: backButton.widthAnchor, multiplier: 2).priority(.required - 1), + ]) + } +} diff --git a/Mastodon/Scene/Onboarding/Share/OnboardingNavigationController.swift b/Mastodon/Scene/Onboarding/Share/OnboardingNavigationController.swift index 07e58b58..537102dc 100644 --- a/Mastodon/Scene/Onboarding/Share/OnboardingNavigationController.swift +++ b/Mastodon/Scene/Onboarding/Share/OnboardingNavigationController.swift @@ -34,7 +34,7 @@ extension OnboardingNavigationController { super.traitCollectionDidChange(previousTraitCollection) } - + } extension OnboardingNavigationController { @@ -47,4 +47,5 @@ extension OnboardingNavigationController { gradientBorderView.isHidden = false } } + } diff --git a/Mastodon/Scene/Onboarding/Share/OnboardingViewControllerAppearance.swift b/Mastodon/Scene/Onboarding/Share/OnboardingViewControllerAppearance.swift index 2405f2a8..c4fae4dd 100644 --- a/Mastodon/Scene/Onboarding/Share/OnboardingViewControllerAppearance.swift +++ b/Mastodon/Scene/Onboarding/Share/OnboardingViewControllerAppearance.swift @@ -22,7 +22,7 @@ extension OnboardingViewControllerAppearance { static var viewBottomPaddingHeightExtend: CGFloat { return 22 } func setupOnboardingAppearance() { - view.backgroundColor = Asset.Theme.Mastodon.systemGroupedBackground.color + view.backgroundColor = Asset.Scene.Onboarding.onboardingBackground.color setupNavigationBarAppearance() @@ -39,31 +39,22 @@ extension OnboardingViewControllerAppearance { // use TransparentBackground so view push / dismiss will be more visual nature // please add opaque background for status bar manually if needs - switch traitCollection.userInterfaceIdiom { - case .pad: - if traitCollection.horizontalSizeClass == .regular { - // do nothing - } else { - fallthrough - } - default: - let barAppearance = UINavigationBarAppearance() - barAppearance.configureWithTransparentBackground() - navigationItem.standardAppearance = barAppearance - navigationItem.compactAppearance = barAppearance - navigationItem.scrollEdgeAppearance = barAppearance - if #available(iOS 15.0, *) { - navigationItem.compactScrollEdgeAppearance = barAppearance - } else { - // Fallback on earlier versions - } + let barAppearance = UINavigationBarAppearance() + barAppearance.configureWithTransparentBackground() + navigationItem.standardAppearance = barAppearance + navigationItem.compactAppearance = barAppearance + navigationItem.scrollEdgeAppearance = barAppearance + if #available(iOS 15.0, *) { + navigationItem.compactScrollEdgeAppearance = barAppearance + } else { + // Fallback on earlier versions } } func setupNavigationBarBackgroundView() { let navigationBarBackgroundView: UIView = { let view = UIView() - view.backgroundColor = Asset.Theme.Mastodon.systemGroupedBackground.color + view.backgroundColor = Asset.Scene.Onboarding.onboardingBackground.color return view }() diff --git a/Mastodon/Scene/Onboarding/Welcome/View/GradientBorderView.swift b/Mastodon/Scene/Onboarding/Welcome/View/GradientBorderView.swift index c9a4a0d7..68e7968b 100644 --- a/Mastodon/Scene/Onboarding/Welcome/View/GradientBorderView.swift +++ b/Mastodon/Scene/Onboarding/Welcome/View/GradientBorderView.swift @@ -12,6 +12,10 @@ final class GradientBorderView: UIView { let gradientLayer = CAGradientLayer() let maskLayer = CAShapeLayer() + var cornerRadius: CGFloat = 9 { + didSet { setNeedsLayout() } + } + override init(frame: CGRect) { super.init(frame: frame) _init() @@ -48,7 +52,7 @@ extension GradientBorderView { super.layoutSubviews() let bezierPath = UIBezierPath(rect: bounds) - bezierPath.append(UIBezierPath(roundedRect: bounds.insetBy(dx: 3, dy: 3), cornerRadius: 10)) + bezierPath.append(UIBezierPath(roundedRect: bounds.insetBy(dx: 3, dy: 3), cornerRadius: cornerRadius)) maskLayer.fillRule = .evenOdd maskLayer.path = bezierPath.cgPath diff --git a/Mastodon/Scene/Share/View/Button/PrimaryActionButton.swift b/Mastodon/Scene/Share/View/Button/PrimaryActionButton.swift index 326dfa12..3bda63de 100644 --- a/Mastodon/Scene/Share/View/Button/PrimaryActionButton.swift +++ b/Mastodon/Scene/Share/View/Button/PrimaryActionButton.swift @@ -21,6 +21,12 @@ class PrimaryActionButton: UIButton { private var originalButtonTitle: String? + var action: Action = .next { + didSet { + setupAppearance(action: action) + } + } + var adjustsBackgroundImageWhenUserInterfaceStyleChanges = true override init(frame: CGRect) { @@ -35,26 +41,44 @@ class PrimaryActionButton: UIButton { } +extension PrimaryActionButton { + + public enum Action { + case back + case next + } + +} + extension PrimaryActionButton { private func _init() { titleLabel?.font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 17, weight: .semibold)) setTitleColor(.white, for: .normal) - setupBackgroundAppearance() + setupAppearance(action: action) applyCornerRadius(radius: 10) } - func setupBackgroundAppearance() { - setBackgroundImage(UIImage.placeholder(color: Asset.Colors.brandBlue.color), for: .normal) - setBackgroundImage(UIImage.placeholder(color: Asset.Colors.brandBlueDarken20.color), for: .highlighted) - setBackgroundImage(UIImage.placeholder(color: Asset.Colors.disabled.color), for: .disabled) + func setupAppearance(action: Action) { + switch action { + case .back: + setTitleColor(Asset.Colors.Label.primary.color, for: .normal) + setBackgroundImage(UIImage.placeholder(color: Asset.Scene.Onboarding.navigationBackButtonBackground.color), for: .normal) + setBackgroundImage(UIImage.placeholder(color: Asset.Scene.Onboarding.navigationBackButtonBackgroundHighlighted.color), for: .highlighted) + setBackgroundImage(UIImage.placeholder(color: Asset.Colors.disabled.color), for: .disabled) + case .next: + setTitleColor(Asset.Colors.Label.primaryReverse.color, for: .normal) + setBackgroundImage(UIImage.placeholder(color: Asset.Scene.Onboarding.navigationNextButtonBackground.color), for: .normal) + setBackgroundImage(UIImage.placeholder(color: Asset.Scene.Onboarding.navigationNextButtonBackgroundHighlighted.color), for: .highlighted) + setBackgroundImage(UIImage.placeholder(color: Asset.Colors.disabled.color), for: .disabled) + } } override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) if adjustsBackgroundImageWhenUserInterfaceStyleChanges { - setupBackgroundAppearance() + setupAppearance(action: action) } } diff --git a/Mastodon/Scene/Share/View/Container/TouchBlockingView.swift b/Mastodon/Scene/Share/View/Container/TouchBlockingView.swift index b86137f1..5a151812 100644 --- a/Mastodon/Scene/Share/View/Container/TouchBlockingView.swift +++ b/Mastodon/Scene/Share/View/Container/TouchBlockingView.swift @@ -7,7 +7,7 @@ import UIKit -final class TouchBlockingView: UIView { +class TouchBlockingView: UIView { override init(frame: CGRect) { super.init(frame: frame) diff --git a/Mastodon/Scene/Share/View/Content/TimelineHeaderView.swift b/Mastodon/Scene/Share/View/Content/TimelineHeaderView.swift index 2948af4c..50518e59 100644 --- a/Mastodon/Scene/Share/View/Content/TimelineHeaderView.swift +++ b/Mastodon/Scene/Share/View/Content/TimelineHeaderView.swift @@ -126,10 +126,10 @@ struct TimelineHeaderView_Previews: PreviewProvider { static var previews: some View { Group { UIViewPreview(width: 375) { - let headerView = TimelineHeaderView() - headerView.iconImageView.image = Item.EmptyStateHeaderAttribute.Reason.blocking(name: nil).iconImage - headerView.messageLabel.text = Item.EmptyStateHeaderAttribute.Reason.blocking(name: nil).message - return headerView + let serverSectionHeaderView = TimelineHeaderView() + serverSectionHeaderView.iconImageView.image = Item.EmptyStateHeaderAttribute.Reason.blocking(name: nil).iconImage + serverSectionHeaderView.messageLabel.text = Item.EmptyStateHeaderAttribute.Reason.blocking(name: nil).message + return serverSectionHeaderView } .previewLayout(.fixed(width: 375, height: 400)) } From d36e60e2a4c78abdc93aa731980a147bdf8b850a Mon Sep 17 00:00:00 2001 From: CMK Date: Tue, 4 Jan 2022 18:30:59 +0800 Subject: [PATCH 05/12] chore: fix CI build failure issue --- .github/scripts/build.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/scripts/build.sh b/.github/scripts/build.sh index 76e65f49..f5894901 100755 --- a/.github/scripts/build.sh +++ b/.github/scripts/build.sh @@ -7,7 +7,6 @@ set -eo pipefail xcodebuild -workspace Mastodon.xcworkspace \ -scheme Mastodon \ - -disableAutomaticPackageResolution \ -destination "platform=iOS Simulator,name=iPhone SE (2nd generation)" \ clean \ - build | xcpretty \ No newline at end of file + build | xcpretty From c9417a2e172b19ba9e2d7a44757ac5a8da13e998 Mon Sep 17 00:00:00 2001 From: CMK Date: Tue, 4 Jan 2022 18:44:42 +0800 Subject: [PATCH 06/12] fix: category initial selection missing issue --- .../PickServer/MastodonPickServerViewController.swift | 1 - .../PickServer/MastodonPickServerViewModel+Diffable.swift | 6 +++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewController.swift b/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewController.swift index 1fbf204f..54e7bc6d 100644 --- a/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewController.swift +++ b/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewController.swift @@ -110,7 +110,6 @@ extension MastodonPickServerViewController { .observe(\.bounds, options: [.initial, .new]) { [weak self] navigationActionView, _ in guard let self = self else { return } let inset = navigationActionView.frame.height - print("*** \(inset) ***") self.tableView.contentInset.bottom = inset } .store(in: &observations) diff --git a/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewModel+Diffable.swift b/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewModel+Diffable.swift index 15278672..35de40b8 100644 --- a/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewModel+Diffable.swift +++ b/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewModel+Diffable.swift @@ -25,7 +25,11 @@ extension MastodonPickServerViewModel { sectionHeaderSnapshot.appendSections([.main]) sectionHeaderSnapshot.appendItems(categoryPickerItems, toSection: .main) serverSectionHeaderView.delegate = pickServerServerSectionTableHeaderViewDelegate - serverSectionHeaderView.diffableDataSource?.applySnapshot(sectionHeaderSnapshot, animated: false) + serverSectionHeaderView.diffableDataSource?.applySnapshot(sectionHeaderSnapshot, animated: false) { [weak self] in + guard let self = self else { return } + guard let indexPath = self.serverSectionHeaderView.diffableDataSource?.indexPath(for: .all) else { return } + self.serverSectionHeaderView.collectionView.selectItem(at: indexPath, animated: false, scrollPosition: .centeredHorizontally) + } // set tableView diffableDataSource = PickServerSection.tableViewDiffableDataSource( From d08cb9ece949eab27fccd82981b710d047257e33 Mon Sep 17 00:00:00 2001 From: CMK Date: Tue, 4 Jan 2022 19:28:46 +0800 Subject: [PATCH 07/12] chore: update version to .1.3.0 (89) --- AppShared/Info.plist | 4 +- CoreDataStack/Info.plist | 4 +- CoreDataStackTests/Info.plist | 4 +- Mastodon.xcodeproj/project.pbxproj | 32 ++-- .../xcschemes/xcschememanagement.plist | 8 +- .../xcshareddata/swiftpm/Package.resolved | 162 ------------------ Mastodon/Info.plist | 4 +- MastodonIntent/Info.plist | 4 +- MastodonTests/Info.plist | 4 +- MastodonUITests/Info.plist | 4 +- NotificationService/Info.plist | 4 +- ShareActionExtension/Info.plist | 4 +- 12 files changed, 38 insertions(+), 200 deletions(-) diff --git a/AppShared/Info.plist b/AppShared/Info.plist index 9fe845c6..9c87d945 100644 --- a/AppShared/Info.plist +++ b/AppShared/Info.plist @@ -15,8 +15,8 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 1.2.0 + 1.3.0 CFBundleVersion - 88 + 89 diff --git a/CoreDataStack/Info.plist b/CoreDataStack/Info.plist index 9fe845c6..9c87d945 100644 --- a/CoreDataStack/Info.plist +++ b/CoreDataStack/Info.plist @@ -15,8 +15,8 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 1.2.0 + 1.3.0 CFBundleVersion - 88 + 89 diff --git a/CoreDataStackTests/Info.plist b/CoreDataStackTests/Info.plist index 9fe845c6..9c87d945 100644 --- a/CoreDataStackTests/Info.plist +++ b/CoreDataStackTests/Info.plist @@ -15,8 +15,8 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 1.2.0 + 1.3.0 CFBundleVersion - 88 + 89 diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index 79bd6777..e707ae0f 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -4847,7 +4847,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 88; + CURRENT_PROJECT_VERSION = 89; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -4876,7 +4876,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 88; + CURRENT_PROJECT_VERSION = 89; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -4984,11 +4984,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 88; + CURRENT_PROJECT_VERSION = 89; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 88; + DYLIB_CURRENT_VERSION = 89; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AppShared/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5015,11 +5015,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 88; + CURRENT_PROJECT_VERSION = 89; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 88; + DYLIB_CURRENT_VERSION = 89; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AppShared/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5044,11 +5044,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 88; + CURRENT_PROJECT_VERSION = 89; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 88; + DYLIB_CURRENT_VERSION = 89; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = CoreDataStack/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5074,11 +5074,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 88; + CURRENT_PROJECT_VERSION = 89; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 88; + DYLIB_CURRENT_VERSION = 89; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = CoreDataStack/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5141,7 +5141,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 88; + CURRENT_PROJECT_VERSION = 89; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5166,7 +5166,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 88; + CURRENT_PROJECT_VERSION = 89; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5191,7 +5191,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 88; + CURRENT_PROJECT_VERSION = 89; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5216,7 +5216,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 88; + CURRENT_PROJECT_VERSION = 89; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5241,7 +5241,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 88; + CURRENT_PROJECT_VERSION = 89; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5265,7 +5265,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 88; + CURRENT_PROJECT_VERSION = 89; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( diff --git a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist index 8bd09ebc..601fc88a 100644 --- a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist @@ -7,12 +7,12 @@ AppShared.xcscheme_^#shared#^_ orderHint - 18 + 24 CoreDataStack.xcscheme_^#shared#^_ orderHint - 19 + 27 Mastodon - ASDK.xcscheme_^#shared#^_ @@ -102,7 +102,7 @@ MastodonIntent.xcscheme_^#shared#^_ orderHint - 21 + 26 MastodonIntents.xcscheme_^#shared#^_ @@ -122,7 +122,7 @@ ShareActionExtension.xcscheme_^#shared#^_ orderHint - 20 + 25 SuppressBuildableAutocreation diff --git a/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved index d933b5cd..3f83af78 100644 --- a/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,60 +1,6 @@ { "object": { "pins": [ - { - "package": "Alamofire", - "repositoryURL": "https://github.com/Alamofire/Alamofire.git", - "state": { - "branch": null, - "revision": "d120af1e8638c7da36c8481fd61a66c0c08dc4fc", - "version": "5.4.4" - } - }, - { - "package": "AlamofireImage", - "repositoryURL": "https://github.com/Alamofire/AlamofireImage.git", - "state": { - "branch": null, - "revision": "98cbb00ce0ec5fc8e52a5b50a6bfc08d3e5aee10", - "version": "4.2.0" - } - }, - { - "package": "AlamofireNetworkActivityIndicator", - "repositoryURL": "https://github.com/Alamofire/AlamofireNetworkActivityIndicator", - "state": { - "branch": null, - "revision": "392bed083e8d193aca16bfa684ee24e4bcff0510", - "version": "3.1.0" - } - }, - { - "package": "CommonOSLog", - "repositoryURL": "https://github.com/MainasuK/CommonOSLog", - "state": { - "branch": null, - "revision": "c121624a30698e9886efe38aebb36ff51c01b6c2", - "version": "0.1.1" - } - }, - { - "package": "DiffableDataSources", - "repositoryURL": "https://github.com/MainasuK/DiffableDataSources.git", - "state": { - "branch": "feature/async-display-table", - "revision": "73393a97690959d24387c95594c045c62d9c47cf", - "version": null - } - }, - { - "package": "DifferenceKit", - "repositoryURL": "https://github.com/ra1028/DifferenceKit.git", - "state": { - "branch": null, - "revision": "62745d7780deef4a023a792a1f8f763ec7bf9705", - "version": "1.2.0" - } - }, { "package": "FLAnimatedImage", "repositoryURL": "https://github.com/Flipboard/FLAnimatedImage", @@ -64,42 +10,6 @@ "version": "1.0.16" } }, - { - "package": "FPSIndicator", - "repositoryURL": "https://github.com/MainasuK/FPSIndicator.git", - "state": { - "branch": null, - "revision": "e4a5067ccd5293b024c767f09e51056afd4a4796", - "version": "1.1.0" - } - }, - { - "package": "Fuzi", - "repositoryURL": "https://github.com/cezheng/Fuzi.git", - "state": { - "branch": null, - "revision": "f08c8323da21e985f3772610753bcfc652c2103f", - "version": "3.1.3" - } - }, - { - "package": "KeychainAccess", - "repositoryURL": "https://github.com/kishikawakatsumi/KeychainAccess.git", - "state": { - "branch": null, - "revision": "84e546727d66f1adc5439debad16270d0fdd04e7", - "version": "4.2.2" - } - }, - { - "package": "MetaTextKit", - "repositoryURL": "https://github.com/TwidereProject/MetaTextKit.git", - "state": { - "branch": null, - "revision": "7af4182f64329440a4656f2cba307cb5848e496a", - "version": "2.1.2" - } - }, { "package": "Nuke", "repositoryURL": "https://github.com/kean/Nuke.git", @@ -118,42 +28,6 @@ "version": "8.0.0" } }, - { - "package": "Pageboy", - "repositoryURL": "https://github.com/uias/Pageboy", - "state": { - "branch": null, - "revision": "34ecb6e7c4e0e07494960ab2f7cc9a02293915a6", - "version": "3.6.2" - } - }, - { - "package": "PanModal", - "repositoryURL": "https://github.com/slackhq/PanModal.git", - "state": { - "branch": null, - "revision": "b012aecb6b67a8e46369227f893c12544846613f", - "version": "1.2.7" - } - }, - { - "package": "SDWebImage", - "repositoryURL": "https://github.com/SDWebImage/SDWebImage.git", - "state": { - "branch": null, - "revision": "a72df4849408da7e5d3c1b586797b7c601c41d1b", - "version": "5.12.1" - } - }, - { - "package": "swift-collections", - "repositoryURL": "https://github.com/apple/swift-collections.git", - "state": { - "branch": null, - "revision": "9d8719c8bebdc79740b6969c912ac706eb721d7a", - "version": "0.0.7" - } - }, { "package": "swift-nio", "repositoryURL": "https://github.com/apple/swift-nio.git", @@ -189,42 +63,6 @@ "revision": "b3dcd7dbd0d488e1a7077cb33b00f2083e382f07", "version": "5.0.1" } - }, - { - "package": "Tabman", - "repositoryURL": "https://github.com/uias/Tabman", - "state": { - "branch": null, - "revision": "f43489cdd743ba7ad86a422ebb5fcbf34e333df4", - "version": "2.11.1" - } - }, - { - "package": "ThirdPartyMailer", - "repositoryURL": "https://github.com/vtourraine/ThirdPartyMailer.git", - "state": { - "branch": null, - "revision": "779da6ce0793b461ccbbac2804755c1e29b6fa63", - "version": "1.8.0" - } - }, - { - "package": "TOCropViewController", - "repositoryURL": "https://github.com/TimOliver/TOCropViewController.git", - "state": { - "branch": null, - "revision": "dad97167bf1be16aeecd109130900995dd01c515", - "version": "2.6.0" - } - }, - { - "package": "UITextView+Placeholder", - "repositoryURL": "https://github.com/MainasuK/UITextView-Placeholder", - "state": { - "branch": null, - "revision": "20f513ded04a040cdf5467f0891849b1763ede3b", - "version": "1.4.1" - } } ] }, diff --git a/Mastodon/Info.plist b/Mastodon/Info.plist index affa5b05..e96be0cd 100644 --- a/Mastodon/Info.plist +++ b/Mastodon/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 1.2.0 + 1.3.0 CFBundleURLTypes @@ -30,7 +30,7 @@ CFBundleVersion - 88 + 89 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/MastodonIntent/Info.plist b/MastodonIntent/Info.plist index 8ac3d165..e9a180d7 100644 --- a/MastodonIntent/Info.plist +++ b/MastodonIntent/Info.plist @@ -17,9 +17,9 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 1.2.0 + 1.3.0 CFBundleVersion - 88 + 89 NSExtension NSExtensionAttributes diff --git a/MastodonTests/Info.plist b/MastodonTests/Info.plist index 9fe845c6..9c87d945 100644 --- a/MastodonTests/Info.plist +++ b/MastodonTests/Info.plist @@ -15,8 +15,8 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 1.2.0 + 1.3.0 CFBundleVersion - 88 + 89 diff --git a/MastodonUITests/Info.plist b/MastodonUITests/Info.plist index 9fe845c6..9c87d945 100644 --- a/MastodonUITests/Info.plist +++ b/MastodonUITests/Info.plist @@ -15,8 +15,8 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 1.2.0 + 1.3.0 CFBundleVersion - 88 + 89 diff --git a/NotificationService/Info.plist b/NotificationService/Info.plist index 8e14f3a2..fe988a2f 100644 --- a/NotificationService/Info.plist +++ b/NotificationService/Info.plist @@ -17,9 +17,9 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 1.2.0 + 1.3.0 CFBundleVersion - 88 + 89 NSExtension NSExtensionPointIdentifier diff --git a/ShareActionExtension/Info.plist b/ShareActionExtension/Info.plist index 1b302547..a6178ef8 100644 --- a/ShareActionExtension/Info.plist +++ b/ShareActionExtension/Info.plist @@ -17,9 +17,9 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 1.2.0 + 1.3.0 CFBundleVersion - 88 + 89 NSExtension NSExtensionAttributes From a7a36d503ab916d9f2be155b300d269ace8b2b5e Mon Sep 17 00:00:00 2001 From: CMK Date: Wed, 5 Jan 2022 15:11:35 +0800 Subject: [PATCH 08/12] feat: update server rule scene UI --- Mastodon.xcodeproj/project.pbxproj | 146 +++++--- .../xcshareddata/swiftpm/Package.resolved | 153 +++++++++ .../SelectedAccountItem.swift | 0 .../SelectedAccountSection.swift | 0 .../{Item => Compose}/AutoCompleteItem.swift | 0 .../Compose/AutoCompleteSection.swift | 0 .../ComposeStatusAttachmentItem.swift | 0 .../ComposeStatusAttachmentSection.swift | 0 .../{Item => Compose}/ComposeStatusItem.swift | 0 .../ComposeStatusPollItem.swift | 0 .../Compose/ComposeStatusPollSection.swift | 0 .../Compose/ComposeStatusSection.swift | 0 .../CustomEmojiPickerItem.swift | 0 .../Compose/CustomEmojiPickerSection.swift | 0 .../NotificationItem.swift | 0 .../NotificationSection.swift | 0 .../CategoryPickerItem.swift | 0 .../Onboarding/CategoryPickerSection.swift | 0 .../{Item => Onboarding}/PickServerItem.swift | 0 .../Onboarding/PickServerSection.swift | 2 +- .../Diffiable/Onboarding/ServerRuleItem.swift | 21 ++ .../Onboarding/ServerRuleSection.swift | 34 ++ .../Diffiable/{Item => Poll}/PollItem.swift | 0 .../Status => Poll}/PollSection.swift | 0 .../{Item => Profile}/ProfileFieldItem.swift | 0 .../ProfileFieldSection.swift | 0 .../Search/RecommendAccountSection.swift | 0 .../Search/RecommendHashTagSection.swift | 0 .../{Item => Search}/SearchHistoryItem.swift | 0 .../Search/SearchHistorySection.swift | 0 .../{Item => Search}/SearchResultItem.swift | 0 .../Search/SearchResultSection.swift | 0 .../{Item => Settings}/SettingsItem.swift | 0 .../SettingsSection.swift | 0 .../Diffiable/{Item => Status}/Item.swift | 0 .../{Section => }/Status/ReportSection.swift | 0 .../{Section => }/Status/StatusSection.swift | 0 .../Diffiable/{Item => User}/UserItem.swift | 0 .../{Section => User}/UserSection.swift | 0 .../MastodonPickServerViewController.swift | 8 +- .../MastodonServerRulesViewController.swift | 312 +++++------------- ...astodonServerRulesViewModel+Diffable.swift | 26 ++ .../MastodonServerRulesViewModel.swift | 3 + .../ServerRulesTableViewCell.swift | 83 +++++ .../Share/NavigationActionView.swift | 38 ++- .../OnboardingHeadlineTableViewCell.swift} | 14 +- .../OnboardingViewControllerAppearance.swift | 16 + .../Welcome/WelcomeViewController.swift | 23 +- .../View/Button/PrimaryActionButton.swift | 11 +- .../Sources/MastodonExtension}/CALayer.swift | 7 +- .../Sources/MastodonExtension/UIImage.swift | 20 +- .../Entity/Mastodon+Entity+Instance.swift | 2 +- .../Container/ShadowBackgroundContainer.swift | 48 +++ 53 files changed, 652 insertions(+), 315 deletions(-) rename Mastodon/Diffiable/{Item => Account}/SelectedAccountItem.swift (100%) rename Mastodon/Diffiable/{Section => Account}/SelectedAccountSection.swift (100%) rename Mastodon/Diffiable/{Item => Compose}/AutoCompleteItem.swift (100%) rename Mastodon/Diffiable/{Section => }/Compose/AutoCompleteSection.swift (100%) rename Mastodon/Diffiable/{Item => Compose}/ComposeStatusAttachmentItem.swift (100%) rename Mastodon/Diffiable/{Section => }/Compose/ComposeStatusAttachmentSection.swift (100%) rename Mastodon/Diffiable/{Item => Compose}/ComposeStatusItem.swift (100%) rename Mastodon/Diffiable/{Item => Compose}/ComposeStatusPollItem.swift (100%) rename Mastodon/Diffiable/{Section => }/Compose/ComposeStatusPollSection.swift (100%) rename Mastodon/Diffiable/{Section => }/Compose/ComposeStatusSection.swift (100%) rename Mastodon/Diffiable/{Item => Compose}/CustomEmojiPickerItem.swift (100%) rename Mastodon/Diffiable/{Section => }/Compose/CustomEmojiPickerSection.swift (100%) rename Mastodon/Diffiable/{Item => Notification}/NotificationItem.swift (100%) rename Mastodon/Diffiable/{Section/Status => Notification}/NotificationSection.swift (100%) rename Mastodon/Diffiable/{Item => Onboarding}/CategoryPickerItem.swift (100%) rename Mastodon/Diffiable/{Section => }/Onboarding/CategoryPickerSection.swift (100%) rename Mastodon/Diffiable/{Item => Onboarding}/PickServerItem.swift (100%) rename Mastodon/Diffiable/{Section => }/Onboarding/PickServerSection.swift (98%) create mode 100644 Mastodon/Diffiable/Onboarding/ServerRuleItem.swift create mode 100644 Mastodon/Diffiable/Onboarding/ServerRuleSection.swift rename Mastodon/Diffiable/{Item => Poll}/PollItem.swift (100%) rename Mastodon/Diffiable/{Section/Status => Poll}/PollSection.swift (100%) rename Mastodon/Diffiable/{Item => Profile}/ProfileFieldItem.swift (100%) rename Mastodon/Diffiable/{Section => Profile}/ProfileFieldSection.swift (100%) rename Mastodon/Diffiable/{Section => }/Search/RecommendAccountSection.swift (100%) rename Mastodon/Diffiable/{Section => }/Search/RecommendHashTagSection.swift (100%) rename Mastodon/Diffiable/{Item => Search}/SearchHistoryItem.swift (100%) rename Mastodon/Diffiable/{Section => }/Search/SearchHistorySection.swift (100%) rename Mastodon/Diffiable/{Item => Search}/SearchResultItem.swift (100%) rename Mastodon/Diffiable/{Section => }/Search/SearchResultSection.swift (100%) rename Mastodon/Diffiable/{Item => Settings}/SettingsItem.swift (100%) rename Mastodon/Diffiable/{Section => Settings}/SettingsSection.swift (100%) rename Mastodon/Diffiable/{Item => Status}/Item.swift (100%) rename Mastodon/Diffiable/{Section => }/Status/ReportSection.swift (100%) rename Mastodon/Diffiable/{Section => }/Status/StatusSection.swift (100%) rename Mastodon/Diffiable/{Item => User}/UserItem.swift (100%) rename Mastodon/Diffiable/{Section => User}/UserSection.swift (100%) create mode 100644 Mastodon/Scene/Onboarding/ServerRules/MastodonServerRulesViewModel+Diffable.swift create mode 100644 Mastodon/Scene/Onboarding/ServerRules/ServerRulesTableViewCell.swift rename Mastodon/Scene/Onboarding/{PickServer/TableViewCell/PickServerTitleCell.swift => Share/OnboardingHeadlineTableViewCell.swift} (79%) rename {Mastodon/Extension => MastodonSDK/Sources/MastodonExtension}/CALayer.swift (95%) create mode 100644 MastodonSDK/Sources/MastodonUI/View/Container/ShadowBackgroundContainer.swift diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index e707ae0f..3061b6e4 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -22,7 +22,7 @@ 0FAA101C25E10E760017CCDE /* UIFont.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0FAA101B25E10E760017CCDE /* UIFont.swift */; }; 0FAA102725E1126A0017CCDE /* MastodonPickServerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0FAA102625E1126A0017CCDE /* MastodonPickServerViewController.swift */; }; 0FB3D2F725E4C24D00AAD544 /* MastodonPickServerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0FB3D2F625E4C24D00AAD544 /* MastodonPickServerViewModel.swift */; }; - 0FB3D2FE25E4CB6400AAD544 /* PickServerTitleCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0FB3D2FD25E4CB6400AAD544 /* PickServerTitleCell.swift */; }; + 0FB3D2FE25E4CB6400AAD544 /* OnboardingHeadlineTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0FB3D2FD25E4CB6400AAD544 /* OnboardingHeadlineTableViewCell.swift */; }; 0FB3D30825E524C600AAD544 /* PickServerCategoriesCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0FB3D30725E524C600AAD544 /* PickServerCategoriesCell.swift */; }; 0FB3D30F25E525CD00AAD544 /* PickServerCategoryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0FB3D30E25E525CD00AAD544 /* PickServerCategoryView.swift */; }; 0FB3D31E25E534C700AAD544 /* PickServerCategoryCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0FB3D31D25E534C700AAD544 /* PickServerCategoryCollectionViewCell.swift */; }; @@ -195,6 +195,10 @@ DB0617ED277F02C50030EE79 /* OnboardingNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0617EC277F02C50030EE79 /* OnboardingNavigationController.swift */; }; DB0617EF277F12720030EE79 /* NavigationActionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0617EE277F12720030EE79 /* NavigationActionView.swift */; }; DB0617F1278413D00030EE79 /* PickServerServerSectionTableHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0617F0278413D00030EE79 /* PickServerServerSectionTableHeaderView.swift */; }; + DB0617F527855AB90030EE79 /* ServerRuleSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0617F427855AB90030EE79 /* ServerRuleSection.swift */; }; + DB0617FD27855BFE0030EE79 /* ServerRuleItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0617FC27855BFE0030EE79 /* ServerRuleItem.swift */; }; + DB0617FF27855D6C0030EE79 /* MastodonServerRulesViewModel+Diffable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0617FE27855D6C0030EE79 /* MastodonServerRulesViewModel+Diffable.swift */; }; + DB0618012785732C0030EE79 /* ServerRulesTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0618002785732C0030EE79 /* ServerRulesTableViewCell.swift */; }; DB084B5725CBC56C00F898ED /* Status.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB084B5625CBC56C00F898ED /* Status.swift */; }; DB0AC6FC25CD02E600D75117 /* APIService+Instance.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0AC6FB25CD02E600D75117 /* APIService+Instance.swift */; }; DB0C946526A6FD4D0088FB11 /* AlamofireImage in Frameworks */ = {isa = PBXBuildFile; productRef = DB0C946426A6FD4D0088FB11 /* AlamofireImage */; }; @@ -244,7 +248,6 @@ DB427DE225BAA00100D1B89D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DB427DE025BAA00100D1B89D /* LaunchScreen.storyboard */; }; DB427DED25BAA00100D1B89D /* MastodonTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB427DEC25BAA00100D1B89D /* MastodonTests.swift */; }; DB427DF825BAA00100D1B89D /* MastodonUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB427DF725BAA00100D1B89D /* MastodonUITests.swift */; }; - DB44384F25E8C1FA008912A2 /* CALayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB44384E25E8C1FA008912A2 /* CALayer.swift */; }; DB443CD42694627B00159B29 /* AppearanceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB443CD32694627B00159B29 /* AppearanceView.swift */; }; DB44767B260B3B8C00B66B82 /* CustomEmojiPickerInputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB44767A260B3B8C00B66B82 /* CustomEmojiPickerInputView.swift */; }; DB447681260B3ED600B66B82 /* CustomEmojiPickerSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB447680260B3ED600B66B82 /* CustomEmojiPickerSection.swift */; }; @@ -782,7 +785,7 @@ 0FAA101B25E10E760017CCDE /* UIFont.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIFont.swift; sourceTree = ""; }; 0FAA102625E1126A0017CCDE /* MastodonPickServerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonPickServerViewController.swift; sourceTree = ""; }; 0FB3D2F625E4C24D00AAD544 /* MastodonPickServerViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonPickServerViewModel.swift; sourceTree = ""; }; - 0FB3D2FD25E4CB6400AAD544 /* PickServerTitleCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PickServerTitleCell.swift; sourceTree = ""; }; + 0FB3D2FD25E4CB6400AAD544 /* OnboardingHeadlineTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingHeadlineTableViewCell.swift; sourceTree = ""; }; 0FB3D30725E524C600AAD544 /* PickServerCategoriesCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PickServerCategoriesCell.swift; sourceTree = ""; }; 0FB3D30E25E525CD00AAD544 /* PickServerCategoryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PickServerCategoryView.swift; sourceTree = ""; }; 0FB3D31D25E534C700AAD544 /* PickServerCategoryCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PickServerCategoryCollectionViewCell.swift; sourceTree = ""; }; @@ -977,6 +980,10 @@ DB0617EC277F02C50030EE79 /* OnboardingNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingNavigationController.swift; sourceTree = ""; }; DB0617EE277F12720030EE79 /* NavigationActionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationActionView.swift; sourceTree = ""; }; DB0617F0278413D00030EE79 /* PickServerServerSectionTableHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PickServerServerSectionTableHeaderView.swift; sourceTree = ""; }; + DB0617F427855AB90030EE79 /* ServerRuleSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerRuleSection.swift; sourceTree = ""; }; + DB0617FC27855BFE0030EE79 /* ServerRuleItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerRuleItem.swift; sourceTree = ""; }; + DB0617FE27855D6C0030EE79 /* MastodonServerRulesViewModel+Diffable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MastodonServerRulesViewModel+Diffable.swift"; sourceTree = ""; }; + DB0618002785732C0030EE79 /* ServerRulesTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerRulesTableViewCell.swift; sourceTree = ""; }; DB084B5625CBC56C00F898ED /* Status.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Status.swift; sourceTree = ""; }; DB0AC6FB25CD02E600D75117 /* APIService+Instance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+Instance.swift"; sourceTree = ""; }; DB0C946A26A700AB0088FB11 /* MastodonUser+Property.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MastodonUser+Property.swift"; sourceTree = ""; }; @@ -1033,7 +1040,6 @@ DB427DF325BAA00100D1B89D /* MastodonUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MastodonUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; DB427DF725BAA00100D1B89D /* MastodonUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonUITests.swift; sourceTree = ""; }; DB427DF925BAA00100D1B89D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - DB44384E25E8C1FA008912A2 /* CALayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CALayer.swift; sourceTree = ""; }; DB443CD32694627B00159B29 /* AppearanceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppearanceView.swift; sourceTree = ""; }; DB44767A260B3B8C00B66B82 /* CustomEmojiPickerInputView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomEmojiPickerInputView.swift; sourceTree = ""; }; DB447680260B3ED600B66B82 /* CustomEmojiPickerSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomEmojiPickerSection.swift; sourceTree = ""; }; @@ -1598,7 +1604,6 @@ 0FB3D2FC25E4CB4B00AAD544 /* TableViewCell */ = { isa = PBXGroup; children = ( - 0FB3D2FD25E4CB6400AAD544 /* PickServerTitleCell.swift */, 0FB3D33725E6401400AAD544 /* PickServerCell.swift */, DB0F814F264D1E2500F2A12B /* PickServerLoaderTableViewCell.swift */, ); @@ -1862,28 +1867,21 @@ 2D76319C25C151DE00929FB9 /* Diffiable */ = { isa = PBXGroup; children = ( - 2D76319D25C151F600929FB9 /* Section */, - 2D7631B125C159E700929FB9 /* Item */, + DB4F097826A039B400D62E92 /* Onboarding */, + DB0617FB27855B740030EE79 /* Account */, + DB0617F827855B170030EE79 /* User */, + DB0617F927855B460030EE79 /* Profile */, + DB4F097926A039C400D62E92 /* Status */, + DB0617F627855AF30030EE79 /* Poll */, + DB4F097626A0398000D62E92 /* Compose */, + DB0617F727855B010030EE79 /* Notification */, + DB4F097726A039A200D62E92 /* Search */, + DB0617FA27855B660030EE79 /* Settings */, DBCBED2226132E1D00B49291 /* FetchedResultsController */, ); path = Diffiable; sourceTree = ""; }; - 2D76319D25C151F600929FB9 /* Section */ = { - isa = PBXGroup; - children = ( - DB4F097926A039C400D62E92 /* Status */, - DB4F097826A039B400D62E92 /* Onboarding */, - DB4F097726A039A200D62E92 /* Search */, - DB4F097626A0398000D62E92 /* Compose */, - 2D4AD8A126316CD200613EFC /* SelectedAccountSection.swift */, - DB6D9F7C26358ED4008423CD /* SettingsSection.swift */, - DBA94433265CBB5300C537E1 /* ProfileFieldSection.swift */, - DB6B74FB272FF55800C70B6E /* UserSection.swift */, - ); - path = Section; - sourceTree = ""; - }; 2D7631A425C1532200929FB9 /* Share */ = { isa = PBXGroup; children = ( @@ -1930,29 +1928,6 @@ path = TableviewCell; sourceTree = ""; }; - 2D7631B125C159E700929FB9 /* Item */ = { - isa = PBXGroup; - children = ( - 2D7631B225C159F700929FB9 /* Item.swift */, - DB6B74FD272FF59000C70B6E /* UserItem.swift */, - 2D198642261BF09500F0B013 /* SearchResultItem.swift */, - DB4F097C26A03A5B00D62E92 /* SearchHistoryItem.swift */, - 2D4AD8A726316D3500613EFC /* SelectedAccountItem.swift */, - 2D7867182625B77500211898 /* NotificationItem.swift */, - DB4481CB25EE2AFE00BEFB67 /* PollItem.swift */, - DB1E347725F519300079D7DF /* PickServerItem.swift */, - DB1FD45925F27898004CFCFC /* CategoryPickerItem.swift */, - DB66729B25F9F91F00D60309 /* ComposeStatusItem.swift */, - DB3667A0268ABB2E0027D07F /* ComposeStatusAttachmentItem.swift */, - DB3667A7268AE2900027D07F /* ComposeStatusPollItem.swift */, - DB44768A260B3F2100B66B82 /* CustomEmojiPickerItem.swift */, - DB6D9F8326358EEC008423CD /* SettingsItem.swift */, - DBBF1DCA2652539E00E5B703 /* AutoCompleteItem.swift */, - DBA94435265CBB7400C537E1 /* ProfileFieldItem.swift */, - ); - path = Item; - sourceTree = ""; - }; 2DA504672601ADBA008F4E6C /* Decoration */ = { isa = PBXGroup; children = ( @@ -2109,6 +2084,60 @@ path = Deprecated; sourceTree = ""; }; + DB0617F627855AF30030EE79 /* Poll */ = { + isa = PBXGroup; + children = ( + DB4481C525EE2ADA00BEFB67 /* PollSection.swift */, + DB4481CB25EE2AFE00BEFB67 /* PollItem.swift */, + ); + path = Poll; + sourceTree = ""; + }; + DB0617F727855B010030EE79 /* Notification */ = { + isa = PBXGroup; + children = ( + 2D35237926256D920031AF25 /* NotificationSection.swift */, + 2D7867182625B77500211898 /* NotificationItem.swift */, + ); + path = Notification; + sourceTree = ""; + }; + DB0617F827855B170030EE79 /* User */ = { + isa = PBXGroup; + children = ( + DB6B74FB272FF55800C70B6E /* UserSection.swift */, + DB6B74FD272FF59000C70B6E /* UserItem.swift */, + ); + path = User; + sourceTree = ""; + }; + DB0617F927855B460030EE79 /* Profile */ = { + isa = PBXGroup; + children = ( + DBA94433265CBB5300C537E1 /* ProfileFieldSection.swift */, + DBA94435265CBB7400C537E1 /* ProfileFieldItem.swift */, + ); + path = Profile; + sourceTree = ""; + }; + DB0617FA27855B660030EE79 /* Settings */ = { + isa = PBXGroup; + children = ( + DB6D9F7C26358ED4008423CD /* SettingsSection.swift */, + DB6D9F8326358EEC008423CD /* SettingsItem.swift */, + ); + path = Settings; + sourceTree = ""; + }; + DB0617FB27855B740030EE79 /* Account */ = { + isa = PBXGroup; + children = ( + 2D4AD8A126316CD200613EFC /* SelectedAccountSection.swift */, + 2D4AD8A726316D3500613EFC /* SelectedAccountItem.swift */, + ); + path = Account; + sourceTree = ""; + }; DB084B5125CBC56300F898ED /* CoreDataStack */ = { isa = PBXGroup; children = ( @@ -2360,10 +2389,15 @@ isa = PBXGroup; children = ( DB66729525F9F91600D60309 /* ComposeStatusSection.swift */, + DB66729B25F9F91F00D60309 /* ComposeStatusItem.swift */, DB36679E268ABAF20027D07F /* ComposeStatusAttachmentSection.swift */, + DB3667A0268ABB2E0027D07F /* ComposeStatusAttachmentItem.swift */, DB3667A5268AE2620027D07F /* ComposeStatusPollSection.swift */, + DB3667A7268AE2900027D07F /* ComposeStatusPollItem.swift */, DB447680260B3ED600B66B82 /* CustomEmojiPickerSection.swift */, + DB44768A260B3F2100B66B82 /* CustomEmojiPickerItem.swift */, DBBF1DC82652538500E5B703 /* AutoCompleteSection.swift */, + DBBF1DCA2652539E00E5B703 /* AutoCompleteItem.swift */, ); path = Compose; sourceTree = ""; @@ -2374,7 +2408,9 @@ 2DE0FAC02615F04D00CDF649 /* RecommendHashTagSection.swift */, 2DE0FACD2615F7AD00CDF649 /* RecommendAccountSection.swift */, 2D198648261C0B8500F0B013 /* SearchResultSection.swift */, + 2D198642261BF09500F0B013 /* SearchResultItem.swift */, DB4F097A26A039FF00D62E92 /* SearchHistorySection.swift */, + DB4F097C26A03A5B00D62E92 /* SearchHistoryItem.swift */, ); path = Search; sourceTree = ""; @@ -2383,7 +2419,11 @@ isa = PBXGroup; children = ( DB1FD44325F26CCC004CFCFC /* PickServerSection.swift */, + DB1E347725F519300079D7DF /* PickServerItem.swift */, DB1E346725F518E20079D7DF /* CategoryPickerSection.swift */, + DB1FD45925F27898004CFCFC /* CategoryPickerItem.swift */, + DB0617F427855AB90030EE79 /* ServerRuleSection.swift */, + DB0617FC27855BFE0030EE79 /* ServerRuleItem.swift */, ); path = Onboarding; sourceTree = ""; @@ -2392,8 +2432,7 @@ isa = PBXGroup; children = ( 2D76319E25C1521200929FB9 /* StatusSection.swift */, - DB4481C525EE2ADA00BEFB67 /* PollSection.swift */, - 2D35237926256D920031AF25 /* NotificationSection.swift */, + 2D7631B225C159F700929FB9 /* Item.swift */, 5BB04FF4262F0E6D0043BFF6 /* ReportSection.swift */, ); path = Status; @@ -2533,10 +2572,11 @@ DB68A03825E900CC00CFDF14 /* Share */ = { isa = PBXGroup; children = ( - 2D82B9FE25E7863200E36F0F /* OnboardingViewControllerAppearance.swift */, DB2F073325E8ECF000957B2D /* AuthenticationViewModel.swift */, DB029E94266A20430062874E /* MastodonAuthenticationController.swift */, + 2D82B9FE25E7863200E36F0F /* OnboardingViewControllerAppearance.swift */, DB0617EC277F02C50030EE79 /* OnboardingNavigationController.swift */, + 0FB3D2FD25E4CB6400AAD544 /* OnboardingHeadlineTableViewCell.swift */, DB0617EE277F12720030EE79 /* NavigationActionView.swift */, ); path = Share; @@ -2595,6 +2635,8 @@ children = ( DB72601B25E36A2100235243 /* MastodonServerRulesViewController.swift */, DB72602625E36A6F00235243 /* MastodonServerRulesViewModel.swift */, + DB0617FE27855D6C0030EE79 /* MastodonServerRulesViewModel+Diffable.swift */, + DB0618002785732C0030EE79 /* ServerRulesTableViewCell.swift */, ); path = ServerRules; sourceTree = ""; @@ -2797,7 +2839,6 @@ 2DF123A625C3B0210020F248 /* ActiveLabel.swift */, 5DF1056325F887CB00D6C0D4 /* AVPlayer.swift */, 0F20223826146553000C64BF /* Array.swift */, - DB44384E25E8C1FA008912A2 /* CALayer.swift */, 2D206B8525F5FB0900143C56 /* Double.swift */, DB97131E2666078B00BD1E90 /* Date.swift */, DBB3BA2926A81C020004F2D4 /* FLAnimatedImageView.swift */, @@ -3954,6 +3995,7 @@ DB68A06325E905E000CFDF14 /* UIApplication.swift in Sources */, DB02CDAB26256A9500D0A2AF /* ThreadReplyLoaderTableViewCell.swift in Sources */, DB63BE7F268DD1070011D3F9 /* NotificationViewController+StatusProvider.swift in Sources */, + DB0617FF27855D6C0030EE79 /* MastodonServerRulesViewModel+Diffable.swift in Sources */, DBB5255E2611F07A002F1F29 /* ProfileViewModel.swift in Sources */, 2D8434FB25FF46B300EECE90 /* HomeTimelineNavigationBarTitleView.swift in Sources */, 0F1E2D0B2615C39400C38565 /* DoubleTitleLabelNavigationBarTitleView.swift in Sources */, @@ -3990,6 +4032,7 @@ DB789A0B25F9F2950071ACA0 /* ComposeViewController.swift in Sources */, DB938F0926240F3C00E5B6C1 /* RemoteThreadViewModel.swift in Sources */, DB0617ED277F02C50030EE79 /* OnboardingNavigationController.swift in Sources */, + DB0617F527855AB90030EE79 /* ServerRuleSection.swift in Sources */, DBBC24AE26A53DC100398BB9 /* ReplicaStatusView.swift in Sources */, DB75BF1E263C1C1B00EDBF1F /* CustomScheduler.swift in Sources */, 0FAA102725E1126A0017CCDE /* MastodonPickServerViewController.swift in Sources */, @@ -4101,7 +4144,7 @@ DB71FD3C25F8A1C500512AE1 /* APIService+Persist+PersistCache.swift in Sources */, 2DA6055125F74407006356F9 /* AudioContainerViewModel.swift in Sources */, DB4F0968269ED8AD00D62E92 /* SearchHistoryTableHeaderView.swift in Sources */, - 0FB3D2FE25E4CB6400AAD544 /* PickServerTitleCell.swift in Sources */, + 0FB3D2FE25E4CB6400AAD544 /* OnboardingHeadlineTableViewCell.swift in Sources */, 5DA732CC2629CEF500A92342 /* UIView+Remove.swift in Sources */, DBAEDE5C267A058D00D25FF5 /* BlurhashImageCacheService.swift in Sources */, 2D38F1DF25CD46A400561493 /* HomeTimelineViewController+Provider.swift in Sources */, @@ -4146,6 +4189,7 @@ 2D34D9D126148D9E0081BFC0 /* APIService+Recommend.swift in Sources */, DBB525562611EDCA002F1F29 /* UserTimelineViewModel.swift in Sources */, 2D42FF7E25C82218004A627A /* ActionToolBarContainer.swift in Sources */, + DB0618012785732C0030EE79 /* ServerRulesTableViewCell.swift in Sources */, DB221B16260C395900AEFE46 /* CustomEmojiPickerInputViewModel.swift in Sources */, DB0617EF277F12720030EE79 /* NavigationActionView.swift in Sources */, DB1FD43625F26899004CFCFC /* MastodonPickServerViewModel+LoadIndexedServerState.swift in Sources */, @@ -4216,7 +4260,6 @@ DB6180F826391D660018D199 /* MediaPreviewingViewController.swift in Sources */, DB0140CF25C42AEE00F9F3CF /* OSLog.swift in Sources */, DB6B75022730060700C70B6E /* UserProviderFacade+UITableViewDelegate.swift in Sources */, - DB44384F25E8C1FA008912A2 /* CALayer.swift in Sources */, 2D34D9CB261489930081BFC0 /* SearchViewController+Recommend.swift in Sources */, DB71C7CB271D5A0300BE3819 /* LineChartView.swift in Sources */, DB938F1526241FDF00E5B6C1 /* APIService+Thread.swift in Sources */, @@ -4358,6 +4401,7 @@ DBAFB7352645463500371D5F /* Emojis.swift in Sources */, DBCCC71E25F73297007E1AB6 /* APIService+Reblog.swift in Sources */, DBE3CE13261D7D4200430CC6 /* StatusTableViewControllerAspect.swift in Sources */, + DB0617FD27855BFE0030EE79 /* ServerRuleItem.swift in Sources */, 5BB04FD5262E7AFF0043BFF6 /* ReportViewController.swift in Sources */, DBAE3F942616E28B004B8251 /* APIService+Follow.swift in Sources */, ); diff --git a/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved index 3f83af78..e52bb1d9 100644 --- a/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,6 +1,60 @@ { "object": { "pins": [ + { + "package": "Alamofire", + "repositoryURL": "https://github.com/Alamofire/Alamofire.git", + "state": { + "branch": null, + "revision": "f82c23a8a7ef8dc1a49a8bfc6a96883e79121864", + "version": "5.5.0" + } + }, + { + "package": "AlamofireImage", + "repositoryURL": "https://github.com/Alamofire/AlamofireImage.git", + "state": { + "branch": null, + "revision": "98cbb00ce0ec5fc8e52a5b50a6bfc08d3e5aee10", + "version": "4.2.0" + } + }, + { + "package": "AlamofireNetworkActivityIndicator", + "repositoryURL": "https://github.com/Alamofire/AlamofireNetworkActivityIndicator", + "state": { + "branch": null, + "revision": "392bed083e8d193aca16bfa684ee24e4bcff0510", + "version": "3.1.0" + } + }, + { + "package": "CommonOSLog", + "repositoryURL": "https://github.com/MainasuK/CommonOSLog", + "state": { + "branch": null, + "revision": "c121624a30698e9886efe38aebb36ff51c01b6c2", + "version": "0.1.1" + } + }, + { + "package": "DiffableDataSources", + "repositoryURL": "https://github.com/MainasuK/DiffableDataSources.git", + "state": { + "branch": "feature/async-display-table", + "revision": "73393a97690959d24387c95594c045c62d9c47cf", + "version": null + } + }, + { + "package": "DifferenceKit", + "repositoryURL": "https://github.com/ra1028/DifferenceKit.git", + "state": { + "branch": null, + "revision": "62745d7780deef4a023a792a1f8f763ec7bf9705", + "version": "1.2.0" + } + }, { "package": "FLAnimatedImage", "repositoryURL": "https://github.com/Flipboard/FLAnimatedImage", @@ -10,6 +64,42 @@ "version": "1.0.16" } }, + { + "package": "FPSIndicator", + "repositoryURL": "https://github.com/MainasuK/FPSIndicator.git", + "state": { + "branch": null, + "revision": "e4a5067ccd5293b024c767f09e51056afd4a4796", + "version": "1.1.0" + } + }, + { + "package": "Fuzi", + "repositoryURL": "https://github.com/cezheng/Fuzi.git", + "state": { + "branch": null, + "revision": "f08c8323da21e985f3772610753bcfc652c2103f", + "version": "3.1.3" + } + }, + { + "package": "KeychainAccess", + "repositoryURL": "https://github.com/kishikawakatsumi/KeychainAccess.git", + "state": { + "branch": null, + "revision": "84e546727d66f1adc5439debad16270d0fdd04e7", + "version": "4.2.2" + } + }, + { + "package": "MetaTextKit", + "repositoryURL": "https://github.com/TwidereProject/MetaTextKit.git", + "state": { + "branch": null, + "revision": "7af4182f64329440a4656f2cba307cb5848e496a", + "version": "2.1.2" + } + }, { "package": "Nuke", "repositoryURL": "https://github.com/kean/Nuke.git", @@ -28,6 +118,42 @@ "version": "8.0.0" } }, + { + "package": "Pageboy", + "repositoryURL": "https://github.com/uias/Pageboy", + "state": { + "branch": null, + "revision": "34ecb6e7c4e0e07494960ab2f7cc9a02293915a6", + "version": "3.6.2" + } + }, + { + "package": "PanModal", + "repositoryURL": "https://github.com/slackhq/PanModal.git", + "state": { + "branch": null, + "revision": "b012aecb6b67a8e46369227f893c12544846613f", + "version": "1.2.7" + } + }, + { + "package": "SDWebImage", + "repositoryURL": "https://github.com/SDWebImage/SDWebImage.git", + "state": { + "branch": null, + "revision": "0fff0d7505b5306348263ea64fcc561253bbeb21", + "version": "5.12.2" + } + }, + { + "package": "swift-collections", + "repositoryURL": "https://github.com/apple/swift-collections.git", + "state": { + "branch": null, + "revision": "9d8719c8bebdc79740b6969c912ac706eb721d7a", + "version": "0.0.7" + } + }, { "package": "swift-nio", "repositoryURL": "https://github.com/apple/swift-nio.git", @@ -63,6 +189,33 @@ "revision": "b3dcd7dbd0d488e1a7077cb33b00f2083e382f07", "version": "5.0.1" } + }, + { + "package": "Tabman", + "repositoryURL": "https://github.com/uias/Tabman", + "state": { + "branch": null, + "revision": "f43489cdd743ba7ad86a422ebb5fcbf34e333df4", + "version": "2.11.1" + } + }, + { + "package": "ThirdPartyMailer", + "repositoryURL": "https://github.com/vtourraine/ThirdPartyMailer.git", + "state": { + "branch": null, + "revision": "779da6ce0793b461ccbbac2804755c1e29b6fa63", + "version": "1.8.0" + } + }, + { + "package": "TOCropViewController", + "repositoryURL": "https://github.com/TimOliver/TOCropViewController.git", + "state": { + "branch": null, + "revision": "dad97167bf1be16aeecd109130900995dd01c515", + "version": "2.6.0" + } } ] }, diff --git a/Mastodon/Diffiable/Item/SelectedAccountItem.swift b/Mastodon/Diffiable/Account/SelectedAccountItem.swift similarity index 100% rename from Mastodon/Diffiable/Item/SelectedAccountItem.swift rename to Mastodon/Diffiable/Account/SelectedAccountItem.swift diff --git a/Mastodon/Diffiable/Section/SelectedAccountSection.swift b/Mastodon/Diffiable/Account/SelectedAccountSection.swift similarity index 100% rename from Mastodon/Diffiable/Section/SelectedAccountSection.swift rename to Mastodon/Diffiable/Account/SelectedAccountSection.swift diff --git a/Mastodon/Diffiable/Item/AutoCompleteItem.swift b/Mastodon/Diffiable/Compose/AutoCompleteItem.swift similarity index 100% rename from Mastodon/Diffiable/Item/AutoCompleteItem.swift rename to Mastodon/Diffiable/Compose/AutoCompleteItem.swift diff --git a/Mastodon/Diffiable/Section/Compose/AutoCompleteSection.swift b/Mastodon/Diffiable/Compose/AutoCompleteSection.swift similarity index 100% rename from Mastodon/Diffiable/Section/Compose/AutoCompleteSection.swift rename to Mastodon/Diffiable/Compose/AutoCompleteSection.swift diff --git a/Mastodon/Diffiable/Item/ComposeStatusAttachmentItem.swift b/Mastodon/Diffiable/Compose/ComposeStatusAttachmentItem.swift similarity index 100% rename from Mastodon/Diffiable/Item/ComposeStatusAttachmentItem.swift rename to Mastodon/Diffiable/Compose/ComposeStatusAttachmentItem.swift diff --git a/Mastodon/Diffiable/Section/Compose/ComposeStatusAttachmentSection.swift b/Mastodon/Diffiable/Compose/ComposeStatusAttachmentSection.swift similarity index 100% rename from Mastodon/Diffiable/Section/Compose/ComposeStatusAttachmentSection.swift rename to Mastodon/Diffiable/Compose/ComposeStatusAttachmentSection.swift diff --git a/Mastodon/Diffiable/Item/ComposeStatusItem.swift b/Mastodon/Diffiable/Compose/ComposeStatusItem.swift similarity index 100% rename from Mastodon/Diffiable/Item/ComposeStatusItem.swift rename to Mastodon/Diffiable/Compose/ComposeStatusItem.swift diff --git a/Mastodon/Diffiable/Item/ComposeStatusPollItem.swift b/Mastodon/Diffiable/Compose/ComposeStatusPollItem.swift similarity index 100% rename from Mastodon/Diffiable/Item/ComposeStatusPollItem.swift rename to Mastodon/Diffiable/Compose/ComposeStatusPollItem.swift diff --git a/Mastodon/Diffiable/Section/Compose/ComposeStatusPollSection.swift b/Mastodon/Diffiable/Compose/ComposeStatusPollSection.swift similarity index 100% rename from Mastodon/Diffiable/Section/Compose/ComposeStatusPollSection.swift rename to Mastodon/Diffiable/Compose/ComposeStatusPollSection.swift diff --git a/Mastodon/Diffiable/Section/Compose/ComposeStatusSection.swift b/Mastodon/Diffiable/Compose/ComposeStatusSection.swift similarity index 100% rename from Mastodon/Diffiable/Section/Compose/ComposeStatusSection.swift rename to Mastodon/Diffiable/Compose/ComposeStatusSection.swift diff --git a/Mastodon/Diffiable/Item/CustomEmojiPickerItem.swift b/Mastodon/Diffiable/Compose/CustomEmojiPickerItem.swift similarity index 100% rename from Mastodon/Diffiable/Item/CustomEmojiPickerItem.swift rename to Mastodon/Diffiable/Compose/CustomEmojiPickerItem.swift diff --git a/Mastodon/Diffiable/Section/Compose/CustomEmojiPickerSection.swift b/Mastodon/Diffiable/Compose/CustomEmojiPickerSection.swift similarity index 100% rename from Mastodon/Diffiable/Section/Compose/CustomEmojiPickerSection.swift rename to Mastodon/Diffiable/Compose/CustomEmojiPickerSection.swift diff --git a/Mastodon/Diffiable/Item/NotificationItem.swift b/Mastodon/Diffiable/Notification/NotificationItem.swift similarity index 100% rename from Mastodon/Diffiable/Item/NotificationItem.swift rename to Mastodon/Diffiable/Notification/NotificationItem.swift diff --git a/Mastodon/Diffiable/Section/Status/NotificationSection.swift b/Mastodon/Diffiable/Notification/NotificationSection.swift similarity index 100% rename from Mastodon/Diffiable/Section/Status/NotificationSection.swift rename to Mastodon/Diffiable/Notification/NotificationSection.swift diff --git a/Mastodon/Diffiable/Item/CategoryPickerItem.swift b/Mastodon/Diffiable/Onboarding/CategoryPickerItem.swift similarity index 100% rename from Mastodon/Diffiable/Item/CategoryPickerItem.swift rename to Mastodon/Diffiable/Onboarding/CategoryPickerItem.swift diff --git a/Mastodon/Diffiable/Section/Onboarding/CategoryPickerSection.swift b/Mastodon/Diffiable/Onboarding/CategoryPickerSection.swift similarity index 100% rename from Mastodon/Diffiable/Section/Onboarding/CategoryPickerSection.swift rename to Mastodon/Diffiable/Onboarding/CategoryPickerSection.swift diff --git a/Mastodon/Diffiable/Item/PickServerItem.swift b/Mastodon/Diffiable/Onboarding/PickServerItem.swift similarity index 100% rename from Mastodon/Diffiable/Item/PickServerItem.swift rename to Mastodon/Diffiable/Onboarding/PickServerItem.swift diff --git a/Mastodon/Diffiable/Section/Onboarding/PickServerSection.swift b/Mastodon/Diffiable/Onboarding/PickServerSection.swift similarity index 98% rename from Mastodon/Diffiable/Section/Onboarding/PickServerSection.swift rename to Mastodon/Diffiable/Onboarding/PickServerSection.swift index b2079aab..9f74bad5 100644 --- a/Mastodon/Diffiable/Section/Onboarding/PickServerSection.swift +++ b/Mastodon/Diffiable/Onboarding/PickServerSection.swift @@ -28,7 +28,7 @@ extension PickServerSection { guard let dependency = dependency else { return nil } switch item { case .header: - let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: PickServerTitleCell.self), for: indexPath) as! PickServerTitleCell + let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: OnboardingHeadlineTableViewCell.self), for: indexPath) as! OnboardingHeadlineTableViewCell return cell case .server(let server, let attribute): let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: PickServerCell.self), for: indexPath) as! PickServerCell diff --git a/Mastodon/Diffiable/Onboarding/ServerRuleItem.swift b/Mastodon/Diffiable/Onboarding/ServerRuleItem.swift new file mode 100644 index 00000000..37d8b6ee --- /dev/null +++ b/Mastodon/Diffiable/Onboarding/ServerRuleItem.swift @@ -0,0 +1,21 @@ +// +// ServerRuleItem.swift +// Mastodon +// +// Created by MainasuK on 2022-1-5. +// + +import Foundation +import MastodonSDK + +enum ServerRuleItem: Hashable { + case header(domain: String) + case rule(RuleContext) +} + +extension ServerRuleItem { + struct RuleContext: Hashable { + let index: Int + let rule: Mastodon.Entity.Instance.Rule + } +} diff --git a/Mastodon/Diffiable/Onboarding/ServerRuleSection.swift b/Mastodon/Diffiable/Onboarding/ServerRuleSection.swift new file mode 100644 index 00000000..ba96e873 --- /dev/null +++ b/Mastodon/Diffiable/Onboarding/ServerRuleSection.swift @@ -0,0 +1,34 @@ +// +// ServerRuleSection.swift +// Mastodon +// +// Created by MainasuK on 2022-1-5. +// + +import UIKit + +enum ServerRuleSection: Hashable { + case header + case rules +} + +extension ServerRuleSection { + static func tableViewDiffableDataSource( + tableView: UITableView + ) -> UITableViewDiffableDataSource { + return UITableViewDiffableDataSource(tableView: tableView) { tableView, indexPath, item in + switch item { + case .header(let domain): + let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: OnboardingHeadlineTableViewCell.self), for: indexPath) as! OnboardingHeadlineTableViewCell + cell.titleLabel.text = L10n.Scene.ServerRules.title + cell.subTitleLabel.text = L10n.Scene.ServerRules.subtitle(domain) + return cell + case .rule(let ruleContext): + let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: ServerRulesTableViewCell.self), for: indexPath) as! ServerRulesTableViewCell + cell.indexImageView.image = UIImage(systemName: "\(ruleContext.index).circle.fill") ?? UIImage(systemName: "questionmark.circle.fill") + cell.ruleLabel.text = ruleContext.rule.text + return cell + } + } + } +} diff --git a/Mastodon/Diffiable/Item/PollItem.swift b/Mastodon/Diffiable/Poll/PollItem.swift similarity index 100% rename from Mastodon/Diffiable/Item/PollItem.swift rename to Mastodon/Diffiable/Poll/PollItem.swift diff --git a/Mastodon/Diffiable/Section/Status/PollSection.swift b/Mastodon/Diffiable/Poll/PollSection.swift similarity index 100% rename from Mastodon/Diffiable/Section/Status/PollSection.swift rename to Mastodon/Diffiable/Poll/PollSection.swift diff --git a/Mastodon/Diffiable/Item/ProfileFieldItem.swift b/Mastodon/Diffiable/Profile/ProfileFieldItem.swift similarity index 100% rename from Mastodon/Diffiable/Item/ProfileFieldItem.swift rename to Mastodon/Diffiable/Profile/ProfileFieldItem.swift diff --git a/Mastodon/Diffiable/Section/ProfileFieldSection.swift b/Mastodon/Diffiable/Profile/ProfileFieldSection.swift similarity index 100% rename from Mastodon/Diffiable/Section/ProfileFieldSection.swift rename to Mastodon/Diffiable/Profile/ProfileFieldSection.swift diff --git a/Mastodon/Diffiable/Section/Search/RecommendAccountSection.swift b/Mastodon/Diffiable/Search/RecommendAccountSection.swift similarity index 100% rename from Mastodon/Diffiable/Section/Search/RecommendAccountSection.swift rename to Mastodon/Diffiable/Search/RecommendAccountSection.swift diff --git a/Mastodon/Diffiable/Section/Search/RecommendHashTagSection.swift b/Mastodon/Diffiable/Search/RecommendHashTagSection.swift similarity index 100% rename from Mastodon/Diffiable/Section/Search/RecommendHashTagSection.swift rename to Mastodon/Diffiable/Search/RecommendHashTagSection.swift diff --git a/Mastodon/Diffiable/Item/SearchHistoryItem.swift b/Mastodon/Diffiable/Search/SearchHistoryItem.swift similarity index 100% rename from Mastodon/Diffiable/Item/SearchHistoryItem.swift rename to Mastodon/Diffiable/Search/SearchHistoryItem.swift diff --git a/Mastodon/Diffiable/Section/Search/SearchHistorySection.swift b/Mastodon/Diffiable/Search/SearchHistorySection.swift similarity index 100% rename from Mastodon/Diffiable/Section/Search/SearchHistorySection.swift rename to Mastodon/Diffiable/Search/SearchHistorySection.swift diff --git a/Mastodon/Diffiable/Item/SearchResultItem.swift b/Mastodon/Diffiable/Search/SearchResultItem.swift similarity index 100% rename from Mastodon/Diffiable/Item/SearchResultItem.swift rename to Mastodon/Diffiable/Search/SearchResultItem.swift diff --git a/Mastodon/Diffiable/Section/Search/SearchResultSection.swift b/Mastodon/Diffiable/Search/SearchResultSection.swift similarity index 100% rename from Mastodon/Diffiable/Section/Search/SearchResultSection.swift rename to Mastodon/Diffiable/Search/SearchResultSection.swift diff --git a/Mastodon/Diffiable/Item/SettingsItem.swift b/Mastodon/Diffiable/Settings/SettingsItem.swift similarity index 100% rename from Mastodon/Diffiable/Item/SettingsItem.swift rename to Mastodon/Diffiable/Settings/SettingsItem.swift diff --git a/Mastodon/Diffiable/Section/SettingsSection.swift b/Mastodon/Diffiable/Settings/SettingsSection.swift similarity index 100% rename from Mastodon/Diffiable/Section/SettingsSection.swift rename to Mastodon/Diffiable/Settings/SettingsSection.swift diff --git a/Mastodon/Diffiable/Item/Item.swift b/Mastodon/Diffiable/Status/Item.swift similarity index 100% rename from Mastodon/Diffiable/Item/Item.swift rename to Mastodon/Diffiable/Status/Item.swift diff --git a/Mastodon/Diffiable/Section/Status/ReportSection.swift b/Mastodon/Diffiable/Status/ReportSection.swift similarity index 100% rename from Mastodon/Diffiable/Section/Status/ReportSection.swift rename to Mastodon/Diffiable/Status/ReportSection.swift diff --git a/Mastodon/Diffiable/Section/Status/StatusSection.swift b/Mastodon/Diffiable/Status/StatusSection.swift similarity index 100% rename from Mastodon/Diffiable/Section/Status/StatusSection.swift rename to Mastodon/Diffiable/Status/StatusSection.swift diff --git a/Mastodon/Diffiable/Item/UserItem.swift b/Mastodon/Diffiable/User/UserItem.swift similarity index 100% rename from Mastodon/Diffiable/Item/UserItem.swift rename to Mastodon/Diffiable/User/UserItem.swift diff --git a/Mastodon/Diffiable/Section/UserSection.swift b/Mastodon/Diffiable/User/UserSection.swift similarity index 100% rename from Mastodon/Diffiable/Section/UserSection.swift rename to Mastodon/Diffiable/User/UserSection.swift diff --git a/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewController.swift b/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewController.swift index 54e7bc6d..17df72d3 100644 --- a/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewController.swift +++ b/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewController.swift @@ -35,7 +35,7 @@ final class MastodonPickServerViewController: UIViewController, NeedsDependency let tableView: UITableView = { let tableView = ControlContainableTableView() - tableView.register(PickServerTitleCell.self, forCellReuseIdentifier: String(describing: PickServerTitleCell.self)) + tableView.register(OnboardingHeadlineTableViewCell.self, forCellReuseIdentifier: String(describing: OnboardingHeadlineTableViewCell.self)) tableView.register(PickServerCell.self, forCellReuseIdentifier: String(describing: PickServerCell.self)) tableView.register(PickServerLoaderTableViewCell.self, forCellReuseIdentifier: String(describing: PickServerLoaderTableViewCell.self)) tableView.rowHeight = UITableView.automaticDimension @@ -236,6 +236,12 @@ extension MastodonPickServerViewController { viewModel.viewWillAppear.send() } + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + + tableView.flashScrollIndicators() + } + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) diff --git a/Mastodon/Scene/Onboarding/ServerRules/MastodonServerRulesViewController.swift b/Mastodon/Scene/Onboarding/ServerRules/MastodonServerRulesViewController.swift index e93d06e1..6633f6c7 100644 --- a/Mastodon/Scene/Onboarding/ServerRules/MastodonServerRulesViewController.swift +++ b/Mastodon/Scene/Onboarding/ServerRules/MastodonServerRulesViewController.swift @@ -14,8 +14,11 @@ import MetaTextKit final class MastodonServerRulesViewController: UIViewController, NeedsDependency { - var disposeBag = Set() + let logger = Logger(subsystem: "MastodonServerRulesViewController", category: "ViewController") + var disposeBag = Set() + private var observations = Set() + weak var context: AppContext! { willSet { precondition(!isViewLoaded) } } weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } } @@ -25,8 +28,8 @@ final class MastodonServerRulesViewController: UIViewController, NeedsDependency let largeTitleLabel: UILabel = { let label = UILabel() - label.font = UIFontMetrics(forTextStyle: .largeTitle).scaledFont(for: .systemFont(ofSize: 34, weight: .bold)) - label.textColor = .label + label.font = MastodonServerRulesViewController.largeTitleFont + label.textColor = MastodonServerRulesViewController.largeTitleTextColor label.text = L10n.Scene.ServerRules.title label.numberOfLines = 0 return label @@ -34,56 +37,33 @@ final class MastodonServerRulesViewController: UIViewController, NeedsDependency private(set) lazy var subtitleLabel: UILabel = { let label = UILabel() - label.font = UIFontMetrics(forTextStyle: .title1).scaledFont(for: UIFont.systemFont(ofSize: 20)) - label.textColor = .secondaryLabel + label.font = MastodonServerRulesViewController.subTitleFont + label.textColor = MastodonServerRulesViewController.subTitleTextColor label.text = L10n.Scene.ServerRules.subtitle(viewModel.domain) label.numberOfLines = 0 return label }() - let rulesLabel: UILabel = { - let label = UILabel() - label.font = UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 17, weight: .semibold)) - label.textColor = Asset.Colors.Label.primary.color - label.text = "Rules" - label.numberOfLines = 0 - return label + let tableView: UITableView = { + let tableView = UITableView() + tableView.register(OnboardingHeadlineTableViewCell.self, forCellReuseIdentifier: String(describing: OnboardingHeadlineTableViewCell.self)) + tableView.register(ServerRulesTableViewCell.self, forCellReuseIdentifier: String(describing: ServerRulesTableViewCell.self)) + tableView.rowHeight = UITableView.automaticDimension + tableView.separatorStyle = .none + tableView.backgroundColor = .clear + tableView.keyboardDismissMode = .onDrag + if #available(iOS 15.0, *) { + tableView.sectionHeaderTopPadding = 0 + } else { + // Fallback on earlier versions + } + return tableView }() - - let bottomContainerView: UIView = { - let view = UIView() - view.backgroundColor = Asset.Theme.Mastodon.systemGroupedBackground.color - return view - }() - - private(set) lazy var bottomPromptMetaText: MetaText = { - let metaText = MetaText() - metaText.textAttributes = [ - .font: UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 17, weight: .regular), maximumPointSize: 22), - .foregroundColor: UIColor.label, - ] - metaText.linkAttributes = [ - .font: UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 17, weight: .regular), maximumPointSize: 22), - .foregroundColor: Asset.Colors.brandBlue.color, - ] - metaText.textView.isEditable = false - metaText.textView.isSelectable = false - metaText.textView.isScrollEnabled = false - metaText.textView.backgroundColor = Asset.Theme.Mastodon.systemGroupedBackground.color // needs background color to prevent server rules text overlap - return metaText - }() - - let confirmButton: PrimaryActionButton = { - let button = PrimaryActionButton() - button.setTitle(L10n.Scene.ServerRules.Button.confirm, for: .normal) - return button - }() - - let scrollView: UIScrollView = { - let scrollView = UIScrollView() - scrollView.alwaysBounceVertical = true - scrollView.showsVerticalScrollIndicator = false - return scrollView + + let navigationActionView: NavigationActionView = { + let navigationActionView = NavigationActionView() + navigationActionView.backgroundColor = Asset.Scene.Onboarding.onboardingBackground.color + return navigationActionView }() deinit { @@ -97,224 +77,90 @@ extension MastodonServerRulesViewController { override func viewDidLoad() { super.viewDidLoad() + navigationItem.leftBarButtonItem = UIBarButtonItem() + setupOnboardingAppearance() - configureTitleLabel() - configureMargin() - configTextView() - defer { setupNavigationBarBackgroundView() } - bottomContainerView.translatesAutoresizingMaskIntoConstraints = false - view.addSubview(bottomContainerView) + tableView.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(tableView) NSLayoutConstraint.activate([ - view.bottomAnchor.constraint(equalTo: bottomContainerView.bottomAnchor), - bottomContainerView.leadingAnchor.constraint(equalTo: view.leadingAnchor), - bottomContainerView.trailingAnchor.constraint(equalTo: view.trailingAnchor), + tableView.topAnchor.constraint(equalTo: view.topAnchor), + tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor), + tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor), + tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), ]) - bottomContainerView.preservesSuperviewLayoutMargins = true + + navigationActionView.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(navigationActionView) defer { - view.bringSubviewToFront(bottomContainerView) + view.bringSubviewToFront(navigationActionView) } - - confirmButton.translatesAutoresizingMaskIntoConstraints = false - bottomContainerView.addSubview(confirmButton) NSLayoutConstraint.activate([ - bottomContainerView.layoutMarginsGuide.bottomAnchor.constraint(equalTo: confirmButton.bottomAnchor, constant: MastodonServerRulesViewController.viewBottomPaddingHeight), - confirmButton.leadingAnchor.constraint(equalTo: bottomContainerView.layoutMarginsGuide.leadingAnchor), - bottomContainerView.layoutMarginsGuide.trailingAnchor.constraint(equalTo: confirmButton.trailingAnchor), - confirmButton.heightAnchor.constraint(equalToConstant: MastodonServerRulesViewController.actionButtonHeight).priority(.defaultHigh), + navigationActionView.leadingAnchor.constraint(equalTo: view.leadingAnchor), + navigationActionView.trailingAnchor.constraint(equalTo: view.trailingAnchor), + view.bottomAnchor.constraint(equalTo: navigationActionView.bottomAnchor), ]) - bottomPromptMetaText.textView.translatesAutoresizingMaskIntoConstraints = false - bottomContainerView.addSubview(bottomPromptMetaText.textView) - NSLayoutConstraint.activate([ - bottomPromptMetaText.textView.frameLayoutGuide.topAnchor.constraint(equalTo: bottomContainerView.topAnchor, constant: 20), - bottomPromptMetaText.textView.frameLayoutGuide.leadingAnchor.constraint(equalTo: bottomContainerView.layoutMarginsGuide.leadingAnchor), - bottomPromptMetaText.textView.frameLayoutGuide.trailingAnchor.constraint(equalTo: bottomContainerView.layoutMarginsGuide.trailingAnchor), - confirmButton.topAnchor.constraint(equalTo: bottomPromptMetaText.textView.frameLayoutGuide.bottomAnchor, constant: 20), - ]) + navigationActionView + .observe(\.bounds, options: [.initial, .new]) { [weak self] navigationActionView, _ in + guard let self = self else { return } + let inset = navigationActionView.frame.height + self.tableView.contentInset.bottom = inset + } + .store(in: &observations) - scrollView.translatesAutoresizingMaskIntoConstraints = false - view.addSubview(scrollView) - NSLayoutConstraint.activate([ - scrollView.frameLayoutGuide.topAnchor.constraint(equalTo: view.topAnchor), - scrollView.frameLayoutGuide.leadingAnchor.constraint(equalTo: view.readableContentGuide.leadingAnchor), - scrollView.frameLayoutGuide.trailingAnchor.constraint(equalTo: view.readableContentGuide.trailingAnchor), - scrollView.frameLayoutGuide.bottomAnchor.constraint(equalTo: view.bottomAnchor), - scrollView.frameLayoutGuide.widthAnchor.constraint(equalTo: scrollView.contentLayoutGuide.widthAnchor), - ]) - - stackView.axis = .vertical - stackView.distribution = .fill - stackView.spacing = 10 - stackView.isLayoutMarginsRelativeArrangement = true - stackView.layoutMargins = UIEdgeInsets(top: 20, left: 0, bottom: 20, right: 0) - stackView.addArrangedSubview(largeTitleLabel) - stackView.addArrangedSubview(subtitleLabel) - stackView.addArrangedSubview(rulesLabel) + tableView.delegate = self + viewModel.setupDiffableDataSource(tableView: tableView) - stackView.translatesAutoresizingMaskIntoConstraints = false - scrollView.addSubview(stackView) - NSLayoutConstraint.activate([ - stackView.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor), - stackView.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor), - stackView.trailingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor), - scrollView.contentLayoutGuide.bottomAnchor.constraint(equalTo: stackView.bottomAnchor), - ]) - - rulesLabel.attributedText = viewModel.rulesAttributedString - confirmButton.addTarget(self, action: #selector(MastodonServerRulesViewController.confirmButtonPressed(_:)), for: .touchUpInside) + navigationActionView.backButton.addTarget(self, action: #selector(MastodonServerRulesViewController.backButtonPressed(_:)), for: .touchUpInside) + navigationActionView.nextButton.addTarget(self, action: #selector(MastodonServerRulesViewController.nextButtonPressed(_:)), for: .touchUpInside) } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) - scrollView.flashScrollIndicators() - } - - override func viewDidLayoutSubviews() { - super.viewDidLayoutSubviews() - updateScrollViewContentInset() - } - - override func viewSafeAreaInsetsDidChange() { - super.viewSafeAreaInsetsDidChange() - updateScrollViewContentInset() - } - - override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { - super.traitCollectionDidChange(previousTraitCollection) - - setupNavigationBarAppearance() - configureTitleLabel() - configureMargin() + tableView.flashScrollIndicators() } } extension MastodonServerRulesViewController { - private func configureTitleLabel() { - guard UIDevice.current.userInterfaceIdiom == .pad else { - return - } - - switch traitCollection.horizontalSizeClass { - case .regular: - navigationItem.largeTitleDisplayMode = .always - navigationItem.title = L10n.Scene.ServerRules.title.replacingOccurrences(of: "\n", with: " ") - largeTitleLabel.isHidden = true - default: - navigationItem.leftBarButtonItem = nil - navigationItem.largeTitleDisplayMode = .never - navigationItem.title = nil - largeTitleLabel.isHidden = false - } + + @objc private func backButtonPressed(_ sender: UIButton) { + logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public)") + navigationController?.popViewController(animated: true) } - private func configureMargin() { - switch traitCollection.horizontalSizeClass { - case .regular: - let margin = MastodonPickServerViewController.viewEdgeMargin - stackView.layoutMargins = UIEdgeInsets(top: 32, left: margin, bottom: 20, right: margin) - bottomContainerView.layoutMargins = UIEdgeInsets(top: 0, left: margin, bottom: 0, right: margin) - default: - stackView.layoutMargins = UIEdgeInsets(top: 20, left: 0, bottom: 20, right: 0) - bottomContainerView.layoutMargins = .zero - } - } -} + @objc private func nextButtonPressed(_ sender: UIButton) { + logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public)") -extension MastodonServerRulesViewController { - func updateScrollViewContentInset() { - view.layoutIfNeeded() - scrollView.contentInset.bottom = bottomContainerView.frame.height - scrollView.verticalScrollIndicatorInsets.bottom = bottomContainerView.frame.height + let viewModel = MastodonRegisterViewModel(domain: viewModel.domain, context: context, authenticateInfo: viewModel.authenticateInfo, instance: viewModel.instance, applicationToken: viewModel.applicationToken) + coordinator.present(scene: .mastodonRegister(viewModel: viewModel), from: self, transition: .show) } - func configTextView() { - let metaContent = ServerRulesPromptMetaContent(domain: viewModel.domain) - bottomPromptMetaText.configure(content: metaContent) - bottomPromptMetaText.textView.linkDelegate = self - } - - struct ServerRulesPromptMetaContent: MetaContent { - let string: String - let entities: [Meta.Entity] - - init(domain: String) { - let _string = L10n.Scene.ServerRules.prompt(domain) - self.string = _string - - var _entities: [Meta.Entity] = [] - - let termsOfServiceText = L10n.Scene.ServerRules.termsOfService - if let termsOfServiceRange = _string.range(of: termsOfServiceText) { - let url = Mastodon.API.serverRulesURL(domain: domain) - let entity = Meta.Entity(range: NSRange(termsOfServiceRange, in: _string), meta: .url(termsOfServiceText, trimmed: termsOfServiceText, url: url.absoluteString, userInfo: nil)) - _entities.append(entity) - } - - let privacyPolicyText = L10n.Scene.ServerRules.privacyPolicy - if let privacyPolicyRange = _string.range(of: privacyPolicyText) { - let url = Mastodon.API.privacyURL(domain: domain) - let entity = Meta.Entity(range: NSRange(privacyPolicyRange, in: _string), meta: .url(privacyPolicyText, trimmed: privacyPolicyText, url: url.absoluteString, userInfo: nil)) - _entities.append(entity) - } - - self.entities = _entities - } - - func metaAttachment(for entity: Meta.Entity) -> MetaAttachment? { - return nil - } - } - -} - -extension MastodonServerRulesViewController: UITextViewDelegate { - func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool { - return false - } -} - -// MARK: - MetaTextViewDelegate -extension MastodonServerRulesViewController: MetaTextViewDelegate { - func metaTextView(_ metaTextView: MetaTextView, didSelectMeta meta: Meta) { - switch meta { - case .url(_, _, let url, _): - guard let url = URL(string: url) else { return } - coordinator.present(scene: .safari(url: url), from: nil, transition: .safariPresent(animated: true, completion: nil)) - default: - break - } - } -} - -extension MastodonServerRulesViewController { - @objc private func confirmButtonPressed(_ sender: UIButton) { - os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function) - - let viewModel = MastodonRegisterViewModel(domain: self.viewModel.domain, context: self.context, authenticateInfo: self.viewModel.authenticateInfo, instance: self.viewModel.instance, applicationToken: self.viewModel.applicationToken) - self.coordinator.present(scene: .mastodonRegister(viewModel: viewModel), from: self, transition: .show) - } } // MARK: - OnboardingViewControllerAppearance extension MastodonServerRulesViewController: OnboardingViewControllerAppearance { } -#if canImport(SwiftUI) && DEBUG -import SwiftUI - -struct ServerRulesViewController_Previews: PreviewProvider { - - static var previews: some View { - UIViewControllerPreview { - let viewController = MastodonServerRulesViewController() - return viewController - } - .previewLayout(.fixed(width: 375, height: 800)) +// MARK: - UITableViewDelegate +extension MastodonServerRulesViewController: UITableViewDelegate { + func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { + return UIView() } + func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { + guard let diffableDataSource = viewModel.diffableDataSource, + section < diffableDataSource.snapshot().numberOfSections + else { return .leastNonzeroMagnitude } + + let sectionItem = diffableDataSource.snapshot().sectionIdentifiers[section] + switch sectionItem { + case .header: + return .leastNonzeroMagnitude + case .rules: + return 16 + } + } } - -#endif diff --git a/Mastodon/Scene/Onboarding/ServerRules/MastodonServerRulesViewModel+Diffable.swift b/Mastodon/Scene/Onboarding/ServerRules/MastodonServerRulesViewModel+Diffable.swift new file mode 100644 index 00000000..f6385a52 --- /dev/null +++ b/Mastodon/Scene/Onboarding/ServerRules/MastodonServerRulesViewModel+Diffable.swift @@ -0,0 +1,26 @@ +// +// MastodonServerRulesViewModel+Diffable.swift +// Mastodon +// +// Created by MainasuK on 2022-1-5. +// + +import UIKit + +extension MastodonServerRulesViewModel { + func setupDiffableDataSource( + tableView: UITableView + ) { + diffableDataSource = ServerRuleSection.tableViewDiffableDataSource(tableView: tableView) + + var snapshot = NSDiffableDataSourceSnapshot() + snapshot.appendSections([.header, .rules]) + snapshot.appendItems([.header(domain: domain)], toSection: .header) + let ruleItems: [ServerRuleItem] = rules.enumerated().map { i, rule in + let ruleContext = ServerRuleItem.RuleContext(index: i, rule: rule) + return ServerRuleItem.rule(ruleContext) + } + snapshot.appendItems(ruleItems, toSection: .rules) + diffableDataSource?.applySnapshot(snapshot, animated: false, completion: nil) + } +} diff --git a/Mastodon/Scene/Onboarding/ServerRules/MastodonServerRulesViewModel.swift b/Mastodon/Scene/Onboarding/ServerRules/MastodonServerRulesViewModel.swift index 5936a2c0..f2664e0e 100644 --- a/Mastodon/Scene/Onboarding/ServerRules/MastodonServerRulesViewModel.swift +++ b/Mastodon/Scene/Onboarding/ServerRules/MastodonServerRulesViewModel.swift @@ -18,6 +18,9 @@ final class MastodonServerRulesViewModel { let instance: Mastodon.Entity.Instance let applicationToken: Mastodon.Entity.Token + // output + var diffableDataSource: UITableViewDiffableDataSource? + init( domain: String, authenticateInfo: AuthenticationViewModel.AuthenticateInfo, diff --git a/Mastodon/Scene/Onboarding/ServerRules/ServerRulesTableViewCell.swift b/Mastodon/Scene/Onboarding/ServerRules/ServerRulesTableViewCell.swift new file mode 100644 index 00000000..83378b99 --- /dev/null +++ b/Mastodon/Scene/Onboarding/ServerRules/ServerRulesTableViewCell.swift @@ -0,0 +1,83 @@ +// +// ServerRulesTableViewCell.swift +// Mastodon +// +// Created by MainasuK on 2022-1-5. +// + +import UIKit + +final class ServerRulesTableViewCell: UITableViewCell { + + static let margin: CGFloat = 23 + + let indexImageView: UIImageView = { + let imageView = UIImageView() + imageView.tintColor = Asset.Colors.Label.primary.color + return imageView + }() + + let ruleLabel: UILabel = { + let label = UILabel() + label.font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 17, weight: .semibold)) + label.textColor = Asset.Colors.Label.primary.color + label.numberOfLines = 0 + return label + }() + + let separalerLine: UIView = { + let view = UIView() + view.backgroundColor = Asset.Theme.System.separator.color + return view + }() + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + _init() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + _init() + } + +} + +extension ServerRulesTableViewCell { + + private func _init() { + selectionStyle = .none + backgroundColor = .clear + + indexImageView.translatesAutoresizingMaskIntoConstraints = false + contentView.addSubview(indexImageView) + NSLayoutConstraint.activate([ + indexImageView.topAnchor.constraint(greaterThanOrEqualTo: contentView.topAnchor, constant: ServerRulesTableViewCell.margin), + indexImageView.leadingAnchor.constraint(equalTo: contentView.readableContentGuide.leadingAnchor), + contentView.bottomAnchor.constraint(greaterThanOrEqualTo: indexImageView.bottomAnchor, constant: ServerRulesTableViewCell.margin), + indexImageView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + indexImageView.widthAnchor.constraint(equalToConstant: 32).priority(.required - 1), + indexImageView.heightAnchor.constraint(equalToConstant: 32).priority(.required - 1), + ]) + + ruleLabel.translatesAutoresizingMaskIntoConstraints = false + contentView.addSubview(ruleLabel) + NSLayoutConstraint.activate([ + ruleLabel.topAnchor.constraint(greaterThanOrEqualTo: contentView.topAnchor, constant: ServerRulesTableViewCell.margin), + ruleLabel.leadingAnchor.constraint(equalTo: indexImageView.trailingAnchor, constant: 16), + ruleLabel.trailingAnchor.constraint(equalTo: contentView.readableContentGuide.trailingAnchor), + contentView.bottomAnchor.constraint(greaterThanOrEqualTo: ruleLabel.bottomAnchor, constant: ServerRulesTableViewCell.margin), + ruleLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + ]) + + separalerLine.translatesAutoresizingMaskIntoConstraints = false + contentView.addSubview(separalerLine) + NSLayoutConstraint.activate([ + separalerLine.leadingAnchor.constraint(equalTo: contentView.readableContentGuide.leadingAnchor), + separalerLine.trailingAnchor.constraint(equalTo: contentView.readableContentGuide.trailingAnchor), + separalerLine.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + separalerLine.heightAnchor.constraint(equalToConstant: UIView.separatorLineHeight(of: contentView)).priority(.required - 1), + ]) + } + +} diff --git a/Mastodon/Scene/Onboarding/Share/NavigationActionView.swift b/Mastodon/Scene/Onboarding/Share/NavigationActionView.swift index 4b5bb124..dc30227c 100644 --- a/Mastodon/Scene/Onboarding/Share/NavigationActionView.swift +++ b/Mastodon/Scene/Onboarding/Share/NavigationActionView.swift @@ -6,11 +6,14 @@ // import UIKit +import MastodonUI final class NavigationActionView: UIView { static let buttonHeight: CGFloat = 50 + private var observations = Set() + let buttonContainer: UIStackView = { let stackView = UIStackView() stackView.axis = .horizontal @@ -18,6 +21,7 @@ final class NavigationActionView: UIView { return stackView }() + let backButtonShadowContainer = ShadowBackgroundContainer() let backButton: PrimaryActionButton = { let button = PrimaryActionButton() button.action = .back @@ -25,6 +29,7 @@ final class NavigationActionView: UIView { return button }() + let nextButtonShadowContainer = ShadowBackgroundContainer() let nextButton: PrimaryActionButton = { let button = PrimaryActionButton() button.action = .next @@ -56,14 +61,33 @@ extension NavigationActionView { safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: buttonContainer.bottomAnchor, constant: 8), ]) - backButton.translatesAutoresizingMaskIntoConstraints = false - buttonContainer.addArrangedSubview(backButton) - nextButton.translatesAutoresizingMaskIntoConstraints = false - buttonContainer.addArrangedSubview(nextButton) + backButtonShadowContainer.translatesAutoresizingMaskIntoConstraints = false + buttonContainer.addArrangedSubview(backButtonShadowContainer) + nextButtonShadowContainer.translatesAutoresizingMaskIntoConstraints = false + buttonContainer.addArrangedSubview(nextButtonShadowContainer) NSLayoutConstraint.activate([ - backButton.heightAnchor.constraint(equalToConstant: NavigationActionView.buttonHeight).priority(.required - 1), - nextButton.heightAnchor.constraint(equalToConstant: NavigationActionView.buttonHeight).priority(.required - 1), - nextButton.widthAnchor.constraint(equalTo: backButton.widthAnchor, multiplier: 2).priority(.required - 1), + backButtonShadowContainer.heightAnchor.constraint(equalToConstant: NavigationActionView.buttonHeight).priority(.required - 1), + nextButtonShadowContainer.heightAnchor.constraint(equalToConstant: NavigationActionView.buttonHeight).priority(.required - 1), + nextButtonShadowContainer.widthAnchor.constraint(equalTo: backButtonShadowContainer.widthAnchor, multiplier: 2).priority(.required - 1), + ]) + + backButton.translatesAutoresizingMaskIntoConstraints = false + backButtonShadowContainer.addSubview(backButton) + NSLayoutConstraint.activate([ + backButton.topAnchor.constraint(equalTo: backButtonShadowContainer.topAnchor), + backButton.leadingAnchor.constraint(equalTo: backButtonShadowContainer.leadingAnchor), + backButton.trailingAnchor.constraint(equalTo: backButtonShadowContainer.trailingAnchor), + backButton.bottomAnchor.constraint(equalTo: backButtonShadowContainer.bottomAnchor), + ]) + + nextButton.translatesAutoresizingMaskIntoConstraints = false + nextButtonShadowContainer.addSubview(nextButton) + NSLayoutConstraint.activate([ + nextButton.topAnchor.constraint(equalTo: nextButtonShadowContainer.topAnchor), + nextButton.leadingAnchor.constraint(equalTo: nextButtonShadowContainer.leadingAnchor), + nextButton.trailingAnchor.constraint(equalTo: nextButtonShadowContainer.trailingAnchor), + nextButton.bottomAnchor.constraint(equalTo: nextButtonShadowContainer.bottomAnchor), ]) } + } diff --git a/Mastodon/Scene/Onboarding/PickServer/TableViewCell/PickServerTitleCell.swift b/Mastodon/Scene/Onboarding/Share/OnboardingHeadlineTableViewCell.swift similarity index 79% rename from Mastodon/Scene/Onboarding/PickServer/TableViewCell/PickServerTitleCell.swift rename to Mastodon/Scene/Onboarding/Share/OnboardingHeadlineTableViewCell.swift index 161b15d0..f8090734 100644 --- a/Mastodon/Scene/Onboarding/PickServer/TableViewCell/PickServerTitleCell.swift +++ b/Mastodon/Scene/Onboarding/Share/OnboardingHeadlineTableViewCell.swift @@ -1,5 +1,5 @@ // -// PickServerTitleCell.swift +// OnboardingHeadlineTableViewCell.swift // Mastodon // // Created by BradGao on 2021/2/23. @@ -7,12 +7,12 @@ import UIKit -final class PickServerTitleCell: UITableViewCell { +final class OnboardingHeadlineTableViewCell: UITableViewCell { let titleLabel: UILabel = { let label = UILabel() - label.font = UIFontMetrics(forTextStyle: .largeTitle).scaledFont(for: .systemFont(ofSize: 28, weight: .bold)) - label.textColor = Asset.Colors.Label.primary.color + label.font = MastodonPickServerViewController.largeTitleFont + label.textColor = MastodonPickServerViewController.largeTitleTextColor label.text = L10n.Scene.ServerPicker.title label.adjustsFontForContentSizeCategory = true label.numberOfLines = 0 @@ -21,8 +21,8 @@ final class PickServerTitleCell: UITableViewCell { let subTitleLabel: UILabel = { let label = UILabel() - label.font = UIFontMetrics(forTextStyle: .largeTitle).scaledFont(for: .systemFont(ofSize: 17, weight: .regular)) - label.textColor = Asset.Colors.Label.secondary.color + label.font = MastodonPickServerViewController.subTitleFont + label.textColor = MastodonPickServerViewController.subTitleTextColor label.text = "Pick a community based on your interests, region, or a general purpose one. Each community is operated by an entirely independent organization or individual." label.adjustsFontForContentSizeCategory = true label.numberOfLines = 0 @@ -40,7 +40,7 @@ final class PickServerTitleCell: UITableViewCell { } } -extension PickServerTitleCell { +extension OnboardingHeadlineTableViewCell { private func _init() { selectionStyle = .none diff --git a/Mastodon/Scene/Onboarding/Share/OnboardingViewControllerAppearance.swift b/Mastodon/Scene/Onboarding/Share/OnboardingViewControllerAppearance.swift index c4fae4dd..aef6a8ab 100644 --- a/Mastodon/Scene/Onboarding/Share/OnboardingViewControllerAppearance.swift +++ b/Mastodon/Scene/Onboarding/Share/OnboardingViewControllerAppearance.swift @@ -21,6 +21,22 @@ extension OnboardingViewControllerAppearance { static var viewBottomPaddingHeight: CGFloat { return 11 } static var viewBottomPaddingHeightExtend: CGFloat { return 22 } + static var largeTitleFont: UIFont { + return UIFontMetrics(forTextStyle: .largeTitle).scaledFont(for: .systemFont(ofSize: 28, weight: .bold)) + } + + static var largeTitleTextColor: UIColor { + return Asset.Colors.Label.primary.color + } + + static var subTitleFont: UIFont { + return UIFontMetrics(forTextStyle: .largeTitle).scaledFont(for: .systemFont(ofSize: 17, weight: .regular)) + } + + static var subTitleTextColor: UIColor { + return Asset.Colors.Label.secondary.color + } + func setupOnboardingAppearance() { view.backgroundColor = Asset.Scene.Onboarding.onboardingBackground.color diff --git a/Mastodon/Scene/Onboarding/Welcome/WelcomeViewController.swift b/Mastodon/Scene/Onboarding/Welcome/WelcomeViewController.swift index c86b059b..1dff6965 100644 --- a/Mastodon/Scene/Onboarding/Welcome/WelcomeViewController.swift +++ b/Mastodon/Scene/Onboarding/Welcome/WelcomeViewController.swift @@ -56,6 +56,7 @@ final class WelcomeViewController: UIViewController, NeedsDependency { button.setTitleColor(.black, for: .normal) return button }() + let signUpButtonShadowView = UIView() private(set) lazy var signInButton: PrimaryActionButton = { let button = PrimaryActionButton() @@ -72,7 +73,6 @@ final class WelcomeViewController: UIViewController, NeedsDependency { }() let signInButtonShadowView = UIView() - deinit { os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function) } @@ -117,6 +117,16 @@ extension WelcomeViewController { signInButton.heightAnchor.constraint(equalToConstant: WelcomeViewController.actionButtonHeight).priority(.required - 1), ]) + signUpButtonShadowView.translatesAutoresizingMaskIntoConstraints = false + buttonContainer.addSubview(signUpButtonShadowView) + buttonContainer.sendSubviewToBack(signUpButtonShadowView) + NSLayoutConstraint.activate([ + signUpButtonShadowView.topAnchor.constraint(equalTo: signUpButton.topAnchor), + signUpButtonShadowView.leadingAnchor.constraint(equalTo: signUpButton.leadingAnchor), + signUpButtonShadowView.trailingAnchor.constraint(equalTo: signUpButton.trailingAnchor), + signUpButtonShadowView.bottomAnchor.constraint(equalTo: signUpButton.bottomAnchor), + ]) + signInButtonShadowView.translatesAutoresizingMaskIntoConstraints = false buttonContainer.addSubview(signInButtonShadowView) buttonContainer.sendSubviewToBack(signInButtonShadowView) @@ -168,6 +178,17 @@ extension WelcomeViewController { extension WelcomeViewController { private func setupButtonShadowView() { + signUpButtonShadowView.layer.setupShadow( + color: .black, + alpha: 0.25, + x: 0, + y: 1, + blur: 2, + spread: 0, + roundedRect: signInButtonShadowView.bounds, + byRoundingCorners: .allCorners, + cornerRadii: CGSize(width: 10, height: 10) + ) signInButtonShadowView.layer.setupShadow( color: .black, alpha: 0.25, diff --git a/Mastodon/Scene/Share/View/Button/PrimaryActionButton.swift b/Mastodon/Scene/Share/View/Button/PrimaryActionButton.swift index 3bda63de..676d558a 100644 --- a/Mastodon/Scene/Share/View/Button/PrimaryActionButton.swift +++ b/Mastodon/Scene/Share/View/Button/PrimaryActionButton.swift @@ -9,8 +9,8 @@ import UIKit class PrimaryActionButton: UIButton { - var isLoading: Bool = false - + private var originalButtonTitle: String? + lazy var activityIndicator: UIActivityIndicatorView = { let indicator = UIActivityIndicatorView(style: .medium) indicator.color = .white @@ -18,16 +18,13 @@ class PrimaryActionButton: UIButton { indicator.translatesAutoresizingMaskIntoConstraints = false return indicator }() - - private var originalButtonTitle: String? - + var adjustsBackgroundImageWhenUserInterfaceStyleChanges = true var action: Action = .next { didSet { setupAppearance(action: action) } } - - var adjustsBackgroundImageWhenUserInterfaceStyleChanges = true + var isLoading: Bool = false override init(frame: CGRect) { super.init(frame: frame) diff --git a/Mastodon/Extension/CALayer.swift b/MastodonSDK/Sources/MastodonExtension/CALayer.swift similarity index 95% rename from Mastodon/Extension/CALayer.swift rename to MastodonSDK/Sources/MastodonExtension/CALayer.swift index 41ce739e..684a4a70 100644 --- a/Mastodon/Extension/CALayer.swift +++ b/MastodonSDK/Sources/MastodonExtension/CALayer.swift @@ -9,7 +9,7 @@ import UIKit extension CALayer { - func setupShadow( + public func setupShadow( color: UIColor = .black, alpha: Float = 0.5, x: CGFloat = 0, @@ -43,9 +43,8 @@ extension CALayer { } } - func removeShadow() { + public func removeShadow() { shadowRadius = 0 } - - + } diff --git a/MastodonSDK/Sources/MastodonExtension/UIImage.swift b/MastodonSDK/Sources/MastodonExtension/UIImage.swift index 178d289d..e3560af6 100644 --- a/MastodonSDK/Sources/MastodonExtension/UIImage.swift +++ b/MastodonSDK/Sources/MastodonExtension/UIImage.swift @@ -10,12 +10,28 @@ import CoreImage.CIFilterBuiltins import UIKit extension UIImage { - public static func placeholder(size: CGSize = CGSize(width: 1, height: 1), color: UIColor) -> UIImage { + public static func placeholder( + size: CGSize = CGSize(width: 1, height: 1), + color: UIColor, + cornerRadius: CGFloat = 0 + ) -> UIImage { let render = UIGraphicsImageRenderer(size: size) return render.image { (context: UIGraphicsImageRendererContext) in + // set clear fill context.cgContext.setFillColor(color.cgColor) - context.fill(CGRect(origin: .zero, size: size)) + + let rect = CGRect(origin: .zero, size: size) + + // clip corner if needs + if cornerRadius > 0 { + let path = UIBezierPath(roundedRect: rect, cornerRadius: cornerRadius).cgPath + context.cgContext.addPath(path) + context.cgContext.clip(using: .evenOdd) + } + + // set fill + context.fill(rect) } } } diff --git a/MastodonSDK/Sources/MastodonSDK/Entity/Mastodon+Entity+Instance.swift b/MastodonSDK/Sources/MastodonSDK/Entity/Mastodon+Entity+Instance.swift index d0d16ee4..f245d741 100644 --- a/MastodonSDK/Sources/MastodonSDK/Entity/Mastodon+Entity+Instance.swift +++ b/MastodonSDK/Sources/MastodonSDK/Entity/Mastodon+Entity+Instance.swift @@ -86,7 +86,7 @@ extension Mastodon.Entity.Instance { } extension Mastodon.Entity.Instance { - public struct Rule: Codable { + public struct Rule: Codable, Hashable { public let id: String public let text: String } diff --git a/MastodonSDK/Sources/MastodonUI/View/Container/ShadowBackgroundContainer.swift b/MastodonSDK/Sources/MastodonUI/View/Container/ShadowBackgroundContainer.swift new file mode 100644 index 00000000..6b45a050 --- /dev/null +++ b/MastodonSDK/Sources/MastodonUI/View/Container/ShadowBackgroundContainer.swift @@ -0,0 +1,48 @@ +// +// ShadowBackgroundContainer.swift +// +// +// Created by MainasuK on 2022-1-5. +// + +import UIKit +import MastodonExtension + +public final class ShadowBackgroundContainer: UIView { + + public let shadowLayer = CALayer() + + override init(frame: CGRect) { + super.init(frame: frame) + _init() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + _init() + } + +} + +extension ShadowBackgroundContainer { + private func _init() { + layer.insertSublayer(shadowLayer, at: 0) + } + + public override func layoutSubviews() { + super.layoutSubviews() + + shadowLayer.frame = bounds + shadowLayer.setupShadow( + color: .black, + alpha: 0.25, + x: 0, + y: 1, + blur: 2, + spread: 0, + roundedRect: bounds, + byRoundingCorners: .allCorners, + cornerRadii: CGSize(width: 10, height: 10) + ) + } +} From 7bf14c0450ab8705dc675ca3491691f7d7681396 Mon Sep 17 00:00:00 2001 From: CMK Date: Fri, 7 Jan 2022 18:49:37 +0800 Subject: [PATCH 09/12] feat: update register scene UI --- Mastodon.xcodeproj/project.pbxproj | 44 +- .../xcschemes/xcschememanagement.plist | 8 +- .../Diffiable/Onboarding/RegisterItem.swift | 19 + .../Onboarding/RegisterSection.swift | 12 + .../Onboarding/ServerRuleSection.swift | 2 +- Mastodon/Generated/Assets.swift | 2 + .../avatar.placeholder.imageset/Contents.json | 23 + .../avatar.placeholder.imageset/Frame 82.jpg | Bin 0 -> 3585 bytes .../Frame 82@2x.png | Bin 0 -> 4595 bytes .../Frame 82@3x.png | Bin 0 -> 7449 bytes .../Contents.json | 38 + .../MastodonPickServerViewController.swift | 2 +- .../MastodonRegisterAvatarTableViewCell.swift | 77 ++ ...donRegisterPasswordHintTableViewCell.swift | 48 + ...stodonRegisterTextFieldTableViewCell.swift | 136 +++ ...astodonRegisterViewController+Avatar.swift | 42 +- .../MastodonRegisterViewController.swift | 952 +++++------------- .../MastodonRegisterViewModel+Diffable.swift | 231 +++++ .../Register/MastodonRegisterViewModel.swift | 215 ++-- .../{ => Cell}/ServerRulesTableViewCell.swift | 0 .../MastodonServerRulesViewController.swift | 26 +- .../Header/ProfileHeaderViewModel.swift | 5 +- .../Service/KeyboardResponderService.swift | 44 + .../Container/ShadowBackgroundContainer.swift | 18 +- 24 files changed, 1073 insertions(+), 871 deletions(-) create mode 100644 Mastodon/Diffiable/Onboarding/RegisterItem.swift create mode 100644 Mastodon/Diffiable/Onboarding/RegisterSection.swift create mode 100644 Mastodon/Resources/Assets.xcassets/Scene/Onboarding/avatar.placeholder.imageset/Contents.json create mode 100644 Mastodon/Resources/Assets.xcassets/Scene/Onboarding/avatar.placeholder.imageset/Frame 82.jpg create mode 100644 Mastodon/Resources/Assets.xcassets/Scene/Onboarding/avatar.placeholder.imageset/Frame 82@2x.png create mode 100644 Mastodon/Resources/Assets.xcassets/Scene/Onboarding/avatar.placeholder.imageset/Frame 82@3x.png create mode 100644 Mastodon/Resources/Assets.xcassets/Scene/Onboarding/textField.background.colorset/Contents.json create mode 100644 Mastodon/Scene/Onboarding/Register/Cell/MastodonRegisterAvatarTableViewCell.swift create mode 100644 Mastodon/Scene/Onboarding/Register/Cell/MastodonRegisterPasswordHintTableViewCell.swift create mode 100644 Mastodon/Scene/Onboarding/Register/Cell/MastodonRegisterTextFieldTableViewCell.swift create mode 100644 Mastodon/Scene/Onboarding/Register/MastodonRegisterViewModel+Diffable.swift rename Mastodon/Scene/Onboarding/ServerRules/{ => Cell}/ServerRulesTableViewCell.swift (100%) diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index 3061b6e4..349f14ee 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -199,6 +199,10 @@ DB0617FD27855BFE0030EE79 /* ServerRuleItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0617FC27855BFE0030EE79 /* ServerRuleItem.swift */; }; DB0617FF27855D6C0030EE79 /* MastodonServerRulesViewModel+Diffable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0617FE27855D6C0030EE79 /* MastodonServerRulesViewModel+Diffable.swift */; }; DB0618012785732C0030EE79 /* ServerRulesTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0618002785732C0030EE79 /* ServerRulesTableViewCell.swift */; }; + DB0618032785A7100030EE79 /* RegisterSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0618022785A7100030EE79 /* RegisterSection.swift */; }; + DB0618052785A73D0030EE79 /* RegisterItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0618042785A73D0030EE79 /* RegisterItem.swift */; }; + DB0618072785A8880030EE79 /* MastodonRegisterViewModel+Diffable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0618062785A8880030EE79 /* MastodonRegisterViewModel+Diffable.swift */; }; + DB06180A2785B2AB0030EE79 /* MastodonRegisterAvatarTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0618092785B2AB0030EE79 /* MastodonRegisterAvatarTableViewCell.swift */; }; DB084B5725CBC56C00F898ED /* Status.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB084B5625CBC56C00F898ED /* Status.swift */; }; DB0AC6FC25CD02E600D75117 /* APIService+Instance.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0AC6FB25CD02E600D75117 /* APIService+Instance.swift */; }; DB0C946526A6FD4D0088FB11 /* AlamofireImage in Frameworks */ = {isa = PBXBuildFile; productRef = DB0C946426A6FD4D0088FB11 /* AlamofireImage */; }; @@ -396,6 +400,8 @@ DB789A1225F9F2CC0071ACA0 /* ComposeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB789A1125F9F2CC0071ACA0 /* ComposeViewModel.swift */; }; DB7F48452620241000796008 /* ProfileHeaderViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB7F48442620241000796008 /* ProfileHeaderViewModel.swift */; }; DB8190C62601FF0400020C08 /* AttachmentContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB8190C52601FF0400020C08 /* AttachmentContainerView.swift */; }; + DB8481152788121200BBEABA /* MastodonRegisterTextFieldTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB8481142788121200BBEABA /* MastodonRegisterTextFieldTableViewCell.swift */; }; + DB84811727883C2600BBEABA /* MastodonRegisterPasswordHintTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB84811627883C2600BBEABA /* MastodonRegisterPasswordHintTableViewCell.swift */; }; DB852D1926FAEB6B00FC9D81 /* SidebarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB852D1826FAEB6B00FC9D81 /* SidebarViewController.swift */; }; DB852D1C26FB021500FC9D81 /* RootSplitViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB852D1B26FB021500FC9D81 /* RootSplitViewController.swift */; }; DB852D1F26FB037800FC9D81 /* SidebarViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB852D1E26FB037800FC9D81 /* SidebarViewModel.swift */; }; @@ -984,6 +990,10 @@ DB0617FC27855BFE0030EE79 /* ServerRuleItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerRuleItem.swift; sourceTree = ""; }; DB0617FE27855D6C0030EE79 /* MastodonServerRulesViewModel+Diffable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MastodonServerRulesViewModel+Diffable.swift"; sourceTree = ""; }; DB0618002785732C0030EE79 /* ServerRulesTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerRulesTableViewCell.swift; sourceTree = ""; }; + DB0618022785A7100030EE79 /* RegisterSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegisterSection.swift; sourceTree = ""; }; + DB0618042785A73D0030EE79 /* RegisterItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegisterItem.swift; sourceTree = ""; }; + DB0618062785A8880030EE79 /* MastodonRegisterViewModel+Diffable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MastodonRegisterViewModel+Diffable.swift"; sourceTree = ""; }; + DB0618092785B2AB0030EE79 /* MastodonRegisterAvatarTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonRegisterAvatarTableViewCell.swift; sourceTree = ""; }; DB084B5625CBC56C00F898ED /* Status.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Status.swift; sourceTree = ""; }; DB0AC6FB25CD02E600D75117 /* APIService+Instance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+Instance.swift"; sourceTree = ""; }; DB0C946A26A700AB0088FB11 /* MastodonUser+Property.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MastodonUser+Property.swift"; sourceTree = ""; }; @@ -1206,6 +1216,8 @@ DB789A1125F9F2CC0071ACA0 /* ComposeViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeViewModel.swift; sourceTree = ""; }; DB7F48442620241000796008 /* ProfileHeaderViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileHeaderViewModel.swift; sourceTree = ""; }; DB8190C52601FF0400020C08 /* AttachmentContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttachmentContainerView.swift; sourceTree = ""; }; + DB8481142788121200BBEABA /* MastodonRegisterTextFieldTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonRegisterTextFieldTableViewCell.swift; sourceTree = ""; }; + DB84811627883C2600BBEABA /* MastodonRegisterPasswordHintTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonRegisterPasswordHintTableViewCell.swift; sourceTree = ""; }; DB852D1826FAEB6B00FC9D81 /* SidebarViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SidebarViewController.swift; sourceTree = ""; }; DB852D1B26FB021500FC9D81 /* RootSplitViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootSplitViewController.swift; sourceTree = ""; }; DB852D1E26FB037800FC9D81 /* SidebarViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SidebarViewModel.swift; sourceTree = ""; }; @@ -2057,8 +2069,8 @@ DB68A03825E900CC00CFDF14 /* Share */, 0FAA0FDD25E0B5700017CCDE /* Welcome */, 0FAA102525E1125D0017CCDE /* PickServer */, - DBE0821A25CD382900FD6BBD /* Register */, DB72602125E36A2500235243 /* ServerRules */, + DBE0821A25CD382900FD6BBD /* Register */, 2D364F7025E66D5B00204FDC /* ResendEmail */, 2D59819925E4A55C000FB903 /* ConfirmEmail */, ); @@ -2138,6 +2150,24 @@ path = Account; sourceTree = ""; }; + DB0618082785B2790030EE79 /* Cell */ = { + isa = PBXGroup; + children = ( + DB0618002785732C0030EE79 /* ServerRulesTableViewCell.swift */, + ); + path = Cell; + sourceTree = ""; + }; + DB06180B2785B2AF0030EE79 /* Cell */ = { + isa = PBXGroup; + children = ( + DB0618092785B2AB0030EE79 /* MastodonRegisterAvatarTableViewCell.swift */, + DB8481142788121200BBEABA /* MastodonRegisterTextFieldTableViewCell.swift */, + DB84811627883C2600BBEABA /* MastodonRegisterPasswordHintTableViewCell.swift */, + ); + path = Cell; + sourceTree = ""; + }; DB084B5125CBC56300F898ED /* CoreDataStack */ = { isa = PBXGroup; children = ( @@ -2424,6 +2454,8 @@ DB1FD45925F27898004CFCFC /* CategoryPickerItem.swift */, DB0617F427855AB90030EE79 /* ServerRuleSection.swift */, DB0617FC27855BFE0030EE79 /* ServerRuleItem.swift */, + DB0618022785A7100030EE79 /* RegisterSection.swift */, + DB0618042785A73D0030EE79 /* RegisterItem.swift */, ); path = Onboarding; sourceTree = ""; @@ -2633,10 +2665,10 @@ DB72602125E36A2500235243 /* ServerRules */ = { isa = PBXGroup; children = ( + DB0618082785B2790030EE79 /* Cell */, DB72601B25E36A2100235243 /* MastodonServerRulesViewController.swift */, DB72602625E36A6F00235243 /* MastodonServerRulesViewModel.swift */, DB0617FE27855D6C0030EE79 /* MastodonServerRulesViewModel+Diffable.swift */, - DB0618002785732C0030EE79 /* ServerRulesTableViewCell.swift */, ); path = ServerRules; sourceTree = ""; @@ -3197,9 +3229,11 @@ DBE0821A25CD382900FD6BBD /* Register */ = { isa = PBXGroup; children = ( + DB06180B2785B2AF0030EE79 /* Cell */, DBE0821425CD382600FD6BBD /* MastodonRegisterViewController.swift */, 2D939AE725EE1CF80076FA61 /* MastodonRegisterViewController+Avatar.swift */, DBE0822325CD3F1E00FD6BBD /* MastodonRegisterViewModel.swift */, + DB0618062785A8880030EE79 /* MastodonRegisterViewModel+Diffable.swift */, ); path = Register; sourceTree = ""; @@ -3974,6 +4008,7 @@ DBB525502611ED6D002F1F29 /* ProfileHeaderView.swift in Sources */, 0FB3D33225E5F50E00AAD544 /* PickServerSearchCell.swift in Sources */, DB71FD5225F8CCAA00512AE1 /* APIService+Status.swift in Sources */, + DB8481152788121200BBEABA /* MastodonRegisterTextFieldTableViewCell.swift in Sources */, 5D0393962612D266007FE196 /* WebViewModel.swift in Sources */, 5B24BBDA262DB14800A9381B /* ReportViewModel.swift in Sources */, 2D5A3D3825CF8D9F002347D6 /* ScrollViewContainer.swift in Sources */, @@ -4020,7 +4055,9 @@ DB03A795272A981400EE37C5 /* ContentSplitViewController.swift in Sources */, 2D152A8C25C295CC009AA50C /* StatusView.swift in Sources */, DBBC24DE26A54BCB00398BB9 /* MastodonMetricFormatter.swift in Sources */, + DB06180A2785B2AB0030EE79 /* MastodonRegisterAvatarTableViewCell.swift in Sources */, DBB3BA2A26A81C020004F2D4 /* FLAnimatedImageView.swift in Sources */, + DB0618032785A7100030EE79 /* RegisterSection.swift in Sources */, 2DE0FAC82615F5F000CDF649 /* SearchRecommendAccountsCollectionViewCell.swift in Sources */, DBF1D251269DB01200C1C08A /* SearchHistoryViewController.swift in Sources */, 2D42FF8525C8224F004A627A /* HitTestExpandedButton.swift in Sources */, @@ -4178,6 +4215,7 @@ 2DF75BA125D0E29D00694EC8 /* StatusProvider+StatusTableViewCellDelegate.swift in Sources */, 5DF1056425F887CB00D6C0D4 /* AVPlayer.swift in Sources */, DBBF1DCB2652539E00E5B703 /* AutoCompleteItem.swift in Sources */, + DB84811727883C2600BBEABA /* MastodonRegisterPasswordHintTableViewCell.swift in Sources */, 2DA6054725F716A2006356F9 /* PlaybackState.swift in Sources */, DB35FC1F2612F1D9006193C9 /* ProfileRelationshipActionButton.swift in Sources */, DBC7A672260C897100E57475 /* StatusContentWarningEditorView.swift in Sources */, @@ -4215,6 +4253,7 @@ DB6C8C0F25F0A6AE00AAA452 /* Mastodon+Entity+Error.swift in Sources */, DB1E346825F518E20079D7DF /* CategoryPickerSection.swift in Sources */, DB7274F4273BB9B200577D95 /* ListBatchFetchViewModel.swift in Sources */, + DB0618052785A73D0030EE79 /* RegisterItem.swift in Sources */, 2D61254D262547C200299647 /* APIService+Notification.swift in Sources */, DB040ED126538E3D00BEE9D8 /* Trie.swift in Sources */, DB73BF4B27140C0800781945 /* UITableViewDiffableDataSource.swift in Sources */, @@ -4322,6 +4361,7 @@ DBE54AC62636C89F004E7C0B /* NotificationPreference.swift in Sources */, 2D5A3D2825CF8BC9002347D6 /* HomeTimelineViewModel+Diffable.swift in Sources */, DB98339C25C96DE600AD9700 /* APIService+Account.swift in Sources */, + DB0618072785A8880030EE79 /* MastodonRegisterViewModel+Diffable.swift in Sources */, DB6B74FC272FF55800C70B6E /* UserSection.swift in Sources */, 2DF75BA725D10E1000694EC8 /* APIService+Favorite.swift in Sources */, DB9D6C3825E508BE0051B173 /* Attachment.swift in Sources */, diff --git a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist index 601fc88a..95a6213d 100644 --- a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist @@ -7,12 +7,12 @@ AppShared.xcscheme_^#shared#^_ orderHint - 24 + 18 CoreDataStack.xcscheme_^#shared#^_ orderHint - 27 + 20 Mastodon - ASDK.xcscheme_^#shared#^_ @@ -102,7 +102,7 @@ MastodonIntent.xcscheme_^#shared#^_ orderHint - 26 + 19 MastodonIntents.xcscheme_^#shared#^_ @@ -122,7 +122,7 @@ ShareActionExtension.xcscheme_^#shared#^_ orderHint - 25 + 21 SuppressBuildableAutocreation diff --git a/Mastodon/Diffiable/Onboarding/RegisterItem.swift b/Mastodon/Diffiable/Onboarding/RegisterItem.swift new file mode 100644 index 00000000..0fb0aead --- /dev/null +++ b/Mastodon/Diffiable/Onboarding/RegisterItem.swift @@ -0,0 +1,19 @@ +// +// RegisterItem.swift +// Mastodon +// +// Created by MainasuK on 2022-1-5. +// + +import Foundation + +enum RegisterItem: Hashable { + case header + case avatar + case name + case username + case email + case password + case hint + case reason +} diff --git a/Mastodon/Diffiable/Onboarding/RegisterSection.swift b/Mastodon/Diffiable/Onboarding/RegisterSection.swift new file mode 100644 index 00000000..efb67f69 --- /dev/null +++ b/Mastodon/Diffiable/Onboarding/RegisterSection.swift @@ -0,0 +1,12 @@ +// +// RegisterSection.swift +// Mastodon +// +// Created by MainasuK on 2022-1-5. +// + +import UIKit + +enum RegisterSection: Hashable { + case main +} diff --git a/Mastodon/Diffiable/Onboarding/ServerRuleSection.swift b/Mastodon/Diffiable/Onboarding/ServerRuleSection.swift index ba96e873..66abec44 100644 --- a/Mastodon/Diffiable/Onboarding/ServerRuleSection.swift +++ b/Mastodon/Diffiable/Onboarding/ServerRuleSection.swift @@ -25,7 +25,7 @@ extension ServerRuleSection { return cell case .rule(let ruleContext): let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: ServerRulesTableViewCell.self), for: indexPath) as! ServerRulesTableViewCell - cell.indexImageView.image = UIImage(systemName: "\(ruleContext.index).circle.fill") ?? UIImage(systemName: "questionmark.circle.fill") + cell.indexImageView.image = UIImage(systemName: "\(ruleContext.index + 1).circle.fill") ?? UIImage(systemName: "questionmark.circle.fill") cell.ruleLabel.text = ruleContext.rule.text return cell } diff --git a/Mastodon/Generated/Assets.swift b/Mastodon/Generated/Assets.swift index 0761780c..410d81a2 100644 --- a/Mastodon/Generated/Assets.swift +++ b/Mastodon/Generated/Assets.swift @@ -91,12 +91,14 @@ internal enum Asset { } internal enum Scene { internal enum Onboarding { + internal static let avatarPlaceholder = ImageAsset(name: "Scene/Onboarding/avatar.placeholder") internal static let navigationBackButtonBackground = ColorAsset(name: "Scene/Onboarding/navigation.back.button.background") internal static let navigationBackButtonBackgroundHighlighted = ColorAsset(name: "Scene/Onboarding/navigation.back.button.background.highlighted") internal static let navigationNextButtonBackground = ColorAsset(name: "Scene/Onboarding/navigation.next.button.background") internal static let navigationNextButtonBackgroundHighlighted = ColorAsset(name: "Scene/Onboarding/navigation.next.button.background.highlighted") internal static let onboardingBackground = ColorAsset(name: "Scene/Onboarding/onboarding.background") internal static let searchBarBackground = ColorAsset(name: "Scene/Onboarding/search.bar.background") + internal static let textFieldBackground = ColorAsset(name: "Scene/Onboarding/textField.background") } internal enum Profile { internal enum Banner { diff --git a/Mastodon/Resources/Assets.xcassets/Scene/Onboarding/avatar.placeholder.imageset/Contents.json b/Mastodon/Resources/Assets.xcassets/Scene/Onboarding/avatar.placeholder.imageset/Contents.json new file mode 100644 index 00000000..2b84d06b --- /dev/null +++ b/Mastodon/Resources/Assets.xcassets/Scene/Onboarding/avatar.placeholder.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "Frame 82.jpg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Frame 82@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Frame 82@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Assets.xcassets/Scene/Onboarding/avatar.placeholder.imageset/Frame 82.jpg b/Mastodon/Resources/Assets.xcassets/Scene/Onboarding/avatar.placeholder.imageset/Frame 82.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7819c97b9aab4595b11927537488edb716599eba GIT binary patch literal 3585 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 ue@o6w0(=H;Nwmuyli7SdVz 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 literal 0 HcmV?d00001 diff --git a/Mastodon/Resources/Assets.xcassets/Scene/Onboarding/avatar.placeholder.imageset/Frame 82@3x.png b/Mastodon/Resources/Assets.xcassets/Scene/Onboarding/avatar.placeholder.imageset/Frame 82@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..68603b22798213da0fa73b7a74413d2806592113 GIT binary patch literal 7449 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 + + let containerView: UIView = { + let view = UIView() + view.backgroundColor = .clear + view.layer.masksToBounds = true + view.layer.cornerCurve = .continuous + view.layer.cornerRadius = 22 + return view + }() + + let avatarButton: HighlightDimmableButton = { + let button = HighlightDimmableButton() + button.backgroundColor = Asset.Theme.Mastodon.secondaryGroupedSystemBackground.color + button.setImage(Asset.Scene.Onboarding.avatarPlaceholder.image, for: .normal) + return button + }() + + override func prepareForReuse() { + super.prepareForReuse() + + disposeBag.removeAll() + } + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + _init() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + _init() + } + +} + +extension MastodonRegisterAvatarTableViewCell { + + private func _init() { + selectionStyle = .none + backgroundColor = .clear + + containerView.translatesAutoresizingMaskIntoConstraints = false + contentView.addSubview(containerView) + NSLayoutConstraint.activate([ + containerView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 22), + containerView.centerXAnchor.constraint(equalTo: contentView.centerXAnchor), + contentView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor, constant: 8), + containerView.widthAnchor.constraint(equalToConstant: MastodonRegisterAvatarTableViewCell.containerSize.width).priority(.required - 1), + containerView.heightAnchor.constraint(equalToConstant: MastodonRegisterAvatarTableViewCell.containerSize.height).priority(.required - 1), + ]) + + avatarButton.translatesAutoresizingMaskIntoConstraints = false + containerView.addSubview(avatarButton) + NSLayoutConstraint.activate([ + avatarButton.topAnchor.constraint(equalTo: containerView.topAnchor), + avatarButton.leadingAnchor.constraint(equalTo: containerView.leadingAnchor), + avatarButton.trailingAnchor.constraint(equalTo: containerView.trailingAnchor), + avatarButton.bottomAnchor.constraint(equalTo: containerView.bottomAnchor), + ]) + } + +} diff --git a/Mastodon/Scene/Onboarding/Register/Cell/MastodonRegisterPasswordHintTableViewCell.swift b/Mastodon/Scene/Onboarding/Register/Cell/MastodonRegisterPasswordHintTableViewCell.swift new file mode 100644 index 00000000..3aa9d027 --- /dev/null +++ b/Mastodon/Scene/Onboarding/Register/Cell/MastodonRegisterPasswordHintTableViewCell.swift @@ -0,0 +1,48 @@ +// +// MastodonRegisterPasswordHintTableViewCell.swift +// Mastodon +// +// Created by MainasuK on 2022-1-7. +// + +import UIKit + +final class MastodonRegisterPasswordHintTableViewCell: UITableViewCell { + + let passwordRuleLabel: UILabel = { + let label = UILabel() + label.font = .preferredFont(forTextStyle: .footnote) + label.textColor = Asset.Colors.Label.secondary.color + label.text = "Your password needs at least:" + return label + }() + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + _init() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + _init() + } + +} + +extension MastodonRegisterPasswordHintTableViewCell { + + private func _init() { + selectionStyle = .none + backgroundColor = .clear + + passwordRuleLabel.translatesAutoresizingMaskIntoConstraints = false + contentView.addSubview(passwordRuleLabel) + NSLayoutConstraint.activate([ + passwordRuleLabel.topAnchor.constraint(equalTo: contentView.topAnchor), + passwordRuleLabel.leadingAnchor.constraint(equalTo: contentView.readableContentGuide.leadingAnchor), + passwordRuleLabel.trailingAnchor.constraint(equalTo: contentView.readableContentGuide.trailingAnchor), + passwordRuleLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + ]) + } + +} diff --git a/Mastodon/Scene/Onboarding/Register/Cell/MastodonRegisterTextFieldTableViewCell.swift b/Mastodon/Scene/Onboarding/Register/Cell/MastodonRegisterTextFieldTableViewCell.swift new file mode 100644 index 00000000..8e54d1ff --- /dev/null +++ b/Mastodon/Scene/Onboarding/Register/Cell/MastodonRegisterTextFieldTableViewCell.swift @@ -0,0 +1,136 @@ +// +// MastodonRegisterTextFieldTableViewCell.swift +// Mastodon +// +// Created by MainasuK on 2022-1-7. +// + +import UIKit +import Combine +import MastodonUI + +final class MastodonRegisterTextFieldTableViewCell: UITableViewCell { + + static let textFieldHeight: CGFloat = 50 + static let textFieldLabelFont = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 17, weight: .semibold), maximumPointSize: 22) + + var disposeBag = Set() + + let textFieldShadowContainer = ShadowBackgroundContainer() + let textField: UITextField = { + let textField = UITextField() + textField.font = MastodonRegisterTextFieldTableViewCell.textFieldLabelFont + textField.backgroundColor = Asset.Scene.Onboarding.textFieldBackground.color + textField.layer.masksToBounds = true + textField.layer.cornerRadius = 10 + textField.layer.cornerCurve = .continuous + return textField + }() + + override func prepareForReuse() { + super.prepareForReuse() + + disposeBag.removeAll() + textFieldShadowContainer.shadowColor = .black + textFieldShadowContainer.shadowAlpha = 0.25 + resetTextField() + } + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + _init() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + _init() + } + +} + +extension MastodonRegisterTextFieldTableViewCell { + + private func _init() { + selectionStyle = .none + backgroundColor = .clear + + textFieldShadowContainer.translatesAutoresizingMaskIntoConstraints = false + contentView.addSubview(textFieldShadowContainer) + NSLayoutConstraint.activate([ + textFieldShadowContainer.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 6), + textFieldShadowContainer.leadingAnchor.constraint(equalTo: contentView.readableContentGuide.leadingAnchor), + textFieldShadowContainer.trailingAnchor.constraint(equalTo: contentView.readableContentGuide.trailingAnchor), + contentView.bottomAnchor.constraint(equalTo: textFieldShadowContainer.bottomAnchor, constant: 6), + ]) + + textField.translatesAutoresizingMaskIntoConstraints = false + textFieldShadowContainer.addSubview(textField) + NSLayoutConstraint.activate([ + textField.topAnchor.constraint(equalTo: textFieldShadowContainer.topAnchor), + textField.leadingAnchor.constraint(equalTo: textFieldShadowContainer.leadingAnchor), + textField.trailingAnchor.constraint(equalTo: textFieldShadowContainer.trailingAnchor), + textField.bottomAnchor.constraint(equalTo: textFieldShadowContainer.bottomAnchor), + textField.heightAnchor.constraint(equalToConstant: MastodonRegisterTextFieldTableViewCell.textFieldHeight).priority(.required - 1), + ]) + + resetTextField() + } + +} + +extension MastodonRegisterTextFieldTableViewCell { + func resetTextField() { + textField.keyboardType = .default + textField.autocorrectionType = .default + textField.autocapitalizationType = .none + textField.attributedPlaceholder = nil + textField.isSecureTextEntry = false + + let paddingRect = CGRect(x: 0, y: 0, width: 16, height: 10) + textField.leftView = UIView(frame: paddingRect) + textField.leftViewMode = .always + textField.rightView = UIView(frame: paddingRect) + textField.rightViewMode = .always + } + + func setupTextViewRightView(text: String) { + textField.rightView = { + let containerView = UIView() + + let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: 8, height: MastodonRegisterTextFieldTableViewCell.textFieldHeight)) + paddingView.translatesAutoresizingMaskIntoConstraints = false + containerView.addSubview(paddingView) + NSLayoutConstraint.activate([ + paddingView.topAnchor.constraint(equalTo: containerView.topAnchor), + paddingView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor), + paddingView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor), + paddingView.widthAnchor.constraint(equalToConstant: 8).priority(.defaultHigh), + ]) + + let label = UILabel() + label.font = MastodonRegisterTextFieldTableViewCell.textFieldLabelFont + label.textColor = Asset.Colors.Label.primary.color + label.text = text + + label.translatesAutoresizingMaskIntoConstraints = false + containerView.addSubview(label) + NSLayoutConstraint.activate([ + label.topAnchor.constraint(equalTo: containerView.topAnchor), + label.leadingAnchor.constraint(equalTo: paddingView.trailingAnchor), + containerView.trailingAnchor.constraint(equalTo: label.trailingAnchor, constant: 16), + label.bottomAnchor.constraint(equalTo: containerView.bottomAnchor), + ]) + return containerView + }() + } + + func setupTextViewPlaceholder(text: String) { + textField.attributedPlaceholder = NSAttributedString( + string: text, + attributes: [ + .foregroundColor: Asset.Colors.Label.secondary.color, + .font: MastodonRegisterTextFieldTableViewCell.textFieldLabelFont + ] + ) + } +} diff --git a/Mastodon/Scene/Onboarding/Register/MastodonRegisterViewController+Avatar.swift b/Mastodon/Scene/Onboarding/Register/MastodonRegisterViewController+Avatar.swift index b1fa1b43..0add10dc 100644 --- a/Mastodon/Scene/Onboarding/Register/MastodonRegisterViewController+Avatar.swift +++ b/Mastodon/Scene/Onboarding/Register/MastodonRegisterViewController+Avatar.swift @@ -12,36 +12,6 @@ import PhotosUI import UIKit extension MastodonRegisterViewController { - func createMediaContextMenu() -> UIMenu { - var children: [UIMenuElement] = [] - let photoLibraryAction = UIAction(title: L10n.Scene.Compose.MediaSelection.photoLibrary, image: UIImage(systemName: "rectangle.on.rectangle"), identifier: nil, discoverabilityTitle: nil, attributes: [], state: .off) { [weak self] _ in - guard let self = self else { return } - self.present(self.imagePicker, animated: true, completion: nil) - } - children.append(photoLibraryAction) - if UIImagePickerController.isSourceTypeAvailable(.camera) { - let cameraAction = UIAction(title: L10n.Scene.Compose.MediaSelection.camera, image: UIImage(systemName: "camera"), identifier: nil, discoverabilityTitle: nil, attributes: [], state: .off, handler: { [weak self] _ in - guard let self = self else { return } - self.present(self.imagePickerController, animated: true, completion: nil) - }) - children.append(cameraAction) - } - let browseAction = UIAction(title: L10n.Scene.Compose.MediaSelection.browse, image: UIImage(systemName: "ellipsis"), identifier: nil, discoverabilityTitle: nil, attributes: [], state: .off) { [weak self] _ in - guard let self = self else { return } - self.present(self.documentPickerController, animated: true, completion: nil) - } - children.append(browseAction) - if self.viewModel.avatarImage.value != nil { - let deleteAction = UIAction(title: L10n.Scene.Register.Input.Avatar.delete, image: UIImage(systemName: "delete.left"), identifier: nil, discoverabilityTitle: nil, attributes: [.destructive], state: .off) { [weak self] _ in - guard let self = self else { return } - self.viewModel.avatarImage.value = nil - } - children.append(deleteAction) - } - - return UIMenu(title: "", image: nil, identifier: nil, options: .displayInline, children: children) - } - private func cropImage(image: UIImage, pickerViewController: UIViewController) { DispatchQueue.main.async { let cropController = CropViewController(croppingStyle: .default, image: image) @@ -49,6 +19,12 @@ extension MastodonRegisterViewController { cropController.setAspectRatioPreset(.presetSquare, animated: true) cropController.aspectRatioPickerButtonHidden = true cropController.aspectRatioLockEnabled = true + + // fix iPad compatibility issue + // ref: https://github.com/TimOliver/TOCropViewController/issues/365#issuecomment-550239604 + cropController.modalTransitionStyle = .crossDissolve + cropController.transitioningDelegate = nil + pickerViewController.dismiss(animated: true, completion: { self.present(cropController, animated: true, completion: nil) }) @@ -57,7 +33,6 @@ extension MastodonRegisterViewController { } // MARK: - PHPickerViewControllerDelegate - extension MastodonRegisterViewController: PHPickerViewControllerDelegate { func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) { guard let itemProvider = results.first?.itemProvider, itemProvider.canLoadObject(ofClass: UIImage.self) else { @@ -86,7 +61,6 @@ extension MastodonRegisterViewController: PHPickerViewControllerDelegate { } // MARK: - UIImagePickerControllerDelegate - extension MastodonRegisterViewController: UIImagePickerControllerDelegate & UINavigationControllerDelegate { func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) { picker.dismiss(animated: true, completion: nil) @@ -103,7 +77,6 @@ extension MastodonRegisterViewController: UIImagePickerControllerDelegate & UINa } // MARK: - UIDocumentPickerDelegate - extension MastodonRegisterViewController: UIDocumentPickerDelegate { func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) { guard let url = urls.first else { return } @@ -121,10 +94,9 @@ extension MastodonRegisterViewController: UIDocumentPickerDelegate { } // MARK: - CropViewControllerDelegate - extension MastodonRegisterViewController: CropViewControllerDelegate { public func cropViewController(_ cropViewController: CropViewController, didCropToImage image: UIImage, withRect cropRect: CGRect, angle: Int) { - self.viewModel.avatarImage.value = image + self.viewModel.avatarImage = image cropViewController.dismiss(animated: true, completion: nil) } } diff --git a/Mastodon/Scene/Onboarding/Register/MastodonRegisterViewController.swift b/Mastodon/Scene/Onboarding/Register/MastodonRegisterViewController.swift index 8428aaa7..b278a396 100644 --- a/Mastodon/Scene/Onboarding/Register/MastodonRegisterViewController.swift +++ b/Mastodon/Scene/Onboarding/Register/MastodonRegisterViewController.swift @@ -16,11 +16,11 @@ final class MastodonRegisterViewController: UIViewController, NeedsDependency, O static let avatarImageMaxSizeInPixel = CGSize(width: 400, height: 400) - static let textFieldLabelFont = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 17, weight: .semibold), maximumPointSize: 22) - static let errorPromptLabelFont = UIFontMetrics(forTextStyle: .caption1).scaledFont(for: .systemFont(ofSize: 13, weight: .semibold), maximumPointSize: 18) + let logger = Logger(subsystem: "MastodonRegisterViewController", category: "ViewController") var disposeBag = Set() - + private var observations = Set() + weak var context: AppContext! { willSet { precondition(!isViewLoaded) } } weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } } @@ -51,236 +51,30 @@ final class MastodonRegisterViewController: UIViewController, NeedsDependency, O let tapGestureRecognizer = UITapGestureRecognizer.singleTapGestureRecognizer - let scrollView: UIScrollView = { - let scrollview = UIScrollView() - scrollview.showsVerticalScrollIndicator = false - scrollview.keyboardDismissMode = .interactive - scrollview.alwaysBounceVertical = true - scrollview.clipsToBounds = false // make content could display over bleeding - scrollview.translatesAutoresizingMaskIntoConstraints = false - return scrollview + let tableView: UITableView = { + let tableView = UITableView() + tableView.rowHeight = UITableView.automaticDimension + tableView.separatorStyle = .none + tableView.backgroundColor = .clear + tableView.keyboardDismissMode = .onDrag + if #available(iOS 15.0, *) { + tableView.sectionHeaderTopPadding = .leastNonzeroMagnitude + } else { + // Fallback on earlier versions + } + return tableView }() - let stackView = UIStackView() - - let largeTitleLabel: UILabel = { - let label = UILabel() - label.font = UIFontMetrics(forTextStyle: .largeTitle).scaledFont(for: .systemFont(ofSize: 34, weight: .bold)) - label.textColor = Asset.Colors.Label.primary.color - label.text = L10n.Scene.Register.title - label.numberOfLines = 0 - return label - }() - - let avatarView: UIView = { - let view = UIView() - view.backgroundColor = .clear - return view - }() - - let avatarButton: UIButton = { - let button = HighlightDimmableButton() - let boldFont = UIFont.systemFont(ofSize: 42) - let configuration = UIImage.SymbolConfiguration(font: boldFont) - let image = UIImage(systemName: "person.fill.viewfinder", withConfiguration: configuration) - - button.setImage(image?.withRenderingMode(UIImage.RenderingMode.alwaysTemplate), for: UIControl.State.normal) - button.imageView?.tintColor = Asset.Colors.Label.secondary.color - button.backgroundColor = Asset.Theme.Mastodon.secondaryGroupedSystemBackground.color - button.layer.cornerRadius = 10 - button.clipsToBounds = true - - return button - }() - - let plusIconImageView: UIImageView = { - let icon = UIImageView() - let image = Asset.Circles.plusCircleFill.image.withRenderingMode(.alwaysTemplate) - icon.image = image - icon.tintColor = Asset.Colors.Icon.plus.color - icon.backgroundColor = UIColor(dynamicProvider: { collection in - switch collection.userInterfaceStyle { - case .dark: - return Asset.Theme.Mastodon.secondaryGroupedSystemBackground.color - default: - return .white - } - }) - return icon - }() - - let domainLabel: UILabel = { - let label = UILabel() - label.font = MastodonRegisterViewController.textFieldLabelFont - label.textColor = Asset.Colors.Label.primary.color - return label - }() - - let usernameTextField: UITextField = { - let textField = UITextField() - textField.returnKeyType = .next - textField.autocapitalizationType = .none - textField.autocorrectionType = .no - textField.backgroundColor = Asset.Theme.Mastodon.secondaryGroupedSystemBackground.color - textField.textColor = Asset.Colors.Label.primary.color - textField.attributedPlaceholder = NSAttributedString(string: L10n.Scene.Register.Input.Username.placeholder, - attributes: [NSAttributedString.Key.foregroundColor: Asset.Colors.Label.secondary.color, - NSAttributedString.Key.font: MastodonRegisterViewController.textFieldLabelFont]) - textField.borderStyle = UITextField.BorderStyle.roundedRect - textField.font = MastodonRegisterViewController.textFieldLabelFont - textField.leftView = { - let containerView = UIView() - - let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: 5, height: textField.frame.height)) - paddingView.translatesAutoresizingMaskIntoConstraints = false - containerView.addSubview(paddingView) - NSLayoutConstraint.activate([ - paddingView.topAnchor.constraint(equalTo: containerView.topAnchor), - paddingView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor), - paddingView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor), - paddingView.widthAnchor.constraint(equalToConstant: 5).priority(.defaultHigh), - ]) - - let label = UILabel() - label.font = MastodonRegisterViewController.textFieldLabelFont - label.textColor = Asset.Colors.Label.primary.color - label.text = " @" - - label.translatesAutoresizingMaskIntoConstraints = false - containerView.addSubview(label) - NSLayoutConstraint.activate([ - label.topAnchor.constraint(equalTo: containerView.topAnchor), - label.leadingAnchor.constraint(equalTo: paddingView.trailingAnchor), - label.trailingAnchor.constraint(equalTo: containerView.trailingAnchor), - label.bottomAnchor.constraint(equalTo: containerView.bottomAnchor), - ]) - return containerView - }() - textField.leftViewMode = .always - return textField - }() - - let usernameErrorPromptLabel: UILabel = { - let label = UILabel() - let color = Asset.Colors.danger.color - let font = MastodonRegisterViewController.errorPromptLabelFont - return label - }() - - let displayNameTextField: UITextField = { - let textField = UITextField() - textField.returnKeyType = .next - textField.autocapitalizationType = .none - textField.autocorrectionType = .no - textField.backgroundColor = Asset.Theme.Mastodon.secondaryGroupedSystemBackground.color - textField.textColor = Asset.Colors.Label.primary.color - textField.attributedPlaceholder = NSAttributedString(string: L10n.Scene.Register.Input.DisplayName.placeholder, - attributes: [NSAttributedString.Key.foregroundColor: Asset.Colors.Label.secondary.color, - NSAttributedString.Key.font: MastodonRegisterViewController.textFieldLabelFont]) - textField.borderStyle = UITextField.BorderStyle.roundedRect - let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: 5, height: textField.frame.height)) - textField.leftView = paddingView - textField.leftViewMode = .always - textField.font = MastodonRegisterViewController.textFieldLabelFont - return textField - }() - - let emailTextField: UITextField = { - let textField = UITextField() - textField.returnKeyType = .next - textField.autocapitalizationType = .none - textField.autocorrectionType = .no - textField.keyboardType = .emailAddress - textField.backgroundColor = Asset.Theme.Mastodon.secondaryGroupedSystemBackground.color - textField.textColor = Asset.Colors.Label.primary.color - textField.attributedPlaceholder = NSAttributedString(string: L10n.Scene.Register.Input.Email.placeholder, - attributes: [NSAttributedString.Key.foregroundColor: Asset.Colors.Label.secondary.color, - NSAttributedString.Key.font: MastodonRegisterViewController.textFieldLabelFont]) - textField.borderStyle = UITextField.BorderStyle.roundedRect - let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: 5, height: textField.frame.height)) - textField.leftView = paddingView - textField.leftViewMode = .always - textField.font = MastodonRegisterViewController.textFieldLabelFont - return textField - }() - - let emailErrorPromptLabel: UILabel = { - let label = UILabel() - let color = Asset.Colors.danger.color - let font = MastodonRegisterViewController.errorPromptLabelFont - return label - }() - - let passwordTextField: UITextField = { - let textField = UITextField() - textField.returnKeyType = .next // set to "Return" depends on if the last input field or not - textField.autocapitalizationType = .none - textField.autocorrectionType = .no - textField.keyboardType = .asciiCapable - textField.isSecureTextEntry = true - textField.backgroundColor = Asset.Theme.Mastodon.secondaryGroupedSystemBackground.color - textField.textColor = Asset.Colors.Label.primary.color - textField.attributedPlaceholder = NSAttributedString(string: L10n.Scene.Register.Input.Password.placeholder, - attributes: [NSAttributedString.Key.foregroundColor: Asset.Colors.Label.secondary.color, - NSAttributedString.Key.font: MastodonRegisterViewController.textFieldLabelFont]) - textField.borderStyle = UITextField.BorderStyle.roundedRect - let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: 5, height: textField.frame.height)) - textField.leftView = paddingView - textField.leftViewMode = .always - textField.font = MastodonRegisterViewController.textFieldLabelFont - return textField - }() - - let passwordCheckLabel: UILabel = { - let label = UILabel() - label.numberOfLines = 0 - return label - }() - - let passwordErrorPromptLabel: UILabel = { - let label = UILabel() - let color = Asset.Colors.danger.color - let font = MastodonRegisterViewController.errorPromptLabelFont - return label - }() - - - lazy var reasonTextField: UITextField = { - let textField = UITextField() - textField.returnKeyType = .next // set to "Return" depends on if the last input field or not - textField.autocapitalizationType = .none - textField.autocorrectionType = .no - textField.backgroundColor = Asset.Theme.Mastodon.secondaryGroupedSystemBackground.color - textField.textColor = Asset.Colors.Label.primary.color - textField.attributedPlaceholder = NSAttributedString(string: L10n.Scene.Register.Input.Invite.registrationUserInviteRequest, - attributes: [NSAttributedString.Key.foregroundColor: Asset.Colors.Label.secondary.color, - NSAttributedString.Key.font: MastodonRegisterViewController.textFieldLabelFont]) - textField.borderStyle = UITextField.BorderStyle.roundedRect - let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: 5, height: textField.frame.height)) - textField.leftView = paddingView - textField.leftViewMode = .always - textField.font = MastodonRegisterViewController.textFieldLabelFont - return textField - }() - - let reasonErrorPromptLabel: UILabel = { - let label = UILabel() - let color = Asset.Colors.danger.color - let font = MastodonRegisterViewController.errorPromptLabelFont - return label - }() - - let buttonContainer = UIView() - let signUpButton: PrimaryActionButton = { - let button = PrimaryActionButton() - button.isEnabled = false - button.setTitle(L10n.Common.Controls.Actions.continue, for: .normal) - return button + let navigationActionView: NavigationActionView = { + let navigationActionView = NavigationActionView() + navigationActionView.backgroundColor = Asset.Scene.Onboarding.onboardingBackground.color + return navigationActionView }() deinit { os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", (#file as NSString).lastPathComponent, #line, #function) } + } extension MastodonRegisterViewController { @@ -289,517 +83,200 @@ extension MastodonRegisterViewController { super.viewDidLoad() setupOnboardingAppearance() - configureTitleLabel() defer { setupNavigationBarBackgroundView() - configureFormLayout() } - avatarButton.menu = createMediaContextMenu() - avatarButton.showsMenuAsPrimaryAction = true + tableView.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(tableView) + NSLayoutConstraint.activate([ + tableView.topAnchor.constraint(equalTo: view.topAnchor), + tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor), + tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor), + tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), + ]) - domainLabel.text = "@" + viewModel.domain + " " - domainLabel.sizeToFit() - passwordCheckLabel.attributedText = MastodonRegisterViewModel.attributeStringForPassword(validateState: .empty) - usernameTextField.rightView = domainLabel - usernameTextField.rightViewMode = .always - usernameTextField.delegate = self - displayNameTextField.delegate = self - emailTextField.delegate = self - passwordTextField.delegate = self - - // gesture - view.addGestureRecognizer(tapGestureRecognizer) - tapGestureRecognizer.addTarget(self, action: #selector(tapGestureRecognizerHandler)) - - // stackView - stackView.axis = .vertical - stackView.distribution = .fill - stackView.spacing = 40 - stackView.layoutMargins = UIEdgeInsets(top: 20, left: 0, bottom: 26, right: 0) - stackView.isLayoutMarginsRelativeArrangement = true - stackView.addArrangedSubview(largeTitleLabel) - stackView.addArrangedSubview(avatarView) - - let formTableStackView = UIStackView() - stackView.addArrangedSubview(formTableStackView) - formTableStackView.axis = .vertical - formTableStackView.distribution = .fill - formTableStackView.spacing = 40 - - formTableStackView.addArrangedSubview(usernameTextField) - formTableStackView.addArrangedSubview(displayNameTextField) - formTableStackView.addArrangedSubview(emailTextField) - formTableStackView.addArrangedSubview(passwordTextField) - formTableStackView.addArrangedSubview(passwordCheckLabel) - if viewModel.approvalRequired { - formTableStackView.addArrangedSubview(reasonTextField) + navigationActionView.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(navigationActionView) + defer { + view.bringSubviewToFront(navigationActionView) } - - usernameErrorPromptLabel.translatesAutoresizingMaskIntoConstraints = false - formTableStackView.addSubview(usernameErrorPromptLabel) NSLayoutConstraint.activate([ - usernameErrorPromptLabel.topAnchor.constraint(equalTo: usernameTextField.bottomAnchor, constant: 6), - usernameErrorPromptLabel.leadingAnchor.constraint(equalTo: usernameTextField.leadingAnchor), - usernameErrorPromptLabel.trailingAnchor.constraint(equalTo: usernameTextField.trailingAnchor), + navigationActionView.leadingAnchor.constraint(equalTo: view.leadingAnchor), + navigationActionView.trailingAnchor.constraint(equalTo: view.trailingAnchor), + view.bottomAnchor.constraint(equalTo: navigationActionView.bottomAnchor), ]) - emailErrorPromptLabel.translatesAutoresizingMaskIntoConstraints = false - formTableStackView.addSubview(emailErrorPromptLabel) - NSLayoutConstraint.activate([ - emailErrorPromptLabel.topAnchor.constraint(equalTo: emailTextField.bottomAnchor, constant: 6), - emailErrorPromptLabel.leadingAnchor.constraint(equalTo: emailTextField.leadingAnchor), - emailErrorPromptLabel.trailingAnchor.constraint(equalTo: emailTextField.trailingAnchor), - ]) + navigationActionView + .observe(\.bounds, options: [.initial, .new]) { [weak self] navigationActionView, _ in + guard let self = self else { return } + let inset = navigationActionView.frame.height + self.tableView.contentInset.bottom = inset + } + .store(in: &observations) - passwordErrorPromptLabel.translatesAutoresizingMaskIntoConstraints = false - formTableStackView.addSubview(passwordErrorPromptLabel) - NSLayoutConstraint.activate([ - passwordErrorPromptLabel.topAnchor.constraint(equalTo: passwordCheckLabel.bottomAnchor, constant: 2), - passwordErrorPromptLabel.leadingAnchor.constraint(equalTo: passwordTextField.leadingAnchor), - passwordErrorPromptLabel.trailingAnchor.constraint(equalTo: passwordTextField.trailingAnchor), - ]) - - // scrollView - view.addSubview(scrollView) - NSLayoutConstraint.activate([ - scrollView.frameLayoutGuide.topAnchor.constraint(equalTo: view.layoutMarginsGuide.topAnchor), - scrollView.frameLayoutGuide.leadingAnchor.constraint(equalTo: view.readableContentGuide.leadingAnchor), - view.readableContentGuide.trailingAnchor.constraint(equalTo: scrollView.frameLayoutGuide.trailingAnchor), - scrollView.frameLayoutGuide.bottomAnchor.constraint(equalTo: view.layoutMarginsGuide.bottomAnchor), - scrollView.frameLayoutGuide.widthAnchor.constraint(equalTo: scrollView.contentLayoutGuide.widthAnchor), - ]) - - // stackView - scrollView.addSubview(stackView) - stackView.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - stackView.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor), - stackView.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor), - stackView.trailingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor), - stackView.widthAnchor.constraint(equalTo: scrollView.contentLayoutGuide.widthAnchor), - scrollView.contentLayoutGuide.bottomAnchor.constraint(equalTo: stackView.bottomAnchor), - ]) - - // photoview - avatarView.translatesAutoresizingMaskIntoConstraints = false - avatarView.addSubview(avatarButton) - NSLayoutConstraint.activate([ - avatarView.heightAnchor.constraint(equalToConstant: 92).priority(.required - 1), - ]) - avatarButton.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - avatarButton.heightAnchor.constraint(equalToConstant: 92).priority(.required - 1), - avatarButton.widthAnchor.constraint(equalToConstant: 92).priority(.required - 1), - avatarButton.leadingAnchor.constraint(greaterThanOrEqualTo: avatarView.leadingAnchor).priority(.required - 1), - avatarView.trailingAnchor.constraint(greaterThanOrEqualTo: avatarButton.trailingAnchor).priority(.required - 1), - avatarButton.centerXAnchor.constraint(equalTo: avatarView.centerXAnchor), - avatarButton.centerYAnchor.constraint(equalTo: avatarView.centerYAnchor), - ]) - - plusIconImageView.translatesAutoresizingMaskIntoConstraints = false - avatarView.addSubview(plusIconImageView) - NSLayoutConstraint.activate([ - plusIconImageView.centerXAnchor.constraint(equalTo: avatarButton.trailingAnchor), - plusIconImageView.centerYAnchor.constraint(equalTo: avatarButton.bottomAnchor), - ]) - - // textfield - NSLayoutConstraint.activate([ - usernameTextField.heightAnchor.constraint(equalToConstant: 50).priority(.required - 1), - displayNameTextField.heightAnchor.constraint(equalToConstant: 50).priority(.required - 1), - emailTextField.heightAnchor.constraint(equalToConstant: 50).priority(.required - 1), - passwordTextField.heightAnchor.constraint(equalToConstant: 50).priority(.required - 1), - ]) - - // password - formTableStackView.setCustomSpacing(6, after: passwordTextField) - formTableStackView.setCustomSpacing(32, after: passwordCheckLabel) + navigationActionView.backButton.addTarget(self, action: #selector(MastodonRegisterViewController.backButtonPressed(_:)), for: .touchUpInside) + navigationActionView.nextButton.addTarget(self, action: #selector(MastodonRegisterViewController.nextButtonPressed(_:)), for: .touchUpInside) - // return - if viewModel.approvalRequired { - reasonTextField.returnKeyType = .done - } else { - passwordTextField.returnKeyType = .done - } - - // button - formTableStackView.addArrangedSubview(buttonContainer) - signUpButton.translatesAutoresizingMaskIntoConstraints = false - buttonContainer.addSubview(signUpButton) - NSLayoutConstraint.activate([ - signUpButton.topAnchor.constraint(equalTo: buttonContainer.topAnchor), - signUpButton.leadingAnchor.constraint(equalTo: buttonContainer.leadingAnchor), - buttonContainer.trailingAnchor.constraint(equalTo: signUpButton.trailingAnchor), - buttonContainer.bottomAnchor.constraint(equalTo: signUpButton.bottomAnchor), - signUpButton.heightAnchor.constraint(equalToConstant: MastodonRegisterViewController.actionButtonHeight).priority(.required - 1), - buttonContainer.heightAnchor.constraint(equalToConstant: MastodonRegisterViewController.actionButtonHeight).priority(.required - 1), - ]) - signUpButton.setContentHuggingPriority(.defaultLow, for: .horizontal) - signUpButton.setContentHuggingPriority(.defaultLow, for: .vertical) - signUpButton.setContentCompressionResistancePriority(.required - 1, for: .vertical) - signUpButton.setContentCompressionResistancePriority(.required - 1, for: .horizontal) - buttonContainer.setContentCompressionResistancePriority(.required - 1, for: .vertical) - - Publishers.CombineLatest( - KeyboardResponderService.shared.state.eraseToAnyPublisher(), - KeyboardResponderService.shared.endFrame.eraseToAnyPublisher() - ) - .sink(receiveValue: { [weak self] state, endFrame in - guard let self = self else { return } - - guard state == .dock else { - self.scrollView.contentInset.bottom = 0.0 - self.scrollView.verticalScrollIndicatorInsets.bottom = 0.0 - return - } - - let contentFrame = self.view.convert(self.scrollView.frame, to: nil) - let padding = contentFrame.maxY - endFrame.minY - guard padding > 0 else { - self.scrollView.contentInset.bottom = 0.0 - self.scrollView.verticalScrollIndicatorInsets.bottom = 0.0 - return - } - - self.scrollView.contentInset.bottom = padding + 16 - self.scrollView.verticalScrollIndicatorInsets.bottom = padding + 16 - - if self.passwordTextField.isFirstResponder { - let contentFrame = self.buttonContainer.convert(self.signUpButton.frame, to: nil) - let labelPadding = contentFrame.maxY - endFrame.minY - let contentOffsetY = self.scrollView.contentOffset.y - DispatchQueue.main.async { - self.scrollView.setContentOffset(CGPoint(x: 0, y: contentOffsetY + labelPadding + 16.0), animated: true) - } - } - }) - .store(in: &disposeBag) - - avatarButton.publisher(for: \.isHighlighted, options: .new) - .receive(on: DispatchQueue.main) - .sink { [weak self] isHighlighted in - guard let self = self else { return } - let alpha: CGFloat = isHighlighted ? 0.6 : 1 - self.plusIconImageView.alpha = alpha - } - .store(in: &disposeBag) - - viewModel.isRegistering - .receive(on: DispatchQueue.main) - .sink { [weak self] isRegistering in - guard let self = self else { return } - isRegistering ? self.signUpButton.showLoading() : self.signUpButton.stopLoading() - } - .store(in: &disposeBag) - - viewModel.usernameValidateState - .receive(on: DispatchQueue.main) - .sink { [weak self] validateState in - guard let self = self else { return } - self.setTextFieldValidAppearance(self.usernameTextField, validateState: validateState) - } - .store(in: &disposeBag) - viewModel.usernameErrorPrompt - .receive(on: DispatchQueue.main) - .sink { [weak self] prompt in - guard let self = self else { return } - self.usernameErrorPromptLabel.attributedText = prompt - } - .store(in: &disposeBag) - viewModel.displayNameValidateState - .receive(on: DispatchQueue.main) - .sink { [weak self] validateState in - guard let self = self else { return } - self.setTextFieldValidAppearance(self.displayNameTextField, validateState: validateState) - } - .store(in: &disposeBag) - viewModel.emailValidateState - .receive(on: DispatchQueue.main) - .sink { [weak self] validateState in - guard let self = self else { return } - self.setTextFieldValidAppearance(self.emailTextField, validateState: validateState) - } - .store(in: &disposeBag) - viewModel.emailErrorPrompt - .receive(on: DispatchQueue.main) - .sink { [weak self] prompt in - guard let self = self else { return } - self.emailErrorPromptLabel.attributedText = prompt - } - .store(in: &disposeBag) - viewModel.passwordValidateState - .receive(on: DispatchQueue.main) - .sink { [weak self] validateState in - guard let self = self else { return } - self.setTextFieldValidAppearance(self.passwordTextField, validateState: validateState) - self.passwordCheckLabel.attributedText = MastodonRegisterViewModel.attributeStringForPassword(validateState: validateState) - } - .store(in: &disposeBag) - viewModel.passwordErrorPrompt - .receive(on: DispatchQueue.main) - .sink { [weak self] prompt in - guard let self = self else { return } - self.passwordErrorPromptLabel.attributedText = prompt - } - .store(in: &disposeBag) - viewModel.reasonErrorPrompt - .receive(on: DispatchQueue.main) - .sink { [weak self] prompt in - guard let self = self else { return } - self.reasonErrorPromptLabel.attributedText = prompt - } - .store(in: &disposeBag) - - viewModel.isAllValid + viewModel.$isAllValid .receive(on: DispatchQueue.main) .sink { [weak self] isAllValid in guard let self = self else { return } - self.signUpButton.isEnabled = isAllValid + self.navigationActionView.nextButton.isEnabled = isAllValid } .store(in: &disposeBag) - - viewModel.error - .receive(on: DispatchQueue.main) - .sink { [weak self] error in - guard let self = self else { return } - guard let error = error as? Mastodon.API.Error else { return } - let alertController = UIAlertController(for: error, title: "Sign Up Failure", preferredStyle: .alert) - let okAction = UIAlertAction(title: L10n.Common.Controls.Actions.ok, style: .default, handler: nil) - alertController.addAction(okAction) - self.coordinator.present( - scene: .alertController(alertController: alertController), - from: nil, - transition: .alertController(animated: true, completion: nil) - ) - } + + viewModel.setupDiffableDataSource(tableView: tableView) + + KeyboardResponderService + .configure( + scrollView: tableView, + layoutNeedsUpdate: viewModel.viewDidAppear.eraseToAnyPublisher() + ) .store(in: &disposeBag) - viewModel.avatarImage + // gesture + view.addGestureRecognizer(tapGestureRecognizer) + tapGestureRecognizer.addTarget(self, action: #selector(tapGestureRecognizerHandler)) + +// // return +// if viewModel.approvalRequired { +// reasonTextField.returnKeyType = .done +// } else { +// passwordTextField.returnKeyType = .done +// } +// +// viewModel.usernameValidateState +// .receive(on: DispatchQueue.main) +// .sink { [weak self] validateState in +// guard let self = self else { return } +// self.setTextFieldValidAppearance(self.usernameTextField, validateState: validateState) +// } +// .store(in: &disposeBag) +// viewModel.usernameErrorPrompt +// .receive(on: DispatchQueue.main) +// .sink { [weak self] prompt in +// guard let self = self else { return } +// self.usernameErrorPromptLabel.attributedText = prompt +// } +// .store(in: &disposeBag) +// viewModel.displayNameValidateState +// .receive(on: DispatchQueue.main) +// .sink { [weak self] validateState in +// guard let self = self else { return } +// self.setTextFieldValidAppearance(self.displayNameTextField, validateState: validateState) +// } +// .store(in: &disposeBag) +// viewModel.emailValidateState +// .receive(on: DispatchQueue.main) +// .sink { [weak self] validateState in +// guard let self = self else { return } +// self.setTextFieldValidAppearance(self.emailTextField, validateState: validateState) +// } +// .store(in: &disposeBag) +// viewModel.emailErrorPrompt +// .receive(on: DispatchQueue.main) +// .sink { [weak self] prompt in +// guard let self = self else { return } +// self.emailErrorPromptLabel.attributedText = prompt +// } +// .store(in: &disposeBag) +// viewModel.passwordValidateState +// .receive(on: DispatchQueue.main) +// .sink { [weak self] validateState in +// guard let self = self else { return } +// self.setTextFieldValidAppearance(self.passwordTextField, validateState: validateState) +// self.passwordCheckLabel.attributedText = MastodonRegisterViewModel.attributeStringForPassword(validateState: validateState) +// } +// .store(in: &disposeBag) +// viewModel.passwordErrorPrompt +// .receive(on: DispatchQueue.main) +// .sink { [weak self] prompt in +// guard let self = self else { return } +// self.passwordErrorPromptLabel.attributedText = prompt +// } +// .store(in: &disposeBag) +// viewModel.reasonErrorPrompt +// .receive(on: DispatchQueue.main) +// .sink { [weak self] prompt in +// guard let self = self else { return } +// self.reasonErrorPromptLabel.attributedText = prompt +// } +// .store(in: &disposeBag) +// viewModel.error +// .receive(on: DispatchQueue.main) +// .sink { [weak self] error in +// guard let self = self else { return } +// guard let error = error as? Mastodon.API.Error else { return } +// let alertController = UIAlertController(for: error, title: "Sign Up Failure", preferredStyle: .alert) +// let okAction = UIAlertAction(title: L10n.Common.Controls.Actions.ok, style: .default, handler: nil) +// alertController.addAction(okAction) +// self.coordinator.present( +// scene: .alertController(alertController: alertController), +// from: nil, +// transition: .alertController(animated: true, completion: nil) +// ) +// } +// .store(in: &disposeBag) +// + + viewModel.avatarMediaMenuActionPublisher .receive(on: DispatchQueue.main) - .sink{ [weak self] image in + .sink { [weak self] action in guard let self = self else { return } - self.avatarButton.menu = self.createMediaContextMenu() - if let avatar = image { - self.avatarButton.setImage(avatar, for: .normal) - } else { - let boldFont = UIFont.systemFont(ofSize: 42) - let configuration = UIImage.SymbolConfiguration(font: boldFont) - let image = UIImage(systemName: "person.fill.viewfinder", withConfiguration: configuration) - self.avatarButton.setImage(image?.withRenderingMode(UIImage.RenderingMode.alwaysTemplate), for: UIControl.State.normal) + switch action { + case .photoLibrary: + self.present(self.imagePicker, animated: true, completion: nil) + case .camera: + self.present(self.imagePickerController, animated: true, completion: nil) + case .browse: + self.present(self.documentPickerController, animated: true, completion: nil) + case .delete: + self.viewModel.avatarImage = nil } } .store(in: &disposeBag) - NotificationCenter.default - .publisher(for: UITextField.textDidChangeNotification, object: usernameTextField) + + viewModel.$isRegistering .receive(on: DispatchQueue.main) - .sink { [weak self] _ in + .sink { [weak self] isRegistering in guard let self = self else { return } - self.viewModel.username.value = self.usernameTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" + isRegistering ? self.navigationActionView.nextButton.showLoading() : self.navigationActionView.nextButton.stopLoading() } .store(in: &disposeBag) - - NotificationCenter.default - .publisher(for: UITextField.textDidChangeNotification, object: displayNameTextField) - .receive(on: DispatchQueue.main) - .sink { [weak self] _ in - guard let self = self else { return } - self.viewModel.displayName.value = self.displayNameTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - } - .store(in: &disposeBag) - - NotificationCenter.default - .publisher(for: UITextField.textDidChangeNotification, object: emailTextField) - .receive(on: DispatchQueue.main) - .sink { [weak self] _ in - guard let self = self else { return } - self.viewModel.email.value = self.emailTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - } - .store(in: &disposeBag) - - NotificationCenter.default - .publisher(for: UITextField.textDidChangeNotification, object: passwordTextField) - .receive(on: DispatchQueue.main) - .sink { [weak self] _ in - guard let self = self else { return } - self.viewModel.password.value = self.passwordTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - } - .store(in: &disposeBag) - - if viewModel.approvalRequired { - reasonTextField.delegate = self - NSLayoutConstraint.activate([ - reasonTextField.heightAnchor.constraint(equalToConstant: 50).priority(.defaultHigh), - ]) - reasonErrorPromptLabel.translatesAutoresizingMaskIntoConstraints = false - stackView.addSubview(reasonErrorPromptLabel) - NSLayoutConstraint.activate([ - reasonErrorPromptLabel.topAnchor.constraint(equalTo: reasonTextField.bottomAnchor, constant: 6), - reasonErrorPromptLabel.leadingAnchor.constraint(equalTo: reasonTextField.leadingAnchor), - reasonErrorPromptLabel.trailingAnchor.constraint(equalTo: reasonTextField.trailingAnchor), - ]) - - viewModel.reasonValidateState - .receive(on: DispatchQueue.main) - .sink { [weak self] validateState in - guard let self = self else { return } - self.setTextFieldValidAppearance(self.reasonTextField, validateState: validateState) - } - .store(in: &disposeBag) - NotificationCenter.default - .publisher(for: UITextField.textDidChangeNotification, object: reasonTextField) - .receive(on: DispatchQueue.main) - .sink { [weak self] _ in - guard let self = self else { return } - self.viewModel.reason.value = self.reasonTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - } - .store(in: &disposeBag) - } - - signUpButton.addTarget(self, action: #selector(MastodonRegisterViewController.signUpButtonPressed(_:)), for: .touchUpInside) } - override func viewDidLayoutSubviews() { - super.viewDidLayoutSubviews() - plusIconImageView.layer.cornerRadius = plusIconImageView.frame.width / 2 - plusIconImageView.layer.masksToBounds = true - } - - override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { - super.traitCollectionDidChange(previousTraitCollection) + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) - configureTitleLabel() - configureFormLayout() - } -} - -extension MastodonRegisterViewController: UITextFieldDelegate { - func textFieldDidBeginEditing(_ textField: UITextField) { - let text = textField.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - - switch textField { - case usernameTextField: - viewModel.username.value = text - case displayNameTextField: - viewModel.displayName.value = text - case emailTextField: - viewModel.email.value = text - case passwordTextField: - viewModel.password.value = text - case reasonTextField: - viewModel.reason.value = text - default: - break - } + viewModel.viewDidAppear.send() } - func textFieldDidEndEditing(_ textField: UITextField) { - let text = textField.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - - switch textField { - case usernameTextField: - viewModel.username.value = text - case displayNameTextField: - viewModel.displayName.value = text - case emailTextField: - viewModel.email.value = text - case passwordTextField: - viewModel.password.value = text - case reasonTextField: - viewModel.reason.value = text - default: - break - } - } - - func textFieldShouldReturn(_ textField: UITextField) -> Bool { - switch textField { - case usernameTextField: - displayNameTextField.becomeFirstResponder() - case displayNameTextField: - emailTextField.becomeFirstResponder() - case emailTextField: - passwordTextField.becomeFirstResponder() - case passwordTextField: - if viewModel.approvalRequired { - reasonTextField.becomeFirstResponder() - } else { - passwordTextField.resignFirstResponder() - } - case reasonTextField: - reasonTextField.resignFirstResponder() - default: - break - } - return true - } - - func showShadowWithColor(color: UIColor, textField: UITextField) { - // To apply Shadow - textField.layer.shadowOpacity = 1 - textField.layer.shadowRadius = 2.0 - textField.layer.shadowOffset = CGSize.zero - textField.layer.shadowColor = color.cgColor - // textField.layer.shadowPath = UIBezierPath(roundedRect: textField.bounds, byRoundingCorners: .allCorners, cornerRadii: CGSize(width: 2.0, height: 2.0)).cgPath - } - - private func setTextFieldValidAppearance(_ textField: UITextField, validateState: MastodonRegisterViewModel.ValidateState) { - switch validateState { - case .empty: - showShadowWithColor(color: textField.isFirstResponder ? Asset.Colors.brandBlue.color : .clear, textField: textField) - case .valid: - showShadowWithColor(color: Asset.Colors.TextField.valid.color, textField: textField) - case .invalid: - showShadowWithColor(color: Asset.Colors.TextField.invalid.color, textField: textField) - } - } } extension MastodonRegisterViewController { - private func configureTitleLabel() { - switch traitCollection.horizontalSizeClass { - case .regular: - navigationItem.largeTitleDisplayMode = .always - navigationItem.title = L10n.Scene.ServerPicker.title.replacingOccurrences(of: "\n", with: " ") - largeTitleLabel.isHidden = true - default: - navigationItem.largeTitleDisplayMode = .never - navigationItem.title = nil - largeTitleLabel.isHidden = false - } - } - private func configureFormLayout() { - switch traitCollection.horizontalSizeClass { - case .regular: - stackView.axis = .horizontal - stackView.distribution = .fillProportionally - default: - stackView.axis = .vertical - stackView.distribution = .fill - } - } - - private func configureMargin() { - - } -} - -extension MastodonRegisterViewController { @objc private func tapGestureRecognizerHandler(_ sender: UITapGestureRecognizer) { view.endEditing(true) } - @objc private func signUpButtonPressed(_ sender: UIButton) { - os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", (#file as NSString).lastPathComponent, #line, #function) - guard viewModel.isAllValid.value else { return } - - guard !viewModel.isRegistering.value else { return } - viewModel.isRegistering.value = true + @objc private func backButtonPressed(_ sender: UIButton) { + logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public)") + navigationController?.popViewController(animated: true) + } - let username = viewModel.username.value - let email = viewModel.email.value - let password = viewModel.password.value + @objc private func nextButtonPressed(_ sender: UIButton) { + logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public)") + + guard viewModel.isAllValid else { return } + + guard !viewModel.isRegistering else { return } + viewModel.isRegistering = true + + let username = viewModel.username + let email = viewModel.email + let password = viewModel.password + let reason = viewModel.reason let locale: String = { guard let url = Bundle.main.url(forResource: "local-codes", withExtension: "json"), @@ -814,7 +291,7 @@ extension MastodonRegisterViewController { guard localCode[code] != nil else { return "en" } return code }() - + // pick device preferred language guard let identifier = Locale.preferredLanguages.first else { return fallbackLanguageCode @@ -843,19 +320,19 @@ extension MastodonRegisterViewController { return languageCode } return firstMatchExtendCode - + }() let query = Mastodon.API.Account.RegisterQuery( - reason: viewModel.reason.value, + reason: reason, username: username, email: email, password: password, agreement: true, // user confirmed in the server rules scene locale: locale ) - + var retryCount = 0 - + // register without show server rules context.apiService.accountRegister( domain: viewModel.domain, @@ -864,7 +341,7 @@ extension MastodonRegisterViewController { ) .tryCatch { [weak self] error -> AnyPublisher, Error> in guard let self = self else { throw error } - guard let error = self.viewModel.error.value as? Mastodon.API.Error, + guard let error = self.viewModel.error as? Mastodon.API.Error, case let .generic(errorEntity) = error.mastodonError, errorEntity.error == "Validation failed: Locale is not included in the list" else { @@ -891,10 +368,10 @@ extension MastodonRegisterViewController { .receive(on: DispatchQueue.main) .sink { [weak self] completion in guard let self = self else { return } - self.viewModel.isRegistering.value = false + self.viewModel.isRegistering = false switch completion { case .failure(let error): - self.viewModel.error.send(error) + self.viewModel.error = error case .finished: break } @@ -902,9 +379,9 @@ extension MastodonRegisterViewController { guard let self = self else { return } let userToken = response.value let updateCredentialQuery: Mastodon.API.Account.UpdateCredentialQuery = { - let displayName: String? = self.viewModel.displayName.value.isEmpty ? nil : self.viewModel.displayName.value + let displayName: String? = self.viewModel.name.isEmpty ? nil : self.viewModel.name let avatar: Mastodon.Query.MediaAttachment? = { - guard let avatarImage = self.viewModel.avatarImage.value else { return nil } + guard let avatarImage = self.viewModel.avatarImage else { return nil } guard avatarImage.size.width <= MastodonRegisterViewController.avatarImageMaxSizeInPixel.width else { return .png(avatarImage.af.imageScaled(to: MastodonRegisterViewController.avatarImageMaxSizeInPixel).pngData()) } @@ -920,4 +397,67 @@ extension MastodonRegisterViewController { } .store(in: &disposeBag) } + +} + +extension MastodonRegisterViewController: UITextFieldDelegate { +// func textFieldDidBeginEditing(_ textField: UITextField) { +// let text = textField.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" +// +// switch textField { +// case usernameTextField: +// viewModel.username.value = text +// case displayNameTextField: +// viewModel.displayName.value = text +// case emailTextField: +// viewModel.email.value = text +// case passwordTextField: +// viewModel.password.value = text +// case reasonTextField: +// viewModel.reason.value = text +// default: +// break +// } +// } +// +// func textFieldDidEndEditing(_ textField: UITextField) { +// let text = textField.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" +// +// switch textField { +// case usernameTextField: +// viewModel.username.value = text +// case displayNameTextField: +// viewModel.displayName.value = text +// case emailTextField: +// viewModel.email.value = text +// case passwordTextField: +// viewModel.password.value = text +// case reasonTextField: +// viewModel.reason.value = text +// default: +// break +// } +// } +// +// func textFieldShouldReturn(_ textField: UITextField) -> Bool { +// switch textField { +// case usernameTextField: +// displayNameTextField.becomeFirstResponder() +// case displayNameTextField: +// emailTextField.becomeFirstResponder() +// case emailTextField: +// passwordTextField.becomeFirstResponder() +// case passwordTextField: +// if viewModel.approvalRequired { +// reasonTextField.becomeFirstResponder() +// } else { +// passwordTextField.resignFirstResponder() +// } +// case reasonTextField: +// reasonTextField.resignFirstResponder() +// default: +// break +// } +// return true +// } } diff --git a/Mastodon/Scene/Onboarding/Register/MastodonRegisterViewModel+Diffable.swift b/Mastodon/Scene/Onboarding/Register/MastodonRegisterViewModel+Diffable.swift new file mode 100644 index 00000000..e075f47c --- /dev/null +++ b/Mastodon/Scene/Onboarding/Register/MastodonRegisterViewModel+Diffable.swift @@ -0,0 +1,231 @@ +// +// MastodonRegisterViewModel+Diffable.swift +// Mastodon +// +// Created by MainasuK on 2022-1-5. +// + +import UIKit +import Combine + +extension MastodonRegisterViewModel { + func setupDiffableDataSource( + tableView: UITableView + ) { + tableView.register(OnboardingHeadlineTableViewCell.self, forCellReuseIdentifier: String(describing: OnboardingHeadlineTableViewCell.self)) + tableView.register(MastodonRegisterAvatarTableViewCell.self, forCellReuseIdentifier: String(describing: MastodonRegisterAvatarTableViewCell.self)) + tableView.register(MastodonRegisterTextFieldTableViewCell.self, forCellReuseIdentifier: String(describing: MastodonRegisterTextFieldTableViewCell.self)) + tableView.register(MastodonRegisterPasswordHintTableViewCell.self, forCellReuseIdentifier: String(describing: MastodonRegisterPasswordHintTableViewCell.self)) + + diffableDataSource = UITableViewDiffableDataSource(tableView: tableView) { tableView, indexPath, item in + switch item { + case .header: + let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: OnboardingHeadlineTableViewCell.self), for: indexPath) as! OnboardingHeadlineTableViewCell + cell.titleLabel.text = L10n.Scene.Register.title + cell.subTitleLabel.isHidden = true + return cell + case .avatar: + let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: MastodonRegisterAvatarTableViewCell.self), for: indexPath) as! MastodonRegisterAvatarTableViewCell + self.configureAvatar(cell: cell) + return cell + case .name: + let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: MastodonRegisterTextFieldTableViewCell.self), for: indexPath) as! MastodonRegisterTextFieldTableViewCell + cell.setupTextViewPlaceholder(text: L10n.Scene.Register.Input.DisplayName.placeholder) + cell.textField.keyboardType = .default + cell.textField.autocapitalizationType = .words + cell.textField.text = self.name + NotificationCenter.default.publisher(for: UITextField.textDidChangeNotification, object: cell.textField) + .receive(on: DispatchQueue.main) + .compactMap { notification in + guard let textField = notification.object as? UITextField else { + assertionFailure() + return nil + } + return textField.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" + } + .assign(to: \.name, on: self) + .store(in: &cell.disposeBag) + return cell + case .username: + let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: MastodonRegisterTextFieldTableViewCell.self), for: indexPath) as! MastodonRegisterTextFieldTableViewCell + cell.setupTextViewRightView(text: "@" + self.domain) + cell.setupTextViewPlaceholder(text: L10n.Scene.Register.Input.Username.placeholder) + cell.textField.keyboardType = .alphabet + cell.textField.autocorrectionType = .no + cell.textField.text = self.username + NotificationCenter.default.publisher(for: UITextField.textDidChangeNotification, object: cell.textField) + .receive(on: DispatchQueue.main) + .compactMap { notification in + guard let textField = notification.object as? UITextField else { + assertionFailure() + return nil + } + return textField.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" + } + .assign(to: \.username, on: self) + .store(in: &cell.disposeBag) + self.configureTextFieldCell(cell: cell, validateState: self.$usernameValidateState) + return cell + case .email: + let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: MastodonRegisterTextFieldTableViewCell.self), for: indexPath) as! MastodonRegisterTextFieldTableViewCell + cell.setupTextViewPlaceholder(text: L10n.Scene.Register.Input.Email.placeholder) + cell.textField.keyboardType = .emailAddress + cell.textField.autocorrectionType = .no + cell.textField.text = self.email + NotificationCenter.default.publisher(for: UITextField.textDidChangeNotification, object: cell.textField) + .receive(on: DispatchQueue.main) + .compactMap { notification in + guard let textField = notification.object as? UITextField else { + assertionFailure() + return nil + } + return textField.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" + } + .assign(to: \.email, on: self) + .store(in: &cell.disposeBag) + self.configureTextFieldCell(cell: cell, validateState: self.$emailValidateState) + return cell + case .password: + let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: MastodonRegisterTextFieldTableViewCell.self), for: indexPath) as! MastodonRegisterTextFieldTableViewCell + cell.setupTextViewPlaceholder(text: L10n.Scene.Register.Input.Password.placeholder) + cell.textField.keyboardType = .alphabet + cell.textField.autocorrectionType = .no + cell.textField.isSecureTextEntry = true + cell.textField.text = self.password + NotificationCenter.default.publisher(for: UITextField.textDidChangeNotification, object: cell.textField) + .receive(on: DispatchQueue.main) + .compactMap { notification in + guard let textField = notification.object as? UITextField else { + assertionFailure() + return nil + } + return textField.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" + } + .assign(to: \.password, on: self) + .store(in: &cell.disposeBag) + self.configureTextFieldCell(cell: cell, validateState: self.$passwordValidateState) + return cell + case .hint: + let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: MastodonRegisterPasswordHintTableViewCell.self), for: indexPath) as! MastodonRegisterPasswordHintTableViewCell + return cell + case .reason: + let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: MastodonRegisterTextFieldTableViewCell.self), for: indexPath) as! MastodonRegisterTextFieldTableViewCell + cell.setupTextViewPlaceholder(text: L10n.Scene.Register.Input.Invite.registrationUserInviteRequest) + cell.textField.keyboardType = .default + cell.textField.text = self.reason + NotificationCenter.default.publisher(for: UITextField.textDidChangeNotification, object: cell.textField) + .receive(on: DispatchQueue.main) + .compactMap { notification in + guard let textField = notification.object as? UITextField else { + assertionFailure() + return nil + } + return textField.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" + } + .assign(to: \.reason, on: self) + .store(in: &cell.disposeBag) + self.configureTextFieldCell(cell: cell, validateState: self.$reasonValidateState) + return cell + default: + assertionFailure() + return UITableViewCell() + } + } + + var snapshot = NSDiffableDataSourceSnapshot() + snapshot.appendSections([.main]) + snapshot.appendItems([.header], toSection: .main) + snapshot.appendItems([.avatar, .name, .username, .email, .password, .hint], toSection: .main) + if approvalRequired { + snapshot.appendItems([.reason], toSection: .main) + } + diffableDataSource?.applySnapshot(snapshot, animated: false, completion: nil) + } +} + +extension MastodonRegisterViewModel { + private func configureAvatar(cell: MastodonRegisterAvatarTableViewCell) { + self.$avatarImage + .receive(on: DispatchQueue.main) + .sink { [weak self, weak cell] image in + guard let self = self else { return } + guard let cell = cell else { return } + let image = image ?? Asset.Scene.Onboarding.avatarPlaceholder.image + cell.avatarButton.setImage(image, for: .normal) + cell.avatarButton.menu = self.createAvatarMediaContextMenu() + cell.avatarButton.showsMenuAsPrimaryAction = true + } + .store(in: &cell.disposeBag) + } + + enum AvatarMediaMenuAction { + case photoLibrary + case camera + case browse + case delete + } + + private func createAvatarMediaContextMenu() -> UIMenu { + var children: [UIMenuElement] = [] + + // Photo Library + let photoLibraryAction = UIAction(title: L10n.Scene.Compose.MediaSelection.photoLibrary, image: UIImage(systemName: "rectangle.on.rectangle"), identifier: nil, discoverabilityTitle: nil, attributes: [], state: .off) { [weak self] _ in + guard let self = self else { return } + self.avatarMediaMenuActionPublisher.send(.photoLibrary) + } + children.append(photoLibraryAction) + + // Camera + if UIImagePickerController.isSourceTypeAvailable(.camera) { + let cameraAction = UIAction(title: L10n.Scene.Compose.MediaSelection.camera, image: UIImage(systemName: "camera"), identifier: nil, discoverabilityTitle: nil, attributes: [], state: .off, handler: { [weak self] _ in + guard let self = self else { return } + self.avatarMediaMenuActionPublisher.send(.camera) + }) + children.append(cameraAction) + } + + // Browse + let browseAction = UIAction(title: L10n.Scene.Compose.MediaSelection.browse, image: UIImage(systemName: "ellipsis"), identifier: nil, discoverabilityTitle: nil, attributes: [], state: .off) { [weak self] _ in + guard let self = self else { return } + self.avatarMediaMenuActionPublisher.send(.browse) + } + children.append(browseAction) + + // Delete + if avatarImage != nil { + let deleteAction = UIAction(title: L10n.Scene.Register.Input.Avatar.delete, image: UIImage(systemName: "delete.left"), identifier: nil, discoverabilityTitle: nil, attributes: [.destructive], state: .off) { [weak self] _ in + guard let self = self else { return } + self.avatarMediaMenuActionPublisher.send(.delete) + } + children.append(deleteAction) + } + + return UIMenu(title: "", image: nil, identifier: nil, options: .displayInline, children: children) + } + + private func configureTextFieldCell( + cell: MastodonRegisterTextFieldTableViewCell, + validateState: Published.Publisher + ) { + Publishers.CombineLatest( + validateState, + cell.textField.publisher(for: \.isFirstResponder) + ) + .receive(on: DispatchQueue.main) + .sink { [weak cell] validateState, isFirstResponder in + guard let cell = cell else { return } + switch validateState { + case .empty: + cell.textFieldShadowContainer.shadowColor = isFirstResponder ? Asset.Colors.brandBlue.color : .black + cell.textFieldShadowContainer.shadowAlpha = isFirstResponder ? 1 : 0.25 + case .valid: + cell.textFieldShadowContainer.shadowColor = Asset.Colors.TextField.valid.color + cell.textFieldShadowContainer.shadowAlpha = 1 + case .invalid: + cell.textFieldShadowContainer.shadowColor = Asset.Colors.TextField.invalid.color + cell.textFieldShadowContainer.shadowAlpha = 1 + } + } + .store(in: &cell.disposeBag) + } +} diff --git a/Mastodon/Scene/Onboarding/Register/MastodonRegisterViewModel.swift b/Mastodon/Scene/Onboarding/Register/MastodonRegisterViewModel.swift index 6c9e0754..5971cc74 100644 --- a/Mastodon/Scene/Onboarding/Register/MastodonRegisterViewModel.swift +++ b/Mastodon/Scene/Onboarding/Register/MastodonRegisterViewModel.swift @@ -14,18 +14,19 @@ final class MastodonRegisterViewModel { var disposeBag = Set() // input + let context: AppContext let domain: String let authenticateInfo: AuthenticationViewModel.AuthenticateInfo let instance: Mastodon.Entity.Instance let applicationToken: Mastodon.Entity.Token - let context: AppContext - - let username = CurrentValueSubject("") - let displayName = CurrentValueSubject("") - let email = CurrentValueSubject("") - let password = CurrentValueSubject("") - let reason = CurrentValueSubject("") - let avatarImage = CurrentValueSubject(nil) + let viewDidAppear = CurrentValueSubject(Void()) + + @Published var avatarImage: UIImage? = nil + @Published var name = "" + @Published var username = "" + @Published var email = "" + @Published var password = "" + @Published var reason = "" let usernameErrorPrompt = CurrentValueSubject(nil) let emailErrorPrompt = CurrentValueSubject(nil) @@ -33,21 +34,25 @@ final class MastodonRegisterViewModel { let reasonErrorPrompt = CurrentValueSubject(nil) // output + var diffableDataSource: UITableViewDiffableDataSource? let approvalRequired: Bool let applicationAuthorization: Mastodon.API.OAuth.Authorization - let usernameValidateState = CurrentValueSubject(.empty) - let displayNameValidateState = CurrentValueSubject(.empty) - let emailValidateState = CurrentValueSubject(.empty) - let passwordValidateState = CurrentValueSubject(.empty) - let reasonValidateState = CurrentValueSubject(.empty) + + @Published var usernameValidateState: ValidateState = .empty + @Published var displayNameValidateState: ValidateState = .empty + @Published var emailValidateState: ValidateState = .empty + @Published var passwordValidateState: ValidateState = .empty + @Published var reasonValidateState: ValidateState = .empty - let isRegistering = CurrentValueSubject(false) - let isAllValid = CurrentValueSubject(false) - let error = CurrentValueSubject(nil) + @Published var isRegistering = false + @Published var isAllValid = false + @Published var error: Error? = nil + + let avatarMediaMenuActionPublisher = PassthroughSubject() init( - domain: String, context: AppContext, + domain: String, authenticateInfo: AuthenticationViewModel.AuthenticateInfo, instance: Mastodon.Entity.Instance, applicationToken: Mastodon.Entity.Token @@ -60,7 +65,15 @@ final class MastodonRegisterViewModel { self.approvalRequired = instance.approvalRequired ?? false self.applicationAuthorization = Mastodon.API.OAuth.Authorization(accessToken: applicationToken.accessToken) - username + $name + .map { name in + guard !name.isEmpty else { return .empty } + return .valid + } + .assign(to: \.displayNameValidateState, on: self) + .store(in: &disposeBag) + + $username .map { username in guard !username.isEmpty else { return .empty } var isValid = true @@ -79,114 +92,120 @@ final class MastodonRegisterViewModel { } return isValid ? .valid : .invalid } - .assign(to: \.value, on: usernameValidateState) + .assign(to: \.usernameValidateState, on: self) .store(in: &disposeBag) - username - .filter { !$0.isEmpty } - .debounce(for: .milliseconds(300), scheduler: DispatchQueue.main) - .removeDuplicates() - .compactMap { [weak self] text -> AnyPublisher, Error>, Never>? in - guard let self = self else { return nil } - let query = Mastodon.API.Account.AccountLookupQuery(acct: text) - return context.apiService.accountLookup(domain: domain, query: query, authorization: self.applicationAuthorization) - .map { - response -> Result, Error> in - Result.success(response) - } - .catch { error in - Just(Result.failure(error)) - } - .eraseToAnyPublisher() - } - .switchToLatest() - .sink { [weak self] result in - guard let self = self else { return } - switch result { - case .success: - let text = L10n.Scene.Register.Error.Reason.taken(L10n.Scene.Register.Error.Item.username) - self.usernameErrorPrompt.value = MastodonRegisterViewModel.errorPromptAttributedString(for: text) - self.usernameValidateState.value = .invalid - case .failure: - break - } - } - .store(in: &disposeBag) - - usernameValidateState - .sink { [weak self] validateState in - if validateState == .valid { - self?.usernameErrorPrompt.value = nil - } - } - .store(in: &disposeBag) + // TODO: check username available +// username +// .filter { !$0.isEmpty } +// .debounce(for: .milliseconds(300), scheduler: DispatchQueue.main) +// .removeDuplicates() +// .compactMap { [weak self] text -> AnyPublisher, Error>, Never>? in +// guard let self = self else { return nil } +// let query = Mastodon.API.Account.AccountLookupQuery(acct: text) +// return context.apiService.accountLookup(domain: domain, query: query, authorization: self.applicationAuthorization) +// .map { +// response -> Result, Error> in +// Result.success(response) +// } +// .catch { error in +// Just(Result.failure(error)) +// } +// .eraseToAnyPublisher() +// } +// .switchToLatest() +// .sink { [weak self] result in +// guard let self = self else { return } +// switch result { +// case .success: +// let text = L10n.Scene.Register.Error.Reason.taken(L10n.Scene.Register.Error.Item.username) +// self.usernameErrorPrompt.value = MastodonRegisterViewModel.errorPromptAttributedString(for: text) +// self.usernameValidateState.value = .invalid +// case .failure: +// break +// } +// } +// .store(in: &disposeBag) +// +// usernameValidateState +// .sink { [weak self] validateState in +// if validateState == .valid { +// self?.usernameErrorPrompt.value = nil +// } +// } +// .store(in: &disposeBag) - displayName - .map { displayname in - guard !displayname.isEmpty else { return .empty } - return .valid - } - .assign(to: \.value, on: displayNameValidateState) - .store(in: &disposeBag) - email + $email .map { email in guard !email.isEmpty else { return .empty } return MastodonRegisterViewModel.isValidEmail(email) ? .valid : .invalid } - .assign(to: \.value, on: emailValidateState) + .assign(to: \.emailValidateState, on: self) .store(in: &disposeBag) - password + + $password .map { password in guard !password.isEmpty else { return .empty } return password.count >= 8 ? .valid : .invalid } - .assign(to: \.value, on: passwordValidateState) + .assign(to: \.passwordValidateState, on: self) .store(in: &disposeBag) + if approvalRequired { - reason + $reason .map { invite in guard !invite.isEmpty else { return .empty } return .valid } - .assign(to: \.value, on: reasonValidateState) + .assign(to: \.reasonValidateState, on: self) .store(in: &disposeBag) } - error - .sink { [weak self] error in - guard let self = self else { return } - let error = error as? Mastodon.API.Error - let mastodonError = error?.mastodonError - if case let .generic(genericMastodonError) = mastodonError, - let details = genericMastodonError.details - { - self.usernameErrorPrompt.value = details.usernameErrorDescriptions.first.flatMap { MastodonRegisterViewModel.errorPromptAttributedString(for: $0) } - self.emailErrorPrompt.value = details.emailErrorDescriptions.first.flatMap { MastodonRegisterViewModel.errorPromptAttributedString(for: $0) } - self.passwordErrorPrompt.value = details.passwordErrorDescriptions.first.flatMap { MastodonRegisterViewModel.errorPromptAttributedString(for: $0) } - self.reasonErrorPrompt.value = details.reasonErrorDescriptions.first.flatMap { MastodonRegisterViewModel.errorPromptAttributedString(for: $0) } - } else { - self.usernameErrorPrompt.value = nil - self.emailErrorPrompt.value = nil - self.passwordErrorPrompt.value = nil - self.reasonErrorPrompt.value = nil - } - } - .store(in: &disposeBag) - +// error +// .sink { [weak self] error in +// guard let self = self else { return } +// let error = error as? Mastodon.API.Error +// let mastodonError = error?.mastodonError +// if case let .generic(genericMastodonError) = mastodonError, +// let details = genericMastodonError.details +// { +// self.usernameErrorPrompt.value = details.usernameErrorDescriptions.first.flatMap { MastodonRegisterViewModel.errorPromptAttributedString(for: $0) } +// self.emailErrorPrompt.value = details.emailErrorDescriptions.first.flatMap { MastodonRegisterViewModel.errorPromptAttributedString(for: $0) } +// self.passwordErrorPrompt.value = details.passwordErrorDescriptions.first.flatMap { MastodonRegisterViewModel.errorPromptAttributedString(for: $0) } +// self.reasonErrorPrompt.value = details.reasonErrorDescriptions.first.flatMap { MastodonRegisterViewModel.errorPromptAttributedString(for: $0) } +// } else { +// self.usernameErrorPrompt.value = nil +// self.emailErrorPrompt.value = nil +// self.passwordErrorPrompt.value = nil +// self.reasonErrorPrompt.value = nil +// } +// } +// .store(in: &disposeBag) +// let publisherOne = Publishers.CombineLatest4( - usernameValidateState.eraseToAnyPublisher(), - displayNameValidateState.eraseToAnyPublisher(), - emailValidateState.eraseToAnyPublisher(), - passwordValidateState.eraseToAnyPublisher() + $usernameValidateState, + $displayNameValidateState, + $emailValidateState, + $passwordValidateState ) - .map { $0.0 == .valid && $0.1 == .valid && $0.2 == .valid && $0.3 == .valid } + .map { + $0.0 == .valid && + $0.1 == .valid && + $0.2 == .valid && + $0.3 == .valid + } + + let publisherTwo = $reasonValidateState.map { reasonValidateState -> Bool in + guard self.approvalRequired else { return true } + return reasonValidateState == .valid + } Publishers.CombineLatest( publisherOne, - approvalRequired ? reasonValidateState.map { $0 == .valid }.eraseToAnyPublisher() : Just(true).eraseToAnyPublisher() + publisherTwo ) .map { $0 && $1 } - .assign(to: \.value, on: isAllValid) + .assign(to: \.isAllValid, on: self) .store(in: &disposeBag) } } diff --git a/Mastodon/Scene/Onboarding/ServerRules/ServerRulesTableViewCell.swift b/Mastodon/Scene/Onboarding/ServerRules/Cell/ServerRulesTableViewCell.swift similarity index 100% rename from Mastodon/Scene/Onboarding/ServerRules/ServerRulesTableViewCell.swift rename to Mastodon/Scene/Onboarding/ServerRules/Cell/ServerRulesTableViewCell.swift diff --git a/Mastodon/Scene/Onboarding/ServerRules/MastodonServerRulesViewController.swift b/Mastodon/Scene/Onboarding/ServerRules/MastodonServerRulesViewController.swift index 6633f6c7..f6369282 100644 --- a/Mastodon/Scene/Onboarding/ServerRules/MastodonServerRulesViewController.swift +++ b/Mastodon/Scene/Onboarding/ServerRules/MastodonServerRulesViewController.swift @@ -26,24 +26,6 @@ final class MastodonServerRulesViewController: UIViewController, NeedsDependency let stackView = UIStackView() - let largeTitleLabel: UILabel = { - let label = UILabel() - label.font = MastodonServerRulesViewController.largeTitleFont - label.textColor = MastodonServerRulesViewController.largeTitleTextColor - label.text = L10n.Scene.ServerRules.title - label.numberOfLines = 0 - return label - }() - - private(set) lazy var subtitleLabel: UILabel = { - let label = UILabel() - label.font = MastodonServerRulesViewController.subTitleFont - label.textColor = MastodonServerRulesViewController.subTitleTextColor - label.text = L10n.Scene.ServerRules.subtitle(viewModel.domain) - label.numberOfLines = 0 - return label - }() - let tableView: UITableView = { let tableView = UITableView() tableView.register(OnboardingHeadlineTableViewCell.self, forCellReuseIdentifier: String(describing: OnboardingHeadlineTableViewCell.self)) @@ -135,7 +117,13 @@ extension MastodonServerRulesViewController { @objc private func nextButtonPressed(_ sender: UIButton) { logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public)") - let viewModel = MastodonRegisterViewModel(domain: viewModel.domain, context: context, authenticateInfo: viewModel.authenticateInfo, instance: viewModel.instance, applicationToken: viewModel.applicationToken) + let viewModel = MastodonRegisterViewModel( + context: context, + domain: viewModel.domain, + authenticateInfo: viewModel.authenticateInfo, + instance: viewModel.instance, + applicationToken: viewModel.applicationToken + ) coordinator.present(scene: .mastodonRegister(viewModel: viewModel), from: self, transition: .show) } diff --git a/Mastodon/Scene/Profile/Header/ProfileHeaderViewModel.swift b/Mastodon/Scene/Profile/Header/ProfileHeaderViewModel.swift index e8405b6a..40883120 100644 --- a/Mastodon/Scene/Profile/Header/ProfileHeaderViewModel.swift +++ b/Mastodon/Scene/Profile/Header/ProfileHeaderViewModel.swift @@ -14,6 +14,7 @@ import MastodonMeta final class ProfileHeaderViewModel { + static let avatarImageMaxSizeInPixel = CGSize(width: 400, height: 400) static let maxProfileFieldCount = 4 var disposeBag = Set() @@ -190,8 +191,8 @@ extension ProfileHeaderViewModel { let image: UIImage? = { guard case let .image(_image) = editProfileInfo.avatarImageResource.value else { return nil } guard let image = _image else { return nil } - guard image.size.width <= MastodonRegisterViewController.avatarImageMaxSizeInPixel.width else { - return image.af.imageScaled(to: MastodonRegisterViewController.avatarImageMaxSizeInPixel) + guard image.size.width <= ProfileHeaderViewModel.avatarImageMaxSizeInPixel.width else { + return image.af.imageScaled(to: ProfileHeaderViewModel.avatarImageMaxSizeInPixel) } return image }() diff --git a/MastodonSDK/Sources/MastodonUI/Service/KeyboardResponderService.swift b/MastodonSDK/Sources/MastodonUI/Service/KeyboardResponderService.swift index 65328afa..db600a67 100644 --- a/MastodonSDK/Sources/MastodonUI/Service/KeyboardResponderService.swift +++ b/MastodonSDK/Sources/MastodonUI/Service/KeyboardResponderService.swift @@ -90,3 +90,47 @@ extension KeyboardResponderService { case dock } } + +extension KeyboardResponderService { + public static func configure( + scrollView: UIScrollView, + layoutNeedsUpdate: AnyPublisher, + additionalSafeAreaInsets: AnyPublisher = CurrentValueSubject(.zero).eraseToAnyPublisher() + ) -> AnyCancellable { + let tuple = Publishers.CombineLatest3( + KeyboardResponderService.shared.isShow, + KeyboardResponderService.shared.state, + KeyboardResponderService.shared.endFrame + ) + + return Publishers.CombineLatest3( + tuple, + layoutNeedsUpdate, + additionalSafeAreaInsets + ) + .sink(receiveValue: { [weak scrollView] tuple, _, additionalSafeAreaInsets in + guard let scrollView = scrollView else { return } + guard let view = scrollView.superview else { return } + + let (isShow, state, endFrame) = tuple + + guard isShow, state == .dock else { + scrollView.contentInset.bottom = additionalSafeAreaInsets.bottom + scrollView.verticalScrollIndicatorInsets.bottom = additionalSafeAreaInsets.bottom + return + } + + // isShow AND dock state + let contentFrame = view.convert(scrollView.frame, to: nil) + let padding = contentFrame.maxY - endFrame.minY + guard padding > 0 else { + scrollView.contentInset.bottom = additionalSafeAreaInsets.bottom + scrollView.verticalScrollIndicatorInsets.bottom = additionalSafeAreaInsets.bottom + return + } + + scrollView.contentInset.bottom = padding - scrollView.safeAreaInsets.bottom + additionalSafeAreaInsets.bottom + scrollView.verticalScrollIndicatorInsets.bottom = padding - scrollView.safeAreaInsets.bottom + additionalSafeAreaInsets.bottom + }) + } +} diff --git a/MastodonSDK/Sources/MastodonUI/View/Container/ShadowBackgroundContainer.swift b/MastodonSDK/Sources/MastodonUI/View/Container/ShadowBackgroundContainer.swift index 6b45a050..3f2f5df4 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Container/ShadowBackgroundContainer.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Container/ShadowBackgroundContainer.swift @@ -10,6 +10,18 @@ import MastodonExtension public final class ShadowBackgroundContainer: UIView { + public var shadowAlpha: CGFloat = 0.25 { + didSet { setNeedsLayout() } + } + + public var shadowColor: UIColor = .black { + didSet { setNeedsLayout() } + } + + public var cornerRadius: CGFloat = 10 { + didSet { setNeedsLayout() } + } + public let shadowLayer = CALayer() override init(frame: CGRect) { @@ -34,15 +46,15 @@ extension ShadowBackgroundContainer { shadowLayer.frame = bounds shadowLayer.setupShadow( - color: .black, - alpha: 0.25, + color: shadowColor, + alpha: Float(shadowAlpha), x: 0, y: 1, blur: 2, spread: 0, roundedRect: bounds, byRoundingCorners: .allCorners, - cornerRadii: CGSize(width: 10, height: 10) + cornerRadii: CGSize(width: cornerRadius, height: cornerRadius) ) } } From 548e4cc28f2653016436287f29ef6f7ca0fcac6c Mon Sep 17 00:00:00 2001 From: CMK Date: Fri, 7 Jan 2022 19:11:56 +0800 Subject: [PATCH 10/12] feat: update email confirm scene UI --- Localization/app.json | 2 +- .../MastodonConfirmEmailViewController.swift | 45 +++++++++---------- .../MastodonRegisterAvatarTableViewCell.swift | 37 +++++++++++++++ ...donRegisterPasswordHintTableViewCell.swift | 2 +- .../MastodonRegisterViewController.swift | 14 +++--- 5 files changed, 67 insertions(+), 33 deletions(-) diff --git a/Localization/app.json b/Localization/app.json index 5e74bc69..2edca199 100644 --- a/Localization/app.json +++ b/Localization/app.json @@ -303,7 +303,7 @@ "subtitle": "Tap the link we emailed to you to verify your account.", "button": { "open_email_app": "Open Email App", - "dont_receive_email": "I never got an email" + "resend": "Resend" }, "dont_receive_email": { "title": "Check your email", diff --git a/Mastodon/Scene/Onboarding/ConfirmEmail/MastodonConfirmEmailViewController.swift b/Mastodon/Scene/Onboarding/ConfirmEmail/MastodonConfirmEmailViewController.swift index 0718938f..585dcb31 100644 --- a/Mastodon/Scene/Onboarding/ConfirmEmail/MastodonConfirmEmailViewController.swift +++ b/Mastodon/Scene/Onboarding/ConfirmEmail/MastodonConfirmEmailViewController.swift @@ -46,21 +46,11 @@ final class MastodonConfirmEmailViewController: UIViewController, NeedsDependenc imageView.contentMode = .scaleAspectFit return imageView }() - - let openEmailButton: UIButton = { - let button = PrimaryActionButton() - button.setTitle(L10n.Scene.ConfirmEmail.Button.openEmailApp, for: .normal) - button.addTarget(self, action: #selector(openEmailButtonPressed(_:)), for: UIControl.Event.touchUpInside) - return button - }() - - let dontReceiveButton: UIButton = { - let button = UIButton(type: .system) - button.titleLabel?.font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: UIFont.boldSystemFont(ofSize: 15)) - button.setTitleColor(Asset.Colors.brandBlue.color, for: .normal) - button.setTitle(L10n.Scene.ConfirmEmail.Button.dontReceiveEmail, for: .normal) - button.addTarget(self, action: #selector(dontReceiveButtonPressed(_:)), for: UIControl.Event.touchUpInside) - return button + + let navigationActionView: NavigationActionView = { + let navigationActionView = NavigationActionView() + navigationActionView.backgroundColor = Asset.Scene.Onboarding.onboardingBackground.color + return navigationActionView }() deinit { @@ -73,6 +63,8 @@ extension MastodonConfirmEmailViewController { override func viewDidLoad() { + navigationItem.leftBarButtonItem = UIBarButtonItem() + setupOnboardingAppearance() configureTitleLabel() configureMargin() @@ -83,13 +75,12 @@ extension MastodonConfirmEmailViewController { stackView.spacing = 10 stackView.layoutMargins = UIEdgeInsets(top: 10, left: 0, bottom: 23, right: 0) stackView.isLayoutMarginsRelativeArrangement = true - stackView.addArrangedSubview(self.largeTitleLabel) - stackView.addArrangedSubview(self.subtitleLabel) - stackView.addArrangedSubview(self.emailImageView) + stackView.addArrangedSubview(largeTitleLabel) + stackView.addArrangedSubview(subtitleLabel) + stackView.addArrangedSubview(emailImageView) emailImageView.setContentHuggingPriority(.defaultLow, for: .vertical) emailImageView.setContentCompressionResistancePriority(.defaultLow, for: .vertical) - stackView.addArrangedSubview(self.openEmailButton) - stackView.addArrangedSubview(self.dontReceiveButton) + stackView.addArrangedSubview(navigationActionView) view.addSubview(stackView) stackView.translatesAutoresizingMaskIntoConstraints = false @@ -99,10 +90,7 @@ extension MastodonConfirmEmailViewController { stackView.trailingAnchor.constraint(equalTo: view.layoutMarginsGuide.trailingAnchor), stackView.bottomAnchor.constraint(equalTo: view.readableContentGuide.bottomAnchor), ]) - NSLayoutConstraint.activate([ - self.openEmailButton.heightAnchor.constraint(equalToConstant: 46), - ]) - + self.viewModel.timestampUpdatePublisher .sink { [weak self] _ in guard let self = self else { return } @@ -140,6 +128,13 @@ extension MastodonConfirmEmailViewController { .store(in: &self.disposeBag) } .store(in: &self.disposeBag) + + + navigationActionView.backButton.setTitle("Resend", for: .normal) // TODO: i18n + navigationActionView.backButton.addTarget(self, action: #selector(MastodonConfirmEmailViewController.resendButtonPressed(_:)), for: .touchUpInside) + + navigationActionView.nextButton.setTitle(L10n.Scene.ConfirmEmail.Button.openEmailApp, for: .normal) + navigationActionView.nextButton.addTarget(self, action: #selector(MastodonConfirmEmailViewController.openEmailButtonPressed(_:)), for: .touchUpInside) } override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { @@ -190,7 +185,7 @@ extension MastodonConfirmEmailViewController { self.coordinator.present(scene: .alertController(alertController: alertController), from: self, transition: .alertController(animated: true, completion: nil)) } - @objc private func dontReceiveButtonPressed(_ sender: UIButton) { + @objc private func resendButtonPressed(_ sender: UIButton) { let alertController = UIAlertController(title: L10n.Scene.ConfirmEmail.DontReceiveEmail.title, message: L10n.Scene.ConfirmEmail.DontReceiveEmail.description, preferredStyle: .alert) let resendAction = UIAlertAction(title: L10n.Scene.ConfirmEmail.DontReceiveEmail.resendEmail, style: .default) { _ in let url = Mastodon.API.resendEmailURL(domain: self.viewModel.authenticateInfo.domain) diff --git a/Mastodon/Scene/Onboarding/Register/Cell/MastodonRegisterAvatarTableViewCell.swift b/Mastodon/Scene/Onboarding/Register/Cell/MastodonRegisterAvatarTableViewCell.swift index 4d46533e..304bd02d 100644 --- a/Mastodon/Scene/Onboarding/Register/Cell/MastodonRegisterAvatarTableViewCell.swift +++ b/Mastodon/Scene/Onboarding/Register/Cell/MastodonRegisterAvatarTableViewCell.swift @@ -30,6 +30,34 @@ final class MastodonRegisterAvatarTableViewCell: UITableViewCell { return button }() + let editBannerView: UIView = { + let bannerView = UIView() + bannerView.backgroundColor = UIColor.black.withAlphaComponent(0.5) + bannerView.isUserInteractionEnabled = false + + let label: UILabel = { + let label = UILabel() + label.textColor = .white + label.text = L10n.Common.Controls.Actions.edit + label.font = .systemFont(ofSize: 13, weight: .semibold) + label.textAlignment = .center + label.minimumScaleFactor = 0.5 + label.adjustsFontSizeToFitWidth = true + return label + }() + + label.translatesAutoresizingMaskIntoConstraints = false + bannerView.addSubview(label) + NSLayoutConstraint.activate([ + label.topAnchor.constraint(equalTo: bannerView.topAnchor), + label.leadingAnchor.constraint(equalTo: bannerView.leadingAnchor), + label.trailingAnchor.constraint(equalTo: bannerView.trailingAnchor), + label.bottomAnchor.constraint(equalTo: bannerView.bottomAnchor), + ]) + + return bannerView + }() + override func prepareForReuse() { super.prepareForReuse() @@ -72,6 +100,15 @@ extension MastodonRegisterAvatarTableViewCell { avatarButton.trailingAnchor.constraint(equalTo: containerView.trailingAnchor), avatarButton.bottomAnchor.constraint(equalTo: containerView.bottomAnchor), ]) + + editBannerView.translatesAutoresizingMaskIntoConstraints = false + containerView.addSubview(editBannerView) + NSLayoutConstraint.activate([ + editBannerView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor), + editBannerView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor), + editBannerView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor), + editBannerView.heightAnchor.constraint(equalToConstant: 22), + ]) } } diff --git a/Mastodon/Scene/Onboarding/Register/Cell/MastodonRegisterPasswordHintTableViewCell.swift b/Mastodon/Scene/Onboarding/Register/Cell/MastodonRegisterPasswordHintTableViewCell.swift index 3aa9d027..829c70a7 100644 --- a/Mastodon/Scene/Onboarding/Register/Cell/MastodonRegisterPasswordHintTableViewCell.swift +++ b/Mastodon/Scene/Onboarding/Register/Cell/MastodonRegisterPasswordHintTableViewCell.swift @@ -13,7 +13,7 @@ final class MastodonRegisterPasswordHintTableViewCell: UITableViewCell { let label = UILabel() label.font = .preferredFont(forTextStyle: .footnote) label.textColor = Asset.Colors.Label.secondary.color - label.text = "Your password needs at least:" + label.text = L10n.Scene.Register.Input.Password.hint return label }() diff --git a/Mastodon/Scene/Onboarding/Register/MastodonRegisterViewController.swift b/Mastodon/Scene/Onboarding/Register/MastodonRegisterViewController.swift index b278a396..a1fd9742 100644 --- a/Mastodon/Scene/Onboarding/Register/MastodonRegisterViewController.swift +++ b/Mastodon/Scene/Onboarding/Register/MastodonRegisterViewController.swift @@ -82,6 +82,8 @@ extension MastodonRegisterViewController { override func viewDidLoad() { super.viewDidLoad() + navigationItem.leftBarButtonItem = UIBarButtonItem() + setupOnboardingAppearance() defer { setupNavigationBarBackgroundView() @@ -128,12 +130,12 @@ extension MastodonRegisterViewController { viewModel.setupDiffableDataSource(tableView: tableView) - KeyboardResponderService - .configure( - scrollView: tableView, - layoutNeedsUpdate: viewModel.viewDidAppear.eraseToAnyPublisher() - ) - .store(in: &disposeBag) +// KeyboardResponderService +// .configure( +// scrollView: tableView, +// layoutNeedsUpdate: viewModel.viewDidAppear.eraseToAnyPublisher() +// ) +// .store(in: &disposeBag) // gesture view.addGestureRecognizer(tapGestureRecognizer) From 5431d7a98cdc4b11a0209690d86e40183bd390f8 Mon Sep 17 00:00:00 2001 From: CMK Date: Fri, 7 Jan 2022 19:14:39 +0800 Subject: [PATCH 11/12] chore: update version to 1.3.0 (90) --- AppShared/Info.plist | 2 +- CoreDataStack/Info.plist | 2 +- CoreDataStackTests/Info.plist | 2 +- Mastodon.xcodeproj/project.pbxproj | 32 +++++++++---------- .../xcschemes/xcschememanagement.plist | 8 ++--- Mastodon/Info.plist | 2 +- MastodonIntent/Info.plist | 2 +- MastodonTests/Info.plist | 2 +- MastodonUITests/Info.plist | 2 +- NotificationService/Info.plist | 2 +- ShareActionExtension/Info.plist | 2 +- 11 files changed, 29 insertions(+), 29 deletions(-) diff --git a/AppShared/Info.plist b/AppShared/Info.plist index 9c87d945..f652792e 100644 --- a/AppShared/Info.plist +++ b/AppShared/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString 1.3.0 CFBundleVersion - 89 + 90 diff --git a/CoreDataStack/Info.plist b/CoreDataStack/Info.plist index 9c87d945..f652792e 100644 --- a/CoreDataStack/Info.plist +++ b/CoreDataStack/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString 1.3.0 CFBundleVersion - 89 + 90 diff --git a/CoreDataStackTests/Info.plist b/CoreDataStackTests/Info.plist index 9c87d945..f652792e 100644 --- a/CoreDataStackTests/Info.plist +++ b/CoreDataStackTests/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString 1.3.0 CFBundleVersion - 89 + 90 diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index 349f14ee..b79fb901 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -4931,7 +4931,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 89; + CURRENT_PROJECT_VERSION = 90; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -4960,7 +4960,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 89; + CURRENT_PROJECT_VERSION = 90; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -5068,11 +5068,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 89; + CURRENT_PROJECT_VERSION = 90; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 89; + DYLIB_CURRENT_VERSION = 90; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AppShared/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5099,11 +5099,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 89; + CURRENT_PROJECT_VERSION = 90; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 89; + DYLIB_CURRENT_VERSION = 90; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AppShared/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5128,11 +5128,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 89; + CURRENT_PROJECT_VERSION = 90; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 89; + DYLIB_CURRENT_VERSION = 90; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = CoreDataStack/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5158,11 +5158,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 89; + CURRENT_PROJECT_VERSION = 90; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 89; + DYLIB_CURRENT_VERSION = 90; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = CoreDataStack/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5225,7 +5225,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 89; + CURRENT_PROJECT_VERSION = 90; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5250,7 +5250,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 89; + CURRENT_PROJECT_VERSION = 90; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5275,7 +5275,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 89; + CURRENT_PROJECT_VERSION = 90; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5300,7 +5300,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 89; + CURRENT_PROJECT_VERSION = 90; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5325,7 +5325,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 89; + CURRENT_PROJECT_VERSION = 90; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5349,7 +5349,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 89; + CURRENT_PROJECT_VERSION = 90; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( diff --git a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist index 95a6213d..56e26925 100644 --- a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist @@ -7,12 +7,12 @@ AppShared.xcscheme_^#shared#^_ orderHint - 18 + 26 CoreDataStack.xcscheme_^#shared#^_ orderHint - 20 + 27 Mastodon - ASDK.xcscheme_^#shared#^_ @@ -102,7 +102,7 @@ MastodonIntent.xcscheme_^#shared#^_ orderHint - 19 + 25 MastodonIntents.xcscheme_^#shared#^_ @@ -122,7 +122,7 @@ ShareActionExtension.xcscheme_^#shared#^_ orderHint - 21 + 24 SuppressBuildableAutocreation diff --git a/Mastodon/Info.plist b/Mastodon/Info.plist index e96be0cd..8f0b7211 100644 --- a/Mastodon/Info.plist +++ b/Mastodon/Info.plist @@ -30,7 +30,7 @@ CFBundleVersion - 89 + 90 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/MastodonIntent/Info.plist b/MastodonIntent/Info.plist index e9a180d7..78d3b58e 100644 --- a/MastodonIntent/Info.plist +++ b/MastodonIntent/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString 1.3.0 CFBundleVersion - 89 + 90 NSExtension NSExtensionAttributes diff --git a/MastodonTests/Info.plist b/MastodonTests/Info.plist index 9c87d945..f652792e 100644 --- a/MastodonTests/Info.plist +++ b/MastodonTests/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString 1.3.0 CFBundleVersion - 89 + 90 diff --git a/MastodonUITests/Info.plist b/MastodonUITests/Info.plist index 9c87d945..f652792e 100644 --- a/MastodonUITests/Info.plist +++ b/MastodonUITests/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString 1.3.0 CFBundleVersion - 89 + 90 diff --git a/NotificationService/Info.plist b/NotificationService/Info.plist index fe988a2f..77c7421d 100644 --- a/NotificationService/Info.plist +++ b/NotificationService/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString 1.3.0 CFBundleVersion - 89 + 90 NSExtension NSExtensionPointIdentifier diff --git a/ShareActionExtension/Info.plist b/ShareActionExtension/Info.plist index a6178ef8..ae948488 100644 --- a/ShareActionExtension/Info.plist +++ b/ShareActionExtension/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString 1.3.0 CFBundleVersion - 89 + 90 NSExtension NSExtensionAttributes From 0d96fd9f9e34ee1cde6d320eaea47ab125c64379 Mon Sep 17 00:00:00 2001 From: CMK Date: Mon, 10 Jan 2022 11:20:44 +0800 Subject: [PATCH 12/12] chore: add password hint i18n words and a11y hint --- Localization/app.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Localization/app.json b/Localization/app.json index 2edca199..0071f6f9 100644 --- a/Localization/app.json +++ b/Localization/app.json @@ -253,6 +253,12 @@ }, "password": { "placeholder": "password", + "require": "Your password needs at least:", + "character_limit": "8 characters", + "accessibility": { + "checked": "checked", + "unchecked": "unchecked" + }, "hint": "Your password needs at least eight characters" }, "invite": {