mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-05 11:58:32 +00:00
Update iconography visible in launch video (#1762)
This commit is contained in:
@@ -33,35 +33,45 @@ internal enum Asset {
|
||||
internal static let appLogo = ImageAsset(name: "images/app-logo")
|
||||
internal static let serverSelectionIcon = ImageAsset(name: "images/server-selection-icon")
|
||||
internal static let closeCircle = ImageAsset(name: "images/close-circle")
|
||||
internal static let addLocation = ImageAsset(name: "images/add-location")
|
||||
internal static let attachment = ImageAsset(name: "images/attachment")
|
||||
internal static let photosLibrary = ImageAsset(name: "images/photos-library")
|
||||
internal static let takePhoto = ImageAsset(name: "images/take-photo")
|
||||
internal static let textFormatting = ImageAsset(name: "images/text-formatting")
|
||||
internal static let bold = ImageAsset(name: "images/bold")
|
||||
internal static let bulletList = ImageAsset(name: "images/bullet-list")
|
||||
internal static let closeRte = ImageAsset(name: "images/close-rte")
|
||||
internal static let codeBlock = ImageAsset(name: "images/code-block")
|
||||
internal static let composerAttachment = ImageAsset(name: "images/composer-attachment")
|
||||
internal static let editing = ImageAsset(name: "images/editing")
|
||||
internal static let indent = ImageAsset(name: "images/indent")
|
||||
internal static let inlineCode = ImageAsset(name: "images/inline-code")
|
||||
internal static let italic = ImageAsset(name: "images/italic")
|
||||
internal static let link = ImageAsset(name: "images/link")
|
||||
internal static let numberedList = ImageAsset(name: "images/numbered-list")
|
||||
internal static let quote = ImageAsset(name: "images/quote")
|
||||
internal static let sendMessage = ImageAsset(name: "images/send-message")
|
||||
internal static let strikethrough = ImageAsset(name: "images/strikethrough")
|
||||
internal static let textFormat = ImageAsset(name: "images/text-format")
|
||||
internal static let underline = ImageAsset(name: "images/underline")
|
||||
internal static let unindent = ImageAsset(name: "images/unindent")
|
||||
internal static let encryptionNormal = ImageAsset(name: "images/encryption-normal")
|
||||
internal static let encryptionTrusted = ImageAsset(name: "images/encryption-trusted")
|
||||
internal static let encryptionWarning = ImageAsset(name: "images/encryption-warning")
|
||||
internal static let decryptionError = ImageAsset(name: "images/decryption-error")
|
||||
internal static let endedPoll = ImageAsset(name: "images/ended-poll")
|
||||
internal static let compose = ImageAsset(name: "images/compose")
|
||||
internal static let launchBackground = ImageAsset(name: "images/launch-background")
|
||||
internal static let locationMarker = ImageAsset(name: "images/location-marker")
|
||||
internal static let locationPin = ImageAsset(name: "images/location-pin")
|
||||
internal static let locationPointerFull = ImageAsset(name: "images/location-pointer-full")
|
||||
internal static let locationPointer = ImageAsset(name: "images/location-pointer")
|
||||
internal static let closeRte = ImageAsset(name: "images/close-rte")
|
||||
internal static let composerAttachment = ImageAsset(name: "images/composer-attachment")
|
||||
internal static let timelineComposerSendMessage = ImageAsset(name: "images/timeline-composer-send-message")
|
||||
internal static let addReaction = ImageAsset(name: "images/add-reaction")
|
||||
internal static let copy = ImageAsset(name: "images/copy")
|
||||
internal static let editOutline = ImageAsset(name: "images/edit-outline")
|
||||
internal static let forward = ImageAsset(name: "images/forward")
|
||||
internal static let reply = ImageAsset(name: "images/reply")
|
||||
internal static let viewSource = ImageAsset(name: "images/view-source")
|
||||
internal static let timelineEndedPoll = ImageAsset(name: "images/timeline-ended-poll")
|
||||
internal static let timelinePollAttachment = ImageAsset(name: "images/timeline-poll-attachment")
|
||||
internal static let timelinePoll = ImageAsset(name: "images/timeline-poll")
|
||||
internal static let timelineReactionAddMore = ImageAsset(name: "images/timeline-reaction-add-more")
|
||||
internal static let waitingGradient = ImageAsset(name: "images/waiting-gradient")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// Copyright 2022 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Compound
|
||||
import SwiftUI
|
||||
|
||||
extension Label {
|
||||
/// Creates a label using a local asset as a Compound icon and a title generated from a string.
|
||||
/// The icon size will be 24pt, scaling relative to the `bodyLG` with Dynamic Type.
|
||||
/// - Parameters:
|
||||
/// - title: A string used as the label’s title.
|
||||
/// - iconAsset: The asset to use as the custom Compound icon.
|
||||
///
|
||||
/// The supplied asset should have a square frame or it may end up distorted.
|
||||
init(_ title: some StringProtocol, iconAsset: ImageAsset) where Title == Text, Icon == CompoundIcon {
|
||||
self.init {
|
||||
Text(title)
|
||||
} icon: {
|
||||
CompoundIcon(customImage: iconAsset.swiftUIImage)
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a label using a local asset as a Compound icon and a title generated from a string.
|
||||
/// - Parameters:
|
||||
/// - title: A string used as the label’s title.
|
||||
/// - iconAsset: The asset to use as the custom Compound icon.
|
||||
/// - size: The size of the icon.
|
||||
/// - font: The font that the icon will scale relative to for Dynamic Type.
|
||||
///
|
||||
/// The supplied asset should have a square frame or it may end up distorted.
|
||||
init(_ title: some StringProtocol,
|
||||
iconAsset: ImageAsset,
|
||||
iconSize: CompoundIcon.Size,
|
||||
relativeTo font: Font) where Title == Text, Icon == CompoundIcon {
|
||||
self.init {
|
||||
Text(title)
|
||||
} icon: {
|
||||
CompoundIcon(customImage: iconAsset.swiftUIImage, size: iconSize, relativeTo: font)
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
-9
@@ -16,21 +16,23 @@
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct FixedIconSizeLabelStyle: LabelStyle {
|
||||
@ScaledMetric private var iconSize: CGFloat
|
||||
extension LabelStyle where Self == MenuSheetLabelStyle {
|
||||
/// A label style for labels that are within a menu that is being presented as a sheet.
|
||||
static var menuSheet: Self { MenuSheetLabelStyle() }
|
||||
}
|
||||
|
||||
init(iconSize: Double = 24.0) {
|
||||
_iconSize = .init(wrappedValue: iconSize)
|
||||
}
|
||||
|
||||
/// The style used for labels that are part of a menu that's presented as
|
||||
/// a sheet as `TimelineItemMenu` and `RoomAttachmentPicker`.
|
||||
struct MenuSheetLabelStyle: LabelStyle {
|
||||
var spacing: CGFloat = 16
|
||||
|
||||
func makeBody(configuration: Configuration) -> some View {
|
||||
HStack(spacing: spacing) {
|
||||
configuration
|
||||
.icon
|
||||
.frame(width: iconSize, height: iconSize)
|
||||
configuration.icon
|
||||
configuration.title
|
||||
}
|
||||
.multilineTextAlignment(.leading)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding(16)
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Compound
|
||||
import SwiftUI
|
||||
import WysiwygComposer
|
||||
|
||||
@@ -82,6 +83,7 @@ struct ComposerToolbar: View {
|
||||
.frame(width: closeRTEButtonSize, height: closeRTEButtonSize)
|
||||
.padding(7)
|
||||
}
|
||||
.accessibilityLabel(L10n.actionClose)
|
||||
.accessibilityIdentifier(A11yIdentifiers.roomScreen.composerToolbar.closeFormattingOptions)
|
||||
}
|
||||
|
||||
@@ -152,12 +154,11 @@ struct ComposerToolbar: View {
|
||||
private var submitButtonImage: some View {
|
||||
// ZStack with opacity so the button size is consistent.
|
||||
ZStack {
|
||||
Image(systemName: "checkmark")
|
||||
CompoundIcon(\.check)
|
||||
.opacity(context.viewState.composerMode.isEdit ? 1 : 0)
|
||||
.fontWeight(.medium)
|
||||
.accessibilityLabel(L10n.actionConfirm)
|
||||
.accessibilityHidden(!context.viewState.composerMode.isEdit)
|
||||
Image(asset: Asset.Images.timelineComposerSendMessage)
|
||||
Image(asset: Asset.Images.sendMessage)
|
||||
.resizable()
|
||||
.frame(width: sendButtonIconSize, height: sendButtonIconSize)
|
||||
.padding(EdgeInsets(top: 10, leading: 11, bottom: 10, trailing: 9))
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Compound
|
||||
import SwiftUI
|
||||
import WysiwygComposer
|
||||
|
||||
@@ -132,11 +133,11 @@ private struct MessageComposerReplyHeader: View {
|
||||
.cornerRadius(13.0)
|
||||
.overlay(alignment: .topTrailing) {
|
||||
Button(action: action) {
|
||||
Image(systemName: "xmark")
|
||||
.font(.compound.bodySM.weight(.medium))
|
||||
CompoundIcon(\.close, size: .small, relativeTo: .compound.bodySMSemibold)
|
||||
.foregroundColor(.compound.iconTertiary)
|
||||
.padding(8.0)
|
||||
.padding(4.0)
|
||||
}
|
||||
.accessibilityLabel(L10n.actionClose)
|
||||
}
|
||||
.padding(.vertical, 8.0)
|
||||
.padding(.horizontal, -4.0)
|
||||
@@ -148,26 +149,29 @@ private struct MessageComposerEditHeader: View {
|
||||
|
||||
var body: some View {
|
||||
HStack(alignment: .center) {
|
||||
Label(L10n.commonEditing, systemImage: "pencil.line")
|
||||
Label(L10n.commonEditing,
|
||||
iconAsset: Asset.Images.editing,
|
||||
iconSize: .xSmall,
|
||||
relativeTo: .compound.bodySMSemibold)
|
||||
.labelStyle(MessageComposerHeaderLabelStyle())
|
||||
Spacer()
|
||||
Button(action: action) {
|
||||
Image(systemName: "xmark")
|
||||
.font(.compound.bodySM.weight(.medium))
|
||||
CompoundIcon(\.close, size: .small, relativeTo: .compound.bodySMSemibold)
|
||||
.foregroundColor(.compound.iconTertiary)
|
||||
.padding(EdgeInsets(top: 10, leading: 12, bottom: 12, trailing: 14))
|
||||
.padding([.leading, .vertical], 6.0)
|
||||
}
|
||||
.accessibilityLabel(L10n.actionClose)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct MessageComposerHeaderLabelStyle: LabelStyle {
|
||||
func makeBody(configuration: Configuration) -> some View {
|
||||
HStack(alignment: .firstTextBaseline, spacing: 5) {
|
||||
HStack(alignment: .center, spacing: 4) {
|
||||
configuration.icon
|
||||
configuration.title
|
||||
}
|
||||
.font(.compound.bodySM)
|
||||
.font(.compound.bodySMSemibold)
|
||||
.foregroundColor(.compound.textSecondary)
|
||||
.lineLimit(1)
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Compound
|
||||
import SwiftUI
|
||||
import WysiwygComposer
|
||||
|
||||
@@ -35,6 +36,7 @@ struct RoomAttachmentPicker: View {
|
||||
.foregroundColor(.compound.textActionPrimary)
|
||||
.padding(7)
|
||||
}
|
||||
.accessibilityLabel(L10n.actionAddToTimeline)
|
||||
.accessibilityIdentifier(A11yIdentifiers.roomScreen.composerToolbar.openComposeOptions)
|
||||
.popover(isPresented: $context.showAttachmentPopover) {
|
||||
VStack(alignment: .leading, spacing: 0.0) {
|
||||
@@ -42,7 +44,8 @@ struct RoomAttachmentPicker: View {
|
||||
context.showAttachmentPopover = false
|
||||
context.send(viewAction: .displayMediaPicker)
|
||||
} label: {
|
||||
PickerLabel(title: L10n.screenRoomAttachmentSourceGallery, icon: Image(systemName: "photo.fill"))
|
||||
Label(L10n.screenRoomAttachmentSourceGallery, iconAsset: Asset.Images.photosLibrary)
|
||||
.labelStyle(.menuSheet)
|
||||
}
|
||||
.accessibilityIdentifier(A11yIdentifiers.roomScreen.attachmentPickerPhotoLibrary)
|
||||
|
||||
@@ -50,7 +53,8 @@ struct RoomAttachmentPicker: View {
|
||||
context.showAttachmentPopover = false
|
||||
context.send(viewAction: .displayDocumentPicker)
|
||||
} label: {
|
||||
PickerLabel(title: L10n.screenRoomAttachmentSourceFiles, icon: Image(systemName: "paperclip"))
|
||||
Label(L10n.screenRoomAttachmentSourceFiles, iconAsset: Asset.Images.attachment)
|
||||
.labelStyle(.menuSheet)
|
||||
}
|
||||
.accessibilityIdentifier(A11yIdentifiers.roomScreen.attachmentPickerDocuments)
|
||||
|
||||
@@ -58,7 +62,8 @@ struct RoomAttachmentPicker: View {
|
||||
context.showAttachmentPopover = false
|
||||
context.send(viewAction: .displayCameraPicker)
|
||||
} label: {
|
||||
PickerLabel(title: L10n.screenRoomAttachmentSourceCamera, icon: Image(systemName: "camera.fill"))
|
||||
Label(L10n.screenRoomAttachmentSourceCamera, iconAsset: Asset.Images.takePhoto)
|
||||
.labelStyle(.menuSheet)
|
||||
}
|
||||
.accessibilityIdentifier(A11yIdentifiers.roomScreen.attachmentPickerCamera)
|
||||
|
||||
@@ -66,7 +71,8 @@ struct RoomAttachmentPicker: View {
|
||||
context.showAttachmentPopover = false
|
||||
context.send(viewAction: .displayLocationPicker)
|
||||
} label: {
|
||||
PickerLabel(title: L10n.screenRoomAttachmentSourceLocation, icon: Image(asset: Asset.Images.locationPin))
|
||||
Label(L10n.screenRoomAttachmentSourceLocation, iconAsset: Asset.Images.addLocation)
|
||||
.labelStyle(.menuSheet)
|
||||
}
|
||||
.accessibilityIdentifier(A11yIdentifiers.roomScreen.attachmentPickerLocation)
|
||||
|
||||
@@ -74,7 +80,8 @@ struct RoomAttachmentPicker: View {
|
||||
context.showAttachmentPopover = false
|
||||
context.send(viewAction: .displayPollForm)
|
||||
} label: {
|
||||
PickerLabel(title: L10n.screenRoomAttachmentSourcePoll, icon: Image(asset: Asset.Images.timelinePollAttachment))
|
||||
Label(L10n.screenRoomAttachmentSourcePoll, icon: \.polls)
|
||||
.labelStyle(.menuSheet)
|
||||
}
|
||||
.accessibilityIdentifier(A11yIdentifiers.roomScreen.attachmentPickerPoll)
|
||||
|
||||
@@ -83,7 +90,8 @@ struct RoomAttachmentPicker: View {
|
||||
context.showAttachmentPopover = false
|
||||
context.send(viewAction: .enableTextFormatting)
|
||||
} label: {
|
||||
PickerLabel(title: L10n.screenRoomAttachmentTextFormatting, icon: Image(asset: Asset.Images.textFormat))
|
||||
Label(L10n.screenRoomAttachmentTextFormatting, iconAsset: Asset.Images.textFormat)
|
||||
.labelStyle(.menuSheet)
|
||||
}
|
||||
.accessibilityIdentifier(A11yIdentifiers.roomScreen.attachmentPickerTextFormatting)
|
||||
}
|
||||
@@ -104,30 +112,6 @@ struct RoomAttachmentPicker: View {
|
||||
.presentationDragIndicator(.visible)
|
||||
}
|
||||
}
|
||||
|
||||
private struct PickerLabel: View {
|
||||
let title: String
|
||||
let icon: Image
|
||||
|
||||
init(title: String, icon: Image) {
|
||||
self.title = title
|
||||
self.icon = icon
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
Label {
|
||||
Text(title)
|
||||
} icon: {
|
||||
icon
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
}
|
||||
.labelStyle(FixedIconSizeLabelStyle(iconSize: 20))
|
||||
.multilineTextAlignment(.leading)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding(16)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct RoomAttachmentPicker_Previews: PreviewProvider, TestablePreview {
|
||||
|
||||
@@ -141,11 +141,11 @@ private struct CreatePollOptionView: View {
|
||||
if editMode?.wrappedValue == .active {
|
||||
Button(action: deleteAction) {
|
||||
CompoundIcon(\.delete)
|
||||
.font(.system(size: 24))
|
||||
.foregroundColor(.compound.iconCriticalPrimary)
|
||||
}
|
||||
.disabled(!canDeleteItem)
|
||||
.buttonStyle(PlainButtonStyle())
|
||||
.accessibilityLabel(L10n.actionRemove)
|
||||
}
|
||||
TextField(text: $text) {
|
||||
Text(placeholder)
|
||||
|
||||
@@ -261,9 +261,9 @@ struct HomeScreen: View {
|
||||
Button {
|
||||
context.send(viewAction: .startChat)
|
||||
} label: {
|
||||
Image(systemName: "square.and.pencil")
|
||||
.fontWeight(.semibold)
|
||||
CompoundIcon(customImage: Asset.Images.compose.swiftUIImage)
|
||||
}
|
||||
.accessibilityLabel(L10n.actionStartChat)
|
||||
.accessibilityIdentifier(A11yIdentifiers.homeScreen.startChat)
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ struct HomeScreenEmptyStateView: View {
|
||||
.padding(.bottom, 12)
|
||||
|
||||
Button { context.send(viewAction: .startChat) } label: {
|
||||
Label(L10n.actionStartChat, systemImage: "square.and.pencil")
|
||||
Label(L10n.actionStartChat, iconAsset: Asset.Images.compose)
|
||||
.font(.compound.bodyLGSemibold)
|
||||
.foregroundColor(.compound.textOnSolidPrimary)
|
||||
.padding(.vertical, 6)
|
||||
|
||||
@@ -143,12 +143,10 @@ struct HomeScreenRoomCell: View {
|
||||
case .none, .allMessages:
|
||||
EmptyView()
|
||||
case .mentionsAndKeywordsOnly:
|
||||
CompoundIcon(\.mention)
|
||||
.font(.system(size: 15))
|
||||
CompoundIcon(\.mention, size: .custom(15), relativeTo: .compound.bodyMD)
|
||||
.accessibilityLabel(L10n.a11yNotificationsMentionsOnly)
|
||||
case .mute:
|
||||
CompoundIcon(\.notificationsSolidOff)
|
||||
.font(.system(size: 15))
|
||||
CompoundIcon(\.notificationsSolidOff, size: .custom(15), relativeTo: .compound.bodyMD)
|
||||
.accessibilityLabel(L10n.a11yNotificationsMuted)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,8 +25,7 @@ struct ThreadDecorator: View {
|
||||
.foregroundColor(.compound.textPrimary)
|
||||
.font(.compound.bodyXS)
|
||||
} icon: {
|
||||
CompoundIcon(\.threads)
|
||||
.font(.system(size: 16))
|
||||
CompoundIcon(\.threads, size: .xSmall, relativeTo: .compound.bodyXS)
|
||||
.foregroundColor(.compound.iconSecondary)
|
||||
}
|
||||
.labelStyle(.custom(spacing: 4))
|
||||
|
||||
@@ -209,7 +209,7 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
|
||||
}
|
||||
|
||||
if timelineItem.hasFailedToSend {
|
||||
Image(systemName: "exclamationmark.circle.fill")
|
||||
CompoundIcon(\.error, size: .xSmall, relativeTo: .compound.bodyXS)
|
||||
}
|
||||
}
|
||||
.font(.compound.bodyXS)
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Compound
|
||||
import SwiftUI
|
||||
|
||||
struct TimelineItemStatusView: View {
|
||||
@@ -50,12 +51,10 @@ struct TimelineItemStatusView: View {
|
||||
TimelineDeliveryStatusView(deliveryStatus: .sent)
|
||||
}
|
||||
case .sendingFailed:
|
||||
// The bubbles handle the failure internally
|
||||
// Bubbles handle the failure internally, but plain items don't.
|
||||
if style == .plain {
|
||||
Image(systemName: "exclamationmark.circle.fill")
|
||||
.resizable()
|
||||
CompoundIcon(\.error, size: .xSmall, relativeTo: .compound.bodyMD)
|
||||
.foregroundColor(.compound.iconCriticalPrimary)
|
||||
.frame(width: 16, height: 16)
|
||||
.onTapGesture {
|
||||
context.sendFailedConfirmationDialogInfo = .init(itemID: timelineItem.id)
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ struct TimelineReactionAddMoreButtonLabel: View {
|
||||
|
||||
var body: some View {
|
||||
TimelineReactionButtonLabel {
|
||||
Image(asset: Asset.Images.timelineReactionAddMore)
|
||||
Image(asset: Asset.Images.addReaction)
|
||||
.resizable()
|
||||
.frame(width: addMoreButtonIconSize, height: addMoreButtonIconSize)
|
||||
// Vertical sizing is done by the layout so that the add more button
|
||||
|
||||
+3
-2
@@ -14,6 +14,7 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Compound
|
||||
import SwiftUI
|
||||
|
||||
/// The item shown when all previous items are un-decryptable due to
|
||||
@@ -27,7 +28,7 @@ struct EncryptedHistoryRoomTimelineView: View {
|
||||
.font(.compound.bodyMDSemibold)
|
||||
.foregroundColor(.compound.textInfoPrimary)
|
||||
} icon: {
|
||||
Image(systemName: "info.circle.fill")
|
||||
CompoundIcon(\.info, size: .small, relativeTo: .compound.bodyMDSemibold)
|
||||
.foregroundColor(.compound.iconInfoPrimary)
|
||||
}
|
||||
.labelStyle(EncryptedHistoryLabelStyle())
|
||||
@@ -46,7 +47,7 @@ struct EncryptedHistoryRoomTimelineView: View {
|
||||
|
||||
private struct EncryptedHistoryLabelStyle: LabelStyle {
|
||||
func makeBody(configuration: Configuration) -> some View {
|
||||
HStack(alignment: .firstTextBaseline, spacing: 16) {
|
||||
HStack(alignment: .top, spacing: 16) {
|
||||
configuration.icon
|
||||
configuration.title
|
||||
}
|
||||
|
||||
@@ -21,8 +21,9 @@ struct EncryptedRoomTimelineView: View {
|
||||
|
||||
var body: some View {
|
||||
TimelineStyler(timelineItem: timelineItem) {
|
||||
Label(timelineItem.body, systemImage: "lock.shield")
|
||||
Label(timelineItem.body, iconAsset: Asset.Images.decryptionError, iconSize: .small, relativeTo: .compound.bodyLG)
|
||||
.labelStyle(RoomTimelineViewLabelStyle())
|
||||
.font(.compound.bodyLG)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,11 +32,10 @@ struct RoomTimelineViewLabelStyle: LabelStyle {
|
||||
@Environment(\.timelineStyle) private var timelineStyle
|
||||
|
||||
func makeBody(configuration: Configuration) -> some View {
|
||||
HStack(alignment: .firstTextBaseline, spacing: 8) {
|
||||
HStack(alignment: .center, spacing: 8) {
|
||||
configuration.icon
|
||||
.foregroundColor(.compound.iconSecondary)
|
||||
configuration.title
|
||||
.font(.body)
|
||||
.foregroundColor(.compound.textPrimary)
|
||||
}
|
||||
.padding(.horizontal, timelineStyle == .bubbles ? 4 : 0)
|
||||
@@ -63,6 +63,11 @@ struct EncryptedRoomTimelineView_Previews: PreviewProvider, TestablePreview {
|
||||
timestamp: "Later",
|
||||
isOutgoing: true,
|
||||
senderId: "Anne"))
|
||||
|
||||
EncryptedRoomTimelineView(timelineItem: itemWith(text: "Some other text that is very long and will wrap onto multiple lines.",
|
||||
timestamp: "Later",
|
||||
isOutgoing: true,
|
||||
senderId: "Anne"))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -101,27 +101,27 @@ enum TimelineItemMenuAction: Identifiable, Hashable {
|
||||
var label: some View {
|
||||
switch self {
|
||||
case .copy:
|
||||
Label(L10n.actionCopy, systemImage: "doc.on.doc")
|
||||
Label(L10n.actionCopy, iconAsset: Asset.Images.copy)
|
||||
case .edit:
|
||||
Label(L10n.actionEdit, systemImage: "pencil.line")
|
||||
Label(L10n.actionEdit, iconAsset: Asset.Images.editOutline)
|
||||
case .copyPermalink:
|
||||
Label(L10n.actionCopyLinkToMessage, systemImage: "link")
|
||||
Label(L10n.actionCopyLinkToMessage, icon: \.link)
|
||||
case .reply(let isThread):
|
||||
Label(isThread ? L10n.actionReplyInThread : L10n.actionReply, systemImage: "arrowshape.turn.up.left")
|
||||
Label(isThread ? L10n.actionReplyInThread : L10n.actionReply, iconAsset: Asset.Images.reply)
|
||||
case .forward:
|
||||
Label(L10n.actionForward, systemImage: "arrowshape.turn.up.right")
|
||||
Label(L10n.actionForward, iconAsset: Asset.Images.forward)
|
||||
case .redact:
|
||||
Label(L10n.actionRemove, systemImage: "trash")
|
||||
Label(L10n.actionRemove, icon: \.delete)
|
||||
case .viewSource:
|
||||
Label(L10n.actionViewSource, systemImage: "doc.text.below.ecg")
|
||||
Label(L10n.actionViewSource, iconAsset: Asset.Images.viewSource)
|
||||
case .retryDecryption:
|
||||
Label(L10n.actionRetryDecryption, systemImage: "arrow.down.message")
|
||||
case .report:
|
||||
Label(L10n.actionReportContent, systemImage: "exclamationmark.bubble")
|
||||
Label(L10n.actionReportContent, icon: \.chatProblem)
|
||||
case .react:
|
||||
Label(L10n.actionReact, systemImage: "hand.thumbsup")
|
||||
Label(L10n.actionReact, iconAsset: Asset.Images.addReaction)
|
||||
case .endPoll:
|
||||
Label { Text(L10n.actionEndPoll) } icon: { CompoundIcon(customImage: Asset.Images.endedPoll.swiftUIImage) }
|
||||
Label(L10n.actionEndPoll, iconAsset: Asset.Images.endedPoll)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -227,13 +227,14 @@ public struct TimelineItemMenu: View {
|
||||
context.send(viewAction: .displayEmojiPicker(itemID: item.id))
|
||||
}
|
||||
} label: {
|
||||
Image(asset: Asset.Images.timelineReactionAddMore)
|
||||
Image(asset: Asset.Images.addReaction)
|
||||
.resizable()
|
||||
.frame(width: addMoreButtonIconSize, height: addMoreButtonIconSize)
|
||||
.frame(maxHeight: .infinity, alignment: .center)
|
||||
.foregroundColor(.compound.iconSecondary)
|
||||
.padding(10)
|
||||
}
|
||||
.accessibilityLabel(L10n.actionReact)
|
||||
}
|
||||
.padding(.horizontal)
|
||||
.frame(maxWidth: .infinity, alignment: .center)
|
||||
@@ -269,10 +270,7 @@ public struct TimelineItemMenu: View {
|
||||
send(action)
|
||||
} label: {
|
||||
action.label
|
||||
.labelStyle(FixedIconSizeLabelStyle())
|
||||
.multilineTextAlignment(.leading)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding()
|
||||
.labelStyle(.menuSheet)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,6 @@ struct SettingsScreen: View {
|
||||
Spacer()
|
||||
|
||||
CompoundIcon(\.chevronRight)
|
||||
.font(.system(size: 24))
|
||||
.foregroundColor(.compound.iconTertiaryAlpha)
|
||||
.flipsForRightToLeftLayoutDirection(true)
|
||||
}
|
||||
|
||||
@@ -167,15 +167,6 @@ class RoomProxy: RoomProxyProtocol {
|
||||
roomListItem.avatarUrl().flatMap(URL.init(string:))
|
||||
}
|
||||
|
||||
var encryptionBadgeImage: UIImage? {
|
||||
guard isEncrypted else {
|
||||
return nil
|
||||
}
|
||||
|
||||
// return trusted image for now, should be updated after verification status known
|
||||
return Asset.Images.encryptionTrusted.image
|
||||
}
|
||||
|
||||
var invitedMembersCount: Int {
|
||||
Int(room.invitedMembersCount())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user