kopia lustrzana https://github.com/nextcloud/social
Merge pull request #52 from nextcloud-gmbh/frontend-implement-different-streams
Frontend implement different streamspull/56/head
commit
f6f7f2cd6a
|
@ -73,6 +73,9 @@ class ActivityPubController extends Controller {
|
||||||
/** @var MiscService */
|
/** @var MiscService */
|
||||||
private $miscService;
|
private $miscService;
|
||||||
|
|
||||||
|
/** @var NavigationController */
|
||||||
|
private $navigationController;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ActivityPubController constructor.
|
* ActivityPubController constructor.
|
||||||
|
@ -90,11 +93,13 @@ class ActivityPubController extends Controller {
|
||||||
IRequest $request, SocialPubController $socialPubController,
|
IRequest $request, SocialPubController $socialPubController,
|
||||||
ActivityService $activityService, ImportService $importService,
|
ActivityService $activityService, ImportService $importService,
|
||||||
FollowService $followService, ActorService $actorService, NotesRequest $notesRequest,
|
FollowService $followService, ActorService $actorService, NotesRequest $notesRequest,
|
||||||
|
NavigationController $navigationController,
|
||||||
MiscService $miscService
|
MiscService $miscService
|
||||||
) {
|
) {
|
||||||
parent::__construct(Application::APP_NAME, $request);
|
parent::__construct(Application::APP_NAME, $request);
|
||||||
|
|
||||||
$this->socialPubController = $socialPubController;
|
$this->socialPubController = $socialPubController;
|
||||||
|
$this->navigationController = $navigationController;
|
||||||
|
|
||||||
$this->activityService = $activityService;
|
$this->activityService = $activityService;
|
||||||
$this->importService = $importService;
|
$this->importService = $importService;
|
||||||
|
@ -119,10 +124,11 @@ class ActivityPubController extends Controller {
|
||||||
* @param string $username
|
* @param string $username
|
||||||
*
|
*
|
||||||
* @return Response
|
* @return Response
|
||||||
|
* @throws \OC\User\NoUserException
|
||||||
*/
|
*/
|
||||||
public function actor(string $username): Response {
|
public function actor(string $username): Response {
|
||||||
if (!$this->checkSourceActivityStreams()) {
|
if (!$this->checkSourceActivityStreams()) {
|
||||||
return $this->socialPubController->actor($username);
|
return $this->navigationController->public($username);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -326,7 +332,7 @@ class ActivityPubController extends Controller {
|
||||||
private function checkSourceActivityStreams(): bool {
|
private function checkSourceActivityStreams(): bool {
|
||||||
|
|
||||||
// uncomment this line to display the result that would be return to an ActivityPub service (TEST)
|
// uncomment this line to display the result that would be return to an ActivityPub service (TEST)
|
||||||
return true;
|
// return true;
|
||||||
|
|
||||||
if ($this->request->getHeader('Accept')
|
if ($this->request->getHeader('Accept')
|
||||||
=== 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"') {
|
=== 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"') {
|
||||||
|
|
|
@ -95,7 +95,7 @@ class LocalController extends Controller {
|
||||||
* @param MiscService $miscService
|
* @param MiscService $miscService
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
IRequest $request, string $userId, PersonService $personService,
|
IRequest $request, $userId, PersonService $personService,
|
||||||
FollowService $followService, ActorService $actorService,
|
FollowService $followService, ActorService $actorService,
|
||||||
PostService $postService, NoteService $noteService,
|
PostService $postService, NoteService $noteService,
|
||||||
MiscService $miscService
|
MiscService $miscService
|
||||||
|
@ -181,11 +181,11 @@ class LocalController extends Controller {
|
||||||
*
|
*
|
||||||
* @return DataResponse
|
* @return DataResponse
|
||||||
*/
|
*/
|
||||||
public function streamHome(): DataResponse {
|
public function streamHome(int $since = 0, int $limit = 5): DataResponse {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$actor = $this->actorService->getActorFromUserId($this->userId);
|
$actor = $this->actorService->getActorFromUserId($this->userId);
|
||||||
$posts = $this->noteService->getHomeNotesForActor($actor);
|
$posts = $this->noteService->getHomeNotesForActor($actor, $since, $limit);
|
||||||
|
|
||||||
return $this->success($posts);
|
return $this->success($posts);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
|
@ -203,11 +203,11 @@ class LocalController extends Controller {
|
||||||
*
|
*
|
||||||
* @return DataResponse
|
* @return DataResponse
|
||||||
*/
|
*/
|
||||||
public function streamDirect(): DataResponse {
|
public function streamDirect(int $since = 0, int $limit = 5): DataResponse {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$actor = $this->actorService->getActorFromUserId($this->userId);
|
$actor = $this->actorService->getActorFromUserId($this->userId);
|
||||||
$posts = $this->noteService->getDirectNotesForActor($actor);
|
$posts = $this->noteService->getDirectNotesForActor($actor, $since, $limit);
|
||||||
|
|
||||||
return $this->success($posts);
|
return $this->success($posts);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
|
|
|
@ -142,11 +142,12 @@ class NotesRequest extends NotesRequestBuilder {
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getHomeNotesForActorId(string $actorId): array {
|
public function getHomeNotesForActorId(string $actorId, $since, $limit): array {
|
||||||
$qb = $this->getNotesSelectSql();
|
$qb = $this->getNotesSelectSql();
|
||||||
|
|
||||||
$this->rightJoinFollowing($qb);
|
$this->rightJoinFollowing($qb);
|
||||||
$this->limitToActorId($qb, $actorId, 'f');
|
$this->limitToActorId($qb, $actorId, 'f');
|
||||||
|
$this->limitPaginate($qb, $since, $limit);
|
||||||
// $this->leftJoinCacheActors($qb, 'attributed_to');
|
// $this->leftJoinCacheActors($qb, 'attributed_to');
|
||||||
|
|
||||||
$notes = [];
|
$notes = [];
|
||||||
|
@ -192,9 +193,10 @@ class NotesRequest extends NotesRequestBuilder {
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getDirectNotesForActorId(string $actorId): array {
|
public function getDirectNotesForActorId(string $actorId, $since, $limit): array {
|
||||||
$qb = $this->getNotesSelectSql();
|
$qb = $this->getNotesSelectSql();
|
||||||
$this->limitToRecipient($qb, $actorId);
|
$this->limitToRecipient($qb, $actorId);
|
||||||
|
$this->limitPaginate($qb, $since, $limit);
|
||||||
$this->leftJoinCacheActors($qb, 'attributed_to');
|
$this->leftJoinCacheActors($qb, 'attributed_to');
|
||||||
|
|
||||||
$notes = [];
|
$notes = [];
|
||||||
|
|
|
@ -312,8 +312,8 @@ class NoteService implements ICoreService {
|
||||||
*
|
*
|
||||||
* @return Note[]
|
* @return Note[]
|
||||||
*/
|
*/
|
||||||
public function getHomeNotesForActor(Person $actor): array {
|
public function getHomeNotesForActor(Person $actor, $since, $limit): array {
|
||||||
return $this->notesRequest->getHomeNotesForActorId($actor->getId());
|
return $this->notesRequest->getHomeNotesForActorId($actor->getId(), $since, $limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -322,8 +322,8 @@ class NoteService implements ICoreService {
|
||||||
*
|
*
|
||||||
* @return Note[]
|
* @return Note[]
|
||||||
*/
|
*/
|
||||||
public function getDirectNotesForActor(Person $actor): array {
|
public function getDirectNotesForActor(Person $actor, $since, $limit): array {
|
||||||
return $this->notesRequest->getDirectNotesForActorId($actor->getId());
|
return $this->notesRequest->getDirectNotesForActorId($actor->getId(), $since, $limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
46
src/App.vue
46
src/App.vue
|
@ -89,12 +89,22 @@ export default {
|
||||||
{
|
{
|
||||||
id: 'social-timeline',
|
id: 'social-timeline',
|
||||||
classes: [],
|
classes: [],
|
||||||
icon: 'icon-category-monitoring',
|
icon: 'icon-home',
|
||||||
text: t('social', 'Timeline'),
|
text: t('social', 'Home'),
|
||||||
router: {
|
router: {
|
||||||
name: 'timeline'
|
name: 'timeline'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'social-direct-messages',
|
||||||
|
classes: [],
|
||||||
|
router: {
|
||||||
|
name: 'timeline',
|
||||||
|
params: { type: 'direct' }
|
||||||
|
},
|
||||||
|
icon: 'icon-comment',
|
||||||
|
text: t('social', 'Direct messages')
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'social-account',
|
id: 'social-account',
|
||||||
classes: [],
|
classes: [],
|
||||||
|
@ -106,28 +116,28 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'social-friends',
|
id: 'social-spacer',
|
||||||
classes: [],
|
classes: []
|
||||||
href: '#',
|
|
||||||
icon: 'icon-category-social',
|
|
||||||
text: t('social', 'Friends')
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'social-favorites',
|
id: 'social-local',
|
||||||
classes: [],
|
classes: [],
|
||||||
href: '#',
|
icon: 'icon-category-monitoring',
|
||||||
icon: 'icon-favorite',
|
text: t('social', 'Local timeline'),
|
||||||
text: t('social', 'Favorites')
|
router: {
|
||||||
|
name: 'timeline',
|
||||||
|
params: { type: 'timeline' }
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'social-direct-messages',
|
id: 'social-global',
|
||||||
classes: [],
|
classes: [],
|
||||||
href: '#',
|
icon: 'icon-link',
|
||||||
icon: 'icon-comment',
|
text: t('social', 'Global timeline'),
|
||||||
utils: {
|
router: {
|
||||||
counter: 3
|
name: 'timeline',
|
||||||
},
|
params: { type: 'federated' }
|
||||||
text: t('social', 'Direct messages')
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -33,13 +33,13 @@
|
||||||
|
|
||||||
<ul class="user-profile--sections">
|
<ul class="user-profile--sections">
|
||||||
<li>
|
<li>
|
||||||
<router-link to="./" class="icon-category-monitoring">{{ accountInfo.posts }} posts</router-link>
|
<router-link :to="{ name: 'profile', params: { account: $route.params.account }}" class="icon-category-monitoring">{{ accountInfo.posts }} posts</router-link>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<router-link to="./following" class="icon-category-social">{{ accountInfo.following }} following</router-link>
|
<router-link :to="{ name: 'following', params: { account: $route.params.account }}" class="icon-category-social">{{ accountInfo.following }} following</router-link>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<router-link to="./followers" class="icon-category-social">{{ accountInfo.followers }} followers</router-link>
|
<router-link :to="{ name: 'followers', params: { account: $route.params.account }}" class="icon-category-social">{{ accountInfo.followers }} followers</router-link>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -41,6 +41,10 @@ export default new Router({
|
||||||
routes: [
|
routes: [
|
||||||
{
|
{
|
||||||
path: '/:index(index.php/)?apps/social/',
|
path: '/:index(index.php/)?apps/social/',
|
||||||
|
redirect: { name: 'timeline' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/:index(index.php/)?apps/social/timeline/:type?',
|
||||||
components: {
|
components: {
|
||||||
default: Timeline
|
default: Timeline
|
||||||
},
|
},
|
||||||
|
@ -48,7 +52,7 @@ export default new Router({
|
||||||
name: 'timeline'
|
name: 'timeline'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/:index(index.php/)?apps/social/account/:account',
|
path: '/:index(index.php/)?apps/social/account/@:account',
|
||||||
components: {
|
components: {
|
||||||
default: Profile
|
default: Profile
|
||||||
},
|
},
|
||||||
|
@ -78,7 +82,7 @@ export default new Router({
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/:index(index.php/)?apps/social/:account',
|
path: '/:index(index.php/)?apps/social/@:account',
|
||||||
component: Profile,
|
component: Profile,
|
||||||
props: true,
|
props: true,
|
||||||
name: 'public'
|
name: 'public'
|
||||||
|
|
|
@ -25,18 +25,25 @@ import Vue from 'vue'
|
||||||
|
|
||||||
const state = {
|
const state = {
|
||||||
timeline: {},
|
timeline: {},
|
||||||
since: new Date()
|
since: Math.floor(Date.now() / 1000) + 1,
|
||||||
|
type: 'home'
|
||||||
}
|
}
|
||||||
const mutations = {
|
const mutations = {
|
||||||
addToTimeline(state, data) {
|
addToTimeline(state, data) {
|
||||||
for (let item in data) {
|
for (let item in data) {
|
||||||
state.since = data[item].published
|
state.since = data[item].publishedTime
|
||||||
Vue.set(state.timeline, data[item].id, data[item])
|
Vue.set(state.timeline, data[item].id, data[item])
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
addPost(state, data) {
|
addPost(state, data) {
|
||||||
// FIXME: push data we receive to the timeline array
|
// FIXME: push data we receive to the timeline array
|
||||||
// state.timeline.push(data)
|
// state.timeline.push(data)
|
||||||
|
},
|
||||||
|
resetTimeline(state) {
|
||||||
|
state.timeline = {}
|
||||||
|
},
|
||||||
|
setTimelineType(state, type) {
|
||||||
|
state.type = type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const getters = {
|
const getters = {
|
||||||
|
@ -47,6 +54,10 @@ const getters = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const actions = {
|
const actions = {
|
||||||
|
changeTimelineType(context, type) {
|
||||||
|
context.commit('resetTimeline')
|
||||||
|
context.commit('setTimelineType', type)
|
||||||
|
},
|
||||||
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) => {
|
||||||
context.commit('addPost', { data: response.data })
|
context.commit('addPost', { data: response.data })
|
||||||
|
@ -60,9 +71,9 @@ const actions = {
|
||||||
},
|
},
|
||||||
fetchTimeline(context, { account, sinceTimestamp }) {
|
fetchTimeline(context, { account, sinceTimestamp }) {
|
||||||
if (typeof sinceTimestamp === 'undefined') {
|
if (typeof sinceTimestamp === 'undefined') {
|
||||||
sinceTimestamp = Date.parse(state.since) / 1000
|
sinceTimestamp = state.since - 1
|
||||||
}
|
}
|
||||||
return axios.get(OC.generateUrl('apps/social/api/v1/stream/timeline?limit=5&since=' + sinceTimestamp)).then((response) => {
|
return axios.get(OC.generateUrl(`apps/social/api/v1/stream/${state.type}?limit=5&since=` + sinceTimestamp)).then((response) => {
|
||||||
if (response.status === -1) {
|
if (response.status === -1) {
|
||||||
throw response.message
|
throw response.message
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="social__wrapper">
|
<div class="social__wrapper">
|
||||||
|
{{ type }}
|
||||||
<div class="social__container">
|
<div class="social__container">
|
||||||
<transition name="slide-fade">
|
<transition name="slide-fade">
|
||||||
<div v-if="showInfo" class="social__welcome">
|
<div v-if="showInfo" class="social__welcome">
|
||||||
|
@ -124,6 +125,12 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
type: function() {
|
||||||
|
if (this.$route.params.type) {
|
||||||
|
return this.$route.params.type
|
||||||
|
}
|
||||||
|
return 'home'
|
||||||
|
},
|
||||||
url: function() {
|
url: function() {
|
||||||
return OC.linkTo('social', 'img/nextcloud.png')
|
return OC.linkTo('social', 'img/nextcloud.png')
|
||||||
},
|
},
|
||||||
|
@ -181,7 +188,7 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeMount: function() {
|
beforeMount: function() {
|
||||||
|
this.$store.dispatch('changeTimelineType', this.type)
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
hideInfo() {
|
hideInfo() {
|
||||||
|
@ -201,6 +208,7 @@ export default {
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
OC.Notification.showTemporary('Failed to load more timeline entries')
|
OC.Notification.showTemporary('Failed to load more timeline entries')
|
||||||
console.error('Failed to load more timeline entries', error)
|
console.error('Failed to load more timeline entries', error)
|
||||||
|
$state.complete()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Ładowanie…
Reference in New Issue