Various improvements

This commit is contained in:
Ilya Laktyushin
2025-02-22 19:17:36 +04:00
parent eecb2ef5c0
commit 8d7f9bf372
122 changed files with 3454 additions and 1121 deletions

View File

@@ -20,11 +20,13 @@ import Markdown
import GradientBackground
import LegacyComponents
import DrawingUI
import SolidRoundedButtonComponent
import ButtonComponent
import AnimationCache
import EmojiTextAttachmentView
import MediaEditor
import AvatarBackground
import LottieComponent
import UndoUI
public struct AvatarKeyboardInputData: Equatable {
var emoji: EmojiPagerContentComponent
@@ -126,7 +128,14 @@ final class AvatarEditorScreenComponent: Component {
})
}
self.selectedBackground = .gradient(markup.backgroundColors.map { UInt32(bitPattern: $0) })
var isPremium = false
let colorsValue = markup.backgroundColors.map { UInt32(bitPattern: $0) }
if let defaultColor = AvatarBackground.defaultBackgrounds.first(where: { $0.colors == colorsValue}) {
if defaultColor.isPremium {
isPremium = true
}
}
self.selectedBackground = .gradient(colorsValue, isPremium)
self.previousColor = self.selectedBackground
} else {
self.selectedBackground = AvatarBackground.defaultBackgrounds.first!
@@ -188,6 +197,8 @@ final class AvatarEditorScreenComponent: Component {
private let buttonView = ComponentView<Empty>()
private var component: AvatarEditorScreenComponent?
private var environment: EnvironmentType?
private weak var state: State?
private var navigationMetrics: (navigationHeight: CGFloat, statusBarHeight: CGFloat)?
@@ -783,12 +794,15 @@ final class AvatarEditorScreenComponent: Component {
private var isExpanded = false
func update(component: AvatarEditorScreenComponent, availableSize: CGSize, state: State, environment: Environment<ViewControllerComponentContainer.Environment>, transition: ComponentTransition) -> CGSize {
func update(component: AvatarEditorScreenComponent, availableSize: CGSize, state: State, environment: Environment<EnvironmentType>, transition: ComponentTransition) -> CGSize {
self.component = component
let environment = environment[EnvironmentType.self].value
self.environment = environment
self.state = state
let environment = environment[ViewControllerComponentContainer.Environment.self].value
let strings = environment.strings
let theme = environment.theme
let controller = environment.controller
self.controller = {
@@ -990,6 +1004,7 @@ final class AvatarEditorScreenComponent: Component {
transition: transition,
component: AnyComponent(BackgroundColorComponent(
theme: environment.theme,
isPremium: component.context.isPremium,
values: AvatarBackground.defaultBackgrounds,
selectedValue: state.selectedBackground,
customValue: state.customColor,
@@ -1037,8 +1052,8 @@ final class AvatarEditorScreenComponent: Component {
colors: state.selectedBackground.colors,
colorsChanged: { [weak state] colors in
if let state {
state.customColor = .gradient(colors)
state.selectedBackground = .gradient(colors)
state.customColor = .gradient(colors, true)
state.selectedBackground = .gradient(colors, true)
state.updated(transition: .immediate)
}
},
@@ -1268,29 +1283,65 @@ final class AvatarEditorScreenComponent: Component {
case .suggest:
buttonText = strings.AvatarEditor_SuggestProfilePhoto
case .user:
buttonText = strings.AvatarEditor_SetProfilePhoto
//TODO:localize
buttonText = "Set My Photo" //strings.AvatarEditor_SetProfilePhoto
case .group, .forum:
buttonText = strings.AvatarEditor_SetGroupPhoto
case .channel:
buttonText = strings.AvatarEditor_SetChannelPhoto
}
var isLocked = false
if component.peerType != .suggest, !component.context.isPremium {
if state.selectedBackground.isPremium {
isLocked = true
}
if let selectedFile = state.selectedFile {
if selectedFile.isSticker {
isLocked = true
}
}
}
var buttonContents: [AnyComponentWithIdentity<Empty>] = []
buttonContents.append(AnyComponentWithIdentity(id: AnyHashable(buttonText), component: AnyComponent(
Text(text: buttonText, font: Font.semibold(17.0), color: theme.list.itemCheckColors.foregroundColor)
)))
if !component.context.isPremium && isLocked {
buttonContents.append(AnyComponentWithIdentity(id: AnyHashable(0 as Int), component: AnyComponent(LottieComponent(
content: LottieComponent.AppBundleContent(name: "premium_unlock"),
color: theme.list.itemCheckColors.foregroundColor,
startingPosition: .begin,
size: CGSize(width: 30.0, height: 30.0),
loop: true
))))
}
let buttonSize = self.buttonView.update(
transition: transition,
component: AnyComponent(
SolidRoundedButtonComponent(
title: buttonText,
theme: SolidRoundedButtonComponent.Theme(theme: environment.theme),
fontSize: 17.0,
height: 50.0,
cornerRadius: 10.0,
ButtonComponent(
background: ButtonComponent.Background(
color: theme.list.itemCheckColors.fillColor,
foreground: theme.list.itemCheckColors.foregroundColor,
pressedColor: theme.list.itemCheckColors.fillColor.withMultipliedAlpha(0.8)
),
content: AnyComponentWithIdentity(id: AnyHashable(0 as Int), component: AnyComponent(
HStack(buttonContents, spacing: 3.0)
)),
isEnabled: true,
displaysProgress: false,
action: { [weak self] in
self?.complete()
if isLocked {
self?.presentPremiumToast()
} else {
self?.complete()
}
}
)
),
environment: {},
containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: environment.navigationHeight - environment.statusBarHeight)
containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: 50.0)
)
if let buttonView = self.buttonView.view {
if buttonView.superview == nil {
@@ -1298,10 +1349,41 @@ final class AvatarEditorScreenComponent: Component {
}
transition.setFrame(view: buttonView, frame: CGRect(origin: CGPoint(x: sideInset, y: contentHeight), size: buttonSize))
}
let bottomPanelFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight - 4.0), size: CGSize(width: availableSize.width, height: availableSize.height - contentHeight + 4.0))
if let controller = environment.controller(), !controller.automaticallyControlPresentationContextLayout {
let layout = ContainerViewLayout(
size: availableSize,
metrics: environment.metrics,
deviceMetrics: environment.deviceMetrics,
intrinsicInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: bottomPanelFrame.height, right: 0.0),
safeInsets: UIEdgeInsets(top: 0.0, left: environment.safeInsets.left, bottom: 0.0, right: environment.safeInsets.right),
additionalInsets: .zero,
statusBarHeight: environment.statusBarHeight,
inputHeight: nil,
inputHeightIsInteractivellyChanging: false,
inVoiceOver: false
)
controller.presentationContext.containerLayoutUpdated(layout, transition: transition.containedViewLayoutTransition)
}
return availableSize
}
private func presentPremiumToast() {
guard let environment = self.environment, let component = self.component, let parentController = environment.controller() else {
return
}
HapticFeedback().impact(.light)
let controller = premiumAlertController(
context: component.context,
parentController: parentController,
text: environment.strings.AvatarEditor_PremiumNeeded_Background
)
parentController.present(controller, in: .window(.root))
}
private let queue = Queue()
func complete() {
guard let state = self.state, let file = state.selectedFile, let controller = self.controller?() else {
@@ -1531,6 +1613,9 @@ public final class AvatarEditorScreen: ViewControllerComponentContainer {
let componentReady = Promise<Bool>()
super.init(context: context, component: AvatarEditorScreenComponent(context: context, ready: componentReady, peerType: peerType, markup: markup), navigationBarAppearance: .transparent)
self.automaticallyControlPresentationContextLayout = false
self.navigationPresentation = .modal
self.readyValue.set(componentReady.get() |> timeout(0.3, queue: .mainQueue(), alternate: .single(true)))