diff --git a/WorkbenchReplacement.xcodeproj/project.pbxproj b/DBSyn.xcodeproj/project.pbxproj similarity index 76% rename from WorkbenchReplacement.xcodeproj/project.pbxproj rename to DBSyn.xcodeproj/project.pbxproj index 4df0f0e..f02b8ca 100644 --- a/WorkbenchReplacement.xcodeproj/project.pbxproj +++ b/DBSyn.xcodeproj/project.pbxproj @@ -12,19 +12,19 @@ 000000000000000000000015 /* DatabaseModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 000000000000000000000012 /* DatabaseModel.swift */; }; 000000000000000000000017 /* MySQLProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 000000000000000000000016 /* MySQLProtocol.swift */; }; - A10000000000000000000003 /* WorkbenchReplacement.icns in Resources */ = {isa = PBXBuildFile; fileRef = A10000000000000000000001 /* WorkbenchReplacement.icns */; }; - A10000000000000000000004 /* WorkbenchBrand.png in Resources */ = {isa = PBXBuildFile; fileRef = A10000000000000000000002 /* WorkbenchBrand.png */; }; + A10000000000000000000003 /* DBSyn.icns in Resources */ = {isa = PBXBuildFile; fileRef = A10000000000000000000001 /* DBSyn.icns */; }; + A10000000000000000000004 /* DBSynBrand.png in Resources */ = {isa = PBXBuildFile; fileRef = A10000000000000000000002 /* DBSynBrand.png */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 00000000000000000000000F /* WorkbenchReplacement.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = WorkbenchReplacement.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 00000000000000000000000F /* DBSyn.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DBSyn.app; sourceTree = BUILT_PRODUCTS_DIR; }; 000000000000000000000010 /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = ""; }; 000000000000000000000011 /* MainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainView.swift; sourceTree = ""; }; 000000000000000000000012 /* DatabaseModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseModel.swift; sourceTree = ""; }; 000000000000000000000016 /* MySQLProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MySQLProtocol.swift; sourceTree = ""; }; - A10000000000000000000001 /* WorkbenchReplacement.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = WorkbenchReplacement.icns; sourceTree = ""; }; - A10000000000000000000002 /* WorkbenchBrand.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = WorkbenchBrand.png; sourceTree = ""; }; + A10000000000000000000001 /* DBSyn.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = DBSyn.icns; sourceTree = ""; }; + A10000000000000000000002 /* DBSynBrand.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = DBSynBrand.png; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -41,12 +41,12 @@ 000000000000000000000002 = { isa = PBXGroup; children = ( - 000000000000000000000003 /* WorkbenchReplacement */, + 000000000000000000000003 /* DBSyn */, 000000000000000000000004 /* Products */, ); sourceTree = ""; }; - 000000000000000000000003 /* WorkbenchReplacement */ = { + 000000000000000000000003 /* DBSyn */ = { isa = PBXGroup; children = ( 000000000000000000000010 /* App.swift */, @@ -55,13 +55,13 @@ 000000000000000000000016 /* MySQLProtocol.swift */, A10000000000000000000005 /* Resources */,); - path = WorkbenchReplacement; + path = DBSyn; sourceTree = ""; }; 000000000000000000000004 /* Products */ = { isa = PBXGroup; children = ( - 00000000000000000000000F /* WorkbenchReplacement.app */, + 00000000000000000000000F /* DBSyn.app */, ); name = Products; sourceTree = ""; @@ -70,8 +70,8 @@ A10000000000000000000005 /* Resources */ = { isa = PBXGroup; children = ( - A10000000000000000000001 /* WorkbenchReplacement.icns */, - A10000000000000000000002 /* WorkbenchBrand.png */, + A10000000000000000000001 /* DBSyn.icns */, + A10000000000000000000002 /* DBSynBrand.png */, ); path = Resources; sourceTree = ""; @@ -79,9 +79,9 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - 000000000000000000000005 /* WorkbenchReplacement */ = { + 000000000000000000000005 /* DBSyn */ = { isa = PBXNativeTarget; - buildConfigurationList = 00000000000000000000000A /* Build configuration list for PBXNativeTarget "WorkbenchReplacement" */; + buildConfigurationList = 00000000000000000000000A /* Build configuration list for PBXNativeTarget "DBSyn" */; buildPhases = ( 000000000000000000000006 /* Sources */, 000000000000000000000008 /* Frameworks */, @@ -91,9 +91,9 @@ ); dependencies = ( ); - name = WorkbenchReplacement; - productName = WorkbenchReplacement; - productReference = 00000000000000000000000F /* WorkbenchReplacement.app */; + name = DBSyn; + productName = DBSyn; + productReference = 00000000000000000000000F /* DBSyn.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ @@ -109,7 +109,7 @@ }; }; }; - buildConfigurationList = 000000000000000000000009 /* Build configuration list for PBXProject "WorkbenchReplacement" */; + buildConfigurationList = 000000000000000000000009 /* Build configuration list for PBXProject "DBSyn" */; compatibilityVersion = "Xcode 14.0"; developmentRegion = en; hasScannedForEncodings = 0; @@ -122,7 +122,7 @@ projectDirPath = ""; projectRoot = ""; targets = ( - 000000000000000000000005 /* WorkbenchReplacement */, + 000000000000000000000005 /* DBSyn */, ); }; /* End PBXProject section */ @@ -133,8 +133,8 @@ buildActionMask = 2147483647; files = ( - A10000000000000000000003 /* WorkbenchReplacement.icns in Resources */, - A10000000000000000000004 /* WorkbenchBrand.png in Resources */,); + A10000000000000000000003 /* DBSyn.icns in Resources */, + A10000000000000000000004 /* DBSynBrand.png in Resources */,); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ @@ -184,10 +184,10 @@ DEVELOPMENT_TEAM = 39R6U3437D; ENABLE_APP_SANDBOX = NO; GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_KEY_CFBundleDisplayName = "Workbench Replacement"; - INFOPLIST_KEY_CFBundleIconFile = WorkbenchReplacement; + INFOPLIST_KEY_CFBundleDisplayName = "DBSyn"; + INFOPLIST_KEY_CFBundleIconFile = DBSyn; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.developer-tools"; - PRODUCT_BUNDLE_IDENTIFIER = net.absdev.WorkbenchReplacement; + PRODUCT_BUNDLE_IDENTIFIER = net.absdev.DBSyn; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; @@ -202,10 +202,10 @@ DEVELOPMENT_TEAM = 39R6U3437D; ENABLE_APP_SANDBOX = NO; GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_KEY_CFBundleDisplayName = "Workbench Replacement"; - INFOPLIST_KEY_CFBundleIconFile = WorkbenchReplacement; + INFOPLIST_KEY_CFBundleDisplayName = "DBSyn"; + INFOPLIST_KEY_CFBundleIconFile = DBSyn; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.developer-tools"; - PRODUCT_BUNDLE_IDENTIFIER = net.absdev.WorkbenchReplacement; + PRODUCT_BUNDLE_IDENTIFIER = net.absdev.DBSyn; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; @@ -215,7 +215,7 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 000000000000000000000009 /* Build configuration list for PBXProject "WorkbenchReplacement" */ = { + 000000000000000000000009 /* Build configuration list for PBXProject "DBSyn" */ = { isa = XCConfigurationList; buildConfigurations = ( 00000000000000000000000B /* Debug */, @@ -224,7 +224,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 00000000000000000000000A /* Build configuration list for PBXNativeTarget "WorkbenchReplacement" */ = { + 00000000000000000000000A /* Build configuration list for PBXNativeTarget "DBSyn" */ = { isa = XCConfigurationList; buildConfigurations = ( 00000000000000000000000D /* Debug */, diff --git a/WorkbenchReplacement/App.swift b/DBSyn/App.swift similarity index 93% rename from WorkbenchReplacement/App.swift rename to DBSyn/App.swift index 7066cd1..1c7edef 100644 --- a/WorkbenchReplacement/App.swift +++ b/DBSyn/App.swift @@ -2,18 +2,18 @@ import SwiftUI import AppKit extension Notification.Name { - static let workbenchRevealSQLEditor = Notification.Name("WorkbenchReplacement.RevealSQLEditor") + static let workbenchRevealSQLEditor = Notification.Name("DBSyn.RevealSQLEditor") } @main -struct WorkbenchReplacementApp: App { +struct DBSynApp: App { @StateObject private var model = DatabaseModel() var body: some Scene { - WindowGroup("Workbench Replacement") { + WindowGroup("DBSyn") { WorkbenchLaunchView() .onAppear { - if let iconURL = Bundle.main.url(forResource: "WorkbenchReplacement", withExtension: "icns"), + if let iconURL = Bundle.main.url(forResource: "DBSyn", withExtension: "icns"), let icon = NSImage(contentsOf: iconURL) { NSApplication.shared.applicationIconImage = icon } @@ -24,6 +24,17 @@ struct WorkbenchReplacementApp: App { .defaultSize(width: 1200, height: 800) .windowResizability(.contentSize) .commands { + CommandGroup(replacing: .appInfo) { + Button("About DBSyn") { + let icon = NSImage(contentsOfFile: Bundle.main.path(forResource: "DBSynBrand", ofType: "png") ?? "") + NSApplication.shared.orderFrontStandardAboutPanel(options: [ + .applicationName: "DBSyn", + .applicationIcon: icon ?? NSApplication.shared.applicationIconImage, + .version: "Phase 59.2", + .credits: NSAttributedString(string: "Native MySQL client for macOS") + ]) + } + } WorkbenchFileCommands(model: model) } @@ -343,7 +354,7 @@ struct WorkbenchSplashView: View { Spacer() if let path = Bundle.main.path( - forResource: "WorkbenchBrand", + forResource: "DBSynBrand", ofType: "png" ), let image = NSImage(contentsOfFile: path) { Image(nsImage: image) @@ -352,7 +363,7 @@ struct WorkbenchSplashView: View { .frame(width: 160, height: 160) } - Text("Workbench Replacement") + Text("DBSyn") .font(.system(size: 30, weight: .bold)) Text("Modern MySQL Client for macOS") @@ -372,7 +383,7 @@ struct WorkbenchSplashView: View { ProgressView() .frame(width: 260) - Text("Starting Workbench Replacement…") + Text("Starting DBSyn…") .font(.caption) .foregroundStyle(.secondary) .padding(.bottom, 30) diff --git a/WorkbenchReplacement/DatabaseModel.swift b/DBSyn/DatabaseModel.swift similarity index 100% rename from WorkbenchReplacement/DatabaseModel.swift rename to DBSyn/DatabaseModel.swift diff --git a/WorkbenchReplacement/MainView.swift b/DBSyn/MainView.swift similarity index 99% rename from WorkbenchReplacement/MainView.swift rename to DBSyn/MainView.swift index ae52ac4..974e3bf 100644 --- a/WorkbenchReplacement/MainView.swift +++ b/DBSyn/MainView.swift @@ -175,7 +175,7 @@ struct MainView: View { private var mainToolbar: some View { HStack(spacing: 16) { - Image(nsImage: NSImage(named: "WorkbenchBrand") ?? NSImage(contentsOfFile: Bundle.main.path(forResource: "WorkbenchBrand", ofType: "png") ?? "") ?? NSImage()) + Image(nsImage: NSImage(named: "DBSynBrand") ?? NSImage(contentsOfFile: Bundle.main.path(forResource: "DBSynBrand", ofType: "png") ?? "") ?? NSImage()) .resizable() .scaledToFit() .frame(width: 30, height: 30) @@ -3463,7 +3463,7 @@ struct WorkbenchDatabaseTransferView: View { func write(_ value: String) throws { try handle?.write(contentsOf: Data(value.utf8)) } - try write("-- WorkbenchReplacement native export\n-- Database: \(database)\n-- Generated: \(Date())\nSET NAMES utf8mb4;\n\n") + try write("-- DBSyn native export\n-- Database: \(database)\n-- Generated: \(Date())\nSET NAMES utf8mb4;\n\n") let db = quoteIdentifier(database) for (index, table) in tables.enumerated() { try Task.checkCancellation() diff --git a/WorkbenchReplacement/MySQLProtocol.swift b/DBSyn/MySQLProtocol.swift similarity index 99% rename from WorkbenchReplacement/MySQLProtocol.swift rename to DBSyn/MySQLProtocol.swift index 1c38113..ab7fdc9 100644 --- a/WorkbenchReplacement/MySQLProtocol.swift +++ b/DBSyn/MySQLProtocol.swift @@ -358,7 +358,7 @@ private final class PersistentMySQLSessions { let connection: MySQLWireConnection } - private let queue = DispatchQueue(label: "WorkbenchReplacement.MySQLSessions") + private let queue = DispatchQueue(label: "DBSyn.MySQLSessions") private var connections: [UUID: Entry] = [:] func execute(profile: ConnectionProfile, database: String, diff --git a/WorkbenchReplacement/Resources/WorkbenchReplacement.icns b/DBSyn/Resources/DBSyn.icns similarity index 100% rename from WorkbenchReplacement/Resources/WorkbenchReplacement.icns rename to DBSyn/Resources/DBSyn.icns diff --git a/WorkbenchReplacement/Resources/WorkbenchBrand.png b/DBSyn/Resources/DBSynBrand.png similarity index 100% rename from WorkbenchReplacement/Resources/WorkbenchBrand.png rename to DBSyn/Resources/DBSynBrand.png diff --git a/docs/PHASE59-2-DBSYN-REBRAND.md b/docs/PHASE59-2-DBSYN-REBRAND.md new file mode 100644 index 0000000..981b597 --- /dev/null +++ b/docs/PHASE59-2-DBSYN-REBRAND.md @@ -0,0 +1,10 @@ +# Phase 59.2 — DBSyn rebrand + +- Renamed Xcode project, app target, product, source directory, icon resource, image resource and release script to DBSyn. +- Updated bundle display name and identifier to `net.absdev.DBSyn`. +- Replaced the default About menu with an explicit About DBSyn action and branded About panel. +- Preserved original icon artwork (now `DBSyn.icns` and `DBSynBrand.png`). +- Kept six legacy UserDefaults/Keychain service identifiers intentionally to preserve previously saved connections, SQL history, scripts, credentials and snapshots. These are internal compatibility keys, not displayed branding. +- Xcode project needs to be opened using `DBSyn.xcodeproj`; old project path no longer exists. +- Because the bundle identifier changes, existing macOS Keychain access may require credentials to be re-entered depending on code-signing identity. +- Swift parser verified on all four Swift files; Xcode build requires macOS. diff --git a/scripts/release-dbsyn.sh b/scripts/release-dbsyn.sh new file mode 100755 index 0000000..e2c4641 --- /dev/null +++ b/scripts/release-dbsyn.sh @@ -0,0 +1,17 @@ +#!/bin/bash +set -euo pipefail +ROOT="$(cd "$(dirname "$0")/.." && pwd)" +PHASE="${1:?Usage: release-dbsyn.sh PHASE NAME}" +NAME="${2:?Usage: release-dbsyn.sh PHASE NAME}" +cd "$ROOT" +mkdir -p releases +xcodebuild -project DBSyn.xcodeproj -scheme DBSyn -configuration Release -destination 'platform=macOS' -derivedDataPath "$ROOT/build" clean build +APP="$ROOT/build/Build/Products/Release/DBSyn.app" +test -d "$APP" +SOURCE="DBSyn-Phase${PHASE}-${NAME}-Source.zip" +BINARY="DBSyn-Phase${PHASE}-${NAME}-App-Unsigned.zip" +/usr/bin/zip -qr "releases/$SOURCE" DBSyn DBSyn.xcodeproj docs scripts -x '*.DS_Store' +(cd "$ROOT/build/Build/Products/Release" && /usr/bin/zip -qr "$ROOT/releases/$BINARY" DBSyn.app) +/usr/bin/unzip -tq "releases/$SOURCE" >/dev/null +/usr/bin/unzip -tq "releases/$BINARY" >/dev/null +printf 'Created:\n %s\n %s\n' "releases/$SOURCE" "releases/$BINARY"