Add proximity alert toasts

This commit is contained in:
Ilya Laktyushin 2020-10-29 16:28:51 +04:00
parent 7666f05864
commit db42d63c40
8 changed files with 129 additions and 4 deletions

View File

@ -38,6 +38,7 @@ static_library(
"//submodules/LiveLocationTimerNode:LiveLocationTimerNode", "//submodules/LiveLocationTimerNode:LiveLocationTimerNode",
"//submodules/TelegramNotices:TelegramNotices", "//submodules/TelegramNotices:TelegramNotices",
"//submodules/TooltipUI:TooltipUI", "//submodules/TooltipUI:TooltipUI",
"//submodules/UndoUI:UndoUI",
], ],
frameworks = [ frameworks = [
"$SDKROOT/System/Library/Frameworks/Foundation.framework", "$SDKROOT/System/Library/Frameworks/Foundation.framework",

View File

@ -39,6 +39,7 @@ swift_library(
"//submodules/LiveLocationTimerNode:LiveLocationTimerNode", "//submodules/LiveLocationTimerNode:LiveLocationTimerNode",
"//submodules/TelegramNotices:TelegramNotices", "//submodules/TelegramNotices:TelegramNotices",
"//submodules/TooltipUI:TooltipUI", "//submodules/TooltipUI:TooltipUI",
"//submodules/UndoUI:UndoUI",
], ],
visibility = [ visibility = [
"//visibility:public", "//visibility:public",

View File

@ -195,6 +195,8 @@ class LocationDistancePickerScreenNode: ViewControllerTracingNode, UIScrollViewD
private let unitLabelNode: ImmediateTextNode private let unitLabelNode: ImmediateTextNode
private let smallUnitLabelNode: ImmediateTextNode private let smallUnitLabelNode: ImmediateTextNode
private var pickerTimer: SwiftSignalKit.Timer?
private var containerLayout: (ContainerViewLayout, CGFloat)? private var containerLayout: (ContainerViewLayout, CGFloat)?
private var distancesDisposable: Disposable? private var distancesDisposable: Disposable?
@ -321,6 +323,8 @@ class LocationDistancePickerScreenNode: ViewControllerTracingNode, UIScrollViewD
deinit { deinit {
self.distancesDisposable?.dispose() self.distancesDisposable?.dispose()
self.pickerTimer?.invalidate()
} }
func setupPickerView() { func setupPickerView() {
@ -345,6 +349,18 @@ class LocationDistancePickerScreenNode: ViewControllerTracingNode, UIScrollViewD
self.contentContainerNode.addSubnode(self.unitLabelNode) self.contentContainerNode.addSubnode(self.unitLabelNode)
self.contentContainerNode.addSubnode(self.smallUnitLabelNode) self.contentContainerNode.addSubnode(self.smallUnitLabelNode)
self.pickerTimer?.invalidate()
let pickerTimer = SwiftSignalKit.Timer(timeout: 0.4, repeat: true, completion: { [weak self] in
if let strongSelf = self {
if strongSelf.update() {
strongSelf.updateDoneButtonTitle()
}
}
}, queue: Queue.mainQueue())
self.pickerTimer = pickerTimer
pickerTimer.start()
self.updateDoneButtonTitle() self.updateDoneButtonTitle()
} }
@ -414,7 +430,8 @@ class LocationDistancePickerScreenNode: ViewControllerTracingNode, UIScrollViewD
} }
} }
fileprivate func update() { var previousReportedValue: Int32?
fileprivate func update() -> Bool {
if let pickerView = self.pickerView { if let pickerView = self.pickerView {
let selectedLargeRow = pickerView.selectedRow(inComponent: 0) let selectedLargeRow = pickerView.selectedRow(inComponent: 0)
var selectedSmallRow = pickerView.selectedRow(inComponent: 1) var selectedSmallRow = pickerView.selectedRow(inComponent: 1)
@ -429,7 +446,16 @@ class LocationDistancePickerScreenNode: ViewControllerTracingNode, UIScrollViewD
if !self.usesMetricSystem { if !self.usesMetricSystem {
value = Int32(Double(value) * 1.60934) value = Int32(Double(value) * 1.60934)
} }
self.updated?(value)
if let previousReportedValue = self.previousReportedValue, value == previousReportedValue {
return false
} else {
self.updated?(value)
self.previousReportedValue = value
return true
}
} else {
return false
} }
} }

View File

@ -7,6 +7,7 @@ import SyncCore
import Postbox import Postbox
import SwiftSignalKit import SwiftSignalKit
import TelegramPresentationData import TelegramPresentationData
import TelegramStringFormatting
import AccountContext import AccountContext
import AppBundle import AppBundle
import CoreLocation import CoreLocation
@ -14,6 +15,7 @@ import PresentationDataUtils
import OpenInExternalAppUI import OpenInExternalAppUI
import ShareController import ShareController
import DeviceAccess import DeviceAccess
import UndoUI
public class LocationViewParams { public class LocationViewParams {
let sendLiveLocation: (TelegramMediaMap) -> Void let sendLiveLocation: (TelegramMediaMap) -> Void
@ -202,6 +204,21 @@ public final class LocationViewController: ViewController {
} }
} }
}) })
strongSelf.present(
UndoOverlayController(
presentationData: strongSelf.presentationData,
content: .setProximityAlert(
title: strongSelf.presentationData.strings.Location_ProximityAlertCancelled,
text: "",
cancelled: true
),
elevatedLayout: false,
action: { action in
return true
}
),
in: .current
)
} }
} else { } else {
DeviceAccess.authorizeAccess(to: .location(.live), locationManager: strongSelf.locationManager, presentationData: strongSelf.presentationData, present: { c, a in DeviceAccess.authorizeAccess(to: .location(.live), locationManager: strongSelf.locationManager, presentationData: strongSelf.presentationData, present: { c, a in
@ -254,6 +271,30 @@ public final class LocationViewController: ViewController {
} }
} }
}) })
var text: String
let distanceString = shortStringForDistance(strings: strongSelf.presentationData.strings, distance: distance)
if let compactDisplayTitle = compactDisplayTitle {
text = strongSelf.presentationData.strings.Location_ProximityAlertSetText(compactDisplayTitle, distanceString).0
} else {
text = strongSelf.presentationData.strings.Location_ProximityAlertSetTextGroup(distanceString).0
}
strongSelf.present(
UndoOverlayController(
presentationData: strongSelf.presentationData,
content: .setProximityAlert(
title: strongSelf.presentationData.strings.Location_ProximityAlertSetTitle,
text: text,
cancelled: false
),
elevatedLayout: false,
action: { action in
return true
}
),
in: .current
)
} else { } else {
strongSelf.present(textAlertController(context: strongSelf.context, 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, 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()
@ -293,6 +334,42 @@ public final class LocationViewController: ViewController {
|> deliverOnMainQueue).start(next: { coordinate in |> deliverOnMainQueue).start(next: { coordinate in
params.sendLiveLocation(TelegramMediaMap(coordinate: coordinate, liveBroadcastingTimeout: 30 * 60, proximityNotificationRadius: distance)) params.sendLiveLocation(TelegramMediaMap(coordinate: coordinate, liveBroadcastingTimeout: 30 * 60, proximityNotificationRadius: distance))
}) })
let _ = (strongSelf.context.account.postbox.loadedPeerWithId(strongSelf.subject.id.peerId)
|> deliverOnMainQueue).start(next: { [weak self] peer in
guard let strongSelf = self else {
return
}
var compactDisplayTitle: String?
if let peer = peer as? TelegramUser {
compactDisplayTitle = peer.compactDisplayTitle
}
var text: String
let distanceString = shortStringForDistance(strings: strongSelf.presentationData.strings, distance: distance)
if let compactDisplayTitle = compactDisplayTitle {
text = strongSelf.presentationData.strings.Location_ProximityAlertSetText(compactDisplayTitle, distanceString).0
} else {
text = strongSelf.presentationData.strings.Location_ProximityAlertSetTextGroup(distanceString).0
}
strongSelf.present(
UndoOverlayController(
presentationData: strongSelf.presentationData,
content: .setProximityAlert(
title: strongSelf.presentationData.strings.Location_ProximityAlertSetTitle,
text: text,
cancelled: false
),
elevatedLayout: false,
action: { action in
return true
}
),
in: .current
)
})
} else { } else {
let _ = (context.account.postbox.loadedPeerWithId(subject.id.peerId) let _ = (context.account.postbox.loadedPeerWithId(subject.id.peerId)
|> deliverOnMainQueue).start(next: { peer in |> deliverOnMainQueue).start(next: { peer in

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -21,6 +21,7 @@ public enum UndoOverlayContent {
case chatAddedToFolder(chatTitle: String, folderTitle: String) case chatAddedToFolder(chatTitle: String, folderTitle: String)
case chatRemovedFromFolder(chatTitle: String, folderTitle: String) case chatRemovedFromFolder(chatTitle: String, folderTitle: String)
case messagesUnpinned(title: String, text: String, undo: Bool, isHidden: Bool) case messagesUnpinned(title: String, text: String, undo: Bool, isHidden: Bool)
case setProximityAlert(title: String, text: String, cancelled: Bool)
} }
public enum UndoOverlayAction { public enum UndoOverlayAction {

View File

@ -221,7 +221,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
} }
displayUndo = undo displayUndo = undo
self.originalRemainingSeconds = undo ? 5 : 5 self.originalRemainingSeconds = 5
case let .emoji(path, text): case let .emoji(path, text):
self.iconNode = nil self.iconNode = nil
self.iconCheckNode = nil self.iconCheckNode = nil
@ -388,6 +388,23 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
} }
}) })
} }
case let .setProximityAlert(title, text, cancelled):
self.iconNode = nil
self.iconCheckNode = nil
self.animationNode = AnimationNode(animation: cancelled ? "anim_proximity_cancelled" : "anim_proximity_set", colors: [:], scale: 0.45)
self.animatedStickerNode = nil
let body = MarkdownAttributeSet(font: Font.regular(14.0), textColor: .white)
let bold = MarkdownAttributeSet(font: Font.semibold(14.0), textColor: .white)
let link = MarkdownAttributeSet(font: Font.regular(14.0), textColor: undoTextColor)
let attributedText = parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes(body: body, bold: bold, link: link, linkAttribute: { _ in return nil }), textAlignment: .natural)
self.titleNode.attributedText = NSAttributedString(string: title, font: Font.semibold(14.0), textColor: .white)
if !text.isEmpty {
self.textNode.attributedText = attributedText
}
displayUndo = false
self.originalRemainingSeconds = 3
} }
self.remainingSeconds = self.originalRemainingSeconds self.remainingSeconds = self.originalRemainingSeconds
@ -416,7 +433,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
switch content { switch content {
case .removedChat: case .removedChat:
self.panelWrapperNode.addSubnode(self.timerTextNode) self.panelWrapperNode.addSubnode(self.timerTextNode)
case .archivedChat, .hidArchive, .revealedArchive, .succeed, .emoji, .swipeToReply, .actionSucceeded, .stickersModified, .chatAddedToFolder, .chatRemovedFromFolder, .messagesUnpinned: case .archivedChat, .hidArchive, .revealedArchive, .succeed, .emoji, .swipeToReply, .actionSucceeded, .stickersModified, .chatAddedToFolder, .chatRemovedFromFolder, .messagesUnpinned, .setProximityAlert:
break break
case .dice: case .dice:
self.panelWrapperNode.clipsToBounds = true self.panelWrapperNode.clipsToBounds = true