Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios

This commit is contained in:
Mike Renoir 2023-07-19 12:16:40 +02:00
commit 91397ac1ea
11 changed files with 60 additions and 83 deletions

View File

@ -9698,7 +9698,7 @@ Sorry for the inconvenience.";
"Story.Privacy.CategoryContacts" = "Contacts"; "Story.Privacy.CategoryContacts" = "Contacts";
"Story.Privacy.CategoryCloseFriends" = "Close Friends"; "Story.Privacy.CategoryCloseFriends" = "Close Friends";
"Story.Privacy.CategorySelectedContacts" = "Selected Contacts"; "Story.Privacy.CategorySelectedContacts" = "Selected Contacts";
"Story.Privacy.ExcludedPeople" = "ExcludedPeople"; "Story.Privacy.ExcludedPeople" = "Excluded People";
"Story.Privacy.ExcludePeople" = "exclude people"; "Story.Privacy.ExcludePeople" = "exclude people";
"Story.Privacy.ExcludePeopleExceptNames" = "except %@"; "Story.Privacy.ExcludePeopleExceptNames" = "except %@";

View File

@ -2540,6 +2540,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
return nil return nil
} }
private weak var storyCameraTooltip: TooltipScreen?
fileprivate func openStoryCamera(fromList: Bool) { fileprivate func openStoryCamera(fromList: Bool) {
var reachedCountLimit = false var reachedCountLimit = false
var premiumNeeded = false var premiumNeeded = false
@ -2575,6 +2576,10 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
} }
if reachedCountLimit || premiumNeeded || hasActiveCall || hasActiveGroupCall { if reachedCountLimit || premiumNeeded || hasActiveCall || hasActiveGroupCall {
if let storyCameraTooltip = self.storyCameraTooltip {
self.storyCameraTooltip = nil
storyCameraTooltip.dismiss()
}
if let componentView = self.chatListHeaderView() { if let componentView = self.chatListHeaderView() {
var sourceFrame: CGRect? var sourceFrame: CGRect?
if fromList { if fromList {
@ -2626,6 +2631,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
} }
} }
) )
self.storyCameraTooltip = tooltipController
self.present(tooltipController, in: .window(.root)) self.present(tooltipController, in: .window(.root))
} }
} }

View File

@ -1260,7 +1260,12 @@ open class TextNode: ASDisplayNode {
var effectiveLineRange = brokenLineRange var effectiveLineRange = brokenLineRange
var additionalTrailingLine: (CTLine, Double)? var additionalTrailingLine: (CTLine, Double)?
if lineRange.length == 0 || (CTLineGetTypographicBounds(originalLine, nil, nil, nil) - CTLineGetTrailingWhitespaceWidth(originalLine) + truncationTokenWidth) < Double(lineConstrainedSize.width) { var measureFitWidth = CTLineGetTypographicBounds(originalLine, nil, nil, nil) - CTLineGetTrailingWhitespaceWidth(originalLine)
if customTruncationToken != nil {
measureFitWidth += truncationTokenWidth
}
if lineRange.length == 0 || measureFitWidth < Double(lineConstrainedSize.width) {
if didClipLinebreak { if didClipLinebreak {
if lineRange.length == 0 { if lineRange.length == 0 {
coreTextLine = CTLineCreateWithAttributedString(NSAttributedString()) coreTextLine = CTLineCreateWithAttributedString(NSAttributedString())
@ -1274,7 +1279,7 @@ open class TextNode: ASDisplayNode {
coreTextLine = originalLine coreTextLine = originalLine
} }
} else { } else {
coreTextLine = CTLineCreateTruncatedLine(originalLine, Double(lineConstrainedSize.width), truncationType, truncationToken) ?? truncationToken coreTextLine = CTLineCreateTruncatedLine(originalLine, max(1.0, Double(lineConstrainedSize.width) - truncationTokenWidth), truncationType, truncationToken) ?? truncationToken
let runs = (CTLineGetGlyphRuns(coreTextLine) as [AnyObject]) as! [CTRun] let runs = (CTLineGetGlyphRuns(coreTextLine) as [AnyObject]) as! [CTRun]
for run in runs { for run in runs {
let runAttributes: NSDictionary = CTRunGetAttributes(run) let runAttributes: NSDictionary = CTRunGetAttributes(run)

View File

@ -1022,7 +1022,6 @@ private final class MediaPlayerContext {
if isPaused && self.fadeTimer != nil { if isPaused && self.fadeTimer != nil {
playbackStatus = .paused playbackStatus = .paused
} else if reportRate.isZero { } else if reportRate.isZero {
//playbackStatus = .buffering(initial: false, whilePlaying: true)
playbackStatus = .playing playbackStatus = .playing
statusTimestamp = 0.0 statusTimestamp = 0.0
} else { } else {

View File

@ -53,7 +53,7 @@ final class PeerInfoStoryGridScreenComponent: Component {
private weak var state: EmptyComponentState? private weak var state: EmptyComponentState?
private var environment: EnvironmentType? private var environment: EnvironmentType?
private var paneNode: PeerInfoStoryPaneNode? private(set) var paneNode: PeerInfoStoryPaneNode?
private var paneStatusDisposable: Disposable? private var paneStatusDisposable: Disposable?
private(set) var paneStatusText: String? private(set) var paneStatusText: String?
@ -171,74 +171,6 @@ final class PeerInfoStoryGridScreenComponent: Component {
self.environment?.controller()?.push(PeerInfoStoryGridScreen(context: component.context, peerId: component.peerId, scope: .archive)) self.environment?.controller()?.push(PeerInfoStoryGridScreen(context: component.context, peerId: component.peerId, scope: .archive))
}))) })))
} }
/*if photoCount != 0 && videoCount != 0 {
items.append(.separator)
let showPhotos: Bool
switch pane.contentType {
case .photo, .photoOrVideo:
showPhotos = true
default:
showPhotos = false
}
let showVideos: Bool
switch pane.contentType {
case .video, .photoOrVideo:
showVideos = true
default:
showVideos = false
}
items.append(.action(ContextMenuActionItem(text: strings.SharedMedia_ShowPhotos, icon: { theme in
if !showPhotos {
return nil
}
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor)
}, action: { [weak pane] _, a in
a(.default)
guard let pane = pane else {
return
}
let updatedContentType: PeerInfoVisualMediaPaneNode.ContentType
switch pane.contentType {
case .photoOrVideo:
updatedContentType = .video
case .photo:
updatedContentType = .photo
case .video:
updatedContentType = .photoOrVideo
default:
updatedContentType = pane.contentType
}
pane.updateContentType(contentType: updatedContentType)
})))
items.append(.action(ContextMenuActionItem(text: strings.SharedMedia_ShowVideos, icon: { theme in
if !showVideos {
return nil
}
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor)
}, action: { [weak pane] _, a in
a(.default)
guard let pane = pane else {
return
}
let updatedContentType: PeerInfoVisualMediaPaneNode.ContentType
switch pane.contentType {
case .photoOrVideo:
updatedContentType = .photo
case .photo:
updatedContentType = .photoOrVideo
case .video:
updatedContentType = .video
default:
updatedContentType = pane.contentType
}
pane.updateContentType(contentType: updatedContentType)
})))
}*/
} }
let contextController = ContextController(account: component.context.account, presentationData: presentationData, source: .reference(PeerInfoContextReferenceContentSource(controller: controller, sourceNode: source)), items: .single(ContextController.Items(content: .list(items))), gesture: nil) let contextController = ContextController(account: component.context.account, presentationData: presentationData, source: .reference(PeerInfoContextReferenceContentSource(controller: controller, sourceNode: source)), items: .single(ContextController.Items(content: .list(items))), gesture: nil)
@ -554,8 +486,6 @@ public class PeerInfoStoryGridScreen: ViewControllerComponentContainer {
} }
moreBarButton.addTarget(self, action: #selector(self.morePressed), forControlEvents: .touchUpInside) moreBarButton.addTarget(self, action: #selector(self.morePressed), forControlEvents: .touchUpInside)
self.navigationItem.setRightBarButton(moreBarButtonItem, animated: false)
self.titleView = ChatTitleView( self.titleView = ChatTitleView(
context: context, theme: context: context, theme:
presentationData.theme, presentationData.theme,
@ -594,6 +524,8 @@ public class PeerInfoStoryGridScreen: ViewControllerComponentContainer {
title = nil title = nil
} }
self.titleView?.titleContent = .custom(presentationData.strings.StoryList_TitleSaved, title, false) self.titleView?.titleContent = .custom(presentationData.strings.StoryList_TitleSaved, title, false)
self.navigationItem.setRightBarButton(self.moreBarButtonItem, animated: false)
case .archive: case .archive:
guard let componentView = self.node.hostView.componentView as? PeerInfoStoryGridScreenComponent.View else { guard let componentView = self.node.hostView.componentView as? PeerInfoStoryGridScreenComponent.View else {
return return
@ -605,6 +537,19 @@ public class PeerInfoStoryGridScreen: ViewControllerComponentContainer {
title = presentationData.strings.StoryList_TitleArchive title = presentationData.strings.StoryList_TitleArchive
} }
self.titleView?.titleContent = .custom(title, nil, false) self.titleView?.titleContent = .custom(title, nil, false)
var hasMenu = false
if componentView.selectedCount != 0 {
hasMenu = true
} else if let paneNode = componentView.paneNode, !paneNode.isEmpty {
hasMenu = true
}
if hasMenu {
self.navigationItem.setRightBarButton(self.moreBarButtonItem, animated: false)
} else {
self.navigationItem.setRightBarButton(nil, animated: false)
}
} }
} }

View File

@ -1446,7 +1446,7 @@ final class ShareWithPeersScreenComponent: Component {
case .closeFriends: case .closeFriends:
title = environment.strings.Story_Privacy_CategoryCloseFriends title = environment.strings.Story_Privacy_CategoryCloseFriends
case .contacts: case .contacts:
title = environment.strings.Story_Privacy_ExcludePeople title = environment.strings.Story_Privacy_ExcludedPeople
case .nobody: case .nobody:
title = environment.strings.Story_Privacy_CategorySelectedContacts title = environment.strings.Story_Privacy_CategorySelectedContacts
case .everyone: case .everyone:
@ -2023,7 +2023,7 @@ public class ShareWithPeersScreen: ViewControllerComponentContainer {
id: .contacts, id: .contacts,
title: presentationData.strings.Story_Privacy_CategoryContacts, title: presentationData.strings.Story_Privacy_CategoryContacts,
icon: "Chat List/Tabs/IconContacts", icon: "Chat List/Tabs/IconContacts",
iconColor: .yellow, iconColor: .violet,
actionTitle: contactsSubtitle actionTitle: contactsSubtitle
)) ))
@ -2063,7 +2063,7 @@ public class ShareWithPeersScreen: ViewControllerComponentContainer {
id: .selectedContacts, id: .selectedContacts,
title: presentationData.strings.Story_Privacy_CategorySelectedContacts, title: presentationData.strings.Story_Privacy_CategorySelectedContacts,
icon: "Chat List/Filters/Group", icon: "Chat List/Filters/Group",
iconColor: .violet, iconColor: .yellow,
actionTitle: selectedContactsSubtitle actionTitle: selectedContactsSubtitle
)) ))

View File

@ -171,6 +171,13 @@ public extension StoryContainerScreen {
|> take(1) |> take(1)
|> mapToSignal { state -> Signal<StoryContentContextState, NoError> in |> mapToSignal { state -> Signal<StoryContentContextState, NoError> in
if let slice = state.slice { if let slice = state.slice {
#if DEBUG && true
if "".isEmpty {
return .single(state)
|> delay(4.0, queue: .mainQueue())
}
#endif
return waitUntilStoryMediaPreloaded(context: context, peerId: slice.peer.id, storyItem: slice.item.storyItem) return waitUntilStoryMediaPreloaded(context: context, peerId: slice.peer.id, storyItem: slice.item.storyItem)
|> timeout(4.0, queue: .mainQueue(), alternate: .complete()) |> timeout(4.0, queue: .mainQueue(), alternate: .complete())
|> map { _ -> StoryContentContextState in |> map { _ -> StoryContentContextState in

View File

@ -82,6 +82,8 @@ final class StoryItemContentComponent: Component {
private var currentProgressTimerValue: Double = 0.0 private var currentProgressTimerValue: Double = 0.0
private var videoProgressDisposable: Disposable? private var videoProgressDisposable: Disposable?
private var ignoreBufferingTimestamp: Double = 0.0
private var markedAsSeen: Bool = false private var markedAsSeen: Bool = false
private var contentLoaded: Bool = false private var contentLoaded: Bool = false
@ -252,6 +254,7 @@ final class StoryItemContentComponent: Component {
override func leaveAmbientMode() { override func leaveAmbientMode() {
if let videoNode = self.videoNode { if let videoNode = self.videoNode {
self.ignoreBufferingTimestamp = CFAbsoluteTimeGetCurrent()
videoNode.setSoundEnabled(true) videoNode.setSoundEnabled(true)
videoNode.continueWithOverridingAmbientMode(isAmbient: false) videoNode.continueWithOverridingAmbientMode(isAmbient: false)
} }
@ -259,6 +262,7 @@ final class StoryItemContentComponent: Component {
override func enterAmbientMode(ambient: Bool) { override func enterAmbientMode(ambient: Bool) {
if let videoNode = self.videoNode { if let videoNode = self.videoNode {
self.ignoreBufferingTimestamp = CFAbsoluteTimeGetCurrent()
if ambient { if ambient {
videoNode.continueWithOverridingAmbientMode(isAmbient: true) videoNode.continueWithOverridingAmbientMode(isAmbient: true)
} else { } else {
@ -369,6 +373,16 @@ final class StoryItemContentComponent: Component {
isBuffering = true isBuffering = true
} }
if isBuffering {
if CFAbsoluteTimeGetCurrent() - self.ignoreBufferingTimestamp < 0.3 {
isBuffering = false
} else {
self.ignoreBufferingTimestamp = 0.0
}
} else {
self.ignoreBufferingTimestamp = 0.0
}
if case .buffering(true, _, _, _) = videoPlaybackStatus.status { if case .buffering(true, _, _, _) = videoPlaybackStatus.status {
timestampAndDuration = (nil, effectiveDuration) timestampAndDuration = (nil, effectiveDuration)
} else if effectiveDuration > 0.0 { } else if effectiveDuration > 0.0 {

View File

@ -2468,7 +2468,7 @@ public final class StoryItemSetContainerComponent: Component {
privacyIcon = ComponentView() privacyIcon = ComponentView()
self.privacyIcon = privacyIcon self.privacyIcon = privacyIcon
} }
let closeFriendIconSize = privacyIcon.update( let privacyIconSize = privacyIcon.update(
transition: privacyIconTransition, transition: privacyIconTransition,
component: AnyComponent(PlainButtonComponent( component: AnyComponent(PlainButtonComponent(
content: AnyComponent( content: AnyComponent(
@ -2504,7 +2504,7 @@ public final class StoryItemSetContainerComponent: Component {
let tooltipScreen = TooltipScreen( let tooltipScreen = TooltipScreen(
account: component.context.account, account: component.context.account,
sharedContext: component.context.sharedContext, sharedContext: component.context.sharedContext,
text: .plain(text: tooltipText), style: .default, location: TooltipScreen.Location.point(closeFriendIconView.convert(closeFriendIconView.bounds, to: self).offsetBy(dx: 1.0, dy: 6.0), .top), displayDuration: .infinite, shouldDismissOnTouch: { _, _ in text: .plain(text: tooltipText), style: .default, location: TooltipScreen.Location.point(closeFriendIconView.convert(closeFriendIconView.bounds, to: nil).offsetBy(dx: 1.0, dy: 6.0), .top), displayDuration: .infinite, shouldDismissOnTouch: { _, _ in
return .dismiss(consume: true) return .dismiss(consume: true)
} }
) )
@ -2524,7 +2524,7 @@ public final class StoryItemSetContainerComponent: Component {
environment: {}, environment: {},
containerSize: CGSize(width: 44.0, height: 44.0) containerSize: CGSize(width: 44.0, height: 44.0)
) )
let closeFriendIconFrame = CGRect(origin: CGPoint(x: headerRightOffset - closeFriendIconSize.width - 8.0, y: 23.0), size: closeFriendIconSize) let closeFriendIconFrame = CGRect(origin: CGPoint(x: headerRightOffset - privacyIconSize.width - 8.0, y: 22.0), size: privacyIconSize)
if let closeFriendIconView = privacyIcon.view { if let closeFriendIconView = privacyIcon.view {
if closeFriendIconView.superview == nil { if closeFriendIconView.superview == nil {
self.controlsContainerView.addSubview(closeFriendIconView) self.controlsContainerView.addSubview(closeFriendIconView)
@ -3886,7 +3886,7 @@ public final class StoryItemSetContainerComponent: Component {
self.requestSave() self.requestSave()
}))) })))
if component.slice.item.storyItem.isPublic && (component.slice.peer.addressName != nil || !component.slice.peer._asPeer().usernames.isEmpty) && component.slice.item.storyItem.expirationTimestamp > Int32(Date().timeIntervalSince1970) { if component.slice.item.storyItem.isPublic && (component.slice.peer.addressName != nil || !component.slice.peer._asPeer().usernames.isEmpty) && (component.slice.item.storyItem.expirationTimestamp > Int32(Date().timeIntervalSince1970) || component.slice.item.storyItem.isPinned) {
items.append(.action(ContextMenuActionItem(text: component.strings.Story_Context_CopyLink, icon: { theme in items.append(.action(ContextMenuActionItem(text: component.strings.Story_Context_CopyLink, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Link"), color: theme.contextMenu.primaryColor) return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Link"), color: theme.contextMenu.primaryColor)
}, action: { [weak self] _, a in }, action: { [weak self] _, a in

View File

@ -374,6 +374,7 @@ public final class StoryPeerListComponent: Component {
self.scrollContainerView = UIView() self.scrollContainerView = UIView()
self.scrollContainerView.clipsToBounds = true self.scrollContainerView.clipsToBounds = true
self.scrollContainerView.isExclusiveTouch = true
self.titleView = UIImageView() self.titleView = UIImageView()
self.titleView.layer.anchorPoint = CGPoint(x: 0.0, y: 0.5) self.titleView.layer.anchorPoint = CGPoint(x: 0.0, y: 0.5)

@ -1 +1 @@
Subproject commit ef358c48b05ccd59319a7ceded340b75baffa751 Subproject commit ebc8452d3a0d0bc18822b4eb6ca61ec8fa7a70a5