Presentación

Firebase Auth

Cloud Firestore

Cloud Storage

Cloud Functions

Curso Firebase para Web se encuentra en desarrollo. Vuelve pronto para encontrar nuevas lecciones.

  • Como punto de partida tenemos que realizar varios ajustes en nuestra store. Más concretamente en el módulo user.js para gestionar los metadatos del usuario donde guardaremos la sala a la que está conectado y cuándo fue la última conexión. Adeás haremos uso de los nuevos métodos Firestore para tratar con matrices.
const actions = {
  async updateMeta(context, { roomID, exit, uid }) {
    const ref = db.collection("users").doc(uid);
    const userDoc = await ref.get();
    if (!userDoc.exists) await ref.set({});
    const method = exit ? "arrayRemove" : "arrayUnion";
    await ref.update({
      connected: firebase.firestore.FieldValue[method](roomID),
      [`joined.${roomID}`]: Date.now(),
    });
  },

  async getMeta({ state, commit }) {
    const ref = db.collection("users").doc(state.user.uid);
    await ref.update({ connected: [] });
    const query = ref.onSnapshot(doSnapshot);
    commit("setUserListener", query);
    function doSnapshot(doc) {
      commit("setMeta", doc.data());
    }
  },
};
  • Ahora debemos invocar la acción updateMeta al acceder y al salir de nuestro componente/vista ViewRoom.vue.
async created() {
  this.userUid = this.$store.state.user.user.uid; // IMPORTANTE 🔥
  try {
    await this.$store.dispatch("user/updateMeta", {
      roomID: this.id,
      exit: false,
      uid: this.userUid
    });
    ...
  } catch (error) {
    ...
  }
},

async destroyed() {
  try {
    await this.$store.dispatch("user/updateMeta", {
      roomID: this.id,
      exit: true,
      uid: this.userUid
    });
  } catch (error) {
    ...
  }
},
  • Ya no podemos seguir escuchando los mensajes sólo cuando estamos conectados a una sala de conversación, sino que debemos hacerlo siempre. Es la única forma de saber si hay mensajes nuevos para un usuario que no está conectado a ninguna sala.
  • Debemos ajustar nuestro módulo messages.js para hacer uso de collectionGroup.
const actions = {
  async getMessages({ commit }) {
    const query = db
      .collectionGroup("messages") // IMPORTANTE 🔥
      .orderBy("createdAt", "desc")
      .onSnapshot(doSnapShot);
      ...
    }
  },

  async createMessage({ rootState }, { roomID, message }) {
    await db
      .collection("rooms")
      .doc(roomID)
      .collection("messages")
      .add({
        ...
        userName: rootState.user.user.displayName,
        roomId: roomID, // IMPORTANTE 🔥
        message,
        ...
      });
  }
};
  • Con todo listo debemos decicir qué mensajes se consideran "no leídos" para el usuario. La forma más sencilla es crear una propiedad computada en RoomsView.vue y pasarle la información como custom prop al componente RoomsComponent.vue.
<RoomsComponent :unread-messages="unreadMessages" :rooms="rooms" />

export default {
  name: "RoomsView",
  computed: {
    ...
    ...mapState("messages", ["messages"]),
    unreadMessages() {
      return this.messages.filter(message => {
        return (
          // User participated
          this.meta.joined[message.roomId] &&
          // Message sent after user last connection
          this.meta.joined[message.roomId] < message.createdAt
        );
      });
    }
  },
  components: {
    RoomsComponent
  }
};
  • Ya casi lo tenemos. En este momento debemos ir al componente RoomsComponent.vue y actuar con la nueva información de mensajes sin leer mostrando la alerta. Todo depende de un nuevo método que indique si cada sala de conversación tiene mensajes sin leer.
methods: {
    hasUnreadMessages(roomId) {
        return this.unreadMessages.filter(message => {
            return message.roomId === roomId;
        });
    }
}
  • Por último queda ajustar nuestra de store index.js para invocar y desactivar los módulos cuando haya y no haya autentificación respectivamente.
actions: {
    checkAuth({ dispatch, commit }) {
        auth.onAuthStateChanged(async function(user) {
        if (user) {
            commit("user/setUser", user);
            try {
                await dispatch("user/getMeta");
                await dispatch("rooms/getRooms");
                await dispatch("messages/getMessages");
            } catch (error) {
                ...
            }
        } else {
            commit("user/setMeta", {});
            commit("user/setUserListener", () => {});
            commit("rooms/setRooms", []);
            commit("rooms/setRoomsListener", () => {});
            commit("messages/setMessages", []);
            commit("messages/setMessagesListener", () => {});
            commit("user/setUser", null);
        }
        });
    }
},
Storyblok: el primer CMS headless tanto para desarrolladores como para marketers

El primer headless CMS tanto para desarrolladores como para marketers. Pruébalo gratis.

Código inicial
Aprende Firebase en Escuela Vue

¿Tienes alguna pregunta sobre esta lección de Curso Firebase para Web?

Resuelve todas tus dudas sobre Firebase en la Comunidad de Escuela Vue: un lugar donde participar, aprender y ayudar. ¡Te esperamos!.

Tras el registro (si no lo has hecho ya) serás redirigido/a al canal adecuado en la Comunidad.

Twitter

Sigue el día a día y todo lo relacionado con Escuela Vue a través de su cuenta de Twitter.

Discord

En la Comunidad de Escuela Vue podrás solucionar tus dudas y ayudar a otras personas como tú a solucionar las suyas.

Recibe novedades en tu 📬