From dd060ae23746fb412171a8bb74149090b6441789 Mon Sep 17 00:00:00 2001 From: mikoldin Date: Fri, 5 Sep 2025 15:42:31 +0800 Subject: [PATCH 1/8] Use Lucide icons on conversation cells and components --- .../Context Menu/ContextMenuVC+Action.swift | 12 ++++----- .../ContextMenuVC+EmojiReactsView.swift | 4 ++- .../Conversations/ConversationSearch.swift | 7 +++-- Session/Conversations/ConversationVC.swift | 4 +-- .../ExpandingAttachmentsButton.swift | 24 ++++++++++++++--- .../Conversations/Input View/InputView.swift | 12 +++++++-- .../VoiceMessageRecordingView.swift | 18 ++++++++----- .../Message Cells/CallMessageCell.swift | 14 +++++++--- .../Content Views/DocumentView.swift | 26 ++++++++++++------- .../Content Views/LinkPreviewView.swift | 5 ++-- .../Content Views/MediaPlaceholderView.swift | 17 ++++++------ .../OpenGroupInvitationView.swift | 6 +++-- .../Content Views/QuoteView.swift | 8 ++++-- .../Content Views/ReactionContainerView.swift | 4 ++- .../SwiftUI/DocumentView_SwiftUI.swift | 3 ++- .../SwiftUI/LinkPreviewView_SwiftUI.swift | 5 ++-- .../OpenGroupInvitationView_SwiftUI.swift | 5 ++-- .../SwiftUI/QuoteView_SwiftUI.swift | 7 +++-- .../SwiftUI/VoiceMessageView_SwiftUI.swift | 2 +- .../Message Cells/InfoMessageCell.swift | 12 +++++++-- .../Message Cells/VisibleMessageCell.swift | 4 ++- .../Settings/ProfilePictureVC.swift | 4 ++- 22 files changed, 139 insertions(+), 64 deletions(-) diff --git a/Session/Conversations/Context Menu/ContextMenuVC+Action.swift b/Session/Conversations/Context Menu/ContextMenuVC+Action.swift index 53b44ea9b5..abe6ecc1a3 100644 --- a/Session/Conversations/Context Menu/ContextMenuVC+Action.swift +++ b/Session/Conversations/Context Menu/ContextMenuVC+Action.swift @@ -58,7 +58,7 @@ extension ContextMenuVC { static func info(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action { return Action( - icon: UIImage(named: "ic_info"), + icon: Lucide.image(icon: .info, size: 24), title: "info".localized(), accessibilityLabel: "Message info" ) { _ in delegate?.info(cellViewModel) } @@ -66,7 +66,7 @@ extension ContextMenuVC { static func retry(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action { return Action( - icon: UIImage(systemName: "arrow.triangle.2.circlepath"), + icon: Lucide.image(icon: .refreshCw, size: 24), title: (cellViewModel.state == .failedToSync ? "resync".localized() : "resend".localized() @@ -77,7 +77,7 @@ extension ContextMenuVC { static func reply(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action { return Action( - icon: UIImage(named: "ic_reply"), + icon: Lucide.image(icon: .reply, size: 24), title: "reply".localized(), shouldDismissInfoScreen: true, accessibilityLabel: "Reply to message" @@ -86,7 +86,7 @@ extension ContextMenuVC { static func copy(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action { return Action( - icon: UIImage(named: "ic_copy"), + icon: Lucide.image(icon: .copy, size: 24), title: "copy".localized(), feedback: "copied".localized(), accessibilityLabel: "Copy text" @@ -95,7 +95,7 @@ extension ContextMenuVC { static func copySessionID(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action { return Action( - icon: UIImage(named: "ic_copy"), + icon: Lucide.image(icon: .copy, size: 24), title: "accountIDCopy".localized(), feedback: "copied".localized(), accessibilityLabel: "Copy Session ID" @@ -118,7 +118,7 @@ extension ContextMenuVC { static func save(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action { return Action( - icon: UIImage(named: "ic_download"), + icon: Lucide.image(icon: .arrowDownToLine, size: 24), title: "save".localized(), feedback: "saved".localized(), accessibilityLabel: "Save attachment" diff --git a/Session/Conversations/Context Menu/ContextMenuVC+EmojiReactsView.swift b/Session/Conversations/Context Menu/ContextMenuVC+EmojiReactsView.swift index 1a855eafc8..11806325b1 100644 --- a/Session/Conversations/Context Menu/ContextMenuVC+EmojiReactsView.swift +++ b/Session/Conversations/Context Menu/ContextMenuVC+EmojiReactsView.swift @@ -1,6 +1,7 @@ // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. import UIKit +import Lucide import SessionUIKit import SessionUtilitiesKit @@ -83,7 +84,8 @@ extension ContextMenuVC { private func setUpViewHierarchy() { // Icon image - let iconImageView = UIImageView(image: #imageLiteral(resourceName: "ic_plus_24").withRenderingMode(.alwaysTemplate)) + let iconImageView = UIImageView(image: Lucide.image(icon: .plus, size: iconSize)? + .withRenderingMode(.alwaysTemplate)) iconImageView.themeTintColor = .textPrimary iconImageView.set(.width, to: iconSize) iconImageView.set(.height, to: iconSize) diff --git a/Session/Conversations/ConversationSearch.swift b/Session/Conversations/ConversationSearch.swift index 69e80a7b90..271ccad6ea 100644 --- a/Session/Conversations/ConversationSearch.swift +++ b/Session/Conversations/ConversationSearch.swift @@ -2,6 +2,7 @@ import UIKit import Combine +import Lucide import GRDB import SignalUtilitiesKit import SessionUIKit @@ -149,7 +150,8 @@ public final class SearchResultsBar: UIView { }() private lazy var upButton: UIButton = { - let icon = #imageLiteral(resourceName: "ic_chevron_up").withRenderingMode(.alwaysTemplate) + let icon = Lucide.image(icon: .chevronUp, size: 24)? + .withRenderingMode(.alwaysTemplate) let result: UIButton = UIButton() result.setImage(icon, for: UIControl.State.normal) result.themeTintColor = .primary @@ -159,7 +161,8 @@ public final class SearchResultsBar: UIView { }() private lazy var downButton: UIButton = { - let icon = #imageLiteral(resourceName: "ic_chevron_down").withRenderingMode(.alwaysTemplate) + let icon = Lucide.image(icon: .chevronDown, size: 24)? + .withRenderingMode(.alwaysTemplate) let result: UIButton = UIButton() result.setImage(icon, for: UIControl.State.normal) result.themeTintColor = .primary diff --git a/Session/Conversations/ConversationVC.swift b/Session/Conversations/ConversationVC.swift index ab8471b452..864f31be8f 100644 --- a/Session/Conversations/ConversationVC.swift +++ b/Session/Conversations/ConversationVC.swift @@ -317,7 +317,7 @@ final class ConversationVC: BaseVC, LibSessionRespondingViewController, Conversa lazy var scrollButton: RoundIconButton = { let result: RoundIconButton = RoundIconButton( - image: UIImage(named: "ic_chevron_down")? + image: Lucide.image(icon: .chevronDown, size: 32)? .withRenderingMode(.alwaysTemplate) ) { [weak self] in // The table view's content size is calculated by the estimated height of cells, @@ -1441,7 +1441,7 @@ final class ConversationVC: BaseVC, LibSessionRespondingViewController, Conversa if shouldHaveCallButton { let callButton = UIBarButtonItem( - image: UIImage(named: "Phone"), + image: Lucide.image(icon: .phone, size: 24), style: .plain, target: self, action: #selector(startCall) diff --git a/Session/Conversations/Input View/ExpandingAttachmentsButton.swift b/Session/Conversations/Input View/ExpandingAttachmentsButton.swift index 7a86f0e68c..80d3754457 100644 --- a/Session/Conversations/Input View/ExpandingAttachmentsButton.swift +++ b/Session/Conversations/Input View/ExpandingAttachmentsButton.swift @@ -1,6 +1,7 @@ // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. import UIKit +import Lucide import SessionUIKit final class ExpandingAttachmentsButton: UIView, InputViewButtonDelegate { @@ -42,7 +43,11 @@ final class ExpandingAttachmentsButton: UIView, InputViewButtonDelegate { }() lazy var gifButtonContainer = container(for: gifButton) lazy var documentButton: InputViewButton = { - let result = InputViewButton(icon: #imageLiteral(resourceName: "actionsheet_document_black"), delegate: self, hasOpaqueBackground: true) + let result = InputViewButton( + icon: Lucide.image(icon: .file, size: InputViewButton.expandedSize), + delegate: self, + hasOpaqueBackground: true + ) result.accessibilityIdentifier = "Documents folder" result.accessibilityLabel = "Files" result.isAccessibilityElement = true @@ -51,7 +56,11 @@ final class ExpandingAttachmentsButton: UIView, InputViewButtonDelegate { }() lazy var documentButtonContainer = container(for: documentButton) lazy var libraryButton: InputViewButton = { - let result = InputViewButton(icon: #imageLiteral(resourceName: "actionsheet_camera_roll_black"), delegate: self, hasOpaqueBackground: true) + let result = InputViewButton( + icon: Lucide.image(icon: .images, size: InputViewButton.expandedSize), + delegate: self, + hasOpaqueBackground: true + ) result.accessibilityIdentifier = "Images folder" result.accessibilityLabel = "Photo library" result.isAccessibilityElement = true @@ -60,7 +69,11 @@ final class ExpandingAttachmentsButton: UIView, InputViewButtonDelegate { }() lazy var libraryButtonContainer = container(for: libraryButton) lazy var cameraButton: InputViewButton = { - let result = InputViewButton(icon: #imageLiteral(resourceName: "actionsheet_camera_black"), delegate: self, hasOpaqueBackground: true) + let result = InputViewButton( + icon: Lucide.image(icon: .camera, size: InputViewButton.expandedSize), + delegate: self, + hasOpaqueBackground: true + ) result.accessibilityIdentifier = "Select camera button" result.accessibilityLabel = "Camera" result.isAccessibilityElement = true @@ -69,7 +82,10 @@ final class ExpandingAttachmentsButton: UIView, InputViewButtonDelegate { }() lazy var cameraButtonContainer = container(for: cameraButton) lazy var mainButton: InputViewButton = { - let result = InputViewButton(icon: #imageLiteral(resourceName: "ic_plus_24"), delegate: self) + let result = InputViewButton( + icon: Lucide.image(icon: .plus, size: InputViewButton.expandedSize), + delegate: self + ) result.accessibilityLabel = "Add attachment" return result diff --git a/Session/Conversations/Input View/InputView.swift b/Session/Conversations/Input View/InputView.swift index 74316f9525..5ff6763c5a 100644 --- a/Session/Conversations/Input View/InputView.swift +++ b/Session/Conversations/Input View/InputView.swift @@ -2,6 +2,7 @@ import UIKit import Combine +import Lucide import SessionUIKit import SessionMessagingKit import SessionUtilitiesKit @@ -73,7 +74,10 @@ final class InputView: UIView, InputViewButtonDelegate, InputTextViewDelegate, M }() private lazy var voiceMessageButton: InputViewButton = { - let result = InputViewButton(icon: #imageLiteral(resourceName: "Microphone"), delegate: self) + let result = InputViewButton( + icon: Lucide.image(icon: .mic, size: InputViewButton.iconSize), + delegate: self + ) result.accessibilityLabel = "New voice message" result.accessibilityIdentifier = "New voice message" result.isAccessibilityElement = true @@ -82,7 +86,11 @@ final class InputView: UIView, InputViewButtonDelegate, InputTextViewDelegate, M }() private lazy var sendButton: InputViewButton = { - let result = InputViewButton(icon: #imageLiteral(resourceName: "ArrowUp"), isSendButton: true, delegate: self) + let result = InputViewButton( + icon: Lucide.image(icon: .arrowUp, size: InputViewButton.iconSize), + isSendButton: true, + delegate: self + ) result.isHidden = true result.accessibilityIdentifier = "Send message button" result.accessibilityLabel = "Send message button" diff --git a/Session/Conversations/Input View/VoiceMessageRecordingView.swift b/Session/Conversations/Input View/VoiceMessageRecordingView.swift index de2c7be67c..f4512cc202 100644 --- a/Session/Conversations/Input View/VoiceMessageRecordingView.swift +++ b/Session/Conversations/Input View/VoiceMessageRecordingView.swift @@ -1,6 +1,7 @@ // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. import UIKit +import Lucide import SessionUIKit import SessionUtilitiesKit @@ -19,7 +20,7 @@ final class VoiceMessageRecordingView: UIView { private lazy var iconImageView: UIImageView = { let result: UIImageView = UIImageView() - result.image = UIImage(named: "Microphone")? + result.image = Lucide.image(icon: .mic, size: VoiceMessageRecordingView.iconSize)? .withRenderingMode(.alwaysTemplate) result.themeTintColor = .white result.contentMode = .scaleAspectFit @@ -58,12 +59,16 @@ final class VoiceMessageRecordingView: UIView { return result }() + + private lazy var chevronImage: UIImage? = Lucide.image( + icon: .chevronLeft, + size: VoiceMessageRecordingView.chevronSize + ) private lazy var chevronImageView: UIImageView = { let result: UIImageView = UIImageView( image: (Dependencies.isRTL ? - UIImage(named: "small_chevron_left")?.withHorizontallyFlippedOrientation() : - UIImage(named: "small_chevron_left") + chevronImage?.withHorizontallyFlippedOrientation() : chevronImage )? .withRenderingMode(.alwaysTemplate) ) @@ -320,7 +325,8 @@ final class VoiceMessageRecordingView: UIView { UIView.animate(withDuration: 0.25, delay: 0, options: .transitionCrossDissolve, animations: { self.lockView.alpha = 0 - self.iconImageView.image = UIImage(named: "ArrowUp")?.withRenderingMode(.alwaysTemplate) + self.iconImageView.image = Lucide.image(icon: .arrowUp, size: VoiceMessageRecordingView.iconSize)? + .withRenderingMode(.alwaysTemplate) self.slideToCancelStackView.alpha = 0 self.cancelButton.alpha = 1 }, completion: { _ in @@ -411,7 +417,7 @@ extension VoiceMessageRecordingView { // Lock icon let lockIconImageView: UIImageView = UIImageView( - image: UIImage(named: "ic_lock_outline")? + image: Lucide.image(icon: .lockKeyhole, size: LockView.lockIconSize)? .withRenderingMode(.alwaysTemplate) ) lockIconImageView.themeTintColor = .textPrimary @@ -421,7 +427,7 @@ extension VoiceMessageRecordingView { // Chevron icon let chevronIconImageView: UIImageView = UIImageView( - image: UIImage(named: "ic_chevron_up")? + image: Lucide.image(icon: .chevronUp, size: LockView.chevronIconSize)? .withRenderingMode(.alwaysTemplate) ) chevronIconImageView.themeTintColor = .textPrimary diff --git a/Session/Conversations/Message Cells/CallMessageCell.swift b/Session/Conversations/Message Cells/CallMessageCell.swift index 305ea3a29c..5c184b58df 100644 --- a/Session/Conversations/Message Cells/CallMessageCell.swift +++ b/Session/Conversations/Message Cells/CallMessageCell.swift @@ -1,6 +1,7 @@ // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. import UIKit +import Lucide import AVFAudio import SessionUIKit import SessionMessagingKit @@ -27,7 +28,7 @@ final class CallMessageCell: MessageCell { private lazy var iconImageView: UIImageView = UIImageView() private lazy var infoImageView: UIImageView = { let result: UIImageView = UIImageView( - image: UIImage(named: "ic_info")? + image: Lucide.image(icon: .info, size: Self.iconSize)? .withRenderingMode(.alwaysTemplate) ) result.themeTintColor = .textPrimary @@ -149,10 +150,15 @@ final class CallMessageCell: MessageCell { iconImageView.image = { switch messageInfo.state { - case .outgoing: return UIImage(named: "CallOutgoing")?.withRenderingMode(.alwaysTemplate) - case .incoming: return UIImage(named: "CallIncoming")?.withRenderingMode(.alwaysTemplate) + case .outgoing: + return Lucide.image(icon: .phoneOutgoing, size: Self.iconSize)? + .withRenderingMode(.alwaysTemplate) + case .incoming: + return Lucide.image(icon: .phoneIncoming, size: Self.iconSize)? + .withRenderingMode(.alwaysTemplate) case .missed, .permissionDenied, .permissionDeniedMicrophone: - return UIImage(named: "CallMissed")?.withRenderingMode(.alwaysTemplate) + return Lucide.image(icon: .phoneMissed, size: Self.iconSize)? + .withRenderingMode(.alwaysTemplate) default: return nil } }() diff --git a/Session/Conversations/Message Cells/Content Views/DocumentView.swift b/Session/Conversations/Message Cells/Content Views/DocumentView.swift index aef1f49e9b..c6a268508f 100644 --- a/Session/Conversations/Message Cells/Content Views/DocumentView.swift +++ b/Session/Conversations/Message Cells/Content Views/DocumentView.swift @@ -1,5 +1,6 @@ // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. +import Lucide import UIKit import SessionUIKit import SessionMessagingKit @@ -22,33 +23,37 @@ final class DocumentView: UIView { } private func setUpViewHierarchy(attachment: Attachment, textColor: ThemeValue) { + let documentIconSize = CGSize(width: 24, height: 32) + let imageBackgroundView: UIView = UIView() imageBackgroundView.themeBackgroundColor = .messageBubble_overlay addSubview(imageBackgroundView) // Image view let imageView = UIImageView( - image: UIImage(systemName: "doc")? + image: Lucide.image(icon: .file, size: documentIconSize.height)? .withRenderingMode(.alwaysTemplate) ) imageView.setContentCompressionResistancePriority(.required, for: .horizontal) imageView.setContentHuggingPriority(.required, for: .horizontal) imageView.contentMode = .scaleAspectFit imageView.themeTintColor = textColor - imageView.set(.width, to: 24) - imageView.set(.height, to: 32) + imageView.set(.width, to: documentIconSize.width) + imageView.set(.height, to: documentIconSize.height) if attachment.isAudio { + let audioIconSize = documentIconSize.height * 0.32 + let audioImageView = UIImageView( - image: UIImage(systemName: "music.note")? + image: Lucide.image(icon: .music2, size: audioIconSize)? .withRenderingMode(.alwaysTemplate) ) audioImageView.contentMode = .scaleAspectFit audioImageView.themeTintColor = textColor imageView.addSubview(audioImageView) audioImageView.center(.horizontal, in: imageView) - audioImageView.center(.vertical, in: imageView, withInset: 4) - audioImageView.set(.height, to: .height, of: imageView, multiplier: 0.32) + audioImageView.center(.vertical, in: imageView, withInset: 2) + audioImageView.set(.height, to: audioIconSize) } // Body label @@ -81,16 +86,17 @@ final class DocumentView: UIView { rightContainerView.addSubview(activityIndicator) activityIndicator.pin(to: rightContainerView, withInset: 8) + let accessoryIconSize = 24.0 + let rightImageView = UIImageView( image: { guard attachment.state != .failedDownload && attachment.state != .failedUpload else { - return UIImage(named: "warning")? - .withRenderingMode(.alwaysTemplate) + return Lucide.image(icon: .fileWarning, size: accessoryIconSize) } switch attachment.isAudio { case true: return UIImage(systemName: "play.fill") - case false: return UIImage(systemName: "arrow.down") + case false: return Lucide.image(icon: .arrowDown, size: accessoryIconSize) } }()?.withRenderingMode(.alwaysTemplate) ) @@ -99,7 +105,7 @@ final class DocumentView: UIView { rightImageView.contentMode = .scaleAspectFit rightImageView.themeTintColor = textColor rightImageView.isHidden = (attachment.state == .uploading || attachment.state == .downloading) - rightImageView.set(.height, to: 24) + rightImageView.set(.height, to: accessoryIconSize) rightContainerView.addSubview(rightImageView) rightImageView.center(in: rightContainerView) diff --git a/Session/Conversations/Message Cells/Content Views/LinkPreviewView.swift b/Session/Conversations/Message Cells/Content Views/LinkPreviewView.swift index 7ec1765625..cac3c6a178 100644 --- a/Session/Conversations/Message Cells/Content Views/LinkPreviewView.swift +++ b/Session/Conversations/Message Cells/Content Views/LinkPreviewView.swift @@ -1,6 +1,7 @@ // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. import UIKit +import Lucide import NVActivityIndicatorView import SessionUIKit import SessionMessagingKit @@ -70,7 +71,7 @@ final class LinkPreviewView: UIView { private lazy var cancelButton: UIButton = { let result: UIButton = UIButton(type: .custom) result.setImage( - UIImage(named: "X")? + Lucide.image(icon: .x, size: LinkPreviewView.cancelButtonSize)? .withRenderingMode(.alwaysTemplate), for: .normal ) @@ -156,7 +157,7 @@ final class LinkPreviewView: UIView { var image: UIImage? = state.image let stateHasImage: Bool = (image != nil) if image == nil && (state is LinkPreview.DraftState || state is LinkPreview.SentState) { - image = UIImage(named: "Link")?.withRenderingMode(.alwaysTemplate) + image = Lucide.image(icon: .link, size: 32)?.withRenderingMode(.alwaysTemplate) } // Image view diff --git a/Session/Conversations/Message Cells/Content Views/MediaPlaceholderView.swift b/Session/Conversations/Message Cells/Content Views/MediaPlaceholderView.swift index d70572f72b..2f34ea6c5f 100644 --- a/Session/Conversations/Message Cells/Content Views/MediaPlaceholderView.swift +++ b/Session/Conversations/Message Cells/Content Views/MediaPlaceholderView.swift @@ -1,5 +1,6 @@ // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. +import Lucide import UIKit import SessionMessagingKit import SessionUIKit @@ -29,13 +30,13 @@ final class MediaPlaceholderView: UIView { cellViewModel: MessageViewModel, textColor: ThemeValue ) { - let (iconName, attachmentDescription): (String, String) = { + let (icon, attachmentDescription): (Lucide.Icon?, String) = { guard cellViewModel.variant == .standardIncoming, let attachment: Attachment = cellViewModel.attachments?.first else { return ( - "actionsheet_document_black", // stringlint:ignore + .file, "file".localized().lowercased() ) // Should never occur } @@ -43,19 +44,19 @@ final class MediaPlaceholderView: UIView { switch (attachment.isAudio, (attachment.isImage || attachment.isVideo)) { case (true, _): return ( - "attachment_audio", // stringlint:ignore + .mic, "audio".localized().lowercased() ) case (_, true): return ( - "actionsheet_camera_roll_black", // stringlint:ignore + .images, "media".localized().lowercased() ) default: return ( - "actionsheet_document_black", // stringlint:ignore + .file, "file".localized().lowercased() ) } @@ -66,11 +67,11 @@ final class MediaPlaceholderView: UIView { imageContainerView.set(.width, to: MediaPlaceholderView.iconImageViewSize) imageContainerView.set(.height, to: MediaPlaceholderView.iconImageViewSize) - let imageView = UIImageView(image: UIImage(named: iconName)?.withRenderingMode(.alwaysTemplate)) + let imageView = UIImageView(image: Lucide + .image(icon: .file, size: MediaPlaceholderView.iconSize)? + .withRenderingMode(.alwaysTemplate)) imageView.themeTintColor = textColor imageView.contentMode = .scaleAspectFit - imageView.set(.width, to: MediaPlaceholderView.iconSize) - imageView.set(.height, to: MediaPlaceholderView.iconSize) imageContainerView.addSubview(imageView) imageView.center(in: imageContainerView) diff --git a/Session/Conversations/Message Cells/Content Views/OpenGroupInvitationView.swift b/Session/Conversations/Message Cells/Content Views/OpenGroupInvitationView.swift index b076ac680a..5b5fa85cc2 100644 --- a/Session/Conversations/Message Cells/Content Views/OpenGroupInvitationView.swift +++ b/Session/Conversations/Message Cells/Content Views/OpenGroupInvitationView.swift @@ -1,6 +1,7 @@ // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. import UIKit +import Lucide import SessionUIKit import SessionMessagingKit @@ -69,9 +70,10 @@ final class OpenGroupInvitationView: UIView { iconContainerView.set(.width, to: OpenGroupInvitationView.iconImageViewSize) iconContainerView.set(.height, to: OpenGroupInvitationView.iconImageViewSize) - let iconName = (isOutgoing ? "Globe" : "Plus") // stringlint:ignore + let iconName: Lucide.Icon = isOutgoing ? .globe : .plus let iconImageView = UIImageView( - image: UIImage(named: iconName)?.withRenderingMode(.alwaysTemplate) + image: Lucide.image(icon: iconName, size: Self.iconSize)? + .withRenderingMode(.alwaysTemplate) ) iconImageView.themeTintColor = (isOutgoing ? .messageBubble_outgoingText : .textPrimary) iconImageView.contentMode = .scaleAspectFit diff --git a/Session/Conversations/Message Cells/Content Views/QuoteView.swift b/Session/Conversations/Message Cells/Content Views/QuoteView.swift index 1c7d67b06c..816456c6c4 100644 --- a/Session/Conversations/Message Cells/Content Views/QuoteView.swift +++ b/Session/Conversations/Message Cells/Content Views/QuoteView.swift @@ -1,6 +1,7 @@ // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. import UIKit +import Lucide import SessionUIKit import SessionMessagingKit import SessionUtilitiesKit @@ -98,7 +99,7 @@ final class QuoteView: UIView { if let attachment: Attachment = attachment { let isAudio: Bool = attachment.isAudio - let fallbackImageName: String = (isAudio ? "attachment_audio" : "actionsheet_document_black") // stringlint:ignore + let imageContainerView: UIView = UIView() imageContainerView.themeBackgroundColor = .messageBubble_overlay imageContainerView.layer.cornerRadius = VisibleMessageCell.smallCornerRadius @@ -107,8 +108,11 @@ final class QuoteView: UIView { imageContainerView.set(.height, to: thumbnailSize) mainStackView.addArrangedSubview(imageContainerView) + let fallbackIcon: Lucide.Icon = (isAudio ? .mic : .file) + let imageView: SessionImageView = SessionImageView( - image: UIImage(named: fallbackImageName)?.withRenderingMode(.alwaysTemplate), + image: Lucide.image(icon: fallbackIcon, size: Self.iconSize)? + .withRenderingMode(.alwaysTemplate), dataManager: dependencies[singleton: .imageDataManager] ) imageView.themeTintColor = { diff --git a/Session/Conversations/Message Cells/Content Views/ReactionContainerView.swift b/Session/Conversations/Message Cells/Content Views/ReactionContainerView.swift index 80f11e7122..89bda3db7f 100644 --- a/Session/Conversations/Message Cells/Content Views/ReactionContainerView.swift +++ b/Session/Conversations/Message Cells/Content Views/ReactionContainerView.swift @@ -1,6 +1,7 @@ // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. import UIKit +import Lucide import SessionUIKit import SessionUtilitiesKit import SignalUtilitiesKit @@ -56,7 +57,8 @@ final class ReactionContainerView: UIView { lazy var collapseButton: UIView = { let arrow: UIImageView = UIImageView( - image: UIImage(named: "ic_chevron_up")?.withRenderingMode(.alwaysTemplate) + image: Lucide.image(icon: .chevronUp, size: ReactionContainerView.arrowSize.height)? + .withRenderingMode(.alwaysTemplate) ) arrow.themeTintColor = .textPrimary arrow.set(.width, to: ReactionContainerView.arrowSize.width) diff --git a/Session/Conversations/Message Cells/Content Views/SwiftUI/DocumentView_SwiftUI.swift b/Session/Conversations/Message Cells/Content Views/SwiftUI/DocumentView_SwiftUI.swift index e6a8f1e56f..22d6e24ebf 100644 --- a/Session/Conversations/Message Cells/Content Views/SwiftUI/DocumentView_SwiftUI.swift +++ b/Session/Conversations/Message Cells/Content Views/SwiftUI/DocumentView_SwiftUI.swift @@ -1,6 +1,7 @@ // Copyright © 2023 Rangeproof Pty Ltd. All rights reserved. import SwiftUI +import Lucide import SessionUIKit import SessionMessagingKit @@ -77,7 +78,7 @@ struct DocumentView_SwiftUI: View { } else if attachment.state == .failedDownload || attachment.state == .failedUpload, - let invalidImage: UIImage = UIImage(named: "warning")?.withRenderingMode(.alwaysTemplate) + let invalidImage = Lucide.image(icon: .triangleAlert, size: 24)?.withRenderingMode(.alwaysTemplate) { Image(uiImage: invalidImage) .resizable() diff --git a/Session/Conversations/Message Cells/Content Views/SwiftUI/LinkPreviewView_SwiftUI.swift b/Session/Conversations/Message Cells/Content Views/SwiftUI/LinkPreviewView_SwiftUI.swift index 82ba8d086d..eb8d8c585c 100644 --- a/Session/Conversations/Message Cells/Content Views/SwiftUI/LinkPreviewView_SwiftUI.swift +++ b/Session/Conversations/Message Cells/Content Views/SwiftUI/LinkPreviewView_SwiftUI.swift @@ -1,6 +1,7 @@ // Copyright © 2023 Rangeproof Pty Ltd. All rights reserved. import SwiftUI +import Lucide import SessionUIKit import SessionMessagingKit @@ -64,7 +65,7 @@ public struct LinkPreviewView_SwiftUI: View { .cornerRadius(state is LinkPreview.SentState ? 0 : 8) } else if state is LinkPreview.DraftState || state is LinkPreview.SentState, - let defaultImage: UIImage = UIImage(named: "Link")?.withRenderingMode(.alwaysTemplate) + let defaultImage = Lucide.image(icon: .link, size: 24)?.withRenderingMode(.alwaysTemplate) { Image(uiImage: defaultImage) .foregroundColor( @@ -108,7 +109,7 @@ public struct LinkPreviewView_SwiftUI: View { Button(action: { onCancel?() }, label: { - if let image: UIImage = UIImage(named: "X")?.withRenderingMode(.alwaysTemplate) { + if let image = Lucide.image(icon: .x, size: 24)?.withRenderingMode(.alwaysTemplate) { Image(uiImage: image) .foregroundColor(themeColor: .textPrimary) } diff --git a/Session/Conversations/Message Cells/Content Views/SwiftUI/OpenGroupInvitationView_SwiftUI.swift b/Session/Conversations/Message Cells/Content Views/SwiftUI/OpenGroupInvitationView_SwiftUI.swift index ecf4994cdc..af3fd7550f 100644 --- a/Session/Conversations/Message Cells/Content Views/SwiftUI/OpenGroupInvitationView_SwiftUI.swift +++ b/Session/Conversations/Message Cells/Content Views/SwiftUI/OpenGroupInvitationView_SwiftUI.swift @@ -1,6 +1,7 @@ // Copyright © 2023 Rangeproof Pty Ltd. All rights reserved. import SwiftUI +import Lucide import SessionUIKit import SessionMessagingKit import SessionUtilitiesKit @@ -32,14 +33,14 @@ struct OpenGroupInvitationView_SwiftUI: View { self.textColor = textColor self.isOutgoing = isOutgoing } - + var body: some View { HStack( alignment: .center, spacing: Values.mediumSpacing ) { // Icon - if let iconImage = UIImage(named: isOutgoing ? "Globe" : "Plus")? + if let iconImage = Lucide.image(icon: isOutgoing ? .globe : .plus, size: Self.iconSize)? .withRenderingMode(.alwaysTemplate) { Circle() diff --git a/Session/Conversations/Message Cells/Content Views/SwiftUI/QuoteView_SwiftUI.swift b/Session/Conversations/Message Cells/Content Views/SwiftUI/QuoteView_SwiftUI.swift index 9f92551551..c5d117ccfb 100644 --- a/Session/Conversations/Message Cells/Content Views/SwiftUI/QuoteView_SwiftUI.swift +++ b/Session/Conversations/Message Cells/Content Views/SwiftUI/QuoteView_SwiftUI.swift @@ -1,6 +1,7 @@ // Copyright © 2023 Rangeproof Pty Ltd. All rights reserved. import SwiftUI +import Lucide import SessionUIKit import SessionMessagingKit import SessionUtilitiesKit @@ -90,9 +91,11 @@ struct QuoteView_SwiftUI: View { .resizable() .aspectRatio(contentMode: .fill) } placeholder: { - let fallbackImageName: String = (attachment.isAudio ? "attachment_audio" : "actionsheet_document_black") + let fallbackIcon: Lucide.Icon = (attachment.isAudio ? .mic : .file) - if let image = UIImage(named: fallbackImageName)?.withRenderingMode(.alwaysTemplate) { + if let image = Lucide.image(icon: fallbackIcon, size: Self.iconSize)? + .withRenderingMode(.alwaysTemplate) { + Image(uiImage: image) .foregroundColor(themeColor: { switch info.mode { diff --git a/Session/Conversations/Message Cells/Content Views/SwiftUI/VoiceMessageView_SwiftUI.swift b/Session/Conversations/Message Cells/Content Views/SwiftUI/VoiceMessageView_SwiftUI.swift index ad507a9117..fd334b7ead 100644 --- a/Session/Conversations/Message Cells/Content Views/SwiftUI/VoiceMessageView_SwiftUI.swift +++ b/Session/Conversations/Message Cells/Content Views/SwiftUI/VoiceMessageView_SwiftUI.swift @@ -36,7 +36,7 @@ struct VoiceMessageView_SwiftUI: View { width: Self.toggleContainerSize, height: Self.toggleContainerSize ) - if let toggleImage: UIImage = UIImage(named: isPlaying ? "Pause" : "Play")?.withRenderingMode(.alwaysTemplate) { + if let toggleImage: UIImage = UIImage(systemName: isPlaying ? "pause" : "play.fill")?.withRenderingMode(.alwaysTemplate) { Image(uiImage: toggleImage) .resizable() .foregroundColor(themeColor: .textPrimary) diff --git a/Session/Conversations/Message Cells/InfoMessageCell.swift b/Session/Conversations/Message Cells/InfoMessageCell.swift index 9c626a90c5..9729311389 100644 --- a/Session/Conversations/Message Cells/InfoMessageCell.swift +++ b/Session/Conversations/Message Cells/InfoMessageCell.swift @@ -1,6 +1,7 @@ // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. import UIKit +import Lucide import SessionUIKit import SessionMessagingKit import SessionUtilitiesKit @@ -110,9 +111,16 @@ final class InfoMessageCell: MessageCell { let icon: UIImage? = { switch cellViewModel.variant { case .infoDisappearingMessagesUpdate: - return UIImage(systemName: "timer") + return Lucide.image( + icon: .timer, + size: InfoMessageCell.iconSize + ) - case .infoMediaSavedNotification: return UIImage(named: "ic_download") + case .infoMediaSavedNotification: + return Lucide.image( + icon: .download, + size: InfoMessageCell.iconSize + ) default: return nil } diff --git a/Session/Conversations/Message Cells/VisibleMessageCell.swift b/Session/Conversations/Message Cells/VisibleMessageCell.swift index 21a9517955..d13a96fc0f 100644 --- a/Session/Conversations/Message Cells/VisibleMessageCell.swift +++ b/Session/Conversations/Message Cells/VisibleMessageCell.swift @@ -1,6 +1,7 @@ // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. import UIKit +import Lucide import SessionUIKit import SignalUtilitiesKit import SessionUtilitiesKit @@ -117,7 +118,8 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate { let size = VisibleMessageCell.replyButtonSize result.set(.width, to: size) result.set(.height, to: size) - result.image = UIImage(named: "ic_reply")?.withRenderingMode(.alwaysTemplate) + result.image = Lucide.image(icon: .reply, size: size)? + .withRenderingMode(.alwaysTemplate) result.themeTintColor = .textPrimary return result diff --git a/Session/Conversations/Settings/ProfilePictureVC.swift b/Session/Conversations/Settings/ProfilePictureVC.swift index 8a21c190f9..04be930495 100644 --- a/Session/Conversations/Settings/ProfilePictureVC.swift +++ b/Session/Conversations/Settings/ProfilePictureVC.swift @@ -1,6 +1,7 @@ // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. import UIKit +import Lucide import SessionUIKit import SessionUtilitiesKit @@ -65,7 +66,8 @@ final class ProfilePictureVC: BaseVC { // Close button let closeButton = UIBarButtonItem( - image: #imageLiteral(resourceName: "X").withRenderingMode(.alwaysTemplate), + image: Lucide.image(icon: .x, size: 24)? + .withRenderingMode(.alwaysTemplate), style: .plain, target: self, action: #selector(close) From 3576c4be3559d095fa4833243860108e5c7cee36 Mon Sep 17 00:00:00 2001 From: mikoldin Date: Mon, 8 Sep 2025 10:56:35 +0800 Subject: [PATCH 2/8] Updated Lucide version Used `LucidIconView` on some pages --- Session.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/swiftpm/Package.resolved | 4 +-- .../Context Menu/ContextMenuVC+Action.swift | 14 ++++---- .../ContextMenuVC+EmojiReactsView.swift | 3 +- .../VoiceMessageRecordingView.swift | 10 ++---- .../Message Cells/CallMessageCell.swift | 7 ++-- .../Content Views/DeletedMessageView.swift | 2 +- .../Content Views/DocumentView.swift | 5 +-- .../Content Views/MediaPlaceholderView.swift | 4 +-- .../OpenGroupInvitationView.swift | 6 +--- .../Content Views/QuoteView.swift | 3 +- .../Content Views/ReactionContainerView.swift | 5 +-- .../SwiftUI/DocumentView_SwiftUI.swift | 2 +- .../SwiftUI/LinkPreviewView_SwiftUI.swift | 7 ++-- .../OpenGroupInvitationView_SwiftUI.swift | 32 ++++++++----------- .../SwiftUI/QuoteView_SwiftUI.swift | 29 ++++++----------- .../Message Cells/VisibleMessageCell.swift | 7 ++-- .../Settings/ProfilePictureVC.swift | 2 +- .../Views & Modals/ReactionListSheet.swift | 3 +- .../SessionLabelCarouselView.swift | 9 +++--- .../UIContextualAction+Utilities.swift | 4 +-- 21 files changed, 62 insertions(+), 98 deletions(-) diff --git a/Session.xcodeproj/project.pbxproj b/Session.xcodeproj/project.pbxproj index 157c149838..8b594c034c 100644 --- a/Session.xcodeproj/project.pbxproj +++ b/Session.xcodeproj/project.pbxproj @@ -10362,7 +10362,7 @@ repositoryURL = "https://github.com/session-foundation/session-lucide.git"; requirement = { kind = upToNextMajorVersion; - minimumVersion = 0.468.0; + minimumVersion = 0.473.1; }; }; /* End XCRemoteSwiftPackageReference section */ diff --git a/Session.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Session.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 40c1f21016..67fc0c49b2 100644 --- a/Session.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Session.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -105,8 +105,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/session-foundation/session-lucide.git", "state" : { - "revision" : "af00ad53d714823e07f984aadd7af38bafaae69e", - "version" : "0.473.0" + "revision" : "7da7fc6a2c42ee8549b0b9804455b43c61a0e63f", + "version" : "0.473.1" } }, { diff --git a/Session/Conversations/Context Menu/ContextMenuVC+Action.swift b/Session/Conversations/Context Menu/ContextMenuVC+Action.swift index abe6ecc1a3..b4de4747ca 100644 --- a/Session/Conversations/Context Menu/ContextMenuVC+Action.swift +++ b/Session/Conversations/Context Menu/ContextMenuVC+Action.swift @@ -58,7 +58,7 @@ extension ContextMenuVC { static func info(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action { return Action( - icon: Lucide.image(icon: .info, size: 24), + icon: Lucide.image(icon: .info, size: IconSize.medium.size), title: "info".localized(), accessibilityLabel: "Message info" ) { _ in delegate?.info(cellViewModel) } @@ -66,7 +66,7 @@ extension ContextMenuVC { static func retry(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action { return Action( - icon: Lucide.image(icon: .refreshCw, size: 24), + icon: Lucide.image(icon: .refreshCw, size: IconSize.medium.size), title: (cellViewModel.state == .failedToSync ? "resync".localized() : "resend".localized() @@ -77,7 +77,7 @@ extension ContextMenuVC { static func reply(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action { return Action( - icon: Lucide.image(icon: .reply, size: 24), + icon: Lucide.image(icon: .reply, size: IconSize.medium.size), title: "reply".localized(), shouldDismissInfoScreen: true, accessibilityLabel: "Reply to message" @@ -86,7 +86,7 @@ extension ContextMenuVC { static func copy(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action { return Action( - icon: Lucide.image(icon: .copy, size: 24), + icon: Lucide.image(icon: .copy, size: IconSize.medium.size), title: "copy".localized(), feedback: "copied".localized(), accessibilityLabel: "Copy text" @@ -95,7 +95,7 @@ extension ContextMenuVC { static func copySessionID(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action { return Action( - icon: Lucide.image(icon: .copy, size: 24), + icon: Lucide.image(icon: .copy, size: IconSize.medium.size), title: "accountIDCopy".localized(), feedback: "copied".localized(), accessibilityLabel: "Copy Session ID" @@ -104,7 +104,7 @@ extension ContextMenuVC { static func delete(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action { return Action( - icon: Lucide.image(icon: .trash2, size: 24), + icon: Lucide.image(icon: .trash2, size: IconSize.medium.size), title: "delete".localized(), expirationInfo: ExpirationInfo( expiresStartedAtMs: cellViewModel.expiresStartedAtMs, @@ -118,7 +118,7 @@ extension ContextMenuVC { static func save(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action { return Action( - icon: Lucide.image(icon: .arrowDownToLine, size: 24), + icon: Lucide.image(icon: .arrowDownToLine, size: IconSize.medium.size), title: "save".localized(), feedback: "saved".localized(), accessibilityLabel: "Save attachment" diff --git a/Session/Conversations/Context Menu/ContextMenuVC+EmojiReactsView.swift b/Session/Conversations/Context Menu/ContextMenuVC+EmojiReactsView.swift index 11806325b1..47a03c8cdc 100644 --- a/Session/Conversations/Context Menu/ContextMenuVC+EmojiReactsView.swift +++ b/Session/Conversations/Context Menu/ContextMenuVC+EmojiReactsView.swift @@ -84,8 +84,7 @@ extension ContextMenuVC { private func setUpViewHierarchy() { // Icon image - let iconImageView = UIImageView(image: Lucide.image(icon: .plus, size: iconSize)? - .withRenderingMode(.alwaysTemplate)) + let iconImageView = LucideIconView(icon: .plus, size: iconSize) iconImageView.themeTintColor = .textPrimary iconImageView.set(.width, to: iconSize) iconImageView.set(.height, to: iconSize) diff --git a/Session/Conversations/Input View/VoiceMessageRecordingView.swift b/Session/Conversations/Input View/VoiceMessageRecordingView.swift index f4512cc202..8cd5ede56c 100644 --- a/Session/Conversations/Input View/VoiceMessageRecordingView.swift +++ b/Session/Conversations/Input View/VoiceMessageRecordingView.swift @@ -416,20 +416,14 @@ extension VoiceMessageRecordingView { layer.borderWidth = 1 // Lock icon - let lockIconImageView: UIImageView = UIImageView( - image: Lucide.image(icon: .lockKeyhole, size: LockView.lockIconSize)? - .withRenderingMode(.alwaysTemplate) - ) + let lockIconImageView: LucideIconView = LucideIconView(icon: .lockKeyhole, size: LockView.lockIconSize) lockIconImageView.themeTintColor = .textPrimary lockIconImageView.set(.width, to: LockView.lockIconSize) lockIconImageView.set(.height, to: LockView.lockIconSize) stackView.addArrangedSubview(lockIconImageView) // Chevron icon - let chevronIconImageView: UIImageView = UIImageView( - image: Lucide.image(icon: .chevronUp, size: LockView.chevronIconSize)? - .withRenderingMode(.alwaysTemplate) - ) + let chevronIconImageView: LucideIconView = LucideIconView(icon: .chevronUp, size: LockView.chevronIconSize) chevronIconImageView.themeTintColor = .textPrimary chevronIconImageView.set(.width, to: LockView.chevronIconSize) chevronIconImageView.set(.height, to: LockView.chevronIconSize) diff --git a/Session/Conversations/Message Cells/CallMessageCell.swift b/Session/Conversations/Message Cells/CallMessageCell.swift index 5c184b58df..d023b3f987 100644 --- a/Session/Conversations/Message Cells/CallMessageCell.swift +++ b/Session/Conversations/Message Cells/CallMessageCell.swift @@ -26,11 +26,8 @@ final class CallMessageCell: MessageCell { private lazy var infoImageViewHeightConstraint: NSLayoutConstraint = infoImageView.set(.height, to: 0) private lazy var iconImageView: UIImageView = UIImageView() - private lazy var infoImageView: UIImageView = { - let result: UIImageView = UIImageView( - image: Lucide.image(icon: .info, size: Self.iconSize)? - .withRenderingMode(.alwaysTemplate) - ) + private lazy var infoImageView: LucideIconView = { + let result: LucideIconView = LucideIconView(icon: .info, size: Self.iconSize) result.themeTintColor = .textPrimary return result diff --git a/Session/Conversations/Message Cells/Content Views/DeletedMessageView.swift b/Session/Conversations/Message Cells/Content Views/DeletedMessageView.swift index 566ddceca1..49de40a15b 100644 --- a/Session/Conversations/Message Cells/Content Views/DeletedMessageView.swift +++ b/Session/Conversations/Message Cells/Content Views/DeletedMessageView.swift @@ -34,7 +34,7 @@ final class DeletedMessageView: UIView { imageContainerView.set(.width, to: DeletedMessageView.iconImageViewSize) imageContainerView.set(.height, to: DeletedMessageView.iconImageViewSize) - let imageView = UIImageView(image: Lucide.image(icon: .trash2, size: DeletedMessageView.iconSize)?.withRenderingMode(.alwaysTemplate)) + let imageView = LucideIconView(icon: .trash2, size: DeletedMessageView.iconSize) imageView.themeTintColor = textColor imageView.contentMode = .scaleAspectFit imageView.set(.width, to: DeletedMessageView.iconSize) diff --git a/Session/Conversations/Message Cells/Content Views/DocumentView.swift b/Session/Conversations/Message Cells/Content Views/DocumentView.swift index c6a268508f..cc575aff27 100644 --- a/Session/Conversations/Message Cells/Content Views/DocumentView.swift +++ b/Session/Conversations/Message Cells/Content Views/DocumentView.swift @@ -30,10 +30,7 @@ final class DocumentView: UIView { addSubview(imageBackgroundView) // Image view - let imageView = UIImageView( - image: Lucide.image(icon: .file, size: documentIconSize.height)? - .withRenderingMode(.alwaysTemplate) - ) + let imageView = LucideIconView(icon: .file, size: documentIconSize.height) imageView.setContentCompressionResistancePriority(.required, for: .horizontal) imageView.setContentHuggingPriority(.required, for: .horizontal) imageView.contentMode = .scaleAspectFit diff --git a/Session/Conversations/Message Cells/Content Views/MediaPlaceholderView.swift b/Session/Conversations/Message Cells/Content Views/MediaPlaceholderView.swift index 2f34ea6c5f..96a483cdb3 100644 --- a/Session/Conversations/Message Cells/Content Views/MediaPlaceholderView.swift +++ b/Session/Conversations/Message Cells/Content Views/MediaPlaceholderView.swift @@ -67,9 +67,7 @@ final class MediaPlaceholderView: UIView { imageContainerView.set(.width, to: MediaPlaceholderView.iconImageViewSize) imageContainerView.set(.height, to: MediaPlaceholderView.iconImageViewSize) - let imageView = UIImageView(image: Lucide - .image(icon: .file, size: MediaPlaceholderView.iconSize)? - .withRenderingMode(.alwaysTemplate)) + let imageView = LucideIconView(icon: .file, size: MediaPlaceholderView.iconSize) imageView.themeTintColor = textColor imageView.contentMode = .scaleAspectFit imageContainerView.addSubview(imageView) diff --git a/Session/Conversations/Message Cells/Content Views/OpenGroupInvitationView.swift b/Session/Conversations/Message Cells/Content Views/OpenGroupInvitationView.swift index 5b5fa85cc2..4ea44eaf09 100644 --- a/Session/Conversations/Message Cells/Content Views/OpenGroupInvitationView.swift +++ b/Session/Conversations/Message Cells/Content Views/OpenGroupInvitationView.swift @@ -70,11 +70,7 @@ final class OpenGroupInvitationView: UIView { iconContainerView.set(.width, to: OpenGroupInvitationView.iconImageViewSize) iconContainerView.set(.height, to: OpenGroupInvitationView.iconImageViewSize) - let iconName: Lucide.Icon = isOutgoing ? .globe : .plus - let iconImageView = UIImageView( - image: Lucide.image(icon: iconName, size: Self.iconSize)? - .withRenderingMode(.alwaysTemplate) - ) + let iconImageView = LucideIconView(icon: isOutgoing ? .globe : .plus, size: Self.iconSize) iconImageView.themeTintColor = (isOutgoing ? .messageBubble_outgoingText : .textPrimary) iconImageView.contentMode = .scaleAspectFit iconImageView.set(.width, to: OpenGroupInvitationView.iconSize) diff --git a/Session/Conversations/Message Cells/Content Views/QuoteView.swift b/Session/Conversations/Message Cells/Content Views/QuoteView.swift index 816456c6c4..307dab5201 100644 --- a/Session/Conversations/Message Cells/Content Views/QuoteView.swift +++ b/Session/Conversations/Message Cells/Content Views/QuoteView.swift @@ -240,7 +240,8 @@ final class QuoteView: UIView { if mode == .draft { // Cancel button let cancelButton = UIButton(type: .custom) - cancelButton.setImage(UIImage(named: "X")?.withRenderingMode(.alwaysTemplate), for: .normal) + cancelButton.setImage(Lucide.image(icon: .x, size: Self.iconSize)? + .withRenderingMode(.alwaysTemplate), for: .normal) cancelButton.themeTintColor = .textPrimary cancelButton.set(.width, to: cancelButtonSize) cancelButton.set(.height, to: cancelButtonSize) diff --git a/Session/Conversations/Message Cells/Content Views/ReactionContainerView.swift b/Session/Conversations/Message Cells/Content Views/ReactionContainerView.swift index 89bda3db7f..03381cdf2e 100644 --- a/Session/Conversations/Message Cells/Content Views/ReactionContainerView.swift +++ b/Session/Conversations/Message Cells/Content Views/ReactionContainerView.swift @@ -56,10 +56,7 @@ final class ReactionContainerView: UIView { }() lazy var collapseButton: UIView = { - let arrow: UIImageView = UIImageView( - image: Lucide.image(icon: .chevronUp, size: ReactionContainerView.arrowSize.height)? - .withRenderingMode(.alwaysTemplate) - ) + let arrow = LucideIconView(icon: .chevronUp, size: ReactionContainerView.arrowSize.height) arrow.themeTintColor = .textPrimary arrow.set(.width, to: ReactionContainerView.arrowSize.width) arrow.set(.height, to: ReactionContainerView.arrowSize.height) diff --git a/Session/Conversations/Message Cells/Content Views/SwiftUI/DocumentView_SwiftUI.swift b/Session/Conversations/Message Cells/Content Views/SwiftUI/DocumentView_SwiftUI.swift index 22d6e24ebf..07d0f0b489 100644 --- a/Session/Conversations/Message Cells/Content Views/SwiftUI/DocumentView_SwiftUI.swift +++ b/Session/Conversations/Message Cells/Content Views/SwiftUI/DocumentView_SwiftUI.swift @@ -25,7 +25,7 @@ struct DocumentView_SwiftUI: View { spacing: 0 ) { ZStack { - Image(systemName: "doc") + LucideIcon(.file) .font(.system(size: Values.largeFontSize)) .foregroundColor(themeColor: textColor) diff --git a/Session/Conversations/Message Cells/Content Views/SwiftUI/LinkPreviewView_SwiftUI.swift b/Session/Conversations/Message Cells/Content Views/SwiftUI/LinkPreviewView_SwiftUI.swift index eb8d8c585c..93103fd613 100644 --- a/Session/Conversations/Message Cells/Content Views/SwiftUI/LinkPreviewView_SwiftUI.swift +++ b/Session/Conversations/Message Cells/Content Views/SwiftUI/LinkPreviewView_SwiftUI.swift @@ -63,11 +63,8 @@ public struct LinkPreviewView_SwiftUI: View { height: imageSize ) .cornerRadius(state is LinkPreview.SentState ? 0 : 8) - } else if - state is LinkPreview.DraftState || state is LinkPreview.SentState, - let defaultImage = Lucide.image(icon: .link, size: 24)?.withRenderingMode(.alwaysTemplate) - { - Image(uiImage: defaultImage) + } else if state is LinkPreview.DraftState || state is LinkPreview.SentState { + LucideIcon(.link, size: 24) .foregroundColor( themeColor: isOutgoing ? .messageBubble_outgoingText : diff --git a/Session/Conversations/Message Cells/Content Views/SwiftUI/OpenGroupInvitationView_SwiftUI.swift b/Session/Conversations/Message Cells/Content Views/SwiftUI/OpenGroupInvitationView_SwiftUI.swift index af3fd7550f..7fe7c9c0d4 100644 --- a/Session/Conversations/Message Cells/Content Views/SwiftUI/OpenGroupInvitationView_SwiftUI.swift +++ b/Session/Conversations/Message Cells/Content Views/SwiftUI/OpenGroupInvitationView_SwiftUI.swift @@ -40,24 +40,20 @@ struct OpenGroupInvitationView_SwiftUI: View { spacing: Values.mediumSpacing ) { // Icon - if let iconImage = Lucide.image(icon: isOutgoing ? .globe : .plus, size: Self.iconSize)? - .withRenderingMode(.alwaysTemplate) - { - Circle() - .fill(themeColor: (isOutgoing ? .messageBubble_overlay : .primary)) - .frame( - width: Self.iconImageViewSize, - height: Self.iconImageViewSize - ) - .overlay { - Image(uiImage: iconImage) - .foregroundColor(themeColor: (isOutgoing ? .messageBubble_outgoingText : .textPrimary)) - .frame( - width: Self.iconSize, - height: Self.iconSize - ) - } - } + Circle() + .fill(themeColor: (isOutgoing ? .messageBubble_overlay : .primary)) + .frame( + width: Self.iconImageViewSize, + height: Self.iconImageViewSize + ) + .overlay { + LucideIcon(isOutgoing ? .globe : .plus, size: Self.iconSize) + .foregroundColor(themeColor: (isOutgoing ? .messageBubble_outgoingText : .textPrimary)) + .frame( + width: Self.iconSize, + height: Self.iconSize + ) + } // Text VStack( diff --git a/Session/Conversations/Message Cells/Content Views/SwiftUI/QuoteView_SwiftUI.swift b/Session/Conversations/Message Cells/Content Views/SwiftUI/QuoteView_SwiftUI.swift index c5d117ccfb..2fe06552a8 100644 --- a/Session/Conversations/Message Cells/Content Views/SwiftUI/QuoteView_SwiftUI.swift +++ b/Session/Conversations/Message Cells/Content Views/SwiftUI/QuoteView_SwiftUI.swift @@ -91,25 +91,16 @@ struct QuoteView_SwiftUI: View { .resizable() .aspectRatio(contentMode: .fill) } placeholder: { - let fallbackIcon: Lucide.Icon = (attachment.isAudio ? .mic : .file) - - if let image = Lucide.image(icon: fallbackIcon, size: Self.iconSize)? - .withRenderingMode(.alwaysTemplate) { - - Image(uiImage: image) - .foregroundColor(themeColor: { - switch info.mode { - case .regular: return (info.direction == .outgoing ? - .messageBubble_outgoingText : - .messageBubble_incomingText - ) - case .draft: return .textPrimary - } - }()) - } - else { - Color.clear - } + LucideIcon((attachment.isAudio ? .mic : .file), size: Self.iconSize) + .foregroundColor(themeColor: { + switch info.mode { + case .regular: return (info.direction == .outgoing ? + .messageBubble_outgoingText : + .messageBubble_incomingText + ) + case .draft: return .textPrimary + } + }()) } .frame( width: Self.iconSize, diff --git a/Session/Conversations/Message Cells/VisibleMessageCell.swift b/Session/Conversations/Message Cells/VisibleMessageCell.swift index d13a96fc0f..84f9e26f37 100644 --- a/Session/Conversations/Message Cells/VisibleMessageCell.swift +++ b/Session/Conversations/Message Cells/VisibleMessageCell.swift @@ -113,13 +113,12 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate { return result }() - private lazy var replyIconImageView: UIImageView = { - let result = UIImageView() + private lazy var replyIconImageView: LucideIconView = { let size = VisibleMessageCell.replyButtonSize + + let result = LucideIconView(icon: .reply, size: size) result.set(.width, to: size) result.set(.height, to: size) - result.image = Lucide.image(icon: .reply, size: size)? - .withRenderingMode(.alwaysTemplate) result.themeTintColor = .textPrimary return result diff --git a/Session/Conversations/Settings/ProfilePictureVC.swift b/Session/Conversations/Settings/ProfilePictureVC.swift index 04be930495..7aaa8ea47f 100644 --- a/Session/Conversations/Settings/ProfilePictureVC.swift +++ b/Session/Conversations/Settings/ProfilePictureVC.swift @@ -66,7 +66,7 @@ final class ProfilePictureVC: BaseVC { // Close button let closeButton = UIBarButtonItem( - image: Lucide.image(icon: .x, size: 24)? + image: Lucide.image(icon: .x, size: IconSize.medium.size)? .withRenderingMode(.alwaysTemplate), style: .plain, target: self, diff --git a/Session/Conversations/Views & Modals/ReactionListSheet.swift b/Session/Conversations/Views & Modals/ReactionListSheet.swift index e723a66c1b..b49901810f 100644 --- a/Session/Conversations/Views & Modals/ReactionListSheet.swift +++ b/Session/Conversations/Views & Modals/ReactionListSheet.swift @@ -1,6 +1,7 @@ // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. import UIKit +import Lucide import DifferenceKit import SessionUIKit import SessionMessagingKit @@ -453,7 +454,7 @@ extension ReactionListSheet: UITableViewDelegate, UITableViewDataSource { ), trailingAccessory: (!canRemoveEmoji ? nil : .icon( - UIImage(named: "X")? + Lucide.image(icon: .x, size: IconSize.medium.size)? .withRenderingMode(.alwaysTemplate), size: .medium ) diff --git a/Session/Conversations/Views & Modals/SessionLabelCarouselView.swift b/Session/Conversations/Views & Modals/SessionLabelCarouselView.swift index 25005c3324..5cdd238e87 100644 --- a/Session/Conversations/Views & Modals/SessionLabelCarouselView.swift +++ b/Session/Conversations/Views & Modals/SessionLabelCarouselView.swift @@ -1,6 +1,7 @@ // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. import UIKit +import Lucide import SessionUIKit import SessionUtilitiesKit @@ -73,16 +74,16 @@ final class SessionLabelCarouselView: UIView, UIScrollViewDelegate { return result }() - private lazy var arrowLeft: UIImageView = { - let result = UIImageView(image: UIImage(systemName: "chevron.left")?.withRenderingMode(.alwaysTemplate)) + private lazy var arrowLeft: LucideIconView = { + let result = LucideIconView(icon: .chevronLeft) result.themeTintColor = .textPrimary result.set(.height, to: 10) result.set(.width, to: 5) return result }() - private lazy var arrowRight: UIImageView = { - let result = UIImageView(image: UIImage(systemName: "chevron.right")?.withRenderingMode(.alwaysTemplate)) + private lazy var arrowRight: LucideIconView = { + let result = LucideIconView(icon: .chevronRight) result.themeTintColor = .textPrimary result.set(.height, to: 10) result.set(.width, to: 5) diff --git a/Session/Utilities/UIContextualAction+Utilities.swift b/Session/Utilities/UIContextualAction+Utilities.swift index 5b5ce426a4..488e266e1c 100644 --- a/Session/Utilities/UIContextualAction+Utilities.swift +++ b/Session/Utilities/UIContextualAction+Utilities.swift @@ -122,7 +122,7 @@ public extension UIContextualAction { case .clear: return UIContextualAction( title: "clear".localized(), - icon: Lucide.image(icon: .trash2, size: 24, color: .white), + icon: Lucide.image(icon: .trash2, size: 24), themeTintColor: .white, themeBackgroundColor: themeBackgroundColor, side: side, @@ -615,7 +615,7 @@ public extension UIContextualAction { case .delete: return UIContextualAction( title: "delete".localized(), - icon: Lucide.image(icon: .trash2, size: 24, color: .white), + icon: Lucide.image(icon: .trash2, size: 24), themeTintColor: .white, themeBackgroundColor: themeBackgroundColor, accessibility: Accessibility(identifier: "Delete button"), From f186c688cfaf4f6a34ba6dbdaecf788092a57e3c Mon Sep 17 00:00:00 2001 From: mikoldin Date: Mon, 8 Sep 2025 11:14:39 +0800 Subject: [PATCH 3/8] Use Lucide icons in calls views --- Session/Calls/VideoPreviewVC.swift | 5 +++-- Session/Calls/Views & Modals/CallMissedTipsModal.swift | 7 +++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Session/Calls/VideoPreviewVC.swift b/Session/Calls/VideoPreviewVC.swift index 449b36fbcf..3b82807e1d 100644 --- a/Session/Calls/VideoPreviewVC.swift +++ b/Session/Calls/VideoPreviewVC.swift @@ -1,6 +1,7 @@ // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. import UIKit +import Lucide import SessionUIKit import CoreMedia @@ -44,7 +45,7 @@ class VideoPreviewVC: UIViewController, CameraManagerDelegate { private lazy var closeButton: UIButton = { let result = UIButton(type: .custom) result.setImage( - UIImage(named: "X")? + Lucide.image(icon: .x, size: 24)? .withRenderingMode(.alwaysTemplate), for: .normal ) @@ -59,7 +60,7 @@ class VideoPreviewVC: UIViewController, CameraManagerDelegate { private lazy var confirmButton: UIButton = { let result = UIButton(type: .custom) result.setImage( - UIImage(named: "Check")? + Lucide.image(icon: .check, size: 24)? .withRenderingMode(.alwaysTemplate), for: .normal ) diff --git a/Session/Calls/Views & Modals/CallMissedTipsModal.swift b/Session/Calls/Views & Modals/CallMissedTipsModal.swift index eb702f6c4a..e4664698a7 100644 --- a/Session/Calls/Views & Modals/CallMissedTipsModal.swift +++ b/Session/Calls/Views & Modals/CallMissedTipsModal.swift @@ -1,6 +1,7 @@ // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. import UIKit +import Lucide import SessionUIKit import SessionUtilitiesKit @@ -11,10 +12,8 @@ final class CallMissedTipsModal: Modal { private lazy var tipsIconContainerView: UIView = UIView() - private lazy var tipsIconImageView: UIImageView = { - let result: UIImageView = UIImageView( - image: UIImage(named: "Tips")?.withRenderingMode(.alwaysTemplate) - ) + private lazy var tipsIconImageView: LucideIconView = { + let result = LucideIconView(icon: .lightbulb) result.themeTintColor = .textPrimary result.set(.width, to: 19) result.set(.height, to: 28) From 58badd906bf786fe3eb76471586af5bece4e0028 Mon Sep 17 00:00:00 2001 From: mikoldin Date: Mon, 8 Sep 2025 15:42:32 +0800 Subject: [PATCH 4/8] Media icon updates to Lucide set --- Session.xcodeproj/project.pbxproj | 16 ++++++++++++ Session/Calls/CallVC.swift | 6 ++--- .../Closed Groups/EditGroupViewModel.swift | 5 ++-- Session/Closed Groups/NewClosedGroupVC.swift | 6 ++++- .../View/AppReviewPromptDialog.swift | 3 ++- Session/Home/HomeVC.swift | 3 ++- .../DocumentTitleViewController.swift | 5 ++-- .../ImagePickerController.swift | 7 ++++-- .../SendMediaNavigationController.swift | 11 +++++---- .../crop-lock-custom.imageset/Contents.json | 23 ++++++++++++++++++ .../crop-lock-custom.png | Bin 0 -> 621 bytes .../crop-lock-custom@2x.png | Bin 0 -> 1021 bytes .../crop-lock-custom@3x.png | Bin 0 -> 1475 bytes .../crop-unlock-custom.imageset/Contents.json | 23 ++++++++++++++++++ .../crop-unlock-custom.png | Bin 0 -> 593 bytes .../crop-unlock-custom@2x.png | Bin 0 -> 1052 bytes .../crop-unlock-custom@3x.png | Bin 0 -> 1563 bytes Session/Open Groups/JoinOpenGroupVC.swift | 6 ++++- .../Open Groups/OpenGroupSuggestionGrid.swift | 5 ++-- Session/Settings/HelpViewModel.swift | 12 +++------ .../Settings/PrivacySettingsViewModel.swift | 3 ++- .../SessionHostingViewController.swift | 6 ++++- .../AttachmentItemCollection.swift | 3 ++- .../AttachmentTextToolbar.swift | 5 +++- .../ImageEditorBrushViewController.swift | 7 +++--- .../ImageEditorCropViewController.swift | 20 +++++++++------ .../ImageEditorTextViewController.swift | 5 ++-- .../Image Editing/ImageEditorView.swift | 9 ++++--- .../OWSViewController+ImageEditor.swift | 9 +++++++ .../Shared Views/ApprovalRailCellView.swift | 3 ++- .../Shared Views/OWSButton.swift | 19 +++++++++++++++ 31 files changed, 169 insertions(+), 51 deletions(-) create mode 100644 Session/Meta/Images.xcassets/crop-lock-custom.imageset/Contents.json create mode 100644 Session/Meta/Images.xcassets/crop-lock-custom.imageset/crop-lock-custom.png create mode 100644 Session/Meta/Images.xcassets/crop-lock-custom.imageset/crop-lock-custom@2x.png create mode 100644 Session/Meta/Images.xcassets/crop-lock-custom.imageset/crop-lock-custom@3x.png create mode 100644 Session/Meta/Images.xcassets/crop-unlock-custom.imageset/Contents.json create mode 100644 Session/Meta/Images.xcassets/crop-unlock-custom.imageset/crop-unlock-custom.png create mode 100644 Session/Meta/Images.xcassets/crop-unlock-custom.imageset/crop-unlock-custom@2x.png create mode 100644 Session/Meta/Images.xcassets/crop-unlock-custom.imageset/crop-unlock-custom@3x.png diff --git a/Session.xcodeproj/project.pbxproj b/Session.xcodeproj/project.pbxproj index 8b594c034c..d1ae3e9755 100644 --- a/Session.xcodeproj/project.pbxproj +++ b/Session.xcodeproj/project.pbxproj @@ -1158,6 +1158,8 @@ FDFE75B42ABD46B600655640 /* MockUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD83B9D127D59495005E1583 /* MockUserDefaults.swift */; }; FDFE75B52ABD46B700655640 /* MockUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD83B9D127D59495005E1583 /* MockUserDefaults.swift */; }; FDFF9FDF2A787F57005E0628 /* JSONEncoder+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDFF9FDE2A787F57005E0628 /* JSONEncoder+Utilities.swift */; }; + FE5809902E6EACB0000296AB /* Lucide in Frameworks */ = {isa = PBXBuildFile; productRef = FE58098F2E6EACB0000296AB /* Lucide */; }; + FE5809922E6EADFA000296AB /* Lucide in Frameworks */ = {isa = PBXBuildFile; productRef = FE5809912E6EADFA000296AB /* Lucide */; }; FED288F32E4C28CF00C31171 /* AppReviewPromptDialog.swift in Sources */ = {isa = PBXBuildFile; fileRef = FED288F22E4C28CF00C31171 /* AppReviewPromptDialog.swift */; }; FED288F82E4C3BE100C31171 /* AppReviewPromptModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FED288F72E4C3BE100C31171 /* AppReviewPromptModel.swift */; }; /* End PBXBuildFile section */ @@ -2480,6 +2482,7 @@ FD22866F2C38D42300BC06F7 /* DifferenceKit in Frameworks */, C33FD9C2255A54EF00E217F9 /* SessionMessagingKit.framework in Frameworks */, C33FD9C4255A54EF00E217F9 /* SessionSnodeKit.framework in Frameworks */, + FE5809922E6EADFA000296AB /* Lucide in Frameworks */, C33FD9C5255A54EF00E217F9 /* SessionUtilitiesKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -2515,6 +2518,7 @@ FD2286732C38D43900BC06F7 /* DifferenceKit in Frameworks */, FDC4386C27B4E90300C60D73 /* SessionUtilitiesKit.framework in Frameworks */, C3C2A70B25539E1E00C340D1 /* SessionSnodeKit.framework in Frameworks */, + FE5809902E6EACB0000296AB /* Lucide in Frameworks */, FD6A39132C2A946A00762359 /* SwiftProtobuf in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -5287,6 +5291,7 @@ packageProductDependencies = ( FD6A39212C2AA91D00762359 /* NVActivityIndicatorView */, FD22866E2C38D42300BC06F7 /* DifferenceKit */, + FE5809912E6EADFA000296AB /* Lucide */, ); productName = SignalUtilitiesKit; productReference = C33FD9AB255A548A00E217F9 /* SignalUtilitiesKit.framework */; @@ -5361,6 +5366,7 @@ FD6A39122C2A946A00762359 /* SwiftProtobuf */, FD2286722C38D43900BC06F7 /* DifferenceKit */, FD6673F92D7021F800041530 /* SessionUtil */, + FE58098F2E6EACB0000296AB /* Lucide */, ); productName = SessionMessagingKit; productReference = C3C2A6F025539DE700C340D1 /* SessionMessagingKit.framework */; @@ -10511,6 +10517,16 @@ package = FD6A390E2C2A93CD00762359 /* XCRemoteSwiftPackageReference "WebRTC" */; productName = WebRTC; }; + FE58098F2E6EACB0000296AB /* Lucide */ = { + isa = XCSwiftPackageProductDependency; + package = FD756BEE2D06686500BD7199 /* XCRemoteSwiftPackageReference "session-lucide" */; + productName = Lucide; + }; + FE5809912E6EADFA000296AB /* Lucide */ = { + isa = XCSwiftPackageProductDependency; + package = FD756BEE2D06686500BD7199 /* XCRemoteSwiftPackageReference "session-lucide" */; + productName = Lucide; + }; /* End XCSwiftPackageProductDependency section */ }; rootObject = D221A080169C9E5E00537ABF /* Project object */; diff --git a/Session/Calls/CallVC.swift b/Session/Calls/CallVC.swift index 85b9f8c668..9463da7d65 100644 --- a/Session/Calls/CallVC.swift +++ b/Session/Calls/CallVC.swift @@ -3,6 +3,7 @@ import UIKit import MediaPlayer import AVKit +import Lucide import SessionUIKit import SessionMessagingKit import SessionUtilitiesKit @@ -82,10 +83,7 @@ final class CallVC: UIViewController, VideoPreviewDelegate, AVRoutePickerViewDel result.themeBackgroundColor = .backgroundSecondary result.makeViewDraggable() - let noVideoIcon: UIImageView = UIImageView( - image: UIImage(systemName: "video.slash")? - .withRenderingMode(.alwaysTemplate) - ) + let noVideoIcon = LucideIconView(icon: .videoOff, size: 28) noVideoIcon.themeTintColor = .textPrimary noVideoIcon.set(.width, to: 34) noVideoIcon.set(.height, to: 28) diff --git a/Session/Closed Groups/EditGroupViewModel.swift b/Session/Closed Groups/EditGroupViewModel.swift index 01916f533c..7456d86226 100644 --- a/Session/Closed Groups/EditGroupViewModel.swift +++ b/Session/Closed Groups/EditGroupViewModel.swift @@ -2,6 +2,7 @@ import Foundation import Combine +import Lucide import GRDB import DifferenceKit import SessionUIKit @@ -253,7 +254,7 @@ class EditGroupViewModel: SessionTableViewModel, NavigatableStateHolder, Editabl elements: [ SessionCell.Info( id: .invite, - leadingAccessory: .icon(UIImage(named: "icon_invite")?.withRenderingMode(.alwaysTemplate)), + leadingAccessory: .icon(Lucide.image(icon: .userRoundPlus, size: 24)?.withRenderingMode(.alwaysTemplate)), title: "membersInvite".localized(), accessibility: Accessibility( identifier: "Invite button", @@ -264,7 +265,7 @@ class EditGroupViewModel: SessionTableViewModel, NavigatableStateHolder, Editabl (!isUpdatedGroup || !dependencies[feature: .updatedGroupsAllowInviteById] ? nil : SessionCell.Info( id: .inviteById, - leadingAccessory: .icon(UIImage(named: "ic_plus_24")?.withRenderingMode(.alwaysTemplate)), + leadingAccessory: .icon(Lucide.image(icon: .plus, size: 24)?.withRenderingMode(.alwaysTemplate)), title: "accountIdOrOnsInvite".localized(), accessibility: Accessibility( identifier: "Invite by id", diff --git a/Session/Closed Groups/NewClosedGroupVC.swift b/Session/Closed Groups/NewClosedGroupVC.swift index c332d1b6a2..16bab69a0d 100644 --- a/Session/Closed Groups/NewClosedGroupVC.swift +++ b/Session/Closed Groups/NewClosedGroupVC.swift @@ -2,6 +2,7 @@ import UIKit import Combine +import Lucide import GRDB import DifferenceKit import SessionUIKit @@ -228,7 +229,10 @@ final class NewClosedGroupVC: BaseVC, UITableViewDataSource, UITableViewDelegate setNavBarTitle("groupCreate".localized(), customFontSize: customTitleFontSize) if !hideCloseButton { - let closeButton = UIBarButtonItem(image: #imageLiteral(resourceName: "X"), style: .plain, target: self, action: #selector(close)) + let closeIcon = Lucide.image(icon: .x, size: IconSize.medium.size)? + .withRenderingMode(.alwaysTemplate) + + let closeButton = UIBarButtonItem(image: closeIcon, style: .plain, target: self, action: #selector(close)) closeButton.themeTintColor = .textPrimary navigationItem.rightBarButtonItem = closeButton navigationItem.leftBarButtonItem?.accessibilityIdentifier = "Cancel" diff --git a/Session/Home/App Review/View/AppReviewPromptDialog.swift b/Session/Home/App Review/View/AppReviewPromptDialog.swift index f1878753ea..ec3aa84e62 100644 --- a/Session/Home/App Review/View/AppReviewPromptDialog.swift +++ b/Session/Home/App Review/View/AppReviewPromptDialog.swift @@ -1,6 +1,7 @@ // Copyright © 2025 Rangeproof Pty Ltd. All rights reserved. import UIKit +import Lucide import SessionUIKit class AppReviewPromptDialog: UIView { @@ -14,7 +15,7 @@ class AppReviewPromptDialog: UIView { .withConfiguration( UIButton.Configuration .plain() - .withImage(UIImage(named: "X")?.withRenderingMode(.alwaysTemplate)) + .withImage(Lucide.image(icon: .x, size: Self.closeSize)?.withRenderingMode(.alwaysTemplate)) .withContentInsets(NSDirectionalEdgeInsets(top: 6, leading: 6, bottom: 6, trailing: 6)) ) .withConfigurationUpdateHandler { button in diff --git a/Session/Home/HomeVC.swift b/Session/Home/HomeVC.swift index ecab5c8318..b4c731b4b1 100644 --- a/Session/Home/HomeVC.swift +++ b/Session/Home/HomeVC.swift @@ -2,6 +2,7 @@ import UIKit import Combine +import Lucide import GRDB import DifferenceKit import SessionUIKit @@ -108,7 +109,7 @@ public final class HomeVC: BaseVC, LibSessionRespondingViewController, UITableVi button.isAccessibilityElement = true button.clipsToBounds = true button.setImage( - UIImage(named: "Plus")? + Lucide.image(icon: .plus, size: IconSize.medium.size)? .withRenderingMode(.alwaysTemplate), for: .normal ) diff --git a/Session/Media Viewing & Editing/DocumentTitleViewController.swift b/Session/Media Viewing & Editing/DocumentTitleViewController.swift index ea1814950e..9dcf2ba62b 100644 --- a/Session/Media Viewing & Editing/DocumentTitleViewController.swift +++ b/Session/Media Viewing & Editing/DocumentTitleViewController.swift @@ -2,6 +2,7 @@ import UIKit import QuartzCore +import Lucide import UniformTypeIdentifiers import GRDB import DifferenceKit @@ -358,8 +359,8 @@ class DocumentCell: UITableViewCell { // MARK: - UI - private let iconImageView: UIImageView = { - let result: UIImageView = UIImageView(image: UIImage(systemName: "doc")?.withRenderingMode(.alwaysTemplate)) + private let iconImageView: LucideIconView = { + let result: LucideIconView = LucideIconView(icon: .file, size: 46) result.translatesAutoresizingMaskIntoConstraints = false result.themeTintColor = .textPrimary result.contentMode = .scaleAspectFit diff --git a/Session/Media Viewing & Editing/ImagePickerController.swift b/Session/Media Viewing & Editing/ImagePickerController.swift index ae89e63281..3ac7bf5ffc 100644 --- a/Session/Media Viewing & Editing/ImagePickerController.swift +++ b/Session/Media Viewing & Editing/ImagePickerController.swift @@ -4,6 +4,7 @@ import Foundation import Combine import Photos import PhotosUI +import Lucide import SessionUIKit import SignalUtilitiesKit import SessionMessagingKit @@ -75,7 +76,7 @@ class ImagePickerGridController: UICollectionViewController, PhotoLibraryDelegat // quickly toggle between the Capture and the Picker VC's, we use the same custom "X" // icon here rather than the system "stop" icon so that the spacing matches exactly. // Otherwise there's a noticable shift in the icon placement. - let cancelImage = #imageLiteral(resourceName: "X") + let cancelImage = Lucide.image(icon: .x, size: 24) let cancelButton = UIBarButtonItem(image: cancelImage, style: .plain, target: self, action: #selector(didPressCancel)) cancelButton.themeTintColor = .textPrimary @@ -95,7 +96,9 @@ class ImagePickerGridController: UICollectionViewController, PhotoLibraryDelegat collectionView.addGestureRecognizer(selectionPanGesture) if PHPhotoLibrary.authorizationStatus(for: .readWrite) == .limited { - let addSeletedPhotoButton = UIBarButtonItem.init(barButtonSystemItem: .add, target: self, action: #selector(addSelectedPhoto)) + let plusImage = Lucide.image(icon: .plus, size: 24) + + let addSeletedPhotoButton = UIBarButtonItem.init(image: plusImage, style: .plain, target: self, action: #selector(addSelectedPhoto)) self.navigationItem.rightBarButtonItem = addSeletedPhotoButton } } diff --git a/Session/Media Viewing & Editing/SendMediaNavigationController.swift b/Session/Media Viewing & Editing/SendMediaNavigationController.swift index 5be73955ea..d6a8f7fd7b 100644 --- a/Session/Media Viewing & Editing/SendMediaNavigationController.swift +++ b/Session/Media Viewing & Editing/SendMediaNavigationController.swift @@ -3,6 +3,7 @@ import UIKit import Combine import Photos +import Lucide import SignalUtilitiesKit import SessionUIKit import SessionMessagingKit @@ -193,7 +194,7 @@ class SendMediaNavigationController: UINavigationController { private lazy var mediaLibraryModeButton: InputViewButton = { let result: InputViewButton = InputViewButton( - icon: UIImage(named: "actionsheet_camera_roll_black")? + icon: Lucide.image(icon: .images, size: IconSize.medium.size)? .withRenderingMode(.alwaysTemplate) ) { [weak self] in self?.didTapMediaLibraryModeButton() } @@ -648,12 +649,12 @@ private class DoneButton: UIView { }() private lazy var chevron: UIView = { - let image: UIImage = { - guard Dependencies.isRTL else { return #imageLiteral(resourceName: "small_chevron_right") } + let image: Lucide.Icon = { + guard Dependencies.isRTL else { return .chevronRight } - return #imageLiteral(resourceName: "small_chevron_left") + return .chevronLeft }() - let result: UIImageView = UIImageView(image: image.withRenderingMode(.alwaysTemplate)) + let result: LucideIconView = LucideIconView(icon: image) result.contentMode = .scaleAspectFit result.themeTintColor = .textPrimary result.set(.width, to: 10) diff --git a/Session/Meta/Images.xcassets/crop-lock-custom.imageset/Contents.json b/Session/Meta/Images.xcassets/crop-lock-custom.imageset/Contents.json new file mode 100644 index 0000000000..0296e80ea0 --- /dev/null +++ b/Session/Meta/Images.xcassets/crop-lock-custom.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "crop-lock-custom.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "crop-lock-custom@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "crop-lock-custom@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Session/Meta/Images.xcassets/crop-lock-custom.imageset/crop-lock-custom.png b/Session/Meta/Images.xcassets/crop-lock-custom.imageset/crop-lock-custom.png new file mode 100644 index 0000000000000000000000000000000000000000..cb79c1558a658ff81f1a152c01974811540b6128 GIT binary patch literal 621 zcmV-z0+RiSP)w!(MXM z*N`pGE2EE6of%=fkMt#O%7l(AfL^}*E`6hT@?O|E^A0_5gMLN5QMYp9tW&h-Ok%Bb z2*r0vf_iv88ch&@6x*S&fIM!f&wPGaTWNlA)&viZy3a_H7~P^sU+V=q664D}(BJGj(HLfF1E;lKOVu$MoZ zqQiVQhMv2%&X+3uRF(iXibUuD8=3&vC{Sj9F`t}qArvP{e!YMUgu^cye|weK5ki_2 z3NJKzA)3)jG@})5X7WAjR?eV{97XRV6f+Qk(@Ik;M!QVyYm_=ozH)0Vv2= z9OUlAuDdK zs{mI9t^wnXY@%ZS~*yKlR4>LeZyu z_RJ5vb@%(81_39Ihs~=xSF7bsvyXQcNxgQYR>@DHD?m~A$fIqY&K(zb9;?!Pr7LUW zD0w9~N<-Cki-Km02bba`r;a58O6W{~>ppp<^Hx_kt1(&ZjAm0^-f{ZPcWa4nJ9Ra~ z8#{`BWF48ak)d%8Lwv7U*qH!>rv*&&d(GS;);g9MO4a7JiPps^8vpM6&gby0L0Q>k zax5?$^D;IQd6FF6y4%D(XeDo z@L~qAM=nkE|JcBreE8FH-r)KJmh-B+dTVlCO@F^lP5zX=c#H3m9=^>}xPGQR zR%A?M-7naHOkXl(inu`bN!6#} z#|uyYy0|Rad$PCJb&caK0pj{oRIa~Reg48`rx-WO=y~rqZYsPj`!7pm(dx9U>B)`L zd^@kbJ!{0W?I=g?QIEto-*R(5@9umrF*EzeuBPLC(IN^7KQ>)HE|$3UV$u2FtRt)r z-{bvHcx+th*ihx8C8m(T72i9}T5E#9hxgU*;-vCl>~QU#U}ydKsanJI80$Y*bJ-<7 zX_{8-d|kNb*ny0f^WZ^&6e@7$l(JuIYC9*cys(c&UZJa?bISxxmq4u}OYSfk9ye+P cWu1ooQ%u*p-1fEe2j*4=Pgg&ebxsLQ0JRpu>i_@% literal 0 HcmV?d00001 diff --git a/Session/Meta/Images.xcassets/crop-lock-custom.imageset/crop-lock-custom@3x.png b/Session/Meta/Images.xcassets/crop-lock-custom.imageset/crop-lock-custom@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..1a7fd66b31ffdcbcadf916beef89049430c6f64b GIT binary patch literal 1475 zcmb7EX;2af6h>1MjaDnMv|~*z^T0MOO^3YjTGPxd&VmAT91Neqk(k-5_}Lz0Dy_(SEzaB{eW3dswD+^y91bAJ15qK#yK~C zHvoWjOLsL~69CW*@rAhsC#%g2o;Yvpxvgz3?4T~m%sHg^s9IHIepDNTpnh|!UI1oP z>$3(a{`O;6sRnRApFpnqkoCSZWK>MGH}X9pNKhzgDWm6eOubLJ$g>s0KI@GDfPqC< zYzH2Sw_-0=F>3J*@wfw+6X2rGnzi9Tk~L7=?EWa7&2*S_*Pf0mS;H`J5X_bPr0+z| zzo&$I`~J2O7wV#I^2@VCbC7qZL5o zG+I3>izvnEB7!hWT6-Ul7fiXUnZI@F(4ZeYhoXKgsNSYO09^scD4pB?kotX=L1w+ra(d>Q}0}|s)1yg(XRC3 z+QkvEQwY@XRPuJzYJFN)XXvfqw(Zki2)9S8TYV;LCI;l)j_}bJ+VH}n*;7jXd^NxQ z0q=BU31irPU|il#vC1gUa2bCy+keLk#*vE01YzBo+VGt@*#{Z z^#M+*KP+{34IR#vFE=1e%V%CBGsEq6Q_U-;Y%9u>*d+vW;s!w^RT)ZqzE)YlCDIOQ z-LpM?1IfiUd_iD+%8M4u&Cv)fEusr<6RIE6$s%63+9o@0Oig3x^lV|`<;cn&P{5x4 z`(&46qk#+j=6~NqWfHMr+-}!!ZSvoGVS)43lO8==AjXd&F(7G> zL76!kOgFUjIIJw|U5H6!&Y`kv%g2vqvWcFn^f_b|T-4N5V51&8omG|dG0uRG9yGn* zV2HOCLKEX??|S-p!uHYx-NL8WcYiwuI}&GUC8TS&%nh~)KCJc10@gx+>bqN*pmQ=h zq(B3cdjyXr-ojno#EaHvff8gaXK|}_TxEsXwu!5)=iF8XOan8jK5CuXqgOL;SIs`Q zbde=WWne~%;7&7IoStwZ%@v+a580nT8Shtf7T*<|QNr-XtIS|?{wNuHbPIwD74<3h zL4ha5s(}lAgfMuw__=B$l(d|_2dCFvl3ol#+X|sK3=-q&WtNF&DE@AjAg^;lb1=n1 za3rJJvt#}hUGwFmw_X-PKmXUq2g7_RO;Je3(itnRORhm+y874GM_vYW1d%|}PiG}xrLSiI JjOmUc{{?zu%n|?q literal 0 HcmV?d00001 diff --git a/Session/Meta/Images.xcassets/crop-unlock-custom.imageset/Contents.json b/Session/Meta/Images.xcassets/crop-unlock-custom.imageset/Contents.json new file mode 100644 index 0000000000..bf240d3b5b --- /dev/null +++ b/Session/Meta/Images.xcassets/crop-unlock-custom.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "crop-unlock-custom.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "crop-unlock-custom@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "crop-unlock-custom@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Session/Meta/Images.xcassets/crop-unlock-custom.imageset/crop-unlock-custom.png b/Session/Meta/Images.xcassets/crop-unlock-custom.imageset/crop-unlock-custom.png new file mode 100644 index 0000000000000000000000000000000000000000..e62cf88ddde2e235eb44d3cd8c263695c8be1cb9 GIT binary patch literal 593 zcmV-X0|WK~#7F?U{{D z!!QtqUl9W^f|-Ca0cHYV0>T8a0c-#pkWNsTfOZ04f`$p`2E|t=igBANKX>9P{7FxZ zQ!CAreZI2`B=(!B)57W5=?HsD=ClfQ2Spro=xd|)2^7)Ah-#7%Z6qVw7zNjq7cw-j zM%Kv$?ZRmWK0eFmePAGzqq?_n^21@I>?zDpPNC~9X;XAONV zWMjl)a}>^*e`8IK&AH5par#EjdQQ{wTR6Q&_gdF;hmgZMUBEBvbNCSzL(0g#(?ihC zoNk>?A%w)#GN?@~;in8S#&2`1NEo>cu4x30QLj8=yGqFzA(rLm4ZOh@2q7^dv*5ZK zoxWWABawF6`80x7Q?x{sDXoL0w5|)5w(l zEEtgr_6eF3URqTRa`Zd|Ox3S8k`ZkrBSOUW+#Guf9UbNH f8M}A+koJzn8rFWp@N00000NkvXXu0mjfp2_*~ literal 0 HcmV?d00001 diff --git a/Session/Meta/Images.xcassets/crop-unlock-custom.imageset/crop-unlock-custom@2x.png b/Session/Meta/Images.xcassets/crop-unlock-custom.imageset/crop-unlock-custom@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..065d15c640026b1b893539f26adda0a15eacbafb GIT binary patch literal 1052 zcmeAS@N?(olHy`uVBq!ia0vp^DImIN3W zWVZ;%LtIW_4>m9*oX|*P<6pNJX+oq;s>m*7jTpbvx~KnE>fQ}5Jsny!J@)SQ ztMk7{F>xri2-NEIOmo}rw)NuFi47@^JyMH*%bG6GjNDLuq_#h6!jc;cU)@{G+A(=K z$9biInUO+=1&UZqTqN>1Zn(1p!-|av2T7qfA2K>#rViYpqy{zgSbhzJzd7r8eonh?&f(pc*wiKZ8=S-RcOSkwcd?J?gZgcP1t+Y! zwq9f}IXwL;>y&v4p1lfZCxj~MG2K(#TT>omomLm%t=YCl_WHeqrYQoaH)*e!-uJpG zZ~exD26a+*6WTs^DcreH-F4W!<#$PY;>`mWzMkk(@Nv~j2wBV@X!_v4YJe@D(`T7Y zE;dR3z6EBOEpf8Z(%@a4G55;R!n0}%^bGp?EA|-tn0_P3)l<^>c13oNbL`>o2j}cE z%IH8Kuc*|{i>k*IXBajaD7H^9)Cu>|4h0!J;j8G!9S3^^T3$wO^I`7U#r$oh<%9o~ z?Ku}0Rc}yF$&Yh>f7ppXWB!%s#oJ$0EqY)PB{E@-R_fHNNoq6g-Z@Wkbe=Ntv;bqF z(BTP+JKKXNEaACnpJDDgAyHl^durTjnvwI|d|_%8~W z_p5yukv{C*WBkh7&co@1_x+XK5V;<`IUK2JC-vcY+h?U(ON p|36E73pixGI9{Pez)9pId*oS*10u7!gMpcu!PC{xWt~$(69DFP!y*6x literal 0 HcmV?d00001 diff --git a/Session/Meta/Images.xcassets/crop-unlock-custom.imageset/crop-unlock-custom@3x.png b/Session/Meta/Images.xcassets/crop-unlock-custom.imageset/crop-unlock-custom@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..80ca2a525851931ad89745ec4ceab369a6ce3448 GIT binary patch literal 1563 zcmb7ES5OlO5DiTsh>Z}Cawjkr3HbcEW-|fZq9}FRN7*E}njo zdXaxD&(}2SM-qe&uXuPa@9Z#&tHWCFtATTmNGAv0sJu+F%smdlb{7IIw=B>s;8^bX zuKXb}Yb6@K*+@D$!x+Kza8m^-6BrCfQAsUvu=`O+?MXzSDdSTtiY>;Dm5ddW{jWxu z79#RhPKZ{gjDg7jn7K=udRg>xeja{RbMPokpv%tDD(Q{r-b0LIsjtKYG zj)1NcNM_~E+$1`4MB@V&J4-(ss;%zOc{_^x?yS2x+pFk-j_yCKUdFb2eS@l_1ER^d zq&$67-&~ZHL=tkE2i82dgS7X*`|YY6hKXC>JV??Vs6u+LZ1ec+zC`5 z25{p~PA|xZ!)x6Z!owFR6|NK>GH6e_pJGLAx|V=`FnsTg58V{_gE-(o*E@%QO%Ds$sw8e`fc476+DQ@OaUb!Fm3m z-*{m|Q@?JBxbkQ)&Ij62nuafalm1JvGoC>s=3*_B*M_XS!rQeuy6gpgHj zZD@>g%CWp#x~hDD&eC~22d+P{Z5*1g71BC`v%1)Mje;j+Al+!pl*Q$ZRn<&~CM+O1 zVsgBki;|Lph767_`Y&O!%}-B4!4rs8THoAHk+|ZC1Sq(a>qj&nhT~m_3n%zNc{=x^ zUC}Sk8*oHe2e3Fw1#x=g?P$2_f(zD_hrY8FQxKZwyr#$PY7W(`1{>P8vj-n4`b~3= z<;>QM+9_2?%kphXOCn~uq)v2kn6tYHvA+Fg6z)N8jf}hT04x7k%ssG#oz!#x1fwX>VeZ z=@kJk-BCwaQU*L2*Y{yHaP5=A_8e%$H>miXzArUMk$P>*a#Z}bTzJBdQ_2KG^vyLb z=1?*l!v6Nz#)z6^Zzx>zCXB!^ZqA!e^$5%~Mkq8>F-2sj(!*SmLNE=)zkG`bF}WI{ zUpkeOdJ~%C4HHEOW69o2$uk#W{N(|BXDaX+se3L&q1|Z>$8~!TpTcGlg2|5pr@Cb1 zvD2f#Q%w5mGrqfOH08p#zW(gUNY%{owZ`40`Av_5_=u7n2s+*WciRE}SsE>QAkTca_SvvypG zw>&Y%--Qc9p?xYQ6{K9WL`s;rODq@hkFFGNU-XZmALP=!HA8Tp`!b0jHzvVIg%{DN&PKlXa>`F5wjfL5 wWS: UIHostingController UIView { + let button = OWSButton() + button.setImage(image: image) + button.themeTintColor = .textPrimary + button.addTarget(self, action: selector, for: .touchUpInside) + + return button + } } // MARK: - diff --git a/SignalUtilitiesKit/Shared Views/ApprovalRailCellView.swift b/SignalUtilitiesKit/Shared Views/ApprovalRailCellView.swift index 30fd976c21..5855c55487 100644 --- a/SignalUtilitiesKit/Shared Views/ApprovalRailCellView.swift +++ b/SignalUtilitiesKit/Shared Views/ApprovalRailCellView.swift @@ -1,6 +1,7 @@ // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. import UIKit +import Lucide import SessionUIKit import SessionUtilitiesKit @@ -27,7 +28,7 @@ public class ApprovalRailCellView: GalleryRailCellView { strongSelf.approvalRailCellDelegate?.approvalRailCellView(strongSelf, didRemoveItem: attachmentItem) } - button.setImage(UIImage(named: "x-24")?.withRenderingMode(.alwaysTemplate), for: .normal) + button.setImage(Lucide.image(icon: .x, size: 24)?.withRenderingMode(.alwaysTemplate), for: .normal) button.themeTintColor = .white button.themeShadowColor = .black button.layer.shadowRadius = 2 diff --git a/SignalUtilitiesKit/Shared Views/OWSButton.swift b/SignalUtilitiesKit/Shared Views/OWSButton.swift index c06726e35c..93c539f006 100644 --- a/SignalUtilitiesKit/Shared Views/OWSButton.swift +++ b/SignalUtilitiesKit/Shared Views/OWSButton.swift @@ -32,6 +32,17 @@ public class OWSButton: UIButton { setImage(imageName: imageName) self.themeTintColor = tintColor } + + public init(image: UIImage?, tintColor: ThemeValue?, block: @escaping () -> Void = { }) { + super.init(frame: .zero) + + self.block = block + addTarget(self, action: #selector(didTap), for: .touchUpInside) + + setImage(image: image) + + self.themeTintColor = tintColor + } public func setImage(imageName: String) { setImage( @@ -40,6 +51,14 @@ public class OWSButton: UIButton { for: .normal ) } + + public func setImage(image: UIImage?) { + setImage( + image? + .withRenderingMode(.alwaysTemplate), + for: .normal + ) + } public required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") From bc8deed65da0c073fe1a6c9e8efbf293c89fc3e5 Mon Sep 17 00:00:00 2001 From: mikoldin Date: Mon, 8 Sep 2025 16:25:47 +0800 Subject: [PATCH 5/8] Updated images to use Lucide set Added new custom icons for calls, conversation and image edit --- Session.xcodeproj/project.pbxproj | 15 +++++++ Session/Calls/CallVC.swift | 39 +++++++++++------- .../Views & Modals/IncomingCallBanner.swift | 4 +- .../SwiftUI/QuoteView_SwiftUI.swift | 16 ++++--- .../Views & Modals/InfoBanner.swift | 10 ++--- .../Database/Convenience/Interaction+UI.swift | 10 +++-- .../StartConversationScreen.swift | 22 ++++++---- .../Contents.json | 12 ++++++ .../phone-fill-answer-custom.pdf | Bin 0 -> 4579 bytes .../phone-fill-custom.imageset/Contents.json | 12 ++++++ .../phone-fill-custom.pdf | Bin 0 -> 11396 bytes .../users-group-custom.imageset/Contents.json | 12 ++++++ .../users-group-custom.pdf | Bin 0 -> 4882 bytes .../crop-lock-custom.imageset/Contents.json | 15 +------ .../crop-lock-custom.pdf | Bin 0 -> 4669 bytes .../crop-lock-custom.png | Bin 621 -> 0 bytes .../crop-lock-custom@2x.png | Bin 1021 -> 0 bytes .../crop-lock-custom@3x.png | Bin 1475 -> 0 bytes .../crop-unlock-custom.imageset/Contents.json | 15 +------ .../crop-unlock-custom.pdf | Bin 0 -> 4686 bytes .../crop-unlock-custom.png | Bin 593 -> 0 bytes .../crop-unlock-custom@2x.png | Bin 1052 -> 0 bytes .../crop-unlock-custom@3x.png | Bin 1563 -> 0 bytes Session/Settings/SettingsViewModel.swift | 4 +- Session/Shared/SessionCarouselView.swift | 7 +++- .../SAEScreenLockViewController.swift | 9 +++- .../Modals & Toast/ConfirmationModal.swift | 2 +- .../Components/TopBannerController.swift | 3 +- 28 files changed, 130 insertions(+), 77 deletions(-) create mode 100644 Session/Meta/Images.xcassets/Session/phone-fill-answer-custom.imageset/Contents.json create mode 100644 Session/Meta/Images.xcassets/Session/phone-fill-answer-custom.imageset/phone-fill-answer-custom.pdf create mode 100644 Session/Meta/Images.xcassets/Session/phone-fill-custom.imageset/Contents.json create mode 100644 Session/Meta/Images.xcassets/Session/phone-fill-custom.imageset/phone-fill-custom.pdf create mode 100644 Session/Meta/Images.xcassets/Session/users-group-custom.imageset/Contents.json create mode 100644 Session/Meta/Images.xcassets/Session/users-group-custom.imageset/users-group-custom.pdf create mode 100644 Session/Meta/Images.xcassets/crop-lock-custom.imageset/crop-lock-custom.pdf delete mode 100644 Session/Meta/Images.xcassets/crop-lock-custom.imageset/crop-lock-custom.png delete mode 100644 Session/Meta/Images.xcassets/crop-lock-custom.imageset/crop-lock-custom@2x.png delete mode 100644 Session/Meta/Images.xcassets/crop-lock-custom.imageset/crop-lock-custom@3x.png create mode 100644 Session/Meta/Images.xcassets/crop-unlock-custom.imageset/crop-unlock-custom.pdf delete mode 100644 Session/Meta/Images.xcassets/crop-unlock-custom.imageset/crop-unlock-custom.png delete mode 100644 Session/Meta/Images.xcassets/crop-unlock-custom.imageset/crop-unlock-custom@2x.png delete mode 100644 Session/Meta/Images.xcassets/crop-unlock-custom.imageset/crop-unlock-custom@3x.png diff --git a/Session.xcodeproj/project.pbxproj b/Session.xcodeproj/project.pbxproj index d1ae3e9755..faccb3804e 100644 --- a/Session.xcodeproj/project.pbxproj +++ b/Session.xcodeproj/project.pbxproj @@ -1160,6 +1160,8 @@ FDFF9FDF2A787F57005E0628 /* JSONEncoder+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDFF9FDE2A787F57005E0628 /* JSONEncoder+Utilities.swift */; }; FE5809902E6EACB0000296AB /* Lucide in Frameworks */ = {isa = PBXBuildFile; productRef = FE58098F2E6EACB0000296AB /* Lucide */; }; FE5809922E6EADFA000296AB /* Lucide in Frameworks */ = {isa = PBXBuildFile; productRef = FE5809912E6EADFA000296AB /* Lucide */; }; + FEACA5AF2E6FB03300AA20F3 /* Lucide in Frameworks */ = {isa = PBXBuildFile; productRef = FEACA5AE2E6FB03300AA20F3 /* Lucide */; }; + FEACA5B12E6FB10E00AA20F3 /* Lucide in Frameworks */ = {isa = PBXBuildFile; productRef = FEACA5B02E6FB10E00AA20F3 /* Lucide */; }; FED288F32E4C28CF00C31171 /* AppReviewPromptDialog.swift in Sources */ = {isa = PBXBuildFile; fileRef = FED288F22E4C28CF00C31171 /* AppReviewPromptDialog.swift */; }; FED288F82E4C3BE100C31171 /* AppReviewPromptModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FED288F72E4C3BE100C31171 /* AppReviewPromptModel.swift */; }; /* End PBXBuildFile section */ @@ -2448,6 +2450,7 @@ B8D64FC725BA78520029CFC0 /* SessionMessagingKit.framework in Frameworks */, C3D90A5C25773A25002C9DF5 /* SessionUtilitiesKit.framework in Frameworks */, C3402FE52559036600EA6424 /* SessionUIKit.framework in Frameworks */, + FEACA5AF2E6FB03300AA20F3 /* Lucide in Frameworks */, B8D64FCB25BA78A90029CFC0 /* SignalUtilitiesKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -2456,6 +2459,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + FEACA5B12E6FB10E00AA20F3 /* Lucide in Frameworks */, B8D64FBB25BA78310029CFC0 /* SessionMessagingKit.framework in Frameworks */, FD8A5B182DBF47E9004C689B /* SessionUIKit.framework in Frameworks */, B8D64FBD25BA78310029CFC0 /* SessionSnodeKit.framework in Frameworks */, @@ -5222,6 +5226,7 @@ name = SessionShareExtension; packageProductDependencies = ( FD860CC82D6ED2ED00BBE29C /* DifferenceKit */, + FEACA5AE2E6FB03300AA20F3 /* Lucide */, ); productName = SignalShareExtension; productReference = 453518681FC635DD00210559 /* SessionShareExtension.appex */; @@ -10527,6 +10532,16 @@ package = FD756BEE2D06686500BD7199 /* XCRemoteSwiftPackageReference "session-lucide" */; productName = Lucide; }; + FEACA5AE2E6FB03300AA20F3 /* Lucide */ = { + isa = XCSwiftPackageProductDependency; + package = FD756BEE2D06686500BD7199 /* XCRemoteSwiftPackageReference "session-lucide" */; + productName = Lucide; + }; + FEACA5B02E6FB10E00AA20F3 /* Lucide */ = { + isa = XCSwiftPackageProductDependency; + package = FD756BEE2D06686500BD7199 /* XCRemoteSwiftPackageReference "session-lucide" */; + productName = Lucide; + }; /* End XCSwiftPackageProductDependency section */ }; rootObject = D221A080169C9E5E00537ABF /* Project object */; diff --git a/Session/Calls/CallVC.swift b/Session/Calls/CallVC.swift index 9463da7d65..7bc62a37d2 100644 --- a/Session/Calls/CallVC.swift +++ b/Session/Calls/CallVC.swift @@ -96,10 +96,7 @@ final class CallVC: UIViewController, VideoPreviewDelegate, AVRoutePickerViewDel result.addSubview(floatingRemoteVideoView) floatingRemoteVideoView.pin(to: result) - let swappingVideoIcon: UIImageView = UIImageView( - image: UIImage(systemName: "arrow.2.squarepath")? - .withRenderingMode(.alwaysTemplate) - ) + let swappingVideoIcon = LucideIconView(icon: .repeat2, size: 12) swappingVideoIcon.themeTintColor = .textPrimary swappingVideoIcon.set(.width, to: 16) swappingVideoIcon.set(.height, to: 12) @@ -143,7 +140,7 @@ final class CallVC: UIViewController, VideoPreviewDelegate, AVRoutePickerViewDel private lazy var minimizeButton: UIButton = { let result = UIButton(type: .custom) result.setImage( - UIImage(named: "Minimize")? + Lucide.image(icon: .minimize2, size: 24)? .withRenderingMode(.alwaysTemplate), for: .normal ) @@ -162,7 +159,7 @@ final class CallVC: UIViewController, VideoPreviewDelegate, AVRoutePickerViewDel result.accessibilityIdentifier = "Answer call" result.accessibilityLabel = "Answer call" result.setImage( - UIImage(named: "AnswerCall")? + UIImage(named: "phone-fill-answer-custom")? .withRenderingMode(.alwaysTemplate), for: .normal ) @@ -182,7 +179,7 @@ final class CallVC: UIViewController, VideoPreviewDelegate, AVRoutePickerViewDel let result = UIButton(type: .custom) result.accessibilityLabel = "End call button" result.setImage( - UIImage(named: "EndCall")? + UIImage(named: "phone-fill-custom")? .withRenderingMode(.alwaysTemplate), for: .normal ) @@ -208,7 +205,7 @@ final class CallVC: UIViewController, VideoPreviewDelegate, AVRoutePickerViewDel let result = UIButton(type: .custom) result.isEnabled = call.isVideoEnabled result.setImage( - UIImage(named: "SwitchCamera")? + Lucide.image(icon: .switchCamera, size: 24)? .withRenderingMode(.alwaysTemplate), for: .normal ) @@ -225,7 +222,7 @@ final class CallVC: UIViewController, VideoPreviewDelegate, AVRoutePickerViewDel private lazy var switchAudioButton: UIButton = { let result = UIButton(type: .custom) result.setImage( - UIImage(named: "AudioOff")? + Lucide.image(icon: .micOff, size: 24)? .withRenderingMode(.alwaysTemplate), for: .normal ) @@ -248,7 +245,7 @@ final class CallVC: UIViewController, VideoPreviewDelegate, AVRoutePickerViewDel private lazy var videoButton: UIButton = { let result = UIButton(type: .custom) result.setImage( - UIImage(named: "VideoCall")? + Lucide.image(icon: .video, size: 24)? .withRenderingMode(.alwaysTemplate), for: .normal ) @@ -276,7 +273,7 @@ final class CallVC: UIViewController, VideoPreviewDelegate, AVRoutePickerViewDel private lazy var routePickerButton: UIButton = { let result = UIButton(type: .custom) result.setImage( - UIImage(named: "Speaker")? + Lucide.image(icon: .volume2, size: 24)? .withRenderingMode(.alwaysTemplate), for: .normal ) @@ -828,33 +825,43 @@ final class CallVC: UIViewController, VideoPreviewDelegate, AVRoutePickerViewDel switch currentOutput.portType { case .builtInSpeaker: - let image = UIImage(named: "Speaker")?.withRenderingMode(.alwaysTemplate) + let image = Lucide.image(icon: .volume2, size: 24)? + .withRenderingMode(.alwaysTemplate) + routePickerButton.setImage(image, for: .normal) routePickerButton.themeTintColor = .backgroundSecondary routePickerButton.themeBackgroundColor = .textPrimary case .headphones: - let image = UIImage(named: "Headsets")?.withRenderingMode(.alwaysTemplate) + let image = UIImage(named: "Headsets")? + .withRenderingMode(.alwaysTemplate) + routePickerButton.setImage(image, for: .normal) routePickerButton.themeTintColor = .backgroundSecondary routePickerButton.themeBackgroundColor = .textPrimary case .bluetoothLE: fallthrough case .bluetoothA2DP: - let image = UIImage(named: "Bluetooth")?.withRenderingMode(.alwaysTemplate) + let image = UIImage(named: "Bluetooth")? + .withRenderingMode(.alwaysTemplate) + routePickerButton.setImage(image, for: .normal) routePickerButton.themeTintColor = .backgroundSecondary routePickerButton.themeBackgroundColor = .textPrimary case .bluetoothHFP: - let image = UIImage(named: "Airpods")?.withRenderingMode(.alwaysTemplate) + let image = UIImage(named: "Airpods")? + .withRenderingMode(.alwaysTemplate) + routePickerButton.setImage(image, for: .normal) routePickerButton.themeTintColor = .backgroundSecondary routePickerButton.themeBackgroundColor = .textPrimary case .builtInReceiver: fallthrough default: - let image = UIImage(named: "Speaker")?.withRenderingMode(.alwaysTemplate) + let image = Lucide.image(icon: .volume2, size: 24)? + .withRenderingMode(.alwaysTemplate) + routePickerButton.setImage(image, for: .normal) routePickerButton.themeTintColor = .textPrimary routePickerButton.themeBackgroundColor = .backgroundSecondary diff --git a/Session/Calls/Views & Modals/IncomingCallBanner.swift b/Session/Calls/Views & Modals/IncomingCallBanner.swift index e40a97724d..6e69f91b84 100644 --- a/Session/Calls/Views & Modals/IncomingCallBanner.swift +++ b/Session/Calls/Views & Modals/IncomingCallBanner.swift @@ -41,7 +41,7 @@ final class IncomingCallBanner: UIView, UIGestureRecognizerDelegate { .withConfiguration( UIButton.Configuration .plain() - .withImage(UIImage(named: "AnswerCall")?.withRenderingMode(.alwaysTemplate)) + .withImage(UIImage(named: "phone-fill-answer-custom")?.withRenderingMode(.alwaysTemplate)) .withContentInsets(NSDirectionalEdgeInsets(top: 6, leading: 6, bottom: 6, trailing: 6)) ) .withConfigurationUpdateHandler { button in @@ -65,7 +65,7 @@ final class IncomingCallBanner: UIView, UIGestureRecognizerDelegate { .withConfiguration( UIButton.Configuration .plain() - .withImage(UIImage(named: "EndCall")?.withRenderingMode(.alwaysTemplate)) + .withImage(UIImage(named: "phone-fill-custom")?.withRenderingMode(.alwaysTemplate)) .withContentInsets(NSDirectionalEdgeInsets(top: 13, leading: 9, bottom: 13, trailing: 9)) ) .withConfigurationUpdateHandler { button in diff --git a/Session/Conversations/Message Cells/Content Views/SwiftUI/QuoteView_SwiftUI.swift b/Session/Conversations/Message Cells/Content Views/SwiftUI/QuoteView_SwiftUI.swift index 2fe06552a8..9e100b4238 100644 --- a/Session/Conversations/Message Cells/Content Views/SwiftUI/QuoteView_SwiftUI.swift +++ b/Session/Conversations/Message Cells/Content Views/SwiftUI/QuoteView_SwiftUI.swift @@ -181,15 +181,13 @@ struct QuoteView_SwiftUI: View { onCancel?() }, label: { - if let image = UIImage(named: "X")?.withRenderingMode(.alwaysTemplate) { - Image(uiImage: image) - .foregroundColor(themeColor: .textPrimary) - .frame( - width: Self.cancelButtonSize, - height: Self.cancelButtonSize, - alignment: .center - ) - } + LucideIcon(.x, size: Self.cancelButtonSize) + .foregroundColor(themeColor: .textPrimary) + .frame( + width: Self.cancelButtonSize, + height: Self.cancelButtonSize, + alignment: .center + ) } ) } diff --git a/Session/Conversations/Views & Modals/InfoBanner.swift b/Session/Conversations/Views & Modals/InfoBanner.swift index a76ec30f60..610d83099e 100644 --- a/Session/Conversations/Views & Modals/InfoBanner.swift +++ b/Session/Conversations/Views & Modals/InfoBanner.swift @@ -3,6 +3,7 @@ // stringlint:disable import UIKit +import Lucide import SessionUIKit final class InfoBanner: UIView { @@ -14,12 +15,11 @@ final class InfoBanner: UIView { var image: UIImage? { switch self { case .none: return nil - case .link: return UIImage(systemName: "arrow.up.right.square")?.withRenderingMode(.alwaysTemplate) + case .link: return Lucide.image(icon: .squareArrowUpRight, size: 12)? + .withRenderingMode(.alwaysTemplate) case .close: - return UIImage( - systemName: "xmark", - withConfiguration: UIImage.SymbolConfiguration(pointSize: 12, weight: .bold) - )?.withRenderingMode(.alwaysTemplate) + return Lucide.image(icon: .x, size: 12)? + .withRenderingMode(.alwaysTemplate) } } } diff --git a/Session/Database/Convenience/Interaction+UI.swift b/Session/Database/Convenience/Interaction+UI.swift index cb79dcfb24..58db6e55d6 100644 --- a/Session/Database/Convenience/Interaction+UI.swift +++ b/Session/Database/Convenience/Interaction+UI.swift @@ -1,6 +1,7 @@ // Copyright © 2025 Rangeproof Pty Ltd. All rights reserved. import UIKit +import Lucide import SessionUIKit import SessionMessagingKit @@ -34,7 +35,8 @@ public extension Interaction.State { case (.sent, false, _): return ( - UIImage(systemName: "checkmark.circle"), + Lucide.image(icon: .circleCheck, size: 12)? + .withRenderingMode(.alwaysTemplate), "disappearingMessagesSent".localized(), .messageBubble_deliveryStatus ) @@ -48,14 +50,16 @@ public extension Interaction.State { case (.failed, _, _): return ( - UIImage(systemName: "exclamationmark.triangle"), + Lucide.image(icon: .triangleAlert, size: 12)? + .withRenderingMode(.alwaysTemplate), "messageStatusFailedToSend".localized(), .danger ) case (.failedToSync, _, _): return ( - UIImage(systemName: "exclamationmark.triangle"), + Lucide.image(icon: .triangleAlert, size: 12)? + .withRenderingMode(.alwaysTemplate), "messageStatusFailedToSync".localized(), .warning ) diff --git a/Session/Home/New Conversation/StartConversationScreen.swift b/Session/Home/New Conversation/StartConversationScreen.swift index 5937053c4e..96e923aa64 100644 --- a/Session/Home/New Conversation/StartConversationScreen.swift +++ b/Session/Home/New Conversation/StartConversationScreen.swift @@ -1,6 +1,7 @@ // Copyright © 2024 Rangeproof Pty Ltd. All rights reserved. import SwiftUI +import Lucide import SessionUIKit import SignalUtilitiesKit import SessionUtilitiesKit @@ -28,7 +29,7 @@ struct StartConversationScreen: View { .putNumber(1) .localized() NewConversationCell( - image: "Message", // stringlint:ignore + image: Lucide.image(icon: .messageSquare, size: 24), title: title ) { let viewController: SessionHostingViewController = SessionHostingViewController( @@ -50,7 +51,7 @@ struct StartConversationScreen: View { .padding(.trailing, -Values.largeSpacing) NewConversationCell( - image: "Group", + image: UIImage(named: "users-group-custom"), title: "groupCreate".localized() ) { let viewController = NewClosedGroupVC(using: dependencies) @@ -68,7 +69,7 @@ struct StartConversationScreen: View { .padding(.trailing, -Values.largeSpacing) NewConversationCell( - image: "Globe", // stringlint:ignore + image: Lucide.image(icon: .globe, size: 24), title: "communityJoin".localized() ) { let viewController = JoinOpenGroupVC(using: dependencies) @@ -86,7 +87,7 @@ struct StartConversationScreen: View { .padding(.trailing, -Values.largeSpacing) NewConversationCell( - image: "icon_invite", // stringlint:ignore + image: Lucide.image(icon: .userRoundPlus, size: 24), title: "sessionInviteAFriend".localized() ) { let viewController: SessionHostingViewController = SessionHostingViewController( @@ -130,7 +131,7 @@ struct StartConversationScreen: View { } fileprivate struct NewConversationCell: View { - let image: String + let image: UIImage? let title: String let action: () -> () @@ -143,10 +144,13 @@ fileprivate struct NewConversationCell: View { spacing: Values.smallSpacing ) { ZStack(alignment: .center) { - Image(image) - .renderingMode(.template) - .foregroundColor(themeColor: .textPrimary) - .frame(width: 25, height: 24, alignment: .bottom) + if let icon = image { + Image(uiImage: icon) + .resizable() + .renderingMode(.template) + .foregroundColor(themeColor: .textPrimary) + .frame(width: 25, height: 24, alignment: .bottom) + } } .frame(width: 38, height: 38, alignment: .leading) diff --git a/Session/Meta/Images.xcassets/Session/phone-fill-answer-custom.imageset/Contents.json b/Session/Meta/Images.xcassets/Session/phone-fill-answer-custom.imageset/Contents.json new file mode 100644 index 0000000000..f6d5fe83a1 --- /dev/null +++ b/Session/Meta/Images.xcassets/Session/phone-fill-answer-custom.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "phone-fill-answer-custom.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Session/Meta/Images.xcassets/Session/phone-fill-answer-custom.imageset/phone-fill-answer-custom.pdf b/Session/Meta/Images.xcassets/Session/phone-fill-answer-custom.imageset/phone-fill-answer-custom.pdf new file mode 100644 index 0000000000000000000000000000000000000000..36cc3f4f051c54d73595856e3be2fd5442941004 GIT binary patch literal 4579 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

q*yN4ZI}LZpgLFRA$P#&x7WU4W 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 literal 0 HcmV?d00001 diff --git a/Session/Meta/Images.xcassets/Session/users-group-custom.imageset/Contents.json b/Session/Meta/Images.xcassets/Session/users-group-custom.imageset/Contents.json new file mode 100644 index 0000000000..e3cee03aa8 --- /dev/null +++ b/Session/Meta/Images.xcassets/Session/users-group-custom.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "users-group-custom.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Session/Meta/Images.xcassets/Session/users-group-custom.imageset/users-group-custom.pdf b/Session/Meta/Images.xcassets/Session/users-group-custom.imageset/users-group-custom.pdf new file mode 100644 index 0000000000000000000000000000000000000000..a9804b71e4eceb54c1e0b82c816c6d21548f63fa GIT binary patch literal 4882 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 literal 0 HcmV?d00001 diff --git a/Session/Meta/Images.xcassets/crop-lock-custom.imageset/Contents.json b/Session/Meta/Images.xcassets/crop-lock-custom.imageset/Contents.json index 0296e80ea0..23dc2e687b 100644 --- a/Session/Meta/Images.xcassets/crop-lock-custom.imageset/Contents.json +++ b/Session/Meta/Images.xcassets/crop-lock-custom.imageset/Contents.json @@ -1,19 +1,8 @@ { "images" : [ { - "filename" : "crop-lock-custom.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "crop-lock-custom@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "crop-lock-custom@3x.png", - "idiom" : "universal", - "scale" : "3x" + "filename" : "crop-lock-custom.pdf", + "idiom" : "universal" } ], "info" : { diff --git a/Session/Meta/Images.xcassets/crop-lock-custom.imageset/crop-lock-custom.pdf b/Session/Meta/Images.xcassets/crop-lock-custom.imageset/crop-lock-custom.pdf new file mode 100644 index 0000000000000000000000000000000000000000..0d53a9cd84b0a4aae76ce8ff89a23061a48ee6c7 GIT binary patch literal 4669 zcmai2c|6qJ_a{c0$dW|JNU|G)k)dSI-dMB77=y9QFf*1cAtH&2F!nu5N@U-Xv4-qr zk9bH#vWxs?+McK9`MzGi`^U^@-uK-1J@=fMGw*W+;A$G;5Q+0Zfgth#LO_xrterCu z1iEkm1Xe@i-CYsa)v!ooG{F@GBH%nxAVozW3S&<(0!sa14aZ^aJ&`CJNJsXq$i$$b)y*lgHZYpLSq<`#!C*V*BH=s{Sc|00^e1yFX z>%AEzPEBpz)DWf@PgNQwo^dnCHH$Td3UP#)wb7czAecp6jn+zuPMzDGU}n$EVlYkz z02o`{WB|UBle@zuQcS~3_^3DZ_-gUwi^AH#fR8C-^J!l*52)^AXw)Qex%4erwl-IM z)$G}LwrG!ZgupziIMGw@00AWLkTt9~M`>;3cw!sl*JA|ZX0A9N7?vQ4`sT4=jaQItoY|2H&esp;RP z8w_IarD+YKb`7F&r(161+73}-2A+B8+z2=V0^C+&AEv6fc>zwf8ML3l%}ou>I3^P$ zodGBdiJSsfQDZ`=B^h#T8R}?_rg(_KAo{}wAdwt8v?|?wPJ0>%-_>?5i$eg_2XF>9 zrXzeu%BV-_PAIj&Va9+VE72)m)3zYCsU&*LnYJ_vae($_f33I_`tHx zwksNTv#*heNRf2ar9F2#_Erb!p`9~CkJw41?&6r^VUILlv?$70iD0 zW4AvwZz3+249IcoGdhOhUjp9C$w4HTyqUd$-qdgJaghQVV?U4jaMdv>0>RDmQ#z}H zt32B`_V9ZQ%E7iu?q_IOeL~Aa&!{kFM!82yY7qHESfg%BG{f!Ac!-wV9agH-_1E-Q zJ@bH|6`k|fS!(prg1dwyLY$1suBPdk8_8^L|8m1bb7*(Ps}pQ_c2^edSAt=-vRHijL3WVn4r55(=T*FeJHy$-|C~R zGvkJo=iRVe&c5L?H4Exbf)-#mZF8*=QIXIV|bE^b3?gY+?B zNbqDoyF7SSqRYm|VVZ`~jAYDjhOBReL?xdZNU}(3NJ1wahJw-h&IL}@E&|SRPM%JB zPDbU{<$zIv(UWC1y>Sbt*X?~d>ys68vomM%`1=a_7lso1p#9dF$=PH1Up4RLw+%)P zi1sb^C-=X7V^jD-`Ng$^VCt7a==-+rjTvoI^_dS4Rnx~v>?99<6aI=m`E1|p@K!eD z`5D5D^GxkIv*VAnVmkO@#~wW^NJZa7-&zot9`2gdwe@N*>fuH%J4whC%ktXY=RAE^ zSK}hGS*67;LOohNvPD!Upi`)`KK^37&6A~~m?zFfVNc?U_MhO3#)=L~A?4Gf#>3;* zYUZ=goz}A6s296+yY5tkyRD2Ee2O3a^lY*8tKEt%xD@*=-M!cQwnsjJ!>*sG+@&&S za`|p{-i$+=SKB@PO?|sOY5hQX>6F-%EAscivKC!7R?mF~)!*KlG5qU{XKrn4)oIVT znuRKl@xqC;n#Jn1ahHj7KcdfB-;^&tf1&>p{^I(@zXxaMX7A~nS?6E>rQWwbuI{Q& zg5RahzKw{jf~~|adN$~O(3hY*9o>Z6 z@nzz-5_Z88mFv?|A*d#lcrfTbPZjvH!F>a`Z*OsDNoPp>Rk1*JSDre)D#6fGrRQet z+iT%Hy;;4}Ct5|%iq7PSss!YB1Zg3sC207KjU)tr&p z&$F#;{@S{)V3{$JTEnS@aY?D82@dh`3Fq{@wcn*H3ILgh9F#a8OIftY%wEPB*@=xv zaCQ*7i`w_@pNRLAwS-s_1Mp84My*}ai`UGzW_;Iumv^5s%5zmrmfao!nNjje(WKRYB2g>~s1>Y9jAsG0Eg3rMp{6T&)$uSN4K^eF%o z{Jh0SJ>B2F^}qIQ?(fZZw{34AhGvEEMop1Ok?JrYy;CS>>U7WbZ28e9=RZQf^AU{L+| z%Rb*^<~P!EI9IgOX<@l93;9zY>P6la&N-7l_9KUpiEU{^p+oC??RzCpP3tQ%Hak70 zJr*LSj!$?V^Yj#i>a!1#Hez-ojQa902eTVSE;QMhg$B7LQ!;Ymu>JS*#Pq{Gv?&Yn zofpPFN4^Bd=?y;GbI8B$wq~rO5?KZ0694_In zL~b_K934nSr^cR~0Y`g1Svb|e=COd;`m#LPNu5x9ZM7O#(3U;lWRmds)7zA%skN`` zCUK;18f$vB$$BqF_TLP;yc_fHoHku_Ya4S5i2N$QJFyF%T&=M9cBAweq>tL>jnrd z)zw3d30Wf}iG?F0;C3-MiHe~84G=}&$4^nQKNaCGJuCBDetwsazhLNZ*b)TRQdLz! z;8FG*a{7fH$!5keq^tVhJ1H9QGn0YwIcZ z=F_K-T$;DsK918x@+`16)Xw(c?g+SuyJ^R~@@Sw9T+ROM)j)Tr0P^M~6bSmPGo{&; z`jJkj>kc5tpe$yNF=EHat&Nl0`K(dyOa)QxQ+d8hT(ZLgh~B&`Xt2;Wq461%mz7w5 z3?VJ4ThSSH*a>2_N;LTjsJq2kIS9DwB|Y7cY0d%lJ7%<`Tb^No>3&>YCodloKHv3< zFSTmXjv=@#@sYM@)U(G?u}e)6soYHa8{LhP<{-Jm=oMe)XBSjN+iq^@!gmt6@6Rhl z2Kn=(PJ3@}h}VVj+PHNgLPM8Tl;5XU<{p?su=4lXx?qM2^()EIX&J*tChd{9h}^5M zTk6VU1XK?P3+Tt(T$alUj+mGhE!HV>6oKk`}?%TyworbO{mG^BlK@x zaw8HFgCty{$3=~Ko>H-N>RX;c~9h8D(X#!)n$cX91(bDP`iTXKb)=0v`gWyL)M0XCO z3BL-BRyz9R*mzNWhe&mq2wPERr=}?{Tv)WCXf+l)acE8+D3D)Ga*flL+f5F*e7cpB zUBM3E=Klg^uqgVCzi&iGsWx`WRTaG>ALUcR!lKJi$5ypV5e3ZCB(E7b`jsE zZxe6hSlOb>!H(703UnO^D3cb-e(eu~q8GwpmEAn;8j| zDmH?{=r&^{=a1?e8@pb~RbL8=I~O`Lrz;G%b`28*=ZFf?1Dq+-Iggxe0F^CIY9MjwH&;tWAXzN*2MExEfsz}n9_ z`o>=8sc_hGMiiQM2+fKV)MEwxRK40Wf&wO|td(M;9UZzN5;-LFSg2fXIgmK0jtX~A zYHe$Fx~&x7vworX{sluN$MpXwBb1-%k0x3UCilBOz<#5Y`k;)#UhW%YkffF~pWr26wx z!4!@1M&aN%lmm*qJH=1R{4bZZFb-G{0d$3OS>A#Vee1VN;LKSD@(1<698(om2C<8KT?uFc|kV%|78dJFP}6_iu@<^r=2uRhMdViF&T)|fB0k|uz#F`fJ2~NQ8*yw z%ciA9&Yh5~j1w!(MXM z*N`pGE2EE6of%=fkMt#O%7l(AfL^}*E`6hT@?O|E^A0_5gMLN5QMYp9tW&h-Ok%Bb z2*r0vf_iv88ch&@6x*S&fIM!f&wPGaTWNlA)&viZy3a_H7~P^sU+V=q664D}(BJGj(HLfF1E;lKOVu$MoZ zqQiVQhMv2%&X+3uRF(iXibUuD8=3&vC{Sj9F`t}qArvP{e!YMUgu^cye|weK5ki_2 z3NJKzA)3)jG@})5X7WAjR?eV{97XRV6f+Qk(@Ik;M!QVyYm_=ozH)0Vv2= z9OUlAuDdK zs{mI9t^wnXY@%ZS~*yKlR4>LeZyu z_RJ5vb@%(81_39Ihs~=xSF7bsvyXQcNxgQYR>@DHD?m~A$fIqY&K(zb9;?!Pr7LUW zD0w9~N<-Cki-Km02bba`r;a58O6W{~>ppp<^Hx_kt1(&ZjAm0^-f{ZPcWa4nJ9Ra~ z8#{`BWF48ak)d%8Lwv7U*qH!>rv*&&d(GS;);g9MO4a7JiPps^8vpM6&gby0L0Q>k zax5?$^D;IQd6FF6y4%D(XeDo z@L~qAM=nkE|JcBreE8FH-r)KJmh-B+dTVlCO@F^lP5zX=c#H3m9=^>}xPGQR zR%A?M-7naHOkXl(inu`bN!6#} z#|uyYy0|Rad$PCJb&caK0pj{oRIa~Reg48`rx-WO=y~rqZYsPj`!7pm(dx9U>B)`L zd^@kbJ!{0W?I=g?QIEto-*R(5@9umrF*EzeuBPLC(IN^7KQ>)HE|$3UV$u2FtRt)r z-{bvHcx+th*ihx8C8m(T72i9}T5E#9hxgU*;-vCl>~QU#U}ydKsanJI80$Y*bJ-<7 zX_{8-d|kNb*ny0f^WZ^&6e@7$l(JuIYC9*cys(c&UZJa?bISxxmq4u}OYSfk9ye+P cWu1ooQ%u*p-1fEe2j*4=Pgg&ebxsLQ0JRpu>i_@% diff --git a/Session/Meta/Images.xcassets/crop-lock-custom.imageset/crop-lock-custom@3x.png b/Session/Meta/Images.xcassets/crop-lock-custom.imageset/crop-lock-custom@3x.png deleted file mode 100644 index 1a7fd66b31ffdcbcadf916beef89049430c6f64b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1475 zcmb7EX;2af6h>1MjaDnMv|~*z^T0MOO^3YjTGPxd&VmAT91Neqk(k-5_}Lz0Dy_(SEzaB{eW3dswD+^y91bAJ15qK#yK~C zHvoWjOLsL~69CW*@rAhsC#%g2o;Yvpxvgz3?4T~m%sHg^s9IHIepDNTpnh|!UI1oP z>$3(a{`O;6sRnRApFpnqkoCSZWK>MGH}X9pNKhzgDWm6eOubLJ$g>s0KI@GDfPqC< zYzH2Sw_-0=F>3J*@wfw+6X2rGnzi9Tk~L7=?EWa7&2*S_*Pf0mS;H`J5X_bPr0+z| zzo&$I`~J2O7wV#I^2@VCbC7qZL5o zG+I3>izvnEB7!hWT6-Ul7fiXUnZI@F(4ZeYhoXKgsNSYO09^scD4pB?kotX=L1w+ra(d>Q}0}|s)1yg(XRC3 z+QkvEQwY@XRPuJzYJFN)XXvfqw(Zki2)9S8TYV;LCI;l)j_}bJ+VH}n*;7jXd^NxQ z0q=BU31irPU|il#vC1gUa2bCy+keLk#*vE01YzBo+VGt@*#{Z z^#M+*KP+{34IR#vFE=1e%V%CBGsEq6Q_U-;Y%9u>*d+vW;s!w^RT)ZqzE)YlCDIOQ z-LpM?1IfiUd_iD+%8M4u&Cv)fEusr<6RIE6$s%63+9o@0Oig3x^lV|`<;cn&P{5x4 z`(&46qk#+j=6~NqWfHMr+-}!!ZSvoGVS)43lO8==AjXd&F(7G> zL76!kOgFUjIIJw|U5H6!&Y`kv%g2vqvWcFn^f_b|T-4N5V51&8omG|dG0uRG9yGn* zV2HOCLKEX??|S-p!uHYx-NL8WcYiwuI}&GUC8TS&%nh~)KCJc10@gx+>bqN*pmQ=h zq(B3cdjyXr-ojno#EaHvff8gaXK|}_TxEsXwu!5)=iF8XOan8jK5CuXqgOL;SIs`Q zbde=WWne~%;7&7IoStwZ%@v+a580nT8Shtf7T*<|QNr-XtIS|?{wNuHbPIwD74<3h zL4ha5s(}lAgfMuw__=B$l(d|_2dCFvl3ol#+X|sK3=-q&WtNF&DE@AjAg^;lb1=n1 za3rJJvt#}hUGwFmw_X-PKmXUq2g7_RO;Je3(itnRORhm+y874GM_vYW1d%|}PiG}xrLSiI JjOmUc{{?zu%n|?q diff --git a/Session/Meta/Images.xcassets/crop-unlock-custom.imageset/Contents.json b/Session/Meta/Images.xcassets/crop-unlock-custom.imageset/Contents.json index bf240d3b5b..352cc1cbb4 100644 --- a/Session/Meta/Images.xcassets/crop-unlock-custom.imageset/Contents.json +++ b/Session/Meta/Images.xcassets/crop-unlock-custom.imageset/Contents.json @@ -1,19 +1,8 @@ { "images" : [ { - "filename" : "crop-unlock-custom.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "crop-unlock-custom@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "crop-unlock-custom@3x.png", - "idiom" : "universal", - "scale" : "3x" + "filename" : "crop-unlock-custom.pdf", + "idiom" : "universal" } ], "info" : { diff --git a/Session/Meta/Images.xcassets/crop-unlock-custom.imageset/crop-unlock-custom.pdf b/Session/Meta/Images.xcassets/crop-unlock-custom.imageset/crop-unlock-custom.pdf new file mode 100644 index 0000000000000000000000000000000000000000..20759e9994ec79a14ad35cf6e740a5235a3e8501 GIT binary patch literal 4686 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 literal 0 HcmV?d00001 diff --git a/Session/Meta/Images.xcassets/crop-unlock-custom.imageset/crop-unlock-custom.png b/Session/Meta/Images.xcassets/crop-unlock-custom.imageset/crop-unlock-custom.png deleted file mode 100644 index e62cf88ddde2e235eb44d3cd8c263695c8be1cb9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 593 zcmV-X0|WK~#7F?U{{D z!!QtqUl9W^f|-Ca0cHYV0>T8a0c-#pkWNsTfOZ04f`$p`2E|t=igBANKX>9P{7FxZ zQ!CAreZI2`B=(!B)57W5=?HsD=ClfQ2Spro=xd|)2^7)Ah-#7%Z6qVw7zNjq7cw-j zM%Kv$?ZRmWK0eFmePAGzqq?_n^21@I>?zDpPNC~9X;XAONV zWMjl)a}>^*e`8IK&AH5par#EjdQQ{wTR6Q&_gdF;hmgZMUBEBvbNCSzL(0g#(?ihC zoNk>?A%w)#GN?@~;in8S#&2`1NEo>cu4x30QLj8=yGqFzA(rLm4ZOh@2q7^dv*5ZK zoxWWABawF6`80x7Q?x{sDXoL0w5|)5w(l zEEtgr_6eF3URqTRa`Zd|Ox3S8k`ZkrBSOUW+#Guf9UbNH f8M}A+koJzn8rFWp@N00000NkvXXu0mjfp2_*~ diff --git a/Session/Meta/Images.xcassets/crop-unlock-custom.imageset/crop-unlock-custom@2x.png b/Session/Meta/Images.xcassets/crop-unlock-custom.imageset/crop-unlock-custom@2x.png deleted file mode 100644 index 065d15c640026b1b893539f26adda0a15eacbafb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1052 zcmeAS@N?(olHy`uVBq!ia0vp^DImIN3W zWVZ;%LtIW_4>m9*oX|*P<6pNJX+oq;s>m*7jTpbvx~KnE>fQ}5Jsny!J@)SQ ztMk7{F>xri2-NEIOmo}rw)NuFi47@^JyMH*%bG6GjNDLuq_#h6!jc;cU)@{G+A(=K z$9biInUO+=1&UZqTqN>1Zn(1p!-|av2T7qfA2K>#rViYpqy{zgSbhzJzd7r8eonh?&f(pc*wiKZ8=S-RcOSkwcd?J?gZgcP1t+Y! zwq9f}IXwL;>y&v4p1lfZCxj~MG2K(#TT>omomLm%t=YCl_WHeqrYQoaH)*e!-uJpG zZ~exD26a+*6WTs^DcreH-F4W!<#$PY;>`mWzMkk(@Nv~j2wBV@X!_v4YJe@D(`T7Y zE;dR3z6EBOEpf8Z(%@a4G55;R!n0}%^bGp?EA|-tn0_P3)l<^>c13oNbL`>o2j}cE z%IH8Kuc*|{i>k*IXBajaD7H^9)Cu>|4h0!J;j8G!9S3^^T3$wO^I`7U#r$oh<%9o~ z?Ku}0Rc}yF$&Yh>f7ppXWB!%s#oJ$0EqY)PB{E@-R_fHNNoq6g-Z@Wkbe=Ntv;bqF z(BTP+JKKXNEaACnpJDDgAyHl^durTjnvwI|d|_%8~W z_p5yukv{C*WBkh7&co@1_x+XK5V;<`IUK2JC-vcY+h?U(ON p|36E73pixGI9{Pez)9pId*oS*10u7!gMpcu!PC{xWt~$(69DFP!y*6x diff --git a/Session/Meta/Images.xcassets/crop-unlock-custom.imageset/crop-unlock-custom@3x.png b/Session/Meta/Images.xcassets/crop-unlock-custom.imageset/crop-unlock-custom@3x.png deleted file mode 100644 index 80ca2a525851931ad89745ec4ceab369a6ce3448..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1563 zcmb7ES5OlO5DiTsh>Z}Cawjkr3HbcEW-|fZq9}FRN7*E}njo zdXaxD&(}2SM-qe&uXuPa@9Z#&tHWCFtATTmNGAv0sJu+F%smdlb{7IIw=B>s;8^bX zuKXb}Yb6@K*+@D$!x+Kza8m^-6BrCfQAsUvu=`O+?MXzSDdSTtiY>;Dm5ddW{jWxu z79#RhPKZ{gjDg7jn7K=udRg>xeja{RbMPokpv%tDD(Q{r-b0LIsjtKYG zj)1NcNM_~E+$1`4MB@V&J4-(ss;%zOc{_^x?yS2x+pFk-j_yCKUdFb2eS@l_1ER^d zq&$67-&~ZHL=tkE2i82dgS7X*`|YY6hKXC>JV??Vs6u+LZ1ec+zC`5 z25{p~PA|xZ!)x6Z!owFR6|NK>GH6e_pJGLAx|V=`FnsTg58V{_gE-(o*E@%QO%Ds$sw8e`fc476+DQ@OaUb!Fm3m z-*{m|Q@?JBxbkQ)&Ij62nuafalm1JvGoC>s=3*_B*M_XS!rQeuy6gpgHj zZD@>g%CWp#x~hDD&eC~22d+P{Z5*1g71BC`v%1)Mje;j+Al+!pl*Q$ZRn<&~CM+O1 zVsgBki;|Lph767_`Y&O!%}-B4!4rs8THoAHk+|ZC1Sq(a>qj&nhT~m_3n%zNc{=x^ zUC}Sk8*oHe2e3Fw1#x=g?P$2_f(zD_hrY8FQxKZwyr#$PY7W(`1{>P8vj-n4`b~3= z<;>QM+9_2?%kphXOCn~uq)v2kn6tYHvA+Fg6z)N8jf}hT04x7k%ssG#oz!#x1fwX>VeZ z=@kJk-BCwaQU*L2*Y{yHaP5=A_8e%$H>miXzArUMk$P>*a#Z}bTzJBdQ_2KG^vyLb z=1?*l!v6Nz#)z6^Zzx>zCXB!^ZqA!e^$5%~Mkq8>F-2sj(!*SmLNE=)zkG`bF}WI{ zUpkeOdJ~%C4HHEOW69o2$uk#W{N(|BXDaX+se3L&q1|Z>$8~!TpTcGlg2|5pr@Cb1 zvD2f#Q%w5mGrqfOH08p#zW(gUNY%{owZ`40`Av_5_=u7n2s+*WciRE}SsE>QAkTca_SvvypG zw>&Y%--Qc9p?xYQ6{K9WL`s;rODq@hkFFGNU-XZmALP=!HA8Tp`!b0jHzvVIg%{DN&PKlXa>`F5wjfL5 wWS], Never> = [ SessionNavItem( id: .close, - image: UIImage(named: "X")? + image: Lucide.image(icon: .x, size: IconSize.medium.size)? .withRenderingMode(.alwaysTemplate), style: .plain, accessibilityIdentifier: "Close button" @@ -112,7 +112,7 @@ class SettingsViewModel: SessionTableViewModel, NavigationItemSource, Navigatabl lazy var rightNavItems: AnyPublisher<[SessionNavItem], Never> = [ SessionNavItem( id: .qrCode, - image: UIImage(named: "QRCode")? + image: Lucide.image(icon: .qrCode, size: IconSize.medium.size)? .withRenderingMode(.alwaysTemplate), style: .plain, accessibilityIdentifier: "View QR code", diff --git a/Session/Shared/SessionCarouselView.swift b/Session/Shared/SessionCarouselView.swift index 6111f6df07..81a437183f 100644 --- a/Session/Shared/SessionCarouselView.swift +++ b/Session/Shared/SessionCarouselView.swift @@ -1,6 +1,7 @@ // Copyright © 2023 Rangeproof Pty Ltd. All rights reserved. import UIKit +import Lucide import SessionUIKit import SessionUtilitiesKit @@ -41,7 +42,8 @@ final class SessionCarouselView: UIView, UIScrollViewDelegate { private lazy var arrowLeft: UIButton = { let result = UIButton(type: .custom) - result.setImage(UIImage(systemName: "chevron.left")?.withRenderingMode(.alwaysTemplate), for: .normal) + result.setImage(Lucide.image(icon: .chevronLeft, size: self.info.arrowsSize.height)? + .withRenderingMode(.alwaysTemplate), for: .normal) result.addTarget(self, action: #selector(scrollToPreviousSlice), for: .touchUpInside) result.themeTintColor = .textPrimary result.set(.width, to: self.info.arrowsSize.width) @@ -53,7 +55,8 @@ final class SessionCarouselView: UIView, UIScrollViewDelegate { private lazy var arrowRight: UIButton = { let result = UIButton(type: .custom) - result.setImage(UIImage(systemName: "chevron.right")?.withRenderingMode(.alwaysTemplate), for: .normal) + result.setImage(Lucide.image(icon: .chevronRight, size: self.info.arrowsSize.height)? + .withRenderingMode(.alwaysTemplate), for: .normal) result.addTarget(self, action: #selector(scrollToNextSlice), for: .touchUpInside) result.themeTintColor = .textPrimary result.set(.width, to: self.info.arrowsSize.width) diff --git a/SessionShareExtension/SAEScreenLockViewController.swift b/SessionShareExtension/SAEScreenLockViewController.swift index 216365d4cb..4105742e1e 100644 --- a/SessionShareExtension/SAEScreenLockViewController.swift +++ b/SessionShareExtension/SAEScreenLockViewController.swift @@ -1,6 +1,7 @@ // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. import UIKit +import Lucide import SignalUtilitiesKit import SessionUIKit import SessionUtilitiesKit @@ -43,7 +44,13 @@ final class SAEScreenLockViewController: ScreenLockViewController { }() private lazy var closeButton: UIBarButtonItem = { - let closeButton: UIBarButtonItem = UIBarButtonItem(image: UIImage(named: "X"), style: .plain, target: self, action: #selector(dismissPressed)) + let closeButton: UIBarButtonItem = UIBarButtonItem( + image: Lucide.image(icon: .x, size: 24)? + .withRenderingMode(.alwaysTemplate), + style: .plain, + target: self, + action: #selector(dismissPressed) + ) closeButton.themeTintColor = .textPrimary return closeButton diff --git a/SessionUIKit/Components/Modals & Toast/ConfirmationModal.swift b/SessionUIKit/Components/Modals & Toast/ConfirmationModal.swift index 90be264afb..39efa3521b 100644 --- a/SessionUIKit/Components/Modals & Toast/ConfirmationModal.swift +++ b/SessionUIKit/Components/Modals & Toast/ConfirmationModal.swift @@ -260,7 +260,7 @@ public class ConfirmationModal: Modal, UITextFieldDelegate, UITextViewDelegate { .withConfiguration( UIButton.Configuration .plain() - .withImage(UIImage(named: "X")?.withRenderingMode(.alwaysTemplate)) + .withImage(Lucide.image(icon: .x, size: 24)?.withRenderingMode(.alwaysTemplate)) .withContentInsets(NSDirectionalEdgeInsets(top: 6, leading: 6, bottom: 6, trailing: 6)) ) .withConfigurationUpdateHandler { button in diff --git a/SessionUIKit/Components/TopBannerController.swift b/SessionUIKit/Components/TopBannerController.swift index 1b4aa3c001..0b796bc30d 100644 --- a/SessionUIKit/Components/TopBannerController.swift +++ b/SessionUIKit/Components/TopBannerController.swift @@ -1,6 +1,7 @@ // Copyright © 2023 Rangeproof Pty Ltd. All rights reserved. import UIKit +import Lucide public class TopBannerController: UIViewController { public enum Warning: String, Codable { @@ -63,7 +64,7 @@ public class TopBannerController: UIViewController { let result: UIButton = UIButton() result.translatesAutoresizingMaskIntoConstraints = false result.setImage( - UIImage(systemName: "xmark", withConfiguration: UIImage.SymbolConfiguration(pointSize: 12, weight: .bold))? + Lucide.image(icon: .x, size: 24)? .withRenderingMode(.alwaysTemplate), for: .normal ) From 2a07eaf62678fa7379415b80bd01cbd3274b3d50 Mon Sep 17 00:00:00 2001 From: mikoldin Date: Tue, 9 Sep 2025 13:27:09 +0800 Subject: [PATCH 6/8] Additional System Icons to Lucide icons --- .../MediaPageViewController.swift | 9 +++- .../MediaTileViewController.swift | 5 +- .../UIContextualAction+Utilities.swift | 47 ++++++++++++++----- 3 files changed, 46 insertions(+), 15 deletions(-) diff --git a/Session/Media Viewing & Editing/MediaPageViewController.swift b/Session/Media Viewing & Editing/MediaPageViewController.swift index 63bb6e82d7..de0ba2e5aa 100644 --- a/Session/Media Viewing & Editing/MediaPageViewController.swift +++ b/Session/Media Viewing & Editing/MediaPageViewController.swift @@ -1,6 +1,7 @@ // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. import UIKit +import Lucide import GRDB import SessionUIKit import SessionMessagingKit @@ -300,7 +301,9 @@ class MediaPageViewController: UIPageViewController, UIPageViewControllerDataSou lazy var shareBarButton: UIBarButtonItem = { let shareBarButton = UIBarButtonItem( - barButtonSystemItem: .action, + image: Lucide.image(icon: .share, size: 24)? + .withRenderingMode(.alwaysTemplate), + style: .plain, target: self, action: #selector(didPressShare) ) @@ -311,7 +314,9 @@ class MediaPageViewController: UIPageViewController, UIPageViewControllerDataSou lazy var deleteBarButton: UIBarButtonItem = { let deleteBarButton = UIBarButtonItem( - barButtonSystemItem: .trash, + image: Lucide.image(icon: .trash2, size: 24)? + .withRenderingMode(.alwaysTemplate), + style: .plain, target: self, action: #selector(didPressDelete) ) diff --git a/Session/Media Viewing & Editing/MediaTileViewController.swift b/Session/Media Viewing & Editing/MediaTileViewController.swift index a5cc997b8c..7d08f26797 100644 --- a/Session/Media Viewing & Editing/MediaTileViewController.swift +++ b/Session/Media Viewing & Editing/MediaTileViewController.swift @@ -2,6 +2,7 @@ import UIKit import QuartzCore +import Lucide import GRDB import DifferenceKit import SessionUIKit @@ -127,7 +128,9 @@ public class MediaTileViewController: UIViewController, UICollectionViewDataSour lazy var deleteButton: UIBarButtonItem = { let result: UIBarButtonItem = UIBarButtonItem( - barButtonSystemItem: .trash, + image: Lucide.image(icon: .trash2, size: 24)? + .withRenderingMode(.alwaysTemplate), + style: .plain, target: self, action: #selector(didPressDelete) ) diff --git a/Session/Utilities/UIContextualAction+Utilities.swift b/Session/Utilities/UIContextualAction+Utilities.swift index 488e266e1c..f952f3905b 100644 --- a/Session/Utilities/UIContextualAction+Utilities.swift +++ b/Session/Utilities/UIContextualAction+Utilities.swift @@ -122,7 +122,7 @@ public extension UIContextualAction { case .clear: return UIContextualAction( title: "clear".localized(), - icon: Lucide.image(icon: .trash2, size: 24), + icon: Lucide.image(icon: .trash2, size: IconSize.medium.size), themeTintColor: .white, themeBackgroundColor: themeBackgroundColor, side: side, @@ -163,7 +163,7 @@ public extension UIContextualAction { case .hide: return UIContextualAction( title: "hide".localized(), - icon: UIImage(systemName: "eye.slash"), + icon: Lucide.image(icon: .eyeOff, size: IconSize.medium.size), themeTintColor: .white, themeBackgroundColor: themeBackgroundColor, accessibility: Accessibility(identifier: "Hide button"), @@ -214,9 +214,24 @@ public extension UIContextualAction { case .pin: let isCurrentlyPinned: Bool = (threadViewModel.threadPinnedPriority > 0) + + var pin: (title: String, icon: UIImage?) { + if isCurrentlyPinned { + return ( + "pinUnpin".localized(), + Lucide.image(icon: .pinOff, size: IconSize.medium.size) + ) + } else { + return ( + "pin".localized(), + Lucide.image(icon: .pin, size: IconSize.medium.size) + ) + } + } + return UIContextualAction( - title: (isCurrentlyPinned ? "pinUnpin".localized() : "pin".localized()), - icon: (isCurrentlyPinned ? UIImage(systemName: "pin.slash") : UIImage(systemName: "pin")), + title: pin.title, + icon: pin.icon, themeTintColor: .white, themeBackgroundColor: .conversationButton_swipeTertiary, // Always Tertiary accessibility: Accessibility( @@ -274,15 +289,23 @@ public extension UIContextualAction { // MARK: -- mute case .mute: + var mute: (title: String, icon: UIImage?) { + guard threadViewModel.threadMutedUntilTimestamp == nil else { + return ( + "notificationsMute".localized(), + Lucide.image(icon: .volumeOff, size: IconSize.medium.size) + ) + } + return ( + "notificationsMuteUnmute".localized(), + Lucide.image(icon: .volume, size: IconSize.medium.size) + ) + } + + return UIContextualAction( - title: (threadViewModel.threadMutedUntilTimestamp == nil ? - "notificationsMute".localized() : - "notificationsMuteUnmute".localized() - ), - icon: (threadViewModel.threadMutedUntilTimestamp == nil ? - UIImage(systemName: "speaker.slash") : - UIImage(systemName: "speaker") - ), + title: mute.title, + icon: mute.icon, themeTintColor: .white, themeBackgroundColor: themeBackgroundColor, accessibility: Accessibility( From 5ac89c5177a7041671c9380aad296f362c7595a4 Mon Sep 17 00:00:00 2001 From: mikoldin Date: Tue, 9 Sep 2025 13:41:52 +0800 Subject: [PATCH 7/8] Fix wrong icon for infoMediaSavedNotification --- Session/Conversations/Message Cells/InfoMessageCell.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Session/Conversations/Message Cells/InfoMessageCell.swift b/Session/Conversations/Message Cells/InfoMessageCell.swift index 9729311389..0e97494d83 100644 --- a/Session/Conversations/Message Cells/InfoMessageCell.swift +++ b/Session/Conversations/Message Cells/InfoMessageCell.swift @@ -118,7 +118,7 @@ final class InfoMessageCell: MessageCell { case .infoMediaSavedNotification: return Lucide.image( - icon: .download, + icon: .arrowDownToLine, size: InfoMessageCell.iconSize ) From baa79ff548a6fa7f1fbf3b6d895c6832232191a4 Mon Sep 17 00:00:00 2001 From: mikoldin Date: Tue, 9 Sep 2025 13:48:35 +0800 Subject: [PATCH 8/8] Update sizes to use IconSize --- Session/Calls/CallVC.swift | 14 +++++++------- Session/Calls/VideoPreviewVC.swift | 4 ++-- Session/Closed Groups/EditGroupViewModel.swift | 4 ++-- Session/Conversations/ConversationSearch.swift | 4 ++-- Session/Conversations/ConversationVC.swift | 2 +- .../SwiftUI/DocumentView_SwiftUI.swift | 2 +- .../SwiftUI/LinkPreviewView_SwiftUI.swift | 4 ++-- .../Settings/ThreadSettingsViewModel.swift | 2 +- .../New Conversation/StartConversationScreen.swift | 6 +++--- .../ImagePickerController.swift | 4 ++-- .../MediaPageViewController.swift | 4 ++-- .../MediaTileViewController.swift | 2 +- .../Utilities/UIContextualAction+Utilities.swift | 2 +- .../SAEScreenLockViewController.swift | 2 +- .../Modals & Toast/ConfirmationModal.swift | 2 +- SessionUIKit/Components/TopBannerController.swift | 2 +- .../AttachmentTextToolbar.swift | 2 +- .../Shared Views/ApprovalRailCellView.swift | 2 +- 18 files changed, 32 insertions(+), 32 deletions(-) diff --git a/Session/Calls/CallVC.swift b/Session/Calls/CallVC.swift index 7bc62a37d2..f7cd69aa9f 100644 --- a/Session/Calls/CallVC.swift +++ b/Session/Calls/CallVC.swift @@ -140,7 +140,7 @@ final class CallVC: UIViewController, VideoPreviewDelegate, AVRoutePickerViewDel private lazy var minimizeButton: UIButton = { let result = UIButton(type: .custom) result.setImage( - Lucide.image(icon: .minimize2, size: 24)? + Lucide.image(icon: .minimize2, size: IconSize.medium.size)? .withRenderingMode(.alwaysTemplate), for: .normal ) @@ -205,7 +205,7 @@ final class CallVC: UIViewController, VideoPreviewDelegate, AVRoutePickerViewDel let result = UIButton(type: .custom) result.isEnabled = call.isVideoEnabled result.setImage( - Lucide.image(icon: .switchCamera, size: 24)? + Lucide.image(icon: .switchCamera, size: IconSize.medium.size)? .withRenderingMode(.alwaysTemplate), for: .normal ) @@ -222,7 +222,7 @@ final class CallVC: UIViewController, VideoPreviewDelegate, AVRoutePickerViewDel private lazy var switchAudioButton: UIButton = { let result = UIButton(type: .custom) result.setImage( - Lucide.image(icon: .micOff, size: 24)? + Lucide.image(icon: .micOff, size: IconSize.medium.size)? .withRenderingMode(.alwaysTemplate), for: .normal ) @@ -245,7 +245,7 @@ final class CallVC: UIViewController, VideoPreviewDelegate, AVRoutePickerViewDel private lazy var videoButton: UIButton = { let result = UIButton(type: .custom) result.setImage( - Lucide.image(icon: .video, size: 24)? + Lucide.image(icon: .video, size: IconSize.medium.size)? .withRenderingMode(.alwaysTemplate), for: .normal ) @@ -273,7 +273,7 @@ final class CallVC: UIViewController, VideoPreviewDelegate, AVRoutePickerViewDel private lazy var routePickerButton: UIButton = { let result = UIButton(type: .custom) result.setImage( - Lucide.image(icon: .volume2, size: 24)? + Lucide.image(icon: .volume2, size: IconSize.medium.size)? .withRenderingMode(.alwaysTemplate), for: .normal ) @@ -825,7 +825,7 @@ final class CallVC: UIViewController, VideoPreviewDelegate, AVRoutePickerViewDel switch currentOutput.portType { case .builtInSpeaker: - let image = Lucide.image(icon: .volume2, size: 24)? + let image = Lucide.image(icon: .volume2, size: IconSize.medium.size)? .withRenderingMode(.alwaysTemplate) routePickerButton.setImage(image, for: .normal) @@ -859,7 +859,7 @@ final class CallVC: UIViewController, VideoPreviewDelegate, AVRoutePickerViewDel case .builtInReceiver: fallthrough default: - let image = Lucide.image(icon: .volume2, size: 24)? + let image = Lucide.image(icon: .volume2, size: IconSize.medium.size)? .withRenderingMode(.alwaysTemplate) routePickerButton.setImage(image, for: .normal) diff --git a/Session/Calls/VideoPreviewVC.swift b/Session/Calls/VideoPreviewVC.swift index 3b82807e1d..1d95758d96 100644 --- a/Session/Calls/VideoPreviewVC.swift +++ b/Session/Calls/VideoPreviewVC.swift @@ -45,7 +45,7 @@ class VideoPreviewVC: UIViewController, CameraManagerDelegate { private lazy var closeButton: UIButton = { let result = UIButton(type: .custom) result.setImage( - Lucide.image(icon: .x, size: 24)? + Lucide.image(icon: .x, size: IconSize.medium.size)? .withRenderingMode(.alwaysTemplate), for: .normal ) @@ -60,7 +60,7 @@ class VideoPreviewVC: UIViewController, CameraManagerDelegate { private lazy var confirmButton: UIButton = { let result = UIButton(type: .custom) result.setImage( - Lucide.image(icon: .check, size: 24)? + Lucide.image(icon: .check, size: IconSize.medium.size)? .withRenderingMode(.alwaysTemplate), for: .normal ) diff --git a/Session/Closed Groups/EditGroupViewModel.swift b/Session/Closed Groups/EditGroupViewModel.swift index 7456d86226..9fa23af451 100644 --- a/Session/Closed Groups/EditGroupViewModel.swift +++ b/Session/Closed Groups/EditGroupViewModel.swift @@ -254,7 +254,7 @@ class EditGroupViewModel: SessionTableViewModel, NavigatableStateHolder, Editabl elements: [ SessionCell.Info( id: .invite, - leadingAccessory: .icon(Lucide.image(icon: .userRoundPlus, size: 24)?.withRenderingMode(.alwaysTemplate)), + leadingAccessory: .icon(Lucide.image(icon: .userRoundPlus, size: IconSize.medium.size)?.withRenderingMode(.alwaysTemplate)), title: "membersInvite".localized(), accessibility: Accessibility( identifier: "Invite button", @@ -265,7 +265,7 @@ class EditGroupViewModel: SessionTableViewModel, NavigatableStateHolder, Editabl (!isUpdatedGroup || !dependencies[feature: .updatedGroupsAllowInviteById] ? nil : SessionCell.Info( id: .inviteById, - leadingAccessory: .icon(Lucide.image(icon: .plus, size: 24)?.withRenderingMode(.alwaysTemplate)), + leadingAccessory: .icon(Lucide.image(icon: .plus, size: IconSize.medium.size)?.withRenderingMode(.alwaysTemplate)), title: "accountIdOrOnsInvite".localized(), accessibility: Accessibility( identifier: "Invite by id", diff --git a/Session/Conversations/ConversationSearch.swift b/Session/Conversations/ConversationSearch.swift index 271ccad6ea..849562326b 100644 --- a/Session/Conversations/ConversationSearch.swift +++ b/Session/Conversations/ConversationSearch.swift @@ -150,7 +150,7 @@ public final class SearchResultsBar: UIView { }() private lazy var upButton: UIButton = { - let icon = Lucide.image(icon: .chevronUp, size: 24)? + let icon = Lucide.image(icon: .chevronUp, size: IconSize.medium.size)? .withRenderingMode(.alwaysTemplate) let result: UIButton = UIButton() result.setImage(icon, for: UIControl.State.normal) @@ -161,7 +161,7 @@ public final class SearchResultsBar: UIView { }() private lazy var downButton: UIButton = { - let icon = Lucide.image(icon: .chevronDown, size: 24)? + let icon = Lucide.image(icon: .chevronDown, size: IconSize.medium.size)? .withRenderingMode(.alwaysTemplate) let result: UIButton = UIButton() result.setImage(icon, for: UIControl.State.normal) diff --git a/Session/Conversations/ConversationVC.swift b/Session/Conversations/ConversationVC.swift index 864f31be8f..b81964bb95 100644 --- a/Session/Conversations/ConversationVC.swift +++ b/Session/Conversations/ConversationVC.swift @@ -1441,7 +1441,7 @@ final class ConversationVC: BaseVC, LibSessionRespondingViewController, Conversa if shouldHaveCallButton { let callButton = UIBarButtonItem( - image: Lucide.image(icon: .phone, size: 24), + image: Lucide.image(icon: .phone, size: IconSize.medium.size), style: .plain, target: self, action: #selector(startCall) diff --git a/Session/Conversations/Message Cells/Content Views/SwiftUI/DocumentView_SwiftUI.swift b/Session/Conversations/Message Cells/Content Views/SwiftUI/DocumentView_SwiftUI.swift index 07d0f0b489..e611e9b460 100644 --- a/Session/Conversations/Message Cells/Content Views/SwiftUI/DocumentView_SwiftUI.swift +++ b/Session/Conversations/Message Cells/Content Views/SwiftUI/DocumentView_SwiftUI.swift @@ -78,7 +78,7 @@ struct DocumentView_SwiftUI: View { } else if attachment.state == .failedDownload || attachment.state == .failedUpload, - let invalidImage = Lucide.image(icon: .triangleAlert, size: 24)?.withRenderingMode(.alwaysTemplate) + let invalidImage = Lucide.image(icon: .triangleAlert, size: IconSize.medium.size)?.withRenderingMode(.alwaysTemplate) { Image(uiImage: invalidImage) .resizable() diff --git a/Session/Conversations/Message Cells/Content Views/SwiftUI/LinkPreviewView_SwiftUI.swift b/Session/Conversations/Message Cells/Content Views/SwiftUI/LinkPreviewView_SwiftUI.swift index 93103fd613..6386eaee0b 100644 --- a/Session/Conversations/Message Cells/Content Views/SwiftUI/LinkPreviewView_SwiftUI.swift +++ b/Session/Conversations/Message Cells/Content Views/SwiftUI/LinkPreviewView_SwiftUI.swift @@ -64,7 +64,7 @@ public struct LinkPreviewView_SwiftUI: View { ) .cornerRadius(state is LinkPreview.SentState ? 0 : 8) } else if state is LinkPreview.DraftState || state is LinkPreview.SentState { - LucideIcon(.link, size: 24) + LucideIcon(.link, size: IconSize.medium.size) .foregroundColor( themeColor: isOutgoing ? .messageBubble_outgoingText : @@ -106,7 +106,7 @@ public struct LinkPreviewView_SwiftUI: View { Button(action: { onCancel?() }, label: { - if let image = Lucide.image(icon: .x, size: 24)?.withRenderingMode(.alwaysTemplate) { + if let image = Lucide.image(icon: .x, size: IconSize.medium.size)?.withRenderingMode(.alwaysTemplate) { Image(uiImage: image) .foregroundColor(themeColor: .textPrimary) } diff --git a/Session/Conversations/Settings/ThreadSettingsViewModel.swift b/Session/Conversations/Settings/ThreadSettingsViewModel.swift index b5c39cc9ce..fe2b55ac5e 100644 --- a/Session/Conversations/Settings/ThreadSettingsViewModel.swift +++ b/Session/Conversations/Settings/ThreadSettingsViewModel.swift @@ -1088,7 +1088,7 @@ class ThreadSettingsViewModel: SessionTableViewModel, NavigatableStateHolder, Ob SessionCell.Info( id: .debugDeleteAttachmentsBeforeNow, leadingAccessory: .icon( - Lucide.image(icon: .trash2, size: 24)? + Lucide.image(icon: .trash2, size: IconSize.medium.size)? .withRenderingMode(.alwaysTemplate), customTint: .danger ), diff --git a/Session/Home/New Conversation/StartConversationScreen.swift b/Session/Home/New Conversation/StartConversationScreen.swift index 96e923aa64..e8971023a4 100644 --- a/Session/Home/New Conversation/StartConversationScreen.swift +++ b/Session/Home/New Conversation/StartConversationScreen.swift @@ -29,7 +29,7 @@ struct StartConversationScreen: View { .putNumber(1) .localized() NewConversationCell( - image: Lucide.image(icon: .messageSquare, size: 24), + image: Lucide.image(icon: .messageSquare, size: IconSize.medium.size), title: title ) { let viewController: SessionHostingViewController = SessionHostingViewController( @@ -69,7 +69,7 @@ struct StartConversationScreen: View { .padding(.trailing, -Values.largeSpacing) NewConversationCell( - image: Lucide.image(icon: .globe, size: 24), + image: Lucide.image(icon: .globe, size: IconSize.medium.size), title: "communityJoin".localized() ) { let viewController = JoinOpenGroupVC(using: dependencies) @@ -87,7 +87,7 @@ struct StartConversationScreen: View { .padding(.trailing, -Values.largeSpacing) NewConversationCell( - image: Lucide.image(icon: .userRoundPlus, size: 24), + image: Lucide.image(icon: .userRoundPlus, size: IconSize.medium.size), title: "sessionInviteAFriend".localized() ) { let viewController: SessionHostingViewController = SessionHostingViewController( diff --git a/Session/Media Viewing & Editing/ImagePickerController.swift b/Session/Media Viewing & Editing/ImagePickerController.swift index 3ac7bf5ffc..aee465fafe 100644 --- a/Session/Media Viewing & Editing/ImagePickerController.swift +++ b/Session/Media Viewing & Editing/ImagePickerController.swift @@ -76,7 +76,7 @@ class ImagePickerGridController: UICollectionViewController, PhotoLibraryDelegat // quickly toggle between the Capture and the Picker VC's, we use the same custom "X" // icon here rather than the system "stop" icon so that the spacing matches exactly. // Otherwise there's a noticable shift in the icon placement. - let cancelImage = Lucide.image(icon: .x, size: 24) + let cancelImage = Lucide.image(icon: .x, size: IconSize.medium.size) let cancelButton = UIBarButtonItem(image: cancelImage, style: .plain, target: self, action: #selector(didPressCancel)) cancelButton.themeTintColor = .textPrimary @@ -96,7 +96,7 @@ class ImagePickerGridController: UICollectionViewController, PhotoLibraryDelegat collectionView.addGestureRecognizer(selectionPanGesture) if PHPhotoLibrary.authorizationStatus(for: .readWrite) == .limited { - let plusImage = Lucide.image(icon: .plus, size: 24) + let plusImage = Lucide.image(icon: .plus, size: IconSize.medium.size) let addSeletedPhotoButton = UIBarButtonItem.init(image: plusImage, style: .plain, target: self, action: #selector(addSelectedPhoto)) self.navigationItem.rightBarButtonItem = addSeletedPhotoButton diff --git a/Session/Media Viewing & Editing/MediaPageViewController.swift b/Session/Media Viewing & Editing/MediaPageViewController.swift index de0ba2e5aa..7041f2c3ef 100644 --- a/Session/Media Viewing & Editing/MediaPageViewController.swift +++ b/Session/Media Viewing & Editing/MediaPageViewController.swift @@ -301,7 +301,7 @@ class MediaPageViewController: UIPageViewController, UIPageViewControllerDataSou lazy var shareBarButton: UIBarButtonItem = { let shareBarButton = UIBarButtonItem( - image: Lucide.image(icon: .share, size: 24)? + image: Lucide.image(icon: .share, size: IconSize.medium.size)? .withRenderingMode(.alwaysTemplate), style: .plain, target: self, @@ -314,7 +314,7 @@ class MediaPageViewController: UIPageViewController, UIPageViewControllerDataSou lazy var deleteBarButton: UIBarButtonItem = { let deleteBarButton = UIBarButtonItem( - image: Lucide.image(icon: .trash2, size: 24)? + image: Lucide.image(icon: .trash2, size: IconSize.medium.size)? .withRenderingMode(.alwaysTemplate), style: .plain, target: self, diff --git a/Session/Media Viewing & Editing/MediaTileViewController.swift b/Session/Media Viewing & Editing/MediaTileViewController.swift index 7d08f26797..100db65612 100644 --- a/Session/Media Viewing & Editing/MediaTileViewController.swift +++ b/Session/Media Viewing & Editing/MediaTileViewController.swift @@ -128,7 +128,7 @@ public class MediaTileViewController: UIViewController, UICollectionViewDataSour lazy var deleteButton: UIBarButtonItem = { let result: UIBarButtonItem = UIBarButtonItem( - image: Lucide.image(icon: .trash2, size: 24)? + image: Lucide.image(icon: .trash2, size: IconSize.medium.size)? .withRenderingMode(.alwaysTemplate), style: .plain, target: self, diff --git a/Session/Utilities/UIContextualAction+Utilities.swift b/Session/Utilities/UIContextualAction+Utilities.swift index f952f3905b..a1b72cc79c 100644 --- a/Session/Utilities/UIContextualAction+Utilities.swift +++ b/Session/Utilities/UIContextualAction+Utilities.swift @@ -638,7 +638,7 @@ public extension UIContextualAction { case .delete: return UIContextualAction( title: "delete".localized(), - icon: Lucide.image(icon: .trash2, size: 24), + icon: Lucide.image(icon: .trash2, size: IconSize.medium.size), themeTintColor: .white, themeBackgroundColor: themeBackgroundColor, accessibility: Accessibility(identifier: "Delete button"), diff --git a/SessionShareExtension/SAEScreenLockViewController.swift b/SessionShareExtension/SAEScreenLockViewController.swift index 4105742e1e..a3130c4031 100644 --- a/SessionShareExtension/SAEScreenLockViewController.swift +++ b/SessionShareExtension/SAEScreenLockViewController.swift @@ -45,7 +45,7 @@ final class SAEScreenLockViewController: ScreenLockViewController { private lazy var closeButton: UIBarButtonItem = { let closeButton: UIBarButtonItem = UIBarButtonItem( - image: Lucide.image(icon: .x, size: 24)? + image: Lucide.image(icon: .x, size: IconSize.medium.size)? .withRenderingMode(.alwaysTemplate), style: .plain, target: self, diff --git a/SessionUIKit/Components/Modals & Toast/ConfirmationModal.swift b/SessionUIKit/Components/Modals & Toast/ConfirmationModal.swift index 39efa3521b..bb5c53bc3c 100644 --- a/SessionUIKit/Components/Modals & Toast/ConfirmationModal.swift +++ b/SessionUIKit/Components/Modals & Toast/ConfirmationModal.swift @@ -260,7 +260,7 @@ public class ConfirmationModal: Modal, UITextFieldDelegate, UITextViewDelegate { .withConfiguration( UIButton.Configuration .plain() - .withImage(Lucide.image(icon: .x, size: 24)?.withRenderingMode(.alwaysTemplate)) + .withImage(Lucide.image(icon: .x, size: IconSize.medium.size)?.withRenderingMode(.alwaysTemplate)) .withContentInsets(NSDirectionalEdgeInsets(top: 6, leading: 6, bottom: 6, trailing: 6)) ) .withConfigurationUpdateHandler { button in diff --git a/SessionUIKit/Components/TopBannerController.swift b/SessionUIKit/Components/TopBannerController.swift index 0b796bc30d..708a4f38ca 100644 --- a/SessionUIKit/Components/TopBannerController.swift +++ b/SessionUIKit/Components/TopBannerController.swift @@ -64,7 +64,7 @@ public class TopBannerController: UIViewController { let result: UIButton = UIButton() result.translatesAutoresizingMaskIntoConstraints = false result.setImage( - Lucide.image(icon: .x, size: 24)? + Lucide.image(icon: .x, size: IconSize.medium.size)? .withRenderingMode(.alwaysTemplate), for: .normal ) diff --git a/SignalUtilitiesKit/Media Viewing & Editing/Attachment Approval/AttachmentTextToolbar.swift b/SignalUtilitiesKit/Media Viewing & Editing/Attachment Approval/AttachmentTextToolbar.swift index 09246fe0e0..ee15c57822 100644 --- a/SignalUtilitiesKit/Media Viewing & Editing/Attachment Approval/AttachmentTextToolbar.swift +++ b/SignalUtilitiesKit/Media Viewing & Editing/Attachment Approval/AttachmentTextToolbar.swift @@ -39,7 +39,7 @@ class AttachmentTextToolbar: UIView, UITextViewDelegate { private var bottomStackView: UIStackView? private lazy var sendButton: InputViewButton = { - let sendIcon = Lucide.image(icon: .arrowUp, size: 24) + let sendIcon = Lucide.image(icon: .arrowUp, size: IconSize.medium.size) let result = InputViewButton(icon: sendIcon, isSendButton: true, delegate: self) result.accessibilityIdentifier = "Send message button" diff --git a/SignalUtilitiesKit/Shared Views/ApprovalRailCellView.swift b/SignalUtilitiesKit/Shared Views/ApprovalRailCellView.swift index 5855c55487..7d589c976b 100644 --- a/SignalUtilitiesKit/Shared Views/ApprovalRailCellView.swift +++ b/SignalUtilitiesKit/Shared Views/ApprovalRailCellView.swift @@ -28,7 +28,7 @@ public class ApprovalRailCellView: GalleryRailCellView { strongSelf.approvalRailCellDelegate?.approvalRailCellView(strongSelf, didRemoveItem: attachmentItem) } - button.setImage(Lucide.image(icon: .x, size: 24)?.withRenderingMode(.alwaysTemplate), for: .normal) + button.setImage(Lucide.image(icon: .x, size: IconSize.medium.size)?.withRenderingMode(.alwaysTemplate), for: .normal) button.themeTintColor = .white button.themeShadowColor = .black button.layer.shadowRadius = 2