This repository has been archived by the owner on May 10, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 440
/
IPFSCustomGatewayView.swift
136 lines (124 loc) · 4.88 KB
/
IPFSCustomGatewayView.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// Copyright 2023 The Brave Authors. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
import SwiftUI
import BraveCore
import DesignSystem
struct IPFSCustomGatewayView: View {
private static let ipfsTestPath = "ipfs"
private static let ipfsTestCID = "bafkqae2xmvwgg33nmuqhi3zajfiemuzahiwss"
private static let ipfsTestContent = "Welcome to IPFS :-)"
private enum SetButtonStatus {
case enabled
case disabled
case loading
}
private let ipfsAPI: IpfsAPI
private let isForNFT: Bool
@State private var url: String = "https://"
@State private var setButtonStatus: SetButtonStatus = .disabled
@State private var isPresentingWrongGatewayAlert: Bool = false
init(ipfsAPI: IpfsAPI, isForNFT: Bool = false) {
self.ipfsAPI = ipfsAPI
self.isForNFT = isForNFT
}
var body: some View {
List {
Section(footer: Text(Strings.Wallet.nftGatewayLongDescription)) {
TextField(ipfsAPI.nftIpfsGateway?.absoluteString ?? "https://", text: $url)
.font(.body)
.keyboardType(.URL)
.autocapitalization(.none)
.disableAutocorrection(true)
.foregroundColor(Color(.braveLabel))
.onChange(of: url) { newValue in
if newValue.count < 8 && "https://".hasPrefix(newValue) {
self.url = "https://"
setButtonStatus = .disabled
} else {
// The withSecureUrlScheme is used in order to force user to use secure url scheme
// Instead of checking paste-board with every character entry, the textView text is analyzed
// and according to what prefix copied or entered, text is altered to start with https://
// this logic block repeating https:// and http:// schemes
let textEntered = newValue.withSecureUrlScheme
self.url = textEntered
let oldValue = isForNFT ? ipfsAPI.nftIpfsGateway : ipfsAPI.ipfsGateway
if let enteredURL = URL(string: textEntered), enteredURL != oldValue {
setButtonStatus = .enabled
} else {
setButtonStatus = .disabled
}
}
}
.listRowBackground(Color(.secondaryBraveGroupedBackground))
}
}
.listStyle(InsetGroupedListStyle())
.listBackgroundColor(Color(UIColor.braveGroupedBackground))
.navigationBarTitleDisplayMode(.inline)
.navigationTitle(isForNFT ? Strings.Wallet.customizeIPFSNFTPublicGatewayNavTitle : Strings.Wallet.customizeIPFSPublicGatewayNavTitle)
.navigationBarItems(
// Have to use this instead of toolbar placement to have a custom button style
trailing: Button(action: {
validateURLAndSet()
}) {
if setButtonStatus == .loading {
ProgressView()
} else {
Text(Strings.Wallet.setGatewayButtonTitle)
}
}
.buttonStyle(BraveFilledButtonStyle(size: .small))
.disabled(setButtonStatus != .enabled)
)
.alert(isPresented: $isPresentingWrongGatewayAlert) {
Alert(
title: Text(Strings.Wallet.wrongGatewayAlertTitle),
message: Text(Strings.Wallet.wrongGatewayAlertDescription),
dismissButton: .cancel(Text(Strings.OKString))
)
}
.onAppear {
// SwiftUI bug, has to wait a bit (#7044: bug only exists
// in iOS 15. Will revisit once iOS 15 support is removed)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
if let url = isForNFT ? ipfsAPI.nftIpfsGateway?.absoluteString : ipfsAPI.ipfsGateway?.absoluteString {
self.url = url
}
}
}
}
private func validateURLAndSet() {
Task { @MainActor in
guard let enteredURL = URL(string: url), enteredURL.isSecureWebPage() else {
isPresentingWrongGatewayAlert = true
return
}
var testURL = enteredURL
testURL.append(pathComponents: IPFSCustomGatewayView.ipfsTestPath, IPFSCustomGatewayView.ipfsTestCID)
setButtonStatus = .loading
resignFirstResponder()
do {
let (data, _) = try await URLSession.shared.data(from: testURL)
if String(data: data, encoding: .utf8) == IPFSCustomGatewayView.ipfsTestContent {
if isForNFT {
ipfsAPI.nftIpfsGateway = enteredURL
} else {
ipfsAPI.ipfsGateway = enteredURL
}
setButtonStatus = .disabled
} else {
isPresentingWrongGatewayAlert = true
setButtonStatus = .enabled
}
} catch {
isPresentingWrongGatewayAlert = true
setButtonStatus = .enabled
}
}
}
private func resignFirstResponder() {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
}