ContentView.swift 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. // Copyright 2020 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. import Combine
  15. import FirebaseCore
  16. import FirebaseInstallations
  17. import FirebaseMessaging
  18. import SwiftUI
  19. import UIKit
  20. struct ContentView: View {
  21. @EnvironmentObject var identity: Identity
  22. @EnvironmentObject var settings: UserSettings
  23. @State private var log: String = ""
  24. var body: some View {
  25. NavigationView {
  26. // Outer stack containing the list and the buttons.
  27. VStack {
  28. List {
  29. VStack(alignment: .leading) {
  30. Text("InstallationsID")
  31. .font(.subheadline)
  32. .fontWeight(.semibold)
  33. Text(identity.installationsID ?? "None").foregroundColor(.green)
  34. }
  35. VStack(alignment: .leading) {
  36. Text("Token")
  37. .font(.subheadline)
  38. .fontWeight(.semibold)
  39. Text(identity.token ?? "None")
  40. .foregroundColor(.green)
  41. // Increase the layout priority to allow more than one line to be shown. Without this,
  42. // the
  43. // simulator renders a single truncated line even though the Preview renders it
  44. // appropriately. Potentially a bug in the simulator?
  45. .layoutPriority(1)
  46. .lineLimit(7)
  47. }
  48. NavigationLink(destination: SettingsView()) {
  49. Text("Settings")
  50. .fontWeight(.semibold)
  51. }
  52. NavigationLink(destination: TopicView()) {
  53. Text("Topic")
  54. .fontWeight(.semibold)
  55. }
  56. // MARK: Action buttons
  57. VStack(alignment: .leading) {
  58. Text("getToken")
  59. .fontWeight(.semibold)
  60. HStack {
  61. Button(action: getIDAndToken) {
  62. HStack {
  63. Image(systemName: "arrow.clockwise.circle.fill")
  64. Text("FID & Token")
  65. .fontWeight(.semibold)
  66. }
  67. }
  68. Button(action: getFCMToken) {
  69. HStack {
  70. Image(systemName: "arrow.clockwise.circle.fill").font(.body)
  71. Text("getToken")
  72. .fontWeight(.semibold)
  73. }
  74. }
  75. }
  76. }.font(.system(size: 14))
  77. VStack(alignment: .leading) {
  78. Text("deleteToken")
  79. .fontWeight(.semibold)
  80. HStack {
  81. Button(action: deleteFCMToken) {
  82. HStack {
  83. Image(systemName: "trash.fill")
  84. Text("deleteToken")
  85. .fontWeight(.semibold)
  86. }
  87. }
  88. }
  89. }.font(.system(size: 14))
  90. VStack(alignment: .leading) {
  91. Text("delete")
  92. .fontWeight(.semibold)
  93. HStack {
  94. Button(action: deleteFCM) {
  95. HStack {
  96. Image(systemName: "trash.fill")
  97. Text("FM.delete")
  98. .fontWeight(.semibold)
  99. }
  100. }
  101. Button(action: deleteFID) {
  102. HStack {
  103. Image(systemName: "trash.fill")
  104. Text("FIS.delete")
  105. .fontWeight(.semibold)
  106. }
  107. }
  108. }
  109. }.font(.system(size: 14))
  110. Text("\(log)")
  111. .lineLimit(10)
  112. .multilineTextAlignment(.leading)
  113. }
  114. .navigationBarTitle("Firebase Messaging")
  115. }.buttonStyle(IdentityButtonStyle())
  116. }
  117. }
  118. func getIDAndToken() {
  119. Messaging.messaging().token { token, error in
  120. guard let token = token, error == nil else {
  121. self.log = "Failed getting iid and token: \(String(describing: error))"
  122. return
  123. }
  124. self.identity.token = token
  125. self.log = "Successfully got token."
  126. print("Token: ", self.identity.token ?? "")
  127. Installations.installations().installationID { fid, error in
  128. self.identity.installationsID = fid
  129. self.log = "Successfully got iid and token."
  130. }
  131. }
  132. }
  133. func getFCMToken() {
  134. Messaging.messaging().token { token, error in
  135. guard let token = token, error == nil else {
  136. self.log = "Failed getting iid and token: \(String(describing: error))"
  137. return
  138. }
  139. self.identity.token = token
  140. self.log = "Successfully got token."
  141. print("Token: ", self.identity.token ?? "")
  142. }
  143. }
  144. func deleteFCMToken() {
  145. Messaging.messaging().deleteToken { error in
  146. if let error = error as NSError? {
  147. self.log = "Failed deleting token: \(error)"
  148. return
  149. }
  150. self.log = "Successfully deleted token."
  151. }
  152. }
  153. func deleteFCM() {
  154. Messaging.messaging().deleteData { error in
  155. if let error = error as NSError? {
  156. self.log = "Failed deleting Messaging: \(error)"
  157. return
  158. }
  159. self.log = "Successfully deleted Messaging data."
  160. }
  161. }
  162. func deleteFID() {
  163. Installations.installations().delete { error in
  164. if let error = error as NSError? {
  165. self.log = "Failed deleting FID: \(error)"
  166. return
  167. }
  168. self.log = "Successfully deleted FID."
  169. }
  170. }
  171. }
  172. struct ActivityViewController: UIViewControllerRepresentable {
  173. var activityItems: [Any]
  174. var applicationActivities: [UIActivity]? = nil
  175. func makeUIViewController(context: UIViewControllerRepresentableContext<ActivityViewController>)
  176. -> UIActivityViewController {
  177. let controller = UIActivityViewController(
  178. activityItems: activityItems,
  179. applicationActivities: applicationActivities
  180. )
  181. return controller
  182. }
  183. func updateUIViewController(_ uiViewController: UIActivityViewController,
  184. context: UIViewControllerRepresentableContext<
  185. ActivityViewController
  186. >) {}
  187. }
  188. struct SettingsView: View {
  189. @EnvironmentObject var settings: UserSettings
  190. @State var shouldUseDelegate = true
  191. @State private var isSharePresented: Bool = false
  192. var body: some View {
  193. VStack {
  194. List {
  195. Toggle(isOn: $settings.isAutoInitEnabled) {
  196. Text("isAutoInitEnabled")
  197. .fontWeight(.semibold)
  198. }
  199. Toggle(isOn: $settings.shouldUseDelegateThanNotification) {
  200. Text("shouldUseDelegate")
  201. .fontWeight(.semibold)
  202. }
  203. Button(action: shareToken) {
  204. HStack {
  205. Image(systemName: "square.and.arrow.up").font(.body)
  206. Text("Share Token")
  207. .fontWeight(.semibold)
  208. }
  209. }
  210. .sheet(isPresented: $isSharePresented, onDismiss: {
  211. print("Dismiss")
  212. }, content: {
  213. let items = [Messaging.messaging().fcmToken]
  214. ActivityViewController(activityItems: items as [Any])
  215. })
  216. }
  217. .font(.subheadline)
  218. .foregroundColor(.blue)
  219. }
  220. }
  221. func shareToken() {
  222. isSharePresented = true
  223. }
  224. }
  225. struct ContentView_Previews: PreviewProvider {
  226. // A fake filled identity for testing rendering of a filled cell.
  227. static let filledIdentity: Identity = {
  228. var identity = Identity()
  229. identity.installationsID = UUID().uuidString
  230. // The token is a long string, generate a very long repeating string of characters to see how
  231. // the view
  232. // will react.
  233. let longString = UUID().uuidString.replacingOccurrences(of: "-", with: "")
  234. identity.token = Array(repeating: longString, count: 8).reduce("", +)
  235. return identity
  236. }()
  237. static let filledSettings: UserSettings = {
  238. var settings = UserSettings()
  239. settings.shouldUseDelegateThanNotification = true
  240. settings.isAutoInitEnabled = true
  241. return settings
  242. }()
  243. static var previews: some View {
  244. Group {
  245. ContentView().environmentObject(filledIdentity).environmentObject(filledSettings)
  246. }
  247. }
  248. }
  249. struct IdentityButtonStyle: ButtonStyle {
  250. func makeBody(configuration: Self.Configuration) -> some View {
  251. configuration.label
  252. .frame(minWidth: 0, maxWidth: 120)
  253. .padding()
  254. .foregroundColor(.white)
  255. .background(Color.yellow)
  256. .cornerRadius(20)
  257. // Push the button down a bit when it's pressed.
  258. .scaleEffect(configuration.isPressed ? 0.9 : 1)
  259. .font(.footnote)
  260. }
  261. }