This commit is contained in:
Ali 2023-07-26 20:23:59 +04:00
parent 29f29e927e
commit c5039d9be1
6 changed files with 155 additions and 59 deletions

View File

@ -2018,10 +2018,14 @@ final class ChatListControllerNode: ASDisplayNode, UIGestureRecognizerDelegate {
}
var effectiveStorySubscriptions: EngineStorySubscriptions?
if let controller = self.controller, let storySubscriptions = controller.orderedStorySubscriptions, shouldDisplayStoriesInChatListHeader(storySubscriptions: storySubscriptions, isHidden: controller.location == .chatList(groupId: .archive)) {
effectiveStorySubscriptions = controller.orderedStorySubscriptions
if let controller = self.controller, case .forum = controller.location {
effectiveStorySubscriptions = nil
} else {
effectiveStorySubscriptions = EngineStorySubscriptions(accountItem: nil, items: [], hasMoreToken: nil)
if let controller = self.controller, let storySubscriptions = controller.orderedStorySubscriptions, shouldDisplayStoriesInChatListHeader(storySubscriptions: storySubscriptions, isHidden: controller.location == .chatList(groupId: .archive)) {
effectiveStorySubscriptions = controller.orderedStorySubscriptions
} else {
effectiveStorySubscriptions = EngineStorySubscriptions(accountItem: nil, items: [], hasMoreToken: nil)
}
}
let navigationBarSize = self.navigationBarView.update(

View File

@ -483,15 +483,15 @@ public final class PeerStoryListContext {
self.peerId = peerId
self.isArchived = isArchived
self.stateValue = State(peerReference: nil, items: [], totalCount: 0, loadMoreToken: 0, isCached: true, allEntityFiles: [:])
self.stateValue = State(peerReference: nil, items: [], totalCount: 0, loadMoreToken: 0, isCached: true, hasCache: false, allEntityFiles: [:])
let _ = (account.postbox.transaction { transaction -> (PeerReference?, [EngineStoryItem], Int, [MediaId: TelegramMediaFile]) in
let _ = (account.postbox.transaction { transaction -> (PeerReference?, [EngineStoryItem], Int, [MediaId: TelegramMediaFile], Bool) in
let key = ValueBoxKey(length: 8 + 1)
key.setInt64(0, value: peerId.toInt64())
key.setInt8(8, value: isArchived ? 1 : 0)
let cached = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPeerStoryListHeads, key: key))?.get(CachedPeerStoryListHead.self)
guard let cached = cached else {
return (nil, [], 0, [:])
return (nil, [], 0, [:], false)
}
var items: [EngineStoryItem] = []
var allEntityFiles: [MediaId: TelegramMediaFile] = [:]
@ -540,14 +540,14 @@ public final class PeerStoryListContext {
let peerReference = transaction.getPeer(peerId).flatMap(PeerReference.init)
return (peerReference, items, Int(cached.totalCount), allEntityFiles)
return (peerReference, items, Int(cached.totalCount), allEntityFiles, true)
}
|> deliverOn(self.queue)).start(next: { [weak self] peerReference, items, totalCount, allEntityFiles in
|> deliverOn(self.queue)).start(next: { [weak self] peerReference, items, totalCount, allEntityFiles, hasCache in
guard let `self` = self else {
return
}
self.stateValue = State(peerReference: peerReference, items: items, totalCount: totalCount, loadMoreToken: 0, isCached: true, allEntityFiles: allEntityFiles)
self.stateValue = State(peerReference: peerReference, items: items, totalCount: totalCount, loadMoreToken: 0, isCached: true, hasCache: hasCache, allEntityFiles: allEntityFiles)
self.loadMore(completion: nil)
})
}
@ -678,6 +678,7 @@ public final class PeerStoryListContext {
updatedState.items.removeAll()
updatedState.isCached = false
}
updatedState.hasCache = true
var existingIds = Set(updatedState.items.map { $0.id })
for item in storyItems {
@ -952,6 +953,7 @@ public final class PeerStoryListContext {
public var totalCount: Int
public var loadMoreToken: Int?
public var isCached: Bool
public var hasCache: Bool
public var allEntityFiles: [MediaId: TelegramMediaFile]
init(
@ -960,6 +962,7 @@ public final class PeerStoryListContext {
totalCount: Int,
loadMoreToken: Int?,
isCached: Bool,
hasCache: Bool,
allEntityFiles: [MediaId: TelegramMediaFile]
) {
self.peerReference = peerReference
@ -967,6 +970,7 @@ public final class PeerStoryListContext {
self.totalCount = totalCount
self.loadMoreToken = loadMoreToken
self.isCached = isCached
self.hasCache = hasCache
self.allEntityFiles = allEntityFiles
}
}

View File

@ -50,7 +50,7 @@ final class PeerInfoStoryGridScreenComponent: Component {
final class View: UIView {
private var component: PeerInfoStoryGridScreenComponent?
private weak var state: EmptyComponentState?
private(set) weak var state: EmptyComponentState?
private var environment: EnvironmentType?
private(set) var paneNode: PeerInfoStoryPaneNode?
@ -172,6 +172,24 @@ final class PeerInfoStoryGridScreenComponent: Component {
})))
}
}
if let paneNode = self.paneNode, !paneNode.isSelectionModeActive, case .saved = component.scope {
if !paneNode.isEmpty {
items.append(.action(ContextMenuActionItem(text: presentationData.strings.Conversation_ContextMenuSelect, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Select"), color: theme.contextMenu.primaryColor)
}, action: { [weak self] _, a in
a(.default)
guard let self, let paneNode = self.paneNode else {
return
}
paneNode.setIsSelectionModeActive(true)
(self.environment?.controller() as? PeerInfoStoryGridScreen)?.updateTitle()
})))
}
}
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)
contextController.passthroughTouchEvent = { [weak self] sourceView, point in
@ -306,11 +324,19 @@ final class PeerInfoStoryGridScreenComponent: Component {
self.selectionPanel = selectionPanel
}
let buttonText: String
switch component.scope {
case .saved:
buttonText = environment.strings.Common_Delete
case .archive:
buttonText = environment.strings.StoryList_SaveToProfile
}
let selectionPanelSize = selectionPanel.update(
transition: selectionPanelTransition,
component: AnyComponent(BottomButtonPanelComponent(
theme: environment.theme,
title: environment.strings.StoryList_SaveToProfile,
title: buttonText,
label: nil,
isEnabled: true,
insets: UIEdgeInsets(top: 0.0, left: sideInset, bottom: environment.safeInsets.bottom, right: sideInset),
@ -322,20 +348,49 @@ final class PeerInfoStoryGridScreenComponent: Component {
return
}
let _ = component.context.engine.messages.updateStoriesArePinned(ids: paneNode.selectedItems, isPinned: true).start()
let presentationData = component.context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: environment.theme)
let title: String = presentationData.strings.StoryList_TooltipStoriesSavedToProfile(Int32(paneNode.selectedIds.count))
environment.controller()?.present(UndoOverlayController(
presentationData: presentationData,
content: .info(title: title, text: presentationData.strings.StoryList_TooltipStoriesSavedToProfileText, timeout: nil),
elevatedLayout: false,
animateInAsReplacement: false,
action: { _ in return false }
), in: .current)
paneNode.clearSelection()
switch component.scope {
case .saved:
let presentationData = component.context.sharedContext.currentPresentationData.with({ $0 })
let actionSheet = ActionSheetController(presentationData: presentationData)
actionSheet.setItemGroups([
ActionSheetItemGroup(items: [
ActionSheetButtonItem(title: presentationData.strings.Common_Delete, color: .destructive, action: { [weak self, weak actionSheet] in
actionSheet?.dismissAnimated()
guard let self, let paneNode = self.paneNode, let component = self.component else {
return
}
let _ = component.context.engine.messages.deleteStories(ids: Array(paneNode.selectedIds)).start()
paneNode.setIsSelectionModeActive(false)
(self.environment?.controller() as? PeerInfoStoryGridScreen)?.updateTitle()
})
]),
ActionSheetItemGroup(items: [
ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
})
])
])
self.environment?.controller()?.present(actionSheet, in: .window(.root))
case .archive:
let _ = component.context.engine.messages.updateStoriesArePinned(ids: paneNode.selectedItems, isPinned: true).start()
let presentationData = component.context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: environment.theme)
let title: String = presentationData.strings.StoryList_TooltipStoriesSavedToProfile(Int32(paneNode.selectedIds.count))
environment.controller()?.present(UndoOverlayController(
presentationData: presentationData,
content: .info(title: title, text: presentationData.strings.StoryList_TooltipStoriesSavedToProfileText, timeout: nil),
elevatedLayout: false,
animateInAsReplacement: false,
action: { _ in return false }
), in: .current)
paneNode.clearSelection()
}
}
)),
environment: {},
@ -462,6 +517,7 @@ public class PeerInfoStoryGridScreen: ViewControllerComponentContainer {
private var moreBarButton: MoreHeaderButton?
private var moreBarButtonItem: UIBarButtonItem?
private var doneBarButtonItem: UIBarButtonItem?
public init(
context: AccountContext,
@ -493,6 +549,9 @@ public class PeerInfoStoryGridScreen: ViewControllerComponentContainer {
}
moreBarButton.addTarget(self, action: #selector(self.morePressed), forControlEvents: .touchUpInside)
let doneBarButtonItem = UIBarButtonItem(title: presentationData.strings.Common_Done, style: .done, target: self, action: #selector(self.donePressed))
self.doneBarButtonItem = doneBarButtonItem
self.titleView = ChatTitleView(
context: context, theme:
presentationData.theme,
@ -528,7 +587,7 @@ public class PeerInfoStoryGridScreen: ViewControllerComponentContainer {
switch self.scope {
case .saved:
guard let componentView = self.node.hostView.componentView as? PeerInfoStoryGridScreenComponent.View else {
guard let componentView = self.node.hostView.componentView as? PeerInfoStoryGridScreenComponent.View, let paneNode = componentView.paneNode else {
return
}
let title: String?
@ -539,7 +598,11 @@ public class PeerInfoStoryGridScreen: ViewControllerComponentContainer {
}
self.titleView?.titleContent = .custom(presentationData.strings.StoryList_TitleSaved, title, false)
self.navigationItem.setRightBarButton(self.moreBarButtonItem, animated: false)
if paneNode.isSelectionModeActive {
self.navigationItem.setRightBarButton(self.doneBarButtonItem, animated: false)
} else {
self.navigationItem.setRightBarButton(self.moreBarButtonItem, animated: false)
}
case .archive:
guard let componentView = self.node.hostView.componentView as? PeerInfoStoryGridScreenComponent.View else {
return
@ -577,6 +640,14 @@ public class PeerInfoStoryGridScreen: ViewControllerComponentContainer {
componentView.morePressed(source: moreBarButton.referenceNode)
}
@objc private func donePressed() {
guard let componentView = self.node.hostView.componentView as? PeerInfoStoryGridScreenComponent.View, let paneNode = componentView.paneNode else {
return
}
paneNode.setIsSelectionModeActive(false)
self.updateTitle()
}
override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
super.containerLayoutUpdated(layout, transition: transition)

View File

@ -874,6 +874,8 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
}
}
public private(set) var isSelectionModeActive: Bool
private var currentParams: (size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData)?
private let ready = Promise<Bool>()
@ -930,6 +932,8 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
self.navigationController = navigationController
self.isSaved = isSaved
self.isArchive = isArchive
self.isSelectionModeActive = isArchive
self.presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
@ -1228,7 +1232,7 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
}
)
//TODO:selection
if isArchive {
if isArchive || self.isSelectionModeActive {
self._itemInteraction?.selectedIds = Set()
}
self.itemGridBinding.itemInteraction = self._itemInteraction
@ -1520,22 +1524,6 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
}
public func updateContentType(contentType: ContentType) {
/*if self.contentType == contentType {
return
}
self.contentType = contentType
self.contentTypePromise.set(contentType)
self.itemGrid.hideScrollingArea()
var threadId: Int64?
if case let .replyThread(message) = chatLocation {
threadId = Int64(message.messageId.id)
}
self.listSource = self.context.engine.messages.sparseMessageList(peerId: self.peerId, threadId: threadId, tag: tagMaskForType(self.contentType))
self.isRequestingView = false
self.requestHistoryAroundVisiblePosition(synchronous: true, reloadAtTop: true)*/
}
public func updateZoomLevel(level: ZoomLevel) {
@ -1544,6 +1532,23 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
//let _ = updateVisualMediaStoredState(engine: self.context.engine, peerId: self.peerId, messageTag: self.stateTag, state: VisualMediaStoredState(zoomLevel: level.rawValue)).start()
}
public func setIsSelectionModeActive(_ value: Bool) {
if self.isSelectionModeActive != value {
self.isSelectionModeActive = value
if value {
if self._itemInteraction?.selectedIds == nil {
self._itemInteraction?.selectedIds = Set()
}
} else {
self._itemInteraction?.selectedIds = nil
}
self.selectedIdsPromise.set(self._itemInteraction?.selectedIds ?? Set())
self.updateSelectedItems(animated: true)
}
}
public func ensureMessageIsVisible(id: MessageId) {
}

View File

@ -477,8 +477,11 @@ func peerInfoScreenSettingsData(context: AccountContext, peerId: EnginePeer.Id,
|> distinctUntilChanged
let storyListContext = PeerStoryListContext(account: context.account, peerId: peerId, isArchived: false)
let hasStories: Signal<Bool, NoError> = storyListContext.state
|> map { state -> Bool in
let hasStories: Signal<Bool?, NoError> = storyListContext.state
|> map { state -> Bool? in
if !state.hasCache {
return nil
}
return !state.items.isEmpty
}
|> distinctUntilChanged
@ -564,7 +567,7 @@ func peerInfoScreenSettingsData(context: AccountContext, peerId: EnginePeer.Id,
groupsInCommon: nil,
linkedDiscussionPeer: nil,
members: nil,
storyListContext: storyListContext,
storyListContext: hasStories == true ? storyListContext : nil,
encryptionKeyFingerprint: nil,
globalSettings: globalSettings,
invitations: nil,
@ -705,8 +708,11 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
}
let storyListContext = PeerStoryListContext(account: context.account, peerId: peerId, isArchived: false)
let hasStories: Signal<Bool, NoError> = storyListContext.state
|> map { state -> Bool in
let hasStories: Signal<Bool?, NoError> = storyListContext.state
|> map { state -> Bool? in
if !state.hasCache {
return nil
}
return !state.items.isEmpty
}
|> distinctUntilChanged
@ -722,14 +728,18 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|> map { peerView, availablePanes, globalNotificationSettings, encryptionKeyFingerprint, status, hasStories -> PeerInfoScreenData in
var availablePanes = availablePanes
if hasStories, peerView.peers[peerView.peerId] is TelegramUser, peerView.peerId != context.account.peerId {
availablePanes?.insert(.stories, at: 0)
}
if availablePanes != nil, groupsInCommon != nil, let cachedData = peerView.cachedData as? CachedUserData {
if cachedData.commonGroupCount != 0 {
availablePanes?.append(.groupsInCommon)
if let hasStories {
if hasStories, peerView.peers[peerView.peerId] is TelegramUser, peerView.peerId != context.account.peerId {
availablePanes?.insert(.stories, at: 0)
}
if availablePanes != nil, groupsInCommon != nil, let cachedData = peerView.cachedData as? CachedUserData {
if cachedData.commonGroupCount != 0 {
availablePanes?.append(.groupsInCommon)
}
}
} else {
availablePanes = nil
}
return PeerInfoScreenData(

View File

@ -792,9 +792,11 @@ private func settingsItems(data: PeerInfoScreenData?, context: AccountContext, p
}
}
items[.stories]!.append(PeerInfoScreenDisclosureItem(id: 0, text: presentationData.strings.Settings_MyStories, icon: PresentationResourcesSettings.stories, action: {
interaction.openSettings(.stories)
}))
if data.storyListContext != nil || data.peer?.isPremium == true {
items[.stories]!.append(PeerInfoScreenDisclosureItem(id: 0, text: presentationData.strings.Settings_MyStories, icon: PresentationResourcesSettings.stories, action: {
interaction.openSettings(.stories)
}))
}
items[.shortcuts]!.append(PeerInfoScreenDisclosureItem(id: 1, text: presentationData.strings.Settings_SavedMessages, icon: PresentationResourcesSettings.savedMessages, action: {
interaction.openSettings(.savedMessages)