mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 12:07:55 +00:00
Move BigIcon into Compound and add a new TitleAndIcon component. (#4866)
* Move BigIcon into Compound. * Replace the old server selection image asset with the \.host icon. * Add a new TitleAndIcon component to Compound. * Add the ability to override TitleAndIcon's padding.
This commit is contained in:
@@ -30,7 +30,6 @@ internal enum Asset {
|
||||
}
|
||||
internal enum Images {
|
||||
internal static let appLogo = ImageAsset(name: "images/app-logo")
|
||||
internal static let serverSelectionIcon = ImageAsset(name: "images/server-selection-icon")
|
||||
internal static let backgroundBottom = ImageAsset(name: "images/background-bottom")
|
||||
internal static let closeRte = ImageAsset(name: "images/close-rte")
|
||||
internal static let composerAttachment = ImageAsset(name: "images/composer-attachment")
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
//
|
||||
// Copyright 2025 Element Creations Ltd.
|
||||
// Copyright 2022-2025 New Vector Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
// Please see LICENSE files in the repository root for full details.
|
||||
//
|
||||
|
||||
import Compound
|
||||
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 `bigIcon()` modifier directly on the Image.
|
||||
struct BigIcon: View {
|
||||
enum Style {
|
||||
case defaultSolid
|
||||
case `default`
|
||||
case alertSolid
|
||||
case alert
|
||||
case successSolid
|
||||
case success
|
||||
|
||||
var foregroundColor: Color {
|
||||
switch self {
|
||||
case .defaultSolid, .default:
|
||||
.compound.iconSecondary
|
||||
case .alertSolid, .alert:
|
||||
.compound.iconCriticalPrimary
|
||||
case .successSolid, .success:
|
||||
.compound.iconSuccessPrimary
|
||||
}
|
||||
}
|
||||
|
||||
var backgroundFillColor: Color {
|
||||
switch self {
|
||||
case .defaultSolid:
|
||||
.compound.bgSubtleSecondary
|
||||
case .alertSolid:
|
||||
.compound.bgCriticalSubtle
|
||||
case .successSolid:
|
||||
.compound.bgSuccessSubtle
|
||||
case .default, .alert, .success:
|
||||
.compound.bgCanvasDefault
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The icon that is shown.
|
||||
let icon: KeyPath<CompoundIcons, Image>
|
||||
var style: Style = .defaultSolid
|
||||
|
||||
var body: some View {
|
||||
CompoundIcon(icon, size: .custom(32), relativeTo: .compound.headingLG)
|
||||
.modifier(BigIconModifier(style: style))
|
||||
}
|
||||
}
|
||||
|
||||
extension Image {
|
||||
/// Styles the image for use as the main/top/hero screen icon. You should prefer
|
||||
/// 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: .compound.headingLG)
|
||||
.modifier(BigIconModifier(style: style))
|
||||
}
|
||||
}
|
||||
|
||||
private struct BigIconModifier: ViewModifier {
|
||||
let style: BigIcon.Style
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
content
|
||||
.scaledFrame(size: 64, relativeTo: .compound.headingLG)
|
||||
.foregroundColor(style.foregroundColor)
|
||||
.background {
|
||||
RoundedRectangle(cornerRadius: 14)
|
||||
.fill(style.backgroundFillColor)
|
||||
}
|
||||
.accessibilityHidden(true)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Previews
|
||||
|
||||
struct BigIcon_Previews: PreviewProvider, TestablePreview {
|
||||
static var previews: some View {
|
||||
VStack(spacing: 40) {
|
||||
HStack(spacing: 20) {
|
||||
BigIcon(icon: \.lockSolid)
|
||||
Image(systemName: "hourglass")
|
||||
.bigIcon()
|
||||
Image(asset: Asset.Images.serverSelectionIcon)
|
||||
.bigIcon(insets: 19)
|
||||
}
|
||||
|
||||
VStack(spacing: 20) {
|
||||
HStack(spacing: 20) {
|
||||
BigIcon(icon: \.helpSolid)
|
||||
BigIcon(icon: \.helpSolid, style: .default)
|
||||
}
|
||||
|
||||
HStack(spacing: 20) {
|
||||
BigIcon(icon: \.errorSolid, style: .alertSolid)
|
||||
BigIcon(icon: \.errorSolid, style: .alert)
|
||||
}
|
||||
|
||||
HStack(spacing: 20) {
|
||||
BigIcon(icon: \.checkCircleSolid, style: .successSolid)
|
||||
BigIcon(icon: \.checkCircleSolid, style: .success)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,6 @@ enum TestablePreviewsDictionary {
|
||||
"AuthenticationStartScreen_Previews" : AuthenticationStartScreen_Previews.self,
|
||||
"AvatarHeaderView_Previews" : AvatarHeaderView_Previews.self,
|
||||
"BadgeLabel_Previews" : BadgeLabel_Previews.self,
|
||||
"BigIcon_Previews" : BigIcon_Previews.self,
|
||||
"BlockedUsersScreen_Previews" : BlockedUsersScreen_Previews.self,
|
||||
"BloomModifier_Previews" : BloomModifier_Previews.self,
|
||||
"BugReportScreen_Previews" : BugReportScreen_Previews.self,
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
// Please see LICENSE files in the repository root for full details.
|
||||
//
|
||||
|
||||
import Compound
|
||||
import SwiftUI
|
||||
|
||||
struct LoginScreen: View {
|
||||
|
||||
+2
-2
@@ -6,6 +6,7 @@
|
||||
// Please see LICENSE files in the repository root for full details.
|
||||
//
|
||||
|
||||
import Compound
|
||||
import SwiftUI
|
||||
|
||||
struct ServerSelectionScreen: View {
|
||||
@@ -32,8 +33,7 @@ struct ServerSelectionScreen: View {
|
||||
/// The title, message and icon at the top of the screen.
|
||||
var header: some View {
|
||||
VStack(spacing: 8) {
|
||||
Image(asset: Asset.Images.serverSelectionIcon)
|
||||
.bigIcon(insets: 19)
|
||||
BigIcon(icon: \.host)
|
||||
.padding(.bottom, 8)
|
||||
|
||||
Text(L10n.screenChangeServerTitle)
|
||||
|
||||
@@ -12,7 +12,7 @@ struct LinkNewDeviceScreen: View {
|
||||
@Bindable var context: LinkNewDeviceScreenViewModel.Context
|
||||
|
||||
var body: some View {
|
||||
FullscreenDialog(topPadding: 24) {
|
||||
FullscreenDialog(topPadding: 0) {
|
||||
mainContent
|
||||
} bottomContent: {
|
||||
buttons
|
||||
@@ -28,33 +28,15 @@ struct LinkNewDeviceScreen: View {
|
||||
var mainContent: some View {
|
||||
switch context.viewState.mode {
|
||||
case .loading, .readyToLink:
|
||||
VStack(spacing: 16) {
|
||||
BigIcon(icon: \.computer, style: .default)
|
||||
|
||||
Text(L10n.screenLinkNewDeviceRootTitle)
|
||||
.font(.compound.headingMDBold)
|
||||
.foregroundColor(.compound.textPrimary)
|
||||
.multilineTextAlignment(.center)
|
||||
}
|
||||
.padding(.horizontal, 8)
|
||||
TitleAndIcon(title: L10n.screenLinkNewDeviceRootTitle,
|
||||
icon: \.computer,
|
||||
iconStyle: .default)
|
||||
.padding(.horizontal, -16) // Remove the FullscreenDialog's default padding in this state.
|
||||
case .notSupported:
|
||||
VStack(spacing: 16) {
|
||||
BigIcon(icon: \.errorSolid, style: .alertSolid)
|
||||
|
||||
VStack(spacing: 8) {
|
||||
Text(L10n.screenLinkNewDeviceErrorNotSupportedTitle)
|
||||
.font(.compound.headingMDBold)
|
||||
.foregroundColor(.compound.textPrimary)
|
||||
.multilineTextAlignment(.center)
|
||||
|
||||
Text(L10n.screenLinkNewDeviceErrorNotSupportedSubtitle)
|
||||
.font(.compound.bodyMD)
|
||||
.foregroundColor(.compound.textSecondary)
|
||||
.multilineTextAlignment(.center)
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 24)
|
||||
.padding(.bottom, 40)
|
||||
TitleAndIcon(title: L10n.screenLinkNewDeviceErrorNotSupportedTitle,
|
||||
subtitle: L10n.screenLinkNewDeviceErrorNotSupportedSubtitle,
|
||||
icon: \.errorSolid,
|
||||
iconStyle: .alertSolid)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -6,6 +6,7 @@
|
||||
// Please see LICENSE files in the repository root for full details.
|
||||
//
|
||||
|
||||
import Compound
|
||||
import SwiftUI
|
||||
|
||||
/// A prompt that asks the user whether they would like to enable Analytics or not.
|
||||
|
||||
Reference in New Issue
Block a user