Browse Source

Get user position and display nearby people on map (close #2)

master
Skylar Ittner 3 months ago
parent
commit
83bef5b3d5
6 changed files with 225 additions and 15 deletions
  1. 3
    1
      package.json
  2. 58
    2
      www/js/api.js
  3. 2
    2
      www/js/home.js
  4. 114
    2
      www/js/map.js
  5. 32
    0
      www/js/platform.js
  6. 16
    8
      www/pages/home.html

+ 3
- 1
package.json View File

@@ -12,6 +12,7 @@
12 12
   "dependencies": {
13 13
     "cordova-android": "^8.0.0",
14 14
     "cordova-plugin-app-version": "^0.1.9",
15
+    "cordova-plugin-geolocation": "^4.0.1",
15 16
     "cordova-plugin-headercolor": "^1.0.0",
16 17
     "cordova-plugin-inappbrowser": "^3.0.0",
17 18
     "cordova-plugin-statusbar": "^2.4.2",
@@ -27,7 +28,8 @@
27 28
       "cordova-plugin-inappbrowser": {},
28 29
       "phonegap-plugin-barcodescanner": {
29 30
         "ANDROID_SUPPORT_V4_VERSION": "27.+"
30
-      }
31
+      },
32
+      "cordova-plugin-geolocation": {}
31 33
     },
32 34
     "platforms": [
33 35
       "android"

+ 58
- 2
www/js/api.js View File

@@ -4,6 +4,15 @@
4 4
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 5
  */
6 6
 
7
+/**
8
+ * Get the API endpoint URL for an action
9
+ * @param {String} action
10
+ * @return {String}
11
+ */
12
+function getActionUrl(action) {
13
+    return SETTINGS["server"] + "/" + action;
14
+}
15
+
7 16
 /**
8 17
  * Call an API function on the server.
9 18
  * @param {string} action
@@ -16,19 +25,66 @@ function callAPI(action, data, success, failure) {
16 25
     return $.ajax({
17 26
         type: 'POST',
18 27
         dataType: 'json',
19
-        url: SETTINGS["server"] + "/" + action,
28
+        url: getActionUrl(action),
20 29
         data: data,
21 30
         timeout: 5000,
22 31
         success: function (data, textStatus) {
23 32
             if (data.status === "OK") {
24 33
                 success(data);
25
-            } else if (data.status === "ERROR") {
34
+                return;
35
+            }
36
+            if (typeof failure != 'function') {
37
+                return;
38
+            }
39
+            if (data.status === "ERROR") {
26 40
                 failure(data.msg);
27 41
             } else {
28 42
                 failure("The server sent an invalid response.");
29 43
             }
30 44
         },
31 45
         error: function (xhr, textStatus, errorThrown) {
46
+            if (typeof failure != 'function') {
47
+                return;
48
+            }
49
+            switch (textStatus) {
50
+                case "timeout":
51
+                    failure("Couldn't connect to the server (timeout).");
52
+                    break;
53
+                case "error":
54
+                    failure("Couldn't connect to the server (error).");
55
+                    break;
56
+                case "parseerror":
57
+                    failure("The server sent a malformed response.");
58
+                    break;
59
+                default:
60
+                    failure("Couldn't connect to the server.");
61
+            }
62
+        }
63
+    });
64
+}
65
+
66
+/**
67
+ * Call an API function on the server.  Makes fewer assumptions about what
68
+ * constitutes a success response.
69
+ * @param {string} action
70
+ * @param {array} data key: value array of arguments for the server.
71
+ * @param {function} success Called with the JSON response object.
72
+ * @param {function} failure Called with an error message string.
73
+ * @return {undefined}
74
+ */
75
+function callAPIRawResponse(action, data, success, failure) {
76
+    return $.ajax({
77
+        type: 'POST',
78
+        url: getActionUrl(action),
79
+        data: data,
80
+        timeout: 5000,
81
+        success: function (data, textStatus) {
82
+            success(data);
83
+        },
84
+        error: function (xhr, textStatus, errorThrown) {
85
+            if (typeof failure != 'function') {
86
+                return;
87
+            }
32 88
             switch (textStatus) {
33 89
                 case "timeout":
34 90
                     failure("Couldn't connect to the server (timeout).");

+ 2
- 2
www/js/home.js View File

@@ -18,7 +18,7 @@ $(".view-main").on("card:open", ".card-expandable", function () {
18 18
 });
19 19
 
20 20
 $(".view-main").on("card:closed", "#map-card", function () {
21
-    leafletgllayer._glMap.setPitch(0);
21
+    //leafletgllayer._glMap.setPitch(0);
22 22
     leafletmap.invalidateSize();
23 23
 });
24 24
 
@@ -46,7 +46,7 @@ function loadBalance(callback) {
46 46
 }
47 47
 
48 48
 function openMapCard() {
49
-    leafletgllayer._glMap.setPitch(40);
49
+    //leafletgllayer._glMap.setPitch(40);
50 50
     leafletmap.invalidateSize();
51 51
 }
52 52
 

+ 114
- 2
www/js/map.js View File

@@ -4,12 +4,20 @@
4 4
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 5
  */
6 6
 
7
+var userPositionIsReal = false;
8
+var userposition = {
9
+    coords: {
10
+        latitude: 46.595,
11
+        longitude: -112.019,
12
+        accuracy: 10000
13
+    }
14
+};
7 15
 
8 16
 var leafletmap = L.map('map', {
9 17
     minZoom: 12,
10 18
     maxZoom: 20
11 19
 });
12
-leafletmap.setView([46.595, -112.019], 13);
20
+
13 21
 leafletmap.attributionControl.setPrefix("");
14 22
 var leafletgllayer = L.mapboxGL({
15 23
     attribution: "© OpenMapTiles © OpenStreetMap contributors",
@@ -18,4 +26,108 @@ var leafletgllayer = L.mapboxGL({
18 26
     pitch: 0
19 27
 });
20 28
 
21
-leafletgllayer.addTo(leafletmap);
29
+leafletgllayer.addTo(leafletmap);
30
+
31
+L.control.scale().addTo(leafletmap);
32
+
33
+var leafletpeoplelayer = L.geoJson(
34
+        {
35
+            name: "Nearby People",
36
+            type: "FeatureCollection",
37
+            features: [
38
+                {
39
+                    type: "Feature",
40
+                    geometry: {
41
+                        type: "Point",
42
+                        coordinates: [0, 0]
43
+                    },
44
+                    properties: {
45
+                        id: "",
46
+                        name: "",
47
+                        username: "",
48
+                        verified: false
49
+                    }
50
+                }
51
+            ]
52
+        },
53
+        {
54
+            onEachFeature: function (feature, layer) {
55
+                if (feature.properties && feature.properties.popupContent) {
56
+                    layer.bindPopup(feature.properties.popupContent);
57
+                }
58
+            },
59
+            pointToLayer: function (feature, latlng) {
60
+                return L.marker(latlng);
61
+//                return L.circleMarker(latlng, {
62
+//                    radius: 14,
63
+//                    fillColor: "#f00",
64
+//                    color: "#000",
65
+//                    weight: 1,
66
+//                    opacity: 1,
67
+//                    fillOpacity: 0.6
68
+//                });
69
+            }
70
+        }
71
+);
72
+
73
+function updateMap() {
74
+    var diagonalMeters = leafletmap.getBounds().getNorthWest().distanceTo(leafletmap.getBounds().getSouthEast());
75
+    var radius = (diagonalMeters / 2.0) / 1609.344;
76
+    callAPIRawResponse("getnearby", {
77
+        key: localStorage.getItem("key"),
78
+        latitude: leafletmap.getCenter().lat,
79
+        longitude: leafletmap.getCenter().lng,
80
+        radius: radius,
81
+        format: "geojson"
82
+    }, function (data) {
83
+        if (data.type == "FeatureCollection") {
84
+            leafletpeoplelayer.clearLayers();
85
+            data.features.forEach(function (item) {
86
+                item.properties.popupContent = "<i class=\"fas fa-user\"></i> " + item.properties.name + "<br><br><a class=\"button button-small button-fill text-color-white\" href=\"/sendmoney/" + item.properties.id + "\">Send Money</a>";
87
+                leafletpeoplelayer.addData(item);
88
+            });
89
+            leafletmap.addLayer(leafletpeoplelayer);
90
+        }
91
+    });
92
+}
93
+
94
+function recenterMapPosition() {
95
+    var zoom = 13;
96
+    if (userposition.coords.accuracy < 100) {
97
+        zoom = 15;
98
+    }
99
+    if (userposition.coords.accuracy < 50) {
100
+        zoom = 16;
101
+    }
102
+    leafletmap.setView([userposition.coords.latitude, userposition.coords.longitude], zoom);
103
+}
104
+
105
+function recenterMapToUserPosition() {
106
+    if (userPositionIsReal == false) {
107
+        getLocation(function (position) {
108
+            userposition = position;
109
+            userPositionIsReal = true;
110
+            recenterMapPosition();
111
+        });
112
+    } else {
113
+        recenterMapPosition();
114
+    }
115
+}
116
+
117
+// Attempt to get user location
118
+watchLocation(function (position) {
119
+    userposition = position;
120
+    if (userPositionIsReal == false) {
121
+        recenterMapPosition();
122
+        userPositionIsReal = true;
123
+    }
124
+});
125
+
126
+// Set map to default position
127
+recenterMapPosition();
128
+// Load nearby people
129
+updateMap();
130
+// Watch for map moving
131
+leafletmap.on("moveend", function () {
132
+    updateMap();
133
+});

+ 32
- 0
www/js/platform.js View File

@@ -14,6 +14,38 @@ var openBrowser = function (url) {
14 14
 
15 15
 }
16 16
 
17
+var getLocation = function (success, error) {
18
+    if ("geolocation" in navigator) {
19
+        navigator.geolocation.getCurrentPosition(function (position) {
20
+            success(position);
21
+        }, function (err) {
22
+            error(err.message);
23
+        }, {
24
+            enableHighAccuracy: true,
25
+            timeout: 5000,
26
+            maximumAge: 0
27
+        });
28
+    } else {
29
+        error("Location is unavailable.");
30
+    }
31
+}
32
+
33
+var watchLocation = function (success, error) {
34
+    if ("geolocation" in navigator) {
35
+        navigator.geolocation.watchPosition(function (position) {
36
+            success(position);
37
+        }, function (err) {
38
+            error(err.message);
39
+        }, {
40
+            enableHighAccuracy: true,
41
+            timeout: 5000,
42
+            maximumAge: 0
43
+        });
44
+    } else {
45
+        error("Location is unavailable.");
46
+    }
47
+}
48
+
17 49
 function initCordova() {
18 50
     platform_type = "cordova";
19 51
 

+ 16
- 8
www/pages/home.html View File

@@ -84,17 +84,25 @@
84 84
             <div class="col-100 tablet-50 desktop-33">
85 85
                 <div class="card card-expandable elevation-2" id="map-card" style="margin-top: var(--f7-card-margin-vertical);" onclick="openMapCard()">
86 86
 
87
-                    <div class="card-content text-align-center" style="min-height: 16.58em;">
88
-
89
-                        <div class="card-header card-opened-fade-out" style="z-index: 9999999; background-color: rgba(255,255,255,0.5);">
90
-                            Nearby
87
+                    <div class="card-header card-opened-fade-out" style="z-index: 9999999; background-color: rgba(255,255,255,0.5);">
88
+                        <div>Nearby</div>
89
+                        <div>
90
+                            <span class="link icon-only card-prevent-open" onclick="recenterMapToUserPosition()" style="margin-top: 0.1em; cursor: pointer;">
91
+                                <i class="material-icons" style="font-size: 16pt;">my_location</i>
92
+                            </span>
91 93
                         </div>
94
+                    </div>
95
+
96
+                    <div class="card-content text-align-center" style="min-height: 16.58em;">
92 97
 
93 98
                         <div class="navbar card-opened-fade-in">
94 99
                             <div class="navbar-inner">
95 100
                                 <div class="title">Nearby</div>
96 101
 
97 102
                                 <div class="right">
103
+                                    <a href="" class="link icon-only" onclick="recenterMapToUserPosition()">
104
+                                        <i class="material-icons">my_location</i>
105
+                                    </a>
98 106
                                     <a href="#" class="link icon-only card-close">
99 107
                                         <i class="material-icons">close</i>
100 108
                                     </a>
@@ -124,11 +132,11 @@
124 132
     <script src="js/home.js"></script>
125 133
 
126 134
     <script>
127
-                    setTimeout(function () {
128
-                        loadHomePage(function () {
135
+                                        setTimeout(function () {
136
+                                            loadHomePage(function () {
129 137
 
130
-                        });
131
-                    }, 500);
138
+                                            });
139
+                                        }, 500);
132 140
     </script>
133 141
 
134 142
 </div>

Loading…
Cancel
Save