Refactoring
This commit is contained in:
parent
ee3407dd69
commit
f9ffe542a5
|
@ -14,18 +14,14 @@
|
|||
F80048082961E6DE00E6868A /* StatusDataHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F80048072961E6DE00E6868A /* StatusDataHandler.swift */; };
|
||||
F800480A2961EA1900E6868A /* AttachmentDataHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F80048092961EA1900E6868A /* AttachmentDataHandler.swift */; };
|
||||
F802884F297AEED5000BDD51 /* DatabaseError.swift in Sources */ = {isa = PBXBuildFile; fileRef = F802884E297AEED5000BDD51 /* DatabaseError.swift */; };
|
||||
F80864112975537F009F035C /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F80864102975537F009F035C /* NotificationService.swift */; };
|
||||
F808641429756666009F035C /* NotificationRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = F808641329756666009F035C /* NotificationRow.swift */; };
|
||||
F8121CA5298A819100B466C7 /* InstanceService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8121CA4298A819100B466C7 /* InstanceService.swift */; };
|
||||
F8121CA8298A86D600B466C7 /* InstanceRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8121CA7298A86D600B466C7 /* InstanceRow.swift */; };
|
||||
F8163776297C3E3D00E6E04A /* PublicTimelineService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8163775297C3E3D00E6E04A /* PublicTimelineService.swift */; };
|
||||
F8210DCF2966B600001D9973 /* ImageRowAsync.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8210DCE2966B600001D9973 /* ImageRowAsync.swift */; };
|
||||
F8210DD52966BB7E001D9973 /* Nuke in Frameworks */ = {isa = PBXBuildFile; productRef = F8210DD42966BB7E001D9973 /* Nuke */; };
|
||||
F8210DD72966BB7E001D9973 /* NukeExtensions in Frameworks */ = {isa = PBXBuildFile; productRef = F8210DD62966BB7E001D9973 /* NukeExtensions */; };
|
||||
F8210DD92966BB7E001D9973 /* NukeUI in Frameworks */ = {isa = PBXBuildFile; productRef = F8210DD82966BB7E001D9973 /* NukeUI */; };
|
||||
F8210DDD2966CF17001D9973 /* StatusData+Status.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8210DDC2966CF17001D9973 /* StatusData+Status.swift */; };
|
||||
F8210DDF2966CFC7001D9973 /* AttachmentData+Attachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8210DDE2966CFC7001D9973 /* AttachmentData+Attachment.swift */; };
|
||||
F8210DE12966D0C4001D9973 /* StatusService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8210DE02966D0C4001D9973 /* StatusService.swift */; };
|
||||
F8210DE52966E160001D9973 /* Color+SystemColors.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8210DE42966E160001D9973 /* Color+SystemColors.swift */; };
|
||||
F8210DE72966E1D1001D9973 /* Color+Assets.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8210DE62966E1D1001D9973 /* Color+Assets.swift */; };
|
||||
F8210DEA2966E4F9001D9973 /* AnimatePlaceholderModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8210DE92966E4F9001D9973 /* AnimatePlaceholderModifier.swift */; };
|
||||
|
@ -83,7 +79,6 @@
|
|||
F88C2482295C3A4F0006098B /* StatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88C2481295C3A4F0006098B /* StatusView.swift */; };
|
||||
F88E4D42297E69FD0057491A /* StatusesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88E4D41297E69FD0057491A /* StatusesView.swift */; };
|
||||
F88E4D44297E82EB0057491A /* Status+MediaAttachmentType.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88E4D43297E82EB0057491A /* Status+MediaAttachmentType.swift */; };
|
||||
F88E4D46297E89DF0057491A /* TrendsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88E4D45297E89DF0057491A /* TrendsService.swift */; };
|
||||
F88E4D48297E90CD0057491A /* TrendStatusesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88E4D47297E90CD0057491A /* TrendStatusesView.swift */; };
|
||||
F88E4D4A297EA0490057491A /* RouterPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88E4D49297EA0490057491A /* RouterPath.swift */; };
|
||||
F88E4D4D297EA4290057491A /* EmojiText in Frameworks */ = {isa = PBXBuildFile; productRef = F88E4D4C297EA4290057491A /* EmojiText */; };
|
||||
|
@ -91,7 +86,6 @@
|
|||
F88E4D52297EA6DA0057491A /* String+Markdown.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88E4D51297EA6DA0057491A /* String+Markdown.swift */; };
|
||||
F88E4D54297EA7EE0057491A /* MarkdownFormattedText.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88E4D53297EA7EE0057491A /* MarkdownFormattedText.swift */; };
|
||||
F88E4D56297EAD6E0057491A /* AppRouteur.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88E4D55297EAD6E0057491A /* AppRouteur.swift */; };
|
||||
F88E4D5A297ECEE60057491A /* SearchService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88E4D59297ECEE60057491A /* SearchService.swift */; };
|
||||
F88FAD21295F3944009B20C9 /* HomeFeedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88FAD20295F3944009B20C9 /* HomeFeedView.swift */; };
|
||||
F88FAD27295F400E009B20C9 /* NotificationsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88FAD26295F400E009B20C9 /* NotificationsView.swift */; };
|
||||
F88FAD2A295F43B8009B20C9 /* AccountData+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88FAD28295F43B8009B20C9 /* AccountData+CoreDataClass.swift */; };
|
||||
|
@ -119,14 +113,21 @@
|
|||
F89D6C4629718193001DA3D4 /* ThemeSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = F89D6C4529718193001DA3D4 /* ThemeSection.swift */; };
|
||||
F89D6C4A297196FF001DA3D4 /* ImagesViewer.swift in Sources */ = {isa = PBXBuildFile; fileRef = F89D6C49297196FF001DA3D4 /* ImagesViewer.swift */; };
|
||||
F8A93D7E2965FD89001D8331 /* UserProfileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8A93D7D2965FD89001D8331 /* UserProfileView.swift */; };
|
||||
F8A93D802965FED4001D8331 /* AccountService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8A93D7F2965FED4001D8331 /* AccountService.swift */; };
|
||||
F8B1E64F2973F61400EE0D10 /* Drops in Frameworks */ = {isa = PBXBuildFile; productRef = F8B1E64E2973F61400EE0D10 /* Drops */; };
|
||||
F8B1E6512973FB7E00EE0D10 /* ToastrService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8B1E6502973FB7E00EE0D10 /* ToastrService.swift */; };
|
||||
F8B9B345298D1FCB009CC69C /* Client.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8B9B344298D1FCB009CC69C /* Client.swift */; };
|
||||
F8B9B347298D4A7C009CC69C /* Client+Trends.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8B9B346298D4A7C009CC69C /* Client+Trends.swift */; };
|
||||
F8B9B349298D4AA2009CC69C /* Client+Timeline.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8B9B348298D4AA2009CC69C /* Client+Timeline.swift */; };
|
||||
F8B9B34B298D4ACE009CC69C /* Client+Tags.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8B9B34A298D4ACE009CC69C /* Client+Tags.swift */; };
|
||||
F8B9B34D298D4AE4009CC69C /* Client+Notifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8B9B34C298D4AE4009CC69C /* Client+Notifications.swift */; };
|
||||
F8B9B34F298D4B14009CC69C /* Client+Statuses.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8B9B34E298D4B14009CC69C /* Client+Statuses.swift */; };
|
||||
F8B9B351298D4B34009CC69C /* Client+Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8B9B350298D4B34009CC69C /* Client+Account.swift */; };
|
||||
F8B9B353298D4B5D009CC69C /* Client+Search.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8B9B352298D4B5D009CC69C /* Client+Search.swift */; };
|
||||
F8B9B356298D4C1E009CC69C /* Client+Instance.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8B9B355298D4C1E009CC69C /* Client+Instance.swift */; };
|
||||
F8C14392296AF0B3001FE31D /* String+Exif.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8C14391296AF0B3001FE31D /* String+Exif.swift */; };
|
||||
F8C14394296AF21B001FE31D /* Double+Round.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8C14393296AF21B001FE31D /* Double+Round.swift */; };
|
||||
F8C5E55F2988E92600ADF6A7 /* AccountModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8C5E55E2988E92600ADF6A7 /* AccountModel.swift */; };
|
||||
F8C5E56229892CC300ADF6A7 /* FirstAppear.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8C5E56129892CC300ADF6A7 /* FirstAppear.swift */; };
|
||||
F8C7EDBF298169EE002843BC /* TagsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8C7EDBE298169EE002843BC /* TagsService.swift */; };
|
||||
F8CC95CE2970761D00C9C2AC /* TintColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8CC95CD2970761D00C9C2AC /* TintColor.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
|
@ -138,15 +139,11 @@
|
|||
F80048072961E6DE00E6868A /* StatusDataHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusDataHandler.swift; sourceTree = "<group>"; };
|
||||
F80048092961EA1900E6868A /* AttachmentDataHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttachmentDataHandler.swift; sourceTree = "<group>"; };
|
||||
F802884E297AEED5000BDD51 /* DatabaseError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseError.swift; sourceTree = "<group>"; };
|
||||
F80864102975537F009F035C /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = "<group>"; };
|
||||
F808641329756666009F035C /* NotificationRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationRow.swift; sourceTree = "<group>"; };
|
||||
F8121CA4298A819100B466C7 /* InstanceService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstanceService.swift; sourceTree = "<group>"; };
|
||||
F8121CA7298A86D600B466C7 /* InstanceRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstanceRow.swift; sourceTree = "<group>"; };
|
||||
F8163775297C3E3D00E6E04A /* PublicTimelineService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PublicTimelineService.swift; sourceTree = "<group>"; };
|
||||
F8210DCE2966B600001D9973 /* ImageRowAsync.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageRowAsync.swift; sourceTree = "<group>"; };
|
||||
F8210DDC2966CF17001D9973 /* StatusData+Status.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "StatusData+Status.swift"; sourceTree = "<group>"; };
|
||||
F8210DDE2966CFC7001D9973 /* AttachmentData+Attachment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AttachmentData+Attachment.swift"; sourceTree = "<group>"; };
|
||||
F8210DE02966D0C4001D9973 /* StatusService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusService.swift; sourceTree = "<group>"; };
|
||||
F8210DE42966E160001D9973 /* Color+SystemColors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Color+SystemColors.swift"; sourceTree = "<group>"; };
|
||||
F8210DE62966E1D1001D9973 /* Color+Assets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Color+Assets.swift"; sourceTree = "<group>"; };
|
||||
F8210DE92966E4F9001D9973 /* AnimatePlaceholderModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnimatePlaceholderModifier.swift; sourceTree = "<group>"; };
|
||||
|
@ -207,13 +204,11 @@
|
|||
F88C2481295C3A4F0006098B /* StatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusView.swift; sourceTree = "<group>"; };
|
||||
F88E4D41297E69FD0057491A /* StatusesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusesView.swift; sourceTree = "<group>"; };
|
||||
F88E4D43297E82EB0057491A /* Status+MediaAttachmentType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Status+MediaAttachmentType.swift"; sourceTree = "<group>"; };
|
||||
F88E4D45297E89DF0057491A /* TrendsService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrendsService.swift; sourceTree = "<group>"; };
|
||||
F88E4D47297E90CD0057491A /* TrendStatusesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrendStatusesView.swift; sourceTree = "<group>"; };
|
||||
F88E4D49297EA0490057491A /* RouterPath.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RouterPath.swift; sourceTree = "<group>"; };
|
||||
F88E4D51297EA6DA0057491A /* String+Markdown.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Markdown.swift"; sourceTree = "<group>"; };
|
||||
F88E4D53297EA7EE0057491A /* MarkdownFormattedText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkdownFormattedText.swift; sourceTree = "<group>"; };
|
||||
F88E4D55297EAD6E0057491A /* AppRouteur.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppRouteur.swift; sourceTree = "<group>"; };
|
||||
F88E4D59297ECEE60057491A /* SearchService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchService.swift; sourceTree = "<group>"; };
|
||||
F88FAD20295F3944009B20C9 /* HomeFeedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeFeedView.swift; sourceTree = "<group>"; };
|
||||
F88FAD26295F400E009B20C9 /* NotificationsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsView.swift; sourceTree = "<group>"; };
|
||||
F88FAD28295F43B8009B20C9 /* AccountData+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AccountData+CoreDataClass.swift"; sourceTree = "<group>"; };
|
||||
|
@ -240,13 +235,20 @@
|
|||
F89D6C4529718193001DA3D4 /* ThemeSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemeSection.swift; sourceTree = "<group>"; };
|
||||
F89D6C49297196FF001DA3D4 /* ImagesViewer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImagesViewer.swift; sourceTree = "<group>"; };
|
||||
F8A93D7D2965FD89001D8331 /* UserProfileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfileView.swift; sourceTree = "<group>"; };
|
||||
F8A93D7F2965FED4001D8331 /* AccountService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountService.swift; sourceTree = "<group>"; };
|
||||
F8B1E6502973FB7E00EE0D10 /* ToastrService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToastrService.swift; sourceTree = "<group>"; };
|
||||
F8B9B344298D1FCB009CC69C /* Client.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Client.swift; sourceTree = "<group>"; };
|
||||
F8B9B346298D4A7C009CC69C /* Client+Trends.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Client+Trends.swift"; sourceTree = "<group>"; };
|
||||
F8B9B348298D4AA2009CC69C /* Client+Timeline.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Client+Timeline.swift"; sourceTree = "<group>"; };
|
||||
F8B9B34A298D4ACE009CC69C /* Client+Tags.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Client+Tags.swift"; sourceTree = "<group>"; };
|
||||
F8B9B34C298D4AE4009CC69C /* Client+Notifications.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Client+Notifications.swift"; sourceTree = "<group>"; };
|
||||
F8B9B34E298D4B14009CC69C /* Client+Statuses.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Client+Statuses.swift"; sourceTree = "<group>"; };
|
||||
F8B9B350298D4B34009CC69C /* Client+Account.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Client+Account.swift"; sourceTree = "<group>"; };
|
||||
F8B9B352298D4B5D009CC69C /* Client+Search.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Client+Search.swift"; sourceTree = "<group>"; };
|
||||
F8B9B355298D4C1E009CC69C /* Client+Instance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Client+Instance.swift"; sourceTree = "<group>"; };
|
||||
F8C14391296AF0B3001FE31D /* String+Exif.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Exif.swift"; sourceTree = "<group>"; };
|
||||
F8C14393296AF21B001FE31D /* Double+Round.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Double+Round.swift"; sourceTree = "<group>"; };
|
||||
F8C5E55E2988E92600ADF6A7 /* AccountModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountModel.swift; sourceTree = "<group>"; };
|
||||
F8C5E56129892CC300ADF6A7 /* FirstAppear.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirstAppear.swift; sourceTree = "<group>"; };
|
||||
F8C7EDBE298169EE002843BC /* TagsService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TagsService.swift; sourceTree = "<group>"; };
|
||||
F8C937A929882CA90004D782 /* Vernissage-001.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Vernissage-001.xcdatamodel"; sourceTree = "<group>"; };
|
||||
F8CC95CD2970761D00C9C2AC /* TintColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TintColor.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
@ -348,7 +350,6 @@
|
|||
F89992CD296D92E7005994BF /* AttachmentModel.swift */,
|
||||
F898DE7129728CB2004B4A6A /* CommentModel.swift */,
|
||||
F8C5E55E2988E92600ADF6A7 /* AccountModel.swift */,
|
||||
F88FAD2C295F4AD7009B20C9 /* ApplicationState.swift */,
|
||||
F866F6AD29606367002E8F88 /* ApplicationViewMode.swift */,
|
||||
F8CC95CD2970761D00C9C2AC /* TintColor.swift */,
|
||||
F89D6C3E29716E41001DA3D4 /* Theme.swift */,
|
||||
|
@ -463,6 +464,7 @@
|
|||
F83901A2295D863B00456AE2 /* Widgets */,
|
||||
F8341F96295C6427009C8EE6 /* CoreData */,
|
||||
F8341F95295C640C009C8EE6 /* Models */,
|
||||
F8B9B354298D4B88009CC69C /* EnvironmentObjects */,
|
||||
F8341F94295C63FE009C8EE6 /* Extensions */,
|
||||
F8341F93295C63E2009C8EE6 /* Views */,
|
||||
F88C246B295C37B80006098B /* VernissageApp.swift */,
|
||||
|
@ -491,19 +493,11 @@
|
|||
F85D4970296402DC00751DF7 /* AuthorizationService.swift */,
|
||||
F87AEB912986C44E00434FB6 /* AuthorizationSession.swift */,
|
||||
F85D4974296407F100751DF7 /* HomeTimelineService.swift */,
|
||||
F8A93D7F2965FED4001D8331 /* AccountService.swift */,
|
||||
F8210DE02966D0C4001D9973 /* StatusService.swift */,
|
||||
F8B1E6502973FB7E00EE0D10 /* ToastrService.swift */,
|
||||
F85E131F297409CD006A051D /* ErrorsService.swift */,
|
||||
F80864102975537F009F035C /* NotificationService.swift */,
|
||||
F886F256297859E300879356 /* CacheImageService.swift */,
|
||||
F8163775297C3E3D00E6E04A /* PublicTimelineService.swift */,
|
||||
F88E4D45297E89DF0057491A /* TrendsService.swift */,
|
||||
F88E4D49297EA0490057491A /* RouterPath.swift */,
|
||||
F88E4D59297ECEE60057491A /* SearchService.swift */,
|
||||
F8C7EDBE298169EE002843BC /* TagsService.swift */,
|
||||
F829193B2983012400367CE2 /* ImageSizeService.swift */,
|
||||
F8121CA4298A819100B466C7 /* InstanceService.swift */,
|
||||
);
|
||||
path = Services;
|
||||
sourceTree = "<group>";
|
||||
|
@ -553,6 +547,23 @@
|
|||
path = StatusView;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F8B9B354298D4B88009CC69C /* EnvironmentObjects */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F88FAD2C295F4AD7009B20C9 /* ApplicationState.swift */,
|
||||
F8B9B344298D1FCB009CC69C /* Client.swift */,
|
||||
F8B9B346298D4A7C009CC69C /* Client+Trends.swift */,
|
||||
F8B9B348298D4AA2009CC69C /* Client+Timeline.swift */,
|
||||
F8B9B34A298D4ACE009CC69C /* Client+Tags.swift */,
|
||||
F8B9B34C298D4AE4009CC69C /* Client+Notifications.swift */,
|
||||
F8B9B34E298D4B14009CC69C /* Client+Statuses.swift */,
|
||||
F8B9B350298D4B34009CC69C /* Client+Account.swift */,
|
||||
F8B9B352298D4B5D009CC69C /* Client+Search.swift */,
|
||||
F8B9B355298D4C1E009CC69C /* Client+Instance.swift */,
|
||||
);
|
||||
path = EnvironmentObjects;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F8C5E56029892C8A00ADF6A7 /* ViewModifiers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -657,12 +668,11 @@
|
|||
F866F6A0296040A8002E8F88 /* ApplicationSettings+CoreDataClass.swift in Sources */,
|
||||
F8764189298ABEC80057D362 /* ErrorView.swift in Sources */,
|
||||
F8210DEA2966E4F9001D9973 /* AnimatePlaceholderModifier.swift in Sources */,
|
||||
F8163776297C3E3D00E6E04A /* PublicTimelineService.swift in Sources */,
|
||||
F886F257297859E300879356 /* CacheImageService.swift in Sources */,
|
||||
F8984E4D296B648000A2610F /* UIImage+Blurhash.swift in Sources */,
|
||||
F897978A2968314A00B22335 /* LoadingIndicator.swift in Sources */,
|
||||
F8B9B351298D4B34009CC69C /* Client+Account.swift in Sources */,
|
||||
F8210DE52966E160001D9973 /* Color+SystemColors.swift in Sources */,
|
||||
F8C7EDBF298169EE002843BC /* TagsService.swift in Sources */,
|
||||
F88FAD2B295F43B8009B20C9 /* AccountData+CoreDataProperties.swift in Sources */,
|
||||
F85D4975296407F100751DF7 /* HomeTimelineService.swift in Sources */,
|
||||
F80048062961850500E6868A /* StatusData+CoreDataProperties.swift in Sources */,
|
||||
|
@ -670,8 +680,8 @@
|
|||
F88C2475295C37BB0006098B /* CoreDataHandler.swift in Sources */,
|
||||
F87AEB972986D16D00434FB6 /* AuthorisationError.swift in Sources */,
|
||||
F829193C2983012400367CE2 /* ImageSizeService.swift in Sources */,
|
||||
F8B9B345298D1FCB009CC69C /* Client.swift in Sources */,
|
||||
F88FAD2A295F43B8009B20C9 /* AccountData+CoreDataClass.swift in Sources */,
|
||||
F8210DE12966D0C4001D9973 /* StatusService.swift in Sources */,
|
||||
F85DBF8F296732E20069BF89 /* AccountsView.swift in Sources */,
|
||||
F85D49872964334100751DF7 /* String+Date.swift in Sources */,
|
||||
F897978829681B9C00B22335 /* UserAvatar.swift in Sources */,
|
||||
|
@ -679,6 +689,7 @@
|
|||
F8210DDD2966CF17001D9973 /* StatusData+Status.swift in Sources */,
|
||||
F8210DCF2966B600001D9973 /* ImageRowAsync.swift in Sources */,
|
||||
F85D498329642FAC00751DF7 /* AttachmentData+Comperable.swift in Sources */,
|
||||
F8B9B353298D4B5D009CC69C /* Client+Search.swift in Sources */,
|
||||
F85D497B29640C8200751DF7 /* UsernameRow.swift in Sources */,
|
||||
F89D6C4429718092001DA3D4 /* AccentsSection.swift in Sources */,
|
||||
F88E4D42297E69FD0057491A /* StatusesView.swift in Sources */,
|
||||
|
@ -686,7 +697,6 @@
|
|||
F85D497929640B9D00751DF7 /* ImagesCarousel.swift in Sources */,
|
||||
F8C5E55F2988E92600ADF6A7 /* AccountModel.swift in Sources */,
|
||||
F89D6C3F29716E41001DA3D4 /* Theme.swift in Sources */,
|
||||
F88E4D5A297ECEE60057491A /* SearchService.swift in Sources */,
|
||||
F8CC95CE2970761D00C9C2AC /* TintColor.swift in Sources */,
|
||||
F89992CC296D9231005994BF /* StatusModel.swift in Sources */,
|
||||
F80048052961850500E6868A /* StatusData+CoreDataClass.swift in Sources */,
|
||||
|
@ -698,16 +708,16 @@
|
|||
F8B1E6512973FB7E00EE0D10 /* ToastrService.swift in Sources */,
|
||||
F88E4D48297E90CD0057491A /* TrendStatusesView.swift in Sources */,
|
||||
F89992CE296D92E7005994BF /* AttachmentModel.swift in Sources */,
|
||||
F8121CA5298A819100B466C7 /* InstanceService.swift in Sources */,
|
||||
F800480A2961EA1900E6868A /* AttachmentDataHandler.swift in Sources */,
|
||||
F80048032961850500E6868A /* AttachmentData+CoreDataClass.swift in Sources */,
|
||||
F897978D2968369600B22335 /* HapticService.swift in Sources */,
|
||||
F8341F90295C636C009C8EE6 /* Data+Exif.swift in Sources */,
|
||||
F89D6C4A297196FF001DA3D4 /* ImagesViewer.swift in Sources */,
|
||||
F80864112975537F009F035C /* NotificationService.swift in Sources */,
|
||||
F8A93D7E2965FD89001D8331 /* UserProfileView.swift in Sources */,
|
||||
F88C246E295C37B80006098B /* MainView.swift in Sources */,
|
||||
F86B721E296C458700EE59EC /* BlurredImage.swift in Sources */,
|
||||
F8B9B349298D4AA2009CC69C /* Client+Timeline.swift in Sources */,
|
||||
F8B9B34B298D4ACE009CC69C /* Client+Tags.swift in Sources */,
|
||||
F88C2478295C37BB0006098B /* Vernissage.xcdatamodeld in Sources */,
|
||||
F88E4D52297EA6DA0057491A /* String+Markdown.swift in Sources */,
|
||||
F898DE7229728CB2004B4A6A /* CommentModel.swift in Sources */,
|
||||
|
@ -723,13 +733,13 @@
|
|||
F857F9FD297D8ED3002C109C /* ActionMenu.swift in Sources */,
|
||||
F876418D298AE5020057D362 /* PaginableStatusesView.swift in Sources */,
|
||||
F85D49852964301800751DF7 /* StatusData+Attachments.swift in Sources */,
|
||||
F8B9B34D298D4AE4009CC69C /* Client+Notifications.swift in Sources */,
|
||||
F8764187298ABB520057D362 /* ViewState.swift in Sources */,
|
||||
F8210DE72966E1D1001D9973 /* Color+Assets.swift in Sources */,
|
||||
F88ABD9429687CA4004EF61E /* ComposeView.swift in Sources */,
|
||||
F89CEB802984198600A1376F /* AttachmentData+HighestImage.swift in Sources */,
|
||||
F87AEB942986C51B00434FB6 /* AppConstants.swift in Sources */,
|
||||
F86B7214296BFDCE00EE59EC /* UserProfileHeader.swift in Sources */,
|
||||
F88E4D46297E89DF0057491A /* TrendsService.swift in Sources */,
|
||||
F85D497D29640D5900751DF7 /* InteractionRow.swift in Sources */,
|
||||
F86167C6297FE6CC004D1F67 /* AvatarShapesSection.swift in Sources */,
|
||||
F866F6A729604629002E8F88 /* SignInView.swift in Sources */,
|
||||
|
@ -739,12 +749,15 @@
|
|||
F8121CA8298A86D600B466C7 /* InstanceRow.swift in Sources */,
|
||||
F802884F297AEED5000BDD51 /* DatabaseError.swift in Sources */,
|
||||
F85D4971296402DC00751DF7 /* AuthorizationService.swift in Sources */,
|
||||
F8B9B356298D4C1E009CC69C /* Client+Instance.swift in Sources */,
|
||||
F88E4D56297EAD6E0057491A /* AppRouteur.swift in Sources */,
|
||||
F88FAD32295F5029009B20C9 /* RemoteFileService.swift in Sources */,
|
||||
F88FAD27295F400E009B20C9 /* NotificationsView.swift in Sources */,
|
||||
F86B7216296BFFDA00EE59EC /* UserProfileStatuses.swift in Sources */,
|
||||
F897978F29684BCB00B22335 /* LoadingView.swift in Sources */,
|
||||
F8B9B34F298D4B14009CC69C /* Client+Statuses.swift in Sources */,
|
||||
F89992C9296D6DC7005994BF /* CommentBody.swift in Sources */,
|
||||
F8B9B347298D4A7C009CC69C /* Client+Trends.swift in Sources */,
|
||||
F88FAD2D295F4AD7009B20C9 /* ApplicationState.swift in Sources */,
|
||||
F88E4D54297EA7EE0057491A /* MarkdownFormattedText.swift in Sources */,
|
||||
F866F6A1296040A8002E8F88 /* ApplicationSettings+CoreDataProperties.swift in Sources */,
|
||||
|
@ -753,7 +766,6 @@
|
|||
F83CBEFB298298A1002972C8 /* ImageCarouselPicture.swift in Sources */,
|
||||
F89A46DC296EAACE0062125F /* SettingsView.swift in Sources */,
|
||||
F866F6AE29606367002E8F88 /* ApplicationViewMode.swift in Sources */,
|
||||
F8A93D802965FED4001D8331 /* AccountService.swift in Sources */,
|
||||
F866F6AA29605AFA002E8F88 /* SceneDelegate.swift in Sources */,
|
||||
F86167C8297FE781004D1F67 /* AvatarShape.swift in Sources */,
|
||||
F85D4973296406E700751DF7 /* BottomRight.swift in Sources */,
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
//
|
||||
// https://mczachurski.dev
|
||||
// Copyright © 2023 Marcin Czachurski and the repository contributors.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import MastodonKit
|
||||
|
||||
/// Mastodon 'Account'.
|
||||
extension Client {
|
||||
public class Accounts: BaseClient {
|
||||
|
||||
public func account(withId accountId: String) async throws -> Account? {
|
||||
return try await mastodonClient.account(for: accountId)
|
||||
}
|
||||
|
||||
public func relationships(withId accountId: String) async throws -> Relationship? {
|
||||
return try await mastodonClient.relationships(for: accountId)
|
||||
}
|
||||
|
||||
public func statuses(createdBy accountId: String,
|
||||
onlyMedia: Bool = true,
|
||||
excludeReplies: Bool = true,
|
||||
maxId: String? = nil,
|
||||
sinceId: String? = nil,
|
||||
minId: String? = nil,
|
||||
limit: Int = 40) async throws -> [Status] {
|
||||
return try await mastodonClient.statuses(for: accountId,
|
||||
onlyMedia: onlyMedia,
|
||||
excludeReplies: excludeReplies,
|
||||
maxId: maxId,
|
||||
sinceId: sinceId,
|
||||
minId: minId,
|
||||
limit: limit)
|
||||
}
|
||||
|
||||
public func follow(account accountId: String) async throws -> Relationship? {
|
||||
return try await mastodonClient.follow(for: accountId)
|
||||
}
|
||||
|
||||
public func unfollow(account accountId: String) async throws -> Relationship? {
|
||||
return try await mastodonClient.unfollow(for: accountId)
|
||||
}
|
||||
|
||||
public func mute(account accountId: String) async throws -> Relationship? {
|
||||
return try await mastodonClient.mute(for: accountId)
|
||||
}
|
||||
|
||||
public func unmute(account accountId: String) async throws -> Relationship? {
|
||||
return try await mastodonClient.unmute(for: accountId)
|
||||
}
|
||||
|
||||
public func block(account accountId: String) async throws -> Relationship? {
|
||||
return try await mastodonClient.block(for: accountId)
|
||||
}
|
||||
|
||||
public func unblock(account accountId: String) async throws -> Relationship? {
|
||||
return try await mastodonClient.unblock(for: accountId)
|
||||
}
|
||||
|
||||
public func followers(account accountId: String, page: Int) async throws -> [Account] {
|
||||
return try await mastodonClient.followers(for: accountId, page: page)
|
||||
}
|
||||
|
||||
public func following(account accountId: String, page: Int) async throws -> [Account] {
|
||||
return try await mastodonClient.following(for: accountId, page: page)
|
||||
}
|
||||
|
||||
public func favourites(maxId: String? = nil,
|
||||
sinceId: String? = nil,
|
||||
minId: String? = nil,
|
||||
limit: Int = 10,
|
||||
page: Int? = nil) async throws -> [Status] {
|
||||
return try await mastodonClient.favourites(limit: limit, page: page)
|
||||
}
|
||||
|
||||
public func bookmarks(maxId: String? = nil,
|
||||
sinceId: String? = nil,
|
||||
minId: String? = nil,
|
||||
limit: Int = 10,
|
||||
page: Int? = nil) async throws -> [Status] {
|
||||
return try await mastodonClient.bookmarks(limit: limit, page: page)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
//
|
||||
// https://mczachurski.dev
|
||||
// Copyright © 2023 Marcin Czachurski and the repository contributors.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import MastodonKit
|
||||
|
||||
/// Mastodon 'Search'.
|
||||
extension Client {
|
||||
public class Instances {
|
||||
|
||||
public let pixelfedInstances: [String] = [
|
||||
"https://pixelfed.de",
|
||||
"https://pixelfed.social",
|
||||
"https://pxlmo.com",
|
||||
"https://metapixl.com",
|
||||
"https://pixey.org",
|
||||
"https://pixel.tchncs.de",
|
||||
"https://pixelfed.tokyo",
|
||||
"https://pixelfed.fr",
|
||||
"https://pixelfed.nz",
|
||||
"https://pixelfed.au",
|
||||
"https://pixelfed.eus",
|
||||
"https://pixelfed.bachgau.social",
|
||||
"https://pixelfed.es",
|
||||
"https://pixelfed.cz",
|
||||
"https://pixelfed.automat.click",
|
||||
"https://gram.social",
|
||||
"https://nixorigin.one",
|
||||
"https://miniature.photography",
|
||||
"https://fedifilm.art",
|
||||
"https://fedipix.de",
|
||||
"https://pixel.jabbxi.de",
|
||||
"https://nodegray.com",
|
||||
"https://socialpixels.xyz",
|
||||
"https://pixel.mamutut.space",
|
||||
"https://pixelfed.fioverse.zone",
|
||||
"https://pixel.artemai.art",
|
||||
"https://pix.anduin.net",
|
||||
"https://jauntypix.net",
|
||||
"https://faf.photos",
|
||||
"https://pix.vleij.com",
|
||||
"https://pixels.gsi.li",
|
||||
"https://eorzea.photos"
|
||||
]
|
||||
|
||||
func instances(urls: [String]) async -> [Instance] {
|
||||
var instances: [Instance] = []
|
||||
|
||||
await withTaskGroup(of: Instance?.self) { group in
|
||||
for url in urls {
|
||||
group.addTask {
|
||||
do {
|
||||
if let baseUrl = URL(string: url) {
|
||||
let client = MastodonClient(baseURL: baseUrl)
|
||||
return try await client.readInstanceInformation()
|
||||
}
|
||||
|
||||
return nil
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Cannot download instance information: \(url.string)")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for await instance in group {
|
||||
if let instance {
|
||||
instances.append(instance)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return instances
|
||||
}
|
||||
|
||||
func instance(url: URL) async throws -> Instance {
|
||||
let client = MastodonClient(baseURL: url)
|
||||
return try await client.readInstanceInformation()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// https://mczachurski.dev
|
||||
// Copyright © 2023 Marcin Czachurski and the repository contributors.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import MastodonKit
|
||||
|
||||
/// Mastodon 'Notifications'.
|
||||
extension Client {
|
||||
public class Notifications: BaseClient {
|
||||
public func notifications(maxId: MaxId? = nil,
|
||||
sinceId: SinceId? = nil,
|
||||
minId: MinId? = nil,
|
||||
limit: Int? = nil
|
||||
) async throws -> Linkable<[MastodonKit.Notification]> {
|
||||
return try await mastodonClient.notifications(maxId: maxId, sinceId: sinceId, minId: minId, limit: limit)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
//
|
||||
// https://mczachurski.dev
|
||||
// Copyright © 2023 Marcin Czachurski and the repository contributors.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import MastodonKit
|
||||
|
||||
/// Mastodon 'Search'.
|
||||
extension Client {
|
||||
public class Search: BaseClient {
|
||||
public func search(query: String, resultsType: Mastodon.Search.ResultsType) async throws -> SearchResults? {
|
||||
return try await mastodonClient.search(query: query, type: resultsType)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
//
|
||||
// https://mczachurski.dev
|
||||
// Copyright © 2023 Marcin Czachurski and the repository contributors.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import MastodonKit
|
||||
|
||||
/// Mastodon 'Statuses'.
|
||||
extension Client {
|
||||
public class Statuses: BaseClient {
|
||||
|
||||
public func status(withId statusId: String) async throws -> Status? {
|
||||
return try await mastodonClient.status(statusId: statusId)
|
||||
}
|
||||
|
||||
func favourite(statusId: String) async throws -> Status? {
|
||||
return try await mastodonClient.favourite(statusId: statusId)
|
||||
}
|
||||
|
||||
func unfavourite(statusId: String) async throws -> Status? {
|
||||
return try await mastodonClient.unfavourite(statusId: statusId)
|
||||
}
|
||||
|
||||
func boost(statusId: String) async throws -> Status? {
|
||||
return try await mastodonClient.boost(statusId: statusId)
|
||||
}
|
||||
|
||||
func unboost(statusId: String) async throws -> Status? {
|
||||
return try await mastodonClient.unboost(statusId: statusId)
|
||||
}
|
||||
|
||||
func bookmark(statusId: String) async throws -> Status? {
|
||||
return try await mastodonClient.bookmark(statusId: statusId)
|
||||
}
|
||||
|
||||
func unbookmark(statusId: String) async throws -> Status? {
|
||||
return try await mastodonClient.unbookmark(statusId: statusId)
|
||||
}
|
||||
|
||||
func new(status: Mastodon.Statuses.Components) async throws -> Status? {
|
||||
return try await mastodonClient.new(statusComponents: status)
|
||||
}
|
||||
|
||||
func comments(to statusId: String) async throws -> [CommentModel] {
|
||||
var commentViewModels: [CommentModel] = []
|
||||
|
||||
try await self.getCommentDescendants(to: statusId, showDivider: true, to: &commentViewModels)
|
||||
|
||||
return commentViewModels
|
||||
}
|
||||
|
||||
public func favouritedBy(statusId: String, page: Int) async throws -> [Account] {
|
||||
return try await mastodonClient.favouritedBy(for: statusId, page: page)
|
||||
}
|
||||
|
||||
public func rebloggedBy(statusId: String, page: Int) async throws -> [Account] {
|
||||
return try await mastodonClient.rebloggedBy(for: statusId, page: page)
|
||||
}
|
||||
|
||||
private func getCommentDescendants(to statusId: String, showDivider: Bool, to commentViewModels: inout [CommentModel]) async throws {
|
||||
let context = try await mastodonClient.getContext(for: statusId)
|
||||
|
||||
let descendants = context.descendants.toStatusViewModel()
|
||||
for status in descendants {
|
||||
commentViewModels.append(CommentModel(status: status, showDivider: showDivider))
|
||||
|
||||
if status.repliesCount > 0 {
|
||||
try await self.getCommentDescendants(to: status.id, showDivider: false, to: &commentViewModels)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
//
|
||||
// https://mczachurski.dev
|
||||
// Copyright © 2023 Marcin Czachurski and the repository contributors.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import MastodonKit
|
||||
|
||||
/// Mastodon 'Tags'.
|
||||
extension Client {
|
||||
public class Tags: BaseClient {
|
||||
public func get(tag: String) async throws -> Tag? {
|
||||
return try await mastodonClient.tag(hashtag: tag)
|
||||
}
|
||||
|
||||
public func follow(tag: String) async throws -> Tag? {
|
||||
return try await mastodonClient.follow(hashtag: tag)
|
||||
}
|
||||
|
||||
public func unfollow(tag: String) async throws -> Tag? {
|
||||
return try await mastodonClient.unfollow(hashtag: tag)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
//
|
||||
// https://mczachurski.dev
|
||||
// Copyright © 2023 Marcin Czachurski and the repository contributors.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import MastodonKit
|
||||
|
||||
/// Mastodon 'Timeline'.
|
||||
extension Client {
|
||||
public class PublicTimeline: BaseClient {
|
||||
public func getStatuses(local: Bool,
|
||||
remote: Bool,
|
||||
maxId: String? = nil,
|
||||
sinceId: String? = nil,
|
||||
minId: String? = nil,
|
||||
limit: Int = 40) async throws -> [Status] {
|
||||
return try await mastodonClient.getPublicTimeline(local: local,
|
||||
remote: remote,
|
||||
onlyMedia: true,
|
||||
maxId: maxId,
|
||||
sinceId: sinceId,
|
||||
minId: minId,
|
||||
limit: limit)
|
||||
}
|
||||
|
||||
public func getTagStatuses(tag: String,
|
||||
local: Bool,
|
||||
remote: Bool,
|
||||
maxId: String? = nil,
|
||||
sinceId: String? = nil,
|
||||
minId: String? = nil,
|
||||
limit: Int = 40) async throws -> [Status] {
|
||||
return try await mastodonClient.getTagTimeline(tag: tag,
|
||||
local: local,
|
||||
remote: remote,
|
||||
onlyMedia: true,
|
||||
maxId: maxId,
|
||||
sinceId: sinceId,
|
||||
minId: minId,
|
||||
limit: limit)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
//
|
||||
// https://mczachurski.dev
|
||||
// Copyright © 2023 Marcin Czachurski and the repository contributors.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import MastodonKit
|
||||
|
||||
/// Mastodon 'Trends'.
|
||||
extension Client {
|
||||
public class Trends: BaseClient {
|
||||
public func statuses(range: Mastodon.PixelfedTrends.TrendRange) async throws -> [Status] {
|
||||
return try await mastodonClient.statusesTrends(range: range)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
//
|
||||
// https://mczachurski.dev
|
||||
// Copyright © 2023 Marcin Czachurski and the repository contributors.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import MastodonKit
|
||||
|
||||
public class Client: ObservableObject {
|
||||
public static let shared = Client()
|
||||
private init() { }
|
||||
|
||||
private var mastodonClient: MastodonClientAuthenticated?
|
||||
|
||||
func setAccount(account: AccountModel) {
|
||||
guard let accessToken = account.accessToken else {
|
||||
return
|
||||
}
|
||||
|
||||
self.mastodonClient = MastodonClient(baseURL: account.serverUrl).getAuthenticated(token: accessToken)
|
||||
}
|
||||
}
|
||||
|
||||
extension Client {
|
||||
public var trends: Trends? { return Trends(mastodonClient: self.mastodonClient) }
|
||||
public var publicTimeline: PublicTimeline? { return PublicTimeline(mastodonClient: self.mastodonClient) }
|
||||
public var tags: Tags? { return Tags(mastodonClient: self.mastodonClient) }
|
||||
public var notifications: Notifications? { return Notifications(mastodonClient: self.mastodonClient) }
|
||||
public var statuses: Statuses? { return Statuses(mastodonClient: self.mastodonClient) }
|
||||
public var accounts: Accounts? { return Accounts(mastodonClient: self.mastodonClient) }
|
||||
public var search: Search? { return Search(mastodonClient: self.mastodonClient) }
|
||||
public var instances: Instances { return Instances() }
|
||||
}
|
||||
|
||||
public class BaseClient {
|
||||
public var mastodonClient: MastodonClientAuthenticated
|
||||
|
||||
init?(mastodonClient: MastodonClientAuthenticated?) {
|
||||
guard let mastodonClient else {
|
||||
return nil
|
||||
}
|
||||
|
||||
self.mastodonClient = mastodonClient
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ import Foundation
|
|||
|
||||
public enum AuthorisationError: Error {
|
||||
case badServerUrl
|
||||
case accessTokenNotFound
|
||||
}
|
||||
|
||||
extension AuthorisationError: LocalizedError {
|
||||
|
@ -15,6 +16,8 @@ extension AuthorisationError: LocalizedError {
|
|||
switch self {
|
||||
case .badServerUrl:
|
||||
return NSLocalizedString("Bad url to server.", comment: "User enter bad URL to server.")
|
||||
case .accessTokenNotFound:
|
||||
return NSLocalizedString("Acess token not found.", comment: "Access token is not saved in account model.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
import SwiftUI
|
||||
|
||||
/// Modifier for using with view placeholders (with redacted modifier).
|
||||
struct AnimatePlaceholderModifier: AnimatableModifier {
|
||||
@Binding var isLoading: Bool
|
||||
|
||||
|
@ -39,6 +40,8 @@ struct AnimatePlaceholderModifier: AnimatableModifier {
|
|||
}
|
||||
|
||||
extension View {
|
||||
|
||||
/// Animate redacted placeholders.
|
||||
func animatePlaceholder(isLoading: Binding<Bool>) -> some View {
|
||||
self.modifier(AnimatePlaceholderModifier(isLoading: isLoading))
|
||||
}
|
||||
|
|
|
@ -1,153 +0,0 @@
|
|||
//
|
||||
// https://mczachurski.dev
|
||||
// Copyright © 2023 Marcin Czachurski and the repository contributors.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import MastodonKit
|
||||
|
||||
public class AccountService {
|
||||
public static let shared = AccountService()
|
||||
private init() { }
|
||||
|
||||
public func account(withId accountId: String, for account: AccountModel?) async throws -> Account? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
|
||||
return try await client.account(for: accountId)
|
||||
}
|
||||
|
||||
public func relationships(withId accountId: String, for account: AccountModel?) async throws -> Relationship? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
|
||||
return try await client.relationships(for: accountId)
|
||||
}
|
||||
|
||||
public func statuses(createdBy accountId: String,
|
||||
for account: AccountModel?,
|
||||
onlyMedia: Bool = true,
|
||||
excludeReplies: Bool = true,
|
||||
maxId: String? = nil,
|
||||
sinceId: String? = nil,
|
||||
minId: String? = nil,
|
||||
limit: Int = 40) async throws -> [Status] {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return []
|
||||
}
|
||||
|
||||
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
|
||||
return try await client.statuses(for: accountId,
|
||||
onlyMedia: onlyMedia,
|
||||
excludeReplies: excludeReplies,
|
||||
maxId: maxId,
|
||||
sinceId: sinceId,
|
||||
minId: minId,
|
||||
limit: limit)
|
||||
}
|
||||
|
||||
public func follow(account accountId: String, for account: AccountModel?) async throws -> Relationship? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
|
||||
return try await client.follow(for: accountId)
|
||||
}
|
||||
|
||||
public func unfollow(account accountId: String, for account: AccountModel?) async throws -> Relationship? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
|
||||
return try await client.unfollow(for: accountId)
|
||||
}
|
||||
|
||||
public func mute(account accountId: String, for account: AccountModel?) async throws -> Relationship? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
|
||||
return try await client.mute(for: accountId)
|
||||
}
|
||||
|
||||
public func unmute(account accountId: String, for account: AccountModel?) async throws -> Relationship? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
|
||||
return try await client.unmute(for: accountId)
|
||||
}
|
||||
|
||||
public func block(account accountId: String, for account: AccountModel?) async throws -> Relationship? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
|
||||
return try await client.block(for: accountId)
|
||||
}
|
||||
|
||||
public func unblock(account accountId: String, for account: AccountModel?) async throws -> Relationship? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
|
||||
return try await client.unblock(for: accountId)
|
||||
}
|
||||
|
||||
public func followers(account accountId: String, for account: AccountModel?, page: Int) async throws -> [Account] {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return []
|
||||
}
|
||||
|
||||
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
|
||||
return try await client.followers(for: accountId, page: page)
|
||||
}
|
||||
|
||||
public func following(account accountId: String, for account: AccountModel?, page: Int) async throws -> [Account] {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return []
|
||||
}
|
||||
|
||||
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
|
||||
return try await client.following(for: accountId, page: page)
|
||||
}
|
||||
|
||||
public func favourites(for account: AccountModel?,
|
||||
maxId: String? = nil,
|
||||
sinceId: String? = nil,
|
||||
minId: String? = nil,
|
||||
limit: Int = 10,
|
||||
page: Int? = nil) async throws -> [Status] {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return []
|
||||
}
|
||||
|
||||
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
|
||||
return try await client.favourites(limit: limit, page: page)
|
||||
}
|
||||
|
||||
public func bookmarks(for account: AccountModel?,
|
||||
maxId: String? = nil,
|
||||
sinceId: String? = nil,
|
||||
minId: String? = nil,
|
||||
limit: Int = 10,
|
||||
page: Int? = nil) async throws -> [Status] {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return []
|
||||
}
|
||||
|
||||
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
|
||||
return try await client.bookmarks(limit: limit, page: page)
|
||||
}
|
||||
}
|
|
@ -8,6 +8,8 @@ import Foundation
|
|||
import AuthenticationServices
|
||||
|
||||
public class AuthorizationSession: NSObject, ObservableObject, ASWebAuthenticationPresentationContextProviding {
|
||||
|
||||
/// Presentation anchor used during showing in app browser for sign in user (OAuth).
|
||||
public func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
|
||||
DispatchQueue.main.sync {
|
||||
return ASPresentationAnchor()
|
||||
|
|
|
@ -1,78 +0,0 @@
|
|||
//
|
||||
// https://mczachurski.dev
|
||||
// Copyright © 2023 Marcin Czachurski and the repository contributors.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import MastodonKit
|
||||
|
||||
public class InstanceService {
|
||||
public static let shared = InstanceService()
|
||||
private init() { }
|
||||
|
||||
public let pixelfedInstances: [String] = [
|
||||
"https://pixelfed.de",
|
||||
"https://pixelfed.social",
|
||||
"https://pxlmo.com",
|
||||
"https://metapixl.com",
|
||||
"https://pixey.org",
|
||||
"https://pixel.tchncs.de",
|
||||
"https://pixelfed.tokyo",
|
||||
"https://pixelfed.fr",
|
||||
"https://pixelfed.nz",
|
||||
"https://pixelfed.au",
|
||||
"https://pixelfed.eus",
|
||||
"https://pixelfed.bachgau.social",
|
||||
"https://pixelfed.es",
|
||||
"https://pixelfed.cz",
|
||||
"https://pixelfed.automat.click",
|
||||
"https://gram.social",
|
||||
"https://nixorigin.one",
|
||||
"https://miniature.photography",
|
||||
"https://fedifilm.art",
|
||||
"https://fedipix.de",
|
||||
"https://pixel.jabbxi.de",
|
||||
"https://nodegray.com",
|
||||
"https://socialpixels.xyz",
|
||||
"https://pixel.mamutut.space",
|
||||
"https://pixelfed.fioverse.zone",
|
||||
"https://pixel.artemai.art",
|
||||
"https://pix.anduin.net",
|
||||
"https://jauntypix.net",
|
||||
"https://faf.photos",
|
||||
"https://pix.vleij.com",
|
||||
"https://pixels.gsi.li",
|
||||
"https://eorzea.photos"
|
||||
]
|
||||
|
||||
func instances(urls: [String]) async -> [Instance] {
|
||||
var instances: [Instance] = []
|
||||
|
||||
await withTaskGroup(of: Instance?.self) { group in
|
||||
for url in urls {
|
||||
group.addTask {
|
||||
do {
|
||||
if let baseUrl = URL(string: url) {
|
||||
let client = MastodonClient(baseURL: baseUrl)
|
||||
return try await client.readInstanceInformation()
|
||||
}
|
||||
|
||||
return nil
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Cannot download instance information: \(url.string)")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for await instance in group {
|
||||
if let instance {
|
||||
instances.append(instance)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return instances
|
||||
}
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
//
|
||||
// https://mczachurski.dev
|
||||
// Copyright © 2023 Marcin Czachurski and the repository contributors.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import MastodonKit
|
||||
|
||||
public class NotificationService {
|
||||
public static let shared = NotificationService()
|
||||
private init() { }
|
||||
|
||||
public func notifications(for account: AccountModel?,
|
||||
maxId: MaxId? = nil,
|
||||
sinceId: SinceId? = nil,
|
||||
minId: MinId? = nil,
|
||||
limit: Int? = nil
|
||||
) async throws -> Linkable<[MastodonKit.Notification]> {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return Linkable<[MastodonKit.Notification]>(data: [])
|
||||
}
|
||||
|
||||
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
|
||||
return try await client.notifications(maxId: maxId, sinceId: sinceId, minId: minId, limit: limit)
|
||||
}
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
//
|
||||
// https://mczachurski.dev
|
||||
// Copyright © 2023 Marcin Czachurski and the repository contributors.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import MastodonKit
|
||||
|
||||
public class PublicTimelineService {
|
||||
public static let shared = PublicTimelineService()
|
||||
private init() { }
|
||||
|
||||
public func getStatuses(for account: AccountModel?,
|
||||
local: Bool,
|
||||
remote: Bool,
|
||||
maxId: String? = nil,
|
||||
sinceId: String? = nil,
|
||||
minId: String? = nil,
|
||||
limit: Int = 40) async throws -> [Status] {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return []
|
||||
}
|
||||
|
||||
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
|
||||
return try await client.getPublicTimeline(local: local, remote: remote, onlyMedia: true, maxId: maxId, sinceId: sinceId, minId: minId, limit: limit)
|
||||
}
|
||||
|
||||
public func getTagStatuses(for account: AccountModel?,
|
||||
tag: String,
|
||||
local: Bool,
|
||||
remote: Bool,
|
||||
maxId: String? = nil,
|
||||
sinceId: String? = nil,
|
||||
minId: String? = nil,
|
||||
limit: Int = 40) async throws -> [Status] {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return []
|
||||
}
|
||||
|
||||
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
|
||||
return try await client.getTagTimeline(tag: tag, local: local, remote: remote, onlyMedia: true, maxId: maxId, sinceId: sinceId, minId: minId, limit: limit)
|
||||
}
|
||||
}
|
|
@ -47,14 +47,14 @@ class RouterPath: ObservableObject {
|
|||
path.append(to)
|
||||
}
|
||||
|
||||
public func handle(url: URL, account: AccountModel? = nil) -> OpenURLAction.Result {
|
||||
public func handle(url: URL) -> OpenURLAction.Result {
|
||||
if url.pathComponents.contains(where: { $0 == "tags" }), let tag = url.pathComponents.last {
|
||||
navigate(to: .tag(hashTag: tag))
|
||||
return .handled
|
||||
} else if url.lastPathComponent.first == "@", let host = url.host {
|
||||
let acct = "\(url.lastPathComponent)@\(host)"
|
||||
Task {
|
||||
await navigateToAccountFrom(acct: acct, url: url, account: account)
|
||||
await navigateToAccountFrom(acct: acct, url: url)
|
||||
}
|
||||
|
||||
return .handled
|
||||
|
@ -63,13 +63,9 @@ class RouterPath: ObservableObject {
|
|||
return urlHandler?(url) ?? .systemAction
|
||||
}
|
||||
|
||||
public func navigateToAccountFrom(acct: String, url: URL, account: AccountModel? = nil) async {
|
||||
guard let account else { return }
|
||||
|
||||
public func navigateToAccountFrom(acct: String, url: URL) async {
|
||||
Task {
|
||||
let results = try? await SearchService.shared.search(for: account,
|
||||
query: acct,
|
||||
resultsType: Mastodon.Search.ResultsType.accounts)
|
||||
let results = try? await Client.shared.search?.search(query: acct, resultsType: Mastodon.Search.ResultsType.accounts)
|
||||
|
||||
if let accountFromApi = results?.accounts.first {
|
||||
navigate(to: .userProfile(accountId: accountFromApi.id,
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
//
|
||||
// https://mczachurski.dev
|
||||
// Copyright © 2023 Marcin Czachurski and the repository contributors.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import MastodonKit
|
||||
|
||||
public class SearchService {
|
||||
public static let shared = SearchService()
|
||||
private init() { }
|
||||
|
||||
public func search(for account: AccountModel?,
|
||||
query: String,
|
||||
resultsType: Mastodon.Search.ResultsType) async throws -> SearchResults? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
|
||||
return try await client.search(query: query, type: resultsType)
|
||||
}
|
||||
}
|
|
@ -1,125 +0,0 @@
|
|||
//
|
||||
// https://mczachurski.dev
|
||||
// Copyright © 2023 Marcin Czachurski and the repository contributors.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import MastodonKit
|
||||
|
||||
public class StatusService {
|
||||
public static let shared = StatusService()
|
||||
private init() { }
|
||||
|
||||
public func status(withId statusId: String, for account: AccountModel?) async throws -> Status? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
|
||||
return try await client.status(statusId: statusId)
|
||||
}
|
||||
|
||||
func favourite(statusId: String, for account: AccountModel?) async throws -> Status? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
|
||||
return try await client.favourite(statusId: statusId)
|
||||
}
|
||||
|
||||
func unfavourite(statusId: String, for account: AccountModel?) async throws -> Status? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
|
||||
return try await client.unfavourite(statusId: statusId)
|
||||
}
|
||||
|
||||
func boost(statusId: String, for account: AccountModel?) async throws -> Status? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
|
||||
return try await client.boost(statusId: statusId)
|
||||
}
|
||||
|
||||
func unboost(statusId: String, for account: AccountModel?) async throws -> Status? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
|
||||
return try await client.unboost(statusId: statusId)
|
||||
}
|
||||
|
||||
func bookmark(statusId: String, for account: AccountModel?) async throws -> Status? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
|
||||
return try await client.bookmark(statusId: statusId)
|
||||
}
|
||||
|
||||
func unbookmark(statusId: String, for account: AccountModel?) async throws -> Status? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
|
||||
return try await client.unbookmark(statusId: statusId)
|
||||
}
|
||||
|
||||
func new(status: Mastodon.Statuses.Components, for account: AccountModel?) async throws -> Status? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
|
||||
return try await client.new(statusComponents: status)
|
||||
}
|
||||
|
||||
func comments(to statusId: String, for account: AccountModel) async throws -> [CommentModel] {
|
||||
var commentViewModels: [CommentModel] = []
|
||||
|
||||
let client = MastodonClient(baseURL: account.serverUrl).getAuthenticated(token: account.accessToken ?? String.empty())
|
||||
try await self.getCommentDescendants(to: statusId, client: client, showDivider: true, to: &commentViewModels)
|
||||
|
||||
return commentViewModels
|
||||
}
|
||||
|
||||
public func favouritedBy(statusId: String, for account: AccountModel?, page: Int) async throws -> [Account] {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return []
|
||||
}
|
||||
|
||||
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
|
||||
return try await client.favouritedBy(for: statusId, page: page)
|
||||
}
|
||||
|
||||
public func rebloggedBy(statusId: String, for account: AccountModel?, page: Int) async throws -> [Account] {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return []
|
||||
}
|
||||
|
||||
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
|
||||
return try await client.rebloggedBy(for: statusId, page: page)
|
||||
}
|
||||
|
||||
private func getCommentDescendants(to statusId: String, client: MastodonClientAuthenticated, showDivider: Bool, to commentViewModels: inout [CommentModel]) async throws {
|
||||
let context = try await client.getContext(for: statusId)
|
||||
|
||||
let descendants = context.descendants.toStatusViewModel()
|
||||
for status in descendants {
|
||||
commentViewModels.append(CommentModel(status: status, showDivider: showDivider))
|
||||
|
||||
if status.repliesCount > 0 {
|
||||
try await self.getCommentDescendants(to: status.id, client: client, showDivider: false, to: &commentViewModels)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
//
|
||||
// https://mczachurski.dev
|
||||
// Copyright © 2023 Marcin Czachurski and the repository contributors.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import MastodonKit
|
||||
|
||||
public class TagsService {
|
||||
public static let shared = TagsService()
|
||||
private init() { }
|
||||
|
||||
public func get(tag: String, for account: AccountModel?) async throws -> Tag? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
|
||||
return try await client.tag(hashtag: tag)
|
||||
}
|
||||
|
||||
public func follow(tag: String, for account: AccountModel?) async throws -> Tag? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
|
||||
return try await client.follow(hashtag: tag)
|
||||
}
|
||||
|
||||
public func unfollow(tag: String, for account: AccountModel?) async throws -> Tag? {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
|
||||
return try await client.unfollow(hashtag: tag)
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
//
|
||||
// https://mczachurski.dev
|
||||
// Copyright © 2023 Marcin Czachurski and the repository contributors.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import MastodonKit
|
||||
|
||||
public class TrendsService {
|
||||
public static let shared = TrendsService()
|
||||
private init() { }
|
||||
|
||||
public func statuses(for account: AccountModel?,
|
||||
range: Mastodon.PixelfedTrends.TrendRange) async throws -> [Status] {
|
||||
guard let accessToken = account?.accessToken, let serverUrl = account?.serverUrl else {
|
||||
return []
|
||||
}
|
||||
|
||||
let client = MastodonClient(baseURL: serverUrl).getAuthenticated(token: accessToken)
|
||||
return try await client.statusesTrends(range: range)
|
||||
}
|
||||
}
|
|
@ -13,14 +13,15 @@ struct VernissageApp: App {
|
|||
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
|
||||
|
||||
let coreDataHandler = CoreDataHandler.shared
|
||||
|
||||
@StateObject var applicationState = ApplicationState.shared
|
||||
@StateObject var client = Client.shared
|
||||
@StateObject var routerPath = RouterPath()
|
||||
|
||||
@State var applicationViewMode: ApplicationViewMode = .loading
|
||||
@State var tintColor = ApplicationState.shared.tintColor.color()
|
||||
@State var theme = ApplicationState.shared.theme.colorScheme()
|
||||
|
||||
@StateObject private var routerPath = RouterPath()
|
||||
|
||||
|
||||
var body: some Scene {
|
||||
WindowGroup {
|
||||
NavigationStack(path: $routerPath.path) {
|
||||
|
@ -43,6 +44,7 @@ struct VernissageApp: App {
|
|||
}
|
||||
.environment(\.managedObjectContext, coreDataHandler.container.viewContext)
|
||||
.environmentObject(applicationState)
|
||||
.environmentObject(client)
|
||||
.environmentObject(routerPath)
|
||||
.tint(self.tintColor)
|
||||
.preferredColorScheme(self.theme)
|
||||
|
@ -65,8 +67,10 @@ struct VernissageApp: App {
|
|||
}
|
||||
|
||||
Task { @MainActor in
|
||||
self.applicationState.account = AccountModel(accountData: accountData)
|
||||
let accountModel = AccountModel(accountData: accountData)
|
||||
self.applicationState.account = accountModel
|
||||
self.applicationState.lastSeenStatusId = accountData.lastSeenStatusId
|
||||
self.client.setAccount(account: accountModel)
|
||||
self.applicationViewMode = .mainView
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ struct AccountsView: View {
|
|||
}
|
||||
|
||||
@EnvironmentObject var applicationState: ApplicationState
|
||||
@EnvironmentObject var client: Client
|
||||
|
||||
@State var entityId: String
|
||||
@State var listType: ListType
|
||||
|
@ -124,25 +125,13 @@ struct AccountsView: View {
|
|||
private func loadFromApi() async throws -> [Account] {
|
||||
switch self.listType {
|
||||
case .followers:
|
||||
return try await AccountService.shared.followers(
|
||||
account: self.entityId,
|
||||
for: self.applicationState.account,
|
||||
page: page)
|
||||
return try await self.client.accounts?.followers(account: self.entityId, page: page) ?? []
|
||||
case .following:
|
||||
return try await AccountService.shared.following(
|
||||
account: self.entityId,
|
||||
for: self.applicationState.account,
|
||||
page: page)
|
||||
return try await self.client.accounts?.following(account: self.entityId, page: page) ?? []
|
||||
case .favourited:
|
||||
return try await StatusService.shared.favouritedBy(
|
||||
statusId: self.entityId,
|
||||
for: self.applicationState.account,
|
||||
page: page)
|
||||
return try await self.client.statuses?.favouritedBy(statusId: self.entityId, page: page) ?? []
|
||||
case .reblogged:
|
||||
return try await StatusService.shared.rebloggedBy(
|
||||
statusId: self.entityId,
|
||||
for: self.applicationState.account,
|
||||
page: page)
|
||||
return try await self.client.statuses?.rebloggedBy(statusId: self.entityId, page: page) ?? []
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ struct ComposeView: View {
|
|||
}
|
||||
|
||||
@EnvironmentObject var applicationState: ApplicationState
|
||||
@EnvironmentObject var client: Client
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
@State var statusViewModel: StatusModel?
|
||||
|
@ -100,9 +101,7 @@ struct ComposeView: View {
|
|||
|
||||
private func publishStatus() async {
|
||||
do {
|
||||
_ = try await StatusService.shared.new(
|
||||
status: Mastodon.Statuses.Components(inReplyToId: self.statusViewModel?.id, text: self.text),
|
||||
for: self.applicationState.account)
|
||||
_ = try await self.client.statuses?.new(status: Mastodon.Statuses.Components(inReplyToId: self.statusViewModel?.id, text: self.text))
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Error during post status.", showToastr: true)
|
||||
}
|
||||
|
|
|
@ -16,7 +16,9 @@ struct MainView: View {
|
|||
}
|
||||
|
||||
@Environment(\.managedObjectContext) private var viewContext
|
||||
|
||||
@EnvironmentObject var applicationState: ApplicationState
|
||||
@EnvironmentObject var client: Client
|
||||
@EnvironmentObject var routerPath: RouterPath
|
||||
|
||||
@State private var navBarTitle: String = "Home"
|
||||
|
@ -151,7 +153,9 @@ struct MainView: View {
|
|||
Menu {
|
||||
ForEach(self.dbAccounts) { account in
|
||||
Button {
|
||||
self.applicationState.account = AccountModel(accountData: account)
|
||||
let accountModel = AccountModel(accountData: account)
|
||||
self.applicationState.account = accountModel
|
||||
self.client.setAccount(account: accountModel)
|
||||
self.applicationState.lastSeenStatusId = account.lastSeenStatusId
|
||||
|
||||
ApplicationSettingsHandler.shared.setAccountAsDefault(accountData: account)
|
||||
|
|
|
@ -9,6 +9,7 @@ import MastodonKit
|
|||
|
||||
struct NotificationsView: View {
|
||||
@EnvironmentObject var applicationState: ApplicationState
|
||||
@EnvironmentObject var client: Client
|
||||
|
||||
@State var accountId: String
|
||||
@State private var notifications: [MastodonKit.Notification] = []
|
||||
|
@ -70,21 +71,17 @@ struct NotificationsView: View {
|
|||
|
||||
func loadNotifications() async {
|
||||
do {
|
||||
let linkable = try await NotificationService.shared.notifications(
|
||||
for: self.applicationState.account,
|
||||
maxId: maxId,
|
||||
minId: minId,
|
||||
limit: 5)
|
||||
|
||||
self.minId = linkable.link?.minId
|
||||
self.maxId = linkable.link?.maxId
|
||||
self.notifications = linkable.data
|
||||
|
||||
if linkable.data.isEmpty {
|
||||
self.allItemsLoaded = true
|
||||
if let linkable = try await self.client.notifications?.notifications(maxId: maxId, minId: minId, limit: 5) {
|
||||
self.minId = linkable.link?.minId
|
||||
self.maxId = linkable.link?.maxId
|
||||
self.notifications = linkable.data
|
||||
|
||||
if linkable.data.isEmpty {
|
||||
self.allItemsLoaded = true
|
||||
}
|
||||
|
||||
self.state = .loaded
|
||||
}
|
||||
|
||||
self.state = .loaded
|
||||
} catch {
|
||||
if !Task.isCancelled {
|
||||
ErrorService.shared.handle(error, message: "Error during download notifications from server.", showToastr: true)
|
||||
|
@ -97,18 +94,15 @@ struct NotificationsView: View {
|
|||
|
||||
private func loadMoreNotifications() async {
|
||||
do {
|
||||
let linkable = try await NotificationService.shared.notifications(
|
||||
for: self.applicationState.account,
|
||||
maxId: self.maxId,
|
||||
limit: self.defaultPageSize)
|
||||
|
||||
if linkable.data.isEmpty {
|
||||
self.allItemsLoaded = true
|
||||
return
|
||||
if let linkable = try await self.client.notifications?.notifications(maxId: self.maxId, limit: self.defaultPageSize) {
|
||||
if linkable.data.isEmpty {
|
||||
self.allItemsLoaded = true
|
||||
return
|
||||
}
|
||||
|
||||
self.maxId = linkable.link?.maxId
|
||||
self.notifications.append(contentsOf: linkable.data)
|
||||
}
|
||||
|
||||
self.maxId = linkable.link?.maxId
|
||||
self.notifications.append(contentsOf: linkable.data)
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Error during download notifications from server.", showToastr: !Task.isCancelled)
|
||||
}
|
||||
|
@ -116,18 +110,15 @@ struct NotificationsView: View {
|
|||
|
||||
private func loadNewNotifications() async {
|
||||
do {
|
||||
let linkable = try await NotificationService.shared.notifications(
|
||||
for: self.applicationState.account,
|
||||
minId: self.minId,
|
||||
limit: self.defaultPageSize)
|
||||
|
||||
if let first = linkable.data.first, self.notifications.contains(where: { notification in notification.id == first.id }) {
|
||||
// We have all notifications, we don't have to do anything.
|
||||
return
|
||||
if let linkable = try await self.client.notifications?.notifications(minId: self.minId, limit: self.defaultPageSize) {
|
||||
if let first = linkable.data.first, self.notifications.contains(where: { notification in notification.id == first.id }) {
|
||||
// We have all notifications, we don't have to do anything.
|
||||
return
|
||||
}
|
||||
|
||||
self.minId = linkable.link?.minId
|
||||
self.notifications.insert(contentsOf: linkable.data, at: 0)
|
||||
}
|
||||
|
||||
self.minId = linkable.link?.minId
|
||||
self.notifications.insert(contentsOf: linkable.data, at: 0)
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Error during download notifications from server.", showToastr: !Task.isCancelled)
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ struct PaginableStatusesView: View {
|
|||
}
|
||||
|
||||
@EnvironmentObject private var applicationState: ApplicationState
|
||||
@EnvironmentObject private var client: Client
|
||||
@EnvironmentObject private var routerPath: RouterPath
|
||||
|
||||
@State public var listType: ListType
|
||||
|
@ -137,15 +138,9 @@ struct PaginableStatusesView: View {
|
|||
switch self.listType {
|
||||
|
||||
case .favourites:
|
||||
return try await AccountService.shared.favourites(
|
||||
for: self.applicationState.account,
|
||||
limit: self.defaultLimit,
|
||||
page: self.page)
|
||||
return try await self.client.accounts?.favourites(limit: self.defaultLimit, page: self.page) ?? []
|
||||
case .bookmarks:
|
||||
return try await AccountService.shared.bookmarks(
|
||||
for: self.applicationState.account,
|
||||
limit: self.defaultLimit,
|
||||
page: self.page)
|
||||
return try await self.client.accounts?.bookmarks(limit: self.defaultLimit, page: self.page) ?? []
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,9 @@ import AuthenticationServices
|
|||
struct SignInView: View {
|
||||
@Environment(\.managedObjectContext) private var viewContext
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
@EnvironmentObject var applicationState: ApplicationState
|
||||
@EnvironmentObject var client: Client
|
||||
|
||||
@State private var serverAddress: String = String.empty()
|
||||
@State private var instances: [Instance] = []
|
||||
|
@ -62,7 +64,7 @@ struct SignInView: View {
|
|||
|
||||
}
|
||||
.onFirstAppear {
|
||||
self.instances = await InstanceService.shared.instances(urls: InstanceService.shared.pixelfedInstances)
|
||||
self.instances = await self.client.instances.instances(urls: self.client.instances.pixelfedInstances)
|
||||
}
|
||||
.navigationBarTitle("Sign in to Pixelfed")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
|
|
|
@ -10,6 +10,7 @@ import AVFoundation
|
|||
|
||||
struct StatusView: View {
|
||||
@EnvironmentObject var applicationState: ApplicationState
|
||||
@EnvironmentObject var client: Client
|
||||
@EnvironmentObject var routerPath: RouterPath
|
||||
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
@ -80,7 +81,7 @@ struct StatusView: View {
|
|||
|
||||
MarkdownFormattedText(statusViewModel.content.asMarkdown)
|
||||
.environment(\.openURL, OpenURLAction { url in
|
||||
routerPath.handle(url: url, account: self.applicationState.account)
|
||||
routerPath.handle(url: url)
|
||||
})
|
||||
|
||||
VStack (alignment: .leading) {
|
||||
|
@ -145,7 +146,7 @@ struct StatusView: View {
|
|||
private func loadData() async {
|
||||
do {
|
||||
// Get status from API.
|
||||
if let status = try await StatusService.shared.status(withId: self.statusId, for: self.applicationState.account) {
|
||||
if let status = try await self.client.statuses?.status(withId: self.statusId) {
|
||||
let statusViewModel = StatusModel(status: status)
|
||||
|
||||
self.statusViewModel = statusViewModel
|
||||
|
|
|
@ -17,6 +17,7 @@ struct StatusesView: View {
|
|||
}
|
||||
|
||||
@EnvironmentObject private var applicationState: ApplicationState
|
||||
@EnvironmentObject private var client: Client
|
||||
@EnvironmentObject private var routerPath: RouterPath
|
||||
|
||||
@State public var listType: ListType
|
||||
|
@ -162,47 +163,42 @@ struct StatusesView: View {
|
|||
private func loadFromApi(maxId: String? = nil, sinceId: String? = nil, minId: String? = nil) async throws -> [Status] {
|
||||
switch self.listType {
|
||||
case .local:
|
||||
return try await PublicTimelineService.shared.getStatuses(
|
||||
for: self.applicationState.account,
|
||||
return try await self.client.publicTimeline?.getStatuses(
|
||||
local: true,
|
||||
remote: false,
|
||||
maxId: maxId,
|
||||
sinceId: sinceId,
|
||||
minId: minId,
|
||||
limit: self.defaultLimit)
|
||||
limit: self.defaultLimit) ?? []
|
||||
case .federated:
|
||||
return try await PublicTimelineService.shared.getStatuses(
|
||||
for: self.applicationState.account,
|
||||
return try await self.client.publicTimeline?.getStatuses(
|
||||
local: false,
|
||||
remote: true,
|
||||
maxId: maxId,
|
||||
sinceId: sinceId,
|
||||
minId: minId,
|
||||
limit: self.defaultLimit)
|
||||
limit: self.defaultLimit) ?? []
|
||||
case .favourites:
|
||||
return try await AccountService.shared.favourites(
|
||||
for: self.applicationState.account,
|
||||
return try await self.client.accounts?.favourites(
|
||||
maxId: maxId,
|
||||
sinceId: sinceId,
|
||||
minId: minId,
|
||||
limit: self.defaultLimit)
|
||||
limit: self.defaultLimit) ?? []
|
||||
case .bookmarks:
|
||||
return try await AccountService.shared.bookmarks(
|
||||
for: self.applicationState.account,
|
||||
return try await self.client.accounts?.bookmarks(
|
||||
maxId: maxId,
|
||||
sinceId: sinceId,
|
||||
minId: minId,
|
||||
limit: self.defaultLimit)
|
||||
limit: self.defaultLimit) ?? []
|
||||
case .hashtag(let tag):
|
||||
return try await PublicTimelineService.shared.getTagStatuses(
|
||||
for: self.applicationState.account,
|
||||
return try await self.client.publicTimeline?.getTagStatuses(
|
||||
tag: tag,
|
||||
local: false,
|
||||
remote: true,
|
||||
maxId: maxId,
|
||||
sinceId: sinceId,
|
||||
minId: minId,
|
||||
limit: self.defaultLimit)
|
||||
limit: self.defaultLimit) ?? []
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -243,7 +239,7 @@ struct StatusesView: View {
|
|||
|
||||
private func loadTag(hashtag: String) async {
|
||||
do {
|
||||
self.tag = try await TagsService.shared.get(tag: hashtag, for: self.applicationState.account)
|
||||
self.tag = try await self.client.tags?.get(tag: hashtag)
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Error during loading tag from server.", showToastr: false)
|
||||
}
|
||||
|
@ -251,7 +247,7 @@ struct StatusesView: View {
|
|||
|
||||
private func follow(hashtag: String) async {
|
||||
do {
|
||||
self.tag = try await TagsService.shared.follow(tag: hashtag, for: self.applicationState.account)
|
||||
self.tag = try await self.client.tags?.follow(tag: hashtag)
|
||||
ToastrService.shared.showSuccess("You are following the tag.", imageSystemName: "number.square.fill")
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Error during following tag.", showToastr: true)
|
||||
|
@ -260,7 +256,7 @@ struct StatusesView: View {
|
|||
|
||||
private func unfollow(hashtag: String) async {
|
||||
do {
|
||||
self.tag = try await TagsService.shared.unfollow(tag: hashtag, for: self.applicationState.account)
|
||||
self.tag = try await self.client.tags?.unfollow(tag: hashtag)
|
||||
ToastrService.shared.showSuccess("Tag has been unfollowed.", imageSystemName: "number.square")
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Error during unfollowing tag.", showToastr: true)
|
||||
|
|
|
@ -8,8 +8,9 @@ import SwiftUI
|
|||
import MastodonKit
|
||||
|
||||
struct TrendStatusesView: View {
|
||||
|
||||
@EnvironmentObject private var applicationState: ApplicationState
|
||||
@EnvironmentObject private var client: Client
|
||||
|
||||
@State public var accountId: String
|
||||
|
||||
@State private var tabSelectedValue: Mastodon.PixelfedTrends.TrendRange = .daily
|
||||
|
@ -108,16 +109,14 @@ struct TrendStatusesView: View {
|
|||
}
|
||||
|
||||
private func loadStatuses() async throws {
|
||||
let statuses = try await TrendsService.shared.statuses(
|
||||
for: self.applicationState.account,
|
||||
range: tabSelectedValue)
|
||||
|
||||
var inPlaceStatuses: [StatusModel] = []
|
||||
|
||||
for item in statuses.getStatusesWithImagesOnly() {
|
||||
inPlaceStatuses.append(StatusModel(status: item))
|
||||
if let statuses = try await client.trends?.statuses(range: tabSelectedValue) {
|
||||
var inPlaceStatuses: [StatusModel] = []
|
||||
|
||||
for item in statuses.getStatusesWithImagesOnly() {
|
||||
inPlaceStatuses.append(StatusModel(status: item))
|
||||
}
|
||||
|
||||
self.statusViewModels = inPlaceStatuses
|
||||
}
|
||||
|
||||
self.statusViewModels = inPlaceStatuses
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import MastodonKit
|
|||
|
||||
struct UserProfileView: View {
|
||||
@EnvironmentObject private var applicationState: ApplicationState
|
||||
@EnvironmentObject private var client: Client
|
||||
|
||||
@State public var accountId: String
|
||||
@State public var accountDisplayName: String?
|
||||
|
@ -58,8 +59,8 @@ struct UserProfileView: View {
|
|||
|
||||
private func loadData() async {
|
||||
do {
|
||||
async let relationshipTask = AccountService.shared.relationships(withId: self.accountId, for: self.applicationState.account)
|
||||
async let accountTask = AccountService.shared.account(withId: self.accountId, for: self.applicationState.account)
|
||||
async let relationshipTask = self.client.accounts?.relationships(withId: self.accountId)
|
||||
async let accountTask = self.client.accounts?.account(withId: self.accountId)
|
||||
|
||||
// Wait for download account and relationships.
|
||||
(self.relationship, self.account) = try await (relationshipTask, accountTask)
|
||||
|
@ -155,17 +156,11 @@ struct UserProfileView: View {
|
|||
private func onMuteAccount(account: Account) async {
|
||||
do {
|
||||
if self.relationship?.muting == true {
|
||||
if let relationship = try await AccountService.shared.unmute(
|
||||
account: account.id,
|
||||
for: self.applicationState.account
|
||||
) {
|
||||
if let relationship = try await self.client.accounts?.unmute(account: account.id) {
|
||||
self.relationship = relationship
|
||||
}
|
||||
} else {
|
||||
if let relationship = try await AccountService.shared.mute(
|
||||
account: account.id,
|
||||
for: self.applicationState.account
|
||||
) {
|
||||
if let relationship = try await self.client.accounts?.mute(account: account.id) {
|
||||
self.relationship = relationship
|
||||
}
|
||||
}
|
||||
|
@ -177,17 +172,11 @@ struct UserProfileView: View {
|
|||
private func onBlockAccount(account: Account) async {
|
||||
do {
|
||||
if self.relationship?.blocking == true {
|
||||
if let relationship = try await AccountService.shared.unblock(
|
||||
account: account.id,
|
||||
for: self.applicationState.account
|
||||
) {
|
||||
if let relationship = try await self.client.accounts?.unblock(account: account.id) {
|
||||
self.relationship = relationship
|
||||
}
|
||||
} else {
|
||||
if let relationship = try await AccountService.shared.block(
|
||||
account: account.id,
|
||||
for: self.applicationState.account
|
||||
) {
|
||||
if let relationship = try await self.client.accounts?.block(account: account.id) {
|
||||
self.relationship = relationship
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import SwiftUI
|
|||
|
||||
struct ImageRow: View {
|
||||
@EnvironmentObject var applicationState: ApplicationState
|
||||
@EnvironmentObject var client: Client
|
||||
@EnvironmentObject var routerPath: RouterPath
|
||||
|
||||
private let status: StatusData
|
||||
|
@ -74,7 +75,7 @@ struct ImageRow: View {
|
|||
}
|
||||
.onLongPressGesture(minimumDuration: 0.2) {
|
||||
Task {
|
||||
try? await StatusService.shared.favourite(statusId: self.status.id, for: self.applicationState.account)
|
||||
try? await self.client.statuses?.favourite(statusId: self.status.id)
|
||||
}
|
||||
|
||||
self.showThumbImage = true
|
||||
|
|
|
@ -10,6 +10,7 @@ import NukeUI
|
|||
|
||||
struct ImageRowAsync: View {
|
||||
@EnvironmentObject var applicationState: ApplicationState
|
||||
@EnvironmentObject var client: Client
|
||||
@EnvironmentObject var routerPath: RouterPath
|
||||
|
||||
@State public var statusViewModel: StatusModel
|
||||
|
@ -129,7 +130,7 @@ struct ImageRowAsync: View {
|
|||
}
|
||||
.onLongPressGesture(minimumDuration: 0.2) {
|
||||
Task {
|
||||
try? await StatusService.shared.favourite(statusId: self.statusViewModel.id, for: self.applicationState.account)
|
||||
try? await self.client.statuses?.favourite(statusId: self.statusViewModel.id)
|
||||
}
|
||||
|
||||
self.showThumbImage = true
|
||||
|
|
|
@ -10,6 +10,7 @@ import Drops
|
|||
|
||||
struct InteractionRow: View {
|
||||
@EnvironmentObject var applicationState: ApplicationState
|
||||
@EnvironmentObject var client: Client
|
||||
@EnvironmentObject var routerPath: RouterPath
|
||||
|
||||
@State var statusViewModel: StatusModel
|
||||
|
@ -38,8 +39,8 @@ struct InteractionRow: View {
|
|||
ActionButton {
|
||||
do {
|
||||
let status = self.reblogged
|
||||
? try await StatusService.shared.unboost(statusId: self.statusViewModel.id, for: self.applicationState.account)
|
||||
: try await StatusService.shared.boost(statusId: self.statusViewModel.id, for: self.applicationState.account)
|
||||
? try await self.client.statuses?.unboost(statusId: self.statusViewModel.id)
|
||||
: try await self.client.statuses?.boost(statusId: self.statusViewModel.id)
|
||||
|
||||
if let status {
|
||||
self.reblogsCount = status.reblogsCount == self.reblogsCount
|
||||
|
@ -66,8 +67,8 @@ struct InteractionRow: View {
|
|||
ActionButton {
|
||||
do {
|
||||
let status = self.favourited
|
||||
? try await StatusService.shared.unfavourite(statusId: self.statusViewModel.id, for: self.applicationState.account)
|
||||
: try await StatusService.shared.favourite(statusId: self.statusViewModel.id, for: self.applicationState.account)
|
||||
? try await self.client.statuses?.unfavourite(statusId: self.statusViewModel.id)
|
||||
: try await self.client.statuses?.favourite(statusId: self.statusViewModel.id)
|
||||
|
||||
if let status {
|
||||
self.favouritesCount = status.favouritesCount == self.favouritesCount
|
||||
|
@ -94,8 +95,8 @@ struct InteractionRow: View {
|
|||
ActionButton {
|
||||
do {
|
||||
_ = self.bookmarked
|
||||
? try await StatusService.shared.unbookmark(statusId: self.statusViewModel.id, for: self.applicationState.account)
|
||||
: try await StatusService.shared.bookmark(statusId: self.statusViewModel.id, for: self.applicationState.account)
|
||||
? try await self.client.statuses?.unbookmark(statusId: self.statusViewModel.id)
|
||||
: try await self.client.statuses?.bookmark(statusId: self.statusViewModel.id)
|
||||
|
||||
self.bookmarked.toggle()
|
||||
ToastrService.shared.showSuccess("Bookmarked", imageSystemName: "bookmark.fill")
|
||||
|
|
|
@ -10,6 +10,7 @@ import MastodonKit
|
|||
struct CommentsSection: View {
|
||||
@Environment(\.colorScheme) var colorScheme
|
||||
@EnvironmentObject var applicationState: ApplicationState
|
||||
@EnvironmentObject var client: Client
|
||||
|
||||
@State public var statusId: String
|
||||
@State private var commentViewModels: [CommentModel]?
|
||||
|
@ -51,9 +52,7 @@ struct CommentsSection: View {
|
|||
}
|
||||
.task {
|
||||
do {
|
||||
if let accountData = applicationState.account {
|
||||
self.commentViewModels = try await StatusService.shared.comments(to: statusId, for: accountData)
|
||||
}
|
||||
self.commentViewModels = try await self.client.statuses?.comments(to: statusId) ?? []
|
||||
} catch {
|
||||
ErrorService.shared.handle(error, message: "Comments cannot be downloaded.", showToastr: !Task.isCancelled)
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import MastodonKit
|
|||
|
||||
struct UserProfileHeader: View {
|
||||
@EnvironmentObject private var applicationState: ApplicationState
|
||||
@EnvironmentObject private var client: Client
|
||||
@EnvironmentObject private var routerPath: RouterPath
|
||||
|
||||
@State var account: Account
|
||||
|
@ -75,7 +76,7 @@ struct UserProfileHeader: View {
|
|||
if let note = account.note, !note.isEmpty {
|
||||
MarkdownFormattedText(note.asMarkdown, withFontSize: 14, andWidth: Int(UIScreen.main.bounds.width) - 16)
|
||||
.environment(\.openURL, OpenURLAction { url in
|
||||
routerPath.handle(url: url, account: self.applicationState.account)
|
||||
routerPath.handle(url: url)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -104,17 +105,11 @@ struct UserProfileHeader: View {
|
|||
private func onRelationshipButtonTap() async {
|
||||
do {
|
||||
if self.relationship?.following == true {
|
||||
if let relationship = try await AccountService.shared.unfollow(
|
||||
account: self.account.id,
|
||||
for: self.applicationState.account
|
||||
) {
|
||||
if let relationship = try await self.client.accounts?.unfollow(account: self.account.id) {
|
||||
self.relationship = relationship
|
||||
}
|
||||
} else {
|
||||
if let relationship = try await AccountService.shared.follow(
|
||||
account: self.account.id,
|
||||
for: self.applicationState.account
|
||||
) {
|
||||
if let relationship = try await self.client.accounts?.follow(account: self.account.id) {
|
||||
self.relationship = relationship
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@ import MastodonKit
|
|||
|
||||
struct UserProfileStatuses: View {
|
||||
@EnvironmentObject private var applicationState: ApplicationState
|
||||
@EnvironmentObject private var client: Client
|
||||
|
||||
@State public var accountId: String
|
||||
|
||||
@State private var allItemsLoaded = false
|
||||
|
@ -60,10 +62,7 @@ struct UserProfileStatuses: View {
|
|||
}
|
||||
|
||||
private func loadStatuses() async throws {
|
||||
let statuses = try await AccountService.shared.statuses(
|
||||
createdBy: self.accountId,
|
||||
for: self.applicationState.account,
|
||||
limit: self.defaultLimit)
|
||||
let statuses = try await self.client.accounts?.statuses(createdBy: self.accountId, limit: self.defaultLimit) ?? []
|
||||
var inPlaceStatuses: [StatusModel] = []
|
||||
|
||||
for item in statuses {
|
||||
|
@ -80,11 +79,7 @@ struct UserProfileStatuses: View {
|
|||
|
||||
private func loadMoreStatuses() async throws {
|
||||
if let lastStatusId = self.statusViewModels.last?.id {
|
||||
let previousStatuses = try await AccountService.shared.statuses(
|
||||
createdBy: self.accountId,
|
||||
for: self.applicationState.account,
|
||||
maxId: lastStatusId,
|
||||
limit: self.defaultLimit)
|
||||
let previousStatuses = try await self.client.accounts?.statuses(createdBy: self.accountId, maxId: lastStatusId, limit: self.defaultLimit) ?? []
|
||||
|
||||
if previousStatuses.isEmpty {
|
||||
self.allItemsLoaded = true
|
||||
|
|
Loading…
Reference in New Issue