Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ archives are vendored under `vendor/zennotes/` with their source identity and
checksums (`manifest.json`), and `package-lock.json` pins the complete install.
A clean checkout installs them with `npm ci`, without a source clone or sibling
repository. The vendored set is the core release
[core-2.77.0-core.hfe38f5ee2a70bd64](https://github.com/ZenNotes/zennotes/releases/tag/core-2.77.0-core.hfe38f5ee2a70bd64)
(desktop commit `3f0356de`, clean tree).
[core-2.78.0-core.h0bc32cbd73a78fac](https://github.com/ZenNotes/zennotes/releases/tag/core-2.78.0-core.h0bc32cbd73a78fac)
(desktop commit `52ab86fd`, clean tree).

`npm run boundaries:check` verifies the pins, installed versions, singleton
React/CodeMirror peers, and public export usage. `npm run core:adopt -- <core-tag>`
Expand Down
40 changes: 28 additions & 12 deletions ios/App/App.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
objects = {

/* Begin PBXBuildFile section */
0D482B74B72550D754DC59E4 /* CalendarWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6D3810E32BD1F68308D5F9E /* CalendarWidget.swift */; };
11A978B6D133577F0EF5748C /* CalendarWidgetIntents.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B50085E6BF8C0AEEA206C86 /* CalendarWidgetIntents.swift */; };
1620DB6173A8CFE3D41D46DA /* ZenWidgets.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = F342B601563BB02825474641 /* ZenWidgets.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
172569C163FC68A0C0C58F02 /* WidgetTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3175A5673A3065A7A684CC9D /* WidgetTheme.swift */; };
230C7E4950AA2E50A25A394C /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = F7650E04BDA8754AB2119967 /* PrivacyInfo.xcprivacy */; };
Expand All @@ -28,9 +30,11 @@
50B271D11FEDC1A000F3C39B /* public in Resources */ = {isa = PBXBuildFile; fileRef = 50B271D01FEDC1A000F3C39B /* public */; };
5CA8650C3B7DF616A8B69229 /* ZNViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A24C226FEA7EA30D28C20477 /* ZNViewController.swift */; };
5CA8650D3B7DF616A8B69229 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A24C2270EA7EA30D28C20477 /* SceneDelegate.swift */; };
5F3188CBB861D6DF7A1A2DDC /* WidgetActionLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48BC3D75A44C9064DF636C2F /* WidgetActionLog.swift */; };
60BB3C8B9335A8DF5C0C752D /* NewNoteWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 486736422F5CB5716CAA674F /* NewNoteWidget.swift */; };
66714DDFC6EB0A9732DE176A /* WidgetBridgePlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 830C64B43794EBCBD9091276 /* WidgetBridgePlugin.swift */; };
6B30A84670984EC66F0422E2 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 6A7467BA76B7322966D7EA03 /* PrivacyInfo.xcprivacy */; };
7933D95CCAF6766300D6F19B /* CalendarWidgetIntents.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B50085E6BF8C0AEEA206C86 /* CalendarWidgetIntents.swift */; };
80DB78E0507751992FCE4245 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4ED02E2781BE90C097D648B8 /* WidgetKit.framework */; };
88E96F6793476380FB4028C7 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = D61B685B388CE720F2588065 /* PrivacyInfo.xcprivacy */; };
9929F4C805DC04F7A7F2058C /* WidgetSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EAB64B0086A91CBCB3B5802 /* WidgetSnapshot.swift */; };
Expand All @@ -43,6 +47,7 @@
BA7E23B65E109265261E0F5E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 155E04D763AD80DA2E56D38D /* Foundation.framework */; };
C10DF11E5A2B4C7D9E8F0A1B /* CloudFilesPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = C10DF11F5A2B4C7D9E8F0A1C /* CloudFilesPlugin.swift */; };
D17E4E8551A97CF08FDE5F82 /* FolderPickerPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A91962841901607F2906263 /* FolderPickerPlugin.swift */; };
D283CDD647BD7C0D803FB8FE /* WidgetActionLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48BC3D75A44C9064DF636C2F /* WidgetActionLog.swift */; };
DE19FCF1249C6A4D528227C2 /* ShareExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = E1424FEA5946506EA505941C /* ShareExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
F59E347AA2D96EB117D7C2CD /* ZenWidgetsBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = C218F6CD95CD249E2926D1DA /* ZenWidgetsBundle.swift */; };
FB56F003004840A2A553E931 /* KeyboardBackdropPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 424F5A2D64394F429AF0ED50 /* KeyboardBackdropPlugin.swift */; };
Expand Down Expand Up @@ -97,6 +102,7 @@
3A7702CA7CC6312CAD599CD7 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS26.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
424F5A2D64394F429AF0ED50 /* KeyboardBackdropPlugin.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = KeyboardBackdropPlugin.swift; sourceTree = "<group>"; };
486736422F5CB5716CAA674F /* NewNoteWidget.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NewNoteWidget.swift; sourceTree = "<group>"; };
48BC3D75A44C9064DF636C2F /* WidgetActionLog.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WidgetActionLog.swift; sourceTree = "<group>"; };
4ED02E2781BE90C097D648B8 /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS26.0.sdk/System/Library/Frameworks/WidgetKit.framework; sourceTree = DEVELOPER_DIR; };
50379B222058CBB4000EE86E /* capacitor.config.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = capacitor.config.json; sourceTree = "<group>"; };
504EC3041FED79650016851F /* App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = App.app; sourceTree = BUILT_PRODUCTS_DIR; };
Expand All @@ -115,12 +121,14 @@
830C64B43794EBCBD9091276 /* WidgetBridgePlugin.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WidgetBridgePlugin.swift; sourceTree = "<group>"; };
85847153B31EF561562A9281 /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS26.0.sdk/System/Library/Frameworks/SwiftUI.framework; sourceTree = DEVELOPER_DIR; };
8A91962841901607F2906263 /* FolderPickerPlugin.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = FolderPickerPlugin.swift; sourceTree = "<group>"; };
8B50085E6BF8C0AEEA206C86 /* CalendarWidgetIntents.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CalendarWidgetIntents.swift; sourceTree = "<group>"; };
8EAB64B0086A91CBCB3B5802 /* WidgetSnapshot.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WidgetSnapshot.swift; sourceTree = "<group>"; };
9115A46C405EC261610EC467 /* CloudFileStream.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CloudFileStream.swift; sourceTree = "<group>"; };
A24C226FEA7EA30D28C20477 /* ZNViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ZNViewController.swift; sourceTree = "<group>"; };
A24C2270EA7EA30D28C20477 /* SceneDelegate.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
AF277DCFFFF123FFC6DF26C7 /* Pods_App.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_App.framework; sourceTree = BUILT_PRODUCTS_DIR; };
AF51FD2D460BCFE21FA515B2 /* Pods-App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.release.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.release.xcconfig"; sourceTree = "<group>"; };
B6D3810E32BD1F68308D5F9E /* CalendarWidget.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CalendarWidget.swift; sourceTree = "<group>"; };
C10DF11F5A2B4C7D9E8F0A1C /* CloudFilesPlugin.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CloudFilesPlugin.swift; sourceTree = "<group>"; };
C218F6CD95CD249E2926D1DA /* ZenWidgetsBundle.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ZenWidgetsBundle.swift; sourceTree = "<group>"; };
CC30A5CCEA5991955FBC0360 /* CloudFlowUITests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CloudFlowUITests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -294,6 +302,9 @@
E826831F57D7B9D9D5121461 /* ZenWidgets.entitlements */,
DB10756BA75711FC150E34FD /* Assets.xcassets */,
6A7467BA76B7322966D7EA03 /* PrivacyInfo.xcprivacy */,
B6D3810E32BD1F68308D5F9E /* CalendarWidget.swift */,
8B50085E6BF8C0AEEA206C86 /* CalendarWidgetIntents.swift */,
48BC3D75A44C9064DF636C2F /* WidgetActionLog.swift */,
);
name = ZenWidgets;
path = ZenWidgets;
Expand Down Expand Up @@ -509,6 +520,9 @@
60BB3C8B9335A8DF5C0C752D /* NewNoteWidget.swift in Sources */,
B516881658A9D3C9AFC1259E /* RecentNotesWidget.swift in Sources */,
9F314931CA3D31AAFCF26E15 /* TasksWidget.swift in Sources */,
0D482B74B72550D754DC59E4 /* CalendarWidget.swift in Sources */,
11A978B6D133577F0EF5748C /* CalendarWidgetIntents.swift in Sources */,
D283CDD647BD7C0D803FB8FE /* WidgetActionLog.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -527,6 +541,8 @@
C10DF11E5A2B4C7D9E8F0A1B /* CloudFilesPlugin.swift in Sources */,
FD65529207121AA61FF892C5 /* CloudFileStream.swift in Sources */,
34CD033D6469BD27C1F5F22B /* BackgroundSyncPlugin.swift in Sources */,
7933D95CCAF6766300D6F19B /* CalendarWidgetIntents.swift in Sources */,
5F3188CBB861D6DF7A1A2DDC /* WidgetActionLog.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -608,12 +624,12 @@
CLANG_ENABLE_OBJC_WEAK = NO;
CODE_SIGN_ENTITLEMENTS = ZenWidgets/ZenWidgets.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 49;
CURRENT_PROJECT_VERSION = 51;
DEVELOPMENT_TEAM = WYY7PK57DM;
GENERATE_INFOPLIST_FILE = NO;
INFOPLIST_FILE = ZenWidgets/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
MARKETING_VERSION = 1.33.0;
MARKETING_VERSION = 1.34.0;
PRODUCT_BUNDLE_IDENTIFIER = md.zennotes.ZenWidgets;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
Expand Down Expand Up @@ -737,12 +753,12 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = App/App.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 49;
CURRENT_PROJECT_VERSION = 51;
DEVELOPMENT_TEAM = WYY7PK57DM;
INFOPLIST_FILE = App/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 1.33.0;
MARKETING_VERSION = 1.34.0;
OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
PRODUCT_BUNDLE_IDENTIFIER = md.zennotes;
PRODUCT_NAME = "$(TARGET_NAME)";
Expand All @@ -759,12 +775,12 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = App/App.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 49;
CURRENT_PROJECT_VERSION = 51;
DEVELOPMENT_TEAM = WYY7PK57DM;
INFOPLIST_FILE = App/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 1.33.0;
MARKETING_VERSION = 1.34.0;
PRODUCT_BUNDLE_IDENTIFIER = md.zennotes;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "";
Expand All @@ -779,12 +795,12 @@
CLANG_ENABLE_OBJC_WEAK = NO;
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 49;
CURRENT_PROJECT_VERSION = 51;
DEVELOPMENT_TEAM = WYY7PK57DM;
GENERATE_INFOPLIST_FILE = NO;
INFOPLIST_FILE = ShareExtension/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
MARKETING_VERSION = 1.33.0;
MARKETING_VERSION = 1.34.0;
PRODUCT_BUNDLE_IDENTIFIER = md.zennotes.ShareExtension;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
Expand All @@ -801,12 +817,12 @@
CLANG_ENABLE_OBJC_WEAK = NO;
CODE_SIGN_ENTITLEMENTS = ZenWidgets/ZenWidgets.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 49;
CURRENT_PROJECT_VERSION = 51;
DEVELOPMENT_TEAM = WYY7PK57DM;
GENERATE_INFOPLIST_FILE = NO;
INFOPLIST_FILE = ZenWidgets/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
MARKETING_VERSION = 1.33.0;
MARKETING_VERSION = 1.34.0;
PRODUCT_BUNDLE_IDENTIFIER = md.zennotes.ZenWidgets;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
Expand Down Expand Up @@ -839,12 +855,12 @@
CLANG_ENABLE_OBJC_WEAK = NO;
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 49;
CURRENT_PROJECT_VERSION = 51;
DEVELOPMENT_TEAM = WYY7PK57DM;
GENERATE_INFOPLIST_FILE = NO;
INFOPLIST_FILE = ShareExtension/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
MARKETING_VERSION = 1.33.0;
MARKETING_VERSION = 1.34.0;
PRODUCT_BUNDLE_IDENTIFIER = md.zennotes.ShareExtension;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
Expand Down
25 changes: 23 additions & 2 deletions ios/App/App/WidgetBridgePlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,18 @@ import WidgetKit
/// (ios/App/ZenWidgets). The WebView publishes the widget snapshot
/// (src/bridge/widgets.ts builds it from the store) and this writes it into
/// the App Group — the only place a widget extension can read — then asks
/// WidgetKit to re-render. The extension never sees the vault itself.
/// WidgetKit to re-render. The extension never sees the vault itself; the
/// Calendar widget's checkbox taps come back through readActions
/// (WidgetActionLog, src/bridge/widget-calendar.ts).
@objc(WidgetBridgePlugin)
public class WidgetBridgePlugin: CAPPlugin, CAPBridgedPlugin {
public let identifier = "WidgetBridgePlugin"
public let jsName = "ZenWidgets"
public let pluginMethods: [CAPPluginMethod] = [
CAPPluginMethod(name: "update", returnType: CAPPluginReturnPromise),
CAPPluginMethod(name: "clear", returnType: CAPPluginReturnPromise),
CAPPluginMethod(name: "consumeLaunchLink", returnType: CAPPluginReturnPromise)
CAPPluginMethod(name: "consumeLaunchLink", returnType: CAPPluginReturnPromise),
CAPPluginMethod(name: "readActions", returnType: CAPPluginReturnPromise)
]

private let appGroupId = "group.md.zennotes"
Expand Down Expand Up @@ -66,11 +69,29 @@ public class WidgetBridgePlugin: CAPPlugin, CAPBridgedPlugin {
call.reject("Could not write the widget snapshot: \(error.localizedDescription)")
return
}
WidgetActionLog.prune(through: Self.actionsAck(json))
WidgetCenter.shared.reloadAllTimelines()
call.resolve()
}
}

/// The newest Calendar widget tap this snapshot says the app applied.
private static func actionsAck(_ json: String) -> Double {
guard let object = try? JSONSerialization.jsonObject(with: Data(json.utf8)) as? [String: Any],
let calendar = object["calendar"] as? [String: Any]
else { return 0 }
return calendar["actionsAck"] as? Double ?? 0
}

/// The Calendar widget's logged taps, oldest first. Reading leaves them
/// in place: a snapshot whose `actionsAck` covers a tap clears it.
@objc func readActions(_ call: CAPPluginCall) {
DispatchQueue.global(qos: .utility).async {
let list = WidgetActionLog.read().sorted { ($0["at"] as? Double ?? 0) < ($1["at"] as? Double ?? 0) }
call.resolve(["actions": list])
}
}

@objc func clear(_ call: CAPPluginCall) {
DispatchQueue.global(qos: .utility).async {
if let url = self.snapshotURL() {
Expand Down
Loading
Loading