Remove loading indicator where load times are fast
If the load time is too fast (on a mid-tier device), then for most people they will see a flicker of a loading spinner (which looks like a bug). These indicators would only marginally improve the experience of people with the slowest devices, but for most people this will just look like a bug. I left the indicators in the InsightsPage since those queries actually do take >=300ms on a mid-tier device.
This commit is contained in:
parent
b44cbae131
commit
1b164aaaf1
11
EditPlan.tsx
11
EditPlan.tsx
|
@ -6,12 +6,7 @@ import {
|
||||||
} from "@react-navigation/native";
|
} from "@react-navigation/native";
|
||||||
import { useCallback, useEffect, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
import { Pressable, StyleSheet, View } from "react-native";
|
import { Pressable, StyleSheet, View } from "react-native";
|
||||||
import {
|
import { IconButton, Switch as PaperSwitch, Text } from "react-native-paper";
|
||||||
ActivityIndicator,
|
|
||||||
IconButton,
|
|
||||||
Switch as PaperSwitch,
|
|
||||||
Text,
|
|
||||||
} from "react-native-paper";
|
|
||||||
import ReorderableList, {
|
import ReorderableList, {
|
||||||
ReorderableListRenderItemInfo,
|
ReorderableListRenderItemInfo,
|
||||||
} from "react-native-reorderable-list";
|
} from "react-native-reorderable-list";
|
||||||
|
@ -171,9 +166,7 @@ export default function EditPlan() {
|
||||||
{DAYS.map((day) => renderDay(day))}
|
{DAYS.map((day) => renderDay(day))}
|
||||||
|
|
||||||
<Text style={[styles.title, { marginTop: MARGIN }]}>Exercises</Text>
|
<Text style={[styles.title, { marginTop: MARGIN }]}>Exercises</Text>
|
||||||
{names === undefined ? (
|
{names !== undefined && (
|
||||||
<ActivityIndicator />
|
|
||||||
) : (
|
|
||||||
<ReorderableList
|
<ReorderableList
|
||||||
data={names}
|
data={names}
|
||||||
ListEmptyComponent={<Text>No exercises yet</Text>}
|
ListEmptyComponent={<Text>No exercises yet</Text>}
|
||||||
|
|
|
@ -25,6 +25,8 @@ interface HourCount {
|
||||||
export default function InsightsPage() {
|
export default function InsightsPage() {
|
||||||
const [weekCounts, setWeekCounts] = useState<WeekCount[]>();
|
const [weekCounts, setWeekCounts] = useState<WeekCount[]>();
|
||||||
const [hourCounts, setHourCounts] = useState<HourCount[]>();
|
const [hourCounts, setHourCounts] = useState<HourCount[]>();
|
||||||
|
const [loadingWeeks, setLoadingWeeks] = useState(true);
|
||||||
|
const [loadingHours, setLoadingHours] = useState(true);
|
||||||
const [period, setPeriod] = useState(Periods.Monthly);
|
const [period, setPeriod] = useState(Periods.Monthly);
|
||||||
const [showWeek, setShowWeek] = useState(false);
|
const [showWeek, setShowWeek] = useState(false);
|
||||||
const [showHour, setShowHour] = useState(false);
|
const [showHour, setShowHour] = useState(false);
|
||||||
|
@ -53,14 +55,22 @@ export default function InsightsPage() {
|
||||||
ORDER BY hour
|
ORDER BY hour
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
setLoadingWeeks(true);
|
||||||
|
setLoadingHours(true);
|
||||||
setTimeout(
|
setTimeout(
|
||||||
() =>
|
() =>
|
||||||
AppDataSource.manager
|
AppDataSource.manager
|
||||||
.query(selectWeeks)
|
.query(selectWeeks)
|
||||||
.then(setWeekCounts)
|
.then(setWeekCounts)
|
||||||
|
.then(() => setLoadingWeeks(false))
|
||||||
.then(() =>
|
.then(() =>
|
||||||
AppDataSource.manager.query(selectHours).then(setHourCounts)
|
AppDataSource.manager.query(selectHours).then(setHourCounts)
|
||||||
),
|
)
|
||||||
|
.then(() => setLoadingHours(false))
|
||||||
|
.finally(() => {
|
||||||
|
setLoadingWeeks(false);
|
||||||
|
setLoadingHours(false);
|
||||||
|
}),
|
||||||
400
|
400
|
||||||
);
|
);
|
||||||
}, [period])
|
}, [period])
|
||||||
|
@ -126,9 +136,9 @@ export default function InsightsPage() {
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{weekCounts === undefined && <ActivityIndicator />}
|
{loadingWeeks ? (
|
||||||
|
<ActivityIndicator />
|
||||||
{weekCounts?.length > 0 && (
|
) : (
|
||||||
<AppPieChart
|
<AppPieChart
|
||||||
options={weekCounts.map((weekCount) => ({
|
options={weekCounts.map((weekCount) => ({
|
||||||
label: DAYS[weekCount.week],
|
label: DAYS[weekCount.week],
|
||||||
|
@ -136,6 +146,7 @@ export default function InsightsPage() {
|
||||||
}))}
|
}))}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{weekCounts?.length === 0 && (
|
{weekCounts?.length === 0 && (
|
||||||
<Text style={{ marginBottom: MARGIN }}>
|
<Text style={{ marginBottom: MARGIN }}>
|
||||||
No entries yet! Start recording sets to see your most active days of
|
No entries yet! Start recording sets to see your most active days of
|
||||||
|
@ -166,14 +177,15 @@ export default function InsightsPage() {
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{hourCounts === undefined && <ActivityIndicator />}
|
{loadingHours ? (
|
||||||
|
<ActivityIndicator />
|
||||||
{hourCounts?.length > 0 && (
|
) : (
|
||||||
<Chart
|
<Chart
|
||||||
data={hourCounts.map((hc) => hc.count)}
|
data={hourCounts.map((hc) => hc.count)}
|
||||||
labels={hourCounts.map((hc) => hourLabel(hc.hour))}
|
labels={hourCounts.map((hc) => hourLabel(hc.hour))}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{hourCounts?.length === 0 && (
|
{hourCounts?.length === 0 && (
|
||||||
<Text>
|
<Text>
|
||||||
No entries yet! Start recording sets to see your most active hours
|
No entries yet! Start recording sets to see your most active hours
|
||||||
|
|
10
SetList.tsx
10
SetList.tsx
|
@ -5,16 +5,16 @@ import {
|
||||||
} from "@react-navigation/native";
|
} from "@react-navigation/native";
|
||||||
import { useCallback, useState } from "react";
|
import { useCallback, useState } from "react";
|
||||||
import { FlatList } from "react-native";
|
import { FlatList } from "react-native";
|
||||||
import { ActivityIndicator, List } from "react-native-paper";
|
import { List } from "react-native-paper";
|
||||||
import { Like } from "typeorm";
|
import { Like } from "typeorm";
|
||||||
import { StackParams } from "./AppStack";
|
import { StackParams } from "./AppStack";
|
||||||
import { LIMIT } from "./constants";
|
|
||||||
import { getNow, setRepo, settingsRepo } from "./db";
|
|
||||||
import DrawerHeader from "./DrawerHeader";
|
import DrawerHeader from "./DrawerHeader";
|
||||||
import GymSet, { defaultSet } from "./gym-set";
|
|
||||||
import ListMenu from "./ListMenu";
|
import ListMenu from "./ListMenu";
|
||||||
import Page from "./Page";
|
import Page from "./Page";
|
||||||
import SetItem from "./SetItem";
|
import SetItem from "./SetItem";
|
||||||
|
import { LIMIT } from "./constants";
|
||||||
|
import { getNow, setRepo, settingsRepo } from "./db";
|
||||||
|
import GymSet, { defaultSet } from "./gym-set";
|
||||||
import Settings from "./settings";
|
import Settings from "./settings";
|
||||||
|
|
||||||
export default function SetList() {
|
export default function SetList() {
|
||||||
|
@ -134,7 +134,7 @@ export default function SetList() {
|
||||||
}, [sets, ids]);
|
}, [sets, ids]);
|
||||||
|
|
||||||
const getContent = () => {
|
const getContent = () => {
|
||||||
if (!settings || sets === undefined) return <ActivityIndicator />;
|
if (!settings || sets === undefined) return null;
|
||||||
if (sets.length === 0)
|
if (sets.length === 0)
|
||||||
return (
|
return (
|
||||||
<List.Item
|
<List.Item
|
||||||
|
|
|
@ -7,16 +7,14 @@ import {
|
||||||
} from "@react-navigation/native";
|
} from "@react-navigation/native";
|
||||||
import { useCallback, useMemo, useRef, useState } from "react";
|
import { useCallback, useMemo, useRef, useState } from "react";
|
||||||
import { FlatList, NativeModules, TextInput, View } from "react-native";
|
import { FlatList, NativeModules, TextInput, View } from "react-native";
|
||||||
import {
|
import { IconButton, ProgressBar } from "react-native-paper";
|
||||||
ActivityIndicator,
|
import { PERMISSIONS, RESULTS, check, request } from "react-native-permissions";
|
||||||
Button,
|
|
||||||
IconButton,
|
|
||||||
ProgressBar,
|
|
||||||
useTheme,
|
|
||||||
} from "react-native-paper";
|
|
||||||
import { check, PERMISSIONS, request, RESULTS } from "react-native-permissions";
|
|
||||||
import AppInput from "./AppInput";
|
import AppInput from "./AppInput";
|
||||||
import { StackParams } from "./AppStack";
|
import { StackParams } from "./AppStack";
|
||||||
|
import PrimaryButton from "./PrimaryButton";
|
||||||
|
import Select from "./Select";
|
||||||
|
import StackHeader from "./StackHeader";
|
||||||
|
import StartPlanItem from "./StartPlanItem";
|
||||||
import { getBestSet } from "./best.service";
|
import { getBestSet } from "./best.service";
|
||||||
import { PADDING } from "./constants";
|
import { PADDING } from "./constants";
|
||||||
import { convert } from "./conversions";
|
import { convert } from "./conversions";
|
||||||
|
@ -25,12 +23,8 @@ import { AppDataSource } from "./data-source";
|
||||||
import { getNow, setRepo, settingsRepo } from "./db";
|
import { getNow, setRepo, settingsRepo } from "./db";
|
||||||
import { fixNumeric } from "./fix-numeric";
|
import { fixNumeric } from "./fix-numeric";
|
||||||
import GymSet from "./gym-set";
|
import GymSet from "./gym-set";
|
||||||
import Select from "./Select";
|
|
||||||
import Settings from "./settings";
|
import Settings from "./settings";
|
||||||
import StackHeader from "./StackHeader";
|
|
||||||
import StartPlanItem from "./StartPlanItem";
|
|
||||||
import { toast } from "./toast";
|
import { toast } from "./toast";
|
||||||
import PrimaryButton from "./PrimaryButton";
|
|
||||||
|
|
||||||
export default function StartPlan() {
|
export default function StartPlan() {
|
||||||
const { params } = useRoute<RouteProp<StackParams, "StartPlan">>();
|
const { params } = useRoute<RouteProp<StackParams, "StartPlan">>();
|
||||||
|
@ -40,7 +34,6 @@ export default function StartPlan() {
|
||||||
const [selected, setSelected] = useState(0);
|
const [selected, setSelected] = useState(0);
|
||||||
const [settings, setSettings] = useState<Settings>();
|
const [settings, setSettings] = useState<Settings>();
|
||||||
const [counts, setCounts] = useState<CountMany[]>();
|
const [counts, setCounts] = useState<CountMany[]>();
|
||||||
const { colors } = useTheme();
|
|
||||||
const weightRef = useRef<TextInput>(null);
|
const weightRef = useRef<TextInput>(null);
|
||||||
const repsRef = useRef<TextInput>(null);
|
const repsRef = useRef<TextInput>(null);
|
||||||
const exercises = useMemo(() => params.plan.exercises.split(","), [params]);
|
const exercises = useMemo(() => params.plan.exercises.split(","), [params]);
|
||||||
|
@ -222,9 +215,7 @@ export default function StartPlan() {
|
||||||
label="Unit"
|
label="Unit"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{counts === undefined ? (
|
{counts !== undefined && (
|
||||||
<ActivityIndicator />
|
|
||||||
) : (
|
|
||||||
<FlatList
|
<FlatList
|
||||||
data={counts}
|
data={counts}
|
||||||
keyExtractor={(count) => count.name}
|
keyExtractor={(count) => count.name}
|
||||||
|
|
|
@ -3,18 +3,18 @@ import { format } from "date-fns";
|
||||||
import { useEffect, useMemo, useState } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
import { View } from "react-native";
|
import { View } from "react-native";
|
||||||
import { FileSystem } from "react-native-file-access";
|
import { FileSystem } from "react-native-file-access";
|
||||||
import { ActivityIndicator, IconButton, List } from "react-native-paper";
|
import { IconButton, List } from "react-native-paper";
|
||||||
import Share from "react-native-share";
|
import Share from "react-native-share";
|
||||||
import { captureScreen } from "react-native-view-shot";
|
import { captureScreen } from "react-native-view-shot";
|
||||||
import { StackParams } from "./AppStack";
|
import { StackParams } from "./AppStack";
|
||||||
import Chart from "./Chart";
|
import Chart from "./Chart";
|
||||||
|
import Select from "./Select";
|
||||||
|
import StackHeader from "./StackHeader";
|
||||||
import { PADDING } from "./constants";
|
import { PADDING } from "./constants";
|
||||||
import { setRepo } from "./db";
|
import { setRepo } from "./db";
|
||||||
import GymSet from "./gym-set";
|
import GymSet from "./gym-set";
|
||||||
import { Metrics } from "./metrics";
|
import { Metrics } from "./metrics";
|
||||||
import { Periods } from "./periods";
|
import { Periods } from "./periods";
|
||||||
import Select from "./Select";
|
|
||||||
import StackHeader from "./StackHeader";
|
|
||||||
import Volume from "./volume";
|
import Volume from "./volume";
|
||||||
|
|
||||||
export default function ViewGraph() {
|
export default function ViewGraph() {
|
||||||
|
@ -76,7 +76,7 @@ export default function ViewGraph() {
|
||||||
}, [params.name, metric, period]);
|
}, [params.name, metric, period]);
|
||||||
|
|
||||||
const weightChart = useMemo(() => {
|
const weightChart = useMemo(() => {
|
||||||
if (weights === undefined) return <ActivityIndicator />;
|
if (weights === undefined) return null;
|
||||||
|
|
||||||
let periodFormat = "do";
|
let periodFormat = "do";
|
||||||
if (period === Periods.Weekly) periodFormat = "iii";
|
if (period === Periods.Weekly) periodFormat = "iii";
|
||||||
|
@ -95,7 +95,7 @@ export default function ViewGraph() {
|
||||||
}, [weights, period]);
|
}, [weights, period]);
|
||||||
|
|
||||||
const volumeChart = useMemo(() => {
|
const volumeChart = useMemo(() => {
|
||||||
if (volumes === undefined) return <ActivityIndicator />;
|
if (volumes === undefined) return null;
|
||||||
|
|
||||||
let periodFormat = "do";
|
let periodFormat = "do";
|
||||||
if (period === Periods.Weekly) periodFormat = "iii";
|
if (period === Periods.Weekly) periodFormat = "iii";
|
||||||
|
|
Loading…
Reference in New Issue
Block a user