Merge pull request #1126 from mastodon/ios-20-server-details
Server Details in Settings (IOS-20)
|
@ -715,6 +715,7 @@
|
|||
"notifications": "Notifications",
|
||||
"support_mastodon": "Support Mastodon",
|
||||
"about_mastodon": "About Mastodon",
|
||||
"server_details": "Server Details",
|
||||
"logout": "Logout %@"
|
||||
}
|
||||
|
||||
|
@ -725,6 +726,9 @@
|
|||
"privacy_policy": "Privacy Policy",
|
||||
"clear_media_storage": "Clear Media Storage"
|
||||
},
|
||||
"about_instance": {
|
||||
"message_admin": "Message Admin"
|
||||
},
|
||||
"general": {
|
||||
"title": "General",
|
||||
"appearance": {
|
||||
|
|
|
@ -715,6 +715,7 @@
|
|||
"notifications": "Notifications",
|
||||
"support_mastodon": "Support Mastodon",
|
||||
"about_mastodon": "About Mastodon",
|
||||
"server_details": "Server Details",
|
||||
"logout": "Logout %@"
|
||||
}
|
||||
|
||||
|
|
|
@ -715,6 +715,7 @@
|
|||
"notifications": "Notifications",
|
||||
"support_mastodon": "Support Mastodon",
|
||||
"about_mastodon": "About Mastodon",
|
||||
"server_details": "Server Details",
|
||||
"logout": "Logout %@"
|
||||
}
|
||||
|
||||
|
@ -725,6 +726,16 @@
|
|||
"privacy_policy": "Privacy Policy",
|
||||
"clear_media_storage": "Clear Media Storage"
|
||||
},
|
||||
|
||||
"server_details": {
|
||||
"about": "About",
|
||||
"rules": "Rules"
|
||||
"about_instance": {
|
||||
"title": "Adminstrator"
|
||||
"message_admin": "Message Admin",
|
||||
"legal_notice": "A legal notice"
|
||||
}
|
||||
},
|
||||
"general": {
|
||||
"title": "General",
|
||||
"appearance": {
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 54;
|
||||
objectVersion = 60;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
|
@ -20,7 +20,6 @@
|
|||
0FB3D31E25E534C700AAD544 /* PickServerCategoryCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0FB3D31D25E534C700AAD544 /* PickServerCategoryCollectionViewCell.swift */; };
|
||||
0FB3D33825E6401400AAD544 /* PickServerCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0FB3D33725E6401400AAD544 /* PickServerCell.swift */; };
|
||||
164F0EBC267D4FE400249499 /* BoopSound.caf in Resources */ = {isa = PBXBuildFile; fileRef = 164F0EBB267D4FE400249499 /* BoopSound.caf */; };
|
||||
18BC7629F65E6DB12CB8416D /* Pods_Mastodon_MastodonUITests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C030226D3C73DCC23D67452 /* Pods_Mastodon_MastodonUITests.framework */; };
|
||||
27D701F5292FC2D60031BCBB /* DataSourceFacade+URL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27D701F4292FC2D60031BCBB /* DataSourceFacade+URL.swift */; };
|
||||
2A1BF99529F7E68400FA1BA5 /* DataSourceFacade+UserView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A1BF99429F7E68400FA1BA5 /* DataSourceFacade+UserView.swift */; };
|
||||
2A1FE47C2938BB2600784BF1 /* FollowedTagsViewModel+DiffableDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A1FE47B2938BB2600784BF1 /* FollowedTagsViewModel+DiffableDataSource.swift */; };
|
||||
|
@ -109,29 +108,31 @@
|
|||
5D0393962612D266007FE196 /* WebViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D0393952612D266007FE196 /* WebViewModel.swift */; };
|
||||
5DA732CC2629CEF500A92342 /* UIView+Remove.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DA732CB2629CEF500A92342 /* UIView+Remove.swift */; };
|
||||
5DF1056425F887CB00D6C0D4 /* AVPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DF1056325F887CB00D6C0D4 /* AVPlayer.swift */; };
|
||||
5E0DEC05797A7E6933788DDB /* Pods_MastodonTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 452147B2903DF38070FE56A2 /* Pods_MastodonTests.framework */; };
|
||||
5E44BF88AD33646E64727BCF /* Pods_MastodonTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD92E0F10BDE4FE7C4B999F2 /* Pods_MastodonTests.framework */; };
|
||||
6213AF5A28939C8400BCADB6 /* BookmarkViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6213AF5928939C8400BCADB6 /* BookmarkViewModel.swift */; };
|
||||
6213AF5C28939C8A00BCADB6 /* BookmarkViewModel+State.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6213AF5B28939C8A00BCADB6 /* BookmarkViewModel+State.swift */; };
|
||||
6213AF5E2893A8B200BCADB6 /* DataSourceFacade+Bookmark.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6213AF5D2893A8B200BCADB6 /* DataSourceFacade+Bookmark.swift */; };
|
||||
62FD27D12893707600B205C5 /* BookmarkViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62FD27D02893707600B205C5 /* BookmarkViewController.swift */; };
|
||||
62FD27D32893707B00B205C5 /* BookmarkViewController+DataSourceProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62FD27D22893707B00B205C5 /* BookmarkViewController+DataSourceProvider.swift */; };
|
||||
62FD27D52893708A00B205C5 /* BookmarkViewModel+Diffable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62FD27D42893708A00B205C5 /* BookmarkViewModel+Diffable.swift */; };
|
||||
71458AF57697DB405CFEC37C /* Pods_Mastodon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8C2A2448AEEDA65B4CD099FC /* Pods_Mastodon.framework */; };
|
||||
7910197261F9D06EFCDCCDBC /* Pods_MastodonTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 89FE8B85A00419CEF4678056 /* Pods_MastodonTests.framework */; };
|
||||
855149C8295F1C5F00943D96 /* UIInterfaceOrientationMask.swift in Sources */ = {isa = PBXBuildFile; fileRef = 855149C7295F1C5F00943D96 /* UIInterfaceOrientationMask.swift */; };
|
||||
855149CA29606D6400943D96 /* PortraitAlertController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 855149C929606D6400943D96 /* PortraitAlertController.swift */; };
|
||||
85904C02293BC0EB0011C817 /* ImageProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85904C01293BC0EB0011C817 /* ImageProvider.swift */; };
|
||||
85904C04293BC1940011C817 /* URLActivityItemWithMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85904C03293BC1940011C817 /* URLActivityItemWithMetadata.swift */; };
|
||||
85BC11B32932414900E191CD /* AltTextViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85BC11B22932414900E191CD /* AltTextViewController.swift */; };
|
||||
87FFDA5D898A5C42ADCB35E7 /* Pods_Mastodon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A4ABE34829701A4496C5BB64 /* Pods_Mastodon.framework */; };
|
||||
9E44C7202967AD17004B2A72 /* MastodonSDKDynamic in Frameworks */ = {isa = PBXBuildFile; productRef = 9E44C71F2967AD17004B2A72 /* MastodonSDKDynamic */; };
|
||||
9E44C7222967AD17004B2A72 /* MastodonSDKDynamic in Embed Frameworks */ = {isa = PBXBuildFile; productRef = 9E44C71F2967AD17004B2A72 /* MastodonSDKDynamic */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
|
||||
C24C97032922F30500BAE8CB /* RefreshControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = C24C97022922F30500BAE8CB /* RefreshControl.swift */; };
|
||||
D807C6C029DE197900A4E17C /* EducationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D807C6BF29DE197900A4E17C /* EducationViewController.swift */; };
|
||||
D808B94C296ECFDC0031EB1E /* StatusEditHistoryViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D808B94B296ECFDC0031EB1E /* StatusEditHistoryViewModel.swift */; };
|
||||
D808B94E296EFBBA0031EB1E /* StatusEditHistoryTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D808B94D296EFBBA0031EB1E /* StatusEditHistoryTableViewCell.swift */; };
|
||||
D80911082AC4BFDE00EB4D15 /* ServerDetailsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D80911072AC4BFDE00EB4D15 /* ServerDetailsViewController.swift */; };
|
||||
D8099078294BC8A30050219F /* PrivacyTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8099077294BC8A30050219F /* PrivacyTableViewController.swift */; };
|
||||
D809907A294BC9390050219F /* PrivacyTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8099079294BC9390050219F /* PrivacyTableViewCell.swift */; };
|
||||
D809907C294D25510050219F /* PrivacyViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D809907B294D25510050219F /* PrivacyViewModel.swift */; };
|
||||
D81439862AD415DE0071A88F /* AboutInstance.swift in Sources */ = {isa = PBXBuildFile; fileRef = D81439852AD415DE0071A88F /* AboutInstance.swift */; };
|
||||
D81439882AD450A40071A88F /* AboutInstanceTableViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = D81439872AD450A40071A88F /* AboutInstanceTableViewDataSource.swift */; };
|
||||
D81A22752AB4643200905D71 /* SearchResultsOverviewTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D81A22742AB4643200905D71 /* SearchResultsOverviewTableViewController.swift */; };
|
||||
D81A22782AB4782400905D71 /* SearchResultOverviewSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = D81A22772AB4782400905D71 /* SearchResultOverviewSection.swift */; };
|
||||
D81A227B2AB47B9A00905D71 /* SearchResultDefaultSectionTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D81A227A2AB47B9A00905D71 /* SearchResultDefaultSectionTableViewCell.swift */; };
|
||||
|
@ -144,6 +145,8 @@
|
|||
D8318A882A4468D300C0FB73 /* NotificationSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8318A872A4468D300C0FB73 /* NotificationSettingsViewController.swift */; };
|
||||
D8318A8A2A4468DC00C0FB73 /* AboutViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8318A892A4468DC00C0FB73 /* AboutViewController.swift */; };
|
||||
D8363B1629469CE200A74079 /* OnboardingNextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8363B1529469CE200A74079 /* OnboardingNextView.swift */; };
|
||||
D852C23C2AC5D02C00309232 /* AboutInstanceViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D852C23B2AC5D02C00309232 /* AboutInstanceViewController.swift */; };
|
||||
D852C23E2AC5D03300309232 /* InstanceRulesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D852C23D2AC5D03300309232 /* InstanceRulesViewController.swift */; };
|
||||
D87BFC8B291D5C6B00FEE264 /* MastodonLoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D87BFC8A291D5C6B00FEE264 /* MastodonLoginView.swift */; };
|
||||
D87BFC8D291EB81200FEE264 /* MastodonLoginViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D87BFC8C291EB81200FEE264 /* MastodonLoginViewModel.swift */; };
|
||||
D87BFC8F291EC26A00FEE264 /* MastodonLoginServerTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D87BFC8E291EC26A00FEE264 /* MastodonLoginServerTableViewCell.swift */; };
|
||||
|
@ -173,6 +176,10 @@
|
|||
D8F917112A4C6B40008A5370 /* GeneralSettingToggleTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8F917102A4C6B40008A5370 /* GeneralSettingToggleTableViewCell.swift */; };
|
||||
D8F917122A4C6B67008A5370 /* GeneralSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8318A832A4468A800C0FB73 /* GeneralSettingsViewController.swift */; };
|
||||
D8F917142A4D74C3008A5370 /* GeneralSettingsDiffableTableViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8F917132A4D74C3008A5370 /* GeneralSettingsDiffableTableViewDataSource.swift */; };
|
||||
D8FAAE3D2AD042E700DC1832 /* AdminTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8FAAE3C2AD042E700DC1832 /* AdminTableViewCell.swift */; };
|
||||
D8FAAE3F2AD0430E00DC1832 /* ContactAdminTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8FAAE3E2AD0430E00DC1832 /* ContactAdminTableViewCell.swift */; };
|
||||
D8FAAE412AD0475900DC1832 /* AboutInstanceTableViewHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8FAAE402AD0475900DC1832 /* AboutInstanceTableViewHeader.swift */; };
|
||||
D8FAAE432AD047B200DC1832 /* AboutInstanceTableFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8FAAE422AD047B200DC1832 /* AboutInstanceTableFooterView.swift */; };
|
||||
DB0009A626AEE5DC009B9D2D /* Intents.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = DB0009A926AEE5DC009B9D2D /* Intents.intentdefinition */; settings = {ATTRIBUTES = (codegen, ); }; };
|
||||
DB0009A726AEE5DC009B9D2D /* Intents.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = DB0009A926AEE5DC009B9D2D /* Intents.intentdefinition */; };
|
||||
DB023D26279FFB0A005AC798 /* ShareActivityProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB023D25279FFB0A005AC798 /* ShareActivityProvider.swift */; };
|
||||
|
@ -489,6 +496,7 @@
|
|||
DBFEEC99279BDCDE004F81DD /* ProfileAboutViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBFEEC98279BDCDE004F81DD /* ProfileAboutViewModel.swift */; };
|
||||
DBFEEC9B279BDDD9004F81DD /* ProfileAboutViewModel+Diffable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBFEEC9A279BDDD9004F81DD /* ProfileAboutViewModel+Diffable.swift */; };
|
||||
DBFEEC9D279C12C1004F81DD /* ProfileFieldEditCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBFEEC9C279C12C1004F81DD /* ProfileFieldEditCollectionViewCell.swift */; };
|
||||
EF7771EAA493A869D65A105C /* Pods_Mastodon_MastodonUITests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD12474E169668871A9F6AB4 /* Pods_Mastodon_MastodonUITests.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
|
@ -714,7 +722,6 @@
|
|||
2D8434FA25FF46B300EECE90 /* HomeTimelineNavigationBarTitleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeTimelineNavigationBarTitleView.swift; sourceTree = "<group>"; };
|
||||
2D84350425FF858100EECE90 /* UIScrollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIScrollView.swift; sourceTree = "<group>"; };
|
||||
2D939AB425EDD8A90076FA61 /* String.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = String.swift; sourceTree = "<group>"; };
|
||||
2DA7D05025CA545E00804E11 /* LoadMoreConfigurableTableViewContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadMoreConfigurableTableViewContainer.swift; sourceTree = "<group>"; };
|
||||
2DAC9E37262FC2320062E1A6 /* SuggestionAccountViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SuggestionAccountViewController.swift; sourceTree = "<group>"; };
|
||||
2DAC9E3D262FC2400062E1A6 /* SuggestionAccountViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SuggestionAccountViewModel.swift; sourceTree = "<group>"; };
|
||||
2DAC9E45262FC9FD0062E1A6 /* SuggestionAccountTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SuggestionAccountTableViewCell.swift; sourceTree = "<group>"; };
|
||||
|
@ -722,9 +729,7 @@
|
|||
2DE0FACD2615F7AD00CDF649 /* RecommendAccountSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecommendAccountSection.swift; sourceTree = "<group>"; };
|
||||
2E1F6A67FDF9771D3E064FDC /* Pods-Mastodon.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon.debug.xcconfig"; path = "Target Support Files/Pods-Mastodon/Pods-Mastodon.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
3B7FD8F28DDA8FBCE5562B78 /* Pods-NotificationService.asdk - debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.asdk - debug.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.asdk - debug.xcconfig"; sourceTree = "<group>"; };
|
||||
3C030226D3C73DCC23D67452 /* Pods_Mastodon_MastodonUITests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Mastodon_MastodonUITests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
3E08A432F40BA7B9CAA9DB68 /* Pods-AppShared.release snapshot.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AppShared.release snapshot.xcconfig"; path = "Target Support Files/Pods-AppShared/Pods-AppShared.release snapshot.xcconfig"; sourceTree = "<group>"; };
|
||||
452147B2903DF38070FE56A2 /* Pods_MastodonTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_MastodonTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
459EA4F43058CAB47719E963 /* Pods-Mastodon-MastodonUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon-MastodonUITests.debug.xcconfig"; path = "Target Support Files/Pods-Mastodon-MastodonUITests/Pods-Mastodon-MastodonUITests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
46DAB0EBDDFB678347CD96FF /* Pods-MastodonTests.asdk - release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MastodonTests.asdk - release.xcconfig"; path = "Target Support Files/Pods-MastodonTests/Pods-MastodonTests.asdk - release.xcconfig"; sourceTree = "<group>"; };
|
||||
5B24BBD7262DB14800A9381B /* ReportViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReportViewModel.swift; sourceTree = "<group>"; };
|
||||
|
@ -756,12 +761,13 @@
|
|||
85904C03293BC1940011C817 /* URLActivityItemWithMetadata.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLActivityItemWithMetadata.swift; sourceTree = "<group>"; };
|
||||
85BC11B22932414900E191CD /* AltTextViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AltTextViewController.swift; sourceTree = "<group>"; };
|
||||
8850E70A1D5FF51432E43653 /* Pods-Mastodon-MastodonUITests.asdk - release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon-MastodonUITests.asdk - release.xcconfig"; path = "Target Support Files/Pods-Mastodon-MastodonUITests/Pods-Mastodon-MastodonUITests.asdk - release.xcconfig"; sourceTree = "<group>"; };
|
||||
89FE8B85A00419CEF4678056 /* Pods_MastodonTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_MastodonTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
8C2A2448AEEDA65B4CD099FC /* Pods_Mastodon.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Mastodon.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
8E79CCBE51FBC3F7FE8CF49F /* Pods-MastodonTests.release snapshot.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MastodonTests.release snapshot.xcconfig"; path = "Target Support Files/Pods-MastodonTests/Pods-MastodonTests.release snapshot.xcconfig"; sourceTree = "<group>"; };
|
||||
8ED8C4B1F1BA2DCFF2926BB1 /* Pods-Mastodon-NotificationService.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon-NotificationService.debug.xcconfig"; path = "Target Support Files/Pods-Mastodon-NotificationService/Pods-Mastodon-NotificationService.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
9780A4C98FFC65B32B50D1C0 /* Pods-MastodonTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MastodonTests.release.xcconfig"; path = "Target Support Files/Pods-MastodonTests/Pods-MastodonTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
9A0982D8F349244EB558CDFD /* Pods-AppShared.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AppShared.debug.xcconfig"; path = "Target Support Files/Pods-AppShared/Pods-AppShared.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
9CFF58FD900AC059428700E7 /* Pods-NotificationService.asdk - release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.asdk - release.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.asdk - release.xcconfig"; sourceTree = "<group>"; };
|
||||
A4ABE34829701A4496C5BB64 /* Pods_Mastodon.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Mastodon.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
A67FD038ECDA0E411AF8DB4D /* Pods-Mastodon-MastodonUITests.asdk.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon-MastodonUITests.asdk.xcconfig"; path = "Target Support Files/Pods-Mastodon-MastodonUITests/Pods-Mastodon-MastodonUITests.asdk.xcconfig"; sourceTree = "<group>"; };
|
||||
A9B1FB898DFD6063B044298C /* Pods-AppShared.asdk - debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AppShared.asdk - debug.xcconfig"; path = "Target Support Files/Pods-AppShared/Pods-AppShared.asdk - debug.xcconfig"; sourceTree = "<group>"; };
|
||||
B31D44635FCF6452F7E1B865 /* Pods-Mastodon-AppShared.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon-AppShared.release.xcconfig"; path = "Target Support Files/Pods-Mastodon-AppShared/Pods-Mastodon-AppShared.release.xcconfig"; sourceTree = "<group>"; };
|
||||
|
@ -770,14 +776,16 @@
|
|||
BD7598A87F4497045EDEF252 /* Pods-Mastodon.asdk - release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon.asdk - release.xcconfig"; path = "Target Support Files/Pods-Mastodon/Pods-Mastodon.asdk - release.xcconfig"; sourceTree = "<group>"; };
|
||||
C24C97022922F30500BAE8CB /* RefreshControl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefreshControl.swift; sourceTree = "<group>"; };
|
||||
C3789232A52F43529CA67E95 /* Pods-MastodonIntent.asdk - debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MastodonIntent.asdk - debug.xcconfig"; path = "Target Support Files/Pods-MastodonIntent/Pods-MastodonIntent.asdk - debug.xcconfig"; sourceTree = "<group>"; };
|
||||
CD92E0F10BDE4FE7C4B999F2 /* Pods_MastodonTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_MastodonTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D7D7CF93E262178800077512 /* Pods-Mastodon-AppShared.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon-AppShared.debug.xcconfig"; path = "Target Support Files/Pods-Mastodon-AppShared/Pods-Mastodon-AppShared.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
D807C6BF29DE197900A4E17C /* EducationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EducationViewController.swift; sourceTree = "<group>"; };
|
||||
D808B94B296ECFDC0031EB1E /* StatusEditHistoryViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusEditHistoryViewModel.swift; sourceTree = "<group>"; };
|
||||
D808B94D296EFBBA0031EB1E /* StatusEditHistoryTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusEditHistoryTableViewCell.swift; sourceTree = "<group>"; };
|
||||
D80911072AC4BFDE00EB4D15 /* ServerDetailsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerDetailsViewController.swift; sourceTree = "<group>"; };
|
||||
D8099077294BC8A30050219F /* PrivacyTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivacyTableViewController.swift; sourceTree = "<group>"; };
|
||||
D8099079294BC9390050219F /* PrivacyTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivacyTableViewCell.swift; sourceTree = "<group>"; };
|
||||
D809907B294D25510050219F /* PrivacyViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivacyViewModel.swift; sourceTree = "<group>"; };
|
||||
D81439852AD415DE0071A88F /* AboutInstance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutInstance.swift; sourceTree = "<group>"; };
|
||||
D81439872AD450A40071A88F /* AboutInstanceTableViewDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutInstanceTableViewDataSource.swift; sourceTree = "<group>"; };
|
||||
D81A22742AB4643200905D71 /* SearchResultsOverviewTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultsOverviewTableViewController.swift; sourceTree = "<group>"; };
|
||||
D81A22772AB4782400905D71 /* SearchResultOverviewSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultOverviewSection.swift; sourceTree = "<group>"; };
|
||||
D81A227A2AB47B9A00905D71 /* SearchResultDefaultSectionTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultDefaultSectionTableViewCell.swift; sourceTree = "<group>"; };
|
||||
|
@ -787,7 +795,6 @@
|
|||
D82463532A52B47B00A3DBDD /* be */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = be; path = be.lproj/WidgetExtension.strings; sourceTree = "<group>"; };
|
||||
D82463542A52B47B00A3DBDD /* be */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = be; path = be.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
D82463552A52B47B00A3DBDD /* be */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = be; path = be.lproj/Intents.stringsdict; sourceTree = "<group>"; };
|
||||
D82BD7512ABC42D6009A374A /* Coordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Coordinator.swift; sourceTree = "<group>"; };
|
||||
D82BD7542ABC73AF009A374A /* NotificationPolicyTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationPolicyTableViewCell.swift; sourceTree = "<group>"; };
|
||||
D8318A7F2A4466D300C0FB73 /* SettingsCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsCoordinator.swift; sourceTree = "<group>"; };
|
||||
D8318A832A4468A800C0FB73 /* GeneralSettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneralSettingsViewController.swift; sourceTree = "<group>"; };
|
||||
|
@ -795,6 +802,8 @@
|
|||
D8318A872A4468D300C0FB73 /* NotificationSettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsViewController.swift; sourceTree = "<group>"; };
|
||||
D8318A892A4468DC00C0FB73 /* AboutViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutViewController.swift; sourceTree = "<group>"; };
|
||||
D8363B1529469CE200A74079 /* OnboardingNextView.swift */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.swift; path = OnboardingNextView.swift; sourceTree = "<group>"; tabWidth = 4; };
|
||||
D852C23B2AC5D02C00309232 /* AboutInstanceViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutInstanceViewController.swift; sourceTree = "<group>"; };
|
||||
D852C23D2AC5D03300309232 /* InstanceRulesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstanceRulesViewController.swift; sourceTree = "<group>"; };
|
||||
D87BFC8A291D5C6B00FEE264 /* MastodonLoginView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonLoginView.swift; sourceTree = "<group>"; };
|
||||
D87BFC8C291EB81200FEE264 /* MastodonLoginViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonLoginViewModel.swift; sourceTree = "<group>"; };
|
||||
D87BFC8E291EC26A00FEE264 /* MastodonLoginServerTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonLoginServerTableViewCell.swift; sourceTree = "<group>"; };
|
||||
|
@ -834,6 +843,10 @@
|
|||
D8F9170E2A4B47EF008A5370 /* Coordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Coordinator.swift; sourceTree = "<group>"; };
|
||||
D8F917102A4C6B40008A5370 /* GeneralSettingToggleTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneralSettingToggleTableViewCell.swift; sourceTree = "<group>"; };
|
||||
D8F917132A4D74C3008A5370 /* GeneralSettingsDiffableTableViewDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneralSettingsDiffableTableViewDataSource.swift; sourceTree = "<group>"; };
|
||||
D8FAAE3C2AD042E700DC1832 /* AdminTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdminTableViewCell.swift; sourceTree = "<group>"; };
|
||||
D8FAAE3E2AD0430E00DC1832 /* ContactAdminTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactAdminTableViewCell.swift; sourceTree = "<group>"; };
|
||||
D8FAAE402AD0475900DC1832 /* AboutInstanceTableViewHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutInstanceTableViewHeader.swift; sourceTree = "<group>"; };
|
||||
D8FAAE422AD047B200DC1832 /* AboutInstanceTableFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutInstanceTableFooterView.swift; sourceTree = "<group>"; };
|
||||
DB0009A826AEE5DC009B9D2D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.intentdefinition; name = Base; path = Base.lproj/Intents.intentdefinition; sourceTree = "<group>"; };
|
||||
DB0009AD26AEE5E4009B9D2D /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/Intents.strings; sourceTree = "<group>"; };
|
||||
DB023D25279FFB0A005AC798 /* ShareActivityProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareActivityProvider.swift; sourceTree = "<group>"; };
|
||||
|
@ -897,7 +910,6 @@
|
|||
DB1FD44325F26CCC004CFCFC /* PickServerSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PickServerSection.swift; sourceTree = "<group>"; };
|
||||
DB1FD44F25F26FA1004CFCFC /* MastodonPickServerViewModel+Diffable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MastodonPickServerViewModel+Diffable.swift"; sourceTree = "<group>"; };
|
||||
DB1FD45925F27898004CFCFC /* CategoryPickerItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CategoryPickerItem.swift; sourceTree = "<group>"; };
|
||||
DB1FD45F25F278AF004CFCFC /* CategoryPickerSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CategoryPickerSection.swift; sourceTree = "<group>"; };
|
||||
DB2B3ABD25E37E15007045F9 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
DB2F073325E8ECF000957B2D /* AuthenticationViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthenticationViewModel.swift; sourceTree = "<group>"; };
|
||||
DB336F3E278E668C0031E64B /* StatusTableViewCell+ViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "StatusTableViewCell+ViewModel.swift"; sourceTree = "<group>"; };
|
||||
|
@ -1239,6 +1251,7 @@
|
|||
DBFEEC9A279BDDD9004F81DD /* ProfileAboutViewModel+Diffable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ProfileAboutViewModel+Diffable.swift"; sourceTree = "<group>"; };
|
||||
DBFEEC9C279C12C1004F81DD /* ProfileFieldEditCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileFieldEditCollectionViewCell.swift; sourceTree = "<group>"; };
|
||||
DBFEF06726A58D07006D7ED1 /* ShareActionExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ShareActionExtension.entitlements; sourceTree = "<group>"; };
|
||||
DD12474E169668871A9F6AB4 /* Pods_Mastodon_MastodonUITests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Mastodon_MastodonUITests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DDB1B139FA8EA26F510D58B6 /* Pods-AppShared.asdk - release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AppShared.asdk - release.xcconfig"; path = "Target Support Files/Pods-AppShared/Pods-AppShared.asdk - release.xcconfig"; sourceTree = "<group>"; };
|
||||
DF65937EC1FF64462BC002EE /* Pods-MastodonTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MastodonTests.profile.xcconfig"; path = "Target Support Files/Pods-MastodonTests/Pods-MastodonTests.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
E5C7236E58D14A0322FE00F2 /* Pods-Mastodon-MastodonUITests.asdk - debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon-MastodonUITests.asdk - debug.xcconfig"; path = "Target Support Files/Pods-Mastodon-MastodonUITests/Pods-Mastodon-MastodonUITests.asdk - debug.xcconfig"; sourceTree = "<group>"; };
|
||||
|
@ -1248,7 +1261,6 @@
|
|||
ECA373ABA86BE3C2D7ED878E /* Pods-AppShared.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AppShared.release.xcconfig"; path = "Target Support Files/Pods-AppShared/Pods-AppShared.release.xcconfig"; sourceTree = "<group>"; };
|
||||
EE13214BC0246BE5210CCC10 /* Pods-AppShared.asdk.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AppShared.asdk.xcconfig"; path = "Target Support Files/Pods-AppShared/Pods-AppShared.asdk.xcconfig"; sourceTree = "<group>"; };
|
||||
F31E7502A7E3945B98C6CBAF /* Pods-NotificationService.asdk.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.asdk.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.asdk.xcconfig"; sourceTree = "<group>"; };
|
||||
F4A2A2D7000E477CA459ADA9 /* Pods_AppShared.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_AppShared.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
F920AD4EC23B0D00F5CCA58E /* Pods-MastodonIntent.asdk - release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MastodonIntent.asdk - release.xcconfig"; path = "Target Support Files/Pods-MastodonIntent/Pods-MastodonIntent.asdk - release.xcconfig"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
|
@ -1279,7 +1291,7 @@
|
|||
files = (
|
||||
357FEEAF29523D470021C9DC /* MastodonSDKDynamic in Frameworks */,
|
||||
DBF96326262EC0A6001D8D25 /* AuthenticationServices.framework in Frameworks */,
|
||||
87FFDA5D898A5C42ADCB35E7 /* Pods_Mastodon.framework in Frameworks */,
|
||||
71458AF57697DB405CFEC37C /* Pods_Mastodon.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -1288,8 +1300,7 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
9E44C7202967AD17004B2A72 /* MastodonSDKDynamic in Frameworks */,
|
||||
5E44BF88AD33646E64727BCF /* Pods_MastodonTests.framework in Frameworks */,
|
||||
5E0DEC05797A7E6933788DDB /* Pods_MastodonTests.framework in Frameworks */,
|
||||
7910197261F9D06EFCDCCDBC /* Pods_MastodonTests.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -1297,7 +1308,7 @@
|
|||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
18BC7629F65E6DB12CB8416D /* Pods_Mastodon_MastodonUITests.framework in Frameworks */,
|
||||
EF7771EAA493A869D65A105C /* Pods_Mastodon_MastodonUITests.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -1722,15 +1733,14 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
DBF96325262EC0A6001D8D25 /* AuthenticationServices.framework */,
|
||||
A4ABE34829701A4496C5BB64 /* Pods_Mastodon.framework */,
|
||||
3C030226D3C73DCC23D67452 /* Pods_Mastodon_MastodonUITests.framework */,
|
||||
452147B2903DF38070FE56A2 /* Pods_MastodonTests.framework */,
|
||||
F4A2A2D7000E477CA459ADA9 /* Pods_AppShared.framework */,
|
||||
DB8FAB9E26AEC3A2008E5AF4 /* Intents.framework */,
|
||||
DB8FABA926AEC3A2008E5AF4 /* IntentsUI.framework */,
|
||||
2A6451022964223800CD8B8A /* UniformTypeIdentifiers.framework */,
|
||||
2A728121297EA9D7004138C5 /* WidgetKit.framework */,
|
||||
2A728123297EA9D7004138C5 /* SwiftUI.framework */,
|
||||
8C2A2448AEEDA65B4CD099FC /* Pods_Mastodon.framework */,
|
||||
DD12474E169668871A9F6AB4 /* Pods_Mastodon_MastodonUITests.framework */,
|
||||
89FE8B85A00419CEF4678056 /* Pods_MastodonTests.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
|
@ -1756,6 +1766,7 @@
|
|||
D8F916FF2A4AD898008A5370 /* Settings Overview */,
|
||||
D8F917042A4B0657008A5370 /* General Settings */,
|
||||
D81D12432A4E181C005009D4 /* Notification Settings */,
|
||||
D80911062AC4BFD100EB4D15 /* Server Details */,
|
||||
D8F917092A4B2AFF008A5370 /* About Mastodon */,
|
||||
D8318A7F2A4466D300C0FB73 /* SettingsCoordinator.swift */,
|
||||
);
|
||||
|
@ -1783,6 +1794,17 @@
|
|||
path = Bookmark;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D80911062AC4BFD100EB4D15 /* Server Details */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D8FAAE3B2AD042CD00DC1832 /* Table View Components */,
|
||||
D80911072AC4BFDE00EB4D15 /* ServerDetailsViewController.swift */,
|
||||
D852C23B2AC5D02C00309232 /* AboutInstanceViewController.swift */,
|
||||
D852C23D2AC5D03300309232 /* InstanceRulesViewController.swift */,
|
||||
);
|
||||
path = "Server Details";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D8099076294BC2BA0050219F /* Privacy */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -1929,6 +1951,19 @@
|
|||
path = "About Mastodon";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D8FAAE3B2AD042CD00DC1832 /* Table View Components */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D8FAAE3C2AD042E700DC1832 /* AdminTableViewCell.swift */,
|
||||
D8FAAE3E2AD0430E00DC1832 /* ContactAdminTableViewCell.swift */,
|
||||
D8FAAE402AD0475900DC1832 /* AboutInstanceTableViewHeader.swift */,
|
||||
D8FAAE422AD047B200DC1832 /* AboutInstanceTableFooterView.swift */,
|
||||
D81439852AD415DE0071A88F /* AboutInstance.swift */,
|
||||
D81439872AD450A40071A88F /* AboutInstanceTableViewDataSource.swift */,
|
||||
);
|
||||
path = "Table View Components";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DB01409B25C40BB600F9F3CF /* Onboarding */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -2110,7 +2145,6 @@
|
|||
DB427DD325BAA00100D1B89D /* Products */,
|
||||
1EBA4F56E920856A3FC84ACB /* Pods */,
|
||||
3FE14AD363ED19AE7FF210A6 /* Frameworks */,
|
||||
DB98335F25C93B0400AD9700 /* Recovered References */,
|
||||
D8A6FE6029325F5900666A47 /* Localization */,
|
||||
);
|
||||
indentWidth = 4;
|
||||
|
@ -2638,17 +2672,6 @@
|
|||
path = Thread;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DB98335F25C93B0400AD9700 /* Recovered References */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CD92E0F10BDE4FE7C4B999F2 /* Pods_MastodonTests.framework */,
|
||||
2DA7D05025CA545E00804E11 /* LoadMoreConfigurableTableViewContainer.swift */,
|
||||
DB1FD45F25F278AF004CFCFC /* CategoryPickerSection.swift */,
|
||||
D82BD7512ABC42D6009A374A /* Coordinator.swift */,
|
||||
);
|
||||
name = "Recovered References";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DB98EB4A27B0F0F50082E365 /* Cell */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -3269,7 +3292,7 @@
|
|||
};
|
||||
};
|
||||
buildConfigurationList = DB427DCD25BAA00100D1B89D /* Build configuration list for PBXProject "Mastodon" */;
|
||||
compatibilityVersion = "Xcode 9.3";
|
||||
compatibilityVersion = "Xcode 15.0";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
|
@ -3615,6 +3638,7 @@
|
|||
DB023D26279FFB0A005AC798 /* ShareActivityProvider.swift in Sources */,
|
||||
5D0393962612D266007FE196 /* WebViewModel.swift in Sources */,
|
||||
5B24BBDA262DB14800A9381B /* ReportViewModel.swift in Sources */,
|
||||
D80911082AC4BFDE00EB4D15 /* ServerDetailsViewController.swift in Sources */,
|
||||
2D5A3D3825CF8D9F002347D6 /* ScrollViewContainer.swift in Sources */,
|
||||
DB6180EF26391CA50018D199 /* MediaPreviewImageViewController.swift in Sources */,
|
||||
DB1E347825F519300079D7DF /* PickServerItem.swift in Sources */,
|
||||
|
@ -3642,11 +3666,14 @@
|
|||
DB697DD6278F4C29004EF2F7 /* DataSourceProvider.swift in Sources */,
|
||||
DB0FCB8E2796C0B7006C02E2 /* TrendCollectionViewCell.swift in Sources */,
|
||||
0F1E2D0B2615C39400C38565 /* DoubleTitleLabelNavigationBarTitleView.swift in Sources */,
|
||||
D81439862AD415DE0071A88F /* AboutInstance.swift in Sources */,
|
||||
DBDFF1902805543100557A48 /* DiscoveryPostsViewController.swift in Sources */,
|
||||
DB697DD9278F4CED004EF2F7 /* HomeTimelineViewController+DataSourceProvider.swift in Sources */,
|
||||
DB45FAD725CA6C76005A8AC7 /* UIBarButtonItem.swift in Sources */,
|
||||
D8FAAE432AD047B200DC1832 /* AboutInstanceTableFooterView.swift in Sources */,
|
||||
D808B94E296EFBBA0031EB1E /* StatusEditHistoryTableViewCell.swift in Sources */,
|
||||
2D8434F525FF465D00EECE90 /* HomeTimelineNavigationBarTitleViewModel.swift in Sources */,
|
||||
D852C23E2AC5D03300309232 /* InstanceRulesViewController.swift in Sources */,
|
||||
DB938F0F2624119800E5B6C1 /* ThreadViewModel+LoadThreadState.swift in Sources */,
|
||||
DB6180F226391CF40018D199 /* MediaPreviewImageViewModel.swift in Sources */,
|
||||
62FD27D12893707600B205C5 /* BookmarkViewController.swift in Sources */,
|
||||
|
@ -3665,6 +3692,7 @@
|
|||
DBDFF19C28055BD600557A48 /* DiscoveryViewModel.swift in Sources */,
|
||||
DBB3BA2A26A81C020004F2D4 /* FLAnimatedImageView.swift in Sources */,
|
||||
DB3E6FF32806D97400B035AE /* DiscoveryNewsViewModel+State.swift in Sources */,
|
||||
D8FAAE3F2AD0430E00DC1832 /* ContactAdminTableViewCell.swift in Sources */,
|
||||
DB6746ED278F45F0008A6B94 /* AutoGenerateProtocolRelayDelegate.swift in Sources */,
|
||||
DB0618032785A7100030EE79 /* RegisterSection.swift in Sources */,
|
||||
DB63F76B279A5ED300455B82 /* NotificationTimelineViewModel+LoadOldestState.swift in Sources */,
|
||||
|
@ -3693,6 +3721,7 @@
|
|||
DBFEEC9D279C12C1004F81DD /* ProfileFieldEditCollectionViewCell.swift in Sources */,
|
||||
DB3E6FEC2806D7F100B035AE /* DiscoveryNewsViewController.swift in Sources */,
|
||||
DBCBED1726132DB500B49291 /* UserTimelineViewModel+Diffable.swift in Sources */,
|
||||
D8FAAE412AD0475900DC1832 /* AboutInstanceTableViewHeader.swift in Sources */,
|
||||
2DE0FACE2615F7AD00CDF649 /* RecommendAccountSection.swift in Sources */,
|
||||
2DAC9E3E262FC2400062E1A6 /* SuggestionAccountViewModel.swift in Sources */,
|
||||
DB603113279EBEBA00A935FE /* DataSourceFacade+Block.swift in Sources */,
|
||||
|
@ -3856,6 +3885,7 @@
|
|||
DB68A04A25E9027700CFDF14 /* AdaptiveStatusBarStyleNavigationController.swift in Sources */,
|
||||
0FB3D33825E6401400AAD544 /* PickServerCell.swift in Sources */,
|
||||
6213AF5C28939C8A00BCADB6 /* BookmarkViewModel+State.swift in Sources */,
|
||||
D81439882AD450A40071A88F /* AboutInstanceTableViewDataSource.swift in Sources */,
|
||||
D807C6C029DE197900A4E17C /* EducationViewController.swift in Sources */,
|
||||
2D364F7825E66D8300204FDC /* MastodonResendEmailViewModel.swift in Sources */,
|
||||
DBEFCD7B282A162400C0ABEA /* ReportReasonView.swift in Sources */,
|
||||
|
@ -3923,6 +3953,7 @@
|
|||
D8B5E4F42A4ED0240008970C /* NotificationSettingsViewModel.swift in Sources */,
|
||||
DBD376B2269302A4007FEC24 /* UITableViewCell.swift in Sources */,
|
||||
DB4F0966269ED52200D62E92 /* SearchResultViewModel.swift in Sources */,
|
||||
D852C23C2AC5D02C00309232 /* AboutInstanceViewController.swift in Sources */,
|
||||
D8F917142A4D74C3008A5370 /* GeneralSettingsDiffableTableViewDataSource.swift in Sources */,
|
||||
DB6180FA26391F2E0018D199 /* MediaPreviewViewModel.swift in Sources */,
|
||||
2D7631A825C1535600929FB9 /* StatusTableViewCell.swift in Sources */,
|
||||
|
@ -3938,6 +3969,7 @@
|
|||
DB3E6FE42806A5B800B035AE /* DiscoverySection.swift in Sources */,
|
||||
DB697DDB278F4DE3004EF2F7 /* DataSourceProvider+StatusTableViewCellDelegate.swift in Sources */,
|
||||
DB87D4512609CF1E00D12C0D /* ComposeStatusPollOptionAppendEntryCollectionViewCell.swift in Sources */,
|
||||
D8FAAE3D2AD042E700DC1832 /* AdminTableViewCell.swift in Sources */,
|
||||
DBB45B5627B39FC9002DC5A7 /* MediaPreviewVideoViewController.swift in Sources */,
|
||||
D8A6AB6C291C5136003AB663 /* MastodonLoginViewController.swift in Sources */,
|
||||
DB0FCB8027968F70006C02E2 /* MastodonStatusThreadViewModel.swift in Sources */,
|
||||
|
|
|
@ -46,6 +46,15 @@
|
|||
"version": "3.1.3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"package": "FXPageControl",
|
||||
"repositoryURL": "https://github.com/nicklockwood/FXPageControl.git",
|
||||
"state": {
|
||||
"branch": null,
|
||||
"revision": "a94633402ba98c52f86c2a70e61ff086dec9de78",
|
||||
"version": "1.6.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"package": "KeychainAccess",
|
||||
"repositoryURL": "https://github.com/kishikawakatsumi/KeychainAccess.git",
|
||||
|
@ -91,15 +100,6 @@
|
|||
"version": "10.11.2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"package": "NukeFLAnimatedImagePlugin",
|
||||
"repositoryURL": "https://github.com/kean/Nuke-FLAnimatedImage-Plugin.git",
|
||||
"state": {
|
||||
"branch": null,
|
||||
"revision": "b59c346a7d536336db3b0f12c72c6e53ee709e16",
|
||||
"version": "8.0.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"package": "Pageboy",
|
||||
"repositoryURL": "https://github.com/uias/Pageboy",
|
||||
|
@ -216,6 +216,15 @@
|
|||
"revision": "20f513ded04a040cdf5467f0891849b1763ede3b",
|
||||
"version": "1.4.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"package": "XLPagerTabStrip",
|
||||
"repositoryURL": "https://github.com/xmartlabs/XLPagerTabStrip.git",
|
||||
"state": {
|
||||
"branch": null,
|
||||
"revision": "211ed62aa376722cf93c429802a8b6ff66a8bd52",
|
||||
"version": "9.1.0"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -546,7 +546,9 @@ private extension SceneCoordinator {
|
|||
accountName: accountName,
|
||||
setting: setting,
|
||||
appContext: appContext,
|
||||
authContext: authContext)
|
||||
authContext: authContext,
|
||||
sceneCoordinator: self
|
||||
)
|
||||
settingsCoordinator.delegate = self
|
||||
settingsCoordinator.start()
|
||||
|
||||
|
@ -648,7 +650,5 @@ extension SceneCoordinator: SettingsCoordinatorDelegate {
|
|||
authenticationController.authenticationSession?.start()
|
||||
|
||||
self.mastodonAuthenticationController = authenticationController
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import MastodonAsset
|
|||
import MastodonLocalization
|
||||
|
||||
final class ServerRulesTableViewCell: UITableViewCell {
|
||||
|
||||
static let reuseIdentifier = "ServerRulesTableViewCell"
|
||||
static let margin: CGFloat = 23
|
||||
|
||||
let indexImageView: UIImageView = {
|
||||
|
|
|
@ -15,10 +15,7 @@ extension MastodonServerRulesViewModel {
|
|||
|
||||
var snapshot = NSDiffableDataSourceSnapshot<ServerRuleSection, ServerRuleItem>()
|
||||
snapshot.appendSections([.rules])
|
||||
let ruleItems: [ServerRuleItem] = rules.enumerated().map { i, rule in
|
||||
let ruleContext = ServerRuleItem.RuleContext(index: i, rule: rule)
|
||||
return ServerRuleItem.rule(ruleContext)
|
||||
}
|
||||
let ruleItems: [ServerRuleItem] = rules.enumerated().map { index, rule in return ServerRuleItem.rule(index: index, rule: rule) }
|
||||
snapshot.appendItems(ruleItems, toSection: .rules)
|
||||
diffableDataSource?.apply(snapshot, animatingDifferences: false)
|
||||
}
|
||||
|
|
|
@ -9,12 +9,5 @@ import Foundation
|
|||
import MastodonSDK
|
||||
|
||||
enum ServerRuleItem: Hashable {
|
||||
case rule(RuleContext)
|
||||
}
|
||||
|
||||
extension ServerRuleItem {
|
||||
struct RuleContext: Hashable {
|
||||
let index: Int
|
||||
let rule: Mastodon.Entity.Instance.Rule
|
||||
}
|
||||
case rule(index: Int, rule: Mastodon.Entity.Instance.Rule)
|
||||
}
|
||||
|
|
|
@ -19,11 +19,11 @@ extension ServerRuleSection {
|
|||
) -> UITableViewDiffableDataSource<ServerRuleSection, ServerRuleItem> {
|
||||
return UITableViewDiffableDataSource(tableView: tableView) { tableView, indexPath, item in
|
||||
switch item {
|
||||
case .rule(let ruleContext):
|
||||
case .rule(let index, let rule):
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: ServerRulesTableViewCell.self), for: indexPath) as! ServerRulesTableViewCell
|
||||
cell.indexImageView.image = UIImage(systemName: "\(ruleContext.index + 1).circle") ?? UIImage(systemName: "questionmark.circle")
|
||||
cell.indexImageView.image = UIImage(systemName: "\(index + 1).circle") ?? UIImage(systemName: "questionmark.circle")
|
||||
cell.indexImageView.tintColor = Asset.Colors.Brand.lightBlurple.color
|
||||
cell.ruleLabel.text = ruleContext.rule.text
|
||||
cell.ruleLabel.text = rule.text
|
||||
return cell
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ enum AboutSettingsEntry: Hashable {
|
|||
case .privacyPolicy:
|
||||
return L10n.Scene.Settings.AboutMastodon.privacyPolicy
|
||||
case .clearMediaCache(_):
|
||||
return L10n.Scene.Settings.AboutMastodon.cleaerMediaStorage
|
||||
return L10n.Scene.Settings.AboutMastodon.clearMediaStorage
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
// Copyright © 2023 Mastodon gGmbH. All rights reserved.
|
||||
|
||||
import UIKit
|
||||
import MastodonSDK
|
||||
|
||||
protocol AboutInstanceViewControllerDelegate: AnyObject {
|
||||
func showAdminAccount(_ viewController: AboutInstanceViewController, account: Mastodon.Entity.Account)
|
||||
func sendEmailToAdmin(_ viewController: AboutInstanceViewController, emailAddress: String)
|
||||
}
|
||||
|
||||
class AboutInstanceViewController: UIViewController {
|
||||
|
||||
weak var delegate: AboutInstanceViewControllerDelegate?
|
||||
var dataSource: AboutInstanceTableViewDataSource?
|
||||
|
||||
let tableView: UITableView
|
||||
let headerView: AboutInstanceTableHeaderView
|
||||
let footerView: AboutInstanceTableFooterView
|
||||
|
||||
var instance: Mastodon.Entity.V2.Instance?
|
||||
|
||||
init() {
|
||||
tableView = UITableView(frame: .zero, style: .insetGrouped)
|
||||
tableView.translatesAutoresizingMaskIntoConstraints = false
|
||||
tableView.register(ContactAdminTableViewCell.self, forCellReuseIdentifier: ContactAdminTableViewCell.reuseIdentifier)
|
||||
tableView.register(AdminTableViewCell.self, forCellReuseIdentifier: AdminTableViewCell.reuseIdentifier)
|
||||
|
||||
headerView = AboutInstanceTableHeaderView()
|
||||
footerView = AboutInstanceTableFooterView()
|
||||
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
|
||||
let dataSource = AboutInstanceTableViewDataSource(tableView: tableView) { tableView, indexPath, itemIdentifier in
|
||||
switch itemIdentifier {
|
||||
|
||||
case .adminAccount(let account):
|
||||
guard let cell = tableView.dequeueReusableCell(withIdentifier: AdminTableViewCell.reuseIdentifier, for: indexPath) as? AdminTableViewCell else { fatalError("WTF?! Wrong cell.") }
|
||||
|
||||
cell.condensedUserView.configure(with: account, showFollowers: false)
|
||||
|
||||
return cell
|
||||
|
||||
case .contactAdmin:
|
||||
guard let cell = tableView.dequeueReusableCell(withIdentifier: ContactAdminTableViewCell.reuseIdentifier, for: indexPath) as? ContactAdminTableViewCell else { fatalError("WTF?! Wrong cell.") }
|
||||
|
||||
cell.configure()
|
||||
|
||||
return cell
|
||||
}
|
||||
}
|
||||
|
||||
tableView.delegate = self
|
||||
tableView.dataSource = dataSource
|
||||
|
||||
self.dataSource = dataSource
|
||||
|
||||
view.addSubview(tableView)
|
||||
|
||||
setupConstraints()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
|
||||
|
||||
private func setupConstraints() {
|
||||
let constraints = [
|
||||
tableView.topAnchor.constraint(equalTo: view.topAnchor),
|
||||
tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
|
||||
view.trailingAnchor.constraint(equalTo: tableView.trailingAnchor),
|
||||
view.bottomAnchor.constraint(equalTo: tableView.bottomAnchor),
|
||||
]
|
||||
|
||||
NSLayoutConstraint.activate(constraints)
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
tableView.tableHeaderView = headerView
|
||||
tableView.tableFooterView = footerView
|
||||
}
|
||||
|
||||
override func viewWillLayoutSubviews() {
|
||||
super.viewWillLayoutSubviews()
|
||||
|
||||
if let tableHeaderView = tableView.tableHeaderView {
|
||||
let size = tableHeaderView.systemLayoutSizeFitting(.init(width: self.tableView.frame.width, height: 10_000))
|
||||
tableHeaderView.frame.size = size
|
||||
tableView.tableHeaderView = tableHeaderView
|
||||
}
|
||||
|
||||
if let tableFooterView = tableView.tableFooterView {
|
||||
let size = tableFooterView.systemLayoutSizeFitting(.init(width: self.tableView.frame.width, height: 10_000))
|
||||
tableFooterView.frame.size = size
|
||||
tableView.tableFooterView = tableFooterView
|
||||
}
|
||||
|
||||
super.viewWillLayoutSubviews()
|
||||
}
|
||||
|
||||
func update(with instance: Mastodon.Entity.V2.Instance) {
|
||||
|
||||
self.instance = instance
|
||||
var snapshot = NSDiffableDataSourceSnapshot<AboutInstanceSection, AboutInstanceItem>()
|
||||
|
||||
snapshot.appendSections([.main])
|
||||
if let account = instance.contact?.account {
|
||||
snapshot.appendItems([.adminAccount(account)], toSection: .main)
|
||||
}
|
||||
|
||||
if let email = instance.contact?.email {
|
||||
snapshot.appendItems([.contactAdmin(email)], toSection: .main)
|
||||
}
|
||||
|
||||
dataSource?.apply(snapshot, animatingDifferences: false)
|
||||
|
||||
guard let thumbnailUrlString = instance.thumbnail?.url, let thumbnailUrl = URL(string: thumbnailUrlString) else { return }
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.headerView.updateImage(with: thumbnailUrl) { [weak self] in
|
||||
DispatchQueue.main.async {
|
||||
guard let self else { return }
|
||||
|
||||
self.view.setNeedsLayout()
|
||||
self.view.layoutIfNeeded()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func updateFooter(with extendedDescription: Mastodon.Entity.ExtendedDescription) {
|
||||
DispatchQueue.main.async {
|
||||
self.footerView.update(with: extendedDescription)
|
||||
|
||||
self.view.setNeedsLayout()
|
||||
self.view.layoutIfNeeded()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension AboutInstanceViewController: UITableViewDelegate {
|
||||
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
guard let snapshot = dataSource?.snapshot() else {
|
||||
return tableView.deselectRow(at: indexPath, animated: true)
|
||||
}
|
||||
|
||||
switch snapshot.itemIdentifiers(inSection: .main)[indexPath.row] {
|
||||
case .adminAccount(let account):
|
||||
delegate?.showAdminAccount(self, account: account)
|
||||
case .contactAdmin(let email):
|
||||
delegate?.sendEmailToAdmin(self, emailAddress: email)
|
||||
}
|
||||
|
||||
tableView.deselectRow(at: indexPath, animated: true)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
// Copyright © 2023 Mastodon gGmbH. All rights reserved.
|
||||
|
||||
import UIKit
|
||||
import MastodonSDK
|
||||
|
||||
protocol InstanceRulesViewControllerDelegate: AnyObject {
|
||||
|
||||
}
|
||||
|
||||
class InstanceRulesViewController: UIViewController {
|
||||
|
||||
weak var delegate: InstanceRulesViewControllerDelegate?
|
||||
let tableView: UITableView
|
||||
var dataSource: UITableViewDiffableDataSource<ServerRuleSection, ServerRuleItem>?
|
||||
|
||||
var sections: [ServerRuleSection] = []
|
||||
|
||||
init() {
|
||||
tableView = UITableView(frame: .zero, style: .insetGrouped)
|
||||
tableView.translatesAutoresizingMaskIntoConstraints = false
|
||||
tableView.register(ServerRulesTableViewCell.self, forCellReuseIdentifier: ServerRulesTableViewCell.reuseIdentifier)
|
||||
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
view.addSubview(tableView)
|
||||
|
||||
let dataSource = ServerRuleSection.tableViewDiffableDataSource(tableView: tableView)
|
||||
|
||||
tableView.dataSource = dataSource
|
||||
self.dataSource = dataSource
|
||||
|
||||
setupConstraints()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
|
||||
|
||||
private func setupConstraints() {
|
||||
let constraints = [
|
||||
tableView.topAnchor.constraint(equalTo: view.topAnchor),
|
||||
tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
|
||||
view.trailingAnchor.constraint(equalTo: tableView.trailingAnchor),
|
||||
view.bottomAnchor.constraint(equalTo: tableView.bottomAnchor),
|
||||
]
|
||||
|
||||
NSLayoutConstraint.activate(constraints)
|
||||
}
|
||||
|
||||
func update(with instance: Mastodon.Entity.V2.Instance) {
|
||||
guard let dataSource, let rules = instance.rules, rules.isNotEmpty else { return }
|
||||
|
||||
var snapshot = NSDiffableDataSourceSnapshot<ServerRuleSection, ServerRuleItem>()
|
||||
|
||||
snapshot.appendSections([.rules])
|
||||
let ruleItems = rules.enumerated().compactMap { index, rule in ServerRuleItem.rule(index: index, rule: rule) }
|
||||
snapshot.appendItems(ruleItems, toSection: .rules)
|
||||
|
||||
dataSource.apply(snapshot)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,165 @@
|
|||
// Copyright © 2023 Mastodon gGmbH. All rights reserved.
|
||||
|
||||
import UIKit
|
||||
import MastodonSDK
|
||||
import MastodonLocalization
|
||||
import MetaTextKit
|
||||
|
||||
enum ServerDetailsTab: Int, CaseIterable {
|
||||
case about = 0
|
||||
case rules = 1
|
||||
|
||||
var title: String {
|
||||
switch self {
|
||||
case .about: return L10n.Scene.Settings.ServerDetails.about
|
||||
case .rules: return L10n.Scene.Settings.ServerDetails.rules
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protocol ServerDetailsViewControllerDelegate: AnyObject {}
|
||||
|
||||
class ServerDetailsViewController: UIViewController {
|
||||
|
||||
weak var delegate: (ServerDetailsViewControllerDelegate & AboutInstanceViewControllerDelegate & InstanceRulesViewControllerDelegate & MetaLabelDelegate)? {
|
||||
didSet {
|
||||
aboutInstanceViewController.delegate = delegate
|
||||
instanceRulesViewController.delegate = delegate
|
||||
aboutInstanceViewController.footerView.contentLabel.linkDelegate = delegate
|
||||
}
|
||||
}
|
||||
let pageController: UIPageViewController
|
||||
|
||||
private let segmentedControlWrapper: UIView
|
||||
let segmentedControl: UISegmentedControl
|
||||
let aboutInstanceViewController: AboutInstanceViewController
|
||||
let instanceRulesViewController: InstanceRulesViewController
|
||||
let containerView: UIView
|
||||
|
||||
init(domain: String) {
|
||||
segmentedControl = UISegmentedControl()
|
||||
segmentedControl.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
segmentedControlWrapper = UIView()
|
||||
segmentedControlWrapper.translatesAutoresizingMaskIntoConstraints = false
|
||||
segmentedControlWrapper.addSubview(segmentedControl)
|
||||
|
||||
containerView = UIView()
|
||||
containerView.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
aboutInstanceViewController = AboutInstanceViewController()
|
||||
instanceRulesViewController = InstanceRulesViewController()
|
||||
|
||||
pageController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal)
|
||||
pageController.setViewControllers([aboutInstanceViewController], direction: .forward, animated: false)
|
||||
pageController.view.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
|
||||
view.addSubview(segmentedControlWrapper)
|
||||
view.addSubview(containerView)
|
||||
view.backgroundColor = .systemGroupedBackground
|
||||
|
||||
containerView.addSubview(pageController.view)
|
||||
addChild(pageController)
|
||||
pageController.didMove(toParent: self)
|
||||
pageController.delegate = self
|
||||
pageController.dataSource = self
|
||||
|
||||
ServerDetailsTab.allCases.forEach {
|
||||
segmentedControl.insertSegment(withTitle: $0.title, at: $0.rawValue, animated: false)
|
||||
}
|
||||
segmentedControl.selectedSegmentIndex = ServerDetailsTab.about.rawValue
|
||||
segmentedControl.addTarget(self, action: #selector(ServerDetailsViewController.segmentedControlValueChanged(_:)), for: .valueChanged)
|
||||
|
||||
setupConstraints()
|
||||
|
||||
title = domain
|
||||
|
||||
setupNavigationBarAppearance()
|
||||
setupNavigationBarBackgroundView()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
|
||||
|
||||
private func setupConstraints() {
|
||||
let constraints = [
|
||||
segmentedControlWrapper.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
|
||||
segmentedControlWrapper.leadingAnchor.constraint(equalTo: view.leadingAnchor),
|
||||
view.trailingAnchor.constraint(equalTo: segmentedControlWrapper.trailingAnchor),
|
||||
|
||||
containerView.topAnchor.constraint(equalTo: segmentedControlWrapper.bottomAnchor),
|
||||
containerView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
|
||||
view.trailingAnchor.constraint(equalTo: containerView.trailingAnchor),
|
||||
view.bottomAnchor.constraint(equalTo: containerView.bottomAnchor),
|
||||
|
||||
segmentedControl.topAnchor.constraint(equalTo: segmentedControlWrapper.topAnchor, constant: 4),
|
||||
segmentedControl.leadingAnchor.constraint(equalTo: segmentedControlWrapper.leadingAnchor, constant: 16),
|
||||
segmentedControlWrapper.trailingAnchor.constraint(equalTo: segmentedControl.trailingAnchor, constant: 16),
|
||||
segmentedControlWrapper.bottomAnchor.constraint(equalTo: segmentedControl.bottomAnchor, constant: 8),
|
||||
|
||||
pageController.view.topAnchor.constraint(equalTo: containerView.topAnchor),
|
||||
pageController.view.leadingAnchor.constraint(equalTo: containerView.leadingAnchor),
|
||||
containerView.trailingAnchor.constraint(equalTo: pageController.view.trailingAnchor),
|
||||
containerView.bottomAnchor.constraint(equalTo: pageController.view.bottomAnchor),
|
||||
]
|
||||
|
||||
NSLayoutConstraint.activate(constraints)
|
||||
}
|
||||
|
||||
//MARK: - Actions
|
||||
@objc
|
||||
func segmentedControlValueChanged(_ sender: UISegmentedControl) {
|
||||
guard let selectedTab = ServerDetailsTab(rawValue: sender.selectedSegmentIndex) else { return }
|
||||
|
||||
switch selectedTab {
|
||||
case .about:
|
||||
pageController.setViewControllers([aboutInstanceViewController], direction: .reverse, animated: true)
|
||||
case .rules:
|
||||
pageController.setViewControllers([instanceRulesViewController], direction: .forward, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
func update(with instance: Mastodon.Entity.V2.Instance) {
|
||||
aboutInstanceViewController.update(with: instance)
|
||||
instanceRulesViewController.update(with: instance)
|
||||
}
|
||||
|
||||
func updateFooter(with extendedDescription: Mastodon.Entity.ExtendedDescription) {
|
||||
aboutInstanceViewController.updateFooter(with: extendedDescription)
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - UIPageViewControllerDataSource
|
||||
extension ServerDetailsViewController: UIPageViewControllerDataSource {
|
||||
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
|
||||
if viewController == instanceRulesViewController {
|
||||
return aboutInstanceViewController
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
|
||||
if viewController == aboutInstanceViewController {
|
||||
return instanceRulesViewController
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - UIPageViewControllerDelegate
|
||||
extension ServerDetailsViewController: UIPageViewControllerDelegate {
|
||||
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
|
||||
guard let currentViewController = pageViewController.viewControllers?.first else { return }
|
||||
|
||||
if currentViewController == aboutInstanceViewController {
|
||||
segmentedControl.selectedSegmentIndex = ServerDetailsTab.about.rawValue
|
||||
} else if currentViewController == instanceRulesViewController {
|
||||
segmentedControl.selectedSegmentIndex = ServerDetailsTab.rules.rawValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension ServerDetailsViewController: OnboardingViewControllerAppearance {}
|
|
@ -0,0 +1,18 @@
|
|||
// Copyright © 2023 Mastodon gGmbH. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
import MastodonSDK
|
||||
import MastodonLocalization
|
||||
|
||||
enum AboutInstanceSection: Int, Hashable {
|
||||
case main = 0
|
||||
|
||||
var title: String {
|
||||
return L10n.Scene.Settings.ServerDetails.AboutInstance.title
|
||||
}
|
||||
}
|
||||
|
||||
enum AboutInstanceItem: Hashable {
|
||||
case adminAccount(Mastodon.Entity.Account)
|
||||
case contactAdmin(String)
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
// Copyright © 2023 Mastodon gGmbH. All rights reserved.
|
||||
|
||||
import UIKit
|
||||
import MetaTextKit
|
||||
import MastodonSDK
|
||||
import MastodonMeta
|
||||
import MastodonCore
|
||||
import MastodonAsset
|
||||
import MastodonLocalization
|
||||
|
||||
class AboutInstanceTableFooterView: UIView {
|
||||
let headlineLabel: UILabel
|
||||
let contentLabel: MetaLabel
|
||||
|
||||
init() {
|
||||
|
||||
headlineLabel = UILabel()
|
||||
headlineLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||
headlineLabel.font = UIFontMetrics(forTextStyle: .title2).scaledFont(for: .systemFont(ofSize: 22, weight: .bold))
|
||||
|
||||
contentLabel = MetaLabel(style: .aboutInstance)
|
||||
contentLabel.numberOfLines = 0
|
||||
contentLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||
super.init(frame: .zero)
|
||||
|
||||
addSubview(headlineLabel)
|
||||
addSubview(contentLabel)
|
||||
|
||||
setupConstraints()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
|
||||
|
||||
private func setupConstraints() {
|
||||
|
||||
let horizontalMargin = 16.0
|
||||
let verticalMargin = 24.0
|
||||
|
||||
let constraints = [
|
||||
headlineLabel.topAnchor.constraint(equalTo: topAnchor, constant: verticalMargin),
|
||||
headlineLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: horizontalMargin),
|
||||
trailingAnchor.constraint(equalTo: headlineLabel.trailingAnchor, constant: horizontalMargin),
|
||||
|
||||
contentLabel.topAnchor.constraint(equalTo: headlineLabel.bottomAnchor, constant: 8),
|
||||
contentLabel.leadingAnchor.constraint(equalTo: headlineLabel.leadingAnchor),
|
||||
contentLabel.trailingAnchor.constraint(equalTo: headlineLabel.trailingAnchor),
|
||||
bottomAnchor.constraint(equalTo: contentLabel.bottomAnchor, constant: verticalMargin),
|
||||
]
|
||||
|
||||
NSLayoutConstraint.activate(constraints)
|
||||
}
|
||||
|
||||
func update(with extendedDescription: Mastodon.Entity.ExtendedDescription) {
|
||||
headlineLabel.text = L10n.Scene.Settings.ServerDetails.AboutInstance.legalNotice
|
||||
|
||||
let content = extendedDescription.content
|
||||
.replacingOccurrences(of: "<br>", with: "\n")
|
||||
.replacingOccurrences(of: "\n\n", with: "\n")
|
||||
|
||||
|
||||
if let metaContent = try? MastodonMetaContent.convert(document: MastodonContent(content: content, emojis: [:])) {
|
||||
contentLabel.configure(content: metaContent)
|
||||
} else {
|
||||
let content = PlaintextMetaContent(string: content)
|
||||
contentLabel.configure(content: content)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright © 2023 Mastodon gGmbH. All rights reserved.
|
||||
|
||||
import UIKit
|
||||
|
||||
class AboutInstanceTableViewDataSource: UITableViewDiffableDataSource<AboutInstanceSection, AboutInstanceItem> {
|
||||
|
||||
override init(tableView: UITableView, cellProvider: @escaping UITableViewDiffableDataSource<AboutInstanceSection, AboutInstanceItem>.CellProvider) {
|
||||
super.init(tableView: tableView, cellProvider: cellProvider)
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||
guard let section = AboutInstanceSection(rawValue: section) else { return nil }
|
||||
|
||||
return section.title.uppercased()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright © 2023 Mastodon gGmbH. All rights reserved.
|
||||
|
||||
import UIKit
|
||||
import MastodonAsset
|
||||
import AlamofireImage
|
||||
|
||||
class AboutInstanceTableHeaderView: UIView {
|
||||
let thumbnailImageView: UIImageView
|
||||
|
||||
init() {
|
||||
thumbnailImageView = UIImageView(image: Asset.Settings.aboutInstancePlaceholder.image)
|
||||
thumbnailImageView.contentMode = .scaleAspectFill
|
||||
thumbnailImageView.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
super.init(frame: .zero)
|
||||
|
||||
addSubview(thumbnailImageView)
|
||||
|
||||
setupConstraints()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
|
||||
|
||||
private func setupConstraints() {
|
||||
let constraints = [
|
||||
thumbnailImageView.topAnchor.constraint(equalTo: topAnchor),
|
||||
thumbnailImageView.leadingAnchor.constraint(equalTo: leadingAnchor),
|
||||
trailingAnchor.constraint(equalTo: thumbnailImageView.trailingAnchor),
|
||||
bottomAnchor.constraint(equalTo: thumbnailImageView.bottomAnchor, constant: 16),
|
||||
]
|
||||
|
||||
NSLayoutConstraint.activate(constraints)
|
||||
}
|
||||
|
||||
func updateImage(with thumbnailURL: URL, completion: (() -> Void)? = nil) {
|
||||
thumbnailImageView.af.setImage(withURL: thumbnailURL, placeholderImage: Asset.Settings.aboutInstancePlaceholder.image, completion: { _ in
|
||||
completion?()
|
||||
})
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
// Copyright © 2023 Mastodon gGmbH. All rights reserved.
|
||||
|
||||
import UIKit
|
||||
|
||||
typealias AdminTableViewCell = SearchResultsProfileTableViewCell
|
|
@ -0,0 +1,22 @@
|
|||
// Copyright © 2023 Mastodon gGmbH. All rights reserved.
|
||||
|
||||
import UIKit
|
||||
import MastodonAsset
|
||||
import MastodonLocalization
|
||||
|
||||
class ContactAdminTableViewCell: UITableViewCell {
|
||||
|
||||
static let reuseIdentifier = "ContactAdminTableViewCell"
|
||||
|
||||
func configure() {
|
||||
var configuration = defaultContentConfiguration()
|
||||
|
||||
configuration.textProperties.color = Asset.Colors.Brand.blurple.color
|
||||
configuration.image = UIImage(systemName: "envelope")
|
||||
configuration.imageProperties.tintColor = Asset.Colors.Brand.blurple.color
|
||||
configuration.text = L10n.Scene.Settings.ServerDetails.AboutInstance.messageAdmin
|
||||
backgroundColor = .secondarySystemGroupedBackground
|
||||
|
||||
contentConfiguration = configuration
|
||||
}
|
||||
}
|
|
@ -10,62 +10,78 @@ struct SettingsSection: Hashable {
|
|||
enum SettingsEntry: Hashable {
|
||||
case general
|
||||
case notifications
|
||||
case serverDetails(domain: String)
|
||||
case aboutMastodon
|
||||
case logout(accountName: String)
|
||||
|
||||
var title: String {
|
||||
switch self {
|
||||
case .general:
|
||||
return L10n.Scene.Settings.Overview.general
|
||||
case .notifications:
|
||||
return L10n.Scene.Settings.Overview.notifications
|
||||
case .aboutMastodon:
|
||||
return L10n.Scene.Settings.Overview.aboutMastodon
|
||||
case .logout(let accountName):
|
||||
return L10n.Scene.Settings.Overview.logout(accountName)
|
||||
case .general:
|
||||
return L10n.Scene.Settings.Overview.general
|
||||
case .notifications:
|
||||
return L10n.Scene.Settings.Overview.notifications
|
||||
case .serverDetails(_):
|
||||
return L10n.Scene.Settings.Overview.serverDetails
|
||||
case .aboutMastodon:
|
||||
return L10n.Scene.Settings.Overview.aboutMastodon
|
||||
case .logout(let accountName):
|
||||
return L10n.Scene.Settings.Overview.logout(accountName)
|
||||
}
|
||||
}
|
||||
|
||||
var secondaryTitle: String? {
|
||||
switch self {
|
||||
case .serverDetails(domain: let domain):
|
||||
return domain
|
||||
case .general, .notifications, .aboutMastodon, .logout(_):
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
var accessoryType: UITableViewCell.AccessoryType {
|
||||
switch self {
|
||||
case .general, .notifications, .aboutMastodon, .logout(_):
|
||||
return .disclosureIndicator
|
||||
case .general, .notifications, .serverDetails(_), .aboutMastodon, .logout(_):
|
||||
return .disclosureIndicator
|
||||
}
|
||||
}
|
||||
|
||||
var icon: UIImage? {
|
||||
switch self {
|
||||
case .general:
|
||||
return UIImage(systemName: "gear")
|
||||
case .notifications:
|
||||
return UIImage(systemName: "bell.badge")
|
||||
case .aboutMastodon:
|
||||
return UIImage(systemName: "info.circle.fill")
|
||||
case .logout(_):
|
||||
return nil
|
||||
case .general:
|
||||
return UIImage(systemName: "gear")
|
||||
case .notifications:
|
||||
return UIImage(systemName: "bell.badge")
|
||||
case .serverDetails(_):
|
||||
return UIImage(systemName: "server.rack")
|
||||
case .aboutMastodon:
|
||||
return UIImage(systemName: "info.circle.fill")
|
||||
case .logout(_):
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
var iconBackgroundColor: UIColor? {
|
||||
switch self {
|
||||
case .general:
|
||||
return .systemGray
|
||||
case .notifications:
|
||||
return .systemRed
|
||||
case .aboutMastodon:
|
||||
return .systemPurple
|
||||
case .logout(_):
|
||||
return nil
|
||||
case .general:
|
||||
return .systemGray
|
||||
case .notifications:
|
||||
return .systemRed
|
||||
case .serverDetails(_):
|
||||
return .systemTeal
|
||||
case .aboutMastodon:
|
||||
return .systemPurple
|
||||
case .logout(_):
|
||||
return nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var textColor: UIColor {
|
||||
switch self {
|
||||
case .general, .notifications, .aboutMastodon:
|
||||
return .label
|
||||
case .logout(_):
|
||||
return .red
|
||||
case .general, .notifications, .aboutMastodon, .serverDetails(_):
|
||||
return .label
|
||||
case .logout(_):
|
||||
return .red
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,7 +9,9 @@ class SettingsTableViewCell: UITableViewCell {
|
|||
let iconImageView: UIImageView
|
||||
let iconImageBackgroundView: UIView
|
||||
let titleLabel: UILabel
|
||||
let secondaryLabel: UILabel
|
||||
|
||||
private let labelStackView: UIStackView
|
||||
private let contentStackView: UIStackView
|
||||
|
||||
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
|
@ -21,8 +23,17 @@ class SettingsTableViewCell: UITableViewCell {
|
|||
iconImageBackgroundView.addSubview(iconImageView)
|
||||
|
||||
titleLabel = UILabel()
|
||||
titleLabel.font = UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 17, weight: .regular))
|
||||
secondaryLabel = UILabel()
|
||||
secondaryLabel.font = UIFontMetrics(forTextStyle: .caption1).scaledFont(for: .systemFont(ofSize: 12, weight: .regular))
|
||||
secondaryLabel.textColor = .secondaryLabel
|
||||
|
||||
contentStackView = UIStackView(arrangedSubviews: [iconImageBackgroundView, titleLabel])
|
||||
labelStackView = UIStackView(arrangedSubviews: [titleLabel, secondaryLabel])
|
||||
labelStackView.axis = .vertical
|
||||
labelStackView.spacing = 2
|
||||
labelStackView.alignment = .leading
|
||||
|
||||
contentStackView = UIStackView(arrangedSubviews: [iconImageBackgroundView, labelStackView])
|
||||
contentStackView.translatesAutoresizingMaskIntoConstraints = false
|
||||
contentStackView.axis = .horizontal
|
||||
contentStackView.alignment = .center
|
||||
|
@ -50,8 +61,8 @@ class SettingsTableViewCell: UITableViewCell {
|
|||
iconImageView.centerXAnchor.constraint(equalTo: iconImageBackgroundView.centerXAnchor),
|
||||
iconImageView.widthAnchor.constraint(equalToConstant: 20),
|
||||
|
||||
titleLabel.topAnchor.constraint(greaterThanOrEqualTo: contentView.topAnchor, constant: 12),
|
||||
contentView.bottomAnchor.constraint(greaterThanOrEqualTo: titleLabel.bottomAnchor, constant: 12),
|
||||
labelStackView.topAnchor.constraint(greaterThanOrEqualTo: contentView.topAnchor, constant: 12),
|
||||
contentView.bottomAnchor.constraint(greaterThanOrEqualTo: labelStackView.bottomAnchor, constant: 12),
|
||||
]
|
||||
|
||||
NSLayoutConstraint.activate(constraints)
|
||||
|
@ -61,6 +72,13 @@ class SettingsTableViewCell: UITableViewCell {
|
|||
titleLabel.textColor = entry.textColor
|
||||
titleLabel.text = entry.title
|
||||
|
||||
if let secondaryTitle = entry.secondaryTitle {
|
||||
secondaryLabel.isHidden = false
|
||||
secondaryLabel.text = secondaryTitle
|
||||
} else {
|
||||
secondaryLabel.isHidden = true
|
||||
}
|
||||
|
||||
if let icon = entry.icon {
|
||||
iconImageView.image = icon
|
||||
iconImageView.tintColor = .white
|
||||
|
@ -73,7 +91,6 @@ class SettingsTableViewCell: UITableViewCell {
|
|||
iconImageBackgroundView.backgroundColor = entry.iconBackgroundColor
|
||||
|
||||
accessoryType = entry.accessoryType
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,11 +16,11 @@ class SettingsViewController: UIViewController {
|
|||
var tableViewDataSource: UITableViewDiffableDataSource<SettingsSection, SettingsEntry>?
|
||||
let tableView: UITableView
|
||||
|
||||
init(accountName: String) {
|
||||
init(accountName: String, domain: String) {
|
||||
|
||||
sections = [
|
||||
.init(entries: [.general, .notifications]),
|
||||
.init(entries: [.aboutMastodon]),
|
||||
.init(entries: [.serverDetails(domain: domain), .aboutMastodon]),
|
||||
.init(entries: [.logout(accountName: accountName)])
|
||||
]
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import MastodonCore
|
|||
import CoreDataStack
|
||||
import MastodonSDK
|
||||
import Combine
|
||||
import MetaTextKit
|
||||
|
||||
protocol SettingsCoordinatorDelegate: AnyObject {
|
||||
func logout(_ settingsCoordinator: SettingsCoordinator)
|
||||
|
@ -26,15 +27,17 @@ class SettingsCoordinator: NSObject, Coordinator {
|
|||
let appContext: AppContext
|
||||
let authContext: AuthContext
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
let sceneCoordinator: SceneCoordinator
|
||||
|
||||
init(presentedOn: UIViewController, accountName: String, setting: Setting, appContext: AppContext, authContext: AuthContext) {
|
||||
init(presentedOn: UIViewController, accountName: String, setting: Setting, appContext: AppContext, authContext: AuthContext, sceneCoordinator: SceneCoordinator) {
|
||||
self.presentedOn = presentedOn
|
||||
navigationController = UINavigationController()
|
||||
self.setting = setting
|
||||
self.appContext = appContext
|
||||
self.authContext = authContext
|
||||
self.sceneCoordinator = sceneCoordinator
|
||||
|
||||
settingsViewController = SettingsViewController(accountName: accountName)
|
||||
settingsViewController = SettingsViewController(accountName: accountName, domain: authContext.mastodonAuthenticationBox.domain)
|
||||
}
|
||||
|
||||
func start() {
|
||||
|
@ -65,8 +68,29 @@ extension SettingsCoordinator: SettingsViewControllerDelegate {
|
|||
let notificationViewController = NotificationSettingsViewController(currentSetting: currentSetting, notificationsEnabled: notificationsEnabled)
|
||||
notificationViewController.delegate = self
|
||||
|
||||
self.navigationController.pushViewController(notificationViewController, animated: true)
|
||||
navigationController.pushViewController(notificationViewController, animated: true)
|
||||
case .serverDetails(let domain):
|
||||
let serverDetailsViewController = ServerDetailsViewController(domain: domain)
|
||||
serverDetailsViewController.delegate = self
|
||||
|
||||
appContext.apiService.instanceV2(domain: domain)
|
||||
.sink { _ in
|
||||
|
||||
} receiveValue: { content in
|
||||
serverDetailsViewController.update(with: content.value)
|
||||
}
|
||||
.store(in: &disposeBag)
|
||||
|
||||
appContext.apiService.extendedDescription(domain: domain)
|
||||
.sink { _ in
|
||||
|
||||
} receiveValue: { content in
|
||||
serverDetailsViewController.updateFooter(with: content.value)
|
||||
}
|
||||
.store(in: &disposeBag)
|
||||
|
||||
|
||||
navigationController.pushViewController(serverDetailsViewController, animated: true)
|
||||
case .aboutMastodon:
|
||||
let aboutViewController = AboutViewController()
|
||||
aboutViewController.delegate = self
|
||||
|
@ -135,6 +159,8 @@ extension SettingsCoordinator: NotificationSettingsViewControllerDelegate {
|
|||
|
||||
guard viewModel.updated else { return }
|
||||
|
||||
//Show spinner?
|
||||
|
||||
let authenticationBox = authContext.mastodonAuthenticationBox
|
||||
guard let subscription = setting.activeSubscription,
|
||||
setting.domain == authenticationBox.domain,
|
||||
|
@ -183,3 +209,58 @@ extension SettingsCoordinator: PolicySelectionViewControllerDelegate {
|
|||
try? self.appContext.managedObjectContext.save()
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - ServerDetailsViewControllerDelegate
|
||||
extension SettingsCoordinator: ServerDetailsViewControllerDelegate {
|
||||
|
||||
}
|
||||
|
||||
extension SettingsCoordinator: AboutInstanceViewControllerDelegate {
|
||||
@MainActor func showAdminAccount(_ viewController: AboutInstanceViewController, account: Mastodon.Entity.Account) {
|
||||
Task {
|
||||
let user = try await appContext.apiService.fetchUser(username: account.username, domain: authContext.mastodonAuthenticationBox.domain, authenticationBox: authContext.mastodonAuthenticationBox)
|
||||
|
||||
let profileViewModel = ProfileViewModel(context: appContext, authContext: authContext, optionalMastodonUser: user)
|
||||
|
||||
_ = await MainActor.run {
|
||||
sceneCoordinator.present(scene: .profile(viewModel: profileViewModel), transition: .show)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func sendEmailToAdmin(_ viewController: AboutInstanceViewController, emailAddress: String) {
|
||||
if let emailUrl = URL(string: "mailto:\(emailAddress)"), UIApplication.shared.canOpenURL(emailUrl) {
|
||||
UIApplication.shared.open(emailUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension SettingsCoordinator: InstanceRulesViewControllerDelegate {
|
||||
|
||||
}
|
||||
|
||||
extension SettingsCoordinator: MetaLabelDelegate {
|
||||
@MainActor
|
||||
func metaLabel(_ metaLabel: MetaLabel, didSelectMeta meta: Meta) {
|
||||
switch meta {
|
||||
case .url(_, _, let url, _):
|
||||
guard let url = URL(string: url) else { return }
|
||||
_ = sceneCoordinator.present(scene: .safari(url: url), from: nil, transition: .safariPresent(animated: true, completion: nil))
|
||||
case .mention(_, _, let userInfo):
|
||||
guard let href = userInfo?["href"] as? String,
|
||||
let url = URL(string: href) else { return }
|
||||
_ = sceneCoordinator.present(scene: .safari(url: url), from: nil, transition: .safariPresent(animated: true, completion: nil))
|
||||
case .hashtag(_, let hashtag, _):
|
||||
let hashtagTimelineViewModel = HashtagTimelineViewModel(context: appContext, authContext: authContext, hashtag: hashtag)
|
||||
_ = sceneCoordinator.present(scene: .hashtagTimeline(viewModel: hashtagTimelineViewModel), from: nil, transition: .show)
|
||||
case .email(let email, _):
|
||||
if let emailUrl = URL(string: "mailto:\(email)"), UIApplication.shared.canOpenURL(emailUrl) {
|
||||
UIApplication.shared.open(emailUrl)
|
||||
}
|
||||
case .emoji:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,239 +0,0 @@
|
|||
{
|
||||
"pins" : [
|
||||
{
|
||||
"identity" : "alamofire",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/Alamofire/Alamofire.git",
|
||||
"state" : {
|
||||
"revision" : "8dd85aee02e39dd280c75eef88ffdb86eed4b07b",
|
||||
"version" : "5.6.2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "alamofireimage",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/Alamofire/AlamofireImage.git",
|
||||
"state" : {
|
||||
"revision" : "98cbb00ce0ec5fc8e52a5b50a6bfc08d3e5aee10",
|
||||
"version" : "4.2.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "commonoslog",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/MainasuK/CommonOSLog",
|
||||
"state" : {
|
||||
"revision" : "c121624a30698e9886efe38aebb36ff51c01b6c2",
|
||||
"version" : "0.1.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "faviconfinder",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/will-lumley/FaviconFinder.git",
|
||||
"state" : {
|
||||
"revision" : "1f74844f77f79b95c0bb0130b3a87d4f340e6d3a",
|
||||
"version" : "3.3.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "flanimatedimage",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/Flipboard/FLAnimatedImage.git",
|
||||
"state" : {
|
||||
"revision" : "d4f07b6f164d53c1212c3e54d6460738b1981e9f",
|
||||
"version" : "1.0.17"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "fpsindicator",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/MainasuK/FPSIndicator.git",
|
||||
"state" : {
|
||||
"revision" : "e4a5067ccd5293b024c767f09e51056afd4a4796",
|
||||
"version" : "1.1.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "fuzi",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/cezheng/Fuzi.git",
|
||||
"state" : {
|
||||
"revision" : "f08c8323da21e985f3772610753bcfc652c2103f",
|
||||
"version" : "3.1.3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "keychainaccess",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/kishikawakatsumi/KeychainAccess.git",
|
||||
"state" : {
|
||||
"revision" : "84e546727d66f1adc5439debad16270d0fdd04e7",
|
||||
"version" : "4.2.2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "metatextkit",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/TwidereProject/MetaTextKit.git",
|
||||
"state" : {
|
||||
"revision" : "dcd5255d6930c2fab408dc8562c577547e477624",
|
||||
"version" : "2.2.5"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "nextlevelsessionexporter",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/NextLevel/NextLevelSessionExporter.git",
|
||||
"state" : {
|
||||
"revision" : "b6c0cce1aa37fe1547d694f958fac3c3524b74da",
|
||||
"version" : "0.4.6"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "nuke",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/kean/Nuke.git",
|
||||
"state" : {
|
||||
"revision" : "a002b7fd786f2df2ed4333fe73a9727499fd9d97",
|
||||
"version" : "10.11.2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "nuke-flanimatedimage-plugin",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/kean/Nuke-FLAnimatedImage-Plugin.git",
|
||||
"state" : {
|
||||
"revision" : "b59c346a7d536336db3b0f12c72c6e53ee709e16",
|
||||
"version" : "8.0.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "pageboy",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/uias/Pageboy",
|
||||
"state" : {
|
||||
"revision" : "af8fa81788b893205e1ff42ddd88c5b0b315d7c5",
|
||||
"version" : "3.7.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "panmodal",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/slackhq/PanModal.git",
|
||||
"state" : {
|
||||
"revision" : "b012aecb6b67a8e46369227f893c12544846613f",
|
||||
"version" : "1.2.7"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "sdwebimage",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/SDWebImage/SDWebImage.git",
|
||||
"state" : {
|
||||
"revision" : "9248fe561a2a153916fb9597e3af4434784c6d32",
|
||||
"version" : "5.13.4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "stripes",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/eneko/Stripes.git",
|
||||
"state" : {
|
||||
"revision" : "d533fd44b8043a3abbf523e733599173d6f98c11",
|
||||
"version" : "0.2.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swift-collections",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-collections.git",
|
||||
"state" : {
|
||||
"revision" : "f504716c27d2e5d4144fa4794b12129301d17729",
|
||||
"version" : "1.0.3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swift-nio",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-nio.git",
|
||||
"state" : {
|
||||
"revision" : "546610d52b19be3e19935e0880bb06b9c03f5cef",
|
||||
"version" : "1.14.4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swift-nio-zlib-support",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-nio-zlib-support.git",
|
||||
"state" : {
|
||||
"revision" : "37760e9a52030bb9011972c5213c3350fa9d41fd",
|
||||
"version" : "1.0.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swiftsoup",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/scinfu/SwiftSoup.git",
|
||||
"state" : {
|
||||
"revision" : "6778575285177365cbad3e5b8a72f2a20583cfec",
|
||||
"version" : "2.4.3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swiftui-introspect",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/siteline/SwiftUI-Introspect.git",
|
||||
"state" : {
|
||||
"revision" : "f2616860a41f9d9932da412a8978fec79c06fe24",
|
||||
"version" : "0.1.4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "tabbarpager",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/TwidereProject/TabBarPager.git",
|
||||
"state" : {
|
||||
"revision" : "488aa66d157a648901b61721212c0dec23d27ee5",
|
||||
"version" : "0.1.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "tabman",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/uias/Tabman",
|
||||
"state" : {
|
||||
"revision" : "4a4f7c755b875ffd4f9ef10d67a67883669d2465",
|
||||
"version" : "2.13.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "tocropviewcontroller",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/TimOliver/TOCropViewController.git",
|
||||
"state" : {
|
||||
"revision" : "d0470491f56e734731bbf77991944c0dfdee3e0e",
|
||||
"version" : "2.6.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "uihostingconfigurationbackport",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/woxtu/UIHostingConfigurationBackport.git",
|
||||
"state" : {
|
||||
"revision" : "6091f2d38faa4b24fc2ca0389c651e2f666624a3",
|
||||
"version" : "0.1.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "uitextview-placeholder",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/MainasuK/UITextView-Placeholder.git",
|
||||
"state" : {
|
||||
"revision" : "20f513ded04a040cdf5467f0891849b1763ede3b",
|
||||
"version" : "1.4.1"
|
||||
}
|
||||
}
|
||||
],
|
||||
"version" : 2
|
||||
}
|
|
@ -42,7 +42,6 @@ let package = Package(
|
|||
.package(url: "https://github.com/apple/swift-collections.git", from: "1.0.3"),
|
||||
.package(url: "https://github.com/apple/swift-nio.git", from: "2.0.0"),
|
||||
.package(url: "https://github.com/Flipboard/FLAnimatedImage.git", from: "1.0.0"),
|
||||
.package(url: "https://github.com/kean/Nuke-FLAnimatedImage-Plugin.git", from: "8.0.0"),
|
||||
.package(url: "https://github.com/kean/Nuke.git", from: "10.3.1"),
|
||||
.package(url: "https://github.com/kishikawakatsumi/KeychainAccess.git", from: "4.2.2"),
|
||||
.package(url: "https://github.com/slackhq/PanModal.git", from: "1.2.7"),
|
||||
|
@ -54,6 +53,7 @@ let package = Package(
|
|||
.package(url: "https://github.com/SDWebImage/SDWebImage.git", from: "5.12.0"),
|
||||
.package(url: "https://github.com/eneko/Stripes.git", from: "0.2.0"),
|
||||
.package(url: "https://github.com/NextLevel/NextLevelSessionExporter.git", from: "0.4.6"),
|
||||
.package(url: "https://github.com/xmartlabs/XLPagerTabStrip.git", from: "9.1.0"),
|
||||
],
|
||||
targets: [
|
||||
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
|
||||
|
@ -126,6 +126,8 @@ let package = Package(
|
|||
.product(name: "PanModal", package: "PanModal"),
|
||||
.product(name: "Stripes", package: "Stripes"),
|
||||
.product(name: "NextLevelSessionExporter", package: "NextLevelSessionExporter"),
|
||||
.product(name: "SDWebImage", package: "SDWebImage"),
|
||||
.product(name: "XLPagerTabStrip", package: "XLPagerTabStrip"),
|
||||
]
|
||||
),
|
||||
.testTarget(
|
||||
|
|
|
@ -1,17 +1,15 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "dark.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "dark@2x.png",
|
||||
"filename" : "about_instance_placeholder@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "dark@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
After Width: | Height: | Size: 68 KiB |
|
@ -1,23 +0,0 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "automatic.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "automatic@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "automatic@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 97 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 95 KiB |
|
@ -1,23 +0,0 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "light.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "light@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "light@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 96 KiB |
|
@ -219,9 +219,7 @@ public enum Asset {
|
|||
}
|
||||
}
|
||||
public enum Settings {
|
||||
public static let automatic = ImageAsset(name: "Settings/automatic")
|
||||
public static let dark = ImageAsset(name: "Settings/dark")
|
||||
public static let light = ImageAsset(name: "Settings/light")
|
||||
public static let aboutInstancePlaceholder = ImageAsset(name: "Settings/about_instance_placeholder")
|
||||
}
|
||||
public enum Theme {
|
||||
public enum System {
|
||||
|
|
|
@ -24,4 +24,8 @@ extension APIService {
|
|||
) -> AnyPublisher<Mastodon.Response.Content<Mastodon.Entity.V2.Instance>, Error> {
|
||||
return Mastodon.API.V2.Instance.instance(session: session, domain: domain)
|
||||
}
|
||||
|
||||
public func extendedDescription(domain: String) -> AnyPublisher<Mastodon.Response.Content<Mastodon.Entity.ExtendedDescription>, Error> {
|
||||
return Mastodon.API.Instance.extendedDescription(session: session, domain: domain)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1418,7 +1418,7 @@ public enum L10n {
|
|||
public enum Settings {
|
||||
public enum AboutMastodon {
|
||||
/// Clear Media Storage
|
||||
public static let cleaerMediaStorage = L10n.tr("Localizable", "Scene.Settings.AboutMastodon.CleaerMediaStorage", fallback: "Clear Media Storage")
|
||||
public static let clearMediaStorage = L10n.tr("Localizable", "Scene.Settings.AboutMastodon.ClearMediaStorage", fallback: "Clear Media Storage")
|
||||
/// Contribute to Mastodon
|
||||
public static let contributeToMastodon = L10n.tr("Localizable", "Scene.Settings.AboutMastodon.ContributeToMastodon", fallback: "Contribute to Mastodon")
|
||||
/// Even More Settings
|
||||
|
@ -1509,6 +1509,8 @@ public enum L10n {
|
|||
}
|
||||
/// Notifications
|
||||
public static let notifications = L10n.tr("Localizable", "Scene.Settings.Overview.Notifications", fallback: "Notifications")
|
||||
/// Server Details
|
||||
public static let serverDetails = L10n.tr("Localizable", "Scene.Settings.Overview.ServerDetails", fallback: "Server Details")
|
||||
/// Support Mastodon
|
||||
public static let supportMastodon = L10n.tr("Localizable", "Scene.Settings.Overview.SupportMastodon", fallback: "Support Mastodon")
|
||||
/// Settings
|
||||
|
@ -1592,6 +1594,20 @@ public enum L10n {
|
|||
public static let title = L10n.tr("Localizable", "Scene.Settings.Section.SpicyZone.Title", fallback: "The Spicy Zone")
|
||||
}
|
||||
}
|
||||
public enum ServerDetails {
|
||||
/// About
|
||||
public static let about = L10n.tr("Localizable", "Scene.Settings.ServerDetails.About", fallback: "About")
|
||||
/// Rules
|
||||
public static let rules = L10n.tr("Localizable", "Scene.Settings.ServerDetails.Rules", fallback: "Rules")
|
||||
public enum AboutInstance {
|
||||
/// A legal notice
|
||||
public static let legalNotice = L10n.tr("Localizable", "Scene.Settings.ServerDetails.AboutInstance.LegalNotice", fallback: "A legal notice")
|
||||
/// Message Admin
|
||||
public static let messageAdmin = L10n.tr("Localizable", "Scene.Settings.ServerDetails.AboutInstance.MessageAdmin", fallback: "Message Admin")
|
||||
/// Administrator
|
||||
public static let title = L10n.tr("Localizable", "Scene.Settings.ServerDetails.AboutInstance.Title", fallback: "Administrator")
|
||||
}
|
||||
}
|
||||
}
|
||||
public enum SuggestionAccount {
|
||||
/// Follow all
|
||||
|
|
|
@ -527,6 +527,7 @@ uploaded to Mastodon.";
|
|||
"Scene.Settings.Overview.General" = "General";
|
||||
"Scene.Settings.Overview.Notifications" = "Notifications";
|
||||
"Scene.Settings.Overview.SupportMastodon" = "Support Mastodon";
|
||||
"Scene.Settings.Overview.ServerDetails" = "Server Details";
|
||||
"Scene.Settings.Overview.AboutMastodon" = "About Mastodon";
|
||||
"Scene.Settings.Overview.Logout" = "Logout %@";
|
||||
|
||||
|
@ -534,7 +535,13 @@ uploaded to Mastodon.";
|
|||
"Scene.Settings.AboutMastodon.MoreSettings" = "Even More Settings";
|
||||
"Scene.Settings.AboutMastodon.ContributeToMastodon" = "Contribute to Mastodon";
|
||||
"Scene.Settings.AboutMastodon.PrivacyPolicy" = "Privacy Policy";
|
||||
"Scene.Settings.AboutMastodon.CleaerMediaStorage" = "Clear Media Storage";
|
||||
"Scene.Settings.AboutMastodon.ClearMediaStorage" = "Clear Media Storage";
|
||||
|
||||
"Scene.Settings.ServerDetails.About" = "About";
|
||||
"Scene.Settings.ServerDetails.Rules" = "Rules";
|
||||
"Scene.Settings.ServerDetails.AboutInstance.Title" = "Administrator";
|
||||
"Scene.Settings.ServerDetails.AboutInstance.MessageAdmin" = "Message Admin";
|
||||
"Scene.Settings.ServerDetails.AboutInstance.LegalNotice" = "A legal notice";
|
||||
|
||||
"Scene.Settings.General.Title" = "General";
|
||||
"Scene.Settings.General.Appearance.SectionTitle" = "Appearance";
|
||||
|
|
|
@ -527,6 +527,7 @@ uploaded to Mastodon.";
|
|||
"Scene.Settings.Overview.General" = "General";
|
||||
"Scene.Settings.Overview.Notifications" = "Notifications";
|
||||
"Scene.Settings.Overview.SupportMastodon" = "Support Mastodon";
|
||||
"Scene.Settings.Overview.ServerDetails" = "Server Details";
|
||||
"Scene.Settings.Overview.AboutMastodon" = "About Mastodon";
|
||||
"Scene.Settings.Overview.Logout" = "Logout %@";
|
||||
|
||||
|
@ -534,7 +535,13 @@ uploaded to Mastodon.";
|
|||
"Scene.Settings.AboutMastodon.MoreSettings" = "Even More Settings";
|
||||
"Scene.Settings.AboutMastodon.ContributeToMastodon" = "Contribute to Mastodon";
|
||||
"Scene.Settings.AboutMastodon.PrivacyPolicy" = "Privacy Policy";
|
||||
"Scene.Settings.AboutMastodon.CleaerMediaStorage" = "Clear Media Storage";
|
||||
"Scene.Settings.AboutMastodon.ClearMediaStorage" = "Clear Media Storage";
|
||||
|
||||
"Scene.Settings.ServerDetails.About" = "About";
|
||||
"Scene.Settings.ServerDetails.Rules" = "Rules";
|
||||
"Scene.Settings.ServerDetails.AboutInstance.Title" = "Administrator";
|
||||
"Scene.Settings.ServerDetails.AboutInstance.MessageAdmin" = "Message Admin";
|
||||
"Scene.Settings.ServerDetails.AboutInstance.LegalNotice" = "A legal notice";
|
||||
|
||||
"Scene.Settings.General.Title" = "General";
|
||||
"Scene.Settings.General.Appearance.SectionTitle" = "Appearance";
|
||||
|
|
|
@ -30,11 +30,7 @@ extension Mastodon.API.Instance {
|
|||
session: URLSession,
|
||||
domain: String
|
||||
) -> AnyPublisher<Mastodon.Response.Content<Mastodon.Entity.Instance>, Error> {
|
||||
let request = Mastodon.API.get(
|
||||
url: instanceEndpointURL(domain: domain),
|
||||
query: nil,
|
||||
authorization: nil
|
||||
)
|
||||
let request = Mastodon.API.get(url: instanceEndpointURL(domain: domain))
|
||||
return session.dataTaskPublisher(for: request)
|
||||
.tryMap { data, response in
|
||||
let value: Mastodon.Entity.Instance
|
||||
|
@ -53,5 +49,27 @@ extension Mastodon.API.Instance {
|
|||
}
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
|
||||
static func extendedDescriptionEndpointURL(domain: String) -> URL {
|
||||
return Mastodon.API.endpointURL(domain: domain).appendingPathComponent("instance").appendingPathComponent("extended_description")
|
||||
}
|
||||
|
||||
/// Extended description of the server
|
||||
///
|
||||
/// - Returns: A ``MastodonSDK.Mastodon.Entity.ExtendedDescription``
|
||||
///
|
||||
/// ## Reference:
|
||||
/// [Document](https://docs.joinmastodon.org/methods/instance/#extended_description)
|
||||
public static func extendedDescription(
|
||||
session: URLSession,
|
||||
domain: String
|
||||
) -> AnyPublisher<Mastodon.Response.Content<Mastodon.Entity.ExtendedDescription>, Error> {
|
||||
let request = Mastodon.API.get(url: extendedDescriptionEndpointURL(domain: domain))
|
||||
return session.dataTaskPublisher(for: request)
|
||||
.tryMap { data, response in
|
||||
let value = try Mastodon.API.decode(type: Mastodon.Entity.ExtendedDescription.self, from: data, response: response)
|
||||
return Mastodon.Response.Content(value: value, response: response)
|
||||
}
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
// Copyright © 2023 Mastodon gGmbH. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
|
||||
extension Mastodon.Entity {
|
||||
/// Extended description of the server
|
||||
|
||||
/// ## Reference:
|
||||
/// [Document](https://docs.joinmastodon.org/entities/ExtendedDescription/)
|
||||
public struct ExtendedDescription: Codable {
|
||||
public let updatedAt: Date
|
||||
public let content: String
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case updatedAt = "updated_at"
|
||||
case content
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,12 +10,11 @@ extension Mastodon.Entity.V2 {
|
|||
/// # Reference
|
||||
/// [Document](https://docs.joinmastodon.org/entities/instance/)
|
||||
public struct Instance: Codable {
|
||||
|
||||
|
||||
public let domain: String?
|
||||
public let title: String
|
||||
public let description: String
|
||||
public let shortDescription: String?
|
||||
public let email: String?
|
||||
public let version: String?
|
||||
public let languages: [String]? // (ISO 639 Part 1-5 language codes)
|
||||
public let registrations: Mastodon.Entity.V2.Instance.Registrations?
|
||||
|
@ -25,7 +24,7 @@ extension Mastodon.Entity.V2 {
|
|||
public let statistics: Mastodon.Entity.Instance.Statistics?
|
||||
|
||||
public let thumbnail: Thumbnail?
|
||||
public let contactAccount: Mastodon.Entity.Account?
|
||||
public let contact: Mastodon.Entity.V2.Instance.Contact?
|
||||
public let rules: [Mastodon.Entity.Instance.Rule]?
|
||||
|
||||
// https://github.com/mastodon/mastodon/pull/16485
|
||||
|
@ -36,7 +35,7 @@ extension Mastodon.Entity.V2 {
|
|||
self.title = domain
|
||||
self.description = ""
|
||||
self.shortDescription = nil
|
||||
self.email = ""
|
||||
self.contact = nil
|
||||
self.version = nil
|
||||
self.languages = nil
|
||||
self.registrations = nil
|
||||
|
@ -45,7 +44,6 @@ extension Mastodon.Entity.V2 {
|
|||
self.urls = nil
|
||||
self.statistics = nil
|
||||
self.thumbnail = nil
|
||||
self.contactAccount = nil
|
||||
self.rules = nil
|
||||
self.configuration = nil
|
||||
}
|
||||
|
@ -55,7 +53,6 @@ extension Mastodon.Entity.V2 {
|
|||
case title
|
||||
case description
|
||||
case shortDescription = "short_description"
|
||||
case email
|
||||
case version
|
||||
case languages
|
||||
case registrations
|
||||
|
@ -65,7 +62,7 @@ extension Mastodon.Entity.V2 {
|
|||
case statistics = "stats"
|
||||
|
||||
case thumbnail
|
||||
case contactAccount = "contact_account"
|
||||
case contact
|
||||
case rules
|
||||
|
||||
case configuration
|
||||
|
@ -106,3 +103,10 @@ extension Mastodon.Entity.V2.Instance {
|
|||
public let url: String?
|
||||
}
|
||||
}
|
||||
|
||||
extension Mastodon.Entity.V2.Instance {
|
||||
public struct Contact: Codable {
|
||||
public let email: String?
|
||||
public let account: Mastodon.Entity.Account?
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ extension MetaLabel {
|
|||
case accountListUsername
|
||||
case sidebarHeadline(isSelected: Bool)
|
||||
case sidebarSubheadline(isSelected: Bool)
|
||||
case aboutInstance
|
||||
}
|
||||
|
||||
public convenience init(style: Style) {
|
||||
|
@ -129,6 +130,10 @@ extension MetaLabel {
|
|||
case .sidebarSubheadline(let isSelected):
|
||||
font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 13, weight: .regular), maximumPointSize: 18)
|
||||
textColor = isSelected ? .white : Asset.Colors.Label.secondary.color
|
||||
case .aboutInstance:
|
||||
font = UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 17, weight: .regular))
|
||||
textColor = .label
|
||||
paragraphStyle.paragraphSpacing = 0
|
||||
}
|
||||
|
||||
self.font = font
|
||||
|
|
|
@ -163,7 +163,7 @@ public class CondensedUserView: UIView {
|
|||
}
|
||||
}
|
||||
|
||||
public func configure(with account: Mastodon.Entity.Account) {
|
||||
public func configure(with account: Mastodon.Entity.Account, showFollowers: Bool = true) {
|
||||
let displayNameMetaContent: MetaContent
|
||||
do {
|
||||
let content = MastodonContent(content: account.displayNameWithFallback, emojis: account.emojis?.asDictionary ?? [:])
|
||||
|
@ -174,10 +174,16 @@ public class CondensedUserView: UIView {
|
|||
|
||||
displayNameLabel.configure(content: displayNameMetaContent)
|
||||
acctLabel.text = account.acct
|
||||
followersLabel.attributedText = NSAttributedString(
|
||||
format: NSAttributedString(string: L10n.Common.UserList.followersCount("%@"), attributes: [.font: UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 15, weight: .regular))]),
|
||||
args: NSAttributedString(string: Self.metricFormatter.string(from: account.followersCount) ?? account.followersCount.formatted(), attributes: [.font: UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 15, weight: .bold))])
|
||||
)
|
||||
|
||||
if showFollowers {
|
||||
followersLabel.attributedText = NSAttributedString(
|
||||
format: NSAttributedString(string: L10n.Common.UserList.followersCount("%@"), attributes: [.font: UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 15, weight: .regular))]),
|
||||
args: NSAttributedString(string: Self.metricFormatter.string(from: account.followersCount) ?? account.followersCount.formatted(), attributes: [.font: UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 15, weight: .bold))])
|
||||
)
|
||||
followersLabel.isHidden = false
|
||||
} else {
|
||||
followersLabel.isHidden = false
|
||||
}
|
||||
|
||||
avatarImageView.setImage(url: account.avatarImageURL())
|
||||
|
||||
|
|
5
Podfile
|
@ -7,11 +7,6 @@ target 'Mastodon' do
|
|||
# Comment the next line if you don't want to use dynamic frameworks
|
||||
use_frameworks!
|
||||
|
||||
# Pods for Mastodon
|
||||
|
||||
# UI
|
||||
pod 'XLPagerTabStrip', '~> 9.0.0'
|
||||
|
||||
# misc
|
||||
pod 'SwiftGen', '~> 6.6.2'
|
||||
pod 'Kanna', '~> 5.2.2'
|
||||
|
|
|
@ -4,27 +4,23 @@ PODS:
|
|||
- Sourcery/CLI-Only (= 1.9.2)
|
||||
- Sourcery/CLI-Only (1.9.2)
|
||||
- SwiftGen (6.6.2)
|
||||
- XLPagerTabStrip (9.0.0)
|
||||
|
||||
DEPENDENCIES:
|
||||
- Kanna (~> 5.2.2)
|
||||
- Sourcery (~> 1.9)
|
||||
- SwiftGen (~> 6.6.2)
|
||||
- XLPagerTabStrip (~> 9.0.0)
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- Kanna
|
||||
- Sourcery
|
||||
- SwiftGen
|
||||
- XLPagerTabStrip
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
Kanna: 01cfbddc127f5ff0963692f285fcbc8a9d62d234
|
||||
Sourcery: 179539341c2261068528cd15a31837b7238fd901
|
||||
SwiftGen: 1366a7f71aeef49954ca5a63ba4bef6b0f24138c
|
||||
XLPagerTabStrip: 61c57fd61f611ee5f01ff1495ad6fbee8bf496c5
|
||||
|
||||
PODFILE CHECKSUM: 8c962b3cbb4c225f1e57fb2e4ca03d1f22c45e5e
|
||||
PODFILE CHECKSUM: 597c21d7aa08efec996048577c3c4fbeffbb6305
|
||||
|
||||
COCOAPODS: 1.13.0
|
||||
|
|