Live location improvements

This commit is contained in:
Ilya Laktyushin 2024-04-17 01:49:15 +04:00
parent 156c84e4f7
commit 6766f1358c
7 changed files with 40 additions and 32 deletions

View File

@ -177,7 +177,7 @@ public final class LiveLocationManagerImpl: LiveLocationManager {
let addedStopped = stopMessageIds.subtracting(self.stopMessageIds) let addedStopped = stopMessageIds.subtracting(self.stopMessageIds)
self.stopMessageIds = stopMessageIds self.stopMessageIds = stopMessageIds
for id in addedStopped { for id in addedStopped {
self.editMessageDisposables.set((self.engine.messages.requestEditLiveLocation(messageId: id, stop: true, coordinate: nil, heading: nil, proximityNotificationRadius: nil) self.editMessageDisposables.set((self.engine.messages.requestEditLiveLocation(messageId: id, stop: true, coordinate: nil, heading: nil, proximityNotificationRadius: nil, extendPeriod: nil)
|> deliverOn(self.queue)).start(completed: { [weak self] in |> deliverOn(self.queue)).start(completed: { [weak self] in
if let strongSelf = self { if let strongSelf = self {
strongSelf.editMessageDisposables.set(nil, forKey: id) strongSelf.editMessageDisposables.set(nil, forKey: id)
@ -232,7 +232,7 @@ public final class LiveLocationManagerImpl: LiveLocationManager {
let ids = self.broadcastToMessageIds let ids = self.broadcastToMessageIds
let remainingIds = Atomic<Set<EngineMessage.Id>>(value: Set(ids.keys)) let remainingIds = Atomic<Set<EngineMessage.Id>>(value: Set(ids.keys))
for id in ids.keys { for id in ids.keys {
self.editMessageDisposables.set((self.engine.messages.requestEditLiveLocation(messageId: id, stop: false, coordinate: (latitude: coordinate.latitude, longitude: coordinate.longitude, accuracyRadius: Int32(accuracyRadius)), heading: heading.flatMap { Int32($0) }, proximityNotificationRadius: nil) self.editMessageDisposables.set((self.engine.messages.requestEditLiveLocation(messageId: id, stop: false, coordinate: (latitude: coordinate.latitude, longitude: coordinate.longitude, accuracyRadius: Int32(accuracyRadius)), heading: heading.flatMap { Int32($0) }, proximityNotificationRadius: nil, extendPeriod: nil)
|> deliverOn(self.queue)).start(completed: { [weak self] in |> deliverOn(self.queue)).start(completed: { [weak self] in
if let strongSelf = self { if let strongSelf = self {
strongSelf.editMessageDisposables.set(nil, forKey: id) strongSelf.editMessageDisposables.set(nil, forKey: id)

View File

@ -63,6 +63,8 @@ public final class ChatMessageLiveLocationTimerNode: ASDisplayNode {
}), selector: #selector(RadialTimeoutNodeTimer.event), userInfo: nil, repeats: true) }), selector: #selector(RadialTimeoutNodeTimer.event), userInfo: nil, repeats: true)
self.animationTimer = animationTimer self.animationTimer = animationTimer
RunLoop.main.add(animationTimer, forMode: .common) RunLoop.main.add(animationTimer, forMode: .common)
self.setNeedsDisplay()
} }
} }

View File

@ -47,12 +47,12 @@ class LocationViewInteraction {
let share: () -> Void let share: () -> Void
let setupProximityNotification: (Bool, EngineMessage.Id?) -> Void let setupProximityNotification: (Bool, EngineMessage.Id?) -> Void
let updateSendActionHighlight: (Bool) -> Void let updateSendActionHighlight: (Bool) -> Void
let sendLiveLocation: (Int32?, Bool) -> Void let sendLiveLocation: (Int32?, Bool, EngineMessage.Id?) -> Void
let stopLiveLocation: () -> Void let stopLiveLocation: () -> Void
let updateRightBarButton: (LocationViewRightBarButton) -> Void let updateRightBarButton: (LocationViewRightBarButton) -> Void
let present: (ViewController) -> Void let present: (ViewController) -> Void
init(toggleMapModeSelection: @escaping () -> Void, updateMapMode: @escaping (LocationMapMode) -> Void, toggleTrackingMode: @escaping () -> Void, goToCoordinate: @escaping (CLLocationCoordinate2D) -> Void, requestDirections: @escaping (TelegramMediaMap, String?, OpenInLocationDirections) -> Void, share: @escaping () -> Void, setupProximityNotification: @escaping (Bool, EngineMessage.Id?) -> Void, updateSendActionHighlight: @escaping (Bool) -> Void, sendLiveLocation: @escaping (Int32?, Bool) -> Void, stopLiveLocation: @escaping () -> Void, updateRightBarButton: @escaping (LocationViewRightBarButton) -> Void, present: @escaping (ViewController) -> Void) { init(toggleMapModeSelection: @escaping () -> Void, updateMapMode: @escaping (LocationMapMode) -> Void, toggleTrackingMode: @escaping () -> Void, goToCoordinate: @escaping (CLLocationCoordinate2D) -> Void, requestDirections: @escaping (TelegramMediaMap, String?, OpenInLocationDirections) -> Void, share: @escaping () -> Void, setupProximityNotification: @escaping (Bool, EngineMessage.Id?) -> Void, updateSendActionHighlight: @escaping (Bool) -> Void, sendLiveLocation: @escaping (Int32?, Bool, EngineMessage.Id?) -> Void, stopLiveLocation: @escaping () -> Void, updateRightBarButton: @escaping (LocationViewRightBarButton) -> Void, present: @escaping (ViewController) -> Void) {
self.toggleMapModeSelection = toggleMapModeSelection self.toggleMapModeSelection = toggleMapModeSelection
self.updateMapMode = updateMapMode self.updateMapMode = updateMapMode
self.toggleTrackingMode = toggleTrackingMode self.toggleTrackingMode = toggleTrackingMode
@ -214,7 +214,7 @@ public final class LocationViewController: ViewController {
return state return state
} }
let _ = context.engine.messages.requestEditLiveLocation(messageId: messageId, stop: false, coordinate: nil, heading: nil, proximityNotificationRadius: 0).start(completed: { [weak self] in let _ = context.engine.messages.requestEditLiveLocation(messageId: messageId, stop: false, coordinate: nil, heading: nil, proximityNotificationRadius: 0, extendPeriod: nil).start(completed: { [weak self] in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
@ -283,7 +283,7 @@ public final class LocationViewController: ViewController {
return state return state
} }
let _ = context.engine.messages.requestEditLiveLocation(messageId: messageId, stop: false, coordinate: nil, heading: nil, proximityNotificationRadius: distance).start(completed: { [weak self] in let _ = context.engine.messages.requestEditLiveLocation(messageId: messageId, stop: false, coordinate: nil, heading: nil, proximityNotificationRadius: distance, extendPeriod: nil).start(completed: { [weak self] in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
@ -323,7 +323,7 @@ public final class LocationViewController: ViewController {
} else { } else {
strongSelf.present(textAlertController(context: strongSelf.context, updatedPresentationData: updatedPresentationData, title: strongSelf.presentationData.strings.Location_LiveLocationRequired_Title, text: strongSelf.presentationData.strings.Location_LiveLocationRequired_Description, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Location_LiveLocationRequired_ShareLocation, action: { strongSelf.present(textAlertController(context: strongSelf.context, updatedPresentationData: updatedPresentationData, title: strongSelf.presentationData.strings.Location_LiveLocationRequired_Title, text: strongSelf.presentationData.strings.Location_LiveLocationRequired_Description, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Location_LiveLocationRequired_ShareLocation, action: {
completion() completion()
strongSelf.interaction?.sendLiveLocation(distance, false) strongSelf.interaction?.sendLiveLocation(distance, false, nil)
}), TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {})], actionLayout: .vertical), in: .window(.root)) }), TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {})], actionLayout: .vertical), in: .window(.root))
} }
completion() completion()
@ -341,7 +341,7 @@ public final class LocationViewController: ViewController {
return return
} }
strongSelf.controllerNode.updateSendActionHighlight(highlighted) strongSelf.controllerNode.updateSendActionHighlight(highlighted)
}, sendLiveLocation: { [weak self] distance, extend in }, sendLiveLocation: { [weak self] distance, extend, messageId in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
@ -413,12 +413,18 @@ public final class LocationViewController: ViewController {
let sendLiveLocationImpl: (Int32) -> Void = { [weak controller] period in let sendLiveLocationImpl: (Int32) -> Void = { [weak controller] period in
controller?.dismissAnimated() controller?.dismissAnimated()
let _ = (strongSelf.controllerNode.coordinate if extend {
|> deliverOnMainQueue).start(next: { coordinate in if let messageId {
params.sendLiveLocation(TelegramMediaMap(coordinate: coordinate, liveBroadcastingTimeout: period)) let _ = context.engine.messages.requestEditLiveLocation(messageId: messageId, stop: false, coordinate: nil, heading: nil, proximityNotificationRadius: nil, extendPeriod: period).start()
}) }
} else {
strongSelf.controllerNode.showAll() let _ = (strongSelf.controllerNode.coordinate
|> deliverOnMainQueue).start(next: { coordinate in
params.sendLiveLocation(TelegramMediaMap(coordinate: coordinate, liveBroadcastingTimeout: period))
})
strongSelf.controllerNode.showAll()
}
} }
controller.setItemGroups([ controller.setItemGroups([

View File

@ -48,14 +48,14 @@ private enum LocationViewEntryId: Hashable {
private enum LocationViewEntry: Comparable, Identifiable { private enum LocationViewEntry: Comparable, Identifiable {
case info(PresentationTheme, TelegramMediaMap, String?, Double?, ExpectedTravelTime, ExpectedTravelTime, ExpectedTravelTime, Bool) case info(PresentationTheme, TelegramMediaMap, String?, Double?, ExpectedTravelTime, ExpectedTravelTime, ExpectedTravelTime, Bool)
case toggleLiveLocation(PresentationTheme, String, String, Double?, Double?, Bool) case toggleLiveLocation(PresentationTheme, String, String, Double?, Double?, Bool, EngineMessage.Id?)
case liveLocation(PresentationTheme, PresentationDateTimeFormat, PresentationPersonNameOrder, EngineMessage, Double?, ExpectedTravelTime, ExpectedTravelTime, ExpectedTravelTime, Int) case liveLocation(PresentationTheme, PresentationDateTimeFormat, PresentationPersonNameOrder, EngineMessage, Double?, ExpectedTravelTime, ExpectedTravelTime, ExpectedTravelTime, Int)
var stableId: LocationViewEntryId { var stableId: LocationViewEntryId {
switch self { switch self {
case .info: case .info:
return .info return .info
case let .toggleLiveLocation(_, _, _, _, _, additional): case let .toggleLiveLocation(_, _, _, _, _, additional, _):
return .toggleLiveLocation(additional) return .toggleLiveLocation(additional)
case let .liveLocation(_, _, _, message, _, _, _, _, _): case let .liveLocation(_, _, _, message, _, _, _, _, _):
return .liveLocation(message.stableId) return .liveLocation(message.stableId)
@ -70,8 +70,8 @@ private enum LocationViewEntry: Comparable, Identifiable {
} else { } else {
return false return false
} }
case let .toggleLiveLocation(lhsTheme, lhsTitle, lhsSubtitle, lhsBeginTimestamp, lhsTimeout, lhsAdditional): case let .toggleLiveLocation(lhsTheme, lhsTitle, lhsSubtitle, lhsBeginTimestamp, lhsTimeout, lhsAdditional, lhsMessageId):
if case let .toggleLiveLocation(rhsTheme, rhsTitle, rhsSubtitle, rhsBeginTimestamp, rhsTimeout, rhsAdditional) = rhs, lhsTheme === rhsTheme, lhsTitle == rhsTitle, lhsSubtitle == rhsSubtitle, lhsBeginTimestamp == rhsBeginTimestamp, lhsTimeout == rhsTimeout, lhsAdditional == rhsAdditional { if case let .toggleLiveLocation(rhsTheme, rhsTitle, rhsSubtitle, rhsBeginTimestamp, rhsTimeout, rhsAdditional, rhsMessageId) = rhs, lhsTheme === rhsTheme, lhsTitle == rhsTitle, lhsSubtitle == rhsSubtitle, lhsBeginTimestamp == rhsBeginTimestamp, lhsTimeout == rhsTimeout, lhsAdditional == rhsAdditional, lhsMessageId == rhsMessageId {
return true return true
} else { } else {
return false return false
@ -94,11 +94,11 @@ private enum LocationViewEntry: Comparable, Identifiable {
case .toggleLiveLocation, .liveLocation: case .toggleLiveLocation, .liveLocation:
return true return true
} }
case let .toggleLiveLocation(_, _, _, _, _, lhsAdditional): case let .toggleLiveLocation(_, _, _, _, _, lhsAdditional, _):
switch rhs { switch rhs {
case .info: case .info:
return false return false
case let .toggleLiveLocation(_, _, _, _, _, rhsAdditional): case let .toggleLiveLocation(_, _, _, _, _, rhsAdditional, _):
return !lhsAdditional && rhsAdditional return !lhsAdditional && rhsAdditional
case .liveLocation: case .liveLocation:
return true return true
@ -137,7 +137,7 @@ private enum LocationViewEntry: Comparable, Identifiable {
}, walkingAction: { }, walkingAction: {
interaction?.requestDirections(location, nil, .walking) interaction?.requestDirections(location, nil, .walking)
}) })
case let .toggleLiveLocation(_, title, subtitle, beginTimstamp, timeout, additional): case let .toggleLiveLocation(_, title, subtitle, beginTimstamp, timeout, additional, messageId):
var beginTimeAndTimeout: (Double, Double)? var beginTimeAndTimeout: (Double, Double)?
if let beginTimstamp = beginTimstamp, let timeout = timeout { if let beginTimstamp = beginTimstamp, let timeout = timeout {
beginTimeAndTimeout = (beginTimstamp, timeout) beginTimeAndTimeout = (beginTimstamp, timeout)
@ -160,13 +160,13 @@ private enum LocationViewEntry: Comparable, Identifiable {
if additional { if additional {
interaction?.stopLiveLocation() interaction?.stopLiveLocation()
} else { } else {
interaction?.sendLiveLocation(nil, true) interaction?.sendLiveLocation(nil, true, messageId)
} }
} else { } else {
interaction?.stopLiveLocation() interaction?.stopLiveLocation()
} }
} else { } else {
interaction?.sendLiveLocation(nil, false) interaction?.sendLiveLocation(nil, false, nil)
} }
}, highlighted: { highlight in }, highlighted: { highlight in
interaction?.updateSendActionHighlight(highlight) interaction?.updateSendActionHighlight(highlight)
@ -442,10 +442,10 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
if case let .channel(channel) = subject.author, case .broadcast = channel.info, activeOwnLiveLocation == nil { if case let .channel(channel) = subject.author, case .broadcast = channel.info, activeOwnLiveLocation == nil {
} else { } else {
if let timeout, Int32(timeout) != liveLocationIndefinitePeriod { if let timeout, Int32(timeout) != liveLocationIndefinitePeriod {
entries.append(.toggleLiveLocation(presentationData.theme, presentationData.strings.Map_SharingLocation, presentationData.strings.Map_TapToAddTime, beginTime, timeout, false)) entries.append(.toggleLiveLocation(presentationData.theme, presentationData.strings.Map_SharingLocation, presentationData.strings.Map_TapToAddTime, beginTime, timeout, false, activeOwnLiveLocation?.id))
entries.append(.toggleLiveLocation(presentationData.theme, title, subtitle, beginTime, timeout, true)) entries.append(.toggleLiveLocation(presentationData.theme, title, subtitle, beginTime, timeout, true, nil))
} else { } else {
entries.append(.toggleLiveLocation(presentationData.theme, title, subtitle, beginTime, timeout, false)) entries.append(.toggleLiveLocation(presentationData.theme, title, subtitle, beginTime, timeout, false, nil))
} }
} }

View File

@ -263,7 +263,7 @@ private func requestEditMessageInternal(accountPeerId: PeerId, postbox: Postbox,
} }
} }
func _internal_requestEditLiveLocation(postbox: Postbox, network: Network, stateManager: AccountStateManager, messageId: MessageId, stop: Bool, coordinate: (latitude: Double, longitude: Double, accuracyRadius: Int32?)?, heading: Int32?, proximityNotificationRadius: Int32?) -> Signal<Void, NoError> { func _internal_requestEditLiveLocation(postbox: Postbox, network: Network, stateManager: AccountStateManager, messageId: MessageId, stop: Bool, coordinate: (latitude: Double, longitude: Double, accuracyRadius: Int32?)?, heading: Int32?, proximityNotificationRadius: Int32?, extendPeriod: Int32?) -> Signal<Void, NoError> {
return postbox.transaction { transaction -> (Api.InputPeer, TelegramMediaMap)? in return postbox.transaction { transaction -> (Api.InputPeer, TelegramMediaMap)? in
guard let inputPeer = transaction.getPeer(messageId.peerId).flatMap(apiInputPeer) else { guard let inputPeer = transaction.getPeer(messageId.peerId).flatMap(apiInputPeer) else {
return nil return nil
@ -305,7 +305,7 @@ func _internal_requestEditLiveLocation(postbox: Postbox, network: Network, state
if let _ = proximityNotificationRadius { if let _ = proximityNotificationRadius {
flags |= 1 << 3 flags |= 1 << 3
} }
inputMedia = .inputMediaGeoLive(flags: flags, geoPoint: inputGeoPoint, heading: heading, period: liveBroadcastingTimeout, proximityNotificationRadius: proximityNotificationRadius) inputMedia = .inputMediaGeoLive(flags: flags, geoPoint: inputGeoPoint, heading: heading, period: extendPeriod.flatMap { $0 + liveBroadcastingTimeout } ?? liveBroadcastingTimeout, proximityNotificationRadius: proximityNotificationRadius)
} else { } else {
inputMedia = .inputMediaGeoLive(flags: 1 << 0, geoPoint: .inputGeoPoint(flags: 0, lat: media.latitude, long: media.longitude, accuracyRadius: nil), heading: nil, period: nil, proximityNotificationRadius: nil) inputMedia = .inputMediaGeoLive(flags: 1 << 0, geoPoint: .inputGeoPoint(flags: 0, lat: media.latitude, long: media.longitude, accuracyRadius: nil), heading: nil, period: nil, proximityNotificationRadius: nil)
} }
@ -319,7 +319,7 @@ func _internal_requestEditLiveLocation(postbox: Postbox, network: Network, state
if let updates = updates { if let updates = updates {
stateManager.addUpdates(updates) stateManager.addUpdates(updates)
} }
if coordinate == nil && proximityNotificationRadius == nil { if coordinate == nil && proximityNotificationRadius == nil && extendPeriod == nil {
return postbox.transaction { transaction -> Void in return postbox.transaction { transaction -> Void in
transaction.updateMessage(messageId, update: { currentMessage in transaction.updateMessage(messageId, update: { currentMessage in
var storeForwardInfo: StoreMessageForwardInfo? var storeForwardInfo: StoreMessageForwardInfo?

View File

@ -130,8 +130,8 @@ public extension TelegramEngine {
return _internal_requestEditMessage(account: self.account, messageId: messageId, text: text, media: media, entities: entities, inlineStickers: inlineStickers, webpagePreviewAttribute: webpagePreviewAttribute, disableUrlPreview: disableUrlPreview, scheduleTime: scheduleTime) return _internal_requestEditMessage(account: self.account, messageId: messageId, text: text, media: media, entities: entities, inlineStickers: inlineStickers, webpagePreviewAttribute: webpagePreviewAttribute, disableUrlPreview: disableUrlPreview, scheduleTime: scheduleTime)
} }
public func requestEditLiveLocation(messageId: MessageId, stop: Bool, coordinate: (latitude: Double, longitude: Double, accuracyRadius: Int32?)?, heading: Int32?, proximityNotificationRadius: Int32?) -> Signal<Void, NoError> { public func requestEditLiveLocation(messageId: MessageId, stop: Bool, coordinate: (latitude: Double, longitude: Double, accuracyRadius: Int32?)?, heading: Int32?, proximityNotificationRadius: Int32?, extendPeriod: Int32?) -> Signal<Void, NoError> {
return _internal_requestEditLiveLocation(postbox: self.account.postbox, network: self.account.network, stateManager: self.account.stateManager, messageId: messageId, stop: stop, coordinate: coordinate, heading: heading, proximityNotificationRadius: proximityNotificationRadius) return _internal_requestEditLiveLocation(postbox: self.account.postbox, network: self.account.network, stateManager: self.account.stateManager, messageId: messageId, stop: stop, coordinate: coordinate, heading: heading, proximityNotificationRadius: proximityNotificationRadius, extendPeriod: extendPeriod)
} }
public func addSecretChatMessageScreenshot(peerId: PeerId) -> Signal<Never, NoError> { public func addSecretChatMessageScreenshot(peerId: PeerId) -> Signal<Never, NoError> {

View File

@ -46,7 +46,7 @@ final class MediaEditorVideoFFMpegWriter: MediaEditorVideoExportWriter {
} }
self.pool = pool self.pool = pool
if !self.ffmpegWriter.setup(withOutputPath: outputPath, width: width, height: height, bitrate: 200 * 1000, framerate: 30) { if !self.ffmpegWriter.setup(withOutputPath: outputPath, width: width, height: height, bitrate: 240 * 1000, framerate: 30) {
self.status = .failed self.status = .failed
} }
} }