mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various improvements
This commit is contained in:
parent
575eb2ca5f
commit
c73f24f5f2
@ -13715,6 +13715,7 @@ Sorry for the inconvenience.";
|
||||
"PeerInfo.Gifts.SendGift" = "Send Gift";
|
||||
"PeerInfo.Gifts.ChannelNotify" = "Notify About New Gifts";
|
||||
"PeerInfo.Gifts.ChannelNotifyTooltip" = "You will receive a message from Telegram when your channel receives a gift.";
|
||||
"PeerInfo.Gifts.ChannelNotifyDisabledTooltip" = "You will not receive a message from Telegram when your channel receives a gift.";
|
||||
|
||||
"Notification.StarsGift.Channel.Sent" = "%1$@ sent a gift to %2$@ for %3$@";
|
||||
|
||||
|
@ -87,7 +87,7 @@ public func calculateAvatarColors(context: AccountContext?, explicitColorIndex:
|
||||
}
|
||||
|
||||
let colors: [UIColor]
|
||||
if icon != .none && icon != .cameraIcon {
|
||||
if icon != .none {
|
||||
if case .deletedIcon = icon {
|
||||
colors = AvatarNode.grayscaleColors
|
||||
} else if case .phoneIcon = icon {
|
||||
@ -120,6 +120,8 @@ public func calculateAvatarColors(context: AccountContext?, explicitColorIndex:
|
||||
backgroundColors = theme.chatList.pinnedArchiveAvatarColor.backgroundColors.colors
|
||||
}
|
||||
colors = [backgroundColors.1, backgroundColors.0]
|
||||
} else if case .cameraIcon = icon {
|
||||
colors = AvatarNode.repostColors
|
||||
} else {
|
||||
colors = AvatarNode.grayscaleColors
|
||||
}
|
||||
@ -288,7 +290,7 @@ public final class AvatarNode: ASDisplayNode {
|
||||
]
|
||||
|
||||
static let repostColors: [UIColor] = [
|
||||
UIColor(rgb: 0x34C76F), UIColor(rgb: 0x3DA1FD)
|
||||
UIColor(rgb: 0x3DA1FD), UIColor(rgb: 0x34C76F)
|
||||
]
|
||||
|
||||
public final class ContentNode: ASDisplayNode {
|
||||
|
@ -68,15 +68,15 @@ public struct GridNodeLayout: Equatable {
|
||||
public let scrollIndicatorInsets: UIEdgeInsets?
|
||||
public let preloadSize: CGFloat
|
||||
public let type: GridNodeLayoutType
|
||||
public let cutout: CGRect?
|
||||
public let cutouts: [CGRect]
|
||||
|
||||
public init(size: CGSize, insets: UIEdgeInsets, scrollIndicatorInsets: UIEdgeInsets? = nil, preloadSize: CGFloat, type: GridNodeLayoutType, cutout: CGRect? = nil) {
|
||||
public init(size: CGSize, insets: UIEdgeInsets, scrollIndicatorInsets: UIEdgeInsets? = nil, preloadSize: CGFloat, type: GridNodeLayoutType, cutouts: [CGRect] = []) {
|
||||
self.size = size
|
||||
self.insets = insets
|
||||
self.scrollIndicatorInsets = scrollIndicatorInsets
|
||||
self.preloadSize = preloadSize
|
||||
self.type = type
|
||||
self.cutout = cutout
|
||||
self.cutouts = cutouts
|
||||
}
|
||||
}
|
||||
|
||||
@ -568,9 +568,13 @@ open class GridNode: GridNodeScroller, ASScrollViewDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
if let cutout = self.gridLayout.cutout, cutout.intersects(CGRect(origin: nextItemOrigin, size: itemSize)) {
|
||||
if !self.gridLayout.cutouts.isEmpty, nextItemOrigin.y < itemSize.height * 3.0 {
|
||||
for cutout in self.gridLayout.cutouts {
|
||||
if cutout.intersects(CGRect(origin: nextItemOrigin, size: itemSize)) {
|
||||
nextItemOrigin.x += cutout.width + itemSpacing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !incrementedCurrentRow {
|
||||
incrementedCurrentRow = true
|
||||
|
@ -26,7 +26,7 @@ typedef void (^TGMediaAvatarPresentImpl)(id<LegacyComponentsContext>, void (^)(U
|
||||
@property (nonatomic, copy) void (^requestSearchController)(TGMediaAssetsController *);
|
||||
@property (nonatomic, copy) CGRect (^sourceRect)(void);
|
||||
|
||||
@property (nonatomic, copy) void (^requestAvatarEditor)(void (^)(UIImage *image, void(^commit)(void)), void (^)(UIImage *image, NSURL *asset, TGVideoEditAdjustments *adjustments, void(^commit)(void)));
|
||||
@property (nonatomic, copy) void (^requestAvatarEditor)(void (^)(UIImage *image, void(^commit)(void)), void (^)(UIImage *image, NSURL *asset, id adjustments, id markup, void(^commit)(void)));
|
||||
|
||||
@property (nonatomic, strong) id<TGPhotoPaintStickersContext> stickersContext;
|
||||
|
||||
|
@ -193,60 +193,60 @@
|
||||
}];
|
||||
[itemViews addObject:galleryItem];
|
||||
|
||||
if (!_signup) {
|
||||
TGMenuSheetButtonItemView *viewItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"ProfilePhoto.SetEmoji") type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:^
|
||||
{
|
||||
__strong TGMediaAvatarMenuMixin *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
return;
|
||||
|
||||
__strong TGMenuSheetController *strongController = weakController;
|
||||
if (strongController == nil)
|
||||
return;
|
||||
|
||||
[strongController dismissAnimated:true];
|
||||
if (strongSelf != nil && strongSelf.requestAvatarEditor) {
|
||||
strongSelf.requestAvatarEditor(^(UIImage *image, void (^commit)(void)) {
|
||||
__strong TGMediaAvatarMenuMixin *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
return;
|
||||
|
||||
if (strongSelf.willFinishWithImage != nil) {
|
||||
strongSelf.willFinishWithImage(image, ^{
|
||||
if (strongSelf.didFinishWithImage != nil)
|
||||
strongSelf.didFinishWithImage(image);
|
||||
|
||||
commit();
|
||||
});
|
||||
} else {
|
||||
if (strongSelf.didFinishWithImage != nil)
|
||||
strongSelf.didFinishWithImage(image);
|
||||
|
||||
commit();
|
||||
}
|
||||
}, ^(UIImage *image, NSURL *asset, TGVideoEditAdjustments *adjustments, void (^commit)(void)) {
|
||||
__strong TGMediaAvatarMenuMixin *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
return;
|
||||
|
||||
if (strongSelf.willFinishWithVideo != nil) {
|
||||
strongSelf.willFinishWithVideo(image, ^{
|
||||
if (strongSelf.didFinishWithVideo != nil)
|
||||
strongSelf.didFinishWithVideo(image, asset, adjustments);
|
||||
|
||||
commit();
|
||||
});
|
||||
} else {
|
||||
if (strongSelf.didFinishWithVideo != nil)
|
||||
strongSelf.didFinishWithVideo(image, asset, adjustments);
|
||||
|
||||
commit();
|
||||
}
|
||||
});
|
||||
}
|
||||
}];
|
||||
[itemViews addObject:viewItem];
|
||||
}
|
||||
// if (!_signup) {
|
||||
// TGMenuSheetButtonItemView *viewItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"ProfilePhoto.SetEmoji") type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:^
|
||||
// {
|
||||
// __strong TGMediaAvatarMenuMixin *strongSelf = weakSelf;
|
||||
// if (strongSelf == nil)
|
||||
// return;
|
||||
//
|
||||
// __strong TGMenuSheetController *strongController = weakController;
|
||||
// if (strongController == nil)
|
||||
// return;
|
||||
//
|
||||
// [strongController dismissAnimated:true];
|
||||
// if (strongSelf != nil && strongSelf.requestAvatarEditor) {
|
||||
// strongSelf.requestAvatarEditor(^(UIImage *image, void (^commit)(void)) {
|
||||
// __strong TGMediaAvatarMenuMixin *strongSelf = weakSelf;
|
||||
// if (strongSelf == nil)
|
||||
// return;
|
||||
//
|
||||
// if (strongSelf.willFinishWithImage != nil) {
|
||||
// strongSelf.willFinishWithImage(image, ^{
|
||||
// if (strongSelf.didFinishWithImage != nil)
|
||||
// strongSelf.didFinishWithImage(image);
|
||||
//
|
||||
// commit();
|
||||
// });
|
||||
// } else {
|
||||
// if (strongSelf.didFinishWithImage != nil)
|
||||
// strongSelf.didFinishWithImage(image);
|
||||
//
|
||||
// commit();
|
||||
// }
|
||||
// }, ^(UIImage *image, NSURL *asset, id adjustments, id markup, void (^commit)(void)) {
|
||||
// __strong TGMediaAvatarMenuMixin *strongSelf = weakSelf;
|
||||
// if (strongSelf == nil)
|
||||
// return;
|
||||
//
|
||||
// if (strongSelf.willFinishWithVideo != nil) {
|
||||
// strongSelf.willFinishWithVideo(image, ^{
|
||||
// if (strongSelf.didFinishWithVideo != nil)
|
||||
// strongSelf.didFinishWithVideo(image, asset, adjustments);
|
||||
//
|
||||
// commit();
|
||||
// });
|
||||
// } else {
|
||||
// if (strongSelf.didFinishWithVideo != nil)
|
||||
// strongSelf.didFinishWithVideo(image, asset, adjustments);
|
||||
//
|
||||
// commit();
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// }];
|
||||
// [itemViews addObject:viewItem];
|
||||
// }
|
||||
|
||||
// if (_hasSearchButton)
|
||||
// {
|
||||
|
@ -1546,7 +1546,7 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
||||
let itemSpacing: CGFloat = 1.0
|
||||
let itemWidth = floorToScreenPixels((width - itemSpacing * CGFloat(itemsPerRow - 1)) / CGFloat(itemsPerRow))
|
||||
|
||||
var cutoutRect: CGRect?
|
||||
var cutoutRects: [CGRect] = []
|
||||
var cameraRect: CGRect? = CGRect(origin: CGPoint(x: layout.safeInsets.left, y: 0.0), size: CGSize(width: itemWidth, height: itemWidth * 2.0 + 1.0))
|
||||
if self.cameraView == nil && self.modernCameraView == nil {
|
||||
cameraRect = nil
|
||||
@ -1647,9 +1647,11 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
||||
|
||||
transition.updateFrame(node: self.containerNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: bounds.width, height: bounds.height)))
|
||||
|
||||
cutoutRect = cameraRect
|
||||
if let cameraRect {
|
||||
cutoutRects.append(cameraRect)
|
||||
}
|
||||
if let _ = self.avatarEditorPreviewView {
|
||||
cutoutRect = CGRect(origin: CGPoint(x: layout.safeInsets.left, y: 0.0), size: CGSize(width: cameraRect != nil ? itemWidth * 2.0 : itemWidth, height: itemWidth))
|
||||
cutoutRects.append(CGRect(x: cameraRect != nil ? cameraRect!.maxX + itemSpacing : layout.safeInsets.left, y: 0.0, width: itemWidth, height: itemWidth))
|
||||
}
|
||||
|
||||
var itemHeight = itemWidth
|
||||
@ -1657,7 +1659,7 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
||||
itemHeight = floor(itemWidth * 1.227)
|
||||
}
|
||||
let preloadSize: CGFloat = itemHeight// * 3.0
|
||||
self.gridNode.transaction(GridNodeTransaction(deleteItems: [], insertItems: [], updateItems: [], scrollToItem: nil, updateLayout: GridNodeUpdateLayout(layout: GridNodeLayout(size: bounds.size, insets: gridInsets, scrollIndicatorInsets: nil, preloadSize: preloadSize, type: .fixed(itemSize: CGSize(width: itemWidth, height: itemHeight), fillWidth: true, lineSpacing: itemSpacing, itemSpacing: itemSpacing), cutout: cutoutRect), transition: transition), itemTransition: .immediate, stationaryItems: .none, updateFirstIndexInSectionOffset: nil, updateOpaqueState: nil, synchronousLoads: false), completion: { [weak self] _ in
|
||||
self.gridNode.transaction(GridNodeTransaction(deleteItems: [], insertItems: [], updateItems: [], scrollToItem: nil, updateLayout: GridNodeUpdateLayout(layout: GridNodeLayout(size: bounds.size, insets: gridInsets, scrollIndicatorInsets: nil, preloadSize: preloadSize, type: .fixed(itemSize: CGSize(width: itemWidth, height: itemHeight), fillWidth: true, lineSpacing: itemSpacing, itemSpacing: itemSpacing), cutouts: cutoutRects), transition: transition), itemTransition: .immediate, stationaryItems: .none, updateFirstIndexInSectionOffset: nil, updateOpaqueState: nil, synchronousLoads: false), completion: { [weak self] _ in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
@ -1680,9 +1682,6 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
||||
if let avatarEditorPreviewView = self.avatarEditorPreviewView {
|
||||
avatarEditorPreviewView.frame = CGRect(origin: CGPoint(x: cameraRect != nil ? cameraRect!.maxX + itemSpacing : layout.safeInsets.left, y: 0.0), size: CGSize(width: itemWidth, height: itemWidth))
|
||||
avatarEditorPreviewView.updateLayout(size: CGSize(width: itemWidth, height: itemWidth))
|
||||
if self.gridNode.view.subviews.last !== avatarEditorPreviewView {
|
||||
self.gridNode.view.bringSubviewToFront(avatarEditorPreviewView)
|
||||
}
|
||||
}
|
||||
|
||||
if let selectionNode = self.selectionNode, let controller = self.controller {
|
||||
|
@ -419,8 +419,6 @@ public class AvatarGalleryController: ViewController, StandalonePresentableContr
|
||||
private let centralItemAttributesDisposable = DisposableSet();
|
||||
|
||||
public var openAvatarSetup: ((@escaping () -> Void) -> Void)?
|
||||
public var avatarPhotoEditCompletion: ((UIImage) -> Void)?
|
||||
public var avatarVideoEditCompletion: ((UIImage, URL, TGVideoEditAdjustments?) -> Void)?
|
||||
|
||||
public var removedEntry: ((AvatarGalleryEntry) -> Void)?
|
||||
|
||||
|
@ -815,8 +815,13 @@ func _internal_upgradeStarGift(account: Account, formId: Int64?, reference: Star
|
||||
case let .updateNewMessage(message, _, _):
|
||||
if let message = StoreMessage(apiMessage: message, accountPeerId: account.peerId, peerIsForum: false) {
|
||||
for media in message.media {
|
||||
if let action = media as? TelegramMediaAction, case let .starGiftUnique(gift, _, _, savedToProfile, canExportDate, transferStars, _, _, _, _) = action.action, case let .Id(messageId) = message.id {
|
||||
let _ = messageId
|
||||
if let action = media as? TelegramMediaAction, case let .starGiftUnique(gift, _, _, savedToProfile, canExportDate, transferStars, _, peerId, _, savedId) = action.action, case let .Id(messageId) = message.id {
|
||||
let reference: StarGiftReference
|
||||
if let peerId, let savedId {
|
||||
reference = .peer(peerId: peerId, id: savedId)
|
||||
} else {
|
||||
reference = .message(messageId: messageId)
|
||||
}
|
||||
return .single(ProfileGiftsContext.State.StarGift(
|
||||
gift: gift,
|
||||
reference: reference,
|
||||
@ -1098,6 +1103,14 @@ private final class ProfileGiftsContextImpl {
|
||||
}
|
||||
}
|
||||
|
||||
func toggleStarGiftsNotifications(enabled: Bool) {
|
||||
self.actionDisposable.set(
|
||||
_internal_toggleStarGiftsNotifications(account: self.account, peerId: self.peerId, enabled: enabled).startStrict()
|
||||
)
|
||||
self.notificationsEnabled = enabled
|
||||
self.pushState()
|
||||
}
|
||||
|
||||
private func pushState() {
|
||||
self._state = ProfileGiftsContext.State(gifts: self.gifts, count: self.count, dataState: self.dataState, notificationsEnabled: self.notificationsEnabled)
|
||||
self.stateValue.set(.single(ProfileGiftsContext.State(gifts: self.gifts, count: self.count, dataState: self.dataState, notificationsEnabled: self.notificationsEnabled)))
|
||||
@ -1330,6 +1343,12 @@ public final class ProfileGiftsContext {
|
||||
}
|
||||
}
|
||||
|
||||
public func toggleStarGiftsNotifications(enabled: Bool) {
|
||||
self.impl.with { impl in
|
||||
impl.toggleStarGiftsNotifications(enabled: enabled)
|
||||
}
|
||||
}
|
||||
|
||||
public var currentState: ProfileGiftsContext.State? {
|
||||
var state: ProfileGiftsContext.State?
|
||||
self.impl.syncWith { impl in
|
||||
|
@ -1464,10 +1464,16 @@ func _internal_sendStarsPaymentForm(account: Account, formId: Int64, source: Bot
|
||||
case .giftCode, .stars, .starsGift, .starsChatSubscription, .starGift, .starGiftUpgrade, .starGiftTransfer:
|
||||
receiptMessageId = nil
|
||||
}
|
||||
} else if case let .starGiftUnique(gift, _, _, savedToProfile, canExportDate, transferStars, _, _, _, _) = action.action, case let .Id(messageId) = message.id {
|
||||
} else if case let .starGiftUnique(gift, _, _, savedToProfile, canExportDate, transferStars, _, peerId, _, savedId) = action.action, case let .Id(messageId) = message.id {
|
||||
let reference: StarGiftReference
|
||||
if let peerId, let savedId {
|
||||
reference = .peer(peerId: peerId, id: savedId)
|
||||
} else {
|
||||
reference = .message(messageId: messageId)
|
||||
}
|
||||
resultGift = ProfileGiftsContext.State.StarGift(
|
||||
gift: gift,
|
||||
reference: .message(messageId: messageId),
|
||||
reference: reference,
|
||||
fromPeer: nil,
|
||||
date: message.timestamp,
|
||||
text: nil,
|
||||
|
@ -1374,31 +1374,50 @@ final class AvatarEditorScreenComponent: Component {
|
||||
}
|
||||
}
|
||||
|
||||
let colors: [NSNumber] = state.selectedBackground.colors.map { Int32(bitPattern: $0) as NSNumber }
|
||||
let backgroundColors = state.selectedBackground.colors.map { Int32(bitPattern: $0) }
|
||||
guard let codableEntity = CodableDrawingEntity(entity: entity) else {
|
||||
return
|
||||
}
|
||||
|
||||
let entitiesData = DrawingEntitiesView.encodeEntitiesData([entity])
|
||||
|
||||
let paintingData = TGPaintingData(
|
||||
drawing: nil,
|
||||
entitiesData: entitiesData,
|
||||
image: nil,
|
||||
stillImage: nil,
|
||||
hasAnimation: entity.isAnimated,
|
||||
stickers: []
|
||||
)
|
||||
|
||||
let adjustments = PGPhotoEditorValues(
|
||||
originalSize: size,
|
||||
let values = MediaEditorValues(
|
||||
peerId: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(0)),
|
||||
originalDimensions: PixelDimensions(size),
|
||||
cropOffset: .zero,
|
||||
cropRect: CGRect(origin: .zero, size: size),
|
||||
cropScale: 1.0,
|
||||
cropRotation: 0.0,
|
||||
cropOrientation: .up,
|
||||
cropLockedAspectRatio: 1.0,
|
||||
cropMirrored: false,
|
||||
cropMirroring: false,
|
||||
cropOrientation: nil,
|
||||
gradientColors: nil,
|
||||
videoTrimRange: nil,
|
||||
videoIsMuted: false,
|
||||
videoIsFullHd: false,
|
||||
videoIsMirrored: false,
|
||||
videoVolume: nil,
|
||||
additionalVideoPath: nil,
|
||||
additionalVideoIsDual: false,
|
||||
additionalVideoPosition: nil,
|
||||
additionalVideoScale: nil,
|
||||
additionalVideoRotation: nil,
|
||||
additionalVideoPositionChanges: [],
|
||||
additionalVideoTrimRange: nil,
|
||||
additionalVideoOffset: nil,
|
||||
additionalVideoVolume: nil,
|
||||
collage: [],
|
||||
nightTheme: false,
|
||||
drawing: nil,
|
||||
maskDrawing: nil,
|
||||
entities: [codableEntity],
|
||||
toolValues: [:],
|
||||
paintingData: paintingData,
|
||||
sendAsGif: true
|
||||
audioTrack: nil,
|
||||
audioTrackTrimRange: nil,
|
||||
audioTrackOffset: nil,
|
||||
audioTrackVolume: nil,
|
||||
audioTrackSamples: nil,
|
||||
collageTrackSamples: nil,
|
||||
coverImageTimestamp: nil,
|
||||
qualityPreset: .profileHigh
|
||||
)
|
||||
let preset: TGMediaVideoConversionPreset = TGMediaVideoConversionPresetProfileHigh
|
||||
|
||||
let combinedImage = generateImage(size, contextGenerator: { size, context in
|
||||
let bounds = CGRect(origin: .zero, size: size)
|
||||
@ -1415,12 +1434,19 @@ final class AvatarEditorScreenComponent: Component {
|
||||
}, opaque: false)!
|
||||
|
||||
if entity.isAnimated {
|
||||
let markup: UploadPeerPhotoMarkup
|
||||
if stickerPackId != 0 {
|
||||
controller.videoCompletion(combinedImage, tempUrl, TGVideoEditAdjustments(photoEditorValues: adjustments, preset: preset, stickerPackId: stickerPackId, stickerPackAccessHash: stickerPackAccessHash, documentId: fileId, colors: colors), { [weak controller] in
|
||||
markup = .sticker(packReference: .id(id: stickerPackId, accessHash: stickerPackAccessHash), fileId: fileId, backgroundColors: backgroundColors)
|
||||
} else {
|
||||
markup = .emoji(fileId: fileId, backgroundColors: backgroundColors)
|
||||
}
|
||||
|
||||
if stickerPackId != 0 {
|
||||
controller.videoCompletion(combinedImage, tempUrl, values, markup, { [weak controller] in
|
||||
controller?.dismiss()
|
||||
})
|
||||
} else {
|
||||
controller.videoCompletion(combinedImage, tempUrl, TGVideoEditAdjustments(photoEditorValues: adjustments, preset: preset, documentId: fileId, colors: colors), { [weak controller] in
|
||||
controller.videoCompletion(combinedImage, tempUrl, values, markup, { [weak controller] in
|
||||
controller?.dismiss()
|
||||
})
|
||||
}
|
||||
@ -1461,7 +1487,7 @@ public final class AvatarEditorScreen: ViewControllerComponentContainer {
|
||||
}
|
||||
|
||||
public var imageCompletion: (UIImage, @escaping () -> Void) -> Void = { _, _ in }
|
||||
public var videoCompletion: (UIImage, URL, TGVideoEditAdjustments, @escaping () -> Void) -> Void = { _, _, _, _ in }
|
||||
public var videoCompletion: (UIImage, URL, MediaEditorValues, UploadPeerPhotoMarkup, @escaping () -> Void) -> Void = { _, _, _, _, _ in }
|
||||
|
||||
public static func inputData(context: AccountContext, isGroup: Bool) -> Signal<AvatarKeyboardInputData, NoError> {
|
||||
let emojiItems = EmojiPagerContentComponent.emojiInputData(
|
||||
|
@ -3959,6 +3959,9 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
|
||||
return
|
||||
}
|
||||
if gestureRecognizer.numberOfTouches == 2, let subject = self.subject, !self.entitiesView.hasSelection {
|
||||
if case .avatarEditor = self.controller?.mode {
|
||||
return
|
||||
}
|
||||
switch subject {
|
||||
case .message, .gift:
|
||||
return
|
||||
@ -3979,6 +3982,9 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
|
||||
return
|
||||
}
|
||||
if gestureRecognizer.numberOfTouches == 2, let subject = self.subject, !self.entitiesView.hasSelection {
|
||||
if case .avatarEditor = self.controller?.mode {
|
||||
return
|
||||
}
|
||||
switch subject {
|
||||
case .message, .gift:
|
||||
return
|
||||
@ -3999,6 +4005,9 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
|
||||
return
|
||||
}
|
||||
if gestureRecognizer.numberOfTouches == 2, let subject = self.subject, !self.entitiesView.hasSelection {
|
||||
if case .avatarEditor = self.controller?.mode {
|
||||
return
|
||||
}
|
||||
switch subject {
|
||||
case .message, .gift:
|
||||
return
|
||||
@ -4168,19 +4177,20 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
|
||||
let sourceAspectRatio = sourceLocalFrame.height / sourceLocalFrame.width
|
||||
|
||||
let duration: Double = 0.4
|
||||
let timingFunction = kCAMediaTimingFunctionSpring
|
||||
|
||||
self.previewContainerView.layer.animatePosition(from: sourceLocalFrame.center, to: self.previewContainerView.center, duration: duration, timingFunction: kCAMediaTimingFunctionSpring, completion: { _ in
|
||||
self.previewContainerView.layer.animatePosition(from: sourceLocalFrame.center, to: self.previewContainerView.center, duration: duration, timingFunction: timingFunction, completion: { _ in
|
||||
completion()
|
||||
})
|
||||
self.previewContainerView.layer.animateScale(from: sourceScale, to: 1.0, duration: duration, timingFunction: kCAMediaTimingFunctionSpring)
|
||||
self.previewContainerView.layer.animateBounds(from: CGRect(origin: CGPoint(x: 0.0, y: (self.previewContainerView.bounds.height - self.previewContainerView.bounds.width * sourceAspectRatio) / 2.0), size: CGSize(width: self.previewContainerView.bounds.width, height: self.previewContainerView.bounds.width * sourceAspectRatio)), to: self.previewContainerView.bounds, duration: duration, timingFunction: kCAMediaTimingFunctionSpring)
|
||||
self.previewContainerView.layer.animateBounds(from: CGRect(origin: CGPoint(x: 0.0, y: (self.previewContainerView.bounds.height - self.previewContainerView.bounds.width * sourceAspectRatio) / 2.0), size: CGSize(width: self.previewContainerView.bounds.width, height: self.previewContainerView.bounds.width * sourceAspectRatio)), to: self.previewContainerView.bounds, duration: duration, timingFunction: timingFunction)
|
||||
|
||||
self.backgroundDimView.isHidden = false
|
||||
self.backgroundDimView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25)
|
||||
self.backgroundDimView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.35)
|
||||
|
||||
if let componentView = self.componentHost.view {
|
||||
componentView.layer.animatePosition(from: sourceLocalFrame.center, to: componentView.center, duration: duration, timingFunction: kCAMediaTimingFunctionSpring)
|
||||
componentView.layer.animateScale(from: sourceScale, to: 1.0, duration: duration, timingFunction: kCAMediaTimingFunctionSpring)
|
||||
componentView.layer.animateScale(from: sourceScale, to: 1.0, duration: duration, timingFunction: timingFunction)
|
||||
componentView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
|
||||
}
|
||||
}
|
||||
@ -5231,7 +5241,9 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
|
||||
let result = super.hitTest(point, with: event)
|
||||
if result == self.componentHost.view {
|
||||
let point = self.view.convert(point, to: self.previewContainerView)
|
||||
return self.previewContainerView.hitTest(point, with: event)
|
||||
if let previewResult = self.previewContainerView.hitTest(point, with: event) {
|
||||
return previewResult
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
@ -6189,7 +6201,8 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
|
||||
fileprivate let transitionOut: (Bool, Bool?) -> TransitionOut?
|
||||
|
||||
public var cancelled: (Bool) -> Void = { _ in }
|
||||
public var completion: (MediaEditorScreenImpl.Result, @escaping (@escaping () -> Void) -> Void) -> Void = { _, _ in }
|
||||
public var willComplete: (UIImage?, Bool, @escaping () -> Void) -> Void
|
||||
public var completion: (MediaEditorScreenImpl.Result, @escaping (@escaping () -> Void) -> Void) -> Void
|
||||
public var dismissed: () -> Void = { }
|
||||
public var willDismiss: () -> Void = { }
|
||||
public var sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)?
|
||||
@ -6222,6 +6235,7 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
|
||||
initialLink: (url: String, name: String?)? = nil,
|
||||
transitionIn: TransitionIn?,
|
||||
transitionOut: @escaping (Bool, Bool?) -> TransitionOut?,
|
||||
willComplete: @escaping (UIImage?, Bool, @escaping () -> Void) -> Void = { _, _, commit in commit() },
|
||||
completion: @escaping (MediaEditorScreenImpl.Result, @escaping (@escaping () -> Void) -> Void) -> Void
|
||||
) {
|
||||
self.context = context
|
||||
@ -6238,6 +6252,7 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
|
||||
self.initialLink = initialLink
|
||||
self.transitionIn = transitionIn
|
||||
self.transitionOut = transitionOut
|
||||
self.willComplete = willComplete
|
||||
self.completion = completion
|
||||
|
||||
self.storiesBlockedPeers = BlockedPeersContext(account: context.account, subject: .stories)
|
||||
@ -7401,6 +7416,10 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
|
||||
|
||||
makeEditorImageComposition(context: self.node.ciContext, postbox: self.context.account.postbox, inputImage: inputImage, dimensions: storyDimensions, values: mediaEditor.values, time: firstFrameTime, textScale: 2.0, completion: { [weak self] coverImage in
|
||||
if let self {
|
||||
self.willComplete(coverImage, true, { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
Logger.shared.log("MediaEditor", "Completed with video \(videoResult)")
|
||||
self.completion(MediaEditorScreenImpl.Result(media: .video(video: videoResult, coverImage: coverImage, values: mediaEditor.values, duration: duration, dimensions: mediaEditor.values.resultDimensions), mediaAreas: mediaAreas, caption: caption, coverTimestamp: mediaEditor.values.coverImageTimestamp, options: self.state.privacy, stickers: stickers, randomId: randomId), { [weak self] finished in
|
||||
self?.node.animateOut(finished: true, saveDraft: false, completion: { [weak self] in
|
||||
@ -7410,6 +7429,7 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -7430,6 +7450,10 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
|
||||
}
|
||||
makeEditorImageComposition(context: self.node.ciContext, postbox: self.context.account.postbox, inputImage: image, dimensions: storyDimensions, outputDimensions: outputDimensions, values: values, time: .zero, textScale: 2.0, completion: { [weak self] resultImage in
|
||||
if let self, let resultImage {
|
||||
self.willComplete(resultImage, false, { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
Logger.shared.log("MediaEditor", "Completed with image \(resultImage)")
|
||||
self.completion(MediaEditorScreenImpl.Result(media: .image(image: resultImage, dimensions: PixelDimensions(resultImage.size)), mediaAreas: mediaAreas, caption: caption, coverTimestamp: nil, options: self.state.privacy, stickers: stickers, randomId: randomId), { [weak self] finished in
|
||||
self?.node.animateOut(finished: true, saveDraft: false, completion: { [weak self] in
|
||||
@ -7442,6 +7466,7 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
|
||||
if case let .draft(draft, id) = actualSubject, id == nil {
|
||||
removeStoryDraft(engine: self.context.engine, path: draft.path, delete: true)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -1579,9 +1579,10 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
||||
hasSavedMessageTags,
|
||||
isPremiumRequiredForStoryPosting,
|
||||
starsRevenueContextAndState,
|
||||
revenueContextAndState
|
||||
revenueContextAndState,
|
||||
profileGiftsContext.state
|
||||
)
|
||||
|> map { peerView, availablePanes, globalNotificationSettings, status, currentInvitationsContext, invitations, currentRequestsContext, requests, hasStories, accountIsPremium, recommendedChannels, hasSavedMessages, hasSavedMessagesChats, hasSavedMessageTags, isPremiumRequiredForStoryPosting, starsRevenueContextAndState, revenueContextAndState -> PeerInfoScreenData in
|
||||
|> map { peerView, availablePanes, globalNotificationSettings, status, currentInvitationsContext, invitations, currentRequestsContext, requests, hasStories, accountIsPremium, recommendedChannels, hasSavedMessages, hasSavedMessagesChats, hasSavedMessageTags, isPremiumRequiredForStoryPosting, starsRevenueContextAndState, revenueContextAndState, profileGiftsState -> PeerInfoScreenData in
|
||||
var availablePanes = availablePanes
|
||||
if let hasStories {
|
||||
if hasStories {
|
||||
@ -1605,7 +1606,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
||||
}
|
||||
|
||||
if availablePanes != nil, let cachedData = peerView.cachedData as? CachedChannelData {
|
||||
if let starGiftsCount = cachedData.starGiftsCount, starGiftsCount > 0 {
|
||||
if (cachedData.starGiftsCount ?? 0) > 0 || (profileGiftsState.count ?? 0) > 0 {
|
||||
availablePanes?.insert(.gifts, at: hasStories ? 1 : 0)
|
||||
}
|
||||
}
|
||||
|
@ -9610,6 +9610,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
currentIsVideo = !videoRepresentations.isEmpty
|
||||
emojiMarkup = emojiMarkupValue
|
||||
}
|
||||
let _ = emojiMarkup
|
||||
|
||||
let peerId = self.peerId
|
||||
let _ = (self.context.engine.data.get(
|
||||
@ -9685,31 +9686,31 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
let mixin = TGMediaAvatarMenuMixin(context: legacyController.context, parentController: emptyController, hasSearchButton: true, hasDeleteButton: hasDeleteButton, hasViewButton: false, personalPhoto: strongSelf.isSettings || strongSelf.isMyProfile, isVideo: currentIsVideo, saveEditedPhotos: false, saveCapturedMedia: false, signup: false, forum: isForum, title: title, isSuggesting: [.custom, .suggest].contains(mode))!
|
||||
mixin.stickersContext = LegacyPaintStickersContext(context: strongSelf.context)
|
||||
let _ = strongSelf.currentAvatarMixin.swap(mixin)
|
||||
var isFromEditor = false
|
||||
mixin.requestAvatarEditor = { [weak self, weak parentController] imageCompletion, videoCompletion in
|
||||
guard let strongSelf = self, let imageCompletion, let videoCompletion else {
|
||||
return
|
||||
}
|
||||
let peerType: AvatarEditorScreen.PeerType
|
||||
if mode == .suggest {
|
||||
peerType = .suggest
|
||||
} else if case .legacyGroup = peer {
|
||||
peerType = .group
|
||||
} else if case let .channel(channel) = peer {
|
||||
if case .group = channel.info {
|
||||
peerType = channel.flags.contains(.isForum) ? .forum : .group
|
||||
} else {
|
||||
peerType = .channel
|
||||
}
|
||||
} else {
|
||||
peerType = .user
|
||||
}
|
||||
let controller = AvatarEditorScreen(context: strongSelf.context, inputData: keyboardInputData.get(), peerType: peerType, markup: emojiMarkup)
|
||||
controller.imageCompletion = imageCompletion
|
||||
controller.videoCompletion = videoCompletion
|
||||
parentController?.push(controller)
|
||||
isFromEditor = true
|
||||
}
|
||||
let isFromEditor = !"".isEmpty
|
||||
// mixin.requestAvatarEditor = { [weak self, weak parentController] imageCompletion, videoCompletion in
|
||||
// guard let strongSelf = self, let imageCompletion, let videoCompletion else {
|
||||
// return
|
||||
// }
|
||||
// let peerType: AvatarEditorScreen.PeerType
|
||||
// if mode == .suggest {
|
||||
// peerType = .suggest
|
||||
// } else if case .legacyGroup = peer {
|
||||
// peerType = .group
|
||||
// } else if case let .channel(channel) = peer {
|
||||
// if case .group = channel.info {
|
||||
// peerType = channel.flags.contains(.isForum) ? .forum : .group
|
||||
// } else {
|
||||
// peerType = .channel
|
||||
// }
|
||||
// } else {
|
||||
// peerType = .user
|
||||
// }
|
||||
// let controller = AvatarEditorScreen(context: strongSelf.context, inputData: keyboardInputData.get(), peerType: peerType, markup: emojiMarkup)
|
||||
// controller.imageCompletion = imageCompletion
|
||||
// controller.videoCompletion = videoCompletion
|
||||
// parentController?.push(controller)
|
||||
// isFromEditor = true
|
||||
// }
|
||||
|
||||
if let confirmationTextPhoto, let confirmationAction {
|
||||
mixin.willFinishWithImage = { [weak self, weak parentController] image, commit in
|
||||
@ -9737,12 +9738,12 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
self?.controller?.updateProfilePhoto(image, mode: mode, uploadStatus: nil)
|
||||
}
|
||||
}
|
||||
mixin.didFinishWithVideo = { [weak self] image, asset, adjustments in
|
||||
if let image = image, let asset = asset {
|
||||
completion(image)
|
||||
self?.controller?.updateProfileVideo(image, asset: asset, adjustments: adjustments, mode: mode)
|
||||
}
|
||||
}
|
||||
// mixin.didFinishWithVideo = { [weak self] image, asset, adjustments, _ in
|
||||
// if let image = image, let asset = asset {
|
||||
// completion(image)
|
||||
// self?.controller?.updateProfileVideo(image, asset: asset, adjustments: adjustments, mode: mode)
|
||||
// }
|
||||
// }
|
||||
mixin.didFinishWithDelete = {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
@ -12238,12 +12239,6 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
completion()
|
||||
})
|
||||
}
|
||||
galleryController.avatarPhotoEditCompletion = { [weak self] image in
|
||||
self?.controller?.updateProfilePhoto(image, mode: .generic, uploadStatus: nil)
|
||||
}
|
||||
galleryController.avatarVideoEditCompletion = { [weak self] image, asset, adjustments in
|
||||
self?.controller?.updateProfileVideo(image, asset: asset, adjustments: adjustments, mode: .generic)
|
||||
}
|
||||
galleryController.removedEntry = { [weak self] entry in
|
||||
if let item = PeerInfoAvatarListItem(entry: entry) {
|
||||
let _ = self?.headerNode.avatarListNode.listContainerNode.deleteItem(item)
|
||||
|
@ -69,7 +69,32 @@ extension PeerInfoScreenImpl {
|
||||
}
|
||||
}
|
||||
|
||||
let _ = hasDeleteButton
|
||||
struct ConfirmationAlert {
|
||||
let title: String
|
||||
let photoText: String
|
||||
let videoText: String
|
||||
let action: String
|
||||
}
|
||||
|
||||
let confirmationAlert: ConfirmationAlert?
|
||||
switch mode {
|
||||
case .suggest:
|
||||
confirmationAlert = ConfirmationAlert(
|
||||
title: self.presentationData.strings.UserInfo_SuggestPhotoTitle(peer.compactDisplayTitle).string,
|
||||
photoText: self.presentationData.strings.UserInfo_SuggestPhoto_AlertPhotoText(peer.compactDisplayTitle).string,
|
||||
videoText: self.presentationData.strings.UserInfo_SuggestPhoto_AlertVideoText(peer.compactDisplayTitle).string,
|
||||
action: self.presentationData.strings.UserInfo_SuggestPhoto_AlertSuggest
|
||||
)
|
||||
case .custom:
|
||||
confirmationAlert = ConfirmationAlert(
|
||||
title: self.presentationData.strings.UserInfo_SetCustomPhotoTitle(peer.compactDisplayTitle).string,
|
||||
photoText: self.presentationData.strings.UserInfo_SetCustomPhoto_AlertPhotoText(peer.compactDisplayTitle, peer.compactDisplayTitle).string,
|
||||
videoText: self.presentationData.strings.UserInfo_SetCustomPhoto_AlertVideoText(peer.compactDisplayTitle, peer.compactDisplayTitle).string,
|
||||
action: self.presentationData.strings.UserInfo_SetCustomPhoto_AlertSet
|
||||
)
|
||||
default:
|
||||
confirmationAlert = nil
|
||||
}
|
||||
|
||||
let parentController = (self.context.sharedContext.mainWindow?.viewController as? NavigationController)?.topViewController as? ViewController
|
||||
|
||||
@ -77,6 +102,9 @@ extension PeerInfoScreenImpl {
|
||||
let mainController = self.context.sharedContext.makeAvatarMediaPickerScreen(context: self.context, getSourceRect: { return nil }, canDelete: hasDeleteButton, performDelete: { [weak self] in
|
||||
self?.openAvatarRemoval(mode: mode, peer: peer, item: item)
|
||||
}, completion: { result, transitionView, transitionRect, transitionImage, fromCamera, transitionOut, cancelled in
|
||||
var resultImage: UIImage?
|
||||
let uploadStatusPromise = Promise<PeerInfoAvatarUploadStatus>(.progress(0.0))
|
||||
|
||||
let subject: Signal<MediaEditorScreenImpl.Subject?, NoError>
|
||||
if let asset = result as? PHAsset {
|
||||
subject = .single(.asset(asset))
|
||||
@ -112,15 +140,21 @@ extension PeerInfoScreenImpl {
|
||||
peerType = .user
|
||||
}
|
||||
let controller = AvatarEditorScreen(context: self.context, inputData: keyboardInputData.get(), peerType: peerType, markup: emojiMarkup)
|
||||
//controller.imageCompletion = imageCompletion
|
||||
//controller.videoCompletion = videoCompletion
|
||||
controller.imageCompletion = { [weak self] image, commit in
|
||||
resultImage = image
|
||||
self?.updateProfilePhoto(image, mode: mode, uploadStatus: uploadStatusPromise)
|
||||
commit()
|
||||
}
|
||||
controller.videoCompletion = { [weak self] image, url, values, markup, commit in
|
||||
resultImage = image
|
||||
self?.updateProfileVideo(image, asset: url, values: values, markup: markup, mode: mode, uploadStatus: uploadStatusPromise)
|
||||
commit()
|
||||
}
|
||||
parentController?.push(controller)
|
||||
//isFromEditor = true
|
||||
return
|
||||
}
|
||||
|
||||
var resultImage: UIImage?
|
||||
let uploadStatusPromise = Promise<PeerInfoAvatarUploadStatus>(.progress(0.0))
|
||||
let editorController = MediaEditorScreenImpl(
|
||||
context: self.context,
|
||||
mode: .avatarEditor,
|
||||
@ -153,7 +187,18 @@ extension PeerInfoScreenImpl {
|
||||
)
|
||||
}
|
||||
return nil
|
||||
}, completion: { [weak self] result, commit in
|
||||
},
|
||||
willComplete: { [weak self, weak parentController] image, isVideo, commit in
|
||||
if let self, let confirmationAlert, let image {
|
||||
let controller = photoUpdateConfirmationController(context: self.context, peer: peer, image: image, text: isVideo ? confirmationAlert.videoText : confirmationAlert.photoText, doneTitle: confirmationAlert.action, commit: {
|
||||
commit()
|
||||
})
|
||||
parentController?.presentInGlobalOverlay(controller)
|
||||
} else {
|
||||
commit()
|
||||
}
|
||||
},
|
||||
completion: { [weak self] result, commit in
|
||||
switch result.media {
|
||||
case let .image(image, _):
|
||||
resultImage = image
|
||||
@ -161,10 +206,8 @@ extension PeerInfoScreenImpl {
|
||||
commit({})
|
||||
case let .video(video, coverImage, values, _, _):
|
||||
if let coverImage {
|
||||
let _ = values
|
||||
//TODO:release
|
||||
resultImage = coverImage
|
||||
self?.updateProfileVideo(coverImage, asset: video, adjustments: nil, mode: mode)
|
||||
self?.updateProfileVideo(coverImage, asset: video, values: values, markup: nil, mode: mode, uploadStatus: uploadStatusPromise)
|
||||
}
|
||||
commit({})
|
||||
default:
|
||||
@ -416,227 +459,135 @@ extension PeerInfoScreenImpl {
|
||||
}))
|
||||
}
|
||||
|
||||
// public func updateProfileVideo(_ image: UIImage, video: MediaEditorScreenImpl.MediaResult.VideoResult, values: MediaEditorValues, mode: PeerInfoAvatarEditingMode) {
|
||||
// var markup: UploadPeerPhotoMarkup? = nil
|
||||
// if let fileId = adjustments?.documentId, let backgroundColors = adjustments?.colors as? [Int32], fileId != 0 {
|
||||
// if let packId = adjustments?.stickerPackId, let accessHash = adjustments?.stickerPackAccessHash, packId != 0 {
|
||||
// markup = .sticker(packReference: .id(id: packId, accessHash: accessHash), fileId: fileId, backgroundColors: backgroundColors)
|
||||
// } else {
|
||||
// markup = .emoji(fileId: fileId, backgroundColors: backgroundColors)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// var videoStartTimestamp: Double? = nil
|
||||
// if let adjustments = adjustments, adjustments.videoStartValue > 0.0 {
|
||||
// videoStartTimestamp = adjustments.videoStartValue - adjustments.trimStartValue
|
||||
// }
|
||||
//
|
||||
// var uploadVideo = true
|
||||
// if let _ = markup {
|
||||
// if let data = self.context.currentAppConfiguration.with({ $0 }).data, let uploadVideoValue = data["upload_markup_video"] as? Bool, uploadVideoValue {
|
||||
// uploadVideo = true
|
||||
// } else {
|
||||
// uploadVideo = false
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// guard let photoResource = self.setupProfilePhotoUpload(image: image, mode: mode, indefiniteProgress: !uploadVideo) else {
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// let context = self.context
|
||||
//
|
||||
// let videoResource: Signal<TelegramMediaResource?, UploadPeerPhotoError>
|
||||
// if uploadVideo {
|
||||
// let path = NSTemporaryDirectory() + "\(Int64.random(in: Int64.min ... Int64.max)).mp4"
|
||||
// let videoExport = MediaEditorVideoExport(
|
||||
// postbox: context.account.postbox,
|
||||
// subject: .image(image: image),
|
||||
// configuration: configuration,
|
||||
// outputPath: path
|
||||
// )
|
||||
//
|
||||
// videoResource = Signal<TelegramMediaResource?, UploadPeerPhotoError> { [weak self] subscriber in
|
||||
// let entityRenderer: LegacyPaintEntityRenderer? = adjustments.flatMap { adjustments in
|
||||
// if let paintingData = adjustments.paintingData, paintingData.hasAnimation {
|
||||
// return LegacyPaintEntityRenderer(postbox: account.postbox, adjustments: adjustments)
|
||||
// } else {
|
||||
// return nil
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// let tempFile = EngineTempBox.shared.tempFile(fileName: "video.mp4")
|
||||
// let uploadInterface = LegacyLiveUploadInterface(context: context)
|
||||
// let signal: SSignal
|
||||
// if let url = asset as? URL, url.absoluteString.hasSuffix(".jpg"), let data = try? Data(contentsOf: url, options: [.mappedRead]), let image = UIImage(data: data), let entityRenderer = entityRenderer {
|
||||
// let durationSignal: SSignal = SSignal(generator: { subscriber in
|
||||
// let disposable = (entityRenderer.duration()).start(next: { duration in
|
||||
// subscriber.putNext(duration)
|
||||
// subscriber.putCompletion()
|
||||
// })
|
||||
//
|
||||
// return SBlockDisposable(block: {
|
||||
// disposable.dispose()
|
||||
// })
|
||||
// })
|
||||
// signal = durationSignal.map(toSignal: { duration -> SSignal in
|
||||
// if let duration = duration as? Double {
|
||||
// return TGMediaVideoConverter.renderUIImage(image, duration: duration, adjustments: adjustments, path: tempFile.path, watcher: nil, entityRenderer: entityRenderer)!
|
||||
// } else {
|
||||
// return SSignal.single(nil)
|
||||
// }
|
||||
// })
|
||||
// } else if let asset = asset as? AVAsset {
|
||||
// signal = TGMediaVideoConverter.convert(asset, adjustments: adjustments, path: tempFile.path, watcher: uploadInterface, entityRenderer: entityRenderer)!
|
||||
// } else {
|
||||
// signal = SSignal.complete()
|
||||
// }
|
||||
//
|
||||
// let signalDisposable = signal.start(next: { next in
|
||||
// if let result = next as? TGMediaVideoConversionResult {
|
||||
// if let image = result.coverImage, let data = image.jpegData(compressionQuality: 0.7) {
|
||||
// account.postbox.mediaBox.storeResourceData(photoResource.id, data: data)
|
||||
// }
|
||||
//
|
||||
// if let timestamp = videoStartTimestamp {
|
||||
// videoStartTimestamp = max(0.0, min(timestamp, result.duration - 0.05))
|
||||
// }
|
||||
//
|
||||
// var value = stat()
|
||||
// if stat(result.fileURL.path, &value) == 0 {
|
||||
// if let data = try? Data(contentsOf: result.fileURL) {
|
||||
// let resource: TelegramMediaResource
|
||||
// if let liveUploadData = result.liveUploadData as? LegacyLiveUploadInterfaceResult {
|
||||
// resource = LocalFileMediaResource(fileId: liveUploadData.id)
|
||||
// } else {
|
||||
// resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
|
||||
// }
|
||||
// account.postbox.mediaBox.storeResourceData(resource.id, data: data, synchronous: true)
|
||||
// subscriber.putNext(resource)
|
||||
//
|
||||
// EngineTempBox.shared.dispose(tempFile)
|
||||
// }
|
||||
// }
|
||||
// subscriber.putCompletion()
|
||||
// } else if let strongSelf = self, let progress = next as? NSNumber {
|
||||
// Queue.mainQueue().async {
|
||||
// strongSelf.controllerNode.state = strongSelf.controllerNode.state.withAvatarUploadProgress(.value(CGFloat(progress.floatValue * 0.45)))
|
||||
// if let (layout, navigationHeight) = strongSelf.controllerNode.validLayout {
|
||||
// strongSelf.controllerNode.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .immediate, additive: false)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }, error: { _ in
|
||||
// }, completed: nil)
|
||||
//
|
||||
// let disposable = ActionDisposable {
|
||||
// signalDisposable?.dispose()
|
||||
// }
|
||||
//
|
||||
// return ActionDisposable {
|
||||
// disposable.dispose()
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// videoResource = .single(nil)
|
||||
// }
|
||||
//
|
||||
// var dismissStatus: (() -> Void)?
|
||||
// if [.suggest, .fallback, .accept].contains(mode) {
|
||||
// let statusController = OverlayStatusController(theme: self.presentationData.theme, type: .loading(cancelled: { [weak self] in
|
||||
// self?.controllerNode.updateAvatarDisposable.set(nil)
|
||||
// dismissStatus?()
|
||||
// }))
|
||||
// dismissStatus = { [weak statusController] in
|
||||
// statusController?.dismiss()
|
||||
// }
|
||||
// if let topController = self.navigationController?.topViewController as? ViewController {
|
||||
// topController.presentInGlobalOverlay(statusController)
|
||||
// } else if let topController = self.parentController?.topViewController as? ViewController {
|
||||
// topController.presentInGlobalOverlay(statusController)
|
||||
// } else {
|
||||
// self.presentInGlobalOverlay(statusController)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// let peerId = self.peerId
|
||||
// let isSettings = self.isSettings
|
||||
// let isMyProfile = self.isMyProfile
|
||||
// self.controllerNode.updateAvatarDisposable.set((videoResource
|
||||
// |> mapToSignal { videoResource -> Signal<UpdatePeerPhotoStatus, UploadPeerPhotoError> in
|
||||
// if isSettings || isMyProfile {
|
||||
// if case .fallback = mode {
|
||||
// return context.engine.accountData.updateFallbackPhoto(resource: photoResource, videoResource: videoResource, videoStartTimestamp: videoStartTimestamp, markup: markup, mapResourceToAvatarSizes: { resource, representations in
|
||||
// return mapResourceToAvatarSizes(postbox: account.postbox, resource: resource, representations: representations)
|
||||
// })
|
||||
// } else {
|
||||
// return context.engine.accountData.updateAccountPhoto(resource: photoResource, videoResource: videoResource, videoStartTimestamp: videoStartTimestamp, markup: markup, mapResourceToAvatarSizes: { resource, representations in
|
||||
// return mapResourceToAvatarSizes(postbox: account.postbox, resource: resource, representations: representations)
|
||||
// })
|
||||
// }
|
||||
// } else if case .custom = mode {
|
||||
// return context.engine.contacts.updateContactPhoto(peerId: peerId, resource: photoResource, videoResource: videoResource, videoStartTimestamp: videoStartTimestamp, markup: markup, mode: .custom, mapResourceToAvatarSizes: { resource, representations in
|
||||
// return mapResourceToAvatarSizes(postbox: account.postbox, resource: resource, representations: representations)
|
||||
// })
|
||||
// } else if case .suggest = mode {
|
||||
// return context.engine.contacts.updateContactPhoto(peerId: peerId, resource: photoResource, videoResource: videoResource, videoStartTimestamp: videoStartTimestamp, markup: markup, mode: .suggest, mapResourceToAvatarSizes: { resource, representations in
|
||||
// return mapResourceToAvatarSizes(postbox: account.postbox, resource: resource, representations: representations)
|
||||
// })
|
||||
// } else {
|
||||
// return context.engine.peers.updatePeerPhoto(peerId: peerId, photo: context.engine.peers.uploadedPeerPhoto(resource: photoResource), video: videoResource.flatMap { context.engine.peers.uploadedPeerVideo(resource: $0) |> map(Optional.init) }, videoStartTimestamp: videoStartTimestamp, markup: markup, mapResourceToAvatarSizes: { resource, representations in
|
||||
// return mapResourceToAvatarSizes(postbox: account.postbox, resource: resource, representations: representations)
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
// |> deliverOnMainQueue).startStrict(next: { [weak self] result in
|
||||
// guard let strongSelf = self else {
|
||||
// return
|
||||
// }
|
||||
// switch result {
|
||||
// case .complete:
|
||||
// strongSelf.controllerNode.state = strongSelf.controllerNode.state.withUpdatingAvatar(nil).withAvatarUploadProgress(nil)
|
||||
// case let .progress(value):
|
||||
// strongSelf.controllerNode.state = strongSelf.controllerNode.state.withAvatarUploadProgress(.value(CGFloat(0.45 + value * 0.55)))
|
||||
// }
|
||||
// if let (layout, navigationHeight) = strongSelf.controllerNode.validLayout {
|
||||
// strongSelf.controllerNode.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .immediate, additive: false)
|
||||
// }
|
||||
//
|
||||
// if case .complete = result {
|
||||
// dismissStatus?()
|
||||
//
|
||||
// let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: strongSelf.peerId))
|
||||
// |> deliverOnMainQueue).startStandalone(next: { [weak self] peer in
|
||||
// if let strongSelf = self, let peer {
|
||||
// switch mode {
|
||||
// case .fallback:
|
||||
// (strongSelf.parentController?.topViewController as? ViewController)?.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .image(image: image, title: nil, text: strongSelf.presentationData.strings.Privacy_ProfilePhoto_PublicVideoSuccess, round: true, undoText: nil), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .current)
|
||||
// case .custom:
|
||||
// strongSelf.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .invitedToVoiceChat(context: strongSelf.context, peer: peer, title: nil, text: strongSelf.presentationData.strings.UserInfo_SetCustomPhoto_SuccessVideoText(peer.compactDisplayTitle).string, action: nil, duration: 5), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .current)
|
||||
//
|
||||
// let _ = (strongSelf.context.peerChannelMemberCategoriesContextsManager.profilePhotos(postbox: strongSelf.context.account.postbox, network: strongSelf.context.account.network, peerId: strongSelf.peerId, fetch: peerInfoProfilePhotos(context: strongSelf.context, peerId: strongSelf.peerId)) |> ignoreValues).startStandalone()
|
||||
// case .suggest:
|
||||
// if let navigationController = (strongSelf.navigationController as? NavigationController) {
|
||||
// strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer), keepStack: .default, completion: { _ in
|
||||
// }))
|
||||
// }
|
||||
// case .accept:
|
||||
// (strongSelf.parentController?.topViewController as? ViewController)?.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .image(image: image, title: strongSelf.presentationData.strings.Conversation_SuggestedVideoSuccess, text: strongSelf.presentationData.strings.Conversation_SuggestedVideoSuccessText, round: true, undoText: nil), elevatedLayout: false, animateInAsReplacement: true, action: { [weak self] action in
|
||||
// if case .info = action {
|
||||
// self?.parentController?.openSettings()
|
||||
// }
|
||||
// return false
|
||||
// }), in: .current)
|
||||
// default:
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// }))
|
||||
// }
|
||||
public func updateProfileVideo(_ image: UIImage, asset: Any?, values: MediaEditorValues?, markup: UploadPeerPhotoMarkup?, mode: PeerInfoAvatarEditingMode, uploadStatus: Promise<PeerInfoAvatarUploadStatus>?) {
|
||||
var uploadVideo = true
|
||||
if let _ = markup {
|
||||
if let data = self.context.currentAppConfiguration.with({ $0 }).data, let uploadVideoValue = data["upload_markup_video"] as? Bool, uploadVideoValue {
|
||||
uploadVideo = true
|
||||
} else {
|
||||
uploadVideo = false
|
||||
}
|
||||
}
|
||||
guard let photoResource = self.setupProfilePhotoUpload(image: image, mode: mode, indefiniteProgress: !uploadVideo) else {
|
||||
uploadStatus?.set(.single(.done))
|
||||
return
|
||||
}
|
||||
|
||||
public func updateProfileVideo(_ image: UIImage, asset: Any?, adjustments: TGVideoEditAdjustments?, mode: PeerInfoAvatarEditingMode) {
|
||||
var videoStartTimestamp: Double? = nil
|
||||
if let values, let coverImageTimestamp = values.coverImageTimestamp, coverImageTimestamp > 0.0 {
|
||||
videoStartTimestamp = coverImageTimestamp - (values.videoTrimRange?.lowerBound ?? 0.0)
|
||||
}
|
||||
|
||||
let account = self.context.account
|
||||
let context = self.context
|
||||
|
||||
let videoResource: Signal<TelegramMediaResource?, UploadPeerPhotoError>
|
||||
if uploadVideo {
|
||||
videoResource = Signal { subscriber in
|
||||
return EmptyDisposable
|
||||
}
|
||||
} else {
|
||||
videoResource = .single(nil)
|
||||
}
|
||||
|
||||
var dismissStatus: (() -> Void)?
|
||||
if [.suggest, .fallback, .accept].contains(mode) {
|
||||
let statusController = OverlayStatusController(theme: self.presentationData.theme, type: .loading(cancelled: { [weak self] in
|
||||
self?.controllerNode.updateAvatarDisposable.set(nil)
|
||||
dismissStatus?()
|
||||
}))
|
||||
dismissStatus = { [weak statusController] in
|
||||
statusController?.dismiss()
|
||||
}
|
||||
if let topController = self.navigationController?.topViewController as? ViewController {
|
||||
topController.presentInGlobalOverlay(statusController)
|
||||
} else if let topController = self.parentController?.topViewController as? ViewController {
|
||||
topController.presentInGlobalOverlay(statusController)
|
||||
} else {
|
||||
self.presentInGlobalOverlay(statusController)
|
||||
}
|
||||
}
|
||||
|
||||
let peerId = self.peerId
|
||||
let isSettings = self.isSettings
|
||||
let isMyProfile = self.isMyProfile
|
||||
self.controllerNode.updateAvatarDisposable.set((videoResource
|
||||
|> mapToSignal { videoResource -> Signal<UpdatePeerPhotoStatus, UploadPeerPhotoError> in
|
||||
if isSettings || isMyProfile {
|
||||
if case .fallback = mode {
|
||||
return context.engine.accountData.updateFallbackPhoto(resource: photoResource, videoResource: videoResource, videoStartTimestamp: videoStartTimestamp, markup: markup, mapResourceToAvatarSizes: { resource, representations in
|
||||
return mapResourceToAvatarSizes(postbox: account.postbox, resource: resource, representations: representations)
|
||||
})
|
||||
} else {
|
||||
return context.engine.accountData.updateAccountPhoto(resource: photoResource, videoResource: videoResource, videoStartTimestamp: videoStartTimestamp, markup: markup, mapResourceToAvatarSizes: { resource, representations in
|
||||
return mapResourceToAvatarSizes(postbox: account.postbox, resource: resource, representations: representations)
|
||||
})
|
||||
}
|
||||
} else if case .custom = mode {
|
||||
return context.engine.contacts.updateContactPhoto(peerId: peerId, resource: photoResource, videoResource: videoResource, videoStartTimestamp: videoStartTimestamp, markup: markup, mode: .custom, mapResourceToAvatarSizes: { resource, representations in
|
||||
return mapResourceToAvatarSizes(postbox: account.postbox, resource: resource, representations: representations)
|
||||
})
|
||||
} else if case .suggest = mode {
|
||||
return context.engine.contacts.updateContactPhoto(peerId: peerId, resource: photoResource, videoResource: videoResource, videoStartTimestamp: videoStartTimestamp, markup: markup, mode: .suggest, mapResourceToAvatarSizes: { resource, representations in
|
||||
return mapResourceToAvatarSizes(postbox: account.postbox, resource: resource, representations: representations)
|
||||
})
|
||||
} else {
|
||||
return context.engine.peers.updatePeerPhoto(peerId: peerId, photo: context.engine.peers.uploadedPeerPhoto(resource: photoResource), video: videoResource.flatMap { context.engine.peers.uploadedPeerVideo(resource: $0) |> map(Optional.init) }, videoStartTimestamp: videoStartTimestamp, markup: markup, mapResourceToAvatarSizes: { resource, representations in
|
||||
return mapResourceToAvatarSizes(postbox: account.postbox, resource: resource, representations: representations)
|
||||
})
|
||||
}
|
||||
}
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] result in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
switch result {
|
||||
case .complete:
|
||||
uploadStatus?.set(.single(.done))
|
||||
strongSelf.controllerNode.state = strongSelf.controllerNode.state.withUpdatingAvatar(nil).withAvatarUploadProgress(nil)
|
||||
case let .progress(value):
|
||||
uploadStatus?.set(.single(.progress(value)))
|
||||
strongSelf.controllerNode.state = strongSelf.controllerNode.state.withAvatarUploadProgress(.value(CGFloat(0.45 + value * 0.55)))
|
||||
}
|
||||
if let (layout, navigationHeight) = strongSelf.controllerNode.validLayout {
|
||||
strongSelf.controllerNode.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .immediate, additive: false)
|
||||
}
|
||||
|
||||
if case .complete = result {
|
||||
dismissStatus?()
|
||||
|
||||
let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: strongSelf.peerId))
|
||||
|> deliverOnMainQueue).startStandalone(next: { [weak self] peer in
|
||||
if let strongSelf = self, let peer {
|
||||
switch mode {
|
||||
case .fallback:
|
||||
(strongSelf.parentController?.topViewController as? ViewController)?.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .image(image: image, title: nil, text: strongSelf.presentationData.strings.Privacy_ProfilePhoto_PublicVideoSuccess, round: true, undoText: nil), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .current)
|
||||
case .custom:
|
||||
strongSelf.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .invitedToVoiceChat(context: strongSelf.context, peer: peer, title: nil, text: strongSelf.presentationData.strings.UserInfo_SetCustomPhoto_SuccessVideoText(peer.compactDisplayTitle).string, action: nil, duration: 5), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .current)
|
||||
|
||||
let _ = (strongSelf.context.peerChannelMemberCategoriesContextsManager.profilePhotos(postbox: strongSelf.context.account.postbox, network: strongSelf.context.account.network, peerId: strongSelf.peerId, fetch: peerInfoProfilePhotos(context: strongSelf.context, peerId: strongSelf.peerId)) |> ignoreValues).startStandalone()
|
||||
case .suggest:
|
||||
if let navigationController = (strongSelf.navigationController as? NavigationController) {
|
||||
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer), keepStack: .default, completion: { _ in
|
||||
}))
|
||||
}
|
||||
case .accept:
|
||||
(strongSelf.parentController?.topViewController as? ViewController)?.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .image(image: image, title: strongSelf.presentationData.strings.Conversation_SuggestedVideoSuccess, text: strongSelf.presentationData.strings.Conversation_SuggestedVideoSuccessText, round: true, undoText: nil), elevatedLayout: false, animateInAsReplacement: true, action: { [weak self] action in
|
||||
if case .info = action {
|
||||
self?.parentController?.openSettings()
|
||||
}
|
||||
return false
|
||||
}), in: .current)
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
public func oldUpdateProfileVideo(_ image: UIImage, asset: Any?, adjustments: TGVideoEditAdjustments?, mode: PeerInfoAvatarEditingMode) {
|
||||
var markup: UploadPeerPhotoMarkup? = nil
|
||||
if let fileId = adjustments?.documentId, let backgroundColors = adjustments?.colors as? [Int32], fileId != 0 {
|
||||
if let packId = adjustments?.stickerPackId, let accessHash = adjustments?.stickerPackAccessHash, packId != 0 {
|
||||
|
@ -411,7 +411,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
||||
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(CheckComponent(
|
||||
theme: checkTheme,
|
||||
size: CGSize(width: 22.0, height: 22.0),
|
||||
selected: self.notify
|
||||
selected: self.profileGifts.currentState?.notificationsEnabled ?? false
|
||||
))),
|
||||
AnyComponentWithIdentity(id: AnyHashable(1), component: AnyComponent(MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(string: presentationData.strings.PeerInfo_Gifts_ChannelNotify, font: Font.regular(17.0), textColor: presentationData.theme.list.itemPrimaryTextColor))
|
||||
@ -421,20 +421,23 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
||||
)),
|
||||
effectAlignment: .center,
|
||||
action: { [weak self] in
|
||||
guard let self else {
|
||||
guard let self, let currentState = self.profileGifts.currentState else {
|
||||
return
|
||||
}
|
||||
self.notify = !self.notify
|
||||
let enabled = !(currentState.notificationsEnabled ?? false)
|
||||
self.profileGifts.toggleStarGiftsNotifications(enabled: enabled)
|
||||
|
||||
let animation = enabled ? "anim_profileunmute" : "anim_profilemute"
|
||||
let text = enabled ? presentationData.strings.PeerInfo_Gifts_ChannelNotifyTooltip : presentationData.strings.PeerInfo_Gifts_ChannelNotifyDisabledTooltip
|
||||
|
||||
if self.notify {
|
||||
let controller = UndoOverlayController(
|
||||
presentationData: presentationData,
|
||||
content: .universal(animation: "anim_profileunmute", scale: 0.075, colors: ["__allcolors__": UIColor.white], title: nil, text: presentationData.strings.PeerInfo_Gifts_ChannelNotifyTooltip, customUndoText: nil, timeout: nil),
|
||||
content: .universal(animation: animation, scale: 0.075, colors: ["__allcolors__": UIColor.white], title: nil, text: text, customUndoText: nil, timeout: nil),
|
||||
appearance: UndoOverlayController.Appearance(bottomInset: 53.0),
|
||||
action: { _ in return true }
|
||||
)
|
||||
self.chatControllerInteraction.presentController(controller, nil)
|
||||
}
|
||||
|
||||
self.updateScrolling(transition: .immediate)
|
||||
},
|
||||
animateAlpha: false,
|
||||
|
@ -1233,10 +1233,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
}
|
||||
}
|
||||
controller.videoCompletion = { [weak self] image, url, adjustments, commit in
|
||||
controller.videoCompletion = { [weak self] image, url, values, markup, commit in
|
||||
if let strongSelf = self {
|
||||
if let rootController = strongSelf.effectiveNavigationController as? TelegramRootController, let settingsController = rootController.accountSettingsController as? PeerInfoScreenImpl {
|
||||
settingsController.updateProfileVideo(image, asset: AVURLAsset(url: url), adjustments: adjustments, mode: .accept)
|
||||
settingsController.updateProfileVideo(image, asset: AVURLAsset(url: url), values: values, markup: markup, mode: .accept, uploadStatus: nil)
|
||||
commit()
|
||||
}
|
||||
}
|
||||
@ -1271,7 +1271,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}, videoCompletion: { [weak self] image, url, adjustments in
|
||||
if let strongSelf = self {
|
||||
if let rootController = strongSelf.effectiveNavigationController as? TelegramRootController, let settingsController = rootController.accountSettingsController as? PeerInfoScreenImpl {
|
||||
settingsController.updateProfileVideo(image, asset: AVURLAsset(url: url), adjustments: adjustments, mode: .accept)
|
||||
settingsController.oldUpdateProfileVideo(image, asset: AVURLAsset(url: url), adjustments: adjustments, mode: .accept)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -642,15 +642,15 @@ public func createChannelController(context: AccountContext, mode: CreateChannel
|
||||
}))
|
||||
presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
|
||||
}
|
||||
mixin.requestAvatarEditor = { imageCompletion, videoCompletion in
|
||||
guard let imageCompletion, let videoCompletion else {
|
||||
return
|
||||
}
|
||||
let controller = AvatarEditorScreen(context: context, inputData: keyboardInputData.get(), peerType: .channel, markup: nil)
|
||||
controller.imageCompletion = imageCompletion
|
||||
controller.videoCompletion = videoCompletion
|
||||
pushControllerImpl?(controller)
|
||||
}
|
||||
// mixin.requestAvatarEditor = { imageCompletion, videoCompletion in
|
||||
// guard let imageCompletion, let videoCompletion else {
|
||||
// return
|
||||
// }
|
||||
// let controller = AvatarEditorScreen(context: context, inputData: keyboardInputData.get(), peerType: .channel, markup: nil)
|
||||
// controller.imageCompletion = imageCompletion
|
||||
// controller.videoCompletion = videoCompletion
|
||||
// pushControllerImpl?(controller)
|
||||
// }
|
||||
mixin.didFinishWithImage = { image in
|
||||
if let image = image {
|
||||
completedChannelPhotoImpl(image)
|
||||
|
@ -1061,15 +1061,15 @@ public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId]
|
||||
}))
|
||||
presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
|
||||
}
|
||||
mixin.requestAvatarEditor = { imageCompletion, videoCompletion in
|
||||
guard let imageCompletion, let videoCompletion else {
|
||||
return
|
||||
}
|
||||
let controller = AvatarEditorScreen(context: context, inputData: keyboardInputData.get(), peerType: .group, markup: nil)
|
||||
controller.imageCompletion = imageCompletion
|
||||
controller.videoCompletion = videoCompletion
|
||||
pushImpl?(controller)
|
||||
}
|
||||
// mixin.requestAvatarEditor = { imageCompletion, videoCompletion in
|
||||
// guard let imageCompletion, let videoCompletion else {
|
||||
// return
|
||||
// }
|
||||
// let controller = AvatarEditorScreen(context: context, inputData: keyboardInputData.get(), peerType: .group, markup: nil)
|
||||
// controller.imageCompletion = imageCompletion
|
||||
// controller.videoCompletion = videoCompletion
|
||||
// pushImpl?(controller)
|
||||
// }
|
||||
mixin.didFinishWithImage = { image in
|
||||
if let image = image {
|
||||
completedGroupPhotoImpl(image)
|
||||
|
Loading…
x
Reference in New Issue
Block a user