This commit is contained in:
Thomas Ricouard 2024-05-04 13:19:19 +02:00
parent ba4cc899f8
commit c3edabb183
25 changed files with 269 additions and 276 deletions

View file

@ -8,10 +8,10 @@ import LinkPresentation
import Lists
import MediaUI
import Models
import Notifications
import StatusKit
import SwiftUI
import Timeline
import Notifications
@MainActor
extension View {
@ -67,7 +67,7 @@ extension View {
case .notificationsRequests:
NotificationsRequestsListView()
case let .notificationForAccount(accountId):
NotificationsListView(lockedType: nil ,
NotificationsListView(lockedType: nil,
lockedAccountId: accountId,
scrollToTopSignal: .constant(0))
case .blockedAccounts:

View file

@ -1,8 +1,8 @@
import AppIntents
import Env
import MediaUI
import StatusKit
import SwiftUI
import AppIntents
extension IceCubesApp {
var appScene: some Scene {
@ -126,7 +126,7 @@ extension IceCubesApp {
.windowResizability(.contentMinSize)
}
private func handleIntent(_ intent: any AppIntent) {
private func handleIntent(_: any AppIntent) {
if let postIntent = appIntentService.handledIntent?.intent as? PostIntent {
#if os(visionOS) || os(macOS)
openWindow(value: WindowDestinationEditor.prefilledStatusEditor(text: postIntent.content ?? "",
@ -138,7 +138,8 @@ extension IceCubesApp {
} else if let tabIntent = appIntentService.handledIntent?.intent as? TabIntent {
selectedTab = tabIntent.tab.toAppTab
} else if let imageIntent = appIntentService.handledIntent?.intent as? PostImageIntent,
let urls = imageIntent.images?.compactMap({ $0.fileURL }) {
let urls = imageIntent.images?.compactMap({ $0.fileURL })
{
appRouterPath.presentedSheet = .imageURL(urls: urls,
visibility: userPreferences.postVisibility)
}

View file

@ -1,10 +1,10 @@
import Account
import AppIntents
import DesignSystem
import Explore
import Foundation
import StatusKit
import SwiftUI
import AppIntents
@MainActor
enum Tab: Int, Identifiable, Hashable, CaseIterable, Codable {

View file

@ -1,5 +1,5 @@
import SwiftUI
import AppIntents
import SwiftUI
@Observable
public class AppIntentService: @unchecked Sendable {
@ -12,7 +12,7 @@ public class AppIntentService: @unchecked Sendable {
let intent: any AppIntent
init(intent: any AppIntent) {
self.id = UUID().uuidString
id = UUID().uuidString
self.intent = intent
}
}
@ -21,5 +21,5 @@ public class AppIntentService: @unchecked Sendable {
var handledIntent: HandledIntent?
private init() { }
private init() {}
}

View file

@ -1,23 +1,21 @@
import Foundation
import AppIntents
import AppAccount
import Network
import AppIntents
import Env
import Foundation
import Models
import Network
enum PostVisibility: String, AppEnum {
case direct, priv, unlisted, pub
public static var caseDisplayRepresentations: [PostVisibility : DisplayRepresentation] {
public static var caseDisplayRepresentations: [PostVisibility: DisplayRepresentation] {
[.direct: "Private",
.priv: "Followers Only",
.unlisted: "Quiet Public",
.pub: "Public"]
}
static var typeDisplayName: LocalizedStringResource {
get { "Visibility" }
}
static var typeDisplayName: LocalizedStringResource { "Visibility" }
public static let typeDisplayRepresentation: TypeDisplayRepresentation = "Visibility"
@ -47,21 +45,19 @@ struct AppAccountWrapper: Identifiable, AppEntity {
var displayRepresentation: DisplayRepresentation {
DisplayRepresentation(title: "\(account.accountName ?? account.server)")
}
}
struct DefaultAppAccountQuery: EntityQuery {
func entities(for identifiers: [AppAccountWrapper.ID]) async throws -> [AppAccountWrapper] {
return await AppAccountsManager.shared.availableAccounts.filter { account in
identifiers.contains { id in
id == account.id
}
}.map{ AppAccountWrapper(account: $0 )}
}.map { AppAccountWrapper(account: $0) }
}
func suggestedEntities() async throws -> [AppAccountWrapper] {
await AppAccountsManager.shared.availableAccounts.map{ .init(account: $0)}
await AppAccountsManager.shared.availableAccounts.map { .init(account: $0) }
}
func defaultResult() async -> AppAccountWrapper? {
@ -72,10 +68,9 @@ struct DefaultAppAccountQuery: EntityQuery {
struct InlinePostIntent: AppIntent {
static let title: LocalizedStringResource = "Send text status to Mastodon"
static var description: IntentDescription {
get {
"Send a text status to Mastodon using Ice Cubes"
}
}
static let openAppWhenRun: Bool = false
@Parameter(title: "Account", requestValueDialog: IntentDialog("Account"))

View file

@ -1,13 +1,12 @@
import Foundation
import AppIntents
import Foundation
struct PostImageIntent: AppIntent {
static let title: LocalizedStringResource = "Post an image to Mastodon"
static var description: IntentDescription {
get {
"Use Ice Cubes to post a status with an image to Mastodon"
}
}
static let openAppWhenRun: Bool = true
@Parameter(title: "Image",

View file

@ -1,13 +1,12 @@
import Foundation
import AppIntents
import Foundation
struct PostIntent: AppIntent {
static let title: LocalizedStringResource = "Post status to Mastodon"
static var description: IntentDescription {
get {
"Use Ice Cubes to post a status to Mastodon"
}
}
static let openAppWhenRun: Bool = true
@Parameter(title: "Post content", inputConnectionBehavior: .connectToPreviousIntentResult)

View file

@ -1,5 +1,5 @@
import Foundation
import AppIntents
import Foundation
enum TabEnum: String, AppEnum, Sendable {
case timeline, notifications, mentions, explore, messages, settings
@ -12,13 +12,11 @@ enum TabEnum: String, AppEnum, Sendable {
case lists
case links
static var typeDisplayName: LocalizedStringResource {
get { "Tab" }
}
static var typeDisplayName: LocalizedStringResource { "Tab" }
static let typeDisplayRepresentation: TypeDisplayRepresentation = "Tab"
nonisolated static var caseDisplayRepresentations: [TabEnum : DisplayRepresentation] {
nonisolated static var caseDisplayRepresentations: [TabEnum: DisplayRepresentation] {
[.timeline: .init(title: "Home Timeline"),
.trending: .init(title: "Trending Timeline"),
.federated: .init(title: "Federated Timeline"),
@ -34,8 +32,7 @@ enum TabEnum: String, AppEnum, Sendable {
.followedTags: .init(title: "Followed Tags"),
.lists: .init(title: "Lists"),
.links: .init(title: "Trending Links"),
.post: .init(title: "New post"),
]
.post: .init(title: "New post")]
}
var toAppTab: Tab {
@ -79,10 +76,9 @@ enum TabEnum: String, AppEnum, Sendable {
struct TabIntent: AppIntent {
static let title: LocalizedStringResource = "Open on a tab"
static var description: IntentDescription {
get {
"Open the app on a specific tab"
}
}
static let openAppWhenRun: Bool = true
@Parameter(title: "Selected tab")

View file

@ -333,7 +333,6 @@ public struct AccountDetailView: View {
Label("account.blocked", systemImage: "person.crop.circle.badge.xmark")
}
Button {
routerPath.navigate(to: .mutedAccounts)
} label: {

View file

@ -4,9 +4,9 @@ public struct ErrorView: View {
public let title: LocalizedStringKey
public let message: LocalizedStringKey
public let buttonTitle: LocalizedStringKey
public let onButtonPress: (() async -> Void)
public let onButtonPress: () async -> Void
public init(title: LocalizedStringKey, message: LocalizedStringKey, buttonTitle: LocalizedStringKey, onButtonPress: @escaping (() async -> Void) ) {
public init(title: LocalizedStringKey, message: LocalizedStringKey, buttonTitle: LocalizedStringKey, onButtonPress: @escaping (() async -> Void)) {
self.title = title
self.message = message
self.buttonTitle = buttonTitle

View file

@ -179,7 +179,8 @@ public enum SheetDestination: Identifiable, Hashable {
} else if let client,
client.isAuth,
client.hasConnection(with: url),
let id = Int(url.lastPathComponent) {
let id = Int(url.lastPathComponent)
{
if url.absoluteString.contains(client.server) {
navigate(to: .statusDetail(id: String(id)))
} else {
@ -193,7 +194,8 @@ public enum SheetDestination: Identifiable, Hashable {
public func handleDeepLink(url: URL) -> OpenURLAction.Result {
guard let client,
client.isAuth,
let id = Int(url.lastPathComponent) else {
let id = Int(url.lastPathComponent)
else {
return urlHandler?(url) ?? .systemAction
}
// First check whether we already know that the client's server federates with the server this post is on

View file

@ -1,7 +1,7 @@
import SwiftUI
import Models
import DesignSystem
import Env
import Models
import SwiftUI
struct NotificationsHeaderFilteredView: View {
@Environment(Theme.self) private var theme

View file

@ -24,7 +24,8 @@ public struct NotificationsListView: View {
public init(lockedType: Models.Notification.NotificationType? = nil,
lockedAccountId: String? = nil,
scrollToTopSignal: Binding<Int>) {
scrollToTopSignal: Binding<Int>)
{
self.lockedType = lockedType
self.lockedAccountId = lockedAccountId
_scrollToTopSignal = scrollToTopSignal

View file

@ -1,7 +1,7 @@
import SwiftUI
import Network
import DesignSystem
import Models
import Network
import SwiftUI
@MainActor
struct NotificationsPolicyView: View {
@ -84,7 +84,7 @@ struct NotificationsPolicyView: View {
do {
isUpdating = true
self.policy = try await client.put(endpoint: Notifications.putPolicy(policy: policy))
} catch { }
} catch {}
}
}
}

View file

@ -39,7 +39,7 @@ import SwiftUI
private let filterKey = "notification-filter"
var state: State = .loading
var isLockedType: Bool = false
var lockedAccountId: String? = nil
var lockedAccountId: String?
var policy: Models.NotificationsPolicy?
var selectedType: Models.Notification.NotificationType? {
didSet {

View file

@ -1,7 +1,7 @@
import SwiftUI
import Network
import Models
import DesignSystem
import Models
import Network
import SwiftUI
@MainActor
public struct NotificationsRequestsListView: View {
@ -13,9 +13,10 @@ public struct NotificationsRequestsListView: View {
case error
case requests(_ data: [NotificationsRequest])
}
@State private var viewState: ViewState = .loading
public init() { }
public init() {}
public var body: some View {
List {
@ -74,7 +75,7 @@ public struct NotificationsRequestsListView: View {
private func fetchRequests() async {
do {
viewState = .requests(try await client.get(endpoint: Notifications.requests))
viewState = try .requests(await client.get(endpoint: Notifications.requests))
} catch {
viewState = .error
}

View file

@ -1,8 +1,8 @@
import SwiftUI
import Models
import DesignSystem
import Env
import Models
import Network
import SwiftUI
struct NotificationsRequestsRowView: View {
@Environment(Theme.self) private var theme

View file

@ -73,25 +73,25 @@ public extension StatusEditor {
.scrollPosition(id: $scrollID, anchor: .top)
.animation(.bouncy(duration: 0.3), value: editorFocusState)
.animation(.bouncy(duration: 0.3), value: followUpSEVMs)
#if !os(visionOS)
#if !os(visionOS)
.background(theme.primaryBackgroundColor)
#endif
#endif
.safeAreaInset(edge: .bottom) {
AutoCompleteView(viewModel: focusedSEVM)
}
#if os(visionOS)
#if os(visionOS)
.ornament(attachmentAnchor: .scene(.leading)) {
AccessoryView(focusedSEVM: focusedSEVM,
followUpSEVMs: $followUpSEVMs)
}
#else
#else
.safeAreaInset(edge: .bottom) {
if presentationDetent == .large || presentationDetent == .medium {
AccessoryView(focusedSEVM: focusedSEVM,
followUpSEVMs: $followUpSEVMs)
}
}
#endif
#endif
.accessibilitySortPriority(1) // Ensure that all elements inside the `ScrollView` occur earlier than the accessory views
.navigationTitle(focusedSEVM.mode.title)
.navigationBarTitleDisplayMode(.inline)

View file

@ -754,8 +754,8 @@ public extension StatusEditor {
let compressor = Compressor()
if let compressedData = await compressor.compressImageFrom(url: url),
let image = UIImage(data: compressedData) {
let image = UIImage(data: compressedData)
{
containers.append(MediaContainer(
id: UUID().uuidString,
image: image,