state = { selectedUnit: "MB", count: 1, units: {} };
selectedUnit:
Holds currenct selected unit type.
count:
Holds number to be converted.
units:
String identifiers of the possible units.
constructor(props) {
super(props);
this.onUnitChange = this.onUnitChange.bind(this);
this.onCount = this.onCount.bind(this);
}
Binds this
context to onEvents.
componentDidMount() {
this.calculateUnits(this.state.selectedUnit, this.state.count);
}
Runs calculateUnits
method on initializing.
onUnitChange(unit) {
this.setState({ selectedUnit: unit });
this.calculateUnits(unit, this.state.count);
}
Changes selected unit from the state and calculates this unit with given number.
onCount(input) {
const count = [undefined,NaN].indexOf(input) == -1 ? parseInt(input) : 1;
this.setState({ count });
this.calculateUnits(this.state.selectedUnit, count);
}
Handles the on input event of number input. Checks for undefined or NaN type and parses it as integer. If it's not an eligible input gives 1 as default.
renderPicker() {
// I rendered picker externally for quick editing
return (
<Picker
selectedValue={this.state.selectedUnit}
style={styles.picker}
onValueChange={this.onUnitChange}
>
<Picker.Item label={"Bit"} value={"b"} />
// ...
<Picker.Item label={"Terabyte"} value={"TB"} />
</Picker>
);
}
Renders unit picker. Helps clean up the render
method with seperating the block.
calculateUnits(unit, count) {
const units = {
'b': convert(count, unit, 'b'),
// ...
'TB': convert(count, unit, 'TB'),
};
this.setState({ units });
}
Converts given number and unit type to all types and sets it to the state with key-value pairs. Convert function comes with 'data-unit-converter'
npm package. This is a third-party library but it's my package so i think it's not a problem to use in this project.
render() {
return (
<View style={...}>
<View style={...}>
<TextInput ... />
{this.renderPicker()}
</View>
<View style={...}>
<ScrollView>
<UnitRows
count={this.state.count}
from={this.state.selectedUnit}
units={this.state.units} />
</ScrollView>
</View>
</View>
);
}
Default container of the app. Uses one extra component which is <UnitRows />
. It can be found on components directory. <UnitRows />
takes 3 arguments. count
is for the number to be converted. from
is the selected unit type. units
is carries all converted unit types. All directly given from state.
render() {
return <View style={styles.container}>
{Object.keys(this.props.units).map((key, index) => {
return <Row key={index + 1}
unit={key}
value={this.props.units[key]}
count={this.props.count}
from={this.props.from} />
})}
</View>;
}
Renders all types of converted number as its type. Takes units and maps it through a component array. This component array contains <Row/>
component. Row component takes unit type, value as converted value, count as initial number and from which is pickers value from AppComponent.
formatCount(count) {
const formatted = parseFloat(this.props.value).toPrecision(5);
return parseFloat(formatted);
}
Formats given value to give 5 chars of a float number and returns it.
onLongPressed() {
Alert.alert("DataConverter", this.formatCount().toString(), [
{
text: "Copy",
onPress: () => {
Clipboard.setString(`${this.formatCount()} ${this.props.unit}`); // Copy to clipboard with unit name
}
},
{
text: "Share",
onPress: () => {
Share.share({
title: "DataConverter",
message: `${this.props.count} ${this.props.from} equals ${this.props.value} ${this.props.unit}` // Share equality
// Ex. 1 MB equals 1024 KB
});
}
}
]);
}
Opens a dialog window with two buttons. Which are copy
and share
. Copy basically copies pressed unit number to clipboard. Share is just a default share option of the operating systems. Sharing format: 1024MB equals 1GB
.
render() {
const colors = {
b: "#c10e0e",
// ...
TB: "#56a5a0"
};
return (
<TouchableOpacity
activeOpacity={0.75}
onLongPress={this.onLongPressed.bind(this)}
style={..., backgroundColor: colors[this.props.unit]}
>
<View style={...}>
<Text style={...}>{this.formatCount()}</Text>
</View>
<View style={...}>
<Text style={...}>{this.props.unit}</Text>
</View>
</TouchableOpacity>
);
}
Renders a row of unit with a given unit type and value. This defined colors helds a color for each type of unit. We can select a color with units code name, using it as an object key. eg. colors['MB']
gives #68ba16
. Touchable opacity takes onLongPress event as an event listener and opens a dialog window that mention just above.