mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-04-24 10:32:46 +02:00
Merge branch 'develop' into steve/5903_lls_start
# Conflicts: # Riot/Modules/Room/RoomViewController.h # RiotSwiftUI/Modules/Room/LocationSharing/Coordinator/LocationSharingCoordinator.swift # RiotSwiftUI/Modules/Room/LocationSharing/LocationSharingModels.swift # RiotSwiftUI/Modules/Room/LocationSharing/LocationSharingViewModel.swift
This commit is contained in:
+50
-4
@@ -17,12 +17,44 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
import MatrixSDK
|
||||
|
||||
struct LocationSharingCoordinatorParameters {
|
||||
let roomDataSource: MXKRoomDataSource
|
||||
let mediaManager: MXMediaManager
|
||||
let avatarData: AvatarInputProtocol
|
||||
let location: CLLocationCoordinate2D?
|
||||
let coordinateType: MXEventAssetType
|
||||
}
|
||||
|
||||
// Map between type from MatrixSDK and type from SwiftUI target, as we don't want
|
||||
// to add the SDK as a dependency to it. We need to translate from one to the other on this level.
|
||||
extension MXEventAssetType {
|
||||
func locationSharingCoordinateType() -> LocationSharingCoordinateType {
|
||||
let coordinateType: LocationSharingCoordinateType
|
||||
switch self {
|
||||
case .user, .generic:
|
||||
coordinateType = .user
|
||||
case .pin:
|
||||
coordinateType = .pin
|
||||
@unknown default:
|
||||
coordinateType = .user
|
||||
}
|
||||
return coordinateType
|
||||
}
|
||||
}
|
||||
|
||||
extension LocationSharingCoordinateType {
|
||||
func eventAssetType() -> MXEventAssetType {
|
||||
let eventAssetType: MXEventAssetType
|
||||
switch self {
|
||||
case .user:
|
||||
eventAssetType = .user
|
||||
case .pin:
|
||||
eventAssetType = .pin
|
||||
}
|
||||
return eventAssetType
|
||||
}
|
||||
}
|
||||
|
||||
final class LocationSharingCoordinator: Coordinator, Presentable {
|
||||
@@ -50,6 +82,7 @@ final class LocationSharingCoordinator: Coordinator, Presentable {
|
||||
let viewModel = LocationSharingViewModel(mapStyleURL: BuildSettings.tileServerMapStyleURL,
|
||||
avatarData: parameters.avatarData,
|
||||
location: parameters.location,
|
||||
coordinateType: parameters.coordinateType.locationSharingCoordinateType(),
|
||||
isLiveLocationSharingEnabled: BuildSettings.liveLocationSharingEnabled)
|
||||
let view = LocationSharingView(context: viewModel.context)
|
||||
.addDependency(AvatarService.instantiate(mediaManager: parameters.mediaManager))
|
||||
@@ -71,13 +104,26 @@ final class LocationSharingCoordinator: Coordinator, Presentable {
|
||||
switch result {
|
||||
case .cancel:
|
||||
self.completion?()
|
||||
case .share(let latitude, let longitude):
|
||||
case .share(let latitude, let longitude, let coordinateType):
|
||||
|
||||
// Show share sheet on existing location display
|
||||
if let location = self.parameters.location {
|
||||
self.presentShareLocationActivity(with: location)
|
||||
} else {
|
||||
self.shareStaticLocation(latitude: latitude, longitude: longitude)
|
||||
self.locationSharingHostingController.present(Self.shareLocationActivityController(location), animated: true)
|
||||
return
|
||||
}
|
||||
|
||||
self.locationSharingViewModel.startLoading()
|
||||
|
||||
self.parameters.roomDataSource.sendLocation(withLatitude: latitude, longitude: longitude, description: nil, coordinateType: coordinateType.eventAssetType()) { [weak self] _ in
|
||||
guard let self = self else { return }
|
||||
|
||||
self.locationSharingViewModel.stopLoading()
|
||||
self.completion?()
|
||||
} failure: { [weak self] error in
|
||||
guard let self = self else { return }
|
||||
|
||||
MXLog.error("[LocationSharingCoordinator] Failed sharing location with error: \(String(describing: error))")
|
||||
self.locationSharingViewModel.stopLoading(error: .locationSharingError)
|
||||
}
|
||||
|
||||
case .shareLiveLocation(let timeout):
|
||||
|
||||
+21
-8
@@ -17,22 +17,35 @@
|
||||
import Foundation
|
||||
import Mapbox
|
||||
|
||||
class UserLocationAnnotation: NSObject, MGLAnnotation {
|
||||
class LocationAnnotation: NSObject, MGLAnnotation {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
let avatarData: AvatarInputProtocol
|
||||
|
||||
let coordinate: CLLocationCoordinate2D
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(avatarData: AvatarInputProtocol,
|
||||
coordinate: CLLocationCoordinate2D) {
|
||||
init(coordinate: CLLocationCoordinate2D) {
|
||||
|
||||
self.coordinate = coordinate
|
||||
self.avatarData = avatarData
|
||||
|
||||
super.init()
|
||||
}
|
||||
}
|
||||
|
||||
class PinLocationAnnotation: LocationAnnotation {}
|
||||
|
||||
class UserLocationAnnotation: LocationAnnotation {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
let avatarData: AvatarInputProtocol
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(avatarData: AvatarInputProtocol,
|
||||
coordinate: CLLocationCoordinate2D) {
|
||||
|
||||
self.avatarData = avatarData
|
||||
|
||||
super.init(coordinate: coordinate)
|
||||
}
|
||||
}
|
||||
@@ -19,15 +19,22 @@ import SwiftUI
|
||||
import Combine
|
||||
import CoreLocation
|
||||
|
||||
// This is the equivalent of MXEventAssetType in the MatrixSDK
|
||||
enum LocationSharingCoordinateType {
|
||||
case user
|
||||
case pin
|
||||
}
|
||||
|
||||
enum LocationSharingViewAction {
|
||||
case cancel
|
||||
case share
|
||||
case shareLiveLocation
|
||||
case sharePinLocation
|
||||
case goToUserLocation
|
||||
}
|
||||
|
||||
enum LocationSharingViewModelResult {
|
||||
case cancel
|
||||
case share(latitude: Double, longitude: Double)
|
||||
case share(latitude: Double, longitude: Double, coordinateType: LocationSharingCoordinateType)
|
||||
case shareLiveLocation(timeout: TimeInterval)
|
||||
}
|
||||
|
||||
@@ -47,17 +54,19 @@ struct LocationSharingViewState: BindableState {
|
||||
/// Current user avatarData
|
||||
let userAvatarData: AvatarInputProtocol
|
||||
|
||||
/// User map annotation to display existing location
|
||||
let userAnnotation: UserLocationAnnotation?
|
||||
/// Shared annotation to display existing location
|
||||
let sharedAnnotation: LocationAnnotation?
|
||||
|
||||
/// Map annotations to display on map
|
||||
var annotations: [UserLocationAnnotation]
|
||||
var annotations: [LocationAnnotation]
|
||||
|
||||
/// Map annotation to focus on
|
||||
var highlightedAnnotation: UserLocationAnnotation?
|
||||
var highlightedAnnotation: LocationAnnotation?
|
||||
|
||||
/// Indicates whether the user has moved around the map to drop a pin somewhere other than their current location
|
||||
var isPinDropSharing: Bool = false
|
||||
var isPinDropSharing: Bool {
|
||||
return bindings.pinLocation != nil
|
||||
}
|
||||
|
||||
var showLoadingIndicator: Bool = false
|
||||
|
||||
@@ -72,7 +81,7 @@ struct LocationSharingViewState: BindableState {
|
||||
}
|
||||
|
||||
var displayExistingLocation: Bool {
|
||||
return userAnnotation != nil
|
||||
return sharedAnnotation != nil
|
||||
}
|
||||
|
||||
var shareButtonEnabled: Bool {
|
||||
@@ -87,6 +96,7 @@ struct LocationSharingViewState: BindableState {
|
||||
struct LocationSharingViewStateBindings {
|
||||
var alertInfo: AlertInfo<LocationSharingAlertType>?
|
||||
var userLocation: CLLocationCoordinate2D?
|
||||
var pinLocation: CLLocationCoordinate2D?
|
||||
}
|
||||
|
||||
enum LocationSharingAlertType {
|
||||
|
||||
@@ -38,6 +38,7 @@ enum MockLocationSharingScreenState: MockScreenState, CaseIterable {
|
||||
let viewModel = LocationSharingViewModel(mapStyleURL: mapStyleURL,
|
||||
avatarData: AvatarInput(mxContentUri: "", matrixItemId: "alice:matrix.org", displayName: "Alice"),
|
||||
location: location,
|
||||
coordinateType: .user,
|
||||
isLiveLocationSharingEnabled: true)
|
||||
return ([viewModel],
|
||||
AnyView(LocationSharingView(context: viewModel.context)
|
||||
|
||||
@@ -41,21 +41,27 @@ class LocationSharingViewModel: LocationSharingViewModelType, LocationSharingVie
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(mapStyleURL: URL, avatarData: AvatarInputProtocol, location: CLLocationCoordinate2D? = nil, isLiveLocationSharingEnabled: Bool = false) {
|
||||
init(mapStyleURL: URL, avatarData: AvatarInputProtocol, location: CLLocationCoordinate2D? = nil, coordinateType: LocationSharingCoordinateType, isLiveLocationSharingEnabled: Bool = false) {
|
||||
|
||||
var userAnnotation: UserLocationAnnotation?
|
||||
var annotations: [UserLocationAnnotation] = []
|
||||
var highlightedAnnotation: UserLocationAnnotation?
|
||||
var sharedAnnotation: LocationAnnotation?
|
||||
var annotations: [LocationAnnotation] = []
|
||||
var highlightedAnnotation: LocationAnnotation?
|
||||
var showsUserLocation: Bool = false
|
||||
|
||||
// Displaying an existing location
|
||||
if let userCoordinate = location {
|
||||
let userLocationAnnotation = UserLocationAnnotation(avatarData: avatarData, coordinate: userCoordinate)
|
||||
if let sharedCoordinate = location {
|
||||
let sharedLocationAnnotation: LocationAnnotation
|
||||
switch coordinateType {
|
||||
case .user:
|
||||
sharedLocationAnnotation = UserLocationAnnotation(avatarData: avatarData, coordinate: sharedCoordinate)
|
||||
case .pin:
|
||||
sharedLocationAnnotation = PinLocationAnnotation(coordinate: sharedCoordinate)
|
||||
}
|
||||
|
||||
annotations.append(userLocationAnnotation)
|
||||
highlightedAnnotation = userLocationAnnotation
|
||||
annotations.append(sharedLocationAnnotation)
|
||||
highlightedAnnotation = sharedLocationAnnotation
|
||||
|
||||
userAnnotation = userLocationAnnotation
|
||||
sharedAnnotation = sharedLocationAnnotation
|
||||
} else {
|
||||
// Share current location
|
||||
showsUserLocation = true
|
||||
@@ -63,7 +69,7 @@ class LocationSharingViewModel: LocationSharingViewModelType, LocationSharingVie
|
||||
|
||||
let viewState = LocationSharingViewState(mapStyleURL: mapStyleURL,
|
||||
userAvatarData: avatarData,
|
||||
userAnnotation: userAnnotation,
|
||||
sharedAnnotation: sharedAnnotation,
|
||||
annotations: annotations,
|
||||
highlightedAnnotation: highlightedAnnotation,
|
||||
showsUserLocation: showsUserLocation,
|
||||
@@ -85,8 +91,8 @@ class LocationSharingViewModel: LocationSharingViewModelType, LocationSharingVie
|
||||
completion?(.cancel)
|
||||
case .share:
|
||||
// Share existing location
|
||||
if let location = state.userAnnotation?.coordinate {
|
||||
completion?(.share(latitude: location.latitude, longitude: location.longitude))
|
||||
if let location = state.sharedAnnotation?.coordinate {
|
||||
completion?(.share(latitude: location.latitude, longitude: location.longitude, coordinateType: .user))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -96,7 +102,16 @@ class LocationSharingViewModel: LocationSharingViewModelType, LocationSharingVie
|
||||
return
|
||||
}
|
||||
|
||||
completion?(.share(latitude: location.latitude, longitude: location.longitude))
|
||||
completion?(.share(latitude: location.latitude, longitude: location.longitude, coordinateType: .user))
|
||||
case .sharePinLocation:
|
||||
guard let pinLocation = state.bindings.pinLocation else {
|
||||
processError(.failedLocatingUser)
|
||||
return
|
||||
}
|
||||
|
||||
completion?(.share(latitude: pinLocation.latitude, longitude: pinLocation.longitude, coordinateType: .pin))
|
||||
case .goToUserLocation:
|
||||
state.bindings.pinLocation = nil
|
||||
case .shareLiveLocation:
|
||||
completion?(.shareLiveLocation(timeout: Constants.liveLocationSharingDefaultTimeout))
|
||||
}
|
||||
|
||||
+7
-7
@@ -35,7 +35,7 @@ class LocationSharingViewModelTests: XCTestCase {
|
||||
XCTAssertNotNil(viewModel.context.viewState.mapStyleURL)
|
||||
XCTAssertNotNil(viewModel.context.viewState.userAvatarData)
|
||||
|
||||
XCTAssertNil(viewModel.context.viewState.userAnnotation)
|
||||
XCTAssertNil(viewModel.context.viewState.sharedAnnotation)
|
||||
XCTAssertNil(viewModel.context.viewState.bindings.userLocation)
|
||||
XCTAssertNil(viewModel.context.viewState.bindings.alertInfo)
|
||||
}
|
||||
@@ -63,7 +63,7 @@ class LocationSharingViewModelTests: XCTestCase {
|
||||
let viewModel = buildViewModel(withLocation: false)
|
||||
|
||||
XCTAssertNil(viewModel.context.viewState.bindings.userLocation)
|
||||
XCTAssertNil(viewModel.context.viewState.userAnnotation)
|
||||
XCTAssertNil(viewModel.context.viewState.sharedAnnotation)
|
||||
|
||||
viewModel.context.send(viewAction: .share)
|
||||
|
||||
@@ -78,9 +78,9 @@ class LocationSharingViewModelTests: XCTestCase {
|
||||
|
||||
viewModel.completion = { result in
|
||||
switch result {
|
||||
case .share(let latitude, let longitude):
|
||||
XCTAssertEqual(latitude, viewModel.context.viewState.userAnnotation?.coordinate.latitude)
|
||||
XCTAssertEqual(longitude, viewModel.context.viewState.userAnnotation?.coordinate.longitude)
|
||||
case .share(let latitude, let longitude, _):
|
||||
XCTAssertEqual(latitude, viewModel.context.viewState.sharedAnnotation?.coordinate.latitude)
|
||||
XCTAssertEqual(longitude, viewModel.context.viewState.sharedAnnotation?.coordinate.longitude)
|
||||
expectation.fulfill()
|
||||
case .cancel:
|
||||
XCTFail()
|
||||
@@ -88,7 +88,7 @@ class LocationSharingViewModelTests: XCTestCase {
|
||||
}
|
||||
|
||||
XCTAssertNil(viewModel.context.viewState.bindings.userLocation)
|
||||
XCTAssertNotNil(viewModel.context.viewState.userAnnotation)
|
||||
XCTAssertNotNil(viewModel.context.viewState.sharedAnnotation)
|
||||
|
||||
viewModel.context.send(viewAction: .share)
|
||||
|
||||
@@ -123,6 +123,6 @@ class LocationSharingViewModelTests: XCTestCase {
|
||||
private func buildViewModel(withLocation: Bool) -> LocationSharingViewModel {
|
||||
LocationSharingViewModel(mapStyleURL: URL(string: "http://empty.com")!,
|
||||
avatarData: AvatarInput(mxContentUri: "", matrixItemId: "", displayName: ""),
|
||||
location: (withLocation ? CLLocationCoordinate2D(latitude: 51.4932641, longitude: -0.257096) : nil))
|
||||
location: (withLocation ? CLLocationCoordinate2D(latitude: 51.4932641, longitude: -0.257096) : nil), coordinateType: .user)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,10 +33,10 @@ struct LocationSharingMapView: UIViewRepresentable {
|
||||
let tileServerMapURL: URL
|
||||
|
||||
/// Map annotations
|
||||
let annotations: [UserLocationAnnotation]
|
||||
let annotations: [LocationAnnotation]
|
||||
|
||||
/// Map annotation to focus on
|
||||
let highlightedAnnotation: UserLocationAnnotation?
|
||||
let highlightedAnnotation: LocationAnnotation?
|
||||
|
||||
/// Current user avatar data, used to replace current location annotation view with the user avatar
|
||||
let userAvatarData: AvatarInputProtocol?
|
||||
@@ -47,6 +47,9 @@ struct LocationSharingMapView: UIViewRepresentable {
|
||||
/// Last user location if `showsUserLocation` has been enabled
|
||||
@Binding var userLocation: CLLocationCoordinate2D?
|
||||
|
||||
/// Coordinate of the center of the map
|
||||
@Binding var mapCenterCoordinate: CLLocationCoordinate2D?
|
||||
|
||||
/// Publish view errors if any
|
||||
let errorSubject: PassthroughSubject<LocationSharingViewError, Never>
|
||||
|
||||
@@ -68,7 +71,7 @@ struct LocationSharingMapView: UIViewRepresentable {
|
||||
mapView.setCenter(highlightedAnnotation.coordinate, zoomLevel: Constants.mapZoomLevel, animated: false)
|
||||
}
|
||||
|
||||
if self.showsUserLocation {
|
||||
if self.showsUserLocation && mapCenterCoordinate == nil {
|
||||
mapView.showsUserLocation = true
|
||||
mapView.userTrackingMode = .follow
|
||||
} else {
|
||||
@@ -114,10 +117,12 @@ extension LocationSharingMapView {
|
||||
func mapView(_ mapView: MGLMapView, viewFor annotation: MGLAnnotation) -> MGLAnnotationView? {
|
||||
|
||||
if let userLocationAnnotation = annotation as? UserLocationAnnotation {
|
||||
return UserLocationAnnotatonView(userLocationAnnotation: userLocationAnnotation)
|
||||
} else if annotation is MGLUserLocation, let currentUserAvatarData = locationSharingMapView.userAvatarData {
|
||||
// Replace default current location annotation view with a UserLocationAnnotatonView
|
||||
return UserLocationAnnotatonView(avatarData: currentUserAvatarData)
|
||||
return LocationAnnotatonView(userLocationAnnotation: userLocationAnnotation)
|
||||
} else if let pinLocationAnnotation = annotation as? PinLocationAnnotation {
|
||||
return LocationAnnotatonView(pinLocationAnnotation: pinLocationAnnotation)
|
||||
} else if annotation is MGLUserLocation && locationSharingMapView.mapCenterCoordinate == nil, let currentUserAvatarData = locationSharingMapView.userAvatarData {
|
||||
// Replace default current location annotation view with a UserLocationAnnotatonView when the map is center on user location
|
||||
return LocationAnnotatonView(avatarData: currentUserAvatarData)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -145,6 +150,16 @@ extension LocationSharingMapView {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
func mapView(_ mapView: MGLMapView, regionDidChangeAnimated animated: Bool) {
|
||||
let mapCenterCoordinate = mapView.centerCoordinate
|
||||
// Prevent this function to set pinLocation when the map is openning
|
||||
guard let userLocation = locationSharingMapView.userLocation,
|
||||
!userLocation.isEqual(to: mapCenterCoordinate, precision: 0.0000000001) else {
|
||||
return
|
||||
}
|
||||
locationSharingMapView.mapCenterCoordinate = mapCenterCoordinate
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ struct LocationSharingMarkerView<Content: View>: View {
|
||||
markerImage
|
||||
.frame(width: 40, height: 40)
|
||||
}
|
||||
.offset(x: 0, y: -23)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,13 +33,7 @@ struct LocationSharingView: View {
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
ZStack(alignment: .bottom) {
|
||||
LocationSharingMapView(tileServerMapURL: context.viewState.mapStyleURL,
|
||||
annotations: context.viewState.annotations,
|
||||
highlightedAnnotation: context.viewState.highlightedAnnotation,
|
||||
userAvatarData: context.viewState.userAvatarData,
|
||||
showsUserLocation: context.viewState.showsUserLocation,
|
||||
userLocation: $context.userLocation,
|
||||
errorSubject: context.viewState.errorSubject)
|
||||
mapView
|
||||
VStack(spacing: 0) {
|
||||
MapCreditsView()
|
||||
if context.viewState.shareButtonVisible {
|
||||
@@ -85,6 +79,39 @@ struct LocationSharingView: View {
|
||||
.navigationViewStyle(StackNavigationViewStyle())
|
||||
}
|
||||
|
||||
var mapView: some View {
|
||||
ZStack(alignment: .topTrailing) {
|
||||
ZStack(alignment: .center) {
|
||||
LocationSharingMapView(tileServerMapURL: context.viewState.mapStyleURL,
|
||||
annotations: context.viewState.annotations,
|
||||
highlightedAnnotation: context.viewState.highlightedAnnotation,
|
||||
userAvatarData: context.viewState.userAvatarData,
|
||||
showsUserLocation: context.viewState.showsUserLocation,
|
||||
userLocation: $context.userLocation,
|
||||
mapCenterCoordinate: $context.pinLocation,
|
||||
errorSubject: context.viewState.errorSubject)
|
||||
if context.viewState.isPinDropSharing {
|
||||
LocationSharingMarkerView(backgroundColor: theme.colors.accent) {
|
||||
Image(uiImage: Asset.Images.locationPinIcon.image)
|
||||
.resizable()
|
||||
.shapedBorder(color: theme.colors.accent, borderWidth: 3, shape: Circle())
|
||||
}
|
||||
}
|
||||
}
|
||||
Button {
|
||||
context.send(viewAction: .goToUserLocation)
|
||||
} label: {
|
||||
Image(uiImage: Asset.Images.locationCenterMapIcon.image)
|
||||
.foregroundColor(theme.colors.accent)
|
||||
}
|
||||
.padding(6.0)
|
||||
.background(theme.colors.background)
|
||||
.clipShape(RoundedCornerShape(radius: 4, corners: [.allCorners]))
|
||||
.shadow(radius: 2.0)
|
||||
.offset(x: -11.0, y: 52)
|
||||
}
|
||||
}
|
||||
|
||||
var buttonsView: some View {
|
||||
VStack(alignment: .leading, spacing: 15) {
|
||||
if !context.viewState.isPinDropSharing {
|
||||
@@ -107,7 +134,7 @@ struct LocationSharingView: View {
|
||||
}
|
||||
} else {
|
||||
LocationSharingOptionButton(text: VectorL10n.locationSharingPinDropShareTitle) {
|
||||
// TODO: - Pin drop sharing action
|
||||
context.send(viewAction: .sharePinLocation)
|
||||
} buttonIcon: {
|
||||
Image(uiImage: Asset.Images.locationPinIcon.image)
|
||||
.resizable()
|
||||
|
||||
@@ -19,7 +19,7 @@ import SwiftUI
|
||||
import Mapbox
|
||||
|
||||
@available(iOS 14, *)
|
||||
class UserLocationAnnotatonView: MGLUserLocationAnnotationView {
|
||||
class LocationAnnotatonView: MGLUserLocationAnnotationView {
|
||||
|
||||
// MARK: Private
|
||||
|
||||
@@ -39,6 +39,14 @@ class UserLocationAnnotatonView: MGLUserLocationAnnotationView {
|
||||
super.init(annotation: userLocationAnnotation, reuseIdentifier: nil)
|
||||
|
||||
self.addUserMarkerView(with: userLocationAnnotation.avatarData)
|
||||
|
||||
}
|
||||
|
||||
init(pinLocationAnnotation: PinLocationAnnotation) {
|
||||
// TODO: Use a reuseIdentifier
|
||||
super.init(annotation: pinLocationAnnotation, reuseIdentifier: nil)
|
||||
|
||||
self.addPinMarkerView()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
@@ -55,12 +63,26 @@ class UserLocationAnnotatonView: MGLUserLocationAnnotationView {
|
||||
}).view else {
|
||||
return
|
||||
}
|
||||
addMarkerView(with: avatarImageView)
|
||||
}
|
||||
|
||||
private func addPinMarkerView() {
|
||||
guard let pinImageView = UIHostingController(rootView: LocationSharingMarkerView(backgroundColor: theme.colors.accent) {
|
||||
Image(uiImage: Asset.Images.locationPinIcon.image)
|
||||
.resizable()
|
||||
.shapedBorder(color: theme.colors.accent, borderWidth: 3, shape: Circle())
|
||||
}).view else {
|
||||
return
|
||||
}
|
||||
addMarkerView(with: pinImageView)
|
||||
}
|
||||
|
||||
private func addMarkerView(with imageView: UIView) {
|
||||
addSubview(imageView)
|
||||
|
||||
addSubview(avatarImageView)
|
||||
|
||||
addConstraints([topAnchor.constraint(equalTo: avatarImageView.topAnchor),
|
||||
leadingAnchor.constraint(equalTo: avatarImageView.leadingAnchor),
|
||||
bottomAnchor.constraint(equalTo: avatarImageView.bottomAnchor),
|
||||
trailingAnchor.constraint(equalTo: avatarImageView.trailingAnchor)])
|
||||
addConstraints([topAnchor.constraint(equalTo: imageView.topAnchor),
|
||||
leadingAnchor.constraint(equalTo: imageView.leadingAnchor),
|
||||
bottomAnchor.constraint(equalTo: imageView.bottomAnchor),
|
||||
trailingAnchor.constraint(equalTo: imageView.trailingAnchor)])
|
||||
}
|
||||
}
|
||||
|
||||
+19
-17
@@ -251,6 +251,25 @@ final class MXRoomNotificationSettingsService: RoomNotificationSettingsServiceTy
|
||||
}
|
||||
}
|
||||
|
||||
extension MXRoom {
|
||||
public var isMuted: Bool {
|
||||
// Check whether an override rule has been defined with the roomm id as rule id.
|
||||
// This kind of rule is created to mute the room
|
||||
guard let rule = self.overridePushRule,
|
||||
rule.actionsContains(actionType: MXPushRuleActionTypeDontNotify),
|
||||
rule.conditionIsEnabled(kind: .eventMatch, for: roomId) else {
|
||||
return false
|
||||
}
|
||||
return rule.enabled
|
||||
}
|
||||
|
||||
public var isMentionsOnly: Bool {
|
||||
// Check push rules at room level
|
||||
guard let rule = roomPushRule else { return false }
|
||||
return rule.enabled && rule.actionsContains(actionType: MXPushRuleActionTypeDontNotify)
|
||||
}
|
||||
}
|
||||
|
||||
// We could move these to their own file and make available in global namespace or move to sdk but they are only used here at the moment
|
||||
fileprivate extension MXRoom {
|
||||
|
||||
@@ -288,23 +307,6 @@ fileprivate extension MXRoom {
|
||||
return .all
|
||||
}
|
||||
|
||||
var isMuted: Bool {
|
||||
// Check whether an override rule has been defined with the roomm id as rule id.
|
||||
// This kind of rule is created to mute the room
|
||||
guard let rule = self.overridePushRule,
|
||||
rule.actionsContains(actionType: MXPushRuleActionTypeDontNotify),
|
||||
rule.conditionIsEnabled(kind: .eventMatch, for: roomId) else {
|
||||
return false
|
||||
}
|
||||
return rule.enabled
|
||||
}
|
||||
|
||||
var isMentionsOnly: Bool {
|
||||
// Check push rules at room level
|
||||
guard let rule = roomPushRule else { return false }
|
||||
return rule.enabled && rule.actionsContains(actionType: MXPushRuleActionTypeDontNotify)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fileprivate extension MXPushRule {
|
||||
|
||||
+1
-1
@@ -109,7 +109,7 @@ class RoomAccessTypeChooserService: RoomAccessTypeChooserServiceProtocol {
|
||||
|
||||
switch self.selectedType {
|
||||
case .private:
|
||||
_joinRule = .private
|
||||
_joinRule = .invite
|
||||
case .public:
|
||||
_joinRule = .public
|
||||
case .restricted:
|
||||
|
||||
Reference in New Issue
Block a user