Merge pull request #641 from vector-im/bwindels/location-tile
add location tile view so we don't throw when a location is shared
This commit is contained in:
commit
9220b6675b
4 changed files with 74 additions and 11 deletions
|
@ -16,21 +16,43 @@ limitations under the License.
|
||||||
|
|
||||||
import {BaseMessageTile} from "./BaseMessageTile.js";
|
import {BaseMessageTile} from "./BaseMessageTile.js";
|
||||||
|
|
||||||
/*
|
|
||||||
map urls:
|
|
||||||
apple: https://developer.apple.com/library/archive/featuredarticles/iPhoneURLScheme_Reference/MapLinks/MapLinks.html
|
|
||||||
android: https://developers.google.com/maps/documentation/urls/guide
|
|
||||||
wp: maps:49.275267 -122.988617
|
|
||||||
https://www.habaneroconsulting.com/stories/insights/2011/opening-native-map-apps-from-the-mobile-browser
|
|
||||||
*/
|
|
||||||
export class LocationTile extends BaseMessageTile {
|
export class LocationTile extends BaseMessageTile {
|
||||||
|
get shape() {
|
||||||
|
return "location";
|
||||||
|
}
|
||||||
|
|
||||||
get mapsLink() {
|
get mapsLink() {
|
||||||
const geoUri = this._getContent().geo_uri;
|
try {
|
||||||
const [lat, long] = geoUri.split(":")[1].split(",");
|
const url = new URL(this._getContent().geo_uri);
|
||||||
return `maps:${lat} ${long}`;
|
if (url.protocol !== "geo:") {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
const [locationStr, ...namedParams] = url.pathname.split(";");
|
||||||
|
const [latStr, longStr] = locationStr.split(",");
|
||||||
|
const lat = parseFloat(latStr);
|
||||||
|
const long = parseFloat(longStr);
|
||||||
|
let uncertainty;
|
||||||
|
for (const namedParam of namedParams) {
|
||||||
|
const [name, value] = namedParam.split("=");
|
||||||
|
if (name === "u") {
|
||||||
|
uncertainty = parseFloat(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.platform.isIOS) {
|
||||||
|
return `http://maps.apple.com/?ll=${lat},${long}`;
|
||||||
|
} else {
|
||||||
|
let uri = `geo:${lat},${long}`;
|
||||||
|
if (uncertainty) {
|
||||||
|
uri = uri + `;u=${uncertainty}`;
|
||||||
|
}
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get label() {
|
get label() {
|
||||||
return `${this.sender} sent their location, click to see it in maps.`;
|
return this.i18n`${this.displayName} sent their location`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -363,6 +363,18 @@ only loads when the top comes into view*/
|
||||||
animation-timing-function: linear;
|
animation-timing-function: linear;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.Timeline_locationLink {
|
||||||
|
padding: 0px 8px;
|
||||||
|
border-radius: 16px;
|
||||||
|
border: 1px solid #e9edf1;
|
||||||
|
background-color: #f3f8fd;
|
||||||
|
text-decoration: none;
|
||||||
|
display: inline-block;
|
||||||
|
line-height: 2rem;
|
||||||
|
vertical-align: top;
|
||||||
|
margin: 1px 4px;
|
||||||
|
}
|
||||||
|
|
||||||
.AnnouncementView {
|
.AnnouncementView {
|
||||||
margin: 5px 0;
|
margin: 5px 0;
|
||||||
padding: 5px 10%;
|
padding: 5px 10%;
|
||||||
|
|
|
@ -22,6 +22,7 @@ import {TextMessageView} from "./timeline/TextMessageView.js";
|
||||||
import {ImageView} from "./timeline/ImageView.js";
|
import {ImageView} from "./timeline/ImageView.js";
|
||||||
import {VideoView} from "./timeline/VideoView.js";
|
import {VideoView} from "./timeline/VideoView.js";
|
||||||
import {FileView} from "./timeline/FileView.js";
|
import {FileView} from "./timeline/FileView.js";
|
||||||
|
import {LocationView} from "./timeline/LocationView.js";
|
||||||
import {MissingAttachmentView} from "./timeline/MissingAttachmentView.js";
|
import {MissingAttachmentView} from "./timeline/MissingAttachmentView.js";
|
||||||
import {AnnouncementView} from "./timeline/AnnouncementView.js";
|
import {AnnouncementView} from "./timeline/AnnouncementView.js";
|
||||||
import {RedactedView} from "./timeline/RedactedView.js";
|
import {RedactedView} from "./timeline/RedactedView.js";
|
||||||
|
@ -49,6 +50,7 @@ export function viewClassForEntry(entry: SimpleTile): TileViewConstructor | unde
|
||||||
case "image": return ImageView;
|
case "image": return ImageView;
|
||||||
case "video": return VideoView;
|
case "video": return VideoView;
|
||||||
case "file": return FileView;
|
case "file": return FileView;
|
||||||
|
case "location": return LocationView;
|
||||||
case "missing-attachment": return MissingAttachmentView;
|
case "missing-attachment": return MissingAttachmentView;
|
||||||
case "redacted":
|
case "redacted":
|
||||||
return RedactedView;
|
return RedactedView;
|
||||||
|
|
27
src/platform/web/ui/session/room/timeline/LocationView.js
Normal file
27
src/platform/web/ui/session/room/timeline/LocationView.js
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 Bruno Windels <bruno@windels.cloud>
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {BaseMessageView} from "./BaseMessageView.js";
|
||||||
|
|
||||||
|
export class LocationView extends BaseMessageView {
|
||||||
|
renderMessageBody(t, vm) {
|
||||||
|
return t.p({className: "Timeline_messageBody statusMessage"}, [
|
||||||
|
t.span(vm.label),
|
||||||
|
t.a({className: "Timeline_locationLink", href: vm.mapsLink, target: "_blank", rel: "noopener"}, vm.i18n`Click to open in maps`),
|
||||||
|
t.time(vm.date + " " + vm.time)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
Reference in a new issue