Skip to content

Commit eb3f95e

Browse files
author
Isaac
committed
Monoforums
1 parent 98dc32f commit eb3f95e

File tree

21 files changed

+264
-109
lines changed

21 files changed

+264
-109
lines changed

Telegram/Telegram-iOS/en.lproj/Localizable.strings

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14377,7 +14377,7 @@ Sorry for the inconvenience.";
1437714377
"PeerInfo.OptionTopics.Enabled" = "Enabled";
1437814378
"PeerInfo.OptionTopics.Disabled" = "Disabled";
1437914379

14380-
"ChannelMessages.Title" = "Allow Channel Messages";
14380+
"ChannelMessages.Title" = "Direct Messages";
1438114381
"ChannelMessages.Info" = "Allow users to send messages to your channel, with the option to charge a fee for each message.";
1438214382
"ChannelMessages.SwitchTitle" = "Allow Channel Messages";
1438314383
"ChannelMessages.PriceSectionTitle" = "PRICE FOR EACH MESSAGE";
@@ -14391,10 +14391,21 @@ Sorry for the inconvenience.";
1439114391
"Chat.InlineTopicMenu.AllTab" = "All";
1439214392
"Chat.ChannelMessagesHint" = "Send a message to the channel's admin";
1439314393
"Chat.ChannelMessagesHintBadge" = "NEW";
14394+
"Chat.ContextMenu.AuthorInfo" = "Sent by %@";
1439414395

14395-
"PeerInfo.AllowChannelMessages" = "Allow Channel Messages";
14396-
"PeerInfo.AllowChannelMessages.On" = "On";
14396+
"PeerInfo.AllowChannelMessages" = "Direct Messages";
14397+
"PeerInfo.AllowChannelMessages.Free" = "Free";
1439714398
"PeerInfo.AllowChannelMessages.Off" = "Off";
14398-
"PeerInfo.ChannelMessages" = "Channel Messages";
14399+
"PeerInfo.ChannelMessages" = "Direct Messages";
1439914400

1440014401
"Chat.EmptyStateMonoforum.Text" = "Send a direct message to the administrator of **%@**.";
14402+
"Chat.EmptyStateMonoforumPaid.Text" = "**%1$@** charges **%2$@**\nper message to its admin.";
14403+
14404+
"Monoforum.NameFormat" = "%@ Messages";
14405+
14406+
"Stars.SendMessage.AdjustmentTitle" = "Price for each Message";
14407+
"Stars.SendMessage.AdjustmentPlaceholder" = "Price for each Message";
14408+
"Stars.SendMessage.AdjustmentSectionHeader" = "PRICE IN STARS";
14409+
"Stars.SendMessage.AdjustmentSectionFooterValue" = "You will receive **%@ Stars**.";
14410+
"Stars.SendMessage.AdjustmentSectionFooterEmpty" = "You will receive **80%**.";
14411+
"Stars.SendMessage.AdjustmentAction" = "OK";

submodules/AvatarNode/Sources/AvatarNode.swift

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,10 @@ public final class AvatarEditOverlayNode: ASDisplayNode {
272272
}
273273
}
274274

275+
private func generateAvatarBubblePath() -> CGPath {
276+
return try! convertSvgPath("M60,30.274903 C60,46.843446 46.568544,60.274904 30,60.274904 C13.431458,60.274904 0,46.843446 0,30.274903 C0,23.634797 2.158635,17.499547 5.810547,12.529785 L6.036133,12.226074 C6.921364,10.896042 7.367402,8.104698 5.548828,5.316895 C3.606939,2.340088 1.186019,0.979668 2.399414,0.470215 C3.148032,0.156204 7.572027,0.000065 10.764648,1.790527 C12.148517,2.56662 13.2296,3.342422 14.09224,4.039734 C14.42622,4.309704 14.892063,4.349773 15.265962,4.138523 C19.618079,1.679604 24.644722,0.274902 30,0.274902 C46.568544,0.274902 60,13.70636 60,30.274903 Z ")
277+
}
278+
275279
public final class AvatarNode: ASDisplayNode {
276280
public static func avatarBubbleMask(size: CGSize) -> UIImage! {
277281
return generateImage(size, rotatedContext: { size, context in
@@ -282,19 +286,20 @@ public final class AvatarNode: ASDisplayNode {
282286
})
283287
}
284288

289+
public static let avatarBubblePath: CGPath = generateAvatarBubblePath()
290+
285291
public static func addAvatarBubblePath(context: CGContext, rect: CGRect) {
286-
if let path = try? convertSvgPath("M60,30.274903 C60,46.843446 46.568544,60.274904 30,60.274904 C13.431458,60.274904 0,46.843446 0,30.274903 C0,23.634797 2.158635,17.499547 5.810547,12.529785 L6.036133,12.226074 C6.921364,10.896042 7.367402,8.104698 5.548828,5.316895 C3.606939,2.340088 1.186019,0.979668 2.399414,0.470215 C3.148032,0.156204 7.572027,0.000065 10.764648,1.790527 C12.148517,2.56662 13.2296,3.342422 14.09224,4.039734 C14.42622,4.309704 14.892063,4.349773 15.265962,4.138523 C19.618079,1.679604 24.644722,0.274902 30,0.274902 C46.568544,0.274902 60,13.70636 60,30.274903 Z ") {
287-
let sx = rect.width / 60.0
288-
let sy = rect.height / 60.0
289-
var transform = CGAffineTransform(
290-
a: sx, b: 0.0,
291-
c: 0.0, d: -sy,
292-
tx: rect.minX,
293-
ty: rect.minY + rect.height
294-
)
295-
let transformedPath = path.copy(using: &transform)!
296-
context.addPath(transformedPath)
297-
}
292+
let path = AvatarNode.avatarBubblePath
293+
let sx = rect.width / 60.0
294+
let sy = rect.height / 60.274904
295+
var transform = CGAffineTransform(
296+
a: sx, b: 0.0,
297+
c: 0.0, d: -sy,
298+
tx: rect.minX,
299+
ty: rect.minY + rect.height
300+
)
301+
let transformedPath = path.copy(using: &transform)!
302+
context.addPath(transformedPath)
298303
}
299304

300305
public static let gradientColors: [[UIColor]] = [

submodules/ChatListUI/Sources/ChatListController.swift

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5316,20 +5316,25 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
53165316

53175317
var deleteTitle = strongSelf.presentationData.strings.Common_Delete
53185318
if case let .channel(channel) = chatPeer {
5319-
if case .broadcast = channel.info {
5319+
if channel.isMonoForum {
53205320
canClear = false
5321-
deleteTitle = strongSelf.presentationData.strings.Channel_LeaveChannel
5322-
if channel.flags.contains(.isCreator) {
5323-
canRemoveGlobally = true
5324-
}
5321+
canRemoveGlobally = false
53255322
} else {
5326-
deleteTitle = strongSelf.presentationData.strings.Group_DeleteGroup
5327-
if channel.flags.contains(.isCreator) {
5328-
canRemoveGlobally = true
5323+
if case .broadcast = channel.info {
5324+
canClear = false
5325+
deleteTitle = strongSelf.presentationData.strings.Channel_LeaveChannel
5326+
if channel.flags.contains(.isCreator) {
5327+
canRemoveGlobally = true
5328+
}
5329+
} else {
5330+
deleteTitle = strongSelf.presentationData.strings.Group_DeleteGroup
5331+
if channel.flags.contains(.isCreator) {
5332+
canRemoveGlobally = true
5333+
}
5334+
}
5335+
if let addressName = channel.addressName, !addressName.isEmpty {
5336+
canClear = false
53295337
}
5330-
}
5331-
if let addressName = channel.addressName, !addressName.isEmpty {
5332-
canClear = false
53335338
}
53345339
} else if case let .legacyGroup(group) = chatPeer {
53355340
if case .creator = group.role {

submodules/ChatListUI/Sources/Node/ChatListItem.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2980,14 +2980,18 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
29802980
if customMessageListData.commandPrefix != nil {
29812981
titleAttributedString = nil
29822982
} else {
2983-
if let displayTitle = itemPeer.chatMainPeer?.displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder) {
2983+
if let displayTitle = itemPeer.chatOrMonoforumMainPeer?.displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder) {
29842984
let textColor: UIColor
29852985
if case let .chatList(index) = item.index, index.messageIndex.id.peerId.namespace == Namespaces.Peer.SecretChat {
29862986
textColor = theme.secretTitleColor
29872987
} else {
29882988
textColor = theme.titleColor
29892989
}
29902990
titleAttributedString = NSAttributedString(string: displayTitle, font: titleFont, textColor: textColor)
2991+
2992+
if case let .channel(channel) = itemPeer.peer, channel.flags.contains(.isMonoforum) {
2993+
titleBadgeText = item.presentationData.strings.ChatList_MonoforumLabel
2994+
}
29912995
}
29922996
}
29932997
} else if let threadInfo = threadInfo {

submodules/DeleteChatPeerActionSheetItem/Sources/DeleteChatPeerActionSheetItem.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,8 @@ private final class DeleteChatPeerActionSheetItemNode: ActionSheetItemNode {
130130
text = PresentationStrings.FormattedString(string: strings.ChatList_DeleteSavedMessagesConfirmation, ranges: [])
131131
} else if case let .legacyGroup(chatPeer) = chatPeer {
132132
text = strings.ChatList_DeleteAndLeaveGroupConfirmation(chatPeer.title)
133-
} else if case let .channel(chatPeer) = chatPeer {
134-
text = strings.ChatList_DeleteAndLeaveGroupConfirmation(chatPeer.title)
133+
} else if case .channel = chatPeer {
134+
text = strings.ChatList_DeleteAndLeaveGroupConfirmation(peer.compactDisplayTitle)
135135
} else if case .secretChat = chatPeer {
136136
text = strings.ChatList_DeleteSecretChatConfirmation(peer.displayTitle(strings: strings, displayOrder: nameOrder))
137137
} else {

submodules/Postbox/Sources/Peer.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@ public protocol Peer: AnyObject, PostboxCoding {
298298
var id: PeerId { get }
299299
var indexName: PeerIndexNameRepresentation { get }
300300
var associatedPeerId: PeerId? { get }
301+
var additionalAssociatedPeerId: PeerId? { get }
301302
var associatedPeerOverridesIdentity: Bool { get }
302303
var notificationSettingsPeerId: PeerId? { get }
303304
var associatedMediaIds: [MediaId]? { get }
@@ -307,6 +308,7 @@ public protocol Peer: AnyObject, PostboxCoding {
307308
}
308309

309310
public extension Peer {
311+
var additionalAssociatedPeerId: PeerId? { return nil }
310312
var associatedPeerOverridesIdentity: Bool { return false }
311313
}
312314

submodules/Postbox/Sources/PeerView.swift

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,23 @@ final class MutablePeerView: MutablePostboxView {
4848
var messageIds = Set<MessageId>()
4949
peerIds.insert(peerId)
5050

51-
if let peer = getPeer(peerId), let associatedPeerId = peer.associatedPeerId {
52-
peerIds.insert(associatedPeerId)
53-
54-
if peer.associatedPeerOverridesIdentity {
55-
self.contactPeerId = associatedPeerId
56-
self.peerIsContact = postbox.contactsTable.isContact(peerId: associatedPeerId)
51+
if let peer = getPeer(peerId) {
52+
if let associatedPeerId = peer.associatedPeerId {
53+
peerIds.insert(associatedPeerId)
54+
55+
if peer.associatedPeerOverridesIdentity {
56+
self.contactPeerId = associatedPeerId
57+
self.peerIsContact = postbox.contactsTable.isContact(peerId: associatedPeerId)
58+
} else {
59+
self.contactPeerId = peerId
60+
}
5761
} else {
5862
self.contactPeerId = peerId
5963
}
64+
65+
if let additionalAssociatedPeerId = peer.additionalAssociatedPeerId {
66+
peerIds.insert(additionalAssociatedPeerId)
67+
}
6068
} else {
6169
self.contactPeerId = peerId
6270
}
@@ -96,6 +104,11 @@ final class MutablePeerView: MutablePostboxView {
96104
} else {
97105
self.notificationSettings = postbox.peerNotificationSettingsTable.getEffective(peerId)
98106
}
107+
if let peer = self.peers[peerId], let additionalAssociatedPeerId = peer.additionalAssociatedPeerId {
108+
if let peer = getPeer(additionalAssociatedPeerId) {
109+
self.peers[additionalAssociatedPeerId] = peer
110+
}
111+
}
99112
for id in messageIds {
100113
if let message = postbox.getMessage(id) {
101114
self.messages[id] = message
@@ -141,8 +154,13 @@ final class MutablePeerView: MutablePostboxView {
141154

142155
var peerIds = Set<PeerId>()
143156
peerIds.insert(self.peerId)
144-
if let peer = getPeer(self.peerId), let associatedPeerId = peer.associatedPeerId {
145-
peerIds.insert(associatedPeerId)
157+
if let peer = getPeer(self.peerId) {
158+
if let associatedPeerId = peer.associatedPeerId {
159+
peerIds.insert(associatedPeerId)
160+
}
161+
if let additionalAssociatedPeerId = peer.additionalAssociatedPeerId {
162+
peerIds.insert(additionalAssociatedPeerId)
163+
}
146164
}
147165
peerIds.formUnion(cachedData.peerIds)
148166

@@ -186,8 +204,13 @@ final class MutablePeerView: MutablePostboxView {
186204
} else {
187205
var peerIds = Set<PeerId>()
188206
peerIds.insert(self.peerId)
189-
if let peer = getPeer(self.peerId), let associatedPeerId = peer.associatedPeerId {
190-
peerIds.insert(associatedPeerId)
207+
if let peer = getPeer(self.peerId) {
208+
if let associatedPeerId = peer.associatedPeerId {
209+
peerIds.insert(associatedPeerId)
210+
}
211+
if let additionalAssociatedPeerId = peer.additionalAssociatedPeerId {
212+
peerIds.insert(additionalAssociatedPeerId)
213+
}
191214
}
192215
if let cachedData = self.cachedData {
193216
peerIds.formUnion(cachedData.peerIds)

submodules/ShareController/Sources/ShareControllerNode.swift

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1285,12 +1285,16 @@ final class ShareControllerNode: ViewControllerTracingNode, ASScrollViewDelegate
12851285
}
12861286
)
12871287
|> take(1)
1288-
|> map { views -> ([EnginePeer.Id: EnginePeer?], [EnginePeer.Id: Int64]) in
1289-
var result: [EnginePeer.Id: EnginePeer?] = [:]
1288+
|> map { views -> ([EnginePeer.Id: EngineRenderedPeer?], [EnginePeer.Id: Int64]) in
1289+
var result: [EnginePeer.Id: EngineRenderedPeer?] = [:]
12901290
var requiresStars: [EnginePeer.Id: Int64] = [:]
12911291
for peerId in peerIds {
12921292
if let view = views.views[PostboxViewKey.basicPeer(peerId)] as? PeerView, let peer = peerViewMainPeer(view) {
1293-
result[peerId] = EnginePeer(peer)
1293+
var peers: [EnginePeer.Id: EnginePeer] = [peer.id: EnginePeer(peer)]
1294+
if let channel = peer as? TelegramChannel, channel.isMonoForum, let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = view.peers[linkedMonoforumId] {
1295+
peers[mainChannel.id] = EnginePeer(mainChannel)
1296+
}
1297+
result[peerId] = EngineRenderedPeer(peerId: peer.id, peers: peers, associatedMedia: [:])
12941298
if peer is TelegramUser, let cachedPeerDataView = views.views[PostboxViewKey.cachedPeerData(peerId: peerId)] as? CachedPeerDataView {
12951299
if let cachedData = cachedPeerDataView.cachedPeerData as? CachedUserData {
12961300
requiresStars[peerId] = cachedData.sendPaidMessageStars?.value
@@ -1307,14 +1311,14 @@ final class ShareControllerNode: ViewControllerTracingNode, ASScrollViewDelegate
13071311
return
13081312
}
13091313

1310-
var mappedPeers: [EnginePeer] = []
1314+
var mappedPeers: [EngineRenderedPeer] = []
13111315
for peerId in peerIds {
13121316
if let maybePeer = peers[peerId], let peer = maybePeer {
13131317
mappedPeers.append(peer)
13141318
}
13151319
}
13161320

1317-
if !tryShare(self.inputFieldNode.text, mappedPeers) {
1321+
if !tryShare(self.inputFieldNode.text, mappedPeers.compactMap(\.peer)) {
13181322
return
13191323
}
13201324

@@ -1328,15 +1332,15 @@ final class ShareControllerNode: ViewControllerTracingNode, ASScrollViewDelegate
13281332
}
13291333
}
13301334

1331-
private func presentPaidMessageAlertIfNeeded(peers: [EnginePeer], requiresStars: [EnginePeer.Id: Int64], completion: @escaping () -> Void) {
1335+
private func presentPaidMessageAlertIfNeeded(peers: [EngineRenderedPeer], requiresStars: [EnginePeer.Id: Int64], completion: @escaping () -> Void) {
13321336
var count: Int32 = Int32(self.messageCount)
13331337
if !self.inputFieldNode.text.isEmpty {
13341338
count += 1
13351339
}
1336-
var chargingPeers: [EnginePeer] = []
1340+
var chargingPeers: [EngineRenderedPeer] = []
13371341
var totalAmount: StarsAmount = .zero
13381342
for peer in peers {
1339-
if let stars = requiresStars[peer.id] {
1343+
if let stars = requiresStars[peer.peerId] {
13401344
chargingPeers.append(peer)
13411345
totalAmount = totalAmount + StarsAmount(value: stars, nanos: 0)
13421346
}

submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramChannel.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,10 @@ public final class TelegramChannel: Peer, Equatable {
223223
}
224224
}
225225

226+
public var additionalAssociatedPeerId: PeerId? {
227+
self.linkedMonoforumId
228+
}
229+
226230
public var indexName: PeerIndexNameRepresentation {
227231
var addressNames = self.usernames.map { $0.username }
228232
if addressNames.isEmpty, let username = self.username, !username.isEmpty {

submodules/TelegramUI/Components/Chat/ChatMessagePaymentAlertController/Sources/ChatMessagePaymentAlertController.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ public func chatMessagePaymentAlertController(
422422
context: AccountContext?,
423423
presentationData: PresentationData,
424424
updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?,
425-
peers: [EnginePeer],
425+
peers: [EngineRenderedPeer],
426426
count: Int32,
427427
amount: StarsAmount,
428428
totalAmount: StarsAmount?,
@@ -452,10 +452,10 @@ public func chatMessagePaymentAlertController(
452452
if peers.count == 1, let peer = peers.first {
453453
let amountString = presentationData.strings.Chat_PaidMessage_Confirm_Text_Stars(Int32(amount.value))
454454
let totalString = presentationData.strings.Chat_PaidMessage_Confirm_Text_Stars(Int32(amount.value * Int64(count)))
455-
if case let .channel(channel) = peer, case .broadcast = channel.info {
456-
text = presentationData.strings.Chat_PaidMessage_Confirm_SingleComment_Text(peer.compactDisplayTitle, amountString, totalString, messagesString).string
455+
if case let .channel(channel) = peer.chatOrMonoforumMainPeer, case .broadcast = channel.info {
456+
text = presentationData.strings.Chat_PaidMessage_Confirm_SingleComment_Text(EnginePeer(channel).compactDisplayTitle, amountString, totalString, messagesString).string
457457
} else {
458-
text = presentationData.strings.Chat_PaidMessage_Confirm_Single_Text(peer.compactDisplayTitle, amountString, totalString, messagesString).string
458+
text = presentationData.strings.Chat_PaidMessage_Confirm_Single_Text(peer.chatOrMonoforumMainPeer?.compactDisplayTitle ?? " ", amountString, totalString, messagesString).string
459459
}
460460
} else {
461461
let amount = totalAmount ?? amount

0 commit comments

Comments
 (0)