diff --git a/frontend-tools/video-js/src/VideoJS.css b/frontend-tools/video-js/src/VideoJS.css
index 3474b06d..aad845a0 100644
--- a/frontend-tools/video-js/src/VideoJS.css
+++ b/frontend-tools/video-js/src/VideoJS.css
@@ -35,15 +35,6 @@
box-sizing: border-box;
}
-/* Responsive App container */
-.App {
- width: 100%;
- max-width: 1400px;
- margin: 0 auto;
- padding: 0 20px;
- box-sizing: border-box;
-}
-
/* Ensure video.js responsive behavior */
.video-js.vjs-fluid {
width: 100% !important;
@@ -248,9 +239,8 @@
.vjs-chapter-floating-tooltip {
font-family:
- -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
- 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
- sans-serif !important;
+ -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans",
+ "Droid Sans", "Helvetica Neue", sans-serif !important;
line-height: 1.4 !important;
animation: fadeIn 0.2s ease-in-out;
}
@@ -353,3 +343,106 @@
font-size: 12px !important;
}
}
+
+/* Played portion, buffered portion, unplayed portion */
+.vjs-play-progress {
+ background-color: #019932 !important;
+}
+.vjs-load-progress {
+ background: rgba(255, 255, 255, 0.5) !important;
+}
+.vjs-progress-holder {
+ background: rgba(255, 255, 255, 0.5) !important;
+}
+
+/* Move progress control out of control bar and position it above */
+.video-js .vjs-progress-control {
+ position: absolute !important;
+ bottom: 46px !important;
+ left: 0 !important;
+ right: 0 !important;
+ width: 100% !important;
+ height: 0 !important;
+ z-index: 3 !important;
+ padding: 0 !important;
+ margin: 0 auto !important;
+}
+
+/* Hide the original progress control from the control bar */
+.video-js .vjs-control-bar .vjs-progress-control {
+ display: none !important;
+}
+
+/* Optional: Ensure the progress control is visible */
+.video-js .vjs-progress-control.vjs-control {
+ display: block !important;
+}
+
+/* Make the seek bar thicker */
+/* .video-js .vjs-play-progress,
+.video-js .vjs-load-progress,
+.video-js .vjs-progress-holder {
+ height: 4px !important;
+} */
+
+/* Remove the semi-transparent background from control bar */
+.video-js .vjs-control-bar {
+ background: transparent !important;
+ background-color: transparent !important;
+ background-image: none !important;
+ display: flex !important;
+ flex-direction: row !important;
+ align-items: center !important;
+ justify-content: flex-start !important;
+ gap: 6px !important;
+}
+
+/* Push specific buttons to the right */
+.video-js .vjs-playback-rate,
+.video-js .vjs-picture-in-picture-control,
+.video-js .vjs-fullscreen-control {
+ margin-left: auto !important;
+ order: 999 !important;
+}
+.video-js .vjs-picture-in-picture-control {
+ margin-left: 0 !important;
+}
+.video-js .vjs-fullscreen-control {
+ margin-left: 0 !important;
+}
+
+/* Make all control bar icons bigger */
+.video-js .vjs-control-bar .vjs-icon-placeholder,
+.video-js .vjs-control-bar .vjs-button .vjs-icon-placeholder,
+.video-js .vjs-control-bar [class*="vjs-icon-"] {
+ font-size: 1.5em !important; /* 1.5x bigger */
+ transform: translateY(-28px) !important; /* Move icons up by 3px */
+}
+.video-js .vjs-control-bar svg {
+ width: 3em !important;
+ height: 3em !important;
+ transform: translateY(-16px) !important;
+}
+
+/******** BEGIN: Custom Remaining Time Styles *********/
+.vjs-control-bar .custom-remaining-time .vjs-remaining-time-display {
+ font-size: 14px !important; /* Increase font size */
+ font-weight: 500;
+ line-height: 1;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 100%;
+ color: #fff;
+}
+
+/* Ensure proper vertical alignment within control bar */
+.vjs-control-bar .custom-remaining-time {
+ top: -5px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 100%;
+}
+
+/********* END: Custom Remaining Time Styles *********/
diff --git a/frontend-tools/video-js/src/components/controls/CustomRemainingTime.js b/frontend-tools/video-js/src/components/controls/CustomRemainingTime.js
new file mode 100644
index 00000000..bdb1a2e2
--- /dev/null
+++ b/frontend-tools/video-js/src/components/controls/CustomRemainingTime.js
@@ -0,0 +1,106 @@
+// components/controls/CustomRemainingTime.js
+import videojs from 'video.js';
+
+// Get the Component base class from Video.js
+const Component = videojs.getComponent('Component');
+
+class CustomRemainingTime extends Component {
+ constructor(player, options) {
+ super(player, options);
+
+ // Bind methods to ensure correct 'this' context
+ this.updateContent = this.updateContent.bind(this);
+
+ // Set up event listeners
+ this.on(player, 'timeupdate', this.updateContent);
+ this.on(player, 'durationchange', this.updateContent);
+ this.on(player, 'loadedmetadata', this.updateContent);
+
+ // Store custom options
+ this.options_ = {
+ displayNegative: false,
+ customPrefix: '',
+ customSuffix: '',
+ ...options,
+ };
+ }
+
+ /**
+ * Create the component's DOM element
+ */
+ createEl() {
+ const el = videojs.dom.createEl('div', {
+ className: 'vjs-remaining-time vjs-time-control vjs-control custom-remaining-time',
+ });
+
+ // Add ARIA accessibility
+ el.innerHTML = `
+ Time Display
+ 0:00 / 0:00
+ `;
+
+ return el;
+ }
+
+ /**
+ * Update the time display
+ */
+ updateContent() {
+ const player = this.player();
+ const currentTime = player.currentTime();
+ const duration = player.duration();
+
+ const display = this.el().querySelector('.vjs-remaining-time-display');
+
+ if (display) {
+ const formattedCurrentTime = this.formatTime(isNaN(currentTime) ? 0 : currentTime);
+ const formattedDuration = this.formatTime(isNaN(duration) ? 0 : duration);
+ display.textContent = `${formattedCurrentTime} / ${formattedDuration}`;
+ }
+ }
+
+ /**
+ * Format time with custom logic
+ */
+ formatTime(seconds) {
+ const { customPrefix, customSuffix } = this.options_;
+
+ const hours = Math.floor(seconds / 3600);
+ const minutes = Math.floor((seconds % 3600) / 60);
+ const secs = Math.floor(seconds % 60);
+
+ let timeString;
+ if (hours > 0) {
+ timeString = `${hours}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
+ } else {
+ timeString = `${minutes}:${secs.toString().padStart(2, '0')}`;
+ }
+
+ return `${customPrefix}${timeString}${customSuffix}`;
+ }
+
+ /**
+ * Add click handler for additional functionality
+ */
+ handleClick() {
+ // Example: Toggle between different time formats
+ console.log('Time display clicked');
+ // Could toggle between current/duration vs remaining time
+ }
+
+ /**
+ * Component disposal cleanup
+ */
+ dispose() {
+ // Clean up any additional resources if needed
+ super.dispose();
+ }
+}
+
+// Set component name for Video.js
+CustomRemainingTime.prototype.controlText_ = 'Time Display';
+
+// Register the component with Video.js
+videojs.registerComponent('CustomRemainingTime', CustomRemainingTime);
+
+export default CustomRemainingTime;
diff --git a/frontend-tools/video-js/src/components/video-player/VideoJSPlayer.jsx b/frontend-tools/video-js/src/components/video-player/VideoJSPlayer.jsx
index 120d54fd..4f3e54e0 100644
--- a/frontend-tools/video-js/src/components/video-player/VideoJSPlayer.jsx
+++ b/frontend-tools/video-js/src/components/video-player/VideoJSPlayer.jsx
@@ -6,6 +6,7 @@ import 'video.js/dist/video-js.css';
import EndScreenOverlay from '../overlays/EndScreenOverlay';
import ChapterMarkers from '../markers/ChapterMarkers';
import NextVideoButton from '../controls/NextVideoButton';
+import CustomRemainingTime from '../controls/CustomRemainingTime';
function VideoJSPlayer() {
const videoRef = useRef(null);
@@ -47,9 +48,7 @@ function VideoJSPlayer() {
sources: mediaData.data?.original_media_url
? [
{
- src:
- mediaData.siteUrl +
- mediaData.data.original_media_url,
+ src: mediaData.siteUrl + mediaData.data.original_media_url,
type: 'video/mp4',
},
]
@@ -155,11 +154,7 @@ function VideoJSPlayer() {
const timer = setTimeout(() => {
// Double-check that we still don't have a player and element exists
- if (
- !playerRef.current &&
- videoRef.current &&
- !videoRef.current.player
- ) {
+ if (!playerRef.current && videoRef.current && !videoRef.current.player) {
playerRef.current = videojs(videoRef.current, {
// ===== STANDARD