mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-01-11 20:10:25 +00:00
asepct ratio fix
This commit is contained in:
parent
f027788266
commit
415efd4e03
4 changed files with 64 additions and 7 deletions
|
|
@ -20,6 +20,7 @@ RCT_EXPORT_VIEW_PROPERTY(allowsExternalPlayback, BOOL)
|
|||
RCT_EXPORT_VIEW_PROPERTY(usesExternalPlaybackWhileExternalScreenIsActive, BOOL)
|
||||
RCT_EXPORT_VIEW_PROPERTY(subtitleBottomOffset, NSNumber)
|
||||
RCT_EXPORT_VIEW_PROPERTY(subtitleFontSize, NSNumber)
|
||||
RCT_EXPORT_VIEW_PROPERTY(resizeMode, NSString)
|
||||
|
||||
// Event properties
|
||||
RCT_EXPORT_VIEW_PROPERTY(onLoad, RCTDirectEventBlock)
|
||||
|
|
|
|||
|
|
@ -91,6 +91,13 @@ class KSPlayerView: UIView {
|
|||
updateSubtitleFont(size: size)
|
||||
}
|
||||
}
|
||||
|
||||
@objc var resizeMode: NSString = "contain" {
|
||||
didSet {
|
||||
print("KSPlayerView: [PROP SETTER] resizeMode setter called with value: \(resizeMode)")
|
||||
applyVideoGravity()
|
||||
}
|
||||
}
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
|
@ -128,7 +135,10 @@ class KSPlayerView: UIView {
|
|||
// KSPlayer's subtitleLabel renders internal subtitles
|
||||
playerView.subtitleLabel.isHidden = false
|
||||
playerView.subtitleBackView.isHidden = false
|
||||
playerView.bringSubviewToFront(playerView.subtitleBackView)
|
||||
// Move subtitle view to main container for independence from video transformations
|
||||
playerView.subtitleBackView.removeFromSuperview()
|
||||
self.addSubview(playerView.subtitleBackView)
|
||||
self.bringSubviewToFront(playerView.subtitleBackView)
|
||||
print("KSPlayerView: [SETUP] Subtitle views made visible")
|
||||
print("KSPlayerView: [SETUP] subtitleLabel.isHidden: \(playerView.subtitleLabel.isHidden)")
|
||||
print("KSPlayerView: [SETUP] subtitleBackView.isHidden: \(playerView.subtitleBackView.isHidden)")
|
||||
|
|
@ -149,7 +159,10 @@ class KSPlayerView: UIView {
|
|||
private func adjustSubtitlePositioning() {
|
||||
// Remove existing constraints for subtitle positioning
|
||||
playerView.subtitleBackView.removeFromSuperview()
|
||||
playerView.addSubview(playerView.subtitleBackView)
|
||||
// Add subtitle view to main container (self) instead of playerView to make it independent of video transformations
|
||||
self.addSubview(playerView.subtitleBackView)
|
||||
// Ensure subtitles are always on top of video
|
||||
self.bringSubviewToFront(playerView.subtitleBackView)
|
||||
|
||||
// Re-add subtitle label to subtitle back view
|
||||
playerView.subtitleBackView.addSubview(playerView.subtitleLabel)
|
||||
|
|
@ -159,13 +172,14 @@ class KSPlayerView: UIView {
|
|||
playerView.subtitleLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
// Store the bottom constraint reference for dynamic updates
|
||||
subtitleBottomConstraint = playerView.subtitleBackView.bottomAnchor.constraint(equalTo: playerView.bottomAnchor, constant: -CGFloat(subtitleBottomOffset.floatValue))
|
||||
// Constrain to main container (self) instead of playerView to make subtitles independent of video transformations
|
||||
subtitleBottomConstraint = playerView.subtitleBackView.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -CGFloat(subtitleBottomOffset.floatValue))
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
// Position subtitles using dynamic offset from React Native
|
||||
subtitleBottomConstraint!,
|
||||
playerView.subtitleBackView.centerXAnchor.constraint(equalTo: playerView.centerXAnchor),
|
||||
playerView.subtitleBackView.widthAnchor.constraint(lessThanOrEqualTo: playerView.widthAnchor, constant: -20),
|
||||
playerView.subtitleBackView.centerXAnchor.constraint(equalTo: self.centerXAnchor),
|
||||
playerView.subtitleBackView.widthAnchor.constraint(lessThanOrEqualTo: self.widthAnchor, constant: -20),
|
||||
playerView.subtitleBackView.heightAnchor.constraint(lessThanOrEqualToConstant: 100),
|
||||
|
||||
// Subtitle label constraints within the back view
|
||||
|
|
@ -200,6 +214,30 @@ class KSPlayerView: UIView {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func applyVideoGravity() {
|
||||
print("KSPlayerView: [VIDEO GRAVITY] Applying resizeMode: \(resizeMode)")
|
||||
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
guard let self = self else { return }
|
||||
|
||||
let contentMode: UIViewContentMode
|
||||
switch self.resizeMode.lowercased {
|
||||
case "cover":
|
||||
contentMode = .scaleAspectFill
|
||||
case "stretch":
|
||||
contentMode = .scaleToFill
|
||||
case "contain":
|
||||
contentMode = .scaleAspectFit
|
||||
default:
|
||||
contentMode = .scaleAspectFit
|
||||
}
|
||||
|
||||
// Set contentMode on the player itself, not the view
|
||||
self.playerView.playerLayer?.player.contentMode = contentMode
|
||||
print("KSPlayerView: [VIDEO GRAVITY] Set player contentMode to: \(contentMode)")
|
||||
}
|
||||
}
|
||||
|
||||
private func setupPlayerCallbacks() {
|
||||
// Configure KSOptions (use static defaults where required)
|
||||
|
|
@ -275,6 +313,9 @@ class KSPlayerView: UIView {
|
|||
if let playerLayer = playerView.playerLayer {
|
||||
playerLayer.delegate = self
|
||||
print("KSPlayerView: Delegate set successfully on playerLayer")
|
||||
|
||||
// Apply video gravity after player is set up
|
||||
applyVideoGravity()
|
||||
} else {
|
||||
print("KSPlayerView: ERROR - playerLayer is nil, cannot set delegate")
|
||||
}
|
||||
|
|
@ -546,7 +587,11 @@ class KSPlayerView: UIView {
|
|||
} else if trackId == -1 {
|
||||
// Disable all subtitles
|
||||
for track in textTracks { track.isEnabled = false }
|
||||
print("KSPlayerView: Disabled all text tracks")
|
||||
// Clear srtControl selection and hide subtitle views
|
||||
self.playerView.srtControl.selectedSubtitleInfo = nil
|
||||
self.playerView.subtitleLabel.isHidden = true
|
||||
self.playerView.subtitleBackView.isHidden = true
|
||||
print("KSPlayerView: Disabled all text tracks and cleared srtControl selection")
|
||||
} else {
|
||||
print("KSPlayerView: Text track \(trackId) not found. Available track IDs: \(textTracks.map { Int($0.trackID) }), array indices: 0..\(textTracks.count - 1)")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ interface KSPlayerViewProps {
|
|||
usesExternalPlaybackWhileExternalScreenIsActive?: boolean;
|
||||
subtitleBottomOffset?: number;
|
||||
subtitleFontSize?: number;
|
||||
resizeMode?: 'contain' | 'cover' | 'stretch';
|
||||
onLoad?: (data: any) => void;
|
||||
onProgress?: (data: any) => void;
|
||||
onBuffering?: (data: any) => void;
|
||||
|
|
@ -52,6 +53,7 @@ export interface KSPlayerProps {
|
|||
usesExternalPlaybackWhileExternalScreenIsActive?: boolean;
|
||||
subtitleBottomOffset?: number;
|
||||
subtitleFontSize?: number;
|
||||
resizeMode?: 'contain' | 'cover' | 'stretch';
|
||||
onLoad?: (data: any) => void;
|
||||
onProgress?: (data: any) => void;
|
||||
onBuffering?: (data: any) => void;
|
||||
|
|
@ -177,6 +179,7 @@ const KSPlayer = forwardRef<KSPlayerRef, KSPlayerProps>((props, ref) => {
|
|||
usesExternalPlaybackWhileExternalScreenIsActive={props.usesExternalPlaybackWhileExternalScreenIsActive}
|
||||
subtitleBottomOffset={props.subtitleBottomOffset}
|
||||
subtitleFontSize={props.subtitleFontSize}
|
||||
resizeMode={props.resizeMode}
|
||||
onLoad={(e: any) => props.onLoad?.(e?.nativeEvent ?? e)}
|
||||
onProgress={(e: any) => props.onProgress?.(e?.nativeEvent ?? e)}
|
||||
onBuffering={(e: any) => props.onBuffering?.(e?.nativeEvent ?? e)}
|
||||
|
|
|
|||
|
|
@ -1315,6 +1315,12 @@ const KSPlayerCore: React.FC = () => {
|
|||
};
|
||||
|
||||
const cycleAspectRatio = () => {
|
||||
// iOS KSPlayer: toggle native resize mode so subtitles remain independent
|
||||
if (Platform.OS === 'ios') {
|
||||
setResizeMode((prev) => (prev === 'cover' ? 'contain' : 'cover'));
|
||||
return;
|
||||
}
|
||||
// Fallback (non‑iOS paths): keep legacy zoom behavior
|
||||
const newZoom = zoomScale === 1.1 ? 1 : 1.1;
|
||||
setZoomScale(newZoom);
|
||||
setZoomTranslateX(0);
|
||||
|
|
@ -2717,7 +2723,7 @@ const KSPlayerCore: React.FC = () => {
|
|||
>
|
||||
<KSPlayerComponent
|
||||
ref={ksPlayerRef}
|
||||
style={[styles.video, customVideoStyles, { transform: [{ scale: zoomScale }] }]}
|
||||
style={styles.video}
|
||||
source={{
|
||||
uri: currentStreamUrl,
|
||||
headers: headers && Object.keys(headers).length > 0 ? headers : undefined
|
||||
|
|
@ -2730,6 +2736,7 @@ const KSPlayerCore: React.FC = () => {
|
|||
usesExternalPlaybackWhileExternalScreenIsActive={true}
|
||||
subtitleBottomOffset={subtitleBottomOffset}
|
||||
subtitleFontSize={subtitleSize}
|
||||
resizeMode={resizeMode === 'none' ? 'contain' : resizeMode}
|
||||
onProgress={handleProgress}
|
||||
onLoad={onLoad}
|
||||
onEnd={onEnd}
|
||||
|
|
@ -2762,6 +2769,7 @@ const KSPlayerCore: React.FC = () => {
|
|||
skip={skip}
|
||||
handleClose={handleClose}
|
||||
cycleAspectRatio={cycleAspectRatio}
|
||||
currentResizeMode={resizeMode}
|
||||
setShowAudioModal={setShowAudioModal}
|
||||
setShowSubtitleModal={setShowSubtitleModal}
|
||||
isSubtitleModalOpen={showSubtitleModal}
|
||||
|
|
|
|||
Loading…
Reference in a new issue