diff --git a/src/domain/session/room/timeline/tiles/LocationTile.js b/src/domain/session/room/timeline/tiles/LocationTile.js index fddc4501..e5f7e1a3 100644 --- a/src/domain/session/room/timeline/tiles/LocationTile.js +++ b/src/domain/session/room/timeline/tiles/LocationTile.js @@ -16,21 +16,43 @@ limitations under the License. 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 { + get shape() { + return "location"; + } + get mapsLink() { - const geoUri = this._getContent().geo_uri; - const [lat, long] = geoUri.split(":")[1].split(","); - return `maps:${lat} ${long}`; + try { + const url = new URL(this._getContent().geo_uri); + 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() { - return `${this.sender} sent their location, click to see it in maps.`; + return this.i18n`${this.displayName} sent their location`; } } diff --git a/src/platform/web/ui/css/themes/element/timeline.css b/src/platform/web/ui/css/themes/element/timeline.css index 6558c003..21ec660f 100644 --- a/src/platform/web/ui/css/themes/element/timeline.css +++ b/src/platform/web/ui/css/themes/element/timeline.css @@ -363,6 +363,18 @@ only loads when the top comes into view*/ 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 { margin: 5px 0; padding: 5px 10%; diff --git a/src/platform/web/ui/session/room/TimelineView.ts b/src/platform/web/ui/session/room/TimelineView.ts index da3dc537..62b7656a 100644 --- a/src/platform/web/ui/session/room/TimelineView.ts +++ b/src/platform/web/ui/session/room/TimelineView.ts @@ -22,6 +22,7 @@ import {TextMessageView} from "./timeline/TextMessageView.js"; import {ImageView} from "./timeline/ImageView.js"; import {VideoView} from "./timeline/VideoView.js"; import {FileView} from "./timeline/FileView.js"; +import {LocationView} from "./timeline/LocationView.js"; import {MissingAttachmentView} from "./timeline/MissingAttachmentView.js"; import {AnnouncementView} from "./timeline/AnnouncementView.js"; import {RedactedView} from "./timeline/RedactedView.js"; @@ -49,6 +50,7 @@ export function viewClassForEntry(entry: SimpleTile): TileViewConstructor | unde case "image": return ImageView; case "video": return VideoView; case "file": return FileView; + case "location": return LocationView; case "missing-attachment": return MissingAttachmentView; case "redacted": return RedactedView; diff --git a/src/platform/web/ui/session/room/timeline/LocationView.js b/src/platform/web/ui/session/room/timeline/LocationView.js new file mode 100644 index 00000000..62073782 --- /dev/null +++ b/src/platform/web/ui/session/room/timeline/LocationView.js @@ -0,0 +1,27 @@ +/* +Copyright 2020 Bruno Windels + +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) + ]); + } +}