Skip to content

Commit

Permalink
Merge pull request #12 from Miskamyasa/mm/mobx
Browse files Browse the repository at this point in the history
pr: mobx intergration
  • Loading branch information
Miskamyasa authored Oct 18, 2024
2 parents 067c990 + e8ca2ac commit 7f36cfa
Show file tree
Hide file tree
Showing 62 changed files with 928 additions and 1,536 deletions.
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,20 @@
"@types/react-redux": "7.1.30",
"@typescript-eslint/eslint-plugin": "6.11.0",
"@typescript-eslint/parser": "6.11.0",
"eslint": "8.52.0",
"eslint": "8.57.0",
"eslint-plugin-import": "2.29.0",
"eslint-plugin-import-newlines": "1.4.0",
"eslint-plugin-react": "7.33.2",
"eslint-plugin-react-hooks": "4.6.0",
"eslint-plugin-react-native": "4.1.0",
"eslint-plugin-sort-keys-fix": "1.1.2",
"eslint-plugin-unused-imports": "3.0.0",
"expo": "51.0.36",
"expo": "51.0.38",
"expo-application": "5.9.1",
"expo-asset": "10.0.10",
"expo-build-properties": "0.12.5",
"expo-constants": "16.0.2",
"expo-dev-client": "4.0.27",
"expo-dev-client": "4.0.28",
"expo-device": "6.0.2",
"expo-file-system": "17.0.1",
"expo-image": "1.13.0",
Expand All @@ -62,7 +62,7 @@
"expo-random": "14.0.1",
"expo-splash-screen": "0.27.6",
"expo-status-bar": "1.12.1",
"expo-updates": "0.25.26",
"expo-updates": "0.25.27",
"i18n-js": "3.8.0",
"lodash": "4.17.21",
"metro-core": "0.80.12",
Expand Down
731 changes: 360 additions & 371 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

14 changes: 2 additions & 12 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@

import type {ReactElement} from "react"

import {initialWindowMetrics, SafeAreaProvider} from "react-native-safe-area-context"
import {Provider} from "react-redux"
import {PersistGate} from "redux-persist/integration/react"

import {Popups} from "./components/popups/Popups"
import {useBootstrapApp} from "./hooks/useBootstrapApp"
import {Navigation} from "./navigation/Navigation"
import {persistor, store} from "./store"
import {StoresProvider} from "./store/StoresProvider"

export function App(): ReactElement | null {
Expand All @@ -21,14 +17,8 @@ export function App(): ReactElement | null {
return (
<SafeAreaProvider initialMetrics={initialWindowMetrics}>
<StoresProvider>
<Provider store={store}>
<PersistGate
loading={null}
persistor={persistor}>
<Navigation />
<Popups />
</PersistGate>
</Provider>
<Navigation/>
<Popups/>
</StoresProvider>
</SafeAreaProvider>
)
Expand Down
19 changes: 7 additions & 12 deletions src/components/ApproachCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import {View, type ViewStyle} from "react-native"
import {layout} from "../constants/layout"
import {createStaticStyles} from "../helpers/createStaticStyles"
import {__date} from "../helpers/i18n"
import {useAppSelector} from "../store"
import type {Approach} from "../store/approaches/types"
import type {Approach} from "../store/approaches/ApproachesStore"
import {useStores} from "../store/useStores"

import {Div} from "./Div"
import {Span} from "./Span"
Expand All @@ -14,7 +14,7 @@ const width
// screen width
= layout.width
// minus icon and title paddings
- (layout.gap * 4.5)
- (layout.gap * 3.5)
// minus icon width
- layout.iconWidth
// minus skill title width
Expand Down Expand Up @@ -72,48 +72,43 @@ export const ApproachCard = memo(function ApproachCard(props: {
flex?: boolean
}) {
const {id, date = false, flex = false} = props
const data = useAppSelector(state => state.approaches.store[id])
const workout = useAppSelector(state => state.workouts.store[data.workoutId])
const {workoutsStore, approachesStore} = useStores()

const data = approachesStore.registry[id]
const workout = workoutsStore.registry[data.workoutId]!

return (
<Div style={flex ? styles.fullWidth : styles.container}>

<View style={styles["30"]}>
<Span>{date ? __date(workout.date) : ""}</Span>
</View>

<View style={styles["10"]}>
<Span>&nbsp;</Span>
</View>

<View style={styles["20"]}>
<Span
size={20}
weight="900">
{data.repeats}
</Span>
</View>

<View style={styles["10"]}>
<Span
size={17}
weight="900">
&times;
</Span>
</View>

<View style={styles["25"]}>
<Span
size={20}
weight="900">
{data.weight}
</Span>
</View>

<View style={styles["5"]}>
<Span>&nbsp;</Span>
</View>

</Div>
)
})
2 changes: 1 addition & 1 deletion src/components/SkillImage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export default function SkillImage({name, banner}: {
}
}
catch (e) {
analytics.sendEvent((e as Error).message)
analytics.trackError(e)
}
return images.customIcon
}, [name])
Expand Down
2 changes: 1 addition & 1 deletion src/components/popups/Popups.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export const Popups = observer(function Portal() {
isVisible={portalStore.visible}
style={styles.modal}>
<Div style={styles.content}>
{portalStore.component ?? null}
{portalStore.current ?? null}
</Div>
</Modal>
<Errors />
Expand Down
2 changes: 2 additions & 0 deletions src/constants/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ export const appVersion = String(__DEV__
export const defaultRepeats = 10

export const defaultWeight = 0

export const EMPTY_ARRAY: [] = [] as const
6 changes: 2 additions & 4 deletions src/features/skills/SelectedSkillProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {createContext, Component, type ReactElement, type ReactNode} from "react"

import type {Skill} from "../../store/skills/types"
import type {Skill} from "../../store/skills/SkillsStore"

type ContextValue = {
selected: null | Skill
Expand All @@ -14,9 +14,7 @@ const SelectedSkillContext = createContext<ContextValue>({

SelectedSkillContext.displayName = "SelectedSkillContext"

class SelectedSkillProvider extends Component<{
children: ReactNode
}> {
class SelectedSkillProvider extends Component<{children: ReactNode}> {
setSelected = (selected: Skill | null): void => this.setState(() => ({selected}))

state = {
Expand Down
8 changes: 4 additions & 4 deletions src/features/skills/SkillsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {FlatList} from "react-native"

import {flatList} from "../../constants/defaultStyles"
import {__t} from "../../helpers/i18n"
import type {Categories} from "../../store/skills/types"
import type {Categories} from "../../store/skills/SkillsStore"

import {SelectedSkillProvider} from "./SelectedSkillProvider"
import {SkillsListHeader} from "./SkillsListHeader"
Expand All @@ -15,7 +15,7 @@ type SkillsSection = {
title: string
}

const sections: Array<SkillsSection> = [
const sections: SkillsSection[] = [
{key: "custom", title: __t("exercises.sections.custom")},
{key: "base", title: __t("exercises.sections.base")},
{key: "other", title: __t("exercises.sections.other")},
Expand All @@ -29,11 +29,11 @@ function renderItem({item}: {item: SkillsSection}): ReactElement {
)
}

function keyExtractor(item: SkillsSection): string {
const keyExtractor = function keyExtractor(item: SkillsSection): string {
return item.key
}

export const SkillsList = memo(function SkillsList(): ReactElement {
export const SkillsList = memo(function SkillsList() {
return (
<SelectedSkillProvider>
<FlatList
Expand Down
31 changes: 9 additions & 22 deletions src/features/skills/SkillsListHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {Fragment, useCallback, useContext, type ReactElement} from "react"
import {Fragment, useCallback, useContext} from "react"
import {StyleSheet, View} from "react-native"

import {isEmpty} from "lodash"
import {observer} from "mobx-react"

import {primaryColors, secondaryColors} from "../../colors/colors"
Expand All @@ -14,10 +13,7 @@ import {analytics} from "../../helpers/analytics"
import {__locale, __t} from "../../helpers/i18n"
import {useBoolean} from "../../hooks/useBoolean"
import {useKeyboard} from "../../hooks/useKeyboard"
import {navigation} from "../../navigation/config"
import {useAppDispatch, useAppSelector} from "../../store"
import {useStores} from "../../store/useStores"
import {addSkillToWorkout} from "../../store/workouts/actions"

import {NewSkillForm} from "./NewSkillForm"
import {SelectedSkillContext} from "./SelectedSkillProvider"
Expand Down Expand Up @@ -47,44 +43,35 @@ const staticStyles = StyleSheet.create({
},
})

export const SkillsListHeader = observer(function SkillsListHeader(): ReactElement | null {
const {skillsStore} = useStores()

const workout = useAppSelector(state => state.workouts.current)
export const SkillsListHeader = observer(function SkillsListHeader() {
const {skillsStore, workoutsStore} = useStores()

const {selected, setSelected} = useContext(SelectedSkillContext)

const [, dismissKeyboard] = useKeyboard()
const [visible, openModal, closeModal] = useBoolean(false, undefined, dismissKeyboard)

const dispatch = useAppDispatch()

const handleStart = useCallback(() => {
if (selected) {
analytics.sendEvent("add_skill_to_workout", {skill: selected.title["en"]})
dispatch(addSkillToWorkout(selected.id))
workoutsStore.addSkillToWorkout(selected.id)
analytics.trackEvent("add_skill_to_workout", {skill: selected.title["en"]})
setSelected(null)
}
}, [dispatch, selected, setSelected])
}, [workoutsStore, selected, setSelected])

const handleSubmitNewSkill = useCallback((text: string) => {
closeModal()
if (text.length > 0) {
analytics.sendEvent("new_skill_form_submit", {title: text})
analytics.trackEvent("new_skill_form_submit", {title: text})
skillsStore.addCustomSkill(text)
}
}, [closeModal, skillsStore])

const openNewSkillModal = useCallback(() => {
analytics.sendEvent("new_skill_form_open")
analytics.trackEvent("new_skill_form_open")
openModal()
}, [openModal])

if (!workout || isEmpty(workout)) {
navigation.replace("HomeScreen", undefined)
return null
}

return (
<Fragment>
<View style={staticStyles.container}>
Expand Down Expand Up @@ -114,7 +101,7 @@ export const SkillsListHeader = observer(function SkillsListHeader(): ReactEleme
style={staticStyles.text}>
{__t("exercises.selected")}
{":\n"}
{selected ? skillsStore.registry.get(selected.id)!.title[__locale()] : "-"}
{selected ? skillsStore.registry[selected.id]!.title[__locale()] : "-"}
</Span>
</Div>
<Div
Expand Down
41 changes: 16 additions & 25 deletions src/features/skills/SkillsListItem.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
import {useCallback, useContext, type ReactElement} from "react"
import {useCallback, useContext} from "react"
import {StyleSheet, TouchableOpacity, type ViewStyle} from "react-native"

import MaterialIcons from "@expo/vector-icons/MaterialIcons"
import {isEmpty} from "lodash"
import {observer} from "mobx-react"

import {useThemeColor} from "../../colors/useThemeColor"
import {Div} from "../../components/Div"
import SkillImage from "../../components/SkillImage"
import {Span} from "../../components/Span"
import {EMPTY_ARRAY} from "../../constants/common"
import {layout} from "../../constants/layout"
import {analytics} from "../../helpers/analytics"
import {__locale} from "../../helpers/i18n"
import {navigation} from "../../navigation/config"
import {useAppSelector} from "../../store"
import type {Skill} from "../../store/skills/types"
import type {Skill} from "../../store/skills/SkillsStore"
import {useStores} from "../../store/useStores"

import {SelectedSkillContext} from "./SelectedSkillProvider"
Expand All @@ -33,47 +32,39 @@ const selected: ViewStyle = {
backgroundColor: "rgba(184,184,184, 0.2)",
}

const help: ViewStyle = {
marginRight: layout.gap,
}

const staticStyles = StyleSheet.create({
container,
help,
help: {
marginRight: layout.gap,
},
selected,
})

const hitSlop = {left: 8, top: 8, right: 8, bottom: 8}

export const SkillsListItem = observer(function SkillsListItem({id}: {
export const SkillsListItem = observer(function SkillsListItem(props: {
id: Skill["id"]
}): ReactElement | null {
const {skillsStore} = useStores()
}) {
const color = useThemeColor("text")
const {skillsStore, workoutsStore} = useStores()

const skill = skillsStore.registry.get(id)!
const skill = skillsStore.registry[props.id]!

const currentSkills = useAppSelector(state => state.workouts.current?.skills)
const currentSkills = workoutsStore.registry[workoutsStore.current!]?.skills || EMPTY_ARRAY

const {selected, setSelected} = useContext(SelectedSkillContext)

const showInfoScreen = useCallback(() => {
analytics.sendEvent("show_info_for_skill", {title: skill.title["en"]})
navigation.navigate("SkillInfoScreen", {id})
}, [id, skill.title])
analytics.trackEvent("show_info_for_skill", {title: skill.title["en"]})
navigation.navigate("SkillInfoScreen", {id: props.id})
}, [props.id, skill.title])

const toggleSelected = useCallback(() => {
setSelected(skill)
}, [skill, setSelected])

if (isEmpty(skill)) {
return null
}

return (
<Div
disabled={currentSkills?.includes(skill.id)}
style={selected?.id === id ? staticStyles.selected : staticStyles.container}
style={selected?.id === props.id ? staticStyles.selected : staticStyles.container}
onPress={toggleSelected}>
<SkillImage name={skill.icon} />
<Span
Expand All @@ -84,7 +75,7 @@ export const SkillsListItem = observer(function SkillsListItem({id}: {
{skill.category !== "custom" && skill.description[__locale()]
? (
<TouchableOpacity
hitSlop={hitSlop}
hitSlop={layout.hitSlop}
style={staticStyles.help}
onPress={showInfoScreen}>
<MaterialIcons
Expand Down
Loading

0 comments on commit 7f36cfa

Please sign in to comment.