Skip to content

Commit

Permalink
Merge pull request #232 from SFTtech/milo/refactoring-code-improvements
Browse files Browse the repository at this point in the history
refactor to get rid of proxy-memoize dependency
  • Loading branch information
mikonse authored Sep 4, 2024
2 parents 2974d6c + 10a8165 commit c1bc0bb
Show file tree
Hide file tree
Showing 108 changed files with 926 additions and 1,267 deletions.
13 changes: 13 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "Abrechnung API",
"type": "shell",
"command": ".venv/bin/abrechnung -c config.yaml -vvv api",
"problemMatcher": []
}
]
}
8 changes: 8 additions & 0 deletions frontend/apps/mobile/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@
"dependsOn": ["ensure-symlink", "sync-deps", "pod-install", "collect-assets"],
"options": {}
},
"tsc-watch": {
"executor": "nx:run-commands",
"options": {
"commands": ["npx tsc -p tsconfig.app.json --noEmit --watch"],
"cwd": "apps/mobile",
"parallel": false
}
},
"pod-install": {
"executor": "@nx/react-native:pod-install",
"options": {}
Expand Down
17 changes: 17 additions & 0 deletions frontend/apps/mobile/src/@types/react-navigation.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { RootDrawerParamList } from "../navigation/types";
// import type { StackNavigationOptions as OriginalStackNavigationOptions } from "@react-navigation/stack";
// import type { DrawerNavigationOptions as OriginalDrawerNavigationOptions } from "@react-navigation/drawer";

declare global {
namespace ReactNavigation {
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface RootParamList extends RootDrawerParamList {}

// interface StackNavigationOptions extends OriginalStackNavigationOptions {
// onGoBack?: (() => void) | (() => Promise<void>);
// }
// interface DrawerNavigationOptions extends OriginalDrawerNavigationOptions {
// onGoBack?: (() => void) | (() => Promise<void>);
// }
}
}
17 changes: 5 additions & 12 deletions frontend/apps/mobile/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,20 @@ import { useColorScheme } from "./hooks/useColorScheme";
import { Navigation } from "./navigation";
import { NotificationProvider } from "./notifications";
import { SplashScreen } from "./screens/SplashScreen";
import {
selectAuthSlice,
selectSettingsSlice,
selectTheme,
setGlobalInfo,
useAppDispatch,
useAppSelector,
} from "./store";
import { selectTheme, setGlobalInfo, useAppDispatch, useAppSelector } from "./store";
import { CustomDarkTheme, CustomLightTheme } from "./theme";

export const App: React.FC = () => {
const colorScheme = useColorScheme();
const dispatch = useAppDispatch();
const [api, setApi] = React.useState<{ api: Api; websocket: AbrechnungWebSocket } | undefined>(undefined);

const accessToken = useAppSelector((state) => selectAccessToken({ state: selectAuthSlice(state) }));
const baseUrl = useAppSelector((state) => selectBaseUrl({ state: selectAuthSlice(state) }));
const accessToken = useAppSelector(selectAccessToken);
const baseUrl = useAppSelector(selectBaseUrl);
const isAuthenticated = accessToken !== undefined;
const userId = useAppSelector((state) => selectCurrentUserId({ state: selectAuthSlice(state) }));
const userId = useAppSelector(selectCurrentUserId);
const groupStoreStatus = useAppSelector((state) => state.groups.status);
const themeMode = useAppSelector((state) => selectTheme({ state: selectSettingsSlice(state) }));
const themeMode = useAppSelector(selectTheme);
const useDarkTheme = themeMode === "system" ? colorScheme === "dark" : themeMode === "dark";
const theme = useDarkTheme ? CustomDarkTheme : CustomLightTheme;

Expand Down
6 changes: 3 additions & 3 deletions frontend/apps/mobile/src/components/GroupListItem.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { selectGroupById } from "@abrechnung/redux";
import { useNavigation } from "@react-navigation/native";
import React from "react";
import { List } from "react-native-paper";
import { useApi } from "../core/ApiProvider";
import { changeActiveGroup, selectGroupSlice, useAppDispatch, useAppSelector } from "../store";
import { changeActiveGroup, useAppDispatch } from "../store";
import { RootDrawerParamList } from "../navigation/types";
import { DrawerNavigationProp } from "@react-navigation/drawer";
import { useGroup } from "@abrechnung/redux";

interface Props {
groupId: number;
Expand All @@ -15,7 +15,7 @@ export const GroupListItem: React.FC<Props> = ({ groupId }) => {
const navigation = useNavigation<DrawerNavigationProp<RootDrawerParamList>>();
const dispatch = useAppDispatch();
const { api } = useApi();
const group = useAppSelector((state) => selectGroupById({ state: selectGroupSlice(state), groupId }));
const group = useGroup(groupId);

if (group === undefined) {
return null;
Expand Down
28 changes: 9 additions & 19 deletions frontend/apps/mobile/src/components/PositionDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { selectSortedAccounts, wipPositionUpdated } from "@abrechnung/redux";
import { useSortedAccounts, wipPositionUpdated } from "@abrechnung/redux";
import { TransactionPosition, PositionValidator, PositionValidationErrors } from "@abrechnung/types";
import memoize from "proxy-memoize";
import React, { useCallback, useEffect, useState } from "react";
import { ScrollView, StyleSheet } from "react-native";
import {
Expand All @@ -15,7 +14,7 @@ import {
TextInput,
useTheme,
} from "react-native-paper";
import { RootState, selectAccountSlice, useAppDispatch, useAppSelector } from "../store";
import { useAppDispatch } from "../store";
import { NumericInput } from "./NumericInput";
import { KeyboardAvoidingDialog } from "./style/KeyboardAvoidingDialog";

Expand Down Expand Up @@ -59,22 +58,13 @@ export const PositionDialog: React.FC<Props> = ({

const [localEditingState, setLocalEditingState] = useState<localEditingState>(initialEditingState);
const [searchTerm, setSearchTerm] = useState("");
const selector = React.useCallback(
memoize((state: RootState) => {
const sorted = selectSortedAccounts({
state: selectAccountSlice(state),
groupId,
sortMode: "name",
searchTerm,
});
if (!editing) {
return sorted.filter((acc) => (localEditingState.usages[acc.id] ?? 0) > 0);
}
return sorted;
}),
[groupId, searchTerm, editing, localEditingState]
);
const accounts = useAppSelector(selector);
const sortedAccounts = useSortedAccounts(groupId, "name", undefined, searchTerm);
const accounts = React.useMemo(() => {
if (!editing) {
return sortedAccounts.filter((acc) => (localEditingState.usages[acc.id] ?? 0) > 0);
}
return sortedAccounts;
}, [sortedAccounts, localEditingState, editing]);
const [errors, setErrors] = useState<PositionValidationErrors>(emptyFormErrors);

const toggleShare = (accountID: number) => {
Expand Down
13 changes: 5 additions & 8 deletions frontend/apps/mobile/src/components/style/Searchbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -155,16 +155,13 @@ const Searchbar = React.forwardRef<TextInputHandles, Props>(
}
};

const { colors, roundness, dark, isV3 } = theme;
const textColor = isV3 ? theme.colors.onSurface : theme.colors.text;
const { colors, roundness, dark } = theme;
const textColor = theme.colors.onSurface;
const iconColor = customIconColor || (dark ? textColor : color(textColor).alpha(0.54).rgb().string());
const rippleColor = color(textColor).alpha(0.32).rgb().string();

return (
<Surface
style={[{ borderRadius: roundness }, !isV3 && styles.elevation, styles.container, style]}
{...(theme.isV3 && { elevation })}
>
<Surface style={[{ borderRadius: roundness }, styles.container, style]} {...(theme.isV3 && { elevation })}>
<IconButton
accessibilityRole="button"
borderless
Expand All @@ -186,13 +183,13 @@ const Searchbar = React.forwardRef<TextInputHandles, Props>(
styles.input,
{
color: textColor,
...(theme.isV3 ? theme.fonts.default : theme.fonts.regular),
...theme.fonts.default,
...Platform.select({ web: { outline: "none" } }),
},
inputStyle,
]}
placeholder={placeholder || ""}
placeholderTextColor={theme.isV3 ? theme.colors.onSurface : theme.colors?.placeholder}
placeholderTextColor={theme.colors.onSurface}
selectionColor={colors?.primary}
underlineColorAndroid="transparent"
returnKeyType="search"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const EMPTY_LIST: string[] = [];

export const TagSelectDialog: React.FC<Props> = ({ groupId, value, onChange, showDialog, onHideDialog, title }) => {
const theme = useTheme();
const usedTags = useAppSelector((state) => selectTagsInGroup({ state, groupId }));
const usedTags = useAppSelector((state) => selectTagsInGroup(state, groupId));

const [tags, setTags] = useState<string[]>(EMPTY_LIST);
const [searchTerm, setSearchTerm] = useState("");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ScrollView, View } from "react-native";
import { useEffect, useState } from "react";
import { createComparator, lambdaComparator } from "@abrechnung/utils";
import { Account, TransactionShare } from "@abrechnung/types";
import { useAppSelector, selectAccountSlice } from "../../store";
import { useAppSelector } from "../../store";
import { selectGroupAccounts } from "@abrechnung/redux";

interface Props {
Expand All @@ -28,7 +28,7 @@ export const ShareSelect: React.FC<Props> = ({
}) => {
const [shares, setShares] = useState<TransactionShare>({});
const [searchTerm, setSearchTerm] = useState("");
const accounts = useAppSelector((state) => selectGroupAccounts({ state: selectAccountSlice(state), groupId }));
const accounts = useAppSelector((state) => selectGroupAccounts(state, groupId));
const [filteredAccounts, setFilteredAccounts] = useState<Account[]>([]);

const toggleShare = (accountID: number) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import { selectSortedAccounts } from "@abrechnung/redux";
import { useSortedAccounts } from "@abrechnung/redux";
import { TransactionShare } from "@abrechnung/types";
import memoize from "proxy-memoize";
import * as React from "react";
import { useState } from "react";
import { ScrollView } from "react-native";
import { Button, Checkbox, Dialog, List, Searchbar } from "react-native-paper";
import { getAccountIcon } from "../../constants/Icons";
import { RootState, selectAccountSlice, useAppSelector } from "../../store";
import { KeyboardAvoidingDialog } from "../style/KeyboardAvoidingDialog";

interface Props {
Expand Down Expand Up @@ -34,22 +32,13 @@ export const TransactionShareDialog: React.FC<Props> = ({
excludedAccounts = [],
}) => {
const [searchTerm, setSearchTerm] = useState("");
const selector = React.useCallback(
memoize((state: RootState) => {
const sorted = selectSortedAccounts({
state: selectAccountSlice(state),
groupId,
sortMode: "name",
searchTerm,
});
if (disabled) {
return sorted.filter((acc) => (value[acc.id] ?? 0) > 0 && !excludedAccounts.includes(acc.id));
}
return sorted.filter((acc) => !excludedAccounts.includes(acc.id));
}),
[groupId, searchTerm, disabled, value, excludedAccounts]
);
const accounts = useAppSelector(selector);
const sortedAccounts = useSortedAccounts(groupId, "name", undefined, searchTerm);
const accounts = React.useMemo(() => {
if (disabled) {
return sortedAccounts.filter((acc) => (value[acc.id] ?? 0) > 0 && !excludedAccounts.includes(acc.id));
}
return sortedAccounts.filter((acc) => !excludedAccounts.includes(acc.id));
}, [sortedAccounts, excludedAccounts, value, disabled]);

const toggleShare = (account_id: number) => {
if (!onChange) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { TransactionShareDialog } from "./TransactionShareDialog";
import { useEffect, useState } from "react";
import { TouchableHighlight, View } from "react-native";
import { TransactionShare } from "@abrechnung/types";
import { useAppSelector, selectAccountSlice } from "../../store";
import { useAppSelector } from "../../store";
import { selectGroupAccounts } from "@abrechnung/redux";

interface Props {
Expand Down Expand Up @@ -33,7 +33,7 @@ export const TransactionShareInput: React.FC<Props> = ({
const [showDialog, setShowDialog] = useState(false);
const [stringifiedValue, setStringifiedValue] = useState("");
const theme = useTheme();
const accounts = useAppSelector((state) => selectGroupAccounts({ state: selectAccountSlice(state), groupId }));
const accounts = useAppSelector((state) => selectGroupAccounts(state, groupId));

useEffect(() => {
if (!value) {
Expand Down
21 changes: 6 additions & 15 deletions frontend/apps/mobile/src/navigation/DrawerContent.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,21 @@
import { selectGroups } from "@abrechnung/redux";
import { DrawerContentScrollView, DrawerNavigationProp } from "@react-navigation/drawer";
import { DrawerContentComponentProps, DrawerContentScrollView, DrawerNavigationProp } from "@react-navigation/drawer";
import { useNavigation } from "@react-navigation/native";
import * as React from "react";
import { ScrollView, ScrollViewProps, StyleSheet, View } from "react-native";
import { StyleSheet, View } from "react-native";
import { ActivityIndicator, Drawer, IconButton, useTheme } from "react-native-paper";
import MaterialCommunityIcons from "react-native-vector-icons/MaterialCommunityIcons";
import { useOptionalApi } from "../core/ApiProvider";
import {
changeActiveGroup,
selectActiveGroupId,
selectGroupSlice,
selectUiSlice,
useAppDispatch,
useAppSelector,
} from "../store";
import { changeActiveGroup, selectActiveGroupId, useAppDispatch, useAppSelector } from "../store";
import { RootDrawerParamList } from "./types";

type Props = React.ForwardRefExoticComponent<ScrollViewProps & React.RefAttributes<ScrollView>>;

export const DrawerContent: React.FC<Props> = (props) => {
export const DrawerContent: React.FC<DrawerContentComponentProps> = (props) => {
const theme = useTheme();
const { api } = useOptionalApi();
const dispatch = useAppDispatch();
const navigation = useNavigation<DrawerNavigationProp<RootDrawerParamList>>();
const activeGroupID = useAppSelector((state) => selectActiveGroupId({ state: selectUiSlice(state) }));
const groups = useAppSelector((state) => selectGroups({ state: selectGroupSlice(state) }));
const activeGroupID = useAppSelector(selectActiveGroupId);
const groups = useAppSelector(selectGroups);

if (!api) {
return null;
Expand Down
Loading

0 comments on commit c1bc0bb

Please sign in to comment.