mirror of
https://github.com/Dimillian/IceCubesApp.git
synced 2024-12-24 16:10:38 +00:00
Swiftformat
This commit is contained in:
parent
9fd1b4ef73
commit
eb6050a38f
48 changed files with 304 additions and 314 deletions
|
@ -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
|
||||
|
|
|
@ -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,7 +28,7 @@ struct SwipeActionsSettingsView: View {
|
|||
}
|
||||
Section {
|
||||
ForEach(StatusAction.allCases) { action in
|
||||
if (action != .none) {
|
||||
if action != .none {
|
||||
Label(action.displayName(), systemImage: action.iconName()).tag(action)
|
||||
}
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ struct SwipeActionsSettingsView: View {
|
|||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,7 +45,7 @@ struct TimelineTab: View {
|
|||
routerPath.client = client
|
||||
if !didAppear && canFilterTimeline {
|
||||
didAppear = true
|
||||
if(client.isAuth) {
|
||||
if client.isAuth {
|
||||
timeline = lastTimelineFilter
|
||||
} else {
|
||||
timeline = .federated
|
||||
|
@ -58,15 +58,15 @@ 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
|
||||
}
|
||||
})
|
||||
.onChange(of: currentAccount.account?.id, perform: { _ in
|
||||
if(client.isAuth && canFilterTimeline) {
|
||||
if client.isAuth, canFilterTimeline {
|
||||
timeline = lastTimelineFilter
|
||||
} else {
|
||||
timeline = .federated
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import DesignSystem
|
||||
import Models
|
||||
import Network
|
||||
import SwiftUI
|
||||
import DesignSystem
|
||||
|
||||
@MainActor
|
||||
public class AppAccountViewModel: ObservableObject {
|
||||
|
@ -38,10 +38,11 @@ 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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@ public class CurrentInstance: ObservableObject {
|
|||
return 0
|
||||
}
|
||||
|
||||
|
||||
public var isFiltersSupported: Bool {
|
||||
version >= 4
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
@ -91,8 +91,7 @@ public struct HTMLString: Codable, Equatable, Hashable {
|
|||
} catch {
|
||||
asSafeMarkdownAttributedString = AttributedString(stringLiteral: htmlValue)
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
asSafeMarkdownAttributedString = AttributedString(stringLiteral: htmlValue)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import Foundation
|
||||
|
||||
fileprivate enum CodingKeys: CodingKey {
|
||||
private enum CodingKeys: CodingKey {
|
||||
case asDate
|
||||
}
|
||||
|
||||
|
|
|
@ -54,16 +54,14 @@ public protocol AnyStatus {
|
|||
var language: String? { get }
|
||||
}
|
||||
|
||||
extension AnyStatus {
|
||||
public var viewId: String {
|
||||
get {
|
||||
public extension AnyStatus {
|
||||
var viewId: String {
|
||||
if let editedAt {
|
||||
return "\(id)\(editedAt.asDate.description)"
|
||||
}
|
||||
return id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protocol StatusUI {
|
||||
var userMentioned: Bool? { get set }
|
||||
|
@ -137,7 +135,6 @@ public struct Status: AnyStatus, Codable, Identifiable, Equatable, Hashable, Sta
|
|||
language: language)
|
||||
}
|
||||
|
||||
|
||||
public static func placeholders() -> [Status] {
|
||||
[.placeholder(), .placeholder(), .placeholder(), .placeholder(), .placeholder()]
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ class NotificationsViewModel: ObservableObject {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
var currentAccount: CurrentAccount?
|
||||
|
||||
@Published var state: State = .loading
|
||||
|
|
|
@ -4,7 +4,6 @@ import Models
|
|||
import Network
|
||||
import Shimmer
|
||||
import SwiftUI
|
||||
import DesignSystem
|
||||
|
||||
public struct StatusDetailView: View {
|
||||
@EnvironmentObject private var theme: Theme
|
||||
|
|
|
@ -54,10 +54,12 @@ 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) {
|
||||
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
|
||||
|
|
|
@ -34,13 +34,11 @@ public class StatusEditorViewModel: NSObject, ObservableObject {
|
|||
}
|
||||
|
||||
var markedTextRange: UITextRange? {
|
||||
get {
|
||||
guard let textView else {
|
||||
return nil
|
||||
}
|
||||
return textView.markedTextRange
|
||||
}
|
||||
}
|
||||
|
||||
@Published var statusText = NSMutableAttributedString(string: "") {
|
||||
didSet {
|
||||
|
@ -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 {
|
||||
|
@ -691,6 +691,7 @@ public class StatusEditorViewModel: NSObject, ObservableObject {
|
|||
}
|
||||
|
||||
// MARK: - DropDelegate
|
||||
|
||||
extension StatusEditorViewModel: DropDelegate {
|
||||
public func performDrop(info: DropInfo) -> Bool {
|
||||
let item = info.itemProviders(for: StatusEditorUTTypeSupported.types())
|
||||
|
@ -700,13 +701,16 @@ extension StatusEditorViewModel: DropDelegate {
|
|||
}
|
||||
|
||||
// MARK: - UITextPasteDelegate
|
||||
|
||||
extension StatusEditorViewModel: UITextPasteDelegate {
|
||||
public func textPasteConfigurationSupporting(
|
||||
_ textPasteConfigurationSupporting: UITextPasteConfigurationSupporting,
|
||||
transform item: UITextPasteItem) {
|
||||
_: UITextPasteConfigurationSupporting,
|
||||
transform item: UITextPasteItem
|
||||
) {
|
||||
if !item.itemProvider.registeredContentTypes(conformingTo: .image).isEmpty ||
|
||||
!item.itemProvider.registeredContentTypes(conformingTo: .video).isEmpty ||
|
||||
!item.itemProvider.registeredContentTypes(conformingTo: .gif).isEmpty {
|
||||
!item.itemProvider.registeredContentTypes(conformingTo: .gif).isEmpty
|
||||
{
|
||||
processItemsProvider(items: [item.itemProvider])
|
||||
item.setNoResult()
|
||||
} else {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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")) {
|
||||
Text("status.action.delete"))
|
||||
{
|
||||
Task {
|
||||
await viewModel.delete()
|
||||
}
|
||||
},
|
||||
secondaryButton: .cancel())
|
||||
secondaryButton: .cancel()
|
||||
)
|
||||
})
|
||||
.alignmentGuide(.listRowSeparatorLeading) { _ in
|
||||
-100
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue