mirror of
https://github.com/Dimillian/IceCubesApp.git
synced 2024-12-26 15:02:39 +01:00
f68bc3e306
The pending-button can now be shown in any corner the user prefers. This is accomplished by allowing the user to move the counter left in addition to the already present option to move it down. Fixes #1637 Signed-off-by: Paul Schuetz <pa.schuetz@web.de>
261 lines
9.6 KiB
Swift
261 lines
9.6 KiB
Swift
import Combine
|
|
import DesignSystem
|
|
import Env
|
|
import Models
|
|
import Network
|
|
import Observation
|
|
import Status
|
|
import SwiftUI
|
|
|
|
@Observable class DisplaySettingsLocalValues {
|
|
var tintColor = Theme.shared.tintColor
|
|
var primaryBackgroundColor = Theme.shared.primaryBackgroundColor
|
|
var secondaryBackgroundColor = Theme.shared.secondaryBackgroundColor
|
|
var labelColor = Theme.shared.labelColor
|
|
var lineSpacing = Theme.shared.lineSpacing
|
|
var fontSizeScale = Theme.shared.fontSizeScale
|
|
}
|
|
|
|
@MainActor
|
|
struct DisplaySettingsView: View {
|
|
typealias FontState = Theme.FontState
|
|
|
|
@Environment(\.colorScheme) private var colorScheme
|
|
@Environment(Theme.self) private var theme
|
|
@Environment(UserPreferences.self) private var userPreferences
|
|
|
|
@State private var localValues = DisplaySettingsLocalValues()
|
|
|
|
@State private var isFontSelectorPresented = false
|
|
|
|
private let previewStatusViewModel = StatusRowViewModel(status: Status.placeholder(forSettings: true, language: "la"),
|
|
client: Client(server: ""),
|
|
routerPath: RouterPath()) // translate from latin button
|
|
|
|
var body: some View {
|
|
ZStack(alignment: .top) {
|
|
Form {
|
|
StatusRowView(viewModel: previewStatusViewModel)
|
|
.allowsHitTesting(false)
|
|
.opacity(0)
|
|
.hidden()
|
|
themeSection
|
|
fontSection
|
|
layoutSection
|
|
platformsSection
|
|
resetSection
|
|
}
|
|
.navigationTitle("settings.display.navigation-title")
|
|
.scrollContentBackground(.hidden)
|
|
.background(theme.secondaryBackgroundColor)
|
|
.task(id: localValues.tintColor) {
|
|
do { try await Task.sleep(for: .microseconds(500)) } catch {}
|
|
theme.tintColor = localValues.tintColor
|
|
}
|
|
.task(id: localValues.primaryBackgroundColor) {
|
|
do { try await Task.sleep(for: .microseconds(500)) } catch {}
|
|
theme.primaryBackgroundColor = localValues.primaryBackgroundColor
|
|
}
|
|
.task(id: localValues.secondaryBackgroundColor) {
|
|
do { try await Task.sleep(for: .microseconds(500)) } catch {}
|
|
theme.secondaryBackgroundColor = localValues.secondaryBackgroundColor
|
|
}
|
|
.task(id: localValues.labelColor) {
|
|
do { try await Task.sleep(for: .microseconds(500)) } catch {}
|
|
theme.labelColor = localValues.labelColor
|
|
}
|
|
.task(id: localValues.lineSpacing) {
|
|
do { try await Task.sleep(for: .microseconds(500)) } catch {}
|
|
theme.lineSpacing = localValues.lineSpacing
|
|
}
|
|
.task(id: localValues.fontSizeScale) {
|
|
do { try await Task.sleep(for: .microseconds(500)) } catch {}
|
|
theme.fontSizeScale = localValues.fontSizeScale
|
|
}
|
|
examplePost
|
|
}
|
|
}
|
|
|
|
private var examplePost: some View {
|
|
VStack(spacing: 0) {
|
|
StatusRowView(viewModel: previewStatusViewModel)
|
|
.allowsHitTesting(false)
|
|
.padding(.layoutPadding)
|
|
.background(theme.primaryBackgroundColor)
|
|
.cornerRadius(8)
|
|
.padding(.horizontal, .layoutPadding)
|
|
.padding(.top, .layoutPadding)
|
|
.background(theme.secondaryBackgroundColor)
|
|
Rectangle()
|
|
.fill(theme.secondaryBackgroundColor)
|
|
.frame(height: 30)
|
|
.mask(LinearGradient(gradient: Gradient(colors: [theme.secondaryBackgroundColor, .clear]),
|
|
startPoint: .top, endPoint: .bottom))
|
|
}
|
|
}
|
|
|
|
@ViewBuilder
|
|
private var themeSection: some View {
|
|
@Bindable var theme = theme
|
|
Section {
|
|
Toggle("settings.display.theme.systemColor", isOn: $theme.followSystemColorScheme)
|
|
themeSelectorButton
|
|
Group {
|
|
ColorPicker("settings.display.theme.tint", selection: $localValues.tintColor)
|
|
ColorPicker("settings.display.theme.background", selection: $localValues.primaryBackgroundColor)
|
|
ColorPicker("settings.display.theme.secondary-background", selection: $localValues.secondaryBackgroundColor)
|
|
ColorPicker("settings.display.theme.text-color", selection: $localValues.labelColor)
|
|
}
|
|
.disabled(theme.followSystemColorScheme)
|
|
.opacity(theme.followSystemColorScheme ? 0.5 : 1.0)
|
|
.onChange(of: theme.selectedSet) {
|
|
localValues.tintColor = theme.tintColor
|
|
localValues.primaryBackgroundColor = theme.primaryBackgroundColor
|
|
localValues.secondaryBackgroundColor = theme.secondaryBackgroundColor
|
|
localValues.labelColor = theme.labelColor
|
|
}
|
|
} header: {
|
|
Text("settings.display.section.theme")
|
|
} footer: {
|
|
if theme.followSystemColorScheme {
|
|
Text("settings.display.section.theme.footer")
|
|
}
|
|
}
|
|
.listRowBackground(theme.primaryBackgroundColor)
|
|
}
|
|
|
|
private var fontSection: some View {
|
|
Section("settings.display.section.font") {
|
|
Picker("settings.display.font", selection: .init(get: { () -> FontState in
|
|
if theme.chosenFont?.fontName == "OpenDyslexic-Regular" {
|
|
return FontState.openDyslexic
|
|
} else if theme.chosenFont?.fontName == "AtkinsonHyperlegible-Regular" {
|
|
return FontState.hyperLegible
|
|
} else if theme.chosenFont?.fontName == ".AppleSystemUIFontRounded-Regular" {
|
|
return FontState.SFRounded
|
|
}
|
|
return theme.chosenFontData != nil ? FontState.custom : FontState.system
|
|
}, set: { newValue in
|
|
switch newValue {
|
|
case .system:
|
|
theme.chosenFont = nil
|
|
case .openDyslexic:
|
|
theme.chosenFont = UIFont(name: "OpenDyslexic", size: 1)
|
|
case .hyperLegible:
|
|
theme.chosenFont = UIFont(name: "Atkinson Hyperlegible", size: 1)
|
|
case .SFRounded:
|
|
theme.chosenFont = UIFont.systemFont(ofSize: 1).rounded()
|
|
case .custom:
|
|
isFontSelectorPresented = true
|
|
}
|
|
})) {
|
|
ForEach(FontState.allCases, id: \.rawValue) { fontState in
|
|
Text(fontState.title).tag(fontState)
|
|
}
|
|
}
|
|
.navigationDestination(isPresented: $isFontSelectorPresented, destination: { FontPicker() })
|
|
|
|
VStack {
|
|
Slider(value: $localValues.fontSizeScale, in: 0.5 ... 1.5, step: 0.1)
|
|
Text("settings.display.font.scaling-\(String(format: "%.1f", localValues.fontSizeScale))")
|
|
.font(.scaledBody)
|
|
}
|
|
.alignmentGuide(.listRowSeparatorLeading) { d in
|
|
d[.leading]
|
|
}
|
|
|
|
VStack {
|
|
Slider(value: $localValues.lineSpacing, in: 0.4 ... 10.0, step: 0.2)
|
|
Text("settings.display.font.line-spacing-\(String(format: "%.1f", localValues.lineSpacing))")
|
|
.font(.scaledBody)
|
|
}
|
|
.alignmentGuide(.listRowSeparatorLeading) { d in
|
|
d[.leading]
|
|
}
|
|
}
|
|
.listRowBackground(theme.primaryBackgroundColor)
|
|
}
|
|
|
|
@ViewBuilder
|
|
private var layoutSection: some View {
|
|
@Bindable var theme = theme
|
|
@Bindable var userPreferences = userPreferences
|
|
Section("settings.display.section.display") {
|
|
Picker("settings.display.avatar.position", selection: $theme.avatarPosition) {
|
|
ForEach(Theme.AvatarPosition.allCases, id: \.rawValue) { position in
|
|
Text(position.description).tag(position)
|
|
}
|
|
}
|
|
Picker("settings.display.avatar.shape", selection: $theme.avatarShape) {
|
|
ForEach(Theme.AvatarShape.allCases, id: \.rawValue) { shape in
|
|
Text(shape.description).tag(shape)
|
|
}
|
|
}
|
|
Toggle("settings.display.full-username", isOn: $theme.displayFullUsername)
|
|
Picker("settings.display.status.action-buttons", selection: $theme.statusActionsDisplay) {
|
|
ForEach(Theme.StatusActionsDisplay.allCases, id: \.rawValue) { buttonStyle in
|
|
Text(buttonStyle.description).tag(buttonStyle)
|
|
}
|
|
}
|
|
Picker("settings.display.status.media-style", selection: $theme.statusDisplayStyle) {
|
|
ForEach(Theme.StatusDisplayStyle.allCases, id: \.rawValue) { buttonStyle in
|
|
Text(buttonStyle.description).tag(buttonStyle)
|
|
}
|
|
}
|
|
Toggle("settings.display.translate-button", isOn: $userPreferences.showTranslateButton)
|
|
Toggle("settings.display.pending-at-bottom", isOn: $userPreferences.pendingShownAtBottom)
|
|
Toggle("settings.display.pending-left", isOn: $userPreferences.pendingShownLeft)
|
|
}
|
|
.listRowBackground(theme.primaryBackgroundColor)
|
|
}
|
|
|
|
@ViewBuilder
|
|
private var platformsSection: some View {
|
|
@Bindable var userPreferences = userPreferences
|
|
if UIDevice.current.userInterfaceIdiom == .phone {
|
|
Section("iPhone") {
|
|
Toggle("settings.display.show-tab-label", isOn: $userPreferences.showiPhoneTabLabel)
|
|
}
|
|
.listRowBackground(theme.primaryBackgroundColor)
|
|
}
|
|
|
|
if UIDevice.current.userInterfaceIdiom == .pad {
|
|
Section("iPad") {
|
|
Toggle("settings.display.show-ipad-column", isOn: $userPreferences.showiPadSecondaryColumn)
|
|
}
|
|
.listRowBackground(theme.primaryBackgroundColor)
|
|
}
|
|
}
|
|
|
|
private var resetSection: some View {
|
|
Section {
|
|
Button {
|
|
theme.followSystemColorScheme = true
|
|
theme.applySet(set: colorScheme == .dark ? .iceCubeDark : .iceCubeLight)
|
|
theme.avatarShape = .rounded
|
|
theme.avatarPosition = .top
|
|
theme.statusActionsDisplay = .full
|
|
|
|
localValues.tintColor = theme.tintColor
|
|
localValues.primaryBackgroundColor = theme.primaryBackgroundColor
|
|
localValues.secondaryBackgroundColor = theme.secondaryBackgroundColor
|
|
localValues.labelColor = theme.labelColor
|
|
|
|
} label: {
|
|
Text("settings.display.restore")
|
|
}
|
|
}
|
|
.listRowBackground(theme.primaryBackgroundColor)
|
|
}
|
|
|
|
private var themeSelectorButton: some View {
|
|
NavigationLink(destination: ThemePreviewView()) {
|
|
HStack {
|
|
Text("settings.display.section.theme")
|
|
Spacer()
|
|
Text(theme.selectedSet.rawValue)
|
|
}
|
|
}
|
|
}
|
|
}
|