This commit is contained in:
parent
db943df0c8
commit
a1b82e9723
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "misskey",
|
"name": "misskey",
|
||||||
"author": "syuilo <i@syuilo.com>",
|
"author": "syuilo <i@syuilo.com>",
|
||||||
"version": "8.26.0",
|
"version": "9.0.0",
|
||||||
"clientVersion": "1.0.9358",
|
"clientVersion": "1.0.9358",
|
||||||
"codename": "nighthike",
|
"codename": "nighthike",
|
||||||
"main": "./built/index.js",
|
"main": "./built/index.js",
|
||||||
|
|
|
@ -1,53 +0,0 @@
|
||||||
export default function(qs: string) {
|
|
||||||
const q = {
|
|
||||||
text: ''
|
|
||||||
};
|
|
||||||
|
|
||||||
qs.split(' ').forEach(x => {
|
|
||||||
if (/^([a-z_]+?):(.+?)$/.test(x)) {
|
|
||||||
const [key, value] = x.split(':');
|
|
||||||
switch (key) {
|
|
||||||
case 'user':
|
|
||||||
q['includeUserUsernames'] = value.split(',');
|
|
||||||
break;
|
|
||||||
case 'exclude_user':
|
|
||||||
q['excludeUserUsernames'] = value.split(',');
|
|
||||||
break;
|
|
||||||
case 'follow':
|
|
||||||
q['following'] = value == 'null' ? null : value == 'true';
|
|
||||||
break;
|
|
||||||
case 'reply':
|
|
||||||
q['reply'] = value == 'null' ? null : value == 'true';
|
|
||||||
break;
|
|
||||||
case 'renote':
|
|
||||||
q['renote'] = value == 'null' ? null : value == 'true';
|
|
||||||
break;
|
|
||||||
case 'media':
|
|
||||||
q['media'] = value == 'null' ? null : value == 'true';
|
|
||||||
break;
|
|
||||||
case 'poll':
|
|
||||||
q['poll'] = value == 'null' ? null : value == 'true';
|
|
||||||
break;
|
|
||||||
case 'until':
|
|
||||||
case 'since':
|
|
||||||
// YYYY-MM-DD
|
|
||||||
if (/^[0-9]+\-[0-9]+\-[0-9]+$/) {
|
|
||||||
const [yyyy, mm, dd] = value.split('-');
|
|
||||||
q[`${key}_date`] = (new Date(parseInt(yyyy, 10), parseInt(mm, 10) - 1, parseInt(dd, 10))).getTime();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
q[key] = value;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
q.text += x + ' ';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (q.text) {
|
|
||||||
q.text = q.text.trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
return q;
|
|
||||||
}
|
|
|
@ -63,7 +63,7 @@ export default Vue.extend({
|
||||||
local: true,
|
local: true,
|
||||||
reply: false,
|
reply: false,
|
||||||
renote: false,
|
renote: false,
|
||||||
media: false,
|
file: false,
|
||||||
poll: false
|
poll: false
|
||||||
}).then(notes => {
|
}).then(notes => {
|
||||||
this.notes = notes;
|
this.notes = notes;
|
||||||
|
|
|
@ -42,8 +42,8 @@
|
||||||
<span v-if="p.deletedAt" style="opacity: 0.5">%i18n:@deleted%</span>
|
<span v-if="p.deletedAt" style="opacity: 0.5">%i18n:@deleted%</span>
|
||||||
<misskey-flavored-markdown v-if="p.text" :text="p.text" :i="$store.state.i"/>
|
<misskey-flavored-markdown v-if="p.text" :text="p.text" :i="$store.state.i"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="media" v-if="p.media.length > 0">
|
<div class="files" v-if="p.files.length > 0">
|
||||||
<mk-media-list :media-list="p.media" :raw="true"/>
|
<mk-media-list :media-list="p.files" :raw="true"/>
|
||||||
</div>
|
</div>
|
||||||
<mk-poll v-if="p.poll" :note="p"/>
|
<mk-poll v-if="p.poll" :note="p"/>
|
||||||
<mk-url-preview v-for="url in urls" :url="url" :key="url" :detail="true"/>
|
<mk-url-preview v-for="url in urls" :url="url" :key="url" :detail="true"/>
|
||||||
|
@ -114,7 +114,7 @@ export default Vue.extend({
|
||||||
isRenote(): boolean {
|
isRenote(): boolean {
|
||||||
return (this.note.renote &&
|
return (this.note.renote &&
|
||||||
this.note.text == null &&
|
this.note.text == null &&
|
||||||
this.note.mediaIds.length == 0 &&
|
this.note.fileIds.length == 0 &&
|
||||||
this.note.poll == null);
|
this.note.poll == null);
|
||||||
},
|
},
|
||||||
p(): any {
|
p(): any {
|
||||||
|
|
|
@ -28,8 +28,8 @@
|
||||||
<misskey-flavored-markdown v-if="p.text" :text="p.text" :i="$store.state.i" :class="$style.text"/>
|
<misskey-flavored-markdown v-if="p.text" :text="p.text" :i="$store.state.i" :class="$style.text"/>
|
||||||
<a class="rp" v-if="p.renote">RP:</a>
|
<a class="rp" v-if="p.renote">RP:</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="media" v-if="p.media.length > 0">
|
<div class="files" v-if="p.files.length > 0">
|
||||||
<mk-media-list :media-list="p.media"/>
|
<mk-media-list :media-list="p.files"/>
|
||||||
</div>
|
</div>
|
||||||
<mk-poll v-if="p.poll" :note="p" ref="pollViewer"/>
|
<mk-poll v-if="p.poll" :note="p" ref="pollViewer"/>
|
||||||
<a class="location" v-if="p.geo" :href="`https://maps.google.com/maps?q=${p.geo.coordinates[1]},${p.geo.coordinates[0]}`" target="_blank">%fa:map-marker-alt% 位置情報</a>
|
<a class="location" v-if="p.geo" :href="`https://maps.google.com/maps?q=${p.geo.coordinates[1]},${p.geo.coordinates[0]}`" target="_blank">%fa:map-marker-alt% 位置情報</a>
|
||||||
|
@ -110,7 +110,7 @@ export default Vue.extend({
|
||||||
isRenote(): boolean {
|
isRenote(): boolean {
|
||||||
return (this.note.renote &&
|
return (this.note.renote &&
|
||||||
this.note.text == null &&
|
this.note.text == null &&
|
||||||
this.note.mediaIds.length == 0 &&
|
this.note.fileIds.length == 0 &&
|
||||||
this.note.poll == null);
|
this.note.poll == null);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -122,7 +122,7 @@ export default Vue.extend({
|
||||||
prepend(note, silent = false) {
|
prepend(note, silent = false) {
|
||||||
//#region 弾く
|
//#region 弾く
|
||||||
const isMyNote = note.userId == this.$store.state.i.id;
|
const isMyNote = note.userId == this.$store.state.i.id;
|
||||||
const isPureRenote = note.renoteId != null && note.text == null && note.mediaIds.length == 0 && note.poll == null;
|
const isPureRenote = note.renoteId != null && note.text == null && note.fileIds.length == 0 && note.poll == null;
|
||||||
|
|
||||||
if (this.$store.state.settings.showMyRenotes === false) {
|
if (this.$store.state.settings.showMyRenotes === false) {
|
||||||
if (isMyNote && isPureRenote) {
|
if (isMyNote && isPureRenote) {
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<span class="icon" v-if="geo">%fa:map-marker-alt%</span>
|
<span class="icon" v-if="geo">%fa:map-marker-alt%</span>
|
||||||
<span v-if="!reply">%i18n:@note%</span>
|
<span v-if="!reply">%i18n:@note%</span>
|
||||||
<span v-if="reply">%i18n:@reply%</span>
|
<span v-if="reply">%i18n:@reply%</span>
|
||||||
<span class="count" v-if="media.length != 0">{{ '%i18n:@attaches%'.replace('{}', media.length) }}</span>
|
<span class="count" v-if="files.length != 0">{{ '%i18n:@attaches%'.replace('{}', files.length) }}</span>
|
||||||
<span class="count" v-if="uploadings.length != 0">{{ '%i18n:@uploading-media%'.replace('{}', uploadings.length) }}<mk-ellipsis/></span>
|
<span class="count" v-if="uploadings.length != 0">{{ '%i18n:@uploading-media%'.replace('{}', uploadings.length) }}<mk-ellipsis/></span>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
:reply="reply"
|
:reply="reply"
|
||||||
@posted="onPosted"
|
@posted="onPosted"
|
||||||
@change-uploadings="onChangeUploadings"
|
@change-uploadings="onChangeUploadings"
|
||||||
@change-attached-media="onChangeMedia"
|
@change-attached-files="onChangeFiles"
|
||||||
@geo-attached="onGeoAttached"
|
@geo-attached="onGeoAttached"
|
||||||
@geo-dettached="onGeoDettached"/>
|
@geo-dettached="onGeoDettached"/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -29,7 +29,7 @@ export default Vue.extend({
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
uploadings: [],
|
uploadings: [],
|
||||||
media: [],
|
files: [],
|
||||||
geo: null
|
geo: null
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@ -42,8 +42,8 @@ export default Vue.extend({
|
||||||
onChangeUploadings(files) {
|
onChangeUploadings(files) {
|
||||||
this.uploadings = files;
|
this.uploadings = files;
|
||||||
},
|
},
|
||||||
onChangeMedia(media) {
|
onChangeFiles(files) {
|
||||||
this.media = media;
|
this.files = files;
|
||||||
},
|
},
|
||||||
onGeoAttached(geo) {
|
onGeoAttached(geo) {
|
||||||
this.geo = geo;
|
this.geo = geo;
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
@keydown="onKeydown" @paste="onPaste" :placeholder="placeholder"
|
@keydown="onKeydown" @paste="onPaste" :placeholder="placeholder"
|
||||||
v-autocomplete="'text'"
|
v-autocomplete="'text'"
|
||||||
></textarea>
|
></textarea>
|
||||||
<div class="medias" :class="{ with: poll }" v-show="files.length != 0">
|
<div class="files" :class="{ with: poll }" v-show="files.length != 0">
|
||||||
<x-draggable :list="files" :options="{ animation: 150 }">
|
<x-draggable :list="files" :options="{ animation: 150 }">
|
||||||
<div v-for="file in files" :key="file.id">
|
<div v-for="file in files" :key="file.id">
|
||||||
<div class="img" :style="{ backgroundImage: `url(${file.thumbnailUrl})` }" :title="file.name"></div>
|
<div class="img" :style="{ backgroundImage: `url(${file.thumbnailUrl})` }" :title="file.name"></div>
|
||||||
|
@ -188,7 +188,7 @@ export default Vue.extend({
|
||||||
(this.$refs.poll as any).set(draft.data.poll);
|
(this.$refs.poll as any).set(draft.data.poll);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.$emit('change-attached-media', this.files);
|
this.$emit('change-attached-files', this.files);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,12 +225,12 @@ export default Vue.extend({
|
||||||
|
|
||||||
attachMedia(driveFile) {
|
attachMedia(driveFile) {
|
||||||
this.files.push(driveFile);
|
this.files.push(driveFile);
|
||||||
this.$emit('change-attached-media', this.files);
|
this.$emit('change-attached-files', this.files);
|
||||||
},
|
},
|
||||||
|
|
||||||
detachMedia(id) {
|
detachMedia(id) {
|
||||||
this.files = this.files.filter(x => x.id != id);
|
this.files = this.files.filter(x => x.id != id);
|
||||||
this.$emit('change-attached-media', this.files);
|
this.$emit('change-attached-files', this.files);
|
||||||
},
|
},
|
||||||
|
|
||||||
onChangeFile() {
|
onChangeFile() {
|
||||||
|
@ -249,7 +249,7 @@ export default Vue.extend({
|
||||||
this.text = '';
|
this.text = '';
|
||||||
this.files = [];
|
this.files = [];
|
||||||
this.poll = false;
|
this.poll = false;
|
||||||
this.$emit('change-attached-media', this.files);
|
this.$emit('change-attached-files', this.files);
|
||||||
},
|
},
|
||||||
|
|
||||||
onKeydown(e) {
|
onKeydown(e) {
|
||||||
|
@ -297,7 +297,7 @@ export default Vue.extend({
|
||||||
if (driveFile != null && driveFile != '') {
|
if (driveFile != null && driveFile != '') {
|
||||||
const file = JSON.parse(driveFile);
|
const file = JSON.parse(driveFile);
|
||||||
this.files.push(file);
|
this.files.push(file);
|
||||||
this.$emit('change-attached-media', this.files);
|
this.$emit('change-attached-files', this.files);
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
//#endregion
|
//#endregion
|
||||||
|
@ -354,7 +354,7 @@ export default Vue.extend({
|
||||||
|
|
||||||
(this as any).api('notes/create', {
|
(this as any).api('notes/create', {
|
||||||
text: this.text == '' ? undefined : this.text,
|
text: this.text == '' ? undefined : this.text,
|
||||||
mediaIds: this.files.length > 0 ? this.files.map(f => f.id) : undefined,
|
fileIds: this.files.length > 0 ? this.files.map(f => f.id) : undefined,
|
||||||
replyId: this.reply ? this.reply.id : undefined,
|
replyId: this.reply ? this.reply.id : undefined,
|
||||||
renoteId: this.renote ? this.renote.id : undefined,
|
renoteId: this.renote ? this.renote.id : undefined,
|
||||||
poll: this.poll ? (this.$refs.poll as any).get() : undefined,
|
poll: this.poll ? (this.$refs.poll as any).get() : undefined,
|
||||||
|
@ -514,7 +514,7 @@ root(isDark)
|
||||||
margin-right 8px
|
margin-right 8px
|
||||||
white-space nowrap
|
white-space nowrap
|
||||||
|
|
||||||
> .medias
|
> .files
|
||||||
margin 0
|
margin 0
|
||||||
padding 0
|
padding 0
|
||||||
background isDark ? #181b23 : lighten($theme-color, 98%)
|
background isDark ? #181b23 : lighten($theme-color, 98%)
|
||||||
|
|
|
@ -7,9 +7,9 @@
|
||||||
<misskey-flavored-markdown v-if="note.text" :text="note.text" :i="$store.state.i"/>
|
<misskey-flavored-markdown v-if="note.text" :text="note.text" :i="$store.state.i"/>
|
||||||
<a class="rp" v-if="note.renoteId" :href="`/notes/${note.renoteId}`">RP: ...</a>
|
<a class="rp" v-if="note.renoteId" :href="`/notes/${note.renoteId}`">RP: ...</a>
|
||||||
</div>
|
</div>
|
||||||
<details v-if="note.media.length > 0">
|
<details v-if="note.files.length > 0">
|
||||||
<summary>({{ '%i18n:@media-count%'.replace('{}', note.media.length) }})</summary>
|
<summary>({{ '%i18n:@media-count%'.replace('{}', note.files.length) }})</summary>
|
||||||
<mk-media-list :media-list="note.media"/>
|
<mk-media-list :media-list="note.files"/>
|
||||||
</details>
|
</details>
|
||||||
<details v-if="note.poll">
|
<details v-if="note.poll">
|
||||||
<summary>%i18n:@poll%</summary>
|
<summary>%i18n:@poll%</summary>
|
||||||
|
|
|
@ -68,7 +68,7 @@ export default Vue.extend({
|
||||||
(this as any).api('notes/user-list-timeline', {
|
(this as any).api('notes/user-list-timeline', {
|
||||||
listId: this.list.id,
|
listId: this.list.id,
|
||||||
limit: fetchLimit + 1,
|
limit: fetchLimit + 1,
|
||||||
mediaOnly: this.mediaOnly,
|
withFiles: this.mediaOnly,
|
||||||
includeMyRenotes: this.$store.state.settings.showMyRenotes,
|
includeMyRenotes: this.$store.state.settings.showMyRenotes,
|
||||||
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
|
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
|
||||||
includeLocalRenotes: this.$store.state.settings.showLocalRenotes
|
includeLocalRenotes: this.$store.state.settings.showLocalRenotes
|
||||||
|
@ -90,7 +90,7 @@ export default Vue.extend({
|
||||||
listId: this.list.id,
|
listId: this.list.id,
|
||||||
limit: fetchLimit + 1,
|
limit: fetchLimit + 1,
|
||||||
untilId: (this.$refs.timeline as any).tail().id,
|
untilId: (this.$refs.timeline as any).tail().id,
|
||||||
mediaOnly: this.mediaOnly,
|
withFiles: this.mediaOnly,
|
||||||
includeMyRenotes: this.$store.state.settings.showMyRenotes,
|
includeMyRenotes: this.$store.state.settings.showMyRenotes,
|
||||||
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
|
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
|
||||||
includeLocalRenotes: this.$store.state.settings.showLocalRenotes
|
includeLocalRenotes: this.$store.state.settings.showLocalRenotes
|
||||||
|
@ -109,7 +109,7 @@ export default Vue.extend({
|
||||||
return promise;
|
return promise;
|
||||||
},
|
},
|
||||||
onNote(note) {
|
onNote(note) {
|
||||||
if (this.mediaOnly && note.media.length == 0) return;
|
if (this.mediaOnly && note.files.length == 0) return;
|
||||||
|
|
||||||
// Prepend a note
|
// Prepend a note
|
||||||
(this.$refs.timeline as any).prepend(note);
|
(this.$refs.timeline as any).prepend(note);
|
||||||
|
|
|
@ -28,8 +28,8 @@
|
||||||
<misskey-flavored-markdown v-if="p.text" :text="p.text" :i="$store.state.i"/>
|
<misskey-flavored-markdown v-if="p.text" :text="p.text" :i="$store.state.i"/>
|
||||||
<a class="rp" v-if="p.renote != null">RP:</a>
|
<a class="rp" v-if="p.renote != null">RP:</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="media" v-if="p.media.length > 0">
|
<div class="files" v-if="p.files.length > 0">
|
||||||
<mk-media-list :media-list="p.media"/>
|
<mk-media-list :media-list="p.files"/>
|
||||||
</div>
|
</div>
|
||||||
<mk-poll v-if="p.poll" :note="p" ref="pollViewer"/>
|
<mk-poll v-if="p.poll" :note="p" ref="pollViewer"/>
|
||||||
<a class="location" v-if="p.geo" :href="`https://maps.google.com/maps?q=${p.geo.coordinates[1]},${p.geo.coordinates[0]}`" target="_blank">%fa:map-marker-alt% %i18n:@location%</a>
|
<a class="location" v-if="p.geo" :href="`https://maps.google.com/maps?q=${p.geo.coordinates[1]},${p.geo.coordinates[0]}`" target="_blank">%fa:map-marker-alt% %i18n:@location%</a>
|
||||||
|
@ -54,11 +54,11 @@
|
||||||
</article>
|
</article>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="srwrkujossgfuhrbnvqkybtzxpblgchi">
|
<div v-else class="srwrkujossgfuhrbnvqkybtzxpblgchi">
|
||||||
<div v-if="note.media.length > 0">
|
<div v-if="note.files.length > 0">
|
||||||
<mk-media-list :media-list="note.media"/>
|
<mk-media-list :media-list="note.files"/>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="note.renote && note.renote.media.length > 0">
|
<div v-if="note.renote && note.renote.files.length > 0">
|
||||||
<mk-media-list :media-list="note.renote.media"/>
|
<mk-media-list :media-list="note.renote.files"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -100,7 +100,7 @@ export default Vue.extend({
|
||||||
isRenote(): boolean {
|
isRenote(): boolean {
|
||||||
return (this.note.renote &&
|
return (this.note.renote &&
|
||||||
this.note.text == null &&
|
this.note.text == null &&
|
||||||
this.note.mediaIds.length == 0 &&
|
this.note.fileIds.length == 0 &&
|
||||||
this.note.poll == null);
|
this.note.poll == null);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -371,7 +371,7 @@ root(isDark)
|
||||||
.mk-url-preview
|
.mk-url-preview
|
||||||
margin-top 8px
|
margin-top 8px
|
||||||
|
|
||||||
> .media
|
> .files
|
||||||
> img
|
> img
|
||||||
display block
|
display block
|
||||||
max-width 100%
|
max-width 100%
|
||||||
|
|
|
@ -127,7 +127,7 @@ export default Vue.extend({
|
||||||
prepend(note, silent = false) {
|
prepend(note, silent = false) {
|
||||||
//#region 弾く
|
//#region 弾く
|
||||||
const isMyNote = note.userId == this.$store.state.i.id;
|
const isMyNote = note.userId == this.$store.state.i.id;
|
||||||
const isPureRenote = note.renoteId != null && note.text == null && note.mediaIds.length == 0 && note.poll == null;
|
const isPureRenote = note.renoteId != null && note.text == null && note.fileIds.length == 0 && note.poll == null;
|
||||||
|
|
||||||
if (this.$store.state.settings.showMyRenotes === false) {
|
if (this.$store.state.settings.showMyRenotes === false) {
|
||||||
if (isMyNote && isPureRenote) {
|
if (isMyNote && isPureRenote) {
|
||||||
|
|
|
@ -96,7 +96,7 @@ export default Vue.extend({
|
||||||
(this.$refs.timeline as any).init(() => new Promise((res, rej) => {
|
(this.$refs.timeline as any).init(() => new Promise((res, rej) => {
|
||||||
(this as any).api(this.endpoint, {
|
(this as any).api(this.endpoint, {
|
||||||
limit: fetchLimit + 1,
|
limit: fetchLimit + 1,
|
||||||
mediaOnly: this.mediaOnly,
|
withFiles: this.mediaOnly,
|
||||||
includeMyRenotes: this.$store.state.settings.showMyRenotes,
|
includeMyRenotes: this.$store.state.settings.showMyRenotes,
|
||||||
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
|
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
|
||||||
includeLocalRenotes: this.$store.state.settings.showLocalRenotes
|
includeLocalRenotes: this.$store.state.settings.showLocalRenotes
|
||||||
|
@ -117,7 +117,7 @@ export default Vue.extend({
|
||||||
|
|
||||||
const promise = (this as any).api(this.endpoint, {
|
const promise = (this as any).api(this.endpoint, {
|
||||||
limit: fetchLimit + 1,
|
limit: fetchLimit + 1,
|
||||||
mediaOnly: this.mediaOnly,
|
withFiles: this.mediaOnly,
|
||||||
untilId: (this.$refs.timeline as any).tail().id,
|
untilId: (this.$refs.timeline as any).tail().id,
|
||||||
includeMyRenotes: this.$store.state.settings.showMyRenotes,
|
includeMyRenotes: this.$store.state.settings.showMyRenotes,
|
||||||
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
|
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
|
||||||
|
@ -138,7 +138,7 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
onNote(note) {
|
onNote(note) {
|
||||||
if (this.mediaOnly && note.media.length == 0) return;
|
if (this.mediaOnly && note.files.length == 0) return;
|
||||||
|
|
||||||
// Prepend a note
|
// Prepend a note
|
||||||
(this.$refs.timeline as any).prepend(note);
|
(this.$refs.timeline as any).prepend(note);
|
||||||
|
|
|
@ -24,12 +24,12 @@ export default Vue.extend({
|
||||||
mounted() {
|
mounted() {
|
||||||
(this as any).api('users/notes', {
|
(this as any).api('users/notes', {
|
||||||
userId: this.user.id,
|
userId: this.user.id,
|
||||||
withMedia: true,
|
withFiles: true,
|
||||||
limit: 9
|
limit: 9
|
||||||
}).then(notes => {
|
}).then(notes => {
|
||||||
notes.forEach(note => {
|
notes.forEach(note => {
|
||||||
note.media.forEach(media => {
|
note.files.forEach(file => {
|
||||||
if (this.images.length < 9) this.images.push(media);
|
if (this.images.length < 9) this.images.push(file);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
this.fetching = false;
|
this.fetching = false;
|
||||||
|
|
|
@ -66,7 +66,7 @@ export default Vue.extend({
|
||||||
limit: fetchLimit + 1,
|
limit: fetchLimit + 1,
|
||||||
untilDate: this.date ? this.date.getTime() : undefined,
|
untilDate: this.date ? this.date.getTime() : undefined,
|
||||||
includeReplies: this.mode == 'with-replies',
|
includeReplies: this.mode == 'with-replies',
|
||||||
withMedia: this.mode == 'with-media'
|
withFiles: this.mode == 'with-media'
|
||||||
}).then(notes => {
|
}).then(notes => {
|
||||||
if (notes.length == fetchLimit + 1) {
|
if (notes.length == fetchLimit + 1) {
|
||||||
notes.pop();
|
notes.pop();
|
||||||
|
@ -86,7 +86,7 @@ export default Vue.extend({
|
||||||
userId: this.user.id,
|
userId: this.user.id,
|
||||||
limit: fetchLimit + 1,
|
limit: fetchLimit + 1,
|
||||||
includeReplies: this.mode == 'with-replies',
|
includeReplies: this.mode == 'with-replies',
|
||||||
withMedia: this.mode == 'with-media',
|
withFiles: this.mode == 'with-media',
|
||||||
untilId: (this.$refs.timeline as any).tail().id
|
untilId: (this.$refs.timeline as any).tail().id
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ export default define({
|
||||||
offset: this.offset,
|
offset: this.offset,
|
||||||
renote: false,
|
renote: false,
|
||||||
reply: false,
|
reply: false,
|
||||||
media: false,
|
file: false,
|
||||||
poll: false
|
poll: false
|
||||||
}).then(notes => {
|
}).then(notes => {
|
||||||
const note = notes ? notes[0] : null;
|
const note = notes ? notes[0] : null;
|
||||||
|
|
|
@ -40,8 +40,8 @@
|
||||||
<span v-if="p.deletedAt" style="opacity: 0.5">(%i18n:@deleted%)</span>
|
<span v-if="p.deletedAt" style="opacity: 0.5">(%i18n:@deleted%)</span>
|
||||||
<misskey-flavored-markdown v-if="p.text" :text="p.text" :i="$store.state.i"/>
|
<misskey-flavored-markdown v-if="p.text" :text="p.text" :i="$store.state.i"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="media" v-if="p.media.length > 0">
|
<div class="files" v-if="p.files.length > 0">
|
||||||
<mk-media-list :media-list="p.media" :raw="true"/>
|
<mk-media-list :media-list="p.files" :raw="true"/>
|
||||||
</div>
|
</div>
|
||||||
<mk-poll v-if="p.poll" :note="p"/>
|
<mk-poll v-if="p.poll" :note="p"/>
|
||||||
<mk-url-preview v-for="url in urls" :url="url" :key="url" :detail="true"/>
|
<mk-url-preview v-for="url in urls" :url="url" :key="url" :detail="true"/>
|
||||||
|
@ -113,7 +113,7 @@ export default Vue.extend({
|
||||||
isRenote(): boolean {
|
isRenote(): boolean {
|
||||||
return (this.note.renote &&
|
return (this.note.renote &&
|
||||||
this.note.text == null &&
|
this.note.text == null &&
|
||||||
this.note.mediaIds.length == 0 &&
|
this.note.fileIds.length == 0 &&
|
||||||
this.note.poll == null);
|
this.note.poll == null);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -369,7 +369,7 @@ root(isDark)
|
||||||
> .mk-url-preview
|
> .mk-url-preview
|
||||||
margin-top 8px
|
margin-top 8px
|
||||||
|
|
||||||
> .media
|
> .files
|
||||||
> img
|
> img
|
||||||
display block
|
display block
|
||||||
max-width 100%
|
max-width 100%
|
||||||
|
|
|
@ -28,8 +28,8 @@
|
||||||
<misskey-flavored-markdown v-if="p.text" :text="p.text" :i="$store.state.i" :class="$style.text"/>
|
<misskey-flavored-markdown v-if="p.text" :text="p.text" :i="$store.state.i" :class="$style.text"/>
|
||||||
<a class="rp" v-if="p.renote != null">RP:</a>
|
<a class="rp" v-if="p.renote != null">RP:</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="media" v-if="p.media.length > 0">
|
<div class="files" v-if="p.files.length > 0">
|
||||||
<mk-media-list :media-list="p.media"/>
|
<mk-media-list :media-list="p.files"/>
|
||||||
</div>
|
</div>
|
||||||
<mk-poll v-if="p.poll" :note="p" ref="pollViewer"/>
|
<mk-poll v-if="p.poll" :note="p" ref="pollViewer"/>
|
||||||
<mk-url-preview v-for="url in urls" :url="url" :key="url"/>
|
<mk-url-preview v-for="url in urls" :url="url" :key="url"/>
|
||||||
|
@ -90,7 +90,7 @@ export default Vue.extend({
|
||||||
isRenote(): boolean {
|
isRenote(): boolean {
|
||||||
return (this.note.renote &&
|
return (this.note.renote &&
|
||||||
this.note.text == null &&
|
this.note.text == null &&
|
||||||
this.note.mediaIds.length == 0 &&
|
this.note.fileIds.length == 0 &&
|
||||||
this.note.poll == null);
|
this.note.poll == null);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -414,7 +414,7 @@ root(isDark)
|
||||||
.mk-url-preview
|
.mk-url-preview
|
||||||
margin-top 8px
|
margin-top 8px
|
||||||
|
|
||||||
> .media
|
> .files
|
||||||
> img
|
> img
|
||||||
display block
|
display block
|
||||||
max-width 100%
|
max-width 100%
|
||||||
|
|
|
@ -125,7 +125,7 @@ export default Vue.extend({
|
||||||
prepend(note, silent = false) {
|
prepend(note, silent = false) {
|
||||||
//#region 弾く
|
//#region 弾く
|
||||||
const isMyNote = note.userId == this.$store.state.i.id;
|
const isMyNote = note.userId == this.$store.state.i.id;
|
||||||
const isPureRenote = note.renoteId != null && note.text == null && note.mediaIds.length == 0 && note.poll == null;
|
const isPureRenote = note.renoteId != null && note.text == null && note.fileIds.length == 0 && note.poll == null;
|
||||||
|
|
||||||
if (this.$store.state.settings.showMyRenotes === false) {
|
if (this.$store.state.settings.showMyRenotes === false) {
|
||||||
if (isMyNote && isPureRenote) {
|
if (isMyNote && isPureRenote) {
|
||||||
|
|
|
@ -200,12 +200,12 @@ export default Vue.extend({
|
||||||
|
|
||||||
attachMedia(driveFile) {
|
attachMedia(driveFile) {
|
||||||
this.files.push(driveFile);
|
this.files.push(driveFile);
|
||||||
this.$emit('change-attached-media', this.files);
|
this.$emit('change-attached-files', this.files);
|
||||||
},
|
},
|
||||||
|
|
||||||
detachMedia(file) {
|
detachMedia(file) {
|
||||||
this.files = this.files.filter(x => x.id != file.id);
|
this.files = this.files.filter(x => x.id != file.id);
|
||||||
this.$emit('change-attached-media', this.files);
|
this.$emit('change-attached-files', this.files);
|
||||||
},
|
},
|
||||||
|
|
||||||
onChangeFile() {
|
onChangeFile() {
|
||||||
|
@ -269,7 +269,7 @@ export default Vue.extend({
|
||||||
this.text = '';
|
this.text = '';
|
||||||
this.files = [];
|
this.files = [];
|
||||||
this.poll = false;
|
this.poll = false;
|
||||||
this.$emit('change-attached-media');
|
this.$emit('change-attached-files');
|
||||||
},
|
},
|
||||||
|
|
||||||
post() {
|
post() {
|
||||||
|
@ -277,7 +277,7 @@ export default Vue.extend({
|
||||||
const viaMobile = this.$store.state.settings.disableViaMobile !== true;
|
const viaMobile = this.$store.state.settings.disableViaMobile !== true;
|
||||||
(this as any).api('notes/create', {
|
(this as any).api('notes/create', {
|
||||||
text: this.text == '' ? undefined : this.text,
|
text: this.text == '' ? undefined : this.text,
|
||||||
mediaIds: this.files.length > 0 ? this.files.map(f => f.id) : undefined,
|
fileIds: this.files.length > 0 ? this.files.map(f => f.id) : undefined,
|
||||||
replyId: this.reply ? this.reply.id : undefined,
|
replyId: this.reply ? this.reply.id : undefined,
|
||||||
renoteId: this.renote ? this.renote.id : undefined,
|
renoteId: this.renote ? this.renote.id : undefined,
|
||||||
poll: this.poll ? (this.$refs.poll as any).get() : undefined,
|
poll: this.poll ? (this.$refs.poll as any).get() : undefined,
|
||||||
|
|
|
@ -7,9 +7,9 @@
|
||||||
<misskey-flavored-markdown v-if="note.text" :text="note.text" :i="$store.state.i"/>
|
<misskey-flavored-markdown v-if="note.text" :text="note.text" :i="$store.state.i"/>
|
||||||
<a class="rp" v-if="note.renoteId">RP: ...</a>
|
<a class="rp" v-if="note.renoteId">RP: ...</a>
|
||||||
</div>
|
</div>
|
||||||
<details v-if="note.media.length > 0">
|
<details v-if="note.files.length > 0">
|
||||||
<summary>({{ '%i18n:@media-count%'.replace('{}', note.media.length) }})</summary>
|
<summary>({{ '%i18n:@media-count%'.replace('{}', note.files.length) }})</summary>
|
||||||
<mk-media-list :media-list="note.media"/>
|
<mk-media-list :media-list="note.files"/>
|
||||||
</details>
|
</details>
|
||||||
<details v-if="note.poll">
|
<details v-if="note.poll">
|
||||||
<summary>%i18n:@poll%</summary>
|
<summary>%i18n:@poll%</summary>
|
||||||
|
|
|
@ -41,7 +41,7 @@ export default Vue.extend({
|
||||||
(this.$refs.timeline as any).init(() => new Promise((res, rej) => {
|
(this.$refs.timeline as any).init(() => new Promise((res, rej) => {
|
||||||
(this as any).api('users/notes', {
|
(this as any).api('users/notes', {
|
||||||
userId: this.user.id,
|
userId: this.user.id,
|
||||||
withMedia: this.withMedia,
|
withFiles: this.withMedia,
|
||||||
limit: fetchLimit + 1
|
limit: fetchLimit + 1
|
||||||
}).then(notes => {
|
}).then(notes => {
|
||||||
if (notes.length == fetchLimit + 1) {
|
if (notes.length == fetchLimit + 1) {
|
||||||
|
@ -62,7 +62,7 @@ export default Vue.extend({
|
||||||
|
|
||||||
const promise = (this as any).api('users/notes', {
|
const promise = (this as any).api('users/notes', {
|
||||||
userId: this.user.id,
|
userId: this.user.id,
|
||||||
withMedia: this.withMedia,
|
withFiles: this.withMedia,
|
||||||
limit: fetchLimit + 1,
|
limit: fetchLimit + 1,
|
||||||
untilId: (this.$refs.timeline as any).tail().id
|
untilId: (this.$refs.timeline as any).tail().id
|
||||||
});
|
});
|
||||||
|
|
|
@ -26,7 +26,7 @@ export default Vue.extend({
|
||||||
mounted() {
|
mounted() {
|
||||||
(this as any).api('users/notes', {
|
(this as any).api('users/notes', {
|
||||||
userId: this.user.id,
|
userId: this.user.id,
|
||||||
withMedia: true,
|
withFiles: true,
|
||||||
limit: 6
|
limit: 6
|
||||||
}).then(notes => {
|
}).then(notes => {
|
||||||
notes.forEach(note => {
|
notes.forEach(note => {
|
||||||
|
|
|
@ -33,19 +33,19 @@ props:
|
||||||
ja-JP: "投稿の本文"
|
ja-JP: "投稿の本文"
|
||||||
en-US: "The text of this note"
|
en-US: "The text of this note"
|
||||||
|
|
||||||
mediaIds:
|
fileIds:
|
||||||
type: "id(DriveFile)[]"
|
type: "id(DriveFile)[]"
|
||||||
optional: true
|
optional: true
|
||||||
desc:
|
desc:
|
||||||
ja-JP: "添付されているメディアのID (なければレスポンスでは空配列)"
|
ja-JP: "添付されているファイルのID (なければレスポンスでは空配列)"
|
||||||
en-US: "The IDs of the attached media (empty array for response if no media is attached)"
|
en-US: "The IDs of the attached files (empty array for response if no files is attached)"
|
||||||
|
|
||||||
media:
|
files:
|
||||||
type: "entity(DriveFile)[]"
|
type: "entity(DriveFile)[]"
|
||||||
optional: true
|
optional: true
|
||||||
desc:
|
desc:
|
||||||
ja-JP: "添付されているメディア"
|
ja-JP: "添付されているファイル"
|
||||||
en-US: "The attached media"
|
en-US: "The attached files"
|
||||||
|
|
||||||
userId:
|
userId:
|
||||||
type: "id(User)"
|
type: "id(User)"
|
||||||
|
|
|
@ -16,9 +16,9 @@ const summarize = (note: any): string => {
|
||||||
// 本文
|
// 本文
|
||||||
summary += note.text ? note.text : '';
|
summary += note.text ? note.text : '';
|
||||||
|
|
||||||
// メディアが添付されているとき
|
// ファイルが添付されているとき
|
||||||
if (note.media.length != 0) {
|
if (note.files.length != 0) {
|
||||||
summary += ` (${note.media.length}つのメディア)`;
|
summary += ` (${note.files.length}つのファイル)`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 投票が添付されているとき
|
// 投票が添付されているとき
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { INote } from '../models/note';
|
import { INote } from '../models/note';
|
||||||
|
|
||||||
export default function(note: INote): boolean {
|
export default function(note: INote): boolean {
|
||||||
return note.renoteId != null && (note.text != null || note.poll != null || (note.mediaIds != null && note.mediaIds.length > 0));
|
return note.renoteId != null && (note.text != null || note.poll != null || (note.fileIds != null && note.fileIds.length > 0));
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,7 @@ export async function deleteDriveFile(driveFile: string | mongo.ObjectID | IDriv
|
||||||
|
|
||||||
// このDriveFileを添付しているNoteをすべて削除
|
// このDriveFileを添付しているNoteをすべて削除
|
||||||
await Promise.all((
|
await Promise.all((
|
||||||
await Note.find({ mediaIds: d._id })
|
await Note.find({ fileIds: d._id })
|
||||||
).map(x => deleteNote(x)));
|
).map(x => deleteNote(x)));
|
||||||
|
|
||||||
// このDriveFileを添付しているMessagingMessageをすべて削除
|
// このDriveFileを添付しているMessagingMessageをすべて削除
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { IUser, pack as packUser } from './user';
|
||||||
import { pack as packApp } from './app';
|
import { pack as packApp } from './app';
|
||||||
import PollVote, { deletePollVote } from './poll-vote';
|
import PollVote, { deletePollVote } from './poll-vote';
|
||||||
import Reaction, { deleteNoteReaction } from './note-reaction';
|
import Reaction, { deleteNoteReaction } from './note-reaction';
|
||||||
import { pack as packFile } from './drive-file';
|
import { pack as packFile, IDriveFile } from './drive-file';
|
||||||
import NoteWatching, { deleteNoteWatching } from './note-watching';
|
import NoteWatching, { deleteNoteWatching } from './note-watching';
|
||||||
import NoteReaction from './note-reaction';
|
import NoteReaction from './note-reaction';
|
||||||
import Favorite, { deleteFavorite } from './favorite';
|
import Favorite, { deleteFavorite } from './favorite';
|
||||||
|
@ -17,9 +17,20 @@ const Note = db.get<INote>('notes');
|
||||||
Note.createIndex('uri', { sparse: true, unique: true });
|
Note.createIndex('uri', { sparse: true, unique: true });
|
||||||
Note.createIndex('userId');
|
Note.createIndex('userId');
|
||||||
Note.createIndex('tagsLower');
|
Note.createIndex('tagsLower');
|
||||||
|
Note.createIndex('_files.contentType');
|
||||||
Note.createIndex({
|
Note.createIndex({
|
||||||
createdAt: -1
|
createdAt: -1
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 後方互換性のため
|
||||||
|
Note.update({}, {
|
||||||
|
$rename: {
|
||||||
|
mediaIds: 'fileIds'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
multi: true
|
||||||
|
});
|
||||||
|
|
||||||
export default Note;
|
export default Note;
|
||||||
|
|
||||||
export function isValidText(text: string): boolean {
|
export function isValidText(text: string): boolean {
|
||||||
|
@ -34,7 +45,7 @@ export type INote = {
|
||||||
_id: mongo.ObjectID;
|
_id: mongo.ObjectID;
|
||||||
createdAt: Date;
|
createdAt: Date;
|
||||||
deletedAt: Date;
|
deletedAt: Date;
|
||||||
mediaIds: mongo.ObjectID[];
|
fileIds: mongo.ObjectID[];
|
||||||
replyId: mongo.ObjectID;
|
replyId: mongo.ObjectID;
|
||||||
renoteId: mongo.ObjectID;
|
renoteId: mongo.ObjectID;
|
||||||
poll: {
|
poll: {
|
||||||
|
@ -92,6 +103,7 @@ export type INote = {
|
||||||
inbox?: string;
|
inbox?: string;
|
||||||
};
|
};
|
||||||
_replyIds?: mongo.ObjectID[];
|
_replyIds?: mongo.ObjectID[];
|
||||||
|
_files?: IDriveFile[];
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -271,11 +283,15 @@ export const pack = async (
|
||||||
_note.app = packApp(_note.appId);
|
_note.app = packApp(_note.appId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Populate media
|
// Populate files
|
||||||
_note.media = hide ? [] : Promise.all(_note.mediaIds.map((fileId: mongo.ObjectID) =>
|
_note.files = hide ? [] : Promise.all(_note.fileIds.map((fileId: mongo.ObjectID) =>
|
||||||
packFile(fileId)
|
packFile(fileId)
|
||||||
));
|
));
|
||||||
|
|
||||||
|
// 後方互換性のため
|
||||||
|
_note.mediaIds = _note.fileIds;
|
||||||
|
_note.media = _note.files;
|
||||||
|
|
||||||
// When requested a detailed note data
|
// When requested a detailed note data
|
||||||
if (opts.detail) {
|
if (opts.detail) {
|
||||||
//#region 重いので廃止
|
//#region 重いので廃止
|
||||||
|
@ -344,7 +360,7 @@ export const pack = async (
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hide) {
|
if (hide) {
|
||||||
_note.mediaIds = [];
|
_note.fileIds = [];
|
||||||
_note.text = null;
|
_note.text = null;
|
||||||
_note.poll = null;
|
_note.poll = null;
|
||||||
_note.cw = null;
|
_note.cw = null;
|
||||||
|
|
|
@ -78,11 +78,11 @@ export async function createNote(value: any, resolver?: Resolver, silent = false
|
||||||
}
|
}
|
||||||
//#endergion
|
//#endergion
|
||||||
|
|
||||||
// 添付メディア
|
// 添付ファイル
|
||||||
// TODO: attachmentは必ずしもImageではない
|
// TODO: attachmentは必ずしもImageではない
|
||||||
// TODO: attachmentは必ずしも配列ではない
|
// TODO: attachmentは必ずしも配列ではない
|
||||||
// Noteがsensitiveなら添付もsensitiveにする
|
// Noteがsensitiveなら添付もsensitiveにする
|
||||||
const media = note.attachment
|
const files = note.attachment
|
||||||
.map(attach => attach.sensitive = note.sensitive)
|
.map(attach => attach.sensitive = note.sensitive)
|
||||||
? await Promise.all(note.attachment.map(x => resolveImage(actor, x)))
|
? await Promise.all(note.attachment.map(x => resolveImage(actor, x)))
|
||||||
: [];
|
: [];
|
||||||
|
@ -100,7 +100,7 @@ export async function createNote(value: any, resolver?: Resolver, silent = false
|
||||||
|
|
||||||
return await post(actor, {
|
return await post(actor, {
|
||||||
createdAt: new Date(note.published),
|
createdAt: new Date(note.published),
|
||||||
media,
|
files: files,
|
||||||
reply,
|
reply,
|
||||||
renote: undefined,
|
renote: undefined,
|
||||||
cw: note.summary,
|
cw: note.summary,
|
||||||
|
|
|
@ -8,8 +8,8 @@ import User from '../../../models/user';
|
||||||
import toHtml from '../misc/get-note-html';
|
import toHtml from '../misc/get-note-html';
|
||||||
|
|
||||||
export default async function renderNote(note: INote, dive = true): Promise<any> {
|
export default async function renderNote(note: INote, dive = true): Promise<any> {
|
||||||
const promisedFiles: Promise<IDriveFile[]> = note.mediaIds
|
const promisedFiles: Promise<IDriveFile[]> = note.fileIds
|
||||||
? DriveFile.find({ _id: { $in: note.mediaIds } })
|
? DriveFile.find({ _id: { $in: note.fileIds } })
|
||||||
: Promise.resolve([]);
|
: Promise.resolve([]);
|
||||||
|
|
||||||
let inReplyTo;
|
let inReplyTo;
|
||||||
|
|
|
@ -58,7 +58,7 @@ export default async (ctx: Router.IRouterContext) => {
|
||||||
$or: [{
|
$or: [{
|
||||||
text: { $ne: null }
|
text: { $ne: null }
|
||||||
}, {
|
}, {
|
||||||
mediaIds: { $ne: [] }
|
fileIds: { $ne: [] }
|
||||||
}]
|
}]
|
||||||
}]
|
}]
|
||||||
} as any;
|
} as any;
|
||||||
|
|
|
@ -20,9 +20,9 @@ export default (params: any) => new Promise(async (res, rej) => {
|
||||||
const [renote, renoteErr] = $.bool.optional.get(params.renote);
|
const [renote, renoteErr] = $.bool.optional.get(params.renote);
|
||||||
if (renoteErr) return rej('invalid renote param');
|
if (renoteErr) return rej('invalid renote param');
|
||||||
|
|
||||||
// Get 'media' parameter
|
// Get 'files' parameter
|
||||||
const [media, mediaErr] = $.bool.optional.get(params.media);
|
const [files, filesErr] = $.bool.optional.get(params.files);
|
||||||
if (mediaErr) return rej('invalid media param');
|
if (filesErr) return rej('invalid files param');
|
||||||
|
|
||||||
// Get 'poll' parameter
|
// Get 'poll' parameter
|
||||||
const [poll, pollErr] = $.bool.optional.get(params.poll);
|
const [poll, pollErr] = $.bool.optional.get(params.poll);
|
||||||
|
@ -79,8 +79,8 @@ export default (params: any) => new Promise(async (res, rej) => {
|
||||||
query.renoteId = renote ? { $exists: true, $ne: null } : null;
|
query.renoteId = renote ? { $exists: true, $ne: null } : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (media != undefined) {
|
if (files != undefined) {
|
||||||
query.mediaIds = media ? { $exists: true, $ne: null } : [];
|
query.fileIds = files ? { $exists: true, $ne: null } : [];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (poll != undefined) {
|
if (poll != undefined) {
|
||||||
|
|
|
@ -71,9 +71,15 @@ export const meta = {
|
||||||
ref: 'geo'
|
ref: 'geo'
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
fileIds: $.arr($.type(ID)).optional.unique().range(1, 4).note({
|
||||||
|
desc: {
|
||||||
|
'ja-JP': '添付するファイル'
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
mediaIds: $.arr($.type(ID)).optional.unique().range(1, 4).note({
|
mediaIds: $.arr($.type(ID)).optional.unique().range(1, 4).note({
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': '添付するメディア'
|
'ja-JP': '添付するファイル (このパラメータは廃止予定です。代わりに fileIds を使ってください。)'
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
@ -124,15 +130,16 @@ export default (params: any, user: ILocalUser, app: IApp) => new Promise(async (
|
||||||
}
|
}
|
||||||
|
|
||||||
let files: IDriveFile[] = [];
|
let files: IDriveFile[] = [];
|
||||||
if (ps.mediaIds !== undefined) {
|
const fileIds = ps.fileIds != null ? ps.fileIds : ps.mediaIds != null ? ps.mediaIds : null;
|
||||||
|
if (fileIds != null) {
|
||||||
// Fetch files
|
// Fetch files
|
||||||
// forEach だと途中でエラーなどがあっても return できないので
|
// forEach だと途中でエラーなどがあっても return できないので
|
||||||
// 敢えて for を使っています。
|
// 敢えて for を使っています。
|
||||||
for (const mediaId of ps.mediaIds) {
|
for (const fileId of fileIds) {
|
||||||
// Fetch file
|
// Fetch file
|
||||||
// SELECT _id
|
// SELECT _id
|
||||||
const entity = await DriveFile.findOne({
|
const entity = await DriveFile.findOne({
|
||||||
_id: mediaId,
|
_id: fileId,
|
||||||
'metadata.userId': user._id
|
'metadata.userId': user._id
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -155,7 +162,7 @@ export default (params: any, user: ILocalUser, app: IApp) => new Promise(async (
|
||||||
|
|
||||||
if (renote == null) {
|
if (renote == null) {
|
||||||
return rej('renoteee is not found');
|
return rej('renoteee is not found');
|
||||||
} else if (renote.renoteId && !renote.text && !renote.mediaIds) {
|
} else if (renote.renoteId && !renote.text && !renote.fileIds) {
|
||||||
return rej('cannot renote to renote');
|
return rej('cannot renote to renote');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -176,7 +183,7 @@ export default (params: any, user: ILocalUser, app: IApp) => new Promise(async (
|
||||||
}
|
}
|
||||||
|
|
||||||
// 返信対象が引用でないRenoteだったらエラー
|
// 返信対象が引用でないRenoteだったらエラー
|
||||||
if (reply.renoteId && !reply.text && !reply.mediaIds) {
|
if (reply.renoteId && !reply.text && !reply.fileIds) {
|
||||||
return rej('cannot reply to renote');
|
return rej('cannot reply to renote');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,13 +198,13 @@ export default (params: any, user: ILocalUser, app: IApp) => new Promise(async (
|
||||||
|
|
||||||
// テキストが無いかつ添付ファイルが無いかつRenoteも無いかつ投票も無かったらエラー
|
// テキストが無いかつ添付ファイルが無いかつRenoteも無いかつ投票も無かったらエラー
|
||||||
if ((ps.text === undefined || ps.text === null) && files === null && renote === null && ps.poll === undefined) {
|
if ((ps.text === undefined || ps.text === null) && files === null && renote === null && ps.poll === undefined) {
|
||||||
return rej('text, mediaIds, renoteId or poll is required');
|
return rej('text, fileIds, renoteId or poll is required');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 投稿を作成
|
// 投稿を作成
|
||||||
const note = await create(user, {
|
const note = await create(user, {
|
||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
media: files,
|
files: files,
|
||||||
poll: ps.poll,
|
poll: ps.poll,
|
||||||
text: ps.text,
|
text: ps.text,
|
||||||
reply,
|
reply,
|
||||||
|
|
|
@ -33,9 +33,9 @@ export default async (params: any, user: ILocalUser) => {
|
||||||
throw 'only one of sinceId, untilId, sinceDate, untilDate can be specified';
|
throw 'only one of sinceId, untilId, sinceDate, untilDate can be specified';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get 'mediaOnly' parameter
|
// Get 'withFiles' parameter
|
||||||
const [mediaOnly, mediaOnlyErr] = $.bool.optional.get(params.mediaOnly);
|
const [withFiles, withFilesErr] = $.bool.optional.get(params.withFiles);
|
||||||
if (mediaOnlyErr) throw 'invalid mediaOnly param';
|
if (withFilesErr) throw 'invalid withFiles param';
|
||||||
|
|
||||||
// ミュートしているユーザーを取得
|
// ミュートしているユーザーを取得
|
||||||
const mutedUserIds = user ? (await Mute.find({
|
const mutedUserIds = user ? (await Mute.find({
|
||||||
|
@ -68,8 +68,8 @@ export default async (params: any, user: ILocalUser) => {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mediaOnly) {
|
if (withFiles) {
|
||||||
query.mediaIds = { $exists: true, $ne: [] };
|
query.fileIds = { $exists: true, $ne: [] };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sinceId) {
|
if (sinceId) {
|
||||||
|
|
|
@ -66,7 +66,7 @@ export const meta = {
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
mediaOnly: $.bool.optional.note({
|
withFiles: $.bool.optional.note({
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'true にすると、メディアが添付された投稿だけ取得します'
|
'ja-JP': 'true にすると、メディアが添付された投稿だけ取得します'
|
||||||
}
|
}
|
||||||
|
@ -164,7 +164,7 @@ export default async (params: any, user: ILocalUser) => {
|
||||||
}, {
|
}, {
|
||||||
text: { $ne: null }
|
text: { $ne: null }
|
||||||
}, {
|
}, {
|
||||||
mediaIds: { $ne: [] }
|
fileIds: { $ne: [] }
|
||||||
}, {
|
}, {
|
||||||
poll: { $ne: null }
|
poll: { $ne: null }
|
||||||
}]
|
}]
|
||||||
|
@ -180,7 +180,7 @@ export default async (params: any, user: ILocalUser) => {
|
||||||
}, {
|
}, {
|
||||||
text: { $ne: null }
|
text: { $ne: null }
|
||||||
}, {
|
}, {
|
||||||
mediaIds: { $ne: [] }
|
fileIds: { $ne: [] }
|
||||||
}, {
|
}, {
|
||||||
poll: { $ne: null }
|
poll: { $ne: null }
|
||||||
}]
|
}]
|
||||||
|
@ -196,16 +196,16 @@ export default async (params: any, user: ILocalUser) => {
|
||||||
}, {
|
}, {
|
||||||
text: { $ne: null }
|
text: { $ne: null }
|
||||||
}, {
|
}, {
|
||||||
mediaIds: { $ne: [] }
|
fileIds: { $ne: [] }
|
||||||
}, {
|
}, {
|
||||||
poll: { $ne: null }
|
poll: { $ne: null }
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ps.mediaOnly) {
|
if (ps.withFiles) {
|
||||||
query.$and.push({
|
query.$and.push({
|
||||||
mediaIds: { $exists: true, $ne: [] }
|
fileIds: { $exists: true, $ne: [] }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,9 +33,9 @@ export default async (params: any, user: ILocalUser) => {
|
||||||
throw 'only one of sinceId, untilId, sinceDate, untilDate can be specified';
|
throw 'only one of sinceId, untilId, sinceDate, untilDate can be specified';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get 'mediaOnly' parameter
|
// Get 'withFiles' parameter
|
||||||
const [mediaOnly, mediaOnlyErr] = $.bool.optional.get(params.mediaOnly);
|
const [withFiles, withFilesErr] = $.bool.optional.get(params.withFiles);
|
||||||
if (mediaOnlyErr) throw 'invalid mediaOnly param';
|
if (withFilesErr) throw 'invalid withFiles param';
|
||||||
|
|
||||||
// ミュートしているユーザーを取得
|
// ミュートしているユーザーを取得
|
||||||
const mutedUserIds = user ? (await Mute.find({
|
const mutedUserIds = user ? (await Mute.find({
|
||||||
|
@ -69,8 +69,8 @@ export default async (params: any, user: ILocalUser) => {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mediaOnly) {
|
if (withFiles) {
|
||||||
query.mediaIds = { $exists: true, $ne: [] };
|
query.fileIds = { $exists: true, $ne: [] };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sinceId) {
|
if (sinceId) {
|
||||||
|
|
|
@ -247,7 +247,7 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) =>
|
||||||
if (media != null) {
|
if (media != null) {
|
||||||
if (media) {
|
if (media) {
|
||||||
push({
|
push({
|
||||||
mediaIds: {
|
fileIds: {
|
||||||
$exists: true,
|
$exists: true,
|
||||||
$ne: null
|
$ne: null
|
||||||
}
|
}
|
||||||
|
@ -255,11 +255,11 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) =>
|
||||||
} else {
|
} else {
|
||||||
push({
|
push({
|
||||||
$or: [{
|
$or: [{
|
||||||
mediaIds: {
|
fileIds: {
|
||||||
$exists: false
|
$exists: false
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
mediaIds: null
|
fileIds: null
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,7 @@ export const meta = {
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
mediaOnly: $.bool.optional.note({
|
withFiles: $.bool.optional.note({
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'true にすると、メディアが添付された投稿だけ取得します'
|
'ja-JP': 'true にすると、メディアが添付された投稿だけ取得します'
|
||||||
}
|
}
|
||||||
|
@ -154,7 +154,7 @@ export default async (params: any, user: ILocalUser) => {
|
||||||
}, {
|
}, {
|
||||||
text: { $ne: null }
|
text: { $ne: null }
|
||||||
}, {
|
}, {
|
||||||
mediaIds: { $ne: [] }
|
fileIds: { $ne: [] }
|
||||||
}, {
|
}, {
|
||||||
poll: { $ne: null }
|
poll: { $ne: null }
|
||||||
}]
|
}]
|
||||||
|
@ -170,7 +170,7 @@ export default async (params: any, user: ILocalUser) => {
|
||||||
}, {
|
}, {
|
||||||
text: { $ne: null }
|
text: { $ne: null }
|
||||||
}, {
|
}, {
|
||||||
mediaIds: { $ne: [] }
|
fileIds: { $ne: [] }
|
||||||
}, {
|
}, {
|
||||||
poll: { $ne: null }
|
poll: { $ne: null }
|
||||||
}]
|
}]
|
||||||
|
@ -186,16 +186,16 @@ export default async (params: any, user: ILocalUser) => {
|
||||||
}, {
|
}, {
|
||||||
text: { $ne: null }
|
text: { $ne: null }
|
||||||
}, {
|
}, {
|
||||||
mediaIds: { $ne: [] }
|
fileIds: { $ne: [] }
|
||||||
}, {
|
}, {
|
||||||
poll: { $ne: null }
|
poll: { $ne: null }
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ps.mediaOnly) {
|
if (ps.withFiles) {
|
||||||
query.$and.push({
|
query.$and.push({
|
||||||
mediaIds: { $exists: true, $ne: [] }
|
fileIds: { $exists: true, $ne: [] }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
|
||||||
}
|
}
|
||||||
|
|
||||||
if (media != undefined) {
|
if (media != undefined) {
|
||||||
query.mediaIds = media ? { $exists: true, $ne: null } : null;
|
query.fileIds = media ? { $exists: true, $ne: null } : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (poll != undefined) {
|
if (poll != undefined) {
|
||||||
|
|
|
@ -73,7 +73,7 @@ export const meta = {
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
mediaOnly: $.bool.optional.note({
|
withFiles: $.bool.optional.note({
|
||||||
desc: {
|
desc: {
|
||||||
'ja-JP': 'true にすると、メディアが添付された投稿だけ取得します'
|
'ja-JP': 'true にすると、メディアが添付された投稿だけ取得します'
|
||||||
}
|
}
|
||||||
|
@ -160,7 +160,7 @@ export default async (params: any, user: ILocalUser) => {
|
||||||
}, {
|
}, {
|
||||||
text: { $ne: null }
|
text: { $ne: null }
|
||||||
}, {
|
}, {
|
||||||
mediaIds: { $ne: [] }
|
fileIds: { $ne: [] }
|
||||||
}, {
|
}, {
|
||||||
poll: { $ne: null }
|
poll: { $ne: null }
|
||||||
}]
|
}]
|
||||||
|
@ -176,7 +176,7 @@ export default async (params: any, user: ILocalUser) => {
|
||||||
}, {
|
}, {
|
||||||
text: { $ne: null }
|
text: { $ne: null }
|
||||||
}, {
|
}, {
|
||||||
mediaIds: { $ne: [] }
|
fileIds: { $ne: [] }
|
||||||
}, {
|
}, {
|
||||||
poll: { $ne: null }
|
poll: { $ne: null }
|
||||||
}]
|
}]
|
||||||
|
@ -192,16 +192,16 @@ export default async (params: any, user: ILocalUser) => {
|
||||||
}, {
|
}, {
|
||||||
text: { $ne: null }
|
text: { $ne: null }
|
||||||
}, {
|
}, {
|
||||||
mediaIds: { $ne: [] }
|
fileIds: { $ne: [] }
|
||||||
}, {
|
}, {
|
||||||
poll: { $ne: null }
|
poll: { $ne: null }
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ps.mediaOnly) {
|
if (ps.withFiles) {
|
||||||
query.$and.push({
|
query.$and.push({
|
||||||
mediaIds: { $exists: true, $ne: [] }
|
fileIds: { $exists: true, $ne: [] }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,9 +27,9 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) =>
|
||||||
const [includeReplies = true, includeRepliesErr] = $.bool.optional.get(params.includeReplies);
|
const [includeReplies = true, includeRepliesErr] = $.bool.optional.get(params.includeReplies);
|
||||||
if (includeRepliesErr) return rej('invalid includeReplies param');
|
if (includeRepliesErr) return rej('invalid includeReplies param');
|
||||||
|
|
||||||
// Get 'withMedia' parameter
|
// Get 'withFiles' parameter
|
||||||
const [withMedia = false, withMediaErr] = $.bool.optional.get(params.withMedia);
|
const [withFiles = false, withFilesErr] = $.bool.optional.get(params.withFiles);
|
||||||
if (withMediaErr) return rej('invalid withMedia param');
|
if (withFilesErr) return rej('invalid withFiles param');
|
||||||
|
|
||||||
// Get 'limit' parameter
|
// Get 'limit' parameter
|
||||||
const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
|
const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
|
||||||
|
@ -104,8 +104,8 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) =>
|
||||||
query.replyId = null;
|
query.replyId = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (withMedia) {
|
if (withFiles) {
|
||||||
query.mediaIds = {
|
query.fileIds = {
|
||||||
$exists: true,
|
$exists: true,
|
||||||
$ne: []
|
$ne: []
|
||||||
};
|
};
|
||||||
|
|
|
@ -84,7 +84,7 @@ type Option = {
|
||||||
text?: string;
|
text?: string;
|
||||||
reply?: INote;
|
reply?: INote;
|
||||||
renote?: INote;
|
renote?: INote;
|
||||||
media?: IDriveFile[];
|
files?: IDriveFile[];
|
||||||
geo?: any;
|
geo?: any;
|
||||||
poll?: any;
|
poll?: any;
|
||||||
viaMobile?: boolean;
|
viaMobile?: boolean;
|
||||||
|
@ -135,7 +135,7 @@ export default async (user: IUser, data: Option, silent = false) => new Promise<
|
||||||
|
|
||||||
const mentionedUsers = await extractMentionedUsers(tokens);
|
const mentionedUsers = await extractMentionedUsers(tokens);
|
||||||
|
|
||||||
const note = await insertNote(user, data, tokens, tags, mentionedUsers);
|
const note = await insertNote(user, data, tags, mentionedUsers);
|
||||||
|
|
||||||
res(note);
|
res(note);
|
||||||
|
|
||||||
|
@ -309,10 +309,10 @@ async function publish(user: IUser, note: INote, noteObj: any, reply: INote, ren
|
||||||
publishToUserLists(note, noteObj);
|
publishToUserLists(note, noteObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function insertNote(user: IUser, data: Option, tokens: ReturnType<typeof parse>, tags: string[], mentionedUsers: IUser[]) {
|
async function insertNote(user: IUser, data: Option, tags: string[], mentionedUsers: IUser[]) {
|
||||||
const insert: any = {
|
const insert: any = {
|
||||||
createdAt: data.createdAt,
|
createdAt: data.createdAt,
|
||||||
mediaIds: data.media ? data.media.map(file => file._id) : [],
|
fileIds: data.files ? data.files.map(file => file._id) : [],
|
||||||
replyId: data.reply ? data.reply._id : null,
|
replyId: data.reply ? data.reply._id : null,
|
||||||
renoteId: data.renote ? data.renote._id : null,
|
renoteId: data.renote ? data.renote._id : null,
|
||||||
text: data.text,
|
text: data.text,
|
||||||
|
@ -347,7 +347,8 @@ async function insertNote(user: IUser, data: Option, tokens: ReturnType<typeof p
|
||||||
_user: {
|
_user: {
|
||||||
host: user.host,
|
host: user.host,
|
||||||
inbox: isRemoteUser(user) ? user.inbox : undefined
|
inbox: isRemoteUser(user) ? user.inbox : undefined
|
||||||
}
|
},
|
||||||
|
_files: data.files ? data.files : []
|
||||||
};
|
};
|
||||||
|
|
||||||
if (data.uri != null) insert.uri = data.uri;
|
if (data.uri != null) insert.uri = data.uri;
|
||||||
|
|
|
@ -23,7 +23,7 @@ export default async function(user: IUser, note: INote) {
|
||||||
deletedAt: new Date(),
|
deletedAt: new Date(),
|
||||||
text: null,
|
text: null,
|
||||||
tags: [],
|
tags: [],
|
||||||
mediaIds: [],
|
fileIds: [],
|
||||||
poll: null,
|
poll: null,
|
||||||
geo: null
|
geo: null
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue