Location sharing

This commit is contained in:
Tony Garnock-Jones 2016-06-05 16:42:30 -04:00
parent 02f4f9f89c
commit f4d1f5c800
3 changed files with 218 additions and 0 deletions

View File

@ -0,0 +1,52 @@
<!doctype html>
<html>
<head>
<title>Syndicate: Location</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<link href="style.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/2.2.1/mustache.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/blueimp-md5/2.3.0/js/md5.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAgjLSNu9Cx4V1bNxhSTM4ZzqADbGoYmZ0"></script>
<script src="../../dist/syndicatecompiler.js"></script>
<script src="../../dist/syndicate.js"></script>
<script type="text/syndicate-js" src="index.js"></script>
</head>
<body>
<template id="json">
<pre>{{ blob }}</pre>
</template>
<template id="info">
<div>
<p>
{{ email }}<br>
{{ address}}<br>
<small>Last update: {{ timestamp }}</small>
</p>
</div>
</template>
<template id="markerList-option">
<option value="{{ id }}">{{ email }}</option>
</template>
<div id="map"></div>
<div class="row">
<fieldset>
<label for="my_email">Email (or name):</label>
<input type="email" name="my_email" id="my_email">
</fieldset>
<fieldset>
<label for="group">Group key:</label>
<input type="text" name="group" id="group">
</fieldset>
</div>
<div class="row">
<fieldset>
<select id="markerList"></select>
<button id="findMarker">Find</button>
</fieldset>
</div>
</body>
</html>

View File

@ -0,0 +1,140 @@
assertion type location(id, email, timestamp, lat, lng);
message type findMarker(id);
var brokerConnection = Syndicate.Broker.brokerConnection;
var toBroker = Syndicate.Broker.toBroker;
var fromBroker = Syndicate.Broker.fromBroker;
ground dataspace G {
Syndicate.UI.spawnUIDriver();
Syndicate.Timer.spawnTimerDriver();
Syndicate.Broker.spawnBrokerClientDriver();
actor {
var id = Syndicate.RandomID.randomId(4, true);
var email_element = document.getElementById('my_email');
if (localStorage.my_email) {
email_element.value = localStorage.my_email;
} else {
localStorage.my_email = email_element.value = id;
}
var group_element = document.getElementById('group');
var url_group_match = /group=(.*)$/.exec(document.location.search || '');
if (url_group_match) {
localStorage.group = group_element.value = url_group_match[1];
} else if (localStorage.group) {
group_element.value = localStorage.group;
} else {
localStorage.group = group_element.value = 'Public';
}
var mapInitialized = false;
var map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 42, lng: -71},
zoom: 18
});
var infoWindow = new google.maps.InfoWindow();
var geocoder = new google.maps.Geocoder();
var wsurl_base = 'wss://demo-broker.syndicate-lang.org:8443/location/';
var wsurl = wsurl_base + group_element.value.trim();
var watchId = ('geolocation' in navigator)
&& navigator.geolocation.watchPosition(Syndicate.Dataspace.wrap(function (pos) {
:: location(id,
email_element.value.trim(),
+new Date(),
pos.coords.latitude,
pos.coords.longitude);
if (!mapInitialized && map) {
mapInitialized = true;
map.setCenter({lat: pos.coords.latitude, lng: pos.coords.longitude});
}
}));
react {
var currentLocation = null;
var selectedMarker = null;
assert brokerConnection(wsurl);
assert toBroker(wsurl, currentLocation) when (currentLocation);
on message Syndicate.UI.globalEvent('#my_email', 'change', _) {
localStorage.my_email = currentLocation[1] = email_element.value.trim();
}
on message Syndicate.UI.globalEvent('#group', 'change', _) {
localStorage.group = group_element.value.trim();
wsurl = wsurl_base + group_element.value.trim();
}
on message Syndicate.UI.globalEvent('#findMarker', 'click', $e) {
:: findMarker(document.getElementById('markerList').value);
}
on message Syndicate.UI.globalEvent('#markerList', 'change', $e) {
:: findMarker(document.getElementById('markerList').value);
}
on message ($loc = location(_, _, _, _, _)) {
currentLocation = loc;
}
during fromBroker(wsurl, location($id, $email, _, _, _)) {
var ui = new Syndicate.UI.Anchor();
var marker = new google.maps.Marker({
map: map,
clickable: true,
icon: 'https://www.gravatar.com/avatar/' + md5(email.trim().toLowerCase()) + '?s=32&d=retro'
});
var latestTimestamp = null;
var latestPosition = null;
function selectMarker() {
selectedMarker = marker;
updateInfoWindow();
infoWindow.open(map, marker);
}
function updateInfoWindow() {
if (selectedMarker === marker && latestPosition && latestTimestamp) {
geocoder.geocode({'location': latestPosition}, function (results, status) {
if (status === google.maps.GeocoderStatus.OK && results[0]) {
infoWindow.setContent(Mustache.render(document.getElementById('info').innerHTML, {
email: email,
timestamp: latestTimestamp ? latestTimestamp.toString() : '',
address: results[0].formatted_address
}));
}
});
}
}
do {
marker.addListener('click', Syndicate.Dataspace.wrap(function () {
selectMarker();
}));
}
assert ui.html('#markerList',
Mustache.render(document.getElementById('markerList-option').innerHTML, {
id: id,
email: email
}));
on message findMarker(id) {
selectMarker();
if (latestPosition) map.panTo(latestPosition);
}
on asserted fromBroker(wsurl, location(id, email, $timestamp, $lat, $lng)) {
latestTimestamp = new Date(timestamp);
latestPosition = {lat: lat, lng: lng};
marker.setPosition(latestPosition);
marker.setTitle(email + ' ' + latestTimestamp.toTimeString());
updateInfoWindow();
}
finally {
marker.setMap(null);
if (selectedMarker === marker) selectedMarker = null;
}
}
}
}
}

View File

@ -0,0 +1,26 @@
template {
display: none;
}
#map {
width: 100%;
height: 75vh;
}
.row {
display: flex;
}
.row fieldset {
flex: 1;
border: none;
}
.row fieldset label {
display: inline-block;
}
.row fieldset input {
display: inline-block;
width: 100%;
}