1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "calendar_napi.h"
17 #include "calendar_log.h"
18 #include "napi_util.h"
19 #include "napi_queue.h"
20 #include "native_util.h"
21
22 namespace {
23 const std::string CALENDAR_CLASS_NAME = "Calendar";
24 }
25
26 namespace OHOS::CalendarApi {
27
Constructor(napi_env env)28 napi_value CalendarNapi::Constructor(napi_env env)
29 {
30 const napi_property_descriptor properties[] = {
31 DECLARE_NAPI_FUNCTION("addEvent", AddEvent),
32 DECLARE_NAPI_FUNCTION("addEvents", AddEvents),
33 DECLARE_NAPI_FUNCTION("deleteEvent", DeleteEvent),
34 DECLARE_NAPI_FUNCTION("deleteEvents", DeleteEvents),
35 DECLARE_NAPI_FUNCTION("updateEvent", UpdateEvent),
36 DECLARE_NAPI_FUNCTION("updateEvents", UpdateEvents),
37 DECLARE_NAPI_FUNCTION("getEvents", GetEvents),
38 DECLARE_NAPI_FUNCTION("getConfig", GetConfig),
39 DECLARE_NAPI_FUNCTION("setConfig", SetConfig),
40 DECLARE_NAPI_FUNCTION("getAccount", GetAccount),
41 };
42 size_t count = sizeof(properties) / sizeof(properties[0]);
43 return NapiUtil::DefineClass(env, "Calendar", properties, count, CalendarNapi::New);
44 }
45
46 /*
47 * [JS API Prototype]
48 * var calendar = new Calendar();
49 */
New(napi_env env,napi_callback_info info)50 napi_value CalendarNapi::New(napi_env env, napi_callback_info info)
51 {
52 auto ctxt = std::make_shared<ContextBase>();
53 auto input = [env, ctxt](size_t argc, napi_value* argv) {
54 CHECK_ARGS_RETURN_VOID(ctxt, argc <= 1, "invalid arguments!");
55 };
56 ctxt->GetCbInfoSync(env, info, input);
57 NAPI_ASSERT(env, ctxt->status == napi_ok, "invalid arguments!");
58
59 auto calendar = new (std::nothrow) CalendarNapi();
60 NAPI_ASSERT(env, calendar != nullptr, "no memory for calendar");
61
62 auto finalize = [](napi_env env, void* data, void* hint) {
63 LOG_DEBUG("calendar finalize.");
64 auto* calendar = reinterpret_cast<CalendarNapi*>(data);
65 CHECK_RETURN_VOID(calendar != nullptr, "finalize null!");
66 delete calendar;
67 };
68 if (napi_wrap(env, ctxt->self, calendar, finalize, nullptr, nullptr) != napi_ok) {
69 delete calendar;
70 GET_AND_THROW_LAST_ERROR(env);
71 return nullptr;
72 }
73 return ctxt->self;
74 }
75
ToJson(napi_env env,napi_value inner,CalendarNapi * & out)76 napi_status CalendarNapi::ToJson(napi_env env, napi_value inner, CalendarNapi*& out)
77 {
78 LOG_DEBUG("CalendarNapi::ToJson");
79 return NapiUtil::Unwrap(env, inner, reinterpret_cast<void**>(&out), CalendarNapi::Constructor(env));
80 }
81
SetNative(std::shared_ptr<Native::Calendar> & calendar)82 void CalendarNapi::SetNative(std::shared_ptr<Native::Calendar>& calendar)
83 {
84 calendar_ = calendar;
85 }
GetNative()86 std::shared_ptr<Native::Calendar>& CalendarNapi::GetNative()
87 {
88 return calendar_;
89 }
90
AddEvent(napi_env env,napi_callback_info info)91 napi_value CalendarNapi::AddEvent(napi_env env, napi_callback_info info)
92 {
93 LOG_INFO("AddEvent");
94 struct AddEventContext : public ContextBase {
95 Event event;
96 int eventId;
97 };
98 auto ctxt = std::make_shared<AddEventContext>();
99 auto input = [env, ctxt](size_t argc, napi_value* argv) {
100 // required atleast 1 arguments :: <eventFilter>
101 CHECK_ARGS_RETURN_VOID(ctxt, argc == 1, "invalid arguments!");
102 ctxt->status = NapiUtil::GetValue(env, argv[0], ctxt->event);
103 CHECK_STATUS_RETURN_VOID(ctxt, "AddEvent failed!");
104 Native::DumpEvent(ctxt->event);
105 CHECK_STATUS_RETURN_VOID(ctxt, "invalid arg[0], i.e. invalid keys!");
106 };
107 ctxt->GetCbInfo(env, info, input);
108 auto execute = [ctxt]() {
109 auto calendar = reinterpret_cast<CalendarNapi*>(ctxt->native);
110 CHECK_RETURN_VOID(calendar != nullptr, "CalendarNapi nullptr");
111 auto nativeCalendar = calendar->GetNative();
112 CHECK_RETURN_VOID(nativeCalendar != nullptr, "nativeCalendar nullptr");
113 ctxt->eventId = nativeCalendar->AddEvent(ctxt->event);
114 ctxt->status = (ctxt->eventId > 0) ? napi_ok : napi_generic_failure;
115 CHECK_STATUS_RETURN_VOID(ctxt, "AddEvent failed!");
116 };
117 auto output = [env, ctxt](napi_value& result) {
118 ctxt->status = NapiUtil::SetValue(ctxt->env, ctxt->eventId, result);
119 CHECK_STATUS_RETURN_VOID(ctxt, "output failed");
120 };
121 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output);
122 }
123
AddEvents(napi_env env,napi_callback_info info)124 napi_value CalendarNapi::AddEvents(napi_env env, napi_callback_info info)
125 {
126 LOG_INFO("AddEvents");
127 struct AddEventsContext : public ContextBase {
128 std::vector<Event> events;
129 int count;
130 };
131 auto ctxt = std::make_shared<AddEventsContext>();
132 auto input = [env, ctxt](size_t argc, napi_value* argv) {
133 // required atleast 1 arguments :: <eventFilter>
134 CHECK_ARGS_RETURN_VOID(ctxt, argc == 1, "invalid arguments!");
135 ctxt->status = NapiUtil::GetValue(env, argv[0], ctxt->events);
136 CHECK_STATUS_RETURN_VOID(ctxt, "GetValue failed!");
137 CHECK_STATUS_RETURN_VOID(ctxt, "invalid arg[0], i.e. invalid keys!");
138 };
139 ctxt->GetCbInfo(env, info, input);
140 auto execute = [ctxt]() {
141 auto calendar = reinterpret_cast<CalendarNapi*>(ctxt->native);
142 CHECK_RETURN_VOID(calendar != nullptr, "CalendarNapi nullptr");
143 auto nativeCalendar = calendar->GetNative();
144 CHECK_RETURN_VOID(nativeCalendar != nullptr, "nativeCalendar nullptr");
145 ctxt->count = nativeCalendar->AddEvents(ctxt->events);
146 ctxt->status = (ctxt->count > 0) ? napi_ok : napi_generic_failure;
147 CHECK_STATUS_RETURN_VOID(ctxt, "AddEvent failed!");
148 };
149 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
150 }
151
DeleteEvent(napi_env env,napi_callback_info info)152 napi_value CalendarNapi::DeleteEvent(napi_env env, napi_callback_info info)
153 {
154 LOG_INFO("DeleteEvent");
155 struct DeleteEventContext : public ContextBase {
156 bool result;
157 int eventId;
158 };
159 auto ctxt = std::make_shared<DeleteEventContext>();
160 auto input = [env, ctxt](size_t argc, napi_value* argv) {
161 // required atleast 1 arguments :: <number>
162 CHECK_ARGS_RETURN_VOID(ctxt, argc == 1, "invalid arguments!");
163 NapiUtil::GetValue(env, argv[0], ctxt->eventId);
164 CHECK_STATUS_RETURN_VOID(ctxt, "invalid arg[0], i.e. invalid keys!");
165 };
166 ctxt->GetCbInfo(env, info, input);
167 auto execute = [ctxt]() {
168 auto calendar = reinterpret_cast<CalendarNapi*>(ctxt->native);
169 CHECK_RETURN_VOID(calendar != nullptr, "CalendarNapi nullptr");
170 auto nativeCalendar = calendar->GetNative();
171 CHECK_RETURN_VOID(nativeCalendar != nullptr, "nativeCalendar nullptr");
172 ctxt->result = nativeCalendar->DeleteEvent(ctxt->eventId);
173 };
174 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
175 }
176
DeleteEvents(napi_env env,napi_callback_info info)177 napi_value CalendarNapi::DeleteEvents(napi_env env, napi_callback_info info)
178 {
179 LOG_INFO("DeleteEvents");
180 struct DeleteEventsContext : public ContextBase {
181 int result;
182 std::vector<int> ids;
183 };
184 auto ctxt = std::make_shared<DeleteEventsContext>();
185 auto input = [env, ctxt](size_t argc, napi_value* argv) {
186 // required atleast 1 arguments :: <number>
187 CHECK_ARGS_RETURN_VOID(ctxt, argc == 1, "invalid arguments!");
188 NapiUtil::GetValue(env, argv[0], ctxt->ids);
189 CHECK_STATUS_RETURN_VOID(ctxt, "invalid arg[0], i.e. invalid keys!");
190 };
191 ctxt->GetCbInfo(env, info, input);
192 auto execute = [ctxt]() {
193 auto calendar = reinterpret_cast<CalendarNapi*>(ctxt->native);
194 CHECK_RETURN_VOID(calendar != nullptr, "CalendarNapi nullptr");
195 auto nativeCalendar = calendar->GetNative();
196 CHECK_RETURN_VOID(nativeCalendar != nullptr, "nativeCalendar nullptr");
197 ctxt->result = nativeCalendar->DeleteEvents(ctxt->ids);
198 };
199 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
200 }
201
UpdateEvent(napi_env env,napi_callback_info info)202 napi_value CalendarNapi::UpdateEvent(napi_env env, napi_callback_info info)
203 {
204 LOG_INFO("UpdateEvent");
205 struct UpdateEventContext : public ContextBase {
206 bool result;
207 Event event;
208 };
209 auto ctxt = std::make_shared<UpdateEventContext>();
210 auto input = [env, ctxt](size_t argc, napi_value* argv) {
211 // required atleast 1 arguments :: <number>
212 CHECK_ARGS_RETURN_VOID(ctxt, argc == 1, "invalid arguments!");
213 NapiUtil::GetValue(env, argv[0], ctxt->event);
214 CHECK_STATUS_RETURN_VOID(ctxt, "invalid arg[0], i.e. invalid keys!");
215 };
216 ctxt->GetCbInfo(env, info, input);
217 auto execute = [ctxt]() {
218 auto calendar = reinterpret_cast<CalendarNapi*>(ctxt->native);
219 CHECK_RETURN_VOID(calendar != nullptr, "CalendarNapi nullptr");
220 auto nativeCalendar = calendar->GetNative();
221 CHECK_RETURN_VOID(nativeCalendar != nullptr, "nativeCalendar nullptr");
222 ctxt->result = nativeCalendar->UpdateEvent(ctxt->event);
223 };
224 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
225 }
226
UpdateEvents(napi_env env,napi_callback_info info)227 napi_value CalendarNapi::UpdateEvents(napi_env env, napi_callback_info info)
228 {
229 LOG_INFO("UpdateEvents");
230 struct DeleteEventsContext : public ContextBase {
231 int result;
232 std::vector<Event> events;
233 CalendarNapi *calendar;
234 };
235 auto ctxt = std::make_shared<DeleteEventsContext>();
236 auto input = [env, ctxt](size_t argc, napi_value* argv) {
237 // required atleast 1 arguments :: <number>
238 CHECK_ARGS_RETURN_VOID(ctxt, argc == 1, "invalid arguments!");
239 NapiUtil::GetValue(env, argv[0], ctxt->events);
240 CHECK_STATUS_RETURN_VOID(ctxt, "invalid arg[0], i.e. invalid keys!");
241 };
242 ctxt->GetCbInfo(env, info, input);
243 auto execute = [ctxt]() {
244 auto calendar = reinterpret_cast<CalendarNapi*>(ctxt->native);
245 CHECK_RETURN_VOID(calendar != nullptr, "CalendarNapi nullptr");
246 auto nativeCalendar = calendar->GetNative();
247 CHECK_RETURN_VOID(nativeCalendar != nullptr, "nativeCalendar nullptr");
248 ctxt->result = nativeCalendar->UpdateEvents(ctxt->events);
249 };
250 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
251 }
252
GetEvents(napi_env env,napi_callback_info info)253 napi_value CalendarNapi::GetEvents(napi_env env, napi_callback_info info)
254 {
255 struct GetEventsContext : public ContextBase {
256 EventFilterNapi* eventFilter;
257 std::vector<std::string> eventKeys;
258 std::vector<Event> events;
259 };
260 auto ctxt = std::make_shared<GetEventsContext>();
261 auto input = [env, ctxt](size_t argc, napi_value* argv) {
262 CHECK_ARGS_RETURN_VOID(ctxt, argc <= 2, "invalid arguments!");
263 if (argc >= 1) {
264 napi_valuetype type = napi_undefined;
265 napi_typeof(env, argv[0], &type);
266 CHECK_ARGS_RETURN_VOID(ctxt, type == napi_object, "type error!");
267 ctxt->status = NapiUtil::GetValue(env, argv[0], ctxt->eventFilter);
268 CHECK_STATUS_RETURN_VOID(ctxt, "invalid arg[0], i.e. invalid keys!");
269 }
270 if (argc == 2) {
271 // required atleast 2 arguments :: <eventKey>
272 napi_valuetype type = napi_undefined;
273 napi_typeof(env, argv[0], &type);
274 ctxt->status = NapiUtil::GetValue(env, argv[1], ctxt->eventKeys);
275 CHECK_STATUS_RETURN_VOID(ctxt, "invalid arg[1], i.e. invalid keys!");
276 }
277 };
278 ctxt->GetCbInfo(env, info, input);
279
280 auto execute = [ctxt]() {
281 std::shared_ptr<Native::EventFilter> nativeFilter = nullptr;
282 if (ctxt->eventFilter != nullptr) {
283 nativeFilter = ctxt->eventFilter->GetNative();
284 }
285 auto calendar = reinterpret_cast<CalendarNapi*>(ctxt->native);
286 CHECK_RETURN_VOID(calendar != nullptr, "CalendarNapi nullptr");
287 auto nativeCalendar = calendar->GetNative();
288 CHECK_RETURN_VOID(nativeCalendar != nullptr, "nativeCalendar nullptr");
289 ctxt->events = nativeCalendar->GetEvents(nativeFilter, ctxt->eventKeys);
290 ctxt->status = (true) ? napi_ok : napi_generic_failure;
291 CHECK_STATUS_RETURN_VOID(ctxt, "GetEvents failed!");
292 };
293 auto output = [env, ctxt](napi_value& result) {
294 ctxt->status = NapiUtil::SetValue(ctxt->env, ctxt->events, result);
295 CHECK_STATUS_RETURN_VOID(ctxt, "output failed");
296 };
297 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output);
298 }
299
GetConfig(napi_env env,napi_callback_info info)300 napi_value CalendarNapi::GetConfig(napi_env env, napi_callback_info info)
301 {
302 LOG_INFO("GetConfig");
303 size_t argc = 0;
304 napi_value thisVar = nullptr;
305 auto status = napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr);
306 if (status != napi_ok) {
307 LOG_ERROR("GetConfig napi_get_cb_info failed %{public}d", status);
308 return nullptr;
309 }
310 CalendarNapi *calendarNapi = nullptr;
311 status = napi_unwrap(env, thisVar, (void **)&calendarNapi);
312 if (status != napi_ok) {
313 LOG_ERROR("GetConfig napi_unwrap failed %{public}d", status);
314 return nullptr;
315 }
316 if (calendarNapi == nullptr) {
317 LOG_ERROR("GetConfig reinterpret_cast failed");
318 return nullptr;
319 }
320 auto nativeCalendar = calendarNapi->GetNative();
321 CHECK_RETURN(nativeCalendar != nullptr, "GetConfig -> get nativeCalendar nullptr", nullptr);
322 auto config = nativeCalendar->GetConfig();
323 LOG_DEBUG("config.enableReminder:%{public}d", config.enableReminder.value_or(-1));
324 if (std::get_if<1>(&config.color)) {
325 LOG_DEBUG("config.color:%{public}s", std::to_string(std::get<1>(config.color)).c_str());
326 } else {
327 LOG_ERROR("config.color is null");
328 }
329 napi_value result;
330 status = NapiUtil::SetValue(env, config, result);
331 if (status != napi_ok) {
332 LOG_ERROR("SetValue failed %{public}d", status);
333 return nullptr;
334 }
335 return result;
336 }
337
SetConfig(napi_env env,napi_callback_info info)338 napi_value CalendarNapi::SetConfig(napi_env env, napi_callback_info info)
339 {
340 LOG_INFO("SetConfig");
341 struct SetConfigContext : public ContextBase {
342 int result;
343 CalendarConfig config;
344 CalendarNapi *calendar;
345 };
346 auto ctxt = std::make_shared<SetConfigContext>();
347 auto input = [env, ctxt](size_t argc, napi_value* argv) {
348 // required atleast 1 arguments :: <CalendarConfig>
349 CHECK_ARGS_RETURN_VOID(ctxt, argc == 1, "invalid arguments!");
350 NapiUtil::GetValue(env, argv[0], ctxt->config);
351 CHECK_STATUS_RETURN_VOID(ctxt, "invalid arg[0], i.e. invalid config!");
352 };
353 ctxt->GetCbInfo(env, info, input);
354 auto execute = [ctxt]() {
355 auto calendar = reinterpret_cast<CalendarNapi*>(ctxt->native);
356 CHECK_RETURN_VOID(calendar != nullptr, "CalendarNapi nullptr");
357 auto nativeCalendar = calendar->GetNative();
358 CHECK_RETURN_VOID(nativeCalendar != nullptr, "nativeCalendar nullptr");
359 ctxt->result = nativeCalendar->SetConfig(ctxt->config);
360 };
361 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
362 }
363
GetAccount(napi_env env,napi_callback_info info)364 napi_value CalendarNapi::GetAccount(napi_env env, napi_callback_info info)
365 {
366 LOG_INFO("GetAccount");
367 size_t argc = 0;
368 napi_value thisVar = nullptr;
369 auto status = napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr);
370 if (status != napi_ok) {
371 LOG_ERROR("GetAccount napi_get_cb_info failed %{public}d", status);
372 return nullptr;
373 }
374 CalendarNapi *calendarNapi = nullptr;
375 status = napi_unwrap(env, thisVar, (void **)&calendarNapi);
376 if (status != napi_ok) {
377 LOG_ERROR("GetAccount napi_unwrap failed %{public}d", status);
378 return nullptr;
379 }
380 if (calendarNapi == nullptr) {
381 LOG_ERROR("GetAccount reinterpret_cast failed");
382 return nullptr;
383 }
384 auto nativeCalendar = calendarNapi->GetNative();
385 CHECK_RETURN(nativeCalendar != nullptr, "GetAccount -> get nativeCalendar nullptr", nullptr);
386 auto account = nativeCalendar->GetAccount();
387 LOG_DEBUG("account.name:%{public}s", account.name.c_str());
388 LOG_DEBUG("account.type:%{public}s", account.type.c_str());
389 if (account.displayName) {
390 LOG_DEBUG("account.displayName:%{public}s", account.displayName.value().c_str());
391 }
392 napi_value result;
393 status = NapiUtil::SetValue(env, account, result);
394 if (status != napi_ok) {
395 LOG_ERROR("SetValue failed %{public}d", status);
396 return nullptr;
397 }
398 return result;
399 }
400
CalendarAccountConstructor(napi_env env,napi_callback_info info)401 napi_value CalendarAccountConstructor(napi_env env, napi_callback_info info)
402 {
403 napi_value thisArg = nullptr;
404 void* data = nullptr;
405
406 napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, &data);
407
408 napi_value global = nullptr;
409 napi_get_global(env, &global);
410
411 return thisArg;
412 }
413
CalendarAccountInit(napi_env env,napi_value exports)414 static void CalendarAccountInit(napi_env env, napi_value exports)
415 {
416 napi_value name = nullptr;
417 napi_value type = nullptr;
418 napi_value displayName = nullptr;
419
420 napi_create_string_utf8(env, "name", NAPI_AUTO_LENGTH, &name);
421 napi_create_string_utf8(env, "type", NAPI_AUTO_LENGTH, &type);
422 napi_create_string_utf8(env, "displayName", NAPI_AUTO_LENGTH, &displayName);
423
424 napi_property_descriptor calendarAccountProperties[] = {
425 DECLARE_NAPI_PROPERTY("name", name),
426 DECLARE_NAPI_PROPERTY("type", type),
427 DECLARE_NAPI_PROPERTY("displayName", displayName),
428 };
429 napi_value result = nullptr;
430 napi_define_class(env, "CalendarAccount", NAPI_AUTO_LENGTH, CalendarAccountConstructor, nullptr,
431 sizeof(calendarAccountProperties) / sizeof(napi_property_descriptor), calendarAccountProperties, &result);
432 napi_set_named_property(env, exports, "CalendarAccount", result);
433 }
434
Init(napi_env env,napi_value exports)435 napi_value CalendarNapi::Init(napi_env env, napi_value exports)
436 {
437 auto status = napi_set_named_property(env, exports, "Calendar", CalendarNapi::Constructor(env));
438 LOG_INFO("init Calendar %{public}d", status);
439 CalendarAccountInit(env, exports);
440 return exports;
441 }
442 }