Swiftformat

This commit is contained in:
Thomas Ricouard 2023-02-12 16:29:41 +01:00
parent 9fd1b4ef73
commit eb6050a38f
48 changed files with 304 additions and 314 deletions

View file

@ -3,9 +3,9 @@ import AppAccount
import DesignSystem
import Env
import Models
import Network
import SwiftUI
import Timeline
import Network
struct AccountSettingsView: View {
@Environment(\.dismiss) private var dismiss

View file

@ -43,7 +43,7 @@ struct DisplaySettingsView: View {
Picker("settings.display.font", selection: .init(get: { () -> FontState in
if userPreferences.chosenFont?.fontName == "OpenDyslexic-Regular" {
return FontState.openDyslexic
} else if userPreferences.chosenFont?.fontName == "AtkinsonHyperlegible-Regular" {
} else if userPreferences.chosenFont?.fontName == "AtkinsonHyperlegible-Regular" {
return FontState.hyperLegible
}
return userPreferences.chosenFontData != nil ? FontState.custom : FontState.system

View file

@ -45,8 +45,8 @@ struct IconSelectorView: View {
static let items = [
IconSelector(title: "Official icons", icons: [.primary, .alt1, .alt2, .alt3, .alt4, .alt5, .alt6, .alt7, .alt8,
.alt9, .alt10, .alt11, .alt12, .alt13, .alt14,
.alt15, .alt16, .alt17, .alt18, .alt19, .alt25]),
.alt9, .alt10, .alt11, .alt12, .alt13, .alt14,
.alt15, .alt16, .alt17, .alt18, .alt19, .alt25]),
IconSelector(title: "Icons by Albert Kinng", icons: [.alt20, .alt21, .alt22, .alt23, .alt24]),
IconSelector(title: "Icons by Dan van Moll", icons: [.alt26, .alt27, .alt28]),
IconSelector(title: "Icons by @te6-in (GitHub)", icons: [.alt29, .alt30, .alt31, .alt32]),

View file

@ -102,11 +102,11 @@ struct SettingsTabs: View {
NavigationLink(destination: DisplaySettingsView()) {
Label("settings.general.display", systemImage: "paintpalette")
}
if HapticManager.shared.supportsHaptics {
NavigationLink(destination: HapticSettingsView()) {
Label("settings.general.haptic", systemImage: "waveform.path")
}
if HapticManager.shared.supportsHaptics {
NavigationLink(destination: HapticSettingsView()) {
Label("settings.general.haptic", systemImage: "waveform.path")
}
}
NavigationLink(destination: remoteLocalTimelinesView) {
Label("settings.general.remote-timelines", systemImage: "dot.radiowaves.right")
}

View file

@ -16,7 +16,7 @@ struct SwipeActionsSettingsView: View {
}
Section {
ForEach(StatusAction.allCases) { action in
if (action != .none) {
if action != .none {
Label(action.displayName(), systemImage: action.iconName()).tag(action)
}
}
@ -28,20 +28,20 @@ struct SwipeActionsSettingsView: View {
}
Section {
ForEach(StatusAction.allCases) { action in
if (action != .none) {
if action != .none {
Label(action.displayName(), systemImage: action.iconName()).tag(action)
}
}
}
}
Label("settings.swipeactions.status.trailing", systemImage: "arrow.left.circle")
Picker(selection: $userPreferences.swipeActionsStatusTrailingLeft, label: makeSwipeLabel(left: true, text: "settings.swipeactions.status.trailing.left")) {
Picker(selection: $userPreferences.swipeActionsStatusTrailingLeft, label: makeSwipeLabel(left: true, text: "settings.swipeactions.status.trailing.left")) {
Section {
Label(StatusAction.none.displayName(), systemImage: StatusAction.none.iconName()).tag(StatusAction.none)
}
Section {
ForEach(StatusAction.allCases) { action in
if (action != .none) {
if action != .none {
Label(action.displayName(), systemImage: action.iconName()).tag(action)
}
}
@ -53,7 +53,7 @@ struct SwipeActionsSettingsView: View {
}
Section {
ForEach(StatusAction.allCases) { action in
if (action != .none) {
if action != .none {
Label(action.displayName(), systemImage: action.iconName()).tag(action)
}
}
@ -69,6 +69,6 @@ struct SwipeActionsSettingsView: View {
private func makeSwipeLabel(left: Bool, text: LocalizedStringKey) -> some View {
return Label(text, systemImage: left ? "rectangle.lefthalf.filled" : "rectangle.righthalf.filled")
.padding(.leading, 16)
.padding(.leading, 16)
}
}

View file

@ -20,7 +20,7 @@ struct TimelineTab: View {
@State private var timeline: TimelineFilter
@State private var scrollToTopSignal: Int = 0
@AppStorage("last_timeline_filter") public var lastTimelineFilter: TimelineFilter = TimelineFilter.home
@AppStorage("last_timeline_filter") public var lastTimelineFilter: TimelineFilter = .home
private let canFilterTimeline: Bool
@ -45,10 +45,10 @@ struct TimelineTab: View {
routerPath.client = client
if !didAppear && canFilterTimeline {
didAppear = true
if(client.isAuth) {
if client.isAuth {
timeline = lastTimelineFilter
} else {
timeline = .federated
timeline = .federated
}
}
Task {
@ -58,18 +58,18 @@ struct TimelineTab: View {
routerPath.presentedSheet = .addAccount
}
}
.onChange(of: client.isAuth, perform: { isAuth in
if(client.isAuth) {
.onChange(of: client.isAuth, perform: { _ in
if client.isAuth {
timeline = lastTimelineFilter
} else {
timeline = .federated
timeline = .federated
}
})
.onChange(of: currentAccount.account?.id, perform: { _ in
if(client.isAuth && canFilterTimeline) {
if client.isAuth, canFilterTimeline {
timeline = lastTimelineFilter
} else {
timeline = .federated
timeline = .federated
}
})
.onChange(of: $popToRootTab.wrappedValue) { popToRootTab in
@ -85,7 +85,7 @@ struct TimelineTab: View {
routerPath.path = []
}
.onChange(of: timeline) { timeline in
if(timeline == .home || timeline == .federated || timeline == .local) {
if timeline == .home || timeline == .federated || timeline == .local {
lastTimelineFilter = timeline
}
}

View file

@ -283,8 +283,8 @@ public struct AccountDetailView: View {
ForEach(currentAccount.sortedLists) { list in
NavigationLink(value: RouterDestinations.list(list: list)) {
Text(list.title)
.font(.scaledHeadline)
.foregroundColor(theme.labelColor)
.font(.scaledHeadline)
.foregroundColor(theme.labelColor)
}
.listRowBackground(theme.primaryBackgroundColor)
.contextMenu {
@ -405,7 +405,7 @@ public struct AccountDetailView: View {
} else {
Menu {
ForEach(MutingDurations.allCases, id: \.rawValue) { duration in
Button (duration.description) {
Button(duration.description) {
Task {
do {
viewModel.relationship = try await client.post(endpoint: Accounts.mute(id: account.id, json: MuteData(duration: duration.rawValue)))

View file

@ -3,10 +3,10 @@ import SwiftUI
enum MutingDurations: Int, CaseIterable {
case infinite = 0
case fiveMinutes = 300
case thirtyMinutes = 1_800
case oneHour = 3_600
case sixHours = 21_600
case oneDay = 86_400
case thirtyMinutes = 1800
case oneHour = 3600
case sixHours = 21600
case oneDay = 86400
case threeDays = 259_200
case sevenDays = 604_800

View file

@ -1,7 +1,7 @@
import DesignSystem
import Models
import Network
import SwiftUI
import DesignSystem
@MainActor
public class AppAccountViewModel: ObservableObject {
@ -38,14 +38,15 @@ public class AppAccountViewModel: ObservableObject {
if let account {
if let image = Self.avatarsCache[account.id] {
self.roundedAvatar = image
roundedAvatar = image
} else if let (data, _) = try? await URLSession.shared.data(from: account.avatar),
let image = UIImage(data: data)?.roundedImage {
self.roundedAvatar = image
let image = UIImage(data: data)?.roundedImage
{
roundedAvatar = image
Self.avatarsCache[account.id] = image
}
}
} catch { }
} catch {}
}
}

View file

@ -17,7 +17,7 @@ class ConversationDetailViewModel: ObservableObject {
init(conversation: Conversation) {
self.conversation = conversation
messages = conversation.lastStatus != nil ? [conversation.lastStatus!] : []
messages = conversation.lastStatus != nil ? [conversation.lastStatus!] : []
}
func fetchMessages() async {

View file

@ -61,7 +61,7 @@ struct ConversationMessageView: View {
.padding(.trailing, isOwnMessage ? 0 : 24)
}
if message.id == String(conversation.lastStatus?.id ?? "") {
if message.id == String(conversation.lastStatus?.id ?? "") {
HStack {
if isOwnMessage {
Spacer()

View file

@ -1,16 +1,15 @@
import UIKit
extension UIImage{
public var roundedImage: UIImage? {
let rect = CGRect(origin:CGPoint(x: 0, y: 0), size: self.size)
UIGraphicsBeginImageContextWithOptions(self.size, false, 1)
public extension UIImage {
var roundedImage: UIImage? {
let rect = CGRect(origin: CGPoint(x: 0, y: 0), size: size)
UIGraphicsBeginImageContextWithOptions(size, false, 1)
defer { UIGraphicsEndImageContext() }
UIBezierPath(
roundedRect: rect,
cornerRadius: self.size.height
cornerRadius: size.height
).addClip()
self.draw(in: rect)
draw(in: rect)
return UIGraphicsGetImageFromCurrentImageContext()
}
}

View file

@ -21,7 +21,6 @@ public class CurrentInstance: ObservableObject {
return 0
}
public var isFiltersSupported: Bool {
version >= 4
}

View file

@ -1,6 +1,6 @@
import SwiftUI
public enum StatusAction : String, CaseIterable, Identifiable {
public enum StatusAction: String, CaseIterable, Identifiable {
public var id: String {
"\(rawValue)"
}

View file

@ -2,7 +2,7 @@ import Foundation
import SwiftSoup
import SwiftUI
fileprivate enum CodingKeys: CodingKey {
private enum CodingKeys: CodingKey {
case htmlValue, asMarkdown, asRawText, statusesURLs
}
@ -16,7 +16,7 @@ public struct HTMLString: Codable, Equatable, Hashable {
private var main_regex: NSRegularExpression?
private var underscore_regex: NSRegularExpression?
public init(from decoder: Decoder) {
var alreadyDecoded: Bool = false
var alreadyDecoded = false
do {
let container = try decoder.singleValueContainer()
htmlValue = try container.decode(String.self)
@ -77,7 +77,7 @@ public struct HTMLString: Codable, Equatable, Hashable {
}
}
public init(stringValue: String, parseMarkdown:Bool = false) {
public init(stringValue: String, parseMarkdown: Bool = false) {
htmlValue = stringValue
asMarkdown = stringValue
asRawText = stringValue
@ -91,8 +91,7 @@ public struct HTMLString: Codable, Equatable, Hashable {
} catch {
asSafeMarkdownAttributedString = AttributedString(stringLiteral: htmlValue)
}
}
else {
} else {
asSafeMarkdownAttributedString = AttributedString(stringLiteral: htmlValue)
}
}

View file

@ -1,6 +1,6 @@
import Foundation
fileprivate enum CodingKeys: CodingKey {
private enum CodingKeys: CodingKey {
case asDate
}
@ -39,7 +39,7 @@ public struct ServerDate: Codable, Hashable, Equatable {
}()
public init() {
asDate = Date()-100
asDate = Date() - 100
}
public init(from decoder: Decoder) throws {

View file

@ -54,14 +54,12 @@ public protocol AnyStatus {
var language: String? { get }
}
extension AnyStatus {
public var viewId: String {
get {
if let editedAt {
return "\(id)\(editedAt.asDate.description)"
}
return id
public extension AnyStatus {
var viewId: String {
if let editedAt {
return "\(id)\(editedAt.asDate.description)"
}
return id
}
}
@ -107,37 +105,36 @@ public struct Status: AnyStatus, Codable, Identifiable, Equatable, Hashable, Sta
public let sensitive: Bool
public let language: String?
public static func placeholder(forSettings:Bool = false, language:String? = nil) -> Status {
public static func placeholder(forSettings: Bool = false, language: String? = nil) -> Status {
.init(id: UUID().uuidString,
content: .init(stringValue: "Lorem ipsum [#dolor](#) sit amet\nconsectetur [@adipiscing](#) elit\nAsed do eiusmod tempor incididunt ut labore.", parseMarkdown: forSettings),
content: .init(stringValue: "Lorem ipsum [#dolor](#) sit amet\nconsectetur [@adipiscing](#) elit\nAsed do eiusmod tempor incididunt ut labore.", parseMarkdown: forSettings),
account: .placeholder(),
createdAt: ServerDate(),
editedAt: nil,
reblog: nil,
mediaAttachments: [],
mentions: [],
repliesCount: 0,
reblogsCount: 0,
favouritesCount: 0,
card: nil,
favourited: false,
reblogged: false,
pinned: false,
bookmarked: false,
emojis: [],
url: "https://example.com",
application: nil,
inReplyToAccountId: nil,
visibility: .pub,
poll: nil,
spoilerText: .init(stringValue: ""),
filtered: [],
sensitive: false,
language: language)
account: .placeholder(),
createdAt: ServerDate(),
editedAt: nil,
reblog: nil,
mediaAttachments: [],
mentions: [],
repliesCount: 0,
reblogsCount: 0,
favouritesCount: 0,
card: nil,
favourited: false,
reblogged: false,
pinned: false,
bookmarked: false,
emojis: [],
url: "https://example.com",
application: nil,
inReplyToAccountId: nil,
visibility: .pub,
poll: nil,
spoilerText: .init(stringValue: ""),
filtered: [],
sensitive: false,
language: language)
}
public static func placeholders() -> [Status] {
[.placeholder(), .placeholder(), .placeholder(), .placeholder(), .placeholder()]
}

View file

@ -112,7 +112,7 @@ public struct StatusData: Encodable {
public let thumbnail: String?
public let focus: String?
public init(id: String, description: String?, thumbnail: String?, focus: String?) {
public init(id: String, description: String?, thumbnail: String?, focus: String?) {
self.id = id
self.description = description
self.thumbnail = thumbnail

View file

@ -98,8 +98,8 @@ public struct NotificationsListView: View {
EmptyView(iconName: "bell.slash",
title: "notifications.empty.title",
message: "notifications.empty.message")
.listRowBackground(theme.primaryBackgroundColor)
.listSectionSeparator(.hidden)
.listRowBackground(theme.primaryBackgroundColor)
.listSectionSeparator(.hidden)
} else {
ForEach(notifications) { notification in
NotificationRowView(notification: notification)

View file

@ -32,6 +32,7 @@ class NotificationsViewModel: ObservableObject {
}
}
}
var currentAccount: CurrentAccount?
@Published var state: State = .loading
@ -100,10 +101,10 @@ class NotificationsViewModel: ObservableObject {
var latestMinId = minId
do {
while let newNotifications: [Models.Notification] =
try await client.get(endpoint: Notifications.notifications(minId: latestMinId,
maxId: nil,
types: queryTypes,
limit: Constants.notificationLimit)),
try await client.get(endpoint: Notifications.notifications(minId: latestMinId,
maxId: nil,
types: queryTypes,
limit: Constants.notificationLimit)),
!newNotifications.isEmpty,
pagesLoaded < maxPages
{

View file

@ -4,7 +4,6 @@ import Models
import Network
import Shimmer
import SwiftUI
import DesignSystem
public struct StatusDetailView: View {
@EnvironmentObject private var theme: Theme
@ -111,15 +110,15 @@ public struct StatusDetailView: View {
StatusRowView(viewModel: .init(status: status,
isCompact: false,
isFocused: true))
.overlay {
GeometryReader { reader in
VStack{}
.onAppear {
statusHeight = reader.size.height
.overlay {
GeometryReader { reader in
VStack {}
.onAppear {
statusHeight = reader.size.height
}
}
}
}
.id(status.id)
.id(status.id)
}
private var errorView: some View {

View file

@ -78,7 +78,7 @@ class StatusDetailViewModel: ObservableObject {
state = .display(status: data.status, context: data.context, date: Date())
}
} else {
state = .display(status: data.status, context: data.context,date: Date())
state = .display(status: data.status, context: data.context, date: Date())
scrollToId = statusId
}
} catch {

View file

@ -33,7 +33,7 @@ struct StatusEditorAccessoryView: View {
Image(systemName: "photo.fill.on.rectangle.fill")
}
}
.accessibilityLabel("accessibility.editor.button.attach-photo")
.accessibilityLabel("accessibility.editor.button.attach-photo")
.disabled(viewModel.showPoll)
Button {
@ -85,7 +85,7 @@ struct StatusEditorAccessoryView: View {
}
.accessibilityLabel("accessibility.editor.button.language")
if preferences.isOpenAIEnabled {
if preferences.isOpenAIEnabled {
AIMenu.disabled(!viewModel.canPost)
}
}

View file

@ -54,12 +54,14 @@ enum StatusEditorUTTypeSupported: String, CaseIterable {
if self == .jpeg || self == .png || self == .tiff || self == .image {
if let imageURL = result as? URL,
let data = try? Data(contentsOf: imageURL),
let image = UIImage(data: data) {
let image = UIImage(data: data)
{
return image
} else if let data = result as? Data,
let image = UIImage(data: data) {
let image = UIImage(data: data)
{
return image
} else if let transferable = await getImageTansferable(item: item){
} else if let transferable = await getImageTansferable(item: item) {
return transferable
}
}
@ -139,7 +141,7 @@ struct MovieFileTranseferable: Transferable {
FileRepresentation(contentType: .movie) { movie in
SentTransferredFile(movie.url)
} importing: { received in
return Self(url: localURLFor(received: received))
Self(url: localURLFor(received: received))
}
}
}
@ -155,7 +157,7 @@ struct ImageFileTranseferable: Transferable {
FileRepresentation(contentType: .image) { image in
SentTransferredFile(image.url)
} importing: { received in
return Self(url: localURLFor(received: received))
Self(url: localURLFor(received: received))
}
}
}
@ -171,12 +173,12 @@ struct GifFileTranseferable: Transferable {
FileRepresentation(contentType: .gif) { gif in
SentTransferredFile(gif.url)
} importing: { received in
return Self(url: localURLFor(received: received))
Self(url: localURLFor(received: received))
}
}
}
fileprivate func localURLFor(received: ReceivedTransferredFile) -> URL {
private func localURLFor(received: ReceivedTransferredFile) -> URL {
let copy = URL.temporaryDirectory.appending(path: "\(UUID().uuidString).\(received.file.pathExtension)")
try? FileManager.default.copyItem(at: received.file, to: copy)
return copy

View file

@ -37,11 +37,11 @@ public struct StatusEditorView: View {
.padding(.horizontal, .layoutPadding)
TextView($viewModel.statusText,
getTextView: { textView in
viewModel.textView = textView
})
.placeholder(String(localized: "status.editor.text.placeholder"))
.setKeyboardType(preferences.isSocialKeyboardEnabled ? .twitter : .default)
.padding(.horizontal, .layoutPadding)
viewModel.textView = textView
})
.placeholder(String(localized: "status.editor.text.placeholder"))
.setKeyboardType(preferences.isSocialKeyboardEnabled ? .twitter : .default)
.padding(.horizontal, .layoutPadding)
StatusEditorMediaView(viewModel: viewModel)
if let status = viewModel.embeddedStatus {
StatusEmbeddedView(status: status)

View file

@ -34,12 +34,10 @@ public class StatusEditorViewModel: NSObject, ObservableObject {
}
var markedTextRange: UITextRange? {
get {
guard let textView else {
return nil
}
return textView.markedTextRange
guard let textView else {
return nil
}
return textView.markedTextRange
}
@Published var statusText = NSMutableAttributedString(string: "") {
@ -372,7 +370,8 @@ public class StatusEditorViewModel: NSObject, ObservableObject {
mediaAttachment: nil,
error: nil))
} else if var content = content as? ImageFileTranseferable,
let image = content.image {
let image = content.image
{
mediasImages.append(.init(image: image,
movieTransferable: nil,
gifTransferable: nil,
@ -682,6 +681,7 @@ public class StatusEditorViewModel: NSObject, ObservableObject {
}
// MARK: - Custom emojis
func fetchCustomEmojis() async {
guard let client else { return }
do {
@ -690,7 +690,8 @@ public class StatusEditorViewModel: NSObject, ObservableObject {
}
}
//MARK: - DropDelegate
// MARK: - DropDelegate
extension StatusEditorViewModel: DropDelegate {
public func performDrop(info: DropInfo) -> Bool {
let item = info.itemProviders(for: StatusEditorUTTypeSupported.types())
@ -700,17 +701,20 @@ extension StatusEditorViewModel: DropDelegate {
}
// MARK: - UITextPasteDelegate
extension StatusEditorViewModel: UITextPasteDelegate {
public func textPasteConfigurationSupporting(
_ textPasteConfigurationSupporting: UITextPasteConfigurationSupporting,
transform item: UITextPasteItem) {
if !item.itemProvider.registeredContentTypes(conformingTo: .image).isEmpty ||
!item.itemProvider.registeredContentTypes(conformingTo: .video).isEmpty ||
!item.itemProvider.registeredContentTypes(conformingTo: .gif).isEmpty {
processItemsProvider(items: [item.itemProvider])
item.setNoResult()
} else {
item.setDefaultResult()
}
_: UITextPasteConfigurationSupporting,
transform item: UITextPasteItem
) {
if !item.itemProvider.registeredContentTypes(conformingTo: .image).isEmpty ||
!item.itemProvider.registeredContentTypes(conformingTo: .video).isEmpty ||
!item.itemProvider.registeredContentTypes(conformingTo: .gif).isEmpty
{
processItemsProvider(items: [item.itemProvider])
item.setNoResult()
} else {
item.setDefaultResult()
}
}
}

View file

@ -1,9 +1,8 @@
import SwiftUI
import DesignSystem
import SwiftUI
extension TextView.Representable {
final class Coordinator: NSObject, UITextViewDelegate {
internal let textView: UIKitTextView
private var originalText: NSMutableAttributedString = .init()
@ -16,8 +15,8 @@ extension TextView.Representable {
init(text: Binding<NSMutableAttributedString>,
calculatedHeight: Binding<CGFloat>,
getTextView: ((UITextView) -> Void)?
) {
getTextView: ((UITextView) -> Void)?)
{
textView = UIKitTextView()
textView.backgroundColor = .clear
textView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
@ -47,7 +46,7 @@ extension TextView.Representable {
self.getTextView?(textView)
}
func textViewDidBeginEditing(_ textView: UITextView) {
func textViewDidBeginEditing(_: UITextView) {
originalText = text.wrappedValue
DispatchQueue.main.async {
self.recalculateHeight()
@ -61,15 +60,13 @@ extension TextView.Representable {
}
}
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
func textView(_: UITextView, shouldChangeTextIn _: NSRange, replacementText _: String) -> Bool {
return true
}
}
}
extension TextView.Representable.Coordinator {
func update(representable: TextView.Representable) {
textView.keyboardType = representable.keyboard
recalculateHeight()
@ -84,5 +81,4 @@ extension TextView.Representable.Coordinator {
self.calculatedHeight.wrappedValue = newSize.height
}
}
}

View file

@ -1,7 +1,6 @@
import SwiftUI
public extension TextView {
/// Specify a placeholder text
/// - Parameter placeholder: The placeholder text
func placeholder(_ placeholder: String) -> TextView {
@ -35,5 +34,4 @@ public extension TextView {
view.keyboard = keyboardType
return view
}
}

View file

@ -2,7 +2,6 @@ import SwiftUI
extension TextView {
struct Representable: UIViewRepresentable {
@Binding var text: NSMutableAttributedString
@Binding var calculatedHeight: CGFloat
@ -13,7 +12,7 @@ extension TextView {
context.coordinator.textView
}
func updateUIView(_ view: UIKitTextView, context: Context) {
func updateUIView(_: UIKitTextView, context: Context) {
context.coordinator.update(representable: self)
if !context.coordinator.didBecomeFirstResponder {
context.coordinator.textView.becomeFirstResponder()
@ -28,7 +27,5 @@ extension TextView {
getTextView: getTextView
)
}
}
}

View file

@ -1,9 +1,8 @@
import SwiftUI
import DesignSystem
import SwiftUI
/// A SwiftUI TextView implementation that supports both scrolling and auto-sizing layouts
public struct TextView: View {
@Environment(\.layoutDirection) private var layoutDirection
@Binding private var text: NSMutableAttributedString
@ -20,8 +19,8 @@ public struct TextView: View {
/// - Parameters:
/// - text: A binding to the attributed text
public init(_ text: Binding<NSMutableAttributedString>,
getTextView: ((UITextView) -> Void)? = nil
) {
getTextView: ((UITextView) -> Void)? = nil)
{
_text = text
_isEmpty = Binding(
get: { text.wrappedValue.string.isEmpty },
@ -53,19 +52,16 @@ public struct TextView: View {
alignment: .topLeading
)
}
}
final class UIKitTextView: UITextView {
override var keyCommands: [UIKeyCommand]? {
return (super.keyCommands ?? []) + [
UIKeyCommand(input: UIKeyCommand.inputEscape, modifierFlags: [], action: #selector(escape(_:)))
UIKeyCommand(input: UIKeyCommand.inputEscape, modifierFlags: [], action: #selector(escape(_:))),
]
}
@objc private func escape(_ sender: Any) {
@objc private func escape(_: Any) {
resignFirstResponder()
}
}

View file

@ -37,7 +37,8 @@ public struct StatusPollView: View {
private func isSelected(option: Poll.Option) -> Bool {
if let optionIndex = viewModel.poll.options.firstIndex(where: { $0.id == option.id }),
let _ = viewModel.votes.firstIndex(of: optionIndex) {
let _ = viewModel.votes.firstIndex(of: optionIndex)
{
return true
}
return false

View file

@ -83,7 +83,8 @@ struct StatusRowContextMenu: View {
}
} label: {
if let statusLang = viewModel.status.language,
let languageName = Locale.current.localizedString(forLanguageCode: statusLang) {
let languageName = Locale.current.localizedString(forLanguageCode: statusLang)
{
Label("status.action.translate-from-\(languageName)", systemImage: "captions.bubble")
} else {
Label("status.action.translate", systemImage: "captions.bubble")
@ -113,8 +114,7 @@ struct StatusRowContextMenu: View {
}
Button(role: .destructive,
action: { viewModel.showDeleteAlert = true },
label: { Label("status.action.delete", systemImage: "trash") }
)
label: { Label("status.action.delete", systemImage: "trash") })
}
} else if !viewModel.isRemote {
Section(viewModel.status.account.acct) {

View file

@ -1,7 +1,7 @@
import SwiftUI
import Env
import DesignSystem
import Env
import Models
import SwiftUI
struct StatusRowDetailView: View {
@Environment(\.openURL) private var openURL
@ -96,5 +96,4 @@ struct StatusRowDetailView: View {
.padding(.leading, .layoutPadding)
}
}
}

View file

@ -118,12 +118,14 @@ public struct StatusRowView: View {
title: Text("status.action.delete.confirm.title"),
message: Text("status.action.delete.confirm.message"),
primaryButton: .destructive(
Text("status.action.delete")) {
Task {
await viewModel.delete()
}
},
secondaryButton: .cancel())
Text("status.action.delete"))
{
Task {
await viewModel.delete()
}
},
secondaryButton: .cancel()
)
})
.alignmentGuide(.listRowSeparatorLeading) { _ in
-100
@ -500,7 +502,7 @@ public struct StatusRowView: View {
await viewModel.unbookmark()
} else {
await
viewModel.bookmark()
viewModel.bookmark()
}
}
case .none:
@ -522,7 +524,7 @@ public struct StatusRowView: View {
}
@ViewBuilder
private func makeSwipeButtonForTask(action: StatusAction, task: @escaping () async -> Void ) -> some View {
private func makeSwipeButtonForTask(action: StatusAction, task: @escaping () async -> Void) -> some View {
Button {
Task {
HapticManager.shared.fireHaptic(of: .notification(.success))

View file

@ -42,7 +42,6 @@ public class StatusRowViewModel: ObservableObject {
}
var highlightRowColor: Color {
if status.visibility == .direct {
return theme.tintColor.opacity(0.15)
} else if status.userMentioned != nil {
@ -271,7 +270,7 @@ public class StatusRowViewModel: ObservableObject {
do {
favoriters = try await client.get(endpoint: Statuses.favoritedBy(id: status.id, maxId: nil))
rebloggers = try await client.get(endpoint: Statuses.rebloggedBy(id: status.id, maxId: nil))
} catch { }
} catch {}
}
private func updateFromStatus(status: Status) {

View file

@ -196,7 +196,7 @@ extension TimelineFilter: Codable {
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
var container = encoder.container(keyedBy: CodingKeys.self)
switch self {
case .home:
try container.encode(CodingKeys.home.rawValue, forKey: .home)
@ -206,13 +206,13 @@ extension TimelineFilter: Codable {
try container.encode(CodingKeys.federated.rawValue, forKey: .federated)
case .trending:
try container.encode(CodingKeys.trending.rawValue, forKey: .trending)
case .hashtag(let tag, let accountId):
case let .hashtag(tag, accountId):
var nestedContainer = container.nestedUnkeyedContainer(forKey: .hashtag)
try nestedContainer.encode(tag)
try nestedContainer.encode(accountId)
case .list(let list):
case let .list(list):
try container.encode(list, forKey: .list)
case .remoteLocal(let server, let filter):
case let .remoteLocal(server, filter):
var nestedContainer = container.nestedUnkeyedContainer(forKey: .hashtag)
try nestedContainer.encode(server)
try nestedContainer.encode(filter)
@ -260,17 +260,17 @@ extension RemoteTimelineFilter: Codable {
case .trending:
self = .trending
default:
throw DecodingError.dataCorrupted(
DecodingError.Context(
codingPath: container.codingPath,
debugDescription: "Unabled to decode enum."
)
throw DecodingError.dataCorrupted(
DecodingError.Context(
codingPath: container.codingPath,
debugDescription: "Unabled to decode enum."
)
)
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
var container = encoder.container(keyedBy: CodingKeys.self)
switch self {
case .local:
try container.encode(CodingKeys.local.rawValue, forKey: .local)

View file

@ -65,7 +65,8 @@ public struct TimelineView: View {
if let collectionView,
let index,
let rows = collectionView.dataSource?.collectionView(collectionView, numberOfItemsInSection: 0),
rows > index {
rows > index
{
collectionView.scrollToItem(at: .init(row: index, section: 0),
at: .top,
animated: viewModel.scrollToIndexAnimated)