Run SwiftFormat.

This commit is contained in:
Doug
2026-05-27 14:38:50 +01:00
committed by Doug
parent 5138e05e47
commit fa67713726
573 changed files with 2426 additions and 2426 deletions
@@ -126,11 +126,11 @@ final class CompletionSuggestionService: CompletionSuggestionServiceProtocol {
&& selectedRange.location <= upperBound
&& selectedRange.length <= upperBound - lowerBound
}
guard let match else {
return nil
}
var suggestionText = String(text[match.range])
let firstChar = suggestionText.removeFirst()
@@ -27,9 +27,9 @@ enum ComposerToolbarViewModelAction {
case sendMessage(plain: String, html: String?, mode: ComposerMode, intentionalMentions: IntentionalMentions)
case editLastMessage
case attach(ComposerAttachmentType)
case handlePasteOrDrop(providers: [NSItemProvider])
case composerModeChanged(mode: ComposerMode)
case composerFocusedChanged(isFocused: Bool)
@@ -84,7 +84,7 @@ struct ComposerToolbarViewState: BindableState {
var keyCommands: [WysiwygKeyCommand] = []
var bindings: ComposerToolbarViewStateBindings
var isUploading: Bool {
switch composerMode {
case .previewVoiceMessage(_, _, let isUploading):
@@ -93,7 +93,7 @@ struct ComposerToolbarViewState: BindableState {
return false
}
}
var showSendButton: Bool {
switch composerMode {
case .recordVoiceMessage:
@@ -221,7 +221,7 @@ extension FormatItem {
return \.link
}
}
var accessibilityIdentifier: String {
switch type {
case .bold:
@@ -250,7 +250,7 @@ extension FormatItem {
return A11yIdentifiers.roomScreen.composerToolbar.link
}
}
var accessibilityLabel: String {
let localizedAction = switch type {
case .bold:
@@ -336,7 +336,7 @@ enum ComposerMode: Equatable {
case edit(originalEventOrTransactionID: TimelineItemIdentifier.EventOrTransactionID, type: EditType)
case recordVoiceMessage(state: AudioRecorderState)
case previewVoiceMessage(state: AudioPlayerState, waveform: WaveformSource, isUploading: Bool)
var isEdit: Bool {
switch self {
case .edit:
@@ -345,7 +345,7 @@ enum ComposerMode: Equatable {
return false
}
}
var isTextEditingEnabled: Bool {
switch self {
case .default, .reply, .edit:
@@ -28,23 +28,23 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
private let attributedStringBuilder: AttributedStringBuilderProtocol
private var hasAppeard = false
private let actionsSubject: PassthroughSubject<ComposerToolbarViewModelAction, Never> = .init()
var actions: AnyPublisher<ComposerToolbarViewModelAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
private struct WysiwygLinkData {
let action: LinkAction
let range: NSRange
var url: String
var text: String
}
private var currentLinkData: WysiwygLinkData?
private var replyLoadingTask: Task<Void, Never>?
init(initialText: String? = nil,
roomProxy: JoinedRoomProxyProtocol,
wysiwygViewModel: WysiwygComposerViewModel,
@@ -84,7 +84,7 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
.removeDuplicates()
.weakAssign(to: \.state.isRoomEncrypted, on: self)
.store(in: &cancellables)
context.$viewState
.map(\.composerMode)
.removeDuplicates()
@@ -93,13 +93,13 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
self?.actionsSubject.send(.composerModeChanged(mode: $0))
}
.store(in: &cancellables)
context.$viewState
.map(\.bindings.composerFocused)
.removeDuplicates()
.sink { [weak self] in self?.actionsSubject.send(.composerFocusedChanged(isFocused: $0)) }
.store(in: &cancellables)
wysiwygViewModel.$isContentEmpty
.removeDuplicates()
.sink { [weak self] isEmpty in
@@ -122,7 +122,7 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
self?.actionsSubject.send(.contentChanged(isEmpty: plainComposerText.string.isEmpty))
}
.store(in: &cancellables)
wysiwygViewModel.$actionStates
.map { actions in
FormatType
@@ -149,13 +149,13 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
focusComposerIfHardwareKeyboardConnected()
let identityStatusChangesPublisher = roomProxy.identityStatusChangesPublisher.receive(on: DispatchQueue.main)
Task { [weak self] in
for await changes in identityStatusChangesPublisher.values {
guard !Task.isCancelled else {
return
}
await self?.processIdentityStatusChanges(changes)
}
}
@@ -176,7 +176,7 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
func stop() {
saveDraft()
}
override func process(viewAction: ComposerToolbarViewAction) {
switch viewAction {
case .composerAppeared:
@@ -252,7 +252,7 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
}
}
}
func process(timelineAction: TimelineComposerAction) {
switch timelineAction {
case .setMode(mode: let mode):
@@ -398,7 +398,7 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
private var plainComposerContent: PlainComposerContent {
let attributedString = NSMutableAttributedString(attributedString: context.plainComposerText)
var shouldMakeAnotherPass = false
var userIDs = Set<String>()
var containsAtRoom = false
@@ -558,24 +558,24 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
MXLog.error("Failed retrieving room member for identity status change: \(change)")
continue
}
identityPinningViolations[change.userId] = member
default:
// clear
identityPinningViolations[change.userId] = nil
}
}
state.canSend = identityPinningViolations.isEmpty
}
private func set(mode: ComposerMode) {
if state.composerMode.isLoadingReply, state.composerMode.replyEventID != mode.replyEventID {
replyLoadingTask?.cancel()
}
guard mode != state.composerMode else { return }
state.composerMode = mode
switch mode {
case .default:
@@ -589,14 +589,14 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
state.bindings.composerFocused = true
}
}
private func set(text: String) {
if context.composerFormattingEnabled {
wysiwygViewModel.textView.flushPills()
wysiwygViewModel.setHtmlContent(text)
} else {
let attributedString = NSMutableAttributedString(string: text)
parseUserMentionsMarkdown(text) { range, url in
// Call your handleUserMention function here
attributedString.addAttribute(.link, value: url, range: range)
@@ -649,19 +649,19 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
range: wysiwygViewModel.attributedContent.selection,
url: linkAction.url ?? "",
text: "")
let urlBinding: Binding<String> = .init { [weak self] in
self?.currentLinkData?.url ?? ""
} set: { [weak self] value in
self?.currentLinkData?.url = value
}
let textBinding: Binding<String> = .init { [weak self] in
self?.currentLinkData?.text ?? ""
} set: { [weak self] value in
self?.currentLinkData?.text = value
}
switch linkAction {
case .createWithText:
state.bindings.alertInfo = makeCreateWithTextAlertInfo(urlBinding: urlBinding, textBinding: textBinding)
@@ -673,7 +673,7 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
break
}
}
private func makeCreateWithTextAlertInfo(urlBinding: Binding<String>, textBinding: Binding<String>) -> AlertInfo<UUID> {
AlertInfo(id: UUID(),
title: L10n.richTextEditorCreateLink,
@@ -683,7 +683,7 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
secondaryButton: AlertInfo<UUID>.AlertButton(title: L10n.actionSave) {
self.restoreComposerSelectedRange()
self.createLinkWithText()
},
textFields: [AlertInfo<UUID>.AlertTextField(placeholder: L10n.commonText,
text: textBinding,
@@ -694,7 +694,7 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
autoCapitalization: .never,
autoCorrectionDisabled: true)])
}
private func makeSetUrlAlertInfo(urlBinding: Binding<String>, isEdit: Bool) -> AlertInfo<UUID> {
AlertInfo(id: UUID(),
title: isEdit ? L10n.richTextEditorEditLink : L10n.richTextEditorCreateLink,
@@ -704,14 +704,14 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
secondaryButton: AlertInfo<UUID>.AlertButton(title: L10n.actionSave) {
self.restoreComposerSelectedRange()
self.setLink()
},
textFields: [AlertInfo<UUID>.AlertTextField(placeholder: L10n.richTextEditorUrlPlaceholder,
text: urlBinding,
autoCapitalization: .never,
autoCorrectionDisabled: true)])
}
private func makeEditChoiceAlertInfo(urlBinding: Binding<String>) -> AlertInfo<UUID> {
AlertInfo(id: UUID(),
title: L10n.richTextEditorEditLink,
@@ -726,23 +726,23 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
}
}])
}
private func restoreComposerSelectedRange() {
guard let currentLinkData else { return }
wysiwygViewModel.select(range: currentLinkData.range)
}
private func setLink() {
guard let currentLinkData else { return }
wysiwygViewModel.applyLinkOperation(.setLink(urlString: currentLinkData.url))
}
private func createLinkWithText() {
guard let currentLinkData else { return }
wysiwygViewModel.applyLinkOperation(.createLink(urlString: currentLinkData.url,
text: currentLinkData.text))
}
private func removeLinks() {
wysiwygViewModel.applyLinkOperation(.removeLinks)
}
@@ -819,7 +819,7 @@ extension ComposerToolbarViewModel {
if !canSend {
roomProxy.identityStatusChangesPublisher = .init([.init(userId: RoomMemberProxyMock.mockAlice.userID, changedTo: .verificationViolation)])
}
let wysiwygViewModel = WysiwygComposerViewModel()
let viewModel = ComposerToolbarViewModel(roomProxy: roomProxy,
wysiwygViewModel: wysiwygViewModel,
@@ -17,6 +17,6 @@ protocol ComposerToolbarViewModelProtocol {
func start()
func stop()
func process(timelineAction: TimelineComposerAction)
}
@@ -23,7 +23,7 @@ struct CompletionSuggestionView: View {
/// To make the scrolling more apparent we show a factional amount
static let maxVisibleRows: CGFloat = 4.5
}
// MARK: Public
@State private var prototypeListItemFrame: CGRect = .zero
@@ -47,7 +47,7 @@ struct CompletionSuggestionView: View {
.padding(.bottom, Constants.listItemPadding)
}
}
private func list() -> some View {
List(items) { item in
Button {
@@ -66,18 +66,18 @@ struct CompletionSuggestionView: View {
private func contentHeightForRowCount(_ count: CGFloat) -> CGFloat {
(prototypeListItemFrame.height + Constants.listItemPadding * 2 + Constants.listItemSpacing) * count - Constants.listItemSpacing / 2 + Constants.topPadding - Constants.listItemPadding
}
private struct ListItemPaddingModifier: ViewModifier {
private let isFirst: Bool
init(isFirst: Bool) {
self.isFirst = isFirst
}
func body(content: Content) -> some View {
let topPadding: CGFloat = isFirst ? Constants.topPadding : Constants.listItemPadding
let bottomPadding: CGFloat = Constants.listItemPadding
return content
.padding(.top, topPadding)
.padding(.bottom, bottomPadding)
@@ -236,7 +236,7 @@ struct ComposerToolbar: View {
// sending e.g. accepting current autocorrection.
// Fixes https://github.com/element-hq/element-x-ios/issues/3216
context.presendCallback?()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
context.send(viewAction: .sendMessage)
}
@@ -14,7 +14,7 @@ struct FormattingToolbar: View {
var formatItems: [FormatItem]
/// The action when an item is selected
var formatAction: (FormatType) -> Void
var body: some View {
ScrollView(.horizontal) {
HStack(spacing: 5) {
@@ -50,7 +50,7 @@ private extension FormatItem {
return .compound.iconDisabled
}
}
var backgroundColor: Color {
switch state {
case .reversed:
@@ -78,7 +78,7 @@ struct MessageComposer: View {
pasteHandler: pasteAction)
}
}
private var composerHeight: CGFloat {
let baseHeight = isExpanded ? ComposerConstant.maxHeight : ComposerConstant.minHeight
return (baseHeight - composerTranslation).clamped(to: ComposerConstant.allowedHeightRange)
@@ -95,7 +95,7 @@ struct MessageComposer: View {
EmptyView()
}
}
private var resizeGrabber: some View {
Capsule()
.foregroundStyle(.tertiary)
@@ -103,7 +103,7 @@ struct MessageComposer: View {
.padding(.vertical, 8)
.frame(maxWidth: .infinity)
}
private var dragGesture: some Gesture {
DragGesture()
.onChanged { value in
@@ -14,11 +14,11 @@ struct MessageComposerTextField: View {
@Binding var text: NSAttributedString
@Binding var presendCallback: (() -> Void)?
@Binding var selectedRange: NSRange
let maxHeight: CGFloat
let keyHandler: GenericKeyHandler
let pasteHandler: PasteHandler
var body: some View {
UITextViewWrapper(text: $text,
presendCallback: $presendCallback,
@@ -30,7 +30,7 @@ struct MessageComposerTextField: View {
.background(placeholderView, alignment: .topLeading)
.background { keyboardShortcuts }
}
@ViewBuilder
private var placeholderView: some View {
if text.string.isEmpty {
@@ -54,18 +54,18 @@ struct MessageComposerTextField: View {
private struct UITextViewWrapper: UIViewRepresentable {
@Environment(\.timelineContext) private var timelineContext
@Binding var text: NSAttributedString
@Binding var presendCallback: (() -> Void)?
@Binding var selectedRange: NSRange
let maxHeight: CGFloat
let keyHandler: GenericKeyHandler
let pasteHandler: PasteHandler
private let font = UIFont.preferredFont(forTextStyle: .body)
func makeUIView(context: UIViewRepresentableContext<UITextViewWrapper>) -> UITextView {
// Need to use TextKit 1 for mentions
let textView = ElementTextView(timelineContext: timelineContext,
@@ -89,21 +89,21 @@ private struct UITextViewWrapper: UIViewRepresentable {
if ProcessInfo.processInfo.isiOSAppOnMac {
textView.autocorrectionType = .no
}
textView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
return textView
}
func sizeThatFits(_ proposal: ProposedViewSize, uiView: UITextView, context: Context) -> CGSize? {
// Note: Coalescing a width of zero here returns a size for the view with 1 line of text visible.
let newSize = uiView.sizeThatFits(CGSize(width: proposal.width ?? .zero, height: maxHeight))
let width = proposal.width ?? newSize.width
let height = min(maxHeight, newSize.height)
return CGSize(width: width, height: height)
}
func updateUIView(_ textView: UITextView, context: UIViewRepresentableContext<UITextViewWrapper>) {
// Prevent the textView from inheriting attributes from mention pills
textView.typingAttributes = [.font: font,
@@ -149,7 +149,7 @@ private struct UITextViewWrapper: UIViewRepresentable {
}
}
}
func makeCoordinator() -> Coordinator {
Coordinator(text: $text,
selectedRange: $selectedRange,
@@ -157,16 +157,16 @@ private struct UITextViewWrapper: UIViewRepresentable {
keyHandler: keyHandler,
pasteHandler: pasteHandler)
}
final class Coordinator: NSObject, UITextViewDelegate, ElementTextViewDelegate {
private var text: Binding<NSAttributedString>
private var selectedRange: Binding<NSRange>
private let maxHeight: CGFloat
private let keyHandler: GenericKeyHandler
private let pasteHandler: PasteHandler
init(text: Binding<NSAttributedString>,
selectedRange: Binding<NSRange>,
maxHeight: CGFloat,
@@ -178,11 +178,11 @@ private struct UITextViewWrapper: UIViewRepresentable {
self.keyHandler = keyHandler
self.pasteHandler = pasteHandler
}
func textViewDidChange(_ textView: UITextView) {
text.wrappedValue = textView.attributedText
}
func textViewDidReceiveKeyPress(_ textView: UITextView, key: UIKeyboardHIDUsage) {
keyHandler(key)
}
@@ -190,7 +190,7 @@ private struct UITextViewWrapper: UIViewRepresentable {
func textViewDidReceiveShiftEnterKeyPress(_ textView: UITextView) {
textView.insertText("\n")
}
func textView(_ textView: UITextView, didReceivePasteWith providers: [NSItemProvider]) {
pasteHandler(providers)
}
@@ -242,7 +242,7 @@ private class ElementTextView: UITextView, PillAttachmentViewProviderDelegate {
[UIKeyCommand(input: "\r", modifierFlags: .shift, action: #selector(shiftEnterKeyPressed)),
UIKeyCommand(input: "\r", modifierFlags: [], action: #selector(enterKeyPressed))]
}
@objc func shiftEnterKeyPressed(sender: UIKeyCommand) {
elementDelegate?.textViewDidReceiveShiftEnterKeyPress(self)
}
@@ -269,21 +269,21 @@ private class ElementTextView: UITextView, PillAttachmentViewProviderDelegate {
super.pressesBegan(presses, with: event)
}
// Pasting support
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if super.canPerformAction(action, withSender: sender) {
return true
}
guard action == #selector(paste(_:)) else {
return false
}
return UIPasteboard.general.itemProviders.filter { !$0.isSupportedForPasteOrDrop }.isEmpty
}
override func paste(_ sender: Any?) {
let providers = UIPasteboard.general.itemProviders
@@ -312,7 +312,7 @@ private class ElementTextView: UITextView, PillAttachmentViewProviderDelegate {
func registerPillView(_ pillView: UIView) {
pillViews.add(pillView)
}
func flushPills() {
for view in pillViews.allObjects {
view.alpha = 0.0
@@ -341,15 +341,15 @@ struct MessageComposerTextField_Previews: PreviewProvider, TestablePreview {
PreviewWrapper(text: "A really long message that will wrap to multiple lines on a phone in portrait.")
}
}
struct PreviewWrapper: View {
@State var text: NSAttributedString
init(text: String) {
_text = .init(initialValue: .init(string: text, attributes: [.font: UIFont.preferredFont(forTextStyle: .body),
.foregroundColor: UIColor.compound.textPrimary]))
}
var body: some View {
MessageComposerTextField(placeholder: "Placeholder",
text: $text,
@@ -79,10 +79,10 @@ struct RoomAttachmentPicker: View {
struct RoomAttachmentPicker_Previews: PreviewProvider, TestablePreview {
static let viewModel = makeViewModel()
static func makeViewModel() -> ComposerToolbarViewModel {
let appSettings = AppSettings.volatile()
return ComposerToolbarViewModel(roomProxy: JoinedRoomProxyMock(.init()),
wysiwygViewModel: WysiwygComposerViewModel(),
completionSuggestionService: CompletionSuggestionServiceMock(configuration: .init()),
@@ -92,7 +92,7 @@ struct RoomAttachmentPicker_Previews: PreviewProvider, TestablePreview {
analyticsService: AnalyticsServiceMock(.init()),
composerDraftService: ComposerDraftServiceMock(.init()))
}
static var previews: some View {
RoomAttachmentPicker(context: viewModel.context)
}
@@ -18,12 +18,12 @@ struct VoiceMessagePreviewComposer: View {
@ScaledMetric private var waveformLineWidth = 2.0
@ScaledMetric private var waveformLinePadding = 2.0
@GestureState var isDragging = false
let onPlay: () -> Void
let onPause: () -> Void
let onSeek: (Double) -> Void
let onScrubbing: (Bool) -> Void
var timeLabelContent: String {
// Display the duration if progress is 0.0
let percent = playerState.progress > 0.0 ? playerState.progress : 1.0
@@ -43,7 +43,7 @@ struct VoiceMessagePreviewComposer: View {
.foregroundColor(.compound.textSecondary)
.monospacedDigit()
.fixedSize(horizontal: true, vertical: true)
waveformView
.waveformInteraction(isDragging: $isDragging,
progress: playerState.progress,
@@ -77,7 +77,7 @@ struct VoiceMessagePreviewComposer: View {
.progressMask(progress: playerState.progress)
}
}
private func onPlayPause() {
if playerState.playbackState == .playing {
onPause()
@@ -17,13 +17,13 @@ struct VoiceMessageRecordingView: View {
@ScaledMetric private var waveformLineWidth = 2.0
@ScaledMetric private var waveformLinePadding = 2.0
@ScaledMetric private var recordingIndicatorSize = 8
private static let elapsedTimeFormatter: DateFormatter = {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "mm:ss"
return dateFormatter
}()
private var timeLabelContent: String {
Self.elapsedTimeFormatter.string(from: Date(timeIntervalSinceReferenceDate: recorderState.duration))
}
@@ -37,7 +37,7 @@ struct VoiceMessageRecordingView: View {
HStack(spacing: 8) {
VoiceMessageRecordingBadge()
.frame(width: recordingIndicatorSize, height: recordingIndicatorSize)
Text(timeLabelContent)
.lineLimit(1)
.font(.compound.bodySMSemibold)
@@ -55,7 +55,7 @@ struct VoiceMessageRecordingView: View {
private struct VoiceMessageRecordingBadge: View {
@State private var opacity: CGFloat = 0
var body: some View {
Circle()
.foregroundColor(.red)