mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-04-16 06:28:27 +02:00
5720: Rework some location sharing related view
This commit is contained in:
@@ -47,4 +47,10 @@ public struct ColorValues: Colors {
|
||||
public let background: UIColor
|
||||
|
||||
public let namesAndAvatars: [UIColor]
|
||||
|
||||
// MARK: - Others colors
|
||||
|
||||
public let white: UIColor
|
||||
|
||||
public let purple: UIColor
|
||||
}
|
||||
|
||||
@@ -68,4 +68,11 @@ public protocol Colors {
|
||||
/// - Avatars default states that include first name letter
|
||||
var namesAndAvatars: [ColorType] { get }
|
||||
|
||||
// MARK: - Others colors
|
||||
|
||||
/// White
|
||||
var white: ColorType { get }
|
||||
|
||||
/// Purple
|
||||
var purple: ColorType { get }
|
||||
}
|
||||
|
||||
@@ -49,6 +49,12 @@ public struct ColorSwiftUI: Colors {
|
||||
|
||||
public let namesAndAvatars: [Color]
|
||||
|
||||
// MARK: - Others colors
|
||||
|
||||
public let white: Color
|
||||
|
||||
public let purple: Color
|
||||
|
||||
init(values: ColorValues) {
|
||||
accent = Color(values.accent)
|
||||
alert = Color(values.alert)
|
||||
@@ -63,5 +69,7 @@ public struct ColorSwiftUI: Colors {
|
||||
navigation = Color(values.navigation)
|
||||
background = Color(values.background)
|
||||
namesAndAvatars = values.namesAndAvatars.map({ Color($0) })
|
||||
white = Color(values.white)
|
||||
purple = Color(values.purple)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,12 @@ import UIKit
|
||||
|
||||
public let namesAndAvatars: [UIColor]
|
||||
|
||||
// MARK: - Others colors
|
||||
|
||||
public let white: UIColor
|
||||
|
||||
public let purple: UIColor
|
||||
|
||||
init(values: ColorValues) {
|
||||
accent = values.accent
|
||||
alert = values.alert
|
||||
@@ -62,6 +68,8 @@ import UIKit
|
||||
navigation = values.navigation
|
||||
background = values.background
|
||||
namesAndAvatars = values.namesAndAvatars
|
||||
white = values.white
|
||||
purple = values.purple
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,9 @@ public class DarkColors {
|
||||
UIColor(rgb:0x2DC2C5),
|
||||
UIColor(rgb:0x5C56F5),
|
||||
UIColor(rgb:0x74D12C)
|
||||
]
|
||||
],
|
||||
white: UIColor(rgb: 0xFFFFFF),
|
||||
purple: UIColor(rgb: 0x5C56F5)
|
||||
)
|
||||
|
||||
public static var uiKit = ColorsUIKit(values: values)
|
||||
|
||||
@@ -43,7 +43,9 @@ public class LightColors {
|
||||
UIColor(rgb:0x2DC2C5),
|
||||
UIColor(rgb:0x5C56F5),
|
||||
UIColor(rgb:0x74D12C)
|
||||
]
|
||||
],
|
||||
white: UIColor(rgb: 0xFFFFFF),
|
||||
purple: UIColor(rgb: 0x5C56F5)
|
||||
)
|
||||
|
||||
public static var uiKit = ColorsUIKit(values: values)
|
||||
|
||||
23
Riot/Assets/Images.xcassets/Room/Location/location_live_icon.imageset/Contents.json
vendored
Normal file
23
Riot/Assets/Images.xcassets/Room/Location/location_live_icon.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "location_live_icon.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "location_live_icon@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "location_live_icon@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
Riot/Assets/Images.xcassets/Room/Location/location_live_icon.imageset/location_live_icon.png
vendored
Normal file
BIN
Riot/Assets/Images.xcassets/Room/Location/location_live_icon.imageset/location_live_icon.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
BIN
Riot/Assets/Images.xcassets/Room/Location/location_live_icon.imageset/location_live_icon@2x.png
vendored
Normal file
BIN
Riot/Assets/Images.xcassets/Room/Location/location_live_icon.imageset/location_live_icon@2x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.7 KiB |
BIN
Riot/Assets/Images.xcassets/Room/Location/location_live_icon.imageset/location_live_icon@3x.png
vendored
Normal file
BIN
Riot/Assets/Images.xcassets/Room/Location/location_live_icon.imageset/location_live_icon@3x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.0 KiB |
23
Riot/Assets/Images.xcassets/Room/Location/location_pin_icon.imageset/Contents.json
vendored
Normal file
23
Riot/Assets/Images.xcassets/Room/Location/location_pin_icon.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "location_pin_icon.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "location_pin_icon@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "location_pin_icon@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
Riot/Assets/Images.xcassets/Room/Location/location_pin_icon.imageset/location_pin_icon.png
vendored
Normal file
BIN
Riot/Assets/Images.xcassets/Room/Location/location_pin_icon.imageset/location_pin_icon.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
BIN
Riot/Assets/Images.xcassets/Room/Location/location_pin_icon.imageset/location_pin_icon@2x.png
vendored
Normal file
BIN
Riot/Assets/Images.xcassets/Room/Location/location_pin_icon.imageset/location_pin_icon@2x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.9 KiB |
BIN
Riot/Assets/Images.xcassets/Room/Location/location_pin_icon.imageset/location_pin_icon@3x.png
vendored
Normal file
BIN
Riot/Assets/Images.xcassets/Room/Location/location_pin_icon.imageset/location_pin_icon@3x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.8 KiB |
@@ -19,5 +19,8 @@
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,7 +172,9 @@ internal class Asset: NSObject {
|
||||
internal static let voiceCallHangonIcon = ImageAsset(name: "voice_call_hangon_icon")
|
||||
internal static let voiceCallHangupIcon = ImageAsset(name: "voice_call_hangup_icon")
|
||||
internal static let liveLocationIcon = ImageAsset(name: "live_location_icon")
|
||||
internal static let locationLiveIcon = ImageAsset(name: "location_live_icon")
|
||||
internal static let locationMarkerIcon = ImageAsset(name: "location_marker_icon")
|
||||
internal static let locationPinIcon = ImageAsset(name: "location_pin_icon")
|
||||
internal static let locationShareIcon = ImageAsset(name: "location_share_icon")
|
||||
internal static let locationUserMarker = ImageAsset(name: "location_user_marker")
|
||||
internal static let pollCheckboxDefault = ImageAsset(name: "poll_checkbox_default")
|
||||
|
||||
@@ -20,23 +20,17 @@ import Mapbox
|
||||
|
||||
class LocationMarkerView: MGLAnnotationView, NibLoadable {
|
||||
|
||||
@IBOutlet private var markerBackground: UIImageView!
|
||||
@IBOutlet private var backgroundImageView: UIImageView!
|
||||
@IBOutlet private var avatarView: UserAvatarView!
|
||||
|
||||
private static var usernameColorGenerator = UserNameColorGenerator()
|
||||
private let theme: Theme = ThemeService.shared().theme
|
||||
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
translatesAutoresizingMaskIntoConstraints = false
|
||||
}
|
||||
|
||||
func setAvatarData(_ avatarData: AvatarViewDataProtocol) {
|
||||
Self.usernameColorGenerator.defaultColor = theme.colors.primaryContent
|
||||
Self.usernameColorGenerator.userNameColors = theme.colors.namesAndAvatars
|
||||
let image = Asset.Images.locationUserMarker.image.withRenderingMode(.alwaysTemplate)
|
||||
markerBackground.image = image
|
||||
markerBackground.tintColor = Self.usernameColorGenerator.color(from: avatarData.matrixItemId)
|
||||
func setAvatarData(_ avatarData: AvatarViewDataProtocol, avatarBackgroundColor: UIColor) {
|
||||
backgroundImageView.image = Asset.Images.locationUserMarker.image
|
||||
backgroundImageView.tintColor = avatarBackgroundColor
|
||||
avatarView.fill(with: avatarData)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
||||
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
@@ -65,7 +63,7 @@
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<connections>
|
||||
<outlet property="avatarView" destination="qut-wn-BX3" id="wHA-bz-A2y"/>
|
||||
<outlet property="markerBackground" destination="ldO-kc-R5W" id="52a-Fs-iu7"/>
|
||||
<outlet property="backgroundImageView" destination="ldO-kc-R5W" id="52a-Fs-iu7"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="58.695652173913047" y="4.6875"/>
|
||||
</view>
|
||||
|
||||
@@ -39,6 +39,7 @@ class RoomTimelineLocationView: UIView, NibLoadable, Themable, MGLMapViewDelegat
|
||||
|
||||
private var mapView: MGLMapView!
|
||||
private var annotationView: LocationMarkerView?
|
||||
private static var usernameColorGenerator = UserNameColorGenerator()
|
||||
|
||||
// MARK: Public
|
||||
|
||||
@@ -82,7 +83,8 @@ class RoomTimelineLocationView: UIView, NibLoadable, Themable, MGLMapViewDelegat
|
||||
annotationView = LocationMarkerView.loadFromNib()
|
||||
|
||||
if let userAvatarData = userAvatarData {
|
||||
annotationView?.setAvatarData(userAvatarData)
|
||||
let avatarBackgroundColor = Self.usernameColorGenerator.color(from: userAvatarData.matrixItemId)
|
||||
annotationView?.setAvatarData(userAvatarData, avatarBackgroundColor: avatarBackgroundColor)
|
||||
}
|
||||
|
||||
if let annotations = mapView.annotations {
|
||||
@@ -99,6 +101,7 @@ class RoomTimelineLocationView: UIView, NibLoadable, Themable, MGLMapViewDelegat
|
||||
// MARK: - Themable
|
||||
|
||||
func update(theme: Theme) {
|
||||
Self.usernameColorGenerator.update(theme: theme)
|
||||
descriptionLabel.textColor = theme.colors.primaryContent
|
||||
descriptionLabel.font = theme.fonts.footnote
|
||||
descriptionIcon.tintColor = theme.colors.accent
|
||||
|
||||
@@ -94,8 +94,7 @@ extension ThreadTableViewCell: Themable {
|
||||
|
||||
func update(theme: Theme) {
|
||||
self.theme = theme
|
||||
Self.usernameColorGenerator.defaultColor = theme.colors.primaryContent
|
||||
Self.usernameColorGenerator.userNameColors = theme.colors.namesAndAvatars
|
||||
Self.usernameColorGenerator.update(theme: theme)
|
||||
updateRootMessageSenderColor()
|
||||
rootMessageAvatarView.backgroundColor = .clear
|
||||
if let attributedText = rootMessageContentLabel.attributedText {
|
||||
|
||||
@@ -48,3 +48,12 @@ final class UserNameColorGenerator: NSObject {
|
||||
return self.userNameColors[senderNameColorIndex]
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Themable
|
||||
extension UserNameColorGenerator: Themable {
|
||||
|
||||
func update(theme: Theme) {
|
||||
self.defaultColor = theme.colors.primaryContent
|
||||
self.userNameColors = theme.colors.namesAndAvatars
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,14 @@ struct AvatarImage: View {
|
||||
var mxContentUri: String?
|
||||
var matrixItemId: String
|
||||
var displayName: String?
|
||||
var size: AvatarSize
|
||||
var size: AvatarSize?
|
||||
|
||||
var sizeValue: CGFloat? {
|
||||
guard let size = size else {
|
||||
return nil
|
||||
}
|
||||
return CGFloat(size.rawValue)
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
Group {
|
||||
@@ -42,7 +49,7 @@ struct AvatarImage: View {
|
||||
.resizable()
|
||||
}
|
||||
}
|
||||
.frame(width: CGFloat(size.rawValue), height: CGFloat(size.rawValue))
|
||||
.frame(width: sizeValue, height: sizeValue)
|
||||
.clipShape(Circle())
|
||||
.onAppear {
|
||||
viewModel.inject(dependencies: dependencies)
|
||||
@@ -59,7 +66,7 @@ struct AvatarImage: View {
|
||||
|
||||
@available(iOS 14.0, *)
|
||||
extension AvatarImage {
|
||||
init(avatarData: AvatarInputProtocol, size: AvatarSize) {
|
||||
init(avatarData: AvatarInputProtocol, size: AvatarSize?) {
|
||||
self.init(
|
||||
mxContentUri: avatarData.mxContentUri,
|
||||
matrixItemId: avatarData.matrixItemId,
|
||||
|
||||
@@ -40,7 +40,7 @@ class AvatarViewModel: InjectableObject, ObservableObject {
|
||||
matrixItemId: String,
|
||||
displayName: String?,
|
||||
colorCount: Int,
|
||||
avatarSize: AvatarSize) {
|
||||
avatarSize: AvatarSize?) {
|
||||
|
||||
let placeholderViewModel = PlaceholderAvatarViewModel(displayName: displayName,
|
||||
matrixItemId: matrixItemId,
|
||||
@@ -52,7 +52,7 @@ class AvatarViewModel: InjectableObject, ObservableObject {
|
||||
return
|
||||
}
|
||||
|
||||
avatarService.avatarImage(mxContentUri: mxContentUri, avatarSize: avatarSize)
|
||||
avatarService.avatarImage(mxContentUri: mxContentUri, avatarSize: avatarSize ?? .large)
|
||||
.sink { completion in
|
||||
guard case let .failure(error) = completion else { return }
|
||||
UILog.error("[AvatarService] Failed to retrieve avatar: \(error)")
|
||||
|
||||
@@ -23,7 +23,7 @@ extension ThemeSwiftUI {
|
||||
/// Get the stable display name color based on userId.
|
||||
/// - Parameter userId: The user id used to hash.
|
||||
/// - Returns: The SwiftUI color for the associated userId.
|
||||
func displayNameColor(for userId: String) -> Color {
|
||||
func displayUserColor(for userId: String) -> Color {
|
||||
let senderNameColorIndex = Int(userId.vc_hashCode % Int32(colors.namesAndAvatars.count))
|
||||
return colors.namesAndAvatars[senderNameColorIndex]
|
||||
}
|
||||
37
RiotSwiftUI/Modules/Common/Util/BorderModifier.swift
Normal file
37
RiotSwiftUI/Modules/Common/Util/BorderModifier.swift
Normal file
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// Copyright 2022 New Vector Ltd
|
||||
//
|
||||
// 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 SwiftUI
|
||||
|
||||
@available(iOS 14.0, *)
|
||||
struct BorderModifier<Shape: InsettableShape>: ViewModifier {
|
||||
|
||||
var color: Color
|
||||
var borderWidth: CGFloat
|
||||
var shape: Shape
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
content
|
||||
.overlay(shape.stroke(color, lineWidth: borderWidth))
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 14.0, *)
|
||||
extension View {
|
||||
func shapedBorder<Shape: InsettableShape>(color: Color, borderWidth: CGFloat, shape: Shape) -> some View {
|
||||
modifier(BorderModifier(color: color, borderWidth: borderWidth, shape: shape))
|
||||
}
|
||||
}
|
||||
@@ -49,7 +49,8 @@ final class LocationSharingCoordinator: Coordinator, Presentable {
|
||||
|
||||
let viewModel = LocationSharingViewModel(mapStyleURL: BuildSettings.tileServerMapStyleURL,
|
||||
avatarData: parameters.avatarData,
|
||||
location: parameters.location)
|
||||
location: parameters.location,
|
||||
isLiveLocationSharingEnabled: BuildSettings.liveLocationSharingEnabled)
|
||||
let view = LocationSharingView(context: viewModel.context)
|
||||
.addDependency(AvatarService.instantiate(mediaManager: parameters.mediaManager))
|
||||
|
||||
|
||||
@@ -62,6 +62,9 @@ struct LocationSharingViewState: BindableState {
|
||||
/// True to indicate to show and follow current user location
|
||||
var showsUserLocation: Bool = false
|
||||
|
||||
/// Used to hide live location sharing features until is finished
|
||||
var isLiveLocationSharingEnabled: Bool
|
||||
|
||||
var shareButtonVisible: Bool {
|
||||
return self.displayExistingLocation == false
|
||||
}
|
||||
|
||||
@@ -37,7 +37,8 @@ enum MockLocationSharingScreenState: MockScreenState, CaseIterable {
|
||||
let mapStyleURL = URL(string: "https://api.maptiler.com/maps/streets/style.json?key=fU3vlMsMn4Jb6dnEIFsx")!
|
||||
let viewModel = LocationSharingViewModel(mapStyleURL: mapStyleURL,
|
||||
avatarData: AvatarInput(mxContentUri: "", matrixItemId: "alice:matrix.org", displayName: "Alice"),
|
||||
location: location)
|
||||
location: location,
|
||||
isLiveLocationSharingEnabled: true)
|
||||
return ([viewModel],
|
||||
AnyView(LocationSharingView(context: viewModel.context)
|
||||
.addDependency(MockAvatarService.example)))
|
||||
|
||||
@@ -35,7 +35,7 @@ class LocationSharingViewModel: LocationSharingViewModelType, LocationSharingVie
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(mapStyleURL: URL, avatarData: AvatarInputProtocol, location: CLLocationCoordinate2D? = nil) {
|
||||
init(mapStyleURL: URL, avatarData: AvatarInputProtocol, location: CLLocationCoordinate2D? = nil, isLiveLocationSharingEnabled: Bool) {
|
||||
|
||||
var userAnnotation: UserLocationAnnotation?
|
||||
var annotations: [UserLocationAnnotation] = []
|
||||
@@ -60,7 +60,8 @@ class LocationSharingViewModel: LocationSharingViewModelType, LocationSharingVie
|
||||
userAnnotation: userAnnotation,
|
||||
annotations: annotations,
|
||||
highlightedAnnotation: highlightedAnnotation,
|
||||
showsUserLocation: showsUserLocation)
|
||||
showsUserLocation: showsUserLocation,
|
||||
isLiveLocationSharingEnabled: isLiveLocationSharingEnabled)
|
||||
|
||||
super.init(initialViewState: viewState)
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
import SwiftUI
|
||||
|
||||
@available(iOS 14.0, *)
|
||||
struct LocationSharingUserMarkerView: View {
|
||||
struct LocationSharingMarkerView<Content: View>: View {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
@@ -25,37 +25,21 @@ struct LocationSharingUserMarkerView: View {
|
||||
|
||||
@Environment(\.theme) private var theme: ThemeSwiftUI
|
||||
|
||||
@State private var frame: CGRect = .zero
|
||||
|
||||
private var usernameColorGenerator: UserNameColorGenerator {
|
||||
let usernameColorGenerator = UserNameColorGenerator()
|
||||
let theme = ThemeService.shared().theme
|
||||
usernameColorGenerator.defaultColor = theme.textPrimaryColor
|
||||
usernameColorGenerator.userNameColors = theme.userNameColors
|
||||
return usernameColorGenerator
|
||||
}
|
||||
|
||||
// MARK: Public
|
||||
|
||||
let isMarker: Bool
|
||||
let avatarData: AvatarInputProtocol
|
||||
let backgroundColor: Color
|
||||
@ViewBuilder var markerImage: Content
|
||||
|
||||
var body: some View {
|
||||
let fillColor: Color = Color(usernameColorGenerator.color(from:avatarData.matrixItemId))
|
||||
ZStack {
|
||||
Circle()
|
||||
.fill(fillColor)
|
||||
.frame(width: 40, height: 40)
|
||||
if isMarker {
|
||||
Rectangle()
|
||||
.rotation(Angle(degrees: 45))
|
||||
.fill(fillColor)
|
||||
.frame(width: 7, height: 7)
|
||||
.offset(x: 0, y: 19)
|
||||
}
|
||||
AvatarImage(avatarData: avatarData, size: .small)
|
||||
Rectangle()
|
||||
.rotation(Angle(degrees: 45))
|
||||
.fill(backgroundColor)
|
||||
.frame(width: 7, height: 7)
|
||||
.offset(x: 0, y: 22)
|
||||
markerImage
|
||||
.frame(width: 42, height: 42)
|
||||
}
|
||||
.background(ViewFrameReader(frame: $frame))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,8 +52,14 @@ struct LocationSharingUserMarkerView_Previews: PreviewProvider {
|
||||
matrixItemId: "test",
|
||||
displayName: "Alice")
|
||||
VStack(alignment: .center, spacing: 15) {
|
||||
LocationSharingUserMarkerView(isMarker: true, avatarData: avatarData)
|
||||
LocationSharingUserMarkerView(isMarker: false, avatarData: avatarData)
|
||||
LocationSharingMarkerView(backgroundColor: .green) {
|
||||
AvatarImage(avatarData: avatarData, size: nil)
|
||||
.shapedBorder(color: Color.green, borderWidth: 3, shape: Circle())
|
||||
}
|
||||
LocationSharingMarkerView(backgroundColor: .green) {
|
||||
AvatarImage(avatarData: avatarData, size: nil)
|
||||
.shapedBorder(color: Color.green, borderWidth: 3, shape: Circle())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,12 +27,12 @@ struct LocationSharingOptionButton<Content: View>: View {
|
||||
|
||||
let text: String
|
||||
let action: () -> (Void)
|
||||
@ViewBuilder var content: Content
|
||||
@ViewBuilder var buttonIcon: Content
|
||||
|
||||
var body: some View {
|
||||
Button(action: action) {
|
||||
HStack(spacing: 18) {
|
||||
content
|
||||
buttonIcon
|
||||
.frame(width: 40, height: 40)
|
||||
Text(text)
|
||||
.font(theme.fonts.body)
|
||||
@@ -45,16 +45,22 @@ struct LocationSharingOptionButton<Content: View>: View {
|
||||
@available(iOS 14.0, *)
|
||||
struct LocationSharingOptionButton_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
VStack {
|
||||
LocationSharingOptionButton(text: "Share my current location") {
|
||||
VStack(alignment: .leading) {
|
||||
LocationSharingOptionButton(text: VectorL10n.locationSharingStaticShareTitle) {
|
||||
|
||||
} content: {
|
||||
LocationSharingUserMarkerView(isMarker: false, avatarData: AvatarInput(mxContentUri: "", matrixItemId: "test", displayName: "Nicolas"))
|
||||
} buttonIcon: {
|
||||
AvatarImage(avatarData: AvatarInput(mxContentUri: nil, matrixItemId: "Alice", displayName: "Alice"), size: nil)
|
||||
.shapedBorder(color: Color.green, borderWidth: 3, shape: Circle())
|
||||
}
|
||||
LocationSharingOptionButton(text: "Share live location") {
|
||||
LocationSharingOptionButton(text: VectorL10n.locationSharingLiveShareTitle) {
|
||||
|
||||
} content: {
|
||||
LocationSharingOptionButtonIcon(fillColor: Color.purple, image: Asset.Images.liveLocationIcon.image)
|
||||
} buttonIcon: {
|
||||
Image(uiImage: Asset.Images.locationLiveIcon.image)
|
||||
}
|
||||
LocationSharingOptionButton(text: VectorL10n.locationSharingPinDropShareTitle) {
|
||||
|
||||
} buttonIcon: {
|
||||
Image(uiImage: Asset.Images.locationPinIcon.image)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
//
|
||||
// Copyright 2022 New Vector Ltd
|
||||
//
|
||||
// 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 SwiftUI
|
||||
|
||||
@available(iOS 14.0, *)
|
||||
struct LocationSharingOptionButtonIcon: View {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
|
||||
@Environment(\.theme) private var theme: ThemeSwiftUI
|
||||
|
||||
let fillColor: Color
|
||||
let image: UIImage
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
Circle()
|
||||
.fill(fillColor)
|
||||
.frame(width: 40, height: 40)
|
||||
Image(uiImage: image)
|
||||
.renderingMode(.template)
|
||||
.foregroundColor(Color.white)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 14.0, *)
|
||||
struct LocationSharingOptionButtonIcon_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
LocationSharingOptionButtonIcon(fillColor: Color.green, image: Asset.Images.locationMarkerIcon.image)
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ struct LocationSharingView: View {
|
||||
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
VStack {
|
||||
VStack(spacing: 0) {
|
||||
ZStack(alignment: .bottom) {
|
||||
LocationSharingMapView(tileServerMapURL: context.viewState.mapStyleURL,
|
||||
annotations: context.viewState.annotations,
|
||||
@@ -46,7 +46,7 @@ struct LocationSharingView: View {
|
||||
}
|
||||
if context.viewState.shareButtonVisible {
|
||||
buttonsView
|
||||
.cornerRadius(5)
|
||||
.cornerRadius(10)
|
||||
}
|
||||
}
|
||||
.toolbar {
|
||||
@@ -90,25 +90,25 @@ struct LocationSharingView: View {
|
||||
if !context.viewState.isPinDropSharing {
|
||||
LocationSharingOptionButton(text: VectorL10n.locationSharingStaticShareTitle) {
|
||||
context.send(viewAction: .share)
|
||||
} content: {
|
||||
LocationSharingUserMarkerView(isMarker: false, avatarData: context.viewState.userAvatarData)
|
||||
} buttonIcon: {
|
||||
AvatarImage(avatarData: context.viewState.userAvatarData, size: nil)
|
||||
.shapedBorder(color: theme.displayUserColor(for: context.viewState.userAvatarData.matrixItemId), borderWidth: 3, shape: Circle())
|
||||
}
|
||||
.disabled(!context.viewState.shareButtonEnabled)
|
||||
// Disable for now until live location sharing is done
|
||||
if BuildSettings.liveLocationSharingEnabled {
|
||||
// Hide for now until live location sharing is finished
|
||||
if context.viewState.isLiveLocationSharingEnabled {
|
||||
LocationSharingOptionButton(text: VectorL10n.locationSharingLiveShareTitle) {
|
||||
// TODO: - Start live location sharing
|
||||
} content: {
|
||||
LocationSharingOptionButtonIcon(fillColor: Color.purple, image: Asset.Images.liveLocationIcon.image)
|
||||
} buttonIcon: {
|
||||
Image(uiImage: Asset.Images.locationLiveIcon.image)
|
||||
}
|
||||
.disabled(!context.viewState.shareButtonEnabled)
|
||||
}
|
||||
} else {
|
||||
LocationSharingOptionButton(text: VectorL10n.locationSharingPinDropShareTitle) {
|
||||
// TODO: - Pin drop sharing action
|
||||
} content: {
|
||||
LocationSharingOptionButtonIcon(fillColor:
|
||||
theme.colors.primaryContent, image: Asset.Images.locationMarkerIcon.image)
|
||||
} buttonIcon: {
|
||||
Image(uiImage: Asset.Images.locationPinIcon.image)
|
||||
}
|
||||
.disabled(!context.viewState.shareButtonEnabled)
|
||||
}
|
||||
|
||||
@@ -21,6 +21,10 @@ import Mapbox
|
||||
@available(iOS 14, *)
|
||||
class UserLocationAnnotatonView: MGLUserLocationAnnotationView {
|
||||
|
||||
// MARK: Private
|
||||
|
||||
@Environment(\.theme) private var theme: ThemeSwiftUI
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(avatarData: AvatarInputProtocol) {
|
||||
@@ -45,7 +49,10 @@ class UserLocationAnnotatonView: MGLUserLocationAnnotationView {
|
||||
|
||||
private func addUserMarkerView(with avatarData: AvatarInputProtocol) {
|
||||
|
||||
guard let avatarImageView = UIHostingController(rootView: LocationSharingUserMarkerView(isMarker: true, avatarData: avatarData)).view else {
|
||||
guard let avatarImageView = UIHostingController(rootView: LocationSharingMarkerView(backgroundColor: theme.displayUserColor(for: avatarData.matrixItemId)) {
|
||||
AvatarImage(avatarData: avatarData, size: nil)
|
||||
.shapedBorder(color: theme.displayUserColor(for: avatarData.matrixItemId), borderWidth: 3, shape: Circle())
|
||||
}).view else {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ struct TemplateRoomChatBubbleView: View {
|
||||
.accessibility(identifier: "bubbleImage")
|
||||
VStack(alignment: .leading){
|
||||
Text(bubble.sender.displayName ?? "")
|
||||
.foregroundColor(theme.displayNameColor(for: bubble.sender.id))
|
||||
.foregroundColor(theme.displayUserColor(for: bubble.sender.id))
|
||||
.font(theme.fonts.bodySB)
|
||||
ForEach(bubble.items) { item in
|
||||
TemplateRoomChatBubbleContentView(bubbleItem: item)
|
||||
|
||||
Reference in New Issue
Block a user