From d8d93de096cb6fcc5c1799a02dcee23b4ac88194 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Tue, 5 Nov 2019 20:36:52 +0400 Subject: [PATCH] Add silent posting and scheduling from in-app camera --- .../LegacyComponents/TGCameraController.h | 4 +- .../LegacyComponents/TGCameraController.m | 128 +++++++++++++++++- .../TGMediaPickerModernGalleryMixin.m | 8 +- .../LegacyComponents/TGPassportAttachMenu.m | 2 +- .../Data and Storage/StorageUsageItem.swift | 2 +- .../TelegramUI/ChatController.swift | 4 +- .../TelegramUI/TelegramUI/LegacyCamera.swift | 88 ++---------- 7 files changed, 149 insertions(+), 87 deletions(-) diff --git a/submodules/LegacyComponents/LegacyComponents/TGCameraController.h b/submodules/LegacyComponents/LegacyComponents/TGCameraController.h index 2169853fb3..85bb772f78 100644 --- a/submodules/LegacyComponents/LegacyComponents/TGCameraController.h +++ b/submodules/LegacyComponents/LegacyComponents/TGCameraController.h @@ -45,7 +45,7 @@ typedef enum { @property (nonatomic, strong) NSString *recipientName; -@property (nonatomic, copy) void(^finishedWithResults)(TGOverlayController *controller, TGMediaSelectionContext *selectionContext, TGMediaEditingContext *editingContext, id currentItem); +@property (nonatomic, copy) void(^finishedWithResults)(TGOverlayController *controller, TGMediaSelectionContext *selectionContext, TGMediaEditingContext *editingContext, id currentItem, bool silentPosting, int32_t scheduleTime); @property (nonatomic, copy) void(^finishedWithPhoto)(TGOverlayController *controller, UIImage *resultImage, NSString *caption, NSArray *entities, NSArray *stickers, NSNumber *timer); @property (nonatomic, copy) void(^finishedWithVideo)(TGOverlayController *controller, NSURL *videoURL, UIImage *previewImage, NSTimeInterval duration, CGSize dimensions, TGVideoEditAdjustments *adjustments, NSString *caption, NSArray *entities, NSArray *stickers, NSNumber *timer); @@ -55,6 +55,8 @@ typedef enum { @property (nonatomic, copy) void(^finishedTransitionOut)(void); @property (nonatomic, copy) void(^customPresentOverlayController)(TGOverlayController *(^)(id)); +@property (nonatomic, copy) void (^presentScheduleController)(void (^)(int32_t)); + - (instancetype)initWithContext:(id)context saveEditedPhotos:(bool)saveEditedPhotos saveCapturedMedia:(bool)saveCapturedMedia; - (instancetype)initWithContext:(id)context saveEditedPhotos:(bool)saveEditedPhotos saveCapturedMedia:(bool)saveCapturedMedia intent:(TGCameraControllerIntent)intent; - (instancetype)initWithContext:(id)context saveEditedPhotos:(bool)saveEditedPhotos saveCapturedMedia:(bool)saveCapturedMedia camera:(PGCamera *)camera previewView:(TGCameraPreviewView *)previewView intent:(TGCameraControllerIntent)intent; diff --git a/submodules/LegacyComponents/LegacyComponents/TGCameraController.m b/submodules/LegacyComponents/LegacyComponents/TGCameraController.m index 37b5a2b97b..8bb1df16ee 100644 --- a/submodules/LegacyComponents/LegacyComponents/TGCameraController.m +++ b/submodules/LegacyComponents/LegacyComponents/TGCameraController.m @@ -45,6 +45,7 @@ #import #import +#import #import "TGMediaPickerGallerySelectedItemsModel.h" #import "TGCameraCapturedPhoto.h" @@ -1251,6 +1252,128 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus model.controller = galleryController; model.suggestionContext = self.suggestionContext; + __weak TGModernGalleryController *weakGalleryController = galleryController; + __weak TGMediaPickerGalleryModel *weakModel = model; + + model.interfaceView.doneLongPressed = ^(TGMediaPickerGalleryItem *item) { + __strong TGCameraController *strongSelf = weakSelf; + __strong TGMediaPickerGalleryModel *strongModel = weakModel; + if (strongSelf == nil || !(strongSelf.hasSilentPosting || strongSelf.hasSchedule) || strongSelf->_shortcut) + return; + + if (iosMajorVersion() >= 10) { + UIImpactFeedbackGenerator *generator = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleMedium]; + [generator impactOccurred]; + } + + bool effectiveHasSchedule = strongSelf.hasSchedule; + for (id item in strongModel.selectionContext.selectedItems) + { + if ([item isKindOfClass:[TGMediaAsset class]]) + { + if ([[strongSelf->_editingContext timerForItem:item] integerValue] > 0) + { + effectiveHasSchedule = false; + break; + } + } + } + + TGMediaPickerSendActionSheetController *controller = [[TGMediaPickerSendActionSheetController alloc] initWithContext:strongSelf->_context sendButtonFrame:strongModel.interfaceView.doneButtonFrame canSendSilently:strongSelf->_hasSilentPosting canSchedule:effectiveHasSchedule]; + controller.send = ^{ + __strong TGCameraController *strongSelf = weakSelf; + __strong TGMediaPickerGalleryModel *strongModel = weakModel; + + if (strongSelf == nil || strongModel == nil) + return; + + __strong TGModernGalleryController *strongController = weakGalleryController; + if (strongController == nil) + return; + + if ([item isKindOfClass:[TGMediaPickerGalleryVideoItem class]]) + { + TGMediaPickerGalleryVideoItemView *itemView = (TGMediaPickerGalleryVideoItemView *)[strongController itemViewForItem:item]; + [itemView stop]; + [itemView setPlayButtonHidden:true animated:true]; + } + + if (strongSelf->_selectionContext.allowGrouping) + [[NSUserDefaults standardUserDefaults] setObject:@(!strongSelf->_selectionContext.grouping) forKey:@"TG_mediaGroupingDisabled_v0"]; + + if (strongSelf.finishedWithResults != nil) + strongSelf.finishedWithResults(strongController, strongSelf->_selectionContext, strongSelf->_editingContext, item.asset, false, 0); + + [strongSelf _dismissTransitionForResultController:strongController]; + }; + controller.sendSilently = ^{ + __strong TGCameraController *strongSelf = weakSelf; + __strong TGMediaPickerGalleryModel *strongModel = weakModel; + + if (strongSelf == nil || strongModel == nil) + return; + + __strong TGModernGalleryController *strongController = weakGalleryController; + if (strongController == nil) + return; + + if ([item isKindOfClass:[TGMediaPickerGalleryVideoItem class]]) + { + TGMediaPickerGalleryVideoItemView *itemView = (TGMediaPickerGalleryVideoItemView *)[strongController itemViewForItem:item]; + [itemView stop]; + [itemView setPlayButtonHidden:true animated:true]; + } + + if (strongSelf->_selectionContext.allowGrouping) + [[NSUserDefaults standardUserDefaults] setObject:@(!strongSelf->_selectionContext.grouping) forKey:@"TG_mediaGroupingDisabled_v0"]; + + if (strongSelf.finishedWithResults != nil) + strongSelf.finishedWithResults(strongController, strongSelf->_selectionContext, strongSelf->_editingContext, item.asset, true, 0); + + [strongSelf _dismissTransitionForResultController:strongController]; + }; + controller.schedule = ^{ + __strong TGCameraController *strongSelf = weakSelf; + if (strongSelf == nil) + return; + + strongSelf.presentScheduleController(^(int32_t time) { + __strong TGCameraController *strongSelf = weakSelf; + __strong TGMediaPickerGalleryModel *strongModel = weakModel; + + if (strongSelf == nil || strongModel == nil) + return; + + __strong TGModernGalleryController *strongController = weakGalleryController; + if (strongController == nil) + return; + + if ([item isKindOfClass:[TGMediaPickerGalleryVideoItem class]]) + { + TGMediaPickerGalleryVideoItemView *itemView = (TGMediaPickerGalleryVideoItemView *)[strongController itemViewForItem:item]; + [itemView stop]; + [itemView setPlayButtonHidden:true animated:true]; + } + + if (strongSelf->_selectionContext.allowGrouping) + [[NSUserDefaults standardUserDefaults] setObject:@(!strongSelf->_selectionContext.grouping) forKey:@"TG_mediaGroupingDisabled_v0"]; + + if (strongSelf.finishedWithResults != nil) + strongSelf.finishedWithResults(strongController, strongSelf->_selectionContext, strongSelf->_editingContext, item.asset, false, time); + + [strongSelf _dismissTransitionForResultController:strongController]; + }); + }; + + id windowManager = nil; + id windowContext = nil; + windowManager = [strongSelf->_context makeOverlayWindowManager]; + windowContext = [windowManager context]; + + TGOverlayControllerWindow *controllerWindow = [[TGOverlayControllerWindow alloc] initWithManager:windowManager parentController:strongSelf contentController:(TGOverlayController *)controller]; + controllerWindow.hidden = false; + }; + model.willFinishEditingItem = ^(id editableItem, id adjustments, id representation, bool hasChanges) { __strong TGCameraController *strongSelf = weakSelf; @@ -1278,9 +1401,6 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus model.interfaceView.hasSwipeGesture = false; galleryController.model = model; - - __weak TGModernGalleryController *weakGalleryController = galleryController; - __weak TGMediaPickerGalleryModel *weakModel = model; if (_items.count > 1) [model.interfaceView updateSelectionInterface:selectionContext.count counterVisible:(selectionContext.count > 0) animated:false]; @@ -1318,7 +1438,7 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus [[NSUserDefaults standardUserDefaults] setObject:@(!strongSelf->_selectionContext.grouping) forKey:@"TG_mediaGroupingDisabled_v0"]; if (strongSelf.finishedWithResults != nil) - strongSelf.finishedWithResults(strongController, strongSelf->_selectionContext, strongSelf->_editingContext, item.asset); + strongSelf.finishedWithResults(strongController, strongSelf->_selectionContext, strongSelf->_editingContext, item.asset, false, 0); if (strongSelf->_shortcut) return; diff --git a/submodules/LegacyComponents/LegacyComponents/TGMediaPickerModernGalleryMixin.m b/submodules/LegacyComponents/LegacyComponents/TGMediaPickerModernGalleryMixin.m index bd45c12d04..eaca03b4ec 100644 --- a/submodules/LegacyComponents/LegacyComponents/TGMediaPickerModernGalleryMixin.m +++ b/submodules/LegacyComponents/LegacyComponents/TGMediaPickerModernGalleryMixin.m @@ -1,5 +1,7 @@ #import "TGMediaPickerModernGalleryMixin.h" +#import "LegacyComponentsInternal.h" + #import #import @@ -144,8 +146,10 @@ if (strongSelf == nil || !(hasSilentPosting || hasSchedule)) return; - UIImpactFeedbackGenerator *generator = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleMedium]; - [generator impactOccurred]; + if (iosMajorVersion() >= 10) { + UIImpactFeedbackGenerator *generator = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleMedium]; + [generator impactOccurred]; + } bool effectiveHasSchedule = hasSchedule; for (id item in strongSelf->_galleryModel.selectionContext.selectedItems) diff --git a/submodules/LegacyComponents/LegacyComponents/TGPassportAttachMenu.m b/submodules/LegacyComponents/LegacyComponents/TGPassportAttachMenu.m index 12d35852dc..cfe5081397 100644 --- a/submodules/LegacyComponents/LegacyComponents/TGPassportAttachMenu.m +++ b/submodules/LegacyComponents/LegacyComponents/TGPassportAttachMenu.m @@ -382,7 +382,7 @@ [strongCameraView attachPreviewViewAnimated:true]; }; - controller.finishedWithResults = ^(__unused TGOverlayController *controller, TGMediaSelectionContext *selectionContext, TGMediaEditingContext *editingContext, id currentItem) + controller.finishedWithResults = ^(__unused TGOverlayController *controller, TGMediaSelectionContext *selectionContext, TGMediaEditingContext *editingContext, id currentItem, __unused bool silentPosting, __unused int32_t scheduleTime) { __strong TGMenuSheetController *strongMenuController = weakMenuController; if (strongMenuController == nil) diff --git a/submodules/SettingsUI/Sources/Data and Storage/StorageUsageItem.swift b/submodules/SettingsUI/Sources/Data and Storage/StorageUsageItem.swift index 35db5fc49b..c7b479dbed 100644 --- a/submodules/SettingsUI/Sources/Data and Storage/StorageUsageItem.swift +++ b/submodules/SettingsUI/Sources/Data and Storage/StorageUsageItem.swift @@ -279,7 +279,7 @@ private final class StorageUsageItemNode: ListViewItemNode { lineNode.backgroundColor = category.color - var categoryWidth = max(floor(lineWidth * category.fraction), 6.0) + var categoryWidth = max(floor(lineWidth * category.fraction), 2.0) if i == strongSelf.lineNodes.count - 1 { categoryWidth = lineWidth - (lineOrigin.x - lineInset) } diff --git a/submodules/TelegramUI/TelegramUI/ChatController.swift b/submodules/TelegramUI/TelegramUI/ChatController.swift index 440e6ec0f6..8da7b3c5d2 100644 --- a/submodules/TelegramUI/TelegramUI/ChatController.swift +++ b/submodules/TelegramUI/TelegramUI/ChatController.swift @@ -5456,12 +5456,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }) }, openCamera: { [weak self] cameraView, menuController in if let strongSelf = self, let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer { - presentedLegacyCamera(context: strongSelf.context, peer: peer, cameraView: cameraView, menuController: menuController, parentController: strongSelf, editingMedia: editMediaOptions != nil, saveCapturedPhotos: settings.storeEditedPhotos, mediaGrouping: true, initialCaption: inputText.string, hasSchedule: !strongSelf.presentationInterfaceState.isScheduledMessages && peer.id.namespace != Namespaces.Peer.SecretChat, sendMessagesWithSignals: { [weak self] signals in + presentedLegacyCamera(context: strongSelf.context, peer: peer, cameraView: cameraView, menuController: menuController, parentController: strongSelf, editingMedia: editMediaOptions != nil, saveCapturedPhotos: settings.storeEditedPhotos, mediaGrouping: true, initialCaption: inputText.string, hasSchedule: !strongSelf.presentationInterfaceState.isScheduledMessages && peer.id.namespace != Namespaces.Peer.SecretChat, sendMessagesWithSignals: { [weak self] signals, silentPosting, scheduleTime in if let strongSelf = self { if editMediaOptions != nil { strongSelf.editMessageMediaWithLegacySignals(signals!) } else { - strongSelf.enqueueMediaMessages(signals: signals, silentPosting: false) + strongSelf.enqueueMediaMessages(signals: signals, silentPosting: silentPosting, scheduleTime: scheduleTime) } if !inputText.string.isEmpty { //strongSelf.clearInputText() diff --git a/submodules/TelegramUI/TelegramUI/LegacyCamera.swift b/submodules/TelegramUI/TelegramUI/LegacyCamera.swift index 10b972611e..d745057a2d 100644 --- a/submodules/TelegramUI/TelegramUI/LegacyCamera.swift +++ b/submodules/TelegramUI/TelegramUI/LegacyCamera.swift @@ -11,7 +11,7 @@ import ShareController import LegacyUI import LegacyMediaPickerUI -func presentedLegacyCamera(context: AccountContext, peer: Peer, cameraView: TGAttachmentCameraView?, menuController: TGMenuSheetController?, parentController: ViewController, editingMedia: Bool, saveCapturedPhotos: Bool, mediaGrouping: Bool, initialCaption: String, hasSchedule: Bool, sendMessagesWithSignals: @escaping ([Any]?) -> Void, recognizedQRCode: @escaping (String) -> Void = { _ in }, presentSchedulePicker: @escaping (@escaping (Int32) -> Void) -> Void) { +func presentedLegacyCamera(context: AccountContext, peer: Peer, cameraView: TGAttachmentCameraView?, menuController: TGMenuSheetController?, parentController: ViewController, editingMedia: Bool, saveCapturedPhotos: Bool, mediaGrouping: Bool, initialCaption: String, hasSchedule: Bool, sendMessagesWithSignals: @escaping ([Any]?, Bool, Int32) -> Void, recognizedQRCode: @escaping (String) -> Void = { _ in }, presentSchedulePicker: @escaping (@escaping (Int32) -> Void) -> Void) { let presentationData = context.sharedContext.currentPresentationData.with { $0 } let legacyController = LegacyController(presentation: .custom, theme: presentationData.theme) legacyController.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .portrait, compactSize: .portrait) @@ -29,6 +29,12 @@ func presentedLegacyCamera(context: AccountContext, peer: Peer, cameraView: TGAt controller = TGCameraController() } + controller.presentScheduleController = { done in + presentSchedulePicker { time in + done?(time) + } + } + if #available(iOSApplicationExtension 11.0, iOS 11.0, *) { } else { controller.customPresentOverlayController = { [weak legacyController] generateController in @@ -99,10 +105,10 @@ func presentedLegacyCamera(context: AccountContext, peer: Peer, cameraView: TGAt legacyController?.dismiss() } - controller.finishedWithResults = { [weak menuController, weak legacyController] overlayController, selectionContext, editingContext, currentItem in + controller.finishedWithResults = { [weak menuController, weak legacyController] overlayController, selectionContext, editingContext, currentItem, silentPosting, scheduleTime in if let selectionContext = selectionContext, let editingContext = editingContext { let signals = TGCameraController.resultSignals(for: selectionContext, editingContext: editingContext, currentItem: currentItem, storeAssets: saveCapturedPhotos && !isSecretChat, saveEditedPhotos: saveCapturedPhotos && !isSecretChat, descriptionGenerator: legacyAssetPickerItemGenerator()) - sendMessagesWithSignals(signals) + sendMessagesWithSignals(signals, silentPosting, scheduleTime) } menuController?.dismiss(animated: false) @@ -118,7 +124,7 @@ func presentedLegacyCamera(context: AccountContext, peer: Peer, cameraView: TGAt description["timer"] = timer } if let item = legacyAssetPickerItemGenerator()(description, caption, entities, nil) { - sendMessagesWithSignals([SSignal.single(item)]) + sendMessagesWithSignals([SSignal.single(item)], false, 0) } } @@ -143,7 +149,7 @@ func presentedLegacyCamera(context: AccountContext, peer: Peer, cameraView: TGAt description["timer"] = timer } if let item = legacyAssetPickerItemGenerator()(description, caption, entities, nil) { - sendMessagesWithSignals([SSignal.single(item)]) + sendMessagesWithSignals([SSignal.single(item)], false, 0) } } menuController?.dismiss(animated: false) @@ -193,7 +199,7 @@ func presentedLegacyShortcutCamera(context: AccountContext, saveCapturedMedia: B legacyController?.dismiss() } - controller.finishedWithResults = { [weak controller, weak parentController, weak legacyController] overlayController, selectionContext, editingContext, currentItem in + controller.finishedWithResults = { [weak controller, weak parentController, weak legacyController] overlayController, selectionContext, editingContext, currentItem, _, _ in if let selectionContext = selectionContext, let editingContext = editingContext { let signals = TGCameraController.resultSignals(for: selectionContext, editingContext: editingContext, currentItem: currentItem, storeAssets: saveCapturedMedia, saveEditedPhotos: saveEditedPhotos, descriptionGenerator: legacyAssetPickerItemGenerator()) if let parentController = parentController { @@ -218,77 +224,7 @@ func presentedLegacyShortcutCamera(context: AccountContext, saveCapturedMedia: B }), showInChat: nil, externalShare: false), in: .window(.root)) } } - - //legacyController?.dismissWithAnimation() } parentController.present(legacyController, in: .window(.root)) - - - /*TGCameraControllerWindow *controllerWindow = [[TGCameraControllerWindow alloc] initWithManager:[[TGLegacyComponentsContext shared] makeOverlayWindowManager] parentController:TGAppDelegateInstance.rootController contentController:controller]; - controllerWindow.hidden = false; - - CGSize screenSize = TGScreenSize(); - if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) - controllerWindow.frame = CGRectMake(0, 0, screenSize.width, screenSize.height); - - CGRect startFrame = CGRectMake(0, screenSize.height, screenSize.width, screenSize.height); - [controller beginTransitionInFromRect:startFrame]; - - __weak TGCameraController *weakCameraController = controller; - controller.finishedWithResults = ^(TGOverlayController *controller, TGMediaSelectionContext *selectionContext, TGMediaEditingContext *editingContext, id currentItem) - { - __autoreleasing NSString *disabledMessage = nil; - if (![TGApplicationFeatures isPhotoUploadEnabledForPeerType:TGApplicationFeaturePeerPrivate disabledMessage:&disabledMessage]) - { - [TGCustomAlertView presentAlertWithTitle:TGLocalized(@"FeatureDisabled.Oops") message:disabledMessage cancelButtonTitle:TGLocalized(@"Common.OK") okButtonTitle:nil completionBlock:nil]; - return; - } - - __strong TGCameraController *strongCameraController = weakCameraController; - if (strongCameraController == nil) - return; - - [TGCameraController showTargetController:[TGCameraController resultSignalsForSelectionContext:selectionContext editingContext:editingContext currentItem:currentItem storeAssets:false saveEditedPhotos:false descriptionGenerator:^id(id item, NSString *caption, NSArray *entities, __unused NSString *stickers) - { - if ([item isKindOfClass:[NSDictionary class]]) - { - NSDictionary *dict = (NSDictionary *)item; - NSString *type = dict[@"type"]; - - if ([type isEqualToString:@"editedPhoto"]) - { - NSMutableDictionary *result = [[NSMutableDictionary alloc] init]; - result[@"type"] = @"image"; - result[@"image"] = dict[@"image"]; - if (caption.length > 0) - result[@"caption"] = caption; - if (entities.count > 0) - result[@"entities"] = entities; - if (dict[@"stickers"] != nil) - result[@"stickers"] = dict[@"stickers"]; - - return result; - } - else if ([type isEqualToString:@"cameraVideo"]) - { - NSMutableDictionary *result = [[NSMutableDictionary alloc] init]; - result[@"type"] = @"cameraVideo"; - result[@"url"] = dict[@"url"]; - if (dict[@"adjustments"] != nil) - result[@"adjustments"] = dict[@"adjustments"]; - if (entities.count > 0) - result[@"entities"] = entities; - if (dict[@"stickers"] != nil) - result[@"stickers"] = dict[@"stickers"]; - if (dict[@"previewImage"] != nil) - result[@"previewImage"] = dict[@"previewImage"]; - - return result; - } - } - - return nil; - }] cameraController:strongCameraController resultController:controller navigationController:(TGNavigationController *)controller.navigationController]; - };*/ }