Fixed typos & misspells (#88)

* Fixed typos and misspells

* Other typos
This commit is contained in:
Romain Vincens 2023-01-17 15:14:50 +01:00 committed by GitHub
parent 899ccd8ad7
commit bb72327f52
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
48 changed files with 281 additions and 281 deletions

View file

@ -9,8 +9,8 @@ import Timeline
@MainActor @MainActor
extension View { extension View {
func withAppRouteur() -> some View { func withAppRouter() -> some View {
navigationDestination(for: RouteurDestinations.self) { destination in navigationDestination(for: RouterDestinations.self) { destination in
switch destination { switch destination {
case let .accountDetail(id): case let .accountDetail(id):
AccountDetailView(accountId: id) AccountDetailView(accountId: id)
@ -43,7 +43,7 @@ extension View {
StatusEditorView(mode: .replyTo(status: status)) StatusEditorView(mode: .replyTo(status: status))
.withEnvironments() .withEnvironments()
case let .newStatusEditor(visibility): case let .newStatusEditor(visibility):
StatusEditorView(mode: .new(vivibilty: visibility)) StatusEditorView(mode: .new(visibility: visibility))
.withEnvironments() .withEnvironments()
case let .editStatusEditor(status): case let .editStatusEditor(status):
StatusEditorView(mode: .edit(status: status)) StatusEditorView(mode: .edit(status: status))

View file

@ -13,7 +13,7 @@ struct QuickLookPreview: UIViewControllerRepresentable {
let urls: [URL] let urls: [URL]
func makeUIViewController(context: Context) -> UINavigationController { func makeUIViewController(context: Context) -> UINavigationController {
let controller = AppQLPreviewCpntroller() let controller = AppQLPreviewController()
controller.dataSource = context.coordinator controller.dataSource = context.coordinator
controller.delegate = context.coordinator controller.delegate = context.coordinator
let nav = UINavigationController(rootViewController: controller) let nav = UINavigationController(rootViewController: controller)
@ -49,7 +49,7 @@ struct QuickLookPreview: UIViewControllerRepresentable {
} }
} }
class AppQLPreviewCpntroller: QLPreviewController { class AppQLPreviewController: QLPreviewController {
private var closeButton: UIBarButtonItem { private var closeButton: UIBarButtonItem {
.init(title: "Done", style: .plain, target: self, action: #selector(onCloseButton)) .init(title: "Done", style: .plain, target: self, action: #selector(onCloseButton))
} }

View file

@ -4,25 +4,25 @@ import SafariServices
import SwiftUI import SwiftUI
extension View { extension View {
func withSafariRouteur() -> some View { func withSafariRouter() -> some View {
modifier(SafariRouteur()) modifier(SafariRouter())
} }
} }
private struct SafariRouteur: ViewModifier { private struct SafariRouter: ViewModifier {
@EnvironmentObject private var theme: Theme @EnvironmentObject private var theme: Theme
@EnvironmentObject private var preferences: UserPreferences @EnvironmentObject private var preferences: UserPreferences
@EnvironmentObject private var routeurPath: RouterPath @EnvironmentObject private var routerPath: RouterPath
@State private var safari: SFSafariViewController? @State private var safari: SFSafariViewController?
func body(content: Content) -> some View { func body(content: Content) -> some View {
content content
.environment(\.openURL, OpenURLAction { url in .environment(\.openURL, OpenURLAction { url in
routeurPath.handle(url: url) routerPath.handle(url: url)
}) })
.onAppear { .onAppear {
routeurPath.urlHandler = { url in routerPath.urlHandler = { url in
guard preferences.preferredBrowser == .inAppSafari else { return .systemAction } guard preferences.preferredBrowser == .inAppSafari else { return .systemAction }
// SFSafariViewController only supports initial URLs with http:// or https:// schemes. // SFSafariViewController only supports initial URLs with http:// or https:// schemes.
guard let scheme = url.scheme, ["https", "http"].contains(scheme.lowercased()) else { guard let scheme = url.scheme, ["https", "http"].contains(scheme.lowercased()) else {

View file

@ -27,7 +27,7 @@ struct SideBarView<Content: View>: View {
Button { Button {
selectedTab = .profile selectedTab = .profile
} label: { } label: {
AppAccountsSelectorView(routeurPath: RouterPath(), AppAccountsSelectorView(routerPath: RouterPath(),
accountCreationEnabled: false, accountCreationEnabled: false,
avatarSize: .status) avatarSize: .status)
} }

View file

@ -10,36 +10,36 @@ struct ExploreTab: View {
@EnvironmentObject private var preferences: UserPreferences @EnvironmentObject private var preferences: UserPreferences
@EnvironmentObject private var currentAccount: CurrentAccount @EnvironmentObject private var currentAccount: CurrentAccount
@EnvironmentObject private var client: Client @EnvironmentObject private var client: Client
@StateObject private var routeurPath = RouterPath() @StateObject private var routerPath = RouterPath()
@Binding var popToRootTab: Tab @Binding var popToRootTab: Tab
var body: some View { var body: some View {
NavigationStack(path: $routeurPath.path) { NavigationStack(path: $routerPath.path) {
ExploreView() ExploreView()
.withAppRouteur() .withAppRouter()
.withSheetDestinations(sheetDestinations: $routeurPath.presentedSheet) .withSheetDestinations(sheetDestinations: $routerPath.presentedSheet)
.toolbar { .toolbar {
statusEditorToolbarItem(routeurPath: routeurPath, statusEditorToolbarItem(routerPath: routerPath,
visibility: preferences.serverPreferences?.postVisibility ?? .pub) visibility: preferences.serverPreferences?.postVisibility ?? .pub)
if UIDevice.current.userInterfaceIdiom != .pad { if UIDevice.current.userInterfaceIdiom != .pad {
ToolbarItem(placement: .navigationBarLeading) { ToolbarItem(placement: .navigationBarLeading) {
AppAccountsSelectorView(routeurPath: routeurPath) AppAccountsSelectorView(routerPath: routerPath)
} }
} }
} }
} }
.withSafariRouteur() .withSafariRouter()
.environmentObject(routeurPath) .environmentObject(routerPath)
.onChange(of: $popToRootTab.wrappedValue) { popToRootTab in .onChange(of: $popToRootTab.wrappedValue) { popToRootTab in
if popToRootTab == .explore { if popToRootTab == .explore {
routeurPath.path = [] routerPath.path = []
} }
} }
.onChange(of: currentAccount.account?.id) { _ in .onChange(of: currentAccount.account?.id) { _ in
routeurPath.path = [] routerPath.path = []
} }
.onAppear { .onAppear {
routeurPath.client = client routerPath.client = client
} }
} }
} }

View file

@ -11,18 +11,18 @@ struct MessagesTab: View {
@EnvironmentObject private var watcher: StreamWatcher @EnvironmentObject private var watcher: StreamWatcher
@EnvironmentObject private var client: Client @EnvironmentObject private var client: Client
@EnvironmentObject private var currentAccount: CurrentAccount @EnvironmentObject private var currentAccount: CurrentAccount
@StateObject private var routeurPath = RouterPath() @StateObject private var routerPath = RouterPath()
@Binding var popToRootTab: Tab @Binding var popToRootTab: Tab
var body: some View { var body: some View {
NavigationStack(path: $routeurPath.path) { NavigationStack(path: $routerPath.path) {
ConversationsListView() ConversationsListView()
.withAppRouteur() .withAppRouter()
.withSheetDestinations(sheetDestinations: $routeurPath.presentedSheet) .withSheetDestinations(sheetDestinations: $routerPath.presentedSheet)
.toolbar { .toolbar {
if UIDevice.current.userInterfaceIdiom != .pad { if UIDevice.current.userInterfaceIdiom != .pad {
ToolbarItem(placement: .navigationBarLeading) { ToolbarItem(placement: .navigationBarLeading) {
AppAccountsSelectorView(routeurPath: routeurPath) AppAccountsSelectorView(routerPath: routerPath)
} }
} }
} }
@ -30,16 +30,16 @@ struct MessagesTab: View {
} }
.onChange(of: $popToRootTab.wrappedValue) { popToRootTab in .onChange(of: $popToRootTab.wrappedValue) { popToRootTab in
if popToRootTab == .messages { if popToRootTab == .messages {
routeurPath.path = [] routerPath.path = []
} }
} }
.onChange(of: currentAccount.account?.id) { _ in .onChange(of: currentAccount.account?.id) { _ in
routeurPath.path = [] routerPath.path = []
} }
.onAppear { .onAppear {
routeurPath.client = client routerPath.client = client
} }
.withSafariRouteur() .withSafariRouter()
.environmentObject(routeurPath) .environmentObject(routerPath)
} }
} }

View file

@ -10,39 +10,39 @@ struct NotificationsTab: View {
@EnvironmentObject private var watcher: StreamWatcher @EnvironmentObject private var watcher: StreamWatcher
@EnvironmentObject private var currentAccount: CurrentAccount @EnvironmentObject private var currentAccount: CurrentAccount
@EnvironmentObject private var userPreferences: UserPreferences @EnvironmentObject private var userPreferences: UserPreferences
@StateObject private var routeurPath = RouterPath() @StateObject private var routerPath = RouterPath()
@Binding var popToRootTab: Tab @Binding var popToRootTab: Tab
var body: some View { var body: some View {
NavigationStack(path: $routeurPath.path) { NavigationStack(path: $routerPath.path) {
NotificationsListView() NotificationsListView()
.withAppRouteur() .withAppRouter()
.withSheetDestinations(sheetDestinations: $routeurPath.presentedSheet) .withSheetDestinations(sheetDestinations: $routerPath.presentedSheet)
.toolbar { .toolbar {
statusEditorToolbarItem(routeurPath: routeurPath, statusEditorToolbarItem(routerPath: routerPath,
visibility: userPreferences.serverPreferences?.postVisibility ?? .pub) visibility: userPreferences.serverPreferences?.postVisibility ?? .pub)
if UIDevice.current.userInterfaceIdiom != .pad { if UIDevice.current.userInterfaceIdiom != .pad {
ToolbarItem(placement: .navigationBarLeading) { ToolbarItem(placement: .navigationBarLeading) {
AppAccountsSelectorView(routeurPath: routeurPath) AppAccountsSelectorView(routerPath: routerPath)
} }
} }
} }
.id(currentAccount.account?.id) .id(currentAccount.account?.id)
} }
.onAppear { .onAppear {
routeurPath.client = client routerPath.client = client
watcher.unreadNotificationsCount = 0 watcher.unreadNotificationsCount = 0
userPreferences.pushNotificationsCount = 0 userPreferences.pushNotificationsCount = 0
} }
.withSafariRouteur() .withSafariRouter()
.environmentObject(routeurPath) .environmentObject(routerPath)
.onChange(of: $popToRootTab.wrappedValue) { popToRootTab in .onChange(of: $popToRootTab.wrappedValue) { popToRootTab in
if popToRootTab == .notifications { if popToRootTab == .notifications {
routeurPath.path = [] routerPath.path = []
} }
} }
.onChange(of: currentAccount.account?.id) { _ in .onChange(of: currentAccount.account?.id) { _ in
routeurPath.path = [] routerPath.path = []
} }
} }
} }

View file

@ -10,19 +10,19 @@ import SwiftUI
struct ProfileTab: View { struct ProfileTab: View {
@EnvironmentObject private var client: Client @EnvironmentObject private var client: Client
@EnvironmentObject private var currentAccount: CurrentAccount @EnvironmentObject private var currentAccount: CurrentAccount
@StateObject private var routeurPath = RouterPath() @StateObject private var routerPath = RouterPath()
@Binding var popToRootTab: Tab @Binding var popToRootTab: Tab
var body: some View { var body: some View {
NavigationStack(path: $routeurPath.path) { NavigationStack(path: $routerPath.path) {
if let account = currentAccount.account { if let account = currentAccount.account {
AccountDetailView(account: account) AccountDetailView(account: account)
.withAppRouteur() .withAppRouter()
.withSheetDestinations(sheetDestinations: $routeurPath.presentedSheet) .withSheetDestinations(sheetDestinations: $routerPath.presentedSheet)
.toolbar { .toolbar {
if UIDevice.current.userInterfaceIdiom != .pad { if UIDevice.current.userInterfaceIdiom != .pad {
ToolbarItem(placement: .navigationBarLeading) { ToolbarItem(placement: .navigationBarLeading) {
AppAccountsSelectorView(routeurPath: routeurPath) AppAccountsSelectorView(routerPath: routerPath)
} }
} }
} }
@ -35,16 +35,16 @@ struct ProfileTab: View {
} }
.onChange(of: $popToRootTab.wrappedValue) { popToRootTab in .onChange(of: $popToRootTab.wrappedValue) { popToRootTab in
if popToRootTab == .messages { if popToRootTab == .messages {
routeurPath.path = [] routerPath.path = []
} }
} }
.onChange(of: currentAccount.account?.id) { _ in .onChange(of: currentAccount.account?.id) { _ in
routeurPath.path = [] routerPath.path = []
} }
.onAppear { .onAppear {
routeurPath.client = client routerPath.client = client
} }
.withSafariRouteur() .withSafariRouter()
.environmentObject(routeurPath) .environmentObject(routerPath)
} }
} }

View file

@ -15,14 +15,14 @@ struct SettingsTabs: View {
@EnvironmentObject private var appAccountsManager: AppAccountsManager @EnvironmentObject private var appAccountsManager: AppAccountsManager
@EnvironmentObject private var theme: Theme @EnvironmentObject private var theme: Theme
@StateObject private var routeurPath = RouterPath() @StateObject private var routerPath = RouterPath()
@State private var addAccountSheetPresented = false @State private var addAccountSheetPresented = false
@Binding var popToRootTab: Tab @Binding var popToRootTab: Tab
var body: some View { var body: some View {
NavigationStack(path: $routeurPath.path) { NavigationStack(path: $routerPath.path) {
Form { Form {
appSection appSection
accountsSection accountsSection
@ -33,22 +33,22 @@ struct SettingsTabs: View {
.navigationTitle(Text("Settings")) .navigationTitle(Text("Settings"))
.navigationBarTitleDisplayMode(.inline) .navigationBarTitleDisplayMode(.inline)
.toolbarBackground(theme.primaryBackgroundColor, for: .navigationBar) .toolbarBackground(theme.primaryBackgroundColor, for: .navigationBar)
.withAppRouteur() .withAppRouter()
.withSheetDestinations(sheetDestinations: $routeurPath.presentedSheet) .withSheetDestinations(sheetDestinations: $routerPath.presentedSheet)
} }
.onAppear { .onAppear {
routeurPath.client = client routerPath.client = client
} }
.task { .task {
if appAccountsManager.currentAccount.oauthToken != nil { if appAccountsManager.currentAccount.oauthToken != nil {
await currentInstance.fetchCurrentInstance() await currentInstance.fetchCurrentInstance()
} }
} }
.withSafariRouteur() .withSafariRouter()
.environmentObject(routeurPath) .environmentObject(routerPath)
.onChange(of: $popToRootTab.wrappedValue) { popToRootTab in .onChange(of: $popToRootTab.wrappedValue) { popToRootTab in
if popToRootTab == .notifications { if popToRootTab == .notifications {
routeurPath.path = [] routerPath.path = []
} }
} }
} }
@ -156,7 +156,7 @@ struct SettingsTabs: View {
} }
.listRowBackground(theme.primaryBackgroundColor) .listRowBackground(theme.primaryBackgroundColor)
Button { Button {
routeurPath.presentedSheet = .addRemoteLocalTimeline routerPath.presentedSheet = .addRemoteLocalTimeline
} label: { } label: {
Label("Add a local timeline", systemImage: "badge.plus.radiowaves.right") Label("Add a local timeline", systemImage: "badge.plus.radiowaves.right")
} }

View file

@ -12,7 +12,7 @@ struct TimelineTab: View {
@EnvironmentObject private var currentAccount: CurrentAccount @EnvironmentObject private var currentAccount: CurrentAccount
@EnvironmentObject private var preferences: UserPreferences @EnvironmentObject private var preferences: UserPreferences
@EnvironmentObject private var client: Client @EnvironmentObject private var client: Client
@StateObject private var routeurPath = RouterPath() @StateObject private var routerPath = RouterPath()
@Binding var popToRootTab: Tab @Binding var popToRootTab: Tab
@State private var didAppear: Bool = false @State private var didAppear: Bool = false
@ -28,17 +28,17 @@ struct TimelineTab: View {
} }
var body: some View { var body: some View {
NavigationStack(path: $routeurPath.path) { NavigationStack(path: $routerPath.path) {
TimelineView(timeline: $timeline, scrollToTopSignal: $scrollToTopSignal) TimelineView(timeline: $timeline, scrollToTopSignal: $scrollToTopSignal)
.withAppRouteur() .withAppRouter()
.withSheetDestinations(sheetDestinations: $routeurPath.presentedSheet) .withSheetDestinations(sheetDestinations: $routerPath.presentedSheet)
.toolbar { .toolbar {
toolbarView toolbarView
} }
.id(currentAccount.account?.id) .id(currentAccount.account?.id)
} }
.onAppear { .onAppear {
routeurPath.client = client routerPath.client = client
if !didAppear && canFilterTimeline { if !didAppear && canFilterTimeline {
didAppear = true didAppear = true
timeline = client.isAuth ? .home : .federated timeline = client.isAuth ? .home : .federated
@ -47,7 +47,7 @@ struct TimelineTab: View {
await currentAccount.fetchLists() await currentAccount.fetchLists()
} }
if !client.isAuth { if !client.isAuth {
routeurPath.presentedSheet = .addAccount routerPath.presentedSheet = .addAccount
} }
} }
.onChange(of: client.isAuth, perform: { isAuth in .onChange(of: client.isAuth, perform: { isAuth in
@ -58,18 +58,18 @@ struct TimelineTab: View {
}) })
.onChange(of: $popToRootTab.wrappedValue) { popToRootTab in .onChange(of: $popToRootTab.wrappedValue) { popToRootTab in
if popToRootTab == .timeline { if popToRootTab == .timeline {
if routeurPath.path.isEmpty { if routerPath.path.isEmpty {
scrollToTopSignal += 1 scrollToTopSignal += 1
} else { } else {
routeurPath.path = [] routerPath.path = []
} }
} }
} }
.onChange(of: currentAccount.account?.id) { _ in .onChange(of: currentAccount.account?.id) { _ in
routeurPath.path = [] routerPath.path = []
} }
.withSafariRouteur() .withSafariRouter()
.environmentObject(routeurPath) .environmentObject(routerPath)
} }
@ViewBuilder @ViewBuilder
@ -114,7 +114,7 @@ struct TimelineTab: View {
} }
} }
Button { Button {
routeurPath.presentedSheet = .addRemoteLocalTimeline routerPath.presentedSheet = .addRemoteLocalTimeline
} label: { } label: {
Label("Add a local timeline", systemImage: "badge.plus.radiowaves.right") Label("Add a local timeline", systemImage: "badge.plus.radiowaves.right")
} }
@ -123,7 +123,7 @@ struct TimelineTab: View {
private var addAccountButton: some View { private var addAccountButton: some View {
Button { Button {
routeurPath.presentedSheet = .addAccount routerPath.presentedSheet = .addAccount
} label: { } label: {
Image(systemName: "person.badge.plus") Image(systemName: "person.badge.plus")
} }
@ -139,10 +139,10 @@ struct TimelineTab: View {
if client.isAuth { if client.isAuth {
if UIDevice.current.userInterfaceIdiom != .pad { if UIDevice.current.userInterfaceIdiom != .pad {
ToolbarItem(placement: .navigationBarLeading) { ToolbarItem(placement: .navigationBarLeading) {
AppAccountsSelectorView(routeurPath: routeurPath) AppAccountsSelectorView(routerPath: routerPath)
} }
} }
statusEditorToolbarItem(routeurPath: routeurPath, statusEditorToolbarItem(routerPath: routerPath,
visibility: preferences.serverPreferences?.postVisibility ?? .pub) visibility: preferences.serverPreferences?.postVisibility ?? .pub)
} else { } else {
ToolbarItem(placement: .navigationBarTrailing) { ToolbarItem(placement: .navigationBarTrailing) {
@ -153,7 +153,7 @@ struct TimelineTab: View {
case let .list(list): case let .list(list):
ToolbarItem { ToolbarItem {
Button { Button {
routeurPath.presentedSheet = .listEdit(list: list) routerPath.presentedSheet = .listEdit(list: list)
} label: { } label: {
Image(systemName: "list.bullet") Image(systemName: "list.bullet")
} }

View file

@ -9,7 +9,7 @@ import SwiftUI
struct AccountDetailHeaderView: View { struct AccountDetailHeaderView: View {
@EnvironmentObject private var theme: Theme @EnvironmentObject private var theme: Theme
@EnvironmentObject private var quickLook: QuickLook @EnvironmentObject private var quickLook: QuickLook
@EnvironmentObject private var routeurPath: RouterPath @EnvironmentObject private var routerPath: RouterPath
@Environment(\.redactionReasons) private var reasons @Environment(\.redactionReasons) private var reasons
@ObservedObject var viewModel: AccountDetailViewModel @ObservedObject var viewModel: AccountDetailViewModel
@ -93,10 +93,10 @@ struct AccountDetailHeaderView: View {
} label: { } label: {
makeCustomInfoLabel(title: "Posts", count: account.statusesCount) makeCustomInfoLabel(title: "Posts", count: account.statusesCount)
} }
NavigationLink(value: RouteurDestinations.following(id: account.id)) { NavigationLink(value: RouterDestinations.following(id: account.id)) {
makeCustomInfoLabel(title: "Following", count: account.followingCount) makeCustomInfoLabel(title: "Following", count: account.followingCount)
} }
NavigationLink(value: RouteurDestinations.followers(id: account.id)) { NavigationLink(value: RouterDestinations.followers(id: account.id)) {
makeCustomInfoLabel(title: "Followers", count: account.followersCount) makeCustomInfoLabel(title: "Followers", count: account.followersCount)
} }
}.offset(y: 20) }.offset(y: 20)
@ -127,7 +127,7 @@ struct AccountDetailHeaderView: View {
.font(.body) .font(.body)
.padding(.top, 8) .padding(.top, 8)
.environment(\.openURL, OpenURLAction { url in .environment(\.openURL, OpenURLAction { url in
routeurPath.handle(url: url) routerPath.handle(url: url)
}) })
} }
.padding(.horizontal, .layoutPadding) .padding(.horizontal, .layoutPadding)

View file

@ -14,7 +14,7 @@ public struct AccountDetailView: View {
@EnvironmentObject private var preferences: UserPreferences @EnvironmentObject private var preferences: UserPreferences
@EnvironmentObject private var theme: Theme @EnvironmentObject private var theme: Theme
@EnvironmentObject private var client: Client @EnvironmentObject private var client: Client
@EnvironmentObject private var routeurPath: RouterPath @EnvironmentObject private var routerPath: RouterPath
@StateObject private var viewModel: AccountDetailViewModel @StateObject private var viewModel: AccountDetailViewModel
@State private var scrollOffset: CGFloat = 0 @State private var scrollOffset: CGFloat = 0
@ -41,7 +41,7 @@ public struct AccountDetailView: View {
} content: { } content: {
LazyVStack(alignment: .leading) { LazyVStack(alignment: .leading) {
makeHeaderView(proxy: proxy) makeHeaderView(proxy: proxy)
familliarFollowers familiarFollowers
.offset(y: -36) .offset(y: -36)
featuredTagsView featuredTagsView
.offset(y: -36) .offset(y: -36)
@ -163,7 +163,7 @@ public struct AccountDetailView: View {
if !viewModel.featuredTags.isEmpty { if !viewModel.featuredTags.isEmpty {
ForEach(viewModel.featuredTags) { tag in ForEach(viewModel.featuredTags) { tag in
Button { Button {
routeurPath.navigate(to: .hashTag(tag: tag.name, account: viewModel.accountId)) routerPath.navigate(to: .hashTag(tag: tag.name, account: viewModel.accountId))
} label: { } label: {
VStack(alignment: .leading, spacing: 0) { VStack(alignment: .leading, spacing: 0) {
Text("#\(tag.name)") Text("#\(tag.name)")
@ -181,18 +181,18 @@ public struct AccountDetailView: View {
} }
@ViewBuilder @ViewBuilder
private var familliarFollowers: some View { private var familiarFollowers: some View {
if !viewModel.familliarFollowers.isEmpty { if !viewModel.familiarFollowers.isEmpty {
VStack(alignment: .leading, spacing: 2) { VStack(alignment: .leading, spacing: 2) {
Text("Also followed by") Text("Also followed by")
.font(.headline) .font(.headline)
.padding(.leading, .layoutPadding) .padding(.leading, .layoutPadding)
ScrollView(.horizontal, showsIndicators: false) { ScrollView(.horizontal, showsIndicators: false) {
LazyHStack(spacing: 0) { LazyHStack(spacing: 0) {
ForEach(viewModel.familliarFollowers) { account in ForEach(viewModel.familiarFollowers) { account in
AvatarView(url: account.avatar, size: .badge) AvatarView(url: account.avatar, size: .badge)
.onTapGesture { .onTapGesture {
routeurPath.navigate(to: .accountDetailWithAccount(account: account)) routerPath.navigate(to: .accountDetailWithAccount(account: account))
} }
.padding(.leading, -4) .padding(.leading, -4)
} }
@ -265,7 +265,7 @@ public struct AccountDetailView: View {
private var listsListView: some View { private var listsListView: some View {
Group { Group {
ForEach(currentAccount.lists) { list in ForEach(currentAccount.lists) { list in
NavigationLink(value: RouteurDestinations.list(list: list)) { NavigationLink(value: RouterDestinations.list(list: list)) {
HStack { HStack {
Text(list.title) Text(list.title)
Spacer() Spacer()
@ -349,13 +349,13 @@ public struct AccountDetailView: View {
Section(account.acct) { Section(account.acct) {
if !viewModel.isCurrentUser { if !viewModel.isCurrentUser {
Button { Button {
routeurPath.presentedSheet = .mentionStatusEditor(account: account, routerPath.presentedSheet = .mentionStatusEditor(account: account,
visibility: preferences.serverPreferences?.postVisibility ?? .pub) visibility: preferences.serverPreferences?.postVisibility ?? .pub)
} label: { } label: {
Label("Mention", systemImage: "at") Label("Mention", systemImage: "at")
} }
Button { Button {
routeurPath.presentedSheet = .mentionStatusEditor(account: account, visibility: .direct) routerPath.presentedSheet = .mentionStatusEditor(account: account, visibility: .direct)
} label: { } label: {
Label("Message", systemImage: "tray.full") Label("Message", systemImage: "tray.full")
} }
@ -364,7 +364,7 @@ public struct AccountDetailView: View {
if viewModel.relationship?.following == true { if viewModel.relationship?.following == true {
Button { Button {
routeurPath.presentedSheet = .listAddAccount(account: account) routerPath.presentedSheet = .listAddAccount(account: account)
} label: { } label: {
Label("Add/Remove from lists", systemImage: "list.bullet") Label("Add/Remove from lists", systemImage: "list.bullet")
} }

View file

@ -60,7 +60,7 @@ class AccountDetailViewModel: ObservableObject, StatusesFetcher {
@Published var statusesState: StatusesState = .loading @Published var statusesState: StatusesState = .loading
@Published var relationship: Relationshionship? @Published var relationship: Relationship?
@Published var pinned: [Status] = [] @Published var pinned: [Status] = []
@Published var favourites: [Status] = [] @Published var favourites: [Status] = []
@Published var bookmarks: [Status] = [] @Published var bookmarks: [Status] = []
@ -68,7 +68,7 @@ class AccountDetailViewModel: ObservableObject, StatusesFetcher {
private var bookmarksNextPage: LinkHandler? private var bookmarksNextPage: LinkHandler?
@Published var featuredTags: [FeaturedTag] = [] @Published var featuredTags: [FeaturedTag] = []
@Published var fields: [Account.Field] = [] @Published var fields: [Account.Field] = []
@Published var familliarFollowers: [Account] = [] @Published var familiarFollowers: [Account] = []
@Published var selectedTab = Tab.statuses { @Published var selectedTab = Tab.statuses {
didSet { didSet {
switch selectedTab { switch selectedTab {
@ -104,8 +104,8 @@ class AccountDetailViewModel: ObservableObject, StatusesFetcher {
struct AccountData { struct AccountData {
let account: Account let account: Account
let featuredTags: [FeaturedTag] let featuredTags: [FeaturedTag]
let relationships: [Relationshionship] let relationships: [Relationship]
let familliarFollowers: [FamilliarAccounts] let familiarFollowers: [FamiliarAccounts]
} }
func fetchAccount() async { func fetchAccount() async {
@ -119,7 +119,7 @@ class AccountDetailViewModel: ObservableObject, StatusesFetcher {
featuredTags = data.featuredTags featuredTags = data.featuredTags
featuredTags.sort { $0.statusesCountInt > $1.statusesCountInt } featuredTags.sort { $0.statusesCountInt > $1.statusesCountInt }
relationship = data.relationships.first relationship = data.relationships.first
familliarFollowers = data.familliarFollowers.first?.accounts ?? [] familiarFollowers = data.familiarFollowers.first?.accounts ?? []
} catch { } catch {
if let account { if let account {
@ -134,17 +134,17 @@ class AccountDetailViewModel: ObservableObject, StatusesFetcher {
async let account: Account = client.get(endpoint: Accounts.accounts(id: accountId)) async let account: Account = client.get(endpoint: Accounts.accounts(id: accountId))
async let featuredTags: [FeaturedTag] = client.get(endpoint: Accounts.featuredTags(id: accountId)) async let featuredTags: [FeaturedTag] = client.get(endpoint: Accounts.featuredTags(id: accountId))
if client.isAuth && !isCurrentUser { if client.isAuth && !isCurrentUser {
async let relationships: [Relationshionship] = client.get(endpoint: Accounts.relationships(ids: [accountId])) async let relationships: [Relationship] = client.get(endpoint: Accounts.relationships(ids: [accountId]))
async let familliarFollowers: [FamilliarAccounts] = client.get(endpoint: Accounts.familiarFollowers(withAccount: accountId)) async let familiarFollowers: [FamiliarAccounts] = client.get(endpoint: Accounts.familiarFollowers(withAccount: accountId))
return try await .init(account: account, return try await .init(account: account,
featuredTags: featuredTags, featuredTags: featuredTags,
relationships: relationships, relationships: relationships,
familliarFollowers: familliarFollowers) familiarFollowers: familiarFollowers)
} }
return try await .init(account: account, return try await .init(account: account,
featuredTags: featuredTags, featuredTags: featuredTags,
relationships: [], relationships: [],
familliarFollowers: []) familiarFollowers: [])
} }
func fetchStatuses() async { func fetchStatuses() async {

View file

@ -10,9 +10,9 @@ public class AccountsListRowViewModel: ObservableObject {
var client: Client? var client: Client?
@Published var account: Account @Published var account: Account
@Published var relationShip: Relationshionship @Published var relationShip: Relationship
public init(account: Account, relationShip: Relationshionship) { public init(account: Account, relationShip: Relationship) {
self.account = account self.account = account
self.relationShip = relationShip self.relationShip = relationShip
} }
@ -20,7 +20,7 @@ public class AccountsListRowViewModel: ObservableObject {
public struct AccountsListRow: View { public struct AccountsListRow: View {
@EnvironmentObject private var currentAccount: CurrentAccount @EnvironmentObject private var currentAccount: CurrentAccount
@EnvironmentObject private var routeurPath: RouterPath @EnvironmentObject private var routerPath: RouterPath
@EnvironmentObject private var client: Client @EnvironmentObject private var client: Client
@StateObject var viewModel: AccountsListRowViewModel @StateObject var viewModel: AccountsListRowViewModel
@ -43,7 +43,7 @@ public struct AccountsListRow: View {
.font(.footnote) .font(.footnote)
.lineLimit(3) .lineLimit(3)
.environment(\.openURL, OpenURLAction { url in .environment(\.openURL, OpenURLAction { url in
routeurPath.handle(url: url) routerPath.handle(url: url)
}) })
} }
Spacer() Spacer()
@ -58,7 +58,7 @@ public struct AccountsListRow: View {
} }
.contentShape(Rectangle()) .contentShape(Rectangle())
.onTapGesture { .onTapGesture {
routeurPath.navigate(to: .accountDetailWithAccount(account: viewModel.account)) routerPath.navigate(to: .accountDetailWithAccount(account: viewModel.account))
} }
} }
} }

View file

@ -33,13 +33,13 @@ class AccountsListViewModel: ObservableObject {
case loading case loading
case display(accounts: [Account], case display(accounts: [Account],
relationships: [Relationshionship], relationships: [Relationship],
nextPageState: PagingState) nextPageState: PagingState)
case error(error: Error) case error(error: Error)
} }
private var accounts: [Account] = [] private var accounts: [Account] = []
private var relationships: [Relationshionship] = [] private var relationships: [Relationship] = []
@Published var state = State.loading @Published var state = State.loading
@ -98,7 +98,7 @@ class AccountsListViewModel: ObservableObject {
maxId: nextPageId)) maxId: nextPageId))
} }
accounts.append(contentsOf: newAccounts) accounts.append(contentsOf: newAccounts)
let newRelationships: [Relationshionship] = let newRelationships: [Relationship] =
try await client.get(endpoint: Accounts.relationships(ids: newAccounts.map { $0.id })) try await client.get(endpoint: Accounts.relationships(ids: newAccounts.map { $0.id }))
relationships.append(contentsOf: newRelationships) relationships.append(contentsOf: newRelationships)

View file

@ -9,10 +9,10 @@ public class FollowButtonViewModel: ObservableObject {
public let accountId: String public let accountId: String
public let shouldDisplayNotify: Bool public let shouldDisplayNotify: Bool
@Published public private(set) var relationship: Relationshionship @Published public private(set) var relationship: Relationship
@Published public private(set) var isUpdating: Bool = false @Published public private(set) var isUpdating: Bool = false
public init(accountId: String, relationship: Relationshionship, shouldDisplayNotify: Bool) { public init(accountId: String, relationship: Relationship, shouldDisplayNotify: Bool) {
self.accountId = accountId self.accountId = accountId
self.relationship = relationship self.relationship = relationship
self.shouldDisplayNotify = shouldDisplayNotify self.shouldDisplayNotify = shouldDisplayNotify

View file

@ -4,7 +4,7 @@ import Env
import SwiftUI import SwiftUI
public struct AppAccountView: View { public struct AppAccountView: View {
@EnvironmentObject private var routeurPath: RouterPath @EnvironmentObject private var routerPath: RouterPath
@EnvironmentObject var appAccounts: AppAccountsManager @EnvironmentObject var appAccounts: AppAccountsManager
@StateObject var viewModel: AppAccountViewModel @StateObject var viewModel: AppAccountViewModel
@ -45,7 +45,7 @@ public struct AppAccountView: View {
if appAccounts.currentAccount.id == viewModel.appAccount.id, if appAccounts.currentAccount.id == viewModel.appAccount.id,
let account = viewModel.account let account = viewModel.account
{ {
routeurPath.navigate(to: .accountDetailWithAccount(account: account)) routerPath.navigate(to: .accountDetailWithAccount(account: account))
} else { } else {
appAccounts.currentAccount = viewModel.appAccount appAccounts.currentAccount = viewModel.appAccount
} }

View file

@ -6,18 +6,18 @@ public struct AppAccountsSelectorView: View {
@EnvironmentObject private var currentAccount: CurrentAccount @EnvironmentObject private var currentAccount: CurrentAccount
@EnvironmentObject private var appAccounts: AppAccountsManager @EnvironmentObject private var appAccounts: AppAccountsManager
@ObservedObject var routeurPath: RouterPath @ObservedObject var routerPath: RouterPath
@State private var accountsViewModel: [AppAccountViewModel] = [] @State private var accountsViewModel: [AppAccountViewModel] = []
private let accountCreationEnabled: Bool private let accountCreationEnabled: Bool
private let avatarSize: AvatarView.Size private let avatarSize: AvatarView.Size
public init(routeurPath: RouterPath, public init(routerPath: RouterPath,
accountCreationEnabled: Bool = true, accountCreationEnabled: Bool = true,
avatarSize: AvatarView.Size = .badge) avatarSize: AvatarView.Size = .badge)
{ {
self.routeurPath = routeurPath self.routerPath = routerPath
self.accountCreationEnabled = accountCreationEnabled self.accountCreationEnabled = accountCreationEnabled
self.avatarSize = avatarSize self.avatarSize = avatarSize
} }
@ -62,7 +62,7 @@ public struct AppAccountsSelectorView: View {
if let account = currentAccount.account, if let account = currentAccount.account,
viewModel.account?.id == account.id viewModel.account?.id == account.id
{ {
routeurPath.navigate(to: .accountDetailWithAccount(account: account)) routerPath.navigate(to: .accountDetailWithAccount(account: account))
} else { } else {
appAccounts.currentAccount = viewModel.appAccount appAccounts.currentAccount = viewModel.appAccount
} }
@ -79,7 +79,7 @@ public struct AppAccountsSelectorView: View {
if accountCreationEnabled { if accountCreationEnabled {
Divider() Divider()
Button { Button {
routeurPath.presentedSheet = .addAccount routerPath.presentedSheet = .addAccount
} label: { } label: {
Label("Add Account", systemImage: "person.badge.plus") Label("Add Account", systemImage: "person.badge.plus")
} }

View file

@ -6,7 +6,7 @@ import Shimmer
import SwiftUI import SwiftUI
public struct ConversationsListView: View { public struct ConversationsListView: View {
@EnvironmentObject private var routeurPath: RouterPath @EnvironmentObject private var routerPath: RouterPath
@EnvironmentObject private var watcher: StreamWatcher @EnvironmentObject private var watcher: StreamWatcher
@EnvironmentObject private var client: Client @EnvironmentObject private var client: Client
@EnvironmentObject private var theme: Theme @EnvironmentObject private var theme: Theme

View file

@ -4,10 +4,10 @@ import SwiftUI
@MainActor @MainActor
public extension View { public extension View {
func statusEditorToolbarItem(routeurPath: RouterPath, visibility: Models.Visibility) -> some ToolbarContent { func statusEditorToolbarItem(routerPath: RouterPath, visibility: Models.Visibility) -> some ToolbarContent {
ToolbarItem(placement: .navigationBarTrailing) { ToolbarItem(placement: .navigationBarTrailing) {
Button { Button {
routeurPath.presentedSheet = .newStatusEditor(visibility: visibility) routerPath.presentedSheet = .newStatusEditor(visibility: visibility)
} label: { } label: {
Image(systemName: "square.and.pencil") Image(systemName: "square.and.pencil")
} }

View file

@ -3,7 +3,7 @@ import Models
import SwiftUI import SwiftUI
public struct TagRowView: View { public struct TagRowView: View {
@EnvironmentObject private var routeurPath: RouterPath @EnvironmentObject private var routerPath: RouterPath
let tag: Tag let tag: Tag
@ -24,7 +24,7 @@ public struct TagRowView: View {
} }
.contentShape(Rectangle()) .contentShape(Rectangle())
.onTapGesture { .onTapGesture {
routeurPath.navigate(to: .hashTag(tag: tag.name, account: nil)) routerPath.navigate(to: .hashTag(tag: tag.name, account: nil))
} }
} }
} }

View file

@ -160,7 +160,7 @@ public class PushNotificationsService: ObservableObject {
{ {
return data return data
} else { } else {
let key = Self.makeRandomeNotificationsAuthKey() let key = Self.makeRandomNotificationsAuthKey()
keychain.set(key.base64EncodedString(), keychain.set(key.base64EncodedString(),
forKey: Constants.keychainAuthKey, forKey: Constants.keychainAuthKey,
withAccess: .accessibleAfterFirstUnlock) withAccess: .accessibleAfterFirstUnlock)
@ -168,7 +168,7 @@ public class PushNotificationsService: ObservableObject {
} }
} }
private static func makeRandomeNotificationsAuthKey() -> Data { private static func makeRandomNotificationsAuthKey() -> Data {
let byteCount = 16 let byteCount = 16
var bytes = Data(count: byteCount) var bytes = Data(count: byteCount)
_ = bytes.withUnsafeMutableBytes { SecRandomCopyBytes(kSecRandomDefault, byteCount, $0.baseAddress!) } _ = bytes.withUnsafeMutableBytes { SecRandomCopyBytes(kSecRandomDefault, byteCount, $0.baseAddress!) }

View file

@ -3,7 +3,7 @@ import Models
import Network import Network
import SwiftUI import SwiftUI
public enum RouteurDestinations: Hashable { public enum RouterDestinations: Hashable {
case accountDetail(id: String) case accountDetail(id: String)
case accountDetailWithAccount(account: Account) case accountDetailWithAccount(account: Account)
case statusDetail(id: String) case statusDetail(id: String)
@ -48,12 +48,12 @@ public class RouterPath: ObservableObject {
public var client: Client? public var client: Client?
public var urlHandler: ((URL) -> OpenURLAction.Result)? public var urlHandler: ((URL) -> OpenURLAction.Result)?
@Published public var path: [RouteurDestinations] = [] @Published public var path: [RouterDestinations] = []
@Published public var presentedSheet: SheetDestinations? @Published public var presentedSheet: SheetDestinations?
public init() {} public init() {}
public func navigate(to: RouteurDestinations) { public func navigate(to: RouterDestinations) {
path.append(to) path.append(to)
} }

View file

@ -10,7 +10,7 @@ import SwiftUI
public struct ExploreView: View { public struct ExploreView: View {
@EnvironmentObject private var theme: Theme @EnvironmentObject private var theme: Theme
@EnvironmentObject private var client: Client @EnvironmentObject private var client: Client
@EnvironmentObject private var routeurPath: RouterPath @EnvironmentObject private var routerPath: RouterPath
@StateObject private var viewModel = ExploreViewModel() @StateObject private var viewModel = ExploreViewModel()

View file

@ -49,7 +49,7 @@ class ExploreViewModel: ObservableObject {
@Published var results: [String: SearchResults] = [:] @Published var results: [String: SearchResults] = [:]
@Published var isLoaded = false @Published var isLoaded = false
@Published var suggestedAccounts: [Account] = [] @Published var suggestedAccounts: [Account] = []
@Published var suggestedAccountsRelationShips: [Relationshionship] = [] @Published var suggestedAccountsRelationShips: [Relationship] = []
@Published var trendingTags: [Tag] = [] @Published var trendingTags: [Tag] = []
@Published var trendingStatuses: [Status] = [] @Published var trendingStatuses: [Status] = []
@Published var trendingLinks: [Card] = [] @Published var trendingLinks: [Card] = []
@ -126,7 +126,7 @@ class ExploreViewModel: ObservableObject {
offset: nil, offset: nil,
following: nil), following: nil),
forceVersion: .v2) forceVersion: .v2)
let relationships: [Relationshionship] = let relationships: [Relationship] =
try await client.get(endpoint: Accounts.relationships(ids: results.accounts.map { $0.id })) try await client.get(endpoint: Accounts.relationships(ids: results.accounts.map { $0.id }))
results.relationships = relationships results.relationships = relationships
self.results[searchQuery] = results self.results[searchQuery] = results

View file

@ -71,7 +71,7 @@ public struct Account: Codable, Identifiable, Equatable, Hashable {
} }
} }
public struct FamilliarAccounts: Codable { public struct FamiliarAccounts: Codable {
public let id: String public let id: String
public let accounts: [Account] public let accounts: [Account]
} }

View file

@ -1,6 +1,6 @@
import Foundation import Foundation
public struct MediaAttachement: Codable, Identifiable, Hashable { public struct MediaAttachment: Codable, Identifiable, Hashable {
public struct MetaContainer: Codable, Equatable { public struct MetaContainer: Codable, Equatable {
public struct Meta: Codable, Equatable { public struct Meta: Codable, Equatable {
public let width: Int? public let width: Int?

View file

@ -1,6 +1,6 @@
import Foundation import Foundation
public struct Relationshionship: Codable { public struct Relationship: Codable {
public let id: String public let id: String
public let following: Bool public let following: Bool
public let showingReblogs: Bool public let showingReblogs: Bool
@ -15,7 +15,7 @@ public struct Relationshionship: Codable {
public let note: String public let note: String
public let notifying: Bool public let notifying: Bool
public static func placeholder() -> Relationshionship { public static func placeholder() -> Relationship {
.init(id: UUID().uuidString, .init(id: UUID().uuidString,
following: false, following: false,
showingReblogs: false, showingReblogs: false,

View file

@ -6,7 +6,7 @@ public struct SearchResults: Decodable {
} }
public let accounts: [Account] public let accounts: [Account]
public var relationships: [Relationshionship] = [] public var relationships: [Relationship] = []
public let statuses: [Status] public let statuses: [Status]
public let hashtags: [Tag] public let hashtags: [Tag]
} }

View file

@ -4,7 +4,7 @@ public struct ServerPreferences: Decodable {
public let postVisibility: Visibility? public let postVisibility: Visibility?
public let postIsSensitive: Bool? public let postIsSensitive: Bool?
public let postLanguage: String? public let postLanguage: String?
public let autoExpandmedia: AutoExpandMedia? public let autoExpandMedia: AutoExpandMedia?
public let autoExpandSpoilers: Bool? public let autoExpandSpoilers: Bool?
public enum AutoExpandMedia: String, Decodable { public enum AutoExpandMedia: String, Decodable {
@ -17,7 +17,7 @@ public struct ServerPreferences: Decodable {
case postVisibility = "posting:default:visibility" case postVisibility = "posting:default:visibility"
case postIsSensitive = "posting:default:sensitive" case postIsSensitive = "posting:default:sensitive"
case postLanguage = "posting:default:language" case postLanguage = "posting:default:language"
case autoExpandmedia = "reading:expand:media" case autoExpandMedia = "reading:expand:media"
case autoExpandSpoilers = "reading:expand:spoilers" case autoExpandSpoilers = "reading:expand:spoilers"
} }
} }

View file

@ -32,7 +32,7 @@ public protocol AnyStatus {
var account: Account { get } var account: Account { get }
var createdAt: ServerDate { get } var createdAt: ServerDate { get }
var editedAt: ServerDate? { get } var editedAt: ServerDate? { get }
var mediaAttachments: [MediaAttachement] { get } var mediaAttachments: [MediaAttachment] { get }
var mentions: [Mention] { get } var mentions: [Mention] { get }
var repliesCount: Int { get } var repliesCount: Int { get }
var reblogsCount: Int { get } var reblogsCount: Int { get }
@ -65,7 +65,7 @@ public struct Status: AnyStatus, Codable, Identifiable {
public let createdAt: ServerDate public let createdAt: ServerDate
public let editedAt: ServerDate? public let editedAt: ServerDate?
public let reblog: ReblogStatus? public let reblog: ReblogStatus?
public let mediaAttachments: [MediaAttachement] public let mediaAttachments: [MediaAttachment]
public let mentions: [Mention] public let mentions: [Mention]
public let repliesCount: Int public let repliesCount: Int
public let reblogsCount: Int public let reblogsCount: Int
@ -130,7 +130,7 @@ public struct ReblogStatus: AnyStatus, Codable, Identifiable {
public let account: Account public let account: Account
public let createdAt: String public let createdAt: String
public let editedAt: ServerDate? public let editedAt: ServerDate?
public let mediaAttachments: [MediaAttachement] public let mediaAttachments: [MediaAttachment]
public let mentions: [Mention] public let mentions: [Mention]
public let repliesCount: Int public let repliesCount: Int
public let reblogsCount: Int public let reblogsCount: Int

View file

@ -7,7 +7,7 @@ import SwiftUI
struct NotificationRowView: View { struct NotificationRowView: View {
@EnvironmentObject private var theme: Theme @EnvironmentObject private var theme: Theme
@EnvironmentObject private var routeurPath: RouterPath @EnvironmentObject private var routerPath: RouterPath
@Environment(\.redactionReasons) private var reasons @Environment(\.redactionReasons) private var reasons
let notification: Models.Notification let notification: Models.Notification
@ -44,7 +44,7 @@ struct NotificationRowView: View {
} }
.contentShape(Rectangle()) .contentShape(Rectangle())
.onTapGesture { .onTapGesture {
routeurPath.navigate(to: .accountDetailWithAccount(account: notification.account)) routerPath.navigate(to: .accountDetailWithAccount(account: notification.account))
} }
} }
@ -74,7 +74,7 @@ struct NotificationRowView: View {
} }
.contentShape(Rectangle()) .contentShape(Rectangle())
.onTapGesture { .onTapGesture {
routeurPath.navigate(to: .accountDetailWithAccount(account: notification.account)) routerPath.navigate(to: .accountDetailWithAccount(account: notification.account))
} }
} }
@ -103,13 +103,13 @@ struct NotificationRowView: View {
.font(.callout) .font(.callout)
.foregroundColor(.gray) .foregroundColor(.gray)
.environment(\.openURL, OpenURLAction { url in .environment(\.openURL, OpenURLAction { url in
routeurPath.handle(url: url) routerPath.handle(url: url)
}) })
} }
} }
.contentShape(Rectangle()) .contentShape(Rectangle())
.onTapGesture { .onTapGesture {
routeurPath.navigate(to: .accountDetailWithAccount(account: notification.account)) routerPath.navigate(to: .accountDetailWithAccount(account: notification.account))
} }
} }
} }

View file

@ -114,8 +114,8 @@ public struct NotificationsListView: View {
} }
case .error: case .error:
ErrorView(title: "An error occured", ErrorView(title: "An error occurred",
message: "An error occured while loading your notifications, please retry.", message: "An error occurred while loading your notifications, please retry.",
buttonTitle: "Retry") { buttonTitle: "Retry") {
Task { Task {
await viewModel.fetchNotifications() await viewModel.fetchNotifications()

View file

@ -10,7 +10,7 @@ public struct StatusDetailView: View {
@EnvironmentObject private var currentAccount: CurrentAccount @EnvironmentObject private var currentAccount: CurrentAccount
@EnvironmentObject private var watcher: StreamWatcher @EnvironmentObject private var watcher: StreamWatcher
@EnvironmentObject private var client: Client @EnvironmentObject private var client: Client
@EnvironmentObject private var routeurPath: RouterPath @EnvironmentObject private var routerPath: RouterPath
@Environment(\.openURL) private var openURL @Environment(\.openURL) private var openURL
@StateObject private var viewModel: StatusDetailViewModel @StateObject private var viewModel: StatusDetailViewModel
@State private var isLoaded: Bool = false @State private var isLoaded: Bool = false
@ -63,8 +63,8 @@ public struct StatusDetailView: View {
} }
case .error: case .error:
ErrorView(title: "An error occured", ErrorView(title: "An error occurred",
message: "An error occured while this post context, please try again.", message: "An error occurred while this post context, please try again.",
buttonTitle: "Retry") { buttonTitle: "Retry") {
Task { Task {
await viewModel.fetch() await viewModel.fetch()
@ -86,7 +86,7 @@ public struct StatusDetailView: View {
openURL(url) openURL(url)
} }
DispatchQueue.main.async { DispatchQueue.main.async {
_ = routeurPath.path.popLast() _ = routerPath.path.popLast()
} }
} }
DispatchQueue.main.async { DispatchQueue.main.async {

View file

@ -12,7 +12,7 @@ struct StatusEditorAccessoryView: View {
@FocusState<Bool>.Binding var isSpoilerTextFocused: Bool @FocusState<Bool>.Binding var isSpoilerTextFocused: Bool
@ObservedObject var viewModel: StatusEditorViewModel @ObservedObject var viewModel: StatusEditorViewModel
@State private var isDrafsSheetDisplayed: Bool = false @State private var isDraftsSheetDisplayed: Bool = false
@State private var isLanguageSheetDisplayed: Bool = false @State private var isLanguageSheetDisplayed: Bool = false
@State private var languageSearch: String = "" @State private var languageSearch: String = ""
@ -46,7 +46,7 @@ struct StatusEditorAccessoryView: View {
if !viewModel.mode.isInShareExtension { if !viewModel.mode.isInShareExtension {
Button { Button {
isDrafsSheetDisplayed = true isDraftsSheetDisplayed = true
} label: { } label: {
Image(systemName: "archivebox") Image(systemName: "archivebox")
} }
@ -71,7 +71,7 @@ struct StatusEditorAccessoryView: View {
.padding(.vertical, 12) .padding(.vertical, 12)
.background(.ultraThinMaterial) .background(.ultraThinMaterial)
} }
.sheet(isPresented: $isDrafsSheetDisplayed) { .sheet(isPresented: $isDraftsSheetDisplayed) {
draftsSheetView draftsSheetView
} }
.sheet(isPresented: $isLanguageSheetDisplayed, content: { .sheet(isPresented: $isLanguageSheetDisplayed, content: {
@ -133,7 +133,7 @@ struct StatusEditorAccessoryView: View {
.listRowBackground(theme.primaryBackgroundColor) .listRowBackground(theme.primaryBackgroundColor)
.onTapGesture { .onTapGesture {
viewModel.insertStatusText(text: draft) viewModel.insertStatusText(text: draft)
isDrafsSheetDisplayed = false isDraftsSheetDisplayed = false
} }
} }
.onDelete { indexes in .onDelete { indexes in
@ -144,7 +144,7 @@ struct StatusEditorAccessoryView: View {
} }
.toolbar { .toolbar {
ToolbarItem(placement: .navigationBarLeading) { ToolbarItem(placement: .navigationBarLeading) {
Button("Cancel", action: { isDrafsSheetDisplayed = false }) Button("Cancel", action: { isDraftsSheetDisplayed = false })
} }
} }
.scrollContentBackground(.hidden) .scrollContentBackground(.hidden)

View file

@ -19,7 +19,7 @@ struct StatusEditorMediaEditView: View {
} }
.listRowBackground(theme.primaryBackgroundColor) .listRowBackground(theme.primaryBackgroundColor)
Section { Section {
if let url = container.mediaAttachement?.url { if let url = container.mediaAttachment?.url {
AsyncImage( AsyncImage(
url: url, url: url,
content: { image in content: { image in
@ -43,7 +43,7 @@ struct StatusEditorMediaEditView: View {
.scrollContentBackground(.hidden) .scrollContentBackground(.hidden)
.background(theme.secondaryBackgroundColor) .background(theme.secondaryBackgroundColor)
.onAppear { .onAppear {
imageDescription = container.mediaAttachement?.description ?? "" imageDescription = container.mediaAttachment?.description ?? ""
} }
.navigationTitle("Edit Image") .navigationTitle("Edit Image")
.navigationBarTitleDisplayMode(.inline) .navigationBarTitleDisplayMode(.inline)

View file

@ -19,10 +19,10 @@ struct StatusEditorMediaView: View {
ZStack(alignment: .bottomTrailing) { ZStack(alignment: .bottomTrailing) {
if container.image != nil { if container.image != nil {
makeLocalImage(container: container) makeLocalImage(container: container)
} else if let url = container.mediaAttachement?.url ?? container.mediaAttachement?.previewUrl { } else if let url = container.mediaAttachment?.url ?? container.mediaAttachment?.previewUrl {
makeLazyImage(url: url) makeLazyImage(url: url)
} }
if container.mediaAttachement?.description?.isEmpty == false { if container.mediaAttachment?.description?.isEmpty == false {
altMarker altMarker
} }
} }
@ -41,7 +41,7 @@ struct StatusEditorMediaView: View {
ZStack(alignment: .center) { ZStack(alignment: .center) {
Image(uiImage: container.image!) Image(uiImage: container.image!)
.resizable() .resizable()
.blur(radius: container.mediaAttachement == nil ? 20 : 0) .blur(radius: container.mediaAttachment == nil ? 20 : 0)
.aspectRatio(contentMode: .fill) .aspectRatio(contentMode: .fill)
.frame(width: 150, height: 150) .frame(width: 150, height: 150)
.cornerRadius(8) .cornerRadius(8)
@ -69,7 +69,7 @@ struct StatusEditorMediaView: View {
} }
.buttonStyle(.bordered) .buttonStyle(.bordered)
} }
} else if container.mediaAttachement == nil { } else if container.mediaAttachment == nil {
ProgressView() ProgressView()
} }
} }
@ -96,7 +96,7 @@ struct StatusEditorMediaView: View {
Button { Button {
editingContainer = container editingContainer = container
} label: { } label: {
Label(container.mediaAttachement?.description?.isEmpty == false ? Label(container.mediaAttachment?.description?.isEmpty == false ?
"Edit description" : "Add description", "Edit description" : "Add description",
systemImage: "pencil.line") systemImage: "pencil.line")
} }

View file

@ -41,14 +41,14 @@ public struct StatusEditorView: View {
.placeholder("What's on your mind") .placeholder("What's on your mind")
.padding(.horizontal, .layoutPadding) .padding(.horizontal, .layoutPadding)
StatusEditorMediaView(viewModel: viewModel) StatusEditorMediaView(viewModel: viewModel)
if let status = viewModel.embededStatus { if let status = viewModel.embeddedStatus {
StatusEmbededView(status: status) StatusEmbeddedView(status: status)
.padding(.horizontal, .layoutPadding) .padding(.horizontal, .layoutPadding)
.disabled(true) .disabled(true)
} else if let status = viewModel.replyToStatus { } else if let status = viewModel.replyToStatus {
Divider() Divider()
.padding(.top, 20) .padding(.top, 20)
StatusEmbededView(status: status) StatusEmbeddedView(status: status)
.padding(.horizontal, .layoutPadding) .padding(.horizontal, .layoutPadding)
.disabled(true) .disabled(true)
} }
@ -158,7 +158,7 @@ public struct StatusEditorView: View {
private var accountHeaderView: some View { private var accountHeaderView: some View {
if let account = currentAccount.account { if let account = currentAccount.account {
HStack { HStack {
AppAccountsSelectorView(routeurPath: RouterPath(), AppAccountsSelectorView(routerPath: RouterPath(),
accountCreationEnabled: false, accountCreationEnabled: false,
avatarSize: .status) avatarSize: .status)
VStack(alignment: .leading, spacing: 4) { VStack(alignment: .leading, spacing: 4) {
@ -210,10 +210,10 @@ public struct StatusEditorView: View {
prompt.label prompt.label
} }
} }
if let backup = viewModel.backupStatustext { if let backup = viewModel.backupStatusText {
Button { Button {
viewModel.replaceTextWith(text: backup.string) viewModel.replaceTextWith(text: backup.string)
viewModel.backupStatustext = nil viewModel.backupStatusText = nil
} label: { } label: {
Label("Restore previous text", systemImage: "arrow.uturn.right") Label("Restore previous text", systemImage: "arrow.uturn.right")
} }

View file

@ -10,7 +10,7 @@ public class StatusEditorViewModel: ObservableObject {
struct ImageContainer: Identifiable { struct ImageContainer: Identifiable {
let id = UUID().uuidString let id = UUID().uuidString
let image: UIImage? let image: UIImage?
let mediaAttachement: MediaAttachement? let mediaAttachment: MediaAttachment?
let error: Error? let error: Error?
} }
@ -28,7 +28,7 @@ public class StatusEditorViewModel: ObservableObject {
} }
} }
@Published var backupStatustext: NSAttributedString? @Published var backupStatusText: NSAttributedString?
@Published var showPoll: Bool = false @Published var showPoll: Bool = false
@Published var pollVotingFrequency = PollVotingFrequency.oneVote @Published var pollVotingFrequency = PollVotingFrequency.oneVote
@ -52,7 +52,7 @@ public class StatusEditorViewModel: ObservableObject {
@Published var mediasImages: [ImageContainer] = [] @Published var mediasImages: [ImageContainer] = []
@Published var replyToStatus: Status? @Published var replyToStatus: Status?
@Published var embededStatus: Status? @Published var embeddedStatus: Status?
var canPost: Bool { var canPost: Bool {
statusText.length > 0 || !mediasImages.isEmpty statusText.length > 0 || !mediasImages.isEmpty
} }
@ -68,8 +68,8 @@ public class StatusEditorViewModel: ObservableObject {
@Published var selectedLanguage: String? @Published var selectedLanguage: String?
private var currentSuggestionRange: NSRange? private var currentSuggestionRange: NSRange?
private var embededStatusURL: URL? { private var embeddedStatusURL: URL? {
return embededStatus?.reblog?.url ?? embededStatus?.url return embeddedStatus?.reblog?.url ?? embeddedStatus?.url
} }
private var uploadTask: Task<Void, Never>? private var uploadTask: Task<Void, Never>?
@ -129,7 +129,7 @@ public class StatusEditorViewModel: ObservableObject {
visibility: visibility, visibility: visibility,
inReplyToId: mode.replyToStatus?.id, inReplyToId: mode.replyToStatus?.id,
spoilerText: spoilerOn ? spoilerText : nil, spoilerText: spoilerOn ? spoilerText : nil,
mediaIds: mediasImages.compactMap { $0.mediaAttachement?.id }, mediaIds: mediasImages.compactMap { $0.mediaAttachment?.id },
poll: pollData, poll: pollData,
language: selectedLanguage) language: selectedLanguage)
switch mode { switch mode {
@ -185,10 +185,10 @@ public class StatusEditorViewModel: ObservableObject {
spoilerOn = !status.spoilerText.isEmpty spoilerOn = !status.spoilerText.isEmpty
spoilerText = status.spoilerText spoilerText = status.spoilerText
visibility = status.visibility visibility = status.visibility
mediasImages = status.mediaAttachments.map { .init(image: nil, mediaAttachement: $0, error: nil) } mediasImages = status.mediaAttachments.map { .init(image: nil, mediaAttachment: $0, error: nil) }
case let .quote(status): case let .quote(status):
embededStatus = status embeddedStatus = status
if let url = embededStatusURL { if let url = embeddedStatusURL {
statusText = .init(string: "\n\nFrom: @\(status.reblog?.account.acct ?? status.account.acct)\n\(url)") statusText = .init(string: "\n\nFrom: @\(status.reblog?.account.acct ?? status.account.acct)\n\(url)")
selectedRange = .init(location: 0, length: 0) selectedRange = .init(location: 0, length: 0)
} }
@ -243,16 +243,16 @@ public class StatusEditorViewModel: ObservableObject {
range: NSRange(location: range.location, length: range.length)) range: NSRange(location: range.location, length: range.length))
} }
var attachementsToRemove: [NSRange] = [] var attachmentsToRemove: [NSRange] = []
statusText.enumerateAttribute(.attachment, in: range) { attachement, _, _ in statusText.enumerateAttribute(.attachment, in: range) { attachment, _, _ in
if let attachement = attachement as? NSTextAttachment, let image = attachement.image { if let attachment = attachment as? NSTextAttachment, let image = attachment.image {
attachementsToRemove.append(range) attachmentsToRemove.append(range)
mediasImages.append(.init(image: image, mediaAttachement: nil, error: nil)) mediasImages.append(.init(image: image, mediaAttachment: nil, error: nil))
} }
} }
if !attachementsToRemove.isEmpty { if !attachmentsToRemove.isEmpty {
processMediasToUpload() processMediasToUpload()
for range in attachementsToRemove { for range in attachmentsToRemove {
statusText.removeAttribute(.attachment, range: range) statusText.removeAttribute(.attachment, range: range)
} }
} }
@ -261,23 +261,23 @@ public class StatusEditorViewModel: ObservableObject {
private func processItemsProvider(items: [NSItemProvider]) { private func processItemsProvider(items: [NSItemProvider]) {
Task { Task {
var initalText: String = "" var initialText: String = ""
for item in items { for item in items {
if let identifiter = item.registeredTypeIdentifiers.first, if let identifier = item.registeredTypeIdentifiers.first,
let handledItemType = StatusEditorUTTypeSupported(rawValue: identifiter) let handledItemType = StatusEditorUTTypeSupported(rawValue: identifier)
{ {
do { do {
let content = try await handledItemType.loadItemContent(item: item) let content = try await handledItemType.loadItemContent(item: item)
if let text = content as? String { if let text = content as? String {
initalText += "\(text) " initialText += "\(text) "
} else if let image = content as? UIImage { } else if let image = content as? UIImage {
mediasImages.append(.init(image: image, mediaAttachement: nil, error: nil)) mediasImages.append(.init(image: image, mediaAttachment: nil, error: nil))
} }
} catch {} } catch {}
} }
} }
if !initalText.isEmpty { if !initialText.isEmpty {
statusText = .init(string: initalText) statusText = .init(string: initialText)
selectedRange = .init(location: statusText.string.utf16.count, length: 0) selectedRange = .init(location: statusText.string.utf16.count, length: 0)
} }
if !mediasImages.isEmpty { if !mediasImages.isEmpty {
@ -293,11 +293,11 @@ public class StatusEditorViewModel: ObservableObject {
} }
private func checkEmbed() { private func checkEmbed() {
if let url = embededStatusURL, if let url = embeddedStatusURL,
!statusText.string.contains(url.absoluteString) !statusText.string.contains(url.absoluteString)
{ {
embededStatus = nil embeddedStatus = nil
mode = .new(vivibilty: visibility) mode = .new(visibility: visibility)
} }
} }
@ -361,7 +361,7 @@ public class StatusEditorViewModel: ObservableObject {
if var text = response.choices.first?.text { if var text = response.choices.first?.text {
text.removeFirst() text.removeFirst()
text.removeFirst() text.removeFirst()
backupStatustext = statusText backupStatusText = statusText
replaceTextWith(text: text) replaceTextWith(text: text)
} }
} catch {} } catch {}
@ -383,10 +383,10 @@ public class StatusEditorViewModel: ObservableObject {
if let data = try await media.loadTransferable(type: Data.self), if let data = try await media.loadTransferable(type: Data.self),
let image = UIImage(data: data) let image = UIImage(data: data)
{ {
medias.append(.init(image: image, mediaAttachement: nil, error: nil)) medias.append(.init(image: image, mediaAttachment: nil, error: nil))
} }
} catch { } catch {
medias.append(.init(image: nil, mediaAttachement: nil, error: error)) medias.append(.init(image: nil, mediaAttachment: nil, error: error))
} }
} }
DispatchQueue.main.async { [weak self] in DispatchQueue.main.async { [weak self] in
@ -411,37 +411,37 @@ public class StatusEditorViewModel: ObservableObject {
func upload(container: ImageContainer) async { func upload(container: ImageContainer) async {
if let index = indexOf(container: container) { if let index = indexOf(container: container) {
let originalContainer = mediasImages[index] let originalContainer = mediasImages[index]
let newContainer = ImageContainer(image: originalContainer.image, mediaAttachement: nil, error: nil) let newContainer = ImageContainer(image: originalContainer.image, mediaAttachment: nil, error: nil)
mediasImages[index] = newContainer mediasImages[index] = newContainer
do { do {
if let data = originalContainer.image?.jpegData(compressionQuality: 0.90) { if let data = originalContainer.image?.jpegData(compressionQuality: 0.90) {
let uploadedMedia = try await uploadMedia(data: data) let uploadedMedia = try await uploadMedia(data: data)
if let index = indexOf(container: newContainer) { if let index = indexOf(container: newContainer) {
mediasImages[index] = .init(image: mode.isInShareExtension ? originalContainer.image : nil, mediasImages[index] = .init(image: mode.isInShareExtension ? originalContainer.image : nil,
mediaAttachement: uploadedMedia, mediaAttachment: uploadedMedia,
error: nil) error: nil)
} }
} }
} catch { } catch {
if let index = indexOf(container: newContainer) { if let index = indexOf(container: newContainer) {
mediasImages[index] = .init(image: originalContainer.image, mediaAttachement: nil, error: error) mediasImages[index] = .init(image: originalContainer.image, mediaAttachment: nil, error: error)
} }
} }
} }
} }
func addDescription(container: ImageContainer, description: String) async { func addDescription(container: ImageContainer, description: String) async {
guard let client, let attachment = container.mediaAttachement else { return } guard let client, let attachment = container.mediaAttachment else { return }
if let index = indexOf(container: container) { if let index = indexOf(container: container) {
do { do {
let media: MediaAttachement = try await client.put(endpoint: Media.media(id: attachment.id, let media: MediaAttachment = try await client.put(endpoint: Media.media(id: attachment.id,
description: description)) description: description))
mediasImages[index] = .init(image: nil, mediaAttachement: media, error: nil) mediasImages[index] = .init(image: nil, mediaAttachment: media, error: nil)
} catch {} } catch {}
} }
} }
private func uploadMedia(data: Data) async throws -> MediaAttachement? { private func uploadMedia(data: Data) async throws -> MediaAttachment? {
guard let client else { return nil } guard let client else { return nil }
return try await client.mediaUpload(endpoint: Media.medias, return try await client.mediaUpload(endpoint: Media.medias,
version: .v2, version: .v2,

View file

@ -4,7 +4,7 @@ import UIKit
public extension StatusEditorViewModel { public extension StatusEditorViewModel {
enum Mode { enum Mode {
case replyTo(status: Status) case replyTo(status: Status)
case new(vivibilty: Visibility) case new(visibility: Visibility)
case edit(status: Status) case edit(status: Status)
case quote(status: Status) case quote(status: Status)
case mention(account: Account, visibility: Visibility) case mention(account: Account, visibility: Visibility)

View file

@ -4,7 +4,7 @@ import Models
import SwiftUI import SwiftUI
@MainActor @MainActor
public struct StatusEmbededView: View { public struct StatusEmbeddedView: View {
@EnvironmentObject private var theme: Theme @EnvironmentObject private var theme: Theme
public let status: Status public let status: Status

View file

@ -25,8 +25,8 @@ public struct StatusesListView<Fetcher>: View where Fetcher: StatusesFetcher {
.padding(.vertical, .dividerPadding) .padding(.vertical, .dividerPadding)
} }
case .error: case .error:
ErrorView(title: "An error occured", ErrorView(title: "An error occurred",
message: "An error occured while loading posts, please try again.", message: "An error occurred while loading posts, please try again.",
buttonTitle: "Retry") { buttonTitle: "Retry") {
Task { Task {
await fetcher.fetchStatuses() await fetcher.fetchStatuses()

View file

@ -7,7 +7,7 @@ import SwiftUI
struct StatusActionsView: View { struct StatusActionsView: View {
@Environment(\.openURL) private var openURL @Environment(\.openURL) private var openURL
@EnvironmentObject private var theme: Theme @EnvironmentObject private var theme: Theme
@EnvironmentObject private var routeurPath: RouterPath @EnvironmentObject private var routerPath: RouterPath
@ObservedObject var viewModel: StatusRowViewModel @ObservedObject var viewModel: StatusRowViewModel
let generator = UINotificationFeedbackGenerator() let generator = UINotificationFeedbackGenerator()
@ -119,7 +119,7 @@ struct StatusActionsView: View {
if viewModel.favouritesCount > 0 { if viewModel.favouritesCount > 0 {
Divider() Divider()
NavigationLink(value: RouteurDestinations.favouritedBy(id: viewModel.status.id)) { NavigationLink(value: RouterDestinations.favouritedBy(id: viewModel.status.id)) {
Text("\(viewModel.favouritesCount) favorites") Text("\(viewModel.favouritesCount) favorites")
.font(.callout) .font(.callout)
Spacer() Spacer()
@ -128,7 +128,7 @@ struct StatusActionsView: View {
} }
if viewModel.reblogsCount > 0 { if viewModel.reblogsCount > 0 {
Divider() Divider()
NavigationLink(value: RouteurDestinations.rebloggedBy(id: viewModel.status.id)) { NavigationLink(value: RouterDestinations.rebloggedBy(id: viewModel.status.id)) {
Text("\(viewModel.reblogsCount) boosts") Text("\(viewModel.reblogsCount) boosts")
.font(.callout) .font(.callout)
Spacer() Spacer()
@ -142,7 +142,7 @@ struct StatusActionsView: View {
generator.notificationOccurred(.success) generator.notificationOccurred(.success)
switch action { switch action {
case .respond: case .respond:
routeurPath.presentedSheet = .replyToStatusEditor(status: viewModel.status) routerPath.presentedSheet = .replyToStatusEditor(status: viewModel.status)
case .favourite: case .favourite:
if viewModel.isFavourited { if viewModel.isFavourited {
await viewModel.unFavourite() await viewModel.unFavourite()

View file

@ -10,7 +10,7 @@ public struct StatusMediaPreviewView: View {
@EnvironmentObject private var quickLook: QuickLook @EnvironmentObject private var quickLook: QuickLook
@EnvironmentObject private var theme: Theme @EnvironmentObject private var theme: Theme
public let attachements: [MediaAttachement] public let attachments: [MediaAttachment]
public let sensitive: Bool public let sensitive: Bool
public let isNotifications: Bool public let isNotifications: Bool
@ -30,13 +30,13 @@ public struct StatusMediaPreviewView: View {
if theme.statusDisplayStyle == .compact { if theme.statusDisplayStyle == .compact {
return 100 return 100
} }
if attachements.count == 1 { if attachments.count == 1 {
return 300 return 300
} }
return attachements.count > 2 ? 100 : 200 return attachments.count > 2 ? 100 : 200
} }
private func size(for media: MediaAttachement) -> CGSize? { private func size(for media: MediaAttachment) -> CGSize? {
if isNotifications { if isNotifications {
return .init(width: 50, height: 50) return .init(width: 50, height: 50)
} }
@ -62,30 +62,30 @@ public struct StatusMediaPreviewView: View {
public var body: some View { public var body: some View {
Group { Group {
if attachements.count == 1, let attachement = attachements.first { if attachments.count == 1, let attachment = attachments.first {
makeFeaturedImagePreview(attachement: attachement) makeFeaturedImagePreview(attachment: attachment)
.onTapGesture { .onTapGesture {
Task { Task {
await quickLook.prepareFor(urls: attachements.compactMap { $0.url }, selectedURL: attachement.url!) await quickLook.prepareFor(urls: attachments.compactMap { $0.url }, selectedURL: attachment.url!)
} }
} }
} else { } else {
if isNotifications || theme.statusDisplayStyle == .compact { if isNotifications || theme.statusDisplayStyle == .compact {
HStack { HStack {
makeAttachementView(for: 0) makeAttachmentView(for: 0)
makeAttachementView(for: 1) makeAttachmentView(for: 1)
makeAttachementView(for: 2) makeAttachmentView(for: 2)
makeAttachementView(for: 3) makeAttachmentView(for: 3)
} }
} else { } else {
VStack { VStack {
HStack { HStack {
makeAttachementView(for: 0) makeAttachmentView(for: 0)
makeAttachementView(for: 1) makeAttachmentView(for: 1)
} }
HStack { HStack {
makeAttachementView(for: 2) makeAttachmentView(for: 2)
makeAttachementView(for: 3) makeAttachmentView(for: 3)
} }
} }
} }
@ -109,9 +109,9 @@ public struct StatusMediaPreviewView: View {
Text(altTextDisplayed ?? "") Text(altTextDisplayed ?? "")
} }
.onAppear { .onAppear {
if sensitive && preferences.serverPreferences?.autoExpandmedia == .hideSensitive { if sensitive && preferences.serverPreferences?.autoExpandMedia == .hideSensitive {
isHidingMedia = true isHidingMedia = true
} else if preferences.serverPreferences?.autoExpandmedia == .hideAll { } else if preferences.serverPreferences?.autoExpandMedia == .hideAll {
isHidingMedia = true isHidingMedia = true
} else { } else {
isHidingMedia = false isHidingMedia = false
@ -120,18 +120,18 @@ public struct StatusMediaPreviewView: View {
} }
@ViewBuilder @ViewBuilder
private func makeAttachementView(for index: Int) -> some View { private func makeAttachmentView(for index: Int) -> some View {
if attachements.count > index { if attachments.count > index {
makePreview(attachement: attachements[index]) makePreview(attachment: attachments[index])
} }
} }
@ViewBuilder @ViewBuilder
private func makeFeaturedImagePreview(attachement: MediaAttachement) -> some View { private func makeFeaturedImagePreview(attachment: MediaAttachment) -> some View {
switch attachement.supportedType { switch attachment.supportedType {
case .image: case .image:
if theme.statusDisplayStyle == .large, if theme.statusDisplayStyle == .large,
let size = size(for: attachement), let size = size(for: attachment),
UIDevice.current.userInterfaceIdiom != .pad, UIDevice.current.userInterfaceIdiom != .pad,
UIDevice.current.userInterfaceIdiom != .mac UIDevice.current.userInterfaceIdiom != .mac
{ {
@ -140,7 +140,7 @@ public struct StatusMediaPreviewView: View {
let newSize = imageSize(from: size, let newSize = imageSize(from: size,
newWidth: availableWidth) newWidth: availableWidth)
ZStack(alignment: .bottomTrailing) { ZStack(alignment: .bottomTrailing) {
LazyImage(url: attachement.url) { state in LazyImage(url: attachment.url) { state in
if let image = state.image { if let image = state.image {
image image
.resizingMode(.aspectFill) .resizingMode(.aspectFill)
@ -156,7 +156,7 @@ public struct StatusMediaPreviewView: View {
if sensitive { if sensitive {
cornerSensitiveButton cornerSensitiveButton
} }
if let alt = attachement.description, !alt.isEmpty, !isNotifications { if let alt = attachment.description, !alt.isEmpty, !isNotifications {
Button { Button {
altTextDisplayed = alt altTextDisplayed = alt
isAltAlertDisplayed = true isAltAlertDisplayed = true
@ -170,7 +170,7 @@ public struct StatusMediaPreviewView: View {
} }
} else { } else {
AsyncImage( AsyncImage(
url: attachement.url, url: attachment.url,
content: { image in content: { image in
image image
.resizable() .resizable()
@ -187,7 +187,7 @@ public struct StatusMediaPreviewView: View {
) )
} }
case .gifv, .video, .audio: case .gifv, .video, .audio:
if let url = attachement.url { if let url = attachment.url {
VideoPlayerView(viewModel: .init(url: url)) VideoPlayerView(viewModel: .init(url: url))
.frame(height: imageMaxHeight) .frame(height: imageMaxHeight)
} }
@ -197,14 +197,14 @@ public struct StatusMediaPreviewView: View {
} }
@ViewBuilder @ViewBuilder
private func makePreview(attachement: MediaAttachement) -> some View { private func makePreview(attachment: MediaAttachment) -> some View {
if let type = attachement.supportedType { if let type = attachment.supportedType {
Group { Group {
GeometryReader { proxy in GeometryReader { proxy in
switch type { switch type {
case .image: case .image:
ZStack(alignment: .bottomTrailing) { ZStack(alignment: .bottomTrailing) {
LazyImage(url: attachement.url) { state in LazyImage(url: attachment.url) { state in
if let image = state.image { if let image = state.image {
image image
.resizingMode(.aspectFill) .resizingMode(.aspectFill)
@ -222,7 +222,7 @@ public struct StatusMediaPreviewView: View {
if sensitive { if sensitive {
cornerSensitiveButton cornerSensitiveButton
} }
if let alt = attachement.description, !alt.isEmpty, !isNotifications { if let alt = attachment.description, !alt.isEmpty, !isNotifications {
Button { Button {
altTextDisplayed = alt altTextDisplayed = alt
isAltAlertDisplayed = true isAltAlertDisplayed = true
@ -236,7 +236,7 @@ public struct StatusMediaPreviewView: View {
} }
} }
case .gifv, .video, .audio: case .gifv, .video, .audio:
if let url = attachement.url { if let url = attachment.url {
VideoPlayerView(viewModel: .init(url: url)) VideoPlayerView(viewModel: .init(url: url))
.frame(width: isNotifications ? imageMaxHeight : proxy.frame(in: .local).width) .frame(width: isNotifications ? imageMaxHeight : proxy.frame(in: .local).width)
.frame(height: imageMaxHeight) .frame(height: imageMaxHeight)
@ -248,7 +248,7 @@ public struct StatusMediaPreviewView: View {
} }
.onTapGesture { .onTapGesture {
Task { Task {
await quickLook.prepareFor(urls: attachements.compactMap { $0.url }, selectedURL: attachement.url!) await quickLook.prepareFor(urls: attachments.compactMap { $0.url }, selectedURL: attachment.url!)
} }
} }
} }

View file

@ -4,7 +4,7 @@ import SwiftUI
struct StatusRowContextMenu: View { struct StatusRowContextMenu: View {
@EnvironmentObject private var account: CurrentAccount @EnvironmentObject private var account: CurrentAccount
@EnvironmentObject private var routeurPath: RouterPath @EnvironmentObject private var routerPath: RouterPath
@Environment(\.openURL) var openURL @Environment(\.openURL) var openURL
@ -41,7 +41,7 @@ struct StatusRowContextMenu: View {
systemImage: "bookmark") systemImage: "bookmark")
} }
Button { Button {
routeurPath.presentedSheet = .replyToStatusEditor(status: viewModel.status) routerPath.presentedSheet = .replyToStatusEditor(status: viewModel.status)
} label: { } label: {
Label("Reply", systemImage: "arrowshape.turn.up.left") Label("Reply", systemImage: "arrowshape.turn.up.left")
} }
@ -49,7 +49,7 @@ struct StatusRowContextMenu: View {
if viewModel.status.visibility == .pub, !viewModel.isRemote { if viewModel.status.visibility == .pub, !viewModel.isRemote {
Button { Button {
routeurPath.presentedSheet = .quoteStatusEditor(status: viewModel.status) routerPath.presentedSheet = .quoteStatusEditor(status: viewModel.status)
} label: { } label: {
Label("Quote this post", systemImage: "quote.bubble") Label("Quote this post", systemImage: "quote.bubble")
} }
@ -89,7 +89,7 @@ struct StatusRowContextMenu: View {
Label(viewModel.isPinned ? "Unpin" : "Pin", systemImage: viewModel.isPinned ? "pin.fill" : "pin") Label(viewModel.isPinned ? "Unpin" : "Pin", systemImage: viewModel.isPinned ? "pin.fill" : "pin")
} }
Button { Button {
routeurPath.presentedSheet = .editStatusEditor(status: viewModel.status) routerPath.presentedSheet = .editStatusEditor(status: viewModel.status)
} label: { } label: {
Label("Edit", systemImage: "pencil") Label("Edit", systemImage: "pencil")
} }
@ -100,12 +100,12 @@ struct StatusRowContextMenu: View {
} else if !viewModel.isRemote { } else if !viewModel.isRemote {
Section(viewModel.status.account.acct) { Section(viewModel.status.account.acct) {
Button { Button {
routeurPath.presentedSheet = .mentionStatusEditor(account: viewModel.status.account, visibility: .pub) routerPath.presentedSheet = .mentionStatusEditor(account: viewModel.status.account, visibility: .pub)
} label: { } label: {
Label("Mention", systemImage: "at") Label("Mention", systemImage: "at")
} }
Button { Button {
routeurPath.presentedSheet = .mentionStatusEditor(account: viewModel.status.account, visibility: .direct) routerPath.presentedSheet = .mentionStatusEditor(account: viewModel.status.account, visibility: .direct)
} label: { } label: {
Label("Message", systemImage: "tray.full") Label("Message", systemImage: "tray.full")
} }

View file

@ -12,7 +12,7 @@ public struct StatusRowView: View {
@EnvironmentObject private var account: CurrentAccount @EnvironmentObject private var account: CurrentAccount
@EnvironmentObject private var theme: Theme @EnvironmentObject private var theme: Theme
@EnvironmentObject private var client: Client @EnvironmentObject private var client: Client
@EnvironmentObject private var routeurPath: RouterPath @EnvironmentObject private var routerPath: RouterPath
@StateObject var viewModel: StatusRowViewModel @StateObject var viewModel: StatusRowViewModel
public init(viewModel: StatusRowViewModel) { public init(viewModel: StatusRowViewModel) {
@ -34,7 +34,7 @@ public struct StatusRowView: View {
let status: AnyStatus = viewModel.status.reblog ?? viewModel.status let status: AnyStatus = viewModel.status.reblog ?? viewModel.status
{ {
Button { Button {
routeurPath.navigate(to: .accountDetailWithAccount(account: status.account)) routerPath.navigate(to: .accountDetailWithAccount(account: status.account))
} label: { } label: {
AvatarView(url: status.account.avatar, size: .status) AvatarView(url: status.account.avatar, size: .status)
} }
@ -51,16 +51,16 @@ public struct StatusRowView: View {
.tint(viewModel.isFocused ? theme.tintColor : .gray) .tint(viewModel.isFocused ? theme.tintColor : .gray)
.contentShape(Rectangle()) .contentShape(Rectangle())
.onTapGesture { .onTapGesture {
viewModel.navigateToDetail(routeurPath: routeurPath) viewModel.navigateToDetail(routerPath: routerPath)
} }
} }
} }
} }
.onAppear { .onAppear {
viewModel.client = client viewModel.client = client
if !viewModel.isCompact, viewModel.embededStatus == nil { if !viewModel.isCompact, viewModel.embeddedStatus == nil {
Task { Task {
await viewModel.loadEmbededStatus() await viewModel.loadEmbeddedStatus()
} }
} }
if preferences.serverPreferences?.autoExpandSpoilers == true { if preferences.serverPreferences?.autoExpandSpoilers == true {
@ -74,7 +74,7 @@ public struct StatusRowView: View {
Color.clear Color.clear
.contentShape(Rectangle()) .contentShape(Rectangle())
.onTapGesture { .onTapGesture {
viewModel.navigateToDetail(routeurPath: routeurPath) viewModel.navigateToDetail(routerPath: routerPath)
} }
} }
} }
@ -112,10 +112,10 @@ public struct StatusRowView: View {
.onTapGesture { .onTapGesture {
if viewModel.isRemote, let url = viewModel.status.account.url { if viewModel.isRemote, let url = viewModel.status.account.url {
Task { Task {
await routeurPath.navigateToAccountFrom(url: url) await routerPath.navigateToAccountFrom(url: url)
} }
} else { } else {
routeurPath.navigate(to: .accountDetailWithAccount(account: viewModel.status.account)) routerPath.navigate(to: .accountDetailWithAccount(account: viewModel.status.account))
} }
} }
} }
@ -137,10 +137,10 @@ public struct StatusRowView: View {
.onTapGesture { .onTapGesture {
if viewModel.isRemote { if viewModel.isRemote {
Task { Task {
await routeurPath.navigateToAccountFrom(url: mention.url) await routerPath.navigateToAccountFrom(url: mention.url)
} }
} else { } else {
routeurPath.navigate(to: .accountDetail(id: mention.id)) routerPath.navigate(to: .accountDetail(id: mention.id))
} }
} }
} }
@ -154,10 +154,10 @@ public struct StatusRowView: View {
Button { Button {
if viewModel.isRemote, let url = status.account.url { if viewModel.isRemote, let url = status.account.url {
Task { Task {
await routeurPath.navigateToAccountFrom(url: url) await routerPath.navigateToAccountFrom(url: url)
} }
} else { } else {
routeurPath.navigate(to: .accountDetailWithAccount(account: status.account)) routerPath.navigate(to: .accountDetailWithAccount(account: status.account))
} }
} label: { } label: {
accountView(status: status) accountView(status: status)
@ -169,7 +169,7 @@ public struct StatusRowView: View {
makeStatusContentView(status: status) makeStatusContentView(status: status)
.contentShape(Rectangle()) .contentShape(Rectangle())
.onTapGesture { .onTapGesture {
viewModel.navigateToDetail(routeurPath: routeurPath) viewModel.navigateToDetail(routerPath: routerPath)
} }
} }
} }
@ -194,16 +194,16 @@ public struct StatusRowView: View {
EmojiTextApp(status.content.asMarkdown, emojis: status.emojis) EmojiTextApp(status.content.asMarkdown, emojis: status.emojis)
.font(.body) .font(.body)
.environment(\.openURL, OpenURLAction { url in .environment(\.openURL, OpenURLAction { url in
routeurPath.handleStatus(status: status, url: url) routerPath.handleStatus(status: status, url: url)
}) })
Spacer() Spacer()
} }
if !reasons.contains(.placeholder) { if !reasons.contains(.placeholder) {
if !viewModel.isCompact, !viewModel.isEmbedLoading, let embed = viewModel.embededStatus { if !viewModel.isCompact, !viewModel.isEmbedLoading, let embed = viewModel.embeddedStatus {
StatusEmbededView(status: embed) StatusEmbeddedView(status: embed)
} else if viewModel.isEmbedLoading, !viewModel.isCompact { } else if viewModel.isEmbedLoading, !viewModel.isCompact {
StatusEmbededView(status: .placeholder()) StatusEmbeddedView(status: .placeholder())
.redacted(reason: .placeholder) .redacted(reason: .placeholder)
.shimmering() .shimmering()
} }
@ -216,21 +216,21 @@ public struct StatusRowView: View {
if !status.mediaAttachments.isEmpty { if !status.mediaAttachments.isEmpty {
if theme.statusDisplayStyle == .compact { if theme.statusDisplayStyle == .compact {
HStack { HStack {
StatusMediaPreviewView(attachements: status.mediaAttachments, StatusMediaPreviewView(attachments: status.mediaAttachments,
sensitive: status.sensitive, sensitive: status.sensitive,
isNotifications: viewModel.isCompact) isNotifications: viewModel.isCompact)
Spacer() Spacer()
} }
.padding(.vertical, 4) .padding(.vertical, 4)
} else { } else {
StatusMediaPreviewView(attachements: status.mediaAttachments, StatusMediaPreviewView(attachments: status.mediaAttachments,
sensitive: status.sensitive, sensitive: status.sensitive,
isNotifications: viewModel.isCompact) isNotifications: viewModel.isCompact)
.padding(.vertical, 4) .padding(.vertical, 4)
} }
} }
if let card = status.card, if let card = status.card,
viewModel.embededStatus?.url != status.card?.url, viewModel.embeddedStatus?.url != status.card?.url,
status.mediaAttachments.isEmpty, status.mediaAttachments.isEmpty,
!viewModel.isEmbedLoading, !viewModel.isEmbedLoading,
theme.statusDisplayStyle == .large theme.statusDisplayStyle == .large

View file

@ -18,7 +18,7 @@ public class StatusRowViewModel: ObservableObject {
@Published var isBookmarked: Bool @Published var isBookmarked: Bool
@Published var reblogsCount: Int @Published var reblogsCount: Int
@Published var repliesCount: Int @Published var repliesCount: Int
@Published var embededStatus: Status? @Published var embeddedStatus: Status?
@Published var displaySpoiler: Bool = false @Published var displaySpoiler: Bool = false
@Published var isEmbedLoading: Bool = true @Published var isEmbedLoading: Bool = true
@Published var isFiltered: Bool = false @Published var isFiltered: Bool = false
@ -59,15 +59,15 @@ public class StatusRowViewModel: ObservableObject {
isFiltered = filter != nil isFiltered = filter != nil
} }
func navigateToDetail(routeurPath: RouterPath) { func navigateToDetail(routerPath: RouterPath) {
if isRemote, let url = status.reblog?.url ?? status.url { if isRemote, let url = status.reblog?.url ?? status.url {
routeurPath.navigate(to: .remoteStatusDetail(url: url)) routerPath.navigate(to: .remoteStatusDetail(url: url))
} else { } else {
routeurPath.navigate(to: .statusDetail(id: status.reblog?.id ?? status.id)) routerPath.navigate(to: .statusDetail(id: status.reblog?.id ?? status.id))
} }
} }
func loadEmbededStatus() async { func loadEmbeddedStatus() async {
guard let client, guard let client,
let urls = status.content.findStatusesURLs(), let urls = status.content.findStatusesURLs(),
!urls.isEmpty, !urls.isEmpty,
@ -93,7 +93,7 @@ public class StatusRowViewModel: ObservableObject {
embed = results.statuses.first embed = results.statuses.first
} }
withAnimation { withAnimation {
embededStatus = embed embeddedStatus = embed
isEmbedLoading = false isEmbedLoading = false
} }
} catch { } catch {