feat: daily timeline advanced UI and calendar integration
This commit is contained in:
@@ -122,6 +122,7 @@ export function compileExpressToTimeline(
|
||||
designMD: DesignMD,
|
||||
company?: CompanyProfile,
|
||||
videoDurations?: Record<string, number>,
|
||||
variationId?: string,
|
||||
): { elements: TimelineElement[]; layers: TimelineLayer[] } {
|
||||
const fps = 30;
|
||||
const elements: TimelineElement[] = [];
|
||||
@@ -278,14 +279,19 @@ export function compileExpressToTimeline(
|
||||
});
|
||||
}
|
||||
|
||||
// Process fields — prefer new TemplateField[] format over legacy editableFields
|
||||
const fieldsToProcess = (scene.fields && scene.fields.length > 0)
|
||||
? scene.fields
|
||||
: null;
|
||||
|
||||
const activeVariation = variationId && scene.variations ? scene.variations.find(v => v.id === variationId) : null;
|
||||
|
||||
if (fieldsToProcess) {
|
||||
// New TemplateField[] format: process ALL natures
|
||||
for (const field of fieldsToProcess) {
|
||||
const position = activeVariation && activeVariation.positions[field.id]
|
||||
? { ...field.position, ...activeVariation.positions[field.id] }
|
||||
: field.position;
|
||||
|
||||
let value: string;
|
||||
|
||||
if (field.nature === 'static') {
|
||||
@@ -346,12 +352,12 @@ export function compileExpressToTimeline(
|
||||
sourceFieldId: field.id,
|
||||
type: elType,
|
||||
content: field.type === 'sticker' ? compiledContent : (value || ''),
|
||||
x: field.position.x,
|
||||
y: field.position.y,
|
||||
x: position.x,
|
||||
y: position.y,
|
||||
startFrame: sceneStart,
|
||||
endFrame: sceneEnd,
|
||||
scale: 1,
|
||||
rotation: field.position.rotation || 0,
|
||||
rotation: position.rotation || 0,
|
||||
opacity: field.style.opacity ?? 100,
|
||||
blendMode: field.style.blendMode,
|
||||
layerId,
|
||||
@@ -372,8 +378,8 @@ export function compileExpressToTimeline(
|
||||
textAlign: (field.style.textAlign as 'left' | 'center' | 'right') || (field.type === 'sticker' ? 'left' : 'center'),
|
||||
} : {}),
|
||||
...(field.type === 'image' || field.type === 'video' ? {
|
||||
width: field.position.w,
|
||||
height: field.position.h,
|
||||
width: position.w,
|
||||
height: position.h,
|
||||
objectFit: ((field.nature === 'brand-variable' && field.brandSource === 'intro-video')
|
||||
? (designMD.introVideoFit || field.style.mediaFit || 'cover')
|
||||
: (field.nature === 'brand-variable' && field.brandSource === 'outro-video')
|
||||
@@ -386,8 +392,8 @@ export function compileExpressToTimeline(
|
||||
: undefined,
|
||||
} : {}),
|
||||
...(field.type === 'shape' ? {
|
||||
width: field.position.w,
|
||||
height: field.position.h,
|
||||
width: position.w,
|
||||
height: position.h,
|
||||
shapeType: field.style.shapeType || 'rectangle',
|
||||
color: field.style.shapeFill || designMD.primaryColor,
|
||||
} : {}),
|
||||
@@ -397,6 +403,10 @@ export function compileExpressToTimeline(
|
||||
} else {
|
||||
// Legacy ExpressField[] format
|
||||
for (const field of scene.editableFields) {
|
||||
const position = activeVariation && activeVariation.positions[field.id]
|
||||
? { ...field.position, ...activeVariation.positions[field.id] }
|
||||
: field.position;
|
||||
|
||||
let value = resolveBrandValue(field, fieldData[field.id] || '', designMD, company, company?.brandContent);
|
||||
// For media fields, placeholder text is not a valid URL — clear it to avoid crashing Remotion
|
||||
const isLegacyMedia = field.type === 'media' || field.type === 'logo';
|
||||
@@ -421,8 +431,8 @@ export function compileExpressToTimeline(
|
||||
sourceFieldId: field.id,
|
||||
type: elType,
|
||||
content: value || '',
|
||||
x: field.position.x,
|
||||
y: field.position.y,
|
||||
x: position.x,
|
||||
y: position.y,
|
||||
startFrame: sceneStart,
|
||||
endFrame: sceneEnd,
|
||||
scale: 1,
|
||||
@@ -444,11 +454,11 @@ export function compileExpressToTimeline(
|
||||
fontFamily: resolveFont(field, designMD),
|
||||
color: resolveColor(field, designMD),
|
||||
textAlign: (field.style.textAlign as 'left' | 'center' | 'right') || 'center',
|
||||
width: field.position.w,
|
||||
width: position.w,
|
||||
} : {}),
|
||||
...(field.type === 'media' || field.type === 'logo' ? {
|
||||
width: field.position.w,
|
||||
height: field.position.h,
|
||||
width: position.w,
|
||||
height: position.h,
|
||||
objectFit: 'cover' as const,
|
||||
} : {}),
|
||||
transitionIn: scene.transition ? { type: scene.transition.type as TransitionType, duration: scene.transition.duration } : undefined,
|
||||
|
||||
Reference in New Issue
Block a user