DiscoverPlaces Raport #11 – dodawanie komentarzy, poprawienie wyglądu aplikacji

Czas na przedostatni raport na temat tworzenia projektu DiscoverPlaces, a w nim komponent tworzenia komentarza oraz zmiana wyglądu aplikacji.

Tworzenie komentarza

Komponent tworzenia komentarza jest bardzo podobny do tego służącego do dodawania nowej wiadomości. Dużą zaletę stanowi tutaj fakt, że poprzednio tworząc komponent tworzenia wiadomości, pola odpowiedzialne za wybór zdjęcia oraz wideo, zostały wyodrębnione do osobnych komponentów, co pozwala na użycie ich również w tym komponencie. Poniżej można zobaczyć kod:

import React, { Component } from 'react';
import { View, Text } from 'react-native';
import { createComment, HTTP_CREATED } from './../../config/api';
import update from 'immutability-helper';
import { FormLabel, FormInput, Button } from 'react-native-elements';
import PhotoPicker from './../Utils/PhotoPicker';
import VideoPicker from './../Utils/VideoPicker';
import { COLORS, STYLES } from './../../config/style';

export default class Creator extends Component
{
  constructor (props) {
    super(props);

    this.state = {
      messageId: props.messageId,
      comment: {
        content: null,
        photo: null,
        video: null
      }
    };
  }

  updateField (property, value) {
    if (!this.state.comment.hasOwnProperty(property)) {
      return;
    }

    const comment = update(this.state.comment, {[property]: {
      $set: value
    }});

    this.setState({
      comment: comment
    });
    this.validate();
  }

  handlePick (target, source) {
    const comment = update(this.state.comment, {[target]: {
      $set: source
    }});

    this.setState({
      comment: comment
    });
    this.validate();
  }

  validate () {
    if (
      (this.state.comment.content && this.state.comment.content !== '')
      || this.state.comment.photo
      || this.state.comment.video
    ) {
      this.setState({valid: true});
    } else {
      this.setState({valid: false});
    }
  }

  submit () {
    this.validate();
    if (!this.state.valid) {
      return false;
    }

    createComment(this.state.messageId, this.state.comment)
      .then(response =>  {
        if (response.status === HTTP_CREATED) {
          this.props.onCreate();
        }
      });
  }

  render () {
    return (
      <View>
        {!this.state.valid &&
          <Text
            style={STYLES.error}
          >
              You have to add content, photo or video
            </Text>
        }
        <FormLabel>Content</FormLabel>
        <FormInput
          onChangeText={(content) => this.updateField('content', content)}
          value={this.state.comment.content}
        />
        <PhotoPicker
          onPick={this.handlePick.bind(this)}
        />
        <VideoPicker
          onPick={this.handlePick.bind(this)}
        />
        <Button
          buttonStyle={STYLES.submit}
          title="Add comment"
          icon={{name: 'plus', type: 'font-awesome'}}
          backgroundColor={COLORS.blue}
          onPress={this.submit.bind(this)}
        />
      </View>
    );
  }
}

Tutaj dodatkowo przez props przekazywana jest metoda onCreate(), która następnie jest wywoływana po dodaniu komentarza. Jej implementacja znajduje się w komponencie List, odpowiedzialnym za wyświetlanie listy wiadomości. Za zadanie ma odświeżenie wiadomości oraz komentarzy po dodaniu nowego komentarza. Dlatego odświeżenie wiadomości, ponieważ w API mamy tylko jeden endpoint, który zwraca wiadomości wraz z komentarzami. Gdyby tych wiadomości było bardzo dużo można byłoby tutaj pokusić się o stworzenie paginacji oraz endpoint do wczytywania pojedynczej wiadomości, co pozwoliłoby po dodaniu komentarza odświeżyć tylko jedną wiadomość.

Zmiana wyglądu aplikacji

Z racji iż prototyp aplikacji to były po prostu elementy z paczki react-native-elements wstawiane z kolorami jakie akurat mi przyszły na myśl, to pasowało to jakoś ładniej ułożyć. W tym celu utworzyłem sobie plik style.js, w którym zamieściłem kolory oraz obiekt styli, które następnie są wstawiane w odpowiednich miejscach:

import { StyleSheet } from 'react-native';

export const COLORS = {
  blue: '#43A9B8',
  black: '#0C090D',
  yellow: '#F9C22E',
  orange: '#F15946',
  pink: '#E01A4F'
};

export const STYLES = StyleSheet.create({
  error: {
    marginTop: 20,
    marginBottom: 10,
    marginLeft: 20,
    marginRight: 20,
    padding: 5,
    textAlign: 'center',
    backgroundColor: COLORS.pink,
    color: 'white'
  },
  picker: {
    marginLeft: 10,
    marginRight: 10
  },
  submit: {
    marginTop: 10,
    marginBottom: 10
  },
  createMessageButton: {
    marginTop: 20,
    marginBottom: 5
  },
  attachmentPreviewButton: {
    padding: 5,
    marginTop: -10,
    marginRight: -10
  },
  messageContent: {
    marginTop: 20,
    marginBottom: 20
  },
  commentContent: {
    marginTop: 10,
    marginBottom: 10
  },
  toggleCommentsButton: {
    marginTop: 10
  },
  modalView: {
    margin: 0
  },
  closeButton: {
    position: 'absolute',
    top: 0,
    right: 0,
    zIndex: 9999
  }
});

Cudów z wyglądem nie ma, ale tragedii myślę też nie. Trochę się wkopałem z tym react-native-elements, bo z tego co później znalazłem to są jakieś fajniejsze rzeczy do użycia, a stylowania od zera to po prostu nienawidzę. Nigdy nie mogę się zdecydować na jakąś wersję, przez co zwykle jest to przekombinowane.

Dalsze plany

Zamierzam jeszcze dorzucić tutaj jakiś loader, żeby było wiadomo, że na przykład w danym momencie wczytywane są wiadomości czy trwa przesyłanie zdjęcia na serwer. Dodatkowo pozostaje kwestia poprawienia kilku bugów oraz sprawdzenie tego na fizycznym urządzeniu.

Udostępnij: