oficina / calendar Public

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.
Paul Campbell pushed by codex agent, operated by paul@keymail.dev d13312056d8d24a7fea86a0f346238501b16f9a4 parent 2d81e66
9 files changed, +141 −70
  • native/apple/Package.resolved +13 −13
  • native/apple/Package.swift +2 −2
  • native/apple/Sources/CalendarApp/CalendarApp.swift +4 −4
  • native/apple/Sources/CalendarKit/CalendarWorkspace.swift +3 −2
  • native/ios/Info.plist +35 −0
  • native/ios/project.yml +45 −31
  • native/macos/CalendarMacStore.xcodeproj/project.pbxproj +5 −3
  • native/macos/Info.plist +13 −0
  • native/macos/project.yml +21 −15

CI passed — run details

diff --git a/native/apple/Package.resolved b/native/apple/Package.resolved
index 710f96c..cf50d40 100644
--- a/native/apple/Package.resolved
+++ b/native/apple/Package.resolved
@@ -1,22 +1,22 @@
{
- "pins": [
+ "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": 2
+ "version" : 2
}
diff --git a/native/apple/Package.swift b/native/apple/Package.swift
index d2e6c1e..5c2847e 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: "CalendarNative", platforms: [.macOS(.v14), .iOS(.v17)],
products: [.library(name: "CalendarKit", targets: ["CalendarKit"]), .executable(name: "CalendarMac", targets: ["CalendarMac"])],
diff --git a/native/apple/Sources/CalendarApp/CalendarApp.swift b/native/apple/Sources/CalendarApp/CalendarApp.swift
index f03a37e..78368d4 100644
--- a/native/apple/Sources/CalendarApp/CalendarApp.swift
+++ b/native/apple/Sources/CalendarApp/CalendarApp.swift
@@ -19,11 +19,11 @@ import AppKit
WindowGroup("Calendar", id: "calendar") {
Group {
if let client = connection.client {
- CalendarWorkspace(client: client, model: model, signOut: { model.clear(); connection.signOut(); model = CalendarModel() })
+ CalendarWorkspace(client: client, model: model, accounts: { model.clear(); connection.showAccounts(); model = CalendarModel() }, signOut: { model.clear(); connection.signOut(); model = CalendarModel() })
} else {
- NativeSignInView("Oficina Calendar", systemImage: "calendar", connection: connection)
+ NativeAccountsView("Oficina Calendar", systemImage: "calendar", connection: connection)
}
- }.tint(Color(red: 0.78, green: 0.22, blue: 0.29))
+ }.id(connection.activeAccountID).onOpenURL(perform: connection.handleOpenURL).tint(Color(red: 0.78, green: 0.22, blue: 0.29))
#if os(macOS)
.frame(minWidth: 780, minHeight: 650)
#endif
@@ -41,7 +41,7 @@ import AppKit
if let client = connection.client {
CalendarMenuView(client: client, model: model).tint(Color(red: 0.78, green: 0.22, blue: 0.29))
} else {
- NativeSignInView("Oficina Calendar", systemImage: "calendar", connection: connection)
+ NativeAccountsView("Oficina Calendar", systemImage: "calendar", connection: connection)
.frame(width: 380, height: 480)
}
}.menuBarExtraStyle(.window)
diff --git a/native/apple/Sources/CalendarKit/CalendarWorkspace.swift b/native/apple/Sources/CalendarKit/CalendarWorkspace.swift
index 9bc5f0c..9c1a218 100644
--- a/native/apple/Sources/CalendarKit/CalendarWorkspace.swift
+++ b/native/apple/Sources/CalendarKit/CalendarWorkspace.swift
@@ -4,6 +4,7 @@ import SwiftUI
@MainActor public struct CalendarWorkspace: View {
public let client: NativeHTTP
public let signOut: () -> Void
+ private let accounts: (() -> Void)?
@StateObject private var model: CalendarModel
@State private var quickAdding = false
@State private var settings = false
@@ -14,7 +15,7 @@ import SwiftUI
@State private var column: NavigationSplitViewColumn = .detail
@Environment(\.dynamicTypeSize) private var typeSize
private let accent = Color(red: 0.78, green: 0.22, blue: 0.29)
- public init(client: NativeHTTP, model: CalendarModel? = nil, signOut: @escaping () -> Void) { self.client = client; self.signOut = signOut; _model = StateObject(wrappedValue: model ?? CalendarModel()) }
+ public init(client: NativeHTTP, model: CalendarModel? = nil, accounts: (() -> Void)? = nil, signOut: @escaping () -> Void) { self.client = client; self.signOut = signOut; self.accounts = accounts; _model = StateObject(wrappedValue: model ?? CalendarModel()) }
public var body: some View {
NavigationSplitView(preferredCompactColumn: $column) {
@@ -32,7 +33,7 @@ import SwiftUI
Button("Settings", systemImage: "gear") { settings = true }
Button("Sign out", action: signOut)
}
- }.navigationTitle("Calendar").navigationSplitViewColumnWidth(min: 220, ideal: 260, max: 340)
+ }.toolbar { if let accounts { ToolbarItem(placement: .navigation) { Button("Accounts", systemImage: "chevron.backward", action: accounts) } } }.navigationTitle("Calendar").navigationSplitViewColumnWidth(min: 220, ideal: 260, max: 340)
} detail: {
List {
Section {
diff --git a/native/ios/Info.plist b/native/ios/Info.plist
new file mode 100644
index 0000000..dee8168
--- /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.calendar.signin</string>
+ <key>CFBundleURLSchemes</key>
+ <array>
+ <string>works.oficina.calendar</string>
+ </array>
+ </dict>
+ </array>
+ <key>CFBundleVersion</key>
+ <string>$(CURRENT_PROJECT_VERSION)</string>
+</dict>
+</plist>
diff --git a/native/ios/project.yml b/native/ios/project.yml
index 4959bd1..247ba91 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: '5.0'
CODE_SIGN_STYLE: Automatic
- MARKETING_VERSION: '0.1.0'
+ MARKETING_VERSION: 0.1.0
CURRENT_PROJECT_VERSION: '1'
targets:
CalendarPhone:
type: application
platform: iOS
sources:
- - ../apple/Sources/CalendarApp
- - Assets.xcassets
- - path: ../LICENSE.lucide
- buildPhase: resources
- - path: ../PrivacyInfo.xcprivacy
- buildPhase: resources
+ - ../apple/Sources/CalendarApp
+ - Assets.xcassets
+ - path: ../LICENSE.lucide
+ buildPhase: resources
+ - path: ../PrivacyInfo.xcprivacy
+ buildPhase: resources
dependencies:
- - package: CalendarNative
- product: CalendarKit
- - package: RastrilloNative
- product: RastrilloApple
+ - package: CalendarNative
+ product: CalendarKit
+ - package: RastrilloNative
+ product: RastrilloApple
settings:
base:
ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon
- PRODUCT_BUNDLE_IDENTIFIER: net.amadan.oficina.calendar.ios
- TARGETED_DEVICE_FAMILY: '1,2'
- GENERATE_INFOPLIST_FILE: YES
+ PROVISIONING_PROFILE_SPECIFIER: $(OFICINA_PROVISIONING_PROFILE)
+ PRODUCT_BUNDLE_IDENTIFIER: works.oficina.calendar
+ TARGETED_DEVICE_FAMILY: 1,2
+ GENERATE_INFOPLIST_FILE: true
INFOPLIST_KEY_CFBundleDisplayName: Oficina Calendar
- 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.calendar.signin
+ CFBundleURLSchemes:
+ - works.oficina.calendar
+ CFBundleTypeRole: Editor
+ CFBundleShortVersionString: $(MARKETING_VERSION)
+ CFBundleVersion: $(CURRENT_PROJECT_VERSION)
CalendarReviewPhone:
type: application
platform: iOS
- sources: [Review]
+ sources:
+ - Review
dependencies:
- - package: CalendarNative
- product: CalendarKit
- - package: RastrilloNative
- product: RastrilloApple
+ - package: CalendarNative
+ product: CalendarKit
+ - package: RastrilloNative
+ product: RastrilloApple
settings:
base:
PRODUCT_BUNDLE_IDENTIFIER: net.amadan.oficina.calendar.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
CalendarPhoneUITests:
type: bundle.ui-testing
platform: iOS
- sources: [UITests]
+ sources:
+ - UITests
dependencies:
- - target: CalendarReviewPhone
+ - target: CalendarReviewPhone
settings:
base:
- GENERATE_INFOPLIST_FILE: YES
+ GENERATE_INFOPLIST_FILE: true
TEST_TARGET_NAME: CalendarReviewPhone
schemes:
CalendarReviewPhone:
@@ -73,4 +86,5 @@ schemes:
targets:
CalendarReviewPhone: all
test:
- targets: [CalendarPhoneUITests]
+ targets:
+ - CalendarPhoneUITests
diff --git a/native/macos/CalendarMacStore.xcodeproj/project.pbxproj b/native/macos/CalendarMacStore.xcodeproj/project.pbxproj
index c4368f0..7d85cf2 100644
--- a/native/macos/CalendarMacStore.xcodeproj/project.pbxproj
+++ b/native/macos/CalendarMacStore.xcodeproj/project.pbxproj
@@ -180,7 +180,8 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
- PRODUCT_BUNDLE_IDENTIFIER = net.amadan.oficina.calendar;
+ PRODUCT_BUNDLE_IDENTIFIER = works.oficina.calendar;
+ PROVISIONING_PROFILE_SPECIFIER = "$(OFICINA_PROVISIONING_PROFILE)";
SDKROOT = macosx;
};
name = Debug;
@@ -196,7 +197,8 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
- PRODUCT_BUNDLE_IDENTIFIER = net.amadan.oficina.calendar;
+ PRODUCT_BUNDLE_IDENTIFIER = works.oficina.calendar;
+ PROVISIONING_PROFILE_SPECIFIER = "$(OFICINA_PROVISIONING_PROFILE)";
SDKROOT = macosx;
};
name = Release;
@@ -364,7 +366,7 @@
repositoryURL = "https://amadan.net/rastrillo/native";
requirement = {
kind = revision;
- revision = 4c61d6283a188c95647e1d0e609e69d29c2e7fa1;
+ revision = 229525909e1d6ac3b6a353d1c4d022798b0e9a24;
};
};
/* End XCRemoteSwiftPackageReference section */
diff --git a/native/macos/Info.plist b/native/macos/Info.plist
index 9070ef0..dd46943 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.calendar.signin</string>
+ <key>CFBundleURLSchemes</key>
+ <array>
+ <string>works.oficina.calendar</string>
+ </array>
+ </dict>
+ </array>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>LSApplicationCategoryType</key>
diff --git a/native/macos/project.yml b/native/macos/project.yml
index d4fe807..f064a2e 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: '5.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:
CalendarMacStore:
type: application
platform: macOS
sources:
- - ../apple/Sources/CalendarApp
- - path: AppIcon.icns
- buildPhase: resources
- - path: ../LICENSE.lucide
- buildPhase: resources
- - path: ../PrivacyInfo.xcprivacy
- buildPhase: resources
+ - ../apple/Sources/CalendarApp
+ - path: AppIcon.icns
+ buildPhase: resources
+ - path: ../LICENSE.lucide
+ buildPhase: resources
+ - path: ../PrivacyInfo.xcprivacy
+ buildPhase: resources
dependencies:
- - package: CalendarNative
- product: CalendarKit
- - package: RastrilloNative
- product: RastrilloApple
+ - package: CalendarNative
+ product: CalendarKit
+ - 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.calendar.signin
+ CFBundleURLSchemes:
+ - works.oficina.calendar
+ CFBundleTypeRole: Editor
settings:
base:
- PRODUCT_BUNDLE_IDENTIFIER: net.amadan.oficina.calendar
+ PROVISIONING_PROFILE_SPECIFIER: $(OFICINA_PROVISIONING_PROFILE)
+ PRODUCT_BUNDLE_IDENTIFIER: works.oficina.calendar
CODE_SIGN_ENTITLEMENTS: AppStore.entitlements