mirror of
https://github.com/mediacms-io/mediacms.git
synced 2025-12-09 13:42:29 -05:00
Compare commits
9 Commits
9b3d9fe1e7
...
feat/ui-tr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ddf23271ea | ||
|
|
f2c83b8998 | ||
|
|
2c367d7eeb | ||
|
|
6eae3310ad | ||
|
|
e536c74576 | ||
|
|
aeef8284bf | ||
|
|
a90fcbf8dd | ||
|
|
1b3cdfd302 | ||
|
|
cd7dd4f72c |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -35,3 +35,4 @@ frontend-tools/video-editor/client/public/videos/sample-video.mp3
|
||||
frontend-tools/chapters-editor/client/public/videos/sample-video.mp3
|
||||
static/chapters_editor/videos/sample-video.mp3
|
||||
static/video_editor/videos/sample-video.mp3
|
||||
templates/todo-MS4.md
|
||||
|
||||
@@ -69,7 +69,7 @@ Copyright Markos Gogoulos.
|
||||
|
||||
## Support and paid services
|
||||
|
||||
We provide custom installations, development of extra functionality, migration from existing systems, integrations with legacy systems, training and support. Contact us at info@mediacms.io for more information.
|
||||
We provide custom installations, development of extra functionality, migration from existing systems, integrations with legacy systems, training and support. Checkout our [services page](https://mediacms.io/#services/) for more information.
|
||||
|
||||
### Commercial Hostings
|
||||
**Elestio**
|
||||
|
||||
@@ -1 +1 @@
|
||||
VERSION = "7.2.1"
|
||||
VERSION = "7.3.0"
|
||||
|
||||
@@ -329,10 +329,17 @@ class Media(models.Model):
|
||||
|
||||
if to_transcribe:
|
||||
TranscriptionRequest.objects.create(media=self, translate_to_english=False)
|
||||
tasks.whisper_transcribe.delay(self.friendly_token, translate_to_english=False)
|
||||
tasks.whisper_transcribe.apply_async(
|
||||
args=[self.friendly_token, False],
|
||||
countdown=10,
|
||||
)
|
||||
|
||||
if to_transcribe_and_translate:
|
||||
TranscriptionRequest.objects.create(media=self, translate_to_english=True)
|
||||
tasks.whisper_transcribe.delay(self.friendly_token, translate_to_english=True)
|
||||
tasks.whisper_transcribe.apply_async(
|
||||
args=[self.friendly_token, True],
|
||||
countdown=10,
|
||||
)
|
||||
|
||||
def update_search_vector(self):
|
||||
"""
|
||||
|
||||
@@ -150,6 +150,11 @@ const App = () => {
|
||||
canRedo={historyPosition < history.length - 1}
|
||||
/>
|
||||
|
||||
{/* Timeline Header */}
|
||||
<div className="timeline-header-container">
|
||||
<h2 className="timeline-header-title">Add Chapters</h2>
|
||||
</div>
|
||||
|
||||
{/* Timeline Controls */}
|
||||
<TimelineControls
|
||||
currentTime={currentTime}
|
||||
|
||||
@@ -20,7 +20,7 @@ const useVideoChapters = () => {
|
||||
// Sort by start time to find chronological position
|
||||
const sortedSegments = allSegments.sort((a, b) => a.startTime - b.startTime);
|
||||
// Find the index of our new segment
|
||||
const chapterIndex = sortedSegments.findIndex(seg => seg.startTime === newSegmentStartTime);
|
||||
const chapterIndex = sortedSegments.findIndex((seg) => seg.startTime === newSegmentStartTime);
|
||||
return `Chapter ${chapterIndex + 1}`;
|
||||
};
|
||||
|
||||
@@ -30,10 +30,16 @@ const useVideoChapters = () => {
|
||||
const sortedSegments = [...segments].sort((a, b) => a.startTime - b.startTime);
|
||||
|
||||
// Renumber each segment based on its chronological position
|
||||
return sortedSegments.map((segment, index) => ({
|
||||
// Only update titles that follow the default "Chapter X" pattern to preserve custom titles
|
||||
return sortedSegments.map((segment, index) => {
|
||||
const currentTitle = segment.chapterTitle || '';
|
||||
const isDefaultTitle = /^Chapter \d+$/.test(currentTitle);
|
||||
|
||||
return {
|
||||
...segment,
|
||||
chapterTitle: `Chapter ${index + 1}`
|
||||
}));
|
||||
chapterTitle: isDefaultTitle ? `Chapter ${index + 1}` : currentTitle,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
// Helper function to parse time string (HH:MM:SS.mmm) to seconds
|
||||
@@ -124,9 +130,7 @@ const useVideoChapters = () => {
|
||||
let initialSegments: Segment[] = [];
|
||||
|
||||
// Check if we have existing chapters from the backend
|
||||
const existingChapters =
|
||||
(typeof window !== 'undefined' && (window as any).MEDIA_DATA?.chapters) ||
|
||||
[];
|
||||
const existingChapters = (typeof window !== 'undefined' && (window as any).MEDIA_DATA?.chapters) || [];
|
||||
|
||||
if (existingChapters.length > 0) {
|
||||
// Create segments from existing chapters
|
||||
@@ -564,8 +568,11 @@ const useVideoChapters = () => {
|
||||
`Updating segments with action: ${actionType}, recordHistory: ${isSignificantChange ? 'true' : 'false'}`
|
||||
);
|
||||
|
||||
// Renumber all segments to ensure proper chronological naming
|
||||
const renumberedSegments = renumberAllSegments(e.detail.segments);
|
||||
|
||||
// Update segment state immediately for UI feedback
|
||||
setClipSegments(e.detail.segments);
|
||||
setClipSegments(renumberedSegments);
|
||||
|
||||
// Always save state to history for non-intermediate actions
|
||||
if (isSignificantChange) {
|
||||
@@ -573,7 +580,7 @@ const useVideoChapters = () => {
|
||||
// ensure we capture the state properly
|
||||
setTimeout(() => {
|
||||
// Deep clone to ensure state is captured correctly
|
||||
const segmentsClone = JSON.parse(JSON.stringify(e.detail.segments));
|
||||
const segmentsClone = JSON.parse(JSON.stringify(renumberedSegments));
|
||||
|
||||
// Create a complete state snapshot
|
||||
const stateWithAction: EditorState = {
|
||||
|
||||
@@ -1,4 +1,16 @@
|
||||
#chapters-editor-root {
|
||||
.timeline-header-container {
|
||||
margin-left: 1rem;
|
||||
margin-top: -0.5rem;
|
||||
}
|
||||
|
||||
.timeline-header-title {
|
||||
font-size: 1.125rem;
|
||||
font-weight: 600;
|
||||
color: #059669;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.timeline-container-card {
|
||||
background-color: white;
|
||||
border-radius: 0.5rem;
|
||||
@@ -11,6 +23,8 @@
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-bottom: 0.5rem;
|
||||
border-bottom: 2px solid rgba(16, 185, 129, 0.2);
|
||||
}
|
||||
|
||||
.timeline-title {
|
||||
@@ -21,6 +35,8 @@
|
||||
|
||||
.timeline-title-text {
|
||||
font-weight: 700;
|
||||
color: #059669;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.current-time {
|
||||
@@ -48,10 +64,11 @@
|
||||
.timeline-container {
|
||||
position: relative;
|
||||
min-width: 100%;
|
||||
background-color: #fafbfc;
|
||||
background-color: #E2EDE4;
|
||||
height: 70px;
|
||||
border-radius: 0.25rem;
|
||||
overflow: visible !important;
|
||||
border: 1px solid rgba(16, 185, 129, 0.2);
|
||||
}
|
||||
|
||||
.timeline-marker {
|
||||
@@ -194,7 +211,7 @@
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 0.4rem;
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
background-color: rgba(16, 185, 129, 0.6);
|
||||
color: white;
|
||||
opacity: 1;
|
||||
transition: background-color 0.2s;
|
||||
@@ -202,15 +219,15 @@
|
||||
}
|
||||
|
||||
.clip-segment:hover .clip-segment-info {
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
background-color: rgba(16, 185, 129, 0.7);
|
||||
}
|
||||
|
||||
.clip-segment.selected .clip-segment-info {
|
||||
background-color: rgba(59, 130, 246, 0.5);
|
||||
background-color: rgba(5, 150, 105, 0.8);
|
||||
}
|
||||
|
||||
.clip-segment.selected:hover .clip-segment-info {
|
||||
background-color: rgba(59, 130, 246, 0.4);
|
||||
background-color: rgba(5, 150, 105, 0.75);
|
||||
}
|
||||
|
||||
.clip-segment-name {
|
||||
|
||||
@@ -309,6 +309,11 @@ const App = () => {
|
||||
canRedo={historyPosition < history.length - 1}
|
||||
/>
|
||||
|
||||
{/* Timeline Header */}
|
||||
<div className="timeline-header-container">
|
||||
<h2 className="timeline-header-title">Trim or Split</h2>
|
||||
</div>
|
||||
|
||||
{/* Timeline Controls */}
|
||||
<TimelineControls
|
||||
currentTime={currentTime}
|
||||
|
||||
@@ -1,4 +1,16 @@
|
||||
#video-editor-trim-root {
|
||||
.timeline-header-container {
|
||||
margin-left: 1rem;
|
||||
margin-top: -0.5rem;
|
||||
}
|
||||
|
||||
.timeline-header-title {
|
||||
font-size: 1.125rem;
|
||||
font-weight: 600;
|
||||
color: #2563eb;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.timeline-container-card {
|
||||
background-color: white;
|
||||
border-radius: 0.5rem;
|
||||
@@ -11,6 +23,8 @@
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-bottom: 0.5rem;
|
||||
border-bottom: 2px solid rgba(59, 130, 246, 0.2);
|
||||
}
|
||||
|
||||
.timeline-title {
|
||||
@@ -21,6 +35,8 @@
|
||||
|
||||
.timeline-title-text {
|
||||
font-weight: 700;
|
||||
color: #2563eb;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.current-time {
|
||||
@@ -48,10 +64,11 @@
|
||||
.timeline-container {
|
||||
position: relative;
|
||||
min-width: 100%;
|
||||
background-color: #fafbfc;
|
||||
background-color: #eff6ff;
|
||||
height: 70px;
|
||||
border-radius: 0.25rem;
|
||||
overflow: visible !important;
|
||||
border: 1px solid rgba(59, 130, 246, 0.2);
|
||||
}
|
||||
|
||||
.timeline-marker {
|
||||
@@ -194,7 +211,7 @@
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 0.4rem;
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
background-color: rgba(59, 130, 246, 0.6);
|
||||
color: white;
|
||||
opacity: 1;
|
||||
transition: background-color 0.2s;
|
||||
@@ -202,15 +219,15 @@
|
||||
}
|
||||
|
||||
.clip-segment:hover .clip-segment-info {
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
background-color: rgba(59, 130, 246, 0.7);
|
||||
}
|
||||
|
||||
.clip-segment.selected .clip-segment-info {
|
||||
background-color: rgba(59, 130, 246, 0.5);
|
||||
background-color: rgba(37, 99, 235, 0.8);
|
||||
}
|
||||
|
||||
.clip-segment.selected:hover .clip-segment-info {
|
||||
background-color: rgba(59, 130, 246, 0.4);
|
||||
background-color: rgba(37, 99, 235, 0.75);
|
||||
}
|
||||
|
||||
.clip-segment-name {
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user