mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-08 19:10:53 +00:00
Group stats improvements
This commit is contained in:
parent
9f50fa0640
commit
6b56018756
@ -5565,6 +5565,7 @@ Any member of this group will be able to see messages in the channel.";
|
||||
"Stats.GroupMessagesTitle" = "MESSAGES";
|
||||
"Stats.GroupActionsTitle" = "ACTIONS";
|
||||
"Stats.GroupTopHoursTitle" = "TOP HOURS";
|
||||
"Stats.GroupTopWeekdaysTitle" = "TOP DAYS OF WEEK";
|
||||
"Stats.GroupTopPostersTitle" = "TOP MEMBERS";
|
||||
"Stats.GroupTopAdminsTitle" = "TOP ADMINS";
|
||||
"Stats.GroupTopInvitersTitle" = "TOP INVITERS";
|
||||
@ -5583,6 +5584,9 @@ Any member of this group will be able to see messages in the channel.";
|
||||
"Stats.GroupTopPosterChars_many" = "%@ symbols per message";
|
||||
"Stats.GroupTopPosterChars_any" = "%@ symbols per message";
|
||||
|
||||
"Stats.GroupTopPoster.History" = "History";
|
||||
"Stats.GroupTopPoster.Promote" = "Promote";
|
||||
|
||||
"Stats.GroupTopAdminDeletions_0" = "%@ deletions";
|
||||
"Stats.GroupTopAdminDeletions_1" = "%@ deletion";
|
||||
"Stats.GroupTopAdminDeletions_2" = "%@ deletions";
|
||||
@ -5604,9 +5608,15 @@ Any member of this group will be able to see messages in the channel.";
|
||||
"Stats.GroupTopAdminBans_many" = "%@ bans";
|
||||
"Stats.GroupTopAdminBans_any" = "%@ bans";
|
||||
|
||||
"Stats.GroupTopAdmin.Actions" = "Actions";
|
||||
"Stats.GroupTopAdmin.Promote" = "Promote";
|
||||
|
||||
"Stats.GroupTopInviterInvites_0" = "%@ invitations";
|
||||
"Stats.GroupTopInviterInvites_1" = "%@ invitation";
|
||||
"Stats.GroupTopInviterInvites_2" = "%@ invitations";
|
||||
"Stats.GroupTopInviterInvites_3_10" = "%@ invitations";
|
||||
"Stats.GroupTopInviterInvites_many" = "%@ invitations";
|
||||
"Stats.GroupTopInviterInvites_any" = "%@ invitations";
|
||||
|
||||
"Stats.GroupTopInviter.History" = "History";
|
||||
"Stats.GroupTopInviter.Promote" = "Promote";
|
||||
|
@ -214,6 +214,34 @@ public final class ChatPeerNearbyData: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
public enum ChatSearchDomain: Equatable {
|
||||
case everything
|
||||
case members
|
||||
case member(Peer)
|
||||
|
||||
public static func ==(lhs: ChatSearchDomain, rhs: ChatSearchDomain) -> Bool {
|
||||
switch lhs {
|
||||
case .everything:
|
||||
if case .everything = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case .members:
|
||||
if case .members = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .member(lhsPeer):
|
||||
if case let .member(rhsPeer) = rhs, lhsPeer.isEqual(rhsPeer) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public final class NavigateToChatControllerParams {
|
||||
public let navigationController: NavigationController
|
||||
public let chatController: ChatController?
|
||||
@ -227,7 +255,7 @@ public final class NavigateToChatControllerParams {
|
||||
public let useExisting: Bool
|
||||
public let purposefulAction: (() -> Void)?
|
||||
public let scrollToEndIfExists: Bool
|
||||
public let activateMessageSearch: Bool
|
||||
public let activateMessageSearch: (ChatSearchDomain, String)?
|
||||
public let peekData: ChatPeekTimeout?
|
||||
public let peerNearbyData: ChatPeerNearbyData?
|
||||
public let animated: Bool
|
||||
@ -235,7 +263,7 @@ public final class NavigateToChatControllerParams {
|
||||
public let parentGroupId: PeerGroupId?
|
||||
public let completion: (ChatController) -> Void
|
||||
|
||||
public init(navigationController: NavigationController, chatController: ChatController? = nil, context: AccountContext, chatLocation: ChatLocation, subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, updateTextInputState: ChatTextInputState? = nil, activateInput: Bool = false, keepStack: NavigateToChatKeepStack = .default, useExisting: Bool = true, purposefulAction: (() -> Void)? = nil, scrollToEndIfExists: Bool = false, activateMessageSearch: Bool = false, peekData: ChatPeekTimeout? = nil, peerNearbyData: ChatPeerNearbyData? = nil, animated: Bool = true, options: NavigationAnimationOptions = [], parentGroupId: PeerGroupId? = nil, completion: @escaping (ChatController) -> Void = { _ in }) {
|
||||
public init(navigationController: NavigationController, chatController: ChatController? = nil, context: AccountContext, chatLocation: ChatLocation, subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, updateTextInputState: ChatTextInputState? = nil, activateInput: Bool = false, keepStack: NavigateToChatKeepStack = .default, useExisting: Bool = true, purposefulAction: (() -> Void)? = nil, scrollToEndIfExists: Bool = false, activateMessageSearch: (ChatSearchDomain, String)? = nil, peekData: ChatPeekTimeout? = nil, peerNearbyData: ChatPeerNearbyData? = nil, animated: Bool = true, options: NavigationAnimationOptions = [], parentGroupId: PeerGroupId? = nil, completion: @escaping (ChatController) -> Void = { _ in }) {
|
||||
self.navigationController = navigationController
|
||||
self.chatController = chatController
|
||||
self.context = context
|
||||
@ -482,6 +510,7 @@ public protocol SharedAccountContext: class {
|
||||
func messageFromPreloadedChatHistoryViewForLocation(id: MessageId, location: ChatHistoryLocationInput, account: Account, chatLocation: ChatLocation, tagMask: MessageTags?) -> Signal<(MessageIndex?, Bool), NoError>
|
||||
func makeOverlayAudioPlayerController(context: AccountContext, peerId: PeerId, type: MediaManagerPlayerType, initialMessageId: MessageId, initialOrder: MusicPlaybackSettingsOrder, parentNavigationController: NavigationController?) -> ViewController & OverlayAudioPlayerController
|
||||
func makePeerInfoController(context: AccountContext, peer: Peer, mode: PeerInfoControllerMode, avatarInitiallyExpanded: Bool, fromChat: Bool) -> ViewController?
|
||||
func makeChannelAdminController(context: AccountContext, peerId: PeerId, adminId: PeerId, initialParticipant: ChannelParticipant) -> ViewController?
|
||||
func makeDeviceContactInfoController(context: AccountContext, subject: DeviceContactInfoSubject, completed: (() -> Void)?, cancelled: (() -> Void)?) -> ViewController
|
||||
func makePeersNearbyController(context: AccountContext) -> ViewController
|
||||
func makeComposeController(context: AccountContext) -> ViewController
|
||||
|
@ -666,6 +666,9 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
case .destructive:
|
||||
color = item.presentationData.theme.list.itemDisclosureActions.destructive.fillColor
|
||||
textColor = item.presentationData.theme.list.itemDisclosureActions.destructive.foregroundColor
|
||||
case .accent:
|
||||
color = item.presentationData.theme.list.itemDisclosureActions.accent.fillColor
|
||||
textColor = item.presentationData.theme.list.itemDisclosureActions.accent.foregroundColor
|
||||
}
|
||||
mappedOptions.append(ItemListRevealOption(key: index, title: option.title, icon: .none, color: color, textColor: textColor))
|
||||
index += 1
|
||||
|
@ -30,6 +30,12 @@ public class PercentPieChartController: BaseChartController {
|
||||
let pieController: PieChartComponentController
|
||||
let transitionRenderer: PercentPieAnimationRenderer
|
||||
|
||||
var initiallyZoomed = false
|
||||
public convenience init(chartsCollection: ChartsCollection, initiallyZoomed: Bool) {
|
||||
self.init(chartsCollection: chartsCollection)
|
||||
self.initiallyZoomed = initiallyZoomed
|
||||
}
|
||||
|
||||
override public init(chartsCollection: ChartsCollection) {
|
||||
transitionRenderer = PercentPieAnimationRenderer()
|
||||
percentController = PercentChartComponentController(isZoomed: false,
|
||||
@ -88,14 +94,14 @@ public class PercentPieChartController: BaseChartController {
|
||||
pieController.previewBarChartRenderer]
|
||||
}
|
||||
|
||||
public override func initializeChart() {
|
||||
public override func initializeChart() {
|
||||
percentController.initialize(chartsCollection: initialChartsCollection,
|
||||
initialDate: Date(),
|
||||
totalHorizontalRange: BaseConstants.defaultRange,
|
||||
totalVerticalRange: BaseConstants.defaultRange)
|
||||
switchToChart(chartsCollection: percentController.chartsCollection, isZoomed: false, animated: false)
|
||||
|
||||
if let lastDate = initialChartsCollection.axisValues.last {
|
||||
if let lastDate = initialChartsCollection.axisValues.last, self.initiallyZoomed {
|
||||
TimeInterval.animationDurationMultipler = 0.00001
|
||||
self.didTapZoomIn(date: lastDate, animated: false)
|
||||
TimeInterval.animationDurationMultipler = 1.0
|
||||
|
@ -11,6 +11,7 @@ public enum ChartType {
|
||||
case lines
|
||||
case twoAxis
|
||||
case pie
|
||||
case area
|
||||
case bars
|
||||
case step
|
||||
case twoAxisStep
|
||||
@ -76,7 +77,9 @@ public func createChartController(_ data: String, type: ChartType, getDetailsDat
|
||||
controller = TwoAxisLinesChartController(chartsCollection: collection)
|
||||
controller.isZoomable = false
|
||||
case .pie:
|
||||
controller = PercentPieChartController(chartsCollection: collection)
|
||||
controller = PercentPieChartController(chartsCollection: collection, initiallyZoomed: true)
|
||||
case .area:
|
||||
controller = PercentPieChartController(chartsCollection: collection, initiallyZoomed: false)
|
||||
case .bars:
|
||||
controller = StackedBarsChartController(chartsCollection: collection)
|
||||
controller.isZoomable = false
|
||||
|
@ -274,6 +274,7 @@ public enum ItemListPeerItemRevealOptionType {
|
||||
case neutral
|
||||
case warning
|
||||
case destructive
|
||||
case accent
|
||||
}
|
||||
|
||||
public struct ItemListPeerItemRevealOption {
|
||||
@ -624,6 +625,9 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
|
||||
case .destructive:
|
||||
color = item.presentationData.theme.list.itemDisclosureActions.destructive.fillColor
|
||||
textColor = item.presentationData.theme.list.itemDisclosureActions.destructive.foregroundColor
|
||||
case .accent:
|
||||
color = item.presentationData.theme.list.itemDisclosureActions.accent.fillColor
|
||||
textColor = item.presentationData.theme.list.itemDisclosureActions.accent.foregroundColor
|
||||
}
|
||||
mappedOptions.append(ItemListRevealOption(key: index, title: option.title, icon: .none, color: color, textColor: textColor))
|
||||
index += 1
|
||||
|
@ -21,11 +21,23 @@ private final class GroupStatsControllerArguments {
|
||||
let context: AccountContext
|
||||
let loadDetailedGraph: (StatsGraph, Int64) -> Signal<StatsGraph?, NoError>
|
||||
let openPeer: (PeerId) -> Void
|
||||
let openPeerHistory: (PeerId) -> Void
|
||||
let openPeerAdminActions: (PeerId) -> Void
|
||||
let promotePeer: (PeerId) -> Void
|
||||
let setPostersPeerIdWithRevealedOptions: (PeerId?, PeerId?) -> Void
|
||||
let setAdminsPeerIdWithRevealedOptions: (PeerId?, PeerId?) -> Void
|
||||
let setInvitersPeerIdWithRevealedOptions: (PeerId?, PeerId?) -> Void
|
||||
|
||||
init(context: AccountContext, loadDetailedGraph: @escaping (StatsGraph, Int64) -> Signal<StatsGraph?, NoError>, openPeer: @escaping (PeerId) -> Void) {
|
||||
init(context: AccountContext, loadDetailedGraph: @escaping (StatsGraph, Int64) -> Signal<StatsGraph?, NoError>, openPeer: @escaping (PeerId) -> Void, openPeerHistory: @escaping (PeerId) -> Void, openPeerAdminActions: @escaping (PeerId) -> Void, promotePeer: @escaping (PeerId) -> Void, setPostersPeerIdWithRevealedOptions: @escaping (PeerId?, PeerId?) -> Void, setAdminsPeerIdWithRevealedOptions: @escaping (PeerId?, PeerId?) -> Void, setInvitersPeerIdWithRevealedOptions: @escaping (PeerId?, PeerId?) -> Void) {
|
||||
self.context = context
|
||||
self.loadDetailedGraph = loadDetailedGraph
|
||||
self.openPeer = openPeer
|
||||
self.openPeerHistory = openPeerHistory
|
||||
self.openPeerAdminActions = openPeerAdminActions
|
||||
self.promotePeer = promotePeer
|
||||
self.setPostersPeerIdWithRevealedOptions = setPostersPeerIdWithRevealedOptions
|
||||
self.setAdminsPeerIdWithRevealedOptions = setAdminsPeerIdWithRevealedOptions
|
||||
self.setInvitersPeerIdWithRevealedOptions = setInvitersPeerIdWithRevealedOptions
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,6 +50,7 @@ private enum StatsSection: Int32 {
|
||||
case messages
|
||||
case actions
|
||||
case topHours
|
||||
case topWeekdays
|
||||
case topPosters
|
||||
case topAdmins
|
||||
case topInviters
|
||||
@ -68,14 +81,17 @@ private enum StatsEntry: ItemListNodeEntry {
|
||||
case topHoursTitle(PresentationTheme, String)
|
||||
case topHoursGraph(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, StatsGraph, ChartType)
|
||||
|
||||
case topWeekdaysTitle(PresentationTheme, String)
|
||||
case topWeekdaysGraph(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, StatsGraph, ChartType)
|
||||
|
||||
case topPostersTitle(PresentationTheme, String, String)
|
||||
case topPoster(Int32, PresentationTheme, PresentationStrings, PresentationDateTimeFormat, Peer, GroupStatsTopPoster)
|
||||
case topPoster(Int32, PresentationTheme, PresentationStrings, PresentationDateTimeFormat, Peer, GroupStatsTopPoster, Bool)
|
||||
|
||||
case topAdminsTitle(PresentationTheme, String, String)
|
||||
case topAdmin(Int32, PresentationTheme, PresentationStrings, PresentationDateTimeFormat, Peer, GroupStatsTopAdmin)
|
||||
case topAdmin(Int32, PresentationTheme, PresentationStrings, PresentationDateTimeFormat, Peer, GroupStatsTopAdmin, Bool)
|
||||
|
||||
case topInvitersTitle(PresentationTheme, String, String)
|
||||
case topInviter(Int32, PresentationTheme, PresentationStrings, PresentationDateTimeFormat, Peer, GroupStatsTopInviter)
|
||||
case topInviter(Int32, PresentationTheme, PresentationStrings, PresentationDateTimeFormat, Peer, GroupStatsTopInviter, Bool)
|
||||
|
||||
var section: ItemListSectionId {
|
||||
switch self {
|
||||
@ -95,6 +111,8 @@ private enum StatsEntry: ItemListNodeEntry {
|
||||
return StatsSection.actions.rawValue
|
||||
case .topHoursTitle, .topHoursGraph:
|
||||
return StatsSection.topHours.rawValue
|
||||
case .topWeekdaysTitle, .topWeekdaysGraph:
|
||||
return StatsSection.topWeekdays.rawValue
|
||||
case .topPostersTitle, .topPoster:
|
||||
return StatsSection.topPosters.rawValue
|
||||
case .topAdminsTitle, .topAdmin:
|
||||
@ -138,17 +156,21 @@ private enum StatsEntry: ItemListNodeEntry {
|
||||
return 14
|
||||
case .topHoursGraph:
|
||||
return 15
|
||||
case .topWeekdaysTitle:
|
||||
return 16
|
||||
case .topWeekdaysGraph:
|
||||
return 17
|
||||
case .topPostersTitle:
|
||||
return 1000
|
||||
case let .topPoster(index, _, _, _, _, _):
|
||||
case let .topPoster(index, _, _, _, _, _, _):
|
||||
return 1001 + index
|
||||
case .topAdminsTitle:
|
||||
return 2000
|
||||
case let .topAdmin(index, _, _, _, _, _):
|
||||
case let .topAdmin(index, _, _, _, _, _, _):
|
||||
return 2001 + index
|
||||
case .topInvitersTitle:
|
||||
return 3000
|
||||
case let .topInviter(index, _, _, _, _, _):
|
||||
case let .topInviter(index, _, _, _, _, _, _):
|
||||
return 30001 + index
|
||||
}
|
||||
}
|
||||
@ -251,14 +273,26 @@ private enum StatsEntry: ItemListNodeEntry {
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .topWeekdaysTitle(lhsTheme, lhsText):
|
||||
if case let .topWeekdaysTitle(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .topWeekdaysGraph(lhsTheme, lhsStrings, lhsDateTimeFormat, lhsGraph, lhsType):
|
||||
if case let .topWeekdaysGraph(rhsTheme, rhsStrings, rhsDateTimeFormat, rhsGraph, rhsType) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsDateTimeFormat == rhsDateTimeFormat, lhsGraph == rhsGraph, lhsType == rhsType {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .topPostersTitle(lhsTheme, lhsText, lhsDates):
|
||||
if case let .topPostersTitle(rhsTheme, rhsText, rhsDates) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsDates == rhsDates {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .topPoster(lhsIndex, lhsTheme, lhsStrings, lhsDateTimeFormat, lhsPeer, lhsTopPoster):
|
||||
if case let .topPoster(rhsIndex, rhsTheme, rhsStrings, rhsDateTimeFormat, rhsPeer, rhsTopPoster) = rhs, lhsIndex == rhsIndex, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsDateTimeFormat == rhsDateTimeFormat, arePeersEqual(lhsPeer, rhsPeer), lhsTopPoster == rhsTopPoster {
|
||||
case let .topPoster(lhsIndex, lhsTheme, lhsStrings, lhsDateTimeFormat, lhsPeer, lhsTopPoster, lhsRevealed):
|
||||
if case let .topPoster(rhsIndex, rhsTheme, rhsStrings, rhsDateTimeFormat, rhsPeer, rhsTopPoster, rhsRevealed) = rhs, lhsIndex == rhsIndex, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsDateTimeFormat == rhsDateTimeFormat, arePeersEqual(lhsPeer, rhsPeer), lhsTopPoster == rhsTopPoster, lhsRevealed == rhsRevealed {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
@ -269,8 +303,8 @@ private enum StatsEntry: ItemListNodeEntry {
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .topAdmin(lhsIndex, lhsTheme, lhsStrings, lhsDateTimeFormat, lhsPeer, lhsTopAdmin):
|
||||
if case let .topAdmin(rhsIndex, rhsTheme, rhsStrings, rhsDateTimeFormat, rhsPeer, rhsTopAdmin) = rhs, lhsIndex == rhsIndex, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsDateTimeFormat == rhsDateTimeFormat, arePeersEqual(lhsPeer, rhsPeer), lhsTopAdmin == rhsTopAdmin {
|
||||
case let .topAdmin(lhsIndex, lhsTheme, lhsStrings, lhsDateTimeFormat, lhsPeer, lhsTopAdmin, lhsRevealed):
|
||||
if case let .topAdmin(rhsIndex, rhsTheme, rhsStrings, rhsDateTimeFormat, rhsPeer, rhsTopAdmin, rhsRevealed) = rhs, lhsIndex == rhsIndex, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsDateTimeFormat == rhsDateTimeFormat, arePeersEqual(lhsPeer, rhsPeer), lhsTopAdmin == rhsTopAdmin, lhsRevealed == rhsRevealed {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
@ -281,8 +315,8 @@ private enum StatsEntry: ItemListNodeEntry {
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .topInviter(lhsIndex, lhsTheme, lhsStrings, lhsDateTimeFormat, lhsPeer, lhsTopInviter):
|
||||
if case let .topInviter(rhsIndex, rhsTheme, rhsStrings, rhsDateTimeFormat, rhsPeer, rhsTopInviter) = rhs, lhsIndex == rhsIndex, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsDateTimeFormat == rhsDateTimeFormat, arePeersEqual(lhsPeer, rhsPeer), lhsTopInviter == rhsTopInviter {
|
||||
case let .topInviter(lhsIndex, lhsTheme, lhsStrings, lhsDateTimeFormat, lhsPeer, lhsTopInviter, lhsRevealed):
|
||||
if case let .topInviter(rhsIndex, rhsTheme, rhsStrings, rhsDateTimeFormat, rhsPeer, rhsTopInviter, rhsRevealed) = rhs, lhsIndex == rhsIndex, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsDateTimeFormat == rhsDateTimeFormat, arePeersEqual(lhsPeer, rhsPeer), lhsTopInviter == rhsTopInviter, lhsRevealed == rhsRevealed {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
@ -305,7 +339,8 @@ private enum StatsEntry: ItemListNodeEntry {
|
||||
let .languagesTitle(_, text),
|
||||
let .messagesTitle(_, text),
|
||||
let .actionsTitle(_, text),
|
||||
let .topHoursTitle(_, text):
|
||||
let .topHoursTitle(_, text),
|
||||
let .topWeekdaysTitle(_, text):
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .topPostersTitle(_, text, dates),
|
||||
let .topAdminsTitle(_, text, dates),
|
||||
@ -319,9 +354,10 @@ private enum StatsEntry: ItemListNodeEntry {
|
||||
let .languagesGraph(_, _, _, graph, type),
|
||||
let .messagesGraph(_, _, _, graph, type),
|
||||
let .actionsGraph(_, _, _, graph, type),
|
||||
let .topHoursGraph(_, _, _, graph, type):
|
||||
let .topHoursGraph(_, _, _, graph, type),
|
||||
let .topWeekdaysGraph(_, _, _, graph, type):
|
||||
return StatsGraphItem(presentationData: presentationData, graph: graph, type: type, sectionId: self.section, style: .blocks)
|
||||
case let .topPoster(_, _, strings, dateTimeFormat, peer, topPoster):
|
||||
case let .topPoster(_, _, strings, dateTimeFormat, peer, topPoster, revealed):
|
||||
var textComponents: [String] = []
|
||||
if topPoster.messageCount > 0 {
|
||||
textComponents.append(strings.Stats_GroupTopPosterMessages(topPoster.messageCount))
|
||||
@ -329,10 +365,19 @@ private enum StatsEntry: ItemListNodeEntry {
|
||||
textComponents.append(strings.Stats_GroupTopPosterChars(topPoster.averageChars))
|
||||
}
|
||||
}
|
||||
return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: .firstLast, context: arguments.context, peer: peer, height: .generic, aliasHandling: .standard, nameColor: .primary, nameStyle: .plain, presence: nil, text: .text(textComponents.joined(separator: ", ")), label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: nil), revealOptions: nil, switchValue: nil, enabled: true, highlighted: false, selectable: true, sectionId: self.section, action: {
|
||||
var options: [ItemListPeerItemRevealOption] = []
|
||||
options.append(ItemListPeerItemRevealOption(type: .accent, title: strings.Stats_GroupTopPoster_History, action: {
|
||||
arguments.openPeerHistory(peer.id)
|
||||
}))
|
||||
options.append(ItemListPeerItemRevealOption(type: .neutral, title: strings.Stats_GroupTopPoster_Promote, action: {
|
||||
arguments.promotePeer(peer.id)
|
||||
}))
|
||||
return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: .firstLast, context: arguments.context, peer: peer, height: .generic, aliasHandling: .standard, nameColor: .primary, nameStyle: .plain, presence: nil, text: .text(textComponents.joined(separator: ", ")), label: .none, editing: ItemListPeerItemEditing(editable: true, editing: false, revealed: revealed), revealOptions: ItemListPeerItemRevealOptions(options: options), switchValue: nil, enabled: true, highlighted: false, selectable: true, sectionId: self.section, action: {
|
||||
arguments.openPeer(peer.id)
|
||||
}, setPeerIdWithRevealedOptions: { _, _ in }, removePeer: { _ in })
|
||||
case let .topAdmin(_, _, strings, dateTimeFormat, peer, topAdmin):
|
||||
}, setPeerIdWithRevealedOptions: { peerId, fromPeerId in
|
||||
arguments.setPostersPeerIdWithRevealedOptions(peerId, fromPeerId)
|
||||
}, removePeer: { _ in })
|
||||
case let .topAdmin(_, _, strings, dateTimeFormat, peer, topAdmin, revealed):
|
||||
var textComponents: [String] = []
|
||||
if topAdmin.deletedCount > 0 {
|
||||
textComponents.append(strings.Stats_GroupTopAdminDeletions(topAdmin.deletedCount))
|
||||
@ -343,22 +388,38 @@ private enum StatsEntry: ItemListNodeEntry {
|
||||
if topAdmin.bannedCount > 0 {
|
||||
textComponents.append(strings.Stats_GroupTopAdminBans(topAdmin.bannedCount))
|
||||
}
|
||||
|
||||
return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: .firstLast, context: arguments.context, peer: peer, height: .generic, aliasHandling: .standard, nameColor: .primary, nameStyle: .plain, presence: nil, text: .text(textComponents.joined(separator: ", ")), label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: nil), revealOptions: nil, switchValue: nil, enabled: true, highlighted: false, selectable: true, sectionId: self.section, action: {
|
||||
var options: [ItemListPeerItemRevealOption] = []
|
||||
options.append(ItemListPeerItemRevealOption(type: .accent, title: strings.Stats_GroupTopAdmin_Actions, action: {
|
||||
arguments.openPeerAdminActions(peer.id)
|
||||
}))
|
||||
options.append(ItemListPeerItemRevealOption(type: .neutral, title: strings.Stats_GroupTopAdmin_Promote, action: {
|
||||
arguments.promotePeer(peer.id)
|
||||
}))
|
||||
return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: .firstLast, context: arguments.context, peer: peer, height: .generic, aliasHandling: .standard, nameColor: .primary, nameStyle: .plain, presence: nil, text: .text(textComponents.joined(separator: ", ")), label: .none, editing: ItemListPeerItemEditing(editable: true, editing: false, revealed: revealed), revealOptions: ItemListPeerItemRevealOptions(options: options), switchValue: nil, enabled: true, highlighted: false, selectable: true, sectionId: self.section, action: {
|
||||
arguments.openPeer(peer.id)
|
||||
}, setPeerIdWithRevealedOptions: { _, _ in }, removePeer: { _ in })
|
||||
case let .topInviter(_, _, strings, dateTimeFormat, peer, topInviter):
|
||||
}, setPeerIdWithRevealedOptions: { peerId, fromPeerId in
|
||||
arguments.setAdminsPeerIdWithRevealedOptions(peerId, fromPeerId)
|
||||
}, removePeer: { _ in })
|
||||
case let .topInviter(_, _, strings, dateTimeFormat, peer, topInviter, revealed):
|
||||
var textComponents: [String] = []
|
||||
textComponents.append(strings.Stats_GroupTopInviterInvites(topInviter.inviteCount))
|
||||
|
||||
return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: .firstLast, context: arguments.context, peer: peer, height: .generic, aliasHandling: .standard, nameColor: .primary, nameStyle: .plain, presence: nil, text: .text(textComponents.joined(separator: ", ")), label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: nil), revealOptions: nil, switchValue: nil, enabled: true, highlighted: false, selectable: true, sectionId: self.section, action: {
|
||||
var options: [ItemListPeerItemRevealOption] = []
|
||||
options.append(ItemListPeerItemRevealOption(type: .accent, title: strings.Stats_GroupTopPoster_History, action: {
|
||||
arguments.openPeerHistory(peer.id)
|
||||
}))
|
||||
options.append(ItemListPeerItemRevealOption(type: .neutral, title: strings.Stats_GroupTopPoster_Promote, action: {
|
||||
arguments.promotePeer(peer.id)
|
||||
}))
|
||||
return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: .firstLast, context: arguments.context, peer: peer, height: .generic, aliasHandling: .standard, nameColor: .primary, nameStyle: .plain, presence: nil, text: .text(textComponents.joined(separator: ", ")), label: .none, editing: ItemListPeerItemEditing(editable: true, editing: false, revealed: revealed), revealOptions: ItemListPeerItemRevealOptions(options: options), switchValue: nil, enabled: true, highlighted: false, selectable: true, sectionId: self.section, action: {
|
||||
arguments.openPeer(peer.id)
|
||||
}, setPeerIdWithRevealedOptions: { _, _ in }, removePeer: { _ in })
|
||||
}, setPeerIdWithRevealedOptions: { peerId, fromPeerId in
|
||||
arguments.setInvitersPeerIdWithRevealedOptions(peerId, fromPeerId)
|
||||
}, removePeer: { _ in })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func groupStatsControllerEntries(data: GroupStats?, peers: [PeerId: Peer]?, presentationData: PresentationData) -> [StatsEntry] {
|
||||
private func groupStatsControllerEntries(state: GroupStatsState, data: GroupStats?, peers: [PeerId: Peer]?, presentationData: PresentationData) -> [StatsEntry] {
|
||||
var entries: [StatsEntry] = []
|
||||
|
||||
if let data = data {
|
||||
@ -404,13 +465,18 @@ private func groupStatsControllerEntries(data: GroupStats?, peers: [PeerId: Peer
|
||||
entries.append(.topHoursGraph(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, data.topHoursGraph, .hourlyStep))
|
||||
}
|
||||
|
||||
if !data.topWeekdaysGraph.isEmpty {
|
||||
entries.append(.topWeekdaysTitle(presentationData.theme, presentationData.strings.Stats_GroupTopWeekdaysTitle))
|
||||
entries.append(.topWeekdaysGraph(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, data.topWeekdaysGraph, .area))
|
||||
}
|
||||
|
||||
if let peers = peers {
|
||||
if !data.topPosters.isEmpty {
|
||||
entries.append(.topPostersTitle(presentationData.theme, presentationData.strings.Stats_GroupTopPostersTitle, dates))
|
||||
var index: Int32 = 0
|
||||
for topPoster in data.topPosters {
|
||||
if let peer = peers[topPoster.peerId], topPoster.messageCount > 0 {
|
||||
entries.append(.topPoster(index, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, peer, topPoster))
|
||||
entries.append(.topPoster(index, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, peer, topPoster, topPoster.peerId == state.posterPeerIdWithRevealedOptions))
|
||||
index += 1
|
||||
}
|
||||
}
|
||||
@ -420,7 +486,7 @@ private func groupStatsControllerEntries(data: GroupStats?, peers: [PeerId: Peer
|
||||
var index: Int32 = 0
|
||||
for topAdmin in data.topAdmins {
|
||||
if let peer = peers[topAdmin.peerId], (topAdmin.deletedCount + topAdmin.kickedCount + topAdmin.bannedCount) > 0 {
|
||||
entries.append(.topAdmin(index, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, peer, topAdmin))
|
||||
entries.append(.topAdmin(index, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, peer, topAdmin, topAdmin.peerId == state.adminPeerIdWithRevealedOptions))
|
||||
index += 1
|
||||
}
|
||||
}
|
||||
@ -430,7 +496,7 @@ private func groupStatsControllerEntries(data: GroupStats?, peers: [PeerId: Peer
|
||||
var index: Int32 = 0
|
||||
for topInviter in data.topInviters {
|
||||
if let peer = peers[topInviter.peerId], topInviter.inviteCount > 0 {
|
||||
entries.append(.topInviter(index, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, peer, topInviter))
|
||||
entries.append(.topInviter(index, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, peer, topInviter, topInviter.peerId == state.inviterPeerIdWithRevealedOptions))
|
||||
index += 1
|
||||
}
|
||||
}
|
||||
@ -441,8 +507,55 @@ private func groupStatsControllerEntries(data: GroupStats?, peers: [PeerId: Peer
|
||||
return entries
|
||||
}
|
||||
|
||||
private struct GroupStatsState: Equatable {
|
||||
let posterPeerIdWithRevealedOptions: PeerId?
|
||||
let adminPeerIdWithRevealedOptions: PeerId?
|
||||
let inviterPeerIdWithRevealedOptions: PeerId?
|
||||
|
||||
init() {
|
||||
self.posterPeerIdWithRevealedOptions = nil
|
||||
self.adminPeerIdWithRevealedOptions = nil
|
||||
self.inviterPeerIdWithRevealedOptions = nil
|
||||
}
|
||||
|
||||
init(posterPeerIdWithRevealedOptions: PeerId?, adminPeerIdWithRevealedOptions: PeerId?, inviterPeerIdWithRevealedOptions: PeerId?) {
|
||||
self.posterPeerIdWithRevealedOptions = posterPeerIdWithRevealedOptions
|
||||
self.adminPeerIdWithRevealedOptions = adminPeerIdWithRevealedOptions
|
||||
self.inviterPeerIdWithRevealedOptions = inviterPeerIdWithRevealedOptions
|
||||
}
|
||||
|
||||
static func ==(lhs: GroupStatsState, rhs: GroupStatsState) -> Bool {
|
||||
if lhs.posterPeerIdWithRevealedOptions != rhs.posterPeerIdWithRevealedOptions {
|
||||
return false
|
||||
}
|
||||
if lhs.adminPeerIdWithRevealedOptions != rhs.adminPeerIdWithRevealedOptions {
|
||||
return false
|
||||
}
|
||||
if lhs.inviterPeerIdWithRevealedOptions != rhs.inviterPeerIdWithRevealedOptions {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func withUpdatedPosterPeerIdWithRevealedOptions(_ posterPeerIdWithRevealedOptions: PeerId?) -> GroupStatsState {
|
||||
return GroupStatsState(posterPeerIdWithRevealedOptions: posterPeerIdWithRevealedOptions, adminPeerIdWithRevealedOptions: posterPeerIdWithRevealedOptions != nil ? nil : self.adminPeerIdWithRevealedOptions, inviterPeerIdWithRevealedOptions: posterPeerIdWithRevealedOptions != nil ? nil : self.inviterPeerIdWithRevealedOptions)
|
||||
}
|
||||
|
||||
func withUpdatedAdminPeerIdWithRevealedOptions(_ adminPeerIdWithRevealedOptions: PeerId?) -> GroupStatsState {
|
||||
return GroupStatsState(posterPeerIdWithRevealedOptions: adminPeerIdWithRevealedOptions != nil ? nil : self.posterPeerIdWithRevealedOptions, adminPeerIdWithRevealedOptions: adminPeerIdWithRevealedOptions, inviterPeerIdWithRevealedOptions: adminPeerIdWithRevealedOptions != nil ? nil : self.inviterPeerIdWithRevealedOptions)
|
||||
}
|
||||
|
||||
func withUpdatedInviterPeerIdWithRevealedOptions(_ inviterPeerIdWithRevealedOptions: PeerId?) -> GroupStatsState {
|
||||
return GroupStatsState(posterPeerIdWithRevealedOptions: inviterPeerIdWithRevealedOptions != nil ? nil : self.posterPeerIdWithRevealedOptions, adminPeerIdWithRevealedOptions: inviterPeerIdWithRevealedOptions != nil ? nil : self.adminPeerIdWithRevealedOptions, inviterPeerIdWithRevealedOptions: inviterPeerIdWithRevealedOptions)
|
||||
}
|
||||
}
|
||||
|
||||
public func groupStatsController(context: AccountContext, peerId: PeerId, cachedPeerData: CachedPeerData) -> ViewController {
|
||||
var openPeerImpl: ((PeerId) -> Void)?
|
||||
let statePromise = ValuePromise(GroupStatsState())
|
||||
let stateValue = Atomic(value: GroupStatsState())
|
||||
let updateState: ((GroupStatsState) -> GroupStatsState) -> Void = { f in
|
||||
statePromise.set(stateValue.modify { f($0) })
|
||||
}
|
||||
|
||||
let actionsDisposable = DisposableSet()
|
||||
let dataPromise = Promise<GroupStats?>(nil)
|
||||
@ -452,6 +565,14 @@ public func groupStatsController(context: AccountContext, peerId: PeerId, cached
|
||||
if let cachedData = cachedPeerData as? CachedChannelData {
|
||||
datacenterId = cachedData.statsDatacenterId
|
||||
}
|
||||
|
||||
var openPeerImpl: ((PeerId) -> Void)?
|
||||
var openPeerHistoryImpl: ((PeerId) -> Void)?
|
||||
var openPeerAdminActionsImpl: ((PeerId) -> Void)?
|
||||
var promotePeerImpl: ((PeerId) -> Void)?
|
||||
|
||||
let peerView = Promise<PeerView>()
|
||||
peerView.set(context.account.viewTracker.peerView(peerId, updateData: true))
|
||||
|
||||
let statsContext = GroupStatsContext(postbox: context.account.postbox, network: context.account.network, datacenterId: datacenterId, peerId: peerId)
|
||||
let dataSignal: Signal<GroupStats?, NoError> = statsContext.state
|
||||
@ -459,7 +580,7 @@ public func groupStatsController(context: AccountContext, peerId: PeerId, cached
|
||||
return state.stats
|
||||
} |> afterNext({ [weak statsContext] stats in
|
||||
if let statsContext = statsContext, let stats = stats {
|
||||
if case .OnDemand = stats.newMembersBySourceGraph {
|
||||
if case .OnDemand = stats.topWeekdaysGraph {
|
||||
statsContext.loadGrowthGraph()
|
||||
statsContext.loadMembersGraph()
|
||||
statsContext.loadNewMembersBySourceGraph()
|
||||
@ -467,6 +588,7 @@ public func groupStatsController(context: AccountContext, peerId: PeerId, cached
|
||||
statsContext.loadMessagesGraph()
|
||||
statsContext.loadActionsGraph()
|
||||
statsContext.loadTopHoursGraph()
|
||||
statsContext.loadTopWeekdaysGraph()
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -505,15 +627,45 @@ public func groupStatsController(context: AccountContext, peerId: PeerId, cached
|
||||
return statsContext.loadDetailedGraph(graph, x: x)
|
||||
}, openPeer: { peerId in
|
||||
openPeerImpl?(peerId)
|
||||
}, openPeerHistory: { peerId in
|
||||
openPeerHistoryImpl?(peerId)
|
||||
}, openPeerAdminActions: { peerId in
|
||||
openPeerAdminActionsImpl?(peerId)
|
||||
}, promotePeer: { peerId in
|
||||
promotePeerImpl?(peerId)
|
||||
}, setPostersPeerIdWithRevealedOptions: { peerId, fromPeerId in
|
||||
updateState { state in
|
||||
if (peerId == nil && fromPeerId == state.posterPeerIdWithRevealedOptions) || (peerId != nil && fromPeerId == nil) {
|
||||
return state.withUpdatedPosterPeerIdWithRevealedOptions(peerId)
|
||||
} else {
|
||||
return state
|
||||
}
|
||||
}
|
||||
}, setAdminsPeerIdWithRevealedOptions: { peerId, fromPeerId in
|
||||
updateState { state in
|
||||
if (peerId == nil && fromPeerId == state.adminPeerIdWithRevealedOptions) || (peerId != nil && fromPeerId == nil) {
|
||||
return state.withUpdatedAdminPeerIdWithRevealedOptions(peerId)
|
||||
} else {
|
||||
return state
|
||||
}
|
||||
}
|
||||
}, setInvitersPeerIdWithRevealedOptions: { peerId, fromPeerId in
|
||||
updateState { state in
|
||||
if (peerId == nil && fromPeerId == state.inviterPeerIdWithRevealedOptions) || (peerId != nil && fromPeerId == nil) {
|
||||
return state.withUpdatedInviterPeerIdWithRevealedOptions(peerId)
|
||||
} else {
|
||||
return state
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
let longLoadingSignal: Signal<Bool, NoError> = .single(false) |> then(.single(true) |> delay(2.0, queue: Queue.mainQueue()))
|
||||
|
||||
let previousData = Atomic<GroupStats?>(value: nil)
|
||||
|
||||
let signal = combineLatest(context.sharedContext.presentationData, dataPromise.get(), peersPromise.get(), longLoadingSignal)
|
||||
let signal = combineLatest(statePromise.get(), context.sharedContext.presentationData, dataPromise.get(), peersPromise.get(), longLoadingSignal)
|
||||
|> deliverOnMainQueue
|
||||
|> map { presentationData, data, peers, longLoading -> (ItemListControllerState, (ItemListNodeState, Any)) in
|
||||
|> map { state, presentationData, data, peers, longLoading -> (ItemListControllerState, (ItemListNodeState, Any)) in
|
||||
let previous = previousData.swap(data)
|
||||
var emptyStateItem: ItemListControllerEmptyStateItem?
|
||||
if data == nil {
|
||||
@ -525,7 +677,7 @@ public func groupStatsController(context: AccountContext, peerId: PeerId, cached
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.ChannelInfo_Stats), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: groupStatsControllerEntries(data: data, peers: peers, presentationData: presentationData), style: .blocks, emptyStateItem: emptyStateItem, crossfadeState: previous == nil, animateChanges: false)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: groupStatsControllerEntries(state: state, data: data, peers: peers, presentationData: presentationData), style: .blocks, emptyStateItem: emptyStateItem, crossfadeState: previous == nil, animateChanges: false)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
@ -556,5 +708,35 @@ public func groupStatsController(context: AccountContext, peerId: PeerId, cached
|
||||
})
|
||||
}
|
||||
}
|
||||
openPeerHistoryImpl = { [weak controller] participantPeerId in
|
||||
if let navigationController = controller?.navigationController as? NavigationController {
|
||||
let _ = (context.account.postbox.loadedPeerWithId(participantPeerId)
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).start(next: { peer in
|
||||
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, chatController: nil, context: context, chatLocation: .peer(peerId), subject: nil, botStart: nil, updateTextInputState: nil, activateInput: false, keepStack: .always, useExisting: false, purposefulAction: nil, scrollToEndIfExists: false, activateMessageSearch: (.member(peer), ""), animated: true))
|
||||
})
|
||||
}
|
||||
}
|
||||
openPeerAdminActionsImpl = { [weak controller] participantPeerId in
|
||||
if let navigationController = controller?.navigationController as? NavigationController {
|
||||
let _ = (context.account.postbox.loadedPeerWithId(peerId)
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).start(next: { peer in
|
||||
let controller = context.sharedContext.makeChatRecentActionsController(context: context, peer: peer)
|
||||
navigationController.pushViewController(controller)
|
||||
})
|
||||
}
|
||||
}
|
||||
promotePeerImpl = { [weak controller] participantPeerId in
|
||||
if let navigationController = controller?.navigationController as? NavigationController {
|
||||
let _ = (fetchChannelParticipant(account: context.account, peerId: peerId, participantId: participantPeerId)
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).start(next: { participant in
|
||||
if let participant = participant, let controller = context.sharedContext.makeChannelAdminController(context: context, peerId: peerId, adminId: participantPeerId, initialParticipant: participant) {
|
||||
navigationController.pushViewController(controller)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
return controller
|
||||
}
|
||||
|
@ -544,7 +544,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[1918567619] = { return Api.Updates.parse_updatesCombined($0) }
|
||||
dict[1957577280] = { return Api.Updates.parse_updates($0) }
|
||||
dict[301019932] = { return Api.Updates.parse_updateShortSentMessage($0) }
|
||||
dict[447818040] = { return Api.stats.MegagroupStats.parse_megagroupStats($0) }
|
||||
dict[-276825834] = { return Api.stats.MegagroupStats.parse_megagroupStats($0) }
|
||||
dict[-884757282] = { return Api.StatsAbsValueAndPrev.parse_statsAbsValueAndPrev($0) }
|
||||
dict[1038967584] = { return Api.MessageMedia.parse_messageMediaEmpty($0) }
|
||||
dict[1457575028] = { return Api.MessageMedia.parse_messageMediaGeo($0) }
|
||||
|
@ -663,13 +663,13 @@ public struct stats {
|
||||
|
||||
}
|
||||
public enum MegagroupStats: TypeConstructorDescription {
|
||||
case megagroupStats(period: Api.StatsDateRangeDays, members: Api.StatsAbsValueAndPrev, messages: Api.StatsAbsValueAndPrev, viewers: Api.StatsAbsValueAndPrev, posters: Api.StatsAbsValueAndPrev, growthGraph: Api.StatsGraph, membersGraph: Api.StatsGraph, newMembersBySourceGraph: Api.StatsGraph, languagesGraph: Api.StatsGraph, messagesGraph: Api.StatsGraph, actionsGraph: Api.StatsGraph, topHoursGraph: Api.StatsGraph, topPosters: [Api.StatsGroupTopPoster], topAdmins: [Api.StatsGroupTopAdmin], topInviters: [Api.StatsGroupTopInviter], users: [Api.User])
|
||||
case megagroupStats(period: Api.StatsDateRangeDays, members: Api.StatsAbsValueAndPrev, messages: Api.StatsAbsValueAndPrev, viewers: Api.StatsAbsValueAndPrev, posters: Api.StatsAbsValueAndPrev, growthGraph: Api.StatsGraph, membersGraph: Api.StatsGraph, newMembersBySourceGraph: Api.StatsGraph, languagesGraph: Api.StatsGraph, messagesGraph: Api.StatsGraph, actionsGraph: Api.StatsGraph, topHoursGraph: Api.StatsGraph, weekdaysGraph: Api.StatsGraph, topPosters: [Api.StatsGroupTopPoster], topAdmins: [Api.StatsGroupTopAdmin], topInviters: [Api.StatsGroupTopInviter], users: [Api.User])
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .megagroupStats(let period, let members, let messages, let viewers, let posters, let growthGraph, let membersGraph, let newMembersBySourceGraph, let languagesGraph, let messagesGraph, let actionsGraph, let topHoursGraph, let topPosters, let topAdmins, let topInviters, let users):
|
||||
case .megagroupStats(let period, let members, let messages, let viewers, let posters, let growthGraph, let membersGraph, let newMembersBySourceGraph, let languagesGraph, let messagesGraph, let actionsGraph, let topHoursGraph, let weekdaysGraph, let topPosters, let topAdmins, let topInviters, let users):
|
||||
if boxed {
|
||||
buffer.appendInt32(447818040)
|
||||
buffer.appendInt32(-276825834)
|
||||
}
|
||||
period.serialize(buffer, true)
|
||||
members.serialize(buffer, true)
|
||||
@ -683,6 +683,7 @@ public struct stats {
|
||||
messagesGraph.serialize(buffer, true)
|
||||
actionsGraph.serialize(buffer, true)
|
||||
topHoursGraph.serialize(buffer, true)
|
||||
weekdaysGraph.serialize(buffer, true)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(topPosters.count))
|
||||
for item in topPosters {
|
||||
@ -709,8 +710,8 @@ public struct stats {
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .megagroupStats(let period, let members, let messages, let viewers, let posters, let growthGraph, let membersGraph, let newMembersBySourceGraph, let languagesGraph, let messagesGraph, let actionsGraph, let topHoursGraph, let topPosters, let topAdmins, let topInviters, let users):
|
||||
return ("megagroupStats", [("period", period), ("members", members), ("messages", messages), ("viewers", viewers), ("posters", posters), ("growthGraph", growthGraph), ("membersGraph", membersGraph), ("newMembersBySourceGraph", newMembersBySourceGraph), ("languagesGraph", languagesGraph), ("messagesGraph", messagesGraph), ("actionsGraph", actionsGraph), ("topHoursGraph", topHoursGraph), ("topPosters", topPosters), ("topAdmins", topAdmins), ("topInviters", topInviters), ("users", users)])
|
||||
case .megagroupStats(let period, let members, let messages, let viewers, let posters, let growthGraph, let membersGraph, let newMembersBySourceGraph, let languagesGraph, let messagesGraph, let actionsGraph, let topHoursGraph, let weekdaysGraph, let topPosters, let topAdmins, let topInviters, let users):
|
||||
return ("megagroupStats", [("period", period), ("members", members), ("messages", messages), ("viewers", viewers), ("posters", posters), ("growthGraph", growthGraph), ("membersGraph", membersGraph), ("newMembersBySourceGraph", newMembersBySourceGraph), ("languagesGraph", languagesGraph), ("messagesGraph", messagesGraph), ("actionsGraph", actionsGraph), ("topHoursGraph", topHoursGraph), ("weekdaysGraph", weekdaysGraph), ("topPosters", topPosters), ("topAdmins", topAdmins), ("topInviters", topInviters), ("users", users)])
|
||||
}
|
||||
}
|
||||
|
||||
@ -763,21 +764,25 @@ public struct stats {
|
||||
if let signature = reader.readInt32() {
|
||||
_12 = Api.parse(reader, signature: signature) as? Api.StatsGraph
|
||||
}
|
||||
var _13: [Api.StatsGroupTopPoster]?
|
||||
if let _ = reader.readInt32() {
|
||||
_13 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsGroupTopPoster.self)
|
||||
var _13: Api.StatsGraph?
|
||||
if let signature = reader.readInt32() {
|
||||
_13 = Api.parse(reader, signature: signature) as? Api.StatsGraph
|
||||
}
|
||||
var _14: [Api.StatsGroupTopAdmin]?
|
||||
var _14: [Api.StatsGroupTopPoster]?
|
||||
if let _ = reader.readInt32() {
|
||||
_14 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsGroupTopAdmin.self)
|
||||
_14 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsGroupTopPoster.self)
|
||||
}
|
||||
var _15: [Api.StatsGroupTopInviter]?
|
||||
var _15: [Api.StatsGroupTopAdmin]?
|
||||
if let _ = reader.readInt32() {
|
||||
_15 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsGroupTopInviter.self)
|
||||
_15 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsGroupTopAdmin.self)
|
||||
}
|
||||
var _16: [Api.User]?
|
||||
var _16: [Api.StatsGroupTopInviter]?
|
||||
if let _ = reader.readInt32() {
|
||||
_16 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||
_16 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsGroupTopInviter.self)
|
||||
}
|
||||
var _17: [Api.User]?
|
||||
if let _ = reader.readInt32() {
|
||||
_17 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
@ -795,8 +800,9 @@ public struct stats {
|
||||
let _c14 = _14 != nil
|
||||
let _c15 = _15 != nil
|
||||
let _c16 = _16 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 {
|
||||
return Api.stats.MegagroupStats.megagroupStats(period: _1!, members: _2!, messages: _3!, viewers: _4!, posters: _5!, growthGraph: _6!, membersGraph: _7!, newMembersBySourceGraph: _8!, languagesGraph: _9!, messagesGraph: _10!, actionsGraph: _11!, topHoursGraph: _12!, topPosters: _13!, topAdmins: _14!, topInviters: _15!, users: _16!)
|
||||
let _c17 = _17 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 {
|
||||
return Api.stats.MegagroupStats.megagroupStats(period: _1!, members: _2!, messages: _3!, viewers: _4!, posters: _5!, growthGraph: _6!, membersGraph: _7!, newMembersBySourceGraph: _8!, languagesGraph: _9!, messagesGraph: _10!, actionsGraph: _11!, topHoursGraph: _12!, weekdaysGraph: _13!, topPosters: _14!, topAdmins: _15!, topInviters: _16!, users: _17!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
|
@ -553,11 +553,12 @@ public final class GroupStats: Equatable {
|
||||
public let messagesGraph: StatsGraph
|
||||
public let actionsGraph: StatsGraph
|
||||
public let topHoursGraph: StatsGraph
|
||||
public let topWeekdaysGraph: StatsGraph
|
||||
public let topPosters: [GroupStatsTopPoster]
|
||||
public let topAdmins: [GroupStatsTopAdmin]
|
||||
public let topInviters: [GroupStatsTopInviter]
|
||||
|
||||
init(period: StatsDateRange, members: StatsValue, messages: StatsValue, viewers: StatsValue, posters: StatsValue, growthGraph: StatsGraph, membersGraph: StatsGraph, newMembersBySourceGraph: StatsGraph, languagesGraph: StatsGraph, messagesGraph: StatsGraph, actionsGraph: StatsGraph, topHoursGraph: StatsGraph, topPosters: [GroupStatsTopPoster], topAdmins: [GroupStatsTopAdmin], topInviters: [GroupStatsTopInviter]) {
|
||||
init(period: StatsDateRange, members: StatsValue, messages: StatsValue, viewers: StatsValue, posters: StatsValue, growthGraph: StatsGraph, membersGraph: StatsGraph, newMembersBySourceGraph: StatsGraph, languagesGraph: StatsGraph, messagesGraph: StatsGraph, actionsGraph: StatsGraph, topHoursGraph: StatsGraph, topWeekdaysGraph: StatsGraph, topPosters: [GroupStatsTopPoster], topAdmins: [GroupStatsTopAdmin], topInviters: [GroupStatsTopInviter]) {
|
||||
self.period = period
|
||||
self.members = members
|
||||
self.messages = messages
|
||||
@ -570,6 +571,7 @@ public final class GroupStats: Equatable {
|
||||
self.messagesGraph = messagesGraph
|
||||
self.actionsGraph = actionsGraph
|
||||
self.topHoursGraph = topHoursGraph
|
||||
self.topWeekdaysGraph = topWeekdaysGraph
|
||||
self.topPosters = topPosters
|
||||
self.topAdmins = topAdmins
|
||||
self.topInviters = topInviters
|
||||
@ -612,6 +614,9 @@ public final class GroupStats: Equatable {
|
||||
if lhs.topHoursGraph != rhs.topHoursGraph {
|
||||
return false
|
||||
}
|
||||
if lhs.topWeekdaysGraph != rhs.topWeekdaysGraph {
|
||||
return false
|
||||
}
|
||||
if lhs.topPosters != rhs.topPosters {
|
||||
return false
|
||||
}
|
||||
@ -625,31 +630,35 @@ public final class GroupStats: Equatable {
|
||||
}
|
||||
|
||||
public func withUpdatedGrowthGraph(_ growthGraph: StatsGraph) -> GroupStats {
|
||||
return GroupStats(period: self.period, members: self.members, messages: self.messages, viewers: self.viewers, posters: self.posters, growthGraph: growthGraph, membersGraph: self.membersGraph, newMembersBySourceGraph: self.newMembersBySourceGraph, languagesGraph: self.languagesGraph, messagesGraph: self.messagesGraph, actionsGraph: self.actionsGraph, topHoursGraph: self.topHoursGraph, topPosters: self.topPosters, topAdmins: self.topAdmins, topInviters: self.topInviters)
|
||||
return GroupStats(period: self.period, members: self.members, messages: self.messages, viewers: self.viewers, posters: self.posters, growthGraph: growthGraph, membersGraph: self.membersGraph, newMembersBySourceGraph: self.newMembersBySourceGraph, languagesGraph: self.languagesGraph, messagesGraph: self.messagesGraph, actionsGraph: self.actionsGraph, topHoursGraph: self.topHoursGraph, topWeekdaysGraph: self.topWeekdaysGraph, topPosters: self.topPosters, topAdmins: self.topAdmins, topInviters: self.topInviters)
|
||||
}
|
||||
|
||||
public func withUpdatedMembersGraph(_ membersGraph: StatsGraph) -> GroupStats {
|
||||
return GroupStats(period: self.period, members: self.members, messages: self.messages, viewers: self.viewers, posters: self.posters, growthGraph: self.growthGraph, membersGraph: membersGraph, newMembersBySourceGraph: self.newMembersBySourceGraph, languagesGraph: self.languagesGraph, messagesGraph: self.messagesGraph, actionsGraph: self.actionsGraph, topHoursGraph: self.topHoursGraph, topPosters: self.topPosters, topAdmins: self.topAdmins, topInviters: self.topInviters)
|
||||
return GroupStats(period: self.period, members: self.members, messages: self.messages, viewers: self.viewers, posters: self.posters, growthGraph: self.growthGraph, membersGraph: membersGraph, newMembersBySourceGraph: self.newMembersBySourceGraph, languagesGraph: self.languagesGraph, messagesGraph: self.messagesGraph, actionsGraph: self.actionsGraph, topHoursGraph: self.topHoursGraph, topWeekdaysGraph: self.topWeekdaysGraph, topPosters: self.topPosters, topAdmins: self.topAdmins, topInviters: self.topInviters)
|
||||
}
|
||||
|
||||
public func withUpdatedNewMembersBySourceGraph(_ newMembersBySourceGraph: StatsGraph) -> GroupStats {
|
||||
return GroupStats(period: self.period, members: self.members, messages: self.messages, viewers: self.viewers, posters: self.posters, growthGraph: self.growthGraph, membersGraph: self.membersGraph, newMembersBySourceGraph: newMembersBySourceGraph, languagesGraph: self.languagesGraph, messagesGraph: self.messagesGraph, actionsGraph: self.actionsGraph, topHoursGraph: self.topHoursGraph, topPosters: self.topPosters, topAdmins: self.topAdmins, topInviters: self.topInviters)
|
||||
return GroupStats(period: self.period, members: self.members, messages: self.messages, viewers: self.viewers, posters: self.posters, growthGraph: self.growthGraph, membersGraph: self.membersGraph, newMembersBySourceGraph: newMembersBySourceGraph, languagesGraph: self.languagesGraph, messagesGraph: self.messagesGraph, actionsGraph: self.actionsGraph, topHoursGraph: self.topHoursGraph, topWeekdaysGraph: self.topWeekdaysGraph, topPosters: self.topPosters, topAdmins: self.topAdmins, topInviters: self.topInviters)
|
||||
}
|
||||
|
||||
public func withUpdatedLanguagesGraph(_ languagesGraph: StatsGraph) -> GroupStats {
|
||||
return GroupStats(period: self.period, members: self.members, messages: self.messages, viewers: self.viewers, posters: self.posters, growthGraph: self.growthGraph, membersGraph: self.membersGraph, newMembersBySourceGraph: self.newMembersBySourceGraph, languagesGraph: languagesGraph, messagesGraph: self.messagesGraph, actionsGraph: self.actionsGraph, topHoursGraph: self.topHoursGraph, topPosters: self.topPosters, topAdmins: self.topAdmins, topInviters: self.topInviters)
|
||||
return GroupStats(period: self.period, members: self.members, messages: self.messages, viewers: self.viewers, posters: self.posters, growthGraph: self.growthGraph, membersGraph: self.membersGraph, newMembersBySourceGraph: self.newMembersBySourceGraph, languagesGraph: languagesGraph, messagesGraph: self.messagesGraph, actionsGraph: self.actionsGraph, topHoursGraph: self.topHoursGraph, topWeekdaysGraph: self.topWeekdaysGraph, topPosters: self.topPosters, topAdmins: self.topAdmins, topInviters: self.topInviters)
|
||||
}
|
||||
|
||||
public func withUpdatedMessagesGraph(_ messagesGraph: StatsGraph) -> GroupStats {
|
||||
return GroupStats(period: self.period, members: self.members, messages: self.messages, viewers: self.viewers, posters: self.posters, growthGraph: self.growthGraph, membersGraph: self.membersGraph, newMembersBySourceGraph: self.newMembersBySourceGraph, languagesGraph: self.languagesGraph, messagesGraph: messagesGraph, actionsGraph: self.actionsGraph, topHoursGraph: self.topHoursGraph, topPosters: self.topPosters, topAdmins: self.topAdmins, topInviters: self.topInviters)
|
||||
return GroupStats(period: self.period, members: self.members, messages: self.messages, viewers: self.viewers, posters: self.posters, growthGraph: self.growthGraph, membersGraph: self.membersGraph, newMembersBySourceGraph: self.newMembersBySourceGraph, languagesGraph: self.languagesGraph, messagesGraph: messagesGraph, actionsGraph: self.actionsGraph, topHoursGraph: self.topHoursGraph, topWeekdaysGraph: self.topWeekdaysGraph, topPosters: self.topPosters, topAdmins: self.topAdmins, topInviters: self.topInviters)
|
||||
}
|
||||
|
||||
public func withUpdatedActionsGraph(_ actionsGraph: StatsGraph) -> GroupStats {
|
||||
return GroupStats(period: self.period, members: self.members, messages: self.messages, viewers: self.viewers, posters: self.posters, growthGraph: self.growthGraph, membersGraph: self.membersGraph, newMembersBySourceGraph: self.newMembersBySourceGraph, languagesGraph: self.languagesGraph, messagesGraph: self.messagesGraph, actionsGraph: actionsGraph, topHoursGraph: self.topHoursGraph, topPosters: self.topPosters, topAdmins: self.topAdmins, topInviters: self.topInviters)
|
||||
return GroupStats(period: self.period, members: self.members, messages: self.messages, viewers: self.viewers, posters: self.posters, growthGraph: self.growthGraph, membersGraph: self.membersGraph, newMembersBySourceGraph: self.newMembersBySourceGraph, languagesGraph: self.languagesGraph, messagesGraph: self.messagesGraph, actionsGraph: actionsGraph, topHoursGraph: self.topHoursGraph, topWeekdaysGraph: self.topWeekdaysGraph, topPosters: self.topPosters, topAdmins: self.topAdmins, topInviters: self.topInviters)
|
||||
}
|
||||
|
||||
public func withUpdatedTopHoursGraph(_ topHoursGraph: StatsGraph) -> GroupStats {
|
||||
return GroupStats(period: self.period, members: self.members, messages: self.messages, viewers: self.viewers, posters: self.posters, growthGraph: self.growthGraph, membersGraph: self.membersGraph, newMembersBySourceGraph: self.newMembersBySourceGraph, languagesGraph: self.languagesGraph, messagesGraph: self.messagesGraph, actionsGraph: self.actionsGraph, topHoursGraph: topHoursGraph, topPosters: self.topPosters, topAdmins: self.topAdmins, topInviters: self.topInviters)
|
||||
return GroupStats(period: self.period, members: self.members, messages: self.messages, viewers: self.viewers, posters: self.posters, growthGraph: self.growthGraph, membersGraph: self.membersGraph, newMembersBySourceGraph: self.newMembersBySourceGraph, languagesGraph: self.languagesGraph, messagesGraph: self.messagesGraph, actionsGraph: self.actionsGraph, topHoursGraph: topHoursGraph, topWeekdaysGraph: self.topWeekdaysGraph, topPosters: self.topPosters, topAdmins: self.topAdmins, topInviters: self.topInviters)
|
||||
}
|
||||
|
||||
public func withUpdatedTopWeekdaysGraph(_ topWeekdaysGraph: StatsGraph) -> GroupStats {
|
||||
return GroupStats(period: self.period, members: self.members, messages: self.messages, viewers: self.viewers, posters: self.posters, growthGraph: self.growthGraph, membersGraph: self.membersGraph, newMembersBySourceGraph: self.newMembersBySourceGraph, languagesGraph: self.languagesGraph, messagesGraph: self.messagesGraph, actionsGraph: self.actionsGraph, topHoursGraph: self.topHoursGraph, topWeekdaysGraph: topWeekdaysGraph, topPosters: self.topPosters, topAdmins: self.topAdmins, topInviters: self.topInviters)
|
||||
}
|
||||
}
|
||||
|
||||
@ -684,7 +693,7 @@ private func requestGroupStats(postbox: Postbox, network: Network, datacenterId:
|
||||
return signal
|
||||
|> mapToSignal { result -> Signal<GroupStats?, MTRpcError> in
|
||||
return postbox.transaction { transaction -> GroupStats? in
|
||||
if case let .megagroupStats(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, users) = result {
|
||||
if case let .megagroupStats(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, users) = result {
|
||||
var parsedUsers: [Peer] = []
|
||||
for user in users {
|
||||
parsedUsers.append(TelegramUser(user: user))
|
||||
@ -858,6 +867,21 @@ private final class GroupStatsContextImpl {
|
||||
}
|
||||
}
|
||||
|
||||
func loadTopWeekdaysGraph() {
|
||||
guard let stats = self._state.stats else {
|
||||
return
|
||||
}
|
||||
if case let .OnDemand(token) = stats.topWeekdaysGraph {
|
||||
self.disposables.set((requestGraph(network: self.network, datacenterId: self.datacenterId, token: token)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] graph in
|
||||
if let strongSelf = self, let graph = graph {
|
||||
strongSelf._state = GroupStatsContextState(stats: strongSelf._state.stats?.withUpdatedTopWeekdaysGraph(graph))
|
||||
strongSelf._statePromise.set(.single(strongSelf._state))
|
||||
}
|
||||
}), forKey: token)
|
||||
}
|
||||
}
|
||||
|
||||
func loadDetailedGraph(_ graph: StatsGraph, x: Int64) -> Signal<StatsGraph?, NoError> {
|
||||
if let token = graph.token {
|
||||
return requestGraph(network: self.network, datacenterId: self.datacenterId, token: token, x: x)
|
||||
@ -930,6 +954,12 @@ public final class GroupStatsContext {
|
||||
}
|
||||
}
|
||||
|
||||
public func loadTopWeekdaysGraph() {
|
||||
self.impl.with { impl in
|
||||
impl.loadTopWeekdaysGraph()
|
||||
}
|
||||
}
|
||||
|
||||
public func loadDetailedGraph(_ graph: StatsGraph, x: Int64) -> Signal<StatsGraph?, NoError> {
|
||||
return Signal { subscriber in
|
||||
let disposable = MetaDisposable()
|
||||
@ -973,7 +1003,11 @@ extension StatsGraph {
|
||||
case let .statsGraphError(error):
|
||||
self = .Failed(error: error)
|
||||
case let .statsGraphAsync(token):
|
||||
self = .OnDemand(token: token)
|
||||
if !token.isEmpty {
|
||||
self = .OnDemand(token: token)
|
||||
} else {
|
||||
self = .Failed(error: "An error occured. Please try again later.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1056,11 +1090,11 @@ extension GroupStatsTopInviter {
|
||||
extension GroupStats {
|
||||
convenience init(apiMegagroupStats: Api.stats.MegagroupStats) {
|
||||
switch apiMegagroupStats {
|
||||
case let .megagroupStats(period, members, messages, viewers, posters, apiGrowthGraph, apiMembersGraph, apiNewMembersBySourceGraph, apiLanguagesGraph, apiMessagesGraph, apiActionsGraph, apiTopHoursGraph, topPosters, topAdmins, topInviters, users):
|
||||
case let .megagroupStats(period, members, messages, viewers, posters, apiGrowthGraph, apiMembersGraph, apiNewMembersBySourceGraph, apiLanguagesGraph, apiMessagesGraph, apiActionsGraph, apiTopHoursGraph, apiTopWeekdaysGraph, topPosters, topAdmins, topInviters, users):
|
||||
let growthGraph = StatsGraph(apiStatsGraph: apiGrowthGraph)
|
||||
let isEmpty = growthGraph.isEmpty
|
||||
|
||||
self.init(period: StatsDateRange(apiStatsDateRangeDays: period), members: StatsValue(apiStatsAbsValueAndPrev: members), messages: StatsValue(apiStatsAbsValueAndPrev: messages), viewers: StatsValue(apiStatsAbsValueAndPrev: viewers), posters: StatsValue(apiStatsAbsValueAndPrev: posters), growthGraph: growthGraph, membersGraph: StatsGraph(apiStatsGraph: apiMembersGraph), newMembersBySourceGraph: StatsGraph(apiStatsGraph: apiNewMembersBySourceGraph), languagesGraph: StatsGraph(apiStatsGraph: apiLanguagesGraph), messagesGraph: StatsGraph(apiStatsGraph: apiMessagesGraph), actionsGraph: StatsGraph(apiStatsGraph: apiActionsGraph), topHoursGraph: StatsGraph(apiStatsGraph: apiTopHoursGraph), topPosters: topPosters.map { GroupStatsTopPoster(apiStatsGroupTopPoster: $0) }, topAdmins: topAdmins.map { GroupStatsTopAdmin(apiStatsGroupTopAdmin: $0) }, topInviters: topInviters.map { GroupStatsTopInviter(apiStatsGroupTopInviter: $0) })
|
||||
self.init(period: StatsDateRange(apiStatsDateRangeDays: period), members: StatsValue(apiStatsAbsValueAndPrev: members), messages: StatsValue(apiStatsAbsValueAndPrev: messages), viewers: StatsValue(apiStatsAbsValueAndPrev: viewers), posters: StatsValue(apiStatsAbsValueAndPrev: posters), growthGraph: growthGraph, membersGraph: StatsGraph(apiStatsGraph: apiMembersGraph), newMembersBySourceGraph: StatsGraph(apiStatsGraph: apiNewMembersBySourceGraph), languagesGraph: StatsGraph(apiStatsGraph: apiLanguagesGraph), messagesGraph: StatsGraph(apiStatsGraph: apiMessagesGraph), actionsGraph: StatsGraph(apiStatsGraph: apiActionsGraph), topHoursGraph: StatsGraph(apiStatsGraph: apiTopHoursGraph), topWeekdaysGraph: StatsGraph(apiStatsGraph: apiTopWeekdaysGraph), topPosters: topPosters.map { GroupStatsTopPoster(apiStatsGroupTopPoster: $0) }, topAdmins: topAdmins.map { GroupStatsTopAdmin(apiStatsGroupTopAdmin: $0) }, topInviters: topInviters.map { GroupStatsTopInviter(apiStatsGroupTopInviter: $0) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -314,7 +314,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
|
||||
private var isDismissed = false
|
||||
|
||||
private var focusOnSearchAfterAppearance: Bool = false
|
||||
private var focusOnSearchAfterAppearance: (ChatSearchDomain, String)?
|
||||
|
||||
private let keepPeerInfoScreenDataHotDisposable = MetaDisposable()
|
||||
|
||||
@ -4738,9 +4738,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
|
||||
self.interfaceInteraction = interfaceInteraction
|
||||
|
||||
if self.focusOnSearchAfterAppearance {
|
||||
self.focusOnSearchAfterAppearance = false
|
||||
self.interfaceInteraction?.beginMessageSearch(.everything, "")
|
||||
if let search = self.focusOnSearchAfterAppearance {
|
||||
self.focusOnSearchAfterAppearance = nil
|
||||
self.interfaceInteraction?.beginMessageSearch(search.0, search.1)
|
||||
}
|
||||
|
||||
self.chatDisplayNode.interfaceInteraction = interfaceInteraction
|
||||
@ -5005,8 +5005,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
}
|
||||
|
||||
if self.focusOnSearchAfterAppearance {
|
||||
self.focusOnSearchAfterAppearance = false
|
||||
if let _ = self.focusOnSearchAfterAppearance {
|
||||
self.focusOnSearchAfterAppearance = nil
|
||||
if let searchNode = self.navigationBar?.contentNode as? ChatSearchNavigationContentNode {
|
||||
searchNode.activate()
|
||||
}
|
||||
@ -9253,9 +9253,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
}
|
||||
|
||||
func activateSearch() {
|
||||
self.focusOnSearchAfterAppearance = true
|
||||
self.interfaceInteraction?.beginMessageSearch(.everything, "")
|
||||
func activateSearch(domain: ChatSearchDomain = .everything, query: String = "") {
|
||||
self.focusOnSearchAfterAppearance = (domain, query)
|
||||
self.interfaceInteraction?.beginMessageSearch(domain, query)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,35 +128,6 @@ struct ChatSearchResultsState: Equatable {
|
||||
let totalCount: Int32
|
||||
let completed: Bool
|
||||
}
|
||||
|
||||
enum ChatSearchDomain: Equatable {
|
||||
case everything
|
||||
case members
|
||||
case member(Peer)
|
||||
|
||||
static func ==(lhs: ChatSearchDomain, rhs: ChatSearchDomain) -> Bool {
|
||||
switch lhs {
|
||||
case .everything:
|
||||
if case .everything = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case .members:
|
||||
if case .members = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .member(lhsPeer):
|
||||
if case let .member(rhsPeer) = rhs, lhsPeer.isEqual(rhsPeer) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum ChatSearchDomainSuggestionContext: Equatable {
|
||||
case none
|
||||
|
@ -34,8 +34,8 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam
|
||||
controller.scrollToEndOfHistory()
|
||||
let _ = params.navigationController.popToViewController(controller, animated: params.animated)
|
||||
params.completion(controller)
|
||||
} else if params.activateMessageSearch {
|
||||
controller.activateSearch()
|
||||
} else if let search = params.activateMessageSearch {
|
||||
controller.activateSearch(domain: search.0, query: search.1)
|
||||
let _ = params.navigationController.popToViewController(controller, animated: params.animated)
|
||||
params.completion(controller)
|
||||
} else {
|
||||
@ -70,8 +70,8 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam
|
||||
controller = ChatControllerImpl(context: params.context, chatLocation: params.chatLocation, subject: params.subject, botStart: params.botStart, peekData: params.peekData, peerNearbyData: params.peerNearbyData)
|
||||
}
|
||||
controller.purposefulAction = params.purposefulAction
|
||||
if params.activateMessageSearch {
|
||||
controller.activateSearch()
|
||||
if let search = params.activateMessageSearch {
|
||||
controller.activateSearch(domain: search.0, query: search.1)
|
||||
}
|
||||
let resolvedKeepStack: Bool
|
||||
switch params.keepStack {
|
||||
|
@ -2410,7 +2410,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
|
||||
private func openChatWithMessageSearch() {
|
||||
if let navigationController = (self.controller?.navigationController as? NavigationController) {
|
||||
self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(self.peerId), activateMessageSearch: true))
|
||||
self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(self.peerId), activateMessageSearch: (.everything, "")))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1014,6 +1014,11 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
||||
return controller
|
||||
}
|
||||
|
||||
public func makeChannelAdminController(context: AccountContext, peerId: PeerId, adminId: PeerId, initialParticipant: ChannelParticipant) -> ViewController? {
|
||||
let controller = channelAdminController(context: context, peerId: peerId, adminId: adminId, initialParticipant: initialParticipant, updated: { _ in }, upgradedToSupergroup: { _, _ in }, transferedOwnership: { _ in })
|
||||
return controller
|
||||
}
|
||||
|
||||
public func openExternalUrl(context: AccountContext, urlContext: OpenURLContext, url: String, forceExternal: Bool, presentationData: PresentationData, navigationController: NavigationController?, dismissInput: @escaping () -> Void) {
|
||||
openExternalUrlImpl(context: context, urlContext: urlContext, url: url, forceExternal: forceExternal, presentationData: presentationData, navigationController: navigationController, dismissInput: dismissInput)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user