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

add feed picker view (UI only) #103 #1706

Merged
merged 2 commits into from
Dec 24, 2024
Merged
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 display of mastodon usernames so it shows @[email protected] rather than [email protected]
- Nos now publishes the hashtags it finds in your note when you post. This means it works the way you’ve always expected it to work. [#44](https://github.com/verse-pbc/issues/issues/44)
- Fixed crash related to tracking delete events. [#96](https://github.com/verse-pbc/issues/issues/96)
- Added feed picker view (UI only). [#103](https://github.com/verse-pbc/issues/issues/103)

### Internal Changes
- Upgraded to Xcode 16. [#1570](https://github.com/planetary-social/nos/issues/1570)
Expand Down
8 changes: 8 additions & 0 deletions Nos.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,9 @@
50089A0C2C97182200834588 /* CurrentUser+PublishEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50089A0B2C97182200834588 /* CurrentUser+PublishEvents.swift */; };
50089A0D2C97182200834588 /* CurrentUser+PublishEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50089A0B2C97182200834588 /* CurrentUser+PublishEvents.swift */; };
50089A172C98678600834588 /* View+ListRowGradientBackground.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50089A162C98678600834588 /* View+ListRowGradientBackground.swift */; };
501728B42D16EFB000CF2A07 /* FeedPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 501728B32D16EFAC00CF2A07 /* FeedPicker.swift */; };
502B6C3D2C9462A400446316 /* PushNotificationRegistrar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 502B6C3C2C9462A400446316 /* PushNotificationRegistrar.swift */; };
503CA9532D19ACCC00805EF8 /* HorizontalLine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 503CA9522D19ACC800805EF8 /* HorizontalLine.swift */; };
5044546E2C90726A00251A7E /* Event+Fetching.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5044546D2C90726A00251A7E /* Event+Fetching.swift */; };
504454702C90728500251A7E /* Event+Hydration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5044546F2C90728500251A7E /* Event+Hydration.swift */; };
504454712C90728E00251A7E /* Event+Fetching.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5044546D2C90726A00251A7E /* Event+Fetching.swift */; };
Expand Down Expand Up @@ -755,7 +757,9 @@
50089A002C9712EF00834588 /* JSONEvent+Kinds.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "JSONEvent+Kinds.swift"; sourceTree = "<group>"; };
50089A0B2C97182200834588 /* CurrentUser+PublishEvents.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CurrentUser+PublishEvents.swift"; sourceTree = "<group>"; };
50089A162C98678600834588 /* View+ListRowGradientBackground.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+ListRowGradientBackground.swift"; sourceTree = "<group>"; };
501728B32D16EFAC00CF2A07 /* FeedPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedPicker.swift; sourceTree = "<group>"; };
502B6C3C2C9462A400446316 /* PushNotificationRegistrar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushNotificationRegistrar.swift; sourceTree = "<group>"; };
503CA9522D19ACC800805EF8 /* HorizontalLine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HorizontalLine.swift; sourceTree = "<group>"; };
5044546D2C90726A00251A7E /* Event+Fetching.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Event+Fetching.swift"; sourceTree = "<group>"; };
5044546F2C90728500251A7E /* Event+Hydration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Event+Hydration.swift"; sourceTree = "<group>"; };
5045540C2C81E10C0044ECAE /* EditableAvatarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditableAvatarView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1599,6 +1603,7 @@
C9CDBBA329A8FA2900C555C7 /* GoldenPostView.swift */,
C930E0562BA49DAD002B5776 /* GridPattern.swift */,
C9A0DAE329C69F0C00466635 /* HighlightedText.swift */,
503CA9522D19ACC800805EF8 /* HorizontalLine.swift */,
2D4010A12AD87DF300F93AD4 /* KnownFollowersView.swift */,
C9A0DADC29C689C900466635 /* NosNavigationBar.swift */,
C97B28892C10B07100DC1FC0 /* NosNavigationStack.swift */,
Expand Down Expand Up @@ -1695,6 +1700,7 @@
C96877B32B4EDCCF0051ED2F /* Home */ = {
isa = PBXGroup;
children = (
501728B32D16EFAC00CF2A07 /* FeedPicker.swift */,
C9DEBFD8298941000078B43A /* HomeFeedView.swift */,
5BE281C92AE2CCEB00880466 /* HomeTab.swift */,
03C7E7912CB9C0AF0054624C /* WelcomeToFeedTip.swift */,
Expand Down Expand Up @@ -2560,6 +2566,7 @@
C9CDBBA429A8FA2900C555C7 /* GoldenPostView.swift in Sources */,
C92F01582AC4D6F700972489 /* NosTextField.swift in Sources */,
C9C2B77C29E072E400548B4A /* WebSocket+Nos.swift in Sources */,
503CA9532D19ACCC00805EF8 /* HorizontalLine.swift in Sources */,
C9DEC003298945150078B43A /* String+Lorem.swift in Sources */,
04C9D7912CC29D5000EAAD4D /* FeaturedAuthor+Cohort1.swift in Sources */,
038EF09D2CC16D640031F7F2 /* PrivateKeyView.swift in Sources */,
Expand Down Expand Up @@ -2616,6 +2623,7 @@
C92F01552AC4D6CF00972489 /* BeveledSeparator.swift in Sources */,
50DE6B1B2C6B88FE0065665D /* View+StyledBorder.swift in Sources */,
C93EC2FD29C3785C0012EE2A /* View+RoundedCorner.swift in Sources */,
501728B42D16EFB000CF2A07 /* FeedPicker.swift in Sources */,
5B503F622A291A1A0098805A /* JSONRelayMetadata.swift in Sources */,
C98298332ADD7F9A0096C5B5 /* DeepLinkService.swift in Sources */,
03F7C4F42C10E05B006FF613 /* URLSessionProtocol.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0x18",
"green" : "0x18",
"red" : "0x18"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
17 changes: 17 additions & 0 deletions Nos/Views/Components/HorizontalLine.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import SwiftUI

/// A thin horizontal line with the provided color.
///
/// The default thickness of the line is 1 point, but it can be overridden,
/// such as to make it 1 pixel (e.g. `1 / UIScreen.main.scale`).
struct HorizontalLine: View {
let color: Color
var height: CGFloat = 1

var body: some View {
Rectangle()
.frame(height: height)
.frame(maxWidth: .infinity)
.foregroundStyle(color)
}
}
78 changes: 78 additions & 0 deletions Nos/Views/Home/FeedPicker.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import CoreData
import SwiftUI

/// The source to be used for a feed of notes.
enum FeedSource: Hashable, Equatable {
case following
case relay(String)
case list(String)

var displayName: String {
switch self {
case .following: String(localized: "following")
case .relay(let name), .list(let name): name
}
}

static func == (lhs: FeedSource, rhs: FeedSource) -> Bool {
switch (lhs, rhs) {
case (.following, .following): true
case (.relay(let name1), .relay(let name2)): name1 == name2
case (.list(let name1), .list(let name2)): name1 == name2
default: false
}
}
}

/// A picker view used to pick which source a feed should show notes from.
struct FeedPicker: View {
@Binding var selectedSource: FeedSource

@FetchRequest var relays: FetchedResults<Relay>

init(author: Author, selectedSource: Binding<FeedSource>) {
_selectedSource = selectedSource
_relays = FetchRequest(fetchRequest: Relay.relays(for: author))
}

var body: some View {
VStack(spacing: 0) {
HorizontalLine(color: .buttonBevelBottom)

ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 0) {
ForEach(allSources, id: \.self) { source in
Button(action: {
withAnimation(nil) {
selectedSource = source
}
}, label: {
Text(source.displayName)
.font(.system(size: 16, weight: selectedSource == source ? .medium : .regular))
.padding(.horizontal, 10)
.padding(.vertical, 4)
.background(selectedSource == source ? Color.pickerBackgroundSelected : Color.clear)
.foregroundStyle(selectedSource == source ? Color.white : Color.secondaryTxt)
.clipShape(Capsule())
})
}
}
.padding(.horizontal, 8)
}
.frame(height: 40)

HorizontalLine(color: .panelBevelBottom, height: 1 / UIScreen.main.scale)

HorizontalLine(color: .black, height: 1 / UIScreen.main.scale)
}
.background(Color.cardBgTop)
}

private var allSources: [FeedSource] {
var sources = [FeedSource]()
sources.append(.following)
sources.append(contentsOf: relays.map { FeedSource.relay($0.host!) })
// TODO: Add lists
return sources
}
}
20 changes: 17 additions & 3 deletions Nos/Views/Home/HomeFeedView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,17 @@ struct HomeFeedView: View {
/// The amount of time (in seconds) the loading indicator will be shown when showTimedLoadingIndicator is set to
/// true.
static let staticLoadTime: TimeInterval = 2

private let stackSpacing: CGFloat = 8

let user: Author

/// A tip to display at the top of the feed.
let welcomeTip = WelcomeToFeedTip()

@State private var showRelayPicker = false
@State private var selectedRelay: Relay?
@State private var selectedRelay: Relay?
@State private var pickerSelected = FeedSource.following

init(user: Author) {
self.user = user
Expand Down Expand Up @@ -67,14 +70,17 @@ struct HomeFeedView: View {

var body: some View {
ZStack {
VStack(spacing: 8) {
VStack(spacing: stackSpacing) {
TipView(welcomeTip)
.padding(.top, 20)
.padding(.horizontal, 16)
.readabilityPadding()
.tipBackground(LinearGradient.horizontalAccentReversed)
.tipViewStyle(.inline)

FeedPicker(author: user, selectedSource: $pickerSelected)
.padding(.bottom, -stackSpacing) // remove the padding below the picker

PagedNoteListView(
refreshController: $refreshController,
databaseFilter: homeFeedFetchRequest,
Expand Down Expand Up @@ -137,6 +143,12 @@ struct HomeFeedView: View {
ToolbarItem(placement: .navigationBarLeading) {
SideMenuButton()
}
ToolbarItem(placement: .principal) {
Image.nosLogo
.resizable()
.scaledToFit()
.frame(height: 20)
}
ToolbarItem(placement: .navigationBarTrailing) {
Button {
withAnimation {
Expand All @@ -150,8 +162,10 @@ struct HomeFeedView: View {
.frame(minWidth: 40, minHeight: 40)
}
}
.toolbarBackground(.visible, for: .navigationBar)
.toolbarBackground(Color.cardBgBottom, for: .navigationBar)
.navigationBarTitle("", displayMode: .inline)
.padding(.top, 1)
.nosNavigationBar(navigationBarTitle)
.onAppear {
if router.selectedTab == .home {
isVisible = true
Expand Down
Loading