From 052b3c99eefa0d2483d950151ee86239b9365168 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Fri, 22 Dec 2023 12:40:19 +0800 Subject: [PATCH] Fixes for users with the accessibility buttonShapes feature enabled on iOS --- .../Share/Views/ShareExtensionView.swift | 11 +- .../App/Views/BottomBars/CustomTabBar.swift | 2 +- .../App/Views/BottomBars/CustomToolBar.swift | 2 +- .../LibraryFeatureCardNavigationLink.swift | 1 + .../LibraryItemListNavigationLink.swift | 1 + .../App/Views/Home/HomeFeedViewIOS.swift | 203 +++++++----------- .../App/Views/Profile/FiltersView.swift | 8 +- .../Views/Profile/NewsletterEmailsView.swift | 5 +- .../App/Views/Profile/SubscriptionsView.swift | 3 +- .../Views/WebReader/WebReaderContainer.swift | 53 +++-- .../Sources/App/Views/WelcomeView.swift | 1 + 11 files changed, 135 insertions(+), 155 deletions(-) diff --git a/apple/OmnivoreKit/Sources/App/AppExtensions/Share/Views/ShareExtensionView.swift b/apple/OmnivoreKit/Sources/App/AppExtensions/Share/Views/ShareExtensionView.swift index cc5fcb6a6..808cb0dd0 100644 --- a/apple/OmnivoreKit/Sources/App/AppExtensions/Share/Views/ShareExtensionView.swift +++ b/apple/OmnivoreKit/Sources/App/AppExtensions/Share/Views/ShareExtensionView.swift @@ -140,8 +140,11 @@ public struct ShareExtensionView: View { Text("Add Labels").font(Font.system(size: 12, weight: .medium)).tint(Color.white) } icon: { Image.label.resizable(resizingMode: .stretch).frame(width: 17, height: 17).tint(Color.white) - }.padding(.leading, 10).padding(.trailing, 12) + } + .foregroundColor(Color.white) + .padding(.leading, 10).padding(.trailing, 12) }) + .buttonStyle(.plain) .frame(height: 28) .background(Color.blue) .cornerRadius(24) @@ -243,7 +246,7 @@ public struct ShareExtensionView: View { .aspectRatio(contentMode: .fit) .frame(width: 15, height: 15) } - } + }.buttonStyle(.plain) } var closeButton: some View { @@ -262,7 +265,7 @@ public struct ShareExtensionView: View { .font(Font.title.weight(.bold)) .frame(width: 12, height: 12) } - }) + }).buttonStyle(.plain) } var titleBar: some View { @@ -337,12 +340,14 @@ public struct ShareExtensionView: View { viewModel.handleReadNowAction(extensionContext: extensionContext) }, label: { Text("Read Now") + .foregroundColor(Color.white) #if os(iOS) .font(Font.system(size: 17, weight: .semibold)) .tint(Color.white) .padding(20) #endif }) + .buttonStyle(.plain) #if os(iOS) .frame(height: 50) .background(Color.blue) diff --git a/apple/OmnivoreKit/Sources/App/Views/BottomBars/CustomTabBar.swift b/apple/OmnivoreKit/Sources/App/Views/BottomBars/CustomTabBar.swift index 4c489aeb8..4b9691d12 100644 --- a/apple/OmnivoreKit/Sources/App/Views/BottomBars/CustomTabBar.swift +++ b/apple/OmnivoreKit/Sources/App/Views/BottomBars/CustomTabBar.swift @@ -38,6 +38,6 @@ struct TabBarButton: View { .frame(width: 28, height: 28) .foregroundColor(selectedTab == key ? Color.blue : Color.themeTabButtonColor) .frame(maxWidth: .infinity) - }) + }).buttonStyle(.plain) } } diff --git a/apple/OmnivoreKit/Sources/App/Views/BottomBars/CustomToolBar.swift b/apple/OmnivoreKit/Sources/App/Views/BottomBars/CustomToolBar.swift index 6cc415cee..19f0fc262 100644 --- a/apple/OmnivoreKit/Sources/App/Views/BottomBars/CustomToolBar.swift +++ b/apple/OmnivoreKit/Sources/App/Views/BottomBars/CustomToolBar.swift @@ -61,6 +61,6 @@ struct ToolBarButton: View { .frame(width: 28, height: 28) .foregroundColor(ThemeManager.currentTheme.toolbarColor) .frame(maxWidth: .infinity) - }) + }).buttonStyle(.plain) } } diff --git a/apple/OmnivoreKit/Sources/App/Views/Home/Components/LibraryFeatureCardNavigationLink.swift b/apple/OmnivoreKit/Sources/App/Views/Home/Components/LibraryFeatureCardNavigationLink.swift index 07e1d86d9..22c9cba70 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Home/Components/LibraryFeatureCardNavigationLink.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Home/Components/LibraryFeatureCardNavigationLink.swift @@ -38,6 +38,7 @@ struct LibraryFeatureCardNavigationLink: View { LibraryFeatureCard(item: item, viewer: dataService.currentViewer) } ) + .buttonStyle(.plain) .confirmationDialog("", isPresented: $showFeatureActions) { if FeaturedItemFilter(rawValue: viewModel.fetcher.featureFilter) == .pinned { Button("Unpin", action: { diff --git a/apple/OmnivoreKit/Sources/App/Views/Home/Components/LibraryItemListNavigationLink.swift b/apple/OmnivoreKit/Sources/App/Views/Home/Components/LibraryItemListNavigationLink.swift index 5fb630fce..582c7ee7b 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Home/Components/LibraryItemListNavigationLink.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Home/Components/LibraryItemListNavigationLink.swift @@ -86,6 +86,7 @@ struct LibraryItemGridCardNavigationLink: View { GridCard(item: LibraryItemData.make(from: item), isContextMenuOpen: $isContextMenuOpen, actionHandler: actionHandler) } ) + .buttonStyle(.plain) .aspectRatio(1.0, contentMode: .fill) .background( Color.secondarySystemGroupedBackground diff --git a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift index 7aac80d8c..26de7a666 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift @@ -7,6 +7,76 @@ import UserNotifications import Utils import Views +struct FiltersHeader: View { + @ObservedObject var viewModel: HomeFeedViewModel + + var body: some View { + GeometryReader { reader in + ScrollView(.horizontal, showsIndicators: false) { + HStack { + if viewModel.searchTerm.count > 0 { + TextChipButton.makeSearchFilterButton(title: viewModel.searchTerm) { + viewModel.searchTerm = "" + }.frame(maxWidth: reader.size.width * 0.66) + } else { + if UIDevice.isIPhone { + Menu( + content: { + ForEach(viewModel.filters) { filter in + Button(filter.name, action: { + viewModel.appliedFilter = filter + }) + } + }, + label: { + TextChipButton.makeMenuButton( + title: viewModel.appliedFilter?.name ?? "-", + color: .systemGray6 + ) + } + ).buttonStyle(.plain) + } + } + Menu( + content: { + ForEach(LinkedItemSort.allCases, id: \.self) { sort in + Button(sort.displayName, action: { viewModel.appliedSort = sort.rawValue }) + } + }, + label: { + TextChipButton.makeMenuButton( + title: LinkedItemSort(rawValue: viewModel.appliedSort)?.displayName ?? "Sort", + color: .systemGray6 + ) + } + ).buttonStyle(.plain) + + TextChipButton.makeAddLabelButton(color: .systemGray6, onTap: { viewModel.showLabelsSheet = true }) + ForEach(viewModel.selectedLabels, id: \.self) { label in + TextChipButton.makeRemovableLabelButton(feedItemLabel: label, negated: false) { + viewModel.selectedLabels.removeAll { $0.id == label.id } + } + } + ForEach(viewModel.negatedLabels, id: \.self) { label in + TextChipButton.makeRemovableLabelButton(feedItemLabel: label, negated: true) { + viewModel.negatedLabels.removeAll { $0.id == label.id } + } + } + Spacer() + } + } + } + .padding(.top, 0) + .padding(.bottom, 10) + .padding(.leading, 15) + .listRowSpacing(0) + .listRowInsets(.init(top: 0, leading: 0, bottom: 0, trailing: 0)) + .frame(maxWidth: .infinity, minHeight: 38) + .background(Color.systemBackground) + .dynamicTypeSize(.small ... .accessibility1) + } +} + struct AnimatingCellHeight: AnimatableModifier { var height: CGFloat = 0 @@ -189,7 +259,6 @@ struct AnimatingCellHeight: AnimatableModifier { action: { isEditMode = isEditMode == .active ? .inactive : .active }, label: { Image.selectMultiple - .foregroundColor(Color.appGrayTextContrast) } ) } @@ -211,14 +280,12 @@ struct AnimatingCellHeight: AnimatableModifier { }, label: { Image.addLink - .foregroundColor(Color.appGrayTextContrast) } ) Button( action: { searchPresented = true }, label: { Image.magnifyingGlass - .foregroundColor(Color.appGrayTextContrast) } ) } @@ -229,10 +296,12 @@ struct AnimatingCellHeight: AnimatableModifier { viewModel.bulkAction(dataService: dataService, action: .archive, items: Array(selection)) isEditMode = .inactive }, label: { Image(systemName: "archivebox") }) + .padding(.trailing, 10) Button(action: { viewModel.bulkAction(dataService: dataService, action: .delete, items: Array(selection)) isEditMode = .inactive }, label: { Image(systemName: "trash") }) + .padding(.trailing, 10) Spacer() Text("\(selection.count) selected").font(.footnote) Spacer() @@ -350,72 +419,12 @@ struct AnimatingCellHeight: AnimatableModifier { @ObservedObject var networkMonitor = NetworkMonitor() var filtersHeader: some View { - GeometryReader { reader in - ScrollView(.horizontal, showsIndicators: false) { - HStack { - if viewModel.searchTerm.count > 0 { - TextChipButton.makeSearchFilterButton(title: viewModel.searchTerm) { - viewModel.searchTerm = "" - }.frame(maxWidth: reader.size.width * 0.66) - } else { - if UIDevice.isIPhone { - Menu( - content: { - ForEach(viewModel.filters) { filter in - Button(filter.name, action: { - viewModel.appliedFilter = filter - }) - } - }, - label: { - TextChipButton.makeMenuButton( - title: viewModel.appliedFilter?.name ?? "-", - color: .systemGray6 - ) - } - ) - } - } - Menu( - content: { - ForEach(LinkedItemSort.allCases, id: \.self) { sort in - Button(sort.displayName, action: { viewModel.appliedSort = sort.rawValue }) - } - }, - label: { - TextChipButton.makeMenuButton( - title: LinkedItemSort(rawValue: viewModel.appliedSort)?.displayName ?? "Sort", - color: .systemGray6 - ) - } - ) - TextChipButton.makeAddLabelButton(color: .systemGray6, onTap: { viewModel.showLabelsSheet = true }) - ForEach(viewModel.selectedLabels, id: \.self) { label in - TextChipButton.makeRemovableLabelButton(feedItemLabel: label, negated: false) { - viewModel.selectedLabels.removeAll { $0.id == label.id } - } - } - ForEach(viewModel.negatedLabels, id: \.self) { label in - TextChipButton.makeRemovableLabelButton(feedItemLabel: label, negated: true) { - viewModel.negatedLabels.removeAll { $0.id == label.id } - } - } - Spacer() - } - } - } - .padding(.top, 0) - .padding(.bottom, 10) - .padding(.leading, 15) - .listRowSpacing(0) - .listRowInsets(.init(top: 0, leading: 0, bottom: 0, trailing: 0)) - .frame(maxWidth: .infinity, minHeight: 38) - .background(Color.systemBackground) - .overlay(Rectangle() - .padding(.leading, 15) - .frame(width: nil, height: 0.5, alignment: .bottom) - .foregroundColor(isListScrolled ? Color(hex: "#3D3D3D") : Color.systemBackground), alignment: .bottom) - .dynamicTypeSize(.small ... .accessibility1) + FiltersHeader(viewModel: viewModel) + .overlay(Rectangle() + .padding(.leading, 15) + .frame(width: nil, height: 0.5, alignment: .bottom) + .foregroundColor(isListScrolled ? Color(hex: "#3D3D3D") : Color.systemBackground), alignment: .bottom) + .dynamicTypeSize(.small ... .accessibility1) } func menuItems(for item: Models.LibraryItem) -> some View { @@ -464,7 +473,7 @@ struct AnimatingCellHeight: AnimatableModifier { .background(Color(hex: "#007AFF")?.opacity(0.1)) .cornerRadius(5) }.frame(maxWidth: .infinity, alignment: .leading) - }) + }).buttonStyle(.plain) Spacer() } .padding(.top, 10) @@ -820,59 +829,7 @@ struct AnimatingCellHeight: AnimatableModifier { } var filtersHeader: some View { - GeometryReader { reader in - ScrollView(.horizontal, showsIndicators: false) { - HStack { - if viewModel.searchTerm.count > 0 { - TextChipButton.makeSearchFilterButton(title: viewModel.searchTerm) { - viewModel.searchTerm = "" - }.frame(maxWidth: reader.size.width * 0.66) - } else { - Menu( - content: { - ForEach(viewModel.filters, id: \.self) { filter in - Button(filter.name, action: { viewModel.appliedFilter = filter }) - } - }, - label: { - TextChipButton.makeMenuButton( - title: viewModel.appliedFilter?.name ?? "-", - color: .systemGray6 - ) - } - ) - } - Menu( - content: { - ForEach(LinkedItemSort.allCases, id: \.self) { sort in - Button(sort.displayName, action: { viewModel.appliedSort = sort.rawValue }) - } - }, - label: { - TextChipButton.makeMenuButton( - title: LinkedItemSort(rawValue: viewModel.appliedSort)?.displayName ?? "Sort", - color: .systemGray6 - ) - } - ) - TextChipButton.makeAddLabelButton(color: .systemGray6, onTap: { viewModel.showLabelsSheet = true }) - ForEach(viewModel.selectedLabels, id: \.self) { label in - TextChipButton.makeRemovableLabelButton(feedItemLabel: label, negated: false) { - viewModel.selectedLabels.removeAll { $0.id == label.id } - } - } - ForEach(viewModel.negatedLabels, id: \.self) { label in - TextChipButton.makeRemovableLabelButton(feedItemLabel: label, negated: true) { - viewModel.negatedLabels.removeAll { $0.id == label.id } - } - } - Spacer() - } - .padding(0) - } - .listRowSeparator(.hidden) - } - .dynamicTypeSize(.small ... .accessibility1) + FiltersHeader(viewModel: viewModel) } var body: some View { diff --git a/apple/OmnivoreKit/Sources/App/Views/Profile/FiltersView.swift b/apple/OmnivoreKit/Sources/App/Views/Profile/FiltersView.swift index 89086bef6..bd02c3ceb 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Profile/FiltersView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Profile/FiltersView.swift @@ -94,8 +94,12 @@ struct FiltersView: View { } Section(header: Text("Saved Searches")) { - ForEach(viewModel.libraryFilters) { filter in - Text(filter.name) + if viewModel.libraryFilters.count > 0 { + ForEach(viewModel.libraryFilters) { filter in + Text(filter.name) + } + } else { + Text("No saved searches found") } } diff --git a/apple/OmnivoreKit/Sources/App/Views/Profile/NewsletterEmailsView.swift b/apple/OmnivoreKit/Sources/App/Views/Profile/NewsletterEmailsView.swift index 2ab0b17c9..6c960a36a 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Profile/NewsletterEmailsView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Profile/NewsletterEmailsView.swift @@ -76,12 +76,13 @@ struct NewsletterEmailsView: View { OperationToast(operationMessage: $viewModel.operationMessage, showOperationToast: $viewModel.showOperationToast, operationStatus: $viewModel.operationStatus) } label: { EmptyView() - } + }.buttonStyle(.plain) + WindowLink(level: .alert, transition: .move(edge: .bottom), isPresented: $viewModel.showAddressCopied) { MessageToast() } label: { EmptyView() - } + }.buttonStyle(.plain) #if os(iOS) Form { diff --git a/apple/OmnivoreKit/Sources/App/Views/Profile/SubscriptionsView.swift b/apple/OmnivoreKit/Sources/App/Views/Profile/SubscriptionsView.swift index 371b16b77..eccbc6806 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Profile/SubscriptionsView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Profile/SubscriptionsView.swift @@ -161,7 +161,8 @@ struct SubscriptionsView: View { OperationToast(operationMessage: $viewModel.operationMessage, showOperationToast: $viewModel.showOperationToast, operationStatus: $viewModel.operationStatus) } label: { EmptyView() - } + }.buttonStyle(.plain) + if viewModel.feeds.isEmpty, viewModel.newsletters.isEmpty, viewModel.isLoading { ProgressView() } else if viewModel.hasNetworkError { diff --git a/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift index c4ae5923f..ae752df32 100644 --- a/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift +++ b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift @@ -129,29 +129,31 @@ struct WebReaderContainerView: View { return AnyView(ProgressView() .padding(.horizontal)) } else { - return AnyView(Button( - action: { - switch audioController.state { - case .playing: - if audioController.itemAudioProperties?.itemID == self.item.unwrappedID { - audioController.pause() - return + return AnyView( + Button( + action: { + switch audioController.state { + case .playing: + if audioController.itemAudioProperties?.itemID == self.item.unwrappedID { + audioController.pause() + return + } + fallthrough + case .paused: + if audioController.itemAudioProperties?.itemID == self.item.unwrappedID { + audioController.unpause() + return + } + fallthrough + default: + audioController.play(itemAudioProperties: item.audioProperties) } - fallthrough - case .paused: - if audioController.itemAudioProperties?.itemID == self.item.unwrappedID { - audioController.unpause() - return - } - fallthrough - default: - audioController.play(itemAudioProperties: item.audioProperties) + }, + label: { + textToSpeechButtonImage } - }, - label: { - textToSpeechButtonImage - } - )) + ).buttonStyle(.plain) + ) } } @@ -258,6 +260,8 @@ struct WebReaderContainerView: View { .padding(.vertical) } ) + .buttonStyle(.plain) + Spacer() #endif @@ -267,6 +271,7 @@ struct WebReaderContainerView: View { Image.label } ) + .buttonStyle(.plain) .padding(.trailing, 4) Button( @@ -275,6 +280,7 @@ struct WebReaderContainerView: View { Image.notebook } ) + .buttonStyle(.plain) .padding(.trailing, 4) #if os(iOS) @@ -292,6 +298,7 @@ struct WebReaderContainerView: View { Image.readerSettings } ) + .buttonStyle(.plain) .padding(.horizontal, 5) .popover(isPresented: $showPreferencesPopover) { webPreferencesPopoverView @@ -318,6 +325,7 @@ struct WebReaderContainerView: View { #endif } ) + .buttonStyle(.plain) #if os(macOS) .frame(maxWidth: 100) .padding(.trailing, 16) @@ -372,7 +380,8 @@ struct WebReaderContainerView: View { OperationToast(operationMessage: $viewModel.operationMessage, showOperationToast: $viewModel.showOperationToast, operationStatus: $viewModel.operationStatus) } label: { EmptyView() - } + }.buttonStyle(.plain) + if let articleContent = viewModel.articleContent { WebReader( item: item, diff --git a/apple/OmnivoreKit/Sources/App/Views/WelcomeView.swift b/apple/OmnivoreKit/Sources/App/Views/WelcomeView.swift index 63e410b36..77b32451a 100644 --- a/apple/OmnivoreKit/Sources/App/Views/WelcomeView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/WelcomeView.swift @@ -149,6 +149,7 @@ struct WelcomeView: View { .sheet(isPresented: $showAboutPage) { if let url = URL(string: "https://omnivore.app/about") { SafariView(url: url) + .ignoresSafeArea(.all, edges: .bottom) } } .onTapGesture {