Skip to content

Commit

Permalink
Merge pull request #1123 from WalletConnect/feature/notify-sample-part-2
Browse files Browse the repository at this point in the history
[Notify] Sample Subscription and Preferences screens
  • Loading branch information
flypaper0 authored Sep 20, 2023
2 parents 7ed4adb + c1ef1f0 commit e41c2d0
Show file tree
Hide file tree
Showing 26 changed files with 631 additions and 266 deletions.
80 changes: 56 additions & 24 deletions Example/ExampleApp.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
"repositoryURL": "https://github.com/krzyzanowskim/CryptoSwift.git",
"state": {
"branch": null,
"revision": "db51c407d3be4a051484a141bf0bff36c43d3b1e",
"version": "1.8.0"
"revision": "32f641cf24fc7abc1c591a2025e9f2f572648b0f",
"version": "1.7.2"
}
},
{
Expand Down Expand Up @@ -69,8 +69,8 @@
"repositoryURL": "https://github.com/getsentry/sentry-cocoa.git",
"state": {
"branch": null,
"revision": "14aa6e47b03b820fd2b338728637570b9e969994",
"version": "8.12.0"
"revision": "04bee4ad86d74d4cb4d7101ff826d6e355301ba9",
"version": "8.9.4"
}
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,6 @@ import UIKit
struct AppearanceConfigurator: Configurator {

func configure() {
let appearance = UINavigationBarAppearance()
appearance.backgroundColor = .w_background
appearance.shadowColor = .clear
appearance.titleTextAttributes = [
.foregroundColor: UIColor.w_foreground
]

UINavigationBar.appearance().standardAppearance = appearance
UINavigationBar.appearance().scrollEdgeAppearance = appearance
UINavigationBar.appearance().compactAppearance = appearance
}
}
27 changes: 1 addition & 26 deletions Example/WalletApp/BusinessLayer/ListingsSertice/Listings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,35 +11,10 @@ struct Listing: Codable {
@FailableDecodable
private(set) var lg: URL?
}
struct App: Codable {
@FailableDecodable
private(set) var ios: URL?

@FailableDecodable
private(set) var android: URL?

@FailableDecodable
private(set) var browser: URL?
}
struct Mobile: Codable {
let native: String?
let universal: String?
}
struct Metadata: Codable {
struct Colors: Codable {
let primary: String?
let secondary: String?
}
let shortName: String
let colors: Colors
}
let id: String
let name: String
let description: String
let homepage: String
let image_url: ImageURL
let app: App
let mobile: Mobile
let metadata: Metadata
let chains: [String]
let dapp_url: String
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import HTTPClient
enum ListingsAPI: HTTPService {

var path: String {
return "/v3/dapps"
return "/w3i/v1/projects"
}

var method: HTTPMethod {
Expand All @@ -16,7 +16,7 @@ enum ListingsAPI: HTTPService {
}

var queryParameters: [String : String]? {
return ["projectId": InputConfig.projectId, "is_notify_enabled": "true"]
return ["projectId": InputConfig.projectId, "entries": "100", "is_verified": "false"]
}

var additionalHeaderFields: [String : String]? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import HTTPClient
final class ListingsNetworkService {

struct ListingsResponse: Codable {
let listings: [String: Listing]
let projects: [String: Listing]
}

func getListings() async throws -> [Listing] {
let httpClient = HTTPNetworkClient(host: "explorer-api.walletconnect.com")
let response = try await httpClient.request(ListingsResponse.self, at: ListingsAPI.notifyDApps)
return response.listings.values.compactMap { $0 }
return response.projects.values.compactMap { $0 }
}
}
52 changes: 52 additions & 0 deletions Example/WalletApp/Common/Helpers/CacheAsyncImage.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import SwiftUI

struct CacheAsyncImage<Content>: View where Content: View{

private let url: URL?
private let scale: CGFloat
private let transaction: Transaction
private let content: (AsyncImagePhase) -> Content

init(
url: URL?,
scale: CGFloat = 1.0,
transaction: Transaction = Transaction(),
@ViewBuilder content: @escaping (AsyncImagePhase) -> Content
){
self.url = url
self.scale = scale
self.transaction = transaction
self.content = content
}

var body: some View{
if let url, let cached = ImageCache[url] {
content(.success(cached))
} else {
AsyncImage(
url: url,
scale: scale,
transaction: transaction
){ phase in
cacheAndRender(phase: phase)
}
}
}
func cacheAndRender(phase: AsyncImagePhase) -> some View{
if case .success (let image) = phase, let url {
ImageCache[url] = image
}
return content(phase)
}
}
fileprivate class ImageCache{
static private var cache: [URL: Image] = [:]
static subscript(url: URL) -> Image?{
get{
ImageCache.cache[url]
}
set{
ImageCache.cache[url] = newValue
}
}
}
9 changes: 9 additions & 0 deletions Example/WalletApp/Common/VIPER/SceneViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import SwiftUI

enum NavigationBarStyle {
case translucent(UIColor)
case clear
}

protocol SceneViewModel {
Expand Down Expand Up @@ -80,8 +81,16 @@ private extension SceneViewController {
func setupNavigationBarStyle() {
switch viewModel.navigationBarStyle {
case .translucent(let color):
navigationController?.navigationBar.backgroundColor = .w_background
navigationController?.navigationBar.barTintColor = color
navigationController?.navigationBar.isTranslucent = true
case .clear:
navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
navigationController?.navigationBar.shadowImage = UIImage()
navigationController?.navigationBar.isTranslucent = true
navigationController?.navigationBar.backgroundColor = .clear
navigationController?.navigationBar.barTintColor = .clear
navigationController?.navigationBar.tintColor = .w_foreground
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import Foundation
import WalletConnectNotify

typealias SubscriptionScope = [String: ScopeValue]

struct SubscriptionsViewModel: Identifiable {
let subscription: NotifySubscription

Expand All @@ -12,15 +14,23 @@ struct SubscriptionsViewModel: Identifiable {
return try? subscription.metadata.icons.first?.asURL()
}

var title: String {
var subtitle: String {
return subscription.metadata.description
}

var name: String {
return subscription.metadata.name
}

var subtitle: String {
var description: String {
return subscription.metadata.description
}

var url: String {
var domain: String {
return subscription.metadata.url
}

var scope: SubscriptionScope {
return subscription.scope
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ final class NotificationsPresenter: ObservableObject {
}

func subscription(forListing listing: ListingViewModel) -> SubscriptionsViewModel? {
return subscriptions.first(where: { $0.url == listing.appDomain })
return subscriptions.first(where: { $0.domain == listing.appDomain })
}

func subscribe(listing: ListingViewModel) async throws {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ final class NotificationsRouter {
}

func presentNotifications(subscription: NotifySubscription) {
PushMessagesModule.create(app: app, subscription: subscription)
SubscriptionModule.create(app: app, subscription: subscription)
.push(from: viewController)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ struct NotificationsView: View {
content: { item, isSelected in
Text(item)
.font(.headline)
.foregroundColor(isSelected ? Color.black : Color.gray )
.foregroundColor(isSelected ? Color.primary : Color.secondary )
.padding(.horizontal, 16)
.padding(.vertical, 8)
},
selection: {
VStack(spacing: 0) {
Spacer()
Rectangle()
.fill(Color.black)
.fill(Color.primary)
.frame(height: 1)
}
})
Expand All @@ -52,6 +52,7 @@ struct NotificationsView: View {
listingRow(listing: listing)
.listRowSeparator(.hidden)
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 16, trailing: 0))
.listRowBackground(Color.clear)
}
}
.listStyle(PlainListStyle())
Expand Down Expand Up @@ -89,6 +90,7 @@ struct NotificationsView: View {
subscriptionRow(subscription: subscription)
.listRowSeparator(.hidden)
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 16, trailing: 0))
.listRowBackground(Color.clear)
}
.onDelete { indexSet in
Task(priority: .high) {
Expand All @@ -110,23 +112,23 @@ struct NotificationsView: View {
} label: {
VStack {
HStack(spacing: 10) {
AsyncImage(url: subscription.imageUrl) { phase in
CacheAsyncImage(url: subscription.imageUrl) { phase in
if let image = phase.image {
image
.resizable()
.frame(width: 60, height: 60)
.background(Color.black.opacity(0.1))
.background(Color.grey8.opacity(0.1))
.cornerRadius(30, corners: .allCorners)
} else {
Color.black.opacity(0.1)
Color.grey8.opacity(0.1)
.frame(width: 60, height: 60)
.cornerRadius(30, corners: .allCorners)
}
}
.padding(.leading, 20)

VStack(alignment: .leading, spacing: 2) {
Text(subscription.title)
Text(subscription.name)
.foregroundColor(.grey8)
.font(.system(size: 20, weight: .semibold, design: .rounded))

Expand All @@ -148,15 +150,15 @@ struct NotificationsView: View {
private func listingRow(listing: ListingViewModel) -> some View {
VStack {
HStack(spacing: 10) {
AsyncImage(url: listing.imageUrl) { phase in
CacheAsyncImage(url: listing.imageUrl) { phase in
if let image = phase.image {
image
.resizable()
.frame(width: 60, height: 60)
.background(Color.black.opacity(0.1))
.background(Color.grey8.opacity(0.1))
.cornerRadius(30, corners: .allCorners)
} else {
Color.black.opacity(0.1)
Color.grey8.opacity(0.1)
.frame(width: 60, height: 60)
.cornerRadius(30, corners: .allCorners)
}
Expand All @@ -178,11 +180,15 @@ struct NotificationsView: View {
if let subscription = presenter.subscription(forListing: listing) {
AsyncButton("Unsubscribe") {
try await presenter.unsubscribe(subscription: subscription)
}.padding(16.0)
}
.foregroundColor(.red)
.padding(16.0)
} else {
AsyncButton("Subscribe") {
try await presenter.subscribe(listing: listing)
}.padding(16.0)
}
.foregroundColor(.primary)
.padding(16.0)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import WalletConnectNotify

final class NotifyPreferencesInteractor {

func updatePreferences(subscription: NotifySubscription, scope: Set<String>) async throws {
try await Notify.instance.update(topic: subscription.topic, scope: scope)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import SwiftUI
import WalletConnectNotify

final class NotifyPreferencesModule {

@discardableResult
static func create(app: Application, subscription: NotifySubscription) -> UIViewController {
let router = NotifyPreferencesRouter(app: app)
let interactor = NotifyPreferencesInteractor()
let presenter = NotifyPreferencesPresenter(subscription: subscription, interactor: interactor, router: router)
let view = NotifyPreferencesView().environmentObject(presenter)
let viewController = SceneViewController(viewModel: presenter, content: view)

router.viewController = viewController

return viewController
}

}
Loading

0 comments on commit e41c2d0

Please sign in to comment.