From c039665a9729ba671c2eadf38c7ef06b6000e044 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Sun, 25 Apr 2021 22:32:46 +0900
Subject: [PATCH 1/7] Fix #7481

---
 src/client/components/drive.file.vue         | 2 +-
 src/client/components/drive.folder.vue       | 2 +-
 src/client/components/drive.vue              | 2 +-
 src/client/components/post-form-attaches.vue | 2 +-
 src/client/pages/mentions.vue                | 1 -
 src/client/ui/deck/mentions-column.vue       | 1 -
 6 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/src/client/components/drive.file.vue b/src/client/components/drive.file.vue
index 293465e428..37b1afc1b3 100644
--- a/src/client/components/drive.file.vue
+++ b/src/client/components/drive.file.vue
@@ -81,7 +81,7 @@ export default defineComponent({
 		getMenu() {
 			return [{
 				text: this.$ts.rename,
-				icon: faICursor,
+				icon: 'fas fa-i-cursor',
 				action: this.rename
 			}, {
 				text: this.file.isSensitive ? this.$ts.unmarkAsSensitive : this.$ts.markAsSensitive,
diff --git a/src/client/components/drive.folder.vue b/src/client/components/drive.folder.vue
index 6ddd392527..4c09e7775a 100644
--- a/src/client/components/drive.folder.vue
+++ b/src/client/components/drive.folder.vue
@@ -247,7 +247,7 @@ export default defineComponent({
 				}
 			}, null, {
 				text: this.$ts.rename,
-				icon: faICursor,
+				icon: 'fas fa-i-cursor',
 				action: this.rename
 			}, null, {
 				text: this.$ts.delete,
diff --git a/src/client/components/drive.vue b/src/client/components/drive.vue
index bd5bd8008b..06f9cf7806 100644
--- a/src/client/components/drive.vue
+++ b/src/client/components/drive.vue
@@ -614,7 +614,7 @@ export default defineComponent({
 				type: 'label'
 			}, this.folder ? {
 				text: this.$ts.renameFolder,
-				icon: faICursor,
+				icon: 'fas fa-i-cursor',
 				action: () => { this.renameFolder(this.folder); }
 			} : undefined, this.folder ? {
 				text: this.$ts.deleteFolder,
diff --git a/src/client/components/post-form-attaches.vue b/src/client/components/post-form-attaches.vue
index eba7e7af36..f832ea87b5 100644
--- a/src/client/components/post-form-attaches.vue
+++ b/src/client/components/post-form-attaches.vue
@@ -93,7 +93,7 @@ export default defineComponent({
 			if (this.menu) return;
 			this.menu = os.modalMenu([{
 				text: this.$ts.renameFile,
-				icon: faICursor,
+				icon: 'fas fa-i-cursor',
 				action: () => { this.rename(file) }
 			}, {
 				text: file.isSensitive ? this.$ts.unmarkAsSensitive : this.$ts.markAsSensitive,
diff --git a/src/client/pages/mentions.vue b/src/client/pages/mentions.vue
index a12993ebb8..798d3e342d 100644
--- a/src/client/pages/mentions.vue
+++ b/src/client/pages/mentions.vue
@@ -25,7 +25,6 @@ export default defineComponent({
 				endpoint: 'notes/mentions',
 				limit: 10,
 			},
-			faAt
 		};
 	},
 
diff --git a/src/client/ui/deck/mentions-column.vue b/src/client/ui/deck/mentions-column.vue
index 053ef918f0..c625bb3ea1 100644
--- a/src/client/ui/deck/mentions-column.vue
+++ b/src/client/ui/deck/mentions-column.vue
@@ -36,7 +36,6 @@ export default defineComponent({
 				endpoint: 'notes/mentions',
 				limit: 10,
 			},
-			faAt
 		}
 	},
 

From 8bce241170cd5b40b200c3b00d104677c35ba8e5 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Mon, 26 Apr 2021 10:46:55 +0900
Subject: [PATCH 2/7] :art:

---
 src/client/pages/user/index.vue |  6 +--
 src/client/scripts/theme.ts     |  2 +
 src/client/themes/d-astro.json5 | 76 ++++++++++++++++++++++++++++++
 src/client/themes/l-light.json5 |  2 +-
 src/client/themes/l-vivid.json5 | 82 +++++++++++++++++++++++++++++++++
 5 files changed, 164 insertions(+), 4 deletions(-)
 create mode 100644 src/client/themes/d-astro.json5
 create mode 100644 src/client/themes/l-vivid.json5

diff --git a/src/client/pages/user/index.vue b/src/client/pages/user/index.vue
index a1fe7ec09f..717ca5d8fe 100644
--- a/src/client/pages/user/index.vue
+++ b/src/client/pages/user/index.vue
@@ -161,15 +161,15 @@
 					</dl>
 				</div>
 				<div class="status">
-					<MkA :to="userPage(user)" :class="{ active: page === 'index' }">
+					<MkA :to="userPage(user)" :class="{ active: page === 'index' }" v-click-anime>
 						<b>{{ number(user.notesCount) }}</b>
 						<span>{{ $ts.notes }}</span>
 					</MkA>
-					<MkA :to="userPage(user, 'following')" :class="{ active: page === 'following' }">
+					<MkA :to="userPage(user, 'following')" :class="{ active: page === 'following' }" v-click-anime>
 						<b>{{ number(user.followingCount) }}</b>
 						<span>{{ $ts.following }}</span>
 					</MkA>
-					<MkA :to="userPage(user, 'followers')" :class="{ active: page === 'followers' }">
+					<MkA :to="userPage(user, 'followers')" :class="{ active: page === 'followers' }" v-click-anime>
 						<b>{{ number(user.followersCount) }}</b>
 						<span>{{ $ts.followers }}</span>
 					</MkA>
diff --git a/src/client/scripts/theme.ts b/src/client/scripts/theme.ts
index b0bf620a7d..09441c8a76 100644
--- a/src/client/scripts/theme.ts
+++ b/src/client/scripts/theme.ts
@@ -18,9 +18,11 @@ export const builtinThemes = [
 	require('@client/themes/l-light.json5'),
 	require('@client/themes/l-apricot.json5'),
 	require('@client/themes/l-rainy.json5'),
+	require('@client/themes/l-vivid.json5'),
 
 	require('@client/themes/d-dark.json5'),
 	require('@client/themes/d-persimmon.json5'),
+	require('@client/themes/d-astro.json5'),
 	require('@client/themes/d-black.json5'),
 ] as Theme[];
 
diff --git a/src/client/themes/d-astro.json5 b/src/client/themes/d-astro.json5
new file mode 100644
index 0000000000..a88e949c3c
--- /dev/null
+++ b/src/client/themes/d-astro.json5
@@ -0,0 +1,76 @@
+{
+	id: '080a01c5-377d-4fbb-88cc-6bb5d04977ea',
+	base: 'dark',
+	name: 'Mi Astro',
+	author: 'syuilo',
+	props: {
+		bg: '#232125',
+		fg: '#efdab9',
+		cwBg: '#687390',
+		cwFg: '#393f4f',
+		link: '#78b0a0',
+		warn: '#ecb637',
+		badge: '#31b1ce',
+		error: '#ec4137',
+		focus: ':alpha<0.3<@accent',
+		navBg: '@panel',
+		navFg: '@fg',
+		panel: '#2a272b',
+		accent: '#81c08b',
+		header: ':alpha<0.7<@bg',
+		infoBg: '#253142',
+		infoFg: '#fff',
+		renote: '#659CC8',
+		shadow: 'rgba(0, 0, 0, 0.3)',
+		divider: 'rgba(255, 255, 255, 0.1)',
+		hashtag: '#ff9156',
+		mention: '#ffd152',
+		modalBg: 'rgba(0, 0, 0, 0.5)',
+		success: '#86b300',
+		buttonBg: 'rgba(255, 255, 255, 0.05)',
+		acrylicBg: ':alpha<0.5<@bg',
+		cwHoverBg: '#707b97',
+		indicator: '@accent',
+		mentionMe: '#fb5d38',
+		messageBg: ':lighten<5<@bg',
+		navActive: '@accent',
+		infoWarnBg: '#42321c',
+		infoWarnFg: '#ffbd3e',
+		navHoverFg: ':lighten<17<@fg',
+		dateLabelFg: '@fg',
+		inputBorder: '#959da2',
+		panelBorder: 'rgba(0, 0, 0, 0)',
+		panelShadow: '" 0 8px 24px rgba(0, 0, 0, 0.12)',
+		accentDarken: ':darken<10<@accent',
+		acrylicPanel: ':alpha<0.5<@panel',
+		navIndicator: '@accent',
+		accentLighten: ':lighten<10<@accent',
+		buttonHoverBg: 'rgba(255, 255, 255, 0.1)',
+		driveFolderBg: ':alpha<0.3<@accent',
+		fgHighlighted: ':lighten<3<@fg',
+		panelHeaderBg: ':lighten<3<@panel',
+		panelHeaderFg: '@fg',
+		htmlThemeColor: '@bg',
+		panelHighlight: ':lighten<3<@panel',
+		listItemHoverBg: 'rgba(255, 255, 255, 0.03)',
+		scrollbarHandle: 'rgba(255, 255, 255, 0.2)',
+		wallpaperOverlay: 'rgba(0, 0, 0, 0.5)',
+		panelHeaderDivider: 'rgba(0, 0, 0, 0)',
+		scrollbarHandleHover: 'rgba(255, 255, 255, 0.4)',
+		X2: ':darken<2<@panel',
+		X3: 'rgba(255, 255, 255, 0.05)',
+		X4: 'rgba(255, 255, 255, 0.1)',
+		X5: 'rgba(255, 255, 255, 0.05)',
+		X6: 'rgba(255, 255, 255, 0.15)',
+		X7: 'rgba(255, 255, 255, 0.05)',
+		X8: ':lighten<5<@accent',
+		X9: ':darken<5<@accent',
+		X10: ':alpha<0.4<@accent',
+		X11: 'rgba(0, 0, 0, 0.3)',
+		X12: 'rgba(255, 255, 255, 0.1)',
+		X13: 'rgba(255, 255, 255, 0.15)',
+		X14: ':alpha<0.5<@navBg',
+		X15: ':alpha<0<@panel',
+		X16: ':alpha<0.7<@panel',
+	},
+}
diff --git a/src/client/themes/l-light.json5 b/src/client/themes/l-light.json5
index fdc1700b95..27a973c88a 100644
--- a/src/client/themes/l-light.json5
+++ b/src/client/themes/l-light.json5
@@ -10,7 +10,7 @@
 	props: {
 		bg: '#f9f9f9',
 		fg: '#676767',
-		divider: 'rgb(223, 223, 223)',
+		divider: '#e8e8e8',
 		header: ':alpha<0.7<@panel',
 		navBg: '#fff',
 		panel: '#fff',
diff --git a/src/client/themes/l-vivid.json5 b/src/client/themes/l-vivid.json5
new file mode 100644
index 0000000000..a21e053b0a
--- /dev/null
+++ b/src/client/themes/l-vivid.json5
@@ -0,0 +1,82 @@
+{
+	id: '6128c2a9-5c54-43fe-a47d-17942356470b',
+
+	name: 'Mi Vivid',
+	author: 'syuilo',
+
+	base: 'light',
+
+	props: {
+		bg: '#fafafa',
+		fg: '#444',
+		cwBg: '#b1b9c1',
+		cwFg: '#fff',
+		link: '#ff9400',
+		warn: '#ecb637',
+		badge: '#31b1ce',
+		error: '#ec4137',
+		focus: ':alpha<0.3<@accent',
+		navBg: '@panel',
+		navFg: '@fg',
+		panel: '#fff',
+		accent: '#008cff',
+		header: ':alpha<0.7<@panel',
+		infoBg: '#e5f5ff',
+		infoFg: '#72818a',
+		renote: '@accent',
+		shadow: 'rgba(0, 0, 0, 0.1)',
+		divider: 'rgba(0, 0, 0, 0.08)',
+		hashtag: '#92d400',
+		mention: '@accent',
+		modalBg: 'rgba(0, 0, 0, 0.3)',
+		success: '#86b300',
+		buttonBg: 'rgba(0, 0, 0, 0.05)',
+		acrylicBg: ':alpha<0.5<@bg',
+		cwHoverBg: '#bbc4ce',
+		indicator: '@accent',
+		mentionMe: '@mention',
+		messageBg: '@panel',
+		navActive: '@accent',
+		infoWarnBg: '#fff0db',
+		infoWarnFg: '#573c08',
+		navHoverFg: ':darken<17<@fg',
+		dateLabelFg: '@fg',
+		inputBorder: '#dae0e4',
+		panelBorder: 'rgba(0, 0, 0, 0)',
+		panelShadow: '" 0 8px 24px rgb(21 43 75 / 8%)',
+		accentDarken: ':darken<10<@accent',
+		acrylicPanel: ':alpha<0.5<@panel',
+		navIndicator: '@accent',
+		accentLighten: ':lighten<10<@accent',
+		buttonHoverBg: 'rgba(0, 0, 0, 0.1)',
+		driveFolderBg: ':alpha<0.3<@accent',
+		fgHighlighted: ':darken<3<@fg',
+		fgTransparent: ':alpha<0.5<@fg',
+		panelHeaderBg: ':lighten<3<@panel',
+		panelHeaderFg: '@fg',
+		htmlThemeColor: '@bg',
+		panelHighlight: ':darken<3<@panel',
+		listItemHoverBg: 'rgba(0, 0, 0, 0.03)',
+		scrollbarHandle: 'rgba(0, 0, 0, 0.2)',
+		wallpaperOverlay: 'rgba(255, 255, 255, 0.5)',
+		fgTransparentWeak: ':alpha<0.75<@fg',
+		panelHeaderDivider: '@divider',
+		scrollbarHandleHover: 'rgba(0, 0, 0, 0.4)',
+		X2: ':darken<2<@panel',
+		X3: 'rgba(0, 0, 0, 0.05)',
+		X4: 'rgba(0, 0, 0, 0.1)',
+		X5: 'rgba(0, 0, 0, 0.05)',
+		X6: 'rgba(0, 0, 0, 0.25)',
+		X7: 'rgba(0, 0, 0, 0.05)',
+		X8: ':lighten<5<@accent',
+		X9: ':darken<5<@accent',
+		X10: ':alpha<0.4<@accent',
+		X11: 'rgba(0, 0, 0, 0.1)',
+		X12: 'rgba(0, 0, 0, 0.1)',
+		X13: 'rgba(0, 0, 0, 0.15)',
+		X14: ':alpha<0.5<@navBg',
+		X15: ':alpha<0<@panel',
+		X16: ':alpha<0.7<@panel',
+		X17: ':alpha<0.8<@bg',
+	},
+}

From 42539575a659a6dbf165f0e9c20495a748ce61b6 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Mon, 26 Apr 2021 11:10:45 +0900
Subject: [PATCH 3/7] =?UTF-8?q?=E3=82=AE=E3=83=A3=E3=83=A9=E3=83=AA?=
 =?UTF-8?q?=E3=83=BC=E6=8A=95=E7=A8=BF=E3=81=AE=E7=B7=A8=E9=9B=86=E3=81=A8?=
 =?UTF-8?q?=E5=89=8A=E9=99=A4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/client/pages/gallery/edit.vue             | 168 ++++++++++++++++++
 src/client/pages/gallery/new.vue              | 110 ------------
 src/client/pages/gallery/post.vue             |  10 ++
 src/client/router.ts                          |   3 +-
 .../api/endpoints/gallery/posts/delete.ts     |  40 +++++
 .../api/endpoints/gallery/posts/update.ts     |  81 +++++++++
 6 files changed, 301 insertions(+), 111 deletions(-)
 create mode 100644 src/client/pages/gallery/edit.vue
 delete mode 100644 src/client/pages/gallery/new.vue
 create mode 100644 src/server/api/endpoints/gallery/posts/delete.ts
 create mode 100644 src/server/api/endpoints/gallery/posts/update.ts

diff --git a/src/client/pages/gallery/edit.vue b/src/client/pages/gallery/edit.vue
new file mode 100644
index 0000000000..cd6a0defdd
--- /dev/null
+++ b/src/client/pages/gallery/edit.vue
@@ -0,0 +1,168 @@
+<template>
+<FormBase>
+	<FormSuspense :p="init">
+		<FormInput v-model:value="title">
+			<span>{{ $ts.title }}</span>
+		</FormInput>
+
+		<FormTextarea v-model:value="description" :max="500">
+			<span>{{ $ts.description }}</span>
+		</FormTextarea>
+
+		<FormGroup>
+			<div v-for="file in files" :key="file.id" class="_formItem _formPanel wqugxsfx" :style="{ backgroundImage: file ? `url(${ file.thumbnailUrl })` : null }">
+				<div class="name">{{ file.name }}</div>
+				<button class="remove _button" @click="remove(file)" v-tooltip="$ts.remove"><i class="fas fa-times"></i></button>
+			</div>
+			<FormButton @click="selectFile" primary><i class="fas fa-plus"></i> {{ $ts.attachFile }}</FormButton>
+		</FormGroup>
+
+		<FormSwitch v-model:value="isSensitive">{{ $ts.markAsSensitive }}</FormSwitch>
+
+		<FormButton v-if="postId" @click="save" primary><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
+		<FormButton v-else @click="save" primary><i class="fas fa-save"></i> {{ $ts.publish }}</FormButton>
+
+		<FormButton v-if="postId" @click="del" danger><i class="fas fa-trash-alt"></i> {{ $ts.delete }}</FormButton>
+	</FormSuspense>
+</FormBase>
+</template>
+
+<script lang="ts">
+import { computed, defineComponent } from 'vue';
+import FormButton from '@client/components/form/button.vue';
+import FormInput from '@client/components/form/input.vue';
+import FormTextarea from '@client/components/form/textarea.vue';
+import FormSwitch from '@client/components/form/switch.vue';
+import FormTuple from '@client/components/form/tuple.vue';
+import FormBase from '@client/components/form/base.vue';
+import FormGroup from '@client/components/form/group.vue';
+import FormSuspense from '@client/components/form/suspense.vue';
+import { selectFile } from '@client/scripts/select-file';
+import * as os from '@client/os';
+import * as symbols from '@client/symbols';
+
+export default defineComponent({
+	components: {
+		FormButton,
+		FormInput,
+		FormTextarea,
+		FormSwitch,
+		FormBase,
+		FormGroup,
+		FormSuspense,
+	},
+
+	props: {
+		postId: {
+			type: String,
+			required: false,
+			default: null,
+		}
+	},
+	
+	data() {
+		return {
+			[symbols.PAGE_INFO]: computed(() => this.postId ? {
+				title: this.$ts.edit,
+				icon: 'fas fa-pencil-alt'
+			} : {
+				title: this.$ts.postToGallery,
+				icon: 'fas fa-pencil-alt'
+			}),
+			init: null,
+			files: [],
+			description: null,
+			title: null,
+			isSensitive: false,
+		}
+	},
+
+	watch: {
+		postId: {
+			handler() {
+				this.init = () => this.postId ? os.api('gallery/posts/show', {
+					postId: this.postId
+				}).then(post => {
+					this.files = post.files;
+					this.title = post.title;
+					this.description = post.description;
+					this.isSensitive = post.isSensitive;
+				}) : Promise.resolve(null);
+			},
+			immediate: true,
+		}
+	},
+
+	methods: {
+		selectFile(e) {
+			selectFile(e.currentTarget || e.target, null, true).then(files => {
+				this.files = this.files.concat(files);
+			});
+		},
+
+		remove(file) {
+			this.files = this.files.filter(f => f.id !== file.id);
+		},
+
+		async save() {
+			if (this.postId) {
+				await os.apiWithDialog('gallery/posts/update', {
+					postId: this.postId,
+					title: this.title,
+					description: this.description,
+					fileIds: this.files.map(file => file.id),
+					isSensitive: this.isSensitive,
+				});
+				this.$router.push(`/gallery/${this.postId}`);
+			} else {
+				const post = await os.apiWithDialog('gallery/posts/create', {
+					title: this.title,
+					description: this.description,
+					fileIds: this.files.map(file => file.id),
+					isSensitive: this.isSensitive,
+				});
+				this.$router.push(`/gallery/${post.id}`);
+			}
+		},
+
+		async del() {
+			const { canceled } = await os.dialog({
+				type: 'warning',
+				text: this.$ts.deleteConfirm,
+				showCancelButton: true
+			});
+			if (canceled) return;
+			await os.apiWithDialog('gallery/posts/delete', {
+				postId: this.postId,
+			});
+			this.$router.push(`/gallery`);
+		}
+	}
+});
+</script>
+
+<style lang="scss" scoped>
+.wqugxsfx {
+	height: 200px;
+	background-size: contain;
+	background-position: center;
+	background-repeat: no-repeat;
+	position: relative;
+
+	> .name {
+		position: absolute;
+		top: 8px;
+		left: 9px;
+		padding: 8px;
+		background: var(--panel);
+	}
+
+	> .remove {
+		position: absolute;
+		top: 8px;
+		right: 9px;
+		padding: 8px;
+		background: var(--panel);
+	}
+}
+</style>
diff --git a/src/client/pages/gallery/new.vue b/src/client/pages/gallery/new.vue
deleted file mode 100644
index 3f9756df8e..0000000000
--- a/src/client/pages/gallery/new.vue
+++ /dev/null
@@ -1,110 +0,0 @@
-<template>
-<FormBase>
-	<FormInput v-model:value="title">
-		<span>{{ $ts.title }}</span>
-	</FormInput>
-
-	<FormTextarea v-model:value="description" :max="500">
-		<span>{{ $ts.description }}</span>
-	</FormTextarea>
-
-	<FormGroup>
-		<div v-for="file in files" :key="file.id" class="_formItem _formPanel wqugxsfx" :style="{ backgroundImage: file ? `url(${ file.thumbnailUrl })` : null }">
-			<div class="name">{{ file.name }}</div>
-			<button class="remove _button" @click="remove(file)" v-tooltip="$ts.remove"><i class="fas fa-times"></i></button>
-		</div>
-		<FormButton @click="selectFile" primary><i class="fas fa-plus"></i> {{ $ts.attachFile }}</FormButton>
-	</FormGroup>
-
-	<FormSwitch v-model:value="isSensitive">{{ $ts.markAsSensitive }}</FormSwitch>
-
-	<FormButton @click="publish" primary><i class="fas fa-save"></i> {{ $ts.publish }}</FormButton>
-</FormBase>
-</template>
-
-<script lang="ts">
-import { defineComponent } from 'vue';
-import FormButton from '@client/components/form/button.vue';
-import FormInput from '@client/components/form/input.vue';
-import FormTextarea from '@client/components/form/textarea.vue';
-import FormSwitch from '@client/components/form/switch.vue';
-import FormTuple from '@client/components/form/tuple.vue';
-import FormBase from '@client/components/form/base.vue';
-import FormGroup from '@client/components/form/group.vue';
-import { selectFile } from '@client/scripts/select-file';
-import * as os from '@client/os';
-import * as symbols from '@client/symbols';
-
-export default defineComponent({
-	components: {
-		FormButton,
-		FormInput,
-		FormTextarea,
-		FormSwitch,
-		FormBase,
-		FormGroup,
-	},
-	
-	data() {
-		return {
-			[symbols.PAGE_INFO]: {
-				title: this.$ts.postToGallery,
-				icon: 'fas fa-pencil-alt'
-			},
-			files: [],
-			description: null,
-			title: null,
-			isSensitive: false,
-		}
-	},
-
-	methods: {
-		selectFile(e) {
-			selectFile(e.currentTarget || e.target, null, true).then(files => {
-				this.files = this.files.concat(files);
-			});
-		},
-
-		remove(file) {
-			this.files = this.files.filter(f => f.id !== file.id);
-		},
-
-		async publish() {
-			const post = await os.apiWithDialog('gallery/posts/create', {
-				title: this.title,
-				description: this.description,
-				fileIds: this.files.map(file => file.id),
-				isSensitive: this.isSensitive,
-			});
-
-			this.$router.push(`/gallery/${post.id}`);
-		}
-	}
-});
-</script>
-
-<style lang="scss" scoped>
-.wqugxsfx {
-	height: 200px;
-	background-size: contain;
-	background-position: center;
-	background-repeat: no-repeat;
-	position: relative;
-
-	> .name {
-		position: absolute;
-		top: 8px;
-		left: 9px;
-		padding: 8px;
-		background: var(--panel);
-	}
-
-	> .remove {
-		position: absolute;
-		top: 8px;
-		right: 9px;
-		padding: 8px;
-		background: var(--panel);
-	}
-}
-</style>
diff --git a/src/client/pages/gallery/post.vue b/src/client/pages/gallery/post.vue
index 9bd102cee2..703506a78d 100644
--- a/src/client/pages/gallery/post.vue
+++ b/src/client/pages/gallery/post.vue
@@ -19,6 +19,7 @@
 						<MkButton class="button" @click="like()" v-else v-tooltip="$ts._gallery.like"><i class="far fa-heart"></i><span class="count" v-if="post.likedCount > 0">{{ post.likedCount }}</span></MkButton>
 					</div>
 					<div class="other">
+						<button v-if="$i && $i.id === post.user.id" class="_button" @click="edit" v-tooltip="$ts.edit" v-click-anime><i class="fas fa-pencil-alt fa-fw"></i></button>
 						<button class="_button" @click="shareWithNote" v-tooltip="$ts.shareWithNote" v-click-anime><i class="fas fa-retweet fa-fw"></i></button>
 						<button class="_button" @click="share" v-tooltip="$ts.share" v-click-anime><i class="fas fa-share-alt fa-fw"></i></button>
 					</div>
@@ -84,6 +85,11 @@ export default defineComponent({
 					title: this.post.title,
 					text: this.post.description,
 				},
+				actions: [{
+					icon: 'fas fa-pencil-alt',
+					text: this.$ts.edit,
+					handler: this.edit
+				}]
 			} : null),
 			otherPostsPagination: {
 				endpoint: 'users/gallery/posts',
@@ -154,6 +160,10 @@ export default defineComponent({
 				this.post.likedCount--;
 			});
 		},
+
+		edit() {
+			this.$router.push(`/gallery/${this.post.id}/edit`);
+		}
 	}
 });
 </script>
diff --git a/src/client/router.ts b/src/client/router.ts
index 5371bf17d9..8dcc1d1eb4 100644
--- a/src/client/router.ts
+++ b/src/client/router.ts
@@ -38,7 +38,8 @@ export const router = createRouter({
 		{ path: '/pages/new', component: page('page-editor/page-editor') },
 		{ path: '/pages/edit/:pageId', component: page('page-editor/page-editor'), props: route => ({ initPageId: route.params.pageId }) },
 		{ path: '/gallery', component: page('gallery/index') },
-		{ path: '/gallery/new', component: page('gallery/new') },
+		{ path: '/gallery/new', component: page('gallery/edit') },
+		{ path: '/gallery/:postId/edit', component: page('gallery/edit'), props: route => ({ postId: route.params.postId }) },
 		{ path: '/gallery/:postId', component: page('gallery/post'), props: route => ({ postId: route.params.postId }) },
 		{ path: '/channels', component: page('channels') },
 		{ path: '/channels/new', component: page('channel-editor') },
diff --git a/src/server/api/endpoints/gallery/posts/delete.ts b/src/server/api/endpoints/gallery/posts/delete.ts
new file mode 100644
index 0000000000..8b54828b20
--- /dev/null
+++ b/src/server/api/endpoints/gallery/posts/delete.ts
@@ -0,0 +1,40 @@
+import $ from 'cafy';
+import define from '../../../define';
+import { ApiError } from '../../../error';
+import { GalleryPosts } from '../../../../../models';
+import { ID } from '@/misc/cafy-id';
+
+export const meta = {
+	tags: ['gallery'],
+
+	requireCredential: true as const,
+
+	kind: 'write:gallery',
+
+	params: {
+		postId: {
+			validator: $.type(ID),
+		},
+	},
+
+	errors: {
+		noSuchPost: {
+			message: 'No such post.',
+			code: 'NO_SUCH_POST',
+			id: 'ae52f367-4bd7-4ecd-afc6-5672fff427f5'
+		},
+	}
+};
+
+export default define(meta, async (ps, user) => {
+	const post = await GalleryPosts.findOne({
+		id: ps.postId,
+		userId: user.id,
+	});
+
+	if (post == null) {
+		throw new ApiError(meta.errors.noSuchPost);
+	}
+
+	await GalleryPosts.delete(post.id);
+});
diff --git a/src/server/api/endpoints/gallery/posts/update.ts b/src/server/api/endpoints/gallery/posts/update.ts
new file mode 100644
index 0000000000..c8bb8d48c9
--- /dev/null
+++ b/src/server/api/endpoints/gallery/posts/update.ts
@@ -0,0 +1,81 @@
+import $ from 'cafy';
+import * as ms from 'ms';
+import define from '../../../define';
+import { ID } from '../../../../../misc/cafy-id';
+import { DriveFiles, GalleryPosts } from '../../../../../models';
+import { GalleryPost } from '../../../../../models/entities/gallery-post';
+import { ApiError } from '../../../error';
+
+export const meta = {
+	tags: ['gallery'],
+
+	requireCredential: true as const,
+
+	kind: 'write:gallery',
+
+	limit: {
+		duration: ms('1hour'),
+		max: 300
+	},
+
+	params: {
+		postId: {
+			validator: $.type(ID),
+		},
+
+		title: {
+			validator: $.str.min(1),
+		},
+
+		description: {
+			validator: $.optional.nullable.str,
+		},
+
+		fileIds: {
+			validator: $.arr($.type(ID)).unique().range(1, 32),
+		},
+
+		isSensitive: {
+			validator: $.optional.bool,
+			default: false,
+		},
+	},
+
+	res: {
+		type: 'object' as const,
+		optional: false as const, nullable: false as const,
+		ref: 'GalleryPost',
+	},
+
+	errors: {
+
+	}
+};
+
+export default define(meta, async (ps, user) => {
+	const files = (await Promise.all(ps.fileIds.map(fileId =>
+		DriveFiles.findOne({
+			id: fileId,
+			userId: user.id
+		})
+	))).filter(file => file != null);
+
+	if (files.length === 0) {
+		throw new Error();
+	}
+
+	await GalleryPosts.update({
+		id: ps.postId,
+		userId: user.id,
+	}, {
+		updatedAt: new Date(),
+		title: ps.title,
+		description: ps.description,
+		isSensitive: ps.isSensitive,
+		fileIds: files.map(file => file.id)
+	});
+
+	const post = await GalleryPosts.findOneOrFail(ps.postId);
+
+	return await GalleryPosts.pack(post, user);
+});

From d348e211d440aa42626b8593666315ea72ae62f5 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Mon, 26 Apr 2021 11:12:34 +0900
Subject: [PATCH 4/7] New Crowdin updates (#7482)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Italian)

* New translations reversi-bot.md (Italian)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Italian)
---
 locales/fr-FR.yml             | 24 ++++++++++-------
 locales/it-IT.yml             | 51 +++++++++++++++++++++++++++++++++++
 src/docs/it-IT/reversi-bot.md |  2 +-
 3 files changed, 66 insertions(+), 11 deletions(-)

diff --git a/locales/fr-FR.yml b/locales/fr-FR.yml
index dcac32e3ef..5500c3a377 100644
--- a/locales/fr-FR.yml
+++ b/locales/fr-FR.yml
@@ -900,11 +900,13 @@ _theme:
   funcKind: "Type de fonction"
   argument: "Argument"
   alpha: "Transparence"
-  darken: "Assombrir"
+  darken: "Sombre"
+  lighten: "Clair"
   inputConstantName: "Insérez un nom de constante"
   importInfo: "Vous pouvez importer un thème vers l’éditeur de thèmes en saisissant son code ici."
   deleteConstantConfirm: "Êtes-vous sûr·e de vouloir supprimer la constante {const} ?"
   keys:
+    accent: "Accentuation"
     bg: "Arrière-plan"
     fg: "Texte"
     focus: "Mise au point"
@@ -940,6 +942,8 @@ _theme:
     driveFolderBg: "Arrière-plan du dossier de disque"
     badge: "Badge"
     messageBg: "Arrière plan de la discussion"
+    accentDarken: "Plus sombre"
+    accentLighten: "Plus clair"
     fgHighlighted: "Texte mis en évidence"
 _sfx:
   note: "Nouvelle note"
@@ -1155,12 +1159,12 @@ _instanceCharts:
   usersTotal: "Nombre d'utilisateur·rice·s au total cumulé"
   notes: "Variation du nombre des notes"
   notesTotal: "Nombre total cumulé des notes"
-  ff: "Variation des abonné·e·s"
-  ffTotal: "Nombre d'abonné·e·s au total cumulé"
+  ff: "Variation des abonné·e·s et des abonnements"
+  ffTotal: "Total cumulé du nombre d'abonné·e·s et du nombre d'abonnements"
   cacheSize: "Variation de la taille du cache"
-  cacheSizeTotal: "La taille du cache au total cumulé"
+  cacheSizeTotal: "Total cumulé de la taille du cache"
   files: "Variation du nombre de fichiers"
-  filesTotal: "Nombre de fichiers au total cumulé"
+  filesTotal: "Total cumulé du nombre de fichiers"
 _timelines:
   home: "Principal"
   local: "Local"
@@ -1237,7 +1241,7 @@ _pages:
   deleted: "La page a été supprimée"
   pageSetting: "Paramètres de la Page"
   nameAlreadyExists: "L'URL de page spécifiée existe déjà"
-  invalidNameTitle: "La URL de la page spécifiée n’est pas valide"
+  invalidNameTitle: "L'URL de page spécifiée n’est pas valide"
   invalidNameText: "Assurez-vous qu’il n’est pas vide"
   editThisPage: "Éditer cette page"
   viewSource: "Afficher la source"
@@ -1259,14 +1263,14 @@ _pages:
   font: "Police de caractères"
   fontSerif: "Serif"
   fontSansSerif: "Sans Serif"
-  eyeCatchingImageSet: "Définir une image attirante"
-  eyeCatchingImageRemove: "Supprimer une image attirante"
+  eyeCatchingImageSet: "Définir une image attractive"
+  eyeCatchingImageRemove: "Supprimer l'image attractive"
   chooseBlock: "Ajouter un bloc"
   selectType: "Choisir un type"
   enterVariableName: "Veuillez entrer un nom pour votre variable"
-  variableNameIsAlreadyUsed: "Cette variable est déjà utilisée"
+  variableNameIsAlreadyUsed: "Ce nom de variable est déjà utilisé"
   contentBlocks: "Contenu"
-  inputBlocks: "Entrée"
+  inputBlocks: "Blocs d'entrée"
   specialBlocks: "Spécial"
   blocks:
     text: "Texte"
diff --git a/locales/it-IT.yml b/locales/it-IT.yml
index b96f3c99a5..cc1178426a 100644
--- a/locales/it-IT.yml
+++ b/locales/it-IT.yml
@@ -571,6 +571,7 @@ useGlobalSetting: "Usa impostazioni generali"
 useGlobalSettingDesc: "Se abilitato, le impostazioni notifiche dell'account verranno utilizzate. Se disabilitato, si possono definire diverse singole impostazioni."
 other: "Avanzate"
 fileIdOrUrl: "ID o URL del file"
+chatOpenBehavior: "Comportamento della finestra di chat quando viene aperta"
 behavior: "Comportamento"
 abuseReports: "Segnala"
 reportAbuse: "Segnala"
@@ -652,8 +653,10 @@ youAreRunningUpToDateClient: "Stai usando la versione più recente del client."
 newVersionOfClientAvailable: "Una nuova versione del tuo client è disponibile."
 usageAmount: "In utilizzo"
 capacity: "Capacità"
+inUse: "In utilizzo"
 editCode: "Modifica codice"
 apply: "Applica"
+receiveAnnouncementFromInstance: "Ricevi i messaggi informativi dall'istanza"
 emailNotification: "Eventi per notifiche via mail"
 publish: "Pubblico"
 inChannelSearch: "Cerca in canale"
@@ -932,6 +935,7 @@ _widgets:
   photos: "Foto"
   digitalClock: "Orologio digitale"
   federation: "Federazione"
+  postForm: "Finestra di pubblicazione"
   button: "Pulsante"
   onlineUsers: "Utenti online"
   jobQueue: "Coda di lavoro"
@@ -1005,6 +1009,9 @@ _instanceCharts:
   users: "Variazione del numero di utenti"
   usersTotal: "Totale cumulativo di utenti"
   notes: "Variazione del numero di note"
+  notesTotal: "Totale cumulato di note"
+  files: "Variazione del numero di file"
+  filesTotal: "Totale cumulato del numero di file"
 _timelines:
   home: "Home"
   local: "Locale"
@@ -1012,8 +1019,16 @@ _timelines:
   global: "Federata"
 _rooms:
   roomOf: "Camera di {user}"
+  addFurniture: "Disponi mobilia"
+  translate: "Sposta"
+  rotate: "Ruota"
+  exit: "Indietro"
   remove: "Togli"
+  clear: "Rimuovi tutto"
+  clearConfirm: "Sei sicur@ di voler rimuovere tutti i mobili dalla tua camera?"
   leaveConfirm: "Hai fatto modifiche ancora non salvate. Vuoi davvero uscire?"
+  chooseImage: "Seleziona immagine"
+  roomType: "Tipo di stanza"
   _roomType:
     default: "Predefinito"
     washitsu: "Washitsu"
@@ -1050,6 +1065,7 @@ _rooms:
     cube: "Cubo"
     tv: "Televisore"
     pinguin: "Pinguino"
+    rubik-cube: "Cubo di Rubik"
     bin: "Cestino"
     cup-noodle: "Noodle istantanei"
 _pages:
@@ -1060,6 +1076,8 @@ _pages:
   updated: "Pagina aggiornata con successo!"
   deleted: "Pagina eliminata"
   pageSetting: "Impostazioni pagina"
+  nameAlreadyExists: "Esiste già una pagina con lo stesso URL."
+  invalidNameTitle: "L'URL di pagina definito non è valido"
   editThisPage: "Modifica questa pagina"
   viewSource: "Visualizza sorgente"
   viewPage: "Visualizza pagina"
@@ -1072,11 +1090,21 @@ _pages:
   content: "Blocco di pagina"
   variables: "Variabili"
   title: "Titolo"
+  url: "URL della pagina"
+  summary: "Riassunto di pagina"
   hideTitleWhenPinned: "Nascondere il titolo pagina quando è fissata in cima al profilo."
   font: "Tipo di carattere"
   fontSerif: "Serif"
   fontSansSerif: "Sans serif"
+  eyeCatchingImageSet: "Imposta un'immagine attrattiva"
+  eyeCatchingImageRemove: "Elimina l'immagine attrattiva"
   chooseBlock: "Aggiungi blocco"
+  selectType: "Seleziona tipo"
+  enterVariableName: "Digita un nome di variabile"
+  variableNameIsAlreadyUsed: "Esiste già una variabile con lo stesso nome"
+  contentBlocks: "Contenuto"
+  inputBlocks: "Blocchi di input"
+  specialBlocks: "Speciale"
   blocks:
     text: "Testo"
     textarea: "Area di testo"
@@ -1086,16 +1114,20 @@ _pages:
     if: "Se"
     _if:
       variable: "Variabili"
+    post: "Finestra di pubblicazione"
     _post:
       text: "Contenuto"
+    textInput: "Immissione testo"
     _textInput:
       name: "Nome della variabile"
       text: "Titolo"
       default: "Valore predefinito"
+    textareaInput: "Immissione testo a più righe"
     _textareaInput:
       name: "Nome della variabile"
       text: "Titolo"
       default: "Valore predefinito"
+    numberInput: "Immissione numerica"
     _numberInput:
       name: "Nome della variabile"
       text: "Titolo"
@@ -1108,24 +1140,35 @@ _pages:
       id: "ID nota"
       idDescription: "Qui puoi anche incollare l'URL della nota che vuoi impostare."
       detailed: "Visualizzazione dettagliata"
+    switch: "Interruttore"
     _switch:
       name: "Nome della variabile"
       text: "Titolo"
       default: "Valore predefinito"
+    counter: "Contatore"
     _counter:
       name: "Nome della variabile"
       text: "Titolo"
+      inc: "Valore da aggiungere"
     _button:
       text: "Titolo"
+      colored: "Colorato"
+      action: "Operazione da eseguire quando viene premuto il pulsante"
       _action:
+        dialog: "Visualizzare una finestra di dialogo"
         _dialog:
           content: "Contenuto"
+        resetRandom: "Ripristinare un numero aleatorio"
         pushEvent: "Inviare evento"
         _pushEvent:
           event: "Nome evento"
           message: "Messaggio da visualizzare quando abilitato"
           variable: "Variabile da inviare"
           no-variable: "Nessun contenuto"
+        callAiScript: "Chiamare AiScript"
+        _callAiScript:
+          functionName: "Nome della funzione"
+    radioButton: "Opzioni"
     _radioButton:
       name: "Nome della variabile"
       title: "Titolo"
@@ -1139,6 +1182,8 @@ _pages:
       list: "Liste"
     blocks:
       text: "Testo"
+      multiLineText: "Testo (a più righe)"
+      textList: "Lista di testo"
       _strLen:
         arg1: "Testo"
       _strPick:
@@ -1193,13 +1238,18 @@ _pages:
         arg2: "B"
       _if:
         arg1: "Se"
+        arg2: "Se"
       random: "Aleatorietà"
       _randomPick:
         arg1: "Liste"
       _dailyRandomPick:
         arg1: "Liste"
+      _seedRandom:
+        arg2: "Probabilità"
       _seedRandomPick:
         arg2: "Liste"
+      _DRPWPM:
+        arg1: "Lista di testo"
       _pick:
         arg1: "Liste"
       _listLen:
@@ -1213,6 +1263,7 @@ _pages:
     types:
       string: "Testo"
       array: "Liste"
+      stringArray: "Lista di testo"
 _notification:
   fileUploaded: "File caricato correttamente"
   youGotMention: "{name} ti ha menzionato"
diff --git a/src/docs/it-IT/reversi-bot.md b/src/docs/it-IT/reversi-bot.md
index 7ab2a7212e..00d4a18a8e 100644
--- a/src/docs/it-IT/reversi-bot.md
+++ b/src/docs/it-IT/reversi-bot.md
@@ -110,7 +110,7 @@ y = Math.floor(pos / mapWidth)
 ```
 
 ### フォームコントロールの種類
-#### スイッチ
+#### Interruttore
 type: `switch` スイッチを表示します。何かの機能をオン/オフさせたい場合に有用です。
 
 ##### プロパティ

From 4b205aee913fdfcb9a58f48c13149301f69ce568 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Mon, 26 Apr 2021 12:34:41 +0900
Subject: [PATCH 5/7] Fix #7480

---
 src/server/web/index.ts | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/src/server/web/index.ts b/src/server/web/index.ts
index c3b184088b..cc343063af 100644
--- a/src/server/web/index.ts
+++ b/src/server/web/index.ts
@@ -252,7 +252,7 @@ router.get('/users/:user', async ctx => {
 });
 
 // Note
-router.get('/notes/:note', async ctx => {
+router.get('/notes/:note', async (ctx, next) => {
 	const note = await Notes.findOne(ctx.params.note);
 
 	if (note) {
@@ -277,11 +277,11 @@ router.get('/notes/:note', async ctx => {
 		return;
 	}
 
-	ctx.status = 404;
+	await next();
 });
 
 // Page
-router.get('/@:user/pages/:page', async ctx => {
+router.get('/@:user/pages/:page', async (ctx, next) => {
 	const { username, host } = parseAcct(ctx.params.user);
 	const user = await Users.findOne({
 		usernameLower: username.toLowerCase(),
@@ -314,12 +314,12 @@ router.get('/@:user/pages/:page', async ctx => {
 		return;
 	}
 
-	ctx.status = 404;
+	await next();
 });
 
 // Clip
 // TODO: 非publicなclipのハンドリング
-router.get('/clips/:clip', async ctx => {
+router.get('/clips/:clip', async (ctx, next) => {
 	const clip = await Clips.findOne({
 		id: ctx.params.clip,
 	});
@@ -339,11 +339,11 @@ router.get('/clips/:clip', async ctx => {
 		return;
 	}
 
-	ctx.status = 404;
+	await next();
 });
 
 // Gallery post
-router.get('/gallery/:post', async ctx => {
+router.get('/gallery/:post', async (ctx, next) => {
 	const post = await GalleryPosts.findOne(ctx.params.post);
 
 	if (post) {
@@ -362,11 +362,11 @@ router.get('/gallery/:post', async ctx => {
 		return;
 	}
 
-	ctx.status = 404;
+	await next();
 });
 
 // Channel
-router.get('/channels/:channel', async ctx => {
+router.get('/channels/:channel', async (ctx, next) => {
 	const channel = await Channels.findOne({
 		id: ctx.params.channel,
 	});
@@ -384,7 +384,7 @@ router.get('/channels/:channel', async ctx => {
 		return;
 	}
 
-	ctx.status = 404;
+	await next();
 });
 //#endregion
 

From 77ccf3b929e46f6df1222f70fff936cab449fe21 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Mon, 26 Apr 2021 12:47:54 +0900
Subject: [PATCH 6/7] Fix #7483

---
 src/client/components/captcha.vue | 26 ++++++++++++++++----------
 1 file changed, 16 insertions(+), 10 deletions(-)

diff --git a/src/client/components/captcha.vue b/src/client/components/captcha.vue
index 26215df09d..5da8ede3b9 100644
--- a/src/client/components/captcha.vue
+++ b/src/client/components/captcha.vue
@@ -6,7 +6,7 @@
 </template>
 
 <script lang="ts">
-import { defineComponent } from 'vue';
+import { defineComponent, PropType } from 'vue';
 
 type Captcha = {
 	render(container: string | Node, options: {
@@ -32,7 +32,7 @@ declare global {
 export default defineComponent({
 	props: {
 		provider: {
-			type: String,
+			type: String as PropType<CaptchaProvider>,
 			required: true,
 		},
 		sitekey: {
@@ -51,19 +51,25 @@ export default defineComponent({
 	},
 
 	computed: {
-		loaded() {
-			return !!window[this.provider as CaptchaProvider];
+		variable(): string {
+			switch (this.provider) {
+				case 'hcaptcha': return 'hcaptcha';
+				case 'recaptcha': return 'grecaptcha';
+			}
 		},
-		src() {
+		loaded(): boolean {
+			return !!window[this.variable];
+		},
+		src(): string {
 			const endpoint = ({
 				hcaptcha: 'https://hcaptcha.com/1',
 				recaptcha: 'https://www.recaptcha.net/recaptcha',
-			} as Record<PropertyKey, unknown>)[this.provider];
+			} as Record<CaptchaProvider, string>)[this.provider];
 
-			return `${typeof endpoint == 'string' ? endpoint : 'about:invalid'}/api.js?render=explicit`;
+			return `${typeof endpoint === 'string' ? endpoint : 'about:invalid'}/api.js?render=explicit`;
 		},
-		captcha() {
-			return window[this.provider as CaptchaProvider] || {} as unknown as Captcha;
+		captcha(): Captcha {
+			return window[this.variable] || {} as unknown as Captcha;
 		},
 	},
 
@@ -94,7 +100,7 @@ export default defineComponent({
 
 	methods: {
 		reset() {
-			this.captcha?.reset();
+			if (this.captcha?.reset) this.captcha.reset();
 		},
 		requestRender() {
 			if (this.captcha.render && this.$refs.captcha instanceof Element) {

From fa9f0d9ff9c72b440c6cf9a2218ef071bf62e44d Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Mon, 26 Apr 2021 13:00:01 +0900
Subject: [PATCH 7/7] 12.79.2

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 561c4d08be..0469a3648c 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
 	"name": "misskey",
 	"author": "syuilo <syuilotan@yahoo.co.jp>",
-	"version": "12.79.1",
+	"version": "12.79.2",
 	"codename": "indigo",
 	"repository": {
 		"type": "git",