From 484d17f53f26ff3e8961d86f03ef94f62f8f62ed Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Sat, 2 Jun 2018 00:15:17 +0900
Subject: [PATCH] wip

---
 .../mobile/views/components/follow-button.vue | 49 ++++++++++++-------
 src/client/app/mobile/views/pages/user.vue    |  1 -
 .../activitypub/kernel/accept/follow.ts       |  2 +-
 src/remote/activitypub/kernel/follow.ts       |  2 +-
 .../activitypub/kernel/reject/follow.ts       |  2 +-
 src/remote/activitypub/kernel/undo/follow.ts  |  2 +-
 src/server/activitypub.ts                     | 19 +++++--
 src/server/api/endpoints.ts                   |  4 +-
 .../following/{request => requests}/accept.ts |  2 +-
 .../following/{request => requests}/reject.ts |  2 +-
 src/server/api/endpoints/i/update.ts          |  2 +-
 .../requests/accept-all.ts}                   |  6 +--
 .../requests/accept.ts}                       | 18 +++----
 .../requests/reject.ts}                       | 12 ++---
 14 files changed, 73 insertions(+), 50 deletions(-)
 rename src/server/api/endpoints/following/{request => requests}/accept.ts (87%)
 rename src/server/api/endpoints/following/{request => requests}/reject.ts (87%)
 rename src/services/{user/accept-all-follow-requests.ts => following/requests/accept-all.ts} (75%)
 rename src/services/{user/accept-follow-request.ts => following/requests/accept.ts} (68%)
 rename src/services/{user/reject-follow-request.ts => following/requests/reject.ts} (52%)

diff --git a/src/client/app/mobile/views/components/follow-button.vue b/src/client/app/mobile/views/components/follow-button.vue
index a6b5cf055..9c363d716 100644
--- a/src/client/app/mobile/views/components/follow-button.vue
+++ b/src/client/app/mobile/views/components/follow-button.vue
@@ -1,13 +1,16 @@
 <template>
 <button class="mk-follow-button"
-	:class="{ wait: wait, follow: !user.isFollowing, unfollow: user.isFollowing }"
+	:class="{ wait: wait, following: user.isFollowing, unfollow: user.isFollowing }"
 	@click="onClick"
 	:disabled="wait"
 >
-	<template v-if="!wait && user.isFollowing">%fa:minus%</template>
-	<template v-if="!wait && !user.isFollowing">%fa:plus%</template>
-	<template v-if="wait">%fa:spinner .pulse .fw%</template>
-	{{ user.isFollowing ? '%i18n:@unfollow%' : '%i18n:@follow%' }}
+	<template v-if="!wait">
+		<template v-if="user.hasPendingFollowRequestFromYou">%fa:hourglass-half% %i18n:@request-pending%</template>
+		<template v-else-if="user.isFollowing">%fa:minus% %i18n:@unfollow%</template>
+		<template v-else-if="!user.isFollowing && user.isLocked">%fa:plus% %i18n:@follow-request%</template>
+		<template v-else-if="!user.isFollowing && !user.isLocked">%fa:plus% %i18n:@follow%</template>
+	</template>
+	<template v-else>%fa:spinner .pulse .fw%</template>
 </button>
 </template>
 
@@ -66,15 +69,27 @@ export default Vue.extend({
 					this.wait = false;
 				});
 			} else {
-				(this as any).api('following/create', {
-					userId: this.user.id
-				}).then(() => {
-					this.user.isFollowing = true;
-				}).catch(err => {
-					console.error(err);
-				}).then(() => {
-					this.wait = false;
-				});
+				if (this.user.isLocked && this.user.hasPendingFollowRequestFromYou) {
+					(this as any).api('following/requests/cancel', {
+						userId: this.user.id
+					}).then(() => {
+						this.user.hasPendingFollowRequestFromYou = false;
+					}).catch(err => {
+						console.error(err);
+					}).then(() => {
+						this.wait = false;
+					});
+				} else {
+					(this as any).api('following/create', {
+						userId: this.user.id
+					}).then(() => {
+						this.user.isFollowing = true;
+					}).catch(err => {
+						console.error(err);
+					}).then(() => {
+						this.wait = false;
+					});
+				}
 			}
 		}
 	}
@@ -90,11 +105,11 @@ export default Vue.extend({
 	cursor pointer
 	padding 0 16px
 	margin 0
-	height inherit
-	font-size 16px
+	line-height 36px
+	font-size 14px
 	outline none
 	border solid 1px $theme-color
-	border-radius 4px
+	border-radius 36px
 
 	*
 		pointer-events none
diff --git a/src/client/app/mobile/views/pages/user.vue b/src/client/app/mobile/views/pages/user.vue
index b3b820650..3d3701590 100644
--- a/src/client/app/mobile/views/pages/user.vue
+++ b/src/client/app/mobile/views/pages/user.vue
@@ -184,7 +184,6 @@ root(isDark)
 
 				> .mk-follow-button
 					float right
-					height 40px
 
 			> .title
 				margin 8px 0
diff --git a/src/remote/activitypub/kernel/accept/follow.ts b/src/remote/activitypub/kernel/accept/follow.ts
index 9d425419a..0f414ba32 100644
--- a/src/remote/activitypub/kernel/accept/follow.ts
+++ b/src/remote/activitypub/kernel/accept/follow.ts
@@ -1,7 +1,7 @@
 import * as mongo from 'mongodb';
 import User, { IRemoteUser } from '../../../../models/user';
 import config from '../../../../config';
-import accept from '../../../../services/user/accept-follow-request';
+import accept from '../../../../services/following/requests/accept';
 import { IFollow } from '../../type';
 
 export default async (actor: IRemoteUser, activity: IFollow): Promise<void> => {
diff --git a/src/remote/activitypub/kernel/follow.ts b/src/remote/activitypub/kernel/follow.ts
index 7e31eb32e..464f8582b 100644
--- a/src/remote/activitypub/kernel/follow.ts
+++ b/src/remote/activitypub/kernel/follow.ts
@@ -23,5 +23,5 @@ export default async (actor: IRemoteUser, activity: IFollow): Promise<void> => {
 		throw new Error('フォローしようとしているユーザーはローカルユーザーではありません');
 	}
 
-	await follow(actor, followee, activity);
+	await follow(actor, followee);
 };
diff --git a/src/remote/activitypub/kernel/reject/follow.ts b/src/remote/activitypub/kernel/reject/follow.ts
index 862f3def3..c139865d0 100644
--- a/src/remote/activitypub/kernel/reject/follow.ts
+++ b/src/remote/activitypub/kernel/reject/follow.ts
@@ -1,7 +1,7 @@
 import * as mongo from 'mongodb';
 import User, { IRemoteUser } from '../../../../models/user';
 import config from '../../../../config';
-import reject from '../../../../services/user/reject-follow-request';
+import reject from '../../../../services/following/requests/reject';
 import { IFollow } from '../../type';
 
 export default async (actor: IRemoteUser, activity: IFollow): Promise<void> => {
diff --git a/src/remote/activitypub/kernel/undo/follow.ts b/src/remote/activitypub/kernel/undo/follow.ts
index c0b10c189..763d5723c 100644
--- a/src/remote/activitypub/kernel/undo/follow.ts
+++ b/src/remote/activitypub/kernel/undo/follow.ts
@@ -23,5 +23,5 @@ export default async (actor: IRemoteUser, activity: IFollow): Promise<void> => {
 		throw new Error('フォロー解除しようとしているユーザーはローカルユーザーではありません');
 	}
 
-	await unfollow(actor, followee, activity);
+	await unfollow(actor, followee);
 };
diff --git a/src/server/activitypub.ts b/src/server/activitypub.ts
index 3c07a3e2f..c846e28c0 100644
--- a/src/server/activitypub.ts
+++ b/src/server/activitypub.ts
@@ -7,7 +7,7 @@ const httpSignature = require('http-signature');
 import { createHttp } from '../queue';
 import pack from '../remote/activitypub/renderer';
 import Note from '../models/note';
-import User, { isLocalUser } from '../models/user';
+import User, { isLocalUser, ILocalUser } from '../models/user';
 import renderNote from '../remote/activitypub/renderer/note';
 import renderKey from '../remote/activitypub/renderer/key';
 import renderPerson from '../remote/activitypub/renderer/person';
@@ -69,7 +69,10 @@ router.get('/notes/:note', async (ctx, next) => {
 router.get('/users/:user/outbox', async ctx => {
 	const userId = new mongo.ObjectID(ctx.params.user);
 
-	const user = await User.findOne({ _id: userId });
+	const user = await User.findOne({
+		_id: userId,
+		host: null
+	});
 
 	if (user === null) {
 		ctx.status = 404;
@@ -91,7 +94,10 @@ router.get('/users/:user/outbox', async ctx => {
 router.get('/users/:user/publickey', async ctx => {
 	const userId = new mongo.ObjectID(ctx.params.user);
 
-	const user = await User.findOne({ _id: userId });
+	const user = await User.findOne({
+		_id: userId,
+		host: null
+	});
 
 	if (user === null) {
 		ctx.status = 404;
@@ -109,14 +115,17 @@ router.get('/users/:user/publickey', async ctx => {
 router.get('/users/:user', async ctx => {
 	const userId = new mongo.ObjectID(ctx.params.user);
 
-	const user = await User.findOne({ _id: userId });
+	const user = await User.findOne({
+		_id: userId,
+		host: null
+	});
 
 	if (user === null) {
 		ctx.status = 404;
 		return;
 	}
 
-	ctx.body = pack(renderPerson(user));
+	ctx.body = pack(renderPerson(user as ILocalUser));
 });
 
 // follow form
diff --git a/src/server/api/endpoints.ts b/src/server/api/endpoints.ts
index bd8f30b38..ad51a249b 100644
--- a/src/server/api/endpoints.ts
+++ b/src/server/api/endpoints.ts
@@ -449,12 +449,12 @@ const endpoints: Endpoint[] = [
 		kind: 'following-write'
 	},
 	{
-		name: 'following/request/accept',
+		name: 'following/requests/accept',
 		withCredential: true,
 		kind: 'following-write'
 	},
 	{
-		name: 'following/request/reject',
+		name: 'following/requests/reject',
 		withCredential: true,
 		kind: 'following-write'
 	},
diff --git a/src/server/api/endpoints/following/request/accept.ts b/src/server/api/endpoints/following/requests/accept.ts
similarity index 87%
rename from src/server/api/endpoints/following/request/accept.ts
rename to src/server/api/endpoints/following/requests/accept.ts
index bf0aff4b7..f8df3b785 100644
--- a/src/server/api/endpoints/following/request/accept.ts
+++ b/src/server/api/endpoints/following/requests/accept.ts
@@ -1,5 +1,5 @@
 import $ from 'cafy'; import ID from '../../../../../cafy-id';
-import acceptFollowRequest from '../../../../../services/user/accept-follow-request';
+import acceptFollowRequest from '../../../../../services/following/requests/accept';
 import User from '../../../../../models/user';
 
 /**
diff --git a/src/server/api/endpoints/following/request/reject.ts b/src/server/api/endpoints/following/requests/reject.ts
similarity index 87%
rename from src/server/api/endpoints/following/request/reject.ts
rename to src/server/api/endpoints/following/requests/reject.ts
index 5a995e196..4900127a5 100644
--- a/src/server/api/endpoints/following/request/reject.ts
+++ b/src/server/api/endpoints/following/requests/reject.ts
@@ -1,5 +1,5 @@
 import $ from 'cafy'; import ID from '../../../../../cafy-id';
-import rejectFollowRequest from '../../../../../services/user/reject-follow-request';
+import rejectFollowRequest from '../../../../../services/following/requests/reject';
 import User from '../../../../../models/user';
 
 /**
diff --git a/src/server/api/endpoints/i/update.ts b/src/server/api/endpoints/i/update.ts
index 103cd3ac3..8ee3c8486 100644
--- a/src/server/api/endpoints/i/update.ts
+++ b/src/server/api/endpoints/i/update.ts
@@ -5,7 +5,7 @@ import $ from 'cafy'; import ID from '../../../../cafy-id';
 import User, { isValidName, isValidDescription, isValidLocation, isValidBirthday, pack } from '../../../../models/user';
 import event from '../../../../publishers/stream';
 import DriveFile from '../../../../models/drive-file';
-import acceptAllFollowRequests from '../../../../services/user/accept-all-follow-requests';
+import acceptAllFollowRequests from '../../../../services/following/requests/accept-all';
 
 /**
  * Update myself
diff --git a/src/services/user/accept-all-follow-requests.ts b/src/services/following/requests/accept-all.ts
similarity index 75%
rename from src/services/user/accept-all-follow-requests.ts
rename to src/services/following/requests/accept-all.ts
index 397a0d7ec..9708d9e65 100644
--- a/src/services/user/accept-all-follow-requests.ts
+++ b/src/services/following/requests/accept-all.ts
@@ -1,6 +1,6 @@
-import User, { IUser } from "../../models/user";
-import FollowRequest from "../../models/follow-request";
-import accept from './accept-follow-request';
+import User, { IUser } from "../../../models/user";
+import FollowRequest from "../../../models/follow-request";
+import accept from './accept';
 
 /**
  * 指定したユーザー宛てのフォローリクエストをすべて承認
diff --git a/src/services/user/accept-follow-request.ts b/src/services/following/requests/accept.ts
similarity index 68%
rename from src/services/user/accept-follow-request.ts
rename to src/services/following/requests/accept.ts
index 8b5c82c84..2dff9b01f 100644
--- a/src/services/user/accept-follow-request.ts
+++ b/src/services/following/requests/accept.ts
@@ -1,12 +1,12 @@
-import User, { IUser, isRemoteUser, ILocalUser } from "../../models/user";
-import FollowRequest from "../../models/follow-request";
-import pack from '../../remote/activitypub/renderer';
-import renderFollow from '../../remote/activitypub/renderer/follow';
-import renderAccept from '../../remote/activitypub/renderer/accept';
-import { deliver } from '../../queue';
-import Following from "../../models/following";
-import FollowingLog from "../../models/following-log";
-import FollowedLog from "../../models/followed-log";
+import User, { IUser, isRemoteUser, ILocalUser } from "../../../models/user";
+import FollowRequest from "../../../models/follow-request";
+import pack from '../../../remote/activitypub/renderer';
+import renderFollow from '../../../remote/activitypub/renderer/follow';
+import renderAccept from '../../../remote/activitypub/renderer/accept';
+import { deliver } from '../../../queue';
+import Following from "../../../models/following";
+import FollowingLog from "../../../models/following-log";
+import FollowedLog from "../../../models/followed-log";
 
 export default async function(followee: IUser, follower: IUser) {
 	const following = await Following.insert({
diff --git a/src/services/user/reject-follow-request.ts b/src/services/following/requests/reject.ts
similarity index 52%
rename from src/services/user/reject-follow-request.ts
rename to src/services/following/requests/reject.ts
index c6388f53e..acd419d0e 100644
--- a/src/services/user/reject-follow-request.ts
+++ b/src/services/following/requests/reject.ts
@@ -1,9 +1,9 @@
-import User, { IUser, isRemoteUser, ILocalUser } from "../../models/user";
-import FollowRequest from "../../models/follow-request";
-import pack from '../../remote/activitypub/renderer';
-import renderFollow from '../../remote/activitypub/renderer/follow';
-import renderReject from '../../remote/activitypub/renderer/reject';
-import { deliver } from '../../queue';
+import User, { IUser, isRemoteUser, ILocalUser } from "../../../models/user";
+import FollowRequest from "../../../models/follow-request";
+import pack from '../../../remote/activitypub/renderer';
+import renderFollow from '../../../remote/activitypub/renderer/follow';
+import renderReject from '../../../remote/activitypub/renderer/reject';
+import { deliver } from '../../../queue';
 
 export default async function(followee: IUser, follower: IUser) {
 	if (isRemoteUser(follower)) {