+
☁️ CRM
☁️ CRM
6
native applications + web
347
companies
60
countries
more than
100K users
🌟 New Feature development
🕣
X months to implement
❌
some were rejected
🥇
hight priority platforms received feature first
😓
сomplicated to configure
🎯 Our Goals
✍️
Enable organizations to write their own plugins
🚀
Simultaneous release on all platforms
⚙️
Overwrite the standard functionality
📱
Mobile UI/UX & offline support
Shell
Admin panel
Bundels
Native dependencies
Navigation (react-navigation)
- react-native-screens
- react-native-safe-area-context
- react-native-gesture-handler
Charts
- victory-native
- react-native-svg
Other
- react-native-datetimepicker/datetimepicker
- callstack/react-native-slider
- react-native-vector-icons
- react-native-picker/picker
Custom Bridges
- Database
- Data Updates
- Navigation
- Initial Parameters
- ... and 15 more
Database
Database
SELECT Name FROM Account
SELECT Name FROM Account WHERE Id = "1"
QUERY
Rule_Select [ColumnNames] Rule_from <ObjectName> Rule_where [Expression]
SELECT Name FROM Account WHERE Id = "1"
Lexicel
analyzer
Grammar
parser
Visitor
+ permissions
Database
Data Updates
Account
Product
SELECT Name FROM Account
SELECT * FROM Product
Data Updates
SELECT Name FROM Account
Account
Navigation
Navigation
/**
* @param {Object} params - An object
* that will be passed to the page.
* @param {string} entity - The name of the page.
* @param {string | null} id - The id or null.
* @param {"new" | "view" | "edit"} mode
* - The mode of the page, one of 'new', 'view' or 'edit'.
* @param {"present" | "push"} presentationMode
*- The mode of presentation, either 'present' (default) or 'push'.
*/
navigate(
params: Object,
entity: string,
id: string,
mode: "new" | "view" | "edit",
presentationMode: "present" | "push"
)
Initial Parameters
shell://deeplink/react-app/111?name=Test3&value=Value
- Native method
- Deeplink
Initial Parameters
const App = (initialPrameters) => {...}
initialPrameters = {
"entity": "Widget",
"recordId": "111",
"queryItems": {
"name": "Test3",
"value": "Value"
},
}
Design system
Theme
const DefaultTheme: Theme = {
dark: false,
fonts: {...},
colors: {...},
...
}
Fonts
const fonts = Platform.select({
ios: {
regular: {
fontFamily: 'System',
fontWeight: '400',
},
medium: {
fontFamily: 'System',
fontWeight: '500',
},
light: {
fontFamily: 'System',
fontWeight: '300',
},
thin: {
fontFamily: 'System',
fontWeight: '100',
},
},
web: {...}
}
Colors
colors: {
primary: '#0768FD',
secondary: '#0076AE',
tertiary: '#595959',
background: '#F6F6F6',
surface: '#ffffff',
error: '#E20000',
text: '#000000',
...
}
Colors
Typography
-
Headline
-
Title
-
Paragraph
-
Text
-
Caption
Typography
const styles = StyleSheet.create({
title: {
marginBottom: 15,
color: '#20232a',
fontSize: 30,
fontWeight: 'bold',
},
subTitle: {
marginTop: 10,
color: '#ccc',
fontSize: 30,
}
});
Typography
export const FONT_STYLES = {
heading1: {
marginBottom: 15,
color: '#20232a',
fontSize: 30,
fontWeight: 'bold',
},
body: {
marginTop: 10,
color: '#000',
fontSize: 30,
}
};
const styles = StyleSheet.create({
title: {
...FONT_STYLES.heading1,
fontSize: 31
},
subTitle: {
...FONT_STYLES.body,
color: '#ccc'
}
});
Typography
const StyledText = ({ family, style, ...rest }) => {
const { colors, fonts } = useTheme();
const textColor = colors.text;
const font = fonts[family];
const writingDirection = I18nManager.isRTL ? 'rtl' : 'ltr';
return (
<Text
{...rest}
style={[
{ color: textColor, ...font, textAlign: 'left', writingDirection },
style,
]}
/>
);
};
export default StyledText;
Typography
const theme = {
...
typography: {
text: {
fontSize: 14,
lineHeight: 20,
marginVertical: 2,
letterSpacing: 0.25,
},
caption: {...},
placeholder: {...}
}
}
const Caption = ({syles, ...rest}) => (
const { typography } = useTheme();
<StyledText
{...rest}
family="regular"
style={[typography, props.style]}
/>
);
Components
<TextInput
placeholder="Placeholder"
/>
Components
<TextInput
placeholder="Placeholder"
label="Password"
/>
Components
<TextInput
placeholder="Placeholder"
label="Password"
required
/>
Components
<TextInput
placeholder="Placeholder"
label="Password"
required
asteriskPosition="???"
/>
Components
<TextInput
placeholder="Placeholder"
label={<Text><Text>*</Text> Password</Text>}
/>
Components
<TextInput
placeholder="Placeholder"
label={<Text><Text>*</Text> Password</Text>}
leftIcon="user"
/>
Components
<TextInput
placeholder="Placeholder"
label={<Text><Text>*</Text> Password</Text>}
leftIcon="user"
onLeftIconPress={()=>???}
/>
Components
<TextInput
placeholder="Placeholder"
label={<Text><Text>*</Text> Password</Text>}
LeftElement={
<Icon name="person" size={15} color="#ccc" />
}
/>
Components
<TextInput
placeholder="Placeholder"
label={<Text><Text>*</Text> Password</Text>}
LeftElement={
<Icon name="person" size={15} color="#ccc" />
}
RightElement={
<Icon name="eye-off" size={15} color="#ccc" />
}
/>
Design system
75 component
the 50% are base component
more than
95% codebase
is React Native
Design system
Downsides
There is no ability to use packages with native code for clients
The complexity of the maintenance
The complexity of developers' onboarding
API&Components discovery
🧛🏻♂️ Memory Leaks
Our memory leaks
Third-party library's memory leaks
Clients memory leaks
RN Memory Leak
- RootView
- RNScreen
- ...
Screen 1
Screen 2
Screen N
- RootView
- RNScreen
- ...
Screen 1
Screen 2
Screen N
❌
❌
- RootView 1
- RNScreen 2
- ... n
Screen 1
Screen 2
Screen N
Clients memory leaks
navigate(
...
presentationMode: "push"
)
Clients memory leaks
Clients memory leaks
Clients memory leaks
We: "We don’t need explicit instructions, they can figure it out"
As a result:
Conclusion
26
our widgets
214
client widgets
(52 are on a prod)
Our clients write more widgets than us:
Any Questions?
RN
By Andrii Chubai
RN
- 112