Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/assets/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,7 @@
"TRY_AGAIN": "TRY AGAIN",
"TRY_BEFORE_RATING": "Please try the content before rating it.",
"TRY_DIFF_QR": "Try a different QR code?",
"TRY_CONTENT_ON": "Try this content on the mobile app: ",
"UNABLE_TO_FETCH_CONTENT": "Unable to fetch retired content",
"UNENROLL_CONFIRMATION_MESSAGE": "You can rejoin an active or upcoming batch later",
"UNENROLL_FROM_COURSE": "Leave Training",
Expand Down
62 changes: 38 additions & 24 deletions src/services/content/content-share-handler.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,32 @@
import { of } from 'rxjs';
import { SocialSharing } from '@ionic-native/social-sharing/ngx';
import { ContentService, StorageService, Content } from 'sunbird-sdk';
import { ContentService, StorageService, Content, ContentData, DeviceInfo } from 'sunbird-sdk';
import { ContentShareHandlerService, CommonUtilService, UtilityService, TelemetryGeneratorService } from '../../services';
import { SbSharePopupComponent } from '../../app/components/popups/sb-share-popup/sb-share-popup.component';
import { AppVersion } from '@ionic-native/app-version/ngx';
describe('ContentShareHandlerService', () => {
let contentShareHandlerService: ContentShareHandlerService;
const mockContentService: Partial<ContentService> = {};
const mockStorageService: Partial<StorageService> = {
getStorageDestinationDirectoryPath: jest.fn(() => 'dirpath')
};
const mockDeviceInfo: Partial<DeviceInfo> = {
getDeviceID: jest.fn(() => 'device_id')
};
const mockCommonUtilService: Partial<CommonUtilService> = {
showToast: jest.fn()
showToast: jest.fn(),
getAppName: jest.fn(() => Promise.resolve('resolved')),
translateMessage: jest.fn(() => 'Try this: ')
};
const mockSocialSharing: Partial<SocialSharing> = {
share: jest.fn()
};
const mockUtilityService: Partial<UtilityService> = {
getBuildConfigValue: jest.fn(() => Promise.resolve('baseurl'))
};
const mockAppVersion: Partial<AppVersion> = {
getPackageName: jest.fn(() => Promise.resolve('packageName'))
};
const mockTelemetryGeneratorService: Partial<TelemetryGeneratorService> = {
generateImpressionTelemetry: jest.fn(),
generateInteractTelemetry: jest.fn(),
Expand All @@ -34,10 +43,12 @@ describe('ContentShareHandlerService', () => {
contentShareHandlerService = new ContentShareHandlerService(
mockContentService as ContentService,
mockStorageService as StorageService,
mockDeviceInfo as DeviceInfo,
mockCommonUtilService as CommonUtilService,
mockSocialSharing as SocialSharing,
mockTelemetryGeneratorService as TelemetryGeneratorService,
mockUtilityService as UtilityService
mockUtilityService as UtilityService,
mockAppVersion as AppVersion
);
});

Expand Down Expand Up @@ -76,27 +87,30 @@ describe('ContentShareHandlerService', () => {
}, 100);
});

// it('should share link', (done) => {
// // arrange
// contentShareHandlerService.exportContent = jest.fn();
// contentShareHandlerService.generateShareInteractEvents = jest.fn();
// const shareParams = {
// byLink: true,
// link: 'link'
// };
// const content: Partial<Content> = {
// identifier: 'id',
// contentType: 'contentType',
// };
// // act
// contentShareHandlerService.shareContent(shareParams, content as Content);
// // assert
// setTimeout(() => {
// // expect(mockSocialSharing.share).toHaveBeenCalled();
// done();
// }, 100);

// });
it('should share link', (done) => {
// arrange
contentShareHandlerService.exportContent = jest.fn();
contentShareHandlerService.generateShareInteractEvents = jest.fn();
const shareParams = {
byLink: true,
link: 'link'
};
const contentData: Partial<ContentData> = {
contentType: 'dummyType'
};
const content: Partial<Content> = {
identifier: 'id',
contentType: 'contentType',
contentData: contentData as ContentData
};
// act
contentShareHandlerService.shareContent(shareParams, content as Content);
// assert
setTimeout(() => {
expect(mockSocialSharing.share).toHaveBeenCalled();
done();
}, 0);
});


it('should share file', () => {
Expand Down
32 changes: 29 additions & 3 deletions src/services/content/content-share-handler.service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Injectable, Inject } from '@angular/core';
import {
ContentService, StorageService, ContentExportRequest, ContentExportResponse,
Content, Rollup, CorrelationData, ContentDetailRequest, TelemetryObject,
Content, Rollup, CorrelationData, ContentDetailRequest, TelemetryObject, DeviceInfo,
} from 'sunbird-sdk';
import { CommonUtilService } from '../common-util.service';
import { InteractSubtype, InteractType, Environment, PageId } from '../telemetry-constants';
Expand All @@ -10,13 +10,17 @@ import { TelemetryGeneratorService } from '../telemetry-generator.service';
import { ShareUrl, ContentType } from '../../app/app.constant';
import { UtilityService } from '../utility-service';
import { ContentUtil } from '@app/util/content-util';
import { AppVersion } from '@ionic-native/app-version/ngx';

@Injectable({
providedIn: 'root'
})

export class ContentShareHandlerService {
public telemetryObject: TelemetryObject;
appName: string;
shareUrl: string;
shareUTMUrl: string;
// enum shareParams = {
// byLink: boolean | undefined,
// link: string | undefined,
Expand All @@ -26,11 +30,15 @@ export class ContentShareHandlerService {
constructor(
@Inject('CONTENT_SERVICE') private contentService: ContentService,
@Inject('STORAGE_SERVICE') private storageService: StorageService,
@Inject('DEVICE_INFO') private deviceInfo: DeviceInfo,
private commonUtilService: CommonUtilService,
private social: SocialSharing,
private telemetryGeneratorService: TelemetryGeneratorService,
private utilityService: UtilityService) {
private utilityService: UtilityService,
private appVersion: AppVersion) {
this.commonUtilService.getAppName().then((res) => { this.appName = res; });
}

public async shareContent(shareParams: any, content: Content, corRelationList?: CorrelationData[], rollup?: Rollup) {
this.telemetryObject = ContentUtil.getTelemetryObject(content);
let exportContentRequest: ContentExportRequest;
Expand All @@ -44,7 +52,9 @@ export class ContentShareHandlerService {
this.generateShareInteractEvents(InteractType.OTHER,
InteractSubtype.SHARE_LIBRARY_SUCCESS,
content.contentData.contentType, corRelationList, rollup);
this.social.share(null, null, null, shareParams.link);
let shareLink = content.contentData.name + ' on ' + this.appName + ' ' + this.getContentUtm(shareParams.link, content);
shareLink = shareLink + `\n\n${this.commonUtilService.translateMessage('TRY_CONTENT_ON')}` + await this.getPackageNameWithUTM(true);
this.social.share(null, null, null, shareLink);
} else if (shareParams && shareParams.saveFile) {
exportContentRequest = {
contentIds: [content.identifier],
Expand Down Expand Up @@ -76,6 +86,22 @@ export class ContentShareHandlerService {
});
}

async getPackageNameWithUTM(utm: boolean): Promise<string> {
const pkg = await this.appVersion.getPackageName();
if (utm) {
const utmParams = `&referrer=utm_source%3D${this.deviceInfo.getDeviceID()}%26utm_campaign%3Dshare_app`;
const shareUTMUrl = `https://play.google.com/store/apps/details?id=${pkg}${utmParams}`;
return shareUTMUrl;
} else {
return `https://play.google.com/store/apps/details?id=${pkg}&hl=en_IN`;
}
}

getContentUtm(contentLink: string, content: Content): string {
const contentUTM: string = `referrer=utm_source%3D${this.appName.toLocaleLowerCase()}_mobile%26utm_content%3D${content.identifier}%26utm_campaign%3Dshare_content`;
return contentLink + '?' + contentUTM;
}

generateShareInteractEvents(interactType, subType, contentType, corRelationList, rollup) {
const values = new Map();
values['ContentType'] = contentType;
Expand Down