Update tab bar to allow opting into digest

This commit is contained in:
Jackson Harper
2024-04-15 20:27:36 +08:00
committed by Hongbo Wu
parent 4e61b360d7
commit 2b53d7791a
8 changed files with 3526 additions and 18 deletions

View File

@ -2,25 +2,31 @@ import Foundation
import SwiftUI
struct CustomTabBar: View {
let displayTabs: [String]
@Binding var selectedTab: String
let hideFollowingTab: Bool
var body: some View {
HStack(spacing: 0) {
if !hideFollowingTab {
if displayTabs.contains("following") {
TabBarButton(key: "following",
image: Image.tabFollowing,
selectedTab: $selectedTab,
selectionColor: Color(hex: "EE8232"))
}
TabBarButton(key: "digest",
image: Image.tabDigest,
selectedTab: $selectedTab,
selectedImage: Image.tabDigestSelected)
TabBarButton(key: "inbox",
image: Image.tabLibrary,
selectedTab: $selectedTab)
// TabBarButton(key: "profile", image: Image.tabProfile, selectedTab: $selectedTab)
if displayTabs.contains("digest") {
TabBarButton(key: "digest",
image: Image.tabDigest,
selectedTab: $selectedTab,
selectedImage: Image.tabDigestSelected)
}
if displayTabs.contains("inbox") {
TabBarButton(key: "inbox",
image: Image.tabLibrary,
selectedTab: $selectedTab)
}
if displayTabs.contains("profile") {
TabBarButton(key: "profile", image: Image.tabProfile, selectedTab: $selectedTab)
}
}
.padding(.top, 10)
.padding(.bottom, 10)

View File

@ -21,6 +21,9 @@ struct LibraryTabView: View {
@AppStorage("LibraryTabView::hideFollowingTab") var hideFollowingTab = false
@AppStorage(UserDefaultKey.lastSelectedTabItem.rawValue) var selectedTab = "inbox"
@AppStorage("LibraryTabView::digestEnabled") var digestEnabled = false
@AppStorage("LibraryTabView::hasCheckedForDigestFeature") var hasCheckedForDigestFeature = false
@State var isEditMode: EditMode = .inactive
@State var showExpandedAudioPlayer = false
@State var presentPushContainer = true
@ -76,6 +79,28 @@ struct LibraryTabView: View {
@State var operationStatus: OperationStatus = .none
@State var operationMessage: String?
var showDigest: Bool {
if digestEnabled, #available(iOS 17.0, *) {
return true
}
return false
}
var displayTabs: [String] {
var res = [String]()
if !hideFollowingTab {
res.append("following")
}
if showDigest {
res.append("digest")
}
res.append("inbox")
if !showDigest {
res.append("profile")
}
return res
}
var body: some View {
VStack(spacing: 0) {
WindowLink(level: .alert, transition: .move(edge: .bottom), isPresented: $showOperationToast) {
@ -116,24 +141,29 @@ struct LibraryTabView: View {
}.tag("following")
}
if #available(iOS 17.0, *) {
if showDigest, #available(iOS 17.0, *) {
NavigationView {
LibraryDigestView(dataService: dataService)
.navigationBarTitleDisplayMode(.inline)
.navigationViewStyle(.stack)
}.tag("digest")
NavigationView {
HomeFeedContainerView(viewModel: inboxViewModel, isEditMode: $isEditMode)
.navigationBarTitleDisplayMode(.inline)
.navigationViewStyle(.stack)
}.tag("inbox")
} else {
NavigationView {
HomeFeedContainerView(viewModel: inboxViewModel, isEditMode: $isEditMode)
.navigationBarTitleDisplayMode(.inline)
.navigationViewStyle(.stack)
}.tag("inbox")
NavigationView {
ProfileView()
.navigationViewStyle(.stack)
}.tag("profile")
}
NavigationView {
ProfileView()
.navigationViewStyle(.stack)
}.tag("profile")
}
if let audioProperties = audioController.itemAudioProperties {
MiniPlayerViewer(itemAudioProperties: audioProperties)
@ -146,7 +176,9 @@ struct LibraryTabView: View {
.frame(maxWidth: .infinity)
}
if isEditMode != .active {
CustomTabBar(selectedTab: $selectedTab, hideFollowingTab: hideFollowingTab)
CustomTabBar(
displayTabs: displayTabs,
selectedTab: $selectedTab)
.padding(0)
}
}
@ -204,5 +236,19 @@ struct LibraryTabView: View {
}
selectedTab = "inbox"
}
.task {
do {
if let viewer = try await dataService.fetchViewer() {
digestEnabled = viewer.digestEnabled ?? false
if !hasCheckedForDigestFeature {
hasCheckedForDigestFeature = true
selectedTab = "digest"
}
}
} catch {
print("ERROR FETCHING VIEWER: ", error)
print("")
}
}
}
}

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="22522" systemVersion="23B81" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="22757" systemVersion="23B81" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<entity name="Filter" representedClassName="Filter" syncable="YES" codeGenerationType="class">
<attribute name="defaultFilter" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="filter" optional="YES" attributeType="String"/>
@ -137,6 +137,7 @@
<attribute name="username" optional="YES" attributeType="String"/>
</entity>
<entity name="Viewer" representedClassName="Viewer" syncable="YES" codeGenerationType="class">
<attribute name="digestEnabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="name" attributeType="String"/>
<attribute name="profileImageURL" optional="YES" attributeType="String"/>
<attribute name="userID" attributeType="String"/>

View File

@ -0,0 +1,10 @@
public struct FeatureInternal {
public let name: String
public let enabled: Bool
public init(name: String, enabled: Bool) {
self.name = name
self.enabled = enabled
}
}

File diff suppressed because it is too large Load Diff

View File

@ -15,6 +15,8 @@ public enum RuleActionType {
case delete
case markAsRead
case sendNotification
case export
case webhook
static func from(_ other: Enums.RuleActionType) -> RuleActionType {
switch other {
@ -28,6 +30,10 @@ public enum RuleActionType {
return .sendNotification
case .delete:
return .delete
case Enums.RuleActionType.export:
return .export
case Enums.RuleActionType.webhook:
return .webhook
}
}
}

View File

@ -17,7 +17,9 @@ public extension DataService {
profileImageURL: try $0.profile(
selection: .init { try $0.pictureUrl() }
),
intercomHash: try $0.intercomHash()
intercomHash: try $0.intercomHash(),
digestEnabled: true // (try $0.featureList(selection: featureSelection.list.nullable)?
// .filter { $0.enabled && $0.name == "digest" } ?? []).count > 0
)
}
@ -65,6 +67,7 @@ public struct ViewerInternal {
public let name: String
public let profileImageURL: String?
public let intercomHash: String?
public let digestEnabled: Bool?
func persist(context: NSManagedObjectContext) throws {
try context.performAndWait {
@ -73,6 +76,7 @@ public struct ViewerInternal {
viewer.username = username
viewer.name = name
viewer.profileImageURL = profileImageURL
viewer.digestEnabled = digestEnabled ?? false
do {
try context.save()

View File

@ -0,0 +1,6 @@
import Models
import SwiftGraphQL
let featureSelection = Selection.Feature {
FeatureInternal(name: try $0.name(), enabled: try $0.grantedAt() != nil)
}