parent
537a1b960d
commit
48d4d59ac8
3
App.tsx
3
App.tsx
|
@ -14,7 +14,7 @@ import {
|
|||
} from 'react-native-paper';
|
||||
import {SQLiteDatabase} from 'react-native-sqlite-storage';
|
||||
import Ionicon from 'react-native-vector-icons/Ionicons';
|
||||
import {createPlans, createSets, createSettings, getDb} from './db';
|
||||
import {addSound, createPlans, createSets, createSettings, getDb} from './db';
|
||||
import Routes from './Routes';
|
||||
|
||||
export const Drawer = createDrawerNavigator<DrawerParamList>();
|
||||
|
@ -58,6 +58,7 @@ const App = () => {
|
|||
await _db.executeSql(createPlans);
|
||||
await _db.executeSql(createSets);
|
||||
await _db.executeSql(createSettings);
|
||||
await _db.executeSql(addSound).catch(() => null);
|
||||
setDb(_db);
|
||||
const [result] = await _db.executeSql(`SELECT * FROM settings LIMIT 1`);
|
||||
if (result.rows.length === 0)
|
||||
|
|
|
@ -36,7 +36,11 @@ export default function EditSet() {
|
|||
const settings: Settings = result.rows.item(0);
|
||||
if (!settings.alarm) return;
|
||||
const milliseconds = settings.minutes * 60 * 1000 + settings.seconds * 1000;
|
||||
NativeModules.AlarmModule.timer(milliseconds, !!settings.vibrate);
|
||||
NativeModules.AlarmModule.timer(
|
||||
milliseconds,
|
||||
!!settings.vibrate,
|
||||
settings.sound,
|
||||
);
|
||||
}, [db]);
|
||||
|
||||
const update = useCallback(
|
||||
|
|
|
@ -6,11 +6,12 @@ import React, {
|
|||
useState,
|
||||
} from 'react';
|
||||
import {NativeModules, StyleSheet, Text, View} from 'react-native';
|
||||
import {Searchbar, TextInput} from 'react-native-paper';
|
||||
import {Button, Searchbar, TextInput} from 'react-native-paper';
|
||||
import {DatabaseContext, SnackbarContext} from './App';
|
||||
import ConfirmDialog from './ConfirmDialog';
|
||||
import MassiveSwitch from './MassiveSwitch';
|
||||
import Settings from './settings';
|
||||
import DocumentPicker from 'react-native-document-picker';
|
||||
|
||||
export default function SettingsPage() {
|
||||
const [vibrate, setVibrate] = useState(true);
|
||||
|
@ -19,6 +20,7 @@ export default function SettingsPage() {
|
|||
const [seconds, setSeconds] = useState<string>('');
|
||||
const [alarm, setAlarm] = useState<boolean>(false);
|
||||
const [predictive, setPredictive] = useState<boolean>(false);
|
||||
const [sound, setSound] = useState<string>('');
|
||||
const [battery, setBattery] = useState(false);
|
||||
const [ignoring, setIgnoring] = useState(false);
|
||||
const [search, setSearch] = useState('');
|
||||
|
@ -35,6 +37,7 @@ export default function SettingsPage() {
|
|||
setPredictive(!!settings.predict);
|
||||
setMaxSets(settings.sets.toString());
|
||||
setVibrate(!!settings.vibrate);
|
||||
setSound(settings.sound);
|
||||
NativeModules.AlarmModule.ignoringBattery(setIgnoring);
|
||||
}, [db]);
|
||||
|
||||
|
@ -44,10 +47,10 @@ export default function SettingsPage() {
|
|||
|
||||
useEffect(() => {
|
||||
db.executeSql(
|
||||
`UPDATE settings SET vibrate=?,minutes=?,sets=?,seconds=?,alarm=?,predict=?`,
|
||||
[vibrate, minutes, maxSets, seconds, alarm, predictive],
|
||||
`UPDATE settings SET vibrate=?,minutes=?,sets=?,seconds=?,alarm=?,predict=?,sound=?`,
|
||||
[vibrate, minutes, maxSets, seconds, alarm, predictive, sound],
|
||||
);
|
||||
}, [vibrate, minutes, maxSets, seconds, alarm, predictive, db]);
|
||||
}, [vibrate, minutes, maxSets, seconds, alarm, predictive, sound, db]);
|
||||
|
||||
const changeAlarmEnabled = useCallback(
|
||||
(enabled: boolean) => {
|
||||
|
@ -72,6 +75,14 @@ export default function SettingsPage() {
|
|||
[setVibrate],
|
||||
);
|
||||
|
||||
const changeSound = useCallback(async () => {
|
||||
const {fileCopyUri} = await DocumentPicker.pickSingle({
|
||||
type: 'audio/*',
|
||||
copyTo: 'documentDirectory',
|
||||
});
|
||||
if (fileCopyUri) setSound(fileCopyUri);
|
||||
}, []);
|
||||
|
||||
const items: {name: string; element: ReactNode}[] = [
|
||||
{
|
||||
name: 'Sets per workout',
|
||||
|
@ -162,6 +173,15 @@ export default function SettingsPage() {
|
|||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
name: 'Alarm sound',
|
||||
element: (
|
||||
<Button onPress={changeSound}>
|
||||
Alarm sound
|
||||
{sound ? ': ' + sound.split('/')[sound.split('/').length - 1] : null}
|
||||
</Button>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
|
|
|
@ -23,11 +23,12 @@ class AlarmModule internal constructor(context: ReactApplicationContext?) :
|
|||
|
||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||
@ReactMethod
|
||||
fun timer(milliseconds: Int, vibrate: Boolean) {
|
||||
fun timer(milliseconds: Int, vibrate: Boolean, sound: String?) {
|
||||
Log.d("AlarmModule", "Queue alarm for $milliseconds delay")
|
||||
val intent = Intent(reactApplicationContext, TimerService::class.java)
|
||||
intent.putExtra("milliseconds", milliseconds)
|
||||
intent.putExtra("vibrate", vibrate)
|
||||
intent.putExtra("sound", sound)
|
||||
reactApplicationContext.startService(intent)
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import android.os.Vibrator
|
|||
import androidx.annotation.RequiresApi
|
||||
import android.content.Intent
|
||||
import android.media.AudioAttributes
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.VibrationEffect
|
||||
import android.os.IBinder
|
||||
|
@ -21,9 +22,25 @@ class AlarmService : Service(), OnPreparedListener {
|
|||
onDestroy()
|
||||
return START_STICKY
|
||||
}
|
||||
mediaPlayer = MediaPlayer.create(applicationContext, R.raw.argon)
|
||||
mediaPlayer?.start()
|
||||
mediaPlayer?.setOnCompletionListener { vibrator?.cancel() }
|
||||
val sound = intent.extras?.getString("sound")
|
||||
if (sound == null) {
|
||||
mediaPlayer = MediaPlayer.create(applicationContext, R.raw.argon)
|
||||
mediaPlayer?.start()
|
||||
mediaPlayer?.setOnCompletionListener { vibrator?.cancel() }
|
||||
} else {
|
||||
mediaPlayer = MediaPlayer().apply {
|
||||
setAudioAttributes(
|
||||
AudioAttributes.Builder()
|
||||
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
|
||||
.setUsage(AudioAttributes.USAGE_MEDIA)
|
||||
.build()
|
||||
)
|
||||
setDataSource(applicationContext, Uri.parse(sound))
|
||||
prepare()
|
||||
start()
|
||||
setOnCompletionListener { vibrator?.cancel() }
|
||||
}
|
||||
}
|
||||
val pattern = longArrayOf(0, 300, 1300, 300, 1300, 300)
|
||||
vibrator = applicationContext.getSystemService(VIBRATOR_SERVICE) as Vibrator
|
||||
val audioAttributes = AudioAttributes.Builder()
|
||||
|
|
|
@ -19,12 +19,14 @@ class TimerService : Service() {
|
|||
private var currentMs: Long? = null
|
||||
private var countdownTimer: CountDownTimer? = null
|
||||
private var vibrate: Boolean = true
|
||||
private var sound: String? = null
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
Log.d("TimerService", "Started timer service.")
|
||||
Log.d("TimerService", "endMs=$endMs,currentMs=$currentMs")
|
||||
vibrate = intent!!.extras!!.getBoolean("vibrate")
|
||||
sound = intent.extras?.getString("sound")
|
||||
if (intent.action == "add") {
|
||||
manager?.cancel(NOTIFICATION_ID_DONE)
|
||||
endMs = currentMs!!.toInt().plus(60000)
|
||||
|
@ -80,6 +82,7 @@ class TimerService : Service() {
|
|||
manager?.cancel(NOTIFICATION_ID_PENDING)
|
||||
val alarmIntent = Intent(applicationContext, AlarmService::class.java)
|
||||
alarmIntent.putExtra("vibrate", vibrate)
|
||||
alarmIntent.putExtra("sound", sound)
|
||||
applicationContext.startService(alarmIntent)
|
||||
}
|
||||
}
|
||||
|
|
4
db.ts
4
db.ts
|
@ -32,3 +32,7 @@ export const createSettings = `
|
|||
sets INTEGER NOT NULL DEFAULT 3
|
||||
);
|
||||
`;
|
||||
|
||||
export const addSound = `
|
||||
ALTER TABLE settings ADD COLUMN sound TEXT NULL;
|
||||
`;
|
||||
|
|
|
@ -5,4 +5,5 @@ export default interface Settings {
|
|||
vibrate: number;
|
||||
predict: number;
|
||||
sets: number;
|
||||
sound: string;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user