skillstore-cli 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +95 -0
- package/data/bundles/devflow-complete.json +19 -0
- package/data/free-skills/devflow-agile/manifest.json +19 -0
- package/data/free-skills/devflow-agile/plugin/commands/agile/retro.md +23 -0
- package/data/free-skills/devflow-agile/plugin/commands/agile/review.md +21 -0
- package/data/free-skills/devflow-agile/plugin/commands/agile/sprint.md +30 -0
- package/data/free-skills/devflow-agile/plugin/commands/agile/standup.md +20 -0
- package/data/free-skills/devflow-agile/plugin/commands/agile.md +35 -0
- package/data/free-skills/devflow-agile/plugin/commands/devflow.md +42 -0
- package/data/free-skills/devflow-agile/plugin/skills/developer/SKILL.md +93 -0
- package/data/free-skills/devflow-agile/plugin/skills/developer/assets/sample-output.md +182 -0
- package/data/free-skills/devflow-agile/plugin/skills/developer/references/clean-architecture.md +361 -0
- package/data/free-skills/devflow-agile/plugin/skills/developer/references/clean-code-guide.md +207 -0
- package/data/free-skills/devflow-agile/plugin/skills/developer/references/debugging-methodology.md +191 -0
- package/data/free-skills/devflow-agile/template/agents/agile-coach.md +76 -0
- package/data/free-skills/devflow-agile/template/workflows/agile-sprint-workflow.md +81 -0
- package/data/free-skills/devflow-bootstrap/manifest.json +8 -0
- package/data/free-skills/devflow-bootstrap/plugin/commands/bootstrap/auto.md +31 -0
- package/data/free-skills/devflow-bootstrap/plugin/commands/bootstrap.md +38 -0
- package/data/free-skills/devflow-bootstrap/plugin/commands/devflow.md +20 -0
- package/data/free-skills/devflow-bootstrap/plugin/skills/project-scaffold/SKILL.md +56 -0
- package/data/free-skills/devflow-bootstrap/plugin/skills/project-scaffold/assets/sample-output.md +216 -0
- package/data/free-skills/devflow-bootstrap/plugin/skills/project-scaffold/references/architecture-decisions.md +254 -0
- package/data/free-skills/devflow-bootstrap/plugin/skills/project-scaffold/references/stack-templates.md +400 -0
- package/data/free-skills/devflow-bootstrap/template/agents/bootstrap-specialist.md +56 -0
- package/data/free-skills/devflow-bootstrap/template/workflows/bootstrap-workflow.md +70 -0
- package/data/free-skills/devflow-docs/manifest.json +8 -0
- package/data/free-skills/devflow-docs/plugin/commands/devflow.md +20 -0
- package/data/free-skills/devflow-docs/plugin/commands/docs/generate.md +17 -0
- package/data/free-skills/devflow-docs/plugin/commands/docs/parse.md +19 -0
- package/data/free-skills/devflow-docs/plugin/commands/docs.md +26 -0
- package/data/free-skills/devflow-docs/plugin/skills/pdf-processor/SKILL.md +59 -0
- package/data/free-skills/devflow-docs/plugin/skills/pdf-processor/assets/sample-output.md +114 -0
- package/data/free-skills/devflow-docs/plugin/skills/pdf-processor/references/extraction-techniques.md +115 -0
- package/data/free-skills/devflow-docs/plugin/skills/pdf-processor/references/ocr-strategies.md +167 -0
- package/data/free-skills/devflow-docs/template/agents/docs-specialist.md +35 -0
- package/data/free-skills/devflow-docs/template/workflows/docs-workflow.md +70 -0
- package/data/free-skills/devflow-postproject/manifest.json +13 -0
- package/data/free-skills/devflow-postproject/plugin/commands/devflow.md +34 -0
- package/data/free-skills/devflow-postproject/plugin/commands/postproject/handover.md +21 -0
- package/data/free-skills/devflow-postproject/plugin/commands/postproject/retro.md +21 -0
- package/data/free-skills/devflow-postproject/plugin/commands/postproject/support.md +21 -0
- package/data/free-skills/devflow-postproject/plugin/commands/postproject.md +32 -0
- package/data/free-skills/devflow-postproject/plugin/skills/retrospective/SKILL.md +70 -0
- package/data/free-skills/devflow-postproject/plugin/skills/retrospective/assets/sample-output.md +79 -0
- package/data/free-skills/devflow-postproject/plugin/skills/retrospective/references/facilitation-techniques.md +178 -0
- package/data/free-skills/devflow-postproject/plugin/skills/retrospective/references/lessons-learned-template.md +118 -0
- package/data/free-skills/devflow-postproject/plugin/skills/retrospective/references/retro-techniques.md +100 -0
- package/data/free-skills/devflow-postproject/template/agents/transition-manager.md +71 -0
- package/data/free-skills/devflow-postproject/template/workflows/transition-workflow.md +72 -0
- package/data/free-skills/devflow-presale/manifest.json +15 -0
- package/data/free-skills/devflow-presale/plugin/commands/devflow.md +47 -0
- package/data/free-skills/devflow-presale/plugin/commands/presale/analyze.md +30 -0
- package/data/free-skills/devflow-presale/plugin/commands/presale/estimate.md +30 -0
- package/data/free-skills/devflow-presale/plugin/commands/presale/price.md +30 -0
- package/data/free-skills/devflow-presale/plugin/commands/presale/propose.md +30 -0
- package/data/free-skills/devflow-presale/plugin/commands/presale.md +42 -0
- package/data/free-skills/devflow-presale/plugin/skills/requirement-analysis/SKILL.md +63 -0
- package/data/free-skills/devflow-presale/plugin/skills/requirement-analysis/assets/sample-output.md +129 -0
- package/data/free-skills/devflow-presale/plugin/skills/requirement-analysis/references/extraction-framework.md +140 -0
- package/data/free-skills/devflow-presale/plugin/skills/requirement-analysis/references/output-template.md +132 -0
- package/data/free-skills/devflow-presale/template/agents/presale-lead.md +83 -0
- package/data/free-skills/devflow-presale/template/agents/proposal-reviewer.md +63 -0
- package/data/free-skills/devflow-presale/template/workflows/presale-workflow.md +70 -0
- package/data/registry/categories.json +7 -0
- package/data/registry/packages.json +184 -0
- package/data/shared/framework/agents/brainstormer.md +74 -0
- package/data/shared/framework/agents/code-reviewer.md +87 -0
- package/data/shared/framework/agents/debugger.md +84 -0
- package/data/shared/framework/agents/docs-manager.md +55 -0
- package/data/shared/framework/agents/git-manager.md +59 -0
- package/data/shared/framework/agents/planner.md +68 -0
- package/data/shared/framework/agents/researcher.md +66 -0
- package/data/shared/framework/agents/tester.md +65 -0
- package/data/shared/framework/commands/cook/auto.md +27 -0
- package/data/shared/framework/commands/cook.md +45 -0
- package/data/shared/framework/commands/fix/ci.md +21 -0
- package/data/shared/framework/commands/fix/test.md +26 -0
- package/data/shared/framework/commands/fix/types.md +29 -0
- package/data/shared/framework/commands/fix.md +26 -0
- package/data/shared/framework/commands/git/cm.md +37 -0
- package/data/shared/framework/commands/git/pr.md +40 -0
- package/data/shared/framework/config/CLAUDE.md.template +26 -0
- package/data/shared/framework/config/settings.json +41 -0
- package/data/shared/framework/config/skillstore.config.json +29 -0
- package/data/shared/framework/hooks/discord-notify.sh +85 -0
- package/data/shared/framework/hooks/docs-sync.sh +53 -0
- package/data/shared/framework/hooks/modularization-hook.js +103 -0
- package/data/shared/framework/hooks/notification.js +94 -0
- package/data/shared/framework/hooks/quality-gate.js +109 -0
- package/data/shared/framework/hooks/scout-block.js +77 -0
- package/data/shared/framework/hooks/telegram-notify.sh +77 -0
- package/data/shared/framework/protocols/error-recovery.md +80 -0
- package/data/shared/framework/protocols/orchestration-protocol.md +112 -0
- package/data/shared/framework/quality/review-protocol.md +76 -0
- package/data/shared/framework/quality/verification-protocol.md +66 -0
- package/data/shared/framework/rules/development-rules.md +75 -0
- package/data/shared/framework/skills/backend-development/SKILL.md +77 -0
- package/data/shared/framework/skills/backend-development/assets/sample-output.md +175 -0
- package/data/shared/framework/skills/backend-development/references/advanced-patterns.md +180 -0
- package/data/shared/framework/skills/backend-development/references/api-design-guide.md +160 -0
- package/data/shared/framework/skills/backend-development/references/architecture-patterns.md +183 -0
- package/data/shared/framework/skills/backend-development/references/observability-resilience.md +155 -0
- package/data/shared/framework/skills/backend-development/references/troubleshooting.md +199 -0
- package/data/shared/framework/skills/codebase-analysis/SKILL.md +72 -0
- package/data/shared/framework/skills/codebase-analysis/assets/sample-output.md +263 -0
- package/data/shared/framework/skills/codebase-analysis/references/analysis-techniques.md +241 -0
- package/data/shared/framework/skills/codebase-analysis/references/dependency-mapping.md +280 -0
- package/data/shared/framework/skills/codebase-analysis/references/tech-debt-assessment.md +208 -0
- package/data/shared/framework/skills/databases/SKILL.md +72 -0
- package/data/shared/framework/skills/databases/assets/sample-output.md +212 -0
- package/data/shared/framework/skills/databases/references/advanced-data-patterns.md +259 -0
- package/data/shared/framework/skills/databases/references/query-optimization.md +214 -0
- package/data/shared/framework/skills/databases/references/schema-design.md +159 -0
- package/data/shared/framework/skills/databases/references/troubleshooting.md +214 -0
- package/data/shared/framework/skills/debugging-investigation/SKILL.md +84 -0
- package/data/shared/framework/skills/debugging-investigation/assets/sample-output.md +314 -0
- package/data/shared/framework/skills/debugging-investigation/references/systematic-debugging.md +197 -0
- package/data/shared/framework/skills/debugging-investigation/references/tool-specific-guides.md +202 -0
- package/data/shared/framework/skills/debugging-investigation/references/troubleshooting-patterns.md +196 -0
- package/data/shared/framework/skills/frontend-development/SKILL.md +67 -0
- package/data/shared/framework/skills/frontend-development/assets/sample-output.md +110 -0
- package/data/shared/framework/skills/frontend-development/references/component-patterns.md +112 -0
- package/data/shared/framework/skills/frontend-development/references/performance-guide.md +169 -0
- package/data/shared/framework/skills/frontend-development/references/routing-forms-realtime.md +374 -0
- package/data/shared/framework/skills/frontend-development/references/ssr-rsc-patterns.md +284 -0
- package/data/shared/framework/skills/frontend-development/references/troubleshooting.md +154 -0
- package/data/shared/framework/skills/mobile-development/SKILL.md +67 -0
- package/data/shared/framework/skills/mobile-development/assets/sample-output.md +382 -0
- package/data/shared/framework/skills/mobile-development/references/mobile-patterns.md +681 -0
- package/data/shared/framework/skills/mobile-development/references/mobile-performance.md +524 -0
- package/data/shared/framework/skills/mobile-development/references/troubleshooting.md +158 -0
- package/data/shared/framework/skills/security-audit/SKILL.md +83 -0
- package/data/shared/framework/skills/security-audit/assets/sample-output.md +451 -0
- package/data/shared/framework/skills/security-audit/references/owasp-checklist.md +580 -0
- package/data/shared/framework/skills/security-audit/references/secure-coding-patterns.md +433 -0
- package/data/shared/framework/skills/security-audit/references/vulnerability-remediation.md +331 -0
- package/data/shared/framework/skills/ui-generation/SKILL.md +70 -0
- package/data/shared/framework/skills/ui-generation/assets/sample-output.md +139 -0
- package/data/shared/framework/skills/ui-generation/references/accessibility-responsive.md +127 -0
- package/data/shared/framework/skills/ui-generation/references/compound-components.md +252 -0
- package/data/shared/framework/skills/ui-generation/references/generation-patterns.md +110 -0
- package/data/shared/framework/skills/ui-generation/references/storybook-design-system.md +278 -0
- package/data/shared/framework/skills/ui-generation/references/troubleshooting.md +198 -0
- package/data/shared/framework/workflows/documentation-management.md +58 -0
- package/data/shared/framework/workflows/primary-workflow.md +88 -0
- package/dist/commands/activate.d.ts +3 -0
- package/dist/commands/activate.d.ts.map +1 -0
- package/dist/commands/activate.js +34 -0
- package/dist/commands/activate.js.map +1 -0
- package/dist/commands/bundle.d.ts +3 -0
- package/dist/commands/bundle.d.ts.map +1 -0
- package/dist/commands/bundle.js +64 -0
- package/dist/commands/bundle.js.map +1 -0
- package/dist/commands/install.d.ts +3 -0
- package/dist/commands/install.d.ts.map +1 -0
- package/dist/commands/install.js +99 -0
- package/dist/commands/install.js.map +1 -0
- package/dist/commands/list.d.ts +3 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +37 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/search.d.ts +3 -0
- package/dist/commands/search.d.ts.map +1 -0
- package/dist/commands/search.js +30 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/status.d.ts +3 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +35 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/update.d.ts +3 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +68 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/download/cache.d.ts +3 -0
- package/dist/download/cache.d.ts.map +1 -0
- package/dist/download/cache.js +18 -0
- package/dist/download/cache.js.map +1 -0
- package/dist/download/client.d.ts +2 -0
- package/dist/download/client.d.ts.map +1 -0
- package/dist/download/client.js +58 -0
- package/dist/download/client.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/installer/file-copier.d.ts +6 -0
- package/dist/installer/file-copier.d.ts.map +1 -0
- package/dist/installer/file-copier.js +32 -0
- package/dist/installer/file-copier.js.map +1 -0
- package/dist/installer/plugin-installer.d.ts +12 -0
- package/dist/installer/plugin-installer.d.ts.map +1 -0
- package/dist/installer/plugin-installer.js +33 -0
- package/dist/installer/plugin-installer.js.map +1 -0
- package/dist/installer/template-installer.d.ts +12 -0
- package/dist/installer/template-installer.d.ts.map +1 -0
- package/dist/installer/template-installer.js +45 -0
- package/dist/installer/template-installer.js.map +1 -0
- package/dist/license/crypto.d.ts +16 -0
- package/dist/license/crypto.d.ts.map +1 -0
- package/dist/license/crypto.js +50 -0
- package/dist/license/crypto.js.map +1 -0
- package/dist/license/license-store.d.ts +19 -0
- package/dist/license/license-store.d.ts.map +1 -0
- package/dist/license/license-store.js +99 -0
- package/dist/license/license-store.js.map +1 -0
- package/dist/license/validator.d.ts +32 -0
- package/dist/license/validator.d.ts.map +1 -0
- package/dist/license/validator.js +81 -0
- package/dist/license/validator.js.map +1 -0
- package/dist/registry/loader.d.ts +30 -0
- package/dist/registry/loader.d.ts.map +1 -0
- package/dist/registry/loader.js +22 -0
- package/dist/registry/loader.js.map +1 -0
- package/dist/registry/search-engine.d.ts +9 -0
- package/dist/registry/search-engine.d.ts.map +1 -0
- package/dist/registry/search-engine.js +30 -0
- package/dist/registry/search-engine.js.map +1 -0
- package/dist/utils/config.d.ts +14 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +28 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/logger.d.ts +9 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +22 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/paths.d.ts +20 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +79 -0
- package/dist/utils/paths.js.map +1 -0
- package/package.json +54 -0
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
# Mobile Performance Optimization
|
|
2
|
+
|
|
3
|
+
## Rendering Performance
|
|
4
|
+
|
|
5
|
+
### FlatList Optimization (React Native)
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
<FlatList
|
|
9
|
+
data={items}
|
|
10
|
+
renderItem={renderItem}
|
|
11
|
+
keyExtractor={(item) => item.id}
|
|
12
|
+
// Critical performance props:
|
|
13
|
+
getItemLayout={(_, index) => ({
|
|
14
|
+
length: ITEM_HEIGHT,
|
|
15
|
+
offset: ITEM_HEIGHT * index,
|
|
16
|
+
index,
|
|
17
|
+
})}
|
|
18
|
+
maxToRenderPerBatch={10} // Render 10 items per batch
|
|
19
|
+
windowSize={5} // Render 5 screens worth of content
|
|
20
|
+
removeClippedSubviews={true} // Unmount off-screen items (Android)
|
|
21
|
+
initialNumToRender={10} // First render shows 10 items
|
|
22
|
+
/>
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**Common FlatList mistakes:**
|
|
26
|
+
- Creating new functions/objects inside `renderItem` — extract and memoize
|
|
27
|
+
- Missing `keyExtractor` or using array index as key
|
|
28
|
+
- Not providing `getItemLayout` for fixed-height items
|
|
29
|
+
- Wrapping FlatList in ScrollView (breaks virtualization)
|
|
30
|
+
|
|
31
|
+
### Memoize Expensive Components
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
// React Native — memo with custom comparison
|
|
35
|
+
const OrderCard = memo(function OrderCard({ order, onPress }: Props) {
|
|
36
|
+
return (
|
|
37
|
+
<Pressable onPress={onPress}>
|
|
38
|
+
<Text>{order.title}</Text>
|
|
39
|
+
<Text>{order.status}</Text>
|
|
40
|
+
</Pressable>
|
|
41
|
+
);
|
|
42
|
+
}, (prev, next) => prev.order.id === next.order.id && prev.order.status === next.order.status);
|
|
43
|
+
|
|
44
|
+
// Extract renderItem to avoid re-creation
|
|
45
|
+
const renderItem = useCallback(({ item }: { item: Order }) => (
|
|
46
|
+
<OrderCard order={item} onPress={() => handlePress(item.id)} />
|
|
47
|
+
), [handlePress]);
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Flutter ListView Optimization
|
|
51
|
+
|
|
52
|
+
```dart
|
|
53
|
+
// Use ListView.builder — NEVER ListView with children for long lists
|
|
54
|
+
ListView.builder(
|
|
55
|
+
itemCount: items.length,
|
|
56
|
+
itemBuilder: (context, index) => OrderCard(order: items[index]),
|
|
57
|
+
// For fixed-height items:
|
|
58
|
+
itemExtent: 80.0,
|
|
59
|
+
// Or use prototype:
|
|
60
|
+
prototypeItem: const OrderCard(order: Order.placeholder()),
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
// Use const constructors everywhere possible
|
|
64
|
+
class OrderCard extends StatelessWidget {
|
|
65
|
+
const OrderCard({required this.order}); // const constructor
|
|
66
|
+
final Order order;
|
|
67
|
+
// ...
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Image Handling
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
// React Native — use FastImage for caching
|
|
75
|
+
import FastImage from 'react-native-fast-image';
|
|
76
|
+
|
|
77
|
+
<FastImage
|
|
78
|
+
source={{
|
|
79
|
+
uri: imageUrl,
|
|
80
|
+
priority: FastImage.priority.normal,
|
|
81
|
+
cache: FastImage.cacheControl.immutable,
|
|
82
|
+
}}
|
|
83
|
+
style={{ width: 100, height: 100 }}
|
|
84
|
+
resizeMode={FastImage.resizeMode.cover}
|
|
85
|
+
/>
|
|
86
|
+
|
|
87
|
+
// Preload images for upcoming screens
|
|
88
|
+
FastImage.preload([
|
|
89
|
+
{ uri: 'https://example.com/hero.jpg' },
|
|
90
|
+
{ uri: 'https://example.com/banner.jpg' },
|
|
91
|
+
]);
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
```dart
|
|
95
|
+
// Flutter — CachedNetworkImage
|
|
96
|
+
CachedNetworkImage(
|
|
97
|
+
imageUrl: imageUrl,
|
|
98
|
+
placeholder: (_, __) => const ShimmerPlaceholder(),
|
|
99
|
+
errorWidget: (_, __, ___) => const Icon(Icons.error),
|
|
100
|
+
memCacheWidth: 200, // Decode to smaller resolution
|
|
101
|
+
)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
**Image best practices:**
|
|
105
|
+
- Serve images at appropriate resolution (1x, 2x, 3x)
|
|
106
|
+
- Use WebP format when possible (30% smaller than JPEG)
|
|
107
|
+
- Implement progressive loading (blur placeholder → full image)
|
|
108
|
+
- Set `memCacheWidth`/`memCacheHeight` to decoded size, not original
|
|
109
|
+
|
|
110
|
+
## Memory Management
|
|
111
|
+
|
|
112
|
+
### Avoiding Leaks
|
|
113
|
+
|
|
114
|
+
The top 3 causes of memory leaks in mobile apps:
|
|
115
|
+
|
|
116
|
+
**1. Unremoved listeners and subscriptions**
|
|
117
|
+
```typescript
|
|
118
|
+
// BAD — listener never removed
|
|
119
|
+
useEffect(() => {
|
|
120
|
+
socket.on('orderUpdate', handleUpdate);
|
|
121
|
+
}, []);
|
|
122
|
+
|
|
123
|
+
// GOOD — cleanup on unmount
|
|
124
|
+
useEffect(() => {
|
|
125
|
+
socket.on('orderUpdate', handleUpdate);
|
|
126
|
+
return () => socket.off('orderUpdate', handleUpdate);
|
|
127
|
+
}, []);
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**2. Timers not cleared**
|
|
131
|
+
```typescript
|
|
132
|
+
// BAD — interval runs forever
|
|
133
|
+
useEffect(() => {
|
|
134
|
+
setInterval(pollStatus, 5000);
|
|
135
|
+
}, []);
|
|
136
|
+
|
|
137
|
+
// GOOD — clear on unmount
|
|
138
|
+
useEffect(() => {
|
|
139
|
+
const id = setInterval(pollStatus, 5000);
|
|
140
|
+
return () => clearInterval(id);
|
|
141
|
+
}, []);
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**3. Closures holding stale references**
|
|
145
|
+
```typescript
|
|
146
|
+
// BAD — closure captures entire component scope
|
|
147
|
+
const heavyCallback = () => {
|
|
148
|
+
processLargeDataset(allOrders); // Holds reference to allOrders
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
// GOOD — use ref for latest value without capturing
|
|
152
|
+
const ordersRef = useRef(allOrders);
|
|
153
|
+
ordersRef.current = allOrders;
|
|
154
|
+
const heavyCallback = useCallback(() => {
|
|
155
|
+
processLargeDataset(ordersRef.current);
|
|
156
|
+
}, []);
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Large List Memory Patterns
|
|
160
|
+
|
|
161
|
+
For lists with 1000+ items:
|
|
162
|
+
|
|
163
|
+
| Strategy | When | Implementation |
|
|
164
|
+
|----------|------|---------------|
|
|
165
|
+
| Windowed rendering | Always for large lists | FlatList (RN) / ListView.builder (Flutter) |
|
|
166
|
+
| Pagination | Server-side data | Load 20 items, fetch more on scroll |
|
|
167
|
+
| Cursor-based infinite scroll | Feed-style data | `onEndReached` + cursor token |
|
|
168
|
+
| Section list | Grouped data | SectionList (RN) / SliverList with headers |
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
// Infinite scroll with cursor pagination
|
|
172
|
+
function useInfiniteOrders() {
|
|
173
|
+
return useInfiniteQuery({
|
|
174
|
+
queryKey: ['orders'],
|
|
175
|
+
queryFn: ({ pageParam }) => orderApi.list({ cursor: pageParam, limit: 20 }),
|
|
176
|
+
getNextPageParam: (lastPage) => lastPage.nextCursor,
|
|
177
|
+
initialPageParam: undefined,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// In component
|
|
182
|
+
<FlatList
|
|
183
|
+
data={orders.pages.flatMap((p) => p.items)}
|
|
184
|
+
onEndReached={() => {
|
|
185
|
+
if (hasNextPage && !isFetchingNextPage) fetchNextPage();
|
|
186
|
+
}}
|
|
187
|
+
onEndReachedThreshold={0.5}
|
|
188
|
+
ListFooterComponent={isFetchingNextPage ? <Spinner /> : null}
|
|
189
|
+
/>
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## Network Optimization
|
|
193
|
+
|
|
194
|
+
### Request Batching
|
|
195
|
+
Combine multiple small requests into one when possible.
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
// BAD — 5 separate requests on screen load
|
|
199
|
+
const user = await api.getUser(id);
|
|
200
|
+
const orders = await api.getOrders(id);
|
|
201
|
+
const addresses = await api.getAddresses(id);
|
|
202
|
+
const favorites = await api.getFavorites(id);
|
|
203
|
+
const notifications = await api.getNotifications(id);
|
|
204
|
+
|
|
205
|
+
// GOOD — single batched request
|
|
206
|
+
const { user, orders, addresses, favorites, notifications } =
|
|
207
|
+
await api.getUserDashboard(id);
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Caching Strategies
|
|
211
|
+
|
|
212
|
+
| Strategy | TTL | Use Case |
|
|
213
|
+
|----------|-----|----------|
|
|
214
|
+
| Cache first, revalidate in background | 30s–5min | Order list, product catalog |
|
|
215
|
+
| Network first, cache fallback | 0 | Payment status, real-time data |
|
|
216
|
+
| Cache only | 24h+ | App config, static content |
|
|
217
|
+
| Stale-while-revalidate | 5min | User profile, settings |
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
// TanStack Query — stale-while-revalidate
|
|
221
|
+
useQuery({
|
|
222
|
+
queryKey: ['products', categoryId],
|
|
223
|
+
queryFn: () => productApi.list(categoryId),
|
|
224
|
+
staleTime: 5 * 60 * 1000, // Fresh for 5 minutes
|
|
225
|
+
gcTime: 30 * 60 * 1000, // Keep in cache 30 minutes
|
|
226
|
+
});
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Offline Fallback
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
// Network-aware fetcher with offline fallback
|
|
233
|
+
async function fetchWithOfflineFallback<T>(
|
|
234
|
+
key: string,
|
|
235
|
+
fetcher: () => Promise<T>,
|
|
236
|
+
): Promise<T> {
|
|
237
|
+
try {
|
|
238
|
+
const data = await fetcher();
|
|
239
|
+
await localCache.set(key, data); // Update cache
|
|
240
|
+
return data;
|
|
241
|
+
} catch (error) {
|
|
242
|
+
if (isNetworkError(error)) {
|
|
243
|
+
const cached = await localCache.get<T>(key);
|
|
244
|
+
if (cached) return cached;
|
|
245
|
+
}
|
|
246
|
+
throw error;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## Startup Optimization
|
|
252
|
+
|
|
253
|
+
### Splash Screen Strategy
|
|
254
|
+
|
|
255
|
+
```
|
|
256
|
+
Cold start timeline:
|
|
257
|
+
├── 0ms OS launches process
|
|
258
|
+
├── 100ms Native splash screen shows (configured in native project)
|
|
259
|
+
├── 300ms JS/Dart engine initializes
|
|
260
|
+
├── 500ms App component mounts
|
|
261
|
+
├── 800ms Critical data fetched (auth check, config)
|
|
262
|
+
├── 1000ms Home screen renders
|
|
263
|
+
└── 1200ms Splash hides, app interactive
|
|
264
|
+
Target: < 1.5s cold start
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### Lazy Initialization
|
|
268
|
+
Don't initialize everything at app launch.
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
// BAD — everything initialized at startup
|
|
272
|
+
function App() {
|
|
273
|
+
initAnalytics();
|
|
274
|
+
initCrashReporting();
|
|
275
|
+
initFeatureFlags();
|
|
276
|
+
initDeepLinking();
|
|
277
|
+
initPushNotifications();
|
|
278
|
+
prefetchAllData();
|
|
279
|
+
return <Navigator />;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// GOOD — only init critical services at startup
|
|
283
|
+
function App() {
|
|
284
|
+
useEffect(() => {
|
|
285
|
+
// Critical — init immediately
|
|
286
|
+
initCrashReporting();
|
|
287
|
+
initAuth();
|
|
288
|
+
|
|
289
|
+
// Deferred — init after first render
|
|
290
|
+
InteractionManager.runAfterInteractions(() => {
|
|
291
|
+
initAnalytics();
|
|
292
|
+
initFeatureFlags();
|
|
293
|
+
initDeepLinking();
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
// Lazy — init when needed
|
|
297
|
+
// Push notifications: init after user completes onboarding
|
|
298
|
+
// Prefetch: only prefetch current screen's data
|
|
299
|
+
}, []);
|
|
300
|
+
|
|
301
|
+
return <Navigator />;
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Code Splitting (React Native)
|
|
306
|
+
Use `React.lazy` for screens not immediately visible:
|
|
307
|
+
|
|
308
|
+
```typescript
|
|
309
|
+
// Lazy-load screens that are not on the initial stack
|
|
310
|
+
const SettingsScreen = React.lazy(() => import('./screens/SettingsScreen'));
|
|
311
|
+
const ProfileScreen = React.lazy(() => import('./screens/ProfileScreen'));
|
|
312
|
+
|
|
313
|
+
// Hermes bytecode precompilation — ensure metro config is set
|
|
314
|
+
// metro.config.js
|
|
315
|
+
module.exports = { transformer: { hermesParser: true } };
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
## Battery Optimization
|
|
319
|
+
|
|
320
|
+
### Background Task Guidelines
|
|
321
|
+
|
|
322
|
+
| Task | Approach | Frequency |
|
|
323
|
+
|------|----------|-----------|
|
|
324
|
+
| Data sync | WorkManager (Android) / BGTaskScheduler (iOS) | Every 15-30 min |
|
|
325
|
+
| Location tracking | Significant location changes, not continuous GPS | On significant movement |
|
|
326
|
+
| Push handling | Silent push triggers minimal work | Event-driven |
|
|
327
|
+
| File upload | Background transfer API | On WiFi only |
|
|
328
|
+
|
|
329
|
+
### Location Tracking Efficiency
|
|
330
|
+
|
|
331
|
+
```typescript
|
|
332
|
+
// BAD — continuous high-accuracy tracking
|
|
333
|
+
watchPosition({ enableHighAccuracy: true, distanceFilter: 0 });
|
|
334
|
+
|
|
335
|
+
// GOOD — balanced accuracy based on use case
|
|
336
|
+
const locationConfig = {
|
|
337
|
+
delivery_tracking: {
|
|
338
|
+
enableHighAccuracy: true,
|
|
339
|
+
distanceFilter: 50, // Update every 50 meters
|
|
340
|
+
interval: 10_000, // Android: every 10 seconds
|
|
341
|
+
},
|
|
342
|
+
store_finder: {
|
|
343
|
+
enableHighAccuracy: false, // Cell/WiFi is good enough
|
|
344
|
+
distanceFilter: 500,
|
|
345
|
+
maximumAge: 60_000, // Accept 1-minute-old location
|
|
346
|
+
},
|
|
347
|
+
background_geofence: {
|
|
348
|
+
// Use geofencing API instead of polling
|
|
349
|
+
// Triggers only when entering/exiting defined regions
|
|
350
|
+
},
|
|
351
|
+
};
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
## App Size Optimization
|
|
355
|
+
|
|
356
|
+
### Size Budget
|
|
357
|
+
|
|
358
|
+
| Category | Target | Approach |
|
|
359
|
+
|----------|--------|----------|
|
|
360
|
+
| Android APK | < 30 MB | AAB + dynamic delivery |
|
|
361
|
+
| iOS IPA | < 50 MB | Asset catalogs + on-demand resources |
|
|
362
|
+
| JS bundle (RN) | < 5 MB | Tree shaking + lazy imports |
|
|
363
|
+
| Images | < 10 MB total | WebP + appropriate resolution |
|
|
364
|
+
| Fonts | < 2 MB | Subset fonts to used characters |
|
|
365
|
+
|
|
366
|
+
### Asset Optimization
|
|
367
|
+
|
|
368
|
+
```bash
|
|
369
|
+
# Android — use App Bundle for size optimization
|
|
370
|
+
# Automatically splits by density, ABI, and language
|
|
371
|
+
./gradlew bundleRelease
|
|
372
|
+
|
|
373
|
+
# iOS — enable bitcode and asset optimization
|
|
374
|
+
# In Xcode: Build Settings → Enable Bitcode = YES
|
|
375
|
+
# Use asset catalogs for automatic thinning
|
|
376
|
+
|
|
377
|
+
# React Native — analyze bundle size
|
|
378
|
+
npx react-native-bundle-visualizer
|
|
379
|
+
|
|
380
|
+
# Flutter — analyze app size
|
|
381
|
+
flutter build apk --analyze-size
|
|
382
|
+
flutter build ios --analyze-size
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
### Tree Shaking and Dead Code
|
|
386
|
+
|
|
387
|
+
```typescript
|
|
388
|
+
// BAD — imports entire library
|
|
389
|
+
import _ from 'lodash';
|
|
390
|
+
const sorted = _.sortBy(items, 'date');
|
|
391
|
+
|
|
392
|
+
// GOOD — import only what you need
|
|
393
|
+
import sortBy from 'lodash/sortBy';
|
|
394
|
+
const sorted = sortBy(items, 'date');
|
|
395
|
+
|
|
396
|
+
// BETTER — use native methods when possible
|
|
397
|
+
const sorted = [...items].sort((a, b) => a.date.localeCompare(b.date));
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
## Testing Strategy
|
|
401
|
+
|
|
402
|
+
### Testing Pyramid for Mobile
|
|
403
|
+
|
|
404
|
+
```
|
|
405
|
+
╱╲
|
|
406
|
+
╱ ╲ E2E Tests (Detox / integration_test)
|
|
407
|
+
╱ 10% ╲ Full user flows on real device/simulator
|
|
408
|
+
╱────────╲
|
|
409
|
+
╱ ╲ Component/Widget Tests
|
|
410
|
+
╱ 30% ╲ Render + interact + assert
|
|
411
|
+
╱──────────────╲
|
|
412
|
+
╱ ╲ Unit Tests
|
|
413
|
+
╱ 60% ╲ Business logic, utilities, stores
|
|
414
|
+
╱────────────────────╲
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
### Unit Tests
|
|
418
|
+
|
|
419
|
+
```typescript
|
|
420
|
+
// Test business logic in isolation
|
|
421
|
+
describe('CartStore', () => {
|
|
422
|
+
it('calculates total correctly', () => {
|
|
423
|
+
const store = useCartStore.getState();
|
|
424
|
+
store.addItem({ id: '1', name: 'Pizza', price: 12.99, quantity: 2 });
|
|
425
|
+
store.addItem({ id: '2', name: 'Drink', price: 3.50, quantity: 1 });
|
|
426
|
+
expect(store.total()).toBe(29.48);
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
it('removes item by id', () => {
|
|
430
|
+
const store = useCartStore.getState();
|
|
431
|
+
store.addItem({ id: '1', name: 'Pizza', price: 12.99, quantity: 1 });
|
|
432
|
+
store.removeItem('1');
|
|
433
|
+
expect(store.items).toHaveLength(0);
|
|
434
|
+
});
|
|
435
|
+
});
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
### Component / Widget Tests
|
|
439
|
+
|
|
440
|
+
```typescript
|
|
441
|
+
// React Native — Testing Library
|
|
442
|
+
it('shows order details and navigates on press', () => {
|
|
443
|
+
const onPress = jest.fn();
|
|
444
|
+
render(<OrderCard order={mockOrder} onPress={onPress} />);
|
|
445
|
+
|
|
446
|
+
expect(screen.getByText('Pizza Margherita')).toBeTruthy();
|
|
447
|
+
expect(screen.getByText('$12.99')).toBeTruthy();
|
|
448
|
+
|
|
449
|
+
fireEvent.press(screen.getByText('Pizza Margherita'));
|
|
450
|
+
expect(onPress).toHaveBeenCalledTimes(1);
|
|
451
|
+
});
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
```dart
|
|
455
|
+
// Flutter — widget test
|
|
456
|
+
testWidgets('OrderCard shows details and responds to tap', (tester) async {
|
|
457
|
+
var tapped = false;
|
|
458
|
+
await tester.pumpWidget(MaterialApp(
|
|
459
|
+
home: OrderCard(order: mockOrder, onTap: () => tapped = true),
|
|
460
|
+
));
|
|
461
|
+
|
|
462
|
+
expect(find.text('Pizza Margherita'), findsOneWidget);
|
|
463
|
+
expect(find.text('\$12.99'), findsOneWidget);
|
|
464
|
+
|
|
465
|
+
await tester.tap(find.text('Pizza Margherita'));
|
|
466
|
+
expect(tapped, isTrue);
|
|
467
|
+
});
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
### E2E Tests
|
|
471
|
+
|
|
472
|
+
```typescript
|
|
473
|
+
// Detox (React Native) — full user flow
|
|
474
|
+
describe('Order Flow', () => {
|
|
475
|
+
beforeAll(async () => {
|
|
476
|
+
await device.launchApp({ newInstance: true });
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
it('places an order successfully', async () => {
|
|
480
|
+
await element(by.id('menu-tab')).tap();
|
|
481
|
+
await element(by.text('Pizza Margherita')).tap();
|
|
482
|
+
await element(by.id('add-to-cart')).tap();
|
|
483
|
+
await element(by.id('cart-tab')).tap();
|
|
484
|
+
await expect(element(by.text('1 item'))).toBeVisible();
|
|
485
|
+
await element(by.id('checkout-button')).tap();
|
|
486
|
+
await element(by.id('confirm-order')).tap();
|
|
487
|
+
await expect(element(by.text('Order Confirmed'))).toBeVisible();
|
|
488
|
+
});
|
|
489
|
+
});
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
## Platform-Specific Optimizations
|
|
493
|
+
|
|
494
|
+
### iOS
|
|
495
|
+
|
|
496
|
+
| Optimization | Implementation |
|
|
497
|
+
|-------------|---------------|
|
|
498
|
+
| Large Title navigation | Use `headerLargeTitle: true` for content screens |
|
|
499
|
+
| Haptic feedback | `UIImpactFeedbackGenerator` on key interactions |
|
|
500
|
+
| Dynamic Type | Support system font scaling in all text |
|
|
501
|
+
| Safe Area | Always use `SafeAreaView` / `SafeArea` |
|
|
502
|
+
| ProMotion (120Hz) | Ensure animations use native driver |
|
|
503
|
+
|
|
504
|
+
### Android
|
|
505
|
+
|
|
506
|
+
| Optimization | Implementation |
|
|
507
|
+
|-------------|---------------|
|
|
508
|
+
| Material 3 / Dynamic Color | Use `DynamicColorTheme` on Android 12+ |
|
|
509
|
+
| Predictive back gesture | Handle back navigation with animation preview |
|
|
510
|
+
| Edge-to-edge display | Draw behind system bars with proper insets |
|
|
511
|
+
| App Startup library | Lazy-init content providers |
|
|
512
|
+
| Baseline Profiles | Generate profiles for critical user paths |
|
|
513
|
+
|
|
514
|
+
### Shared Checklist
|
|
515
|
+
|
|
516
|
+
Before every release:
|
|
517
|
+
- [ ] Test on oldest supported OS version
|
|
518
|
+
- [ ] Test on lowest-tier target device
|
|
519
|
+
- [ ] Profile startup time (cold + warm)
|
|
520
|
+
- [ ] Check memory usage over 10-minute session
|
|
521
|
+
- [ ] Verify offline behavior
|
|
522
|
+
- [ ] Run accessibility scanner
|
|
523
|
+
- [ ] Check battery usage in background
|
|
524
|
+
- [ ] Verify deep links work from terminated state
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# Mobile Development Troubleshooting Guide
|
|
2
|
+
|
|
3
|
+
## iOS Build Failures
|
|
4
|
+
|
|
5
|
+
### CocoaPods version conflicts
|
|
6
|
+
**Symptom:** `Pod install` fails with version incompatibility or spec repo errors.
|
|
7
|
+
```bash
|
|
8
|
+
# Reset CocoaPods cache and reinstall
|
|
9
|
+
cd ios && pod deintegrate && pod cache clean --all
|
|
10
|
+
rm -rf Pods Podfile.lock
|
|
11
|
+
pod repo update
|
|
12
|
+
pod install --verbose
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### Xcode compatibility issues
|
|
16
|
+
**Symptom:** Build fails after Xcode update with framework or SDK errors.
|
|
17
|
+
- Check minimum deployment target matches all pod requirements.
|
|
18
|
+
- Update `IPHONEOS_DEPLOYMENT_TARGET` in Podfile: `platform :ios, '15.0'`.
|
|
19
|
+
- Clean derived data: `rm -rf ~/Library/Developer/Xcode/DerivedData`.
|
|
20
|
+
- Reset package caches: Xcode → File → Packages → Reset Package Caches.
|
|
21
|
+
|
|
22
|
+
### Code signing failures
|
|
23
|
+
**Symptom:** `Signing requires a development team`, provisioning profile errors.
|
|
24
|
+
1. Verify team ID in Xcode → Signing & Capabilities.
|
|
25
|
+
2. Check provisioning profile: `security find-identity -p codesigning -v`.
|
|
26
|
+
3. For CI: ensure certificates are in the keychain and profiles in `~/Library/MobileDevice/Provisioning Profiles/`.
|
|
27
|
+
4. Revoke and regenerate if expired: Apple Developer Portal → Certificates.
|
|
28
|
+
|
|
29
|
+
## Android Build Failures
|
|
30
|
+
|
|
31
|
+
### Gradle version issues
|
|
32
|
+
**Symptom:** `Could not determine the dependencies of task`, Gradle sync fails.
|
|
33
|
+
```bash
|
|
34
|
+
# Clean and rebuild
|
|
35
|
+
cd android && ./gradlew clean
|
|
36
|
+
rm -rf .gradle build app/build
|
|
37
|
+
./gradlew assembleDebug --stacktrace
|
|
38
|
+
```
|
|
39
|
+
- Check `gradle-wrapper.properties` distribution URL matches project requirements.
|
|
40
|
+
- Verify `com.android.tools.build:gradle` version in root `build.gradle` is compatible.
|
|
41
|
+
|
|
42
|
+
### NDK configuration errors
|
|
43
|
+
**Symptom:** `NDK not configured` or native build failures.
|
|
44
|
+
- Set `ndk.dir` in `local.properties` or `ANDROID_NDK_HOME` env variable.
|
|
45
|
+
- Ensure NDK version matches: check `ndkVersion` in `app/build.gradle`.
|
|
46
|
+
- Install via SDK Manager: `sdkmanager "ndk;25.2.9519653"`.
|
|
47
|
+
|
|
48
|
+
### Keystore issues
|
|
49
|
+
**Symptom:** `keystore was tampered with, or password was incorrect`.
|
|
50
|
+
- Verify keystore path and password in `gradle.properties` or environment variables.
|
|
51
|
+
- List keystore contents: `keytool -list -v -keystore release.keystore`.
|
|
52
|
+
- Never commit keystores to git — use CI secrets management.
|
|
53
|
+
|
|
54
|
+
## React Native Red Screen Common Causes
|
|
55
|
+
|
|
56
|
+
**Top causes and fixes:**
|
|
57
|
+
1. **Native module not linked** — `null is not an object (evaluating 'NativeModule.method')`.
|
|
58
|
+
- Fix: `cd ios && pod install` or rebuild the app. Auto-linking should handle most cases in RN 0.60+.
|
|
59
|
+
2. **Metro bundler cache stale** — Mysterious errors after dependency changes.
|
|
60
|
+
- Fix: `npx react-native start --reset-cache`.
|
|
61
|
+
3. **Version mismatch** — JS bundle and native code out of sync.
|
|
62
|
+
- Fix: Clean build → `cd android && ./gradlew clean && cd ../ios && pod install` → rebuild.
|
|
63
|
+
4. **Missing return statement** — Component returns `undefined`.
|
|
64
|
+
- Fix: Ensure all code paths return valid JSX or `null`.
|
|
65
|
+
|
|
66
|
+
## App Crash on Startup
|
|
67
|
+
|
|
68
|
+
**Diagnosis workflow:**
|
|
69
|
+
1. **iOS:** Check Xcode console or `Console.app` for crash logs.
|
|
70
|
+
2. **Android:** `adb logcat *:E | grep -i "fatal\|crash\|exception"`.
|
|
71
|
+
3. **React Native:** Look for "RCTFatalException" or "java.lang.RuntimeException".
|
|
72
|
+
|
|
73
|
+
**Common causes:**
|
|
74
|
+
1. **Native module initialization failure** — A module's `init` method crashes.
|
|
75
|
+
- Fix: Check native module compatibility with your RN version. Update or patch.
|
|
76
|
+
2. **Missing required permissions** — App accesses hardware before permission granted.
|
|
77
|
+
- Fix: Add permission checks before accessing camera, location, etc.
|
|
78
|
+
3. **Invalid app configuration** — Malformed `Info.plist` or `AndroidManifest.xml`.
|
|
79
|
+
- Fix: Validate XML, check for required keys (e.g., `NSCameraUsageDescription`).
|
|
80
|
+
4. **ProGuard stripping required classes** — Release build crashes, debug works fine.
|
|
81
|
+
- Fix: Add keep rules in `proguard-rules.pro` for libraries that use reflection.
|
|
82
|
+
|
|
83
|
+
## JS Thread vs UI Thread Performance Profiling
|
|
84
|
+
|
|
85
|
+
**Diagnosis:**
|
|
86
|
+
1. Enable React Native Performance Monitor: shake device → "Perf Monitor".
|
|
87
|
+
2. Two frame rates shown: UI thread (native animations) and JS thread (logic/rendering).
|
|
88
|
+
3. If **JS thread drops** but UI is smooth: heavy JavaScript computation.
|
|
89
|
+
4. If **UI thread drops**: native view hierarchy too complex or heavy native animations.
|
|
90
|
+
|
|
91
|
+
**JS thread optimization:**
|
|
92
|
+
- Move heavy computation to `InteractionManager.runAfterInteractions()`.
|
|
93
|
+
- Use `useMemo` / `useCallback` to prevent unnecessary recalculations.
|
|
94
|
+
- Offload work to native modules or JSI for CPU-intensive tasks.
|
|
95
|
+
|
|
96
|
+
**UI thread optimization:**
|
|
97
|
+
- Use `Animated` with `useNativeDriver: true` for animations.
|
|
98
|
+
- Flatten view hierarchy — deep nesting degrades native layout performance.
|
|
99
|
+
- Use `removeClippedSubviews` on long `FlatList` components.
|
|
100
|
+
|
|
101
|
+
## Push Notification Not Received
|
|
102
|
+
|
|
103
|
+
### iOS checklist
|
|
104
|
+
- [ ] APNs certificate/key is valid and not expired (check in Apple Developer Portal).
|
|
105
|
+
- [ ] Correct environment: sandbox for dev, production for release.
|
|
106
|
+
- [ ] Device token is registered and sent to backend.
|
|
107
|
+
- [ ] `UIBackgroundModes` includes `remote-notification` in `Info.plist`.
|
|
108
|
+
- [ ] User granted notification permission (check `UNUserNotificationCenter` authorization status).
|
|
109
|
+
- [ ] Silent notifications: `content-available: 1` header set, app has background mode enabled.
|
|
110
|
+
|
|
111
|
+
### Android checklist
|
|
112
|
+
- [ ] `google-services.json` is up to date and in `app/` directory.
|
|
113
|
+
- [ ] FCM server key matches the project in Firebase Console.
|
|
114
|
+
- [ ] Device has Google Play Services (or use fallback for Huawei).
|
|
115
|
+
- [ ] Notification channel created (required for Android 8+).
|
|
116
|
+
- [ ] Battery optimization not killing the app: Settings → Apps → Battery → Unrestricted.
|
|
117
|
+
- [ ] Test with `adb shell am broadcast` or Firebase Console test message.
|
|
118
|
+
|
|
119
|
+
## Deep Links Not Working
|
|
120
|
+
|
|
121
|
+
**Verification steps:**
|
|
122
|
+
1. **iOS Universal Links:**
|
|
123
|
+
- Verify `apple-app-site-association` file: `curl -v https://yourdomain.com/.well-known/apple-app-site-association`.
|
|
124
|
+
- Must return `application/json` content type (not served as download).
|
|
125
|
+
- Check `applinks:` entitlement in Xcode → Signing & Capabilities.
|
|
126
|
+
- Test: `xcrun simctl openurl booted "https://yourdomain.com/path"`.
|
|
127
|
+
|
|
128
|
+
2. **Android App Links:**
|
|
129
|
+
- Verify `assetlinks.json`: `curl https://yourdomain.com/.well-known/assetlinks.json`.
|
|
130
|
+
- Check `intent-filter` in `AndroidManifest.xml` has `autoVerify="true"`.
|
|
131
|
+
- Verify: `adb shell pm get-app-links <package_name>`.
|
|
132
|
+
- Test: `adb shell am start -a android.intent.action.VIEW -d "https://yourdomain.com/path"`.
|
|
133
|
+
|
|
134
|
+
3. **Custom URI schemes** (`myapp://path`):
|
|
135
|
+
- Simpler but less secure — any app can register the same scheme.
|
|
136
|
+
- Test: `adb shell am start -a android.intent.action.VIEW -d "myapp://path"`.
|
|
137
|
+
|
|
138
|
+
## App Store / Play Store Rejection Common Reasons
|
|
139
|
+
|
|
140
|
+
### Apple App Store
|
|
141
|
+
1. **Crash on review** — Test on the exact iOS version and device type reviewers use (latest).
|
|
142
|
+
- Fix: Test on physical device with release build before submitting.
|
|
143
|
+
2. **Missing privacy policy** — Required for all apps.
|
|
144
|
+
3. **Incomplete metadata** — Screenshots missing for required device sizes.
|
|
145
|
+
4. **Non-HTTPS network calls** — ATS (App Transport Security) violations.
|
|
146
|
+
- Fix: Ensure all API calls use HTTPS. Remove ATS exceptions.
|
|
147
|
+
5. **Guideline 4.3 (Spam)** — App too similar to existing apps or is a web wrapper.
|
|
148
|
+
- Fix: Add meaningful native functionality beyond the website.
|
|
149
|
+
|
|
150
|
+
### Google Play Store
|
|
151
|
+
1. **Target API level too low** — Must target recent Android API level.
|
|
152
|
+
- Fix: Update `targetSdkVersion` in `build.gradle` to the required level.
|
|
153
|
+
2. **Missing Data Safety section** — Required disclosure of data collection practices.
|
|
154
|
+
3. **Deceptive permissions** — Requesting permissions not justified by app functionality.
|
|
155
|
+
- Fix: Remove unnecessary permissions, add clear rationale for required ones.
|
|
156
|
+
4. **Policy violation on user data** — Collecting data without consent disclosure.
|
|
157
|
+
- Fix: Add consent dialogs, update privacy policy.
|
|
158
|
+
5. **Crashes on specific devices** — Test with Firebase Test Lab across device matrix.
|