6#include <QtCore/private/qcore_ohos_p.h>
7#include <QtCore/private/qnapi_p.h>
8#include <QtCore/private/qohoscommon_p.h>
9#include <QtCore/private/qohosjstools_p.h>
10#include <QtCore/private/qohoslogger_p.h>
11#include <QtCore/private/qohospathutils_p.h>
20#include <database/udmf/udmf_meta.h>
21#include <database/udmf/utd.h>
31std::optional<
std::string> tryMapMimeTypeToUtdTypeId(
const std::string &mimeType)
37 unsigned int typesCount = 0;
38 const char **utdTypeIds = ::OH_Utd_GetTypesByMimeType(mimeType.c_str(), &typesCount);
39 if (utdTypeIds ==
nullptr && typesCount != 0) {
40 qOhosReportFatalErrorAndAbort(
41 "%s: got inconsistent result from OH_Utd_GetTypesByMimeType() call: array is null, size is %u",
42 Q_FUNC_INFO, typesCount);
45 auto utdTypeIdsList = utdTypeIds !=
nullptr
46 ? std::vector<std::string>(utdTypeIds, utdTypeIds + typesCount)
47 : std::vector<std::string>();
49 ::OH_Utd_DestroyStringList(utdTypeIds, typesCount);
51 return !utdTypeIdsList.empty()
52 ?
std::make_optional(utdTypeIdsList.front())
56std::optional<QNapi::Object> tryMakeShareKitSharedDataRecordObject(
59 auto optUtdType = record.mimeType != mimeTextUriList
60 ? tryMapMimeTypeToUtdTypeId(record.mimeType)
61 : std::optional<std::string>(UDMF_META_HYPERLINK);
63 if (!optUtdType.has_value()) {
65 "%s: Cannot convert mime type: %s to utd type.", Q_FUNC_INFO, record
.mimeType.c_str());
69 std::vector<std::pair<std::string, QNapi::ValueWrapper>> objectProperties = {
70 {
"utd", optUtdType.value()},
73 if (record.content.has_value()) {
74 objectProperties.emplace_back(
"content", record.content.value());
75 }
else if (record.filePath.has_value()) {
76 objectProperties.emplace_back(
78 tryMapPathToOhosFileUri(record.filePath.value()).value_or(
""));
80 qOhosPrintfWarning(
"%s: Record doesn't have content nor uri.", Q_FUNC_INFO);
84 if (record.title.has_value())
85 objectProperties.emplace_back(
"title", record.title.value());
87 if (record.label.has_value())
88 objectProperties.emplace_back(
"label", record.label.value());
90 if (record.description.has_value())
91 objectProperties.emplace_back(
"description", record.description.value());
93 if (record.thumbnail.has_value()) {
94 auto thumbnail = record.thumbnail.value();
95 auto napiThumbnail = QNapi::TypedArrayOf<std::uint8_t>::New(jsState.env(), thumbnail.length());
96 std::memcpy(napiThumbnail.Data(), thumbnail.data(), thumbnail.length());
98 objectProperties.emplace_back(
"thumbnail", napiThumbnail);
101 if (record.thumbnailFilePath.has_value()) {
102 objectProperties.emplace_back(
104 tryMapPathToOhosFileUri(record.thumbnailFilePath.value()).value_or(
""));
107 if (record.extraData.has_value()) {
108 objectProperties.emplace_back(
110 QOhosJsEnv::toNapiValue(jsState.env(), QJsonObject::fromVariantMap(record.extraData.value())));
113 return std::make_optional(QNapi::makeObject(jsState.env(), objectProperties));
116std::optional<QNapi::Object> tryMakeShareKitShareControllerAnchorObject(
119 if (anchor.windowOffset.isNull())
122 auto shareControllerAnchorObject = QNapi::makeObject(
130 {
"x", anchor.windowOffset.x()},
131 {
"y", anchor.windowOffset.y()},
136 if (anchor.size.has_value() && anchor.size.value().isValid()) {
137 shareControllerAnchorObject.set(
142 {
"width", anchor.size.value().width()},
143 {
"height", anchor.size.value().height()},
147 return std::make_optional(shareControllerAnchorObject);
150QNapi::Object makeShareKitControllerOptionsObject(
153 auto controllerOptionsObject = QNapi::makeObject(jsState.env());
155 if (controllerOptions.selectionMode.has_value()) {
156 controllerOptionsObject.set(
157 "selectionMode", jsState.mapOhosEnumToJs(controllerOptions.selectionMode.value()));
160 if (controllerOptions.anchor.has_value()) {
161 auto controllerAnchorObject = tryMakeShareKitShareControllerAnchorObject(
162 jsState, controllerOptions.anchor.value());
163 if (controllerAnchorObject.has_value())
164 controllerOptionsObject.set(
"anchor", controllerAnchorObject.value());
167 if (controllerOptions.previewMode.has_value()) {
168 controllerOptionsObject.set(
169 "previewMode", jsState.mapOhosEnumToJs(controllerOptions.previewMode.value()));
172 if (controllerOptions.excludedAbilities.has_value()) {
173 controllerOptionsObject.set(
176 jsState.env(), controllerOptions.excludedAbilities.value(),
177 [&](
auto excludedAbilityType) {
178 return jsState.mapOhosEnumToJs(excludedAbilityType);
182 return controllerOptionsObject;
185std::shared_ptr<
void> registerOnOffShareCompletedEventHandler(
186 QNapi::Object shareController, QOhosConsumer<ShareOperationResult> shareCompletedCallback)
188 return registerQOhosOnOffMethodsBasedEventHandler(
189 shareController,
"shareCompleted",
190 [shareCompletedCallback = std::move(shareCompletedCallback)](
const QNapi::CallbackInfo &cbInfo) {
191 const auto shareOperationResult = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
192 const auto targetAbilityName = shareOperationResult.eval<QNapi::String>(
193 "targetAbilityInfo.name");
194 shareCompletedCallback(
196 .targetAbilityName = targetAbilityName,
202 QOhosJsState &jsState, QNapi::Object uiAbility,
203 const std::vector<SharedRecord> &recordsToShare,
ControllerOptions controllerOptions,
204 std::function<
void()> panelClosedCallback, QOhosConsumer<ShareOperationResult> shareCompletedCallback,
205 QOhosConsumer<std::shared_ptr<
void>> resultConsumer)
207 qOhosPrintfDebug(
"%s: sharing %lu records through ShareKit", Q_FUNC_INFO, recordsToShare.size());
209 if (recordsToShare.empty()) {
210 qOhosPrintfWarning(
"%s: No records to share. Skipping...", Q_FUNC_INFO);
211 resultConsumer(
nullptr);
215 auto firstRecord = tryMakeShareKitSharedDataRecordObject(jsState, recordsToShare.front());
216 if (!firstRecord.has_value()) {
217 qOhosPrintfWarning(
"%s: Failed to create the very first record, skip sharing", Q_FUNC_INFO);
218 resultConsumer(
nullptr);
222 "%s: record #0 to be shared: %s",
223 Q_FUNC_INFO, QNapi::toJsonString(firstRecord.value()).c_str());
225 auto sharedDataObject = jsState.eval<QNapi::Object>(
226 "@kit.ShareKit.systemShare.SharedData<new>(*)", {firstRecord.value()});
228 for (
std::size_t i = 1; i < recordsToShare.size(); i++) {
229 auto record = tryMakeShareKitSharedDataRecordObject(jsState, recordsToShare.at(i));
230 if (record.has_value()) {
232 "%s: record #%zu to be shared: %s",
233 Q_FUNC_INFO, i, QNapi::toJsonString(record.value()).c_str());
234 sharedDataObject.eval(
"addRecord(*)", {record.value()});
236 qOhosPrintfWarning(
"%s: Failed to create record", Q_FUNC_INFO);
240 auto controller = jsState.eval<QNapi::Object>(
241 "@kit.ShareKit.systemShare.ShareController<new>(*)", {sharedDataObject});
243 auto callbacksHandle = QtOhos::moveToSharedPtr(
244 std::vector<std::shared_ptr<
void>>{
245 registerQOhosOnOffMethodsBasedEventHandler(
246 controller,
"dismiss", std::move(panelClosedCallback)),
247 registerOnOffShareCompletedEventHandler(controller, std::move(shareCompletedCallback)),
250 controller.evalToPromiseOrRejectOnThrow(
253 uiAbility.get<QNapi::Object>(
"context"),
254 makeShareKitControllerOptionsObject(jsState, controllerOptions),
256 .withContext(
std::move(resultConsumer))
258 [callbacksHandle](
auto &resultConsumer) {
259 resultConsumer(callbacksHandle);
262 [](
const QOhosCallbackInfo &cbInfo,
auto &resultConsumer) {
263 QtOhos::logJsCallbackError(cbInfo,
"ShareController.show()");
264 resultConsumer(
nullptr);
268template<
typename ...Ts>
269QOhosConsumer<Ts...> makeAsyncConsumer(
270 QOhosConsumer<Ts...> baseConsumer, QOhosConsumer<std::function<
void()>> asyncExecutor)
272 auto sharedBaseConsumer = QtOhos::moveToSharedPtr(std::move(baseConsumer));
273 return [sharedBaseConsumer, asyncExecutor = std::move(asyncExecutor)](
const Ts &...args) {
275 [sharedBaseConsumer, args...]()
mutable {
276 (*sharedBaseConsumer)(
std::move(args)...);
284 QWindow *optInstanceMainWindow,
const std::vector<SharedRecord> &recordsToShare,
286 QOhosConsumer<ShareOperationResult> shareCompletedCallback)
288 auto optMainWindowInstanceObjectRef =
289 optInstanceMainWindow !=
nullptr
290 ?
std::make_optional(QtOhos::QObjectThreadSafeRef(optInstanceMainWindow))
293 auto panelClosedJsCallback = makeAsyncConsumer(
294 std::move(panelClosedCallback), &QtOhos::invokeInQtThread);
295 auto shareCompletedJsCallback = makeAsyncConsumer(
296 std::move(shareCompletedCallback), &QtOhos::invokeInQtThread);
298 return QOhosJsThreadGateway::evalWithPromise<std::shared_ptr<
void>>(
299 [&](QOhosJsState &jsState, QOhosTaskPromise<std::shared_ptr<
void>> evalPromise) {
300 auto optUiAbility = optMainWindowInstanceObjectRef.has_value()
301 ? jsState.tryGetQAbilityByQWindow(optMainWindowInstanceObjectRef.value())
302 : jsState.defaultQAbility();
303 if (!optUiAbility.has_value()) {
304 qOhosPrintfWarning(
"%s: no UIAbility available to share data with ShareKit", Q_FUNC_INFO);
305 evalPromise(
nullptr);
310 jsState, optUiAbility.value(), recordsToShare, controllerOptions, std::move(panelClosedJsCallback),
311 std::move(shareCompletedJsCallback), std::move(evalPromise));
std::shared_ptr< void > shareData(QWindow *optInstanceMainWindow, const std::vector< SharedRecord > &recordsToShare, ControllerOptions controllerOptions, std::function< void()> panelClosedCallback, QOhosConsumer< ShareOperationResult > shareCompletedCallback)