Update HeroImage to match the BigIcon component from Compound. (#3439)

We can move it across in a following PR.
This commit is contained in:
Doug
2024-10-23 12:13:14 +01:00
committed by GitHub
parent 01886bb4d8
commit 6584b4d084
259 changed files with 552 additions and 545 deletions
@@ -10,39 +10,36 @@ import SwiftUI
/// An image that is styled for use as the main/top/hero screen icon. This component
/// takes a compound icon. If you would like to apply it to an SFSymbol, you can call
/// the `heroImage()` modifier directly on the Image.
struct HeroImage: View {
/// the `bigIcon()` modifier directly on the Image.
struct BigIcon: View {
enum Style {
case normal
case subtle
case defaultSolid
case `default`
case alertSolid
case alert
case successSolid
case success
case critical
case criticalOnSecondary
var foregroundColor: Color {
switch self {
case .normal:
.compound.iconPrimary
case .subtle:
case .defaultSolid, .default:
.compound.iconSecondary
case .success:
.compound.iconSuccessPrimary
case .critical, .criticalOnSecondary:
case .alertSolid, .alert:
.compound.iconCriticalPrimary
case .successSolid, .success:
.compound.iconSuccessPrimary
}
}
var backgroundFillColor: Color {
switch self {
case .normal:
case .defaultSolid:
.compound.bgSubtleSecondary
case .subtle:
.compound.bgSubtlePrimary
case .success:
.compound.bgSuccessSubtle
case .critical:
case .alertSolid:
.compound.bgCriticalSubtle
case .criticalOnSecondary:
case .successSolid:
.compound.bgSuccessSubtle
case .default, .alert, .success:
.compound.bgCanvasDefault
}
}
@@ -50,32 +47,32 @@ struct HeroImage: View {
/// The icon that is shown.
let icon: KeyPath<CompoundIcons, Image>
var style: Style = .normal
var style: Style = .defaultSolid
var body: some View {
CompoundIcon(icon, size: .custom(42), relativeTo: .title)
.modifier(HeroImageModifier(style: style))
CompoundIcon(icon, size: .custom(32), relativeTo: .title)
.modifier(BigIconModifier(style: style))
}
}
extension Image {
/// Styles the image for use as the main/top/hero screen icon. You should prefer
/// the HeroImage component when possible, by using an icon from Compound.
func heroImage(insets: CGFloat = 16, style: HeroImage.Style = .normal) -> some View {
/// the BigIcon component when possible, by using an icon from Compound.
func bigIcon(insets: CGFloat = 16, style: BigIcon.Style = .defaultSolid) -> some View {
resizable()
.renderingMode(.template)
.aspectRatio(contentMode: .fit)
.scaledPadding(insets, relativeTo: .title)
.modifier(HeroImageModifier(style: style))
.modifier(BigIconModifier(style: style))
}
}
private struct HeroImageModifier: ViewModifier {
let style: HeroImage.Style
private struct BigIconModifier: ViewModifier {
let style: BigIcon.Style
func body(content: Content) -> some View {
content
.scaledFrame(size: 70, relativeTo: .title)
.scaledFrame(size: 64, relativeTo: .title)
.foregroundColor(style.foregroundColor)
.background {
RoundedRectangle(cornerRadius: 14)
@@ -87,22 +84,32 @@ private struct HeroImageModifier: ViewModifier {
// MARK: - Previews
struct HeroImage_Previews: PreviewProvider, TestablePreview {
struct BigIcon_Previews: PreviewProvider, TestablePreview {
static var previews: some View {
VStack(spacing: 20) {
VStack(spacing: 40) {
HStack(spacing: 20) {
HeroImage(icon: \.lockSolid)
BigIcon(icon: \.lockSolid)
Image(systemName: "hourglass")
.heroImage()
.bigIcon()
Image(asset: Asset.Images.serverSelectionIcon)
.heroImage(insets: 19)
.bigIcon(insets: 19)
}
HStack(spacing: 20) {
HeroImage(icon: \.helpSolid, style: .subtle)
HeroImage(icon: \.checkCircleSolid, style: .success)
HeroImage(icon: \.error, style: .critical)
HeroImage(icon: \.error, style: .criticalOnSecondary)
VStack(spacing: 20) {
HStack(spacing: 20) {
BigIcon(icon: \.helpSolid)
BigIcon(icon: \.helpSolid, style: .default)
}
HStack(spacing: 20) {
BigIcon(icon: \.error, style: .alertSolid)
BigIcon(icon: \.error, style: .alert)
}
HStack(spacing: 20) {
BigIcon(icon: \.checkCircleSolid, style: .successSolid)
BigIcon(icon: \.checkCircleSolid, style: .success)
}
}
}
}
@@ -58,7 +58,7 @@ struct AppLockSetupPINScreen: View {
var header: some View {
VStack(spacing: 8) {
HeroImage(icon: \.lockSolid)
BigIcon(icon: \.lockSolid)
.padding(.bottom, 8)
Text(context.viewState.title)
@@ -45,7 +45,7 @@ struct LoginScreen: View {
/// The header containing the title and icon.
var header: some View {
VStack(spacing: 8) {
HeroImage(icon: \.lockSolid)
BigIcon(icon: \.lockSolid)
.padding(.bottom, 8)
Text(L10n.screenLoginTitleWithHomeserver(context.viewState.homeserver.address))
@@ -29,7 +29,7 @@ struct ServerConfirmationScreen: View {
var header: some View {
VStack(spacing: 8) {
Image(systemSymbol: .personCropCircleFill)
.heroImage()
.bigIcon()
.padding(.bottom, 8)
Text(context.viewState.title)
@@ -32,7 +32,7 @@ struct ServerSelectionScreen: View {
var header: some View {
VStack(spacing: 8) {
Image(asset: Asset.Images.serverSelectionIcon)
.heroImage(insets: 19)
.bigIcon(insets: 19)
.padding(.bottom, 8)
Text(L10n.screenChangeServerTitle)
@@ -15,7 +15,7 @@ struct EncryptionResetPasswordScreen: View {
var body: some View {
FullscreenDialog {
VStack(spacing: 16) {
HeroImage(icon: \.lockSolid)
BigIcon(icon: \.lockSolid)
Text(L10n.screenResetEncryptionPasswordTitle)
.foregroundColor(.compound.textPrimary)
@@ -39,7 +39,7 @@ struct EncryptionResetScreen: View {
private var header: some View {
VStack(spacing: 8) {
HeroImage(icon: \.error, style: .criticalOnSecondary)
BigIcon(icon: \.error, style: .alert)
.padding(.bottom, 8)
Text(L10n.screenEncryptionResetTitle)
@@ -88,7 +88,7 @@ struct JoinRoomScreen: View {
@ViewBuilder
private var knockedView: some View {
VStack(spacing: 16) {
HeroImage(icon: \.checkCircleSolid, style: .success)
BigIcon(icon: \.checkCircleSolid, style: .successSolid)
VStack(spacing: 8) {
Text(L10n.screenJoinRoomKnockSentTitle)
.font(.compound.headingMDBold)
@@ -35,7 +35,7 @@ struct AnalyticsPromptScreen: View {
private var header: some View {
VStack(spacing: 8) {
HeroImage(icon: \.chart)
BigIcon(icon: \.chart)
.padding(.bottom, 8)
Text(L10n.screenAnalyticsPromptTitle(InfoPlistReader.main.bundleDisplayName))
@@ -37,7 +37,7 @@ struct IdentityConfirmationScreen: View {
@ViewBuilder
private var screenHeader: some View {
VStack(spacing: 0) {
HeroImage(icon: \.lockSolid)
BigIcon(icon: \.lockSolid)
.padding(.bottom, 16)
Text(L10n.screenIdentityConfirmationTitle)
@@ -29,7 +29,7 @@ struct IdentityConfirmedScreen: View {
@ViewBuilder
private var screenHeader: some View {
VStack(spacing: 0) {
HeroImage(icon: \.checkCircle, style: .success)
BigIcon(icon: \.checkCircle, style: .successSolid)
.padding(.bottom, 16)
Text(L10n.screenIdentityConfirmedTitle)
@@ -27,7 +27,7 @@ struct NotificationPermissionsScreen: View {
/// The main content of the screen that is shown inside the scroll view.
private var mainContent: some View {
VStack(spacing: 8) {
HeroImage(icon: \.notificationsSolid)
BigIcon(icon: \.notificationsSolid)
.padding(.bottom, 8)
Text(L10n.screenNotificationOptinTitle)
@@ -58,11 +58,11 @@ struct SessionVerificationScreen: View {
private var screenHeader: some View {
VStack(spacing: 0) {
if context.viewState.verificationState == .initial {
HeroImage(icon: \.lockSolid)
BigIcon(icon: \.lockSolid)
.padding(.bottom, 16)
} else {
Image(systemName: headerImageName)
.heroImage()
.bigIcon()
.padding(.bottom, 16)
}
@@ -50,7 +50,7 @@ struct PinnedEventsTimelineScreen: View {
private var content: some View {
if timelineContext.viewState.pinnedEventIDs.isEmpty {
VStack(spacing: 16) {
HeroImage(icon: \.pin, style: .normal)
BigIcon(icon: \.pin)
Text(L10n.screenPinnedTimelineEmptyStateHeadline)
.font(.compound.headingSMSemibold)
.foregroundStyle(.compound.textPrimary)
@@ -41,7 +41,7 @@ struct QRCodeLoginScreen: View {
FullscreenDialog {
VStack(alignment: .leading, spacing: 40) {
VStack(spacing: 16) {
HeroImage(icon: \.computer, style: .subtle)
BigIcon(icon: \.computer, style: .default)
VStack(spacing: 8) {
Text(L10n.screenQrCodeLoginInitialStateTitle(InfoPlistReader.main.productionAppName))
@@ -101,7 +101,7 @@ struct QRCodeLoginScreen: View {
VStack(spacing: 16) {
switch state {
case .deviceCode:
HeroImage(icon: \.computer, style: .subtle)
BigIcon(icon: \.computer, style: .default)
VStack(spacing: 8) {
Text(L10n.screenQrCodeLoginDeviceCodeTitle)
@@ -115,7 +115,7 @@ struct QRCodeLoginScreen: View {
.multilineTextAlignment(.center)
}
case .verificationCode:
HeroImage(icon: \.lock, style: .subtle)
BigIcon(icon: \.lock, style: .default)
VStack(spacing: 8) {
Text(L10n.screenQrCodeLoginVerifyCodeTitle)
@@ -136,7 +136,7 @@ struct QRCodeLoginScreen: View {
FullscreenDialog {
VStack(spacing: 40) {
VStack(spacing: 16) {
HeroImage(icon: \.takePhotoSolid, style: .subtle)
BigIcon(icon: \.takePhotoSolid, style: .default)
Text(L10n.screenQrCodeLoginScanningStateTitle)
.foregroundColor(.compound.textPrimary)
@@ -256,7 +256,7 @@ struct QRCodeLoginScreen: View {
switch errorState {
case .noCameraPermission:
VStack(spacing: 16) {
HeroImage(icon: \.takePhotoSolid, style: .subtle)
BigIcon(icon: \.takePhotoSolid, style: .default)
VStack(spacing: 8) {
Text(L10n.screenQrCodeLoginNoCameraPermissionStateTitle)
@@ -273,7 +273,7 @@ struct QRCodeLoginScreen: View {
case .connectionNotSecure:
VStack(spacing: 40) {
VStack(spacing: 16) {
HeroImage(icon: \.error, style: .criticalOnSecondary)
BigIcon(icon: \.error, style: .alert)
VStack(spacing: 8) {
Text(L10n.screenQrCodeLoginConnectionNoteSecureStateTitle)
@@ -339,7 +339,7 @@ struct QRCodeLoginScreen: View {
}
VStack(spacing: 16) {
HeroImage(icon: \.error, style: .criticalOnSecondary)
BigIcon(icon: \.error, style: .alert)
VStack(spacing: 8) {
Text(title)
@@ -38,7 +38,7 @@ struct ResolveVerifiedUserSendFailureScreen: View {
var header: some View {
VStack(spacing: 8) {
HeroImage(icon: \.error, style: .critical)
BigIcon(icon: \.error, style: .alertSolid)
.padding(.bottom, 8)
Text(context.viewState.title)
@@ -40,7 +40,7 @@ struct SecureBackupKeyBackupScreen: View {
private var disableBackupSection: some View {
VStack(spacing: 16) {
HeroImage(icon: \.keyOffSolid)
BigIcon(icon: \.keyOffSolid)
Text(L10n.screenKeyBackupDisableTitle)
.foregroundColor(.compound.textPrimary)
@@ -15,7 +15,7 @@ struct SecureBackupLogoutConfirmationScreen: View {
var body: some View {
FullscreenDialog {
VStack(spacing: 16) {
HeroImage(icon: \.keyOffSolid)
BigIcon(icon: \.keyOffSolid)
content
}
.padding()
@@ -53,7 +53,7 @@ struct SecureBackupRecoveryKeyScreen: View {
private var header: some View {
VStack(spacing: 16) {
HeroImage(icon: \.keySolid)
BigIcon(icon: \.keySolid)
Text(context.viewState.title)
.foregroundColor(.compound.textPrimary)