-
Notifications
You must be signed in to change notification settings - Fork 172
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Wallet] Edit session namespaces (#231)
* Edit session namespaces UI * Update namespace error handling * Pending requests * Show SessionRequest Screen * Reload SessionDetails on request respond * Unused import removed
- Loading branch information
Showing
13 changed files
with
384 additions
and
277 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
138 changes: 138 additions & 0 deletions
138
Example/ExampleApp/SessionDetails/SessionDetailView.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
import SwiftUI | ||
import WalletConnectAuth | ||
|
||
struct SessionDetailView: View { | ||
|
||
@ObservedObject var viewModel: SessionDetailViewModel | ||
|
||
var didPressSessionRequest: ((Request) -> Void)? | ||
|
||
var body: some View { | ||
List { | ||
Section { headerView() } | ||
|
||
ForEach(viewModel.chains, id: \.self) { chain in | ||
Section(header: header(chain: chain)) { | ||
if let namespace = viewModel.namespace(for: chain) { | ||
|
||
if namespace.accounts.isNotEmpty { | ||
accountSection(chain: chain, namespace: namespace) | ||
} | ||
|
||
if namespace.methods.isNotEmpty { | ||
methodsSection(chain: chain, namespace: namespace) | ||
} | ||
|
||
if namespace.events.isNotEmpty { | ||
methodsSection(chain: chain, namespace: namespace) | ||
} | ||
} | ||
} | ||
} | ||
|
||
if viewModel.requests.isNotEmpty { | ||
requestsSection() | ||
} | ||
} | ||
.listStyle(.insetGrouped) | ||
} | ||
} | ||
|
||
private extension SessionDetailView { | ||
|
||
func accountSection(chain: String, namespace: SessionNamespaceViewModel) -> some View { | ||
Section(header: headerRow("Accounts")) { | ||
ForEach(namespace.accounts, id: \.self) { account in | ||
plainRow(account.absoluteString) | ||
} | ||
.onDelete { indices in Task { | ||
await viewModel.remove(field: .accounts, at: indices, for: chain) | ||
}} | ||
} | ||
} | ||
|
||
func methodsSection(chain: String, namespace: SessionNamespaceViewModel) -> some View { | ||
Section(header: headerRow("Methods")) { | ||
ForEach(namespace.methods, id: \.self) { method in | ||
plainRow(method) | ||
} | ||
.onDelete { indices in Task { | ||
await viewModel.remove(field: .methods, at: indices, for: chain) | ||
}} | ||
} | ||
} | ||
|
||
func eventsSection(chain: String, namespace: SessionNamespaceViewModel) -> some View { | ||
Section(header: headerRow("Events")) { | ||
ForEach(namespace.events, id: \.self) { event in | ||
plainRow(event) | ||
} | ||
.onDelete { indices in Task { | ||
await viewModel.remove(field: .events, at: indices, for: chain) | ||
}} | ||
} | ||
} | ||
|
||
func requestsSection() -> some View { | ||
Section(header: Text("Pending requests")) { | ||
ForEach(viewModel.requests, id: \.method) { request in | ||
Button(action: { didPressSessionRequest?(request) }) { | ||
plainRow(request.method) | ||
} | ||
} | ||
} | ||
} | ||
|
||
func headerView() -> some View { | ||
VStack(spacing: 12.0) { | ||
AsyncImage(url: viewModel.peerIconURL) { image in | ||
image | ||
.resizable() | ||
.aspectRatio(contentMode: .fill) | ||
.clipShape(Circle()) | ||
} placeholder: { | ||
ProgressView().progressViewStyle(.circular) | ||
} | ||
.frame(width: 64, height: 64) | ||
.frame(maxWidth: .infinity) | ||
|
||
Text(viewModel.peerName) | ||
.font(.headline) | ||
|
||
VStack { | ||
Text(viewModel.peerDescription) | ||
Text(viewModel.peerURL) | ||
} | ||
.font(.footnote) | ||
.foregroundColor(.secondaryLabel) | ||
|
||
Button("Ping") { | ||
viewModel.ping() | ||
} | ||
.buttonStyle(BorderedProminentButtonStyle()) | ||
} | ||
.background(Color(.systemGroupedBackground)) | ||
.listRowInsets(EdgeInsets()) | ||
} | ||
|
||
func headerRow(_ text: String) -> some View { | ||
return Text(text) | ||
.font(.footnote) | ||
.foregroundColor(.secondaryLabel) | ||
} | ||
|
||
func plainRow(_ text: String) -> some View { | ||
return Text(text) | ||
.font(.body) | ||
} | ||
|
||
func header(chain: String) -> some View { | ||
HStack { | ||
Text(chain) | ||
Spacer() | ||
Button("Delete") { Task { | ||
await viewModel.remove(field: .chain, for: chain) | ||
}} | ||
} | ||
} | ||
} |
47 changes: 47 additions & 0 deletions
47
Example/ExampleApp/SessionDetails/SessionDetailViewController.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import UIKit | ||
import SwiftUI | ||
import WalletConnectAuth | ||
import WalletConnectUtils | ||
|
||
final class SessionDetailViewController: UIHostingController<SessionDetailView> { | ||
|
||
private let viewModel: SessionDetailViewModel | ||
|
||
init(session: Session, client: Auth) { | ||
self.viewModel = SessionDetailViewModel(session: session, client: client) | ||
super.init(rootView: SessionDetailView(viewModel: viewModel)) | ||
|
||
rootView.didPressSessionRequest = { [weak self] request in | ||
self?.showSessionRequest(request) | ||
} | ||
} | ||
|
||
func reload() { | ||
viewModel.objectWillChange.send() | ||
} | ||
|
||
private func showSessionRequest(_ request: Request) { | ||
let viewController = RequestViewController(request) | ||
viewController.onSign = { [unowned self] in | ||
let result = Signer.signEth(request: request) | ||
let response = JSONRPCResponse<AnyCodable>(id: request.id, result: result) | ||
Auth.instance.respond(topic: request.topic, response: .response(response)) | ||
reload() | ||
} | ||
viewController.onReject = { [unowned self] in | ||
Auth.instance.respond( | ||
topic: request.topic, | ||
response: .error(JSONRPCErrorResponse( | ||
id: request.id, | ||
error: JSONRPCErrorResponse.Error(code: 0, message: "")) | ||
) | ||
) | ||
reload() | ||
} | ||
present(viewController, animated: true) | ||
} | ||
|
||
@MainActor required dynamic init?(coder aDecoder: NSCoder) { | ||
fatalError("init(coder:) has not been implemented") | ||
} | ||
} |
Oops, something went wrong.