Open map from timeline (#1199)

* Add navigation to expaneded map

* Add MapLibreMapView.Options

* Add AppActivityView

* Add ShareToMapsAppActivity

* Add share sheet presentation

* Add localisations

* Cleanup

* Fix UT build errors

* Revert breaking change

* Fix UIView setup

* Add support for location’s description

* Show popover on iPad

* Restore assets

* More cleanup
This commit is contained in:
Alfonso Grillo
2023-06-29 11:12:42 +02:00
committed by GitHub
parent 67e48e465f
commit 3f6bfbcc14
22 changed files with 489 additions and 150 deletions
@@ -43,9 +43,9 @@ struct GeoURI: Hashable {
var string: String {
if let uncertainty {
return "geo:\(latitude),\(longitude);u=\(uncertainty)"
return "geo:\(string(for: latitude)),\(string(for: longitude));u=\(string(for: uncertainty))"
} else {
return "geo:\(latitude),\(longitude)"
return "geo:\(string(for: latitude)),\(string(for: longitude))"
}
}
@@ -64,6 +64,10 @@ struct GeoURI: Hashable {
let uncertainty = matchOutput.uncertainty.flatMap(Double.init)
return .init(latitude: latitude, longitude: longitude, uncertainty: uncertainty)
}
private func string(for number: Double) -> String {
NumberFormatter.decimal.string(from: .init(floatLiteral: number)) ?? "\(number)"
}
}
// swiftlint:disable:next large_tuple
@@ -78,3 +82,13 @@ extension GeoURI {
self.init(latitude: coordinate.latitude, longitude: coordinate.longitude)
}
}
private extension NumberFormatter {
static let decimal: NumberFormatter = {
let numberFormatter = NumberFormatter()
numberFormatter.locale = Locale(identifier: "en_US_POSIX")
numberFormatter.numberStyle = .decimal
numberFormatter.maximumFractionDigits = 30
return numberFormatter
}()
}
@@ -115,32 +115,12 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
return .none
}
var source: MediaSourceProxy?
var body: String
switch timelineItem {
case let item as ImageRoomTimelineItem:
source = item.content.source
body = item.content.body
case let item as VideoRoomTimelineItem:
source = item.content.source
body = item.content.body
case let item as FileRoomTimelineItem:
source = item.content.source
body = item.content.body
case let item as AudioRoomTimelineItem:
// For now we are just displaying audio messages with the File preview until we create a timeline player for them.
source = item.content.source
body = item.content.body
case let item as LocationRoomTimelineItem:
guard let geoURI = item.content.geoURI else { return .none }
return .displayLocation(body: item.content.body, geoURI: geoURI)
default:
return .none
}
guard let source else { return .none }
switch await mediaProvider.loadFileFromSource(source, body: body) {
case .success(let file):
return .displayMediaFile(file: file, title: body)
case .failure:
return .none
return await displayMediaActionIfPossible(timelineItem: timelineItem)
}
}
@@ -221,6 +201,37 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
// Recompute all attributed strings on content size changes -> DynamicType support
updateTimelineItems()
}
private func displayMediaActionIfPossible(timelineItem: RoomTimelineItemProtocol) async -> RoomTimelineControllerAction {
var source: MediaSourceProxy?
var body: String
switch timelineItem {
case let item as ImageRoomTimelineItem:
source = item.content.source
body = item.content.body
case let item as VideoRoomTimelineItem:
source = item.content.source
body = item.content.body
case let item as FileRoomTimelineItem:
source = item.content.source
body = item.content.body
case let item as AudioRoomTimelineItem:
// For now we are just displaying audio messages with the File preview until we create a timeline player for them.
source = item.content.source
body = item.content.body
default:
return .none
}
guard let source else { return .none }
switch await mediaProvider.loadFileFromSource(source, body: body) {
case .success(let file):
return .displayMediaFile(file: file, title: body)
case .failure:
return .none
}
}
private func updateTimelineItems() {
var newTimelineItems = [RoomTimelineItemProtocol]()
@@ -26,6 +26,7 @@ enum RoomTimelineControllerCallback {
enum RoomTimelineControllerAction {
case displayMediaFile(file: MediaFileHandleProxy, title: String?)
case displayLocation(body: String, geoURI: GeoURI)
case none
}