mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-09 03:20:48 +00:00
Various improvements
This commit is contained in:
parent
56aff0306e
commit
d6f9cfcc84
@ -580,8 +580,8 @@ open class ItemListController: ViewController, KeyShortcutResponder, Presentable
|
||||
}
|
||||
}
|
||||
|
||||
public func ensureItemNodeVisible(_ itemNode: ListViewItemNode, animated: Bool = true, curve: ListViewAnimationCurve = .Default(duration: 0.25)) {
|
||||
(self.displayNode as! ItemListControllerNode).listNode.ensureItemNodeVisible(itemNode, animated: animated, curve: curve)
|
||||
public func ensureItemNodeVisible(_ itemNode: ListViewItemNode, animated: Bool = true, overflow: CGFloat = 0.0, atTop: Bool = false, curve: ListViewAnimationCurve = .Default(duration: 0.25)) {
|
||||
(self.displayNode as! ItemListControllerNode).listNode.ensureItemNodeVisible(itemNode, animated: animated, overflow: overflow, atTop: atTop, curve: curve)
|
||||
}
|
||||
|
||||
public func afterLayout(_ f: @escaping () -> Void) {
|
||||
|
@ -389,7 +389,7 @@ open class ItemListControllerNode: ASDisplayNode {
|
||||
}
|
||||
case .unknown, .none:
|
||||
if let headerItemNode = strongSelf.headerItemNode {
|
||||
headerItemNode.updateContentOffset(0.0, transition: .immediate)
|
||||
headerItemNode.updateContentOffset(1000.0, transition: .immediate)
|
||||
strongSelf.navigationBar.updateBackgroundAlpha(0.0, transition: .immediate)
|
||||
} else {
|
||||
strongSelf.navigationBar.updateBackgroundAlpha(1.0, transition: .immediate)
|
||||
|
@ -27,14 +27,16 @@ private final class CreateGiveawayControllerArguments {
|
||||
let openPeersSelection: () -> Void
|
||||
let openChannelsSelection: () -> Void
|
||||
let openPremiumIntro: () -> Void
|
||||
let scrollToDate: () -> Void
|
||||
|
||||
init(context: AccountContext, updateState: @escaping ((CreateGiveawayControllerState) -> CreateGiveawayControllerState) -> Void, dismissInput: @escaping () -> Void, openPeersSelection: @escaping () -> Void, openChannelsSelection: @escaping () -> Void, openPremiumIntro: @escaping () -> Void) {
|
||||
init(context: AccountContext, updateState: @escaping ((CreateGiveawayControllerState) -> CreateGiveawayControllerState) -> Void, dismissInput: @escaping () -> Void, openPeersSelection: @escaping () -> Void, openChannelsSelection: @escaping () -> Void, openPremiumIntro: @escaping () -> Void, scrollToDate: @escaping () -> Void) {
|
||||
self.context = context
|
||||
self.updateState = updateState
|
||||
self.dismissInput = dismissInput
|
||||
self.openPeersSelection = openPeersSelection
|
||||
self.openChannelsSelection = openChannelsSelection
|
||||
self.openPremiumIntro = openPremiumIntro
|
||||
self.scrollToDate = scrollToDate
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,7 +51,7 @@ private enum CreateGiveawaySection: Int32 {
|
||||
}
|
||||
|
||||
private enum CreateGiveawayEntryTag: ItemListItemTag {
|
||||
case usage
|
||||
case date
|
||||
|
||||
func isEqual(to other: ItemListItemTag) -> Bool {
|
||||
if let other = other as? CreateGiveawayEntryTag, self == other {
|
||||
@ -409,11 +411,20 @@ private enum CreateGiveawayEntry: ItemListNodeEntry {
|
||||
}
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: "Ends", label: text, labelStyle: active ? .coloredText(theme.list.itemAccentColor) : .text, sectionId: self.section, style: .blocks, disclosureStyle: .none, action: {
|
||||
arguments.dismissInput()
|
||||
var focus = false
|
||||
arguments.updateState { state in
|
||||
var updatedState = state
|
||||
updatedState.pickingTimeLimit = !state.pickingTimeLimit
|
||||
if updatedState.pickingTimeLimit {
|
||||
focus = true
|
||||
}
|
||||
return updatedState
|
||||
}
|
||||
if focus {
|
||||
Queue.mainQueue().after(0.1) {
|
||||
arguments.scrollToDate()
|
||||
}
|
||||
}
|
||||
})
|
||||
case let .timeCustomPicker(_, dateTimeFormat, date):
|
||||
return ItemListDatePickerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, date: date, sectionId: self.section, style: .blocks, updated: { date in
|
||||
@ -422,7 +433,7 @@ private enum CreateGiveawayEntry: ItemListNodeEntry {
|
||||
updatedState.time = date
|
||||
return updatedState
|
||||
})
|
||||
})
|
||||
}, tag: CreateGiveawayEntryTag.date)
|
||||
case let .timeInfo(_, text):
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
|
||||
case let .durationHeader(_, text):
|
||||
@ -626,6 +637,7 @@ public func createGiveawayController(context: AccountContext, updatedPresentatio
|
||||
var openPremiumIntroImpl: (() -> Void)?
|
||||
var presentControllerImpl: ((ViewController) -> Void)?
|
||||
var pushControllerImpl: ((ViewController) -> Void)?
|
||||
var scrollToDateImpl: (() -> Void)?
|
||||
var dismissImpl: (() -> Void)?
|
||||
var dismissInputImpl: (() -> Void)?
|
||||
|
||||
@ -639,6 +651,8 @@ public func createGiveawayController(context: AccountContext, updatedPresentatio
|
||||
openChannelsSelectionImpl?()
|
||||
}, openPremiumIntro: {
|
||||
openPremiumIntroImpl?()
|
||||
}, scrollToDate: {
|
||||
scrollToDateImpl?()
|
||||
})
|
||||
|
||||
let presentationData = updatedPresentationData?.signal ?? context.sharedContext.presentationData
|
||||
@ -867,9 +881,6 @@ public func createGiveawayController(context: AccountContext, updatedPresentatio
|
||||
}
|
||||
})
|
||||
} else {
|
||||
let alertController = textAlertController(context: context, updatedPresentationData: updatedPresentationData, title: nil, text: presentationData.strings.Premium_Purchase_ErrorUnknown, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})])
|
||||
presentControllerImpl?(alertController)
|
||||
|
||||
updateState { state in
|
||||
var updatedState = state
|
||||
updatedState.updating = false
|
||||
@ -903,6 +914,15 @@ public func createGiveawayController(context: AccountContext, updatedPresentatio
|
||||
}
|
||||
}
|
||||
)
|
||||
controller.dismissed = {
|
||||
updateState { state in
|
||||
var updatedState = state
|
||||
if updatedState.peers.isEmpty {
|
||||
updatedState.mode = .giveaway
|
||||
}
|
||||
return updatedState
|
||||
}
|
||||
}
|
||||
pushControllerImpl?(controller)
|
||||
})
|
||||
}
|
||||
@ -937,5 +957,27 @@ public func createGiveawayController(context: AccountContext, updatedPresentatio
|
||||
pushControllerImpl?(controller)
|
||||
}
|
||||
|
||||
scrollToDateImpl = { [weak controller] in
|
||||
controller?.afterLayout({
|
||||
guard let controller = controller else {
|
||||
return
|
||||
}
|
||||
|
||||
var resultItemNode: ListViewItemNode?
|
||||
let _ = controller.frameForItemNode({ listItemNode in
|
||||
if let itemNode = listItemNode as? ItemListItemNode {
|
||||
if let tag = itemNode.tag as? CreateGiveawayEntryTag, tag == .date {
|
||||
resultItemNode = listItemNode
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
if let resultItemNode = resultItemNode {
|
||||
controller.ensureItemNodeVisible(resultItemNode, overflow: 120.0, atTop: true)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return controller
|
||||
}
|
||||
|
@ -260,7 +260,7 @@ class GiftOptionItemNode: ItemListRevealOptionsItemNode {
|
||||
|
||||
let titleAttributedString = NSAttributedString(string: item.title, font: titleFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor)
|
||||
let statusAttributedString = NSAttributedString(string: item.subtitle ?? "", font: statusFont, textColor: item.subtitleActive ? item.presentationData.theme.list.itemAccentColor : item.presentationData.theme.list.itemSecondaryTextColor)
|
||||
let badgeAttributedString = NSAttributedString(string: item.badge ?? "", font: Font.with(size: 14.0, design: .round, weight: .semibold), textColor: item.presentationData.theme.list.itemCheckColors.foregroundColor)
|
||||
let badgeAttributedString = NSAttributedString(string: item.badge ?? "", font: Font.with(size: 13.0, design: .round, weight: .semibold), textColor: item.presentationData.theme.list.itemCheckColors.foregroundColor)
|
||||
|
||||
let labelColor: UIColor
|
||||
let labelFont: UIFont
|
||||
@ -450,7 +450,7 @@ class GiftOptionItemNode: ItemListRevealOptionsItemNode {
|
||||
var badgeOffset: CGFloat = 0.0
|
||||
if badgeLayout.size.width > 0.0 {
|
||||
let badgeFrame = CGRect(origin: CGPoint(x: leftInset + editingOffset + avatarInset + 2.0, y: strongSelf.titleNode.frame.maxY + titleSpacing), size: badgeLayout.size)
|
||||
let badgeBackgroundFrame = badgeFrame.insetBy(dx: -2.0, dy: -2.0)
|
||||
let badgeBackgroundFrame = badgeFrame.insetBy(dx: -3.0, dy: -2.0)
|
||||
|
||||
let badgeBackgroundNode: ASImageNode
|
||||
if let current = strongSelf.badgeBackgroundNode {
|
||||
@ -491,7 +491,7 @@ class GiftOptionItemNode: ItemListRevealOptionsItemNode {
|
||||
strongSelf.containerNode.addSubnode(iconNode)
|
||||
|
||||
strongSelf.labelBackgroundNode = backgroundNode
|
||||
strongSelf.labelIconNode = backgroundNode
|
||||
strongSelf.labelIconNode = iconNode
|
||||
}
|
||||
|
||||
if let icon = iconNode.image {
|
||||
|
@ -22,6 +22,7 @@ public struct UserLimitsConfiguration: Equatable {
|
||||
public let maxStoriesWeeklyCount: Int32
|
||||
public let maxStoriesMonthlyCount: Int32
|
||||
public let maxStoriesSuggestedReactions: Int32
|
||||
public let maxGiveawayChannelsCount: Int32
|
||||
|
||||
public static var defaultValue: UserLimitsConfiguration {
|
||||
return UserLimitsConfiguration(
|
||||
@ -44,7 +45,8 @@ public struct UserLimitsConfiguration: Equatable {
|
||||
maxExpiringStoriesCount: 3,
|
||||
maxStoriesWeeklyCount: 7,
|
||||
maxStoriesMonthlyCount: 30,
|
||||
maxStoriesSuggestedReactions: 1
|
||||
maxStoriesSuggestedReactions: 1,
|
||||
maxGiveawayChannelsCount: 10
|
||||
)
|
||||
}
|
||||
|
||||
@ -68,7 +70,8 @@ public struct UserLimitsConfiguration: Equatable {
|
||||
maxExpiringStoriesCount: Int32,
|
||||
maxStoriesWeeklyCount: Int32,
|
||||
maxStoriesMonthlyCount: Int32,
|
||||
maxStoriesSuggestedReactions: Int32
|
||||
maxStoriesSuggestedReactions: Int32,
|
||||
maxGiveawayChannelsCount: Int32
|
||||
) {
|
||||
self.maxPinnedChatCount = maxPinnedChatCount
|
||||
self.maxArchivedPinnedChatCount = maxArchivedPinnedChatCount
|
||||
@ -90,6 +93,7 @@ public struct UserLimitsConfiguration: Equatable {
|
||||
self.maxStoriesWeeklyCount = maxStoriesWeeklyCount
|
||||
self.maxStoriesMonthlyCount = maxStoriesMonthlyCount
|
||||
self.maxStoriesSuggestedReactions = maxStoriesSuggestedReactions
|
||||
self.maxGiveawayChannelsCount = maxGiveawayChannelsCount
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,5 +138,6 @@ extension UserLimitsConfiguration {
|
||||
self.maxStoriesWeeklyCount = getValue("stories_sent_weekly_limit", orElse: defaultValue.maxStoriesWeeklyCount)
|
||||
self.maxStoriesMonthlyCount = getValue("stories_sent_monthly_limit", orElse: defaultValue.maxStoriesMonthlyCount)
|
||||
self.maxStoriesSuggestedReactions = getValue("stories_suggested_reactions_limit", orElse: defaultValue.maxStoriesMonthlyCount)
|
||||
self.maxGiveawayChannelsCount = getGeneralValue("giveaway_add_peers_max", orElse: defaultValue.maxGiveawayChannelsCount)
|
||||
}
|
||||
}
|
||||
|
@ -56,6 +56,7 @@ public enum EngineConfiguration {
|
||||
public let maxStoriesWeeklyCount: Int32
|
||||
public let maxStoriesMonthlyCount: Int32
|
||||
public let maxStoriesSuggestedReactions: Int32
|
||||
public let maxGiveawayChannelsCount: Int32
|
||||
|
||||
public static var defaultValue: UserLimits {
|
||||
return UserLimits(UserLimitsConfiguration.defaultValue)
|
||||
@ -81,7 +82,8 @@ public enum EngineConfiguration {
|
||||
maxExpiringStoriesCount: Int32,
|
||||
maxStoriesWeeklyCount: Int32,
|
||||
maxStoriesMonthlyCount: Int32,
|
||||
maxStoriesSuggestedReactions: Int32
|
||||
maxStoriesSuggestedReactions: Int32,
|
||||
maxGiveawayChannelsCount: Int32
|
||||
) {
|
||||
self.maxPinnedChatCount = maxPinnedChatCount
|
||||
self.maxArchivedPinnedChatCount = maxArchivedPinnedChatCount
|
||||
@ -103,6 +105,7 @@ public enum EngineConfiguration {
|
||||
self.maxStoriesWeeklyCount = maxStoriesWeeklyCount
|
||||
self.maxStoriesMonthlyCount = maxStoriesMonthlyCount
|
||||
self.maxStoriesSuggestedReactions = maxStoriesSuggestedReactions
|
||||
self.maxGiveawayChannelsCount = maxGiveawayChannelsCount
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -159,7 +162,8 @@ public extension EngineConfiguration.UserLimits {
|
||||
maxExpiringStoriesCount: userLimitsConfiguration.maxExpiringStoriesCount,
|
||||
maxStoriesWeeklyCount: userLimitsConfiguration.maxStoriesWeeklyCount,
|
||||
maxStoriesMonthlyCount: userLimitsConfiguration.maxStoriesMonthlyCount,
|
||||
maxStoriesSuggestedReactions: userLimitsConfiguration.maxStoriesSuggestedReactions
|
||||
maxStoriesSuggestedReactions: userLimitsConfiguration.maxStoriesSuggestedReactions,
|
||||
maxGiveawayChannelsCount: userLimitsConfiguration.maxGiveawayChannelsCount
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1452,8 +1452,9 @@ final class ShareWithPeersScreenComponent: Component {
|
||||
}
|
||||
}
|
||||
|
||||
let index = self.selectedPeers.firstIndex(of: peer.id)
|
||||
let togglePeer = {
|
||||
if let index = self.selectedPeers.firstIndex(of: peer.id) {
|
||||
if let index {
|
||||
self.selectedPeers.remove(at: index)
|
||||
self.updateSelectedGroupPeers()
|
||||
} else {
|
||||
@ -1462,11 +1463,12 @@ final class ShareWithPeersScreenComponent: Component {
|
||||
update()
|
||||
}
|
||||
if peer.id.isGroupOrChannel {
|
||||
if case .channels = component.stateContext.subject, self.selectedPeers.count >= 10 {
|
||||
if case .channels = component.stateContext.subject, self.selectedPeers.count >= component.context.userLimits.maxGiveawayChannelsCount, index == nil {
|
||||
self.hapticFeedback.error()
|
||||
return
|
||||
}
|
||||
if case .channels = component.stateContext.subject {
|
||||
if case let .channel(channel) = peer, channel.addressName == nil, !self.selectedPeers.contains(peer.id) {
|
||||
if case let .channel(channel) = peer, channel.addressName == nil, index == nil {
|
||||
let alertController = textAlertController(
|
||||
context: component.context,
|
||||
forceTheme: environment.theme,
|
||||
@ -1488,7 +1490,8 @@ final class ShareWithPeersScreenComponent: Component {
|
||||
update()
|
||||
}
|
||||
} else {
|
||||
if case .members = component.stateContext.subject, self.selectedPeers.count >= 10 {
|
||||
if case .members = component.stateContext.subject, self.selectedPeers.count >= 10, index == nil {
|
||||
self.hapticFeedback.error()
|
||||
return
|
||||
}
|
||||
togglePeer()
|
||||
@ -2359,7 +2362,7 @@ final class ShareWithPeersScreenComponent: Component {
|
||||
case .channels:
|
||||
title = "Add Channels"
|
||||
actionButtonTitle = "Save Channels"
|
||||
subtitle = "select up to 10 channels"
|
||||
subtitle = "select up to \(component.context.userLimits.maxGiveawayChannelsCount) channels"
|
||||
}
|
||||
|
||||
let titleComponent: AnyComponent<Empty>
|
||||
@ -2982,6 +2985,10 @@ public class ShareWithPeersScreen: ViewControllerComponentContainer {
|
||||
}
|
||||
|
||||
deinit {
|
||||
if !self.isDismissed {
|
||||
self.isDismissed = true
|
||||
self.dismissed()
|
||||
}
|
||||
}
|
||||
|
||||
override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user