1 /* 2 * Copyright (c) 2025 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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_WEB_DATA_DETECTOR_ADAPTER_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_WEB_DATA_DETECTOR_ADAPTER_H 18 19 #include <list> 20 #include <unordered_map> 21 #include <mutex> 22 23 #include "interfaces/inner_api/ace/ai/data_detector_interface.h" 24 25 #include "base/memory/ace_type.h" 26 #include "base/memory/referenced.h" 27 #include "core/components/web/web_property.h" 28 29 namespace OHOS::Ace::NG { 30 31 struct NodeData { 32 std::string path; 33 std::string text; 34 }; 35 36 struct EntityMatch { 37 size_t start; // u16 38 size_t end; // u16 39 std::string entityType; 40 std::string clean; 41 std::map<std::string, std::string> params; 42 }; 43 44 struct WebDataDetectorConfig { 45 bool enable; 46 bool enablePreview; 47 std::string types; 48 std::string color; 49 std::string textDecorationStyle; 50 }; 51 52 struct AIMenuInfo { 53 std::string entityType; 54 std::string content; 55 std::string outerHTML; 56 RectF rect; // refer to web 57 }; 58 59 const size_t MAX_CACHE_SIZE = 100; 60 const size_t MAX_SELECTED_TEXT_SIZE = 255; 61 62 using DataDetectorResult = std::vector<EntityMatch>; // for single node 63 64 enum class AISupportStatus { 65 UNKNOWN = 0, 66 UNSUPPORTED, 67 SUPPORTED, 68 }; 69 70 struct DataDetectorRequestData { 71 std::string requestId; 72 std::vector<NodeData> nodes; 73 std::vector<size_t> detectIds; 74 std::vector<std::pair<size_t, size_t> > detectOffsets; 75 std::vector<DataDetectorResult> matches; 76 }; 77 78 template <typename KeyType, typename ValueType> 79 class WebDataDetectorCache : public AceType { 80 DECLARE_ACE_TYPE(WebDataDetectorCache, AceType); 81 public: WebDataDetectorCache(size_t maxSize)82 explicit WebDataDetectorCache(size_t maxSize) : maxSize_(maxSize) {} 83 Get(const KeyType & key,ValueType & outValue)84 bool Get(const KeyType& key, ValueType& outValue) 85 { 86 std::lock_guard<std::mutex> lock(mutex_); 87 auto it = cacheMap_.find(key); 88 if (it == cacheMap_.end()) { 89 return false; 90 } 91 92 accessQueue_.splice(accessQueue_.begin(), accessQueue_, it->second.queueIt); 93 outValue = it->second.value; 94 return true; 95 } 96 Put(const KeyType & key,const ValueType & value)97 void Put(const KeyType& key, const ValueType& value) 98 { 99 std::lock_guard<std::mutex> lock(mutex_); 100 101 auto it = cacheMap_.find(key); 102 if (it != cacheMap_.end()) { 103 it->second.value = value; 104 accessQueue_.splice(accessQueue_.begin(), accessQueue_, it->second.queueIt); 105 return; 106 } 107 108 accessQueue_.push_front(key); 109 cacheMap_[key] = {value, accessQueue_.begin()}; 110 111 if (cacheMap_.size() > maxSize_) { 112 cacheMap_.erase(accessQueue_.back()); 113 accessQueue_.pop_back(); 114 } 115 } 116 117 private: 118 struct CacheNode { 119 ValueType value; 120 typename std::list<KeyType>::iterator queueIt; 121 }; 122 123 std::unordered_map<KeyType, CacheNode> cacheMap_; 124 std::list<KeyType> accessQueue_; 125 size_t maxSize_; 126 std::mutex mutex_; 127 }; 128 129 class WebDataDetectorAdapter : public AceType { 130 DECLARE_ACE_TYPE(WebDataDetectorAdapter, AceType); 131 132 public: 133 explicit WebDataDetectorAdapter(const WeakPtr<Pattern>& pattern, size_t cacheSize = 100); 134 ~WebDataDetectorAdapter() override = default; 135 SetPattern(const WeakPtr<Pattern> & pattern)136 void SetPattern(const WeakPtr<Pattern>& pattern) 137 { 138 pattern_ = pattern; 139 } 140 GetDataDetectorEnable()141 bool GetDataDetectorEnable() 142 { 143 return config_.enable; 144 } 145 GetDataDetectorEnablePrewiew()146 bool GetDataDetectorEnablePrewiew() 147 { 148 return config_.enablePreview; 149 } 150 151 void SetDataDetectorEnable(bool enable); 152 void SetDataDetectorConfig(const TextDetectConfig& config); 153 void Init(); 154 void InitJSProxy(); 155 void ReleaseJSProxy(); 156 void SetNWebConfig(); 157 158 void ProcessRequest(const std::string& jsonStr); 159 160 std::string PrepareDetectText(const std::string& requestId); 161 void SendRequestToAI(const std::string& requestId); 162 void ParseAIResultByType(std::shared_ptr<DataDetectorRequestData>& requestContext, const std::string& detectType, 163 const std::unique_ptr<JsonValue>& jsonValue); 164 void HandleResultFromAI(const std::string& requestId, const TextDataDetectResult& result); 165 std::string GetResultJsonString(const std::string& requestId); 166 void SendResultToJS(const std::string& resultStr); 167 168 std::map<std::string, std::string> AttrsToParams(const std::unique_ptr<JsonValue>& jsonValue); 169 170 static std::map<std::string, std::string> ParseExtraParams( 171 const std::string& detectType, const std::unique_ptr<JsonValue>& item); 172 static int32_t MatchInOffsets(EntityMatch& match, const std::vector<std::pair<size_t, size_t> >& detectOffsets); 173 174 void ProcessClick(const std::string& jsonStr); 175 void InitAIMenu(); 176 void GetAIMenu(); 177 bool IsAISupported(); 178 RectF CalcAIMenuRect(double left, double top, double right, double bottom); 179 bool GetAIMenuOptions( 180 const AIMenuInfo& info, std::vector<std::pair<std::string, std::function<void()>>>& menuOptions); 181 bool ShowAIMenu(const AIMenuInfo& info); 182 void OnClickAIMenuOption(const AIMenuInfo& info, const std::pair<std::string, FuncVariant>& menuOption); 183 void OnClickMenuItem(const std::string& action, const AIMenuInfo& info); 184 185 void OnClickAISelectMenuOption(TextDataDetectType type, const std::string& content); 186 void DetectSelectedText(const std::string& text); 187 static DataDetectorResult ParseAIResultJson(std::unique_ptr<JsonValue>& jsonValue); 188 void OnDetectSelectedTextDone(const TextDataDetectResult& result); 189 void UpdateAISelectMenu(const std::string& entityType, const std::string& content); 190 191 static std::string ReplaceARGBToRGBA(const std::string& text); 192 static std::string UrlDecode(const std::string& str); 193 bool SetPreviewMenuLink(const std::string& link); 194 bool GetPreviewMenuBuilder(std::function<void()>& menuBuilder, std::function<void()>& previewBuilder); 195 std::string GetLinkOuterHTML(const std::string& entityType, const std::string& content); 196 std::function<void()> GetPreviewMenuOptionCallback(TextDataDetectType type, const std::string& content); 197 RefPtr<FrameNode> GetPreviewMenuNode(const AIMenuInfo& info); 198 199 void SetPreviewMenuAttr(TextDataDetectType type = TextDataDetectType::INVALID, const std::string& content = "", 200 const std::map<std::string, std::string>& params = {}); 201 202 static TextDataDetectType ConvertTypeFromString(const std::string& type); 203 204 void CloseAIMenu(); 205 void CloseOtherMenu(); 206 207 void AIPostTask(const std::function<void()>& task, TaskExecutor::TaskType taskType, const std::string& name, 208 uint32_t delay = 0); 209 bool SetRequestContext(const std::string& requestId, DataDetectorRequestData&& requestData); 210 bool RemoveRequestContext(const std::string& requestId); 211 void ResetContextMap(); 212 std::shared_ptr<DataDetectorRequestData> GetRequestContext(const std::string& requestId); 213 214 private: 215 216 WeakPtr<Pattern> pattern_; 217 218 // properties 219 WebDataDetectorConfig config_ { false, false, "", "", "" }; 220 WebDataDetectorConfig newConfig_ { false, false, "", "", "" }; 221 bool hasInit_ = false; 222 223 bool initDataDetectorProxy_ = false; 224 225 // preview menu 226 TextDataDetectType previewMenuType_ = TextDataDetectType::INVALID; 227 std::string previewMenuContent_ = ""; 228 std::map<std::string, std::string> previewMenuExtraParams_; 229 std::unordered_set<std::string> extraParamKeys_; 230 231 // cache 232 RefPtr<WebDataDetectorCache<std::string, DataDetectorResult>> resultCache_ = nullptr; 233 234 // request context 235 std::mutex contextMutex_; 236 std::unordered_map<std::string, std::shared_ptr<DataDetectorRequestData> > contextMap_; 237 238 // ai menu 239 TextDataDetectResult textDetectResult_; 240 bool initAIMenu_ = false; 241 AISupportStatus aiSupportStatus_ = AISupportStatus::UNKNOWN; 242 }; 243 244 } // namespace OHOS::Ace 245 246 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_WEB_DATA_DETECTOR_ADAPTER_H