Folder improvements

This commit is contained in:
Ali 2023-04-04 23:31:04 +04:00
parent 361fa693d9
commit 55b5918841
8 changed files with 177 additions and 22 deletions

View File

@ -9129,3 +9129,7 @@ Sorry for the inconvenience.";
"Channel.AdminLog.JoinedViaFolderInviteLink" = "%1$@ joined via invite link %2$@ (community)";
"Conversation.OpenChatFolder" = "VIEW CHAT LIST";
"Premium.MaxChannelsText" = "You can only join **%1$@** groups and channels. Upgrade to **Telegram Premium** to increase the links limit to **%2$@**.";
"Premium.MaxChannelsNoPremiumText" = "You can only join **%1$@** groups and channels. We are working to let you increase this limit in the future.";
"Premium.MaxChannelsFinalText" = "Sorry, you can only join **%1$@** groups and channels";

View File

@ -898,6 +898,7 @@ public enum PremiumLimitSubject {
case accounts
case linksPerSharedFolder
case membershipInSharedFolders
case channels
}
public protocol ComposeController: ViewController {

View File

@ -1871,6 +1871,18 @@ func openCreateChatListFolderLink(context: AccountContext, folderId: Int32, chec
})
pushController(limitController)
return
case let .tooManyChannels(limit, _):
let limitController = context.sharedContext.makePremiumLimitController(context: context, subject: .linksPerSharedFolder, count: limit, action: {
})
pushController(limitController)
return
case let .tooManyChannelsInAccount(limit, _):
let limitController = context.sharedContext.makePremiumLimitController(context: context, subject: .channels, count: limit, action: {
})
pushController(limitController)
return
}
let presentationData = context.sharedContext.currentPresentationData.with { $0 }

View File

@ -392,19 +392,26 @@ public class CheckLayer: CALayer {
}
if !parameters.theme.filledBorder && !parameters.theme.hasShadow && !parameters.theme.overlayBorder {
checkProgress = parameters.animationProgress
let fillProgress: CGFloat = parameters.animationProgress
context.setFillColor(parameters.theme.backgroundColor.mixedWith(parameters.theme.borderColor, alpha: 1.0 - fillProgress).cgColor)
context.fillEllipse(in: CGRect(origin: CGPoint(), size: size))
let innerDiameter: CGFloat = (fillProgress * 0.0) + (1.0 - fillProgress) * (size.width - borderWidth * 2.0)
context.setBlendMode(.copy)
context.setFillColor(UIColor.clear.cgColor)
context.fillEllipse(in: CGRect(origin: CGPoint(x: (size.width - innerDiameter) * 0.5, y: (size.height - innerDiameter) * 0.5), size: CGSize(width: innerDiameter, height: innerDiameter)))
context.setBlendMode(.normal)
if parameters.theme.isDottedBorder {
checkProgress = 0.0
let borderInset = borderWidth / 2.0 + inset
let borderFrame = CGRect(origin: CGPoint(), size: size).insetBy(dx: borderInset, dy: borderInset)
context.strokeEllipse(in: borderFrame)
} else {
checkProgress = parameters.animationProgress
let fillProgress: CGFloat = parameters.animationProgress
context.setFillColor(parameters.theme.backgroundColor.mixedWith(parameters.theme.borderColor, alpha: 1.0 - fillProgress).cgColor)
context.fillEllipse(in: CGRect(origin: CGPoint(), size: size))
let innerDiameter: CGFloat = (fillProgress * 0.0) + (1.0 - fillProgress) * (size.width - borderWidth * 2.0)
context.setBlendMode(.copy)
context.setFillColor(UIColor.clear.cgColor)
context.fillEllipse(in: CGRect(origin: CGPoint(x: (size.width - innerDiameter) * 0.5, y: (size.height - innerDiameter) * 0.5), size: CGSize(width: innerDiameter, height: innerDiameter)))
context.setBlendMode(.normal)
}
} else {
checkProgress = parameters.animatingOut ? 1.0 : parameters.animationProgress

View File

@ -800,6 +800,25 @@ private final class LimitSheetContent: CombinedComponent {
badgeText = "\(limit)"
string = strings.Premium_MaxChatsInFolderNoPremiumText("\(limit)").string
}
case .channels:
let limit = state.limits.maxChannelsCount
let premiumLimit = state.premiumLimits.maxChannelsCount
iconName = "Premium/Chat"
badgeText = "\(component.count)"
string = component.count >= premiumLimit ? strings.Premium_MaxChannelsFinalText("\(premiumLimit)").string : strings.Premium_MaxChannelsText("\(limit)", "\(premiumLimit)").string
defaultValue = component.count > limit ? "\(limit)" : ""
premiumValue = component.count >= premiumLimit ? "" : "\(premiumLimit)"
if component.count >= premiumLimit {
badgeGraphPosition = max(0.15, CGFloat(limit) / CGFloat(premiumLimit))
} else {
badgeGraphPosition = max(0.15, CGFloat(component.count) / CGFloat(premiumLimit))
}
badgePosition = max(0.15, CGFloat(component.count) / CGFloat(premiumLimit))
if isPremiumDisabled {
badgeText = "\(limit)"
string = strings.Premium_MaxChannelsNoPremiumText("\(limit)").string
}
case .linksPerSharedFolder:
/*let count: Int32 = 5 + Int32("".count)// component.count
let limit: Int32 = 5 + Int32("".count)//state.limits.maxSharedFolderInviteLinks
@ -991,10 +1010,7 @@ private final class LimitSheetContent: CombinedComponent {
gloss: isIncreaseButton,
animationName: isIncreaseButton ? buttonAnimationName : nil,
iconPosition: .right,
action: { [weak component] in
guard let component = component else {
return
}
action: {
component.dismiss()
if isIncreaseButton {
component.action()
@ -1133,6 +1149,7 @@ public class PremiumLimitScreen: ViewControllerComponentContainer {
case accounts
case linksPerSharedFolder
case membershipInSharedFolders
case channels
}
public init(context: AccountContext, subject: PremiumLimitScreen.Subject, count: Int32, action: @escaping () -> Void) {

View File

@ -32,6 +32,8 @@ public enum ExportChatFolderError {
case generic
case sharedFolderLimitExceeded(limit: Int32, premiumLimit: Int32)
case limitExceeded(limit: Int32, premiumLimit: Int32)
case tooManyChannels(limit: Int32, premiumLimit: Int32)
case tooManyChannelsInAccount(limit: Int32, premiumLimit: Int32)
}
public struct ExportedChatFolderLink: Equatable {
@ -94,6 +96,21 @@ func _internal_exportChatFolder(account: Account, filterId: Int32, title: String
}
}
}
} else if error.errorDescription == "USER_CHANNELS_TOO_MUCH" || error.errorDescription == "CHANNELS_TOO_MUCH" {
return account.postbox.transaction { transaction -> (AppConfiguration, Bool) in
return (currentAppConfiguration(transaction: transaction), transaction.getPeer(account.peerId)?.isPremium ?? false)
}
|> castError(ExportChatFolderError.self)
|> mapToSignal { appConfiguration, isPremium -> Signal<Api.chatlists.ExportedChatlistInvite, ExportChatFolderError> in
let userDefaultLimits = UserLimitsConfiguration(appConfiguration: appConfiguration, isPremium: false)
let userPremiumLimits = UserLimitsConfiguration(appConfiguration: appConfiguration, isPremium: true)
if isPremium {
return .fail(.tooManyChannelsInAccount(limit: userPremiumLimits.maxFolderChatsCount, premiumLimit: userPremiumLimits.maxFolderChatsCount))
} else {
return .fail(.tooManyChannelsInAccount(limit: userDefaultLimits.maxFolderChatsCount, premiumLimit: userPremiumLimits.maxFolderChatsCount))
}
}
} else {
return .fail(.generic)
}
@ -391,6 +408,7 @@ public enum JoinChatFolderLinkError {
case dialogFilterLimitExceeded(limit: Int32, premiumLimit: Int32)
case sharedFolderLimitExceeded(limit: Int32, premiumLimit: Int32)
case tooManyChannels(limit: Int32, premiumLimit: Int32)
case tooManyChannelsInAccount(limit: Int32, premiumLimit: Int32)
}
public final class JoinChatFolderResult {
@ -406,6 +424,25 @@ public final class JoinChatFolderResult {
}
func _internal_joinChatFolderLink(account: Account, slug: String, peerIds: [EnginePeer.Id]) -> Signal<JoinChatFolderResult, JoinChatFolderLinkError> {
/*#if DEBUG
if "".isEmpty {
return account.postbox.transaction { transaction -> (AppConfiguration, Bool) in
return (currentAppConfiguration(transaction: transaction), transaction.getPeer(account.peerId)?.isPremium ?? false)
}
|> castError(JoinChatFolderLinkError.self)
|> mapToSignal { appConfiguration, isPremium -> Signal<JoinChatFolderResult, JoinChatFolderLinkError> in
let userDefaultLimits = UserLimitsConfiguration(appConfiguration: appConfiguration, isPremium: false)
let userPremiumLimits = UserLimitsConfiguration(appConfiguration: appConfiguration, isPremium: true)
if isPremium {
return .fail(.tooManyChannelsInAccount(limit: userPremiumLimits.maxFolderChatsCount, premiumLimit: userPremiumLimits.maxFolderChatsCount))
} else {
return .fail(.tooManyChannelsInAccount(limit: userDefaultLimits.maxFolderChatsCount, premiumLimit: userPremiumLimits.maxFolderChatsCount))
}
}
}
#endif*/
return account.postbox.transaction { transaction -> ([Api.InputPeer], Int) in
var newChatCount = 0
for peerId in peerIds {
@ -476,6 +513,21 @@ func _internal_joinChatFolderLink(account: Account, slug: String, peerIds: [Engi
return .fail(.sharedFolderLimitExceeded(limit: userDefaultLimits.maxSharedFolderJoin, premiumLimit: userPremiumLimits.maxSharedFolderJoin))
}
}
} else if error.errorDescription == "CHANNELS_TOO_MUCH" {
return account.postbox.transaction { transaction -> (AppConfiguration, Bool) in
return (currentAppConfiguration(transaction: transaction), transaction.getPeer(account.peerId)?.isPremium ?? false)
}
|> castError(JoinChatFolderLinkError.self)
|> mapToSignal { appConfiguration, isPremium -> Signal<Api.Updates, JoinChatFolderLinkError> in
let userDefaultLimits = UserLimitsConfiguration(appConfiguration: appConfiguration, isPremium: false)
let userPremiumLimits = UserLimitsConfiguration(appConfiguration: appConfiguration, isPremium: true)
if isPremium {
return .fail(.tooManyChannelsInAccount(limit: userPremiumLimits.maxSharedFolderJoin, premiumLimit: userPremiumLimits.maxSharedFolderJoin))
} else {
return .fail(.tooManyChannelsInAccount(limit: userDefaultLimits.maxSharedFolderJoin, premiumLimit: userPremiumLimits.maxSharedFolderJoin))
}
}
} else {
return .fail(.generic)
}

View File

@ -1159,19 +1159,46 @@ private final class ChatFolderLinkPreviewScreenComponent: Component {
return
}
let context = component.context
let navigationController = controller.navigationController as? NavigationController
switch error {
case .generic:
controller.dismiss()
case let .dialogFilterLimitExceeded(limit, _):
let limitController = PremiumLimitScreen(context: component.context, subject: .folders, count: limit, action: {})
let limitController = PremiumLimitScreen(context: component.context, subject: .folders, count: limit, action: { [weak navigationController] in
guard let navigationController else {
return
}
navigationController.pushViewController(PremiumIntroScreen(context: context, source: .folders))
})
controller.push(limitController)
controller.dismiss()
case let .sharedFolderLimitExceeded(limit, _):
let limitController = PremiumLimitScreen(context: component.context, subject: .membershipInSharedFolders, count: limit, action: {})
let limitController = PremiumLimitScreen(context: component.context, subject: .membershipInSharedFolders, count: limit, action: { [weak navigationController] in
guard let navigationController else {
return
}
navigationController.pushViewController(PremiumIntroScreen(context: context, source: .membershipInSharedFolders))
})
controller.push(limitController)
controller.dismiss()
case let .tooManyChannels(limit, _):
let limitController = PremiumLimitScreen(context: component.context, subject: .chatsPerFolder, count: limit, action: {})
let limitController = PremiumLimitScreen(context: component.context, subject: .chatsPerFolder, count: limit, action: { [weak navigationController] in
guard let navigationController else {
return
}
navigationController.pushViewController(PremiumIntroScreen(context: component.context, source: .chatsPerFolder))
})
controller.push(limitController)
controller.dismiss()
case let .tooManyChannelsInAccount(limit, _):
let limitController = PremiumLimitScreen(context: component.context, subject: .channels, count: limit, action: { [weak navigationController] in
guard let navigationController else {
return
}
navigationController.pushViewController(PremiumIntroScreen(context: component.context, source: .groupsAndChannels))
})
controller.push(limitController)
controller.dismiss()
}
@ -1391,23 +1418,56 @@ private final class ChatFolderLinkPreviewScreenComponent: Component {
return
}
let context = component.context
let navigationController = controller.navigationController as? NavigationController
//TODO:localize
let text: String
switch error {
case .generic:
text = "An error occurred"
case let .sharedFolderLimitExceeded(limit, _):
let limitController = component.context.sharedContext.makePremiumLimitController(context: component.context, subject: .membershipInSharedFolders, count: limit, action: {
let limitController = component.context.sharedContext.makePremiumLimitController(context: component.context, subject: .membershipInSharedFolders, count: limit, action: { [weak navigationController] in
guard let navigationController else {
return
}
navigationController.pushViewController(PremiumIntroScreen(context: context, source: .membershipInSharedFolders))
})
controller.push(limitController)
return
case let .limitExceeded(limit, _):
let limitController = component.context.sharedContext.makePremiumLimitController(context: component.context, subject: .linksPerSharedFolder, count: limit, action: {
let limitController = component.context.sharedContext.makePremiumLimitController(context: component.context, subject: .linksPerSharedFolder, count: limit, action: { [weak navigationController] in
guard let navigationController else {
return
}
navigationController.pushViewController(PremiumIntroScreen(context: component.context, source: .linksPerSharedFolder))
})
controller.push(limitController)
return
case let .tooManyChannels(limit, _):
let limitController = PremiumLimitScreen(context: component.context, subject: .chatsPerFolder, count: limit, action: { [weak navigationController] in
guard let navigationController else {
return
}
navigationController.pushViewController(PremiumIntroScreen(context: component.context, source: .chatsPerFolder))
})
controller.push(limitController)
controller.dismiss()
return
case let .tooManyChannelsInAccount(limit, _):
let limitController = PremiumLimitScreen(context: component.context, subject: .channels, count: limit, action: { [weak navigationController] in
guard let navigationController else {
return
}
navigationController.pushViewController(PremiumIntroScreen(context: component.context, source: .groupsAndChannels))
})
controller.push(limitController)
controller.dismiss()
return
}
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }

View File

@ -1680,6 +1680,8 @@ public final class SharedAccountContextImpl: SharedAccountContext {
mappedSubject = .linksPerSharedFolder
case .membershipInSharedFolders:
mappedSubject = .membershipInSharedFolders
case .channels:
mappedSubject = .channels
}
return PremiumLimitScreen(context: context, subject: mappedSubject, count: count, action: action)
}