Compare commits
3 Commits
01124b76a3
...
6d692c2730
Author | SHA1 | Date |
---|---|---|
Shadowfacts | 6d692c2730 | |
Shadowfacts | d0f8691560 | |
Shadowfacts | 9a43ab5a13 |
|
@ -76,10 +76,6 @@
|
||||||
D627944D23A9A03D00D38C68 /* ListTimelineViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D627944C23A9A03D00D38C68 /* ListTimelineViewController.swift */; };
|
D627944D23A9A03D00D38C68 /* ListTimelineViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D627944C23A9A03D00D38C68 /* ListTimelineViewController.swift */; };
|
||||||
D627944F23A9C99800D38C68 /* EditListAccountsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D627944E23A9C99800D38C68 /* EditListAccountsViewController.swift */; };
|
D627944F23A9C99800D38C68 /* EditListAccountsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D627944E23A9C99800D38C68 /* EditListAccountsViewController.swift */; };
|
||||||
D627FF76217E923E00CC0648 /* DraftsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D627FF75217E923E00CC0648 /* DraftsManager.swift */; };
|
D627FF76217E923E00CC0648 /* DraftsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D627FF75217E923E00CC0648 /* DraftsManager.swift */; };
|
||||||
D627FF79217E950100CC0648 /* DraftsTableViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D627FF78217E950100CC0648 /* DraftsTableViewController.xib */; };
|
|
||||||
D627FF7B217E951500CC0648 /* DraftsTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D627FF7A217E951500CC0648 /* DraftsTableViewController.swift */; };
|
|
||||||
D627FF7D217E958900CC0648 /* DraftTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D627FF7C217E958900CC0648 /* DraftTableViewCell.xib */; };
|
|
||||||
D627FF7F217E95E000CC0648 /* DraftTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D627FF7E217E95E000CC0648 /* DraftTableViewCell.swift */; };
|
|
||||||
D6285B5321EA708700FE4B39 /* StatusFormat.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6285B5221EA708700FE4B39 /* StatusFormat.swift */; };
|
D6285B5321EA708700FE4B39 /* StatusFormat.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6285B5221EA708700FE4B39 /* StatusFormat.swift */; };
|
||||||
D6289E84217B795D0003D1D7 /* LargeImageViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D6289E83217B795D0003D1D7 /* LargeImageViewController.xib */; };
|
D6289E84217B795D0003D1D7 /* LargeImageViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D6289E83217B795D0003D1D7 /* LargeImageViewController.xib */; };
|
||||||
D62D2422217AA7E1005076CC /* UserActivityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62D2421217AA7E1005076CC /* UserActivityManager.swift */; };
|
D62D2422217AA7E1005076CC /* UserActivityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62D2421217AA7E1005076CC /* UserActivityManager.swift */; };
|
||||||
|
@ -257,6 +253,8 @@
|
||||||
D6BC9DDA232D8BE5002CA326 /* SearchResultsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6BC9DD9232D8BE5002CA326 /* SearchResultsViewController.swift */; };
|
D6BC9DDA232D8BE5002CA326 /* SearchResultsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6BC9DD9232D8BE5002CA326 /* SearchResultsViewController.swift */; };
|
||||||
D6BEA245291A0EDE002F4D01 /* Duckable in Frameworks */ = {isa = PBXBuildFile; productRef = D6BEA244291A0EDE002F4D01 /* Duckable */; };
|
D6BEA245291A0EDE002F4D01 /* Duckable in Frameworks */ = {isa = PBXBuildFile; productRef = D6BEA244291A0EDE002F4D01 /* Duckable */; };
|
||||||
D6BEA247291A0F2D002F4D01 /* Duckable+Root.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6BEA246291A0F2D002F4D01 /* Duckable+Root.swift */; };
|
D6BEA247291A0F2D002F4D01 /* Duckable+Root.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6BEA246291A0F2D002F4D01 /* Duckable+Root.swift */; };
|
||||||
|
D6BEA249291C6118002F4D01 /* DraftsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6BEA248291C6118002F4D01 /* DraftsView.swift */; };
|
||||||
|
D6BEA24B291C6A2B002F4D01 /* AlertWithData.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6BEA24A291C6A2B002F4D01 /* AlertWithData.swift */; };
|
||||||
D6BED174212667E900F02DA0 /* TimelineStatusTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6BED173212667E900F02DA0 /* TimelineStatusTableViewCell.swift */; };
|
D6BED174212667E900F02DA0 /* TimelineStatusTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6BED173212667E900F02DA0 /* TimelineStatusTableViewCell.swift */; };
|
||||||
D6C143DA253510F4007DC240 /* ComposeEmojiTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C143D9253510F4007DC240 /* ComposeEmojiTextField.swift */; };
|
D6C143DA253510F4007DC240 /* ComposeEmojiTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C143D9253510F4007DC240 /* ComposeEmojiTextField.swift */; };
|
||||||
D6C1B2082545D1EC00DAAA66 /* StatusCardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C1B2072545D1EC00DAAA66 /* StatusCardView.swift */; };
|
D6C1B2082545D1EC00DAAA66 /* StatusCardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C1B2072545D1EC00DAAA66 /* StatusCardView.swift */; };
|
||||||
|
@ -432,10 +430,6 @@
|
||||||
D627944C23A9A03D00D38C68 /* ListTimelineViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTimelineViewController.swift; sourceTree = "<group>"; };
|
D627944C23A9A03D00D38C68 /* ListTimelineViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTimelineViewController.swift; sourceTree = "<group>"; };
|
||||||
D627944E23A9C99800D38C68 /* EditListAccountsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditListAccountsViewController.swift; sourceTree = "<group>"; };
|
D627944E23A9C99800D38C68 /* EditListAccountsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditListAccountsViewController.swift; sourceTree = "<group>"; };
|
||||||
D627FF75217E923E00CC0648 /* DraftsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DraftsManager.swift; sourceTree = "<group>"; };
|
D627FF75217E923E00CC0648 /* DraftsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DraftsManager.swift; sourceTree = "<group>"; };
|
||||||
D627FF78217E950100CC0648 /* DraftsTableViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = DraftsTableViewController.xib; sourceTree = "<group>"; };
|
|
||||||
D627FF7A217E951500CC0648 /* DraftsTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DraftsTableViewController.swift; sourceTree = "<group>"; };
|
|
||||||
D627FF7C217E958900CC0648 /* DraftTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = DraftTableViewCell.xib; sourceTree = "<group>"; };
|
|
||||||
D627FF7E217E95E000CC0648 /* DraftTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DraftTableViewCell.swift; sourceTree = "<group>"; };
|
|
||||||
D6285B5221EA708700FE4B39 /* StatusFormat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusFormat.swift; sourceTree = "<group>"; };
|
D6285B5221EA708700FE4B39 /* StatusFormat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusFormat.swift; sourceTree = "<group>"; };
|
||||||
D6289E83217B795D0003D1D7 /* LargeImageViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = LargeImageViewController.xib; sourceTree = "<group>"; };
|
D6289E83217B795D0003D1D7 /* LargeImageViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = LargeImageViewController.xib; sourceTree = "<group>"; };
|
||||||
D62D2421217AA7E1005076CC /* UserActivityManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserActivityManager.swift; sourceTree = "<group>"; };
|
D62D2421217AA7E1005076CC /* UserActivityManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserActivityManager.swift; sourceTree = "<group>"; };
|
||||||
|
@ -615,6 +609,8 @@
|
||||||
D6BC9DD9232D8BE5002CA326 /* SearchResultsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultsViewController.swift; sourceTree = "<group>"; };
|
D6BC9DD9232D8BE5002CA326 /* SearchResultsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultsViewController.swift; sourceTree = "<group>"; };
|
||||||
D6BEA243291A0C83002F4D01 /* Duckable */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Duckable; path = Packages/Duckable; sourceTree = "<group>"; };
|
D6BEA243291A0C83002F4D01 /* Duckable */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Duckable; path = Packages/Duckable; sourceTree = "<group>"; };
|
||||||
D6BEA246291A0F2D002F4D01 /* Duckable+Root.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Duckable+Root.swift"; sourceTree = "<group>"; };
|
D6BEA246291A0F2D002F4D01 /* Duckable+Root.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Duckable+Root.swift"; sourceTree = "<group>"; };
|
||||||
|
D6BEA248291C6118002F4D01 /* DraftsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DraftsView.swift; sourceTree = "<group>"; };
|
||||||
|
D6BEA24A291C6A2B002F4D01 /* AlertWithData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertWithData.swift; sourceTree = "<group>"; };
|
||||||
D6BED173212667E900F02DA0 /* TimelineStatusTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineStatusTableViewCell.swift; sourceTree = "<group>"; };
|
D6BED173212667E900F02DA0 /* TimelineStatusTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineStatusTableViewCell.swift; sourceTree = "<group>"; };
|
||||||
D6C143D9253510F4007DC240 /* ComposeEmojiTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeEmojiTextField.swift; sourceTree = "<group>"; };
|
D6C143D9253510F4007DC240 /* ComposeEmojiTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeEmojiTextField.swift; sourceTree = "<group>"; };
|
||||||
D6C1B2072545D1EC00DAAA66 /* StatusCardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusCardView.swift; sourceTree = "<group>"; };
|
D6C1B2072545D1EC00DAAA66 /* StatusCardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusCardView.swift; sourceTree = "<group>"; };
|
||||||
|
@ -743,15 +739,6 @@
|
||||||
path = "Hashtag Cell";
|
path = "Hashtag Cell";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
D61959D0241E842400A37B8E /* Draft Cell */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
D627FF7C217E958900CC0648 /* DraftTableViewCell.xib */,
|
|
||||||
D627FF7E217E95E000CC0648 /* DraftTableViewCell.swift */,
|
|
||||||
);
|
|
||||||
path = "Draft Cell";
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
D61959D2241E846D00A37B8E /* Models */ = {
|
D61959D2241E846D00A37B8E /* Models */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -850,15 +837,6 @@
|
||||||
path = Lists;
|
path = Lists;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
D627FF77217E94F200CC0648 /* Drafts */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
D627FF78217E950100CC0648 /* DraftsTableViewController.xib */,
|
|
||||||
D627FF7A217E951500CC0648 /* DraftsTableViewController.swift */,
|
|
||||||
);
|
|
||||||
path = Drafts;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
D62D241E217AA46B005076CC /* Shortcuts */ = {
|
D62D241E217AA46B005076CC /* Shortcuts */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -906,7 +884,6 @@
|
||||||
D641C787213DD862004B4513 /* Compose */,
|
D641C787213DD862004B4513 /* Compose */,
|
||||||
D641C785213DD83B004B4513 /* Conversation */,
|
D641C785213DD83B004B4513 /* Conversation */,
|
||||||
D6F2E960249E772F005846BB /* Crash Reporter */,
|
D6F2E960249E772F005846BB /* Crash Reporter */,
|
||||||
D627FF77217E94F200CC0648 /* Drafts */,
|
|
||||||
D627943C23A5635D00D38C68 /* Explore */,
|
D627943C23A5635D00D38C68 /* Explore */,
|
||||||
D6A4DCC92553666600D9DE31 /* Fast Account Switcher */,
|
D6A4DCC92553666600D9DE31 /* Fast Account Switcher */,
|
||||||
D641C788213DD86D004B4513 /* Large Image */,
|
D641C788213DD86D004B4513 /* Large Image */,
|
||||||
|
@ -1011,6 +988,7 @@
|
||||||
D62275A724F1CA2800B82A16 /* ComposeReplyContentView.swift */,
|
D62275A724F1CA2800B82A16 /* ComposeReplyContentView.swift */,
|
||||||
D6E4267625327FB400C02E1C /* ComposeAutocompleteView.swift */,
|
D6E4267625327FB400C02E1C /* ComposeAutocompleteView.swift */,
|
||||||
D6C143D9253510F4007DC240 /* ComposeEmojiTextField.swift */,
|
D6C143D9253510F4007DC240 /* ComposeEmojiTextField.swift */,
|
||||||
|
D6BEA248291C6118002F4D01 /* DraftsView.swift */,
|
||||||
);
|
);
|
||||||
path = Compose;
|
path = Compose;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -1284,6 +1262,7 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
D6B4A4FE2506B81A000C81C1 /* AccountDisplayNameLabel.swift */,
|
D6B4A4FE2506B81A000C81C1 /* AccountDisplayNameLabel.swift */,
|
||||||
|
D6BEA24A291C6A2B002F4D01 /* AlertWithData.swift */,
|
||||||
D68E6F5E253C9B2D001A1B4C /* BaseEmojiLabel.swift */,
|
D68E6F5E253C9B2D001A1B4C /* BaseEmojiLabel.swift */,
|
||||||
D6ADB6EF28ED1F25009924AB /* CachedImageView.swift */,
|
D6ADB6EF28ED1F25009924AB /* CachedImageView.swift */,
|
||||||
D6895DC328D65342006341DA /* ConfirmReblogStatusPreviewView.swift */,
|
D6895DC328D65342006341DA /* ConfirmReblogStatusPreviewView.swift */,
|
||||||
|
@ -1312,7 +1291,6 @@
|
||||||
D626494023C122C800612E6E /* Asset Picker */,
|
D626494023C122C800612E6E /* Asset Picker */,
|
||||||
D6C7D27B22B6EBE200071952 /* Attachments */,
|
D6C7D27B22B6EBE200071952 /* Attachments */,
|
||||||
D6DEA0DB268400AF00FE896A /* Confirm Load More Cell */,
|
D6DEA0DB268400AF00FE896A /* Confirm Load More Cell */,
|
||||||
D61959D0241E842400A37B8E /* Draft Cell */,
|
|
||||||
D611C2CC232DC5FC00C86A49 /* Hashtag Cell */,
|
D611C2CC232DC5FC00C86A49 /* Hashtag Cell */,
|
||||||
D61AC1DA232EA43100C54D2D /* Instance Cell */,
|
D61AC1DA232EA43100C54D2D /* Instance Cell */,
|
||||||
D641C78C213DD937004B4513 /* Notifications */,
|
D641C78C213DD937004B4513 /* Notifications */,
|
||||||
|
@ -1670,7 +1648,6 @@
|
||||||
D61AC1D9232EA42D00C54D2D /* InstanceTableViewCell.xib in Resources */,
|
D61AC1D9232EA42D00C54D2D /* InstanceTableViewCell.xib in Resources */,
|
||||||
D626493923C0FD0000612E6E /* AllPhotosTableViewCell.xib in Resources */,
|
D626493923C0FD0000612E6E /* AllPhotosTableViewCell.xib in Resources */,
|
||||||
D6A3BC8B2321F79B00FD64D5 /* AccountTableViewCell.xib in Resources */,
|
D6A3BC8B2321F79B00FD64D5 /* AccountTableViewCell.xib in Resources */,
|
||||||
D627FF7D217E958900CC0648 /* DraftTableViewCell.xib in Resources */,
|
|
||||||
D6A3BC7D232195C600FD64D5 /* ActionNotificationGroupTableViewCell.xib in Resources */,
|
D6A3BC7D232195C600FD64D5 /* ActionNotificationGroupTableViewCell.xib in Resources */,
|
||||||
D6412B0B24B0D4C600F5412E /* ProfileHeaderView.xib in Resources */,
|
D6412B0B24B0D4C600F5412E /* ProfileHeaderView.xib in Resources */,
|
||||||
D6C82B5725C5F3F20017F1E6 /* ExpandThreadTableViewCell.xib in Resources */,
|
D6C82B5725C5F3F20017F1E6 /* ExpandThreadTableViewCell.xib in Resources */,
|
||||||
|
@ -1682,7 +1659,6 @@
|
||||||
D663625D2135C74800C9CBA2 /* ConversationMainStatusTableViewCell.xib in Resources */,
|
D663625D2135C74800C9CBA2 /* ConversationMainStatusTableViewCell.xib in Resources */,
|
||||||
D640D76922BAF5E6004FBE69 /* DomainBlocks.plist in Resources */,
|
D640D76922BAF5E6004FBE69 /* DomainBlocks.plist in Resources */,
|
||||||
D6289E84217B795D0003D1D7 /* LargeImageViewController.xib in Resources */,
|
D6289E84217B795D0003D1D7 /* LargeImageViewController.xib in Resources */,
|
||||||
D627FF79217E950100CC0648 /* DraftsTableViewController.xib in Resources */,
|
|
||||||
D626493D23C1000300612E6E /* AlbumTableViewCell.xib in Resources */,
|
D626493D23C1000300612E6E /* AlbumTableViewCell.xib in Resources */,
|
||||||
D627944723A6AC9300D38C68 /* BasicTableViewCell.xib in Resources */,
|
D627944723A6AC9300D38C68 /* BasicTableViewCell.xib in Resources */,
|
||||||
D64BC19023C18B9D000D0238 /* FollowRequestNotificationTableViewCell.xib in Resources */,
|
D64BC19023C18B9D000D0238 /* FollowRequestNotificationTableViewCell.xib in Resources */,
|
||||||
|
@ -1861,7 +1837,7 @@
|
||||||
D67B506D250B291200FAECFB /* BlurHashDecode.swift in Sources */,
|
D67B506D250B291200FAECFB /* BlurHashDecode.swift in Sources */,
|
||||||
D62275A024F1677200B82A16 /* ComposeHostingController.swift in Sources */,
|
D62275A024F1677200B82A16 /* ComposeHostingController.swift in Sources */,
|
||||||
04DACE8E212CC7CC009840C4 /* ImageCache.swift in Sources */,
|
04DACE8E212CC7CC009840C4 /* ImageCache.swift in Sources */,
|
||||||
D627FF7B217E951500CC0648 /* DraftsTableViewController.swift in Sources */,
|
D6BEA249291C6118002F4D01 /* DraftsView.swift in Sources */,
|
||||||
D6403CC224A6B72D00E81C55 /* VisualEffectImageButton.swift in Sources */,
|
D6403CC224A6B72D00E81C55 /* VisualEffectImageButton.swift in Sources */,
|
||||||
D6531DEE246B81C9000F9538 /* GifvAttachmentView.swift in Sources */,
|
D6531DEE246B81C9000F9538 /* GifvAttachmentView.swift in Sources */,
|
||||||
D673ACCE2919E74200D6F8B0 /* MenuPicker.swift in Sources */,
|
D673ACCE2919E74200D6F8B0 /* MenuPicker.swift in Sources */,
|
||||||
|
@ -1875,7 +1851,6 @@
|
||||||
D6BC9DDA232D8BE5002CA326 /* SearchResultsViewController.swift in Sources */,
|
D6BC9DDA232D8BE5002CA326 /* SearchResultsViewController.swift in Sources */,
|
||||||
D61ABEF628EE74D400B29151 /* StatusCollectionViewCell.swift in Sources */,
|
D61ABEF628EE74D400B29151 /* StatusCollectionViewCell.swift in Sources */,
|
||||||
D61DC84628F498F200B82C6E /* Logging.swift in Sources */,
|
D61DC84628F498F200B82C6E /* Logging.swift in Sources */,
|
||||||
D627FF7F217E95E000CC0648 /* DraftTableViewCell.swift in Sources */,
|
|
||||||
D6B17255254F88B800128392 /* OppositeCollapseKeywordsView.swift in Sources */,
|
D6B17255254F88B800128392 /* OppositeCollapseKeywordsView.swift in Sources */,
|
||||||
D6A00B1D26379FC900316AD4 /* PollOptionsView.swift in Sources */,
|
D6A00B1D26379FC900316AD4 /* PollOptionsView.swift in Sources */,
|
||||||
D6DF95C12533F5DE0027A9B6 /* RelationshipMO.swift in Sources */,
|
D6DF95C12533F5DE0027A9B6 /* RelationshipMO.swift in Sources */,
|
||||||
|
@ -1933,6 +1908,7 @@
|
||||||
D681E4D3246E2AFF0053414F /* MuteConversationActivity.swift in Sources */,
|
D681E4D3246E2AFF0053414F /* MuteConversationActivity.swift in Sources */,
|
||||||
D6969EA0240C8384002843CE /* EmojiLabel.swift in Sources */,
|
D6969EA0240C8384002843CE /* EmojiLabel.swift in Sources */,
|
||||||
D64BC18623C1253A000D0238 /* AssetPreviewViewController.swift in Sources */,
|
D64BC18623C1253A000D0238 /* AssetPreviewViewController.swift in Sources */,
|
||||||
|
D6BEA24B291C6A2B002F4D01 /* AlertWithData.swift in Sources */,
|
||||||
D61ABEFE28F1C92600B29151 /* FavoriteService.swift in Sources */,
|
D61ABEFE28F1C92600B29151 /* FavoriteService.swift in Sources */,
|
||||||
D663626221360B1900C9CBA2 /* Preferences.swift in Sources */,
|
D663626221360B1900C9CBA2 /* Preferences.swift in Sources */,
|
||||||
D626493823C0FD0000612E6E /* AllPhotosTableViewCell.swift in Sources */,
|
D626493823C0FD0000612E6E /* AllPhotosTableViewCell.swift in Sources */,
|
||||||
|
|
|
@ -107,6 +107,8 @@ extension Draft: Equatable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension Draft: Identifiable {}
|
||||||
|
|
||||||
extension Draft {
|
extension Draft {
|
||||||
enum CodingKeys: String, CodingKey {
|
enum CodingKeys: String, CodingKey {
|
||||||
case id
|
case id
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
class DraftsManager: Codable {
|
class DraftsManager: Codable, ObservableObject {
|
||||||
|
|
||||||
private(set) static var shared: DraftsManager = load()
|
private(set) static var shared: DraftsManager = load()
|
||||||
|
|
||||||
|
@ -48,7 +48,12 @@ class DraftsManager: Codable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var drafts: [UUID: Draft] = [:]
|
func encode(to encoder: Encoder) throws {
|
||||||
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
|
try container.encode(drafts, forKey: .drafts)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Published private var drafts: [UUID: Draft] = [:]
|
||||||
var sorted: [Draft] {
|
var sorted: [Draft] {
|
||||||
return drafts.values.sorted(by: { $0.lastModified > $1.lastModified })
|
return drafts.values.sorted(by: { $0.lastModified > $1.lastModified })
|
||||||
}
|
}
|
||||||
|
|
|
@ -335,9 +335,7 @@ class ComposeHostingController: UIHostingController<ComposeContainerView>, Ducka
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func draftsButtonPresed() {
|
@objc func draftsButtonPresed() {
|
||||||
let draftsVC = DraftsTableViewController(account: mastodonController.accountInfo!, exclude: draft)
|
uiState.isShowingDraftsList = true
|
||||||
draftsVC.delegate = self
|
|
||||||
present(UINavigationController(rootViewController: draftsVC), animated: true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -377,6 +375,16 @@ extension ComposeHostingController: ComposeUIStateDelegate {
|
||||||
|
|
||||||
present(ComposeDrawingNavigationController(editing: drawing, delegate: self), animated: true)
|
present(ComposeDrawingNavigationController(editing: drawing, delegate: self), animated: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func selectDraft(_ draft: Draft) {
|
||||||
|
if self.draft.hasContent {
|
||||||
|
DraftsManager.save()
|
||||||
|
} else {
|
||||||
|
DraftsManager.shared.remove(self.draft)
|
||||||
|
}
|
||||||
|
uiState.draft = draft
|
||||||
|
uiState.isShowingDraftsList = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ComposeHostingController: AssetPickerViewControllerDelegate {
|
extension ComposeHostingController: AssetPickerViewControllerDelegate {
|
||||||
|
@ -403,42 +411,6 @@ extension ComposeHostingController: AssetPickerViewControllerDelegate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ComposeHostingController: DraftsTableViewControllerDelegate {
|
|
||||||
func draftSelectionCanceled() {
|
|
||||||
}
|
|
||||||
|
|
||||||
func shouldSelectDraft(_ draft: Draft, completion: @escaping (Bool) -> Void) {
|
|
||||||
if draft.inReplyToID != self.draft.inReplyToID,
|
|
||||||
self.draft.hasContent {
|
|
||||||
let alertController = UIAlertController(title: "Different Reply", message: "The selected draft is a reply to a different status, do you wish to use it?", preferredStyle: .alert)
|
|
||||||
alertController.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { (_) in
|
|
||||||
completion(false)
|
|
||||||
}))
|
|
||||||
alertController.addAction(UIAlertAction(title: "Restore Draft", style: .default, handler: { (_) in
|
|
||||||
completion(true)
|
|
||||||
}))
|
|
||||||
// we can't present the laert ourselves since the compose VC is already presenting the draft selector
|
|
||||||
// but presenting on the presented view controller seems hacky, is there a better way to do this?
|
|
||||||
presentedViewController!.present(alertController, animated: true)
|
|
||||||
} else {
|
|
||||||
completion(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func draftSelected(_ draft: Draft) {
|
|
||||||
if self.draft.hasContent {
|
|
||||||
DraftsManager.save()
|
|
||||||
} else {
|
|
||||||
DraftsManager.shared.remove(self.draft)
|
|
||||||
}
|
|
||||||
|
|
||||||
uiState.draft = draft
|
|
||||||
}
|
|
||||||
|
|
||||||
func draftSelectionCompleted() {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// superseded by duckable stuff
|
// superseded by duckable stuff
|
||||||
@available(iOS, obsoleted: 16.0)
|
@available(iOS, obsoleted: 16.0)
|
||||||
extension ComposeHostingController: UIAdaptivePresentationControllerDelegate {
|
extension ComposeHostingController: UIAdaptivePresentationControllerDelegate {
|
||||||
|
|
|
@ -82,6 +82,7 @@ struct WrappedTextView: UIViewRepresentable {
|
||||||
|
|
||||||
func updateUIView(_ uiView: UITextView, context: Context) {
|
func updateUIView(_ uiView: UITextView, context: Context) {
|
||||||
uiView.text = text
|
uiView.text = text
|
||||||
|
context.coordinator.textView = uiView
|
||||||
context.coordinator.text = $text
|
context.coordinator.text = $text
|
||||||
context.coordinator.didChange = textDidChange
|
context.coordinator.didChange = textDidChange
|
||||||
// wait until the next runloop iteration so that SwiftUI view updates have finished and
|
// wait until the next runloop iteration so that SwiftUI view updates have finished and
|
||||||
|
@ -96,6 +97,7 @@ struct WrappedTextView: UIViewRepresentable {
|
||||||
}
|
}
|
||||||
|
|
||||||
class Coordinator: NSObject, UITextViewDelegate, ComposeTextViewCaretScrolling {
|
class Coordinator: NSObject, UITextViewDelegate, ComposeTextViewCaretScrolling {
|
||||||
|
weak var textView: UITextView?
|
||||||
var text: Binding<String>
|
var text: Binding<String>
|
||||||
var didChange: ((UITextView) -> Void)?
|
var didChange: ((UITextView) -> Void)?
|
||||||
var caretScrollPositionAnimator: UIViewPropertyAnimator?
|
var caretScrollPositionAnimator: UIViewPropertyAnimator?
|
||||||
|
@ -103,6 +105,16 @@ struct WrappedTextView: UIViewRepresentable {
|
||||||
init(text: Binding<String>, didChange: ((UITextView) -> Void)?) {
|
init(text: Binding<String>, didChange: ((UITextView) -> Void)?) {
|
||||||
self.text = text
|
self.text = text
|
||||||
self.didChange = didChange
|
self.didChange = didChange
|
||||||
|
|
||||||
|
super.init()
|
||||||
|
|
||||||
|
NotificationCenter.default.addObserver(self, selector: #selector(keyboardDidShow), name: UIResponder.keyboardDidShowNotification, object: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func keyboardDidShow() {
|
||||||
|
guard let textView,
|
||||||
|
textView.isFirstResponder else { return }
|
||||||
|
ensureCursorVisible(textView: textView)
|
||||||
}
|
}
|
||||||
|
|
||||||
func textViewDidChange(_ textView: UITextView) {
|
func textViewDidChange(_ textView: UITextView) {
|
||||||
|
|
|
@ -37,7 +37,7 @@ extension ComposeTextViewCaretScrolling {
|
||||||
rectToMakeVisible.origin.y -= cursorRect.height
|
rectToMakeVisible.origin.y -= cursorRect.height
|
||||||
rectToMakeVisible.size.height *= 3
|
rectToMakeVisible.size.height *= 3
|
||||||
|
|
||||||
let animator = UIViewPropertyAnimator(duration: 0.1, curve: .linear) {
|
let animator = UIViewPropertyAnimator(duration: 0.2, curve: .easeInOut) {
|
||||||
scrollView.scrollRectToVisible(rectToMakeVisible, animated: false)
|
scrollView.scrollRectToVisible(rectToMakeVisible, animated: false)
|
||||||
}
|
}
|
||||||
self.caretScrollPositionAnimator = animator
|
self.caretScrollPositionAnimator = animator
|
||||||
|
|
|
@ -15,6 +15,7 @@ protocol ComposeUIStateDelegate: AnyObject {
|
||||||
// @available(iOS, obsoleted: 16.0)
|
// @available(iOS, obsoleted: 16.0)
|
||||||
func presentAssetPickerSheet()
|
func presentAssetPickerSheet()
|
||||||
func presentComposeDrawing()
|
func presentComposeDrawing()
|
||||||
|
func selectDraft(_ draft: Draft)
|
||||||
|
|
||||||
func keyboardWillShow(accessoryView: UIView, notification: Notification)
|
func keyboardWillShow(accessoryView: UIView, notification: Notification)
|
||||||
func keyboardWillHide(accessoryView: UIView, notification: Notification)
|
func keyboardWillHide(accessoryView: UIView, notification: Notification)
|
||||||
|
@ -27,6 +28,7 @@ class ComposeUIState: ObservableObject {
|
||||||
|
|
||||||
@Published var draft: Draft
|
@Published var draft: Draft
|
||||||
@Published var isShowingSaveDraftSheet = false
|
@Published var isShowingSaveDraftSheet = false
|
||||||
|
@Published var isShowingDraftsList = false
|
||||||
@Published var attachmentsMissingDescriptions = Set<UUID>()
|
@Published var attachmentsMissingDescriptions = Set<UUID>()
|
||||||
@Published var autocompleteState: AutocompleteState? = nil
|
@Published var autocompleteState: AutocompleteState? = nil
|
||||||
|
|
||||||
|
|
|
@ -98,6 +98,9 @@ struct ComposeView: View {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.navigationTitle(navTitle)
|
.navigationTitle(navTitle)
|
||||||
|
.sheet(isPresented: $uiState.isShowingDraftsList) {
|
||||||
|
DraftsView(currentDraft: draft)
|
||||||
|
}
|
||||||
.actionSheet(isPresented: $uiState.isShowingSaveDraftSheet, content: self.saveAndCloseSheet)
|
.actionSheet(isPresented: $uiState.isShowingSaveDraftSheet, content: self.saveAndCloseSheet)
|
||||||
.alert(isPresented: $isShowingPostErrorAlert) {
|
.alert(isPresented: $isShowingPostErrorAlert) {
|
||||||
Alert(
|
Alert(
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
//
|
||||||
|
// DraftsView.swift
|
||||||
|
// Tusker
|
||||||
|
//
|
||||||
|
// Created by Shadowfacts on 11/9/22.
|
||||||
|
// Copyright © 2022 Shadowfacts. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct DraftsView: View {
|
||||||
|
let currentDraft: Draft
|
||||||
|
@EnvironmentObject var uiState: ComposeUIState
|
||||||
|
@EnvironmentObject var mastodonController: MastodonController
|
||||||
|
@StateObject private var draftsManager = DraftsManager.shared
|
||||||
|
@State private var draftForDifferentReply: Draft?
|
||||||
|
|
||||||
|
private var visibleDrafts: [Draft] {
|
||||||
|
draftsManager.sorted.filter {
|
||||||
|
$0.accountID == mastodonController.accountInfo!.id && $0.id != currentDraft.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
NavigationView {
|
||||||
|
List {
|
||||||
|
ForEach(visibleDrafts) { draft in
|
||||||
|
Button {
|
||||||
|
maybeSelectDraft(draft)
|
||||||
|
} label: {
|
||||||
|
DraftView(draft: draft)
|
||||||
|
}
|
||||||
|
.onDrag {
|
||||||
|
let activity = UserActivityManager.editDraftActivity(id: draft.id, accountID: mastodonController.accountInfo!.id)
|
||||||
|
activity.displaysAuxiliaryScene = true
|
||||||
|
return NSItemProvider(object: activity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.onDelete { indices in
|
||||||
|
indices
|
||||||
|
.map { visibleDrafts[$0] }
|
||||||
|
.forEach { draftsManager.remove($0) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.listStyle(.plain)
|
||||||
|
.navigationTitle(Text("Drafts"))
|
||||||
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
|
.toolbar {
|
||||||
|
ToolbarItem(placement: .cancellationAction) {
|
||||||
|
Button("Cancel") {
|
||||||
|
uiState.isShowingDraftsList = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.alertWithData("Different Reply", data: $draftForDifferentReply) { draft in
|
||||||
|
Button("Cancel", role: .cancel) {
|
||||||
|
draftForDifferentReply = nil
|
||||||
|
}
|
||||||
|
Button("Restore Draft") {
|
||||||
|
uiState.delegate?.selectDraft(draft)
|
||||||
|
}
|
||||||
|
} message: { draft in
|
||||||
|
Text("The selected draft is a reply to a different post, do you wish to use it?")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func maybeSelectDraft(_ draft: Draft) {
|
||||||
|
if draft.inReplyToID != currentDraft.inReplyToID,
|
||||||
|
currentDraft.hasContent {
|
||||||
|
draftForDifferentReply = draft
|
||||||
|
} else {
|
||||||
|
uiState.delegate?.selectDraft(draft)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DraftView: View {
|
||||||
|
@ObservedObject private var draft: Draft
|
||||||
|
|
||||||
|
init(draft: Draft) {
|
||||||
|
self._draft = ObservedObject(wrappedValue: draft)
|
||||||
|
}
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
HStack {
|
||||||
|
VStack(alignment: .leading) {
|
||||||
|
if draft.contentWarningEnabled {
|
||||||
|
Text(draft.contentWarning)
|
||||||
|
.font(.body.bold())
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
}
|
||||||
|
|
||||||
|
Text(draft.text)
|
||||||
|
.font(.body)
|
||||||
|
|
||||||
|
HStack(spacing: 8) {
|
||||||
|
ForEach(draft.attachments) { attachment in
|
||||||
|
ComposeAttachmentImage(attachment: attachment, fullSize: false)
|
||||||
|
.frame(width: 50, height: 50)
|
||||||
|
.cornerRadius(5)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
Text(draft.lastModified.timeAgoString())
|
||||||
|
.font(.body)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DraftsView_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
DraftsView(currentDraft: Draft(accountID: ""))
|
||||||
|
}
|
||||||
|
}
|
|
@ -168,6 +168,16 @@ struct MainComposeWrappedTextView: UIViewRepresentable {
|
||||||
self.text = text
|
self.text = text
|
||||||
self.didChange = didChange
|
self.didChange = didChange
|
||||||
self.uiState = uiState
|
self.uiState = uiState
|
||||||
|
|
||||||
|
super.init()
|
||||||
|
|
||||||
|
NotificationCenter.default.addObserver(self, selector: #selector(keyboardDidShow), name: UIResponder.keyboardDidShowNotification, object: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func keyboardDidShow() {
|
||||||
|
guard let textView,
|
||||||
|
textView.isFirstResponder else { return }
|
||||||
|
ensureCursorVisible(textView: textView)
|
||||||
}
|
}
|
||||||
|
|
||||||
func textViewDidChange(_ textView: UITextView) {
|
func textViewDidChange(_ textView: UITextView) {
|
||||||
|
|
|
@ -1,142 +0,0 @@
|
||||||
//
|
|
||||||
// DraftsTableViewController.swift
|
|
||||||
// Tusker
|
|
||||||
//
|
|
||||||
// Created by Shadowfacts on 10/22/18.
|
|
||||||
// Copyright © 2018 Shadowfacts. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
protocol DraftsTableViewControllerDelegate: AnyObject {
|
|
||||||
func draftSelectionCanceled()
|
|
||||||
func shouldSelectDraft(_ draft: Draft, completion: @escaping (Bool) -> Void)
|
|
||||||
func draftSelected(_ draft: Draft)
|
|
||||||
func draftSelectionCompleted()
|
|
||||||
}
|
|
||||||
|
|
||||||
class DraftsTableViewController: UITableViewController {
|
|
||||||
|
|
||||||
let account: LocalData.UserAccountInfo
|
|
||||||
let excludedDraft: Draft?
|
|
||||||
weak var delegate: DraftsTableViewControllerDelegate?
|
|
||||||
|
|
||||||
var drafts = [Draft]()
|
|
||||||
|
|
||||||
init(account: LocalData.UserAccountInfo, exclude: Draft? = nil) {
|
|
||||||
self.account = account
|
|
||||||
self.excludedDraft = exclude
|
|
||||||
|
|
||||||
super.init(nibName: "DraftsTableViewController", bundle: nil)
|
|
||||||
|
|
||||||
title = "Drafts"
|
|
||||||
navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancelPressed))
|
|
||||||
}
|
|
||||||
|
|
||||||
required init?(coder aDecoder: NSCoder) {
|
|
||||||
fatalError("init(coder:) has not been implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
override func viewDidLoad() {
|
|
||||||
super.viewDidLoad()
|
|
||||||
|
|
||||||
tableView.rowHeight = UITableView.automaticDimension
|
|
||||||
tableView.estimatedRowHeight = 140
|
|
||||||
|
|
||||||
tableView.register(UINib(nibName: "DraftTableViewCell", bundle: nil), forCellReuseIdentifier: "draftCell")
|
|
||||||
|
|
||||||
tableView.dragDelegate = self
|
|
||||||
|
|
||||||
drafts = DraftsManager.shared.sorted.filter { (draft) in
|
|
||||||
draft.accountID == account.id && draft != excludedDraft
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func draft(for indexPath: IndexPath) -> Draft {
|
|
||||||
return drafts[indexPath.row]
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Table View Data Source
|
|
||||||
|
|
||||||
override func numberOfSections(in tableView: UITableView) -> Int {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
|
||||||
return drafts.count
|
|
||||||
}
|
|
||||||
|
|
||||||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
|
||||||
guard let cell = tableView.dequeueReusableCell(withIdentifier: "draftCell", for: indexPath) as? DraftTableViewCell else { fatalError() }
|
|
||||||
|
|
||||||
cell.updateUI(for: draft(for: indexPath))
|
|
||||||
|
|
||||||
return cell
|
|
||||||
}
|
|
||||||
|
|
||||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
|
||||||
let draft = self.draft(for: indexPath)
|
|
||||||
func select() {
|
|
||||||
delegate?.draftSelected(draft)
|
|
||||||
dismiss(animated: true) {
|
|
||||||
self.delegate?.draftSelectionCompleted()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let delegate = delegate {
|
|
||||||
delegate.shouldSelectDraft(draft) { (shouldSelect) in
|
|
||||||
if shouldSelect {
|
|
||||||
select()
|
|
||||||
} else {
|
|
||||||
tableView.selectRow(at: nil, animated: true, scrollPosition: .none)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
select()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
|
|
||||||
return .delete
|
|
||||||
}
|
|
||||||
|
|
||||||
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
|
|
||||||
guard editingStyle == .delete else { return }
|
|
||||||
DraftsManager.shared.remove(draft(for: indexPath))
|
|
||||||
drafts.remove(at: indexPath.row)
|
|
||||||
tableView.deleteRows(at: [indexPath], with: .automatic)
|
|
||||||
}
|
|
||||||
|
|
||||||
override func tableView(_ tableView: UITableView, contextMenuConfigurationForRowAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? {
|
|
||||||
return UIContextMenuConfiguration(actionProvider: { _ in
|
|
||||||
return UIMenu(children: [
|
|
||||||
UIAction(title: "Delete Draft", image: UIImage(systemName: "trash"), attributes: .destructive, handler: { [unowned self] _ in
|
|
||||||
DraftsManager.shared.remove(self.draft(for: indexPath))
|
|
||||||
drafts.remove(at: indexPath.row)
|
|
||||||
tableView.deleteRows(at: [indexPath], with: .automatic)
|
|
||||||
})
|
|
||||||
])
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Interaction
|
|
||||||
|
|
||||||
@objc func cancelPressed() {
|
|
||||||
delegate?.draftSelectionCanceled()
|
|
||||||
dismiss(animated: true)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
extension DraftsTableViewController: UITableViewDragDelegate {
|
|
||||||
func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
|
|
||||||
let draft = self.draft(for: indexPath)
|
|
||||||
let activity = UserActivityManager.editDraftActivity(id: draft.id, accountID: account.id)
|
|
||||||
activity.displaysAuxiliaryScene = true
|
|
||||||
let provider = NSItemProvider(object: activity)
|
|
||||||
return [UIDragItem(itemProvider: provider)]
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14810.11" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
|
||||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
|
||||||
<dependencies>
|
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14766.13"/>
|
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
|
||||||
</dependencies>
|
|
||||||
<objects>
|
|
||||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="DraftsTableViewController" customModule="Tusker" customModuleProvider="target">
|
|
||||||
<connections>
|
|
||||||
<outlet property="view" destination="O5v-ea-iTS" id="sft-3K-LZf"/>
|
|
||||||
</connections>
|
|
||||||
</placeholder>
|
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
|
||||||
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="O5v-ea-iTS">
|
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
|
||||||
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
|
||||||
<point key="canvasLocation" x="-302" y="87"/>
|
|
||||||
</tableView>
|
|
||||||
</objects>
|
|
||||||
</document>
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
//
|
||||||
|
// AlertWithData.swift
|
||||||
|
// Tusker
|
||||||
|
//
|
||||||
|
// Created by Shadowfacts on 11/9/22.
|
||||||
|
// Copyright © 2022 Shadowfacts. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct AlertWithData<Data, A: View, M: View>: ViewModifier {
|
||||||
|
let title: LocalizedStringKey
|
||||||
|
@Binding var data: Data?
|
||||||
|
let actions: (Data) -> A
|
||||||
|
let message: (Data) -> M
|
||||||
|
|
||||||
|
private var isPresented: Binding<Bool> {
|
||||||
|
Binding(get: {
|
||||||
|
data != nil
|
||||||
|
}, set: { newValue in
|
||||||
|
guard !newValue else {
|
||||||
|
fatalError("Cannot set isPresented to true without data")
|
||||||
|
}
|
||||||
|
data = nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
init(title: LocalizedStringKey, data: Binding<Data?>, @ViewBuilder actions: @escaping (Data) -> A, @ViewBuilder message: @escaping (Data) -> M) {
|
||||||
|
self.title = title
|
||||||
|
self._data = data
|
||||||
|
self.actions = actions
|
||||||
|
self.message = message
|
||||||
|
}
|
||||||
|
|
||||||
|
func body(content: Content) -> some View {
|
||||||
|
content
|
||||||
|
.alert(title, isPresented: isPresented, presenting: data, actions: actions, message: message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension View {
|
||||||
|
func alertWithData<Data, A: View, M: View>(_ title: LocalizedStringKey, data: Binding<Data?>, @ViewBuilder actions: @escaping (Data) -> A, @ViewBuilder message: @escaping (Data) -> M) -> some View {
|
||||||
|
modifier(AlertWithData(title: title, data: data, actions: actions, message: message))
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,71 +0,0 @@
|
||||||
//
|
|
||||||
// DraftsTableViewCell.swift
|
|
||||||
// Tusker
|
|
||||||
//
|
|
||||||
// Created by Shadowfacts on 10/22/18.
|
|
||||||
// Copyright © 2018 Shadowfacts. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
import Photos
|
|
||||||
|
|
||||||
class DraftTableViewCell: UITableViewCell {
|
|
||||||
|
|
||||||
@IBOutlet weak var contentWarningLabel: UILabel!
|
|
||||||
@IBOutlet weak var contentLabel: UILabel!
|
|
||||||
@IBOutlet weak var lastModifiedLabel: UILabel!
|
|
||||||
@IBOutlet weak var attachmentsStackViewContainer: UIView!
|
|
||||||
@IBOutlet weak var attachmentsStackView: UIStackView!
|
|
||||||
|
|
||||||
override func awakeFromNib() {
|
|
||||||
super.awakeFromNib()
|
|
||||||
|
|
||||||
contentWarningLabel.font = UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 15, weight: .bold))
|
|
||||||
contentWarningLabel.adjustsFontForContentSizeCategory = true
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateUI(for draft: Draft) {
|
|
||||||
contentWarningLabel.text = draft.contentWarning
|
|
||||||
contentWarningLabel.isHidden = !draft.contentWarningEnabled
|
|
||||||
contentLabel.text = draft.text
|
|
||||||
lastModifiedLabel.text = draft.lastModified.timeAgoString()
|
|
||||||
|
|
||||||
attachmentsStackViewContainer.isHidden = draft.attachments.count == 0
|
|
||||||
|
|
||||||
for attachment in draft.attachments {
|
|
||||||
let size = CGSize(width: 50, height: 50)
|
|
||||||
let imageView = UIImageView(frame: CGRect(origin: .zero, size: size))
|
|
||||||
imageView.contentMode = .scaleAspectFill
|
|
||||||
imageView.layer.masksToBounds = true
|
|
||||||
imageView.layer.cornerRadius = 5
|
|
||||||
attachmentsStackView.addArrangedSubview(imageView)
|
|
||||||
imageView.widthAnchor.constraint(equalTo: imageView.heightAnchor).isActive = true
|
|
||||||
|
|
||||||
imageView.backgroundColor = .secondarySystemBackground
|
|
||||||
imageView.contentMode = .scaleAspectFill
|
|
||||||
|
|
||||||
switch attachment.data {
|
|
||||||
case let .asset(asset):
|
|
||||||
PHImageManager.default().requestImage(for: asset, targetSize: size, contentMode: .aspectFill, options: nil) { (image, _) in
|
|
||||||
imageView.image = image
|
|
||||||
}
|
|
||||||
case let .image(image):
|
|
||||||
imageView.image = image
|
|
||||||
case .video(_):
|
|
||||||
// videos aren't saved to drafts, so this is unreachable
|
|
||||||
return
|
|
||||||
case let .drawing(drawing):
|
|
||||||
imageView.image = drawing.imageInLightMode(from: drawing.bounds)
|
|
||||||
imageView.backgroundColor = .white
|
|
||||||
imageView.contentMode = .scaleAspectFit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override func prepareForReuse() {
|
|
||||||
super.prepareForReuse()
|
|
||||||
|
|
||||||
attachmentsStackView.arrangedSubviews.forEach { $0.removeFromSuperview() }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,98 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
|
||||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
|
||||||
<dependencies>
|
|
||||||
<deployment identifier="iOS"/>
|
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/>
|
|
||||||
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
|
||||||
</dependencies>
|
|
||||||
<objects>
|
|
||||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
|
||||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="143" id="Q7N-Mt-RPF" customClass="DraftTableViewCell" customModule="Tusker" customModuleProvider="target">
|
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="143"/>
|
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Q7N-Mt-RPF" id="KVi-jA-AET">
|
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="143"/>
|
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
|
||||||
<subviews>
|
|
||||||
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="gaD-3B-qO1">
|
|
||||||
<rect key="frame" x="16" y="11" width="351" height="124"/>
|
|
||||||
<subviews>
|
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Content Warning" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="VhS-ig-6Fu">
|
|
||||||
<rect key="frame" x="0.0" y="0.0" width="351" height="18"/>
|
|
||||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
|
|
||||||
<color key="textColor" systemColor="secondaryLabelColor"/>
|
|
||||||
<nil key="highlightedColor"/>
|
|
||||||
</label>
|
|
||||||
<view contentMode="scaleToFill" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="zMS-88-DcM">
|
|
||||||
<rect key="frame" x="0.0" y="26" width="351" height="40"/>
|
|
||||||
<subviews>
|
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" ambiguous="YES" text="Content" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="3" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="8eA-yd-rBp">
|
|
||||||
<rect key="frame" x="0.0" y="0.0" width="310.5" height="32"/>
|
|
||||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
|
||||||
<nil key="textColor"/>
|
|
||||||
<nil key="highlightedColor"/>
|
|
||||||
</label>
|
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" text="2m" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="D2X-9O-iQw">
|
|
||||||
<rect key="frame" x="326.5" y="0.0" width="24.5" height="20.5"/>
|
|
||||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
|
||||||
<color key="textColor" systemColor="secondaryLabelColor"/>
|
|
||||||
<nil key="highlightedColor"/>
|
|
||||||
</label>
|
|
||||||
</subviews>
|
|
||||||
<constraints>
|
|
||||||
<constraint firstItem="D2X-9O-iQw" firstAttribute="leading" secondItem="8eA-yd-rBp" secondAttribute="trailing" constant="16" id="6Ux-ee-J5h"/>
|
|
||||||
<constraint firstAttribute="trailing" secondItem="D2X-9O-iQw" secondAttribute="trailing" id="IRH-mM-HSs"/>
|
|
||||||
<constraint firstItem="8eA-yd-rBp" firstAttribute="leading" secondItem="zMS-88-DcM" secondAttribute="leading" id="StS-F9-9B3"/>
|
|
||||||
<constraint firstItem="8eA-yd-rBp" firstAttribute="top" secondItem="zMS-88-DcM" secondAttribute="top" id="Uuq-g5-n0A"/>
|
|
||||||
<constraint firstItem="D2X-9O-iQw" firstAttribute="top" secondItem="zMS-88-DcM" secondAttribute="top" id="lWB-6Z-nbG"/>
|
|
||||||
<constraint firstAttribute="bottom" secondItem="8eA-yd-rBp" secondAttribute="bottom" id="zCK-s5-4Zo"/>
|
|
||||||
</constraints>
|
|
||||||
</view>
|
|
||||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="csc-gx-KVg">
|
|
||||||
<rect key="frame" x="0.0" y="74" width="351" height="50"/>
|
|
||||||
<subviews>
|
|
||||||
<stackView opaque="NO" contentMode="scaleToFill" ambiguous="YES" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="htC-hf-vJ4">
|
|
||||||
<rect key="frame" x="0.0" y="0.0" width="352" height="50"/>
|
|
||||||
<constraints>
|
|
||||||
<constraint firstAttribute="height" constant="50" id="lxT-O2-afE"/>
|
|
||||||
</constraints>
|
|
||||||
</stackView>
|
|
||||||
</subviews>
|
|
||||||
<constraints>
|
|
||||||
<constraint firstItem="htC-hf-vJ4" firstAttribute="leading" secondItem="csc-gx-KVg" secondAttribute="leading" id="c0s-O9-XKa"/>
|
|
||||||
<constraint firstItem="htC-hf-vJ4" firstAttribute="top" secondItem="csc-gx-KVg" secondAttribute="top" id="lcl-RN-qHw"/>
|
|
||||||
<constraint firstAttribute="bottom" secondItem="htC-hf-vJ4" secondAttribute="bottom" id="oHX-Qh-bmI"/>
|
|
||||||
</constraints>
|
|
||||||
</view>
|
|
||||||
</subviews>
|
|
||||||
<constraints>
|
|
||||||
<constraint firstAttribute="trailing" secondItem="csc-gx-KVg" secondAttribute="trailing" id="AcZ-yc-8Zh"/>
|
|
||||||
</constraints>
|
|
||||||
</stackView>
|
|
||||||
</subviews>
|
|
||||||
<constraints>
|
|
||||||
<constraint firstAttribute="bottom" secondItem="gaD-3B-qO1" secondAttribute="bottomMargin" constant="8" id="4Hz-ax-JI6"/>
|
|
||||||
<constraint firstItem="gaD-3B-qO1" firstAttribute="leading" secondItem="KVi-jA-AET" secondAttribute="leadingMargin" id="KRA-Q8-klX"/>
|
|
||||||
<constraint firstAttribute="trailing" secondItem="gaD-3B-qO1" secondAttribute="trailingMargin" constant="8" id="iGc-c4-n9y"/>
|
|
||||||
<constraint firstItem="gaD-3B-qO1" firstAttribute="top" secondItem="KVi-jA-AET" secondAttribute="topMargin" id="rVE-Jo-6zG"/>
|
|
||||||
</constraints>
|
|
||||||
</tableViewCellContentView>
|
|
||||||
<connections>
|
|
||||||
<outlet property="attachmentsStackView" destination="htC-hf-vJ4" id="kEX-m7-LuE"/>
|
|
||||||
<outlet property="attachmentsStackViewContainer" destination="csc-gx-KVg" id="rIM-pj-TFX"/>
|
|
||||||
<outlet property="contentLabel" destination="8eA-yd-rBp" id="Uy0-8G-WbU"/>
|
|
||||||
<outlet property="contentWarningLabel" destination="VhS-ig-6Fu" id="jIU-vr-OsY"/>
|
|
||||||
<outlet property="lastModifiedLabel" destination="D2X-9O-iQw" id="dx7-0E-RuM"/>
|
|
||||||
</connections>
|
|
||||||
<point key="canvasLocation" x="-388" y="184.85757121439281"/>
|
|
||||||
</tableViewCell>
|
|
||||||
</objects>
|
|
||||||
<resources>
|
|
||||||
<systemColor name="secondaryLabelColor">
|
|
||||||
<color red="0.23529411764705882" green="0.23529411764705882" blue="0.2627450980392157" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/>
|
|
||||||
</systemColor>
|
|
||||||
</resources>
|
|
||||||
</document>
|
|
Loading…
Reference in New Issue