Skip to content

Commit

Permalink
Merge pull request #1762 from planetary-social/bdm/1677-access-mutabi…
Browse files Browse the repository at this point in the history
…lity

audited codebase for strict access control and mutability annotations #185
  • Loading branch information
bryanmontz authored Feb 11, 2025
2 parents 7096b87 + 8ea7555 commit 34f5989
Show file tree
Hide file tree
Showing 147 changed files with 612 additions and 626 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added functionality to get follows notifications in the Notifications tab. [#127](https://github.com/verse-pbc/issues/issues/127)
- Refactored the way the ProfileView downloads data and logs analytics events. [#1748](https://github.com/planetary-social/nos/pull/1748)
- Refactored the way we close relay subscriptions. [#1754](https://github.com/planetary-social/nos/pull/1754)
- Audited codebase for strict access control and mutability annotations. [#185](https://github.com/verse-pbc/issues/issues/185)

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

Expand Down
12 changes: 6 additions & 6 deletions Nos.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
030036AB2C5D872B002C71F5 /* NewNotesButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030036AA2C5D872B002C71F5 /* NewNotesButton.swift */; };
0303B1532D025C9A00077929 /* AuthorList+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0303B13E2D025BDD00077929 /* AuthorList+CoreDataProperties.swift */; };
0303B1542D025C9A00077929 /* AuthorList+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0303B13E2D025BDD00077929 /* AuthorList+CoreDataProperties.swift */; };
0304D0A72C9B4BF2001D16C7 /* OpenGraphMetatdata.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0304D0A62C9B4BF2001D16C7 /* OpenGraphMetatdata.swift */; };
0304D0A82C9B4BF2001D16C7 /* OpenGraphMetatdata.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0304D0A62C9B4BF2001D16C7 /* OpenGraphMetatdata.swift */; };
0304D0A72C9B4BF2001D16C7 /* OpenGraphMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0304D0A62C9B4BF2001D16C7 /* OpenGraphMetadata.swift */; };
0304D0A82C9B4BF2001D16C7 /* OpenGraphMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0304D0A62C9B4BF2001D16C7 /* OpenGraphMetadata.swift */; };
0304D0B22C9B731F001D16C7 /* MockOpenGraphService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0304D0B12C9B731F001D16C7 /* MockOpenGraphService.swift */; };
0304D0B32C9B731F001D16C7 /* MockOpenGraphService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0304D0B12C9B731F001D16C7 /* MockOpenGraphService.swift */; };
030AE4292BE3D63C004DEE02 /* FeaturedAuthor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030AE4282BE3D63C004DEE02 /* FeaturedAuthor.swift */; };
Expand Down Expand Up @@ -639,7 +639,7 @@
030036AA2C5D872B002C71F5 /* NewNotesButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewNotesButton.swift; sourceTree = "<group>"; };
0303B11E2D0257D400077929 /* Nos 21.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Nos 21.xcdatamodel"; sourceTree = "<group>"; };
0303B13E2D025BDD00077929 /* AuthorList+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AuthorList+CoreDataProperties.swift"; sourceTree = "<group>"; };
0304D0A62C9B4BF2001D16C7 /* OpenGraphMetatdata.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenGraphMetatdata.swift; sourceTree = "<group>"; };
0304D0A62C9B4BF2001D16C7 /* OpenGraphMetadata.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenGraphMetadata.swift; sourceTree = "<group>"; };
0304D0B12C9B731F001D16C7 /* MockOpenGraphService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockOpenGraphService.swift; sourceTree = "<group>"; };
030AE4282BE3D63C004DEE02 /* FeaturedAuthor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeaturedAuthor.swift; sourceTree = "<group>"; };
030E56C92CC1BC6200A4A51E /* PublicKeyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PublicKeyView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1559,7 +1559,7 @@
03E7118B2C936DE5000B6F96 /* OpenGraph */ = {
isa = PBXGroup;
children = (
0304D0A62C9B4BF2001D16C7 /* OpenGraphMetatdata.swift */,
0304D0A62C9B4BF2001D16C7 /* OpenGraphMetadata.swift */,
03E711802C936DD1000B6F96 /* OpenGraphParser.swift */,
03C49AC12C938DE100502321 /* SoupOpenGraphParser.swift */,
);
Expand Down Expand Up @@ -2590,7 +2590,7 @@
03D1B42C2C3C1B0D001778CD /* TLVElement.swift in Sources */,
C987F85B29BA9ED800B44E7A /* Font+Clarity.swift in Sources */,
3FB5E651299D28A200386527 /* OnboardingView.swift in Sources */,
0304D0A72C9B4BF2001D16C7 /* OpenGraphMetatdata.swift in Sources */,
0304D0A72C9B4BF2001D16C7 /* OpenGraphMetadata.swift in Sources */,
C973AB5F2A323167002AED16 /* AuthorReference+CoreDataProperties.swift in Sources */,
030FECAB2CB5E0B900820014 /* BuildYourNetworkView.swift in Sources */,
A3B943CF299AE00100A15A08 /* Keychain.swift in Sources */,
Expand Down Expand Up @@ -2796,7 +2796,7 @@
035729CA2BE4173E005FEE85 /* PreviewData.swift in Sources */,
037975D12C0E341500ADDF37 /* MockFeatureFlags.swift in Sources */,
C92E7F682C4EFF3D00B80638 /* WebSocketErrorEvent.swift in Sources */,
0304D0A82C9B4BF2001D16C7 /* OpenGraphMetatdata.swift in Sources */,
0304D0A82C9B4BF2001D16C7 /* OpenGraphMetadata.swift in Sources */,
50089A0D2C97182200834588 /* CurrentUser+PublishEvents.swift in Sources */,
504454722C90729100251A7E /* Event+Hydration.swift in Sources */,
5BD08BB22A38E96F00BB926C /* JSONRelayMetadata.swift in Sources */,
Expand Down
2 changes: 1 addition & 1 deletion Nos/Controller/ContentWarningController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ enum ContentWarningType {

/// A class that takes a collection of content reports and generates a content warning string that can be
/// displayed to the user.
@Observable class ContentWarningController {
@Observable final class ContentWarningController {

var reports: [Event]
var type: ContentWarningType
Expand Down
6 changes: 3 additions & 3 deletions Nos/Controller/NoteEditorController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ import UIKit
///
/// To use: instantiate and pass into a `NoteTextEditor` view. You can retrieve the typed text via the `text` property
/// when the user indicates they are ready to post it.
@Observable class NoteEditorController: NSObject, UITextViewDelegate {
@Observable final class NoteEditorController: NSObject, UITextViewDelegate {

@ObservationIgnored @Dependency(\.analytics) private var analytics

/// The height that fits all entered text. This value will be updated by `NoteUITextViewRepresentable`
/// automatically, and should be used to set the frame of `NoteUITextViewRepresentable` from SwiftUI. This is done
/// to work around some incompatibilities between UIKit and SwiftUI where the UITextView won't expand properly.
var intrinsicHeight: CGFloat = 0
private(set) var intrinsicHeight: CGFloat = 0

/// A variable that controls whether the mention autocomplete window should be shown. This window is triggered
/// by typing an '@' symbol and allows the user to search for another user to mention in their note.
Expand All @@ -35,7 +35,7 @@ import UIKit
}

/// Whether the user has entered any text.
var isEmpty = true
private(set) var isEmpty = true

/// The attributed text the user has entered.
var text: AttributedString? {
Expand Down
8 changes: 4 additions & 4 deletions Nos/Controller/NoteWarningController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ extension Publisher {
}
}

@Observable @MainActor class NoteWarningController {
@Observable @MainActor final class NoteWarningController {

var showWarning: Bool {
if userHidWarning {
Expand All @@ -32,7 +32,7 @@ extension Publisher {
}
}
var userHidWarning = false
var outOfNetwork = false
private(set) var outOfNetwork = false

var note: Event? {
didSet {
Expand All @@ -47,8 +47,8 @@ extension Publisher {
@ObservationIgnored @Dependency(\.persistenceController) var persistenceController
@ObservationIgnored @Dependency(\.userDefaults) var userDefaults

var noteReports = [Event]()
var authorReports = [Event]()
private(set) var noteReports = [Event]()
private(set) var authorReports = [Event]()
private var cancellables = [AnyCancellable]()
private var noteReportsWatcher: NSFetchedResultsController<Event>?
private var authorReportsWatcher: NSFetchedResultsController<Event>?
Expand Down
14 changes: 7 additions & 7 deletions Nos/Controller/PagedNoteDataSource.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import Dependencies
import Logger

/// Works with ``PagedNoteListView`` to paginate reverse-chronological events from CoreData and relays simultaneously.
class PagedNoteDataSource<Header: View, EmptyPlaceholder: View>: NSObject, UICollectionViewDataSource,
final class PagedNoteDataSource<Header: View, EmptyPlaceholder: View>: NSObject, UICollectionViewDataSource,
NSFetchedResultsControllerDelegate, UICollectionViewDataSourcePrefetching {

var fetchedResultsController: NSFetchedResultsController<Event>
var collectionView: UICollectionView
private var fetchedResultsController: NSFetchedResultsController<Event>
private var collectionView: UICollectionView

@Dependency(\.relayService) private var relayService: RelayService
private(set) var databaseFilter: NSFetchRequest<Event>
Expand All @@ -18,12 +18,12 @@ class PagedNoteDataSource<Header: View, EmptyPlaceholder: View>: NSObject, UICol
private var managedObjectContext: NSManagedObjectContext
private var header: () -> Header
private var emptyPlaceholder: () -> EmptyPlaceholder
let pageSize = 20
private let pageSize = 20

// We intentionally generate unique IDs for cell reuse to get around
// [this issue](https://github.com/planetary-social/nos/issues/873)
lazy var headerReuseID = { "Header-\(self.description)" }()
lazy var footerReuseID = { "Footer-\(self.description)" }()
private lazy var headerReuseID = { "Header-\(self.description)" }()
private lazy var footerReuseID = { "Footer-\(self.description)" }()

init(
databaseFilter: NSFetchRequest<Event>,
Expand Down Expand Up @@ -198,7 +198,7 @@ class PagedNoteDataSource<Header: View, EmptyPlaceholder: View>: NSObject, UICol

/// Instructs the pager to load more data if we are getting close to the end of the object in the list.
/// - Parameter indexPath: the indexPath last loaded by the collection view.
func loadMoreIfNeeded(for indexPath: IndexPath) {
private func loadMoreIfNeeded(for indexPath: IndexPath) {
largestLoadedRowIndex = max(largestLoadedRowIndex, indexPath.row)
let lastPageStartIndex = (fetchedResultsController.fetchedObjects?.count ?? 0) - pageSize
if indexPath.row > lastPageStartIndex {
Expand Down
8 changes: 4 additions & 4 deletions Nos/Controller/PersistenceController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import BackgroundTasks

final class PersistenceController {

@Dependency(\.currentUser) var currentUser
@Dependency(\.crashReporting) var crashReporting
@Dependency(\.currentUser) private var currentUser
@Dependency(\.crashReporting) private var crashReporting

/// Increment this to delete core data on update
private static let version = 3
Expand Down Expand Up @@ -146,13 +146,13 @@ final class PersistenceController {
extension PersistenceController {

/// The ID of the background task that runs the `DatabaseCleaner`. Needs to match the value in Info.plist.
static let cleanupBackgroundTaskID = "com.verse.nos.database-cleaner"
private static let cleanupBackgroundTaskID = "com.verse.nos.database-cleaner"

/// Cleans up unneeded entities from the database. Our local database is really just a cache, and we need to
/// invalidate old items to keep it from growing indefinitely.
///
/// This should only be called once right at app launch.
@MainActor func cleanupEntities() async {
@MainActor private func cleanupEntities() async {
guard let authorKey = currentUser.author?.hexadecimalPublicKey else {
return
}
Expand Down
2 changes: 1 addition & 1 deletion Nos/Controller/RefreshController.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Foundation

/// Defines a common interface for refreshing.
@Observable @MainActor class RefreshController {
@Observable @MainActor final class RefreshController {
/// Whether a refresh should start or not. When this is `true`, the view and data source will begin refreshing.
var startRefresh: Bool

Expand Down
22 changes: 11 additions & 11 deletions Nos/Controller/SearchController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ enum SearchOrigin {
/// so this contains all search results, period.
private(set) var authorResults = [Author]()

var state: SearchState = .noQuery
private(set) var state: SearchState = .noQuery

@ObservationIgnored @Dependency(\.router) private var router
@ObservationIgnored @Dependency(\.relayService) private var relayService
@ObservationIgnored @Dependency(\.persistenceController) private var persistenceController
@ObservationIgnored @Dependency(\.currentUser) var currentUser
@ObservationIgnored @Dependency(\.currentUser) private var currentUser
@ObservationIgnored @Dependency(\.analytics) private var analytics

private var cancellables = [AnyCancellable]()
Expand All @@ -71,10 +71,10 @@ enum SearchOrigin {
private let stillLoadingTime: TimeInterval = 10

/// The origin of the current search.
let searchOrigin: SearchOrigin
private let searchOrigin: SearchOrigin

/// If true, will automatically trigger routing to detail views for exact matches of NIP-05s, npubs, and note ids.
let routesMatchesAutomatically: Bool
private let routesMatchesAutomatically: Bool

// MARK: - Init

Expand Down Expand Up @@ -126,7 +126,7 @@ enum SearchOrigin {
}

/// Observes changes in the `NSManagedObjectContext` and updates the query and author results.
func observeContextChanges() {
private func observeContextChanges() {
NotificationCenter.default.publisher(
for: NSNotification.Name.NSManagedObjectContextObjectsDidChange,
object: context
Expand All @@ -147,7 +147,7 @@ enum SearchOrigin {

// MARK: - Internal

func author(fromPublicKey publicKeyString: String) -> Author? {
private func author(fromPublicKey publicKeyString: String) -> Author? {
let strippedString = publicKeyString.trimmingCharacters(
in: NSCharacterSet.whitespacesAndNewlines
)
Expand All @@ -161,14 +161,14 @@ enum SearchOrigin {
return author
}

func authors(named name: String) -> [Author] {
private func authors(named name: String) -> [Author] {
guard let authors = try? Author.find(named: name, context: context) else {
return []
}
return authors.sorted(by: { $0.followers.count > $1.followers.count })
}

func clear() {
private func clear() {
state = .noQuery
searchSubscriptions.removeAll()
timer?.invalidate()
Expand Down Expand Up @@ -200,7 +200,7 @@ enum SearchOrigin {
/// - Warning: SIDE EFFECT WARNING:
/// These functions search other systems for the given query and add relevant authors to the database.
/// The database then generates a notification which is listened to above and results are reloaded.
func search(for query: String) {
private func search(for query: String) {
// if there are no results, go into the `loading` state (which will show the spinner)
// otherwise, keep showing the results
if state != .results {
Expand All @@ -213,7 +213,7 @@ enum SearchOrigin {
}
}

func searchRelays(for query: String) {
private func searchRelays(for query: String) {
Task {
let searchFilter = Filter(
kinds: [.metaData],
Expand All @@ -230,7 +230,7 @@ enum SearchOrigin {
}
}

func startSearchTimer() {
private func startSearchTimer() {
timer?.invalidate()

timer = Timer.scheduledTimer(withTimeInterval: stillLoadingTime, repeats: false) { _ in
Expand Down
2 changes: 1 addition & 1 deletion Nos/Extensions/NSManagedObject+Nos.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import CoreData
import Logger

public class NosManagedObject: NSManagedObject {
class NosManagedObject: NSManagedObject {

// Not sure why this is necessary, but SwiftUI previews crash on NSManagedObject.init(context:) otherwise.
convenience init(context: NSManagedObjectContext) {
Expand Down
Loading

0 comments on commit 34f5989

Please sign in to comment.