Function bodies 189 total
getDuration function · javascript · L597-L604 (8 LOC)src/js/player.js
function getDuration() {
const videoDur = video.duration || 0;
const allClips = Timeline.getClips();
const audioDur = allClips
.filter(c => c.type === 'audio')
.reduce((max, c) => Math.max(max, c.startTime + c.duration), 0);
return Math.max(videoDur, audioDur);
}applyFilter function · javascript · L607-L609 (3 LOC)src/js/player.js
function applyFilter(filterString) {
video.style.filter = filterString;
}init function · javascript · L612-L657 (46 LOC)src/js/player.js
function init() {
video.addEventListener('timeupdate', () => {
updateTimeDisplay();
if (isPlaying) syncAudioClips(getCurrentTime());
});
video.addEventListener('ended', () => {
// Check if audio clips are still playing
const audioDur = getDuration();
const current = getCurrentTime();
if (current < audioDur - 0.1) {
// Audio still has time left, keep playing in audio-only mode
audioOnlyTime = current;
startAudioSyncLoop();
return;
}
isPlaying = false;
stopAllAudio();
stopAudioSyncLoop();
playBtn.textContent = 'Play';
playBtn.setAttribute('aria-label', 'Play');
Accessibility.announceStatus('Playback finished');
});
// Seek slider
seekSlider.addEventListener('input', () => {
seekTo(parseFloat(seekSlider.value));
});
// Volume slider
volumeSlider.addEventListener('input', () => {
setVolume(parseInt(volumeSlider.value));
});
generateId function · javascript · L17-L19 (3 LOC)src/js/timeline.js
function generateId() {
return `clip-${++clipIdCounter}`;
}saveState function · javascript · L22-L26 (5 LOC)src/js/timeline.js
function saveState() {
undoStack.push(JSON.parse(JSON.stringify(clips)));
if (undoStack.length > 50) undoStack.shift();
redoStack = [];
}undo function · javascript · L29-L39 (11 LOC)src/js/timeline.js
function undo() {
if (undoStack.length === 0) {
Accessibility.announce('Nothing to undo');
return;
}
redoStack.push(JSON.parse(JSON.stringify(clips)));
clips = undoStack.pop();
renderAllTracks();
Accessibility.announce('Undone');
Accessibility.setStatus('Undo performed');
}redo function · javascript · L42-L52 (11 LOC)src/js/timeline.js
function redo() {
if (redoStack.length === 0) {
Accessibility.announce('Nothing to redo');
return;
}
undoStack.push(JSON.parse(JSON.stringify(clips)));
clips = redoStack.pop();
renderAllTracks();
Accessibility.announce('Redone');
Accessibility.setStatus('Redo performed');
}Want fix-PRs on findings? Install Repobility's GitHub App · github.com/apps/repobility-bot
addClip function · javascript · L55-L80 (26 LOC)src/js/timeline.js
function addClip(clipData) {
saveState();
const id = generateId();
const clip = {
id,
name: clipData.name || 'Untitled',
type: clipData.type || 'video', // 'video', 'audio', 'text'
filePath: clipData.filePath || '',
startTime: clipData.startTime ?? getTrackEndTime(clipData.type || 'video'),
duration: clipData.duration || 5,
trimStart: clipData.trimStart || 0,
trimEnd: clipData.trimEnd || 0,
volume: clipData.volume ?? 100,
speed: clipData.speed || 1,
filters: clipData.filters || {},
text: clipData.text || '',
fontSize: clipData.fontSize || 48,
textColor: clipData.textColor || '#ffffff',
textPosition: clipData.textPosition || 'center',
};
clips.push(clip);
renderAllTracks();
Accessibility.announce(`Added ${clip.type} clip: ${clip.name}, duration ${Accessibility.formatTime(clip.duration)}`);
Accessibility.setStatus(`Clip added: ${clip.name}`);
return id;
}getTrackEndTime function · javascript · L83-L87 (5 LOC)src/js/timeline.js
function getTrackEndTime(type) {
const trackClips = clips.filter(c => c.type === type);
if (trackClips.length === 0) return 0;
return Math.max(...trackClips.map(c => c.startTime + c.duration));
}removeClip function · javascript · L90-L101 (12 LOC)src/js/timeline.js
function removeClip(clipId) {
saveState();
const clip = clips.find(c => c.id === clipId);
if (!clip) return;
const name = clip.name;
clips = clips.filter(c => c.id !== clipId);
if (selectedClipId === clipId) selectedClipId = null;
renderAllTracks();
hideClipProperties();
Accessibility.announce(`Deleted clip: ${name}`);
Accessibility.setStatus(`Clip deleted: ${name}`);
}splitClip function · javascript · L104-L131 (28 LOC)src/js/timeline.js
function splitClip(clipId, splitTime) {
const clip = clips.find(c => c.id === clipId);
if (!clip) return;
const relativeTime = splitTime - clip.startTime;
if (relativeTime <= 0.1 || relativeTime >= clip.duration - 0.1) {
Accessibility.announce('Cannot split at this position');
return;
}
saveState();
const secondHalf = {
...clip,
name: clip.name + ' (2)',
startTime: splitTime,
duration: clip.duration - relativeTime,
trimStart: clip.trimStart + relativeTime,
};
clip.duration = relativeTime;
clip.name = clip.name.replace(/ \(1\)$/, '') + ' (1)';
clips.push({ ...secondHalf, id: generateId() });
renderAllTracks();
Accessibility.announce(`Split clip at ${Accessibility.formatTime(splitTime)}`);
Accessibility.setStatus('Clip split');
}splitAtPlayhead function · javascript · L134-L148 (15 LOC)src/js/timeline.js
function splitAtPlayhead() {
if (!selectedClipId) {
// Find clip under playhead
const clipUnderPlayhead = clips.find(c =>
c.startTime <= playheadPosition && c.startTime + c.duration > playheadPosition
);
if (clipUnderPlayhead) {
splitClip(clipUnderPlayhead.id, playheadPosition);
} else {
Accessibility.announce('No clip at playhead position');
}
return;
}
splitClip(selectedClipId, playheadPosition);
}duplicateClip function · javascript · L151-L167 (17 LOC)src/js/timeline.js
function duplicateClip(clipId) {
const clip = clips.find(c => c.id === (clipId || selectedClipId));
if (!clip) {
Accessibility.announce('No clip selected to duplicate');
return;
}
saveState();
const newClip = {
...clip,
id: generateId(),
name: clip.name + ' (copy)',
startTime: clip.startTime + clip.duration,
};
clips.push(newClip);
renderAllTracks();
Accessibility.announce(`Duplicated clip: ${clip.name}`);
}selectClip function · javascript · L170-L186 (17 LOC)src/js/timeline.js
function selectClip(clipId) {
selectedClipId = clipId;
// Update UI
document.querySelectorAll('.clip').forEach(el => {
el.setAttribute('aria-selected', el.dataset.clipId === clipId ? 'true' : 'false');
});
const clip = clips.find(c => c.id === clipId);
if (clip) {
showClipProperties(clip);
// Show edit toolbar when clip is selected
const editToolbar = document.getElementById('video-toolbar-edit');
if (editToolbar) editToolbar.classList.remove('hidden');
const editLabel = document.getElementById('edit-tools-label');
if (editLabel) editLabel.textContent = `Editing: ${clip.name}`;
Accessibility.announce(`Selected: ${clip.name}, ${clip.type} clip, starts at ${Accessibility.formatTime(clip.startTime)}, duration ${Accessibility.formatTime(clip.duration)}`);
}
}showClipProperties function · javascript · L189-L204 (16 LOC)src/js/timeline.js
function showClipProperties(clip) {
const panel = document.getElementById('clip-properties');
if (panel) panel.classList.remove('hidden');
const nameInput = document.getElementById('clip-name-input');
const startInput = document.getElementById('clip-start-input');
const durationInput = document.getElementById('clip-duration-input');
const volumeSlider = document.getElementById('clip-volume-slider');
const volumeDisplay = document.getElementById('clip-volume-display');
const speedSelect = document.getElementById('clip-speed-select');
if (nameInput) nameInput.value = clip.name;
if (startInput) startInput.value = clip.startTime.toFixed(1);
if (durationInput) durationInput.value = clip.duration.toFixed(1);
if (volumeSlider) volumeSlider.value = clip.volume;
if (volumeDisplay) volumeDisplay.textContent = clip.volume + '%';
if (speedSelect) speedSelect.value = clip.speed;
}Generated by Repobility's multi-pass static-analysis pipeline (https://repobility.com)
hideClipProperties function · javascript · L207-L212 (6 LOC)src/js/timeline.js
function hideClipProperties() {
const panel = document.getElementById('clip-properties');
if (panel) panel.classList.add('hidden');
const editToolbar = document.getElementById('video-toolbar-edit');
if (editToolbar) editToolbar.classList.add('hidden');
}updateClipProperty function · javascript · L215-L222 (8 LOC)src/js/timeline.js
function updateClipProperty(clipId, prop, value) {
const clip = clips.find(c => c.id === (clipId || selectedClipId));
if (!clip) return;
saveState();
clip[prop] = value;
renderAllTracks();
Accessibility.announceStatus(`${prop} updated to ${value}`);
}getPPS function · javascript · L225-L227 (3 LOC)src/js/timeline.js
function getPPS() {
return BASE_PPS * zoom;
}zoomIn function · javascript · L230-L235 (6 LOC)src/js/timeline.js
function zoomIn() {
zoom = Math.min(zoom * 1.25, 5);
renderAllTracks();
document.getElementById('zoom-level').textContent = Math.round(zoom * 100) + '%';
Accessibility.announceStatus(`Zoom: ${Math.round(zoom * 100)}%`);
}zoomOut function · javascript · L238-L243 (6 LOC)src/js/timeline.js
function zoomOut() {
zoom = Math.max(zoom / 1.25, 0.2);
renderAllTracks();
document.getElementById('zoom-level').textContent = Math.round(zoom * 100) + '%';
Accessibility.announceStatus(`Zoom: ${Math.round(zoom * 100)}%`);
}renderAllTracks function · javascript · L246-L254 (9 LOC)src/js/timeline.js
function renderAllTracks() {
renderTrack('video', document.getElementById('video-track-clips'));
renderTrack('audio', document.getElementById('audio-track-clips'));
renderTrack('text', document.getElementById('text-track-clips'));
renderRuler();
updatePlayhead();
// Notify listeners
onChangeCallbacks.forEach(cb => { try { cb(); } catch(e) {} });
}onChange function · javascript · L257-L259 (3 LOC)src/js/timeline.js
function onChange(callback) {
onChangeCallbacks.push(callback);
}renderTrack function · javascript · L262-L325 (64 LOC)src/js/timeline.js
function renderTrack(type, container) {
container.innerHTML = '';
const trackClips = clips.filter(c => c.type === type);
const pps = getPPS();
// Set track width based on content
const maxEnd = trackClips.length > 0
? Math.max(...trackClips.map(c => c.startTime + c.duration))
: 60;
container.style.width = Math.max((maxEnd + 10) * pps, container.parentElement.clientWidth) + 'px';
trackClips.forEach(clip => {
const el = document.createElement('div');
el.className = `clip ${type}-clip`;
el.dataset.clipId = clip.id;
el.setAttribute('role', 'option');
el.setAttribute('aria-selected', clip.id === selectedClipId ? 'true' : 'false');
el.setAttribute('aria-label', `${clip.name}, ${type} clip, starts at ${Accessibility.formatTimeDisplay(clip.startTime)}, duration ${Accessibility.formatTimeDisplay(clip.duration)}`);
el.setAttribute('tabindex', '0');
el.style.left = (clip.startTime * pps) + 'px';
el.sRepobility · code-quality intelligence platform · https://repobility.com
setupClipDrag function · javascript · L328-L357 (30 LOC)src/js/timeline.js
function setupClipDrag(element, clip) {
let isDragging = false;
let startX, originalStart;
element.addEventListener('mousedown', (e) => {
if (e.target.classList.contains('clip-handle')) return;
isDragging = true;
startX = e.clientX;
originalStart = clip.startTime;
saveState();
document.body.style.cursor = 'grabbing';
e.preventDefault();
});
document.addEventListener('mousemove', (e) => {
if (!isDragging) return;
const dx = e.clientX - startX;
const dt = dx / getPPS();
clip.startTime = Math.max(0, originalStart + dt);
element.style.left = (clip.startTime * getPPS()) + 'px';
});
document.addEventListener('mouseup', () => {
if (!isDragging) return;
isDragging = false;
document.body.style.cursor = '';
renderAllTracks();
Accessibility.announceStatus(`Clip moved to ${Accessibility.formatTime(clip.startTime)}`);
});
}setupHandleDrag function · javascript · L360-L395 (36 LOC)src/js/timeline.js
function setupHandleDrag(handle, clip, side) {
let isDragging = false;
let startX, originalDuration, originalStart;
handle.addEventListener('mousedown', (e) => {
isDragging = true;
startX = e.clientX;
originalDuration = clip.duration;
originalStart = clip.startTime;
saveState();
e.preventDefault();
e.stopPropagation();
});
document.addEventListener('mousemove', (e) => {
if (!isDragging) return;
const dx = e.clientX - startX;
const dt = dx / getPPS();
if (side === 'right') {
clip.duration = Math.max(0.5, originalDuration + dt);
} else {
const newStart = Math.max(0, originalStart + dt);
const startDiff = newStart - originalStart;
clip.startTime = newStart;
clip.duration = Math.max(0.5, originalDuration - startDiff);
clip.trimStart = (clip.trimStart || 0) + startDiff;
}
renderAllTracks();
});
document.addEventListener('mouseuprenderRuler function · javascript · L398-L435 (38 LOC)src/js/timeline.js
function renderRuler() {
const canvas = document.getElementById('ruler-canvas');
if (!canvas) return;
const container = document.getElementById('timeline-container');
const pps = getPPS();
const totalTime = getTotalDuration() + 10;
const width = Math.max(totalTime * pps, container.clientWidth);
canvas.width = width;
canvas.height = 24;
const ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, width, 24);
ctx.fillStyle = '#7878a0';
ctx.font = '10px Consolas, monospace';
// Determine step based on zoom
let step = 1;
if (pps < 20) step = 10;
else if (pps < 40) step = 5;
else if (pps < 80) step = 2;
for (let t = 0; t <= totalTime; t += step) {
const x = t * pps;
ctx.fillStyle = '#7878a0';
ctx.fillRect(x, 16, 1, 8);
ctx.fillText(Accessibility.formatTimeDisplay(t), x + 3, 12);
}
// Sub-ticks
const subStep = step / 4;
ctx.fillStyle = '#4a4a6a';
for (let t = 0; t <= totalTiupdatePlayhead function · javascript · L438-L443 (6 LOC)src/js/timeline.js
function updatePlayhead() {
const playhead = document.getElementById('playhead');
if (!playhead) return;
const pps = getPPS();
playhead.style.left = (80 + playheadPosition * pps) + 'px';
}setPlayheadPosition function · javascript · L446-L449 (4 LOC)src/js/timeline.js
function setPlayheadPosition(time) {
playheadPosition = Math.max(0, time);
updatePlayhead();
}getTotalDuration function · javascript · L452-L455 (4 LOC)src/js/timeline.js
function getTotalDuration() {
if (clips.length === 0) return 0;
return Math.max(...clips.map(c => c.startTime + c.duration));
}getClips function · javascript · L458-L460 (3 LOC)src/js/timeline.js
function getClips() {
return clips;
}getSelectedClip function · javascript · L463-L465 (3 LOC)src/js/timeline.js
function getSelectedClip() {
return clips.find(c => c.id === selectedClipId);
}Repobility's GitHub App fixes findings like these · https://github.com/apps/repobility-bot
getClipsAtTime function · javascript · L468-L470 (3 LOC)src/js/timeline.js
function getClipsAtTime(time) {
return clips.filter(c => time >= c.startTime && time < c.startTime + c.duration);
}getVideoClips function · javascript · L473-L475 (3 LOC)src/js/timeline.js
function getVideoClips() {
return clips.filter(c => c.type === 'video').sort((a, b) => a.startTime - b.startTime);
}clearAll function · javascript · L478-L485 (8 LOC)src/js/timeline.js
function clearAll() {
saveState();
clips = [];
selectedClipId = null;
renderAllTracks();
hideClipProperties();
Accessibility.announce('Timeline cleared');
}trimClip function · javascript · L488-L504 (17 LOC)src/js/timeline.js
function trimClip(clipId, trimStart, trimEnd) {
const clip = clips.find(c => c.id === (clipId || selectedClipId));
if (!clip) return;
saveState();
if (trimStart !== undefined && trimStart > 0) {
clip.startTime += trimStart;
clip.duration -= trimStart;
clip.trimStart = (clip.trimStart || 0) + trimStart;
}
if (trimEnd !== undefined && trimEnd > 0) {
clip.duration -= trimEnd;
clip.trimEnd = (clip.trimEnd || 0) + trimEnd;
}
clip.duration = Math.max(0.5, clip.duration);
renderAllTracks();
Accessibility.announce(`Clip trimmed. New duration: ${Accessibility.formatTime(clip.duration)}`);
}removeAudio function · javascript · L507-L514 (8 LOC)src/js/timeline.js
function removeAudio(clipId) {
const clip = clips.find(c => c.id === (clipId || selectedClipId));
if (!clip) return;
saveState();
clip.volume = 0;
renderAllTracks();
Accessibility.announce('Audio removed from clip');
}serialize function · javascript · L517-L519 (3 LOC)src/js/timeline.js
function serialize() {
return { clips, zoom, clipIdCounter };
}deserialize function · javascript · L522-L529 (8 LOC)src/js/timeline.js
function deserialize(data) {
clips = data.clips || [];
zoom = data.zoom || 1;
clipIdCounter = data.clipIdCounter || 0;
selectedClipId = null;
renderAllTracks();
Accessibility.announce(`Project loaded with ${clips.length} clips`);
}initTimelineClick function · javascript · L532-L542 (11 LOC)src/js/timeline.js
function initTimelineClick() {
const container = document.getElementById('timeline-container');
container.addEventListener('click', (e) => {
if (e.target.closest('.clip')) return;
const rect = container.getBoundingClientRect();
const x = e.clientX - rect.left + container.scrollLeft - 80;
const time = Math.max(0, x / getPPS());
setPlayheadPosition(time);
Accessibility.announceStatus(`Playhead at ${Accessibility.formatTime(time)}`);
});
}‹ prevpage 4 / 4