@yz-social/civildefense.io 4.5.7 → 4.5.8

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@yz-social/civildefense.io",
3
3
  "description": "Browser app to safely share live sightings on a map.",
4
- "version": "4.5.7",
4
+ "version": "4.5.8",
5
5
  "keywords": [
6
6
  "map",
7
7
  "browser",
@@ -44,6 +44,14 @@ export class P2PWebNetwork {
44
44
  Object.assign(network, {infoLogger, debugLogger, disconnector: disconnect, transport, nodeIdentity, peer});
45
45
  network.resetStatePromises();
46
46
  network.info(`Created network node for kernel ${this.kernelVersion} region 0x${this.regionCode(region.lat, region.lng).toString(16)}.`);
47
+ peer.onError(error => {
48
+ network.info(`error: ${error.message || error}`);
49
+ throw error;
50
+ });
51
+ //peer.onLog('debug', (...rest) => network.debug('DEBUG', ...rest));
52
+ //peer.onLog('info', (...rest) => network.debug('INFO', ...rest));
53
+ peer.onLog('warn', (...rest) => network.info('WARNING', ...rest));
54
+ peer.onLog('error', (...rest) => network.info('ERROR', ...rest));
47
55
  const { peers, ms } = status;
48
56
  network.info(`Connected ${peers} connections through ${bridgeUrl} in ${ms.toLocaleString()} ms.`);
49
57
  network.attached(network);
@@ -0,0 +1,145 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Material Web Autocomplete Combo Box</title>
6
+ <script type="importmap">
7
+ {
8
+ "imports": {
9
+ "uuid": "https://unpkg.com/uuid@13.0.0/dist/index.js",
10
+ "@material/web/": "https://esm.run/@material/web/",
11
+ "s2js": "./s2js/s2js.esm.js",
12
+ "bigfloat": "./bigfloat/esm/index.js",
13
+ "leaflet": "./leaflet/leaflet-src.esm.js",
14
+ "minidenticons": "./minidenticons/minidenticons.min.js",
15
+ "@axona/protocol": "./axona-protocol/src/index.js",
16
+ "@axona/protocol/std": "./axona-protocol/std/index.js",
17
+ "@axona/protocol/connect.js": "./axona-protocol/src/connect.js"
18
+ }
19
+ }
20
+ </script>
21
+ <script type="module">
22
+ import '@material/web/all.js';
23
+ import {styles as typescaleStyles} from '@material/web/typography/md-typescale-styles.js';
24
+ document.adoptedStyleSheets.push(typescaleStyles.styleSheet);
25
+ </script>
26
+ <!-- Load Material Web Components via CDN -->
27
+ <!-- <script type="module"> -->
28
+ <!-- import '@material/web/textfield/filled-text-field.js'; -->
29
+ <!-- import '@material/web/menu/menu.js'; -->
30
+ <!-- import '@material/web/menu/menu-item.js'; -->
31
+ <!-- </script> -->
32
+ <style>
33
+ .combo-box-container {
34
+ position: relative;
35
+ display: inline-block;
36
+ width: 300px;
37
+ margin: 40px;
38
+ }
39
+ md-filled-text-field {
40
+ width: 100%;
41
+ }
42
+ md-menu {
43
+ /* Match the width of the textfield anchor */
44
+ --md-menu-container-width: 300px;
45
+ }
46
+ </style>
47
+ </head>
48
+ <body>
49
+
50
+ <div class="combo-box-container">
51
+ <!-- The editable text input acting as the anchor -->
52
+ <md-filled-text-field
53
+ id="combo-input"
54
+ label="Choose a fruit"
55
+ placeholder="Type to search..."
56
+ autocomplete="off">
57
+ </md-filled-text-field>
58
+
59
+ <!-- The dropdown menu containing autocomplete suggestions -->
60
+ <md-menu id="combo-menu" anchor="combo-input" stay-open-on-outside-click>
61
+ <!-- Populated dynamically via JavaScript -->
62
+ </md-menu>
63
+ </div>
64
+
65
+ <script>
66
+ const input = document.getElementById('combo-input');
67
+ const menu = document.getElementById('combo-menu');
68
+
69
+ // Dataset for autocomplete
70
+ const itemsList = [
71
+ 'Apple', 'Banana', 'Blueberry', 'Cherry', 'Grape',
72
+ 'Lemon', 'Mango', 'Orange', 'Peach', 'Strawberry'
73
+ ];
74
+
75
+ // Build and filter menu items based on input value
76
+ function updateMenu(filterText = '') {
77
+ const normalizedFilter = filterText.toLowerCase().trim();
78
+
79
+ // Filter list items
80
+ const filtered = itemsList.filter(item =>
81
+ item.toLowerCase().includes(normalizedFilter)
82
+ );
83
+
84
+ // Clear existing menu items
85
+ menu.innerHTML = '';
86
+
87
+ if (filtered.length === 0) {
88
+ // Show a disabled helper item if no match found
89
+ const noResult = document.createElement('md-menu-item');
90
+ noResult.disabled = true;
91
+ //noResult.headline = 'No matches found';
92
+ noResult.textContent = 'No matches found';
93
+ menu.appendChild(noResult);
94
+ return;
95
+ }
96
+
97
+ // Append matched options
98
+ filtered.forEach(item => {
99
+ const menuItem = document.createElement('md-menu-item');
100
+ //menuItem.headline = item;
101
+ menuItem.textContent = item;
102
+ // Store raw value on the element for extraction during selection
103
+ menuItem.dataset.value = item;
104
+ menu.appendChild(menuItem);
105
+ });
106
+ }
107
+
108
+ // Filter list and open menu as user types
109
+ input.addEventListener('input', (e) => {
110
+ updateMenu(e.target.value);
111
+ if (!menu.open) {
112
+ menu.open = true;
113
+ }
114
+ });
115
+
116
+ // Re-open full menu list when user clicks or focuses inside the input
117
+ input.addEventListener('focus', () => {
118
+ updateMenu(input.value);
119
+ menu.open = true;
120
+ });
121
+
122
+ // Handle selection event from the Material menu
123
+ menu.addEventListener('close-menu', (e) => {
124
+ // e.detail.item holds the clicked md-menu-item instance
125
+ const selectedItem = e.detail.item;
126
+ if (selectedItem && selectedItem.dataset.value) {
127
+ input.value = selectedItem.dataset.value;
128
+ // Optionally trigger a change event for form tracking
129
+ input.dispatchEvent(new Event('change'));
130
+ }
131
+ });
132
+
133
+ // Close the dropdown cleanly if the user hits "Escape" or "Enter" inside input
134
+ input.addEventListener('keydown', (e) => {
135
+ if (e.key === 'Escape' || e.key === 'Enter') {
136
+ menu.open = false;
137
+ if(e.key === 'Enter') input.blur();
138
+ }
139
+ });
140
+
141
+ // Initial population of the menu
142
+ updateMenu();
143
+ </script>
144
+ </body>
145
+ </html>
@@ -1,6 +1,6 @@
1
1
  const { Request, Response, URL, clients} = self;
2
2
  // Little point in trying to automatically pull this through package.json, as we need a byte change in THIS file to trigger a new worker.
3
- const serviceVersion = '4.5.7';
3
+ const serviceVersion = '4.5.8';
4
4
 
5
5
  const cacheList = [ // The files we need.
6
6
  "/",
package/server/app.js CHANGED
@@ -46,6 +46,12 @@ const argv = yargs(hideBin(process.argv))
46
46
  default: 5,
47
47
  description: "Additional variable seconds (+/- variableSpacing/2) to add to fixedSpacing between each portal."
48
48
  })
49
+ .option('info', {
50
+ alias: 'i',
51
+ type: 'boolean',
52
+ default: true,
53
+ description: "Run with info logging."
54
+ })
49
55
  .option('verbose', {
50
56
  alias: 'v',
51
57
  type: 'boolean',
@@ -94,20 +100,28 @@ if (cluster.isPrimary) { // Parent process with portal webserver through which c
94
100
  }));
95
101
 
96
102
  app.listen(port);
97
- console.log('Listening on', port, 'and starting', argv.nPortals, 'nodes.');
103
+ console.log(new Date(), `Listening on ${port} and starting ${argv.nPortals} nodes on ${logicalCores} ${cpus()[0].model} logical cores.`);
98
104
  for (let i = 0; i < argv.nPortals; i++) {
99
105
  cluster.fork();
100
- await new Promise(resolve => setTimeout(resolve, 1e3));
106
+ await new Promise(resolve => setTimeout(resolve, 2e3)); // Number chosen to give an unspikey rise in packets/s.
101
107
  }
102
108
  } else {
103
109
  process.title = 'axona-starting';
104
110
  const { P2PWebNetwork, location } = await import('../index.js');
105
- const network = await P2PWebNetwork.create({region: location});
111
+ const network = await P2PWebNetwork.create({
112
+ region: location,
113
+ infoLogger: (...rest) => argv.info && console.log(new Date(), ...rest),
114
+ debugLogger: (...rest) => argv.verbose && console.log(new Date(), ...rest)
115
+ });
106
116
  process.title = 'axona-' + network.nodeIdentity.id;
107
- //let update = setInterval(() => network.info(network.peer.health().axonRoles.length, 'axons'), 10e3);
117
+ let update = setInterval(() => {
118
+ const roles = network.peer.health().axonRoles;
119
+ network.debug(roles.length, 'axons',
120
+ roles.reduce((total, role) => total + (role.isRoot ? 1 : 0), 0), 'roots');
121
+ }, 10e3);
108
122
  process.on('SIGINT', async () => { // Leave the network politely.
109
123
  console.log(process.title, 'Shutdown for Ctrl+C');
110
- //clearInterval(update)
124
+ clearInterval(update)
111
125
  await network.disconnect();
112
126
  process.exit(0);
113
127
  });
@@ -0,0 +1,7 @@
1
+ {
2
+ "uswest/80": "37.4852,-122.2364",
3
+ "useast/89": "40,-75",
4
+ "uscentle/88": "35,-83",
5
+ "easteu/47": "50,17",
6
+ "loc": "37,-122"
7
+ }