mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-04-16 06:28:27 +02:00
MESSENGER-5379 dynamic location attribution from style.json
This commit is contained in:
@@ -410,6 +410,18 @@ class RoomTimelineLocationView: UIView, NibLoadable, Themable, MGLMapViewDelegat
|
||||
self.isMapViewLoadingFailed = false
|
||||
}
|
||||
|
||||
func mapView(_ mapView: MGLMapView, didFinishLoading style: MGLStyle) {
|
||||
// bwi #5379: set copyright to info from style json if available. Needs reevaluation if there is more than one source
|
||||
|
||||
for source in style.sources {
|
||||
if let tileSource = source as? MGLRasterTileSource {
|
||||
for attributionInfo in tileSource.attributionInfos {
|
||||
attributionLabel.text = attributionLabel.text?.appending(attributionInfo.title.plainTextString())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Action
|
||||
|
||||
@IBAction private func didTapTightButton(_ sender: Any) {
|
||||
|
||||
@@ -68,7 +68,9 @@ struct LiveLocationSharingViewer: View {
|
||||
if viewModel.viewState.isBottomSheetVisible {
|
||||
VStack(alignment: .center) {
|
||||
Spacer()
|
||||
MapCreditsView(action: {
|
||||
// bwi #5379: we don't use live location sharing, if this changes we need to use attribution from viewmodel here
|
||||
MapCreditsView(attributions: LocationSharingAttribution(),
|
||||
action: {
|
||||
viewModel.send(viewAction: .mapCreditsDidTap)
|
||||
})
|
||||
.offset(y: -bottomSheetCollapsedHeight) // Put the copyright action above the collapsed bottom sheet
|
||||
@@ -88,7 +90,8 @@ struct LiveLocationSharingViewer: View {
|
||||
|
||||
// Show map credits only if map is visible
|
||||
if !viewModel.viewState.showMapLoadingError {
|
||||
MapCreditsView(action: {
|
||||
MapCreditsView(attributions:LocationSharingAttribution(),
|
||||
action: {
|
||||
viewModel.send(viewAction: .mapCreditsDidTap)
|
||||
})
|
||||
.padding(.bottom, 5)
|
||||
@@ -122,7 +125,9 @@ struct LiveLocationSharingViewer: View {
|
||||
.background(theme.colors.system.ignoresSafeArea())
|
||||
.bottomSheet(sheet, if: viewModel.viewState.isBottomSheetVisible)
|
||||
.actionSheet(isPresented: $viewModel.showMapCreditsSheet) {
|
||||
MapCreditsActionSheet(openURL: { url in
|
||||
MapCreditsActionSheet(
|
||||
attribution: LocationSharingAttribution(),
|
||||
openURL: { url in
|
||||
UIApplication.shared.vc_open(url, completionHandler: nil)
|
||||
}).sheet
|
||||
}
|
||||
|
||||
@@ -17,20 +17,32 @@
|
||||
import SwiftUI
|
||||
|
||||
struct MapCreditsActionSheet {
|
||||
// bwi #5379 dynamic attribution from style.json
|
||||
let attribution: LocationSharingAttribution
|
||||
|
||||
// Open URL action
|
||||
let openURL: (URL) -> Void
|
||||
|
||||
// Map credits action sheet
|
||||
var sheet: ActionSheet {
|
||||
ActionSheet(title: Text(BWIL10n.locationSharingMapCreditsTitle),
|
||||
buttons: [
|
||||
.default(Text("© MapTiler")) {
|
||||
openURL(URL(string: "https://www.maptiler.com/copyright/")!)
|
||||
},
|
||||
.default(Text("© OpenStreetMap")) {
|
||||
openURL(URL(string: "https://www.openstreetmap.org/copyright")!)
|
||||
},
|
||||
.cancel()
|
||||
])
|
||||
buttons: self.creditButtons(attribution: attribution))
|
||||
}
|
||||
|
||||
func creditButtons( attribution: LocationSharingAttribution) -> [ActionSheet.Button] {
|
||||
|
||||
var buttons = [ActionSheet.Button]()
|
||||
|
||||
// bwi #5379 a bit scetchy but you can asume that url and text have the same index
|
||||
for (index, copyright) in attribution.copyrightTexts.enumerated() {
|
||||
buttons.append(.default(Text(copyright)) {
|
||||
if let url = attribution.copyrightLinks[index] {
|
||||
openURL(url)
|
||||
}
|
||||
})
|
||||
}
|
||||
buttons.append(.cancel())
|
||||
|
||||
return buttons
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,25 +25,41 @@ struct MapCreditsView: View {
|
||||
|
||||
// MARK: Public
|
||||
|
||||
// MARK: Public
|
||||
|
||||
// bwi #5379 use dynamic attributions from style.json
|
||||
@ObservedObject var attributions:LocationSharingAttribution
|
||||
|
||||
var action: (() -> Void)?
|
||||
|
||||
var body: some View {
|
||||
HStack {
|
||||
Spacer()
|
||||
Spacer()
|
||||
Button {
|
||||
action?()
|
||||
} label: {
|
||||
Text(BWIL10n.locationSharingCopyrightLabel)
|
||||
Text(copyrightText(attribution:attributions))
|
||||
.font(theme.fonts.footnote)
|
||||
.foregroundColor(theme.colors.accent)
|
||||
}
|
||||
.padding(.horizontal)
|
||||
}
|
||||
}
|
||||
|
||||
func copyrightText( attribution: LocationSharingAttribution) -> String {
|
||||
var copyright = ""
|
||||
|
||||
for copyrightText in attribution.copyrightTexts {
|
||||
copyright.append(copyrightText)
|
||||
}
|
||||
|
||||
return copyright
|
||||
}
|
||||
}
|
||||
|
||||
struct MapCreditsView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
MapCreditsView()
|
||||
|
||||
MapCreditsView(attributions: LocationSharingAttribution(copyrightTexts: [""], copyrightLinks: [URL(string: "www.someurl.org")]))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +68,9 @@ struct LocationSharingMapView: UIViewRepresentable {
|
||||
|
||||
/// Called when the user pan on the map
|
||||
var userDidPan: (() -> Void)?
|
||||
|
||||
// bwi #5379: for copyright attribution
|
||||
var attributionsChanged: ((LocationSharingAttribution) -> Void)?
|
||||
|
||||
// MARK: - UIViewRepresentable
|
||||
|
||||
@@ -154,6 +157,23 @@ extension LocationSharingMapView {
|
||||
return nil
|
||||
}
|
||||
|
||||
func mapView(_ mapView: MGLMapView, didFinishLoading style: MGLStyle) {
|
||||
// bwi #5379: set copyright to info from style json if available. Needs reevaluation if there is more than one source
|
||||
|
||||
var attribution = LocationSharingAttribution()
|
||||
|
||||
for source in style.sources {
|
||||
if let tileSource = source as? MGLRasterTileSource {
|
||||
for attributionInfo in tileSource.attributionInfos {
|
||||
attribution.copyrightTexts.append(attributionInfo.title.plainTextString())
|
||||
attribution.copyrightLinks.append(attributionInfo.url)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
locationSharingMapView.attributionsChanged?(attribution)
|
||||
}
|
||||
|
||||
func mapViewDidFailLoadingMap(_ mapView: MGLMapView, withError error: Error) {
|
||||
locationSharingMapView.errorSubject.send(.failedLoadingMap)
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ enum LocationSharingViewAction {
|
||||
case shareLiveLocation(timeout: LiveLocationSharingTimeout)
|
||||
case userDidPan
|
||||
case mapCreditsDidTap
|
||||
case showMapCredit(mapAttribution: LocationSharingAttribution)
|
||||
}
|
||||
|
||||
enum LocationSharingViewModelResult {
|
||||
@@ -95,6 +96,8 @@ struct LocationSharingViewState: BindableState {
|
||||
let errorSubject = PassthroughSubject<LocationSharingViewError, Never>()
|
||||
|
||||
var bindings = LocationSharingViewStateBindings()
|
||||
|
||||
var attribution = LocationSharingAttribution()
|
||||
}
|
||||
|
||||
struct LocationSharingViewStateBindings {
|
||||
|
||||
@@ -91,6 +91,8 @@ class LocationSharingViewModel: LocationSharingViewModelType, LocationSharingVie
|
||||
state.isPinDropSharing = true
|
||||
case .mapCreditsDidTap:
|
||||
state.bindings.showMapCreditsSheet.toggle()
|
||||
case .showMapCredit(mapAttribution: let mapAttribution):
|
||||
state.attribution = mapAttribution
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,12 +43,15 @@ struct LocationSharingView: View {
|
||||
} else {
|
||||
// Show map credits only if map is visible
|
||||
|
||||
MapCreditsView(action: {
|
||||
MapCreditsView(
|
||||
attributions:context.viewState.attribution,
|
||||
action: {
|
||||
context.send(viewAction: .mapCreditsDidTap)
|
||||
})
|
||||
.padding(.bottom, 10.0)
|
||||
.actionSheet(isPresented: $context.showMapCreditsSheet) {
|
||||
MapCreditsActionSheet(openURL: { url in
|
||||
MapCreditsActionSheet(attribution:context.viewState.attribution,
|
||||
openURL: { url in
|
||||
UIApplication.shared.vc_open(url, completionHandler: nil)
|
||||
}).sheet
|
||||
}
|
||||
@@ -101,7 +104,10 @@ struct LocationSharingView: View {
|
||||
errorSubject: context.viewState.errorSubject,
|
||||
userDidPan: {
|
||||
context.send(viewAction: .userDidPan)
|
||||
})
|
||||
},
|
||||
attributionsChanged: { attribution in
|
||||
context.send(viewAction: .showMapCredit(mapAttribution: attribution))
|
||||
})
|
||||
if context.viewState.isPinDropSharing {
|
||||
LocationSharingMarkerView(backgroundColor: theme.colors.accent) {
|
||||
if BWIBuildSettings.shared.bwiEnableBuMUI {
|
||||
|
||||
@@ -25,6 +25,7 @@ enum StaticLocationViewingViewAction {
|
||||
case share
|
||||
case mapCreditsDidTap
|
||||
case showUserLocation
|
||||
case showMapCredit(mapAttribution: LocationSharingAttribution)
|
||||
}
|
||||
|
||||
enum StaticLocationViewingViewModelResult {
|
||||
@@ -60,6 +61,8 @@ struct StaticLocationViewingViewState: BindableState {
|
||||
let errorSubject = PassthroughSubject<LocationSharingViewError, Never>()
|
||||
|
||||
var bindings = StaticLocationViewingViewBindings()
|
||||
|
||||
var attribution = LocationSharingAttribution()
|
||||
}
|
||||
|
||||
struct StaticLocationViewingViewBindings {
|
||||
|
||||
@@ -71,6 +71,8 @@ class StaticLocationViewingViewModel: StaticLocationViewingViewModelType, Static
|
||||
state.bindings.showMapCreditsSheet.toggle()
|
||||
case .showUserLocation:
|
||||
showsCurrentUserLocation()
|
||||
case .showMapCredit(mapAttribution: let mapAttribution):
|
||||
state.attribution = mapAttribution
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,10 @@ struct StaticLocationView: View {
|
||||
showsUserLocationMode: viewModel.viewState.showsUserLocationMode,
|
||||
userLocation: Binding.constant(nil),
|
||||
mapCenterCoordinate: Binding.constant(nil),
|
||||
errorSubject: viewModel.viewState.errorSubject)
|
||||
errorSubject: viewModel.viewState.errorSubject,
|
||||
attributionsChanged: { attribution in
|
||||
viewModel.send(viewAction: .showMapCredit(mapAttribution: attribution))
|
||||
})
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
@@ -52,13 +55,17 @@ struct StaticLocationView: View {
|
||||
showsUserLocationMode: ShowUserLocationMode.hide,
|
||||
userLocation: Binding.constant(nil),
|
||||
mapCenterCoordinate: Binding.constant(nil),
|
||||
errorSubject: viewModel.viewState.errorSubject)
|
||||
MapCreditsView(action: {
|
||||
errorSubject: viewModel.viewState.errorSubject,
|
||||
attributionsChanged: { attribution in
|
||||
viewModel.send(viewAction: .showMapCredit(mapAttribution: attribution))
|
||||
})
|
||||
MapCreditsView(attributions: viewModel.viewState.attribution, action: {
|
||||
viewModel.send(viewAction: .mapCreditsDidTap)
|
||||
})
|
||||
.padding(.bottom, 10.0 + safeAreaInsets.bottom)
|
||||
.actionSheet(isPresented: $viewModel.showMapCreditsSheet) {
|
||||
MapCreditsActionSheet(openURL: { url in
|
||||
MapCreditsActionSheet(attribution:viewModel.viewState.attribution,
|
||||
openURL: { url in
|
||||
UIApplication.shared.vc_open(url, completionHandler: nil)
|
||||
}).sheet
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
//
|
||||
/*
|
||||
* Copyright (c) 2022 BWI GmbH
|
||||
*
|
||||
* 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 Foundation
|
||||
|
||||
class LocationSharingAttribution: ObservableObject {
|
||||
var copyrightTexts: [String]
|
||||
var copyrightLinks: [URL?]
|
||||
|
||||
init() {
|
||||
copyrightTexts = []
|
||||
copyrightLinks = []
|
||||
}
|
||||
|
||||
init( copyrightTexts: [String], copyrightLinks: [URL?]) {
|
||||
self.copyrightLinks = copyrightLinks
|
||||
self.copyrightTexts = copyrightTexts
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user