Преглед изворни кода

Reuse the content view from other test app in the new SwiftUI test app (#9176)

Chen Liang пре 4 година
родитељ
комит
fdeb13df42

+ 22 - 0
.github/workflows/messaging.yml

@@ -198,3 +198,25 @@ jobs:
       run: scripts/install_prereqs.sh MessagingSample iOS
     - name: Build
       run: ([ -z $plist_secret ] || scripts/build.sh MessagingSample iOS)
+
+  messaging-swiftui-sample-build-test:
+    # Don't run on private repo unless it is a PR.
+    if: (github.repository == 'Firebase/firebase-ios-sdk' && github.event_name == 'schedule') || github.event_name == 'pull_request'
+    env:
+      plist_secret: ${{ secrets.GHASecretsGPGPassphrase1 }}
+    runs-on: macos-11
+    steps:
+    - uses: actions/checkout@v2
+    - uses: mikehardy/buildcache-action@50738c6c77de7f34e66b870e4f8ede333b69d077
+      with:
+        cache_key: ${{ matrix.os }}
+    - name: Setup Bundler
+      run: scripts/setup_bundler.sh
+    - name: Install Secret GoogleService-Info.plist
+      run: |
+        scripts/decrypt_gha_secret.sh scripts/gha-encrypted/messaging-sample-plist.gpg \
+          FirebaseMessaging/Apps/Shared/GoogleService-Info.plist "$plist_secret"
+    - name: Prereqs
+      run: scripts/install_prereqs.sh SwiftUISample iOS
+    - name: Build
+      run: ([ -z $plist_secret ] || scripts/build.sh SwiftUISample iOS)

+ 6 - 6
FirebaseMessaging/Apps/Sample/Sample.xcodeproj/project.pbxproj

@@ -321,10 +321,10 @@
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_ENTITLEMENTS = Sample/Sample.entitlements;
-				CODE_SIGN_IDENTITY = "iPhone Developer";
+				CODE_SIGN_IDENTITY = "Apple Development";
 				CODE_SIGN_STYLE = Manual;
 				DEVELOPMENT_ASSET_PATHS = "\"Sample/Preview Content\"";
-				DEVELOPMENT_TEAM = EQHXZ8M8AV;
+				DEVELOPMENT_TEAM = "";
 				ENABLE_PREVIEWS = YES;
 				INFOPLIST_FILE = Sample/Info.plist;
 				LD_RUNPATH_SEARCH_PATHS = (
@@ -333,7 +333,7 @@
 				);
 				PRODUCT_BUNDLE_IDENTIFIER = com.google.firebase.extensions.dev;
 				PRODUCT_NAME = "$(TARGET_NAME)";
-				PROVISIONING_PROFILE_SPECIFIER = "Firebase iOS App Extensions Dev";
+				PROVISIONING_PROFILE_SPECIFIER = "";
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
 				SWIFT_VERSION = 5.0;
 				TARGETED_DEVICE_FAMILY = "1,2";
@@ -346,10 +346,10 @@
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_ENTITLEMENTS = Sample/Sample.entitlements;
-				CODE_SIGN_IDENTITY = "iPhone Developer";
+				CODE_SIGN_IDENTITY = "Apple Development";
 				CODE_SIGN_STYLE = Manual;
 				DEVELOPMENT_ASSET_PATHS = "\"Sample/Preview Content\"";
-				DEVELOPMENT_TEAM = EQHXZ8M8AV;
+				DEVELOPMENT_TEAM = "";
 				ENABLE_PREVIEWS = YES;
 				INFOPLIST_FILE = Sample/Info.plist;
 				LD_RUNPATH_SEARCH_PATHS = (
@@ -358,7 +358,7 @@
 				);
 				PRODUCT_BUNDLE_IDENTIFIER = com.google.firebase.extensions.dev;
 				PRODUCT_NAME = "$(TARGET_NAME)";
-				PROVISIONING_PROFILE_SPECIFIER = "Firebase iOS App Extensions Dev";
+				PROVISIONING_PROFILE_SPECIFIER = "";
 				SWIFT_VERSION = 5.0;
 				TARGETED_DEVICE_FAMILY = "1,2";
 			};

+ 0 - 12
FirebaseMessaging/Apps/Shared/Identity.swift

@@ -13,22 +13,10 @@
 // limitations under the License.
 
 import SwiftUI
-import FirebaseMessaging
-import FirebaseInstallations
 
 public final class Identity: ObservableObject {
   // Identity that is unique per app.
   @Published public var installationsID: String? = nil
   // The token that Firebase Messaging use to send notifications.
   @Published public var token: String? = nil
-
-  init() {
-    Installations.installations().installationID(completion: { fid, error in
-      if let error = error as NSError? {
-        print("Failed to get FID: ", error)
-        return
-      }
-      self.installationsID = fid
-    })
-  }
 }

+ 1 - 0
FirebaseMessaging/Apps/Shared/UserSettings.swift

@@ -13,6 +13,7 @@
 // limitations under the License.
 
 import SwiftUI
+import FirebaseCore
 import FirebaseMessaging
 
 public final class UserSettings: ObservableObject {

+ 21 - 9
FirebaseMessaging/Apps/SwiftUISample/SwiftUISample.xcodeproj/project.pbxproj

@@ -7,18 +7,24 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
+		5104EF0A2787BC590026A7C4 /* Identity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5104EF052787BC590026A7C4 /* Identity.swift */; };
+		5104EF0B2787BC590026A7C4 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5104EF062787BC590026A7C4 /* ContentView.swift */; };
+		5104EF0C2787BC590026A7C4 /* UserSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5104EF072787BC590026A7C4 /* UserSettings.swift */; };
+		5104EF0E2787BC590026A7C4 /* TopicView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5104EF092787BC590026A7C4 /* TopicView.swift */; };
+		5104EF12278909060026A7C4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5104EF11278909060026A7C4 /* Assets.xcassets */; };
 		5134F860277EAEC600AEE915 /* SwiftUISampleApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5134F85F277EAEC600AEE915 /* SwiftUISampleApp.swift */; };
-		5134F862277EAEC600AEE915 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5134F861277EAEC600AEE915 /* ContentView.swift */; };
-		5134F864277EAEC900AEE915 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5134F863277EAEC900AEE915 /* Assets.xcassets */; };
 		5134F867277EAEC900AEE915 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5134F866277EAEC900AEE915 /* Preview Assets.xcassets */; };
 		5134F86E277EAEF800AEE915 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5134F86D277EAEF800AEE915 /* GoogleService-Info.plist */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXFileReference section */
+		5104EF052787BC590026A7C4 /* Identity.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Identity.swift; path = ../../Shared/Identity.swift; sourceTree = "<group>"; };
+		5104EF062787BC590026A7C4 /* ContentView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ContentView.swift; path = ../../Shared/ContentView.swift; sourceTree = "<group>"; };
+		5104EF072787BC590026A7C4 /* UserSettings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = UserSettings.swift; path = ../../Shared/UserSettings.swift; sourceTree = "<group>"; };
+		5104EF092787BC590026A7C4 /* TopicView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TopicView.swift; path = ../../Shared/TopicView.swift; sourceTree = "<group>"; };
+		5104EF11278909060026A7C4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = ../../Shared/Assets.xcassets; sourceTree = "<group>"; };
 		5134F85C277EAEC600AEE915 /* SwiftUISample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftUISample.app; sourceTree = BUILT_PRODUCTS_DIR; };
 		5134F85F277EAEC600AEE915 /* SwiftUISampleApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUISampleApp.swift; sourceTree = "<group>"; };
-		5134F861277EAEC600AEE915 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
-		5134F863277EAEC900AEE915 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
 		5134F866277EAEC900AEE915 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
 		5134F86D277EAEF800AEE915 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "../../Shared/GoogleService-Info.plist"; sourceTree = "<group>"; };
 		5134F86F277EAF0A00AEE915 /* SwiftUISample.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = SwiftUISample.entitlements; sourceTree = "<group>"; };
@@ -56,12 +62,15 @@
 		5134F85E277EAEC600AEE915 /* SwiftUISample */ = {
 			isa = PBXGroup;
 			children = (
+				5104EF062787BC590026A7C4 /* ContentView.swift */,
+				5104EF052787BC590026A7C4 /* Identity.swift */,
+				5104EF092787BC590026A7C4 /* TopicView.swift */,
+				5104EF072787BC590026A7C4 /* UserSettings.swift */,
 				5134F870277EAF1600AEE915 /* Info.plist */,
 				5134F86F277EAF0A00AEE915 /* SwiftUISample.entitlements */,
 				5134F85F277EAEC600AEE915 /* SwiftUISampleApp.swift */,
 				5134F86D277EAEF800AEE915 /* GoogleService-Info.plist */,
-				5134F861277EAEC600AEE915 /* ContentView.swift */,
-				5134F863277EAEC900AEE915 /* Assets.xcassets */,
+				5104EF11278909060026A7C4 /* Assets.xcassets */,
 				5134F865277EAEC900AEE915 /* Preview Content */,
 			);
 			path = SwiftUISample;
@@ -141,7 +150,7 @@
 			buildActionMask = 2147483647;
 			files = (
 				5134F867277EAEC900AEE915 /* Preview Assets.xcassets in Resources */,
-				5134F864277EAEC900AEE915 /* Assets.xcassets in Resources */,
+				5104EF12278909060026A7C4 /* Assets.xcassets in Resources */,
 				5134F86E277EAEF800AEE915 /* GoogleService-Info.plist in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -153,8 +162,11 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				5134F862277EAEC600AEE915 /* ContentView.swift in Sources */,
 				5134F860277EAEC600AEE915 /* SwiftUISampleApp.swift in Sources */,
+				5104EF0E2787BC590026A7C4 /* TopicView.swift in Sources */,
+				5104EF0C2787BC590026A7C4 /* UserSettings.swift in Sources */,
+				5104EF0A2787BC590026A7C4 /* Identity.swift in Sources */,
+				5104EF0B2787BC590026A7C4 /* ContentView.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -318,7 +330,7 @@
 				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
 				CODE_SIGN_ENTITLEMENTS = SwiftUISample/SwiftUISample.entitlements;
 				CODE_SIGN_IDENTITY = "Apple Development";
-				CODE_SIGN_STYLE = Manual;
+				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = 1;
 				DEVELOPMENT_ASSET_PATHS = "\"SwiftUISample/Preview Content\"";
 				DEVELOPMENT_TEAM = "";

+ 0 - 11
FirebaseMessaging/Apps/SwiftUISample/SwiftUISample/Assets.xcassets/AccentColor.colorset/Contents.json

@@ -1,11 +0,0 @@
-{
-  "colors" : [
-    {
-      "idiom" : "universal"
-    }
-  ],
-  "info" : {
-    "author" : "xcode",
-    "version" : 1
-  }
-}

+ 0 - 98
FirebaseMessaging/Apps/SwiftUISample/SwiftUISample/Assets.xcassets/AppIcon.appiconset/Contents.json

@@ -1,98 +0,0 @@
-{
-  "images" : [
-    {
-      "idiom" : "iphone",
-      "scale" : "2x",
-      "size" : "20x20"
-    },
-    {
-      "idiom" : "iphone",
-      "scale" : "3x",
-      "size" : "20x20"
-    },
-    {
-      "idiom" : "iphone",
-      "scale" : "2x",
-      "size" : "29x29"
-    },
-    {
-      "idiom" : "iphone",
-      "scale" : "3x",
-      "size" : "29x29"
-    },
-    {
-      "idiom" : "iphone",
-      "scale" : "2x",
-      "size" : "40x40"
-    },
-    {
-      "idiom" : "iphone",
-      "scale" : "3x",
-      "size" : "40x40"
-    },
-    {
-      "idiom" : "iphone",
-      "scale" : "2x",
-      "size" : "60x60"
-    },
-    {
-      "idiom" : "iphone",
-      "scale" : "3x",
-      "size" : "60x60"
-    },
-    {
-      "idiom" : "ipad",
-      "scale" : "1x",
-      "size" : "20x20"
-    },
-    {
-      "idiom" : "ipad",
-      "scale" : "2x",
-      "size" : "20x20"
-    },
-    {
-      "idiom" : "ipad",
-      "scale" : "1x",
-      "size" : "29x29"
-    },
-    {
-      "idiom" : "ipad",
-      "scale" : "2x",
-      "size" : "29x29"
-    },
-    {
-      "idiom" : "ipad",
-      "scale" : "1x",
-      "size" : "40x40"
-    },
-    {
-      "idiom" : "ipad",
-      "scale" : "2x",
-      "size" : "40x40"
-    },
-    {
-      "idiom" : "ipad",
-      "scale" : "1x",
-      "size" : "76x76"
-    },
-    {
-      "idiom" : "ipad",
-      "scale" : "2x",
-      "size" : "76x76"
-    },
-    {
-      "idiom" : "ipad",
-      "scale" : "2x",
-      "size" : "83.5x83.5"
-    },
-    {
-      "idiom" : "ios-marketing",
-      "scale" : "1x",
-      "size" : "1024x1024"
-    }
-  ],
-  "info" : {
-    "author" : "xcode",
-    "version" : 1
-  }
-}

+ 0 - 6
FirebaseMessaging/Apps/SwiftUISample/SwiftUISample/Assets.xcassets/Contents.json

@@ -1,6 +0,0 @@
-{
-  "info" : {
-    "author" : "xcode",
-    "version" : 1
-  }
-}

+ 0 - 28
FirebaseMessaging/Apps/SwiftUISample/SwiftUISample/ContentView.swift

@@ -1,28 +0,0 @@
-// Copyright 2022 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import SwiftUI
-
-struct ContentView: View {
-  var body: some View {
-    Text("Hello, world!")
-      .padding()
-  }
-}
-
-struct ContentView_Previews: PreviewProvider {
-  static var previews: some View {
-    ContentView()
-  }
-}

+ 55 - 4
FirebaseMessaging/Apps/SwiftUISample/SwiftUISample/SwiftUISampleApp.swift

@@ -12,19 +12,26 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+import Combine
 import UIKit
 import SwiftUI
 import FirebaseCore
+import FirebaseInstallations
 import FirebaseMessaging
 
-@main
+class AppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDelegate,
+  MessagingDelegate {
+  let identity = Identity()
+  var cancellables = Set<AnyCancellable>()
+
+  // Must implement the method to make swizzling work in SwiftUI lifecycle.
+  func application(_ application: UIApplication,
+                   didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {}
 
-class AppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDelegate {
   func application(_ application: UIApplication,
                    didFinishLaunchingWithOptions launchOptions: [UIApplication
                      .LaunchOptionsKey: Any]? = nil) -> Bool {
     FirebaseApp.configure()
-    application.delegate = self
 
     // Request permissions for push notifications
     let center = UNUserNotificationCenter.current()
@@ -35,17 +42,61 @@ class AppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDele
       }
     }
     application.registerForRemoteNotifications()
+
+    // Observe token refresh - two ways
+    // First way: use MessagingDelegate
+    let settings = UserSettings()
+    if settings.shouldUseDelegateThanNotification {
+      Messaging.messaging().delegate = self
+    } else {
+      // Second way: use notification to subscribe to token refresh
+      NotificationCenter.default
+        .publisher(for: Notification.Name.MessagingRegistrationTokenRefreshed)
+        .map { $0.object as? String }
+        .receive(on: RunLoop.main)
+        .assign(to: \Identity.token, on: identity)
+        .store(in: &cancellables)
+    }
+
+    // Subscribe to fid changes
+    // Somehow FID notification is not triggered during app start, will have to invest
+    refreshInstallationsID()
+    NotificationCenter.default
+      .publisher(for: Notification.Name.InstallationIDDidChange)
+      .receive(on: RunLoop.main)
+      .sink(receiveValue: { _ in
+        self.refreshInstallationsID()
+      })
+      .store(in: &cancellables)
     return true
   }
+
+  func refreshInstallationsID() {
+    Installations.installations().installationID(completion: { fid, error in
+      if let error = error as NSError? {
+        print("Failed to get FID: ", error)
+        return
+      }
+      self.identity.installationsID = fid
+    })
+  }
+
+  func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
+    identity.token = fcmToken
+    print("=============================\n")
+    print("Did refresh token:\n", identity.token ?? "")
+    print("\n=============================\n")
+  }
 }
 
+@main
 struct SwiftUISampleApp: App {
   // Add the adapter to access notifications APIs in AppDelegate
   @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
 
   var body: some Scene {
     WindowGroup {
-      ContentView()
+      ContentView().environmentObject(appDelegate.identity).environmentObject(UserSettings())
     }
   }
 }

+ 11 - 0
scripts/build.sh

@@ -35,6 +35,7 @@ product can be one of:
   InAppMessaging
   Messaging
   MessagingSample
+  SwiftUISample
   MLModelDownloaderSample
   RemoteConfig
   RemoteConfigSample
@@ -424,6 +425,16 @@ case "$product-$platform-$method" in
     fi
     ;;
 
+  SwiftUISample-*-*)
+    if check_secrets; then
+      RunXcodebuild \
+        -workspace 'FirebaseMessaging/Apps/SwiftUISample/SwiftUISample.xcworkspace' \
+        -scheme "SwiftUISample" \
+        "${xcb_flags[@]}" \
+        build
+    fi
+    ;;
+
   MLModelDownloaderSample-*-*)
   if check_secrets; then
     RunXcodebuild \

+ 5 - 0
scripts/install_prereqs.sh

@@ -142,6 +142,11 @@ case "$project-$platform-$method" in
     bundle exec pod install --project-directory=FirebaseMessaging/Apps/Sample --repo-update
     ;;
 
+  SwiftUISample-*)
+    install_xcpretty
+    bundle exec pod install --project-directory=FirebaseMessaging/Apps/SwiftUISample --repo-update
+    ;;
+
   MLModelDownloaderSample-*)
     install_xcpretty
     bundle exec pod install --project-directory=FirebaseMLModelDownloader/Apps/Sample --repo-update