Skip to content

Commit

Permalink
added lists view and two ways to navigate to it
Browse files Browse the repository at this point in the history
  • Loading branch information
bryanmontz committed Jan 8, 2025
1 parent deb11e0 commit a0a5686
Show file tree
Hide file tree
Showing 10 changed files with 240 additions and 21 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Release Notes

- Fixed: adding/removing relays not reflected on feed filter. [#119](https://github.com/verse-pbc/issues/issues/119)
- Added Lists view and two ways to navigate to it.

### Internal Changes

Expand Down
12 changes: 12 additions & 0 deletions Nos.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@
50EA86D42D28150F001E62CC /* FeedSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50EA86D32D28150D001E62CC /* FeedSource.swift */; };
50EA86D52D28150F001E62CC /* FeedSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50EA86D32D28150D001E62CC /* FeedSource.swift */; };
50EA885C2D2D523F001E62CC /* follow_set_with_unknown_tag.json in Resources */ = {isa = PBXBuildFile; fileRef = 50EA885B2D2D5235001E62CC /* follow_set_with_unknown_tag.json */; };
50EA886F2D2D5783001E62CC /* ListsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50EA886E2D2D5780001E62CC /* ListsView.swift */; };
50F695072C6392C4000E4C74 /* zap_receipt.json in Resources */ = {isa = PBXBuildFile; fileRef = 50F695062C6392C4000E4C74 /* zap_receipt.json */; };
5B098DBC2BDAF6CB00500A1B /* NoteParserTests+NIP08.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B098DBB2BDAF6CB00500A1B /* NoteParserTests+NIP08.swift */; };
5B098DC62BDAF73500500A1B /* AttributedString+Links.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B098DC52BDAF73500500A1B /* AttributedString+Links.swift */; };
Expand Down Expand Up @@ -793,6 +794,7 @@
50E2EB712C86175900D4B360 /* NSRegularExpression+Replacement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSRegularExpression+Replacement.swift"; sourceTree = "<group>"; };
50EA86D32D28150D001E62CC /* FeedSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedSource.swift; sourceTree = "<group>"; };
50EA885B2D2D5235001E62CC /* follow_set_with_unknown_tag.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = follow_set_with_unknown_tag.json; sourceTree = "<group>"; };
50EA886E2D2D5780001E62CC /* ListsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListsView.swift; sourceTree = "<group>"; };
50F695062C6392C4000E4C74 /* zap_receipt.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = zap_receipt.json; sourceTree = "<group>"; };
5B098DBB2BDAF6CB00500A1B /* NoteParserTests+NIP08.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NoteParserTests+NIP08.swift"; sourceTree = "<group>"; };
5B098DC52BDAF73500500A1B /* AttributedString+Links.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AttributedString+Links.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1580,6 +1582,14 @@
path = Onboarding;
sourceTree = "<group>";
};
50EA886D2D2D5776001E62CC /* Lists */ = {
isa = PBXGroup;
children = (
50EA886E2D2D5780001E62CC /* ListsView.swift */,
);
path = Lists;
sourceTree = "<group>";
};
5B79F5E92B97B5D7002DA9BE /* Edit */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -2069,6 +2079,7 @@
65BD8DC12BDAF2C300802039 /* Discover */,
03618B112C825D8700BCBC55 /* Fixtures */,
C96877B32B4EDCCF0051ED2F /* Home */,
50EA886D2D2D5776001E62CC /* Lists */,
04368D542C99D32B00DEAA2E /* Moderation */,
C9CFF6D02AB241EB00D4B368 /* Modifiers */,
03618C6D2C8267E600BCBC55 /* Note */,
Expand Down Expand Up @@ -2418,6 +2429,7 @@
5BC0D9CC2B867B9D005D6980 /* NamesAPI.swift in Sources */,
C987F81D29BA6D9A00B44E7A /* ProfileTab.swift in Sources */,
C9ADB14129951CB10075E7F8 /* NSManagedObject+Nos.swift in Sources */,
50EA886F2D2D5783001E62CC /* ListsView.swift in Sources */,
503CA9792D19C39F00805EF8 /* FeedCustomizerView.swift in Sources */,
C9F84C21298DC36800C6714D /* AppView.swift in Sources */,
C9CE5B142A0172CF008E198C /* WebView.swift in Sources */,
Expand Down
66 changes: 66 additions & 0 deletions Nos/Assets/Localization/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -4755,6 +4755,17 @@
}
}
},
"deleteList" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Delete List"
}
}
}
},
"deleteMyAccount" : {
"extractionState" : "manual",
"localizations" : {
Expand Down Expand Up @@ -5822,6 +5833,17 @@
}
}
},
"editListInfo" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Edit List Info"
}
}
}
},
"editProfile" : {
"extractionState" : "manual",
"localizations" : {
Expand Down Expand Up @@ -10412,6 +10434,17 @@
}
}
},
"lists" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Lists"
}
}
}
},
"loading" : {
"extractionState" : "manual",
"localizations" : {
Expand Down Expand Up @@ -10887,6 +10920,28 @@
}
}
},
"manageUsers" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Manage Users"
}
}
}
},
"manageYourLists" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Manage Your Lists"
}
}
}
},
"mention" : {
"extractionState" : "manual",
"localizations" : {
Expand Down Expand Up @@ -20313,6 +20368,17 @@
}
}
},
"yourLists" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Your Lists"
}
}
}
},
"yourProfile" : {
"extractionState" : "manual",
"localizations" : {
Expand Down
12 changes: 2 additions & 10 deletions Nos/Controller/FeedController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import SwiftUI
private(set) var listRowItems: [FeedToggleRow.Item] = []
private(set) var relayRowItems: [FeedToggleRow.Item] = []

private var lists: [AuthorList] = [] {
private(set) var lists: [AuthorList] = [] {
didSet {
updateEnabledSources()
}
Expand All @@ -38,16 +38,8 @@ import SwiftUI
}

@ObservationIgnored private lazy var listsPublisher = {
let request = NSFetchRequest<AuthorList>(entityName: "AuthorList")
request.sortDescriptors = [NSSortDescriptor(keyPath: \Event.createdAt, ascending: false)]
request.predicate = NSPredicate(
format: "kind = %i AND author = %@ AND title != nil",
EventKind.followSet.rawValue,
author
)

let listWatcher = NSFetchedResultsController(
fetchRequest: request,
fetchRequest: AuthorList.authorLists(ownedBy: author),
managedObjectContext: persistenceController.viewContext,
sectionNameKeyPath: nil,
cacheName: "FeedController.listWatcher"
Expand Down
11 changes: 11 additions & 0 deletions Nos/Models/CoreData/AuthorList+CoreDataClass.swift
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,15 @@ public class AuthorList: Event {
var allAuthors: Set<Author> {
authors.union(privateAuthors)
}

static func authorLists(ownedBy owner: Author) -> NSFetchRequest<AuthorList> {
let request = NSFetchRequest<AuthorList>(entityName: "AuthorList")
request.sortDescriptors = [NSSortDescriptor(keyPath: \Event.createdAt, ascending: false)]
request.predicate = NSPredicate(
format: "kind = %i AND author = %@ AND title != nil AND deletedOn.@count = 0",
EventKind.followSet.rawValue,
owner
)
return request
}
}
33 changes: 23 additions & 10 deletions Nos/Views/Home/FeedCustomizerView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ struct FeedCustomizerView: View {

@Environment(FeedController.self) var feedController
let author: Author
@Binding var shouldNavigateToLists: Bool
@Binding var shouldNavigateToRelays: Bool

@AppStorage("selectedFeedTogglesTab") private var selectedTab = FeedTab.lists
Expand All @@ -53,18 +54,30 @@ struct FeedCustomizerView: View {
items: feedController.listRowItems,
footer: {
Group {
Text("Create your own lists on ") +
Text("Listr ")
.foregroundStyle(Color.accent) +
Text(Image(systemName: "link"))
.foregroundStyle(Color.accent)
}
.padding()
.onTapGesture {
if let url = URL(string: "https://listr.lol/feed") {
UIApplication.shared.open(url)
if feedController.listRowItems.isEmpty {
Group {
Text("Create your own lists on ") +
Text("Listr ")
.foregroundStyle(Color.accent) +
Text(Image(systemName: "link"))
.foregroundStyle(Color.accent)
}
.onTapGesture {
if let url = URL(string: "https://listr.lol/feed") {
UIApplication.shared.open(url)
}
}
} else {
SecondaryActionButton(
"manageYourLists",
font: .clarity(.semibold, textStyle: .footnote),
image: Image(systemName: "slider.horizontal.3")
) {
shouldNavigateToLists = true
}
}
}
.padding()
},
noContent: {
Text("It doesn’t look like you have created any lists.") // TODO: localize
Expand Down
21 changes: 20 additions & 1 deletion Nos/Views/Home/HomeFeedView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ struct HomeFeedView: View {
/// to get some data from relay. The amount of time is defined in `staticLoadTime`.
@State private var showTimedLoadingIndicator = true

@State private var shouldNavigateToListsOnAppear = false
@State private var shouldNavigateToRelaysOnAppear = false

/// The amount of time (in seconds) the loading indicator will be shown when showTimedLoadingIndicator is set to
Expand Down Expand Up @@ -130,7 +131,11 @@ struct HomeFeedView: View {
.transition(.opacity)

VStack {
FeedCustomizerView(author: user, shouldNavigateToRelays: $shouldNavigateToRelaysOnAppear)
FeedCustomizerView(
author: user,
shouldNavigateToLists: $shouldNavigateToListsOnAppear,
shouldNavigateToRelays: $shouldNavigateToRelaysOnAppear
)
Spacer()
}
.transition(.move(edge: .top))
Expand Down Expand Up @@ -187,6 +192,17 @@ struct HomeFeedView: View {
GoToFeedTip.viewedFeed.sendDonation()
}
}
.onChange(of: shouldNavigateToListsOnAppear) {
if shouldNavigateToListsOnAppear {
showFeedSelector = false

DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(300)) {
router.push(ListsDestination(author: user))
}

shouldNavigateToListsOnAppear = false
}
}
.onChange(of: shouldNavigateToRelaysOnAppear) {
if shouldNavigateToRelaysOnAppear {
showFeedSelector = false
Expand All @@ -198,6 +214,9 @@ struct HomeFeedView: View {
shouldNavigateToRelaysOnAppear = false
}
}
.navigationDestination(for: ListsDestination.self) { destination in
ListsView(author: destination.author)
}
.navigationDestination(for: RelaysDestination.self) { destination in
RelayView(author: destination.author)
}
Expand Down
94 changes: 94 additions & 0 deletions Nos/Views/Lists/ListsView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import CoreData
import SwiftUI

struct ListsDestination: Hashable {
let author: Author
}

struct ListsView: View {
@Environment(\.managedObjectContext) private var viewContext

let author: Author

@FetchRequest var lists: FetchedResults<AuthorList>

init(author: Author) {
self.author = author
_lists = FetchRequest(fetchRequest: AuthorList.authorLists(ownedBy: author))
}

var body: some View {
ZStack {
Color.appBg

Group {
if lists.isEmpty {
VStack {
Image(systemName: "person.2")

Text("Add your favorite accounts to public lists and pin them to your home feed")
}
} else {
ScrollView {
VStack(spacing: 0) {
ForEach(lists) { list in
HStack {
VStack(alignment: .leading) {
Text(list.title ?? "")
.font(.body)

if let description = list.listDescription {
Text(description)
.foregroundStyle(Color.secondaryTxt)
.font(.footnote)
}
}

Spacer()

Menu {
Button("editListInfo") {
// TODO: Edit List Info
}
Button("manageUsers") {
// TODO: Manage Users
}
Button("deleteList", role: .destructive) {
// TODO: Delete List
}
} label: {
Image(systemName: "ellipsis")
.foregroundStyle(Color.secondaryTxt)
.fontWeight(.bold)
}
}
.padding(.horizontal, 16)
.padding(.vertical, 12)
.frame(minHeight: 50)

BeveledSeparator()
}
}
.background(LinearGradient.cardBackground)
.clipShape(RoundedRectangle(cornerRadius: 15))
.mimicCardButtonStyle()
}
.padding(EdgeInsets(top: 16, leading: 16, bottom: 16, trailing: 16))
}
}
}
.scrollContentBackground(.hidden)
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
ActionButton("new", action: newButtonPressed)
.frame(height: 22)
.padding(.bottom, 3)
}
}
.nosNavigationBar("yourLists")
}

private func newButtonPressed() {

Check failure on line 92 in Nos/Views/Lists/ListsView.swift

View workflow job for this annotation

GitHub Actions / swift_lint

Don't include vertical whitespace (empty line) before closing braces (vertical_whitespace_closing_braces)
}
}
1 change: 1 addition & 0 deletions Nos/Views/SideMenu/SideMenu.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ struct SideMenu: View {
enum Destination {
case settings
case relays
case lists
case profile
case about
}
Expand Down
Loading

0 comments on commit a0a5686

Please sign in to comment.