mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-09 03:20:48 +00:00
Various Improvements
This commit is contained in:
parent
64b80e92b4
commit
666b076867
@ -6257,7 +6257,8 @@ Sorry for the inconvenience.";
|
||||
|
||||
"VoiceChat.MutedByAdmin" = "Muted by Admin";
|
||||
"VoiceChat.MutedByAdminHelp" = "Tap if you want to speak";
|
||||
"Invitation.JoinVoiceChat" = "Join Voice Chat";
|
||||
"Invitation.JoinVoiceChatAsSpeaker" = "Join as Speaker";
|
||||
"Invitation.JoinVoiceChatAsListener" = "Join as Listener";
|
||||
|
||||
"VoiceChat.CancelSpeakRequest" = "Cancel Request to Speak";
|
||||
|
||||
@ -6281,3 +6282,8 @@ Sorry for the inconvenience.";
|
||||
"Conversation.StickerRemovedFromFavorites" = "Sticker was removed from Favorites";
|
||||
|
||||
"Conversation.DeletedFromContacts" = "**%@** deleted from your contacts";
|
||||
|
||||
"Conversation.VoiceChat" = "Voice Chat";
|
||||
|
||||
"Conversation.JoinVoiceChatAsSpeaker" = "JOIN AS SPEAKER";
|
||||
"Conversation.JoinVoiceChatAsListener" = "JOIN AS LISTENER";
|
||||
|
@ -136,6 +136,8 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus
|
||||
|
||||
bool _shutterIsBusy;
|
||||
|
||||
UIImpactFeedbackGenerator *_feedbackGenerator;
|
||||
|
||||
NSMutableSet *_previousQRCodes;
|
||||
}
|
||||
@end
|
||||
@ -172,6 +174,10 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus
|
||||
_saveCapturedMedia = saveCapturedMedia;
|
||||
|
||||
_previousQRCodes = [[NSMutableSet alloc] init];
|
||||
|
||||
if (iosMajorVersion() >= 10) {
|
||||
_feedbackGenerator = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleLight];
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@ -905,6 +911,12 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus
|
||||
|
||||
- (void)shutterPressed
|
||||
{
|
||||
if (iosMajorVersion() >= 13.0) {
|
||||
[_feedbackGenerator impactOccurredWithIntensity:0.5];
|
||||
} else {
|
||||
[_feedbackGenerator impactOccurred];
|
||||
}
|
||||
|
||||
PGCameraMode cameraMode = _camera.cameraMode;
|
||||
switch (cameraMode)
|
||||
{
|
||||
@ -939,6 +951,12 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus
|
||||
|
||||
- (void)shutterReleased
|
||||
{
|
||||
if (iosMajorVersion() >= 13.0) {
|
||||
[_feedbackGenerator impactOccurredWithIntensity:0.6];
|
||||
} else {
|
||||
[_feedbackGenerator impactOccurred];
|
||||
}
|
||||
|
||||
[_switchToVideoTimer invalidate];
|
||||
_switchToVideoTimer = nil;
|
||||
|
||||
|
@ -60,7 +60,8 @@ public func paragraphStyleWithAlignment(_ alignment: NSTextAlignment) -> NSParag
|
||||
public func parseMarkdownIntoAttributedString(_ string: String, attributes: MarkdownAttributes, textAlignment: NSTextAlignment = .natural) -> NSAttributedString {
|
||||
let nsString = string as NSString
|
||||
let result = NSMutableAttributedString()
|
||||
var remainingRange = NSMakeRange(0, nsString.length)
|
||||
let wholeRange = NSMakeRange(0, nsString.length)
|
||||
var remainingRange = wholeRange
|
||||
|
||||
var bodyAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.font: attributes.body.font, NSAttributedString.Key.foregroundColor: attributes.body.textColor, NSAttributedString.Key.paragraphStyle: paragraphStyleWithAlignment(textAlignment)]
|
||||
if !attributes.body.additionalAttributes.isEmpty {
|
||||
@ -93,7 +94,7 @@ public func parseMarkdownIntoAttributedString(_ string: String, attributes: Mark
|
||||
result.append(NSAttributedString(string: parsedLinkText, attributes: linkAttributes))
|
||||
}
|
||||
} else if character == UInt16(("*" as UnicodeScalar).value) {
|
||||
if range.location + 1 != remainingRange.length {
|
||||
if range.location + 1 != wholeRange.length {
|
||||
let nextCharacter = nsString.character(at: range.location + 1)
|
||||
if nextCharacter == character {
|
||||
remainingRange = NSMakeRange(range.location + range.length + 1, remainingRange.location + remainingRange.length - (range.location + range.length + 1))
|
||||
|
@ -773,9 +773,9 @@ public final class MediaPlayerScrubbingNode: ASDisplayNode {
|
||||
private var animating = false
|
||||
public func animateTo(_ timestamp: Double) {
|
||||
self.animateToValue = timestamp
|
||||
ContainedViewLayoutTransition.animated(duration: 0.2, curve: .easeInOut).animateView({
|
||||
UIView.animate(withDuration: 0.2, delay: 0.0, options: [.curveEaseInOut, .allowAnimatedContent, .layoutSubviews], animations: {
|
||||
self.updateProgress()
|
||||
}, completion: { finished in
|
||||
}, completion: { _ in
|
||||
self.animateToValue = nil
|
||||
self.animating = false
|
||||
})
|
||||
@ -804,11 +804,11 @@ public final class MediaPlayerScrubbingNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
if let animateToValue = animateToValue {
|
||||
if animating {
|
||||
if let animateToValue = self.animateToValue {
|
||||
if self.animating {
|
||||
return
|
||||
} else if let (_, duration) = timestampAndDuration {
|
||||
animating = true
|
||||
self.animating = true
|
||||
timestampAndDuration = (animateToValue, duration)
|
||||
}
|
||||
}
|
||||
@ -823,6 +823,7 @@ public final class MediaPlayerScrubbingNode: ASDisplayNode {
|
||||
node.foregroundContentNode.position = foregroundContentFrame.center
|
||||
node.foregroundContentNode.bounds = CGRect(origin: CGPoint(), size: foregroundContentFrame.size)
|
||||
|
||||
|
||||
node.bufferingNode.frame = backgroundFrame
|
||||
node.bufferingNode.updateLayout(size: backgroundFrame.size, transition: .immediate)
|
||||
|
||||
@ -872,19 +873,28 @@ public final class MediaPlayerScrubbingNode: ASDisplayNode {
|
||||
handleNodeContainer.isHidden = false
|
||||
}
|
||||
} else if let statusValue = self.statusValue {
|
||||
let actualTimestamp: Double
|
||||
if statusValue.generationTimestamp.isZero || !isPlaying {
|
||||
var actualTimestamp: Double
|
||||
if statusValue.generationTimestamp.isZero || !isPlaying || self.animateToValue != nil {
|
||||
actualTimestamp = timestamp
|
||||
} else {
|
||||
let currentTimestamp = CACurrentMediaTime()
|
||||
actualTimestamp = timestamp + (currentTimestamp - statusValue.generationTimestamp) * statusValue.baseRate
|
||||
}
|
||||
|
||||
var progress = CGFloat(actualTimestamp / duration)
|
||||
if progress.isNaN || !progress.isFinite {
|
||||
progress = 0.0
|
||||
}
|
||||
progress = min(1.0, progress)
|
||||
node.foregroundNode.frame = CGRect(origin: backgroundFrame.origin, size: CGSize(width: floorToScreenPixels(progress * backgroundFrame.size.width), height: backgroundFrame.size.height))
|
||||
|
||||
let foregroundFrame = CGRect(origin: backgroundFrame.origin, size: CGSize(width: floorToScreenPixels(progress * backgroundFrame.size.width), height: backgroundFrame.size.height))
|
||||
if let _ = self.animateToValue {
|
||||
let previousFrame = node.foregroundNode.frame
|
||||
node.foregroundNode.frame = foregroundFrame
|
||||
node.foregroundNode.layer.animateFrame(from: previousFrame, to: foregroundFrame, duration: 0.2, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue)
|
||||
} else {
|
||||
node.foregroundNode.frame = foregroundFrame
|
||||
}
|
||||
|
||||
if let handleNodeContainer = node.handleNodeContainer {
|
||||
handleNodeContainer.bounds = bounds.offsetBy(dx: -floorToScreenPixels(bounds.size.width * progress), dy: 0.0)
|
||||
|
@ -594,6 +594,13 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate
|
||||
self.animateOut(shared: true, completion: {
|
||||
})
|
||||
self.completed?(peerIds)
|
||||
|
||||
Queue.mainQueue().after(0.15) {
|
||||
if self.hapticFeedback == nil {
|
||||
self.hapticFeedback = HapticFeedback()
|
||||
}
|
||||
self.hapticFeedback?.success()
|
||||
}
|
||||
}
|
||||
let fromForeignApp = self.fromForeignApp
|
||||
self.shareDisposable.set((signal
|
||||
|
@ -260,10 +260,13 @@ public final class GroupCallNavigationAccessoryPanel: ASDisplayNode {
|
||||
self.joinButtonTitleNode.attributedText = NSAttributedString(string: presentationData.strings.VoiceChat_PanelJoin.uppercased(), font: Font.semibold(15.0), textColor: presentationData.theme.chat.inputPanel.actionControlForegroundColor)
|
||||
self.joinButtonBackgroundNode.image = generateStretchableFilledCircleImage(diameter: 28.0, color: presentationData.theme.chat.inputPanel.actionControlFillColor)
|
||||
|
||||
self.titleNode.attributedText = NSAttributedString(string: presentationData.strings.VoiceChat_Title, font: Font.semibold(15.0), textColor: presentationData.theme.chat.inputPanel.primaryTextColor)
|
||||
self.textNode.attributedText = NSAttributedString(string: self.textNode.attributedText?.string ?? "", font: Font.regular(13.0), textColor: presentationData.theme.chat.inputPanel.secondaryTextColor)
|
||||
|
||||
self.muteIconNode.image = PresentationResourcesChat.chatTitleMuteIcon(presentationData.theme)
|
||||
|
||||
if let (size, leftInset, rightInset) = self.validLayout {
|
||||
self.updateLayout(size: size, leftInset: leftInset, rightInset: rightInset, transition: .immediate)
|
||||
}
|
||||
}
|
||||
|
||||
private func animateTextChange() {
|
||||
@ -498,7 +501,14 @@ public final class GroupCallNavigationAccessoryPanel: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
let titleSize = self.titleNode.updateLayout(CGSize(width: size.width, height: .greatestFiniteMagnitude))
|
||||
var title = self.strings.VoiceChat_Title
|
||||
if let voiceChatTitle = self.currentData?.info.title, voiceChatTitle.count < 15 {
|
||||
title = voiceChatTitle
|
||||
}
|
||||
|
||||
self.titleNode.attributedText = NSAttributedString(string: title, font: Font.semibold(15.0), textColor: self.theme.chat.inputPanel.primaryTextColor)
|
||||
|
||||
let titleSize = self.titleNode.updateLayout(CGSize(width: size.width / 2.0 - 56.0, height: .greatestFiniteMagnitude))
|
||||
let textSize = self.textNode.updateLayout(CGSize(width: size.width, height: .greatestFiniteMagnitude))
|
||||
|
||||
let titleFrame = CGRect(origin: CGPoint(x: leftInset + 16.0, y: 9.0), size: titleSize)
|
||||
|
@ -118,7 +118,7 @@ public final class AccountGroupCallContextImpl: AccountGroupCallContext {
|
||||
}
|
||||
return GroupCallPanelData(
|
||||
peerId: peerId,
|
||||
info: GroupCallInfo(id: call.id, accessHash: call.accessHash, participantCount: state.totalCount, clientParams: nil, streamDcId: nil, title: nil, recordingStartTimestamp: nil),
|
||||
info: GroupCallInfo(id: call.id, accessHash: call.accessHash, participantCount: state.totalCount, clientParams: nil, streamDcId: nil, title: state.title, recordingStartTimestamp: nil),
|
||||
topParticipants: topParticipants,
|
||||
participantCount: state.totalCount,
|
||||
activeSpeakers: activeSpeakers,
|
||||
|
@ -2157,8 +2157,12 @@ public final class VoiceChatController: ViewController {
|
||||
self.hapticFeedback.impact(.light)
|
||||
case .ended, .cancelled:
|
||||
self.actionButton.pressing = false
|
||||
self.call.raiseHand()
|
||||
self.actionButton.playAnimation()
|
||||
|
||||
let location = gestureRecognizer.location(in: self.actionButton.view)
|
||||
if self.actionButton.hitTest(location, with: nil) != nil {
|
||||
self.call.raiseHand()
|
||||
self.actionButton.playAnimation()
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ public final class VoiceChatJoinScreen: ViewController {
|
||||
override public func loadDisplayNode() {
|
||||
self.displayNode = Node(context: self.context, requestLayout: { [weak self] transition in
|
||||
self?.requestLayout(transition: transition)
|
||||
})
|
||||
}, asSpeaker: self.invite != nil)
|
||||
self.controllerNode.dismiss = { [weak self] in
|
||||
self?.presentingViewController?.dismiss(animated: false, completion: nil)
|
||||
}
|
||||
@ -187,6 +187,7 @@ public final class VoiceChatJoinScreen: ViewController {
|
||||
class Node: ViewControllerTracingNode, UIScrollViewDelegate {
|
||||
private let context: AccountContext
|
||||
private var presentationData: PresentationData
|
||||
private let asSpeaker: Bool
|
||||
|
||||
private var call: CachedChannelData.ActiveCall?
|
||||
|
||||
@ -222,10 +223,10 @@ public final class VoiceChatJoinScreen: ViewController {
|
||||
|
||||
private let disposable = MetaDisposable()
|
||||
|
||||
init(context: AccountContext, requestLayout: @escaping (ContainedViewLayoutTransition) -> Void) {
|
||||
init(context: AccountContext, requestLayout: @escaping (ContainedViewLayoutTransition) -> Void, asSpeaker: Bool) {
|
||||
self.context = context
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
self.asSpeaker = asSpeaker
|
||||
self.requestLayout = requestLayout
|
||||
|
||||
let roundedBackground = generateStretchableFilledCircleImage(radius: 16.0, color: self.presentationData.theme.actionSheet.opaqueItemBackgroundColor)
|
||||
@ -633,7 +634,7 @@ public final class VoiceChatJoinScreen: ViewController {
|
||||
transition.updateAlpha(node: self.actionsBackgroundNode, alpha: 1.0)
|
||||
|
||||
self.actionButtonNode.isEnabled = true
|
||||
self.actionButtonNode.setTitle(self.presentationData.strings.Invitation_JoinVoiceChat, with: Font.medium(20.0), with: self.presentationData.theme.actionSheet.standardActionTextColor, for: .normal)
|
||||
self.actionButtonNode.setTitle(self.asSpeaker ? self.presentationData.strings.Invitation_JoinVoiceChatAsSpeaker : self.presentationData.strings.Invitation_JoinVoiceChatAsListener, with: Font.medium(20.0), with: self.presentationData.theme.actionSheet.standardActionTextColor, for: .normal)
|
||||
|
||||
self.transitionToContentNode(VoiceChatPreviewContentNode(context: self.context, peer: peer, title: title, memberCount: memberCount, theme: self.presentationData.theme, strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder))
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -10519,7 +10519,13 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
strongController.dismiss()
|
||||
} else if peerId == strongSelf.context.account.peerId {
|
||||
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
|
||||
strongSelf.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: true, text: messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_SavedMessages_One : presentationData.strings.Conversation_ForwardTooltip_SavedMessages_Many), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .current)
|
||||
strongSelf.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: true, text: messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_SavedMessages_One : presentationData.strings.Conversation_ForwardTooltip_SavedMessages_Many), elevatedLayout: false, animateInAsReplacement: true, action: { [weak self] value in
|
||||
if case .info = value, let strongSelf = self, let navigationController = strongSelf.effectiveNavigationController {
|
||||
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(context.account.peerId), keepStack: .always, purposefulAction: {}, peekData: nil))
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}), in: .current)
|
||||
|
||||
let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peerId, messages: messages.map { message -> EnqueueMessage in
|
||||
return .forward(source: message.id, grouping: .auto, attributes: [])
|
||||
|
@ -280,7 +280,12 @@ final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
case "telegram_message":
|
||||
actionTitle = item.presentationData.strings.Conversation_ViewMessage
|
||||
case "telegram_voicechat":
|
||||
actionTitle = item.presentationData.strings.Conversation_JoinVoiceChat
|
||||
title = item.presentationData.strings.Conversation_VoiceChat
|
||||
if webpage.url.contains("voicechat=") {
|
||||
actionTitle = item.presentationData.strings.Conversation_JoinVoiceChatAsSpeaker
|
||||
} else {
|
||||
actionTitle = item.presentationData.strings.Conversation_JoinVoiceChatAsListener
|
||||
}
|
||||
case "telegram_background":
|
||||
title = item.presentationData.strings.Conversation_ChatBackground
|
||||
subtitle = nil
|
||||
|
Loading…
x
Reference in New Issue
Block a user