Restore recent accounts and return from native browser sign-in
Reviewed by GPT-6 Astra. Add saved account switching, app URL handlers, and domain-based Store bundle identifiers. Both Mac and iOS signed build 4 archives and exports verified under Team Tito. Sheets uses native thumbnail rows, a More menu, and bottom search and creation controls.
13 files changed,
+298
−112
native/apple/Package.resolved+14 −14native/apple/Package.swift+2 −2native/apple/Sources/SheetsApp/SheetsAccountWindow.swift+23 −0native/apple/Sources/SheetsApp/SheetsApp.swift+1 −14native/apple/Sources/SheetsKit/SheetThumbnail.swift+47 −0native/apple/Sources/SheetsKit/SheetWire.swift+1 −0native/apple/Sources/SheetsKit/SheetsWorkspace.swift+84 −30native/ios/Info.plist+35 −0native/ios/UITests/NativeUITests.swift+3 −3native/ios/project.yml+45 −31native/macos/Info.plist+13 −0native/macos/SheetsMacStore.xcodeproj/project.pbxproj+9 −3native/macos/project.yml+21 −15
CI passed — run details
diff --git a/native/apple/Package.resolved b/native/apple/Package.resolved| index 2a9b2ab..409646d 100644 |
| --- a/native/apple/Package.resolved |
| +++ b/native/apple/Package.resolved |
| @@ -1,23 +1,23 @@ |
| { |
| - "originHash": "9d29c6ae8f4af5dee8048418fbb2bcf1e7b93e8e5686925de1e91eaeb45ea50b", |
| - "pins": [ |
| + "originHash" : "13a00072049b15231376e022de38fd86d188294f4d9d77e737067588243a631c", |
| + "pins" : [ |
| { |
| - "identity": "native", |
| - "kind": "remoteSourceControl", |
| - "location": "https://amadan.net/rastrillo/native", |
| - "state": { |
| - "revision": "4c61d6283a188c95647e1d0e609e69d29c2e7fa1" |
| + "identity" : "native", |
| + "kind" : "remoteSourceControl", |
| + "location" : "https://amadan.net/rastrillo/native", |
| + "state" : { |
| + "revision" : "229525909e1d6ac3b6a353d1c4d022798b0e9a24" |
| } |
| }, |
| { |
| - "identity": "sparkle", |
| - "kind": "remoteSourceControl", |
| - "location": "https://github.com/sparkle-project/Sparkle", |
| - "state": { |
| - "revision": "ac2def288cbff5cfc7df3ffef6abdf45b72bcb0a", |
| - "version": "2.9.6" |
| + "identity" : "sparkle", |
| + "kind" : "remoteSourceControl", |
| + "location" : "https://github.com/sparkle-project/Sparkle", |
| + "state" : { |
| + "revision" : "ac2def288cbff5cfc7df3ffef6abdf45b72bcb0a", |
| + "version" : "2.9.6" |
| } |
| } |
| ], |
| - "version": 3 |
| + "version" : 3 |
| } |
diff --git a/native/apple/Package.swift b/native/apple/Package.swift| index a50e12d..adb01bd 100644 |
| --- a/native/apple/Package.swift |
| +++ b/native/apple/Package.swift |
| @@ -2,8 +2,8 @@ |
| import PackageDescription |
| import Foundation |
| -let sharedNative: Package.Dependency = ProcessInfo.processInfo.environment["OFICINA_NATIVE_PACKAGE_PATH"].map { .package(path: $0) } |
| - ?? .package(url: "https://amadan.net/rastrillo/native", revision: "4c61d6283a188c95647e1d0e609e69d29c2e7fa1") |
| +let sharedNative: Package.Dependency = ProcessInfo.processInfo.environment["OFICINA_NATIVE_PACKAGE_PATH"].map { .package(name: "native", path: $0) } |
| + ?? .package(url: "https://amadan.net/rastrillo/native", revision: "229525909e1d6ac3b6a353d1c4d022798b0e9a24") |
| let package = Package(name: "SheetsNative", platforms: [.macOS(.v26), .iOS(.v26)], |
| products: [.library(name:"SheetsKit",targets:["SheetsKit"]), .executable(name:"SheetsMac",targets:["SheetsMac"]), .executable(name:"SheetsReview",targets:["SheetsReview"])], |
diff --git a/native/apple/Sources/SheetsApp/SheetsAccountWindow.swift b/native/apple/Sources/SheetsApp/SheetsAccountWindow.swift| new file mode 100644 |
| index 0000000..ce074cb |
| --- /dev/null |
| +++ b/native/apple/Sources/SheetsApp/SheetsAccountWindow.swift |
| @@ -0,0 +1,23 @@ |
| +import RastrilloApple |
| +import SheetsKit |
| +import SwiftUI |
| + |
| +/// Each window owns its navigation and model lifetime. Switching an account in |
| +/// one window must never discard another window's unconfirmed edits. |
| +struct SheetsAccountWindow: View { |
| + @StateObject private var connection = NativeConnection(defaultServer: "https://sheets.oficina.works") |
| + var body: some View { |
| + Group { |
| + if let client = connection.client { |
| + SheetsWorkspace(client: client, accounts: connection.showAccounts, signOut: connection.signOut) |
| + .id(connection.activeAccountID) |
| + } else { |
| + NativeAccountsView("Oficina Sheets", systemImage: "tablecells", connection: connection) |
| + } |
| + }.onOpenURL(perform: connection.handleOpenURL) |
| + .tint(.green) |
| + #if os(macOS) |
| + .frame(minWidth: 760, minHeight: 600) |
| + #endif |
| + } |
| +} |
diff --git a/native/apple/Sources/SheetsApp/SheetsApp.swift b/native/apple/Sources/SheetsApp/SheetsApp.swift| index 96628e4..5a3f64f 100644 |
| --- a/native/apple/Sources/SheetsApp/SheetsApp.swift |
| +++ b/native/apple/Sources/SheetsApp/SheetsApp.swift |
| @@ -12,21 +12,8 @@ import SwiftUI |
| #if os(macOS) |
| @NSApplicationDelegateAdaptor(SheetsApplicationDelegate.self) private var appDelegate |
| #endif |
| - @StateObject private var connection = NativeConnection( |
| - defaultServer: "https://sheets.oficina.works") |
| var body: some Scene { |
| - WindowGroup { |
| - Group { |
| - if let client = connection.client { |
| - SheetsWorkspace(client: client, signOut: connection.signOut) |
| - } else { |
| - NativeSignInView("Oficina Sheets", systemImage: "tablecells", connection: connection) |
| - } |
| - }.tint(.green) |
| - #if os(macOS) |
| - .frame(minWidth: 760, minHeight: 600) |
| - #endif |
| - } |
| + WindowGroup { SheetsAccountWindow() } |
| #if os(macOS) |
| #if canImport(RastrilloMacUpdates) |
| .commands { NativeUpdateCommands(updater: updater) } |
diff --git a/native/apple/Sources/SheetsKit/SheetThumbnail.swift b/native/apple/Sources/SheetsKit/SheetThumbnail.swift| new file mode 100644 |
| index 0000000..d3328dc |
| --- /dev/null |
| +++ b/native/apple/Sources/SheetsKit/SheetThumbnail.swift |
| @@ -0,0 +1,47 @@ |
| +import SwiftUI |
| + |
| +struct SheetPreview: Decodable, Hashable, Sendable { |
| + let Rows: Int |
| + let Cols: Int |
| + let Empty: Bool |
| + let Cells: [SheetPreviewCell]? |
| +} |
| +struct SheetPreviewCell: Decodable, Hashable, Sendable { |
| + let R: Int |
| + let C: Int |
| + let Fill: String |
| + let Bold: Bool |
| +} |
| + |
| +/// Renders shape metadata only: no cell text, web view, or external image fetch. |
| +struct SheetThumbnail: View { |
| + private let preview: SheetPreview? |
| + init(_ preview: SheetPreview?) { self.preview = preview } |
| + |
| + var body: some View { |
| + Canvas { context, size in |
| + let border = Path(roundedRect: CGRect(origin: .zero, size: size).insetBy(dx: 0.5, dy: 0.5), cornerRadius: 3) |
| + context.fill(border, with: .color(.primary.opacity(0.025))) |
| + context.stroke(border, with: .color(.secondary.opacity(0.3)), lineWidth: 1) |
| + guard let preview, !preview.Empty, (1...12).contains(preview.Rows), |
| + (1...8).contains(preview.Cols) else { return } |
| + let width = (size.width - 8) / Double(preview.Cols) |
| + let height = (size.height - 8) / Double(preview.Rows) |
| + for cell in (preview.Cells ?? []).prefix(96) { |
| + guard (0..<preview.Rows).contains(cell.R), (0..<preview.Cols).contains(cell.C) else { continue } |
| + let rect = CGRect(x: 4 + Double(cell.C) * width, y: 4 + Double(cell.R) * height, width: width, height: height) |
| + if !cell.Fill.isEmpty { |
| + let fill = cell.Fill |
| + let isHex = fill.count == 7 && fill.hasPrefix("#") && UInt64(fill.dropFirst(), radix: 16) != nil |
| + context.fill(Path(rect), with: .color(isHex ? Color(hex: fill) : .accentColor.opacity(0.15))) |
| + } |
| + let mark = CGRect(x: rect.minX + width * 0.15, y: rect.minY + height * 0.35, |
| + width: width * 0.7, height: height * 0.3) |
| + context.fill(Path(roundedRect: mark, cornerRadius: 0.5), |
| + with: .color(.secondary.opacity(cell.Bold ? 0.8 : 0.4))) |
| + } |
| + } |
| + .frame(width: 52, height: 68) |
| + .accessibilityHidden(true) |
| + } |
| +} |
diff --git a/native/apple/Sources/SheetsKit/SheetWire.swift b/native/apple/Sources/SheetsKit/SheetWire.swift| index fc56d43..a7b6c3b 100644 |
| --- a/native/apple/Sources/SheetsKit/SheetWire.swift |
| +++ b/native/apple/Sources/SheetsKit/SheetWire.swift |
| @@ -5,6 +5,7 @@ struct SheetSummary: Decodable, Identifiable, Hashable, Sendable { |
| let Title: String |
| let TabID: UInt64 |
| let TabName: String |
| + var Preview: SheetPreview? = nil |
| var id: UInt64 { self.ID } |
| } |
| struct SheetList: Decodable { let Sheets: [SheetSummary]? } |
diff --git a/native/apple/Sources/SheetsKit/SheetsWorkspace.swift b/native/apple/Sources/SheetsKit/SheetsWorkspace.swift| index dabc154..c894bad 100644 |
| --- a/native/apple/Sources/SheetsKit/SheetsWorkspace.swift |
| +++ b/native/apple/Sources/SheetsKit/SheetsWorkspace.swift |
| @@ -9,47 +9,22 @@ import SwiftUI |
| var id: String { name } |
| } |
| @State private var panel: Panel? |
| - @State private var title = "" |
| + @State private var query = "" |
| @State private var pendingSheet: SheetSummary? |
| @State private var askDiscard = false |
| @FocusState private var formulaFocused: Bool |
| @Environment(\.scenePhase) private var scenePhase |
| @AppStorage("sheets.appearance") private var appearance = "auto" |
| private let signOut: () -> Void |
| - public init(client: NativeHTTP, signOut: @escaping () -> Void) { |
| + private let accounts: (() -> Void)? |
| + public init(client: NativeHTTP, accounts: (() -> Void)? = nil, signOut: @escaping () -> Void) { |
| _model = State(initialValue: SheetModel(client: client)) |
| self.signOut = signOut |
| + self.accounts = accounts |
| } |
| public var body: some View { |
| NavigationSplitView(preferredCompactColumn: $column) { |
| - List { |
| - ForEach(model.sheets) { sheet in |
| - Button(sheet.Title) { |
| - if model.hasUnconfirmedChanges { |
| - pendingSheet = sheet |
| - askDiscard = true |
| - } else { |
| - Task { await model.open(sheet) } |
| - } |
| - }.disabled(model.busy) |
| - } |
| - Button("New sheet", systemImage: "plus") { Task { await model.create() } }.disabled( |
| - model.hasUnconfirmedChanges || model.busy) |
| - Button("Import workbook", systemImage: "square.and.arrow.down") { show("Import") }.disabled( |
| - model.hasUnconfirmedChanges || model.busy) |
| - Picker("Appearance", selection: $appearance) { |
| - Text("System").tag("auto") |
| - Text("Light").tag("light") |
| - Text("Dark").tag("dark") |
| - } |
| - Button("Sign out") { |
| - if !model.hasUnconfirmedChanges && !model.busy { |
| - signOut() |
| - } else { |
| - model.error = "Save or discard your cell edit before signing out." |
| - } |
| - } |
| - }.navigationTitle("Sheets") |
| + library |
| } detail: { |
| if model.page != nil { |
| editor |
| @@ -87,6 +62,85 @@ import SwiftUI |
| Button("Cancel", role: .cancel) { pendingSheet = nil } |
| } |
| } |
| + private var filteredSheets: [SheetSummary] { |
| + query.isEmpty ? model.sheets : model.sheets.filter { $0.Title.localizedStandardContains(query) } |
| + } |
| + private var library: some View { |
| + List { |
| + if !model.error.isEmpty { |
| + Label(model.error, systemImage: "exclamationmark.circle").foregroundStyle(.red) |
| + } |
| + ForEach(filteredSheets) { sheet in |
| + Button { |
| + if model.hasUnconfirmedChanges { |
| + pendingSheet = sheet |
| + askDiscard = true |
| + } else { Task { await model.open(sheet) } } |
| + } label: { |
| + HStack(spacing: 16) { |
| + SheetThumbnail(sheet.Preview) |
| + VStack(alignment: .leading, spacing: 4) { |
| + Text(verbatim: sheet.Title).font(.headline).foregroundStyle(.primary) |
| + Text(verbatim: sheet.TabName).font(.subheadline).foregroundStyle(.secondary) |
| + } |
| + Spacer(minLength: 0) |
| + Image(systemName: "chevron.right").font(.caption.bold()).foregroundStyle(.tertiary) |
| + }.padding(.vertical, 6) |
| + }.disabled(model.busy).accessibilityElement(children: .combine) |
| + .accessibilityLabel(sheet.Title).accessibilityValue(sheet.TabName) |
| + } |
| + } |
| + .listStyle(.plain) |
| + .overlay { |
| + if model.sheets.isEmpty && model.error.isEmpty { |
| + ContentUnavailableView("No spreadsheets", systemImage: "tablecells", |
| + description: Text("Create a spreadsheet or import a workbook.")) |
| + } else if filteredSheets.isEmpty && !query.isEmpty { |
| + ContentUnavailableView.search(text: query) |
| + } |
| + } |
| + .navigationTitle("Sheets") |
| + .searchable(text: $query, prompt: "Search spreadsheets") |
| + .refreshable { await model.loadList() } |
| + .toolbar { |
| + if let accounts { |
| + ToolbarItem(placement: .navigation) { |
| + Button("Accounts", systemImage: "chevron.backward", action: accounts) |
| + .disabled(model.hasUnconfirmedChanges || model.busy) |
| + } |
| + } |
| + ToolbarItem(placement: .primaryAction) { |
| + Menu { |
| + Button("Import", systemImage: "square.and.arrow.down") { show("Import") } |
| + .disabled(model.hasUnconfirmedChanges || model.busy) |
| + Picker("Appearance", selection: $appearance) { |
| + Text("System").tag("auto") |
| + Text("Light").tag("light") |
| + Text("Dark").tag("dark") |
| + } |
| + Button("Sign out", systemImage: "rectangle.portrait.and.arrow.right", role: .destructive, |
| + action: signOut).disabled(model.hasUnconfirmedChanges || model.busy) |
| + } label: { |
| + VStack(spacing: 3) { |
| + Circle().frame(width: 3, height: 3) |
| + Circle().frame(width: 3, height: 3) |
| + Circle().frame(width: 3, height: 3) |
| + }.frame(width: 20, height: 20) |
| + }.accessibilityLabel("More") |
| + } |
| + #if os(iOS) |
| + DefaultToolbarItem(kind: .search, placement: .bottomBar) |
| + ToolbarSpacer(.flexible, placement: .bottomBar) |
| + ToolbarItem(placement: .bottomBar) { newSheet } |
| + #else |
| + ToolbarItem { newSheet } |
| + #endif |
| + } |
| + } |
| + private var newSheet: some View { |
| + Button("New spreadsheet", systemImage: "plus") { Task { await model.create() } } |
| + .disabled(model.hasUnconfirmedChanges || model.busy) |
| + } |
| private func show(_ name: String) { |
| panel = Panel(name: name) |
| } |
diff --git a/native/ios/Info.plist b/native/ios/Info.plist| new file mode 100644 |
| index 0000000..87efa57 |
| --- /dev/null |
| +++ b/native/ios/Info.plist |
| @@ -0,0 +1,35 @@ |
| +<?xml version="1.0" encoding="UTF-8"?> |
| +<!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>CFBundleName</key> |
| + <string>$(PRODUCT_NAME)</string> |
| + <key>CFBundlePackageType</key> |
| + <string>APPL</string> |
| + <key>CFBundleShortVersionString</key> |
| + <string>$(MARKETING_VERSION)</string> |
| + <key>CFBundleURLTypes</key> |
| + <array> |
| + <dict> |
| + <key>CFBundleTypeRole</key> |
| + <string>Editor</string> |
| + <key>CFBundleURLName</key> |
| + <string>works.oficina.sheets.signin</string> |
| + <key>CFBundleURLSchemes</key> |
| + <array> |
| + <string>works.oficina.sheets</string> |
| + </array> |
| + </dict> |
| + </array> |
| + <key>CFBundleVersion</key> |
| + <string>$(CURRENT_PROJECT_VERSION)</string> |
| +</dict> |
| +</plist> |
diff --git a/native/ios/UITests/NativeUITests.swift b/native/ios/UITests/NativeUITests.swift| index 6235cd3..9c1bfb6 100644 |
| --- a/native/ios/UITests/NativeUITests.swift |
| +++ b/native/ios/UITests/NativeUITests.swift |
| @@ -6,7 +6,7 @@ import XCTest |
| let app = XCUIApplication() |
| app.launch() |
| defer { app.terminate() } |
| - let create = app.buttons["New sheet"] |
| + let create = app.buttons["New spreadsheet"] |
| XCTAssertTrue(create.waitForExistence(timeout: 15)) |
| create.tap() |
| let formula = app.textFields["Cell contents or formula"] |
| @@ -78,8 +78,8 @@ import XCTest |
| let app = XCUIApplication() |
| app.launch() |
| defer { app.terminate() } |
| - XCTAssertTrue(app.buttons["New sheet"].waitForExistence(timeout: 15)) |
| - app.buttons["New sheet"].tap() |
| + XCTAssertTrue(app.buttons["New spreadsheet"].waitForExistence(timeout: 15)) |
| + app.buttons["New spreadsheet"].tap() |
| let formula = app.textFields["Cell contents or formula"] |
| XCTAssertTrue(formula.waitForExistence(timeout: 10)) |
| formula.tap() |
diff --git a/native/ios/project.yml b/native/ios/project.yml| index 3c993f6..cf4b8ca 100644 |
| --- a/native/ios/project.yml |
| +++ b/native/ios/project.yml |
| @@ -8,64 +8,77 @@ packages: |
| path: ../apple |
| RastrilloNative: |
| url: https://amadan.net/rastrillo/native |
| - revision: 4c61d6283a188c95647e1d0e609e69d29c2e7fa1 |
| + revision: 229525909e1d6ac3b6a353d1c4d022798b0e9a24 |
| settings: |
| base: |
| SWIFT_VERSION: '6.0' |
| CODE_SIGN_STYLE: Automatic |
| - MARKETING_VERSION: '0.1.0' |
| + MARKETING_VERSION: 0.1.0 |
| CURRENT_PROJECT_VERSION: '1' |
| targets: |
| SheetsPhone: |
| type: application |
| platform: iOS |
| sources: |
| - - ../apple/Sources/SheetsApp |
| - - Assets.xcassets |
| - - path: ../LICENSE.lucide |
| - buildPhase: resources |
| - - path: ../PrivacyInfo.xcprivacy |
| - buildPhase: resources |
| + - ../apple/Sources/SheetsApp |
| + - Assets.xcassets |
| + - path: ../LICENSE.lucide |
| + buildPhase: resources |
| + - path: ../PrivacyInfo.xcprivacy |
| + buildPhase: resources |
| dependencies: |
| - - package: SheetsNative |
| - product: SheetsKit |
| - - package: RastrilloNative |
| - product: RastrilloApple |
| + - package: SheetsNative |
| + product: SheetsKit |
| + - package: RastrilloNative |
| + product: RastrilloApple |
| settings: |
| base: |
| ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon |
| - PRODUCT_BUNDLE_IDENTIFIER: net.amadan.oficina.sheets.ios |
| - TARGETED_DEVICE_FAMILY: '1,2' |
| - GENERATE_INFOPLIST_FILE: YES |
| + PROVISIONING_PROFILE_SPECIFIER: $(OFICINA_PROVISIONING_PROFILE) |
| + PRODUCT_BUNDLE_IDENTIFIER: works.oficina.sheets |
| + TARGETED_DEVICE_FAMILY: 1,2 |
| + GENERATE_INFOPLIST_FILE: true |
| INFOPLIST_KEY_CFBundleDisplayName: Oficina Sheets |
| - INFOPLIST_KEY_UILaunchScreen_Generation: YES |
| - INFOPLIST_KEY_UISupportedInterfaceOrientations: UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortraitUpsideDown |
| - |
| + INFOPLIST_KEY_UILaunchScreen_Generation: true |
| + INFOPLIST_KEY_UISupportedInterfaceOrientations: UIInterfaceOrientationPortrait |
| + UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight |
| + UIInterfaceOrientationPortraitUpsideDown |
| + info: |
| + path: Info.plist |
| + properties: |
| + CFBundleURLTypes: |
| + - CFBundleURLName: works.oficina.sheets.signin |
| + CFBundleURLSchemes: |
| + - works.oficina.sheets |
| + CFBundleTypeRole: Editor |
| + CFBundleShortVersionString: $(MARKETING_VERSION) |
| + CFBundleVersion: $(CURRENT_PROJECT_VERSION) |
| SheetsReviewPhone: |
| type: application |
| platform: iOS |
| - sources: [Review] |
| + sources: |
| + - Review |
| dependencies: |
| - - package: SheetsNative |
| - product: SheetsKit |
| - - package: RastrilloNative |
| - product: RastrilloApple |
| + - package: SheetsNative |
| + product: SheetsKit |
| + - package: RastrilloNative |
| + product: RastrilloApple |
| settings: |
| base: |
| PRODUCT_BUNDLE_IDENTIFIER: net.amadan.oficina.sheets.review |
| - TARGETED_DEVICE_FAMILY: '1,2' |
| - GENERATE_INFOPLIST_FILE: YES |
| - INFOPLIST_KEY_UILaunchScreen_Generation: YES |
| - |
| + TARGETED_DEVICE_FAMILY: 1,2 |
| + GENERATE_INFOPLIST_FILE: true |
| + INFOPLIST_KEY_UILaunchScreen_Generation: true |
| SheetsPhoneUITests: |
| type: bundle.ui-testing |
| platform: iOS |
| - sources: [UITests] |
| + sources: |
| + - UITests |
| dependencies: |
| - - target: SheetsReviewPhone |
| + - target: SheetsReviewPhone |
| settings: |
| base: |
| - GENERATE_INFOPLIST_FILE: YES |
| + GENERATE_INFOPLIST_FILE: true |
| TEST_TARGET_NAME: SheetsReviewPhone |
| schemes: |
| SheetsReviewPhone: |
| @@ -73,4 +86,5 @@ schemes: |
| targets: |
| SheetsReviewPhone: all |
| test: |
| - targets: [SheetsPhoneUITests] |
| + targets: |
| + - SheetsPhoneUITests |
diff --git a/native/macos/Info.plist b/native/macos/Info.plist| index 2cab40b..aa4219b 100644 |
| --- a/native/macos/Info.plist |
| +++ b/native/macos/Info.plist |
| @@ -20,6 +20,19 @@ |
| <string>APPL</string> |
| <key>CFBundleShortVersionString</key> |
| <string>$(MARKETING_VERSION)</string> |
| + <key>CFBundleURLTypes</key> |
| + <array> |
| + <dict> |
| + <key>CFBundleTypeRole</key> |
| + <string>Editor</string> |
| + <key>CFBundleURLName</key> |
| + <string>works.oficina.sheets.signin</string> |
| + <key>CFBundleURLSchemes</key> |
| + <array> |
| + <string>works.oficina.sheets</string> |
| + </array> |
| + </dict> |
| + </array> |
| <key>CFBundleVersion</key> |
| <string>$(CURRENT_PROJECT_VERSION)</string> |
| <key>LSApplicationCategoryType</key> |
diff --git a/native/macos/SheetsMacStore.xcodeproj/project.pbxproj b/native/macos/SheetsMacStore.xcodeproj/project.pbxproj| index 1daea87..6cfc4a7 100644 |
| --- a/native/macos/SheetsMacStore.xcodeproj/project.pbxproj |
| +++ b/native/macos/SheetsMacStore.xcodeproj/project.pbxproj |
| @@ -12,12 +12,14 @@ |
| 9C78334F6EDBA092C0D0E169 /* SheetsApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 916E654E0C8D3B86BB58C018 /* SheetsApp.swift */; }; |
| B09E36EA52DF0E19FC743C56 /* SheetsKit in Frameworks */ = {isa = PBXBuildFile; productRef = CD52B595B2129268F78A0A8A /* SheetsKit */; }; |
| C52F3F48EAE4BD0A51D2BE94 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 8AA0125DF292C29086DFC83E /* PrivacyInfo.xcprivacy */; }; |
| + CAA9732AF6C006EFA3A6EEEC /* SheetsAccountWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B6A575CBF89AE7854830BA2 /* SheetsAccountWindow.swift */; }; |
| DBF0A51B0431713C3FFB89A9 /* RastrilloApple in Frameworks */ = {isa = PBXBuildFile; productRef = 6334833E1C593E852E1F7FD4 /* RastrilloApple */; }; |
| /* End PBXBuildFile section */ |
| /* Begin PBXFileReference section */ |
| 12E225ACCFB2785464CCBCB8 /* apple */ = {isa = PBXFileReference; lastKnownFileType = folder; name = apple; path = ../apple; sourceTree = SOURCE_ROOT; }; |
| 255C08D1CA0763B1DE054572 /* SheetsMacStore.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SheetsMacStore.app; sourceTree = BUILT_PRODUCTS_DIR; }; |
| + 4B6A575CBF89AE7854830BA2 /* SheetsAccountWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SheetsAccountWindow.swift; sourceTree = "<group>"; }; |
| 54261A6D711BA4C90D042C6A /* AppIcon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = AppIcon.icns; sourceTree = "<group>"; }; |
| 5AA27588A5A207F206A0F3F6 /* LICENSE.lucide */ = {isa = PBXFileReference; path = LICENSE.lucide; sourceTree = "<group>"; }; |
| 8AA0125DF292C29086DFC83E /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; }; |
| @@ -66,6 +68,7 @@ |
| B8C7D78FF3DFFC221BBB89D3 /* SheetsApp */ = { |
| isa = PBXGroup; |
| children = ( |
| + 4B6A575CBF89AE7854830BA2 /* SheetsAccountWindow.swift */, |
| 916E654E0C8D3B86BB58C018 /* SheetsApp.swift */, |
| ); |
| name = SheetsApp; |
| @@ -162,6 +165,7 @@ |
| isa = PBXSourcesBuildPhase; |
| buildActionMask = 2147483647; |
| files = ( |
| + CAA9732AF6C006EFA3A6EEEC /* SheetsAccountWindow.swift in Sources */, |
| 9C78334F6EDBA092C0D0E169 /* SheetsApp.swift in Sources */, |
| ); |
| runOnlyForDeploymentPostprocessing = 0; |
| @@ -180,7 +184,8 @@ |
| "$(inherited)", |
| "@executable_path/../Frameworks", |
| ); |
| - PRODUCT_BUNDLE_IDENTIFIER = net.amadan.oficina.sheets; |
| + PRODUCT_BUNDLE_IDENTIFIER = works.oficina.sheets; |
| + PROVISIONING_PROFILE_SPECIFIER = "$(OFICINA_PROVISIONING_PROFILE)"; |
| SDKROOT = macosx; |
| }; |
| name = Release; |
| @@ -256,7 +261,8 @@ |
| "$(inherited)", |
| "@executable_path/../Frameworks", |
| ); |
| - PRODUCT_BUNDLE_IDENTIFIER = net.amadan.oficina.sheets; |
| + PRODUCT_BUNDLE_IDENTIFIER = works.oficina.sheets; |
| + PROVISIONING_PROFILE_SPECIFIER = "$(OFICINA_PROVISIONING_PROFILE)"; |
| SDKROOT = macosx; |
| }; |
| name = Debug; |
| @@ -364,7 +370,7 @@ |
| repositoryURL = "https://amadan.net/rastrillo/native"; |
| requirement = { |
| kind = revision; |
| - revision = 4c61d6283a188c95647e1d0e609e69d29c2e7fa1; |
| + revision = 229525909e1d6ac3b6a353d1c4d022798b0e9a24; |
| }; |
| }; |
| /* End XCRemoteSwiftPackageReference section */ |
diff --git a/native/macos/project.yml b/native/macos/project.yml| index b69d6e1..954e5bb 100644 |
| --- a/native/macos/project.yml |
| +++ b/native/macos/project.yml |
| @@ -7,31 +7,31 @@ packages: |
| path: ../apple |
| RastrilloNative: |
| url: https://amadan.net/rastrillo/native |
| - revision: 4c61d6283a188c95647e1d0e609e69d29c2e7fa1 |
| + revision: 229525909e1d6ac3b6a353d1c4d022798b0e9a24 |
| settings: |
| base: |
| SWIFT_VERSION: '6.0' |
| CODE_SIGN_STYLE: Automatic |
| - MARKETING_VERSION: '0.1.0' |
| + MARKETING_VERSION: 0.1.0 |
| CURRENT_PROJECT_VERSION: '3' |
| - ENABLE_HARDENED_RUNTIME: YES |
| + ENABLE_HARDENED_RUNTIME: true |
| targets: |
| SheetsMacStore: |
| type: application |
| platform: macOS |
| sources: |
| - - ../apple/Sources/SheetsApp |
| - - path: AppIcon.icns |
| - buildPhase: resources |
| - - path: ../LICENSE.lucide |
| - buildPhase: resources |
| - - path: ../PrivacyInfo.xcprivacy |
| - buildPhase: resources |
| + - ../apple/Sources/SheetsApp |
| + - path: AppIcon.icns |
| + buildPhase: resources |
| + - path: ../LICENSE.lucide |
| + buildPhase: resources |
| + - path: ../PrivacyInfo.xcprivacy |
| + buildPhase: resources |
| dependencies: |
| - - package: SheetsNative |
| - product: SheetsKit |
| - - package: RastrilloNative |
| - product: RastrilloApple |
| + - package: SheetsNative |
| + product: SheetsKit |
| + - package: RastrilloNative |
| + product: RastrilloApple |
| info: |
| path: Info.plist |
| properties: |
| @@ -42,7 +42,13 @@ targets: |
| CFBundleIconFile: AppIcon |
| LSApplicationCategoryType: public.app-category.productivity |
| NSHighResolutionCapable: true |
| + CFBundleURLTypes: |
| + - CFBundleURLName: works.oficina.sheets.signin |
| + CFBundleURLSchemes: |
| + - works.oficina.sheets |
| + CFBundleTypeRole: Editor |
| settings: |
| base: |
| - PRODUCT_BUNDLE_IDENTIFIER: net.amadan.oficina.sheets |
| + PROVISIONING_PROFILE_SPECIFIER: $(OFICINA_PROVISIONING_PROFILE) |
| + PRODUCT_BUNDLE_IDENTIFIER: works.oficina.sheets |
| CODE_SIGN_ENTITLEMENTS: AppStore.entitlements |