@yz-social/civildefense.io 4.5.8 → 4.5.16
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/index.js +2 -1
- package/package.json +5 -3
- package/public/about/en.html +1 -1
- package/public/about/es.html +1 -1
- package/public/images/loading.gif +0 -0
- package/public/index.html +106 -107
- package/public/javascripts/agent.js +37 -30
- package/public/javascripts/alert.js +112 -64
- package/public/javascripts/conversation.js +8 -5
- package/public/javascripts/hashtags.js +247 -43
- package/public/javascripts/main.js +6 -2
- package/public/javascripts/map.js +4 -2
- package/public/javascripts/p2pWebNetwork.js +31 -10
- package/public/javascripts/s2.js +7 -3
- package/public/javascripts/service-manager.js +5 -4
- package/public/javascripts/translations.js +1 -0
- package/public/javascripts/versions.js +16 -5
- package/public/service-worker.js +7 -7
- package/public/stylesheets/style.css +74 -12
- package/server/app.js +34 -23
- package/server/{location.json → location.save.json} +1 -1
- package/spec/axonSpec.js +9 -8
- package/spec/conversationSpec.js +2 -2
- package/public/junk.html +0 -145
package/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { P2PWebNetwork } from "./public/javascripts/p2pWebNetwork.js";
|
|
2
|
-
export { agentTopic, alertTopic, canonicalTag } from "./public/javascripts/versions.js";
|
|
2
|
+
export { topicRegion, agentTopic, alertTopic, canonicalTag } from "./public/javascripts/versions.js";
|
|
3
3
|
export { getContainingCells } from "./public/javascripts/s2.js";
|
|
4
4
|
export { location } from "./server/getLocation.js";
|
|
5
|
+
export { deriveTopicIdBig } from "@axona/protocol";
|
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.
|
|
4
|
+
"version": "4.5.16",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"map",
|
|
7
7
|
"browser",
|
|
@@ -10,14 +10,16 @@
|
|
|
10
10
|
"scripts": {
|
|
11
11
|
"start": "npm stop; node ./server/app.js",
|
|
12
12
|
"stop": "pkill yz.social",
|
|
13
|
-
"postinstall": "touch server/location.json; chmod a+w server/location.json"
|
|
13
|
+
"postinstall": "touch server/location.json; chmod a+w server/location.json",
|
|
14
|
+
"prepack": "mv server/location.json server/location.save.json",
|
|
15
|
+
"postpack": "mv server/location.save.json server/location.json"
|
|
14
16
|
},
|
|
15
17
|
"type": "module",
|
|
16
18
|
"exports": {
|
|
17
19
|
".": "./index.js"
|
|
18
20
|
},
|
|
19
21
|
"dependencies": {
|
|
20
|
-
"@axona/protocol": "github:axona-net/axona-protocol#semver:^4.
|
|
22
|
+
"@axona/protocol": "github:axona-net/axona-protocol#semver:^4.59.2",
|
|
21
23
|
"cors": "^2.8.6",
|
|
22
24
|
"express": "^4.22.1",
|
|
23
25
|
"leaflet": "^1.9.4",
|
package/public/about/en.html
CHANGED
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
<!-- <hr class="rule"> -->
|
|
129
129
|
|
|
130
130
|
<h1>The Bigger Picture</h1>
|
|
131
|
-
<p>The Civil Defense
|
|
131
|
+
<p>The Civil Defense runs on the <a href="https://github.com/axona-net/axona-protocol" target="yz.other" rel="noopener">Axona network</a>. Both are free and open source.</p>
|
|
132
132
|
<p>Axona is a modern descendant of the old <a href="https://en.wikipedia.org/wiki/Peer-to-peer" target="yz.other" rel="noopener">peer-to-peer networks</a> such as <a href="https://en.wikipedia.org/wiki/Napster">Napster</a>. It has a unique self-healing routing mechanism that uses neuron learning techniques to find the best way to distribute alerts. It is analogous to <a href="https://en.wikipedia.org/wiki/Tor_(network)" target="yz.other" rel="noopener">TOR</a> (The Onion Router), but designed from the ground up to run in mobile and desktop browsers.</p>
|
|
133
133
|
<p>We are also developing a comprehensive quantum-ready cryptography system that will add private-groups for Civil Defense and any software on the network. We believe there are many applications where developers, users, and the public all benefit from open software and secure, decentralized networks — without app stores, servers, or data centers. Beyond Civil Defense, we are also developing large-scale <a href="https://en.wikipedia.org/wiki/Distributed_computing" target="yz.other" rel="noopener">multiuser collaboration</a> and <a href="https://poverty-action.org/inclusive-instant-payment-systems-evidence-based-approach-design-impact" target="yz.other" rel="noopener">Inclusive Instant Payment Systems</a>.</p>
|
|
134
134
|
|
package/public/about/es.html
CHANGED
|
@@ -113,7 +113,7 @@
|
|
|
113
113
|
</ul>
|
|
114
114
|
|
|
115
115
|
<h1>El Panorama General</h1>
|
|
116
|
-
<p>
|
|
116
|
+
<p>La Defensa Civil opera en la <a href="https://github.com/axona-net/axona-protocol" target="yz.other" rel="noopener">red Axona</a>. Ambos son gratuitos y de código abierto.</p>
|
|
117
117
|
<p>Axona es un descendiente moderno de las antiguas <a href="https://en.wikipedia.org/wiki/Peer-to-peer" target="yz.other" rel="noopener">redes entre pares</a> como <a href="https://en.wikipedia.org/wiki/Napster">Napster</a>. Tiene un mecanismo único de enrutamiento autocurativo que utiliza técnicas de aprendizaje neuronal para encontrar la mejor manera de distribuir alertas. Es análogo a <a href="https://en.wikipedia.org/wiki/Tor_(network)" target="yz.other" rel="noopener">TOR</a> (The Onion Router), pero diseñado desde cero para funcionar en navegadores móviles y de escritorio.</p>
|
|
118
118
|
<p>También estamos desarrollando un sistema integral de criptografía preparado para la era cuántica que añadirá grupos privados para Defensa Civil y cualquier software en la red. Creemos que hay muchas aplicaciones en las que los desarrolladores, los usuarios y el público en general se benefician del software abierto y las redes seguras y descentralizadas, sin tiendas de aplicaciones, servidores ni centros de datos. Más allá de Defensa Civil, también estamos desarrollando <a href="https://en.wikipedia.org/wiki/Distributed_computing" target="yz.other" rel="noopener">colaboración multiusuario a gran escala</a> y <a href="https://poverty-action.org/inclusive-instant-payment-systems-evidence-based-approach-design-impact" target="yz.other" rel="noopener">Sistemas de Pago Instantáneo Inclusivos</a>.</p>
|
|
119
119
|
|
|
Binary file
|
package/public/index.html
CHANGED
|
@@ -25,12 +25,11 @@
|
|
|
25
25
|
"uuid": "https://unpkg.com/uuid@13.0.0/dist/index.js",
|
|
26
26
|
"@material/web/": "https://esm.run/@material/web/",
|
|
27
27
|
"s2js": "./s2js/s2js.esm.js",
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
"@axona/protocol/std": "./axona-protocol/std/index.js"
|
|
33
|
-
"@axona/protocol/connect.js": "./axona-protocol/src/connect.js"
|
|
28
|
+
"bigfloat": "./bigfloat/esm/index.js",
|
|
29
|
+
"leaflet": "./leaflet/leaflet-src.esm.js",
|
|
30
|
+
"minidenticons": "./minidenticons/minidenticons.min.js",
|
|
31
|
+
"@axona/protocol": "./axona-protocol/src/index.js",
|
|
32
|
+
"@axona/protocol/std": "./axona-protocol/std/index.js"
|
|
34
33
|
}
|
|
35
34
|
}
|
|
36
35
|
</script>
|
|
@@ -45,123 +44,123 @@
|
|
|
45
44
|
</head>
|
|
46
45
|
<body>
|
|
47
46
|
<section data-nosnippet>
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
<div id="subPopoverControls"> <!-- Our control, that appear within the map and the marker popups in stack order -->
|
|
47
|
+
<div id="mapCapture">
|
|
48
|
+
<div id="map"></div>
|
|
49
|
+
<img src="images/civil-defense-240.png" alt="civildefense" class="about-image">
|
|
50
|
+
</div>
|
|
54
51
|
|
|
55
|
-
<
|
|
56
|
-
<img src="images/civil-defense-240.png" alt="civildefense" class="about-image"></img>
|
|
57
|
-
</button>
|
|
52
|
+
<div id="subPopoverControls"> <!-- Our control, that appear within the map and the marker popups in stack order -->
|
|
58
53
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
<img src="images/qr-scan.svg" alt="qr code" class="button-image">
|
|
62
|
-
</button>
|
|
63
|
-
<button id="share">
|
|
64
|
-
<img src="images/share.svg" alt="share" class="button-image">
|
|
54
|
+
<button id="aboutButton" class="about-button">
|
|
55
|
+
<img src="images/civil-defense-240.png" alt="civildefense" class="about-image"></img>
|
|
65
56
|
</button>
|
|
66
|
-
<button id="recenterButton">
|
|
67
|
-
<img src="images/recenter.svg" alt="recenter on position" class="button-image">
|
|
68
|
-
</button>
|
|
69
|
-
</div>
|
|
70
57
|
|
|
71
|
-
|
|
72
|
-
|
|
58
|
+
<div class="button-container">
|
|
59
|
+
<button id="qrButton">
|
|
60
|
+
<img src="images/qr-scan.svg" alt="qr code" class="button-image">
|
|
61
|
+
</button>
|
|
62
|
+
<button id="share">
|
|
63
|
+
<img src="images/share.svg" alt="share" class="button-image">
|
|
64
|
+
</button>
|
|
65
|
+
<button id="recenterButton">
|
|
66
|
+
<img src="images/recenter.svg" alt="recenter on position" class="button-image">
|
|
67
|
+
</button>
|
|
68
|
+
</div>
|
|
73
69
|
|
|
74
|
-
|
|
70
|
+
<md-chip-set class="watching-hashtags"></md-chip-set>
|
|
71
|
+
</div>
|
|
75
72
|
|
|
76
|
-
|
|
77
|
-
<div class="display-content"></div>
|
|
78
|
-
</div>
|
|
73
|
+
<div id="info" class="info-banner loading"></div>
|
|
79
74
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
<h1>Civil Defense</h1>
|
|
83
|
-
<ul>
|
|
84
|
-
<li id="aboutReport"></li>
|
|
85
|
-
<li id="aboutShared"></li>
|
|
86
|
-
<li id="aboutFade"></li>
|
|
87
|
-
</ul>
|
|
88
|
-
<p> <a id="learnMore" href="about/index.html" target="yz.sidebar">Learn More</a> </p>
|
|
89
|
-
<p>
|
|
90
|
-
<span id="aboutAnyone1"></span>
|
|
91
|
-
<a id="aboutAnyone2" href="https://github.com/YZ-social/Yz.social" target="yz.sidebar"></a>
|
|
92
|
-
<span id="aboutAnyone3"></span>
|
|
93
|
-
</p>
|
|
94
|
-
<hr>
|
|
95
|
-
<div>
|
|
96
|
-
<label>
|
|
97
|
-
<md-checkbox id="showNotifications" touch-target="wrapper"></md-checkbox>
|
|
98
|
-
<span id="showNotificationsLabel"></span>
|
|
99
|
-
</label>
|
|
100
|
-
</div>
|
|
101
|
-
<div class="handle-avatar">
|
|
102
|
-
<md-outlined-text-field id="myHandle" placeholder="anonymous"></md-outlined-text-field>
|
|
103
|
-
<md-outlined-icon-button id="myAvatar"></md-outlined-icon-button>
|
|
104
|
-
</div>
|
|
105
|
-
<hr>
|
|
106
|
-
<div class="source-updates">
|
|
107
|
-
<md-elevated-button id="checkForUpdates"></md-elevated-button>
|
|
108
|
-
<md-elevated-button id="downloadUpdates" class="hidden"></md-elevated-button>
|
|
109
|
-
<span id="updateStatus"></span>
|
|
110
|
-
</div>
|
|
111
|
-
<p><small>
|
|
112
|
-
<label for="scriptChooser"> <span id="version">Version</span></label>
|
|
113
|
-
<span id="appVersion"></span>,
|
|
114
|
-
kernel: <span id="kernelVersion"></span>.
|
|
115
|
-
</small>
|
|
116
|
-
<small><a id="wipe" href="#"></a></small></p>
|
|
117
|
-
<input id="scriptChooser" type="file" accept="text/javascript"></input>
|
|
75
|
+
<div id="qrContainer" class="hidden">
|
|
76
|
+
<div class="display-content"></div>
|
|
118
77
|
</div>
|
|
119
|
-
</div>
|
|
120
78
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
79
|
+
<div id="aboutContainer" class="hidden">
|
|
80
|
+
<div class="display-content">
|
|
81
|
+
<h1>Civil Defense</h1>
|
|
82
|
+
<ul>
|
|
83
|
+
<li id="aboutReport"></li>
|
|
84
|
+
<li id="aboutShared"></li>
|
|
85
|
+
<li id="aboutFade"></li>
|
|
86
|
+
</ul>
|
|
87
|
+
<p> <a id="learnMore" href="about/index.html" target="yz.sidebar">Learn More</a> </p>
|
|
88
|
+
<p>
|
|
89
|
+
<span id="aboutAnyone1"></span>
|
|
90
|
+
<a id="aboutAnyone2" href="https://github.com/YZ-social/Yz.social" target="yz.sidebar"></a>
|
|
91
|
+
<span id="aboutAnyone3"></span>
|
|
92
|
+
</p>
|
|
93
|
+
<hr>
|
|
94
|
+
<div>
|
|
95
|
+
<label>
|
|
96
|
+
<md-checkbox id="showNotifications" touch-target="wrapper"></md-checkbox>
|
|
97
|
+
<span id="showNotificationsLabel"></span>
|
|
98
|
+
</label>
|
|
129
99
|
</div>
|
|
130
|
-
<
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
<
|
|
141
|
-
|
|
142
|
-
|
|
100
|
+
<div class="handle-avatar">
|
|
101
|
+
<md-outlined-text-field id="myHandle" placeholder="anonymous"></md-outlined-text-field>
|
|
102
|
+
<md-outlined-icon-button id="myAvatar"></md-outlined-icon-button>
|
|
103
|
+
</div>
|
|
104
|
+
<hr>
|
|
105
|
+
<div class="source-updates">
|
|
106
|
+
<md-elevated-button id="checkForUpdates"></md-elevated-button>
|
|
107
|
+
<md-elevated-button id="downloadUpdates" class="hidden"></md-elevated-button>
|
|
108
|
+
<span id="updateStatus"></span>
|
|
109
|
+
</div>
|
|
110
|
+
<p><small>
|
|
111
|
+
<label for="scriptChooser"> <span id="version">Version</span></label>
|
|
112
|
+
<span id="appVersion"></span>,
|
|
113
|
+
kernel: <span id="kernelVersion"></span>.
|
|
114
|
+
</small>
|
|
115
|
+
<small><a id="wipe" href="#"></a></small></p>
|
|
116
|
+
<input id="scriptChooser" type="file" accept="text/javascript"></input>
|
|
143
117
|
</div>
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
118
|
+
</div>
|
|
119
|
+
|
|
120
|
+
<div id="correspondentContainer" class="hidden">
|
|
121
|
+
<div class="display-content">
|
|
122
|
+
<div class="private-label">
|
|
123
|
+
<div class="describe">
|
|
124
|
+
<span id="describePrivate1"></span>
|
|
125
|
+
<span class="handle"></span>
|
|
126
|
+
<md-icon class="avatar"></md-icon>
|
|
127
|
+
<span id="describePrivate2"></span>
|
|
128
|
+
</div>
|
|
129
|
+
<md-outlined-text-field></md-outlined-text-field>
|
|
130
|
+
<md-outlined-icon-button></md-outlined-icon-button>
|
|
131
|
+
</div>
|
|
132
|
+
<div id="pickLabels"></div>
|
|
133
|
+
<div class="public-label">
|
|
134
|
+
<div id="describePublic" class="describe"></div>
|
|
135
|
+
<md-outlined-button></md-outlined-button>
|
|
136
|
+
<md-outlined-icon-button></md-outlined-icon-button>
|
|
137
|
+
</div>
|
|
138
|
+
<div class="system-label">
|
|
139
|
+
<div id="describeSystem" class="describe"></div>
|
|
140
|
+
<md-outlined-button></md-outlined-button>
|
|
141
|
+
<md-outlined-icon-button></md-outlined-icon-button>
|
|
142
|
+
</div>
|
|
143
|
+
<input type="file" accept="image/*"></input>
|
|
144
|
+
<div>
|
|
145
|
+
<md-text-button id="correspondentCancel">Cancel</md-text-button>
|
|
146
|
+
<md-text-button id="correspondentOK">OK</md-text-button>
|
|
147
|
+
</div>
|
|
148
148
|
</div>
|
|
149
149
|
</div>
|
|
150
|
-
</div>
|
|
151
150
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
151
|
+
<div id="updateContainer" class="hidden">
|
|
152
|
+
<div class="display-content">
|
|
153
|
+
<h1 id="newVersionHeader">New version available</h1>
|
|
154
|
+
<p id="updateNowQuestion"></p>
|
|
155
|
+
<p id="updateReload"></p>
|
|
156
|
+
<p id="updateDefer"></p>
|
|
157
|
+
<md-elevated-button id="downloadUpdates2"></md-elevated-button>
|
|
158
|
+
<md-elevated-button id="downloadDefer"></md-elevated-button>
|
|
159
|
+
</div>
|
|
160
160
|
</div>
|
|
161
|
-
</div>
|
|
162
161
|
|
|
163
|
-
|
|
164
|
-
<script type="module" src="javascripts/main.js"></script>
|
|
162
|
+
<md-menu positioning="popover" id="popoverMenu"></md-menu>
|
|
165
163
|
</section>
|
|
164
|
+
<script type="module" src="javascripts/main.js"></script>
|
|
166
165
|
</body>
|
|
167
166
|
</html>
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
const { localStorage } = globalThis;
|
|
2
2
|
import { v4 as uuidv4 } from 'uuid';
|
|
3
3
|
import { minidenticonSvg } from 'minidenticons';
|
|
4
|
-
import { createAuthorIdentity } from '@axona/protocol';
|
|
5
4
|
import { agentTopic, agentPersistKey } from './versions.js';
|
|
6
5
|
import { Int } from './translations.js';
|
|
7
6
|
import { consume, openDisplay } from './display.js';
|
|
@@ -65,7 +64,7 @@ export class Agent {
|
|
|
65
64
|
const owner = this.tag;
|
|
66
65
|
['handle', 'avatar'].forEach(type => {
|
|
67
66
|
const eventName = this.networkPersistKey(type);
|
|
68
|
-
contact.subscribe({eventName, region, owner,
|
|
67
|
+
contact.subscribe({eventName, region, owner, since: 'latest', handler: data => this.setPublicData({...data, type})});
|
|
69
68
|
});
|
|
70
69
|
});
|
|
71
70
|
}
|
|
@@ -129,23 +128,25 @@ export class Agent {
|
|
|
129
128
|
const eventName = this.networkPersistKey(type);
|
|
130
129
|
const region = this.currentRegion;
|
|
131
130
|
const owner = this.tag;
|
|
132
|
-
// TODO: set owner as well.
|
|
133
131
|
const contact = await networkPromise;
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
//
|
|
147
|
-
//
|
|
148
|
-
//
|
|
132
|
+
|
|
133
|
+
// First kill previous, if any.
|
|
134
|
+
// Publish doesn't know whether subscribers will be since all or latest, so it must retain all unkilled.
|
|
135
|
+
// Thus if we only kill the last one when there is no value,
|
|
136
|
+
// a subscribe since:latest will produce the PREVIOUS value -- the last unkilled one.
|
|
137
|
+
|
|
138
|
+
const killTag = this.publicMsgId[type];
|
|
139
|
+
console.log('persist', {type, killTag, value: value && value.slice(0, 15)});
|
|
140
|
+
if (killTag) await contact.publish({eventName, region, owner, killTag, payload: null});
|
|
141
|
+
|
|
142
|
+
if (!value) return null;
|
|
143
|
+
let payload = value;
|
|
144
|
+
// Our downsampling is such that we do not need to chunkify.
|
|
145
|
+
// if (type === 'avatar') {
|
|
146
|
+
// const blob = await P2PWebNetwork.dataURL2blob(value);
|
|
147
|
+
// payload = (await contact.chunkifyBlob({blob, region})).topic;
|
|
148
|
+
// }
|
|
149
|
+
return contact.publish({eventName, region, owner, payload});
|
|
149
150
|
}
|
|
150
151
|
|
|
151
152
|
// We represent handles and avatars by inserting stuff into given elements.
|
|
@@ -156,8 +157,9 @@ export class Agent {
|
|
|
156
157
|
element.textContent = value || '(none)';
|
|
157
158
|
element.value = value || ''; // Hack: handle input[type="text"] as well. Must be property assignment, not attribute.
|
|
158
159
|
}
|
|
160
|
+
static spinner = 'images/loading.gif';
|
|
159
161
|
static avatar(element, value) { // Update avatar element with value.
|
|
160
|
-
element.innerHTML = value === null ? '(none)' : (value.startsWith('data') ? this.makeImage(value) : Agent.makeIdenticon(value));
|
|
162
|
+
element.innerHTML = value === null ? '(none)' : (value === this.spinner || value.startsWith('data') ? this.makeImage(value) : Agent.makeIdenticon(value));
|
|
161
163
|
}
|
|
162
164
|
static downsampleResolution = 128; // max height or width
|
|
163
165
|
static makeImage(url) {
|
|
@@ -237,11 +239,8 @@ export class Agent {
|
|
|
237
239
|
this.updateValue(null, 'private', 'avatar');
|
|
238
240
|
};
|
|
239
241
|
fileChooser.onchange = async event => {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
const blob = await P2PWebNetwork.downsampledBlob({blob: fileChooser.files[0], maxDimension: Agent.downsampleResolution});
|
|
243
|
-
this.updateValue(await P2PWebNetwork.blob2dataURL(blob), 'private', 'avatar');
|
|
244
|
-
console.log('clearing avatar selection');
|
|
242
|
+
await this.fileEvent(fileChooser, event, 'private');
|
|
243
|
+
console.log('cleared avatar selection');
|
|
245
244
|
};
|
|
246
245
|
fileChooser.click();
|
|
247
246
|
});
|
|
@@ -263,6 +262,16 @@ export class Agent {
|
|
|
263
262
|
content.parentElement.classList.toggle('hidden', true);
|
|
264
263
|
};
|
|
265
264
|
}
|
|
265
|
+
async fileEvent(fileChooser, event, scope) { // Update value from fileChooser change event, return dataURL;
|
|
266
|
+
consume(event);
|
|
267
|
+
if (!fileChooser.files.length) return '';
|
|
268
|
+
const file = fileChooser.files[0];
|
|
269
|
+
const maxDimension = Agent.downsampleResolution;
|
|
270
|
+
const blob = await P2PWebNetwork.downsampledBlob({blob: file, maxDimension});
|
|
271
|
+
const dataURL = await P2PWebNetwork.blob2dataURL(blob);
|
|
272
|
+
await this.updateValue(dataURL, scope, 'avatar');
|
|
273
|
+
return dataURL;
|
|
274
|
+
}
|
|
266
275
|
static current = null;
|
|
267
276
|
static tag = null;
|
|
268
277
|
static identity = null;
|
|
@@ -275,7 +284,7 @@ export class Agent {
|
|
|
275
284
|
static async initialize() { // Initialize what the agent needs from the about screen
|
|
276
285
|
let tag = localStorage.getItem('usertag');
|
|
277
286
|
const persistAs = tag || uuidv4(); // Give it SOMETHING to persistAs.
|
|
278
|
-
const myIdentity = await createAuthorIdentity({persistAs});
|
|
287
|
+
const myIdentity = await P2PWebNetwork.createAuthorIdentity({persistAs});
|
|
279
288
|
if (tag !== persistAs) { // Fix up persistence by moving it to where it need to go.
|
|
280
289
|
// WARNING: This relies on undocumented behavior of createAuthorIdentity().
|
|
281
290
|
const realTag = myIdentity.authorId;
|
|
@@ -304,17 +313,15 @@ export class Agent {
|
|
|
304
313
|
fileChooser.oncancel = event => {
|
|
305
314
|
consume(event);
|
|
306
315
|
console.log('cancel my avatar');
|
|
316
|
+
myAgent.updateValue(this.spinner, 'public', 'avatar', false);
|
|
307
317
|
myAgent.updateValue(null, 'public', 'avatar');
|
|
308
318
|
myAgent.persistPrivate(null, 'avatar'); // So that we'll have it next session.
|
|
309
319
|
console.log('clearing avatar selection');
|
|
310
320
|
};
|
|
311
321
|
fileChooser.onchange = async event => {
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
const blob = await P2PWebNetwork.downsampledBlob({blob: fileChooser.files[0], maxDimension: Agent.downsampleResolution});
|
|
315
|
-
const url = await P2PWebNetwork.blob2dataURL(blob);
|
|
322
|
+
myAgent.updateValue(this.spinner, 'public', 'avatar', false);
|
|
323
|
+
const url = await myAgent.fileEvent(fileChooser, event, 'public');
|
|
316
324
|
console.log('set my avatar', url.slice(0, 50));
|
|
317
|
-
myAgent.updateValue(url, 'public', 'avatar');
|
|
318
325
|
myAgent.persistPrivate(url, 'avatar'); // So that we'll have it next session.
|
|
319
326
|
};
|
|
320
327
|
fileChooser.click();
|