mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various fixes
This commit is contained in:
parent
4b5ccefbc8
commit
46f9dd3af2
@ -63,7 +63,7 @@ public enum LegacyICloudFilePickerMode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func legacyICloudFilePicker(theme: PresentationTheme, mode: LegacyICloudFilePickerMode = .default, documentTypes: [String] = ["public.item"], forceDarkTheme: Bool = false, completion: @escaping ([URL]) -> Void) -> ViewController {
|
public func legacyICloudFilePicker(theme: PresentationTheme, mode: LegacyICloudFilePickerMode = .default, documentTypes: [String] = ["public.item"], forceDarkTheme: Bool = false, dismissed: @escaping () -> Void = {}, completion: @escaping ([URL]) -> Void) -> ViewController {
|
||||||
var dismissImpl: (() -> Void)?
|
var dismissImpl: (() -> Void)?
|
||||||
let legacyController = LegacyICloudFileController(presentation: .modal(animateIn: true), theme: theme, completion: { urls in
|
let legacyController = LegacyICloudFileController(presentation: .modal(animateIn: true), theme: theme, completion: { urls in
|
||||||
dismissImpl?()
|
dismissImpl?()
|
||||||
@ -96,6 +96,7 @@ public func legacyICloudFilePicker(theme: PresentationTheme, mode: LegacyICloudF
|
|||||||
if let legacyController = legacyController {
|
if let legacyController = legacyController {
|
||||||
legacyController.dismiss()
|
legacyController.dismiss()
|
||||||
}
|
}
|
||||||
|
dismissed()
|
||||||
}
|
}
|
||||||
legacyController.bind(controller: UIViewController())
|
legacyController.bind(controller: UIViewController())
|
||||||
return legacyController
|
return legacyController
|
||||||
|
@ -412,6 +412,7 @@ private final class LocationPickerContext: AttachmentMediaPickerContext {
|
|||||||
public func storyLocationPickerController(
|
public func storyLocationPickerController(
|
||||||
context: AccountContext,
|
context: AccountContext,
|
||||||
location: CLLocationCoordinate2D?,
|
location: CLLocationCoordinate2D?,
|
||||||
|
dismissed: @escaping () -> Void,
|
||||||
completion: @escaping (TelegramMediaMap, Int64?, String?, String?, String?) -> Void
|
completion: @escaping (TelegramMediaMap, Int64?, String?, String?, String?) -> Void
|
||||||
) -> ViewController {
|
) -> ViewController {
|
||||||
let presentationData = context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: defaultDarkColorPresentationTheme)
|
let presentationData = context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: defaultDarkColorPresentationTheme)
|
||||||
@ -427,5 +428,8 @@ public func storyLocationPickerController(
|
|||||||
}
|
}
|
||||||
controller.navigationPresentation = .flatModal
|
controller.navigationPresentation = .flatModal
|
||||||
controller.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait)
|
controller.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait)
|
||||||
|
controller.didDismiss = {
|
||||||
|
dismissed()
|
||||||
|
}
|
||||||
return controller
|
return controller
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
|
||||||
|
|
||||||
|
swift_library(
|
||||||
|
name = "ContextReferenceButtonComponent",
|
||||||
|
module_name = "ContextReferenceButtonComponent",
|
||||||
|
srcs = glob([
|
||||||
|
"Sources/**/*.swift",
|
||||||
|
]),
|
||||||
|
copts = [
|
||||||
|
"-warnings-as-errors",
|
||||||
|
],
|
||||||
|
deps = [
|
||||||
|
"//submodules/Display",
|
||||||
|
"//submodules/ComponentFlow",
|
||||||
|
"//submodules/ContextUI",
|
||||||
|
],
|
||||||
|
visibility = [
|
||||||
|
"//visibility:public",
|
||||||
|
],
|
||||||
|
)
|
@ -0,0 +1,123 @@
|
|||||||
|
import Foundation
|
||||||
|
import UIKit
|
||||||
|
import Display
|
||||||
|
import ComponentFlow
|
||||||
|
|
||||||
|
public final class ContextReferenceButtonComponent: Component {
|
||||||
|
let content: AnyComponent<Empty>
|
||||||
|
let tag: AnyObject?
|
||||||
|
let minSize: CGSize?
|
||||||
|
let action: (UIView, ContextGesture?) -> Void
|
||||||
|
|
||||||
|
public init(
|
||||||
|
content: AnyComponent<Empty>,
|
||||||
|
tag: AnyObject? = nil,
|
||||||
|
minSize: CGSize?,
|
||||||
|
action: @escaping (UIView, ContextGesture?) -> Void
|
||||||
|
) {
|
||||||
|
self.content = content
|
||||||
|
self.tag = tag
|
||||||
|
self.minSize = minSize
|
||||||
|
self.action = action
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func ==(lhs: ContextReferenceButtonComponent, rhs: ContextReferenceButtonComponent) -> Bool {
|
||||||
|
if lhs.content != rhs.content {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.tag !== rhs.tag {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.minSize != rhs.minSize {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class View: UIView, ComponentTaggedView {
|
||||||
|
let buttonView: HighlightableButtonNode
|
||||||
|
let sourceView: ContextControllerSourceNode
|
||||||
|
let contextContentView: ContextReferenceContentNode
|
||||||
|
|
||||||
|
private let componentView: ComponentView<Empty>
|
||||||
|
|
||||||
|
private var component: ContextReferenceButtonComponent?
|
||||||
|
|
||||||
|
public func matches(tag: Any) -> Bool {
|
||||||
|
if let component = self.component, let componentTag = component.tag {
|
||||||
|
let tag = tag as AnyObject
|
||||||
|
if componentTag === tag {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
public init() {
|
||||||
|
self.componentView = ComponentView()
|
||||||
|
self.buttonView = HighlightableButtonNode()
|
||||||
|
self.sourceView = ContextControllerSourceNode()
|
||||||
|
self.contextContentView = ContextReferenceContentNode()
|
||||||
|
|
||||||
|
super.init(frame: CGRect())
|
||||||
|
|
||||||
|
self.addSubview(self.buttonView.view)
|
||||||
|
self.buttonView.addSubnode(self.sourceView)
|
||||||
|
self.sourceView.addSubnode(self.contextContentView)
|
||||||
|
|
||||||
|
self.sourceView.activated = { [weak self] gesture, _ in
|
||||||
|
if let self, let component = self.component {
|
||||||
|
component.action(self, gesture)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.buttonView.addTarget(self, action: #selector(self.pressed), forControlEvents: .touchUpInside)
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder aDecoder: NSCoder) {
|
||||||
|
preconditionFailure()
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func pressed() {
|
||||||
|
self.component?.action(self, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func update(component: ContextReferenceButtonComponent, availableSize: CGSize, transition: Transition) -> CGSize {
|
||||||
|
self.component = component
|
||||||
|
|
||||||
|
let componentSize = self.componentView.update(
|
||||||
|
transition: transition,
|
||||||
|
component: component.content,
|
||||||
|
environment: {},
|
||||||
|
containerSize: availableSize
|
||||||
|
)
|
||||||
|
|
||||||
|
var size = componentSize
|
||||||
|
if let minSize = component.minSize {
|
||||||
|
size.width = max(size.width, minSize.width)
|
||||||
|
size.height = max(size.height, minSize.height)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let componentView = self.componentView.view {
|
||||||
|
componentView.isUserInteractionEnabled = false
|
||||||
|
if componentView.superview == nil {
|
||||||
|
self.contextContentView.view.addSubview(componentView)
|
||||||
|
}
|
||||||
|
transition.setFrame(view: componentView, frame: CGRect(origin: CGPoint(x: floor((size.width - componentSize.width) / 2.0), y: floor((size.height - componentSize.height) / 2.0)), size: componentSize))
|
||||||
|
}
|
||||||
|
|
||||||
|
transition.setFrame(view: self.buttonView.view, frame: CGRect(origin: .zero, size: size))
|
||||||
|
transition.setFrame(view: self.sourceView.view, frame: CGRect(origin: .zero, size: size))
|
||||||
|
transition.setFrame(view: self.contextContentView.view, frame: CGRect(origin: .zero, size: size))
|
||||||
|
|
||||||
|
return size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func makeView() -> View {
|
||||||
|
return View()
|
||||||
|
}
|
||||||
|
|
||||||
|
public func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: Transition) -> CGSize {
|
||||||
|
return view.update(component: self, availableSize: availableSize, transition: transition)
|
||||||
|
}
|
||||||
|
}
|
@ -181,9 +181,9 @@ public class LegacyMessageInputPanelNode: ASDisplayNode, TGCaptionPanelView {
|
|||||||
likeAction: nil,
|
likeAction: nil,
|
||||||
likeOptionsAction: nil,
|
likeOptionsAction: nil,
|
||||||
inputModeAction: nil,
|
inputModeAction: nil,
|
||||||
timeoutAction: self.chatLocation.peerId?.namespace == Namespaces.Peer.CloudUser ? { [weak self] sourceView in
|
timeoutAction: self.chatLocation.peerId?.namespace == Namespaces.Peer.CloudUser ? { [weak self] sourceView, gesture in
|
||||||
if let self {
|
if let self {
|
||||||
self.presentTimeoutSetup(sourceView: sourceView)
|
self.presentTimeoutSetup(sourceView: sourceView, gesture: gesture)
|
||||||
}
|
}
|
||||||
} : nil,
|
} : nil,
|
||||||
forwardAction: nil,
|
forwardAction: nil,
|
||||||
@ -235,7 +235,7 @@ public class LegacyMessageInputPanelNode: ASDisplayNode, TGCaptionPanelView {
|
|||||||
return inputPanelSize.height - 8.0
|
return inputPanelSize.height - 8.0
|
||||||
}
|
}
|
||||||
|
|
||||||
private func presentTimeoutSetup(sourceView: UIView) {
|
private func presentTimeoutSetup(sourceView: UIView, gesture: ContextGesture?) {
|
||||||
self.hapticFeedback.impact(.light)
|
self.hapticFeedback.impact(.light)
|
||||||
|
|
||||||
var items: [ContextMenuItem] = []
|
var items: [ContextMenuItem] = []
|
||||||
@ -284,7 +284,7 @@ public class LegacyMessageInputPanelNode: ASDisplayNode, TGCaptionPanelView {
|
|||||||
updateTimeout(nil)
|
updateTimeout(nil)
|
||||||
})))
|
})))
|
||||||
|
|
||||||
let contextController = ContextController(presentationData: presentationData, source: .reference(HeaderContextReferenceContentSource(sourceView: sourceView)), items: .single(ContextController.Items(content: .list(items))), gesture: nil)
|
let contextController = ContextController(presentationData: presentationData, source: .reference(HeaderContextReferenceContentSource(sourceView: sourceView)), items: .single(ContextController.Items(content: .list(items))), gesture: gesture)
|
||||||
self.present(contextController)
|
self.present(contextController)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1117,7 +1117,7 @@ final class MediaEditorScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
timeoutAction: isEditingStory ? nil : { [weak self] view in
|
timeoutAction: isEditingStory ? nil : { [weak self] view, gesture in
|
||||||
guard let self, let controller = self.environment?.controller() as? MediaEditorScreen else {
|
guard let self, let controller = self.environment?.controller() as? MediaEditorScreen else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -1130,7 +1130,7 @@ final class MediaEditorScreenComponent: Component {
|
|||||||
} else {
|
} else {
|
||||||
hasPremium = false
|
hasPremium = false
|
||||||
}
|
}
|
||||||
controller?.presentTimeoutSetup(sourceView: view, hasPremium: hasPremium)
|
controller?.presentTimeoutSetup(sourceView: view, gesture: gesture, hasPremium: hasPremium)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
forwardAction: nil,
|
forwardAction: nil,
|
||||||
@ -2972,7 +2972,15 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
location = draft.location
|
location = draft.location
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let locationController = storyLocationPickerController(context: self.context, location: location, completion: { [weak self] location, queryId, resultId, address, countryCode in
|
let locationController = storyLocationPickerController(
|
||||||
|
context: self.context,
|
||||||
|
location: location,
|
||||||
|
dismissed: { [weak self] in
|
||||||
|
if let self {
|
||||||
|
self.mediaEditor?.play()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
completion: { [weak self] location, queryId, resultId, address, countryCode in
|
||||||
if let self {
|
if let self {
|
||||||
let emojiFile: Signal<TelegramMediaFile?, NoError>
|
let emojiFile: Signal<TelegramMediaFile?, NoError>
|
||||||
if let countryCode {
|
if let countryCode {
|
||||||
@ -3050,7 +3058,13 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
}
|
}
|
||||||
|
|
||||||
func presentAudioPicker() {
|
func presentAudioPicker() {
|
||||||
self.controller?.present(legacyICloudFilePicker(theme: self.presentationData.theme, mode: .import, documentTypes: ["public.mp3"], forceDarkTheme: true, completion: { [weak self] urls in
|
self.controller?.present(legacyICloudFilePicker(theme: self.presentationData.theme, mode: .import, documentTypes: ["public.mp3"], forceDarkTheme: true, dismissed: { [weak self] in
|
||||||
|
if let self {
|
||||||
|
Queue.mainQueue().after(0.1) {
|
||||||
|
self.mediaEditor?.play()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, completion: { [weak self] urls in
|
||||||
guard let self, let mediaEditor = self.mediaEditor, !urls.isEmpty, let url = urls.first else {
|
guard let self, let mediaEditor = self.mediaEditor, !urls.isEmpty, let url = urls.first else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -3075,10 +3089,6 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.requestUpdate(transition: .easeInOut(duration: 0.2))
|
self.requestUpdate(transition: .easeInOut(duration: 0.2))
|
||||||
|
|
||||||
Queue.mainQueue().after(0.1) {
|
|
||||||
self.mediaEditor?.play()
|
|
||||||
}
|
|
||||||
}), in: .window(.root))
|
}), in: .window(.root))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3096,7 +3106,13 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
action: { [weak self] f in
|
action: { [weak self] f in
|
||||||
f.dismissWithResult(.default)
|
f.dismissWithResult(.default)
|
||||||
if let self {
|
if let self {
|
||||||
self.mediaEditor?.setAudioTrack(nil)
|
if let mediaEditor = self.mediaEditor {
|
||||||
|
mediaEditor.setAudioTrack(nil)
|
||||||
|
|
||||||
|
if !mediaEditor.sourceIsVideo && !mediaEditor.isPlaying {
|
||||||
|
mediaEditor.play()
|
||||||
|
}
|
||||||
|
}
|
||||||
self.requestUpdate(transition: .easeInOut(duration: 0.25))
|
self.requestUpdate(transition: .easeInOut(duration: 0.25))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3887,7 +3903,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func presentTimeoutSetup(sourceView: UIView, hasPremium: Bool) {
|
func presentTimeoutSetup(sourceView: UIView, gesture: ContextGesture?, hasPremium: Bool) {
|
||||||
self.hapticFeedback.impact(.light)
|
self.hapticFeedback.impact(.light)
|
||||||
|
|
||||||
var items: [ContextMenuItem] = []
|
var items: [ContextMenuItem] = []
|
||||||
@ -3908,7 +3924,6 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
let presentationData = self.context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: defaultDarkPresentationTheme)
|
let presentationData = self.context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: defaultDarkPresentationTheme)
|
||||||
let title = presentationData.strings.Story_Editor_ExpirationText
|
let title = presentationData.strings.Story_Editor_ExpirationText
|
||||||
let currentValue = self.state.privacy.timeout
|
let currentValue = self.state.privacy.timeout
|
||||||
let currentArchived = self.state.privacy.pin
|
|
||||||
let emptyAction: ((ContextMenuActionItem.Action) -> Void)? = nil
|
let emptyAction: ((ContextMenuActionItem.Action) -> Void)? = nil
|
||||||
|
|
||||||
items.append(.action(ContextMenuActionItem(text: title, textLayout: .multiline, textFont: .small, icon: { _ in return nil }, action: emptyAction)))
|
items.append(.action(ContextMenuActionItem(text: title, textLayout: .multiline, textFont: .small, icon: { _ in return nil }, action: emptyAction)))
|
||||||
@ -3944,7 +3959,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
}
|
}
|
||||||
})))
|
})))
|
||||||
items.append(.action(ContextMenuActionItem(text: presentationData.strings.Story_Editor_ExpirationValue(24), icon: { theme in
|
items.append(.action(ContextMenuActionItem(text: presentationData.strings.Story_Editor_ExpirationValue(24), icon: { theme in
|
||||||
return currentValue == 86400 && !currentArchived ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil
|
return currentValue == 86400 ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil
|
||||||
}, action: { _, a in
|
}, action: { _, a in
|
||||||
a(.default)
|
a(.default)
|
||||||
|
|
||||||
@ -3966,7 +3981,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
}
|
}
|
||||||
})))
|
})))
|
||||||
|
|
||||||
let contextController = ContextController(presentationData: presentationData, source: .reference(HeaderContextReferenceContentSource(controller: self, sourceView: sourceView)), items: .single(ContextController.Items(content: .list(items))), gesture: nil)
|
let contextController = ContextController(presentationData: presentationData, source: .reference(HeaderContextReferenceContentSource(controller: self, sourceView: sourceView)), items: .single(ContextController.Items(content: .list(items))), gesture: gesture)
|
||||||
self.present(contextController, in: .window(.root))
|
self.present(contextController, in: .window(.root))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,6 +37,8 @@ swift_library(
|
|||||||
"//submodules/AnimatedCountLabelNode",
|
"//submodules/AnimatedCountLabelNode",
|
||||||
"//submodules/TelegramUI/Components/MessageInputActionButtonComponent",
|
"//submodules/TelegramUI/Components/MessageInputActionButtonComponent",
|
||||||
"//submodules/SearchPeerMembers",
|
"//submodules/SearchPeerMembers",
|
||||||
|
"//submodules/ContextUI",
|
||||||
|
"//submodules/TelegramUI/Components/ContextReferenceButtonComponent",
|
||||||
],
|
],
|
||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
|
@ -18,6 +18,9 @@ import AudioToolbox
|
|||||||
import AnimatedTextComponent
|
import AnimatedTextComponent
|
||||||
import AnimatedCountLabelNode
|
import AnimatedCountLabelNode
|
||||||
import MessageInputActionButtonComponent
|
import MessageInputActionButtonComponent
|
||||||
|
import ContextReferenceButtonComponent
|
||||||
|
|
||||||
|
private let timeoutButtonTag = GenericComponentViewTag()
|
||||||
|
|
||||||
public final class MessageInputPanelComponent: Component {
|
public final class MessageInputPanelComponent: Component {
|
||||||
public struct ContextQueryTypes: OptionSet {
|
public struct ContextQueryTypes: OptionSet {
|
||||||
@ -120,7 +123,7 @@ public final class MessageInputPanelComponent: Component {
|
|||||||
public let likeAction: (() -> Void)?
|
public let likeAction: (() -> Void)?
|
||||||
public let likeOptionsAction: ((UIView, ContextGesture?) -> Void)?
|
public let likeOptionsAction: ((UIView, ContextGesture?) -> Void)?
|
||||||
public let inputModeAction: (() -> Void)?
|
public let inputModeAction: (() -> Void)?
|
||||||
public let timeoutAction: ((UIView) -> Void)?
|
public let timeoutAction: ((UIView, ContextGesture?) -> Void)?
|
||||||
public let forwardAction: (() -> Void)?
|
public let forwardAction: (() -> Void)?
|
||||||
public let moreAction: ((UIView, ContextGesture?) -> Void)?
|
public let moreAction: ((UIView, ContextGesture?) -> Void)?
|
||||||
public let presentVoiceMessagesUnavailableTooltip: ((UIView) -> Void)?
|
public let presentVoiceMessagesUnavailableTooltip: ((UIView) -> Void)?
|
||||||
@ -172,7 +175,7 @@ public final class MessageInputPanelComponent: Component {
|
|||||||
likeAction: (() -> Void)?,
|
likeAction: (() -> Void)?,
|
||||||
likeOptionsAction: ((UIView, ContextGesture?) -> Void)?,
|
likeOptionsAction: ((UIView, ContextGesture?) -> Void)?,
|
||||||
inputModeAction: (() -> Void)?,
|
inputModeAction: (() -> Void)?,
|
||||||
timeoutAction: ((UIView) -> Void)?,
|
timeoutAction: ((UIView, ContextGesture?) -> Void)?,
|
||||||
forwardAction: (() -> Void)?,
|
forwardAction: (() -> Void)?,
|
||||||
moreAction: ((UIView, ContextGesture?) -> Void)?,
|
moreAction: ((UIView, ContextGesture?) -> Void)?,
|
||||||
presentVoiceMessagesUnavailableTooltip: ((UIView) -> Void)?,
|
presentVoiceMessagesUnavailableTooltip: ((UIView) -> Void)?,
|
||||||
@ -1458,7 +1461,7 @@ public final class MessageInputPanelComponent: Component {
|
|||||||
if let timeoutAction = component.timeoutAction, let timeoutValue = component.timeoutValue {
|
if let timeoutAction = component.timeoutAction, let timeoutValue = component.timeoutValue {
|
||||||
let timeoutButtonSize = self.timeoutButton.update(
|
let timeoutButtonSize = self.timeoutButton.update(
|
||||||
transition: transition,
|
transition: transition,
|
||||||
component: AnyComponent(Button(
|
component: AnyComponent(ContextReferenceButtonComponent(
|
||||||
content: AnyComponent(
|
content: AnyComponent(
|
||||||
TimeoutContentComponent(
|
TimeoutContentComponent(
|
||||||
color: .white,
|
color: .white,
|
||||||
@ -1467,13 +1470,12 @@ public final class MessageInputPanelComponent: Component {
|
|||||||
value: timeoutValue
|
value: timeoutValue
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
action: { [weak self] in
|
tag: timeoutButtonTag,
|
||||||
guard let self, let timeoutButtonView = self.timeoutButton.view else {
|
minSize: CGSize(width: 32.0, height: 32.0),
|
||||||
return
|
action: { view, gesture in
|
||||||
|
timeoutAction(view, gesture)
|
||||||
}
|
}
|
||||||
timeoutAction(timeoutButtonView)
|
)),
|
||||||
}
|
|
||||||
).minSize(CGSize(width: 32.0, height: 32.0))),
|
|
||||||
environment: {},
|
environment: {},
|
||||||
containerSize: CGSize(width: 32.0, height: 32.0)
|
containerSize: CGSize(width: 32.0, height: 32.0)
|
||||||
)
|
)
|
||||||
|
@ -78,13 +78,13 @@ public final class TimeoutContentComponent: Component {
|
|||||||
if let textView = self.text.view, let snapshotView = textView.snapshotView(afterScreenUpdates: false) {
|
if let textView = self.text.view, let snapshotView = textView.snapshotView(afterScreenUpdates: false) {
|
||||||
snapshotView.frame = textView.frame
|
snapshotView.frame = textView.frame
|
||||||
self.addSubview(snapshotView)
|
self.addSubview(snapshotView)
|
||||||
snapshotView.layer.animatePosition(from: .zero, to: CGPoint(x: 0.0, y: 3.0), duration: 0.2, removeOnCompletion: false, additive: true)
|
snapshotView.layer.animatePosition(from: .zero, to: CGPoint(x: 0.0, y: -3.0), duration: 0.2, removeOnCompletion: false, additive: true)
|
||||||
snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { _ in
|
snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { _ in
|
||||||
snapshotView.removeFromSuperview()
|
snapshotView.removeFromSuperview()
|
||||||
})
|
})
|
||||||
|
|
||||||
textView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
textView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||||
textView.layer.animatePosition(from: CGPoint(x: 0.0, y: -3.0), to: .zero, duration: 0.2, additive: true)
|
textView.layer.animatePosition(from: CGPoint(x: 0.0, y: 3.0), to: .zero, duration: 0.2, additive: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -503,6 +503,8 @@ final class ShareWithPeersScreenComponent: Component {
|
|||||||
let translation = recognizer.translation(in: self)
|
let translation = recognizer.translation(in: self)
|
||||||
self.dismissPanState = DismissPanState(translation: translation.y)
|
self.dismissPanState = DismissPanState(translation: translation.y)
|
||||||
self.state?.updated(transition: .immediate)
|
self.state?.updated(transition: .immediate)
|
||||||
|
|
||||||
|
self.updateModalOverlayTransition(transition: .immediate)
|
||||||
case .cancelled, .ended:
|
case .cancelled, .ended:
|
||||||
if self.dismissPanState != nil {
|
if self.dismissPanState != nil {
|
||||||
let translation = recognizer.translation(in: self)
|
let translation = recognizer.translation(in: self)
|
||||||
@ -512,8 +514,13 @@ final class ShareWithPeersScreenComponent: Component {
|
|||||||
|
|
||||||
if translation.y > 100.0 || velocity.y > 10.0 {
|
if translation.y > 100.0 || velocity.y > 10.0 {
|
||||||
controller.requestDismiss()
|
controller.requestDismiss()
|
||||||
|
Queue.mainQueue().justDispatch {
|
||||||
|
controller.updateModalStyleOverlayTransitionFactor(0.0, transition: .animated(duration: 0.3, curve: .spring))
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
self.state?.updated(transition: Transition(animation: .curve(duration: 0.3, curve: .spring)))
|
let transition = Transition(animation: .curve(duration: 0.3, curve: .spring))
|
||||||
|
self.state?.updated(transition: transition)
|
||||||
|
self.updateModalOverlayTransition(transition: transition)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -782,7 +789,7 @@ final class ShareWithPeersScreenComponent: Component {
|
|||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let controller = ShareWithPeersScreen(
|
let peersController = ShareWithPeersScreen(
|
||||||
context: component.context,
|
context: component.context,
|
||||||
initialPrivacy: EngineStoryPrivacy(base: .nobody, additionallyIncludePeers: []),
|
initialPrivacy: EngineStoryPrivacy(base: .nobody, additionallyIncludePeers: []),
|
||||||
stateContext: stateContext,
|
stateContext: stateContext,
|
||||||
@ -797,10 +804,40 @@ final class ShareWithPeersScreenComponent: Component {
|
|||||||
self.state?.updated(transition: .spring(duration: 0.4))
|
self.state?.updated(transition: .spring(duration: 0.4))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
self.environment?.controller()?.push(controller)
|
if let controller = self.environment?.controller() as? ShareWithPeersScreen {
|
||||||
|
controller.dismissAllTooltips()
|
||||||
|
controller.push(peersController)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func updateModalOverlayTransition(transition: Transition) {
|
||||||
|
guard let _ = self.component, let environment = self.environment, let itemLayout = self.itemLayout else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var topOffset = -self.scrollView.bounds.minY + itemLayout.topInset
|
||||||
|
topOffset = max(0.0, topOffset)
|
||||||
|
if let dismissPanState = self.dismissPanState {
|
||||||
|
topOffset += dismissPanState.translation
|
||||||
|
}
|
||||||
|
|
||||||
|
let topOffsetDistance: CGFloat = min(200.0, floor(itemLayout.containerSize.height * 0.25))
|
||||||
|
var topOffsetFraction = topOffset / topOffsetDistance
|
||||||
|
topOffsetFraction = max(0.0, min(1.0, topOffsetFraction))
|
||||||
|
|
||||||
|
let transitionFactor: CGFloat = 1.0 - topOffsetFraction
|
||||||
|
if let controller = environment.controller() {
|
||||||
|
Queue.mainQueue().justDispatch {
|
||||||
|
var transition = transition
|
||||||
|
if controller.modalStyleOverlayTransitionFactor.isZero && transitionFactor > 0.0, transition.animation.isImmediate {
|
||||||
|
transition = .spring(duration: 0.4)
|
||||||
|
}
|
||||||
|
controller.updateModalStyleOverlayTransitionFactor(transitionFactor, transition: transition.containedViewLayoutTransition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private func updateScrolling(transition: Transition) {
|
private func updateScrolling(transition: Transition) {
|
||||||
guard let component = self.component, let environment = self.environment, let itemLayout = self.itemLayout else {
|
guard let component = self.component, let environment = self.environment, let itemLayout = self.itemLayout else {
|
||||||
return
|
return
|
||||||
@ -819,21 +856,7 @@ final class ShareWithPeersScreenComponent: Component {
|
|||||||
var bottomAlpha: CGFloat = bottomDistance / bottomAlphaDistance
|
var bottomAlpha: CGFloat = bottomDistance / bottomAlphaDistance
|
||||||
bottomAlpha = max(0.0, min(1.0, bottomAlpha))
|
bottomAlpha = max(0.0, min(1.0, bottomAlpha))
|
||||||
|
|
||||||
let topOffsetDistance: CGFloat = min(200.0, floor(itemLayout.containerSize.height * 0.25))
|
self.updateModalOverlayTransition(transition: transition)
|
||||||
self.topOffsetDistance = topOffsetDistance
|
|
||||||
var topOffsetFraction = topOffset / topOffsetDistance
|
|
||||||
topOffsetFraction = max(0.0, min(1.0, topOffsetFraction))
|
|
||||||
|
|
||||||
let transitionFactor: CGFloat = 1.0 - topOffsetFraction
|
|
||||||
if let controller = environment.controller() {
|
|
||||||
Queue.mainQueue().justDispatch {
|
|
||||||
var transition = transition
|
|
||||||
if controller.modalStyleOverlayTransitionFactor.isZero && transitionFactor > 0.0, transition.animation.isImmediate {
|
|
||||||
transition = .spring(duration: 0.4)
|
|
||||||
}
|
|
||||||
controller.updateModalStyleOverlayTransitionFactor(transitionFactor, transition: transition.containedViewLayoutTransition)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var visibleBounds = self.scrollView.bounds
|
var visibleBounds = self.scrollView.bounds
|
||||||
visibleBounds.origin.y -= itemLayout.topInset
|
visibleBounds.origin.y -= itemLayout.topInset
|
||||||
@ -1043,7 +1066,7 @@ final class ShareWithPeersScreenComponent: Component {
|
|||||||
if isStories {
|
if isStories {
|
||||||
let _ = self.presentSendAsPeer()
|
let _ = self.presentSendAsPeer()
|
||||||
} else {
|
} else {
|
||||||
self.hapticFeedback.tap()
|
self.hapticFeedback.impact(.light)
|
||||||
self.environment?.controller()?.dismiss()
|
self.environment?.controller()?.dismiss()
|
||||||
self.component?.peerCompletion(peer.id)
|
self.component?.peerCompletion(peer.id)
|
||||||
}
|
}
|
||||||
|
@ -2045,7 +2045,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio
|
|||||||
|
|
||||||
if isSecretMedia {
|
if isSecretMedia {
|
||||||
let remainingTime: Int32?
|
let remainingTime: Int32?
|
||||||
if let (maybeBeginTime, timeout) = secretBeginTimeAndTimeout {
|
if let (maybeBeginTime, timeout) = secretBeginTimeAndTimeout, Int32(timeout) != viewOnceTimeout {
|
||||||
if let beginTime = maybeBeginTime {
|
if let beginTime = maybeBeginTime {
|
||||||
let elapsedTime = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970 - beginTime
|
let elapsedTime = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970 - beginTime
|
||||||
remainingTime = Int32(max(0.0, timeout - elapsedTime))
|
remainingTime = Int32(max(0.0, timeout - elapsedTime))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user