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

added list detail view #155 #1736

Open
wants to merge 2 commits into
base: feature/edit-lists-ui
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -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
92 changes: 92 additions & 0 deletions Nos/Views/Lists/AuthorListDetailView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
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
NavigationLink {
ProfileView(author: author)
} label: {
AuthorObservationView(authorID: author.hexadecimalPublicKey) { author in
AuthorCard(author: author)
.padding(.horizontal, 13)
.padding(.top, 5)
.readabilityPadding()
.task {
subscriptions[author.id] =
await relayService.requestMetadata(
for: author.hexadecimalPublicKey,
since: author.lastUpdatedMetadata
)
}
.disabled(true) // skips the onTap action in AuthorCard
}
}
}
}
.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)
}
}
}
Loading