Skip to content

Commit

Permalink
Global timeline
Browse files Browse the repository at this point in the history
  • Loading branch information
mei23 committed May 13, 2020
1 parent cec005d commit ce44005
Show file tree
Hide file tree
Showing 10 changed files with 210 additions and 1 deletion.
1 change: 1 addition & 0 deletions locales/en-US.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ instance: "Instance"
settings: "Settings"
profile: "Profile"
timeline: "Timeline"
globalTimeline: "Global"
noAccountDescription: "This user has not written a profile description"
login: "Login"
loginWaiting: "Logging in"
Expand Down
1 change: 1 addition & 0 deletions locales/ja-JP.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ instance: "インスタンス"
settings: "設定"
profile: "プロフィール"
timeline: "タイムライン"
globalTimeline: "グローバル"
noAccountDescription: "自己紹介はありません"
login: "ログイン"
loginWaiting: "ログイン中"
Expand Down
3 changes: 2 additions & 1 deletion src/client/app.ui.vue
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@
</transition>
<div class="buttons">
<button v-if="$store.getters.isSignedIn" class="button nav _button" @click="() => { navOpen = !navOpen; notificationsOpen = false; }" ref="navButton"><fa :icon="navOpen ? faTimes : faBars"/><i v-if="$store.state.i.hasUnreadSpecifiedNotes || $store.state.i.pendingReceivedFollowRequestsCount"><fa :icon="faCircle"/></i></button>
<button v-if="$store.getters.isSignedIn" class="button home _button" :disabled="$route.path === '/'" @click="$router.push('/')"><fa :icon="faHome"/></button>
<button v-if="$store.getters.isSignedIn && $route.path !== '/'" class="button home _button" @click="$router.push('/')"><fa :icon="faHome"/></button>
<button v-if="$store.getters.isSignedIn && $route.path === '/'" class="button home _button" @click="$router.push('/global')"><fa :icon="faGlobe"/></button>
<button v-if="$store.getters.isSignedIn" class="button notifications _button" @click="notificationsOpen = !notificationsOpen" ref="notificationsButton"><fa :icon="notificationsOpen ? faTimes : faBell"/><i v-if="$store.state.i.hasUnreadNotification"><fa :icon="faCircle"/></i></button>
<button v-if="$store.getters.isSignedIn" class="button post _buttonPrimary" @click="post()"><fa :icon="faPencilAlt"/></button>
</div>
Expand Down
46 changes: 46 additions & 0 deletions src/client/pages/index.global.timeline.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<template>
<x-notes ref="timeline" :pagination="pagination" @before="$emit('before')" @after="e => $emit('after', e)"/>
</template>

<script lang="ts">
import Vue from 'vue';
import XNotes from '../components/notes.vue';
export default Vue.extend({
components: {
XNotes
},
data() {
return {
connection: null,
pagination: null,
};
},
created() {
this.$once('hook:beforeDestroy', () => {
this.connection.dispose();
});
const prepend = note => {
(this.$refs.timeline as any).prepend(note);
};
const onChangeFollowing = () => {
this.fetch();
};
this.connection = this.$root.stream.useSharedConnection('globalTimeline');
this.connection.on('note', prepend);
this.connection.on('follow', onChangeFollowing);
this.connection.on('unfollow', onChangeFollowing);
this.pagination = {
endpoint: 'notes/global-timeline',
limit: 10,
params: {}
};
}
});
</script>
30 changes: 30 additions & 0 deletions src/client/pages/index.global.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<template>
<div class="dp-global">
<x-global-timeline @before="before()" @after="after()"/>
</div>
</template>

<script lang="ts">
import Vue from 'vue';
import Progress from '../scripts/loading';
import XGlobalTimeline from './index.global.timeline.vue';
export default Vue.extend({
metaInfo() {
return {
title: this.$t('globalTimeline')
};
},
components: {
XGlobalTimeline
},
methods: {
before() {
Progress.start();
},
after() {
Progress.done();
}
}
});
</script>
2 changes: 2 additions & 0 deletions src/client/pages/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
<script lang="ts">
import Vue from 'vue';
import Home from './index.home.vue';
import Global from './index.global.vue';
export default Vue.extend({
components: {
Home,
Global,
Welcome: () => import('./index.welcome.vue').then(m => m.default),
}
});
Expand Down
1 change: 1 addition & 0 deletions src/client/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const router = new VueRouter({
mode: 'history',
routes: [
{ path: '/', name: 'index', component: DpIndex },
{ path: '/global', name: 'global', component: () => import('./pages/index.global.vue').then(m => m.default) },
{ path: '/@:user', name: 'user', component: () => import('./pages/user/index.vue').then(m => m.default), children: [
{ path: 'following', name: 'userFollowing', component: () => import('./pages/user/follow-list.vue').then(m => m.default), props: { type: 'following' } },
{ path: 'followers', name: 'userFollowers', component: () => import('./pages/user/follow-list.vue').then(m => m.default), props: { type: 'followers' } },
Expand Down
74 changes: 74 additions & 0 deletions src/server/api/endpoints/notes/global-timeline.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import $ from 'cafy';
import { ID } from '../../../../misc/cafy-id';
import define from '../../define';
import { makePaginationQuery } from '../../common/make-pagination-query';
import { Notes } from '../../../../models';
import { generateMuteQuery } from '../../common/generate-mute-query';

export const meta = {
desc: {
'ja-JP': 'グローバルタイムラインを取得します。'
},

tags: ['notes'],

params: {
withFiles: {
validator: $.optional.bool,
desc: {
'ja-JP': 'ファイルが添付された投稿に限定するか否か'
}
},

limit: {
validator: $.optional.num.range(1, 100),
default: 10
},

sinceId: {
validator: $.optional.type(ID),
},

untilId: {
validator: $.optional.type(ID),
},

sinceDate: {
validator: $.optional.num
},

untilDate: {
validator: $.optional.num
},
},

res: {
type: 'array' as const,
optional: false as const, nullable: false as const,
items: {
type: 'object' as const,
optional: false as const, nullable: false as const,
ref: 'Note',
}
},
};

export default define(meta, async (ps, user) => {
//#region Construct query
const query = makePaginationQuery(Notes.createQueryBuilder('note'),
ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate)
.andWhere('note.visibility = \'public\'')
.andWhere('note.replyId IS NULL')
.leftJoinAndSelect('note.user', 'user');

if (user) generateMuteQuery(query, user);

if (ps.withFiles) {
query.andWhere('note.fileIds != \'{}\'');
}
//#endregion

const timeline = await query.take(ps.limit!).getMany();

return await Notes.packMany(timeline, user);
});
51 changes: 51 additions & 0 deletions src/server/api/stream/channels/global-timeline.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import autobind from 'autobind-decorator';
import shouldMuteThisNote from '../../../../misc/should-mute-this-note';
import Channel from '../channel';
import { Notes } from '../../../../models';
import { PackedNote } from '../../../../models/repositories/note';

export default class extends Channel {
public readonly chName = 'globalTimeline';
public static shouldShare = true;
public static requireCredential = false;

@autobind
public async init(params: any) {
// Subscribe events
this.subscriber.on('notesStream', this.onNote);
}

@autobind
private async onNote(note: PackedNote) {
if (note.visibility !== 'public') return;

// リプライなら再pack
if (note.replyId != null) {
note.reply = await Notes.pack(note.replyId, this.user, {
detail: true
});
}
// Renoteなら再pack
if (note.renoteId != null) {
note.renote = await Notes.pack(note.renoteId, this.user, {
detail: true
});
}

// 返信は除外
if (note.reply) {
return;
}

// 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する
if (shouldMuteThisNote(note, this.muting)) return;

this.send('note', note);
}

@autobind
public dispose() {
// Unsubscribe events
this.subscriber.off('notesStream', this.onNote);
}
}
2 changes: 2 additions & 0 deletions src/server/api/stream/channels/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import main from './main';
import homeTimeline from './home-timeline';
import globalTimeline from './global-timeline';
import queueStats from './queue-stats';
import serverStats from './server-stats';
import userList from './user-list';
Expand All @@ -11,6 +12,7 @@ import admin from './admin';
export default {
main,
homeTimeline,
globalTimeline,
queueStats,
serverStats,
userList,
Expand Down

0 comments on commit ce44005

Please sign in to comment.