Compare commits

..

5 Commits

Author SHA1 Message Date
11f25ea2e7 8.31.0 2018-09-08 06:44:34 +09:00
ef62497777 ActivityPub Outboxの修正とactivity idのURLを実装 (#2662)
* Fix Outbox structure

* Implement activity endpoint

* Use in instead of or

* Use in, addition
2018-09-08 05:24:55 +09:00
2824d8a5b6 Add animation 2018-09-08 04:54:11 +09:00
1c84c0828e 良い感じに 2018-09-08 01:46:01 +09:00
39e4494836 🎨 2018-09-08 01:31:50 +09:00
6 changed files with 112 additions and 78 deletions

View File

@ -1,8 +1,8 @@
{ {
"name": "misskey", "name": "misskey",
"author": "syuilo <i@syuilo.com>", "author": "syuilo <i@syuilo.com>",
"version": "8.30.0", "version": "8.31.0",
"clientVersion": "1.0.9481", "clientVersion": "1.0.9486",
"codename": "nighthike", "codename": "nighthike",
"main": "./built/index.js", "main": "./built/index.js",
"private": true, "private": true,

View File

@ -4,9 +4,9 @@
<p class="empty" v-else-if="tags.length == 0">%fa:exclamation-circle%%i18n:@empty%</p> <p class="empty" v-else-if="tags.length == 0">%fa:exclamation-circle%%i18n:@empty%</p>
<div v-else> <div v-else>
<vue-word-cloud <vue-word-cloud
:words="tags.map(x => [x.name, x.count])" :words="tags.slice(0, 20).map(x => [x.name, x.count])"
:color="color" :color="color"
font-family="Roboto"> :spacing="1">
<template slot-scope="{word, text, weight}"> <template slot-scope="{word, text, weight}">
<div style="cursor: pointer;" :title="weight"> <div style="cursor: pointer;" :title="weight">
{{ text }} {{ text }}
@ -50,7 +50,7 @@ export default Vue.extend({
const peak = Math.max.apply(null, this.tags.map(x => x.count)); const peak = Math.max.apply(null, this.tags.map(x => x.count));
const w = weight / peak; const w = weight / peak;
if (w == 1) { if (w > 0.9) {
return this.$store.state.device.darkmode ? '#ff4e69' : '#ff4e69'; return this.$store.state.device.darkmode ? '#ff4e69' : '#ff4e69';
} else if (w > 0.5) { } else if (w > 0.5) {
return this.$store.state.device.darkmode ? '#3bc4c7' : '#3bc4c7'; return this.$store.state.device.darkmode ? '#3bc4c7' : '#3bc4c7';

View File

@ -1,6 +1,7 @@
<template> <template>
<div class="mk-welcome-timeline"> <div class="mk-welcome-timeline">
<div v-for="note in notes"> <transition-group name="ldzpakcixzickvggyixyrhqwjaefknon" tag="div">
<div v-for="note in notes" :key="note.id">
<mk-avatar class="avatar" :user="note.user" target="_blank"/> <mk-avatar class="avatar" :user="note.user" target="_blank"/>
<div class="body"> <div class="body">
<header> <header>
@ -17,6 +18,7 @@
</div> </div>
</div> </div>
</div> </div>
</transition-group>
</div> </div>
</template> </template>
@ -83,9 +85,18 @@ export default Vue.extend({
</script> </script>
<style lang="stylus" scoped> <style lang="stylus" scoped>
.ldzpakcixzickvggyixyrhqwjaefknon-enter
.ldzpakcixzickvggyixyrhqwjaefknon-leave-to
opacity 0
transform translateY(-30px)
root(isDark) root(isDark)
background isDark ? #282C37 : #fff background isDark ? #282C37 : #fff
> div
> *
transition transform .3s ease, opacity .3s ease
> div > div
padding 16px padding 16px
overflow-wrap break-word overflow-wrap break-word

View File

@ -5,7 +5,7 @@ export default (object: any, note: INote) => {
const attributedTo = `${config.url}/users/${note.userId}`; const attributedTo = `${config.url}/users/${note.userId}`;
return { return {
id: `${config.url}/notes/${note._id}`, id: `${config.url}/notes/${note._id}/activity`,
actor: `${config.url}/users/${note.userId}`, actor: `${config.url}/users/${note.userId}`,
type: 'Announce', type: 'Announce',
published: note.createdAt.toISOString(), published: note.createdAt.toISOString(),

View File

@ -10,7 +10,7 @@ import User, { isLocalUser, ILocalUser, IUser } from '../models/user';
import renderNote from '../remote/activitypub/renderer/note'; import renderNote from '../remote/activitypub/renderer/note';
import renderKey from '../remote/activitypub/renderer/key'; import renderKey from '../remote/activitypub/renderer/key';
import renderPerson from '../remote/activitypub/renderer/person'; import renderPerson from '../remote/activitypub/renderer/person';
import Outbox from './activitypub/outbox'; import Outbox, { packActivity } from './activitypub/outbox';
import Followers from './activitypub/followers'; import Followers from './activitypub/followers';
import Following from './activitypub/following'; import Following from './activitypub/following';
@ -77,6 +77,22 @@ router.get('/notes/:note', async (ctx, next) => {
setResponseType(ctx); setResponseType(ctx);
}); });
// note activity
router.get('/notes/:note/activity', async ctx => {
const note = await Note.findOne({
_id: new mongo.ObjectID(ctx.params.note),
visibility: { $in: ['public', 'home'] }
});
if (note === null) {
ctx.status = 404;
return;
}
ctx.body = pack(await packActivity(note));
setResponseType(ctx);
});
// outbox // outbox
router.get('/users/:user/outbox', Outbox); router.get('/users/:user/outbox', Outbox);

View File

@ -8,8 +8,10 @@ import renderOrderedCollection from '../../remote/activitypub/renderer/ordered-c
import renderOrderedCollectionPage from '../../remote/activitypub/renderer/ordered-collection-page'; import renderOrderedCollectionPage from '../../remote/activitypub/renderer/ordered-collection-page';
import { setResponseType } from '../activitypub'; import { setResponseType } from '../activitypub';
import Note from '../../models/note'; import Note, { INote } from '../../models/note';
import renderNote from '../../remote/activitypub/renderer/note'; import renderNote from '../../remote/activitypub/renderer/note';
import renderCreate from '../../remote/activitypub/renderer/create';
import renderAnnounce from '../../remote/activitypub/renderer/announce';
import { countIf } from '../../prelude/array'; import { countIf } from '../../prelude/array';
export default async (ctx: Router.IRouterContext) => { export default async (ctx: Router.IRouterContext) => {
@ -53,15 +55,7 @@ export default async (ctx: Router.IRouterContext) => {
const query = { const query = {
userId: user._id, userId: user._id,
$and: [{ visibility: { $in: ['public', 'home'] }
$or: [ { visibility: 'public' }, { visibility: 'home' } ]
}, { // exclude renote, but include quote
$or: [{
text: { $ne: null }
}, {
fileIds: { $ne: [] }
}]
}]
} as any; } as any;
if (sinceId) { if (sinceId) {
@ -85,10 +79,10 @@ export default async (ctx: Router.IRouterContext) => {
if (sinceId) notes.reverse(); if (sinceId) notes.reverse();
const renderedNotes = await Promise.all(notes.map(note => renderNote(note, false))); const activities = await Promise.all(notes.map(note => packActivity(note)));
const rendered = renderOrderedCollectionPage( const rendered = renderOrderedCollectionPage(
`${partOf}?page=true${sinceId ? `&since_id=${sinceId}` : ''}${untilId ? `&until_id=${untilId}` : ''}`, `${partOf}?page=true${sinceId ? `&since_id=${sinceId}` : ''}${untilId ? `&until_id=${untilId}` : ''}`,
user.notesCount, renderedNotes, partOf, user.notesCount, activities, partOf,
notes.length > 0 ? `${partOf}?page=true&since_id=${notes[0]._id}` : null, notes.length > 0 ? `${partOf}?page=true&since_id=${notes[0]._id}` : null,
notes.length > 0 ? `${partOf}?page=true&until_id=${notes[notes.length - 1]._id}` : null notes.length > 0 ? `${partOf}?page=true&until_id=${notes[notes.length - 1]._id}` : null
); );
@ -105,3 +99,16 @@ export default async (ctx: Router.IRouterContext) => {
setResponseType(ctx); setResponseType(ctx);
} }
}; };
/**
* Pack Create<Note> or Announce Activity
* @param note Note
*/
export async function packActivity(note: INote): Promise<object> {
if (note.renoteId && note.text == null) {
const renote = await Note.findOne(note.renoteId);
return renderAnnounce(renote.uri ? renote.uri : `${config.url}/notes/${renote._id}`, note);
}
return renderCreate(await renderNote(note, false), note);
}