mirror of
https://github.com/Dimillian/IceCubesApp.git
synced 2025-01-26 20:45:03 +01:00
Better status focused screen transition
This commit is contained in:
parent
aaafac8e5a
commit
98035e8530
@ -21,6 +21,14 @@ private struct IsSupporter: EnvironmentKey {
|
||||
static let defaultValue: Bool = false
|
||||
}
|
||||
|
||||
private struct IsStatusDetailLoaded: EnvironmentKey {
|
||||
static let defaultValue: Bool = false
|
||||
}
|
||||
|
||||
private struct IsStatusFocused: EnvironmentKey {
|
||||
static let defaultValue: Bool = false
|
||||
}
|
||||
|
||||
public extension EnvironmentValues {
|
||||
var isSecondaryColumn: Bool {
|
||||
get { self[SecondaryColumnKey.self] }
|
||||
@ -46,4 +54,14 @@ public extension EnvironmentValues {
|
||||
get { self[IsSupporter.self] }
|
||||
set { self[IsSupporter.self] = newValue }
|
||||
}
|
||||
|
||||
var isStatusDetailLoaded: Bool {
|
||||
get { self[IsStatusDetailLoaded.self] }
|
||||
set { self[IsStatusDetailLoaded.self] = newValue }
|
||||
}
|
||||
|
||||
var isStatusFocused: Bool {
|
||||
get { self[IsStatusFocused.self] }
|
||||
set { self[IsStatusFocused.self] = newValue }
|
||||
}
|
||||
}
|
||||
|
@ -22,15 +22,15 @@ public struct StatusDetailView: View {
|
||||
@AccessibilityFocusState private var initialFocusBugWorkaround: Bool
|
||||
|
||||
public init(statusId: String) {
|
||||
_viewModel = StateObject(wrappedValue: .init(statusId: statusId))
|
||||
_viewModel = StateObject(wrappedValue: { .init(statusId: statusId) }())
|
||||
}
|
||||
|
||||
public init(status: Status) {
|
||||
_viewModel = StateObject(wrappedValue: .init(status: status))
|
||||
_viewModel = StateObject(wrappedValue: { .init(status: status) }())
|
||||
}
|
||||
|
||||
public init(remoteStatusURL: URL) {
|
||||
_viewModel = StateObject(wrappedValue: .init(remoteStatusURL: remoteStatusURL))
|
||||
_viewModel = StateObject(wrappedValue: { .init(remoteStatusURL: remoteStatusURL) }())
|
||||
}
|
||||
|
||||
public var body: some View {
|
||||
@ -147,8 +147,9 @@ public struct StatusDetailView: View {
|
||||
private func makeCurrentStatusView(status: Status) -> some View {
|
||||
StatusRowView(viewModel: { .init(status: status,
|
||||
client: client,
|
||||
routerPath: routerPath,
|
||||
isFocused: true) })
|
||||
routerPath: routerPath) })
|
||||
.environment(\.isStatusFocused, true)
|
||||
.environment(\.isStatusDetailLoaded, !viewModel.isLoadingContext)
|
||||
.accessibilityFocused($initialFocusBugWorkaround, equals: true)
|
||||
.overlay {
|
||||
GeometryReader { reader in
|
||||
|
@ -12,6 +12,7 @@ public struct StatusRowView: View {
|
||||
@Environment(\.redactionReasons) private var reasons
|
||||
@Environment(\.isCompact) private var isCompact: Bool
|
||||
@Environment(\.accessibilityVoiceOverEnabled) private var accessibilityVoiceOverEnabled
|
||||
@Environment(\.isStatusFocused) private var isFocused
|
||||
|
||||
@EnvironmentObject private var quickLook: QuickLook
|
||||
@EnvironmentObject private var theme: Theme
|
||||
@ -66,20 +67,22 @@ public struct StatusRowView: View {
|
||||
StatusRowContentView(viewModel: viewModel)
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
guard !isFocused else { return }
|
||||
viewModel.navigateToDetail()
|
||||
}
|
||||
.accessibilityActions {
|
||||
if viewModel.isFocused, viewModel.showActions {
|
||||
if isFocused, viewModel.showActions {
|
||||
accessibilityActions
|
||||
}
|
||||
}
|
||||
}
|
||||
if viewModel.showActions, viewModel.isFocused || theme.statusActionsDisplay != .none, !isInCaptureMode {
|
||||
if viewModel.showActions, isFocused || theme.statusActionsDisplay != .none, !isInCaptureMode {
|
||||
StatusRowActionsView(viewModel: viewModel)
|
||||
.padding(.top, 8)
|
||||
.tint(viewModel.isFocused ? theme.tintColor : .gray)
|
||||
.tint(isFocused ? theme.tintColor : .gray)
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
guard !isFocused else { return }
|
||||
viewModel.navigateToDetail()
|
||||
}
|
||||
}
|
||||
@ -122,15 +125,16 @@ public struct StatusRowView: View {
|
||||
leading: .layoutPadding,
|
||||
bottom: 12,
|
||||
trailing: .layoutPadding))
|
||||
.accessibilityElement(children: viewModel.isFocused ? .contain : .combine)
|
||||
.accessibilityLabel(viewModel.isFocused == false && accessibilityVoiceOverEnabled
|
||||
.accessibilityElement(children: isFocused ? .contain : .combine)
|
||||
.accessibilityLabel(isFocused == false && accessibilityVoiceOverEnabled
|
||||
? CombinedAccessibilityLabel(viewModel: viewModel).finalLabel() : Text(""))
|
||||
.accessibilityHidden(viewModel.filter?.filter.filterAction == .hide)
|
||||
.accessibilityAction {
|
||||
guard !isFocused else { return }
|
||||
viewModel.navigateToDetail()
|
||||
}
|
||||
.accessibilityActions {
|
||||
if viewModel.isFocused == false, viewModel.showActions {
|
||||
if isFocused == false, viewModel.showActions {
|
||||
accessibilityActions
|
||||
}
|
||||
}
|
||||
@ -138,6 +142,7 @@ public struct StatusRowView: View {
|
||||
Color.clear
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
guard !isFocused else { return }
|
||||
viewModel.navigateToDetail()
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ import SwiftUI
|
||||
@MainActor
|
||||
public class StatusRowViewModel: ObservableObject {
|
||||
let status: Status
|
||||
let isFocused: Bool
|
||||
// Whether this status is on a remote local timeline (many actions are unavailable if so)
|
||||
let isRemote: Bool
|
||||
let showActions: Bool
|
||||
@ -102,7 +101,6 @@ public class StatusRowViewModel: ObservableObject {
|
||||
public init(status: Status,
|
||||
client: Client,
|
||||
routerPath: RouterPath,
|
||||
isFocused: Bool = false,
|
||||
isRemote: Bool = false,
|
||||
showActions: Bool = true,
|
||||
textDisabled: Bool = false)
|
||||
@ -111,7 +109,6 @@ public class StatusRowViewModel: ObservableObject {
|
||||
finalStatus = status.reblog ?? status
|
||||
self.client = client
|
||||
self.routerPath = routerPath
|
||||
self.isFocused = isFocused
|
||||
self.isRemote = isRemote
|
||||
self.showActions = showActions
|
||||
self.textDisabled = textDisabled
|
||||
@ -159,7 +156,6 @@ public class StatusRowViewModel: ObservableObject {
|
||||
}
|
||||
|
||||
func navigateToDetail() {
|
||||
guard !isFocused else { return }
|
||||
if isRemote, let url = URL(string: finalStatus.url ?? "") {
|
||||
routerPath.navigate(to: .remoteStatusDetail(url: url))
|
||||
} else {
|
||||
|
@ -9,7 +9,12 @@ struct StatusRowActionsView: View {
|
||||
@EnvironmentObject private var currentAccount: CurrentAccount
|
||||
@EnvironmentObject private var statusDataController: StatusDataController
|
||||
@EnvironmentObject private var userPreferences: UserPreferences
|
||||
|
||||
@Environment(\.isStatusFocused) private var isFocused
|
||||
@Environment(\.isStatusDetailLoaded) private var isStatusDetailLoaded
|
||||
|
||||
@ObservedObject var viewModel: StatusRowViewModel
|
||||
|
||||
|
||||
func privateBoost() -> Bool {
|
||||
viewModel.status.visibility == .priv && viewModel.status.account.id == currentAccount.account?.id
|
||||
@ -75,8 +80,8 @@ struct StatusRowActionsView: View {
|
||||
}
|
||||
}
|
||||
|
||||
func count(dataController: StatusDataController, viewModel: StatusRowViewModel, theme: Theme) -> Int? {
|
||||
if theme.statusActionsDisplay == .discret, !viewModel.isFocused {
|
||||
func count(dataController: StatusDataController, isFocused: Bool, theme: Theme) -> Int? {
|
||||
if theme.statusActionsDisplay == .discret, isFocused {
|
||||
return nil
|
||||
}
|
||||
switch self {
|
||||
@ -148,8 +153,11 @@ struct StatusRowActionsView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
if viewModel.isFocused {
|
||||
|
||||
if isStatusDetailLoaded {
|
||||
StatusRowDetailView(viewModel: viewModel)
|
||||
.transition(.move(edge: .bottom))
|
||||
.animation(.snappy)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -179,7 +187,7 @@ struct StatusRowActionsView: View {
|
||||
.disabled(action == .boost &&
|
||||
(viewModel.status.visibility == .direct || viewModel.status.visibility == .priv && viewModel.status.account.id != currentAccount.account?.id))
|
||||
if let count = action.count(dataController: statusDataController,
|
||||
viewModel: viewModel,
|
||||
isFocused: isFocused,
|
||||
theme: theme), !viewModel.isRemote
|
||||
{
|
||||
Text("\(count)")
|
||||
|
@ -6,6 +6,7 @@ import SwiftUI
|
||||
struct StatusRowContentView: View {
|
||||
@Environment(\.redactionReasons) private var reasons
|
||||
@Environment(\.isCompact) private var isCompact
|
||||
@Environment(\.isStatusFocused) private var isFocused
|
||||
|
||||
@EnvironmentObject private var theme: Theme
|
||||
|
||||
@ -44,7 +45,7 @@ struct StatusRowContentView: View {
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
.accessibilityHidden(viewModel.isFocused == false)
|
||||
.accessibilityHidden(isFocused == false)
|
||||
.padding(.vertical, 4)
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,8 @@ import SwiftUI
|
||||
|
||||
struct StatusRowHeaderView: View {
|
||||
@Environment(\.isInCaptureMode) private var isInCaptureMode: Bool
|
||||
@Environment(\.isStatusFocused) private var isFocused
|
||||
|
||||
@EnvironmentObject private var theme: Theme
|
||||
|
||||
let viewModel: StatusRowViewModel
|
||||
@ -29,7 +31,7 @@ struct StatusRowHeaderView: View {
|
||||
viewModel.navigateToAccountDetail(account: viewModel.finalStatus.account)
|
||||
}
|
||||
.accessibilityActions {
|
||||
if viewModel.isFocused {
|
||||
if isFocused {
|
||||
StatusRowContextMenu(viewModel: viewModel)
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import SwiftUI
|
||||
|
||||
struct StatusRowTextView: View {
|
||||
@EnvironmentObject private var theme: Theme
|
||||
@Environment(\.isStatusFocused) private var isFocused
|
||||
|
||||
@ObservedObject var viewModel: StatusRowViewModel
|
||||
|
||||
@ -15,11 +16,11 @@ struct StatusRowTextView: View {
|
||||
emojis: viewModel.finalStatus.emojis,
|
||||
language: viewModel.finalStatus.language,
|
||||
lineLimit: viewModel.lineLimit)
|
||||
.font(viewModel.isFocused ? .scaledBodyFocused : .scaledBody)
|
||||
.font(isFocused ? .scaledBodyFocused : .scaledBody)
|
||||
.lineSpacing(CGFloat(theme.lineSpacing))
|
||||
.foregroundColor(viewModel.textDisabled ? .gray : theme.labelColor)
|
||||
.emojiSize(viewModel.isFocused ? Font.scaledBodyFocusedFont.emojiSize : Font.scaledBodyFont.emojiSize)
|
||||
.emojiBaselineOffset(viewModel.isFocused ? Font.scaledBodyFocusedFont.emojiBaselineOffset : Font.scaledBodyFont.emojiBaselineOffset)
|
||||
.emojiSize(isFocused ? Font.scaledBodyFocusedFont.emojiSize : Font.scaledBodyFont.emojiSize)
|
||||
.emojiBaselineOffset(isFocused ? Font.scaledBodyFocusedFont.emojiBaselineOffset : Font.scaledBodyFont.emojiBaselineOffset)
|
||||
.environment(\.openURL, OpenURLAction { url in
|
||||
viewModel.routerPath.handleStatus(status: viewModel.finalStatus, url: url)
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user