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 22namespace { 23 const std::string CALENDAR_CLASS_NAME = "Calendar"; 24} 25 26namespace OHOS::CalendarApi { 27 28napi_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 */ 50napi_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 76napi_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 82void CalendarNapi::SetNative(std::shared_ptr<Native::Calendar>& calendar) 83{ 84 calendar_ = calendar; 85} 86std::shared_ptr<Native::Calendar>& CalendarNapi::GetNative() 87{ 88 return calendar_; 89} 90 91napi_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 124napi_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 152napi_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 ctxt->status = 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 177napi_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 ctxt->status = 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 202napi_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 ctxt->status = 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 227napi_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 ctxt->status = 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 253napi_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 300napi_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 338napi_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 ctxt->status = 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 364napi_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:%{private}s", account.name.c_str()); 388 LOG_DEBUG("account.type:%{private}s", account.type.c_str()); 389 if (account.displayName) { 390 LOG_DEBUG("account.displayName:%{private}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 401napi_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 414static 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 435napi_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}