Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

show follow notification in tab #1727

Open
wants to merge 29 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
e75f954
update appDelegate
pelumy Jan 8, 2025
3ecfbb7
update NotificationViewModel
pelumy Jan 8, 2025
09b5895
update coredata classes
pelumy Jan 8, 2025
a05bdb7
update push notification service
pelumy Jan 8, 2025
c49006f
update NotificationView
pelumy Jan 8, 2025
dd9e6b4
clean up
pelumy Jan 9, 2025
5175b64
Merge remote-tracking branch 'origin/main' into it/127-follow-notific…
pelumy Jan 9, 2025
9846f80
add changelog
pelumy Jan 9, 2025
0361260
fix swiftlint warnings
pelumy Jan 9, 2025
98b792f
fix swiftlint warning
pelumy Jan 9, 2025
b66dcab
create new coredata model version
pelumy Jan 13, 2025
22fe772
write notifications unit test
pelumy Jan 13, 2025
48e1a77
update unit test
pelumy Jan 13, 2025
33ed191
update notificationViewModel
pelumy Jan 13, 2025
980c234
create Follows notification card
pelumy Jan 13, 2025
9619a7b
update Notification view and coredataclass
pelumy Jan 13, 2025
761a415
update databasecleaner
pelumy Jan 13, 2025
f4f51cf
cleanup
pelumy Jan 13, 2025
b23d1d9
use localised strings
pelumy Jan 13, 2025
c3d1074
Merge remote-tracking branch 'origin/main' into it/127-follow-notific…
pelumy Jan 13, 2025
27de0ce
fix comment
pelumy Jan 13, 2025
1f18b23
Merge remote-tracking branch 'origin/main' into it/127-follow-notific…
pelumy Jan 13, 2025
2fa4555
fix UI and autoscroll
pelumy Jan 14, 2025
afc211d
fetch events and nosNotifications on notificationView
pelumy Jan 17, 2025
5940bcc
Merge remote-tracking branch 'origin/main' into it/127-follow-notific…
pelumy Jan 17, 2025
b11162c
Revert "fetch events and nosNotifications on notificationView"
pelumy Jan 27, 2025
63f3481
delete notifications and events on launch if needed
pelumy Jan 28, 2025
286bb5f
Merge remote-tracking branch 'origin/main' into it/127-follow-notific…
pelumy Jan 28, 2025
bcdeb39
fix swiftlint warning
pelumy Jan 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Improved naming of a couple list-related classes.
- Track TestFlight vs AppStore installations in Posthog. [#130](https://github.com/verse-pbc/issues/issues/130)
- Track breadcrumbs in Sentry for all analytics events. [#125](https://github.com/verse-pbc/issues/issues/125)
- Added functionality to get follows notifications in the Notifications tab. [#127](https://github.com/verse-pbc/issues/issues/127)

## [1.1] - 2025-01-03Z

Expand Down
36 changes: 23 additions & 13 deletions Nos.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@
04368D2B2C99A2C400DEAA2E /* FlagOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04368D2A2C99A2C400DEAA2E /* FlagOption.swift */; };
04368D312C99A78800DEAA2E /* NosRadioButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04368D302C99A78800DEAA2E /* NosRadioButton.swift */; };
04368D4B2C99CFC700DEAA2E /* ContentFlagView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04368D4A2C99CFC700DEAA2E /* ContentFlagView.swift */; };
045027492D318E1300DA9835 /* NosNotificationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 045027482D318E1300DA9835 /* NosNotificationTests.swift */; };
045028002D35484400DA9835 /* FollowsNotificationCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 045027FF2D35484400DA9835 /* FollowsNotificationCard.swift */; };
045EDCF32CAAF47600B67964 /* FlagSuccessView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 045EDCF22CAAF47600B67964 /* FlagSuccessView.swift */; };
045EDD052CAC025700B67964 /* ScrollViewProxy+Animate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 045EDD042CAC025700B67964 /* ScrollViewProxy+Animate.swift */; };
0496D6312C975E6900D29375 /* FlagOptionPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0496D6302C975E6900D29375 /* FlagOptionPicker.swift */; };
Expand Down Expand Up @@ -739,6 +741,9 @@
04368D2A2C99A2C400DEAA2E /* FlagOption.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlagOption.swift; sourceTree = "<group>"; };
04368D302C99A78800DEAA2E /* NosRadioButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NosRadioButton.swift; sourceTree = "<group>"; };
04368D4A2C99CFC700DEAA2E /* ContentFlagView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentFlagView.swift; sourceTree = "<group>"; };
045027482D318E1300DA9835 /* NosNotificationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NosNotificationTests.swift; sourceTree = "<group>"; };
045027622D31A08D00DA9835 /* Nos 24.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Nos 24.xcdatamodel"; sourceTree = "<group>"; };
045027FF2D35484400DA9835 /* FollowsNotificationCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowsNotificationCard.swift; sourceTree = "<group>"; };
045EDCF22CAAF47600B67964 /* FlagSuccessView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlagSuccessView.swift; sourceTree = "<group>"; };
045EDD042CAC025700B67964 /* ScrollViewProxy+Animate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ScrollViewProxy+Animate.swift"; sourceTree = "<group>"; };
0496D6302C975E6900D29375 /* FlagOptionPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlagOptionPicker.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1382,6 +1387,7 @@
children = (
C94437E529B0DB83004D8C86 /* NotificationsView.swift */,
C98B8B3F29FBF83B009789C8 /* NotificationCard.swift */,
045027FF2D35484400DA9835 /* FollowsNotificationCard.swift */,
);
path = Notifications;
sourceTree = "<group>";
Expand Down Expand Up @@ -1447,6 +1453,7 @@
035729A12BE4167E005FEE85 /* AuthorTests.swift */,
035729A32BE4167E005FEE85 /* EventTests.swift */,
035729A42BE4167E005FEE85 /* FollowTests.swift */,
045027482D318E1300DA9835 /* NosNotificationTests.swift */,
);
path = CoreData;
sourceTree = "<group>";
Expand Down Expand Up @@ -2258,7 +2265,7 @@
C9B737702AB24D5F00398BE7 /* XCRemoteSwiftPackageReference "SwiftGenPlugin" */,
C91565BF2B2368FA0068EECA /* XCRemoteSwiftPackageReference "ViewInspector" */,
3AD3185B2B294E6200026B07 /* XCRemoteSwiftPackageReference "xcstrings-tool-plugin" */,
C9FD34F42BCEC89C008F8D95 /* XCRemoteSwiftPackageReference "secp256k1.swift" */,
C9FD34F42BCEC89C008F8D95 /* XCRemoteSwiftPackageReference "secp256k1" */,
C9FD35112BCED5A6008F8D95 /* XCRemoteSwiftPackageReference "nostr-sdk-ios" */,
03C49ABE2C938A9C00502321 /* XCRemoteSwiftPackageReference "SwiftSoup" */,
039389212CA4985C00698978 /* XCRemoteSwiftPackageReference "SDWebImageWebPCoder" */,
Expand Down Expand Up @@ -2638,6 +2645,7 @@
C9CDBBA429A8FA2900C555C7 /* GoldenPostView.swift in Sources */,
C92F01582AC4D6F700972489 /* NosTextField.swift in Sources */,
C9C2B77C29E072E400548B4A /* WebSocket+Nos.swift in Sources */,
045028002D35484400DA9835 /* FollowsNotificationCard.swift in Sources */,
503CA9532D19ACCC00805EF8 /* HorizontalLine.swift in Sources */,
C9DEC003298945150078B43A /* String+Lorem.swift in Sources */,
04C9D7912CC29D5000EAAD4D /* FeaturedAuthor+Cohort1.swift in Sources */,
Expand Down Expand Up @@ -2804,6 +2812,7 @@
035729AC2BE4167E005FEE85 /* Bech32Tests.swift in Sources */,
C936B4632A4CB01C00DF1EB9 /* PushNotificationService.swift in Sources */,
C9C5475A2A4F1D8C006B0741 /* NosNotification+CoreDataClass.swift in Sources */,
045027492D318E1300DA9835 /* NosNotificationTests.swift in Sources */,
508133DC2C7A007700DFBF75 /* AttributedString+Quotation.swift in Sources */,
CD09A74929A521210063464F /* Router.swift in Sources */,
C90B16B82AFED96300CB4B85 /* URLExtensionTests.swift in Sources */,
Expand Down Expand Up @@ -2924,11 +2933,11 @@
/* Begin PBXTargetDependency section */
3AD3185D2B294E9000026B07 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
productRef = 3AD3185C2B294E9000026B07 /* plugin:XCStringsToolPlugin */;
productRef = 3AD3185C2B294E9000026B07 /* XCStringsToolPlugin */;
};
3AEABEF32B2BF806001BC933 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
productRef = 3AEABEF22B2BF806001BC933 /* plugin:XCStringsToolPlugin */;
productRef = 3AEABEF22B2BF806001BC933 /* XCStringsToolPlugin */;
};
C90862C229E9804B00C35A71 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
Expand All @@ -2937,11 +2946,11 @@
};
C9A6C7442AD83F7A001F9500 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
productRef = C9A6C7432AD83F7A001F9500 /* plugin:SwiftGenPlugin */;
productRef = C9A6C7432AD83F7A001F9500 /* SwiftGenPlugin */;
};
C9D573402AB24A3700E06BB4 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
productRef = C9D5733F2AB24A3700E06BB4 /* plugin:SwiftGenPlugin */;
productRef = C9D5733F2AB24A3700E06BB4 /* SwiftGenPlugin */;
};
C9DEBFE6298941020078B43A /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
Expand Down Expand Up @@ -3815,7 +3824,7 @@
minimumVersion = 4.0.0;
};
};
C9FD34F42BCEC89C008F8D95 /* XCRemoteSwiftPackageReference "secp256k1.swift" */ = {
C9FD34F42BCEC89C008F8D95 /* XCRemoteSwiftPackageReference "secp256k1" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/GigaBitcoin/secp256k1.swift";
requirement = {
Expand Down Expand Up @@ -3854,12 +3863,12 @@
package = 03C49ABE2C938A9C00502321 /* XCRemoteSwiftPackageReference "SwiftSoup" */;
productName = SwiftSoup;
};
3AD3185C2B294E9000026B07 /* plugin:XCStringsToolPlugin */ = {
3AD3185C2B294E9000026B07 /* XCStringsToolPlugin */ = {
isa = XCSwiftPackageProductDependency;
package = 3AD3185B2B294E6200026B07 /* XCRemoteSwiftPackageReference "xcstrings-tool-plugin" */;
productName = "plugin:XCStringsToolPlugin";
};
3AEABEF22B2BF806001BC933 /* plugin:XCStringsToolPlugin */ = {
3AEABEF22B2BF806001BC933 /* XCStringsToolPlugin */ = {
isa = XCSwiftPackageProductDependency;
package = 3AD3185B2B294E6200026B07 /* XCRemoteSwiftPackageReference "xcstrings-tool-plugin" */;
productName = "plugin:XCStringsToolPlugin";
Expand Down Expand Up @@ -3938,7 +3947,7 @@
package = C99DBF7C2A9E81CF00F7068F /* XCRemoteSwiftPackageReference "SDWebImageSwiftUI" */;
productName = SDWebImageSwiftUI;
};
C9A6C7432AD83F7A001F9500 /* plugin:SwiftGenPlugin */ = {
C9A6C7432AD83F7A001F9500 /* SwiftGenPlugin */ = {
isa = XCSwiftPackageProductDependency;
package = C9B737702AB24D5F00398BE7 /* XCRemoteSwiftPackageReference "SwiftGenPlugin" */;
productName = "plugin:SwiftGenPlugin";
Expand All @@ -3958,7 +3967,7 @@
package = C9B71DBC2A8E9BAD0031ED9F /* XCRemoteSwiftPackageReference "sentry-cocoa" */;
productName = Sentry;
};
C9D5733F2AB24A3700E06BB4 /* plugin:SwiftGenPlugin */ = {
C9D5733F2AB24A3700E06BB4 /* SwiftGenPlugin */ = {
isa = XCSwiftPackageProductDependency;
package = C9C8450C2AB249DB00654BC1 /* XCRemoteSwiftPackageReference "SwiftGenPlugin" */;
productName = "plugin:SwiftGenPlugin";
Expand All @@ -3970,12 +3979,12 @@
};
C9FD34F52BCEC89C008F8D95 /* secp256k1 */ = {
isa = XCSwiftPackageProductDependency;
package = C9FD34F42BCEC89C008F8D95 /* XCRemoteSwiftPackageReference "secp256k1.swift" */;
package = C9FD34F42BCEC89C008F8D95 /* XCRemoteSwiftPackageReference "secp256k1" */;
productName = secp256k1;
};
C9FD34F72BCEC8B5008F8D95 /* secp256k1 */ = {
isa = XCSwiftPackageProductDependency;
package = C9FD34F42BCEC89C008F8D95 /* XCRemoteSwiftPackageReference "secp256k1.swift" */;
package = C9FD34F42BCEC89C008F8D95 /* XCRemoteSwiftPackageReference "secp256k1" */;
productName = secp256k1;
};
C9FD35122BCED5A6008F8D95 /* NostrSDK */ = {
Expand All @@ -3999,6 +4008,7 @@
C936B4572A4C7B7C00DF1EB9 /* Nos.xcdatamodeld */ = {
isa = XCVersionGroup;
children = (
045027622D31A08D00DA9835 /* Nos 24.xcdatamodel */,
5022F9472D2188650012FF4B /* Nos 23.xcdatamodel */,
503CAB7B2D1DA6DB00805EF8 /* Nos 22.xcdatamodel */,
0303B11E2D0257D400077929 /* Nos 21.xcdatamodel */,
Expand All @@ -4015,7 +4025,7 @@
C9C547562A4F1D1A006B0741 /* Nos 9.xcdatamodel */,
5BFF66AF2A4B55FC00AA79DD /* Nos 10.xcdatamodel */,
);
currentVersion = 5022F9472D2188650012FF4B /* Nos 23.xcdatamodel */;
currentVersion = 045027622D31A08D00DA9835 /* Nos 24.xcdatamodel */;
path = Nos.xcdatamodeld;
sourceTree = "<group>";
versionGroupType = wrapper.xcdatamodel;
Expand Down
3 changes: 3 additions & 0 deletions Nos/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Dependencies
import SDWebImage
import SDWebImageWebPCoder

@MainActor
class AppDelegate: NSObject, UIApplicationDelegate {

@Dependency(\.currentUser) private var currentUser
Expand Down Expand Up @@ -45,6 +46,8 @@ class AppDelegate: NSObject, UIApplicationDelegate {
do {
Log.info("PushNotifications: Received background notification. Subscribing to relays.")
analytics.receivedNotification()
// Call PushNotificationService to handle follow notifications
await pushNotificationService.application(application, didReceiveRemoteNotification: userInfo)
await currentUser.subscribe()
try await Task.sleep(for: .seconds(10))
Log.info("PushNotifications: Sync complete")
Expand Down
17 changes: 17 additions & 0 deletions Nos/Controller/PersistenceController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ final class PersistenceController {
/// Increment this to delete core data on update
private static let version = 3
private static let versionKey = "NosPersistenceControllerVersion"
private static let createdNosNotifications = "CreatedNosNotifications"

static var preview: PersistenceController = {
let controller = PersistenceController(inMemory: true)
Expand Down Expand Up @@ -41,13 +42,29 @@ final class PersistenceController {
private(set) var container: NSPersistentContainer
private let model: NSManagedObjectModel
private let inMemory: Bool
private var recreateNosNotifications: Bool {
get {
UserDefaults.standard.bool(forKey: Self.createdNosNotifications)
}
set {
UserDefaults.standard.set(newValue, forKey: Self.createdNosNotifications)
}
}

init(containerName: String = "Nos", inMemory: Bool = false, erase: Bool = false) {
self.inMemory = inMemory
let modelURL = Bundle.current.url(forResource: "Nos", withExtension: "momd")!
model = NSManagedObjectModel(contentsOf: modelURL)!
container = NSPersistentContainer(name: containerName, managedObjectModel: model)
setUp(erasingPrevious: erase)

if !recreateNosNotifications {
Task {
let context = newBackgroundContext()
try await DatabaseCleaner.deleteNotificationsAndEvents(in: context)
recreateNosNotifications = true
}
}
}

private func setUp(erasingPrevious: Bool) {
Expand Down
7 changes: 7 additions & 0 deletions Nos/Models/CoreData/Author+CoreDataClass.swift
Original file line number Diff line number Diff line change
Expand Up @@ -406,4 +406,11 @@ import Logger
// Publish the modified list
await currentUser.publishMuteList(keys: Array(Set(mutedList)))
}

/// Returns true if this event tagged the given author.
func this(author: Author) -> Bool {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this name should be a little more descriptive. If I just saw it at the call site like authorA.this(author: authorB) I would probably guess that it was some sort of equality check. The comment is confusing me too, because it says "if this event tagged" but this is a function on Author, so what event are we talking about?

followNotifications.contains(where: { element in
(element as? NosNotification)?.follower == author
})
}
}
2 changes: 2 additions & 0 deletions Nos/Models/CoreData/Event+Fetching.swift
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,9 @@ extension Event {
let readStoryClause = "(isRead = 1 AND receivedAt > %@)"
let userReportClause = "(kind == \(EventKind.report.rawValue) AND " +
"authorReferences.@count > 0 AND eventReferences.@count == 0)"
let notificationClause = "(notifications.@count = 0)"
let clauses = "\(oldUnreferencedEventsClause) AND" +
"\(notificationClause) AND " +
"\(notOwnEventClause) AND " +
"NOT \(readStoryClause) AND " +
"NOT \(userReportClause)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ extension Event {
@NSManaged public var seenOnRelays: Set<Relay>
@NSManaged public var shouldBePublishedTo: Set<Relay>
@NSManaged public var isRead: Bool
@NSManaged public var notifications: NosNotification?
}

// MARK: Generated accessors for authorReferences
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ extension NosNotification {
}

@NSManaged public var isRead: Bool
@NSManaged public var eventID: String?
@NSManaged public var user: Author?
@NSManaged public var follower: Author?
@NSManaged public var createdAt: Date?
@NSManaged public var event: Event?
}

extension NosNotification: Identifiable {}
2 changes: 1 addition & 1 deletion Nos/Models/CoreData/Nos.xcdatamodeld/.xccurrentversion
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
<plist version="1.0">
<dict>
<key>_XCCurrentVersionName</key>
<string>Nos 23.xcdatamodel</string>
<string>Nos 24.xcdatamodel</string>
</dict>
</plist>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?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>_XCCurrentVersionName</key>
<string>Nos.xcdatamodel</string>
</dict>
</plist>
Loading