pinokiod 3.259.0 → 3.261.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.
package/kernel/peer.js CHANGED
@@ -37,8 +37,16 @@ class PeerDiscovery {
37
37
  }
38
38
  }
39
39
  announce() {
40
- if (this.socket) {
41
- this.socket.send(this.message, 0, this.message.length, this.port, '192.168.1.255');
40
+ if (!this.socket) {
41
+ return
42
+ }
43
+ const targets = this._broadcastTargets()
44
+ for (const target of targets) {
45
+ try {
46
+ this.socket.send(this.message, 0, this.message.length, this.port, target)
47
+ } catch (err) {
48
+ console.error('peer broadcast failed', { target, err })
49
+ }
42
50
  }
43
51
  }
44
52
  async check(kernel) {
@@ -641,6 +649,7 @@ class PeerDiscovery {
641
649
  const classification = this.classifyAddress(address, Boolean(iface.internal))
642
650
  results.push({
643
651
  address,
652
+ netmask: String(iface.netmask || '').trim() || null,
644
653
  interface: ifaceName,
645
654
  internal: Boolean(iface.internal),
646
655
  scope: classification.scope,
@@ -731,6 +740,51 @@ class PeerDiscovery {
731
740
  }
732
741
  return entries
733
742
  }
743
+ _broadcastTargets() {
744
+ const addresses = this._collectInterfaceAddresses()
745
+ this.interface_addresses = addresses
746
+ const targets = new Set()
747
+ for (const entry of addresses) {
748
+ if (!entry || !entry.shareable) {
749
+ continue
750
+ }
751
+ const broadcast = this._deriveBroadcastAddress(entry.address, entry.netmask)
752
+ if (broadcast) {
753
+ targets.add(broadcast)
754
+ }
755
+ }
756
+ targets.add('255.255.255.255')
757
+ return Array.from(targets)
758
+ }
759
+ _deriveBroadcastAddress(address, netmask) {
760
+ const addrOctets = this._parseIPv4(address)
761
+ if (!addrOctets) {
762
+ return null
763
+ }
764
+ let maskOctets = this._parseIPv4(netmask)
765
+ if (!maskOctets) {
766
+ maskOctets = [255, 255, 255, 0]
767
+ }
768
+ const broadcastOctets = addrOctets.map((octet, idx) => {
769
+ const mask = maskOctets[idx]
770
+ return ((octet & mask) | (~mask & 255)) & 255
771
+ })
772
+ const candidate = broadcastOctets.join('.')
773
+ if (candidate.startsWith('127.') || candidate.startsWith('169.254.') || candidate === '0.0.0.0') {
774
+ return null
775
+ }
776
+ return candidate
777
+ }
778
+ _parseIPv4(value) {
779
+ if (!value || typeof value !== 'string') {
780
+ return null
781
+ }
782
+ const octets = value.split('.').map(Number)
783
+ if (octets.length !== 4 || octets.some((val) => Number.isNaN(val) || val < 0 || val > 255)) {
784
+ return null
785
+ }
786
+ return octets
787
+ }
734
788
  }
735
789
 
736
790
  module.exports = PeerDiscovery;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pinokiod",
3
- "version": "3.259.0",
3
+ "version": "3.261.0",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/server/index.js CHANGED
@@ -3250,7 +3250,6 @@ class Server {
3250
3250
  this.kernel.store.set("theme", config.theme)
3251
3251
  //this.theme = config.theme
3252
3252
  }
3253
- console.log("THEME CHANGED", theme_changed)
3254
3253
  // 2. Handle HOME
3255
3254
  if (config.home) {
3256
3255
  // set "new_home"
@@ -3335,9 +3334,7 @@ class Server {
3335
3334
  this.kernel.store.set("NO_PROXY", config.NO_PROXY)
3336
3335
 
3337
3336
  if (theme_changed) {
3338
- console.log("> syncConfig")
3339
3337
  await this.syncConfig()
3340
- console.log("onrefresh", this.onrefresh)
3341
3338
  if (this.onrefresh) {
3342
3339
  try {
3343
3340
  this.onrefresh({ theme: this.theme, colors: this.colors })
@@ -8208,7 +8205,6 @@ class Server {
8208
8205
 
8209
8206
  this.app.post("/config", ex(async (req, res) => {
8210
8207
  try {
8211
- console.log("POST /config", req.body)
8212
8208
  let message = await this.setConfig(req.body)
8213
8209
  res.json({ success: true, message })
8214
8210
  } catch (e) {
@@ -2932,6 +2932,13 @@ document.addEventListener("DOMContentLoaded", () => {
2932
2932
  header.appendChild(iconWrapper);
2933
2933
  header.appendChild(headingStack);
2934
2934
 
2935
+ const closeButton = document.createElement('button');
2936
+ closeButton.type = 'button';
2937
+ closeButton.className = 'create-launcher-modal-close';
2938
+ closeButton.setAttribute('aria-label', 'Close create launcher modal');
2939
+ closeButton.innerHTML = '<i class="fa-solid fa-xmark"></i>';
2940
+ header.appendChild(closeButton);
2941
+
2935
2942
  const promptLabel = document.createElement('label');
2936
2943
  promptLabel.className = 'create-launcher-modal-label';
2937
2944
  promptLabel.textContent = 'What do you want to do?';
@@ -3190,12 +3197,8 @@ document.addEventListener("DOMContentLoaded", () => {
3190
3197
  });
3191
3198
 
3192
3199
  cancelButton.addEventListener('click', hideCreateLauncherModal);
3200
+ closeButton.addEventListener('click', hideCreateLauncherModal);
3193
3201
  confirmButton.addEventListener('click', submitCreateLauncherModal);
3194
- overlay.addEventListener('click', (event) => {
3195
- if (event.target === overlay) {
3196
- hideCreateLauncherModal();
3197
- }
3198
- });
3199
3202
 
3200
3203
  advancedLink.addEventListener('click', () => {
3201
3204
  hideCreateLauncherModal();
@@ -200,6 +200,7 @@ body.dark .url-dropdown-empty-description {
200
200
  font-family: "SF Pro Text", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
201
201
  -webkit-backdrop-filter: blur(28px);
202
202
  backdrop-filter: blur(28px);
203
+ position: relative;
203
204
  }
204
205
  body.dark .create-launcher-modal {
205
206
  background: rgba(17, 24, 39, 0.82);
@@ -215,6 +216,33 @@ body.dark .create-launcher-modal {
215
216
  align-items: center;
216
217
  gap: 18px;
217
218
  padding-bottom: 4px;
219
+ position: relative;
220
+ }
221
+ .create-launcher-modal-close {
222
+ position: absolute;
223
+ top: 0;
224
+ right: 0;
225
+ border: none;
226
+ background: transparent;
227
+ color: #6b7280;
228
+ font-size: 18px;
229
+ padding: 6px;
230
+ cursor: pointer;
231
+ line-height: 1;
232
+ }
233
+ .create-launcher-modal-close:hover {
234
+ color: #4f46e5;
235
+ }
236
+ .create-launcher-modal-close:focus-visible {
237
+ outline: 2px solid #4f46e5;
238
+ outline-offset: 2px;
239
+ border-radius: 4px;
240
+ }
241
+ body.dark .create-launcher-modal-close {
242
+ color: rgba(255,255,255,0.75);
243
+ }
244
+ body.dark .create-launcher-modal-close:hover {
245
+ color: #a5b4fc;
218
246
  }
219
247
  .create-launcher-modal-icon {
220
248
  width: 44px;
@@ -1163,6 +1163,12 @@ function initUrlDropdown(config = {}) {
1163
1163
  modalContent.setAttribute('role', 'dialog');
1164
1164
  modalContent.setAttribute('aria-modal', 'true');
1165
1165
 
1166
+ const closeButton = document.createElement('button');
1167
+ closeButton.type = 'button';
1168
+ closeButton.className = 'create-launcher-modal-close';
1169
+ closeButton.setAttribute('aria-label', 'Close create launcher modal');
1170
+ closeButton.innerHTML = '<i class="fa-solid fa-xmark"></i>';
1171
+
1166
1172
  const title = document.createElement('h3');
1167
1173
  title.id = 'quick-create-launcher-title';
1168
1174
  title.textContent = 'Create';
@@ -1204,6 +1210,7 @@ function initUrlDropdown(config = {}) {
1204
1210
  actions.appendChild(confirmButton);
1205
1211
 
1206
1212
  label.appendChild(input);
1213
+ modalContent.appendChild(closeButton);
1207
1214
  modalContent.appendChild(title);
1208
1215
  modalContent.appendChild(description);
1209
1216
  modalContent.appendChild(label);
@@ -1212,13 +1219,8 @@ function initUrlDropdown(config = {}) {
1212
1219
  overlay.appendChild(modalContent);
1213
1220
  document.body.appendChild(overlay);
1214
1221
 
1215
- overlay.addEventListener('click', function(event) {
1216
- if (event.target === overlay) {
1217
- hideCreateLauncherModal();
1218
- }
1219
- });
1220
-
1221
1222
  cancelButton.addEventListener('click', hideCreateLauncherModal);
1223
+ closeButton.addEventListener('click', hideCreateLauncherModal);
1222
1224
  confirmButton.addEventListener('click', confirmCreateLauncherModal);
1223
1225
  input.addEventListener('keydown', handleCreateModalKeydown);
1224
1226
 
@@ -322,8 +322,10 @@ body.dark .browser-options-row {
322
322
  }
323
323
  */
324
324
  body.dark .context-menu-wrapper {
325
- background: rgba(0,0,0,0.9);
326
- color: white;
325
+ background: rgba(0,0,0,0.9) !important;
326
+ color: white !important;
327
+ border: 1px solid rgba(255,255,255,0.1);
328
+ box-shadow: 0 12px 30px rgba(0,0,0,0.45);
327
329
  }
328
330
  .context-menu-wrapper {
329
331
  background: rgba(0,0,0,0.06) !important;
@@ -158,8 +158,10 @@ body.dark .browser-options-row {
158
158
  }
159
159
  */
160
160
  body.dark .context-menu-wrapper {
161
- background: rgba(0,0,0,0.9);
162
- color: white;
161
+ background: rgba(0,0,0,0.9) !important;
162
+ color: white !important;
163
+ border: 1px solid rgba(255,255,255,0.1);
164
+ box-shadow: 0 12px 30px rgba(0,0,0,0.45);
163
165
  }
164
166
  .context-menu-wrapper {
165
167
  background: whitesmoke !important;
@@ -194,6 +196,7 @@ body.dark .context-menu-wrapper {
194
196
  padding: 6px 10px !important;
195
197
  text-align: left;
196
198
  color: black;
199
+ margin: 0 !important;
197
200
  }
198
201
  body.dark .btn {
199
202
  background: rgba(255,255,255,0.05) !important;
@@ -209,6 +212,7 @@ body.dark .btn {
209
212
  }
210
213
  body.dark .context-menu .btn {
211
214
  color: white;
215
+ background: none !important;
212
216
  }
213
217
  body.dark .open-menu, body.dark .browse {
214
218
  border: none !important;
@@ -128,8 +128,10 @@ body.dark .browser-options-row {
128
128
  }
129
129
  */
130
130
  body.dark .context-menu-wrapper {
131
- background: rgba(0,0,0,0.9);
132
- color: white;
131
+ background: rgba(0,0,0,0.9) !important;
132
+ color: white !important;
133
+ border: 1px solid rgba(255,255,255,0.1);
134
+ box-shadow: 0 12px 30px rgba(0,0,0,0.45);
133
135
  }
134
136
  .context-menu-wrapper {
135
137
  background: rgba(0,0,0,0.06) !important;
@@ -135,8 +135,10 @@ body.dark .browser-options-row {
135
135
  }
136
136
  */
137
137
  body.dark .context-menu-wrapper {
138
- background: rgba(0,0,0,0.9);
139
- color: white;
138
+ background: rgba(0,0,0,0.9) !important;
139
+ color: white !important;
140
+ border: 1px solid rgba(255,255,255,0.1);
141
+ box-shadow: 0 12px 30px rgba(0,0,0,0.45);
140
142
  }
141
143
  .context-menu-wrapper {
142
144
  background: rgba(0,0,0,0.06) !important;
@@ -782,9 +784,12 @@ document.addEventListener('DOMContentLoaded', function() {
782
784
  %>
783
785
  <% if (directHosts.length > 0) { %>
784
786
  <ul class="access-point-list">
785
- <% directHosts.forEach((point) => { %>
787
+ <% directHosts.forEach((point) => {
788
+ const hasProtocol = /^https?:\/\//i.test(point.url)
789
+ const hrefValue = hasProtocol ? point.url : `http://${point.url}`
790
+ %>
786
791
  <li>
787
- <a class='net' target="_blank" href="<%= point.url %>"><%= point.url %></a>
792
+ <a class='net' target="_blank" href="<%= hrefValue %>"><%= point.url %></a>
788
793
  <% if (point.badge) { %>
789
794
  <span class="badge"><%= point.badge %></span>
790
795
  <% } %>
@@ -651,8 +651,10 @@ body.dark .browser-options-row {
651
651
  }
652
652
  */
653
653
  body.dark .context-menu-wrapper {
654
- background: rgba(0,0,0,0.9);
655
- color: white;
654
+ background: rgba(0,0,0,0.9) !important;
655
+ color: white !important;
656
+ border: 1px solid rgba(255,255,255,0.1);
657
+ box-shadow: 0 12px 30px rgba(0,0,0,0.45);
656
658
  }
657
659
  .context-menu-wrapper {
658
660
  background: rgba(0,0,0,0.06) !important;