Skip to content

Commit

Permalink
added list detail view #155
Browse files Browse the repository at this point in the history
  • Loading branch information
bryanmontz committed Jan 17, 2025
1 parent ef72d5e commit b5bed57
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 53 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- 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. [#133](https://github.com/verse-pbc/issues/issues/133)
- Added view for editing a list's title and description. [#134](https://github.com/verse-pbc/issues/issues/134)
- Added List detail view. [#155](https://github.com/verse-pbc/issues/issues/155)

### Internal Changes
- Added function for creating a new list and a test verifying list editing. [#112](https://github.com/verse-pbc/issues/issues/112)
Expand Down
8 changes: 8 additions & 0 deletions Nos.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,8 @@
509533002C62535400E0BACA /* zap_request.json in Resources */ = {isa = PBXBuildFile; fileRef = 509532FF2C62535400E0BACA /* zap_request.json */; };
5095330B2C625B5D00E0BACA /* zap_request_one_sat.json in Resources */ = {isa = PBXBuildFile; fileRef = 509533092C625B5D00E0BACA /* zap_request_one_sat.json */; };
5095330C2C625B5D00E0BACA /* zap_request_no_amount.json in Resources */ = {isa = PBXBuildFile; fileRef = 5095330A2C625B5D00E0BACA /* zap_request_no_amount.json */; };
50CBD7AB2D39341B00BF8A0B /* AuthorListDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50CBD7AA2D39341700BF8A0B /* AuthorListDetailView.swift */; };
50CBD8152D3A8FED00BF8A0B /* ListCircle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50CBD80F2D3A8B6D00BF8A0B /* ListCircle.swift */; };
50DE6B1B2C6B88FE0065665D /* View+StyledBorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50DE6B1A2C6B88FE0065665D /* View+StyledBorder.swift */; };
50E2EB722C86175900D4B360 /* NSRegularExpression+Replacement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50E2EB712C86175900D4B360 /* NSRegularExpression+Replacement.swift */; };
50E2EB7B2C8617C800D4B360 /* NSRegularExpression+Replacement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50E2EB712C86175900D4B360 /* NSRegularExpression+Replacement.swift */; };
Expand Down Expand Up @@ -792,6 +794,8 @@
509532FF2C62535400E0BACA /* zap_request.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = zap_request.json; sourceTree = "<group>"; };
509533092C625B5D00E0BACA /* zap_request_one_sat.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = zap_request_one_sat.json; sourceTree = "<group>"; };
5095330A2C625B5D00E0BACA /* zap_request_no_amount.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = zap_request_no_amount.json; sourceTree = "<group>"; };
50CBD7AA2D39341700BF8A0B /* AuthorListDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthorListDetailView.swift; sourceTree = "<group>"; };
50CBD80F2D3A8B6D00BF8A0B /* ListCircle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListCircle.swift; sourceTree = "<group>"; };
50DE6B1A2C6B88FE0065665D /* View+StyledBorder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+StyledBorder.swift"; sourceTree = "<group>"; };
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>"; };
Expand Down Expand Up @@ -1589,8 +1593,10 @@
50EA886D2D2D5776001E62CC /* Lists */ = {
isa = PBXGroup;
children = (
50CBD7AA2D39341700BF8A0B /* AuthorListDetailView.swift */,
50EA886E2D2D5780001E62CC /* AuthorListsView.swift */,
50EA89A52D3010EA001E62CC /* EditAuthorListView.swift */,
50CBD80F2D3A8B6D00BF8A0B /* ListCircle.swift */,
);
path = Lists;
sourceTree = "<group>";
Expand Down Expand Up @@ -2512,6 +2518,7 @@
3F30020D29C382EB003D4F8B /* OnboardingLoginView.swift in Sources */,
C9A25B3D29F174D200B39534 /* ReadabilityPadding.swift in Sources */,
04C9D7952CC29E0A00EAAD4D /* FeaturedAuthor+Cohort3.swift in Sources */,
50CBD8152D3A8FED00BF8A0B /* ListCircle.swift in Sources */,
C9DFA972299BF9E8006929C1 /* CompactNoteView.swift in Sources */,
C9AC31AD2A55E0BD00A94E5A /* NotificationViewModel.swift in Sources */,
0326347A2C10C57A00E489B5 /* FileStorageAPIClient.swift in Sources */,
Expand Down Expand Up @@ -2580,6 +2587,7 @@
C92DF80529C25DE900400561 /* URL+Extensions.swift in Sources */,
3F60F42929B27D3E000D62C4 /* ThreadView.swift in Sources */,
C9B678DB29EEBF3B00303F33 /* DependencyInjection.swift in Sources */,
50CBD7AB2D39341B00BF8A0B /* AuthorListDetailView.swift in Sources */,
5B098DC62BDAF73500500A1B /* AttributedString+Links.swift in Sources */,
65BD8DC42BDAF2C300802039 /* DiscoverContentsView.swift in Sources */,
C95D68A9299E709900429F86 /* LinearGradient+Planetary.swift in Sources */,
Expand Down
89 changes: 89 additions & 0 deletions Nos/Views/Lists/AuthorListDetailView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import Dependencies
import SwiftUI

struct AuthorListDetailView: View {

@Dependency(\.relayService) private var relayService
@EnvironmentObject private var router: Router

@ObservedObject var list: AuthorList

/// Subscriptions for metadata requests from the relay service, keyed by author ID.
@State private var subscriptions = [ObjectIdentifier: SubscriptionCancellable]()

@State private var showingEditListInfo = false

var body: some View {
ScrollView {
VStack(spacing: 16) {
ListCircle()

VStack(spacing: 3) {
Text(list.title ?? "")
.font(.headline.weight(.bold))
.multilineTextAlignment(.center)

Text(String.localizedStringWithFormat(String(localized: "xUsers"), list.allAuthors.count))
.foregroundStyle(Color.secondaryTxt)
.font(.footnote)

if let description = list.listDescription, !description.isEmpty {
Text(description)
.foregroundStyle(Color.secondaryTxt)
.font(.footnote)
.padding(.top, 8)
}
}
}
.padding(.top, 24)

LazyVStack {
ForEach(list.allAuthors.sorted(by: { ($0.displayName ?? "") < ($1.displayName ?? "") })) { author in
AuthorObservationView(authorID: author.hexadecimalPublicKey) { author in
AuthorCard(author: author) {
router.push(author)
}
.padding(.horizontal, 13)
.padding(.top, 5)
.readabilityPadding()
.task {
subscriptions[author.id] =
await relayService.requestMetadata(
for: author.hexadecimalPublicKey,
since: author.lastUpdatedMetadata
)
}
}
}
}
.padding(.vertical, 12)
}
.nosNavigationBar("")
.background(Color.appBg)
.toolbar {
ToolbarItem(placement: .primaryAction) {
Menu {
Button("editListInfo") {
showingEditListInfo = true
}
Button("manageUsers") {
// TODO: Manage Users
}
Button("deleteList", role: .destructive) {
// TODO: Delete List
}
} label: {
Image(systemName: "ellipsis")
.foregroundStyle(Color.secondaryTxt)
.fontWeight(.bold)
.padding(.vertical, 12)
}
}
}
.sheet(isPresented: $showingEditListInfo) {
NavigationStack {
EditAuthorListView(list: list)
}
}
}
}
70 changes: 19 additions & 51 deletions Nos/Views/Lists/AuthorListsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ struct AuthorListsView: View {

@FetchRequest var lists: FetchedResults<AuthorList>

@State private var listToEditInfo: AuthorList?
@State private var showingCreateList = false

init(author: Author) {
Expand All @@ -29,18 +28,7 @@ struct AuthorListsView: View {
Group {
if lists.isEmpty {
VStack(spacing: 40) {
ZStack {
Circle()
.fill(Color.white)
.frame(width: 80, height: 80)

Image(systemName: "person.2")
.resizable()
.fontWeight(.semibold)
.aspectRatio(contentMode: .fit)
.frame(width: 48)
.foregroundStyle(Color.black)
}
ListCircle()

Text("listsDescription")
.font(.subheadline.weight(.medium))
Expand All @@ -54,38 +42,25 @@ struct AuthorListsView: View {
ScrollView {
VStack(spacing: 0) {
ForEach(lists) { list in
HStack {
VStack(alignment: .leading) {
Text(list.title ?? "")
.font(.body)

Text(list.rowDescription)
.foregroundStyle(Color.secondaryTxt)
.font(.footnote)
}

Spacer()

Menu {
Button("editListInfo") {
listToEditInfo = list
}
Button("manageUsers") {
// TODO: Manage Users
}
Button("deleteList", role: .destructive) {
// TODO: Delete List
NavigationLink {
AuthorListDetailView(list: list)
} label: {
HStack {
VStack(alignment: .leading) {
Text(list.title ?? "")
.font(.body)

Text(list.rowDescription)
.foregroundStyle(Color.secondaryTxt)
.font(.footnote)
}
} label: {
Image(systemName: "ellipsis")
.foregroundStyle(Color.secondaryTxt)
.fontWeight(.bold)
.padding()

Spacer()
}
.padding(.leading, 16)
.padding(.vertical, 12)
.frame(minHeight: 50)
}
.padding(.leading, 16)
.padding(.vertical, 12)
.frame(minHeight: 50)

BeveledSeparator()
}
Expand All @@ -107,14 +82,6 @@ struct AuthorListsView: View {
}
}
.nosNavigationBar("yourLists")
.sheet(item: $listToEditInfo) { list in
NavigationStack {
EditAuthorListView(list: list)
.onDisappear {
listToEditInfo = nil
}
}
}
.sheet(isPresented: $showingCreateList) {
NavigationStack {
EditAuthorListView()
Expand All @@ -135,7 +102,8 @@ extension AuthorList {
let countString = String.localizedStringWithFormat(String(localized: "xUsers"), authorCount)
descriptionComponents.append(countString)

descriptionComponents.append(listDescription ?? String(localized: "noDescription"))
let description = listDescription?.isEmpty == false ? listDescription! : String(localized: "noDescription")
descriptionComponents.append(description)
return descriptionComponents.joined(separator: "")
}
}
7 changes: 5 additions & 2 deletions Nos/Views/Lists/EditAuthorListView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ struct EditAuthorListView: View {
init(list: AuthorList? = nil) {
self.list = list
mode = list == nil ? .create : .update

title = list?.title ?? ""
description = list?.listDescription ?? ""
}

var body: some View {
Expand Down Expand Up @@ -61,12 +64,12 @@ struct EditAuthorListView: View {
}
.nosNavigationBar(mode == .create ? "newList" : "editListInfo")
.toolbar {
ToolbarItem(placement: .topBarLeading) {
ToolbarItem(placement: .cancellationAction) {
Button("cancel") {
dismiss()
}
}
ToolbarItem(placement: .topBarTrailing) {
ToolbarItem(placement: .primaryAction) {
ActionButton(mode == .create ? "next" : "save", action: saveButtonPressed)
.frame(height: 22)
.padding(.bottom, 3)
Expand Down
19 changes: 19 additions & 0 deletions Nos/Views/Lists/ListCircle.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import SwiftUI

/// A white circle with a group icon in it for representing an ``AuthorList``.
struct ListCircle: View {
var body: some View {
ZStack {
Circle()
.fill(Color.white)
.frame(width: 80, height: 80)

Image(systemName: "person.2")
.resizable()
.fontWeight(.semibold)
.aspectRatio(contentMode: .fit)
.frame(width: 48)
.foregroundStyle(Color.black)
}
}
}

0 comments on commit b5bed57

Please sign in to comment.