From 8d39283d46cfb34b638b085f85761d681dd50605 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Sun, 19 Apr 2020 09:05:20 +0900
Subject: [PATCH] Resolve #6276

---
 locales/ja-JP.yml                             |  2 ++
 src/client/components/page/page.post.vue      | 34 ++++++++++++++++++-
 .../page-editor/els/page-editor.el.post.vue   | 10 ++++--
 src/client/scripts/aoiscript/evaluator.ts     | 10 +++---
 4 files changed, 48 insertions(+), 8 deletions(-)

diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 90b5a0d8c4..787b2e8eeb 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -778,6 +778,8 @@ _pages:
     post: "投稿フォーム"
     _post:
       text: "内容"
+      attachCanvasImage: "キャンバスの画像を添付する"
+      canvasId: "キャンバスID"
 
     textInput: "テキスト入力"
     _textInput:
diff --git a/src/client/components/page/page.post.vue b/src/client/components/page/page.post.vue
index 92a9d653f8..4a04ba5225 100644
--- a/src/client/components/page/page.post.vue
+++ b/src/client/components/page/page.post.vue
@@ -10,6 +10,7 @@ import Vue from 'vue';
 import i18n from '../../i18n';
 import MkTextarea from '../ui/textarea.vue';
 import MkButton from '../ui/button.vue';
+import { apiUrl } from '../../config';
 
 export default Vue.extend({
 	i18n,
@@ -41,10 +42,39 @@ export default Vue.extend({
 		}
 	},
 	methods: {
-		post() {
+		upload() {
+			return new Promise((ok) => {
+				const dialog = this.$root.dialog({
+					type: 'waiting',
+					text: this.$t('uploading') + '...',
+					showOkButton: false,
+					showCancelButton: false,
+					cancelableByBgClick: false
+				});
+				const canvas = this.script.aoiScript.canvases[this.value.canvasId];
+				canvas.toBlob(blob => {
+					const data = new FormData();
+					data.append('file', blob);
+					data.append('i', this.$store.state.i.token);
+
+					fetch(apiUrl + '/drive/files/create', {
+						method: 'POST',
+						body: data
+					})
+					.then(response => response.json())
+					.then(f => {
+						dialog.close();
+						ok(f);
+					})
+				});
+			});
+		},
+		async post() {
 			this.posting = true;
+			const file = this.value.attachCanvasImage ? await this.upload() : null;
 			this.$root.api('notes/create', {
 				text: this.text,
+				fileIds: file ? [file.id] : undefined,
 			}).then(() => {
 				this.posted = true;
 				this.$root.dialog({
@@ -59,9 +89,11 @@ export default Vue.extend({
 
 <style lang="scss" scoped>
 .ngbfujlo {
+	position: relative;
 	padding: 32px;
 	border-radius: 6px;
 	box-shadow: 0 2px 8px var(--shadow);
+	z-index: 1;
 
 	> .button {
 		margin-top: 32px;
diff --git a/src/client/pages/page-editor/els/page-editor.el.post.vue b/src/client/pages/page-editor/els/page-editor.el.post.vue
index 10ec885d0f..2c6ce24e95 100644
--- a/src/client/pages/page-editor/els/page-editor.el.post.vue
+++ b/src/client/pages/page-editor/els/page-editor.el.post.vue
@@ -2,8 +2,10 @@
 <x-container @remove="() => $emit('remove')" :draggable="true">
 	<template #header><fa :icon="faPaperPlane"/> {{ $t('_pages.blocks.post') }}</template>
 
-	<section style="padding: 0 16px 16px 16px;">
+	<section style="padding: 16px;">
 		<mk-textarea v-model="value.text">{{ $t('_pages.blocks._post.text') }}</mk-textarea>
+		<mk-switch v-model="value.attachCanvasImage"><span>{{ $t('_pages.blocks._post.attachCanvasImage') }}</span></mk-switch>
+		<mk-input v-if="value.attachCanvasImage" v-model="value.canvasId"><span>{{ $t('_pages.blocks._post.canvasId') }}</span></mk-input>
 	</section>
 </x-container>
 </template>
@@ -14,12 +16,14 @@ import { faPaperPlane } from '@fortawesome/free-regular-svg-icons';
 import i18n from '../../../i18n';
 import XContainer from '../page-editor.container.vue';
 import MkTextarea from '../../../components/ui/textarea.vue';
+import MkInput from '../../../components/ui/input.vue';
+import MkSwitch from '../../../components/ui/switch.vue';
 
 export default Vue.extend({
 	i18n,
 
 	components: {
-		XContainer, MkTextarea
+		XContainer, MkTextarea, MkInput, MkSwitch
 	},
 
 	props: {
@@ -36,6 +40,8 @@ export default Vue.extend({
 
 	created() {
 		if (this.value.text == null) Vue.set(this.value, 'text', '');
+		if (this.value.attachCanvasImage == null) Vue.set(this.value, 'attachCanvasImage', false);
+		if (this.value.canvasId == null) Vue.set(this.value, 'canvasId', '');
 	},
 });
 </script>
diff --git a/src/client/scripts/aoiscript/evaluator.ts b/src/client/scripts/aoiscript/evaluator.ts
index 5046d4a1bd..446bab19fb 100644
--- a/src/client/scripts/aoiscript/evaluator.ts
+++ b/src/client/scripts/aoiscript/evaluator.ts
@@ -34,7 +34,7 @@ export class ASEvaluator {
 	private envVars: Record<keyof typeof envVarsDef, any>;
 	public aiscript?: AiScript;
 	private pageVarUpdatedCallback;
-	private canvases: Record<string, HTMLCanvasElement> = {};
+	public canvases: Record<string, HTMLCanvasElement> = {};
 
 	private opts: {
 		randomSeed: string; visitor?: any; page?: any; url?: string;
@@ -104,10 +104,10 @@ export class ASEvaluator {
 							},
 							layout: {
 								padding: {
-									left: 0,
-									right: 0,
-									top: 8,
-									bottom: 0
+									left: 32,
+									right: 32,
+									top: opts.value.has('title') ? 16 : 32,
+									bottom: 16
 								}
 							},
 							legend: {