From 7dd393bd8452ca7fc764a28c86964c67aad44848 Mon Sep 17 00:00:00 2001 From: Josh Brown Date: Fri, 11 Oct 2024 17:19:30 -0400 Subject: [PATCH 1/9] #1601: Go to Your Feed tip --- Nos.xcodeproj/project.pbxproj | 6 +++- Nos/Assets/Localization/Localizable.xcstrings | 11 ++++++ Nos/Views/Discover/DiscoverTab.swift | 27 ++++++++++++--- .../Modifiers/FakePopoverTipViewStyle.swift | 34 +++++++++++++++++++ 4 files changed, 72 insertions(+), 6 deletions(-) create mode 100644 Nos/Views/Modifiers/FakePopoverTipViewStyle.swift diff --git a/Nos.xcodeproj/project.pbxproj b/Nos.xcodeproj/project.pbxproj index 38012c848..88ff92ed6 100644 --- a/Nos.xcodeproj/project.pbxproj +++ b/Nos.xcodeproj/project.pbxproj @@ -101,6 +101,7 @@ 03C68C522C94D8400037DC59 /* SwiftSoup in Frameworks */ = {isa = PBXBuildFile; productRef = 03C68C512C94D8400037DC59 /* SwiftSoup */; }; 03C7E7922CB9C0B30054624C /* WelcomeToFeedTip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03C7E7912CB9C0AF0054624C /* WelcomeToFeedTip.swift */; }; 03C7E7982CB9C16C0054624C /* InlineTipViewStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03C7E7972CB9C1600054624C /* InlineTipViewStyle.swift */; }; + 03C7E7A22CB9CD150054624C /* FakePopoverTipViewStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03C7E7A12CB9CD0B0054624C /* FakePopoverTipViewStyle.swift */; }; 03C8B4962C6D065900A07CCD /* ImageViewer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03C8B4952C6D065900A07CCD /* ImageViewer.swift */; }; 03D1B4282C3C1A5D001778CD /* NostrIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03D1B4272C3C1A5D001778CD /* NostrIdentifier.swift */; }; 03D1B4292C3C1AC9001778CD /* NostrIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03D1B4272C3C1A5D001778CD /* NostrIdentifier.swift */; }; @@ -664,6 +665,7 @@ 03C49AC12C938DE100502321 /* SoupOpenGraphParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoupOpenGraphParser.swift; sourceTree = ""; }; 03C7E7912CB9C0AF0054624C /* WelcomeToFeedTip.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeToFeedTip.swift; sourceTree = ""; }; 03C7E7972CB9C1600054624C /* InlineTipViewStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InlineTipViewStyle.swift; sourceTree = ""; }; + 03C7E7A12CB9CD0B0054624C /* FakePopoverTipViewStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FakePopoverTipViewStyle.swift; sourceTree = ""; }; 03C8B4952C6D065900A07CCD /* ImageViewer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageViewer.swift; sourceTree = ""; }; 03D1B4272C3C1A5D001778CD /* NostrIdentifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NostrIdentifier.swift; sourceTree = ""; }; 03D1B42B2C3C1B0D001778CD /* TLVElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TLVElement.swift; sourceTree = ""; }; @@ -1752,8 +1754,9 @@ C9CFF6D02AB241EB00D4B368 /* Modifiers */ = { isa = PBXGroup; children = ( - 03C7E7972CB9C1600054624C /* InlineTipViewStyle.swift */, 5B0D99022A94090A0039F0C5 /* DoubleTapToPopModifier.swift */, + 03C7E7A12CB9CD0B0054624C /* FakePopoverTipViewStyle.swift */, + 03C7E7972CB9C1600054624C /* InlineTipViewStyle.swift */, C95D68A8299E709800429F86 /* LinearGradient+Planetary.swift */, C95D68A4299E6E1E00429F86 /* PlaceholderModifier.swift */, C9A25B3C29F174D200B39534 /* ReadabilityPadding.swift */, @@ -2396,6 +2399,7 @@ C9AC31AD2A55E0BD00A94E5A /* NotificationViewModel.swift in Sources */, 0326347A2C10C57A00E489B5 /* FileStorageAPIClient.swift in Sources */, C9EE3E632A053910008A7491 /* ExpirationTimeOption.swift in Sources */, + 03C7E7A22CB9CD150054624C /* FakePopoverTipViewStyle.swift in Sources */, C9A0DAE029C697A100466635 /* AboutView.swift in Sources */, C9E8C1132B081E9C002D46B0 /* UNSNameView.swift in Sources */, 0496D6312C975E6900D29375 /* FlagOptionPicker.swift in Sources */, diff --git a/Nos/Assets/Localization/Localizable.xcstrings b/Nos/Assets/Localization/Localizable.xcstrings index df1704e33..b8b5e4d3c 100644 --- a/Nos/Assets/Localization/Localizable.xcstrings +++ b/Nos/Assets/Localization/Localizable.xcstrings @@ -9434,6 +9434,17 @@ } } }, + "goToYourFeed" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Go to your Feed to see notes from your connections." + } + } + } + }, "homeFeed" : { "extractionState" : "manual", "localizations" : { diff --git a/Nos/Views/Discover/DiscoverTab.swift b/Nos/Views/Discover/DiscoverTab.swift index 603f6f5bc..ca9706240 100644 --- a/Nos/Views/Discover/DiscoverTab.swift +++ b/Nos/Views/Discover/DiscoverTab.swift @@ -2,8 +2,9 @@ import SwiftUI import Combine import CoreData import Dependencies +import TipKit -struct DiscoverTab: View { +struct DiscoverTab: View { // MARK: - Properties @EnvironmentObject private var router: Router @@ -20,15 +21,25 @@ struct DiscoverTab: View { @State var predicate: NSPredicate = .false + let goToFeedTip = GoToFeedTip() + // MARK: - View var body: some View { NosNavigationStack(path: $router.discoverPath) { ZStack { - DiscoverContentsView( - featuredAuthorCategory: .all, - searchController: searchController - ) + VStack { + DiscoverContentsView( + featuredAuthorCategory: .all, + searchController: searchController + ) + + TipView(goToFeedTip) + .padding(.horizontal, 12) + .padding(.bottom, 8) + .tipBackground(LinearGradient.horizontalAccentReversed) + .tipViewStyle(.fakePopover) + } } .searchable( text: $searchController.query, @@ -62,6 +73,12 @@ struct DiscoverTab: View { } } +struct GoToFeedTip: Tip { + var title: Text { + Text("goToYourFeed") + } +} + struct SizePreferenceKey: PreferenceKey { static var defaultValue: CGSize = .zero diff --git a/Nos/Views/Modifiers/FakePopoverTipViewStyle.swift b/Nos/Views/Modifiers/FakePopoverTipViewStyle.swift new file mode 100644 index 000000000..a3a62210a --- /dev/null +++ b/Nos/Views/Modifiers/FakePopoverTipViewStyle.swift @@ -0,0 +1,34 @@ +import TipKit + +/// A fake popover tip view style that has a pointing down emoji (👇) in the bottom left instead of the popover chevron. +struct FakePopoverTipViewStyle: TipViewStyle { + func makeBody(configuration: TipViewStyle.Configuration) -> some View { + VStack(alignment: .leading, spacing: 10) { + HStack(alignment: .top) { + configuration.title + .font(.body.bold()) + .foregroundStyle(Color.primaryTxt) + .shadow(color: .lightShadow, radius: 2, x: 0, y: 1) + + Spacer() + + Button { + configuration.tip.invalidate(reason: .tipClosed) + } label: { + Image(systemName: "xmark").scaledToFit() + .foregroundStyle(Color.primaryTxt) + .font(.system(size: 20).bold()) + } + } + + Text("👇") + } + .padding(.vertical, 20) + .padding(.horizontal, 16) + } +} + +extension TipViewStyle where Self == FakePopoverTipViewStyle { + static var fakePopover: Self { Self() } +} + From 7fca4475440eabb65b6fd98360e68e7ee5797d5d Mon Sep 17 00:00:00 2001 From: Josh Brown Date: Fri, 11 Oct 2024 17:31:24 -0400 Subject: [PATCH 2/9] update CHANGELOG; fix swiftlint warning --- CHANGELOG.md | 1 + Nos/Views/Modifiers/FakePopoverTipViewStyle.swift | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d7388d35..16fa446bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Release Notes +- Added a tip to Discover to prompt first-time users to go to their Feed. [#1601](https://github.com/planetary-social/nos/issues/1601) - Added a tip to the Feed to welcome first-time users and explain how the Feed works. [#1602](https://github.com/planetary-social/nos/issues/1602) ## [0.2.2] - 2024-10-11Z diff --git a/Nos/Views/Modifiers/FakePopoverTipViewStyle.swift b/Nos/Views/Modifiers/FakePopoverTipViewStyle.swift index a3a62210a..cf4a68473 100644 --- a/Nos/Views/Modifiers/FakePopoverTipViewStyle.swift +++ b/Nos/Views/Modifiers/FakePopoverTipViewStyle.swift @@ -31,4 +31,3 @@ struct FakePopoverTipViewStyle: TipViewStyle { extension TipViewStyle where Self == FakePopoverTipViewStyle { static var fakePopover: Self { Self() } } - From 4035b2e7cfbf41eeae0c77d76f60073aa3a2ae89 Mon Sep 17 00:00:00 2001 From: Josh Brown Date: Tue, 15 Oct 2024 13:47:33 -0400 Subject: [PATCH 3/9] show Go to Feed tip after following 3 accounts --- .../Components/Button/CircularFollowButton.swift | 1 + Nos/Views/Components/Button/FollowButton.swift | 1 + Nos/Views/Discover/DiscoverTab.swift | 12 ++++++++++++ 3 files changed, 14 insertions(+) diff --git a/Nos/Views/Components/Button/CircularFollowButton.swift b/Nos/Views/Components/Button/CircularFollowButton.swift index 30c565d88..b3f249bda 100644 --- a/Nos/Views/Components/Button/CircularFollowButton.swift +++ b/Nos/Views/Components/Button/CircularFollowButton.swift @@ -32,6 +32,7 @@ struct CircularFollowButton: View { } else { try await currentUser.follow(author: author) analytics.followed(author) + GoToFeedTip.followedAccount.sendDonation() } } catch { crashReporting.report(error) diff --git a/Nos/Views/Components/Button/FollowButton.swift b/Nos/Views/Components/Button/FollowButton.swift index 2a55a5d7e..a194a840d 100644 --- a/Nos/Views/Components/Button/FollowButton.swift +++ b/Nos/Views/Components/Button/FollowButton.swift @@ -39,6 +39,7 @@ struct FollowButton: View { } else { try await currentUser.follow(author: author) analytics.followed(author) + GoToFeedTip.followedAccount.sendDonation() } } catch { crashReporting.report(error) diff --git a/Nos/Views/Discover/DiscoverTab.swift b/Nos/Views/Discover/DiscoverTab.swift index ca9706240..0f9ba3e7c 100644 --- a/Nos/Views/Discover/DiscoverTab.swift +++ b/Nos/Views/Discover/DiscoverTab.swift @@ -73,10 +73,22 @@ struct DiscoverTab: View { } } +/// A tip that's displayed on the Discover view after the user has followed three accounts. struct GoToFeedTip: Tip { + /// A TipKit Event that tracks the number of accounts that have been followed. + static let followedAccount = Tips.Event(id: "followedAccount") + var title: Text { Text("goToYourFeed") } + + var rules: [Rule] { + // Define a rule based on the interaction. + #Rule(Self.followedAccount) { + // Set the conditions for when the tip displays. + $0.donations.count >= 3 + } + } } struct SizePreferenceKey: PreferenceKey { From b0a1808dd05b8db79c4a9bbf9c8d2240b67026c6 Mon Sep 17 00:00:00 2001 From: Josh Brown Date: Tue, 15 Oct 2024 15:50:02 -0400 Subject: [PATCH 4/9] =?UTF-8?q?only=20show=20Go=20to=20Feed=20tip=20if=20t?= =?UTF-8?q?hey=20haven=E2=80=99t=20been=20there?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Nos/Views/Discover/DiscoverTab.swift | 11 +++++++++-- Nos/Views/Home/HomeFeedView.swift | 3 ++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Nos/Views/Discover/DiscoverTab.swift b/Nos/Views/Discover/DiscoverTab.swift index 0f9ba3e7c..a298d15ec 100644 --- a/Nos/Views/Discover/DiscoverTab.swift +++ b/Nos/Views/Discover/DiscoverTab.swift @@ -78,16 +78,23 @@ struct GoToFeedTip: Tip { /// A TipKit Event that tracks the number of accounts that have been followed. static let followedAccount = Tips.Event(id: "followedAccount") + /// A TipKit Event that tracks how many times the Feed has been displayed. + static let viewedFeed = Tips.Event(id: "viewedFeed") + var title: Text { Text("goToYourFeed") } var rules: [Rule] { - // Define a rule based on the interaction. + // Each rule here is combined using the logical AND, so all rules must return true for the tip to display. + #Rule(Self.followedAccount) { - // Set the conditions for when the tip displays. $0.donations.count >= 3 } + + #Rule(Self.viewedFeed) { + $0.donations.count < 2 // for whatever reason, HomeFeedView's onAppear is called before the user views it + } } } diff --git a/Nos/Views/Home/HomeFeedView.swift b/Nos/Views/Home/HomeFeedView.swift index 3768adf2c..71850116f 100644 --- a/Nos/Views/Home/HomeFeedView.swift +++ b/Nos/Views/Home/HomeFeedView.swift @@ -153,13 +153,14 @@ struct HomeFeedView: View { .nosNavigationBar(title: navigationBarTitle) .onAppear { if router.selectedTab == .home { - isVisible = true + isVisible = true } } .onDisappear { isVisible = false } .onChange(of: isVisible) { if isVisible { analytics.showedHome() + GoToFeedTip.viewedFeed.sendDonation() } } } From 634b787c092f58e1c64bee17eef1659108f72d0f Mon Sep 17 00:00:00 2001 From: Josh Brown Date: Tue, 15 Oct 2024 16:08:44 -0400 Subject: [PATCH 5/9] Rename tip view style to Point Down Emoji --- Nos.xcodeproj/project.pbxproj | 8 ++++---- Nos/Views/Discover/DiscoverTab.swift | 2 +- ...pViewStyle.swift => PointDownEmojiTipViewStyle.swift} | 9 +++++---- 3 files changed, 10 insertions(+), 9 deletions(-) rename Nos/Views/Modifiers/{FakePopoverTipViewStyle.swift => PointDownEmojiTipViewStyle.swift} (74%) diff --git a/Nos.xcodeproj/project.pbxproj b/Nos.xcodeproj/project.pbxproj index 88ff92ed6..ebb2bb927 100644 --- a/Nos.xcodeproj/project.pbxproj +++ b/Nos.xcodeproj/project.pbxproj @@ -101,7 +101,7 @@ 03C68C522C94D8400037DC59 /* SwiftSoup in Frameworks */ = {isa = PBXBuildFile; productRef = 03C68C512C94D8400037DC59 /* SwiftSoup */; }; 03C7E7922CB9C0B30054624C /* WelcomeToFeedTip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03C7E7912CB9C0AF0054624C /* WelcomeToFeedTip.swift */; }; 03C7E7982CB9C16C0054624C /* InlineTipViewStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03C7E7972CB9C1600054624C /* InlineTipViewStyle.swift */; }; - 03C7E7A22CB9CD150054624C /* FakePopoverTipViewStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03C7E7A12CB9CD0B0054624C /* FakePopoverTipViewStyle.swift */; }; + 03C7E7A22CB9CD150054624C /* PointDownEmojiTipViewStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03C7E7A12CB9CD0B0054624C /* PointDownEmojiTipViewStyle.swift */; }; 03C8B4962C6D065900A07CCD /* ImageViewer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03C8B4952C6D065900A07CCD /* ImageViewer.swift */; }; 03D1B4282C3C1A5D001778CD /* NostrIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03D1B4272C3C1A5D001778CD /* NostrIdentifier.swift */; }; 03D1B4292C3C1AC9001778CD /* NostrIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03D1B4272C3C1A5D001778CD /* NostrIdentifier.swift */; }; @@ -665,7 +665,7 @@ 03C49AC12C938DE100502321 /* SoupOpenGraphParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoupOpenGraphParser.swift; sourceTree = ""; }; 03C7E7912CB9C0AF0054624C /* WelcomeToFeedTip.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeToFeedTip.swift; sourceTree = ""; }; 03C7E7972CB9C1600054624C /* InlineTipViewStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InlineTipViewStyle.swift; sourceTree = ""; }; - 03C7E7A12CB9CD0B0054624C /* FakePopoverTipViewStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FakePopoverTipViewStyle.swift; sourceTree = ""; }; + 03C7E7A12CB9CD0B0054624C /* PointDownEmojiTipViewStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PointDownEmojiTipViewStyle.swift; sourceTree = ""; }; 03C8B4952C6D065900A07CCD /* ImageViewer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageViewer.swift; sourceTree = ""; }; 03D1B4272C3C1A5D001778CD /* NostrIdentifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NostrIdentifier.swift; sourceTree = ""; }; 03D1B42B2C3C1B0D001778CD /* TLVElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TLVElement.swift; sourceTree = ""; }; @@ -1755,7 +1755,7 @@ isa = PBXGroup; children = ( 5B0D99022A94090A0039F0C5 /* DoubleTapToPopModifier.swift */, - 03C7E7A12CB9CD0B0054624C /* FakePopoverTipViewStyle.swift */, + 03C7E7A12CB9CD0B0054624C /* PointDownEmojiTipViewStyle.swift */, 03C7E7972CB9C1600054624C /* InlineTipViewStyle.swift */, C95D68A8299E709800429F86 /* LinearGradient+Planetary.swift */, C95D68A4299E6E1E00429F86 /* PlaceholderModifier.swift */, @@ -2399,7 +2399,7 @@ C9AC31AD2A55E0BD00A94E5A /* NotificationViewModel.swift in Sources */, 0326347A2C10C57A00E489B5 /* FileStorageAPIClient.swift in Sources */, C9EE3E632A053910008A7491 /* ExpirationTimeOption.swift in Sources */, - 03C7E7A22CB9CD150054624C /* FakePopoverTipViewStyle.swift in Sources */, + 03C7E7A22CB9CD150054624C /* PointDownEmojiTipViewStyle.swift in Sources */, C9A0DAE029C697A100466635 /* AboutView.swift in Sources */, C9E8C1132B081E9C002D46B0 /* UNSNameView.swift in Sources */, 0496D6312C975E6900D29375 /* FlagOptionPicker.swift in Sources */, diff --git a/Nos/Views/Discover/DiscoverTab.swift b/Nos/Views/Discover/DiscoverTab.swift index a298d15ec..b09ebe43d 100644 --- a/Nos/Views/Discover/DiscoverTab.swift +++ b/Nos/Views/Discover/DiscoverTab.swift @@ -38,7 +38,7 @@ struct DiscoverTab: View { .padding(.horizontal, 12) .padding(.bottom, 8) .tipBackground(LinearGradient.horizontalAccentReversed) - .tipViewStyle(.fakePopover) + .tipViewStyle(.pointDownEmoji) } } .searchable( diff --git a/Nos/Views/Modifiers/FakePopoverTipViewStyle.swift b/Nos/Views/Modifiers/PointDownEmojiTipViewStyle.swift similarity index 74% rename from Nos/Views/Modifiers/FakePopoverTipViewStyle.swift rename to Nos/Views/Modifiers/PointDownEmojiTipViewStyle.swift index cf4a68473..7abd3e25c 100644 --- a/Nos/Views/Modifiers/FakePopoverTipViewStyle.swift +++ b/Nos/Views/Modifiers/PointDownEmojiTipViewStyle.swift @@ -1,7 +1,8 @@ import TipKit -/// A fake popover tip view style that has a pointing down emoji (👇) in the bottom left instead of the popover chevron. -struct FakePopoverTipViewStyle: TipViewStyle { +/// A popover tip view style that has a point down emoji (👇) in the bottom left in addition to the title and +/// close button. +struct PointDownEmojiTipViewStyle: TipViewStyle { func makeBody(configuration: TipViewStyle.Configuration) -> some View { VStack(alignment: .leading, spacing: 10) { HStack(alignment: .top) { @@ -28,6 +29,6 @@ struct FakePopoverTipViewStyle: TipViewStyle { } } -extension TipViewStyle where Self == FakePopoverTipViewStyle { - static var fakePopover: Self { Self() } +extension TipViewStyle where Self == PointDownEmojiTipViewStyle { + static var pointDownEmoji: Self { Self() } } From 4c99474e1d07a2438dc0c31872fd484bfb65912f Mon Sep 17 00:00:00 2001 From: Josh Brown Date: Tue, 15 Oct 2024 16:11:15 -0400 Subject: [PATCH 6/9] sort Modifiers group by name --- Nos.xcodeproj/project.pbxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Nos.xcodeproj/project.pbxproj b/Nos.xcodeproj/project.pbxproj index ebb2bb927..20484f32a 100644 --- a/Nos.xcodeproj/project.pbxproj +++ b/Nos.xcodeproj/project.pbxproj @@ -1755,10 +1755,10 @@ isa = PBXGroup; children = ( 5B0D99022A94090A0039F0C5 /* DoubleTapToPopModifier.swift */, - 03C7E7A12CB9CD0B0054624C /* PointDownEmojiTipViewStyle.swift */, 03C7E7972CB9C1600054624C /* InlineTipViewStyle.swift */, C95D68A8299E709800429F86 /* LinearGradient+Planetary.swift */, C95D68A4299E6E1E00429F86 /* PlaceholderModifier.swift */, + 03C7E7A12CB9CD0B0054624C /* PointDownEmojiTipViewStyle.swift */, C9A25B3C29F174D200B39534 /* ReadabilityPadding.swift */, C9E37E0E2A1E7C32003D4B0A /* ReportMenuModifier.swift */, C9A0DAE629C69FA000466635 /* Text+Gradient.swift */, From c00d4156657fe85a11366e7a83aaac9bb91bb976 Mon Sep 17 00:00:00 2001 From: Josh Brown Date: Tue, 15 Oct 2024 18:16:16 -0400 Subject: [PATCH 7/9] add readability padding to Go to Feed tip --- Nos/Views/Discover/DiscoverTab.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Nos/Views/Discover/DiscoverTab.swift b/Nos/Views/Discover/DiscoverTab.swift index b09ebe43d..e26e8ae48 100644 --- a/Nos/Views/Discover/DiscoverTab.swift +++ b/Nos/Views/Discover/DiscoverTab.swift @@ -37,6 +37,7 @@ struct DiscoverTab: View { TipView(goToFeedTip) .padding(.horizontal, 12) .padding(.bottom, 8) + .readabilityPadding() .tipBackground(LinearGradient.horizontalAccentReversed) .tipViewStyle(.pointDownEmoji) } From 0db470ffe2533f26bce3292ec71bf90cf493f0a2 Mon Sep 17 00:00:00 2001 From: Josh Brown Date: Wed, 16 Oct 2024 15:33:13 -0400 Subject: [PATCH 8/9] add analytics, fix bug, display tip on top of scroll view --- Nos.xcodeproj/project.pbxproj | 4 +++ Nos/Service/Analytics.swift | 29 +++++++++++++++---- Nos/Views/Discover/DiscoverTab.swift | 43 +++++++++------------------- Nos/Views/Discover/GoToFeedTip.swift | 26 +++++++++++++++++ Nos/Views/Home/HomeFeedView.swift | 6 ++++ 5 files changed, 73 insertions(+), 35 deletions(-) create mode 100644 Nos/Views/Discover/GoToFeedTip.swift diff --git a/Nos.xcodeproj/project.pbxproj b/Nos.xcodeproj/project.pbxproj index a21a67fb1..c986d5075 100644 --- a/Nos.xcodeproj/project.pbxproj +++ b/Nos.xcodeproj/project.pbxproj @@ -92,6 +92,7 @@ 039C961F2C480F4100A8EB39 /* unsupported_kinds.json in Resources */ = {isa = PBXBuildFile; fileRef = 039C961E2C480F4100A8EB39 /* unsupported_kinds.json */; }; 039C96292C48321E00A8EB39 /* long_form_data.json in Resources */ = {isa = PBXBuildFile; fileRef = 039C96282C48321E00A8EB39 /* long_form_data.json */; }; 03A3AA3B2C5028FF008FE153 /* PublicKeyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A3AA3A2C5028FF008FE153 /* PublicKeyTests.swift */; }; + 03A743452CC048C700893CAE /* GoToFeedTip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A743442CC048C700893CAE /* GoToFeedTip.swift */; }; 03B4E6A22C125CA1006E5F59 /* nostr_build_nip96_upload_response.json in Resources */ = {isa = PBXBuildFile; fileRef = 03B4E6A12C125CA1006E5F59 /* nostr_build_nip96_upload_response.json */; }; 03B4E6AC2C125D13006E5F59 /* FileStorageUploadResponseJSONTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03B4E6AB2C125D13006E5F59 /* FileStorageUploadResponseJSONTests.swift */; }; 03B4E6AE2C125D61006E5F59 /* FileStorageUploadResponseJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03B4E6AD2C125D61006E5F59 /* FileStorageUploadResponseJSON.swift */; }; @@ -639,6 +640,7 @@ 039C961E2C480F4100A8EB39 /* unsupported_kinds.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = unsupported_kinds.json; sourceTree = ""; }; 039C96282C48321E00A8EB39 /* long_form_data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = long_form_data.json; sourceTree = ""; }; 03A3AA3A2C5028FF008FE153 /* PublicKeyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PublicKeyTests.swift; sourceTree = ""; }; + 03A743442CC048C700893CAE /* GoToFeedTip.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GoToFeedTip.swift; sourceTree = ""; }; 03AB2F7D2BF6609500B73DB1 /* UnitTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = UnitTests.xctestplan; sourceTree = ""; }; 03B4E6A12C125CA1006E5F59 /* nostr_build_nip96_upload_response.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = nostr_build_nip96_upload_response.json; sourceTree = ""; }; 03B4E6AB2C125D13006E5F59 /* FileStorageUploadResponseJSONTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileStorageUploadResponseJSONTests.swift; sourceTree = ""; }; @@ -1537,6 +1539,7 @@ 65BD8DBE2BDAF2C300802039 /* DiscoverTab.swift */, 030AE4282BE3D63C004DEE02 /* FeaturedAuthor.swift */, 65BD8DBF2BDAF2C300802039 /* FeaturedAuthorCategory.swift */, + 03A743442CC048C700893CAE /* GoToFeedTip.swift */, ); path = Discover; sourceTree = ""; @@ -2385,6 +2388,7 @@ C9671D73298DB94C00EE7E12 /* Data+Encoding.swift in Sources */, 03C7E7922CB9C0B30054624C /* WelcomeToFeedTip.swift in Sources */, C9646EA129B7A22C007239A4 /* Analytics.swift in Sources */, + 03A743452CC048C700893CAE /* GoToFeedTip.swift in Sources */, 5045540D2C81E10C0044ECAE /* EditableAvatarView.swift in Sources */, DC4AB2F62A4475B800D1478A /* AppDelegate.swift in Sources */, 5B8C96B229DB313300B73AEC /* AuthorCard.swift in Sources */, diff --git a/Nos/Service/Analytics.swift b/Nos/Service/Analytics.swift index bbef658f7..323847049 100644 --- a/Nos/Service/Analytics.swift +++ b/Nos/Service/Analytics.swift @@ -43,7 +43,7 @@ class Analytics { func completedOnboarding() { track("Completed Onboarding") } - + func showedHome() { track("Home Tab Tapped") } @@ -232,7 +232,7 @@ class Analytics { track("Push Notification Registration Failed", properties: ["reason": reason]) } - // MARK: NIP-05 Usernames + // MARK: - NIP-05 Usernames func showedNIP05Wizard() { track("Showed NIP-05 Wizard") @@ -250,8 +250,8 @@ class Analytics { track("Deleted NIP-05 Username") } - // MARK: Message Actions - + // MARK: - Message Actions + func copiedNoteIdentifier() { track("Copied Note Identifier") } @@ -276,7 +276,26 @@ class Analytics { track("Liked Note") } - // MARK: Uploads + // MARK: - Tips + + func dismissedGoToFeedTip() { + track("Go to Feed Tip Dismissed") + } + + func displayedGoToFeedTip() { + track("Go to Feed Tip Displayed") + } + + func dismissedWelcomeToFeedTip() { + track("Welcome to Feed Tip Dismissed") + } + + func displayedWelcomeToFeedTip() { + track("Welcome to Feed Tip Displayed") + } + + // MARK: - Uploads + func selectedUploadFromCamera() { track("Selected Upload From Camera") } diff --git a/Nos/Views/Discover/DiscoverTab.swift b/Nos/Views/Discover/DiscoverTab.swift index e26e8ae48..b349344e2 100644 --- a/Nos/Views/Discover/DiscoverTab.swift +++ b/Nos/Views/Discover/DiscoverTab.swift @@ -28,18 +28,26 @@ struct DiscoverTab: View { var body: some View { NosNavigationStack(path: $router.discoverPath) { ZStack { - VStack { - DiscoverContentsView( - featuredAuthorCategory: .all, - searchController: searchController - ) + DiscoverContentsView( + featuredAuthorCategory: .all, + searchController: searchController + ) + VStack { + Spacer() + TipView(goToFeedTip) .padding(.horizontal, 12) .padding(.bottom, 8) .readabilityPadding() .tipBackground(LinearGradient.horizontalAccentReversed) .tipViewStyle(.pointDownEmoji) + .onAppear { + analytics.displayedGoToFeedTip() + } + .onDisappear { + analytics.dismissedGoToFeedTip() + } } } .searchable( @@ -74,31 +82,6 @@ struct DiscoverTab: View { } } -/// A tip that's displayed on the Discover view after the user has followed three accounts. -struct GoToFeedTip: Tip { - /// A TipKit Event that tracks the number of accounts that have been followed. - static let followedAccount = Tips.Event(id: "followedAccount") - - /// A TipKit Event that tracks how many times the Feed has been displayed. - static let viewedFeed = Tips.Event(id: "viewedFeed") - - var title: Text { - Text("goToYourFeed") - } - - var rules: [Rule] { - // Each rule here is combined using the logical AND, so all rules must return true for the tip to display. - - #Rule(Self.followedAccount) { - $0.donations.count >= 3 - } - - #Rule(Self.viewedFeed) { - $0.donations.count < 2 // for whatever reason, HomeFeedView's onAppear is called before the user views it - } - } -} - struct SizePreferenceKey: PreferenceKey { static var defaultValue: CGSize = .zero diff --git a/Nos/Views/Discover/GoToFeedTip.swift b/Nos/Views/Discover/GoToFeedTip.swift new file mode 100644 index 000000000..87600398d --- /dev/null +++ b/Nos/Views/Discover/GoToFeedTip.swift @@ -0,0 +1,26 @@ +import TipKit + +/// A tip that's displayed on the Discover view after the user has followed three accounts. +struct GoToFeedTip: Tip { + /// A TipKit Event that tracks the number of accounts that have been followed. + static let followedAccount = Tips.Event(id: "followedAccount") + + /// A TipKit Event that tracks how many times the Feed has been displayed. + static let viewedFeed = Tips.Event(id: "viewedFeed") + + var title: Text { + Text("goToYourFeed") + } + + var rules: [Rule] { + // Each rule here is combined using the logical AND, so all rules must return true for the tip to display. + + #Rule(Self.followedAccount) { + $0.donations.count >= 3 + } + + #Rule(Self.viewedFeed) { + $0.donations.count < 1 + } + } +} diff --git a/Nos/Views/Home/HomeFeedView.swift b/Nos/Views/Home/HomeFeedView.swift index fd501a3fa..031e70a54 100644 --- a/Nos/Views/Home/HomeFeedView.swift +++ b/Nos/Views/Home/HomeFeedView.swift @@ -74,6 +74,12 @@ struct HomeFeedView: View { .readabilityPadding() .tipBackground(LinearGradient.horizontalAccentReversed) .tipViewStyle(.inline) + .onAppear { + analytics.displayedWelcomeToFeedTip() + } + .onDisappear { + analytics.dismissedWelcomeToFeedTip() + } PagedNoteListView( refreshController: $refreshController, From 3a39174146e8e4ec4aa8a4acf2286bd86b16651b Mon Sep 17 00:00:00 2001 From: Josh Brown Date: Thu, 17 Oct 2024 12:00:07 -0400 Subject: [PATCH 9/9] remove analytics from tips --- Nos/Service/Analytics.swift | 18 ------------------ Nos/Views/Discover/DiscoverTab.swift | 6 ------ Nos/Views/Home/HomeFeedView.swift | 6 ------ 3 files changed, 30 deletions(-) diff --git a/Nos/Service/Analytics.swift b/Nos/Service/Analytics.swift index 323847049..320350e15 100644 --- a/Nos/Service/Analytics.swift +++ b/Nos/Service/Analytics.swift @@ -276,24 +276,6 @@ class Analytics { track("Liked Note") } - // MARK: - Tips - - func dismissedGoToFeedTip() { - track("Go to Feed Tip Dismissed") - } - - func displayedGoToFeedTip() { - track("Go to Feed Tip Displayed") - } - - func dismissedWelcomeToFeedTip() { - track("Welcome to Feed Tip Dismissed") - } - - func displayedWelcomeToFeedTip() { - track("Welcome to Feed Tip Displayed") - } - // MARK: - Uploads func selectedUploadFromCamera() { diff --git a/Nos/Views/Discover/DiscoverTab.swift b/Nos/Views/Discover/DiscoverTab.swift index b349344e2..f7f2f814e 100644 --- a/Nos/Views/Discover/DiscoverTab.swift +++ b/Nos/Views/Discover/DiscoverTab.swift @@ -42,12 +42,6 @@ struct DiscoverTab: View { .readabilityPadding() .tipBackground(LinearGradient.horizontalAccentReversed) .tipViewStyle(.pointDownEmoji) - .onAppear { - analytics.displayedGoToFeedTip() - } - .onDisappear { - analytics.dismissedGoToFeedTip() - } } } .searchable( diff --git a/Nos/Views/Home/HomeFeedView.swift b/Nos/Views/Home/HomeFeedView.swift index 031e70a54..fd501a3fa 100644 --- a/Nos/Views/Home/HomeFeedView.swift +++ b/Nos/Views/Home/HomeFeedView.swift @@ -74,12 +74,6 @@ struct HomeFeedView: View { .readabilityPadding() .tipBackground(LinearGradient.horizontalAccentReversed) .tipViewStyle(.inline) - .onAppear { - analytics.displayedWelcomeToFeedTip() - } - .onDisappear { - analytics.dismissedWelcomeToFeedTip() - } PagedNoteListView( refreshController: $refreshController,