Merge branch 'master' into alarm-module
This commit is contained in:
commit
8504f8b811
|
@ -28,6 +28,7 @@ export default function EditSet() {
|
||||||
milliseconds,
|
milliseconds,
|
||||||
!!settings.vibrate,
|
!!settings.vibrate,
|
||||||
settings.sound,
|
settings.sound,
|
||||||
|
!!settings.noSound,
|
||||||
);
|
);
|
||||||
const nextAlarm = new Date();
|
const nextAlarm = new Date();
|
||||||
nextAlarm.setTime(nextAlarm.getTime() + milliseconds);
|
nextAlarm.setTime(nextAlarm.getTime() + milliseconds);
|
||||||
|
|
|
@ -5,6 +5,7 @@ import {Divider, List, Menu, Text} from 'react-native-paper';
|
||||||
import {HomePageParams} from './home-page-params';
|
import {HomePageParams} from './home-page-params';
|
||||||
import Set from './set';
|
import Set from './set';
|
||||||
import {deleteSet} from './set.service';
|
import {deleteSet} from './set.service';
|
||||||
|
import {format} from './time';
|
||||||
import useDark from './use-dark';
|
import useDark from './use-dark';
|
||||||
import {useSettings} from './use-settings';
|
import {useSettings} from './use-settings';
|
||||||
|
|
||||||
|
@ -63,7 +64,7 @@ export default function SetItem({
|
||||||
alignSelf: 'center',
|
alignSelf: 'center',
|
||||||
color: dark ? '#909090ff' : '#717171ff',
|
color: dark ? '#909090ff' : '#717171ff',
|
||||||
}}>
|
}}>
|
||||||
{item.created?.replace('T', ' ')}
|
{format(item.created || '', settings.date)}
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
<Menu
|
<Menu
|
||||||
|
|
|
@ -33,6 +33,7 @@ export default function SettingsPage() {
|
||||||
showSets,
|
showSets,
|
||||||
theme,
|
theme,
|
||||||
alarm,
|
alarm,
|
||||||
|
noSound,
|
||||||
} = settings;
|
} = settings;
|
||||||
const {color, setColor} = useColor();
|
const {color, setColor} = useColor();
|
||||||
const {toast} = useSnackbar();
|
const {toast} = useSnackbar();
|
||||||
|
@ -139,9 +140,19 @@ export default function SettingsPage() {
|
||||||
[toast, update],
|
[toast, update],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const changeNoSound = useCallback(
|
||||||
|
(enabled: boolean) => {
|
||||||
|
update(enabled, 'noSound');
|
||||||
|
if (enabled) toast('Disable sound on rest timer alarms.', 4000);
|
||||||
|
else toast('Enabled sound for rest timer alarms.', 4000);
|
||||||
|
},
|
||||||
|
[toast, update],
|
||||||
|
);
|
||||||
|
|
||||||
const switches: Input<boolean>[] = [
|
const switches: Input<boolean>[] = [
|
||||||
{name: 'Rest timers', value: !!alarm, onChange: changeAlarmEnabled},
|
{name: 'Rest timers', value: !!alarm, onChange: changeAlarmEnabled},
|
||||||
{name: 'Vibrate', value: !!vibrate, onChange: changeVibrate},
|
{name: 'Vibrate', value: !!vibrate, onChange: changeVibrate},
|
||||||
|
{name: 'Disable sound', value: !!noSound, onChange: changeNoSound},
|
||||||
{name: 'Record notifications', value: !!notify, onChange: changeNotify},
|
{name: 'Record notifications', value: !!notify, onChange: changeNotify},
|
||||||
{name: 'Show images', value: !!images, onChange: changeImages},
|
{name: 'Show images', value: !!images, onChange: changeImages},
|
||||||
{name: 'Show unit', value: !!showUnit, onChange: changeUnit},
|
{name: 'Show unit', value: !!showUnit, onChange: changeUnit},
|
||||||
|
@ -217,16 +228,18 @@ export default function SettingsPage() {
|
||||||
dropdownIconColor={color}
|
dropdownIconColor={color}
|
||||||
selectedValue={settings.date}
|
selectedValue={settings.date}
|
||||||
onValueChange={changeDate}>
|
onValueChange={changeDate}>
|
||||||
|
<Picker.Item value="%Y-%m-%d %H:%M" label="1990-12-24 15:05" />
|
||||||
|
<Picker.Item value="%Y-%m-%d" label="1990-12-24" />
|
||||||
|
<Picker.Item value="%d/%m" label="24/12 (dd/MM)" />
|
||||||
|
<Picker.Item value="%H:%M" label="15:05 (24-hour time)" />
|
||||||
|
<Picker.Item value="%h:%M %p" label="3:05 PM (12-hour time)" />
|
||||||
|
<Picker.Item value="%d/%m/%y" label="24/12/1996" />
|
||||||
|
<Picker.Item value="%A %h:%M %p" label="Monday 3:05 PM" />
|
||||||
<Picker.Item
|
<Picker.Item
|
||||||
value="%Y-%m-%d %H:%M"
|
value="%d/%m/%y %h:%M %p"
|
||||||
label="Format date as 1990-12-24 15:05"
|
label="24/12/1990 3:05 PM"
|
||||||
/>
|
/>
|
||||||
<Picker.Item
|
<Picker.Item value="%d/%m %h:%M %p" label="24/12 3:05 PM" />
|
||||||
value="%Y-%m-%d"
|
|
||||||
label="Format date as 1990-12-24 (YYYY-MM-dd)"
|
|
||||||
/>
|
|
||||||
<Picker.Item value="%d/%m" label="Format date as 24/12 (dd/MM)" />
|
|
||||||
<Picker.Item value="%H:%M" label="Format date as 15:05 (HH:MM)" />
|
|
||||||
</Picker>
|
</Picker>
|
||||||
)}
|
)}
|
||||||
{'alarm sound'.includes(search.toLowerCase()) && (
|
{'alarm sound'.includes(search.toLowerCase()) && (
|
||||||
|
|
|
@ -11,7 +11,7 @@ import MassiveInput from './MassiveInput';
|
||||||
import {useSnackbar} from './MassiveSnack';
|
import {useSnackbar} from './MassiveSnack';
|
||||||
import {PlanPageParams} from './plan-page-params';
|
import {PlanPageParams} from './plan-page-params';
|
||||||
import Set from './set';
|
import Set from './set';
|
||||||
import {addSet, countManyToday, getDistinctSets} from './set.service';
|
import {addSet, countMany} from './set.service';
|
||||||
import SetForm from './SetForm';
|
import SetForm from './SetForm';
|
||||||
import StackHeader from './StackHeader';
|
import StackHeader from './StackHeader';
|
||||||
import {useSettings} from './use-settings';
|
import {useSettings} from './use-settings';
|
||||||
|
@ -30,7 +30,6 @@ export default function StartPlan() {
|
||||||
const [selected, setSelected] = useState(0);
|
const [selected, setSelected] = useState(0);
|
||||||
const {settings} = useSettings();
|
const {settings} = useSettings();
|
||||||
const [counts, setCounts] = useState<CountMany[]>();
|
const [counts, setCounts] = useState<CountMany[]>();
|
||||||
const [distinctSets, setDistinctSets] = useState<Set[]>();
|
|
||||||
const weightRef = useRef<TextInput>(null);
|
const weightRef = useRef<TextInput>(null);
|
||||||
const repsRef = useRef<TextInput>(null);
|
const repsRef = useRef<TextInput>(null);
|
||||||
const unitRef = useRef<TextInput>(null);
|
const unitRef = useRef<TextInput>(null);
|
||||||
|
@ -44,16 +43,10 @@ export default function StartPlan() {
|
||||||
|
|
||||||
useFocusEffect(
|
useFocusEffect(
|
||||||
useCallback(() => {
|
useCallback(() => {
|
||||||
countManyToday().then(newCounts => {
|
countMany(workouts).then(newCounts => {
|
||||||
setCounts(newCounts);
|
setCounts(newCounts);
|
||||||
console.log(`${StartPlan.name}.focus:`, {newCounts});
|
console.log(`${StartPlan.name}.focus:`, {newCounts});
|
||||||
});
|
});
|
||||||
getDistinctSets({limit: 100, offset: 0, search: '%'}).then(
|
|
||||||
newDistinct => {
|
|
||||||
setDistinctSets(newDistinct);
|
|
||||||
console.log(`${StartPlan.name}.focus:`, {newDistinct});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}, [params]),
|
}, [params]),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -69,7 +62,7 @@ export default function StartPlan() {
|
||||||
image: set.image,
|
image: set.image,
|
||||||
unit,
|
unit,
|
||||||
});
|
});
|
||||||
countManyToday().then(setCounts);
|
countMany(workouts).then(setCounts);
|
||||||
if (
|
if (
|
||||||
settings.notify &&
|
settings.notify &&
|
||||||
(+weight > best.weight || (+reps > best.reps && +weight === best.weight))
|
(+weight > best.weight || (+reps > best.reps && +weight === best.weight))
|
||||||
|
@ -95,10 +88,11 @@ export default function StartPlan() {
|
||||||
const select = useCallback(
|
const select = useCallback(
|
||||||
async (index: number) => {
|
async (index: number) => {
|
||||||
setSelected(index);
|
setSelected(index);
|
||||||
console.log(`${StartPlan.name}.next:`, {name, workouts});
|
console.log(`${StartPlan.name}.next:`, {name});
|
||||||
const workout = workouts[index];
|
if (!counts) return;
|
||||||
|
const workout = counts[index];
|
||||||
console.log(`${StartPlan.name}.next:`, {workout});
|
console.log(`${StartPlan.name}.next:`, {workout});
|
||||||
const newBest = await getBestSet(workout);
|
const newBest = await getBestSet(workout.name);
|
||||||
setMinutes(newBest.minutes);
|
setMinutes(newBest.minutes);
|
||||||
setSeconds(newBest.seconds);
|
setSeconds(newBest.seconds);
|
||||||
setName(newBest.name);
|
setName(newBest.name);
|
||||||
|
@ -110,20 +104,6 @@ export default function StartPlan() {
|
||||||
[name, workouts],
|
[name, workouts],
|
||||||
);
|
);
|
||||||
|
|
||||||
const getDescription = useCallback(
|
|
||||||
(countName: string) => {
|
|
||||||
const count = counts?.find(c => c.name === countName);
|
|
||||||
console.log(`${StartPlan.name}:`, {count, countName});
|
|
||||||
if (!distinctSets) return;
|
|
||||||
const distinct = distinctSets.find(d => d.name === countName);
|
|
||||||
console.log(`${StartPlan.name}:`, {distinct});
|
|
||||||
if (settings.showSets)
|
|
||||||
return `${count?.total || 0} / ${distinct?.sets || 3}`;
|
|
||||||
return count?.total || '0';
|
|
||||||
},
|
|
||||||
[counts, distinctSets, settings.showSets],
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<StackHeader title={params.plan.days.replace(/,/g, ', ')} />
|
<StackHeader title={params.plan.days.replace(/,/g, ', ')} />
|
||||||
|
@ -157,13 +137,17 @@ export default function StartPlan() {
|
||||||
innerRef={unitRef}
|
innerRef={unitRef}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{counts && distinctSets && (
|
{counts && (
|
||||||
<FlatList
|
<FlatList
|
||||||
data={workouts}
|
data={counts}
|
||||||
renderItem={({item, index}) => (
|
renderItem={({item, index}) => (
|
||||||
<List.Item
|
<List.Item
|
||||||
title={item}
|
title={item.name}
|
||||||
description={getDescription(item)}
|
description={
|
||||||
|
settings.showSets
|
||||||
|
? `${item.total} / ${item.sets ?? 3}`
|
||||||
|
: item.total.toString()
|
||||||
|
}
|
||||||
onPress={() => select(index)}
|
onPress={() => select(index)}
|
||||||
left={() => (
|
left={() => (
|
||||||
<View
|
<View
|
||||||
|
|
|
@ -64,7 +64,7 @@ export default function ViewBest() {
|
||||||
yData={volumes.map(v => v.value)}
|
yData={volumes.map(v => v.value)}
|
||||||
yFormat={(value: number) =>
|
yFormat={(value: number) =>
|
||||||
`${value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')}${
|
`${value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')}${
|
||||||
volumes[0].unit
|
volumes[0].unit || 'kg'
|
||||||
}`
|
}`
|
||||||
}
|
}
|
||||||
xData={weights}
|
xData={weights}
|
||||||
|
|
|
@ -43,8 +43,8 @@ android {
|
||||||
missingDimensionStrategy "RNNotifications.reactNativeVersion", "reactNative60"
|
missingDimensionStrategy "RNNotifications.reactNativeVersion", "reactNative60"
|
||||||
minSdkVersion rootProject.ext.minSdkVersion
|
minSdkVersion rootProject.ext.minSdkVersion
|
||||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||||
versionCode 36069
|
versionCode 36071
|
||||||
versionName "1.43"
|
versionName "1.45"
|
||||||
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
|
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
|
||||||
|
|
||||||
if (isNewArchitectureEnabled()) {
|
if (isNewArchitectureEnabled()) {
|
||||||
|
|
|
@ -67,7 +67,7 @@ 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, sound: String?) {
|
fun timer(milliseconds: Int, vibrate: Boolean, sound: String?, noSound: Boolean = false) {
|
||||||
Log.d("AlarmModule", "Queue alarm for $milliseconds delay")
|
Log.d("AlarmModule", "Queue alarm for $milliseconds delay")
|
||||||
val intent = Intent(reactApplicationContext, AlarmModule::class.java)
|
val intent = Intent(reactApplicationContext, AlarmModule::class.java)
|
||||||
currentActivity?.startActivityForResult(intent, 0)
|
currentActivity?.startActivityForResult(intent, 0)
|
||||||
|
|
|
@ -21,11 +21,13 @@ class AlarmService : Service(), OnPreparedListener {
|
||||||
return START_STICKY
|
return START_STICKY
|
||||||
}
|
}
|
||||||
val sound = intent.extras?.getString("sound")
|
val sound = intent.extras?.getString("sound")
|
||||||
if (sound == null) {
|
val noSound = intent.extras?.getBoolean("noSound") == true
|
||||||
|
|
||||||
|
if (sound == null && !noSound) {
|
||||||
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 {
|
} else if (sound != null && !noSound) {
|
||||||
mediaPlayer = MediaPlayer().apply {
|
mediaPlayer = MediaPlayer().apply {
|
||||||
setAudioAttributes(
|
setAudioAttributes(
|
||||||
AudioAttributes.Builder()
|
AudioAttributes.Builder()
|
||||||
|
@ -39,6 +41,7 @@ class AlarmService : Service(), OnPreparedListener {
|
||||||
setOnCompletionListener { vibrator?.cancel() }
|
setOnCompletionListener { vibrator?.cancel() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val pattern = longArrayOf(0, 300, 1300, 300, 1300, 300)
|
val pattern = longArrayOf(0, 300, 1300, 300, 1300, 300)
|
||||||
vibrator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
vibrator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||||
val vibratorManager =
|
val vibratorManager =
|
||||||
|
|
|
@ -20,11 +20,13 @@ class TimerService : Service() {
|
||||||
private var endMs: Int = 0
|
private var endMs: Int = 0
|
||||||
private var currentMs: Long = 0
|
private var currentMs: Long = 0
|
||||||
private var vibrate: Boolean = true
|
private var vibrate: Boolean = true
|
||||||
|
private var noSound: Boolean = false
|
||||||
private var sound: String? = null
|
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 {
|
||||||
vibrate = intent?.extras?.getBoolean("vibrate") == true
|
vibrate = intent?.extras?.getBoolean("vibrate") == true
|
||||||
|
noSound = intent?.extras?.getBoolean("noSound") == true
|
||||||
sound = intent?.extras?.getString("sound")
|
sound = intent?.extras?.getString("sound")
|
||||||
val manager = getManager()
|
val manager = getManager()
|
||||||
manager.cancel(NOTIFICATION_ID_DONE)
|
manager.cancel(NOTIFICATION_ID_DONE)
|
||||||
|
@ -93,9 +95,11 @@ class TimerService : Service() {
|
||||||
val manager = getManager()
|
val manager = getManager()
|
||||||
manager.notify(NOTIFICATION_ID_DONE, builder.build())
|
manager.notify(NOTIFICATION_ID_DONE, builder.build())
|
||||||
manager.cancel(NOTIFICATION_ID_PENDING)
|
manager.cancel(NOTIFICATION_ID_PENDING)
|
||||||
val alarmIntent = Intent(applicationContext, AlarmService::class.java)
|
val alarmIntent = Intent(applicationContext, AlarmService::class.java).apply {
|
||||||
alarmIntent.putExtra("vibrate", vibrate)
|
putExtra("vibrate", vibrate)
|
||||||
alarmIntent.putExtra("sound", sound)
|
putExtra("sound", sound)
|
||||||
|
putExtra("noSound", noSound)
|
||||||
|
}
|
||||||
applicationContext.startService(alarmIntent)
|
applicationContext.startService(alarmIntent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -124,11 +128,13 @@ class TimerService : Service() {
|
||||||
val stopIntent = Intent(context, StopTimer::class.java)
|
val stopIntent = Intent(context, StopTimer::class.java)
|
||||||
val pendingStop =
|
val pendingStop =
|
||||||
PendingIntent.getService(context, 0, stopIntent, PendingIntent.FLAG_IMMUTABLE)
|
PendingIntent.getService(context, 0, stopIntent, PendingIntent.FLAG_IMMUTABLE)
|
||||||
val addIntent = Intent(context, TimerService::class.java)
|
val addIntent = Intent(context, TimerService::class.java).apply {
|
||||||
addIntent.action = "add"
|
action = "add"
|
||||||
addIntent.putExtra("vibrate", vibrate)
|
putExtra("vibrate", vibrate)
|
||||||
addIntent.putExtra("sound", sound)
|
putExtra("sound", sound)
|
||||||
addIntent.data = Uri.parse("$currentMs")
|
putExtra("noSound", noSound)
|
||||||
|
data = Uri.parse("$currentMs")
|
||||||
|
}
|
||||||
val pendingAdd = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
val pendingAdd = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||||
PendingIntent.getService(context, 0, addIntent, PendingIntent.FLAG_MUTABLE)
|
PendingIntent.getService(context, 0, addIntent, PendingIntent.FLAG_MUTABLE)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
export default interface CountMany {
|
export default interface CountMany {
|
||||||
name: string;
|
name: string;
|
||||||
total: number;
|
total: number;
|
||||||
|
sets?: number;
|
||||||
}
|
}
|
||||||
|
|
22
db.ts
22
db.ts
|
@ -41,16 +41,16 @@ const migrations = [
|
||||||
)
|
)
|
||||||
`,
|
`,
|
||||||
`
|
`
|
||||||
ALTER TABLE sets ADD COLUMN hidden DEFAULT 0
|
ALTER TABLE sets ADD COLUMN hidden DEFAULT false
|
||||||
`,
|
`,
|
||||||
`
|
`
|
||||||
ALTER TABLE settings ADD COLUMN notify DEFAULT 0
|
ALTER TABLE settings ADD COLUMN notify DEFAULT false
|
||||||
`,
|
`,
|
||||||
`
|
`
|
||||||
ALTER TABLE sets ADD COLUMN image TEXT NULL
|
ALTER TABLE sets ADD COLUMN image TEXT NULL
|
||||||
`,
|
`,
|
||||||
`
|
`
|
||||||
ALTER TABLE settings ADD COLUMN images BOOLEAN DEFAULT 1
|
ALTER TABLE settings ADD COLUMN images BOOLEAN DEFAULT true
|
||||||
`,
|
`,
|
||||||
`
|
`
|
||||||
SELECT * FROM settings LIMIT 1
|
SELECT * FROM settings LIMIT 1
|
||||||
|
@ -74,7 +74,7 @@ const migrations = [
|
||||||
ALTER TABLE sets ADD COLUMN seconds INTEGER NOT NULL DEFAULT 30
|
ALTER TABLE sets ADD COLUMN seconds INTEGER NOT NULL DEFAULT 30
|
||||||
`,
|
`,
|
||||||
`
|
`
|
||||||
ALTER TABLE settings ADD COLUMN showUnit BOOLEAN DEFAULT 1
|
ALTER TABLE settings ADD COLUMN showUnit BOOLEAN DEFAULT true
|
||||||
`,
|
`,
|
||||||
`
|
`
|
||||||
ALTER TABLE sets ADD COLUMN steps TEXT NULL
|
ALTER TABLE sets ADD COLUMN steps TEXT NULL
|
||||||
|
@ -94,10 +94,10 @@ const migrations = [
|
||||||
UPDATE settings SET showUnit = 1
|
UPDATE settings SET showUnit = 1
|
||||||
`,
|
`,
|
||||||
`
|
`
|
||||||
ALTER TABLE settings ADD COLUMN workouts BOOLEAN DEFAULT 1
|
ALTER TABLE settings ADD COLUMN workouts BOOLEAN DEFAULT true
|
||||||
`,
|
`,
|
||||||
`
|
`
|
||||||
ALTER TABLE settings ADD COLUMN steps BOOLEAN DEFAULT 1
|
ALTER TABLE settings ADD COLUMN steps BOOLEAN DEFAULT true
|
||||||
`,
|
`,
|
||||||
`
|
`
|
||||||
ALTER TABLE settings ADD COLUMN nextAlarm TEXT NULL
|
ALTER TABLE settings ADD COLUMN nextAlarm TEXT NULL
|
||||||
|
@ -109,13 +109,19 @@ const migrations = [
|
||||||
ALTER TABLE settings ADD COLUMN date TEXT NULL
|
ALTER TABLE settings ADD COLUMN date TEXT NULL
|
||||||
`,
|
`,
|
||||||
`
|
`
|
||||||
ALTER TABLE settings ADD COLUMN showDate BOOLEAN DEFAULT 0
|
ALTER TABLE settings ADD COLUMN showDate BOOLEAN DEFAULT false
|
||||||
`,
|
`,
|
||||||
`
|
`
|
||||||
ALTER TABLE settings ADD COLUMN theme TEXT
|
ALTER TABLE settings ADD COLUMN theme TEXT
|
||||||
`,
|
`,
|
||||||
`
|
`
|
||||||
ALTER TABLE settings ADD COLUMN showSets BOOLEAN DEFAULT 1
|
ALTER TABLE settings ADD COLUMN showSets BOOLEAN DEFAULT true
|
||||||
|
`,
|
||||||
|
`
|
||||||
|
CREATE INDEX sets_created ON sets(created)
|
||||||
|
`,
|
||||||
|
`
|
||||||
|
ALTER TABLE settings ADD COLUMN noSound BOOLEAN DEFAULT false
|
||||||
`,
|
`,
|
||||||
`
|
`
|
||||||
CREATE INDEX sets_created ON sets(created)
|
CREATE INDEX sets_created ON sets(created)
|
||||||
|
|
28
package.json
28
package.json
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "massive",
|
"name": "massive",
|
||||||
"version": "1.43",
|
"version": "1.45",
|
||||||
"private": true,
|
"private": true,
|
||||||
"license": "GPL-3.0-only",
|
"license": "GPL-3.0-only",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -23,19 +23,19 @@
|
||||||
"@types/react-native-vector-icons": "^6.4.12",
|
"@types/react-native-vector-icons": "^6.4.12",
|
||||||
"babel-plugin-transform-remove-console": "^6.9.4",
|
"babel-plugin-transform-remove-console": "^6.9.4",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-native": "^0.70.1",
|
"react-native": "^0.70.4",
|
||||||
"react-native-document-picker": "^8.1.1",
|
"react-native-document-picker": "^8.1.2",
|
||||||
"react-native-file-access": "^2.5.0",
|
"react-native-file-access": "^2.5.0",
|
||||||
"react-native-gesture-handler": "^2.6.1",
|
"react-native-gesture-handler": "^2.8.0",
|
||||||
"react-native-linear-gradient": "^2.6.2",
|
"react-native-linear-gradient": "^2.6.2",
|
||||||
"react-native-pager-view": "^6.0.0",
|
"react-native-pager-view": "^6.0.1",
|
||||||
"react-native-paper": "^4.12.4",
|
"react-native-paper": "^4.12.5",
|
||||||
"react-native-reanimated": "^2.10.0",
|
"react-native-reanimated": "^2.12.0",
|
||||||
"react-native-safe-area-context": "^4.3.3",
|
"react-native-safe-area-context": "^4.4.1",
|
||||||
"react-native-screens": "^3.17.0",
|
"react-native-screens": "^3.18.2",
|
||||||
"react-native-share": "^7.9.0",
|
"react-native-share": "^7.9.1",
|
||||||
"react-native-sqlite-storage": "^6.0.1",
|
"react-native-sqlite-storage": "^6.0.1",
|
||||||
"react-native-svg": "^13.2.0",
|
"react-native-svg": "^13.4.0",
|
||||||
"react-native-svg-charts": "^5.4.0",
|
"react-native-svg-charts": "^5.4.0",
|
||||||
"react-native-vector-icons": "^9.2.0",
|
"react-native-vector-icons": "^9.2.0",
|
||||||
"react-native-view-shot": "^3.4.0"
|
"react-native-view-shot": "^3.4.0"
|
||||||
|
@ -48,9 +48,9 @@
|
||||||
"@types/react-test-renderer": "^18.0.0",
|
"@types/react-test-renderer": "^18.0.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.29.0",
|
"@typescript-eslint/eslint-plugin": "^5.29.0",
|
||||||
"@typescript-eslint/parser": "^5.29.0",
|
"@typescript-eslint/parser": "^5.29.0",
|
||||||
"eslint": "^7.32.0",
|
"eslint": "^8.26.0",
|
||||||
"metro-react-native-babel-preset": "^0.70.3",
|
"metro-react-native-babel-preset": "^0.73.3",
|
||||||
"typescript": "^4.4.4"
|
"typescript": "^4.8.4"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
"extends": "react-app",
|
"extends": "react-app",
|
||||||
|
|
|
@ -82,18 +82,13 @@ export const getSets = async ({
|
||||||
}: PageParams): Promise<Set[]> => {
|
}: PageParams): Promise<Set[]> => {
|
||||||
const select = `
|
const select = `
|
||||||
SELECT id, name, reps, weight, sets, minutes, seconds,
|
SELECT id, name, reps, weight, sets, minutes, seconds,
|
||||||
STRFTIME(?, created) as created, unit, image, steps
|
created, unit, image, steps
|
||||||
FROM sets
|
FROM sets
|
||||||
WHERE name LIKE ? AND NOT hidden
|
WHERE name LIKE ? AND NOT hidden
|
||||||
ORDER BY STRFTIME('%Y-%m-%d %H:%M', created) DESC
|
ORDER BY STRFTIME('%Y-%m-%d %H:%M', created) DESC
|
||||||
LIMIT ? OFFSET ?
|
LIMIT ? OFFSET ?
|
||||||
`;
|
`;
|
||||||
const [result] = await db.executeSql(select, [
|
const [result] = await db.executeSql(select, [`%${search}%`, limit, offset]);
|
||||||
format,
|
|
||||||
`%${search}%`,
|
|
||||||
limit,
|
|
||||||
offset,
|
|
||||||
]);
|
|
||||||
return result.rows.raw();
|
return result.rows.raw();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -166,14 +161,21 @@ export const countToday = async (name: string): Promise<number> => {
|
||||||
return Number(result.rows.item(0)?.total);
|
return Number(result.rows.item(0)?.total);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const countManyToday = async (): Promise<CountMany[]> => {
|
export const countMany = async (names: string[]): Promise<CountMany[]> => {
|
||||||
|
const questions = names.map(_ => '?').join(',');
|
||||||
|
console.log({questions, names});
|
||||||
const select = `
|
const select = `
|
||||||
SELECT COUNT(*) as total, name FROM sets
|
SELECT workouts.name, COUNT(sets.id) as total, workouts.sets
|
||||||
WHERE created LIKE strftime('%Y-%m-%d%%', 'now', 'localtime')
|
FROM (
|
||||||
AND NOT hidden
|
SELECT distinct name, sets FROM sets
|
||||||
GROUP BY name
|
WHERE name IN (${questions})
|
||||||
|
) workouts
|
||||||
|
LEFT JOIN sets ON sets.name = workouts.name
|
||||||
|
AND sets.created LIKE STRFTIME('%Y-%m-%d%%', 'now', 'localtime')
|
||||||
|
AND NOT sets.hidden
|
||||||
|
GROUP BY workouts.name;
|
||||||
`;
|
`;
|
||||||
const [result] = await db.executeSql(select);
|
const [result] = await db.executeSql(select, names);
|
||||||
return result.rows.raw();
|
return result.rows.raw();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -11,5 +11,5 @@ export default interface Settings {
|
||||||
showDate: number;
|
showDate: number;
|
||||||
theme: 'system' | 'dark' | 'light';
|
theme: 'system' | 'dark' | 'light';
|
||||||
showSets: number;
|
showSets: number;
|
||||||
nextAlarm?: string;
|
noSound: number;
|
||||||
}
|
}
|
||||||
|
|
45
time.ts
45
time.ts
|
@ -14,3 +14,48 @@ export function formatMonth(iso: string) {
|
||||||
const mm = (date.getMonth() + 1).toString();
|
const mm = (date.getMonth() + 1).toString();
|
||||||
return `${dd}/${mm}`;
|
return `${dd}/${mm}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function twelveHour(twentyFourHour: string) {
|
||||||
|
const [hourString, minute] = twentyFourHour.split(':');
|
||||||
|
const hour = +hourString % 24;
|
||||||
|
return (hour % 12 || 12) + ':' + minute + (hour < 12 ? ' AM' : ' PM');
|
||||||
|
}
|
||||||
|
|
||||||
|
function dayOfWeek(iso: string) {
|
||||||
|
const date = new Date(iso);
|
||||||
|
const day = date.getDay();
|
||||||
|
const target = DAYS[day === 0 ? 0 : day - 1];
|
||||||
|
return target.slice(0, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param iso ISO formatted date, e.g. 1996-12-24T14:03:04
|
||||||
|
* @param kind Intended format for the date, e.g. '%Y-%m-%d %H:%M'
|
||||||
|
*/
|
||||||
|
export function format(iso: string, kind: string) {
|
||||||
|
const split = iso.split('T');
|
||||||
|
const [year, month, day] = split[0].split('-');
|
||||||
|
const time = twelveHour(split[1]);
|
||||||
|
switch (kind) {
|
||||||
|
case '%Y-%m-%d %H:%M':
|
||||||
|
return iso.replace('T', ' ').replace(/:\d{2}/, '');
|
||||||
|
case '%Y-%m-%d':
|
||||||
|
return split[0];
|
||||||
|
case '%H:%M':
|
||||||
|
return split[1].replace(/:\d{2}/, '');
|
||||||
|
case '%d/%m/%y %h:%M %p':
|
||||||
|
return `${day}/${month}/${year} ${time}`;
|
||||||
|
case '%d/%m %h:%M %p':
|
||||||
|
return `${day}/${month} ${time}`;
|
||||||
|
case '%d/%m/%y':
|
||||||
|
return `${day}/${month}/${year}`;
|
||||||
|
case '%d/%m':
|
||||||
|
return `${day}/${month}`;
|
||||||
|
case '%h:%M %p':
|
||||||
|
return time;
|
||||||
|
case '%A %h:%M %p':
|
||||||
|
return dayOfWeek(iso) + ' ' + time;
|
||||||
|
default:
|
||||||
|
return iso;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user