Skip to content

Commit

Permalink
Merge pull request #1629 from planetary-social/go-to-feed-tip
Browse files Browse the repository at this point in the history
#1601: Go to Your Feed tip
  • Loading branch information
joshuatbrown authored Oct 17, 2024
2 parents 0f47887 + 3a39174 commit e66f082
Show file tree
Hide file tree
Showing 10 changed files with 107 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
- Added a tag to published contact lists to help us detect the source of lost contact lists. [cleanstr#51](https://github.com/planetary-social/cleanstr/issues/51)
- Removed integration with Universal Name Space [#1636](https://github.com/planetary-social/nos/issues/1636)
Expand Down
10 changes: 9 additions & 1 deletion Nos.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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 */; };
Expand All @@ -102,6 +103,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 /* 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 */; };
Expand Down Expand Up @@ -638,13 +640,15 @@
039C961E2C480F4100A8EB39 /* unsupported_kinds.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = unsupported_kinds.json; sourceTree = "<group>"; };
039C96282C48321E00A8EB39 /* long_form_data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = long_form_data.json; sourceTree = "<group>"; };
03A3AA3A2C5028FF008FE153 /* PublicKeyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PublicKeyTests.swift; sourceTree = "<group>"; };
03A743442CC048C700893CAE /* GoToFeedTip.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GoToFeedTip.swift; sourceTree = "<group>"; };
03AB2F7D2BF6609500B73DB1 /* UnitTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = UnitTests.xctestplan; sourceTree = "<group>"; };
03B4E6A12C125CA1006E5F59 /* nostr_build_nip96_upload_response.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = nostr_build_nip96_upload_response.json; sourceTree = "<group>"; };
03B4E6AB2C125D13006E5F59 /* FileStorageUploadResponseJSONTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileStorageUploadResponseJSONTests.swift; sourceTree = "<group>"; };
03B4E6AD2C125D61006E5F59 /* FileStorageUploadResponseJSON.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileStorageUploadResponseJSON.swift; sourceTree = "<group>"; };
03C49AC12C938DE100502321 /* SoupOpenGraphParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoupOpenGraphParser.swift; sourceTree = "<group>"; };
03C7E7912CB9C0AF0054624C /* WelcomeToFeedTip.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeToFeedTip.swift; sourceTree = "<group>"; };
03C7E7972CB9C1600054624C /* InlineTipViewStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InlineTipViewStyle.swift; sourceTree = "<group>"; };
03C7E7A12CB9CD0B0054624C /* PointDownEmojiTipViewStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PointDownEmojiTipViewStyle.swift; sourceTree = "<group>"; };
03C8B4952C6D065900A07CCD /* ImageViewer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageViewer.swift; sourceTree = "<group>"; };
03D1B4272C3C1A5D001778CD /* NostrIdentifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NostrIdentifier.swift; sourceTree = "<group>"; };
03D1B42B2C3C1B0D001778CD /* TLVElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TLVElement.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1535,6 +1539,7 @@
65BD8DBE2BDAF2C300802039 /* DiscoverTab.swift */,
030AE4282BE3D63C004DEE02 /* FeaturedAuthor.swift */,
65BD8DBF2BDAF2C300802039 /* FeaturedAuthorCategory.swift */,
03A743442CC048C700893CAE /* GoToFeedTip.swift */,
);
path = Discover;
sourceTree = "<group>";
Expand Down Expand Up @@ -1691,10 +1696,11 @@
C9CFF6D02AB241EB00D4B368 /* Modifiers */ = {
isa = PBXGroup;
children = (
03C7E7972CB9C1600054624C /* InlineTipViewStyle.swift */,
5B0D99022A94090A0039F0C5 /* DoubleTapToPopModifier.swift */,
03C7E7972CB9C1600054624C /* InlineTipViewStyle.swift */,
C95D68A8299E709800429F86 /* LinearGradient+Planetary.swift */,
C95D68A4299E6E1E00429F86 /* PlaceholderModifier.swift */,
03C7E7A12CB9CD0B0054624C /* PointDownEmojiTipViewStyle.swift */,
C9A25B3C29F174D200B39534 /* ReadabilityPadding.swift */,
C9E37E0E2A1E7C32003D4B0A /* ReportMenuModifier.swift */,
C9A0DAE629C69FA000466635 /* Text+Gradient.swift */,
Expand Down Expand Up @@ -2331,6 +2337,7 @@
C9AC31AD2A55E0BD00A94E5A /* NotificationViewModel.swift in Sources */,
0326347A2C10C57A00E489B5 /* FileStorageAPIClient.swift in Sources */,
C9EE3E632A053910008A7491 /* ExpirationTimeOption.swift in Sources */,
03C7E7A22CB9CD150054624C /* PointDownEmojiTipViewStyle.swift in Sources */,
C9A0DAE029C697A100466635 /* AboutView.swift in Sources */,
0496D6312C975E6900D29375 /* FlagOptionPicker.swift in Sources */,
A351E1A229BA92240009B7F6 /* ProfileEditView.swift in Sources */,
Expand Down Expand Up @@ -2381,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 */,
Expand Down
12 changes: 12 additions & 0 deletions Nos/Assets/Localization/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -8920,6 +8920,18 @@
}
}
},
"goToYourFeed" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Go to your Feed to see notes from your connections."
}
}
}
},

"homeFeed" : {
"extractionState" : "manual",
"localizations" : {
Expand Down
11 changes: 6 additions & 5 deletions Nos/Service/Analytics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class Analytics {
func completedOnboarding() {
track("Completed Onboarding")
}

func showedHome() {
track("Home Tab Tapped")
}
Expand Down Expand Up @@ -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")
Expand All @@ -250,8 +250,8 @@ class Analytics {
track("Deleted NIP-05 Username")
}

// MARK: Message Actions
// MARK: - Message Actions

func copiedNoteIdentifier() {
track("Copied Note Identifier")
}
Expand All @@ -276,7 +276,8 @@ class Analytics {
track("Liked Note")
}

// MARK: Uploads
// MARK: - Uploads

func selectedUploadFromCamera() {
track("Selected Upload From Camera")
}
Expand Down
1 change: 1 addition & 0 deletions Nos/Views/Components/Button/CircularFollowButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ struct CircularFollowButton: View {
} else {
try await currentUser.follow(author: author)
analytics.followed(author)
GoToFeedTip.followedAccount.sendDonation()
}
} catch {
crashReporting.report(error)
Expand Down
1 change: 1 addition & 0 deletions Nos/Views/Components/Button/FollowButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ struct FollowButton: View {
} else {
try await currentUser.follow(author: author)
analytics.followed(author)
GoToFeedTip.followedAccount.sendDonation()
}
} catch {
crashReporting.report(error)
Expand Down
16 changes: 15 additions & 1 deletion Nos/Views/Discover/DiscoverTab.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -20,6 +21,8 @@ struct DiscoverTab: View {

@State var predicate: NSPredicate = .false

let goToFeedTip = GoToFeedTip()

// MARK: - View

var body: some View {
Expand All @@ -29,6 +32,17 @@ struct DiscoverTab: View {
featuredAuthorCategory: .all,
searchController: searchController
)

VStack {
Spacer()

TipView(goToFeedTip)
.padding(.horizontal, 12)
.padding(.bottom, 8)
.readabilityPadding()
.tipBackground(LinearGradient.horizontalAccentReversed)
.tipViewStyle(.pointDownEmoji)
}
}
.searchable(
text: $searchController.query,
Expand Down
26 changes: 26 additions & 0 deletions Nos/Views/Discover/GoToFeedTip.swift
Original file line number Diff line number Diff line change
@@ -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
}
}
}
3 changes: 2 additions & 1 deletion Nos/Views/Home/HomeFeedView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -154,13 +154,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()
}
}
}
Expand Down
34 changes: 34 additions & 0 deletions Nos/Views/Modifiers/PointDownEmojiTipViewStyle.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import TipKit

/// 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) {
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 == PointDownEmojiTipViewStyle {
static var pointDownEmoji: Self { Self() }
}

0 comments on commit e66f082

Please sign in to comment.