Skip to content

Commit 9e0bb64

Browse files
refactor(analytics): remove AnalyticsServiceBase and obsolete static config props
Remove `AnalyticsServiceBase` by moving the required code to `AnalyticsService`. Remove obsolete static config props.
1 parent 5626d05 commit 9e0bb64

File tree

6 files changed

+131
-183
lines changed

6 files changed

+131
-183
lines changed

lib/common/definitions/config.d.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ declare module Config {
66
USER_AGENT_NAME: string;
77
CLIENT_NAME_ALIAS?: string;
88
FULL_CLIENT_NAME?: string;
9-
ANALYTICS_API_KEY: string;
10-
ANALYTICS_EXCEPTIONS_API_KEY: string;
119
ANALYTICS_INSTALLATION_ID_SETTING_NAME: string;
1210
TRACK_FEATURE_USAGE_SETTING_NAME: string;
1311
ERROR_REPORT_SETTING_NAME: string;

lib/common/services/analytics-service-base.ts

Lines changed: 0 additions & 155 deletions
This file was deleted.

lib/common/static-config-base.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ import * as os from "os";
55
export abstract class StaticConfigBase implements Config.IStaticConfig {
66
public PROJECT_FILE_NAME: string = null;
77
public CLIENT_NAME: string = null;
8-
public ANALYTICS_API_KEY: string = null;
9-
public abstract ANALYTICS_EXCEPTIONS_API_KEY: string;
108
public ANALYTICS_INSTALLATION_ID_SETTING_NAME: string = null;
119
public TRACK_FEATURE_USAGE_SETTING_NAME: string = null;
1210
public ERROR_REPORT_SETTING_NAME: string = null;

lib/common/test/unit-tests/analytics-service.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { CommonLoggerStub, ErrorsStub } from "./stubs";
22
import { Yok } from "../../yok";
3-
import { AnalyticsServiceBase } from '../../services/analytics-service-base';
3+
import { AnalyticsService } from '../../../services/analytics/analytics-service';
44
import helpersLib = require("../../helpers");
55
import { HostInfo } from "../../host-info";
66
import { OsInfo } from "../../os-info";
@@ -43,9 +43,10 @@ interface ITestScenario {
4343

4444
function createTestInjector(testScenario: ITestScenario): IInjector {
4545
const testInjector = new Yok();
46+
4647
testInjector.register("logger", CommonLoggerStub);
4748
testInjector.register("errors", ErrorsStub);
48-
testInjector.register("analyticsService", AnalyticsServiceBase);
49+
testInjector.register("analyticsService", AnalyticsService);
4950
testInjector.register("analyticsSettingsService", {
5051
canDoRequest: () => {
5152
return Promise.resolve(testScenario.canDoRequest);
@@ -92,10 +93,14 @@ function createTestInjector(testScenario: ITestScenario): IInjector {
9293
attachToProcessExitSignals: (context: any, callback: () => void): void => (undefined)
9394
});
9495

96+
testInjector.register("childProcess", {});
97+
testInjector.register("projectDataService", {});
98+
testInjector.register("mobileHelper", {});
99+
95100
return testInjector;
96101
}
97102

98-
describe("analytics-service-base", () => {
103+
describe("analytics-service", () => {
99104
let baseTestScenario: ITestScenario;
100105
let service: IAnalyticsService = null;
101106

lib/config.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@ export class StaticConfig extends StaticConfigBase implements IStaticConfig {
2626
public CLIENT_NAME_KEY_IN_PROJECT_FILE = "nativescript";
2727
public CLIENT_NAME = "tns";
2828
public CLIENT_NAME_ALIAS = "NativeScript";
29-
public ANALYTICS_API_KEY = "5752dabccfc54c4ab82aea9626b7338e";
30-
public ANALYTICS_EXCEPTIONS_API_KEY = "35478fe7de68431399e96212540a3d5d";
3129
public TRACK_FEATURE_USAGE_SETTING_NAME = "TrackFeatureUsage";
3230
public ERROR_REPORT_SETTING_NAME = "TrackExceptions";
3331
public ANALYTICS_INSTALLATION_ID_SETTING_NAME = "AnalyticsInstallationID";

lib/services/analytics/analytics-service.ts

Lines changed: 123 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,73 @@
1-
import { AnalyticsServiceBase } from "../../common/services/analytics-service-base";
21
import { ChildProcess } from "child_process";
32
import * as path from "path";
43
import { cache } from "../../common/decorators";
5-
import { isInteractive } from '../../common/helpers';
4+
import { isInteractive, toBoolean } from '../../common/helpers';
65
import { DeviceTypes, AnalyticsClients } from "../../common/constants";
76

8-
export class AnalyticsService extends AnalyticsServiceBase {
7+
export class AnalyticsService implements IAnalyticsService, IDisposable {
98
private static ANALYTICS_BROKER_START_TIMEOUT = 10 * 1000;
109
private brokerProcess: ChildProcess;
11-
12-
constructor(protected $logger: ILogger,
13-
protected $options: IOptions,
14-
protected $processService: IProcessService,
15-
$staticConfig: Config.IStaticConfig,
16-
$prompter: IPrompter,
17-
$userSettingsService: UserSettings.IUserSettingsService,
18-
$analyticsSettingsService: IAnalyticsSettingsService,
10+
private shouldDisposeInstance: boolean = true;
11+
private analyticsStatuses: IDictionary<AnalyticsStatus> = {};
12+
13+
constructor(private $logger: ILogger,
14+
private $options: IOptions,
15+
private $processService: IProcessService,
16+
private $staticConfig: Config.IStaticConfig,
17+
private $prompter: IPrompter,
18+
private $userSettingsService: UserSettings.IUserSettingsService,
19+
private $analyticsSettingsService: IAnalyticsSettingsService,
1920
private $childProcess: IChildProcess,
2021
private $projectDataService: IProjectDataService,
2122
private $mobileHelper: Mobile.IMobileHelper) {
22-
super($logger, $options, $staticConfig, $processService, $prompter, $userSettingsService, $analyticsSettingsService);
2323
}
2424

25-
public trackException(exception: any, message: string): Promise<void> {
26-
const data: IExceptionsTrackingInformation = {
27-
type: TrackingTypes.Exception,
28-
exception,
29-
message
30-
};
25+
public setShouldDispose(shouldDispose: boolean): void {
26+
this.shouldDisposeInstance = shouldDispose;
27+
}
3128

32-
return this.sendInfoForTracking(data, this.$staticConfig.ERROR_REPORT_SETTING_NAME);
29+
public async checkConsent(): Promise<void> {
30+
if (await this.$analyticsSettingsService.canDoRequest()) {
31+
const initialTrackFeatureUsageStatus = await this.getStatus(this.$staticConfig.TRACK_FEATURE_USAGE_SETTING_NAME);
32+
let trackFeatureUsage = initialTrackFeatureUsageStatus === AnalyticsStatus.enabled;
33+
34+
if (await this.isNotConfirmed(this.$staticConfig.TRACK_FEATURE_USAGE_SETTING_NAME) && isInteractive()) {
35+
this.$logger.out("Do you want to help us improve "
36+
+ this.$analyticsSettingsService.getClientName()
37+
+ " by automatically sending anonymous usage statistics? We will not use this information to identify or contact you."
38+
+ " You can read our official Privacy Policy at");
39+
40+
const message = this.$analyticsSettingsService.getPrivacyPolicyLink();
41+
trackFeatureUsage = await this.$prompter.confirm(message, () => true);
42+
await this.setStatus(this.$staticConfig.TRACK_FEATURE_USAGE_SETTING_NAME, trackFeatureUsage);
43+
44+
await this.trackAcceptFeatureUsage({ acceptTrackFeatureUsage: trackFeatureUsage });
45+
}
46+
47+
const isErrorReportingUnset = await this.isNotConfirmed(this.$staticConfig.ERROR_REPORT_SETTING_NAME);
48+
const isUsageReportingConfirmed = !await this.isNotConfirmed(this.$staticConfig.TRACK_FEATURE_USAGE_SETTING_NAME);
49+
if (isErrorReportingUnset && isUsageReportingConfirmed) {
50+
await this.setStatus(this.$staticConfig.ERROR_REPORT_SETTING_NAME, trackFeatureUsage);
51+
}
52+
}
53+
}
54+
55+
public async setStatus(settingName: string, enabled: boolean): Promise<void> {
56+
this.analyticsStatuses[settingName] = enabled ? AnalyticsStatus.enabled : AnalyticsStatus.disabled;
57+
await this.$userSettingsService.saveSetting(settingName, enabled.toString());
58+
}
59+
60+
public async isEnabled(settingName: string): Promise<boolean> {
61+
const analyticsStatus = await this.getStatus(settingName);
62+
return analyticsStatus === AnalyticsStatus.enabled;
63+
}
64+
65+
public getStatusMessage(settingName: string, jsonFormat: boolean, readableSettingName: string): Promise<string> {
66+
if (jsonFormat) {
67+
return this.getJsonStatusMessage(settingName);
68+
}
69+
70+
return this.getHumanReadableStatusMessage(settingName, readableSettingName);
3371
}
3472

3573
public async trackAcceptFeatureUsage(settings: { acceptTrackFeatureUsage: boolean }): Promise<void> {
@@ -192,6 +230,72 @@ export class AnalyticsService extends AnalyticsServiceBase {
192230
}
193231
});
194232
}
233+
234+
@cache()
235+
private async initAnalyticsStatuses(): Promise<void> {
236+
if (await this.$analyticsSettingsService.canDoRequest()) {
237+
this.$logger.trace("Initializing analytics statuses.");
238+
const settingsNames = [this.$staticConfig.TRACK_FEATURE_USAGE_SETTING_NAME, this.$staticConfig.ERROR_REPORT_SETTING_NAME];
239+
240+
for (const settingName of settingsNames) {
241+
await this.getStatus(settingName);
242+
}
243+
244+
this.$logger.trace("Analytics statuses: ", this.analyticsStatuses);
245+
}
246+
}
247+
248+
private async getStatus(settingName: string): Promise<AnalyticsStatus> {
249+
if (!_.has(this.analyticsStatuses, settingName)) {
250+
const settingValue = await this.$userSettingsService.getSettingValue<string>(settingName);
251+
252+
if (settingValue) {
253+
const isEnabled = toBoolean(settingValue);
254+
if (isEnabled) {
255+
this.analyticsStatuses[settingName] = AnalyticsStatus.enabled;
256+
} else {
257+
this.analyticsStatuses[settingName] = AnalyticsStatus.disabled;
258+
}
259+
} else {
260+
this.analyticsStatuses[settingName] = AnalyticsStatus.notConfirmed;
261+
}
262+
}
263+
264+
return this.analyticsStatuses[settingName];
265+
}
266+
267+
private async isNotConfirmed(settingName: string): Promise<boolean> {
268+
const analyticsStatus = await this.getStatus(settingName);
269+
return analyticsStatus === AnalyticsStatus.notConfirmed;
270+
}
271+
272+
private async getHumanReadableStatusMessage(settingName: string, readableSettingName: string): Promise<string> {
273+
let status: string = null;
274+
275+
if (await this.isNotConfirmed(settingName)) {
276+
status = "disabled until confirmed";
277+
} else {
278+
status = await this.getStatus(settingName);
279+
}
280+
281+
return `${readableSettingName} is ${status}.`;
282+
}
283+
284+
private async getJsonStatusMessage(settingName: string): Promise<string> {
285+
const status = await this.getStatus(settingName);
286+
const enabled = status === AnalyticsStatus.notConfirmed ? null : status === AnalyticsStatus.enabled;
287+
return JSON.stringify({ enabled });
288+
}
289+
290+
public trackException(exception: any, message: string): Promise<void> {
291+
const data: IExceptionsTrackingInformation = {
292+
type: TrackingTypes.Exception,
293+
exception,
294+
message
295+
};
296+
297+
return this.sendInfoForTracking(data, this.$staticConfig.ERROR_REPORT_SETTING_NAME);
298+
}
195299
}
196300

197301
$injector.register("analyticsService", AnalyticsService);

0 commit comments

Comments
 (0)