Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
VideoLAN
VLC-iOS
Commits
6f5a9002
Commit
6f5a9002
authored
Feb 28, 2014
by
Carola
Browse files
Folder functionality for the library
parent
79e1b498
Changes
19
Hide whitespace changes
Inline
Side-by-side
Resources/About Contents.html
View file @
6f5a9002
...
...
@@ -63,6 +63,9 @@ Copyright © 2011-2013 Google Inc. - <a href="#apache2">Apache 2 License</a>
<a
href=
"http://www.inappsettingskit.com"
>
InAppSettingsKit
</a><br
/>
Copyright
©
2009-2013 Luc Vandal, Edovia Inc., Ortwin Gentz, FutureTap GmbH -
<a
href=
"#bsd2clause"
>
2-clause BSD License
</a><br
/>
<br
/>
<a
href=
"https://github.com/lxcid/LXReorderableCollectionViewFlowLayout"
>
LXReorderableCollectionViewFlowLayout
</a><br
/>
Copyright
©
2012 Stan Chang Khin Boon and contributors -
<a
href=
"#mit"
>
MIT License
</a><br
/>
<br
/>
<a
href=
"https://github.com/ole/OBSlider"
>
OBSlider
</a><br
/>
Copyright
©
2011 Ole Begemann and contributors -
<a
href=
"#mit"
>
MIT License
</a><br
/>
<br
/>
...
...
Resources/audio@4x.png
deleted
100644 → 0
View file @
79e1b498
1.56 KB
Resources/blank@4x.png
deleted
100644 → 0
View file @
79e1b498
946 Bytes
Resources/en.lproj/Localizable.strings
View file @
6f5a9002
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
Resources/folder@4x.png
deleted
100644 → 0
View file @
79e1b498
1.21 KB
Resources/movie@4x.png
deleted
100644 → 0
View file @
79e1b498
1.13 KB
Sources/VLCFolderCollectionViewFlowLayout.h
0 → 100755
View file @
6f5a9002
/*****************************************************************************
* VLCFolderCollectionViewFlowLayout.h
* VLC for iOS
*****************************************************************************
* Copyright (c) 2014 VideoLAN. All rights reserved.
* $Id$
*
* Authors: Carola Nitz <nitz.carola # googlemail.com>
*
* Refer to the COPYING file of the official project for license.
*****************************************************************************/
@interface
VLCFolderCollectionViewFlowLayout
:
UICollectionViewFlowLayout
@property
(
assign
,
nonatomic
)
CGFloat
scrollingSpeed
;
@property
(
assign
,
nonatomic
)
UIEdgeInsets
scrollingTriggerEdgeInsets
;
@property
(
strong
,
nonatomic
,
readonly
)
UIPanGestureRecognizer
*
panGestureRecognizer
;
@end
@protocol
VLCFolderCollectionViewDelegateFlowLayout
<
UICollectionViewDelegateFlowLayout
>
-
(
void
)
collectionView
:(
UICollectionView
*
)
collectionView
requestToMoveItemAtIndexPath
:(
NSIndexPath
*
)
currentPath
intoFolderAtIndexPath
:(
NSIndexPath
*
)
newIndexPath
;
@end
\ No newline at end of file
Sources/VLCFolderCollectionViewFlowLayout.m
0 → 100755
View file @
6f5a9002
/*****************************************************************************
* VLCFolderCollectionViewFlowLayout.m
* VLC for iOS
*****************************************************************************
* Copyright (c) 2014 VideoLAN. All rights reserved.
* $Id$
*
* Authors: Carola Nitz <nitz.carola # googlemail.com>
*
* Refer to the COPYING file of the official project for license.
*****************************************************************************/
#import "VLCFolderCollectionViewFlowLayout.h"
#import <objc/runtime.h>
#import "VLCPlaylistViewController.h"
//framrate were motion appears fluent
#define LX_FRAMES_PER_SECOND 60.0
#ifndef CGGEOMETRY_LXSUPPORT_H_
CG_INLINE
CGPoint
LXS_CGPointAdd
(
CGPoint
point1
,
CGPoint
point2
)
{
return
CGPointMake
(
point1
.
x
+
point2
.
x
,
point1
.
y
+
point2
.
y
);
}
#endif
typedef
NS_ENUM
(
NSInteger
,
LXScrollingDirection
)
{
LXScrollingDirectionUnknown
=
0
,
LXScrollingDirectionUp
,
LXScrollingDirectionDown
,
LXScrollingDirectionLeft
,
LXScrollingDirectionRight
};
static
NSString
*
const
kLXScrollingDirectionKey
=
@"LXScrollingDirection"
;
static
NSString
*
const
kLXCollectionViewKeyPath
=
@"collectionView"
;
@interface
CADisplayLink
(
LX_userInfo
)
@property
(
nonatomic
,
copy
)
NSDictionary
*
LX_userInfo
;
@end
@implementation
CADisplayLink
(
LX_userInfo
)
-
(
void
)
setLX_userInfo
:(
NSDictionary
*
)
LX_userInfo
{
objc_setAssociatedObject
(
self
,
"LX_userInfo"
,
LX_userInfo
,
OBJC_ASSOCIATION_COPY
);
}
-
(
NSDictionary
*
)
LX_userInfo
{
return
objc_getAssociatedObject
(
self
,
"LX_userInfo"
);
}
@end
@interface
UICollectionViewCell
(
VLCFolderCollectionViewLayout
)
-
(
UIImage
*
)
LX_rasterizedImage
;
@end
@implementation
UICollectionViewCell
(
VLCFolderCollectionViewLayout
)
-
(
UIImage
*
)
LX_rasterizedImage
{
UIGraphicsBeginImageContextWithOptions
(
self
.
bounds
.
size
,
self
.
isOpaque
,
0
.
0
f
);
[
self
.
layer
renderInContext
:
UIGraphicsGetCurrentContext
()];
UIImage
*
image
=
UIGraphicsGetImageFromCurrentImageContext
();
UIGraphicsEndImageContext
();
return
image
;
}
@end
@interface
VLCFolderCollectionViewFlowLayout
()
{
NSIndexPath
*
_selectedItemIndexPath
;
UIView
*
_currentView
;
CGPoint
_currentViewCenter
;
CGPoint
_panTranslationInCollectionView
;
CADisplayLink
*
_displayLink
;
UIView
*
_folderView
;
}
@end
@implementation
VLCFolderCollectionViewFlowLayout
-
(
void
)
setDefaults
{
_scrollingSpeed
=
300
.
0
f
;
_scrollingTriggerEdgeInsets
=
UIEdgeInsetsMake
(
50
.
0
f
,
50
.
0
f
,
50
.
0
f
,
50
.
0
f
);
}
-
(
void
)
setupCollectionView
{
_panGestureRecognizer
=
[[
UIPanGestureRecognizer
alloc
]
initWithTarget
:
self
action:
@selector
(
handlePanGesture
:)];
for
(
UIGestureRecognizer
*
gestureRecognizer
in
self
.
collectionView
.
gestureRecognizers
)
{
if
([
gestureRecognizer
isKindOfClass
:[
UIPanGestureRecognizer
class
]])
[
gestureRecognizer
requireGestureRecognizerToFail
:
_panGestureRecognizer
];
}
[
self
.
collectionView
addGestureRecognizer
:
_panGestureRecognizer
];
// Useful in multiple scenarios: one common scenario being when the Notification Center drawer is pulled down
[[
NSNotificationCenter
defaultCenter
]
addObserver
:
self
selector
:
@selector
(
handleApplicationWillResignActive
:
)
name
:
UIApplicationWillResignActiveNotification
object
:
nil
];
}
-
(
id
)
init
{
self
=
[
super
init
];
if
(
self
)
{
[
self
setDefaults
];
[
self
addObserver
:
self
forKeyPath
:
kLXCollectionViewKeyPath
options
:
NSKeyValueObservingOptionNew
context
:
nil
];
}
return
self
;
}
-
(
id
)
initWithCoder
:(
NSCoder
*
)
aDecoder
{
self
=
[
super
initWithCoder
:
aDecoder
];
if
(
self
)
{
[
self
setDefaults
];
[
self
addObserver
:
self
forKeyPath
:
kLXCollectionViewKeyPath
options
:
NSKeyValueObservingOptionNew
context
:
nil
];
}
return
self
;
}
-
(
void
)
dealloc
{
[
self
invalidatesScrollTimer
];
[
self
removeObserver
:
self
forKeyPath
:
kLXCollectionViewKeyPath
];
[[
NSNotificationCenter
defaultCenter
]
removeObserver
:
self
name
:
UIApplicationWillResignActiveNotification
object
:
nil
];
}
-
(
void
)
applyLayoutAttributes
:(
UICollectionViewLayoutAttributes
*
)
layoutAttributes
{
if
([
layoutAttributes
.
indexPath
isEqual
:
_selectedItemIndexPath
])
layoutAttributes
.
hidden
=
YES
;
}
-
(
id
<
VLCFolderCollectionViewDelegateFlowLayout
>
)
delegate
{
return
(
id
<
VLCFolderCollectionViewDelegateFlowLayout
>
)
self
.
collectionView
.
delegate
;
}
-
(
void
)
invalidateLayoutIfNecessary
{
NSIndexPath
*
newIndexPath
=
[
self
.
collectionView
indexPathForItemAtPoint
:
_currentView
.
center
];
NSIndexPath
*
previousIndexPath
=
_selectedItemIndexPath
;
if
((
newIndexPath
==
nil
)
||
[
newIndexPath
isEqual
:
previousIndexPath
])
{
_currentView
.
transform
=
CGAffineTransformMakeScale
(
1
.
1
f
,
1
.
1
f
);
[
_folderView
removeFromSuperview
];
return
;
}
UICollectionViewCell
*
cell
=
[
self
.
collectionView
.
dataSource
collectionView
:
self
.
collectionView
cellForItemAtIndexPath
:
newIndexPath
];
if
(
!
_folderView
)
{
_folderView
=
[[
UIView
alloc
]
initWithFrame
:
cell
.
frame
];
_folderView
.
backgroundColor
=
[
UIColor
colorWithRed
:(
236
.
0
f
/
255
.
0
f
)
green
:(
111
.
0
f
/
255
.
0
f
)
blue
:
0
.
0
f
alpha
:
1
.
f
];
_folderView
.
layer
.
cornerRadius
=
8
;
}
[
self
.
collectionView
insertSubview
:
_folderView
atIndex
:
0
];
if
(
!
CGPointEqualToPoint
(
_folderView
.
center
,
cell
.
center
))
_folderView
.
frame
=
cell
.
frame
;
[
UIView
animateWithDuration:
0
.
3
delay:
0
.
0
options:
UIViewAnimationOptionBeginFromCurrentState
animations:
^
{
_currentView
.
transform
=
CGAffineTransformMakeScale
(
1
.
0
f
,
1
.
0
f
);
}
completion
:
nil
];
}
-
(
void
)
invalidatesScrollTimer
{
if
(
!
_displayLink
.
paused
)
[
_displayLink
invalidate
];
_displayLink
=
nil
;
}
-
(
void
)
setupScrollTimerInDirection
:(
LXScrollingDirection
)
direction
{
if
(
!
_displayLink
.
paused
)
{
LXScrollingDirection
oldDirection
=
[
_displayLink
.
LX_userInfo
[
kLXScrollingDirectionKey
]
integerValue
];
if
(
direction
==
oldDirection
)
return
;
}
[
self
invalidatesScrollTimer
];
_displayLink
=
[
CADisplayLink
displayLinkWithTarget
:
self
selector
:
@selector
(
handleScroll
:
)];
_displayLink
.
LX_userInfo
=
@{
kLXScrollingDirectionKey
:
@
(
direction
)
};
[
_displayLink
addToRunLoop
:[
NSRunLoop
mainRunLoop
]
forMode
:
NSRunLoopCommonModes
];
}
#pragma mark - Target/Action methods
// Tight loop, allocate memory sparely, even if they are stack allocation.
-
(
void
)
handleScroll
:(
CADisplayLink
*
)
displayLink
{
LXScrollingDirection
direction
=
(
LXScrollingDirection
)[
displayLink
.
LX_userInfo
[
kLXScrollingDirectionKey
]
integerValue
];
if
(
direction
==
LXScrollingDirectionUnknown
)
return
;
CGSize
frameSize
=
self
.
collectionView
.
bounds
.
size
;
CGSize
contentSize
=
self
.
collectionView
.
contentSize
;
CGPoint
contentOffset
=
self
.
collectionView
.
contentOffset
;
// Important to have an integer `distance` as the `contentOffset` property automatically gets rounded
// and it would diverge from the view's center resulting in a "cell is slipping away under finger"-bug.
CGFloat
distance
=
rint
(
self
.
scrollingSpeed
/
LX_FRAMES_PER_SECOND
);
CGPoint
translation
=
CGPointZero
;
switch
(
direction
)
{
case
LXScrollingDirectionUp
:
{
distance
=
-
distance
;
CGFloat
minY
=
0
.
0
f
;
if
((
contentOffset
.
y
+
distance
)
<=
minY
)
distance
=
-
contentOffset
.
y
;
translation
=
CGPointMake
(
0
.
0
f
,
distance
);
}
break
;
case
LXScrollingDirectionDown
:
{
CGFloat
maxY
=
MAX
(
contentSize
.
height
,
frameSize
.
height
)
-
frameSize
.
height
;
if
((
contentOffset
.
y
+
distance
)
>=
maxY
)
distance
=
maxY
-
contentOffset
.
y
;
translation
=
CGPointMake
(
0
.
0
f
,
distance
);
}
break
;
case
LXScrollingDirectionLeft
:
{
distance
=
-
distance
;
CGFloat
minX
=
0
.
0
f
;
if
((
contentOffset
.
x
+
distance
)
<=
minX
)
distance
=
-
contentOffset
.
x
;
translation
=
CGPointMake
(
distance
,
0
.
0
f
);
}
break
;
case
LXScrollingDirectionRight
:
{
CGFloat
maxX
=
MAX
(
contentSize
.
width
,
frameSize
.
width
)
-
frameSize
.
width
;
if
((
contentOffset
.
x
+
distance
)
>=
maxX
)
distance
=
maxX
-
contentOffset
.
x
;
translation
=
CGPointMake
(
distance
,
0
.
0
f
);
}
break
;
default:
{
// Do nothing...
}
break
;
}
_currentViewCenter
=
LXS_CGPointAdd
(
_currentViewCenter
,
translation
);
_currentView
.
center
=
LXS_CGPointAdd
(
_currentViewCenter
,
_panTranslationInCollectionView
);
self
.
collectionView
.
contentOffset
=
LXS_CGPointAdd
(
contentOffset
,
translation
);
}
-
(
void
)
handlePanGesture
:(
UIPanGestureRecognizer
*
)
gestureRecognizer
{
//keeps the controller from dragging while not in editmode
if
(
!
((
VLCPlaylistViewController
*
)
self
.
delegate
).
isEditing
)
return
;
switch
(
gestureRecognizer
.
state
)
{
case
UIGestureRecognizerStateBegan
:
{
NSIndexPath
*
currentIndexPath
=
[
self
.
collectionView
indexPathForItemAtPoint
:[
gestureRecognizer
locationInView
:
self
.
collectionView
]];
_selectedItemIndexPath
=
currentIndexPath
;
UICollectionViewCell
*
collectionViewCell
=
[
self
.
collectionView
cellForItemAtIndexPath
:
_selectedItemIndexPath
];
_currentView
=
[[
UIView
alloc
]
initWithFrame
:
collectionViewCell
.
frame
];
collectionViewCell
.
highlighted
=
YES
;
UIImageView
*
highlightedImageView
=
[[
UIImageView
alloc
]
initWithImage
:[
collectionViewCell
LX_rasterizedImage
]];
highlightedImageView
.
autoresizingMask
=
UIViewAutoresizingFlexibleWidth
|
UIViewAutoresizingFlexibleHeight
;
highlightedImageView
.
alpha
=
1
.
0
f
;
collectionViewCell
.
highlighted
=
NO
;
UIImageView
*
imageView
=
[[
UIImageView
alloc
]
initWithImage
:[
collectionViewCell
LX_rasterizedImage
]];
imageView
.
autoresizingMask
=
UIViewAutoresizingFlexibleWidth
|
UIViewAutoresizingFlexibleHeight
;
imageView
.
alpha
=
0
.
0
f
;
[
_currentView
addSubview
:
imageView
];
[
_currentView
addSubview
:
highlightedImageView
];
[
self
.
collectionView
addSubview
:
_currentView
];
_currentViewCenter
=
_currentView
.
center
;
[
UIView
animateWithDuration:
0
.
3
delay:
0
.
0
options:
UIViewAnimationOptionBeginFromCurrentState
animations:
^
{
_currentView
.
transform
=
CGAffineTransformMakeScale
(
1
.
1
f
,
1
.
1
f
);
highlightedImageView
.
alpha
=
0
.
0
f
;
imageView
.
alpha
=
1
.
0
f
;
}
completion:
^
(
BOOL
finished
)
{
[
highlightedImageView
removeFromSuperview
];
}];
[
self
invalidateLayout
];
break
;
}
case
UIGestureRecognizerStateChanged
:
{
_panTranslationInCollectionView
=
[
gestureRecognizer
translationInView
:
self
.
collectionView
];
CGPoint
viewCenter
=
_currentView
.
center
=
LXS_CGPointAdd
(
_currentViewCenter
,
_panTranslationInCollectionView
);
[
self
invalidateLayoutIfNecessary
];
switch
(
self
.
scrollDirection
)
{
case
UICollectionViewScrollDirectionVertical
:
{
if
(
viewCenter
.
y
<
(
CGRectGetMinY
(
self
.
collectionView
.
bounds
)
+
self
.
scrollingTriggerEdgeInsets
.
top
))
{
[
self
setupScrollTimerInDirection
:
LXScrollingDirectionUp
];
}
else
{
if
(
viewCenter
.
y
>
(
CGRectGetMaxY
(
self
.
collectionView
.
bounds
)
-
self
.
scrollingTriggerEdgeInsets
.
bottom
))
{
[
self
setupScrollTimerInDirection
:
LXScrollingDirectionDown
];
}
else
{
[
self
invalidatesScrollTimer
];
}
}
}
break
;
case
UICollectionViewScrollDirectionHorizontal
:
{
if
(
viewCenter
.
x
<
(
CGRectGetMinX
(
self
.
collectionView
.
bounds
)
+
self
.
scrollingTriggerEdgeInsets
.
left
))
{
[
self
setupScrollTimerInDirection
:
LXScrollingDirectionLeft
];
}
else
{
if
(
viewCenter
.
x
>
(
CGRectGetMaxX
(
self
.
collectionView
.
bounds
)
-
self
.
scrollingTriggerEdgeInsets
.
right
))
{
[
self
setupScrollTimerInDirection
:
LXScrollingDirectionRight
];
}
else
{
[
self
invalidatesScrollTimer
];
}
}
}
break
;
}
}
break
;
case
UIGestureRecognizerStateCancelled
:
case
UIGestureRecognizerStateEnded
:
{
[
_folderView
removeFromSuperview
];
_folderView
=
nil
;
NSIndexPath
*
newIndexPath
=
[
self
.
collectionView
indexPathForItemAtPoint
:
_currentView
.
center
];
NSIndexPath
*
currentIndexPath
=
_selectedItemIndexPath
;
if
(
newIndexPath
!=
nil
&&
!
[
currentIndexPath
isEqual
:
newIndexPath
])
{
[
UIView
animateWithDuration
:
0
.
3
delay
:
0
.
0
options
:
UIViewAnimationOptionBeginFromCurrentState
animations
:^
{
_currentView
.
transform
=
CGAffineTransformMakeScale
(
0
.
1
f
,
0
.
1
f
);
_currentView
.
center
=
[
self
layoutAttributesForItemAtIndexPath
:
newIndexPath
].
center
;
}
completion
:^
(
BOOL
finished
)
{
[
self
.
delegate
collectionView
:
self
.
collectionView
requestToMoveItemAtIndexPath
:
currentIndexPath
intoFolderAtIndexPath
:
newIndexPath
];
_selectedItemIndexPath
=
nil
;
_currentViewCenter
=
CGPointZero
;
[
_currentView
removeFromSuperview
];
_currentView
=
nil
;
}];
}
else
if
(
currentIndexPath
)
{
[
UIView
animateWithDuration
:
0
.
3
delay
:
0
.
0
options
:
UIViewAnimationOptionBeginFromCurrentState
animations
:^
{
_currentView
.
center
=
[
self
layoutAttributesForItemAtIndexPath
:
currentIndexPath
].
center
;
}
completion
:^
(
BOOL
finished
)
{
_selectedItemIndexPath
=
nil
;
_currentViewCenter
=
CGPointZero
;
[
_currentView
removeFromSuperview
];
_currentView
=
nil
;
[
self
invalidateLayout
];
}];
}
[
self
invalidatesScrollTimer
];
}
break
;
default:
{
// Do nothing...
}
break
;
}
}
#pragma mark - UICollectionViewLayout overridden methods
-
(
NSArray
*
)
layoutAttributesForElementsInRect
:(
CGRect
)
rect
{
NSArray
*
layoutAttributesForElementsInRect
=
[
super
layoutAttributesForElementsInRect
:
rect
];
for
(
UICollectionViewLayoutAttributes
*
layoutAttributes
in
layoutAttributesForElementsInRect
)
{
switch
(
layoutAttributes
.
representedElementCategory
)
{
case
UICollectionElementCategoryCell
:
{
[
self
applyLayoutAttributes
:
layoutAttributes
];
}
break
;
default:
{
// Do nothing...
}
break
;
}
}
return
layoutAttributesForElementsInRect
;
}
-
(
UICollectionViewLayoutAttributes
*
)
layoutAttributesForItemAtIndexPath
:(
NSIndexPath
*
)
indexPath
{
UICollectionViewLayoutAttributes
*
layoutAttributes
=
[
super
layoutAttributesForItemAtIndexPath
:
indexPath
];
switch
(
layoutAttributes
.
representedElementCategory
)
{
case
UICollectionElementCategoryCell
:
{
[
self
applyLayoutAttributes
:
layoutAttributes
];
}
break
;
default:
{
// Do nothing...
}
break
;
}
return
layoutAttributes
;
}
#pragma mark - Key-Value Observing methods
-
(
void
)
observeValueForKeyPath
:(
NSString
*
)
keyPath
ofObject
:(
id
)
object
change
:(
NSDictionary
*
)
change
context
:(
void
*
)
context
{
if
([
keyPath
isEqualToString
:
kLXCollectionViewKeyPath
])
{
if
(
self
.
collectionView
!=
nil
)
{
[
self
setupCollectionView
];
}
else
{
[
self
invalidatesScrollTimer
];
}
}
}
#pragma mark - Notifications
-
(
void
)
handleApplicationWillResignActive
:(
NSNotification
*
)
notification
{
self
.
panGestureRecognizer
.
enabled
=
NO
;
self
.
panGestureRecognizer
.
enabled
=
YES
;
}
@end
Sources/VLCPlaylistCollectionViewCell.h
View file @
6f5a9002
...
...
@@ -30,5 +30,6 @@
-
(
void
)
setEditing
:(
BOOL
)
editing
animated
:(
BOOL
)
animated
;
-
(
void
)
selectionUpdate
;
-
(
void
)
shake
:(
BOOL
)
shake
;
@end
Sources/VLCPlaylistCollectionViewCell.m
View file @
6f5a9002
...
...
@@ -8,6 +8,7 @@
* Authors: Felix Paul Kühne <fkuehne # videolan.org>
* Tamas Timar <ttimar.vlc # gmail.com>
* Gleb Pinigin <gpinigin # gmail.com>
* Carola Nitz <nitz.carola # googlemail.com>
*
* Refer to the COPYING file of the official project for license.
*****************************************************************************/
...
...
@@ -40,6 +41,8 @@
-
(
void
)
setEditing
:(
BOOL
)
editing
animated
:(
BOOL
)
animated
{
self
.
isSelectedView
.
hidden
=
!
editing
;
if
([
_mediaObject
isKindOfClass
:[
MLLabel
class
]]
||
[
_mediaObject
.
labels
count
]
==
0
)
[
self
shake
:
editing
];
[
self
selectionUpdate
];
[
self
_updatedDisplayedInformationForKeyPath
:
@"editing"
];
}
...
...
@@ -52,6 +55,32 @@
self
.
isSelectedView
.
image
=
_checkboxEmptyImage
;
}
-
(
void
)
shake
:(
BOOL
)
shake
{
if
(
shake
)
{
[
UIView
animateWithDuration
:
0
.
3
animations
:
^
{
self
.
contentView
.
transform
=
CGAffineTransformMakeScale
(
0
.
9
f
,
0
.
9
f
);
}];
CAKeyframeAnimation
*
animation
=
[
CAKeyframeAnimation
animationWithKeyPath
:
@"transform.rotation.z"
];
CGFloat
shakeAngle
=
0
.
02
f
;
animation
.
values
=
@[
@
(
-
shakeAngle
),
@
(
shakeAngle
)];
animation
.
autoreverses
=
YES
;
animation
.
duration
=
0
.
125
;
animation
.
repeatCount
=
HUGE_VALF
;
[[
self
layer
]
addAnimation
:
animation
forKey
:
@"shakeAnimation"
];
self
.
contentView
.
layer
.
cornerRadius
=
10
.
0
;
self
.
contentView
.
clipsToBounds
=
YES
;
}
else
{
[
UIView
animateWithDuration
:
0
.
3
animations
:
^
{
self
.
contentView
.
transform
=
CGAffineTransformMakeScale
(
1
.
0
f
,
1
.
0
f
);
self
.
contentView
.
layer
.
cornerRadius
=
0
.
0
;
self
.
contentView
.
clipsToBounds
=
NO
;
}];
[[
self
layer
]
removeAnimationForKey
:
@"shakeAnimation"
];
}
}
-
(
void
)
observeValueForKeyPath
:(
NSString
*
)
keyPath
ofObject
:(
id
)
object
change
:(
NSDictionary
*
)
change
context
:(
void
*
)
context
{
[
self
_updatedDisplayedInformationForKeyPath
:
keyPath
];
...
...
@@ -97,12 +126,50 @@
-
(
void
)
_updatedDisplayedInformationForKeyPath
:(
NSString
*
)
keyPath
{
BOOL
isFolder
=
[
self
.
mediaObject
isKindOfClass
:[
MLLabel
class
]];
self
.
thumbnailView
.
contentMode
=
isFolder
?
UIViewContentModeScaleAspectFit
:
UIViewContentModeScaleAspectFill
;
if
([
self
.
mediaObject
isKindOfClass
:[
MLFile
class
]])
{
MLFile
*
mediaObject
=
self
.
mediaObject
;
[
self
_configureForMLFile
:
mediaObject
];
if
(([
keyPath
isEqualToString
:
@"computedThumbnail"
]
||
!
keyPath
)
||
(
!
self
.
thumbnailView
.
image
&&
[
keyPath
isEqualToString
:
@"editing"
]))
self
.
thumbnailView
.
image
=
[
VLCThumbnailsCache
thumbnailForMediaFile
:
mediaObject
];
}
else
if
([
self
.
mediaObject
isKindOfClass
:[
MLLabel
class
]])
{
MLLabel
*
mediaObject
=
(
MLLabel
*
)
self
.
mediaObject
;
[
self
_configureForFolder
:
mediaObject
];
if
(([
keyPath
isEqualToString
:
@"computedThumbnail"
]
||
!
keyPath
)
||
(
!
self
.
thumbnailView
.
image
&&
[
keyPath
isEqualToString
:
@"editing"
]))
{
NSUInteger
fileNumber
=
[
mediaObject
.
files
count
]
>
3
?
3
:
[
mediaObject
.
files
count
];
if
(
fileNumber
==
0
)
{
self
.
thumbnailView
.
image
=
[
UIImage
imageNamed
:
@"folderIcon"
];
}
else
{
NSArray
*
files
=
[
mediaObject
.
files
allObjects
];
CGSize
frameSize
=
self
.
thumbnailView
.
frame
.
size
;
UIImage
*
displayedImage
;
UIGraphicsBeginImageContext
(
frameSize
);
for
(
NSUInteger
i
=
0
;
i
<
fileNumber
;
i
++
)
{
MLFile
*
file
=
[
files
objectAtIndex
:
i
];
displayedImage
=
[
VLCThumbnailsCache
thumbnailForMediaFile
:
file
];
CGContextRef
context
=
UIGraphicsGetCurrentContext
();
CGFloat
imagePartWidth
=
(
frameSize
.
width
/
fileNumber
);
//the rect in which the image should be drawn
CGRect
clippingRect
=
CGRectMake
(
imagePartWidth
*
i
,
0
,
imagePartWidth
,
frameSize
.
height
);
CGContextSaveGState
(
context
);
CGContextClipToRect
(
context
,
clippingRect
);
//take the center of the clippingRect and calculate the offset from the original center
CGFloat
centerOffset
=
(
imagePartWidth
*
i
+
imagePartWidth
/
2
)
-
frameSize
.
width
/
2
;
//shift the rect to draw the middle of the image in the clippingrect
CGRect
drawingRect
=
CGRectMake
(
centerOffset
,
0
,
frameSize
.
width
,
frameSize
.
height
);
[
displayedImage
drawInRect
:
drawingRect
];
//get rid of the old clippingRect
CGContextRestoreGState
(
context
);
}
displayedImage
=
UIGraphicsGetImageFromCurrentImageContext
();
UIGraphicsEndImageContext
();
self
.
thumbnailView
.
image
=
displayedImage
;
}
}
}
else
if
([
self
.
mediaObject
isKindOfClass
:[
MLAlbum
class
]])
{
MLAlbum
*
mediaObject
=
(
MLAlbum
*
)
self
.
mediaObject
;
[
self
_configureForAlbum
:
mediaObject
];
...
...
@@ -174,7 +241,6 @@
self
.
subtitleLabel
.
text
=
[
NSString
stringWithFormat
:
@"%@"
,
[
VLCTime
timeWithNumber
:[
anyFileFromEpisode
duration
]]];
}
else
self
.
subtitleLabel
.
text
=
[
NSString
stringWithFormat
:
@"S%02dE%02d — %@"
,
showEpisode
.
seasonNumber
.
intValue
,
showEpisode
.
episodeNumber
.
intValue
,
[
VLCTime
timeWithNumber
:[
anyFileFromEpisode
duration
]]];
[
self
_showPositionOfItem
:
anyFileFromEpisode
];
}
...
...
@@ -196,6 +262,15 @@
self
.
progressView
.
hidden
=
YES
;
}
-
(
void
)
_configureForFolder
:(
MLLabel
*
)
label
{
self
.
titleLabel
.
text
=
label
.
name
;
NSUInteger
count
=
label
.
files
.
count
;