commit: 8630f91a13e8b8f7b56d2cb3dd2b700ad5ebd6f6
parent: b96b5eb32731d60f3f56971aae89db818e2742d2
Author: Roger Braun <roger@rogerbraun.net>
Date: Sun, 30 Oct 2016 16:12:35 +0100
Add favorite-button.
Diffstat:
7 files changed, 85 insertions(+), 11 deletions(-)
diff --git a/src/components/favorite_button/favorite_button.js b/src/components/favorite_button/favorite_button.js
@@ -0,0 +1,22 @@
+const FavoriteButton = {
+ props: [ 'status' ],
+ methods: {
+ favorite () {
+ if (!this.status.favorited) {
+ this.$store.dispatch('favorite', { id: this.status.id})
+ } else {
+ this.$store.dispatch('unfavorite', { id: this.status.id})
+ }
+ }
+ },
+ computed: {
+ classes () {
+ return {
+ 'icon-star-empty': !this.status.favorited,
+ 'icon-star': this.status.favorited
+ }
+ }
+ }
+}
+
+export default FavoriteButton
diff --git a/src/components/favorite_button/favorite_button.vue b/src/components/favorite_button/favorite_button.vue
@@ -0,0 +1,14 @@
+<template>
+ <div>
+ <i :class='classes' class='favorite-button fa' v-on:click.prevent='favorite()'></i>
+ <span v-if='status.fave_num > 0'>{{status.fave_num}}</span>
+ </div>
+</template>
+
+<script src="./favorite_button.js" ></script>
+
+<style>
+ .favorite-button {
+ cursor: pointer
+ }
+</style>
diff --git a/src/components/status/status.js b/src/components/status/status.js
@@ -1,4 +1,5 @@
import Attachment from '../attachment/attachment.vue'
+import FavoriteButton from '../favorite_button/favorite_button.vue'
const Status = {
props: [ 'statusoid' ],
@@ -14,9 +15,9 @@ const Status = {
}
},
components: {
- Attachment
+ Attachment,
+ FavoriteButton
}
}
export default Status
-
diff --git a/src/components/status/status.vue b/src/components/status/status.vue
@@ -23,7 +23,9 @@
<small>{{status.created_at_parsed}}</small>
</h4>
- <div v-html="status.statusnet_html"></div>
+ <p>
+ <div v-html="status.statusnet_html"></div>
+ </p>
<div v-if='status.attachments' class='attachments'>
<attachment :status-id="status.id" :nsfw="status.nsfw" :attachment="attachment" v-for="attachment in status.attachments">
@@ -33,12 +35,12 @@
<div>
<div class='status-actions'>
<div ng-click="toggleReplying()">
- <i class='fa fa-reply'></i>
+ <i class='fa icon-reply'></i>
</div>
<div>
- <i class='fa fa-retweet'></i>
+ <i class='fa icon-retweet'></i>
</div>
- <favorite-button status=status></favorite-button>
+ <favorite-button :status=status></favorite-button>
</div>
<!-- <post-status-form ng-if="replying" toggle="toggleReplying" reply-to-status="status" reply-to="{{status.id}}"></post-status-form> -->
diff --git a/src/modules/statuses.js b/src/modules/statuses.js
@@ -1,5 +1,6 @@
import { map, slice, last, intersectionBy, sortBy, unionBy, toInteger, groupBy, differenceBy, each, find } from 'lodash'
import moment from 'moment'
+import apiService from '../services/api/api.service.js'
const defaultState = {
allStatuses: [],
@@ -104,6 +105,18 @@ const updateTimestampsInStatuses = (statuses) => {
const statuses = {
state: defaultState,
+ actions: {
+ favorite ({ rootState, commit }, status) {
+ // Optimistic favoriting...
+ commit('setFavorited', { status, value: true })
+ apiService.favorite({ id: status.id, credentials: rootState.users.currentUser.credentials })
+ },
+ unfavorite ({ rootState, commit }, status) {
+ // Optimistic favoriting...
+ commit('setFavorited', { status, value: false })
+ apiService.unfavorite({ id: status.id, credentials: rootState.users.currentUser.credentials })
+ }
+ },
mutations: {
addNewStatuses (state, { statuses, showImmediately = false, timeline }) {
state.timelines[timeline] = addStatusesToTimeline(statuses, showImmediately, state.timelines[timeline])
@@ -118,6 +131,10 @@ const statuses = {
updateTimestamps (state) {
updateTimestampsInStatuses(state.allStatuses)
},
+ setFavorited (state, { status, value }) {
+ const newStatus = find(state.allStatuses, status)
+ newStatus.favorited = value
+ },
setNsfw (state, { id, nsfw }) {
// For now, walk through all the statuses because the stuff might be in the replied_to_status
// TODO: Save the replied_tos as references.
diff --git a/src/modules/users.js b/src/modules/users.js
@@ -25,7 +25,10 @@ const users = {
.then((response) => {
if (response.ok) {
response.json()
- .then((user) => commit('setCurrentUser', user))
+ .then((user) => {
+ user.credentials = userCredentials
+ commit('setCurrentUser', user)
+ })
.then(() => timelineFetcher.startFetching({store, credentials: userCredentials}))
}
commit('endLogin')
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
@@ -3,11 +3,11 @@ const LOGIN_URL = '/api/account/verify_credentials.json'
const FRIENDS_TIMELINE_URL = '/api/statuses/friends_timeline.json'
const PUBLIC_TIMELINE_URL = '/api/statuses/public_timeline.json'
const PUBLIC_AND_EXTERNAL_TIMELINE_URL = '/api/statuses/public_and_external_timeline.json'
+const FAVORITE_URL = '/api/favorites/create'
+const UNFAVORITE_URL = '/api/favorites/destroy'
// const CONVERSATION_URL = '/api/statusnet/conversation/';
// const STATUS_UPDATE_URL = '/api/statuses/update.json';
// const MEDIA_UPLOAD_URL = '/api/statusnet/media/upload';
-// const FAVORITE_URL = '/api/favorites/create';
-// const UNFAVORITE_URL = '/api/favorites/destroy';
// const FORM_CONTENT_TYPE = {'Content-Type': 'application/x-www-form-urlencoded'};
@@ -43,9 +43,25 @@ const verifyCredentials = (user) => {
})
}
+const favorite = ({ id, credentials }) => {
+ return fetch(`${FAVORITE_URL}/${id}.json`, {
+ headers: authHeaders(credentials),
+ method: 'POST'
+ })
+}
+
+const unfavorite = ({ id, credentials }) => {
+ return fetch(`${UNFAVORITE_URL}/${id}.json`, {
+ headers: authHeaders(credentials),
+ method: 'POST'
+ })
+}
+
const apiService = {
verifyCredentials,
- fetchTimeline
+ fetchTimeline,
+ favorite,
+ unfavorite
}
export default apiService
@@ -104,7 +120,6 @@ export default apiService
// });
// };
-// const favorite = (id) => $http.post(`${FAVORITE_URL}/${id}.json`, null, {headers: authHeaders});
// const unfavorite = (id) => $http.post(`${UNFAVORITE_URL}/${id}.json`, null, {headers: authHeaders});
// // This was impossible to get to work with $http. You're supposed to set Content-Type