diff --git a/src/client/app/desktop/views/components/notes.note.vue b/src/client/app/desktop/views/components/notes.note.vue index ae2793db92..6d0e0c8f5c 100644 --- a/src/client/app/desktop/views/components/notes.note.vue +++ b/src/client/app/desktop/views/components/notes.note.vue @@ -34,24 +34,30 @@ <p class="channel" v-if="p.channel"> <a :href="`${_CH_URL_}/${p.channel.id}`" target="_blank">{{ p.channel.title }}</a>: </p> - <div class="text"> - <a class="reply" v-if="p.reply">%fa:reply%</a> - <mk-note-html v-if="p.text" :text="p.text" :i="os.i" :class="$style.text"/> - <a class="rp" v-if="p.renote">RP:</a> + <p v-if="p.cw != null" class="cw"> + <span class="text" v-if="p.cw != ''">{{ p.cw }}</span> + <span class="toggle" @click="showContent = !showContent">{{ showContent ? '隠す' : 'もっと見る' }}</span> + </p> + <div class="content" v-show="p.cw == null || showContent"> + <div class="text"> + <a class="reply" v-if="p.reply">%fa:reply%</a> + <mk-note-html v-if="p.text" :text="p.text" :i="os.i" :class="$style.text"/> + <a class="rp" v-if="p.renote">RP:</a> + </div> + <div class="media" v-if="p.media.length > 0"> + <mk-media-list :media-list="p.media"/> + </div> + <mk-poll v-if="p.poll" :note="p" ref="pollViewer"/> + <div class="tags" v-if="p.tags && p.tags.length > 0"> + <router-link v-for="tag in p.tags" :key="tag" :to="`/search?q=#${tag}`">{{ tag }}</router-link> + </div> + <a class="location" v-if="p.geo" :href="`http://maps.google.com/maps?q=${p.geo.coordinates[1]},${p.geo.coordinates[0]}`" target="_blank">%fa:map-marker-alt% 位置情報</a> + <div class="map" v-if="p.geo" ref="map"></div> + <div class="renote" v-if="p.renote"> + <mk-note-preview :note="p.renote"/> + </div> + <mk-url-preview v-for="url in urls" :url="url" :key="url"/> </div> - <div class="media" v-if="p.media.length > 0"> - <mk-media-list :media-list="p.media"/> - </div> - <mk-poll v-if="p.poll" :note="p" ref="pollViewer"/> - <div class="tags" v-if="p.tags && p.tags.length > 0"> - <router-link v-for="tag in p.tags" :key="tag" :to="`/search?q=#${tag}`">{{ tag }}</router-link> - </div> - <a class="location" v-if="p.geo" :href="`http://maps.google.com/maps?q=${p.geo.coordinates[1]},${p.geo.coordinates[0]}`" target="_blank">%fa:map-marker-alt% 位置情報</a> - <div class="map" v-if="p.geo" ref="map"></div> - <div class="renote" v-if="p.renote"> - <mk-note-preview :note="p.renote"/> - </div> - <mk-url-preview v-for="url in urls" :url="url" :key="url"/> </div> <footer> <mk-reactions-viewer :note="p" ref="reactionsViewer"/> @@ -113,6 +119,7 @@ export default Vue.extend({ data() { return { + showContent: false, isDetailOpened: false, connection: null, connectionId: null @@ -456,7 +463,7 @@ root(isDark) > .body - > .text + > .cw cursor default display block margin 0 @@ -465,90 +472,117 @@ root(isDark) font-size 1.1em color isDark ? #fff : #717171 - >>> .title - display block - margin-bottom 4px - padding 4px - font-size 90% - text-align center - background isDark ? #2f3944 : #eef1f3 - border-radius 4px - - >>> .code - margin 8px 0 - - >>> .quote - margin 8px - padding 6px 12px - color isDark ? #6f808e : #aaa - border-left solid 3px isDark ? #637182 : #eee - - > .reply + > .text margin-right 8px - color isDark ? #99abbf : #717171 - > .rp - margin-left 4px - font-style oblique - color #a0bf46 - - > .location - margin 4px 0 - font-size 12px - color #ccc - - > .map - width 100% - height 300px - - &:empty - display none - - > .tags - margin 4px 0 0 0 - - > * + > .toggle display inline-block - margin 0 8px 0 0 - padding 2px 8px 2px 16px - font-size 90% - color #8d969e - background #edf0f3 - border-radius 4px - - &:before - content "" - display block - position absolute - top 0 - bottom 0 - left 4px - width 8px - height 8px - margin auto 0 - background #fff - border-radius 100% + padding 4px 8px + font-size 0.7em + color isDark ? #393f4f : #fff + background isDark ? #687390 : #b1b9c1 + border-radius 2px + cursor pointer + user-select none &:hover - text-decoration none - background #e2e7ec + background isDark ? #707b97 : #bbc4ce - .mk-url-preview - margin-top 8px + > .content - > .channel - margin 0 + > .text + cursor default + display block + margin 0 + padding 0 + overflow-wrap break-word + font-size 1.1em + color isDark ? #fff : #717171 - > .mk-poll - font-size 80% + >>> .title + display block + margin-bottom 4px + padding 4px + font-size 90% + text-align center + background isDark ? #2f3944 : #eef1f3 + border-radius 4px - > .renote - margin 8px 0 + >>> .code + margin 8px 0 - > .mk-note-preview - padding 16px - border dashed 1px isDark ? #4e945e : #c0dac6 - border-radius 8px + >>> .quote + margin 8px + padding 6px 12px + color isDark ? #6f808e : #aaa + border-left solid 3px isDark ? #637182 : #eee + + > .reply + margin-right 8px + color isDark ? #99abbf : #717171 + + > .rp + margin-left 4px + font-style oblique + color #a0bf46 + + > .location + margin 4px 0 + font-size 12px + color #ccc + + > .map + width 100% + height 300px + + &:empty + display none + + > .tags + margin 4px 0 0 0 + + > * + display inline-block + margin 0 8px 0 0 + padding 2px 8px 2px 16px + font-size 90% + color #8d969e + background #edf0f3 + border-radius 4px + + &:before + content "" + display block + position absolute + top 0 + bottom 0 + left 4px + width 8px + height 8px + margin auto 0 + background #fff + border-radius 100% + + &:hover + text-decoration none + background #e2e7ec + + .mk-url-preview + margin-top 8px + + > .channel + margin 0 + + > .mk-poll + font-size 80% + + > .renote + margin 8px 0 + + > .mk-note-preview + padding 16px + border dashed 1px isDark ? #4e945e : #c0dac6 + border-radius 8px > footer > button diff --git a/src/client/app/desktop/views/components/post-form.vue b/src/client/app/desktop/views/components/post-form.vue index 919f97f44d..80d9d66753 100644 --- a/src/client/app/desktop/views/components/post-form.vue +++ b/src/client/app/desktop/views/components/post-form.vue @@ -6,6 +6,7 @@ @drop.stop="onDrop" > <div class="content"> + <input v-show="useCw" v-model="cw" placeholder="内容への注釈 (オプション)"> <textarea :class="{ with: (files.length != 0 || poll) }" ref="text" v-model="text" :disabled="posting" @keydown="onKeydown" @paste="onPaste" :placeholder="placeholder" @@ -27,6 +28,7 @@ <button class="drive" title="%i18n:@attach-media-from-drive%" @click="chooseFileFromDrive">%fa:cloud%</button> <button class="kao" title="%i18n:@insert-a-kao%" @click="kao">%fa:R smile%</button> <button class="poll" title="%i18n:@create-poll%" @click="poll = true">%fa:chart-pie%</button> + <button class="poll" title="内容を隠す" @click="useCw = !useCw">%fa:eye-slash%</button> <button class="geo" title="位置情報を添付する" @click="geo ? removeGeo() : setGeo()">%fa:map-marker-alt%</button> <p class="text-count" :class="{ over: text.length > 1000 }">{{ '%i18n:!@text-remain%'.replace('{}', 1000 - text.length) }}</p> <button :class="{ posting }" class="submit" :disabled="!canPost" @click="post"> @@ -46,7 +48,9 @@ export default Vue.extend({ components: { XDraggable }, + props: ['reply', 'renote'], + data() { return { posting: false, @@ -54,11 +58,14 @@ export default Vue.extend({ files: [], uploadings: [], poll: false, + useCw: false, + cw: null, geo: null, autocomplete: null, draghover: false }; }, + computed: { draftId(): string { return this.renote @@ -67,6 +74,7 @@ export default Vue.extend({ ? 'reply:' + this.reply.id : 'note'; }, + placeholder(): string { return this.renote ? '%i18n:!@quote-placeholder%' @@ -74,6 +82,7 @@ export default Vue.extend({ ? '%i18n:!@reply-placeholder%' : '%i18n:!@note-placeholder%'; }, + submitText(): string { return this.renote ? '%i18n:!@renote%' @@ -81,21 +90,26 @@ export default Vue.extend({ ? '%i18n:!@reply%' : '%i18n:!@note%'; }, + canPost(): boolean { return !this.posting && (this.text.length != 0 || this.files.length != 0 || this.poll || this.renote); } }, + watch: { text() { this.saveDraft(); }, + poll() { this.saveDraft(); }, + files() { this.saveDraft(); } }, + mounted() { this.$nextTick(() => { // 書きかけの投稿を復元 @@ -113,13 +127,16 @@ export default Vue.extend({ } }); }, + methods: { focus() { (this.$refs.text as any).focus(); }, + chooseFile() { (this.$refs.file as any).click(); }, + chooseFileFromDrive() { (this as any).apis.chooseDriveFile({ multiple: true @@ -127,32 +144,40 @@ export default Vue.extend({ files.forEach(this.attachMedia); }); }, + attachMedia(driveFile) { this.files.push(driveFile); this.$emit('change-attached-media', this.files); }, + detachMedia(id) { this.files = this.files.filter(x => x.id != id); this.$emit('change-attached-media', this.files); }, + onChangeFile() { Array.from((this.$refs.file as any).files).forEach(this.upload); }, + upload(file) { (this.$refs.uploader as any).upload(file); }, + onChangeUploadings(uploads) { this.$emit('change-uploadings', uploads); }, + clear() { this.text = ''; this.files = []; this.poll = false; this.$emit('change-attached-media', this.files); }, + onKeydown(e) { if ((e.which == 10 || e.which == 13) && (e.ctrlKey || e.metaKey)) this.post(); }, + onPaste(e) { Array.from(e.clipboardData.items).forEach((item: any) => { if (item.kind == 'file') { @@ -160,6 +185,7 @@ export default Vue.extend({ } }); }, + onDragover(e) { const isFile = e.dataTransfer.items[0].kind == 'file'; const isDriveFile = e.dataTransfer.types[0] == 'mk_drive_file'; @@ -169,12 +195,15 @@ export default Vue.extend({ e.dataTransfer.dropEffect = e.dataTransfer.effectAllowed == 'all' ? 'copy' : 'move'; } }, + onDragenter(e) { this.draghover = true; }, + onDragleave(e) { this.draghover = false; }, + onDrop(e): void { this.draghover = false; @@ -195,6 +224,7 @@ export default Vue.extend({ } //#endregion }, + setGeo() { if (navigator.geolocation == null) { alert('お使いの端末は位置情報に対応していません'); @@ -210,10 +240,12 @@ export default Vue.extend({ enableHighAccuracy: true }); }, + removeGeo() { this.geo = null; this.$emit('geo-dettached'); }, + post() { this.posting = true; @@ -223,6 +255,7 @@ export default Vue.extend({ replyId: this.reply ? this.reply.id : undefined, renoteId: this.renote ? this.renote.id : undefined, poll: this.poll ? (this.$refs.poll as any).get() : undefined, + cw: this.useCw ? this.cw || '' : undefined, geo: this.geo ? { coordinates: [this.geo.longitude, this.geo.latitude], altitude: this.geo.altitude, @@ -250,6 +283,7 @@ export default Vue.extend({ this.posting = false; }); }, + saveDraft() { const data = JSON.parse(localStorage.getItem('drafts') || '{}'); @@ -264,6 +298,7 @@ export default Vue.extend({ localStorage.setItem('drafts', JSON.stringify(data)); }, + deleteDraft() { const data = JSON.parse(localStorage.getItem('drafts') || '{}'); @@ -271,6 +306,7 @@ export default Vue.extend({ localStorage.setItem('drafts', JSON.stringify(data)); }, + kao() { this.text += getKao(); } @@ -293,47 +329,54 @@ root(isDark) > .content - textarea + > input + > textarea display block - padding 12px - margin 0 width 100% - max-width 100% - min-width 100% - min-height calc(16px + 12px + 12px) + padding 12px font-size 16px color isDark ? #fff : #333 background isDark ? #191d23 : #fff outline none border solid 1px rgba($theme-color, 0.1) border-radius 4px - transition border-color .3s ease + transition border-color .2s ease &:hover border-color rgba($theme-color, 0.2) transition border-color .1s ease - & + * - & + * + * - border-color rgba($theme-color, 0.2) - transition border-color .1s ease - &:focus - color $theme-color border-color rgba($theme-color, 0.5) transition border-color 0s ease - & + * - & + * + * - border-color rgba($theme-color, 0.5) - transition border-color 0s ease - &:disabled opacity 0.5 &::-webkit-input-placeholder color rgba($theme-color, 0.3) + > input + margin-bottom 8px + + > textarea + margin 0 + max-width 100% + min-width 100% + min-height 64px + + &:hover + & + * + & + * + * + border-color rgba($theme-color, 0.2) + transition border-color .1s ease + + &:focus + & + * + & + * + * + border-color rgba($theme-color, 0.5) + transition border-color 0s ease + &.with border-bottom solid 1px rgba($theme-color, 0.1) !important border-radius 4px 4px 0 0 diff --git a/src/client/app/mobile/views/components/note.vue b/src/client/app/mobile/views/components/note.vue index 0967edeec0..ea4f9cb648 100644 --- a/src/client/app/mobile/views/components/note.vue +++ b/src/client/app/mobile/views/components/note.vue @@ -31,27 +31,33 @@ </header> <div class="body"> <p class="channel" v-if="p.channel != null"><a target="_blank">{{ p.channel.title }}</a>:</p> - <div class="text"> - <a class="reply" v-if="p.reply"> - %fa:reply% - </a> - <mk-note-html v-if="p.text" :text="p.text" :i="os.i" :class="$style.text"/> - <a class="rp" v-if="p.renote != null">RP:</a> + <p v-if="p.cw != null" class="cw"> + <span class="text" v-if="p.cw != ''">{{ p.cw }}</span> + <span class="toggle" @click="showContent = !showContent">{{ showContent ? '隠す' : 'もっと見る' }}</span> + </p> + <div class="content" v-show="p.cw == null || showContent"> + <div class="text"> + <a class="reply" v-if="p.reply"> + %fa:reply% + </a> + <mk-note-html v-if="p.text" :text="p.text" :i="os.i" :class="$style.text"/> + <a class="rp" v-if="p.renote != null">RP:</a> + </div> + <div class="media" v-if="p.media.length > 0"> + <mk-media-list :media-list="p.media"/> + </div> + <mk-poll v-if="p.poll" :note="p" ref="pollViewer"/> + <div class="tags" v-if="p.tags && p.tags.length > 0"> + <router-link v-for="tag in p.tags" :key="tag" :to="`/search?q=#${tag}`">{{ tag }}</router-link> + </div> + <mk-url-preview v-for="url in urls" :url="url" :key="url"/> + <a class="location" v-if="p.geo" :href="`http://maps.google.com/maps?q=${p.geo.coordinates[1]},${p.geo.coordinates[0]}`" target="_blank">%fa:map-marker-alt% 位置情報</a> + <div class="map" v-if="p.geo" ref="map"></div> + <div class="renote" v-if="p.renote"> + <mk-note-preview :note="p.renote"/> + </div> </div> - <div class="media" v-if="p.media.length > 0"> - <mk-media-list :media-list="p.media"/> - </div> - <mk-poll v-if="p.poll" :note="p" ref="pollViewer"/> - <div class="tags" v-if="p.tags && p.tags.length > 0"> - <router-link v-for="tag in p.tags" :key="tag" :to="`/search?q=#${tag}`">{{ tag }}</router-link> - </div> - <mk-url-preview v-for="url in urls" :url="url" :key="url"/> - <a class="location" v-if="p.geo" :href="`http://maps.google.com/maps?q=${p.geo.coordinates[1]},${p.geo.coordinates[0]}`" target="_blank">%fa:map-marker-alt% 位置情報</a> - <div class="map" v-if="p.geo" ref="map"></div> <span class="app" v-if="p.app">via <b>{{ p.app.name }}</b></span> - <div class="renote" v-if="p.renote"> - <mk-note-preview :note="p.renote"/> - </div> </div> <footer> <mk-reactions-viewer :note="p" ref="reactionsViewer"/> @@ -92,6 +98,7 @@ export default Vue.extend({ data() { return { + showContent: false, connection: null, connectionId: null }; @@ -229,7 +236,7 @@ export default Vue.extend({ <style lang="stylus" scoped> @import '~const.styl' -.note +root(isDark) font-size 12px border-bottom solid 1px #eaeaea @@ -388,113 +395,140 @@ export default Vue.extend({ > .body - > .text + > .cw + cursor default display block margin 0 padding 0 overflow-wrap break-word font-size 1.1em - color #717171 + color isDark ? #fff : #717171 - >>> .title - display block - margin-bottom 4px - padding 4px - font-size 90% - text-align center - background #eef1f3 - border-radius 4px - - >>> .code - margin 8px 0 - - >>> .quote - margin 8px - padding 6px 12px - color #aaa - border-left solid 3px #eee - - > .reply + > .text margin-right 8px + + > .toggle + display inline-block + padding 4px 8px + font-size 0.7em + color isDark ? #393f4f : #fff + background isDark ? #687390 : #b1b9c1 + border-radius 2px + cursor pointer + user-select none + + &:hover + background isDark ? #707b97 : #bbc4ce + + > .content + + > .text + display block + margin 0 + padding 0 + overflow-wrap break-word + font-size 1.1em color #717171 - > .rp - margin-left 4px - font-style oblique - color #a0bf46 - - [data-is-me]:after - content "you" - padding 0 4px - margin-left 4px - font-size 80% - color $theme-color-foreground - background $theme-color - border-radius 4px - - .mk-url-preview - margin-top 8px - - > .channel - margin 0 - - > .tags - margin 4px 0 0 0 - - > * - display inline-block - margin 0 8px 0 0 - padding 2px 8px 2px 16px - font-size 90% - color #8d969e - background #edf0f3 - border-radius 4px - - &:before - content "" + >>> .title display block - position absolute - top 0 - bottom 0 - left 4px - width 8px - height 8px - margin auto 0 - background #fff - border-radius 100% + margin-bottom 4px + padding 4px + font-size 90% + text-align center + background #eef1f3 + border-radius 4px - > .media - > img - display block - max-width 100% + >>> .code + margin 8px 0 - > .location - margin 4px 0 - font-size 12px - color #ccc + >>> .quote + margin 8px + padding 6px 12px + color #aaa + border-left solid 3px #eee - > .map - width 100% - height 200px + > .reply + margin-right 8px + color #717171 - &:empty - display none + > .rp + margin-left 4px + font-style oblique + color #a0bf46 + + [data-is-me]:after + content "you" + padding 0 4px + margin-left 4px + font-size 80% + color $theme-color-foreground + background $theme-color + border-radius 4px + + .mk-url-preview + margin-top 8px + + > .channel + margin 0 + + > .tags + margin 4px 0 0 0 + + > * + display inline-block + margin 0 8px 0 0 + padding 2px 8px 2px 16px + font-size 90% + color #8d969e + background #edf0f3 + border-radius 4px + + &:before + content "" + display block + position absolute + top 0 + bottom 0 + left 4px + width 8px + height 8px + margin auto 0 + background #fff + border-radius 100% + + > .media + > img + display block + max-width 100% + + > .location + margin 4px 0 + font-size 12px + color #ccc + + > .map + width 100% + height 200px + + &:empty + display none + + > .mk-poll + font-size 80% + + > .renote + margin 8px 0 + + > .mk-note-preview + padding 16px + border dashed 1px #c0dac6 + border-radius 8px > .app font-size 12px color #ccc - > .mk-poll - font-size 80% - - > .renote - margin 8px 0 - - > .mk-note-preview - padding 16px - border dashed 1px #c0dac6 - border-radius 8px - > footer > button margin 0 @@ -524,6 +558,12 @@ export default Vue.extend({ @media (max-width 350px) display none +.note[data-darkmode] + root(true) + +.note:not([data-darkmode]) + root(false) + </style> <style lang="stylus" module> diff --git a/src/client/app/mobile/views/components/post-form.vue b/src/client/app/mobile/views/components/post-form.vue index 861e8653ba..957af3487b 100644 --- a/src/client/app/mobile/views/components/post-form.vue +++ b/src/client/app/mobile/views/components/post-form.vue @@ -10,6 +10,7 @@ </header> <div class="form"> <mk-note-preview v-if="reply" :note="reply"/> + <input v-show="useCw" v-model="cw" placeholder="内容への注釈 (オプション)"> <textarea v-model="text" ref="text" :disabled="posting" :placeholder="reply ? '%i18n:!@reply-placeholder%' : '%i18n:!@note-placeholder%'"></textarea> <div class="attaches" v-show="files.length != 0"> <x-draggable class="files" :list="files" :options="{ animation: 150 }"> @@ -24,6 +25,7 @@ <button class="drive" @click="chooseFileFromDrive">%fa:cloud%</button> <button class="kao" @click="kao">%fa:R smile%</button> <button class="poll" @click="poll = true">%fa:chart-pie%</button> + <button class="poll" @click="useCw = !useCw">%fa:eye-slash%</button> <button class="geo" @click="geo ? removeGeo() : setGeo()">%fa:map-marker-alt%</button> <input ref="file" class="file" type="file" accept="image/*" multiple="multiple" @change="onChangeFile"/> </div> @@ -39,7 +41,9 @@ export default Vue.extend({ components: { XDraggable }, + props: ['reply'], + data() { return { posting: false, @@ -47,21 +51,27 @@ export default Vue.extend({ uploadings: [], files: [], poll: false, - geo: null + geo: null, + useCw: false, + cw: null }; }, + mounted() { this.$nextTick(() => { this.focus(); }); }, + methods: { focus() { (this.$refs.text as any).focus(); }, + chooseFile() { (this.$refs.file as any).click(); }, + chooseFileFromDrive() { (this as any).apis.chooseDriveFile({ multiple: true @@ -69,23 +79,29 @@ export default Vue.extend({ files.forEach(this.attachMedia); }); }, + attachMedia(driveFile) { this.files.push(driveFile); this.$emit('change-attached-media', this.files); }, + detachMedia(file) { this.files = this.files.filter(x => x.id != file.id); this.$emit('change-attached-media', this.files); }, + onChangeFile() { Array.from((this.$refs.file as any).files).forEach(this.upload); }, + upload(file) { (this.$refs.uploader as any).upload(file); }, + onChangeUploadings(uploads) { this.$emit('change-uploadings', uploads); }, + setGeo() { if (navigator.geolocation == null) { alert('お使いの端末は位置情報に対応していません'); @@ -100,15 +116,18 @@ export default Vue.extend({ enableHighAccuracy: true }); }, + removeGeo() { this.geo = null; }, + clear() { this.text = ''; this.files = []; this.poll = false; this.$emit('change-attached-media'); }, + post() { this.posting = true; const viaMobile = (this as any).os.i.clientSettings.disableViaMobile !== true; @@ -117,6 +136,7 @@ export default Vue.extend({ mediaIds: this.files.length > 0 ? this.files.map(f => f.id) : undefined, replyId: this.reply ? this.reply.id : undefined, poll: this.poll ? (this.$refs.poll as any).get() : undefined, + cw: this.useCw ? this.cw || '' : undefined, geo: this.geo ? { coordinates: [this.geo.longitude, this.geo.latitude], altitude: this.geo.altitude, @@ -133,10 +153,12 @@ export default Vue.extend({ this.posting = false; }); }, + cancel() { this.$emit('cancel'); this.$destroy(); }, + kao() { this.text += getKao(); } @@ -236,14 +258,12 @@ export default Vue.extend({ > .file display none + > input > textarea display block padding 12px margin 0 width 100% - max-width 100% - min-width 100% - min-height 80px font-size 16px color #333 border none @@ -253,6 +273,11 @@ export default Vue.extend({ &:disabled opacity 0.5 + > textarea + max-width 100% + min-width 100% + min-height 80px + > .upload > .drive > .kao diff --git a/src/models/note.ts b/src/models/note.ts index 02801b62de..3c835ed190 100644 --- a/src/models/note.ts +++ b/src/models/note.ts @@ -24,7 +24,7 @@ export function isValidText(text: string): boolean { } export function isValidCw(text: string): boolean { - return text.length <= 100 && text.trim() != ''; + return text.length <= 100; } export type INote = { diff --git a/src/server/api/endpoints/notes/create.ts b/src/server/api/endpoints/notes/create.ts index 14e906eb9d..ea1f41aae2 100644 --- a/src/server/api/endpoints/notes/create.ts +++ b/src/server/api/endpoints/notes/create.ts @@ -23,11 +23,11 @@ module.exports = (params, user: ILocalUser, app: IApp) => new Promise(async (res if (visibilityErr) return rej('invalid visibility'); // Get 'text' parameter - const [text, textErr] = $(params.text).optional.string().pipe(isValidText).$; + const [text = null, textErr] = $(params.text).optional.nullable.string().pipe(isValidText).$; if (textErr) return rej('invalid text'); // Get 'cw' parameter - const [cw, cwErr] = $(params.cw).optional.string().pipe(isValidCw).$; + const [cw, cwErr] = $(params.cw).optional.nullable.string().pipe(isValidCw).$; if (cwErr) return rej('invalid cw'); // Get 'viaMobile' parameter @@ -187,14 +187,14 @@ module.exports = (params, user: ILocalUser, app: IApp) => new Promise(async (res const note = await create(user, { createdAt: new Date(), media: files, - poll: poll, - text: text, + poll, + text, reply, renote, - cw: cw, - tags: tags, - app: app, - viaMobile: viaMobile, + cw, + tags, + app, + viaMobile, visibility, geo }); diff --git a/src/services/note/create.ts b/src/services/note/create.ts index 2380e64ce3..e5ad96898f 100644 --- a/src/services/note/create.ts +++ b/src/services/note/create.ts @@ -63,7 +63,7 @@ export default async (user: IUser, data: { renoteId: data.renote ? data.renote._id : null, text: data.text, poll: data.poll, - cw: data.cw, + cw: data.cw == null ? null : data.cw, tags, userId: user._id, viaMobile: data.viaMobile,