commit 99ae7de5eb6d7170cf176d7f77ebe152d16e4bc0
parent b3d9ee3fc096aae23e02cbfd6f1e8d4b8fd28323
Author: Terry Yiu <git@tyiu.xyz>
Date: Wed, 4 Jun 2025 23:48:22 -0400
Rename Friends of Friends to Trusted Network and add popover tips to DMs and Notifications toolbars on Trusted Network button
Changelog-Changed: Renamed Friends of Friends to Trusted Network
Changelog-Added: Added popover tips to DMs and Notifications toolbars on Trusted Network button
Signed-off-by: Terry Yiu <git@tyiu.xyz>
Diffstat:
9 files changed, 225 insertions(+), 70 deletions(-)
diff --git a/damus.xcodeproj/project.pbxproj b/damus.xcodeproj/project.pbxproj
@@ -30,6 +30,9 @@
3A515C502DF4E100002D3B34 /* TrustedNetworkRepliesTip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A515C4F2DF4E100002D3B34 /* TrustedNetworkRepliesTip.swift */; };
3A515C512DF4E100002D3B34 /* TrustedNetworkRepliesTip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A515C4F2DF4E100002D3B34 /* TrustedNetworkRepliesTip.swift */; };
3A515C522DF4E100002D3B34 /* TrustedNetworkRepliesTip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A515C4F2DF4E100002D3B34 /* TrustedNetworkRepliesTip.swift */; };
+ 3A515C542DF5371D002D3B34 /* TrustedNetworkButtonTipViewStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A515C532DF5371D002D3B34 /* TrustedNetworkButtonTipViewStyle.swift */; };
+ 3A515C552DF5371D002D3B34 /* TrustedNetworkButtonTipViewStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A515C532DF5371D002D3B34 /* TrustedNetworkButtonTipViewStyle.swift */; };
+ 3A515C562DF5371D002D3B34 /* TrustedNetworkButtonTipViewStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A515C532DF5371D002D3B34 /* TrustedNetworkButtonTipViewStyle.swift */; };
3A8CC6CC2A2CFEF900940F5F /* StringUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A8CC6CB2A2CFEF900940F5F /* StringUtil.swift */; };
3A92C0FE2DE16E9800CEEBAC /* FaviconCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A92C0FD2DE16E9800CEEBAC /* FaviconCache.swift */; };
3A92C0FF2DE16E9800CEEBAC /* FaviconCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A92C0FD2DE16E9800CEEBAC /* FaviconCache.swift */; };
@@ -38,6 +41,9 @@
3A96E3FE2D6BCE3800AE1630 /* RepostedTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A96E3FD2D6BCE3800AE1630 /* RepostedTests.swift */; };
3AA247FF297E3D900090C62D /* RepostsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AA247FE297E3D900090C62D /* RepostsView.swift */; };
3AA24802297E3DC20090C62D /* RepostView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AA24801297E3DC20090C62D /* RepostView.swift */; };
+ 3AA2F4E82DF1467A00B18606 /* TrustedNetworkButtonTip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AA2F4E72DF1467A00B18606 /* TrustedNetworkButtonTip.swift */; };
+ 3AA2F4E92DF1467A00B18606 /* TrustedNetworkButtonTip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AA2F4E72DF1467A00B18606 /* TrustedNetworkButtonTip.swift */; };
+ 3AA2F4EA2DF1467A00B18606 /* TrustedNetworkButtonTip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AA2F4E72DF1467A00B18606 /* TrustedNetworkButtonTip.swift */; };
3AA59D1D2999B0400061C48E /* DraftsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AA59D1C2999B0400061C48E /* DraftsModel.swift */; };
3AAA95CA298DF87B00F3D526 /* TranslationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AAA95C9298DF87B00F3D526 /* TranslationService.swift */; };
3AAA95CC298E07E900F3D526 /* DeepLPlan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AAA95CB298E07E900F3D526 /* DeepLPlan.swift */; };
@@ -267,7 +273,7 @@
4C8D00CF29E38B950036AF10 /* nostr_bech32.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C8D00CE29E38B950036AF10 /* nostr_bech32.c */; };
4C8D00D429E3C5D40036AF10 /* NIP19Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C8D00D329E3C5D40036AF10 /* NIP19Tests.swift */; };
4C8D1A6C29F1DFC200ACDF75 /* FriendIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C8D1A6B29F1DFC200ACDF75 /* FriendIcon.swift */; };
- 4C8D1A6F29F31E5000ACDF75 /* FriendsButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C8D1A6E29F31E5000ACDF75 /* FriendsButton.swift */; };
+ 4C8D1A6F29F31E5000ACDF75 /* TrustedNetworkButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C8D1A6E29F31E5000ACDF75 /* TrustedNetworkButton.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 */; };
@@ -781,7 +787,7 @@
82D6FBD52CD99F7900C925F4 /* ConnectWalletView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C7D095C2A098C5D00943473 /* ConnectWalletView.swift */; };
82D6FBD62CD99F7900C925F4 /* WalletView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C7D095D2A098C5D00943473 /* WalletView.swift */; };
82D6FBD72CD99F7900C925F4 /* NWCScannerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C7D09672A0AE9B200943473 /* NWCScannerView.swift */; };
- 82D6FBD82CD99F7900C925F4 /* FriendsButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C8D1A6E29F31E5000ACDF75 /* FriendsButton.swift */; };
+ 82D6FBD82CD99F7900C925F4 /* TrustedNetworkButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C8D1A6E29F31E5000ACDF75 /* TrustedNetworkButton.swift */; };
82D6FBD92CD99F7900C925F4 /* GradientFollowButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = F71694F32A6732B7001F4053 /* GradientFollowButton.swift */; };
82D6FBDA2CD99F7900C925F4 /* AlbyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C7D09652A0AE62100943473 /* AlbyButton.swift */; };
82D6FBDC2CD99F7900C925F4 /* DamusVideoPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C1A9A2929DDF54400516EAC /* DamusVideoPlayerView.swift */; };
@@ -1323,7 +1329,7 @@
D73E5ECC2C6A97F4007EB227 /* SuggestedUsersViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F71694EB2A662292001F4053 /* SuggestedUsersViewModel.swift */; };
D73E5ED22C6A97F4007EB227 /* WalletView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C7D095D2A098C5D00943473 /* WalletView.swift */; };
D73E5ED32C6A97F4007EB227 /* NWCScannerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C7D09672A0AE9B200943473 /* NWCScannerView.swift */; };
- D73E5ED42C6A97F4007EB227 /* FriendsButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C8D1A6E29F31E5000ACDF75 /* FriendsButton.swift */; };
+ D73E5ED42C6A97F4007EB227 /* TrustedNetworkButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C8D1A6E29F31E5000ACDF75 /* TrustedNetworkButton.swift */; };
D73E5ED52C6A97F4007EB227 /* GradientFollowButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = F71694F32A6732B7001F4053 /* GradientFollowButton.swift */; };
D73E5ED62C6A97F4007EB227 /* AlbyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C7D09652A0AE62100943473 /* AlbyButton.swift */; };
D73E5ED82C6A97F4007EB227 /* DamusVideoPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C1A9A2929DDF54400516EAC /* DamusVideoPlayerView.swift */; };
@@ -1874,6 +1880,7 @@
3A47CB792BDA05A200728A7C /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = fi; path = fi.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
3A48E7AF29DFBE9D006E787E /* MutedThreadsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MutedThreadsManager.swift; sourceTree = "<group>"; };
3A515C4F2DF4E100002D3B34 /* TrustedNetworkRepliesTip.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrustedNetworkRepliesTip.swift; sourceTree = "<group>"; };
+ 3A515C532DF5371D002D3B34 /* TrustedNetworkButtonTipViewStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrustedNetworkButtonTipViewStyle.swift; sourceTree = "<group>"; };
3A5C4575296A879E0032D398 /* es-419 */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "es-419"; path = "es-419.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
3A5CAE1D298DC0DB00B5334F /* zh-CN */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-CN"; path = "zh-CN.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
3A5CAE1E298DC0DB00B5334F /* zh-CN */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-CN"; path = "zh-CN.lproj/Localizable.strings"; sourceTree = "<group>"; };
@@ -1908,6 +1915,7 @@
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>"; };
3AA24801297E3DC20090C62D /* RepostView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RepostView.swift; sourceTree = "<group>"; };
+ 3AA2F4E72DF1467A00B18606 /* TrustedNetworkButtonTip.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrustedNetworkButtonTip.swift; sourceTree = "<group>"; };
3AA59D1C2999B0400061C48E /* DraftsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DraftsModel.swift; sourceTree = "<group>"; };
3AA5E70229B682A5002701ED /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/Localizable.strings; sourceTree = "<group>"; };
3AA5E70329B682AD002701ED /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/InfoPlist.strings; sourceTree = "<group>"; };
@@ -2295,7 +2303,7 @@
4C8D00D229E3C19F0036AF10 /* str_block.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = str_block.h; sourceTree = "<group>"; };
4C8D00D329E3C5D40036AF10 /* NIP19Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NIP19Tests.swift; sourceTree = "<group>"; };
4C8D1A6B29F1DFC200ACDF75 /* FriendIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FriendIcon.swift; sourceTree = "<group>"; };
- 4C8D1A6E29F31E5000ACDF75 /* FriendsButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FriendsButton.swift; sourceTree = "<group>"; };
+ 4C8D1A6E29F31E5000ACDF75 /* TrustedNetworkButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrustedNetworkButton.swift; sourceTree = "<group>"; };
4C8EC52429D1FA6C0085D9A8 /* DamusColors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DamusColors.swift; sourceTree = "<group>"; };
4C9054842A6AEAA000811EEC /* NdbTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NdbTests.swift; sourceTree = "<group>"; };
4C9054882A6AED4700811EEC /* NdbTagIterator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NdbTagIterator.swift; sourceTree = "<group>"; };
@@ -2755,6 +2763,8 @@
3A515C4E2DF4E0E6002D3B34 /* Tips */ = {
isa = PBXGroup;
children = (
+ 3AA2F4E72DF1467A00B18606 /* TrustedNetworkButtonTip.swift */,
+ 3A515C532DF5371D002D3B34 /* TrustedNetworkButtonTipViewStyle.swift */,
3A515C4F2DF4E100002D3B34 /* TrustedNetworkRepliesTip.swift */,
);
path = Tips;
@@ -3455,7 +3465,7 @@
isa = PBXGroup;
children = (
5CB017202D2D985800A9ED05 /* CoinosButton.swift */,
- 4C8D1A6E29F31E5000ACDF75 /* FriendsButton.swift */,
+ 4C8D1A6E29F31E5000ACDF75 /* TrustedNetworkButton.swift */,
F71694F32A6732B7001F4053 /* GradientFollowButton.swift */,
4C7D09652A0AE62100943473 /* AlbyButton.swift */,
);
@@ -4692,7 +4702,7 @@
4C3D52B8298DB5C6001C5831 /* TextEvent.swift in Sources */,
4C216F362870A9A700040376 /* InputDismissKeyboard.swift in Sources */,
D74AAFCF2B155D8C006CF0F4 /* ZapDataModel.swift in Sources */,
- 4C8D1A6F29F31E5000ACDF75 /* FriendsButton.swift in Sources */,
+ 4C8D1A6F29F31E5000ACDF75 /* TrustedNetworkButton.swift in Sources */,
D7100C562B76F8E600C59298 /* PurpleViewPrimitives.swift in Sources */,
B57B4C642B312BFA00A232C0 /* RelayAuthenticationDetail.swift in Sources */,
D7EDED2E2B128E8A0018B19C /* CollectionExtension.swift in Sources */,
@@ -4875,6 +4885,7 @@
4CA352A22A76AEC5003BB08B /* LikedNotify.swift in Sources */,
5CC8529F2BD744F60039FFC5 /* HighlightView.swift in Sources */,
BA37598D2ABCCE500018D73B /* PhotoCaptureProcessor.swift in Sources */,
+ 3A515C562DF5371D002D3B34 /* TrustedNetworkButtonTipViewStyle.swift in Sources */,
5CC8529D2BD741CD0039FFC5 /* HighlightEvent.swift in Sources */,
4C9146FD2A2A87C200DDEA40 /* wasm.c in Sources */,
4C75EFAF28049D350006080F /* NostrFilter.swift in Sources */,
@@ -4921,6 +4932,7 @@
4C1A9A2729DDE31900516EAC /* TranslationSettingsView.swift in Sources */,
BA3759942ABCCEBA0018D73B /* CameraService.swift in Sources */,
4CB8838629656C8B00DC99E7 /* NIP05.swift in Sources */,
+ 3AA2F4E82DF1467A00B18606 /* TrustedNetworkButtonTip.swift in Sources */,
4CF0ABD82981980C00D66079 /* Lists.swift in Sources */,
F71694EA2A662232001F4053 /* OnboardingSuggestionsView.swift in Sources */,
4C12536A2A76D3850004F4B8 /* RelaysChangedNotify.swift in Sources */,
@@ -5178,6 +5190,7 @@
82D6FAB42CD99F7900C925F4 /* Verifiable.swift in Sources */,
82D6FAB52CD99F7900C925F4 /* NativeObject.swift in Sources */,
82D6FAB62CD99F7900C925F4 /* String+extension.swift in Sources */,
+ 3A515C552DF5371D002D3B34 /* TrustedNetworkButtonTipViewStyle.swift in Sources */,
82D6FAB72CD99F7900C925F4 /* FlatBufferObject.swift in Sources */,
82D6FAB82CD99F7900C925F4 /* Enum.swift in Sources */,
82D6FAB92CD99F7900C925F4 /* builder.c in Sources */,
@@ -5481,13 +5494,14 @@
82D6FBCC2CD99F7900C925F4 /* CameraPreview.swift in Sources */,
82D6FBCD2CD99F7900C925F4 /* CameraController.swift in Sources */,
82D6FBCE2CD99F7900C925F4 /* OnboardingSuggestionsView.swift in Sources */,
+ 3AA2F4EA2DF1467A00B18606 /* TrustedNetworkButtonTip.swift in Sources */,
82D6FBCF2CD99F7900C925F4 /* SuggestedUserView.swift in Sources */,
82D6FBD02CD99F7900C925F4 /* SuggestedUsersViewModel.swift in Sources */,
82D6FBD12CD99F7900C925F4 /* LoadScript.swift in Sources */,
82D6FBD52CD99F7900C925F4 /* ConnectWalletView.swift in Sources */,
82D6FBD62CD99F7900C925F4 /* WalletView.swift in Sources */,
82D6FBD72CD99F7900C925F4 /* NWCScannerView.swift in Sources */,
- 82D6FBD82CD99F7900C925F4 /* FriendsButton.swift in Sources */,
+ 82D6FBD82CD99F7900C925F4 /* TrustedNetworkButton.swift in Sources */,
82D6FBD92CD99F7900C925F4 /* GradientFollowButton.swift in Sources */,
82D6FBDA2CD99F7900C925F4 /* AlbyButton.swift in Sources */,
82D6FBDC2CD99F7900C925F4 /* DamusVideoPlayerView.swift in Sources */,
@@ -5796,6 +5810,7 @@
D73E5E922C6A97F4007EB227 /* EventGroup.swift in Sources */,
D73E5E932C6A97F4007EB227 /* ZapGroup.swift in Sources */,
D73E5E942C6A97F4007EB227 /* NotificationStatusModel.swift in Sources */,
+ 3A515C542DF5371D002D3B34 /* TrustedNetworkButtonTipViewStyle.swift in Sources */,
D73E5E952C6A97F4007EB227 /* ThreadModel.swift in Sources */,
D73E5E962C6A97F4007EB227 /* ReplyMap.swift in Sources */,
D73E5E972C6A97F4007EB227 /* ProfileModel.swift in Sources */,
@@ -5854,6 +5869,7 @@
D73E5EC02C6A97F4007EB227 /* NostrEvent+.swift in Sources */,
D73E5EC12C6A97F4007EB227 /* NIP98AuthenticatedRequest.swift in Sources */,
D73E5EC22C6A97F4007EB227 /* NostrAuth.swift in Sources */,
+ 3AA2F4E92DF1467A00B18606 /* TrustedNetworkButtonTip.swift in Sources */,
D73E5EC42C6A97F4007EB227 /* ReplyQuoteView.swift in Sources */,
D73E5EC62C6A97F4007EB227 /* ChatBubbleView.swift in Sources */,
D73E5EC72C6A97F4007EB227 /* VisibilityTracker.swift in Sources */,
@@ -5865,7 +5881,7 @@
D73E5ED22C6A97F4007EB227 /* WalletView.swift in Sources */,
D73E5ED32C6A97F4007EB227 /* NWCScannerView.swift in Sources */,
D74E64132DC95CC7004C7892 /* HumanReadableErrors.swift in Sources */,
- D73E5ED42C6A97F4007EB227 /* FriendsButton.swift in Sources */,
+ D73E5ED42C6A97F4007EB227 /* TrustedNetworkButton.swift in Sources */,
D73E5ED52C6A97F4007EB227 /* GradientFollowButton.swift in Sources */,
D73E5ED62C6A97F4007EB227 /* AlbyButton.swift in Sources */,
D73E5ED82C6A97F4007EB227 /* DamusVideoPlayerView.swift in Sources */,
diff --git a/damus/ContentView.swift b/damus/ContentView.swift
@@ -9,10 +9,7 @@ import SwiftUI
import AVKit
import MediaPlayer
import EmojiPicker
-
-#if canImport(TipKit)
import TipKit
-#endif
struct ZapSheet {
let target: ZapTarget
@@ -182,7 +179,7 @@ struct ContentView: View {
NotificationsView(state: damus, notifications: home.notifications, subtitle: $menu_subtitle)
case .dms:
- DirectMessagesView(damus_state: damus_state!, model: damus_state!.dms, settings: damus_state!.settings)
+ DirectMessagesView(damus_state: damus_state!, model: damus_state!.dms, settings: damus_state!.settings, subtitle: $menu_subtitle)
}
}
.background(DamusColors.adaptableWhite)
diff --git a/damus/Models/FriendFilter.swift b/damus/Models/FriendFilter.swift
@@ -35,9 +35,9 @@ enum FriendFilter: String, StringCodable {
func description() -> String {
switch self {
case .all:
- return NSLocalizedString("All", comment: "Human-readable short description of the 'friends filter' when it is set to 'all'")
+ return NSLocalizedString("All", comment: "Human-readable short description of the 'trusted network filter' when it is disabled, and therefore is showing all content.")
case .friends_of_friends:
- return NSLocalizedString("Friends of friends", comment: "Human-readable short description of the 'friends filter' when it is set to 'friends-of-friends'")
+ return NSLocalizedString("Trusted Network", comment: "Human-readable short description of the 'trusted network filter' when it is enabled, and therefore showing content from only the trusted network.")
}
}
}
diff --git a/damus/Views/Buttons/FriendsButton.swift b/damus/Views/Buttons/FriendsButton.swift
@@ -1,44 +0,0 @@
-//
-// FriendsButton.swift
-// damus
-//
-// Created by William Casarin on 2023-04-21.
-//
-
-import SwiftUI
-
-struct FriendsButton: View {
- @Binding var filter: FriendFilter
-
- var body: some View {
- Button(action: {
- switch self.filter {
- case .all:
- self.filter = .friends_of_friends
- case .friends_of_friends:
- self.filter = .all
- }
- }) {
- if filter == .friends_of_friends {
- LINEAR_GRADIENT
- .mask(Image("user-added")
- .resizable()
- ).frame(width: 28, height: 28)
- } else {
- Image("user-added")
- .resizable()
- .frame(width: 28, height: 28)
- .foregroundColor(.gray)
- }
- }
- .buttonStyle(.plain)
- }
-}
-
-struct FriendsButton_Previews: PreviewProvider {
- @State static var enabled: FriendFilter = .all
-
- static var previews: some View {
- FriendsButton(filter: $enabled)
- }
-}
diff --git a/damus/Views/Buttons/TrustedNetworkButton.swift b/damus/Views/Buttons/TrustedNetworkButton.swift
@@ -0,0 +1,54 @@
+//
+// TrustedNetworkButton.swift
+// damus
+//
+// Created by William Casarin on 2023-04-21.
+//
+
+import SwiftUI
+
+struct TrustedNetworkButton: View {
+ @Binding var filter: FriendFilter
+ var action: (@MainActor () -> Void)? = nil
+
+ var MainButton: some View {
+ Button(action: {
+ switch self.filter {
+ case .all:
+ self.filter = .friends_of_friends
+ case .friends_of_friends:
+ self.filter = .all
+ }
+
+ if let action {
+ action()
+ }
+ }) {
+ if filter == .friends_of_friends {
+ LINEAR_GRADIENT
+ .mask(Image(systemName: "network.badge.shield.half.filled")
+ .frame(width: 24, height: 24)
+ )
+ .scaledToFit()
+ .frame(width: 24, height: 24)
+ } else {
+ Image(systemName: "network.slash")
+ .frame(width: 24, height: 24)
+ .foregroundColor(.gray)
+ }
+ }
+ .buttonStyle(.plain)
+ }
+
+ var body: some View {
+ MainButton
+ }
+}
+
+struct TrustedNetworkButton_Previews: PreviewProvider {
+ @State static var enabled: FriendFilter = .all
+
+ static var previews: some View {
+ TrustedNetworkButton(filter: $enabled)
+ }
+}
diff --git a/damus/Views/DirectMessagesView.swift b/damus/Views/DirectMessagesView.swift
@@ -6,6 +6,7 @@
//
import SwiftUI
+import TipKit
enum DMType: Hashable {
case rando
@@ -18,6 +19,7 @@ struct DirectMessagesView: View {
@State var dm_type: DMType = .friend
@ObservedObject var model: DirectMessagesModel
@ObservedObject var settings: UserSettingsStore
+ @Binding var subtitle: String?
func MainContent(requests: Bool) -> some View {
ScrollView {
@@ -72,7 +74,15 @@ struct DirectMessagesView: View {
}
var body: some View {
+ let showTrustedButton = would_filter_non_friends_from_dms(contacts: damus_state.contacts, dms: self.model.dms)
VStack(spacing: 0) {
+ if #available(iOS 17, *), showTrustedButton {
+ TipView(TrustedNetworkButtonTip.shared)
+ .tipBackground(.clear)
+ .tipViewStyle(TrustedNetworkButtonTipViewStyle())
+ .padding(.horizontal)
+ }
+
CustomPicker(tabs: [
(NSLocalizedString("DMs", comment: "Picker option for DM selector for seeing only DMs that have been responded to. DM is the English abbreviation for Direct Message."), DMType.friend),
(NSLocalizedString("Requests", comment: "Picker option for DM selector for seeing only message requests (DMs that someone else sent the user which has not been responded to yet"), DMType.rando),
@@ -92,12 +102,22 @@ struct DirectMessagesView: View {
}
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
- if would_filter_non_friends_from_dms(contacts: damus_state.contacts, dms: self.model.dms) {
-
- FriendsButton(filter: $settings.friend_filter)
+ if showTrustedButton {
+ TrustedNetworkButton(filter: $settings.friend_filter) {
+ if #available(iOS 17, *) {
+ TrustedNetworkButtonTip.shared.invalidate(reason: .actionPerformed)
+ }
+ }
}
}
}
+ .onAppear {
+ self.subtitle = settings.friend_filter.description()
+
+ }
+ .onChange(of: settings.friend_filter) { val in
+ self.subtitle = val.description()
+ }
.navigationTitle(NSLocalizedString("DMs", comment: "Navigation title for view of DMs, where DM is an English abbreviation for Direct Message."))
}
}
@@ -115,6 +135,6 @@ func would_filter_non_friends_from_dms(contacts: Contacts, dms: [DirectMessageMo
struct DirectMessagesView_Previews: PreviewProvider {
static var previews: some View {
let ds = test_damus_state
- DirectMessagesView(damus_state: ds, model: ds.dms, settings: ds.settings)
+ DirectMessagesView(damus_state: ds, model: ds.dms, settings: ds.settings, subtitle: .constant(nil))
}
}
diff --git a/damus/Views/Notifications/NotificationsView.swift b/damus/Views/Notifications/NotificationsView.swift
@@ -6,10 +6,7 @@
//
import SwiftUI
-
-#if canImport(TipKit)
import TipKit
-#endif
class NotificationFilter: ObservableObject, Equatable {
@Published var state: NotificationFilterState
@@ -80,11 +77,10 @@ struct NotificationsView: View {
@SceneStorage("NotificationsView.filter_state") var filter_state: NotificationFilterState = .all
@Binding var subtitle: String?
- @State var showTip: Bool = true
-
@Environment(\.colorScheme) var colorScheme
var body: some View {
+ let showTrustedButton = would_filter_non_friends_from_notifications(contacts: state.contacts, state: filter_state, items: self.notifications.notifications)
TabView(selection: $filter_state) {
NotificationTab(
NotificationFilter(
@@ -121,14 +117,19 @@ struct NotificationsView: View {
Button(
action: { state.nav.push(route: Route.NotificationSettings(settings: state.settings)) },
label: {
- Image("settings")
+ Image(systemName: "gearshape")
+ .frame(width: 24, height: 24)
.foregroundColor(.gray)
}
)
}
ToolbarItem(placement: .navigationBarTrailing) {
- if would_filter_non_friends_from_notifications(contacts: state.contacts, state: filter_state, items: self.notifications.notifications) {
- FriendsButton(filter: $filter.friend_filter)
+ if showTrustedButton {
+ TrustedNetworkButton(filter: $filter.friend_filter) {
+ if #available(iOS 17, *) {
+ TrustedNetworkButtonTip.shared.invalidate(reason: .actionPerformed)
+ }
+ }
}
}
}
@@ -146,6 +147,13 @@ struct NotificationsView: View {
}
.safeAreaInset(edge: .top, spacing: 0) {
VStack(spacing: 0) {
+ if #available(iOS 17, *), showTrustedButton {
+ TipView(TrustedNetworkButtonTip.shared)
+ .tipBackground(.clear)
+ .tipViewStyle(TrustedNetworkButtonTipViewStyle())
+ .padding(.horizontal)
+ }
+
CustomPicker(tabs: [
(NSLocalizedString("All", comment: "Label for filter for all notifications."), NotificationFilterState.all),
(NSLocalizedString("Zaps", comment: "Label for filter for zap notifications."), NotificationFilterState.zaps),
diff --git a/damus/Views/Tips/TrustedNetworkButtonTip.swift b/damus/Views/Tips/TrustedNetworkButtonTip.swift
@@ -0,0 +1,25 @@
+//
+// TrustedNetworkButtonTip.swift
+// damus
+//
+// Created by Terry Yiu on 6/4/25.
+//
+
+import TipKit
+
+@available(iOS 17, *)
+struct TrustedNetworkButtonTip: Tip {
+ static let shared = TrustedNetworkButtonTip()
+
+ var title: Text {
+ Text("Toggle visibility of content from outside your trusted network", comment: "Title of tip that informs users what trusted network means and that they can toggle the visibility of content from outside their trusted network.")
+ }
+
+ var message: Text? {
+ Text("Your trusted network is comprised of profiles you follow and profiles that they follow.", comment: "Description of the tip that informs users what trusted network means.")
+ }
+
+ var image: Image? {
+ Image(systemName: "network.badge.shield.half.filled")
+ }
+}
diff --git a/damus/Views/Tips/TrustedNetworkButtonTipViewStyle.swift b/damus/Views/Tips/TrustedNetworkButtonTipViewStyle.swift
@@ -0,0 +1,79 @@
+//
+// TrustedNetworkButtonTipViewStyle.swift
+// damus
+//
+// Created by Terry Yiu on 6/7/25.
+//
+
+import TipKit
+
+// (tyiu): Apple's native popover tips have a lot of rendering and race condition issues --
+// text being rendered in the wrong locations or not at all, or the tip gets opened in full screen.
+//
+// Instead, we are introducing this custom popover tip view style to emulate a similar look and feel.
+// The main thing needed from this view style is really just an arrow on the top right corner
+// to point to the TrustedNetworkButton on the NotificationsView and DirectMessagesview.
+@available(iOS 17, *)
+struct TrustedNetworkButtonTipViewStyle: TipViewStyle {
+ func makeBody(configuration: Configuration) -> some View {
+ VStack(spacing: 0) {
+ // Arrow pointing up to the button (positioned at top right)
+ HStack {
+ Spacer()
+ Triangle()
+ .fill(Color(.secondarySystemBackground))
+ .frame(width: 24, height: 14)
+ }
+
+ HStack(alignment: .top, spacing: 12) {
+ // Icon
+ configuration.image
+ .foregroundStyle(.tint)
+ .font(.title2)
+
+ VStack(alignment: .leading, spacing: 4) {
+ configuration.title
+ .font(.headline)
+ .fontWeight(.semibold)
+ .foregroundStyle(.primary)
+
+ configuration.message
+ .font(.subheadline)
+ .foregroundStyle(.secondary)
+ }
+
+ Spacer()
+
+ Button(action: { configuration.tip.invalidate(reason: .tipClosed) }) {
+ Image(systemName: "xmark")
+ .fontWeight(.semibold)
+ .foregroundStyle(Color(.tertiaryLabel))
+ }
+ .buttonStyle(PlainButtonStyle())
+ }
+ .padding(.horizontal, 14)
+ .padding(.vertical, 14)
+ .background(Color(.secondarySystemBackground))
+ .clipShape(
+ .rect(
+ topLeadingRadius: 20,
+ bottomLeadingRadius: 20,
+ bottomTrailingRadius: 20,
+ topTrailingRadius: 0
+ )
+ )
+ }
+ }
+}
+
+// Custom triangle shape for the popover arrow
+struct Triangle: Shape {
+ func path(in rect: CGRect) -> Path {
+ var path = Path()
+ path.move(to: CGPoint(x: rect.midX, y: rect.minY))
+ path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
+ path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
+ path.addLine(to: CGPoint(x: rect.midX, y: rect.minY))
+ return path
+ }
+}