بنقرة واحدة
add-feature
Add a new feature or screen to the Ecency mobile app following established patterns
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Add a new feature or screen to the Ecency mobile app following established patterns
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Add a new blockchain mutation wrapper using @ecency/sdk in the mobile app
Use an @ecency/sdk query in the mobile app or create a new app-specific query
Add a new bottom sheet (action sheet) to the mobile app
Review code changes for bugs, pattern violations, and common pitfalls in ecency-mobile
Debug common issues in the Ecency mobile app with known solutions and investigation patterns
| name | add-feature |
| description | Add a new feature or screen to the Ecency mobile app following established patterns |
| argument-hint | ["feature-name"] |
| disable-model-invocation | true |
Guide for adding a new feature to the Ecency mobile app.
The app uses two patterns for screens:
Many existing screens use class components with container/view separation:
src/screens/<feature>/
screen/<feature>Screen.tsx # Class component with business logic
screen/<feature>Styles.ts # EStyleSheet styles
Example: src/screens/transfer/screen/delegateScreen.tsx
New screens should use functional components with hooks:
src/screens/<feature>/
screen/<feature>Screen.tsx # Functional component
children/ # Sub-components
hooks/ # Custom hooks
Location: src/screens/<feature>/screen/<feature>Screen.tsx
import React from 'react';
import { View, Text } from 'react-native';
import { useIntl } from 'react-intl';
import { useQuery } from '@tanstack/react-query';
import { getSomeQueryOptions } from '@ecency/sdk';
import { BasicHeader } from '../../../components';
import { useAppSelector } from '../../../hooks';
import { selectCurrentAccount } from '../../../redux/selectors';
import styles from './<feature>Styles';
const FeatureScreen = ({ route, navigation }) => {
const intl = useIntl();
const currentAccount = useAppSelector(selectCurrentAccount);
const { data, isLoading } = useQuery(getSomeQueryOptions(currentAccount?.name));
return (
<View style={styles.container}>
<BasicHeader title={intl.formatMessage({ id: 'feature.title' })} />
{/* Screen content */}
</View>
);
};
export default FeatureScreen;
In src/constants/routeNames.ts:
export default {
SCREENS: {
// ... existing
FEATURE: 'Feature',
},
// ...
};
In src/navigation/stackNavigator.tsx:
import FeatureScreen from '../screens/<feature>/screen/<feature>Screen';
// Inside the Stack.Navigator:
<Stack.Screen name={ROUTES.SCREENS.FEATURE} component={FeatureScreen} />
import { useNavigation } from '@react-navigation/native';
import ROUTES from '../../constants/routeNames';
const navigation = useNavigation();
navigation.navigate(ROUTES.SCREENS.FEATURE, { /* params */ });
Add strings to src/config/locales/en-US.json:
{
"feature.title": "Feature Title",
"feature.description": "Some description"
}
Use with react-intl:
import { useIntl } from 'react-intl';
const intl = useIntl();
intl.formatMessage({ id: 'feature.title' });
Use react-native-extended-stylesheet with theme variables:
import EStyleSheet from 'react-native-extended-stylesheet';
export default EStyleSheet.create({
container: {
flex: 1,
backgroundColor: '$primaryBackgroundColor',
},
title: {
color: '$primaryBlack',
fontSize: 18,
fontWeight: 'bold',
},
subtitle: {
color: '$primaryDarkGray',
fontSize: 14,
},
});
Key theme variables:
$primaryBackgroundColor — main background$primaryLightBackground — card/section background$primaryBlack — primary text$primaryDarkGray — secondary text$primaryBlue — accent/link color$iconColor — icon tint$primaryRed — error/destructive| State type | Where | When |
|---|---|---|
| Blockchain/API data | TanStack Query via SDK query options | Always for server data |
| Global app state | Redux (src/redux/reducers/) | Auth, settings, UI state |
| Optimistic updates | Redux cache reducer | Vote caching, post metadata |
| Local component state | useState/useReducer | Form inputs, toggles |
import { useAppSelector, useAppDispatch } from '../../hooks';
import { selectCurrentAccount } from '../../redux/selectors';
import { someAction } from '../../redux/actions/someAction';
const currentAccount = useAppSelector(selectCurrentAccount);
const dispatch = useAppDispatch();
dispatch(someAction(payload));
Common components from src/components/:
BasicHeader — screen header with back buttonMainButton — primary action buttonTextInput — styled text inputUserAvatar — user profile pictureIcon — icon componentModal — modal dialogPostCard — post list itemProfileSummary — user profile headerrouteNames.tsstackNavigator.tsxen-US.jsonyarn lint passes