mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-09-02 10:50:11 +00:00
Support multiple pinned threads
This commit is contained in:
parent
f1864a43b9
commit
fa95906962
@ -8241,3 +8241,6 @@ Sorry for the inconvenience.";
|
|||||||
"Attachment.DiscardPasteboardAlertText" = "Discard pasted items?";
|
"Attachment.DiscardPasteboardAlertText" = "Discard pasted items?";
|
||||||
|
|
||||||
"Undo.DeletedTopic" = "Topic Deleted";
|
"Undo.DeletedTopic" = "Topic Deleted";
|
||||||
|
|
||||||
|
"ChatList.MaxThreadPinsFinalText_1" = "Sorry, you can't pin more than **%@** thread to the top. Unpin some that are currently pinned.";
|
||||||
|
"ChatList.MaxThreadPinsFinalText_any" = "Sorry, you can't pin more than **%@** threads to the top. Unpin some that are currently pinned.";
|
||||||
|
@ -519,7 +519,19 @@ func chatForumTopicMenuItems(context: AccountContext, peerId: PeerId, threadId:
|
|||||||
items.append(.action(ContextMenuActionItem(text: isPinned ? presentationData.strings.ChatList_Context_Unpin : presentationData.strings.ChatList_Context_Pin, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: isPinned ? "Chat/Context Menu/Unpin": "Chat/Context Menu/Pin"), color: theme.contextMenu.primaryColor) }, action: { _, f in
|
items.append(.action(ContextMenuActionItem(text: isPinned ? presentationData.strings.ChatList_Context_Unpin : presentationData.strings.ChatList_Context_Pin, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: isPinned ? "Chat/Context Menu/Unpin": "Chat/Context Menu/Pin"), color: theme.contextMenu.primaryColor) }, action: { _, f in
|
||||||
f(.default)
|
f(.default)
|
||||||
|
|
||||||
let _ = context.engine.peers.toggleForumChannelTopicPinned(id: peerId, threadId: threadId).start()
|
let _ = (context.engine.peers.toggleForumChannelTopicPinned(id: peerId, threadId: threadId)
|
||||||
|
|> deliverOnMainQueue).start(error: { error in
|
||||||
|
switch error {
|
||||||
|
case let .limitReached(count):
|
||||||
|
if let chatListController = chatListController {
|
||||||
|
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
|
let text = presentationData.strings.ChatList_MaxThreadPinsFinalText(Int32(count))
|
||||||
|
chatListController.present(textAlertController(context: context, title: presentationData.strings.Premium_LimitReached, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})], parseMarkdown: true), in: .window(.root))
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
})
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1697,85 +1697,160 @@ public final class ChatListNode: ListView {
|
|||||||
})
|
})
|
||||||
|
|
||||||
self.reorderItem = { [weak self] fromIndex, toIndex, transactionOpaqueState -> Signal<Bool, NoError> in
|
self.reorderItem = { [weak self] fromIndex, toIndex, transactionOpaqueState -> Signal<Bool, NoError> in
|
||||||
if let strongSelf = self, let filteredEntries = (transactionOpaqueState as? ChatListOpaqueTransactionState)?.chatListView.filteredEntries {
|
guard let strongSelf = self, let filteredEntries = (transactionOpaqueState as? ChatListOpaqueTransactionState)?.chatListView.filteredEntries else {
|
||||||
guard case let .chatList(groupId) = strongSelf.location else {
|
return .single(false)
|
||||||
return .single(false)
|
}
|
||||||
|
guard fromIndex >= 0 && fromIndex < filteredEntries.count && toIndex >= 0 && toIndex < filteredEntries.count else {
|
||||||
|
return .single(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch strongSelf.location {
|
||||||
|
case let .chatList(groupId):
|
||||||
|
let fromEntry = filteredEntries[filteredEntries.count - 1 - fromIndex]
|
||||||
|
let toEntry = filteredEntries[filteredEntries.count - 1 - toIndex]
|
||||||
|
|
||||||
|
var referenceId: EngineChatList.PinnedItem.Id?
|
||||||
|
var beforeAll = false
|
||||||
|
switch toEntry {
|
||||||
|
case let .PeerEntry(index, _, _, _, _, _, _, _, _, _, _, _, _, _, _, promoInfo, _, _, _):
|
||||||
|
if promoInfo != nil {
|
||||||
|
beforeAll = true
|
||||||
|
} else {
|
||||||
|
if case let .chatList(chatListIndex) = index {
|
||||||
|
referenceId = .peer(chatListIndex.messageIndex.id.peerId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if fromIndex >= 0 && fromIndex < filteredEntries.count && toIndex >= 0 && toIndex < filteredEntries.count {
|
if case let .index(index) = fromEntry.sortIndex, case let .chatList(chatListIndex) = index, let _ = chatListIndex.pinningIndex {
|
||||||
let fromEntry = filteredEntries[filteredEntries.count - 1 - fromIndex]
|
let location: TogglePeerChatPinnedLocation
|
||||||
let toEntry = filteredEntries[filteredEntries.count - 1 - toIndex]
|
if let chatListFilter = chatListFilter {
|
||||||
|
location = .filter(chatListFilter.id)
|
||||||
|
} else {
|
||||||
|
location = .group(groupId._asGroup())
|
||||||
|
}
|
||||||
|
|
||||||
var referenceId: EngineChatList.PinnedItem.Id?
|
let engine = strongSelf.context.engine
|
||||||
var beforeAll = false
|
return engine.peers.getPinnedItemIds(location: location)
|
||||||
switch toEntry {
|
|> mapToSignal { itemIds -> Signal<Bool, NoError> in
|
||||||
case let .PeerEntry(index, _, _, _, _, _, _, _, _, _, _, _, _, _, _, promoInfo, _, _, _):
|
var itemIds = itemIds
|
||||||
if promoInfo != nil {
|
|
||||||
beforeAll = true
|
var itemId: EngineChatList.PinnedItem.Id?
|
||||||
} else {
|
switch fromEntry {
|
||||||
if case let .chatList(chatListIndex) = index {
|
case let .PeerEntry(index, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||||
referenceId = .peer(chatListIndex.messageIndex.id.peerId)
|
if case let .chatList(index) = index {
|
||||||
|
itemId = .peer(index.messageIndex.id.peerId)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
|
||||||
|
|
||||||
if case let .index(index) = fromEntry.sortIndex, case let .chatList(chatListIndex) = index, let _ = chatListIndex.pinningIndex {
|
|
||||||
let location: TogglePeerChatPinnedLocation
|
|
||||||
if let chatListFilter = chatListFilter {
|
|
||||||
location = .filter(chatListFilter.id)
|
|
||||||
} else {
|
|
||||||
location = .group(groupId._asGroup())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let engine = strongSelf.context.engine
|
if let itemId = itemId {
|
||||||
return engine.peers.getPinnedItemIds(location: location)
|
itemIds = itemIds.filter({ $0 != itemId })
|
||||||
|> mapToSignal { itemIds -> Signal<Bool, NoError> in
|
if let referenceId = referenceId {
|
||||||
var itemIds = itemIds
|
var inserted = false
|
||||||
|
for i in 0 ..< itemIds.count {
|
||||||
var itemId: EngineChatList.PinnedItem.Id?
|
if itemIds[i] == referenceId {
|
||||||
switch fromEntry {
|
if fromIndex < toIndex {
|
||||||
case let .PeerEntry(index, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
itemIds.insert(itemId, at: i + 1)
|
||||||
if case let .chatList(index) = index {
|
} else {
|
||||||
itemId = .peer(index.messageIndex.id.peerId)
|
itemIds.insert(itemId, at: i)
|
||||||
}
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if let itemId = itemId {
|
|
||||||
itemIds = itemIds.filter({ $0 != itemId })
|
|
||||||
if let referenceId = referenceId {
|
|
||||||
var inserted = false
|
|
||||||
for i in 0 ..< itemIds.count {
|
|
||||||
if itemIds[i] == referenceId {
|
|
||||||
if fromIndex < toIndex {
|
|
||||||
itemIds.insert(itemId, at: i + 1)
|
|
||||||
} else {
|
|
||||||
itemIds.insert(itemId, at: i)
|
|
||||||
}
|
|
||||||
inserted = true
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
inserted = true
|
||||||
|
break
|
||||||
}
|
}
|
||||||
if !inserted {
|
}
|
||||||
itemIds.append(itemId)
|
if !inserted {
|
||||||
}
|
|
||||||
} else if beforeAll {
|
|
||||||
itemIds.insert(itemId, at: 0)
|
|
||||||
} else {
|
|
||||||
itemIds.append(itemId)
|
itemIds.append(itemId)
|
||||||
}
|
}
|
||||||
return engine.peers.reorderPinnedItemIds(location: location, itemIds: itemIds)
|
} else if beforeAll {
|
||||||
|
itemIds.insert(itemId, at: 0)
|
||||||
} else {
|
} else {
|
||||||
return .single(false)
|
itemIds.append(itemId)
|
||||||
}
|
}
|
||||||
|
return engine.peers.reorderPinnedItemIds(location: location, itemIds: itemIds)
|
||||||
|
} else {
|
||||||
|
return .single(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return .single(false)
|
||||||
|
}
|
||||||
|
case let .forum(peerId):
|
||||||
|
let fromEntry = filteredEntries[filteredEntries.count - 1 - fromIndex]
|
||||||
|
let toEntry = filteredEntries[filteredEntries.count - 1 - toIndex]
|
||||||
|
|
||||||
|
var referenceId: Int64?
|
||||||
|
var beforeAll = false
|
||||||
|
switch toEntry {
|
||||||
|
case let .PeerEntry(index, _, _, _, _, _, _, _, _, _, _, _, _, _, _, promoInfo, _, _, _):
|
||||||
|
if promoInfo != nil {
|
||||||
|
beforeAll = true
|
||||||
|
} else {
|
||||||
|
if case let .forum(_, _, threadId, _, _) = index {
|
||||||
|
referenceId = threadId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if case let .index(index) = fromEntry.sortIndex, case let .forum(pinningIndex, _, _, _, _) = index, case .index = pinningIndex {
|
||||||
|
let engine = strongSelf.context.engine
|
||||||
|
return engine.peers.getForumChannelPinnedTopics(id: peerId)
|
||||||
|
|> mapToSignal { itemIds -> Signal<Bool, NoError> in
|
||||||
|
var itemIds = itemIds
|
||||||
|
|
||||||
|
var itemId: Int64?
|
||||||
|
switch fromEntry {
|
||||||
|
case let .PeerEntry(index, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||||
|
if case let .forum(_, _, threadId, _, _) = index {
|
||||||
|
itemId = threadId
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if let itemId = itemId {
|
||||||
|
itemIds = itemIds.filter({ $0 != itemId })
|
||||||
|
if let referenceId = referenceId {
|
||||||
|
var inserted = false
|
||||||
|
for i in 0 ..< itemIds.count {
|
||||||
|
if itemIds[i] == referenceId {
|
||||||
|
if fromIndex < toIndex {
|
||||||
|
itemIds.insert(itemId, at: i + 1)
|
||||||
|
} else {
|
||||||
|
itemIds.insert(itemId, at: i)
|
||||||
|
}
|
||||||
|
inserted = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !inserted {
|
||||||
|
itemIds.append(itemId)
|
||||||
|
}
|
||||||
|
} else if beforeAll {
|
||||||
|
itemIds.insert(itemId, at: 0)
|
||||||
|
} else {
|
||||||
|
itemIds.append(itemId)
|
||||||
|
}
|
||||||
|
return engine.peers.setForumChannelPinnedTopics(id: peerId, threadIds: itemIds)
|
||||||
|
|> map { _ -> Bool in
|
||||||
|
}
|
||||||
|
|> `catch` { _ -> Signal<Bool, NoError> in
|
||||||
|
return .single(false)
|
||||||
|
}
|
||||||
|
|> then(Signal<Bool, NoError>.single(true))
|
||||||
|
} else {
|
||||||
|
return .single(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return .single(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return .single(false)
|
|
||||||
}
|
}
|
||||||
var startedScrollingAtUpperBound = false
|
var startedScrollingAtUpperBound = false
|
||||||
|
|
||||||
|
@ -386,6 +386,12 @@ func _internal_setForumChannelPinnedTopics(account: Account, id: EnginePeer.Id,
|
|||||||
return .fail(.generic)
|
return .fail(.generic)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
if "".isEmpty {
|
||||||
|
return .complete()
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return account.network.request(Api.functions.channels.reorderPinnedForumTopics(
|
return account.network.request(Api.functions.channels.reorderPinnedForumTopics(
|
||||||
channel: inputChannel,
|
channel: inputChannel,
|
||||||
order: threadIds.map(Int32.init(clamping:))
|
order: threadIds.map(Int32.init(clamping:))
|
||||||
|
@ -878,6 +878,12 @@ public extension TelegramEngine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func getForumChannelPinnedTopics(id: EnginePeer.Id) -> Signal<[Int64], NoError> {
|
||||||
|
return self.account.postbox.transaction { transcation -> [Int64] in
|
||||||
|
return transcation.getPeerPinnedThreads(peerId: id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public func setForumChannelPinnedTopics(id: EnginePeer.Id, threadIds: [Int64]) -> Signal<Never, SetForumChannelTopicPinnedError> {
|
public func setForumChannelPinnedTopics(id: EnginePeer.Id, threadIds: [Int64]) -> Signal<Never, SetForumChannelTopicPinnedError> {
|
||||||
return _internal_setForumChannelPinnedTopics(account: self.account, id: id, threadIds: threadIds)
|
return _internal_setForumChannelPinnedTopics(account: self.account, id: id, threadIds: threadIds)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user