CW
This commit is contained in:
		
							parent
							
								
									4e032a9188
								
							
						
					
					
						commit
						d2d3a7d52b
					
				
					 7 changed files with 374 additions and 232 deletions
				
			
		| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 = {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
	});
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue