Evan You před 9 roky
rodič
revize
9ae0ed28c1

+ 2 - 7
examples/chat/components/Message.vue

@@ -2,7 +2,7 @@
   <li class="message-list-item">
     <h5 class="message-author-name">{{ message.authorName }}</h5>
     <div class="message-time">
-      {{ date }}
+      {{ message.timestamp | time }}
     </div>
     <div class="message-text">{{ message.text }}</div>
   </li>
@@ -10,11 +10,6 @@
 
 <script>
 export default {
-  props: ['message'],
-  computed: {
-    date () {
-      return new Date(this.message.timestamp).toLocaleTimeString()
-    }
-  }
+  props: ['message']
 }
 </script>

+ 41 - 0
examples/chat/components/Thread.vue

@@ -0,0 +1,41 @@
+<template>
+  <li
+    class="thread-list-item"
+    :class="{ active: isCurrentThread }"
+    @click="onClick">
+    <h5 class="thread-name">{{ thread.name }}</h5>
+    <div class="thread-time">
+      {{ lastMessage.timestamp | time }}
+    </div>
+    <div class="thread-last-message">
+      {{ lastMessage.text }}
+    </div>
+  </li>
+</template>
+
+<script>
+import vuex from '../vuex'
+
+export default {
+  props: ['thread'],
+  computed: {
+    isCurrentThread () {
+      return this.thread.id === vuex.state.currentThreadID
+    },
+    lastMessage () {
+      let last
+      this.thread.messages.forEach(message => {
+        if (!last || message.timestamp > last.timestamp) {
+          last = message
+        }
+      })
+      return last
+    }
+  },
+  methods: {
+    onClick () {
+      vuex.actions.switchThread(this.thread.id)
+    }
+  }
+}
+</script>

+ 34 - 0
examples/chat/components/ThreadSection.vue

@@ -0,0 +1,34 @@
+<template>
+  <div class="thread-section">
+    <div class="thread-count">
+      <span v-show="unreadCount">
+        Unread threads: {{ unreadCount }}
+      </span>
+    </div>
+    <ul class="thread-list">
+      <thread v-for="thread in threads" :thread="thread"></thread>
+    </ul>
+  </div>
+</template>
+
+<script>
+import vuex from '../vuex'
+import Thread from './Thread.vue'
+
+export default {
+  components: { Thread },
+  computed: {
+    threads () {
+      return vuex.state.threads
+    },
+    unreadCount () {
+      return vuex.state.threads.reduce((count, thread) => {
+        const hasUnread = thread.messages.some(m => !m.isRead)
+        return hasUnread
+          ? count + 1
+          : count
+      }, 0)
+    }
+  }
+}
+</script>

+ 4 - 0
examples/chat/main.js

@@ -2,6 +2,10 @@ import 'babel-polyfill'
 import Vue from 'vue'
 import App from './components/App.vue'
 
+Vue.filter('time', timestamp => {
+  return new Date(timestamp).toLocaleTimeString()
+})
+
 new Vue({
   el: 'body',
   components: { App }

+ 1 - 3
examples/chat/vuex/actions.js

@@ -3,9 +3,7 @@ import * as types from './mutation-types'
 
 export const getAllMessages = () => dispatch => {
   api.getAllMessages(messages => {
-    messages.forEach(message => {
-      dispatch(types.RECEIVE_MESSAGE, message)
-    })
+    dispatch(types.RECEIVE_ALL, messages)
   })
 }
 

+ 1 - 0
examples/chat/vuex/mutation-types.js

@@ -1,2 +1,3 @@
 export const SWITCH_THREAD = 'SWITCH_THREAD'
+export const RECEIVE_ALL = 'RECEIVE_ALL'
 export const RECEIVE_MESSAGE = 'RECEIVE_MESSAGE'

+ 43 - 18
examples/chat/vuex/mutations.js

@@ -3,28 +3,53 @@ import * as types from './mutation-types'
 
 export default {
 
-  [types.RECEIVE_MESSAGE] (state, message) {
-    // reset error message
-    state.errorMessage = null
-    // create new thread if the thread doesn't exist
-    let thread = state.threads.find(t => t.id === message.threadID)
-    if (!thread) {
-      thread = {
-        id: message.threadID,
-        name: message.threadName,
-        messages: []
+  [types.RECEIVE_ALL] (state, messages) {
+    let latestMessage
+    messages.forEach(message => {
+      // create new thread if the thread doesn't exist
+      let thread = state.threads.find(t => t.id === message.threadID)
+      if (!thread) {
+        thread = {
+          id: message.threadID,
+          name: message.threadName,
+          messages: []
+        }
+        state.threads.push(thread)
+      }
+      // mark the latest message
+      if (!latestMessage || message.timestamp > latestMessage.timestamp) {
+        latestMessage = message
       }
-      state.threads.push(thread)
-    }
-    // set current id if no thread is set
-    if (!state.currentThreadID) {
-      state.currentThreadID = thread.id
-    }
+      // add message to thread
+      addMessageToThread(thread, message, state.currentThreadID)
+    })
+    // set initial thread to the one with the latest message
+    setCurrentThread(state, latestMessage.threadID)
+  },
+
+  [types.RECEIVE_MESSAGE] (state, message) {
     // add message
-    thread.messages.push(message)
+    const thread = state.threads.find(t => t.id === message.threadID)
+    addMessageToThread(thread, message, state.currentThreadID)
   },
 
   [types.SWITCH_THREAD] (state, id) {
-    state.currentThreadID = id
+    setCurrentThread(state, id)
   }
 }
+
+function addMessageToThread (thread, message, currentThreadID) {
+  if (!thread.messages.some(m => m.id === message.id)) {
+    // add a `isRead` field
+    message.isRead = message.threadID === currentThreadID
+    thread.messages.push(message)
+  }
+}
+
+function setCurrentThread (state, id) {
+  state.currentThreadID = id
+  const thread = state.threads.find(t => t.id === id)
+  thread.messages.forEach(message => {
+    message.isRead = true
+  })
+}