1 /*
2 * Copyright (C) 2024-2024 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 #define MLOG_TAG "HighlightAlbumNapi"
17
18 #include <unordered_map>
19 #include <unordered_set>
20
21 #include "highlight_album_napi.h"
22 #include "file_asset_napi.h"
23 #include "media_file_utils.h"
24 #include "medialibrary_client_errno.h"
25 #include "medialibrary_napi_log.h"
26 #include "medialibrary_tracer.h"
27 #include "photo_album.h"
28 #include "photo_album_napi.h"
29 #include "photo_map_column.h"
30 #include "result_set_utils.h"
31 #include "userfile_client.h"
32 #include "vision_column.h"
33 #include "story_album_column.h"
34 #include "story_cover_info_column.h"
35 #include "story_play_info_column.h"
36 #include "user_photography_info_column.h"
37
38 using namespace std;
39
40 namespace OHOS::Media {
41 static const string HIGHLIGHT_ALBUM_CLASS = "HighlightAlbum";
42 thread_local napi_ref HighlightAlbumNapi::constructor_ = nullptr;
43
44 using CompleteCallback = napi_async_complete_callback;
45
HighlightAlbumNapi()46 HighlightAlbumNapi::HighlightAlbumNapi() : highlightmEnv_(nullptr) {}
47
48 HighlightAlbumNapi::~HighlightAlbumNapi() = default;
49
Init(napi_env env,napi_value exports)50 napi_value HighlightAlbumNapi::Init(napi_env env, napi_value exports)
51 {
52 NapiClassInfo info = {
53 .name = HIGHLIGHT_ALBUM_CLASS,
54 .ref = &constructor_,
55 .constructor = Constructor,
56 .props = {
57 DECLARE_NAPI_FUNCTION("getHighlightAlbumInfo", JSGetHighlightAlbumInfo),
58 DECLARE_NAPI_FUNCTION("setHighlightUserActionData", JSSetHighlightUserActionData),
59 DECLARE_NAPI_FUNCTION("getHighlightResource", JSGetHighlightResource),
60 } };
61 MediaLibraryNapiUtils::NapiDefineClass(env, exports, info);
62 return exports;
63 }
64
ParseHighlightAlbum(napi_env env,napi_value arg,shared_ptr<PhotoAlbum> & photoAlbum)65 static napi_value ParseHighlightAlbum(napi_env env, napi_value arg, shared_ptr<PhotoAlbum>& photoAlbum)
66 {
67 napi_valuetype valueType;
68 PhotoAlbumNapi* photoAlbumNapi;
69 CHECK_ARGS(env, napi_typeof(env, arg, &valueType), JS_INNER_FAIL);
70 CHECK_COND_WITH_MESSAGE(env, valueType == napi_object, "Invalid argument type");
71 CHECK_ARGS(env, napi_unwrap(env, arg, reinterpret_cast<void**>(&photoAlbumNapi)), JS_INNER_FAIL);
72 CHECK_COND_WITH_MESSAGE(env, photoAlbumNapi != nullptr, "Failed to get PhotoAlbumNapi object");
73
74 auto photoAlbumPtr = photoAlbumNapi->GetPhotoAlbumInstance();
75 CHECK_COND_WITH_MESSAGE(env, photoAlbumPtr != nullptr, "photoAlbum is null");
76 CHECK_COND_WITH_MESSAGE(env,
77 photoAlbumPtr->GetResultNapiType() == ResultNapiType::TYPE_PHOTOACCESS_HELPER &&
78 PhotoAlbum::CheckPhotoAlbumType(photoAlbumPtr->GetPhotoAlbumType()) &&
79 PhotoAlbum::CheckPhotoAlbumSubType(photoAlbumPtr->GetPhotoAlbumSubType()),
80 "Unsupported type of photoAlbum");
81 photoAlbum = photoAlbumPtr;
82 RETURN_NAPI_TRUE(env);
83 }
84
Constructor(napi_env env,napi_callback_info info)85 napi_value HighlightAlbumNapi::Constructor(napi_env env, napi_callback_info info)
86 {
87 napi_value newTarget = nullptr;
88 CHECK_ARGS(env, napi_get_new_target(env, info, &newTarget), JS_INNER_FAIL);
89 CHECK_COND_RET(newTarget != nullptr, nullptr, "Failed to check new.target");
90
91 size_t argc = ARGS_ONE;
92 napi_value argv[ARGS_ONE] = { 0 };
93 napi_value thisVar = nullptr;
94 shared_ptr<PhotoAlbum> photoAlbum = nullptr;
95 CHECK_ARGS(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr), JS_INNER_FAIL);
96 CHECK_COND_WITH_MESSAGE(env, argc == ARGS_ONE, "Number of args is invalid");
97 CHECK_COND_WITH_MESSAGE(env, ParseHighlightAlbum(env, argv[PARAM0], photoAlbum), "Failed to parse album");
98
99 unique_ptr<HighlightAlbumNapi> obj = make_unique<HighlightAlbumNapi>();
100 CHECK_COND(env, obj != nullptr, JS_INNER_FAIL);
101 obj->highlightAlbumPtr = photoAlbum;
102 obj->highlightmEnv_ = env;
103 CHECK_ARGS(env,
104 napi_wrap(env, thisVar, reinterpret_cast<void*>(obj.get()), HighlightAlbumNapi::Destructor, nullptr,
105 nullptr),
106 JS_INNER_FAIL);
107 obj.release();
108 return thisVar;
109 }
110
Destructor(napi_env env,void * nativeObject,void * finalizeHint)111 void HighlightAlbumNapi::Destructor(napi_env env, void* nativeObject, void* finalizeHint)
112 {
113 auto* hightlihgtAlbum = reinterpret_cast<HighlightAlbumNapi*>(nativeObject);
114 if (hightlihgtAlbum != nullptr) {
115 delete hightlihgtAlbum;
116 hightlihgtAlbum = nullptr;
117 }
118 }
119
120 static const map<int32_t, struct HighlightAlbumInfo> HIGHLIGHT_ALBUM_INFO_MAP = {
121 { COVER_INFO, { PAH_QUERY_HIGHLIGHT_COVER, { ID, HIGHLIGHT_ALBUM_TABLE + "." + PhotoAlbumColumns::ALBUM_ID,
122 AI_ALBUM_ID, SUB_TITLE, CLUSTER_TYPE, CLUSTER_SUB_TYPE,
123 CLUSTER_CONDITION, MIN_DATE_ADDED, MAX_DATE_ADDED, GENERATE_TIME, HIGHLIGHT_VERSION,
124 REMARKS, HIGHLIGHT_STATUS, RATIO, BACKGROUND, FOREGROUND, WORDART, IS_COVERED, COLOR,
125 RADIUS, SATURATION, BRIGHTNESS, BACKGROUND_COLOR_TYPE, SHADOW_LEVEL, TITLE_SCALE_X,
126 TITLE_SCALE_Y, TITLE_RECT_WIDTH, TITLE_RECT_HEIGHT, BACKGROUND_SCALE_X, BACKGROUND_SCALE_Y,
127 BACKGROUND_RECT_WIDTH, BACKGROUND_RECT_HEIGHT, LAYOUT_INDEX, COVER_ALGO_VERSION, COVER_KEY,
128 HIGHLIGHT_IS_MUTED, HIGHLIGHT_IS_FAVORITE, HIGHLIGHT_THEME } } },
129 { PLAY_INFO, { PAH_QUERY_HIGHLIGHT_PLAY, { ID, HIGHLIGHT_ALBUM_TABLE + "." + PhotoAlbumColumns::ALBUM_ID,
130 MUSIC, FILTER, HIGHLIGHT_PLAY_INFO, IS_CHOSEN, PLAY_INFO_VERSION, PLAY_INFO_ID } } },
131 };
132
133 static const map<int32_t, std::string> HIGHLIGHT_USER_ACTION_MAP = {
134 { INSERTED_PIC_COUNT, HIGHLIGHT_INSERT_PIC_COUNT },
135 { REMOVED_PIC_COUNT, HIGHLIGHT_REMOVE_PIC_COUNT },
136 { SHARED_SCREENSHOT_COUNT, HIGHLIGHT_SHARE_SCREENSHOT_COUNT },
137 { SHARED_COVER_COUNT, HIGHLIGHT_SHARE_COVER_COUNT },
138 { RENAMED_COUNT, HIGHLIGHT_RENAME_COUNT },
139 { CHANGED_COVER_COUNT, HIGHLIGHT_CHANGE_COVER_COUNT },
140 { RENDER_VIEWED_TIMES, HIGHLIGHT_RENDER_VIEWED_TIMES },
141 { RENDER_VIEWED_DURATION, HIGHLIGHT_RENDER_VIEWED_DURATION },
142 { ART_LAYOUT_VIEWED_TIMES, HIGHLIGHT_ART_LAYOUT_VIEWED_TIMES },
143 { ART_LAYOUT_VIEWED_DURATION, HIGHLIGHT_ART_LAYOUT_VIEWED_DURATION },
144 };
145
JSGetHighlightAlbumInfoExecute(napi_env env,void * data)146 static void JSGetHighlightAlbumInfoExecute(napi_env env, void *data)
147 {
148 MediaLibraryTracer tracer;
149 tracer.Start("JSGetHighlightAlbumInfoExecute");
150
151 auto *context = static_cast<HighlightAlbumNapiAsyncContext*>(data);
152 string uriStr;
153 std::vector<std::string> fetchColumn;
154 DataShare::DataSharePredicates predicates;
155 if (HIGHLIGHT_ALBUM_INFO_MAP.find(context->highlightAlbumInfoType) != HIGHLIGHT_ALBUM_INFO_MAP.end()) {
156 uriStr = HIGHLIGHT_ALBUM_INFO_MAP.at(context->highlightAlbumInfoType).uriStr;
157 fetchColumn = HIGHLIGHT_ALBUM_INFO_MAP.at(context->highlightAlbumInfoType).fetchColumn;
158 string tabStr;
159 if (context->highlightAlbumInfoType == COVER_INFO) {
160 tabStr = HIGHLIGHT_COVER_INFO_TABLE;
161 } else {
162 tabStr = HIGHLIGHT_PLAY_INFO_TABLE;
163 }
164 vector<string> onClause = {
165 tabStr + "." + PhotoAlbumColumns::ALBUM_ID + " = " +
166 HIGHLIGHT_ALBUM_TABLE + "." + ID
167 };
168 predicates.InnerJoin(HIGHLIGHT_ALBUM_TABLE)->On(onClause);
169 } else {
170 NAPI_ERR_LOG("Invalid highlightAlbumInfoType");
171 return;
172 }
173 CHECK_NULL_PTR_RETURN_VOID(context->objectInfo, "objectInfo is null");
174 auto photoAlbum = context->objectInfo->GetPhotoAlbumInstance();
175 CHECK_NULL_PTR_RETURN_VOID(photoAlbum, "photoAlbum is null");
176 int albumId = photoAlbum->GetAlbumId();
177 int subType = photoAlbum->GetPhotoAlbumSubType();
178 Uri uri (uriStr);
179 if (subType == PhotoAlbumSubType::HIGHLIGHT) {
180 predicates.EqualTo(HIGHLIGHT_ALBUM_TABLE + "." + PhotoAlbumColumns::ALBUM_ID, to_string(albumId));
181 } else if (subType == PhotoAlbumSubType::HIGHLIGHT_SUGGESTIONS) {
182 predicates.EqualTo(HIGHLIGHT_ALBUM_TABLE + "." + AI_ALBUM_ID, to_string(albumId));
183 } else {
184 NAPI_ERR_LOG("Invalid highlight album subType");
185 return;
186 }
187 int errCode = 0;
188 auto resultSet = UserFileClient::Query(uri, predicates, fetchColumn, errCode);
189 if (resultSet != nullptr) {
190 context->highlightAlbumInfo = MediaLibraryNapiUtils::ParseResultSet2JsonStr(resultSet, fetchColumn);
191 }
192 }
193
JSGetHighlightAlbumInfoCompleteCallback(napi_env env,napi_status status,void * data)194 static void JSGetHighlightAlbumInfoCompleteCallback(napi_env env, napi_status status, void *data)
195 {
196 MediaLibraryTracer tracer;
197 tracer.Start("JSGetHighlightAlbumInfoCompleteCallback");
198
199 auto *context = static_cast<HighlightAlbumNapiAsyncContext *>(data);
200 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
201
202 unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
203 jsContext->status = false;
204
205 CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->data), JS_INNER_FAIL);
206 CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->error), JS_INNER_FAIL);
207 if (context->error == ERR_DEFAULT) {
208 CHECK_ARGS_RET_VOID(env, napi_create_string_utf8(env, context->highlightAlbumInfo.c_str(),
209 NAPI_AUTO_LENGTH, &jsContext->data), JS_INNER_FAIL);
210 jsContext->status = true;
211 } else {
212 context->HandleError(env, jsContext->error);
213 }
214
215 tracer.Finish();
216 if (context->work != nullptr) {
217 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
218 context->work, *jsContext);
219 }
220 delete context;
221 }
222
JSSetHighlightUserActionDataExecute(napi_env env,void * data)223 static void JSSetHighlightUserActionDataExecute(napi_env env, void *data)
224 {
225 MediaLibraryTracer tracer;
226 tracer.Start("JSSetHighlightUserActionDataExecute");
227
228 auto *context = static_cast<HighlightAlbumNapiAsyncContext*>(data);
229 string userActionType;
230 if (HIGHLIGHT_USER_ACTION_MAP.find(context->highlightUserActionType) != HIGHLIGHT_USER_ACTION_MAP.end()) {
231 userActionType = HIGHLIGHT_USER_ACTION_MAP.at(context->highlightUserActionType);
232 context->fetchColumn.push_back(userActionType);
233 } else {
234 NAPI_ERR_LOG("Invalid highlightUserActionType");
235 return;
236 }
237 int albumId = context->objectInfo->GetPhotoAlbumInstance()->GetAlbumId();
238 Uri uri(URI_HIGHLIGHT_ALBUM);
239 context->predicates.EqualTo(PhotoAlbumColumns::ALBUM_ID, to_string(albumId));
240 int errCode = 0;
241 auto resultSet = UserFileClient::Query(uri, context->predicates, context->fetchColumn, errCode);
242 if (resultSet != nullptr) {
243 auto count = 0;
244 auto ret = resultSet->GetRowCount(count);
245 if (ret != NativeRdb::E_OK || count == 0 || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
246 NAPI_ERR_LOG("highlight user action data get rdbstore failed");
247 context->error = JS_INNER_FAIL;
248 return;
249 }
250 int64_t userActionDataCount = get<int64_t>(ResultSetUtils::GetValFromColumn(userActionType,
251 resultSet, TYPE_INT64));
252 context->valuesBucket.Put(userActionType, to_string(userActionDataCount + context->actionData));
253 int changedRows = UserFileClient::Update(uri, context->predicates, context->valuesBucket);
254 context->SaveError(changedRows);
255 context->changedRows = changedRows;
256 } else {
257 NAPI_ERR_LOG("highlight user action data resultSet is null");
258 context->error = JS_INNER_FAIL;
259 return;
260 }
261 }
262
JSSetHighlightUserActionDataCompleteCallback(napi_env env,napi_status status,void * data)263 static void JSSetHighlightUserActionDataCompleteCallback(napi_env env, napi_status status, void *data)
264 {
265 MediaLibraryTracer tracer;
266 tracer.Start("JSSetHighlightUserActionDataCompleteCallback");
267
268 auto *context = static_cast<HighlightAlbumNapiAsyncContext*>(data);
269 auto jsContext = make_unique<JSAsyncContextOutput>();
270 jsContext->status = false;
271 CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->data), JS_INNER_FAIL);
272 if (context->error == ERR_DEFAULT) {
273 CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->error), JS_INNER_FAIL);
274 jsContext->status = true;
275 } else {
276 context->HandleError(env, jsContext->error);
277 }
278
279 tracer.Finish();
280 if (context->work != nullptr) {
281 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
282 context->work, *jsContext);
283 }
284 delete context;
285 }
286
GetFdForArrayBuffer(std::string uriStr)287 static int32_t GetFdForArrayBuffer(std::string uriStr)
288 {
289 int32_t fd = 0;
290 Uri uri(uriStr);
291 fd = UserFileClient::OpenFile(uri, MEDIA_FILEMODE_READONLY);
292 if (fd == E_ERR) {
293 NAPI_ERR_LOG("Open highlight cover file failed, error: %{public}d", errno);
294 return E_HAS_FS_ERROR;
295 } else if (fd < 0) {
296 NAPI_ERR_LOG("Open highlight cover file failed due to OpenFile failure");
297 return fd;
298 }
299 return fd;
300 }
301
JSGetHighlightResourceExecute(napi_env env,void * data)302 static void JSGetHighlightResourceExecute(napi_env env, void *data)
303 {
304 MediaLibraryTracer tracer;
305 tracer.Start("JSGetHighlightResourceExecute");
306
307 auto *context = static_cast<HighlightAlbumNapiAsyncContext*>(data);
308 if (context->resourceUri.find(MEDIA_DATA_DB_HIGHLIGHT) == string::npos) {
309 NAPI_ERR_LOG("Invalid highlight resource uri");
310 return;
311 }
312
313 int32_t fd = GetFdForArrayBuffer(context->resourceUri);
314 if (fd < 0) {
315 return;
316 }
317 UniqueFd uniqueFd(fd);
318 off_t fileLen = lseek(uniqueFd.Get(), 0, SEEK_END);
319 if (fileLen < 0) {
320 NAPI_ERR_LOG("Failed to get highlight cover file length, error: %{public}d", errno);
321 return;
322 }
323 off_t ret = lseek(uniqueFd.Get(), 0, SEEK_SET);
324 if (ret < 0) {
325 NAPI_ERR_LOG("Failed to reset highlight cover file offset, error: %{public}d", errno);
326 return;
327 }
328 void* arrayBufferData = nullptr;
329 napi_value arrayBuffer;
330 if (napi_create_arraybuffer(env, fileLen, &arrayBufferData, &arrayBuffer) != napi_ok) {
331 NAPI_ERR_LOG("failed to create napi arraybuffer");
332 return;
333 }
334
335 ssize_t readBytes = read(uniqueFd.Get(), arrayBufferData, fileLen);
336 if (readBytes != fileLen) {
337 NAPI_ERR_LOG("read file failed, read bytes is %{public}zu, actual length is %{public}jd, "
338 "error: %{public}d", readBytes, fileLen, errno);
339 return;
340 }
341 context->napiArrayBuffer = arrayBuffer;
342 }
343
JSGetHighlightResourceCompleteCallback(napi_env env,napi_status status,void * data)344 static void JSGetHighlightResourceCompleteCallback(napi_env env, napi_status status, void *data)
345 {
346 MediaLibraryTracer tracer;
347 tracer.Start("JSGetHighlightResourceCompleteCallback");
348
349 auto *context = static_cast<HighlightAlbumNapiAsyncContext *>(data);
350 CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
351
352 unique_ptr<JSAsyncContextOutput> jsContext = make_unique<JSAsyncContextOutput>();
353 jsContext->status = false;
354
355 CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->data), JS_INNER_FAIL);
356 CHECK_ARGS_RET_VOID(env, napi_get_undefined(env, &jsContext->error), JS_INNER_FAIL);
357 if (context->error == ERR_DEFAULT) {
358 jsContext->data = context->napiArrayBuffer;
359 jsContext->status = true;
360 } else {
361 context->HandleError(env, jsContext->error);
362 }
363
364 tracer.Finish();
365 if (context->work != nullptr) {
366 MediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
367 context->work, *jsContext);
368 }
369 delete context;
370 }
371
JSGetHighlightAlbumInfo(napi_env env,napi_callback_info info)372 napi_value HighlightAlbumNapi::JSGetHighlightAlbumInfo(napi_env env, napi_callback_info info)
373 {
374 MediaLibraryTracer tracer;
375 tracer.Start("JSGetHighlightAlbumInfo");
376
377 napi_value result = nullptr;
378 NAPI_CALL(env, napi_get_undefined(env, &result));
379 unique_ptr<HighlightAlbumNapiAsyncContext> asyncContext = make_unique<HighlightAlbumNapiAsyncContext>();
380 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, result, "asyncContext context is null");
381 CHECK_ARGS(env, MediaLibraryNapiUtils::ParseArgsNumberCallback(env, info, asyncContext,
382 asyncContext->highlightAlbumInfoType), JS_ERR_PARAMETER_INVALID);
383
384 auto photoAlbum = asyncContext->objectInfo->GetPhotoAlbumInstance();
385 CHECK_COND_WITH_MESSAGE(env, photoAlbum != nullptr, "photoAlbum is null");
386 CHECK_COND_WITH_MESSAGE(env,
387 PhotoAlbum::IsHighlightAlbum(photoAlbum->GetPhotoAlbumType(), photoAlbum->GetPhotoAlbumSubType()),
388 "Only and smart highlight album can get highlight album info");
389
390 asyncContext->resultNapiType = ResultNapiType::TYPE_PHOTOACCESS_HELPER;
391 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSGetHighlightAlbumInfo",
392 JSGetHighlightAlbumInfoExecute, JSGetHighlightAlbumInfoCompleteCallback);
393 }
394
JSSetHighlightUserActionData(napi_env env,napi_callback_info info)395 napi_value HighlightAlbumNapi::JSSetHighlightUserActionData(napi_env env, napi_callback_info info)
396 {
397 MediaLibraryTracer tracer;
398 tracer.Start("JSSetHighlightUserActionData");
399
400 napi_value result = nullptr;
401 NAPI_CALL(env, napi_get_undefined(env, &result));
402 unique_ptr<HighlightAlbumNapiAsyncContext> asyncContext = make_unique<HighlightAlbumNapiAsyncContext>();
403 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, result, "asyncContext context is null");
404
405 CHECK_ARGS(env, MediaLibraryNapiUtils::ParseArgsNumberCallback(env, info, asyncContext,
406 asyncContext->highlightUserActionType), JS_ERR_PARAMETER_INVALID);
407 CHECK_NULLPTR_RET(MediaLibraryNapiUtils::GetInt32Arg(env, asyncContext->argv[1], asyncContext->actionData));
408
409 auto photoAlbum = asyncContext->objectInfo->GetPhotoAlbumInstance();
410 CHECK_COND_WITH_MESSAGE(env, photoAlbum != nullptr, "photoAlbum is null");
411 CHECK_COND_WITH_MESSAGE(env,
412 PhotoAlbum::IsHighlightAlbum(photoAlbum->GetPhotoAlbumType(), photoAlbum->GetPhotoAlbumSubType()),
413 "Only and smart highlight album can set user action info");
414
415 asyncContext->resultNapiType = ResultNapiType::TYPE_PHOTOACCESS_HELPER;
416 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSSetHighlightUserActionData",
417 JSSetHighlightUserActionDataExecute, JSSetHighlightUserActionDataCompleteCallback);
418 }
419
JSGetHighlightResource(napi_env env,napi_callback_info info)420 napi_value HighlightAlbumNapi::JSGetHighlightResource(napi_env env, napi_callback_info info)
421 {
422 MediaLibraryTracer tracer;
423 tracer.Start("JSGetHighlightResource");
424
425 napi_value result = nullptr;
426 NAPI_CALL(env, napi_get_undefined(env, &result));
427 unique_ptr<HighlightAlbumNapiAsyncContext> asyncContext = make_unique<HighlightAlbumNapiAsyncContext>();
428 CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext, result, "asyncContext context is null");
429
430 CHECK_ARGS(env, MediaLibraryNapiUtils::ParseArgsStringCallback(env, info, asyncContext, asyncContext->resourceUri),
431 JS_ERR_PARAMETER_INVALID);
432
433 auto photoAlbum = asyncContext->objectInfo->GetPhotoAlbumInstance();
434 CHECK_COND_WITH_MESSAGE(env, photoAlbum != nullptr, "photoAlbum is null");
435 CHECK_COND_WITH_MESSAGE(env,
436 PhotoAlbum::IsHighlightAlbum(photoAlbum->GetPhotoAlbumType(), photoAlbum->GetPhotoAlbumSubType()),
437 "Only and smart highlight album can set user action info");
438
439 asyncContext->resultNapiType = ResultNapiType::TYPE_PHOTOACCESS_HELPER;
440 return MediaLibraryNapiUtils::NapiCreateAsyncWork(env, asyncContext, "JSGetHighlightResource",
441 JSGetHighlightResourceExecute, JSGetHighlightResourceCompleteCallback);
442 }
443
GetPhotoAlbumInstance() const444 shared_ptr<PhotoAlbum> HighlightAlbumNapi::GetPhotoAlbumInstance() const
445 {
446 return highlightAlbumPtr;
447 }
448 } // namespace OHOS::Media
449