vxrn 2.0.0-beta.96.1 → 2.0.0-beta.97.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -333,7 +333,7 @@ ${anchor}`);
333
333
  ${ids.dependency} /* PBXTargetDependency */ = {isa = PBXTargetDependency; target = ${ids.target} /* OneWidgets */; targetProxy = ${ids.proxy} /* PBXContainerItemProxy */; };
334
334
  /* End PBXTargetDependency section */
335
335
  `);
336
- const config = (id, mode) => ` ${id} /* ${mode} */ = {isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_ENTITLEMENTS = OneWidgets/OneWidgets.entitlements; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = ${app.ios?.buildNumber || "1"}; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = OneWidgets/WidgetInfo.plist; IPHONEOS_DEPLOYMENT_TARGET = ${deploymentTarget}; MARKETING_VERSION = "${app.version || "1.0"}"; PRODUCT_BUNDLE_IDENTIFIER = ${bundleId}.widgets; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1"; }; name = ${mode}; };`;
336
+ const config = (id, mode) => ` ${id} /* ${mode} */ = {isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_ENTITLEMENTS = OneWidgets/OneWidgets.entitlements; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = ${app.ios?.buildNumber || "1"}; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = OneWidgets/WidgetInfo.plist; IPHONEOS_DEPLOYMENT_TARGET = ${deploymentTarget}; MARKETING_VERSION = "${app.version || "1.0"}"; PRODUCT_BUNDLE_IDENTIFIER = ${bundleId}.widgets; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "${app.ios?.tablet ? "1,2" : "1"}"; }; name = ${mode}; };`;
337
337
  insert("/* End XCBuildConfiguration section */", `${config(ids.debug, "Debug")}
338
338
  ${config(ids.release, "Release")}`);
339
339
  insert("/* End XCConfigurationList section */", ` ${ids.config} /* Build configuration list for PBXNativeTarget "OneWidgets" */ = {isa = XCConfigurationList; buildConfigurations = (${ids.debug} /* Debug */, ${ids.release} /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; };`);
@@ -367,20 +367,13 @@ function generateSceneDelegate(args) {
367
367
  const { dest, platform, app } = args;
368
368
  if (platform !== "ios") return;
369
369
  FSExtra.writeFileSync(path.join(dest, app.name, "SceneDelegate.swift"), renderSceneDelegateSwift(app.name));
370
- if (app.notifications?.push === true) {
370
+ if (app.notifications?.push === true && !app.ios?.widgets) {
371
371
  FSExtra.writeFileSync(path.join(dest, app.name, `${app.name}.entitlements`), renderPushEntitlements());
372
372
  }
373
373
  }
374
374
  function generateIosWidgets(dest, app) {
375
375
  const widgets = app.ios?.widgets;
376
376
  if (!widgets) return;
377
- if (widgets.jsx) {
378
- try {
379
- module.createRequire(dest + "/").resolve("@use-voltra/ios-client/package.json");
380
- } catch {
381
- throw new Error("[vxrn] native.app.ios.widgets.jsx requires @use-voltra/ios-client");
382
- }
383
- }
384
377
  const appDir = path.join(dest, app.name);
385
378
  const extensionDir = path.join(dest, "OneWidgets");
386
379
  FSExtra.mkdirSync(extensionDir, { recursive: true });
@@ -388,7 +381,7 @@ function generateIosWidgets(dest, app) {
388
381
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
389
382
  <plist version="1.0"><dict><key>com.apple.security.application-groups</key><array><string>${escapeXml(widgets.appGroup)}</string></array></dict></plist>
390
383
  `;
391
- FSExtra.writeFileSync(path.join(appDir, "OneAppWidgets.entitlements"), widgets.pushNotifications ? entitlements.replace("</dict></plist>", "<key>aps-environment</key><string>development</string></dict></plist>") : entitlements);
384
+ FSExtra.writeFileSync(path.join(appDir, "OneAppWidgets.entitlements"), widgets.pushNotifications || app.notifications?.push ? entitlements.replace("</dict></plist>", "<key>aps-environment</key><string>development</string></dict></plist>") : entitlements);
392
385
  FSExtra.writeFileSync(path.join(extensionDir, "OneWidgets.entitlements"), entitlements);
393
386
  FSExtra.writeFileSync(path.join(extensionDir, "WidgetInfo.plist"), `<?xml version="1.0" encoding="UTF-8"?>
394
387
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
@@ -403,7 +396,6 @@ function generateIosWidgets(dest, app) {
403
396
  <key>CFBundleShortVersionString</key><string>${escapeXml(app.version || "1.0")}</string>
404
397
  <key>CFBundleVersion</key><string>${escapeXml(app.ios?.buildNumber || "1")}</string>
405
398
  <key>NSExtension</key><dict><key>NSExtensionPointIdentifier</key><string>com.apple.widgetkit-extension</string></dict>
406
- ${widgets.jsx ? `<key>Voltra_AppGroupIdentifier</key><string>${escapeXml(widgets.appGroup)}</string>` : ""}
407
399
  </dict></plist>
408
400
  `);
409
401
  FSExtra.writeFileSync(path.join(appDir, "OneWidgetContract.swift"), `import Foundation
@@ -418,12 +410,14 @@ enum OneWidgetContract {
418
410
  let title: String
419
411
  let value: String
420
412
  let subtitle: String
413
+ let layout: String?
421
414
  }
422
415
 
423
416
  struct Attributes: ActivityAttributes {
424
417
  struct ContentState: Codable, Hashable {
425
418
  let status: String
426
419
  let value: String
420
+ let layout: String?
427
421
  }
428
422
  let title: String
429
423
  }
@@ -432,7 +426,163 @@ enum OneWidgetContract {
432
426
  FSExtra.writeFileSync(path.join(extensionDir, "OneWidget.swift"), `import SwiftUI
433
427
  import WidgetKit
434
428
  import ActivityKit
435
- ${widgets.jsx ? "import VoltraRuntime" : ""}
429
+
430
+ struct OneWidgetNode: Decodable {
431
+ let type: String
432
+ let text: String?
433
+ let style: Style?
434
+ let children: [OneWidgetNode]?
435
+ let systemName: String?
436
+ let value: Double?
437
+ let total: Double?
438
+ let fill: String?
439
+ let cornerRadius: Double?
440
+ let url: String?
441
+
442
+ struct Style: Decodable {
443
+ let color: String?
444
+ let backgroundColor: String?
445
+ let fontSize: Double?
446
+ let fontWeight: String?
447
+ let fontDesign: String?
448
+ let padding: Double?
449
+ let borderRadius: Double?
450
+ let spacing: Double?
451
+ let width: Double?
452
+ let height: Double?
453
+ let opacity: Double?
454
+ let lineLimit: Int?
455
+ let alignment: String?
456
+ }
457
+ }
458
+
459
+ struct OneActivityView: Decodable {
460
+ let lockScreen: OneWidgetNode
461
+ let compactLeading: OneWidgetNode?
462
+ let compactTrailing: OneWidgetNode?
463
+ let minimal: OneWidgetNode?
464
+ let expandedLeading: OneWidgetNode?
465
+ let expandedTrailing: OneWidgetNode?
466
+ let expandedBottom: OneWidgetNode?
467
+ }
468
+
469
+ private func oneDecode<T: Decodable>(_ value: String?, as type: T.Type) -> T? {
470
+ guard let value, let data = value.data(using: .utf8) else { return nil }
471
+ return try? JSONDecoder().decode(type, from: data)
472
+ }
473
+
474
+ private func oneColor(_ hex: String?) -> Color? {
475
+ guard let hex, hex.count == 7, hex.first == "#",
476
+ let rgb = Int(hex.dropFirst(), radix: 16) else { return nil }
477
+ return Color(red: Double((rgb >> 16) & 255) / 255,
478
+ green: Double((rgb >> 8) & 255) / 255,
479
+ blue: Double(rgb & 255) / 255)
480
+ }
481
+
482
+ struct OneWidgetRendered: View {
483
+ let node: OneWidgetNode
484
+
485
+ private var alignment: Alignment {
486
+ switch node.style?.alignment {
487
+ case "leading": .leading
488
+ case "trailing": .trailing
489
+ default: .center
490
+ }
491
+ }
492
+
493
+ private var horizontalAlignment: HorizontalAlignment {
494
+ switch node.style?.alignment {
495
+ case "center": .center
496
+ case "trailing": .trailing
497
+ default: .leading
498
+ }
499
+ }
500
+
501
+ private var weight: Font.Weight {
502
+ switch node.style?.fontWeight {
503
+ case "medium": .medium
504
+ case "semibold": .semibold
505
+ case "bold": .bold
506
+ default: .regular
507
+ }
508
+ }
509
+
510
+ private var design: Font.Design {
511
+ switch node.style?.fontDesign {
512
+ case "rounded": .rounded
513
+ case "serif": .serif
514
+ case "monospaced": .monospaced
515
+ default: .default
516
+ }
517
+ }
518
+
519
+ var body: some View {
520
+ Group {
521
+ switch node.type {
522
+ case "text":
523
+ Text(node.text ?? "")
524
+ .font(.system(size: CGFloat(node.style?.fontSize ?? 16), weight: weight, design: design))
525
+ case "vstack":
526
+ VStack(alignment: horizontalAlignment, spacing: CGFloat(node.style?.spacing ?? 8)) {
527
+ ForEach(Array((node.children ?? []).enumerated()), id: \\.offset) { _, child in
528
+ OneWidgetRendered(node: child)
529
+ }
530
+ }
531
+ case "hstack":
532
+ HStack(spacing: CGFloat(node.style?.spacing ?? 8)) {
533
+ ForEach(Array((node.children ?? []).enumerated()), id: \\.offset) { _, child in
534
+ OneWidgetRendered(node: child)
535
+ }
536
+ }
537
+ case "zstack":
538
+ ZStack(alignment: alignment) {
539
+ ForEach(Array((node.children ?? []).enumerated()), id: \\.offset) { _, child in
540
+ OneWidgetRendered(node: child)
541
+ }
542
+ }
543
+ case "spacer": Spacer(minLength: 0)
544
+ case "divider": Divider()
545
+ case "image":
546
+ if let systemName = node.systemName {
547
+ Image(systemName: systemName)
548
+ .font(.system(size: CGFloat(node.style?.fontSize ?? 20), weight: weight))
549
+ }
550
+ case "progress":
551
+ ProgressView(value: node.value ?? 0, total: node.total ?? 1)
552
+ .tint(oneColor(node.style?.color))
553
+ case "gauge":
554
+ Gauge(value: node.value ?? 0, in: 0...(node.total ?? 1)) { EmptyView() }
555
+ .gaugeStyle(.accessoryCircular)
556
+ .tint(oneColor(node.style?.color))
557
+ case "circle":
558
+ Circle().fill(oneColor(node.fill) ?? .primary)
559
+ case "rectangle":
560
+ Rectangle().fill(oneColor(node.fill) ?? .primary)
561
+ case "rounded-rectangle":
562
+ RoundedRectangle(cornerRadius: CGFloat(node.cornerRadius ?? 8))
563
+ .fill(oneColor(node.fill) ?? .primary)
564
+ case "link":
565
+ if let url = node.url.flatMap(URL.init(string:)) {
566
+ Link(destination: url) {
567
+ ForEach(Array((node.children ?? []).enumerated()), id: \\.offset) { _, child in
568
+ OneWidgetRendered(node: child)
569
+ }
570
+ }
571
+ }
572
+ default: EmptyView()
573
+ }
574
+ }
575
+ .foregroundColor(oneColor(node.style?.color))
576
+ .lineLimit(node.style?.lineLimit)
577
+ .frame(width: node.style?.width.map { CGFloat($0) },
578
+ height: node.style?.height.map { CGFloat($0) },
579
+ alignment: alignment)
580
+ .opacity(node.style?.opacity ?? 1)
581
+ .padding(CGFloat(node.style?.padding ?? 0))
582
+ .background { if let fill = oneColor(node.style?.backgroundColor) { fill } }
583
+ .clipShape(RoundedRectangle(cornerRadius: CGFloat(node.style?.borderRadius ?? 0)))
584
+ }
585
+ }
436
586
 
437
587
  struct OneWidgetEntry: TimelineEntry {
438
588
  let date: Date
@@ -441,7 +591,7 @@ struct OneWidgetEntry: TimelineEntry {
441
591
 
442
592
  struct OneWidgetProvider: TimelineProvider {
443
593
  func placeholder(in context: Context) -> OneWidgetEntry {
444
- OneWidgetEntry(date: .now, data: .init(title: ${JSON.stringify(widgets.displayName)}, value: "", subtitle: ""))
594
+ OneWidgetEntry(date: .now, data: .init(title: ${JSON.stringify(widgets.displayName)}, value: "", subtitle: "", layout: nil))
445
595
  }
446
596
 
447
597
  func getSnapshot(in context: Context, completion: @escaping (OneWidgetEntry) -> Void) {
@@ -455,7 +605,7 @@ struct OneWidgetProvider: TimelineProvider {
455
605
  private func entry() -> OneWidgetEntry {
456
606
  let stored = UserDefaults(suiteName: OneWidgetContract.appGroup)?.data(forKey: OneWidgetContract.dataKey)
457
607
  let data = stored.flatMap { try? JSONDecoder().decode(OneWidgetContract.Data.self, from: $0) }
458
- ?? .init(title: ${JSON.stringify(widgets.displayName)}, value: "", subtitle: "")
608
+ ?? .init(title: ${JSON.stringify(widgets.displayName)}, value: "", subtitle: "", layout: nil)
459
609
  return OneWidgetEntry(date: .now, data: data)
460
610
  }
461
611
  }
@@ -463,10 +613,16 @@ struct OneWidgetProvider: TimelineProvider {
463
613
  struct OneWidget: Widget {
464
614
  var body: some WidgetConfiguration {
465
615
  StaticConfiguration(kind: OneWidgetContract.kind, provider: OneWidgetProvider()) { entry in
466
- VStack(alignment: .leading, spacing: 8) {
467
- Text(entry.data.title).font(.headline)
468
- Text(entry.data.value).font(.title2).bold()
469
- Text(entry.data.subtitle).font(.caption)
616
+ Group {
617
+ if let layout = oneDecode(entry.data.layout, as: OneWidgetNode.self) {
618
+ OneWidgetRendered(node: layout)
619
+ } else {
620
+ VStack(alignment: .leading, spacing: 8) {
621
+ Text(entry.data.title).font(.headline)
622
+ Text(entry.data.value).font(.title2).bold()
623
+ Text(entry.data.subtitle).font(.caption)
624
+ }
625
+ }
470
626
  }
471
627
  .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
472
628
  .containerBackground(.fill.tertiary, for: .widget)
@@ -480,53 +636,78 @@ struct OneWidget: Widget {
480
636
  struct OneLiveActivity: Widget {
481
637
  var body: some WidgetConfiguration {
482
638
  ActivityConfiguration(for: OneWidgetContract.Attributes.self) { context in
483
- HStack {
484
- VStack(alignment: .leading) {
485
- Text(context.attributes.title).font(.headline)
486
- Text(context.state.status)
639
+ Group {
640
+ if let layout = oneDecode(context.state.layout, as: OneActivityView.self) {
641
+ OneWidgetRendered(node: layout.lockScreen)
642
+ } else {
643
+ HStack {
644
+ VStack(alignment: .leading) {
645
+ Text(context.attributes.title).font(.headline)
646
+ Text(context.state.status)
647
+ }
648
+ Spacer()
649
+ Text(context.state.value).bold()
650
+ }
487
651
  }
488
- Spacer()
489
- Text(context.state.value).bold()
490
652
  }
491
653
  .padding()
492
654
  .activityBackgroundTint(.blue.opacity(0.2))
493
655
  } dynamicIsland: { context in
494
656
  DynamicIsland {
495
- DynamicIslandExpandedRegion(.leading) { Text(context.attributes.title) }
496
- DynamicIslandExpandedRegion(.trailing) { Text(context.state.value) }
497
- DynamicIslandExpandedRegion(.bottom) { Text(context.state.status) }
657
+ DynamicIslandExpandedRegion(.leading) {
658
+ if let layout = oneDecode(context.state.layout, as: OneActivityView.self),
659
+ let leading = layout.expandedLeading {
660
+ OneWidgetRendered(node: leading)
661
+ } else {
662
+ Text(context.attributes.title)
663
+ }
664
+ }
665
+ DynamicIslandExpandedRegion(.trailing) {
666
+ if let layout = oneDecode(context.state.layout, as: OneActivityView.self),
667
+ let trailing = layout.expandedTrailing {
668
+ OneWidgetRendered(node: trailing)
669
+ } else {
670
+ Text(context.state.value)
671
+ }
672
+ }
673
+ DynamicIslandExpandedRegion(.bottom) {
674
+ if let layout = oneDecode(context.state.layout, as: OneActivityView.self) {
675
+ OneWidgetRendered(node: layout.expandedBottom ?? layout.lockScreen)
676
+ } else {
677
+ Text(context.state.status)
678
+ }
679
+ }
498
680
  } compactLeading: {
499
- Text(context.attributes.title)
681
+ if let layout = oneDecode(context.state.layout, as: OneActivityView.self),
682
+ let leading = layout.compactLeading {
683
+ OneWidgetRendered(node: leading)
684
+ } else {
685
+ Text(context.attributes.title)
686
+ }
500
687
  } compactTrailing: {
501
- Text(context.state.value)
688
+ if let layout = oneDecode(context.state.layout, as: OneActivityView.self),
689
+ let trailing = layout.compactTrailing {
690
+ OneWidgetRendered(node: trailing)
691
+ } else {
692
+ Text(context.state.value)
693
+ }
502
694
  } minimal: {
503
- Text(context.state.value)
695
+ if let layout = oneDecode(context.state.layout, as: OneActivityView.self),
696
+ let minimal = layout.minimal {
697
+ OneWidgetRendered(node: minimal)
698
+ } else {
699
+ Text(context.state.value)
700
+ }
504
701
  }
505
702
  }
506
703
  }
507
704
  }
508
705
 
509
- ${widgets.jsx ? `struct OneJSXWidget: Widget {
510
- private let widgetId = ${JSON.stringify(widgets.jsx.id)}
511
-
512
- var body: some WidgetConfiguration {
513
- StaticConfiguration(kind: "Voltra_Widget_${widgets.jsx.id}", provider: VoltraHomeWidgetProvider(widgetId: widgetId)) { entry in
514
- VoltraHomeWidgetView(entry: entry)
515
- }
516
- .configurationDisplayName(${JSON.stringify(widgets.jsx.displayName)})
517
- .description(${JSON.stringify(widgets.jsx.description)})
518
- .supportedFamilies([.systemSmall, .systemMedium])
519
- .contentMarginsDisabled()
520
- }
521
- }
522
- ` : ""}
523
-
524
706
  @main
525
707
  struct OneWidgetsBundle: WidgetBundle {
526
708
  var body: some Widget {
527
709
  OneWidget()
528
710
  OneLiveActivity()
529
- ${widgets.jsx ? "OneJSXWidget()\n VoltraWidget()" : ""}
530
711
  }
531
712
  }
532
713
  `);
@@ -535,8 +716,11 @@ struct OneWidgetsBundle: WidgetBundle {
535
716
 
536
717
  @interface RCT_EXTERN_MODULE(OneWidgetsBridge, RCTEventEmitter)
537
718
  RCT_EXTERN_METHOD(writeWidget:(NSString *)title value:(NSString *)value subtitle:(NSString *)subtitle resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
719
+ RCT_EXTERN_METHOD(writeView:(NSString *)layout resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
538
720
  RCT_EXTERN_METHOD(start:(NSString *)title status:(NSString *)status value:(NSString *)value push:(BOOL)push resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
721
+ RCT_EXTERN_METHOD(startView:(NSString *)title layout:(NSString *)layout push:(BOOL)push resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
539
722
  RCT_EXTERN_METHOD(update:(NSString *)identifier status:(NSString *)status value:(NSString *)value resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
723
+ RCT_EXTERN_METHOD(updateView:(NSString *)identifier layout:(NSString *)layout resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
540
724
  RCT_EXTERN_METHOD(end:(NSString *)identifier resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
541
725
  RCT_EXTERN_METHOD(pushToken:(NSString *)identifier resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
542
726
  @end
@@ -583,7 +767,24 @@ class OneWidgetsBridge: RCTEventEmitter {
583
767
  return
584
768
  }
585
769
  do {
586
- defaults.set(try JSONEncoder().encode(OneWidgetContract.Data(title: title, value: value, subtitle: subtitle)),
770
+ defaults.set(try JSONEncoder().encode(OneWidgetContract.Data(title: title, value: value, subtitle: subtitle, layout: nil)),
771
+ forKey: OneWidgetContract.dataKey)
772
+ WidgetCenter.shared.reloadTimelines(ofKind: OneWidgetContract.kind)
773
+ resolve(nil)
774
+ } catch {
775
+ reject("widget_write", error.localizedDescription, error)
776
+ }
777
+ }
778
+
779
+ @objc(writeView:resolver:rejecter:)
780
+ func writeView(_ layout: String, resolver resolve: RCTPromiseResolveBlock,
781
+ rejecter reject: RCTPromiseRejectBlock) {
782
+ guard let defaults = UserDefaults(suiteName: OneWidgetContract.appGroup) else {
783
+ reject("app_group", "Cannot open the configured App Group", nil)
784
+ return
785
+ }
786
+ do {
787
+ defaults.set(try JSONEncoder().encode(OneWidgetContract.Data(title: "", value: "", subtitle: "", layout: layout)),
587
788
  forKey: OneWidgetContract.dataKey)
588
789
  WidgetCenter.shared.reloadTimelines(ofKind: OneWidgetContract.kind)
589
790
  resolve(nil)
@@ -602,7 +803,27 @@ class OneWidgetsBridge: RCTEventEmitter {
602
803
  do {
603
804
  let activity = try Activity<OneWidgetContract.Attributes>.request(
604
805
  attributes: .init(title: title),
605
- content: .init(state: .init(status: status, value: value), staleDate: nil),
806
+ content: .init(state: .init(status: status, value: value, layout: nil), staleDate: nil),
807
+ pushType: push ? .token : nil
808
+ )
809
+ observeToken(activity)
810
+ resolve(activity.id)
811
+ } catch {
812
+ reject("activity_start", error.localizedDescription, error)
813
+ }
814
+ }
815
+
816
+ @objc(startView:layout:push:resolver:rejecter:)
817
+ func startView(_ title: String, layout: String, push: Bool,
818
+ resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) {
819
+ guard ActivityAuthorizationInfo().areActivitiesEnabled else {
820
+ reject("activities_disabled", "Live Activities are disabled", nil)
821
+ return
822
+ }
823
+ do {
824
+ let activity = try Activity<OneWidgetContract.Attributes>.request(
825
+ attributes: .init(title: title),
826
+ content: .init(state: .init(status: "", value: "", layout: layout), staleDate: nil),
606
827
  pushType: push ? .token : nil
607
828
  )
608
829
  observeToken(activity)
@@ -620,7 +841,20 @@ class OneWidgetsBridge: RCTEventEmitter {
620
841
  return
621
842
  }
622
843
  Task {
623
- await activity.update(.init(state: .init(status: status, value: value), staleDate: nil))
844
+ await activity.update(.init(state: .init(status: status, value: value, layout: nil), staleDate: nil))
845
+ resolve(nil)
846
+ }
847
+ }
848
+
849
+ @objc(updateView:layout:resolver:rejecter:)
850
+ func updateView(_ identifier: String, layout: String,
851
+ resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
852
+ guard let activity = Activity<OneWidgetContract.Attributes>.activities.first(where: { $0.id == identifier }) else {
853
+ reject("activity_missing", "Live Activity not found", nil)
854
+ return
855
+ }
856
+ Task {
857
+ await activity.update(.init(state: .init(status: "", value: "", layout: layout), staleDate: nil))
624
858
  resolve(nil)
625
859
  }
626
860
  }
@@ -646,7 +880,11 @@ class OneWidgetsBridge: RCTEventEmitter {
646
880
  reject("activity_missing", "Live Activity not found", nil)
647
881
  return
648
882
  }
649
- resolve(activity.pushToken?.map { String(format: "%02x", $0) }.joined())
883
+ if let data = activity.pushToken {
884
+ resolve(data.map { String(format: "%02x", $0) }.joined())
885
+ } else {
886
+ resolve(NSNull())
887
+ }
650
888
  }
651
889
  }
652
890
  `);
@@ -869,13 +1107,6 @@ ${schemes.map((scheme) => ` <string>${scheme}</string>`).join("\n")}
869
1107
  }
870
1108
  if (app.ios?.widgets) {
871
1109
  stamps.push(" <key>NSSupportsLiveActivities</key>\n <true/>");
872
- if (app.ios.widgets.jsx) {
873
- stamps.push(` <key>Voltra_AppGroupIdentifier</key>
874
- <string>${escapeXml(app.ios.widgets.appGroup)}</string>`);
875
- if (app.ios.widgets.pushNotifications) {
876
- stamps.push(" <key>Voltra_EnablePushNotifications</key>\n <true/>");
877
- }
878
- }
879
1110
  }
880
1111
  if (stamps.length) {
881
1112
  const anchor = " <key>LSRequiresIPhoneOS</key>";
@@ -1000,7 +1231,7 @@ end`);
1000
1231
  if (platform === "ios" && relativePath.endsWith(".xcodeproj/project.pbxproj")) {
1001
1232
  rendered = patchIosBundlePhase(rendered);
1002
1233
  rendered = patchIosPbxprojSceneDelegate(rendered, appName);
1003
- if (app.notifications?.push === true) {
1234
+ if (app.notifications?.push === true && !app.ios?.widgets) {
1004
1235
  rendered = patchIosPbxprojPushEntitlements(rendered, appName);
1005
1236
  }
1006
1237
  if (app.ios?.widgets) rendered = patchIosPbxprojWidgets(rendered, app);
@@ -1019,16 +1250,6 @@ use_frameworks! :linkage => :${app.ios.useFrameworks}`);
1019
1250
  rendered = nativeProjectPatches.injectOneSwiftPackagesIntoPodfile(rendered);
1020
1251
  if (nitroWebImage) rendered = nativeProjectPatches.injectNitroWebImageModularHeaderIntoPodfile(rendered);
1021
1252
  rendered = nativeProjectPatches.injectHermesMinificationPatchIntoPodfile(rendered);
1022
- if (app.ios?.widgets?.jsx) {
1023
- rendered += `
1024
- # jsx widgets use Voltra's SwiftUI renderer in One's generated extension
1025
- target 'OneWidgets' do
1026
- client = \`node --print "require.resolve('@use-voltra/ios-client/package.json', {paths: ['#{Pod::Config.instance.installation_root}/..']})"\`.strip
1027
- raise 'Install @use-voltra/ios-client to build the JSX widget' if client.empty?
1028
- pod 'VoltraWidget', :path => File.join(File.dirname(client), 'ios')
1029
- end
1030
- `;
1031
- }
1032
1253
  if (!rendered.includes("[vxrn/one] fmt c++17 fix") || !rendered.includes("[vxrn/one] minify iOS Hermes Release bundle input")) {
1033
1254
  throw new Error("[vxrn] failed to apply required iOS Podfile patches");
1034
1255
  }