mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Improve audio playback rate controls
This commit is contained in:
parent
c53d7a1401
commit
88dd028371
@ -8910,3 +8910,11 @@ Sorry for the inconvenience.";
|
|||||||
"Appearance.VoiceOver.Theme" = "%@ Theme";
|
"Appearance.VoiceOver.Theme" = "%@ Theme";
|
||||||
|
|
||||||
"ChatList.EmptyChatListWithArchive" = "All of your chats are archived.";
|
"ChatList.EmptyChatListWithArchive" = "All of your chats are archived.";
|
||||||
|
|
||||||
|
"VoiceOver.Media.PlaybackRate05X" = "0.5X";
|
||||||
|
"VoiceOver.Media.PlaybackRate125X" = "1.25X";
|
||||||
|
"VoiceOver.Media.PlaybackRate15X" = "1.5X";
|
||||||
|
"VoiceOver.Media.PlaybackRate175X" = "1.75X";
|
||||||
|
"VoiceOver.Media.PlaybackRate2X" = "2X";
|
||||||
|
|
||||||
|
"Conversation.AudioRateTooltip15X" = "Audio will play at 1.5X speed.";
|
||||||
|
@ -2713,7 +2713,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
|||||||
strongSelf.context.sharedContext.mediaManager.setPlaylist(nil, type: type, control: SharedMediaPlayerControlAction.playback(.pause))
|
strongSelf.context.sharedContext.mediaManager.setPlaylist(nil, type: type, control: SharedMediaPlayerControlAction.playback(.pause))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mediaAccessoryPanel.setRate = { [weak self] rate in
|
mediaAccessoryPanel.setRate = { [weak self] rate, fromMenu in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -2742,21 +2742,28 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
|||||||
})
|
})
|
||||||
|
|
||||||
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
|
||||||
let slowdown: Bool?
|
let text: String?
|
||||||
|
let rate: CGFloat?
|
||||||
if baseRate == .x1 {
|
if baseRate == .x1 {
|
||||||
slowdown = true
|
text = presentationData.strings.Conversation_AudioRateTooltipNormal
|
||||||
|
rate = 1.0
|
||||||
|
} else if baseRate == .x1_5 {
|
||||||
|
text = presentationData.strings.Conversation_AudioRateTooltip15X
|
||||||
|
rate = 1.5
|
||||||
} else if baseRate == .x2 {
|
} else if baseRate == .x2 {
|
||||||
slowdown = false
|
text = presentationData.strings.Conversation_AudioRateTooltipSpeedUp
|
||||||
|
rate = 2.0
|
||||||
} else {
|
} else {
|
||||||
slowdown = nil
|
text = nil
|
||||||
|
rate = nil
|
||||||
}
|
}
|
||||||
if let slowdown = slowdown {
|
if let rate, let text, !fromMenu {
|
||||||
controller.present(
|
controller.present(
|
||||||
UndoOverlayController(
|
UndoOverlayController(
|
||||||
presentationData: presentationData,
|
presentationData: presentationData,
|
||||||
content: .audioRate(
|
content: .audioRate(
|
||||||
slowdown: slowdown,
|
rate: rate,
|
||||||
text: slowdown ? presentationData.strings.Conversation_AudioRateTooltipNormal : presentationData.strings.Conversation_AudioRateTooltipSpeedUp
|
text: text
|
||||||
),
|
),
|
||||||
elevatedLayout: false,
|
elevatedLayout: false,
|
||||||
animateInAsReplacement: hasTooltip,
|
animateInAsReplacement: hasTooltip,
|
||||||
|
@ -171,7 +171,7 @@ public final class MediaNavigationAccessoryHeaderNode: ASDisplayNode, UIScrollVi
|
|||||||
|
|
||||||
public var tapAction: (() -> Void)?
|
public var tapAction: (() -> Void)?
|
||||||
public var close: (() -> Void)?
|
public var close: (() -> Void)?
|
||||||
public var setRate: ((AudioPlaybackRate) -> Void)?
|
public var setRate: ((AudioPlaybackRate, Bool) -> Void)?
|
||||||
public var togglePlayPause: (() -> Void)?
|
public var togglePlayPause: (() -> Void)?
|
||||||
public var playPrevious: (() -> Void)?
|
public var playPrevious: (() -> Void)?
|
||||||
public var playNext: (() -> Void)?
|
public var playNext: (() -> Void)?
|
||||||
@ -184,21 +184,27 @@ public final class MediaNavigationAccessoryHeaderNode: ASDisplayNode, UIScrollVi
|
|||||||
guard self.playbackBaseRate != oldValue, let playbackBaseRate = self.playbackBaseRate else {
|
guard self.playbackBaseRate != oldValue, let playbackBaseRate = self.playbackBaseRate else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
self.rateButton.accessibilityLabel = self.strings.VoiceOver_Media_PlaybackRate
|
||||||
|
self.rateButton.accessibilityHint = self.strings.VoiceOver_Media_PlaybackRateChange
|
||||||
switch playbackBaseRate {
|
switch playbackBaseRate {
|
||||||
case .x0_5:
|
case .x0_5:
|
||||||
self.rateButton.setContent(.image(optionsRateImage(rate: "0.5X", color: self.theme.rootController.navigationBar.accentTextColor)))
|
self.rateButton.setContent(.image(optionsRateImage(rate: "0.5X", color: self.theme.rootController.navigationBar.accentTextColor)))
|
||||||
|
self.rateButton.accessibilityValue = self.strings.VoiceOver_Media_PlaybackRate05X
|
||||||
case .x1:
|
case .x1:
|
||||||
self.rateButton.setContent(.image(optionsRateImage(rate: "1X", color: self.theme.rootController.navigationBar.controlColor)))
|
self.rateButton.setContent(.image(optionsRateImage(rate: "1X", color: self.theme.rootController.navigationBar.controlColor)))
|
||||||
self.rateButton.accessibilityLabel = self.strings.VoiceOver_Media_PlaybackRate
|
|
||||||
self.rateButton.accessibilityValue = self.strings.VoiceOver_Media_PlaybackRateNormal
|
self.rateButton.accessibilityValue = self.strings.VoiceOver_Media_PlaybackRateNormal
|
||||||
self.rateButton.accessibilityHint = self.strings.VoiceOver_Media_PlaybackRateChange
|
case .x1_25:
|
||||||
|
self.rateButton.setContent(.image(optionsRateImage(rate: "1.25X", color: self.theme.rootController.navigationBar.accentTextColor)))
|
||||||
|
self.rateButton.accessibilityValue = self.strings.VoiceOver_Media_PlaybackRate125X
|
||||||
case .x1_5:
|
case .x1_5:
|
||||||
self.rateButton.setContent(.image(optionsRateImage(rate: "1.5X", color: self.theme.rootController.navigationBar.accentTextColor)))
|
self.rateButton.setContent(.image(optionsRateImage(rate: "1.5X", color: self.theme.rootController.navigationBar.accentTextColor)))
|
||||||
|
self.rateButton.accessibilityValue = self.strings.VoiceOver_Media_PlaybackRate15X
|
||||||
|
case .x1_75:
|
||||||
|
self.rateButton.setContent(.image(optionsRateImage(rate: "1.75X", color: self.theme.rootController.navigationBar.accentTextColor)))
|
||||||
|
self.rateButton.accessibilityValue = self.strings.VoiceOver_Media_PlaybackRate175X
|
||||||
case .x2:
|
case .x2:
|
||||||
self.rateButton.setContent(.image(optionsRateImage(rate: "2X", color: self.theme.rootController.navigationBar.accentTextColor)))
|
self.rateButton.setContent(.image(optionsRateImage(rate: "2X", color: self.theme.rootController.navigationBar.accentTextColor)))
|
||||||
self.rateButton.accessibilityLabel = self.strings.VoiceOver_Media_PlaybackRate
|
self.rateButton.accessibilityValue = self.strings.VoiceOver_Media_PlaybackRate2X
|
||||||
self.rateButton.accessibilityValue = self.strings.VoiceOver_Media_PlaybackRateFast
|
|
||||||
self.rateButton.accessibilityHint = self.strings.VoiceOver_Media_PlaybackRateChange
|
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -379,8 +385,12 @@ public final class MediaNavigationAccessoryHeaderNode: ASDisplayNode, UIScrollVi
|
|||||||
self.rateButton.setContent(.image(optionsRateImage(rate: "0.5X", color: self.theme.rootController.navigationBar.accentTextColor)))
|
self.rateButton.setContent(.image(optionsRateImage(rate: "0.5X", color: self.theme.rootController.navigationBar.accentTextColor)))
|
||||||
case .x1:
|
case .x1:
|
||||||
self.rateButton.setContent(.image(optionsRateImage(rate: "1X", color: self.theme.rootController.navigationBar.controlColor)))
|
self.rateButton.setContent(.image(optionsRateImage(rate: "1X", color: self.theme.rootController.navigationBar.controlColor)))
|
||||||
|
case .x1_25:
|
||||||
|
self.rateButton.setContent(.image(optionsRateImage(rate: "1.25X", color: self.theme.rootController.navigationBar.controlColor)))
|
||||||
case .x1_5:
|
case .x1_5:
|
||||||
self.rateButton.setContent(.image(optionsRateImage(rate: "1.5X", color: self.theme.rootController.navigationBar.accentTextColor)))
|
self.rateButton.setContent(.image(optionsRateImage(rate: "1.5X", color: self.theme.rootController.navigationBar.accentTextColor)))
|
||||||
|
case .x1_75:
|
||||||
|
self.rateButton.setContent(.image(optionsRateImage(rate: "1.75X", color: self.theme.rootController.navigationBar.controlColor)))
|
||||||
case .x2:
|
case .x2:
|
||||||
self.rateButton.setContent(.image(optionsRateImage(rate: "2X", color: self.theme.rootController.navigationBar.accentTextColor)))
|
self.rateButton.setContent(.image(optionsRateImage(rate: "2X", color: self.theme.rootController.navigationBar.accentTextColor)))
|
||||||
default:
|
default:
|
||||||
@ -493,6 +503,7 @@ public final class MediaNavigationAccessoryHeaderNode: ASDisplayNode, UIScrollVi
|
|||||||
transition.updateFrame(node: self.closeButton, frame: CGRect(origin: CGPoint(x: bounds.size.width - 44.0 - rightInset, y: 0.0), size: CGSize(width: 44.0, height: minHeight)))
|
transition.updateFrame(node: self.closeButton, frame: CGRect(origin: CGPoint(x: bounds.size.width - 44.0 - rightInset, y: 0.0), size: CGSize(width: 44.0, height: minHeight)))
|
||||||
let rateButtonSize = CGSize(width: 30.0, height: minHeight)
|
let rateButtonSize = CGSize(width: 30.0, height: minHeight)
|
||||||
transition.updateFrame(node: self.rateButton, frame: CGRect(origin: CGPoint(x: bounds.size.width - 33.0 - closeButtonSize.width - rateButtonSize.width - rightInset, y: -4.0), size: rateButtonSize))
|
transition.updateFrame(node: self.rateButton, frame: CGRect(origin: CGPoint(x: bounds.size.width - 33.0 - closeButtonSize.width - rateButtonSize.width - rightInset, y: -4.0), size: rateButtonSize))
|
||||||
|
|
||||||
transition.updateFrame(node: self.playPauseIconNode, frame: CGRect(origin: CGPoint(x: 6.0, y: 4.0 + UIScreenPixel), size: CGSize(width: 28.0, height: 28.0)))
|
transition.updateFrame(node: self.playPauseIconNode, frame: CGRect(origin: CGPoint(x: 6.0, y: 4.0 + UIScreenPixel), size: CGSize(width: 28.0, height: 28.0)))
|
||||||
transition.updateFrame(node: self.actionButton, frame: CGRect(origin: CGPoint(x: leftInset, y: 0.0), size: CGSize(width: 40.0, height: 37.0)))
|
transition.updateFrame(node: self.actionButton, frame: CGRect(origin: CGPoint(x: leftInset, y: 0.0), size: CGSize(width: 40.0, height: 37.0)))
|
||||||
transition.updateFrame(node: self.scrubbingNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 37.0 - 2.0), size: CGSize(width: size.width, height: 2.0)))
|
transition.updateFrame(node: self.scrubbingNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 37.0 - 2.0), size: CGSize(width: size.width, height: 2.0)))
|
||||||
@ -520,14 +531,16 @@ public final class MediaNavigationAccessoryHeaderNode: ASDisplayNode, UIScrollVi
|
|||||||
} else {
|
} else {
|
||||||
nextRate = .x2
|
nextRate = .x2
|
||||||
}
|
}
|
||||||
self.setRate?(nextRate)
|
self.setRate?(nextRate, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func speedList(strings: PresentationStrings) -> [(String, String, AudioPlaybackRate)] {
|
private func speedList(strings: PresentationStrings) -> [(String, String, AudioPlaybackRate)] {
|
||||||
let speedList: [(String, String, AudioPlaybackRate)] = [
|
let speedList: [(String, String, AudioPlaybackRate)] = [
|
||||||
("0.5x", "0.5x", .x0_5),
|
("0.5x", "0.5x", .x0_5),
|
||||||
(strings.PlaybackSpeed_Normal, "1x", .x1),
|
(strings.PlaybackSpeed_Normal, "1x", .x1),
|
||||||
|
("1.25x", "1.25x", .x1_25),
|
||||||
("1.5x", "1.5x", .x1_5),
|
("1.5x", "1.5x", .x1_5),
|
||||||
|
("1.75x", "1.75x", .x1_75),
|
||||||
("2x", "2x", .x2)
|
("2x", "2x", .x2)
|
||||||
]
|
]
|
||||||
return speedList
|
return speedList
|
||||||
@ -547,7 +560,7 @@ public final class MediaNavigationAccessoryHeaderNode: ASDisplayNode, UIScrollVi
|
|||||||
}, action: { [weak self] _, f in
|
}, action: { [weak self] _, f in
|
||||||
f(.default)
|
f(.default)
|
||||||
|
|
||||||
self?.setRate?(rate)
|
self?.setRate?(rate, true)
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -626,7 +639,7 @@ private final class PlayPauseIconNode: ManagedAnimationNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func optionsRateImage(rate: String, color: UIColor = .white) -> UIImage? {
|
private func optionsRateImage(rate: String, color: UIColor = .white) -> UIImage? {
|
||||||
return generateImage(CGSize(width: 30.0, height: 16.0), rotatedContext: { size, context in
|
return generateImage(CGSize(width: 36.0, height: 16.0), rotatedContext: { size, context in
|
||||||
UIGraphicsPushContext(context)
|
UIGraphicsPushContext(context)
|
||||||
|
|
||||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||||
@ -640,7 +653,11 @@ private func optionsRateImage(rate: String, color: UIColor = .white) -> UIImage?
|
|||||||
|
|
||||||
var offset = CGPoint(x: 1.0, y: 0.0)
|
var offset = CGPoint(x: 1.0, y: 0.0)
|
||||||
var width: CGFloat
|
var width: CGFloat
|
||||||
if rate.count >= 3 {
|
if rate.count >= 5 {
|
||||||
|
string.addAttribute(.kern, value: -0.8 as NSNumber, range: NSRange(string.string.startIndex ..< string.string.endIndex, in: string.string))
|
||||||
|
offset.x += -0.5
|
||||||
|
width = 34.0
|
||||||
|
} else if rate.count >= 3 {
|
||||||
if rate == "0.5X" {
|
if rate == "0.5X" {
|
||||||
string.addAttribute(.kern, value: -0.8 as NSNumber, range: NSRange(string.string.startIndex ..< string.string.endIndex, in: string.string))
|
string.addAttribute(.kern, value: -0.8 as NSNumber, range: NSRange(string.string.startIndex ..< string.string.endIndex, in: string.string))
|
||||||
offset.x += -0.5
|
offset.x += -0.5
|
||||||
|
@ -11,7 +11,7 @@ public final class MediaNavigationAccessoryPanel: ASDisplayNode {
|
|||||||
public let containerNode: MediaNavigationAccessoryContainerNode
|
public let containerNode: MediaNavigationAccessoryContainerNode
|
||||||
|
|
||||||
public var close: (() -> Void)?
|
public var close: (() -> Void)?
|
||||||
public var setRate: ((AudioPlaybackRate) -> Void)?
|
public var setRate: ((AudioPlaybackRate, Bool) -> Void)?
|
||||||
public var togglePlayPause: (() -> Void)?
|
public var togglePlayPause: (() -> Void)?
|
||||||
public var tapAction: (() -> Void)?
|
public var tapAction: (() -> Void)?
|
||||||
public var playPrevious: (() -> Void)?
|
public var playPrevious: (() -> Void)?
|
||||||
@ -32,8 +32,8 @@ public final class MediaNavigationAccessoryPanel: ASDisplayNode {
|
|||||||
close()
|
close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.containerNode.headerNode.setRate = { [weak self] rate in
|
self.containerNode.headerNode.setRate = { [weak self] rate, fromMenu in
|
||||||
self?.setRate?(rate)
|
self?.setRate?(rate, fromMenu)
|
||||||
}
|
}
|
||||||
self.containerNode.headerNode.togglePlayPause = { [weak self] in
|
self.containerNode.headerNode.togglePlayPause = { [weak self] in
|
||||||
if let strongSelf = self, let togglePlayPause = strongSelf.togglePlayPause {
|
if let strongSelf = self, let togglePlayPause = strongSelf.togglePlayPause {
|
||||||
|
@ -669,7 +669,7 @@ open class TelegramBaseController: ViewController, KeyShortcutResponder {
|
|||||||
strongSelf.context.sharedContext.mediaManager.setPlaylist(nil, type: type, control: SharedMediaPlayerControlAction.playback(.pause))
|
strongSelf.context.sharedContext.mediaManager.setPlaylist(nil, type: type, control: SharedMediaPlayerControlAction.playback(.pause))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mediaAccessoryPanel.setRate = { [weak self] rate in
|
mediaAccessoryPanel.setRate = { [weak self] rate, fromMenu in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -687,41 +687,48 @@ open class TelegramBaseController: ViewController, KeyShortcutResponder {
|
|||||||
}
|
}
|
||||||
strongSelf.context.sharedContext.mediaManager.playlistControl(.setBaseRate(baseRate), type: type)
|
strongSelf.context.sharedContext.mediaManager.playlistControl(.setBaseRate(baseRate), type: type)
|
||||||
|
|
||||||
// var hasTooltip = false
|
var hasTooltip = false
|
||||||
// strongSelf.forEachController({ controller in
|
strongSelf.forEachController({ controller in
|
||||||
// if let controller = controller as? UndoOverlayController {
|
if let controller = controller as? UndoOverlayController {
|
||||||
// hasTooltip = true
|
hasTooltip = true
|
||||||
// controller.dismissWithCommitAction()
|
controller.dismissWithCommitAction()
|
||||||
// }
|
}
|
||||||
// return true
|
return true
|
||||||
// })
|
})
|
||||||
//
|
|
||||||
// let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
|
||||||
// let slowdown: Bool?
|
let text: String?
|
||||||
// if baseRate == .x1 {
|
let rate: CGFloat?
|
||||||
// slowdown = true
|
if baseRate == .x1 {
|
||||||
// } else if baseRate == .x2 {
|
text = presentationData.strings.Conversation_AudioRateTooltipNormal
|
||||||
// slowdown = false
|
rate = 1.0
|
||||||
// } else {
|
} else if baseRate == .x1_5 {
|
||||||
// slowdown = nil
|
text = presentationData.strings.Conversation_AudioRateTooltip15X
|
||||||
// }
|
rate = 1.5
|
||||||
// if let slowdown = slowdown {
|
} else if baseRate == .x2 {
|
||||||
// strongSelf.present(
|
text = presentationData.strings.Conversation_AudioRateTooltipSpeedUp
|
||||||
// UndoOverlayController(
|
rate = 2.0
|
||||||
// presentationData: presentationData,
|
} else {
|
||||||
// content: .audioRate(
|
text = nil
|
||||||
// slowdown: slowdown,
|
rate = nil
|
||||||
// text: slowdown ? presentationData.strings.Conversation_AudioRateTooltipNormal : presentationData.strings.Conversation_AudioRateTooltipSpeedUp
|
}
|
||||||
// ),
|
if let rate, let text, !fromMenu {
|
||||||
// elevatedLayout: false,
|
strongSelf.present(
|
||||||
// animateInAsReplacement: hasTooltip,
|
UndoOverlayController(
|
||||||
// action: { action in
|
presentationData: presentationData,
|
||||||
// return true
|
content: .audioRate(
|
||||||
// }
|
rate: rate,
|
||||||
// ),
|
text: text
|
||||||
// in: .current
|
),
|
||||||
// )
|
elevatedLayout: false,
|
||||||
// }
|
animateInAsReplacement: hasTooltip,
|
||||||
|
action: { action in
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
),
|
||||||
|
in: .current
|
||||||
|
)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
mediaAccessoryPanel.togglePlayPause = { [weak self] in
|
mediaAccessoryPanel.togglePlayPause = { [weak self] in
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -36,7 +36,7 @@ private func generateCollapseIcon(theme: PresentationTheme) -> UIImage? {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func optionsRateImage(rate: String, color: UIColor = .white) -> UIImage? {
|
private func optionsRateImage(rate: String, color: UIColor = .white) -> UIImage? {
|
||||||
return generateImage(CGSize(width: 30.0, height: 16.0), rotatedContext: { size, context in
|
return generateImage(CGSize(width: 36.0, height: 16.0), rotatedContext: { size, context in
|
||||||
UIGraphicsPushContext(context)
|
UIGraphicsPushContext(context)
|
||||||
|
|
||||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||||
@ -50,7 +50,11 @@ private func optionsRateImage(rate: String, color: UIColor = .white) -> UIImage?
|
|||||||
|
|
||||||
var offset = CGPoint(x: 1.0, y: 0.0)
|
var offset = CGPoint(x: 1.0, y: 0.0)
|
||||||
var width: CGFloat
|
var width: CGFloat
|
||||||
if rate.count >= 3 {
|
if rate.count >= 5 {
|
||||||
|
string.addAttribute(.kern, value: -0.8 as NSNumber, range: NSRange(string.string.startIndex ..< string.string.endIndex, in: string.string))
|
||||||
|
offset.x += -0.5
|
||||||
|
width = 33.0
|
||||||
|
} else if rate.count >= 3 {
|
||||||
if rate == "0.5X" {
|
if rate == "0.5X" {
|
||||||
string.addAttribute(.kern, value: -0.8 as NSNumber, range: NSRange(string.string.startIndex ..< string.string.endIndex, in: string.string))
|
string.addAttribute(.kern, value: -0.8 as NSNumber, range: NSRange(string.string.startIndex ..< string.string.endIndex, in: string.string))
|
||||||
offset.x += -0.5
|
offset.x += -0.5
|
||||||
@ -418,8 +422,14 @@ final class OverlayPlayerControlsNode: ASDisplayNode {
|
|||||||
let baseRate: AudioPlaybackRate
|
let baseRate: AudioPlaybackRate
|
||||||
if value.status.baseRate.isEqual(to: 2.0) {
|
if value.status.baseRate.isEqual(to: 2.0) {
|
||||||
baseRate = .x2
|
baseRate = .x2
|
||||||
|
} else if value.status.baseRate.isEqual(to: 1.75) {
|
||||||
|
baseRate = .x1_75
|
||||||
} else if value.status.baseRate.isEqual(to: 1.5) {
|
} else if value.status.baseRate.isEqual(to: 1.5) {
|
||||||
|
baseRate = .x1_25
|
||||||
|
} else if value.status.baseRate.isEqual(to: 1.25) {
|
||||||
baseRate = .x1_5
|
baseRate = .x1_5
|
||||||
|
} else if value.status.baseRate.isEqual(to: 0.5) {
|
||||||
|
baseRate = .x0_5
|
||||||
} else {
|
} else {
|
||||||
baseRate = .x1
|
baseRate = .x1
|
||||||
}
|
}
|
||||||
@ -784,8 +794,14 @@ final class OverlayPlayerControlsNode: ASDisplayNode {
|
|||||||
switch baseRate {
|
switch baseRate {
|
||||||
case .x2:
|
case .x2:
|
||||||
self.rateButton.setImage(optionsRateImage(rate: "2X", color: self.presentationData.theme.list.itemAccentColor), for: [])
|
self.rateButton.setImage(optionsRateImage(rate: "2X", color: self.presentationData.theme.list.itemAccentColor), for: [])
|
||||||
|
case .x1_75:
|
||||||
|
self.rateButton.setImage(optionsRateImage(rate: "1.75X", color: self.presentationData.theme.list.itemAccentColor), for: [])
|
||||||
case .x1_5:
|
case .x1_5:
|
||||||
self.rateButton.setImage(optionsRateImage(rate: "1.5X", color: self.presentationData.theme.list.itemAccentColor), for: [])
|
self.rateButton.setImage(optionsRateImage(rate: "1.5X", color: self.presentationData.theme.list.itemAccentColor), for: [])
|
||||||
|
case .x1_25:
|
||||||
|
self.rateButton.setImage(optionsRateImage(rate: "1.25X", color: self.presentationData.theme.list.itemAccentColor), for: [])
|
||||||
|
case .x0_5:
|
||||||
|
self.rateButton.setImage(optionsRateImage(rate: "0.5X", color: self.presentationData.theme.list.itemAccentColor), for: [])
|
||||||
default:
|
default:
|
||||||
self.rateButton.setImage(optionsRateImage(rate: "1X", color: self.presentationData.theme.list.itemSecondaryTextColor), for: [])
|
self.rateButton.setImage(optionsRateImage(rate: "1X", color: self.presentationData.theme.list.itemSecondaryTextColor), for: [])
|
||||||
}
|
}
|
||||||
|
@ -262,7 +262,7 @@ final class PeerInfoListPaneNode: ASDisplayNode, PeerInfoPaneNode {
|
|||||||
strongSelf.context.sharedContext.mediaManager.setPlaylist(nil, type: type, control: SharedMediaPlayerControlAction.playback(.pause))
|
strongSelf.context.sharedContext.mediaManager.setPlaylist(nil, type: type, control: SharedMediaPlayerControlAction.playback(.pause))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mediaAccessoryPanel.setRate = { [weak self] rate in
|
mediaAccessoryPanel.setRate = { [weak self] rate, fromMenu in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -291,21 +291,28 @@ final class PeerInfoListPaneNode: ASDisplayNode, PeerInfoPaneNode {
|
|||||||
})
|
})
|
||||||
|
|
||||||
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
|
||||||
let slowdown: Bool?
|
let text: String?
|
||||||
|
let rate: CGFloat?
|
||||||
if baseRate == .x1 {
|
if baseRate == .x1 {
|
||||||
slowdown = true
|
text = presentationData.strings.Conversation_AudioRateTooltipNormal
|
||||||
|
rate = 1.0
|
||||||
|
} else if baseRate == .x1_5 {
|
||||||
|
text = presentationData.strings.Conversation_AudioRateTooltip15X
|
||||||
|
rate = 1.5
|
||||||
} else if baseRate == .x2 {
|
} else if baseRate == .x2 {
|
||||||
slowdown = false
|
text = presentationData.strings.Conversation_AudioRateTooltipSpeedUp
|
||||||
|
rate = 2.0
|
||||||
} else {
|
} else {
|
||||||
slowdown = nil
|
text = nil
|
||||||
|
rate = nil
|
||||||
}
|
}
|
||||||
if let slowdown = slowdown {
|
if let rate, let text, !fromMenu {
|
||||||
controller.present(
|
controller.present(
|
||||||
UndoOverlayController(
|
UndoOverlayController(
|
||||||
presentationData: presentationData,
|
presentationData: presentationData,
|
||||||
content: .audioRate(
|
content: .audioRate(
|
||||||
slowdown: slowdown,
|
rate: rate,
|
||||||
text: slowdown ? presentationData.strings.Conversation_AudioRateTooltipNormal : presentationData.strings.Conversation_AudioRateTooltipSpeedUp
|
text: text
|
||||||
),
|
),
|
||||||
elevatedLayout: false,
|
elevatedLayout: false,
|
||||||
animateInAsReplacement: hasTooltip,
|
animateInAsReplacement: hasTooltip,
|
||||||
|
@ -18,7 +18,9 @@ public enum MusicPlaybackSettingsLooping: Int32 {
|
|||||||
public enum AudioPlaybackRate: Int32 {
|
public enum AudioPlaybackRate: Int32 {
|
||||||
case x0_5 = 500
|
case x0_5 = 500
|
||||||
case x1 = 1000
|
case x1 = 1000
|
||||||
|
case x1_25 = 1250
|
||||||
case x1_5 = 1500
|
case x1_5 = 1500
|
||||||
|
case x1_75 = 1750
|
||||||
case x2 = 2000
|
case x2 = 2000
|
||||||
case x4 = 4000
|
case x4 = 4000
|
||||||
case x8 = 8000
|
case x8 = 8000
|
||||||
|
@ -26,7 +26,7 @@ public enum UndoOverlayContent {
|
|||||||
case linkCopied(text: String)
|
case linkCopied(text: String)
|
||||||
case banned(text: String)
|
case banned(text: String)
|
||||||
case importedMessage(text: String)
|
case importedMessage(text: String)
|
||||||
case audioRate(slowdown: Bool, text: String)
|
case audioRate(rate: CGFloat, text: String)
|
||||||
case forward(savedMessages: Bool, text: String)
|
case forward(savedMessages: Bool, text: String)
|
||||||
case autoDelete(isOn: Bool, title: String?, text: String)
|
case autoDelete(isOn: Bool, title: String?, text: String)
|
||||||
case gigagroupConversion(text: String)
|
case gigagroupConversion(text: String)
|
||||||
|
@ -540,11 +540,21 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
|
|||||||
displayUndo = false
|
displayUndo = false
|
||||||
}
|
}
|
||||||
self.originalRemainingSeconds = duration
|
self.originalRemainingSeconds = duration
|
||||||
case let .audioRate(slowdown, text):
|
case let .audioRate(rate, text):
|
||||||
self.avatarNode = nil
|
self.avatarNode = nil
|
||||||
self.iconNode = nil
|
self.iconNode = nil
|
||||||
self.iconCheckNode = nil
|
self.iconCheckNode = nil
|
||||||
self.animationNode = AnimationNode(animation: slowdown ? "anim_voicespeedstop" : "anim_voicespeed", colors: [:], scale: 0.066)
|
|
||||||
|
let animationName: String
|
||||||
|
if rate == 1.5 {
|
||||||
|
animationName = "anim_voice1_5x"
|
||||||
|
} else if rate == 2.0 {
|
||||||
|
animationName = "anim_voice2x"
|
||||||
|
} else {
|
||||||
|
animationName = "anim_voice1x"
|
||||||
|
}
|
||||||
|
|
||||||
|
self.animationNode = AnimationNode(animation: animationName, colors: [:], scale: 0.066)
|
||||||
self.animatedStickerNode = nil
|
self.animatedStickerNode = nil
|
||||||
|
|
||||||
let body = MarkdownAttributeSet(font: Font.regular(14.0), textColor: .white)
|
let body = MarkdownAttributeSet(font: Font.regular(14.0), textColor: .white)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user