Skip to content

Commit c356f47

Browse files
committed
fix: composer minor bugs
1 parent ccb267c commit c356f47

File tree

5 files changed

+130
-78
lines changed

5 files changed

+130
-78
lines changed

example/src/components/EventEditorPanel.tsx

Lines changed: 72 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -138,30 +138,37 @@ export default function EventEditorPanel({
138138
Fade In
139139
</Text>
140140
</View>
141-
<SliderField
142-
label="Fade In Smoothness"
143-
value={1 - event.fadeInIntensity}
144-
min={0}
145-
max={1}
146-
step={0.01}
147-
displayValue={`${(1 - event.fadeInIntensity).toFixed(2)}`}
148-
description="Higher smoothness starts from zero intensity"
149-
onValueChange={(value) =>
150-
onUpdateEvent({ fadeInIntensity: 1 - value })
151-
}
152-
colors={colors}
153-
/>
154-
<PanInput
155-
label="Duration"
156-
value={event.fadeInDuration}
157-
unit="sec"
158-
min={0}
159-
max={event.duration / 2}
160-
onValueChange={(value) =>
161-
onUpdateEvent({ fadeInDuration: value })
162-
}
163-
colors={colors}
164-
/>
141+
<View style={styles.fadeFieldsRow}>
142+
<View style={styles.fadeDurationWrapper}>
143+
<PanInput
144+
label="Duration"
145+
value={event.fadeInDuration}
146+
unit="sec"
147+
min={0}
148+
max={event.duration / 2}
149+
description={`How long the fade in takes\n`}
150+
onValueChange={(value) =>
151+
onUpdateEvent({ fadeInDuration: value })
152+
}
153+
colors={colors}
154+
/>
155+
</View>
156+
<View style={styles.fadeSliderWrapper}>
157+
<SliderField
158+
label="Smoothness"
159+
value={1 - event.fadeInIntensity}
160+
min={0}
161+
max={1}
162+
step={0.01}
163+
displayValue={`${(1 - event.fadeInIntensity).toFixed(2)}`}
164+
description="Higher smoothness starts from zero intensity"
165+
onValueChange={(value) =>
166+
onUpdateEvent({ fadeInIntensity: 1 - value })
167+
}
168+
colors={colors}
169+
/>
170+
</View>
171+
</View>
165172
</View>
166173
)}
167174

@@ -177,30 +184,37 @@ export default function EventEditorPanel({
177184
Fade Out
178185
</Text>
179186
</View>
180-
<SliderField
181-
label="Fade Out Smoothness"
182-
value={1 - event.fadeOutIntensity}
183-
min={0}
184-
max={1}
185-
step={0.01}
186-
displayValue={`${(1 - event.fadeOutIntensity).toFixed(2)}`}
187-
description="Higher smoothness ends at zero intensity"
188-
onValueChange={(value) =>
189-
onUpdateEvent({ fadeOutIntensity: 1 - value })
190-
}
191-
colors={colors}
192-
/>
193-
<PanInput
194-
label="Duration"
195-
value={(event as ContinuousComposerEvent).fadeOutDuration}
196-
unit="sec"
197-
min={0}
198-
max={event.duration / 2}
199-
onValueChange={(value) =>
200-
onUpdateEvent({ fadeOutDuration: value })
201-
}
202-
colors={colors}
203-
/>
187+
<View style={styles.fadeFieldsRow}>
188+
<View style={styles.fadeDurationWrapper}>
189+
<PanInput
190+
label="Duration"
191+
value={(event as ContinuousComposerEvent).fadeOutDuration}
192+
unit="sec"
193+
min={0}
194+
max={event.duration / 2}
195+
description={`How long the fade out takes\n`}
196+
onValueChange={(value) =>
197+
onUpdateEvent({ fadeOutDuration: value })
198+
}
199+
colors={colors}
200+
/>
201+
</View>
202+
<View style={styles.fadeSliderWrapper}>
203+
<SliderField
204+
label="Smoothness"
205+
value={1 - event.fadeOutIntensity}
206+
min={0}
207+
max={1}
208+
step={0.01}
209+
displayValue={`${(1 - event.fadeOutIntensity).toFixed(2)}`}
210+
description="Higher smoothness ends at zero intensity"
211+
onValueChange={(value) =>
212+
onUpdateEvent({ fadeOutIntensity: 1 - value })
213+
}
214+
colors={colors}
215+
/>
216+
</View>
217+
</View>
204218
</View>
205219
)}
206220
</KeyboardAwareScrollView>
@@ -368,4 +382,14 @@ const styles = StyleSheet.create({
368382
timeFieldWrapper: {
369383
flex: 1,
370384
},
385+
fadeFieldsRow: {
386+
flexDirection: 'row',
387+
gap: 12,
388+
},
389+
fadeDurationWrapper: {
390+
flex: 1,
391+
},
392+
fadeSliderWrapper: {
393+
flex: 1,
394+
},
371395
});

example/src/components/EventNavigation.tsx

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,41 +2,40 @@ import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
22
import { useTheme } from '../contexts/ThemeContext';
33

44
interface EventNavigationProps {
5-
selectedEventId: string | null;
6-
totalEvents: number;
5+
hasSelection: boolean;
6+
canGoPrevious: boolean;
7+
canGoNext: boolean;
78
onPrevious: () => void;
89
onNext: () => void;
910
}
1011

1112
export default function EventNavigation({
12-
selectedEventId,
13-
totalEvents,
13+
hasSelection,
14+
canGoPrevious,
15+
canGoNext,
1416
onPrevious,
1517
onNext,
1618
}: EventNavigationProps) {
1719
const { colors } = useTheme();
1820

19-
const hasSelection = selectedEventId !== null;
20-
// Navigation buttons are enabled when there's a selection and multiple events
21-
const canNavigate = hasSelection && totalEvents > 1;
22-
2321
return (
2422
<View style={styles.container}>
2523
{/* Previous button */}
2624
<TouchableOpacity
2725
style={[
2826
styles.arrowButton,
29-
{ backgroundColor: colors.card },
30-
!canNavigate && styles.disabledButton,
27+
{
28+
backgroundColor: canGoPrevious ? colors.blue : colors.card,
29+
},
3130
]}
3231
onPress={onPrevious}
33-
disabled={!canNavigate}
32+
disabled={!canGoPrevious}
3433
activeOpacity={0.7}
3534
>
3635
<Text
3736
style={[
3837
styles.arrowText,
39-
{ color: canNavigate ? colors.blue : colors.tertiaryText },
38+
{ color: canGoPrevious ? '#FFFFFF' : colors.tertiaryText },
4039
]}
4140
>
4241
@@ -54,17 +53,18 @@ export default function EventNavigation({
5453
<TouchableOpacity
5554
style={[
5655
styles.arrowButton,
57-
{ backgroundColor: colors.blue },
58-
!canNavigate && { backgroundColor: colors.card },
56+
{
57+
backgroundColor: canGoNext ? colors.blue : colors.card,
58+
},
5959
]}
6060
onPress={onNext}
61-
disabled={!canNavigate}
61+
disabled={!canGoNext}
6262
activeOpacity={0.7}
6363
>
6464
<Text
6565
style={[
6666
styles.arrowText,
67-
{ color: canNavigate ? '#FFFFFF' : colors.tertiaryText },
67+
{ color: canGoNext ? '#FFFFFF' : colors.tertiaryText },
6868
]}
6969
>
7070
@@ -89,9 +89,6 @@ const styles = StyleSheet.create({
8989
alignItems: 'center',
9090
justifyContent: 'center',
9191
},
92-
disabledButton: {
93-
opacity: 0.5,
94-
},
9592
arrowText: {
9693
fontSize: 18,
9794
fontWeight: '600',
@@ -105,4 +102,3 @@ const styles = StyleSheet.create({
105102
fontWeight: '600',
106103
},
107104
});
108-

example/src/components/PanInput.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ interface PanInputProps {
1616
min?: number;
1717
max?: number;
1818
step?: number;
19+
description?: string;
1920
onValueChange: (value: number) => void;
2021
colors: Pick<ThemeColors, 'text' | 'secondaryText' | 'blue' | 'timelineGrid' | 'inputBackground' | 'knobTrack'>;
2122
}
@@ -32,6 +33,7 @@ export default function PanInput({
3233
min = 0,
3334
max = 999,
3435
step = 0.01,
36+
description,
3537
onValueChange,
3638
colors,
3739
}: PanInputProps) {
@@ -98,6 +100,13 @@ export default function PanInput({
98100
</Text>
99101
</Text>
100102
</View>
103+
{description && (
104+
<Text
105+
style={[styles.fieldDescription, { color: colors.secondaryText }]}
106+
>
107+
{description}
108+
</Text>
109+
)}
101110
<View style={[styles.inputRow, { backgroundColor: colors.inputBackground }]}>
102111
<View style={styles.inputContainer}>
103112
<TextInput
@@ -149,6 +158,11 @@ const styles = StyleSheet.create({
149158
fontSize: 16,
150159
fontWeight: '600',
151160
},
161+
fieldDescription: {
162+
fontSize: 12,
163+
marginBottom: 8,
164+
lineHeight: 16,
165+
},
152166
inputRow: {
153167
flexDirection: 'row',
154168
alignItems: 'center',

example/src/contexts/ComposerContext.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ interface ComposerContextValue {
5151
canRedo: boolean;
5252

5353
// Event actions
54-
addEvent: (type: 'transient' | 'continuous') => void;
54+
addEvent: (type: 'transient' | 'continuous', startTime?: number) => void;
5555
updateEvent: (id: string, updates: Partial<ComposerEvent>) => void;
5656
deleteEvent: (id: string) => void;
5757
clearAllEvents: () => void;
@@ -184,13 +184,17 @@ export function ComposerProvider({ children }: { children: ReactNode }) {
184184
// Event actions
185185
// ============================================
186186

187-
const addEvent = (type: 'transient' | 'continuous') => {
187+
const addEvent = (type: 'transient' | 'continuous', startTime?: number) => {
188188
const eventsArray = getEventsArray();
189189
const duration = getCompositionDuration(eventsArray);
190+
191+
// Use provided startTime or default to end of composition
192+
const eventStartTime = startTime ?? duration;
193+
190194
const newEvent =
191195
type === 'transient'
192-
? createDefaultTransientEvent(duration)
193-
: createDefaultContinuousEvent(duration);
196+
? createDefaultTransientEvent(eventStartTime)
197+
: createDefaultContinuousEvent(eventStartTime);
194198

195199
const newEventsById = { ...eventsById, [newEvent.id]: newEvent };
196200
const newEventIds = [...eventIds, newEvent.id];

example/src/screens/Composer.tsx

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,19 @@ export function Composer() {
5555
const [showMoreModal, setShowMoreModal] = useState(false);
5656

5757
// Derive events array for components that need it
58-
const events = eventIds.map((id) => eventsById[id]).filter(Boolean) as ComposerEvent[];
59-
const selectedEvent = selectedEventId ? eventsById[selectedEventId] ?? null : null;
58+
const events = eventIds
59+
.map((id) => eventsById[id])
60+
.filter(Boolean) as ComposerEvent[];
61+
const selectedEvent = selectedEventId
62+
? eventsById[selectedEventId] ?? null
63+
: null;
64+
65+
// Navigation state
66+
const selectedIndex = selectedEventId
67+
? eventIds.indexOf(selectedEventId)
68+
: -1;
69+
const canGoPrevious = selectedIndex > 0;
70+
const canGoNext = selectedIndex >= 0 && selectedIndex < eventIds.length - 1;
6071

6172
// Time display text
6273
const timeText = useDerivedValue(() => {
@@ -127,12 +138,14 @@ export function Composer() {
127138
// Handle add new event
128139
const handleAddTransient = () => {
129140
setShowAddModal(false);
130-
addEvent('transient');
141+
const playheadTime = currentTime.get();
142+
addEvent('transient', playheadTime);
131143
};
132144

133145
const handleAddContinuous = () => {
134146
setShowAddModal(false);
135-
addEvent('continuous');
147+
const playheadTime = currentTime.get();
148+
addEvent('continuous', playheadTime);
136149
};
137150

138151
// Handle export
@@ -206,8 +219,9 @@ export function Composer() {
206219

207220
{/* Event Navigation */}
208221
<EventNavigation
209-
selectedEventId={selectedEventId}
210-
totalEvents={events.length}
222+
hasSelection={selectedEventId !== null}
223+
canGoPrevious={canGoPrevious}
224+
canGoNext={canGoNext}
211225
onPrevious={selectPreviousEvent}
212226
onNext={selectNextEvent}
213227
/>

0 commit comments

Comments
 (0)