Revert my work on surgically updating lists - 1.177 🚀

I tried to maintain the current scroll position
within a list however this caused many issues
to do with outdated data, as well as performance issues.
Now we are going back to just refreshing any list on focus.

Closes #184
This commit is contained in:
Brandon Presley 2023-11-12 16:56:07 +13:00
parent 706d4d1bbd
commit 901cc72fbd
15 changed files with 53 additions and 128 deletions

View File

@ -19,7 +19,6 @@ import { emitter } from "./emitter";
import { TOAST } from "./toast"; import { TOAST } from "./toast";
import { ThemeContext } from "./use-theme"; import { ThemeContext } from "./use-theme";
import AppStack from "./AppStack"; import AppStack from "./AppStack";
import useTimer from "./use-timer";
import { TickEvent } from "./TimerPage"; import { TickEvent } from "./TimerPage";
export const CombinedDefaultTheme = { export const CombinedDefaultTheme = {

View File

@ -81,7 +81,6 @@ export default function EditExercise() {
steps, steps,
created: now, created: now,
}); });
emitter.emit(GYM_SET_CREATED);
navigate("Exercises", { reset: new Date().getTime() }); navigate("Exercises", { reset: new Date().getTime() });
}; };

View File

@ -77,7 +77,6 @@ export default function EditExercises() {
image: removeImage ? "" : uri, image: removeImage ? "" : uri,
} }
); );
emitter.emit(GYM_SET_CREATED);
for (const oldName of params.names) { for (const oldName of params.names) {
await planRepo await planRepo
.createQueryBuilder() .createQueryBuilder()

View File

@ -92,7 +92,6 @@ export default function EditSet() {
const added = async (value: GymSet) => { const added = async (value: GymSet) => {
console.log(`${EditSet.name}.added:`, value); console.log(`${EditSet.name}.added:`, value);
emitter.emit(GYM_SET_CREATED);
startTimer(value.name); startTimer(value.name);
}; };
@ -124,7 +123,6 @@ export default function EditSet() {
const saved = await setRepo.save(newSet); const saved = await setRepo.save(newSet);
notify(newSet); notify(newSet);
if (typeof set.id !== "number") added(saved); if (typeof set.id !== "number") added(saved);
else emitter.emit(GYM_SET_UPDATED, saved);
navigate("Home"); navigate("Home");
}; };
@ -161,7 +159,6 @@ export default function EditSet() {
const remove = async () => { const remove = async () => {
await setRepo.delete(set.id); await setRepo.delete(set.id);
emitter.emit(GYM_SET_DELETED);
navigate("Home"); navigate("Home");
}; };

View File

@ -63,7 +63,6 @@ export default function EditSets() {
if (unit) update.unit = unit; if (unit) update.unit = unit;
if (newImage) update.image = newImage; if (newImage) update.image = newImage;
if (Object.keys(update).length > 0) await setRepo.update(ids, update); if (Object.keys(update).length > 0) await setRepo.update(ids, update);
emitter.emit(GYM_SET_CREATED);
navigate("Home"); navigate("Home");
}; };

View File

@ -1,25 +1,22 @@
import { import {
NavigationProp, NavigationProp,
RouteProp, useFocusEffect,
useNavigation, useNavigation,
useRoute,
} from "@react-navigation/native"; } from "@react-navigation/native";
import { useCallback, useEffect, useState } from "react"; import { useCallback, useState } from "react";
import { FlatList } from "react-native"; import { FlatList } from "react-native";
import { List } from "react-native-paper"; import { List } from "react-native-paper";
import { In } from "typeorm"; import { In } from "typeorm";
import { LIMIT } from "./constants"; import { StackParams } from "./AppStack";
import { setRepo, settingsRepo } from "./db";
import DrawerHeader from "./DrawerHeader"; import DrawerHeader from "./DrawerHeader";
import { emitter } from "./emitter"; import ExerciseItem from "./ExerciseItem";
import GymSet, { GYM_SET_DELETED } from "./gym-set";
import ListMenu from "./ListMenu"; import ListMenu from "./ListMenu";
import Page from "./Page"; import Page from "./Page";
import SetList from "./SetList"; import SetList from "./SetList";
import Settings, { SETTINGS } from "./settings"; import { LIMIT } from "./constants";
import ExerciseItem from "./ExerciseItem"; import { setRepo, settingsRepo } from "./db";
import { DrawerParams } from "./drawer-param-list"; import GymSet from "./gym-set";
import { StackParams } from "./AppStack"; import Settings from "./settings";
export default function ExerciseList() { export default function ExerciseList() {
const [exercises, setExercises] = useState<GymSet[]>(); const [exercises, setExercises] = useState<GymSet[]>();
@ -30,16 +27,6 @@ export default function ExerciseList() {
const [names, setNames] = useState<string[]>([]); const [names, setNames] = useState<string[]>([]);
const [refreshing, setRefreshing] = useState(false); const [refreshing, setRefreshing] = useState(false);
const navigation = useNavigation<NavigationProp<StackParams>>(); const navigation = useNavigation<NavigationProp<StackParams>>();
const { params } = useRoute<RouteProp<DrawerParams, "Exercises">>();
const update = (newExercise: GymSet) => {
console.log(`${ExerciseList.name}.update:`, newExercise);
if (!exercises) return;
const newExercises = exercises.map((exercise) =>
exercise.name === newExercise.name ? newExercise : exercise
);
setExercises(newExercises);
};
const reset = async (value: string) => { const reset = async (value: string) => {
console.log(`${ExerciseList.name}.reset`, value); console.log(`${ExerciseList.name}.reset`, value);
@ -57,23 +44,12 @@ export default function ExerciseList() {
setExercises(newExercises); setExercises(newExercises);
}; };
useEffect(() => { useFocusEffect(
settingsRepo.findOne({ where: {} }).then(setSettings); useCallback(() => {
const description = emitter.addListener(SETTINGS, () => { reset(term);
settingsRepo.findOne({ where: {} }).then(setSettings); settingsRepo.findOne({ where: {} }).then(setSettings);
}); }, [term])
return description.remove; );
}, []);
useEffect(() => {
console.log(`${ExerciseList.name}.useEffect`, params);
if (!params) reset("");
if (params?.search) search(params.search);
else if (params?.update) update(params.update);
else if (params?.reset) reset(term);
else if (params?.clearNames) setNames([]);
/* eslint-disable react-hooks/exhaustive-deps */
}, [params]);
const renderItem = useCallback( const renderItem = useCallback(
({ item }: { item: GymSet }) => ( ({ item }: { item: GymSet }) => (
@ -132,7 +108,6 @@ export default function ExerciseList() {
const remove = async () => { const remove = async () => {
setNames([]); setNames([]);
if (names.length > 0) await setRepo.delete({ name: In(names) }); if (names.length > 0) await setRepo.delete({ name: In(names) });
emitter.emit(GYM_SET_DELETED);
await reset(term); await reset(term);
}; };

View File

@ -1,16 +1,19 @@
import { NavigationProp, useNavigation } from "@react-navigation/native"; import {
import { useCallback, useEffect, useState } from "react"; NavigationProp,
useFocusEffect,
useNavigation,
} from "@react-navigation/native";
import { useCallback, useState } from "react";
import { FlatList, Image } from "react-native"; import { FlatList, Image } from "react-native";
import { List } from "react-native-paper"; import { List } from "react-native-paper";
import DrawerHeader from "./DrawerHeader";
import { GraphsPageParams } from "./GraphsPage";
import Page from "./Page";
import { getBestSets } from "./best.service"; import { getBestSets } from "./best.service";
import { LIMIT } from "./constants"; import { LIMIT } from "./constants";
import { settingsRepo } from "./db"; import { settingsRepo } from "./db";
import DrawerHeader from "./DrawerHeader";
import { emitter } from "./emitter";
import { GraphsPageParams } from "./GraphsPage";
import GymSet from "./gym-set"; import GymSet from "./gym-set";
import Page from "./Page"; import Settings from "./settings";
import Settings, { SETTINGS } from "./settings";
export default function GraphsList() { export default function GraphsList() {
const [bests, setBests] = useState<GymSet[]>(); const [bests, setBests] = useState<GymSet[]>();
@ -21,16 +24,6 @@ export default function GraphsList() {
const [settings, setSettings] = useState<Settings>(); const [settings, setSettings] = useState<Settings>();
const [refreshing, setRefreshing] = useState(false); const [refreshing, setRefreshing] = useState(false);
useEffect(() => {
refresh("");
settingsRepo.findOne({ where: {} }).then(setSettings);
const description = emitter.addListener(SETTINGS, () => {
settingsRepo.findOne({ where: {} }).then(setSettings);
});
return description.remove;
/* eslint-disable react-hooks/exhaustive-deps */
}, []);
const refresh = useCallback( const refresh = useCallback(
async (value: string) => { async (value: string) => {
if (refreshing) return; if (refreshing) return;
@ -41,6 +34,13 @@ export default function GraphsList() {
[refreshing] [refreshing]
); );
useFocusEffect(
useCallback(() => {
refresh(term);
settingsRepo.findOne({ where: {} }).then(setSettings);
}, [refresh, term])
);
const next = useCallback(async () => { const next = useCallback(async () => {
if (end) return; if (end) return;
const newOffset = offset + LIMIT; const newOffset = offset + LIMIT;

View File

@ -1,5 +1,9 @@
import { NavigationProp, useNavigation } from "@react-navigation/native"; import {
import { useCallback, useEffect, useState } from "react"; NavigationProp,
useFocusEffect,
useNavigation,
} from "@react-navigation/native";
import { useCallback, useState } from "react";
import { FlatList } from "react-native"; import { FlatList } from "react-native";
import { List } from "react-native-paper"; import { List } from "react-native-paper";
import { Like } from "typeorm"; import { Like } from "typeorm";
@ -10,14 +14,8 @@ import Page from "./Page";
import SetItem from "./SetItem"; import SetItem from "./SetItem";
import { LIMIT } from "./constants"; import { LIMIT } from "./constants";
import { getNow, setRepo, settingsRepo } from "./db"; import { getNow, setRepo, settingsRepo } from "./db";
import { emitter } from "./emitter"; import GymSet, { defaultSet } from "./gym-set";
import GymSet, { import Settings from "./settings";
GYM_SET_CREATED,
GYM_SET_DELETED,
GYM_SET_UPDATED,
defaultSet,
} from "./gym-set";
import Settings, { SETTINGS } from "./settings";
export default function SetList() { export default function SetList() {
const [refreshing, setRefreshing] = useState(false); const [refreshing, setRefreshing] = useState(false);
@ -44,34 +42,12 @@ export default function SetList() {
[offset] [offset]
); );
useEffect(() => { useFocusEffect(
settingsRepo.findOne({ where: {} }).then(setSettings); useCallback(() => {
reset(""); settingsRepo.findOne({ where: {} }).then(setSettings);
/* eslint-disable react-hooks/exhaustive-deps */ reset(term);
}, []); }, [reset, term])
);
useEffect(() => {
const updated = (gymSet: GymSet) => {
if (!sets) console.log({ sets });
console.log(`${SetList.name}.updated:`, { gymSet, length: sets.length });
const newSets = sets.map((set) => {
if (set.id !== gymSet.id) return set;
if (gymSet.created === undefined) gymSet.created = set.created;
return gymSet;
});
setSets(newSets);
};
const descriptions = [
emitter.addListener(SETTINGS, () => {
settingsRepo.findOne({ where: {} }).then(setSettings);
}),
emitter.addListener(GYM_SET_UPDATED, updated),
emitter.addListener(GYM_SET_CREATED, () => reset("")),
emitter.addListener(GYM_SET_DELETED, () => reset("")),
];
return () => descriptions.forEach((description) => description.remove());
}, [sets]);
const search = (value: string) => { const search = (value: string) => {
console.log(`${SetList.name}.search:`, value); console.log(`${SetList.name}.search:`, value);

View File

@ -5,7 +5,9 @@ import { useForm } from "react-hook-form";
import { NativeModules, ScrollView } from "react-native"; import { NativeModules, ScrollView } from "react-native";
import DocumentPicker from "react-native-document-picker"; import DocumentPicker from "react-native-document-picker";
import { Dirs, FileSystem } from "react-native-file-access"; import { Dirs, FileSystem } from "react-native-file-access";
import { Button, TextInput } from "react-native-paper"; import { Button } from "react-native-paper";
import { PERMISSIONS, RESULTS, check, request } from "react-native-permissions";
import AppInput from "./AppInput";
import ConfirmDialog from "./ConfirmDialog"; import ConfirmDialog from "./ConfirmDialog";
import DrawerHeader from "./DrawerHeader"; import DrawerHeader from "./DrawerHeader";
import Page from "./Page"; import Page from "./Page";
@ -17,11 +19,9 @@ import { setRepo, settingsRepo } from "./db";
import { DrawerParams } from "./drawer-param-list"; import { DrawerParams } from "./drawer-param-list";
import Input from "./input"; import Input from "./input";
import { darkOptions, lightOptions, themeOptions } from "./options"; import { darkOptions, lightOptions, themeOptions } from "./options";
import Settings, { settingsUpdated } from "./settings"; import Settings from "./settings";
import { toast } from "./toast"; import { toast } from "./toast";
import { useTheme } from "./use-theme"; import { useTheme } from "./use-theme";
import { check, PERMISSIONS, RESULTS, request } from "react-native-permissions";
import AppInput from "./AppInput";
const twelveHours = [ const twelveHours = [
"dd/LL/yyyy", "dd/LL/yyyy",
@ -80,7 +80,6 @@ export default function SettingsPage() {
.set({ [key]: value }) .set({ [key]: value })
.printSql() .printSql()
.execute(); .execute();
settingsUpdated();
}, []); }, []);
const soundString = useMemo(() => { const soundString = useMemo(() => {

View File

@ -103,8 +103,7 @@ export default function StartPlan() {
created: now, created: now,
hidden: false, hidden: false,
}; };
const saved = await setRepo.save(newSet); await setRepo.save(newSet);
emitter.emit(GYM_SET_CREATED, saved);
await refresh(); await refresh();
if ( if (
settings.notify && settings.notify &&

View File

@ -24,8 +24,6 @@ export default function StartPlanItem(props: Props) {
const [showMenu, setShowMenu] = useState(false); const [showMenu, setShowMenu] = useState(false);
const { navigate: stackNavigate } = const { navigate: stackNavigate } =
useNavigation<NavigationProp<StackParams>>(); useNavigation<NavigationProp<StackParams>>();
const { navigate: drawerNavigate } =
useNavigation<NavigationProp<DrawerParams>>();
const undo = useCallback(async () => { const undo = useCallback(async () => {
const now = await getNow(); const now = await getNow();
@ -41,7 +39,6 @@ export default function StartPlanItem(props: Props) {
setShowMenu(false); setShowMenu(false);
if (!first) return toast("Nothing to undo."); if (!first) return toast("Nothing to undo.");
await setRepo.delete(first.id); await setRepo.delete(first.id);
emitter.emit(GYM_SET_DELETED, first);
onUndo(); onUndo();
}, [setShowMenu, onUndo, item.name]); }, [setShowMenu, onUndo, item.name]);

View File

@ -85,8 +85,8 @@ android {
applicationId "com.massive" applicationId "com.massive"
minSdkVersion rootProject.ext.minSdkVersion minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 36202 versionCode 36203
versionName "1.176" versionName "1.177"
} }
signingConfigs { signingConfigs {
release { release {

View File

@ -1,16 +1,9 @@
import GymSet from "./gym-set";
export type DrawerParams = { export type DrawerParams = {
Home: {}; Home: {};
Settings: {}; Settings: {};
Graphs: {}; Graphs: {};
Plans: {}; Plans: {};
Exercises: { Exercises: {};
clearNames?: boolean;
search?: string;
update?: GymSet;
reset?: number;
};
Timer: {}; Timer: {};
Weight: {}; Weight: {};
Insights: {}; Insights: {};

View File

@ -1,6 +1,6 @@
{ {
"name": "massive", "name": "massive",
"version": "1.176", "version": "1.177",
"private": true, "private": true,
"license": "GPL-3.0-only", "license": "GPL-3.0-only",
"scripts": { "scripts": {

View File

@ -1,5 +1,4 @@
import { Column, Entity, PrimaryColumn } from "typeorm"; import { Column, Entity, PrimaryColumn } from "typeorm";
import { emitter } from "./emitter";
@Entity() @Entity()
export default class Settings { export default class Settings {
@ -51,9 +50,3 @@ export default class Settings {
@Column("int") @Column("int")
duration: number; duration: number;
} }
export const SETTINGS = "settings";
export const settingsUpdated = () => {
emitter.emit(SETTINGS);
};