mirror of
https://github.com/Dimillian/IceCubesApp.git
synced 2024-11-13 13:01:03 +00:00
Sync with markers API for notifications
This commit is contained in:
parent
4de4c7c82a
commit
590299d102
7 changed files with 59 additions and 19 deletions
|
@ -15,7 +15,7 @@ extension IceCubesApp {
|
|||
ForEach(availableTabs) { tab in
|
||||
if tab == selectedTab || sideBarLoadedTabs.contains(tab) {
|
||||
tab
|
||||
.makeContentView(popToRootTab: $popToRootTab)
|
||||
.makeContentView(selectedTab: $selectedTab, popToRootTab: $popToRootTab)
|
||||
.opacity(tab == selectedTab ? 1 : 0)
|
||||
.transition(.opacity)
|
||||
.id("\(tab)\(appAccountsManager.currentAccount.id)")
|
||||
|
@ -41,7 +41,8 @@ extension IceCubesApp {
|
|||
}
|
||||
|
||||
var notificationsSecondaryColumn: some View {
|
||||
NotificationsTab(popToRootTab: $popToRootTab, lockedType: nil)
|
||||
NotificationsTab(selectedTab: .constant(.notifications),
|
||||
popToRootTab: $popToRootTab, lockedType: nil)
|
||||
.environment(\.isSecondaryColumn, true)
|
||||
.frame(maxWidth: .secondaryColumnWidth)
|
||||
.id(appAccountsManager.currentAccount.id)
|
||||
|
|
|
@ -20,7 +20,7 @@ extension IceCubesApp {
|
|||
selectedTab = newTab
|
||||
})) {
|
||||
ForEach(availableTabs) { tab in
|
||||
tab.makeContentView(popToRootTab: $popToRootTab)
|
||||
tab.makeContentView(selectedTab: $selectedTab, popToRootTab: $popToRootTab)
|
||||
.tabItem {
|
||||
if userPreferences.showiPhoneTabLabel {
|
||||
tab.label
|
||||
|
@ -34,7 +34,6 @@ extension IceCubesApp {
|
|||
}
|
||||
}
|
||||
.id(appAccountsManager.currentClient.id)
|
||||
.environment(\.selectedTab, selectedTab)
|
||||
}
|
||||
|
||||
private func badgeFor(tab: Tab) -> Int {
|
||||
|
|
|
@ -11,7 +11,6 @@ import Timeline
|
|||
struct NotificationsTab: View {
|
||||
@Environment(\.isSecondaryColumn) private var isSecondaryColumn: Bool
|
||||
@Environment(\.scenePhase) private var scenePhase
|
||||
@Environment(\.selectedTab) private var selectedTab: Tab
|
||||
|
||||
@Environment(Theme.self) private var theme
|
||||
@Environment(Client.self) private var client
|
||||
|
@ -22,6 +21,8 @@ struct NotificationsTab: View {
|
|||
@Environment(PushNotificationsService.self) private var pushNotificationsService
|
||||
@State private var routerPath = RouterPath()
|
||||
@State private var scrollToTopSignal: Int = 0
|
||||
|
||||
@Binding var selectedTab: Tab
|
||||
@Binding var popToRootTab: Tab
|
||||
|
||||
let lockedType: Models.Notification.NotificationType?
|
||||
|
@ -72,6 +73,9 @@ struct NotificationsTab: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
.onChange(of: selectedTab, { _, newValue in
|
||||
clearNotifications()
|
||||
})
|
||||
.onChange(of: pushNotificationsService.handledNotification) { _, newValue in
|
||||
if let newValue, let type = newValue.notification.supportedType {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
|
||||
|
|
|
@ -31,7 +31,7 @@ enum Tab: Int, Identifiable, Hashable {
|
|||
}
|
||||
|
||||
@ViewBuilder
|
||||
func makeContentView(popToRootTab: Binding<Tab>) -> some View {
|
||||
func makeContentView(selectedTab: Binding<Tab>, popToRootTab: Binding<Tab>) -> some View {
|
||||
switch self {
|
||||
case .timeline:
|
||||
TimelineTab(popToRootTab: popToRootTab)
|
||||
|
@ -42,9 +42,9 @@ enum Tab: Int, Identifiable, Hashable {
|
|||
case .federated:
|
||||
TimelineTab(popToRootTab: popToRootTab, timeline: .federated)
|
||||
case .notifications:
|
||||
NotificationsTab(popToRootTab: popToRootTab, lockedType: nil)
|
||||
NotificationsTab(selectedTab: selectedTab, popToRootTab: popToRootTab, lockedType: nil)
|
||||
case .mentions:
|
||||
NotificationsTab(popToRootTab: popToRootTab, lockedType: .mention)
|
||||
NotificationsTab(selectedTab: selectedTab, popToRootTab: popToRootTab, lockedType: .mention)
|
||||
case .explore:
|
||||
ExploreTab(popToRootTab: popToRootTab)
|
||||
case .messages:
|
||||
|
@ -113,14 +113,3 @@ enum Tab: Int, Identifiable, Hashable {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct SelectedTab: EnvironmentKey {
|
||||
static let defaultValue: Tab = .timeline
|
||||
}
|
||||
|
||||
extension EnvironmentValues {
|
||||
var selectedTab: Tab {
|
||||
get { self[SelectedTab.self] }
|
||||
set { self[SelectedTab.self] = newValue }
|
||||
}
|
||||
}
|
||||
|
|
12
Packages/Models/Sources/Models/Marker.swift
Normal file
12
Packages/Models/Sources/Models/Marker.swift
Normal file
|
@ -0,0 +1,12 @@
|
|||
import Foundation
|
||||
|
||||
public struct Marker: Codable, Sendable {
|
||||
public struct Content: Codable, Sendable {
|
||||
public let lastReadId: String
|
||||
public let version: Int
|
||||
public let updatedAt: ServerDate
|
||||
}
|
||||
|
||||
public let notifications: Content?
|
||||
public let home: Content?
|
||||
}
|
22
Packages/Network/Sources/Network/Endpoint/Markers.swift
Normal file
22
Packages/Network/Sources/Network/Endpoint/Markers.swift
Normal file
|
@ -0,0 +1,22 @@
|
|||
import Foundation
|
||||
|
||||
public enum Markers: Endpoint {
|
||||
case markers
|
||||
case markNotifications(lastReadId: String)
|
||||
case markHome(lastReadId: String)
|
||||
|
||||
public func path() -> String {
|
||||
"markers"
|
||||
}
|
||||
|
||||
public func queryItems() -> [URLQueryItem]? {
|
||||
switch self {
|
||||
case let .markNotifications(lastReadId):
|
||||
[URLQueryItem(name: "notifications[last_read_id]", value: lastReadId)]
|
||||
case let .markHome(lastReadId):
|
||||
[URLQueryItem(name: "home[last_read_id]", value: lastReadId)]
|
||||
default:
|
||||
nil
|
||||
}
|
||||
}
|
||||
}
|
|
@ -90,6 +90,7 @@ import SwiftUI
|
|||
types: queryTypes,
|
||||
limit: Constants.notificationLimit))
|
||||
consolidatedNotifications = await notifications.consolidated(selectedType: selectedType)
|
||||
markAsRead()
|
||||
nextPageState = notifications.count < Constants.notificationLimit ? .none : .hasNextPage
|
||||
} else if let firstId = consolidatedNotifications.first?.id {
|
||||
var newNotifications: [Models.Notification] = await fetchNewPages(minId: firstId, maxPages: 10)
|
||||
|
@ -97,6 +98,7 @@ import SwiftUI
|
|||
newNotifications = newNotifications.filter { notification in
|
||||
!consolidatedNotifications.contains(where: { $0.id == notification.id })
|
||||
}
|
||||
|
||||
await consolidatedNotifications.insert(
|
||||
contentsOf: newNotifications.consolidated(selectedType: selectedType),
|
||||
at: 0
|
||||
|
@ -107,6 +109,8 @@ import SwiftUI
|
|||
await currentAccount.fetchFollowerRequests()
|
||||
}
|
||||
|
||||
markAsRead()
|
||||
|
||||
withAnimation {
|
||||
state = .display(notifications: consolidatedNotifications,
|
||||
nextPageState: consolidatedNotifications.isEmpty ? .none : nextPageState)
|
||||
|
@ -161,6 +165,15 @@ import SwiftUI
|
|||
state = .error(error: error)
|
||||
}
|
||||
}
|
||||
|
||||
func markAsRead() {
|
||||
guard let client, let id = consolidatedNotifications.first?.notifications.first?.id else { return }
|
||||
Task {
|
||||
do {
|
||||
let _: Marker = try await client.post(endpoint: Markers.markNotifications(lastReadId: id))
|
||||
} catch { }
|
||||
}
|
||||
}
|
||||
|
||||
func handleEvent(event: any StreamEvent) {
|
||||
Task {
|
||||
|
|
Loading…
Reference in a new issue