mirror of
git://jb55.com/damus
synced 2024-09-30 00:40:45 +00:00
Compare commits
45 Commits
c6d9e0b3c9
...
23138c5e03
Author | SHA1 | Date | |
---|---|---|---|
|
23138c5e03 | ||
|
213a622dde | ||
|
4ac3da7612 | ||
|
bb1f912f78 | ||
|
a190a5e8fb | ||
|
514a053dce | ||
|
0b199a18b4 | ||
|
23a125ea0f | ||
|
f406d27507 | ||
|
ceb6eb03fb | ||
|
b917b4e9d6 | ||
|
e981ae247e | ||
|
dcd7b5b111 | ||
|
a721256e9b | ||
|
007bcc8687 | ||
|
ccb94e6d69 | ||
|
3c9fd36654 | ||
|
9a9b5d5f4f | ||
|
d4f041aead | ||
|
8133da82c1 | ||
|
fc8f211da2 | ||
|
cea4922442 | ||
|
669a313f92 | ||
|
ac7d6c65c7 | ||
|
c15f0454de | ||
|
6bddee0354 | ||
|
43fc662bf6 | ||
|
d2b7878d03 | ||
|
97169f4fa2 | ||
|
862101a3f7 | ||
|
a9a2a52881 | ||
|
c8aba00f85 | ||
|
bb321b6e8a | ||
|
4544d1548c | ||
|
e1b787c7ed | ||
|
108456fb59 | ||
|
0982bfbb56 | ||
|
a9e563663a | ||
|
986cc715fa | ||
|
ea4c2a1d1c | ||
|
3c77d58b11 | ||
|
3cea556827 | ||
|
c5bdb22a86 | ||
|
3142fd5700 | ||
|
0a6e40798a |
@ -28,7 +28,7 @@ struct NotificationExtensionState: HeadlessDamusState {
|
|||||||
self.settings = UserSettingsStore()
|
self.settings = UserSettingsStore()
|
||||||
|
|
||||||
self.contacts = Contacts(our_pubkey: keypair.pubkey)
|
self.contacts = Contacts(our_pubkey: keypair.pubkey)
|
||||||
self.mutelist_manager = MutelistManager()
|
self.mutelist_manager = MutelistManager(user_keypair: keypair)
|
||||||
self.keypair = keypair
|
self.keypair = keypair
|
||||||
self.profiles = Profiles(ndb: ndb)
|
self.profiles = Profiles(ndb: ndb)
|
||||||
self.zaps = Zaps(our_pubkey: keypair.pubkey)
|
self.zaps = Zaps(our_pubkey: keypair.pubkey)
|
||||||
|
27
DamusNotificationService/PrivacyInfo.xcprivacy
Normal file
27
DamusNotificationService/PrivacyInfo.xcprivacy
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>NSPrivacyCollectedDataTypes</key>
|
||||||
|
<array/>
|
||||||
|
<key>NSPrivacyAccessedAPITypes</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>NSPrivacyAccessedAPIType</key>
|
||||||
|
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
|
||||||
|
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||||
|
<array>
|
||||||
|
<string>1C8F.1</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>NSPrivacyAccessedAPIType</key>
|
||||||
|
<string>File Timestamp</string>
|
||||||
|
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||||
|
<array>
|
||||||
|
<string>C617.1</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
27
PrivacyInfo.xcprivacy
Normal file
27
PrivacyInfo.xcprivacy
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>NSPrivacyCollectedDataTypes</key>
|
||||||
|
<array/>
|
||||||
|
<key>NSPrivacyAccessedAPITypes</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>NSPrivacyAccessedAPIType</key>
|
||||||
|
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
|
||||||
|
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||||
|
<array>
|
||||||
|
<string>1C8F.1</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>NSPrivacyAccessedAPIType</key>
|
||||||
|
<string>File Timestamp</string>
|
||||||
|
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||||
|
<array>
|
||||||
|
<string>C617.1</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
@ -98,6 +98,7 @@
|
|||||||
4C2B10282A7B0F5C008AA43E /* Log.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C2B10272A7B0F5C008AA43E /* Log.swift */; };
|
4C2B10282A7B0F5C008AA43E /* Log.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C2B10272A7B0F5C008AA43E /* Log.swift */; };
|
||||||
4C2B7BF22A71B6540049DEE7 /* Id.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C2B7BF12A71B6540049DEE7 /* Id.swift */; };
|
4C2B7BF22A71B6540049DEE7 /* Id.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C2B7BF12A71B6540049DEE7 /* Id.swift */; };
|
||||||
4C2CDDF7299D4A5E00879FD5 /* Debouncer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C2CDDF6299D4A5E00879FD5 /* Debouncer.swift */; };
|
4C2CDDF7299D4A5E00879FD5 /* Debouncer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C2CDDF6299D4A5E00879FD5 /* Debouncer.swift */; };
|
||||||
|
4C2D34412BDAF1B300F9FB44 /* NIP10Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C2D34402BDAF1B300F9FB44 /* NIP10Tests.swift */; };
|
||||||
4C30AC7229A5677A00E2BD5A /* NotificationsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C30AC7129A5677A00E2BD5A /* NotificationsView.swift */; };
|
4C30AC7229A5677A00E2BD5A /* NotificationsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C30AC7129A5677A00E2BD5A /* NotificationsView.swift */; };
|
||||||
4C30AC7429A5680900E2BD5A /* EventGroupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C30AC7329A5680900E2BD5A /* EventGroupView.swift */; };
|
4C30AC7429A5680900E2BD5A /* EventGroupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C30AC7329A5680900E2BD5A /* EventGroupView.swift */; };
|
||||||
4C30AC7629A5770900E2BD5A /* NotificationItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C30AC7529A5770900E2BD5A /* NotificationItemView.swift */; };
|
4C30AC7629A5770900E2BD5A /* NotificationItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C30AC7529A5770900E2BD5A /* NotificationItemView.swift */; };
|
||||||
@ -174,6 +175,7 @@
|
|||||||
4C3EA67D28FFBBA300C48A62 /* InvoicesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3EA67C28FFBBA200C48A62 /* InvoicesView.swift */; };
|
4C3EA67D28FFBBA300C48A62 /* InvoicesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3EA67C28FFBBA200C48A62 /* InvoicesView.swift */; };
|
||||||
4C3EA67F28FFC01D00C48A62 /* InvoiceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3EA67E28FFC01D00C48A62 /* InvoiceView.swift */; };
|
4C3EA67F28FFC01D00C48A62 /* InvoiceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3EA67E28FFC01D00C48A62 /* InvoiceView.swift */; };
|
||||||
4C42812C298C848200DBF26F /* TranslateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C42812B298C848200DBF26F /* TranslateView.swift */; };
|
4C42812C298C848200DBF26F /* TranslateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C42812B298C848200DBF26F /* TranslateView.swift */; };
|
||||||
|
4C45E5022BED4D000025A428 /* ThreadReply.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C45E5012BED4D000025A428 /* ThreadReply.swift */; };
|
||||||
4C463CBF2B960B96008A8C36 /* PurpleBackdrop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C463CBE2B960B96008A8C36 /* PurpleBackdrop.swift */; };
|
4C463CBF2B960B96008A8C36 /* PurpleBackdrop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C463CBE2B960B96008A8C36 /* PurpleBackdrop.swift */; };
|
||||||
4C4793012A993CDA00489948 /* mdb.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C4793002A993B9A00489948 /* mdb.c */; settings = {COMPILER_FLAGS = "-w"; }; };
|
4C4793012A993CDA00489948 /* mdb.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C4793002A993B9A00489948 /* mdb.c */; settings = {COMPILER_FLAGS = "-w"; }; };
|
||||||
4C4793042A993DC000489948 /* midl.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C4793032A993DB900489948 /* midl.c */; settings = {COMPILER_FLAGS = "-w"; }; };
|
4C4793042A993DC000489948 /* midl.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C4793032A993DB900489948 /* midl.c */; settings = {COMPILER_FLAGS = "-w"; }; };
|
||||||
@ -247,6 +249,7 @@
|
|||||||
4C8D1A6C29F1DFC200ACDF75 /* FriendIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C8D1A6B29F1DFC200ACDF75 /* FriendIcon.swift */; };
|
4C8D1A6C29F1DFC200ACDF75 /* FriendIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C8D1A6B29F1DFC200ACDF75 /* FriendIcon.swift */; };
|
||||||
4C8D1A6F29F31E5000ACDF75 /* FriendsButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C8D1A6E29F31E5000ACDF75 /* FriendsButton.swift */; };
|
4C8D1A6F29F31E5000ACDF75 /* FriendsButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C8D1A6E29F31E5000ACDF75 /* FriendsButton.swift */; };
|
||||||
4C8EC52529D1FA6C0085D9A8 /* DamusColors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C8EC52429D1FA6C0085D9A8 /* DamusColors.swift */; };
|
4C8EC52529D1FA6C0085D9A8 /* DamusColors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C8EC52429D1FA6C0085D9A8 /* DamusColors.swift */; };
|
||||||
|
4C8FA7242BED58A900798A6A /* ThreadReply.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C45E5012BED4D000025A428 /* ThreadReply.swift */; };
|
||||||
4C9054852A6AEAA000811EEC /* NdbTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C9054842A6AEAA000811EEC /* NdbTests.swift */; };
|
4C9054852A6AEAA000811EEC /* NdbTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C9054842A6AEAA000811EEC /* NdbTests.swift */; };
|
||||||
4C90BD18283A9EE5008EE7EF /* LoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C90BD17283A9EE5008EE7EF /* LoginView.swift */; };
|
4C90BD18283A9EE5008EE7EF /* LoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C90BD17283A9EE5008EE7EF /* LoginView.swift */; };
|
||||||
4C90BD1A283AA67F008EE7EF /* Bech32.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C90BD19283AA67F008EE7EF /* Bech32.swift */; };
|
4C90BD1A283AA67F008EE7EF /* Bech32.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C90BD19283AA67F008EE7EF /* Bech32.swift */; };
|
||||||
@ -484,6 +487,7 @@
|
|||||||
D74AAFD62B155F0C006CF0F4 /* WalletConnect+.swift in Sources */ = {isa = PBXBuildFile; fileRef = D74AAFD52B155F0C006CF0F4 /* WalletConnect+.swift */; };
|
D74AAFD62B155F0C006CF0F4 /* WalletConnect+.swift in Sources */ = {isa = PBXBuildFile; fileRef = D74AAFD52B155F0C006CF0F4 /* WalletConnect+.swift */; };
|
||||||
D74F430A2B23F0BE00425B75 /* DamusPurple.swift in Sources */ = {isa = PBXBuildFile; fileRef = D74F43092B23F0BE00425B75 /* DamusPurple.swift */; };
|
D74F430A2B23F0BE00425B75 /* DamusPurple.swift in Sources */ = {isa = PBXBuildFile; fileRef = D74F43092B23F0BE00425B75 /* DamusPurple.swift */; };
|
||||||
D74F430C2B23FB9B00425B75 /* StoreObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = D74F430B2B23FB9B00425B75 /* StoreObserver.swift */; };
|
D74F430C2B23FB9B00425B75 /* StoreObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = D74F430B2B23FB9B00425B75 /* StoreObserver.swift */; };
|
||||||
|
D753CEAA2BE9DE04001C3A5D /* MutingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D753CEA92BE9DE04001C3A5D /* MutingTests.swift */; };
|
||||||
D76556D62B1E6C08001B0CCC /* DamusPurpleWelcomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D76556D52B1E6C08001B0CCC /* DamusPurpleWelcomeView.swift */; };
|
D76556D62B1E6C08001B0CCC /* DamusPurpleWelcomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D76556D52B1E6C08001B0CCC /* DamusPurpleWelcomeView.swift */; };
|
||||||
D76874F32AE3632B00FB0F68 /* ProfileZapLinkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D76874F22AE3632B00FB0F68 /* ProfileZapLinkView.swift */; };
|
D76874F32AE3632B00FB0F68 /* ProfileZapLinkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D76874F22AE3632B00FB0F68 /* ProfileZapLinkView.swift */; };
|
||||||
D77BFA0B2AE3051200621634 /* ProfileActionSheetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D77BFA0A2AE3051200621634 /* ProfileActionSheetView.swift */; };
|
D77BFA0B2AE3051200621634 /* ProfileActionSheetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D77BFA0A2AE3051200621634 /* ProfileActionSheetView.swift */; };
|
||||||
@ -636,6 +640,8 @@
|
|||||||
D7EDED332B12ACAE0018B19C /* DamusUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7EDED322B12ACAE0018B19C /* DamusUserDefaults.swift */; };
|
D7EDED332B12ACAE0018B19C /* DamusUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7EDED322B12ACAE0018B19C /* DamusUserDefaults.swift */; };
|
||||||
D7EDED342B12ACAE0018B19C /* DamusUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7EDED322B12ACAE0018B19C /* DamusUserDefaults.swift */; };
|
D7EDED342B12ACAE0018B19C /* DamusUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7EDED322B12ACAE0018B19C /* DamusUserDefaults.swift */; };
|
||||||
D7FB10A72B0C371A00FA8D42 /* Log.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C2B10272A7B0F5C008AA43E /* Log.swift */; };
|
D7FB10A72B0C371A00FA8D42 /* Log.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C2B10272A7B0F5C008AA43E /* Log.swift */; };
|
||||||
|
D7FB14222BE5970000398331 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = D7FB14212BE5970000398331 /* PrivacyInfo.xcprivacy */; };
|
||||||
|
D7FB14252BE5A9A800398331 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = D7FB14242BE5A9A800398331 /* PrivacyInfo.xcprivacy */; };
|
||||||
D7FD12262BD345A700CF195B /* FirstAidSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7FD12252BD345A700CF195B /* FirstAidSettingsView.swift */; };
|
D7FD12262BD345A700CF195B /* FirstAidSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7FD12252BD345A700CF195B /* FirstAidSettingsView.swift */; };
|
||||||
D7FF94002AC7AC5300FD969D /* RelayURL.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7FF93FF2AC7AC5200FD969D /* RelayURL.swift */; };
|
D7FF94002AC7AC5300FD969D /* RelayURL.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7FF93FF2AC7AC5200FD969D /* RelayURL.swift */; };
|
||||||
E02429952B7E97740088B16C /* CameraController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E02429942B7E97740088B16C /* CameraController.swift */; };
|
E02429952B7E97740088B16C /* CameraController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E02429942B7E97740088B16C /* CameraController.swift */; };
|
||||||
@ -772,6 +778,9 @@
|
|||||||
3A96D41A298DA94500388A2A /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
3A96D41A298DA94500388A2A /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||||
3A96D41B298DA94500388A2A /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = "<group>"; };
|
3A96D41B298DA94500388A2A /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
3A96D41C298DA94500388A2A /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = nl; path = nl.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
3A96D41C298DA94500388A2A /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = nl; path = nl.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||||
|
3A994C4C2BE5B9370019F632 /* th */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = th; path = th.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||||
|
3A994C4D2BE5B9370019F632 /* th */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = th; path = th.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||||
|
3A994C4E2BE5B9370019F632 /* th */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = th; path = th.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
3AA247FE297E3D900090C62D /* RepostsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RepostsView.swift; sourceTree = "<group>"; };
|
3AA247FE297E3D900090C62D /* RepostsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RepostsView.swift; sourceTree = "<group>"; };
|
||||||
3AA24801297E3DC20090C62D /* RepostView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RepostView.swift; sourceTree = "<group>"; };
|
3AA24801297E3DC20090C62D /* RepostView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RepostView.swift; sourceTree = "<group>"; };
|
||||||
3AA59D1C2999B0400061C48E /* DraftsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DraftsModel.swift; sourceTree = "<group>"; };
|
3AA59D1C2999B0400061C48E /* DraftsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DraftsModel.swift; sourceTree = "<group>"; };
|
||||||
@ -883,6 +892,7 @@
|
|||||||
4C2B10272A7B0F5C008AA43E /* Log.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Log.swift; sourceTree = "<group>"; };
|
4C2B10272A7B0F5C008AA43E /* Log.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Log.swift; sourceTree = "<group>"; };
|
||||||
4C2B7BF12A71B6540049DEE7 /* Id.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Id.swift; sourceTree = "<group>"; };
|
4C2B7BF12A71B6540049DEE7 /* Id.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Id.swift; sourceTree = "<group>"; };
|
||||||
4C2CDDF6299D4A5E00879FD5 /* Debouncer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Debouncer.swift; sourceTree = "<group>"; };
|
4C2CDDF6299D4A5E00879FD5 /* Debouncer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Debouncer.swift; sourceTree = "<group>"; };
|
||||||
|
4C2D34402BDAF1B300F9FB44 /* NIP10Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NIP10Tests.swift; sourceTree = "<group>"; };
|
||||||
4C30AC7129A5677A00E2BD5A /* NotificationsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsView.swift; sourceTree = "<group>"; };
|
4C30AC7129A5677A00E2BD5A /* NotificationsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsView.swift; sourceTree = "<group>"; };
|
||||||
4C30AC7329A5680900E2BD5A /* EventGroupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventGroupView.swift; sourceTree = "<group>"; };
|
4C30AC7329A5680900E2BD5A /* EventGroupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventGroupView.swift; sourceTree = "<group>"; };
|
||||||
4C30AC7529A5770900E2BD5A /* NotificationItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationItemView.swift; sourceTree = "<group>"; };
|
4C30AC7529A5770900E2BD5A /* NotificationItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationItemView.swift; sourceTree = "<group>"; };
|
||||||
@ -986,6 +996,7 @@
|
|||||||
4C3EA67C28FFBBA200C48A62 /* InvoicesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvoicesView.swift; sourceTree = "<group>"; };
|
4C3EA67C28FFBBA200C48A62 /* InvoicesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvoicesView.swift; sourceTree = "<group>"; };
|
||||||
4C3EA67E28FFC01D00C48A62 /* InvoiceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvoiceView.swift; sourceTree = "<group>"; };
|
4C3EA67E28FFC01D00C48A62 /* InvoiceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvoiceView.swift; sourceTree = "<group>"; };
|
||||||
4C42812B298C848200DBF26F /* TranslateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranslateView.swift; sourceTree = "<group>"; };
|
4C42812B298C848200DBF26F /* TranslateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranslateView.swift; sourceTree = "<group>"; };
|
||||||
|
4C45E5012BED4D000025A428 /* ThreadReply.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadReply.swift; sourceTree = "<group>"; };
|
||||||
4C463CBE2B960B96008A8C36 /* PurpleBackdrop.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PurpleBackdrop.swift; sourceTree = "<group>"; };
|
4C463CBE2B960B96008A8C36 /* PurpleBackdrop.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PurpleBackdrop.swift; sourceTree = "<group>"; };
|
||||||
4C478E242A9932C100489948 /* Ndb.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Ndb.swift; sourceTree = "<group>"; };
|
4C478E242A9932C100489948 /* Ndb.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Ndb.swift; sourceTree = "<group>"; };
|
||||||
4C478E262A99353500489948 /* threadpool.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = threadpool.h; sourceTree = "<group>"; };
|
4C478E262A99353500489948 /* threadpool.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = threadpool.h; sourceTree = "<group>"; };
|
||||||
@ -1396,6 +1407,7 @@
|
|||||||
D74AAFD52B155F0C006CF0F4 /* WalletConnect+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WalletConnect+.swift"; sourceTree = "<group>"; };
|
D74AAFD52B155F0C006CF0F4 /* WalletConnect+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WalletConnect+.swift"; sourceTree = "<group>"; };
|
||||||
D74F43092B23F0BE00425B75 /* DamusPurple.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DamusPurple.swift; sourceTree = "<group>"; };
|
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>"; };
|
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>"; };
|
||||||
D76556D52B1E6C08001B0CCC /* DamusPurpleWelcomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DamusPurpleWelcomeView.swift; sourceTree = "<group>"; };
|
D76556D52B1E6C08001B0CCC /* DamusPurpleWelcomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DamusPurpleWelcomeView.swift; sourceTree = "<group>"; };
|
||||||
D76874F22AE3632B00FB0F68 /* ProfileZapLinkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileZapLinkView.swift; sourceTree = "<group>"; };
|
D76874F22AE3632B00FB0F68 /* ProfileZapLinkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileZapLinkView.swift; sourceTree = "<group>"; };
|
||||||
D77BFA0A2AE3051200621634 /* ProfileActionSheetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileActionSheetView.swift; sourceTree = "<group>"; };
|
D77BFA0A2AE3051200621634 /* ProfileActionSheetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileActionSheetView.swift; sourceTree = "<group>"; };
|
||||||
@ -1430,6 +1442,8 @@
|
|||||||
D7EDED202B117DCA0018B19C /* SequenceUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SequenceUtils.swift; sourceTree = "<group>"; };
|
D7EDED202B117DCA0018B19C /* SequenceUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SequenceUtils.swift; sourceTree = "<group>"; };
|
||||||
D7EDED2D2B128E8A0018B19C /* CollectionExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionExtension.swift; sourceTree = "<group>"; };
|
D7EDED2D2B128E8A0018B19C /* CollectionExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionExtension.swift; sourceTree = "<group>"; };
|
||||||
D7EDED322B12ACAE0018B19C /* DamusUserDefaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DamusUserDefaults.swift; sourceTree = "<group>"; };
|
D7EDED322B12ACAE0018B19C /* DamusUserDefaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DamusUserDefaults.swift; sourceTree = "<group>"; };
|
||||||
|
D7FB14212BE5970000398331 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
||||||
|
D7FB14242BE5A9A800398331 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
||||||
D7FD12252BD345A700CF195B /* FirstAidSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirstAidSettingsView.swift; sourceTree = "<group>"; };
|
D7FD12252BD345A700CF195B /* FirstAidSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirstAidSettingsView.swift; sourceTree = "<group>"; };
|
||||||
D7FF93FF2AC7AC5200FD969D /* RelayURL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayURL.swift; sourceTree = "<group>"; };
|
D7FF93FF2AC7AC5200FD969D /* RelayURL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayURL.swift; sourceTree = "<group>"; };
|
||||||
E02429942B7E97740088B16C /* CameraController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CameraController.swift; sourceTree = "<group>"; };
|
E02429942B7E97740088B16C /* CameraController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CameraController.swift; sourceTree = "<group>"; };
|
||||||
@ -1604,7 +1618,6 @@
|
|||||||
4C363A93282704FA006E126D /* Post.swift */,
|
4C363A93282704FA006E126D /* Post.swift */,
|
||||||
4C363A952827096D006E126D /* PostBlock.swift */,
|
4C363A952827096D006E126D /* PostBlock.swift */,
|
||||||
4C363A9928283854006E126D /* Reply.swift */,
|
4C363A9928283854006E126D /* Reply.swift */,
|
||||||
4C363A9B282838B9006E126D /* EventRef.swift */,
|
|
||||||
4C363AA328296DEE006E126D /* SearchModel.swift */,
|
4C363AA328296DEE006E126D /* SearchModel.swift */,
|
||||||
0E8A4BB62AE4359200065E81 /* NostrFilter+Hashable.swift */,
|
0E8A4BB62AE4359200065E81 /* NostrFilter+Hashable.swift */,
|
||||||
4C3AC79A28306D7B00E1F516 /* Contacts.swift */,
|
4C3AC79A28306D7B00E1F516 /* Contacts.swift */,
|
||||||
@ -1777,6 +1790,15 @@
|
|||||||
path = flatbuffers;
|
path = flatbuffers;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
4C45E5002BED4CE10025A428 /* NIP10 */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
4C363A9B282838B9006E126D /* EventRef.swift */,
|
||||||
|
4C45E5012BED4D000025A428 /* ThreadReply.swift */,
|
||||||
|
);
|
||||||
|
path = NIP10;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
4C478E2A2A9935D300489948 /* bindings */ = {
|
4C478E2A2A9935D300489948 /* bindings */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@ -2444,6 +2466,7 @@
|
|||||||
4CE6DEDA27F7A08100C66700 = {
|
4CE6DEDA27F7A08100C66700 = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
D7FB14212BE5970000398331 /* PrivacyInfo.xcprivacy */,
|
||||||
4C32B9362A9AD44700DC3548 /* flatbuffers */,
|
4C32B9362A9AD44700DC3548 /* flatbuffers */,
|
||||||
4C9054862A6AEB4500811EEC /* nostrdb */,
|
4C9054862A6AEB4500811EEC /* nostrdb */,
|
||||||
4C19AE4A2A5CEF7C00C90DB7 /* nostrscript */,
|
4C19AE4A2A5CEF7C00C90DB7 /* nostrscript */,
|
||||||
@ -2474,6 +2497,7 @@
|
|||||||
4CE6DEE527F7A08100C66700 /* damus */ = {
|
4CE6DEE527F7A08100C66700 /* damus */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
4C45E5002BED4CE10025A428 /* NIP10 */,
|
||||||
4C1D4FB32A7967990024F453 /* build-git-hash.txt */,
|
4C1D4FB32A7967990024F453 /* build-git-hash.txt */,
|
||||||
4CA3529C2A76AE47003BB08B /* Notify */,
|
4CA3529C2A76AE47003BB08B /* Notify */,
|
||||||
4CC14FEC2A73FC9A007AEB17 /* Types */,
|
4CC14FEC2A73FC9A007AEB17 /* Types */,
|
||||||
@ -2549,7 +2573,8 @@
|
|||||||
E06336A92B75832100A88E6B /* ImageMetadataTest.swift */,
|
E06336A92B75832100A88E6B /* ImageMetadataTest.swift */,
|
||||||
D7CBD1D52B8D509800BFD889 /* DamusPurpleImpendingExpirationTests.swift */,
|
D7CBD1D52B8D509800BFD889 /* DamusPurpleImpendingExpirationTests.swift */,
|
||||||
D72927AC2BAB515C00F93E90 /* RelayURLTests.swift */,
|
D72927AC2BAB515C00F93E90 /* RelayURLTests.swift */,
|
||||||
D7831AF72BBE11E2005DA780 /* VideoCacheTests.swift */,
|
D753CEA92BE9DE04001C3A5D /* MutingTests.swift */,
|
||||||
|
4C2D34402BDAF1B300F9FB44 /* NIP10Tests.swift */,
|
||||||
);
|
);
|
||||||
path = damusTests;
|
path = damusTests;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -2750,6 +2775,7 @@
|
|||||||
D79C4C182AFEB061003A41B4 /* Info.plist */,
|
D79C4C182AFEB061003A41B4 /* Info.plist */,
|
||||||
D70A3B162B02DCE5008BD568 /* NotificationFormatter.swift */,
|
D70A3B162B02DCE5008BD568 /* NotificationFormatter.swift */,
|
||||||
D74AAFC42B1538DE006CF0F4 /* NotificationExtensionState.swift */,
|
D74AAFC42B1538DE006CF0F4 /* NotificationExtensionState.swift */,
|
||||||
|
D7FB14242BE5A9A800398331 /* PrivacyInfo.xcprivacy */,
|
||||||
);
|
);
|
||||||
path = DamusNotificationService;
|
path = DamusNotificationService;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -2947,6 +2973,7 @@
|
|||||||
ru,
|
ru,
|
||||||
"sv-SE",
|
"sv-SE",
|
||||||
sw,
|
sw,
|
||||||
|
th,
|
||||||
"tr-TR",
|
"tr-TR",
|
||||||
uk,
|
uk,
|
||||||
vi,
|
vi,
|
||||||
@ -2981,6 +3008,7 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
4C1D4FB42A7967990024F453 /* build-git-hash.txt in Resources */,
|
4C1D4FB42A7967990024F453 /* build-git-hash.txt in Resources */,
|
||||||
|
D7FB14222BE5970000398331 /* PrivacyInfo.xcprivacy in Resources */,
|
||||||
3ACB685F297633BC00C46468 /* Localizable.strings in Resources */,
|
3ACB685F297633BC00C46468 /* Localizable.strings in Resources */,
|
||||||
4CE6DEEE27F7A08200C66700 /* Preview Assets.xcassets in Resources */,
|
4CE6DEEE27F7A08200C66700 /* Preview Assets.xcassets in Resources */,
|
||||||
3ACB685C297633BC00C46468 /* InfoPlist.strings in Resources */,
|
3ACB685C297633BC00C46468 /* InfoPlist.strings in Resources */,
|
||||||
@ -3014,6 +3042,7 @@
|
|||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
D7FB14252BE5A9A800398331 /* PrivacyInfo.xcprivacy in Resources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@ -3205,6 +3234,7 @@
|
|||||||
4C86F7C62A76C51100EC0817 /* AttachedWalletNotify.swift in Sources */,
|
4C86F7C62A76C51100EC0817 /* AttachedWalletNotify.swift in Sources */,
|
||||||
4CF0ABE12981A83900D66079 /* MutelistView.swift in Sources */,
|
4CF0ABE12981A83900D66079 /* MutelistView.swift in Sources */,
|
||||||
4CB883A82975FC1800DC99E7 /* Zaps.swift in Sources */,
|
4CB883A82975FC1800DC99E7 /* Zaps.swift in Sources */,
|
||||||
|
4C45E5022BED4D000025A428 /* ThreadReply.swift in Sources */,
|
||||||
D74AAFD42B155ECB006CF0F4 /* Zaps+.swift in Sources */,
|
D74AAFD42B155ECB006CF0F4 /* Zaps+.swift in Sources */,
|
||||||
4C75EFB128049D510006080F /* NostrResponse.swift in Sources */,
|
4C75EFB128049D510006080F /* NostrResponse.swift in Sources */,
|
||||||
4C7D09592A05BEAD00943473 /* KeyboardVisible.swift in Sources */,
|
4C7D09592A05BEAD00943473 /* KeyboardVisible.swift in Sources */,
|
||||||
@ -3511,6 +3541,7 @@
|
|||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
4C2D34412BDAF1B300F9FB44 /* NIP10Tests.swift in Sources */,
|
||||||
4C684A572A7FFAE6005E6031 /* UrlTests.swift in Sources */,
|
4C684A572A7FFAE6005E6031 /* UrlTests.swift in Sources */,
|
||||||
3A90B1832A4EA3C600000D94 /* UserSearchCacheTests.swift in Sources */,
|
3A90B1832A4EA3C600000D94 /* UserSearchCacheTests.swift in Sources */,
|
||||||
4C9B0DEE2A65A75F00CBDA21 /* AttrStringTestExtensions.swift in Sources */,
|
4C9B0DEE2A65A75F00CBDA21 /* AttrStringTestExtensions.swift in Sources */,
|
||||||
@ -3550,6 +3581,7 @@
|
|||||||
4C90BD1C283AC38E008EE7EF /* Bech32Tests.swift in Sources */,
|
4C90BD1C283AC38E008EE7EF /* Bech32Tests.swift in Sources */,
|
||||||
50A50A8D29A09E1C00C01BE7 /* RequestTests.swift in Sources */,
|
50A50A8D29A09E1C00C01BE7 /* RequestTests.swift in Sources */,
|
||||||
4CE6DEF827F7A08200C66700 /* damusTests.swift in Sources */,
|
4CE6DEF827F7A08200C66700 /* damusTests.swift in Sources */,
|
||||||
|
D753CEAA2BE9DE04001C3A5D /* MutingTests.swift in Sources */,
|
||||||
3A3040F329A91366008A0F29 /* ProfileViewTests.swift in Sources */,
|
3A3040F329A91366008A0F29 /* ProfileViewTests.swift in Sources */,
|
||||||
4CF0ABDC2981A19E00D66079 /* ListTests.swift in Sources */,
|
4CF0ABDC2981A19E00D66079 /* ListTests.swift in Sources */,
|
||||||
4C684A552A7E91FE005E6031 /* LongPostTests.swift in Sources */,
|
4C684A552A7E91FE005E6031 /* LongPostTests.swift in Sources */,
|
||||||
@ -3570,6 +3602,7 @@
|
|||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
4C8FA7242BED58A900798A6A /* ThreadReply.swift in Sources */,
|
||||||
D798D21F2B0858D600234419 /* MigratedTypes.swift in Sources */,
|
D798D21F2B0858D600234419 /* MigratedTypes.swift in Sources */,
|
||||||
D7CE1B472B0BE719002EDAD4 /* NativeObject.swift in Sources */,
|
D7CE1B472B0BE719002EDAD4 /* NativeObject.swift in Sources */,
|
||||||
D7CB5D552B11758A00AD4105 /* UnmuteThreadNotify.swift in Sources */,
|
D7CB5D552B11758A00AD4105 /* UnmuteThreadNotify.swift in Sources */,
|
||||||
@ -3731,36 +3764,37 @@
|
|||||||
3A4325AA2961E11400BFCD9D /* Localizable.stringsdict */ = {
|
3A4325AA2961E11400BFCD9D /* Localizable.stringsdict */ = {
|
||||||
isa = PBXVariantGroup;
|
isa = PBXVariantGroup;
|
||||||
children = (
|
children = (
|
||||||
3A5C4575296A879E0032D398 /* es-419 */,
|
|
||||||
3A2B8B0A296A8982009CC16D /* en-US */,
|
|
||||||
3AEB8005297CCEA900713A25 /* tr-TR */,
|
|
||||||
3A185A06297F2C3800F4BDC0 /* lv-LV */,
|
|
||||||
3A929C22297F2CF80090925E /* it-IT */,
|
|
||||||
3AB5B86C2986D8A3006599D2 /* de */,
|
|
||||||
3AF6336A29884C6B0005672A /* pt-PT */,
|
|
||||||
3A93342B29884CA600D6A8F3 /* pl-PL */,
|
|
||||||
3AC524F0298C000B00693EBF /* ar */,
|
3AC524F0298C000B00693EBF /* ar */,
|
||||||
3A96D41C298DA94500388A2A /* nl */,
|
3AA5E70729B9E84A002701ED /* bg */,
|
||||||
3A5CAE1F298DC0DB00B5334F /* zh-CN */,
|
|
||||||
3A25EF152992DA5D008ABE69 /* el-GR */,
|
|
||||||
3A66D929299472FA008B44F4 /* ja */,
|
|
||||||
3A41E55B299D52BE001FA465 /* id */,
|
|
||||||
3A8624DB299E82BE00BD8BE9 /* cs */,
|
3A8624DB299E82BE00BD8BE9 /* cs */,
|
||||||
|
3AB5B86C2986D8A3006599D2 /* de */,
|
||||||
|
3A25EF152992DA5D008ABE69 /* el-GR */,
|
||||||
|
3A2B8B0A296A8982009CC16D /* en-US */,
|
||||||
|
3A5C4575296A879E0032D398 /* es-419 */,
|
||||||
|
3A325AC929C9E0CF002BE7ED /* es-ES */,
|
||||||
|
3AD5662C29BD2F5300BF77C5 /* fa */,
|
||||||
|
3A47CB792BDA05A200728A7C /* fi */,
|
||||||
|
3A821C4029E819D500B4BCA7 /* fr */,
|
||||||
|
3AD14EB529C40F38009D2D9C /* hu-HU */,
|
||||||
|
3A41E55B299D52BE001FA465 /* id */,
|
||||||
|
3A929C22297F2CF80090925E /* it-IT */,
|
||||||
|
3A66D929299472FA008B44F4 /* ja */,
|
||||||
|
3AD5663229C0DA4B00BF77C5 /* ko */,
|
||||||
|
3A185A06297F2C3800F4BDC0 /* lv-LV */,
|
||||||
|
3A96D41C298DA94500388A2A /* nl */,
|
||||||
|
3A93342B29884CA600D6A8F3 /* pl-PL */,
|
||||||
|
3AC59CA929CDDB78007E04A6 /* pt-BR */,
|
||||||
|
3AF6336A29884C6B0005672A /* pt-PT */,
|
||||||
3A827A1A299FC69D00C4D171 /* ru */,
|
3A827A1A299FC69D00C4D171 /* ru */,
|
||||||
|
3AD14EB829C40F3F009D2D9C /* sv-SE */,
|
||||||
|
3ABACEC02A5B3ED10037A847 /* sw */,
|
||||||
|
3A994C4C2BE5B9370019F632 /* th */,
|
||||||
|
3AEB8005297CCEA900713A25 /* tr-TR */,
|
||||||
|
3AA5E70429B682B3002701ED /* uk */,
|
||||||
|
3A325AC629C9E0B8002BE7ED /* vi */,
|
||||||
|
3A5CAE1F298DC0DB00B5334F /* zh-CN */,
|
||||||
3A3040FB29A91F03008A0F29 /* zh-HK */,
|
3A3040FB29A91F03008A0F29 /* zh-HK */,
|
||||||
3A3040FD29A91F31008A0F29 /* zh-TW */,
|
3A3040FD29A91F31008A0F29 /* zh-TW */,
|
||||||
3AA5E70429B682B3002701ED /* uk */,
|
|
||||||
3AA5E70729B9E84A002701ED /* bg */,
|
|
||||||
3AD5662C29BD2F5300BF77C5 /* fa */,
|
|
||||||
3AD5663229C0DA4B00BF77C5 /* ko */,
|
|
||||||
3AD14EB529C40F38009D2D9C /* hu-HU */,
|
|
||||||
3AD14EB829C40F3F009D2D9C /* sv-SE */,
|
|
||||||
3A325AC629C9E0B8002BE7ED /* vi */,
|
|
||||||
3A325AC929C9E0CF002BE7ED /* es-ES */,
|
|
||||||
3AC59CA929CDDB78007E04A6 /* pt-BR */,
|
|
||||||
3A821C4029E819D500B4BCA7 /* fr */,
|
|
||||||
3ABACEC02A5B3ED10037A847 /* sw */,
|
|
||||||
3A47CB792BDA05A200728A7C /* fi */,
|
|
||||||
);
|
);
|
||||||
name = Localizable.stringsdict;
|
name = Localizable.stringsdict;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -3768,35 +3802,36 @@
|
|||||||
3ACB685A297633BC00C46468 /* InfoPlist.strings */ = {
|
3ACB685A297633BC00C46468 /* InfoPlist.strings */ = {
|
||||||
isa = PBXVariantGroup;
|
isa = PBXVariantGroup;
|
||||||
children = (
|
children = (
|
||||||
3ACB685B297633BC00C46468 /* es-419 */,
|
|
||||||
3AEB8003297CCEA800713A25 /* tr-TR */,
|
|
||||||
3A185A04297F2C3800F4BDC0 /* lv-LV */,
|
|
||||||
3A929C20297F2CF80090925E /* it-IT */,
|
|
||||||
3AB5B86A2986D8A3006599D2 /* de */,
|
|
||||||
3AF6336829884C6B0005672A /* pt-PT */,
|
|
||||||
3A93342929884CA600D6A8F3 /* pl-PL */,
|
|
||||||
3AC524EE298C000B00693EBF /* ar */,
|
3AC524EE298C000B00693EBF /* ar */,
|
||||||
3A96D41A298DA94500388A2A /* nl */,
|
3AA5E70529B9E83E002701ED /* bg */,
|
||||||
3A5CAE1D298DC0DB00B5334F /* zh-CN */,
|
|
||||||
3A25EF132992DA5D008ABE69 /* el-GR */,
|
|
||||||
3A66D927299472FA008B44F4 /* ja */,
|
|
||||||
3A41E559299D52BE001FA465 /* id */,
|
|
||||||
3A8624D9299E82BE00BD8BE9 /* cs */,
|
3A8624D9299E82BE00BD8BE9 /* cs */,
|
||||||
|
3AB5B86A2986D8A3006599D2 /* de */,
|
||||||
|
3A25EF132992DA5D008ABE69 /* el-GR */,
|
||||||
|
3ACB685B297633BC00C46468 /* es-419 */,
|
||||||
|
3A325AC829C9E0CF002BE7ED /* es-ES */,
|
||||||
|
3AD5662B29BD2F5300BF77C5 /* fa */,
|
||||||
|
3A47CB772BDA05A200728A7C /* fi */,
|
||||||
|
3A821C3F29E819D500B4BCA7 /* fr */,
|
||||||
|
3AD14EB629C40F38009D2D9C /* hu-HU */,
|
||||||
|
3A41E559299D52BE001FA465 /* id */,
|
||||||
|
3A929C20297F2CF80090925E /* it-IT */,
|
||||||
|
3A66D927299472FA008B44F4 /* ja */,
|
||||||
|
3AD5663329C0DA4B00BF77C5 /* ko */,
|
||||||
|
3A96D41A298DA94500388A2A /* nl */,
|
||||||
|
3A185A04297F2C3800F4BDC0 /* lv-LV */,
|
||||||
|
3A93342929884CA600D6A8F3 /* pl-PL */,
|
||||||
|
3AC59CA829CDDB78007E04A6 /* pt-BR */,
|
||||||
|
3AF6336829884C6B0005672A /* pt-PT */,
|
||||||
3A827A18299FC69D00C4D171 /* ru */,
|
3A827A18299FC69D00C4D171 /* ru */,
|
||||||
|
3AD14EB929C40F3F009D2D9C /* sv-SE */,
|
||||||
|
3ABACEBF2A5B3ED10037A847 /* sw */,
|
||||||
|
3A994C4D2BE5B9370019F632 /* th */,
|
||||||
|
3AEB8003297CCEA800713A25 /* tr-TR */,
|
||||||
|
3AA5E70329B682AD002701ED /* uk */,
|
||||||
|
3A325AC529C9E0B8002BE7ED /* vi */,
|
||||||
|
3A5CAE1D298DC0DB00B5334F /* zh-CN */,
|
||||||
3A3040F929A91ED6008A0F29 /* zh-HK */,
|
3A3040F929A91ED6008A0F29 /* zh-HK */,
|
||||||
3A3040FC29A91F31008A0F29 /* zh-TW */,
|
3A3040FC29A91F31008A0F29 /* zh-TW */,
|
||||||
3AA5E70329B682AD002701ED /* uk */,
|
|
||||||
3AA5E70529B9E83E002701ED /* bg */,
|
|
||||||
3AD5662B29BD2F5300BF77C5 /* fa */,
|
|
||||||
3AD5663329C0DA4B00BF77C5 /* ko */,
|
|
||||||
3AD14EB629C40F38009D2D9C /* hu-HU */,
|
|
||||||
3AD14EB929C40F3F009D2D9C /* sv-SE */,
|
|
||||||
3A325AC529C9E0B8002BE7ED /* vi */,
|
|
||||||
3A325AC829C9E0CF002BE7ED /* es-ES */,
|
|
||||||
3AC59CA829CDDB78007E04A6 /* pt-BR */,
|
|
||||||
3A821C3F29E819D500B4BCA7 /* fr */,
|
|
||||||
3ABACEBF2A5B3ED10037A847 /* sw */,
|
|
||||||
3A47CB772BDA05A200728A7C /* fi */,
|
|
||||||
);
|
);
|
||||||
name = InfoPlist.strings;
|
name = InfoPlist.strings;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -3804,36 +3839,37 @@
|
|||||||
3ACB685D297633BC00C46468 /* Localizable.strings */ = {
|
3ACB685D297633BC00C46468 /* Localizable.strings */ = {
|
||||||
isa = PBXVariantGroup;
|
isa = PBXVariantGroup;
|
||||||
children = (
|
children = (
|
||||||
3ACB685E297633BC00C46468 /* es-419 */,
|
|
||||||
3AEB8004297CCEA800713A25 /* tr-TR */,
|
|
||||||
3A185A05297F2C3800F4BDC0 /* lv-LV */,
|
|
||||||
3A929C21297F2CF80090925E /* it-IT */,
|
|
||||||
3AB5B86B2986D8A3006599D2 /* de */,
|
|
||||||
3AF6336929884C6B0005672A /* pt-PT */,
|
|
||||||
3A93342A29884CA600D6A8F3 /* pl-PL */,
|
|
||||||
3AC524EF298C000B00693EBF /* ar */,
|
3AC524EF298C000B00693EBF /* ar */,
|
||||||
3A96D41B298DA94500388A2A /* nl */,
|
3AA5E70629B9E844002701ED /* bg */,
|
||||||
3A5CAE1E298DC0DB00B5334F /* zh-CN */,
|
|
||||||
3A25EF142992DA5D008ABE69 /* el-GR */,
|
|
||||||
3A66D928299472FA008B44F4 /* ja */,
|
|
||||||
3A41E55A299D52BE001FA465 /* id */,
|
|
||||||
3A8624DA299E82BE00BD8BE9 /* cs */,
|
3A8624DA299E82BE00BD8BE9 /* cs */,
|
||||||
|
3AB5B86B2986D8A3006599D2 /* de */,
|
||||||
|
3A25EF142992DA5D008ABE69 /* el-GR */,
|
||||||
|
3A3040FF29AB02D1008A0F29 /* en-US */,
|
||||||
|
3ACB685E297633BC00C46468 /* es-419 */,
|
||||||
|
3A325AC729C9E0CF002BE7ED /* es-ES */,
|
||||||
|
3AD5662D29BD2F5300BF77C5 /* fa */,
|
||||||
|
3A47CB782BDA05A200728A7C /* fi */,
|
||||||
|
3A821C3E29E819D500B4BCA7 /* fr */,
|
||||||
|
3A41E55A299D52BE001FA465 /* id */,
|
||||||
|
3AD14EB729C40F38009D2D9C /* hu-HU */,
|
||||||
|
3A929C21297F2CF80090925E /* it-IT */,
|
||||||
|
3A66D928299472FA008B44F4 /* ja */,
|
||||||
|
3AD5663129C0DA4B00BF77C5 /* ko */,
|
||||||
|
3A185A05297F2C3800F4BDC0 /* lv-LV */,
|
||||||
|
3A96D41B298DA94500388A2A /* nl */,
|
||||||
|
3A93342A29884CA600D6A8F3 /* pl-PL */,
|
||||||
|
3AC59CA729CDDB78007E04A6 /* pt-BR */,
|
||||||
|
3AF6336929884C6B0005672A /* pt-PT */,
|
||||||
3A827A19299FC69D00C4D171 /* ru */,
|
3A827A19299FC69D00C4D171 /* ru */,
|
||||||
|
3AD14EBA29C40F3F009D2D9C /* sv-SE */,
|
||||||
|
3ABACEC12A5B3ED10037A847 /* sw */,
|
||||||
|
3A994C4E2BE5B9370019F632 /* th */,
|
||||||
|
3AEB8004297CCEA800713A25 /* tr-TR */,
|
||||||
|
3AA5E70229B682A5002701ED /* uk */,
|
||||||
|
3A325AC429C9E0B8002BE7ED /* vi */,
|
||||||
|
3A5CAE1E298DC0DB00B5334F /* zh-CN */,
|
||||||
3A3040FA29A91EFC008A0F29 /* zh-HK */,
|
3A3040FA29A91EFC008A0F29 /* zh-HK */,
|
||||||
3A3040FE29A91F31008A0F29 /* zh-TW */,
|
3A3040FE29A91F31008A0F29 /* zh-TW */,
|
||||||
3A3040FF29AB02D1008A0F29 /* en-US */,
|
|
||||||
3AA5E70229B682A5002701ED /* uk */,
|
|
||||||
3AA5E70629B9E844002701ED /* bg */,
|
|
||||||
3AD5662D29BD2F5300BF77C5 /* fa */,
|
|
||||||
3AD5663129C0DA4B00BF77C5 /* ko */,
|
|
||||||
3AD14EB729C40F38009D2D9C /* hu-HU */,
|
|
||||||
3AD14EBA29C40F3F009D2D9C /* sv-SE */,
|
|
||||||
3A325AC429C9E0B8002BE7ED /* vi */,
|
|
||||||
3A325AC729C9E0CF002BE7ED /* es-ES */,
|
|
||||||
3AC59CA729CDDB78007E04A6 /* pt-BR */,
|
|
||||||
3A821C3E29E819D500B4BCA7 /* fr */,
|
|
||||||
3ABACEC12A5B3ED10037A847 /* sw */,
|
|
||||||
3A47CB782BDA05A200728A7C /* fi */,
|
|
||||||
);
|
);
|
||||||
name = Localizable.strings;
|
name = Localizable.strings;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -3876,7 +3912,7 @@
|
|||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 2;
|
||||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
ENABLE_TESTABILITY = YES;
|
ENABLE_TESTABILITY = YES;
|
||||||
@ -3897,7 +3933,7 @@
|
|||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
|
||||||
MACOSX_DEPLOYMENT_TARGET = 12.3;
|
MACOSX_DEPLOYMENT_TARGET = 12.3;
|
||||||
MARKETING_VERSION = 1.8;
|
MARKETING_VERSION = 1.9;
|
||||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
@ -3943,7 +3979,7 @@
|
|||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 2;
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
ENABLE_NS_ASSERTIONS = NO;
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
@ -3959,7 +3995,7 @@
|
|||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
|
||||||
MACOSX_DEPLOYMENT_TARGET = 12.3;
|
MACOSX_DEPLOYMENT_TARGET = 12.3;
|
||||||
MARKETING_VERSION = 1.8;
|
MARKETING_VERSION = 1.9;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
@ -4005,7 +4041,6 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"$(PROJECT_DIR)",
|
"$(PROJECT_DIR)",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.9;
|
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.jb55.damus2;
|
PRODUCT_BUNDLE_IDENTIFIER = com.jb55.damus2;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||||
@ -4055,7 +4090,6 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"$(PROJECT_DIR)",
|
"$(PROJECT_DIR)",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.9;
|
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.jb55.damus2;
|
PRODUCT_BUNDLE_IDENTIFIER = com.jb55.damus2;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||||
|
@ -76,27 +76,35 @@ func interpret_event_refs_ndb(blocks: [Block], tags: TagsSequence) -> [EventRef]
|
|||||||
}
|
}
|
||||||
|
|
||||||
func interp_event_refs_without_mentions_ndb(_ ev_tags: References<NoteRef>) -> [EventRef] {
|
func interp_event_refs_without_mentions_ndb(_ ev_tags: References<NoteRef>) -> [EventRef] {
|
||||||
|
|
||||||
var count = 0
|
|
||||||
var evrefs: [EventRef] = []
|
var evrefs: [EventRef] = []
|
||||||
var first: Bool = true
|
var first: Bool = true
|
||||||
var first_ref: NoteRef? = nil
|
var root_id: NoteRef? = nil
|
||||||
|
var any_marker: Bool = false
|
||||||
|
|
||||||
for ref in ev_tags {
|
for ref in ev_tags {
|
||||||
if first {
|
if let marker = ref.marker {
|
||||||
first_ref = ref
|
any_marker = true
|
||||||
evrefs.append(.thread_id(ref))
|
switch marker {
|
||||||
first = false
|
case .root: root_id = ref
|
||||||
|
case .reply: evrefs.append(.reply(ref))
|
||||||
|
case .mention: evrefs.append(.mention(.noteref(ref)))
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if !any_marker && first {
|
||||||
|
root_id = ref
|
||||||
|
first = false
|
||||||
|
} else if !any_marker {
|
||||||
evrefs.append(.reply(ref))
|
evrefs.append(.reply(ref))
|
||||||
}
|
}
|
||||||
count += 1
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let first_ref, count == 1 {
|
if let root_id {
|
||||||
let r = first_ref
|
if evrefs.count == 0 {
|
||||||
return [.reply_to_root(r)]
|
return [.reply_to_root(root_id)]
|
||||||
|
} else {
|
||||||
|
evrefs.insert(.thread_id(root_id), at: 0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return evrefs
|
return evrefs
|
||||||
|
@ -699,7 +699,7 @@ struct ContentView: View {
|
|||||||
likes: EventCounter(our_pubkey: pubkey),
|
likes: EventCounter(our_pubkey: pubkey),
|
||||||
boosts: EventCounter(our_pubkey: pubkey),
|
boosts: EventCounter(our_pubkey: pubkey),
|
||||||
contacts: Contacts(our_pubkey: pubkey),
|
contacts: Contacts(our_pubkey: pubkey),
|
||||||
mutelist_manager: MutelistManager(),
|
mutelist_manager: MutelistManager(user_keypair: keypair),
|
||||||
profiles: Profiles(ndb: ndb),
|
profiles: Profiles(ndb: ndb),
|
||||||
dms: home.dms,
|
dms: home.dms,
|
||||||
previews: PreviewCache(),
|
previews: PreviewCache(),
|
||||||
|
@ -112,7 +112,7 @@ class DamusState: HeadlessDamusState {
|
|||||||
likes: EventCounter(our_pubkey: empty_pub),
|
likes: EventCounter(our_pubkey: empty_pub),
|
||||||
boosts: EventCounter(our_pubkey: empty_pub),
|
boosts: EventCounter(our_pubkey: empty_pub),
|
||||||
contacts: Contacts(our_pubkey: empty_pub),
|
contacts: Contacts(our_pubkey: empty_pub),
|
||||||
mutelist_manager: MutelistManager(),
|
mutelist_manager: MutelistManager(user_keypair: kp),
|
||||||
profiles: Profiles(ndb: .empty),
|
profiles: Profiles(ndb: .empty),
|
||||||
dms: DirectMessagesModel(our_pubkey: empty_pub),
|
dms: DirectMessagesModel(our_pubkey: empty_pub),
|
||||||
previews: PreviewCache(),
|
previews: PreviewCache(),
|
||||||
|
@ -1148,8 +1148,8 @@ func should_show_event(event: NostrEvent, damus_state: DamusState) -> Bool {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func should_show_event(state: DamusState, ev: NostrEvent, keypair: Keypair? = nil) -> Bool {
|
func should_show_event(state: DamusState, ev: NostrEvent) -> Bool {
|
||||||
let event_muted = state.mutelist_manager.is_event_muted(ev, keypair: keypair)
|
let event_muted = state.mutelist_manager.is_event_muted(ev)
|
||||||
if event_muted {
|
if event_muted {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -292,9 +292,8 @@ func make_post_tags(post_blocks: [Block], tags: [[String]]) -> PostTags {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func post_to_event(post: NostrPost, keypair: FullKeypair) -> NostrEvent? {
|
func post_to_event(post: NostrPost, keypair: FullKeypair) -> NostrEvent? {
|
||||||
let tags = post.references.map({ r in r.tag }) + post.tags
|
|
||||||
let post_blocks = parse_post_blocks(content: post.content)
|
let post_blocks = parse_post_blocks(content: post.content)
|
||||||
let post_tags = make_post_tags(post_blocks: post_blocks, tags: tags)
|
let post_tags = make_post_tags(post_blocks: post_blocks, tags: post.tags)
|
||||||
let content = post_tags.blocks
|
let content = post_tags.blocks
|
||||||
.map(\.asString)
|
.map(\.asString)
|
||||||
.joined(separator: "")
|
.joined(separator: "")
|
||||||
|
@ -8,12 +8,27 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
class MutelistManager {
|
class MutelistManager {
|
||||||
|
let user_keypair: Keypair
|
||||||
private(set) var event: NostrEvent? = nil
|
private(set) var event: NostrEvent? = nil
|
||||||
|
|
||||||
var users: Set<MuteItem> = []
|
var users: Set<MuteItem> = [] {
|
||||||
var hashtags: Set<MuteItem> = []
|
didSet { self.reset_cache() }
|
||||||
var threads: Set<MuteItem> = []
|
}
|
||||||
var words: Set<MuteItem> = []
|
var hashtags: Set<MuteItem> = [] {
|
||||||
|
didSet { self.reset_cache() }
|
||||||
|
}
|
||||||
|
var threads: Set<MuteItem> = [] {
|
||||||
|
didSet { self.reset_cache() }
|
||||||
|
}
|
||||||
|
var words: Set<MuteItem> = [] {
|
||||||
|
didSet { self.reset_cache() }
|
||||||
|
}
|
||||||
|
|
||||||
|
var muted_notes_cache: [NoteId: EventMuteStatus] = [:]
|
||||||
|
|
||||||
|
init(user_keypair: Keypair) {
|
||||||
|
self.user_keypair = user_keypair
|
||||||
|
}
|
||||||
|
|
||||||
func refresh_sets() {
|
func refresh_sets() {
|
||||||
guard let referenced_mute_items = event?.referenced_mute_items else { return }
|
guard let referenced_mute_items = event?.referenced_mute_items else { return }
|
||||||
@ -42,6 +57,10 @@ class MutelistManager {
|
|||||||
words = new_words
|
words = new_words
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func reset_cache() {
|
||||||
|
self.muted_notes_cache = [:]
|
||||||
|
}
|
||||||
|
|
||||||
func is_muted(_ item: MuteItem) -> Bool {
|
func is_muted(_ item: MuteItem) -> Bool {
|
||||||
switch item {
|
switch item {
|
||||||
case .user(_, _):
|
case .user(_, _):
|
||||||
@ -55,8 +74,8 @@ class MutelistManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func is_event_muted(_ ev: NostrEvent, keypair: Keypair? = nil) -> Bool {
|
func is_event_muted(_ ev: NostrEvent) -> Bool {
|
||||||
return event_muted_reason(ev, keypair: keypair) != nil
|
return self.event_muted_reason(ev) != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func set_mutelist(_ ev: NostrEvent) {
|
func set_mutelist(_ ev: NostrEvent) {
|
||||||
@ -115,14 +134,26 @@ class MutelistManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func event_muted_reason(_ ev: NostrEvent) -> MuteItem? {
|
||||||
|
if let cached_mute_status = self.muted_notes_cache[ev.id] {
|
||||||
|
return cached_mute_status.mute_reason()
|
||||||
|
}
|
||||||
|
if let reason = self.compute_event_muted_reason(ev) {
|
||||||
|
self.muted_notes_cache[ev.id] = .muted(reason: reason)
|
||||||
|
return reason
|
||||||
|
}
|
||||||
|
self.muted_notes_cache[ev.id] = .not_muted
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Check if an event is muted given a collection of ``MutedItem``.
|
/// Check if an event is muted given a collection of ``MutedItem``.
|
||||||
///
|
///
|
||||||
/// - Parameter ev: The ``NostrEvent`` that you want to check the muted reason for.
|
/// - Parameter ev: The ``NostrEvent`` that you want to check the muted reason for.
|
||||||
/// - Returns: The ``MuteItem`` that matched the event. Or `nil` if the event is not muted.
|
/// - Returns: The ``MuteItem`` that matched the event. Or `nil` if the event is not muted.
|
||||||
func event_muted_reason(_ ev: NostrEvent, keypair: Keypair? = nil) -> MuteItem? {
|
func compute_event_muted_reason(_ ev: NostrEvent) -> MuteItem? {
|
||||||
// Events from the current user should not be muted.
|
// Events from the current user should not be muted.
|
||||||
guard keypair?.pubkey != ev.pubkey else { return nil }
|
guard self.user_keypair.pubkey != ev.pubkey else { return nil }
|
||||||
|
|
||||||
// Check if user is muted
|
// Check if user is muted
|
||||||
let check_user_item = MuteItem.user(ev.pubkey, nil)
|
let check_user_item = MuteItem.user(ev.pubkey, nil)
|
||||||
@ -147,7 +178,7 @@ class MutelistManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if word is muted
|
// Check if word is muted
|
||||||
if let keypair, let content: String = ev.maybe_get_content(keypair)?.lowercased() {
|
if let content: String = ev.maybe_get_content(self.user_keypair)?.lowercased() {
|
||||||
for word in words {
|
for word in words {
|
||||||
if case .word(let string, _) = word {
|
if case .word(let string, _) = word {
|
||||||
if content.contains(string.lowercased()) {
|
if content.contains(string.lowercased()) {
|
||||||
@ -159,4 +190,18 @@ class MutelistManager {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum EventMuteStatus {
|
||||||
|
case muted(reason: MuteItem)
|
||||||
|
case not_muted
|
||||||
|
|
||||||
|
func mute_reason() -> MuteItem? {
|
||||||
|
switch self {
|
||||||
|
case .muted(reason: let reason):
|
||||||
|
return reason
|
||||||
|
case .not_muted:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ func should_display_notification(state: HeadlessDamusState, event ev: NostrEvent
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Don't show notifications that match mute list.
|
// Don't show notifications that match mute list.
|
||||||
if state.mutelist_manager.is_event_muted(ev, keypair: state.keypair) {
|
if state.mutelist_manager.is_event_muted(ev) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,12 +10,10 @@ import Foundation
|
|||||||
struct NostrPost {
|
struct NostrPost {
|
||||||
let kind: NostrKind
|
let kind: NostrKind
|
||||||
let content: String
|
let content: String
|
||||||
let references: [RefId]
|
|
||||||
let tags: [[String]]
|
let tags: [[String]]
|
||||||
|
|
||||||
init(content: String, references: [RefId], kind: NostrKind = .text, tags: [[String]] = []) {
|
init(content: String, kind: NostrKind = .text, tags: [[String]] = []) {
|
||||||
self.content = content
|
self.content = content
|
||||||
self.references = references
|
|
||||||
self.kind = kind
|
self.kind = kind
|
||||||
self.tags = tags
|
self.tags = tags
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,15 @@ enum EventRef: Equatable {
|
|||||||
case reply(NoteRef)
|
case reply(NoteRef)
|
||||||
case reply_to_root(NoteRef)
|
case reply_to_root(NoteRef)
|
||||||
|
|
||||||
|
var note_ref: NoteRef {
|
||||||
|
switch self {
|
||||||
|
case .mention(let mnref): return mnref.ref
|
||||||
|
case .thread_id(let ref): return ref
|
||||||
|
case .reply(let ref): return ref
|
||||||
|
case .reply_to_root(let ref): return ref
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var is_mention: NoteRef? {
|
var is_mention: NoteRef? {
|
||||||
if case .mention(let m) = self { return m.ref }
|
if case .mention(let m) = self { return m.ref }
|
||||||
return nil
|
return nil
|
||||||
@ -140,8 +149,3 @@ func interpret_event_refs(blocks: [Block], tags: Tags) -> [EventRef] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func event_is_reply(_ refs: [EventRef]) -> Bool {
|
|
||||||
return refs.contains { evref in
|
|
||||||
return evref.is_reply != nil
|
|
||||||
}
|
|
||||||
}
|
|
63
damus/NIP10/ThreadReply.swift
Normal file
63
damus/NIP10/ThreadReply.swift
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
//
|
||||||
|
// ThreadReply.swift
|
||||||
|
// damus
|
||||||
|
//
|
||||||
|
// Created by William Casarin on 2024-05-09.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
|
||||||
|
struct ThreadReply {
|
||||||
|
let root: NoteRef
|
||||||
|
let reply: NoteRef?
|
||||||
|
let mention: Mention<NoteRef>?
|
||||||
|
|
||||||
|
var is_reply_to_root: Bool {
|
||||||
|
guard let reply else {
|
||||||
|
// if we have no reply and only root then this is reply-to-root,
|
||||||
|
// but it should never really be in this form...
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return root.id == reply.id
|
||||||
|
}
|
||||||
|
|
||||||
|
init(root: NoteRef, reply: NoteRef?, mention: Mention<NoteRef>?) {
|
||||||
|
self.root = root
|
||||||
|
self.reply = reply
|
||||||
|
self.mention = mention
|
||||||
|
}
|
||||||
|
|
||||||
|
init?(event_refs: [EventRef]) {
|
||||||
|
var root: NoteRef? = nil
|
||||||
|
var reply: NoteRef? = nil
|
||||||
|
var mention: Mention<NoteRef>? = nil
|
||||||
|
|
||||||
|
for evref in event_refs {
|
||||||
|
switch evref {
|
||||||
|
case .mention(let m):
|
||||||
|
mention = m
|
||||||
|
case .thread_id(let r):
|
||||||
|
root = r
|
||||||
|
case .reply(let r):
|
||||||
|
reply = r
|
||||||
|
case .reply_to_root(let r):
|
||||||
|
root = r
|
||||||
|
reply = r
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// reply with no root should be considered reply-to-root
|
||||||
|
if root == nil && reply != nil {
|
||||||
|
root = reply
|
||||||
|
}
|
||||||
|
|
||||||
|
// nip10 threads must have a root
|
||||||
|
guard let root else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
self = ThreadReply(root: root, reply: reply, mention: mention)
|
||||||
|
}
|
||||||
|
}
|
@ -73,7 +73,7 @@ var test_damus_state: DamusState = ({
|
|||||||
likes: .init(our_pubkey: our_pubkey),
|
likes: .init(our_pubkey: our_pubkey),
|
||||||
boosts: .init(our_pubkey: our_pubkey),
|
boosts: .init(our_pubkey: our_pubkey),
|
||||||
contacts: .init(our_pubkey: our_pubkey),
|
contacts: .init(our_pubkey: our_pubkey),
|
||||||
mutelist_manager: MutelistManager(),
|
mutelist_manager: MutelistManager(user_keypair: test_keypair),
|
||||||
profiles: .init(ndb: ndb),
|
profiles: .init(ndb: ndb),
|
||||||
dms: .init(our_pubkey: our_pubkey),
|
dms: .init(our_pubkey: our_pubkey),
|
||||||
previews: .init(),
|
previews: .init(),
|
||||||
|
@ -169,7 +169,7 @@ class EventCache {
|
|||||||
var ev = event
|
var ev = event
|
||||||
|
|
||||||
while true {
|
while true {
|
||||||
guard let direct_reply = ev.direct_replies(keypair).last,
|
guard let direct_reply = ev.direct_replies(keypair),
|
||||||
let next_ev = lookup(direct_reply), next_ev != ev
|
let next_ev = lookup(direct_reply), next_ev != ev
|
||||||
else {
|
else {
|
||||||
break
|
break
|
||||||
@ -183,7 +183,7 @@ class EventCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func add_replies(ev: NostrEvent, keypair: Keypair) {
|
func add_replies(ev: NostrEvent, keypair: Keypair) {
|
||||||
for reply in ev.direct_replies(keypair) {
|
if let reply = ev.direct_replies(keypair) {
|
||||||
replies.add(id: reply, reply_id: ev.id)
|
replies.add(id: reply, reply_id: ev.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -218,7 +218,16 @@ class EventCache {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
func lookup(_ evid: NoteId) -> NostrEvent? {
|
func lookup(_ evid: NoteId) -> NostrEvent? {
|
||||||
return events[evid]
|
if let ev = events[evid] {
|
||||||
|
return ev
|
||||||
|
}
|
||||||
|
|
||||||
|
if let ev = self.ndb.lookup_note(evid)?.unsafeUnownedValue?.to_owned() {
|
||||||
|
events[ev.id] = ev
|
||||||
|
return ev
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func insert(_ ev: NostrEvent) {
|
func insert(_ ev: NostrEvent) {
|
||||||
|
@ -58,7 +58,7 @@ func load_bootstrap_relays(pubkey: Pubkey) -> [RelayURL] {
|
|||||||
|
|
||||||
let relay_urls = relays.compactMap({ RelayURL($0) })
|
let relay_urls = relays.compactMap({ RelayURL($0) })
|
||||||
|
|
||||||
let loaded_relays = Array(Set(relay_urls + get_default_bootstrap_relays()))
|
let loaded_relays = Array(Set(relay_urls))
|
||||||
print("Loading custom bootstrap relays: \(loaded_relays)")
|
print("Loading custom bootstrap relays: \(loaded_relays)")
|
||||||
return loaded_relays
|
return loaded_relays
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ class ReplyCounter {
|
|||||||
|
|
||||||
counted.insert(event.id)
|
counted.insert(event.id)
|
||||||
|
|
||||||
for reply in event.direct_replies(keypair) {
|
if let reply = event.direct_replies(keypair) {
|
||||||
if event.pubkey == our_pubkey {
|
if event.pubkey == our_pubkey {
|
||||||
self.our_replies[reply] = event
|
self.our_replies[reply] = event
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ struct DMChatView: View, KeyboardReadable {
|
|||||||
ScrollViewReader { scroller in
|
ScrollViewReader { scroller in
|
||||||
ScrollView {
|
ScrollView {
|
||||||
LazyVStack(alignment: .leading) {
|
LazyVStack(alignment: .leading) {
|
||||||
ForEach(Array(zip(dms.events, dms.events.indices)).filter { should_show_event(state: damus_state, ev: $0.0, keypair: damus_state.keypair)}, id: \.0.id) { (ev, ind) in
|
ForEach(Array(zip(dms.events, dms.events.indices)).filter { should_show_event(state: damus_state, ev: $0.0)}, id: \.0.id) { (ev, ind) in
|
||||||
DMView(event: dms.events[ind], damus_state: damus_state)
|
DMView(event: dms.events[ind], damus_state: damus_state)
|
||||||
.contextMenu{MenuItems(damus_state: damus_state, event: ev, target_pubkey: ev.pubkey, profileModel: ProfileModel(pubkey: ev.pubkey, damus: damus_state))}
|
.contextMenu{MenuItems(damus_state: damus_state, event: ev, target_pubkey: ev.pubkey, profileModel: ProfileModel(pubkey: ev.pubkey, damus: damus_state))}
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ struct DirectMessagesView: View {
|
|||||||
|
|
||||||
func MaybeEvent(_ model: DirectMessageModel) -> some View {
|
func MaybeEvent(_ model: DirectMessageModel) -> some View {
|
||||||
Group {
|
Group {
|
||||||
if let ev = model.events.last(where: { should_show_event(state: damus_state, ev: $0, keypair: damus_state.keypair) }) {
|
if let ev = model.events.last(where: { should_show_event(state: damus_state, ev: $0) }) {
|
||||||
EventView(damus: damus_state, event: ev, pubkey: model.pubkey, options: options)
|
EventView(damus: damus_state, event: ev, pubkey: model.pubkey, options: options)
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
self.model.set_active_dm_model(model)
|
self.model.set_active_dm_model(model)
|
||||||
|
@ -13,18 +13,10 @@ struct ReplyPart: View {
|
|||||||
let keypair: Keypair
|
let keypair: Keypair
|
||||||
let ndb: Ndb
|
let ndb: Ndb
|
||||||
|
|
||||||
var replying_to: NostrEvent? {
|
|
||||||
guard let note_ref = event.event_refs(keypair).first(where: { evref in evref.is_direct_reply != nil })?.is_direct_reply else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return events.lookup(note_ref.note_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Group {
|
Group {
|
||||||
if event_is_reply(event.event_refs(keypair)) {
|
if let reply_ref = event.thread_reply(keypair)?.reply {
|
||||||
ReplyDescription(event: event, replying_to: replying_to, ndb: ndb)
|
ReplyDescription(event: event, replying_to: events.lookup(reply_ref.note_id), ndb: ndb)
|
||||||
} else {
|
} else {
|
||||||
EmptyView()
|
EmptyView()
|
||||||
}
|
}
|
||||||
|
@ -18,14 +18,6 @@ struct SelectedEventView: View {
|
|||||||
|
|
||||||
@StateObject var bar: ActionBarModel
|
@StateObject var bar: ActionBarModel
|
||||||
|
|
||||||
var replying_to: NostrEvent? {
|
|
||||||
guard let note_ref = event.event_refs(damus.keypair).first(where: { evref in evref.is_direct_reply != nil })?.is_direct_reply else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return damus.events.lookup(note_ref.note_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
init(damus: DamusState, event: NostrEvent, size: EventViewKind) {
|
init(damus: DamusState, event: NostrEvent, size: EventViewKind) {
|
||||||
self.damus = damus
|
self.damus = damus
|
||||||
self.event = event
|
self.event = event
|
||||||
@ -48,8 +40,8 @@ struct SelectedEventView: View {
|
|||||||
.minimumScaleFactor(0.75)
|
.minimumScaleFactor(0.75)
|
||||||
.lineLimit(1)
|
.lineLimit(1)
|
||||||
|
|
||||||
if event_is_reply(event.event_refs(damus.keypair)) {
|
if let reply_ref = event.thread_reply(damus.keypair)?.reply {
|
||||||
ReplyDescription(event: event, replying_to: replying_to, ndb: damus.ndb)
|
ReplyDescription(event: event, replying_to: damus.events.lookup(reply_ref.note_id), ndb: damus.ndb)
|
||||||
.padding(.horizontal)
|
.padding(.horizontal)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,13 +92,24 @@ struct PostView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func send_post() {
|
func send_post() {
|
||||||
let refs = references.filter { ref in
|
// don't add duplicate pubkeys but retain order
|
||||||
if case .pubkey(let pk) = ref, filtered_pubkeys.contains(pk) {
|
var pkset = Set<Pubkey>()
|
||||||
return false
|
|
||||||
|
// we only want pubkeys really
|
||||||
|
let pks = references.reduce(into: Array<Pubkey>()) { acc, ref in
|
||||||
|
guard case .pubkey(let pk) = ref else {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
return true
|
|
||||||
|
if pkset.contains(pk) || filtered_pubkeys.contains(pk) {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
let new_post = build_post(state: damus_state, post: self.post, action: action, uploadedMedias: uploadedMedias, references: refs)
|
|
||||||
|
pkset.insert(pk)
|
||||||
|
acc.append(pk)
|
||||||
|
}
|
||||||
|
|
||||||
|
let new_post = build_post(state: damus_state, post: self.post, action: action, uploadedMedias: uploadedMedias, pubkeys: pks)
|
||||||
|
|
||||||
notify(.post(.post(new_post)))
|
notify(.post(.post(new_post)))
|
||||||
|
|
||||||
@ -604,7 +615,29 @@ private func isAlphanumeric(_ char: Character) -> Bool {
|
|||||||
return char.isLetter || char.isNumber
|
return char.isLetter || char.isNumber
|
||||||
}
|
}
|
||||||
|
|
||||||
func build_post(state: DamusState, post: NSMutableAttributedString, action: PostAction, uploadedMedias: [UploadedMedia], references: [RefId]) -> NostrPost {
|
func nip10_reply_tags(replying_to: NostrEvent, keypair: Keypair) -> [[String]] {
|
||||||
|
guard let nip10 = replying_to.thread_reply(keypair) else {
|
||||||
|
// we're replying to a post that isn't in a thread,
|
||||||
|
// just add a single reply-to-root tag
|
||||||
|
return [["e", replying_to.id.hex(), "", "root"]]
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise use the root tag from the parent's nip10 reply and include the note
|
||||||
|
// that we are replying to's note id.
|
||||||
|
var tags = [
|
||||||
|
["e", nip10.root.note_id.hex(), nip10.root.relay ?? "", "root"],
|
||||||
|
["e", replying_to.id.hex(), "", "reply"]
|
||||||
|
]
|
||||||
|
|
||||||
|
// we also add the parent's nip10 reply tag as an additional e tag for context
|
||||||
|
if let reply = nip10.reply {
|
||||||
|
tags.append(["e", reply.note_id.hex(), reply.relay ?? ""])
|
||||||
|
}
|
||||||
|
|
||||||
|
return tags
|
||||||
|
}
|
||||||
|
|
||||||
|
func build_post(state: DamusState, post: NSMutableAttributedString, action: PostAction, uploadedMedias: [UploadedMedia], pubkeys: [Pubkey]) -> NostrPost {
|
||||||
post.enumerateAttributes(in: NSRange(location: 0, length: post.length), options: []) { attributes, range, stop in
|
post.enumerateAttributes(in: NSRange(location: 0, length: post.length), options: []) { attributes, range, stop in
|
||||||
if let link = attributes[.link] as? String {
|
if let link = attributes[.link] as? String {
|
||||||
let nextCharIndex = range.upperBound
|
let nextCharIndex = range.upperBound
|
||||||
@ -634,20 +667,35 @@ func build_post(state: DamusState, post: NSMutableAttributedString, action: Post
|
|||||||
|
|
||||||
let imagesString = uploadedMedias.map { $0.uploadedURL.absoluteString }.joined(separator: " ")
|
let imagesString = uploadedMedias.map { $0.uploadedURL.absoluteString }.joined(separator: " ")
|
||||||
|
|
||||||
var tags = uploadedMedias.compactMap { $0.metadata?.to_tag() }
|
|
||||||
|
|
||||||
if !imagesString.isEmpty {
|
if !imagesString.isEmpty {
|
||||||
content.append(" " + imagesString + " ")
|
content.append(" " + imagesString + " ")
|
||||||
}
|
}
|
||||||
|
|
||||||
if case .quoting(let ev) = action {
|
var tags: [[String]] = []
|
||||||
|
|
||||||
|
switch action {
|
||||||
|
case .replying_to(let replying_to):
|
||||||
|
// start off with the reply tags
|
||||||
|
tags = nip10_reply_tags(replying_to: replying_to, keypair: state.keypair)
|
||||||
|
|
||||||
|
case .quoting(let ev):
|
||||||
content.append(" nostr:" + bech32_note_id(ev.id))
|
content.append(" nostr:" + bech32_note_id(ev.id))
|
||||||
|
|
||||||
if let quoted_ev = state.events.lookup(ev.id) {
|
if let quoted_ev = state.events.lookup(ev.id) {
|
||||||
tags.append(["p", quoted_ev.pubkey.hex()])
|
tags.append(["p", quoted_ev.pubkey.hex()])
|
||||||
}
|
}
|
||||||
|
case .posting(let postTarget):
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
return NostrPost(content: content, references: references, kind: .text, tags: tags)
|
// include pubkeys
|
||||||
|
tags += pubkeys.map { pk in
|
||||||
|
["p", pk.hex()]
|
||||||
|
}
|
||||||
|
|
||||||
|
// append additional tags
|
||||||
|
tags += uploadedMedias.compactMap { $0.metadata?.to_tag() }
|
||||||
|
|
||||||
|
return NostrPost(content: content, kind: .text, tags: tags)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,17 +18,7 @@ struct UserSearch: View {
|
|||||||
|
|
||||||
var users: [Pubkey] {
|
var users: [Pubkey] {
|
||||||
guard let txn = NdbTxn(ndb: damus_state.ndb) else { return [] }
|
guard let txn = NdbTxn(ndb: damus_state.ndb) else { return [] }
|
||||||
return search_profiles(profiles: damus_state.profiles, search: search, txn: txn).sorted { a, b in
|
return search_profiles(profiles: damus_state.profiles, contacts: damus_state.contacts, search: search, txn: txn)
|
||||||
let aFriendTypePriority = get_friend_type(contacts: damus_state.contacts, pubkey: a)?.priority ?? 0
|
|
||||||
let bFriendTypePriority = get_friend_type(contacts: damus_state.contacts, pubkey: b)?.priority ?? 0
|
|
||||||
|
|
||||||
if aFriendTypePriority > bFriendTypePriority {
|
|
||||||
// `a` should be sorted before `b`
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func on_user_tapped(pk: Pubkey) {
|
func on_user_tapped(pk: Pubkey) {
|
||||||
|
@ -113,11 +113,11 @@ struct SearchResultsView: View {
|
|||||||
.frame(maxHeight: .infinity)
|
.frame(maxHeight: .infinity)
|
||||||
.onAppear {
|
.onAppear {
|
||||||
guard let txn = NdbTxn.init(ndb: damus_state.ndb) else { return }
|
guard let txn = NdbTxn.init(ndb: damus_state.ndb) else { return }
|
||||||
self.result = search_for_string(profiles: damus_state.profiles, search: search, txn: txn)
|
self.result = search_for_string(profiles: damus_state.profiles, contacts: damus_state.contacts, search: search, txn: txn)
|
||||||
}
|
}
|
||||||
.onChange(of: search) { new in
|
.onChange(of: search) { new in
|
||||||
guard let txn = NdbTxn.init(ndb: damus_state.ndb) else { return }
|
guard let txn = NdbTxn.init(ndb: damus_state.ndb) else { return }
|
||||||
self.result = search_for_string(profiles: damus_state.profiles, search: search, txn: txn)
|
self.result = search_for_string(profiles: damus_state.profiles, contacts: damus_state.contacts, search: search, txn: txn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -131,7 +131,7 @@ struct SearchResultsView_Previews: PreviewProvider {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
func search_for_string<Y>(profiles: Profiles, search new: String, txn: NdbTxn<Y>) -> Search? {
|
func search_for_string<Y>(profiles: Profiles, contacts: Contacts, search new: String, txn: NdbTxn<Y>) -> Search? {
|
||||||
guard new.count != 0 else {
|
guard new.count != 0 else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -174,7 +174,7 @@ func search_for_string<Y>(profiles: Profiles, search new: String, txn: NdbTxn<Y>
|
|||||||
return .naddr(naddr)
|
return .naddr(naddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
let multisearch = MultiSearch(hashtag: make_hashtagable(searchQuery), profiles: search_profiles(profiles: profiles, search: new, txn: txn))
|
let multisearch = MultiSearch(hashtag: make_hashtagable(searchQuery), profiles: search_profiles(profiles: profiles, contacts: contacts, search: new, txn: txn))
|
||||||
return .multi(multisearch)
|
return .multi(multisearch)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,7 +191,7 @@ func make_hashtagable(_ str: String) -> String {
|
|||||||
return String(new.filter{$0 != " "})
|
return String(new.filter{$0 != " "})
|
||||||
}
|
}
|
||||||
|
|
||||||
func search_profiles<Y>(profiles: Profiles, search: String, txn: NdbTxn<Y>) -> [Pubkey] {
|
func search_profiles<Y>(profiles: Profiles, contacts: Contacts, search: String, txn: NdbTxn<Y>) -> [Pubkey] {
|
||||||
// Search by hex pubkey.
|
// Search by hex pubkey.
|
||||||
if let pubkey = hex_decode_pubkey(search),
|
if let pubkey = hex_decode_pubkey(search),
|
||||||
profiles.lookup_key_by_pubkey(pubkey) != nil
|
profiles.lookup_key_by_pubkey(pubkey) != nil
|
||||||
@ -208,8 +208,16 @@ func search_profiles<Y>(profiles: Profiles, search: String, txn: NdbTxn<Y>) -> [
|
|||||||
return [pk]
|
return [pk]
|
||||||
}
|
}
|
||||||
|
|
||||||
let new = search.lowercased()
|
return profiles.search(search, limit: 10, txn: txn).sorted { a, b in
|
||||||
|
let aFriendTypePriority = get_friend_type(contacts: contacts, pubkey: a)?.priority ?? 0
|
||||||
|
let bFriendTypePriority = get_friend_type(contacts: contacts, pubkey: b)?.priority ?? 0
|
||||||
|
|
||||||
return profiles.search(search, limit: 10, txn: txn)
|
if aFriendTypePriority > bFriendTypePriority {
|
||||||
|
// `a` should be sorted before `b`
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,10 +13,10 @@ struct InnerTimelineView: View {
|
|||||||
let state: DamusState
|
let state: DamusState
|
||||||
let filter: (NostrEvent) -> Bool
|
let filter: (NostrEvent) -> Bool
|
||||||
|
|
||||||
init(events: EventHolder, damus: DamusState, filter: @escaping (NostrEvent) -> Bool) {
|
init(events: EventHolder, damus: DamusState, filter: @escaping (NostrEvent) -> Bool, apply_mute_rules: Bool = true) {
|
||||||
self.events = events
|
self.events = events
|
||||||
self.state = damus
|
self.state = damus
|
||||||
self.filter = filter
|
self.filter = apply_mute_rules ? { filter($0) && !damus.mutelist_manager.is_event_muted($0) } : filter
|
||||||
}
|
}
|
||||||
|
|
||||||
var event_options: EventViewOptions {
|
var event_options: EventViewOptions {
|
||||||
|
@ -15,15 +15,15 @@ struct TimelineView<Content: View>: View {
|
|||||||
let show_friend_icon: Bool
|
let show_friend_icon: Bool
|
||||||
let filter: (NostrEvent) -> Bool
|
let filter: (NostrEvent) -> Bool
|
||||||
let content: Content?
|
let content: Content?
|
||||||
let debouncer: Debouncer
|
let apply_mute_rules: Bool
|
||||||
|
|
||||||
init(events: EventHolder, loading: Binding<Bool>, damus: DamusState, show_friend_icon: Bool, filter: @escaping (NostrEvent) -> Bool, content: (() -> Content)? = nil) {
|
init(events: EventHolder, loading: Binding<Bool>, damus: DamusState, show_friend_icon: Bool, filter: @escaping (NostrEvent) -> Bool, apply_mute_rules: Bool = true, content: (() -> Content)? = nil) {
|
||||||
self.events = events
|
self.events = events
|
||||||
self._loading = loading
|
self._loading = loading
|
||||||
self.damus = damus
|
self.damus = damus
|
||||||
self.show_friend_icon = show_friend_icon
|
self.show_friend_icon = show_friend_icon
|
||||||
self.filter = filter
|
self.filter = filter
|
||||||
self.debouncer = Debouncer(interval: 0.5)
|
self.apply_mute_rules = apply_mute_rules
|
||||||
self.content = content?()
|
self.content = content?()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,14 +42,12 @@ struct TimelineView<Content: View>: View {
|
|||||||
.id("startblock")
|
.id("startblock")
|
||||||
.frame(height: 1)
|
.frame(height: 1)
|
||||||
|
|
||||||
InnerTimelineView(events: events, damus: damus, filter: loading ? { _ in true } : filter)
|
InnerTimelineView(events: events, damus: damus, filter: loading ? { _ in true } : filter, apply_mute_rules: self.apply_mute_rules)
|
||||||
.redacted(reason: loading ? .placeholder : [])
|
.redacted(reason: loading ? .placeholder : [])
|
||||||
.shimmer(loading)
|
.shimmer(loading)
|
||||||
.disabled(loading)
|
.disabled(loading)
|
||||||
.background(GeometryReader { proxy -> Color in
|
.background(GeometryReader { proxy -> Color in
|
||||||
debouncer.debounce_immediate {
|
|
||||||
handle_scroll_queue(proxy, queue: self.events)
|
handle_scroll_queue(proxy, queue: self.events)
|
||||||
}
|
|
||||||
return Color.clear
|
return Color.clear
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
BIN
damus/th.lproj/InfoPlist.strings
Normal file
BIN
damus/th.lproj/InfoPlist.strings
Normal file
Binary file not shown.
BIN
damus/th.lproj/Localizable.strings
Normal file
BIN
damus/th.lproj/Localizable.strings
Normal file
Binary file not shown.
356
damus/th.lproj/Localizable.stringsdict
Normal file
356
damus/th.lproj/Localizable.stringsdict
Normal file
@ -0,0 +1,356 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>followed_by_three_and_others</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@OTHERS@</string>
|
||||||
|
<key>OTHERS</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>d</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>ผู้ติดตามโดย %2$@, %3$@, %4$@ & %1$d คนอื่นๆ</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>followers_count</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@FOLLOWERS@</string>
|
||||||
|
<key>FOLLOWERS</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>d</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>ผู้ติดตาม</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>following_count</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@FOLLOWING@</string>
|
||||||
|
<key>FOLLOWING</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>d</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>กำลังติดตาม</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>imports_count</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@IMPORTS@</string>
|
||||||
|
<key>IMPORTS</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>d</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>นำเข้า</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>reacted_tagged_in_3</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@REACTED@</string>
|
||||||
|
<key>REACTED</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>d</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%2$@ และอีก %1$d คน react ต่อโน้ตที่คุณถูกแท็ก</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>reacted_your_note_3</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@REACTED@</string>
|
||||||
|
<key>REACTED</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>d</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%2$@ และอีก %1$d คน react ต่อโน้ตของคุณ</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>reacted_your_profile_3</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@REACTED@</string>
|
||||||
|
<key>REACTED</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>d</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%2$@ และอีก %1$d คน react ต่อโปรไฟล์ของคุณ</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>reactions_count</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@REACTIONS@</string>
|
||||||
|
<key>REACTIONS</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>d</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>Reactions</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>relays_count</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@RELAYS@</string>
|
||||||
|
<key>RELAYS</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>d</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>รีเลย์</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>replying_to_two_and_others</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@OTHERS@</string>
|
||||||
|
<key>OTHERS</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>d</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>ตอบกลับ %2$@, %3$@ & %1$d คนอื่นๆ</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>reposted_tagged_in_3</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@REPOSTED@</string>
|
||||||
|
<key>REPOSTED</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>d</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%2$@ และอีก %1$d คนรีโพสต์โน้ตที่คุณถูกแท็ก</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>reposted_your_note_3</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@REPOSTED@</string>
|
||||||
|
<key>REPOSTED</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>d</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%2$@ และอีก %1$d คนรีโพสต์โน้ตของคุณ</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>reposted_your_profile_3</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@REPOSTED@</string>
|
||||||
|
<key>REPOSTED</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>d</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%2$@ และอีก %1$d คนรีโพสต์โปรไฟล์ของคุณ</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>reposts_count</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@REPOSTS@</string>
|
||||||
|
<key>REPOSTS</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>d</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>รีโพสต์</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>quoted_reposts_count</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@QUOTE_REPOSTS@</string>
|
||||||
|
<key>QUOTE_REPOSTS</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>d</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>คำพูด</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>sats</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@SATS@</string>
|
||||||
|
<key>SATS</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>d</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>sats</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>sats_count</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%1$#@SATS@</string>
|
||||||
|
<key>SATS</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>@</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%2$@ sats</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>users_talking_about_it</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@USERS@</string>
|
||||||
|
<key>USERS</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>d</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%d ผู้ใช้กำลังพูดถึงเรื่องนี้</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>word_count</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@WORDS@</string>
|
||||||
|
<key>WORDS</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>d</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%d คำ</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>zap_notification_no_message</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%1$#@NOTIFICATION@</string>
|
||||||
|
<key>NOTIFICATION</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>@</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>คุณได้รับ %2$@ sats จาก %3$@</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>zap_notification_with_message</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%1$#@NOTIFICATION@</string>
|
||||||
|
<key>NOTIFICATION</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>@</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>คุณได้รับ %2$@ sats จาก %3$@: "%4$@"</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>zapped_tagged_in_3</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@ZAPPED@</string>
|
||||||
|
<key>ZAPPED</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>d</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%2$@ และอีก %1$d คน Zap โน้ตที่คุณถูกแท็ก</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>zapped_your_note_3</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@ZAPPED@</string>
|
||||||
|
<key>ZAPPED</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>d</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%2$@ และอีก %1$d คน Zap โน้ตของคุณ</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>zapped_your_profile_3</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@ZAPPED@</string>
|
||||||
|
<key>ZAPPED</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>d</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%2$@ และอีก %1$d คน Zap คุณ</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>zaps_count</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@ZAPS@</string>
|
||||||
|
<key>ZAPS</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>d</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>Zaps</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
Binary file not shown.
@ -198,6 +198,20 @@
|
|||||||
<string>Đăng lại</string>
|
<string>Đăng lại</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
|
<key>quoted_reposts_count</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@QUOTE_REPOSTS@</string>
|
||||||
|
<key>QUOTE_REPOSTS</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>d</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>Trích dẫn</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
<key>sats</key>
|
<key>sats</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
Binary file not shown.
@ -198,6 +198,20 @@
|
|||||||
<string>转发</string>
|
<string>转发</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
|
<key>quoted_reposts_count</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@QUOTE_REPOSTS@</string>
|
||||||
|
<key>QUOTE_REPOSTS</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>d</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>引用</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
<key>sats</key>
|
<key>sats</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
Binary file not shown.
@ -198,6 +198,20 @@
|
|||||||
<string>轉發</string>
|
<string>轉發</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
|
<key>quoted_reposts_count</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@QUOTE_REPOSTS@</string>
|
||||||
|
<key>QUOTE_REPOSTS</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>d</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>引用</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
<key>sats</key>
|
<key>sats</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
Binary file not shown.
@ -198,6 +198,20 @@
|
|||||||
<string>轉發</string>
|
<string>轉發</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
|
<key>quoted_reposts_count</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@QUOTE_REPOSTS@</string>
|
||||||
|
<key>QUOTE_REPOSTS</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>d</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>引用</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
<key>sats</key>
|
<key>sats</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
@ -9,6 +9,7 @@ import XCTest
|
|||||||
@testable import damus
|
@testable import damus
|
||||||
|
|
||||||
final class AuthIntegrationTests: XCTestCase {
|
final class AuthIntegrationTests: XCTestCase {
|
||||||
|
/*
|
||||||
func testAuthIntegrationFilterNostrWine() {
|
func testAuthIntegrationFilterNostrWine() {
|
||||||
// Create relay pool and connect to `wss://filter.nostr.wine`
|
// Create relay pool and connect to `wss://filter.nostr.wine`
|
||||||
let relay_url = RelayURL("wss://filter.nostr.wine")!
|
let relay_url = RelayURL("wss://filter.nostr.wine")!
|
||||||
@ -67,6 +68,7 @@ final class AuthIntegrationTests: XCTestCase {
|
|||||||
XCTAssertEqual(sent_msg["kind"] as! Int, 22242)
|
XCTAssertEqual(sent_msg["kind"] as! Int, 22242)
|
||||||
XCTAssertEqual((sent_msg["tags"] as! [[String]]).first { $0[0] == "challenge" }![1], json_received[1] as! String)
|
XCTAssertEqual((sent_msg["tags"] as! [[String]]).first { $0[0] == "challenge" }![1], json_received[1] as! String)
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
func testAuthIntegrationRelayDamusIo() {
|
func testAuthIntegrationRelayDamusIo() {
|
||||||
// Create relay pool and connect to `wss://relay.damus.io`
|
// Create relay pool and connect to `wss://relay.damus.io`
|
||||||
|
@ -25,7 +25,7 @@ func generate_test_damus_state(
|
|||||||
return profiles
|
return profiles
|
||||||
}()
|
}()
|
||||||
|
|
||||||
let mutelist_manager = MutelistManager()
|
let mutelist_manager = MutelistManager(user_keypair: test_keypair)
|
||||||
let damus = DamusState(pool: pool,
|
let damus = DamusState(pool: pool,
|
||||||
keypair: test_keypair,
|
keypair: test_keypair,
|
||||||
likes: .init(our_pubkey: our_pubkey),
|
likes: .init(our_pubkey: our_pubkey),
|
||||||
|
43
damusTests/MutingTests.swift
Normal file
43
damusTests/MutingTests.swift
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
//
|
||||||
|
// MutingTests.swift
|
||||||
|
// damusTests
|
||||||
|
//
|
||||||
|
// Created by Daniel D’Aquino on 2024-05-06.
|
||||||
|
//
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
import XCTest
|
||||||
|
@testable import damus
|
||||||
|
|
||||||
|
final class MutingTests: XCTestCase {
|
||||||
|
func testWordMuting() {
|
||||||
|
// Setup some test data
|
||||||
|
let test_note = NostrEvent(
|
||||||
|
content: "Nostr is the super app. Because it’s actually an ecosystem of apps, all of which make each other better. People haven’t grasped that yet. They will when it’s more accessible and onboarding is more straightforward and intuitive.",
|
||||||
|
keypair: jack_keypair,
|
||||||
|
createdAt: UInt32(Date().timeIntervalSince1970 - 100)
|
||||||
|
)!
|
||||||
|
let spammy_keypair = generate_new_keypair().to_keypair()
|
||||||
|
let spammy_test_note = NostrEvent(
|
||||||
|
content: "Some spammy airdrop just arrived! Why stack sats when you can get scammed instead with some random coin? Call 1-800-GET-SCAMMED to claim your airdrop today!",
|
||||||
|
keypair: spammy_keypair,
|
||||||
|
createdAt: UInt32(Date().timeIntervalSince1970 - 100)
|
||||||
|
)!
|
||||||
|
|
||||||
|
let mute_item: MuteItem = .word("airdrop", nil)
|
||||||
|
let existing_mutelist = test_damus_state.mutelist_manager.event
|
||||||
|
|
||||||
|
guard
|
||||||
|
let full_keypair = test_damus_state.keypair.to_full(),
|
||||||
|
let mutelist = create_or_update_mutelist(keypair: full_keypair, mprev: existing_mutelist, to_add: mute_item)
|
||||||
|
else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
test_damus_state.mutelist_manager.set_mutelist(mutelist)
|
||||||
|
test_damus_state.postbox.send(mutelist)
|
||||||
|
|
||||||
|
XCTAssert(test_damus_state.mutelist_manager.is_event_muted(spammy_test_note))
|
||||||
|
XCTAssertFalse(test_damus_state.mutelist_manager.is_event_muted(test_note))
|
||||||
|
}
|
||||||
|
}
|
272
damusTests/NIP10Tests.swift
Normal file
272
damusTests/NIP10Tests.swift
Normal file
@ -0,0 +1,272 @@
|
|||||||
|
//
|
||||||
|
// NIP10Tests.swift
|
||||||
|
// damusTests
|
||||||
|
//
|
||||||
|
// Created by William Casarin on 2024-04-25.
|
||||||
|
//
|
||||||
|
|
||||||
|
import XCTest
|
||||||
|
@testable import damus
|
||||||
|
|
||||||
|
final class NIP10Tests: XCTestCase {
|
||||||
|
|
||||||
|
override func setUpWithError() throws {
|
||||||
|
// Put setup code here. This method is called before the invocation of each test method in the class.
|
||||||
|
}
|
||||||
|
|
||||||
|
override func tearDownWithError() throws {
|
||||||
|
// Put teardown code here. This method is called after the invocation of each test method in the class.
|
||||||
|
}
|
||||||
|
|
||||||
|
func testExample() throws {
|
||||||
|
// This is an example of a functional test case.
|
||||||
|
// Use XCTAssert and related functions to verify your tests produce the correct results.
|
||||||
|
// Any test you write for XCTest can be annotated as throws and async.
|
||||||
|
// Mark your test throws to produce an unexpected failure when your test encounters an uncaught error.
|
||||||
|
// Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards.
|
||||||
|
}
|
||||||
|
|
||||||
|
func test_new_nip10() {
|
||||||
|
let root_note_id_hex = "7c7d37bc8c04d2ec65cbc7d9275253e6b5cc34b5d10439f158194a3feefa8d52"
|
||||||
|
let direct_reply_hex = "7c7d37bc8c04d2ec65cbc7d9275253e6b5cc34b5d10439f158194a3feefa8d51"
|
||||||
|
let reply_hex = "7c7d37bc8c04d2ec65cbc7d9275253e6b5cc34b5d10439f158194a3feefa8d53"
|
||||||
|
|
||||||
|
let tags = [
|
||||||
|
["e", direct_reply_hex, "", "reply"],
|
||||||
|
["e", root_note_id_hex, "", "root"],
|
||||||
|
["e", reply_hex, "", "reply"],
|
||||||
|
["e", "7c7d37bc8c04d2ec65cbc7d9275253e6b5cc34b5d10439f158194a3feefa8d54", "", "mention"],
|
||||||
|
]
|
||||||
|
|
||||||
|
let root_note_id = NoteId(hex: root_note_id_hex)!
|
||||||
|
let direct_reply_id = NoteId(hex: direct_reply_hex)!
|
||||||
|
let reply_id = NoteId(hex: reply_hex)!
|
||||||
|
|
||||||
|
let note = NdbNote(content: "hi", keypair: test_keypair, kind: 1, tags: tags)!
|
||||||
|
let refs = interp_event_refs_without_mentions_ndb(note.referenced_noterefs)
|
||||||
|
|
||||||
|
XCTAssertEqual(refs.reduce(into: Array<NoteId>(), { xs, r in
|
||||||
|
if let note_id = r.is_thread_id?.note_id { xs.append(note_id) }
|
||||||
|
}), [root_note_id])
|
||||||
|
|
||||||
|
XCTAssertEqual(refs.reduce(into: Array<NoteId>(), { xs, r in
|
||||||
|
if let note_id = r.is_direct_reply?.note_id { xs.append(note_id) }
|
||||||
|
}), [direct_reply_id, reply_id])
|
||||||
|
|
||||||
|
XCTAssertEqual(refs.reduce(into: Array<NoteId>(), { xs, r in
|
||||||
|
if let note_id = r.is_reply?.note_id { xs.append(note_id) }
|
||||||
|
}), [direct_reply_id, reply_id])
|
||||||
|
}
|
||||||
|
|
||||||
|
func test_repost_root() {
|
||||||
|
let mention_hex = "7c7d37bc8c04d2ec65cbc7d9275253e6b5cc34b5d10439f158194a3feefa8d52"
|
||||||
|
let tags = [
|
||||||
|
["e", mention_hex, "", "mention"],
|
||||||
|
]
|
||||||
|
|
||||||
|
let mention_id = NoteId(hex: mention_hex)!
|
||||||
|
let note = NdbNote(content: "hi", keypair: test_keypair, kind: 1, tags: tags)!
|
||||||
|
let refs = interp_event_refs_without_mentions_ndb(note.referenced_noterefs)
|
||||||
|
|
||||||
|
XCTAssertEqual(refs.reduce(into: Array<NoteId>(), { xs, r in
|
||||||
|
if let note_id = r.is_thread_id?.note_id { xs.append(note_id) }
|
||||||
|
}), [])
|
||||||
|
|
||||||
|
XCTAssertEqual(refs.reduce(into: Array<NoteId>(), { xs, r in
|
||||||
|
if let note_id = r.is_direct_reply?.note_id { xs.append(note_id) }
|
||||||
|
}), [])
|
||||||
|
|
||||||
|
XCTAssertEqual(refs.reduce(into: Array<NoteId>(), { xs, r in
|
||||||
|
if let note_id = r.is_reply?.note_id { xs.append(note_id) }
|
||||||
|
}), [])
|
||||||
|
}
|
||||||
|
|
||||||
|
func test_direct_reply_old_nip10() {
|
||||||
|
let root_note_id_hex = "7c7d37bc8c04d2ec65cbc7d9275253e6b5cc34b5d10439f158194a3feefa8d52"
|
||||||
|
let tags = [
|
||||||
|
["e", root_note_id_hex],
|
||||||
|
]
|
||||||
|
|
||||||
|
let root_note_id = NoteId(hex: root_note_id_hex)!
|
||||||
|
|
||||||
|
let note = NdbNote(content: "hi", keypair: test_keypair, kind: 1, tags: tags)!
|
||||||
|
let refs = interp_event_refs_without_mentions_ndb(note.referenced_noterefs)
|
||||||
|
|
||||||
|
XCTAssertEqual(refs.reduce(into: Array<NoteId>(), { xs, r in
|
||||||
|
if let note_id = r.is_thread_id?.note_id { xs.append(note_id) }
|
||||||
|
}), [root_note_id])
|
||||||
|
|
||||||
|
XCTAssertEqual(refs.reduce(into: Array<NoteId>(), { xs, r in
|
||||||
|
if let note_id = r.is_direct_reply?.note_id { xs.append(note_id) }
|
||||||
|
}), [root_note_id])
|
||||||
|
|
||||||
|
XCTAssertEqual(refs.reduce(into: Array<NoteId>(), { xs, r in
|
||||||
|
if let note_id = r.is_reply?.note_id { xs.append(note_id) }
|
||||||
|
}), [root_note_id])
|
||||||
|
}
|
||||||
|
|
||||||
|
func test_direct_reply_new_nip10() {
|
||||||
|
let root_note_id_hex = "7c7d37bc8c04d2ec65cbc7d9275253e6b5cc34b5d10439f158194a3feefa8d52"
|
||||||
|
let tags = [
|
||||||
|
["e", root_note_id_hex, "", "root"],
|
||||||
|
]
|
||||||
|
|
||||||
|
let root_note_id = NoteId(hex: root_note_id_hex)!
|
||||||
|
|
||||||
|
let note = NdbNote(content: "hi", keypair: test_keypair, kind: 1, tags: tags)!
|
||||||
|
let refs = interp_event_refs_without_mentions_ndb(note.referenced_noterefs)
|
||||||
|
|
||||||
|
XCTAssertEqual(refs.reduce(into: Array<NoteId>(), { xs, r in
|
||||||
|
if let note_id = r.is_thread_id?.note_id { xs.append(note_id) }
|
||||||
|
}), [root_note_id])
|
||||||
|
|
||||||
|
XCTAssertEqual(refs.reduce(into: Array<NoteId>(), { xs, r in
|
||||||
|
if let note_id = r.is_direct_reply?.note_id { xs.append(note_id) }
|
||||||
|
}), [root_note_id])
|
||||||
|
|
||||||
|
XCTAssertEqual(refs.reduce(into: Array<NoteId>(), { xs, r in
|
||||||
|
if let note_id = r.is_reply?.note_id { xs.append(note_id) }
|
||||||
|
}), [root_note_id])
|
||||||
|
|
||||||
|
let nip10 = note.thread_reply(test_keypair)!
|
||||||
|
XCTAssertEqual(nip10.is_reply_to_root, true)
|
||||||
|
XCTAssertEqual(nip10.root.note_id, root_note_id)
|
||||||
|
XCTAssertEqual(nip10.reply!.note_id, root_note_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// seen in the wild by the gleasonator
|
||||||
|
func test_single_marker() {
|
||||||
|
let root_note_id_hex = "7c7d37bc8c04d2ec65cbc7d9275253e6b5cc34b5d10439f158194a3feefa8d52"
|
||||||
|
let tags = [
|
||||||
|
["e", root_note_id_hex, "", "reply"],
|
||||||
|
]
|
||||||
|
|
||||||
|
let root_note_id = NoteId(hex: root_note_id_hex)!
|
||||||
|
let note = NdbNote(content: "hi", keypair: test_keypair, kind: 1, tags: tags)!
|
||||||
|
let refs = interp_event_refs_without_mentions_ndb(note.referenced_noterefs)
|
||||||
|
let thread_reply = ThreadReply(event_refs: refs)!
|
||||||
|
|
||||||
|
XCTAssertEqual(thread_reply.mention, nil)
|
||||||
|
XCTAssertEqual(thread_reply.root.note_id, root_note_id)
|
||||||
|
XCTAssertEqual(thread_reply.reply!.note_id, root_note_id)
|
||||||
|
XCTAssertEqual(thread_reply.is_reply_to_root, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func test_marker_reply() {
|
||||||
|
let note_json = """
|
||||||
|
{
|
||||||
|
"pubkey": "5b0183ab6c3e322bf4d41c6b3aef98562a144847b7499543727c5539a114563e",
|
||||||
|
"content": "Can’t zap you btw",
|
||||||
|
"id": "a8dc8b74852d7ad114d5d650b2125459c0cba3c1fdcaaf527e03f24082e11ab3",
|
||||||
|
"created_at": 1715275773,
|
||||||
|
"sig": "4ee5d8f954c6c087ce51ad02d30dd226eea939cd9ef4e8a8ce4bfaf3aba0a852316cfda83ce3fc9a3d98392a738e7c6b036a3b2aced1392db1be3ca190835a17",
|
||||||
|
"kind": 1,
|
||||||
|
"tags": [
|
||||||
|
[
|
||||||
|
"e",
|
||||||
|
"1bb940ce0ba0d4a3b2a589355d908498dcd7452f941cf520072218f7e6ede75e",
|
||||||
|
"wss://relay.nostrplebs.com",
|
||||||
|
"reply"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"p",
|
||||||
|
"6e75f7972397ca3295e0f4ca0fbc6eb9cc79be85bafdd56bd378220ca8eee74e"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"e",
|
||||||
|
"00152d2945459fb394fed2ea95af879c903c4ec42d96327a739fa27c023f20e0",
|
||||||
|
"wss://nostr.mutinywallet.com/",
|
||||||
|
"root"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
|
||||||
|
let replying_to_hex = "a8dc8b74852d7ad114d5d650b2125459c0cba3c1fdcaaf527e03f24082e11ab3"
|
||||||
|
let pk = Pubkey(hex: "5b0183ab6c3e322bf4d41c6b3aef98562a144847b7499543727c5539a114563e")!
|
||||||
|
let last_reply_hex = "1bb940ce0ba0d4a3b2a589355d908498dcd7452f941cf520072218f7e6ede75e"
|
||||||
|
let note = decode_nostr_event_json(json: note_json)!
|
||||||
|
let reply = build_post(state: test_damus_state, post: .init(string: "hello"), action: .replying_to(note), uploadedMedias: [], pubkeys: [pk] + note.referenced_pubkeys.map({pk in pk}))
|
||||||
|
let root_hex = "00152d2945459fb394fed2ea95af879c903c4ec42d96327a739fa27c023f20e0"
|
||||||
|
|
||||||
|
XCTAssertEqual(reply.tags,
|
||||||
|
[
|
||||||
|
["e", root_hex, "wss://nostr.mutinywallet.com/", "root"],
|
||||||
|
["e", replying_to_hex, "", "reply"],
|
||||||
|
["e", last_reply_hex, "wss://relay.nostrplebs.com"],
|
||||||
|
["p", "5b0183ab6c3e322bf4d41c6b3aef98562a144847b7499543727c5539a114563e"],
|
||||||
|
["p", "6e75f7972397ca3295e0f4ca0fbc6eb9cc79be85bafdd56bd378220ca8eee74e"],
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
func test_mixed_nip10() {
|
||||||
|
|
||||||
|
let root_note_id_hex = "27e71cf53299dafb5dc7bcc0a078357418a4375cb1097bf5184662493f79a627"
|
||||||
|
let reply_hex = "1a616998552cf76e9786f76ac68f6104cdae46377330735c68bfe0b9426d2fa8"
|
||||||
|
|
||||||
|
let tags = [
|
||||||
|
[ "e", root_note_id_hex, "", "root" ],
|
||||||
|
[ "e", "f99046bd87be7508d55e139de48517c06ef90830d77a5d3213df858d77bb2f8f" ],
|
||||||
|
[ "e", reply_hex, "", "reply" ],
|
||||||
|
[ "p", "3efdaebb1d8923ebd99c9e7ace3b4194ab45512e2be79c1b7d68d9243e0d2681" ],
|
||||||
|
[ "p", "8ea485266b2285463b13bf835907161c22bb3da1e652b443db14f9cee6720a43" ],
|
||||||
|
[ "p", "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245" ]
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
let root_note_id = NoteId(hex: root_note_id_hex)!
|
||||||
|
let reply_id = NoteId(hex: reply_hex)!
|
||||||
|
|
||||||
|
let note = NdbNote(content: "hi", keypair: test_keypair, kind: 1, tags: tags)!
|
||||||
|
let refs = interp_event_refs_without_mentions_ndb(note.referenced_noterefs)
|
||||||
|
|
||||||
|
XCTAssertEqual(refs.reduce(into: Array<NoteId>(), { xs, r in
|
||||||
|
if let note_id = r.is_thread_id?.note_id { xs.append(note_id) }
|
||||||
|
}), [root_note_id])
|
||||||
|
|
||||||
|
XCTAssertEqual(refs.reduce(into: Array<NoteId>(), { xs, r in
|
||||||
|
if let note_id = r.is_reply?.note_id { xs.append(note_id) }
|
||||||
|
}), [reply_id])
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func test_deprecated_nip10() {
|
||||||
|
let root_note_id_hex = "7c7d37bc8c04d2ec65cbc7d9275253e6b5cc34b5d10439f158194a3feefa8d52"
|
||||||
|
let direct_reply_hex = "7c7d37bc8c04d2ec65cbc7d9275253e6b5cc34b5d10439f158194a3feefa8d51"
|
||||||
|
let reply_hex = "7c7d37bc8c04d2ec65cbc7d9275253e6b5cc34b5d10439f158194a3feefa8d53"
|
||||||
|
let tags = [
|
||||||
|
["e", root_note_id_hex],
|
||||||
|
["e", direct_reply_hex],
|
||||||
|
["e", reply_hex],
|
||||||
|
]
|
||||||
|
|
||||||
|
let root_note_id = NoteId(hex: root_note_id_hex)!
|
||||||
|
let direct_reply_id = NoteId(hex: direct_reply_hex)!
|
||||||
|
let reply_id = NoteId(hex: reply_hex)!
|
||||||
|
|
||||||
|
let note = NdbNote(content: "hi", keypair: test_keypair, kind: 1, tags: tags)!
|
||||||
|
let refs = interp_event_refs_without_mentions_ndb(note.referenced_noterefs)
|
||||||
|
|
||||||
|
XCTAssertEqual(refs.reduce(into: Array<NoteId>(), { xs, r in
|
||||||
|
if let note_id = r.is_thread_id?.note_id { xs.append(note_id) }
|
||||||
|
}), [root_note_id])
|
||||||
|
|
||||||
|
XCTAssertEqual(refs.reduce(into: Array<NoteId>(), { xs, r in
|
||||||
|
if let note_id = r.is_direct_reply?.note_id { xs.append(note_id) }
|
||||||
|
}), [direct_reply_id, reply_id])
|
||||||
|
|
||||||
|
XCTAssertEqual(refs.reduce(into: Array<NoteId>(), { xs, r in
|
||||||
|
if let note_id = r.is_reply?.note_id { xs.append(note_id) }
|
||||||
|
}), [direct_reply_id, reply_id])
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
func testPerformanceExample() throws {
|
||||||
|
// This is an example of a performance test case.
|
||||||
|
self.measure {
|
||||||
|
// Put the code you want to measure the time of here.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -123,7 +123,7 @@ class ReplyTests: XCTestCase {
|
|||||||
post.append(user_tag_attr_string(profile: profile, pubkey: pk))
|
post.append(user_tag_attr_string(profile: profile, pubkey: pk))
|
||||||
post.append(.init(string: "\n"))
|
post.append(.init(string: "\n"))
|
||||||
|
|
||||||
let post_note = build_post(state: test_damus_state, post: post, action: .posting(.none), uploadedMedias: [], references: [.pubkey(pk)])
|
let post_note = build_post(state: test_damus_state, post: post, action: .posting(.none), uploadedMedias: [], pubkeys: [pk])
|
||||||
|
|
||||||
let expected_render = "nostr:\(pk.npub)\nnostr:\(pk.npub)"
|
let expected_render = "nostr:\(pk.npub)\nnostr:\(pk.npub)"
|
||||||
XCTAssertEqual(post_note.content, expected_render)
|
XCTAssertEqual(post_note.content, expected_render)
|
||||||
@ -315,7 +315,7 @@ class ReplyTests: XCTestCase {
|
|||||||
let pk = Pubkey(hex: "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245")!
|
let pk = Pubkey(hex: "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245")!
|
||||||
let content = "this is a @\(pk.npub) mention"
|
let content = "this is a @\(pk.npub) mention"
|
||||||
let blocks = parse_post_blocks(content: content)
|
let blocks = parse_post_blocks(content: content)
|
||||||
let post = NostrPost(content: content, references: [.event(evid)])
|
let post = NostrPost(content: content, tags: [["e", evid.hex()]])
|
||||||
let ev = post_to_event(post: post, keypair: test_keypair_full)!
|
let ev = post_to_event(post: post, keypair: test_keypair_full)!
|
||||||
|
|
||||||
XCTAssertEqual(ev.tags.count, 2)
|
XCTAssertEqual(ev.tags.count, 2)
|
||||||
@ -330,7 +330,7 @@ class ReplyTests: XCTestCase {
|
|||||||
let nsec = "nsec1jmzdz7d0ldqctdxwm5fzue277ttng2pk28n2u8wntc2r4a0w96ssnyukg7"
|
let nsec = "nsec1jmzdz7d0ldqctdxwm5fzue277ttng2pk28n2u8wntc2r4a0w96ssnyukg7"
|
||||||
let content = "this is a @\(nsec) mention"
|
let content = "this is a @\(nsec) mention"
|
||||||
let blocks = parse_post_blocks(content: content)
|
let blocks = parse_post_blocks(content: content)
|
||||||
let post = NostrPost(content: content, references: [.event(evid)])
|
let post = NostrPost(content: content, tags: [["e", evid.hex()]])
|
||||||
let ev = post_to_event(post: post, keypair: test_keypair_full)!
|
let ev = post_to_event(post: post, keypair: test_keypair_full)!
|
||||||
|
|
||||||
XCTAssertEqual(ev.tags.count, 2)
|
XCTAssertEqual(ev.tags.count, 2)
|
||||||
@ -344,13 +344,13 @@ class ReplyTests: XCTestCase {
|
|||||||
let thread_id = NoteId(hex: "a250fc93570c3e87f9c9b08d6b3ef7b8e05d346df8a52c69e30ffecdb178fb9e")!
|
let thread_id = NoteId(hex: "a250fc93570c3e87f9c9b08d6b3ef7b8e05d346df8a52c69e30ffecdb178fb9e")!
|
||||||
let reply_id = NoteId(hex: "9a180a10f16dac9566543ad1fc29616aab272b0cf123ab5d58843e16f4ef03a3")!
|
let reply_id = NoteId(hex: "9a180a10f16dac9566543ad1fc29616aab272b0cf123ab5d58843e16f4ef03a3")!
|
||||||
|
|
||||||
let refs: [RefId] = [
|
let tags = [
|
||||||
.event(thread_id),
|
["e", thread_id.hex()],
|
||||||
.event(reply_id),
|
["e", reply_id.hex()],
|
||||||
.pubkey(pubkey)
|
["p", pubkey.hex()]
|
||||||
]
|
]
|
||||||
|
|
||||||
let post = NostrPost(content: "this is a (@\(pubkey.npub)) mention", references: refs)
|
let post = NostrPost(content: "this is a (@\(pubkey.npub)) mention", tags: tags)
|
||||||
let ev = post_to_event(post: post, keypair: test_keypair_full)!
|
let ev = post_to_event(post: post, keypair: test_keypair_full)!
|
||||||
|
|
||||||
XCTAssertEqual(ev.content, "this is a (nostr:\(pubkey.npub)) mention")
|
XCTAssertEqual(ev.content, "this is a (nostr:\(pubkey.npub)) mention")
|
||||||
|
@ -192,7 +192,7 @@ class damusTests: XCTestCase {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
func testMakeHashtagPost() {
|
func testMakeHashtagPost() {
|
||||||
let post = NostrPost(content: "#damus some content #bitcoin derp #かっこいい wow", references: [])
|
let post = NostrPost(content: "#damus some content #bitcoin derp #かっこいい wow", tags: [])
|
||||||
let ev = post_to_event(post: post, keypair: test_keypair_full)!
|
let ev = post_to_event(post: post, keypair: test_keypair_full)!
|
||||||
|
|
||||||
XCTAssertEqual(ev.tags.count, 3)
|
XCTAssertEqual(ev.tags.count, 3)
|
||||||
@ -269,7 +269,7 @@ class damusTests: XCTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func createEventFromContentString(_ content: String) -> NostrEvent {
|
private func createEventFromContentString(_ content: String) -> NostrEvent {
|
||||||
let post = NostrPost(content: content, references: [])
|
let post = NostrPost(content: content, tags: [])
|
||||||
guard let ev = post_to_event(post: post, keypair: test_keypair_full) else {
|
guard let ev = post_to_event(post: post, keypair: test_keypair_full) else {
|
||||||
XCTFail("Could not create event")
|
XCTFail("Could not create event")
|
||||||
return test_note
|
return test_note
|
||||||
|
@ -340,9 +340,8 @@ extension NdbNote {
|
|||||||
References<RefId>(tags: self.tags)
|
References<RefId>(tags: self.tags)
|
||||||
}
|
}
|
||||||
|
|
||||||
func event_refs(_ keypair: Keypair) -> [EventRef] {
|
func thread_reply(_ keypair: Keypair) -> ThreadReply? {
|
||||||
let refs = interpret_event_refs_ndb(blocks: self.blocks(keypair).blocks, tags: self.tags)
|
ThreadReply(event_refs: interpret_event_refs_ndb(blocks: self.blocks(keypair).blocks, tags: self.tags))
|
||||||
return refs
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func get_content(_ keypair: Keypair) -> String {
|
func get_content(_ keypair: Keypair) -> String {
|
||||||
@ -388,23 +387,17 @@ extension NdbNote {
|
|||||||
return dec
|
return dec
|
||||||
}
|
}
|
||||||
|
|
||||||
public func direct_replies(_ keypair: Keypair) -> [NoteId] {
|
public func direct_replies(_ keypair: Keypair) -> NoteId? {
|
||||||
return event_refs(keypair).reduce(into: []) { acc, evref in
|
return thread_reply(keypair)?.reply?.note_id
|
||||||
if let direct_reply = evref.is_direct_reply {
|
|
||||||
acc.append(direct_reply.note_id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NDBTODO: just use Id
|
// NDBTODO: just use Id
|
||||||
public func thread_id(keypair: Keypair) -> NoteId {
|
public func thread_id(keypair: Keypair) -> NoteId {
|
||||||
for ref in event_refs(keypair) {
|
guard let root = self.thread_reply(keypair)?.root else {
|
||||||
if let thread_id = ref.is_thread_id {
|
return self.id
|
||||||
return thread_id.note_id
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.id
|
return root.note_id
|
||||||
}
|
}
|
||||||
|
|
||||||
public func last_refid() -> NoteId? {
|
public func last_refid() -> NoteId? {
|
||||||
@ -429,7 +422,7 @@ extension NdbNote {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
func is_reply(_ keypair: Keypair) -> Bool {
|
func is_reply(_ keypair: Keypair) -> Bool {
|
||||||
return event_is_reply(self.event_refs(keypair))
|
return thread_reply(keypair)?.reply != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func note_language(_ keypair: Keypair) -> String? {
|
func note_language(_ keypair: Keypair) -> String? {
|
||||||
|
Loading…
Reference in New Issue
Block a user