1 /*
2  * Copyright (C) 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 #include "core/common/ai/ai_write_adapter.h"
17 
18 #include "array_wrapper.h"
19 #include "bool_wrapper.h"
20 #include "int_wrapper.h"
21 #include "want.h"
22 #include "want_params.h"
23 #include "core/components_ng/layout/layout_property.h"
24 #include "core/components_ng/pattern/text/span/span_string.h"
25 #include "core/components_ng/pattern/ui_extension/session_wrapper.h"
26 #include "core/components_ng/pattern/ui_extension/session_wrapper_factory.h"
27 #include "core/components_ng/pattern/ui_extension/ui_extension_pattern.h"
28 #include "core/components_ng/pattern/ui_extension/modal_ui_extension_proxy_impl.h"
29 
30 namespace OHOS::Ace {
31 const std::pair<std::string, std::string> UI_ENTENSION_TYPE = {"ability.want.params.uiExtensionType", "sys/commonUI"};
32 const std::wstring BOUNDARY_SYMBOLS = L",.?,。?!";
33 const std::string API_VERSION = "apiVersion";
34 const std::string RESULT_BUFFER = "resultBuffer";
35 const std::string SHEET_DISMISS = "sheetDismiss";
36 const std::string PROCESS_ID = "processId";
37 const std::string MAX_CONTENT_LENGTH = "maxContentLength";
38 const std::string FIRST_HANDLE_RECT = "firstHandleRect";
39 const std::string SECOND_HANDLE_RECT = "secondHandleRect";
40 const std::string IS_AI_SUPPORT_METADATA = "isAiWritingSupport";
41 const std::string SELECT_CONTENT_LENGTH = "selectContentLength";
42 const std::string REQUEST_LONG_CONTENT = "requestLongContent";
43 const std::string LONG_SENTENCE_BUFFER = "longSentenceBuffer";
44 const std::string LONG_SELECT_START = "longSelectStart";
45 const std::string LONG_SELECT_END = "longSelectEnd";
46 const std::string KEY_PACKAGE_NAME = "keyPackageApp";
47 const std::string START_COMPONONT_TYPE = "startComponentType";
48 
IsSentenceBoundary(const wchar_t value)49 bool AIWriteAdapter::IsSentenceBoundary(const wchar_t value)
50 {
51     for (wchar_t item: BOUNDARY_SYMBOLS) {
52         if (value == item) {
53             return true;
54         }
55     }
56     return false;
57 }
58 
GetSelectLengthOnlyText(const std::wstring & content)59 uint32_t AIWriteAdapter::GetSelectLengthOnlyText(const std::wstring& content)
60 {
61     uint32_t length = 0;
62     for (uint32_t i = 0; i < content.length(); i++) {
63         if (content[i] != L' ' && content[i] != L'\n') {
64             length++;
65         }
66     }
67     return length;
68 }
69 
CloseModalUIExtension()70 void AIWriteAdapter::CloseModalUIExtension()
71 {
72     TAG_LOGI(AceLogTag::ACE_RICH_TEXT, "CloseModalUIExtension.");
73     auto context = pipelineContext_.Upgrade();
74     CHECK_NULL_VOID(context);
75     auto overlayManager = context->GetOverlayManager();
76     CHECK_NULL_VOID(overlayManager);
77     overlayManager->CloseModalUIExtension(sessionId_);
78     SetAIWrite(false);
79 }
80 
ShowModalUIExtension(const AIWriteInfo & info,std::function<void (std::vector<uint8_t> &)> resultCallback)81 void AIWriteAdapter::ShowModalUIExtension(const AIWriteInfo& info,
82     std::function<void(std::vector<uint8_t>&)> resultCallback)
83 {
84     TAG_LOGI(AceLogTag::ACE_RICH_TEXT, "ShowModalUIExtension.");
85     AAFwk::Want want;
86     SetWantParams(info, want);
87     Ace::ModalUIExtensionCallbacks callbacks;
88     BindModalUIExtensionCallback(callbacks, resultCallback);
89 
90     auto context = pipelineContext_.Upgrade();
91     CHECK_NULL_VOID(context);
92     auto overlayManager = context->GetOverlayManager();
93     CHECK_NULL_VOID(overlayManager);
94     Ace::ModalUIExtensionConfig config;
95     sessionId_ = overlayManager->CreateModalUIExtension(want, callbacks, config);
96     aiWriteInfo_ = info;
97 }
98 
SetWantParams(const AIWriteInfo & info,AAFwk::Want & want)99 void AIWriteAdapter::SetWantParams(const AIWriteInfo& info, AAFwk::Want& want)
100 {
101     auto apiVersion = AceApplicationInfo::GetInstance().GetApiTargetVersion();
102     want.SetElementName(bundleName_, abilityName_);
103     want.SetParam(UI_ENTENSION_TYPE.first, UI_ENTENSION_TYPE.second);
104     want.SetParam(API_VERSION, static_cast<int>(apiVersion));
105     want.SetParam(PROCESS_ID, getpid());
106     want.SetParam(MAX_CONTENT_LENGTH, info.maxLength);
107     want.SetParam(SELECT_CONTENT_LENGTH, info.selectLength);
108     want.SetParam(FIRST_HANDLE_RECT, info.firstHandle);
109     want.SetParam(SECOND_HANDLE_RECT, info.secondHandle);
110     want.SetParam(KEY_PACKAGE_NAME, AceApplicationInfo::GetInstance().GetPackageName());
111     want.SetParam(START_COMPONONT_TYPE, info.componentType);
112 }
113 
BindModalUIExtensionCallback(Ace::ModalUIExtensionCallbacks & callbacks,std::function<void (std::vector<uint8_t> &)> resultCallback)114 void AIWriteAdapter::BindModalUIExtensionCallback(
115     Ace::ModalUIExtensionCallbacks& callbacks, std::function<void(std::vector<uint8_t>&)> resultCallback)
116 {
117     callbacks.onResult = [](int32_t code, const AAFwk::Want& want) {
118         TAG_LOGD(AceLogTag::ACE_UIEXTENSIONCOMPONENT, "UIExtension onResult, code: %{public}d", code);
119     };
120     callbacks.onDestroy = [weak = WeakClaim(this)]() {
121         TAG_LOGD(AceLogTag::ACE_UIEXTENSIONCOMPONENT, "UIExtension onDestroy.");
122         auto aiWriteAdapter = weak.Upgrade();
123         CHECK_NULL_VOID(aiWriteAdapter);
124         aiWriteAdapter->CloseModalUIExtension();
125     };
126     callbacks.onError = [weak = WeakClaim(this)](int32_t code, const std::string& name, const std::string& message) {
127         TAG_LOGE(AceLogTag::ACE_UIEXTENSIONCOMPONENT,
128             "UIExtension onError, code: %{public}d, name: %{public}s, message: %{public}s",
129             code, name.c_str(), message.c_str());
130         auto aiWriteAdapter = weak.Upgrade();
131         CHECK_NULL_VOID(aiWriteAdapter);
132         aiWriteAdapter->CloseModalUIExtension();
133     };
134     callbacks.onRelease = [](int32_t code) {
135         TAG_LOGD(AceLogTag::ACE_UIEXTENSIONCOMPONENT, "UIExtension onRelease, code: %{public}d", code);
136     };
137     callbacks.onRemoteReady = [weak = WeakClaim(this)](const std::shared_ptr<Ace::ModalUIExtensionProxy>& proxy) {
138         TAG_LOGD(AceLogTag::ACE_UIEXTENSIONCOMPONENT, "UIExtension onRemoteReady.");
139         auto aiWriteAdapter = weak.Upgrade();
140         CHECK_NULL_VOID(aiWriteAdapter);
141         aiWriteAdapter->SetModalUIExtensionProxy(proxy);
142     };
143     callbacks.onReceive = [weak = WeakClaim(this), cb = std::move(resultCallback)]
144         (const AAFwk::WantParams& wantParams) {
145         auto aiWriteAdapter = weak.Upgrade();
146         CHECK_NULL_VOID(aiWriteAdapter);
147         auto isSheetClose = false;
148         auto isRequest = false;
149         auto result = aiWriteAdapter->GetBufferParam(RESULT_BUFFER, wantParams);
150         isSheetClose = aiWriteAdapter->GetBoolParam(SHEET_DISMISS, wantParams);
151         isRequest = aiWriteAdapter->GetBoolParam(REQUEST_LONG_CONTENT, wantParams);
152         if (isRequest) {
153             aiWriteAdapter->SendData();
154             return;
155         }
156         if (cb && !result.empty()) {
157             cb(result);
158             return;
159         }
160         if (isSheetClose) {
161             aiWriteAdapter->CloseModalUIExtension();
162         }
163     };
164 }
165 
SendData()166 void AIWriteAdapter::SendData()
167 {
168     auto proxy = GetModalUIExtensionProxy();
169     AAFwk::WantParams wantParams;
170     SetArrayParam(wantParams, LONG_SENTENCE_BUFFER, aiWriteInfo_.sentenceBuffer);
171     wantParams.SetParam(LONG_SELECT_START, AAFwk::Integer::Box(aiWriteInfo_.start));
172     wantParams.SetParam(LONG_SELECT_END, AAFwk::Integer::Box(aiWriteInfo_.end));
173     proxy->SendData(wantParams);
174 }
175 
SetArrayParam(AAFwk::WantParams & wantParams,const std::string & key,const std::vector<uint8_t> & value)176 void AIWriteAdapter::SetArrayParam(
177     AAFwk::WantParams& wantParams, const std::string& key, const std::vector<uint8_t>& value)
178 {
179     std::vector<int> valueVec(value.size());
180     std::transform(value.begin(), value.end(), valueVec.begin(),
181         [](uint8_t x) { return static_cast<int>(x); });
182     size_t size = valueVec.size();
183     sptr<AAFwk::IArray> ao = new (std::nothrow) AAFwk::Array(size, AAFwk::g_IID_IInteger);
184     if (ao == nullptr) {
185         return;
186     }
187     for (size_t i = 0; i < size; i++) {
188         ao->Set(i, AAFwk::Integer::Box(value[i]));
189     }
190     wantParams.SetParam(key, ao);
191 }
192 
GetBufferParam(const std::string & key,const AAFwk::WantParams & wantParams)193 std::vector<uint8_t> AIWriteAdapter::GetBufferParam(const std::string& key, const AAFwk::WantParams& wantParams)
194 {
195     std::vector<uint8_t> array;
196     auto value = wantParams.GetParam(key);
197     AAFwk::IArray *ao = AAFwk::IArray::Query(value);
198     if (ao != nullptr && AAFwk::Array::IsIntegerArray(ao)) {
199         auto func = [&](AAFwk::IInterface *object) {
200             CHECK_NULL_VOID(object);
201             AAFwk::IInteger *value = AAFwk::IInteger::Query(object);
202             CHECK_NULL_VOID(value);
203             array.emplace_back(AAFwk::Integer::Unbox(value));
204         };
205         AAFwk::Array::ForEach(ao, func);
206     }
207     return array;
208 }
209 
GetBoolParam(const std::string & key,const AAFwk::WantParams & wantParams)210 bool AIWriteAdapter::GetBoolParam(const std::string& key, const AAFwk::WantParams& wantParams)
211 {
212     auto value = wantParams.GetParam(key);
213     AAFwk::IBoolean *bo = AAFwk::IBoolean::Query(value);
214     if (bo != nullptr) {
215         return AAFwk::Boolean::Unbox(bo);
216     }
217     return false;
218 }
219 }