forked from microsoft/vscode-pull-request-github
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGitHubContactServiceProvider.ts
148 lines (131 loc) · 4.27 KB
/
GitHubContactServiceProvider.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import { IAccount } from '../github/interface';
import { RepositoriesManager } from '../github/repositoriesManager';
/**
* The liveshare contact service contract
*/
interface ContactServiceProvider {
requestAsync(type: string, parameters: Object, cancellationToken?: vscode.CancellationToken): Promise<Object>;
readonly onNotified: vscode.Event<NotifyContactServiceEventArgs>;
}
interface NotifyContactServiceEventArgs {
type: string;
body?: any | undefined;
}
/**
* The liveshare public contact contract
*/
interface Contact {
id: string;
displayName?: string | undefined;
email?: string | undefined;
}
/**
* A contact service provider for liveshare that would suggest contacts based on the pull request manager
*/
export class GitHubContactServiceProvider implements ContactServiceProvider {
private readonly onNotifiedEmitter = new vscode.EventEmitter<NotifyContactServiceEventArgs>();
public onNotified: vscode.Event<NotifyContactServiceEventArgs> = this.onNotifiedEmitter.event;
constructor(private readonly pullRequestManager: RepositoriesManager) {
pullRequestManager.folderManagers.forEach(folderManager => {
folderManager.onDidChangeAssignableUsers(e => {
this.notifySuggestedAccounts(e);
});
});
}
public async requestAsync(
type: string,
_parameters: Object,
_cancellationToken?: vscode.CancellationToken,
): Promise<Object> {
let result: Object | null = null;
switch (type) {
case 'initialize':
result = {
description: 'Pullrequest',
capabilities: {
supportsDispose: false,
supportsInviteLink: false,
supportsPresence: false,
supportsContactPresenceRequest: false,
supportsPublishPresence: false,
},
};
// if we get initialized and users are available on the pr manager
const allAssignableUsers: Map<string, IAccount> = new Map();
for (const pullRequestManager of this.pullRequestManager.folderManagers) {
const batch = pullRequestManager.getAllAssignableUsers();
if (!batch) {
continue;
}
for (const user of batch) {
if (!allAssignableUsers.has(user.login)) {
allAssignableUsers.set(user.login, user);
}
}
}
if (allAssignableUsers.size > 0) {
this.notifySuggestedAccounts(Array.from(allAssignableUsers.values()));
}
break;
default:
throw new Error(`type:${type} not supported`);
}
return result;
}
private async notifySuggestedAccounts(accounts: IAccount[]) {
let currentLoginUser: string | undefined;
try {
currentLoginUser = await this.getCurrentUserLogin();
} catch (e) {
// If there are no GitHub repositories at the time of the above call, then we can get an error here.
// Since we don't care about the error and are just trying to notify accounts and not responding to user action,
// it is safe to ignore and leave currentLoginUser undefined.
}
if (currentLoginUser) {
// Note: only suggest if the current user is part of the aggregated mentionable users
if (accounts.findIndex(u => u.login === currentLoginUser) !== -1) {
this.notifySuggestedUsers(
accounts
.filter(u => u.email)
.map(u => {
return {
id: u.login,
displayName: u.name ? u.name : u.login,
email: u.email,
};
}),
true,
);
}
}
}
private async getCurrentUserLogin(): Promise<string | undefined> {
if (this.pullRequestManager.folderManagers.length === 0) {
return undefined;
}
const origin = await this.pullRequestManager.folderManagers[0]?.getOrigin();
if (origin) {
const currentUser = origin.hub.currentUser ? await origin.hub.currentUser : undefined;
if (currentUser) {
return currentUser.login;
}
}
}
private notify(type: string, body: any) {
this.onNotifiedEmitter.fire({
type,
body,
});
}
private notifySuggestedUsers(contacts: Contact[], exclusive?: boolean) {
this.notify('suggestedUsers', {
contacts,
exclusive,
});
}
}