mirror of
https://github.com/Dimillian/IceCubesApp.git
synced 2025-01-23 06:18:08 +00:00
Swiftformat
This commit is contained in:
parent
06629cc397
commit
83e4e74329
22 changed files with 171 additions and 169 deletions
|
@ -46,7 +46,7 @@ public struct InstanceInfoSection: View {
|
|||
.listRowBackground(theme.primaryBackgroundColor)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private func format(_ int: Int) -> String {
|
||||
let formatter = NumberFormatter()
|
||||
formatter.numberStyle = .decimal
|
||||
|
|
|
@ -5,9 +5,9 @@ import Env
|
|||
import Foundation
|
||||
import Models
|
||||
import Network
|
||||
import Nuke
|
||||
import SwiftUI
|
||||
import Timeline
|
||||
import Nuke
|
||||
|
||||
struct SettingsTabs: View {
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
@ -275,7 +275,7 @@ struct SettingsTabs: View {
|
|||
.scrollContentBackground(.hidden)
|
||||
.background(theme.secondaryBackgroundColor)
|
||||
}
|
||||
|
||||
|
||||
private var cacheSection: some View {
|
||||
Section("settings.section.cache") {
|
||||
if cachedRemoved {
|
||||
|
|
|
@ -61,10 +61,10 @@ public struct AccountsListRow: View {
|
|||
let relationShip = viewModel.relationShip
|
||||
{
|
||||
VStack(alignment: .center) {
|
||||
FollowButton(viewModel: .init(accountId: viewModel.account.id,
|
||||
relationship: relationShip,
|
||||
shouldDisplayNotify: false,
|
||||
relationshipUpdated: { _ in }))
|
||||
FollowButton(viewModel: .init(accountId: viewModel.account.id,
|
||||
relationship: relationShip,
|
||||
shouldDisplayNotify: false,
|
||||
relationshipUpdated: { _ in }))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,7 +100,7 @@ public struct EditAccountView: View {
|
|||
}
|
||||
.listRowBackground(theme.primaryBackgroundColor)
|
||||
}
|
||||
|
||||
|
||||
private var fieldsSection: some View {
|
||||
Section("account.edit.metadata-section-title") {
|
||||
ForEach($viewModel.fields) { $field in
|
||||
|
|
|
@ -4,18 +4,17 @@ import SwiftUI
|
|||
|
||||
@MainActor
|
||||
class EditAccountViewModel: ObservableObject {
|
||||
|
||||
class FieldEditViewModel: ObservableObject, Identifiable {
|
||||
let id = UUID().uuidString
|
||||
@Published var name: String = ""
|
||||
@Published var value: String = ""
|
||||
|
||||
|
||||
init(name: String, value: String) {
|
||||
self.name = name
|
||||
self.value = value
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public var client: Client?
|
||||
|
||||
@Published var displayName: String = ""
|
||||
|
@ -44,7 +43,7 @@ class EditAccountViewModel: ObservableObject {
|
|||
isBot = account.bot
|
||||
isLocked = account.locked
|
||||
isDiscoverable = account.discoverable ?? false
|
||||
fields = account.source?.fields.map{ .init(name: $0.name, value: $0.value.asRawText) } ?? []
|
||||
fields = account.source?.fields.map { .init(name: $0.name, value: $0.value.asRawText) } ?? []
|
||||
withAnimation {
|
||||
isLoading = false
|
||||
}
|
||||
|
@ -60,7 +59,7 @@ class EditAccountViewModel: ObservableObject {
|
|||
bot: isBot,
|
||||
locked: isLocked,
|
||||
discoverable: isDiscoverable,
|
||||
fieldsAttributes: fields.map{ .init(name: $0.name, value: $0.value)})
|
||||
fieldsAttributes: fields.map { .init(name: $0.name, value: $0.value) })
|
||||
let response = try await client?.patch(endpoint: Accounts.updateCredentials(json: data))
|
||||
if response?.statusCode != 200 {
|
||||
saveError = true
|
||||
|
|
|
@ -13,13 +13,13 @@ public struct AppAccountsSelectorView: View {
|
|||
|
||||
private let accountCreationEnabled: Bool
|
||||
private let avatarSize: AvatarView.Size
|
||||
|
||||
|
||||
var showNotificationBadge: Bool {
|
||||
accountsViewModel
|
||||
.filter { $0.account?.id != currentAccount.account?.id }
|
||||
.compactMap{ $0.appAccount.oauthToken }
|
||||
.map{ preferences.getNotificationsCount(for: $0) }
|
||||
.reduce(0, +) > 0
|
||||
.filter { $0.account?.id != currentAccount.account?.id }
|
||||
.compactMap { $0.appAccount.oauthToken }
|
||||
.map { preferences.getNotificationsCount(for: $0) }
|
||||
.reduce(0, +) > 0
|
||||
}
|
||||
|
||||
public init(routerPath: RouterPath,
|
||||
|
|
|
@ -117,22 +117,22 @@ struct ConversationMessageView: View {
|
|||
Label(isLiked ? "status.action.unfavorite" : "status.action.favorite",
|
||||
systemImage: isLiked ? "star.fill" : "star")
|
||||
}
|
||||
Button { Task {
|
||||
do {
|
||||
let status: Status
|
||||
if isBookmarked {
|
||||
status = try await client.post(endpoint: Statuses.unbookmark(id: message.id))
|
||||
} else {
|
||||
status = try await client.post(endpoint: Statuses.bookmark(id: message.id))
|
||||
}
|
||||
withAnimation {
|
||||
isBookmarked = status.bookmarked == true
|
||||
}
|
||||
} catch {}
|
||||
} } label: {
|
||||
Label(isBookmarked ? "status.action.unbookmark" : "status.action.bookmark",
|
||||
systemImage: isBookmarked ? "bookmark.fill" : "bookmark")
|
||||
Button { Task {
|
||||
do {
|
||||
let status: Status
|
||||
if isBookmarked {
|
||||
status = try await client.post(endpoint: Statuses.unbookmark(id: message.id))
|
||||
} else {
|
||||
status = try await client.post(endpoint: Statuses.bookmark(id: message.id))
|
||||
}
|
||||
withAnimation {
|
||||
isBookmarked = status.bookmarked == true
|
||||
}
|
||||
} catch {}
|
||||
} } label: {
|
||||
Label(isBookmarked ? "status.action.unbookmark" : "status.action.bookmark",
|
||||
systemImage: isBookmarked ? "bookmark.fill" : "bookmark")
|
||||
}
|
||||
Divider()
|
||||
if message.account.id == currentAccount.account?.id {
|
||||
Button("status.action.delete", role: .destructive) {
|
||||
|
@ -141,13 +141,13 @@ struct ConversationMessageView: View {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
Section(message.reblog?.account.acct ?? message.account.acct) {
|
||||
Button {
|
||||
routerPath.presentedSheet = .mentionStatusEditor(account: message.reblog?.account ?? message.account, visibility: .pub)
|
||||
} label: {
|
||||
Label("status.action.mention", systemImage: "at")
|
||||
}
|
||||
Section(message.reblog?.account.acct ?? message.account.acct) {
|
||||
Button {
|
||||
routerPath.presentedSheet = .mentionStatusEditor(account: message.reblog?.account ?? message.account, visibility: .pub)
|
||||
} label: {
|
||||
Label("status.action.mention", systemImage: "at")
|
||||
}
|
||||
}
|
||||
Section {
|
||||
Button(role: .destructive) {
|
||||
routerPath.presentedSheet = .report(status: message.reblogAsAsStatus ?? message)
|
||||
|
|
|
@ -10,7 +10,7 @@ struct ConversationsListRow: View {
|
|||
@EnvironmentObject private var routerPath: RouterPath
|
||||
@EnvironmentObject private var theme: Theme
|
||||
@EnvironmentObject private var currentAccount: CurrentAccount
|
||||
|
||||
|
||||
@Binding var conversation: Conversation
|
||||
@ObservedObject var viewModel: ConversationsListViewModel
|
||||
|
||||
|
@ -92,34 +92,34 @@ struct ConversationsListRow: View {
|
|||
Label("conversations.action.mark-read", systemImage: "eye")
|
||||
}
|
||||
|
||||
if let message = conversation.lastStatus {
|
||||
Section("conversations.latest.message") {
|
||||
Button {
|
||||
UIPasteboard.general.string = message.content.asRawText
|
||||
} label: {
|
||||
Label("status.action.copy-text", systemImage: "doc.on.doc")
|
||||
}
|
||||
likeAndBookmark
|
||||
}
|
||||
Divider()
|
||||
if message.account.id != currentAccount.account?.id {
|
||||
Section(message.reblog?.account.acct ?? message.account.acct) {
|
||||
Button {
|
||||
routerPath.presentedSheet = .mentionStatusEditor(account: message.reblog?.account ?? message.account, visibility: .pub)
|
||||
} label: {
|
||||
Label("status.action.mention", systemImage: "at")
|
||||
}
|
||||
}
|
||||
Section {
|
||||
Button(role: .destructive) {
|
||||
routerPath.presentedSheet = .report(status: message.reblogAsAsStatus ?? message)
|
||||
} label: {
|
||||
Label("status.action.report", systemImage: "exclamationmark.bubble")
|
||||
}
|
||||
}
|
||||
}
|
||||
if let message = conversation.lastStatus {
|
||||
Section("conversations.latest.message") {
|
||||
Button {
|
||||
UIPasteboard.general.string = message.content.asRawText
|
||||
} label: {
|
||||
Label("status.action.copy-text", systemImage: "doc.on.doc")
|
||||
}
|
||||
likeAndBookmark
|
||||
}
|
||||
|
||||
Divider()
|
||||
if message.account.id != currentAccount.account?.id {
|
||||
Section(message.reblog?.account.acct ?? message.account.acct) {
|
||||
Button {
|
||||
routerPath.presentedSheet = .mentionStatusEditor(account: message.reblog?.account ?? message.account, visibility: .pub)
|
||||
} label: {
|
||||
Label("status.action.mention", systemImage: "at")
|
||||
}
|
||||
}
|
||||
Section {
|
||||
Button(role: .destructive) {
|
||||
routerPath.presentedSheet = .report(status: message.reblogAsAsStatus ?? message)
|
||||
} label: {
|
||||
Label("status.action.report", systemImage: "exclamationmark.bubble")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button(role: .destructive) {
|
||||
Task {
|
||||
await viewModel.delete(conversation: conversation)
|
||||
|
@ -132,20 +132,20 @@ struct ConversationsListRow: View {
|
|||
@ViewBuilder
|
||||
private var likeAndBookmark: some View {
|
||||
Button {
|
||||
Task {
|
||||
await viewModel.favorite(conversation: conversation)
|
||||
}
|
||||
Task {
|
||||
await viewModel.favorite(conversation: conversation)
|
||||
}
|
||||
} label: {
|
||||
Label(conversation.lastStatus?.favourited ?? false ? "status.action.unfavorite" : "status.action.favorite",
|
||||
systemImage: conversation.lastStatus?.favourited ?? false ? "star.fill" : "star")
|
||||
systemImage: conversation.lastStatus?.favourited ?? false ? "star.fill" : "star")
|
||||
}
|
||||
Button {
|
||||
Task {
|
||||
await viewModel.bookmark(conversation: conversation)
|
||||
}
|
||||
Task {
|
||||
await viewModel.bookmark(conversation: conversation)
|
||||
}
|
||||
} label: {
|
||||
Label(conversation.lastStatus?.bookmarked ?? false ? "status.action.unbookmark" : "status.action.bookmark",
|
||||
systemImage: conversation.lastStatus?.bookmarked ?? false ? "bookmark.fill" : "bookmark")
|
||||
Label(conversation.lastStatus?.bookmarked ?? false ? "status.action.unbookmark" : "status.action.bookmark",
|
||||
systemImage: conversation.lastStatus?.bookmarked ?? false ? "bookmark.fill" : "bookmark")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,30 +16,30 @@ public struct ConversationsListView: View {
|
|||
|
||||
public init() {}
|
||||
|
||||
private var conversations: Binding<[Conversation]> {
|
||||
if viewModel.isLoadingFirstPage {
|
||||
return Binding.constant(Conversation.placeholders())
|
||||
} else {
|
||||
return $viewModel.conversations
|
||||
}
|
||||
private var conversations: Binding<[Conversation]> {
|
||||
if viewModel.isLoadingFirstPage {
|
||||
return Binding.constant(Conversation.placeholders())
|
||||
} else {
|
||||
return $viewModel.conversations
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public var body: some View {
|
||||
ScrollView {
|
||||
LazyVStack {
|
||||
Group {
|
||||
if !conversations.isEmpty || viewModel.isLoadingFirstPage {
|
||||
ForEach(conversations) { $conversation in
|
||||
if viewModel.isLoadingFirstPage {
|
||||
ConversationsListRow(conversation: $conversation, viewModel: viewModel)
|
||||
.padding(.horizontal, .layoutPadding)
|
||||
.redacted(reason: .placeholder)
|
||||
} else {
|
||||
ConversationsListRow(conversation: $conversation, viewModel: viewModel)
|
||||
.padding(.horizontal, .layoutPadding)
|
||||
}
|
||||
Divider()
|
||||
}
|
||||
ForEach(conversations) { $conversation in
|
||||
if viewModel.isLoadingFirstPage {
|
||||
ConversationsListRow(conversation: $conversation, viewModel: viewModel)
|
||||
.padding(.horizontal, .layoutPadding)
|
||||
.redacted(reason: .placeholder)
|
||||
} else {
|
||||
ConversationsListRow(conversation: $conversation, viewModel: viewModel)
|
||||
.padding(.horizontal, .layoutPadding)
|
||||
}
|
||||
Divider()
|
||||
}
|
||||
} else if conversations.isEmpty && !viewModel.isLoadingFirstPage && !viewModel.isError {
|
||||
EmptyView(iconName: "tray",
|
||||
title: "conversations.empty.title",
|
||||
|
|
|
@ -85,23 +85,23 @@ class ConversationsListViewModel: ObservableObject {
|
|||
updateConversationWithNewLastStatus(conversation: conversation, newLastStatus: status)
|
||||
} catch {}
|
||||
}
|
||||
|
||||
private func updateConversationWithNewLastStatus(conversation: Conversation, newLastStatus: Status) {
|
||||
let newConversation = Conversation(id: conversation.id, unread: conversation.unread, lastStatus: newLastStatus, accounts: conversation.accounts)
|
||||
updateConversations(conversation: newConversation)
|
||||
}
|
||||
|
||||
private func updateConversations(conversation: Conversation) {
|
||||
if let index = conversations.firstIndex(where: { $0.id == conversation.id }) {
|
||||
conversations.remove(at: index)
|
||||
}
|
||||
conversations.insert(conversation, at: 0)
|
||||
conversations = conversations.sorted(by: { ($0.lastStatus?.createdAt.asDate ?? Date.now) > ($1.lastStatus?.createdAt.asDate ?? Date.now) })
|
||||
private func updateConversationWithNewLastStatus(conversation: Conversation, newLastStatus: Status) {
|
||||
let newConversation = Conversation(id: conversation.id, unread: conversation.unread, lastStatus: newLastStatus, accounts: conversation.accounts)
|
||||
updateConversations(conversation: newConversation)
|
||||
}
|
||||
|
||||
private func updateConversations(conversation: Conversation) {
|
||||
if let index = conversations.firstIndex(where: { $0.id == conversation.id }) {
|
||||
conversations.remove(at: index)
|
||||
}
|
||||
conversations.insert(conversation, at: 0)
|
||||
conversations = conversations.sorted(by: { ($0.lastStatus?.createdAt.asDate ?? Date.now) > ($1.lastStatus?.createdAt.asDate ?? Date.now) })
|
||||
}
|
||||
|
||||
func handleEvent(event: any StreamEvent) {
|
||||
if let event = event as? StreamEventConversation {
|
||||
updateConversations(conversation: event.conversation)
|
||||
updateConversations(conversation: event.conversation)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ public extension Font {
|
|||
static var scaledHeadline: Font {
|
||||
customFont(size: userScaledFontSize(baseSize: headline), relativeTo: .headline).weight(.semibold)
|
||||
}
|
||||
|
||||
|
||||
static var scaledHeadlinePointSize: CGFloat {
|
||||
customUIFont(size: userScaledFontSize(baseSize: headline)).pointSize
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ public extension Font {
|
|||
static var scaledBody: Font {
|
||||
customFont(size: userScaledFontSize(baseSize: body), relativeTo: .body)
|
||||
}
|
||||
|
||||
|
||||
static var scaledBodyPointSize: CGFloat {
|
||||
customUIFont(size: userScaledFontSize(baseSize: body)).pointSize
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ public extension Font {
|
|||
static var scaledCallout: Font {
|
||||
customFont(size: userScaledFontSize(baseSize: callout), relativeTo: .callout)
|
||||
}
|
||||
|
||||
|
||||
static var scaledCalloutPointSize: CGFloat {
|
||||
customUIFont(size: userScaledFontSize(baseSize: body)).pointSize
|
||||
}
|
||||
|
@ -72,15 +72,15 @@ public extension Font {
|
|||
static var scaledSubheadline: Font {
|
||||
customFont(size: userScaledFontSize(baseSize: subheadline), relativeTo: .subheadline)
|
||||
}
|
||||
|
||||
|
||||
static var scaledSubheadlinePointSize: CGFloat {
|
||||
customUIFont(size: userScaledFontSize(baseSize: subheadline)).pointSize
|
||||
}
|
||||
|
||||
|
||||
static var scaledFootnote: Font {
|
||||
customFont(size: userScaledFontSize(baseSize: footnote), relativeTo: .footnote)
|
||||
}
|
||||
|
||||
|
||||
static var scaledFootnotePointSize: CGFloat {
|
||||
customUIFont(size: userScaledFontSize(baseSize: footnote)).pointSize
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ public extension Font {
|
|||
static var scaledCaption: Font {
|
||||
customFont(size: userScaledFontSize(baseSize: caption), relativeTo: .caption)
|
||||
}
|
||||
|
||||
|
||||
static var scaledCaptionPointSize: CGFloat {
|
||||
customUIFont(size: userScaledFontSize(baseSize: caption)).pointSize
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ public class QuickLook: ObservableObject {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Published public private(set) var urls: [URL] = []
|
||||
@Published public private(set) var isPreparing: Bool = false
|
||||
@Published public private(set) var latestError: Error?
|
||||
|
@ -56,7 +57,7 @@ public class QuickLook: ObservableObject {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private var quickLookDir: URL {
|
||||
try! FileManager.default.url(for: .cachesDirectory,
|
||||
in: .userDomainMask,
|
||||
|
@ -72,8 +73,8 @@ public class QuickLook: ObservableObject {
|
|||
try data.write(to: path)
|
||||
return path
|
||||
}
|
||||
|
||||
private func cleanup(urls: [URL]) {
|
||||
|
||||
private func cleanup(urls _: [URL]) {
|
||||
try? FileManager.default.removeItem(at: quickLookDir)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,12 +6,12 @@ public struct Conversation: Identifiable, Decodable, Hashable, Equatable {
|
|||
public let lastStatus: Status?
|
||||
public let accounts: [Account]
|
||||
|
||||
public init(id: String, unread: Bool, lastStatus: Status? = nil, accounts: [Account]) {
|
||||
self.id = id
|
||||
self.unread = unread
|
||||
self.lastStatus = lastStatus
|
||||
self.accounts = accounts
|
||||
}
|
||||
public init(id: String, unread: Bool, lastStatus: Status? = nil, accounts: [Account]) {
|
||||
self.id = id
|
||||
self.unread = unread
|
||||
self.lastStatus = lastStatus
|
||||
self.accounts = accounts
|
||||
}
|
||||
|
||||
public static func placeholder() -> Conversation {
|
||||
.init(id: UUID().uuidString, unread: false, lastStatus: .placeholder(), accounts: [.placeholder()])
|
||||
|
|
|
@ -159,23 +159,23 @@ public struct UpdateCredentialsData: Encodable, Sendable {
|
|||
public struct SourceData: Encodable, Sendable {
|
||||
public let privacy: Visibility
|
||||
public let sensitive: Bool
|
||||
|
||||
|
||||
public init(privacy: Visibility, sensitive: Bool) {
|
||||
self.privacy = privacy
|
||||
self.sensitive = sensitive
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public struct FieldData: Encodable, Sendable {
|
||||
public let name: String
|
||||
public let value: String
|
||||
|
||||
|
||||
public init(name: String, value: String) {
|
||||
self.name = name
|
||||
self.value = value
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public let displayName: String
|
||||
public let note: String
|
||||
public let source: SourceData
|
||||
|
@ -183,26 +183,26 @@ public struct UpdateCredentialsData: Encodable, Sendable {
|
|||
public let locked: Bool
|
||||
public let discoverable: Bool
|
||||
public let fieldsAttributes: [String: FieldData]
|
||||
|
||||
|
||||
public init(displayName: String,
|
||||
note: String,
|
||||
source: UpdateCredentialsData.SourceData,
|
||||
bot: Bool,
|
||||
locked: Bool,
|
||||
discoverable: Bool,
|
||||
fieldsAttributes: [FieldData]) {
|
||||
fieldsAttributes: [FieldData])
|
||||
{
|
||||
self.displayName = displayName
|
||||
self.note = note
|
||||
self.source = source
|
||||
self.bot = bot
|
||||
self.locked = locked
|
||||
self.discoverable = discoverable
|
||||
|
||||
|
||||
var fieldAttributes: [String: FieldData] = [:]
|
||||
for (index, field) in fieldsAttributes.enumerated() {
|
||||
fieldAttributes[String(index)] = field
|
||||
}
|
||||
self.fieldsAttributes = fieldAttributes
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,20 +14,20 @@ enum StatusEditorUTTypeSupported: String, CaseIterable {
|
|||
case jpeg = "public.jpeg"
|
||||
case png = "public.png"
|
||||
case tiff = "public.tiff"
|
||||
|
||||
|
||||
case video = "public.video"
|
||||
case movie = "public.movie"
|
||||
case mp4 = "public.mpeg-4"
|
||||
case gif = "public.gif"
|
||||
case gif2 = "com.compuserve.gif"
|
||||
case quickTimeMovie = "com.apple.quicktime-movie"
|
||||
|
||||
|
||||
case uiimage = "com.apple.uikit.image"
|
||||
|
||||
|
||||
static func types() -> [UTType] {
|
||||
[.url, .text, .plainText, .image, .jpeg, .png, .tiff, .video, .mpeg4Movie, .gif, .movie, .quickTimeMovie]
|
||||
}
|
||||
|
||||
|
||||
var isVideo: Bool {
|
||||
switch self {
|
||||
case .video, .movie, .mp4, .quickTimeMovie:
|
||||
|
@ -36,7 +36,7 @@ enum StatusEditorUTTypeSupported: String, CaseIterable {
|
|||
return false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var isGif: Bool {
|
||||
switch self {
|
||||
case .gif, .gif2:
|
||||
|
@ -45,7 +45,7 @@ enum StatusEditorUTTypeSupported: String, CaseIterable {
|
|||
return false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func loadItemContent(item: NSItemProvider) async throws -> Any? {
|
||||
let result = try await item.loadItem(forTypeIdentifier: rawValue)
|
||||
if isVideo, let transferable = await getVideoTransferable(item: item) {
|
||||
|
@ -79,7 +79,7 @@ enum StatusEditorUTTypeSupported: String, CaseIterable {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private func getVideoTransferable(item: NSItemProvider) async -> MovieFileTranseferable? {
|
||||
return await withCheckedContinuation { continuation in
|
||||
_ = item.loadTransferable(type: MovieFileTranseferable.self) { result in
|
||||
|
@ -92,7 +92,7 @@ enum StatusEditorUTTypeSupported: String, CaseIterable {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private func getGifTransferable(item: NSItemProvider) async -> GifFileTranseferable? {
|
||||
return await withCheckedContinuation { continuation in
|
||||
_ = item.loadTransferable(type: GifFileTranseferable.self) { result in
|
||||
|
@ -105,7 +105,7 @@ enum StatusEditorUTTypeSupported: String, CaseIterable {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private func getImageTansferable(item: NSItemProvider) async -> ImageFileTranseferable? {
|
||||
return await withCheckedContinuation { continuation in
|
||||
_ = item.loadTransferable(type: ImageFileTranseferable.self) { result in
|
||||
|
@ -140,7 +140,7 @@ struct MovieFileTranseferable: Transferable {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static var transferRepresentation: some TransferRepresentation {
|
||||
FileRepresentation(contentType: .movie) { movie in
|
||||
SentTransferredFile(movie.url)
|
||||
|
@ -152,10 +152,10 @@ struct MovieFileTranseferable: Transferable {
|
|||
|
||||
struct ImageFileTranseferable: Transferable {
|
||||
let url: URL
|
||||
|
||||
|
||||
lazy var data: Data? = try? Data(contentsOf: url)
|
||||
lazy var image: UIImage? = UIImage(data: data ?? Data())
|
||||
|
||||
|
||||
static var transferRepresentation: some TransferRepresentation {
|
||||
FileRepresentation(contentType: .image) { image in
|
||||
SentTransferredFile(image.url)
|
||||
|
@ -167,11 +167,11 @@ struct ImageFileTranseferable: Transferable {
|
|||
|
||||
struct GifFileTranseferable: Transferable {
|
||||
let url: URL
|
||||
|
||||
|
||||
var data: Data? {
|
||||
try? Data(contentsOf: url)
|
||||
}
|
||||
|
||||
|
||||
static var transferRepresentation: some TransferRepresentation {
|
||||
FileRepresentation(contentType: .gif) { gif in
|
||||
SentTransferredFile(gif.url)
|
||||
|
@ -197,7 +197,6 @@ public extension URL {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
extension UIImage {
|
||||
func resized(to size: CGSize) -> UIImage {
|
||||
UIGraphicsImageRenderer(size: size).image { _ in
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
import Foundation
|
||||
import SwiftUI
|
||||
import Models
|
||||
import SwiftUI
|
||||
|
||||
@MainActor
|
||||
class StatusEmbedCache {
|
||||
static let shared = StatusEmbedCache()
|
||||
|
||||
|
||||
private var cache: [URL: Status] = [:]
|
||||
|
||||
private init() { }
|
||||
|
||||
|
||||
private init() {}
|
||||
|
||||
func set(url: URL, status: Status) {
|
||||
cache[url] = status
|
||||
}
|
||||
|
||||
|
||||
func get(url: URL) -> Status? {
|
||||
cache[url]
|
||||
}
|
||||
|
|
|
@ -44,8 +44,8 @@ public struct StatusesListView<Fetcher>: View where Fetcher: StatusesFetcher {
|
|||
client: client,
|
||||
routerPath: routerPath,
|
||||
isRemote: isRemote)
|
||||
|
||||
})
|
||||
|
||||
})
|
||||
.id(status.id)
|
||||
.onAppear {
|
||||
fetcher.statusDidAppear(status: status)
|
||||
|
|
|
@ -47,7 +47,7 @@ public class StatusRowViewModel: ObservableObject {
|
|||
|
||||
var isThread: Bool {
|
||||
status.reblog?.inReplyToId != nil || status.reblog?.inReplyToAccountId != nil ||
|
||||
status.inReplyToId != nil || status.inReplyToAccountId != nil
|
||||
status.inReplyToId != nil || status.inReplyToAccountId != nil
|
||||
}
|
||||
|
||||
var highlightRowColor: Color {
|
||||
|
@ -97,14 +97,15 @@ public class StatusRowViewModel: ObservableObject {
|
|||
}
|
||||
|
||||
isFiltered = filter != nil
|
||||
|
||||
|
||||
if let url = embededStatusURL(),
|
||||
let embed = StatusEmbedCache.shared.get(url: url) {
|
||||
let embed = StatusEmbedCache.shared.get(url: url)
|
||||
{
|
||||
isEmbedLoading = false
|
||||
embeddedStatus = embed
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func markSeen() {
|
||||
// called in on appear so we can cache that the status has been seen.
|
||||
if UserPreferences.shared.suppressDupeReblogs && !seen {
|
||||
|
@ -154,12 +155,13 @@ public class StatusRowViewModel: ObservableObject {
|
|||
routerPath.navigate(to: .accountDetail(id: mention.id))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private func embededStatusURL() -> URL? {
|
||||
let content = status.reblog?.content ?? status.content
|
||||
if !content.statusesURLs.isEmpty,
|
||||
let url = content.statusesURLs.first,
|
||||
client.hasConnection(with: url) {
|
||||
client.hasConnection(with: url)
|
||||
{
|
||||
return url
|
||||
}
|
||||
return nil
|
||||
|
@ -167,19 +169,20 @@ public class StatusRowViewModel: ObservableObject {
|
|||
|
||||
func loadEmbeddedStatus() async {
|
||||
guard embeddedStatus == nil,
|
||||
let url = embededStatusURL() else {
|
||||
let url = embededStatusURL()
|
||||
else {
|
||||
if isEmbedLoading {
|
||||
isEmbedLoading = false
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
if let embed = StatusEmbedCache.shared.get(url: url) {
|
||||
isEmbedLoading = false
|
||||
embeddedStatus = embed
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
do {
|
||||
isEmbedLoading = true
|
||||
var embed: Status?
|
||||
|
|
|
@ -73,7 +73,7 @@ struct StatusRowHeaderView: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private var accountBadgeView: Text {
|
||||
if (viewModel.status.reblogAsAsStatus ?? viewModel.status).account.bot {
|
||||
return Text(Image(systemName: "gearshape.fill")) + Text(" ")
|
||||
|
@ -85,8 +85,8 @@ struct StatusRowHeaderView: View {
|
|||
|
||||
private var dateView: Text {
|
||||
Text(status.createdAt.relativeFormatted) +
|
||||
Text(" ⸱ ") +
|
||||
Text(Image(systemName: viewModel.status.visibility.iconName))
|
||||
Text(" ⸱ ") +
|
||||
Text(Image(systemName: viewModel.status.visibility.iconName))
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
|
|
|
@ -46,7 +46,7 @@ public enum TimelineFilter: Hashable, Equatable {
|
|||
}
|
||||
return [.home, .local, .federated, .trending]
|
||||
}
|
||||
|
||||
|
||||
public var supportNewestPagination: Bool {
|
||||
switch self {
|
||||
case .trending:
|
||||
|
|
|
@ -103,11 +103,11 @@ public struct TimelineView: View {
|
|||
.navigationBarTitleDisplayMode(.inline)
|
||||
.onAppear {
|
||||
viewModel.isTimelineVisible = true
|
||||
|
||||
|
||||
if viewModel.client == nil {
|
||||
viewModel.client = client
|
||||
}
|
||||
|
||||
|
||||
viewModel.timeline = timeline
|
||||
}
|
||||
.onDisappear {
|
||||
|
|
|
@ -147,7 +147,7 @@ extension TimelineViewModel {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
private func clearHomeCache() async {
|
||||
if let client, timeline == .home {
|
||||
await cache.clearCache(for: client.id)
|
||||
|
|
Loading…
Reference in a new issue