Make drafts persistent
This commit makes drafts persistent. It does so by: 1. Converting `DraftsArtifacts` into Nostr events 2. Wrapping those Nostr events into NIP-37 notes 3. Saving those NIP-37 notes into NostrDB 4. Loading those same notes at startup 5. Unwrapping NIP-37 notes into Nostr events 6. Parsing that into `DraftsArtifacts`, loaded into DamusState 7. PostView can then load these drafts Furthermore, a UX indicator was added to show when a draft has been saved. Limitations: 1. No encoding/decoding roundtrip guarantees. That would require extensive and heavy refactoring which is out of the scope of this commit. 2. We rely on `UserSettings` to keep track of note ids, while we do not have Ndb query capabilities 3. No NIP-37 relay sync support has been added yet, as that adds important privacy and sync conflict considerations which are out of the scope of this ticket, which is ensuring people don't lose their progress while writing notes. 4. The main use cases and scenarios have been tested. Because of (1), there may be some small inconsistencies on the stored version of the draft, but care was taken to keep the substantial portions of the content intact. Closes: https://github.com/damus-io/damus/issues/1862 Changelog-Added: Added local persistence of note drafts Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit is contained in:
@@ -1454,6 +1454,9 @@
|
||||
D74F430A2B23F0BE00425B75 /* DamusPurple.swift in Sources */ = {isa = PBXBuildFile; fileRef = D74F43092B23F0BE00425B75 /* DamusPurple.swift */; };
|
||||
D74F430C2B23FB9B00425B75 /* StoreObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = D74F430B2B23FB9B00425B75 /* StoreObserver.swift */; };
|
||||
D753CEAA2BE9DE04001C3A5D /* MutingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D753CEA92BE9DE04001C3A5D /* MutingTests.swift */; };
|
||||
D755B28D2D3E7D8800BBEEFA /* NIP37Draft.swift in Sources */ = {isa = PBXBuildFile; fileRef = D755B28C2D3E7D7D00BBEEFA /* NIP37Draft.swift */; };
|
||||
D755B28E2D3E7D8800BBEEFA /* NIP37Draft.swift in Sources */ = {isa = PBXBuildFile; fileRef = D755B28C2D3E7D7D00BBEEFA /* NIP37Draft.swift */; };
|
||||
D755B28F2D3E7D8800BBEEFA /* NIP37Draft.swift in Sources */ = {isa = PBXBuildFile; fileRef = D755B28C2D3E7D7D00BBEEFA /* NIP37Draft.swift */; };
|
||||
D76556D62B1E6C08001B0CCC /* DamusPurpleWelcomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D76556D52B1E6C08001B0CCC /* DamusPurpleWelcomeView.swift */; };
|
||||
D767066F2C8BB3CF00F09726 /* URLHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = D767066E2C8BB3CE00F09726 /* URLHandler.swift */; };
|
||||
D76874F32AE3632B00FB0F68 /* ProfileZapLinkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D76874F22AE3632B00FB0F68 /* ProfileZapLinkView.swift */; };
|
||||
@@ -1497,6 +1500,10 @@
|
||||
D7ADD3E22B538E3500F104C4 /* DamusPurpleVerifyNpubView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7ADD3E12B538E3500F104C4 /* DamusPurpleVerifyNpubView.swift */; };
|
||||
D7B76C902C825042003A16CB /* PushNotificationClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7D2A3802BF815D000E4B42B /* PushNotificationClient.swift */; };
|
||||
D7B76C912C82507F003A16CB /* NIP98AuthenticatedRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7C6787D2B2D34CC00BCEAFB /* NIP98AuthenticatedRequest.swift */; };
|
||||
D7BEE6F32D37AE1B00CF659F /* NostrSDK in Frameworks */ = {isa = PBXBuildFile; productRef = D7BEE6F22D37AE1B00CF659F /* NostrSDK */; };
|
||||
D7BEE6F52D37B20400CF659F /* NostrSDK in Frameworks */ = {isa = PBXBuildFile; productRef = D7BEE6F42D37B20400CF659F /* NostrSDK */; };
|
||||
D7BEE6F72D37B21400CF659F /* NostrSDK in Frameworks */ = {isa = PBXBuildFile; productRef = D7BEE6F62D37B21400CF659F /* NostrSDK */; };
|
||||
D7BEE6F92D37B37400CF659F /* DraftTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7BEE6F82D37B37400CF659F /* DraftTests.swift */; };
|
||||
D7C48C0B2D12DE0C00A3BACF /* SwiftyCrop in Frameworks */ = {isa = PBXBuildFile; productRef = D7C48C0A2D12DE0C00A3BACF /* SwiftyCrop */; };
|
||||
D7C48C0D2D12E34900A3BACF /* SwiftyCrop in Frameworks */ = {isa = PBXBuildFile; productRef = D7C48C0C2D12E34900A3BACF /* SwiftyCrop */; };
|
||||
D7C48C0F2D12E35600A3BACF /* SwiftyCrop in Frameworks */ = {isa = PBXBuildFile; productRef = D7C48C0E2D12E35600A3BACF /* SwiftyCrop */; };
|
||||
@@ -2436,6 +2443,7 @@
|
||||
D74F43092B23F0BE00425B75 /* DamusPurple.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DamusPurple.swift; sourceTree = "<group>"; };
|
||||
D74F430B2B23FB9B00425B75 /* StoreObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreObserver.swift; sourceTree = "<group>"; };
|
||||
D753CEA92BE9DE04001C3A5D /* MutingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MutingTests.swift; sourceTree = "<group>"; };
|
||||
D755B28C2D3E7D7D00BBEEFA /* NIP37Draft.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NIP37Draft.swift; sourceTree = "<group>"; };
|
||||
D76556D52B1E6C08001B0CCC /* DamusPurpleWelcomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DamusPurpleWelcomeView.swift; sourceTree = "<group>"; };
|
||||
D767066E2C8BB3CE00F09726 /* URLHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLHandler.swift; sourceTree = "<group>"; };
|
||||
D76874F22AE3632B00FB0F68 /* ProfileZapLinkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileZapLinkView.swift; sourceTree = "<group>"; };
|
||||
@@ -2459,6 +2467,7 @@
|
||||
D7ADD3DD2B53854300F104C4 /* DamusPurpleURL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DamusPurpleURL.swift; sourceTree = "<group>"; };
|
||||
D7ADD3DF2B538D4200F104C4 /* DamusPurpleURLSheetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DamusPurpleURLSheetView.swift; sourceTree = "<group>"; };
|
||||
D7ADD3E12B538E3500F104C4 /* DamusPurpleVerifyNpubView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DamusPurpleVerifyNpubView.swift; sourceTree = "<group>"; };
|
||||
D7BEE6F82D37B37400CF659F /* DraftTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DraftTests.swift; sourceTree = "<group>"; };
|
||||
D7C6787D2B2D34CC00BCEAFB /* NIP98AuthenticatedRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NIP98AuthenticatedRequest.swift; sourceTree = "<group>"; };
|
||||
D7CB5D3D2B116DAD00AD4105 /* NotificationsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsManager.swift; sourceTree = "<group>"; };
|
||||
D7CB5D442B116FE800AD4105 /* Contacts+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Contacts+.swift"; sourceTree = "<group>"; };
|
||||
@@ -2514,6 +2523,7 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D7BEE6F32D37AE1B00CF659F /* NostrSDK in Frameworks */,
|
||||
4C06670428FC7EC500038D2A /* Kingfisher in Frameworks */,
|
||||
3A0A30BB2C21397A00F8C9BC /* EmojiPicker in Frameworks */,
|
||||
D70D90982CDED61800CD0534 /* CodeScanner in Frameworks */,
|
||||
@@ -2544,6 +2554,7 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D7BEE6F52D37B20400CF659F /* NostrSDK in Frameworks */,
|
||||
82D6FC862CD9A4A600C925F4 /* MarkdownUI in Frameworks */,
|
||||
82D6FC8A2CD9A54600C925F4 /* SwipeActions in Frameworks */,
|
||||
D7F360292CEBBE34009D34DA /* CodeScanner in Frameworks */,
|
||||
@@ -2560,6 +2571,7 @@
|
||||
files = (
|
||||
D703D7AF2C670FB700A400EA /* MarkdownUI in Frameworks */,
|
||||
D73E5F9D2C6AA8E3007EB227 /* SwipeActions in Frameworks */,
|
||||
D7BEE6F72D37B21400CF659F /* NostrSDK in Frameworks */,
|
||||
D73E5F762C6A997E007EB227 /* EmojiPicker in Frameworks */,
|
||||
D703D7192C66E47100A400EA /* UniformTypeIdentifiers.framework in Frameworks */,
|
||||
D7C48C0F2D12E35600A3BACF /* SwiftyCrop in Frameworks */,
|
||||
@@ -3567,6 +3579,7 @@
|
||||
4CE6DEE527F7A08100C66700 /* damus */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D755B28B2D3E7D6500BBEEFA /* NIP37 */,
|
||||
4C45E5002BED4CE10025A428 /* NIP10 */,
|
||||
4C1D4FB32A7967990024F453 /* build-git-hash.txt */,
|
||||
4CA3529C2A76AE47003BB08B /* Notify */,
|
||||
@@ -3613,6 +3626,7 @@
|
||||
50A50A8C29A09E1C00C01BE7 /* RequestTests.swift */,
|
||||
4C90BD1B283AC38E008EE7EF /* Bech32Tests.swift */,
|
||||
E02B54172B4DFADA0077FF42 /* Bech32ObjectTests.swift */,
|
||||
D7BEE6F82D37B37400CF659F /* DraftTests.swift */,
|
||||
4C363A9F2828A8DD006E126D /* LikeTests.swift */,
|
||||
4C363A9D2828A822006E126D /* ReplyTests.swift */,
|
||||
4CE6DEF727F7A08200C66700 /* damusTests.swift */,
|
||||
@@ -3884,6 +3898,14 @@
|
||||
path = Purple;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D755B28B2D3E7D6500BBEEFA /* NIP37 */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D755B28C2D3E7D7D00BBEEFA /* NIP37Draft.swift */,
|
||||
);
|
||||
path = NIP37;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D78DB85D2C20FE9E00F0AB12 /* Chat */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -3990,6 +4012,7 @@
|
||||
D78DB8582C1CE9CA00F0AB12 /* SwipeActions */,
|
||||
D70D90972CDED61800CD0534 /* CodeScanner */,
|
||||
D7C48C0A2D12DE0C00A3BACF /* SwiftyCrop */,
|
||||
D7BEE6F22D37AE1B00CF659F /* NostrSDK */,
|
||||
);
|
||||
productName = damus;
|
||||
productReference = 4CE6DEE327F7A08100C66700 /* damus.app */;
|
||||
@@ -4056,6 +4079,7 @@
|
||||
82D6FC892CD9A54600C925F4 /* SwipeActions */,
|
||||
D7F360282CEBBE34009D34DA /* CodeScanner */,
|
||||
D7C48C0C2D12E34900A3BACF /* SwiftyCrop */,
|
||||
D7BEE6F42D37B20400CF659F /* NostrSDK */,
|
||||
);
|
||||
productName = "share extension";
|
||||
productReference = 82D6FA972CD9820500C925F4 /* ShareExtension.appex */;
|
||||
@@ -4084,6 +4108,7 @@
|
||||
D73E5F9C2C6AA8E3007EB227 /* SwipeActions */,
|
||||
D70D909B2CDED7B200CD0534 /* CodeScanner */,
|
||||
D7C48C0E2D12E35600A3BACF /* SwiftyCrop */,
|
||||
D7BEE6F62D37B21400CF659F /* NostrSDK */,
|
||||
);
|
||||
productName = "highlighter action extension";
|
||||
productReference = D703D7172C66E47100A400EA /* HighlighterActionExtension.appex */;
|
||||
@@ -4193,6 +4218,7 @@
|
||||
D78DB8572C1CE9CA00F0AB12 /* XCRemoteSwiftPackageReference "SwipeActions" */,
|
||||
D70D90962CDED61800CD0534 /* XCRemoteSwiftPackageReference "CodeScanner" */,
|
||||
D7C48C092D12DE0C00A3BACF /* XCRemoteSwiftPackageReference "SwiftyCrop" */,
|
||||
D7BEE6F12D37AE1B00CF659F /* XCRemoteSwiftPackageReference "nostr-sdk-swift" */,
|
||||
);
|
||||
productRefGroup = 4CE6DEE427F7A08100C66700 /* Products */;
|
||||
projectDirPath = "";
|
||||
@@ -4566,6 +4592,7 @@
|
||||
4C363A8828236948006E126D /* BlocksView.swift in Sources */,
|
||||
4C06670628FCB08600038D2A /* ImageCarousel.swift in Sources */,
|
||||
3A23838E2A297DD200E5AA2E /* ZapButtonModel.swift in Sources */,
|
||||
D755B28D2D3E7D8800BBEEFA /* NIP37Draft.swift in Sources */,
|
||||
F71694F82A6983AF001F4053 /* GrayGradient.swift in Sources */,
|
||||
4C1D4FB12A7958E60024F453 /* VersionInfo.swift in Sources */,
|
||||
D7FF94002AC7AC5300FD969D /* RelayURL.swift in Sources */,
|
||||
@@ -4817,6 +4844,7 @@
|
||||
75AD872B2AA23A460085EF2C /* Block+Tests.swift in Sources */,
|
||||
E0E024112B7C19C20075735D /* TranslationTests.swift in Sources */,
|
||||
F944F56E29EA9CCC0067B3BF /* DamusParseContentTests.swift in Sources */,
|
||||
D7BEE6F92D37B37400CF659F /* DraftTests.swift in Sources */,
|
||||
B501062D2B363036003874F5 /* AuthIntegrationTests.swift in Sources */,
|
||||
4CB883AE2976FA9300DC99E7 /* FormatTests.swift in Sources */,
|
||||
D72A2D052AD9C1B5002AFF62 /* MockDamusState.swift in Sources */,
|
||||
@@ -5098,6 +5126,7 @@
|
||||
82D6FB9E2CD99F7900C925F4 /* ContentFilters.swift in Sources */,
|
||||
82D6FB9F2CD99F7900C925F4 /* DamusCacheManager.swift in Sources */,
|
||||
82D6FBA02CD99F7900C925F4 /* NotificationsManager.swift in Sources */,
|
||||
D755B28E2D3E7D8800BBEEFA /* NIP37Draft.swift in Sources */,
|
||||
82D6FBA12CD99F7900C925F4 /* Contacts+.swift in Sources */,
|
||||
82D6FBA22CD99F7900C925F4 /* ZapType.swift in Sources */,
|
||||
82D6FBA32CD99F7900C925F4 /* NewEventsBits.swift in Sources */,
|
||||
@@ -5788,6 +5817,7 @@
|
||||
D703D7472C67092700A400EA /* UserSettingsStore.swift in Sources */,
|
||||
D703D7852C670C6100A400EA /* Notify.swift in Sources */,
|
||||
D703D7532C670A2600A400EA /* Wallet.swift in Sources */,
|
||||
D755B28F2D3E7D8800BBEEFA /* NIP37Draft.swift in Sources */,
|
||||
D703D75F2C670AA200A400EA /* NostrEvent.swift in Sources */,
|
||||
D703D7442C67086800A400EA /* HeadlessDamusState.swift in Sources */,
|
||||
D703D7922C670D2900A400EA /* RelayURL.swift in Sources */,
|
||||
@@ -6747,6 +6777,14 @@
|
||||
minimumVersion = 1.14.1;
|
||||
};
|
||||
};
|
||||
D7BEE6F12D37AE1B00CF659F /* XCRemoteSwiftPackageReference "nostr-sdk-swift" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/rust-nostr/nostr-sdk-swift";
|
||||
requirement = {
|
||||
kind = revision;
|
||||
revision = 999316a0962d49ad8b7b98d214b9ee6eea694149;
|
||||
};
|
||||
};
|
||||
D7C48C092D12DE0C00A3BACF /* XCRemoteSwiftPackageReference "SwiftyCrop" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/benedom/SwiftyCrop";
|
||||
@@ -6868,6 +6906,21 @@
|
||||
package = D7A343EC2AD0D77C00CED48B /* XCRemoteSwiftPackageReference "swift-snapshot-testing" */;
|
||||
productName = SnapshotTesting;
|
||||
};
|
||||
D7BEE6F22D37AE1B00CF659F /* NostrSDK */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = D7BEE6F12D37AE1B00CF659F /* XCRemoteSwiftPackageReference "nostr-sdk-swift" */;
|
||||
productName = NostrSDK;
|
||||
};
|
||||
D7BEE6F42D37B20400CF659F /* NostrSDK */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = D7BEE6F12D37AE1B00CF659F /* XCRemoteSwiftPackageReference "nostr-sdk-swift" */;
|
||||
productName = NostrSDK;
|
||||
};
|
||||
D7BEE6F62D37B21400CF659F /* NostrSDK */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = D7BEE6F12D37AE1B00CF659F /* XCRemoteSwiftPackageReference "nostr-sdk-swift" */;
|
||||
productName = NostrSDK;
|
||||
};
|
||||
D7C48C0A2D12DE0C00A3BACF /* SwiftyCrop */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = D7C48C092D12DE0C00A3BACF /* XCRemoteSwiftPackageReference "SwiftyCrop" */;
|
||||
|
||||
Reference in New Issue
Block a user