Merge "Migration of RouterModel to be a non-singleton."
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
index 46e1647..1d66aa5 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
@@ -180,7 +180,7 @@
fireReload,
fireTitleChange,
} from '../../../utils/event-util';
-import {GerritView, routerView$} from '../../../services/router/router-model';
+import {GerritView} from '../../../services/router/router-model';
import {
debounce,
DelayedTask,
@@ -604,6 +604,8 @@
// Private but used in tests.
readonly changeModel = getAppContext().changeModel;
+ private readonly routerModel = getAppContext().routerModel;
+
private readonly commentsModel = getAppContext().commentsModel;
private readonly shortcuts = getAppContext().shortcutsService;
@@ -632,7 +634,7 @@
})
);
this.subscriptions.push(
- routerView$.subscribe(view => {
+ this.routerModel.routerView$.subscribe(view => {
this.isViewCurrent = view === GerritView.CHANGE;
})
);
diff --git a/polygerrit-ui/app/elements/core/gr-router/gr-router.ts b/polygerrit-ui/app/elements/core/gr-router/gr-router.ts
index 027c976..2a35494 100644
--- a/polygerrit-ui/app/elements/core/gr-router/gr-router.ts
+++ b/polygerrit-ui/app/elements/core/gr-router/gr-router.ts
@@ -66,7 +66,7 @@
AppElementParams,
} from '../../gr-app-types';
import {LocationChangeEventDetail} from '../../../types/events';
-import {GerritView, updateState} from '../../../services/router/router-model';
+import {GerritView} from '../../../services/router/router-model';
import {firePageError} from '../../../utils/event-util';
import {addQuotesWhen} from '../../../utils/string-util';
import {windowLocationReload} from '../../../utils/dom-util';
@@ -311,6 +311,8 @@
private readonly reporting = getAppContext().reportingService;
+ private readonly routerModel = getAppContext().routerModel;
+
private readonly restApiService = getAppContext().restApiService;
private readonly flagsService = getAppContext().flagsService;
@@ -323,11 +325,11 @@
}
_setParams(params: AppElementParams | GenerateUrlParameters) {
- updateState(
- params.view,
- 'changeNum' in params ? params.changeNum : undefined,
- 'patchNum' in params ? params.patchNum ?? undefined : undefined
- );
+ this.routerModel.updateState({
+ view: params.view,
+ changeNum: 'changeNum' in params ? params.changeNum : undefined,
+ patchNum: 'patchNum' in params ? params.patchNum ?? undefined : undefined,
+ });
this._appElement().params = params;
}
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts
index e527134..ff02d61 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts
@@ -108,7 +108,7 @@
import {AppElementParams, AppElementDiffViewParam} from '../../gr-app-types';
import {EventType, OpenFixPreviewEvent} from '../../../types/events';
import {fireAlert, fireEvent, fireTitleChange} from '../../../utils/event-util';
-import {GerritView, routerView$} from '../../../services/router/router-model';
+import {GerritView} from '../../../services/router/router-model';
import {assertIsDefined} from '../../../utils/common-util';
import {addGlobalShortcut, Key, toggleClass} from '../../../utils/dom-util';
import {CursorMoveResult} from '../../../api/core';
@@ -356,6 +356,9 @@
private readonly restApiService = getAppContext().restApiService;
// Private but used in tests.
+ readonly routerModel = getAppContext().routerModel;
+
+ // Private but used in tests.
readonly userModel = getAppContext().userModel;
// Private but used in tests.
@@ -420,7 +423,7 @@
this.subscriptions.push(
combineLatest([
this.changeModel.currentPatchNum$,
- routerView$,
+ this.routerModel.routerView$,
this.changeModel.diffPath$,
this.userModel.diffPreferences$,
])
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.js b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.js
index 4c4361d..b2d5a27 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.js
@@ -21,7 +21,7 @@
import {ChangeStatus, DiffViewMode, createDefaultDiffPrefs} from '../../../constants/constants.js';
import {stubRestApi, stubUsers, waitUntil} from '../../../test/test-utils.js';
import {ChangeComments} from '../gr-comment-api/gr-comment-api.js';
-import {GerritView, _testOnly_setState as setRouterModelState} from '../../../services/router/router-model.js';
+import {GerritView} from '../../../services/router/router-model.js';
import {
createChange,
createRevisions,
@@ -1206,7 +1206,7 @@
change: createChange(),
diffPath: '/COMMIT_MSG'});
- setRouterModelState({
+ element.routerModel.setState({
changeNum: TEST_NUMERIC_CHANGE_ID, view: GerritView.DIFF, patchNum: 2}
);
element._patchRange = {
@@ -1245,7 +1245,7 @@
change: createChange(),
diffPath: '/COMMIT_MSG'});
- setRouterModelState({
+ element.routerModel.setState({
changeNum: TEST_NUMERIC_CHANGE_ID, view: GerritView.DIFF,
patchNum: 22}
);
@@ -1271,7 +1271,7 @@
change: createChange(),
diffPath: '/COMMIT_MSG'});
- setRouterModelState({
+ element.routerModel.setState({
changeNum: TEST_NUMERIC_CHANGE_ID, view: GerritView.DIFF, patchNum: 2}
);
diff --git a/polygerrit-ui/app/embed/gr-diff-app-context-init.ts b/polygerrit-ui/app/embed/gr-diff-app-context-init.ts
index 9b3e75d..38ed276 100644
--- a/polygerrit-ui/app/embed/gr-diff-app-context-init.ts
+++ b/polygerrit-ui/app/embed/gr-diff-app-context-init.ts
@@ -96,6 +96,9 @@
userModel: (_ctx: Partial<AppContext>) => {
throw new Error('userModel is not implemented');
},
+ routerModel: (_ctx: Partial<AppContext>) => {
+ throw new Error('routerModel is not implemented');
+ },
shortcutsService: (_ctx: Partial<AppContext>) => {
throw new Error('shortcutsService is not implemented');
},
diff --git a/polygerrit-ui/app/services/app-context-init.ts b/polygerrit-ui/app/services/app-context-init.ts
index 46d2178..fbf5b0f 100644
--- a/polygerrit-ui/app/services/app-context-init.ts
+++ b/polygerrit-ui/app/services/app-context-init.ts
@@ -27,6 +27,7 @@
import {GrStorageService} from './storage/gr-storage_impl';
import {UserModel} from './user/user-model';
import {CommentsModel} from './comments/comments-model';
+import {RouterModel} from './router/router-model';
import {ShortcutsService} from './shortcuts/shortcuts-service';
import {BrowserModel} from './browser/browser-model';
import {assertIsDefined} from '../utils/common-util';
@@ -37,6 +38,7 @@
*/
export function createAppContext(): AppContext & Finalizable {
const appRegistry: Registry<AppContext> = {
+ routerModel: (_ctx: Partial<AppContext>) => new RouterModel(),
flagsService: (_ctx: Partial<AppContext>) =>
new FlagsServiceImplementation(),
reportingService: (ctx: Partial<AppContext>) => {
@@ -54,28 +56,41 @@
return new GrRestApiServiceImpl(ctx.authService!, ctx.flagsService!);
},
changeModel: (ctx: Partial<AppContext>) => {
- assertIsDefined(ctx.restApiService, 'restApiService');
- return new ChangeModel(ctx.restApiService!);
+ const routerModel = ctx.routerModel;
+ const restApiService = ctx.restApiService;
+ assertIsDefined(routerModel, 'routerModel');
+ assertIsDefined(restApiService, 'restApiService');
+ return new ChangeModel(routerModel, restApiService);
},
commentsModel: (ctx: Partial<AppContext>) => {
+ const routerModel = ctx.routerModel;
const changeModel = ctx.changeModel;
const restApiService = ctx.restApiService;
- const reporting = ctx.reportingService;
+ const reportingService = ctx.reportingService;
+ assertIsDefined(routerModel, 'routerModel');
assertIsDefined(changeModel, 'changeModel');
assertIsDefined(restApiService, 'restApiService');
- assertIsDefined(reporting, 'reportingService');
- return new CommentsModel(changeModel, restApiService, reporting);
+ assertIsDefined(reportingService, 'reportingService');
+ return new CommentsModel(
+ routerModel,
+ changeModel,
+ restApiService,
+ reportingService
+ );
},
checksModel: (ctx: Partial<AppContext>) => {
+ const routerModel = ctx.routerModel;
const changeModel = ctx.changeModel;
- const reporting = ctx.reportingService;
+ const reportingService = ctx.reportingService;
+ assertIsDefined(routerModel, 'routerModel');
assertIsDefined(changeModel, 'changeModel');
- assertIsDefined(reporting, 'reportingService');
- return new ChecksModel(changeModel, reporting);
+ assertIsDefined(reportingService, 'reportingService');
+ return new ChecksModel(routerModel, changeModel, reportingService);
},
jsApiService: (ctx: Partial<AppContext>) => {
- assertIsDefined(ctx.reportingService, 'reportingService');
- return new GrJsApiInterface(ctx.reportingService!);
+ const reportingService = ctx.reportingService;
+ assertIsDefined(reportingService, 'reportingService');
+ return new GrJsApiInterface(reportingService!);
},
storageService: (_ctx: Partial<AppContext>) => new GrStorageService(),
configModel: (ctx: Partial<AppContext>) => {
diff --git a/polygerrit-ui/app/services/app-context.ts b/polygerrit-ui/app/services/app-context.ts
index bea371f..367fee7 100644
--- a/polygerrit-ui/app/services/app-context.ts
+++ b/polygerrit-ui/app/services/app-context.ts
@@ -26,11 +26,13 @@
import {StorageService} from './storage/gr-storage';
import {UserModel} from './user/user-model';
import {CommentsModel} from './comments/comments-model';
+import {RouterModel} from './router/router-model';
import {ShortcutsService} from './shortcuts/shortcuts-service';
import {BrowserModel} from './browser/browser-model';
import {ConfigModel} from './config/config-model';
export interface AppContext {
+ routerModel: RouterModel;
flagsService: FlagsService;
reportingService: ReportingService;
eventEmitter: EventEmitterService;
diff --git a/polygerrit-ui/app/services/change/change-model.ts b/polygerrit-ui/app/services/change/change-model.ts
index 6a819f8..7055447 100644
--- a/polygerrit-ui/app/services/change/change-model.ts
+++ b/polygerrit-ui/app/services/change/change-model.ts
@@ -32,14 +32,13 @@
startWith,
switchMap,
} from 'rxjs/operators';
-import {routerPatchNum$, routerState$} from '../router/router-model';
+import {RouterModel} from '../router/router-model';
import {
computeAllPatchSets,
computeLatestPatchNum,
} from '../../utils/patch-set-util';
import {ParsedChangeInfo} from '../../types/types';
-import {routerChangeNum$} from '../router/router-model';
import {ChangeInfo} from '../../types/common';
import {RestApiService} from '../gr-rest-api/gr-rest-api';
import {Finalizable} from '../registry';
@@ -118,7 +117,7 @@
* out inconsistent state, e.g. router changeNum already updated, change not
* yet reset to undefined.
*/
- combineLatest([routerState$, this.changeState$])
+ combineLatest([this.routerModel.routerState$, this.changeState$])
.pipe(
filter(([routerState, changeState]) => {
const changeNum = changeState.change?._number;
@@ -128,7 +127,7 @@
distinctUntilChanged()
)
.pipe(
- withLatestFrom(routerPatchNum$, this.latestPatchNum$),
+ withLatestFrom(this.routerModel.routerPatchNum$, this.latestPatchNum$),
map(([_, routerPatchN, latestPatchN]) => routerPatchN || latestPatchN),
distinctUntilChanged()
);
@@ -142,9 +141,12 @@
'reload'
).pipe(startWith(undefined));
- constructor(readonly restApiService: RestApiService) {
+ constructor(
+ readonly routerModel: RouterModel,
+ readonly restApiService: RestApiService
+ ) {
this.subscriptions = [
- combineLatest([routerChangeNum$, this.reload$])
+ combineLatest([this.routerModel.routerChangeNum$, this.reload$])
.pipe(
map(([changeNum, _]) => changeNum),
switchMap(changeNum => {
diff --git a/polygerrit-ui/app/services/change/change-model_test.ts b/polygerrit-ui/app/services/change/change-model_test.ts
index 099a11f..0fb9712 100644
--- a/polygerrit-ui/app/services/change/change-model_test.ts
+++ b/polygerrit-ui/app/services/change/change-model_test.ts
@@ -28,10 +28,7 @@
import {CommitId, NumericChangeId, PatchSetNum} from '../../types/common';
import {ParsedChangeInfo} from '../../types/types';
import {getAppContext} from '../app-context';
-import {
- GerritView,
- _testOnly_setState as setRouterState,
-} from '../router/router-model';
+import {GerritView} from '../router/router-model';
import {ChangeState, LoadingStatus} from './change-model';
import {ChangeModel} from './change-model';
@@ -40,7 +37,10 @@
let knownChange: ParsedChangeInfo;
const testCompleted = new Subject<void>();
setup(() => {
- changeModel = new ChangeModel(getAppContext().restApiService);
+ changeModel = new ChangeModel(
+ getAppContext().routerModel,
+ getAppContext().restApiService
+ );
knownChange = {
...createChange(),
revisions: {
@@ -80,7 +80,10 @@
assert.equal(stub.callCount, 0);
assert.isUndefined(state?.change);
- setRouterState({view: GerritView.CHANGE, changeNum: knownChange._number});
+ changeModel.routerModel.setState({
+ view: GerritView.CHANGE,
+ changeNum: knownChange._number,
+ });
await waitUntil(() => state?.loadingStatus === LoadingStatus.LOADING);
assert.equal(stub.callCount, 1);
assert.isUndefined(state?.change);
@@ -101,7 +104,10 @@
changeModel.changeState$
.pipe(takeUntil(testCompleted))
.subscribe(s => (state = s));
- setRouterState({view: GerritView.CHANGE, changeNum: knownChange._number});
+ changeModel.routerModel.setState({
+ view: GerritView.CHANGE,
+ changeNum: knownChange._number,
+ });
promise.resolve(knownChange);
await waitUntil(() => state?.loadingStatus === LoadingStatus.LOADED);
@@ -127,7 +133,10 @@
changeModel.changeState$
.pipe(takeUntil(testCompleted))
.subscribe(s => (state = s));
- setRouterState({view: GerritView.CHANGE, changeNum: knownChange._number});
+ changeModel.routerModel.setState({
+ view: GerritView.CHANGE,
+ changeNum: knownChange._number,
+ });
promise.resolve(knownChange);
await waitUntil(() => state?.loadingStatus === LoadingStatus.LOADED);
@@ -138,7 +147,10 @@
_number: 123 as NumericChangeId,
};
promise = mockPromise<ParsedChangeInfo | undefined>();
- setRouterState({view: GerritView.CHANGE, changeNum: otherChange._number});
+ changeModel.routerModel.setState({
+ view: GerritView.CHANGE,
+ changeNum: otherChange._number,
+ });
await waitUntil(() => state?.loadingStatus === LoadingStatus.LOADING);
assert.equal(stub.callCount, 2);
assert.isUndefined(state?.change);
@@ -159,7 +171,10 @@
changeModel.changeState$
.pipe(takeUntil(testCompleted))
.subscribe(s => (state = s));
- setRouterState({view: GerritView.CHANGE, changeNum: knownChange._number});
+ changeModel.routerModel.setState({
+ view: GerritView.CHANGE,
+ changeNum: knownChange._number,
+ });
promise.resolve(knownChange);
await waitUntil(() => state?.loadingStatus === LoadingStatus.LOADED);
@@ -167,7 +182,10 @@
promise = mockPromise<ParsedChangeInfo | undefined>();
promise.resolve(undefined);
- setRouterState({view: GerritView.DASHBOARD, changeNum: undefined});
+ changeModel.routerModel.setState({
+ view: GerritView.CHANGE,
+ changeNum: undefined,
+ });
await waitUntil(() => state?.loadingStatus === LoadingStatus.NOT_LOADED);
assert.equal(stub.callCount, 2);
assert.isUndefined(state?.change);
@@ -176,7 +194,10 @@
promise = mockPromise<ParsedChangeInfo | undefined>();
promise.resolve(knownChange);
- setRouterState({view: GerritView.CHANGE, changeNum: knownChange._number});
+ changeModel.routerModel.setState({
+ view: GerritView.CHANGE,
+ changeNum: knownChange._number,
+ });
await waitUntil(() => state?.loadingStatus === LoadingStatus.LOADED);
assert.equal(stub.callCount, 3);
assert.equal(state?.change, knownChange);
diff --git a/polygerrit-ui/app/services/checks/checks-model.ts b/polygerrit-ui/app/services/checks/checks-model.ts
index 4024747..134afd8 100644
--- a/polygerrit-ui/app/services/checks/checks-model.ts
+++ b/polygerrit-ui/app/services/checks/checks-model.ts
@@ -53,9 +53,9 @@
import {getCurrentRevision} from '../../utils/change-util';
import {getShaByPatchNum} from '../../utils/patch-set-util';
import {ReportingService} from '../gr-reporting/gr-reporting';
-import {routerPatchNum$} from '../router/router-model';
import {Execution} from '../../constants/reporting';
import {fireAlert, fireEvent} from '../../utils/event-util';
+import {RouterModel} from '../router/router-model';
/**
* The checks model maintains the state of checks for two patchsets: the latest
@@ -322,6 +322,7 @@
);
constructor(
+ readonly routerModel: RouterModel,
readonly changeModel: ChangeModel,
readonly reporting: ReportingService
) {
@@ -331,14 +332,14 @@
this.checkToPluginMap = map;
}),
combineLatest([
- routerPatchNum$,
+ this.routerModel.routerPatchNum$,
this.changeModel.latestPatchNum$,
]).subscribe(([routerPs, latestPs]) => {
this.latestPatchNum = latestPs;
if (latestPs === undefined) {
this.setPatchset(undefined);
} else if (typeof routerPs === 'number') {
- this.setPatchset(routerPs);
+ this.setPatchset(routerPs as PatchSetNumber);
} else {
this.setPatchset(latestPs);
}
diff --git a/polygerrit-ui/app/services/checks/checks-model_test.ts b/polygerrit-ui/app/services/checks/checks-model_test.ts
index 0d46289..bb90fe2 100644
--- a/polygerrit-ui/app/services/checks/checks-model_test.ts
+++ b/polygerrit-ui/app/services/checks/checks-model_test.ts
@@ -46,6 +46,7 @@
setup(() => {
model = new ChecksModel(
+ getAppContext().routerModel,
getAppContext().changeModel,
getAppContext().reportingService
);
diff --git a/polygerrit-ui/app/services/comments/comments-model.ts b/polygerrit-ui/app/services/comments/comments-model.ts
index d46e08a..95a1030 100644
--- a/polygerrit-ui/app/services/comments/comments-model.ts
+++ b/polygerrit-ui/app/services/comments/comments-model.ts
@@ -37,7 +37,7 @@
} from '../../utils/comment-util';
import {deepEqual} from '../../utils/deep-util';
import {select} from '../../utils/observable-util';
-import {routerChangeNum$} from '../router/router-model';
+import {RouterModel} from '../router/router-model';
import {Finalizable} from '../registry';
import {combineLatest, Subscription} from 'rxjs';
import {fire, fireAlert, fireEvent} from '../../utils/event-util';
@@ -291,6 +291,7 @@
private discardedDrafts: DraftInfo[] = [];
constructor(
+ readonly routerModel: RouterModel,
readonly changeModel: ChangeModel,
readonly restApiService: RestApiService,
readonly reporting: ReportingService
@@ -305,7 +306,7 @@
this.changeModel.currentPatchNum$.subscribe(x => (this.patchNum = x))
);
this.subscriptions.push(
- routerChangeNum$.subscribe(changeNum => {
+ this.routerModel.routerChangeNum$.subscribe(changeNum => {
this.changeNum = changeNum;
this.setState({...initialState});
this.reloadAllComments();
diff --git a/polygerrit-ui/app/services/comments/comments-model_test.ts b/polygerrit-ui/app/services/comments/comments-model_test.ts
index f39cad8..a8f2118 100644
--- a/polygerrit-ui/app/services/comments/comments-model_test.ts
+++ b/polygerrit-ui/app/services/comments/comments-model_test.ts
@@ -30,10 +30,7 @@
} from '../../test/test-data-generators';
import {stubRestApi, waitUntil, waitUntilCalled} from '../../test/test-utils';
import {getAppContext} from '../app-context';
-import {
- GerritView,
- updateState as updateRouterState,
-} from '../router/router-model';
+import {GerritView} from '../router/router-model';
import {PathToCommentsInfoMap} from '../../types/common';
suite('comments model tests', () => {
@@ -76,6 +73,7 @@
test('loads comments', async () => {
const model = new CommentsModel(
+ getAppContext().routerModel,
getAppContext().changeModel,
getAppContext().restApiService,
getAppContext().reportingService
@@ -102,7 +100,10 @@
model.portedComments$.subscribe(c => (portedComments = c ?? {}))
);
- updateRouterState(GerritView.CHANGE, TEST_NUMERIC_CHANGE_ID);
+ model.routerModel.updateState({
+ view: GerritView.CHANGE,
+ changeNum: TEST_NUMERIC_CHANGE_ID,
+ });
model.changeModel.updateStateChange(createParsedChange());
await waitUntilCalled(diffCommentsSpy, 'diffCommentsSpy');
diff --git a/polygerrit-ui/app/services/router/router-model.ts b/polygerrit-ui/app/services/router/router-model.ts
index f549e859..73dee78 100644
--- a/polygerrit-ui/app/services/router/router-model.ts
+++ b/polygerrit-ui/app/services/router/router-model.ts
@@ -15,9 +15,10 @@
* limitations under the License.
*/
-import {NumericChangeId, PatchSetNum} from '../../types/common';
import {BehaviorSubject, Observable} from 'rxjs';
import {distinctUntilChanged, map} from 'rxjs/operators';
+import {Finalizable} from '../registry';
+import {NumericChangeId, PatchSetNum} from '../../types/common';
export enum GerritView {
ADMIN = 'admin',
@@ -42,57 +43,44 @@
patchNum?: PatchSetNum;
}
-// TODO: Figure out how to best enforce immutability of all states. Use Immer?
-// Use DeepReadOnly?
-const initialState: RouterState = {};
+export class RouterModel implements Finalizable {
+ private readonly privateState$ = new BehaviorSubject<RouterState>({});
-const privateState$ = new BehaviorSubject<RouterState>(initialState);
+ readonly routerView$: Observable<GerritView | undefined>;
-export function _testOnly_resetState() {
- // We cannot assign a new subject to privateState$, because all the selectors
- // have already subscribed to the original subject. So we have to emit the
- // initial state on the existing subject.
- privateState$.next({...initialState});
+ readonly routerChangeNum$: Observable<NumericChangeId | undefined>;
+
+ readonly routerPatchNum$: Observable<PatchSetNum | undefined>;
+
+ constructor() {
+ this.routerView$ = this.privateState$.pipe(
+ map(state => state.view),
+ distinctUntilChanged()
+ );
+ this.routerChangeNum$ = this.privateState$.pipe(
+ map(state => state.changeNum),
+ distinctUntilChanged()
+ );
+ this.routerPatchNum$ = this.privateState$.pipe(
+ map(state => state.patchNum),
+ distinctUntilChanged()
+ );
+ }
+
+ finalize() {}
+
+ setState(state: RouterState) {
+ this.privateState$.next(state);
+ }
+
+ updateState(partial: Partial<RouterState>) {
+ this.privateState$.next({
+ ...this.privateState$.getValue(),
+ ...partial,
+ });
+ }
+
+ get routerState$(): Observable<RouterState> {
+ return this.privateState$;
+ }
}
-
-export function _testOnly_setState(state: RouterState) {
- privateState$.next(state);
-}
-
-export function _testOnly_getState() {
- return privateState$.getValue();
-}
-
-// Re-exporting as Observable so that you can only subscribe, but not emit.
-export const routerState$: Observable<RouterState> = privateState$;
-
-// Must only be used by the router service or whatever is in control of this
-// model.
-// TODO: Consider keeping params of type AppElementParams entirely in the state
-export function updateState(
- view?: GerritView,
- changeNum?: NumericChangeId,
- patchNum?: PatchSetNum
-) {
- privateState$.next({
- ...privateState$.getValue(),
- view,
- changeNum,
- patchNum,
- });
-}
-
-export const routerView$ = routerState$.pipe(
- map(state => state.view),
- distinctUntilChanged()
-);
-
-export const routerChangeNum$ = routerState$.pipe(
- map(state => state.changeNum),
- distinctUntilChanged()
-);
-
-export const routerPatchNum$ = routerState$.pipe(
- map(state => state.patchNum),
- distinctUntilChanged()
-);
diff --git a/polygerrit-ui/app/services/user/user-model.ts b/polygerrit-ui/app/services/user/user-model.ts
index 9107b31d..441c09d 100644
--- a/polygerrit-ui/app/services/user/user-model.ts
+++ b/polygerrit-ui/app/services/user/user-model.ts
@@ -85,7 +85,7 @@
preference => preference.diff_view ?? DiffViewMode.SIDE_BY_SIDE
);
- private readonly subscriptions: Subscription[] = [];
+ private subscriptions: Subscription[] = [];
get userState$(): Observable<UserState> {
return this.privateState$;
@@ -135,7 +135,7 @@
for (const s of this.subscriptions) {
s.unsubscribe();
}
- this.subscriptions.splice(0, this.subscriptions.length);
+ this.subscriptions = [];
}
updatePreferences(prefs: Partial<PreferencesInfo>) {
diff --git a/polygerrit-ui/app/test/common-test-setup.ts b/polygerrit-ui/app/test/common-test-setup.ts
index b8a5e49..94e3f69 100644
--- a/polygerrit-ui/app/test/common-test-setup.ts
+++ b/polygerrit-ui/app/test/common-test-setup.ts
@@ -45,8 +45,6 @@
import {_testOnly_allTasks} from '../utils/async-util';
import {cleanUpStorage} from '../services/storage/gr-storage_mock';
-import {_testOnly_resetState as resetRouterState} from '../services/router/router-model';
-
declare global {
interface Window {
assert: typeof chai.assert;
@@ -111,8 +109,6 @@
// tests.
initGlobalVariables(appContext);
- resetRouterState();
-
const shortcuts = appContext.shortcutsService;
assert.isTrue(shortcuts._testOnly_isEmpty());
const selection = document.getSelection();
diff --git a/polygerrit-ui/app/test/test-app-context-init.ts b/polygerrit-ui/app/test/test-app-context-init.ts
index 01d776e..5f5507b 100644
--- a/polygerrit-ui/app/test/test-app-context-init.ts
+++ b/polygerrit-ui/app/test/test-app-context-init.ts
@@ -30,12 +30,14 @@
import {GrJsApiInterface} from '../elements/shared/gr-js-api-interface/gr-js-api-interface-element';
import {UserModel} from '../services/user/user-model';
import {CommentsModel} from '../services/comments/comments-model';
+import {RouterModel} from '../services/router/router-model';
import {ShortcutsService} from '../services/shortcuts/shortcuts-service';
import {BrowserModel} from '../services/browser/browser-model';
import {ConfigModel} from '../services/config/config-model';
export function createTestAppContext(): AppContext & Finalizable {
const appRegistry: Registry<AppContext> = {
+ routerModel: (_ctx: Partial<AppContext>) => new RouterModel(),
flagsService: (_ctx: Partial<AppContext>) =>
new FlagsServiceImplementation(),
reportingService: (_ctx: Partial<AppContext>) => grReportingMock,
@@ -46,23 +48,36 @@
},
restApiService: (_ctx: Partial<AppContext>) => grRestApiMock,
changeModel: (ctx: Partial<AppContext>) => {
- assertIsDefined(ctx.restApiService, 'restApiService');
- return new ChangeModel(ctx.restApiService!);
+ const routerModel = ctx.routerModel;
+ const restApiService = ctx.restApiService;
+ assertIsDefined(routerModel, 'routerModel');
+ assertIsDefined(restApiService, 'restApiService');
+ return new ChangeModel(routerModel, restApiService);
},
commentsModel: (ctx: Partial<AppContext>) => {
- assertIsDefined(ctx.changeModel, 'changeModel');
- assertIsDefined(ctx.restApiService, 'restApiService');
- assertIsDefined(ctx.reportingService, 'reportingService');
+ const routerModel = ctx.routerModel;
+ const changeModel = ctx.changeModel;
+ const restApiService = ctx.restApiService;
+ const reportingService = ctx.reportingService;
+ assertIsDefined(routerModel, 'routerModel');
+ assertIsDefined(changeModel, 'changeModel');
+ assertIsDefined(restApiService, 'restApiService');
+ assertIsDefined(reportingService, 'reportingService');
return new CommentsModel(
- ctx.changeModel!,
- ctx.restApiService!,
- ctx.reportingService!
+ routerModel,
+ changeModel,
+ restApiService,
+ reportingService
);
},
checksModel: (ctx: Partial<AppContext>) => {
- assertIsDefined(ctx.changeModel, 'changeModel');
- assertIsDefined(ctx.reportingService, 'reportingService');
- return new ChecksModel(ctx.changeModel!, ctx.reportingService!);
+ const routerModel = ctx.routerModel;
+ const changeModel = ctx.changeModel;
+ const reportingService = ctx.reportingService;
+ assertIsDefined(routerModel, 'routerModel');
+ assertIsDefined(changeModel, 'changeModel');
+ assertIsDefined(reportingService, 'reportingService');
+ return new ChecksModel(routerModel, changeModel, reportingService);
},
jsApiService: (ctx: Partial<AppContext>) => {
assertIsDefined(ctx.reportingService, 'reportingService');