Skip to content

Commit

Permalink
feat: implement opacity to control visibility of subtitles (#3583)
Browse files Browse the repository at this point in the history
* feat: implement opacity to control visibility of subtitles

implemented per discussion on #3579

updated docs and linked onTextTrackDataChanged to the subtitle style to clarify intent on how to control visibility.

* chore: update type so that we use a union of 0 1 vs any number

* chore: run ktlint to get rid of white spaces

* feat: add ability to have range of numbers for opacity; while, 0 will still not render the subtitles.

added util function for safeGetFloat

updated types

* feat: add ability to suppress subtitles with opacity 0

add data structure for subtitle styles for extensibility

* chore: run yarn check-ios

* chore: update documentation to clarify differences between android and ios

* Update android/src/main/java/com/brentvatne/exoplayer/ExoPlayerView.java

Co-authored-by: Olivier Bouillet <[email protected]>

---------

Co-authored-by: Olivier Bouillet <[email protected]>
  • Loading branch information
coofzilla and freeboub authored Mar 14, 2024
1 parent 41ac781 commit f4cce2e
Show file tree
Hide file tree
Showing 11 changed files with 52 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@ class SubtitleStyle private constructor() {
private set
var paddingBottom = 0
private set
var opacity = 1f
private set

companion object {
private const val PROP_FONT_SIZE_TRACK = "fontSize"
private const val PROP_PADDING_BOTTOM = "paddingBottom"
private const val PROP_PADDING_TOP = "paddingTop"
private const val PROP_PADDING_LEFT = "paddingLeft"
private const val PROP_PADDING_RIGHT = "paddingRight"
private const val PROP_OPACITY = "opacity"

@JvmStatic
fun parse(src: ReadableMap?): SubtitleStyle {
Expand All @@ -33,6 +36,7 @@ class SubtitleStyle private constructor() {
subtitleStyle.paddingTop = ReactBridgeUtils.safeGetInt(src, PROP_PADDING_TOP, 0)
subtitleStyle.paddingLeft = ReactBridgeUtils.safeGetInt(src, PROP_PADDING_LEFT, 0)
subtitleStyle.paddingRight = ReactBridgeUtils.safeGetInt(src, PROP_PADDING_RIGHT, 0)
subtitleStyle.opacity = ReactBridgeUtils.safeGetFloat(src, PROP_OPACITY, 1f)
return subtitleStyle
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@ object ReactBridgeUtils {
return safeGetDouble(map, key, 0.0)
}

@JvmStatic fun safeGetFloat(map: ReadableMap?, key: String?, fallback: Float): Float {
return if (map != null && map.hasKey(key!!) && !map.isNull(key)) map.getDouble(key).toFloat() else fallback
}

@JvmStatic fun safeGetFloat(map: ReadableMap?, key: String?): Float {
return safeGetFloat(map, key, 0.0f)
}

/**
* toStringMap converts a [ReadableMap] into a HashMap.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,13 @@ public void setSubtitleStyle(SubtitleStyle style) {
subtitleLayout.setFixedTextSize(TypedValue.COMPLEX_UNIT_SP, style.getFontSize());
}
subtitleLayout.setPadding(style.getPaddingLeft(), style.getPaddingTop(), style.getPaddingRight(), style.getPaddingBottom());
if (style.getOpacity() != 0) {
subtitleLayout.setAlpha(style.getOpacity());
subtitleLayout.setVisibility(View.VISIBLE);
} else {
subtitleLayout.setVisibility(View.GONE);
}

}

public void setShutterColor(Integer color) {
Expand Down
2 changes: 2 additions & 0 deletions docs/pages/component/events.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,8 @@ Example:
}
```

For details on how to control the visibility of subtitles, see the [subtitleStyle](./props.mdx#subtitleStyle) section.

### `onVideoTracks`

<PlatformsList types={['Android']} />
Expand Down
3 changes: 2 additions & 1 deletion docs/pages/component/props.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -748,11 +748,12 @@ source={{
| paddingBottom | Adjust the bottom padding of the subtitles. Default: 0 | Android |
| paddingLeft | Adjust the left padding of the subtitles. Default: 0 | Android |
| paddingRight | Adjust the right padding of the subtitles. Default: 0 | Android |
| opacity | Adjust the visibility of subtitles with 0 hiding and 1 fully showing them. Android supports float values between 0 and 1 for varying opacity levels, whereas iOS supports only 0 or 1. Default: 1. | Android, iOS |

Example:

```javascript
subtitleStyle={{ paddingBottom: 50, fontSize: 20 }}
subtitleStyle={{ paddingBottom: 50, fontSize: 20, opacity: 0 }}
```

### `textTracks`
Expand Down
17 changes: 17 additions & 0 deletions ios/Video/DataStructures/SubtitleStyle.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
struct SubtitleStyle {
// Extend with more style properties as needed.
private(set) var opacity: CGFloat

enum SubtitleStyleKeys {
static let opacity = "opacity"
}

init(opacity: CGFloat = 1) {
self.opacity = opacity
}

static func parse(from dictionary: [String: Any]?) -> SubtitleStyle {
let opacity = dictionary?[SubtitleStyleKeys.opacity] as? CGFloat ?? 1
return SubtitleStyle(opacity: opacity)
}
}
3 changes: 3 additions & 0 deletions ios/Video/Features/RCTPlayerObserver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ class RCTPlayerObserver: NSObject, AVPlayerItemMetadataOutputPushDelegate, AVPla
}
}

var subtitleStyle: SubtitleStyle?

var playerItem: AVPlayerItem? {
willSet {
removePlayerItemObservers()
Expand All @@ -63,6 +65,7 @@ class RCTPlayerObserver: NSObject, AVPlayerItemMetadataOutputPushDelegate, AVPla
playerItem.add(legibleOutput)
metadataOutput.setDelegate(self, queue: .main)
legibleOutput.setDelegate(self, queue: .main)
legibleOutput.suppressesPlayerRendering = subtitleStyle?.opacity == 0 ? true : false
}
}

Expand Down
6 changes: 6 additions & 0 deletions ios/Video/RCTVideo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -953,6 +953,12 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
_playerObserver.playerLayer = nil
}

@objc
func setSubtitleStyle(_ style: [String: Any]) {
let subtitleStyle = SubtitleStyle.parse(from: style)
_playerObserver.subtitleStyle = subtitleStyle
}

// MARK: - RCTVideoPlayerViewControllerDelegate

func videoPlayerViewControllerWillDismiss(playerViewController: AVPlayerViewController) {
Expand Down
2 changes: 1 addition & 1 deletion ios/Video/RCTVideoManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ @interface RCT_EXTERN_MODULE (RCTVideoManager, RCTViewManager)
RCT_EXPORT_VIEW_PROPERTY(progressUpdateInterval, float);
RCT_EXPORT_VIEW_PROPERTY(restoreUserInterfaceForPIPStopCompletionHandler, BOOL);
RCT_EXPORT_VIEW_PROPERTY(localSourceEncryptionKeyScheme, NSString);

RCT_EXPORT_VIEW_PROPERTY(subtitleStyle, NSDictionary);
/* Should support: onLoadStart, onLoad, and onError to stay consistent with Image */
RCT_EXPORT_VIEW_PROPERTY(onVideoLoadStart, RCTDirectEventBlock);
RCT_EXPORT_VIEW_PROPERTY(onVideoLoad, RCTDirectEventBlock);
Expand Down
1 change: 1 addition & 0 deletions src/specs/VideoNativeComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ type SubtitleStyle = Readonly<{
paddingBottom?: WithDefault<Float, 0>;
paddingLeft?: WithDefault<Float, 0>;
paddingRight?: WithDefault<Float, 0>;
opacity?: WithDefault<Float, 1>;
}>;

export type OnLoadData = Readonly<{
Expand Down
1 change: 1 addition & 0 deletions src/types/video.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ export type SubtitleStyle = {
paddingBottom?: number;
paddingLeft?: number;
paddingRight?: number;
opacity?: number;
};

export enum TextTracksType {
Expand Down

0 comments on commit f4cce2e

Please sign in to comment.