ContentView.swift 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. //
  2. // ContentView.swift
  3. // RemoteConfigSwiftSample
  4. //
  5. // Created by Karen Zeng on 11/16/20.
  6. // Copyright © 2020 Firebase. All rights reserved.
  7. //
  8. import SwiftUI
  9. import FirebaseRemoteConfig
  10. enum ValueType: String, Identifiable {
  11. case string
  12. case boolean
  13. case int
  14. var id: String { rawValue }
  15. }
  16. var remoteConfig: RemoteConfig!
  17. var dateFormatter: DateFormatter!
  18. struct ContentView: View {
  19. @State var paramName: String = ""
  20. @State var valueType: ValueType = ValueType.string
  21. @State var output: [String] = []
  22. @State var fetchTime: Date?
  23. @State var activateTime: Date?
  24. public init() {
  25. remoteConfig = RemoteConfig.remoteConfig()
  26. dateFormatter = DateFormatter()
  27. dateFormatter.timeStyle = .medium
  28. }
  29. var body: some View {
  30. VStack {
  31. Text("Remote Config").bold().padding()
  32. VStack(alignment: .center, spacing: 0) {
  33. ScrollView {
  34. ScrollViewReader { scrollView in
  35. VStack(spacing: 0) {
  36. ForEach(self.output.indices, id: \.self) { i in
  37. Text(self.output[i])
  38. .frame(maxWidth: .infinity, alignment: .leading)
  39. .font(.system(size: 14, design: .monospaced))
  40. .id(i)
  41. }.onAppear {
  42. withAnimation { scrollView.scrollTo(self.output.count - 1) }
  43. }
  44. }.fixedSize(horizontal: false, vertical: true).padding()
  45. if self.output.count == 0 {
  46. HStack {
  47. Spacer()
  48. }
  49. }
  50. }
  51. }.background(Color(UIColor.systemGray6).edgesIgnoringSafeArea(.all))
  52. Button(action: { self.output = [] }) {
  53. Text("Clear logs")
  54. .font(.system(size: 14))
  55. }.frame(maxWidth: .infinity).padding().background(Color(UIColor.systemGray6))
  56. }.zIndex(1)
  57. VStack(alignment: .center) {
  58. HStack {
  59. TextField("Parameter Name", text: $paramName).autocapitalization(.none)
  60. Picker("ValueType", selection: $valueType) {
  61. Text("String").tag(ValueType.string).font(.system(size: 14))
  62. Text("Boolean").tag(ValueType.boolean).font(.system(size: 14))
  63. Text("Int").tag(ValueType.int).font(.system(size: 14))
  64. }.frame(width: 80, height: 60).clipped()
  65. Button(action: getParameter) {
  66. Text("Get").padding()
  67. }
  68. }.padding([.horizontal])
  69. Divider()
  70. HStack(alignment: .center, spacing: 10) {
  71. Button(action: fetchRemoteConfig) {
  72. Text("Fetch").frame(maxWidth: .infinity)
  73. }
  74. Button(action: activateRemoteConfig) {
  75. Text("Activate").frame(maxWidth: .infinity)
  76. }
  77. }.padding()
  78. HStack(alignment: .center, spacing: 10) {
  79. Text("Last fetched:\n" +
  80. (fetchTime != nil ? dateFormatter.string(from: fetchTime!) : "-"))
  81. .foregroundColor(Color.gray)
  82. .frame(maxWidth: .infinity)
  83. .multilineTextAlignment(.center)
  84. Text("Last activated:\n" +
  85. (activateTime != nil ? dateFormatter.string(from: activateTime!) : "-"))
  86. .foregroundColor(Color.gray)
  87. .frame(maxWidth: .infinity)
  88. .multilineTextAlignment(.center)
  89. }.padding().background(Color(UIColor.systemGray6))
  90. }
  91. }
  92. }
  93. func fetchRemoteConfig() {
  94. remoteConfig.fetch(withExpirationDuration: 0) { (status, error) -> Void in
  95. var message: String
  96. if status == .success {
  97. message = "Fetched successfully"
  98. self.fetchTime = Date()
  99. } else {
  100. message = "Fetch error: \(error?.localizedDescription ?? "No error available.")"
  101. }
  102. print(message)
  103. self.log(message)
  104. }
  105. }
  106. func activateRemoteConfig() {
  107. remoteConfig.activate { (activated, error) -> Void in
  108. var message: String
  109. if activated {
  110. message = "Activated updated config"
  111. self.activateTime = Date()
  112. } else if error == nil {
  113. message = "No change in config"
  114. } else {
  115. message = "Activate error: \(error?.localizedDescription ?? "No error available")"
  116. }
  117. print(message)
  118. self.log(message)
  119. }
  120. }
  121. func getParameter() {
  122. let value = remoteConfig.configValue(forKey: paramName)
  123. log("Parameter: \"\(paramName)\"")
  124. switch valueType {
  125. case ValueType.string:
  126. log("Value(String): \"\(value.stringValue ?? "")\"")
  127. case ValueType.boolean:
  128. log("Value(Bool): \(String(value.boolValue))")
  129. case ValueType.int:
  130. log("Value(Int): \(value.numberValue.stringValue)")
  131. }
  132. log("Source: \(getSourceName(value.source))")
  133. }
  134. func log(_ message: String) {
  135. output.append("[\(dateFormatter.string(from: Date()))] \(message)\n")
  136. }
  137. func getSourceName(_ source: RemoteConfigSource) -> String {
  138. switch source {
  139. case RemoteConfigSource.static:
  140. return "STATIC"
  141. case RemoteConfigSource.default:
  142. return "DEFAULT"
  143. case RemoteConfigSource.remote:
  144. return "REMOTE"
  145. default:
  146. return "UNKNOWN"
  147. }
  148. }
  149. }
  150. struct ContentView_Previews: PreviewProvider {
  151. static var previews: some View {
  152. ContentView()
  153. }
  154. }