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
076129348b
commit
c10f020f0a
@ -58,14 +58,14 @@ public struct SharedMediaPlaybackAlbumArt: Equatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public enum SharedMediaPlaybackDisplayData: Equatable {
|
public enum SharedMediaPlaybackDisplayData: Equatable {
|
||||||
case music(title: String?, performer: String?, albumArt: SharedMediaPlaybackAlbumArt?, long: Bool)
|
case music(title: String?, performer: String?, albumArt: SharedMediaPlaybackAlbumArt?, long: Bool, caption: NSAttributedString?)
|
||||||
case voice(author: Peer?, peer: Peer?)
|
case voice(author: Peer?, peer: Peer?)
|
||||||
case instantVideo(author: Peer?, peer: Peer?, timestamp: Int32)
|
case instantVideo(author: Peer?, peer: Peer?, timestamp: Int32)
|
||||||
|
|
||||||
public static func ==(lhs: SharedMediaPlaybackDisplayData, rhs: SharedMediaPlaybackDisplayData) -> Bool {
|
public static func ==(lhs: SharedMediaPlaybackDisplayData, rhs: SharedMediaPlaybackDisplayData) -> Bool {
|
||||||
switch lhs {
|
switch lhs {
|
||||||
case let .music(lhsTitle, lhsPerformer, lhsAlbumArt, lhsDuration):
|
case let .music(lhsTitle, lhsPerformer, lhsAlbumArt, lhsDuration, lhsCaption):
|
||||||
if case let .music(rhsTitle, rhsPerformer, rhsAlbumArt, rhsDuration) = rhs, lhsTitle == rhsTitle, lhsPerformer == rhsPerformer, lhsAlbumArt == rhsAlbumArt, lhsDuration == rhsDuration {
|
if case let .music(rhsTitle, rhsPerformer, rhsAlbumArt, rhsDuration, rhsCaption) = rhs, lhsTitle == rhsTitle, lhsPerformer == rhsPerformer, lhsAlbumArt == rhsAlbumArt, lhsDuration == rhsDuration, lhsCaption?.string == rhsCaption?.string {
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
|
@ -2077,6 +2077,7 @@ public class DrawingScreen: ViewController, TGPhotoDrawingInterfaceController, U
|
|||||||
self._entitiesView = externalEntitiesView
|
self._entitiesView = externalEntitiesView
|
||||||
} else {
|
} else {
|
||||||
self._entitiesView = DrawingEntitiesView(context: self.context, size: controller.size)
|
self._entitiesView = DrawingEntitiesView(context: self.context, size: controller.size)
|
||||||
|
//self._entitiesView = DrawingEntitiesView(context: self.context, size: controller.originalSize)
|
||||||
}
|
}
|
||||||
self._drawingView?.entitiesView = self._entitiesView
|
self._drawingView?.entitiesView = self._entitiesView
|
||||||
self._entitiesView?.drawingView = self._drawingView
|
self._entitiesView?.drawingView = self._drawingView
|
||||||
@ -2942,7 +2943,7 @@ public class DrawingScreen: ViewController, TGPhotoDrawingInterfaceController, U
|
|||||||
super.displayNodeDidLoad()
|
super.displayNodeDidLoad()
|
||||||
|
|
||||||
let dropInteraction = UIDropInteraction(delegate: self)
|
let dropInteraction = UIDropInteraction(delegate: self)
|
||||||
self.view.addInteraction(dropInteraction)
|
self.drawingView.addInteraction(dropInteraction)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func generateResultData() -> TGPaintingData? {
|
public func generateResultData() -> TGPaintingData? {
|
||||||
|
@ -94,7 +94,7 @@ final class InstantPageMediaPlaylistItem: SharedMediaPlaylistItem {
|
|||||||
albumArt = SharedMediaPlaybackAlbumArt(thumbnailResource: ExternalMusicAlbumArtResource(file: .standalone(media: file), title: updatedTitle ?? "", performer: updatedPerformer ?? "", isThumbnail: true), fullSizeResource: ExternalMusicAlbumArtResource(file: .standalone(media: file), title: updatedTitle ?? "", performer: updatedPerformer ?? "", isThumbnail: false))
|
albumArt = SharedMediaPlaybackAlbumArt(thumbnailResource: ExternalMusicAlbumArtResource(file: .standalone(media: file), title: updatedTitle ?? "", performer: updatedPerformer ?? "", isThumbnail: true), fullSizeResource: ExternalMusicAlbumArtResource(file: .standalone(media: file), title: updatedTitle ?? "", performer: updatedPerformer ?? "", isThumbnail: false))
|
||||||
}
|
}
|
||||||
|
|
||||||
return SharedMediaPlaybackDisplayData.music(title: updatedTitle, performer: updatedPerformer, albumArt: albumArt, long: false)
|
return SharedMediaPlaybackDisplayData.music(title: updatedTitle, performer: updatedPerformer, albumArt: albumArt, long: false, caption: nil)
|
||||||
}
|
}
|
||||||
case let .Video(_, _, flags):
|
case let .Video(_, _, flags):
|
||||||
if flags.contains(.instantRoundVideo) {
|
if flags.contains(.instantRoundVideo) {
|
||||||
@ -107,7 +107,7 @@ final class InstantPageMediaPlaylistItem: SharedMediaPlaylistItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return SharedMediaPlaybackDisplayData.music(title: file.fileName ?? "", performer: "", albumArt: nil, long: false)
|
return SharedMediaPlaybackDisplayData.music(title: file.fileName ?? "", performer: "", albumArt: nil, long: false, caption: nil)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -235,17 +235,7 @@
|
|||||||
{
|
{
|
||||||
void(^block)(void) = ^
|
void(^block)(void) = ^
|
||||||
{
|
{
|
||||||
CGAffineTransform transform = CGAffineTransformMakeRotation(-1 * TGRotationForInterfaceOrientation(orientation));
|
[self updateWrapperTransform];
|
||||||
CGFloat scale = 1.0;
|
|
||||||
if (self.frame.size.width != 0.0) {
|
|
||||||
scale = self.frame.size.height / self.frame.size.width;
|
|
||||||
}
|
|
||||||
if (_innerInterfaceOrientation == UIInterfaceOrientationLandscapeLeft) {
|
|
||||||
transform = CGAffineTransformScale(transform, scale, scale);
|
|
||||||
} else if (_innerInterfaceOrientation == UIInterfaceOrientationLandscapeRight) {
|
|
||||||
transform = CGAffineTransformScale(transform, scale, scale);
|
|
||||||
}
|
|
||||||
_wrapperView.transform = transform;
|
|
||||||
[self layoutSubviews];
|
[self layoutSubviews];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -257,6 +247,20 @@
|
|||||||
block();
|
block();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)updateWrapperTransform {
|
||||||
|
CGAffineTransform transform = CGAffineTransformMakeRotation(-1 * TGRotationForInterfaceOrientation(_innerInterfaceOrientation));
|
||||||
|
CGFloat scale = 1.0;
|
||||||
|
if (self.frame.size.width != 0.0) {
|
||||||
|
scale = self.frame.size.height / self.frame.size.width;
|
||||||
|
}
|
||||||
|
if (_innerInterfaceOrientation == UIInterfaceOrientationLandscapeLeft) {
|
||||||
|
transform = CGAffineTransformScale(transform, scale, scale);
|
||||||
|
} else if (_innerInterfaceOrientation == UIInterfaceOrientationLandscapeRight) {
|
||||||
|
transform = CGAffineTransformScale(transform, scale, scale);
|
||||||
|
}
|
||||||
|
_wrapperView.transform = transform;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)layoutSubviews
|
- (void)layoutSubviews
|
||||||
{
|
{
|
||||||
[super layoutSubviews];
|
[super layoutSubviews];
|
||||||
@ -264,6 +268,8 @@
|
|||||||
_wrapperView.bounds = CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height);
|
_wrapperView.bounds = CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height);
|
||||||
_wrapperView.center = CGPointMake(self.bounds.size.width / 2.0, self.bounds.size.height / 2.0);
|
_wrapperView.center = CGPointMake(self.bounds.size.width / 2.0, self.bounds.size.height / 2.0);
|
||||||
|
|
||||||
|
[self updateWrapperTransform];
|
||||||
|
|
||||||
TGCameraPreviewView *previewView = _previewView;
|
TGCameraPreviewView *previewView = _previewView;
|
||||||
if (previewView.superview == _wrapperView)
|
if (previewView.superview == _wrapperView)
|
||||||
previewView.frame = self.bounds;
|
previewView.frame = self.bounds;
|
||||||
|
@ -595,6 +595,10 @@
|
|||||||
hasOnScreenNavigation = (self.viewLoaded && self.view.safeAreaInsets.bottom > FLT_EPSILON) || _context.safeAreaInset.bottom > FLT_EPSILON;
|
hasOnScreenNavigation = (self.viewLoaded && self.view.safeAreaInsets.bottom > FLT_EPSILON) || _context.safeAreaInset.bottom > FLT_EPSILON;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad && _intent == TGMediaAssetsControllerSendFileIntent) {
|
||||||
|
hasOnScreenNavigation = false;
|
||||||
|
}
|
||||||
|
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
|
@ -385,8 +385,8 @@
|
|||||||
__weak TGMediaAvatarMenuMixin *weakSelf = self;
|
__weak TGMediaAvatarMenuMixin *weakSelf = self;
|
||||||
UIViewController *(^presentBlock)(TGMediaAssetsController *) = nil;
|
UIViewController *(^presentBlock)(TGMediaAssetsController *) = nil;
|
||||||
|
|
||||||
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
|
// if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
|
||||||
{
|
// {
|
||||||
presentBlock = ^UIViewController * (TGMediaAssetsController *controller)
|
presentBlock = ^UIViewController * (TGMediaAssetsController *controller)
|
||||||
{
|
{
|
||||||
__strong TGMediaAvatarMenuMixin *strongSelf = weakSelf;
|
__strong TGMediaAvatarMenuMixin *strongSelf = weakSelf;
|
||||||
@ -413,48 +413,51 @@
|
|||||||
|
|
||||||
return controller;
|
return controller;
|
||||||
};
|
};
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
presentBlock = ^UIViewController * (TGMediaAssetsController *controller)
|
// presentBlock = ^UIViewController * (TGMediaAssetsController *controller)
|
||||||
{
|
// {
|
||||||
__strong TGMediaAvatarMenuMixin *strongSelf = weakSelf;
|
// __strong TGMediaAvatarMenuMixin *strongSelf = weakSelf;
|
||||||
if (strongSelf == nil)
|
// if (strongSelf == nil)
|
||||||
return nil;
|
// return nil;
|
||||||
|
//
|
||||||
controller.presentationStyle = TGNavigationControllerPresentationStyleInFormSheet;
|
// controller.presentationStyle = TGNavigationControllerPresentationStyleInFormSheet;
|
||||||
controller.modalPresentationStyle = UIModalPresentationFormSheet;
|
// controller.modalPresentationStyle = UIModalPresentationFormSheet;
|
||||||
|
//
|
||||||
TGOverlayFormsheetWindow *formSheetWindow = [[TGOverlayFormsheetWindow alloc] initWithContext:strongSelf->_context parentController:strongSelf->_parentController contentController:controller];
|
// id<LegacyComponentsOverlayWindowManager> windowManager = nil;
|
||||||
[formSheetWindow showAnimated:true];
|
// windowManager = [strongSelf->_context makeOverlayWindowManager];
|
||||||
|
//
|
||||||
__weak TGNavigationController *weakNavController = controller;
|
// TGOverlayFormsheetWindow *formSheetWindow = [[TGOverlayFormsheetWindow alloc] initWithManager:windowManager parentController:strongSelf->_parentController contentController:controller];
|
||||||
__weak TGOverlayFormsheetWindow *weakFormSheetWindow = formSheetWindow;
|
// [formSheetWindow showAnimated:true];
|
||||||
controller.dismissalBlock = ^
|
//
|
||||||
{
|
// __weak TGNavigationController *weakNavController = controller;
|
||||||
__strong TGMediaAvatarMenuMixin *strongSelf = weakSelf;
|
// __weak TGOverlayFormsheetWindow *weakFormSheetWindow = formSheetWindow;
|
||||||
if (strongSelf == nil)
|
// controller.dismissalBlock = ^
|
||||||
return;
|
// {
|
||||||
|
// __strong TGMediaAvatarMenuMixin *strongSelf = weakSelf;
|
||||||
__strong TGOverlayFormsheetWindow *strongFormSheetWindow = weakFormSheetWindow;
|
// if (strongSelf == nil)
|
||||||
if (strongFormSheetWindow == nil)
|
// return;
|
||||||
return;
|
//
|
||||||
|
// __strong TGOverlayFormsheetWindow *strongFormSheetWindow = weakFormSheetWindow;
|
||||||
__strong TGNavigationController *strongNavController = weakNavController;
|
// if (strongFormSheetWindow == nil)
|
||||||
if (strongNavController != nil)
|
// return;
|
||||||
{
|
//
|
||||||
if (strongNavController.presentingViewController != nil)
|
// __strong TGNavigationController *strongNavController = weakNavController;
|
||||||
[strongNavController.presentingViewController dismissViewControllerAnimated:true completion:nil];
|
// if (strongNavController != nil)
|
||||||
else
|
// {
|
||||||
[strongFormSheetWindow dismissAnimated:true];
|
// if (strongNavController.presentingViewController != nil)
|
||||||
}
|
// [strongNavController.presentingViewController dismissViewControllerAnimated:true completion:nil];
|
||||||
|
// else
|
||||||
if (strongSelf.didDismiss != nil)
|
// [strongFormSheetWindow dismissAnimated:true];
|
||||||
strongSelf.didDismiss();
|
// }
|
||||||
};
|
//
|
||||||
return nil;
|
// if (strongSelf.didDismiss != nil)
|
||||||
};
|
// strongSelf.didDismiss();
|
||||||
}
|
// };
|
||||||
|
// return nil;
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
|
||||||
void (^showMediaPicker)(TGMediaAssetGroup *) = ^(TGMediaAssetGroup *group)
|
void (^showMediaPicker)(TGMediaAssetGroup *) = ^(TGMediaAssetGroup *group)
|
||||||
{
|
{
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
@interface TGOverlayFormsheetWindow : UIWindow
|
@interface TGOverlayFormsheetWindow : UIWindow
|
||||||
|
|
||||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context parentController:(TGViewController *)parentController contentController:(UIViewController *)contentController;
|
- (instancetype)initWithManager:(id<LegacyComponentsOverlayWindowManager>)manager parentController:(TGViewController *)parentController contentController:(UIViewController *)contentController;
|
||||||
|
|
||||||
- (void)showAnimated:(bool)animated;
|
- (void)showAnimated:(bool)animated;
|
||||||
- (void)dismissAnimated:(bool)animated;
|
- (void)dismissAnimated:(bool)animated;
|
||||||
|
@ -14,18 +14,19 @@
|
|||||||
SMetaDisposable *_sizeClassDisposable;
|
SMetaDisposable *_sizeClassDisposable;
|
||||||
UIUserInterfaceSizeClass _sizeClass;
|
UIUserInterfaceSizeClass _sizeClass;
|
||||||
|
|
||||||
id<LegacyComponentsContext> _context;
|
id<LegacyComponentsOverlayWindowManager> _manager;
|
||||||
|
bool _managedIsHidden;
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation TGOverlayFormsheetWindow
|
@implementation TGOverlayFormsheetWindow
|
||||||
|
|
||||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context parentController:(TGViewController *)parentController contentController:(UIViewController *)contentController
|
- (instancetype)initWithManager:(id<LegacyComponentsOverlayWindowManager>)manager parentController:(TGViewController *)parentController contentController:(UIViewController *)contentController
|
||||||
{
|
{
|
||||||
self = [super initWithFrame:[context fullscreenBounds]];
|
self = [super initWithFrame:[[manager context] fullscreenBounds]];
|
||||||
if (self != nil)
|
if (self != nil)
|
||||||
{
|
{
|
||||||
_context = context;
|
_manager = manager;
|
||||||
self.windowLevel = parentController.view.window.windowLevel + 0.0001f;
|
self.windowLevel = parentController.view.window.windowLevel + 0.0001f;
|
||||||
self.backgroundColor = [UIColor clearColor];
|
self.backgroundColor = [UIColor clearColor];
|
||||||
|
|
||||||
@ -34,8 +35,7 @@
|
|||||||
|
|
||||||
_contentController = contentController;
|
_contentController = contentController;
|
||||||
|
|
||||||
if (iosMajorVersion() < 9)
|
[_manager bindController:_contentController];
|
||||||
[self createControllerIfNeeded];
|
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@ -45,88 +45,38 @@
|
|||||||
[_sizeClassDisposable dispose];
|
[_sizeClassDisposable dispose];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)createControllerIfNeeded
|
- (BOOL)isHidden {
|
||||||
{
|
return _managedIsHidden;
|
||||||
if (self.rootViewController != nil)
|
|
||||||
return;
|
|
||||||
|
|
||||||
TGOverlayFormsheetController *controller = [[TGOverlayFormsheetController alloc] initWithContext:_context contentController:_contentController];
|
|
||||||
controller.formSheetWindow = self;
|
|
||||||
self.rootViewController = controller;
|
|
||||||
|
|
||||||
_contentController = nil;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)updateSizeClass:(UIUserInterfaceSizeClass)sizeClass animated:(bool)animated
|
- (void)setHidden:(BOOL)hidden {
|
||||||
{
|
if ([_manager managesWindow]) {
|
||||||
if (_sizeClass == sizeClass)
|
if (![super isHidden]) {
|
||||||
return;
|
[super setHidden:true];
|
||||||
|
|
||||||
_sizeClass = sizeClass;
|
|
||||||
|
|
||||||
if (sizeClass == UIUserInterfaceSizeClassCompact)
|
|
||||||
{
|
|
||||||
if ([self contentController].parentViewController != _parentController)
|
|
||||||
{
|
|
||||||
[[self contentController] removeFromParentViewController];
|
|
||||||
[[self.contentController view] removeFromSuperview];
|
|
||||||
|
|
||||||
[_parentController presentViewController:[self contentController] animated:animated completion:nil];
|
|
||||||
self.hidden = true;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
if (_managedIsHidden != hidden) {
|
||||||
{
|
_managedIsHidden = hidden;
|
||||||
if ([self controller] == nil || [self contentController].parentViewController != [self controller])
|
[_manager setHidden:hidden window:self];
|
||||||
{
|
}
|
||||||
[self createControllerIfNeeded];
|
} else {
|
||||||
|
[super setHidden:hidden];
|
||||||
[self.contentController.presentingViewController dismissViewControllerAnimated:false completion:^
|
|
||||||
{
|
if (!hidden) {
|
||||||
[[self controller] setContentController:[self contentController]];
|
[[[LegacyComponentsGlobals provider] applicationWindows].firstObject endEditing:true];
|
||||||
self.hidden = false;
|
|
||||||
}];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)showAnimated:(bool)animated
|
- (void)showAnimated:(bool)animated
|
||||||
{
|
{
|
||||||
if (iosMajorVersion() >= 9)
|
if ([self contentController].parentViewController != _parentController)
|
||||||
{
|
{
|
||||||
UIUserInterfaceSizeClass sizeClass = [_context currentHorizontalSizeClass];
|
[[self contentController] removeFromParentViewController];
|
||||||
|
[[self.contentController view] removeFromSuperview];
|
||||||
if (sizeClass == UIUserInterfaceSizeClassCompact)
|
|
||||||
{
|
|
||||||
[self updateSizeClass:sizeClass animated:true];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
[self createControllerIfNeeded];
|
|
||||||
|
|
||||||
self.hidden = false;
|
|
||||||
|
|
||||||
if (animated)
|
|
||||||
[[self controller] animateInWithCompletion:nil];
|
|
||||||
}
|
|
||||||
|
|
||||||
__weak TGOverlayFormsheetWindow *weakSelf = self;
|
[_parentController presentViewController:[self contentController] animated:animated completion:nil];
|
||||||
_sizeClassDisposable = [[SMetaDisposable alloc] init];
|
//self.hidden = true;
|
||||||
[_sizeClassDisposable setDisposable:[[_context sizeClassSignal] startWithNext:^(NSNumber *next)
|
|
||||||
{
|
|
||||||
__strong TGOverlayFormsheetWindow *strongSelf = weakSelf;
|
|
||||||
if (strongSelf == nil)
|
|
||||||
return;
|
|
||||||
|
|
||||||
[strongSelf updateSizeClass:next.integerValue animated:false];
|
|
||||||
}]];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
self.hidden = false;
|
|
||||||
|
|
||||||
if (animated)
|
|
||||||
[[self controller] animateInWithCompletion:nil];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,7 +84,8 @@
|
|||||||
{
|
{
|
||||||
TGViewController *parentController = _parentController;
|
TGViewController *parentController = _parentController;
|
||||||
[parentController.associatedWindowStack removeObject:self];
|
[parentController.associatedWindowStack removeObject:self];
|
||||||
self.hidden = true;
|
[_manager setHidden:true window:self];
|
||||||
|
//self.hidden = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)dismissAnimated:(bool)animated
|
- (void)dismissAnimated:(bool)animated
|
||||||
|
@ -190,7 +190,10 @@
|
|||||||
controller.presentationStyle = TGNavigationControllerPresentationStyleInFormSheet;
|
controller.presentationStyle = TGNavigationControllerPresentationStyleInFormSheet;
|
||||||
controller.modalPresentationStyle = UIModalPresentationFormSheet;
|
controller.modalPresentationStyle = UIModalPresentationFormSheet;
|
||||||
|
|
||||||
TGOverlayFormsheetWindow *formSheetWindow = [[TGOverlayFormsheetWindow alloc] initWithContext:context parentController:strongParentController contentController:controller];
|
id<LegacyComponentsOverlayWindowManager> windowManager = nil;
|
||||||
|
windowManager = [context makeOverlayWindowManager];
|
||||||
|
|
||||||
|
TGOverlayFormsheetWindow *formSheetWindow = [[TGOverlayFormsheetWindow alloc] initWithManager:windowManager parentController:strongParentController contentController:controller];
|
||||||
[formSheetWindow showAnimated:true];
|
[formSheetWindow showAnimated:true];
|
||||||
|
|
||||||
__weak TGNavigationController *weakNavController = controller;
|
__weak TGNavigationController *weakNavController = controller;
|
||||||
|
@ -41,7 +41,7 @@ private class MediaHeaderItemNode: ASDisplayNode {
|
|||||||
var subtitleString: NSAttributedString?
|
var subtitleString: NSAttributedString?
|
||||||
if let playbackItem = playbackItem, let displayData = playbackItem.displayData {
|
if let playbackItem = playbackItem, let displayData = playbackItem.displayData {
|
||||||
switch displayData {
|
switch displayData {
|
||||||
case let .music(title, performer, _, long):
|
case let .music(title, performer, _, long, _):
|
||||||
rateButtonHidden = !long
|
rateButtonHidden = !long
|
||||||
let titleText: String = title ?? strings.MediaPlayer_UnknownTrack
|
let titleText: String = title ?? strings.MediaPlayer_UnknownTrack
|
||||||
let subtitleText: String = performer ?? strings.MediaPlayer_UnknownArtist
|
let subtitleText: String = performer ?? strings.MediaPlayer_UnknownArtist
|
||||||
|
@ -6803,7 +6803,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
if let message = strongSelf.chatDisplayNode.historyNode.messageInCurrentHistoryView(index.id) {
|
if let message = strongSelf.chatDisplayNode.historyNode.messageInCurrentHistoryView(index.id) {
|
||||||
let highlightedState = ChatInterfaceHighlightedState(messageStableId: message.stableId)
|
let highlightedState = ChatInterfaceHighlightedState(messageStableId: message.stableId)
|
||||||
controllerInteraction.highlightedState = highlightedState
|
controllerInteraction.highlightedState = highlightedState
|
||||||
strongSelf.updateItemNodesHighlightedStates(animated: false)
|
strongSelf.updateItemNodesHighlightedStates(animated: initial)
|
||||||
strongSelf.scrolledToMessageIdValue = ScrolledToMessageId(id: index.id, allowedReplacementDirection: [])
|
strongSelf.scrolledToMessageIdValue = ScrolledToMessageId(id: index.id, allowedReplacementDirection: [])
|
||||||
|
|
||||||
strongSelf.messageContextDisposable.set((Signal<Void, NoError>.complete() |> delay(0.7, queue: Queue.mainQueue())).start(completed: {
|
strongSelf.messageContextDisposable.set((Signal<Void, NoError>.complete() |> delay(0.7, queue: Queue.mainQueue())).start(completed: {
|
||||||
|
@ -248,7 +248,7 @@ public final class MediaManagerImpl: NSObject, MediaManager {
|
|||||||
var artwork: SharedMediaPlaybackAlbumArt?
|
var artwork: SharedMediaPlaybackAlbumArt?
|
||||||
|
|
||||||
switch displayData {
|
switch displayData {
|
||||||
case let .music(title, performer, artworkValue, _):
|
case let .music(title, performer, artworkValue, _, _):
|
||||||
artwork = artworkValue
|
artwork = artworkValue
|
||||||
|
|
||||||
let titleText: String = title ?? presentationData.strings.MediaPlayer_UnknownTrack
|
let titleText: String = title ?? presentationData.strings.MediaPlayer_UnknownTrack
|
||||||
|
@ -61,19 +61,21 @@ private func timestampLabelWidthForDuration(_ timestamp: Double) -> CGFloat {
|
|||||||
private let titleFont = Font.semibold(18.0)
|
private let titleFont = Font.semibold(18.0)
|
||||||
private let descriptionFont = Font.regular(18.0)
|
private let descriptionFont = Font.regular(18.0)
|
||||||
|
|
||||||
private func stringsForDisplayData(_ data: SharedMediaPlaybackDisplayData?, presentationData: PresentationData) -> (NSAttributedString?, NSAttributedString?, Bool) {
|
private func stringsForDisplayData(_ data: SharedMediaPlaybackDisplayData?, presentationData: PresentationData) -> (NSAttributedString?, NSAttributedString?, Bool, NSAttributedString?) {
|
||||||
var titleString: NSAttributedString?
|
var titleString: NSAttributedString?
|
||||||
var descriptionString: NSAttributedString?
|
var descriptionString: NSAttributedString?
|
||||||
var hasArtist = false
|
var hasArtist = false
|
||||||
|
var captionString: NSAttributedString?
|
||||||
|
|
||||||
if let data = data {
|
if let data = data {
|
||||||
let titleText: String
|
let titleText: String
|
||||||
let subtitleText: String
|
let subtitleText: String
|
||||||
switch data {
|
switch data {
|
||||||
case let .music(title, performer, _, _):
|
case let .music(title, performer, _, _, caption):
|
||||||
titleText = title ?? presentationData.strings.MediaPlayer_UnknownTrack
|
titleText = title ?? presentationData.strings.MediaPlayer_UnknownTrack
|
||||||
subtitleText = performer ?? presentationData.strings.MediaPlayer_UnknownArtist
|
subtitleText = performer ?? presentationData.strings.MediaPlayer_UnknownArtist
|
||||||
hasArtist = performer != nil
|
hasArtist = performer != nil
|
||||||
|
captionString = caption
|
||||||
case .voice, .instantVideo:
|
case .voice, .instantVideo:
|
||||||
titleText = ""
|
titleText = ""
|
||||||
subtitleText = ""
|
subtitleText = ""
|
||||||
@ -83,7 +85,7 @@ private func stringsForDisplayData(_ data: SharedMediaPlaybackDisplayData?, pres
|
|||||||
descriptionString = NSAttributedString(string: subtitleText, font: descriptionFont, textColor: hasArtist ? presentationData.theme.list.itemAccentColor : presentationData.theme.list.itemSecondaryTextColor)
|
descriptionString = NSAttributedString(string: subtitleText, font: descriptionFont, textColor: hasArtist ? presentationData.theme.list.itemAccentColor : presentationData.theme.list.itemSecondaryTextColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (titleString, descriptionString, hasArtist)
|
return (titleString, descriptionString, hasArtist, captionString)
|
||||||
}
|
}
|
||||||
|
|
||||||
final class OverlayPlayerControlsNode: ASDisplayNode {
|
final class OverlayPlayerControlsNode: ASDisplayNode {
|
||||||
@ -146,6 +148,13 @@ final class OverlayPlayerControlsNode: ASDisplayNode {
|
|||||||
private var currentAlbumArt: SharedMediaPlaybackAlbumArt?
|
private var currentAlbumArt: SharedMediaPlaybackAlbumArt?
|
||||||
private var currentFileReference: FileMediaReference?
|
private var currentFileReference: FileMediaReference?
|
||||||
private var statusDisposable: Disposable?
|
private var statusDisposable: Disposable?
|
||||||
|
private var chapterDisposable: Disposable?
|
||||||
|
|
||||||
|
private var previousCaption: NSAttributedString?
|
||||||
|
private var chaptersPromise = ValuePromise<[MediaPlayerScrubbingChapter]>([])
|
||||||
|
private var currentChapter: MediaPlayerScrubbingChapter?
|
||||||
|
|
||||||
|
private let hapticFeedback = HapticFeedback()
|
||||||
|
|
||||||
private var scrubbingDisposable: Disposable?
|
private var scrubbingDisposable: Disposable?
|
||||||
private var leftDurationLabelPushed = false
|
private var leftDurationLabelPushed = false
|
||||||
@ -376,7 +385,7 @@ final class OverlayPlayerControlsNode: ASDisplayNode {
|
|||||||
strongSelf.updateRateButton(baseRate)
|
strongSelf.updateRateButton(baseRate)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let displayData = displayData, case let .music(_, _, _, long) = displayData, long {
|
if let displayData = displayData, case let .music(_, _, _, long, _) = displayData, long {
|
||||||
strongSelf.scrubberNode.enableFineScrubbing = true
|
strongSelf.scrubberNode.enableFineScrubbing = true
|
||||||
rateButtonIsHidden = false
|
rateButtonIsHidden = false
|
||||||
} else {
|
} else {
|
||||||
@ -430,6 +439,58 @@ final class OverlayPlayerControlsNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
self.chapterDisposable = combineLatest(queue: Queue.mainQueue(), mappedStatus, self.chaptersPromise.get())
|
||||||
|
.start(next: { [weak self] status, chapters in
|
||||||
|
if let strongSelf = self, status.duration > 1.0, chapters.count > 0 {
|
||||||
|
let previousChapter = strongSelf.currentChapter
|
||||||
|
var currentChapter: MediaPlayerScrubbingChapter?
|
||||||
|
for chapter in chapters {
|
||||||
|
if chapter.start > status.timestamp {
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
currentChapter = chapter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let chapter = currentChapter, chapter != previousChapter {
|
||||||
|
strongSelf.currentChapter = chapter
|
||||||
|
|
||||||
|
if strongSelf.scrubberNode.isScrubbing {
|
||||||
|
strongSelf.hapticFeedback.impact(.light)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let previousChapter = previousChapter, !strongSelf.infoNode.alpha.isZero {
|
||||||
|
if let snapshotView = strongSelf.infoNode.view.snapshotView(afterScreenUpdates: false) {
|
||||||
|
snapshotView.frame = strongSelf.infoNode.frame
|
||||||
|
strongSelf.infoNode.view.superview?.addSubview(snapshotView)
|
||||||
|
|
||||||
|
let offset: CGFloat = 30.0
|
||||||
|
let snapshotTargetPosition: CGPoint
|
||||||
|
let nodeStartPosition: CGPoint
|
||||||
|
if previousChapter.start < chapter.start {
|
||||||
|
snapshotTargetPosition = CGPoint(x: -offset, y: 0.0)
|
||||||
|
nodeStartPosition = CGPoint(x: offset, y: 0.0)
|
||||||
|
} else {
|
||||||
|
snapshotTargetPosition = CGPoint(x: offset, y: 0.0)
|
||||||
|
nodeStartPosition = CGPoint(x: -offset, y: 0.0)
|
||||||
|
}
|
||||||
|
snapshotView.layer.animatePosition(from: CGPoint(), to: snapshotTargetPosition, duration: 0.2, removeOnCompletion: false, additive: true)
|
||||||
|
snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak snapshotView] _ in
|
||||||
|
snapshotView?.removeFromSuperview()
|
||||||
|
})
|
||||||
|
strongSelf.infoNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||||
|
strongSelf.infoNode.layer.animatePosition(from: nodeStartPosition, to: CGPoint(), duration: 0.2, additive: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
strongSelf.infoNode.attributedText = NSAttributedString(string: chapter.title, font: Font.regular(13.0), textColor: strongSelf.presentationData.theme.list.itemSecondaryTextColor)
|
||||||
|
|
||||||
|
if let layout = strongSelf.validLayout {
|
||||||
|
let _ = strongSelf.updateLayout(width: layout.0, leftInset: layout.1, rightInset: layout.2, maxHeight: layout.3, transition: .immediate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
self.scrubberNode.seek = { [weak self] value in
|
self.scrubberNode.seek = { [weak self] value in
|
||||||
self?.control?(.seek(value))
|
self?.control?(.seek(value))
|
||||||
}
|
}
|
||||||
@ -463,6 +524,7 @@ final class OverlayPlayerControlsNode: ASDisplayNode {
|
|||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
self.statusDisposable?.dispose()
|
self.statusDisposable?.dispose()
|
||||||
|
self.chapterDisposable?.dispose()
|
||||||
self.scrubbingDisposable?.dispose()
|
self.scrubbingDisposable?.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -600,7 +662,15 @@ final class OverlayPlayerControlsNode: ASDisplayNode {
|
|||||||
|
|
||||||
let infoVerticalOrigin: CGFloat = panelHeight - OverlayPlayerControlsNode.basePanelHeight + 36.0
|
let infoVerticalOrigin: CGFloat = panelHeight - OverlayPlayerControlsNode.basePanelHeight + 36.0
|
||||||
|
|
||||||
let (titleString, descriptionString, hasArtist) = stringsForDisplayData(self.displayData, presentationData: self.presentationData)
|
let (titleString, descriptionString, hasArtist, caption) = stringsForDisplayData(self.displayData, presentationData: self.presentationData)
|
||||||
|
|
||||||
|
if self.previousCaption?.string != caption?.string {
|
||||||
|
self.previousCaption = caption
|
||||||
|
let chapters = caption.flatMap { parseMediaPlayerChapters($0) } ?? []
|
||||||
|
self.chaptersPromise.set(chapters)
|
||||||
|
self.scrubberNode.updateContent(.standard(lineHeight: 3.0, lineCap: .round, scrubberHandle: .circle, backgroundColor: self.presentationData.theme.list.controlSecondaryColor, foregroundColor: self.presentationData.theme.list.itemAccentColor, bufferingColor: self.presentationData.theme.list.itemAccentColor.withAlphaComponent(0.4), chapters: chapters))
|
||||||
|
}
|
||||||
|
|
||||||
self.artistButton.isUserInteractionEnabled = hasArtist
|
self.artistButton.isUserInteractionEnabled = hasArtist
|
||||||
let makeTitleLayout = TextNode.asyncLayout(self.titleNode)
|
let makeTitleLayout = TextNode.asyncLayout(self.titleNode)
|
||||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: titleString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: width - sideInset * 2.0 - leftInset - rightInset - infoLabelsLeftInset - infoLabelsRightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .left, lineSpacing: 0.0, cutout: nil, insets: UIEdgeInsets()))
|
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: titleString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: width - sideInset * 2.0 - leftInset - rightInset - infoLabelsLeftInset - infoLabelsRightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .left, lineSpacing: 0.0, cutout: nil, insets: UIEdgeInsets()))
|
||||||
@ -619,7 +689,7 @@ final class OverlayPlayerControlsNode: ASDisplayNode {
|
|||||||
var albumArt: SharedMediaPlaybackAlbumArt?
|
var albumArt: SharedMediaPlaybackAlbumArt?
|
||||||
if let displayData = self.displayData {
|
if let displayData = self.displayData {
|
||||||
switch displayData {
|
switch displayData {
|
||||||
case let .music(_, _, value, _):
|
case let .music(_, _, value, _, _):
|
||||||
albumArt = value
|
albumArt = value
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
@ -913,7 +983,7 @@ final class OverlayPlayerControlsNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@objc func artistPressed() {
|
@objc func artistPressed() {
|
||||||
let (_, descriptionString, _) = stringsForDisplayData(self.displayData, presentationData: self.presentationData)
|
let (_, descriptionString, _, _) = stringsForDisplayData(self.displayData, presentationData: self.presentationData)
|
||||||
if let artist = descriptionString?.string {
|
if let artist = descriptionString?.string {
|
||||||
self.requestSearchByArtist?(artist)
|
self.requestSearchByArtist?(artist)
|
||||||
}
|
}
|
||||||
|
@ -402,7 +402,7 @@ private final class PeerInfoScreenLabeledValueItemNode: PeerInfoScreenItemNode {
|
|||||||
let entities = generateTextEntities(additionalText, enabledTypes: [.mention])
|
let entities = generateTextEntities(additionalText, enabledTypes: [.mention])
|
||||||
let attributedAdditionalText = stringWithAppliedEntities(additionalText, entities: entities, baseColor: presentationData.theme.list.itemPrimaryTextColor, linkColor: presentationData.theme.list.itemAccentColor, baseFont: baseFont, linkFont: linkFont, boldFont: boldFont, italicFont: italicFont, boldItalicFont: boldItalicFont, fixedFont: titleFixedFont, blockQuoteFont: baseFont, underlineLinks: false, message: nil)
|
let attributedAdditionalText = stringWithAppliedEntities(additionalText, entities: entities, baseColor: presentationData.theme.list.itemPrimaryTextColor, linkColor: presentationData.theme.list.itemAccentColor, baseFont: baseFont, linkFont: linkFont, boldFont: boldFont, italicFont: italicFont, boldItalicFont: boldItalicFont, fixedFont: titleFixedFont, blockQuoteFont: baseFont, underlineLinks: false, message: nil)
|
||||||
|
|
||||||
self.additionalTextNode.maximumNumberOfLines = 3
|
self.additionalTextNode.maximumNumberOfLines = 10
|
||||||
self.additionalTextNode.attributedText = attributedAdditionalText
|
self.additionalTextNode.attributedText = attributedAdditionalText
|
||||||
} else {
|
} else {
|
||||||
self.additionalTextNode.attributedText = nil
|
self.additionalTextNode.attributedText = nil
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import UIKit
|
import UIKit
|
||||||
|
import Display
|
||||||
import SwiftSignalKit
|
import SwiftSignalKit
|
||||||
import Postbox
|
import Postbox
|
||||||
import TelegramCore
|
import TelegramCore
|
||||||
import TelegramUIPreferences
|
import TelegramUIPreferences
|
||||||
import AccountContext
|
import AccountContext
|
||||||
import MusicAlbumArtResources
|
import MusicAlbumArtResources
|
||||||
|
import TextFormat
|
||||||
|
|
||||||
private enum PeerMessagesMediaPlaylistLoadAnchor {
|
private enum PeerMessagesMediaPlaylistLoadAnchor {
|
||||||
case messageId(MessageId)
|
case messageId(MessageId)
|
||||||
@ -95,6 +97,15 @@ final class MessageMediaPlaylistItem: SharedMediaPlaylistItem {
|
|||||||
|
|
||||||
var displayData: SharedMediaPlaybackDisplayData? {
|
var displayData: SharedMediaPlaybackDisplayData? {
|
||||||
if let file = extractFileMedia(self.message) {
|
if let file = extractFileMedia(self.message) {
|
||||||
|
let text = self.message.text
|
||||||
|
var entities: [MessageTextEntity] = []
|
||||||
|
if let result = addLocallyGeneratedEntities(text, enabledTypes: [.timecode], entities: [], mediaDuration: file.duration.flatMap(Double.init)) {
|
||||||
|
entities = result
|
||||||
|
}
|
||||||
|
|
||||||
|
let textFont = Font.regular(14.0)
|
||||||
|
let caption = stringWithAppliedEntities(text, entities: entities, baseColor: .white, linkColor: .white, baseFont: textFont, linkFont: textFont, boldFont: textFont, italicFont: textFont, boldItalicFont: textFont, fixedFont: textFont, blockQuoteFont: textFont, underlineLinks: false, message: self.message)
|
||||||
|
|
||||||
for attribute in file.attributes {
|
for attribute in file.attributes {
|
||||||
switch attribute {
|
switch attribute {
|
||||||
case let .Audio(isVoice, duration, title, performer, _):
|
case let .Audio(isVoice, duration, title, performer, _):
|
||||||
@ -114,7 +125,7 @@ final class MessageMediaPlaylistItem: SharedMediaPlaylistItem {
|
|||||||
albumArt = SharedMediaPlaybackAlbumArt(thumbnailResource: ExternalMusicAlbumArtResource(file: .message(message: MessageReference(self.message), media: file), title: updatedTitle ?? "", performer: updatedPerformer ?? "", isThumbnail: true), fullSizeResource: ExternalMusicAlbumArtResource(file: .message(message: MessageReference(self.message), media: file), title: updatedTitle ?? "", performer: updatedPerformer ?? "", isThumbnail: false))
|
albumArt = SharedMediaPlaybackAlbumArt(thumbnailResource: ExternalMusicAlbumArtResource(file: .message(message: MessageReference(self.message), media: file), title: updatedTitle ?? "", performer: updatedPerformer ?? "", isThumbnail: true), fullSizeResource: ExternalMusicAlbumArtResource(file: .message(message: MessageReference(self.message), media: file), title: updatedTitle ?? "", performer: updatedPerformer ?? "", isThumbnail: false))
|
||||||
}
|
}
|
||||||
|
|
||||||
return SharedMediaPlaybackDisplayData.music(title: updatedTitle, performer: updatedPerformer, albumArt: albumArt, long: CGFloat(duration) > 10.0 * 60.0)
|
return SharedMediaPlaybackDisplayData.music(title: updatedTitle, performer: updatedPerformer, albumArt: albumArt, long: CGFloat(duration) > 10.0 * 60.0, caption: caption)
|
||||||
}
|
}
|
||||||
case let .Video(_, _, flags):
|
case let .Video(_, _, flags):
|
||||||
if flags.contains(.instantRoundVideo) {
|
if flags.contains(.instantRoundVideo) {
|
||||||
@ -127,7 +138,7 @@ final class MessageMediaPlaylistItem: SharedMediaPlaylistItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return SharedMediaPlaybackDisplayData.music(title: file.fileName ?? "", performer: self.message.effectiveAuthor?.debugDisplayTitle ?? "", albumArt: nil, long: false)
|
return SharedMediaPlaybackDisplayData.music(title: file.fileName ?? "", performer: self.message.effectiveAuthor?.debugDisplayTitle ?? "", albumArt: nil, long: false, caption: caption)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user