ContentView.swift 8.6 KB

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