@breakside/jskit 2024.6.0 → 2024.8.0

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.
Files changed (48) hide show
  1. package/Frameworks/DOM.jsframework/Info.json +2 -2
  2. package/Frameworks/DOM.jsframework/io.breakside.JSKit.DOM-bundle.js +2 -2
  3. package/Frameworks/FontKit.jsframework/Info.json +2 -2
  4. package/Frameworks/FontKit.jsframework/io.breakside.JSKit.FontKit-bundle.js +2 -2
  5. package/Frameworks/Foundation.jsframework/Info.json +2 -2
  6. package/Frameworks/Foundation.jsframework/JS/JSCalendar.js +93 -0
  7. package/Frameworks/Foundation.jsframework/JS/JSDateFormatter.js +1 -3
  8. package/Frameworks/Foundation.jsframework/JS/JSLocale.js +13 -1
  9. package/Frameworks/Foundation.jsframework/JS/JSTimeZone.js +72 -3
  10. package/Frameworks/Foundation.jsframework/io.breakside.JSKit.Foundation-bundle.js +2 -2
  11. package/Frameworks/Foundation.jsframework/sources.json +6 -6
  12. package/Frameworks/SecurityKit.jsframework/Info.json +2 -2
  13. package/Frameworks/SecurityKit.jsframework/io.breakside.JSKit.SecurityKit-bundle.js +2 -2
  14. package/Info.json +2 -2
  15. package/Node/io.breakside.jskit-bundle.js +2 -2
  16. package/Node/jskit +2 -2
  17. package/Root/Frameworks/APIKit/Info.yaml +1 -1
  18. package/Root/Frameworks/APIKitTesting/Info.yaml +1 -1
  19. package/Root/Frameworks/AuthKit/Info.yaml +1 -1
  20. package/Root/Frameworks/CSSOM/Info.yaml +1 -1
  21. package/Root/Frameworks/ChartKit/Info.yaml +1 -1
  22. package/Root/Frameworks/ConferenceKit/Info.yaml +1 -1
  23. package/Root/Frameworks/DBKit/Info.yaml +1 -1
  24. package/Root/Frameworks/DOM/Info.yaml +1 -1
  25. package/Root/Frameworks/Dispatch/Info.yaml +1 -1
  26. package/Root/Frameworks/FontKit/Info.yaml +1 -1
  27. package/Root/Frameworks/Foundation/Info.yaml +1 -1
  28. package/Root/Frameworks/Foundation/JSCalendar.js +93 -0
  29. package/Root/Frameworks/Foundation/JSDateFormatter.js +1 -3
  30. package/Root/Frameworks/Foundation/JSLocale.js +13 -1
  31. package/Root/Frameworks/Foundation/JSTimeZone.js +72 -3
  32. package/Root/Frameworks/ImageKit/Info.yaml +1 -1
  33. package/Root/Frameworks/MediaKit/Info.yaml +1 -1
  34. package/Root/Frameworks/MediaKitUI/Info.yaml +1 -1
  35. package/Root/Frameworks/NotificationKit/Info.yaml +1 -1
  36. package/Root/Frameworks/PDFKit/Info.yaml +1 -1
  37. package/Root/Frameworks/QRKit/Info.yaml +1 -1
  38. package/Root/Frameworks/SearchKit/Info.yaml +1 -1
  39. package/Root/Frameworks/SecurityKit/Info.yaml +1 -1
  40. package/Root/Frameworks/ServerKit/Info.yaml +1 -1
  41. package/Root/Frameworks/ServerKitTesting/Info.yaml +1 -1
  42. package/Root/Frameworks/TestKit/Info.yaml +1 -1
  43. package/Root/Frameworks/UIKit/Info.yaml +1 -1
  44. package/Root/Frameworks/UIKit/UIApplication.js +16 -0
  45. package/Root/Frameworks/UIKit/UISplitViewController.js +31 -8
  46. package/Root/Frameworks/UIKitTesting/Info.yaml +1 -1
  47. package/Root/Frameworks/UIKitTesting/UIMockApplication.js +2 -0
  48. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "JSBundleType": "framework",
3
3
  "JSBundleIdentifier": "io.breakside.JSKit.DOM",
4
- "JSBundleVersion": "2024.6.0",
4
+ "JSBundleVersion": "2024.8.0",
5
5
  "JSDevelopmentLanguage": "en",
6
6
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
7
7
  "JSBundleEnvironments": {
@@ -9,5 +9,5 @@
9
9
  "node": "DOM+Node.js"
10
10
  },
11
11
  "JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
12
- "GitRevision": "3aecdc11b14a3dbba2028fb148aa9affeb3663b7"
12
+ "GitRevision": "51915bebbceaeb8c5ff390887b1d22da05bfed3a"
13
13
  }
@@ -3,7 +3,7 @@ JSBundle.bundles['io.breakside.JSKit.DOM'] = {
3
3
  "Info": {
4
4
  "JSBundleType": "framework",
5
5
  "JSBundleIdentifier": "io.breakside.JSKit.DOM",
6
- "JSBundleVersion": "2024.6.0",
6
+ "JSBundleVersion": "2024.8.0",
7
7
  "JSDevelopmentLanguage": "en",
8
8
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
9
9
  "JSBundleEnvironments": {
@@ -11,7 +11,7 @@ JSBundle.bundles['io.breakside.JSKit.DOM'] = {
11
11
  "node": "DOM+Node.js"
12
12
  },
13
13
  "JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
14
- "GitRevision": "3aecdc11b14a3dbba2028fb148aa9affeb3663b7"
14
+ "GitRevision": "51915bebbceaeb8c5ff390887b1d22da05bfed3a"
15
15
  },
16
16
  "Resources": [],
17
17
  "ResourceLookup": {
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "JSBundleType": "framework",
3
3
  "JSBundleIdentifier": "io.breakside.JSKit.FontKit",
4
- "JSBundleVersion": "2024.6.0",
4
+ "JSBundleVersion": "2024.8.0",
5
5
  "JSDevelopmentLanguage": "en",
6
6
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
7
7
  "JSBundleEnvironments": {
8
8
  "html": "FontKit+HTML.js"
9
9
  },
10
10
  "JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
11
- "GitRevision": "3aecdc11b14a3dbba2028fb148aa9affeb3663b7"
11
+ "GitRevision": "51915bebbceaeb8c5ff390887b1d22da05bfed3a"
12
12
  }
@@ -3,14 +3,14 @@ JSBundle.bundles['io.breakside.JSKit.FontKit'] = {
3
3
  "Info": {
4
4
  "JSBundleType": "framework",
5
5
  "JSBundleIdentifier": "io.breakside.JSKit.FontKit",
6
- "JSBundleVersion": "2024.6.0",
6
+ "JSBundleVersion": "2024.8.0",
7
7
  "JSDevelopmentLanguage": "en",
8
8
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
9
9
  "JSBundleEnvironments": {
10
10
  "html": "FontKit+HTML.js"
11
11
  },
12
12
  "JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
13
- "GitRevision": "3aecdc11b14a3dbba2028fb148aa9affeb3663b7"
13
+ "GitRevision": "51915bebbceaeb8c5ff390887b1d22da05bfed3a"
14
14
  },
15
15
  "Resources": [],
16
16
  "ResourceLookup": {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "JSBundleType": "framework",
3
3
  "JSBundleIdentifier": "io.breakside.JSKit.Foundation",
4
- "JSBundleVersion": "2024.6.0",
4
+ "JSBundleVersion": "2024.8.0",
5
5
  "JSDevelopmentLanguage": "en",
6
6
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
7
7
  "JSBundleEnvironments": {
@@ -9,5 +9,5 @@
9
9
  "node": "Foundation+Node.js"
10
10
  },
11
11
  "JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
12
- "GitRevision": "3aecdc11b14a3dbba2028fb148aa9affeb3663b7"
12
+ "GitRevision": "51915bebbceaeb8c5ff390887b1d22da05bfed3a"
13
13
  }
@@ -40,6 +40,11 @@ JSClass("JSCalendar", JSObject, {
40
40
  return JSTimeZone.local;
41
41
  },
42
42
 
43
+ setTimezone: function(timezone){
44
+ this._timezone = timezone;
45
+ this.timeZoneChanged();
46
+ },
47
+
43
48
  componentsFromDate: function(units, date, timezone){
44
49
  },
45
50
 
@@ -50,6 +55,93 @@ JSClass("JSCalendar", JSObject, {
50
55
  },
51
56
 
52
57
  dateByAddingComponents: function(addedComponents, toDate){
58
+ },
59
+
60
+ dateChangeTimer: null,
61
+ notificationCenters: null,
62
+ notificationObservers: null,
63
+
64
+ stopSendingNotifications: function(notificationCenter){
65
+ if (this.notificationCenters === null){
66
+ return;
67
+ }
68
+ var i = this.notificationCenters.indexOf(notificationCenter);
69
+ if (i >= 0){
70
+ var observers = this.notificationObservers[i];
71
+ for (var name in observers){
72
+ notificationCenter.removeObserver(name, observers[name]);
73
+ }
74
+ this.notificationCenters.splice(i, 1);
75
+ this.notificationObservers.splice(i, 1);
76
+ }
77
+ if (this.notificationCenters.length === 0){
78
+ this.cancelDayChangeTimer();
79
+ }
80
+ },
81
+
82
+ startSendingNotifications: function(notificationCenter){
83
+ if (this.notificationCenters === null){
84
+ this.notificationCenters = [];
85
+ this.notificationObservers = [];
86
+ }
87
+ var i = this.notificationCenters.indexOf(notificationCenter);
88
+ if (i < 0){
89
+ this.notificationCenters.push(notificationCenter);
90
+ this.notificationObservers.push({
91
+ JSLocalTimeZoneChanged: notificationCenter.addObserver("JSLocalTimeZoneChanged", null, this.timeZoneChanged, this)
92
+ });
93
+ if (this.notificationCenters.length === 1){
94
+ this.scheduleDayChangeTimer();
95
+ }
96
+ }
97
+ },
98
+
99
+ dayChangeTimer: null,
100
+ lastKnownDayComponents: null,
101
+
102
+ cancelDayChangeTimer: function(){
103
+ if (this.dayChangeTimer !== null){
104
+ this.dayChangeTimer.invalidate();
105
+ this.dayChangeTimer = null;
106
+ }
107
+ },
108
+
109
+ scheduleDayChangeTimer: function(){
110
+ this.cancelDayChangeTimer();
111
+ var now = JSDate.now;
112
+ var todayComponents = this.componentsFromDate(JSCalendar.Unit.date, now);
113
+ if (this.lastKnownDayComponents !== null){
114
+ if (todayComponents.year !== this.lastKnownDayComponents.year || todayComponents.month !== this.lastKnownDayComponents.month || todayComponents.day !== this.lastKnownDayComponents.day){
115
+ if (this.notificationCenters !== null){
116
+ var i, l;
117
+ for (i = 0, l = this.notificationCenters.length; i < l; ++i){
118
+ this.notificationCenters[i].post("JSCalendarDayChanged", null, {calendar: this, dayComponents: JSCopy(todayComponents)});
119
+ }
120
+ }
121
+ }
122
+ }
123
+ var tomorrowComponents = this.componentsFromDate(JSCalendar.Unit.date, this.dateByAddingComponents({day: 1}, now));
124
+ var tomorrow = this.dateFromComponents(tomorrowComponents);
125
+ var interval = now.timeIntervalUntilDate(tomorrow);
126
+ this.lastKnownDayComponents = todayComponents;
127
+ this.dateChangeTimer = JSTimer.scheduledTimerWithInterval(interval + 1, this.scheduleDayChangeTimer, this);
128
+ },
129
+
130
+ timeZoneChanged: function(){
131
+ if (this.notificationCenters !== null && this.notificationCenters.length > 0){
132
+ this.scheduleDayChangeTimer();
133
+ }
134
+ },
135
+
136
+ componentsFromComponents: function(units, otherComponents){
137
+ var otherCalendar = otherComponents.calendar || this;
138
+ if (otherCalendar.identifier === this.identifier){
139
+ if (otherCalendar.timezone.identifier === this.identifier){
140
+ return otherComponents;
141
+ }
142
+ }
143
+ var date = otherCalendar.dateFromComponents(otherComponents);
144
+ return this.componentsFromDate(units, date);
53
145
  }
54
146
 
55
147
  });
@@ -709,6 +801,7 @@ JSCalendar.Unit.difference =
709
801
  JSCalendar.Unit.second |
710
802
  JSCalendar.Unit.millisecond;
711
803
 
804
+ JSCalendar.Unit.date = JSCalendar.Unit.year | JSCalendar.Unit.month | JSCalendar.Unit.day;
712
805
 
713
806
  var monthsPerYear = 12;
714
807
  var minutesPerHour = 60;
@@ -80,17 +80,15 @@ JSClass("JSDateFormatter", JSObject, {
80
80
 
81
81
  setLocale: function(locale){
82
82
  this._locale = locale;
83
- this._localeCalendar = JSCalendar.initWithIdentifier(locale.calendarIdentifier);
84
83
  },
85
84
 
86
85
  calendar: JSDynamicProperty('_calendar', null),
87
- _localeCalendar: null,
88
86
 
89
87
  getCalendar: function(){
90
88
  if (this._calendar !== null){
91
89
  return this._calendar;
92
90
  }
93
- return this._localeCalendar;
91
+ return this._locale.calendar;
94
92
  },
95
93
 
96
94
  timezone: JSDynamicProperty('_timezone', null),
@@ -373,6 +373,10 @@ JSClass("JSLocale", JSObject, {
373
373
 
374
374
  calendarIdentifier: JSReadOnlyProperty('_calendarIdentifier', JSCalendar.Identifier.gregorian),
375
375
 
376
+ calendar: JSLazyInitProperty(function(){
377
+ return JSCalendar.initWithIdentifier(this.calendarIdentifier);
378
+ }),
379
+
376
380
  dateFormatForTemplate: function(template){
377
381
  return this._dateFormatsByTemplate[template] || null;
378
382
  },
@@ -410,6 +414,7 @@ JSClass("JSLocale", JSObject, {
410
414
  this._dateFormatsByTemplate.MMMMd = "MMMM d";
411
415
  this._dateFormatsByTemplate.hms = "h:mm:ss a";
412
416
  this._dateFormatsByTemplate.hm = "h:mm a";
417
+ this._dateFormatsByTemplate.hmz = "h:mm a z";
413
418
  this._dateFormatsByTemplate.Hms = "HH:mm:ss";
414
419
  this._dateFormatsByTemplate.Hm = "HH:mm";
415
420
  return;
@@ -556,7 +561,13 @@ JSClass("JSLocale", JSObject, {
556
561
  }else if (part.type === "dayPeriod"){
557
562
  format += "a";
558
563
  }else if (part.type === "timeZoneName"){
559
- if (part.value.length > 4){
564
+ if (part.value.startsWith("GMT-") || part.value.startsWith("GMT+")){
565
+ if (part.value.indexOf(":") >= 0){
566
+ format += "OOOO";
567
+ }else{
568
+ format += "O";
569
+ }
570
+ }else if (part.value.length > 4){
560
571
  format += "zzzz";
561
572
  }else{
562
573
  format += "z";
@@ -606,6 +617,7 @@ JSClass("JSLocale", JSObject, {
606
617
  "MMMMd": unicodeFormatForOptions({month: "long", day: "numeric"}),
607
618
  "hms": unicodeFormatForOptions({hour: "numeric", minute: "numeric", second: "numeric"}),
608
619
  "hm": unicodeFormatForOptions({hour: "numeric", minute: "numeric"}),
620
+ "hmz": unicodeFormatForOptions({hour: "numeric", minute: "numeric", timeZoneName: "short"}),
609
621
  "Hms": unicodeFormatForOptions({hour: "numeric", minute: "numeric", second: "numeric", hour12: false}),
610
622
  "Hm": unicodeFormatForOptions({hour: "numeric", minute: "numeric", hour12: false}),
611
623
  };
@@ -16,6 +16,8 @@
16
16
  // #import "JSObject.js"
17
17
  // #import "JSDate.js"
18
18
  // #import "JSBinarySearcher.js"
19
+ // #import "JSTimer.js"
20
+ // #import "JSTimeInterval.js"
19
21
  // #feature Intl
20
22
  /* global JSGregorianCalendar, Intl, DataView */
21
23
  'use strict';
@@ -533,11 +535,77 @@ JSClass("JSTimeZone", JSObject, {
533
535
 
534
536
  });
535
537
 
538
+ JSTimeZone.changeLocalTimeZoneToSystem = function(){
539
+ if (JSTimeZone.localFollowsSystem){
540
+ return;
541
+ }
542
+ JSTimeZone.localFollowsSystem = true;
543
+ JSTimeZone._changeLocalTimeZone(JSTimeZone.systemTimeZoneIdentifier);
544
+ if (JSTimeZone.notificationCenters.length > 0){
545
+ JSTimeZone.scheduleSystemIdentifierWatchTimer();
546
+ }
547
+ };
548
+
536
549
  JSTimeZone.changeLocalTimeZone = function(identifier){
537
- localIdentifier = identifier;
538
- Object.defineProperty(JSTimeZone, 'local', defaultLocalProperty);
550
+ JSTimeZone.cancelSystemIdentifierWatchTimer();
551
+ JSTimeZone.localFollowsSystem = false;
552
+ JSTimeZone._changeLocalTimeZone(identifier);
539
553
  };
540
554
 
555
+ JSTimeZone._changeLocalTimeZone = function(identifier){
556
+ if (identifier !== localIdentifier){
557
+ localIdentifier = identifier;
558
+ Object.defineProperty(JSTimeZone, 'local', defaultLocalProperty);
559
+ var i, l;
560
+ for (i = 0, l = JSTimeZone.notificationCenters.length; i < l; ++i){
561
+ JSTimeZone.notificationCenters[i].post("JSLocalTimeZoneChanged", null);
562
+ }
563
+ }
564
+ };
565
+
566
+ JSTimeZone.startSendingNotifications = function(notificationCenter){
567
+ var i = JSTimeZone.notificationCenters.indexOf(notificationCenter);
568
+ if (i < 0){
569
+ JSTimeZone.notificationCenters.push(notificationCenter);
570
+ }
571
+ if (JSTimeZone.localFollowsSystem){
572
+ JSTimeZone.scheduleSystemIdentifierWatchTimer();
573
+ }
574
+ };
575
+
576
+ JSTimeZone.scheduleSystemIdentifierWatchTimer = function(){
577
+ if (JSTimeZone.systemIdentifierWatchTimer === null){
578
+ var previousSystemTimeZoneIdentifier = JSTimeZone.systemTimeZoneIdentifier;
579
+ JSTimeZone.systemIdentifierWatchTimer = JSTimer.scheduledRepeatingTimerWithInterval(JSTimeInterval.minutes(1), function(){
580
+ if (JSTimeZone.systemTimeZoneIdentifier !== previousSystemTimeZoneIdentifier){
581
+ previousSystemTimeZoneIdentifier = JSTimeZone.systemTimeZoneIdentifier;
582
+ JSTimeZone._changeLocalTimeZone(JSTimeZone.systemTimeZoneIdentifier);
583
+ }
584
+ });
585
+ }
586
+ };
587
+
588
+ JSTimeZone.cancelSystemIdentifierWatchTimer = function(){
589
+ if (JSTimeZone.systemIdentifierWatchTimer !== null){
590
+ JSTimeZone.systemIdentifierWatchTimer.invalidate();
591
+ JSTimeZone.systemIdentifierWatchTimer = null;
592
+ }
593
+ };
594
+
595
+ JSTimeZone.stopSendingNotifications = function(notificationCenter){
596
+ var i = JSTimeZone.notificationCenters.indexOf(notificationCenter);
597
+ if (i >= 0){
598
+ JSTimeZone.notificationCenters.splice(i, 1);
599
+ }
600
+ if (JSTimeZone.notificationCenters.length === 0){
601
+ JSTimeZone.cancelSystemIdentifierWatchTimer();
602
+ }
603
+ };
604
+
605
+ JSTimeZone.localFollowsSystem = true;
606
+ JSTimeZone.systemIdentifierWatchTimer = null;
607
+ JSTimeZone.notificationCenters = [];
608
+
541
609
  var defaultLocalProperty = {
542
610
  configurable: true,
543
611
  get: function JSTimeZone_getLocal(){
@@ -578,6 +646,7 @@ Object.defineProperties(JSTimeZone, {
578
646
  configurable: true,
579
647
  get: function JSTimeZone_getUTC(){
580
648
  var timezone = JSTimeZone.initWithTimeIntervalFromUTC(0, 'UTC');
649
+ timezone._identifier = "UTC";
581
650
  Object.defineProperty(JSTimeZone, 'utc', {configurable: false, value: timezone});
582
651
  return timezone;
583
652
  }
@@ -601,7 +670,7 @@ JSTimeZone.importZoneInfo = function(info){
601
670
  JSTimeZone.clearZoneInfo = function(info){
602
671
  zoneinfo = emptyZoneInfo;
603
672
  Object.defineProperty(JSTimeZone, 'knownTimeZoneIdentifiers', defaultKnownIdentifiersProperty);
604
- JSTimeZone.changeLocalTimeZone(JSTimeZone.systemTimeZoneIdentifier);
673
+ JSTimeZone.changeLocalTimeZoneToSystem();
605
674
  };
606
675
 
607
676
  JSTimeZone.rulesFromPOSIXString = function(str){
@@ -3,7 +3,7 @@ JSBundle.bundles['io.breakside.JSKit.Foundation'] = {
3
3
  "Info": {
4
4
  "JSBundleType": "framework",
5
5
  "JSBundleIdentifier": "io.breakside.JSKit.Foundation",
6
- "JSBundleVersion": "2024.6.0",
6
+ "JSBundleVersion": "2024.8.0",
7
7
  "JSDevelopmentLanguage": "en",
8
8
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
9
9
  "JSBundleEnvironments": {
@@ -11,7 +11,7 @@ JSBundle.bundles['io.breakside.JSKit.Foundation'] = {
11
11
  "node": "Foundation+Node.js"
12
12
  },
13
13
  "JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
14
- "GitRevision": "3aecdc11b14a3dbba2028fb148aa9affeb3663b7"
14
+ "GitRevision": "51915bebbceaeb8c5ff390887b1d22da05bfed3a"
15
15
  },
16
16
  "Resources": [
17
17
  {
@@ -32,8 +32,9 @@
32
32
  "JSLog.js",
33
33
  "JSObjectGraph.js",
34
34
  "JSDate.js",
35
- "JSTimeZone.js",
35
+ "JSTimer.js",
36
36
  "JSTimeInterval.js",
37
+ "JSTimeZone.js",
37
38
  "JSCalendar.js",
38
39
  "JSLocale.js",
39
40
  "JSMediaType.js",
@@ -75,7 +76,6 @@
75
76
  "JSTextContainer.js",
76
77
  "JSTextLayoutManagerDelegate.js",
77
78
  "JSTextStorage.js",
78
- "JSTimer.js",
79
79
  "JSRunLoop.js",
80
80
  "JSIPAddress.js",
81
81
  "JSURLSessionTask.js",
@@ -118,10 +118,10 @@
118
118
  "Object.defineProperty",
119
119
  "Object.getPrototypeOf",
120
120
  "Object.prototype.hasOwnProperty",
121
- "Intl",
122
- "Uint32Array",
123
121
  "setTimeout",
124
122
  "setInterval",
123
+ "Intl",
124
+ "Uint32Array",
125
125
  "ArrayBuffer",
126
126
  "Uint8Array"
127
127
  ],
@@ -170,8 +170,9 @@
170
170
  "JSObjectGraphLoading",
171
171
  "JSObjectGraph",
172
172
  "JSDate",
173
- "JSTimeZone",
173
+ "JSTimer",
174
174
  "JSTimeInterval",
175
+ "JSTimeZone",
175
176
  "JSCalendar",
176
177
  "JSGregorianCalendar",
177
178
  "JSLocale",
@@ -240,7 +241,6 @@
240
241
  "JSTextContainer",
241
242
  "JSTextLayoutManagerDelegate",
242
243
  "JSTextStorage",
243
- "JSTimer",
244
244
  "JSRunLoop",
245
245
  "JSIPAddress",
246
246
  "JSURLSessionTask",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "JSBundleType": "framework",
3
3
  "JSBundleIdentifier": "io.breakside.JSKit.SecurityKit",
4
- "JSBundleVersion": "2024.6.0",
4
+ "JSBundleVersion": "2024.8.0",
5
5
  "JSDevelopmentLanguage": "en",
6
6
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
7
7
  "JSBundleEnvironments": {
@@ -9,5 +9,5 @@
9
9
  "node": "SecurityKit+Node.js"
10
10
  },
11
11
  "JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
12
- "GitRevision": "3aecdc11b14a3dbba2028fb148aa9affeb3663b7"
12
+ "GitRevision": "51915bebbceaeb8c5ff390887b1d22da05bfed3a"
13
13
  }
@@ -3,7 +3,7 @@ JSBundle.bundles['io.breakside.JSKit.SecurityKit'] = {
3
3
  "Info": {
4
4
  "JSBundleType": "framework",
5
5
  "JSBundleIdentifier": "io.breakside.JSKit.SecurityKit",
6
- "JSBundleVersion": "2024.6.0",
6
+ "JSBundleVersion": "2024.8.0",
7
7
  "JSDevelopmentLanguage": "en",
8
8
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
9
9
  "JSBundleEnvironments": {
@@ -11,7 +11,7 @@ JSBundle.bundles['io.breakside.JSKit.SecurityKit'] = {
11
11
  "node": "SecurityKit+Node.js"
12
12
  },
13
13
  "JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
14
- "GitRevision": "3aecdc11b14a3dbba2028fb148aa9affeb3663b7"
14
+ "GitRevision": "51915bebbceaeb8c5ff390887b1d22da05bfed3a"
15
15
  },
16
16
  "Resources": [],
17
17
  "ResourceLookup": {
package/Info.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "JSBundleType": "node",
3
3
  "JSBundleIdentifier": "io.breakside.jskit",
4
- "JSBundleVersion": "2024.6.0",
4
+ "JSBundleVersion": "2024.8.0",
5
5
  "JSExecutableName": "jskit",
6
6
  "NPMOrganization": "breakside",
7
7
  "JSResources": [
8
8
  "Tests/HTMLTestRunner.js",
9
9
  "Tests/NodeTestRunner.js"
10
10
  ],
11
- "GitRevision": "3aecdc11b14a3dbba2028fb148aa9affeb3663b7"
11
+ "GitRevision": "51915bebbceaeb8c5ff390887b1d22da05bfed3a"
12
12
  }
@@ -3,14 +3,14 @@ JSBundle.bundles['io.breakside.jskit'] = {
3
3
  "Info": {
4
4
  "JSBundleType": "node",
5
5
  "JSBundleIdentifier": "io.breakside.jskit",
6
- "JSBundleVersion": "2024.6.0",
6
+ "JSBundleVersion": "2024.8.0",
7
7
  "JSExecutableName": "jskit",
8
8
  "NPMOrganization": "breakside",
9
9
  "JSResources": [
10
10
  "Tests/HTMLTestRunner.js",
11
11
  "Tests/NodeTestRunner.js"
12
12
  ],
13
- "GitRevision": "3aecdc11b14a3dbba2028fb148aa9affeb3663b7"
13
+ "GitRevision": "51915bebbceaeb8c5ff390887b1d22da05bfed3a"
14
14
  },
15
15
  "Resources": [
16
16
  {
package/Node/jskit CHANGED
@@ -33,8 +33,9 @@ require("./../Frameworks/Foundation.jsframework/JS/JSObject.js");
33
33
  require("./../Frameworks/Foundation.jsframework/JS/JSLog.js");
34
34
  require("./../Frameworks/Foundation.jsframework/JS/JSObjectGraph.js");
35
35
  require("./../Frameworks/Foundation.jsframework/JS/JSDate.js");
36
- require("./../Frameworks/Foundation.jsframework/JS/JSTimeZone.js");
36
+ require("./../Frameworks/Foundation.jsframework/JS/JSTimer.js");
37
37
  require("./../Frameworks/Foundation.jsframework/JS/JSTimeInterval.js");
38
+ require("./../Frameworks/Foundation.jsframework/JS/JSTimeZone.js");
38
39
  require("./../Frameworks/Foundation.jsframework/JS/JSCalendar.js");
39
40
  require("./../Frameworks/Foundation.jsframework/JS/JSLocale.js");
40
41
  require("./../Frameworks/Foundation.jsframework/JS/JSMediaType.js");
@@ -76,7 +77,6 @@ require("./../Frameworks/Foundation.jsframework/JS/JSTextFramesetter.js");
76
77
  require("./../Frameworks/Foundation.jsframework/JS/JSTextContainer.js");
77
78
  require("./../Frameworks/Foundation.jsframework/JS/JSTextLayoutManagerDelegate.js");
78
79
  require("./../Frameworks/Foundation.jsframework/JS/JSTextStorage.js");
79
- require("./../Frameworks/Foundation.jsframework/JS/JSTimer.js");
80
80
  require("./../Frameworks/Foundation.jsframework/JS/JSRunLoop.js");
81
81
  require("./../Frameworks/Foundation.jsframework/JS/JSIPAddress.js");
82
82
  require("./../Frameworks/Foundation.jsframework/JS/JSURLSessionTask.js");
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.APIKit
3
- JSBundleVersion: 2024.6.0
3
+ JSBundleVersion: 2024.8.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSIncludeDirectories:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.APIKitTesting
3
- JSBundleVersion: 2024.6.0
3
+ JSBundleVersion: 2024.8.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.AuthKit
3
- JSBundleVersion: 2024.6.0
3
+ JSBundleVersion: 2024.8.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.CSSOM
3
- JSBundleVersion: 2024.6.0
3
+ JSBundleVersion: 2024.8.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.ChartKit
3
- JSBundleVersion: 2024.6.0
3
+ JSBundleVersion: 2024.8.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2021 Breakside Inc.
6
6
  # JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.ConferenceKit
3
- JSBundleVersion: 2024.6.0
3
+ JSBundleVersion: 2024.8.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.DBKit
3
- JSBundleVersion: 2024.6.0
3
+ JSBundleVersion: 2024.8.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.DOM
3
- JSBundleVersion: 2024.6.0
3
+ JSBundleVersion: 2024.8.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.Dispatch
3
- JSBundleVersion: 2024.6.0
3
+ JSBundleVersion: 2024.8.0
4
4
  JSCopyright: Copyright © 2020 Breakside Inc.
5
5
  JSBundleEnvironments:
6
6
  html: Dispatch+HTML.js
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.FontKit
3
- JSBundleVersion: 2024.6.0
3
+ JSBundleVersion: 2024.8.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.Foundation
3
- JSBundleVersion: 2024.6.0
3
+ JSBundleVersion: 2024.8.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -40,6 +40,11 @@ JSClass("JSCalendar", JSObject, {
40
40
  return JSTimeZone.local;
41
41
  },
42
42
 
43
+ setTimezone: function(timezone){
44
+ this._timezone = timezone;
45
+ this.timeZoneChanged();
46
+ },
47
+
43
48
  componentsFromDate: function(units, date, timezone){
44
49
  },
45
50
 
@@ -50,6 +55,93 @@ JSClass("JSCalendar", JSObject, {
50
55
  },
51
56
 
52
57
  dateByAddingComponents: function(addedComponents, toDate){
58
+ },
59
+
60
+ dateChangeTimer: null,
61
+ notificationCenters: null,
62
+ notificationObservers: null,
63
+
64
+ stopSendingNotifications: function(notificationCenter){
65
+ if (this.notificationCenters === null){
66
+ return;
67
+ }
68
+ var i = this.notificationCenters.indexOf(notificationCenter);
69
+ if (i >= 0){
70
+ var observers = this.notificationObservers[i];
71
+ for (var name in observers){
72
+ notificationCenter.removeObserver(name, observers[name]);
73
+ }
74
+ this.notificationCenters.splice(i, 1);
75
+ this.notificationObservers.splice(i, 1);
76
+ }
77
+ if (this.notificationCenters.length === 0){
78
+ this.cancelDayChangeTimer();
79
+ }
80
+ },
81
+
82
+ startSendingNotifications: function(notificationCenter){
83
+ if (this.notificationCenters === null){
84
+ this.notificationCenters = [];
85
+ this.notificationObservers = [];
86
+ }
87
+ var i = this.notificationCenters.indexOf(notificationCenter);
88
+ if (i < 0){
89
+ this.notificationCenters.push(notificationCenter);
90
+ this.notificationObservers.push({
91
+ JSLocalTimeZoneChanged: notificationCenter.addObserver("JSLocalTimeZoneChanged", null, this.timeZoneChanged, this)
92
+ });
93
+ if (this.notificationCenters.length === 1){
94
+ this.scheduleDayChangeTimer();
95
+ }
96
+ }
97
+ },
98
+
99
+ dayChangeTimer: null,
100
+ lastKnownDayComponents: null,
101
+
102
+ cancelDayChangeTimer: function(){
103
+ if (this.dayChangeTimer !== null){
104
+ this.dayChangeTimer.invalidate();
105
+ this.dayChangeTimer = null;
106
+ }
107
+ },
108
+
109
+ scheduleDayChangeTimer: function(){
110
+ this.cancelDayChangeTimer();
111
+ var now = JSDate.now;
112
+ var todayComponents = this.componentsFromDate(JSCalendar.Unit.date, now);
113
+ if (this.lastKnownDayComponents !== null){
114
+ if (todayComponents.year !== this.lastKnownDayComponents.year || todayComponents.month !== this.lastKnownDayComponents.month || todayComponents.day !== this.lastKnownDayComponents.day){
115
+ if (this.notificationCenters !== null){
116
+ var i, l;
117
+ for (i = 0, l = this.notificationCenters.length; i < l; ++i){
118
+ this.notificationCenters[i].post("JSCalendarDayChanged", null, {calendar: this, dayComponents: JSCopy(todayComponents)});
119
+ }
120
+ }
121
+ }
122
+ }
123
+ var tomorrowComponents = this.componentsFromDate(JSCalendar.Unit.date, this.dateByAddingComponents({day: 1}, now));
124
+ var tomorrow = this.dateFromComponents(tomorrowComponents);
125
+ var interval = now.timeIntervalUntilDate(tomorrow);
126
+ this.lastKnownDayComponents = todayComponents;
127
+ this.dateChangeTimer = JSTimer.scheduledTimerWithInterval(interval + 1, this.scheduleDayChangeTimer, this);
128
+ },
129
+
130
+ timeZoneChanged: function(){
131
+ if (this.notificationCenters !== null && this.notificationCenters.length > 0){
132
+ this.scheduleDayChangeTimer();
133
+ }
134
+ },
135
+
136
+ componentsFromComponents: function(units, otherComponents){
137
+ var otherCalendar = otherComponents.calendar || this;
138
+ if (otherCalendar.identifier === this.identifier){
139
+ if (otherCalendar.timezone.identifier === this.identifier){
140
+ return otherComponents;
141
+ }
142
+ }
143
+ var date = otherCalendar.dateFromComponents(otherComponents);
144
+ return this.componentsFromDate(units, date);
53
145
  }
54
146
 
55
147
  });
@@ -709,6 +801,7 @@ JSCalendar.Unit.difference =
709
801
  JSCalendar.Unit.second |
710
802
  JSCalendar.Unit.millisecond;
711
803
 
804
+ JSCalendar.Unit.date = JSCalendar.Unit.year | JSCalendar.Unit.month | JSCalendar.Unit.day;
712
805
 
713
806
  var monthsPerYear = 12;
714
807
  var minutesPerHour = 60;
@@ -80,17 +80,15 @@ JSClass("JSDateFormatter", JSObject, {
80
80
 
81
81
  setLocale: function(locale){
82
82
  this._locale = locale;
83
- this._localeCalendar = JSCalendar.initWithIdentifier(locale.calendarIdentifier);
84
83
  },
85
84
 
86
85
  calendar: JSDynamicProperty('_calendar', null),
87
- _localeCalendar: null,
88
86
 
89
87
  getCalendar: function(){
90
88
  if (this._calendar !== null){
91
89
  return this._calendar;
92
90
  }
93
- return this._localeCalendar;
91
+ return this._locale.calendar;
94
92
  },
95
93
 
96
94
  timezone: JSDynamicProperty('_timezone', null),
@@ -373,6 +373,10 @@ JSClass("JSLocale", JSObject, {
373
373
 
374
374
  calendarIdentifier: JSReadOnlyProperty('_calendarIdentifier', JSCalendar.Identifier.gregorian),
375
375
 
376
+ calendar: JSLazyInitProperty(function(){
377
+ return JSCalendar.initWithIdentifier(this.calendarIdentifier);
378
+ }),
379
+
376
380
  dateFormatForTemplate: function(template){
377
381
  return this._dateFormatsByTemplate[template] || null;
378
382
  },
@@ -410,6 +414,7 @@ JSClass("JSLocale", JSObject, {
410
414
  this._dateFormatsByTemplate.MMMMd = "MMMM d";
411
415
  this._dateFormatsByTemplate.hms = "h:mm:ss a";
412
416
  this._dateFormatsByTemplate.hm = "h:mm a";
417
+ this._dateFormatsByTemplate.hmz = "h:mm a z";
413
418
  this._dateFormatsByTemplate.Hms = "HH:mm:ss";
414
419
  this._dateFormatsByTemplate.Hm = "HH:mm";
415
420
  return;
@@ -556,7 +561,13 @@ JSClass("JSLocale", JSObject, {
556
561
  }else if (part.type === "dayPeriod"){
557
562
  format += "a";
558
563
  }else if (part.type === "timeZoneName"){
559
- if (part.value.length > 4){
564
+ if (part.value.startsWith("GMT-") || part.value.startsWith("GMT+")){
565
+ if (part.value.indexOf(":") >= 0){
566
+ format += "OOOO";
567
+ }else{
568
+ format += "O";
569
+ }
570
+ }else if (part.value.length > 4){
560
571
  format += "zzzz";
561
572
  }else{
562
573
  format += "z";
@@ -606,6 +617,7 @@ JSClass("JSLocale", JSObject, {
606
617
  "MMMMd": unicodeFormatForOptions({month: "long", day: "numeric"}),
607
618
  "hms": unicodeFormatForOptions({hour: "numeric", minute: "numeric", second: "numeric"}),
608
619
  "hm": unicodeFormatForOptions({hour: "numeric", minute: "numeric"}),
620
+ "hmz": unicodeFormatForOptions({hour: "numeric", minute: "numeric", timeZoneName: "short"}),
609
621
  "Hms": unicodeFormatForOptions({hour: "numeric", minute: "numeric", second: "numeric", hour12: false}),
610
622
  "Hm": unicodeFormatForOptions({hour: "numeric", minute: "numeric", hour12: false}),
611
623
  };
@@ -16,6 +16,8 @@
16
16
  // #import "JSObject.js"
17
17
  // #import "JSDate.js"
18
18
  // #import "JSBinarySearcher.js"
19
+ // #import "JSTimer.js"
20
+ // #import "JSTimeInterval.js"
19
21
  // #feature Intl
20
22
  /* global JSGregorianCalendar, Intl, DataView */
21
23
  'use strict';
@@ -533,11 +535,77 @@ JSClass("JSTimeZone", JSObject, {
533
535
 
534
536
  });
535
537
 
538
+ JSTimeZone.changeLocalTimeZoneToSystem = function(){
539
+ if (JSTimeZone.localFollowsSystem){
540
+ return;
541
+ }
542
+ JSTimeZone.localFollowsSystem = true;
543
+ JSTimeZone._changeLocalTimeZone(JSTimeZone.systemTimeZoneIdentifier);
544
+ if (JSTimeZone.notificationCenters.length > 0){
545
+ JSTimeZone.scheduleSystemIdentifierWatchTimer();
546
+ }
547
+ };
548
+
536
549
  JSTimeZone.changeLocalTimeZone = function(identifier){
537
- localIdentifier = identifier;
538
- Object.defineProperty(JSTimeZone, 'local', defaultLocalProperty);
550
+ JSTimeZone.cancelSystemIdentifierWatchTimer();
551
+ JSTimeZone.localFollowsSystem = false;
552
+ JSTimeZone._changeLocalTimeZone(identifier);
539
553
  };
540
554
 
555
+ JSTimeZone._changeLocalTimeZone = function(identifier){
556
+ if (identifier !== localIdentifier){
557
+ localIdentifier = identifier;
558
+ Object.defineProperty(JSTimeZone, 'local', defaultLocalProperty);
559
+ var i, l;
560
+ for (i = 0, l = JSTimeZone.notificationCenters.length; i < l; ++i){
561
+ JSTimeZone.notificationCenters[i].post("JSLocalTimeZoneChanged", null);
562
+ }
563
+ }
564
+ };
565
+
566
+ JSTimeZone.startSendingNotifications = function(notificationCenter){
567
+ var i = JSTimeZone.notificationCenters.indexOf(notificationCenter);
568
+ if (i < 0){
569
+ JSTimeZone.notificationCenters.push(notificationCenter);
570
+ }
571
+ if (JSTimeZone.localFollowsSystem){
572
+ JSTimeZone.scheduleSystemIdentifierWatchTimer();
573
+ }
574
+ };
575
+
576
+ JSTimeZone.scheduleSystemIdentifierWatchTimer = function(){
577
+ if (JSTimeZone.systemIdentifierWatchTimer === null){
578
+ var previousSystemTimeZoneIdentifier = JSTimeZone.systemTimeZoneIdentifier;
579
+ JSTimeZone.systemIdentifierWatchTimer = JSTimer.scheduledRepeatingTimerWithInterval(JSTimeInterval.minutes(1), function(){
580
+ if (JSTimeZone.systemTimeZoneIdentifier !== previousSystemTimeZoneIdentifier){
581
+ previousSystemTimeZoneIdentifier = JSTimeZone.systemTimeZoneIdentifier;
582
+ JSTimeZone._changeLocalTimeZone(JSTimeZone.systemTimeZoneIdentifier);
583
+ }
584
+ });
585
+ }
586
+ };
587
+
588
+ JSTimeZone.cancelSystemIdentifierWatchTimer = function(){
589
+ if (JSTimeZone.systemIdentifierWatchTimer !== null){
590
+ JSTimeZone.systemIdentifierWatchTimer.invalidate();
591
+ JSTimeZone.systemIdentifierWatchTimer = null;
592
+ }
593
+ };
594
+
595
+ JSTimeZone.stopSendingNotifications = function(notificationCenter){
596
+ var i = JSTimeZone.notificationCenters.indexOf(notificationCenter);
597
+ if (i >= 0){
598
+ JSTimeZone.notificationCenters.splice(i, 1);
599
+ }
600
+ if (JSTimeZone.notificationCenters.length === 0){
601
+ JSTimeZone.cancelSystemIdentifierWatchTimer();
602
+ }
603
+ };
604
+
605
+ JSTimeZone.localFollowsSystem = true;
606
+ JSTimeZone.systemIdentifierWatchTimer = null;
607
+ JSTimeZone.notificationCenters = [];
608
+
541
609
  var defaultLocalProperty = {
542
610
  configurable: true,
543
611
  get: function JSTimeZone_getLocal(){
@@ -578,6 +646,7 @@ Object.defineProperties(JSTimeZone, {
578
646
  configurable: true,
579
647
  get: function JSTimeZone_getUTC(){
580
648
  var timezone = JSTimeZone.initWithTimeIntervalFromUTC(0, 'UTC');
649
+ timezone._identifier = "UTC";
581
650
  Object.defineProperty(JSTimeZone, 'utc', {configurable: false, value: timezone});
582
651
  return timezone;
583
652
  }
@@ -601,7 +670,7 @@ JSTimeZone.importZoneInfo = function(info){
601
670
  JSTimeZone.clearZoneInfo = function(info){
602
671
  zoneinfo = emptyZoneInfo;
603
672
  Object.defineProperty(JSTimeZone, 'knownTimeZoneIdentifiers', defaultKnownIdentifiersProperty);
604
- JSTimeZone.changeLocalTimeZone(JSTimeZone.systemTimeZoneIdentifier);
673
+ JSTimeZone.changeLocalTimeZoneToSystem();
605
674
  };
606
675
 
607
676
  JSTimeZone.rulesFromPOSIXString = function(str){
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.ImageKit
3
- JSBundleVersion: 2024.6.0
3
+ JSBundleVersion: 2024.8.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.MediaKit
3
- JSBundleVersion: 2024.6.0
3
+ JSBundleVersion: 2024.8.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.MediaKitUI
3
- JSBundleVersion: 2024.6.0
3
+ JSBundleVersion: 2024.8.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.NotificationKit
3
- JSBundleVersion: 2024.6.0
3
+ JSBundleVersion: 2024.8.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2021 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.PDFKit
3
- JSBundleVersion: 2024.6.0
3
+ JSBundleVersion: 2024.8.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.QRKit
3
- JSBundleVersion: 2024.6.0
3
+ JSBundleVersion: 2024.8.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.SearchKit
3
- JSBundleVersion: 2024.6.0
3
+ JSBundleVersion: 2024.8.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.SecurityKit
3
- JSBundleVersion: 2024.6.0
3
+ JSBundleVersion: 2024.8.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.ServerKit
3
- JSBundleVersion: 2024.6.0
3
+ JSBundleVersion: 2024.8.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.ServerKitTesting
3
- JSBundleVersion: 2024.6.0
3
+ JSBundleVersion: 2024.8.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.TestKit
3
- JSBundleVersion: 2024.6.0
3
+ JSBundleVersion: 2024.8.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.UIKit
3
- JSBundleVersion: 2024.6.0
3
+ JSBundleVersion: 2024.8.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -73,6 +73,7 @@ JSClass('UIApplication', UIResponder, {
73
73
  }catch (e){
74
74
  error = e;
75
75
  }
76
+ this.startSystemNotifications();
76
77
  }
77
78
  completion.call(target, error);
78
79
  }, this);
@@ -89,6 +90,20 @@ JSClass('UIApplication', UIResponder, {
89
90
  }
90
91
  },
91
92
 
93
+ postsSystemNotifications: true,
94
+
95
+ startSystemNotifications: function(){
96
+ if (this.postsSystemNotifications){
97
+ JSTimeZone.startSendingNotifications(JSNotificationCenter.shared);
98
+ JSLocale.current.calendar.startSendingNotifications(JSNotificationCenter.shared);
99
+ }
100
+ },
101
+
102
+ stopSystemNotifications: function(){
103
+ JSLocale.current.calendar.stopSendingNotifications(JSNotificationCenter.shared);
104
+ JSTimeZone.stopSendingNotifications(JSNotificationCenter.shared);
105
+ },
106
+
92
107
  setupTimeZones: function(completion, target){
93
108
  var subdirectory = (this.bundle.info.JSTimeZoneInfo || "tz") + ".zoneinfo";
94
109
  var metadata = this.bundle.metadataForResourceName("Contents", "json", subdirectory);
@@ -229,6 +244,7 @@ JSClass('UIApplication', UIResponder, {
229
244
  }else{
230
245
  this._stopCalled = true;
231
246
  logger.info("Stopping application");
247
+ this.stopSystemNotifications();
232
248
  var closed = false;
233
249
  var _close = function(){
234
250
  if (closed){
@@ -28,6 +28,9 @@ JSClass("UISplitViewController", UIViewController, {
28
28
  leadingViewOpen: JSReadOnlyProperty(null, null, 'isLeadingViewOpen'),
29
29
  trailingViewOpen: JSReadOnlyProperty(null, null, 'isTrailingViewOpen'),
30
30
 
31
+ leadingViewVisible: JSReadOnlyProperty(null, null, 'isLeadingViewVisible'),
32
+ trailingViewVisible: JSReadOnlyProperty(null, null, 'isTrailingViewVisible'),
33
+
31
34
  splitView: JSReadOnlyProperty(),
32
35
  _defaultViewClass: UISplitView,
33
36
 
@@ -72,52 +75,52 @@ JSClass("UISplitViewController", UIViewController, {
72
75
  if (this.view.mainHidden){
73
76
  this._moveMainViewControllerToLeading();
74
77
  }
75
- if (this._leadingViewController !== null && this.leadingViewOpen){
78
+ if (this._leadingViewController !== null && this.leadingViewVisible){
76
79
  this._leadingViewController.viewWillAppear(animated);
77
80
  }
78
81
  if (this._mainViewController !== null && !this._view.mainHidden){
79
82
  this._mainViewController.viewWillAppear(animated);
80
83
  }
81
- if (this._trailingViewController !== null && this.trailingViewOpen){
84
+ if (this._trailingViewController !== null && this.trailingViewVisible){
82
85
  this._trailingViewController.viewWillAppear(animated);
83
86
  }
84
87
  },
85
88
 
86
89
  viewDidAppear: function(animated){
87
90
  UISplitViewController.$super.viewDidAppear.call(this, animated);
88
- if (this._leadingViewController !== null && this.leadingViewOpen){
91
+ if (this._leadingViewController !== null && this.leadingViewVisible){
89
92
  this._leadingViewController.viewDidAppear(animated);
90
93
  }
91
94
  if (this._mainViewController !== null && !this._view.mainHidden){
92
95
  this._mainViewController.viewDidAppear(animated);
93
96
  }
94
- if (this._trailingViewController !== null && this.trailingViewOpen){
97
+ if (this._trailingViewController !== null && this.trailingViewVisible){
95
98
  this._trailingViewController.viewDidAppear(animated);
96
99
  }
97
100
  },
98
101
 
99
102
  viewWillDisappear: function(animated){
100
103
  UISplitViewController.$super.viewWillDisappear.call(this, animated);
101
- if (this._leadingViewController !== null && this.leadingViewOpen){
104
+ if (this._leadingViewController !== null && this.leadingViewVisible){
102
105
  this._leadingViewController.viewWillDisappear(animated);
103
106
  }
104
107
  if (this._mainViewController !== null && !this._view.mainHidden){
105
108
  this._mainViewController.viewWillDisappear(animated);
106
109
  }
107
- if (this._trailingViewController !== null && this.trailingViewOpen){
110
+ if (this._trailingViewController !== null && this.trailingViewVisible){
108
111
  this._trailingViewController.viewWillDisappear(animated);
109
112
  }
110
113
  },
111
114
 
112
115
  viewDidDisappear: function(animated){
113
116
  UISplitViewController.$super.viewDidDisappear.call(this, animated);
114
- if (this._leadingViewController !== null && this.leadingViewOpen){
117
+ if (this._leadingViewController !== null && this.leadingViewVisible){
115
118
  this._leadingViewController.viewDidDisappear(animated);
116
119
  }
117
120
  if (this._mainViewController !== null && !this._view.mainHidden){
118
121
  this._mainViewController.viewDidDisappear(animated);
119
122
  }
120
- if (this._trailingViewController !== null && this.trailingViewOpen){
123
+ if (this._trailingViewController !== null && this.trailingViewVisible){
121
124
  this._trailingViewController.viewDidDisappear(animated);
122
125
  }
123
126
  },
@@ -417,10 +420,30 @@ JSClass("UISplitViewController", UIViewController, {
417
420
  return this.splitView.leadingViewOpen;
418
421
  },
419
422
 
423
+ isLeadingViewVisible: function(){
424
+ if (this.splitView.leadingViewOpen){
425
+ return true;
426
+ }
427
+ if (this.splitView.leadingCollapses){
428
+ return this.splitView.leadingCollapsedSize > 0;
429
+ }
430
+ return false;
431
+ },
432
+
420
433
  isTrailingViewOpen: function(){
421
434
  return this.splitView.trailingViewOpen;
422
435
  },
423
436
 
437
+ isTrailingViewVisible: function(){
438
+ if (this.splitView.trailingViewOpen){
439
+ return true;
440
+ }
441
+ if (this.splitView.trailingCollapses){
442
+ return this.splitView.trailingCollapsedSize > 0;
443
+ }
444
+ return false;
445
+ },
446
+
424
447
  hideTrailingView: function(animated){
425
448
  if (this.splitView.trailingViewOpen){
426
449
  this.toggleTrailingView(animated);
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.UIKitTesting
3
- JSBundleVersion: 2024.6.0
3
+ JSBundleVersion: 2024.8.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
@@ -42,6 +42,8 @@ JSClass("UIMockApplication", UIApplication, {
42
42
  setupDelegate: function(){
43
43
  },
44
44
 
45
+ postsSystemNotifications: false,
46
+
45
47
  stop: function(completion, target){
46
48
  if (!completion){
47
49
  completion = Promise.completion(Promise.resolveNull);
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "node": ">=10.10.0"
10
10
  },
11
11
  "name": "@breakside/jskit",
12
- "version": "2024.6.0",
12
+ "version": "2024.8.0",
13
13
  "license": "SEE LICENSE IN LICENSE.txt",
14
14
  "files": [
15
15
  "*"