Skip to content

Commit

Permalink
Merge pull request #25 from WalletConnect/feat/account-button
Browse files Browse the repository at this point in the history
Add account button
  • Loading branch information
radeknovis authored Nov 6, 2023
2 parents 4a8972a + e68c1b1 commit 83ffcd9
Show file tree
Hide file tree
Showing 27 changed files with 697 additions and 184 deletions.
8 changes: 6 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,13 @@ let package = Package(
],
dependencies: [
.package(
url: "https://github.com/WalletConnect/WalletConnectSwiftV2", branch: "remove-wcm"
url: "https://github.com/WalletConnect/WalletConnectSwiftV2",
from: "1.9.2"
),
.package(
url: "https://github.com/WalletConnect/QRCode",
from: "14.3.1"
),
.package(url: "https://github.com/WalletConnect/QRCode", from: "14.3.1"),
.package(
url: "https://github.com/pointfreeco/swift-snapshot-testing",
from: "1.10.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/WalletConnect/WalletConnectSwiftV2",
"state" : {
"branch" : "remove-wcm",
"revision" : "04bcc547a61768598286cfa4cb0a06c0475c4d35"
"revision" : "c3c84f221ef945edb766125bc07f03c7694fc516",
"version" : "1.9.2"
}
}
],
Expand Down
33 changes: 5 additions & 28 deletions Sample/Example/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,47 +4,27 @@ import Web3ModalUI

struct ContentView: View {

@State var showUIComponets: Bool = false

@State var id: UUID = UUID()

@State var showUIComponents: Bool = false
@State var socketConnected: Bool = false

var addressFormatted: String? {
guard let address = Store.shared.session?.accounts.first?.address else {
return nil
}

return String(address.prefix(4)) + "..." + String(address.suffix(4))
}

var body: some View {
NavigationView {
VStack {
Spacer()

Button(addressFormatted ?? "Connect Wallet") {
Web3Modal.present()
}
.buttonStyle(W3MButtonStyle())

let chainName = Store.shared.selectedChain?.chainName
Web3Button()

Button(chainName ?? "Select Network") {
Web3Modal.selectChain()
}
.buttonStyle(W3MButtonStyle(variant: .accent, leftIcon: Image(systemName: "network")))
NetworkButton()

Spacer()

NavigationLink(destination: ComponentLibraryView(), isActive: $showUIComponets) {
NavigationLink(destination: ComponentLibraryView(), isActive: $showUIComponents) {
Button("UI components") {
showUIComponets = true
showUIComponents = true
}
.buttonStyle(W3MButtonStyle())
}
}
.id(id)
.overlay(
HStack {
Circle()
Expand All @@ -62,9 +42,6 @@ struct ContentView: View {
.onReceive(Web3Modal.instance.socketConnectionStatusPublisher.receive(on: RunLoop.main), perform: { status in
socketConnected = status == .connected
})
.onReceive(Store.shared.objectWillChange, perform: { _ in
id = UUID()
})
}
}
}
230 changes: 230 additions & 0 deletions Sources/Web3Modal/Components/AccountButton.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
import SwiftUI
import WalletConnectSign
import Web3ModalUI

struct AccountButtonStyle: ButtonStyle {
@ObservedObject var store: Store

public init() {
self.store = .shared
}

init(
store: Store = .shared,
isPressedOverride: Bool? = nil
) {
self.store = store
self.isPressedOverride = isPressedOverride
}

@Environment(\.isEnabled) var isEnabled

var isPressedOverride: Bool?

var addressFormatted: String? {
guard let address = store.session?.accounts.first?.address else {
return nil
}

return String(address.prefix(4)) + "..." + String(address.suffix(4))
}

var selectedChain: Chain {
return store.selectedChain ?? ChainsPresets.ethChains.first!
}

func makeBody(configuration: Configuration) -> some View {
var backgroundColor: Color = .GrayGlass002
let pressedColor: Color = .GrayGlass010
backgroundColor = (isPressedOverride ?? configuration.isPressed) ? pressedColor : backgroundColor
backgroundColor = isEnabled ? backgroundColor : .Overgray010

let verticalPadding = Spacing.xxxs
let leadingPadding = Spacing.xxs
let trailingPadding = Spacing.xxxs

return Group {
if store.balance != nil {
mixedVariant()
} else {
accountVariant()
}
}
.padding(.vertical, verticalPadding)
.padding(.leading, leadingPadding)
.padding(.trailing, trailingPadding)
.background(backgroundColor)
.cornerRadius(Radius.m)
.overlay(
RoundedRectangle(cornerRadius: Radius.m)
.stroke(Color.Overgray010, lineWidth: 1)
)
}

func accountVariant() -> some View {
var textColor: Color = .Foreground100
textColor = isEnabled ? textColor : .Overgray015

return HStack(spacing: Spacing.xxs) {
avatar()

Text(addressFormatted ?? "")
.font(.paragraph500)
.foregroundColor(textColor)
}
.padding(Spacing.xs)
.cornerRadius(Radius.m)
}

func mixedVariant() -> some View {
var textColor: Color = .Foreground100
textColor = isEnabled ? textColor : .Overgray015

var textColorInner: Color = .Foreground200
textColorInner = isEnabled ? textColorInner : .Overgray010

return HStack(spacing: Spacing.xs) {
HStack(spacing: Spacing.xxs) {
networkImage()
.clipShape(Circle())
.saturation(isEnabled ? 1 : 0)
.opacity(isEnabled ? 1 : 0.5)
.frame(width: 24, height: 24)

let balance = store.balance?.roundedDecimal(to: 4, mode: .down) ?? 0

Text(balance == 0 ? "0 \(selectedChain.token.symbol)" : "\(balance, specifier: "%.3f") \(selectedChain.token.symbol)")
.font(.paragraph600)
.foregroundColor(textColor)
.lineLimit(1)
}

HStack(spacing: Spacing.xxs) {
avatar()

Text(addressFormatted ?? "")
.font(.paragraph500)
.foregroundColor(textColorInner)
}
.padding(Spacing.xs)
.background(.GrayGlass005)
.cornerRadius(Radius.m)
.overlay(
RoundedRectangle(cornerRadius: Radius.m)
.stroke(Color.Overgray010, lineWidth: 1)
)
}
}

func networkImage() -> some View {
let storedImage = store.chainImages[selectedChain.imageId]
let chainImage = Image(
uiImage: storedImage ?? UIImage()
)

return chainImage
.resizable()
}

@ViewBuilder
func avatar() -> some View {
Group {
if let avatarUrlString = store.identity?.avatar, let url = URL(string: avatarUrlString) {
AsyncImage(url: url)
} else if let address = store.session?.accounts.first?.address {
W3MAvatarGradient(address: address)
}
}
.saturation(isEnabled ? 1 : 0)
.opacity(isEnabled ? 1 : 0.5)
.frame(width: 20, height: 20)
.clipShape(Circle())
.overlay(Circle().stroke(.GrayGlass010, lineWidth: 3))
}
}

public struct AccountButton: View {
var store: Store

public init() {
self.store = .shared
}

init(store: Store = .shared) {
self.store = store
}

public var body: some View {
Button(action: {
Web3Modal.present()
}, label: {})
.buttonStyle(AccountButtonStyle(store: store))
.onAppear {
fetchIdentity()
fetchBalance()
}
}

func fetchIdentity() {
Task { @MainActor in
do {
try await BlockchainAPIInteractor(store: store).getIdentity()
} catch {
store.toast = .init(style: .error, message: "Failed to fetch identity")
}
}
}

func fetchBalance() {
Task { @MainActor in
do {
try await BlockchainAPIInteractor(store: store).getBalance()
} catch {
store.toast = .init(style: .error, message: "Failed to fetch balance")
}
}
}
}

struct AccountButton_Preview: PreviewProvider {
static let store = { (balance: Double?) -> Store in
let store = Store()
store.balance = balance
store.session = .stub
return store
}

static var previews: some View {
VStack {
AccountButton(store: AccountButton_Preview.store(1.23))

AccountButton(store: AccountButton_Preview.store(nil))

AccountButton(store: AccountButton_Preview.store(1.23))
.disabled(true)

AccountButton(store: AccountButton_Preview.store(nil))
.disabled(true)

Button(action: {}, label: {
// Text("Foo")
})
.buttonStyle(
AccountButtonStyle(
store: AccountButton_Preview.store(1.23),
isPressedOverride: true
)
)

Button(action: {}, label: {
// Text("Foo")
})
.buttonStyle(
AccountButtonStyle(
store: AccountButton_Preview.store(nil),
isPressedOverride: true
)
)
}
}
}
41 changes: 41 additions & 0 deletions Sources/Web3Modal/Components/ConnectButton.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import SwiftUI
import Web3ModalUI

public struct ConnectButton: View {

@ObservedObject var store: Store

public init() {
self.store = .shared
}

init(store: Store = .shared) {
self.store = store
}

public var body: some View {
Button {
Web3Modal.present()
} label: {
if store.connecting {
CircleProgressView(color: .white, lineWidth: 2, isAnimating: .constant(true))
.frame(width: 20, height: 20)
} else {
Text("Connect wallet")
}
}
.buttonStyle(W3MChipButtonStyle())
}
}

struct ConnectButton_Preview: PreviewProvider {

static var previews: some View {
VStack {
ConnectButton()

ConnectButton()
.disabled(true)
}
}
}
Loading

0 comments on commit 83ffcd9

Please sign in to comment.