Skip to content

Commit

Permalink
Merge pull request #1075 from planetary-social/feature/discover-authors
Browse files Browse the repository at this point in the history
Show authors on Discover tab instead of notes
  • Loading branch information
joshuatbrown authored Apr 25, 2024
2 parents 0d2ffff + 1860a2a commit 20d95ba
Show file tree
Hide file tree
Showing 10 changed files with 384 additions and 195 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

- Discover tab now features authors in a variety of categories.
- Fixed an issue where registering a NIP-05 username field could fail silently.
- Fixed an issue where users named with valid urls were unable to be mentioned correctly.
- Fixed an issue where pasting an npub while composing a note created an invalid mention.
Expand Down
67 changes: 32 additions & 35 deletions Nos.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0x29",
"green" : "0x11",
"red" : "0x1A"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
90 changes: 89 additions & 1 deletion Nos/Assets/Localization/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -4037,6 +4037,94 @@
}
}
},
"featuredAuthorCategoryAll" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "All"
}
}
}
},
"featuredAuthorCategoryArt" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Art"
}
}
}
},
"featuredAuthorCategoryEnvironment" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : " Environment"
}
}
}
},
"featuredAuthorCategoryJournalists" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Journalists"
}
}
}
},
"featuredAuthorCategoryMusic" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Music"
}
}
}
},
"featuredAuthorCategoryNew" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "New"
}
}
}
},
"featuredAuthorCategorySports" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Sports"
}
}
}
},
"featuredAuthorCategoryTech" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Tech"
}
}
}
},
"feedSettings" : {
"extractionState" : "manual",
"localizations" : {
Expand Down Expand Up @@ -13594,4 +13682,4 @@
}
},
"version" : "1.0"
}
}
11 changes: 10 additions & 1 deletion Nos/Models/CoreData/Author+CoreDataClass.swift
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,15 @@ import Logger
fetchRequest.sortDescriptors = [NSSortDescriptor(keyPath: \Author.hexadecimalPublicKey, ascending: false)]
return fetchRequest
}


class func matching(npubs: [String]) -> NSFetchRequest<Author> {
let publicKeys = npubs.compactMap { PublicKey(npub: $0)?.hex }
let fetchRequest = NSFetchRequest<Author>(entityName: String(describing: Author.self))
fetchRequest.predicate = NSPredicate(format: "hexadecimalPublicKey in %@", publicKeys)
fetchRequest.sortDescriptors = [NSSortDescriptor(keyPath: \Author.hexadecimalPublicKey, ascending: false)]
return fetchRequest
}

class func find(by pubKey: RawAuthorID, context: NSManagedObjectContext) throws -> Author? {
let fetchRequest = request(by: pubKey)
if let author = try context.fetch(fetchRequest).first {
Expand Down Expand Up @@ -170,6 +178,7 @@ import Logger

@nonobjc public class func allAuthorsRequest() -> NSFetchRequest<Author> {
let fetchRequest = NSFetchRequest<Author>(entityName: "Author")
fetchRequest.sortDescriptors = [NSSortDescriptor(keyPath: \Author.hexadecimalPublicKey, ascending: false)]
return fetchRequest
}

Expand Down
2 changes: 1 addition & 1 deletion Nos/Views/AppView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ struct AppView: View {
}
}

DiscoverView()
DiscoverTab()
.tabItem {
VStack {
let text = Text(.localizable.discover)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Combine
import CoreData
import Dependencies

struct DiscoverView: View {
struct DiscoverTab: View {
// MARK: - Properties

@EnvironmentObject private var relayService: RelayService
Expand All @@ -17,49 +17,13 @@ struct DiscoverView: View {

@State private var performingInitialLoad = true
static let initialLoadTime = 2
@State private var relaySubscriptions = SubscriptionCancellables()
@State private var isVisible = false
private var featuredAuthors: [String]


@StateObject private var searchController = SearchController()
@State private var date = Date(timeIntervalSince1970: Date.now.timeIntervalSince1970 + Double(Self.initialLoadTime))

@State var predicate: NSPredicate = .false

// MARK: - Init

init(featuredAuthors: [String] = Array(Event.discoverTabUserIdToInfo.keys)) {
self.featuredAuthors = featuredAuthors
}

// MARK: - Internal

func cancelSubscriptions() async {
relaySubscriptions.removeAll()
}

func subscribeToNewEvents() async {
await cancelSubscriptions()

let featuredFilter = Filter(
authorKeys: featuredAuthors.compactMap {
PublicKey(npub: $0)?.hex
},
kinds: [.text, .delete],
limit: 200
)

relaySubscriptions.append(await relayService.subscribeToEvents(matching: featuredFilter))
}

func updatePredicate() {
predicate = Event.extendedNetworkPredicate(
currentUser: currentUser,
featuredAuthors: featuredAuthors,
before: date
)
}

// MARK: - View

var body: some View {
Expand All @@ -71,7 +35,10 @@ struct DiscoverView: View {
hideAfter: .now() + .seconds(Self.initialLoadTime)
)
} else {
DiscoverGrid(predicate: predicate, searchController: searchController, columns: $columns)
FeaturedAuthorsView(
featuredAuthorCategory: .all,
searchController: searchController
)
}
}
.searchable(
Expand All @@ -96,18 +63,6 @@ struct DiscoverView: View {
}
}
.animation(.easeInOut, value: columns)
.task {
updatePredicate()
}
.refreshable {
date = .now
}
.onChange(of: date) {
updatePredicate()
}
.refreshable {
date = .now
}
.onAppear {
if router.selectedTab == .discover {
isVisible = true
Expand All @@ -116,12 +71,9 @@ struct DiscoverView: View {
.onDisappear {
isVisible = false
}
.onChange(of: isVisible) {
.onChange(of: isVisible) {
if isVisible {
analytics.showedDiscover()
Task { await subscribeToNewEvents() }
} else {
Task { await cancelSubscriptions() }
}
}
.navigationDestination(for: Event.self) { note in
Expand Down Expand Up @@ -150,7 +102,7 @@ struct SizePreferenceKey: PreferenceKey {
}
}

struct DiscoverView_Previews: PreviewProvider {
struct DiscoverTab_Previews: PreviewProvider {

static var previewData = PreviewData()
static var persistenceController = PersistenceController.preview
Expand Down Expand Up @@ -195,23 +147,19 @@ struct DiscoverView_Previews: PreviewProvider {
@State static var relayFilter: Relay?

static var previews: some View {
if let publicKey = user.publicKey {
DiscoverView(featuredAuthors: [publicKey.npub])
.environment(\.managedObjectContext, previewContext)
.environmentObject(relayService)
.environmentObject(router)
.environment(currentUser)
.onAppear { createTestData(in: previewContext) }

DiscoverView(featuredAuthors: [publicKey.npub])
.environment(\.managedObjectContext, previewContext)
.environmentObject(relayService)
.environmentObject(router)
.environment(currentUser)
.onAppear { createTestData(in: previewContext) }
.previewDevice("iPad Air (5th generation)")
} else {
EmptyView()
}
DiscoverTab()
.environment(\.managedObjectContext, previewContext)
.environmentObject(relayService)
.environmentObject(router)
.environment(currentUser)
.onAppear { createTestData(in: previewContext) }

DiscoverTab()
.environment(\.managedObjectContext, previewContext)
.environmentObject(relayService)
.environmentObject(router)
.environment(currentUser)
.onAppear { createTestData(in: previewContext) }
.previewDevice("iPad Air (5th generation)")
}
}
75 changes: 75 additions & 0 deletions Nos/Views/Discover/FeaturedAuthorCategory.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import Foundation

enum FeaturedAuthorCategory: CaseIterable {
case all
case new // swiftlint:disable:this identifier_name
case journalists
case tech
case art // swiftlint:disable:this identifier_name
case environment
case sports
case music

var text: LocalizedStringResource {
switch self {
case .all: LocalizedStringResource.localizable.featuredAuthorCategoryAll
case .new: LocalizedStringResource.localizable.featuredAuthorCategoryNew
case .journalists: LocalizedStringResource.localizable.featuredAuthorCategoryJournalists
case .tech: LocalizedStringResource.localizable.featuredAuthorCategoryTech
case .art: LocalizedStringResource.localizable.featuredAuthorCategoryArt
case .environment: LocalizedStringResource.localizable.featuredAuthorCategoryEnvironment
case .sports: LocalizedStringResource.localizable.featuredAuthorCategorySports
case .music: LocalizedStringResource.localizable.featuredAuthorCategoryMusic
}
}

var npubs: [String] {
switch self {
case .all:
[
"npub1asuq0pxedwfagpqkdf4lrfmcyfaffgptmayel9947j8krad3x58srs20ap",
"npub1d9nndmy3lx6f00cysrmn2v9t6hz280uwycw0kgcfdhvg99azry8sududfv",
"npub1grz7afdguc67jkjly6fu0xmw0r386t8mtxafutu9u34dy207nt9ql335cv",
"npub1yxzkmtuyctjw2pffp6e9uvyrkp29hrqra2tm3xp3z9707z06muxsg75qvv",
"npub1d7ggne0xsy8e2999q8cyh9zxda688axm07cwncufjeku0nahvfgsyz6qzr",
"npub17a49ajzjlwjv4znh85jcfgmk7qq5ck8m5advx66rudz8g0v034kss2hnk3",
"npub1l9kr6ajfwp6vfjp60vuzxwqwwlw884dff98a9cznujs520shsf9s35xfwh",
"npub1uh8e4y97tvs5zhsq6srr43qy0u66zk8xfy08xcrhef2803sdfcrslq62el",
"npub1aylzctp5p20yc842qfpu2w9j8q0kpqcfx8q3p42ugnp3t8uxg3xq3k8nn0"
]
case .new:
[
"npub1asuq0pxedwfagpqkdf4lrfmcyfaffgptmayel9947j8krad3x58srs20ap"
]
case .journalists:
[
"npub1d9nndmy3lx6f00cysrmn2v9t6hz280uwycw0kgcfdhvg99azry8sududfv",
"npub1grz7afdguc67jkjly6fu0xmw0r386t8mtxafutu9u34dy207nt9ql335cv"
]
case .tech:
[
"npub1d9nndmy3lx6f00cysrmn2v9t6hz280uwycw0kgcfdhvg99azry8sududfv",
"npub1grz7afdguc67jkjly6fu0xmw0r386t8mtxafutu9u34dy207nt9ql335cv",
"npub1yxzkmtuyctjw2pffp6e9uvyrkp29hrqra2tm3xp3z9707z06muxsg75qvv"
]
case .art:
[
"npub1d7ggne0xsy8e2999q8cyh9zxda688axm07cwncufjeku0nahvfgsyz6qzr",
"npub17a49ajzjlwjv4znh85jcfgmk7qq5ck8m5advx66rudz8g0v034kss2hnk3",
"npub1l9kr6ajfwp6vfjp60vuzxwqwwlw884dff98a9cznujs520shsf9s35xfwh"
]
case .environment:
[
"npub1uh8e4y97tvs5zhsq6srr43qy0u66zk8xfy08xcrhef2803sdfcrslq62el"
]
case .sports:
[
"npub1aylzctp5p20yc842qfpu2w9j8q0kpqcfx8q3p42ugnp3t8uxg3xq3k8nn0"
]
case .music:
[
"npub1asuq0pxedwfagpqkdf4lrfmcyfaffgptmayel9947j8krad3x58srs20ap"
]
}
}
}
Loading

0 comments on commit 20d95ba

Please sign in to comment.