Add public stream to profile page

Signed-off-by: Julius Härtl <jus@bitgrid.net>
alpha1
Julius Härtl 2018-12-05 10:50:37 +01:00
rodzic 9d71a7b50c
commit c3bd113694
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4C614C6ED2CDE6DF
6 zmienionych plików z 164 dodań i 132 usunięć

Wyświetl plik

@ -499,9 +499,7 @@ export default {
this.$store.dispatch('post', this.getPostData()).then((response) => { this.$store.dispatch('post', this.getPostData()).then((response) => {
this.post = '' this.post = ''
this.$refs.composerInput.innerText = this.post this.$refs.composerInput.innerText = this.post
this.$store.dispatch('refreshTimeline', { this.$store.dispatch('refreshTimeline')
account: this.currentUser.uid
})
}) })
}, },
remoteSearch(text) { remoteSearch(text) {

Wyświetl plik

@ -7,15 +7,20 @@
<avatar v-else :size="32" :url="avatarUrl" /> <avatar v-else :size="32" :url="avatarUrl" />
</div> </div>
<div class="post-content"> <div class="post-content">
{{ item.account_info }}
<div class="post-author-wrapper"> <div class="post-author-wrapper">
<router-link v-if="item.actor_info && item.local" :to="{ name: 'profile', params: { account: item.actor_info.preferredUsername }}"> <router-link v-if="item.actor_info && item.local" :to="{ name: 'profile', params: { account: item.actor_info.preferredUsername }}">
<span class="post-author">{{ item.actor_info.preferredUsername }}</span> <span class="post-author">{{ item.actor_info.preferredUsername }}</span>
<span class="post-author-id">{{ item.actor_info.account }}</span> <span class="post-author-id">{{ item.actor_info.account }}</span>
</router-link> </router-link>
<a v-else :href="item.actor_info.url"> <a v-else-if="item.actor_info" :href="item.actor_info.url">
<span class="post-author">{{ item.actor_info.preferredUsername }}</span> <span class="post-author">{{ item.actor_info.preferredUsername }}</span>
<span class="post-author-id">{{ item.actor_info.account }}</span> <span class="post-author-id">{{ item.actor_info.account }}</span>
</a> </a>
<a v-else :href="item.attributedTo">
<span class="post-author-id">{{ item.attributedTo }}</span>
</a>
</div> </div>
<div class="post-message" v-html="formatedMessage" /> <div class="post-message" v-html="formatedMessage" />
</div> </div>

Wyświetl plik

@ -0,0 +1,122 @@
<!--
- @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
-
- @author Julius Härtl <jus@bitgrid.net>
-
- @license GNU AGPL version 3 or any later version
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-->
<template>
<div class="social__timeline">
<timeline-entry v-for="entry in timeline" :item="entry" :key="entry.id" />
<infinite-loading ref="infiniteLoading" @infinite="infiniteHandler">
<div slot="spinner"><div class="icon-loading" /></div>
<div slot="no-more"><div class="list-end" /></div>
<div slot="no-results">
<empty-content :item="emptyContentData" />
</div>
</infinite-loading>
</div>
</template>
<script>
import {
PopoverMenu,
AppNavigation,
Multiselect
} from 'nextcloud-vue'
import InfiniteLoading from 'vue-infinite-loading'
import TimelineEntry from './../components/TimelineEntry'
import Composer from './../components/Composer'
import CurrentUserMixin from './../mixins/currentUserMixin'
import EmptyContent from './../components/EmptyContent'
export default {
name: 'Timeline',
components: {
PopoverMenu,
AppNavigation,
TimelineEntry,
Multiselect,
Composer,
InfiniteLoading,
EmptyContent
},
mixins: [CurrentUserMixin],
data: function() {
return {
infoHidden: false,
state: [],
emptyContent: {
default: {
image: 'img/undraw/posts.svg',
title: t('social', 'No posts found'),
description: t('social', 'Posts from people you follow will show up here')
},
direct: {
image: 'img/undraw/direct.svg',
title: t('social', 'No direct messages found'),
description: t('social', 'Posts directed to you will show up here')
},
timeline: {
image: 'img/undraw/local.svg',
title: t('social', 'No local posts found'),
description: t('social', 'Posts from other people on this instance will show up here')
},
federated: {
image: 'img/undraw/global.svg',
title: t('social', 'No global posts found'),
description: t('social', 'Posts from federated instances will show up here')
}
}
}
},
computed: {
emptyContentData() {
if (typeof this.emptyContent[this.$route.params.type] !== 'undefined') {
return this.emptyContent[this.$route.params.type]
}
return this.emptyContent.default
},
timeline: function() {
return this.$store.getters.getTimeline
}
},
beforeMount: function() {
},
methods: {
infiniteHandler($state) {
this.$store.dispatch('fetchTimeline', {
account: this.currentUser.uid
}).then((response) => {
if (response.status === -1) {
OC.Notification.showTemporary('Failed to load more timeline entries')
console.error('Failed to load more timeline entries', response)
$state.complete()
return
}
response.result.length > 0 ? $state.loaded() : $state.complete()
}).catch((error) => {
OC.Notification.showTemporary('Failed to load more timeline entries')
console.error('Failed to load more timeline entries', error)
$state.complete()
})
}
}
}
</script>

Wyświetl plik

@ -26,7 +26,8 @@ import Vue from 'vue'
const state = { const state = {
timeline: {}, timeline: {},
since: Math.floor(Date.now() / 1000) + 1, since: Math.floor(Date.now() / 1000) + 1,
type: 'home' type: 'home',
account: ''
} }
const mutations = { const mutations = {
addToTimeline(state, data) { addToTimeline(state, data) {
@ -41,6 +42,9 @@ const mutations = {
}, },
setTimelineType(state, type) { setTimelineType(state, type) {
state.type = type state.type = type
},
setAccount(state, account) {
state.account = account
} }
} }
const getters = { const getters = {
@ -54,6 +58,12 @@ const actions = {
changeTimelineType(context, type) { changeTimelineType(context, type) {
context.commit('resetTimeline') context.commit('resetTimeline')
context.commit('setTimelineType', type) context.commit('setTimelineType', type)
context.commit('setAccount', '')
},
changeTimelineTypeAccount(context, account) {
context.commit('resetTimeline')
context.commit('setTimelineType', 'account')
context.commit('setAccount', account)
}, },
post(context, post) { post(context, post) {
return axios.post(OC.generateUrl('apps/social/api/v1/post'), { data: post }).then((response) => { return axios.post(OC.generateUrl('apps/social/api/v1/post'), { data: post }).then((response) => {
@ -64,14 +74,20 @@ const actions = {
console.error('Failed to create a post', error) console.error('Failed to create a post', error)
}) })
}, },
refreshTimeline(context, account) { refreshTimeline(context) {
return this.dispatch('fetchTimeline', { account: account, sinceTimestamp: Math.floor(Date.now() / 1000) + 1 }) return this.dispatch('fetchTimeline', { sinceTimestamp: Math.floor(Date.now() / 1000) + 1 })
}, },
fetchTimeline(context, { account, sinceTimestamp }) { fetchTimeline(context, { sinceTimestamp }) {
if (typeof sinceTimestamp === 'undefined') { if (typeof sinceTimestamp === 'undefined') {
sinceTimestamp = state.since - 1 sinceTimestamp = state.since - 1
} }
return axios.get(OC.generateUrl(`apps/social/api/v1/stream/${state.type}?limit=5&since=` + sinceTimestamp)).then((response) => { let url
if (state.type === 'account') {
url = OC.generateUrl(`apps/social/api/v1/account/${state.account}/stream?limit=25&since=` + sinceTimestamp)
} else {
url = OC.generateUrl(`apps/social/api/v1/stream/${state.type}?limit=25&since=` + sinceTimestamp)
}
return axios.get(url).then((response) => {
if (response.status === -1) { if (response.status === -1) {
throw response.message throw response.message
} }

Wyświetl plik

@ -21,30 +21,26 @@
--> -->
<template> <template>
<div class="social__timeline"> <timeline-list />
<timeline-entry v-for="entry in timeline" :item="entry" :key="entry.id" />
</div>
</template> </template>
<style scoped> <style scoped>
.social__timeline {
max-width: 600px;
margin: 15px auto;
}
</style> </style>
<script> <script>
import TimelineEntry from './../components/TimelineEntry' import TimelineList from './../components/TimelineList'
export default { export default {
name: 'ProfileTimeline', name: 'ProfileTimeline',
components: { components: {
TimelineEntry TimelineList
}, },
computed: { computed: {
timeline: function() {
return this.$store.getters.getTimeline },
} beforeMount: function() {
this.$store.dispatch('changeTimelineTypeAccount', this.$route.params.account)
} }
} }
</script> </script>

Wyświetl plik

@ -10,17 +10,8 @@
</p> </p>
</div> </div>
</transition> </transition>
<div class="social__timeline">
<composer /> <composer />
<timeline-entry v-for="entry in timeline" :item="entry" :key="entry.id" /> <timeline-list />
<infinite-loading ref="infiniteLoading" @infinite="infiniteHandler">
<div slot="spinner"><div class="icon-loading" /></div>
<div slot="no-more"><div class="list-end" /></div>
<div slot="no-results">
<empty-content :item="emptyContentData" />
</div>
</infinite-loading>
</div>
</div> </div>
</template> </template>
@ -88,6 +79,7 @@ import TimelineEntry from './../components/TimelineEntry'
import Composer from './../components/Composer' import Composer from './../components/Composer'
import CurrentUserMixin from './../mixins/currentUserMixin' import CurrentUserMixin from './../mixins/currentUserMixin'
import EmptyContent from './../components/EmptyContent' import EmptyContent from './../components/EmptyContent'
import TimelineList from './../components/TimelineList'
export default { export default {
name: 'Timeline', name: 'Timeline',
@ -98,104 +90,24 @@ export default {
Multiselect, Multiselect,
Composer, Composer,
InfiniteLoading, InfiniteLoading,
EmptyContent EmptyContent,
TimelineList
}, },
mixins: [CurrentUserMixin], mixins: [CurrentUserMixin],
data: function() { data: function() {
return { return {
infoHidden: false, infoHidden: false
state: [],
emptyContent: {
default: {
image: 'img/undraw/posts.svg',
title: t('social', 'No posts found'),
description: t('social', 'Posts from people you follow will show up here')
},
direct: {
image: 'img/undraw/direct.svg',
title: t('social', 'No direct messages found'),
description: t('social', 'Posts directed to you will show up here')
},
timeline: {
image: 'img/undraw/local.svg',
title: t('social', 'No local posts found'),
description: t('social', 'Posts from other people on this instance will show up here')
},
federated: {
image: 'img/undraw/global.svg',
title: t('social', 'No global posts found'),
description: t('social', 'Posts from federated instances will show up here')
}
}
} }
}, },
computed: { computed: {
emptyContentData() {
if (typeof this.emptyContent[this.$route.params.type] !== 'undefined') {
return this.emptyContent[this.$route.params.type]
}
return this.emptyContent.default
},
type: function() { type: function() {
if (this.$route.params.type) { if (this.$route.params.type) {
return this.$route.params.type return this.$route.params.type
} }
return 'home' return 'home'
}, },
url: function() {
return OC.linkTo('social', 'img/nextcloud.png')
},
timeline: function() {
return this.$store.getters.getTimeline
},
showInfo() { showInfo() {
return this.$store.getters.getServerData.firstrun && !this.infoHidden return this.$store.getters.getServerData.firstrun && !this.infoHidden
},
menu: function() {
let defaultCategories = [
{
id: 'social-timeline',
classes: [],
href: '#',
icon: 'icon-category-monitoring',
text: t('social', 'Timeline')
},
{
id: 'social-account',
classes: [],
href: '#',
icon: 'icon-category-user',
text: t('social', 'Profile')
},
{
id: 'social-friends',
classes: [],
href: '#',
icon: 'icon-category-social',
text: t('social', 'Friends')
},
{
id: 'social-favorites',
classes: [],
href: '#',
icon: 'icon-favorite',
text: t('social', 'Favorites')
},
{
id: 'social-direct-messages',
classes: [],
href: '#',
icon: 'icon-comment',
utils: {
counter: 3
},
text: t('social', 'Direct messages')
}
]
return {
items: defaultCategories,
loading: false
}
} }
}, },
beforeMount: function() { beforeMount: function() {
@ -204,23 +116,6 @@ export default {
methods: { methods: {
hideInfo() { hideInfo() {
this.infoHidden = true this.infoHidden = true
},
infiniteHandler($state) {
this.$store.dispatch('fetchTimeline', {
account: this.currentUser.uid
}).then((response) => {
if (response.status === -1) {
OC.Notification.showTemporary('Failed to load more timeline entries')
console.error('Failed to load more timeline entries', response)
$state.complete()
return
}
response.result.length > 0 ? $state.loaded() : $state.complete()
}).catch((error) => {
OC.Notification.showTemporary('Failed to load more timeline entries')
console.error('Failed to load more timeline entries', error)
$state.complete()
})
} }
} }
} }