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