Skip to content

Commit e8d978b

Browse files
TinyKittenclaude
andauthored
CustomModalにonShowコールバックを追加しiOSフォーカス遅延のマジックナンバーを除去 (#5575)
* フォーカス遅延をアニメーション時間(180ms)に合わせる Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * CustomModalにonShowコールバックを追加しフォーカス遅延のマジックナンバーを除去 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * onShow/onCloseAnimationEndをrefパターンに変更し不要なエフェクト再実行を防止 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent c9c326e commit e8d978b

File tree

2 files changed

+27
-11
lines changed

2 files changed

+27
-11
lines changed

src/components/CustomModal.tsx

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ type Props = {
1919
onClose?: () => void;
2020
/** 閉じるアニメーションが完了した後に呼ばれるコールバック */
2121
onCloseAnimationEnd?: () => void;
22+
/** 開くアニメーションが完了した後に呼ばれるコールバック */
23+
onShow?: () => void;
2224
dismissOnBackdropPress?: boolean;
2325
backdropStyle?: StyleProp<ViewStyle>;
2426
containerStyle?: StyleProp<ViewStyle>;
@@ -39,6 +41,7 @@ export const CustomModal: React.FC<Props> = ({
3941
children,
4042
onClose,
4143
onCloseAnimationEnd,
44+
onShow,
4245
dismissOnBackdropPress = true,
4346
backdropStyle,
4447
containerStyle,
@@ -49,6 +52,8 @@ export const CustomModal: React.FC<Props> = ({
4952
}) => {
5053
const [isMounted, setIsMounted] = useState(visible);
5154
const opacity = useRef(new Animated.Value(visible ? 1 : 0)).current;
55+
const onShowRef = useRef(onShow);
56+
const onCloseAnimationEndRef = useRef(onCloseAnimationEnd);
5257
const isLEDTheme = useAtomValue(isLEDThemeAtom);
5358
const animatedBackdropStyle = {
5459
opacity,
@@ -65,14 +70,26 @@ export const CustomModal: React.FC<Props> = ({
6570
],
6671
};
6772

73+
useEffect(() => {
74+
onShowRef.current = onShow;
75+
}, [onShow]);
76+
77+
useEffect(() => {
78+
onCloseAnimationEndRef.current = onCloseAnimationEnd;
79+
}, [onCloseAnimationEnd]);
80+
6881
useEffect(() => {
6982
if (visible) {
7083
setIsMounted(true);
7184
Animated.timing(opacity, {
7285
toValue: 1,
7386
duration: animationDuration,
7487
useNativeDriver: true,
75-
}).start();
88+
}).start(({ finished }) => {
89+
if (finished) {
90+
onShowRef.current?.();
91+
}
92+
});
7693
return;
7794
}
7895

@@ -83,10 +100,10 @@ export const CustomModal: React.FC<Props> = ({
83100
}).start(({ finished }) => {
84101
if (finished && !visible) {
85102
setIsMounted(false);
86-
onCloseAnimationEnd?.();
103+
onCloseAnimationEndRef.current?.();
87104
}
88105
});
89-
}, [animationDuration, opacity, visible, onCloseAnimationEnd]);
106+
}, [animationDuration, opacity, visible]);
90107

91108
const handleBackdropPress = () => {
92109
Keyboard.dismiss();

src/components/SavePresetNameModal.tsx

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -109,14 +109,6 @@ export const SavePresetNameModal: React.FC<Props> = ({
109109
);
110110
inboundOpacity.setValue(1);
111111
outboundOpacity.setValue(1);
112-
113-
// モーダルアニメーション(180ms)とKeyboardAvoidingViewのレイアウト確定を待ってからフォーカスする
114-
if (Platform.OS === 'ios') {
115-
const timer = setTimeout(() => {
116-
textInputRef.current?.focus();
117-
}, 300);
118-
return () => clearTimeout(timer);
119-
}
120112
}
121113
}, [visible, defaultName, directionOptions, inboundOpacity, outboundOpacity]);
122114

@@ -163,6 +155,12 @@ export const SavePresetNameModal: React.FC<Props> = ({
163155
onSubmit(name, selectedDirection);
164156
}, [onSubmit, selectedDirection, hasDirectionOptions]);
165157

158+
const handleShow = useCallback(() => {
159+
if (Platform.OS === 'ios') {
160+
textInputRef.current?.focus();
161+
}
162+
}, []);
163+
166164
const canSubmit =
167165
!isEmpty && (!hasDirectionOptions || selectedDirection !== null);
168166
const textColor = isLEDTheme ? '#fff' : '#000';
@@ -171,6 +169,7 @@ export const SavePresetNameModal: React.FC<Props> = ({
171169
<CustomModal
172170
visible={visible}
173171
onClose={onClose}
172+
onShow={handleShow}
174173
backdropStyle={{ backgroundColor: 'rgba(0,0,0,0.5)' }}
175174
contentContainerStyle={[
176175
styles.contentView,

0 commit comments

Comments
 (0)