Prechádzať zdrojové kódy

Rebrand app to Grammar Pro: AI Writing App with App Store-safe bundle naming.

Separate the user-facing display name from PRODUCT_NAME so the bundle ships as Grammar Pro.app, centralize branding constants, and update menu bar and in-app copy.

Co-authored-by: Cursor <cursoragent@cursor.com>
Hussain Afzal 4 týždňov pred
rodič
commit
c728491217

+ 15 - 7
gramora.xcodeproj/project.pbxproj

@@ -7,7 +7,7 @@
 	objects = {
 
 /* Begin PBXFileReference section */
-		A10000012F00000000000001 /* gramora.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; name = gramora.app; path = Gramora.app; sourceTree = BUILT_PRODUCTS_DIR; };
+		A10000012F00000000000001 /* Grammar Pro.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Grammar Pro.app"; sourceTree = BUILT_PRODUCTS_DIR; };
 /* End PBXFileReference section */
 
 /* Begin PBXFileSystemSynchronizedRootGroup section */
@@ -40,7 +40,7 @@
 		A10000052F00000000000001 /* Products */ = {
 			isa = PBXGroup;
 			children = (
-				A10000012F00000000000001 /* gramora.app */,
+				A10000012F00000000000001 /* Grammar Pro.app */,
 			);
 			name = Products;
 			sourceTree = "<group>";
@@ -67,7 +67,7 @@
 			packageProductDependencies = (
 			);
 			productName = gramora;
-			productReference = A10000012F00000000000001 /* gramora.app */;
+			productReference = A10000012F00000000000001 /* Grammar Pro.app */;
 			productType = "com.apple.product-type.application";
 		};
 /* End PBXNativeTarget section */
@@ -252,10 +252,14 @@
 				CODE_SIGN_STYLE = Automatic;
 				COMBINE_HIDPI_IMAGES = YES;
 				CURRENT_PROJECT_VERSION = 1;
+				DEVELOPMENT_TEAM = LY29MGDPPD;
 				ENABLE_APP_SANDBOX = YES;
 				ENABLE_USER_SELECTED_FILES = readonly;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_FILE = gramora/Info.plist;
+				INFOPLIST_KEY_CFBundleDisplayName = "Grammar Pro: AI Writing App";
+				INFOPLIST_KEY_CFBundleName = "Grammar Pro";
+				INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.education";
 				INFOPLIST_KEY_NSHumanReadableCopyright = "";
 				LD_RUNPATH_SEARCH_PATHS = (
 					"$(inherited)",
@@ -263,8 +267,8 @@
 				);
 				MACOSX_DEPLOYMENT_TARGET = 12.0;
 				MARKETING_VERSION = 1.0;
-				PRODUCT_BUNDLE_IDENTIFIER = "com.Gramora";
-				PRODUCT_NAME = Gramora;
+				PRODUCT_BUNDLE_IDENTIFIER = "com.grammar-pro";
+				PRODUCT_NAME = "Grammar Pro";
 				STRING_CATALOG_GENERATE_SYMBOLS = YES;
 				SWIFT_APPROACHABLE_CONCURRENCY = YES;
 				SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;
@@ -283,10 +287,14 @@
 				CODE_SIGN_STYLE = Automatic;
 				COMBINE_HIDPI_IMAGES = YES;
 				CURRENT_PROJECT_VERSION = 1;
+				DEVELOPMENT_TEAM = LY29MGDPPD;
 				ENABLE_APP_SANDBOX = YES;
 				ENABLE_USER_SELECTED_FILES = readonly;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_FILE = gramora/Info.plist;
+				INFOPLIST_KEY_CFBundleDisplayName = "Grammar Pro: AI Writing App";
+				INFOPLIST_KEY_CFBundleName = "Grammar Pro";
+				INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.education";
 				INFOPLIST_KEY_NSHumanReadableCopyright = "";
 				LD_RUNPATH_SEARCH_PATHS = (
 					"$(inherited)",
@@ -294,8 +302,8 @@
 				);
 				MACOSX_DEPLOYMENT_TARGET = 12.0;
 				MARKETING_VERSION = 1.0;
-				PRODUCT_BUNDLE_IDENTIFIER = "com.Gramora";
-				PRODUCT_NAME = Gramora;
+				PRODUCT_BUNDLE_IDENTIFIER = "com.grammar-pro";
+				PRODUCT_NAME = "Grammar Pro";
 				STRING_CATALOG_GENERATE_SYMBOLS = YES;
 				SWIFT_APPROACHABLE_CONCURRENCY = YES;
 				SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;

+ 4 - 4
gramora.xcodeproj/xcshareddata/xcschemes/gramora.xcscheme

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
    LastUpgradeVersion = "2650"
-   version = "1.7">
+   version = "1.8">
    <BuildAction
       parallelizeBuildables = "YES"
       buildImplicitDependencies = "YES"
@@ -16,7 +16,7 @@
             <BuildableReference
                BuildableIdentifier = "primary"
                BlueprintIdentifier = "A10000062F00000000000001"
-               BuildableName = "Gramora.app"
+               BuildableName = "Grammar Pro.app"
                BlueprintName = "gramora"
                ReferencedContainer = "container:gramora.xcodeproj">
             </BuildableReference>
@@ -46,7 +46,7 @@
          <BuildableReference
             BuildableIdentifier = "primary"
             BlueprintIdentifier = "A10000062F00000000000001"
-            BuildableName = "Gramora.app"
+            BuildableName = "Grammar Pro.app"
             BlueprintName = "gramora"
             ReferencedContainer = "container:gramora.xcodeproj">
          </BuildableReference>
@@ -73,7 +73,7 @@
          <BuildableReference
             BuildableIdentifier = "primary"
             BlueprintIdentifier = "A10000062F00000000000001"
-            BuildableName = "Gramora.app"
+            BuildableName = "Grammar Pro.app"
             BlueprintName = "gramora"
             ReferencedContainer = "container:gramora.xcodeproj">
          </BuildableReference>

+ 6 - 0
gramora/App/GramoraApp.swift

@@ -6,6 +6,12 @@ struct GramoraApp: App {
     @StateObject private var themeManager = ThemeManager()
     @StateObject private var appRating = AppRatingManager()
 
+    init() {
+        DispatchQueue.main.async {
+            ApplicationMenu.synchronizeTitle()
+        }
+    }
+
     var body: some Scene {
         WindowGroup {
             MainView()

+ 0 - 20
gramora/Info.plist

@@ -2,27 +2,7 @@
 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
 <dict>
-	<key>CFBundleDevelopmentRegion</key>
-	<string>$(DEVELOPMENT_LANGUAGE)</string>
-	<key>CFBundleExecutable</key>
-	<string>$(EXECUTABLE_NAME)</string>
-	<key>CFBundleIdentifier</key>
-	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
-	<key>CFBundleInfoDictionaryVersion</key>
-	<string>6.0</string>
-	<key>CFBundleDisplayName</key>
-	<string>Gramora</string>
-	<key>CFBundleName</key>
-	<string>Gramora</string>
-	<key>CFBundlePackageType</key>
-	<string>APPL</string>
-	<key>CFBundleShortVersionString</key>
-	<string>$(MARKETING_VERSION)</string>
-	<key>CFBundleVersion</key>
-	<string>$(CURRENT_PROJECT_VERSION)</string>
 	<key>LSMinimumSystemVersion</key>
 	<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
-	<key>NSHumanReadableCopyright</key>
-	<string></string>
 </dict>
 </plist>

+ 14 - 0
gramora/Utilities/AppBrand.swift

@@ -0,0 +1,14 @@
+import Foundation
+
+enum AppBrand {
+    /// Full display name used in the menu bar, Dock, and App Store.
+    static let name = "Grammar Pro: AI Writing App"
+
+    /// On-disk bundle name (`PRODUCT_NAME`). Must not contain ':' for App Store uploads.
+    static let bundleName = "Grammar Pro"
+
+    /// Compact label for tight in-app layouts such as the sidebar header.
+    static let shortName = "Grammar Pro"
+
+    static let premiumName = "Grammar Pro Premium"
+}

+ 1 - 1
gramora/Utilities/AppTheme.swift

@@ -31,7 +31,7 @@ enum AppTheme {
     /// Small extra inset below the title bar on tool pages.
     static let contentTopBreathingRoom: CGFloat = 8
 
-    /// Aligns tool page titles with the sidebar "Gramora" label.
+    /// Aligns tool page titles with the sidebar brand label.
     static var brandLabelTopInset: CGFloat {
         headerTopInset + (logoMarkSize - 22) / 2 + contentTopBreathingRoom
     }

+ 8 - 0
gramora/Utilities/ApplicationMenu.swift

@@ -0,0 +1,8 @@
+import AppKit
+
+enum ApplicationMenu {
+    static func synchronizeTitle() {
+        guard let appMenuItem = NSApplication.shared.mainMenu?.items.first else { return }
+        appMenuItem.title = AppBrand.name
+    }
+}

+ 1 - 0
gramora/Utilities/WindowChromeConfigurator.swift

@@ -40,6 +40,7 @@ private struct WindowChromeAccessor: NSViewRepresentable {
             }
 
             applyChrome(to: window)
+            ApplicationMenu.synchronizeTitle()
         }
 
         private func applyChrome(to window: NSWindow) {

+ 1 - 1
gramora/Views/Components/AppLogoMark.swift

@@ -9,6 +9,6 @@ struct AppLogoMark: View {
             .interpolation(.high)
             .scaledToFit()
             .frame(width: size, height: size)
-            .accessibilityLabel("Gramora")
+            .accessibilityLabel(AppBrand.shortName)
     }
 }

+ 1 - 1
gramora/Views/Components/PremiumCardView.swift

@@ -13,7 +13,7 @@ struct PremiumCardView: View {
                     .font(.system(size: 14))
                     .foregroundStyle(Color(red: 0.95, green: 0.75, blue: 0.20))
 
-                Text(isPremium ? "Gramora Pro" : "Unlock Premium")
+                Text(isPremium ? AppBrand.premiumName : "Unlock Premium")
                     .font(.system(size: 13, weight: .semibold))
                     .foregroundStyle(AppTheme.textPrimary)
             }

+ 2 - 2
gramora/Views/MainView.swift

@@ -79,7 +79,7 @@ struct MainView: View {
         .onAppear {
             appRating.updatePremiumStatus(subscriptions.hasPremiumAccess)
         }
-        .alert("Enjoying Gramora?", isPresented: Binding(
+        .alert("Enjoying \(AppBrand.shortName)?", isPresented: Binding(
             get: { appRating.showRatingPrompt },
             set: { isPresented in
                 if !isPresented, appRating.showRatingPrompt {
@@ -94,7 +94,7 @@ struct MainView: View {
                 appRating.userDeclinedRating()
             }
         } message: {
-            Text("Would you like to rate Gramora on the App Store? Your feedback helps us improve.")
+            Text("Would you like to rate \(AppBrand.name) on the App Store? Your feedback helps us improve.")
         }
     }
 

+ 2 - 1
gramora/Views/SidebarView.swift

@@ -50,9 +50,10 @@ struct SidebarView: View {
         HStack(spacing: 10) {
             AppLogoMark()
 
-            Text("Gramora")
+            Text(AppBrand.shortName)
                 .font(.system(size: 19, weight: .bold))
                 .foregroundStyle(AppTheme.textPrimary)
+                .accessibilityLabel(AppBrand.name)
         }
     }
 }