App Polish (#1098)

* App polish

- Skeleton avatar colour on app switching.
- Bug report icon and string.
- Semi-bold font on room list timestamps.
- Room attachments button spacing and alignment.
- Replace link tint with semi-bold font in AnalyticsSettingsScreen.
- Semi-bold font on Invites button.
- Add padding to media attachment sheet.
- Message composer header layout tweaks.
- Remove indicator after changing homeserver with an MXID.
- Change copy permalink string.
- Formatting of link in Analytics Prompt.
- Remove indicator after changing homeserver with an MXID.
- Change copy permalink string.
- Formatting of link in Analytics Prompt.
- Only semi-bold the room timestamp when unread.
- Tweak the colour of the date separator.
- Add activity indicator to toast style user indicator.
This commit is contained in:
Doug
2023-06-16 17:41:25 +01:00
committed by GitHub
parent 0d737d0dd8
commit 4de39201ed
33 changed files with 169 additions and 103 deletions
@@ -18,41 +18,51 @@ import Combine
import Foundation
enum UserIndicatorType: Equatable {
case toast
case modal(interactiveDismissDisabled: Bool)
case toast(progress: UserIndicator.Progress?)
case modal(progress: UserIndicator.Progress?, interactiveDismissDisabled: Bool)
static var modal: Self {
.modal(interactiveDismissDisabled: false)
}
static var toast: Self { .toast(progress: .none) }
static var modal: Self { .modal(progress: .indeterminate, interactiveDismissDisabled: false) }
}
struct UserIndicator: Equatable, Identifiable {
static func == (lhs: UserIndicator, rhs: UserIndicator) -> Bool {
lhs.id == rhs.id &&
lhs.type == rhs.type &&
lhs.title == rhs.title &&
lhs.iconName == rhs.iconName &&
lhs.persistent == rhs.persistent
}
enum LoaderType {
case unknownProgress
case progress(ProgressPublisher)
enum Progress: Equatable {
static func == (lhs: UserIndicator.Progress, rhs: UserIndicator.Progress) -> Bool {
switch (lhs, rhs) {
case (.indeterminate, .indeterminate): return true
case (.published(let lhsPublisher), .published(let rhsPublisher)): return lhsPublisher === rhsPublisher
default: return false
}
}
case indeterminate
case published(ProgressPublisher)
}
var id: String = UUID().uuidString
var type = UserIndicatorType.toast
var type: UserIndicatorType = .toast
var title: String
var iconName: String?
var persistent = false
var loaderType: LoaderType? = .unknownProgress
// MARK: - Associated values from the type
var progress: Progress? {
switch type {
case .toast(let progress): return progress
case .modal(let progress, _): return progress
}
}
var progressPublisher: AnyPublisher<Double, Never> {
switch loaderType {
case .none, .unknownProgress:
return Empty().eraseToAnyPublisher()
case .some(.progress(let progress)):
return progress.publisher.eraseToAnyPublisher()
switch type {
case .toast(let progress), .modal(let progress, _):
switch progress {
case .none, .indeterminate:
return Empty().eraseToAnyPublisher()
case .some(.published(let progress)):
return progress.publisher.eraseToAnyPublisher()
}
}
}
@@ -60,7 +70,7 @@ struct UserIndicator: Equatable, Identifiable {
switch type {
case .toast:
return false
case .modal(let interactiveDismissDisabled):
case .modal(_, let interactiveDismissDisabled):
return interactiveDismissDisabled
}
}
@@ -24,15 +24,17 @@ struct UserIndicatorModalView: View {
var body: some View {
ZStack {
VStack(spacing: 12.0) {
if case .unknownProgress = indicator.loaderType {
if case .indeterminate = indicator.progress {
ProgressView()
} else if case .progress = indicator.loaderType {
} else if case .published = indicator.progress {
ProgressView(value: progressFraction)
}
HStack {
if let iconName = indicator.iconName {
Image(systemName: iconName)
.font(.compound.bodyLG)
.foregroundColor(.compound.iconPrimary)
}
Text(indicator.title)
.font(.compound.bodyLG)
@@ -66,17 +68,17 @@ struct UserIndicatorModalView_Previews: PreviewProvider {
iconName: "checkmark")
)
.previewDisplayName("Spinner")
UserIndicatorModalView(indicator: UserIndicator(type: .modal,
UserIndicatorModalView(indicator: UserIndicator(type: .modal(progress: .published(ProgressTracker(initialValue: 0.5)),
interactiveDismissDisabled: false),
title: "Successfully logged in",
iconName: "checkmark",
loaderType: .progress(ProgressTracker(initialValue: 0.5)))
iconName: "checkmark")
)
.previewDisplayName("Progress Bar")
UserIndicatorModalView(indicator: UserIndicator(type: .modal,
UserIndicatorModalView(indicator: UserIndicator(type: .modal(progress: .none, interactiveDismissDisabled: false),
title: "Successfully logged in",
iconName: "checkmark",
loaderType: .none)
iconName: "checkmark")
)
.previewDisplayName("No progress")
}
@@ -20,21 +20,27 @@ struct UserIndicatorToastView: View {
let indicator: UserIndicator
var body: some View {
HStack {
HStack(spacing: 4) {
if case .indeterminate = indicator.progress {
ProgressView()
.controlSize(.small)
.tint(.compound.iconPrimary)
}
if let iconName = indicator.iconName {
Image(systemName: iconName)
.font(.compound.bodyMD)
.foregroundColor(.compound.iconPrimary)
}
Text(indicator.title)
.font(.compound.bodySM)
.font(.compound.bodyMD)
.foregroundColor(.compound.textPrimary)
}
.id(indicator.id)
.padding(.horizontal, 12.0)
.padding(.vertical, 10.0)
.frame(minWidth: 150.0)
.background(Color.compound.bgSubtlePrimary)
.clipShape(RoundedCornerShape(radius: 24.0, corners: .allCorners))
.shadow(color: .black.opacity(0.25), radius: 10.0, y: 4.0)
.shadow(color: .black.opacity(0.1), radius: 6.0, y: 4.0)
.transition(toastTransition)
}
@@ -48,11 +54,14 @@ struct UserIndicatorToastView: View {
struct UserIndicatorToastView_Previews: PreviewProvider {
static var previews: some View {
VStack {
VStack(spacing: 30) {
UserIndicatorToastView(indicator: UserIndicator(title: "Successfully logged in",
iconName: "checkmark"))
UserIndicatorToastView(indicator: UserIndicator(title: "Toast without icon"))
UserIndicatorToastView(indicator: UserIndicator(type: .toast(progress: .indeterminate),
title: "Syncing"))
}
}
}