Insole-production time tracker exported from the Create/Anything AI platform. Baseline snapshot before any reverse-engineering or cleanup. - apps/mobile: Expo Router app (iOS/Android/web), the only workspace - publisher/: standalone OpenNext/AWS deploy tooling for the web side - Backend (/api/tasks, /api/logs + DB) lives remotely, not in this repo
62 lines
1.4 KiB
TypeScript
62 lines
1.4 KiB
TypeScript
export enum NotificationFeedbackType {
|
|
Success = 'success',
|
|
Warning = 'warning',
|
|
Error = 'error',
|
|
}
|
|
|
|
export enum ImpactFeedbackStyle {
|
|
Light = 'light',
|
|
Medium = 'medium',
|
|
Heavy = 'heavy',
|
|
Soft = 'soft',
|
|
Rigid = 'rigid',
|
|
}
|
|
|
|
const vibrationPatterns: Record<
|
|
NotificationFeedbackType | ImpactFeedbackStyle | 'selection',
|
|
VibratePattern
|
|
> = {
|
|
[NotificationFeedbackType.Success]: [40, 100, 40],
|
|
[NotificationFeedbackType.Warning]: [50, 100, 50],
|
|
[NotificationFeedbackType.Error]: [60, 100, 60, 100, 60],
|
|
[ImpactFeedbackStyle.Light]: [40],
|
|
[ImpactFeedbackStyle.Medium]: [50],
|
|
[ImpactFeedbackStyle.Heavy]: [60],
|
|
[ImpactFeedbackStyle.Soft]: [35],
|
|
[ImpactFeedbackStyle.Rigid]: [45],
|
|
selection: [50],
|
|
};
|
|
|
|
function isVibrationAvailable(): boolean {
|
|
return (
|
|
typeof window !== 'undefined' &&
|
|
'navigator' in window &&
|
|
'vibrate' in navigator
|
|
);
|
|
}
|
|
|
|
export const selectionAsync = async (): Promise<void> => {
|
|
if (!isVibrationAvailable()) {
|
|
return;
|
|
}
|
|
navigator.vibrate(vibrationPatterns.selection);
|
|
};
|
|
|
|
export const notificationAsync = async (
|
|
type: NotificationFeedbackType = NotificationFeedbackType.Success
|
|
): Promise<void> => {
|
|
if (!isVibrationAvailable()) {
|
|
return;
|
|
}
|
|
navigator.vibrate(vibrationPatterns[type]);
|
|
};
|
|
|
|
export const impactAsync = async (
|
|
style: ImpactFeedbackStyle = ImpactFeedbackStyle.Medium
|
|
): Promise<void> => {
|
|
if (!isVibrationAvailable()) {
|
|
return;
|
|
}
|
|
navigator.vibrate(vibrationPatterns[style]);
|
|
};
|