[WIP] Saved messages

This commit is contained in:
Isaac 2023-12-12 14:06:19 +04:00
parent c3b77b11c0
commit a4e2c4f398
6 changed files with 426 additions and 0 deletions

View File

@ -0,0 +1,29 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "PeerInfoChatListPaneNode",
module_name = "PeerInfoChatListPaneNode",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = [
"//submodules/SSignalKit/SwiftSignalKit",
"//submodules/AsyncDisplayKit",
"//submodules/TelegramCore",
"//submodules/Postbox",
"//submodules/TelegramPresentationData",
"//submodules/AccountContext",
"//submodules/TelegramStringFormatting",
"//submodules/ShimmerEffect",
"//submodules/ComponentFlow",
"//submodules/AppBundle",
"//submodules/ChatListUI",
"//submodules/TelegramUI/Components/PeerInfo/PeerInfoPaneNode",
],
visibility = [
"//visibility:public",
],
)

View File

@ -0,0 +1,205 @@
import AsyncDisplayKit
import Display
import TelegramCore
import SwiftSignalKit
import Postbox
import TelegramPresentationData
import AccountContext
import ContextUI
import TelegramStringFormatting
import ShimmerEffect
import ComponentFlow
import TelegramNotices
import TelegramUIPreferences
import AppBundle
import PeerInfoPaneNode
import ChatListUI
public final class PeerInfoChatListPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScrollViewDelegate, UIGestureRecognizerDelegate {
private let context: AccountContext
private let navigationController: () -> NavigationController?
public weak var parentController: ViewController?
private var currentParams: (size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData)?
private let ready = Promise<Bool>()
private var didSetReady: Bool = false
public var isReady: Signal<Bool, NoError> {
return self.ready.get()
}
private let statusPromise = Promise<PeerInfoStatusData?>(nil)
public var status: Signal<PeerInfoStatusData?, NoError> {
self.statusPromise.get()
}
public var tabBarOffsetUpdated: ((ContainedViewLayoutTransition) -> Void)?
public var tabBarOffset: CGFloat {
return 0.0
}
private var presentationData: PresentationData
private var presentationDataDisposable: Disposable?
private let chatListNode: ChatListNode
public init(context: AccountContext, navigationController: @escaping () -> NavigationController?) {
self.context = context
self.navigationController = navigationController
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
self.chatListNode = ChatListNode(
context: self.context,
location: .savedMessagesChats,
chatListFilter: nil,
previewing: false,
fillPreloadItems: false,
mode: .chatList(appendContacts: false),
isPeerEnabled: nil,
theme: self.presentationData.theme,
fontSize: self.presentationData.listsFontSize,
strings: self.presentationData.strings,
dateTimeFormat: self.presentationData.dateTimeFormat,
nameSortOrder: self.presentationData.nameSortOrder,
nameDisplayOrder: self.presentationData.nameDisplayOrder,
animationCache: self.context.animationCache,
animationRenderer: self.context.animationRenderer,
disableAnimations: false,
isInlineMode: false,
autoSetReady: false,
isMainTab: nil
)
super.init()
self.addSubnode(self.chatListNode)
self.presentationDataDisposable = (self.context.sharedContext.presentationData
|> deliverOnMainQueue).start(next: { [weak self] presentationData in
guard let self else {
return
}
self.presentationData = presentationData
})
self.ready.set(self.chatListNode.ready)
self.chatListNode.peerSelected = { [weak self] peer, _, _, _, _ in
guard let self, let navigationController = self.navigationController() else {
return
}
self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(
navigationController: navigationController,
context: self.context,
chatLocation: .replyThread(ChatReplyThreadMessage(
messageId: makeThreadIdMessageId(
peerId: self.context.account.peerId,
threadId: peer.id.toInt64()
),
channelMessageId: nil,
isChannelPost: false,
isForumPost: false,
maxMessage: nil,
maxReadIncomingMessageId: nil,
maxReadOutgoingMessageId: nil,
unreadCount: 0,
initialFilledHoles: IndexSet(),
initialAnchor: .automatic,
isNotAvailable: false
)),
subject: nil,
keepStack: .always
))
self.chatListNode.clearHighlightAnimated(true)
}
}
deinit {
self.presentationDataDisposable?.dispose()
}
public func ensureMessageIsVisible(id: MessageId) {
}
public func scrollToTop() -> Bool {
return false
}
public func hitTestResultForScrolling() -> UIView? {
return nil
}
public func brieflyDisableTouchActions() {
}
public func findLoadedMessage(id: MessageId) -> Message? {
return nil
}
public func updateHiddenMedia() {
}
public func transferVelocity(_ velocity: CGFloat) {
}
public func cancelPreviewGestures() {
}
public func transitionNodeForGallery(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
return nil
}
public func addToTransitionSurface(view: UIView) {
}
override public func didLoad() {
super.didLoad()
}
override public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
if gestureRecognizer.state != .failed, let otherGestureRecognizer = otherGestureRecognizer as? UIPanGestureRecognizer {
let _ = otherGestureRecognizer
return true
} else {
return false
}
}
public func updateSelectedMessages(animated: Bool) {
}
public func update(size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) {
self.currentParams = (size, topInset, sideInset, bottomInset, visibleHeight, isScrollingLockedAtTop, expandProgress, presentationData)
transition.updateFrame(node: self.chatListNode, frame: CGRect(origin: CGPoint(), size: size))
let (duration, curve) = listViewAnimationDurationAndCurve(transition: transition)
self.chatListNode.updateLayout(
transition: transition,
updateSizeAndInsets: ListViewUpdateSizeAndInsets(
size: size,
insets: UIEdgeInsets(top: topInset, left: sideInset, bottom: bottomInset, right: sideInset),
duration: duration,
curve: curve
),
visibleTopInset: topInset,
originalTopInset: topInset,
storiesInset: 0.0,
inlineNavigationLocation: nil,
inlineNavigationTransitionFraction: 0.0
)
}
override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
guard let result = super.hitTest(point, with: event) else {
return nil
}
return result
}
}

View File

@ -0,0 +1,23 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "PeerInfoPaneNode",
module_name = "PeerInfoPaneNode",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = [
"//submodules/SSignalKit/SwiftSignalKit",
"//submodules/Postbox",
"//submodules/TelegramCore",
"//submodules/AsyncDisplayKit",
"//submodules/Display",
"//submodules/TelegramPresentationData",
],
visibility = [
"//visibility:public",
],
)

View File

@ -0,0 +1,57 @@
import SwiftSignalKit
import Postbox
import TelegramCore
import AsyncDisplayKit
import Display
import TelegramPresentationData
public enum PeerInfoPaneKey: Int32 {
case members
case stories
case media
case files
case music
case voice
case links
case gifs
case groupsInCommon
case recommended
case savedMessagesChats
}
public struct PeerInfoStatusData: Equatable {
public var text: String
public var isActivity: Bool
public var key: PeerInfoPaneKey?
public init(
text: String,
isActivity: Bool,
key: PeerInfoPaneKey?
) {
self.text = text
self.isActivity = isActivity
self.key = key
}
}
public protocol PeerInfoPaneNode: ASDisplayNode {
var isReady: Signal<Bool, NoError> { get }
var parentController: ViewController? { get set }
var status: Signal<PeerInfoStatusData?, NoError> { get }
var tabBarOffsetUpdated: ((ContainedViewLayoutTransition) -> Void)? { get set }
var tabBarOffset: CGFloat { get }
func update(size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition)
func scrollToTop() -> Bool
func transferVelocity(_ velocity: CGFloat)
func cancelPreviewGestures()
func findLoadedMessage(id: MessageId) -> Message?
func transitionNodeForGallery(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?
func addToTransitionSurface(view: UIView)
func updateHiddenMedia()
func updateSelectedMessages(animated: Bool)
func ensureMessageIsVisible(id: MessageId)
}

View File

@ -0,0 +1,26 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "SavedMessagesScreen",
module_name = "SavedMessagesScreen",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = [
"//submodules/SSignalKit/SwiftSignalKit",
"//submodules/Display",
"//submodules/TelegramCore",
"//submodules/Postbox",
"//submodules/TelegramPresentationData",
"//submodules/AccountContext",
"//submodules/ComponentFlow",
"//submodules/Components/ViewControllerComponent",
"//submodules/Components/ComponentDisplayAdapters",
],
visibility = [
"//visibility:public",
],
)

View File

@ -0,0 +1,86 @@
import Foundation
import AsyncDisplayKit
import Display
import ComponentFlow
import ComponentDisplayAdapters
import TelegramCore
import AccountContext
import SwiftSignalKit
import ViewControllerComponent
private final class SavedMessagesScreenComponent: Component {
public let context: AccountContext
public init(
context: AccountContext
) {
self.context = context
}
public static func ==(lhs: SavedMessagesScreenComponent, rhs: SavedMessagesScreenComponent) -> Bool {
if lhs.context !== rhs.context {
return false
}
return true
}
public final class View: UIView {
private var component: SavedMessagesScreenComponent?
private var state: EmptyComponentState?
private var environment: ViewControllerComponentContainer.Environment?
override public init(frame: CGRect) {
super.init(frame: frame)
self.clipsToBounds = true
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
deinit {
}
func update(component: SavedMessagesScreenComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<ViewControllerComponentContainer.Environment>, transition: Transition) -> CGSize {
let environment = environment[ViewControllerComponentContainer.Environment.self].value
let themeUpdated = self.environment?.theme !== environment.theme
self.environment = environment
self.component = component
self.state = state
if themeUpdated {
self.backgroundColor = environment.theme.list.plainBackgroundColor
}
return availableSize
}
}
public func makeView() -> View {
return View(frame: CGRect())
}
public func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment<ViewControllerComponentContainer.Environment>, transition: Transition) -> CGSize {
return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition)
}
}
public class SavedMessagesScreen: ViewControllerComponentContainer {
private let context: AccountContext
public init(context: AccountContext) {
self.context = context
super.init(context: context, component: SavedMessagesScreenComponent(context: context), navigationBarAppearance: .none)
}
required public init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
deinit {
}
}