Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Integrate folder picker on iPad - WPB-11895 #2156

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,8 @@

samwyndham marked this conversation as resolved.
Show resolved Hide resolved
public protocol MainSidebarSelectableMenuItemRepresentable: Sendable {
init(_ mainSidebarMenuItem: MainSidebarMenuItem)
init?<SidebarSelectableMenuItem: MainSidebarSelectableMenuItemRepresentable>(mappingFrom selectableMenuItem: SidebarSelectableMenuItem?)
func mapToMainSidebarMenuItem() -> MainSidebarMenuItem
}

extension MainSidebarMenuItem: MainSidebarSelectableMenuItemRepresentable {
public init(_ mainSidebarMenuItem: MainSidebarMenuItem) { self = mainSidebarMenuItem }
public func mapToMainSidebarMenuItem() -> MainSidebarMenuItem { self }
}

public extension MainSidebarSelectableMenuItemRepresentable {

init?(mappingFrom selectableMenuItem: (some MainSidebarSelectableMenuItemRepresentable)?) {
guard let selectableMenuItem else { return nil }
self.init(selectableMenuItem.mapToMainSidebarMenuItem())
}
}
5 changes: 4 additions & 1 deletion WireUI/Sources/WireSidebarUI/Models/SidebarModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,19 @@ final class SidebarModel: ObservableObject {

let accountImageAction: () -> Void
let menuItemAction: (_ selectedMenuItem: SidebarSelectableMenuItem) -> Void
let foldersAction: (CGRect) -> Void
let connectAction: () -> Void
let supportAction: () -> Void

init(
accountImageAction: @escaping () -> Void,
menuItemAction: @escaping (_: SidebarSelectableMenuItem) -> Void,
menuItemAction: @escaping (SidebarSelectableMenuItem) -> Void,
foldersAction: @escaping (_ buttonFrame: CGRect) -> Void,
connectAction: @escaping () -> Void,
supportAction: @escaping () -> Void
) {
self.accountImageAction = accountImageAction
self.foldersAction = foldersAction
self.menuItemAction = menuItemAction
self.connectAction = connectAction
self.supportAction = supportAction
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"sidebar.conversation_filter.favorites.title" = "Favorites";
"sidebar.conversation_filter.groups.title" = "Groups";
"sidebar.conversation_filter.oneOnOneConversations.title" = "1:1 Conversations";
"sidebar.conversation_filter.folders.title" = "Folders";
"sidebar.conversation_filter.archived.title" = "Archive";

"sidebar.contacts.title" = "Contacts";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,21 @@ struct SidebarMenuItemPreview: View {
iconSize: iconSize,
isHighlighted: false,
title: { Text("Regular") },
action: { print("show all conversations") }
action: { _ in print("show all conversations") }
)
SidebarMenuItemView(
icon: "gamecontroller",
iconSize: iconSize,
isHighlighted: true,
title: { Text("Initially highlighted") },
action: { print("show all conversations") }
action: { _ in print("show all conversations") }
)
SidebarMenuItemView(
icon: "person.3",
iconSize: iconSize,
isLink: true,
title: { Text("Initially highlighted") },
action: { print("show all conversations") }
action: { _ in print("show all conversations") }
)
}
.overlay {
Expand All @@ -68,14 +68,14 @@ struct SidebarMenuItemPreview: View {
iconSize: iconSize,
isHighlighted: false,
title: { Text("Small Icon") },
action: { print("show all conversations") }
action: { _ in print("show all conversations") }
)
SidebarMenuItemView(
icon: "brain",
iconSize: iconSize,
isHighlighted: false,
title: { Text("Little larger Icon") },
action: { print("show all conversations") }
action: { _ in print("show all conversations") }
)
}
.overlay {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ struct SidebarPreview: View {
accountInfo: accountInfo,
selectedMenuItem: $selectedMenuItem,
accountImageAction: {},
foldersAction: { _ in },
connectAction: {},
supportAction: {},
accountImageView: { _, _ in MockAccountImageView() },
Expand Down
12 changes: 10 additions & 2 deletions WireUI/Sources/WireSidebarUI/Views/SidebarMenuItemView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,15 @@ struct SidebarMenuItemView<TitleView: View>: View {
private(set) var isHighlighted = false

private(set) var title: () -> TitleView
private(set) var action: () -> Void
private(set) var action: (CGRect) -> Void
@State private var frame: CGRect = .zero

// MARK: -

var body: some View {
Button(action: action) {
Button {
action(frame)
} label: {
HStack {
Label {
title()
Expand Down Expand Up @@ -87,6 +90,11 @@ struct SidebarMenuItemView<TitleView: View>: View {
.cornerRadius(backgroundCornerRadius)
}
.dynamicTypeSize(...DynamicTypeSize.accessibility1)
.onGeometryChange(for: CGRect.self) { proxy in
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know what exactly happens here, but could it be that this causes performance overhead when scrolling?
I don't think every menu time view should keep track of its frame on the screen.
Maybe we can brainstorm for a bitter idea?

proxy.frame(in: .global)
} action: { newValue in
frame = newValue
}
}
}

Expand Down
27 changes: 22 additions & 5 deletions WireUI/Sources/WireSidebarUI/Views/SidebarView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public struct SidebarView<AccountImageView: View, LegalHoldIndicatorView: View>:
@Binding public var selectedMenuItem: SidebarSelectableMenuItem

private(set) var accountImageAction: () -> Void
private(set) var foldersAction: (CGRect) -> Void
private(set) var connectAction: () -> Void
private(set) var supportAction: () -> Void

Expand All @@ -43,6 +44,7 @@ public struct SidebarView<AccountImageView: View, LegalHoldIndicatorView: View>:
accountInfo: SidebarAccountInfo,
selectedMenuItem: Binding<SidebarSelectableMenuItem>,
accountImageAction: @escaping () -> Void,
foldersAction: @escaping (_ buttonFrame: CGRect) -> Void,
connectAction: @escaping () -> Void,
supportAction: @escaping () -> Void,
accountImageView: @escaping (_ accountImage: AccountImageSource, _ availability: Availability?) -> AccountImageView,
Expand All @@ -51,6 +53,7 @@ public struct SidebarView<AccountImageView: View, LegalHoldIndicatorView: View>:
self.accountInfo = accountInfo
_selectedMenuItem = selectedMenuItem
self.accountImageAction = accountImageAction
self.foldersAction = foldersAction
self.connectAction = connectAction
self.supportAction = supportAction
self.accountImageView = accountImageView
Expand Down Expand Up @@ -117,7 +120,14 @@ public struct SidebarView<AccountImageView: View, LegalHoldIndicatorView: View>:
private var scrollableMenuItems: some View {
VStack(alignment: .leading, spacing: 0) {
menuItemHeader("sidebar.conversation_filter.title", addTopPadding: false)
let conversationFilters = [SidebarSelectableMenuItem.all, .favorites, .groups, .oneOnOne, .archive]
let conversationFilters: [SidebarSelectableMenuItem] = [
.all,
.favorites,
.groups,
.oneOnOne,
.folders,
.archive
]
ForEach(conversationFilters, id: \.self) { conversationFilter in
selectableMenuItem(conversationFilter)
}
Expand Down Expand Up @@ -152,21 +162,21 @@ public struct SidebarView<AccountImageView: View, LegalHoldIndicatorView: View>:
text = Text("sidebar.contacts.connect.title", bundle: .module)
icon = "person.badge.plus"
isLink = false
action = connectAction
action = { connectAction() }

case .support:
text = Text("sidebar.support.title", bundle: .module)
icon = "questionmark.circle"
isLink = true
action = supportAction
action = { supportAction() }
}

return SidebarMenuItemView(
icon: icon,
iconSize: iconSize,
isLink: isLink,
title: { text.wireTextStyle(.body1) },
action: action
action: { _ in action() }
)
}

Expand Down Expand Up @@ -203,13 +213,20 @@ public struct SidebarView<AccountImageView: View, LegalHoldIndicatorView: View>:
icon = "gearshape"
}

let action: (CGRect) -> Void = switch menuItem {
case .folders:
foldersAction
default:
{ _ in selectedMenuItem = menuItem }
}

return SidebarMenuItemView(
icon: icon,
iconSize: iconSize,
isLink: false,
isHighlighted: selectedMenuItem == menuItem,
title: { text.wireTextStyle(.body1) },
action: { selectedMenuItem = menuItem }
action: action
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ public final class SidebarViewController: UIViewController {
}, menuItemAction: { [weak self] menuItem in
guard let self, !skipCallingDelegate else { return }
delegate?.sidebarViewController(self, didSelect: menuItem)
}, foldersAction: { [weak self] rect in
self?.delegate?.sidebarViewController(self!, didTapFoldersAt: rect)
}, connectAction: { [weak self] in
self?.delegate?.sidebarViewControllerDidSelectConnect(self!)
}, supportAction: { [weak self] in
Expand Down Expand Up @@ -173,6 +175,7 @@ private struct SidebarAdapter<AccountImageView: View, LegalHoldIndicatorView: Vi
accountInfo: model.accountInfo,
selectedMenuItem: $model.selectedMenuItem,
accountImageAction: model.accountImageAction,
foldersAction: model.foldersAction,
connectAction: model.connectAction,
supportAction: model.supportAction,
accountImageView: accountImageView,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@
// along with this program. If not, see http://www.gnu.org/licenses/.
//

import Foundation

@MainActor
public protocol SidebarViewControllerDelegate: AnyObject {
func sidebarViewControllerDidSelectAccountImage(_ viewController: SidebarViewController)
func sidebarViewController(_ viewController: SidebarViewController, didTapFoldersAt rect: CGRect)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

didtapFoldersAt rect sounds really fragile to me.
Is there no other way to know which folder was selected?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@caldrian Maybe this is badly named. This is not about identifying which folder was tapped. It is the frame of the Folders button in the sidebar.

func sidebarViewController(_ viewController: SidebarViewController, didSelect menuItem: SidebarSelectableMenuItem)
func sidebarViewControllerDidSelectConnect(_ viewController: SidebarViewController)
func sidebarViewControllerDidSelectSupport(_ viewController: SidebarViewController)
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,18 @@ final class SidebarViewControllerDelegate: WireSidebarUI.SidebarViewControllerDe
let mainCoordinator: AnyMainCoordinator
let connectUIBuilder: ConnectViewControllerBuilderProtocol
let selfProfileUIBuilder: SelfProfileViewControllerBuilderProtocol
let folderPickerViewControllerBuilder: FolderPickerViewControllerBuilder

init(
mainCoordinator: AnyMainCoordinator,
connectUIBuilder: ConnectViewControllerBuilderProtocol,
selfProfileUIBuilder: SelfProfileViewControllerBuilderProtocol
selfProfileUIBuilder: SelfProfileViewControllerBuilderProtocol,
folderPickerViewControllerBuilder: FolderPickerViewControllerBuilder
) {
self.mainCoordinator = mainCoordinator
self.connectUIBuilder = connectUIBuilder
self.selfProfileUIBuilder = selfProfileUIBuilder
self.folderPickerViewControllerBuilder = folderPickerViewControllerBuilder
}

@MainActor
Expand All @@ -45,6 +48,23 @@ final class SidebarViewControllerDelegate: WireSidebarUI.SidebarViewControllerDe
}
}

@MainActor
func sidebarViewController(_ viewController: WireSidebarUI.SidebarViewController, didTapFoldersAt rect: CGRect) {
Task {
let folderPicker = folderPickerViewControllerBuilder.build(mainCoordinator: mainCoordinator)
folderPicker.modalPresentationStyle = .popover

if let popover = folderPicker.popoverPresentationController,
let view = viewController.view,
let window = view.window {
popover.sourceView = view
popover.sourceRect = view.convert(rect, from: window)
}

viewController.present(folderPicker, animated: true)
}
}

@MainActor
public func sidebarViewController(_ viewController: SidebarViewController, didSelect menuItem: SidebarSelectableMenuItem) {
Task {
Expand All @@ -58,7 +78,7 @@ final class SidebarViewControllerDelegate: WireSidebarUI.SidebarViewControllerDe
case .oneOnOne:
await mainCoordinator.showConversationList(conversationFilter: .oneOnOne)
case .folders:
break // Tapping on folder is handled elsewhere
break // handled by `sidebarViewController(_:didTapFoldersAt:)`
case .archive:
await mainCoordinator.showArchive()
case .settings:
Expand Down
Loading
Loading