Add vibration setting for timers
This commit is contained in:
parent
16ba002387
commit
4c185f0346
2
App.tsx
2
App.tsx
|
@ -62,6 +62,8 @@ const App = () => {
|
||||||
if (seconds === null) await setItem('seconds', '30');
|
if (seconds === null) await setItem('seconds', '30');
|
||||||
const alarmEnabled = await getItem('alarmEnabled');
|
const alarmEnabled = await getItem('alarmEnabled');
|
||||||
if (alarmEnabled === null) await setItem('alarmEnabled', 'false');
|
if (alarmEnabled === null) await setItem('alarmEnabled', 'false');
|
||||||
|
const vibrate = await getItem('vibrate');
|
||||||
|
if (vibrate === null) await setItem('vibrate', 'true');
|
||||||
if (!(await getItem('predictiveSets')))
|
if (!(await getItem('predictiveSets')))
|
||||||
await setItem('predictiveSets', 'true');
|
await setItem('predictiveSets', 'true');
|
||||||
if (!(await getItem('maxSets'))) await setItem('maxSets', '3');
|
if (!(await getItem('maxSets'))) await setItem('maxSets', '3');
|
||||||
|
|
|
@ -29,13 +29,14 @@ export default function EditSet() {
|
||||||
}, [navigation]),
|
}, [navigation]),
|
||||||
);
|
);
|
||||||
|
|
||||||
const notify = useCallback(async () => {
|
const startTimer = useCallback(async () => {
|
||||||
const enabled = await AsyncStorage.getItem('alarmEnabled');
|
const enabled = await AsyncStorage.getItem('alarmEnabled');
|
||||||
if (enabled !== 'true') return;
|
if (enabled !== 'true') return;
|
||||||
const minutes = await AsyncStorage.getItem('minutes');
|
const minutes = await AsyncStorage.getItem('minutes');
|
||||||
const seconds = await AsyncStorage.getItem('seconds');
|
const seconds = await AsyncStorage.getItem('seconds');
|
||||||
const milliseconds = Number(minutes) * 60 * 1000 + Number(seconds) * 1000;
|
const milliseconds = Number(minutes) * 60 * 1000 + Number(seconds) * 1000;
|
||||||
NativeModules.AlarmModule.timer(milliseconds);
|
const vibrate = (await AsyncStorage.getItem('vibrate')) === 'true';
|
||||||
|
NativeModules.AlarmModule.timer(milliseconds, vibrate);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const update = useCallback(
|
const update = useCallback(
|
||||||
|
@ -57,11 +58,11 @@ export default function EditSet() {
|
||||||
INSERT INTO sets(name, reps, weight, created, unit)
|
INSERT INTO sets(name, reps, weight, created, unit)
|
||||||
VALUES (?,?,?,strftime('%Y-%m-%dT%H:%M:%S', 'now', 'localtime'),?)
|
VALUES (?,?,?,strftime('%Y-%m-%dT%H:%M:%S', 'now', 'localtime'),?)
|
||||||
`;
|
`;
|
||||||
|
startTimer();
|
||||||
await db.executeSql(insert, [name, reps, weight, unit]);
|
await db.executeSql(insert, [name, reps, weight, unit]);
|
||||||
notify();
|
|
||||||
navigation.goBack();
|
navigation.goBack();
|
||||||
},
|
},
|
||||||
[db, navigation, notify],
|
[db, navigation, startTimer],
|
||||||
);
|
);
|
||||||
|
|
||||||
const save = useCallback(
|
const save = useCallback(
|
||||||
|
|
|
@ -121,7 +121,7 @@ export default function SetList() {
|
||||||
todaysWorkouts[todaysWorkouts.indexOf(todaysSets[0].name!) + 1];
|
todaysWorkouts[todaysWorkouts.indexOf(todaysSets[0].name!) + 1];
|
||||||
}
|
}
|
||||||
const best = await getBest(nextWorkout);
|
const best = await getBest(nextWorkout);
|
||||||
setNextSet({...best, created: new Date().toISOString()});
|
setNextSet({...best});
|
||||||
}, [getTodaysSets, getTodaysPlan, getBest]);
|
}, [getTodaysSets, getTodaysPlan, getBest]);
|
||||||
|
|
||||||
useFocusEffect(
|
useFocusEffect(
|
||||||
|
@ -171,7 +171,6 @@ export default function SetList() {
|
||||||
reps: 0,
|
reps: 0,
|
||||||
weight: 0,
|
weight: 0,
|
||||||
unit: 'kg',
|
unit: 'kg',
|
||||||
created: new Date().toISOString(),
|
|
||||||
};
|
};
|
||||||
navigation.navigate('EditSet', {set: nextSet || set});
|
navigation.navigate('EditSet', {set: nextSet || set});
|
||||||
}, [navigation, nextSet]);
|
}, [navigation, nextSet]);
|
||||||
|
|
|
@ -14,19 +14,20 @@ import MassiveSwitch from './MassiveSwitch';
|
||||||
const {getItem, setItem} = AsyncStorage;
|
const {getItem, setItem} = AsyncStorage;
|
||||||
|
|
||||||
export default function SettingsPage() {
|
export default function SettingsPage() {
|
||||||
|
const [vibrate, setVibrate] = useState(true);
|
||||||
const [minutes, setMinutes] = useState<string>('');
|
const [minutes, setMinutes] = useState<string>('');
|
||||||
const [maxSets, setMaxSets] = useState<string>('3');
|
const [maxSets, setMaxSets] = useState<string>('3');
|
||||||
const [seconds, setSeconds] = useState<string>('');
|
const [seconds, setSeconds] = useState<string>('');
|
||||||
const [alarmEnabled, setAlarmEnabled] = useState<boolean>(false);
|
const [alarm, setAlarm] = useState<boolean>(false);
|
||||||
const [predictiveSets, setPredictiveSets] = useState<boolean>(false);
|
const [predictive, setPredictive] = useState<boolean>(false);
|
||||||
const [showBattery, setShowBattery] = useState(false);
|
const [battery, setBattery] = useState(false);
|
||||||
const [ignoring, setIgnoring] = useState(false);
|
const [ignoring, setIgnoring] = useState(false);
|
||||||
|
|
||||||
const refresh = useCallback(async () => {
|
const refresh = useCallback(async () => {
|
||||||
setMinutes((await getItem('minutes')) || '');
|
setMinutes((await getItem('minutes')) || '');
|
||||||
setSeconds((await getItem('seconds')) || '');
|
setSeconds((await getItem('seconds')) || '');
|
||||||
setAlarmEnabled((await getItem('alarmEnabled')) === 'true');
|
setAlarm((await getItem('alarmEnabled')) === 'true');
|
||||||
setPredictiveSets((await getItem('predictiveSets')) === 'true');
|
setPredictive((await getItem('predictiveSets')) === 'true');
|
||||||
setMaxSets((await getItem('maxSets')) || '');
|
setMaxSets((await getItem('maxSets')) || '');
|
||||||
NativeModules.AlarmModule.ignoringBattery(setIgnoring);
|
NativeModules.AlarmModule.ignoringBattery(setIgnoring);
|
||||||
}, []);
|
}, []);
|
||||||
|
@ -37,27 +38,27 @@ export default function SettingsPage() {
|
||||||
|
|
||||||
const changeAlarmEnabled = useCallback(
|
const changeAlarmEnabled = useCallback(
|
||||||
(enabled: boolean) => {
|
(enabled: boolean) => {
|
||||||
setAlarmEnabled(enabled);
|
setAlarm(enabled);
|
||||||
if (enabled && !ignoring) setShowBattery(true);
|
if (enabled && !ignoring) setBattery(true);
|
||||||
setItem('alarmEnabled', enabled ? 'true' : 'false');
|
setItem('alarmEnabled', enabled ? 'true' : 'false');
|
||||||
},
|
},
|
||||||
[setShowBattery, ignoring],
|
[setBattery, ignoring],
|
||||||
);
|
);
|
||||||
|
|
||||||
const changePredictive = useCallback(
|
const changePredictive = useCallback(
|
||||||
(enabled: boolean) => {
|
(enabled: boolean) => {
|
||||||
setPredictiveSets(enabled);
|
setPredictive(enabled);
|
||||||
setItem('predictiveSets', enabled ? 'true' : 'false');
|
setItem('predictiveSets', enabled ? 'true' : 'false');
|
||||||
ToastAndroid.show(
|
ToastAndroid.show(
|
||||||
'Predictive sets guess whats next based on todays plan.',
|
'Predictive sets guess whats next based on todays plan.',
|
||||||
ToastAndroid.LONG,
|
ToastAndroid.LONG,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
[setPredictiveSets],
|
[setPredictive],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
const textInputs = (
|
||||||
<View style={styles.container}>
|
<>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Rest minutes"
|
label="Rest minutes"
|
||||||
value={minutes}
|
value={minutes}
|
||||||
|
@ -68,8 +69,8 @@ export default function SettingsPage() {
|
||||||
setItem('minutes', text);
|
setItem('minutes', text);
|
||||||
}}
|
}}
|
||||||
style={styles.text}
|
style={styles.text}
|
||||||
|
selectTextOnFocus
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Rest seconds"
|
label="Rest seconds"
|
||||||
value={seconds}
|
value={seconds}
|
||||||
|
@ -80,8 +81,8 @@ export default function SettingsPage() {
|
||||||
setItem('seconds', s);
|
setItem('seconds', s);
|
||||||
}}
|
}}
|
||||||
style={styles.text}
|
style={styles.text}
|
||||||
|
selectTextOnFocus
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Sets per workout"
|
label="Sets per workout"
|
||||||
value={maxSets}
|
value={maxSets}
|
||||||
|
@ -91,30 +92,48 @@ export default function SettingsPage() {
|
||||||
setItem('maxSets', value);
|
setItem('maxSets', value);
|
||||||
}}
|
}}
|
||||||
style={styles.text}
|
style={styles.text}
|
||||||
|
selectTextOnFocus
|
||||||
/>
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
const changeVibrate = useCallback(
|
||||||
|
(value: boolean) => {
|
||||||
|
setVibrate(value);
|
||||||
|
setItem('vibrate', value ? 'true' : 'false');
|
||||||
|
},
|
||||||
|
[setVibrate],
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
{textInputs}
|
||||||
<Text style={styles.text}>Rest timers</Text>
|
<Text style={styles.text}>Rest timers</Text>
|
||||||
<MassiveSwitch
|
<MassiveSwitch
|
||||||
style={[styles.text, {alignSelf: 'flex-start'}]}
|
style={[styles.text, {alignSelf: 'flex-start'}]}
|
||||||
value={alarmEnabled}
|
value={alarm}
|
||||||
onValueChange={changeAlarmEnabled}
|
onValueChange={changeAlarmEnabled}
|
||||||
/>
|
/>
|
||||||
|
<Text style={styles.text}>Vibrate</Text>
|
||||||
|
<MassiveSwitch
|
||||||
|
style={[styles.text, {alignSelf: 'flex-start'}]}
|
||||||
|
value={vibrate}
|
||||||
|
onValueChange={changeVibrate}
|
||||||
|
/>
|
||||||
<ConfirmDialog
|
<ConfirmDialog
|
||||||
title="Battery optimizations"
|
title="Battery optimizations"
|
||||||
show={showBattery}
|
show={battery}
|
||||||
setShow={setShowBattery}
|
setShow={setBattery}
|
||||||
onOk={() => {
|
onOk={() => {
|
||||||
NativeModules.AlarmModule.openSettings();
|
NativeModules.AlarmModule.openSettings();
|
||||||
setShowBattery(false);
|
setBattery(false);
|
||||||
}}>
|
}}>
|
||||||
Disable battery optimizations for Massive to use rest timers.
|
Disable battery optimizations for Massive to use rest timers.
|
||||||
</ConfirmDialog>
|
</ConfirmDialog>
|
||||||
|
|
||||||
<Text style={styles.text}>Predictive sets</Text>
|
<Text style={styles.text}>Predictive sets</Text>
|
||||||
<MassiveSwitch
|
<MassiveSwitch
|
||||||
style={[styles.text, {alignSelf: 'flex-start'}]}
|
style={[styles.text, {alignSelf: 'flex-start'}]}
|
||||||
value={predictiveSets}
|
value={predictive}
|
||||||
onValueChange={changePredictive}
|
onValueChange={changePredictive}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
|
@ -83,7 +83,7 @@ export default function ViewBest() {
|
||||||
<XAxis
|
<XAxis
|
||||||
style={{marginHorizontal: -10, height: xAxisHeight}}
|
style={{marginHorizontal: -10, height: xAxisHeight}}
|
||||||
data={sets}
|
data={sets}
|
||||||
formatLabel={(_value, index) => formatMonth(sets[index].created)}
|
formatLabel={(_value, index) => formatMonth(sets[index].created!)}
|
||||||
contentInset={{left: 10, right: 10}}
|
contentInset={{left: 10, right: 10}}
|
||||||
svg={axesSvg}
|
svg={axesSvg}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -23,10 +23,11 @@ class AlarmModule internal constructor(context: ReactApplicationContext?) :
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||||
@ReactMethod
|
@ReactMethod
|
||||||
fun timer(milliseconds: Int) {
|
fun timer(milliseconds: Int, vibrate: Boolean) {
|
||||||
Log.d("AlarmModule", "Queue alarm for $milliseconds delay")
|
Log.d("AlarmModule", "Queue alarm for $milliseconds delay")
|
||||||
val intent = Intent(reactApplicationContext, TimerService::class.java)
|
val intent = Intent(reactApplicationContext, TimerService::class.java)
|
||||||
intent.putExtra("milliseconds", milliseconds)
|
intent.putExtra("milliseconds", milliseconds)
|
||||||
|
intent.putExtra("vibrate", vibrate)
|
||||||
reactApplicationContext.startService(intent)
|
reactApplicationContext.startService(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,9 @@ class AlarmService : Service(), OnPreparedListener {
|
||||||
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
|
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
|
||||||
.setUsage(AudioAttributes.USAGE_ALARM)
|
.setUsage(AudioAttributes.USAGE_ALARM)
|
||||||
.build()
|
.build()
|
||||||
vibrator!!.vibrate(VibrationEffect.createWaveform(pattern, 1), audioAttributes)
|
val vibrate = intent.extras!!.getBoolean("vibrate")
|
||||||
|
if (vibrate)
|
||||||
|
vibrator!!.vibrate(VibrationEffect.createWaveform(pattern, 1), audioAttributes)
|
||||||
return START_STICKY
|
return START_STICKY
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,17 +19,19 @@ class TimerService : Service() {
|
||||||
private var endMs: Int? = null
|
private var endMs: Int? = null
|
||||||
private var currentMs: Long? = null
|
private var currentMs: Long? = null
|
||||||
private var countdownTimer: CountDownTimer? = null
|
private var countdownTimer: CountDownTimer? = null
|
||||||
|
private var vibrate: Boolean = true
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.O)
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
Log.d("TimerService", "Started timer service.")
|
Log.d("TimerService", "Started timer service.")
|
||||||
Log.d("TimerService", "endMs=$endMs,currentMs=$currentMs")
|
Log.d("TimerService", "endMs=$endMs,currentMs=$currentMs")
|
||||||
if (intent?.action == "add") {
|
vibrate = intent!!.extras!!.getBoolean("vibrate")
|
||||||
|
if (intent.action == "add") {
|
||||||
endMs = currentMs!!.toInt().plus(60000)
|
endMs = currentMs!!.toInt().plus(60000)
|
||||||
applicationContext.stopService(Intent(applicationContext, AlarmService::class.java))
|
applicationContext.stopService(Intent(applicationContext, AlarmService::class.java))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
endMs = intent!!.extras!!.getInt("milliseconds")
|
endMs = intent.extras!!.getInt("milliseconds")
|
||||||
}
|
}
|
||||||
Log.d("TimerService", "endMs=$endMs,currentMs=$currentMs")
|
Log.d("TimerService", "endMs=$endMs,currentMs=$currentMs")
|
||||||
notificationManager = getManager(applicationContext)
|
notificationManager = getManager(applicationContext)
|
||||||
|
@ -68,7 +70,9 @@ class TimerService : Service() {
|
||||||
.setCategory(NotificationCompat.CATEGORY_ALARM)
|
.setCategory(NotificationCompat.CATEGORY_ALARM)
|
||||||
.priority = NotificationCompat.PRIORITY_HIGH
|
.priority = NotificationCompat.PRIORITY_HIGH
|
||||||
notificationManager.notify(NOTIFICATION_ID, builder.build())
|
notificationManager.notify(NOTIFICATION_ID, builder.build())
|
||||||
applicationContext.startService(Intent(applicationContext, AlarmService::class.java))
|
val alarmIntent = Intent(applicationContext, AlarmService::class.java)
|
||||||
|
alarmIntent.putExtra("vibrate", vibrate)
|
||||||
|
applicationContext.startService(alarmIntent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user