From 0bfe8c3958534cfdfe38dc7b33ccf55f3af15402 Mon Sep 17 00:00:00 2001 From: zhaokaixiao Date: Sat, 4 Nov 2023 07:10:31 +0000 Subject: [PATCH 1/2] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=9B=B8=E5=86=8C?= =?UTF-8?q?=E6=8E=92=E5=BA=8F=E8=83=BD=E5=8A=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zhaokaixiao Change-Id: Ie460dfd20de908808ced762bee8c92520aa8a436 --- .../src/photo_album_column.cpp | 23 +- .../medialibrary_data_extension/BUILD.gn | 5 +- .../include/medialibrary_album_operations.h | 1 + .../include/medialibrary_command.h | 1 + .../src/medialibrary_album_operations.cpp | 254 +++++++++++++++++- .../src/medialibrary_command.cpp | 1 + .../src/medialibrary_rdbstore.cpp | 42 +++ .../photo_album_test/src/photo_album_test.cpp | 70 +++++ .../src/media_album_change_request_napi.cpp | 57 ++++ .../src/media_asset_change_request_napi.cpp | 2 +- .../src/scanner/metadata_extractor.cpp | 3 +- frameworks/utils/include/userfilemgr_uri.h | 3 + .../include/medialibrary_db_const.h | 4 +- .../include/photo_album_column.h | 5 + .../include/media_album_change_request_napi.h | 8 +- 15 files changed, 468 insertions(+), 11 deletions(-) diff --git a/frameworks/innerkitsimpl/media_library_helper/src/photo_album_column.cpp b/frameworks/innerkitsimpl/media_library_helper/src/photo_album_column.cpp index 30b500a4c6..d3170c5ee9 100644 --- a/frameworks/innerkitsimpl/media_library_helper/src/photo_album_column.cpp +++ b/frameworks/innerkitsimpl/media_library_helper/src/photo_album_column.cpp @@ -43,6 +43,10 @@ const string PhotoAlbumColumns::CONTAINS_HIDDEN = "contains_hidden"; const string PhotoAlbumColumns::HIDDEN_COUNT = "hidden_count"; const string PhotoAlbumColumns::HIDDEN_COVER = "hidden_cover"; +// For sorting albums +const string PhotoAlbumColumns::ALBUM_ORDER = "album_order"; +const string PhotoAlbumColumns::REFERENCE_ALBUM_ID = "reference_album_id"; + // default fetch columns const set PhotoAlbumColumns::DEFAULT_FETCH_COLUMNS = { ALBUM_ID, ALBUM_TYPE, ALBUM_SUBTYPE, ALBUM_NAME, ALBUM_COVER_URI, ALBUM_COUNT, ALBUM_DATE_MODIFIED @@ -69,8 +73,8 @@ const string PhotoAlbumColumns::CREATE_TABLE = CreateTable() + ALBUM_RELATIVE_PATH + " TEXT, " + CONTAINS_HIDDEN + " INT DEFAULT 0, " + HIDDEN_COUNT + " INT DEFAULT 0, " + - HIDDEN_COVER + " TEXT DEFAULT '' " + - ")"; + HIDDEN_COVER + " TEXT DEFAULT '', " + + ALBUM_ORDER + " INT )"; // Create indexes const string PhotoAlbumColumns::INDEX_ALBUM_TYPES = CreateIndex() + "photo_album_types" + " ON " + TABLE + @@ -99,6 +103,21 @@ const std::string PhotoAlbumColumns::CREATE_ALBUM_MDIRTY_TRIGGER = std::to_string(static_cast(DirtyTypes::TYPE_MDIRTY)) + " WHERE " + ALBUM_ID + " = old." + ALBUM_ID + "; SELECT cloud_sync_func(); END;"; +const std::string PhotoAlbumColumns::ALBUM_DELETE_ORDER_TRIGGER = + " CREATE TRIGGER update_order_trigger AFTER DELETE ON " + PhotoAlbumColumns::TABLE + + " FOR EACH ROW " + + " BEGIN " + + " UPDATE " + PhotoAlbumColumns::TABLE + " SET album_order = album_order - 1" + + " WHERE album_order > old.album_order; " + + " END"; + +const std::string PhotoAlbumColumns::ALBUM_INSERT_ORDER_TRIGGER = + " CREATE TRIGGER insert_order_trigger AFTER INSERT ON " + PhotoAlbumColumns::TABLE + + " BEGIN " + + " UPDATE " + PhotoAlbumColumns::TABLE + " SET album_order = (" + + " SELECT Max(album_order) FROM " + PhotoAlbumColumns::TABLE + ") + 1 WHERE rowid = new.rowid;" + " END"; + bool PhotoAlbumColumns::IsPhotoAlbumColumn(const string &columnName) { static const set PHOTO_ALBUM_COLUMNS = { diff --git a/frameworks/innerkitsimpl/medialibrary_data_extension/BUILD.gn b/frameworks/innerkitsimpl/medialibrary_data_extension/BUILD.gn index 2bd7191963..13ab313123 100644 --- a/frameworks/innerkitsimpl/medialibrary_data_extension/BUILD.gn +++ b/frameworks/innerkitsimpl/medialibrary_data_extension/BUILD.gn @@ -169,7 +169,10 @@ ohos_shared_library("medialibrary_data_extension") { "${MEDIALIB_UTILS_PATH}:post_event_utils", ] - include_dirs = [ "${MEDIALIB_CLOUD_SYNC_PATH}/include" ] + include_dirs = [ + "${MEDIALIB_CLOUD_SYNC_PATH}/include", + "${MEDIALIB_SERVICES_PATH}/media_async_worker/include", + ] external_deps = [ "ability_base:want", diff --git a/frameworks/innerkitsimpl/medialibrary_data_extension/include/medialibrary_album_operations.h b/frameworks/innerkitsimpl/medialibrary_data_extension/include/medialibrary_album_operations.h index 09a2b7a6d6..928dc7f033 100644 --- a/frameworks/innerkitsimpl/medialibrary_data_extension/include/medialibrary_album_operations.h +++ b/frameworks/innerkitsimpl/medialibrary_data_extension/include/medialibrary_album_operations.h @@ -30,6 +30,7 @@ namespace OHOS { namespace Media { +constexpr int32_t NULL_REFERENCE_ALBUM_ID = -1; class MediaLibraryAlbumOperations { public: static int32_t CreateAlbumOperation(MediaLibraryCommand &cmd); diff --git a/frameworks/innerkitsimpl/medialibrary_data_extension/include/medialibrary_command.h b/frameworks/innerkitsimpl/medialibrary_data_extension/include/medialibrary_command.h index 9d739137e7..eded2bfa75 100644 --- a/frameworks/innerkitsimpl/medialibrary_data_extension/include/medialibrary_command.h +++ b/frameworks/innerkitsimpl/medialibrary_data_extension/include/medialibrary_command.h @@ -97,6 +97,7 @@ enum class OperationType : uint32_t { REVERT_EDIT, HIDE, QUERY_HIDDEN, + ALBUM_ORDER, }; class MediaLibraryCommand { diff --git a/frameworks/innerkitsimpl/medialibrary_data_extension/src/medialibrary_album_operations.cpp b/frameworks/innerkitsimpl/medialibrary_data_extension/src/medialibrary_album_operations.cpp index 98f8e830ff..c6aa77fdbf 100644 --- a/frameworks/innerkitsimpl/medialibrary_data_extension/src/medialibrary_album_operations.cpp +++ b/frameworks/innerkitsimpl/medialibrary_data_extension/src/medialibrary_album_operations.cpp @@ -297,7 +297,35 @@ inline int32_t GetStringObject(const ValuesBucket &values, const string &key, st return E_OK; } -inline void PrepareUserAlbum(const string &albumName, const string &relativePath, ValuesBucket &values) +inline int32_t GetIntVal(const ValuesBucket &values, const string &key, int32_t &value) +{ + value = 0; + ValueObject valueObject; + if (values.GetObject(key, valueObject)) { + valueObject.GetInt(value); + } else { + return -EINVAL; + } + return E_OK; +} + +static int32_t ObtainMaxAlbumOrder(int32_t &maxAlbumOrder) +{ + auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore(); + if (uniStore == nullptr) { + MEDIA_ERR_LOG("uniStore is nullptr! failed query album order"); + return -E_HAS_DB_ERROR; + } + std::string queryMaxOrderSql = "SELECT Max(album_order) FROM " + PhotoAlbumColumns::TABLE; + auto resultSet = uniStore->QuerySql(queryMaxOrderSql); + if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) { + MEDIA_ERR_LOG("Failed to query album!"); + return -E_HAS_DB_ERROR; + } + return resultSet->GetInt(0, maxAlbumOrder); +} + +static void PrepareUserAlbum(const string &albumName, const string &relativePath, ValuesBucket &values) { values.PutString(PhotoAlbumColumns::ALBUM_NAME, albumName); values.PutInt(PhotoAlbumColumns::ALBUM_TYPE, PhotoAlbumType::USER); @@ -390,6 +418,9 @@ int32_t MediaLibraryAlbumOperations::DeletePhotoAlbum(RdbPredicates &predicates) shared_ptr MediaLibraryAlbumOperations::QueryPhotoAlbum(MediaLibraryCommand &cmd, const vector &columns) { + if (cmd.GetAbsRdbPredicates()->GetOrder().empty()) { + cmd.GetAbsRdbPredicates()->OrderByAsc(PhotoAlbumColumns::ALBUM_ORDER); + } return MediaLibraryRdbStore::Query(*(cmd.GetAbsRdbPredicates()), columns); } @@ -543,6 +574,225 @@ int32_t AgingPhotoAssets(shared_ptr countPtr) return E_OK; } +static int32_t ObtainAlbumOrders(const int32_t ¤tAlbumId, const int32_t referenceAlbumId, + int32_t ¤tAlbumOrder, int32_t &referenceAlbumOrder) +{ + auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStoreRaw()->GetRaw(); + if (uniStore == nullptr) { + MEDIA_ERR_LOG("uniStore is nullptr! failed query album order"); + return E_HAS_DB_ERROR; + } + const std::string queryCurrentAlbumOrder = "SELECT " + PhotoAlbumColumns::ALBUM_ORDER + " FROM " + + PhotoAlbumColumns::TABLE + " WHERE " + PhotoAlbumColumns::ALBUM_ID + " = " + to_string(currentAlbumId); + const std::string queryReferenceAlbumOrder = "SELECT " + PhotoAlbumColumns::ALBUM_ORDER + " FROM " + + PhotoAlbumColumns::TABLE + " WHERE " + PhotoAlbumColumns::ALBUM_ID + " = " + to_string(referenceAlbumId); + auto resultSet = uniStore->QuerySql(queryCurrentAlbumOrder); + if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) { + return E_HAS_DB_ERROR; + } + int colIndex = -1; + resultSet->GetColumnIndex(PhotoAlbumColumns::ALBUM_ORDER, colIndex); + if (resultSet->GetInt(colIndex, currentAlbumOrder) != NativeRdb::E_OK) { + return E_HAS_DB_ERROR; + } + resultSet = uniStore->QuerySql(queryReferenceAlbumOrder); + if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK + || resultSet->GetInt(colIndex, referenceAlbumOrder) != NativeRdb::E_OK) { + return E_HAS_DB_ERROR; + } + return E_OK; +} + +static int32_t ExecSqls(const vector &sqls, const shared_ptr &store) +{ + int32_t err = NativeRdb::E_OK; + for (const auto &sql : sqls) { + err = store->ExecuteSql(sql); + if (err != NativeRdb::E_OK) { + MEDIA_ERR_LOG("Failed to exec: %{private}s", sql.c_str()); + break; + } + } + return NativeRdb::E_OK; +} + +static int32_t ObtainNotifyAlbumIds(int32_t ¤tAlbumOrder, int32_t referenceAlbumOrder, + vector &changedAlbumIds) +{ + auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStoreRaw()->GetRaw(); + if (uniStore == nullptr) { + MEDIA_ERR_LOG("uniStore is nullptr! failed query album order"); + return E_DB_FAIL; + } + std::string queryAlbumIds = ""; + if (currentAlbumOrder < referenceAlbumOrder) { + queryAlbumIds = "SELECT " + PhotoAlbumColumns::ALBUM_ID + " FROM " + + PhotoAlbumColumns::TABLE + " WHERE " + PhotoAlbumColumns::ALBUM_ORDER + " >= " + + to_string(currentAlbumOrder) + " AND " + PhotoAlbumColumns::ALBUM_ORDER + + " < " + to_string(referenceAlbumOrder); + } else { + queryAlbumIds = "SELECT " + PhotoAlbumColumns::ALBUM_ID + " FROM " + + PhotoAlbumColumns::TABLE + " WHERE " + PhotoAlbumColumns::ALBUM_ORDER + " >= " + + to_string(referenceAlbumOrder) + " AND " + PhotoAlbumColumns::ALBUM_ORDER + + " <= " + to_string(currentAlbumOrder); + } + auto resultSet = uniStore->QuerySql(queryAlbumIds); + if (resultSet == nullptr) { + return E_DB_FAIL; + } + while (resultSet->GoToNextRow() == NativeRdb::E_OK) { + changedAlbumIds.push_back(GetInt32Val(PhotoAlbumColumns::ALBUM_ID, resultSet)); + } + return E_OK; +} + +static void NotifyOrderChange(vector &changedAlbumIds) +{ + if (changedAlbumIds.size() <= 0) { + return; + } + auto watch = MediaLibraryNotify::GetInstance(); + for (int32_t &albumId : changedAlbumIds) { + watch->Notify(MediaFileUtils::GetUriByExtrConditions( + PhotoAlbumColumns::ALBUM_URI_PREFIX, to_string(albumId)), NotifyType::NOTIFY_UPDATE); + } +} + +static int32_t UpdateSortedOrder(const int32_t ¤tAlbumId, const int32_t referenceAlbumId, + int32_t ¤tAlbumOrder, int32_t &referenceAlbumOrder) +{ + auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore(); + if (uniStore == nullptr) { + MEDIA_ERR_LOG("uniStore is nullptr! failed query album order"); + return E_DB_FAIL; + } + std::string updateOtherAlbumOrder = ""; + std::string updateCurrentAlbumOrder = ""; + if (currentAlbumOrder < referenceAlbumOrder) { + updateOtherAlbumOrder = "UPDATE " + PhotoAlbumColumns::TABLE + + " SET " + PhotoAlbumColumns::ALBUM_ORDER + " = " + + PhotoAlbumColumns::ALBUM_ORDER + " -1 WHERE " + PhotoAlbumColumns::ALBUM_ORDER + + " > " + to_string(currentAlbumOrder) + + " and " + PhotoAlbumColumns::ALBUM_ORDER + " < " + to_string(referenceAlbumOrder); + updateCurrentAlbumOrder = "UPDATE " + PhotoAlbumColumns::TABLE + " SET " + PhotoAlbumColumns::ALBUM_ORDER + + " = " + to_string(referenceAlbumOrder) + " -1 WHERE " + + PhotoAlbumColumns::ALBUM_ID + " = " + to_string(currentAlbumId); + } else { + updateOtherAlbumOrder = "UPDATE " + PhotoAlbumColumns::TABLE + + " SET " + PhotoAlbumColumns::ALBUM_ORDER + " = " + + PhotoAlbumColumns::ALBUM_ORDER + " +1 WHERE " + PhotoAlbumColumns::ALBUM_ORDER + " >= " + + to_string(referenceAlbumOrder) + " AND " + PhotoAlbumColumns::ALBUM_ORDER + + " < " + to_string(currentAlbumOrder); + updateCurrentAlbumOrder = "UPDATE " + PhotoAlbumColumns::TABLE + + " SET " + PhotoAlbumColumns::ALBUM_ORDER + " = " + + to_string(referenceAlbumOrder) + " WHERE " + + PhotoAlbumColumns::ALBUM_ID + " = " + to_string(currentAlbumId); + } + vector updateSortedAlbumsSqls = { updateOtherAlbumOrder, updateCurrentAlbumOrder}; + return ExecSqls(updateSortedAlbumsSqls, uniStore); +} + +static int32_t ObtainCurrentAlbumOrder(const int32_t &albumId, int32_t &albumOrder) +{ + auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStoreRaw()->GetRaw(); + if (uniStore == nullptr) { + MEDIA_ERR_LOG("uniStore is nullptr! failed query album order"); + return E_HAS_DB_ERROR; + } + const std::string queryAlbumOrder = "SELECT " + PhotoAlbumColumns::ALBUM_ORDER + " FROM " + + PhotoAlbumColumns::TABLE + " WHERE " + PhotoAlbumColumns::ALBUM_ID + " = " + to_string(albumId); + auto resultSet = uniStore->QuerySql(queryAlbumOrder); + if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) { + return E_HAS_DB_ERROR; + } + int colIndex = -1; + resultSet->GetColumnIndex(PhotoAlbumColumns::ALBUM_ORDER, colIndex); + if (resultSet->GetInt(colIndex, albumOrder) != NativeRdb::E_OK) { + return E_HAS_DB_ERROR; + } + return E_OK; +} + +static int32_t UpdateNullReferenceOrder(const int32_t ¤tAlbumId, + const int32_t ¤tAlbumOrder, const int32_t &maxAlbumOrder) +{ + auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore(); + if (uniStore == nullptr) { + MEDIA_ERR_LOG("uniStore is nullptr! failed query album order"); + return E_DB_FAIL; + } + std::string updateOtherAlbumOrder = "UPDATE " + PhotoAlbumColumns::TABLE + " SET " + + PhotoAlbumColumns::ALBUM_ORDER + " = " + PhotoAlbumColumns::ALBUM_ORDER + " -1 WHERE " + + PhotoAlbumColumns::ALBUM_ORDER + " > " + to_string(currentAlbumOrder) + " and " + + PhotoAlbumColumns::ALBUM_ORDER + " <= " + to_string(maxAlbumOrder); + std::string updateCurrentAlbumOrder = "UPDATE " + PhotoAlbumColumns::TABLE + + " SET " + PhotoAlbumColumns::ALBUM_ORDER + " = " + to_string(maxAlbumOrder) + + " WHERE " + PhotoAlbumColumns::ALBUM_ID + " = " + to_string(currentAlbumId); + vector updateSortedAlbumsSqls = { updateOtherAlbumOrder, updateCurrentAlbumOrder}; + return ExecSqls(updateSortedAlbumsSqls, uniStore); +} + +static int32_t HandleNullReferenceCondition(const int32_t ¤tAlbumId) +{ + int32_t maxAlbumOrder = 0; + int err = ObtainMaxAlbumOrder(maxAlbumOrder); + if (err != E_OK) { + return E_HAS_DB_ERROR; + } + int32_t currentAlbumOrder = -1; + err = ObtainCurrentAlbumOrder(currentAlbumId, currentAlbumOrder); + if (err != E_OK) { + return err; + } + vector changedAlbumIds; + ObtainNotifyAlbumIds(currentAlbumOrder, maxAlbumOrder + 1, changedAlbumIds); // 1: move order curosr to the end + err = UpdateNullReferenceOrder(currentAlbumId, currentAlbumOrder, maxAlbumOrder); + if (err == E_OK) { + NotifyOrderChange(changedAlbumIds); + } + return err; +} + +/** + * Place the current album before the reference album + * @param values contains current and reference album_id + */ +int32_t OrderSingleAlbum(const ValuesBucket &values) +{ + int32_t currentAlbumId; + int32_t referenceAlbumId; + int err = GetIntVal(values, PhotoAlbumColumns::ALBUM_ID, currentAlbumId); + if (err < 0 || currentAlbumId <= 0) { + MEDIA_ERR_LOG("invalid album id"); + return E_INVALID_VALUES; + } + err = GetIntVal(values, PhotoAlbumColumns::REFERENCE_ALBUM_ID, referenceAlbumId); + if (err < 0 || referenceAlbumId == 0 || referenceAlbumId < NULL_REFERENCE_ALBUM_ID) { + MEDIA_ERR_LOG("invalid reference album id"); + return E_INVALID_VALUES; + } + if (currentAlbumId == referenceAlbumId) { // same album, no need to order + return E_OK; + } + if (referenceAlbumId == NULL_REFERENCE_ALBUM_ID) { + return HandleNullReferenceCondition(currentAlbumId); + } + int32_t currentAlbumOrder = -1; // -1: default invalid value + int32_t referenceAlbumOrder = -1; + err = ObtainAlbumOrders(currentAlbumId, referenceAlbumId, currentAlbumOrder, referenceAlbumOrder); + if (err != E_OK) { + MEDIA_ERR_LOG("obtains album order error"); + return err; + } + vector changedAlbumIds; + ObtainNotifyAlbumIds(currentAlbumOrder, referenceAlbumOrder, changedAlbumIds); + err = UpdateSortedOrder(currentAlbumId, referenceAlbumId, currentAlbumOrder, referenceAlbumOrder); + if (err == E_OK) { + NotifyOrderChange(changedAlbumIds); + } + return E_OK; +} + int32_t MediaLibraryAlbumOperations::HandlePhotoAlbum(const OperationType &opType, const ValuesBucket &values, const DataSharePredicates &predicates, shared_ptr countPtr) { @@ -557,6 +807,8 @@ int32_t MediaLibraryAlbumOperations::HandlePhotoAlbum(const OperationType &opTyp return CompatDeletePhotoAssets(predicates, false); case OperationType::AGING: return AgingPhotoAssets(countPtr); + case OperationType::ALBUM_ORDER: + return OrderSingleAlbum(values); default: MEDIA_ERR_LOG("Unknown operation type: %{public}d", opType); return E_ERR; diff --git a/frameworks/innerkitsimpl/medialibrary_data_extension/src/medialibrary_command.cpp b/frameworks/innerkitsimpl/medialibrary_data_extension/src/medialibrary_command.cpp index d173423665..87acf97f64 100644 --- a/frameworks/innerkitsimpl/medialibrary_data_extension/src/medialibrary_command.cpp +++ b/frameworks/innerkitsimpl/medialibrary_data_extension/src/medialibrary_command.cpp @@ -42,6 +42,7 @@ static const map OPRN_TYPE_MAP = { { MEDIA_ALBUMOPRN_CREATEALBUM, OperationType::CREATE }, { MEDIA_FILEOPRN_DELETEASSET, OperationType::DELETE }, { MEDIA_ALBUMOPRN_DELETEALBUM, OperationType::DELETE }, + { MEDIA_FILEOPRN_ORDERALBUM, OperationType::ALBUM_ORDER}, { MEDIA_FILEOPRN_MODIFYASSET, OperationType::UPDATE }, { MEDIA_ALBUMOPRN_MODIFYALBUM, OperationType::UPDATE }, { MEDIA_ALBUMOPRN_QUERYALBUM, OperationType::QUERY }, diff --git a/frameworks/innerkitsimpl/medialibrary_data_extension/src/medialibrary_rdbstore.cpp b/frameworks/innerkitsimpl/medialibrary_data_extension/src/medialibrary_rdbstore.cpp index ef771bcbaa..30b079984d 100644 --- a/frameworks/innerkitsimpl/medialibrary_data_extension/src/medialibrary_rdbstore.cpp +++ b/frameworks/innerkitsimpl/medialibrary_data_extension/src/medialibrary_rdbstore.cpp @@ -583,6 +583,8 @@ int32_t PrepareSystemAlbums(RdbStore &store) for (int32_t i = PhotoAlbumSubType::SYSTEM_START; i <= PhotoAlbumSubType::SYSTEM_END; i++) { values.PutInt(PhotoAlbumColumns::ALBUM_TYPE, PhotoAlbumType::SYSTEM); values.PutInt(PhotoAlbumColumns::ALBUM_SUBTYPE, i); + // 1:order offset,skip 0 for first album + values.PutInt(PhotoAlbumColumns::ALBUM_ORDER, i - PhotoAlbumSubType::SYSTEM_START + 1); AbsRdbPredicates predicates(PhotoAlbumColumns::TABLE); predicates.EqualTo(PhotoAlbumColumns::ALBUM_TYPE, to_string(PhotoAlbumType::SYSTEM)); @@ -895,6 +897,8 @@ static const vector onCreateSqlStrs = { PhotoAlbumColumns::CREATE_ALBUM_INSERT_TRIGGER, PhotoAlbumColumns::CREATE_ALBUM_MDIRTY_TRIGGER, PhotoAlbumColumns::CREATE_ALBUM_DELETE_TRIGGER, + PhotoAlbumColumns::ALBUM_DELETE_ORDER_TRIGGER, + PhotoAlbumColumns::ALBUM_INSERT_ORDER_TRIGGER, PhotoMap::CREATE_TABLE, PhotoMap::CREATE_NEW_TRIGGER, PhotoMap::CREATE_DELETE_TRIGGER, @@ -1520,6 +1524,36 @@ void AddHiddenTimeColumn(RdbStore &store) ExecSqls(sqls, store); } +void AddAlbumOrderColumn(RdbStore &store) +{ + const std::string addAlbumOrderColumn = + "ALTER TABLE " + PhotoAlbumColumns::TABLE + " ADD COLUMN " + + PhotoAlbumColumns::ALBUM_ORDER + " INT"; + const std::string initOriginOrder = + "UPDATE " + PhotoAlbumColumns::TABLE + " SET " + + PhotoAlbumColumns::ALBUM_ORDER + " = rowid"; + const std::string albumDeleteTrigger = + " CREATE TRIGGER update_order_trigger AFTER DELETE ON " + PhotoAlbumColumns::TABLE + + " FOR EACH ROW " + + " BEGIN " + + " UPDATE " + PhotoAlbumColumns::TABLE + " SET album_order = album_order - 1" + + " WHERE album_order > old.album_order; " + + " END"; + const std::string albumInsertTrigger = + " CREATE TRIGGER insert_order_trigger AFTER INSERT ON " + PhotoAlbumColumns::TABLE + + " BEGIN " + + " UPDATE " + PhotoAlbumColumns::TABLE + " SET album_order = (" + + " SELECT Max(album_order) FROM " + PhotoAlbumColumns::TABLE + ") + 1 WHERE rowid = new.rowid;" + " END"; + + const vector addAlbumOrder = { addAlbumOrderColumn, initOriginOrder, + albumDeleteTrigger, albumInsertTrigger}; + int32_t result = ExecSqls(addAlbumOrder, store); + if (result != NativeRdb::E_OK) { + MEDIA_ERR_LOG("Upgrade rdb album order error %{private}d", result); + } +} + static void UpgradeOtherTable(RdbStore &store, int32_t oldVersion) { if (oldVersion < VERSION_ADD_PACKAGE_NAME) { @@ -1569,7 +1603,10 @@ static void UpgradeOtherTable(RdbStore &store, int32_t oldVersion) if (oldVersion < VERSION_UPDATE_DATE_TO_MILLISECOND) { UpdateMillisecondDate(store); } +} +static void UpgradeGalleryFeatureTable(RdbStore &store, int32_t oldVersion) +{ if (oldVersion < VERSION_ADD_HIDDEN_VIEW_COLUMNS) { AddHiddenViewColumn(store); } @@ -1586,6 +1623,10 @@ static void UpgradeOtherTable(RdbStore &store, int32_t oldVersion) if (oldVersion < VERSION_ADD_LOCATION_TABLE) { AddLocationTables(store); } + + if (oldVersion < VERSION_ADD_ALBUM_ORDER) { + AddAlbumOrderColumn(store); + } } int32_t MediaLibraryDataCallBack::OnUpgrade(RdbStore &store, int32_t oldVersion, int32_t newVersion) @@ -1629,6 +1670,7 @@ int32_t MediaLibraryDataCallBack::OnUpgrade(RdbStore &store, int32_t oldVersion, } UpgradeOtherTable(store, oldVersion); + UpgradeGalleryFeatureTable(store, oldVersion); if (!g_upgradeErr) { VariantMap map = {{KEY_PRE_VERSION, oldVersion}, {KEY_AFTER_VERSION, newVersion}}; diff --git a/frameworks/innerkitsimpl/test/unittest/photo_album_test/src/photo_album_test.cpp b/frameworks/innerkitsimpl/test/unittest/photo_album_test/src/photo_album_test.cpp index 40bfb556be..3820aebd58 100644 --- a/frameworks/innerkitsimpl/test/unittest/photo_album_test/src/photo_album_test.cpp +++ b/frameworks/innerkitsimpl/test/unittest/photo_album_test/src/photo_album_test.cpp @@ -174,6 +174,13 @@ inline int32_t UpdatePhotoAlbum(const DataShareValuesBucket &values, const DataS return MediaLibraryDataManager::GetInstance()->Update(cmd, values, predicates); } +inline int32_t OrderAlbums(const DataShareValuesBucket &values, const DataSharePredicates &predicates) +{ + Uri uri(URI_UPDATE_PHOTO_ALBUM); + MediaLibraryCommand cmd(uri, OperationType::ALBUM_ORDER); + return MediaLibraryDataManager::GetInstance()->Update(cmd, values, predicates); +} + void CheckUpdatedAlbum(int32_t albumId, const string &expectedName, const string &expectedCover) { string coverUri; @@ -495,4 +502,67 @@ HWTEST_F(PhotoAlbumTest, photoalbum_update_album_005, TestSize.Level0) CheckUpdatedSystemAlbum(PhotoAlbumSubType::FAVORITE, "", ""); MEDIA_INFO_LOG("photoalbum_update_album_005 end"); } + +/** + * @tc.name: photoalbum_order_album_006 + * @tc.desc: order photo album. + * move current album before reference album + * @tc.type: FUNC + * @tc.require: issueI6P7NG + */ +HWTEST_F(PhotoAlbumTest, photoalbum_order_album_006, TestSize.Level0) +{ + MEDIA_INFO_LOG("photoalbum_order_album_006 enter"); + + // Build empty values + DataShareValuesBucket values; + values.Put(PhotoAlbumColumns::ALBUM_ID, 2); + values.Put(PhotoAlbumColumns::REFERENCE_ALBUM_ID, 5); // 2\5:album_id + // Try to update favorite system + DataSharePredicates predicates; + EXPECT_EQ(OrderAlbums(values, predicates), 0); + MEDIA_INFO_LOG("photoalbum_order_album_006 end"); +} + +/** + * @tc.name: photoalbum_order_album_007 + * @tc.desc: order photo album. + * move current album before reference album + * @tc.type: FUNC + * @tc.require: issueI6P7NG + */ +HWTEST_F(PhotoAlbumTest, photoalbum_order_album_007, TestSize.Level0) +{ + MEDIA_INFO_LOG("photoalbum_order_album_007 enter"); + + // Build empty values + DataShareValuesBucket values; + values.Put(PhotoAlbumColumns::ALBUM_ID, 2); // 2\5:album_id + values.Put(PhotoAlbumColumns::REFERENCE_ALBUM_ID, 5); + // Try to update favorite system + DataSharePredicates predicates; + EXPECT_EQ(OrderAlbums(values, predicates), 0); + MEDIA_INFO_LOG("photoalbum_order_album_007 end"); +} + +/** + * @tc.name: photoalbum_order_album_007 + * @tc.desc: order photo album. + * move current album before reference album + * @tc.type: FUNC + * @tc.require: issueI6P7NG + */ +HWTEST_F(PhotoAlbumTest, photoalbum_order_album_008, TestSize.Level0) +{ + MEDIA_INFO_LOG("photoalbum_order_album_008 enter"); + + // Build empty values + DataShareValuesBucket values; + values.Put(PhotoAlbumColumns::ALBUM_ID, 3); // 3:album_id + values.Put(PhotoAlbumColumns::REFERENCE_ALBUM_ID, -1); + // Try to update favorite system + DataSharePredicates predicates; + EXPECT_EQ(OrderAlbums(values, predicates), 0); + MEDIA_INFO_LOG("photoalbum_order_album_008 end"); +} } // namespace OHOS::Media diff --git a/frameworks/js/src/media_album_change_request_napi.cpp b/frameworks/js/src/media_album_change_request_napi.cpp index 0be0fe8900..63f967769a 100644 --- a/frameworks/js/src/media_album_change_request_napi.cpp +++ b/frameworks/js/src/media_album_change_request_napi.cpp @@ -41,6 +41,7 @@ napi_value MediaAlbumChangeRequestNapi::Init(napi_env env, napi_value exports) .props = { DECLARE_NAPI_FUNCTION("setAlbumName", JSSetAlbumName), DECLARE_NAPI_FUNCTION("setCoverUri", JSSetCoverUri), + DECLARE_NAPI_FUNCTION("placeToFrontOf", JSPlaceToFrontOf) } }; MediaLibraryNapiUtils::NapiDefineClass(env, exports, info); return exports; @@ -97,6 +98,11 @@ shared_ptr MediaAlbumChangeRequestNapi::GetPhotoAlbumInstance() cons return photoAlbum_; } +shared_ptr MediaAlbumChangeRequestNapi::GetReferencePhotoAlbumInstance() const +{ + return referencePhotoAlbum_; +} + napi_value MediaAlbumChangeRequestNapi::JSSetAlbumName(napi_env env, napi_callback_info info) { auto asyncContext = make_unique(); @@ -147,6 +153,54 @@ napi_value MediaAlbumChangeRequestNapi::JSSetCoverUri(napi_env env, napi_callbac return result; } +napi_value MediaAlbumChangeRequestNapi::JSPlaceToFrontOf(napi_env env, napi_callback_info info) +{ + if (!MediaLibraryNapiUtils::IsSystemApp()) { + NapiError::ThrowError(env, E_CHECK_SYSTEMAPP_FAIL, "This interface can be called only by system apps"); + return nullptr; + } + napi_valuetype valueType; + auto asyncContext = make_unique(); + + CHECK_COND_WITH_MESSAGE(env, MediaLibraryNapiUtils::AsyncContextSetObjectInfo( + env, info, asyncContext, ARGS_ONE, ARGS_ONE) == napi_ok, "Failed to get object info"); + CHECK_ARGS(env, napi_typeof(env, asyncContext->argv[PARAM0], &valueType), JS_INNER_FAIL); + CHECK_COND_WITH_MESSAGE(env, valueType == napi_object || valueType == napi_null, "Invalid argument type"); + if (valueType == napi_object) { + PhotoAlbumNapi* photoAlbumNapi; + CHECK_ARGS(env, napi_unwrap(env, asyncContext->argv[PARAM0], + reinterpret_cast(&photoAlbumNapi)), JS_INNER_FAIL); + CHECK_COND_WITH_MESSAGE(env, photoAlbumNapi != nullptr, "Failed to get PhotoAlbumNapi object"); + asyncContext->objectInfo->referencePhotoAlbum_ = photoAlbumNapi->GetPhotoAlbumInstance(); + } + asyncContext->objectInfo->albumChangeOperations_.push_back(AlbumChangeOperation::ORDER_ALBUM); + napi_value result = nullptr; + CHECK_ARGS(env, napi_get_undefined(env, &result), JS_INNER_FAIL); + return result; +} + +static bool OrderAlbumExecute(MediaAlbumChangeRequestAsyncContext& context) +{ + DataShare::DataSharePredicates predicates; + DataShare::DataShareValuesBucket valuesBucket; + auto photoAlbum = context.objectInfo->GetPhotoAlbumInstance(); + auto referenceAlum = context.objectInfo->GetReferencePhotoAlbumInstance(); + Uri updateAlbumUri(URI_COMPAT_ORDER_ALBUM); + valuesBucket.Put(PhotoAlbumColumns::ALBUM_ID, photoAlbum->GetAlbumId()); + int32_t referenceAlbumId = -1; + if (referenceAlum != nullptr) { + referenceAlbumId = referenceAlum->GetAlbumId(); + } + valuesBucket.Put(PhotoAlbumColumns::REFERENCE_ALBUM_ID, referenceAlbumId); + int32_t result = UserFileClient::Update(updateAlbumUri, predicates, valuesBucket); + if (result < 0) { + context.SaveError(result); + NAPI_ERR_LOG("Failed to order albums err: %{public}d", result); + return false; + } + return true; +} + static bool SetAlbumPropertyExecute( MediaAlbumChangeRequestAsyncContext& context, const AlbumChangeOperation& changeOperation) { @@ -198,6 +252,9 @@ static void ApplyAlbumChangeRequestExecute(napi_env env, void* data) case AlbumChangeOperation::SET_COVER_URI: valid = SetAlbumPropertyExecute(*context, changeOperation); break; + case AlbumChangeOperation::ORDER_ALBUM: + valid = OrderAlbumExecute(*context); + break; default: NAPI_ERR_LOG("Invalid album change operation: %{public}d", changeOperation); context->error = JS_ERR_PARAMETER_INVALID; diff --git a/frameworks/js/src/media_asset_change_request_napi.cpp b/frameworks/js/src/media_asset_change_request_napi.cpp index baadd23dff..22a08b79c0 100644 --- a/frameworks/js/src/media_asset_change_request_napi.cpp +++ b/frameworks/js/src/media_asset_change_request_napi.cpp @@ -249,7 +249,7 @@ static bool SetAssetPropertyExecute( DataShare::DataShareValuesBucket valuesBucket; auto fileAsset = context.objectInfo->GetFileAssetInstance(); predicates.SetWhereClause(PhotoColumn::MEDIA_ID + " = ? "); - predicates.SetWhereArgs({ to_string(fileAsset->GetId()) }); + predicates.SetWhereArgs({to_string(fileAsset->GetId())}); switch (changeOperation) { case AssetChangeOperation::SET_FAVORITE: uri = PAH_UPDATE_PHOTO; diff --git a/frameworks/services/media_scanner/src/scanner/metadata_extractor.cpp b/frameworks/services/media_scanner/src/scanner/metadata_extractor.cpp index 3baa9c5fab..668c6283fd 100644 --- a/frameworks/services/media_scanner/src/scanner/metadata_extractor.cpp +++ b/frameworks/services/media_scanner/src/scanner/metadata_extractor.cpp @@ -186,9 +186,8 @@ static std::string ExtractVideoShootingMode(const std::string &genreJson) end = genreJson.find("}", pos); } return genreJson.substr(start + 1, end - start - 1); // 1: length offset - } else { - return ""; } + return ""; } void MetadataExtractor::FillExtractedMetadata(const std::unordered_map &resultMap, diff --git a/frameworks/utils/include/userfilemgr_uri.h b/frameworks/utils/include/userfilemgr_uri.h index efb5261c09..fd0fd1445c 100644 --- a/frameworks/utils/include/userfilemgr_uri.h +++ b/frameworks/utils/include/userfilemgr_uri.h @@ -82,6 +82,7 @@ const std::string MEDIA_ALBUMOPRN_CREATEALBUM = "create_album"; const std::string MEDIA_ALBUMOPRN_MODIFYALBUM = "modify_album"; const std::string MEDIA_ALBUMOPRN_DELETEALBUM = "delete_album"; const std::string MEDIA_ALBUMOPRN_QUERYALBUM = "query_album"; +const std::string MEDIA_FILEOPRN_ORDERALBUM = "order_album"; const std::string MEDIA_FILEOPRN_GETALBUMCAPACITY = "get_album_capacity"; // Photo album operations constants @@ -90,6 +91,8 @@ const std::string URI_QUERY_PHOTO_ALBUM = MEDIALIBRARY_DATA_URI + "/" + PHOTO_AL const std::string URI_DELETE_PHOTOS = MEDIALIBRARY_DATA_URI + "/" + PHOTO_ALBUM_OPRN + "/" + OPRN_DELETE_PHOTOS; const std::string URI_COMPAT_DELETE_PHOTOS = MEDIALIBRARY_DATA_URI + "/" + PHOTO_ALBUM_OPRN + "/" + OPRN_COMPAT_DELETE_PHOTOS; +const std::string URI_COMPAT_ORDER_ALBUM = MEDIALIBRARY_DATA_URI + "/" + PHOTO_ALBUM_OPRN + "/" + + MEDIA_FILEOPRN_ORDERALBUM; // Photo map operations constants const std::string PHOTO_MAP_OPRN = "photo_map_v10_operation"; diff --git a/interfaces/inner_api/media_library_helper/include/medialibrary_db_const.h b/interfaces/inner_api/media_library_helper/include/medialibrary_db_const.h index 470d624692..c9e8b18f5e 100644 --- a/interfaces/inner_api/media_library_helper/include/medialibrary_db_const.h +++ b/interfaces/inner_api/media_library_helper/include/medialibrary_db_const.h @@ -22,7 +22,7 @@ namespace OHOS { namespace Media { -const int32_t MEDIA_RDB_VERSION = 29; +const int32_t MEDIA_RDB_VERSION = 30; enum { VERSION_ADD_CLOUD = 2, VERSION_ADD_META_MODIFED = 3, @@ -56,6 +56,7 @@ enum { VERSION_ADD_HIDDEN_TIME = 27, VERSION_ADD_LAST_VISIT_TIME = 28, VERSION_ADD_LOCATION_TABLE = 29, + VERSION_ADD_ALBUM_ORDER = 30, }; enum { @@ -185,6 +186,7 @@ const std::string MEDIA_DATA_DB_DEVICE_NAME = "device_name"; const std::string MEDIA_DATA_DB_ALBUM = "album"; const std::string MEDIA_DATA_DB_ALBUM_ID = "album_id"; +const std::string MEDIA_DATA_DB_REFERENCE_ALBUM_ID = "reference_album_id"; const std::string MEDIA_DATA_DB_ALBUM_NAME = "album_name"; const std::string MEDIA_DATA_DB_COUNT = "count"; const std::string MEDIA_DATA_BUNDLENAME = "bundle_name"; diff --git a/interfaces/inner_api/media_library_helper/include/photo_album_column.h b/interfaces/inner_api/media_library_helper/include/photo_album_column.h index b2db1ef587..eed0a248b8 100644 --- a/interfaces/inner_api/media_library_helper/include/photo_album_column.h +++ b/interfaces/inner_api/media_library_helper/include/photo_album_column.h @@ -44,6 +44,9 @@ public: static const std::string HIDDEN_COUNT; static const std::string HIDDEN_COVER; + // For sorting albums + static const std::string ALBUM_ORDER; + static const std::string REFERENCE_ALBUM_ID; // default fetch columns static const std::set DEFAULT_FETCH_COLUMNS; @@ -59,6 +62,8 @@ public: static const std::string CREATE_ALBUM_INSERT_TRIGGER; static const std::string CREATE_ALBUM_MDIRTY_TRIGGER; static const std::string CREATE_ALBUM_DELETE_TRIGGER; + static const std::string ALBUM_DELETE_ORDER_TRIGGER; + static const std::string ALBUM_INSERT_ORDER_TRIGGER; // util constants static const std::string ALBUM_URI_PREFIX; diff --git a/interfaces/kits/js/include/media_album_change_request_napi.h b/interfaces/kits/js/include/media_album_change_request_napi.h index 25213f41b8..c387d099bf 100644 --- a/interfaces/kits/js/include/media_album_change_request_napi.h +++ b/interfaces/kits/js/include/media_album_change_request_napi.h @@ -27,16 +27,17 @@ namespace Media { enum class AlbumChangeOperation { SET_ALBUM_NAME, SET_COVER_URI, + ORDER_ALBUM, }; class MediaAlbumChangeRequestNapi : public MediaChangeRequestNapi { public: MediaAlbumChangeRequestNapi() = default; ~MediaAlbumChangeRequestNapi() override = default; - static napi_value Init(napi_env env, napi_value exports); std::shared_ptr GetPhotoAlbumInstance() const; + std::shared_ptr GetReferencePhotoAlbumInstance() const; napi_value ApplyChanges(napi_env env, napi_callback_info info) override; private: @@ -45,12 +46,13 @@ private: static napi_value JSSetAlbumName(napi_env env, napi_callback_info info); static napi_value JSSetCoverUri(napi_env env, napi_callback_info info); + static napi_value JSPlaceToFrontOf(napi_env env, napi_callback_info info); static thread_local napi_ref constructor_; std::shared_ptr photoAlbum_ = nullptr; + std::shared_ptr referencePhotoAlbum_ = nullptr; std::vector albumChangeOperations_; }; - struct MediaAlbumChangeRequestAsyncContext : public NapiError { size_t argc; napi_value argv[NAPI_ARGC_MAX]; @@ -66,4 +68,4 @@ struct MediaAlbumChangeRequestAsyncContext : public NapiError { } // namespace Media } // namespace OHOS -#endif // INTERFACES_KITS_JS_MEDIALIBRARY_INCLUDE_MEDIA_ALBUM_CHANGE_REQUEST_NAPI_H_ +#endif // INTERFACES_KITS_JS_MEDIALIBRARY_INCLUDE_MEDIA_ALBUM_CHANGE_REQUEST_NAPI_H_ \ No newline at end of file -- Gitee From 75c73792f8029323d9b79788c1b77cc32b0a87d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E5=87=AF=E6=99=93?= Date: Sun, 5 Nov 2023 15:11:29 +0000 Subject: [PATCH 2/2] update interfaces/kits/js/include/media_album_change_request_napi.h. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 赵凯晓 --- .../kits/js/include/media_album_change_request_napi.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interfaces/kits/js/include/media_album_change_request_napi.h b/interfaces/kits/js/include/media_album_change_request_napi.h index c387d099bf..0b5dd1d2c9 100644 --- a/interfaces/kits/js/include/media_album_change_request_napi.h +++ b/interfaces/kits/js/include/media_album_change_request_napi.h @@ -13,8 +13,8 @@ * limitations under the License. */ -#ifndef INTERFACES_KITS_JS_MEDIALIBRARY_INCLUDE_MEDIA_ALBUM_CHANGE_REQUEST_NAPI_H_ -#define INTERFACES_KITS_JS_MEDIALIBRARY_INCLUDE_MEDIA_ALBUM_CHANGE_REQUEST_NAPI_H_ +#ifndef INTERFACES_KITS_JS_MEDIALIBRARY_INCLUDE_MEDIA_ALBUM_CHANGE_REQUEST_NAPI_H +#define INTERFACES_KITS_JS_MEDIALIBRARY_INCLUDE_MEDIA_ALBUM_CHANGE_REQUEST_NAPI_H #include "datashare_helper.h" #include "datashare_predicates.h" @@ -68,4 +68,4 @@ struct MediaAlbumChangeRequestAsyncContext : public NapiError { } // namespace Media } // namespace OHOS -#endif // INTERFACES_KITS_JS_MEDIALIBRARY_INCLUDE_MEDIA_ALBUM_CHANGE_REQUEST_NAPI_H_ \ No newline at end of file +#endif // INTERFACES_KITS_JS_MEDIALIBRARY_INCLUDE_MEDIA_ALBUM_CHANGE_REQUEST_NAPI_H \ No newline at end of file -- Gitee