Merge "Fix Error Prone warnings"
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts
index 20efa7a..3ddcae4 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts
@@ -324,6 +324,9 @@
mentionedUsers: AccountInput[] = [];
@state()
+ mentionedUsersInUnresolvedDrafts: AccountInfo[] = [];
+
+ @state()
attentionCcsCount = 0;
@state()
@@ -406,8 +409,6 @@
private readonly accountsModel = getAppContext().accountsModel;
- private mentionedUsersInUnresolvedDrafts: AccountInfo[] = [];
-
private latestPatchNum?: PatchSetNumber;
storeTask?: DelayedTask;
@@ -808,6 +809,7 @@
changedProperties.has('ccs') ||
changedProperties.has('change') ||
changedProperties.has('draftCommentThreads') ||
+ changedProperties.has('mentionedUsersInUnresolvedDrafts') ||
changedProperties.has('includeComments') ||
changedProperties.has('labelsChanged') ||
changedProperties.has('patchsetLevelDraftMessage') ||
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.ts b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.ts
index fda4016..a6f33fa 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.ts
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.ts
@@ -50,6 +50,7 @@
ReviewResult,
RevisionPatchSetNum,
Suggestion,
+ Timestamp,
UrlEncodedCommentId,
UserId,
} from '../../../types/common';
@@ -2583,6 +2584,12 @@
});
test('mentioned user in unresolved draft is added to CC and AttentionSet', async () => {
+ stubRestApi('getAccountDetails').returns(
+ Promise.resolve({
+ ...createAccountWithEmail('abcd@def.com' as EmailAddress),
+ registered_on: '2015-03-12 18:32:08.000000000' as Timestamp,
+ })
+ );
const draft = {
...createDraft(),
message: 'hey @abcd@def.com take a look at this',
@@ -2599,7 +2606,9 @@
discardedDrafts: [],
});
element.draftCommentThreads = [createCommentThread([draft])];
- await waitUntil(() => element.mentionedUsers.length > 0);
+ await waitUntil(
+ () => element.mentionedUsersInUnresolvedDrafts.length > 0
+ );
await element.updateComplete;
@@ -2622,6 +2631,12 @@
});
test('mention user can be manually removed from attention set', async () => {
+ stubRestApi('getAccountDetails').returns(
+ Promise.resolve({
+ ...createAccountWithEmail('abcd@def.com' as EmailAddress),
+ registered_on: '2015-03-12 18:32:08.000000000' as Timestamp,
+ })
+ );
const draft = {
...createDraft(),
message: 'hey @abcd@def.com take a look at this',
@@ -2638,7 +2653,9 @@
discardedDrafts: [],
});
element.draftCommentThreads = [createCommentThread([draft])];
- await waitUntil(() => element.mentionedUsers.length > 0);
+ await waitUntil(
+ () => element.mentionedUsersInUnresolvedDrafts.length > 0
+ );
await element.updateComplete;
diff --git a/polygerrit-ui/app/models/accounts-model/accounts-model.ts b/polygerrit-ui/app/models/accounts-model/accounts-model.ts
index d29d30e..74eb813 100644
--- a/polygerrit-ui/app/models/accounts-model/accounts-model.ts
+++ b/polygerrit-ui/app/models/accounts-model/accounts-model.ts
@@ -9,12 +9,15 @@
import {Finalizable} from '../../services/registry';
import {UserId} from '../../types/common';
import {getUserId, isDetailedAccount} from '../../utils/account-util';
+import {define} from '../dependency';
import {Model} from '../model';
export interface AccountsState {
accounts: {[id: UserId]: AccountDetailInfo};
}
+export const accountsModelToken = define<AccountsModel>('accounts-model');
+
export class AccountsModel extends Model<AccountsState> implements Finalizable {
constructor(readonly restApiService: RestApiService) {
super({
diff --git a/polygerrit-ui/app/models/comments/comments-model.ts b/polygerrit-ui/app/models/comments/comments-model.ts
index 5137407..3372b26 100644
--- a/polygerrit-ui/app/models/comments/comments-model.ts
+++ b/polygerrit-ui/app/models/comments/comments-model.ts
@@ -30,7 +30,7 @@
import {RouterModel} from '../../services/router/router-model';
import {Finalizable} from '../../services/registry';
import {define} from '../dependency';
-import {combineLatest, Subscription} from 'rxjs';
+import {combineLatest, forkJoin, from, Observable, Subscription} from 'rxjs';
import {fire, fireAlert, fireEvent} from '../../utils/event-util';
import {CURRENT} from '../../utils/patch-set-util';
import {RestApiService} from '../../services/gr-rest-api/gr-rest-api';
@@ -45,6 +45,14 @@
import {extractMentionedUsers, getUserId} from '../../utils/account-util';
import {EventType} from '../../types/events';
import {SpecialFilePath} from '../../constants/constants';
+import {AccountsModel} from '../accounts-model/accounts-model';
+import {
+ distinctUntilChanged,
+ map,
+ shareReplay,
+ switchMap,
+} from 'rxjs/operators';
+import {notUndefined} from '../../types/types';
export interface CommentState {
/** undefined means 'still loading' */
@@ -283,22 +291,28 @@
);
});
- public readonly mentionedUsersInUnresolvedDrafts$ = select(
- this.drafts$,
- drafts => {
- const users: AccountInfo[] = [];
- const comments = Object.values(drafts ?? {})
- .flat()
- .filter(c => c.unresolved);
- for (const comment of comments) {
- users.push(...extractMentionedUsers(comment.message));
- }
- return users.filter(
- (user, index) =>
- index === users.findIndex(u => getUserId(u) === getUserId(user))
- );
- }
- );
+ public readonly mentionedUsersInUnresolvedDrafts$: Observable<AccountInfo[]> =
+ this.drafts$.pipe(
+ switchMap(drafts => {
+ const users: AccountInfo[] = [];
+ const comments = Object.values(drafts ?? {})
+ .flat()
+ .filter(c => c.unresolved);
+ for (const comment of comments) {
+ users.push(...extractMentionedUsers(comment.message));
+ }
+ const uniqueUsers = users.filter(
+ (user, index) =>
+ index === users.findIndex(u => getUserId(u) === getUserId(user))
+ );
+ const filledUsers$: Observable<AccountInfo | undefined>[] =
+ uniqueUsers.map(user => from(this.accountsModel.fillDetails(user)));
+ return forkJoin(filledUsers$);
+ }),
+ map(users => users.filter(notUndefined)),
+ distinctUntilChanged(deepEqual),
+ shareReplay(1)
+ );
// Emits a new value even if only a single draft is changed. Components should
// aim to subsribe to something more specific.
@@ -358,6 +372,7 @@
constructor(
readonly routerModel: RouterModel,
readonly changeModel: ChangeModel,
+ readonly accountsModel: AccountsModel,
readonly restApiService: RestApiService,
readonly reporting: ReportingService
) {
diff --git a/polygerrit-ui/app/models/comments/comments-model_test.ts b/polygerrit-ui/app/models/comments/comments-model_test.ts
index 9a4a69d..ba7bd2d 100644
--- a/polygerrit-ui/app/models/comments/comments-model_test.ts
+++ b/polygerrit-ui/app/models/comments/comments-model_test.ts
@@ -67,6 +67,7 @@
const model = new CommentsModel(
getAppContext().routerModel,
testResolver(changeModelToken),
+ getAppContext().accountsModel,
getAppContext().restApiService,
getAppContext().reportingService
);
@@ -122,6 +123,7 @@
const model = new CommentsModel(
getAppContext().routerModel,
testResolver(changeModelToken),
+ getAppContext().accountsModel,
getAppContext().restApiService,
getAppContext().reportingService
);
diff --git a/polygerrit-ui/app/services/app-context-init.ts b/polygerrit-ui/app/services/app-context-init.ts
index 244e94f..2dca9a9 100644
--- a/polygerrit-ui/app/services/app-context-init.ts
+++ b/polygerrit-ui/app/services/app-context-init.ts
@@ -92,9 +92,12 @@
);
dependencies.set(changeModelToken, changeModel);
+ const accountsModel = new AccountsModel(appContext.restApiService);
+
const commentsModel = new CommentsModel(
appContext.routerModel,
changeModel,
+ accountsModel,
appContext.restApiService,
appContext.reportingService
);
diff --git a/polygerrit-ui/app/test/test-app-context-init.ts b/polygerrit-ui/app/test/test-app-context-init.ts
index 5bbec45..15857c8 100644
--- a/polygerrit-ui/app/test/test-app-context-init.ts
+++ b/polygerrit-ui/app/test/test-app-context-init.ts
@@ -33,7 +33,10 @@
import {BrowserModel, browserModelToken} from '../models/browser/browser-model';
import {PluginsModel} from '../models/plugins/plugins-model';
import {MockHighlightService} from '../services/highlight/highlight-service-mock';
-import {AccountsModel} from '../models/accounts-model/accounts-model';
+import {
+ AccountsModel,
+ accountsModelToken,
+} from '../models/accounts-model/accounts-model';
export function createTestAppContext(): AppContext & Finalizable {
const appRegistry: Registry<AppContext> = {
@@ -97,10 +100,15 @@
);
dependencies.set(changeModelToken, changeModelCreator);
+ const accountsModelCreator = () =>
+ new AccountsModel(appContext.restApiService);
+ dependencies.set(accountsModelToken, accountsModelCreator);
+
const commentsModelCreator = () =>
new CommentsModel(
appContext.routerModel,
resolver(changeModelToken),
+ resolver(accountsModelToken),
appContext.restApiService,
appContext.reportingService
);