@react-native-oh-tpl/react-native-calendar-events
Version:
React Native module for harmony Calendar Events
419 lines (402 loc) • 18 kB
text/typescript
/**
* MIT License
*
* Copyright (C) 2024 Huawei Device Co., Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
import Logger from './Logger';
import {BusinessError} from '@ohos.base';
import calendarManager from '@ohos.calendarManager';
import bundleManager from '@ohos.bundle.bundleManager';
import abilityAccessCtrl, { PermissionRequestResult, Permissions } from '@ohos.abilityAccessCtrl';
import { dataConversion, getCalendarType} from "./CalendarUtil"
import { CalendarEventReadable, CalendarEventWritable, EventDetails, Options} from './EventType'
import { TurboModule, TurboModuleContext } from '@rnoh/react-native-openharmony/ts';
import {AuthorizationStatus, Calendar, CalendarOptionsSourceLibrary } from './CalendarType';
import { TM } from '@rnoh/react-native-openharmony/generated/ts';
export const CALENDAR_EVENTS: string = "CalendarEventsView"
export let calendarMgr: calendarManager.CalendarManager | null = null;
let authorized: string = "authorized";
export class CalendarEventTurboModule extends TurboModule implements TM.RNCalendarEvents.Spec{
constructor(ctx: TurboModuleContext) {
super(ctx);
}
async checkAccessToken(permission: Permissions): Promise<abilityAccessCtrl.GrantStatus> {
let grantStatus: abilityAccessCtrl.GrantStatus;
let atManager = abilityAccessCtrl.createAtManager();
// 获取应用程序的accessTokenID
let tokenId: number;
try {
let bundleInfo: bundleManager.BundleInfo =
await bundleManager.getBundleInfoForSelf(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION);
let appInfo: bundleManager.ApplicationInfo = bundleInfo.appInfo;
tokenId = appInfo.accessTokenId;
} catch (err) {
Logger.error(`getBundleInfoForSelf failed, code is ${err.code}, message is ${err.message}`);
}
try {
grantStatus = await atManager.checkAccessToken(tokenId, permission);
} catch (err) {
Logger.error(`checkAccessToken failed, code is ${err.code}, message is ${err.message}`);
}
return grantStatus;
}
async checkPermissions(): Promise<AuthorizationStatus> {
const permissions: Array<Permissions> = ['ohos.permission.READ_CALENDAR'];
let grantStatus: abilityAccessCtrl.GrantStatus = await this.checkAccessToken(permissions[0]);
if (grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
Logger.info(`checkPermissions authorized`);
return new Promise((resolve, reject) => {
resolve("authorized");
});
}
if (grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_DENIED) {
Logger.info(`checkPermissions denied`);
return new Promise((resolve, reject) => {
resolve("denied");
});
}
}
//requestPermiss
async requestPermissions(): Promise<AuthorizationStatus> {
let atManager = abilityAccessCtrl.createAtManager();
let permissionRequestResult : PermissionRequestResult = null;
const permissions: Permissions[] = ['ohos.permission.READ_CALENDAR', 'ohos.permission.WRITE_CALENDAR'];
await atManager.requestPermissionsFromUser(this.ctx.uiAbilityContext, permissions).then(
(result: PermissionRequestResult) => {
permissionRequestResult = result;
}).catch((error: BusinessError) => {
Logger.error(`requestPermissionsAsync failed, code is ${error.code}, message is ${error.message}`);
})
Logger.info(`requestPermissions result =` + permissionRequestResult.permissions);
return await this.checkPermissions()
}
//findCalendars
async findCalendars(): Promise<Calendar[]> {
let checkPermission: string = await this.checkPermissions();
if (checkPermission == authorized) {
let calendar : calendarManager.Calendar[] | undefined = undefined;
let calendarResult : Calendar[] = []
calendarMgr = calendarManager.getCalendarManager(this.ctx.uiAbilityContext);
await calendarMgr.getAllCalendars().then(
async (calendarData:calendarManager.Calendar[]) => {calendar = calendarData}
);
if (calendar && calendar.length > 0) {
calendar.forEach(item => {
calendarResult.push(new Calendar(item.id.toString(), item.getAccount().name, item.getAccount().type))
})
}
return new Promise((resolve, reject) => {
resolve(calendarResult);
});
} else {
return new Promise((resolve, reject) => {
resolve([]);
});
}
}
//saveCalendar
async setConfig(calendar: calendarManager.Calendar, calendarOptions: CalendarOptionsSourceLibrary){
const config: calendarManager.CalendarConfig = {
color: calendarOptions.color
};
calendar.setConfig(config, (err: BusinessError) => {
if (err) {
Logger.error(`Failed to set config. Code: ${err.code}, message: ${err.message}`);
} else {
Logger.info(`Succeeded in setting config, config -> ${JSON.stringify(config)}`);
}
});
}
async saveCalendar(calendarOptions: CalendarOptionsSourceLibrary): Promise<boolean> {
const result: boolean = await new Promise(async (resolve: Function) => {
let checkPermission: string = await this.checkPermissions();
if (checkPermission == authorized) {
if (calendarOptions.title != null && calendarOptions.title.trim().length > 0) {
const calendarAccount: calendarManager.CalendarAccount = {
name: calendarOptions.title,
type: calendarManager.CalendarType.LOCAL,
};
calendarMgr = calendarManager.getCalendarManager(this.ctx.uiAbilityContext);
await calendarMgr.createCalendar(calendarAccount).then(async (data: calendarManager.Calendar) => {
if (calendarOptions.color != null && calendarOptions.color.length > 0) {
if (data){
await this.setConfig(data, calendarOptions)
resolve(true)
}
}
}).catch((error : BusinessError) => {
Logger.error(`saveCalendarAsync Failed to add event, err -> ${JSON.stringify(error)} `);
resolve(false)
});
} else {
Logger.error("new calendars require a `source` object with a `name`");
resolve(false)
}
} else {
resolve(false)
}
})
if (result) {
return new Promise((resolve) => {
resolve(true);
});
} else {
return new Promise((resolve) => {
resolve(false);
});
}
}
//removeCalendar
async removeCalendarById(id: string): Promise<Boolean> {
let removeCalendarBool : boolean = false;
let calendar : calendarManager.Calendar | undefined = undefined;
//根据id,查询calendar
let findCalendarById : Calendar | null;
(await this.findCalendars()).forEach(item => {
if (item.id.toString() == id && item.title != "phone") {
findCalendarById = item
}
})
if (findCalendarById) {
const calendarAccount: calendarManager.CalendarAccount = {
name: findCalendarById.title,
type: getCalendarType(findCalendarById.type)
};
calendarMgr = calendarManager.getCalendarManager(this.ctx.uiAbilityContext);
await calendarMgr?.getCalendar(calendarAccount).then(async (calendarData:calendarManager.Calendar) => {
calendar = calendarData;
await calendarMgr?.deleteCalendar(calendarData).then(() => {
removeCalendarBool = true
}).catch((err: BusinessError) => {
Logger.error(`removeCalendarAsync Failed to remove calendar, err -> ${JSON.stringify(err)}`);
});
})
return new Promise((resolve) => {
resolve(removeCalendarBool);
});
} else {
return new Promise((resolve) => {
Logger.info(`removeCalendarAsync false, calendar is not exist`);
resolve(false);
});
}
}
async removeCalendar(id: string): Promise<string> {
let checkPermission: string = await this.checkPermissions();
if (checkPermission == authorized) {
let saveCalendarBool: Boolean = await this.removeCalendarById(id);
if (saveCalendarBool) {
return new Promise((resolve) => {
resolve("success");
});
}
}
return new Promise((resolve, reject) => {
resolve("fail");
});
}
//findEventById
async findEventById(id: string): Promise<CalendarEventReadable | null> {
let calendar : calendarManager.Calendar | undefined = undefined;
let calendarEventReadable: CalendarEventReadable;
let checkPermission: string = await this.checkPermissions();
if (checkPermission == authorized) {
calendarMgr = calendarManager.getCalendarManager(this.ctx.uiAbilityContext);
await calendarMgr?.getCalendar().then(async (dataCalendar:calendarManager.Calendar) => {
calendar = dataCalendar;
const filter = calendarManager.EventFilter.filterById([Number.parseFloat(id)]);
await calendar.getEvents(filter).then((dataEvent: calendarManager.Event[]) => {
if (dataEvent && dataEvent.length >= 1) {
dataEvent.forEach((item: calendarManager.Event) => {
calendarEventReadable = new CalendarEventReadable()
calendarEventReadable.id = item.id?.toString()
calendarEventReadable.title = item.title
calendarEventReadable.startDate = new Date(item.startTime).toUTCString();
calendarEventReadable.endDate = new Date(item.endTime).toUTCString();
calendarEventReadable.allDay = item.isAllDay
if (item.recurrenceRule && item.recurrenceRule.recurrenceFrequency) {
switch (item.recurrenceRule.recurrenceFrequency.valueOf()){
case 0 :
calendarEventReadable.recurrence = "yearly";
break;
case 1:
calendarEventReadable.recurrence = "monthly";
break;
case 2 :
calendarEventReadable.recurrence = "weekly";
break;
case 3:
calendarEventReadable.recurrence = "daily";
break;
default :
calendarEventReadable.recurrence = "daily";
}
}
calendarEventReadable.location = item.location?.location
calendarEventReadable.description = item.description
calendarEventReadable.timeZone = item.timeZone
})
}
}).catch((err: BusinessError) => {
Logger.error(`Failed to get events, err -> ${JSON.stringify(err)}`);
});
});
}
if (calendarEventReadable) {
return new Promise((resolve, reject) => {
resolve(calendarEventReadable);
});
} else {
return new Promise((resolve, reject) => {
resolve(null);
});
}
}
//fetchAllEvents
async fetchAllEvents(startDate: string, endDate: string, calendarIds?: string[]): Promise<CalendarEventReadable[]> {
let startDateNumber: number = new Date(startDate).getTime();
let endDateNumber: number = new Date(endDate).getTime();
let checkPermission: string = await this.checkPermissions();
let calendarEventReadableArray: CalendarEventReadable[] = [];
if (checkPermission == authorized) {
let calendar : calendarManager.Calendar | undefined = undefined;
calendarMgr = calendarManager.getCalendarManager(this.ctx.uiAbilityContext);
await calendarMgr?.getCalendar().then(async (dataCalendar: calendarManager.Calendar) => {
calendar = dataCalendar;
const eventFilter = calendarManager.EventFilter;
let filter = null;
if (calendarIds && calendarIds.length > 0) {
filter = eventFilter.filterById(calendarIds.map(Number));
} else {
filter = eventFilter.filterByTime(startDateNumber, endDateNumber)
}
await calendar.getEvents(filter).then((dataEvent: calendarManager.Event[]) => {
Logger.info(`fetchAllEventsAsync Succeeded to get events, data -> ${JSON.stringify(dataEvent)}`);
if (dataEvent.length > 0) {
dataEvent.forEach((item: calendarManager.Event) => {
let calendarEventReadable: CalendarEventReadable = new CalendarEventReadable()
calendarEventReadable.id = item.id?.toString()
calendarEventReadable.title = item.title
calendarEventReadable.startDate = new Date(item.startTime).toUTCString();
calendarEventReadable.endDate = new Date(item.endTime).toUTCString();
calendarEventReadable.allDay = item.isAllDay
if (item.recurrenceRule && item.recurrenceRule.recurrenceFrequency) {
switch (item.recurrenceRule.recurrenceFrequency.valueOf()){
case 0 :
calendarEventReadable.recurrence = "yearly";
break;
case 1:
calendarEventReadable.recurrence = "monthly";
break;
case 2 :
calendarEventReadable.recurrence = "weekly";
break;
case 3:
calendarEventReadable.recurrence = "daily";
break;
default :
calendarEventReadable.recurrence = "daily";
}
}
calendarEventReadable.location = item.location?.location
calendarEventReadable.description = item.description
calendarEventReadable.timeZone = item.timeZone
calendarEventReadableArray.push(calendarEventReadable)
})
}
}).catch((err: BusinessError) => {
Logger.error(`fetchAllEventsAsync Failed to get events, err -> ${JSON.stringify(err)}`);
});
});
}
return new Promise((resolve, reject) => {
resolve(calendarEventReadableArray);
});
}
//saveEvent
async saveEvent(title: string, details: CalendarEventWritable, options?: Options): Promise<String> {
const result: boolean = await new Promise(async (resolve: Function) => {
let checkPermission: string = await this.checkPermissions();
if (checkPermission == authorized) {
let calendar : calendarManager.Calendar | undefined = undefined;
//handle data
let eventDetails:EventDetails = new EventDetails();
const events: calendarManager.Event = dataConversion(title, details, eventDetails, options);
calendarMgr = calendarManager.getCalendarManager(this.ctx.uiAbilityContext);
await calendarMgr?.getCalendar().then(
async (calendarData:calendarManager.Calendar) => {
Logger.info(`saveEventAsync Succeeded to get calendar, data -> ${JSON.stringify(calendarData)}`);
calendar = calendarData;
await calendar?.addEvent(events).then((data: number) => {
resolve(true);
}).catch((err: BusinessError) => {
resolve(false)
Logger.error(`saveCalendarAsync Failed to add event, err -> ${JSON.stringify(err)} `);
});
})
} else {
resolve(false);
}
})
if (result) {
return new Promise((resolve, reject) => {
resolve("success");
});
} else {
return new Promise((resolve, reject) => {
resolve("fail");
});
}
}
//removeEvent
async removeEvent(id: string): Promise<string> {
const result: boolean = await new Promise(async (resolve: Function) => {
let checkPermission: string = await this.checkPermissions();
if (checkPermission == authorized) {
let calendar : calendarManager.Calendar | undefined = undefined;
calendarMgr = calendarManager.getCalendarManager(this.ctx.uiAbilityContext);
calendarMgr?.getCalendar()
.then(
(calendarData:calendarManager.Calendar) => {
calendar = calendarData;
calendar?.deleteEvent(Number.parseFloat(id), (err: BusinessError) => {
if (err) {
resolve(false)
} else {
resolve(true)
}
});
})
} else{
resolve(false);
}
});
if (result) {
return new Promise((resolve) => {
resolve("success");
});
} else {
return new Promise((resolve, reject) => {
resolve("fail");
});
}
}
}