From 7a2af2646c8d9803aa0483352eabaf99afd47079 Mon Sep 17 00:00:00 2001 From: admin_gitea Date: Wed, 19 Aug 2026 16:15:52 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E5=9C=A8=E7=BA=BF=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E3=80=81=E6=8F=92=E4=BB=B6=E8=BF=90=E8=A1=8C=E6=97=B6?= =?UTF-8?q?=E4=B8=8E=E5=AE=89=E8=A3=85=E5=8D=B8=E8=BD=BD=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/data/tool-ui/age_calculator.dat | Bin 1417 -> 1417 bytes assets/data/tool-ui/ai_latest_news.dat | Bin 1577 -> 1577 bytes assets/data/tool-ui/ai_translation.dat | Bin 2137 -> 1497 bytes assets/data/tool-ui/archive_tool.dat | Bin 1735 -> 1735 bytes assets/data/tool-ui/area_converter.dat | Bin 2073 -> 2073 bytes assets/data/tool-ui/ascii_art.dat | Bin 1972 -> 1972 bytes assets/data/tool-ui/average_calculator.dat | Bin 2061 -> 2061 bytes assets/data/tool-ui/baidu_hot.dat | Bin 1380 -> 1380 bytes assets/data/tool-ui/base64_codec.dat | Bin 2167 -> 2167 bytes assets/data/tool-ui/batch_rename_preview.dat | Bin 2143 -> 2143 bytes assets/data/tool-ui/bili_hot.dat | Bin 1411 -> 1411 bytes assets/data/tool-ui/blank_line_cleaner.dat | Bin 2077 -> 2077 bytes assets/data/tool-ui/bmi_calculator.dat | Bin 2041 -> 2041 bytes assets/data/tool-ui/calculator_tool.dat | Bin 2058 -> 2058 bytes assets/data/tool-ui/car_info.dat | Bin 1411 -> 1411 bytes assets/data/tool-ui/case_converter.dat | Bin 2169 -> 2169 bytes assets/data/tool-ui/cctv_news.dat | Bin 1380 -> 1380 bytes assets/data/tool-ui/charset_lookup.dat | Bin 2153 -> 2153 bytes assets/data/tool-ui/chinese_converter.dat | Bin 2140 -> 2140 bytes .../data/tool-ui/cidr_subnet_calculator.dat | Bin 2193 -> 2209 bytes assets/data/tool-ui/city_route_query.dat | Bin 1595 -> 1563 bytes .../data/tool-ui/color_contrast_checker.dat | Bin 2033 -> 2033 bytes assets/data/tool-ui/color_picker.dat | Bin 1975 -> 1975 bytes assets/data/tool-ui/column_extractor.dat | Bin 2187 -> 2187 bytes .../data/tool-ui/combination_calculator.dat | Bin 2049 -> 2049 bytes .../tool-ui/compound_interest_calculator.dat | Bin 2023 -> 2023 bytes assets/data/tool-ui/compression_codec.dat | Bin 2236 -> 2236 bytes assets/data/tool-ui/cron_helper.dat | Bin 2150 -> 2150 bytes assets/data/tool-ui/csv_json_converter.dat | Bin 2141 -> 2141 bytes assets/data/tool-ui/csv_tsv_converter.dat | Bin 2124 -> 2124 bytes assets/data/tool-ui/data_size_converter.dat | Bin 2062 -> 2062 bytes .../tool-ui/date_difference_calculator.dat | Bin 1461 -> 1461 bytes assets/data/tool-ui/delimiter_converter.dat | Bin 2190 -> 2190 bytes .../data/tool-ui/dev_environment_config.dat | Bin 2273 -> 2273 bytes assets/data/tool-ui/discount_calculator.dat | Bin 2046 -> 2046 bytes assets/data/tool-ui/dns_query.dat | Bin 2132 -> 2148 bytes assets/data/tool-ui/dns_record_lookup.dat | Bin 2140 -> 2156 bytes assets/data/tool-ui/domain_extractor.dat | Bin 2171 -> 2187 bytes assets/data/tool-ui/domain_price.dat | Bin 2231 -> 2247 bytes assets/data/tool-ui/duplicate_detector.dat | Bin 2157 -> 2157 bytes assets/data/tool-ui/earthquake_info.dat | Bin 1418 -> 1418 bytes assets/data/tool-ui/extension_extractor.dat | Bin 2142 -> 2142 bytes assets/data/tool-ui/extension_statistics.dat | Bin 2111 -> 2111 bytes assets/data/tool-ui/external-tool-host.dat | Bin 1405 -> 1405 bytes assets/data/tool-ui/file_manifest_builder.dat | Bin 2176 -> 2176 bytes assets/data/tool-ui/filename_formatter.dat | Bin 2157 -> 2157 bytes assets/data/tool-ui/football_news.dat | Bin 1400 -> 1400 bytes .../data/tool-ui/form_urlencoded_builder.dat | Bin 2210 -> 2210 bytes assets/data/tool-ui/gcd_lcm_calculator.dat | Bin 2093 -> 2093 bytes assets/data/tool-ui/gold_price.dat | Bin 1429 -> 1429 bytes assets/data/tool-ui/hardware.dat | Bin 1587 -> 1587 bytes assets/data/tool-ui/hash_generator.dat | Bin 2153 -> 2153 bytes assets/data/tool-ui/hash_manifest_builder.dat | Bin 2176 -> 2176 bytes assets/data/tool-ui/hash_manifest_verify.dat | Bin 2159 -> 2159 bytes assets/data/tool-ui/history_today.dat | Bin 1400 -> 1480 bytes assets/data/tool-ui/hmac_generator.dat | Bin 2121 -> 2121 bytes assets/data/tool-ui/hotboard.dat | Bin 1459 -> 1459 bytes assets/data/tool-ui/html_entity.dat | Bin 2118 -> 2118 bytes assets/data/tool-ui/html_js_playground.dat | Bin 2269 -> 2269 bytes assets/data/tool-ui/html_minifier.dat | Bin 2184 -> 2184 bytes assets/data/tool-ui/html_text_extractor.dat | Bin 2158 -> 2158 bytes assets/data/tool-ui/http_diagnostic.dat | Bin 2186 -> 2202 bytes assets/data/tool-ui/http_status_lookup.dat | Bin 2173 -> 2189 bytes .../data/tool-ui/image_metadata_inspector.dat | Bin 1859 -> 1859 bytes assets/data/tool-ui/image_processor.dat | Bin 1738 -> 1738 bytes .../data/tool-ui/indexed_rename_preview.dat | Bin 2177 -> 2177 bytes assets/data/tool-ui/ip_info.dat | Bin 2130 -> 2146 bytes assets/data/tool-ui/ip_lookup.dat | Bin 2116 -> 2132 bytes assets/data/tool-ui/js_obfuscator.dat | Bin 2136 -> 2136 bytes assets/data/tool-ui/json_formatter.dat | Bin 2153 -> 2153 bytes assets/data/tool-ui/json_path_helper.dat | Bin 2203 -> 2203 bytes assets/data/tool-ui/jwt_decoder.dat | Bin 2134 -> 2134 bytes assets/data/tool-ui/key_value_converter.dat | Bin 2190 -> 2190 bytes assets/data/tool-ui/keyword_counter.dat | Bin 2122 -> 2122 bytes assets/data/tool-ui/length_converter.dat | Bin 2091 -> 2091 bytes .../data/tool-ui/line_column_transformer.dat | Bin 2162 -> 2162 bytes assets/data/tool-ui/line_length_analyzer.dat | Bin 2159 -> 2159 bytes assets/data/tool-ui/line_pair_zipper.dat | Bin 2155 -> 2155 bytes assets/data/tool-ui/list_chunker.dat | Bin 2119 -> 2119 bytes assets/data/tool-ui/list_difference.dat | Bin 2122 -> 2122 bytes assets/data/tool-ui/list_group_statistics.dat | Bin 2160 -> 2160 bytes assets/data/tool-ui/list_intersection.dat | Bin 2124 -> 2124 bytes assets/data/tool-ui/list_sampler.dat | Bin 2119 -> 2119 bytes assets/data/tool-ui/list_union.dat | Bin 2101 -> 2101 bytes assets/data/tool-ui/loan_emi_calculator.dat | Bin 2094 -> 2094 bytes assets/data/tool-ui/magic_number_lookup.dat | Bin 2158 -> 2158 bytes assets/data/tool-ui/manifest_deduplicator.dat | Bin 2128 -> 2128 bytes assets/data/tool-ui/manifest_sorter.dat | Bin 2122 -> 2122 bytes .../data/tool-ui/manifest_template_export.dat | Bin 2179 -> 2179 bytes assets/data/tool-ui/markdown_list_cleaner.dat | Bin 2144 -> 2144 bytes assets/data/tool-ui/markdown_preview.dat | Bin 2283 -> 2283 bytes .../tool-ui/markdown_table_normalizer.dat | Bin 2212 -> 2212 bytes assets/data/tool-ui/media_player.dat | Bin 1703 -> 1703 bytes assets/data/tool-ui/median_calculator.dat | Bin 2060 -> 2060 bytes assets/data/tool-ui/mime_lookup.dat | Bin 2118 -> 2134 bytes assets/data/tool-ui/movie_box_office.dat | Bin 1403 -> 1483 bytes assets/data/tool-ui/music.dat | Bin 2272 -> 2288 bytes assets/data/tool-ui/nex_ace_optimize.dat | Bin 1307 -> 1307 bytes assets/data/tool-ui/nex_audio_eq.dat | Bin 1287 -> 1287 bytes assets/data/tool-ui/nex_crosshair.dat | Bin 1288 -> 1288 bytes assets/data/tool-ui/nex_delta_force.dat | Bin 1306 -> 1306 bytes assets/data/tool-ui/nex_disk_health.dat | Bin 1306 -> 1306 bytes assets/data/tool-ui/nex_display_filter.dat | Bin 1309 -> 1309 bytes assets/data/tool-ui/nex_epic_free.dat | Bin 1288 -> 1288 bytes .../tool-ui/nex_event_log_diagnostics.dat | Bin 1332 -> 1332 bytes .../data/tool-ui/nex_file_lock_analysis.dat | Bin 1329 -> 1329 bytes assets/data/tool-ui/nex_gpu_rename.dat | Bin 1289 -> 1289 bytes assets/data/tool-ui/nex_installed_apps.dat | Bin 1309 -> 1309 bytes assets/data/tool-ui/nex_memory_cleanup.dat | Bin 1309 -> 1309 bytes assets/data/tool-ui/nex_memory_limit.dat | Bin 1307 -> 1307 bytes assets/data/tool-ui/nex_mood.dat | Bin 1267 -> 1267 bytes assets/data/tool-ui/nex_network_optimizer.dat | Bin 1328 -> 1328 bytes assets/data/tool-ui/nex_nvidia_driver.dat | Bin 1308 -> 1308 bytes assets/data/tool-ui/nex_optional_features.dat | Bin 1328 -> 1328 bytes assets/data/tool-ui/nex_other_gun_codes.dat | Bin 1310 -> 1310 bytes assets/data/tool-ui/nex_overlay.dat | Bin 1286 -> 1286 bytes .../data/tool-ui/nex_peripheral_optimize.dat | Bin 1330 -> 1330 bytes assets/data/tool-ui/nex_power_management.dat | Bin 1327 -> 1327 bytes .../data/tool-ui/nex_resolution_converter.dat | Bin 1331 -> 1331 bytes assets/data/tool-ui/nex_restore_points.dat | Bin 1309 -> 1309 bytes assets/data/tool-ui/nex_shader_cache.dat | Bin 1307 -> 1307 bytes assets/data/tool-ui/nex_startup_manager.dat | Bin 1310 -> 1310 bytes assets/data/tool-ui/nex_storage_clean.dat | Bin 1308 -> 1308 bytes assets/data/tool-ui/nex_system_optimizer.dat | Bin 1327 -> 1327 bytes assets/data/tool-ui/nex_third_party_tools.dat | Bin 1328 -> 1328 bytes assets/data/tool-ui/nex_tray_island.dat | Bin 1306 -> 1306 bytes assets/data/tool-ui/nex_vertical_overlay.dat | Bin 1327 -> 1327 bytes assets/data/tool-ui/nex_windows_repair.dat | Bin 1309 -> 1309 bytes assets/data/tool-ui/nex_windows_update.dat | Bin 1309 -> 1309 bytes assets/data/tool-ui/number_base.dat | Bin 2230 -> 2230 bytes assets/data/tool-ui/number_base_converter.dat | Bin 2128 -> 2128 bytes assets/data/tool-ui/oil_price.dat | Bin 1540 -> 1556 bytes assets/data/tool-ui/online_tools.dat | Bin 0 -> 2327 bytes assets/data/tool-ui/optimization.dat | Bin 1559 -> 1559 bytes assets/data/tool-ui/password_generator.dat | Bin 2109 -> 2109 bytes assets/data/tool-ui/path_breakdown.dat | Bin 2153 -> 2153 bytes assets/data/tool-ui/path_normalizer.dat | Bin 2154 -> 2154 bytes assets/data/tool-ui/pc_benchmark.dat | Bin 1383 -> 1383 bytes .../data/tool-ui/pear_ai_dish_recognition.dat | Bin 0 -> 1491 bytes .../data/tool-ui/pear_ai_image_describe.dat | Bin 0 -> 1505 bytes .../data/tool-ui/pear_ai_image_detection.dat | Bin 0 -> 1506 bytes assets/data/tool-ui/pear_ai_text_safety.dat | Bin 0 -> 1486 bytes assets/data/tool-ui/pear_answers_book.dat | Bin 0 -> 1468 bytes assets/data/tool-ui/pear_audio_transcript.dat | Bin 0 -> 1520 bytes assets/data/tool-ui/pear_award.dat | Bin 0 -> 1493 bytes assets/data/tool-ui/pear_baidu_place.dat | Bin 0 -> 1483 bytes assets/data/tool-ui/pear_blood_type.dat | Bin 0 -> 1514 bytes assets/data/tool-ui/pear_brainteaser.dat | Bin 0 -> 1483 bytes assets/data/tool-ui/pear_car_price.dat | Bin 0 -> 1529 bytes assets/data/tool-ui/pear_certificate.dat | Bin 0 -> 1515 bytes .../data/tool-ui/pear_chinese_conversion.dat | Bin 0 -> 1522 bytes assets/data/tool-ui/pear_classic_joke.dat | Bin 0 -> 1468 bytes assets/data/tool-ui/pear_college.dat | Bin 0 -> 1463 bytes assets/data/tool-ui/pear_constellation.dat | Bin 0 -> 1437 bytes assets/data/tool-ui/pear_cookbook.dat | Bin 0 -> 1496 bytes assets/data/tool-ui/pear_countdown.dat | Bin 0 -> 1481 bytes .../data/tool-ui/pear_country_population.dat | Bin 0 -> 1506 bytes assets/data/tool-ui/pear_couplet.dat | Bin 0 -> 1447 bytes assets/data/tool-ui/pear_daily_60_image.dat | Bin 0 -> 1486 bytes assets/data/tool-ui/pear_dujitang.dat | Bin 0 -> 1464 bytes assets/data/tool-ui/pear_embeddings.dat | Bin 0 -> 1498 bytes assets/data/tool-ui/pear_exchange_rate.dat | Bin 0 -> 1501 bytes assets/data/tool-ui/pear_funny_joke.dat | Bin 0 -> 1450 bytes assets/data/tool-ui/pear_gold_price.dat | Bin 0 -> 1466 bytes .../data/tool-ui/pear_historical_person.dat | Bin 0 -> 1521 bytes assets/data/tool-ui/pear_hitokoto.dat | Bin 0 -> 1432 bytes assets/data/tool-ui/pear_hot_60_image.dat | Bin 0 -> 1484 bytes assets/data/tool-ui/pear_icp.dat | Bin 0 -> 1443 bytes assets/data/tool-ui/pear_image_prompt.dat | Bin 0 -> 1612 bytes assets/data/tool-ui/pear_ip_details.dat | Bin 0 -> 1546 bytes assets/data/tool-ui/pear_keyword_guide.dat | Bin 0 -> 1485 bytes assets/data/tool-ui/pear_kfc.dat | Bin 0 -> 1491 bytes assets/data/tool-ui/pear_life_calculator.dat | Bin 0 -> 1519 bytes assets/data/tool-ui/pear_llm_reader.dat | Bin 0 -> 1498 bytes assets/data/tool-ui/pear_lottery.dat | Bin 0 -> 1463 bytes assets/data/tool-ui/pear_love_quote.dat | Bin 0 -> 1434 bytes assets/data/tool-ui/pear_love_reply.dat | Bin 0 -> 1450 bytes assets/data/tool-ui/pear_mean_search.dat | Bin 0 -> 1531 bytes assets/data/tool-ui/pear_movie_lines.dat | Bin 0 -> 1515 bytes assets/data/tool-ui/pear_ocr.dat | Bin 0 -> 1491 bytes assets/data/tool-ui/pear_poem.dat | Bin 0 -> 1492 bytes assets/data/tool-ui/pear_qq_level_image.dat | Bin 0 -> 1518 bytes assets/data/tool-ui/pear_question_search.dat | Bin 0 -> 1503 bytes assets/data/tool-ui/pear_quirky_dialogue.dat | Bin 0 -> 1471 bytes assets/data/tool-ui/pear_rainbow.dat | Bin 0 -> 1447 bytes assets/data/tool-ui/pear_random_song.dat | Bin 0 -> 1483 bytes .../data/tool-ui/pear_random_superpower.dat | Bin 0 -> 1521 bytes assets/data/tool-ui/pear_ruozhiba.dat | Bin 0 -> 1480 bytes assets/data/tool-ui/pear_science_news.dat | Bin 0 -> 1468 bytes assets/data/tool-ui/pear_sensitive_words.dat | Bin 0 -> 1551 bytes assets/data/tool-ui/pear_short_recovery.dat | Bin 0 -> 1470 bytes assets/data/tool-ui/pear_site_index.dat | Bin 0 -> 1546 bytes assets/data/tool-ui/pear_ssl.dat | Bin 0 -> 1523 bytes assets/data/tool-ui/pear_stock.dat | Bin 0 -> 1509 bytes assets/data/tool-ui/pear_surname_pun.dat | Bin 0 -> 1483 bytes assets/data/tool-ui/pear_synonym_antonym.dat | Bin 0 -> 1503 bytes assets/data/tool-ui/pear_text_tts.dat | Bin 0 -> 1496 bytes assets/data/tool-ui/pear_today_food.dat | Bin 0 -> 1434 bytes assets/data/tool-ui/pear_trademark.dat | Bin 0 -> 1529 bytes assets/data/tool-ui/pear_translation.dat | Bin 0 -> 1515 bytes assets/data/tool-ui/pear_website_info.dat | Bin 0 -> 1580 bytes assets/data/tool-ui/pear_world_60.dat | Bin 0 -> 1464 bytes assets/data/tool-ui/pear_world_population.dat | Bin 0 -> 1488 bytes assets/data/tool-ui/pear_xf_spark.dat | Bin 0 -> 1496 bytes assets/data/tool-ui/percentage_calculator.dat | Bin 2080 -> 2080 bytes .../tool-ui/percentage_change_calculator.dat | Bin 2119 -> 2119 bytes .../data/tool-ui/permutation_calculator.dat | Bin 2049 -> 2049 bytes assets/data/tool-ui/plugin-host.dat | Bin 1478 -> 1478 bytes assets/data/tool-ui/port_lookup.dat | Bin 2150 -> 2166 bytes assets/data/tool-ui/prefix_suffix_batch.dat | Bin 2158 -> 2158 bytes assets/data/tool-ui/profanity_check.dat | Bin 2154 -> 2154 bytes assets/data/tool-ui/punycode_codec.dat | Bin 2169 -> 2169 bytes assets/data/tool-ui/qq_avatar.dat | Bin 1412 -> 1412 bytes assets/data/tool-ui/qr_generator.dat | Bin 1703 -> 1703 bytes assets/data/tool-ui/qrcode_scanner.dat | Bin 1705 -> 1705 bytes assets/data/tool-ui/query_builder.dat | Bin 2168 -> 2168 bytes assets/data/tool-ui/random_cinema.dat | Bin 1752 -> 1752 bytes assets/data/tool-ui/random_generator.dat | Bin 2171 -> 2171 bytes assets/data/tool-ui/ratio_simplifier.dat | Bin 2075 -> 2075 bytes assets/data/tool-ui/rdap_domain_lookup.dat | Bin 2189 -> 2189 bytes assets/data/tool-ui/rdap_ip_lookup.dat | Bin 2169 -> 2185 bytes assets/data/tool-ui/regex_preset_lookup.dat | Bin 2174 -> 2174 bytes assets/data/tool-ui/regex_tool.dat | Bin 2133 -> 2133 bytes assets/data/tool-ui/safe_browser.dat | Bin 2199 -> 2199 bytes assets/data/tool-ui/sanguosha_skin.dat | Bin 1417 -> 1417 bytes assets/data/tool-ui/serial_terminal.dat | Bin 1546 -> 1546 bytes assets/data/tool-ui/shelf_life.dat | Bin 1477 -> 1477 bytes .../tool-ui/simple_interest_calculator.dat | Bin 2117 -> 2117 bytes assets/data/tool-ui/slug_generator.dat | Bin 2153 -> 2153 bytes assets/data/tool-ui/smart_search.dat | Bin 2151 -> 2167 bytes assets/data/tool-ui/speed_converter.dat | Bin 2090 -> 2090 bytes assets/data/tool-ui/sql_formatter.dat | Bin 2136 -> 2136 bytes assets/data/tool-ui/system_info.dat | Bin 1462 -> 1462 bytes assets/data/tool-ui/system_tool.dat | Bin 1414 -> 1414 bytes assets/data/tool-ui/tax_calculator.dat | Bin 2105 -> 2105 bytes assets/data/tool-ui/tech_news.dat | Bin 1364 -> 1364 bytes assets/data/tool-ui/temperature_converter.dat | Bin 2096 -> 2096 bytes assets/data/tool-ui/template_filler.dat | Bin 2138 -> 2138 bytes assets/data/tool-ui/text_deduplicator.dat | Bin 2124 -> 2124 bytes assets/data/tool-ui/text_diff.dat | Bin 2100 -> 2100 bytes assets/data/tool-ui/text_filter.dat | Bin 2134 -> 2134 bytes assets/data/tool-ui/text_merger.dat | Bin 2070 -> 2070 bytes assets/data/tool-ui/text_numbering.dat | Bin 2121 -> 2121 bytes assets/data/tool-ui/text_reverser.dat | Bin 2152 -> 2152 bytes assets/data/tool-ui/text_sorter.dat | Bin 2118 -> 2118 bytes assets/data/tool-ui/text_splitter.dat | Bin 2120 -> 2120 bytes assets/data/tool-ui/text_statistics.dat | Bin 2154 -> 2154 bytes assets/data/tool-ui/text_trimmer.dat | Bin 2103 -> 2103 bytes .../data/tool-ui/time_duration_converter.dat | Bin 2098 -> 2098 bytes assets/data/tool-ui/timestamp_converter.dat | Bin 2174 -> 2174 bytes assets/data/tool-ui/timezone_abbr_lookup.dat | Bin 1439 -> 1439 bytes assets/data/tool-ui/totp_generator.dat | Bin 2217 -> 2217 bytes assets/data/tool-ui/train_query.dat | Bin 1430 -> 1526 bytes assets/data/tool-ui/ulid_generator.dat | Bin 2185 -> 2185 bytes assets/data/tool-ui/unicode_block_lookup.dat | Bin 2175 -> 2175 bytes assets/data/tool-ui/unicode_codec.dat | Bin 2152 -> 2152 bytes assets/data/tool-ui/unit_converter.dat | Bin 1993 -> 1993 bytes assets/data/tool-ui/url_codec.dat | Bin 2180 -> 2180 bytes assets/data/tool-ui/url_inspector.dat | Bin 2200 -> 2216 bytes assets/data/tool-ui/url_redirect_trace.dat | Bin 2237 -> 2253 bytes assets/data/tool-ui/uuid_generator.dat | Bin 2121 -> 2121 bytes assets/data/tool-ui/volume_converter.dat | Bin 2075 -> 2075 bytes assets/data/tool-ui/weather.dat | Bin 2130 -> 2146 bytes assets/data/tool-ui/weight_converter.dat | Bin 2075 -> 2075 bytes assets/data/tool-ui/whitespace_normalizer.dat | Bin 2160 -> 2160 bytes assets/data/tool-ui/workday_calculator.dat | Bin 1453 -> 1453 bytes assets/data/tool-ui/wx_domain_check.dat | Bin 2266 -> 2266 bytes assets/data/tool-ui/xml_formatter.dat | Bin 2120 -> 2120 bytes assets/data/tool-ui/yaml_json_converter.dat | Bin 2158 -> 2158 bytes assets/data/tool-ui/ymhut_uutool_suite.dat | Bin 2125 -> 2125 bytes assets/data/tool-ui/zhihu_hot.dat | Bin 1364 -> 1364 bytes assets/icon.ico | Bin 27607 -> 27338 bytes assets/icons/app_icon.ico | Bin 28729 -> 27338 bytes assets/icons/app_icon.png | Bin 9797 -> 8457 bytes assets/icons/icon.png | Bin 9797 -> 8457 bytes installer/ymhut_box_winui.iss | 351 ++++++-- scripts/build-winui.ps1 | 148 +++- scripts/generate-app-icons.ps1 | 187 +++++ scripts/generate-authenticated-assets.ps1 | 154 ++++ scripts/generate-pearapi-pages.ps1 | 64 ++ scripts/generate-tool-ui-dat.ps1 | 63 +- src/YMhut.Box.Core/Api/PearApiCatalog.cs | 208 +++++ src/YMhut.Box.Core/Api/PearApiClient.cs | 491 +++++++++++ src/YMhut.Box.Core/Api/PearApiModels.cs | 92 +++ .../Api/PearApiPresentationSanitizer.cs | 58 ++ src/YMhut.Box.Core/App/InstallManifest.cs | 11 +- .../App/OpenSourceReferenceService.cs | 13 +- .../Data/AuthenticatedAssetPackage.cs | 234 ++++++ .../Data/ReferenceDataService.cs | 7 + .../Plugins/PluginBridgePolicy.cs | 1 + src/YMhut.Box.Core/Plugins/PluginModels.cs | 73 +- .../Plugins/PluginPackageService.cs | 356 +++++++- .../Plugins/PluginRegistryService.cs | 220 +++++ .../Runtime/PluginRuntimeDependencyModels.cs | 15 + .../Settings/AgreementDocument.cs | 8 +- src/YMhut.Box.Core/Settings/AppSettings.cs | 4 + src/YMhut.Box.Core/Tools/ToolCatalog.cs | 33 +- src/YMhut.Box.Core/Tools/ToolMetadata.cs | 10 +- .../YMhut.Box.DownloadHost.csproj | 1 + .../YMhut.Box.HardwareMonitor.csproj | 1 + .../InstallerApp.cs | 7 + src/YMhut.Box.InstallerBootstrap/Program.cs | 9 +- .../UninstallEngine.cs | 214 +++++ .../UninstallModels.cs | 53 ++ .../UninstallerWindow.cs | 233 ++++++ .../YMhut.Box.InstallerBootstrap.csproj | 4 + src/YMhut.Box.PluginHost/Program.cs | 1 + .../YMhut.Box.PluginHost.csproj | 1 + src/YMhut.Box.PluginTauriHost/LICENSES.txt | 10 + src/YMhut.Box.PluginTauriHost/runtime.json | 9 + .../src-tauri/icons/icon.ico | Bin 28729 -> 27338 bytes .../src-tauri/src/main.rs | 1 + .../template.ymtemplate | 17 + .../template/README.md | 3 + .../YMhut.Box.PrivilegedHost.csproj | 1 + src/YMhut.Box.Tests/ApplicationIconTests.cs | 140 ++++ .../AuthenticatedAssetPackageTests.cs | 143 ++++ .../InstallLayoutPathsTests.cs | 82 ++ src/YMhut.Box.Tests/PearApiClientTests.cs | 344 ++++++++ src/YMhut.Box.Tests/PluginSecurityTests.cs | 128 ++- src/YMhut.Box.Tests/ToolCatalogTests.cs | 17 +- src/YMhut.Box.Tests/ToolUiDefinitionTests.cs | 11 +- .../WeatherCapsuleLayoutTests.cs | 25 + src/YMhut.Box.Tests/YMhut.Box.Tests.csproj | 1 + src/YMhut.Box.Worker/YMhut.Box.Worker.csproj | 1 + src/box-winUI/AgreementWindow.cs | 2 +- src/box-winUI/App.xaml.cs | 2 + src/box-winUI/Assets/LockScreenLogo.png | Bin 2130 -> 2247 bytes src/box-winUI/Assets/Square150x150Logo.png | Bin 4895 -> 5370 bytes src/box-winUI/Assets/Square44x44Logo.png | Bin 1404 -> 1454 bytes src/box-winUI/Assets/StoreLogo.png | Bin 1556 -> 1621 bytes src/box-winUI/Assets/Wide310x150Logo.png | Bin 6569 -> 6888 bytes src/box-winUI/Assets/app_icon.ico | Bin 28729 -> 27338 bytes src/box-winUI/Controls/AppTitleBar.cs | 7 +- src/box-winUI/Controls/RankBadgeFactory.cs | 85 ++ .../Controls/WeatherCapsuleControl.cs | 69 +- .../Controls/WeatherCapsuleDisplayMode.cs | 30 + src/box-winUI/MainWindow.xaml.cs | 68 +- src/box-winUI/Services/AppServices.cs | 14 +- src/box-winUI/Services/KillOnCloseJob.cs | 106 +++ .../Services/LocalToolVendorAssetService.cs | 105 +-- .../Services/PluginHostProcessService.cs | 20 +- .../PluginRuntimeDependencyService.cs | 55 ++ src/box-winUI/Services/RuntimeAssetService.cs | 264 ++++++ .../Services/StartupInitializationService.cs | 3 +- .../Services/TauriPluginProcessService.cs | 140 +++- src/box-winUI/Services/WindowIconService.cs | 91 ++- .../Services/WindowMovePerformanceHelper.cs | 75 +- src/box-winUI/Services/WindowsTrayService.cs | 29 +- src/box-winUI/StartupSplashWindow.cs | 15 +- src/box-winUI/ViewModels/ToolCardViewModel.cs | 16 +- .../ViewModels/Tools/PearApiToolViewModel.cs | 14 + src/box-winUI/Views/AboutPage.cs | 13 +- src/box-winUI/Views/HomePage.cs | 12 +- src/box-winUI/Views/OnlineToolsPage.cs | 188 +++++ src/box-winUI/Views/PluginDocsPage.cs | 65 +- src/box-winUI/Views/PluginPage.cs | 156 +++- src/box-winUI/Views/ToolboxPage.cs | 5 + src/box-winUI/Views/ToolboxSurface.cs | 17 +- .../Tools/AdaptiveToolPage.ResultRenderers.cs | 21 +- src/box-winUI/Views/Tools/AdaptiveToolPage.cs | 39 +- .../Views/Tools/GeneratedPearApiToolPages.cs | 322 ++++++++ .../Views/Tools/GeneratedToolPages.cs | 3 - .../Views/Tools/PearApiToolPageBase.cs | 768 ++++++++++++++++++ src/box-winUI/Views/Tools/ToolPageRegistry.cs | 3 + src/box-winUI/YMhut.Box.WinUI.csproj | 93 ++- 366 files changed, 6683 insertions(+), 490 deletions(-) create mode 100644 assets/data/tool-ui/online_tools.dat create mode 100644 assets/data/tool-ui/pear_ai_dish_recognition.dat create mode 100644 assets/data/tool-ui/pear_ai_image_describe.dat create mode 100644 assets/data/tool-ui/pear_ai_image_detection.dat create mode 100644 assets/data/tool-ui/pear_ai_text_safety.dat create mode 100644 assets/data/tool-ui/pear_answers_book.dat create mode 100644 assets/data/tool-ui/pear_audio_transcript.dat create mode 100644 assets/data/tool-ui/pear_award.dat create mode 100644 assets/data/tool-ui/pear_baidu_place.dat create mode 100644 assets/data/tool-ui/pear_blood_type.dat create mode 100644 assets/data/tool-ui/pear_brainteaser.dat create mode 100644 assets/data/tool-ui/pear_car_price.dat create mode 100644 assets/data/tool-ui/pear_certificate.dat create mode 100644 assets/data/tool-ui/pear_chinese_conversion.dat create mode 100644 assets/data/tool-ui/pear_classic_joke.dat create mode 100644 assets/data/tool-ui/pear_college.dat create mode 100644 assets/data/tool-ui/pear_constellation.dat create mode 100644 assets/data/tool-ui/pear_cookbook.dat create mode 100644 assets/data/tool-ui/pear_countdown.dat create mode 100644 assets/data/tool-ui/pear_country_population.dat create mode 100644 assets/data/tool-ui/pear_couplet.dat create mode 100644 assets/data/tool-ui/pear_daily_60_image.dat create mode 100644 assets/data/tool-ui/pear_dujitang.dat create mode 100644 assets/data/tool-ui/pear_embeddings.dat create mode 100644 assets/data/tool-ui/pear_exchange_rate.dat create mode 100644 assets/data/tool-ui/pear_funny_joke.dat create mode 100644 assets/data/tool-ui/pear_gold_price.dat create mode 100644 assets/data/tool-ui/pear_historical_person.dat create mode 100644 assets/data/tool-ui/pear_hitokoto.dat create mode 100644 assets/data/tool-ui/pear_hot_60_image.dat create mode 100644 assets/data/tool-ui/pear_icp.dat create mode 100644 assets/data/tool-ui/pear_image_prompt.dat create mode 100644 assets/data/tool-ui/pear_ip_details.dat create mode 100644 assets/data/tool-ui/pear_keyword_guide.dat create mode 100644 assets/data/tool-ui/pear_kfc.dat create mode 100644 assets/data/tool-ui/pear_life_calculator.dat create mode 100644 assets/data/tool-ui/pear_llm_reader.dat create mode 100644 assets/data/tool-ui/pear_lottery.dat create mode 100644 assets/data/tool-ui/pear_love_quote.dat create mode 100644 assets/data/tool-ui/pear_love_reply.dat create mode 100644 assets/data/tool-ui/pear_mean_search.dat create mode 100644 assets/data/tool-ui/pear_movie_lines.dat create mode 100644 assets/data/tool-ui/pear_ocr.dat create mode 100644 assets/data/tool-ui/pear_poem.dat create mode 100644 assets/data/tool-ui/pear_qq_level_image.dat create mode 100644 assets/data/tool-ui/pear_question_search.dat create mode 100644 assets/data/tool-ui/pear_quirky_dialogue.dat create mode 100644 assets/data/tool-ui/pear_rainbow.dat create mode 100644 assets/data/tool-ui/pear_random_song.dat create mode 100644 assets/data/tool-ui/pear_random_superpower.dat create mode 100644 assets/data/tool-ui/pear_ruozhiba.dat create mode 100644 assets/data/tool-ui/pear_science_news.dat create mode 100644 assets/data/tool-ui/pear_sensitive_words.dat create mode 100644 assets/data/tool-ui/pear_short_recovery.dat create mode 100644 assets/data/tool-ui/pear_site_index.dat create mode 100644 assets/data/tool-ui/pear_ssl.dat create mode 100644 assets/data/tool-ui/pear_stock.dat create mode 100644 assets/data/tool-ui/pear_surname_pun.dat create mode 100644 assets/data/tool-ui/pear_synonym_antonym.dat create mode 100644 assets/data/tool-ui/pear_text_tts.dat create mode 100644 assets/data/tool-ui/pear_today_food.dat create mode 100644 assets/data/tool-ui/pear_trademark.dat create mode 100644 assets/data/tool-ui/pear_translation.dat create mode 100644 assets/data/tool-ui/pear_website_info.dat create mode 100644 assets/data/tool-ui/pear_world_60.dat create mode 100644 assets/data/tool-ui/pear_world_population.dat create mode 100644 assets/data/tool-ui/pear_xf_spark.dat create mode 100644 scripts/generate-app-icons.ps1 create mode 100644 scripts/generate-authenticated-assets.ps1 create mode 100644 scripts/generate-pearapi-pages.ps1 create mode 100644 src/YMhut.Box.Core/Api/PearApiCatalog.cs create mode 100644 src/YMhut.Box.Core/Api/PearApiClient.cs create mode 100644 src/YMhut.Box.Core/Api/PearApiModels.cs create mode 100644 src/YMhut.Box.Core/Api/PearApiPresentationSanitizer.cs create mode 100644 src/YMhut.Box.Core/Data/AuthenticatedAssetPackage.cs create mode 100644 src/YMhut.Box.Core/Plugins/Runtime/PluginRuntimeDependencyModels.cs create mode 100644 src/YMhut.Box.InstallerBootstrap/UninstallEngine.cs create mode 100644 src/YMhut.Box.InstallerBootstrap/UninstallModels.cs create mode 100644 src/YMhut.Box.InstallerBootstrap/UninstallerWindow.cs create mode 100644 src/YMhut.Box.PluginTauriHost/LICENSES.txt create mode 100644 src/YMhut.Box.PluginTauriHost/runtime.json create mode 100644 src/YMhut.Box.PluginTauriHost/template.ymtemplate create mode 100644 src/YMhut.Box.PluginTauriHost/template/README.md create mode 100644 src/YMhut.Box.Tests/ApplicationIconTests.cs create mode 100644 src/YMhut.Box.Tests/AuthenticatedAssetPackageTests.cs create mode 100644 src/YMhut.Box.Tests/PearApiClientTests.cs create mode 100644 src/YMhut.Box.Tests/WeatherCapsuleLayoutTests.cs create mode 100644 src/box-winUI/Controls/RankBadgeFactory.cs create mode 100644 src/box-winUI/Controls/WeatherCapsuleDisplayMode.cs create mode 100644 src/box-winUI/Services/KillOnCloseJob.cs create mode 100644 src/box-winUI/Services/PluginRuntimeDependencyService.cs create mode 100644 src/box-winUI/Services/RuntimeAssetService.cs create mode 100644 src/box-winUI/ViewModels/Tools/PearApiToolViewModel.cs create mode 100644 src/box-winUI/Views/OnlineToolsPage.cs create mode 100644 src/box-winUI/Views/Tools/GeneratedPearApiToolPages.cs create mode 100644 src/box-winUI/Views/Tools/PearApiToolPageBase.cs diff --git a/assets/data/tool-ui/age_calculator.dat b/assets/data/tool-ui/age_calculator.dat index dca91d3d8988a02e7dc6a849ecc38201df4a87e7..a553351ab6c472fd6529ac256191f431e3d41a3b 100644 GIT binary patch delta 1377 zcmV-n1)lne3yBMmIe$dMfW;%R-%A@zw%oTF@$ml-BP7PO4V{NGIIs8@%!htH84Ey| z1SceIYr}I_stvg{04jE5LUdK4%G$LjGm27;?@^HnHl8xh)M^(V!ve=D>7l&c+$&lA z+i89K_q(V>=aMjQj5vo{$@!G`!5_4>I>>JC7+cS&=ac3B4}V8r_u&LIYlY?2(1(HK zj1z`}j_d~)qa|5JcPd6sy3K@!@UR_B*HHg2h2R^jyhrcNo*p4jrSo6+uU0GJ8VU>q)^e2=~kKfFAw(rcQ zp{OmcwHG>Pet(-NcbGcUaQM08spRJ97+R(?yF;qBSJks9gL1eh@LQp@EnsN8pLmIt{q}ff<1pm9myVIyf;vi;26GqY>J`S~?2Yob zC(zi1CTn*T$w%-;gw(WJzj;P>;L8l(yA&paPGy4%o z?LA2!hV?{m#gAkw<@Aca&5GDQ%ySXH#803+cVxVs6t}u63&4E$MV@Gbf-b_g?KBck zj^%bQTK0&Ok#S|2_&p?Y{9!x^kaYKXc*8g;&_k#L-J!&tuY@>D#eR?b|U+ zmw(xNmxw+vXWP{9w<@CYw{Jcx(8Ok^TvK4oe97IAN&Ao`knP(S3!gyE5SmFtBLlNI zKDh_g7#VfbG_W-ZJ+e2tCmO=fQ0$=lo)6n8rNSf$e+7#%SP*JKyw(g_#OnV^tRkQ1 zT}wK-1w>0aOQs;B0KX{@IByJnAx!7|a(}${$Y4kWRGdbA;FB+OV&k^14s9N2Xc)`} z#M@=TFYjensHNZ?-Mu6ns$j!8Uz@L2JAW5KRU@8$`@D7l<^MWi%wn$zlITzk-)@bY zqxd|_gQ5DH<*?3Cy*b@Y9)&c``4C~dGqw}!l9HlTelE{^u~=@aIOtC)1J)4YsedI+ zXXk>gn|FHvDh{`cZW0P0DNK(%e$?ZR4OrwIRV;FBKOZeTIGVG6QxT;60h*axezQ}R z>&bluq@1MkE3B2bRZWGp7^iFTUr_8}Jp&o=;B}K!3hXM7`kG)0QdFef4OpkKC8r`f`|Hp(4evgOWzYMuxyoEm(7xG8vk-%9v}a=MjGQvJ>S>1WBe?S=lYewPHWSciCOaz(%eb&tDGXW9 z`A07uu#O#`YqSd2wdJrgPu>KMt6Kzj;}`$^%)=&4S*sG&bTABc5q*uuS6x8>D_MIM zcLmwqaOF^4+z()tu2o9|;ed;bTC^X{&S@t`nE0C=9@uaC&?->G3IJ@yTfPOO3J#jB z$DBS5?tiwaIyW-|!u~_>Qe4|?`^oM>dO2k^=zw8p&myW=o0;ojFGe?X^lFT1JjK<; zAZv- zy`R2cGZl+a!$5Ce5g~?8&-MFKb_d(?oG}stAbr-7Op{J;)_yt3m*Uwk!{Ng%)3(sNa(xizQ5GW&1nJ%eJm5MZ~w82 zpns55T4cF-uZ1#xt9KnrkcgbO(3|QUj&{F^a9TER!wpmhY?kPXr|H2VswvZy7IM5E z7hqy&0%`xUk$W=;ttx>FsiCBbpU}s3!kCs$wvc!$B1dzBAB)S?RQ5y?x1_la?`D@M z|D$4()r`rWL!m#=mpGcAJah{Qy(vA#Dt{$>t<~0;c(0ybaXW61jWhY? zNyoOcEcvfwl1zqsF+>wI=nfBc);v|*&c~tnv|-Wio~W2ZB03kaoQuVJEb5`;cYiqX zt|!m}>BYzQsq>=k>g4`r7HCktrwXu)kHrPs>p@ygkGBlbzx2vGpvr4Nyy{e9-a!Kz z%vK163y$KgOaux6Jo>F+cDrn!7fV)j+`w3HjC<1eP@37Ow1OJ(k2bX6gj|3Ms6hMJ zJ5u%1S&b~Xm47G@iy>jTc}8k@W`B@w-1ZIYynb*xb2n(UvFh>HD9vZQ+(j-duk5B` zU~4`@yi~ubD$hY!KhS4-dwZQOQ#+txc_l#|9xowSqOYyK+^{evXXGK4c<;e1zG|ay z1Q;itZX-yhStiTHbVF6p=_f$1KyT8d&EG%2&n(KO)Oa{SSBP*`%H`(kFj_-~y4zx| z@gR=(od8h_SdA_R3IW(CIPki)x{=$XO4ZVy_95R4sF*FQRw35hr^qNq^Frrejy>RX j?x^nJieb4#xWON3 diff --git a/assets/data/tool-ui/ai_latest_news.dat b/assets/data/tool-ui/ai_latest_news.dat index 00b79761dffdc9991f1bcec3f9a00f812adafa7c..a427fe118e1b563c24cf824e22f706a875a13630 100644 GIT binary patch delta 1571 zcmV+;2Hg3n45%CjQ^F2T_L9n*IGL3Na+ zkrs#QS!4yG1?dK4#aLAT-Fv*l;h$C}i4u4lL$sRlssLlUJ9XYIDI26eFLL;0d*C|X zap$zV=rXZCpPLR2CbO1vU0Esa1`d4hMijWX!k0bKlE_ltD1XlIvE!+EYH})+{BFH* z(iNb$g5djBZ`2eKprE~WBW!T=*vzy$H2t|WWoh^*9V!X;PjO~S;?26#n?Ngk&+WnlTrvJjlg&vGW5lf8=M_S3gf zThJVn2u}Gh{eRHygH1KBbw?DBLd=?7enQJJYb1~|T@6pV=3QShZF z%7YO@3(3JkdpdL1A@!|jHH^P3aB-PncZ@IcDv|r!4!Ac+RTVNy1eT4w?Cigi-@%>w zqE4|+`LUYQoux8+`;{N-31i{L==J14(F5~xr2;Mft$)4CIYzR<94uIoG1{Geb_;hi zR+wLAngg@)=>+jFS4TH35HYTM8EM%mRfG_pJHcSQ_jzJ30N-9udQgY&p4NQerv0SY zVEort*dq5ZPTJQo8TF4H5qYB;)M{SJ<1bf&fM6!fg7dOS11TtGvr2+_MGQ%9Kn!=# zP|IZ*iGNGZ5@eCBt0EaSx~MXhH1AZY2vzHEEO%txwO)i^2)H`THB$F++K{Z z!+!)MLx?>BpsHqxEEESVB&9I-kku<}kuLH9lHIVx$(ss!y8&+F!qD7%<28pT7c|{? zR{21$5&6{_WKyto3(BpdK~GZ)zWNtc1aJ3q^>ftqf<^bKCuw z9xb6}WqI0C-Z*zz5^C8h6Fv0%YL*w_olfS;Kv?BT7Q&~Y>4uMMdL4i28tXd-)DP1d z-?LgEo&ve>qU*WOaGxj*AgHQ)CXIuiRAk`hHlI?@IN;N~vP@P@Q5!wpCBTt&W`CD? zG&7C-vUpUjnu7JtvvS>_bI$e}J*Jt1;)cX35=zx&7LgUFLxykj=!^YOVfG?W?7z&w zn8Ngo3n4m+N3l}!fIcWWIIV4x)}i|{_&bk-ndzB_&lo?>iz?ll`{US z(n51%hX1b|Cw2CsCpAMHY!Z^x0)H2L4Bu^yA&~q|)0MYCr4eLcV(-Ot)`DRbLC7ro zJ>3@*Vu{T2qZ=IXyWOdCQ7fWLdWZ?Lc_*5}+e zTW^fyaSqk#P5X>C^UKuCC*Fr%`taR~!Qy6Kc8h>Qz2Mbjh`W5Ga-CFz^MCMa(A$7u zkmblvSU8Q%6sjnwKGQSD!BNiP!gk>jh^>k#WG^fQb02~a(|?9TIM-v`rJnktHegaU}oI0CR{*VAvF`ZXupIizCxRH z6n~)Wco`lE%=&(UW>*VI{#kh?5Pe_82#ly+(?8vn;0nk;tQ0BmN+<%ag)p?%h63i} zn>TqLC>R$YB_zucJ#;t8ROm=#tcR)a+zK}zab4mg0AFf?a?th|mmH(&#D8JOZOS|F VIvUzb;o#6#VfZ)!Jhq;M6-oLL3OE1& delta 1571 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 diff --git a/assets/data/tool-ui/archive_tool.dat b/assets/data/tool-ui/archive_tool.dat index 46fad0edfd17ca2c41e7c7a935b29621422a5d0c..7e3d12b780da4396793141a2f0779781043b1c4a 100644 GIT binary patch delta 1700 zcmV;V23z^Z4aW_TH-EX@B#~n(aA2meb1i#qpP(gr>66mqKeB^2H9K3#P}N{F6g56Y z8tTguQJxKQt-QX*a_>c2U#evX4EP^NlE*ou|Cz0*sTkOP%O}GtNE(2fd!KhQpISJL zBDtI0pi8TJk?VwRPO!BBaf^ogQq<=Vwp){ybExDC_!T$7oPT9dgGh~jcF7WsaBZ^I zUG#H;t_x~@Ih@aJ-_pkcen`%8Sq03?VP2;!iSVri!*fpwkX(Itjw*Sse!Pc$sbXfs z+{~s6!^-yzZ^=$StJS0jttC#%TUOD80ndNQ*vRjD5&I_1xPy^8ZOjaN(-LjDXOs@) zoF^wRP365Wmw!gn8&d5BuMAlEhW9Z(72rwc49L4LlOj}$Zy(vR2|9#&&hc;bJr>^4 zM6F40H&nDA>VNHSfKuS%(P-_;AX^Zm;Rg{A!NT62hB79#>1*LCLYJcN2?m(9J;0-E;OnD^Z%zjJM z%pQW!t;EOQyFM{(@L(S^J3|>P4Ur6g5c4DD#iv;gW!ErY=kq>IS)EJBN5;T$@WWQA zF&|1&F`@4XKR!0l4Tq9snRvKdeA~wUtSAK)v6N~M;153qO&^gDdKEAIMgV>NGl<`_ zkRLiKtABhB15=;hu1h4 z@LWoQQcXD6wJ9uBE!nAXBhoVv76uS~mjZD+kC_a145%9@*>bP6n|YHUX|rL}M(0~& zlHF_CX_-`)rx@Z~g_}ZAVq5chQqtZ-}O%E)UpOK6q_zDK-h#( zC(jjaHB(#k;%xbBC)Z8mR!P{lH%DjwSaIXnrALLZa^EG`F?!Iql!arDaL}jmh~!pc zaBLWIU}UhJ*k;_+Y(qzJSR_pVj0sq`Y)6WY*kMEz3NQC7>jwnYFX1l6tSiB_A%7_E zfPE5d5XPsA2ZRp*#5u`wZj)1JO9PXPN9 z0ItmAa*)qLVZ&M7&gHU25_)l>dM~xe4R%oc~xm6n3xCj#aMuM0e|^1m6o-Kz@|1X1yJ9iwB+g(gKdKAVEN`EaE7DlNbc4H z{W6;bSx!MdT(}hj^UGr)3q-*)oP-W_Q&^LJ9eKw2=LPe@ip2by$y;h`1%EOCT*F|+ zzaELVGVg6*eL#%mYtCmyHol{YykTT1$_0408JH-ui;^v<6;o_Qr~eFKYwc!LtiAYXCPH8%FfCSUqR`K;VGh#S8XW9Bu{Mmd&Xak zU=}W0GOkcP4aBOEW7p{87rg?gxr5N*iw(#*P%JP{9Ue(osUB z_k(UBF|13X1!0wst1jq=6lt|L%Iu{xXK6{g*1~V#Ct#f+*_cLErhionAjV_Nhv!yu z=oNE-Xr)c;0$INAnmnjttkw@`@ZeJEk~#*Aef9;#!5js$5@nC6Zke-&WssjquulT~ zyb5<<#`L0y(gGlrqs=_@La}`<3Fpb$rJjG3kSo^Sua#1*I3vI%K|RO5kMsr+t=9$5 uUj3>mG<^pbHjE{YVI79;q0ytos4wFBhcb|SQ+R_AHiF+C2@tx6 delta 1700 zcmV;V23z^Z4aW_TH-AcrIQQ{UrkjE==#GT$wEXL^M^?ME=&Me#Yjrae;-k~zvE#G( zSposX;baC1-^vL*K*hExV21eFV-OblF{Q##zv9F>)GGupveY(U)y`&rTJ|K9zCQsD zjRsyU4g_40ZcH1T>K`P>lhtFMui3ljiqG>>Nr2WS;I3R`*nd-6oN#LdM-#x*^B7l& zJ{&<{_7RE`&3PTGcK_=WLbSG*1lYyggQc2+7nZ6CH!jl&SD-$uV%_<1Q_-UC z%)jE$bMm!XE z8rebr#isiGwY}^(Gk8l4FHQhDBZIK5bwe$O9WOB%jeie)INv6XjX5XjwG@+zgJ1m1 zE(XWvCNy*-ws_B{WM?!wx6VIN2N3)o!*g>WuoF&F8CUO6(J|58v?QRf5ONf}-^i%Y zl{CERmH$85a{$Ts!yKxBzCLC;d=}1L&*U`|2$n_*!{gp&Q&umH|8`c76Vmx{`$nx} zmAhcspnt~~WNEosoNB*1>vCzmdH`EOz(XZrP`_Ev(;b21YkIyTF$~ApXf@i6Uams7 zaMn_0im6`X+ZDz9#h2%EUt&G*z2yu%Wo&pIe8+Z5)Wi3S1S8*CHi0~eMX3Xls7c7FmD*@+$NXAB{8MFk^uEj{Wk@uC{lstW?j70|V+CJ74ucPa@d*!BZY#&%7;DRDs;4L90-ll)ozB z5P!?L(B#)(PSUJGN9_xo3jCh_sp*c${G(OT5#eGycr1rIfJO6B)g|z!epXs(0l}c1 zse(ns_HZUcVQ;0_?ZuyB;4{yP_;r^R-YX`t%|gh^deg;Gj`Ptykz!xGG6|peM--7R z5NqV^(v_7I%}ExnZv*qC81xJ*#~3?$vww9KE7jhj^rU=2rC~wVkXp1yMlodO{D1^I z&~8iq94J4~v6A+0z+U1G%j!VTN{vHND!wd|3UHDVP zd0=9pIpLuLW#VIv{2+(`Q*z_EdcRT`?H3wDi1w(BCR@zvb@bvRw9yd2E zi&5uiZ@Z(B?EioG|!oF%=D9A4B*Rxw^$ zn3CwzgD5ZY-o8BQ2CvU!*HP2CR%4xiJZ|D;{#1GsX&3ZM_JK4+bjzB0@Q-)-s+k7p zuO$p~Yhc!TI+p0CYW~-)g)3np@Io$L1aS^AcNh5zok>;&XEWj7QEfjZsDF6B%)2_2 zhYVPVxURweKY^^E??~v$`%Avwm|gpdd7Oe7IMLarrV+(Oolj$;Ggb$$WM$6`zszqb~88_0K?XsRzoP!ED zY%PCFQNH`9wUrn>3I)C42lA6rM#chfvezhZx&X8)*S%owMNVr+2iw6+$})<0i+W6n ugCND`tPgsAA`FsF1088$M3EY;T6SEJ_rga5ke|b{v;!ITuZU6b4D!xFc21T6 diff --git a/assets/data/tool-ui/area_converter.dat b/assets/data/tool-ui/area_converter.dat index 7966b8a7f7a106feaff8f4ef0e1160719af38d18..979e4ba99d1770dba6e659f4af7a5fe04bd1e018 100644 GIT binary patch delta 2038 zcmV6C?M0z?yAPce(#?;A^@&+w>Onx zA%jhEk7O<37-H|@lii26cN4aU4=lW4*Y6noZ%k_b%t9S1H-atxqV*xTWmpkV!Tzm` zjnD*N6AZuPreScCilac8ZNV#WP+(AuOlyQYL8}WJ&f;{pGk*zzX~w9vMibdW^Vq<9 z>!mTft*&#_GqjP-8d(hw8xJKLA!;=YH|wBM#lfYG7AiL&34dH@`gym9O{q@qi7NBp z`l{d!^+9MU~c={SMUX&GL)9Fl`@r^NTzw8vHZTRf~XuvbCC$Fj+~0;Td4L zRf0|UK!k@)K7Vi~2o!zLVk9pMJBE#>9Q7*c_3u~AgJA62i-%^TPeKFij8MfAM<*TU z#0_Pa*E^IVaw_zv+8v}2iqVjegWh}u&83W^6r~o%Qbb@fxw((EM-9$OTwZqoy(q1mf0V)adjXkEu-bd2?4gQ!-+y1^p@TeIW?rfks{c@^CE~>6 z=Gy|b&DC3-^3kbnRK|;YwBXRmFfMdnxbHA56@kDF#?n8RRV0f~OY(&fI*D}li2FD+9bNa3 z>@_r$+vVdJ;mHd;*QFq`%nTknwr*U)h(lYdEx$#AL8Fq2D5KdYO`kjv^`*a5h@;obI? zJ8GtEOaz`aL&Y66iwPTbLPE)<8NgSmaTkk8A1xJeN4>#+TlW@iA8WkosJcCgdgqqU zn)2rd0!{^@J%>x9%VZhOTJwJu;e$r3x0^C|9=v+TzS8IY{QvqE@!E=hG}?pEabdD>O$9P={l8frBMKNuYu_A#9P;1xOgzL|y z3DAnB=ErdUTVoToECFjzzDNyHINyQRgv&!DXE-a8M_yp(ok>#UGtnST@46M5s^ zT(*3Mur);U=5W6pdzu-iq1oOW+2zp{51Rg)-2Tm-R_W7ib+h%yv|V=vGmy~qjC=cQ zw%H0WA6=ZFQY)L$1|8UvoiOFg1Hjt^(-E5}BwRTG6Z>p^C#<80ToSoFDmxzZTOMKL zcF5t8vXP>S;T2_QMKRGCsee>XrpUEH82}B4x(7-ukePigB07h_dj2Hi%8MZ7Jx8HU z(9T9mUam;NwWq=Nj$ku81V6>s=sTShH#KZ}0bP%!;NfMxqPt34HV~^3dV$a7o*1)noETD+ zj#s$95$Yo3m$rn5mVY#M+1N1#xWr6frno(ex_$*edwYi!JR!XlK7|8kG zdR&;7L{L5_H~pAKax*brn2;AayvT7g04+atr0PR3nH`*Vi{rs__e?ipS#p5$ba{8l zSTPN;Gg--l>Z7HTOc~K!wz`Zoi`L%t=)7%LY#@wPJMz_vZhwuLEhO;<^>)?vM>vH& zVToE{J6RoQ%Aig?y%1CU0uFcv`$&Ly4pDRkGyVHeRcI^G3k6fPpy0wZZBLMO1c9`? z8;T0!!p85ny?Hs=2#p>M!!8tld%6=rzQO$hQ`)?Oz|Aor!7`9o8$; z#|Jo13g{jyb9=mcCOKjTp_>(kJN)NBEuiDvNE*fJOiALf5C_ex-_fhQt`=bNQ@<=k U4ZxU(Df(Go3GXM`guclBJj!1K>Hq)$ delta 2038 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 diff --git a/assets/data/tool-ui/average_calculator.dat b/assets/data/tool-ui/average_calculator.dat index 6e1434614a71901c005ae5a864a715c886e4bca8..a85ef2ba9ee9500e96ab4e6491092d1c1957f02c 100644 GIT binary patch delta 2022 zcmVCtS?kiORNF$az5aJ3q5M_1@sMEfGR z5iq5};3p#vd6_JFGV8~TqHm&c!V zP3jvXmaJa6my+R|;$-kYHV)uPj>Gn$`cQxUi-xEHpy?UM-yQ}^cwOZXn-?`Nr>#2Y z(yctQ>E_@g!P{4*4{B|JX+`tNDM=wTI+=j|Gj@E7csl8&n|-fL4ViWnQzees(S#M@ z|9}`Hcf`JJ6o353=X+cCPT4R=8t*G-IA9s;oe@9b_ z3Usl&esm|&s$Ek+vJup;7nvvp=gKIzfH)Bf)~%w!Jp`U4(O*67Jj=fS*L2!1OyQY1 zhKDgmSM7<#JVxoL<|e^ZZ8v=8$+d=N5R#$yRQ~658atWTGA5`P{($nKm$y5uX6ZdN zc(+XK|9?0kHEYsG?xP~;EydK6pOk8q_n5k3ConPV`^(YsVCAf>aRE3((sd8+3*Mo* z&5igaKUei8>=M<>67=UdDQTDx4^_(1W4tuJDowNE%?X<-)X^F*ZvB^z{YwEA z$+rDyrELKeT&oigd<{&{43c%umj=>>>4Tz4zADYsmQ15aZU|mMyHD3V|=WKaGSd^s0&ii+u(L#nt9%dn40VSMFDU|!2aj0wMLgU{x>tU;C?WI_9+^oRbG1c_*IC(;HhT5l!80x`ApC` zu1^0xUCrA}3*7b=M0{|Uqj}&22@qHyK+mS$L@O4xIG=5b5gTKj8_jFjDnI$5pwbmt z0%6oEXxFYaXqu`)h4{S`&YN~?ur=NON`Jz{y>+@Y5N+*N6G|sM&9tpLDD(LTaV(KP z`;L_Fj8NiTQhPFwye5C^AYrK%0k9*QiV&Izwkd91Duwm+gH%2Giwmvxk+5+vvu0`J z_vp6Z1-49RQbO@$EL$7W!VI?{_!ZyO?#i(z$vuiVi|L$um)4B8D+;L{8iViTt$#v% zG*|YXm$&ze%_QW67XG5ub3DT%l1I48Iax^-3H(XnDG64 zbarz&#mHa(9n}2cT5P@)hpMSbKBvbtx@KuTzXPbJcU0<^%1-54J z|7l=i6Zh!*F;J0N9YB^(f~&>&OmR`)CCv|xa?~M7r%7y)Zi=#Fx*MCx`d{Vn5 z7z`-7MDe_nDCk(?{3FE@E3GPe1nNUkYyuG3dvHjh{eeHwETULS`(`L1y#a1C4yOlg zUM>a_0v#$QnTLZvJc_KaSgzE`cHzf8HBbw&I-oloif7$F*jU#xb+te2VE zLD&~0g`<-Cck5R>+Wfqm-igD7F1LL~k$O;J;^YGoNP5l;i!)QoT@4~2*QJ=UNy&$V z?pB!`loOzwsUp&ffXqLYmDGrzx5<6PSK>tFRULn$UR_Fw?)?0yP@giPE+RntUD+Uwuesy zRfhq@Y)wNz*WO`7F%Ir8sR2K}7DR9OX+m23m%_(*Hfy2muWi||y8F+3d)lHMpojPD zXsQZ#`+!p+abNrP*jWAj3y5@Te8!K}@e4uj(0U}lQN*kWkPqj}g$WfhTPyI`^2n*G z1{TW@5y?>v+O3c#>?RS>^9B)hc0!;*(6EVin-ZD$|EUC_c>vJicEq#SW5UMDHj>bz EF`F6dwEzGB delta 2022 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 delta 1377 zcmV-n1)lok3gilq6n}gqMMMtWSN&~do{13m;6l-JYkr1is@tBf3u-fthO7@S`Ff`< z>hdjXq%lAarXh+8Fy$QY&&bm6F3jh%piIv?j00kmp(>4{`cVv}lc@kx$|whiDiPrI zxqQ)C<^1qeMvfrPgkB1lesGGeL;QBs`Jy=53#SI)0G9MH;(sG_`DD0!$+-{dq}|bH zTu-rC=KLnsA$!8+$NFSCq!88KRV~04gu5w>NuB9H2O+MCVU$}H;+=Mck4lR#YTS{d zPmQ+T^p4VPQ@-{s7%284v=J`RmcQ8wa~_EqWZ;5*5)j7-LFO$wy4>NBai^IH##Z9E zzDXv}iZQb6RDYsqAc)B5!^v$*rqKXL!g{2ZrVP3tBGGxRU4ij#$HgSvx=mHhZ_8%n`I zZ2L8-scO`1X?64OtY&(g=R1Vqm^?a%lPaYzG6gkCdbat=(!_#QGvXQ?+$KRtvPk_3cz)6zEXy8#RBSf+xRH6SDOnYaYVTv>X|DO}J)pl?g_me!IqAV1s%<%O zI6ITLNPi?H0OhtHW?zLUCaiOko$lx_o4q`9LCoCt`NXR6OuD68ZNs0Dgb@6;7+2W; z7aeHt6R>FyUox1?_diZ4Qyb7S=V{V`@zw6o-6cY&N&+0ad{KzLuwX zUVmk->RPqp#zLm-G3dGnEn+)t^d;5I@vABzbV?DFVO?5t_V%t(8jn!}K8dAH-yN_~ zSOo71b-dr$i?$yJvm*hWeEkb2yvLBi0d zxr15v>GbM~O+jGz_djO_HQy(jyCl$beB*iANYLBAFsGhv$b^tnaF^ps@y!`)Y~YPHYdyamPU$dLwLpksEFArKkMfqkl=U zb#U4ViDE7cbFNX1qbeF^P{r?Jz1#tJ)-8?HLMS%3H!Lb&BI8?zrgPUGeQIU(cxUnz z@!#};v1fAyoSipn>0IhxQ?CXarrk;WuZJ3r{x=%QdjL}2>*U=G9abfh>J^ytgJNrt z(AeIO?cHc5Qy=WnFEYPKypqpw+kd3+-h|-g8?6Ah4m_o5(4tJwq4tS)SLp754Mnu_ zD!W)yw;1KRa=bd#hXUQ6#7e6>Ql|~Y#kQU8|D#~ry~Ed&fh%oGNVef1zfo&vUZ!~V zL|Cy*ay;zEEq9f^=>D??D?#Zd)};{9ISe{nGc8o<1#D~l<`1mJ!T%) diff --git a/assets/data/tool-ui/base64_codec.dat b/assets/data/tool-ui/base64_codec.dat index f820b5294c6352f51eeb43bdf0157af49de0f30c..62c7142da0206605748c7d553ff14fed27818c85 100644 GIT binary patch delta 2135 zcmV-d2&nh>5cd#}H-GH^lgdFcGVsy*@qad#66+> zfOfn}rkdjxg( z9S5{s;kYs_*Ba(?fincAcWd5Tn)tDx7 zsW0zg{ACLu_Z%9pbcV~_4yej*lD6;@EM4t)kQ?kcIA?)S^U1!WS-c_~WlG`BCLGv1 z@m$Egx!}e)Uw`t?KfLg&Zt@i|KzZoc>uh#aDa(vfyH<0W;e<2=Bgba_F#XxLKzVxW z`{*R0Gbxvx;zXSDg|3a$0Gcx{)mf37UAMaKN{7DMD7OD-=9rz~5-k6sK%Oyj8CvUJ z6IJb{KdW=6C(}D4y|rIJS$oRRBL->b?zs3Og_b+Gw0~w{Zjp|Wa70$3Y%Q{fm^md} zzOL_F%5UHi6|{0c38V7FvBzOgW9G^OE?{5wcvLms3%F*1H)AD$^inH4UaBMPdR%+a!A^Fo2hEVy z&_0$AlYgt}NeIk1=O*lryzSCN1*KeV?&?v_^(vwnrQjk%g-PQcm#`T!j9K5R4to6g zNt<7yA;$RLd#$Nb{7h3MMnSmO&B({m&6BmF)?F3JOnUE)bux{iZT`AAD_UIT+Updw zRl@56W-z^`48qM?CxAJ!(3|HwGyBvw5gbKczJD{|d>v(2Pm5@?$Fp&$NnMls*w}t! zgR6pbS%!v9C-Q%HsPTd;aYfWw^8B~*xZKn5Dr36EPWkw_+qM>1CHt$@dj1lFI7z^I zCq7V!QW|R4NT+ii$RGT{UV4e@N|LFa8(ey0B*;-TYrEM?KSn#avBt za(@|Jcmjb5|I@r-G=u;SJhX&|-}Exz#l3gT^`2p)Sn8h7g=c8Je8JjgEZth2IEveW zhEeQMwsB%n=o0|CR0*myt-=?EGTV7Udk8d~6A-@t60OHR7l5~nOS54@=e}bRYK@BO zy=CWKCBLqmiq|v3Sag6&PMe5zDABb)N@ zy(=GltSD9HOGetCyzTQW=f^wwQp%Mp(Xy>cu;fWZ+|iGLh%?uYN&OWkac*ccj(=fa zw*|_28zpAytidoJUzzEkh^p{(fH%rotMxie>}#%{CFK#k?MiTL*3Kl2c3c6iYdo>u z%V60Z%NtP+WJB)-o)Y1{%L)`U^1jhf_@jEt{R%&GUvTYV>(B|m(Wx>1YT@yM9O@3I?;1P2_ zE$>3LB35PVJ5Kr^lBt$ps=5)%6VK4>>XKGVs+7z;~%w zZ*EeZE6LH*u9UQfW^+@&82^*S22Rzd6K2R-Z<_gXdtk#ObD{aNnDeVnbdYT``#~k%*OuJO zWhu1diK6umC zW1*i=86eFbQRz`kIjziulz(9{m)aTQpVUa;3>5n^7B-gX)iQFy7Z!^yxTdW}<$a6v z>I`M|7Gi`Qp^(*P%b}yXI5@9er8yJaN0@t0xT)6^CvHfcw_R8>1coEct@H$hWPl8v zfJ>v~$Wvx2j?*Yv-aG!;mHVeL5B|a%@Qf~QNjdm!d$x{z!pg`GRDag~B@tE)zgjm@ zjuIswl>Wx4%%_0H^i?@1=m|wE_U`yxiq94T#unmNBmq&TgP&O|iw7?MaG!_<*%I-0 z*>($z*J!w}v`Q5m&spB|SOTpY7$cEXr%I~1}LVw@9`-$g&p=N9Xs0)i_Tk0QIrtd#?Fusm_ z1Er9cBu-IPiriY(FV@>qLzqX|2&s)j$xBqu0liy4)WDjWh&XI7()-laN%h|Igelu~ z?8lRjWxj?@(l?@_5Q77YZxLTUJy{?-C5I(qy@~|33b&hakbeTbQT6p8C|pUH?V$~( zh6Ip|Ej1~F{eE>f| zQqrwc=>i4xtf%(UB7U9g^6f!A-0GD)+YUanH|=Q@c^K`5Yz4DVdY<&DI4tf>slw~# z`d^I<+|Fmi$T+jBVapSXd2fxu5BZFNZ2B#PM>4FN7EnS>saG1rH#~Xc^Fvx*Wu8?X z>;aHR14X=67v2n+)yuO6_@Z+_8@)^!>KN=V+5i5LrV7-Gif|ad_O6ydKG07inG`s^ NM_?FBBnFQ0b<-?;Fs%Rp delta 2135 zcmV-d2&nh>5cd#}H-CkycX+{iz?qEE{y*!*fk*;luW@+CyUQI^80-gQ87ejX=DrS4 zV`Weuvz-2t)$*zs5Se6^GqLanFeGWiplDUBqUfgb4b){Ez-;uu4lg(Wo#FuL2ZNS@y7fJsBsF zy=k`|+>kc39v?lU@j9dO`Nr*KKr&e3ISHBsX5(h{5TL=xdIGOa`uPgY}_KYKT6n3tv+Re{tfs$OhZzA>JR@X8whSmTj#`54zDcIHZn3;{x8g9^;zDDKKjPK8_-6h z8myGNZhYZhS?rx4SI3)gzcZdcU6@S!YjysA{93m?&3TpWFS9cvh z_nmUU3oFEF?kR?{k6KO9SGJ@3g707o5y5RC+yPtj&Ab$Qb!zjwyXwTcPj(pM#{X=w z^*N@q(X*!y><~dtEs!?7o$})CPl>!$_rGsjrkz^kr_^b!8C--hbQ%XnsfF1Tg zR(q#nQs(S&<8)vHAyK><@4;dvyu(+Tv=qx0QyfjtH1o4a@UaV2&>2#09q-&z2;HWC8OelM+t_CTsR@$uFT zt_I;_TF5=EB3tcsIrXrn0AK1Dzr!tBH)AOh3#%u*~7wVMX=e- zs`ptBhC=D(CH%QL}F`isQy9+Fk9{pH-Dq<^REscG?u7j0zU$B;uO1!{Svb+XfuEbG1J@8X8eHRCRFKBYqj7|Bv>sP+oyb|c_ew}99%ZtGHK!{|liVTdOu)@2P zLn5VH0p@%Z+djzt#_wxBMN@lrUKRwV)j3FZ%Qx@;21+Qtn7p{AQdb|K&%nV zs%^N5O4fA*BBDy@o<02cFV6a&9DhdWUDpjf=+ybB(5)O1DSkQ?;;*1KeAtf@gloDG zCU80sr_SA|wMJk8Tf2Smuw6vto)4QA#jTpkkhLGjsgq#v2HYy)I=ew+4bnm4e)!2| zgrF947lq5am+5XKoPGG`Rg{)|r51vYT_v^u-XkB#m;+1J_g(ual#DI+{D0a$fYUM< z9}KtAUsk1yX2?{zS}{jt!}B@IVv*rcvawz{2)rOEWb2@^ID46)`Pu&RY|<5|Zs{jl zOY}7f`u!r07x;|cw9bz2Fzqm5lw;-4Mc6hbBoUV;>9T~yaYwTy-YUeue5-d*=n9?G zB7KBswpUxcpc|JKB*YeLLVwK;-Lje3hKmO)wYT>q>U8w2PN>i|X57S~Q4S&xk=i?&*q($a> z256=Z(W}hK+T7Di4oL#BHjx6wrYJa7K=V-OT)%rEcjab7I5@=23m~mAT;lcVzzZuN zLti*iVA2<|26&p}t=MM=!bs^ZLKsTgYU8CgGY(%ym)pX}N7>BuVhO(1#}tnPIqhYi zIsdR+5N&tqd-1S78g*NIghkHtk0RT&^_`aFu56*(}dG&4b3q8l4 zVj2Sgwe;YG-uI%W)Feb0K`!{pvPz*#k7hbJMe@D1euV{UK3%|UNvcgiTxNtmJ+l<5 zF@qu>rs}5`bJ+^y%Q#H z$ROTg71EWvcb)z6M}MDF2|qo6RMa_Q?D%tof?q&(;*;<=Hq}>hJFI#SJLp+Ms<)$* zcHrFarr1O0?p-B6S4SkkO>@+X*(}g8M-o?`jZm?oVNw|a0(qWy~E9l@v@O? zt&hhuQbr|Z_J4Z!>Sc}ON!42?+dn$_o1@B*x&11>dc3Y>fJV-hGhAKL$}v7|L=OgG z;amk6%6h`TtxMhC3N-)z^ux@hf!F67*n=mA=+?0~1GPt2`F#S6zsna)uM5VN{cl|* z?8?Qu$*357FfoT|RGkgVhn1kXXu(%y!6JWHq285Z>QI4OoZpWCQ(MD)4!~8-2LB$7 zCmE2SK_*~i{JWJ<6yjsp6R5vGZSwuJ#-+4}iB+A$&!OqshgR#~QA&uuOf2UN&&XJ5 NME&F3BqgZ8!vn2nGAaN7 diff --git a/assets/data/tool-ui/batch_rename_preview.dat b/assets/data/tool-ui/batch_rename_preview.dat index 9f2e82d4557628122430d9a6718f8f65638c82b4..c02a0e5ff26fc944570bb493fa15fd282f195898 100644 GIT binary patch delta 2103 zcmV-72*~%}5Z@4xKYsy`>56}hG#CRJAyT~)##Dgoodd?$TX_R$0Rte=$KB+8t54Dj zNUTy`3G(cIx<5-DqX^m|mhy5|pke|8;qHAt9h!(6HSV#ES>-x0vIQwFmn|=fdk>TD zvf%gMm3o1<5n-;lrdHRN#t$&%yiw|f3KH;T*xDa_MH24ftbcQq^82&zz+n`nsHv81 zE^hL>I!r7&l=3r3oL^hhVE{^!Nzkz)cy4=uiT+3+l&y$zpsr@L;TyrP(42FDv2uE= z9fH$oKM@k&;2bsH5Z6(L%TH58XDiZ&C4oPxcISexe^xM%w zpva`z8zdQF%qmY+sCWoW*gXIMbMiY){P0VO z;%Y@wu2o*|ajgivHnA-5;4yN6kjRiJKL!0aKxJS@T(rARhQ0tPD@!P$;Ar{T3Rdxp zAbz)GE-yqoD`pDEd21ZZRdfEV)?@$At^BZ7u`K%YfPcmwew}Glib^#L^mlJ$6oG$V z9VzoY%+Jz^ry#`*X^~Ugu&K_UehQnt!^;_P|KJLH@8jzjQdUx{j;SYlEEp;F_~bC~ zhRhsIxq!O)G(K9(pk=j?(akX2Ulv_F8`jnN;99@Ma1mebBwABdDm| zcfKPCqd{PY-pcaq>NOl7+q!EdS6@rp8^#RrI00ZIw=^7|6k4%GqA#c9Dp+a|FSK6a zmS^4mC~f6SaKAJ4edpb+FSrPph_Z<}2pfO#x_@Zx0@kH!W^N1^BFuogWIFb!cK*y? zOY#@)@*BYtJ_b}^^A_5D7|y=4IJzuX|8LMEdKSgO-Czc2G8`U$OR}EG<#K058C?<` zO{R?#h|UYOeg)6TIB2@j>sc55hUS5r)Z=nF#lDx>ENX_YLy~wA<9!EzAt}p)$u3YX z`G1)E^tgmZ$^0W?mfrWyR;GpQ@-%HaEvzA$d<1BmrA0~*;goNGyD=9jT_aE6Krsdh z%oI)0zPy0FGmbZOnRQ;R(kJk?+#9}@&srO)I;|Z_%YxLZu1D+3p=|^6LrlEU?*BC0 z1Ez3xOK?OITOB9Xq(YRf@<24o0}JFxAAd%a9TXenRpE&?8hazMw3_6G=0NFjXu0@} zhYgv3lWQ^4WC?u^nEn%+(RjqPvLs;}yQi`Q<@T~7+Lo%@I(#lx@+Gt9nvh%0Qlzua zU`r#Pq)0u!6~am=q*4q1H8_!*kVW#dfg~N*xiM)0qA$j*SYKM1)pma+8B^GP*nh1L zJ%N_+d$5?MnRaG5u5-`xI%uQQBV7p3kkMhh$|;M~{MDsF2xb!79OK!X-SJPQcI4=M zvLX*N^3_+Alfuqx^zpWY|4FlYLR|aeyP+1?sOY4^)VT0CDQZl`L=Chn08#qcAYs0X zEWIc3DlEIv8lK*hySzz3?^`Ir9UP1bFT)L97YT9kO|!NwO7MH9WkxXD5xOGCs^K z1;~#E@|-9G^MuRc7e4Pm>X@A&iE4kRYjd9|^ z6|<@PB3?pqS-;e#+Dt5+(Y}UYO8h52O&l+wlIl zwo3$1Asqn*@mQn_iYgzzu=05U0EDwy$D!tX|7jMrm@U7W&vU(US+?l<-`zj!pydN1 zCd|~CApv-ZjBZrDAb*!E#IT?(I+S^NWtB;@)TtY>nY?DAj%JaQ1 z5&B|cmoMEjDOxBP61(7c#>h-QcZIur@r_Oa%CZo&5eR+W{`M$qQSJxtwFm>`Ug!K) zxVdOr%;a7nFgK5L%rveo*7zMj5L8y*|7=Tj+8q@IpK1X!S8%1CbtF(qq>r6AiMOX| zpc=-FQXpJ&e}BioG(5I>q$Xx5al;GLAaVxrL%>U7Uj~5ytiRCx2xiAb2py9B2Kr&dMlLakrO_tMwW*Ae7LEV_ delta 2103 zcmV-72*~%}5Z@4xKY!brr?uG?XBK+ZPWi7MH4hCK;`#$6sQVbslmT{u{=nryngP%gr#aLY;Q3iYNXy!9*nZw$$#2m z6I)(qU0S!Rrwq$J`)H~IQLn2JwUn1V?oQsA>6*GoMe>7a^M60Om9g5osBrlMv-Tl$ zl{r}B=WvG`;qX(0)*pW-gNf<5#h;^@bz@v37YZ1dz}#;Nq9|>`bvCB$3%C-TJszaW zh=;@LF6+UH3DFTgNl;G#3*b_~wq8omA}!KaCl2Ws@muCfQkZht+812i~UF2IbpyWUijk>4(4o5$k=9oR+tK zN9rm+8rB)|^`3>@7%x#q;{=obpksOYvexIe7(G-4a*bxp+y%ZQAfK=gNL@l>{XIc0+N>{VaFf40j=zL@b& zs#m{4HznSYH93t!t>w`?n)AuJetO2X$fx$hrD(m9;bk0kqjj{IR;7;u?bwNxNgfSW zUt=*P#SiVgo%VrDp;N+X&jj+)g$Fr@7{4+=S%1K2re@W>r)&RmahRCvfYpgGqjN98 z<@SBD!!ORMC#(3eJO<{L9-)CL89pzIIhO|OFNdQ39s62Jk*iCUp-Cib1&6qoa+-m+l3t?%YRcMO=xArA*Ng#Kx0J6o+~*iVC2SsxnI_p zw$tbu;a5~<&dkeBLgu@whiSGAzr%2{a-u?sD)Aj;Y07uk{)<)}<>31x8sl0NlE;;J z1^)#*&6CR%{8I5u>Ci8Lb{rk{8_e5`R`4 zw;oH%^6=du5UN%=1+mVKHa5R5J42nd3t#08sEm$^160zUp*xaI5RULSB&FVxL`NWh zlLHNv7(yt5#{1JRV~wN@rK_)Td5%R;l&F7R@^MqwVuFVtMZ-ZF%bH%!`IhgYEBm!O zEk~CoAVlHTKi$uOQa_i@n`pNmcYpEjj!J~iB5w4LDY%|(EM)=~EQ<7g)-sQo5I$dO z>E>wArOcP9{Vu?IZ-T9yQQs>ZtR2xcsMdoYfy3wMJi(NzL%Ua-tUjs~gul*)C#hAA z!u8!j9D{lI(H?~Nu<5enHlWXFIo`Hw@~kkuz@Hy+++A{Df^_eU6?|%0Z-4j7xpiLX z*ff=!gwy$PN*{H5R4?Dc_@bL)(z10`T~{za-r<&0km4l7dl4YiLlQiqG($g<M_qxaZfaa$h3bIiT@>|K3-)@zhKh534> z^0F8h<4Epxzu)wl{^6(VP-fy|=>9tM;4chW&-QBa97P;qGlrZCRd zQqFP*{+|_c+CuoO+g8t&7`OM(8}QdL7)_O0P-u?Q_k}h5EX%y>tbfM(6y#H4dOEU& zKvrHTXLjJB=24+uY%AX{6Nkv5bq=H-3o->*HklpYfEMs=^8{`IGm@j(BMYJSmFxXW zXg2)z$>DS(%vceXa9pEc1VTCJe~BGdDzp~3$wdJ=Z4DjKkWm_>=WH2v39 z7H1y)($xZp**1cV7W6v}L)SHo+95*dyPqvjAs4Bea~kOije>|3)uq9E;U(}(!iVI; z1^o@m<@7t;@SoR|xoY7lpUrje-^75Aeb;}W4aetC)_tot7Jp6DthUZS#AQ^1K7*Vv zpryUmtj4|aH*$O$&j>9}3ehD9hJNH+&RH*W{X~9ve)DZFw?=jE4;LY>(W0@dTXG46 z9e_TMLX14IZ5qOJA4uO4S47k4nxIM}N(y$xTa}c^_`qaRiW|)l>?nez7 z?LV*8PNIhVdw=8{d8h>$8_M}Jbg>%*XK;3rHGU)zcC9&)2gR7X8oD_m!%)RlL~ChMQ9^K!ilk%5>Js7>f{Y z%EFx$?=Zhjqg_B{rtraZmtp$R#|}m4hBoqqvC`N5Uoi6|-^9H9th&+oNav}o{Elax h>fVpj?oSBkd_bxxxJuL?V1RJk&eN>U6l*9*0nk7@E&%`l diff --git a/assets/data/tool-ui/bili_hot.dat b/assets/data/tool-ui/bili_hot.dat index 179f9cdc8ec1512df672e27dd60efdb2b024eb0f..20b778caf9b88755282f4bcef66e16a87395dd30 100644 GIT binary patch literal 1411 zcmV-}1$_EhO-NN#RY@@d2moSfY-wL;Z*-Ooz<_tLiw~Zmm;cuR%PCWx#6wa6<0cCt zN|7{KS_x}d`y2CTxCUKQL59#3OY6AJn;o1=#t!Q_L&3~U=hp;z)ad`<-^;r6K;Cln zF9XziyUy*)n1EC&@!*bKyPRCe$q={Y1Pkael?K7q5!xXSfSw#=Pu)D83Hd#X6l|P7(NNhR zNaKs;vvX9NNDRyDkCpZEn_Q$x21;rCU;?oy?Jfs>su$}*jxECg*)l>@zgXT!Z*&cZ zFFR5h=DK0~Q7>DGvYiRPk51FRE!$jsBy?Pc94`N|bz5GMF=R>1FIlwLS_a>pkK`y4A({bfd;;vLM>X1H?Y}Qp7C<6#V9tj9c$kMj+o>SZ z4vMgq%WsHbldcqeaqLE!Pw&LN_6scQP+zVXo>+HXWBmOV%UPaCt*QNYA?+U~&>b2u z2|Y&s=`|1FgzjK6VKvre+m>SW7=;8TZL95b#Q%gsEL`o5IIi#gqNLQRCvOfHhxIW~ zJI_GB#@05{Rj=?5>DA{jjha&wzGm^TMTU8momDrB$812h7j`eF`=$5xtPS|v8+<-8 zUgl(y=2i5#;+?&r?983&iI=Ei2bTp?Lls`+sFlMuqfMx(B8lP>XRv{ruCQX9vb+;$ zxPkLzOpUjZU@vdHz_ISo>b4TKrL@g?7@=2@ks0_YCN&gA%3_MiE)kZS`>5ga>+|T_ z2L_IW!Vmlra-+DF|7J_f^TeeRt^XzzXP;O~#lcBE@oJZZlwLpi;ozCbMXN=u6AeVrjni4D9gXU-lTTi~ zrnf>44^@S10TbQ!h*lt~R$hI>YmJR2CQJs1rvb6VW~;zr9~wG@6Y!V}*uzk|Y^ff0 zLcNGLdRZ5y7$#>N*1Jkc3z z{ntO(u}hw<{snJKXdk3eM>(?Lw%(V)KDjj-`AZARK_^+)6~lnhOCskUk?hXF+_;6W zYJ7_&TAl|(X)Z0WHvt5yN_5L8Wvd~=k&`No9=A*zueX7lIcLrg?R!PjndhM8;D;*` zpD?(vpC4OszOrHZoe<^e?Y5(G&@c>n-ILfir2LIs;+f&wrAuYLRbDGX+78Ha4-Jm{ zF>z{3J1A(&KkD4QO9PX8&S)eK1-boUO{!!*fEd_~OR>2qhxLVpAjxlN@<|U)Gx{rW zU8p=!id2Vo&3?#IvOUm6lOjwJ^$lw<7Be-i^;)+y*f|3Rau`i+6B7fqm38U|J}D{ zptyT5M=i5`lXJi_C2SX%-fheuVKT*GSm+#c_L*me<8=#+(2<64*9qnXYWwf2%?AS# zzR#0w4z?gPmE_?V9v%f==MwIGZOgNAr54IAC^$(d*PXyZN!+Rrr%nT6%{HL)yx`LX zoTzzD*^Vid+S>%rBJtmYQ>9qB#@1sx1L0I#SKIV~P^9UeF{6Y>al`l~1iVvEkh?I{ R<2R6Yi4Jeqi_AMViEM1bvUC6d literal 1411 zcmV-}1$_EhO-NN#RY@@d2moSfY-wL;Z*((!{q}~tbxyZa(VDI(c8q&j8mlLq4|!)@ zACAfKz>GrH?z1MFiONQWPiEE$XPlQN#$D4xiPS!G1~kcD40jSvU0U-HV%>xqsrp*A z%kRjtK^Wz$$5B4m@Ddub2Ii#Ux39ZF=q!3kr=zu4mDvq>!Ms~14h}jh}_$!Nv24J3 z9IO3Oc7}Z?P3c2hPEzJ9D0l?%wT#!|sT6zOB(J0~E66w^+cl=6>>g(DaOQ$kK;&tf zQ=;^A1m}s*jB6_)#KB@X8bj2YvJMxq9*ZQNfceCGg5{a(rBV=C2eyFHLf4CE&e5Eu z?k|r5f=e*-K9N;hI=@f<^oI#4B;QD2`SkU`m98SE1C06I?xH2`9hfm_aSq?AY72n- z=}x8)BsZk(!vtg|2NPtpM03PQr!E9Rgy(b~IE5?q>y4s&8bUmea#vg9O}8`2iv;BY zFtEYm?d7o?(`0}^yZLu5R)Q^$ljQ>6A7mo|%y`EOgXRTxMqKNPZc8Z3WWeY6Nq;z- zfNLot6({E}3e{zI7;urdChpsX4E#MTzq*NFb+=n+O~iWvB*r4>k)}O6z@&&LOK4{A z0uY|d=Kr$jVICe&|OTMLG94t+EvNf{+>&AvjEJ{^r6ejZApCK z(+zF)tJM6#lf=~w(F|A-pP07CM7OL7S>0h`1N2kD0Aq5Uj9D)O`uko434~bN=ZLTkIG%( z-wl~Y4&NUJ0R;bSHJ!xP@KjR^>!mW3fc`WPchZMT1TC*1Mo}Ju##Fdo2$-*b*NiDk z?c6SzHcKewAUepGL>^fOx<6B<`^vK7<#C~4k{~HF5aX*I#_VO|A(Z*IYA-WQ|Np@M zD6f$0ww9o?k)psYF#^OX7#H+$+Q}?saYRr+wsv~^?rodjF~Y;io811Tr4x{$Tw#LM zk|7D5KqYTrIvS{?{u<3v(Qy+a2-#m7Df{~gV(2RP zJh{>$!D-y1<0>l|$g;JqZ>s%!dU2m0S23GJbfk-y*R)st1W1(<9|@Q6<=@bOeht=Y zJ}ARp-t1426jD&QM^L#AWLQ<0A%;(y{YJDIz+YPzyQ~?Ul)3n|+^scJDmZLrFQ(cG zoHAfPS+#d4?!DJXL4jA)(~oOVZP-M{!vPKTxHQl%hRe@+NeTipM`n%%9Paw*ut&P@ RH_IfgFcFHV-ax?kPFPE3z6JmQ diff --git a/assets/data/tool-ui/blank_line_cleaner.dat b/assets/data/tool-ui/blank_line_cleaner.dat index 6e210c6215953f0a8ddd38168c21da5e2bfd76a4..d1ed7b3ce1d5081bf8def1add8c66296c5b4e6e4 100644 GIT binary patch delta 2038 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 delta 2006 zcmV;{2PydZ5BU#}Ie)nHFpIn!PRN#w=@%kq998X}7o^rmg+}q3BcLze!iXYivIB_kZgWncrSd|4M=INU0d7 zd>;_B+9?hz zbQTac^oq2vSDuJO`fFy{vAtFJJGKu(WRfFMKZ?vo{#E4uf^Z}}D5Wx#0g5eF1g*Ui zJIwDnVSff5kIrKNE9_ZuY{eyE4ZCCOUMZFo>IqKH2B2GH1Vl~Neb4x-x+sIvZJfZt%WeLy_7 zp{dcOn6|M;kkJS5E?zlWk*F%F2nqRXhJV8|$%`^T^?LGw?@3eF9Y)CB+t_?nQUqK~ zB~nl>d$@6eGq?%U6luOo04zj{g`-Q2y$8=4zs)bie||x!(})W^NFwI~P+Kq_v@3Z}Gd$6$ba#nR2;qoXg}H z1gZnl9`qmchDU`1Vlv3Pm+O6Cft2EG!ud?ag&eyeYi@ckSoGF_M?}b69B9>PkJ8pnKgj&*JOKIbI>A6}dEu{x z`T69NJ@A!zu4#$!ql7yAIE35Z9D)teAa)?XlDDU=EAcAd3iqU@L9EG5et$XJqq{nV z61F&kW+NXa|`gFL)U0r*HpD!+Af zR%XLL+32+$wbF&-W8p{nmq3Kyt9-wgnJ(;CDnGSZ3W_|Z3g0=H3m_v0@VU?;5nEI> zr-dd!9aV+ks#;s&@3tvAH-EMX>QO%{vA`qn$~Ro1yu56kfnRj9p!3(^CW?KINZ6YJc#tB%5(v+0W8r zE-;k@G;DNi?a~I0IO-nh)NZ~QuL|erC(y48(7`{idw4gK#6?3q1giIW#p-?Uz zMm`(I_G`V8nosuqX4=hga5Ct93|BN+nDv5N_yJldF@$UzWU~YBRP26~^ul o#P>yS7T4xpK<+LWuUsL4>HKZo>c2V(Dch-3vr`uMQV@8&p&J0`m;e9( diff --git a/assets/data/tool-ui/calculator_tool.dat b/assets/data/tool-ui/calculator_tool.dat index 5508a87959ad50a675dfb76be49caf312fc299ed..8eb9ee5c70efe087f219fe3256c84474d649b174 100644 GIT binary patch delta 2022 zcmVGDcjeZDOypHgG0e+vePQjqCubj zpf(+SSUQk_LB(4iKDt63W!)e~70z?r0*;;itJ+CRdPittmw)j&e9!fq1sHlnPd9T3 zx>oPfr2%rj?;N@&^gYBZ-S=%^-g}3Qb|}I5bfU!dWr+OZiq4qF$HO%P5^2~5NghSa zanBHy;_zMMR@|q%gz<^NpLwO@8&!*td9icdfu{RrrTIU#n*r3`xUM|tS-Iu6-HC@j z&y(6IBX6VZ?|)CqK=I*$1_=w&?1U{A(C5MHG@Z6QAk$89nb@K;OX;62fKuQ~b6Kyk<{dB%1Y>8HjZf_$KF;t~%9tE#yv$FKs6 z4U$Mj9+2eIR+{O7s|V$5W_716WH-#uBC?xCvpv~I%70(4-F>SjI+8T4tNxtdngk;* zK?7-$Ni7w!Mf6TJ2gdWbQkH4sk#c#m4Bni_c;yM*21c=7G#+F|Ud{{UWn$=Z(Izw$ zmX3rJVM%lZ-4IUudHh%A+%(sDAJe6GDAPW4Uz{qJ#7B6ml)p?-G97>7k1Ab|hr4jU zEt(Xt@_&g;htZKp6*oZR13JKLp}E6(Qp?IMI$0O}4gDYd$-TlHVIwE9?UObuYF% zd<>i*=)^gl_;PBG{isTVxFf0;k6r6@j@1lXkrvG)*FiHXYcBWis*PYOU)9#lTOb#y zNjRT>!3Kpx`By&h&K$Of_{hfpmvejcL32QUwSB}1Rn1R!JzJj{ajMiyY!wzC!xFis z;D6HOe7=1LU5dPt=c!s6_7n*>auj)a?&*7Z5rkfU=%?f#X&MN?MIC5zjWK*q4@*e9I|)8-qGA|#c5 zI}M)FXjqlSIILZ`dB4-h&eH?J%2``4(|`F1yt2&bBdZ6(8NNkd@ygLOJrun==w5y+ zsNgk6FI3Zm%@dY4G%9+N3Tr>ZX)$A0^ibpj_Nn0XH11itg zlVoRWG~ni|n5(Ie`_?bdAb+apuX2{!1AvA~QbMw|YO6Fo_ukTTsoUJ~dTuMo!GA2# z%O6uHdYdIh<#Hzjv^3KbQ1LxRu$lafouqP)L@-;Ahtn5zatgcwQ)%B&lrEw#tY=P) z%boErSpI+*RK`#PqewR2~0#KHRDHhp>p?^Ri2esJK%o353D;Jk5q8+3ln$LR3T(fT_T0JkE zCnaXNo@2a#)b;g)dZ=F~29S_#(WEy^1m|LtU+xR4LYVpYifbAWNflm~lQ(jd+({%C ziik&)c%o{7xm2gDbfb=#`~+Ps5r6e`fg$-z3Djrhm7t8er!Z@5zz0jqvVU43!ZT1E z^D598zE8_^lO3gQHZ-gC^@?*2=nMoG(7=@|Gd<@B@P$TnK(5!(;j_T7XKi%pEz?P1 z!I5O+BT77|pY_OD0Yi^W)y&A}-rarK&}dIKLh7QrxiS+hbKTm# z)&!~gvvc$}`0UrLZrOF{7%8~d)wDHI)3;$qoeDlt}4jq)HumB*;L;UVqH|SL~ z;j66n$?}e9(!(GnBmxeEE+(`gc*u^5Nge>^V0F&hZ>ao^ynpQ0T}JZAefV?sc+Utg z1p=cxpu}}XLnT+VDZr9*?~)}c_F!Y?^81*Iul`quIM;x@hRz8YX=1y*SUb6SQ>gY( zFkcTcwMuwnWt|SMMRDZxuD0f_nwPC1kK4KDzQB5o5-)&VY$d{>Zq?nbAa#RT4v@GS z!Q)SjtYXVk2463|d#1NjYuY;CS0NWMMt_@L<31tsq#2^epX$(AjguxGaw_seXoc2! zHyMSO1Lzi&escMYvK(e2GLjb`gN6=HLJC@hBUETcEaHS?p^cXr6ZeOt4^3qTk)(fE E&-T;!CIA2c delta 2022 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 delta 1377 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 N{8XtW#Ge&&z8RdSHFp32 diff --git a/assets/data/tool-ui/cctv_news.dat b/assets/data/tool-ui/cctv_news.dat index 504e4b43b093b35e691d350c7840de4ac3f8bfba..5de3da7d1ac6a80e4aaa2e4b4e5747cf221e26ca 100644 GIT binary patch delta 1345 zcmV-H1-|;^3gilqG=F9){xBteS@$m@z z861F-4Bol)=nrL}W-HW4hZTNXR{~NEX+ePiRPZNbhke;Pxt?xjX5m0tD>Kr(hZ4t^ z(0z+(t6Fo~0_&gxj~&C<|gTb1#n<(AYV+h!vD8D&R{j-v|1FX|kOFPexU%m$%Zb28pYn$bxnNE4wM;c~SVkxu3>Iw=GD zd{RU*VSmeQE`PK^Wg=c;C>g1gs1{iRvoZg1NK2#KERj$qz+Sb7P239CMev7g%{6N@ zd#&((O?0(Mqy-Axx^h=cb2xQKIVi1k0UH8HjBy;p|PuPw5uMLqv7l=+cG z3HT9My@(i0ujP=-;B+y+Q-w3dbG5Z;SBPQ9BYaKHjDM;md2TzKfY}o)T#Vfj9EYb1 zw1Ju{WEnm$EQGmik+6X0A-0}YR>Dx~tE4IF>+#e_b;zOV`3gcH_&CzjAidAaBEvjY z0aeV_Mq!cA;#5uSV5kOvc;xpbg!#6Ac7>z76NPQ=CKPT%Mz_aHZrdAv{VJvh!`txv zacOuiYk!$Gan~pOtNs}KN&6#)rC}`;?XeGOW2?`+fp*<&E<-*zy|m<&lpk_6L-Z(b zaDAW8-`!&y*3PdL?ypu7;p zubetJs-|_+Okvh1F)fH80QpRWX9B%T``@N#ciz4oVhSrHH0dt~ezY^&$&g966KzAjESGQ(gWnQY@ zK7VdWrK6w%x*3QVVDwrk(PmTQG*Sn3c2e5y$@{1D@Ng!TkWbi;W;iT$hW{7yJ7*1U zGNGZx;dnfl%!rUtY?D$8)mdOm5_$DdL3F|Jqt2?=Zm(4kG?7+Ywe}P*yr^OfO@Eys z3MI&4^*iFA;kJ=fgd5DfMbxKKZPune(SND*(Dc^_~01L5T5eb?0;;7 zc)D^|TU{f{GT3fKt=MFvZ{!o=x@s3oqpbnN|>rXjj|3hW8)mnj_eVt1ygBdfXfGOTrZ;y z1kr!d&7t^+ar+7XNMytI?~%(7cRk&_a!pF&~e7e DEnB1w delta 1345 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 delta 2103 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 FyrdK;20j1) delta 1587 zcmV-32F&@J47&`F8-F1aJ<*h*{FF<>ud+hzW4w~9L8QNg|F)NYF6JO7=m*)q)oRrd$e<_!GYj#&Dl2EeVCacy_sxlYjpxokap_le@mY50YEv z$mXiO&fxFXy9VPNeDBXyAJdd9P0aTa;?i*jpsi=|0Stah@iw*6Fu!~MYxShJL7?0g z7)SeGj@vyU04|A*^kXu)79yzcLgGGM%I=ns!Q=JKbRw4u1ZWD75%jAJRk_9gmHJD>OuK{GXk&>sSkRA_r3P8bVgDZ7dhG z3OZz`90oKc$mKHWPX(XlT5N=S`BABGDYkr=UUtH-AQyA?O{&HZzd<-j@@g7cY`O1G8~8CI2pDgGirYA$bKvetSwbnO}% z2&oMJLB2()n3DGA4|UCZfbgqF=z0^x>PQ(qZ`r7HBN$jhIuHJ-HLCf$E8EJ|ea zi$~&pz+|!sh6#I%D%8LJ^-7;pJ7odQ-JN8BhkyH0Y^eVV%PM4yzOARA+D&fI)y5Ml ziRL85C;Zn{J$;m`81=(@GqJ=w9z#rycK~@}Rs5EkDder6%w0ZeRF>Y38Wm3M>U_`9 z;mP^S^03S&|*fMRegVLCf~ZP7&?Rn&wreV8d9O%QactsOb<~nE^Epe!NMVY=I}L4 zj0XjGbm&~jc39g-x)Kxxmof6Mr5un%3Ke619@Rb?0K6b&iZ1xERd^l7A{Jh_Jg9wl zd_G1{%%5avOZ?q~*@`n%WD_N3z>vO;>18u}aF{``gNU~L%z`rm^tk=Z`Yg|zw|_M? z*y*0EIQ-(773)pqp;D@}o+C!nd#G}<)f5AP#kQF|WrZ`>nr#?pzyit^(EJ0``Qz5#8qpulIe+;%ZsSeBWMbA606j*0#sU7|g3d2j@?*w{`*v^4A zXz1+ee}QRjDf)OX(4hnJxk1TUFn^$y&zL74oXW0)(d2w1Bzz8Mn-t?bCM}8ezt;S$ z;nTNS_|ok>C}aO1pDCjyU+Z7@{8vmoA2y5lb~IylNH|#5P$dR!)Kjd3@4uYLjql_n zSSy~yY8GB{z}=@vacuqik(3L>*6-aIF@RITF6B@6oY$bNl;n5rn;oXM(0|we9$vGk zPYhlnc9MH=1Ksk&WohY)*Z$jZUUVNx87v z^Bc*K%Bx_N2*bv6$v=J#nUN4AYF>wOiI4^mv$g*N4G>DfUxPPp`@#)tGfR!hqN3FE z_U`7NhVdSBO?;UL4C101$K!Lk@c$<>MS9zjlapqkhGZ({FDTkfb1Zx0b94+$FWCu@ lE94G#Uf_|rmBuRhn@L}H6ZP=0n968fw}XtNq%w0H)0l=;7G(ec diff --git a/assets/data/tool-ui/color_contrast_checker.dat b/assets/data/tool-ui/color_contrast_checker.dat index d395269b92dba0adff998b3e0fca4e41f7fa38a5..a807fb42a6fba65a4ba071632a92c439fd4939c5 100644 GIT binary patch delta 1990 zcmV;%2RZoh5AhF>L4O$o;el|sXfWRus0z*@z!sS!&6t?M$13AdO|HfR1GS8iFa*|> z8V~biC3vkqR=|gKGPC>yQLANOVp;w!@Ud&b!iVyg+sYj-#mCN*5q|So$_G5Pt!eT#u^RWb0-GNaB_RJOI3f2)`}!Svh(vV#fL{`ZSsfioY@_&yTpW9C8{g z6*a|O|BFcV3$cOWA*m8$X7-+4oZcA@aEEcdKb)--rHRgtJ1(q_XVTFFruiQ!!s>MVi};vNJ|>c2_>Nq6G?n|>K1Vc`P!5)SMp=}S#w~Qc$6;-# zzyvgSxPL4QdK$ME9znthERvjD)&Vj8w|TvCE>;E-UZwpMB@Fc!Q!Fif!{Ma^6x>*S zPL2Rcq<5HYL?)li;^m3KSEdNWKci8qkFA_D()fD=%WjXUS^ExS8}{>wR*TFwmSsi} zn4RVQl6TYL3EaKbJBcF&&BO$HQndSRDU0qX2?^gWNk*|ap`X-dg-45u@W_& zShF}T$gTFl&z<^CIIXsX963Y7uKyZaROFo)Pvb|-fk{?%>7kG@%J`L|fIb(e1o*wW zQH+10R9b)-&?TU`LRV$M#jWQA25~GhCxI@d$QaEM`j<{kut)Y~%+8?t9=|ne7FGJN z7k`Ea_R!2rvkJQRU+r2-E%Yuk3%)PWXVu=AgY%~6wjOgqN>xiYP=-1{I_}mgWhuoZ z@6sMa{<8;WdI&6?Ktf~F9M&gFv?|(ZxA=JdSIDHEv^S258t_*gOByEe7C#DZ# zsEbTo@Y;f~8!Jbf;yt!L=i>G+B?KYW0e}A0;S<@LOBC%vUTvH!j1*lplr66&ZG?># zq&FpUTqM+;O>fuKsCf2l)N;6;QGo@0I39DJ@mK=Gqo-)~wH*9@YQlaz?NTt8WYXHB zxYo#eg41@Vs2b1K-f0@*gA=5l)Q|jXt{hcn}*A+x!Ir3s(k|XceiIOKkc;2Su(3yxkRUl{CH) zNejf$=YvDcLzj!?!_+4KkkdJCZGo7EKwmU(=;;mD*j2-%#gZ=pql{KKk_8#!016JdF70E7^wzo!PF-0NN-Gh2lR?>5rkn`WNMhg4J>#`F zU69UD(6ebPIoLp(o7Ii1xhg#u6UTG0WGE{@=hAP<(R6zX&{*b6>;`~sTz@vo`_G-? z!lRTsuI!%$8Q@j>X@)Pe{;)^?q@~f#4{0E zD4_Ab?!Cz}s=zqK286*lpnp}?ixVjxFb|q?=ZFTYP%j9B=Z<$!y2KR>S~1h9gZfFI#Q1W@--9a670K+lE2J7grLNfw#InK}pF&U-Z$rv%c4 Yfm&w9TSh@O#^5Z)7z$^wI92+gyxYjo3IG5A delta 1990 zcmV;%2RZoh5AhF>L4S2QR~_H*G2`~V)n8nm#(jrq{Oi?iGQt6G{ftUo2k%TaSjwb( zMHxTF!W+^oBb>L{8g>e^++wMY)@S9QAIdsiGp=vYj_VmP51!ZSf;wM|;7F&MG6H%b zUtY^L+GPx$>3Vo)uLI#D1@x~hDXkdSzBej_n@B?x7F^=#uzxP=j(tP`Y({)gwoGP8 zF-p|@JFNjiK#Z5@XWgc5VXNp!beY0MH3UuQAVi@zsVN;DN`y7(z=dj=G1Fv$QQzqI z&}^gaHn2_n23^37HfOHURa`@Xq{GyO@;!p9Pj`2T*y4RSA7=d7Ab>thKRQ{jT&Vcq z7X?fYY9eA>;eVR`l?T*Su~j_f@yo;{N88jLD`{}`J&J6C(Zxdkbc6xTJ<&1iU0NpL z^sj;a`N7Q`(4dAm(hqdJn_%E|>J2^iQ-!k>ihz|ZJY_gICZj`3r!DihM zEnjMd0?1`RySqae_*wGg^E^i50mT=rV_n2mNYc-qu>6KjD4SJP(*#Qr*hUO)nBDkH zL|Fsz>VFbL2f5m9)GRX!^8M1b9-hBZ&{Pt#NYcm0;OLsL7IM7U4tpBer$0Zer83KX zxVfzF4u3SgOI|`&z?Jb`#@b2N1&v?J{Y5t5H$nvg1%VD#MKTKhR8Ql+B^R5oqxLDj z+%IK?4kmO}+IY5*0yor;K4_(nx~@e;`}H715`Xz|!sM-3uK)geVPRMP?z{H1ww*T= z3}t=xmtXGh{<7O5938KoO=_WT=!oP7*zZJuoq|S$@vpH~u_Gwg(Yj~)nJIKETd;-B zP(x&7Pt6G^7tmat;Tf4w$5PlH_JnPuFKN>STpotmZ|F%!eW9AyVMqNLz9@tj51=mP zihmD!LhuYM_eD2wp1vM_TP;&)!@rNER+V*f^*;J6Za$GSfXN#t-s3`(y{KU}`vOz` zb{G@sM&nL{_e)YX;563Ot8Au^cClw+l|&J2t3vpijPBh0<<-}I3GIl-^4RROY>gq% zuREpuL!0@s=l_rGOY>zd@cGLyX8cy-1$uLdIv+uP_7p(V2>Cjq&U%PJQ7~ zjl#@Zv5FM9EjsY})$Bs_ByKub*LPeA6vac*XW@}+oE3-ua~?ZR-7^Y{yW^Pw*nc(2 z&yH2pnz1ryH1LR*7BYR6G)8;Bg8yr5wHJW784&^P(I|W#d-%0JwHSX=_sK3a1k^F9 zfZ7&A75=&c69gMQffXDL8A2sYDc%ea8*#eS*Wse~FtCbMNq z$#38N$z#0(u;5Bci3WU6@W7^e)|LgGAp`}D0NF_6Mtny_ZCPnbDib}ianS-b=)A*| zb#;*n2E|EY8o6Fm=x6#cBHZG$gU~$Up=)!ZlFQsM0NNCm>ODI-70Zw+M}G%153z1b z?ZNkrCK5TrDP(jEotII`AWrU*HWqe5<=fa*d8+N;NH&Je*1L2ad{Gmc9)rx2*}j z9G=GLW}$S%JwXHtu8L)x*?+jtQ3RdlT{T(XepG7q?r1-}CqQr;u|Gb{h7#6@u~)V( zKPfk?oJ!>Kq7n zF7CD zg`#3zoQ43fR{B4Rjo$Q@rCLrj$AtLsy`9*#-ildKU;}6^c!}It=JVQ~#o{g{Mhrro<%SF-hfL zcYiKJBb+-cFF%79xi!cPCeo`O##)`Vo751CwSPhF>cjkSuhaPk5@GLA=0&9XDK1OD Y>YBHBS!@14GW^{taX)>ecj{(6pa>V+IRF3v diff --git a/assets/data/tool-ui/color_picker.dat b/assets/data/tool-ui/color_picker.dat index c1b8f5731a392b71315c225ad6aff4cbc31ccc01..63711e66afa6d48a350a3ca324439229724ff8ef 100644 GIT binary patch delta 1942 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 diff --git a/assets/data/tool-ui/column_extractor.dat b/assets/data/tool-ui/column_extractor.dat index a8a8165203dc2e5e73322ed34d65a57992378638..3e877799cee365706671adeb7e1053ffff14b6c7 100644 GIT binary patch delta 2151 zcmV-t2$=Va5sML!JAV&ujSJQ0c?+y+!FI8Y#;!X#`^KmHqIO`gX1gNX`Z`9pLqsx( zplyp!?+Q2zZ9U``UJG(dQjnE@p@9D-I?gtU#O}yI-<_!Mpwh}Lhp@k=AmQFfJPRwS zJc~}DV-WsU!xbBZ(8Ukk1ICD|LapiUv6hj|2%Y)V6#Ll)xPPa0aL)A*ZV-r=Cx~MW zex5!)x8AMC9-9QQcsE6sGk7Vn z9;*ZVETy;kyI|L?`wYM~RhO~>jRP>)*T1jEuEZ_rD1TsLRtCicB=73o2{FN$VNrvn zK&w61{RART_Km30I3sP2|25HG2%dkF#z5Qfl_%V|GfdhK^b*Vs zgvimdMSnMWNYQ2A*q>$nxnOic^}JXL@PFI|aNn{Lc@#XD9J1fcdTmWz^T<>Rd2P74 zcqHGRI(iojShB&q9n#H<_Mw>tbMKxf@*K%@{>ID&luA5B7DMF+?8=*rRlnLM*lhp7 z78AN@BH7{KNIZ_=KNGX%t~~mCat+3F3B84oG#9kROt zbYntzd2m3tV$C}|HT}E#e&ecalwH>~i(+Agh(Y>HQqs9YPKO)TiZ{1rlGxo_i@#UF zQ8|$(Wi|!9l3i#id2fWq3Px~vG7U5S&d`>MtjCLe(@WLmz3wDKgKrzJ4Kz1=RJ^R& z-hULImymvAZwhTX8r)YL?>~=H>2s8ASk=l<&=|tNU~m7&J{Hx!9o_e!nJIcVmA${J zBp?El8Dre-+;U1blWxi9i_cFX*5LDq2IPHWjT(Zs(dNE-t)b#TlxSEHb`}dOGl z7Ly$o@0RTyU=Mtbq&d$bsX|5ezLqb|?teR{Gm7Dn0s|R25rQ{Ca$DQUBZ1~-3j%_f97iW`Dn9+&v!sd>+q_sY5yhvb~34!!jfXjJOaq7q=7z#RAi5J8xUoAc2Nzb~u zDh0U%t&rv_0t^pQH?|Lz>LNrS9=dK(W)D?kvgNP~`7?toSDnBz%uFx>@8qVmhH3<^ zjegCwQU+B@_Jw%V_hsESP#XM7N`EQvzW^7L@iL22g1_u2b22MdYQ7NaczH$Kfxyw( zIxK2{eCrG93adE3yUTZ3@8x4+npihCAF`e@*Oq{BUk`E`^#hd7;*PqjXE{ z@A95V2gOX3qn^Pf$JzmI8h;EKeNS+*5#c;J%5mXR;cXzjG$2$tq}!YZvYcK(3J0+C z-)L6<7Sw+AW~Lod0P()dzY+bs8tG5%SS>Aq+XAh8&t)<{Ba^Th_N=tt<_fSS=!7?b zl!lNJa_BL<--bQO(qHkEZi0X${YK8M^JqZlOAK>c-R~~vVf(8amw$~WeIPbbuy>SS znr>IJ-@4>f;y}s^fn)|}g1A{4kgEU1m5CAcdBtBwo#SM79Ud_PW;x6q^}QQPA9;-A z&3i8#20>fl!>&<%x+ORPtCccQdXeQ^#-#N=(q-n)QE(qy(2wD0+y^<@LbWL=-}CDq zPqyGfrqbkO&loVR#D8xv@BUV1oZJbji)-np zt-P2WyD}Dk#3PTg{Ww}{+6>EoN&jR8eOS0WERS#%-hn}vy`z=pWoYNF$UyxAfI8N% zQUm%!i85#Gj@Rro6cm1%dZbKuY+p8o?AqnzAFoR#sh`~4S$|n)FyfTfi0*-s+ZphC z!KO%R7{UT;x zEUbdS=%n#4V@qVZxZ_$WfzV zGWHu4DeA@V=^2ZKea=F3u8-b+#X_wD**HVQEwuZiO^HnPToJNl; dS?o86N1!5x4kz4J%YaA*EeMPjI|OYZWzR5RG0y-1 delta 2151 zcmV-t2$=Va5sML!JAY>=YK1aPm$g9>9{i(Lj&C1T(3<#~ZZgL}H;Wq$&U?SnSV(5OBx3roCM z>89aryL_BsNi&A2GAMNpO`(#l9u8;4#!R6RLOEzf##i`W4KT56t#WMV-e=~K_lKj& z@p>6ON{+i`F&5gL`13+WE>qtu24qp6lVrj^_S#gq@7h!=N_A+ne)t!)x_XE%>1Onx zdej`#Wgph{dVekkN|17sx!6S@`@hm7q``;Ru%2H@VW~M|C54X8ax!v)qu|?y6rO>B zYqA4FX`35lf+D3oXS=;I+*#KM9t}Pt;J4(}fIMb<$+<$Xf)i)|sB)vBl=wbsEC};p@0x7NFkE1s2=9CYQI&O=H;VE<{GVTQl z0}YIg6ixfn_HcWj+sR2i%C_aIieT{|;{ySeDEyczClM%V2yt*Yl3L-f2XjZL4SPmO zc%TW|UVr>ChR8nQ@sE+W)FowC$7}tE6UXuC+i`6X(ksQjOO!?PB!lO z%6~t}nUX|S8q0ze*?+?gf@jGuMdRKIj-SJ8EeY*VN{L=KW?WCXg!OH)$>#Hmv@yCRf1sj0yeM? zQi$Czdx|e<(~o~|RmOsK1&2gJ>4fYuiD%ikFuJUI@~D}|{5jkSol9;1PwysP$$toB z_=g}@xYkd^t%%v%IfvcQsYM>B=t$zTB7_>SQfuaO)ov@zjk;!qVA!`r@m6MV!D5B4c z>A&hN7*oe9@M8iLRf%a`O9hqdkXTb1KHf%rr#Q&eM`=<*$fR=R_78nmuz6XpOe@~ig@#sQ1V_c%Iv-2sC@WKz7AFt&Ium*!3Dd__AiSQQ*ykBlz(<63p=fU z_C_aXuU$!CDKbi2jhj^{qDehiw<*N#+VeFWAAV_yrY&SBaIk}605IR zabnDSzyw?HHasj`%ZSCCoPWBf>+@apesQ=LGq;b3gDS-_{|M?-e(LQ>E)w7WIH4Nd%S3kr`N{QsBj6A^|OHHQNH$ZF?!On$AkF+o?h-!AAlNqn%*xW_E^yl z_`2xSCGpuEX+a=S!3llW!PWNN7aI`f#81@tsAHuh$rHtWDS*@M_#t{$2Eo^QI1Vhj5N!YEREtb;j@F0147&d{>a(E)!q~%h0J7^e1KD%+tq$J9bO>=?Iz|tbefR3U^ZVJ!A$DS=`mT zsKkIWP^>H;b^h>;GP6mqWG$0PiHY0e$XSZX{h;E_UX0LHW&XR71xwRs{6h@|8p^>^ zfSc-^u&g;&ADd9AeQj~IowD~rKhNh(ZQbf!ujj`kbsc>4M&R&ic`PxF#uWf-JGPsw z%n6IF1<(lC*?+$9ZuPWw9<{}aNeaW`rfmCTeBA5+EWX9# z+1V{jWw1F;aiW$Rjhyxtm(G71wmeF|i{G^KBC+rCZpLo9RqE4YfQrEg!>}pnLxd0C zK_NR4%A?p6v&!;M&vA_=F$8|tV}hlGu1t#i>xT%7|6sYO(ZUtS_;Mp;geMYYpLB!i z94Tk9^KwxCHKhXBoJZfkO(rzpo()RYJ$r)Mpat*6=~l@~VHeHYV??&| d&M`i7lUiaRr-mxqoM0$@NA;R1jzQ`=mmS(QB#OQ3rdy47v@B1l1a#ZQ+AoLy7*Y75b+*2J>lRj3xRKp^{A493F$KIO zQa;d3j`xVrLVvJ|{u=%&s5V4TaEQ#q1qoU~6U4GDpDTcKDZde}A39j0!yVRO8LIQx zc*VBIlT=2l{dt$r1ha{ZmQU2i*DkFji8@0mtIR1EXC30&8Q-W>`{^lr+~!VV&bUi^ z#Vw9)E>Q&yc51INOSzo_VleG^d-MYqOU*2+CKdk47Jq-r^qV2(;`kEZfewo3;l#87 z%kl$k2;-3fm8cVO%)(`1;8cCp_mIN5wq4$eS-t*SLnBU8iVHv%-t>EkT}$jqCN2KS z0oF)V2i~NbBG%SYopXYD&N%OPW$$#!Uy`%T4C=BMK~_}DEN{Pex}0Hs1*H!JyDHo1w1s}2*1~fp4rZD zzTlDTg69g;+1Sv4P};uV5h)1B32Pz56l*7H2_ynoIIoxB1^-Lq<8Bng)fd+HB=qLo z-H{gckyEt8g8)!3iq+9YtqWq#AYD)dkZAr1>3^AAPqtD<#*n&ht3qz4hxgye>nO8p z2nmmgF`C~#M)|rYcA^54a2h*07f7fBVb-{G!T)qK#1%HkeGf9HZLXp%931{I`CVGNPU|80L{2PMwJ_<=WXR333f!H-$%!N$DTr>zeDo5&Y*mk*#Cvnpj}w_@KZ z?Wh3Va@3aQyznDE5e|{0K<@y=+;cMB5^AhlF4PVp?3?`^2=J6WFN~D7otE!l zf@Tvy|B4AQ&i7c}E8*u=XU0vZv^A9$fCF^;SI%%35P+zhqUj z@ktU&nS*plKcAoIh=pvmZA!QC{gVSzSwN=^mHImqSTj@qfNC zUkZtXLLW=Lpnf1DHz0Vtgq(gB>&$nB(M@;^ki10zrL_tIVKe2$Ter|dj9V?IBqteT zBI6w}Yo`8KB5;%m7lR7MPznE%$>|YDU2p8K$jnU)hDJ$r2knw<12*e*^<>y|4nd0>q{JN zdG1lrf=sQ3vC!CiZ8>e@T`7u#Zr6+d+ICjGfHRy2!Mc-GSs%0| zt@)(>YT#?R?bGhY){zX`2sCT~xbmpo!bDZ%2#Ht@47jDdcO%Z2EE{Z%?|p+Znf9)q}1rU>$Za0y~~e32C}^<>_t=J2D9IfYme{gwnY4B` zUEV_MGlWY!FmWY|)`~VY3cDLrwN#kM@5@r;6itxGya6N>dVkInDe#0;2?>m3`db)A zA5k>fV#RdNb}Z`AwehIk+>EeYci}tIjhWo)*w{{r?sR{bNdL$M-AB}H-bfaA9~ygUo~+;+U(@Zh9d=6Nv&qm?@R8_W@fDt<&RVC>2ZsyovyYo}d*0 oe>=g1Ow7(9cdOChUr~33$V5G|2H9o|v{DuW+>W#}i%DNI{QDv7)c^nh delta 2006 zcmV;{2Pyc05P=YoL4Pp{JNc~d?grfRDsNG06Yc#HL>kfrTO&?%ZFEkw1Q>}J`Q(d z*#GQ%dX6__Mt{n9X(T%MPf2FGPN^@(a`Ob}Qx{A}@yj~f)G+PKmk!0Wf0gDoX}!{e z#G&HK!f+KZpBs_$=dVrN?}^pK`>lRI^V z**H8Er2J6=ZYyj{j}b=ciiJMq$M*BAbIb|c#RxsWw|}`l9PqSdYo5P1WGRun1$%N8 za<;DIu5-<84f?e3w>^ZxXt_qHbP;m~HpPw_P*?AR8hbLWp&qftQcb+hMP6&z3P@B; zyh1$XQ@-Kg476Ec#;*#n6)$r^FIpd8G{2|o_!Si(UY9Le70U`hTG9>eyGy*Ty}&kS2ss_xf^nHqtQYlVqe{)hso~@rEgh2h*Og!7c3J?;4RT zGy@N46EFJ(*>I^=tam9bbr~>S;_9iGzl!a05_l=?9s48<=QAB zP5G#kne!rj`rxsS_#(8?CBI=qo42K?T+bbrW2j+>XGsX1_r+};u`b0WW{cC{TB#=H z==Hh{l%yR34nR)){lZ@do5ukN#I0E#0R`o8@h)RZ0jg$bgc5$>Qsw7kv@=mE3%ob6 z&3~^%R8Vf0dfNEGKEXml2lLivehV0W@8y_xauIQ0fIyyFEx@LE9F`y}DzvG&mK&*$ z@q(|dj9F~9ntBK$;5?9gTjteFuk}mJ;Q-RGO^U-!M0km&ZGH#f5K*EO$^LX8`mC#H z>jhF_i%*d>4XRxgvbqe*lv@UYFP`cKEq~WzbuwQE?mqpAS1npgh~Bt^fr|^R48fUZJke--YKj3gghZcph(H0S*}9K7vdtQ!0=#u6%LW%!cflegRwTg( zhLzF2LSQCi?12_z|74-4py93(G{ZTu7nprSsnmmEQ=)qu+`*FUkS^V_fnDe^bbrW< z4i@F5JLwwbdVzNDT>|y(bDi`Bumhij!2k33W2}Z0&~Z>%voKgr^DEdH*252jt2Q>v)pH$EOXrWf&zRm+8Kwbc$nwUT3eQ?Ov#_=jCDTgs*P zKl!p+pAM{Oux!p0u9ivy`F|FtD@8hW!uj(DMQ}n(lN_3 zv&7QesgxHcxrq*%26(%C!icSL!hNLxyDCy3qE`R@#Odve<%LQce%~i`XR~cyY6~p$ zv}sC)7Nh6KaANulVxeOCUO`uQ0WI~#2yflymLauiS*W>U&BqxF>d&;Lc_t40Y602q z0uc`YkRK&Z==Pt1$@EYN2Vf75WF9_*w;*E5?egq>l(dnfabxXSHxd71qPB{& zkY<}vE3kjQq<@(saYQ8NK>}6wjwo`2KAuO4mkH)I9%GqMwtt(c%lKSEyx+`%XAME! zr~6}f_q$UWuD#whP2uK-ju5WSV<(O&<^`k3tnEJ{Q1M)v=n@>(7sE|FXZaPdX?6>Y zrzY!fP<^6%z*~lK$rh$%Vl^7?)~lC?-8D_=9e#4d>25oWOg7KobN_$le(^b diff --git a/assets/data/tool-ui/compound_interest_calculator.dat b/assets/data/tool-ui/compound_interest_calculator.dat index 41aa443b963547f7e09a56944f3fc97fcb9fa038..1a871efb1bb3a13164947ebbe8ecc4f64a70b572 100644 GIT binary patch delta 1974 zcmV;n2TAzn59be%M}NOONt0+Aq9n#DbhQ3w|NY=8kaI7o`6Mxt9H#Gz7W~gDb+T4e zt$W0J5F&KT_~jabYoF_{u_>k zxNWVn0ffAGs-0d|YB5$~{f0~KamuQpV_Ni=gU|TeyTFQ68-EeVTxT%nBF68KxGJg` zB&v9u!1QZW^00T6hiP@?9#g~pHcLH4WGbiMK=oS~pNoomJuqe^ptc9MK4#~omwJy6 zytf*K$s0QwFWv>ttV;JZYr9e;;*lnGySw6_%8PLEeX;7C(y`Mh(m8DYPYlS5eEgF2 zLPIMI2P)#eTz^_2r=La!!9uWw2TcTi{WZpST?avRIw=}oZwkayd1dx1xQe)-dUT;v zz-`M;!o{Lrux7)US$Xzre1GPSDFDR^k2yRakBE*tVR-6$ zz)Rh-y|iR~8NFmm+?$^07Ep7jx_whNGv0DeX>!oQJD+skuHUP+d=TfrmTjNDyDbcE z-}oV6G&BsbRZ2Oo$bOcv2rf4l`P84!y4Y1KJM%lHw-A;048atgpdiHbF7%`aI7;SD=}^3aTXez!1^-?E6B#=&Zm@Pf!SQ=1F*h# zFn)Z7{EP<^TrDDita{cafjmCj-NVs1;>S)RXQds#ZJg<5_YL%tbq4M)(d z)qhMOGIxwofDbAW5Pbs5DpD+gZJ9f`pXtO=ow4Kc%nPz%b5I4ru-Y*C1jAr88hHQ0&pVNm^+MUc&H1FW} zygqk&)D#8l;t=Y!2Q1J$59hQVBZ9yQzTda2$K`DRi8ViW#QFcYp5YjQ$|W z_>*p=p!S6qwE!F$oaSEA>HMX(9%VrY*}d<7d9~{Mquuv>7cq z?Zm4`^pgE**HmO|bbaZZ!mIR>Q+gkZ!(!X1;V-%GfUSA(JJ_h3T@ruPdDGv0>%zKk zRA{2vlPv6){Cr`rkE8iuV}F_8gz%BC00GOL0&U`8 zVAdBtu`DfzAiKOt+ZZe5si0?6_a-jK5i50$SBW&!ZB|J*hVSC!4>$Naz(NX_rVhy# zc>=bsy}*_Xi~gy~pSVag9*dXhql&fGQ_N6Aq6mnZkt1u+(R6H>TYtdiYq#>Hxq_te z$XvP0V2|4-)ynkGR^o|jdCzeD`I`5AVVQC@adEwV%73ZebX?K9oPly`V_vUy>i`Rc z84qZ9C_q-l2O9ZsLnhPv%}Y0AoQxlS>pHVvvzGf{@9a!)JC43Cr7kfG^Kc%GhJ0SH zhOvZo6i9?l=KF=w>whAztzJ8J#KfWcd!J2Qx$G|Z+y^-XYi(S1^HKD?R%!X01^k?Q zUWap;MZAr3-ZO8HWBM$e>D*0Gg7?{@FtPwRe){=@%l>SuE{O9;8c}`4;EyuAXyF3o=xj=*e&giw?QbYKHw1pno@iN-VC_aUQ%PjS=v4 zm83(WxV1=UpmzWz5j&S;JR`NzNNKEvOcvAg2S~}No=Dck6NNRbB~cU4?w+}cM#A(l zY*3f>artqXcu}jk=#yrz2heiSEzUs%NH9}BBOK3;WeYKk_k2dW{l_`T`2s&FmYMnK zg{GC?CcFgZI4}7S*P*cQD<*L_Y&M?Dh#{)h>W@5{O2|7$7Pmy87t_&fvTuD1@h0kd IB6;N0o#6ZBaR2}S delta 1974 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 aSG&U{ delta 2200 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 delta 2119 zcmV-N2)Os=5atk&Hh(9*o66ccRfkkLS{&G<_j!J%r;{MlHkvxHJFw)!TKu39yED)=bNRA?MpE>~P4DLa z3~9KFoPdqS)rsVen6jrH6nj1&gpms@*3iY z27XTvg0mA{ol3+Hs^y`^g6+t#cDzV)^DK{Sjg{tT2xR2C7z%~V_X&$`=TW;f#{h|9 z=`@(1xg-5_oqyx_l_qS534ztJK4x57`#?<@X!gv&_XMtmJbp6VT162;FK{#PN`6#c zAK?1wnd!_2Xs}=50!%^a{M=}*g(3(f7G&AowF&aGDEXo)726CknXHRr)#i!szy_rF zp$gc`qOb#T*1=`%i&N5+4{q4%F3@mKzBNFt9Pk*hLrz(bb1mdkTCEj1CzhSmG!PGd7-I90)ppy zqPbjen18C)&Gy985EXm9&DU%MMAN#R0cfle3TBFIzn;XYGZnuGadA%YU%n*7WZ#)+ zyXFMA>A0o|A#J<%k_RIgD%tx$&x~#5Q277jF*pk+6_q{v)%8vMbmIYlFd1Ki4#M?6 z6*`LkloXR{rpFRE`tg9=xn*S8Uk(KZs})k^20~eQ*UP zM5dmA>RyHm$dOpc-hT{OT=OdYK4)(?fiZ#N#X`;`uHwArFFERvyhAtpt?K7*$F=+p zw|`Y}IR7?kBR$A*?V6cPd-r_%s>Z=Tc!g!FLz^>JyIakv*#TG9d~x5D-Y1kU zP^c?oV-?m9XVM~{kh@bF6Dh(PSh+NxdO7j9X{utzYqg?=cc1`l=9QlG_@_cY+}wZ% z!6GVok+Qim_A3(+vH^?WU|jz2P=_ceV}GY%is&{JiHvleLu4(Z)m(tP3u!OFKWPOfoG0UiM0cH@3EP812s5RvA! z`ks`=_T9M1WoXGphHkL;{7$GFG`WTNz|0Y#`G)Qg1rNeUH5vh#d@e({ z25^a<7|XAXD=ulxS+nSCpiB4YYuk1ACvr!^*|dH=6)1* z?LvUh`H>HbesUm16XJGg8h;^8=bSm|%y8RSmvSM>b8ba{^pO3*;yfz?nrrSicMbFu z>WjclxuqpBavfm57uN*fx~)iOR;mGD2Z@?^zkK2m+=Z*7aNj1AW5lg$HVh=M4QjB$ z2_S7Ogf&0*T}(4YF8#(KvxzkdajDcLc1T=h9Y|O{4<=bZjFS`@!hfaprar<#eKzEs zDyPrTLjaTdd=Cf0k;E?>oyKUFx_Db6zcn*5m<|M1d~Nt3A{!Z3dPD7J67oQ{m{v^l zxQ#cN`^v%GG1ArDFuRtPbw2FA)|0pSUiJ-ZRfs(xAWGdC%sJal8LL1Xwzt5cXivLj zCr(KZ7FW$#s$3NtB7Zb!cuqcgfI&0aG8+8UT8q5SlZ-|U z1BS;1filG+WZ=eiKPGuKoxs<`hW{H4K^TzOVEW|pJpCfU*sYU{w|q#AFm{nCz=s66 z>gdE@(y&;J&Ka+m7QZua#s}vM_@fxox^B@jV0KBYl14U^)PHl?(&c2vbMlOe^Mcpj zdAUOBwky+a_#bb3>}R6K3xuQzz-J;Ugo3o?2!!j;@AH*kvqo4n&}1V)H1qOYv0Au9 zDxzX=s4>K|$K|XEb*{kWH8RQ0^;e+?fqGBkNVX6&?Cy5(Q}Cu(CiUwu8Bz+gwv85j z?peMpNUC>UN`Gg5PmGSIWgef@ZY`Nc#J|0&I7OFRiKyJBYtR z{@|++yi$)03=zcJIS+jSsd+4=5oDO|Z6-5vDKo<+_CVbE4JXp1XlqF}tEaDiIE##R xQ7mfOpqk`qz!DoGG(3$*|f;Cy(n_^K?m*_paqj5lCw(Gquqx?3e8 zYx-<4r!e*tn-18OyirPSK^B1(mDqwC*_ux*T)jLPt2{(c=6_%~kvh6qWDZDF!gm89 zsC%jtfLjs)F=oVSG~Xz}Gr_<{Gb1jr*`VYI_$kxHt7Nw#f>yc;)}Ajz@u8 z(J~w8t^_;Ay8KbY!cfuHt5^*b%xkF-HMbW7s$KEwrP&_M*g8otSL3dc<=<%i4l>w7 z(~}uKkGMvt3V))6aF$nKV&NxyJm_hh%$e#47*te3n7yWLyurLrvw@R-os#MXBk{y@ zGpY(pN zftr4aLwU{0oX8nj`z7a{xQ|uWgULTgqonEmQvFDVi9B!{ zA-}6%kI?W^+LjRR)0LHV!x4ju26G_g~JrLg!+e+}x|6!??LYL1UK;AaVf}i$wu>z#`9rx2=*bAJXjdVsz z{v(!r>r1+>%fPjL-Z5BV|7Mm@25w%?`Pu9PS$|j5-iw_Wf}%@$IF-1wvkB+@0occw zkrhRuQ2Sshdw&uHw%vu?zqh@U%cK!gEcKn*a9$-~Ls+u4Cw_QR^m|&aT-Im_wJyQONCMtX@M%5g$I9W!o36#4I zOVv^^uBA3H*I-^}YA~`G;O%2F4A3J^lz(cB6olp^2wy5N9~ilsYzAhR|!MM ztLq>lX_@Nhz^VDQ<-Wa(**oe2+BJ9m$?>|hzrtAAJ5 z?E*vlY|nCQow>wyzIeqj35Q;KT!0hnYv09yk;4M}I!M0kgB z3PVwL$vBR?`t}OvVY%?btxB{ zn(J_l{m=Vv@HtZ7K_V={>GA>zMRj$y0GM%MbtqB9#0wN=80o__yGq{}6^I+s=xfrm-V-~* zfC7`6hIn}K(bQP65+L@ zhvJlufOotm1%k-To#~BaXzR>j@iRgfG7(cu%_@=C&~SU$d{XfMYkw3t{ae>o#aOb< zc`0hd)BlfbkCLvP#^0E&um^JILfyE;ju7TPl0hB5BY=|MdwS|5%YH@m5tUr(z&Vk6j=t}KwW2AM3qGHdxUybHh*roL04hk&q^nx71S@6 zErgrm#K6FD+#-0o?Lo7VR_E9|&ba+fC0Mw$D)Et$oGe6{yfdi$7femrwogrBmK;Ou z3=YwnNLj>D3;8ofnx^m(CZ^H#ab&{Z?gj&({wwfV{k=YIZC5z!h(E>)!ID-^A$D$8FD zsVXEY`O(QG0rfPT!|gOn5ZFGd(Z7rEJQ! zj_>Y)dBnDXFj$tUKq1ZS2E~~!)umo(EU{ITp!#z=M->q9Wq#EDxYnV8&d_~4afZ=Y zK9WggLJ3{AC3Lt~a12hVF{NIL6%nBW(oOPj^t(B%d`QcI zo$^0lv6y84XMZAx=O$&G<7~*L-FVQbBpvRUMDejD%LYX)@%z|zSpl7jVkm;CYk+Ac zJSb_#ZQxZZ(__hU!`kE=de$MCq82l|YOsN)ZE~gNFgVniUBI*ggS+1U|D3iaubPkC zvO*8^3w z=>}TD7h{bqE+Zg@brYrc=uhsOwQ-MGWmfaHPb}ysck2E^;=Usyjo>)V?Bw<`i>s~( zAshJY^19!b_v>KOxCMdoeVwr=w6Ku_e*m|@= z`R)c^;@{T=1DW+S!1l9@OfpS9-iTsV@dR77wE8O`fM`ECZm>Uh8@x@ zFI(-YwyUNaHw78G@v)`m!)^-MP$fBNw3Ch&%YR5^uXVg{bNruSMjw262*U}pSZ&V> z*1`fr?G${rx|TfNY$%&twH~WF#~knE5WM_?4NB$u9&Wn-2HUD{uutfAL%E5JMR$g& z1ZB~C$JSY2r3Sx3A9FjGmPoJGa!wI*PYR_}aqM2ztDruq>=WFasv`X|u-4}y`|?$B zXMZk@lqZAPT;Z@UeW#X+w0<=LDIc-uLM9p6RG-+=DLPT;zT3Ok!i4sYyonkD)3j*k zYoqcYKncdUTUCz@x}-(dv+ts+)*!*bRrsVeLB2EJOEf4H)8n)aR7Z0mSRpy8wb@g% z#)IJ!`g`frD9wd;Z{I1(>d;JtRc&3#qkorayxp2%ud~wJr#>V!MI*32&@o7{U&N(- z9SFN(n+?aG(4~!7G>i|k5elis?~n&4_vv%FnrPXOq(-jsP^)}<0vB({15Gb4{-q~(26)x3tICX3!%v|S)`7^9%7%Aov?SBuF z{2m|L{=aQtW}sgJUU0Dx`55wLOh(Xe4*!_DhVZGFN8~8=C;i&0n$#n%ncHIES24y=}mp)y)bd`B=ez!(IN#5&?8o!Q}H$<79ry z+X?0sv-K~IBA!TH|F1k4A@wL!8Gj6F7P?LsxX8}?Ifl!!L?#6b@Ut@6}X zvOK&sP*@L-8;gxbMmBp8Ov~?vdPH?kRMv`t;nLv+SUFgEAH9xZExQ~?&CG+E=-kblJIwqQ+V z`Hdvx3Q`~nj!hXLXXYFvwUH+AKHRugw!QIbZ(^mBP<7h$$pf-dhU7kXv``dZG)im% zL?t}AM_1NP{EZ%5?jGDge(vo)u+PP+{==sH{OB-LSuo{Bm!P`xC*0v{O(bE+}HC}_{PTg-1j?vm*Y?b4!S@mmQ5E`J~m3G6?UYBKpb zfmjK@GA->ecz$jboQN3;tZl4@0v%~kM;7K_&<%JCt_F1#sD-tX9>FXPC-7!k6?$Mk z@R|QrKT5EgmGYv+&)%&3_ zQ(GaIv2U&IjjGYehDDM_TT2yKytS$Sf^nc5pv?qsxrUCc7_{Dv$?(zl*=h);V^;l* zd;Bn5E}`o~r8q%yAgiRZ4?YNID`}fe$WNt%x4m}bZcq9w24fD(4BPEJmN4Trmm4w2 zFRxgN0{9!X*MD0hV>%du#EhN8!MQGRCf`xrxPQI7rvw_gD%s^ImdN;_m(lRfDhUKa zF~e_otGFSVO5SZhTubS$ZCZ4*)vNScULL&MZo?np8s1yHn5*P9voO^rUTFx3+&mws+F2Bb0;*qI heDgJ2T*nU7))@E)8St(PkEeBTAC4fHv!oqLQpsSOC%gav diff --git a/assets/data/tool-ui/csv_tsv_converter.dat b/assets/data/tool-ui/csv_tsv_converter.dat index ecf377bc1ae2f32db662be2cc588d7332d7c57e6..38e223b846ff21a331c632aefe367a54a65cd7b1 100644 GIT binary patch delta 2087 zcmV+?2-x?`5X=yeJb&XeNoi`Gnv{U7K|dMYwzPoj!s`&JB2Nj`^|?cfnCo{lnCH-C7SK}+L>ef52rZ^+ky zLh%8bfP_XR0j+xqSXx0g0HM0eGhPZ2kJGE=-6+n*MFFCN%xBjY&H;Mwel{sZkHHh40_zR}sO2M`8z*b< zTK!)IJCMD!0Dm#Hw>5@)whJP&|G?eJlCa;~B1;(!^vkHjOmIai1s-k3Zi$nsw5Q=*`iD1`fd zVc`2W{YPp3hN7}6Os-@ z7r85%`X(|0shvo0`kcY2Fo1XJ-{Okr$>COGq6iFpRNhc%z_WoF`CYG?ldmiymSdKT z)A8z2v40D`<`WrNB+TK%JZ?y|L|$}GA2KRRHNFSVW^<|=y(sz&`m{hsMUSv<@}Y4V zRSA%54DHvU=pfX7-gc+P4RkgeFCl=FpPQPEt>5~l!}jiiqVO))%0vlDhEc>Fc%-14 z5b7-xyX;B?Imod=EiM^HnAJPxxlB>*;XoBjPJioSxPr_t%M!`N;8KVk+{R^YIBZz= zsk-RHH(P58ag+T+#kzx$_L*49E>4v<&V=>{=IbyNFCeS7YL5hFa!nU48BsqhP<~b zmrDDrdb>+#utb|Sy!S`$Hz&QlWIQ#xets7^A{{?N!nL(P%!#kAS+}IL7$&GtUIj%I z%mM9gstTnk{=yGN317s(kwS8TgcDXi0)IQdP)@=34BKIQ7YDwiBmv@Y94cjUfybzA zP!|<+S?F!1P0-7O=z-1(qHt9?FjG8_$6*ls$po`smvz$V?BvJ5bou{;+4~=y z_MDiJQhGGaGSdCMjbVZVHiSuLHpy;h4yZDk0okuU1l#)@1OcOGl4%JKNBV3V^ncE! z=>JZ^Pm?JmLM@045r$pi2&d6C*P>0ZpA(ShyU#_gKO5SR@*OF$L3Q>!#>aafOw;1EBcij})DHJ0#=FgB^ZRrs3$;ha z%2Ug4B8nuxD&X%D9V!>h1y(!csfzwgC^S(hTiRdLD~*^)1SKutA|Fogj(>3g(``vzMSq4^AU2zvyT8MQRz$y2>8Oa^I9qiH_&YM@`@?%O5_Fvwgjp4|E;1d;QAqH^N&` zoq01LWnGLiL_u*T&};|Kd_p$UT^+yGu6-0yBGI9+W+WD*g0gAcV1H=ESNPF}0K2Lq z{Z9dAGYrc*JL53_wN}3?LPsRS7JL=>0P{jlG*)ptP zl=uQ(})#C6nW3Dv2g@3oy3ykZ-MLABBHmsWy zf4&X|y+dP){{f)c0d-Z>$ZY?lw#nbRQ%>t&gm`Ba*Hl-i%XlL$Uf1Wa7b_1M=8 z`<$)JwLJpKdg(vkj6>Y*zGbZ12WpWQQn;Tr0U`UnqH~yHJyZAwV}&GV;~}GxmJW7@ z7L_DKSA=NVmkqV(u5;P3ncCu1Rgp1?WfpCd$yaJVYalq_j=9r0_|Wu$8^@Q?s&BWZ RHRvDRX%@c861QR#)zT0;|ET}~ delta 2087 zcmV+?2-x?`5X=yeJbyOpZK&B}5^;MWT+uT>i5i z?cYUG4^Wr0W0*O+H-iuLw_3y>?65ouQoGoRpgAwaN@22XzN~V>_xnnw6u;~7H^Ss* zTA6RIziO^U1Ue!0I4PVgdqpY&-7ATBScGMS1_9GTps{X9kAG{9rR{g+bmmQ15|=}B z|7TXXLMbE)*wqnNdJ0KB?ev(L4w5Y3GB}t+5(>mv{zLlKV#ph#2{(Gc@hzJ`4*bt3r@MlCS8`{n3V&3wK zP;rUdjERp4;&@oT9#Icu{d@}c=OOk2YWpOO zgh-(iu9fr;sgH{G54if_d;B4W(}NJveA&|!39jr5{iQxO3-(L(=p_rzu2iHA23kic zi~r;k{eQ3T<%2~p#kdCB{pCs4(3w42W$8cbO=nw9Zp!cyDbGMxF;Raef<$$HX$=Pr zwn!Y_Vb?zmu|zVgy*j{b<{+7_Y9&5NqLbtt<-`JlQPXTS1JWDL?%w^!Ldw*S+@kS; z`8qoCd&N^mSW1ySG zDx~8Fx9OEtG<&3nlyqr0i(1T(6%#v|qhAWLPPXzJcr5?Q!|xS} z8l_Vkx{ts;7`L81q}5H_AIQ}4JEMN9)Gzg~vuj!R>^NSKXUH=9cI~ixYGWnYAXK{w zNL9P_lYjl*&$JjuDFniZm z$@RoqSnE?g?qhvHVsQktX{g?cs7r-Em0YI0u>YIsw-`&Zp^C?4QGKr~x~UxTXn!6L zgTqF_t0^%w?d|ZbT1yPO2hQn?4kNPYXwot`Rar6r)`x8YKBu>@Ub8Z z#s;PrMNQc*6GQ$rnj4R>@_{MintnQA%%KZ3fT2#*X>?Wl_c8+n_>+!d()>W{Ytk_ugyOI+3=w@-fJh1j)2whCDD`O#A{{q5|h zG00c?s0Q%)R&zbt`#3`QYna3Md9_X$CXzw*h-jFEQqZ5i7SDSqqqAoH{(n9Ly}B>J ziKvHvMe7Ts>=BL;$>{ltr7{qZSIopUFw1J8IIWrlir|cEF^lE6#yGyFv!{T5AmUtM`L_%!#py-B`WMur+~o4s^zbj_`6AWIL;ig2pFw z*Bsi_2;b@H*3o;A=t%av{(l+fu-j;1>45keCB5!rW%xX$9N(5g?0FEpvw8o!e8kWs zL!C-0excz4Mq~nVx@a5HzPELlQly@;MUdxUtH>H_()=u{EeVSAV9b=!K>N=aB|k&3 zB>!^W`26K5cz@f)Z0v=XcJo$Bi64pj^ti8uw%B$;Y!8Rtm8z%Paeu^C$Kh`n-u+T@ zlHQNK@H#j?6i}?vZ{)6=E8EkCbK+qepaYaEUwdQ#fR&15q&JWifUW@++;X&-vKb1kNU5M@-n-a3=R`T z3i_HlV^4Xicc`<3@_%|!o(Uh7ljtqjfD;HLN3{xFB_mg;xgC++hQsN4lWgpGimpkD zKkCxEsYWQgH_wct4k#>LMC#*7DdFZ`u&0YrV!@VoHgdb6+8=pGzO7Gg8*|%8CX|jM zZ|{eS>~dYl8)AU>Fgtwep4<)HOvZ9M(3cO;M#~%+Cm}2Ihkv5spM+pIZ>h6b=)Ya( zV*qntg71pyXt9X-2ZMR~e_HYBYNZP!#j*yN7b9P;PsnxsNqDE(=|xTP#@_N;n6d=2G#0Rc=YRxX)GJalVssgKs RZIO~Sj<#vYfTEHRCSW1N8$SR5 diff --git a/assets/data/tool-ui/data_size_converter.dat b/assets/data/tool-ui/data_size_converter.dat index 18601820be6f4fbf909af9b46aa14842b8d3e0e0..9d16f63ca034adc8388fcad54dcd9b7cc0577d9b 100644 GIT binary patch delta 2022 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 Ed}3JYbpQYW diff --git a/assets/data/tool-ui/date_difference_calculator.dat b/assets/data/tool-ui/date_difference_calculator.dat index 121e8bce67d3459333b35f0f07348716fbb3fc23..5a14e95c3d58b281cc63bf4c1765039bdeab859e 100644 GIT binary patch delta 1409 zcmV-{1%CRq3$+W7MSuKifWF>%Vat0sO(`5MdIx?%H`A-CWtWIe(E7DTd`~^vXAYh| zLC4&(m!ew+-!jfCc&y+2JH2SJWk|tBVsI@Jx}$SMAPAhnvqa;7^!MaIjrk zBagR$B3^nrIt6A8n}U(TIH)Oc6y3kArt~(v`i=}0kw_l3YlqJ3D!y?cR*$^xND+YW^eXbBeELZXCDU_1Jx)pBq6BsxG8zK@zj-%PdMNa0w0wa>IqEBJ4 z2&D0*G}?0Mx_^pYp2oe+8cRpCJxhzR@BlF33l^&kse%e3hokg1z!fax7Q+hmG1M!| zs$*Y{a9D>fPP_lvn<8RQ>>;1&ZOF}87__Bmmtk`296+mMFA{Zh7luI2UQRAR+Dpd5?b<@!@wtV>d4E#o*@(m3*vimzIvWo<|LFy9 z3f#I6=h%G9e@#Rup^ZX|VKV1kF%b`3w;e@5cxma|+l=uQqXBW3)a_x$B9Am}Z42Vu zXi9js3j^h^5flo~J%0#C14j=?UwDF4a*E9QZ`-?L6w9}21)a*&T6pJgN+V}FBt9rz z=@UL)w13WxM|&h*p@A|V)A%#k6NpE>$(KVtMsvB&?gn26h)c?L#KinS{XoY%tI}+v z09ZFKP8h??!?H8@r^wY>u(pTbyjOL~cc8&E&4lg;(|shBz1SsYt6MH3Kz%v-(I%v< z(0`hX+~uRsu%wC#)P(SyQxHrKd-!)V=74Yw2+gh{+*<*2NdF%xbpZ3Ysv_(aYSe24 z+m;;2{`DjsUNmsjh&v85RR$l`>h8?A!3eF{0<|suhrf1qV(ie*U6<>>%rX1|{Jy8!zTsc1|RQ)2rN^MA*N zinlvQiY>+&5~~{`6xUlUlFIS8K6?1s19#3I#299NBZ5QAuWkp6Hm|BJ^+v}SYey`C zY+!D!iZ`TR+7APg zx78AqaMkpG*tLcS9(OY8Uecs>cbH3D3SfLeYcA@Uc)$uCo#m{1Us3%pEyl}@M zHp${vj|9)w6|Zcwvig&tG^PniF4*1n$anm-=tKGPhY$0C2IrlE81<) z`>+2Ho3wK9_icm5eh&#jhuYw2=L83onJXwvf4Up!&zNS^dQHXn2JqYQ9gV-gmhH&% P(W+^U%=R(@zN?x_J)*aF delta 1409 zcmV-{1%CRq3$+W7MSq(d6*WKA7Tcc)fRlHK2tq1J0Qf=mG>QQXEOQMGyF7Q4ZX+Tv%hyEgn8>dLZ$Qqt9f}!KZ8S4xfy7|yg z<$xi0P|#c9FfK|>rZxdUBVJkRez`;f|ZhObvMJKlCFl&3Op38X&HvIv~zB&CC! z|K_NWPD!Rv>{8b|qV@z46N>^vHgt6U^hOTNnsC@K-gW5LZUlOd4+~TT7#VlviP@FAo8==84 zl}0|fj~9k*)skFV2WYTRsT9_7{>evzh{GZqSBUMnDVee{X*Fb+l*wNiDq`=f_Hj3T z8-MUH#@|alfHYBKA7?-6Xk@HswK?hWequ2Orx!x`+`!derYo4WEc>6y>Y8;y)+7Uy zb3`Gq(e^C{vMLsoGzj+B)&40ht~J7@i|~jdl|z#RO#uh$@q;oPQJZWdyXyb|ManlF zL)W=&9SO+$z2VqE5kHI_GbaJ09e@EPhJR*TCl11n0C4vbMY;OIevY?1cf03iBg~WF zMX_5YYr=V%Q-%4E&$?~oB*TbwPzHZ7j#8@Vr=e45dvbyL$4JY^r3hwUDbW>QBRhlT zQBCG|;5=Z9%r8;Q$vx>~E3*_6s>aFn5p<4bcr72oSyo)L^0UQ^ z7AxZ{Uhk{=#$>6Ff`fK_fo`*|c|pDt$VFVKPK*yMn8?s%eFu@G<0YZVY~jWf62zWB z5ZTR=`2)&l_M9=YEesI09NY7s7=MC*#C!L^9K9QsV7Ry>T#U2_iJmJyzt?vD<#l>WB`goNEG6U}K>I_YWHcWzVV2+iA;=(BnyWE^QNDBOrV8z|K+1hEa zBp*m~8hl!8;J%l9_(UPIT(`2>zO_^%#1D3IMNonG!X}^ PaSJ|=j@U%yzYb0@WA3ls diff --git a/assets/data/tool-ui/delimiter_converter.dat b/assets/data/tool-ui/delimiter_converter.dat index abe6a1b7cbe4f454aef2713440c1cbc0c3b4271b..4338890babbbea509844f8e4050f1a63ba8f1ee0 100644 GIT binary patch delta 2151 zcmV-t2$=Vd5snd%K7X2Rj@LG|7~W-Z8q%6jK{m}CXnoVe!uHry5K=OKdXbS4gpBwQ zxPQ2hXU8YWS`xs|O{;HVM)QIxpw>O$Xsp3`C8)gNqT7A?D7u;gYoGGngo;4gK}666 zyHp|2I%@cT44Tm455F{KWeeTf{|as~7HaHV>&sr4_kv8@PJd?q0^Rwf_Rn2XVf%7W z+n+jFJG3Cb?@Z=c5Ix}P^aM55d1b#cQdTx zsO4;`-J;PoCV$J^y+u!@BVZ|ru><8n@v{K${f(}-oe{bTbxm%|B4XCprl!c z58nw0ewQ>uHlD=uMv-G)Eo&Skn^$yMG#}d=-JP9oyA@1$%HwG5y$cCzW2 zuPX$Dx`CcI&TH@Me#Z}Y)$>=H!M|;5*<-{(rRrtFD;OHNaU$GA(%FT6=<+QkdIPt-c)%6$ClnYY$ND*6rJ)bJ4u4VpdMDPz#Ou^nC|j& z?oNqfE;-6O<@x5E*lpX%2m7>k>h*NPsi``qn2iD`qolwK+0)I%-g`;RhJ~?4waQDU z9me&$gnv0P-lx!};rOky9JW?f5s|y!PrNDF=&^}V9C<~r7ZXOg&*7F8e@^PT8thba zy3ZZ4%#oKga#1NV+{jc#Q6@42r}B)en15ftJ!DiJsqOLreJSMbCJT^poUfH* ziCvdKZLw3;SXx3PhpQ(wz8cGJaCLQpFAj!DobE`VYVP0gkoEKobspNEDptUx{%vbC z)hmJ^SZ*hx)R(z&w)mAb2pawpnFtltJGj`z@UwSphig-7tGUNs3`h*#Ub^s&E!LWb zwts6s6MUg8d|Q4=G>18~Uj+_uNPm_igy8~UW`&TgH~#`aQq)2mp5adx+Ap0+-X}=5 zu_G{`ISm^QE)qe0%QLRW!HyIkJ)mL@SVJ}r1!oC|(<5)fpz1D*(hiU9ue2-tVatbx-FACxVL`W+*0qkt!fshrlg@56jJkomiI;ho@JeE=_=x*^mvFH=@sDr4y&b5Ns3(~L}>y?^oL z>p1Vq$dCGbCMg<4xMC;Ozib3DER5Ez{`Qzp6y;k%AaJjVS~RVv1xqMsfn9&0M{&$@ zx{-%P%@L|43`FvPhk!xB78#v#zb+1lALyio7rZO>eKL!&sM&NRi&*%-*$f9yRk&|3NfkV0P*h_vJjo5Fuh(gV48d& z$%BsP=*3(tNoa3(|H3E(9c}weTD^10FttU;ZN7v`z?$yS8?NnoDn-*wuukpWXAs<>5;!4zbblM#u z_`1bbNR|0JXTlZptoRkDvWsV);~bn)nT|zbQTgD^+?x=pk6lAM%tmUu z+lfV-nb~;2Q9CJ|L!?fatmzKj))a+AmpK4=T!ls@I2kA+?A+E%W@_Q5ZfQzTTw`Ci zk@W(tN{@4R_J8!hSP3dw&zxf&@OHn#_p{m)oOYnWFy1{083#4cz62PiR3VuUs?Q|*%r!_GCb|>F-7k)cn201Zgb?U>C#k2Y_x&sK& d!A6+NeEBc7B7M(T)%6Ab!!GZ^cKOBv(j2KaEBycf delta 2151 zcmV-t2$=Vd5snd%K7W~DvZEw|U@6hIK;+IV(CTBaW(ZElOkzpQypzGvae7liXoXZ4 z3z2l$p=SnWj-ibke)h(T7mgEHv|Gs#I|$5~Wm(!rByOxtQt7;eP~w%(e|&swCy$hq zU{tw%HY=v&U8scSonwT`gt5zN{6ca<6J~SD@mfXUk|wU!N`F(SPZJF0YeZ+HC&7jm zAoE5P)`m7M=I63h%)>G0VSt>?5_Em0Ue)Laaqqol{W|Nr2tp zl_vXsL|?#f;#}ya5JBFw-(?_8D}W38)Z}0gnP32zTmna7t9;v#xYKHYN+1laJ&bg- z7kEIw89KEt?&UUe050=s|A6i2v`5BtEz+w#VcCYXTghp1iiR&2Z0yoU_`)cjO8v8oEx z>8EQgtqwk2daLH(ZgVBN^KKGgJ{Uc)-jAz6c$daG@CuV0_^DMYpMwyhN|?9OJoE<@ zdVft{>x>ei+-RXmXi=qFGyZ@PW>5{TTsstL`Y*(2m4 z#{Jt|mJ;I)z^a)Y(XoeR_BE}3<}@$&Uw=JeYhFyVhL2*r7#S(tkQ^sdTZ?>T1OLCo zkmdLoA<=NuUx|)@gygGyLmdZ!H_z-BS6z*?!jpFvJW`@?#9{Xd?hoaDwua3m|6NA3 zUm111de-oQ?3(;|r%k7zum&-n>%&g~fEa5Mu%4BhiRb2XeEg5ww{u`hl+ramM}Gr$ z)Ip=!$W9WnREEaM*Q_<){CHiMjA?fhYhs{`^<-Ca{!S}PmV4Yzpn1%RiFR83=oo^x zdM&exwH(V#T7#JUmFAu)AXG0Wr!`>qK})gaW$X^HhC+HEv=_^ z(dr(5pe$;XBN>*D$~~j|GRsB#1gV>j@bn*Y!mRQ)nUr6lw-Me`S&V^o7Ne~~Iv6q6 zdT1O?eM7W3S=(N-diPS&uC@ghp>mN4%shmbYCKHj&~F{*e%bK{rUha1_J6+iiLxcf zy(mM~b!W5H9F9NSVp|PX)NsI|&MOYiwf{T3=dWncuc7$|rnx*_(}3_0FH#goZ|+sTTs z?#Mak28%f6>#F)vO-INKL4S=d#wa}>Ke*}?{LSI>gi^f@%WUp5W+{#g1$3j8xz$q6 zf9~vBf|$NxZ?Ace33UZY#Wnr1N$nord0qa>OmyI(bbpTBJ>tn6&Qv_Si#pdXWer{{ z7M=&*f;P4~%LP(Ug}Wlzh{7GFLkdT)7fVAy8KDJiUg z?Kj(c^g4GVJIDZ91VV5tnZT`>=1ju2zW-oX_%#63Z!n;aw5=ND-Bj>!0!pmoilkUB z@s;nzJbdb|JhJj*MSmN}%dz^*+ht?{r^;d|_87{cEVRE?70vo=oC>4F&RIVak86Ny zo^d-h(wY8NyNXV#kG>&L)7?+qm6p0yQ6@t}SR)PMQo!LpDuA~W;uW?ZyC zOeG_R_kJiedi!IjbDu=|ee`a%B7I8)P%nJa1lD=juio9We&=r7!C7SIyk&ZxZDj7+hD-K}exC*=OmuEL7a?=9^e|(6S{pE@U z?rirw-`@0x9Djh)h^!~N-*gQ55;?k;Pv27Ri~D2;8G&r?spqHyTzv{wE{d*^lMt1o zB1QYV_5bG_p@0TFggc{oWMO8B3sTPZe}iyVgB+*_w`lEj(|qX5$NnHIab!Zr=;W2>F+CR7ToNMOv&+Dz!sVZNgO`-lYWs6lX$ zlx0J1RDU>bv|&c9Z#wL@U6zbXSGp=3#Cp}ijI3CBJpc^bDd0+vr0l4Vtu-?!fR1(V d>eF2s(j@mp@)u-O`U)K{1`ygPwuv0k_9_8uLIVH* diff --git a/assets/data/tool-ui/dev_environment_config.dat b/assets/data/tool-ui/dev_environment_config.dat index 656f4795fd62aaa91f30194a1b910fc36e127588..c04156c0f0b2540ce658274298d3b5987a3d0298 100644 GIT binary patch delta 2232 zcmV;p2uJtf5#bS#L4PO`XtpLVx!XMgmy97lY(Up|`RTl$WFmqSe#s94)v<|A0*_NO z_~Sw+{|TbZHs2{@3h_}QwmR^d9~?(gHG@wjrP$Jb(cXP>hCE-yG?@k$e_)suC={jb zuCp?DscsP5R52lEW-o>rJt+yIr1RPDV(?=9@$MAAHW|d+hJU}$qqobf7HGQvGoUt& zTlxjBl@}tYe&tMk~;QSt_LM7Co@=r=(DNx8k%VqhACt zqN1MZ@o8saP=7Rj)jYO@3-GnC$9-SyD%lpt)k}s)$wo1oD@Kay19SE;jw*exEKps$ zQ~J;c1rkJ`T_?p*B-n!-pDVaEUi?+ zI^oIqCx6o{2|LTT{LdM@QEPWXybmwh`F_s@0krisZ9F=-915Ac3qNucPNaDJA>1iG zdC<7sZVn^5IG&a?9|w>#XQ5H0t0d|OC&ucG#9?dR7BWzvoiEuTRxi@LvYLTN_b zhp=B!Bf51~nN<4|UnDx|gR2mK!M``q%&0}1?9$&0xOOBDt9E5XWlehczPg2bua2J5 z`hP@3`r`D-wPY;ep-dQD>k${d-Kub8R6Ot}gozd0>c@u6$T&bp1isp9oWU(XQP=;e zsVdk7E~5@_w%iB+8vsmjfq)Ja#seiZQV=bw9e-5;MeVa1M3RQ?5kdZz)wrEmMXC0| z5Vz2z`Id6z76hJQ#W(UA_A3*Q-5$5$Lw}74X_WE`&m`MX|E z3;^f_BmY`{_ga@l3m@T}3@PxQu8N#bPlxX}uJs5Vp*UOmyYQDd4qXrH6@q-?euMc% zEV!vTl)san+}Wt9t?~ogl;9ja0#OE%ZZBvt{D=168d`vbooxP^{E&IvI=wA>q3J7sFAKlu+6**4R9NWUPYA%YlU869!G>;^Gyf{1MY@L&C zVvpf!-adfH?NtSW?F=(w#{xV5}IEPa%p_Z+zH>b!2$iTCNVE3(2miM19=`I zalAlM35tZ=I_j2EoK1Up8x29p6@UGha2>!St-nK=Mv>k-2l3Kk7-9{T8cxy6;Kk|3 z+?i$32o zNqpI#1+(v4_PLcM>HrWp%F@*YQdF=mGz>q&h>Yp3x=x#@{DShS$~0_e&3|08>(l&l z*JE0PZNYF0Y5~S;LI7k5;8@h5utv%OY;nE3U&M$D6Ik&3Tke`%Qo+9&kiDVFi1BKV z^`ynQDEQ=l6Qfc5`|vCd#lTQADD<+iecdRk7f^E4;P?2Nl?bA|LluN3Ch$@z+@gu7MIGJbq0 ze9!B+Cv+c?ynja33vkvUFb<12!rt3VdKXJ)5h%*gbMLvh%+LtwbI#s}w_MI;l&_if ztx`?tZ$5r3SUbx3M2V{sm8Ygp2c(`THL{Vo{yoi;)^`S;8SzSdzAVoOhMBZvxW zw_eY|`3AISE|yxw^B!(3*KiKDt!BF5RZj zeGk%+@_}fxmcpAqzO#)(#$SS(%Rg-9RKX^Q@fuXQmJB9ej7AOmZ-OjZfHov}sllnh z?_(r^L@`|aWB41b>NNm_=PDjpgBz?*@wXBbC6ea33gwacpyF>J&02psvjIA(MF*^Q GTDtaY)lKmL delta 2232 zcmV;p2uJtf5#bS#L4U7YsDRee@9qC}5Pb}1#i@vEMo7k0tE&9gr?>}Eoi3HayOq44 zqyFO+08aEJkx_`TdV22(A6Gc4+`yFxN>?aQYt#Y7ajdi)&g=jHl5se_Q-PWJnPyBD zkavpmiCf^xm}7gS5XUjld;!3D1C+Wn=)&)pjsI~`!H@pR`F~U;lu4yM2SAA4_M+_W zh+Qf@diRQKhDu<=vI*+VDy2u@W;j6F*8`1Hi6Dv~`fek(>G6;wvvN#6SZcyS{f}ax zHOWTU>FBqicHE`&Z$EPR-6*WG9m6uv6Cj&H80IJ5@Pk0r$nSyrN#8IKd=ar|oqzw{tRwwsW)OQt2ESq2)mDQZ<3#(;S3R-Y!q0rbPKAyU*=6;n_JBAudGy))N@n$Zj{{4HNsFmoMIf za3tt9VuT!2c_|KTZKN+ytG8F|v5_|TI`&O!nXpR}-&uPb;;D*=Cu`>K2;{TDF;6RJ zZ*Ya8BY*!fZm?bTyEcf{Lja66rX}7My3X$Upp#UXYJ%*n;0xgXe-tcC0*P^T2!Ve209Bb}Gpt z)NL?h#sxTbrQxgkxNvO}c~fzhJFrJJ#|TJ-rW>Nff(eGKB>KmW>bx8DiP4L@IZ$|k zI)CWi!c(yawC8!T8&pB1{duQXUcKPTomxq}>Y(MinjugQhx>xLO497i*Du3T%?t8_irmo^dKgl3dc@{6e&!1O5jsI+w z25e=G2QR#*RuSVwRR3RW)Q*YTyQo15gcDaOnSyz3dMSJw?Emew=#Y!`IsfljlD793tcn{HNnWYW!83J}_zUrT zT>uISDwX)1wtXvXnEMB*B4CH^Ngs zr3VCPwwN;TCcOOWO>RnD3-~|bJ=LxbOM+k+-#9nY}MSW=|RGmqqdw-cF8#8G1 zL|p^nt69Po@4;}Ol!_#y4P)Nq7r{|Ft<5F=$QZq1Cv0!>|!%`K>;p`b9#ZF&C)Sda%nh927oQn3Q zmCil=UTS*@J)zW}u(&=O34anKA@R9qPD}331@BTicI^Up&%fxpwKUkcfo1G6%Zmw1g$rq0zSD`RMfAd5xXlm^C8+sr{TbIR*awY>V z<0=eCoXDT1ff7=3riy330xjtLo=VFB+dyvKx-q2p4{3h^`5#l%;E0M z!wVwKy8~hM`%F5%?0+o>mz5PL`12^RaCylu0K zD$ZLBmy`0$-w&wbN!qQcBrBMWCAH89I2yglr@2c9N7$hNJ@6fjZoCR2z6Q4D?<&6pX6@GRifglG46Me8)x%!1HmIkn zYIC&NU@;DR)tb_F(GU_tk?O{B6U&^oPn$gKA3F@PO(y0^OP-)~4K08`KCcSE&LM?7 GdVCX;AY!}# diff --git a/assets/data/tool-ui/discount_calculator.dat b/assets/data/tool-ui/discount_calculator.dat index 9596ba091d27b9fd96025ae8f1a2b762f0009e17..d0a2b2aefa9354b184c9280037f493ecdf137887 100644 GIT binary patch delta 2006 zcmV;{2Pyde5B?93K7UNK^q_pU+~MIhlXE03e=}3P zjpQIBf+X>exw4#nIh=k)Wq2X={hO!Nu`T5XC-JD6}B zaJi`V1-4PI>TKe{o^MgQ8cZ~1IDqc@ULH~ zK&XvBtb=Z*$OEcYjykVaXvzt?XxBBatSVPGW~aG*Lw{oko<%WWk4cwkZk0`h){b{` zt3tn&&^nz7)txRw^D>nZn?)WSY_JciTnpA(9kq8t*_X_Zlpy}H`#cogSrliX?12Cb zhw|KvR7^WE9GIv6BQQZHEN$>_EU^QbFV)-$`JnExDAvqOAeL6K7_?iTwi&P2tzqkXTuHuHdntw1#z?-5v zPvk1dA1g;Gois+ac7C9{(jZ1-c!qzSv#;dC(QhsCx*TVEo~A236T~$Dy@Wi&>F>;w zMn&Z|zME0=Q>#lYi~|=(e&;SMJ!ju$DPRcmPk)FIJ7zGt+T9)`*BVl<1Qpz}Ub}&! zsF*9TrARG!U`A3JhZ3S)&NY%;*0YSft|3i@3x0Mrw!X?^Zu=^N_*{Cqr8jm)f6@Hr z8D-prkUFR#&2ACWv2Bp+?Ho+dt&Jdnc;vzXM}Vw>46yDSZD6jTs4xGU&Yppd_6SZ? zM}L6sq1m*QuP%Hk+uDdb^lTXaE>MdPo5rQ_%^N_)iwgBy!ctWuk zV0wc z6cWf8|7eSr1w};Gqmd&mW^@OAZ7uT^_O>9PniuOm{pPh#z)UF={H96x0|QSep}Ero zptz<+ylPvm-_(jNJ3jT_>H{N)os3>F853s~PI}YK@eA3LrI@bsjo`7Hi~a^pcz@lQ zUzp$PS*~C?x|FEVyQI10yfj}1%y0auACK0IT_&Mjrtn+x^TNGaK;X;* znm}~a=UP-^yf z!jCe72??gDY;#MRt+kRi$&6*yT-6GuaIFJW<$h%8ho}sv7ac=VMUGOo};MFUoLBdz$>V7zK^?wiU5y3(R zb+)eGHLeOA4weX_KEPBA3U0Ey2o$k=F6A(?_#SrM$t#6zC)C2Q1_emYf^^C0zer~m zLza$ z9=`%|sUkWcM!>1qJ_R_4J%7k_`JvC_!1H9!V}hlrO&Jg4+pXNhl{+qm@MYw41)r?* zIxz7y$~u_;kUwWa#43(g2CDHr*fa;5XGAQUP0|C+sqHZ!su|}Mf|7=Xtca59s^i5v zRYs{jbRss6&xzXWKZba@p;28HWs$*-lS)1NUZegV`zzx(2!qv`Y<~}ac+zJ=7(4DN z8qTh!SKO32B80-cM_Lxh zqgkO@hH^FTeq%vtH&Ji1Qxi2x=W}*@{AYHuvk`Is%m;F&Y(TleYC!yPsV(wxWf04~ z8-y|@S+hv!eP!T67k^Z~Vsy{z3BZm~FK+)3dq`Xp_)9p);C*mksa)=|BzH^06=shV zh)isK2QIN&^vkhCUZY2^oy67xE3fuUeZ>TcZIKX3joaeajYq7upF11x%U!b`&y7^E zKH6zU4^bCp*~I%2SvuJTN?yZ`kf=LDRc@a#ymCvIcYoDgqK5yeY zSp4`PUcI?PtmSHfoIL%zoiwjiFtgio;42(LbYD#$K-fEF$o|3-Z!pBC+0yjn`O@u@ zNsQDujlwmG_fKd3RNFV<9SBx)59+m5CO~$o?YQ+AXkcx4i1NH1yKK*zv&jh-L^+=% oP~&yO-!;tbH8ExHkT{}UfZk1ydtaVjKBrM@;KUX>dcfdJo~KObbN~PV delta 2006 zcmV;{2Pyde5B?93K7UyuaGeayt?8ZKUDxID$u~X)o0r5OIM^m*DAN4#=rCBDO>^L5 zp&37b{%C7;+NHMQqrZf;*kd@7WaUA`>mMO`{ctcY7)7>-?x$3K$M4%t57J2EUJ3cw zRSq@NQCPPcEq16mBoew3gIYDPr(d{y?CzYNN;OvP5CnanMSttvt>p7p>Ha9p3#Xd* z^l$ZKS&$QzBDIe>2Mj<9*CbsX5dnb%Y;B9Bus9ooZKvZQQ+Md=4M#Dpa+Hl|)(DBxoI<7zZ4J zl35wy2#+n99i)Cj&*%v$WQOgdg4a_sCLwbM;7T*1#_m6B_|og*EP`l6{WeDs_O^r5 zPP;uqHH!A`WK(Aa5yld?SA-dY&cHa6>oM7vI!~}5Xn(=+kVReSq_Gm=6Uz#db;es^ z%Lniv=8Vsb;{9A@)|3L?1gL%>k3#6!}X?OEMTguAd9( zEoxx5k!(8nV*&@|NnJM<|2*7oa`T69O}L{8Yruy;3c^!aDJ;M_7SVXLJjN}TV7|^` zQKKRPDSyLx!gMb2l6U!56Yt>kM;z<+xYEz>EJyJp%BqzcOcE%p5dm%tDM z5?8pnB&Jd+{wT!5`^*~w7b%n);FHr0BG9}%yA}X7_o=a73Ir3-Di2TJ3xIyM9 zKHfGnl-1>JuBLd+o0XVmP#8c2)60^}6o1RZ>ixr{WIDsMZ*T{9;a^u{_S@l9ioIAP zcIC7G^|Re!56zsn;-wCa#jBF_kP}eAq-7!}Ynbx9WykI$@sg>8sWgx^bB+xT*CMhv z`!_$~AVLJnHLf4Rm$Up!A`ZwNC{DHyiqhPQVZ}bqC7&{E5|;2UhE_d31o(-!=zka@ z{4dLLXqT-D{T1)6Bm6uBFg!5|3L}>`)mZcJv40x?U&a46AHakD7at`E=&K>yPqMjW zh8QF;v`qS>|101A{>iYgW7jGAh+vY-)f`dc=jSz(Gw$r_o!HUE$0Iil@yuiP#*Hx$ zU-;uUv7(sf(dk;mH6K%9zb;q*T8?py@u~+&rS5st7 zW|PDjJ?+*IvS(xi5u={9ml+A6&RJQf^H?(mVw|99|uXSn=lDYD23mrjaB*g!*b1cHu)Vh^ZG zxPE&Hn{=i%frid+`}jGyp97m;?%mm{?RZ`LrGt^5PTCDstql?7LU9vk*2h}|H~hE) zJnB}hzTML8AeLKSvxct!^nITnXg zvSr1Sf@)k%qe4`~)-N0H+wKk&7QErGMV`d#X^Nq16&yq`p)~Fg(0`tpyK+XnSqtIlhT-1Kss~NBl)KQJLfpz@3 z6)D+kWp}5#>0cZa`Eb>>)9d&85NM%%uPw9dG3Qc~lHgKw!++DLXBIbCz{LCf=l}?^ zuvn5Epd<{W2j7V*VwdSh{-N?ZU0>%2D%vpdHAXS+l_XFMndIj7;EV!G=C zidgAfUCT&-8&A{`B2dq4NP5)$R-IK6yT(8D!JK_H)FbHOM?F*H=LLj@LeUqep*s}O orRe*d;v_O13gZI}A^bd@{I!}7+1HxC2WaJh;-eYG{Ik;VUnMWwl>h($ diff --git a/assets/data/tool-ui/dns_query.dat b/assets/data/tool-ui/dns_query.dat index cb8000d2a044d664071c924e00426d644f3854f6..8a636a06ee68e07626b3c127255afe5d62078070 100644 GIT binary patch literal 2148 zcmV-q2%Gm=O-NN#RY@@d2>@hnb6;_FWpa78%X2Yn3WnO}2MEZ#>O0f|6Aw3y4Z>!p z^7>`7f*tW%I&en14p7lIoi0EeNJU!dE#_c-QVc5v_6{XA8kTAca&1Wwgkp>=#k~Q? z1VDbeXc5$j(bDW;k-x;<+{CnL;ZNFdw8xRY;^Bhm?2WAP;J%nZ#wT&0rGn2rK9|;hl(-PX}6FTD<@g z9p!0VZXheR>2{&@m4pg+UOAW!j9#6zT#CYA$1jj7_d#b^+NYoFD94*zO*)Xq1>!6E zo0okbuEd}-23RH6xT3A2ak+b`>+q06y##%8ZvVOh_Wy*G+m&RwN{81xD(a7S1sm)5 z{J>{sUYDL;>mnm~(FjGtLn}y2Ev?8Mtv&82Z-y?b?@+xnId}22}}RqY?^UlnN4l{ULE7XUBYuym3qUj)}jHj0-%_n*j+*l9YFxDjmJ3 zo69w60!Xq8L!LN=(){0a;b@`O%hH(oL%0A_hdn65$_yMvJ7N)RybeSJ&guGzxCRn@ zxajdG6XWfoHk=iu+9cF6E86wD@aBVKl6`*C)n+x4)ps5n1FM6h#P5{L#tuZ2q?C(7a;*Q&{dC{KE-FMv#urgF}2*#c2u6mFXOIRx?|< zR|5)RPPo=y5TY-l*CzG!jS=CkD=2QMCDl6`%S$2|r_UcqY2gG}#CpDewkitKC1ta# zLn7ynj3cx!3N^)OT71-%;_}245oA#f8R}7(7YAqM5nDmv>S((@O_~4>)f&1PA{Glz2naK1~q9hB3)^FO*~} z*gQKKmsVSI3KoX9i)TxcPlz~md3qlIOshJ8q;gHTo-^#lZ6Jjo|% zmEX~dss3V77*9c7VPnuZMU$v+EF7+ z>kOBYr6)@Ayp)~3eC{OIeZL@_b~f-*X&T@l%JK1c;_1~BPlg;#_L{@Z+b#3Z8LsyI zBOjYP(UJsK0|3hKW6sveghG3ZB4%@C%-oX-u^jb+_y_v`mthjju*8Z537luVC$MUE z;1vaP=c=+ldmit**sMW=SpaWgnBrZ7DSOoH8J3sEQc9I@x&w#P04G9pE%}S!cppnR z#02<7gwJZI7`!Ey+}#-0Lb3%hJw)9MiP{Z3VhKA^c2#MPV-Q422Z!Z6A=1rhv1U2Qz8v6vB?G`GsSF{?aJ! zL9(ks{rVCCXn_8W&m1$MZ4T84T4Eiz5>+%T_Q?iub4z>S0H z+uX|7#V~9y{txuxYia?IO;vcA3ot|!M>p!r*yDLBjPyMIdg5$UGleu@oS#D>Gor%! z*@%=u?VPDQT?Y88pOQ#xLOkF>CyXIHXjr;(Sx}mzXt4Tr3nmGfBcGg3ArsLlN=v64 zZC*P++8jVb{s*J+QIejerbkyLQQ)y2iBVKx>l-5k^xH;8A~&Oz4;xVxi}+kbUnt1A zg~oJv3$w!_S2^w)wl>rFwKh_Z+%vm57)skuA$kkO8kp_eYjC+;U%_A$Cm>7fPM$S@ ze;n@VbLf5&xXb=+0oPo!$%E2QB1c#!73cNCzGAt(opp@Q>2%(?sQvHHT&wfaukUB= z>0ksB(%z6_VjZ=E1ngD7Z0e8=h22%prK@R`l~(t3w&!Y`A15faFI$Au$gpBnA(&-F zOl>$zCBJ$K*DDy2p^Mtd`itCxUs8faW@h!;%zqp}$U)QQ$e;eKiQIl0|L({!PWEE! zg$t%Nkl<@DZ9~NiYS?U+eR&5=|B<|wj!XhM`CU$Oa6#t>$qTv+&^`h9O{XRnw$Ka|sFTbnAN^WJYN{^y0_&_HvnC+o2hs7Mt6B6$^+DKUXj2oi? zIcxesUJ73H;Qex5%a_XPP>^ljAt_(mIY5j5Z~|%jm%RWdBC$%{w)L%}uk&SS*XKjs afeu<%CAKE*g;6UsRV`|&m&vq+pC>S_2_EVI literal 2132 zcmV-a2&?y5O-NN#RY@@d2>@hnb6;_FWpa7w?IeIa5+i&FShY23_cZW7VG=TD#psO{ z{ciM{6W-~hzL`9>td$sV#|!;~_xU@{m@H1-!!;!D6naLkqInOARqK&LmlDXR-&dXe zCtWoG(oszxxkE)aN_GC9tl*+4CwB*hFVi?!e1R0ju)VF#N^H!Ryyn56>xv*24oqd| zY{9C)+k_pSh+MPUYK)0aSg;^u=y(lmRH6kx46zwMUDuo2HKLi1p;$7^cl@C{UVY0Qy#Wk+H4pU@t&D#m;fM1snwBinH} zcFKz#H*xr2HbcdYk*&VjuIlftZpQ2;wWb%sUc0x{8fJbN>r6bqYp4yE_`UocXOp*D zbz=)t4uSCYReD~-IbF7oxa_D#uBPl9&7)c8w^~q+0%8?&6kFvV(Wf$LyJn1QIsP=Y zL~#!S6)G}qysUVZK*NkSK_?`G1k5;9+!Cv|cLJ`$)g}l=GCs5R`;_ldWcrf^5Z(mB zlFjNRg&oTFi!J9+>S}eSUfn9PNO(BUA1~XAm6NWRg|*xNkY{eYJG5B?{5r%k;f@0$ zY=)xHu@-P|1KG+MPmdU+hp%&)C>CyaE9g+kqI(LIc;Z#_GAQE?^Oj%+WT1h+r{b(K zm0D`Sj=}JtD5QejY>M8e*o1Fx&a}nU0$ML74?KlKozvTgXYIhoddB)(B3c1P+HR{E z7=%72h`H28H|1xOWY$!!K*r_X@5l<}6x3+30iIyVMzY+jyjJ=g8nAgAX2Vu=Fyuhx zTz=%h_JJR1x{rJhQ1dK9(_qiT+ch;GJoVqMaG&US?n!?ZC;sjkX=y%n@aSvo#Y0Hc zX1ttZH}1f@IPAE*c09BX-~b(K@{%Cl_2!LAmdj?hu0*uECH0h26c!p{1W=H-_Q(A9 zU-&i1T%cMwP^r=?K;p-_G}$Ma-TX*8-O+fp_4@L6X1ls z6%H21y^@2tU6dZO=^csAu8AOehs12y3>-soG6!{GI zIeMbp5rzZu7}1u>RYc>Wr@ea*_=Bd6&%UZ;?o!w#5CBpf4dQ?xL=+@)+-u}Sum1qD zI+VLlJ(8ay0wqxZhTSEvm1EggTD5dCcOx;eq`NsB>Finls*>fST6|R`bG^3)k6!Ty zIFKEJL|*#e02feZ`me73tuawnYP0*8^gdhmsb&rFSvT{sV#Yco?|2zth(Nq>RVf{Z z<5JcaH%{J=7i3YmV|T3eLy-*Y4)M7Vm~2#-;C_dNu+o_!!c}Mfc@T}1#By50PN}RV z{>Tp#8oVxLOol|_Ig3b)Q%fB#{Kkf^_}Bj)O62aZE(*(JLl*Y+i*6y4e^d$=D=l%U zrqCQxEfvjzyA`ua^Ui{|{^uBK;Gr$SD}Sko^YGD!p5*&|>gma1tvVNieJCZIP@6VYQGEXnMX*hfm!$iQU*GLJM?L!Z^ z1Xb>)vbZI{0IhSs0xG<>%Yn%$@ww;v$JmIhwE7ne@Vs}9}Sj%oVL^^a?@PTjBSjBvaxHI zJ6C!4zaw9aueuN|R<+tD7G-T5p(Tm|=poN9?`!5c3{I$kOSah`Bzli}#PAuOqF>TY zMJ0ba)WKE?)gmoJE3z*yI~T0&>5>$@Yw`DZa4S6=In2vPYcZR*XqzV)4ANhef;PD@ z1r|_EVmc9!-r25HXzLub*2s3(c!ai;oW3z7f3V&s#t7L<0uQrc3ceQ5oS#`{ho^!o&k zZQUK3@zES3@b$WjUY=7(?QzWS36$(I6iKC*g1aLMs|k#YT8^9vEJ6m?R}Ulw)(7{W$-gmlVp^-~jvJYboU zC!=h7(wLRDgsVnjmNDY`9I0 K{^*@^iRekhY$p)_ diff --git a/assets/data/tool-ui/dns_record_lookup.dat b/assets/data/tool-ui/dns_record_lookup.dat index 4a9a7a861104864a90c9a63db46f66e5ba3e922a..dd130e08aab6a88acd7bb0fb3119318ebfaafb6d 100644 GIT binary patch delta 2151 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 Na?Vk2Z=#n3PCd^<6Y~H7 diff --git a/assets/data/tool-ui/domain_extractor.dat b/assets/data/tool-ui/domain_extractor.dat index 07b4f80ad204a6f230f44cff815c62fc8dce109f..8de39e9366099085247e5cc8f7389db196e5666e 100644 GIT binary patch delta 2184 zcmV;32zU4U5Q`Cz8-I$s_o}RqJNrV?DMdaS(p0!QUhq+VUJ9SbA?mQ&Kn%7K@8(r- zToMJ%;{#G^{aDIc-hrdmC{=1M1@=-dByiSj*USo69@*G$|KM5Purmbzp@bUKEs*Sjv#= z0wMjCa_FJ5VtiX#0y4bs)Zq~a%3Q_wMbg~H{irm{;(OQTkE=yCz5ci9Yy?jKNBaKb zSP$K07%4ToU|Zk7KKBX=AzjMMOA~Uz(A~CkvdjgzF<*?`U{wqRB8&Z)veCDeyiEW& zdj6`rq9!{}b$ z!J0xgt;PAwd6GQJG@=wTlyj8mPZWO1348F za9gz4J6=yO>*BdX5!1NuQwaYx2n2LYo$+S-$!7!GnSVB>Pgvy#UeB(`?G3s3&0 zhro9+{6T^U#^?E$+pJ2v*^DavPA$ecGChy9f*zh3jlTmX>`lrlW}(;|r1buWr-xRM zAG+!I6Mw}+Y&P+%7qtW;_HkxT%DvcN9{>zu^hNF?ePVN=WV#6zd(hBCC;b;U#wkJo;Rk4lxMs=VS&l(?-Ir`6Mvv%`LyRWkkP^>E?h%z{{X;u;(>7> zsst`d2;<@XvFm*B9~vk1a14QVQfjpdIWboWUJZ`sefP~bi%@^oh$>cDJwCIkwzaWM3XL#d*=wl2QmKH66AlN-h+MfKhPyjo@ZrvXA7brXzK6&>KK z6)(i{)7Vm)$bJ2fFzEG>X&WV{evc|lhMOayGVh%4MJ=g*n7jaJ-fT$tG}Qu}j%6d~ zb0_7zH0aS~2tXz3HWoA!D%FH`?@f<(lz*f~m_boP=AWtJsR5m$SZZ%su3U{pmm)@C zemM4>)}w0mPf|e&IA*K9o|ylqEiRxUb;J0FG7206mRn}Upg7KF5U&?j$@N!-00`u| zq#7Cj?3e|WYn&K{!%4eoi&)IjL84$vd->%7CHqknMW zwWDFTQ?x-JBfQjD_FRFCE3?DLK<{Pe9bnQ&Jl7k5beyuo&_q`EV$lYbp`*67R zIMYoD!1cX4)<=crNhIsr-=`Ih+=hNvHTSEZx7_ZVfS2U0)$8%nu;K&Lf1Sub$cte~ zKALM8@)TX&2}*q_gZkm)au|t`oPVFz8+Bx%|5OnJ$BwNVlFciqrk9$ubK3}PK0-)Bt<&9T(R`Bal2wq>X1mm1_9`H_(F@D|Qf5#Uq{a41Dkv6uYFpYahrKv%kaf?Aw0wWc{1Iwy2GMK$VFPk&0}0P(Wq;#aXj znIHt1MyJL95Q3dZR^(Hp?-^o!k&!yvWI_f|9{Cb&VbPEiNz7 z?``z|PN=>P`myHBOjy{zXnAw#%j(Uo4)%qAA>U-}0N)xPO=(n2Sb8UToT!)6JoSET za7!P;HY9HTf-!_QaQtM-g6U+Td>Kxn>In02E*3-uuSpyk2Y=no;(%4?eyz+NGinuI zlFj0_aZYYz6|b53iB9%?+R~6C_Wc7MeciiASx+@{><``UHwQHj6yZTVc+=Pus(HY+ z3w_&5V}u69*N1I_q5m);Uf;suIWORD9c$nNu-LI>J!u?y!&H zbgwqO57@XDzkfu?PUc%q>l|tgXCld5^>i9~womu;e?>FBm=X3hg~)wkRQy)Xn^+=8 zDF)~4@#Z9~9!n`e3yg=C6>=UuTniT?5WGeKIjOh})MO|c?c<`AMTg#i&Uiqd&P!ES z)Jh_ml*CF=h`rr?xQ!Q}c2?M3c#I{-kITE`fMR8-et(G2Ez_cmdNtBsEVyiJ!KQCQ zKK!L=c261|`RXZ|)IfJgqN|;MJ@7=+Io;6)gyVXWzD!#O5$c{NOgSSZIV`|jjWETV z+f2~sb)Ccv0}Q7VC4?Peczy>wHBrxAVgi)JccR^DHSpUlC9TuP2m(?0!l=WTRa~xP Kv~2M$mI0v@-$bzh delta 2167 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 VqbwPz*%mIJ-BPU+IdL64Vi$x2N)!M9 literal 2231 zcmV;o2uSx?O-NN#RY@@d3;<+rZDDC{UvP41V`X__D_*v(xoM`opZYr4*2tl46p^)> z0NA8V;r&y1nj_)m83n)nGrCiC!6rSxG#R{iBG$vQ?Nu zIuxO%jFvAY(_)w%L-_FbaXbIj))gxq|qTuM52NM>JU{!-Z8pe&A*^Doxm=-1z}W_cksS|%hyz4 zKmQVqe6{+MT^82N3ZTtn*I_IVWPT|Lt0#_&)c>2dVt))|_4ME^H-9P!+F zBZqSvo^m_C>qqh!TlfC4*`M7Ef)B2V0a%~EUELT6&XGwYY`XEJcXMJjzCrqqwyu)k zjV~!%uW>%Lt35i^vwB7Or8BrY|83(2o^wwjg~!~sY32>09qjPorwtR(j8i0PVXCXg zueM7$$N}J<Qj(!@ z#)UvmY`j&Uvr(I9cdE}PtpG0jv@rQ$a7xK5We8#rY`tmk(nq<|*zzw(E-QdUT{8q} z0i=c}JKuciamG;}V$MknlFJCw!&7PQaeDgdQAWEWzS4_k`=kvF)OrhyeY++WjxoI1 zgrx(7x&;MBdQH_Ub*g)Y_mtdwFK~%1X`9Lr5rzo3Ni|vxh4zgB`#$la4i!vH_dv$P zORZ3t+A2Tx3iqLak!B4K0Qx1IG<+1t{w;vS3!+U8g23BfY6{9Jo_E+%W-pa6JjT~f z7P6!RWY+62s<{6NIH{s@*pyBAuM}d!b9>cpClpmiW#?r$phQImtt;M&HQ6mW1HVb2g9<>rP`T4feqmMEJaYtt3>Om0u$ZGkw5St$L@~LMtolRWK{x-m8(@#?3J-D&UQzk{K|C3Ry9oEx|b;*|0SHWLFf6C=m2vq%qqP=f z*g@szyd>_pfx)6W$!omz*Ke4FxnJ3P zl8N-YnNL#A$1+GZnz=qi6qz^EKU?+!huHjN@UNC^$cNT4fPQU~2?M&{?JC>ntz-qV zOhKeh%^w>uhSG)# zCirg36IKX}9j4#;O+PKu#sKCjmRlyAUwHh#jF#MTDL%E3d)6}^v;X2WLNs$mL(O>2I@Eb@5ADN5~LP-vX&mWkZon@w6Oc95Ag zqJCV^$hw|=9)VO$Fq)rl8fqa6I^wx!ru2xuDkrrfha-<2@11A;;TN;XiSFbfhJ|mT zTMP5!F>S(l?&bKPL$PyV9*Xg`QT*-*Nyi)1*g=iIdhv0JP%#6m21_D}; zhY8weB*!^$5G#=ZN|Ye@9QKKXw&tJsg}&ZmKL~`5G(2C2h@{LOB6DIo&n5|)Js53k zX3!7uRW0;<8AdsA(576Nz_ICf@!fdiXl51sFs&6)>|Wi-lx`jgMf~}LIr@irzzbHh z!=WuD)iCr1^IMT`@ZHh4bdEH5d^1^JWg>)FOY!pPy!1?gEe0MxcBSFqkggvqFykZo z7p+gFt;ozwI-EkYQ1aP(fg=m4o^ROdq!c`@yj2ByIn32X*|ecG59XLogN2~Z0m)&4 zsjZE}dIQcQ@C~!3ej29Fu`U7@D4f=Wl5xSS_jzrDNiy;T0-f+rQ zVR&Q3VjMO6;&qBmkchc^V@idg>DpQViZ?9+o_u;4SU7GVm~b!wMgzI|i&xY>+@>Qv z16*!b4=t&3)L0=tgZj0LW{IT8_XS-5uhwS=GcE$~UFI-gjNT!V#`G0ol^&Tg=&%sk zdPl88fS6U8U?Kj82&l?@bIl3*F(lGkDeYk@jST#+_di$=%E92X-t3)|X&+j;5Jp#teV)DmIcuTaq8k||1p%$)x(X^o^w_MlpQ?}{#GRIVn4wha9VGFQMANm zyEQ9E045Idp+mm?f?uI;35T*-7CT_YNX=lOnw+Ns>gt#?Vkc|;$qE9 zdU=vC|8d>4VUC$#8aI6QJ%4KatlsLqczp(J90ckcLWVvQvE+9xnsV=hn( zLTY(o9%FPnpZ#i|>!k~SwiA`8Ikr5GO%JHu(U#`)d@REl|+h|eYZ FP=8%3R|)_C diff --git a/assets/data/tool-ui/duplicate_detector.dat b/assets/data/tool-ui/duplicate_detector.dat index 388c78d776ab9f76295a4e9d8a18e7db649deb3d..0ca8574306c64877a39bd4ad5bc0073b5420d6e9 100644 GIT binary patch delta 2119 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 delta 1377 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 diff --git a/assets/data/tool-ui/extension_statistics.dat b/assets/data/tool-ui/extension_statistics.dat index 7641a12315a23ff49adfa791a9dcc0da44379cfa..2010661dd0e8dba98888cbd43c73d980bda8e9bb 100644 GIT binary patch delta 2071 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 B{D%Ml diff --git a/assets/data/tool-ui/external-tool-host.dat b/assets/data/tool-ui/external-tool-host.dat index 9f4a79cfb09fd45947b5a1aec975b6a205520584..66afe23dffef76a6ae0101ab07579700af01cef5 100644 GIT binary patch delta 1361 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 T=5$)8r~Hp5z=g_qCNA1L3R0<^ diff --git a/assets/data/tool-ui/file_manifest_builder.dat b/assets/data/tool-ui/file_manifest_builder.dat index 82420e26392dbc2e26678a061db4f34fa4389cca..a716de390ce73f65e6a6718849f1eb04fd7c3aab 100644 GIT binary patch delta 2135 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

q|A#g`dY`96o-(7=u~VI!DNt`FQhlglqIGY zX@^ET92?_AFiZU6ymO^l28fUkzyf4lh#NhrzK*5)dXboZUV2vu3w-<}|HzXVx}IPu z^7}8bGZbs9=tLYZ^@v$o3Z?wb9`pzYDZKzw;X9CXQq!N@7wP?g(to+$c#dlVhlO1c z5e8I}*KpD34evK&t25EsX-@4Ul_Gxo$rwF;E4b__A$p&FJ$U-mZQl$luJ4%7*#Okg zOw5vvnr+%$d?8@_g1fN5P?7j+7NkRXKk|G6%BB&~FAyj--zV7IOcM&r7uy8ZYXnF$ z@e-VGW&TC}*WU_Tlz*09@XuTfz6}#yX&sYjm>`ek3i~F!FSONuHO2vn1==wVZRa2fk|$e2+j&rfcQ2y;!sU5=1cC=!%jTygnkJ(a;{C!ecdeZ2LTtD=1PYa*iB*(A-%nuUUtNm+v N(A%p5yttXDrntx#CpiEB diff --git a/assets/data/tool-ui/filename_formatter.dat b/assets/data/tool-ui/filename_formatter.dat index bbad27f1bf34ad9f4383df7b540468b485748a3b..16867795f3ea34d3fb5da9792b81e2b88ed706b3 100644 GIT binary patch delta 2119 zcmV-N2)Os{5bY3Z9Ft{`pFPn zK(X)h(AZVjeS4Y+A}RrHBH?)BaJ8~shz81eUOq8=Vk}@}kaxNY(%|AC*l+Qn!yO~0 z$^9fDx@)GGz=*z^T%!)t`?yC78E2;lKVU%jbP6M>2E=Ta6Mu@~2x9H%CvtunL-ANT zD|Xegn*R^DA7IoP&YPdiHUHJ=W6=c?2x2=hr2&z_JqdxiSW7H`etB-SJC{_%B#UoO zM=JKfd+-EGw1sUHSnI^f*F`~il5CdygSpyhCLa>8q6~yR6I$*-QF$>f`6B2@nyz21 zY)84wodCf8Du34C&Yv>7gEvg$VnM-^kE)Bdf-tN0kwh(A}iblbZ0nTWL=^ z;78W*+T`Cw>8vAq5*W6+2n7CkU{u!fw|a^!Wac3+VQvhwZhnvI=~g1{`c5tWTPr>L z=Zr;G5IjaJuspOOU-WE|1+}b6K9#fhguTj19%-1J;(up_GvprseOzhkmVMX8ngsXb zvFB|vHD@{?MPtwRZD}a_Gx10EIH_zu+Qv7xAx$+8a{kZZLzbw-A_v2{{L-N*1m(Hg z>)A?*W}W+5U3%ra=mfAt!CSEBgFVguYYU6Eu!qVXzm`^}=->3J^B~CY8SLVv6QgD5 zIGQf2j(^A^kK0kx9U%B6$63(Azu5qWvNAe>ON=TH)lWz;Lz_d-Uy6`5r57*?+Hc<* z?)awWUIV83*lO5G{)4n5T^=>W6m)?+k5 zi*+uAYKXj*DNyp3yh3D@aIZ)mD?HiW}pF#k_$FYsk!4su((sdV=14xQM9S_7QRf%qI*w1ny zM1Nde)w{cN#qttZlkmYkhoWXNwoeTcNR2=G2eyYl)Eq}!J?HESTBsd^ut$NRm`)$DCt2}e+ja3AB zdl1Z%gwrNic)HGN@-PvIuAS>mp@pbGqj7nn8`n6uQ3qyUR0ZsgI1%UIRY(-y=HPA< zUhy(I;C=bJ?PQr7b)7fzPhQ@g%A$$goNM}nvd*(csxpX%6`ZY_*$~$PR zYvoK=KfZy{)f#eWK!|d3r<-O_ua^8evbp2^^MI z?f)ccA8pp84|+ac)6`T%|4@i@JLtYgm-dzzNp~go&c9XntxS{Qj}C{ zrd$>l6=c{k_SHny&)7x8FZHkM*+PR7L9mi_=jfhvdU|v&ZaBu>+G_E)oDU+BKnF#( z#KRTlv>MFh4>C{CN0Yr%9Q~^$gjwAJn6^W2Oou&zXW3vLXxMZgAD|`uy5l6Rr$#pF zBmW7@(ZmeEON!hBu{#4U1b?JWaDBr>5K@=Ob!L?$6nkBiO(XjvsA%|@qg>5mqoxNS z=ob?6Rgr)+WE;^qZ5SSYI;p4=O8Pv%iTZHxLy3M=)qQ#w!uU`x&BZ-EB9~n*k&=?~ z7Bne>T(a?V^(E&A&O+K7;J4sN_5C{&O>enJ@&ux0!>R@QbY=XsZ+~nDhM(srs0KRu zrqga$wun%3`(hhAq;SH<YISC@yb`1PT!T5PXa({LlIFV6c@R1Mq@+(;585ii86?-~XSAx~Ic(e5HqEUh6 zC6*ySScv+i>N1|-SK1A@cT+Ux9H5+H<@J2U#y;Yb9|>0pL=J3Vw#v(fz!q;?lhF?I zoGA150S&Q?K!5C#)vE#Pqda4#EtB%63aD0E+xq}BTwJdi=E^GXfa0p^HY$}yQ6+F1 zUQ3cjis5fko;lsCylKL!&q z&{^SUu4m5_tWAW4G6MPPd0q;}B5>vp639?d0p-#!FF*&B)99!#sD?0xiQ`2S5_@ti xJ%DAxc7w$H>VM6yD1^ZLSYlG`BwesX4tKfUL#R?X%B%cOa}dZ|veOP=D(@&nD)RsU delta 2119 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 delta 1361 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 diff --git a/assets/data/tool-ui/gcd_lcm_calculator.dat b/assets/data/tool-ui/gcd_lcm_calculator.dat index 5393016f477433f0da083870a3ad099c055483c2..8685efe53222d18af92ed58e5eb657fe6ccd213c 100644 GIT binary patch delta 2054 zcmV+h2>JJ|5Umi9J%7G&>5#>2b5(>*a#d^@F0h}Xo$XzHta?tKQdNRgq=TdVWwfe4 zOa?n^`319f;DE%|_F*ZV=nMp;EI>OAk32ov@{e%z5bdcRQh90*ZUVUosl>SEMGz@e zpY3Z^+PFY#q?u2>dHHf?G>XTPcQTqSWP5p<@%GmH!fXDcV1LME_rYaCJM*v7`3nE)yB7%_uzEx5w*+mA;N4`Xn@A6;6Q-*S{*?s8k_gZ|Xn;9_E7Zeo< z*zYzfQah*cnty;T1mY2dG&i(5wmr5vO!$R|C?41QrOPugnxHJ<{j{^(BNQ3D4TY9ce0EQ z#lk$nFa&{S$3viyWxip zx)PmqLL-azjyB>G>TBKW0pUcE-Cd8od)bzE{XMS5ut0ra^{}#JDEEzev*p{>K)*vt zHf3^?aDRlZYSZsY8`PMQD|EdGQX?z4RCLItI~7CA1WSoqDo|vv!h4k6ias2{b55vX zDG6)Pn&B|{7c@Kmx*{nRD5!ajRxFMsnykBwjWx>XA?TuJ$=6$x_pBN*`j zW)O4#IF+rWiFF%Gsw~4xh)Kg2qe2t_y~c(}4AHitgE| z0nQw+CeT!(a(npQN@p=VqKy6awh&yL^~{_jJDKG1Hn}hyZ`1-(0tnM5J_@0Zza@3t zk$?U=aCFeqpGFgdtM(LFiEaoEV*8)k#>MjtUtv5w^0=b`VuwTqj>yU)ofxRHX3Z;@ zGdY=Xl{ii>=aEHO{V{VS(l@rdU0B_5vbN&93?v#JAVXVki(dF2=T+jef+tlj+YCo= zS2^HIM6Yxqm_KRy9EpTZP4v9PSDAzn4u9cl9bgv5o(Jvsswr{Plp9tH>FnX3tYjBb ze-eibHS(wBAi@3C!W0Lt6BN7uh=x28i<>0|qBdsxNO#%`~e*xVjH?=qBon!9=t$)Ff+-M@1{M~G^ddGtmD!d@?W*WKnG?YDSqneJ| zm`(3<#&}j)u~QEaC`;Z87MFHeGt+YeXZ}g{Y!BPmoL%X+g;QW<6jD|7cZp`F<;Kat zZYVQ?pxD(udhp+JbOe8;?y!}UI&)+utzaQOJX{SEk-O6kNFtvFg-OfzT7Nw&#ZtUb zbx&?RtC6&h0%RI19xfw(JsW(LzBm`eYyd(I*N}H@mv@moiV2$sefu()xhSs+5?=YXNep>$GQ%Jc0P}lDa7DwCWj`zM<4=2 zBF=F<6=+1l{e3uzAM}a$GKdkS2;pEcWup#R+(dm5Es%+B}y ziFb*W*VJTM)v&7|RoUVS>vZ*g({ICS7!_|MsDeXcBy3XMqUwEPkFiA=R$i>_MFhT- z)~eO_^x3sgt1rCJUVqJ;!aYGS>>Cw+A4mFq?^Dko81@xQ!~#+cgL~@(cfEBdV>8pr zr^n!2W<(W)z-$*YQf?gZ!=nUPhDWF&(3}c?5p?1MRMYFS%qk%Z`;beSo$)>*rm6xc z9&6S=3Bpz`U6_(u&VHXhy{>JN#!yXAP>2VoRIBr`tpkpAY=2CC#-I5}(e%|-ZyJ0u zlq2yeoVS20n^FbWd7s+wbP@#9procT|2QA`4LwnvEOnK}l`2BQx7){_okiUFzP9Ig ztEB^{b7>;-S|`H>_wyjGHEgYaSdx0@%#(gaKyRBmUDKEqNO@scFsn@9l?AkMvn@~D2Dl^t$zv4Ijt@k1 zksw6-Qx6o{Oek~tlql$*ee_z~)=?5Za{uqJ*X99z_G^?>SG~D~{ie_Rqko>GNf=;q kkWR$on;4M0OUC|hm>K(n{n#q!^*3?>%vOFSDTTQ=tch#(y8r+H delta 2054 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 FN^!Tg_y7O^ diff --git a/assets/data/tool-ui/hash_generator.dat b/assets/data/tool-ui/hash_generator.dat index 43efb454bcc1e494750073dd93de06fe58498085..d86aa1493cebc80854a339cd9119ae7ddf45c68a 100644 GIT binary patch delta 2119 zcmV-N2)Os@5a|$*Ie(D<$YoDribm9^T1gF?;TS?f&ymqY$wo+=J=sY92MpaM_%ei? z5X?0lQr)Z3idft|^eN6069uDm&PYpBI+sj@xu=?3j;1t}*y^(od>r95%XVq9pOV!% z`)v4u**`+@CFYJYaYx0IUd^;s*#&ztTCH9q$y<5efbK*fD1WldTi`XACXp3tM04k# zG%P+ZYIQn8P-v4jEbp^RxeUCckATw{WN+QB(T__CEk!uJ$WI-2Dzr|g2fdMGsH+#BNT?0DnZysI_n( z%m)YUt&US%U?VXkc0p$hdGu;a8ziQWkX>N4(RKx!L}7KlY+}&c88bxWaHrI(&d_gY zHq$H!HPME`Uu;4sd`C~NR|Bpsp93_GddJ3vXn)?T7D&-#?WQ=*QdCjMeuFhych&# zXMZsx{~J8{*-pj)U^8J{U%#=c!|3bEV$w3zHdJ<=3eWMF?2{9C3lrg$lue z0y)$oSMs7pv-D-F048gediqd!8_fo#==-`4oD@k8z>yT!BvNef@s$ssB-wJ9bcigZ zj4uJxE%7I2r9DlJ`F_-g?dnEGzWy?PwDUI14#F4(>OEv$Y zw`>R_C;^zFI6oS&2sbp=fZ8s=ZblL@eQu>G8I3A6N~9QXuYwv4F<7_kkwOQ_S}q*3 zUq@l zV>o)Qk0}ka_}AOVmSStgFp2~-gb?n_N}hSlJU&XoR9Lh_d(|npki9hfaFaqe&9^_H zQ(H4QbVN>f!0NkLp68Fa{f>Efq*gNxHSfwMscdS7KrJ0vw>MRV@vlpf^R~shw_d)D zKGjXKW<`z|f9vnGV~g7d`OYuMNq-?sUu08GnWA#aikWX3$4B+q&vo&a@(BfdNG;0x z@l*x3S7?bWv6YGHY|h2~db4{nfI5fZ zmm87CFVy7W*Cl%PfV2vc9V%d8M`AfAQ$b#tt1X=E_>9TQd7%!J_w8wQAb$!^o8YU~ zK=g5}7+$3EB1PPn`5lPoSDcWxwUP!pEdT|DQp5n59?^BdbiSfI_L;{e$Ay>{o-!?S z_#Tw6$_)Sa3W-pxd4usf1dqbj_ri+MOsqdGfX9%0v$l~?%Q+DE4`a=cMHqf!~F*{&%H!grIH zgBom_Q@Ik&UVEOG6gG|xcO%e($Z5s!=o|xxnsn<=t{QoP*);SQ&p723(n#4C$PO5h zj->MUHf%nZicky;x_=?Un0XO`6AI+{3h(&aM`j*f5(dZMZ*-Ou6FxYI#;6x zVwV>ZxaApyQs%KdpJBO+pL|;r?RTf{KB5@RHHojMEoVFHr2@k_LS<{Zk)wS4xg=`r z4HdSzQ*)D7chXW&nQWz+XLI0A9%vWqbCzs<%eIdwO^(}uC4WG?>W6GSr&>T-$im}* z5Rep^XS_rnqltN*guiv|UHu-duYrPOVY9!b7r(O+KQ?B!w)bY0bg*Pq7rEb@Q3~EK z1lQWI=(!l~H=ixqS$#fIiyu3(`)Wd8FbUmoxLm<_la$>`_7Cue@`g?l)z$cLS^=et zg6Zu7R<9)Rxqt7cL`@s^?tzvUC$iXE>c$WlR`Bdrsn}5WbRD`%iocTzt8ehoj&fa! zI)`h1u3f3aDjS7r7937lC<(kV^e(V@|IOt0mw?sN!WbKk?C~rLeq~7f2>>i%MCOu4 zP)L{+ntAZLY1&`|KkQ$fJ>g&r8hL4d;n&*B}q|_CV#Uo}G3bKoHp~TWTL=dA;h+ x!a>Lm6a}WOWCh}FCQIjKn`v0^Ig>@e9>n6E0ds8D`72oC)2TVmIl_s-t_w{M90>pb delta 2119 zcmV-N2)Os@5a|$*Ie$t!YCBz`T8aI}JQh)Rl#)5aN3FVB6^n)0Xkha_g}8Wd&G(yt zeIbtr^{v=hZ_^4{Qm-|5vgK=B-6$Z!%hB>dGM$I6A4OaWm;#!#I3wAf-SZCKhuf1c ztY*>267?6_5Z49;ycax&5*Y~(bCK_#c{>#2kHOgow-caJP=7hyBi-Z4?5GQ?DZ|p> z>K)m(4N}g1yLQVV*_(+XBM`=L@;p?K>k}yK;6CL`m*bz+om}2=oT;YO?ruG2Z;g@D z52L-9Fl1!G?=%gO-MI<*zs;#COr`aL!}H!PlIwWX2XkuK>^t2Cmj-pPj534#>S8zO z*A)`@H_N9;+d*4O$MHoCKEqsAIe&+C(D&#edS)4dlUnr=)nlxp z+P$NayKx48kmYcLtK~ZWUx|sK5zX11G_<$^nZ-@b>C7-bs&I#GTiroMw$3+8@J2Fz zzFeIOoJ3P7*X^m1bhC!NW@;lr$vatX2K>AiY~X3@+8TYC}zrzToY7B9%H9@o&?Asbij{vlwRp)T9so8{7#N}aSC>M=dR^Igt zCtK@)n01lFYr91Nje^eq2lg3*>=EE=Aib5{HG(v0C`W&yRqZV5y*03EW_SnTHg zm{U*9u@}1Pg2An#ET@tG(7CH7;EgO*gbg zdiA+^oq@7z1fg#38O?>qv$u`R!!N(ctd?1t*dhR9K0W;ZV2=fIJpB~?Zi3tfijNw7 z`@p5DsqiClPf#H5bUHXgxKpF}7vJ{9@8UcIpoWMgbP4KKtSHR-eKc$n71q0BI@5xi z1b-pYvs+?ftOv3}x@A@`*^fgz?`$6HQ}e4fBzdT0u7VC=>WL1)-T zsFkV$4@1sMak^5a@%x?Hy~&qH-})`%PJdf%gkVU^ZlXs|<~gqNdgoJhp$Q3EhvPqI z4>hLi%Y-_u0QE2yt7Ob7VNU)ExDmpkyYNLzT!AAq~1GARz3d|FcUWJ-4GJvIAp zs#ZCUYkR}+p?=6ik?!;5xYMiAX+y-AjKdS=sct+G22B;JVq-{bM{I6!X<-UnG?qQGBSpecWN)0VJs^4J@oPYc6${s7M=LmSX0?na_f3N&A@v z%|_t@0F))#$iPq2RmO-KN`aM0y38z2h8e>cP_!p84dspULE@(B-|zXkRevkdAP&jb z?+Y^>)pg}5TCwW%nNK~VWpT#jG=m!&kP8JXtZx(#Eyp^dSW3-4wvl*`6(x_iab)@P zHSkomDH^gZQ!Merhh&YK5mBmt}MLbc#kw{jBTGHC^|+=3@b4anNm zZ5YAR)Ph`ssSeZ)NxIh;F@FvYBbTa=hQNdB3|veqr~m3$q|oHEyT4w}@ixnQg`5ho zGtF|aD5|0{$zQNs%O{}WlRHK}?FZq~gfa~+#`w<;iRz(DIG3t7Qh-4X-#x_7NKcpU z^3ET4u4%G(`K+SigBv;oZL2FtFe_azN=QZQ>Xf%C?|OB2i9iirKYyCPWSji~fAlZq zcg>h95}}Auc+?PjUdy(5K5;N1DQIC21va=AxtGpGVUP~DSTbXlf_AJ(4k^8Y%ZY;O!XvZmVpWCx6 zzJE~nF!sezs&LOuxqp9V+}G(ZbM~EE=z@gyWSc%F>#oHy@NK0mdzIr$dfL zg^)9X7<(*O!!kALEv&DrF=>E}A+BRn_{k8jQ1xn@aJ*m_dFj~Lx-$69Ep0HTDESr= z=;U-U-5&Eo7uL*89g>O>=t=`6PsS0dzycdTIGz3I%J`=UFn{X1Y0Q7pVijPDkqnPm zuS~lSwY<|aK*=c>s5qjoE7>BVaVeyhs8f+|DbPobGMLW~kRPA z00?F?;Gz#PWj`t!*k7{gp9xG5rNWF9Y-M>645}&!V+GOiK!0%-5 zijm7BiN0KQu1;V=$3e81q&B$f+P0sc3A1Fbt|HkPFeuqj#u;0^>W7ni+rt}eC5u;A z457k%O;!}NyOea_&u{xH=t&;*Pggp}J|MQ(B>eCv_CU@~J8c`%hRMe}DGVVO5gGSs xwLo&3#yJ>-g6R0F8bLjuxUv@I34$)>uljYl62-IP_*PLJ{{Q&Ou5k^@1*fg)n|D{^~O-oG;F~ zc&xctz|KZMP6@anR&mpe$dA)nuBavC?@HJ2r0fPbaVC<+9{g9l;TO`c_K`(2eWx_yL^ z`}wl-C9&hPrhic<^V=4I>VmuyRqX+wkAf^%KB6aTQY>&527>nMx*MKUG z?8D5@;~{Jfv#`R0*6EJq+V&FoNQB)Zuvg$#u_v^Z{f0BJvBpnS=Qp>6Allfk~ydpbdd5hDJAA0#cZ=YA*7_{9j1#Mt>uE{**hFccO{-$rk1` zi#2+H#^0J+0sz?`(Fea8jUO4+`5?+=HgFOUjV;jLldE*-(G5jh-+oM#O-Q7V-Etdb zNpW{k?7!HKT0Ogb%zu~*ZYlz>NvL%011kNIKY!#usb|00+$9S9ZJ;}a9dhIGj zHKq?@89xPcugMIzTxBMXZJ6oDT8?L`qH)u1ccEJ1a=JDJ;h*to8|Hqr9)Fy|f`>ci z7UAo1thb?-GFx;ul|+~OH=cK*C);V;$^Qs@=Gq~fw!l5Tw3DIF6v`n#0gUO1*$@bp z@_(|iM-nH;(W_<80OwNg#)^g&Z>one%sj!vj%fh)6_2FWL9QcI>_>Qh=Zk`|C{2f< z|3&TI(+j*3w(&vDa!pJxRba3`99SrOv4#fxrig6ZL+^uoud&Eu{V1y+yPMBxoPlC_ zlAJ&ihJk57#30a=q&o`WdcJ@NApc$_7=OlFN#?H#oC-U<LYt3vnc9ls6(SLBfgP6V6xS5$J){MlTyU2%YVza z24$-d>(<@=mUwT%ZlbPhWujlgzw4|LX?A|>Q+u4PfSUHix-@ zOU6Fd-t|~blB{I)z0)xaq5dA!hi0~1x+#dKR;GscLZYJ2+QjcLH`5F0q}PNVgeHY}5qt)16_1Kz>^ab&J#|;n=54N4GwJAZu8SUsfz9IY6P07h98lg>4W+rIDeeF`HQKIz$opJhuy zH^#=itKguDW=c0LgYd)eGoF{-o(Nz+X$S(nGqxXleiU00TFv4ItYHNT)f<(Bn1{#dVddB0sm>n`X&F?NBX>K62Z8{#OcBxG{L3`9cZ z)yw?bFZ4#}=~Fx+F7&V$eEXG(nVeRTE@*-IHRz?={fU!0CREn?v`n?GHQ54uG@taxha9S+5-SWqSKT~F+gBs-7Hs}oXl_NDYK zM=&QS41=MaQ`gv!amFu=Ltc~(ua~B~qwPIwce$3$>y1tFb}e*Gp@`+5#m^4)*x~w> N2oUEEe*^7{Xr%oHE~fwh delta 2135 zcmV-d2&ngf5r7epK!1yFei0)CcuPemAI_zy$fe3;uCEO4Q#{6ye%P<^Oe)h7hfBP< zu|;grz#*xJ!kU~8G&-#Xy)7qMk)W{DG9u61rZbtA@qzmXew{I3Tz&>5k!X*u9rgbk zMMgZx1(UMKx@>z&Jk3`X$<9uBHWg>6=5q=pE+puSDJ|&j3xBLxU{W#4%BsR5#ZGaX z1Hsit@nB_rq|inj&5qnzFq&;6Jq^Tq6phg>%x1@&2!Q&P%QX<`jP+I@Id(3$W%)IS zPy)4p<87^$N}RdsZ2Kw4M^MCawR}+|ig5S2c|=_7KQz8|D&+z86MA;KD33@@eTV!= z4fH|~_~z)i5`P=%{(ew;31b$hOI3w(OyJpW76XGRMxKC1-Z0G#&Lc?nu(;^z@na3b zpGQ+k^`GatD4Hvq4{zOEW8}IrhPf;z`Y`l!FF&f%j0vRt!JpOC;cDJ+Ipalo+%?p$ zhQDngvqr_)dW%(*kD zMoC1|u6YZ~?FT?hYWzr!W`kBZN>xoy*lkpOb1dL`bgA)mAw?an$27mK1ijC&e7= zLRuJfNTeH~7qGibij;k4^ze#7P3XQznxsBwdVxLbF4~S-VZxed9u$#GDGjNapRXeW zsK>`nHaMnp#{D~Q%M{CHn@0rS=OWtEY_KtE0e>a7q`SASa%w5-`q#a1SB1L&En-e9 z%4YXTK|;xD$MxJ~R~sMo$>57wIWu*nal`Fj|EQ++@M($4&uFhO_~>}RJiY~*nl{Sl z0`E99+us1>rQl^VMtM>Y)&Z5eMKhUz2ndfqlg}(qlF^wyUqJr^3Q)vKL=mY&DnV@= zG=ErkJ6(B6hz|`$n5|GS=UH?pn0$W$rBZ4lhOosj@3aTtGtOQPmHnS-h{x@VfO=gL z-0Gt=xY%4;To0a(aIQ|dt9bfNGgy(vo-4L?C8oPjjrs9FsaiMJY{k5n6Ne60!{W=ORvgd}`Jty)EA z%Xz2hu6VT!#|B&oP7IG?JW3ZZ!rQklE*L#vH0Sek1&J6AkK#XAhJA#8bdA}H`F}a{ zMnBLcq}30iXU;}mCyJU=$$ECQ@WF+c?tjD1)t+7wf2XfN1WoCh0Zbib_+~09-hqVjbg5=B zR)awc@kEir`b6m-nZ&A1DX|O`bE)a6ID=SEQ!zbNuA2x-mIEC4bCf!A+lH z(VUn&L;TvmnA1){J}1ieGzQp=Cq zO@i)l^S)z1#MGCYY*TMk1b-3jAqD<6#@owCoSUm03Qz^u6VT*(2dQOsS%0PYic$k7 zM)O#+Oth5h#uEKB7>UZUq~w-{c=oh6UFuOjla)gC%VvHaMX?cF#qVTei7Q#|A$bKi z9I8Yd(szumz(ynrZ;U)^r?IA|;Z12P3ZJZk_qW z$(&#@dqT<>_tKYyj1DVC=FiTo1U_-CTOYCh+xkHN=3*#XO$CqSD$3zpFUL7L8{ zQG9_FYCB%R5q+S%0QTG0HoqWBTZ?_3&4R z|GH?KDiXdQ4R;&{ob~}L?Nhk5n^K|itvcf~I_d7#{b&~!tQ3E+pokzTDo?h+tgM7G1x^heF&dyiR~=Vv9oI#e)_AP{DEH@$yK6j-NW@X(XtNlTJi4MS1E;)JuF&(XjDJ6t!#~5<{_&0rLkK6bP|*I_ z=w26Fzxv5QaX`H}GzHb(lNw+@0QRdwnJ%yZv!~x6B4TlVo_Tez6Qj)I-pYV?|vU2^c*=Wo}2=a z%^lY-Eq^5ZpFuy$n!=L|ueAB7G@L;}fYZd35rrUuiY^x-*nL(^u6m*~+4Sn%i6}%0 z6i3-vRAp~%Ye&JG)9=Kcy29mNl6zWv@rG(1n~?`i$_o!(LJ(v^C3n;5C9*UlYSTcK zX;VyIji!TT2BEi9rARA=IeXSjeE{h*s$JP*n14x2u)Gb7@Q0qaPpSgYZK5uF2Dce| z#EB!n2Vyj-&Po%@{Pk)C+F$Q3G^s=ue~zwWW$+22=(zKNBy{ZwfN^YH|Asz-koXt( zHR+HUMX|REp@X=ID`Ljgt9+FtjBm_RAdpgPuGM1=1KU4D1shcM$Y{r30 zZhxg7CEs~U5uGzqomuhPlq@yb*pj}dG%OVhk9&dp>-7i}Lvsd$L@-2FVaSDiXo9UX zRFhv0=9RE$ETPhWpMNeh82F&^;{RF!-AuM#hIQ#4Mbh{@V7CHa zRTwmE1FJtY@kLCyUevcN5<~|1Ze`kTK2NbgdIY0(+DlH8vTsiQg1GkbR1J+l+){fp z-(gT*Lw;1w?hcLx77@)}je5b$ku;X0Hr7R7w&lHe_tzQaYVaXSJUvgpc|P0H`hQer z)~cYjdcH5*4JyA*op5v+o5>c#xL+v*;Lb`SmxW^pGaSSgdfCDnx_bhou^*+1{$KTF z;c;@-Hvq1j?#!(aHVHoY9hyD=QRlp-(so!b7_Qeu5aGF1>fWWIY;d6!G0@9BMVrs+ z&&y{~HLjhw{F=v43VU#?Sor2aHh-gW18;G%TC!z6-TyF$)v}KV-jcHMIek!Gys+9k zkir*Dse}_FV>^-=wG%9KtniY>t7k`qNkOCHP=DwQn{_#^}cpBQZCspG_Ir`jw!G9Z)8}&SD zn_f%Y*XZrgUD_W*>(e97ImaW*x0TWptq64qtO}AC)!<|Z#+GKwyjOb{L>qYnxl}8U zC~AhGFpk)eO0gMWteLXYZGm=;vJuvXA5klUoxGu8pZx`3Ecte03X%*^FSHTK>ks(5 zP0`ttUmS^ZS$(AL8PY(97=P)>*@R7gl{at2JX9V0l&Zntx=c_~l>)D`zk; zE@MH_UdWKiV<93vF~IXyh55yZ7t5kQSNh&D;O$Gry_^8uWYmM9V*z`8*0AqGLA{@NeQbTOVyFv8^UAQ?J zf5zNNrE94WB|330I_p-~KgL0A)G7{S6-!w#3W7cTV04;`aD#cg0R1Y))3WS%_OhG^ zlEP%$b>gcHR!PyjDR;N#a7^jAY!>1$?o_xmzhAs_zSRqN0Xb`j(Cy7EDUl!OO8MR1_)?7 zO_~r?q#07UWo={YOPuSXFpxeSSS=B%qQ#R4pewFkZbQR-QsL^(bK7oR{~vw!K%8Pu zLniVs!+3p_qksP%#LvKpdX@m?xpuHAS0;Bw7Zb8mg+~{q+GsbEE1g`|?DyGgE1rN= z!!dv%j_;ZDMEO#)hU!z3QGi+DAcC=HHd9`LC7NmV+$-3H_YdNU%}ZSq1ztkz0-?(U zemH8${8n=RHMZGGz$$DHrl(zFe$28pd>56cbC-N%_CVOrh?i`ozqkY0IuQs!%w1kN xEx#g;&`0oP+O|mU$e*|Kv4iI1>nU?U0yWXT8QyFaz3rbw_T$dg_rsbKYuK%Ef<8aHf_~21X`G``=RSx1We5r7W1Q@h)63@3s7f_<<1!H z1ehUX2D!k(EMEYs(~A+JAZY90=bp)}^YK;88>fvSIl**(Cj5CzkA& zV}7Dn%-&ll%NOkevK-LIhE1cP{C9q5C13T>B|5hZX8RUK0Dp*!+V)W%BLy;^m9zx+5+;S~Aw`BT_SGktikU$}d(41J&H8&hQC3KdStA<0_T zhSc+xa=ZAWr+*-vo4<#qcO3*b%g0L(QtSWr-Js^9w*b?LM24D)dET1b9&}2lz08Zf zUe(ib-q3 zb3W1=!+#ENW9fTQ1%d)?{y~5W(ADePH8M%{GMdd{Ga*?gbqr~IClYtoUp`J2M7MsA z7qq>&`E0bRo92bgV=eRAa)RiV1eE=pm{@#ixzR+kh3k}1GP@1|FN~vL*6#a~t%5ug zKr+#vNOjO&i(*E(G#zTyftVH-yk0nk%H-O`LVt>|t#!MGv>nf<>PEP+bh5_3ei~OX zz>PeEpFwC?Bhmu==05>74hd8QZry8%4>O3|nAEc^)@_Mjb$6NRT&FAdh7M<;ei_$Z;_dLf<$&REIUl@Pewc*&tcUDTZK z3x65v)o>zEyJJMO11Twv$Qf}6R!G-GNgpy;o8`B1M(gPGXU&ti3xa$vA=bhFr4p_# z95@zomPkr zl~|&;YXB5izy~1$L%-d?yagmeVq4&07Jpj!4nwNp9ml)UwwaLJ%XIKAgzfyAc(Q%JGhL#LV_(bm*TC@EU7o0mmxtlKDzqRJ2FHJhAY(P6}ZAFMO1Z~>LUVSAO+ zeDa|!Cp9a`dt)N24!9oy0$Bm78$FO338WdyqP;0r11&%lgZVmwkt6oU#@!Mp%L|7s z*Tq(m)8Pp}^3=UdIpj&uAXKqPWPjt03As1Zf-IICCr)rXNUk^~#*+jZ!w3!uH&1ku zuh5(#YmHmGHY8Mvov1ke;Xa=$;1%QmGEh~GAZeGz*az~hF9ct1>x+O*hMLlzpco!@ zdT^iZ?GDXq!AvJpvWRKMly6E|(3k42qbfhPz>m)9Fk6w|nIuq=GIK3##D7ktxb4mh z-yGm=-+*Xrmq1BuR}J>CC+4@KB7oRYq|Ua5WIm8gsc=LZ)wwQ`0CLLcSWfm(m?gLC zfo%QRUs$8B6jnJ16>F@ZW}M9Msi_rcrBqa#k$C86YicKQgAsQ(UH4TFA4Y~>Bh#BW zTz&Za%MqQBjv)YnV7()aPk+I(7wrrnKbWdYwf)ON1|w84??J#C$Wt%WblMv4bmNoF z01aobu#x*%8;9o*TO9~mq9CrSZxK8ek$5ZJRX-js1{%%+Y+CysZ#-X`R0T+cP*7`m z)?)ZK43)SO2{snd-pNG<2xR6a-jNZm|wxJ?%}{GJn{eg9=Y$`p-SW zSp(nKO~ovoz|lSSBWcXm?AR`l7?Mz%nvL%I)qKnmP@c6y5p+}&ri3C5L8bq}hohq5 zT}NF%Y)(>tIIs+Qc%K}NdVgPbMiGQ&I-01e?C8^DIp|#qIEmcQ@pdX( z&jNF`QrKKKqqySS@|b3%sP1u($~+D&0W4|#4e7c#2GC)y*?+U!`%=j?S(xu^@~Ajl zfzib_U#L|S{H(LK0wyf_vx$=aeMPqA1#RVH1iGf0dlf<=8jPBNo54UY^l-5QSvBAG zzdc1wVv7eLx`Z5hT23P{$qLe3DHo9nQDxgQBTl+dX$&+qI-;?!#iu!6xa7?J?-$O) zIh%?E`|{24P=Ad{$0UB8v3jOv0k+uRy~Ot~!f&*oLZ4#sjONC_2PF5(Mx;_8n~~|H zm6XsYdahpd-{Ol<^1lHRL1Vxu0}~|)20mUb$3no1sS)eHs#|5Q{>4QRm(gei0T@j& z;Wne`uukMNm`=3%zSRf2wWfx5y&?*{lJLqxuwDu=6F`!WP|B4?do~TzHOKHqH&uP- xzv6BDiBDy->PihZW8h-LWR<7jtRod{bG!UScpbq!`yuwD@xRlHtEH8&63TJL6T1Ka diff --git a/assets/data/tool-ui/history_today.dat b/assets/data/tool-ui/history_today.dat index 5aeb681eb92a6ae4d344298bcdafefe373d7f1f9..d38585089539b9769313eee2958acbc52c12f457 100644 GIT binary patch delta 1474 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 diff --git a/assets/data/tool-ui/hmac_generator.dat b/assets/data/tool-ui/hmac_generator.dat index 0e7a5b6f31f9e33de8b2ec6aba90c8a2b6e8fcc8..5e22323a819435a7a343000640cf2821ac3ef887 100644 GIT binary patch delta 2087 zcmV+?2-x?@5XlgbIe$wE3_bnT-;3c>pvo|@stE_@I8EY)qH;m4mur$;vYHoEIosl0^V64{$`Z)(<`_&-f z6@L=#gK>^XY4abAZPwD>2rt|h5~qp#81N?1bS=@&Q~~#PPJhFv{RTK7g>6K;J04~F zeDxtG*U_5_rbY}SZxP*Dh!C$NVx79D`1=8fkDJ-d*RhzNR{;J0Sa#5)JNpVXN}EoG2) z*TvAh0`;fS=mt*GYz)5X(zxYl+ZeN+y;y&K&RZe}6776^@%>i2Ri{&!i7ITo+Ze-D z3&?=IT#V+BUylLlM}J9{Jy7iXO>Sl*;GbXA#wy5OE`MWI07R3%Wk)CGtcg(0&5;FD zsUJ<0(SaV+(zlLSoTFE7#ZpaZ1e$>m!de(JuyEftkI98!Ga}G0@=6Vqio-T|1Qbub zon6;yqxD=3)q!&undWusK*hPZtMvISg=F7*R5>!!Gmzqbq^eGDmU~U-m9g3J99K=V zL{-3Mb$^)K?%_=svap5KA`Q$N|2{&DM?i`zYAl;G)m|LnH-mJeUs^8>1r9R+40X2P z;qK|IXxjdZkI*YHobDXuwcNF_K@z_<_oDyNk{YzzWS1=JZ%sc`e)Y#K`0hj)Y*1Fp zY+Z(5;``|_&|<_8@dCL*0v)s!^gDw?E#a#<<$u!?v_sK^YIhV?!@n~bbqKcI7PNeC z>I6`6cGo^xsx9dFj*OedE3bgCJm5@U5GoVp{6hcjgyKb4X1O9eM5Sqv zYJ;p30&!SdyksAKv0B8D>^UW$BbC7l|PEK=v(!nL-0srLZS)ZsGR#$>fL z-FBA{4tX`Zhab>ORP7>kBbX*@fpCFIx)wc(Etn!+dKU+nH3`B*ehe^BE_MV{k;X#5RhzP~?95E1r`G;{8Y^2yk80`q#pdey-EX`(>21I-XW-6Nq6n zez;`W_!gGQGGVVi2}=4FO`A08(N;Bn_%*E~<1Kk4ABlNg5^ETVUTRpEM}OU4Pu3W7 zwWn|@oM;zG2uQ>%0}xlx-}cM~UUwL5+7(KROXa*!)OE23C417UcEf-{S(HD<&#~v? zgnl9_oK+U8Ez}8?@1?1^DJs#yUNBS`IWt1$;7;drI>t!yD+;g|5q&Z%Y7iN}7F22dGZT4-y=I;8@ndI|R*vkhzHu2$1y7-n_GD z+9mnN@3sD*{Jyv;;+UxLnIKIJc>GMwnJ+jR6>vAYqDli%w|4nZi+_M}8UkdfMv7hr z7%>!y3>mlO8VU14Xch}ADu?v-liC6NX!ea`)OC3H#C_y;26QY|a?Y33!aC%8fU!XU z&f)uuceEENl*%~u>(-lqu7W_4RkOH>&$)UsWL$~G)Kc9c!PRr2Co7{Z4ZJ{5rJX(#qGK!G> zJs8vRCCP0GreaFEHG%uGzAGRd?Ol?2^7i7^Q=?RT$3=7YD_nx_?T@B)TC>bW9FvVk zg-_}I5wx_kJ!#tCYqwRE{~K?ss_Lsv&6|2kUhjfRmgyA5@_#UDZs0p`v0QK@?QmZT!Cj#(e)H32v@M|aOtw-n`wEHZr! zZUtKN*+45V<*dmZAmh&%eDh3Goi9nzedw~ZOeTA2tst3ctZ_S15?iIs{Ec{Nx~W<< R?`b|5OFJ7r$>aoeeXdQA7oPwC delta 2087 zcmV+?2-x?@5XlgbIe+Zd41=&D*W#3LbZOWujHBF~-@wgoluzC@|5XxOl<8s*c2_=H zFx3@hQI5DBKyyPB(oV6@wrfba{Zs>)XHLdWYw8RYn9{pIw_93z9obX>Gw_@!#+KVq ztxz39<}xD0I$5UMJq>n^miMJBvAUw)ANa5Or1ytNGug1=E`QgE6VXE=GCTwIx1g=- zR*_r-_n*w9(kolKsKc}PQH+E`Q5D6Ito6~5-UJquKrhb*Vhx6hEAQTU*(s(Nntd+M z{Q;6Dfg4OdzBOM>-+e_$<4(oRS97tCY3bZlK3N-}n3#Pn;dd{c!i+>^CWe=yj&=6r ztUN4zcPUzWl7BC+$LjB+#`LR8eV*ApKBH!YRXaGv*4T56ochbu*H@!$u~UY|Qwoy~9!ywegE!G|6e@(QeYyjfAWWsyNW2cq|y1Lbw*sf}am@gru3 zR%G~Ryh=JnaJBv1e2L8_hSmYStvEbB`y_onUhqmpRahYnw`tj0Oe%+E7CLWh#m^Wd zbtqkOGk^XBjhpNkb!)BZIq;SAOeOrBN%u5C_V4aPS;RDl-@o?J?)qA>yFRQhKb7;9 zF=V{{{p>&UoMeOwK~*v7&*t#w12=YwL=buxngp>H>nwSJDggHX(n(jN zFo7-BZfv+Wg`Bu#~%3bDN(&t{THV1Mys3FKExV9h0e7y=PUe|$zNR$g#H z8jlM3*X(8g$uUTL;Vf91$X6e=7gpw+95Jo|dVb|$bCM=aA2%gVzs#kjEZb@Q3n_wr zky)`;b?&}EzJ69eC!(Nd_g|FujU!8XvtWvtH#f!-gR5gUiPNld1KR}FN%A`}KGGZV zDu30^hE+k+S8Kt^ZAP&eCRdy{B1Dlgnq>b!PKW>$acj|kKk#@yNAYNjdX8!BfJGI? ztGz27oA}-x#g=8YSp{!V+gZu6z>-+%Vmqyp@uF)1&9S)tO`O1*Vp8NmDgG0L4=R~h zLEah1o@H*sRW%r63SA}z{z2IL6ZQz8nt$v6W68BUwf2Kai;ONqUQbYlJRN{Ja%;RD zFOUCD@Bc&ZR-IdrD?EajllY1Xi(gHD-hG^_kjgN>HvxcOO@980_7t(TUFe#9^V!&B z4i}4Eo<-M+6{awu_)iZbllw8TkL?7|8tP*U#c|`ON-`)s$Q?+Fgr{8=VP^Y!tQsPPh~w%kn0g#re}`8~S^*2c`q>kiTkldcn`z}w~h|+%6 zV^G%E%|3LaCvM&l*EhJ-9`MU{BSo^xM*F9PK<%$k{Z!|H=_TkDkATa+O*RvRHxfTG zW|PiUws7n3eF?=a&t6-M@;~+)pMNUs;$on*y~cK*^Z>LR^uK&YhHW*U4+HTahX-W6 zv}Y>SFxYrJk9a`)F6`^_J#Q^Oqa6>VC@cRDQLMGiCsU^S1(JE5YeC^3-lV&*t8UR# zZqV78$>Wbi4cz_Mb3C^f|4ADSgqo1x#p#yi$Hr7*vgFssb?owooF4xACx21D>ZjV! zk-j*7D1l(L#Y)Mf&iN8W@QY4NnIR1R<>yGRy6=Gwyk@7!l>%V~R`@N4ixy4#5CZsiAJSmoqp|I-)Q@@^rNs&KUAE=b5X znsA^ST7%~)?dWx@>Ku;?c3P?wAcx`tYgK5*_H;8Q{{Mi*Fn@SvKI*gm8Ai74s^$i- zl70rDo@=951mBH=b`X6C>G;$WuCa=+gNz&=c;ii}E37}1L;jZy77KWc&pClm=dIoD zdEwY8j3frSg49MF@#;&Pc7aJX0P~Bcp@liz?Fdr+P-MB~q{7#ycDj+*J3UjR%gze; zL?m|_1f((bo_~G?Kdur~AO{%0J?#2$#T#+!C$o$r)eR-F8mJPZ!Hy@mba+&x9T(#N zzT`x)QA0eLqq%fik2Q|$rmxAx?OH`(pijZ{Gx;lAuc2;CYf5KfQd7x2_t>LkJ}ug6 z7&f6i?+WbMKB$R=K|{;lyOf3dkM*Nk R_afCy6|1}WN`lO6oXGLgBdGuY diff --git a/assets/data/tool-ui/hotboard.dat b/assets/data/tool-ui/hotboard.dat index b3618de632c6ca1648e4b9c19c9e400ad31ab59b..0703a360ceac2492697f3ee5be2eb9a2ee1147e8 100644 GIT binary patch literal 1459 zcmV;k1x)%`O-NN#RY@@d2mokrbYgE|a%4rt590)31Pe{U`!_=geS0mOVnU4HI%Uho zP@pccCoJLpPt9Q8Bsau+L4_N9PpN*IOXejodbjM|X8OBb`Vv21O7K19%73+ihu{}t zK~BU;*2L$`6+yMv(lK}#e5@H5WP*uHD>jm^dDq_J1w$NNY|RK5&U;1sCq(N{Dy$G} z^SNa8-je4FE2=GUKKDtw)G%O~SY4RRSK&hjmqZ?v(@649)S4(RP!;4AI0RPYcKL|x zfy+yf&pOM7OVFcauMa?lV&Agor~K8(24LXRNpWB`b#}G4kmC)3YhUA)!W5z!K|-Be z++=6pGjZ-6l42Ab%tw?8zx(<4OU3P^($zI%9eQ&$HY?c$ULuTnfo48J^)i<3mUbBR z@{(}aTxxfPR-Esx*Airy;pi_Qtj&l7g^5S6+|}2SS-j4tZnxJE?;{xD;&8VJ8W{+~ z6pr5@Pp%@cxw2cl3kUkja~E32;vPaZ*@TpA8Y$lyU@OHsIs5W}Qw#HOOk#3w$`7DXSHCmSz z?rb2c8M|hqei|pYKxQYOr3!U?oi}z8u9Kx9KG5=#c@Fo&3I8{(%|+_-H|?|&JL8Q@ zQUL}pS;xB7cXmSFmu4!G+Qb}vt=9dJWhmLZ`9e?fS0Kre|F%n zz>_5dMH<<--VXhDeP=rpz-62&r~C9~7c?US61+qc>!0~}n)YoAT#{So`y-Qpw*v?9 ztPD)5*_N`|m$V{kII93AwhGZ&-t~ozb?S3BvwuuaP&PgZLxx3sGyO{!67*FTqLr?a zIg4WxtXTA2F&Z)k9|xi%o=rC6hgSz2;q)jrfn9!VZ;Ou)aLD20xqm@>#!3Nq{_^ON zY%ObLXl4 z3W;h>HrCxVB&Wa~`pA5)`S!q}P6ez!C_hsr%A71V_%y$Ub_bs?;E)r&H%Drnu1>W2;$XKc7198pJ6CH&a7a$BPxCfO|1~S<<7_r zD#0xyJnln^yv5fzTkPiydxBU!kc!zloMpRc73A9r(GGj#w4KsmfVn8 zqY4F;#-YmVt0BX+8>a&*`wC~J@miHD=^7^R8Rilp;hg4EivF(0?E_P8@LxGzXjMfa z9TI|oUBH_(GrHn-U?GcF(2KVJ7M&_qpb9?2@OFJStmgkK_e@KbQS=f-p6`1#rT<)X zJ4dalnNfMlYfgHUHW>XyVKp|`TISyMR%g)ovsI!=%VUw0>nImR7=EH$!7>X^vJ3-L zT5aXZghib9$3=B5qvG(R3#)zwndPwAnhtfqGCMWvT*CZ)D`Sdk|2UDY0tdqfS}OJe zr9Ymr)Fs@re-7YD=7{a_+{a9w)GoJJi7zCuhW)Q4G;1~5L({|8&dD}@tlwwn9?px? z{0w17b07t8h$DSQx1WB->ZO!W{n(w25@g{9B320BmX|r`K(mrRYQ-vK)cr$-TH-*i z!gT<-fF5IcJW#FZSi89;y!zs5mT@e$KLw!r~5nKpT}ZESyxAJ|KXCZT&~pNBty N#*00+TijKT5R}vb%T@pY literal 1459 zcmV;k1x)%`O-NN#RY@@d2mokrbYgE|a%B7;>zT2J;MEQO{VWjUu_E6I9vllDRnW7h zk;f%BBZ0}M#DbX*(HP3g?WaH%@*t!>@nxf*e5Qv(HJ2+g%doAS&9s1ipfu19CyVfj z(mdA6pd_C1NI;oh+I?qY_INOTI015!pi{+Dur<2UZ zArT-tC}Ujf;SMhq9(k7hfY;zY*X}qA}fcQ zgf%XG%_syA^XZ8=Y5jAOM#v%}HX7egwtSE{ZY~#?J%nlkoI)e`{5tR5B#BR$i6&p4 zZcD6Kgqbf=@hngtob^3fxQTP+_C*Y|NHh;}_e9iz%WskmSUArAa2$-V2|%xJ1Y%pe zJ)&no3c|nET?!#NmXue#3)6<>C_NyI@^6J**y>3Y*`kNTuk+6`E-P#r>Ho&j$JQr^ z1W*S(!$ns*AE_sV$)c_{b<6JjF*4l$LJ)3vQ2Y^MU|dnxTRdA zRT!_ViWah2_mfgxYn1WmZ{lD3!ne~dO)yD(L$qXs#}&#|SLTGsfJ{wVOa+_0=e1r~ zJ?hpZ7Mu{9gRq*pGqR|Bd+T3_ho8PXO;$iZ;((h~wktCO!&&1-Qwx^ zUHg2L#E+4V>!MS5=FK%et6%Cg9bQG;Ql}%7dt`dOb%HQM9KkfRkf5i59nNtwdz!XY z)fB$>WMi;{JsXq{@ra|)`Sl;W4KHVTg%53{BnIowAMb-y~UetiAOmu za5+DIuA`&H%Lz-72y6Se5cj;uo_RWQ>5+F=S8>CK(=Up`EKoA~tCn?mKb<3m`O zKkaF$ur+x58l^5S#nP>VtIwwPBBs-O;yl5hCzM zS@+Yasn<&%R%mBpOc-Qh@?5pm{tPH>9u>v|E;BT9|(z&L1tVs<@5PRY(e)F Nh@@9qoBA>TJueHW*JA(x diff --git a/assets/data/tool-ui/html_entity.dat b/assets/data/tool-ui/html_entity.dat index a6fd70f6a967c7594962f3c6be005cd160ddf407..70675a49d46e306a641c21244382442c0c9d17db 100644 GIT binary patch delta 2087 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 R5FbuOEQ0sG4tA8I0JFB)1~dQw delta 2087 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 GW58LhRAqVq delta 2232 zcmV;p2uJtb5#14xJ%1GfqG}XbRUBPsPM=0QPy8olT;|5~@h2znC!C4ev=2_^C7%kA z*CcUs4=|s=7VRXKF7Yq(4nl3oT?Rb4C4sIx*RO^$@jANe95;P@WB$aCu2d2v?)F5| zmS}@??(gVf{o?!+9kg|NuO+|{2GU%?Y|1xB)am5mE?buXj(@(4-2!vzh;*s92_(BH_vTC z2KTI(1^y6A=fFd1;bxwsl5lN|l{kLoo`qZAS)gk_ITllvBQy*{#uDPHCM}z{Trqm( ze6)B0t-uyQ1NNW?#X#JlHhy=SZvASLTKohRDNqS5s((RCYU|8P?&0iR?@u#yfIXV7 z@k-C6EuX*~N4Q8k&o)8J6W^NszYqD(7M8P~n1elQxS3=`(<&R)Xbuv!Ep4hqGQf4M z@&gyVcOvtXWlX-HNj75tIF;=k;(s98#g}E#B*|Z-^+U}LU;AWV=A%RDIN6ww0L%&A z*9GA>K7WZOB~Kp^{&w-4^Z8aJ3K;sG>${E2>9ft0puEi$A4T3h>+^eQ=O0-Tr6XPN z5+jrwqO?`1aqJdXe#>J!F)Os!`HC@I&(^umE-KF>7K~}cfLV#_KHe7eI~Nxk8TIH_ zBx1rv{6O>os90v}hdP7mnH=&`gTSlD2Yvn%gMUiRUg~O*>EbSgX*9#A71SUZX4A)_ zJqDmFkDxZY`H}NnpvRXtW8lGBq-N(>I1&psEFXY*MIFroEn#-C$lKD|%*n#cOV1Ef z|8B8hHkCaMU@<7~C_tsoRFh4kwzg<|-WfeOhk(^eH9m^;Z zX@7W)28#GP*sJ7>+ZF$*j|i^cFc2Z^Ltd){3B9LD6 zm9!LFKTm=kpv$pk{Azs>*KKDp{)j`3sgn(%8{~nT86Xn@2@Sx{ry6P%(Yp;HzYDa- z2Zw67(Antg;eJT(DpgV=MDybo0XQ=kSz5J zjR=)UBK4EDnu53s-`I?|f2JilbclH~uA038+?th8?;>dGrQLQx%o)m(xCk7VG9Kml z^D??$i-8dZTMt{c6C??3*#K)waOsyF<}?-YP5g?b(*EmrMEBj9YfBENm2PU=>VJYP zG!D34G9ierk6Rg_FyS2rf8dQ{(oPFhqzL|}76J4FG>$^P_UZ8Aamdr5a(`)aP+0%% zpgPgup6u}Uw5{z?g2;9Tv}x{{K(=>Jr?S@RaVY!LZgE6%5fe`f1nzngA22~Y5sa)u(_`6>AEld7 zEHAUplPKZs5oVbLr*Nh$7pIWAAlrx3L^{(}OI+rW+jikczOAt(1n?TVN$IWMSJyO$ zN)$|mB(Oo_v*gc~>P!`{{ful4c-4y*q5~GCA!sDYpxA*A*?-U>k+kbkm%x4D|5WUh zI|hk-gdN)Zk#2pbgb@2*j$e(>q{(_(hUdcJBB>KvWE8z=8|qf04rXoNDLm3m4Y<~- zh}zB)2B&U}OkvRiPn>>cFrme^2|sR9OTxM&rMbXDNKp49oQ(r3o=*TRwdas|9l+t% zKP`16UCGDLCVxm%rU0d#u8F7|rW?OGc(EPMG~=0CZhz$Fw9#-mo&Z52c$@7`noDcV zu_*d`PHb>1AP;Qnn`cDb$iV(nm1?xd^aCtnTeJ-qK|oBgTFrz>&ugohI>~$posoe= zy+x%7ckuStU` zg$rE>tsOyF{U&rMw4pI5DN7-@Y9~;mc5w9^^_>!+f>pJwnu}rk|9Md7+1*Qq zmeqE`7ZkS*4PdZvnH3r^PE{c>0aEOuDknhm;dzt%TkTr!U-Ya~kdR|@?zw4Y14ZME z8rqeROEI4+i1T+H*lQVQRXYbcP%agoo$;&8pmK*7`Z(awZ&TiEcAJN`AT+$r3*pI` GCp7)2-AGmd diff --git a/assets/data/tool-ui/html_minifier.dat b/assets/data/tool-ui/html_minifier.dat index aaeccf6814505f1a2a3dc096f2e346d0e21eca19..b851d87ed24a6e69f1cb4a62c39b6f3522c8cfaf 100644 GIT binary patch delta 2151 zcmV-t2$=VX5r`3xIDeY~f~k;OkP+NEkY2+;abjbWco8ZHL9Y z@eVWSAS(XZx^NTZD)8~A*xUcJsy04enoyf#0K5F@EL*FlfD>?@a1Zmz#{55C9B&d_ zYpf8KWbc@mv$)(>Rt(B7o)T2e_#s}{POWj*8s|f0(TCu)c7O91K=6)&am4QyCu^?A zD#0@JBq#u&-<5nD^RM`YuM9p6#t&+fH-zcnIUrAK8a8s8RkM#R-_@`bULSbp%jfNX z$oxKjkcFUr&7Dxvs71C@_j9T#DBsX+{~VC|JVAQ#%QU+^?JnkDND|4XuXeZFoSYA_ zdsL|^ow3+w0)L9+11qorA(M!9B=nTtFiA|7^t*11ugsaO!B`TG^B2=zlXloIlhieH zw>_F=lr7h)maBClXXT#UPTK2EOljQ81F-;p`@({uDm_6MMWukKsQR|whZ}GWZrn{h z4Yfqlp*W4fO7gSrW+k=Mudf>ac3m@7t?ox?99*Z3NPmD-1N~4Vpyk1G995{$u-n@< zOH*I-Z9i3mPDrd)4QMw9EKj)*Au?bZ5I1D19c4yj2L9}* z!h$(9T*bX*oXk;iiX#!~)^K;}X`;fF?Cj2~ya(6aH{U(ncc5R%JqU;^LIQH13 z6qhav+6ws}rIsFR>EX>7ig}sLVmbNegIe6|o_~u15m!1FXhEh@&7X=Fbx{4o%g0qJ zfS%P}al3*QCbE{+QYsUR!;nXg#mg*1V-yLpPr^F-N|t}aCAjw@Yc=N)bQgXV#g&8q zhiXjL`JajJKu9%oX#_!5CYC^|drc8dZ6-K08$4Na95R#AG1y|)0aVOerfyJz#ASa^ zz<&%&(h3oy<9W?3Ee+Fgdt|-e?jAa@2x@-RqbXQ$B5afB!767{wT1;CaKZ#|0Tk%7 zR12hUC2v;>80tc0IYUCaVL4Fvzr?gex+12hJ8%51KnG-wt2b4;4f$GeWclz;G3p1o z9Qd%?+~QF2`cUeHD!^wz1`z4w*iCxh2Quvf&pJ&Lad< zQp0YV==s=sT~K$~%7*Be5xzW==MuAHj}Oj@hj&eUe=vwEX0ML?E63(^;SdqPDNe`J zng*=T`u>Ty&et;_@&A6K9}tFKRey=aBM^ZnpQtaKV!~M(3FU@G2+Lo~svWYl#|YFM zt3zH5WNvcGmiy0O);~YJp&9utcCFL+tYhSzt^4I~m@Doy_W(l|B=SiwYKHvDt^bsP z7HXv4(5V3SFDaIC3dYFqsaEqjID7?LFlq8K_1(^Du4b2JR+BUF4hnSf`+w^xyATxn zd(28+LZZ~(HEvu3xFSVvH?hFj2STwAw0?2fFZFLPrY{dWf0^!b07gd;L;)xZJ zpfECNytVUY^L|BFg1kZ6vVUN>BsJwct^mc31fgF!=z-O|kB4=az-VS3DnzHyfETjx~qNBMJdlK4J=G5`j!bWUP`XLre z9c!AKn^+vHeYNAojswU_XHvn@bGY(q%sg;>VMDCeY14%$%FV` z;DlIC|2IDxTFUd~-nfh9=eMRx<4alEDHVEh#im5<)~1%egt64)RY2oyS9C5Jd0Dl- z@`8d2AMuFp+-W(Hu|W2yuC7$6>tQJPH6Mlx28zu(CRQ<9n08?17h<1^4Mfs*oMsPQ z-7P3*m9T=u%ESpTw||4}{>*;-`n-MzFKy;?+qkk`%&RNXmV{*p#!;6=5p)?niEY;4 za0rdIC7A18l~Gq=?e~7Cn^zUTXbu%2T?BxEUqKgb zTtwru;^(&RmLIRFqvs$jhC&vcuAD?@q8Ohar%lUBb1jU6As1LIt`hKrEUvDDw z%50#DU`tUMBY*9QKqlk@2YpDa)8G&1`q0lle@SY0NhN{Q6|$BC7xZ delta 2151 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 diff --git a/assets/data/tool-ui/html_text_extractor.dat b/assets/data/tool-ui/html_text_extractor.dat index d5571fac5ac5a487c6c002f43d93faec103c8758..324ff74d9d2a69b62c0fccaf3fa249634a71b11d 100644 GIT binary patch delta 2119 zcmV-N2)Os|5bh9=K7V*#cNoQHE2qEXc&o*oyqu}I%+;*K62&+YF89}%8z;H34K~dU z0;H_-ZLgvtLwv+d1fgR0l~pF3i<`d&Fjsy!Zc-{df>K{oM+V@vJWTbMyWw{bvBDp; zA8Y>0`4_awPv=d3@AbT^{93H8FAn*09g^qih_L7GU1~AIO@9QYduskF1A>G{f~mAO&2?ds9@JdKfXG?pX^y3P!o<= zz0^bmoG(M)Xzv2nq6!~Pax$6@th`oc$A?lD89MLIfcW)zT`9SJ6hF)2JMg`N<$wTl zi|X`6QL0wb6MuSl8tZPc=KMLUpxljmId<|$7d}%|kwt`F+s@()I_jzm)S{k9(RAA| z%g=(!-^Pej@V0y^iS^XqmxRe%^{$)THst2=a=xA%1tu&lj4b`lY@;;4W~|mx>6MPj zyw(pajIldCY^P4MDRmK4KthA6BA!`7S z98D80rn*QpmGkFXgzL7HU>hy;=@`C;8ks5GAW>ShxKLMA{#m0S zekxQNn*{&X^CR<{$&pt>NOltCtnurclvv0NFqwK$kRrZGUVQ_w{?vD1W11u9X&1+z$0FZiZG$ z8PV1bQpvDGE_>w6*rJEn3}bJ!Z1x@g-gJP|9mz>j7@5U0!E-+J;b5d&ma2(-?qT~j zGs#ATXhoV;zsWRdj7HbgLRtmQ;Dpou|EeEkTY_n%&a)q~xAen4NEyiiy%BHLZJHtN zVt*hHdDYonQaN;bDHd5~*=kohsxFCYg<4;w9zF6UxQ;~W`qe9yQ9n966|D&(`hXM-i5EfKzsp#^;F->>(!qC|=h*0_dSluajrStzF}<9ygnyCR<2 zVYr{F{#R1Iok6cM3KhzKGZTMFuVOAfPWq=VEIEO(gGNtF#%d2q`#*y-ow3<3oy5vE zqsLi8Zndrkd#=BP`J)T%;LOE&vwuo9Cf*GE%3&QRw-#S|GXA>vV^JGM<S@Kw(7}O&wv8DNL-Y$ntga2Hy zgJtDwr=$nfg{`X9aPXzS;RZKrnTVlRs;&)WDd2EI3y6cB8URTnrH$n)*nfI=93^JP zWxoL9lS9d@p{9&}eHzXvaMTkYN5E-sje_2^YzP`_Ed3|#JzAqgu}d!t4j)wIe9FT1 z%89Cj>8i=^$|R`FcTj_DZlWTfLTRSpk;uik0Y@#H9iiZ2q~rz1@IXd6K?J=k&kb$l zpMLVU31K*5rD$ACsdLukHl%eZY(>eFSJv8TplUhpGop(c4f2YDGiv>poun zeY~T8|L&$Ri9ip_=L7OV&12=VphMH%E~upic3HeL9w;L^J;72iH`tLIAOv`}s3IcI zps!v+#xU0m?9LJhyRfvIU7B@X+Wapg8HZ{hOS(2(-Zy?zamwpV1R@3!GK>8fAd8HOs?-+H66uce0e^s?368qXwHTbnrWfx~|N9=qV z^(V!-OU!F6anQRuATU64R2jL>&`lw`J#>xPTrdW~!%>C*QFf;d8JHHI=Cy>n6i>W` zreOQxXQ9bmT7Q#hQv)JwUsb=d-!r31xnv8$muYV&*^hME=NV^Wk<=_|YU+1T#-)>h zWgJ~qmI&RsVg&#Y>U{{?7j=Sp<-rw}ZPb0UvBYO#m!`i(B9@Vd9t(U-!f zV=V{RoQB?QghWbNN#WnA$X0oNZg-Fh=n1s)r$NFbUqDY@8l3^uv}6CCgm|J?=9OOZ xKWkW?#b4PSSj5;O$y<63vWP#No%+q|VxoM*YS2}AXCTAXaIuK4AH8oPFwXy4AKU-{ delta 2119 zcmV-N2)Os|5bh9=K7Z?QpsFd|1+&A!H9o(lP;0!xpABZ>fOt66eP`d`?$GN6H~^^$?V;%(K$OZ*YxSj*sOl zfsa-vC6ez$_u%B=P|O$&1FKmD@2N?x3Ub`hSg`jIMtI3pAmnD9^pTRIe2j1-L^Q&I z3?)t|ciPkuQ_ngLdnUOioO!ez_b9f55dg4Vlo36pmzX1tAgBtHB1e1PC2R_v>jOWN3`ja?l50Ninho0V%2V&Q&ib{@1B;q%|ZfW}d<` zR4)7RE5m<8HK17S3D~(qLkhqg4BjfGx3j!re}B9D5YzprLV&E~Yozry6Ulew8Yl5C z0^EqB7=iyI3SZVaZTyp|)DGkFq&-5`Bfotb(f{R-XI{fNOBx7Pz3ZnB=LVG$oB@NR?hF}lr8bn2@R#7Qe z8Z?;zB_fok_2uZBPgWJQ$|aP36g zJ0atH3l95Q*RDIjsEA12eSYk0{AWR%OOw2;E$~j`Ivdjb8nP~v1c!(DZ&JAl7Cj<8 z0e7OOFO1yyKZ=@cKj&sCdK%G2Ur7-->E67+jg&{K;Paoy_$YBB^Cw~jH z_Tn|j$6ebj9>e~6?8&I}crQQ=%<_yXq!M9C$uC9+%RQ!fKge2G#+$&ww>FI0kpfuIFPlEHbiGPK}k2)Pi#S_8@HgtqIx}yF-Pl(Y~!I5Ro5UJBx zRZ;?MCcla*2^iuLuDuMwGNkR6>Q&+OEwL!QX$R(3YOO{;rIgW|sScy`@$l7HJD8NdPaerRxhjDIg zaJnn4a7&xQwiF6w=E=bV0iD3SG;aATvyuRDtNc`AA?EdV(%Hd=-3k@R89`We>Kmah zE$lm}3_)mf7(*I>qHlMa$hm3##Z<~FZG8WGgecGn-a%C#NsX!G0;%Na@f!G$`4LSN zkvtp2O;fSd8PX-oKW7nSV}AfC*+L|uF{JwxAB@Sat^f+R<$>>Br<0AB96nE7Pm|h_ zz6)%$p;MvjT#VMu9>oRkgXuG(1McQNN#H*WuUc67->oSRQB;5@h#+D=h=JR)0J255 zM|w|L)>scrVApYRb18_m+{Z=FP=o|IYozr4<%AY|sbeWg3^Q#&k$>Hj$YN}tEodEQ zg1jcVQAule4#g0PSCh3kcKRb}wtsX+e1-vm{RH6K#@dz0nxNY--{(Je*5qve90Ac2$yyWS(8V+v#)CT}APP0RAb)&4gtrq}CfV~XBnP>0ePT^=GfcWWGsiPl z!HmwpQ)SUW(nEuScev)1yCj~;X=gN^Xv_^pYXNpA;K=+r0e?}>@_a46sp~#0IuQSd z!4@0`vvcGZHq`pbSRPK1BNyB-Z!?!(0wr!;8VZI>p7`YNjzzYe&>wtw(pQ?a{Oz$b+@74oVkX^lT&Da4h`@mHWVj?r^uY^Cjq^dc$GS zC$u=fAT5S}1b=Dc$haiG&yGhtW&!CPO|Uq~T7^@{2$+HBi?TilQE13u0JI&&t9@Bh zUvZJx>!B(!B;%?NQL%;BpxH6FL&MbF?G@>$gF8fp9I_((TmMu=4`)a1ky3GTdO%vc z3f0<_hn)5acVS6AvEmm#10!ciI7k0_Qs}Hhhto4ww?O+9Wr$nvXD;8aKL4Z)HdK8N x2NPc6o55ekYDYw?%;^bIr|_?V+ahCvbOFwmC>(3sGG9}t#Nxda8s#$&kanH|1^xg4 diff --git a/assets/data/tool-ui/http_diagnostic.dat b/assets/data/tool-ui/http_diagnostic.dat index ead112dfa38ecfa5f174005314bb78772f6d2df1..379a921daa9cfdbd183fff9c92f98a27edd076f5 100644 GIT binary patch delta 2200 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 diff --git a/assets/data/tool-ui/http_status_lookup.dat b/assets/data/tool-ui/http_status_lookup.dat index d0cb74c535c44299ff100cf03b73697164fba7e6..3c178cce8d01d0030dd951e32cfa3e9500b444e3 100644 GIT binary patch delta 2184 zcmV;32zU4W5RDO#9eRi;=)ck3b!q7;XAMd2$X!$g*!6!F_aM%7J%b4}Aq>0tiQlYX!lJBs;s zaK^o%y0(H1k;EO_Q=*~tTt*F?JCOO((VyW06=A8*mo^d{ad?555rEE%3EmH`!k4+- zIr>qZz=?Px)_=H(n7g1Vn$${KE!kFr_%l7d0;HrR!VBL#95?Hank_Yrw?Sc~JR#K* zAFt`0Aqt~hiB#b@1EF`c7Li<*J_0tO=Dgt15x_G~ieeImp6FaxFWAw|i)d6@H)D$1 z_~mq$CABamD$AcL4Tm6TkJf019=2<-52vp;VC|m z^t>j6uAG9q`?yMpk73!0RI7%c0+CVI8Vvt)7ZcHAyn5Cwf+dBJ(HQKJ-MkHOTi6W?i6FZ-N%t&q%frU3m3ZIOgL14P7@^OSpjc|IsiVVL* zp&^w!rLXHOVO1IKyp~1(d^mgHdrV? zGpH@?O8_994|c7eh5NdIb zZ4k;P>6lB#;J86cfkbZ)(*nFSjuJFi@<=g~wouMz`2&;W__kR?C}je3F}G*g zczab8`fVn_n#th5cr2x#g_kU-0=@mxasTY{30YHu{fz}<1tNimR9X*f8 z`-^9FGE&r|=aqSMEnz8n+!Hn_UiPy~qTS--tX zYB=DZUoqZSXX*C1kcf(#mVY^G z@^lA`T~3ckB(|^briofbu)STS(Ofkn{ZE>t&rli{TWf8z&e;~vawmWnSywl~`>Fc< zbkQ3gwzc|&Y0)FhaX(DGxF3+;m-g)W*1S3%IpDny3HQFMqKw6>{T>=pDz~3u|H+VqHnSWH!Y47_(jFnFz(v zbmd=?qQ`2Ks%>s+mDrQ)`X~UbjPW@~%7>;&bl*>_CG_|2w)>AcbZiY9w>Sy2RKjA0Nt)!x6+n ziaqzK!spWxPqk37+rWA5<*P1nQr}clZls$_F{K(_k2MaqnTDepn^c+cR>*C*`hI~$ z555Mepgm2Uk1x9YPI4Vp#t#t=9IKg zv{Z*GYsg6Gs#`HNl^2ZI+o*U=yk`P-7?(Ibr2V={1MfLIQlu5v#l)@)a1jLt?MrtS*U3z&G|&o~#IUHb3#5;}OJ&ETau zJ^5vj9&*qF{k6zvj0Yv=$oL?K|Fe~dToXQHzUa%e4ynUiEq?&zu_ZKyUoA`wfj?RG zdRB*N^RAon8TAK4&#OBhh#m+Oz8DXS7XU5P($r+)OW3H&xX%Ehg8$c&?y~|PPXoE% zP=J|G31+CYSW{+9+HPBp9rJZo^BnS}?mX?jBDe1)u|q~)Y9wsTsLsILe44p!=cWC9 zK2w5zVJ~8U&VO`IZoI#{{IUH67~ooZ12TIVM}S5)=cDgHO{iIDcjg`4YYf;T?2$+& zT((xi0`=kXVDtpeUs-26-37#*;3W8Zxqw6Coy%-3t(k)X&dN-cp`EHUCFYxfmPNqR zZ(OoQBS7)n;0-{!dt}MkrxmT;_L8HGZ-t;fO!DJhy?<&NKI81?TMXrDDax5uk#R+Fy4DxV$>% K#nvy;tN~Jn&`7QT delta 2167 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 delta 1700 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 NLFAp#Ia#s7!XN~SArb%p delta 2135 zcmV-d2&ngg5rGkqL4V8H7P*`^FH>TL11b;osf+kY}fwI;?yYIH`d>^m#& zv)3`EzjQW1iL!I^vhCew$_Yyc9nAEunU6pgn{puLMDKmyt4k;^+7Y#O&306XvNL9FntV#pr+a2 zJ1%;-eOP4laDUu_fsUCApgUrClQ6tQ)dQL!2T-H z>=l9+2K+{>V(JNpQK!1X?TDmzAopLLvgcUV+LAyp0tGnsUmy{Aqo*-f=+g>H3ASUR zx))9D6Nuhc7LUdh=sZ7{aXt!%^5tSUaN1QNR(~RW@3G3lP_UCllwxHZD13a4+3pF} zt}uc(Jh6f6PQ}STFgCmXF*c@GFN<@vJW76%Trw^&q#1I>GKn6tu1!y{*wo7MxU|T)}(({CPH$2jJAbXdc^ZJ z6MxWbOrlLOI(a$7iF?ze1_Up31FvdHfW@X{mz-(-x^W>*zIs+Xf4SEow5+IP(iu zuLLl8;`_l=QUCj@TQ|rsYcGerp$s>cW`A3btK47Jd`FgVX8m<-Xs#MlTf1n>P!6>N z(0^0i*1X(WeetYx%Yrid0;gYx|ho_|hnfNw3VBu*~gWRAus;6~!XekE;MtEvZlOapeA z@h*-15VP&-qE2RR2|r8o2iVm?eE5Bf^7g%jd-u1?kZA;dwD^6K zWaQ-qD^anUFNxi{&Rv|T#kr%mLSZoM3%SrXVfwXL8AMq9Z$P8$y3&<_kbg2I6s3r& zc+d|!IP6KZX;F|^qX#&b*(FO)^icwb)tvy=ckm31(v|u5#yihr6HDES<8&IT?f0?+ z;H)HQ(2)T(JNA)e%&6U9+c-H1;G5zDcSiTrhAx#_bxBm~cS=19cS2@gV>PB6_R^BWrC+|DsA~+)YNO6wzjRZD(k$m;AqjSEy2CKb**) zLQS#tQIFlKkEdma$y*pL04E_QTx+-(W8#+8`wl^f@{P%k2>@UZoZ z^V7uv2>6H-q^%928miE59fX=Ct~9u@)I;6Z-~)6 zr5F*9iJE`2AacO5cz=3Io8i$l0I)NKzBL`DB0bnqlE&M_&h`FB}-}NT?<*xhKPfo?ZL!C%3vj1xanBycy-$SBdM#&puG^Ku33?? zwfkf+tL5=6mZ6Ocb_OQ1<|d5fU_bbf&qbQlU{-9WJo-;kd4D17y4%8>7k{kfsX|O} zD&&S@eH>n18#%uhEz&6!r35}e-AwBqB<=&kbHj&FUEoiWWEjJ+Tz(8Nryz_n2LW!o7^tW-uxICG5&B)P_#}(;UYdNf7PqYY!OR;rFNU{ zV~LW&KCDqIboI(9R1O0k5RY2njUdGrww@hNwic=164KBlHl`>Gd#V7>;~WP6w3s^| zh!*>G{A&-vW0G2p+6R@59*_v?JghA`bRG?_%h!kmBT!nGad585xdDPg&4M2g)F2m{ zEtvN*#U;yn8uG8aIFhqO$@?fZWJ3sOMDu*J9Z6ZX(A@JiVVH@(W{WCAP@$a$iIp(= NDf`al4U;?}V3tjpGPwW% diff --git a/assets/data/tool-ui/ip_info.dat b/assets/data/tool-ui/ip_info.dat index 3a0cf993efdf3a2b2499529c2c3be8b5b961ee12..810546d9954952cf417feebf389694288355fd7d 100644 GIT binary patch literal 2146 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 YoijQ+CA0G4Hlg34r(z?|Z6z%iU1@ANt^fc4 literal 2130 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 K9Z=$NekyN4l^N9l literal 2116 zcmV-K2)p-LO-NN#RY@@d2>@wuUuC zy|w>iWp&77RRan@h`5)%u1awo6qCYUE$Nysf@*z_n*0?(@C@T;IH^Pmc=B!Xco*om zHq9CaIMcQQ&Z~a3-`d)XT<#G&f19)Tr(FnP*@a)ugO(<^IQ?Sp5V#NTNv{B#K73JgVK!e@t9 zU>WTQ1R2@jwRzdju$4%I%>hCNYBYK9WZde+G#ic7QKX45{9we`?X?!4T>Rc*Y;jdZ zjRQK7YWoQ5<9$ff<0U9N z28{$Fjoe1kum_~9;Jej*fFLUV+L`Hr#}Z|o$jaQ)arx>REww2bNq#3Vn;i0q+C5$F zuge{FUG|EwIV{J%g%8Y0D7A6mzcj$6IJB+e*~E6p6Ue8SPYSZ!%yO3H)ak!3WiXsX z#3RKWTSe@o4Jc7tclGG}uD%wR9Rr+y!(VaccxQzvr<<4o8&hDZDbi#`haz*$ts(h4 zSNBn`KoHCLwRa6HfVI+syX<1_l}^lyj%41CS_bCX*&gWPS7DX%2L>*LNW(w(BFEL_ zo^*!r?W};oJzy&1Bl`a>{=~Jx`5OzCyNX@#E8?5M_g`QRj5mId0AFfUE=g$+At9>V z;`HcD;}_jo9jUn|Axsm3x9(0R~89({PfeJk@9nmtiNR&O2h93s>LP?o?_D z4Jx?mw(wSD3mG~cj!9kfaL|Bp|=2w@o7IZ5=Vb&u#oyAd$k=9lJJdno5f+2dn}%Sm|4D?FHf5p ztoDL4EAI}ya()G~40nS@n9+&}RtSAy&xb&CbTyO$FM9{+Y|hc^A}iKxA4WK z!n-VVy7?4(?YS+$*}QmiYcJBgv0eQF{Q1>hOZ-?|`znHq-B(7F+_K(&h6VV=py#el z@dr?0(;8K3HyjC0xfNA?nutCbA?Ky8n~C&3wrg_8 z8c>E9HVXVQ&)XRY7IlpaIrFGou9pY+VD!>18B=;IraHig7W9L%A7f7})9PsV1_LLP zDb@Mb>wD&$aV5wRwFT0=>q0(~m!O%^tp1EY<=Oqekf*MFigEQ2ipt4k zEq!fD$-p>pX@>E2v|OV0-YuAsiI64A!%Zc{FRz$yX=!tSqUGZfWRtGPbNjs5l%cUC z4CsfAvYlxJv8OS&9G{3oaM3_Fn(nN~nQ z(dJwjPrLop4~GoiYbB^wA>A4rCue+M9V5)N?b;eH2D}2uXnK6oyAaHGR9YvV+DzBz zk*EP9!#y_m4+6IV~s)v%g9D5AO8>6&G^`Ysfh)CN1{UG&dgSFROtg$YGpkD5;cSUXL!b& zHX$~UVDOA-f&xnaf6sHiqH)YZnBSv@9?M9yn3bq@xvoNKOEt%SVK{i6$XJJ|B-n9B zWtq0{k=e&*9e&9c+w4xm`Q!-`lL)AGXS65aS}-~+&snEN3ii7r?}T8lR*2@1 z3jZaM9n-N6REX}|RST*@Tk|jMpIEVXW!Q@Z36Tl+~;+as)b}g~Q!EDr*ZS6Bf=To8&i^BT(fE|6hio~yfqTu7q z26}p>r1mkWL)2?tn&LkD)i4tdDcU&csYNqyIs`k3Dx#Ac+DWkwZ$#8{k`7HS{GFOB zdG@qC0$p86!0RJu<{@Y5-}t$9ClhWM>utVZy(g9#v%lnAyIPe`~TK zQwh4%*WUQBT)cVRzaTwzMDo6kPi#21KrhJqK+unzjUYY% diff --git a/assets/data/tool-ui/js_obfuscator.dat b/assets/data/tool-ui/js_obfuscator.dat index 90f569206d7143084bd5afdb60328745bb2dff81..bfa01b2ce885139a5fa45fb8e90c7868fe9e124a 100644 GIT binary patch delta 2103 zcmV-72*~%?5ZDlqIDbTbZOO!~MGk!=z>LxsGABsHO0@S?x3do_S6mBn4_4L>ruW&%Y(T|<(2(8G z;%9mM>Hd}olPso4meJ&##(5|!MCv^u_vG>L?eY~^$K2ZC(tk@Bj@u+P^}}+bFmX;0 znZyCsMe>FPQuZ2)U-9)YfbIufR?dJqD6VL_DZ*lHrtDXx$nx>72Y0MJ2${`!YmDSj zi;BDvGxDlLXLGQ=xl~;R@gPMmYuedlwyS1xRSZ%12}DCC9D_Jvnz_jSNJC=d%vk zbCT&KIrUG2G^#;Lg97Q-M|s`>4FJAIlI3;s;2;k}A~tjbDLy>>c4_z={ob2=P#f5Z zS0!LXYMMGh_|8*}$(kz5L~0XYMFGa^Bh! zYNy|h!|XL=2!4n2H)^vmItgG1j)J46CxWT|3=Ef$rR7@I4};!@PXlj6B(M>+q}aWf^`o@nCD;Hm=D6xUOQyg zg+=C`FulnOZ{pLs2f8lBbeHBRrsV_@wf-{8bdK$OgM|S1{-y%8JMjK~qgv`l^gtS2 zV6k9)+KW8{RSf%#E~UstEis(S8{&pzjI0zd#ecX5O*@fSEAcL(^(!1=`R=OL0jN|c z5RGSyH5D%`G_x-(AS)QW=29E&t)$b7xg|t7Z(UeU79!}qAPCEZ26(F>^+?&q z;)eygSWLtk!@!~vlJ$zjGw6i&MabergVu^t(H>YA3}@CSq~fsxe3=f! zz5vSVrHID4ObMOY-My8BSvaH$}WsiQ{HVCmkPvVQ6jd4?ccmLovR~u2?}|$$8wE6`6HY*ER>85#jr-dgTz`e= z1}F_G*Q8wMy;Y=8Wd2}73czr#7%O2JKHy}t&Lto&1_n#YeCx?o#-Q!p~;EZ4aHT0J}eHfT_rg^ zI3ei;TVyY!IYnAs5HJ<+&4CZEoweeZ{?6)VKkKgf8K#X$DWPzG-YTKpeK~%g6PX}7 zIXZR$nIzrVtv<3NYeYmY`k#NH00bI~HZao;q5X!DNfY9nO@fkg^?&qk`yDR*kI^(| zQhitPyBbCb#R)vX4KUio0PSk(bwU!9;FGzhBFfY|8t_?!Dx7y%E{=Sd6pCfIJ7fZkAV?=bLzdTUigM91yZc^J%NKuW`bn3iBpT^M zY;WmrKuqyAy zszJvu?gQMN{5$AI4t^Qtx7?Z^Gp*|9{X^E4Q3s>Q zC6N173{4wN6IVz}=m!Lbz9;D|I^v$jkHxEE1oTQ|?59;pO@%SJ26ns#9Ksz&XZ1W< zxC?KX)!^sdL?hFd#`cm_+kZa6V+53slA|2=TEYtHZ*FkYESI9#88PbId1f1R)GZky7b6H}4&FFPTUzw8Ts{F}}hBlg1gUH+7 zw*2#q!dmg!L9^>}W@E$jR^G;*+bruw9g+DpdU-)6_b`}xO1;X(XExJz}ojm~l hFuBB?;e6h>`T_qKKY!Q&OAY0XUyW!2@Uz{O zZ|1MflQjoCLTkM@p^q?6~X_D#zc`MghJ?xVA&C6>224| z9xad3->`2{Jd3op<% zla{?-mP3{0P(wl`nat-66$gtO^eR621j(>ZEMHTLNDwS>Uqa6_}>%T#mdY;uRz#?Yh1k4I*3&U(9_X$98Sa ze*JoIA{6O|mYGdm?O5d-9B-^(QoQ`mvXi(G@c50=pp0TOx ziBvdl>RYJatI7#^Az2bf7m5l!o?`f&)zBS^Wp$b^rUjSUtn(WNfHEr2;UcKC2}g({ z#eY$#i9RjIzAWPf_8ENGBsCSFo<@~#r(CFo-1%)Yi;^-nwgnlO^A(@3Kl^Clr2fZx zRHvp2KybtlD2TQL9dgFDh=jN%GmP9%!r^%=@23-9z&mGvNicwKak0#+?}csrI)!e8 zf9`%FHdvI^iJ}Ez*-_D|D=bNU%2ZVBR(}v@60fqfl@YyFM8QfxjqzfE(A)xbsTR4` z(s=I`0h!kA#4%D)!9ZYs5^t3Z%E+LU`m+T8C@zf0bdssJeSh2NBzu3??Q%TVi|i!c ztF8?iNSW;!i}d)V>q>yT#+ivfvU8I7e5^?te8tWD_H zTK^P*oeoT)9x!+1OI4(BN~}+j%*b?^7fVm16PzGt`C+Xd`P~jVzDMdBul2FxRq8 z?cbZ+dAp8go;r|tXl!z@IBApw68UG4F zb;|eM4>pK-J&ybq`ivjxl`=cj=2m6N6uJNH$EjN4zv%=6XWz;~ZSulzF(Qq_3_nl4 zGCeX`0PRh)^F1CaNRF_8xfn&+&D06lLn2#%znE99b0vr|kSkcjR)1<_6jPxa9qj+K zw2iBddc$!J@L?7SoIlD(7!@tBJpC#c`tEoF`lJ=BpE@CYl4$2poau#C=a#|4}!T8=k&o zyo4!PL}i866~)-!#eL^cz2ro6UdlYeBdoDKurHKv7~17wOn*i$92FYWJ+I~LN3Et? zre+7zQi_M!L?kP~#|zzsgR?1Lj#Dn9nlwp@$oVBShWmo@b+KwuW?8hY#i8zKofus7 zb6QaOjJ}RYn~ZA!MAbj|P1bb~hPu7tZ(+dJKYs{NN<7iUi}I+;XV%;|5Omo`l-Sl_ zph4xh!I_$?D1STZ#5dw5))P}heJc|TZSic;lU3@*IS?7OZ`jAl=XpEvB`}eieXd3> zkM7G#Ck2~)z!H5g(*80`8J4ETi#lF4!!nWGS?)5usm0h~|9r)tP_|z+xpEf)P``?# z4GycQ@zm~F3(oI6$~A8`(>xPe3Qw&I?3MpwHoQ6W&M+uqT6vzcX6^B%AQHWSM4yw9 hDrKSnyy>k6a9#~+59#zBTwKL&^D;bI5d^ccnl1HK8kGP5 diff --git a/assets/data/tool-ui/json_formatter.dat b/assets/data/tool-ui/json_formatter.dat index b0b2b939a7f5ddbf401e4559002174cef70dde37..771582c54a3dbe84f6b513d8ac298e07b99579be 100644 GIT binary patch delta 2119 zcmV-N2)Os@5a|$*Ie+EOnWFv!(*gx&@Ct94Y!M4nMX*iJ)S@6xgreX|#wMi2v|p9L zdybxmeFxm+0zY73(#?e&7$S0;ZZzT}Ev##;ZOKGwn$2|ZHgK%8-yCFq3}_&@iq}k{ zBgc?cdZ+-BPJlzkOf+&ZQ{~Yy*BNGPi z3k_`AiFc?+6MrmNoTLaVAiK_Q^GeN#`?|M0z92n;yQ-bDvZ)$4EfSOh1!)krnFe2i z^C`l1Cnhx4VC`+8gJVLlG?Tl1(Qatf*B?~fL=e-YgfU`&qHGqpN^^!OF@=%ADnAio zYJoq#3Od+ZOm5x2!{>P#G3EBncXQf$#P_boy1%bzG#j)z$QzFtMXJ5o>l}JGQ zLx35nYGE}q9)rt~|544Z0=sN*8gD>x^%XrVXP#ax)~)yS)z5ioOI~QaQ@q8;VJupl z(|OaF?0?_#7$k{tn)U+G+9{MwYtw8lQnUyQup?@PYW)x74qzJ#vnqRyS!?7()J1C8 zL6q~ro&IHo%XEX#+!^s;PEHIl}$KS+1HZ$s(nAV4h*fQe#N^ij+~-DCH>Qfu?m{I{|IjCDz= z+4I8p+W;i!-1GJXv_NNL#c(PR_Mnb~I4p@EfP%tKnbn1?)f5)hi8!%EOkF;*2jizZ z3V$GsKZbf{zslON9z*G}0Ql7i%Lq@;F3i}QXeq!o9#21U1{nHh?h>v&u&F-gke*V% z2AXmfl(Ji9eQ|JUXo*>o`2z!=7VSUs*Y$T9()F9A9{-?rs=E%W{Sez5VGpGTdbd|I z?EH_8=cVRs6+5$j?E(f^!oWGVPQMsflGdXkr$z%S`g z9zAV`bvm=MtEN)mk5jnzb+TU6>3{I~T=!oX8VRH^evO^uBBKG(wu_;U4^eL))mV+wIO^ zK8|SR`nZj|F9Wk4+~jgv>>Wf%4~9c2aM7hlh(F@V@>xs=-Bg0&+Zo>w^ndt|LdBww zb6e$F1`}YJ5daADW*lDg^_GSy)cNGX85qdH0x1Xa)suS+K(Y24W+V;piH=73IUVI)ACRP_H9ttDB_+Pg5vgd$+v{x=ZxsY4BLzeVgCt+{p?0 zzdzdn9(MLQ{vyfat&n}AZsDBQnQ?0}_JPp@mSS!M_>bE{hc%d}GN;9<^oMS!^vhk~ zwclMKEE1)%OO~zk*wvNJQsi$XI1rcjSJ&x3s~!NKK;+iLY#M?Be}B?~E31lr@Z5$P zb9zv&T^M>99_|k;DAN-M!@(1$sUx(RGRUob#S!TW-+flR(f;VO%Kpqto+&v&=;wxb zhF04DziY=OFZsKqLIo+7hY}P;-=E_Ll8a98(VY8n^j#Aj5+*67r{UwT~5y>BV(No*Y;sPAA^H9vEBnyeUz-tAlsH5rHJS z15g8tZs!DYp~%kpg&_xDlecmr@7Wa{iMw=106|_qAA7C&h>rs^C}rB0LPBwwA|t-P zjR-T0&OyO6KNzPfY&?{xC$M;0bmFjUZ;QLpxwPx6M;U9?rhm~YLcZuq;OdZ2>m*Ci z)SO;7-wc&YW?QyF7g^EBcB@^~^4M-%vhnpV^{TA`>^7Px84>iQ8 zRs{2P9H;s6x)Js1Ab@rm7U- z2FyPoAvm%OZU*FU!C?i~4*kiR=-_MW;}bG>^!-}M2Zv;Dv)QYIbJJ;=+j$_Vqf4fZ z*C%g#`>wC(r`$-tdeJ@<6F4r53POlab5&=3a(zZKIlJ x+tH7E?yg$?J_mLejch1xr5>yVmf>YWs|XurvXvLW3UE}3XzME??l6imkc;T+B`5#@ delta 2119 zcmV-N2)Os@5a|$*Ie!dnQUX-QEiHmc!gtUW{86;SxoO+GKYlzFsVJPrrXMffO&Q=TTu7GW{+MVyEy&^bSp~*hKr4(5bj9Jj*{6$?;#l~NcU+Tjp zax&wMLpSE){(u(lYUWV2a*z<=KHCfPA-QmFm~h~!v1CJ=E-T>6O$$_Y1;^V1Wu!+3M?E)a2%wOSUp zVYl92W~Qqlm0?DToIYYFONN8NX6GtWyJ;;FVyhktJRHaWOBA+_io)p4NTjuy z5b~9uUQ5{wnmL^A{5r$dUPbw$Z^+$DJ5|WXcQJ8YMWkZ+=QN?= z6s)dZ^nP^Cu2giy=D{VLXnXUbb3d9fPfEyRKSqROwoQj#AHk@bZEZir0$5T#y_v8S z#W-O+0e_y;*HNkRZ25!0TL`twwW$wXad-d?c!NE-D zZh!1n^Nm4@DbkjZ-<`qXo@?;cJ0}BreU!<2CxbBTHZxJMrwPtlQP)aL%rKKn7TJEl z{%g=en--+6NYqWOgo4`QjpXIx5kLA*66d4da|3?bk^2RyykDOT}{dX6TpI4vS*XiJ6@VHwS2D0uQ_|NC~C9rF9CK`+t-a zRG5C}$Y$-G8a!dNjE}=|Tgh&sQu^}f{Dz$pNc!lou1orf{CKkOkw|Sg!VPZB5&>yd zpWy6An}A@?Kv1P4^0%>M8l@mOg#9S#E49IEl?b!Y7>Rj@unU&{uOfF|4Vme$=Fe>L z1g_lltM$%UU1JcxRg`lra+0ub%zqICq=r!I@mr=<^k}+UdbOxhj*7|GDGf6+LZ;Ah z`F^;Q;^UF&1OiyYNNObzpae!S!8IMQ96vc^s2XikNrln_H-+qkoUo{$rBD zPT4myORQoCA`~iRDQ{EqS571>Lt9Rg2bAMmiHVR$D`piv=N34$x^>3q~H= zfWAJpQOP=PL&hth!{az822CD*l!S}2;AJIY8NFs%PhGaT}LY|XVpm7Uh2 zIni6p8~MdV)j}>~PElHR;`kx@8ede~o!%ZB}ivmvVs)Z}&Az z8WPh&%xdi-L!v8>+tA~EuAqBIm-mm)CVL-Dx>XG$O>U`qc`TZu!DiVDy_QzCt=B4E zJF;ENeDz4AA)!ntihn`4y-B@c+q-sTU-B|;i@VMg_vloo&h$~*3{;2j0miqg1oC>M zXQCzu?|qZ3J@uhEnz364fIRoMS*5J5U)r5g2s@jCg86hepppn8g(d&|U`ohOjRWL? zbx5%f)7l$4+T6zK%t`2VrFg{7*jCwmKv7dEXIZIo-=eZ>x_^?VyO2`-LpTv#!lwr~ zLX^qO6^|xW3%5fR5Xt!T<@E3spOX{n#WvpGVR1O!PO)EO@4@eaMK z8Uo`V?xG&JQ|fKbz4Ml@DKBsoR+S2t=+p4vW}92EXF!eu`LJBS==Kr}D1-z7H(crm&}fbqLyFVz45 diff --git a/assets/data/tool-ui/json_path_helper.dat b/assets/data/tool-ui/json_path_helper.dat index 48e091615bdebee8672f42724c3c9d394ac94394..f76cd7407782a65fad9608bf3ab111590b9a7c38 100644 GIT binary patch delta 2167 zcmV--2#EKa5t|W^JAaL#HVYmMgoU4lLntWF9Clb*TLdPD0tX%raH@)Q>Myg;)5vE^ z+Q$U$gK{+x8W@}l18>Ow%mg41d;soy1@+Gxhx^GwK4$3`qS78d{DMJyX;M29XM+|C z>rQ_vV0(j=N_ zA=N3jOL9@wx7zCY_;f1wj?iXlEF#`(Wk6#N^}lzGB5f?5#-K9ffhg&r%#@>+rXq^~ z7}&v&rT4SqUu}5mO8@-ckd7AOl<>y%zc(jgC2-k+R2ETH)PaHGC{%X{R?-R!G$ zk4vT{K&jT9k@roh54*u<KZt0(O#W_yG-lD(i{nP0}D9bd+#+pPU9>i zwcLr2oCJJ zd>+`3c-1gsi=yGFGr@KXplru*3V3&X=oLNCF?PKQ2IJ%Zzf&9hc7?fIMG~UIF6RG~ zwJ`crx>!T5B(vFFR_c5TrqQ_k`?2F{ZP{%0NPpm;m86H15jS_X4By^}cm!|Thqx)@ zw~CjOJv2{m*d5dSMg~N8S{E@>ObjiI17qh-xQvQAUO5Fd&zY@jGf!-6CWnmvIn=Yj zK*&SbVjcnl)osPAUrAwDIO`!=4X+^^i5I+5faR3Vy^p{JBjFoxEnf!K+#riUxr$9= zw|@`6>>tT7_)B=X$=;P ziu%Ba=K;xBY9X{=@wnzR)zTtls`duUwZhP#f$gdV^05j$xot>PCed~@PfQwYFf8`h zyfbZ;AK=x*`~C46!Tp1YA2!9J%|9`8( zYmBmy&-DJTdda|V#7WB=sps8X=F0dOV5`@&#Q%TCL{Cs-p+xY+ldw3a*k0okTl!i} zM&xq8D7q_k=(B7)}nS>tUvG)P_Np#)SxF`3i{|4gc-gZa>a{{64h5m1Lc_KANYO|FD8(z>RezJps4z}bWLujL2|oTt-a`EH?nJQ$iGZu*+4Zg* zzw|Q{R-d>4+me|Uu0D4 zxUGABa;3|@*;*wMEuzJ5B;2**%BgyUp`v-+wMX1SqRE z+cA)oisUNvg%70w^JCf0tR|4c&}gbX7%stg{r$g;5qR*vLkPkmE@C5&wk{H`KWoSFn?;PHuDg0`g6;0%*efy+NY4cq3Pcs(9Jci`{M0G)Eo8A zonGANR!YrC+*(LCF9M@q56=OZRQWrKVuZeCgtS#T#uHYatCSViJ*r-Kw@W>xfCbn1 zCF)-}S1^7Vl#9**8_9vG*><6zpYki1kvkdMUR+ZyYn>YI>7&dJqkp0M8*y&{PHTj! zBu_W(f9J_3a4e7m=T(mnxTwOi3*`>(z@ZQaJ%yb_ z+>XoxF#c9W_fZ&yi2&w<&&oY9waD*kfExFdLd^LU2=T{i#Kkl0DvUKii8WcMHkUmusog}|HnC#S@_!Pf8jChkz!K|jQ3RcS zq{OAu!XpnPbJPXzAbL*T>|66Se{O*WRbBfu9K`-MO1mRo4)AKPnP<5_QugU5e}Ffn z`I+<0<0Cr*i~X9?<*kh{7(x3gg#-q*5v+Jj$#W*86@c=0?*g)l%EDZDRdP*DZR5k@ zc{DrH{?vV{8hsPc{PlpJ&#!bzkVjf96E(KZ-X%0HB5pVp}ASVm)7vD0#FZ5D*zC&b(F9l tAU?#D1^0QQBpuK$M9l>W*}-S%Sa4BhCKg;57F$Pi^Sbmi_(rL%pQV+nJm&xa delta 2167 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 delta 2103 zcmV-72*~%=5Y`ZoHh-7n~#rc#0-5^jQn}6O1WhBbJ^3( zS+`@C5PfYX(Ym!yJixqg)MbFoiQUIa7Ur15Mx2#|X@88E_Z>f;#iX^elmryxbs5XT z{JNW!^+(iy-`7DtrV!_9{^q|d+l?kLA7{1bqb@T)u-jnq;#=N)Df?79pxTGcE{d(~ zuwDBaBUYWqM)Wuuu^o~Wp@cq0JtgC@X9*teT1ks&%VbCPwmcg~kg=IhN;L4s}SnJLBxF2hnT`r+*lz33p=t&w7r$@0?v0{^u z85~r|E;dJO9bMH1Xn!IG^K3K04U3&EKfZ5(G`t5!k%`4xe67w{sbrP6_213|AK6ky zh8yAJY0);NF0K#m2YWH2|HFm`qK@l@5q8`se1G~|_$jJ)j;#Et#`WealRt?8#vOnL zVbOwg;yAB*PMPOZ)zqYjR?tw@H!0`wF#zWT2%s93hTaI{3@#z3I4B#$dIeFvzpRwo ztVOBTpfx!mDH@OkG+|@ILJD_62$%@$TV}44pnnrmS`hL+DT%^!v>}j>3FZQ!G4 z%YPcu^*xu`-W>IdcIioi-`Z2(C&H5AbgIjj!H1n?|4!4!+O61{yQV zKi}7`;IFX4PKl#)ezw^L^IhQtnhsdJG1n}XsJH*}jruF2A=~S}qhOH+||6UtYmlxDudSvww2BT8Pc__9Gp=GdQyCN)zAsVCNuDv;DVJ7)x8z zG;lqYj|zaFjux_rTF})kXcdDsuMHG44>zGl1n_2h?a#e zYi35fd3~Dzt+PgnyXmrP5X>B@Bx-@yP>h5ZgOPaBJ(Jf8=nUulqYNLO9e;1gVLdeS zI{US*G4Nan`}--b^@Q(JcE zh+~r{6h@ZaPsX2caQS`gL>2{Qp18>fW&;YuT z5_BI>?}#F65sult#A%Wgr@y(w;s5I8Z;^RDWg-SCTSOaxwZ`U@?ZUEUk^u5=%>%+T zHS<0EN9P^>PwF@Aq31fd7;_hGsTJaUC&lMiR##B! zo-suJ;x|y1rvH3KcX>|UvZk2QEY}=>zb5m5(Pwy|6SdA1J4jBY#C7nqrEfs4mbzNwGy<5f*lHR5Ul)ik8{Qlt*O zMs5&K_9V?ITQFq0#J#|$*o)}~4h1VG5Z!>KzG`a;BA0SQntz%gc8tW`V|%exOnAY2 z8x)fg+kJkOuWiCQxR>0Hp8IQ9CcUYW{ddVY5x@SP4($`4_J7zjhi6EQV|fGtL^=${ zrkqv7VA(tgd*1cyKr|eIeN#h?FX2^8~trX!c)0qWxk{ zsb=VtYG@*bQGYDibbEd?s|qB$Cl;KX-?!@n)ZuB3Og8&jtC|@A#J=A6CedKy5ngv| zg1@rSiMJNz4NFw7-S61o+2}0?1Y&;4ZJdWB9*ua`^a2B*7igb-u)28;AOXNgywQs3H-PcWxipDwcC%_Z)ZT7*J(Ppj(Z hbgeo3o{z7=mq{{wNzn;}n+lqZy`4f))5|0i_Q^*~8NmPm diff --git a/assets/data/tool-ui/key_value_converter.dat b/assets/data/tool-ui/key_value_converter.dat index 11958dc8a5d3c4668f3ef284545898ede7ec44eb..d9d7493b2074a3922dbadaed6b1f59b2feb569c2 100644 GIT binary patch delta 2151 zcmV-t2$=Vd5snd%K7ZdWx(SBOR6&GL|A$66FNguuN%RVL97x^N+F4d{15y*pxaS60 zk;ts+Sn`}o4}7chjEya@Up<+v8^wD^>IAm9J(v@)84JdHv{kD{b!MlfJ=6Q z7QDQ!qG{0V!QnlgP zBT+4C=ZiuHrL;d=#M_nzRcKE_F33jk>#_086tnNL^jHZWcZWE|ZyATu1!!ZBcXO|HZ zD3WY0p4V6im0-;H4A9*pHfrCsHLj+pkHXyN1$BK6ixs|{Y47k+z?u3gcJ3hXX62IO z(=wT-M1Mv2Y@9ikfR$}$mZvpA{$Qq6m)}MgRgtuG){t~}A}B}dU}MG@G)FI@&Ujt2 z)j|RwldrJM*%%V>cijKNmpsOx+Bbu;RNa6^gQe4e?-B=NP4p>qb zji4He{*xYihi0f2a^qquvwt)$yqTA;=qM|*C4Y8kLV0xodUe`W$V8V^+X)C0wLH#$ z|8553%rQ3fI)qf-!fN+2P^@wz3OP)ifEH3W9guxej$XXPTfrt#nE6`jHRSvkrb}oi z-Ia;5&Uw9pftZqCW6h886xcFb@Cs_>TT5-*2N*a%O;Wd&M9?TpqqrvoHd=Rvl8I~( zS_$_TtCR&`LbZr^r&P+as%fvtIa~VUxtWP6Z900JMzU6}<^D-C%c^l4;VQU))p8~& z<%?td5yBdW+AT>&?qwdavwD81r4^7)1%JyWgv`U|bA}i(xSygrU)&SD0Ug{PiTsjL z*x|1!97rk$+uRmXuD~c_Mt(K|{P#}fC*jKCEJYWkIxZHJMCx-`C~=4Q#$ccP!J66= zLo5bvQ+`E9!Q!p&NTi>opBWQ5FcBfeMz_OHncdwCzYw6?g4X#Ejw2`IUA8ui~-VciWhx0u6oJ2(3YhkdOk< zK@Dm-gf_-^Hc4s4wa{^`%9tk;+jcm8v#orIxdn~gsLavs!>w^C7b>iH`hN=MipO1J zzw(&R_)#7=ji{;NE~rw0_?ie~Al<}3c=v}IY%=BgYx z5tR_TB_0luYN7n5d*B4UV}D%)byH3@+RUw!S5^XQa4+EwA7=Gu8(oxFEHzYNgv4)) zscV00k79b~X>mXfUWjoy+Z5U2RSCC5_b_3Cc6g-r?$Wh44&dZ8h2@HZ)$L#zWv~rA zdD*3i5o4oux-?^x6PU9c-AOfTD>pKirx+t46n;iqq%wwJL}l>fAb(F2nWN0v)*5oC z8*Y*xkD3p~{dyvk@uQZzcHs4z)D0$C@Q~pd)A)*FJAlmvws)fYllSj*q_zx%2IYvJ zag~ukNcKW-&D?AX0#Z^&(+jmTs$*wScG24~M)$X~U@zLqk&VwjU-bS2cC>fIirbGt zW*(jSRJCU}By)a0Q-4wMq#WAuu5kJ!g1a0hN~1bPhyE$AM9e?6b0)Dk#QFN8D4HxG zJo}7#cB4@Aj;bepX=*5_mxim=BbvTYUL2uxre-)v4v=+y$Y3~8w}ywCYe(^%w(Qyj z$8>Z*+MJAqhHn3WL3~RqGZ&x-VX3FMvrm*XwXA9`PF}-r0^07y;og2 zvgBWF%G*b@?rU|eix){Fs8G*v>82!MP#Abut_6syR{mq|@j8fD5H#?^`fKwxmIN(x zJBLicj(}RBU6Q1y)%$=?zFZc#Hic{8cwr=$CF`cXP&(D@LwFV%zq|Kc+;IE-iF=_g z+Lt%tGszvGGJmJ&&jqno3pEgGE^eu~rnNF8`rQc2bBmffBrJ%!u`*H5Tv1~c(-QZj z6v{Y*DCvS_&noEtT^VHB3Z9PMzOa$LmGlsX$%A1pCw?I-M(sTbLAe z(n=a{NHDCg^bHIMtJK_Z(rbvDbZuGX@<{2gqyjmgHefc?&>bVe#vu(OOiTj;IGUL= zO=MPXFm>0cGa565EOMq8%K*s@P{CKIFD+zHrj6+P6~!qi%BfNm&dNE5V&V7~1HS!! deKBD-WDNB-i=*&XIp$K+A;~up;`rqiqP+*iCaeGe delta 2151 zcmV-t2$=Vd5snd%K7XBi@E07&U(#+ZFv`H-)vo}wVrk4}k1wfmmEqkSyZ&{-n#V1X zBC1>V@=OTmW52{hg43x7dLzf-y9 z2pRZz7MG`9WYm3l3=sH;Clcx=FlFx*&qYk1WnRk14-lPwM1H}9Y=rMkDfsLtIS-b( z-zFdhSjgfyuz%u1HF2$JF)SoX4~F6qnk&NKlTAVr{hlj`*})1CHeK{k4?Pr*MEOo% zelvtYRx~nAN3zl_Kl((3Ej_NU!7jRMSLX3}H6_}cwNF`c@o@bsh&fcU;Z?gmJG@S zPNtr%2x}J(SJxna=4wjI@%2u4^kaB~2b;(~xMg6m-vIO@^-aT?K_U+;kxmf$>0v(| z9m`~OSASbmK+{z$^Te9=kG}>hVK9kdv{)eSyWSrN1KbNMFHX|KW?Q z>l_+inwDc2Qd1*QAYKi3;X2DFwi#e|#Tjf;jDNR4hgw||@BerEtL)%A!mA9#CSGWo zTg5;y><_V5`?GI4!no`k?{CJA#ph=ZZP2yLjJUz03y6e!P|ePYk8rngd{I1WdD+^d z57ZdC)Hl4pw{7-;i;;SA<#pbH6<8{P8*J_WHtpTm7QKS@=cwsdhEjb=q&ACS!yQFJ z8h@i?AV5vEoqDUx`fJI7_A=MH#_Uj84 z8V8>-ykvedgH}HARsbfu%A%a|`5EWf2h0)ULdHX-RI`px2OCeIO!gEJ>{a>Uv>T;# zCxKxRCj)f55}HumGvy=nOim*3c)Yg2Js}LfD^mwv7~33cftE0JBgkzRt6@V4fPdt* z`mE12;#xb>0t4%M_7;n9Uu?}&X`l7xQv!<=wB zarVT=rNd}&I0hU#%lv0ymTB@mS2&{U-og=zeoSLTRaa6?ZKp`)hER`}^k+oAPd`-j zU6vd{#1D%DhA%=+&_W!w8y`2VOn;D-z+oV$ASULEr~6(44H8_nXO)`ZEley0R|H@B z#^+`3^X!L{Sxo+M&phgTTH|Qu_Z#^l)9D3BrlmlrmO7F`G2W5*0n^}vBu)489e=mz zQt^oQWMCR2#SR+;^oDkhx*s4X?PtfQ4V02V;6OU-BoFXuU=Be7&A8x4D}RXm(id`$ zdP3>OHy-5mkD>vg1u-E2v_$f052-GLNsne(Cu1cvNHD!1%@Om=9G0R>O0Lj9NoAAT zAR4wHP|2Ie`RB9eDJP*J?)U9?yL=G4U@IVShVLr9Z7Xag#h`dwq9)lYO@g(uj9Q>gHyPZ$}_9=2-! z+IN!6Q0Xr%0gT!(!*PSO{|F&BCH6@&B%vHLG&u}nQt0^{ri!u3RgUzK#6S)Wk!$jG z8Mzmq0acI5-j+Xl?tdI`uEjDT^<*Y8)rxrKeh_`x5Nd#iAnf=WB~TSQPA3Lqn#BbU zCu}wVKT2gn*l4zu(7-tQ6^K_G;20BMPp+4hCanz;5zz91H8xG}r=Rf|Bj%qjt2cxX z6xBrT7K(26hP+%XL>A#v|2_IXu)jmtPtY{->YX~ZZ1)=-UKgYv0k`flC1Ab839gIB{;pN~T%Ug7uGt z?s2?Fd3yyaI3UG9AIRiXx{aV8x$P3?oGb4wO;PG6I2s1bvJ)`F{kez2t}lz3R2@lr zPpt`aE@z~LQGX8R_#H9%0b(gWi({2zOg=!uzYK|28+`zzm+~fI3L`-BUF6C*ozWALaFP;11hq zM8Z4>cJ&qy}AA=6}x*R5LH4>J3ZgQJ!}>0Xm}*<2t#K;>y}bAN_@GU&?XDU=-G*;{WVT&P3twk|V0dWmpLP4TUX zU;n8!aGW#$3CDP?T|8<8*9l-vnWo-M%;# zI8AJY9YMVeOi|B$>HSEvb016BNv|CCEdaW<1yjm1|=80^a=QkHQ zk$_Y7-brr9C0ZLjn1i#9&}aAk4WcW%84tRrY~541WkbCWo+kV@Et^cXD+O>mPnt+FHcy z;gAeCdJ|Qc@3I6t;#v+*O~TOQ+loFPIajV;jUq>rPphmpSepi0z$D^8p<{8J|!USxm5 z3OGmzN?DqG;Wx*K5loYgG4L|b4P~BYi?@^9y_Jj;t)lB2Fv0J>Pcj$G*xMUIw1089 z2dYeY;~DD1t(6>E(3i=z^5!H$b@Ibi*BFxa(fVSPS%+>A{Px{0Ql>>XBBXvl0R zfK~V9Xj%4kLs`*V(06)qcMtMgqwo*ySCklu0NVjeNmn5h_V<`1Jdsfv&{-PQ7~I60 zF(g`%MhD}`6oWsp4L=cKU=wyI`!lfkEd`A#o2e&MNFk>@9JRB01l~riR)3oecMH(3 z6StL&ggpVjh9d+q1moN}i)=HMRv7)80bK1csn2=(?`i$~77x^C(KM8MwBgTD(aqrp za0F53BSHo0aDqW04tArh=$ejp@`~$hAx}r&ubq#;bF>nh z_%R@4&o#mk)CV73)flhs_ck>7xpU18tJho_$ahAY60boR>UzOo`5=t~Y zx&+l(|Cgd}mTL$wgOjDu*~v2=E=2%!bI|`q>mRPVIvJVT)}<%9KA>oHVHwLdzPQa! z9(zyv+MnUs`KFW~lz))dF*Br!hzrMQniuG{y&nCT$$@ELcH-QNZtrHSyiu1O0gKDw zTm%#kV?_CKmLbGkmR4ynADAn5i@O7S2OleJE}##9E!8$HLbf)ttzDCob$sz>5i6)J zXv!H~ku$G1XlC72vs_m-b!~jkahw2{bDrPKwC>;BoLMtM66OZrmzPAbqK<~9{(vn-em zK2?T!Z@`2B7$-y-R?ylZQOsub@n^!k^~CshWA*YsLaF|AZ=zxMbY;_RK^lmgV15sr zRd=RL@pjP9rhg=C@)zY0id9iZsbl-%lp}`F4EcTdxXn%(?Kg!mA(pblhHO>ml+W{z zA!nAxrkjv@Q+$jgcB1G-z664~Ex<4NVyU#fjNU;AfxgVcFxYXa0f@-GxK!%D zvmSd0DO=qBKJ%c*C#8|%NG$x}`AZhwEoz?0_p)MBsX5U;wSSq-C>ZB~R_Cm(Hq|=Y zV=MT#Bz#TtxE--RDGU&qQYFujfG+JvPplEN_ay794tyIIK=lu)rcQO|^(wwog&b}A z&5~`f(>ozEx(vH51wL1~T7-2rtvTmfFlGcRYrr<2+?pKyLVj|+knwhW9YfI0Fbf)F z!g?LUDeLeUrGJasYgWX_?+Uw)jx~+J`Abe!x(*q-D={nhc<<)j>C)kBcK2mgj-+Ua z0wUJO=yS?y%(`2et|ViV0}015LXZ|WzjCZQi@;Kox(k*;dN`H?81wlxtH$uP3D zD;4w4nkPv_RchP(wYG+mA~lED0!6$^b}DqZQ{MqCYt$PhEr4KMSGLz%aiUncxqQ~?N zi<055{!yR+l|j(y)1wT0e81&t zElZEGy8Fh^vs8EOAx4W}&yXE;L3lP2|hdYsQ{!*NkIaW&5ZW?@LT z>#g+>xQ>+UQNrnm1eYZGZ-z|+eRNt&fq!6yRu5utFEhxUpAmbtKA+uOaNW_MU{o{3 zT(E>$5Q)K=9bX8oF3**eW%2uK8z1EQR*SWCgexfngJ8iJB`QPCJQ3YeFmc@E)h!Hw zjf3D-3|eaX6PRMS`Me%5)lIz`fv8Y(TLm0GRo9b{u_`H2yi;{E)k{tO?+eAic1(&nI?64!j zMN(>*(hh^~hFY(I(eaI;DQI!EBMSm>eY0QIew-#E*|%7++G&~H&kh=Bx|R!L>l7)s z1l9BRLHIaI|05g2UeNFDP1-4$Lw}1E7X)VOSGs<5|(Cr`F<`8Pz(u*UwS57Ss)!pH)iMkG6u|x>JnNnDjH1sBLcFKpKAAa`V%Z9 zLALUK8*6HoiijR|vkBhl$d)dI?l|eFRvLh@b9?TBl8V1~B`iDHm{!dTb0-3tqXss~ zNMW(^Vre@ef9!(Ha_34ye}Ao=*|~H%`CU)3j7hWoW>}|=z~u=D_J)DGHIXKf{|_XhonzJ1exZ@#%@kGlxo9bPhek zCCmU$#PiJ{2?EBsk6da}Dd9Y-Z-_{*M_(C?(!NX0Xn|>Ro_|tFf`1Q?T^^XyQ&wls zjjgplurNJt*W#$WiP(zg{@Uh9jAwjKJp9r;MX8G{Z63qKXA8kGM14X|Jbus4z#z2{ zq+K69p^(+Bz-cyk;z@S#=#z7cPtQ3l^1*B#)WD)YCs>J_Q!F+kXan9iZ;#{)7pCauEX5Gk!!x%2Au5Qs=t7 zvT;64jxK7C5>hY5-<4;>wig+kLzmT1sti}?X8YrJvUux6=YRY;1aKWHikT3@SGO!W z)=6f#dH|5~95K&B$2u(3;|^FQ)FNs8l{-q@m6Z4`E^mHox~cqOW3ft>)LJ83<#*L^ z^MIJ2ID}gU8u(nQ@zAIjrW=!xSKAc#xnS3eQ=#9JCYy6|1O({#G_@a^+#;q zBbBn4%$-Uvlz%z4N>tIZwUI5Vm9;6ae z_G-ww{lB1i`b74DOT&AaY0y$<+%qb_K zbJ!+?K>RxS${6TOQl+A(EgDh@r24bOaHz5uT98ZJFCg^)gKrNAkEs&b;GW)lS&>_H RP@Z>!nvy2-CxhY59M$!j5taY| diff --git a/assets/data/tool-ui/length_converter.dat b/assets/data/tool-ui/length_converter.dat index 0e1647d50a8d87bfcbfa80af49d01497c406da6c..d631899812ce6b588f208d9d70c3fe0c361e7147 100644 GIT binary patch delta 2054 zcmV+h2>JJ`5UUW7JAX9#rR&UDEB=Y)fT7ed$x`*Gv3cQ`#-HmpI5NxaJ%R;CU zYYd$!Nf|ie&POE6zgdi{Ap4_(L8*nC+l9Z&0so#0Rq_N(agQGLz3l$f>BJr56Y$Ua zYuwbV!rt@&Z8O(fqn1u*!#gn5ZoY6^uGA82B!8*3XlvU>;~!;99t;Ui zLC{2-|F_o#jN_^N zd@@Jop@tpaQKg?6IvoLWa@w^*I?Z{%R&H^H1@Nv7BLJQN==Iz51lAQZG_UOUGEGXd zBIK@-u<^?8Y=7G8hI)}Y(~Hs`9U<9OM%2$_+H9+oozC0D7mFE8J)ycn#wS`oZG9fe zGEBEbI2wv0mO4JONd$io@l;$clfv!;UPGTrhlt7b>OG8HhWvGv-rxnD)Rb7_?k5SN zGjA>_DYz0jooroBkj&%2(5rlO*v?=Dz7emw)%Uyoa0GktZ&sBu`ygdGkUm zRG-CA>b;;S+ExIp2Qeu#3SV51e_%BpkAusgUbS?VCVZ+TV~M<~R|#zN`aci07wyht z7~7;zl9X|#FMZQCeYCUOA$UjD8bMjktC9jhcFdyh#soN0wm21A`oLuEoFvnNJg*6D z)Kj$KI)BGrWWRiiYITpb-)0KV^%fP1eD}((kmPis5NE|VfScqyD+62NPu8lYFu}c3 z0z+KPpOX>#P_t0H7SmdTovj2cLA@GAl3<}-@xwX0G+_D&gz4b7N0UYzMM<0d-n=%%p|Mabm_$u^pea=?mZ3FkwRJ{R zeSbctY|P4;(-Xya#0sOV8z^X;F$<6HsmbR0SOinr5vcBsTkN#bJ zBml=}yxnAbQVaKI_99nz>IMK4Z=ZO$x*Cb)6s_0|m_xOobDqZXG+?&`5^u^n*{OG{ zyoP7-_1_m;l~$kkGrk(BJ$sw-@z<~6{eOjC(Bi=$lKkeF5^*UI+e(b)tVmfBDjv}+Uzsx`_h%W|k>wCO;dvW6JL%~#GJw0D7)Bi)? zNsiEzhS40q8<>O@lL|xKa(F*IEue+R4b-pZ)$-~;zhX;SGyXc2L*dD6N#6jThkpg7 zuhe*4nxPY^O*8N$I3DvN+)qJgTTE*c2av@xEyZ*ONOzKA9p^KLmT-*ofW>#?;GP0YIZzI}5Rq{1#UN_m$BUklQ#{|o{s}1#f zsZjw6B|?^A6qBaq(r2F0a8HlYlkn)f)~nv#(7MvaSKC{R)o+jt^)w44wzPndhIg!;KBX zzerBDa`c(MixjI{2dpr6rZE>4$9{b>W8bH3o~?In=8wVX!F)u@OC84U9r(#bVgaeJ z76VF}-pNLpnKV^EDz-RAtAENM=*MZ^FC`E02x38J)73>VP2<$!<-DC)mCYHLS#^dB zF~GMHMjv7$ypxJyRW2k}%`trBG?r$?AvhR_;x`w*E*V88WgK1g0M=~SgP(21r_Yg_ zV+Me;Pl_T@Oh+)RxU}EhJ8%b6~O0LH38m>bupKm6uC4EYuv}hK3t>nw}3#KqbX<7lRaBiptL?7Kh?`7U)lOYeKcr`I) zAdvuNop69m{qK&E((Eg^&-toW4E)g4K3BZwInHXqz2z51=YN|fnK@pyB5wfXJSMzQ zoNOcjdy_T;2T0adxiUDn0Z0hq<2Or#uyNjOF1km2mcAdjP!g%2Z*^8XF~Rv z5OABbl6w~uWPf+h{-@U=I1*ps-4wyVNou6GyoUx{unr~Gtg5B`uX z!9X2OLcc?eO%;auE%gCXPMaqG2E;D!zLP%LsZ!SDBl8B-_cT&iG^fs?i$u kdwUC*DjQ;JDxnWIx&=Lol+w0Rgnm4)72xXI24D2jqT{vvvH$=8 delta 2054 zcmV+h2>JJ`5UUW7JAV`Sn43K(PgGwv%#EEnRrNSM(?m(Yd+%KK5I}+wkB=nFx zRM>FMJC^XxL9q4Hz9mUeQbXuR9k`fm*ti=SMq*Q)9-jd?_y)2Hoj%qLbQ*g{%A`_T47_K6xo^FA&9|PpgF9IpYPgdLDQti&yD+$!;ailNSRN5=sb0GeTOUc?KY3_|oQv>@~mbyEZ zuiHXff3-AVVp&npYG%C#Gx#22UvS~f|IB~wn2yS;2Llg2Vj?Zq7ix?81-T!LMW*?k zICzTceSesypB@GFvq9CTs<&;<8PFQY1mG?RIwN`&rRX={|KihsTf6gnVhM8hxv6Aosujy3d#bxv9{ z=qLlQ5=`*l_~8}w`4%RifA+^r&|e!o!Of@SzN+X2PyFnb>LVqvnaD;Ji)96f@aQ~) zZS!eQzN=RpSS2RI9z+07x7hZJvBf(0tBE9*h7r5TT;3|Hw2Y*%>lWlr~Ht-B# z(SLO%?2;o=62TpwUZah<1b5_4ODLJmn&$>Kg*W!fj0kperxVJ>?m+=PW$bfO(dsux zcGWH3g>{vtK1}|!6cZi6b=iy$?|e`~&AXna`DRO!^GQJi^U?(2Mm*JU2Ju7yWw@;S zJ=6s%r&Fa!zrkboaW5{uIqx)!tq1+cOn*HA(d4JOw+DM&;jRI0RPTc+xiLl&vQBrh zvCDogdCZ5nk()PQTrfkb*h9&J5%B7Y!y zPj(83L@zn$s2_T)S?2s!ZnXUVRt9l+Wv|wopbm;%dNxUAw94+nzYuP|i9DS4d3450 zHhqqMj^*LZvICxTDjt3>e9BfP+^5k`^kh%4cTGb35?xipGnif-T=+}Use>m>vK>)# z_P>P=+sbl?v_RgTY;g!S%g8b(Vt*eOgT8j_Dt&Ih;bllolhp)-(&ve8iAiI3+6CZ%CC9vO8K^A0}fOr2V6u5GN#*|U+)pr z+Y(+P9oF!d7;IO$b~B5dLw`c1i0n9D)3=|FH9wk(Wt?&{|BQ*!Y)TkbN+)!CMdh@m z@|Mg>(fRb?a^=rG{q$i+izv=a3o)PHf*b1Zc|#t@<)^l&6|Lj$@5ad2@E~$3afS#W z6JtSS@ygsx>Tx!W0-+u__9_ZMZ*OnftjbD>j+z@Lwqh+vQV{;uemQxUL2M!yx?J#7PGahXwr!SS#MYUnik<<Acrd#P2@jQO+lWu^-^ kD(gsBa;6ruCD;7P-ZJt19=4s}ZnJ4P_6U5E3A-6aGKlN)761SM diff --git a/assets/data/tool-ui/line_column_transformer.dat b/assets/data/tool-ui/line_column_transformer.dat index c77436683dd7df98559c381f0e07b21518193dec..ffb9e7760ec9912bea88a5b2b2ab0df220387777 100644 GIT binary patch delta 2119 zcmV-N2)Ot15b_X^LVtv6K&?Vq!V7Qj5o+TrarF8P@vYkvt7=JPiFLktLgHXZJBBRZ zyZTmYlH^ggBOtWmSkrEgbVP;y`w$B+8Dsl{_Es#%MX>dmuaGP8T~0-&%{%Zw4~+iw zGvd&ngk!f*^Z*7vwnRTh)1~vau}RoaC`6UrT2x*y%jMZ79Dm=rRebsX!+EJh+@63_ zeD_=(KgdIR;JMgY=ZYLuIjmT}3MLE9I9V1tj`Q9^82VmEs~(0qEZuG2|62-a^9P)# zD58n2zHYy|vR_}bwgP)^0=lz^FMl79v6VEr$C=|p4th_V-rAUN9y}hPGnvoM1IKVH^#OlEsR` zP`p=9u+8nd?a1Anmev*du$r~fZ|6QNmewI?c4hFdb|enSCOHxb{|2k#TwFIp9%f%c z$}}>jaeIxCkgTvw=OA|*F@^t` zHTUW{pZ%J6FAU9 z8Kk2E3R?*6pcPtJu+v-1J*h9+krJ*i8dY~Q*ngIYtyLKK#e#KWe38_@89es*ty^9n z784Dg5Ilf0g!#3$rHg1i6!bWqo++j^?$6@+4 zpF4O-7-TCc%usRdVRgC&4dT*QHCj|67*-^W1?O!($1K6c{wTzL;UYcBcOc1zb!7N$f*fzuZqac5Ytk)p&k(-8C#SR{*xD zWUE*(MD96h?Xg+LGm>lz!Tu-lL;&0%&-3#(c=aUV;ZVU@4s~@9u_K;MKB)mGeJhJg zU1`4rAPZpykNCD}47+)c3Pc32TKRnQE0m^L&VMU< z3_BBSqO#ys@*5)D<&G!CDi4?nh3G~TODR3>P4dvXC zRDKbU)BJ&iP=dBW__HcUb-)$>9_zQdrUYZtPM9dY!QZK77fF(IC{&C4ZY2KT(ZJQt zqj-T$ghQl}R*jSUhifDG+knKvt$%R(*CS?WEyWL6swk&MlP9P{aqYM!!+_A#?O_j) zP3c@z0zn6ZV+ZHEIG`y_(z1m?$wP3Ah7%t&^1Kj3tX7FdUA|Ony%;=d#_Iu2o^D=P zYej@gBEcWEa+G#(9hHs=4E}+fK3Rbi5$o(ktq(o-p5+<{EgHllHPw46rGL($!m~o^ zkpKl{i`B{583;Rlx{8t7P%tu(UzDAg&*R5LwwO-=nn0x6x{&vL{e)qk0yfEJSlVi^ z9V}*|8EiT$PHm*9RjiUUQNk2p0cNJ@gBy|0PZf)1`y(VEh41^E>j(Fe z@Uk#-DF*KrvU{G23B(#&SAXUB9w{ug7aTjpa-aKzafI3_-Wi(V5(l$JOr z^zFgeQ7Ay*M-kqH4!BsbFmasas}5|S4v_gK28`J=``cZK0-}0w^cemc^TnnnPm%Lu zfRlG>{3NCUC+dS=^0& zomh~sdgCs2@;)tPj19|_mY=pCG(m1FX zpV}&{Yfb@B?1$(>!$8V?rCV~Qk-dACCX$RH?%k3}DaYJi+r(A3opi@2e;i%$_F^x} zdsnNv6E4#oF>PIJS${ogI(8pMj--RfGC^AlEjl;#2Jc$$6ZFY5us+*SyO^pvOpp|P zd5Sm}bM6MaO>>+<(#&ff$DSqsPqQ|XH5+U8IcszD3k$gZPm;KyJI}jYnL{4r#gKFPJf9EiL|M(;|9@#@K1B#MrN)$*6rRS-XW^aTIiXLgQliT7=kyYf-h>g#vK{|a>g6AA z?8wG&vF~yTB0EJn+OX1nG`_c%*(-l`C<>*g-#!c7(!F0zpREwuCb?7dH;T31{yI_x zauB=2B0;SZ;W>`EQtVMfa@<6|z^4UlHaUG)p@1`09Y8db>1hCFsgype`%$4$v0hZK xP|sy#P6n}U7s{3&71kXlzpv_W*QqTk;Hap51HI)4Dk?_e@7QI09Ss0wvdAN96PW-2 delta 2119 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 delta 2119 zcmV-N2)Os}5bqF>KYwmZxJ5I!@^; z+>OUuvec7?h^1LU6D(+Bfo{ml*5ogfMFpby*P#F_Bm*MWGh=z>&J z51eBE_=PdJN8rGW)3!9fZ$8H4eZ^&Je)>4@srVa%GQkgUd4IQYla)y9y7HYm!P-uE z_1`G}eR?l;uPgJcwNptOa_&*z2bSpFAOmhwJfuJ$KBO<~Zz%uA3?3|{Kt6Fh)bC#|IW)&dNDdgfb3K_P{L~BGj zes7Yq`F~s()w3~?5=N4x(OFh85${y_2t@vckh>8|ON6!ZzsFo{)~nb$U|^sjdPFU( zdBf6#VB*d6${FaQs)Ix)?7D~qnF?q&WQpgg04uwULf(K2?SnwXk|JFRRQ!oUVm?~xcim^+wFd6es?K-%cs{*>n&og zRELM!rw4{VB&a0JiMcsjP?7t7+bz~!B28Gam~G=HrERBS%!v;9U428z=%@t4^Nek1 z_}`R2cV25v(2-|<(aB#piH4`)F4C6Xy=`kdUrLV>$)BT`Bc$#|PQ9-x?Xyq)-2o6gP=mW~z7+nb#FtsHK9}@mp+bz_(q5#~XL(fO&h2*q zMpZ~1FcNOofAs~x_PavlFKos(8Z_AhSbw7zK@>Q;01bRr9R(2G3gEAyZ(?#@Ve0~Y z8uQv9XPVxQl|%EPj;;tbxTrNRXeaH*jVQeZ$acu{KKFt0@BhHp1jR=kyU`aoAC0Ty zQMfY2YPcG1{$MEDpD(MsVmPHV%uC(o=StEPsV0 z5+X-&Q~Gb}{~Y6GGYvXjyem}z3=Y6T3SENmm@^az{&_U?Wkw8T^jpH;@dcVI7yp7l zKw!}j)5;3QrBi^OEVAduL1I#r)<-LFdn{Ro+3Cc9t z)S~%tdSe3Lnx?j>E&Muv^;Y{BYYAZDXUABarB;tFtFyS$X*SCae;W`nL4VeC`sQMC zk4-|xe>>+dC_NfrUGk5H*8%UYK0Bc)c0lT`1Rd}k3R@rUA3wBxk2`++kqVT_b3f@- zyD)DXwHF!>DREhnGU9%HG0lR#E63J|ud>F)a_w#6TLiqf8Z9?~Iv`!vr(BSapSMP> zzI)fl($-D2g6_Y`3PXPgqJLu)T^-AUWhj9R;SF-$0gP8}jXi!rtm@Q-_1L1S5ia`H z9Y~Lk=+=P2oFxeKMtT28L>Ae+_e(FvJd>8I>B|lgNStChIw3#M)L?!H314kb*Y=jw zQ&?JzYnGP?M+#4pQ2Lm8K}AH>R7>D;;~-Q~;$Kq{ir@Qr`87UedIz;*L87#mNgi^ZLbD?h^eQAm;7Uk*aqD13zHVzPOXgko0ApCK&_2DJrqAO=0&&WfwFyd6(Qtnk`M;pK?jT}rm$5aAx8=U>5* zChK>`1Wddoq3O7tzu!yBwV5G|_n&X~3#f43a%E=!W_Zxj`G4GofnxOSW@}@EAED!7KuJ01Oy{Ksj@H8%+N$(7mh7tUqdBVucs;-W@iW{TpQLoC@!I zYQ?MI!sOA-;(u%>I~x6RCZPkw{)1WwF!0hp!osL=o(7@RpY4M89HOhqO=6lcn^r#S zWx|M$H@3&5P0U+$3|iNWD>D)^U_Z?({|kDFEBp@31|dq-{z#A9!{&uSbm$NKCoXhM zJNCpy7o3;fCc-q|w2}Bv()AEc5`?sL&=(~C8Y;2!hCsDx4EpQ6mWBW+doDvh$=L^y xrQLg(#oU?EnbRPd&#;5*O`<=mrJw2WM31i0***&_Juqk_!IKNRnguY6U2cEf9!dZJ diff --git a/assets/data/tool-ui/line_pair_zipper.dat b/assets/data/tool-ui/line_pair_zipper.dat index c342b3e520a10a5b01b7f639c11d8c7cb93c685f..976d4eed00cb0f4165e7e551888cf79c3385f813 100644 GIT binary patch delta 2119 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 diff --git a/assets/data/tool-ui/list_chunker.dat b/assets/data/tool-ui/list_chunker.dat index e5728e8317c60994f9fd7bc88dfd8d79bfec561b..1f61c6e36a29acfc4e64a25413869e2493fac777 100644 GIT binary patch delta 2087 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®ew_H5AT z27`A0)ht*e_BBSDxAJc5mevs3kuvy=Fter*hE?6lLLkZ>IRcPVb9_B5m#Pzl6nNh4 RVS05G$T*o*`f+T0+87bT6M_H$ diff --git a/assets/data/tool-ui/list_difference.dat b/assets/data/tool-ui/list_difference.dat index d04ea9282baf98dd6d004710dd464d06480484e0..db5acdd6eb9dd24bef841bd13c32aca2dec49550 100644 GIT binary patch delta 2087 zcmV+?2-x?^5XumcI)Ap^Va>?_3}rdMnv&Jy#w` z^4;I9erEJrbOCWu%gREXfa(wj9zl`tC6xB!aSSivDx!*2oN zp0Z{8x{e6XK!2IcQAB^QC@~rWDDT&7$27Isd=QCqn2UKno#Qkt>gJjt^O&24newFX z%>3jD4xTKDhN0l_k{?48foeo4mT#b{0^g9icS;wiPm+T6=)7)pKN2RPwk3)1t6ls5 z=4`*nYRR^r}>r??`&Ry!34V9V&CC)MeAJghT2!DW=Best2GuBgxhYJ{1$7qVA zcFl@%sS?l7&K4cG?$C&0kf{tq^P6jwdlHO$1js&NNOUvZo8F&BQ!(ys^{ob6BVq05 z+OTh?v#4U0>8T~N6{^dT9^l`(|1k#H)Z|+d6IH_mHL=f`gm%pu2sShUB^B!dlDQ_2 z67Mtmn17;HnzNckK%aBTVMbAehhrjJ=R+b&HMmBvGGF2MUw&}_z7V~SpSusas?+bw zL1Nxvp3Xlr7-V^P{HeUxuX`{k{4^(4C}(^7RST!1GDKx4bUy<`sJkBj$Y|L(4}a0L zpoos}^l&N+@p@GhkhsJAAz?zr-bvnddDfXULx1c&oskX;_yQ5GY&)+Ij6(&eKsy%l zD?Bxu74mE#T=CK0N$wXkI9?4mN-x6DzFeibJtX(yIdmWL~vzDq>aNVOKYYB@yhHM8qQ6OI}XsQ`o%)~$bKsVmyY$g+}VxO zSn9SU#hA$0PO`u8r5qu0V2CeQ<%>Y7SfQ1r{k$qyjnqb^DSBB)l4C#xcUjE>uO7stG76 zD_4%r7qlzS672{xC@G@uo?xNwbbpX1?H43c|Eza=h?ycXz$|?lQ?Ae`>+AJj? zw%L(1m$Mm@pWp>P#veyS;~9IluI#et-Dv2qt{882(wh$ZZadW{%xh)sf_>@os|SlA zjDK}1I?ua0!jpxmUz)xpkbgguVz@l^DLg=BmV3W$M)BvQwQD)z)pzl9dJKgw1dTFE zs#=t^hH&fevM98aIram85s3KoaAwA0y(6aI6foRI3?Vk~0@jFH?1L4(pJrmXv)0Z@ph{`-Ce7{-q`!*iN*_S9N8J?)N_-k$`F>sxTzhE8d{5^H`k=ua z9}R?i5{Fy8@WHeioTD-VIWUnnGX}B7-Y7LSmc@J(ZCq38O#;Gv z_8+KITbV|_mo%2U^M3#>Uc4Ko?o}^?vC7f(%ASfvM{$ayy392K=f&z*thi=y-Z<0a zp_4dYSeR@vIICzx8B8&|TP?|s9;FC)N`6&ehNI;>n#+a_itZ{b@M7ZXm4+#oEy^;e z#GW~)g0NprT4JlW`9K0fS2!wimSm{(UrGH$?@1Ev9p2a@&wmsS@f3WFN9swk^s8vF z?}YwWM03)9=|rPEene(Z{te4gW@~8zVP&KGdA<*jarsxDx!mGGQyBe?Dyc1h2&57y+-x`XQ-Mhg*Yze8wDuj9VjzDwLZ@-iDXC<&|9p^pymvJYm zO#cY!i;a(Sqkp&;Cf*%6y!LGSQA!p21ciy`ZXK~?+0gWR@f@s~As%?B5MMLQINu`o za`n~>9|=IcJdocy%hL;@wdml9`HphIa#0RKqJU>l(e7rI3n6eD_Ac9Yel3iTC6i-q zfVM1385HI0Q(n&wRUSnY>RXNS7qK(?SqsjEHIYrDzaYVE;)v=L|GW!#w1V7Uxt-4a RLAbt|53@~vvw~)pQgXwa3bz0N delta 2087 zcmV+?2-x?^5XumcI)Af^rJk3e_nk4L==_#hj^^)4(!jtfMu)_)LE~{)wtrqG6ATf z7b5i8lYGp%Q7rq5k&li2wR8hm`5_xGHJzQ1W1KduSYP7qmVb}}(GiJ6HXoKDtnzh8 zYM{gHS`JY3@;jXVZs2_u1|Q}J@%Q2`9tXxgi(P`Lw)g;38D8c>*EfK%5l)S4wj{Qh zV)oyByX>?Q^3Ya%r_^n`PlKk#kbTPA#+r@f`>k@HT&k3DH2vU}x2`+Wjx!r(+FwyPN=l^kSI()w+o9X=xB1$L|r&J+hC)h#^;Eenn z@!5mz>sZPL_x%>kdcy?RL6J<=8j^)I11s~wg_k*e+oBxC1NN?Sq-&q|=2U;OPyHw4 z-_$&WC^zHQI@&YZCLq0dRC}DP)CMXA2wy!~{R4K&MStr|C})N864#(X1D8Ig^VT7I zVXPGP|L=QNj8qTp0n5R3O|Iet5CjZ_t}EcyyKB}%i_rXIW&mV@#zvKM)b3{-GT@tP zMLwf<m5lX%dd_2u)4s_4(aRXil_7XZU zdULq-OED;#WE40$*DQWQ?uJa^GH*FjmRN7Rw-z4swm&%tpsQ^0l6p8zj5nV|K{SH# zQ^w+BZzhyi##$Rn<2XF6EIJDGtLOQDPNDYR!hcdWjORXhK4x#Rm22>1>?8ZR%{}Kc zHmI_CwL=yxY~9p`ftI-os~D&6sadv9BH`ZjOs^ND+rsZ`72ROahjUDH2BO8tPCSAH zJ45+4lEIvzi*Fc%)YbAG)J->8KBjIlT+U&O>Yha^{x2!0O*lKJr&cGfzXZ+rZZ`Vu z{eM0d7OYh-$Ug3Dx>mc6silC;n;ArA?R_GhRyvgFfJ28l=?8pGY5Bv1pC_ZYc*AK6{!lTRon~lOZ zZ@EP>hv2iHT;xr;12Yz(yxQp-}zv+g`=1r(M`SA7vg=ZK^P^R?-SKi%Lv z&k$CN=!v5a{~kxL_c_OG%kTJDghpnkI?Lz+Z|^KV=8AOnQ+zy6U(4DxpIEwr;U+>S z&c$S4GdY$@1ki0|iYjIIP}H)GPhY~+?X zmE8g_m|LzgoHAmrR7Y;`4xCdc+??YKNb6j;JIXwBkVye^mans}4q9?p2Y*+Z7{9{+ zzyeEIAgQP-KmXTe$MiX)!nkU)m480~?!Gaof-bN$NW&azaMsRwuc(<~7tL%mXT$Qf zCMIBja0KEFUsLq4p64ks3pCJ?)S$nFUnv4@HfQH(`OzFgV{7PnY9DqTTU5`mG%-%K zuJd2_9kxj5L`vI6pAdDdR)5Kn;ocI0pDB5;UWkT9Um(l(`W!QmiBbr$8K-vuKvmvg~Vt+Dm)RFu3vky*q zMGtxBRP#Y_ZWa?+IkYU!fasX?$gTn%n(p$M;4nys4`?SXj%g3tYsTv|UIw|>c6p?9 zXGeC+FI{x2cnZ9tzJU7o_erG>Tim$HR#9b}=x=o!0`+0HEQc9O*CUrb8ct>NU2+zK z1(w^6c$_T03w~`kX@B^aU@-SVvRI1-=eLv)K3d(4x4f4Ybji_X>LJP8JV;V-^G`8c zh1Fe1^dBN01)8)u*NWdGnf{AJt+?uG2{^rqUJl?edQ-M#9TdO*(l=A(`n630>?0;h zz0@` z60)HbYB*rRPHP$iL|I}D{Ub7R*WL-oPl}>P1eY~N(8_|<5YCm&Us3L%kuMe{;pOzP7&LLk?a87YpUt8FtWT;sX%Ga06m R59i;7<)-Q+rqHT~_V%9I6l(wg diff --git a/assets/data/tool-ui/list_group_statistics.dat b/assets/data/tool-ui/list_group_statistics.dat index 10ce0507cbd60f30339ebf0923db4dbc9d051940..e5b6e0d6ce04316c0ce93d40cc4e9e340408d0d5 100644 GIT binary patch delta 2119 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 Rx9o4hJe*`9us)8p&LSlr6|?{V diff --git a/assets/data/tool-ui/list_sampler.dat b/assets/data/tool-ui/list_sampler.dat index 95185ac1dc15d34cbdeff2ba3a95df9e5d3d9ee3..233189831559a32157cd3c1f899474d7a2de64e9 100644 GIT binary patch delta 2087 zcmV+?2-x?>5XTUZH-Dhay}3klMI9dP--WB#uq-7x+@8K)V7hCil^SVeU<=;jnBu&l z&;gd>p4XjSsguCzfWn0mhsjY1$jak7oqik$%B$A$5-UYGVJ*7__SuxO|M4brT_pIi zE*_V$J1xVAQh!e&+PG~Sz^^DEiqD8%n6(9{63+w3=70k?CVwSs3vzyc8MrG%440*8 z?fMgFMQxvut%41WbZ237nPAmMbl0q!an*+KHZ&8kerxm$=*c%@W)Ek5?THNchdA+X zY|o)Zw@)#k1^3MPeL?l~jATmDWF_1C#=VEDIq=5>l@% zbrgaTNc6SMFMrQUl_`T|Ced-1(_pt)8Ee5hTY!`Nz_7_Tm)O|dblc|BL1iS7Tx++A zR%dzKG~iLHFq*IfuAA>-cIP|UDB{V!D?U{813R(* zooMK+r@o>m!l8S15?aDUyNh0CP5hg8siWN0OThmtC5g40)H)1aKFO(c`c|Pc#q$--bbgN+)#h!{z20jk3j7H2ls_T5 z91WSML12J*BXayK9B$1W$QA<{kO*b$I8}eNYN)}Dw;t|f+K2p^G7}#tHkp5AKCM%% z(X;4-+n%v@jPQ(0=2Yq)JV^|kTo>SOL!b27Eq_?D=)4@Hjf0uE=sL}9FRh_sk2ER& zoO4_Ih}?MCn%vZUt(p7GI9T=R%X{QthwQGc{-)6$?@8eAEMu2UiFf8ys3B8yoEsEf z{Q(6z6Nna}%o0giAu?M|eSeBuQ7tK8p4Ae_8E;;b3_5Pp>#%w9ENAM!Tir&^r$4W6 zpMTqQu74;XvWG5~Z3F&^TEZv6d) zpQvDR%W7PbOzfz-dPS`C6vuSJTQ#F9lz-S3E1J$ePsY9UQ9o_B@|u>or>u`TW@4`f z`N&USohmN$N%d-Hd+q%5u@;i)HU%jTdhShnZ`93y7`+ScAcZ4|}@ zM2JWZU(H+R;V^}84Byy^N}wb%>JlXkB2HwX?eH9YM&!=`d2a&46Qc&yKAOQC5Pzdf zc7@{Tuwo;c{v+p26yj(r72@y& z8iBND1w8{00X@O9bu>>q8-J(rh@-S>LN5I&~X*bxeuZvUVj5NAw0> zv=W3+vFjOGiCj40LSVj_p2;1mROAI_`U4moHvk#jt9#G;!0Z|7eqQ=towOd%PY z`u3#&R1(fq$U*T6=S6lax)a~|Gkl^Fmgj9A^esux{6>%uy5de?Qa8qznOVkVKsmkRmhXrTrJlYiv1qnmr~fHe!1MBP@1 z0ezXtK4!tPc`ijjon@N1dYFR1D26UA1sPQ63ve+fNo>J0#>$tIWHvRk?cA>b8>a}X zSx-j+)SbNTe_Zwm5qAZ4;5Ucq1>H#kkbey}Ck^nLLRrPNDtd*(RxL_@(xY&Hy`jj4bnp8mB7oaSW-1X?qg{<- z3@EHniNyVJYEFlvOi%w3d`hJ~3yFN8Jp7V9!nxOLq=)U*xY?71x|KxsVeuVIzE6{v zHzbpelwYo?qeF>S%_F)i3J)*D`!K6I)h>pA`7lrA0wC3pdBf5{cgr62u%(%_Y{#%& Rcr7Apf+wz_OzrM^Xk>_g0s8;| delta 2087 zcmV+?2-x?>5XTUZH-GN;;lFYfAli6_RMujs1);l`eEYfQK-Ej?OWHebRntLioE}&l zCsmwwM^@8Zm@i@np@NWW6eq9sYb=lz7~O@l`oI5yRg6iyb>d#(ua(Gh=S*sHoJHFV zB43q56Elp+NkZc8OzV4Bi9V!m&|q+5rVTW;R3} zP?%IqDnt6s&95D!Njw^Fz)gd^OEeyY?qd-2>VgoyGjzsOLZK`Hy&{N7@&cNxae2|4 zFRx^~9aG#ulz;59^v#+v(-$9kz*Qvf5$~(6<=PCLo@sOO*6mKzK26X*A#gL;E2L>z zG5*%_dS+$PN%o#1_t?O^Q#~|>V*km2S9ZvP@JpH-ZyL366boPG!ICSh*=gwiK0GX? z$M;Ka3B0M4v15?r-J7CO@DF#nvc1Y)=na+@nc)uUntz)%bZ%A8Dc8O0J^Ny~k^cAw zVrQMT-{+?*A{bvHe>oev19WLhJ9O=?hJ;afT?gLe0v|Oo;$9MSt#Ws~1DmOammVRs z7{AD13+l|q1D!XxYbgh_3)HE-{KF1K@+5?xYUK8eYB|G!StWYfFrU{r{tk8=1)RzW z$oMgNLx0L;*`>27dE3ChQ2-9{_ zh*~4f({@f|ITeF82Wc510&I|Nef=4owYhQ?V1J-NRc0Ii9-4%hI|HVHk*bTmdt$*O z&Xwdm5%i9!B)^^c-6v^-oC2*;aEhvm$Hap|PE>7*Yzeu!K;)^vC>(m@>1L{={t4un zO&x#CVv-fE^e(;R1jr67ld@6jO8Qs{+ta1bjDg;^%N4FW7qw)mqdMZkjP<8#_%$P% z+da!wOJ#!6uuM$ht zQ{{|ljEiWkA!FYy6J`w3Q2R@7!8UVF>3{6URnzwq;V7m-kMB+xPa{H4w~WfUw0^C$ z>0xkNns6AEl-w4oqs7)W7W9}|dIG6Vn!F5r)k*(Y*KONkH`Kh9bR$P&e@cKkQEKAx zW=K!6Eys3~)7&=L2V|IY!xRFiI!AMP;U{809js=imuU|IH4^N3wW-9~zv=aqX@803 z`Jc-B0^;CYQDuQIJ)oQdnl)r3Den3%ndw8XUQTR|bbJ>G8@y6P@CA19DDETtzag(OL z6dCuWH!!A52A;#wp8opHXxHf3sp*ptj;<;m*{9tuetmw)5y0JCa# z1mv$%!N2w;3|D~wG8-Ib)~RJJ@V~uzysS>6XGrEq5!zec+^Ms+oHPA*euyp0?j7BN zB7Pa@>gwd3n~`qF3&uj&Wk5}wA7eK77CCFcuG4FBvvC4w%Sl>)qjV^-(h1OaXgVRV z3%3iLOzlfxm%#&+t9rHghc9OmAcjoP`S zWij`9gDDp+`k-{jPl7~Pz}X;BOGB$?*E^E`Xh5+soI=Oqc!ETJKW-u^F#k7Ol462_ zfx#6I!ZAyDrIJ2KpV%~8i#wO?i)18Z-4=yI-q3ImokJe(-n4^Q&wqQ_(KDL=w^2|< z)wuA*aDs{1mWl`W&v02drTM-hwRn{l;!=r^&}Ft2!k?u zQZj-A)%y7W7nT`Y@Dsp4fs(|g=AvQYn4d2_klz;OeFawE3}k2O97rcz-N>$qqT zhr)j(5t*P0MFVnBk5>W_dLAWHl`e*r2ggaWP=xEY{zzWX+0h3qZaA_cFTDOu0qAulz?@=vRsSMcnbV@Qm`4}B2tGIh<~$M&2&?c^uF*zht-FZ z2@BhR|DmB}tHKAsi8X4N&q|+RSrS9L4Hk3ueMA1sz!l|nVcYeQmM0^=_}q6BgY{cc0J*oQ1aO_@af ziRTk9cX)m-W^U2lJ z27jf6p)~(-1%6Tif0$EEcw9_cRLlie2v~pE&Xc*=i(EO;Ckdidli~MQNb##;?xp~Kt(n&N_sooG1PMT91_+%otF`Ur|g0!fhx^a1; zRHP79LF^EL7z%lI0?adA{12a!VtKcAZq1xE z_~CBKDmPLrG-GRvJUqLM(qHqkkVwZSTH7ZX{NF*i+=m|PfHjG)u zQIN3h9#p;CDU~a(8PcLW9gJj4Rkd$vV(cg9J7tc;L>uL{!GZU^(rT;&&VO&6$#g++ zo#Ve!n*ju)X zu?^wIRS|2c)qpJ$_CXRVJTIs%^hwe+HUtZIcpU=aE3be3z|M94$ml+A{hn z+6sqROG&hEOk{rtlqmKnWvt37ZwKky10w!^d^M|9ZWcvtQfB=4e~@b|E5vkW2gJF0 zaIjQQ2x)3CZwf5>R)VuctkECIkR`yI2uhQ1{mo*j6OJy;?yfXuGJpT*%HlAj=0nzv z1h0N)oD=67@I(2xS!Xz`GucX>jnSa!CYK$*yF$YscwbwW@_Yia8@|ra)Oe>+TOIrF!l&eelRg38j}I z5{^faZ|^+M47Zlsp{IJB*xTc|>>{aGyXtCWEeZ8ICKp}BR6@w~`ndE7k@K#(-G(Ua zKdx&n%M@`5sDF}{zWN88FIFhumve)v;+=``(h3!)+AXOCNZM9l@mWsxP_) zqVe^@p)-;H`@eF{k`=wUK(mhq=f;P=f6eNS+1E0EY7mMUA2DNrTr{d&L*Xk*&<*61 B>+1jj delta 2071 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 diff --git a/assets/data/tool-ui/magic_number_lookup.dat b/assets/data/tool-ui/magic_number_lookup.dat index d6aff9fb63557fa38e4c9a76c79e32a51d7b3203..67b7a5f99bd830623f964fce92ade37b6ca964e9 100644 GIT binary patch delta 2119 zcmV-N2)Os|5bh9=K7Z<=uKl{^ohJ3Rqu^&Enz zKq{)m)OpvJqrmcMezQ)d(Rr@B0z{vKAh^!}5yQMJbm4g2G=Gct`M~!JRVW~;PGy1V;`(c*$y5~E25it;x(lYvrOjRh#5AI2+$awnUZ9kPEVV`7&*lDi4ReJ`5H;1^H;4LclRF8DLVp)7Q zS=g>zsAPXP9wpzpfdNW{vdT+%?}XeyxKO9fc<>E1pRw;*5=m^(_3LICh{7HEcC^M_ zZbnuPp?`bylAQx6>geA)I!onl*KEoS3g#)xO4k=;;;oSTn4uDlg?rOtqTMiKF70vE z$Z)?Z%gM5A9xOCJLn~p91;0Ontj6P;*{aVGG;m7-vp+@dcF)S9OI48_1zpwD(J1HcvLEJl(UWX+HsipD2-&e6n|!?kTV)e88t(Xht2Z0#^_d-RwM`5=L`Kb z{xC!?G@jn83vil>a|k9ktD4a#t6ie|(o1Tx6Q_Zsb!BfTLfN_xMtcH!2N_5I4CiGP zH4NNZ1VSC>3+;HNhymzSbYi8UR{#wQO`r;!3kK{W*>YqjCLnq=c>X@a@Mji)#D5rl zDj+ztJL#jR!Lzg6_*?3Q7KDNOR4PS6nJ2SJVOHuHpRs};Zd0tQWqG!xy$`y00eoIS zyk_ogX7&?Q&T_}o(o4O z1Tcr!;Sj56KhBL8=yb$UfM0vU=zm99vS2i_wxB_LUxO$#7|0za8kb#0J~)rQ_gg?7 z+dm}~KSO|60s9LOQ%ywGQ$s$?DBJl%E;Pp23|LzjDb_k1R9fo)w_MMfl(VBA{eQ!ypTxJt zKjIEsN~4>MEZ@=#;Dak%v`E{md7*K`oo_vfSWzIQcAFRdxVAT%n__%wIqsO>^f+`{ zk?SMbmF`xl1)$cx`lT!vGMKRaJg-1dT}i07_R`Yq5|)ZVjjr5#=3zmj)6!bV^yl~b zI_+6;7aiAPjco4aV$Iku(0`nrZoYmZ2#b{)?w9dRfno5079b=Tb*TcC75VaVS%A>; zYHEhG$qw;m_h_>@y>IJox1^wo)%6|GBFf&p_>0{zV$L^s3%z|+dq>bp(8NO>=PLPc zOzWux3VPetXQC483mqB+su(I`4B{SOpkgz|)t}5~R{#;k#`&Vw5r5rokTO`V*JTw2 zkfK_G6p1{8yXl+sF>u&}4zb9)!j|LFD9h2r01#fmo~)AJiwKnjhglkNZAdLQ zH>75kw|6UVMY}&_0}K>B=Py#wtnmw7;_|UHf)P3t7CHCNCNAs+%;h;Ps@_1ynV#}IC;OP2 z;14h;xd1_dsAr3Yu|qP|;dvhCu#?PLA(`F;(vG!@C3cC|fOgLIkKUX)bl29Y3un0; zN;uz@!cK!_!k(X@y%$J xW8*rk)urrw`$cuk01wPL{G>e)H!p>(n40SV?R)m-{pq~}_;{1wB*g## delta 2119 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 Re#*O0BPJe#PjZS|o(Z4NB=-OS diff --git a/assets/data/tool-ui/manifest_template_export.dat b/assets/data/tool-ui/manifest_template_export.dat index 49f4b209d9780fd815ced1164e930d13b6be9546..36368550d85538603ef15e249a4b07d9b0498f8c 100644 GIT binary patch delta 2135 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 N;ul&z#I$=#*^n_vAG!bl diff --git a/assets/data/tool-ui/markdown_list_cleaner.dat b/assets/data/tool-ui/markdown_list_cleaner.dat index cedc97f60faafeb3bb180e07d4a6241e83fb02d7..9afed2cda22d699a404b1504a3626bd704e751a1 100644 GIT binary patch delta 2103 zcmV-72*~%~5a1AyK!0Y@Y*qM!A>zo$?wCCxpDc@srxCb=@+1Whunf$ysAKo0ht9i7 zez3!#9e`l|iMjvu?Y)ES^Jo34XoMa)?Se47pIG3eOV7g6(8MJ#8B$_smAG~RN_WtJ zpJ91SWUW9(WU`ZJvX9NR>2F3|{!+>`cv>ziMuPj3KPhXX6@R0lW6VpFFhi3K1{9?R zeM&~Xy#D$oSk4>1%=!f{@x_<$B{*wrs@=;+oX-v+dWdmdi%QjYV_%)T3T7V@1OJij zJEHE08>Zy;LR!n9M&o&o88O0mJESJsC;x(ifW6;i%$s(Hc!d76vpHFMl`g&;K694o zF@U3x^GLz9aDOT+Nu>o7^B_(u;228$f_1M|lDR9W`p(nGQM0lzG3F%yN@p`p%g;DS zP8*&{hc6C&-aN^&hd10_4`}#*jHGq3(*B0+@9pEtXmeRWyY7?(5&98(AMz2Qhj7fC zVJVe_?Ca}ltW*MBkvfJS+7RM^T@Lf-e9_Xgi8JT>C4XCS(QP>*vR5^lFJtQ5?x6DN zFqPI`=}I@c;t&-RXTI6ds1c?|;j5#-Dl}F7dBGFNT0Kg-<-)h;{S;V^Vgll+-f7%@ ze4`=YK~ldEmqtmA!XQA1F_lXm4D>Um@Iedq37v7$*{^lqU0Y|w#e0l@b*Q9puMbg0 zolO5h#ecY20NRuGrDy^5#1cei`6ajLl0Fpn@DEaDlbq0hp~k85QsN3x2R2lV5S`N{ z@Viro%&Vj+zyIK6er@R$apK~Pz7y{F4zaW$wfvnBKtDCgI}U+xrT{VoOO5}No97%> zUQfxVh9XZzD(Zp`?)R_c|Hfy*p}NLYCJ|EH7khgyb_3 z7t6qvcd5OoNr2PW_ zn3rRzljRAh7ziX;@{2QPvb_}Wu)mgBv0h91(gIH{z(R>3pqqzP^`Of`uEw@M?#$Lt z-dFKvYIB!fB9if<6YT8}E3n1E(qWGK$t1~T{ZEpR2Tm3@$9;7byG0k`T)=YHksqt9 zF)76@LKNp4b%&0R6yf1WTa(ED^?#Usp5c7e>@P&>jqcz5T`~m^wvb`Pr;c%U4Ut!> zDxM0W6+lX-OL!-??eL3jfw4^GQ<#3Gpfl+;kB%-i zjk@RR_?abvgQP57{pN=HiS3eY(voN+KT;EEUZ?a99T$(n3sWOM&fL*Uuz#B*+rq&B znZ-M0%=Th~M3cET2f#3*4TMZu z=CllikLZY66O=Yc$+7;og;F?9QW!S|V3AEfawfi$* z?u3vysL>@*ESz0~#svGeWZ1UONId(i3o;{!)u=tV}yEfitM`@-(_xZ|V8Dp4bt=@n@PA;Y?~`W(##u!fq#V;O zHAR1$zhodsQUL}bR_2EnhMNZjfFG0oV#jQSJm~0m0+w^oJROedJ@-@z6Y|+fwpy|E z=lFGOl?>V}a&iga6+8XXyT84b(Ou_^M7B8;MEGtTLRS7e;nKBuDZs&HqpKN;8Te`4wGwd6zNm$DGfYyvcb~c zi!|O!r9Tr`TCK{5q(?*jdF_dkPMewX)v+86NOZz9GPYP0OeFf?^-My8oLZ271<7gu zu$R{mW)OfTig+a=7Kt3A@tf#uYa{-Um|&oyD=_b+xn`7Ba1hqJNcwHy0VY|} hTxfe6A*$imK}heFk6eNTxo(O8cPEmMu_c->J}-_dC}scv delta 2103 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 delta 2248 zcmV;(2siiZ5$h3Z#O^b=lUqvM*caiXz94?w;Usq4O6b2_(&9 zIHiL~R#upsi76fCl!!xEkt;Gx~-Lz=}YGR6q?_f!9|yLiCCH zrL&Bv1ic`LE?|E3EvujU!KU^nPkR)irc+-XY+qP^n$<(-^C*m(to)@H4D#i>_cS$xhc{%qX7GM z=gUc?0aY67n198XUJ~tHEh8Pl$MU`wrQMlu>=*FOCL1KUZ$Gg~>@mc-&U^$wZQdIo zaBRs~4)tUU^gcefNsCAFYX*7FM>H4aaN6Jn)T-kzuHM1u)2tRuuE;{Aa z9R%>9XK4EGL7zX6JDkrO4yUQ-t%Ww!Xdf8LgI>2l$bUA<9-3X(MXz=M3W4f$D&=uK z0rXfabYvbStJB#18A9_S=L4dxbH4eqoO<833rwh!|4%iL5*Z+0` z`YGjXXEb>i_*lMKg5lJWBmyOxl)w&5UF{KeTYt!WDS;GX8$N=Zj%W(9sy~EO4Rvh2 zmNc(^vK2QjE|^TH0Tf(B3`V7xbfpn(85QNM=nI45KPHjTIl_?_+5;l3j;V?{01_ht zU(wb&1rp^f>r9|c*Mb!t@r+g1l1CQJ74Iqz`2`2x0A3n z6CuuL4Y$`!-ckSBf=@hXdehB0`JqfLn}6$I+}mJ&Y#3Ve{tldZgzA5{Yv}!8UL$0c zVQKN=ZtQ))7(=QPJA zd+e~D(g?yB730OAqDUhL%`HJ79|p80nN;inhY9STcv56n%D*a;44aoQY}6N$6My$c zS3p`TRRSttMHC%KSe;)$U~sz~R;VDV7`y5* z%{LjBfxV>2ee7v}T~1}Y6tg^PTz^iTap&8_HT&6*LBlz)Q6x2xU{5{679EI^X`?u`*~2?+jluSD8Rli2#b}^a{2Q_fbS{uavaZhnNNi{7q0TQ>Qe7N}?T~%NFAI z520JC1_5`>_xCraE5btMakqKD*amJa12!&_dG(ugBUBTj1W2)>G?9-YT7R8|47ex{ zH0?ajf50UNhRQm{PYRX86tj{Og%QJ!ELPdxG1K8UtDQ6EuAzCW zzzd#%_KtBiFzfKu#*}nJuS(z4NwjdJ{!qIOP6+QSTu(M9%$Kp6;}_NWJkBe9W(MS4 zwu_BAN+qmxHf?Kh!+*z$4-!Ms`doiRRaZUgK*A)?rkLdnFqIc?a>TMW@vNk`=pn$= zZtLr}N@NR;1pe)Tef_6677bXi-H z^~vNkluuG3-bZHFnZbU0s~LXy<*<^7T8;KP zAkd%*)7Pwwz+RJ-I!xvhuaTH-d_Ym_hlkz6Ycl_5)ol$t(dF)WLY?+V6VZi&ha!6?rQu7Wo z8>*(s$U(6KMciBq(w|#jv{=T-WIv5aMlz+1H=>wa^Ojv3St=eM_{u^i6 WX5o&3#8;^N=_E%7gBJLSN8sEGa7{u0 diff --git a/assets/data/tool-ui/markdown_table_normalizer.dat b/assets/data/tool-ui/markdown_table_normalizer.dat index 39a4433daf1f8db2503355f605f3e5db75d00122..7fad412e83587a7c2fcc127af8b8496ba4b04a9d 100644 GIT binary patch delta 2167 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 NKDSPVFQjFQAikcKK-mBQ delta 1667 zcmV-}27LLa4W|u|H-CjppI*Op!y%-kp|H0feUGP-9J!qAmVJn}wWe&AZ3*huu(M#X z?5iSw{fkM|L8!n11cT6Mzy6jL&h2kV>GLqyvHh@Xql&YspaWOb5$4A1F^$*Fi(iN<(>=#h(HimN_pMm zbrWb67SmdpZTT&d;r)eV-SvfNnkoB(ijO?L*@)JQ_>Pt)2Y7t%3)xq5HU?EG*TJ-E zPSBU|6oSxqQh#P~d+vk~K`-BusnQ>Fs+yk}&6|~!p|**Ed^({`#@{8lRBq#t%BVRS zFF@og-dM_m+H3;E)UKn^PVJ>0OP`~wj2zrxqsRSc*4FFe zv8sxK@{ZQ|=MPc50V4t*p0m1}jwSL~ogzNdDN$Y}^~YOLq;R*9Jw)!vP3cBK1QCy` zT6ZmlsVGw^;;O;DHtbRsOecjMyLGn~8nimTPu>r|_=Bqew7wBP+Ae6waTxDe?v}L6 zB-D5n1%DFdXJC6a(M;C2!3f4skTpz%z2&4xnPnEV$=8x%AiJbsyMgkJ=BTEOwg+`n zD8Ij;nj-6vXbt?pqmLvC?)zShwYU6mD0d?U67MSJ@mJl#aM#z>NPm5cZeUwW-MbH-og%2L?k(X2ok)zS z{AQaBe7LJcA-QzhWibkkG<4Qe^&eUcDzBelK`CRB1wN2m#p-Wu=~Hv-Jk?+ov{&GQSS!@h>9Klk$V^5v z0)K1+%Zk(cT{;3w?EnueKI3`y7S6Jj_re7HJ5i?J&6ab)dSd9b?@!8KI+w~qOt*^h z4y)t+@JSwIZy`FD+0#jji8ZvH-K)@SKd0?qtWm|{gI^p<4A1Lp@V%pw>dM8|{>qf2 z3F#i&pY&&Yz^S0q+O+yFBhoG8BlBsDXn%q3m4};Ij2>VR8uNj#@czkHnBL|VIyX;? zM>gwKtrfE}&Sh0D{(MFgyJGOSd5xjsWd;x%=aJ*1R>M9^nEF=$k(wKtd{-Y_2uXQb zV;iL&<0#GhM-B-X{+nmzyFbapHY`hU6I ztY@eqsT-uGR!It~mh5e8=*U1wF;xhqhL#tyWx0U!xg%0bl zl%FD45keL=d?lE~!}D;mMStMP<6JkC;jygve*v9~TmlF<7&@-%N^jj*N;A&F*kirO zp=C1f!wSn7 z$>`J-(YI$v@sT*AZIrp?%9VjC`}I^wsr4h6?gI|5AL8pkqB3MJB4!d%mulsc?VkL7 z`!7_J?PRS-mIM9JO;U^%JZ0F>@+3i?{X>K~S?}`D*{h&r!@gG-M1Ln$r2+3LR&n)` N!Yj#eb=y^B``tylW%S!h`Vdxc}wjX!w;!3 z2zoRDgJV=4_<3IbvulIxnPQvSr7EY?Y66lw5^EUh4XK2_fva{w92@E`=x$jGWDe z{_j_!iJuO7Pmz)wA;Hd zsZDD(U5LQWaeu<><ga_5M+>zB`wGBA>XG zgLuXXmw2}E)u`sGO7s%t>6V9sz0_aZxYd zf%Efg;R%iwJs%NU*N3dzhJ)^y-@6Y6`yOdGNU31-On>d9^~h=fh$r}NMJ@@dHvkhk z>(qbaX1S{tV(gok1#d;md{;X~K6Dy`;t_xmjP#xr*Mf=>h|lV(+J z_fLrBuYaN#;1Ekl-kF;Aay?xc$EOdPp~;}SiTxDVLj8|5_)UFf6zM=$urqJ?qf>v7 zrM9?cct!E<&sZ;(x1hCc4F_{JCV?{;KNK66f8ny6z+u@6HI$?i4`hSmb3B?Rt7(KW zIxgk?pm0^SKxL4)W{Ov9&rjK*H{-Y~*feU^!+(DF?_`H+8)~#B3)pX>00(<1%OGp< zCUnV}$O~Tye$3ba_=gOMZ;e{;!<9%`3)lP(GEP>=+*?Cx0V0)R?8@**#Kp-W-XKm& z+Uw|zCZk8T6d8UntrWzT;#HuvwqP8xM-BANX)UZ*V*6oq^9Z8rtlkP*cuy;@uFN}(9wF&Ew)CEbj&SiW zbDTK$CN36m`z$Go;0EzS6uf|w-1PD%CCpn_H$aD7CB)$CX}EPrNlM_+mU9A(NT#hI zm&k(o%9nll1|dat20;^KXnv^JHY-@R7k?b7h6ByS&BSHorfow(8n&2aD65}_=`i4O zzH*O+J+mPGm!W9xyfP$((?BCEFwFz$9nP2e29RqWzB3#rU^UNo-&!&ag~BxdV^(9# zz0}#5=!zf(E0!aDC!KB=$Gy|4Q%J#5uJ* zh6p!v*{CCRIfq`ww|~NM-t_n4d+!`tgJxP81bzHr+Ln(}^3$a1aXv6@u6@q|5|_(R z>EA)Gp54`Y_+-Je{7cl-!hUx~a(`Im{Td#6aM=Y2PmqomLieTp?hKZt&|zS1Oh3i>2zlR`|LPGiTDby`*hC|)0Goj`P-9rS~-;s z0&nBgPN_5Z_i|h3a{mKxgMZ!v2eQF$6d-2eQO;cc%iDdz?HlVRY{@1@BbAxm-4fV> zEIr#cnpfqzUkgp1D)3IHyW4(@px0(f z!PTqboEi9)EO!i%&wbyhFWnjbn{)u}NJg|Fvr1ijV`VcQnFFOv|2cGjT3Cux}` zpVNg8%{oZ7ke)83G=F9Ei7Q$;C-tv)(OmZ*5i(KmRvv$#r9X~Hsu@<(X+{k1dnF9J zj3-VeQG}p{@RLHN?qcL1&bF_uDn}*Vb&P9#4{#tk!iP9XgwWaf2%*U6J3d;p0$j5> z19dmDx5dDFRNnmdIN|%k!(6YJjg0J`m_;?B-n=@Z{IUuiUw;{<;+|VAUts?4X%0dF zC39`|x_Wsl{9ETGFLX7VE0IJ3k%<93L=3Og>ohOGv!UO}OR{AOowRLA1Q#y@Jzrm9A!PS9sb6}0vf#x6W(SjEOL2K3rkI36UTKvOtjvgmdSEYzIa%Gf zlfoKUNzN#PAOMNYd2P*pB%1Y27@?MFaS(kFO{CYH-d{BP+IaO()qR8uz7$M2#B^y9 ETbq^WNdN!< delta 2022 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 MuPRk$p-yb`Msyk}8~^|S literal 2118 zcmV-M2)XxJO-NN#RY@@d3jl3tZDn6dqFp5TSb=L`j|eF7THo#`hLJvelP2 zg&s-6Ewt6}yRhi#OPxHAtS38c3ZV()ZOhy+r?Nd-2PDXO7%SRNUlP|%In*+V04t55 zdd2c_*SpUPz;+`k10dp!!vhDl*vfTJk*n%^VW7%wEW%~6g`0{ZBvZI4;ua-ndr*Dh z%E^s=-D4pcR%Kntmpr#?s&qhUJgPwgS8Say>3BK`4MQo;nA# z5bt)7|4;KHPVy4JkR_AA_K=(SwSWG>m;tmi&y(ab*B1Jr5n5IY%iz>JG;_W+6)Cgf zc0^&kvPFEW;!%*P^C(pw5ij$)^mdQK3=U8hG~g*>;CTr}+>wgFihdBpaCy+`o2?(McO_r3ii5;Ea zNGp;`&XMn%T$mfc;$zjo>niZ&iPq<2$);+aD(#4n3_nDT*xZ2Tle43QbvrgG$X{q{ z_D0xNjIZW-tu{I(UmicZ?Sea_3s4X$7NJ&M#P)r+c$7nZUBNn@=$!wN9a-p&L$@cX zd!vh3V@eYC@D=7)m$sOyyth#gN#EfN%}4dF;#so!4zKZd`B8Wxu|zn?%>ueZ+pC}t z{{n9b7=YvrOto9WqJgNO3~=t8dl|gkS*HqiVyG_2hPHrCx|;rEXDJ@av|m{at}O;r zY`ej(JQ0LC1EwNoXLLYcx~(@TCkEY@Egc8zZlV?xN{aFakH%3bx+- zHHmZ%XTPY*H)TeLJ8wZ(j@L|9^drc|F#ZRL4bBl2!rnO`{7e+Slt? zJ`ueZ1a{J;YSz~0zRe<17^sky61oRnljj*>4_;&m*Oj?1epa|uL~o^dn4XMKJG4O$ z+#=b6+9(_*^E{cFI)e@?!9y5dJSD53ZnoPmI;0E)OsKAFWX}kj2T0-}hg^p#DL>E- zS4cP#6?1yd*1}57^qw04fg?ao?b{mmU4LQyfmzh1VoF?K8I0X#?qLcd!mm))>j@wv zus~TYc4HpC+-aB`TY#S}(4}6xd`9do(AJiHMLyDsnMf2u@ zHr;L&1@)|}upApXiIr2y;qR!_PF_w?M0r5Vo+beTY8L8PD7JHaM}ZAxu9kNC7&%L~ zcNPdrtpv4pFfI3ihdO?x6vFAu+gzVzX8t1!YWp!6*@?}Ubt*({UXknV;Wf$ ze`K#cLAPfzEj@eCFL$eVze@tr%%FhcGIz*G?HLJEbB)bSb-0phN!j1*Ac=u|ouEMq z!Zxz*f67QjZBCajO}K%wfp;x?K4t(likUk78C-7-oZ?lNL4KC`bM+LqFfn>RrYoH zlY0g{(~|;+o9Ff;NuuhOnBAWQE=H$L*uSVA;;DH)Z@{3>yT{gayYqG;D#i?!JlTxz*|e1Q#n6b#YJ8Ni!boY zRH@pZQ~LJ0%RO-x?mdaJD7X!v&fq0O>>Lkz0Z;K;gT`maS>n0EV#~iCk4LV009G<+ zts^QV%|aGUD+Uq_Ik@kX4vLbT+Qm^x|215K-Z_?$d}4{0#8eC51nbvqOcUt>b5a!f z4*21Sg~-u*xnG)rA|<_Pkr9vk@mx5mGzcF~5evD~L z*I`nSACNpuL!{(KUab}A&vOm2n@guD9`ItaoacR=?OakRB6wL<9<~dKw`00$@R$kG zo+v6MaX@N&dX>)Hd=qK`es_m1iS=W=myNNjpt;_D<5{U*S`!+6z13(F^iOY({zY6> wc!Yd9sKI5|S#*r_flBI4Rb?kiRkR#KQ9ydv`W+i#NM6zNN@o1;2xi(V$+8^!bpQYW diff --git a/assets/data/tool-ui/movie_box_office.dat b/assets/data/tool-ui/movie_box_office.dat index 23c903dbc4aa126481df590842ee46d3948917ed..eecfcdd437dd5bed5f2a66d8459f37a97d934aa8 100644 GIT binary patch delta 1474 zcmV;z1wH!v3d;+S8-FWWvwelXl>w9U$j*^llDj83*LozPKMJ#!u@-hYFKVL-jn zI`_V^>bQQYxDZf_@gd>f7IPN7aPI^T-i~*6|9j2#crZqm)o%C;mCf}3UE%so7l_A< zB(3Y{quyii)vKr-4%6}M!*~gbhCd{#O%x5{)e#y5a%f2z>`egc-qp34I zUZp80RcYqfQGdh7Ht2YwBRGn0M_RrDU|6>rrFy5pH!>R&w#cF6rfjz_!PZ3+uA(U@ z2`;851F+Gr2pj&9iDDfuKjR{$)eM{+btvsRR)+QhYZOFH}P z^sMkvLXfJrqe=Hh4#HRmK>0l=xtY8NP>IW;#bP zI|{CE#i@npr*hFhh>7Asuyo2~q=<}p{190G(NwKZOc^pf|CP==Q)jU7R(}!lROePc z?pReU+aXds%fO{lGIUDevJnGwAZ`IOF4(Gy)FG0Sody&~rR+sj@$XaBqT)SpE*Q>M zM?Otjhkp!Hu(qFt(CP#v6Rw~n<$ZqUT6KY=i_;`C&SL|`l*VlBa{LrT(kGn!RvjjQ z0S>Z`!}A*0C{6C7CaMNH4Q8`3`NB@^W8T2FuXUI4hJeUwU=f*jX7=70g#VvqgPx`_ zh$JN8z(mC4js9IBn;D?PkDg@POumys$r6nabbtPc@vT>>%!+ZW-cc!dk)8iAxfi}C zjtV~Ov~FIiszd0#R96l#IEvth7{QZ@qUE+m7?dlkV;$t9px_n#NzPON4Nzj4&m9|( zH2W4B=jj|JpX^SjhQd3<0vSurgV!LK?QS$!dRXwNaxnE8PTCowOu8$wDpZw{D(9ZC z&wu+!c%#ieh9M*{G+Wgd3Q}xMzOYegsti(Pr)%- zsZS12K37$jTV|1y;XeG%22NJejP*4S4P3dzxo0)|iw4TG90e-G^)Bh!*OF!%@<`z- z!16LuP^N(o_5df@ zw%o$U9BwTs2g-|Ga--tdQttfU{6gCGpy@R?f7&)yI+N*V|LzvlTd$~3BXL`U5|U%H ze?JJs%r$pe!GXPv!!I2_(oRpHB?FHMyZf;%AaE?Q@DKyG|9+9*ZJ@Llsa?80!hd28 z#uPDZk1VVoLrdZXizXYB5$`4jPE$Zu3&o+cTxvfz7HRvTJ_1$@XK8$ev?NxA?`$X)1s>PJbgQ0w<=AwZXnnzYVyGHj`fOgAbw09|HDL=6}nzQO4Iqcw;)*vs!ak0CA0|k%IM7F;o8y1j->n7dbb4FYh_`xfX#XfEjg(qBmSLJzk(ruQEB3=TOASy`0`J=3eokn0PhgE2Ar+<#$R%HcuZ z`oacO_2Fu*gJJ8^Y&4rW-MXxhl6A-gGuOZqzL|@*CkMVCVSQr{B**mx_n95#ieNSGWe@Te6a1Cz^Eb?tSWl99ms4|s|+O-Gb c2q=nb1*B-(!u5Ct6(GuUoeEB5-EM0De_1x)Z2$lO delta 1393 zcmV-%1&;d53;PO?8-ETUNp8eF`0u_u>@y=DOSH%}I+5BazmfHdUF zSQS+-LtS{b?BsCc{H3sKsYHFd)$ElveWxigA#o=I$+-S|>0@{uG$6mS;`6+stcx3? zquZzoF+)%Ksc}ZyKD9|YKru%DkWvjxXto`Tr2^Knp;Z>tQ-4MLdr}`>I~vsI)gW(U zn=h4&c#Cs?E@+8+lr+Qch~^$&OiZsOPPRcEvvfz5yKsV5xRWC58p#QeZWq$2N)8wp zLz#>a>65lrtJmY@U-@6bt*jN%pM~jU0w_~*r9M|+c14Is}r<{}L>-98*3 zTf^^ts4UC^=a>%=`(8x)O1MBy&BiFT_>6LWk_GIA_NDTq>u9;<-%WbE&}=FNBoZ25JKr=CZyN`DXKf$hVl=1JDnPfr%m9;MDL z_|#Dw@RWafL=YP&j`zjL)=CXK%^A0l)LUiL6Sa(ey-2Zpm*QJZY1FDm5y)#WE8ftd z37_geRF_oWH4;W75T%or*D~__%2YiY_3Fb zf1%~P(tNI}7Z#P7IIQy@ouBe_WU~0S#c$S30LM1?8RkBb`v5@s9bb1#tD>}SCkICP z|Abee)+5@v=qAWdFdJ8f&l-TE&`30qL189aXMa~@#0hl6p<%MHSG|hKjvB|lL?JU9 zUXWbN+Qp0)4aQZA3Eqr#a=SDlrNPr=R{p33*+iL z)Pr|NREDQAZ8DS(9pVA7N}Ee;n8p8T`~B(@aq2ul>}Ph#)A{~(h$xB`sMRwkM!GaS zy;rV(2=b3COwwfFfBjm)Q+jkADbFMZ34e*`d}Z2Y;bGm=jSWo&_-!4-tb*4ER6L83 z99mCn6MoIxPG-bQv4GiV1Qg3^5juL88HudqriSynn&h z^})@AIAL@h5Z!Eo({}0+!y6<)del>0lC^>SV4L(5iTWUaX$Wc{{iso)10=8&`)Q2+ zv>IK(>6fB9J5in6n2Nyn1Fv%y;CM?BAS}xs6ifBT>PJm8^0J>P6<>uXz&Cq{JRX+m zz+Wm!B7~nPEe?r@LY;`(fh{-nOn;E$q8IPjc}O&jUZa?TnW(_Qsvi}#j5mQEEMjEpBM2k77Uaov^ejout zVyR=K=pgW`de!UzG0PI&30M<hB+5XB(C?`#2-HDE`QtmvmV~mXqTG7N4nLk^LCia);x( zU-p*gtV5vKIEGoSJHH0P@4wDcEIsj0EhUz6al8Q?T2ch=dNQyGz@q>Bf}N_}Uvac7 diff --git a/assets/data/tool-ui/music.dat b/assets/data/tool-ui/music.dat index fcb9f3598597c37e95aa5b33ec229242a7ffc1d5..083173cbca2fe71b42588525e32ebf8f8b95bb8b 100644 GIT binary patch literal 2288 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 diff --git a/assets/data/tool-ui/nex_ace_optimize.dat b/assets/data/tool-ui/nex_ace_optimize.dat index 7fa7c8bd6c67f432400e57b5177036ac0c5c463f..80d88415a77dcf8a145126b1fe8588917434e774 100644 GIT binary patch delta 1264 zcmVv!ZALV4= z>~Z#|VQ;A)zvJ1`oGCQM5-J)z0A&et-2ao+uZl=Y?8zR%seedK*mN1_E2<0atzr$U zcPEUYC7Rv}6zR$hXwu0Y@&F9y=~%j|O_X|lL9UP?QRIIivV$3Q%kyg?xvQ!|0a_N5 zP0D>sJc&Ryey0=^NHQ*0U?gxy8b}@(3rEKI<$Rbl-^_G*!-!PYZZsOT`qPhi#|~z_ zQ0I(=Lo6*eOn=WNhR^Gv*?Q0;#SEZ**Vdkuk{82l^)p?fQTB(BlJ!)TWiEh9>o3PJ z1@_S^HEV>F?&7;JGyZ0WQ_mSCHJ7bps zjU|bM_5Ni`ikdV5)B-y?(63IJ|8CZ2W!~S)p1fp^FZ$XB@bVp6&hQm^*~3-7_-}t2 zTc6H+pI3%*~$c+of75;;c3MJ0Z7-JiGzqdT6rUcZ&M6S2>c)y-v94SFtwX*F%P zJ743=uA33Aewx-#pTs1+cvRQjp?~vN>F~VaC&MAs8QzG9(o39afB@y&4hS$~QQj>+ zPA!b@7qqidt0jtFZdW)oSlWqT@^nqGy5tileC^V$95%h0K}cM*Xp8bT@m88EOee2g zv42Mck$k*H857{&C^#2j{p|XYZ%T>0YO%A*!eyVgm!{q1E*8g1-l|-;OqH1q%nzt& zaF8^QeZGev$6yy0pA1<>&s87c2x+UglU8)Vt6NiXvOS=+f-n-j8AZR*p3sPj^qKfA zg&J^>zZpIL>dEWYte4HUnx4(V5nb>DSAQ(`1&JNsQjb4mExqiOr}PljnCL2@4k=v! zKwNQ&|K?-W5jBZy4ux{<(G^H^O&cza{A1xArf?1{Es+Grtyg^v7~7yhn&ZnNxYTSU z3vOS#<6Ip_2Lh}kvG8D9-Vg_=2*u#%CyVXfC|)0QIu_NhVw{2G*HId|mFl!ZFMl$~ zsW%A{Qw2fC-{`;prknCeH3oGMWfT1iPqg6+Ym2v!E$RD|Jvh^)WSDKsOizhUB5IlG zS^c15lMkjI<@{qv=oLtQ)Q zS1_-FGgDwlM0CQ~s delta 1264 zcmVJ%g;3)XH|$r#2@p`2B7A!}@v5Bj@qUe!T`_Q1 zWqhASm|_p>dP6m=6(T7hXG3*?&pEsI-G+du_S;?$XOiu!*MD?9-}KPdud^Jc`Q2QE zki(&wE15pO*P&KOuxrJ3-s!>U23!#oj$y=}8JMG~8VOc~HC+U^&LXNk5PzC-uiduYNJS}+Lm;lSWC$sdN=b%X%~jyd2@lD97q?W3X548Q+IqJ% z9jEcRVg*ydX&HZe8}wiFA@UuHmiNgi8Dmay8YA5gWDruzk2Bj77WXzC#{zav~|8$L>qN z3#Ag0+<&)th3|WX*zKEPSOBtDsTpgmGSP8eoq5sH$3kx!M%BqBc-;`)t+@4^nUBv= z|1V^{%H{2!ch-Lo7!qNa=RGK?jrDIswO=>}3Vwb7e_aGc8xzYlf+d4J$O5i*PYGTyX`N$cWVHSk*hgE)tp zZ#s-`5w4!1e$vpRT4No6g%gfJHOc(VqEPtj_9aE##=QbdGT;aYJ9GI9V9Iza=E9z1 zkkQ7&%eC9`c3BA&SU#jbH6boUuHLLBFXPZ&F=3GP`WNG@{8H{Ucs+faE|ylhXr`I= z6Mu8!K%aNjCLaL~$N{o7?5!z{!#QC-4i>4HQEPv3+tpnTg1H21U*<{Jwf1>9aTV91 z`~*<&4=9X`I$rx(0%ns!ZOL3ydyDQnWu~tRUJU?UL#&fn`8s4_ux668Q6GHXZ?6=$ z$SDBrI$r=iq2^5F=9icZm845N41lnn%zt?n<1s(>mUPw+ds{95>D>Di{q$@o>dCAi zDX4Ss)xIF0Birs1i@Lbht6fm~T8(B}lZlRdE75{fQS<%lw2OnV5F1D>&jVf2@fQ~I zBT!rVtd;Swy!q41NZy(J)q2E>yezUAaVTu^Ckh1eW`1V*hb(~MxQE$Up3r^VQGZ-> zO_Z~8(iyvrnmqk6m(AYyL>^m(m~`)w4-WwW32@xX83;U4AI*^AZ*63X(_oNh3d>^g zT**%2%i@P2fGP=Yd8qq<&R-d9dT);TX3)zw{U+o*`^Xy2b_r_hL;C4&u<(CTvw zrdAxi<69-sy)=vs_KUv#UZF$EHfeV>9Y)NcAtN&%Aveb5)o)7>qm){z-_L(F4gvm7 zMqqX;Sb;s>1?TJ|pv;1MrBFlIQJ#%E5jR!S9t^e+ym)=5kR0j|JN;uj3?EYxFo3Jt aq{}{(Fj|3XTL2EJ+SRpOy*$mSz_?5>)NR!O diff --git a/assets/data/tool-ui/nex_audio_eq.dat b/assets/data/tool-ui/nex_audio_eq.dat index aa56ba3edef0142b6c9aa29dcc7458fbbb355df5..902b9ab9bd5ee15ffc8233c8a08a3ecdfd4b0a71 100644 GIT binary patch delta 1248 zcmV<61Rwi{3Wo}iH-C^hNIOAV72)Kt9gqlB-^1>Z)D8=Es6^oSyc4JQr<%}=~jTkO7lFMr?raPzk&J6zs?Z=0mI z12P-HkV`lKlKrj#Se9}`fDUh^jk0)S4r^x0V9grbUE9(;fwjA4gq2edg-O@PrBecJ zJLVWWP^2Zd^ixkr@>O{3Yy&2EN5+GVK97v{(*FGI z{k*KKmNqh8gnyDN1WPN$Il`U0J_zNByM|tScX6IJyy`+mj+CK=nG5c5Agfg#m@Uf! zZJRj2^Fm4s&n(JTg*yT}Ky+*(f!oK$b+vw1#Sg~9+@Po%H!=Y~GRZ0R$2ex+vTslW z+;8cTcw&U;bq4+Z*DWEj2I}8n&@TR$sSrYW^4j7ASbsSA82V7b1%POoh)-B2HJ^AT zq;B{ttR+>)w}SLwO$jU6tjJQcwFcDTyt%DBUm|b9%=7a!fBhDerUP(Djx0pD9}?&r z{E=(oW>=D(54bSh5&rX;b>VPWK6+N zwJ`R6jM>Hlr=xZPV3%+G-6oH6h9Mm~gJp;WPuMNpcyGCd=o-({mN$?vH@$#HFP9sV z;(vvXQ4`|%f{P)&Ut`UdgO>pDk*-T;;@E}|XZCdqK-kZd!2lc6{Aw5Sh&LBwE7W6l zpsGe3iHH6tdTRf>bQru)sfK9=(UZMmTg`?pbRC~UlBdKE(@iN<{?9FT*rrvSvSwG& z4A#OSVps0e7*&L`Jte699gIr2UARY7v44dbeeN06u`c+fUX)T(;*}zc9;{;^QR=q3 zoj-Q^5&>AD_K~eIJ(LjGXV6crqEO_d6it`Mnnj%(>`ngyT?9D}f{BKLVV0NDw`^@% zlnmgGfkSN4Yt-c6#V}-Iq1Yhr8Vx#M>dvCR)L?BJDiOt45i=s(^c1`*G>%416MtNP zc!f63Xkb`pR2<~9z+H#Ch8>9E^r8wa0(vThT2!L^Vn>Gm&v4FJ{(G{xmg zG}Q0m6&xxUsx0sOzdKPTG0*%kXd7~8-HQoi$}F$iD6a9wql}x3G`0GVEk5;Y1|V(^5}@ zm`ikrI68jFR{wxNtc<89_SU2^A!nmX=a6AOHPZ8JbFZHbpD_%t>>OY2s8!>@uyeI7 zx5d|7E~g~b;}w$s;5jQ`S0f}j4l!=N7oI9Bv=eew9T^5&$$y2Yc`>HpHidc5>iFtq z6-xqAJaW_rIy;0I-x?=3J(urO$hGt67*1AhaD(Q4uW$buApPI#+1Mx^>l z`VZJTaVDYjn1_8fWfy=LtCWqkX!U2^DuAkRU={g!evfrkh*4ZPti>?F=in#fn*t0D zrsh?zaV={~=7G8loku~Wp`hebMcW$=FvMD!r8`Wt!f%7e(}Q zg2}q(O@Fsc(z7Dijn}^pC>CVRMlT6{=f%u924+*XFxF~Yv#m#E6;$@bXj=EaFbZFG z^B77uY)w2>e4Jh?!Gy<`0B;!h*5+qZ!P!FKZ%Z?w7&l|-eqX!eT*C|Lfn>X5X24Rd zvqYl@es_?53$!>geO>pq17y zpI38beFt5M*@~?Y+nv%Tv{)Uuy!8MA=Tb_zW~(|6A%V(+Az$u@sYH6z--n~X!3B|KGhN0dk)J>-SuX%WXYY>?8kjN&7`Ws zOV4cQ@QVR&=gD%EU+D(NpbtE7gYl657_pE;hAC+CuVqTJ;&7BH9|O1V9Xt}Nb${`9 zIO6u}Lw@^cq;ECq#TNARh~RXTu5L5xGN(2XX(aud@{`X?TrV#(+vFfYPN)u19&B;~ z@;g}=VqG{|4fWH3>B??9CvwR>o7?D^`hg~8p6zpoS+P<%D|dRJxM$!WfJCUR2Z&Re zeSKnEu*XwNf$Reu;16^@Q$Kt9-&ua0$G|5g&q@aiGk2PeA-qv(+&I0VDXXO6ue>3- zAlvF-4qJF=FyN)gd6%(vV;sxpXYP`# KE<*hCk@%Z>Uu`S^ diff --git a/assets/data/tool-ui/nex_crosshair.dat b/assets/data/tool-ui/nex_crosshair.dat index a5462f12dcc5d6e83af64dddf3dcb0befebe1d90..e1657a2884ea9f473dac72a34e0f8e641f04187e 100644 GIT binary patch delta 1248 zcmV<61Rwi|3Wy4jIDZSDY0ln$E+I*#aU-z+@+V^j%#-3coC1X-(baRx_;kpBrAraiYKh~f zsy`u2ix|zt2UK4SVyKOZ`cGEzSwk`=XLMoB7rMODiFTmre1BFa_2wN!@)6%}HF%6H zGo;^3$*BTIGzhc4OG+Ec%O}JgU5*1L2Vm5YRJ;mFefJ{wU3uCDqzkTK-xhn>tr|rH zQjERHUy_sI6jRordgNO~(-ra_9ph$Sj;pAonLwPQ9}PcsH0v#QPR)*YE_HK9HQTHy z;xT4(5WvrvvwwH=x`u|5FcPs}KFrH#r913PQwVsHJb~L!U!r3TIsbeH&Q2UrPJ+%; z_g=@q+*zHN{0Z(F`#h05c<6O zR^J7KE2%1F0DUkg^NMBq#!C#7e7(+j1fIc2dZydG+jDH&Y#gV0y)|qpb}xo&jfk`s zd28Om9qBHJl0O`(pC_<5=*vVLE=E3b#CI-qcI~2zK>_4i%x{go&|*o^T}G1d`$8rTUHJzUbir_ z$oquBeBvw_2k6lShQ_qi3p}ny6Gw4A6@~BYgd=&V`gOAiE)RHpJ31X z@WQ-1fdK=Ck7Xk#Tz&GwTCR|{czbTGyMOH6{uX8jW-R5*pji!JE{9tyd$3O{uzn^P zt!U$mUY*3O;%4#145AT}D`@-wGJ!qROU;K2!t{z~&0eAO@44^2~>{eiC z&G|u8bB89W*gCV;@{}`uWZ=??n~VB+X3dXn!Yu zt#{mv4G@6MS&qQbTj1K$TniQT6gnLyB95RiCNaZ=^}Ad$xsw7n=nC=HKl=gMk%b?5 zB;n-}YKMo3a+OjOxBx`Q7n~3-XYdp!wofn;BvKsvwL~))7&EW`R30p9>ORT6P7=sa zmFyDGa2uMF*=>&Qv8>gi=G44t*<+Rk_AQC<)>4aDh6cqEmE?c0h-x KgM?3G5fSIa;<97o@LZ(pG=#5 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 ZMbP6{!k!jAuFkZ{zMXb?*z zA2qoS3p#v;Su?rNAsbqstm%fU<26_G7gQd2P@+Bv+C-*zxk`*k3g40%_HRW91#+iC zo}hQs))g)@@?fd?nyM)cDPBle9%nn_>`b#+7%>T>ZTijzuz$*dFm>rFzdPwWlD!AF z2^1WFqDz9{$h+Rid8gRdK94wpqx$cI&|PJjiHsuPFUr8vgA5Gp$>36lu9j3Ny8!V8parXy;N^x-`*pnDQ6?!DTJU zYv*8;4r%4TW`EsMA6xq04)iIommWmhx%4KD3NliBG$1XlQ`pORNJHAzEWeZMIKnE+ zoV0Rq-&|Ow9V=6qKT&uCXx}iRgDw*C^Jc?7;&)emn>;=lcDPa^F-mwUH~aVuXy4!& zm_9rMf<509^`MbZvU6~zz)ZLPyBmvr_&9zEMi*8xbbo09IJPA+%5YCBxoUfB4lQ3$ znq2`f*|mWlyjgy{c^6Skm_dEF21m08%8wJqYZ&V!q8kn0+6U3XGm1G^U za`Z9ZHHoF%9J2!`Ec)3!>n3WGo z>R{CIoqrLYu62l2jV(T62krNnBhVpZ8Buo`J+WZbf|N7JnmqY)26!HW+z=or36&~d zu20h?tMU;xAGFre0oH7yBfe~ywd<2tOEe^$Oy-mz33v-`!&Gl+H>Tu-2S;W}Cacm;Dkah)@X((LIN#!w3li%BeDbEksUxJ zC-?{8wukQr1F2(9Vd*d|b%k0Ej_(QW26_0q13(@FP?S{Bp+I&IqQR7#JoNi6+YVVY z3$s$3qNfJYjk!FhU|E_w`oeRpf0xnHPJarPK)@#R-CM|AxS*wggJ9ALNuvU)fPa_| z_p9i5!WL|GS^)yP0WimcnCTYHIvhBPke%8B7iHTJXxe9a5z^;G`R|;DV7HjBNbxd4 z&^M^eOia}Aq;9L@o3r<#?MxSfSkNh7H8UCF&gK)#0t9FnNb>o@MW_>zy!NeW6G^2& zbgW9h!Stx%+e3HjnMEhgugkXx)oFBa$2fhOX$S*mp>z{Do?hLNkkhh+)VlK>Kba=_B^5o aob5$kUlg3livmF`(prf^xF5lu!AEhzqFZDD delta 1264 zcmVB2rC=P?Li3 zw}Sflb8_ZhA5Gh4F7AQ3J(Ag7gQ~@}(39S#!KF|j$xp&b7k}0i_59*KFrQU-&2%x@ zvWu>d8Vk!R&+_x!vi-rkCoR(+;yl2IO8e9CxnNnt9 z#hD9aYE6bbToNGMTk3I>!?Afehqa=Q@jYiIY}9yLZ%)1xw-s&CV=e6>fI`E}Hj#tQYFTpxX;Z{(q1bQl8s8PPZYn4850!lWUt+nf@I5eN`F1>f9ra4<}^$@{`W?9TY5;e zlg@(k$P0w~6>`3;Ee>!eK|Zh!ndC|NaBWKoN?Psd`13@}5VGo|;=g=q7-J0@(uwgm zr8`xZsJ{6>GN9UJm%sdqZit8cQ4cDv)*9(Av@OTi+4K*HV#KNti?WPZZX^Z=a&&F` zkuH&Icz^$TPIz~y^N&KVL5Yzl@`s&K!bW?-@Rr1$1(FA#A5v*}k*|Xu)-*y0rjPES zv7SDmSg~Q!rLEuJfU(gPH&NDsfHX{%)&|(cP=Fy$vh8r|jzl+@qARr(L8MDa3g(hq zF9zI$eU3F}w!uek$yXX5n*EZLl4u9OxT|?)TmF%haOMRT5;U2^as#yaI zMHY#bvdgfQ0V^o<#fJgb*FZkohj@iF3l(p}6)M)zTN*C(rC^=0OU>Yl`Go?Q?ad<6 z+^qaRN`OQ)g#!~c@Ti_?nRN-&+NT+7=As;{xy*>LDq7El7v0Y>pN!rdBVJ>s(NUBc zIDd*y53{C>Sg9+q6um_(xV@kZsA4<420~%4WM<1d_&!@M+Fpx1E2yf&c1TE!_~y z)c34A)_~Iaa5#segvC+ObLee5mT5U}FQt8kSd}&VtSpEcQlRM3hVfAgqP|OfSpW#Sv`o065%B;T!a%e|pR|IiG;qwSP_E aEMw1-pZg9eA(!AUk=LBUKUcmX+yKPS-*zGZ diff --git a/assets/data/tool-ui/nex_display_filter.dat b/assets/data/tool-ui/nex_display_filter.dat index 0de213e386043472ad9e38b469d846a322fb6de0..205a95feb20b51065360fa57f76d87ba52dc0c03 100644 GIT binary patch delta 1264 zcmV`Ja+$`(AyT0;fx* zs|yFLo<5*?pn5V%&~B52#0)35SIDl}QxNN5=)BJVbR_cqM5BHp*p_?EUnP4dj`1#D5}VC7k@{GE8KjE_-6Y zAoav>=0uBbBPdS0Ft6`%hr)X)WXApx+F=mHxdpH#AtaZMP?T+;%3=araDii4B!tw? zKPddX)ZsUh6DIaDC_EDtGWnS;_BRAu#^;;(HPRBMb`IHE7@!-3FI>Tv@cF<#`A6fJ z4G=`rZ@}6#n}1UjaqWh8>34>-s&+Phx*yAY0)y_J^oc08RO1CNmVC0{cbRPH;2qZjd|wdP{f$_>%0AGD>%EpHioo^I`Q5mR#hszK>;iT~t~+OJFI`j<~)) z-Zvx^@^z`{R9MsT?jD`X^1+&90cQtBf4ttw-7yiywz529GaweweF3O- z9u35by85$uWZnyqkGv)ojcosig+a5HS_u?VcYkK25V%Ptf2X1Z=1~>yl%N;Hsd_6h$uJ_mSvfF7(P9*5 z7Q|AW+TARa&SK!04q``XjF2Um7`TLeSe)~WANW!ObZ9x@lsB@n`Yq~(!^4;{-qZ*Y zn5uAm@)+fepkNk3Fv;mDEug;q1Vh<*Tz`N#%dG$|>GA|AwQ~=k)1b_SQZ`P4IByKu z0WN&`n1AM#eMok@(X%%)Ags!4%FkhY^6-2fq78(Zl|GQd#rnW;bjARE3qq%p{@X0< z=jOrfwE%V25j_{5bdjY5 zXD|PA70P%X-vHdzd_=AIFy_<88)?8IJ(rRLgvSTy{)iZR*bVp!XkABRpdYSEpEKDe z!`E9fSI!3w!dat-d*P_G2U{!ICHb;n>u@W7WN~_!4wt@&6R@q1bwbmIQ&~t&4IOHj aSxWHSc(Yr*#b<7YW4c*UL;wX~O@!r-S$ksu delta 1264 zcmV|7vS90Ut~4pa%K04=Yo67?Q+obGvkbmYcn}`> zMBh=CkrlW7rp0Moa)tcIY_8j%V>-ja21-Tro53}S+T>IidO zDI5M^h*xiZd8b-H%RF~GwW?`s(1E6=`U(;&ej#dNSa|&G~6#OiwaI{b7 zJAWMOrY8mYSD*G_qGiIKYqtjHZ|!Y71~0d9a|qY#V^t1ip8@n=FQkZi{Si~RuunPC z4bOQNMUb;_^ph*s%e3!s@MaOPl@4F2hvm0QgIyt7J`! zln^LCweaIzGEpP-I>v75EW8P*rD>1BH{k+54@ioiOfh>W27}l&M>tyf+PvQYFj@QQ zCNcPI@d1KS&^4?Xb0O7UCC=p(mrDoyQDcDO`3Aq^07``v0zoEe5*bxE!#otRC7iE diff --git a/assets/data/tool-ui/nex_epic_free.dat b/assets/data/tool-ui/nex_epic_free.dat index 9a2d28cd1d1f0655de3887a240dd24899f3cc4bb..93d00a92a746546bbec70a2f6fdb31a00a95ed0a 100644 GIT binary patch delta 1248 zcmV<61Rwi|3Wy4jIDfG|vI>o~3~D7%DeX4ptpIiw#egb4j^ICTW7J!pW%+Zcft#Wd>?WR3JMaD3#_E^ra)^qabrv#{JQStB zYH)+UB!67E#R|*Mduuhf3YZpQ{`%eyPTS2C&(@-5hSS{VF`({Yh`JV%m-biuy#`Gj zT5tI;2;A07gQiC;$-FCP2cI{wnEewC;RSk$Qvv$sXD^yH9%XT$IWcqObxKYiQ-hz3 z>UHSteC@T@?j$8F!m^X?o)QYdX=Ug9M#zUFr+-+@Oa2Qvdsn5SWj#Zr2amVsl^}?l z=|oEIFqdBoNUW`G^z z&@`d2M9Mp5VFlx4jo%~Fjo|3dg|*2rIYH?R1iedM#bX&}$S3X%&yTMb(K2*5RByd`i_azBt`^@<5Rm43J(Ycqx|E`z@+Fj?pk>rRU*c9Urv# z)W2nrB7g6&Qy?DyCqU`WSdeQ0M(Tlq=$CdTu;$9AM!ALu;oFSzK=WuTA0RG!^*Z;}M6`YW4YHO&7>k{(DG{Qygy%i!xI501WOvkMeN; zgaxbClUq*S0wFGkByO`M7TC5pNB{f@`H;d&zcmmOlv!(~$_7IDt`*nBXrro0e0X>R7r delta 1248 zcmV<61Rwi|3Wy4jIDfW0cK|IzMM4nJ=tH61M8)|O+I>$LKA3Bvp8Iz4FBFH{opv>y zmeJgajU{p!eNf)K!n#208_2->iINodTg3*-gGT-58uR;o(md^6z+=c{&`fV3%iZ+Q zLJ^@N7R4_%T(fbSty@6IxDM7Mh|(|!bAKX)Je;{ysV*;0@!4RF z{_x9VpUh(x(bi!eCp!C*#;cC?QO-`N3uVdx$n$xCjSXoljnwPqr~?%-wu|V0z_WVV z;cWtmytdk}e(@!ZF;ZorrW59)ykW1Cszfui1@lN69x~&11%4HbbIR7uO3<=vP?52P z(j9}*&QueZXMYD(+4v!WXjQ43m3AM8{hFu`fMk1r{t0_KLbnLJteoG{@N)B3YHm+; z;s^@@2u^=o`9Blnm|%0TfctbZ+gXCgmh5rx#40Vv2psaf)W~;_2*2>Z5a3h&N7mCp%%Xi5s0zG-h+ab5d z6S)D&^Bxc1G^$n&X2cenI3H{mq{utB(Zn7tCOm=}P_l@5I~Yv|g>i8Bp+LmnC5`~T zGd(3JTYr@ck+MJO;qC+7VU>V0nFdmzLHnU|N;^$npLKL>Bf>QHK{bE_j7eM30ajOnMVq$+L7cx=C z{p|*kf9|}gdiwwCm)rHP#uUoZi7u)u91dj~kt`8bR(^3R8_p+FN$GQc z1vhrd)mMcO8n=scd~rt`)MRL>PfQNovQ`4c9H{QbBY+?vC_q{x(9XZPTKEhz1;QrJ z6g-+YRS++hu8|A3rJra#qhE4b9@id&D}S7Xq4Yn829L?gLlx=dBLraQgAmG3xI75+ z7=246^4cVjVB7zAy7nX_V34fs4k{G+A5_6f>H6UP%60B4w&g={Nw!9tQUpDk(~`smrSg4i?K< zC!oQY-1VZI6+sYaxB7#ns)-?Abo*=wbX`r7S)<(0F?f8On2BARCmC46KA(WRDez-E KB^;6xm7up;c4jO9 diff --git a/assets/data/tool-ui/nex_event_log_diagnostics.dat b/assets/data/tool-ui/nex_event_log_diagnostics.dat index 302ff2d6c4cb7039f943abd08b5db671f175f77c..d63eac0989acb8eb1cce0fbd37855de285e17d05 100644 GIT binary patch delta 1280 zcmV+b1^@cA3bYE4M1L}dhC(4>4w%LHeIfd$i2&1MVCI5zJuAGRRaNskS;7w$H}UVW z>JnR3pC@y z0}*&1uL>>~*U^i_#}q934K&Tvnj5u~^On1Wdqtvu>1%{7_8Zlrf5dTftlmE-e9gO- zUQq?dTN_3eWjzZRv5?$Kw?hAJkJFrveJ#9Z(w$Tyt`@KL+yYO~zRU07HdogelUK^c z=^jC^RZ7;@4^QB&+x)R zWx`XP!%vWHwrb2VX8wE>js-e?U1Xy{Np=Pna1)qQcL&lQMq@)q0yb7#{5xC0;?bB2 zV&G($QSf+b>F0b6=8FZy^j1BKmnj#IkrbZxYCqkxJX4CJYo&_wX@C3#buAhgc`Vb6Xw-VfkF5ae;F7lr2SahGIa8)z)hMy|^ zhdaQQDp4Ueci`nJud3OpL>?8>x6Kk>pg8Yr3+Y?l#38X45?U4J$DVGvoAI3x6m18Gp#362_!k#MGz>1 z|4S4BY!`S%5Zr+p_An;gE_$$*w7NIMi*3lnysagR3-lQNL6L>%9LT4co6djnpQ_`ivEk;EFCVhqee>aRVhg1c}wy!uO#_w8#@! zwDdEjnu(I~s5520Q|9vHwqyAYWW26K*uSias0rFG#gx(SE{pW=ypNa_Z#s3!$1LVt5lE*OF)kuqA}s=;6~qeRj$GdW delta 1280 zcmV+b1^@cA3bYE4M1SY7%OK#L4wEUGB44VPYC}I|Hu9Xxpr@=GYvzzBV(8(7p~-_$ z4^9aOsblz3E03QC0YVms;6~!m(D=z0xs)*`^g_z*zF;}jAQjNS?{^J+P!3`fyODzg z_!wd)uYI^mR^h}!r4M(!iXfO=ad>e}*X#3}*aesY9{wu2BJSFzMn2?)D zO=g1*4w=bAzO^KI7R3GEFt!3I9|cK<{hL3_JcwwvX+(>n8VTO@4gPd5DBzZITvt|T%@o=ws`Q>F%z+H{UL%uP>22ml zF`nPQVwI&lYB*<~IB_b=)>vFWfPl@7^P<>gSu1NYx-|4~J!h7udDZ4N`wkxyDgRxT zHfUuuXf=9HY+-K<8b@R&)d=x<{IE24wfyddf;-visei#JAIGDUFWVB-Be{Je7XPp& z@er{w3rdqK`TTwdPjHDS@HZceX1U=R+hR?IR#5-ayhk3l}WXkKSzS&edH>jJ=vsXN8t;2C)|D?^riel4k z;bdOf`F{x4GTLGzt+nlhtrr_gfKxlq&m@7(jK!b?XvC!5KxOJsH9wkhCX zIC#S`NPz0Hl5aCzRnpbtm4G~BBkyj@i!T3dokH_$mH!Z|`Hur&z8-Jwqcl}vN8qo? z{Myk40LFsVB)vxaKKoG_;qi8HbV}8FXz67Y^?z)9&g8@2T2-j-n7g1zu;Wt!%)upl z=Q4Qk3$%kfCb5nAYrc*d6{!C@^4b($C?n#3?~$c9H6~$8-e{>(z^+C$?8L^poJ$ki zZA6rpQ6(M}YU}q<(r&BQ<@Q6R^e;u+>G-_wEFd~j-7#Rl4q0RibP(9t zDQzc7Na;q|H8;oKy{+_7=QsubUk)eDRDa1-GU?!+MNm*ses{P$R;h$$9H)vzkTyF^ zoKOtI;tH-k?SY(BF0gkJ@13nvO|{DJ6q8HiRVQm^7qCxd#nTR2Js%YeQ{KOtSS+)t zg1YNtp>{&GvxwxRq_F8I*qK&+7SBLte9qZlaJaCr^tdm=O#=BJ@(38l>tst?L4VB` zyUaTm$%VyzN(*V5hrG~EI;K;%u-lZS<_BXzq93Wq2qy&T6t%Y;ze6NCeC9V^sgb)1 zj;q-~Uk44T^fA+1QCb_wS21xs5pd$j36{M7m@nUdkSO9R*S+=xHUjqI+;Sb-!$cMv z;ompybuu;6Iz^@$z5#C~qE%fBC3)bgd4oB(a{H@-NJ)9IjdZ?en8wSAY;lBbBaxCg z4Qz@i@d7U>A(?nn0of+&;MWRsJJ;S4ZKZw??U>lLHGo6VN4K6EY0AqOB_WcYR^b|| qjrg`v%vhKFSz4}u2%v+IGpV*ge^5pC#aPoUYA0c2KUiDUKxFGH+I$@V diff --git a/assets/data/tool-ui/nex_file_lock_analysis.dat b/assets/data/tool-ui/nex_file_lock_analysis.dat index ba2e80481ccb93e0a27dcf536ab5e53eb6c7f60c..475d9c98e23e67b98e39cb847fa185eeaf421e0a 100644 GIT binary patch delta 1280 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 az!vgIiuT5Km$qENhX(VThr632RQJ?YUV@YW delta 1264 zcmVUB4hz? z2AZjMb77gEiPufhMP6}>ntm|cVP~+E+hD2St%a&S$Mlc}yMJiF_?dkZ3^Uq(egS}V zpkBkqtl?TMRlB7JBX$@ae*kUsz6lLZBKJq|!)eG>vJd^FLuVv~E~`l5H=GIGJr2>q zgu`NlTHP}fCP+MariX@uy(x8cjP{;uJ*{Y+0SmxDX6#T5Powsj{Ah=X)oyjR^s@cd z3|iP_8Orjt!+&Z^7eIvpRKOp13}}}U>w$Se150=cJSt4k_||_n3B0la9bTlgC?44_ zwYvLPe2-iGDBEAACh8anSf?EAsY!d59XDheb>e3x0O$^u(PDS$`qaQjm@hPhdtWoYR{p8z@Evs(;}WyR{OS?AAi@y=MhPw7Y#d@MibFmxl-; zbnv~VSuV~@4h0KWztJkLu{4!)e@AP?gVxpQqgME*ldb$qZ#JGsI@%;)E%?JS6d;tA zpC$n=sei=(09Z?H)4uyX+~3emOj27^pd8v7TbZwSa~5ZX zwnXo2ovyMJU{HaTdD2?N(4lH=Lj<49gXFz53$alT$&_Q%SuJwhq6IhkV?rh+N)Psw zXJy#>%HfwZxCtpQFvYg1~c#t1wvC- zzM~0BX208I8!8wE$6RWnHIlBwX_wYnRot6(aB^5qs{Wij237!l6?uwYj4D4{?EMGk z@W@YQ8DVM3`RN4%+JZ0T8n<=Q&?D}Vifr^BJ&RITgS~+N6 zKR~W*9OM36%}~05o%n4O)f+BI1eVnufq(EAfL=J5?kpUqAUFnbdL+qoA=2l@wn_}k z039{3l28la0H5xYL`%<2S!b3Pm9Z)gWPP&5RH#W!!+*FqK8m*TeUR`bN`Plx&6?(P z@!G!i4$qBDPJ0#tzCNB_f=@a-W6XMb*) zM3d`4SA>;qf=Y?sIjPfWdBx7)5+zj}cK1E?$Wgq5Z$>beWJ)PwpoH}pg-j7HvmfRM z&2Ql|(7$u^5Bupt{z1TK5E>zXQxCvmM3WutpUgadX$f#dzn~Dpq=+v?W_jLpn49d! zDhFkVHk+ttEylJ@PYy}n1MaIaI%!RPQ0Wc)BGDz;H)|QKN3GiAPs!;hy||`*8e_J!^8v}DU1ibn?ivp5l-Ze{{ a`R1WvCq_jhL@zj;=iaN0$k;5Qu6d0-O& diff --git a/assets/data/tool-ui/nex_memory_cleanup.dat b/assets/data/tool-ui/nex_memory_cleanup.dat index af9b93a243062fd9b87db425c45abce3e3e199db..ccaf796fb80bb9ca1103b254efabfc7591c4fd9d 100644 GIT binary patch delta 1264 zcmVbtNem$JEXZ_=-DW z7?$Hbn2fMAO^8@7lWHDEG85T(omzJQu#bRMRnzsl5YE>joeV}rykU~6sz&DyVT6o2)%huc<)Erss_Vh@-l zpvh>8>smWOAO3DaL?$o^AAREv7ukUC=ISvSAl;X7RBV?NFIobBP64||L`e8<`0s6o ztOrt6vi$7qyyae@0s24@6)PG?WWuVVS9p4>k~vC;qZW^_2qJ$TR+dccp7T|X$CU-L zM$k3Tyy!|P&VOJYV_x3t4MGT11T^yKPrOmWb%8%n3WF1QPVo+-H^@}^w%_ya)zZK} zs7V--Kv8Pzz@5LZK45O`gl`wZjU!&*p?0{u-v&@klEdw!vqZega;q)}w`By;Vk_S& z7}F>I^W8#~88-A3+g~>40HR{NORxs8Zs09|HB&_|cYlT!hL0R(p(1t8i~y0RfJc4O zfS~^uR}}NSF}>FpuGH7aCGYDENpRq;(gfLXBaB<petA#o$)t=#siX-vqk{Qq1aFrj2fe{eCVB=0icXJ&8*yL{TST4>mv7Pw z_Sn#WBJ{lXL&KHfZ%Wz|BrhhDfyI$lFipf*P(wXvV{gD!3;smN-G|!oPm@yi) zD)(+gqdPD>$E@#fPb5vJ*AU1Lf648asPaJ;@&Luo-D@~ol zB4Yq%B)^Y=W+KB!@_zXE*CessA)DA8qH0(8&NTQit&@(h(8$^4XdBv#!d=#LuzyNd9iR!kjOwjZ)wbHrp$2uIIhqD$R3pG716l@C%~f#ELVut={l}!{9SLe z3cxt}=$tJlS#y1#DfCiL)xDKnZP>sFM7N%pCcfI*RueOCwnYjUPqo?*nQ2WD abi}J$U@ho;*(V--b;6)0O;H-|X6+K-7c87m&Wgc4-xw% z#=tuURh33eXdfdmE2~S7)fU>VLaz+UD>3@Z6CS%~lAn ztwZRmwn-3+LG`fvtj;ebM#0kqD$nHUMu^3V-sJp7%W6FxTIb!gUm*oWe*GGPlfJ>E z&~Z8aIK}3{sYF-P0>H*5*{*y{=VmSu{3w6)b8hGR3pyq2L}`MOZDXYQzY4mBOa zS%2gHO5BsjfimjiX4K{2!c4%W{!rlU+7OOgIz2S=I< z@6S9aHarn+F%rAYhJ~{IhJSq1`=&A7CB?J0# zGWDsa3h{vpj(^SMnI0>nz5v&PWGk` zX*hg`BNx&x5tUB)h&~uw(FfwqugcLYDWAM@-+WA(H;-L!Fg^iFD~sc4eq^;aWv{c1#nf%lKdUpgjbGHJP1C zL4W2iVWKy>Ky}vLk+RsyNpv)zm(b8xFTKyXl`@XJ>LnN3S|14e{~Kz@5yp8Zgi;HC7(ZYo`pYXEbXsz9;u}@33x>KsQz0QFdnI4Vu zKlc4nzle5s8v4*&rv_<0U2{nswb|ga4ddS)4r-gV5f!MoGazO(C)tiPE-}m=^_Ei` z&z!wdX=2aIGXQ%JLqMpeD=%ct^l9pbz|#Dg0K>Hi3V6#OoFxryjUr1|5nI6KbM?|? zM*#^Rq~(0bR=+|SbxAz#4k|)=>Cm+uXkNF%!l7TDUCz_>%3PED!r?~Z#17=~gk$Nn a3i3NjYRI*g%sI^HZ9{@0`+d&3sYI3jK8v~l diff --git a/assets/data/tool-ui/nex_memory_limit.dat b/assets/data/tool-ui/nex_memory_limit.dat index d5aac548e3d6374ca985e4345f797de55e88931b..5812fd055257c8ac8c582366635fb84b3ea377db 100644 GIT binary patch delta 1264 zcmVzI_-q&TBXNn?o6`WY7p|3&~Icnhe9(fxc z85^Jy{%GOqC%6z^6)So$v%Z6uZN$nyIa_Trlcd3(<#l$s9JVPFYD40>= zslBAm_6;)Q3Uca)t5hl&T*&}`9kng>3oR{mAC8QFZ0W|QE+Gu%s^3!fN#`yCWU%Jh;GrqtA zC<1djRe?cl$F1MZa+^`-xPN$3p^WnHdRv^eV*p*EkEV3fP|NzDu$+^_CdP31GXPAE zc7IN!Y1l9uTK^WguI!`se$QF?)giC@&L zEW~$rB>T>9WJyIej@1%2v2$F|sPqLng{` zCW28^X`~P6v`Ql~Fx}pI_NFtFjs-S?8s8coN1h0#`DprRuj9J0g$C+jqOH`+qvxpD z7=NyZF%u!rDX_zG^H;zwAd@{s<< zA4t3k+|amT65Ls2RaV)2hb1%i{oaSl`y$BDd4^3F*oJ}YKQzj?^R)A2<-O&0XKZVo z?${k5%G7(~J+<}nBIjuBgyq_4LUh>soPXUBp)RV` z_Wq8NjJj}vz<@owWjvu-nUYhdZne*G+h!pB2jk*-uNt{1JmrN1@wyiJF3_k@+<%8j z?3UJgh=LSPw8x<`y+jwZDiJTIP5uh-V#+hI%Z2&Aw0w}<0yIl&&!ZO(Ai-BXWeer|a2yX16bdZ&U{$WJq9*W;ZiH@`QuX%foY?#p0{xHHsD*cwo^nzzDeN{IA^k%wYHZY`Os!B z7Iv(zi_**)DbEbF|MNn1%x3Q!GYXSz-c78`O$B(z-&b^h1@cyqNV28I57&zpmQf(3 a?eM1vK}(Naj-Bbwf}r`fhlDXAOV~`)X@1-Q delta 1264 zcmVL<=mBLr%ODZ#{I5AMR4DR**!V~rk5ewu%kJc3$RDqyc z=@LSlHi%@KY5sei#|pRNaWA51(&KA<`_sq3J_Z)^p>4m$r@LQ8om>#qD18?nLRucV z19{;EL}9oKJe3Zt-Z8y`9f%HvCU$Q(nb=`Wo5F&(S!d3qS$|d>9jPg&uoy0hMhq@r zd1|?EfaK6vAF81GnCI3jvAFe>R79t3%GibsLLv0CPlx)0k8)le!@B}z6nHPD%cfvI z3ar5W(x|&q3m08Oz(abI*TX~KmXQ4l2iNzoD;?ROX*a)(MI`kN3s8>Ze5 z_yw<*IFH!xQGaZKfFP&B>&vFe%;?pLRuseEo7=bGR@}CzvwqGZcS)OI?2-=nAgYD>!a)in`8Qe!8c&i|%yk{N*t0{d zM+$jhXF+QRvTg zggMgerym*4oEW+VcXPkxC!Suo#NNW*^cbX8_O~*?sfh#Nh}5j34Pq(j+G;uj@L$IE ze6kP?(IG=xkwL_#Y9PcXMBgT+@t&S1EBrN!{<;IYyFrrSg)&@YFC|m* zuDM-l@lhfH)_CcWc>9j11A!3Sw&C}GNQclqG3YqEV(M)EjDpp)y8P!=lSI@;;SA50 zsQs;p*sfv#yLS6B+2xc@E8Nko?mbW^I(2Of6@SUH7$C=0IQPid4nNgU2$rJWCw~G2 z>B1Wf@W2}o=W@zIu&;Fs?q6U&BBUh~6F&oU#VV4MJ!BEU0w?*h=U!v^*iKxfVv(mQ zd%GgC5{_S`Q62iTcvYQ>4z@dJcSe|zoyM=$nD*jQKT*!pvY$$SzyT?>Vc~iu_~N#)>Jz3zt@i07f_(k1Wq>MW7P8&r>y=pr$c`%Dciv8-F`c z(oNkIng$T08pdHEpMf?TY3LNMDg7rR|7fU@fXDI2pNMrv)PA7}UdqQM`dlZ%d7w=Z zhl&+hWgfFyw5^ zqysk5jieH9x9o#MERw>Sao`U$7-?p=NJHbdyGl9x*aEF!`JIR1w(O}Qk4GoCTdE7Kh8HSL1coQqgpafW7=+IxDB0H2^7M@Dr^Awa?eo6evB$z+H2jMVc aCW>%KY`v;d1NhU|b&uY}CZ#5b91TXvZ3G)e%Gk+5EZt-L*^AIkpt*xw_@?ST)D~zcs_{J3S6~-^1@eT&&nE362 zXqbeHlD4ZI)$I(X}%M|9)7J1s$ltf_EP_4X1+NFUGR=$$qn*` zACKSku@*Uz3Wf7_A_w^*khjz>0G@I8x;4B8D)+7FBg2dA&VMb5Ch(KDB3$P9*cW#g zyX4YrV3gh#82qu~g#WD*Osl_HmA=V}+l=`#_mh%PoKgPypL;_M~EhX8~HKXaDp zb{f(pD$Bq5FMp#IcP&zoUcn;-FmHqjhRE5YYGXKx=Qqdv@8h-8CW~xnVID*S@M7o< z6(7g(M>}!q`Gp-<{RS~eeu}@X*(ZttQv*DFqBcsNm?qr2uVG0V=j8-Srz@bbu7~vn zR>O&zAlm5>LC1%io;m_u{|B3;?18VClk+Yv<4|;vT7MzY2++E?Ba7aP;XIU|XxRv4 z7&RZb%B5`7)1RU{>m}PCWmt>zH%!+%>6l;MT~LfWq!pP)DtLl3^rMQf>>gq$h-#pgCqqzev%%8HH`Vb9jF(Y9~va zF*2Kd8h>Inm1)?cqx*rSUPIj5T%FB(>+1!E_i?KIV~*%_TM;EljH2y4lYcDiIPQ;I zqVG%7ZSUmm{bJVRU90{uZfv4_rmm{}k@IGpR+7pIi|Auw#JGPYl)C#^AZWIc5D*_q1@mdv*QN=XYZ`|MX7gdf?X>oS&mV5qufsDT6 zJAb{t2#Q7uW5qNHO0H8(|7gdX#+|b@e5UD#TwgLY?owB$PqzGRAiQs7Y66x%J}`lLrW!q=f)_Ufl>^^qWZ=%@DM9YqZ=)C zL%--I-xehMalO#9BC@83NLCl9fZ)Ysixk}8e2B&1W!^3fC?=K2S~UPOUGwKjzV2|` z13ig1SS4x<*R1;yd@)$A1Z2;IVf_ew&Rvvsez$_%vtF8|n3sa>l5fKFtJS?YL4P74 zXVr0-xqoktJWe9?PCcY$LxPErCegL$7U-^Dx21gcd#lq8J86gy9z8k+bkZ(q-Zl#Wl2@HLv1Y3REp`@(OzQbAT zxX60jrC)B$;Dzm?0@xKrD~zqRD@nvwu_Tr4-9Hn`lgNS--yeOT=jrX09Hh=PYz+74 u%hr;f5YIB@0sAhVxuO66`Hy!y!4+bD?B^Vus}>ocGS~GPCgmR&D`9#C>21yc delta 1232 zcmV;>1TXvZ3G)e%Gk>Q9A@XmO)gsnKcz*y6q{$RD`@FBu1yq9+FUhdh1K_bq9O}n> znG`g>&Df-Y9@8p4luO)A>QVUyJaWMui`Gj|%Iz+bED=X++2yxFd%##LUV{Dh_MSht z!gQewu>r+Q;R*xB@AE&vOVn9J3HxEBrbO^+!(iiT6{m?X;Bqy`!i*PrICBseRzBn~+6@JJPGAnZ-)daLH zEV2Yn>$!0d=qjNGVdh_W3=|GUd=fl0^nUHjvb}b=scqXiv zF)37=Nl@Q9fYZ*#;{0BfBXLv1+_r7Er4r?{g8FHY;KctzVJgG=s5mb59UOlHEE6Xv zHO}(A^R~>Wt}7$W$S?R-WWABmgA=~u$OxGXIe)ggQ*R*Z?8k6&ar8N>>ws z$3gRnW3YT;)trOvc$DRSe68Yx9f`ZiBxLSX^D5g1-f}~I5ldp}Ma1?;VIz7N#-ToB zdau$>NEEo2pL(!cm6#zvRxWxsLad2a@B)6PJN^w{MF7Wat0rBqZTUaim&O`4Q{EW#3Yzy_Z z4tI9n{KQb~_^XKugKQWg_#20Z?SXifmVbt<`kU2$yb#$?7SI|ozqK)JnHX#d&(H$$ z&G~N1^|dZlXn~!mC8^r~6-|gd8cx9N#~Si5zD8_5kJG5Kg@-$2DTfm=YPn#X8$E9E zndvvaGOLS2mcSN#lMRq?wv=ie{x~85wkAKJD zC_l~R6u}HsTAXJeGEID=83gD8(H_QmIqf_Mtn!!mP(3;`8qeUgSKM=}9ms2!PWktr z*1d^AosWykZTobr`?-^<7Ui&)+xO2@LWZQ4`|mdtOT{D_*SAw*u$#4li^Up2!{H978-YIEEG diff --git a/assets/data/tool-ui/nex_network_optimizer.dat b/assets/data/tool-ui/nex_network_optimizer.dat index 2c3a1baa8ff1086df54382ff3bc0f7397436c782..727ddb0b68a53637f8dc06d70952a3ab5fc00476 100644 GIT binary patch delta 1280 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 aSPR$pA1l;gZ`+bzPH*Xxq}* zF(lm^afiZ3kR_ppR(UfNE&ELRR-5m44>?c^Ad)KG(ti=XXNqt=P}m6?7u)v# zi0FcuTd0NSDhkwU%*I*CmeIR~{$tGRj?>qg$%XnD@Rsa80Ge4mtWB_-N8h3Vbs*yN zxhJn}UpY|Sj#+bz>rQ3gOhAdWnz)gEdeODT0rIbkzY<-%=cy;|RuUzE{2Leiu&J!? z;npvaqHCEX=zkA3;|)7XmhT4^!Wn!&yOYrv$0s;xOc8B4AD0}LnN(Fv{q=zlx*t)T zlD>mxbEf1&7UqqZD&{5&q^llJw9`4sT?SB%rK<|e4q;CW%Kk6iHad)mTOI`afLVQ8 z`vvt`aiXqyQDu(|P(($uT_7+*gOL`ubb!&l9m0Gket+wVG_TkC%*tP>sGnNeFG|M^5eQ_vUFV&s@BtY93G<d0t6N%C$D(VWTLcCC$B@T`oCK_n$mnam8eg=bIUL17Bh6jzk51*GEwka14mJH&%Mi2>9iMOzsfVT@LV9!e1{Nne zZ?wBp$@KlIs>!J+DCPOz_Hhb5oS9%aQP~ut*82tu$xrpgo<}t=CFrl{j+066P=9QQ zN94E%O~fMtHqEhSlhCAP8LW|2H_D77q2hj<=l<1FVb#&2W>gSprVOw~7RoU0NJ}=r8}g a$u)~>(+R_qn2wh-_b_GMQY<7KUu#G<8*1JF diff --git a/assets/data/tool-ui/nex_optional_features.dat b/assets/data/tool-ui/nex_optional_features.dat index 7757b17ee84806d3f4be9c3b5cacad1725d05bd9..f2d5e74231db34fb597e2d612918e2a4e15a7240 100644 GIT binary patch delta 1280 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 avjtc-Z)4b6Lh~2<=2heEK%6JaSAspPT4`ti delta 1264 zcmVq$Q;IP1VLLFnL}utdQ5q5Ay9ztp>1=g%d1a`UotJQM)DOIoy~+Iv^uAJ1FUy| zOAL|o=G7s5ETd3Us2HYm20gE3gp|oESr-kbJ~TMGP8S0dL4TOFtmx`3i*thr{-o~h zK4c6UZ*Llt9_KogO|v86mb@s|#J%U566C;_XwC-%%}e(OurH>Akx}<$b4?D?lZN$- z!V4*XWuX1b53O`L^1oO{&clu~U>~T}r(=c5j|9VM)iY%!0;}{413rZ0)(qDC%cu48 zjkphgjAlG;ihoVjGWGGM*}wr~*81+U%}w&HAXIu|-zi}mQ>-_dq`QT;pM3AUBaIxn zB3J5dz1(PfV{mTT8x;S14AxcTTjf`dQYlAw* zY5IZ{o>TtB!wLNBmPbi;DAL!_mTovDN#1keLZ(+XTYq@naPv|;HXOn_i=oM`NryBZEek zY~g%#;;FQS$_L0T#YG|#(n`l~zmba2Pj;JR_8H~s|F#URt`D|f)o_}Py^6Zs&@zYi z%XG}9{cazxxQsaBBK1^@V|ikRd^9TbReCjqKPdK0d)IG2<_D&w#G@Y z`hQO`TXf-`6$E^k$M(`}ymn*4bz@5L-NP=QA&~Vu#i0BYS!rm5y^FMn<%`f@%Kgo z4vy1*OAej(FXB*O6^$GH;lyx0EuI$N37QB#edko8X;*341)gwyrEfZanS0rU)e&trPEc92Q*X-gB-EEi_ciYb`Dn{0! znQT;E4D0Y;S?zr6zMC-wmBLTcIB<(Bs6LPF%UPp-db9n=oQ5bRzIN5w3$U^GawHLN axM091L1&h$7%|J_++uJb&5mUl*Y6?W@6#m7~ME zjvMObj`4k26E|0ecz@jt?-HhA9HsN>PHV2hxv@1tdVukRlRj7oRCpWDbDlBeHJ_>v z&e$%np$*7@VPNgPydCIISBSFVAwopWwM-qaEeJ^x&Z)Ggf>K;A!iBP1i8yYF&O|w3 z$H+9H8&08sH-A&hc-~rdEls-2S7R0-k%0T(!Fve@dpEJ8nRW*bTTz4(OjZ+sHmAq# zD>=*Su=5-yOLMKrVmJ8Zj8E?IwV#&qchX4dEgshJ4}X}sqNUPd+{##yKyTFuY|AH; zn1{5PBLV4FgSimdLp@D0308>2r*-A z1i#lCUVnj{L|4)(-3JY=KU2>mguK9ph3#0AEwfTBPLKC+VGsn+P8uH07M&(=gG%&; zT?23#L0q9tM+M@f@@eIbU@>z?joaA~Wq!_~C5H5u-g<6lscSMWg1RAYHpdzbe0r zII$v>qv_PDf@6=|l3zf(nWar;@@>960JYUiPImxm` z+v>q7S0J;F%nBvZh_olhysWC%Ql!9%B{C>aPl^!r;UD*f1Sb8??8H0DxDJ1Y365bo zehdgQSx`9F_}$4lIvefUryKD%$tlY8-f`9|E*j65+Q1{s!4J?qfXB=Ik9WgQseins zwD3DSJ;^k$G-x$Sm^*Bq2^f5C5!UM&3>evr&BgQP+wM-ylqE+?%lJHBUTn_;n(TTl z8*9j5OaXeE9eE=zWc^l;!ji?k4WRx_h4V<4t&XACVOg{eSw77B4AxAX2<*-Ew0b+R zZ0Mw=CB~R6bPA$#y7rFicGAX*;8_RdxHEJd4rPQGy446ryP!ANfRj)@bPnT5nyhIM zb;Eo91M--gNhd|}BW-qqEa>#jD_f4*jGjupq+l@VDG_8{by!tV64sNI^oOQpY!?)p K$A3C!A8nB;plOW& delta 1248 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 diff --git a/assets/data/tool-ui/nex_power_management.dat b/assets/data/tool-ui/nex_power_management.dat index 0e61b8561ebe85a745bd4d6ecf413dcc9ef8c501..0682aff0ea2b81d2d357998090525572aa39e804 100644 GIT binary patch delta 1280 zcmV+b1^@c53a<)~KYyjvQe}WBV`C~mV9@F|o%5&}-yhob8KHQcR(3vgrP>vvF}tplXGx-+!x9a}J^e0UAfbuq1aG zMpa(7$1QPF{hBK2LBbF}ZfzVMfLSf0qwDw?xU;kvzNYV;Y564mWZFltvUd|oeaM@u zKGE|{LTOFmrUQSbsLsj$Y|Z$wH;)UA72qDQS#%L!otY@N&zdrx31-Y@L-J*y_OYk^ zBjj9Ux)ervEq}shZX-%S+Stxr-XZG`=%w>!J$hs4=V2CC^38XIb&KoQ#+YU*G3zv9 z1z>`By71+5i1rVqzZ<+1WIqDE)ouvO%k_VRKsC?Dz^Y?TXc3tydzVE(*r%Jt6D^i) z#9s=Z<8p-{ZNvi4y8&K#W>qdIfKs15cW26O(tU(DD1Q)pIKEBy(#%fMq}D(V1KqAB z>~*hQkh)fkfYEoM)y>bC^aoRVKmbM(P>t=O9~lh1oQU~n z2?uMGPUX=PdJw!8wC z8cNmftbcOTQH32(Ilomu#f;T{zI2MxWNx9D&ae~T-X=RW_8EsR>%jMOpV&YfzV5>4 zC#d({!2mFO^-K1AfB7FT?lexuO;Z$-^1l44VBYeXZ!>-mFi$}%p7cUTm(a9w3MEYi zxJlC~V(_{t1^&jp^nv-~4WN?7N6f3twAb{`8-HjkNvU-$)NAi0!m+Q?W(?kp1^Ky# zC_RS^ha>l5Qp$W=G09{CDhhBeRhZbpO+U((^A%Rw6weDwdehhZ;9sTK)+Lh;60Z0$ z;64HNLM3Eo*2l^dM`*^Xbkj^0Gv@vf!_V`306#&U z;eW_v_s~+H_z|vSv`greu&{@;j#cr7YU+lL%WHhf8K05aJSIHHXqX6IgJCA3&!pgp zL)8(E7eW}`ede>7%g+Jnjw6Es!Xs9Cf}cjUPn|Al(YlfJBTg#YM9$aoUs-sEM%^A_mjYEc%|+N~}7de*&kXnJxy69CIeVcCUEI5rf)zS7$E(0@Pa z>0U*rAMt&=c9hEO{``a*_z(}(khnNJz9 zGV~Bb-tin5msjj?wfPm&e37nG;PUNz^$zu@4LXG8==~Sye~yNSntEZvN0!LF=Hz}z zqY=vYGZT}*7eWIMR4!a)=^REg*?Hap(ya|H(h^HhcCGIH4$YOhnOy_+B;&Ck@)wUd zstO`3LOJjfn%C05?s<>;RXUn#ioCHzD1ceElZxWAt(tM=xlhqUR0CP(Y}fzv_Ill~ qu%~e+vwdF#_JiA-dX12HyN(n9 delta 1280 zcmV+b1^@c53a<)~KYy1YR~KIvcF@Z{0laxZtlzz|eChV;^y%2w)n8sw#~w#(vY6wOr9lha3Pv(A$Le54X)>}mXwI}^ELSfPC`#60sM%0N-QSyiWA{DKi*Fb9tJa0HIh}*=12Fwt=v3yYSOss zFX6D10)N$w)kLKh_6Y;pNd|LK!E8K>o53&KiBm*x?xUojDImS>?y@Sg@xGXKGtbA2 zCu>bGt^T17GNS+^QJkCie>I<T)lRTf0fT3w-(U?gf-ue#oIbe)^yr77%{RR!cWq%(}Yx4=iliTCfx6*wWf-~#8Ls5bYMkNE0V()Nr)ym@}@ZD4ivY#}&foHQNY&K{=1Aq9}~0QIMa0Kf)lUGAip9Sj%*=r^M0; zDn>5b|Jyx-V~ZhEL5Kju7|$l=RHGhlsefO!DXymvZ$WCZb^re??&t+d#?G9MTp|bDKQ1>+jI%Pq(C=+o(3)7XGFzeRzwWlwT z_N76NW5w_!&VVp8ZED+ZVD97HL*WZqDb^Oy9Lq8(K@?68ssYW~ine{l qv%q-#)uo&i1HzaEy7Zq9>xI#Qgc|Ud49v8C+qV$f`DBB diff --git a/assets/data/tool-ui/nex_resolution_converter.dat b/assets/data/tool-ui/nex_resolution_converter.dat index 9b96dc81755be7d175147bda8c31add99887dca3..c1b14282c1bc70257dc96317738971cc4b058298 100644 GIT binary patch delta 1280 zcmV+b1^@c93bP83Lw_?I!qbP#9P~lXqQysrb!yMY{_?Bl?SvCwx3=mB9|0xP6 zSnTI#@xe#KdZZ5Q<1)t0B6vCQ1b&4flmQXRoJ*N3`j95;3QDMbv_o)rd~PPCJx923qoD%RXueG+ ztR3iIdt8ws-K)+fnCC;sZ1eU$mX^L1>a?K=>v{ZTl!Pa67ui5(-Un<6B+4jw zhG6pI#D7t8uN@mzV~|VXI<*vvLyn)bUCQzljn2tmh2!1*?uEA+6p?EMYgt<(iDHEj zQdRG?Cu>cGE13kf=?T##CjUvBn(Yrs?5SMUcX*`3u!Z>EfS^{=LncSq>n_aUA_{>N z^pMlZuA}^YCJk*c;^O|yLBOc;^b0n&8gQEV(0^9deD?5pXJvJ5C<(rg(JD45Yeanz zBbCVb!pOEN>mkak)0K+*+_0>~r)B$Oyih#pT>Qo32D z-hWbO-X|WiRjOJ&r?Oy|Z==ZTI_I+eye=>VxMss#*Bi=m2(hmtsba5F3i)M<3k>|D_H1ALL?dXnASA|B=S z-(7#tZ5mT(xmfM>isX9PxJAF@!BV~|^Z-9@^BdFU!Kq#}Pi`Y0v_is@?a8ORAb*29 zh`C~hxtQsj6&@!?I!=CF@zO&>C_eKmXM(yIX(s(kxOe!8X6^)tbGs*~%BN-y zApm8}vTL0Rkpo(#PMIuwB} qbUi_W%R)vF%#5-IVl=#Rz{*}+i4}Aw$h2;`8PEf&D~g4V%49KahJNe- delta 1280 zcmV+b1^@c93bP83Lw^$VtA!H6kTJb@0eE)kD#6S|+S2ym;D^(=n@cg{rUN@$*}X6o z2GN2?pL#1uCnA77g?hnzF{ao-H=~|E%m9s1ruISEY_|}lYMAQP5b{T55YYVRJcl2< zr>z5peO`|gD8=0{=(vmP99KAuT=G*I$@?^fYIBEU_jK0clYgwk%_4$vqv8VYydQ#! zW33w}XJ@JdXh-nF}qvGRdfcMm{N zeEfm*3Dh6iW`$Bv`4x~eDoKVcD7-Cw6^8f>42s#dL2b* zH?f48%h84y2Y2J$3!Dm7okB5Sh&E|ZWxt{N+1F?k=Ro%$g!bCm>@88Fck+|Z(ao%NEo%2-{W z#NKH(#+O=b`bBsoV0>&xFVkM>b}m&jcmZ|a?tkrey?=PmfZgAV*};dF8NT>i;FBk4 z1Y{4=Xod`wWRIm`xaikz(C5DI`B2ZE@7~?NtV1X1(t}n(soxU#pK4u%=7sK(DO6fR zHEr>|q8V$0xM<16`-Q@VYDI|BG#0>oT`I<4UM$If!FYOTR7R>1FI%Y-Rlye7LIeII zBc!dCe}8bG;i~>qahsBRV8CleT^8|ttCgE)EUfQJm2J?u^8h3D!lE@XiPnR-rXexc zYfAbXW4?wdYMj1@8Pi<9CN{fKT{_ouJGe@) zvmAB8sX3D_rXzLLc&m3dswp5BfE(8F2j!nH0e=zhHC5oH84vl>-5o77SeQVQmubd& zO59yZDPfW{L~1>THdVHgNE$-&Hlr(Y!?Quvpsjc#5Gx?@$Sn=P`pfYv=Wb|cW;}8z zJ-3SVj$Rm*=h&1{+4T8D*QnT_7%uNB`pAtYBne;Lq!CrPe`!)0eo~MN5oms1Rt3>( zP=6=iIlz1ly(&LSnSJRBFE)x2t36~>eA5X71&xH%daI^_B3T}~?`!6RC&Z;usVVi_ z$FQ+KpTA*LZj?iDT2NdDO+IJ-Sxoj)bucJxqeb~G!vXfm=WX;)dol0;eVMam7ikG4 zTIT;C;NB^Wo`gnQ*{cp&?W~ZW-IYu;cYhH&t60g6CHD_@CRJdzsstl;=o>2W0BoRTRQekYjALI2~&QAE>iDTVVviwblQo@vR?M0|+Kaf+oE?653R z63Juk3F40!GZULwaX-boh@I%0AK98!IZoHlu9WB#)efb)I)u<8{q`D;G<+5Rk^snK zoOiq7duz1p%Y)Pt<`rMJ1)wvh4|$K64)mo@007bQG%`CtLzP>JMSxKI2ox(O4KQass8O&W6;`lf zO78_3mUdJU#qAjKM%-Gi(b1ZM7`$r;^4~~Zs2Ad#PNh?e=DKrD=vH-ApbR7uN_K~I zFEH*FYIM6A?d?*!m>|;@h0=2-QzT^xj~98o^Nq0`yRPO}g@3tzHlZJur2W)~LgS9w zr#fw57hVe`8L`wbjiyZ1BtiQUl9g_d3r9$f?W}T)XRDcZooIW!8WbDbKyfk>O!TyC zBl#qPK8&ndjPG*vESJh?p! z?wvK+$|t_2<6P8RG`y+Yz(fsMq&J!=6IyVvf?+PicdS;&!Fkov-_d+P3 z)ao0x$bYZf;iWCC^@^1tdy^fAja1m#m^Qe?bj5e2K#hB!wF?d;tk&Wf{4cpYbv@A0 z(>Qc<8WbXQi;3mYc=CIJt@L%j=@v|9H8K1t&~?+c%k;F7NN$Co z0^g2ZJNpGrA7tw1D)8TxZ0@^!_pnA+Zc@0A>M6%xL9-^1@vF(=v2-DD^L)|4+6N6K zV}Gmf3M0zWsl#yGLpp`=AnzvurakC#Fam$Mvcz@1^!fe7t3OAq-$fW2$ODM0D>$Le zhqB;txul7|5W7t#FQ}(^x`u7+HGyb(3&&!+m&hmKLpZIDMmUE? z0_QKuX(-eEsQ_bOv9D0yRc_&JovOwL34hCiC}qv@7$y^{`Gx9Ss|(6aDC`<0hSfVU zeA)GB*Jyt5QK(P_wZyVct5i7r;e>Gt2-%7tl9o{0z+LIF#j34*KYrv4d6aNK=5j_j zngws(2^v_`O<5n1yPq*pIr<_}POA#+Ng;Tz#S=s$5Is7?~;EGyz#1wSNNl zR88kPqXan|%YN|?=;o0rbI$&^o-X1dS(ofrVpkZUB-b3QTEQNGz1z6dl+1k4qS-?| zZ4s>`2K%o>y4qUTZ9}Rp`T#qR``}#YuTY-ez!IS&=7;6pBXKZSeWEHlgb z#{s_bFgTEJQ=5sEKG+iDU&9!DYrHvr@*bIRAQorfU#O*CHYZ)|5C7L5L1G*p<+Uld aP;Js|A$@KT+}9%Uw{RPF**@~vmcAqNgnRk` delta 1264 zcmVAlVPyP7Jhf4XhA;VmKXcEPG^jOK+(wgfkYljC?#H+hou; zJ~EYn&2P>{6?axONs97W|CEjBh_E&cBq3tPD8&iG3>#69B%F+)tq*NubQb-;r`1!P z9)zL)Pr`7+mn13xEEo>#5z_fh0SLisS1I zR{Et{sb}6wv87$S|6B7!*FD5^vF%AB+X9Sn%8}LJq?S%#kn}#$KZq3W`>Dn?^#n2a z|FvSre877ykFU62`&tl-grDCp5pX`;Bgu*X^+KCQ0-qZ(?xSDAlulo19rFj>$dY!Y zsU=xd`A%Vf0e>ProzrT!w?9cAG_}$kIU4m|^M#0+ow(n|WOR}PRW{bx0(p3$eVi@o zrV}U!z@MXgJi;g0qGeSBaQdC+$goToXgA}jJ18!Q`XX>J2%?YxQX#{px5;~aIovQ1 zPOR)fJ`#gPj+;`GpTiBD#jG92z*ccS9GN8`Y;p$>V}BHJ(bjXn%*U`r2ECX{g!4f1 zc$ngx(rlenKrNzQ=$k zf4}7C{=jjIet2#6yloIyvsE0j;Bb~DGH#QD=V_$F!mqy<%ZhNQ+CvC;oO(Me+P$)p z^iC&OfPehynb#nJkcTs9(SPF-fcjWF`Di0R8j- zdL6*t3w4qWKO@PPy3$;sS1l~E;*EhKZQ6`nB7d&A^p|UCgpJFejZ4z|XwrpggWK^T zPb!)VK*Vrn=JXnpd8yT9x+ilGxJa?3BExBra8QD>0zch#;Sh!c)LjW+$2a}iFKE}v zFlfve3|4a_#fUKOw6~^4aH4B>vRNxRS7_rmS$eEfIT#UY&YZH91C5<{lr-%C+VeGM zXn*r?C6(->q(GiFG)IQ0UWz5<%c4nz$`QHoEpI`KmKD>=G5=e_%j=a>??SsFDwMgfNQb5bxFD>V1KD>=9ndo;gohpf76?l- znq&p(xD<($2IWf1i;RPCKJt>SwGm$sNjr4;!_g3fjE0nSQhZsOg4QmOx;9eJ8ol}D z3May+M*AK9UMyGw2MVBh_R)HmK560HoA^{waAY~3?F4hUuM>|QQ&V9d`Pcb6&z>I* zYOUMA6CBp*s~=@=j-m7c)%-xUSo|RGyh0NfFH#7V` zl%xxSEjK2W^EHo`9qBvIs%a4sA}sObSv-4?-DpczioFk8oT5hqVrsQsV>x~`&5|jD z>=pq=z^RuMi|*{v6QOFQjMlC_WW@Rm4+^Z1XRtKY3UyJg)GA>o)K(&2mTmc@&UA4TsP)|~yQE@9?*nEub^ck3|;8sLr zv%~_asy4d#=SBW?xEi7!sfGVIK9lQX4^1)b;db-Y3x6kVskDKRTC0w12fX2;G4xx^ zBda4kKHMK7hiIEZ(~p`sh&NEbu4MFF_T0UE8W&K9cO<@ZMpt+u8`#{YB}H87&o*d65j{sq~NU%cAl1hIL$hbE7E zT1Aq3TYqUu3Sd%Ne#4XpJ0!sDAWw|pKzC^HRu)g%G>7gWQZra1?-=i}Z}Wv$p;0xH zw5dse6QkjTR^r_ax~abII5)dc1#(tCn;BhKr73s44b#J#Q{Dyi<8QU%Oh$!{dT_-5 zhnU#K<#AmGqP9N*IsKaFR$yn#mAMT58|bgIKYvU!TVemZ=Q}N#k2P%8wR_{jv`n4x zgGsLNTrCT@su`g!JHDQQC^oi)=wq0kz*w?oqY9AY-=3aAnwYC&4>2fb9FLm+1byGkv8m#RBNLi)QD4N7-!kID zqbVM3<01m+X^zb2J&7hb^i$9e)WpK>mwzj|-1m3n`jn5zwRmo}-$-Hrb1sF**(`dR zv4_ecwg8S_sU+m)INbWQDXEYlR{JNbW-I~WTAVdmHH{}_jYY?oE8U3#$MyKtD4^=e zZFmE%+VGl2dLR)=7TJ=x zd7|ppO(_*G2j&+1ATak`F~3FlCTVcW2Vb!#AVH|fV$xHSAlsw7vo;hv`g44AR3#UT zTrV>kxNcw_b_B*Nbq3Jm=d<%f&QT!x<*YYOZCe*#@Q7wOpf-jZg7&{p&c58#k7#)* aIaDL_!(q-ec=Q=|_D)zVi2m?R#Z#f5qjX#V delta 1264 zcmVh_KARm-MGICwP4WD|DShT3nwb$n3l;55cLKl z01O6!9ny=H%CQQ%RzaX0rCHA@WPL}Yap>ePy?Wy2@`cn(gYnie6RRW}BHDH;^CuAI zwAI~*Apdo*wC#ISdg`$GJ9Z+<6PLEXR7`H8I>7LhvJY43W`FDOK?Y??*P{5Bhp$B- z&=C^3+gPgagf3C9QH!;Pv^*VI7Ma#LI(YR!;oKL`fvtaQ8j(O<h|8Z_#mc(BuqH zqGXE{w7+hw#MMeJ`J&^N&IvfIo?6-T42eni#eQw|tG|yz)agRs47oqv|FUKzHXIWN zCK-^$NO^=_l+~sIaw%S5lw~@JdPQ{*1cVh^$+<3qTDubY2-_MP6oz-s+QV$j!>We1F2QUD7|G#qGlKqkuFjbnLUJXr5}CE~1%nxzE@5F-SN&rT!V^~L zT3e9Fr6m>s@G~;UQc!wnb7)zK0)MU0P=+|D0e_VfrVcaI9`hw2m9noT_nZ4?gGR|< zJshHWdpu~;&_!GFNh%&{D_h<{QO;GDusS=lfA@WfhN$zMRh+p_YvtlN+j-XX`I>?NZy_831`v?))gMsBUIO~ z1AlN_X~-I1XS9`9>~l9LutOp^WS`x;0sp3nhF-G$@Y*D0j#m&*LxZP{^D!=5Ffrw@ zMoau8J<{K>q`ahl-wn1X_38Y+cQc=#!%!c3fhID%xL_A;H26=o&_1`l4KrB1&=4P1 z?32lNoAoV{DqacMid`fDTj^ORn7g0l)PEsZX*a>U@~#iwv*9xoF&5a^u^~WPglc}g zi}kr6NhRId1&;2G?ZoLb>+;xn!QiEvL%BDMI3}ADo2s;+Z5yc5&bRdvg5H#fd;>k3 zrme;UaD4vs*RT^!^)A6B@(x_xaPDf`otz?_Q)+G+F`n&1T3UwlBNZw_Y=3FWkd}=G%p}K(3d12q-y3w zo6n%ol#4~(h9)kxO*@%5$Ck2T{b>}$0E8)V$oqriXtX|ecPg}Fb^N%R7}3+);Kwy1 zR*TuqWh2Vd?Bfac?fkTdar5k>XB6!mxmLk=`V83(UHM{t{J_ aFkFdPvHDsW1%AkLU6|;(FF~JiOZpA>NOQvg diff --git a/assets/data/tool-ui/nex_startup_manager.dat b/assets/data/tool-ui/nex_startup_manager.dat index 6fd805048f1c4173c1c4cfb3bb2fbe71f5e547c9..f4cd2ad02305fd4c64c4d617b3a93e90b5847a29 100644 GIT binary patch delta 1264 zcmVel&4z;7iS<`mtoRCH*!r2xH&o#v=7t#SDOdI;`?-; zxbnQqclIVVh0uC-UzJ*}Ge@k=E1=1buO8PZ0|f#Tx7o1g?fLN4W5X4e>%93xrcQOHXz=WcP78iyAFG_&ser-a+m5y7$j2OpNQkM?R2p@ zLAh2<{u7th|9?3qeTk5s#eC9ZwZPawgQn!3dph*4%2;T4w+MQSJ_rrAcZn%7UK#!TnMMaC|9?h$HF7(LfM*-b^X^_DQ)h(o z+;dUwm7WRxXOWAyKh*hAWP(1v$vmCYngZLCKa5X|kA<@rk64neL<*N1If4e}--CP$)HSQjVm zoUw<&oz|6~4Hnq`Q}EWE?BiOJTE7s>hA$Gu8fA@;biQVJ@dgUt(;Wc2-6P+6B%Wk_ zMTGE*XapDS4*69W;-UH3&t-mhwCe5bi*Z~xTh214QWUd2HiYG_$=Fm?V}ypDrsoB9 z2!CZif*Y&YItwibM`(DmNwjS5+^jOgl|iIA_uz;RV)-oh>>rWu&M)PDuS=D0L4jSE z)0z;{Q;E%ym8G)10vlMl2XF8u_N#foio7a*smoZ;1MIt?n2q*%xG-)Ke}_$(Jr3i+Ao(~W4PvpTYsZwu%UOe_Lu}Gm`x6{vMPdlQWL~0f-G8f zIimnl?ovO)CvH&sIt-)vRv`XPivg+#Jbi*om6SrW?Mp3nRv*J@r$==vG8s3W7n-Ds zl_pQWzl05!4-IkW75*D;f-K<~c23gTo}VUTyPm&DAwiWBUbCCTEH8qpKsSTnUVlnk z-4K&ZW6)_3>BnIY@%-o-6F{Qj9`qYRF;gxZFTAQ?P*7~gRaKTaZ+AtP$1!3EpsDz* znbk2S>PlULZiT3e*7Xf7Nz!Ihx}X;g4QWh{nhV~Bu~teGnUGic+>WVX1CLrdL4j3)#rNe2 z^{OxGtiH{m{(27e5{PA6OKS_a`*n_Zp}R_dIpO)+i<|3GNS;rm>q+Uqw7p4y=A8~W avorlp3Bl$T{~6yLFDs}`JfkSn;NwF&nQ+el delta 1264 zcmV%`yyMKUA9s9wwlX0@`DgWI4 z0df!*k9PFEUqa)xI-D;UN!*!fbrx)IRx!;JTq-1w63tBJIkkaRPirVFKl@KtOPpr` zm-_xnZ?GVhwk8>$dau=EPr!dV@wB1zsr7tVoH++rkYl; z)A%bPrwSrC{K@a*gT-K=FlP(@q|F^O z^^C#xla?vftsnd^>+Ag_mt79!M@5aY6A>v{uh%dsp8+gJ7FtPL!eGiO0+T+x;LWk+mu>t* zFDA`i0?8*Yf_9FyI`cQ=Nur-iZKa4pbANmtU#*ohp8nDpZ!Msbx9Vd?l#?eNP-V`9 z_-6o(sgpQ2O7+4moAq0Iz&~?Kb5pJ5lOxm%oijB>g%ZOUZ)^~8Hx_&b#tZKZ{XPKO zOUHh4jxE6>hHf#p^3B_%tTEqscXSYk4es6%&ec=*woe<+C8vyZ`NHWI^+QiFXMd3; zPxmlM#PIK5a<{gGb7Q|aqx^XW(tE0O53U%eq}?!#u$m5wfAV)fXz77|d$4Dzm{$DP zh@X9GHJ~>vFOC#P>jKh>i?}?~Rbs)3HI5>mf(5ytStUhLE0x9L|3L0$!0_H@o5fuJ z-}@a^)B1H)CWzi=>JtP%)x_(A#c6A(;^#;oi1oGF=p9y6a$6OVt%fJaU9~XmPkQ*$ zb;#C-%vR7=k$IJW80138PlOvsg_dtq(7h!dnRs#3&nK28GL71$ehQ9CQM81DruT2k aa^U6Xg)nPM-5vc1-*V||X^28S|H4&^(TouQ diff --git a/assets/data/tool-ui/nex_storage_clean.dat b/assets/data/tool-ui/nex_storage_clean.dat index 8170d6b3eb223036bbab49ded809b129baaced75..51bf004aec8befdd791bb7d8288e657ee74830c1 100644 GIT binary patch delta 1264 zcmVVh~P z7UPyvf0$QVg?I!Q8#U5=|@0ItUmRK*RP`R)O_no4| z1Wc!7fQ-HfQgKRcE{q{8>JEq38V4$HUwp>6 zLA}6Jbbkukh)TI?#LNt`SBnGjcSl=#8@DSS2Wt&w#RNW;`;%~!4T9@(emF+KE8qDo z1v>U+=rQk7ADB9LzRH+IkSS=#A1o^Dijugl2K|iIW~GpfHW7oyZ-3hz5~ZYe21Poc>6 z_+EY4_K~LoIyQaa*jW~28(MNvIJpCVOxm_crachx{nBDW1$)4HlNe&R6FZ;vj2119 zRRKDxv*thJFd2vDKEe)$^YLqAHv;Z|tPNRJA|_%?B}=3FFX=AzMrZEDS2w&#;KG$& zg<4>(iGO~bv7;sV2+gEK-l{7H@RpHO?4^AZu!pMPG8Z5ruR%f-yz}J6jNF56k3J|Q zOt_1v!*0)wF7mW7A^2CE?}<77;lAa%uh)w$QT#)a|o;wgXE#~X=D&wn%lw10N@XQU$QzxJQV+PEgi?ng%Y$9aod+`$i4$ zRO$!^tHW3WKtn{lbjN=W_6cv^Nr4nUS&zm`%dZoRL)Qq0m`StZQkIU4QXdf-p)zW= zVS(>d8uVE3dxj$<3^Q2O8k(dvy_ncGCVvl?FX}>nV}=yY4(3D^nP(ca?g8wTpT73v z5!?T?%9aNOJbMqvW(#=l_^Hn===UBx9N@&({-=OpXPf`p6jB7pAV#P&+$mC{)RCoh zD{vRDxx>|qn*GW1tfBM%SX9<tn*J|iM?WKb$@Ax zhQxk`f{_TX=9Lm#wW3ZA%4vMdCJ?}X@HTv%CWf=6eL&tZBRK+2)56+}TXEwo9RA_gVElor}x z&cW`g-}7EMro3-9nPR2hhhJWQC~5uMvEIYc2h-N#+wEfyFl>n#4Sd(oPSh?W7a*z+ zE3rIUgMF!s1YB9XjTmdGzx+6OLv4--a-BHI=XuG7_Z{3P aKTL!S4)R9Xoap3V8{vYzlJg-0ad_?{jc;uL delta 1264 zcmVm1S_FEb!o-)*V%>h4o2jgXGpZDpqxRW1#IbIv1_iK)Dc z*6^Hz22%(b+u#QwEh9jpY);hse$Ru?e5Q-`AR1%;N4e=ee+#X@G#;<6o>VCZe`}tB z-Szf~F>&!}P#rj{Khr~AnXq(snz~V18)7ov9{nQ+*o`HsTz?98e)?#t^VZwLB-V~} zTv1uXgEE{8V)tSRkhYW~kh%M+E8tD2e0Eme=ksqL-vY|Jg*F@1H>Xo;RwI=8n8GGJ zjjRcFZ=KrSFqBqM(bT@5`@~gTeYGpEIX2oco~3ntLg3F&sC&Vu}a(0`<37C7|s+)cO{0~?qzs6x2FZ}kyg($gniEl&iFr_bOf!c0C)c>uo~ zLM~opJ+qz^3svN%6k04S)u>2pa?q69?rJVPZMyCkf0WD&Zg6vP;nM^Yz^r%Sr@}o% zeaM~dM>RC!z~IRDZFa#gF{WEppZFyLeM0e@|F_3tbdl?rK73fTDCNt8oMa;91k@}BKLH;T8b_OXNh{uz`6M)G3B7dPuopFTl|vY zrDTWZBPRx;C?;IKG%OoSPuZbBRRQK=aALmgWI1Bg1(2Nndr(s9l{6MVf@FE-_O@`) z?=8i(xfk(G>_24x(swhKfZTvT9+L6M;Vn`)aeoUL<`kidb9$mlOMNr;>pqV~=lyQq z%>-_i?{fPO+Bl_DIBnoSV-%NMK9j`3H3uT3@%lQ9E0 zs=E8x#OxLEQu;*ly5e|p3Uq1>9|Qej%dW9)1fS;%^XRyH|9!>k$idlG)?QWP#OMpZ zsZsf#a|3v?Wgr1!&(T>=Gy>EkPzUg*qJQPk25LhqT;)YVkc`7AD4OHrpT`bHE*OlA zOMlA;+tJe&u!&@WxCDJZMD6;%295{0PyWv!_VxBV#AQ#|zn%jq&!tns0ljqg`u^-PVrDpnu%s zfi^oQB^wE#AVERV$hb_6mKryU7py@K2E|vQNYW&@s7{s~cdsot#mWWcKeob5EC$>R zr}4es!u%OFEn#AntQ?m*4)@u~wnH7QYJYbQglhWp&eeMh<$3?Kyb72PnqeRyT#E`z z^XCb8U3nMoo4!(JO_APOuuQG=3z2YlcgoCQQ&$`iVn{|##XafDG#u#|jC zrl<=@?EnpcM+(^%9ykfmKoNFrYlY7&9*^>$d+hz(%9;2rtEzciA}Is zU~oy0u!G=20Z_fvPp2LmDl(X?fWI{08!uk{=67HqRw8{e*r^{sy+1WMW-xaJ#wQeC zfPt6hzV61tof%df>wTLByC{N)SXZs=N`aD9_T<9U)=Cj{2!D5=x&pWd86*$3^chK? zY^AGL8bw5Htt*8YLBVV?-q&JhJh4Z^!a75fHp7I7_GH2?1+_;YE3?%8LC8UYI?a1L#L_k>!xKfWFC zv6)(sPJenyW>*as(!K)OQbG#=KyNoqTQ>)%f5$B%V@|{5=hh=j&Usj%_*v^Y{zrrB z@)nilIz`X*JF`RHj8RLSO-@uOv&bKm5*FF9+?Tdg){+5y3uLKizZYJ~7(x5J5~b63 zFlFC<9dn*Ql!l;}3{k_T^{DyQ591@CpoMkSfPbtl{~COmM3DnPQ*f8@n!S9p_R~uT7Fj6Q*84vFP$660M0fPtY@*HZ zh+d}n@^;;MFQFem@V*!Q2w%r7YWsoZ&#E-#26B)2LtXm2f*hEs#bLghB;rO~otPk) z1%J66Ro{$XK|Zy(qK$yl4%$wercY8XLV(A90Z%kDCcgJ7M`3OPdpip7e<2r~qlZhN zX#g~fpp5~d*Qtyc8c~a7H*j2v2^_oqy@&YQV&k~0ytvR|xRKqlND>LgMUA_-<|Cn0 z4-k!B+TM6p&SgYy(Z7AI`&MIPB>&bPRDW%oN@SrMdIO@ouHMOD5hA8EOGLin1#&|! zl)$A6kc7(g8e-!*kts z;8`y-jg=NGYazlwfEv;bljI_0&KK@v5ymVFR`;=D(9PI{g~axNM{BUi0^JWw$$z?! zDRLuC@GpI3?FE*Uz1DbRurWCl^NQ&N3jX{w7T!Y9EjBU z+!7{mr6oj=6+0#j_!aywIH9Y~4r2#0f779pFloPs`TFTC-kRF-KM!9FwPC2sQ*pjq z*iq%k-VW9%^GRDtE#O3T570p4h9qZyl?30*pS{bns;UKDlVhc@Wz@{J*e|~}N{DP72N#s%LwQU9 delta 1280 zcmV+b1^@c53a<)~KYyIt3xB9vbvN0|8vYy74clc5N=qC5K9%@T4j*)@$$Xq#t}mt8 zihO6DkZV&}laK-*FPx9|1j3h!Rk=rf>;23!z*5Oeo8#|pE@J ziN*DZ8f9TJssJ}yju_TId8c9_m6vw}?(*Oglc`IWFa`rf;G||~rNs1{Q{SdznEjlQ z-s4JqR&Nx5@Sh`Vm2rPZ7gZD?u^d=7F~&8djWEMw5VrUZtZjoEQ~H6;%lx$4X4G^3 za}k~>?5!?AK!0$Bh^gn}oY`8-)!#zJHbr$R1;P0n8k=py+6nGmxxr7`-+R(`y7iEz z*=}gc5-$VQ4d1Eddw6QA@LX}E$TGkfBW3`ZpFscpEUyf&dA^Yb(%b{Kw_fkwxLChl z$=KOS+BkQ=kjc4#6>YN0mpuZ~;Y%fTbygYuvG zGxS6Du8|4QIt9hX);(MA6vO*>figEv21qP~6Yc!&jHlqEpP5}#zc6YBE?k{fPhitm z@uJUkjHUQV6mbmgCu?xqFXcqEdPD?r-G?N!rbO5@=+@ib+6K-zOAwbNkG#^4cPL+~ zR7#Yto_`_rUkAA3|M@=~5APSD5pi>d$YcP5`=AT)%kCK|Wf0oD`2P3`#@_(@Kcb~s zgis{C*@-O~LQ*FS(Ik$=fer3RA#yZsL13_D+e5U(E3);`aQJi5mSVpI36`lp7Qk7K z6cR#a5njCN({EKd-Z&u}W9z8dHSk$V3mcIM?|+i=lGu>nE_d*`Q#;0lwz8g*fKuE# zAF;59Ut8B&wcQ0i*o_6GX-;S)%Yq>`rKaIKxHEOy=1OzEh0QL-EHmV|+S2LmxBY~>OTvbOv3U}nG z3V(Tc0=y*IgK~uR1|_-!H=T;>uO^wv0J&>evs5XRj1`<;8Cav22N1nWnk;O#Mjn<& z7IZ#SeQ^m}kqDqjeN@&lRGU@Gbl66l0>ks#Kiz0+-l5Ar84$Jbt=RB1=FLML`KVX5 zpe3^;-XfBc0k1zaA~8(-f#pBM7Y~nRxPQTGIw%suQs5hABK@h?!o|e#71y=XCtJ(Vxh`5ol#wOzrS9=k)jRIeyCnPPl0@@tvE`+nv6<~1+)w-tFhcHOLVWX>}%60GSBea{iD)&@j^#U4*`= qg9Pp#f)d{4*$DWWzjc!^#r=u(?+w_8_LXM(>>Uee4J1)fCr=ZZ=7C!P diff --git a/assets/data/tool-ui/nex_third_party_tools.dat b/assets/data/tool-ui/nex_third_party_tools.dat index f1aaae403a7b271b9fad4c57356beed08088cb83..ac9fc8013f15075e5d65fcd865e12dda4aab43ae 100644 GIT binary patch delta 1280 zcmV+b1^@c63a|>0K!4VzyDvoJ6lu}m??ku5f}k*2bHcgRRz_*D>4{BPO@$9OK_6GdVg#NKD!lQegIbeYL*7| z;N;CYK^@6V0*vrtoka4oJOfoL@l%eF+1Sn>Y;;wJe!MgV9T=No?i31L>6n#M9f_13 zUXa`I!-5JF=TeovQq3I;r{}Kh*D5_}<)}k?0}wb4poqZvp3!bSc~WFXXx!V8jc_ah z?BS@GO(5q&WPgwj5u*xitEw<>ZvXhKJ$~5~$Vvha#QiN6d zn1&WmgB##!Bp6pyfj1+<#gx%Jxw(Y&7|_!xnK`(jJ+{o!iSbmgHwK0wTWmQ_Zh@6J zT5_Ah)_-!ndmlS>GaUtQBg3Sy;;HdoR`c%o{BISVL5ei~Aw~7gkpY8H={;AN0+Y?7oiyofby^_dr%xsV1{Ncr z3x&J(cD2W;yxR$5WW?WIyHvlpB^=5t9;#YrC1pG;X5yo*awF~e6;yP)6=>(i(j2Ah z1%K9adT``RV>kw_OI;g?g#%$ojiLDZh8c3;4?;K?ks(+-UE&wM0pejpmWWUL9%v{J zl#u9d>Xoxx|0Jkhl?$YgZ_C>~=#1NM-&-+gUeP^Bev|&6RHX6z2nQ z)2mG=>HAJ$HPrQb{Or%%)G36Tcz#C|bF74Shfb2wqU6#(vUTFmWI%u zk_mFQAaf$VR5-buye`<(VmB@9>9G`@YRhtGJkZHcjYzpoI*s^_d>9k3 zY5uE%-jTRp$$GafQEmp}Q$tm?WB|A!GocD>BYp_e57-L&lRzrqb}p@3tzMCFegYU9 qZ0KqC4>Ug}I$ln{wG(J9+T%v?h+|B76C)O~uS|UKO$XM*#Q@!s=6MzX delta 1280 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 diff --git a/assets/data/tool-ui/nex_vertical_overlay.dat b/assets/data/tool-ui/nex_vertical_overlay.dat index a6e06c360bb4c9579ee6299789c737396c2f312e..6fead1f4a61768a584711ca1f72e757ea993576a 100644 GIT binary patch delta 1280 zcmV+b1^@c53a<)~KYuxhT=(*h()b zR;!>YJQKJNDv#HesIPem)gi9ZzY25147QMOUa#P_{CozCi!h4ho{#69l0P>KWIy~X zB9IjFw+g(g*2w0gaiKL-UKCMG6ZHRnxYU2pN|xwLt~A-B0;--zQ(}BXI9OJGP4aCA z`{G|3<^6tqaewy=DtI&-UJqsjk8aQWlbg8pKFt5ZS-E(AFG!iKS$p?zlY97=^J7SY zn+wq_|4D~Tx9|tF%FRMkCh>?}zZ=6Om3*(Q74UfNT|KANC=W7s84~Jj{2K%zyX2d7i3ztAWT%D30EmLnN>t zeg5EaxJ^jUE51SE{?jp|C#I8p;sEWOY-#(yz4JM0;`X)kGUDFC0~r|(wULE$=Mg(_ zJ~-UZLR&kjxJ#YuOx$8$6h3n-O?pYi5D`X%HKBiv z)Lzr=cb%lcoy*DW5@9lzlI=`=2A;1fs0)lCQ|d*76JLoXwnsH0xDtw|$^Ld^-+#kv z>ixK9=)nM=svfFpNR0t#YoF&x$^{AotK%4b)KNBb80$h8n42F#gW=J|bI*+yvB9Jx z+LYD%@6=@uFu4crEeNeIuD$&OxEtcR+}PGEr`g=!LDw7J9c`8xRw>RQag5yxlPEd! zPqPFW>4U#(;~X_N+7K5V;hvg_5_w#^JOhnsG;Y6a(AU_~?Sx)539Y*Ar+Jgt(fR?E zy)J?t_-Qems!LQ0ra6!hzSmzegAI4vJAu$H-2(}ou^5+%NK4cDIdoB4{~z-hU+i=@wv5`PPK!qBdZa@M;CJhc+(q?^z@wE?ok^A4un1626)xkxZwRvgpf-SER%OveE?9I2ra#5^| z>m!wCWTXk2JAXAun#s%^`l`fMyH>wcWQY-r<=y>-n^b@#qws}t=%p?&K}84+WXw>| z^q78%XRz4@yYv$470O~Lt!}iBD@612(-&K!2x&Imyzlh~(5N+bHivNYyC~sge;j2g zI`&z;U{;BVm6$D=leO<(0M4iA{S2Vc#JZ6W;H){C$_ zE2t_yW?E}Abli*%pQK+ORa0L8Jd+m}b-llm$QY@)+jDVG>RIS@j&{~_7takYA}l5+ zau$Phy3WN;hM!!r=itj{7Dh8i`?t*WVJaG~4}Z=P);P}jv1y(5uhza168^}U$3~d} z`H^$BQUp6SS|`1K7brG9UYqSlOeaT9gaVlhtA%TJ1951er{goAa}CL z41b%GXEnr14abMQ`97a*Rx|9y1Wf5PI@C1X4nL;$CeRVQPsH%6Oi4iM`)}~GK!Ag2~N6IpQ-hnalEyCeEv;onXN0D9V8^Q z64Z5eLQu!!9J)mSicpxkJ3=vv8%-`UeSb178DpC!cJ(O&u#H}-Ha$|z3Mo-XiRt&< zm-uN#pRs)$4%0+Tqjg~POwV0EOUz?uEFFY(+oNa4BP+~HM#p)%QW|hgXVfj_oc8JS z3fgu1W7u9Kf8^dIyj@+W@v)&f4e!_Qdkth3jrFukk4k)hmj2fLDnoY-I>}+?nnH_)cjF2?O>L=Jx+9~_b9Tf4 diff --git a/assets/data/tool-ui/nex_windows_repair.dat b/assets/data/tool-ui/nex_windows_repair.dat index 2337b6c08b5887989c186d8025e4e4c1a7cbc324..b33cc92127ed5a683c96618bc470cb895f93019f 100644 GIT binary patch delta 1264 zcmVi6aLWm0j_s45 z6l_RTn=W0~?>cdan~1ml=8DT` z*yM-d!tAn#bDljSqWcdZG!7~6kyyyWyTWl6X-(C9u!H%pMZkzdmF!!ruckfp+|;k` zJlcZ{wW6@e3(+}ctZ{7=X*{QKq zUEbC?U5|@Ve1CqjCN16Z;y#>oHVpmw`i&D6dxZGjnIk9nDN>Kookcoo4z#c!gRAm| z$l&*LwztX-ieTYhke}WYWteE5Q9%-*x0#Dl=$?O^O@6TaF=?eo|ImTTH8th|Yx^GD z2yW%+n6 zRXBPQx_?-H1D_ZMi^!G`niKwvp0GJu01Z|ZoTv*8IQ#%O-LBS@H`_L)Gk)5n){2&r zXJL0B3Q#TgDR@t(ICz5P#&dquOKrIQ2pK}OtrTe5k*Nw*+7(&dvB>o>ss#Qrk!%0o*8be`AGVs z-+%MG=WeVBw@kLX0TH{>GSCx-(K^FFs(W)PIlG*9SM#2;A{|0$QTJ#M%)Z_!x@`B} zB;Vz7Za776b$2B+sKUuH9cMunj8hH%Vx)jb#p*-GN&ulJ(|LZi&30y+5a)(ZIIfdl zBF~pJ82t`kz#Hp}ntouX44wt@-dIVbfqx<9sq;3yXMp^=%;9R%Yo2H+(A)^vBhj~= zYU8W@IAaKRAaAjk_hRS%MQs@tmV`L7hu+s8Gcz_Bmd9bq%T6Ko*WZUcWed=Vv?&N$i;*eU23xF@K3q z1SIgdOx7z2tOD_OD2iRM68X(2x#_~n7A=S}LO5>W?-#JBdJ5!2(|!L5Xg}IMAA$YF zK1b0NEgxHGedmVcmorn zpz!M-?O-4kXn(b{%yxFXa*GvoLScE8{(6RHQL;Kp+Av3@;D~H^x>YrE&z_?JSxp2q zXaEVQ)E8#{=I-Nh$kjYH)OdHx!}tuX-8s>cogZF;j+C%{=xCKDD+LP(4w%i{*B@P7 zKvOA2MpTg4Sg}k>vo!c2+kX=>)H$Wz!cJKefL}|WXn!kur~J#zkk_QR0iM)UIBd`1 zeMNnr8Wa`wqjtn$GLSmmV+RTruRN-<2k$5#qBEqmy-po~3m24=22R{Lr-aoWcp4Ay zcf|W?=*NVIHB*ky& z)V6uQ&IUbxS2lz-6eyiU_{YnWR}dVCM0}vWYW|l7F)mc*tz!t!;#3!@&My;Ed4atj2 zzlo!^h6$-2AcQ1vhhxmd1!sPWXqUa6|IS=jzdn*n!R?He$?+OI?r57aRin0hPg)`D zkatz!cp*2aSE@0UL2phPW<>Mq{Y}TC$%LbvEv4>+VC0P@Tmz+3VU{pDFeY3!pWkpfqR zRefwOjFX$BRfetpov+~h5?9g6 z>A4*vy(cyCdokg4`JrVr4hHT0RyUpL4ZlLD1RZ#1aCw3^2x`i*1@0>!%#zG>)PGwv zPkOr>deF#=IB_U)R(i}|oQI3(mU@twPUHe0>{~GuGIOM%dan0aL3dPExWU47l$SHn z-A^^7tTNW@BPgIif8rT05&aG_y_ z(D_v2)UO>#^$6R)qlHQ1QuR&sp!AiP ahuyAkGQlwbFT}GAJ5Z=q-@}RNDpZ+n4{AmL diff --git a/assets/data/tool-ui/nex_windows_update.dat b/assets/data/tool-ui/nex_windows_update.dat index 262bd1207929ea0616ab5bf6b89d66f09fd7737d..d20b823ba34f29a77b52d1b3de0b7972b74e4b88 100644 GIT binary patch delta 1264 zcmV4n^nWAd65GX6J?Mf5Xq0G&%E`_ES+aslms4~~!mu}OxL zE|Su!%Dys9)w~H@;Jw1x5+4j(hYBbuU{V4noCYR4`^ygomU;In)HVF%tAo~If_Ml9 zFM6QA@1lsRrO3^QbbP)PXdMIyH_CSWmG^Hixb$E@14bRi^^p1xfC`ibxLmoa{O@%Ed#V|l1G zHe)1w%b=4_zqt>pRJOd1K)AgblA9g&hgot8p*DpQG=G!~g;toUpR}Dc;3DC)m2{3N z+4m&fwO>i%+?#DYn!&#nN!?8mRLa0k%y;O*dF^DzhE97uC;Q}$;@&QFKbYd<=LXt- z_Oie<#>vJLW{;-D4V!b&y}SlQ7Ei-K1ei$RKa49;)MoBU^QirgWpNn-J8sW<>+!ojonSzEiw0z^ z8kLNDeHVRYc?2cmw~>|}KzAEw&{Rp?70s|L2SIPhIbLdEPYurM<;>Jk|M-Pwi#nqU zs((oDVvUTOB=Vcl*2Z7_`evBd0KoT`{Qtj$etd1am?A{fMgZmSl8QZ`I(#DLBQUh@ z!CY|lO`k0nG4ZATG_Qn2n+C5?QlO4v_*4iJmrM#71U0*pWQp%ahbz@&sgY&?9u>mB zh4UIMjLw+Z;Pa)ce#qjih_R~m3)@12iGTY4&p7tZ^w2!RCVE)Ibfqi%64Snkz(MXm z1iO9Tvu>&BwYV#QH+s9E;Djv+V?!Br`H;5U7$@5 z5E@vXG_){Om>N1EJq(EPxZPiQqbxDGW7va8k?;FnJxtMb71hIB*p;dEsZK_qWuo?-BR{JLIMm^?e-C9@ewrs2Ms@8FcxnI6sC&P0_fUc_eSboMz5*t89;arN3DuaK zI}3g{N&P>-ZGL_fMXp@vS=3+k%EPZ&O{KZ=XF#>gMIL_pspk++n1xsIY$>h5-#cF&0$ zN?Ewpwl!0jC4b%Z9l0|)AVB?rzge(;VDP6=e6OKAMW5n2!-Z`9oNiS~z1xlVKHNeQ z4O*~w{sH12b{9{xR*+#AR-3Ge%L{qwRze_TuE6yxRoa8k7SNv2KZ;UPf{t=JRkb_g z&L`+V5%Nddfw6>%_9-MY#x;f~H&qx`E(gB^6BOh5-G7n~B$$xdXi8`dMXCzqOlj0{ z)Ew_s&F35FglqL6co0fp#`?RkzSD|WfzKaNTXCx#l$Gl4|Dw!zFX>}*fZ7HqE`WrM z_7J5ToC^x4$vO3!bX;C5_*S84Ax(BzQg7t`HxiG8{DodRt&!g^l`VF(|BxVo7x$iY z&tAl=C4UFW>FQ0b3M_bobsdez#3xD91s(LZF4injReZOMc$?83(co*Z>=Nu%bp^_ zqJQAB@?Doo1}6C?<{iAIK?3OFDZhTricd)*9PR}RWqmV4}}D5+$LJ9*^D_k$+aMphf8zl?$QneI3V zus0TFfC6Y|KMH7d-uLZYY}$Th>Lq7>7Jup$J$Cjh%*nktx8p~yGR!F^C}GrGOC)v| zD6U;%6LdYiz~EHqsl(#9aHM!%(kq7>*R^;0pngBj*`Ynq`n$K&rGIf6`H84DE=R}tW>H~M(SKH`dFBO?jYRemJN`A)X z74j7I9nRmgl+`7hLpI3Oz-dKBgXJxCSW(-Q^N32t-+oACU0+j^@*;}h((nYA zj8?^R&S-GteAu(~)F1M(P)3EPm9ZtZ3l_UUeWO+!hEFt=$9^O-4^Q1*qC4+Gn8T%a aXIut}8-F|I%Z`HTyI%&!pa{i!SDXnnv zZMpQW?um6Tt7>Zv`#)c|izix_+f|Y31WL6MV9|_`ptp9^2C)iSO>vk(4T@;x#^{^mCqBPV=x`L>Ro-M39b$?MZ!Ml3qg!>6bSRM^1 zx!qlky(dBx*{v>;TwQ0T#>ue)6Q%J&I9V5-)>?zmTz%WdorO5$&AJmhm!WTMeGSBU zNPrxC0W;N3RgLOG7$g`crC&+22tEBm5ZnTXdcEQMbc_d9r7{pzmcX(P#)EzmgTD`L zQBgfPwn%R_LVv8RI2}6x(Cg#`R!l#9;WCJjOR^#KQrDjF!zc;Ac=`iR0qd*Q=E=v1 z!|Kf>0n8@HrP^}Ue+l;>dq%iS;z4X(Y(L-apJ1Ruaq)6xB}!0!rj z4)W!FVJ{vb^N@N9=`WIlhX9C_Soy^&T+Unqzlvg42Y*WRbb9%p5gw!XK2a1mfOi^f zy@2IM{Rvf8m05;ngFF1k2vlSGQoh6JjALNRP8_%&S=;ByiNX#U$EbR zBVf)t>V$NB?)sZO%GiINEnzi9S?~Bq9KJHCR~@T?2pI+QeM{Iso>52tUZWM+_Av5avmSmSVpn?q)hk=# zMeD5hDagrG&{O&zM{XY3sx7cEkUCQXQeqs_dk?(%pXL6AD`>lr}~xj=nPf9DR15zdPY0qXW2k-gy@V4U}niT+Bav+GN2D-V%b3TeN-;>*k9 zd%tKqA+RupLHy2>;9*F$>(WC#9nq4|a20@MoutKfP&C7Cs4Z$^ebjS#Ws^D7PJe&Y z0bdfPM|g2CW|${RYNIPRDo*$8wZ1pRHg^!7e$am;qUYV)uPHU4lNG4QIkT z9(B(z(qE*>g~1z`2n4nt3^aI;krs4+*pjP~EEvMzRU{ct_hoJ{f=XB8VGJnqp@P82 z-6aszTb@M%fg*2IFuteNhrzEww14uCsow7O6K>KMI{2c-=t&-d)x8j2M|0v03xD>C zZ%xbN;=c*o(@bkyBi(6#>N{nbgX0mvFcFOfDY!nV(8)G6qjytvw){*B`hcFNKAEJ-T3(56-A9CdRkmL>;?)5MgsT6}Q-9nRW)Lys zdUW)4Y!*_-%J0?eN_{BGc;*r>NiQlh7t66B5%{m-%xh2hfuC3mS?XsPe|;S&{iW|f zTYg(MC2d01edVUdcNj4hng0p06Cn@)xtRzb=a3%G@mXOb+X_`gEuTm-q1|>dOK(tB z5bpm>Wz8wlq30JB6p!8b#(!3U81eb?K(SrY@{Ga$e3@9Pf+T-DNzKH221PKa<2MZXa`%aogn zaoIb&w%{xVXdjw!NeW1U6QX8%L+P%II3{hBWXzoT`K_(Y^K0%h=WBIY^`k`Ot>T61 zrnv>3y{QvM=l-8qL9j8G`!KkYuu*%2)aQq!%75KK7`VRz z?ET$XPhL8xF&WV~f{Jr)4Kmt^F1>)&j|(;J_BVa4(UT5Mu79-7^q$?~whM^Kws}NK zmjZ38b33~T?+DAFV}0R=7^&M5iMfvznAAVH;IGt?#3II_s5kRSpr2e+Ik<%Ru_OtB zXaHqZ`1oAZP%{h8z)u%B5sz&)fC}Vi&I%AO7zrV-`{WuSQ7;TL>q-kX4`-I$78{PP zpH`-rx1dE2vVYiyIhSVu61K+T7=4L~LC7!{%*8BbC6~b1QKO9w*y-R5M&-{M_VxmhDMzNq@i9xZFyE^)L@_&OdLB&+Yk%hNq33cW7*sYWb zXo~B5e*p2R;MK}+Od)!01i?p9I&I0QjB7qk*T@dL+tHsv(ti)G|JoIW-Y!IjbL*yP zc_b$G`zai1K|Y;o+rCesnt6QDr8sRR?!@@z@l_Xhm*tb^foiqCA~MN?5c*eFQe*ci ao8E98@exEUB3>R-AM{|iePMbP&@_$_=t6h^ delta 2200 zcmV;J2xs@U5w;PKHh+pCa8b~UT*^OrPsZ0x?E{HM8qS_9IWwqqGcjx_V8E*jZ) z2Sue|x$tNPg7SBY+;AVihsbb@*>;z=%sHZ{je>V zF~AfF{O5kuS2T*Wx8K-C1$~tHXRUX#p*{rmfeT6+t6HVcj6F_l%3>e*SC*V=3u)cssU!`Y_@7rS)iOQIOiV(~G6I>(cYM-Q8u zxllHcehZMHUza=|oFiSJE?q?C2dzHx@k(4TmI#*$=GBVavL=*tVAHOM#3o&P1KL6h zgS>?8ML_2##4-}glAF~{cT4EvblWj}3YYJ3-cUvT?0=feR5pt(j5*b7D!s!`hIoHp zN3n8o)iN(z7PM!KPgNU_T6S=4;lkLEnQPAn2 z!}MK z+f6UR(tpW#@8x+l0u(#H2|s545wf}XTGt~gIU*1D=h6N+XsTMJ(n5F_hko(e#3Q>} z$!mYHA3~K?(L+oP4m|g9p8MUvWETycXTZYX@tFtx8eEjNnlS&&@#qgGyB~YW(z!p@c$l@;XLMN9cGogX>86`1JXY!++^YuPSMp8jMUe0qMWhl@lc6Kkxmk zlH@o>GWDZMa59q%@Wv%bYOr+jG<_YRd22lHI^~}`aCqAt3yB~P<)+3xFb_)a)1qlS zMs58dy_xX-vtxMol(p$2P_#->r6jM`;^eCNFfWo#OooJTYjHN6KSehfzWC@ItM+tz zTYu@&$nK10?cQ)$Os1k4!74VxMd)?F?jm;>xxvi5q^Ics8@N}o2kL2J<`;u>_wXH} z$17-P8RSuE@FZP0loXD?;@;3`mm(mvYcA40G;IsZnW<=NeHt89l6R!jVc3o5giB&| zl??6(v2ECRcU?7 zruz(d8ocA_-?**-&v3DV(7fHpFelEzEf;(8T50O9s=yPmtUzKtutKnIIS}9Id%-Z* zneChH8xv1BJ_PIWEt=B_JnT3UFMq$%Kk}mf+O!gx^Pi7s#}6Wouj4p=-^hI8?uxjx zy=+2(zGegoSKKDq%!oK5*2Hw+k+Nk3*=%hsR*Fj%EoZ{*k?G_4a;^gg$1EsKU*`x+ z4)3!45q3$n_%X*WaU3R8vKvNV?-0DDR;_^9F)b+5#HteG@u~FnWbUT9SbuUUqlEz< zsFH30c6_h@2b#=H7k+n+4nBvD=$9+?P`z{EYZNzTdpHF#N*y)nJLaD(jhP*(Tkh}` z1EOY+v|UlBD!;SExPAbA#9wtHff+ReF;0&OS)s<3?F@R}j`zEg+iDY;t=@io%c3kL z=H%$%76r{tmrf1`k0B{bdVl=|?S-8d^&s!b28^a{XQNG2?MCLvCf`g6s~KhL$e;NBod#-eH2Vj{b|_?dSiV1TmbdX z7&V2i*&E9vs9~>nz{n3j=GhcehO+pJxoI{k5j5jB)XSxV75@=-PMWNlu3yl9ABSxnCwzk++u_%BJ<^kyN>8 z&3KP8yzE5bEP_|f6&V9_Tb!O>!8K~oNLIkVnkB*xJYd?Oi-3PU4U_ui=~pk~xU7>u zd@LFUZXJi6l7IaT?e;PCSF}%q$HtnmYp#O{bA~qYo`eOz%AYoj-Y~_7x9^c_OIPy3 zCRjWKpKlA1nC;j;xi1t0M8`D|SyDyeBBejqL)xkxk|ei-9TfJ1#L3Yl25?e-aZNb7 zk$v*MAsEELzc{5%Z9<)JO>Z=8iwC##*dYL3Et6sJ zN4hmes|w8F@zih|^$^OqV7?oY;TJt&DSW*I5kXM5@Pspwm`F2|PeJmuH-i9dwZze7 zpQEtuD=bF#l`M;+Be&$GYY6z#BFU=o5QYlir4jnv0T`Qz2^MSvg5xLj|HP;rkybr1 aIibiyW)Txi;0z8sp$H%e*}uiCCMfl+F;8Ux diff --git a/assets/data/tool-ui/number_base_converter.dat b/assets/data/tool-ui/number_base_converter.dat index 22c658fb28eac8919b5b73a7a9eb9afedb1bf7a2..825ea878bbf9a9a8b8011c32b46fcf8ed4fdf6f5 100644 GIT binary patch delta 2087 zcmV+?2-x?~5YP~iKz|=c(kJ=(l^?`=ngGc3lY+pTTyoDS@{VAR1d$rtjVXuIj&@Q@ zu-#stP*O~C;{NV&H6(5^BI_d0op}+C14Jf#8d})DqkGL7>C3%%a;*TU(A}d8U&Wm% zTpT~HnQg)YN7q9?U7#A|V)T&zi~b9o4Gr?cPrp>VWgNbNNRBVQnZ zu#5qQX=4>EOYDQBhf*V+N)Oy&0Ux&eX_ny5#u$#{&N}}pZB$QO;pX1f!)OJ(_;qi2 zQ*4rCup)411+(OCb;&SHSGQ0f@r=>l4)}SQ( z`)#ios`pOtqko?8U!zHpQM>A*5nfrvyykz!3-$_pRg^-Wk^Vy~sqe7F%Up80jkr8uPXbQ+GHm=7dKH|c9y(KNOQ3Wyl!d}LX7+Fd@PdK z^s5LL6|6&3SxVlK<>uK7k&Hx&ASbE3&hzajYULt$Y#D&a_A|xlY)+`Jg7GMk=MCg7 zN=$G^2Y>85qg0;V)TQ|0?u=y5SHHFm{mt$AKx zxf$VE2RM|Efs0!!o5`K;0S@=rsFOV3vL4sc41Zp!W&8bLl4q9YCqz_j_x+Wh-6y&8 zJQXIL1Jc!2h4y>dIQd>$^Zw27%G^NgIiSY)1(AZQ$Hx_Ct6Y}jLj_*5u?M9gSn|*D z83uz5BGvWN24XkgczrX9RbcwM{bf&=uq|%$kR08KO2rihI}?#7Xwi-jCNB{JtbW_! z__V0OV%EFfEJ(pjptSs|(>^f?a)%|CFN! zZ@Q1TueXo7e!$z0TOkO+ ztbVOcESv+a&JtWbIugFT>g@tx1x3^uS(&-7pbsvE4AM?xx&)_KT#P(j;^iaHk!>ng zhIuXqiri}7gxE+XOhYL1)iAylU+EM|Za1T}N{+@1)QT;QB-0r2C*$K>!+&=~AmnRL zw^b+v)>+{n4CxezI#knd@e}a(d>gkw4acSAIg~c=mHzfGis54^x>$w-&*SMS~8NMS~9j_M=8z64TBTdS( zxE=lW#JW63>rnz>aeS}p?tg+73S&do5n5Wq2Z@P%=?=7~DtY;ZGvYs6i2#U%=F-;F z9XjSPjR*laYk2;GkGtebUq1l`fP=LxaYz^@d{L+RH#Oem@bsL&m`S7LO)%bc93Jz? zbB)q(@k-AP^U+jOW!qLRnl4bvUCyvQ36Imy455X>{`G91{XxMKoPXye&eV56>O6O- z?+RzEo|ut;Z*qK-Ty-CIXUPj*JO`Xl0wFOrazUx(B!o3|xf>wMlFK}A3L7mNA1
  • rn1Yqr{QHKJ%< zM@xM2jB|5R4S7*e44yYeeCW+{xT$JLt^s^mVCAg_YHIzF!2N0|4FamPj#<~ZNA>Uw z2Ko6W|2A0{9W|=X(-FID(d#fh}a z1)s;@2ICXn18&;_*b{A(e9$23iEIDt*vQPd8Kp?-Bxr0Jq1`#ixR|}v8!wfn;d+Y#PtW?-j zjLCi54Iyko?#D`6ESJT)i=hys8aYiu+bfUkG2P*Mb0A8s6&X9Iq}x)fs_i0W`e>U@ R1K4$NB<@oIwMMU0j6_^D4FCWD delta 2087 zcmV+?2-x?~5YP~iK!4qTw*$n^9;iXU&!d>{K%cYbmMu(4aXOwzMHU+e3c!}Y)%zVO z5W&@}hCC%!oB+UY70kUvq0k>$`yDZQc|8M=z|ZeGrfDh{p&Gk24Js|P58fiU#rV7n zI!E;?pS#;`u*>)_s`-~l7~{8jtD$rpkTI%0tvjH8;B?|2!GEyc+H7L%;72SJ6GRsp z8rC?W=G0vDNBJ;k90zqU-adGx{9@vLQwjgYL?b_{Cv%S>IpiOx6EYo=ufkr-c{Q-tH%VJrdcEk&rhSjpYBZ|uYR?jR@}UE*r> zi64(@`i}-oU@y#bM~s!gzXZ?xHl!WlZ~tI z7!oTsRCvE$v+ySE?Ib3o7|K@qRdtw+OvFAhY1dq>m*woa~^X`1xPbMbDhF>@ELo9LSuB^vv#hZoH9NuB>L$ zID9=oQp#s_T~T%tdt1eS+4%GENc6>rfniC~^8f0buYhCramIbuP!04g_3B3fX}=3l zY+9rx7)zO%U|itRL$%im?k)-NJ~SsP0=yRdAb$qG4)9O>?%whVL=A<%+_3{6(NAD&V&8$Q&-Kp!{U@13GcWpZUgw{M4${CFM z9GPYl#$4RVKZqk+bT6isbqg+3r3wNLYA%LAl(YR3K(T2cC*n@dZ0 z9e;jmwyWeLXZqH8Di1Q-MlUEMYNNf1vQnibdoU!W;Mz@TBuPbA&Ks zkDr9U&`tQ2FK$E<-f5g23pHJPq;*~Qjsp$@z-w>_$OQ~Is5INp)+#-xdjR&5;n{?A z_H~U@CI#bCvOU!om0psNuVM25N+Y12D}O~ZTt2TcktBu3H2Ksg1GTm3!J$|Y9>Rp& z{!nDP))7j5^_i2|0r~=!3&5p=>m>35lo`I2P?(6#u3J^Vtwn{Aou(c(77&cgJkF&> z^D$Vi{0lKs8avrz{$MO=`cLlGFz|vAj)u~KL_ZmLL-YAIPH1}qu>*vR51fpuSbw|d zHNP)RMgd?AyYyghkmdL|+8V z;ZAL20d)tJVgOo*Pi|TbNt!t(4uAb5WN~op^04rpCdA6eNPX1#j6nUynK|H5)yTDO zvF*&pez{Cx6qrA6Wu$m{n{n7dRpB z9<6ZGRuCbZC>1I>(p{OAXHy2=bf`g}l1ksib^d#QXW9C3}84b}cvT^lk$T|;3)^F|X)K7>kHx5e-V%cBSda{&#QL@Sx@J7K!2s2 zZlKC`473~wYRkT}GmA|PpX>M91q;!}2s1ZOAb_Z19w&6Z07SNjnc*a1kvFeeD5GYp zDR;6=#SRhc@?}pOY;ha9 RF3w>?I_Rsdfveb-+2G5q6T1Ka diff --git a/assets/data/tool-ui/oil_price.dat b/assets/data/tool-ui/oil_price.dat index 024e19210eb068215c1c066e0aedf7cb0ee1e7df..d6e39f68f4955693b02ef4e008166d8137d55292 100644 GIT binary patch delta 1555 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 diff --git a/assets/data/tool-ui/online_tools.dat b/assets/data/tool-ui/online_tools.dat new file mode 100644 index 0000000000000000000000000000000000000000..874b5f6d4b3e3023d02770a537718cc6264fec27 GIT binary patch literal 2327 zcmV+y3F!7&O-NN#RY@@d3;=I#Y-w&~UvzJ8Y;zzpPQ?k9Kqi(qIz$}4pQsOy0*zQS zO0{_1+X?A&gczy4q-4)Bark1U&@h@w1$utP9kPr$0)Yho>zD3Vuz*@!1A6yB4LWyl z?-yF9ebu|-TISN@AqaaQ!S`M089tz|KkKgl=wB~Lu=B5iR!)jCsT)H2%R5X~ehPXD zjk@NV1I{#rYuJDxs3YLr4WU;s+{!vNQWGS*qQYMc0;j(#r9WvxM)Voim%RN z2-{J0#o|ZW_IgKQ%7fm$Qv|SiN`v9r=|liDPMt#pGcc89bHMikUnot`r^WU%clZFD zRvE06>F?6y+Rj>^G>|}P7x5~xsMWC16n3LVO6x~P88bydoAQM$YKRtt?5pg}slnBv z)x2sdvR0QbA9nDB@O>``%;^a?=$z5O44QpF(c9*5=2gz<)|v4NVA$!nlNMT3mm9fg z>I@Wf>8`MF?L0o_vd0k>RfA_wp|=`JD_mW7)-yYhOvJhxojgfD$w_)4)YU)!wSfm^aSzJuGw2VZr3N{AS<^htWJ*AA z-{{^!hE~*O69fQD$LQmU83^uGkkAsiA;tw|O2L1*jb?uQKVJL3=EpsM+DAhsm3j8I z?0o0dt#Vll7}o5fTkgzV4RCCDA$j)` z&l*?{C-=t&hCo6Boo-Rew1)Fa)TluKWa-Y8*D|9aG+diH^{~d||9kPHgv-tz-Z@Zj zGcS&XK}c{bL@q%kn_|I*A?sM~R;mp4bLFI#69Y^bG(D8p4#VQrC-s`7O!j+%gt80> z@=ib5K#{u4ISDddOzD!WXtG2&VZgo0=PIr1tJYQo)J2mTV4ny;wAl7im$Tp~YuPm$ zEm3Wu*C5p<^+H*w6;>Gg+elSXhw-)#)kNAX75mvwLjpR*4F>@fZ@cgv zht|=92YAk$r{e8hHc|CwLV|2L=z{w%YEAN`Hdrfss%4!37Q*HEv{i`KVIy+S+VBjt z;K+wwP7Vq?Oep;$^x^3Ub_ncsp59S1<&UI8F;Q3xpD$V|lYLdSsC-$_6k{rj>47EC zwO`TpQ+1SpRcl@Xa3!;8p-jC6FOI#?T{En6v*u9RYR4r+ie-Uo&sa*{pdJyKeCr%1 z9|!?Li$PjLqLy&Z`Y{?{y>u-Hup?}B$%}LmKYyC}>W#E}cAdo^owWZ@h^66yd6Fwe z16(u@rU7`-9s8KCsNLPu6b-A?QEDWxI$z>ucoJ}&116IN#*W+4`_c8s11JLd4_Vh% zz2E5titmIH>IF~%ZubG1)bYzBT}95Lo1zUz3^Rpk!wX7cPluRb$ltMYe=aGgt8n<^ zJCq{rd5uBlJ@e{C(&S-U`1oK(qpXPcj_+HM2`rpJ%7|K$GLZ-!g^_4HLHv2bp*q6d zfx?`bC$dyx_@;mhfp16qbv%?_SB=$h7A6(LxSYl36N6;~SJF-#B`NK39xyzU^B<(u z{Z}q6@Uh|U?VXYEwBx~zPms;Nm6~%JfOWVGkb9=zf&B-;l)NHJKBc>D#Gz~g1-K11}2xXlj7+l2wAD~!#!a)13#O9-czEep3&a{QyG_Tk6B_-B$M)++HjK=-ilda zd$#7pBF(-W4x?9fU)`TcZccvi!*Ac xY`v&x1CW1P_nh@eOv6v(i9R|gMq1=oFV!fIkd}hnFQ5lW>CX{r+Q+><2JHH1b-(}s literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/optimization.dat b/assets/data/tool-ui/optimization.dat index f458688faf93d31b1dadf33dba9524decf14a8f1..1e97362ca23dcf99197a915dbdfe81d963518ebd 100644 GIT binary patch delta 1522 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 diff --git a/assets/data/tool-ui/password_generator.dat b/assets/data/tool-ui/password_generator.dat index 7d466be82a7505389ba4356498adc5320e357dbb..89e12261756cbdc231825dc9c2b8ba39f2e91015 100644 GIT binary patch delta 2071 zcmV+y2IEU5t}i#^c0aes~1c{yo4gJV<>tf+E7 zC{8q?VcKwi%+q4=^XRaX0@=!gw8{hrut2*7k5(B)6Km~xMQ?lmWCQS!mTveTNqR^- zi!5DfW@3)|Ncg7bZ~a^`rQa#B;lApq5K!qX;RjjP94Fe+Y6#H`$N6*yRy9+7o#eo+ z?Z(NWuhh(QYA=)WzH|SlFIq-S_be-k)26N9aO(uYTBqpxkW0r(rn7oQ>i@JYR#qVZ zWlkQi$eaO%&?n{t0*TipHci1}V6krys-d8XUVbv%M}K@39Qj#;KuAhDY*qy@0R`2# z#1I0&blh@B|Lsy=RrDT1D48HBS8;yY8%5j(m|oE8aO%u9Ak&%>G_UkE~G5bazE1cs_X0UaZJwo6%V zz;P>KM}O#SnL%Ax+iG9UzbjW)hRReDV?>%i16Yvg}7%tfj%& z^OEq_oq^2B-PO(-N;)gja%WF#;&5fVcQ) zjzuSVxDyA-mp3J!K~yiiAVmaC*x0WJq8tvTeytsc6wXr>dbY`%v+3w5NufeaO|vF$ zAb$oawNqvWYFgE4%}3e`0jTF%9*kOAu0L3-KrzVD2NCyuR8S&XwY@=V1jmp5Rr15a zmP~b~C{l&Pi=u8XYg|GFXG%~XjdZs?ocEud&-8dH$qjfSE@hATgR=Go*^7Tx?2=hb<2TXU1^XT^0b{0w9DfO<+Y>$%!RTuFl2 zH`sD9!#4VaINpz<(2WHunf1Hvdd*Y3VQmevQr|-K{{3VC2F%M4035@UE#+Qxku zc?~dfV5gIO*+rpEkXC^;zGLSQeSagO$W0#Iv>GztOg@Bo@45yjz-$JVAf6ezF+=8a zE%FBCUJGmd{PFi=*g&Q%!3VvGE_%q zSK|G$M|gS=76A6wlHJ@2yML5M+!RfKlW3xyAvqvtZhwM5W8!Xr;ExWH6q4GS%Q^R8 zGEUP2tYe(ka3yb9T1qnIzc@l8MngPw1R6a6Ow zmG8{Zjoz0qrB7Ow2rPNsy-grBa`iqzd_o4;L(>6s^h;w-2YFuA0e{yElS50ZR1)Ha z)sj@Yit3T2%+1?yEi;48QbkT66YiXWW0yPPWd`?Fs=@DzN-xEw5Iw|UrF#bktQPbC zVCEtbvW{3+KjiP5j2ipO)r+?Maa2qLY-|lVy3tct4xb%-Sq{}LvQbE#C|C6(y|W4M zxq2O&1DnPcM+13V;eT4mUOX46lk0ey`P)d^otMymTc!0tL;dl?$A>gClJM#{4$kn+IM>9 z7{$VD%a`^~bto>{&V|TCnjx@f^-}g?6MkP?;GVKvM16vJ80#AwCJ7^6)-9|Yhz`Z; zEu+TUyF{~H`Q5?o|0Lm^w+8WK3UZz)(|mUY~Z@O(v-j|iFG)wJARks B@8AFc delta 2071 zcmV+y2mo!=qy)C5x1R{X{ot3znXUPXJhLNX;Hor+*GBdR=s*Ik;?_xLyc; zyM&S%8ILw8;?t5aY-yC7jn}#hS4>JsC;-xk#|y?zk+%icdBaKmeRMwa>bNK)Fi9)E z7P>rDAsuO<8p?dz4>oi&@_9XJ8m4tIfKn2cWKqfgS#pe6erTc|wLH>KS~ZgFvo${v zMFk2=3(z3RnSb>1b_wVr*%fdP-NfP!^9UJZ)GW7cn|4d6E{C0=A%ePJ2;R}#l8!Tm z$AiqQo}(Vtki!^Hgt}lbO`$$ugEJ&?MRlHK1KnV!02BR4%Yyst=KIy7+V4E1(S_Sp z&zV0{>yVE3)iW9`WG&E110TSY->i*Mg1xlQcu$=A^M9Y6^@Fv1M?qT(+Z}&t20-DH zy#=z}H?d&GtvEOV1%HtIEG;>}9r)~jTaL;#OPeraW-&~low58~x*x9Q7>6I9**=;l zW8%Orb@tMM^9qgZepY5Z;#%KSRs)|Q(Q}7c(W0kC;`HMF!s=08$TW4<$r6q9k*Y;qn z{!nZzOsr|ZhGJlEl*>$E%!?SAkVdu*&6endW!*dH6YKkGF z4*;Y3DDVU`skK8B-oNx_KHWC)Irl59+=ZHrkyUBg#*U^1?5xKs-+ zFrLP8k-bl-M(Dt9iAw<}DLVKXubm<`*6qt!No-6d8}B$sOeCmilTTnQJC5}`g#H;v zy1sq+!X(a#p1+?KN;kra53IL`uz!u(ds>05U-gFSya8+BRLQ(U`PU)84gYyyl6Fq{ zgO|J50V-x;v^10yxR@jO}*DlCsuv|oq9XNGP;k|J{)qmT}p|JL` zRLgWVI-`Uj_HPd`J9=7in_-TWirQ@UDmSg_DEbgULDqPaLG3#`X24&Ip3lLGOiHI} zimAnPhP22xAOy-Cej_DLyw}u#8_8DuV1i$N>8c>2<~tUz#b>nTJnjQUpzMt@FY6DQ zphxo9mgo0(l+03$t7%VP8GkBAG>=Cn8_*pE+;qSS-+~U*5l8h{I`9uguAQ!qJ+1WF zobysS>|}REGqmENwVt&u>iPc=VdX{Nr;gH91aa7tvGQ&?T{bo-pWe;vNXd*3GE5F} zK)Es1MQ(zAnIFWWOOL(fQlW)rB~Q-xZcUw2zUc3Oa(q&Z-{O&DmVZ;JRg9<8NT7!I zCQw_x(4_tb5+A4u>Hn_k`ZhLWbB5sw_y;p zC8+YccI-Q3bpNKil;@$DpqHj{+}spVNNvWHPBhCCd-$AHe}9i$T)^HW8Q3c6Scmo7 z6sNV&P)>)d&G9F-2Y_0GzXS|Uh4kWI4iZaa(jqEhL<)0lP%kA)C&}eH>;W*Ijo)dq z%-WLbye_Ld&#$gAkY>WQ^#qk`%>a*=P5YId@TgEn>W+%~JEsu73qG5<`5CjuY-9C{^8S+}nalraaHNUpwUAxOU&|2?u3lT2iHFGiMS+ zrf`|7b>t#Bg%>(gqd}TuL)<*j%tDi?-U>^O%1AL(=$;Ukx_&e2TqNVm2NhIhz8!|e zMVM#KFS5W;doU?2vbBfJs{Y3qII74Uzoey2Ly}J@0uV608TOv_opXrt{_epLE?fu8 B3hDp= diff --git a/assets/data/tool-ui/path_breakdown.dat b/assets/data/tool-ui/path_breakdown.dat index c5c26680d1f4adcf0507b80c1c018e439d6196a5..a6a323114bcd685d8d9d0af57a6b65ffeb834e1f 100644 GIT binary patch delta 2119 zcmV-N2)Os@5a|$*Ie%xapE*E|g43YiBXZ0qm7LrQs^b|zV|?v5K;9C(pYn<{jWwV> zGYdxUYb7xTk6lP+L9|Bo4Cy?xg|&e@d$b83{Qcb_zy5I@&3|Iz=Y)$-ATfvFw5HN@ z=0yIWf};*SDsaFG%~QDTXwK{S2be5?4hp&C#zfY(m=`#vlBy6`;nl66k3L*6Euh6Si z^DN2{!mF`p|K>80L}8Ork%b&%7FKa@k=+~>&y6MsK2~Q!-Iz7d**Cy#07G;PUXZ2E z#~y2OOa49b#ouU!9MREVtCT6&t_puPaT`lYV#;0C4oloKo@hC1dHji)c3VFzcYk)H zsz&HSjDHc}g-xW~u!ICVY}Gcz=Fl!Z9z6Zu7{l4^!wU=5$7MWHoIYFFe5zWg7jJ^N zId!@3LWR#nb=3}x^UMSYeU2@d`sH4jpC>?fex1(Y%SzmIeeV(%G$zUyI=?AZNj;bx zMqoqil`^90VDf87ww6$vzDa;2X5#U*3I}9VYJUyj$n?e-^j;G!-|QorW(-&YG6OuH zez!==QcS+J*r8wsqD}6I8ihv6=ozK#S`s51yP!0#tlYT}@INfDzA&57a6Q#&wdOAJ zH|vrY19mI^6TKH9V(M7+NoN*nqq@@$)|#SjCNLkLnaum(v95DG$Mhi`fFns;$36Z1 zYk!|;XiPeIN0dzrSbBY^*j6evKt?rUJfgxG>dw}pp^}Vio`{Q__=9gl6nJt^1|v4^ z)}LXBP=7^Z@$*X|?t_xytw1_k5>&Uk6fTx=(TZ+;HUPxlQP%=8GL`KWGV)6pZvglM zete9ulL34w12?hSO(`}9F)yE6IkbP}&3{2{oEh_@1yuj+UKJVaUUg#>pYPwq)pW9L*AuQ5BX}jX$JPHJds2+ z?MLKTB}>cd3jE;&yh9#_%xt zp!yx@`|$s6k(GY`$86{UGq&Mwk~^673+gqR*y|0Prjy+;yWbtJl!B>M>CJP z`D$|BmDHT|dHh*py_2qRZ*=6#hUrnleY#YNxa1_nkr8TUh6gjpiDmo=Kz|yl0*%S{ zf(Ruzhu_GsQnAGBlE9nlycy9G@xG4Scve0Iez`L!6VmWiO%}IB z{*_!*;l$l6J1MT>hu*OpLx1*Lg=ZJ)pWlHCR=e8|rqULsVs&l$q4iZ;mdv#4mY~Rl z&sZU=I=jaie5w#JyGWUgzdNAyhcJM9>hW1+OYJkjGUw@6Mfx=&b{2ZuhrqD8w#czv z#$31Tp-dA+ih(N#q*162Z|ljtxMVndbYf*3jr~}*z9kE}URm+H9e;iz2xshCe-Vsu7k#)X+Q?5&M>2cblBR;nTQY*bQ6Z|6YS+KLo%|h067eox-gf z8kFLzb}(m3rxOMq51SIzKl-94he8EVHeGMC}^cSP!u z_>$H$JtX{(5CPDPn9_Wh_{fjbGQaV;_Gn`pv&93>w;~FJd)g{}2f_AVW(z$`po)EuASvU3+mp*J( x9;AI60X;9j@;}0YrY0A8fY8$6-U9%SmzC*o^`L)kKhE96kdo~R4X~A!ZKAgN3043A delta 2119 zcmV-N2)Os@5a|$*Ie*{o@W-S{uZ18000P41N~?-!nz$V;kjLY?1;x$h$$X}(j@XW;nYyEvkImCdWzAz(*h z%H{hQ%eM}Dd%rP=;2nFcW$7B$XSz&fRV(7g44OPAt+PRXQ-5T-OB{ASlUXNPEb38F>c%(I^#yR(2WJM-|>kIe^#00*)!gem66qt$O%8fm)+U#|fj z|CK-Xl<{_i&wsdc^51FbqEQGwX9rt*Y*|Ln{l&t#b8WoJ4?>{rSlP9%Akq-S{(L6v zvwUYHzEQ5?Up#eLl@#o(+ov%oAhIyzxR~%TNtIYv{Dm!=D{c|InWuL%Y3slH%A2! zH>e1)*B}W|Pr~_6yl<)O?J{@NJKj>u{4gmR}(=5J~GnkFY#rw#9)p8KpD-vAuvvt6xGIf#I5=tdjgHE(x%O}DLCi< z+x9nmL_bG?0IE zfFq+H{H0p&j$9MygE7D^9vm{6Z zTNCOucGfZdXx2PceT}j|*QaPdJT69gl3vpj+c?VAYhwz+`hcroa|r94CGCsvF|LM> zF85i0B;oof!^sm8GQ%|)B#SS?H5Q@c_=gk=kf|3w0;C~LA zZd^_^Zcl}Z-$=YOwLTAoSCci}ozn`XGt<~#N3y$kDXflOjzWEF{pY$M2iRw47}>J~ z4%PUIuD6|+3b&AyWY57AC3oJ$hw=Y?CNzod+uofbwU#tlWnQ6SysHV*q>3C;{RH`T zn)-U=TL?)=9GL=r-#(UBB#We&pMRTKXG#Bvh-7P*L#b^qTrUJmfbNiZgdA2!z$}^7 zWB|_s)&uTexV`}aWhnCMIA?zsf(#|S%8k>wuNmR@FVM*v1feEWXi}3Ao2?sVAxx?S zzRkC1xiOW_q_~eA2U%aZMMyy4Kpdss%Gc*6~0w-tPGqGCbB@k%Jg(Lm1ap`5rY?WwJZY!hcrrSnXGcKGA~#{D>ISqHpo%HNi$*tr=w%BqK8+;!^`1 zi_D}3X4W1wX?QO$)_mQLm{u5X-(ZJ!RHWbGkSzHY+G1XIYourzVXU&ET_-G>c2aU! zz?$k5?=glh@LdNN?1`Qtg0HW~IPSh}ki?$nohu#uv5dPf(s1P-u74gplyk0|@vRKi zk!wv{7p`9Y>7z8qZ%jJ7!k|mJ)Lt~BLnS0{ZT!oWdqj?VK$V*F#+^ z99J>g5k{#yaYO`{4wKlJmj=$qe@5~u@q^P52u>Vq2fTMK z^e{3Mp*dN_p;1Fmh{ZUvKo{<{q%02ubxE*>jR2gC)O5s&LGWTb`AgYzCbpO7aT($q z%zt>R!~oGMXez;76za2Y2*ytnu2)#NMdW~D=&4J|lo$LsyJE(ii)*6n9yUvLX4rh7 zetu=)MT1(V4}UxJdB$1LBp81b=D4RuqHkXZC6o;?W@=od<{mK<7CzxK0Y$Qw+pS!T zl#vlqyx&S-#ksarQmPyUnD1rr(hcz$W2~-dTUvbg*}jO~=fVMFFH%__lC5Bc+97Xk zx|IOHx6|@?!LPXARpzH@#o*-I&|q~=Y95qgh_J!lctG+kvVO%1!L5v^jMLOh9m2Qp xqbTXMbD4ugA$2ZW(T0Yp0o!O0{U~dr*>+CUMD1J%t6f>-M*4xy)>Y`teZ+XWAd>(9 diff --git a/assets/data/tool-ui/path_normalizer.dat b/assets/data/tool-ui/path_normalizer.dat index a6ce35b9774c052f90751daad5c0d3ff0f9703c7..b2c9cab5e6c9656e7da9f6d295c702ebc4604365 100644 GIT binary patch delta 2119 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 D;FOk& delta 1345 zcmV-H1-|;{3g-%tH-GySecGZP;kUiXUY|Q5{u;%_qZ^w)BIX3tW_zY}T;Xr?$qW-T zP*zER+2tZ!%o{Cd7`n@cbh=2Z^cu@+FdXqU)2k&qk9Ylv5~ag#?;j%41(RznYKU6d zbS2J8fP;Y?V|D6x8}>7lssOsN(?)w6o0s}6lS>U7!YrT6PPs)o9jxO2+X_YQ& zqSrJ3Yryx0y?@_vVkAI-(pbqT7gDl08wF1#@y6X_8CAXwPThU3T0d08TIdbGF6W29 z4D@fnm#bN7k(&GWCbGq;iwx4VM?V%gxS z>_z3CGtm#oLd$T|oYOA%XOf-7&t28;@Fv!jmtFQX!GFcXC<(Cn#RQe;WHFRQZYIZt zJS-E6N4@~Cha<>Mw^5gZ)oAZW{PuFbwdqzUNZ?7+VXu-RQPDZT1X{2Rx035n*W{#s zm;=aAaP<+r20L%)HqPxRXGez8|7XneR6*G3mBd-)%`8~~-i5DuH?@8eAkw`vLB!o! z&}H3wH?T$#8qZrxrV)$uwE`WOX=>km0uE`rQ6E^EV2YA8(6g z4K!Ah?%t-0&-5Mvy%hWa7T4Y?*v6Uj?gg29#CqjFeZEPwO#6*|5Ve}Mk@!61JO&*8X}@Llc8c!f20FU1*X`r9aFx@KuZ>VOmZq3qRC!JDWs z3KU}CegA;ygRNnOw;3kJ9wvy6=q)7opMP~kGUpz=1uiFtO5eF_*06Tc{n_{0)q27} z{De{YF}H|3`IH_1oqwHxQ!Nm|*hEGgMX}wRtOR!;X!1{LRTytts`K9qP;PJu`$HZ6qk9n z5__Pcc5a?$H%k+p+*OHgi2S66BwMC_1gyadx@r`a8SaudDB#swC52+0p!g;A Dvz(hP diff --git a/assets/data/tool-ui/pear_ai_dish_recognition.dat b/assets/data/tool-ui/pear_ai_dish_recognition.dat new file mode 100644 index 0000000000000000000000000000000000000000..3cf0eddac4508ac2aaa2dabedad23a1e1b54ab2c GIT binary patch literal 1491 zcmV;^1uXhmO-NN#RY@@d7yxi(VRBz#XOSTLu7R^2wi7utc*J+gO0D2x0%Cb~%t}OV+4hifY?wvcd^yKG7>YB+qf77@ zn4-rCWgbpRiSd<`)ZRI0eBxdsw+Vt<^Q~+l|D*6%X`0>{$a~*0CRNzrj7+%W%yh-w zRrp(2b52Pm7|tU7;opwA&IF~K;4uv zg3Hyd)_$a`AqcZZiP*9GD$250`4()|;{@)N7DPSz<7LRjIbDmi@~%p5U08=S=QMhI z8@H|Bi8EkC;^{6Ses31xK_(U;v&*5Q+x-CGGtN>C-J`mC5pezY6Shg^IAt^qG23mX z=>Sh8IW~mxvo??~V8GWZFf1}dstwlJJ0SzhqNIWwv6cIpwRvJu%5LeQ7XyAniI6}4 zOsMf+v|tE4!sA6bf&hiBJpH<(5vSk{73fMIWm+}p{Qyxr`#-kgouzO}=9W&dYG35P zMzVB|H-<$EG9os$4=5h~6f&}n89ru6E;tNEUuSStxgSq(sd3;ll@8JD~ zJoG9A42!oZ&_XL`z3ckHhNCFZ0 z4I+na)Yg-TB|DnXGZ53fv#0Kg?E5twH7Y}4ZU0|9B(8f2<^aiCF0gqNw(d~ z^_}7s^eRK!8y~lQia)DN1sFR{;(Q^ZrA}T0F;+`x4_xe$XhhSs=d6q_n&4hCwN)yb z-kaO1^x0Z+@DwNeO*^^t%&aTmhDH=6DL{NsqW32d0>eLF8%%q5LF6|?kBV%PQ@J|E z=GwFvX_@SFdUfC^z(MN)aw+u2FXz40xq$t_FkO?MJB#^~6n|@_ER!SmUagS&f5hia z-sv8?phE;Gq5g(32Q%5IF?mKWUqcIj0x{Zq#XoQ9ocAnEGL8GuUB(7W+)+>U7hev& zq}ap0k(lF&`jp8h6?AbgPY)(bpFxW1QD@jpHru0pX7!k417J03Yo?-WdtMj0&UygD zFB&2bf>t2*n7RYM_p5p_I;9gcO`*}Mzqmy0b?-V-OxYZ%WHoEk{sS_T27Cb2jU&>U>aXC225tES6sT-brYlD?D0yTWM t{Te#N^Ovgi_4?07IWc@&3F&b_u3g@yj+!J=+X3{p;_&9X@?2p@D}q1)-O&I5 literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_ai_image_describe.dat b/assets/data/tool-ui/pear_ai_image_describe.dat new file mode 100644 index 0000000000000000000000000000000000000000..6a1079129bfd1d7e647071293aae942313499ac8 GIT binary patch literal 1505 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 IE%}6$hh7}!6#xJL literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_ai_text_safety.dat b/assets/data/tool-ui/pear_ai_text_safety.dat new file mode 100644 index 0000000000000000000000000000000000000000..323fa26e29537974066ba69cb2fbb284b4b56ff9 GIT binary patch literal 1486 zcmV;<1u^(|`yUyzx1;W+t%y5vx=cL6n=QquPAdhf4d7_(dYxosjd zaql@q6_T1+fK40tqzk2Vv<=+?LqTPJViX&?KIm6-Mqs%I+Hl8{@H|`D0OT4rs5Ft_ZK6mFNFAC%-;tj~m zqvuP+FALY{p>y}=NX$$4>F=k}M=}`tyk`3;Mps>Y0|;;L%}i$Ik=wHQCBEFD;4kjr zMW3^1;cb45FWzeqTdt5AX?ktMj9#5*y*4@3{jU<$6+^x}UGV(77NKn6g`g2Nt8reMWWj<~1$9k9S}3uL|hABra`C5Mh#V znWdf~i3`JQR8JS^oIDLtn@;SH{XF5(5h2ywN^(5m>PL+5igf2Evv1Q30_d`JKyEug4?jew%-+L577qQe26SV3 zkPhL&uM_P2Yx%&W&nzY5!Oa7%cl#w3ZQL&y(UtyQiGhlsKUA#P(fib_BZ;j8-s&f7 zKga%x_{rQY-e>)K14UF4h}auZo$q-nU(1N#1M`s#fo?*dZrsq#+^rDXyW{Xqq`?TvUxP))SD%TDa5PYQ3emwn9A1C%G|Kp`Vi zD!NFbr{=lH_a1_fcJ`_-g#0*FxjqZXK2X5m8KBq76&ND{ymQ4tOHjO3F^l#EcU}2C zjFWsE(M3XfofA#)9FL+4+Q@0whCX_N9$bEnwO25d%^$fT_rlAJFX^$|9EV5#Kv-A5 z#4H)XPf}~~i7E2Rro7CwSKWc!kjj;qH>n1Gre)kLjaMO+%g45TYf%I-(-lnelk=Rv z7n$y;tCWzVluT&LAB^HS9$jJ8`nVbIw&5y>7p!7jN&PUqh0RhCleSfh>VcVU( z0bAjlz4xU3qzX|YqsO5?&`2*DOH;G@PrOeD6^k3HbYN|+(^U`faIy+h^)u^F?}KUF zc3I~(&ZFWHhGpyOl1@(6Zx5ebPWR})-9`WWa;3v?yNm3*{FA>b^ZC?dVxt@9s~(?_=|UROO1yIc%$V>%gYI5y`1< zd-t4I;Qw;Xi0&rRJNznFsFBPC*xN3M^LcumulohN#-VK*6X4IZ@s}&|2Vh!8Njnp1 zc8VV3nUfo(g(69^5jn)hN)^*JFBIhH9w7rJn* oNV#>R<^(U-cvbf>s~7UmD6vNU;s2U#UMM$*GRttiO3blyxQspjm;e9( literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_answers_book.dat b/assets/data/tool-ui/pear_answers_book.dat new file mode 100644 index 0000000000000000000000000000000000000000..b8f5f6f32832d85d1dec0c1ed4d9c982e40b5442 GIT binary patch literal 1468 zcmV;t1w;B-O-NN#RY@@d5dd&yVRBz#ZgY2Ka&uo|Z*OZoFWUvCryCTYS?%_f+8pjY zq`xo@+0X?-NX{1!ZG9nUtxypUq=Tb}Ub@9_SYN;|*?>ODw_f^C*VBS96|r7mae69N z7E9EA@}eLFeJvcrEGuKDsArx@6_xQ|Z?&_XwzSf1kLp!UFz9- zES|k(7~)vV!iT~zNjWdNMbqVk<=MF!0(CsK7>5;QEn{H^5G76DAf8Y&gylRMayMe* zl)T!F&}bgKE4KY=P0_Nok48A~lRi64}K%VkSMItMtBa+}t*) zGj_ih7=+U?8zsJgV(@@BJQgyG0>4l2O0K(C4)T!RA=)8->SvOipj!t+^-ifHv^I2OhFfftYe>wrY z7b|ZBEqkc3k75+_WJ;Idw?vbdhaZBl{PuBxUhC7$$g;VWaB<%JMn$?b33 z!y#);rkth_b{dP(R8kJZO7v+Xf43dFbPBuMk}ScRPSQ9z<@b&t(&^2*>!Q`9QzZ?) zm(-#8u+Q1f<#%93o3FY&hB!OYo-o1fb?cdskSUyVB-Ht^qJUW_J}IE_?T_yRoX1s* zyX3W>&$(Cf!VXj}PvMditF1OTwy}m*h$T6^=qS1Y!MzR_fTF4v(P|c5n!T)b=mZCL zslQG$V_BVBbX@gB)auWZh|g`R<)ZYKLLI+k%I>gHo##AUtiBNYJxw(hKq+Z!M!q%{u5#VvGr@Jsuf--ZmPxSal~#tTx@8zJF%egZzh2!aHb{kwtk#yYYrv=-1NkDcEQ#UW(Bc&!o27NPTWH&bsyfgXYd3+ZXe@^my9o@Uq7urYs?jwqJbze zWP|Mo;4s60i0gTB^_lG}ZDYm5S0O7V6dV;3Kc=RLox4$+xPOcZtj7vMq8Kq$ahcYt zP&^ifq}$ew(MpL?kikHT#hfl7L3*D@{`?ypMPw)T4&YK*$YZa$Sl?-?~<2w~XlFi@Xz$sZCAg9afl zbTB~$rcq4rt#COSwpN$Nk)w%c?yY&Y64OZIzaUfFq*MgfB7y)8zOfc;E z$Lr0S$h>*vXRM*-w(U7D`ead+O6*j;%J!bGqpZ+WNeJ{6``m>2dI6_W`TnMr7S_C7 zFzP`a|Bx?#@;b8l&aFTW2&>fD7^{Nrwu!^E@(vRVRLnB39(1NUl82n56{pQ%=9;(R zgM#GoWOvz0KcPQ$&Yk>v5lG+Mp`SN0c&ctz)TAhNFx&?5MVJM&EbLMEw3zi9J`ti| z^}mOQI%^HQOVs_z6@)L{vBVm_`wLmD?|)P7Z)_Z9)Ui$$XjN@^FQGwwcam77)LdZ% zrwFUh&Z(qK{uF&C{O>JA$>N8b}`Uj?9sqct&L%ZsQOcBkLP_`rM%JC#!&9`QBmA{CrwBu&z2!}!;Y+wk` zA${QK1BUN%)NE@Z47RzXyYG*q>Dc|a0YAW)V!)7!tJIMZjQV4BVrrq7?X$nrp!Uhk z8#eVRD~d!iL>{=qS)M%Oj_DTAIN1IO`KC$He@6!yR?JZHZ(F|czE-i$Qs%kE)MWys z-O#s$KV1HuhZk+I!0j2>vKeJ{K=E_VU`i!66ijBvU{)iytAILUixDP1?QM`|c0oQ- zk(+*lB@S5uy|E+-gUz#x3s5=tDT7vxEigPM19*34Lm)prJ^(fwWk<03R^5#Jx*LHQKq}QTzd{ z`n3~IqJ4r24B(qDr;70@bn}A`{{UJ#$qFn@R?w>VOxn#}DUGl@p0{|eL>AHP@zyR z*;YAbhWN&atazbqU-d4he)L7&fQ5+tGn0$k@UCheLa&>8GEpc`*FjDg8eilEsMt}z z&TA%VOpD~#kTiZ;6OE-^fT^s>)sM$*7~n|!pM8kLvIX&Eif(2nK7@y2XPM2o7r?#& zA#6dY1pO0M#tQL6Jtvcp2IW0aioTMwkSqSCG*1Z~6>}c`*gj%XXfWFCI7%eWyS!(j zYA|H|h??kqugI?yh}W7*A-FBL(*GV2th+ZssoA@4Ok8sN>rh{e`ixGst*y{Ob&^2P z-w-3d$=YYz^8D~$p|JA>r;E%NfG=ZxO;cX{0?}QVN&&qwfsFBy{kR{%+Whmp6$;^O z4Q|l`smYi-RGXPP_Vt0u`}|)%RrDa>cLkCjU!cwOo5_Br@iu)zZzWVq5?z9G|V-&$@*6 zp*8rRj`5CQC0%1Ex0c+(_grPzvneuTwCwuLgu~?hm4L)aFGOP83e5n$7P|m(h9!)# zX}bakPHgN$+8h}9;k3p>mY?$b%p`ZD=hte(i|ktem60D2J5nfM3b8D-=*ltM+vpD3MT({vfHFQ<|{Du;XJY_JJo3+rUvYKE4OX%l#x22$Sd@}V&Y zBhz_(TUF;pNu9{Qt|y73kuR$Hd!V5M85^0c$riEBCEc;L{)M83uA$@DDSl7g&wNfr zkWnuANvOY{fxgU__=G^6SU*s)ntnp7?1$_9j+x{C+ob76QdDPpcA&%8GNrtNW1LJJ zy|{q&Vhm~WcXqn0wI~mXfA)qg0#&CAeM1DKVzp{m%GFs+$5H0tX}M!w{p!hg#>u@l W9~!f<{rr74eP4 zPkPLNB^TJhp-QnAe9Vdbk0bD6_t9Pw=qcPW6M{$d4LouODmhG4iFd?LkNhIfRTV$< zO45y8)WlG7QW`=Bc;<^cMLn*hPCW7)sZ9IU1hst8m-FV{Y?OnysLE=x;_^&R`eK+=~2ph+eD`eigJjL`Zs0Qj}i7?OO z?N~y~O|_mxCfYee)2f*?x)>Y0)R7m)>`4+`b-dcUCdr9+sU3L;;?09R|3mQ#ozS|d zxnp5qM(?JX`L_sYV$Him7BSyK2B#m$N$9tPn;8^Yi<)o8n>$RzV0FT@TZE2TzVqCI zhyGId{%UB3)(wx-CnBBwscEBO6hbULoE^Oir{==XU8HZzCcer!YC^VWnf~W^4k-~3 zc%Ru%y+%H^i+4a48fEE#J>Au9pH@zC78NTTDe4QGzCRNhZGe}ppUekE9N{?&zu^gv zxGuJt_W)h$0pI-PeN}FP!-#cYZli;)^;R_Tz;7LBpcaZ|0mq{Dv9$R|MW?q^0oQ2y zxX12YKw&cb{W1ilT%%n>x7ay8SxN1d|+soh9&_h-WwuhPfJ8pB_TNBvdvXRg*fshE9Z7rqHFfzrzNfhAJ#kXjKVye2#-x3kx$Qy;~XP zDd1_hG0gcew|SU0Dj`A#@!68mw=kf{G7XvaXQWLyK4adAf6@TdOj_r2sxtZd`k_OM z{^-tZlzRjN@i~H?_{(7NGLd-V+#3OZ0-6dGqmh)*F@9Zg?KQzSso^hS;Bo(!>W77T zH7D-qEKroqi!xMvg@!{hkhp9Ae`7^t{O5{aK=`SNtt<5{%w~;eu7^TX*_EQYjE<3% zVg<4OK+gBCi-;!mf_XH%mUhsXX8qhhwUUsrO&UJfa@>HE(={+uVS}!`vft}>OVJ2r z66V+_(ZH^UD+1YhbE5V5AqIeLSHOujd&$-6%Pu&gY;sMLlTk4_j4il|fM*wRgG2xA zU^V8Ruh+>h8t)>+zHWEsNH9|z(YT&ziQP^Dl!l4fvqJScY2S>zT0_4W<2(7)`h_d2i$5S`+%~2 zJW3jO1`s75Q&Zu4c~y?f7$6f?hpstH zh@;Z7d-PwN9K|`AUmX=56MqJ-UZ)Z7nqw$@-x6r`)ta;h9H>@wLX-3X<77{KKA{-dKe4rwl0-8bj0{alNSO%v- zC`8N2J^S3z$6d#UW-G1wLE7o;dSTd#Iym52|Hl(q0zbW%)N&X(lw|UUq%W;hhhW=W zfn6c8dfH~LiZ(~3-zoatKX=R;0Ifn?D1%VMEVL1Qaf4mQTLo<7S`I9*@OqQVvj?_X z%)!%cdQPvcZuHGXPz6C~NM78}w!Tr2;*NZ1=;riDnFB9^Rf6A%3k!1+03)#~cf4Rq zq;HX-H=DTD&ue`M1A@NlPvlnQ-BFy^7*Z%|P3)}p6Y<6YjG34k1hTBQ`x8Uf|!|Pp}R!NGx;*y_91v#-;bSeCzozHTeBU$%KZYGK;RoOeE`i1*y7^MML z6ITuF2sl{M@bgfKhl-pE_Jr#^GH~Bq<^w%@^m(lU0QR68-L0;@N!76>Jq}E@qan&c zy!RsE)^IeIem|YzU@V=MYkkTgJH;Eh@v=g($i^aZxHk`KwyYc}%=g`fQ{cVq-@p=2 zqut7^Y{v`X{)SH-dK-E6_rz}R6!c^Zo>3@Te#}OQJ)3FNhGP&>(SUR)FUx0;suo7L zGpU{3#UEjHsL`?7LFjJ z_8^8!7MVa$oZc!r%f+p;AU%ql78PUaMICG_04ycUcdB#_lDB&OAvH|=Ikh;C8>A|c zxf%`9DtF0qD5F;{O8RAKFf$lJVg%x!!c+y?ybUmM%aWOg)7ze-%7e{XvY6d-VX#Ag zj9GPdpF`gn*LC2S;&8@wF}`kJ;@I4;3kNC0i_zh+60m^`gmgzvX#OvJq(k~rH7|?F z*Mm8)#lo71*E~otx1uaA0RXs6pU@X?wfsT!w|3%G{}qKYEdHO)6VHACt%7Wd*gg*H zySHDNlzJLL(+UN8@1zoP5P4preb9@lyMt~G$7q<}5wB#wp-Lb<>ldBBl`tbvw`j)w zir(t$N#@9y4?^<1AvaMFyEiL=!G*9|tG3}78B|CdqX~`}*zd5s4rNgqsD?Tbi|={O z)YS}goNHm~4`Ef$ThsY=p(Sry__$`Q8yz!9JQa7wJbEj$NrmCTZRJGKyXunkXGv6hefSM@Byog;}IAqVvN$6%j=-vAMba_DD#y zOcI(8wl=(_B7JMVnw=w+=+G(kXOBN!_>Hl{*y#)Diuh~u=D+P(2hA>4vbo(>q`5Od zOpL4o4KQhCQX>6yCX~;7(c*W=h#S**%sUmPAx+gbz80ukQK8kSWk}Z#2HlsZ4&e2M z;l!|2G~2g$l-ig^aDl)4sJyK;^4vU>Yia!F>1~Q93FS#8KV@A6etB99(U5#O;o!UIJO^xn^8j>quCHN4vtmCaZy*s`GeA zgCGDcm6EC;{Kt00j#my2nKgwQLjwcC7%@Zn1E*hPZ75u_N7nZW9xS6#pX?|QO+KvU l7-&A4cJC%4vG&O@*+bZPS1nuMxW(&1^Whey93k_UsWgKJPO-NN#RY@@d4*+mwVRBz$Y;SL5UvznJWpcb9vnq^_9O9Mj@Y&3Pl1lOT z6v^{D#TqFGVp<8jL}sSSGK~xwB`3E9E=9@zD-=4k)Xt5#=daZ~!Ba!uk@0~gNVM}?Add`aZz;sRN%Yhn?oc!7;ca>k(+)ATjlgAw8@_pq?! z22M^eh70i@ds`l^JQ2V?T!xnp{sWbjA$5rmjPro&DE^{m9D7%#qnS8p7%>Z0iLnS* zd40_7LUWQ1VI@wVU{*~5NLH2mAY2UsRr$XIh;rAWss5LC}#Hw*F#NH*aQo(%6fP39M`knYjyongmR$@mD@s{#pp)B*QxXn`%DRZ9@2^d8ECh*M?` zm9f}rjPp+VD@n!odpMQglb$jN;VMoC^kwSusTJZ>Pug3G=Cz|=xJt++z$5!H1^IS8 ziwSHfzP4%3%{yRAW?D_=Ny{c(#{=WT<-vKo1Y|B*EZ=Kwqq8QahbtIy8U6|=_ zkXCm9HqtZ5R6kbuF0Qpy?SiFK>p9{5HU|tXf35o_%GFG^ZMVZGSa71UNs>~)Y2_2# zxN~X2Y=gQlxZv5$E8exyXMU{azD|#v{|gSA8BI)SR08SB#>7C(^jCY-zY$1+IPUH& z5tfbe|65sykIFz*;enGjn33`EsDB(#6-4`d!w;2^HiVl}fJai(q@=9C zJhx>JwLN0JpxO)8bXKL=A#vgsrNWJyzF9)76hS6zkxrF(LkT%gEpqX_kS1(28ocD* z=PTtc>OX$zi<94(Z`IEqFlWk%an^jvw4%@MIqTG%BfBL`!`rx>sdkiI&8_sxxV9Ql zVn|gf#q5&~PWPy7k=gr;7z7E`ZS(N`As!CaVIK|)<01uQLVU=pqp_5~!@#|#O9;4i zF}K>H7}I3-XjZ11wqbi;X6XH_rR6s=ganC5f2umcgqE#nP8!X5b;Ol8%`F_!FYPHA zTgGJbfE*>l&I&WUOKS}YJ;TK>dPE(-0DGHUcx_$5{Y>S967^13>v&SR3F31QgkQ?w zUj9>dDjvtq=0F7pkq0+ZcoiZ(qki-VAJeVGe~OXrj(~j*U=^!Ql@&;*Z0v))7Bihg z1qIPyaAVXy&4Ca^1FIyZt2pUB5#RhyCj&-tp(9N(T%&;tNfrj z!38ZCIvojs>6*AH7*T71PtJzKfQ{O&kQVDq+GBD$k)-MJMz~1M5#HXVUDrDqzVfTh zB+;jcQ1R88to2gMY_N`Od@eRw8SNwqVnEo#f`B~%q$&^9GSPp!GsC5~u(r-I%4K(s QOj5)6^d=%}1{uEv+%ah0V*mgE literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_brainteaser.dat b/assets/data/tool-ui/pear_brainteaser.dat new file mode 100644 index 0000000000000000000000000000000000000000..cf1c13d0bef6ec342beb27d7387a944c11af5b66 GIT binary patch literal 1483 zcmV;+1vL6uO-NN#RY@@d5CCvxVRBz$a$#w1bY)?4Wpd8%dd`w2r*rSgH~4To711Gw zq%f2;a=B3}8a!`;`oVAolq!=e&-06Idw&0vDA+{Y760>sl7%s!({t6`(1^JdbJgMn zukEbq#*A_c5H0O7i73az9<2{_#TYavo-#T%`Y3S7+O?g#n9|~NP5I|>II8`hffFRf zgC|3J!*54~^PFprJ^Ipd4g)Ot80iH-6=3)F{t9<@B{K;9>aF=ixCVdjKJ*wk8-V?q zUo$=HeZV`ajY~PU7BPoz!lYP&Egoo!@QoCMjUXuqRIV%4(8O+O&7M;w6l9xT2!IEA zdsJozm|7O*&VP5H1SarXRkcT;70^_~jfLC`sqHU254ww1(q}0fV=&tx;>U^fa@J|u z68zjHbOW`;r9-`p8SpR9Iw5@L5YVYnYan_0GYL%mU?BU-5uNebA~paI(`Ij;N!pCx z-Y09IfwBkQLmF&0anHqD7?4fJJwCvRuG5N>wq$R)nISoZJy2V_ug6+6-9hu-uu0i! z2si@US7KeZxUwq|Ku~R;#Ueb!@5d_CPv@@h0S;-jld;<|%Gp_oMu}4_*?grTsM5=r zYh1-yTgzw3ptOodO1TpFX+8CIx5}K1lln>{^Jm~F-ZUdzHoO(=6lDLfy9(2#5Vi!&`9uNF&x98(Tvu z?t1@l|B`fB+k_lVsQxDEyI+%(0hr~KUN+hHze_4^+?cV4(94JICukJ^7nJMxDfjdb z6^K2ub)bxx8PZ&ys&_w-mEIivwD)Kc=)v4x+o;vahMN3&a4rjc9+uXKLqRaoS{}*W z5X9EBN%8QciL=7&oR83cxo#@X8S`~6GjCW_v`*>Zhz-81BV~t)7u0ErE?K|25Z{Cs z=#l)axd}Kvu@JX0r*53~@PTE$mgZnu(_7kp?DH-~C^Sh-S+WV*_fUGR&|cZwtka%U z#)G_jtk-~b$y%GZ|6C=|xvwyTLvUJ>w7XbYi$(CTh98m?J@*1$YDpCK{viY8*YTc@ z-^y1q97gUEC{T8sSoX$b`^oku5=WGw8>2vJ#H*1Zh4QJ&I_!o(#kD5@jhui8WVO@t zk%$bD4@lEILxtF{8O~(O>=gd%H&KB6aCv22KgY<0m6?59DZkjWDW;^AF_eU$!53Xf zqRb;wS@U}QNv!ml*LdHpbRM^nPWC2kM6&EdWqVxBqK1pnrB%5~b>3~^_u_pIy33>R z!$PaOFZ<=Zjb)8G5>fyP7tKQyJ!C^zQgp9AM$_-i<7oY7WDuBqgDdc%3p7mArl=bL?a>n%BqMegO6VnK_}6& zlIQrjhQh$a4aop$or@`eEG=|1;%!@#!L(r!MM+9+Tt%HO!*NaTp9Q%Y@_KAT6*GOH znLm{ZywmqxN|zpP4j|3~&!XxR%r#g5m`V)dz-w7Ln6B9xYx7j@x zp5pMehYn9&BpB&NCtArf+yL(L_6yPwdz)d1vz#0zE$w^ml&Gi!;?_tQgC8ogCr!zY z{S*NvnD2A@#t~=q*w1RaOeMFi9{dtbRu`6^DzFj!t@{Irh literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_car_price.dat b/assets/data/tool-ui/pear_car_price.dat new file mode 100644 index 0000000000000000000000000000000000000000..35e7128e4d57f65a072d874417defce4f073a638 GIT binary patch literal 1529 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 R@nEV(Q;#8p-Xh_vWCzo3@&<)7iYWg=eqE zL7MlwI=q*k-Xq7}Y@qL24TvXBsrVzkMlFEh@>Jw8^&|^`tBE~Efwls$g+|JJc6U|V z2#OY2wnx8Mf){s8;=exLd6VWBKDYLxlLb~Y-n4c7%!F!%?rHJPw^S~;KKiAH*)i;W zoR&3;sT{(!J`hjpnDhK8$Fe1M0|^Lxh}AHOSHDjewgvaI1g1keeGX~rjfq{X!s=FASlpiw#HP2(RZBIwN zr6u2b|IDu92V|c)Hr(=X1n59ZujF4+#8}w|Bch!9n#H6U04Z9U_@15^3-Qvf7<|b1 z$fc~dcZ?8HkJY!9Sy0wE7?b0nT9;;Ba0BG=fPkJIFhG3n8dYLpQ-Cq&C1!q~cP1Bp zZuyo=i7-{b<^F-HCA3t$_Vu=c&r*E4@eGf$y`G#~@)a}IX&!#@gZ?_OMIL-uTV}f! zxl(cC<8}HA7QU`#9lv&ZA{SEh|JXz1a$PPg5u~QeO`hc%ow#5p z!`+jjU*JzY3}-vTH+*ja!!@c+-Wf^1^4NCl`IBSJh>LZYJuI_G{MZtR5?w0zn)sZO z3UNSZX?siMqMO~%l#3o+Q6dO4rvBzuhH&@YRiV)st3FEigry6SCRM(@%(so+c(pyp zL{|n@?%znSFDPO&$W8HKt}Z4jg6T2S{K=}flV3D)?=%b}0k~s)_ zZ(TC{>VUlmkmixo(R;J?BKV6OV{HEAc4O%wqyUoc1~)}UK7!1O_7>t52QzJMeBPFA_n+pNr`_btWtLR?$MYXJ6Alhr;ngk)>;i|%lU8_wTcqRJ;HSwo Y(p+TjU$fkh21gXxwGnVneU_UAakhHxMgRZ+ literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_classic_joke.dat b/assets/data/tool-ui/pear_classic_joke.dat new file mode 100644 index 0000000000000000000000000000000000000000..0a179e77b1c14c6f01f6cd285a7b9f53fc63693d GIT binary patch literal 1468 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 R1y%va#Fvko$zbVA%0Fa}&Cvh= literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_constellation.dat b/assets/data/tool-ui/pear_constellation.dat new file mode 100644 index 0000000000000000000000000000000000000000..ded931e17921dfd0c0a3545b9ab2aa7893458b0f GIT binary patch literal 1437 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 literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_country_population.dat b/assets/data/tool-ui/pear_country_population.dat new file mode 100644 index 0000000000000000000000000000000000000000..33d4c48c6161b280d87ffdef3ecbeb5be2034c3b GIT binary patch literal 1506 zcmV<81s(cXO-NN#RY@@d7XWZ&VRBz%Z*^{Ta(Q2HZ*X;NVRUJ4ZaT3MA@J|{$jc7{v1CTV_E{3`?u{v&KrES62)Vk3zb?hO9h8bZo6|fHyTKyxjwnX&Rhe!NreU zjb~gN;#O4LI3d3&Y`=`_FPh&&_2k13V*7?R?LqQ!|ZZE+@+>CzHj%p zTr_K)ODI{jWD_EoK-e|{w(hS!fs>dZ@#~>LbxFqH)T*doW)aj(bZ5f(4NN1tNnhnr zr8=}V&oPw{U=ftscno#!p#WTXNQzn+75()WY>3JR;VA`r;gZQv zd$*I+iFR=2kF=1L);9d0;Dr6^WdWK4sWLu+NgrxMxWl1WkJ4Oyw%II}u?;^jVInh^ z$$Oa(N;wv7Q|hN}3{VB{z@%EIHqIakUJgraIlUyL?v{{tV23O>I8s^DyX_yB#Y*HF zc93m~mXeo8W6$6jVck7>cB<$%0CNH{_sf!}z2=v;!0Pf^yW;Bc`0U>s#3WS^`*C#? z!w?1$5Gw((C}-|62)WKh3w%Xul-;Gmj>v^@)WoZI!Ev|AVe|P0;)sORsC>7Oq4a{| zQ_XEC90Du*NkP&Sn6E_T8X14BSAJcO%DrlFC;cnfv7-%CZZM57N>;l@vn;%PHko_A5-{sp|5pj_*iup^O}06Y^KLR)C+%jOTo_D%R3lR{N?l) z&rqeXyOd_ifmoVf(R;p(JIXweE?V(>Vw70Ki@76GSns8FT!m=k3_AGAsnM9ZKW9nB zp-wOI#UjQGLS0GlTz&vMSCBkeNz(pV8)GgIsW9nsYsYMvH>QC!eBcP((Nk#3EZ)61 zN;2T3g!hn=R~kDy!HDI3_41&qOaj2W|GH%+NhjP!a1+KRUn+&{0ZS9MTCdZCLODwt zbramFY#2%+mSZvG1K!go{95lA`5zIV8v($ekzl^8h= z$dy9pUxZPZy>017)N6v9AaZ;Yh*giF%Y^npty28D#h+KKYHdJ+I^ zqrI4Zi}7Mnce7$IXzK)j!@g%jaFsG96oRtUnGm0u7bhGs<7DYDdy?Y<{#``6z9#CS z&%9KIibCFKNO)JhP^1B$aa*IW#mJMtuy=co^x|!L!x7u`e2O~s4+Ox|m&<|cC4cyq I685!t0!fnH3;+NC literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_couplet.dat b/assets/data/tool-ui/pear_couplet.dat new file mode 100644 index 0000000000000000000000000000000000000000..3dd1f5fe232c1247e611c08af5dceeebb46173c6 GIT binary patch literal 1447 zcmV;Y1z7r7O-NN#RY@@d3;=LtVRBz%Z*_2NWpt~g%uc{ccu**>tB2NJCL8h)BWn}6 z;X_We>k)#;-Z^Q9OPyGh4e%rNNOGS}3yt1vObwnt0OYf8G>FYJ3<|c#WZE(qMiGK< zRIWV7*mn3NpUv2D`CZvcbI_7P-69xiq;?Aywk}d4C*KFPW70yKCL93+d6FyErjT9B zBs23J{m@gFv7T3!UV-+87gw8VRZ^jHxRALj^3x2-AP63Z0dnPIr{$0MIx|kT4nM}M zs=-5tz_Q0z^(|1}ucg^J3@6*D7@gY7Hu-KeCXYG=#TVdFc1~U($4IZ}Q*{w8JowBw zM`;;VW%v)BUQ=wlCj>&_M44`$SYf+g3f#}BvZ^HOI_Dq!QR5Ni@l7MJk!n*|7`a9o z-QDfw@#+gx){^Q?I*f)FZ2$`T15VrddEjV5@ek&Kj?CIVJ2d#csnwdkC)%h|52Wdy z{sBMVq2O=f_E$URr|20&V$ttwnqx5iuNA(`XehUa5OE$IX2mB@8(UkQaDGM|EkZ0^ zMl5h1^j+XJo*m{&hd&+%Nik_KXc{U1ix!HCaGjvIcoG9yVn-Jcl3|A zrojqFQebvThxB-7U#oksNRjg-1_AJP6cd+pM-Q7ft&WgVT`teV9dNijwms3PQ=Y;$ zBPif`Eo(JN()?(5@I>p zc+G5VT`jr$CLb@)Km9wJ9pL~#!;)*ej+>9S;kkI8p;BmNuAe8 z!ofD0_CX=ai}s&aTSQxAu{-d=nE9{l=MvZ6mwe*-Y9DJnqIJ1e*VJj8u# zbH!Ig#ml?P_n;qgV37lC+Oo1U*Bi6zrckCd@-UoC0#}a+72y6g^`el=Vrcji;=0*G zNiE{hPK$#J1fNrrRu_Ht3)5TuX|9rY7nwU6UvV@G?sG%t2}-8Ack%k5DQ}uE-lQ0R zp;Ih4R5Yu0p-XSad4S>B9BdK$I;D7=&5=5ydLBiZR4tp`hWtJ)k;hs4xL`x(TKYapwj&&zJp@P< z90mdTxjx~>ZF)|&hOd{O`2!2~JhMCMk1^Mr=rwHRLod-_4krxZxXA^_I(gVq5%flF zX%o?lt9Asn#9Q(OZUkNd9zGSo%sWjj8RoPBvpc2#kTOSG;Otfn{H51TOf4wa}u0JXruflj`}un zQaGJU4O&!RHY%aeA$2W0O<=6#2Rx#IZ$!lmJ6vA22Xd62l@a>Tf_(W=Wizsrd?V;n z{@RLz-ivSvKfh_Z15L$jq=6Jbdd7*bfp;*O9qJ7GJlzq?Q-{D=G2NE?d4+gq4M~i% zQr>D_n?wN*6S*NKEjY=_s!Iv7a5$RhHM3 zlX(9g9Vb^meNW#@4VfS$PbM~g4zeVHTfd-~fq9HteSFxD`KiD)4Hi@Nz6orUr|g#Z Bykh_W literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_daily_60_image.dat b/assets/data/tool-ui/pear_daily_60_image.dat new file mode 100644 index 0000000000000000000000000000000000000000..41e3ebd02724df857318b479c662a0173b1919ee GIT binary patch literal 1486 zcmV;<1u^DO=Wfa5|Z<-mNwn#%wRNqvq zAuMT>IZl`imZMoANru>$3=W8@Bp#k>@xIQAEJro@EYPkdgTmH&;vexI&SX2MF(Rcf z8A!9rlcFR>UI-Czj$JtKa-{qmOY4Aam^(R{ifB*L!QfKxdjGTe*h}KO)!c&(F5d93 zvd0=BgiIhV*ZRN{;`B^m!7t0w@EfgckD@oJuDfe^ZH(I1i1=AMjUvy9u*2>RFO&%V zr+9BVu#w$eceO3e^86vU&9&Lby^xBzQtc&4wm|ZPGtxJ6`af6xtSw|3g}Ahz5q9p> z`8-MRS54K9r<$G8n-|B5p(@^A0*V;xpvF7N695vv%QBZFvvq8{y1{^=J zt!GIcd!Od+Ms|9D+)zkBonM%B`QxZ_!=iR+_L|_Hr(&Ir?VpSnA`uE_kzac++8!jH z?>_>WhDr?9>-#tJt|mQ@tlls6jY+ zhHA+V6BDM(i}=c!MO;?!Rt0}(;&0@Ry36J6n6YLKzJ1F0}hjoNH-5;?Uye;|71KB7R=93cYo1 z8~)X2e3E6NTt7L2LE0o2BH3!uZvGlew(**J`u-0#wCR35S%fR^GDVv88DpwsOkM`=^GEJ!MIfG88PNE){7{L(?z1|YEb z=Ci@P1AwaDnh?Tp;JT9pLf@Ljm5pj@RZ}A6A$9X_lN#^QtiwDhEHzZ7s8Yh|mxDI7#evIWG> z(f6Zxd(sInW70FL=}Xn5_nt330U+CcAh29gSLvr&Dd$itY11f^59WSKqq9!8p?6`- zo5Gx}xu8DFijlHeK%ma-G=7THa?j#o#h~s$k2T%#xDv#n0IXY2z+bfd=HB|PDPJAH z6A-21os6pG*-99VQ9r+=1WEA*plTk5NMRg07WvW~ScbW_Q!-HIBso3#k{~HyrNtwn zK9^7_qkO(1=$K!|i?liEa{4?zZam$02)edH_P9DJTt;?;`i;92z|X#4W%kGvyRCv6Wh03+xxiMOajH`JWRw7nVbNE_OkFRHY4LCblyoa; z^)Y*iBcc<_c?A_pH^~J0khbz^bia2?!Dg<(-2E|geHN$^WbpkxH(VslQ#e{Xp!zCH zZb)j7>4JI=k7;Iki5Swz%jv|F#&PMJ&H^{ysL~=O#fT@=%{qj_0U@N9g%`-(JMwfD z*SG(T4j2nO`3v`G7rI1Q2>n~$$+IZo*D`+&__&;+goF2wxYdT;uv6 zS@Hm~BZ<|k+1=>P%(YPMdC%RucD*t<=b8aJVx?u%K9~%?pD}r{dAqP%WarLUL@=f? zKL+)z6tIYA{%8w6bME9Z|AnaCevQ-(+;%w9wdjC!=ASvL-M}+~?kRKaJ!jxM#O_8C o;Q!@&a|Q#Yak`FADqYJ}L8^#Fc2mV6_=mEy?QqS!s&|-rNFRUf3;+NC literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_dujitang.dat b/assets/data/tool-ui/pear_dujitang.dat new file mode 100644 index 0000000000000000000000000000000000000000..75fef8ff2840d3aa1c6abb8c4457130044d96cf3 GIT binary patch literal 1464 zcmV;p1xNZ>O-NN#RY@@d4FGUuVRBz&b!usJVQy#5-RTXsDBa&n%b*TN+SEP^R4rBR zkIeab%^Xfr<5&>Aybqa2m=4jc~7g_;$cOzsTsRh?pEW>TT@&s4=&I7ZBZtwWi zmp$ZDGxYHVW&DY5Yap2G5SLAcPp}?L2d|Ulu6b!d zD4f+rFvRksWqZF@Fq+{@`S4vIL3|yOe}dE&Hy(s!W}#WF>8&Xcz1W);vuRP#?BWlL zQVRwWP?k_5W~aoeYBcjA$jy{Er@$#7Xh;HTlY-K+5=Y65wsu}_bRjRcXzzCQZIX?Z zf{oEY;LCZRW$6T4dt^-;hocUe1w( zpZu^28M`Qc(mg2@zQOG{N|z7s8ix=6SgaRgIRAAtBP8&l~ z=&-39j3_Ni!@Lq!FAZyVwiTsOr@aW7>2FIZ1YO)Q4VA~{Lwlg5@&Nr7b4SoTsnHcj zUS02RH!R!y?I}2pmpXpl+8*Okl z9K^+73p}LhRh)-pl^S}FFY~uWpS-t$%w*j+Da}|9>;lm-rrLe+}wNmoN0H;mNTlIKOj?P4ng)Cs*zo>uge-eS3j!*<;nQ+$v!VKnZb> zyUrWFSKj`z)0Z^N+JtymNG0&qaQ6I#byw2o*K{2!j|z%B`BS zD3+1uXS?O*Y+jzKsVD!+N04E<$ce@d^OObVhlx8Mn*`oway&{8;9a@`Y2}~WoT{6! z7!MTt8l=i`rJTiq!6p-!F=Osv)388b!@Sae;bew#p^^nyv}4-?Buq|KuwatR%XxKA zWE9(>nS`8G2(|T6nZu=8tR?|zZq-(wbO^+^Rv{nnZSNPzf=^Rwy!!0+#zT2umnY#Z zmd@q{%~=Y;nh>pr&23J@H9okcH^k67e+_rL2*Vhb-0__KM}Y~hOq1$G>;&^o{JA#W ze@IB+wF=k720g9DaCiK@wj<8&ohZ(cV33lHgG_Ma?r<>QA(&7--VEm>%L)U_;knO( zynlJ3;J+w6-^6LZoDF|ek{#uRhiK@~j5lE!VQqwZ z_itMjA58Q3*}X5Y#sg+hpsKjdi>Vf%0|j4c3hLfLi9)A_J&JtS93_2b$T@*JrOrqL0SwlVeN`DDwQs1XZ4lJ4Tr9Jbfy|Iss#y St7%9+{3dR417@>HyC=NZ6xetG literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_embeddings.dat b/assets/data/tool-ui/pear_embeddings.dat new file mode 100644 index 0000000000000000000000000000000000000000..1146c23edd9294422329f7a1e039d70f5332d6ea GIT binary patch literal 1498 zcmV<01tt1fO-NN#RY@@d4*+mwVRBz(ZDM6)WNB_^bMgko2N<)1BDh79HkE-cW8<7G zouCb7fyzuiSi``W!eX=!fIRg4e^OYg_E5T5__^q#FqzPHl*i0Z+)NkOklje?X zeX#O#O?3E!vWQ?ruS*UIqyVZlGm)aYRssni;fetK*zHk%qt9^u!D$V6P-uJRO*Qk4 z7|&Q-mifP~bdkI0Pn(Xj8S6x}KN+@kD;w%mga0@qv2@Ork?^3VXR?e44ey|7NkQPLV_DaI>0e0)RgbgZ1 zBE!s!=kSwL*kMd|4LsI`0bgXrG^U^aO&0labG#x_JVNP$|pET?7iYbpL+C@%i^SsYmd68;!Nb38nc8TOR?+ zG%SQ6vYO0yoaovPyuv&}(dSRQ`QF9!bO7Ue$XXq&hbEB<3;hK1YWbj{S6Wi^kbc}y z|663JC%BEGNQMnj$%aMA41?04?{;4t%4wozco7nU)c$}w%TuRu%$+oEZ7B(HNmfnM zbWo6jzXx87Fm^v}C1z1{us1<`7;&MWX3bP?S~{ubHY~wo!sEhWe&T`=n;1CCgq>Ofz8ZhEC6O&8#P!y@f=o1L02HZRu-$wOHPh+^Y!%I6)4=>5p(zAS3s#ED=WbKk6ffcYXxv<*I7Aq#O|cte zgD+l^9-||!ak=4Qfbn424z)3~r$`I1T>5b}tK@Dy)`MB`jZ!jSTj}+LaLTR#V-8}l z0k3r&UEi~rJ=Zo-8hW*)oyAHbr6z3T1~5g^tS6RlH;~cHtB`a zT0r|aM(+b&k!tGIeiI+JmCanOnypk_HV}GScDU}{60OrhnsG~!O|z|Djz2X(1L9za zNbKkKrfs3wxLM30h{>q+#mnC33!4Z9%r#`6=2m`C1(1#VIGfd309b_MxW_yvkKIYD z%Hs7?FSBanuCKW{SLxv)tauT)dytUriLH*juXRL>B?Y#~Kv#CI;Se3T_qG@|M=Uh| zk?DA}UfhW`QY_+)Zo1qbz?nsf!Y^*ZxXR9|v#fj%Gv+-fp09aDngz$x51$mQmh?AY z3R(!{8U>USZnFR6<*>x7uo$Z~!MU+uvB1H!sfVC@^RfQvdylcrk}_L-OwzU>q-&s$>k8ZMBXIZT395=%(2gjY2;Im14MNI2wyjeLz!->LiP9@44H{vrWjw&xuxO6lVW9fc{J37msoek-p8%!@iQg# A8~^|S literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_exchange_rate.dat b/assets/data/tool-ui/pear_exchange_rate.dat new file mode 100644 index 0000000000000000000000000000000000000000..116845e10bf1ec15fc42ae2edb0372a29f3b953b GIT binary patch literal 1501 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 Uv1slby8SLZuR68vwQ6cUFfvZmH2?qr literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_historical_person.dat b/assets/data/tool-ui/pear_historical_person.dat new file mode 100644 index 0000000000000000000000000000000000000000..aaf65436ed1682b7f706df7d674a41edd5aa2c92 GIT binary patch literal 1521 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 literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_hot_60_image.dat b/assets/data/tool-ui/pear_hot_60_image.dat new file mode 100644 index 0000000000000000000000000000000000000000..53739024977ffd09978cba51c9671683f26faaa3 GIT binary patch literal 1484 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 literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_image_prompt.dat b/assets/data/tool-ui/pear_image_prompt.dat new file mode 100644 index 0000000000000000000000000000000000000000..e1eab1a2a6275fb8e68a0a91e9fa64c1f6078689 GIT binary patch literal 1612 zcmV-S2DABDO-NN#RY@@d5dd&yVRBz-ZDD6+UvP47ZE$ou&qi~W!Cqvp*xZf`#my7c z=EbP-ay8yT{L$@EXwq3(KWHA+vw{Ti@&MQ{MR%!HmKjbk6^TpabHnA{sr{L&otBek@a722Mu zc5K-~Kyge@;V`aedF+2zS zy_4ISmRptrCWE7F04hwPU|ulQD7ef~w1ELBG;JRt16Z*B6NUBtoD1|bZy7fBK^pQg zuQ1lmKh1o3c_1j1#fjZrw?1nBq{CElR@N8=X9r-tXguXwD|C|Xw+yc_BvT)u%GZ;f zbMBH1&3k6LOa**V5@31;5WUey=9PX;9B11d9R#J}PIKO|-bt&0Q8MKhka+^+w{U_R zU6NfCnY|(p3{OZM2?YuPm%&EfVS`CUu|Ok#tjF598Dou2stp+=ZvH_fSv1c)Fa0j+{oFxv}vJ`AeVrhImdAWAZaX0_XQqV5TRO! zKeh<)cl=sk7mc*j0H{l}0N?_~G_gmShz@NX*n#`I0NV_1Kq)K*9IBF~$>ALl&g6Xg zF4M#YgMpRY$SyaX791b(%LPtlGR$yGGR90WT>4H{% zsY&D}T~>0uC&c8Kwlqx@6#7SK%2q6P<6vIT6`tcSH4eSR^4{3OhMsB3tL=K~1S1Ph z)AG~nkF(!iPCZqqWR~%)7$x`X`CgER0U(`y-aiq{G=G}KepIp!7OX>2i7USv?bawu zxoC>`(`LXzidyzEzUClIlpK-Bqj2-M23jyJjPLZ9&MqjV`8352VW~({_IQkM?HN5J z&5hX%=solNmkT$Ayr(kUE3waqjo@V@uny+#*0`{pI#QU}QLBQcLZGviU(xgd1=}tu z9P4hc3=EoQ|M5;zz6?s+^^Mt-vMYoz0|4=8D`Rvp0O{!9 z0FtIg@rrEfkPkoC9e48ux*OCObwhKCr%N-B^o7ut;v%}veZdesosMG9yqKp4(K?h6 z)obiz3vcM6=KzpLsysyz8XA+WaTP{{U~+!D%>Ln|%(U)2UEa|W>z#t9ep#>zVFc@_ z9b(uX=LD7-5+a{g7o`eN!EBS=k5i7Wd^bxL^*i7NFByj|59jUJ@jSx<*Ojb-UQ|(o z&=zvm>+m~|yqpMy#uuL*=eDZE&OSj}Z+ry!uihsSj0OeU5JlUlGbIzRvbxaPe zlE`&qQwTXx`r@U{c&-eq)@GKy`pS}&4m2T1WKwB|38?uAMBpiQ5Av2e%U&y`I56En KKtwbY>2dwBCl9v( literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_ip_details.dat b/assets/data/tool-ui/pear_ip_details.dat new file mode 100644 index 0000000000000000000000000000000000000000..4bba3d1e4b5e03e56fa15b3254986a3706738ffa GIT binary patch literal 1546 zcmV+l2KD(_O-NN#RY@@d4*+mwVRBz-a9?C)bYW?1bLcYWaUR(c0Bq`Trw26VgO=>{ z$8*tXUA>w@b5OeXXTe9yjt9>|Lam!w)(J@)z+-qp5&St90aQ0X>Kb(IIs-7h@Kh~c zIO*XtJ7Kyg1Vw<6!a!@%4k8k2wReb8WeYi~dsRAUWKlEI{si5`SaS zG9ep2fM1ggfWdT6shvY&oGr6HypoO}-(IyaChaM4qFEhipEZ5a_@!j`U5uYUFOxK& zZ&L5;6sns;?&t_&lCjgQeRcejjZ#NxzFZ{leZM(OPV#)Y?pTOs?BH1lY5*kZpP`mC z@IoRZ-IgZRBB^uvCoctRQK1vnQKNF0;j>oM19dwr3#)8G1rgBaHd5agT_2^Fck)(D z!p-wn)E}Cz6cNQ%YS1fK%6Huo;1K6bZ@9YIVoTo`kZdN-dp>+PE<5`m8>()?b%$I_ zaT_46jpVa^6NNkjFkbHUQK1)?T@2yy;`!BflDO!hi3~{nc-D+QY(_T=OG#<6qbtT@ zmsgey(}rT?b`=?($Jr<|4-wo`C>8=fbIyO+sGfnm;9h04LGX?&)BL}wkjz*kj1nE_ zjL;rZcoCeRa_Usw2EN8vcQ%HW5KR)Xq5+(O*d+q|E%FwbZ} zBf=|w!xh5nnlMe@=N&WI(-z|#we-%QKsNGD09(pO@AfY0LD{ZH=GS<-1#nbwC^P;g z-AT3Sv+Uv9!Z?lIm!*-uQUm16m+)~VbaudY-m{NVtSXiclV(vb*U=twj7s7$IH_gK zrqok_jN_a@V-&cgQe$iU`Mt`Qj|PAr_E$0rmMKI}RQ1+)S8@G7Q)#H`x zBI`R6Q2g*$;k+zvb0s;Y|7z1}?o{HS*^~-UGpZP7?|$3{cSE{znsC9O0qKYXIg-^x?dXCeDvMwuhBv+PHdg9S&|=fe0XO_B)eA-U{YU8c<%!mCLslcwGOQ>4($WKVf%kN>C!@6ZL^9eMD5 zGM^^Mr<=ydpYuoL-yce`a^fw+5`$~uC;YSdN3r=`$T*M-9aQ0nqv-cuPyT%QTqMgU zZJxL|UvMp~u#Yu5+wEdFEzU~Nxu*D#L=eX7-1rI7*AtJb1jO?4x$vjL=NZ)@Rap;+ z8p_}3>1kgxLU(_!V@E3y*(?&Wy(G~I+N^6;Xb7;$!?CfsH;TXH1o>UEnaX?#%LDvT zPZ5Sl07URUZ|?}t{WQ$>$F%r4(W=yqEn0LOud?F}ObAgA>ptm~ zSD9!H5ZoH)0vaPH-)q*7^iO{vZ4nY#to$?eScK4f&kt(u<;(aImJZUwkpu<(40D^q zu|}p3nlThRlCyLJ0L}LCY=>%ULOw7g{D8{aZdxpqHzTbkW3zOrrbPII;qYZl%XlAX zD186p7hT$!*#)?&9A@a)Sm-r35_wDsI^v1-30)DiY}F$WTl}aQ%h(sCwpZt8f4h8+ z7zK;|Mj-M-u8k*Lw|a+-M6)3%J0_m8r7!cvSVD{NtZvK$Cri#X4l?+K@2IQhhO5P7 z`}>?u;#s5G19~fGj8D5V)!G`ISW<@h1@q>L~%qaHAlqUW_h1{o$#5LVjr6 z!Mu}B>Y)Z;XWXjpZJ({)J|um&1p&0ubAoRg?Zz=7l1fY>wWl{$m8YvegLB6$T8^}~WWYQo2I35(0mCk#q)3k4H(Z!4AqFdYUVA258L}4_*6yueCLCe!$ wj=_yfhp(xN>Jy}DRDYi-k!{$EaE|VcX|nI+u6ds5R~vn9_20Rh333g@EjGUa$^ZZW literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_keyword_guide.dat b/assets/data/tool-ui/pear_keyword_guide.dat new file mode 100644 index 0000000000000000000000000000000000000000..689f640d17cf234516e2d1d23145c071491c3428 GIT binary patch literal 1485 zcmV;;1v2_sO-NN#RY@@d5&&>zVRBz5EyC_ z9FF99q!NRn(bRuLqDB{f&8{DOR|^MN!Ux%om=HaHet6Er}Oo7%8BTq9=fL!$QZ z_FgEO^zVaZ3*6_&e>^b4 z(67hZI>~ zi@tkpOH3?jvXH!6(q(my0-t&J5I<~RlPM>HzK$_% z3)&{Z!tZSY(_!ml@1mi1XQY|A-KO?hhP8je^UJ)*_OpqBuQj-<9i8S)nZ(Bz!~}-l zE5Xt>0OA&-t+?!dBXyo|RBJ0jU*1R4KzV4G1Ni@7h3*>0!9G=F#=TOzfkRNN@z?V? zVG36(Q~lNu*b9yB0Dm70FwYoX+%2-z=x`8+I?Mm>NT0D1*z>{*Ek9 zB03WU<9HS6lIRvime()Dp>ov{+Dh&z0++Ac%*htkZk7xTP;qtG`7yLvc zTXBYcY!V64LvVA1+HxH8#RI`}(h z3~Z|cpTaK+$V{9|-(d0u#Iyar@4z+NgtKw6E8s1vO>ozCleG@Eb25Sy!)p3@FTK+t ztt<;qvr>Omc$x;m*qj_`m+#MQZak zHiP8u;5#Ie5iOfg;*Tr+zRV?H`aIeSD|j9RVWWrKnM=7RwPwyP&izr-q*zx7wLSUM z7{#7F@@@=<+Gr2rI(daoU2%MtKYK;Gqm+&byD^Vt93eB;Hv$YtIv|ugo*Jxp{8 z6MS0pfFQpmnW$#<26xjs8CR$HUJ_tx9m{7l&Ttc&-4}J$uw@*}*(i3$z;6rT9k&*p zyihSk1#J&;8jJrTbI6*-vIJyf)e9U^xh(JngMt?M-b+-lsRH nSo5PV@y{d!2}I^YJegWzCkGYJEPn9c4DdgP9&jKaOKfhRp5W#O literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_kfc.dat b/assets/data/tool-ui/pear_kfc.dat new file mode 100644 index 0000000000000000000000000000000000000000..c75280826c8c476cadd53b287fed7e48c708e82a GIT binary patch literal 1491 zcmV;^1uXhmO-NN#RY@@d2mo+pVRBzhH7_rrN8bk)ZbI9#E^qpUg6cVRjdhl;03@=A@8Z8ZI4Yz1P)d@pqPE7 z#u{ta3xp_0mSRT?<%F3%3|;*YNoBe{q1#@2XY?e_iN@|7>aW0C8Ab@XKy~$?FdvSF z$#ecEU2W+{p`ix67Y`!+jBr2~jigMjh?ww@r+$Qs!if`tub3HYbpa&hMl;d<*z<&f z&}GzjlM|6h`9g_b+I}_H9*x`6mS1q!1(OSH9kMF28laeHAh9*oJ@W|YJ7+plHCJM7 zuqF}Q!J7_~D(ECV(=35L;HqqZg$_MNav5Cf`~_0_ z!$jg>VJ?rO?~14wU}}JKL!qZgChvuBp5CWN1~{{d#Qt)osFw4*LdD1mz80~F6klMx zdhziU=A#5LBXRUL3>mZ;nc8Lxk;%7jI~c}r2+sbkjGHJQ{6ogqfo5&vpSU( z_I%>*>|akNBJdBV9#@hdAWmZQOX%7)<5;kug%#M<# z1kg4CfaTc>4wFPQCFLQCtm3;rK)~l?s!UVsPYU-YY!|TbqC!K0cW=Y1()_%ELSRo2 z#RH(1Pm3kETYEN?CVx3SC!vdY_Rdh{dpzeD;g%r1FwH8DsOVrJuiijDHN!t9H2-yJ zaa*GpU=r*vQKP|UN@l}m0NU@LQAb?W?Z6+%+LP9!>r8VC);YT<}dNte6 zwcR(mQ+s>&UaD67-70R;?PBM2{19iA_D088-JGK|)&gPpXAv0aMTxA+O-mUKw8UZ( z*!C(@)%lvcbC9}$kEW|qSw_Za()2c|ZU?t6oB5VnaA0d^?D4&L)VtlkwP?Luims(-CS%{bM$Jf^4-x@>u+kh*d>mhL&xhjvGWY^2jf14znB*BE7ZXg*;B!bVBa z3}2Q?p9^{CVnuH;DndS8Un3l;eb@Y|u0j$|(Jtw;&`3G}U`L-=Kg)ckGG#6}iud9q z`}@^JcGtIRhZWw}blp;+DM@;P(-F!2LAwz(t2B-2)yReG|Ff~0(%xT(c(U?NPu6l|L=(jl8RGk8Yrp5${`qcIFpLVKXtf@Q?K0* zgZ_Nz=hkoD2QS02fx)8O{{!&`)+-6HZ)%7R6m9bfBXu$Q*s2;m_t=9-$yh)Q4Oeo{ z_Z=0b+*|RYM!T+^zMMgHixJ05J*bfqwfsKnO7x#0=|6p;q=SZ43;^?@g16)j5sx~Z zW`Mu}+wR1en`a2aGdRkwMS^knaI=wB$}8iqyd3mxN}4jDP%1uxgOOhv3N>>MG`cb! zo}y)CLFS?{x`?UT-Wj+Ut-?(;(3Opknh|bX9hWu`Vnjv>M;g5j3hIoVJR;f%iI%u| t)9xtRmJ?iuCVmSc+lW{VgH~5>auEU}(tb^br&o^4`nvju-zT=u;=i_u`*QY#{yoxPne0Q30mDxqntcp&}Z6U;;-2BW$M`T zORqI-$Fv|QjE1C-woK*eUUQ$H0$oD;RRLDztdz4)xG$M4RI z%quD#1Pnk_X4l~SBdjJs&~(aCo*O*vn^NJX9GryrA@U zQ$l1FH*>Ej`%G%uKO55gQmJJ)(M(?M9?b|4|@efCj#%Y)EI3LAW8+Za!kUX>Cc1t_2?7aY*cl5vOO+CZamq54qpPq_8$ywyDh2w6x*|QYT&KSI?f*=l7yw4+#W~#}3km`J3l% zcxAiKD8m3*?SI{}6djM2hq`x3PR3Vax1{Js=$9>Lg7FaQFJOrtOj?w@WGp=Ma8h7h zq$r0D+5aXTeyx<9eHHu%%S5$qs?W1g;ZOY>%FJy|U!B-_Yr%DzRZIIi#9uex1 z6YY$wlUq*%FNd$2$@frk-TiKGqbtNrzl(G^b3dEaO@7h0_C-k$s=MW{s2kgtAB+h< z1c`7O?$|vLNQITG3n)Z2aPi|Z*TKl}V&}(1GgA zO#O~VULqTodYnt)PT#`qtcdU3(S%Tj zis)UjIO`y&W4Q05qC!&A>C*eq<8WLxAhrwP9?t-euMu;{lY?kIt8xgQ*n;so=MZV1 z=hgD{I45WI VF9u54nmfXqe7kT0Oc@2@SWCzl`Cb43 literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_llm_reader.dat b/assets/data/tool-ui/pear_llm_reader.dat new file mode 100644 index 0000000000000000000000000000000000000000..134a955e0509bc923882b4c44a20b3fb31d30848 GIT binary patch literal 1498 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 RET+pc&*KaUEfUWUF**tL$*2GT literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_love_quote.dat b/assets/data/tool-ui/pear_love_quote.dat new file mode 100644 index 0000000000000000000000000000000000000000..b5e570c0f61fdb3fe8b86b4074b25faed43efcda GIT binary patch literal 1434 zcmV;L1!ekKO-NN#RY@@d4*+mwVRBz=Z+2y0admHWWzzB1b3+&3Q%ODleKENuTa_sB z(ibdGai~HH8FV@H3)A6U@?WTw=Jpq~IUK zI=Ig&X?Wv0YpZH`C(ZcYZS&2+LHf_wpvNh+#i;k8Nn$czs&i^S?TSp%F10``0$z!u zJErAyIc!!Rl}?Y!UDgr@LV=*@Lz8zz0jm(L^>bE($8?Ls(?L4V=j# zoAxai^e=^}11>tolqGoent{9YYaM>qN&N51>FayEIiL1T*R5i(kT&StAe_}YyYL1m zKBFROS99_RSn2T)+@KEMMzx@|28r1*@YpNFF-8LaI`jH?&V3(A&xK#9siq%1g5_x!9rOrE>S}>tkSco_M z)zZMC6FjpCZkybn4ClV#tpJSIB%VjWmgORG(pGTE=joAb!?zn_%+&(WibXD^=+&bt zP%{+jD7AHqVCtmCdR|MCKDWgDy-8vA1s=q5|ni(W9Du)c`OP}*iA{B>_Zg))&#??8WWGQ zP);p&JILAyN?M`2u&C}uC5N@%e^ww&M9NDe@q}h}uic9gBSk-+;zR3t;ibyM3d;T8 ztoY%m0{zlGVZQBmzcIZu4O@Iw_ky%=ZW~1yjf?^i%`rF*WjzdHAHcfhugQVYw9n#(XBv$x^^t~ht)TYvm2bRt-_*Qyv2IFFe-OQh@v>Qo$-6NxK6gq2lKz0`NDRrn* zEd6CzOeFA=z6Pk)hrHDSWbmP)i~yq%#UF`{z#On%Cvb(+G(Y% zf(*3bD&=lc`{Zs_A$nrGdb@5TdV$m?F7mi}G$LPQ)Xs%9eYC4%qt&d8W>8n$c(*9% zjcU{u5N0A87oNJ!t%*N&`>2VAfUd!QUV|BtNh$;oP(Yk#qsCW6rG;xdbw|=meK-)B zu+FLM;U{ndV=<&4mB20QKll0qU6^~T7O-o;3qaxt*1u=qe3swsUG*>)fL?Yh!jZnH@2|d;VAl{0`=(x*oZF!p1?35SebwUXrk;@ z!Wo0*Oh6uSuDaNT{2XVC=EgM>1xGxB)GP? z)O)*?gD;DR@d;kCd literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_love_reply.dat b/assets/data/tool-ui/pear_love_reply.dat new file mode 100644 index 0000000000000000000000000000000000000000..83e533cfa947652891beb620a678ba55d37c154a GIT binary patch literal 1450 zcmV;b1y%Z4O-NN#RY@@d4*+mwVRBz=Z+2y0a%FIAd5VGyXTpKIJYJ)F{P+4>rRZ{kSl50nGb$TGs=q|h6u2U&m_ErJ7LTwWYu z&VsezkFh&nMaH?AN{jO9uVGv-E2hp-i5S)9KLKDduS7Cu1I@lN^o}}N)!_GW=Jkp? z{=w}151`kz5h3{XrR?{g^zDwVgJhUsN+nMoWBIuFAf0?|Hjoo*n4$#`#2hg;rdK5N zO7qhKD%0Pkpk)3wpHUhQhv_b>u`m5JkOzjGO^wW~Uh99hRyf&#w=uuBg98aQ2+8bh zcm*E0f2~$l9O;t4-5M(oqqO@}qaPV2C+ocy^=7VonJS}S@k&k)0sub*Zj7W%2iQL3 z;-xKEn!k_~_Cj`$&GAiMcf10t&?yyOY`v&&X(rlQ*ND$aQ$p7Sfm0aeUOSwfeb~U? z__swelhWat^heM&nB6B4m8>M7QVZG={22dG1PYXb3y_>6UV#=;E-`{2LPwOTQE@`A zc_&IymHvh^GJaNwB~h9IEUz~jMfsORnFgDQyM7JslmNJ=7_;Dvc59=(pguni9$deqVBCWwV zC2F+c2W6+>Or$9xi7s-?wZlB`5VYAl}du@(>!9&aQW-5x`TRJ2qr(-d<4>^3gpPVOz zeVXaKFEkaU=?0v15w=AwL}!Ddm018SuOFVlx8#VwCg;rh^axMWCh1La2zds#TWV0v zj+W0j4>w3}#ZIJ^K@e}1!~@jD%xlVjyDdb6f#e3&H2h8+{ooy@@FS@P?;J{ugE}jT zkFsdNaS)zFbNdjxXE}SBMG#IkZ0v6PAzT6}3cF@gtAiP$(Y_c-?{F39O-@r1LOZDo)ttQKe8G&vH+;^Wwh?r|wCypBZgTJ3J`>1gQLU`aZvh9G< z;`8fznM@aGKBFfdJPbjlhrIo?;F~aM1+Vfhd>}xZONZG3IOzr{DG=+oEo9p)L(jD> z*n1X4m)@!Vv0X55IfUGV>IFd7g(G%j%a+Cf68>gqvllD#FJZ5X=EAAf*Xss){`J`q zmQ2^GI_0Aj!n{QtqA_prt4bpco5AX;fo2!0)@bAA;9Ww7bwj8n-a&gvMRC>9_xTQ( E+`Wnpe#b7f(2V`!rW+qK}*%fxBEb*<#P=Prd@ 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 RuP2h_s8ONb#FvO$* zo5?O|(bPk3InLa&06+s$dk~`Vq{y8wMJM^MmTT#lbh$6cV5fLh+pd(ap~x-<&guU_9lW zcW?3=hUwRddj%jm-AW9QE1 zj_05Tcw`kH{5Xa6>Px0Hm4|$P-9b3Xx(>Bg;>cy7mk(PU=(Hz>g-n-|oxsYDB!GvX z11!6U#p}^|^C^?dll-fRONYE7g25ht$i+eYAl30(-4s-{nL0omVwZyL(s!*5>LW?X zuj0FR8L^4M`G@r_FJ&mSN13l9dTi0%xUU8FyB^sGP?QykPihx@`Q&9K>)@bguL8X7 z#}bR2Z-`@^w4MN{fta=_^$iG1R?0p@m_R-!#*{W7;l93dp{G(%2UB#6{wCYNRO?I4 zU)sq<{2D864PD`90)?#TE)!h{Cz4*ipnzg42X(j(1}*nShZmJJmpU=(Rde= zB>9{~aTf1B*H!typFlm!^&4Eqz(k{B4r#NFCXMA)%W_-sF(6LWltUUNzM&C(4lkp- zAW=RqDKJf8eIb3%+W*G)zUgj7^<_k!rE?+9B}u@xU>0?pdc=?fsCd#8CNP?L9ePt+ z4Ie8*!-@MQ51}8eHNW9Ew4PHmk{VgESq~L~rhZ`z48@WlB;jb*8`uh(?`6xiV5DKJ#V{-MtlOm=zqlJNnYT7F7iNS%ydE7jBz*q%P zgaUkknnLzZ6ps*HNFiku4I}a!j;i?IKfkit3l}u+GYTLxV)pF z_i%9NI^@HlSOOi^TVs040R^xHNQ#Mw9dU8Wr-Mjk3lHLmbH8fL07vmveTeA}1eJ$u z*avzrIgrkgI4(o#2ItpXVK>(Ud+-tu$typ&TmE4u?yua z-6HQ4^5z(_p&l8K7^Gvha3n&JKTxkWe-;qz1Ld1Wqr6tVVEy?ez`4IT=#E=68yIzc?W%5KyLC}mC&5^?&t?{?2`XKr3${yS8YV}w6tlK3HG%4J01JJS zrTo0l8aLi_If;7At04r7&>DA_Eh&co#m>;2)SUI`%HJm;5;z teZI)*f#J@pzfocdVrr|v{FjQ-p+I=W<*g8>nmAO=ILH>{3{ebFzlc@P)QA88 literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_poem.dat b/assets/data/tool-ui/pear_poem.dat new file mode 100644 index 0000000000000000000000000000000000000000..5170368ce0f117cb38d226e4a0a72e2dc10c1e71 GIT binary patch literal 1492 zcmV;_1uOblO-NN#RY@@d2>@_qVRBz^Z)I)!+~oYG?;K!UPos#8`FJ@qsYK_u??LYv zmZ!e-+^zs`3xY454P8w%Ki76UQ{TB{;D|}n z5{nIUPEznA`jHgY(6qd`Vvu;8{_Nsh=^NyJ{&^r?q|l&Rt(h5WHC8iT{oayn*A^1f z5?FNhW9a%-I0#R_joO|R^Oj|T;*QRVBnwe-2yoOo-+=zY<;-FLBh3Xdi}3-D#QO^v zhkCFbt>30j6D8L5`xmj`IYBjaaAPj9>q)U2gY^9LHvR>FA4_71Hq*JO##eq1RT-@TZGfbedQ>5PvSwwnm|QFH_7DOMJHnV_Taa zmeD~*{n3GCMP%V@`pOw#e4Yd3atN<0EYsgSMCetC2F_#r-g(rO$aq`IOnN)JmnOl0 znAeV<4h)lW?;aR$r%SVK7E&_cTHUr5WcG&dndZ4xvhMcN6Q`gNHD;aZy>>!M4u0)A{b4l)y;lgGp0K<%cgqz71@*2f`AMiD z=*NPAd?3aZ>GD!;rmv+)3LROM9b?(HT)Y*52+6;mY+_0_3EA*Somuw>6+}p9x0e~N zHArxo{oQ$I*TcBA2Rh_O6>5&y;dhpC`B;3BsE>q@E$d(Rq?nSFK3mwi# z$%+NM62XXq7_QTrnh_ysiPemTMG|T-p)m(MGYwv^{i76BZn`~y&ldTX$7WeA+C(eH zSwt?E%U1ZVg~B4PE&qhy%a0B$sQwk{Z9k_F1`-on?IiJ1?gx2Oyh5kF1U)m_dWii? z;{-!>dXXv!UhzAzpgOT&+>6UxJV9BBXiXCejvZ136KNIgRY2%Dz-}nDZ(w#)H*|22 z@0!yQ5+-|v)vdPGS)%(~B)m4#it-{sh!1tkF$NVcC~D(lpC836~w{<5t8M#9$@bKn?=p3->~|Y#gj|gMrZfP}eN<8Rv9`K7dfp?E9Q)!{VdA}MJK8V$YI#tx#Cp`0X|^TtY)_jDm$%;hI0 zc?@e4y@;ht$s9fg>H;Hp!|IaWTHh1>$72WUC54OMWacSlF8yLSfPiM;Imz9auXXL~4>sn=&6UxBs`Gdx= zLQ}wt^xs9r3sprc=6sQPM9|fvpwL0P+lsaq03|Y;^THY5M|m=A`Kaq2))c*?nn0F` zLycx)@L*$a1CDxEDKB<4)D2Ihwa>^~tc2bfEOYrhu18F3lIwdbXDIYkjfQP&heaXW zTG?|dH>V>#wI#s_Lrm{J7q~TEj literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_qq_level_image.dat b/assets/data/tool-ui/pear_qq_level_image.dat new file mode 100644 index 0000000000000000000000000000000000000000..49308f0c34851857c6dcb4413fd4fc163523209f GIT binary patch literal 1518 zcmVDO=Wu&(Ujk@(%`q+p+ya%_i zTeua)H%*oFWvvs|fS?67H``xOeO)~S--t2(OuP+i_W0>*e{=PR<~t6tb9?RX!g+W_ zbR@0YoM{w{HNA^M_+WqW{4NJ6UtYB8xT1|z6ywt$NF!A%9$wdgbgLx{DX>qb8p*H< zHWVUdTY%x@{7|Ids$`n-VlR07F$NN`qD}>I&yg8CQ~`jOZr!g1ujEh1sBm?up7@`p zcp@@j^_u#L6IgG3e$6V~#l4gLpJVtup(IWS)|-w+c*nUvY8=y5LJ_v&*#^Gi&c@Nb zpob)$yO0&vlPI>iuj6*|HIxDc>VchG?@_N5NWaWDdu(uuB=|gF_&CX z7swe`d-yq%JoSE5HZ=RfM;z35uR#-lUINqRtpZ@UdtO&X((Ji{`A9l=`xwCP2$)7_ zV7HeKqFA*wcN)P=bp8U8ipA*c6ZQ3UlGVT-?x5vqRB3;SY~Gff^r6$-(0_t~d+rA% z+rOrdH_2X4H~2_n$^71Hn4Z~^!nDwX_-1XqlS!`Cb!5xT1D04Z^UYHKNV4fP8jq94 ztQNLgO(zG+kyM3SODqJ0z)Ti@p%E*nb4==oW2Q9$+6Fwed$M}ikvHQ&2?YI|Q*$O& z8QQ(Enso8|<6(nwX~k4*>~28Jv#0sXqon*4BI3(cFMc*eE977ef%IU7x;|||Kq(J; z!#?RTv4e^*dui&=NVW47`^g<*DHEBp7%RO@(*Se4oLblvXWf|qZM$66Mo)dWe`*ph zt$`f@M8|)S{p`^VDD@V*G370PYC<%`wKr=2j<2n%4{J{x`GH$?@U4iRkwT!_qgh>iyYs; z^C%ex^!EAuqZi7$OKqz!o_xz>4DnN}vzw_dN>orqjFcX~Fh1>s85P=vjEacjM^Q%n ziN(l4ok&m}4E2pqEJ_M_et*aV=sg9JLQD>n9Fo)t9EBvVMa4AN4oX7f$t1sWHpTCE!q;#%*#yy2aW#$XaNyayB95=R|C6hHOgqElSvMpU6;C2b|) zc+OwzjpT3s`w}|K+j-2=@X~jSl!oCbtEP2>#dqA6duZlmv6E2>Y z!yO7!c*plPAYX`D6EW1cdj1kg8xYa@af;Hno%lVz{4uV9YHs8Lqb*! zZ6Yb+{&}Dfb3$3ekE%-rw>6gRYWk@TP(pFq%1`VN4y5N z#!6ch#dR@W0JXIKTiZLO)4l0mU7m~DDZxHLGD8M%y0%Jzmcx;|)4>~4Xlz-s*A(`n z=HG`Z-{|-ysWhZ&UJ*t`hqbtu3JNhbgy3?Jk)v>|GI@t0nJ4s)CPD?-KsFm4PmpsP zJk^fgi&m6xv|r^|yZ9`u@91khllmaX)cnLn2ArDL#~2x>f94T%XJR>g+3=blZ>2mh U5x1<72AnaEUyNdZc*mW*B2Jn1cK`qY literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_question_search.dat b/assets/data/tool-ui/pear_question_search.dat new file mode 100644 index 0000000000000000000000000000000000000000..969041e1a5ec36cd26c0a51a9914c5744928e4bd GIT binary patch literal 1503 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
    V=Xr5G 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
    V=Xr5G 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%0DLbFOxa-xC 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 diff --git a/assets/icons/app_icon.png b/assets/icons/app_icon.png index 55ce8df536278c43a4f955cdac8d26a9226dab0c..96bda836145af5a6a999a63a3875e213494c1bc3 100644 GIT binary patch literal 8457 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 literal 9797 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 alTDJbOL~{yO!+TqN?ln;sY$^)^8Wy^juZp{ diff --git a/assets/icons/icon.png b/assets/icons/icon.png index 55ce8df536278c43a4f955cdac8d26a9226dab0c..96bda836145af5a6a999a63a3875e213494c1bc3 100644 GIT binary patch literal 8457 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 literal 9797 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 alTDJbOL~{yO!+TqN?ln;sY$^)^8Wy^juZp{ diff --git a/installer/ymhut_box_winui.iss b/installer/ymhut_box_winui.iss index f1b3590..c5a0975 100644 --- a/installer/ymhut_box_winui.iss +++ b/installer/ymhut_box_winui.iss @@ -82,6 +82,7 @@ CloseApplicationsFilter={#MyAppExeName} #endif RestartApplications=no UninstallDisplayIcon={app}\{#MyAppExeName} +UninstallFilesDir={app}\Runtime\uninstall-engine [Languages] Name: "chinesesimp"; MessagesFile: "{#ChineseMessagesFile}" @@ -162,6 +163,7 @@ Name: "desktopicon"; Description: "{cm:DesktopIcon}"; GroupDescription: "{cm:Sho Name: "startmenuicon"; Description: "{cm:StartMenuIcon}"; GroupDescription: "{cm:ShortcutGroup}"; Flags: unchecked Name: "autostart"; Description: "{cm:AutoStart}"; GroupDescription: "{cm:StartupGroup}"; Flags: unchecked Name: "launchapp"; Description: "{cm:LaunchApp}"; GroupDescription: "{cm:StartupGroup}"; Flags: checkedonce +Name: "cleancache"; Description: "{cm:CleanCache}"; GroupDescription: "{cm:MaintenanceGroup}"; Flags: unchecked [Files] Source: "{#PayloadDir}\*"; DestDir: "{app}"; Excludes: "*.pri"; Flags: ignoreversion recursesubdirs createallsubdirs; BeforeInstall: LogCurrentExtractFile @@ -178,50 +180,6 @@ Name: "{app}\data" Name: "{app}\FeedbackPackages"; Permissions: users-modify Name: "{app}\data\legacy-imports" -[InstallDelete] -Type: filesandordirs; Name: "{app}\resources\lang" -Type: filesandordirs; Name: "{app}\lang" -#if Int(QAIsolated) == 0 -Type: filesandordirs; Name: "{localappdata}\YMhut Box\WinUI\Runtime" -Type: filesandordirs; Name: "{localappdata}\YMhut Box\WinUI\runtime" -Type: filesandordirs; Name: "{localappdata}\YMhut Box\WinUI\Runtimes" -Type: filesandordirs; Name: "{localappdata}\YMhut Box\WinUI\runtimes" -Type: filesandordirs; Name: "{localappdata}\YMhut Box\WinUI\Tools" -Type: filesandordirs; Name: "{localappdata}\YMhut Box\WinUI\Metadata" -Type: filesandordirs; Name: "{localappdata}\YMhut Box\Runtime" -Type: filesandordirs; Name: "{localappdata}\YMhut Box\runtime" -Type: filesandordirs; Name: "{localappdata}\YMhut Box\Tools" -Type: filesandordirs; Name: "{localappdata}\YMhut Box\Metadata" -Type: filesandordirs; Name: "{localappdata}\ymhut_box\Runtime" -Type: filesandordirs; Name: "{localappdata}\ymhut_box\runtime" -Type: filesandordirs; Name: "{localappdata}\ymhut_box\Tools" -Type: filesandordirs; Name: "{localappdata}\ymhut_box\Metadata" -Type: filesandordirs; Name: "{localappdata}\YMhut Box\cache"; Check: ShouldCleanCache -Type: filesandordirs; Name: "{userappdata}\YMhut Box\cache"; Check: ShouldCleanCache -Type: filesandordirs; Name: "{localappdata}\ymhut_box\cache"; Check: ShouldCleanCache -Type: filesandordirs; Name: "{userappdata}\ymhut_box\cache"; Check: ShouldCleanCache -#endif -Type: files; Name: "{app}\*.winmd" -Type: files; Name: "{app}\*.pdb" -Type: files; Name: "{app}\workloads*.json" -Type: files; Name: "{app}\installer-layout.txt" -Type: files; Name: "{app}\config\installer-layout.dat" -Type: files; Name: "{app}\config\installer-required-files.dat" -Type: files; Name: "{app}\Assets\data\reference-data.dat" -Type: files; Name: "{app}\YMhut.Box.Worker.exe" -Type: files; Name: "{app}\YMhut.Box.Worker.dll" -Type: files; Name: "{app}\YMhut.Box.Worker.deps.json" -Type: files; Name: "{app}\YMhut.Box.Worker.runtimeconfig.json" -Type: files; Name: "{app}\YMhut.Box.PluginHost.exe" -Type: files; Name: "{app}\YMhut.Box.PluginHost.dll" -Type: files; Name: "{app}\YMhut.Box.PluginHost.deps.json" -Type: files; Name: "{app}\YMhut.Box.PluginHost.runtimeconfig.json" -Type: filesandordirs; Name: "{app}\updater" -Type: files; Name: "{app}\YMhut.Box.Updater.exe" -Type: files; Name: "{app}\YMhut.Box.Updater.dll" -Type: files; Name: "{app}\YMhut.Box.Updater.deps.json" -Type: files; Name: "{app}\YMhut.Box.Updater.runtimeconfig.json" - [Icons] Name: "{userprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: startmenuicon Name: "{userdesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon @@ -265,6 +223,9 @@ var InstallOutputPendingLineCount: Integer; InstallOutputBuffer: string; LastExtractFileName: string; + OldPayloadFiles: TStringList; + NewPayloadFiles: TStringList; + LegacyBackupDir: string; function SendMessage(hWnd: Longint; Msg: Longint; wParam: Longint; lParam: Longint): Longint; external 'SendMessageW@user32.dll stdcall'; @@ -326,7 +287,7 @@ end; function ShouldCleanCache(): Boolean; begin - Result := True; + Result := WizardIsTaskSelected('cleancache'); end; function DetectExistingInstallDir(): string; @@ -373,9 +334,13 @@ end; procedure LayoutInstallOutputMemo(); forward; procedure ScrollInstallOutputToBottom(); forward; +procedure CaptureOldPayloadManifest(); forward; +procedure FinalizeLegacyInstallLayout(); forward; procedure InitializeWizard; begin + OldPayloadFiles := TStringList.Create; + NewPayloadFiles := TStringList.Create; DownloadPage := CreateDownloadPage(SetupMessage(msgWizardPreparing), SetupMessage(msgPreparingDesc), nil); DownloadPage.ShowBaseNameInsteadOfUrl := True; ExistingInstallDir := DetectExistingInstallDir(); @@ -902,37 +867,109 @@ begin end; end; -function ShouldPreserveAppEntry(const Name: string): Boolean; -var - LowerName: string; +function NormalizeManifestEntry(const Value: string): string; begin - LowerName := Lowercase(Name); - Result := - (LowerName = 'data') or - (LowerName = 'feedbackpackages') or - (Pos('unins', LowerName) = 1); + Result := Trim(Value); + StringChangeEx(Result, '/', '\', True); + while (Length(Result) > 0) and (Result[1] = '\') do + Delete(Result, 1, 1); + Result := Lowercase(Result); + if (Result = '') or (Result = '..') or + (Pos('..\', Result) > 0) or (Pos('\..', Result) > 0) or + (Pos(':', Result) > 0) then + Result := ''; end; -procedure CleanOldApplicationPayload(const DirName: string); +procedure LoadInstallManifestFiles(const FileName: string; Files: TStringList); var - FindRec: TFindRec; - EntryPath: string; + Lines: TStringList; + I: Integer; + Entry: string; + InFiles: Boolean; begin - if not DirExists(DirName) then + Files.Clear; + if not FileExists(FileName) then Exit; - if FindFirst(AddBackslash(DirName) + '*', FindRec) then + Lines := TStringList.Create; + try + Lines.LoadFromFile(FileName); + InFiles := False; + for I := 0 to Lines.Count - 1 do + begin + Entry := Trim(Lines[I]); + if (Length(Entry) > 1) and (Entry[1] = '[') then + begin + InFiles := CompareText(Entry, '[Files]') = 0; + Continue; + end; + + if InFiles then + begin + Entry := NormalizeManifestEntry(Entry); + if (Entry <> '') and (Files.IndexOf(Entry) < 0) then + Files.Add(Entry); + end; + end; + finally + Lines.Free; + end; +end; + +function ManifestContains(Files: TStringList; const RelativePath: string): Boolean; +var + Entry: string; +begin + Entry := NormalizeManifestEntry(RelativePath); + Result := (Entry <> '') and (Files.IndexOf(Entry) >= 0); +end; + +function IsPreservedInstallPath(const RelativePath: string): Boolean; +var + Entry: string; +begin + Entry := NormalizeManifestEntry(RelativePath); + Result := + (Entry = 'data') or (Pos('data\', Entry) = 1) or + (Entry = 'feedbackpackages') or (Pos('feedbackpackages\', Entry) = 1) or + (Entry = 'config\install-manifest.ini') or + (Entry = 'unins000.exe') or + (Entry = 'runtime\uninstall-engine') or + (Pos('runtime\uninstall-engine\', Entry) = 1); +end; + +function RelativeInstallPath(const AppDir, FullPath: string): string; +begin + Result := ''; + if Pos(Lowercase(AddBackslash(AppDir)), Lowercase(FullPath)) <> 1 then + Exit; + Result := NormalizeManifestEntry(Copy(FullPath, Length(AddBackslash(AppDir)) + 1, Length(FullPath))); +end; + +procedure CaptureOldPayloadManifest(); +var + ManifestPath: string; +begin + if OldPayloadFiles = nil then + Exit; + ManifestPath := AddBackslash(WizardDirValue) + 'config\install-manifest.ini'; + LoadInstallManifestFiles(ManifestPath, OldPayloadFiles); + Log(Format('Captured %d files from the previous install manifest.', [OldPayloadFiles.Count])); +end; + +function HasToolUiPayload(const AppDir: string): Boolean; +var + FindRec: TFindRec; +begin + Result := False; + if FindFirst(AddBackslash(AppDir) + 'Assets\data\tool-ui\*.dat', FindRec) then begin try repeat - if (FindRec.Name <> '.') and (FindRec.Name <> '..') and - (not ShouldPreserveAppEntry(FindRec.Name)) then + if (FindRec.Attributes and DirectoryAttribute) = 0 then begin - EntryPath := AddBackslash(DirName) + FindRec.Name; - if ((FindRec.Attributes and DirectoryAttribute) <> 0) then - DelTree(EntryPath, True, True, True) - else - DeleteFile(EntryPath); + Result := True; + Exit; end; until not FindNext(FindRec); finally @@ -941,21 +978,169 @@ begin end; end; -procedure CleanLegacyInstallLayout(); +procedure VerifyNewApplicationPayload(const AppDir: string); +var + ManifestPath: string; +begin + ManifestPath := AddBackslash(AppDir) + 'config\install-manifest.ini'; + LoadInstallManifestFiles(ManifestPath, NewPayloadFiles); + if NewPayloadFiles.Count = 0 then + RaiseException('The new install manifest is missing or empty. Legacy files were not changed.'); + + if not FileExists(AddBackslash(AppDir) + '{#MyAppExeName}') or + not FileExists(AddBackslash(AppDir) + 'YMhutBox.dll') or + not FileExists(AddBackslash(AppDir) + 'Assets\runtime-assets.dat') or + not FileExists(AddBackslash(AppDir) + 'Assets\data\ymhut-data.ybin') or + not FileExists(AddBackslash(AppDir) + 'music-api\node.exe') or + not FileExists(AddBackslash(AppDir) + 'music-api\api\ymhut-sidecar.js') or + not FileExists(AddBackslash(AppDir) + 'music-api\api\pnpm-lock.yaml') or + not FileExists(AddBackslash(AppDir) + 'music-api\api\LICENSE') or + not FileExists(AddBackslash(AppDir) + 'unins000.exe') or + not FileExists(AddBackslash(AppDir) + 'Runtime\uninstall-engine\unins000.exe') or + not FileExists(AddBackslash(AppDir) + 'Runtime\uninstall-engine\unins000.dat') or + not HasToolUiPayload(AppDir) then + RaiseException('The new application payload is incomplete. Legacy files were not changed.'); +end; + +procedure RegisterCustomUninstallEntry(const AppDir: string); +var + UninstallKey: string; + UninstallCommand: string; + QuietUninstallCommand: string; +begin + UninstallKey := 'Software\Microsoft\Windows\CurrentVersion\Uninstall\' + '{#MyAppId}' + '_is1'; + UninstallCommand := '"' + AddBackslash(AppDir) + 'unins000.exe" /UNINSTALL /INSTALLDIR="' + AppDir + '"'; + QuietUninstallCommand := UninstallCommand + ' /VERYSILENT /NORESTART'; + + if IsAdminInstallMode then + begin + RegWriteStringValue(HKLM64, UninstallKey, 'UninstallString', UninstallCommand); + RegWriteStringValue(HKLM64, UninstallKey, 'QuietUninstallString', QuietUninstallCommand); + end + else + begin + RegWriteStringValue(HKCU, UninstallKey, 'UninstallString', UninstallCommand); + RegWriteStringValue(HKCU, UninstallKey, 'QuietUninstallString', QuietUninstallCommand); + end; + Log('Registered the YMhut Box uninstall bootstrap.'); +end; + +procedure DeleteKnownObsoletePayload(const AppDir: string); +var + I: Integer; + RelativePath: string; + FullPath: string; +begin + for I := 0 to OldPayloadFiles.Count - 1 do + begin + RelativePath := OldPayloadFiles[I]; + if (not ManifestContains(NewPayloadFiles, RelativePath)) and + (not IsPreservedInstallPath(RelativePath)) then + begin + FullPath := AddBackslash(AppDir) + RelativePath; + if FileExists(FullPath) then + begin + if DeleteFile(FullPath) then + Log('Removed obsolete payload file: ' + RelativePath) + else + Log('Unable to remove obsolete payload file: ' + RelativePath); + end; + end; + end; +end; + +procedure QuarantineLegacyFile(const AppDir, FullPath, RelativePath: string); +var + TargetPath: string; +begin + if LegacyBackupDir = '' then + begin + LegacyBackupDir := AddBackslash(AppDir) + 'data\legacy-imports\program-backup-' + + GetDateTimeString('yyyymmdd-hhnnss', '', ''); + end; + + TargetPath := AddBackslash(LegacyBackupDir) + RelativePath; + ForceDirectories(ExtractFileDir(TargetPath)); + if FileExists(TargetPath) then + TargetPath := TargetPath + '.old'; + + if RenameFile(FullPath, TargetPath) or + (CopyFile(FullPath, TargetPath, False) and DeleteFile(FullPath)) then + Log('Preserved unknown legacy file: ' + RelativePath) + else + Log('Unable to preserve unknown legacy file: ' + RelativePath); +end; + +procedure QuarantineUnknownLegacyFiles(const AppDir, CurrentDir: string); +var + FindRec: TFindRec; + FullPath: string; + RelativePath: string; +begin + if not DirExists(CurrentDir) then + Exit; + + if FindFirst(AddBackslash(CurrentDir) + '*', FindRec) then + begin + try + repeat + if (FindRec.Name <> '.') and (FindRec.Name <> '..') then + begin + FullPath := AddBackslash(CurrentDir) + FindRec.Name; + RelativePath := RelativeInstallPath(AppDir, FullPath); + if (RelativePath <> '') and (not IsPreservedInstallPath(RelativePath)) then + begin + if (FindRec.Attributes and DirectoryAttribute) <> 0 then + begin + QuarantineUnknownLegacyFiles(AppDir, FullPath); + RemoveDir(FullPath); + end + else if (not ManifestContains(NewPayloadFiles, RelativePath)) and + (not ManifestContains(OldPayloadFiles, RelativePath)) then + QuarantineLegacyFile(AppDir, FullPath, RelativePath); + end; + end; + until not FindNext(FindRec); + finally + FindClose(FindRec); + end; + end; +end; + +procedure CleanLegacyRuntimeAndCache(); +begin +#if Int(QAIsolated) == 0 + DelTree(ExpandConstant('{localappdata}\YMhut Box\WinUI\Runtime'), True, True, True); + DelTree(ExpandConstant('{localappdata}\YMhut Box\WinUI\Runtimes'), True, True, True); + DelTree(ExpandConstant('{localappdata}\YMhut Box\WinUI\Tools'), True, True, True); + DelTree(ExpandConstant('{localappdata}\YMhut Box\WinUI\Metadata'), True, True, True); + DelTree(ExpandConstant('{localappdata}\YMhut Box\Runtime'), True, True, True); + DelTree(ExpandConstant('{localappdata}\YMhut Box\Tools'), True, True, True); + DelTree(ExpandConstant('{localappdata}\YMhut Box\Metadata'), True, True, True); + DelTree(ExpandConstant('{localappdata}\ymhut_box\Runtime'), True, True, True); + DelTree(ExpandConstant('{localappdata}\ymhut_box\Tools'), True, True, True); + DelTree(ExpandConstant('{localappdata}\ymhut_box\Metadata'), True, True, True); + if ShouldCleanCache() then + begin + DelTree(ExpandConstant('{localappdata}\YMhut Box\cache'), True, True, True); + DelTree(ExpandConstant('{userappdata}\YMhut Box\cache'), True, True, True); + DelTree(ExpandConstant('{localappdata}\ymhut_box\cache'), True, True, True); + DelTree(ExpandConstant('{userappdata}\ymhut_box\cache'), True, True, True); + end; +#endif +end; + +procedure FinalizeLegacyInstallLayout(); var AppDir: string; begin AppDir := ExpandConstant('{app}'); - CleanOldApplicationPayload(AppDir); - DeleteFilesByPattern(AppDir, '*.winmd', True); - DeleteFilesByPattern(AppDir, '*.pdb', True); - DeleteFilesByPattern(AppDir, 'workloads*.json', True); - DeleteFilesByPattern(AddBackslash(AppDir) + 'Assets\data', '*.json', True); - DeleteFile(AddBackslash(AppDir) + 'installer-layout.txt'); - DeleteFile(AddBackslash(AppDir) + 'config\installer-layout.dat'); - DeleteFile(AddBackslash(AppDir) + 'config\installer-required-files.dat'); - DeleteFile(AddBackslash(AppDir) + 'Assets\data\reference-data.dat'); - CleanCultureFolders(AppDir); + VerifyNewApplicationPayload(AppDir); + if OldPayloadFiles.Count > 0 then + DeleteKnownObsoletePayload(AppDir) + else + QuarantineUnknownLegacyFiles(AppDir, AppDir); + CleanLegacyRuntimeAndCache(); end; function PrepareToInstall(var NeedsRestart: Boolean): string; @@ -978,6 +1163,8 @@ begin Exit; end; + CaptureOldPayloadManifest(); + try if IsWebView2Installed() then LogBootstrapEvent('DEPENDENCY', 'ready|' + GetCustomMessageValue('WebView2RuntimeName')) @@ -1028,8 +1215,6 @@ begin LastInstallProgressPercent := -1; LastExtractFileName := ''; LogBootstrapEvent('STAGE', 'files'); - AppendInstallOutput(CustomMessage('InstallOutputClean')); - CleanLegacyInstallLayout(); AppendInstallOutput(CustomMessage('InstallOutputExtract')); end else if CurStep = ssPostInstall then @@ -1037,6 +1222,8 @@ begin FlushInstallOutput(); LogBootstrapEvent('STAGE', 'finalize'); AppendInstallOutput(CustomMessage('InstallOutputPostInstall')); + FinalizeLegacyInstallLayout(); + RegisterCustomUninstallEntry(ExpandConstant('{app}')); #if Int(QAIsolated) == 0 MigrateLegacyData(); #endif @@ -1044,6 +1231,14 @@ begin end; end; +procedure DeinitializeSetup(); +begin + if OldPayloadFiles <> nil then + OldPayloadFiles.Free; + if NewPayloadFiles <> nil then + NewPayloadFiles.Free; +end; + procedure CurInstallProgressChanged(CurProgress, MaxProgress: Integer); var ProgressPercent: Integer; diff --git a/scripts/build-winui.ps1 b/scripts/build-winui.ps1 index ad28815..2716399 100644 --- a/scripts/build-winui.ps1 +++ b/scripts/build-winui.ps1 @@ -41,6 +41,7 @@ $ServerPublicRoot = Join-Path $Root 'server\update\public' $ServerDownloadRoot = Join-Path $ServerPublicRoot 'downloads' $ToolStateRoot = Join-Path $Root '.cache\tool_state' $NuGetRoot = Join-Path $Root '.cache\nuget' +$BuildTempRoot = Join-Path $Root '.cache\build-temp' $TauriHostRoot = Join-Path $Root 'src\YMhut.Box.PluginTauriHost\src-tauri' $RepositoryCargoHome = Join-Path $Root '.cache\rust-toolchain\cargo' $RepositoryRustupHome = Join-Path $Root '.cache\rust-toolchain\rustup' @@ -324,7 +325,10 @@ function Ensure-TauriPluginHost { return $executable } - Write-Warning 'Cargo was not found, so the optional Tauri plugin host will not be included. Install the Rust stable MSVC toolchain to build ExternalRuntime support.' + if ($Configuration -ieq 'Release') { + throw 'Cargo was not found and no previously built Release Tauri host is available. Release packages require the bundled plugin host.' + } + Write-Warning 'Cargo was not found, so the optional Debug Tauri plugin host will not be included.' return $null } @@ -516,6 +520,12 @@ function Save-ScaledLogo { } function Ensure-MsixAssets { + $iconScript = Join-Path $Root 'scripts\generate-app-icons.ps1' + & $iconScript -Root $Root + if (-not $?) { + throw 'Application icon generation failed.' + } + $sourceIcon = Join-Path $Root 'assets\icons\app_icon.png' if (-not (Test-Path -LiteralPath $sourceIcon)) { throw "MSIX source icon was not found: $sourceIcon" @@ -527,6 +537,18 @@ function Ensure-MsixAssets { Save-ScaledLogo $sourceIcon (Join-Path $ProjectAssets 'Square150x150Logo.png') 150 150 16 '#00FFFFFF' Save-ScaledLogo $sourceIcon (Join-Path $ProjectAssets 'LockScreenLogo.png') 70 70 8 '#00FFFFFF' Save-ScaledLogo $sourceIcon (Join-Path $ProjectAssets 'Wide310x150Logo.png') 310 150 24 '#F5F6F7' -Wordmark + + $iconPath = Join-Path $ProjectAssets 'app_icon.ico' + $bytes = [IO.File]::ReadAllBytes($iconPath) + $count = [BitConverter]::ToUInt16($bytes, 4) + $sizes = for ($index = 0; $index -lt $count; $index++) { + $value = $bytes[6 + ($index * 16)] + if ($value -eq 0) { 256 } else { [int] $value } + } + $missing = @(16, 20, 24, 32, 40, 48, 64, 96, 128, 256) | Where-Object { $_ -notin $sizes } + if ($missing.Count -gt 0) { + throw "Application icon is missing DPI frames: $($missing -join ', ')" + } } function Ensure-LocalDeveloperCertificate { @@ -712,7 +734,13 @@ function Write-LayoutManifests([string] $Directory) { $configDir = Join-Path $Directory 'config' New-Directory $configDir - $required = @($files | Where-Object { $_ -in @('YMhutBox.exe', 'YMhutBox.dll', 'WebView2Loader.dll') }) + $required = @($files | Where-Object { $_ -in @( + 'YMhutBox.exe', + 'YMhutBox.dll', + 'WebView2Loader.dll', + 'Assets/runtime-assets.dat', + 'Assets/data/ymhut-data.ybin' + ) }) if ($required.Count -eq 0) { $required = @('YMhutBox.exe') } @@ -720,6 +748,7 @@ function Write-LayoutManifests([string] $Directory) { $manifest = [System.Collections.Generic.List[string]]::new() if ($versionInfo) { $manifest.Add('[Release]') + $manifest.Add('ManifestVersion=2') $manifest.Add("Version=$($versionInfo.Version)") $manifest.Add("Build=$($versionInfo.Build)") $manifest.Add("Channel=$($versionInfo.Channel)") @@ -1097,6 +1126,7 @@ function Normalize-PublishLayout([string] $Directory) { Remove-RootHelperDuplicates $Directory Assert-UnpackagedLanguageResourcesInLang $Directory Assert-NoDevelopmentArtifacts $Directory + Assert-AuthenticatedAssetLayout $Directory } function Assert-UnpackagedLanguageResourcesInLang([string] $Directory) { @@ -1274,8 +1304,14 @@ function Assert-ToolUiPayload([string] $Directory) { } $files = @(Get-ChildItem -LiteralPath $folder -Filter '*.dat' -File -ErrorAction SilentlyContinue) - if ($files.Count -lt 202) { - throw "Release tool UI payload is incomplete in '$Directory': expected at least 202 .dat definitions, found $($files.Count)" + $expectedFolder = Join-Path $Root 'assets\data\tool-ui' + $expectedNames = @(Get-ChildItem -LiteralPath $expectedFolder -Filter '*.dat' -File -ErrorAction SilentlyContinue | + ForEach-Object Name | Sort-Object) + $actualNames = @($files | ForEach-Object Name | Sort-Object) + $difference = @(Compare-Object -ReferenceObject $expectedNames -DifferenceObject $actualNames) + if ($expectedNames.Count -eq 0 -or $difference.Count -gt 0) { + $details = $difference | ForEach-Object { "$($_.SideIndicator) $($_.InputObject)" } + throw "Release tool UI payload does not exactly match the repository definitions in '$Directory': $($details -join ', ')" } foreach ($file in $files) { @@ -1286,6 +1322,47 @@ function Assert-ToolUiPayload([string] $Directory) { } } +function Assert-AuthenticatedAssetLayout([string] $Directory, [switch] $AllowMsixLogos) { + $assetsRoot = Join-Path $Directory 'Assets' + $runtimePackage = Join-Path $assetsRoot 'runtime-assets.dat' + $referencePackage = Join-Path $assetsRoot 'data\ymhut-data.ybin' + foreach ($package in @($runtimePackage, $referencePackage)) { + if (-not (Test-Path -LiteralPath $package -PathType Leaf)) { + throw "Authenticated asset package is missing from '$Directory': $package" + } + + $bytes = [IO.File]::ReadAllBytes($package) + if ($bytes.Length -lt 97 -or [Text.Encoding]::ASCII.GetString($bytes, 0, 8) -ne 'YMHUTAS2' -or $bytes[8] -ne 2) { + throw "Authenticated asset package has an invalid header: $package" + } + } + + $allowedPng = if ($AllowMsixLogos) { + @( + 'Assets/StoreLogo.png', + 'Assets/Square44x44Logo.png', + 'Assets/Square150x150Logo.png', + 'Assets/Wide310x150Logo.png' + ) + } else { @() } + $blockedExtensions = @( + '.bmp', '.css', '.csv', '.gif', '.glb', '.gltf', '.htm', '.html', '.ico', + '.jpeg', '.jpg', '.js', '.json', '.mjs', '.otf', '.svg', '.ttf', '.wasm', + '.webp', '.woff', '.woff2', '.xls', '.xlsx' + ) + $blocked = @(Get-ChildItem -LiteralPath $assetsRoot -Recurse -File -ErrorAction SilentlyContinue | Where-Object { + $relative = 'Assets/' + ($_.FullName.Substring($assetsRoot.Length).TrimStart('\', '/') -replace '\\', '/') + ($blockedExtensions -contains $_.Extension.ToLowerInvariant()) -or + ($_.Extension -ieq '.png' -and $allowedPng -notcontains $relative) + }) + if ($blocked.Count -gt 0) { + $relativeList = $blocked | ForEach-Object { + 'Assets/' + ($_.FullName.Substring($assetsRoot.Length).TrimStart('\', '/') -replace '\\', '/') + } + throw "Publish Assets contains replaceable plaintext static files: $($relativeList -join ', ')" + } +} + function Copy-PublishToLatest { Stop-ProcessesFromDirectory $LatestRoot Reset-DirectoryInsideRepo $LatestRoot @@ -1293,6 +1370,7 @@ function Copy-PublishToLatest { Normalize-PublishLayout $LatestRoot Assert-MusicApiPayload $LatestRoot Assert-ToolUiPayload $LatestRoot + Assert-AuthenticatedAssetLayout $LatestRoot Write-LayoutManifests $LatestRoot } @@ -1305,6 +1383,7 @@ function Publish-UnpackagedApp([object] $VersionInfo) { '--self-contained', 'true', '--no-restore', '-p:WindowsPackageType=None', + '-p:GenerateAppxPackageOnBuild=false', '-p:PublishSingleFile=false', "-p:AssemblyVersion=$($VersionInfo.PackageVersion)", "-p:FileVersion=$($VersionInfo.PackageVersion)", @@ -1314,6 +1393,7 @@ function Publish-UnpackagedApp([object] $VersionInfo) { Normalize-PublishLayout $PublishRoot Assert-MusicApiPayload $PublishRoot Assert-ToolUiPayload $PublishRoot + Assert-AuthenticatedAssetLayout $PublishRoot Assert-PerMonitorV2Manifest (Join-Path $PublishRoot 'YMhutBox.exe') Write-LayoutManifests $PublishRoot Copy-PublishToLatest @@ -1387,6 +1467,39 @@ function Build-InstallerBootstrap([object] $VersionInfo, [string] $SignTool) { Invoke-ToolQuiet $setupPath @('/WINDOWSELFTEST') 'WinUI installer window navigation self-test failed' " Installer window self-test: $setupPath" } +function Build-UninstallerBootstrap([object] $VersionInfo, [string] $SignTool) { + $bootstrapRoot = Join-Path $Root 'build\winui\uninstaller-bootstrap' + Reset-DirectoryInsideRepo $bootstrapRoot + Invoke-DotNet @( + 'publish', $InstallerBootstrapProject, + '-c', $Configuration, + '-r', 'win-x64', + '--self-contained', 'true', + '--no-restore', + '-p:BootstrapMode=Uninstall', + '-p:AssemblyName=unins000', + "-p:Version=$($VersionInfo.PackageVersion)", + "-p:FileVersion=$($VersionInfo.PackageVersion)", + "-p:InformationalVersion=$($VersionInfo.PackageVersion)", + '-o', $bootstrapRoot + ) + + $bootstrap = Join-Path $bootstrapRoot 'unins000.exe' + if (-not (Test-Path -LiteralPath $bootstrap -PathType Leaf)) { + throw "WinUI uninstaller bootstrap was not produced: $bootstrap" + } + if ($SignTool) { + Sign-Artifact $SignTool $bootstrap + } + Assert-PerMonitorV2Manifest $bootstrap + + foreach ($payloadRoot in @($PublishRoot, $LatestRoot)) { + Copy-Item -LiteralPath $bootstrap -Destination (Join-Path $payloadRoot 'unins000.exe') -Force + Write-LayoutManifests $payloadRoot + } + Write-Host " Uninstaller bootstrap: $(Join-Path $LatestRoot 'unins000.exe')" +} + function Wait-FileWritable([string] $Path, [int] $Attempts = 20, [int] $DelayMilliseconds = 250) { for ($attempt = 1; $attempt -le $Attempts; $attempt++) { $stream = $null @@ -1501,8 +1614,11 @@ function Build-MsixPackage([object] $VersionInfo, [string] $MakeAppx, [string] $ Reset-DirectoryInsideRepo $MsixStageRoot Copy-Item -Path (Join-Path $PublishRoot '*') -Destination $MsixStageRoot -Recurse -Force + Remove-Item -LiteralPath (Join-Path $MsixStageRoot 'unins000.exe') -Force -ErrorAction SilentlyContinue + Write-LayoutManifests $MsixStageRoot Assert-MusicApiPayload $MsixStageRoot Assert-ToolUiPayload $MsixStageRoot + Assert-AuthenticatedAssetLayout $MsixStageRoot Assert-PerMonitorV2Manifest (Join-Path $MsixStageRoot 'YMhutBox.exe') Expand-SatelliteResourcePackages $MsixStageRoot -RemovePackages Restore-LangResourceLayoutForMsix $MsixStageRoot @@ -1516,7 +1632,10 @@ function Build-MsixPackage([object] $VersionInfo, [string] $MakeAppx, [string] $ $stageAssets = Join-Path $MsixStageRoot 'Assets' New-Directory $stageAssets - Copy-Item -Path (Join-Path $ProjectAssets '*') -Destination $stageAssets -Recurse -Force + foreach ($logo in @('StoreLogo.png', 'Square44x44Logo.png', 'Square150x150Logo.png', 'Wide310x150Logo.png')) { + Copy-Item -LiteralPath (Join-Path $ProjectAssets $logo) -Destination (Join-Path $stageAssets $logo) -Force + } + Assert-AuthenticatedAssetLayout $MsixStageRoot -AllowMsixLogos Repair-MsixStageThirdPartyPayloads Invoke-ToolQuiet $MakeAppx @('pack', '/d', $MsixStageRoot, '/p', $msixPath, '/o') 'MakeAppx packaging failed' " MSIX package: $msixPath" @@ -1599,10 +1718,15 @@ pause New-Directory $NuGetRoot New-Directory $OutputRoot +New-Directory $BuildTempRoot $env:DOTNET_CLI_HOME = Join-Path $ToolStateRoot 'dotnet' $env:NUGET_PACKAGES = $NuGetRoot $env:DOTNET_CLI_TELEMETRY_OPTOUT = '1' +$env:TEMP = $BuildTempRoot +$env:TMP = $BuildTempRoot +$env:DOTNET_BUNDLE_EXTRACT_BASE_DIR = Join-Path $BuildTempRoot 'dotnet-bundle' New-Directory $env:DOTNET_CLI_HOME +New-Directory $env:DOTNET_BUNDLE_EXTRACT_BASE_DIR $versionInfo = Get-VersionInfo $makeAppx = Find-WindowsSdkTool 'MakeAppx.exe' @@ -1637,12 +1761,26 @@ foreach ($ridProject in @($Project, $InstallerBootstrapProject)) { } Publish-UnpackagedApp $versionInfo +Build-UninstallerBootstrap $versionInfo $signTool if ($tauriHostExecutable) { $publishedTauriHost = Join-Path $PublishRoot 'tauri-host\ymhut-box-plugin-tauri-host.exe' if (-not (Test-Path -LiteralPath $publishedTauriHost)) { throw "The Tauri plugin host was built but was not included in the publish payload: $publishedTauriHost" } } + $tauriRuntimeFiles = @( + 'tauri-host\runtime.json', + 'tauri-host\template.ymtemplate', + 'tauri-host\LICENSES.txt', + 'tauri-host\template\dist\index.html', + 'tauri-host\template\README.md' + ) +foreach ($relative in $tauriRuntimeFiles) { + $runtimeFile = Join-Path $PublishRoot $relative + if (-not (Test-Path -LiteralPath $runtimeFile -PathType Leaf)) { + throw "The bundled Tauri runtime dependency is missing from the publish payload: $runtimeFile" + } +} if (($Target -in @('exe', 'both')) -and -not $SkipExe) { $exeBuilt = Build-InnoInstaller $versionInfo $signTool -AllowMissingCompiler:($Target -eq 'both') diff --git a/scripts/generate-app-icons.ps1 b/scripts/generate-app-icons.ps1 new file mode 100644 index 0000000..8847a32 --- /dev/null +++ b/scripts/generate-app-icons.ps1 @@ -0,0 +1,187 @@ +[CmdletBinding()] +param( + [string] $Root = (Split-Path -Parent $PSScriptRoot) +) + +$ErrorActionPreference = 'Stop' +Add-Type -AssemblyName System.Drawing + +$sourcePath = Join-Path $Root 'assets\icons\app_icon.png' +if (-not (Test-Path -LiteralPath $sourcePath -PathType Leaf)) { + throw "App icon source was not found: $sourcePath" +} + +function New-ResizedBitmap { + param( + [Drawing.Image] $Source, + [int] $Width, + [int] $Height, + [int] $Padding = 0, + [Drawing.Color] $Background = [Drawing.Color]::Transparent, + [switch] $SharpenSmallAlpha + ) + + $bitmap = [Drawing.Bitmap]::new($Width, $Height, [Drawing.Imaging.PixelFormat]::Format32bppArgb) + $graphics = [Drawing.Graphics]::FromImage($bitmap) + try { + $graphics.CompositingMode = [Drawing.Drawing2D.CompositingMode]::SourceCopy + $graphics.CompositingQuality = [Drawing.Drawing2D.CompositingQuality]::HighQuality + $graphics.InterpolationMode = [Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic + $graphics.PixelOffsetMode = [Drawing.Drawing2D.PixelOffsetMode]::HighQuality + $graphics.SmoothingMode = [Drawing.Drawing2D.SmoothingMode]::HighQuality + $graphics.Clear($Background) + + $availableWidth = $Width - (2 * $Padding) + $availableHeight = $Height - (2 * $Padding) + $scale = [Math]::Min($availableWidth / $Source.Width, $availableHeight / $Source.Height) + $drawWidth = [Math]::Max(1, [int][Math]::Round($Source.Width * $scale)) + $drawHeight = [Math]::Max(1, [int][Math]::Round($Source.Height * $scale)) + $drawX = [int][Math]::Floor(($Width - $drawWidth) / 2) + $drawY = [int][Math]::Floor(($Height - $drawHeight) / 2) + $attributes = [Drawing.Imaging.ImageAttributes]::new() + try { + $attributes.SetWrapMode([Drawing.Drawing2D.WrapMode]::TileFlipXY) + $graphics.DrawImage( + $Source, + [Drawing.Rectangle]::new($drawX, $drawY, $drawWidth, $drawHeight), + 0, + 0, + $Source.Width, + $Source.Height, + [Drawing.GraphicsUnit]::Pixel, + $attributes) + } finally { + $attributes.Dispose() + } + } finally { + $graphics.Dispose() + } + + if ($SharpenSmallAlpha) { + for ($y = 0; $y -lt $Height; $y++) { + for ($x = 0; $x -lt $Width; $x++) { + $color = $bitmap.GetPixel($x, $y) + if ($color.A -le 10) { + $bitmap.SetPixel($x, $y, [Drawing.Color]::Transparent) + } else { + $alpha = if ($color.A -ge 244) { 255 } else { [Math]::Min(255, [int](($color.A - 10) * 255 / 234)) } + $bitmap.SetPixel($x, $y, [Drawing.Color]::FromArgb($alpha, 0, 114, 255)) + } + } + } + } + + return $bitmap +} + +function Get-PngBytes([Drawing.Bitmap] $Bitmap) { + $stream = [IO.MemoryStream]::new() + try { + $Bitmap.Save($stream, [Drawing.Imaging.ImageFormat]::Png) + return $stream.ToArray() + } finally { + $stream.Dispose() + } +} + +function Write-PngIconFile([string] $Path, [hashtable] $Frames) { + $orderedSizes = @($Frames.Keys | ForEach-Object { [int] $_ } | Sort-Object) + $headerSize = 6 + (16 * $orderedSizes.Count) + $offset = $headerSize + $stream = [IO.MemoryStream]::new() + $writer = [IO.BinaryWriter]::new($stream) + try { + $writer.Write([uint16] 0) + $writer.Write([uint16] 1) + $writer.Write([uint16] $orderedSizes.Count) + foreach ($size in $orderedSizes) { + $bytes = [byte[]] $Frames[$size] + $writer.Write([byte] $(if ($size -eq 256) { 0 } else { $size })) + $writer.Write([byte] $(if ($size -eq 256) { 0 } else { $size })) + $writer.Write([byte] 0) + $writer.Write([byte] 0) + $writer.Write([uint16] 1) + $writer.Write([uint16] 32) + $writer.Write([uint32] $bytes.Length) + $writer.Write([uint32] $offset) + $offset += $bytes.Length + } + foreach ($size in $orderedSizes) { + $writer.Write([byte[]] $Frames[$size]) + } + $writer.Flush() + $directory = Split-Path -Parent $Path + if ($directory) { [IO.Directory]::CreateDirectory($directory) | Out-Null } + [IO.File]::WriteAllBytes($Path, $stream.ToArray()) + } finally { + $writer.Dispose() + $stream.Dispose() + } +} + +function Save-Logo { + param( + [Drawing.Image] $Source, + [string] $Path, + [int] $Width, + [int] $Height, + [int] $Padding, + [Drawing.Color] $Background = [Drawing.Color]::Transparent + ) + $bitmap = New-ResizedBitmap $Source $Width $Height $Padding $Background + try { + [IO.Directory]::CreateDirectory((Split-Path -Parent $Path)) | Out-Null + $bitmap.Save($Path, [Drawing.Imaging.ImageFormat]::Png) + } finally { + $bitmap.Dispose() + } +} + +$loaded = [Drawing.Bitmap]::FromFile($sourcePath) +try { + $master = [Drawing.Bitmap]::new($loaded) +} finally { + $loaded.Dispose() +} + +try { + $frames = @{} + foreach ($size in @(16, 20, 24, 32, 40, 48, 64, 96, 128, 256)) { + $frame = New-ResizedBitmap $master $size $size 0 ([Drawing.Color]::Transparent) -SharpenSmallAlpha:($size -le 24) + try { + $frames[$size] = Get-PngBytes $frame + } finally { + $frame.Dispose() + } + } + + $iconTargets = @( + (Join-Path $Root 'assets\icon.ico'), + (Join-Path $Root 'assets\icons\app_icon.ico'), + (Join-Path $Root 'src\box-winUI\Assets\app_icon.ico'), + (Join-Path $Root 'src\YMhut.Box.PluginTauriHost\src-tauri\icons\icon.ico') + ) + foreach ($target in $iconTargets) { + Write-PngIconFile $target $frames + } + + $normalizedSource = Join-Path ([IO.Path]::GetTempPath()) ("ymhut-app-icon-{0}.png" -f [Guid]::NewGuid().ToString('N')) + try { + $master.Save($normalizedSource, [Drawing.Imaging.ImageFormat]::Png) + Copy-Item -LiteralPath $normalizedSource -Destination (Join-Path $Root 'assets\icons\app_icon.png') -Force + Copy-Item -LiteralPath $normalizedSource -Destination (Join-Path $Root 'assets\icons\icon.png') -Force + } finally { + Remove-Item -LiteralPath $normalizedSource -Force -ErrorAction SilentlyContinue + } + + $projectAssets = Join-Path $Root 'src\box-winUI\Assets' + Save-Logo $master (Join-Path $projectAssets 'StoreLogo.png') 50 50 5 + Save-Logo $master (Join-Path $projectAssets 'Square44x44Logo.png') 44 44 4 + Save-Logo $master (Join-Path $projectAssets 'Square150x150Logo.png') 150 150 16 + Save-Logo $master (Join-Path $projectAssets 'LockScreenLogo.png') 70 70 8 + Save-Logo $master (Join-Path $projectAssets 'Wide310x150Logo.png') 310 150 24 ([Drawing.Color]::FromArgb(255, 245, 246, 247)) +} finally { + $master.Dispose() +} + +Write-Host 'Generated DPI-aware YMhut Box application icons.' diff --git a/scripts/generate-authenticated-assets.ps1 b/scripts/generate-authenticated-assets.ps1 new file mode 100644 index 0000000..e6821b0 --- /dev/null +++ b/scripts/generate-authenticated-assets.ps1 @@ -0,0 +1,154 @@ +param( + [Parameter(Mandatory = $true)][string]$Root, + [Parameter(Mandatory = $true)][string]$OutputDirectory +) + +$ErrorActionPreference = 'Stop' +$rootPath = (Resolve-Path -LiteralPath $Root).Path +$outputPath = [IO.Path]::GetFullPath($OutputDirectory) +New-Item -ItemType Directory -Force -Path $outputPath | Out-Null + +Add-Type -AssemblyName System.IO.Compression +Add-Type -AssemblyName System.IO.Compression.FileSystem + +function Get-Sha256([byte[]]$Bytes) { + $sha = [Security.Cryptography.SHA256]::Create() + try { return ([BitConverter]::ToString($sha.ComputeHash($Bytes)) -replace '-', '').ToLowerInvariant() } + finally { $sha.Dispose() } +} + +function Get-KeyMaterial([byte[]]$Salt, [string]$Purpose) { + $purposeBytes = [Text.Encoding]::UTF8.GetBytes("YMhut.Box.AssetPackage.v2|$Purpose") + $material = [byte[]]::new($purposeBytes.Length + $Salt.Length) + [Array]::Copy($purposeBytes, 0, $material, 0, $purposeBytes.Length) + [Array]::Copy($Salt, 0, $material, $purposeBytes.Length, $Salt.Length) + $sha = [Security.Cryptography.SHA512]::Create() + try { return $sha.ComputeHash($material) } + finally { $sha.Dispose() } +} + +function Write-AuthenticatedPackage([byte[]]$Plain, [string]$Purpose, [string]$Path) { + $salt = [byte[]]::new(16) + $iv = [byte[]]::new(16) + $random = [Security.Cryptography.RandomNumberGenerator]::Create() + try { + $random.GetBytes($salt) + $random.GetBytes($iv) + } + finally { $random.Dispose() } + $keys = Get-KeyMaterial $salt $Purpose + $aes = [Security.Cryptography.Aes]::Create() + try { + $aes.Key = $keys[0..31] + $aes.IV = $iv + $aes.Mode = [Security.Cryptography.CipherMode]::CBC + $aes.Padding = [Security.Cryptography.PaddingMode]::PKCS7 + $encryptor = $aes.CreateEncryptor() + try { $cipher = $encryptor.TransformFinalBlock($Plain, 0, $Plain.Length) } + finally { $encryptor.Dispose() } + } + finally { $aes.Dispose() } + + $magic = [Text.Encoding]::ASCII.GetBytes('YMHUTAS2') + $header = [IO.MemoryStream]::new() + $writer = [IO.BinaryWriter]::new($header, [Text.Encoding]::UTF8, $true) + try { + $writer.Write($magic) + $writer.Write([byte]2) + $writer.Write($salt) + $writer.Write($iv) + $writer.Write([long]$Plain.Length) + $writer.Write([long]$cipher.Length) + $writer.Flush() + } + finally { $writer.Dispose() } + + $signed = [byte[]]::new($header.Length + $cipher.Length) + [Array]::Copy($header.ToArray(), 0, $signed, 0, $header.Length) + [Array]::Copy($cipher, 0, $signed, $header.Length, $cipher.Length) + $hmac = [Security.Cryptography.HMACSHA256]::new($keys[32..63]) + try { $tag = $hmac.ComputeHash($signed) } + finally { $hmac.Dispose() } + [IO.File]::WriteAllBytes($Path, $signed + $tag) + $header.Dispose() +} + +function Add-SourceFile([hashtable]$Entries, [string]$Source, [string]$EntryName) { + if (-not (Test-Path -LiteralPath $Source -PathType Leaf)) { throw "Missing authenticated asset source: $Source" } + $normalized = $EntryName.Replace('\', '/').TrimStart('/') + if ($normalized -eq '' -or $normalized.Contains('../') -or $normalized.StartsWith('../')) { throw "Unsafe authenticated asset entry: $EntryName" } + if ($Entries.ContainsKey($normalized)) { throw "Duplicate authenticated asset entry: $normalized" } + $bytes = [IO.File]::ReadAllBytes($Source) + $Entries[$normalized] = [pscustomobject]@{ Path = $normalized; Bytes = $bytes; Sha256 = Get-Sha256 $bytes } +} + +function Add-SourceTree([hashtable]$Entries, [string]$SourceRoot, [string]$Prefix, [scriptblock]$Include = $null) { + if (-not (Test-Path -LiteralPath $SourceRoot -PathType Container)) { throw "Missing authenticated asset directory: $SourceRoot" } + foreach ($file in Get-ChildItem -LiteralPath $SourceRoot -Recurse -File) { + $relative = $file.FullName.Substring($SourceRoot.TrimEnd('\', '/').Length).TrimStart('\', '/').Replace('\', '/') + if ($Include -and -not (& $Include $relative)) { continue } + Add-SourceFile $Entries $file.FullName (("$Prefix/$relative").TrimStart('/')) + } +} + +function New-AssetPackage([hashtable]$Entries, [string]$BundleId, [string]$Purpose, [string]$Path) { + $memory = [IO.MemoryStream]::new() + $archive = [IO.Compression.ZipArchive]::new($memory, [IO.Compression.ZipArchiveMode]::Create, $true) + try { + foreach ($item in ($Entries.Values | Sort-Object Path)) { + $entry = $archive.CreateEntry($item.Path, [IO.Compression.CompressionLevel]::Optimal) + $stream = $entry.Open() + try { $stream.Write($item.Bytes, 0, $item.Bytes.Length) } + finally { $stream.Dispose() } + } + $manifest = [ordered]@{ + schemaVersion = 2 + bundleId = $BundleId + files = @($Entries.Values | Sort-Object Path | ForEach-Object { + [ordered]@{ path = $_.Path; length = $_.Bytes.Length; sha256 = $_.Sha256 } + }) + } + $manifestBytes = [Text.Encoding]::UTF8.GetBytes(($manifest | ConvertTo-Json -Depth 5 -Compress)) + $manifestEntry = $archive.CreateEntry('_manifest.json', [IO.Compression.CompressionLevel]::Optimal) + $manifestStream = $manifestEntry.Open() + try { $manifestStream.Write($manifestBytes, 0, $manifestBytes.Length) } + finally { $manifestStream.Dispose() } + } + finally { $archive.Dispose() } + $plain = $memory.ToArray() + $memory.Dispose() + Write-AuthenticatedPackage $plain $Purpose $Path +} + +$runtimeEntries = @{} +$projectAssets = Join-Path $rootPath 'src\box-winUI\Assets' +$repoAssets = Join-Path $rootPath 'assets' +Add-SourceTree $runtimeEntries (Join-Path $projectAssets 'startup-splash') 'startup-splash' +Add-SourceTree $runtimeEntries (Join-Path $projectAssets 'home-globe') 'home-globe' { + param($relative) + return $relative -notlike 'textures/solar/source/*' -and + $relative -notlike 'textures/solar/optimized/*' -and + $relative -ne 'textures/solar/solar-texture-manifest.json' +} +Add-SourceTree $runtimeEntries (Join-Path $projectAssets 'tool-pages') 'tool-pages' +Add-SourceTree $runtimeEntries (Join-Path $projectAssets 'tool-results') 'tool-results' +Add-SourceTree $runtimeEntries (Join-Path $repoAssets 'icons') 'icons' { param($relative) return $relative -ne '.gitkeep' } +Add-SourceTree $runtimeEntries (Join-Path $repoAssets 'images') 'images' { param($relative) return $relative -ne 'loading.gif' } +Add-SourceFile $runtimeEntries (Join-Path $repoAssets 'download.svg') 'download.svg' +Add-SourceFile $runtimeEntries (Join-Path $repoAssets 'icons\app_icon.ico') 'app_icon.ico' +New-AssetPackage $runtimeEntries 'runtime-assets' 'runtime-assets' (Join-Path $outputPath 'runtime-assets.dat') + +$dataEntries = @{} +$dataRoot = Join-Path $repoAssets 'data' +foreach ($file in Get-ChildItem -LiteralPath $dataRoot -Recurse -File) { + if ($file.Extension -ieq '.dat' -or $file.Name -ieq 'ymhut-data.ybin') { continue } + $relative = $file.FullName.Substring($repoAssets.TrimEnd('\', '/').Length).TrimStart('\', '/').Replace('\', '/') + Add-SourceFile $dataEntries $file.FullName $relative +} +$rankingRoot = Join-Path $rootPath 'server\unified-management\internal\reference\data' +if (Test-Path -LiteralPath $rankingRoot -PathType Container) { + foreach ($file in Get-ChildItem -LiteralPath $rankingRoot -Filter '*.json' -File) { + Add-SourceFile $dataEntries $file.FullName ("data/rankings/$($file.Name)") + } +} +New-AssetPackage $dataEntries 'reference-data' 'reference-data' (Join-Path $outputPath 'ymhut-data.ybin') diff --git a/scripts/generate-pearapi-pages.ps1 b/scripts/generate-pearapi-pages.ps1 new file mode 100644 index 0000000..a95aa60 --- /dev/null +++ b/scripts/generate-pearapi-pages.ps1 @@ -0,0 +1,64 @@ +param( + [string]$Root = (Resolve-Path (Join-Path $PSScriptRoot '..')).Path +) + +$ErrorActionPreference = 'Stop' +$catalogPath = Join-Path $Root 'src\YMhut.Box.Core\Api\PearApiCatalog.cs' +$outputPath = Join-Path $Root 'src\box-winUI\Views\Tools\GeneratedPearApiToolPages.cs' +$pattern = 'D\("(?[^"]+)",\s*\d+,' +$ids = [Collections.Generic.List[string]]::new() +foreach ($line in (Get-Content -LiteralPath $catalogPath -Encoding UTF8)) { + $match = [regex]::Match($line, $pattern) + if ($match.Success) { $ids.Add($match.Groups['id'].Value) } +} +if ($ids.Count -ne 74) { throw "Expected 74 PearAPI definitions, found $($ids.Count)." } +if (($ids | Select-Object -Unique).Count -ne $ids.Count) { throw 'PearAPI tool IDs must be unique.' } +$legacyAliases = @('baidu_hot', 'bili_hot', 'zhihu_hot') + +function Get-ClassStem([string]$id) { + $parts = $id -split '[^A-Za-z0-9]+' + return (($parts | Where-Object { $_ } | ForEach-Object { + if ($_.Length -eq 1) { $_.ToUpperInvariant() } + else { $_.Substring(0, 1).ToUpperInvariant() + $_.Substring(1) } + }) -join '') +} + +$lines = [Collections.Generic.List[string]]::new() +$lines.Add('// ') +$lines.Add('#nullable enable') +$lines.Add('using YMhut.Box.Core.Api;') +$lines.Add('using YMhut.Box.Core.Tools;') +$lines.Add('using YMhut.Box.WinUI.ViewModels.Tools;') +$lines.Add('') +$lines.Add('namespace YMhut.Box.WinUI.Views.Tools;') +$lines.Add('') +$lines.Add('public sealed partial class ToolPageRegistry') +$lines.Add('{') +$lines.Add(' private static partial void RegisterPearApi(ToolPageRegistry registry)') +$lines.Add(' {') +foreach ($id in $ids) { + $stem = Get-ClassStem $id + $lines.Add(" registry.Register<${stem}PearApiToolPage, ${stem}PearApiToolViewModel>(`"$id`", (module, goBack) => new ${stem}PearApiToolPage(module, goBack));") +} +foreach ($id in $legacyAliases) { + $stem = (($id -split '_') | ForEach-Object { if ($_.Length -gt 0) { $_.Substring(0, 1).ToUpperInvariant() + $_.Substring(1) } }) -join '' + $lines.Add(" registry.Register<${stem}PearApiToolPage, ${stem}PearApiToolViewModel>(`"$id`", (module, goBack) => new ${stem}PearApiToolPage(module, goBack));") +} +$lines.Add(' }') +$lines.Add('}') +$lines.Add('') +foreach ($id in $ids) { + $stem = Get-ClassStem $id + $lines.Add("public sealed class ${stem}PearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired(`"$id`"));") + $lines.Add("public sealed class ${stem}PearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new ${stem}PearApiToolViewModel(module), goBack);") + $lines.Add('') +} +foreach ($id in $legacyAliases) { + $stem = (($id -split '_') | ForEach-Object { if ($_.Length -gt 0) { $_.Substring(0, 1).ToUpperInvariant() + $_.Substring(1) } }) -join '' + $lines.Add("public sealed class ${stem}PearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired(`"$id`"));") + $lines.Add("public sealed class ${stem}PearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new ${stem}PearApiToolViewModel(module), goBack);") + $lines.Add('') +} + +Set-Content -LiteralPath $outputPath -Value $lines -Encoding UTF8 +Write-Host "Generated $($ids.Count) PearAPI pages and $($legacyAliases.Count) legacy aliases in $outputPath" diff --git a/scripts/generate-tool-ui-dat.ps1 b/scripts/generate-tool-ui-dat.ps1 index 5a34285..9ee6e5d 100644 --- a/scripts/generate-tool-ui-dat.ps1 +++ b/scripts/generate-tool-ui-dat.ps1 @@ -5,6 +5,7 @@ $ErrorActionPreference = 'Stop' $catalogPath = Join-Path $Root 'src\YMhut.Box.Core\Tools\ToolCatalog.cs' +$pearCatalogPath = Join-Path $Root 'src\YMhut.Box.Core\Api\PearApiCatalog.cs' $nexPath = Join-Path $Root 'src\YMhut.Box.Core\Tools\NexNativeTools.cs' $outputRoot = Join-Path $Root 'assets\data\tool-ui' New-Item -ItemType Directory -Force -Path $outputRoot | Out-Null @@ -32,6 +33,35 @@ foreach ($line in ($rawMatch.Groups['data'].Value -split "`r?`n")) { } } +$pearPattern = 'D\("(?[^"]+)",\s*(?\d+),\s*"(?[^"]+)",\s*"(?[^"]*)",\s*"(?[^"]+)",\s*"(?[^"]+)",\s*PearApiRequestMethod\.(?\w+),\s*PearApiPrivacyClass\.(?\w+),\s*PearApiResultKind\.(?\w+)' +foreach ($line in (Get-Content -LiteralPath $pearCatalogPath -Encoding UTF8)) { + $match = [regex]::Match($line, $pearPattern) + if (-not $match.Success) { continue } + $id = $match.Groups['id'].Value + [void]$ids.Add($id) + $metadata[$id] = [ordered]@{ + zh = $match.Groups['name'].Value + en = $match.Groups['name'].Value + descriptionZh = $match.Groups['description'].Value + descriptionEn = $match.Groups['description'].Value + category = 'network' + offline = $false + pear = $true + pearCategory = $match.Groups['category'].Value + privacy = $match.Groups['privacy'].Value + result = $match.Groups['result'].Value + apiId = $match.Groups['apiId'].Value + } +} +foreach ($alias in @{ baidu_hot = '百度'; bili_hot = '哔哩哔哩'; zhihu_hot = '知乎' }.GetEnumerator()) { + if (-not $metadata.ContainsKey($alias.Key)) { continue } + $metadata[$alias.Key].pear = $true + $metadata[$alias.Key].pearCategory = '网络' + $metadata[$alias.Key].privacy = 'Public' + $metadata[$alias.Key].result = 'RankedList' + $metadata[$alias.Key].apiId = '141' +} + foreach ($match in [regex]::Matches((Get-Content -LiteralPath $nexPath -Raw -Encoding UTF8), 'Tool\("(?[^"]+)"')) { $id = $match.Groups['id'].Value [void]$ids.Add($id) @@ -59,7 +89,13 @@ try { $meta = $metadata[$id] $category = [string]$meta.category $risk = if ($category -in @('security', 'system', 'plugin', 'external')) { 'high' } else { 'normal' } - $primaryKind = switch ($category) { + $primaryKind = if ($meta.pear) { + switch ([string]$meta.privacy) { + 'Public' { 'Output'; break } + 'FileUpload' { 'FilePicker'; break } + default { 'Query' } + } + } else { switch ($category) { 'image' { 'FilePicker'; break } 'calculator' { 'Number'; break } 'network' { 'Query'; break } @@ -69,12 +105,12 @@ try { 'plugin' { 'WebView'; break } 'external' { 'ExternalSurface'; break } default { 'Text' } - } + } } $maxLength = 4096 if ($category -eq 'text' -or $category -eq 'dev' -or $category -eq 'security') { $maxLength = 200000 } $placeholder = '输入此工具所需的值' - if ($category -eq 'network') { $placeholder = '关键词、URL、域名或 IP' } + if ($category -eq 'network') { $placeholder = '按此接口页面的字段填写查询条件' } $primaryControls = [Collections.Generic.List[object]]::new() $primaryControls.Add([ordered]@{ id = 'primary' @@ -88,7 +124,9 @@ try { }) $sections = [Collections.Generic.List[object]]::new() - $primaryTitle = switch ($category) { + $primaryTitle = if ($meta.pear) { + [ordered]@{ zh = "PearAPI · $([string]$meta.pearCategory)"; en = "PearAPI · $([string]$meta.pearCategory)" } + } else { switch ($category) { 'calculator' { [ordered]@{ zh = '计算参数'; en = 'Calculation parameters' } } 'network' { [ordered]@{ zh = '查询条件'; en = 'Query criteria' } } 'image' { [ordered]@{ zh = '文件与媒体'; en = 'Files and media' } } @@ -99,14 +137,14 @@ try { 'plugin' { [ordered]@{ zh = '插件安全容器'; en = 'Plugin security container' } } 'external' { [ordered]@{ zh = '外部程序运行'; en = 'External program launch' } } default { [ordered]@{ zh = '主要操作'; en = 'Primary operation' } } - } + } } if ($category -eq 'calculator') { $primaryControls.Clear() foreach ($numberId in @('number-primary', 'number-secondary', 'number-third', 'number-fourth')) { $primaryControls.Add([ordered]@{ id = $numberId; kind = 'Number'; label = [ordered]@{ zh = '数值参数'; en = 'Numeric parameter' }; defaultValue = '1'; required = $true; isReadOnly = $false; validation = [ordered]@{ minimum = -100000000; maximum = 100000000 } }) } - } elseif ($category -eq 'network') { + } elseif ($category -eq 'network' -and -not $meta.pear) { $primaryControls.Add([ordered]@{ id = 'parameter'; kind = 'ComboBox'; label = [ordered]@{ zh = '来源或分类'; en = 'Source or category' }; defaultValue = ''; required = $false; isReadOnly = $false }) } elseif ($category -eq 'image') { $primaryControls.Add([ordered]@{ id = 'file'; kind = 'FilePicker'; label = [ordered]@{ zh = '文件'; en = 'File' }; placeholder = '选择本地文件'; defaultValue = ''; required = $false; isReadOnly = $false }) @@ -121,7 +159,7 @@ try { layout = $(if ($category -eq 'calculator') { 'grid' } else { 'stack' }) }) - if ($category -in @('text', 'dev', 'security', 'network', 'design')) { + if (-not $meta.pear -and $category -in @('text', 'dev', 'security', 'network', 'design')) { $advancedControls = [Collections.Generic.List[object]]::new() if ($category -in @('text', 'dev', 'security')) { $advancedControls.Add([ordered]@{ id = 'rules'; kind = 'ComboBox'; label = [ordered]@{ zh = '处理规则'; en = 'Processing rules' }; defaultValue = ''; required = $false; isReadOnly = $false }) @@ -142,7 +180,9 @@ try { }) } - $resultKind = switch ($category) { + $resultKind = if ($meta.pear) { + "pear-$(([string]$meta.result).ToLowerInvariant())" + } else { switch ($category) { 'calculator' { 'calculator-table' } 'image' { 'image-preview' } 'data' { 'ranked-list' } @@ -153,7 +193,7 @@ try { 'plugin' { 'status-list' } 'external' { 'status-list' } default { 'text' } - } + } } $actions = [Collections.Generic.List[object]]::new() $actionLabel = switch ($category) { 'calculator' { [ordered]@{ zh = '计算'; en = 'Calculate' } } @@ -217,5 +257,10 @@ try { } finally { $aes.Dispose() } +foreach ($stale in Get-ChildItem -LiteralPath $outputRoot -Filter '*.dat' -File -ErrorAction SilentlyContinue) { + if (-not $ids.Contains($stale.BaseName)) { + Remove-Item -LiteralPath $stale.FullName -Force + } +} Write-Host "Generated $($ids.Count) tool UI definitions in $outputRoot" diff --git a/src/YMhut.Box.Core/Api/PearApiCatalog.cs b/src/YMhut.Box.Core/Api/PearApiCatalog.cs new file mode 100644 index 0000000..836d936 --- /dev/null +++ b/src/YMhut.Box.Core/Api/PearApiCatalog.cs @@ -0,0 +1,208 @@ +using YMhut.Box.Core.Tools; + +namespace YMhut.Box.Core.Api; + +public static class PearApiCatalog +{ + public const string ProviderName = "PearAPI"; + public const string DocumentationUrl = "https://api.pearapi.ai/zh/dashboard/api-list"; + public const string DisclaimerUrl = "https://api.pearapi.ai/zh/disclaimer"; + public const string CatalogVerifiedAt = "2026-08-19"; + + private static readonly IReadOnlyList Definitions = + [ + D("ai_latest_news", 325, "AI 全网最新资讯", "最近 24 小时 AI 模型、研究、工具和产业资讯。", "AI", "/api/latest_ai_consultative", PearApiRequestMethod.Get, PearApiPrivacyClass.Public, PearApiResultKind.News, false, "PearAPI 当前文档把 key 标为必填;YMhut Box 不会索取或发送 Key。", P("key", "Key", "当前文档要求的 Key", required: true)), + D("pear_ai_image_describe", 221, "AI 识图", "上传图片并识别画面主体和内容。", "AI", "/api/airecognizeimg/", PearApiRequestMethod.Multipart, PearApiPrivacyClass.FileUpload, PearApiResultKind.Cards, parameters: [P("file", "图片", "发送至 PearAPI 的图片", PearApiParameterKind.File, true)]), + D("pear_embeddings", 334, "文本向量化", "将文本转换为指定维度的向量。", "AI", "/v1/embeddings", PearApiRequestMethod.PostJson, PearApiPrivacyClass.UserText, PearApiResultKind.Json, false, "该接口位于 /v1/ 且不符合客户端仅允许 /api/ 的固定路径策略。", P("input", "文本", "待向量化文本", PearApiParameterKind.MultilineText, true), P("model", "模型", "向量模型", PearApiParameterKind.Choice, true, "Qwen3-Embedding-0.6B", ["Qwen3-Embedding-8B", "Qwen3-Embedding-0.6B"]), P("dimensions", "维度", "32 至 4096", PearApiParameterKind.Number, true, "1024")), + D("pear_ai_image_detection", 333, "AI 图片鉴定", "检测图片是否可能由 AI 生成。", "AI", "/api/image_identification_chart", PearApiRequestMethod.Multipart, PearApiPrivacyClass.FileUpload, PearApiResultKind.Cards, parameters: [P("image", "图片", "发送至 PearAPI 的图片", PearApiParameterKind.File, true)]), + D("pear_ai_text_safety", 332, "AI 文本合规检测", "检测输入文本的内容风险。", "AI", "/api/text_security", PearApiRequestMethod.PostJson, PearApiPrivacyClass.UserText, PearApiResultKind.Cards, parameters: [P("text", "待检测文本", "不会写入本地缓存", PearApiParameterKind.MultilineText, true, maxLength: 12000)]), + D("pear_ai_dish_recognition", 324, "AI 菜品识别", "上传菜品图片并识别名称。", "AI", "/api/aidish/", PearApiRequestMethod.Multipart, PearApiPrivacyClass.FileUpload, PearApiResultKind.Cards, parameters: [P("file", "菜品图片", "发送至 PearAPI 的图片", PearApiParameterKind.File, true)]), + D("pear_image_prompt", 317, "图片提示词反推", "从图片生成 Flux、Stable Diffusion 或 Midjourney 提示词。", "AI", "/api/prompt_image", PearApiRequestMethod.Multipart, PearApiPrivacyClass.FileUpload, PearApiResultKind.Text, parameters: [P("file", "参考图片", "发送至 PearAPI 的图片", PearApiParameterKind.File, true), P("type", "提示词类型", "生成模型格式", PearApiParameterKind.Choice, true, "flux", ["flux", "stablediffusion", "midjourney", "normal"]), P("lang", "语言", "提示词语言", PearApiParameterKind.Choice, true, "zh", ["zh", "en"])]), + D("ai_translation", 303, "AI 万能翻译", "使用 AI 翻译文本并指定目标语言。", "AI", "/api/translate/ai/", PearApiRequestMethod.Get, PearApiPrivacyClass.UserText, PearApiResultKind.Text, parameters: [P("text", "原文", "待翻译文字", PearApiParameterKind.MultilineText, true, maxLength: 12000), P("target_lang", "目标语言", "用自然语言描述", defaultValue: "简体中文")]), + D("pear_xf_spark", 285, "讯飞星火 Lite", "向免费 Lite 模型提交单轮问题。", "AI", "/api/xfai/", PearApiRequestMethod.Get, PearApiPrivacyClass.UserText, PearApiResultKind.Text, parameters: [P("message", "问题", "单轮问题内容", PearApiParameterKind.MultilineText, true, maxLength: 8000)]), + D("pear_llm_reader", 284, "AI 网页阅读", "读取公网网页并提炼主要内容。", "AI", "/api/llmreader/", PearApiRequestMethod.Get, PearApiPrivacyClass.UserUrl, PearApiResultKind.Text, parameters: [P("url", "网页地址", "仅允许 HTTP(S) 公网地址", PearApiParameterKind.Url, true), P("type", "返回格式", "结果格式", PearApiParameterKind.Choice, false, "json", ["json", "text"])]), + + D("pear_hot_60_image", 156, "热榜 60 秒图片", "生成百度或微博热榜图片。", "生活", "/api/60s/image/hot/", PearApiRequestMethod.Get, PearApiPrivacyClass.Public, PearApiResultKind.Image, parameters: [P("type", "平台", "热榜来源", PearApiParameterKind.Choice, true, "baidu", ["baidu", "weibo"])]), + D("pear_daily_60_image", 155, "每日 60 秒图片", "获取当天 60 秒新闻图片。", "生活", "/api/60s/image/", PearApiRequestMethod.Get, PearApiPrivacyClass.Public, PearApiResultKind.Image), + D("hotboard", 141, "综合热榜", "按平台查看实时热门内容。", "网络", "/api/dailyhot/", PearApiRequestMethod.Get, PearApiPrivacyClass.Public, PearApiResultKind.RankedList, parameters: [P("title", "平台", "榜单平台", PearApiParameterKind.Choice, true, "百度", ["百度", "哔哩哔哩", "知乎", "微博", "今日头条", "少数派", "IT之家", "36氪"])]), + D("pear_world_60", 22, "60 秒读世界", "获取当天世界资讯摘要。", "实用", "/api/60s/", PearApiRequestMethod.Get, PearApiPrivacyClass.Public, PearApiResultKind.News), + D("oil_price", 345, "今日油价", "查询省份 92、95、98 号汽油和 0 号柴油价格。", "生活", "/api/oilprice", PearApiRequestMethod.Get, PearApiPrivacyClass.Financial, PearApiResultKind.Table, parameters: [P("type", "模式", "查询模式", PearApiParameterKind.Choice, true, "get", ["get", "list"]), P("province", "省份", "省级行政区名称", required: true)]), + D("pear_life_calculator", 340, "人生计算器", "根据出生日期量化人生时间进度。", "生活", "/api/life_calculator", PearApiRequestMethod.PostJson, PearApiPrivacyClass.UserText, PearApiResultKind.Cards, parameters: [P("birth_date", "出生日期", "格式 YYYY-MM-DD", PearApiParameterKind.Date, true)]), + D("pear_random_superpower", 327, "随机超能力", "随机生成一种能力和对应限制。", "娱乐", "/api/superpower", PearApiRequestMethod.Get, PearApiPrivacyClass.Public, PearApiResultKind.Image), + D("pear_random_song", 318, "随机点歌", "随机返回一段唱鸭点歌内容。", "娱乐", "/api/click_music", PearApiRequestMethod.Get, PearApiPrivacyClass.Public, PearApiResultKind.Audio), + D("pear_text_tts", 316, "通用文本配音", "用指定音色和风格生成语音。", "实用", "/api/freedub", PearApiRequestMethod.PostJson, PearApiPrivacyClass.UserText, PearApiResultKind.Audio, parameters: [P("text", "配音文本", "发送至 PearAPI 的文本", PearApiParameterKind.MultilineText, true, maxLength: 3000), P("role", "音色", "留空使用默认音色"), P("style", "风格", "语音风格", defaultValue: "cheerful")]), + D("pear_ip_details", 290, "IP 详情", "查询公网 IP 的国家、地区、城市和时区。", "数据", "/api/ip/details/", PearApiRequestMethod.Get, PearApiPrivacyClass.UserText, PearApiResultKind.Cards, parameters: [P("ip", "IP 地址", "IPv4 或 IPv6", required: true)]), + D("pear_gold_price", 286, "今日黄金价格", "查看当天黄金品类价格。", "生活", "/api/goldprice/", PearApiRequestMethod.Get, PearApiPrivacyClass.Public, PearApiResultKind.Table), + D("movie_box_office", 283, "电影实时票房", "查看猫眼实时票房排行。", "娱乐", "/api/maoyan/", PearApiRequestMethod.Get, PearApiPrivacyClass.Public, PearApiResultKind.RankedList), + D("pear_ruozhiba", 282, "随机趣味问答", "随机返回一条弱智吧问答。", "娱乐", "/api/ruozhiba/", PearApiRequestMethod.Get, PearApiPrivacyClass.Public, PearApiResultKind.Cards), + D("pear_qq_level_image", 280, "QQ 等级图像", "按等级和样式生成 QQ 等级图标。", "图像", "/api/qq/level/", PearApiRequestMethod.Get, PearApiPrivacyClass.UserText, PearApiResultKind.Image, parameters: [P("level", "QQ 等级", "正整数", PearApiParameterKind.Number, true), P("type", "样式", "图标集规则", PearApiParameterKind.Choice, false, "1", ["1", "2", "3", "4"])]), + D("pear_historical_person", 277, "历史人物年轮", "查询历史人物生平和年轮信息。", "学习", "/api/yearsmap/", PearApiRequestMethod.Get, PearApiPrivacyClass.UserText, PearApiResultKind.Cards, parameters: [P("name", "人物姓名", "历史人物名", required: true)]), + D("pear_countdown", 275, "倒数日", "获取近期节日和事件倒数日。", "生活", "/api/countdownday/", PearApiRequestMethod.Get, PearApiPrivacyClass.Public, PearApiResultKind.Cards), + D("pear_answers_book", 274, "答案之书", "输入问题并获取随机回答。", "娱乐", "/api/answersbook/", PearApiRequestMethod.Get, PearApiPrivacyClass.UserText, PearApiResultKind.Text, parameters: [P("question", "问题", "要询问的问题", PearApiParameterKind.MultilineText, true, maxLength: 1000)]), + D("city_route_query", 272, "城际路线查询", "查询城市间距离、耗时、油费和过路费。", "生活", "/api/citytravelroutes/", PearApiRequestMethod.Get, PearApiPrivacyClass.UserText, PearApiResultKind.Cards, parameters: [P("from", "出发城市", "城市名称", required: true), P("to", "到达城市", "城市名称", required: true)]), + D("pear_cookbook", 270, "菜谱大全", "按菜名查询简介、材料和做法。", "生活", "/api/cookbook/", PearApiRequestMethod.Get, PearApiPrivacyClass.UserText, PearApiResultKind.Cards, parameters: [P("search", "菜名", "具体菜品名称", required: true)]), + D("pear_car_price", 269, "车辆价格查询", "按具体车型查询价格、配置和封面。", "生活", "/api/car/", PearApiRequestMethod.Get, PearApiPrivacyClass.UserText, PearApiResultKind.Cards, parameters: [P("search", "车型", "例如:法拉利 296", required: true)]), + D("pear_lottery", 268, "彩票开奖查询", "查询常见彩票开奖数据。", "数据", "/api/lottery/", PearApiRequestMethod.Get, PearApiPrivacyClass.Financial, PearApiResultKind.Table, parameters: [P("get", "彩种", "彩种缩写", PearApiParameterKind.Choice, true, "ssq", ["kl8", "ssq", "dlt", "fc3d", "pl3", "pl5", "qlc", "qxc", "sfc", "jqc", "bqc"]), P("num", "天数", "1 至 100", PearApiParameterKind.Number, false, "30")]), + D("pear_stock", 267, "股票数据查询", "查询股票价格、成交量和涨跌幅。", "数据", "/api/stock/", PearApiRequestMethod.Get, PearApiPrivacyClass.Financial, PearApiResultKind.Table, parameters: [P("secid", "股票代码", "证券代码", required: true), P("num", "记录数", "默认 100", PearApiParameterKind.Number, false, "100")]), + D("pear_trademark", 263, "商标信息查询", "按关键词查询商标申请和注册信息。", "数据", "/api/trademark/", PearApiRequestMethod.Get, PearApiPrivacyClass.UserText, PearApiResultKind.Table, parameters: [P("keyword", "商标关键词", "商标名称关键词", required: true)]), + D("pear_poem", 259, "藏头藏尾诗", "按五言或七言生成藏头、藏尾诗。", "学习", "/api/poem_generate/", PearApiRequestMethod.Get, PearApiPrivacyClass.UserText, PearApiResultKind.Text, parameters: [P("type", "言律", "诗句字数", PearApiParameterKind.Choice, true, "wuyan", ["wuyan", "qiyan"]), P("model", "模式", "藏头或藏尾", PearApiParameterKind.Choice, true, "head", ["head", "trail"]), P("text", "藏字", "用于生成的文字", required: true)]), + D("train_query", 249, "高铁动车车票", "按出发地、目的地和日期查询车票。", "生活", "/api/highspeedticket", PearApiRequestMethod.Get, PearApiPrivacyClass.UserText, PearApiResultKind.Table, parameters: [P("from", "出发地", "车站或城市", required: true), P("to", "目的地", "车站或城市", required: true), P("time", "日期", "格式 YYYY-MM-DD,留空为今天", PearApiParameterKind.Date)]), + D("pear_certificate", 236, "在线证书生成", "按标题、获奖人和正文生成证书。", "实用", "/api/certificate/", PearApiRequestMethod.Get, PearApiPrivacyClass.UserText, PearApiResultKind.Image, parameters: [P("name", "获奖人", "显示姓名", required: true), P("title", "证书标题", "奖项标题", required: true), P("text", "正文", "证书正文", PearApiParameterKind.MultilineText, true, maxLength: 600)]), + D("pear_ssl", 234, "SSL 证书验证", "查看签发机构、有效期、算法和指纹。", "网络", "/api/ssl/", PearApiRequestMethod.Get, PearApiPrivacyClass.UserText, PearApiResultKind.Cards, parameters: [P("domain", "域名", "不含协议的公网域名", PearApiParameterKind.Domain, true)]), + D("pear_icp", 233, "ICP备案查询", "查询域名公开备案信息。", "网络", "/api/icp/", PearApiRequestMethod.Get, PearApiPrivacyClass.UserText, PearApiResultKind.Cards, parameters: [P("domain", "域名", "不含 HTTP 协议", PearApiParameterKind.Domain, true)]), + D("pear_blood_type", 231, "血型遗传规律", "根据父母血型计算子代可能血型。", "生活", "/api/bloodtype/", PearApiRequestMethod.Get, PearApiPrivacyClass.UserText, PearApiResultKind.Cards, parameters: [P("father", "父亲血型", "血型", PearApiParameterKind.Choice, true, "A", ["A", "B", "AB", "O"]), P("mother", "母亲血型", "血型", PearApiParameterKind.Choice, true, "B", ["A", "B", "AB", "O"])]), + D("pear_brainteaser", 229, "脑筋急转弯", "随机获取一道题目及答案。", "娱乐", "/api/brainteasers/", PearApiRequestMethod.Get, PearApiPrivacyClass.Public, PearApiResultKind.Cards), + D("pear_synonym_antonym", 224, "近义反义词", "查询词语的近义词和反义词。", "学习", "/api/jinyifanyi/", PearApiRequestMethod.Get, PearApiPrivacyClass.UserText, PearApiResultKind.Cards, parameters: [P("word", "词语", "待查询词语", required: true)]), + D("pear_surname_pun", 220, "姓氏谐音网名", "根据姓氏生成谐音网名。", "娱乐", "/api/namexy/", PearApiRequestMethod.Get, PearApiPrivacyClass.UserText, PearApiResultKind.RankedList, parameters: [P("name", "姓氏", "单个姓氏", required: true, maxLength: 8)]), + D("pear_website_info", 214, "网站基础信息", "读取网站协议、标题、图标、编码和关键词。", "网络", "/api/website/info/", PearApiRequestMethod.Get, PearApiPrivacyClass.UserUrl, PearApiResultKind.Cards, parameters: [P("url", "网站地址", "仅允许 HTTP(S) 公网地址", PearApiParameterKind.Url, true)]), + D("pear_baidu_place", 212, "地名检索", "按关键词检索地点基础信息。", "网络", "/api/baidumap/", PearApiRequestMethod.Get, PearApiPrivacyClass.UserText, PearApiResultKind.Table, parameters: [P("keyword", "地点关键词", "地点名称", required: true)]), + D("pear_audio_transcript", 199, "音视频转文本", "上传音频或视频并识别为文字。", "图像", "/api/audiocr/", PearApiRequestMethod.Multipart, PearApiPrivacyClass.FileUpload, PearApiResultKind.Text, parameters: [P("file", "音视频文件", "发送至 PearAPI,最大 50 MiB", PearApiParameterKind.File, true)]), + D("pear_question_search", 198, "题库搜索", "按题目文本检索公开题库答案。", "学习", "/api/baidutiku/", PearApiRequestMethod.Get, PearApiPrivacyClass.UserText, PearApiResultKind.Cards, parameters: [P("question", "题目", "待检索题目", PearApiParameterKind.MultilineText, true, maxLength: 4000)]), + D("pear_funny_joke", 188, "搞笑段子", "随机获取一条搞笑段子。", "娱乐", "/api/random/duanzi/", PearApiRequestMethod.Get, PearApiPrivacyClass.Public, PearApiResultKind.Text, parameters: [P("type", "格式", "返回格式", PearApiParameterKind.Choice, false, "json", ["json", "text"])]), + D("pear_award", 174, "在线奖状生成", "按姓名、奖项和班级生成奖状。", "实用", "/api/certcommend/", PearApiRequestMethod.Get, PearApiPrivacyClass.UserText, PearApiResultKind.Image, parameters: [P("name", "姓名", "最多 3 个字符", required: true, maxLength: 3), P("title", "奖项", "最多 9 个字符", required: true, maxLength: 9), P("classname", "班级", "班级名称", required: true, maxLength: 40)]), + D("pear_exchange_rate", 173, "货币汇率换算", "按币种和金额执行汇率换算。", "生活", "/api/exchangerate/", PearApiRequestMethod.Get, PearApiPrivacyClass.Financial, PearApiResultKind.Cards, parameters: [P("type", "模式", "get 或 list", PearApiParameterKind.Choice, true, "get", ["get", "list"]), P("before", "原币种", "三位币种代码", required: true), P("after", "目标币种", "三位币种代码", required: true), P("price", "金额", "转换金额", PearApiParameterKind.Number, true)]), + D("pear_science_news", 163, "实时科技资讯", "获取当前最新科技资讯。", "数据", "/api/sciencenews/", PearApiRequestMethod.Get, PearApiPrivacyClass.Public, PearApiResultKind.News), + D("pear_kfc", 162, "疯狂星期四文案", "随机获取一条星期四主题文案。", "娱乐", "/api/kfc", PearApiRequestMethod.Get, PearApiPrivacyClass.Public, PearApiResultKind.Text, parameters: [P("type", "格式", "返回格式", PearApiParameterKind.Choice, false, "json", ["json", "text"])]), + D("pear_sensitive_words", 159, "敏感词检测", "检测文本中的敏感词并返回替换结果。", "开发", "/api/sensitivewords/", PearApiRequestMethod.Get, PearApiPrivacyClass.UserText, PearApiResultKind.Cards, parameters: [P("text", "文本", "待检测文本", PearApiParameterKind.MultilineText, true, maxLength: 12000)]), + D("pear_ocr", 152, "OCR 图像文字识别", "上传图片并识别其中的文字。", "图像", "/api/ocr/", PearApiRequestMethod.Multipart, PearApiPrivacyClass.FileUpload, PearApiResultKind.Text, parameters: [P("file", "图片", "发送至 PearAPI 的图片", PearApiParameterKind.File, true)]), + D("pear_chinese_conversion", 144, "简繁互转", "在简体中文与繁体中文之间转换。", "实用", "/api/conversion/word.php", PearApiRequestMethod.Get, PearApiPrivacyClass.UserText, PearApiResultKind.Text, parameters: [P("text", "文本", "待转换文本", PearApiParameterKind.MultilineText, true, maxLength: 12000), P("type", "方向", "转换方向", PearApiParameterKind.Choice, true, "jzf", ["jzf", "fzj"])]), + D("history_today", 133, "历史上的今天", "获取今天发生的历史事件。", "学习", "/api/lsjt/", PearApiRequestMethod.Get, PearApiPrivacyClass.Public, PearApiResultKind.RankedList, parameters: [P("type", "格式", "返回格式", PearApiParameterKind.Choice, false, "json", ["json", "text"])]), + D("pear_rainbow", 129, "彩虹屁", "随机获取一段夸赞文案。", "娱乐", "/api/caihongpi/", PearApiRequestMethod.Get, PearApiPrivacyClass.Public, PearApiResultKind.Text), + D("pear_couplet", 128, "对联生成", "根据上联生成对应下联。", "学习", "/api/duilian/", PearApiRequestMethod.Get, PearApiPrivacyClass.UserText, PearApiResultKind.Text, parameters: [P("word", "上联", "输入上联", PearApiParameterKind.MultilineText, true, maxLength: 500)]), + D("pear_constellation", 123, "星座运势", "查询当天星座运势。", "娱乐", "/api/xzys/", PearApiRequestMethod.Get, PearApiPrivacyClass.UserText, PearApiResultKind.Cards, parameters: [P("xz", "星座", "星座名称", PearApiParameterKind.Choice, true, "白羊", ["白羊", "金牛", "双子", "巨蟹", "狮子", "处女", "天秤", "天蝎", "射手", "摩羯", "水瓶", "双鱼"])]), + D("pear_mean_search", 116, "据意查句", "根据意思查找现代文、诗词或名言。", "学习", "/api/meansearch/", PearApiRequestMethod.Get, PearApiPrivacyClass.UserText, PearApiResultKind.RankedList, parameters: [P("mean", "含义", "想表达的意思", PearApiParameterKind.MultilineText, true, maxLength: 1000), P("type", "范围", "语料范围", PearApiParameterKind.Choice, false, "现代文", ["现代文", "古诗文"])]), + D("pear_country_population", 109, "国家人口排行", "按名次查看国家人口数据。", "数据", "/api/human/rank.php", PearApiRequestMethod.Get, PearApiPrivacyClass.Public, PearApiResultKind.Table, parameters: [P("num", "名次数量", "留空返回默认数量", PearApiParameterKind.Number)]), + D("pear_world_population", 108, "世界人口详情", "查看世界人口汇总数据。", "数据", "/api/human/alldata.php", PearApiRequestMethod.Get, PearApiPrivacyClass.Public, PearApiResultKind.Cards), + D("pear_keyword_guide", 101, "关键词引导", "按关键词生成相关引导词。", "开发", "/api/guide/", PearApiRequestMethod.Get, PearApiPrivacyClass.UserText, PearApiResultKind.RankedList, parameters: [P("keyword", "关键词", "检索关键词", required: true)]), + D("pear_movie_lines", 100, "影视台词搜寻", "按台词内容查找对应影视作品。", "数据", "/api/media/lines.php", PearApiRequestMethod.Get, PearApiPrivacyClass.UserText, PearApiResultKind.Table, parameters: [P("word", "台词", "台词片段", PearApiParameterKind.MultilineText, true, maxLength: 1000), P("page", "页码", "正整数", PearApiParameterKind.Number, true, "1")]), + D("pear_today_food", 94, "今天吃什么", "随机返回一种食物。", "生活", "/api/today/food.php", PearApiRequestMethod.Get, PearApiPrivacyClass.Public, PearApiResultKind.Cards), + D("pear_site_index", 93, "网址收录查询", "查询域名在常见搜索站点的收录状态。", "开发", "/api/website/shoulu.php", PearApiRequestMethod.Get, PearApiPrivacyClass.UserUrl, PearApiResultKind.Table, parameters: [P("url", "域名", "不含路径的公网域名", PearApiParameterKind.Domain, true)]), + D("pear_short_recovery", 70, "短链接还原", "显示短链接的原始目标。", "网络", "/api/short/recovery/", PearApiRequestMethod.Get, PearApiPrivacyClass.UserUrl, PearApiResultKind.Cards, parameters: [P("url", "短链接", "仅允许 HTTP(S) 公网地址", PearApiParameterKind.Url, true)]), + D("pear_college", 65, "全国高校查询", "按关键词查询高校信息。", "学习", "/api/college/", PearApiRequestMethod.Get, PearApiPrivacyClass.UserText, PearApiResultKind.Table, parameters: [P("keyword", "高校关键词", "学校或专业关键词", required: true)]), + D("pear_love_reply", 63, "恋爱话术", "根据问题返回沟通建议。", "娱乐", "/api/love/", PearApiRequestMethod.Get, PearApiPrivacyClass.UserText, PearApiResultKind.Text, parameters: [P("question", "问题", "请勿输入个人隐私", PearApiParameterKind.MultilineText, true, maxLength: 1000)]), + D("pear_quirky_dialogue", 29, "趣味对话", "随机返回一段趣味对话。", "娱乐", "/api/jdyl/qpdh.php", PearApiRequestMethod.Get, PearApiPrivacyClass.Public, PearApiResultKind.Text), + D("pear_classic_joke", 25, "经典笑话", "随机返回一篇经典笑话。", "娱乐", "/api/jdyl/xiaohua.php", PearApiRequestMethod.Get, PearApiPrivacyClass.Public, PearApiResultKind.Text), + D("pear_love_quote", 24, "经典情话", "随机返回一句情话。", "娱乐", "/api/jdyl/qinghua.php", PearApiRequestMethod.Get, PearApiPrivacyClass.Public, PearApiResultKind.Text), + D("pear_translation", 13, "万能翻译", "自动识别语言并执行常用语种翻译。", "学习", "/api/translate/", PearApiRequestMethod.Get, PearApiPrivacyClass.UserText, PearApiResultKind.Text, parameters: [P("text", "原文", "待翻译内容", PearApiParameterKind.MultilineText, true, maxLength: 12000), P("type", "方向", "AUTO 或指定方向", defaultValue: "AUTO")]), + D("pear_hitokoto", 7, "随机一言", "随机返回一句名言。", "娱乐", "/api/hitokoto/", PearApiRequestMethod.Get, PearApiPrivacyClass.Public, PearApiResultKind.Text), + D("pear_dujitang", 6, "毒鸡汤", "随机返回一句反鸡汤文案。", "娱乐", "/api/dujitang", PearApiRequestMethod.Get, PearApiPrivacyClass.Public, PearApiResultKind.Text) + ]; + + private static readonly IReadOnlyDictionary ById = Definitions + .ToDictionary(definition => definition.ToolId, StringComparer.OrdinalIgnoreCase); + private static readonly IReadOnlyDictionary LegacyAliases = + new Dictionary(StringComparer.OrdinalIgnoreCase) + { + ["baidu_hot"] = ("百度热搜", "通过综合热榜查看百度实时热门内容。", "百度"), + ["bili_hot"] = ("B 站热榜", "通过综合热榜查看哔哩哔哩热门内容。", "哔哩哔哩"), + ["zhihu_hot"] = ("知乎热榜", "通过综合热榜查看知乎实时热门内容。", "知乎") + }; + + public static IReadOnlyList All => Definitions; + + public static IReadOnlyCollection LegacyAliasToolIds { get; } = LegacyAliases.Keys.ToArray(); + + public static bool TryGet(string toolId, out PearApiToolDefinition definition) + { + if (ById.TryGetValue(toolId, out definition!)) + { + return true; + } + + if (!LegacyAliases.TryGetValue(toolId, out var alias) || !ById.TryGetValue("hotboard", out var source)) + { + definition = default!; + return false; + } + + definition = source with + { + ToolId = toolId, + Name = alias.Name, + Description = alias.Description, + Parameters = source.Parameters + .Select(parameter => parameter.Name.Equals("title", StringComparison.OrdinalIgnoreCase) + ? parameter with { DefaultValue = alias.Platform } + : parameter) + .ToArray() + }; + return true; + } + + public static PearApiToolDefinition GetRequired(string toolId) + => TryGet(toolId, out var definition) + ? definition + : throw new KeyNotFoundException($"PearAPI tool definition was not found: {toolId}"); + + public static IEnumerable CreateToolModules(IEnumerable? existingIds = null) + { + var existing = new HashSet(existingIds ?? [], StringComparer.OrdinalIgnoreCase); + return Definitions + .Where(definition => !existing.Contains(definition.ToolId)) + .Select(definition => new ToolModule(new ToolMetadata( + definition.ToolId, + definition.Name, + definition.Description, + MapCategory(definition.Category), + ["PearAPI", definition.Category, definition.Name, "联网工具"], + false, + "\uE774", + 250, + ProviderName, + new ToolOnlineCapabilityInfo( + ProviderName, + definition.PrivacyClass.ToString(), + definition.PrivacyClass != PearApiPrivacyClass.Public, + definition.IsAvailableWithoutKey)))); + } + + private static ToolCategory MapCategory(string category) => category switch + { + "AI" or "数据" or "学习" => ToolCategory.Data, + "网络" => ToolCategory.Network, + "图像" => ToolCategory.Image, + "开发" => ToolCategory.Dev, + _ => ToolCategory.Life + }; + + private static PearApiToolDefinition D( + string toolId, + int apiId, + string name, + string description, + string category, + string endpointPath, + PearApiRequestMethod method, + PearApiPrivacyClass privacy, + PearApiResultKind result, + bool available = true, + string note = "", + params PearApiParameterDefinition[] parameters) + => new( + toolId, + apiId, + name, + description, + category, + endpointPath, + method, + parameters, + privacy, + result, + available, + note, + available && privacy == PearApiPrivacyClass.Public && method == PearApiRequestMethod.Get && parameters.Length == 0 + ? TimeSpan.FromMinutes(2) + : null); + + private static PearApiParameterDefinition P( + string name, + string label, + string description, + PearApiParameterKind kind = PearApiParameterKind.Text, + bool required = false, + string defaultValue = "", + IReadOnlyList? options = null, + int maxLength = 4096) + => new(name, label, description, kind, required, defaultValue, options, maxLength); +} diff --git a/src/YMhut.Box.Core/Api/PearApiClient.cs b/src/YMhut.Box.Core/Api/PearApiClient.cs new file mode 100644 index 0000000..b16564b --- /dev/null +++ b/src/YMhut.Box.Core/Api/PearApiClient.cs @@ -0,0 +1,491 @@ +using System.Collections.Concurrent; +using System.Diagnostics; +using System.Net; +using System.Net.Http.Headers; +using System.Net.Sockets; +using System.Text; +using System.Text.Json; +using YMhut.Box.Core.Logging; + +namespace YMhut.Box.Core.Api; + +public sealed class PearApiClient : IPearApiClient, IDisposable +{ + public static readonly Uri ServiceRoot = new("https://api.pearapi.ai/api/"); + private const int MaximumResponseBytes = 8 * 1024 * 1024; + private const long MaximumImageBytes = 10L * 1024 * 1024; + private const long MaximumMediaBytes = 50L * 1024 * 1024; + private static readonly TimeSpan MinimumRequestInterval = TimeSpan.FromMilliseconds(250); + + private readonly HttpClient _httpClient; + private readonly ILogService? _logService; + private readonly bool _disposeClient; + private readonly SemaphoreSlim _requestGate = new(1, 1); + private readonly ConcurrentDictionary _cache = new(StringComparer.OrdinalIgnoreCase); + private DateTimeOffset _lastRequestAt = DateTimeOffset.MinValue; + + public PearApiClient(HttpClient? httpClient = null, ILogService? logService = null) + { + _httpClient = httpClient ?? new HttpClient(new SocketsHttpHandler + { + AllowAutoRedirect = false, + AutomaticDecompression = DecompressionMethods.All, + ConnectTimeout = TimeSpan.FromSeconds(10) + }); + _disposeClient = httpClient is null; + _logService = logService; + _httpClient.Timeout = Timeout.InfiniteTimeSpan; + _httpClient.DefaultRequestHeaders.Authorization = null; + _httpClient.DefaultRequestHeaders.Remove("Authorization"); + _httpClient.DefaultRequestHeaders.Remove("X-API-Key"); + if (!_httpClient.DefaultRequestHeaders.UserAgent.Any()) + { + _httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("YMhutBox/2.0 PearApiClient"); + } + } + + public async Task SendAsync(PearApiRequest request, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(request); + if (!PearApiCatalog.TryGet(request.ToolId, out var definition)) + { + return Failure(request.ToolId, "未找到联网工具定义。"); + } + + if (!definition.IsAvailableWithoutKey) + { + return Failure(request.ToolId, string.IsNullOrWhiteSpace(definition.AvailabilityNote) + ? "该接口当前不再支持免 Key 调用。" + : definition.AvailabilityNote); + } + + if (!TryCreateAllowedEndpoint(definition.EndpointPath, out var endpoint)) + { + return Failure(request.ToolId, "接口不在 PearAPI 固定安全路径允许列表中。"); + } + + var values = new Dictionary(request.Parameters ?? new Dictionary(), StringComparer.OrdinalIgnoreCase); + var allowedParameters = definition.Parameters + .Where(parameter => !PearApiPresentationSanitizer.IsHiddenField(parameter.Name)) + .Select(parameter => parameter.Name) + .ToHashSet(StringComparer.OrdinalIgnoreCase); + if (values.Keys.Any(key => !allowedParameters.Contains(key))) + { + return Failure(request.ToolId, "请求包含该工具未声明的参数。"); + } + + var validationError = await ValidateAsync(definition, values, request, cancellationToken).ConfigureAwait(false); + if (validationError is not null) + { + return Failure(request.ToolId, validationError); + } + + var cacheKey = BuildCacheKey(definition, values, request.FilePath); + var cacheDuration = definition.PublicCacheDuration; + if (cacheDuration is { } duration && _cache.TryGetValue(cacheKey, out var cached) && DateTimeOffset.UtcNow - cached.StoredAt < duration) + { + return cached.Response with { IsFromCache = true }; + } + + var stopwatch = Stopwatch.StartNew(); + try + { + await WaitForRateLimitAsync(cancellationToken).ConfigureAwait(false); + using var message = await BuildRequestAsync(definition, endpoint, values, request.FilePath, cancellationToken).ConfigureAwait(false); + using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(definition.HasUpload ? 90 : 45)); + using var linked = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeout.Token); + using var response = await _httpClient.SendAsync(message, HttpCompletionOption.ResponseHeadersRead, linked.Token).ConfigureAwait(false); + var bytes = await ReadBoundedContentAsync(response.Content, linked.Token).ConfigureAwait(false); + var contentType = response.Content.Headers.ContentType?.MediaType ?? "application/octet-stream"; + var isText = contentType.StartsWith("text/", StringComparison.OrdinalIgnoreCase) || + contentType.Contains("json", StringComparison.OrdinalIgnoreCase) || + contentType.Contains("xml", StringComparison.OrdinalIgnoreCase); + var content = isText ? Encoding.UTF8.GetString(bytes) : string.Empty; + if (contentType.Contains("json", StringComparison.OrdinalIgnoreCase)) + { + content = PearApiPresentationSanitizer.SanitizeJson(content); + } + stopwatch.Stop(); + var result = new PearApiResponse( + definition.ToolId, + response.IsSuccessStatusCode, + (int)response.StatusCode, + content, + contentType, + response.IsSuccessStatusCode ? null : FriendlyStatus(response.StatusCode), + DateTimeOffset.UtcNow, + stopwatch.Elapsed, + BinaryContent: isText ? null : bytes); + if (result.Success && cacheDuration is not null) + { + _cache[cacheKey] = new CacheEntry(DateTimeOffset.UtcNow, result); + } + + await WriteLogAsync(response.IsSuccessStatusCode ? "Information" : "Warning", definition.ToolId, (int)response.StatusCode, stopwatch.Elapsed, cancellationToken).ConfigureAwait(false); + return result; + } + catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested) + { + return Failure(definition.ToolId, "请求已取消。", stopwatch.Elapsed); + } + catch (OperationCanceledException) + { + return Failure(definition.ToolId, "PearAPI 响应超时。", stopwatch.Elapsed); + } + catch (Exception exception) when (exception is HttpRequestException or IOException or SocketException or InvalidDataException) + { + await WriteFailureLogAsync(definition.ToolId, exception.GetType().Name, stopwatch.Elapsed, cancellationToken).ConfigureAwait(false); + return Failure(definition.ToolId, "PearAPI 暂时不可用,请稍后重试。", stopwatch.Elapsed); + } + } + + public void Dispose() + { + _requestGate.Dispose(); + if (_disposeClient) + { + _httpClient.Dispose(); + } + } + + private static bool TryCreateAllowedEndpoint(string endpointPath, out Uri endpoint) + { + endpoint = default!; + if (string.IsNullOrWhiteSpace(endpointPath) || !endpointPath.StartsWith("/api/", StringComparison.Ordinal)) + { + return false; + } + + if (!Uri.TryCreate(new Uri("https://api.pearapi.ai"), endpointPath, out var candidate) || + !candidate.Scheme.Equals(Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase) || + !candidate.Host.Equals("api.pearapi.ai", StringComparison.OrdinalIgnoreCase) || + candidate.Port != 443 || + !candidate.AbsolutePath.StartsWith("/api/", StringComparison.Ordinal) || + candidate.UserInfo.Length > 0) + { + return false; + } + + endpoint = candidate; + return true; + } + + private static async Task ValidateAsync( + PearApiToolDefinition definition, + IReadOnlyDictionary values, + PearApiRequest request, + CancellationToken cancellationToken) + { + foreach (var parameter in definition.Parameters.Where(parameter => !PearApiPresentationSanitizer.IsHiddenField(parameter.Name))) + { + values.TryGetValue(parameter.Name, out var value); + value = value?.Trim() ?? string.Empty; + if (parameter.Required && parameter.Kind != PearApiParameterKind.File && value.Length == 0) + { + return $"请填写“{parameter.DisplayName}”。"; + } + + if (value.Length > parameter.MaxLength) + { + return $"“{parameter.DisplayName}”超过允许长度。"; + } + + if (parameter.Options is { Count: > 0 } && value.Length > 0 && !parameter.Options.Contains(value, StringComparer.OrdinalIgnoreCase)) + { + return $"“{parameter.DisplayName}”不是允许的选项。"; + } + + if (parameter.Kind == PearApiParameterKind.Url && value.Length > 0) + { + var urlError = await ValidatePublicUrlAsync(value, cancellationToken).ConfigureAwait(false); + if (urlError is not null) + { + return $"“{parameter.DisplayName}”:{urlError}"; + } + } + + if (parameter.Kind == PearApiParameterKind.Domain && value.Length > 0) + { + var domainError = await ValidatePublicDomainAsync(value, cancellationToken).ConfigureAwait(false); + if (domainError is not null) + { + return $"“{parameter.DisplayName}”:{domainError}"; + } + } + } + + if (!definition.HasUpload) + { + return string.IsNullOrWhiteSpace(request.FilePath) ? null : "该工具不接受文件上传。"; + } + + if (string.IsNullOrWhiteSpace(request.FilePath)) + { + var fileRequired = definition.Parameters.Any(parameter => parameter.Kind == PearApiParameterKind.File && parameter.Required); + return fileRequired ? "请选择要上传的文件。" : null; + } + + if (!request.UploadConfirmed) + { + return "上传前必须确认文件将发送至 PearAPI。"; + } + + return ValidateUpload(request.FilePath, out _); + } + + private static async Task ValidatePublicUrlAsync(string value, CancellationToken cancellationToken) + { + if (!Uri.TryCreate(value, UriKind.Absolute, out var uri) || + (uri.Scheme != Uri.UriSchemeHttp && uri.Scheme != Uri.UriSchemeHttps) || + string.IsNullOrWhiteSpace(uri.Host) || uri.UserInfo.Length > 0) + { + return "仅允许不含凭据的 HTTP(S) 公网地址。"; + } + + if (uri.Host.Equals("localhost", StringComparison.OrdinalIgnoreCase) || uri.Host.EndsWith(".local", StringComparison.OrdinalIgnoreCase)) + { + return "不允许回环或局域网地址。"; + } + + return await ValidatePublicHostAsync(uri.DnsSafeHost, cancellationToken).ConfigureAwait(false); + } + + private static async Task ValidatePublicDomainAsync(string value, CancellationToken cancellationToken) + { + var domain = value.Trim().TrimEnd('.'); + if (domain.Length == 0 || domain.Contains('/') || domain.Contains('\\') || domain.Contains(':') || + domain.Contains('@') || domain.Contains('?') || domain.Contains('#') || + Uri.CheckHostName(domain) == UriHostNameType.Unknown) + { + return "请输入不含协议、端口、路径或凭据的公网域名。"; + } + + return await ValidatePublicHostAsync(domain, cancellationToken).ConfigureAwait(false); + } + + private static async Task ValidatePublicHostAsync(string host, CancellationToken cancellationToken) + { + if (host.Equals("localhost", StringComparison.OrdinalIgnoreCase) || host.EndsWith(".local", StringComparison.OrdinalIgnoreCase)) + { + return "不允许回环或局域网地址。"; + } + + IPAddress[] addresses; + if (IPAddress.TryParse(host, out var literal)) + { + addresses = [literal]; + } + else + { + try + { + addresses = await Dns.GetHostAddressesAsync(host, cancellationToken).ConfigureAwait(false); + } + catch (SocketException) + { + return "域名无法解析,未发送请求。"; + } + } + + return addresses.Length == 0 || addresses.Any(IsPrivateAddress) + ? "不允许回环、链路本地或私网地址。" + : null; + } + + private static bool IsPrivateAddress(IPAddress address) + { + if (IPAddress.IsLoopback(address) || address.Equals(IPAddress.Any) || address.Equals(IPAddress.IPv6Any) || + address.IsIPv6LinkLocal || address.IsIPv6SiteLocal || address.IsIPv6Multicast) + { + return true; + } + + if (address.AddressFamily == AddressFamily.InterNetworkV6 && !address.IsIPv4MappedToIPv6) + { + var ipv6Bytes = address.GetAddressBytes(); + return (ipv6Bytes[0] & 0xFE) == 0xFC; + } + + var bytes = address.AddressFamily == AddressFamily.InterNetworkV6 + ? address.MapToIPv4().GetAddressBytes() + : address.GetAddressBytes(); + return bytes[0] == 0 || bytes[0] == 10 || bytes[0] == 127 || + (bytes[0] == 169 && bytes[1] == 254) || + (bytes[0] == 172 && bytes[1] is >= 16 and <= 31) || + (bytes[0] == 192 && bytes[1] == 168) || + (bytes[0] >= 224); + } + + private static string? ValidateUpload(string path, out MediaTypeHeaderValue? mediaType) + { + mediaType = null; + if (!File.Exists(path)) + { + return "所选文件不存在。"; + } + + var info = new FileInfo(path); + Span header = stackalloc byte[16]; + using var stream = File.OpenRead(path); + var read = stream.Read(header); + var kind = DetectFileKind(header[..read]); + if (kind is null) + { + return "文件真实格式不在允许的图像、音频或视频类型中。"; + } + + var isImage = kind.StartsWith("image/", StringComparison.Ordinal); + var limit = isImage ? MaximumImageBytes : MaximumMediaBytes; + if (info.Length <= 0 || info.Length > limit) + { + return isImage ? "图片大小必须在 10 MiB 以内。" : "音视频大小必须在 50 MiB 以内。"; + } + + mediaType = new MediaTypeHeaderValue(kind); + return null; + } + + private static string? DetectFileKind(ReadOnlySpan value) + { + if (value.StartsWith(new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A })) return "image/png"; + if (value.StartsWith(new byte[] { 0xFF, 0xD8, 0xFF })) return "image/jpeg"; + if (value.StartsWith("GIF87a"u8) || value.StartsWith("GIF89a"u8)) return "image/gif"; + if (value.Length >= 12 && value[..4].SequenceEqual("RIFF"u8) && value[8..12].SequenceEqual("WEBP"u8)) return "image/webp"; + if (value.StartsWith("ID3"u8) || (value.Length >= 2 && value[0] == 0xFF && (value[1] & 0xE0) == 0xE0)) return "audio/mpeg"; + if (value.Length >= 12 && value[..4].SequenceEqual("RIFF"u8) && value[8..12].SequenceEqual("WAVE"u8)) return "audio/wav"; + if (value.StartsWith("OggS"u8)) return "audio/ogg"; + if (value.Length >= 8 && value[4..8].SequenceEqual("ftyp"u8)) return "video/mp4"; + if (value.StartsWith(new byte[] { 0x1A, 0x45, 0xDF, 0xA3 })) return "video/webm"; + return null; + } + + private async Task BuildRequestAsync( + PearApiToolDefinition definition, + Uri endpoint, + IReadOnlyDictionary values, + string? filePath, + CancellationToken cancellationToken) + { + var populated = values + .Where(item => !PearApiPresentationSanitizer.IsHiddenField(item.Key) && !string.IsNullOrWhiteSpace(item.Value)) + .ToArray(); + if (definition.Method == PearApiRequestMethod.Get) + { + var builder = new UriBuilder(endpoint) + { + Query = string.Join("&", populated.Select(item => $"{Uri.EscapeDataString(item.Key)}={Uri.EscapeDataString(item.Value.Trim())}")) + }; + return CreateMessage(HttpMethod.Get, builder.Uri); + } + + var message = CreateMessage(HttpMethod.Post, endpoint); + if (definition.Method == PearApiRequestMethod.PostJson) + { + message.Content = new StringContent(JsonSerializer.Serialize(populated.ToDictionary(item => item.Key, item => item.Value.Trim())), Encoding.UTF8, "application/json"); + return message; + } + + var multipart = new MultipartFormDataContent(); + foreach (var item in populated) + { + multipart.Add(new StringContent(item.Value.Trim(), Encoding.UTF8), item.Key); + } + + if (!string.IsNullOrWhiteSpace(filePath)) + { + var error = ValidateUpload(filePath, out var mediaType); + if (error is not null || mediaType is null) + { + multipart.Dispose(); + message.Dispose(); + throw new InvalidDataException(error ?? "文件格式无效。"); + } + + var stream = File.OpenRead(filePath); + var file = new StreamContent(stream); + file.Headers.ContentType = mediaType; + multipart.Add(file, definition.Parameters.First(parameter => parameter.Kind == PearApiParameterKind.File).Name, Path.GetFileName(filePath)); + } + + message.Content = multipart; + await Task.CompletedTask.ConfigureAwait(false); + cancellationToken.ThrowIfCancellationRequested(); + return message; + } + + private static HttpRequestMessage CreateMessage(HttpMethod method, Uri uri) + { + var message = new HttpRequestMessage(method, uri); + message.Headers.Accept.ParseAdd("application/json, text/plain, image/*, audio/*;q=0.8, */*;q=0.5"); + return message; + } + + private async Task WaitForRateLimitAsync(CancellationToken cancellationToken) + { + await _requestGate.WaitAsync(cancellationToken).ConfigureAwait(false); + try + { + var delay = MinimumRequestInterval - (DateTimeOffset.UtcNow - _lastRequestAt); + if (delay > TimeSpan.Zero) + { + await Task.Delay(delay, cancellationToken).ConfigureAwait(false); + } + + _lastRequestAt = DateTimeOffset.UtcNow; + } + finally + { + _requestGate.Release(); + } + } + + private static string BuildCacheKey(PearApiToolDefinition definition, IReadOnlyDictionary values, string? filePath) + { + if (definition.PrivacyClass != PearApiPrivacyClass.Public || definition.Method != PearApiRequestMethod.Get || values.Any(item => !string.IsNullOrWhiteSpace(item.Value)) || !string.IsNullOrWhiteSpace(filePath)) + { + return $"nocache:{Guid.NewGuid():N}"; + } + + return definition.ToolId; + } + + private static async Task ReadBoundedContentAsync(HttpContent content, CancellationToken cancellationToken) + { + if (content.Headers.ContentLength is > MaximumResponseBytes) + { + throw new InvalidDataException("PearAPI response exceeded the size limit."); + } + + await using var input = await content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); + using var output = new MemoryStream(); + var buffer = new byte[16 * 1024]; + while (true) + { + var read = await input.ReadAsync(buffer, cancellationToken).ConfigureAwait(false); + if (read == 0) break; + if (output.Length + read > MaximumResponseBytes) + { + throw new InvalidDataException("PearAPI response exceeded the size limit."); + } + output.Write(buffer, 0, read); + } + + return output.ToArray(); + } + + private static PearApiResponse Failure(string toolId, string message, TimeSpan? elapsed = null) + => new(toolId, false, 0, string.Empty, "text/plain", message, DateTimeOffset.UtcNow, elapsed ?? TimeSpan.Zero); + + private static string FriendlyStatus(HttpStatusCode statusCode) + => statusCode is HttpStatusCode.Unauthorized or HttpStatusCode.Forbidden + ? "PearAPI 已拒绝免 Key 请求,该接口当前可能要求鉴权。" + : $"PearAPI 返回 HTTP {(int)statusCode}。"; + + private Task WriteLogAsync(string level, string toolId, int statusCode, TimeSpan elapsed, CancellationToken cancellationToken) + => _logService?.WriteAsync(level, "pearapi", "PearAPI request completed", $"tool={toolId}; status={statusCode}; elapsedMs={elapsed.TotalMilliseconds:0}", cancellationToken) ?? Task.CompletedTask; + + private Task WriteFailureLogAsync(string toolId, string failureType, TimeSpan elapsed, CancellationToken cancellationToken) + => _logService?.WriteAsync("Warning", "pearapi", "PearAPI request failed", $"tool={toolId}; failure={failureType}; elapsedMs={elapsed.TotalMilliseconds:0}", cancellationToken) ?? Task.CompletedTask; + + private sealed record CacheEntry(DateTimeOffset StoredAt, PearApiResponse Response); +} diff --git a/src/YMhut.Box.Core/Api/PearApiModels.cs b/src/YMhut.Box.Core/Api/PearApiModels.cs new file mode 100644 index 0000000..28484de --- /dev/null +++ b/src/YMhut.Box.Core/Api/PearApiModels.cs @@ -0,0 +1,92 @@ +namespace YMhut.Box.Core.Api; + +public enum PearApiPrivacyClass +{ + Public, + UserText, + UserUrl, + Financial, + FileUpload +} + +public enum PearApiResultKind +{ + Text, + Json, + Cards, + Table, + RankedList, + News, + Image, + Audio +} + +public enum PearApiRequestMethod +{ + Get, + PostJson, + Multipart +} + +public enum PearApiParameterKind +{ + Text, + MultilineText, + Number, + Date, + Choice, + Url, + Domain, + File +} + +public sealed record PearApiParameterDefinition( + string Name, + string DisplayName, + string Description, + PearApiParameterKind Kind = PearApiParameterKind.Text, + bool Required = false, + string DefaultValue = "", + IReadOnlyList? Options = null, + int MaxLength = 4096); + +public sealed record PearApiToolDefinition( + string ToolId, + int ApiId, + string Name, + string Description, + string Category, + string EndpointPath, + PearApiRequestMethod Method, + IReadOnlyList Parameters, + PearApiPrivacyClass PrivacyClass, + PearApiResultKind ResultKind, + bool IsAvailableWithoutKey = true, + string AvailabilityNote = "", + TimeSpan? PublicCacheDuration = null) +{ + public bool HasUpload => Parameters.Any(parameter => parameter.Kind == PearApiParameterKind.File); +} + +public sealed record PearApiRequest( + string ToolId, + IReadOnlyDictionary? Parameters = null, + string? FilePath = null, + bool UploadConfirmed = false); + +public sealed record PearApiResponse( + string ToolId, + bool Success, + int StatusCode, + string Content, + string ContentType, + string? Error, + DateTimeOffset FetchedAt, + TimeSpan Elapsed, + bool IsFromCache = false, + byte[]? BinaryContent = null); + +public interface IPearApiClient +{ + Task SendAsync(PearApiRequest request, CancellationToken cancellationToken = default); +} diff --git a/src/YMhut.Box.Core/Api/PearApiPresentationSanitizer.cs b/src/YMhut.Box.Core/Api/PearApiPresentationSanitizer.cs new file mode 100644 index 0000000..d79a97a --- /dev/null +++ b/src/YMhut.Box.Core/Api/PearApiPresentationSanitizer.cs @@ -0,0 +1,58 @@ +using System.Text; +using System.Text.Json; + +namespace YMhut.Box.Core.Api; + +public static class PearApiPresentationSanitizer +{ + public static bool IsHiddenField(string? name) + { + if (string.IsNullOrWhiteSpace(name)) return false; + var normalized = new string(name.Where(char.IsLetterOrDigit).Select(char.ToLowerInvariant).ToArray()); + return normalized == "apisource"; + } + + public static string SanitizeJson(string content) + { + if (string.IsNullOrWhiteSpace(content)) return content; + try + { + using var document = JsonDocument.Parse(content); + using var output = new MemoryStream(); + using (var writer = new Utf8JsonWriter(output)) + { + WriteSanitized(writer, document.RootElement); + } + return Encoding.UTF8.GetString(output.ToArray()); + } + catch (JsonException) + { + return content; + } + } + + private static void WriteSanitized(Utf8JsonWriter writer, JsonElement value) + { + switch (value.ValueKind) + { + case JsonValueKind.Object: + writer.WriteStartObject(); + foreach (var property in value.EnumerateObject()) + { + if (IsHiddenField(property.Name)) continue; + writer.WritePropertyName(property.Name); + WriteSanitized(writer, property.Value); + } + writer.WriteEndObject(); + break; + case JsonValueKind.Array: + writer.WriteStartArray(); + foreach (var item in value.EnumerateArray()) WriteSanitized(writer, item); + writer.WriteEndArray(); + break; + default: + value.WriteTo(writer); + break; + } + } +} diff --git a/src/YMhut.Box.Core/App/InstallManifest.cs b/src/YMhut.Box.Core/App/InstallManifest.cs index 6397ac6..1e62ff3 100644 --- a/src/YMhut.Box.Core/App/InstallManifest.cs +++ b/src/YMhut.Box.Core/App/InstallManifest.cs @@ -13,6 +13,8 @@ public sealed record InstallManifest( { public const string RelativePath = "config/install-manifest.ini"; + public int SchemaVersion { get; init; } = 1; + public static InstallManifest Parse(string text) { var release = new Dictionary(StringComparer.OrdinalIgnoreCase); @@ -69,7 +71,14 @@ public sealed record InstallManifest( GetReleaseValue(release, "PackageVersion")); } - return new InstallManifest(releaseInfo, requiredFiles, files); + var schemaVersion = release.TryGetValue("ManifestVersion", out var versionValue) && + int.TryParse(versionValue, out var parsedVersion) && parsedVersion > 0 + ? parsedVersion + : 1; + return new InstallManifest(releaseInfo, requiredFiles, files) + { + SchemaVersion = schemaVersion + }; } public static async Task ReadAsync(string installRoot, CancellationToken cancellationToken = default) diff --git a/src/YMhut.Box.Core/App/OpenSourceReferenceService.cs b/src/YMhut.Box.Core/App/OpenSourceReferenceService.cs index 1a646f2..fb395d3 100644 --- a/src/YMhut.Box.Core/App/OpenSourceReferenceService.cs +++ b/src/YMhut.Box.Core/App/OpenSourceReferenceService.cs @@ -53,6 +53,14 @@ public sealed class OpenSourceReferenceService(AppPaths paths, ILogService? logS }; AddMusicApiReferences(references); + references.Add(new OpenSourceReferenceItem( + "PearAPI", + "Online data provider", + "catalog verified 2026-08-19", + "Provides the fixed allowlisted, free endpoints used by the online tools. Runtime code never scrapes the documentation page and never sends an API key.", + "User text, URLs, financial queries, and selected files are sent to PearAPI only after the user runs the corresponding tool. Service availability and returned content are controlled by PearAPI.", + SourceUrl: "https://api.pearapi.ai/zh/dashboard/api-list", + LicensePath: "https://api.pearapi.ai/zh/disclaimer")); await AddPackageReferencesSafelyAsync(references, cancellationToken).ConfigureAwait(false); await AddBundledToolNoticesSafelyAsync(references, cancellationToken).ConfigureAwait(false); @@ -422,8 +430,9 @@ public sealed class OpenSourceReferenceService(AppPaths paths, ILogService? logS "Cache mechanism attribution" => 4, "Runtime" => 5, "Bundled npm dependencies" => 6, - "NuGet package" => 7, - "Third-party tool notice" => 8, + "Online data provider" => 7, + "NuGet package" => 8, + "Third-party tool notice" => 9, _ => 9 }; } diff --git a/src/YMhut.Box.Core/Data/AuthenticatedAssetPackage.cs b/src/YMhut.Box.Core/Data/AuthenticatedAssetPackage.cs new file mode 100644 index 0000000..751f61c --- /dev/null +++ b/src/YMhut.Box.Core/Data/AuthenticatedAssetPackage.cs @@ -0,0 +1,234 @@ +using System.Buffers.Binary; +using System.IO.Compression; +using System.Security.Cryptography; +using System.Text; +using System.Text.Json; + +namespace YMhut.Box.Core.Data; + +///

    +/// Reads the authenticated package format used for bundled web and reference assets. +/// The key is intentionally an application-level packaging key, not DRM: a user with +/// process-level access can still inspect the decrypted bytes. Authentication is what +/// prevents an untrusted replacement from being accepted by the client. +/// +public static class AuthenticatedAssetPackage +{ + private static readonly byte[] Magic = Encoding.ASCII.GetBytes("YMHUTAS2"); + private const byte SchemaVersion = 2; + private const int SaltLength = 16; + private const int IvLength = 16; + private const int TagLength = 32; + private const int HeaderLength = 8 + 1 + SaltLength + IvLength + sizeof(long) + sizeof(long); + private const long MaximumPackageBytes = 512L * 1024 * 1024; + private const long MaximumEntryBytes = 64L * 1024 * 1024; + private const long MaximumTotalEntryBytes = 256L * 1024 * 1024; + private const int MaximumEntryCount = 4096; + + public sealed record PackageEntry(string Path, byte[] Content, string Sha256); + + public sealed record PackageManifest( + int SchemaVersion, + string BundleId, + IReadOnlyList Files); + + public sealed record PackageManifestEntry(string Path, long Length, string Sha256); + + public static IReadOnlyList ReadVerifiedEntries( + ReadOnlySpan package, + string purpose, + CancellationToken cancellationToken = default) + { + if (package.Length > MaximumPackageBytes) + { + throw new InvalidDataException("Authenticated asset package is too large."); + } + + var payload = Decrypt(package, purpose); + using var archive = new ZipArchive(new MemoryStream(payload, writable: false), ZipArchiveMode.Read); + var manifestEntries = archive.Entries + .Where(entry => string.Equals(entry.FullName, "_manifest.json", StringComparison.OrdinalIgnoreCase)) + .ToArray(); + if (manifestEntries.Length != 1 || manifestEntries[0].Length is < 2 or > 2 * 1024 * 1024) + { + throw new InvalidDataException("Authenticated asset package manifest is missing or invalid."); + } + + var manifestEntry = manifestEntries[0]; + using var manifestStream = manifestEntry.Open(); + var manifest = JsonSerializer.Deserialize(manifestStream, JsonOptions) ?? + throw new InvalidDataException("Authenticated asset package manifest is invalid."); + if (manifest.SchemaVersion != SchemaVersion || + !string.Equals(manifest.BundleId, purpose, StringComparison.Ordinal)) + { + throw new InvalidDataException("Authenticated asset package schema is unsupported."); + } + + var declared = new Dictionary(StringComparer.OrdinalIgnoreCase); + foreach (var item in manifest.Files ?? []) + { + var normalized = NormalizeEntryPath(item.Path); + if (!declared.TryAdd(normalized, item) || item.Length < 0 || item.Length > MaximumEntryBytes || !IsSha256(item.Sha256)) + { + throw new InvalidDataException("Authenticated asset package manifest contains an invalid entry."); + } + } + + if (declared.Count == 0 || declared.Count > MaximumEntryCount) + { + throw new InvalidDataException("Authenticated asset package entry count is invalid."); + } + + var actual = archive.Entries + .Where(entry => !entry.FullName.EndsWith("/", StringComparison.Ordinal)) + .Where(entry => !string.Equals(entry.FullName, "_manifest.json", StringComparison.OrdinalIgnoreCase)) + .ToArray(); + if (actual.Length != declared.Count) + { + throw new InvalidDataException("Authenticated asset package entry list does not match its manifest."); + } + + var result = new List(actual.Length); + long totalLength = 0; + foreach (var entry in actual) + { + cancellationToken.ThrowIfCancellationRequested(); + var normalized = NormalizeEntryPath(entry.FullName); + if (!declared.TryGetValue(normalized, out var expected)) + { + throw new InvalidDataException("Authenticated asset package contains an undeclared entry."); + } + + if (entry.Length < 0 || entry.Length > MaximumEntryBytes || totalLength > MaximumTotalEntryBytes - entry.Length) + { + throw new InvalidDataException("Authenticated asset package expanded size is invalid."); + } + + using var stream = entry.Open(); + using var memory = new MemoryStream(entry.Length > 0 && entry.Length <= int.MaxValue ? (int)entry.Length : 0); + stream.CopyTo(memory); + var content = memory.ToArray(); + if (content.LongLength != expected.Length) + { + throw new InvalidDataException($"Authenticated asset entry length mismatch: {normalized}"); + } + + var hash = Convert.ToHexString(SHA256.HashData(content)).ToLowerInvariant(); + if (!CryptographicOperations.FixedTimeEquals( + Encoding.ASCII.GetBytes(hash), + Encoding.ASCII.GetBytes(expected.Sha256.ToLowerInvariant()))) + { + throw new InvalidDataException($"Authenticated asset entry hash mismatch: {normalized}"); + } + + totalLength += content.LongLength; + result.Add(new PackageEntry(normalized, content, hash)); + } + + return result; + } + + public static ZipArchive OpenZipArchive(ReadOnlySpan package, string purpose) + { + var payload = Decrypt(package, purpose); + return new ZipArchive(new MemoryStream(payload, writable: false), ZipArchiveMode.Read, leaveOpen: false); + } + + public static string NormalizeEntryPath(string path) + { + if (string.IsNullOrWhiteSpace(path)) + { + throw new InvalidDataException("Authenticated asset entry path is empty."); + } + + if (path.StartsWith('/') || path.StartsWith('\\') || Path.IsPathRooted(path)) + { + throw new InvalidDataException("Authenticated asset entry path must be relative."); + } + + var normalized = path.Replace('\\', '/'); + var segments = normalized.Split('/', StringSplitOptions.None); + if (normalized.Length > 240 || segments.Any(segment => + segment.Length == 0 || segment is "." or ".." || segment.Contains(':') || segment.Any(char.IsControl))) + { + throw new InvalidDataException("Authenticated asset entry path is unsafe."); + } + + return normalized; + } + + private static byte[] Decrypt(ReadOnlySpan package, string purpose) + { + if (package.Length < HeaderLength + TagLength || !package[..Magic.Length].SequenceEqual(Magic)) + { + throw new InvalidDataException("Authenticated asset package header is invalid."); + } + + var version = package[Magic.Length]; + if (version != SchemaVersion) + { + throw new InvalidDataException("Authenticated asset package version is unsupported."); + } + + var offset = Magic.Length + 1; + var salt = package.Slice(offset, SaltLength).ToArray(); + offset += SaltLength; + var iv = package.Slice(offset, IvLength).ToArray(); + offset += IvLength; + var plainLength = BinaryPrimitives.ReadInt64LittleEndian(package.Slice(offset, sizeof(long))); + offset += sizeof(long); + var cipherLength = BinaryPrimitives.ReadInt64LittleEndian(package.Slice(offset, sizeof(long))); + if (plainLength < 0 || plainLength > MaximumPackageBytes || cipherLength <= 0 || cipherLength > MaximumPackageBytes || + cipherLength > package.Length - HeaderLength - TagLength || HeaderLength + cipherLength + TagLength != package.Length) + { + throw new InvalidDataException("Authenticated asset package lengths are invalid."); + } + + var signedLength = checked(HeaderLength + (int)cipherLength); + var tag = package.Slice(signedLength, TagLength); + var keys = DeriveKeys(salt, purpose); + using var hmac = new HMACSHA256(keys.MacKey); + var calculatedTag = hmac.ComputeHash(package[..signedLength].ToArray()); + if (!CryptographicOperations.FixedTimeEquals(calculatedTag, tag)) + { + throw new InvalidDataException("Authenticated asset package signature is invalid."); + } + + try + { + using var aes = Aes.Create(); + aes.Key = keys.EncryptionKey; + aes.IV = iv; + aes.Mode = CipherMode.CBC; + aes.Padding = PaddingMode.PKCS7; + using var decryptor = aes.CreateDecryptor(); + var cipher = package.Slice(HeaderLength, (int)cipherLength).ToArray(); + var plain = decryptor.TransformFinalBlock(cipher, 0, cipher.Length); + if (plain.LongLength != plainLength) + { + throw new InvalidDataException("Authenticated asset package plaintext length is invalid."); + } + + return plain; + } + catch (CryptographicException exception) + { + throw new InvalidDataException("Authenticated asset package decryption failed.", exception); + } + } + + private static (byte[] EncryptionKey, byte[] MacKey) DeriveKeys(ReadOnlySpan salt, string purpose) + { + var purposeBytes = Encoding.UTF8.GetBytes("YMhut.Box.AssetPackage.v2|" + purpose); + var material = new byte[purposeBytes.Length + salt.Length]; + purposeBytes.CopyTo(material, 0); + salt.CopyTo(material.AsSpan(purposeBytes.Length)); + var digest = SHA512.HashData(material); + return (digest[..32], digest[32..]); + } + + private static bool IsSha256(string? value) + => !string.IsNullOrWhiteSpace(value) && value.Length == 64 && value.All(Uri.IsHexDigit); + + private static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web); +} diff --git a/src/YMhut.Box.Core/Data/ReferenceDataService.cs b/src/YMhut.Box.Core/Data/ReferenceDataService.cs index 80b6919..5d48610 100644 --- a/src/YMhut.Box.Core/Data/ReferenceDataService.cs +++ b/src/YMhut.Box.Core/Data/ReferenceDataService.cs @@ -43,6 +43,7 @@ public interface IReferenceDataService public sealed class ReferenceDataService(AppPaths paths) : IReferenceDataService { private static readonly byte[] YbinMagic = Encoding.ASCII.GetBytes("YMHUTYBIN1"); + private static readonly byte[] AuthenticatedYbinMagic = Encoding.ASCII.GetBytes("YMHUTAS2"); private static readonly byte[] YbinKey = SHA256.HashData(Encoding.UTF8.GetBytes("YMhut.Box.ReferenceData.YBin.v1")); public async Task ReadTextAsync(string relativePath, CancellationToken cancellationToken = default) @@ -326,6 +327,12 @@ public sealed class ReferenceDataService(AppPaths paths) : IReferenceDataService if (package.EndsWith(".ybin", StringComparison.OrdinalIgnoreCase)) { var encrypted = File.ReadAllBytes(package); + if (encrypted.Length >= AuthenticatedYbinMagic.Length && + encrypted.AsSpan(0, AuthenticatedYbinMagic.Length).SequenceEqual(AuthenticatedYbinMagic)) + { + return AuthenticatedAssetPackage.OpenZipArchive(encrypted, "reference-data"); + } + if (encrypted.Length <= YbinMagic.Length + 16 || !encrypted.AsSpan(0, YbinMagic.Length).SequenceEqual(YbinMagic)) { diff --git a/src/YMhut.Box.Core/Plugins/PluginBridgePolicy.cs b/src/YMhut.Box.Core/Plugins/PluginBridgePolicy.cs index 42c88f9..51353af 100644 --- a/src/YMhut.Box.Core/Plugins/PluginBridgePolicy.cs +++ b/src/YMhut.Box.Core/Plugins/PluginBridgePolicy.cs @@ -26,6 +26,7 @@ public static class PluginBridgePolicy ["clipboard.writeText"] = PluginPermission.Clipboard, ["file.openPicker"] = PluginPermission.FilePicker, ["file.savePicker"] = PluginPermission.FilePicker, + ["externalTool.launch"] = PluginPermission.ExternalTool, ["openExternal"] = PluginPermission.OpenExternal }; diff --git a/src/YMhut.Box.Core/Plugins/PluginModels.cs b/src/YMhut.Box.Core/Plugins/PluginModels.cs index 5e527d8..cd60072 100644 --- a/src/YMhut.Box.Core/Plugins/PluginModels.cs +++ b/src/YMhut.Box.Core/Plugins/PluginModels.cs @@ -25,7 +25,8 @@ public enum PluginPermission FileSystemWrite, EnvironmentRead, OpenSystemBrowser, - ExternalRuntime + ExternalRuntime, + ExternalTool } public enum PluginSurfaceKind @@ -69,7 +70,8 @@ public sealed record PluginManifest( PluginRequirementsSpec? Requirements = null, IReadOnlyDictionary? PermissionReasons = null, PluginNetworkSpec? Network = null, - bool BuiltIn = false) + bool BuiltIn = false, + IReadOnlyList? ToolBindings = null) { public static readonly string FileName = "ymhut.plugin.json"; @@ -115,7 +117,59 @@ public sealed record PluginTauriSpec( string TemplateVersion = "1", bool ShellPanel = true, bool BuildOnCreate = true, - bool RebuildOnMissingOrChanged = true); + bool RebuildOnMissingOrChanged = true, + string DistDirectory = "dist", + string HostApiVersion = "2"); + +public enum PluginToolArgumentKind +{ + Text, + Integer, + Boolean, + FilePath, + Choice +} + +public sealed record PluginToolFileSpec( + string Path, + string Sha256); + +public sealed record PluginToolArgumentSpec( + string Name, + PluginToolArgumentKind Kind = PluginToolArgumentKind.Text, + bool Required = false, + int MaxLength = 1024, + IReadOnlyList? Choices = null); + +public sealed record PluginToolBindingSpec( + string Id, + string Name, + string Executable, + IReadOnlyList Files, + IReadOnlyList? Arguments = null, + IReadOnlyList? Parameters = null, + string WorkingDirectory = ".", + string Architecture = "x64", + int TimeoutMs = 0); + +public sealed record PluginPackageManifest( + string Format, + int SchemaVersion, + string PluginId, + string PluginVersion, + string ManifestSha256, + DateTimeOffset CreatedAt, + IReadOnlyList? Files = null) +{ + public const string CurrentFormat = "ymplugin"; + + public const int CurrentSchemaVersion = 1; +} + +public sealed record PluginPackageFile( + string Path, + long Length, + string Sha256); public sealed record PluginCommandSpec( string Id, @@ -202,7 +256,13 @@ public static class PluginPermissionPolicy : [], RunToolIds = permission == PluginPermission.RunTool ? Normalize(manifest.Network?.RunToolIds) - : [] + : [], + ExternalRuntime = permission is PluginPermission.ExternalRuntime or PluginPermission.ExternalTool + ? manifest.Tauri + : null, + ToolBindings = permission is PluginPermission.ExternalRuntime or PluginPermission.ExternalTool + ? manifest.ToolBindings + : null }; var json = JsonSerializer.Serialize(policy); return Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(json))); @@ -279,4 +339,9 @@ public static class PluginIds [JsonSerializable(typeof(PluginRequirementsSpec))] [JsonSerializable(typeof(PluginNetworkSpec))] [JsonSerializable(typeof(PluginTauriSpec))] +[JsonSerializable(typeof(PluginToolFileSpec))] +[JsonSerializable(typeof(PluginToolArgumentSpec))] +[JsonSerializable(typeof(PluginToolBindingSpec))] +[JsonSerializable(typeof(PluginPackageManifest))] +[JsonSerializable(typeof(PluginPackageFile))] internal sealed partial class PluginJsonContext : JsonSerializerContext; diff --git a/src/YMhut.Box.Core/Plugins/PluginPackageService.cs b/src/YMhut.Box.Core/Plugins/PluginPackageService.cs index 2b49f16..91572b3 100644 --- a/src/YMhut.Box.Core/Plugins/PluginPackageService.cs +++ b/src/YMhut.Box.Core/Plugins/PluginPackageService.cs @@ -1,14 +1,18 @@ using System.Text; using System.Text.Json; using System.Text.Json.Serialization; +using System.IO.Compression; +using System.Security.Cryptography; using YMhut.Box.Core.App; +using YMhut.Box.Core.Plugins.Runtime; namespace YMhut.Box.Core.Plugins; public enum PluginTemplateKind { ZeroPermissionWeb, - BridgeNetwork + BridgeNetwork, + TauriPrebuilt } public sealed record PluginPackageResult(bool Succeeded, string Message, string? PluginId = null, string? Path = null); @@ -19,16 +23,22 @@ public interface IPluginPackageService Task ImportFolderAsync(string sourceDirectory, string pluginsRoot, CancellationToken cancellationToken = default); + Task ImportPackageAsync(string packagePath, string pluginsRoot, CancellationToken cancellationToken = default); + + Task ExportPackageAsync(LoadedPlugin plugin, string packagePath, CancellationToken cancellationToken = default); + Task ClearDataAsync(LoadedPlugin plugin, CancellationToken cancellationToken = default); Task UninstallAsync(LoadedPlugin plugin, string pluginsRoot, CancellationToken cancellationToken = default); } -public sealed class PluginPackageService(AppPaths paths, IPluginStateStore stateStore) : IPluginPackageService +public sealed class PluginPackageService(AppPaths paths, IPluginStateStore stateStore) : IPluginPackageService, IPluginPackageGenerator { - private static readonly HashSet NativeExtensions = new(StringComparer.OrdinalIgnoreCase) + private const string PackageMetadataName = ".ymhut-package.json"; + private const long MaximumPackageBytes = 512L * 1024 * 1024; + private static readonly HashSet BlockedNativeExtensions = new(StringComparer.OrdinalIgnoreCase) { - ".exe", ".dll", ".com", ".scr", ".sys", ".msi", ".msix", ".msixbundle", ".appx", ".appxbundle" + ".com", ".scr", ".sys", ".msi", ".msix", ".msixbundle", ".appx", ".appxbundle" }; private static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web) { @@ -66,9 +76,11 @@ public sealed class PluginPackageService(AppPaths paths, IPluginStateStore state var manifest = CreateManifest(id, string.IsNullOrWhiteSpace(name) ? id : name.Trim(), kind); await File.WriteAllTextAsync(Path.Combine(target, PluginManifest.FileName), JsonSerializer.Serialize(manifest, JsonOptions), Encoding.UTF8, cancellationToken).ConfigureAwait(false); await File.WriteAllTextAsync(Path.Combine(target, "README.md"), TemplateReadme(manifest), Encoding.UTF8, cancellationToken).ConfigureAwait(false); - await File.WriteAllTextAsync(Path.Combine(target, "index.html"), TemplateHtml(manifest), Encoding.UTF8, cancellationToken).ConfigureAwait(false); - await File.WriteAllTextAsync(Path.Combine(target, "style.css"), TemplateCss, Encoding.UTF8, cancellationToken).ConfigureAwait(false); - await File.WriteAllTextAsync(Path.Combine(target, "main.js"), TemplateJavaScript(kind), Encoding.UTF8, cancellationToken).ConfigureAwait(false); + var contentRoot = kind == PluginTemplateKind.TauriPrebuilt ? Path.Combine(target, "dist") : target; + Directory.CreateDirectory(contentRoot); + await File.WriteAllTextAsync(Path.Combine(contentRoot, "index.html"), TemplateHtml(manifest), Encoding.UTF8, cancellationToken).ConfigureAwait(false); + await File.WriteAllTextAsync(Path.Combine(contentRoot, "style.css"), TemplateCss, Encoding.UTF8, cancellationToken).ConfigureAwait(false); + await File.WriteAllTextAsync(Path.Combine(contentRoot, "main.js"), TemplateJavaScript(kind), Encoding.UTF8, cancellationToken).ConfigureAwait(false); if (kind == PluginTemplateKind.ZeroPermissionWeb) { await File.WriteAllTextAsync(Path.Combine(target, "worker.js"), "self.onmessage = e => self.postMessage({ doubled: Number(e.data) * 2 });\n", Encoding.UTF8, cancellationToken).ConfigureAwait(false); @@ -97,38 +109,7 @@ public sealed class PluginPackageService(AppPaths paths, IPluginStateStore state try { await CopyDirectoryAsync(source, stagingRoot, cancellationToken).ConfigureAwait(false); - var manifestPath = Path.Combine(stagingRoot, PluginManifest.FileName); - if (!File.Exists(manifestPath)) - { - return new(false, "The selected folder has no ymhut.plugin.json."); - } - PluginManifest? manifest; - await using (var stream = File.OpenRead(manifestPath)) - { - manifest = await JsonSerializer.DeserializeAsync(stream, JsonOptions, cancellationToken).ConfigureAwait(false); - } - if (manifest is null || !PluginIds.IsSafeId(manifest.Id)) - { - return new(false, "The plugin manifest has an invalid ID."); - } - if (manifest.BuiltIn) - { - return new(false, "Imported packages cannot claim built-in status."); - } - var errors = PluginRegistryService.ValidatePackage(manifest, stagingRoot); - if (errors.Count > 0) - { - return new(false, $"Plugin validation failed: {string.Join("; ", errors.Take(4))}", manifest.Id); - } - - var target = Path.GetFullPath(Path.Combine(pluginsRoot, PluginIds.Normalize(manifest.Id))); - if (!PluginRegistryService.IsInside(pluginsRoot, target) || Directory.Exists(target)) - { - return new(false, "A plugin with the same ID already exists.", manifest.Id); - } - Directory.CreateDirectory(pluginsRoot); - Directory.Move(stagingRoot, target); - return new(true, "Plugin folder imported.", manifest.Id, target); + return await FinalizeImportAsync(stagingRoot, pluginsRoot, cancellationToken).ConfigureAwait(false); } finally { @@ -136,6 +117,175 @@ public sealed class PluginPackageService(AppPaths paths, IPluginStateStore state } } + public async Task ImportPackageAsync( + string packagePath, + string pluginsRoot, + CancellationToken cancellationToken = default) + { + if (!File.Exists(packagePath) || !string.Equals(Path.GetExtension(packagePath), ".ymplugin", StringComparison.OrdinalIgnoreCase)) + { + return new(false, "The selected file is not a .ymplugin package."); + } + + var stagingRoot = Path.Combine(paths.Cache, "PluginImports", Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(stagingRoot); + try + { + using var archive = ZipFile.OpenRead(packagePath); + if (archive.Entries.Count > 5000 || archive.Entries.Sum(entry => entry.Length) > MaximumPackageBytes) + { + return new(false, "The plugin package exceeds the supported size or file-count limit."); + } + foreach (var entry in archive.Entries) + { + cancellationToken.ThrowIfCancellationRequested(); + var relative = entry.FullName.Replace('/', Path.DirectorySeparatorChar); + var target = Path.GetFullPath(Path.Combine(stagingRoot, relative)); + if (string.IsNullOrWhiteSpace(relative) || !PluginRegistryService.IsInside(stagingRoot, target)) + { + return new(false, "The plugin package contains an unsafe path."); + } + if (entry.FullName.EndsWith("/", StringComparison.Ordinal)) + { + Directory.CreateDirectory(target); + continue; + } + Directory.CreateDirectory(Path.GetDirectoryName(target)!); + await using var input = entry.Open(); + await using var output = new FileStream(target, FileMode.CreateNew, FileAccess.Write, FileShare.None, 81920, FileOptions.Asynchronous); + await input.CopyToAsync(output, cancellationToken).ConfigureAwait(false); + } + + var metadataPath = Path.Combine(stagingRoot, PackageMetadataName); + if (!File.Exists(metadataPath)) + { + return new(false, "The .ymplugin package metadata is missing."); + } + var metadata = JsonSerializer.Deserialize(await File.ReadAllTextAsync(metadataPath, cancellationToken).ConfigureAwait(false), JsonOptions); + var manifestPath = Path.Combine(stagingRoot, PluginManifest.FileName); + if (metadata is null || metadata.Format != PluginPackageManifest.CurrentFormat || + metadata.SchemaVersion != PluginPackageManifest.CurrentSchemaVersion || !File.Exists(manifestPath) || + !string.Equals(metadata.ManifestSha256, await HashFileAsync(manifestPath, cancellationToken).ConfigureAwait(false), StringComparison.OrdinalIgnoreCase)) + { + return new(false, "The .ymplugin package metadata or manifest hash is invalid."); + } + var inventoryError = await ValidatePackageInventoryAsync(stagingRoot, metadata.Files, cancellationToken).ConfigureAwait(false); + if (inventoryError is not null) + { + return new(false, inventoryError); + } + var manifest = JsonSerializer.Deserialize(await File.ReadAllTextAsync(manifestPath, cancellationToken).ConfigureAwait(false), JsonOptions); + if (manifest is null || + !string.Equals(metadata.PluginId, manifest.Id, StringComparison.OrdinalIgnoreCase) || + !string.Equals(metadata.PluginVersion, manifest.Version, StringComparison.Ordinal)) + { + return new(false, "The .ymplugin package identity does not match its manifest."); + } + return await FinalizeImportAsync(stagingRoot, pluginsRoot, cancellationToken).ConfigureAwait(false); + } + catch (Exception exception) when (exception is InvalidDataException or JsonException or IOException or UnauthorizedAccessException) + { + return new(false, "The .ymplugin archive is damaged or uses an unsupported format."); + } + finally + { + _ = TryDeleteDirectory(stagingRoot); + } + } + + public async Task ExportPackageAsync( + LoadedPlugin plugin, + string packagePath, + CancellationToken cancellationToken = default) + { + if (!plugin.IsValid || !Directory.Exists(plugin.RootPath)) + { + return new(false, "Only a valid installed plugin can be packaged.", plugin.Manifest.Id); + } + var errors = PluginRegistryService.ValidatePackage(plugin.Manifest, plugin.RootPath); + if (errors.Count > 0) + { + return new(false, $"Plugin validation failed: {string.Join("; ", errors.Take(4))}", plugin.Manifest.Id); + } + + packagePath = Path.ChangeExtension(Path.GetFullPath(packagePath), ".ymplugin"); + Directory.CreateDirectory(Path.GetDirectoryName(packagePath)!); + var temporary = packagePath + $".{Environment.ProcessId}.tmp"; + try + { + if (File.Exists(temporary)) File.Delete(temporary); + var sourceFiles = Directory.EnumerateFiles(plugin.RootPath, "*", SearchOption.AllDirectories) + .Where(file => !string.Equals(Path.GetFileName(file), PackageMetadataName, StringComparison.OrdinalIgnoreCase)) + .Select(file => new + { + FullPath = file, + RelativePath = Path.GetRelativePath(plugin.RootPath, file).Replace('\\', '/') + }) + .OrderBy(file => file.RelativePath, StringComparer.Ordinal) + .ToArray(); + var inventory = new List(sourceFiles.Length); + foreach (var file in sourceFiles) + { + cancellationToken.ThrowIfCancellationRequested(); + inventory.Add(new PluginPackageFile( + file.RelativePath, + new FileInfo(file.FullPath).Length, + await HashFileAsync(file.FullPath, cancellationToken).ConfigureAwait(false))); + } + using (var archive = ZipFile.Open(temporary, ZipArchiveMode.Create)) + { + foreach (var file in sourceFiles) + { + cancellationToken.ThrowIfCancellationRequested(); + var entry = archive.CreateEntry(file.RelativePath, CompressionLevel.SmallestSize); + await using var input = File.OpenRead(file.FullPath); + await using var output = entry.Open(); + await input.CopyToAsync(output, cancellationToken).ConfigureAwait(false); + } + var manifestPath = Path.Combine(plugin.RootPath, PluginManifest.FileName); + var metadata = new PluginPackageManifest( + PluginPackageManifest.CurrentFormat, + PluginPackageManifest.CurrentSchemaVersion, + plugin.Manifest.Id, + plugin.Manifest.Version, + await HashFileAsync(manifestPath, cancellationToken).ConfigureAwait(false), + DateTimeOffset.UtcNow, + inventory); + var metadataEntry = archive.CreateEntry(PackageMetadataName, CompressionLevel.SmallestSize); + await using var writer = new StreamWriter(metadataEntry.Open(), new UTF8Encoding(false)); + await writer.WriteAsync(JsonSerializer.Serialize(metadata, JsonOptions)).ConfigureAwait(false); + } + File.Move(temporary, packagePath, true); + return new(true, "Plugin package created.", plugin.Manifest.Id, packagePath); + } + finally + { + if (File.Exists(temporary)) File.Delete(temporary); + } + } + + public async Task CreateAsync( + PluginPackageCreateRequest request, + CancellationToken cancellationToken = default) + { + var pluginsRoot = PluginRegistryService.DefaultPluginsRoot(paths); + var result = await CreateTemplateAsync(pluginsRoot, request.Id, request.Name, PluginTemplateKind.TauriPrebuilt, cancellationToken).ConfigureAwait(false); + if (!result.Succeeded || string.IsNullOrWhiteSpace(result.Path)) + { + throw new InvalidOperationException(result.Message); + } + if (!string.IsNullOrWhiteSpace(request.SourceWebDirectory) && Directory.Exists(request.SourceWebDirectory)) + { + await CopyDirectoryAsync(request.SourceWebDirectory, Path.Combine(result.Path, "dist"), cancellationToken).ConfigureAwait(false); + } + var manifestPath = Path.Combine(result.Path, PluginManifest.FileName); + var manifest = JsonSerializer.Deserialize(await File.ReadAllTextAsync(manifestPath, cancellationToken).ConfigureAwait(false), JsonOptions) + ?? throw new InvalidDataException("The generated plugin manifest is invalid."); + var state = await stateStore.GetStateAsync(manifest.Id, cancellationToken).ConfigureAwait(false); + var plugin = new LoadedPlugin(manifest, result.Path, state, PluginRegistryService.ValidatePackage(manifest, result.Path)); + return new PluginPackageCreateResult(plugin, result.Path, manifestPath, null); + } + public async Task ClearDataAsync(LoadedPlugin plugin, CancellationToken cancellationToken = default) { await stateStore.ClearPluginDataAsync(plugin.Manifest.Id, includeState: false, cancellationToken).ConfigureAwait(false); @@ -168,6 +318,28 @@ public sealed class PluginPackageService(AppPaths paths, IPluginStateStore state private static PluginManifest CreateManifest(string id, string name, PluginTemplateKind kind) { + if (kind == PluginTemplateKind.TauriPrebuilt) + { + return new PluginManifest( + id, + name, + "1.0.0", + "Local developer", + "Prebuilt Tauri surface hosted by the bundled YMhut runtime.", + "dist/index.html", + [PluginPermission.ExternalRuntime], + [new PluginSurface(PluginSurfaceKind.ToolboxTool, "main", name, "Prebuilt Tauri plugin surface", "dist/index.html", "plugin")], + ["dist", "README.md"], + PluginRuntimeKind.Tauri, + Security: new PluginSecuritySpec([PluginPermission.ExternalRuntime]), + Tauri: new PluginTauriSpec(BuildOnCreate: false, RebuildOnMissingOrChanged: false), + ManifestVersion: PluginManifest.CurrentManifestVersion, + ApiVersion: "2", + PermissionReasons: new Dictionary + { + [PluginPermission.ExternalRuntime] = "Render the prebuilt plugin UI in the bundled controlled Tauri host." + }); + } var permissions = kind == PluginTemplateKind.BridgeNetwork ? new[] { PluginPermission.Http, PluginPermission.Log, PluginPermission.Output } : []; @@ -203,7 +375,9 @@ public sealed class PluginPackageService(AppPaths paths, IPluginStateStore state Network: network); } - private static string TemplateReadme(PluginManifest manifest) => $"# {manifest.Name}\n\nManifest v3 WebView sample. Local HTML/CSS/JS needs no client permission. All client and remote-service access must use declared scopes.\n"; + private static string TemplateReadme(PluginManifest manifest) => manifest.Runtime == PluginRuntimeKind.Tauri + ? $"# {manifest.Name}\n\nManifest v3 prebuilt Tauri sample. Put production-ready HTML/CSS/JS in dist/. YMhut Box supplies the fixed host; this package must not depend on Node, npm, Rust, or a private Tauri executable at runtime.\n" + : $"# {manifest.Name}\n\nManifest v3 WebView sample. Local HTML/CSS/JS needs no client permission. All client and remote-service access must use declared scopes.\n"; private static string TemplateHtml(PluginManifest manifest) => $""" @@ -234,7 +408,7 @@ public sealed class PluginPackageService(AppPaths paths, IPluginStateStore state status.textContent = `Wasm result: ${wasm.instance.exports.add(20, 22)}`; }); """ - : """ + : kind == PluginTemplateKind.BridgeNetwork ? """ const status = document.querySelector('#status'); document.querySelector('#run').addEventListener('click', async () => { const response = await window.ymhut.http.fetch({ url: 'https://api.ipify.org?format=json' }); @@ -243,6 +417,11 @@ public sealed class PluginPackageService(AppPaths paths, IPluginStateStore state await window.ymhut.output.set(status.textContent); await window.ymhut.log.info('Bridge/network sample completed'); }); + """ : """ + const status = document.querySelector('#status'); + document.querySelector('#run').addEventListener('click', async () => { + status.textContent = `Bundled Tauri host ready for ${window.__YMHT_RUNTIME__?.pluginId ?? 'plugin'}`; + }); """; private static bool HasUnsafePackageEntry(string root, out string? unsafeEntry) @@ -257,7 +436,7 @@ public sealed class PluginPackageService(AppPaths paths, IPluginStateStore state { var attributes = File.GetAttributes(entry); if ((attributes & FileAttributes.ReparsePoint) != 0 || - ((attributes & FileAttributes.Directory) == 0 && NativeExtensions.Contains(Path.GetExtension(entry)))) + ((attributes & FileAttributes.Directory) == 0 && BlockedNativeExtensions.Contains(Path.GetExtension(entry)))) { unsafeEntry = entry; return true; @@ -271,6 +450,99 @@ public sealed class PluginPackageService(AppPaths paths, IPluginStateStore state return false; } + private static async Task FinalizeImportAsync( + string stagingRoot, + string pluginsRoot, + CancellationToken cancellationToken) + { + var manifestPath = Path.Combine(stagingRoot, PluginManifest.FileName); + if (!File.Exists(manifestPath)) + { + return new(false, "The selected plugin has no ymhut.plugin.json."); + } + PluginManifest? manifest; + await using (var stream = File.OpenRead(manifestPath)) + { + manifest = await JsonSerializer.DeserializeAsync(stream, JsonOptions, cancellationToken).ConfigureAwait(false); + } + if (manifest is null || !PluginIds.IsSafeId(manifest.Id)) + { + return new(false, "The plugin manifest has an invalid ID."); + } + if (manifest.BuiltIn) + { + return new(false, "Imported packages cannot claim built-in status."); + } + var errors = PluginRegistryService.ValidatePackage(manifest, stagingRoot); + if (errors.Count > 0) + { + return new(false, $"Plugin validation failed: {string.Join("; ", errors.Take(4))}", manifest.Id); + } + var target = Path.GetFullPath(Path.Combine(pluginsRoot, PluginIds.Normalize(manifest.Id))); + if (!PluginRegistryService.IsInside(pluginsRoot, target) || Directory.Exists(target)) + { + return new(false, "A plugin with the same ID already exists.", manifest.Id); + } + Directory.CreateDirectory(pluginsRoot); + Directory.Move(stagingRoot, target); + return new(true, "Plugin imported.", manifest.Id, target); + } + + private static async Task HashFileAsync(string path, CancellationToken cancellationToken) + { + await using var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 81920, FileOptions.Asynchronous | FileOptions.SequentialScan); + return Convert.ToHexString(await SHA256.HashDataAsync(stream, cancellationToken).ConfigureAwait(false)); + } + + private static async Task ValidatePackageInventoryAsync( + string root, + IReadOnlyList? inventory, + CancellationToken cancellationToken) + { + if (inventory is null || inventory.Count == 0 || inventory.Count > 5000) + { + return "The .ymplugin package file inventory is missing or invalid."; + } + + var expected = new Dictionary(StringComparer.OrdinalIgnoreCase); + foreach (var item in inventory) + { + if (string.IsNullOrWhiteSpace(item.Path) || string.IsNullOrWhiteSpace(item.Sha256)) + { + return "The .ymplugin package file inventory contains an unsafe or duplicate entry."; + } + var relative = item.Path.Replace('/', Path.DirectorySeparatorChar); + var fullPath = Path.GetFullPath(Path.Combine(root, relative)); + if (string.IsNullOrWhiteSpace(item.Path) || item.Length < 0 || item.Length > MaximumPackageBytes || + item.Sha256.Length != 64 || !item.Sha256.All(Uri.IsHexDigit) || + !PluginRegistryService.IsInside(root, fullPath) || + string.Equals(Path.GetFileName(fullPath), PackageMetadataName, StringComparison.OrdinalIgnoreCase) || + !expected.TryAdd(Path.GetRelativePath(root, fullPath).Replace('\\', '/'), item)) + { + return "The .ymplugin package file inventory contains an unsafe or duplicate entry."; + } + } + + var actualFiles = Directory.EnumerateFiles(root, "*", SearchOption.AllDirectories) + .Where(file => !string.Equals(Path.GetFileName(file), PackageMetadataName, StringComparison.OrdinalIgnoreCase)) + .ToArray(); + if (actualFiles.Length != expected.Count) + { + return "The .ymplugin package file inventory does not match the archive."; + } + foreach (var file in actualFiles) + { + cancellationToken.ThrowIfCancellationRequested(); + var relative = Path.GetRelativePath(root, file).Replace('\\', '/'); + if (!expected.TryGetValue(relative, out var item) || new FileInfo(file).Length != item.Length || + !string.Equals(await HashFileAsync(file, cancellationToken).ConfigureAwait(false), item.Sha256, StringComparison.OrdinalIgnoreCase)) + { + return $"The .ymplugin package file failed integrity validation: {relative}"; + } + } + return null; + } + private static async Task CopyDirectoryAsync(string source, string target, CancellationToken cancellationToken) { Directory.CreateDirectory(target); diff --git a/src/YMhut.Box.Core/Plugins/PluginRegistryService.cs b/src/YMhut.Box.Core/Plugins/PluginRegistryService.cs index a932a95..0160d46 100644 --- a/src/YMhut.Box.Core/Plugins/PluginRegistryService.cs +++ b/src/YMhut.Box.Core/Plugins/PluginRegistryService.cs @@ -1,6 +1,9 @@ using System.Text.Json; using System.Text.Json.Serialization; +using System.Text; using System.Runtime.InteropServices; +using System.Security.Cryptography; +using System.Text.RegularExpressions; using YMhut.Box.Core.App; using YMhut.Box.Core.Logging; using YMhut.Box.Core.Settings; @@ -333,6 +336,223 @@ public sealed class PluginRegistryService( errors.Add("Plugins that declare commands must request ShellExecute or ScriptExecute permission."); } } + + ValidateTauriPackage(manifest, root, declaredPermissions, requiredPermissions, errors, strict); + } + + private static void ValidateTauriPackage( + PluginManifest manifest, + string root, + ISet declaredPermissions, + IReadOnlyList requiredPermissions, + IList errors, + bool strict) + { + var bindings = manifest.ToolBindings ?? []; + if (bindings.Count > 0 && manifest.Runtime != PluginRuntimeKind.Tauri) + { + errors.Add("Native tool bindings are only available to controlled Tauri plugins."); + } + if (bindings.Count > 0 && + (!declaredPermissions.Contains(PluginPermission.ExternalTool) || + !requiredPermissions.Contains(PluginPermission.ExternalTool))) + { + errors.Add("Plugins with native tool bindings must declare ExternalTool as a required permission."); + } + + if (manifest.Runtime == PluginRuntimeKind.Tauri && manifest.Tauri is { } tauri) + { + if (!string.IsNullOrWhiteSpace(tauri.Executable)) + { + errors.Add("Tauri plugins use the bundled YMhut host and cannot declare a private host executable."); + } + if (strict && string.IsNullOrWhiteSpace(tauri.HostApiVersion)) + { + errors.Add("Tauri hostApiVersion is required."); + } + if (!IsSafeRelativePath(root, tauri.DistDirectory)) + { + errors.Add("Tauri distDirectory must exist inside the plugin directory."); + } + } + + var bindingIds = new HashSet(StringComparer.OrdinalIgnoreCase); + var declaredNativeFiles = new HashSet(StringComparer.OrdinalIgnoreCase); + foreach (var binding in bindings) + { + if (!PluginIds.IsSafeId(binding.Id) || !bindingIds.Add(binding.Id)) + { + errors.Add($"Native tool binding id is invalid or duplicated: {binding.Id}"); + } + if (string.IsNullOrWhiteSpace(binding.Name)) + { + errors.Add($"Native tool binding name is required: {binding.Id}"); + } + if (!IsSafeRelativeFile(root, binding.Executable) || + !string.Equals(Path.GetExtension(binding.Executable), ".exe", StringComparison.OrdinalIgnoreCase)) + { + errors.Add($"Native tool executable must be a declared EXE inside the plugin directory: {binding.Id}"); + } + else + { + var executable = Path.GetFullPath(Path.Combine(root, binding.Executable)); + if (IsBlockedNativeToolName(executable)) + { + errors.Add($"Installers, updaters, services, drivers, and uninstallers cannot be bound as plugin tools: {binding.Id}"); + } + if (HasElevatedExecutionManifest(executable)) + { + errors.Add($"Native plugin tools cannot request elevation: {binding.Id}"); + } + } + if (!IsSafeRelativePath(root, binding.WorkingDirectory)) + { + errors.Add($"Native tool working directory escapes the plugin directory: {binding.Id}"); + } + if (binding.Architecture.Trim().ToLowerInvariant() is not ("x64" or "x64compatible")) + { + errors.Add($"Native tool architecture is not supported: {binding.Id}"); + } + if (binding.TimeoutMs < 0 || binding.TimeoutMs > 86_400_000) + { + errors.Add($"Native tool timeout is outside the supported range: {binding.Id}"); + } + + var parameterNames = new HashSet(StringComparer.OrdinalIgnoreCase); + foreach (var parameter in binding.Parameters ?? []) + { + if (!PluginIds.IsSafeId(parameter.Name) || !parameterNames.Add(parameter.Name) || + parameter.MaxLength is < 1 or > 32_768) + { + errors.Add($"Native tool parameter is invalid: {binding.Id}/{parameter.Name}"); + } + if (parameter.Kind == PluginToolArgumentKind.Choice && (parameter.Choices?.Count ?? 0) == 0) + { + errors.Add($"Native tool choice parameter has no allowed values: {binding.Id}/{parameter.Name}"); + } + } + foreach (var template in binding.Arguments ?? []) + { + if (template.Length > 4096 || template.Contains('\0') || template.Contains('\r') || template.Contains('\n')) + { + errors.Add($"Native tool argument template is invalid: {binding.Id}"); + continue; + } + foreach (Match match in Regex.Matches(template, "\\{(?[A-Za-z0-9_.-]+)\\}", RegexOptions.CultureInvariant)) + { + if (!parameterNames.Contains(match.Groups["name"].Value)) + { + errors.Add($"Native tool argument references an undeclared parameter: {binding.Id}/{match.Groups["name"].Value}"); + } + } + } + + var bindingFiles = new HashSet(StringComparer.OrdinalIgnoreCase); + foreach (var file in binding.Files ?? []) + { + var extension = Path.GetExtension(file.Path); + var allowedNativeExtension = extension.Equals(".exe", StringComparison.OrdinalIgnoreCase) || + extension.Equals(".dll", StringComparison.OrdinalIgnoreCase); + if (!bindingFiles.Add(file.Path) || !IsSafeRelativeFile(root, file.Path) || + !allowedNativeExtension) + { + errors.Add($"Native tool file is invalid or duplicated: {binding.Id}/{file.Path}"); + continue; + } + if (!IsSha256(file.Sha256) || !FileHashMatches(root, file)) + { + errors.Add($"Native tool file hash does not match: {binding.Id}/{file.Path}"); + continue; + } + declaredNativeFiles.Add(Path.GetFullPath(Path.Combine(root, file.Path))); + } + var executablePath = Path.GetFullPath(Path.Combine(root, binding.Executable)); + if (!declaredNativeFiles.Contains(executablePath)) + { + errors.Add($"Native tool executable is missing from the hashed file inventory: {binding.Id}"); + } + } + + foreach (var file in Directory.EnumerateFiles(root, "*", SearchOption.AllDirectories)) + { + var extension = Path.GetExtension(file); + if (extension.Equals(".com", StringComparison.OrdinalIgnoreCase) || + extension.Equals(".scr", StringComparison.OrdinalIgnoreCase) || + extension.Equals(".sys", StringComparison.OrdinalIgnoreCase) || + extension.Equals(".msi", StringComparison.OrdinalIgnoreCase) || + extension.Equals(".msix", StringComparison.OrdinalIgnoreCase) || + extension.Equals(".msixbundle", StringComparison.OrdinalIgnoreCase) || + extension.Equals(".appx", StringComparison.OrdinalIgnoreCase) || + extension.Equals(".appxbundle", StringComparison.OrdinalIgnoreCase)) + { + errors.Add($"Blocked native package file: {Path.GetRelativePath(root, file)}"); + } + else if ((extension.Equals(".exe", StringComparison.OrdinalIgnoreCase) || extension.Equals(".dll", StringComparison.OrdinalIgnoreCase)) && + !declaredNativeFiles.Contains(Path.GetFullPath(file))) + { + errors.Add($"Undeclared native package file: {Path.GetRelativePath(root, file)}"); + } + } + } + + private static bool IsSha256(string value) => + value.Length == 64 && value.All(Uri.IsHexDigit); + + private static bool IsBlockedNativeToolName(string path) + { + var name = Path.GetFileNameWithoutExtension(path); + return new[] { "setup", "installer", "install", "uninstall", "updater", "update", "service", "driver" } + .Any(token => name.Contains(token, StringComparison.OrdinalIgnoreCase)); + } + + private static bool HasElevatedExecutionManifest(string path) + { + try + { + var patterns = new[] + { + Encoding.UTF8.GetBytes("requireAdministrator"), + Encoding.UTF8.GetBytes("highestAvailable"), + Encoding.Unicode.GetBytes("requireAdministrator"), + Encoding.Unicode.GetBytes("highestAvailable") + }; + var overlap = patterns.Max(pattern => pattern.Length) - 1; + var buffer = new byte[64 * 1024 + overlap]; + var carried = 0; + using var stream = File.OpenRead(path); + while (true) + { + var read = stream.Read(buffer, carried, buffer.Length - carried); + if (read == 0) + { + return patterns.Any(pattern => buffer.AsSpan(0, carried).IndexOf(pattern) >= 0); + } + var length = carried + read; + if (patterns.Any(pattern => buffer.AsSpan(0, length).IndexOf(pattern) >= 0)) + { + return true; + } + carried = Math.Min(overlap, length); + buffer.AsSpan(length - carried, carried).CopyTo(buffer); + } + } + catch + { + return true; + } + } + + private static bool FileHashMatches(string root, PluginToolFileSpec file) + { + try + { + using var stream = File.OpenRead(Path.GetFullPath(Path.Combine(root, file.Path))); + return string.Equals(Convert.ToHexString(SHA256.HashData(stream)), file.Sha256, StringComparison.OrdinalIgnoreCase); + } + catch + { + return false; + } } public static bool IsSafeRelativeFile(string root, string relativePath) diff --git a/src/YMhut.Box.Core/Plugins/Runtime/PluginRuntimeDependencyModels.cs b/src/YMhut.Box.Core/Plugins/Runtime/PluginRuntimeDependencyModels.cs new file mode 100644 index 0000000..adbae43 --- /dev/null +++ b/src/YMhut.Box.Core/Plugins/Runtime/PluginRuntimeDependencyModels.cs @@ -0,0 +1,15 @@ +namespace YMhut.Box.Core.Plugins.Runtime; + +public sealed record PluginRuntimeDependencyInfo( + bool IsReady, + string HostExecutable, + string RuntimeManifest, + string TemplatePackage, + string HostApiVersion, + string TemplateVersion, + string? Diagnostic = null); + +public interface IPluginRuntimeDependencyService +{ + Task GetAsync(CancellationToken cancellationToken = default); +} diff --git a/src/YMhut.Box.Core/Settings/AgreementDocument.cs b/src/YMhut.Box.Core/Settings/AgreementDocument.cs index 84cb43b..64b0bac 100644 --- a/src/YMhut.Box.Core/Settings/AgreementDocument.cs +++ b/src/YMhut.Box.Core/Settings/AgreementDocument.cs @@ -13,7 +13,13 @@ public static class AgreementDocument public const string MusicProviderDisclaimerVersion = "2.1"; public const int MusicProviderDisclaimerRevision = 3; - public const string CurrentVersion = "2.0.6.2"; + + public const string PearApiNoticeVersion = "1.0"; + + public const string PluginNoticeVersion = "1.0"; + // Keep the agreement version aligned with the shipped release so users who + // accepted an older document are asked to review the expanded terms again. + public const string CurrentVersion = "2.0.7.14"; public const int CurrentRevision = 1; diff --git a/src/YMhut.Box.Core/Settings/AppSettings.cs b/src/YMhut.Box.Core/Settings/AppSettings.cs index 90537fe..c409871 100644 --- a/src/YMhut.Box.Core/Settings/AppSettings.cs +++ b/src/YMhut.Box.Core/Settings/AppSettings.cs @@ -47,6 +47,10 @@ public sealed class AppSettings public string UserAgreementVersion { get; set; } = string.Empty; + public string PearApiNoticeVersion { get; set; } = string.Empty; + + public string PluginNoticeVersion { get; set; } = string.Empty; + public DateTimeOffset? UserAgreementAcceptedAt { get; set; } public bool SidebarCollapsed { get; set; } diff --git a/src/YMhut.Box.Core/Tools/ToolCatalog.cs b/src/YMhut.Box.Core/Tools/ToolCatalog.cs index 57269a1..e599d6d 100644 --- a/src/YMhut.Box.Core/Tools/ToolCatalog.cs +++ b/src/YMhut.Box.Core/Tools/ToolCatalog.cs @@ -1,3 +1,5 @@ +using YMhut.Box.Core.Api; + namespace YMhut.Box.Core.Tools; public sealed class ToolCatalog @@ -6,7 +8,8 @@ public sealed class ToolCatalog { "hardware", "optimization", - "music" + "music", + "online_tools" }; private readonly List _modules; @@ -46,10 +49,14 @@ public sealed class ToolCatalog public static IEnumerable DefaultModules() { - return SortForDisplay(RawToolData + var builtIn = RawToolData .Split('\n', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) .Select(ParseModule) - .Concat([DevEnvironmentConfigModule()])); + .Concat([DevEnvironmentConfigModule()]) + .ToList(); + var ids = builtIn.Select(module => module.Id).ToHashSet(StringComparer.OrdinalIgnoreCase); + builtIn.AddRange(PearApiCatalog.CreateToolModules(ids)); + return SortForDisplay(builtIn); } public static IOrderedEnumerable SortForDisplay( @@ -93,6 +100,25 @@ public sealed class ToolCatalog ? parsedAddedOrder : 0; + if (PearApiCatalog.TryGet(id, out var pearDefinition)) + { + return new ToolModule(new ToolMetadata( + id, + name, + description, + category, + keywords, + offline, + IconForCategory(category), + addedOrder, + PearApiCatalog.ProviderName, + new ToolOnlineCapabilityInfo( + PearApiCatalog.ProviderName, + pearDefinition.PrivacyClass.ToString(), + pearDefinition.PrivacyClass != PearApiPrivacyClass.Public, + pearDefinition.IsAvailableWithoutKey))); + } + return new ToolModule(new ToolMetadata(id, name, description, category, keywords, offline, IconForCategory(category), addedOrder)); } @@ -157,6 +183,7 @@ public sealed class ToolCatalog hardware 硬件与系统状态 实时传感器、静态硬件清单、提供方状态与报告导出。 system true 硬件;系统;状态;传感器;CPU;GPU 300 optimization 优化中心 预览系统变更、按需提权、执行日志和可用回滚。 system true 优化;系统;回滚;清理;网络 290 music 网络音乐播放器 搜索、歌单、播放队列、歌词与系统媒体控制。 network false 音乐;播放器;歌单;歌词;媒体 280 +online_tools 联网工具 安全访问 PearAPI 的免费免 Key 接口,并按用途分类浏览。 network false 联网;PearAPI;在线;API;数据 275 html_js_playground HTML/JS 渲染器 运行 HTML、CSS、JS、引用脚本并查看输出日志 dev false html;js;webview;plugin;playground json_formatter JSON 格式化 美化、压缩并校验 JSON 内容 dev true json;format;pretty;minify base64_codec Base64 编解码 在 Base64 与 UTF-8 文本之间转换 dev true base64;encode;decode diff --git a/src/YMhut.Box.Core/Tools/ToolMetadata.cs b/src/YMhut.Box.Core/Tools/ToolMetadata.cs index 4fc59f0..88a6c33 100644 --- a/src/YMhut.Box.Core/Tools/ToolMetadata.cs +++ b/src/YMhut.Box.Core/Tools/ToolMetadata.cs @@ -1,5 +1,11 @@ namespace YMhut.Box.Core.Tools; +public sealed record ToolOnlineCapabilityInfo( + string Provider, + string PrivacyClass, + bool SendsUserInput, + bool AvailableWithoutAuthentication); + public sealed record ToolMetadata( string Id, string Name, @@ -8,4 +14,6 @@ public sealed record ToolMetadata( IReadOnlyList Keywords, bool OfflineCapable, string IconGlyph, - int AddedOrder = 0); + int AddedOrder = 0, + string? Provider = null, + ToolOnlineCapabilityInfo? OnlineCapability = null); diff --git a/src/YMhut.Box.DownloadHost/YMhut.Box.DownloadHost.csproj b/src/YMhut.Box.DownloadHost/YMhut.Box.DownloadHost.csproj index 1b26d00..704301a 100644 --- a/src/YMhut.Box.DownloadHost/YMhut.Box.DownloadHost.csproj +++ b/src/YMhut.Box.DownloadHost/YMhut.Box.DownloadHost.csproj @@ -6,6 +6,7 @@ enable YMhut.Box.DownloadHost YMhut.Box.DownloadHost + ..\box-winUI\Assets\app_icon.ico none diff --git a/src/YMhut.Box.HardwareMonitor/YMhut.Box.HardwareMonitor.csproj b/src/YMhut.Box.HardwareMonitor/YMhut.Box.HardwareMonitor.csproj index 3b7292f..9d6ce45 100644 --- a/src/YMhut.Box.HardwareMonitor/YMhut.Box.HardwareMonitor.csproj +++ b/src/YMhut.Box.HardwareMonitor/YMhut.Box.HardwareMonitor.csproj @@ -8,6 +8,7 @@ enable YMhut.Box.HardwareMonitor YMhut.Box.HardwareMonitor + ..\box-winUI\Assets\app_icon.ico none diff --git a/src/YMhut.Box.InstallerBootstrap/InstallerApp.cs b/src/YMhut.Box.InstallerBootstrap/InstallerApp.cs index 44ae7b8..92a7aa2 100644 --- a/src/YMhut.Box.InstallerBootstrap/InstallerApp.cs +++ b/src/YMhut.Box.InstallerBootstrap/InstallerApp.cs @@ -20,6 +20,13 @@ public sealed partial class InstallerApp : Application protected override void OnLaunched(LaunchActivatedEventArgs args) { + var mode = InstallerInvocation.Resolve(_arguments); + if (mode == InstallerInvocationMode.Uninstall) + { + _window = new UninstallerWindow(UninstallOptions.Parse(_arguments)); + _window.Activate(); + return; + } _window = new InstallerWindow(InstallerOptions.Parse(_arguments)); _window.Activate(); if (_arguments.Any(argument => argument.Equals("/WINDOWSELFTEST", StringComparison.OrdinalIgnoreCase))) diff --git a/src/YMhut.Box.InstallerBootstrap/Program.cs b/src/YMhut.Box.InstallerBootstrap/Program.cs index ebd77ab..8451c70 100644 --- a/src/YMhut.Box.InstallerBootstrap/Program.cs +++ b/src/YMhut.Box.InstallerBootstrap/Program.cs @@ -22,14 +22,19 @@ public static class Program eventArgs.SetObserved(); }; Environment.SetEnvironmentVariable("MICROSOFT_WINDOWSAPPRUNTIME_BASE_DIRECTORY", AppContext.BaseDirectory); + var invocationMode = InstallerInvocation.Resolve(args); if (args.Any(argument => argument.Equals("/SELFTEST", StringComparison.OrdinalIgnoreCase))) { - Environment.Exit(InstallerEngine.SelfTest() ? 0 : 3); + Environment.Exit(invocationMode == InstallerInvocationMode.Uninstall + ? UninstallEngine.SelfTest(UninstallOptions.Parse(args)) ? 0 : 3 + : InstallerEngine.SelfTest() ? 0 : 3); return; } if (InstallerOptions.IsAutomation(args)) { - Environment.Exit(InstallerEngine.RunForwardedAsync(args).GetAwaiter().GetResult()); + Environment.Exit(invocationMode == InstallerInvocationMode.Uninstall + ? UninstallEngine.RunAsync(UninstallOptions.Parse(args)).GetAwaiter().GetResult().ExitCode + : InstallerEngine.RunForwardedAsync(args).GetAwaiter().GetResult()); return; } RunApp(args); diff --git a/src/YMhut.Box.InstallerBootstrap/UninstallEngine.cs b/src/YMhut.Box.InstallerBootstrap/UninstallEngine.cs new file mode 100644 index 0000000..fc582f3 --- /dev/null +++ b/src/YMhut.Box.InstallerBootstrap/UninstallEngine.cs @@ -0,0 +1,214 @@ +using System.Diagnostics; +using System.Text.Json; + +namespace YMhut.Box.InstallerBootstrap; + +public static class UninstallEngine +{ + public static bool SelfTest(UninstallOptions options) => ResolveEngine(options.InstallDirectory) is not null; + + public static async Task RunAsync( + UninstallOptions options, + IProgress? progress = null, + CancellationToken cancellationToken = default) + { + var engine = ResolveEngine(options.InstallDirectory); + if (engine is null) + { + return new(false, 3, "未找到内部卸载引擎,请重新安装当前版本后再卸载。"); + } + var logRoot = Path.Combine(Path.GetTempPath(), "YMhutBoxSetup"); + Directory.CreateDirectory(logRoot); + var logPath = Path.Combine(logRoot, $"uninstall-{DateTime.Now:yyyyMMdd-HHmmss}.log"); + var arguments = new List + { + "/VERYSILENT", + "/SUPPRESSMSGBOXES", + "/NORESTART", + $"/LOG={logPath}" + }; + progress?.Report("正在关闭组件并清理程序文件…"); + try + { + var startInfo = new ProcessStartInfo + { + FileName = engine, + WorkingDirectory = Path.GetDirectoryName(engine)!, + UseShellExecute = false, + CreateNoWindow = true + }; + foreach (var argument in arguments) startInfo.ArgumentList.Add(argument); + using var process = Process.Start(startInfo); + if (process is null) return new(false, 4, "无法启动内部卸载引擎。", logPath); + await process.WaitForExitAsync(cancellationToken).ConfigureAwait(false); + if (process.ExitCode != 0) + { + return new(false, process.ExitCode, $"卸载引擎退出代码 {process.ExitCode}。", logPath); + } + if (options.RemoveUserData) + { + progress?.Report("正在删除用户明确选择清理的数据…"); + DeleteUserData(options.InstallDirectory); + } + ScheduleBootstrapCleanup(options.InstallDirectory); + return new(true, 0, options.RemoveUserData + ? "程序文件和本地用户数据已完成清理。" + : "程序文件已完成清理,设置、登录态、插件数据和日志已保留。", logPath); + } + catch (OperationCanceledException) + { + return new(false, 1223, "卸载已取消。", logPath); + } + catch (Exception exception) + { + return new(false, 5, $"卸载未完成:{exception.Message}", logPath); + } + } + + private static string? ResolveEngine(string installDirectory) + { + var candidate = Path.GetFullPath(Path.Combine(installDirectory, "Runtime", "uninstall-engine", "unins000.exe")); + var data = Path.ChangeExtension(candidate, ".dat"); + return File.Exists(candidate) && File.Exists(data) && + !string.Equals(candidate, Environment.ProcessPath, StringComparison.OrdinalIgnoreCase) + ? candidate + : null; + } + + private static void DeleteUserData(string installDirectory) + { + var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); + var appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); + var defaultRoot = Path.Combine(localAppData, "YMhut Box", "WinUI"); + var roots = new HashSet(StringComparer.OrdinalIgnoreCase) + { + defaultRoot, + Path.Combine(appData, "YMhut Box"), + Path.Combine(localAppData, "ymhut_box"), + Path.Combine(appData, "ymhut_box") + }; + + // A custom plugin root is user data only when it stays inside an app-owned + // data directory. Never allow a tampered settings file to turn uninstall + // into deletion of an arbitrary user or system directory. + var customPluginRoot = ReadConfiguredPluginRoot(Path.Combine(defaultRoot, "settings.json")); + if (customPluginRoot is not null && IsSafeCustomPluginRoot(customPluginRoot, localAppData, appData)) + { + roots.Add(customPluginRoot); + } + + foreach (var root in roots.OrderByDescending(value => value.Length)) + { + if (!IsSafeUserDataRoot(root, installDirectory) && + !IsSafeCustomPluginRoot(root, localAppData, appData)) + { + continue; + } + + DeleteDirectory(root); + } + } + + private static string? ReadConfiguredPluginRoot(string settingsPath) + { + try + { + if (!File.Exists(settingsPath)) return null; + using var document = JsonDocument.Parse(File.ReadAllText(settingsPath)); + if (!document.RootElement.TryGetProperty("pluginRootPath", out var value) && + !document.RootElement.TryGetProperty("PluginRootPath", out value)) + { + return null; + } + + var configured = value.GetString(); + return string.IsNullOrWhiteSpace(configured) + ? null + : Path.GetFullPath(Environment.ExpandEnvironmentVariables(configured.Trim())); + } + catch + { + return null; + } + } + + private static bool IsSafeCustomPluginRoot(string path, string localAppData, string appData) + { + var fullPath = Path.GetFullPath(path).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); + var allowedParents = new[] + { + Path.Combine(localAppData, "YMhut Box"), + Path.Combine(appData, "YMhut Box"), + Path.Combine(localAppData, "ymhut_box"), + Path.Combine(appData, "ymhut_box") + }; + + return allowedParents.Any(parent => IsChildPath(parent, fullPath)); + } + + private static bool IsSafeUserDataRoot(string path, string installDirectory) + { + try + { + var fullPath = Path.GetFullPath(path).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); + var installRoot = Path.GetFullPath(installDirectory).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); + return !string.Equals(fullPath, installRoot, StringComparison.OrdinalIgnoreCase) && + !string.Equals(fullPath, Path.GetPathRoot(fullPath)?.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar), StringComparison.OrdinalIgnoreCase) && + (fullPath.EndsWith("YMhut Box\\WinUI", StringComparison.OrdinalIgnoreCase) || + fullPath.EndsWith("YMhut Box", StringComparison.OrdinalIgnoreCase) || + fullPath.EndsWith("ymhut_box", StringComparison.OrdinalIgnoreCase)); + } + catch + { + return false; + } + } + + private static bool IsChildPath(string parent, string child) + { + var parentFull = Path.GetFullPath(parent).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); + var childFull = Path.GetFullPath(child).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); + return childFull.StartsWith(parentFull + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase) || + childFull.StartsWith(parentFull + Path.AltDirectorySeparatorChar, StringComparison.OrdinalIgnoreCase); + } + + private static void DeleteDirectory(string root) + { + if (!Directory.Exists(root)) return; + foreach (var path in Directory.EnumerateFileSystemEntries(root, "*", SearchOption.AllDirectories).OrderByDescending(value => value.Length)) + { + try { File.SetAttributes(path, FileAttributes.Normal); } catch { } + } + + try { File.SetAttributes(root, FileAttributes.Normal); } catch { } + try { Directory.Delete(root, recursive: true); } catch { } + + var parent = Path.GetDirectoryName(root); + if (parent is not null && Directory.Exists(parent) && !Directory.EnumerateFileSystemEntries(parent).Any()) + { + try { Directory.Delete(parent); } catch { } + } + } + + private static void ScheduleBootstrapCleanup(string installDirectory) + { + var bootstrap = Path.Combine(installDirectory, "unins000.exe"); + var command = $"ping 127.0.0.1 -n 2 >nul & del /f /q \"{bootstrap}\""; + try + { + _ = Process.Start(new ProcessStartInfo + { + FileName = Environment.GetEnvironmentVariable("ComSpec") ?? "cmd.exe", + Arguments = "/d /c " + command, + WorkingDirectory = installDirectory, + UseShellExecute = false, + CreateNoWindow = true, + WindowStyle = ProcessWindowStyle.Hidden + }); + } + catch + { + // The engine has already completed. Leaving the entry in place is preferable to failing the uninstall. + } + } +} diff --git a/src/YMhut.Box.InstallerBootstrap/UninstallModels.cs b/src/YMhut.Box.InstallerBootstrap/UninstallModels.cs new file mode 100644 index 0000000..0ca8fb2 --- /dev/null +++ b/src/YMhut.Box.InstallerBootstrap/UninstallModels.cs @@ -0,0 +1,53 @@ +namespace YMhut.Box.InstallerBootstrap; + +public enum InstallerInvocationMode +{ + Install, + Uninstall +} + +public sealed record UninstallOptions( + string InstallDirectory, + bool RemoveUserData, + bool Silent, + IReadOnlyList OriginalArguments) +{ + public static UninstallOptions Parse(IReadOnlyList arguments) + { + var directoryArgument = arguments.FirstOrDefault(argument => argument.StartsWith("/INSTALLDIR=", StringComparison.OrdinalIgnoreCase)); + var directory = directoryArgument is null + ? InstallerEngine.DetectExistingInstall() ?? AppContext.BaseDirectory + : directoryArgument[12..].Trim('"'); + return new UninstallOptions( + Path.GetFullPath(directory), + arguments.Any(argument => argument.Equals("/REMOVEUSERDATA", StringComparison.OrdinalIgnoreCase)), + InstallerOptions.IsAutomation(arguments), + arguments); + } +} + +public sealed record UninstallResult( + bool Success, + int ExitCode, + string Message, + string? LogPath = null); + +public static class InstallerInvocation +{ + public static InstallerInvocationMode Resolve(IReadOnlyList arguments) + { +#if UNINSTALL_BOOTSTRAP + return InstallerInvocationMode.Uninstall; +#else + if (arguments.Any(argument => argument.Equals("/UNINSTALL", StringComparison.OrdinalIgnoreCase))) + { + return InstallerInvocationMode.Uninstall; + } + var processName = Path.GetFileNameWithoutExtension(Environment.ProcessPath); + return string.Equals(processName, "unins000", StringComparison.OrdinalIgnoreCase) && + Directory.Exists(Path.Combine(AppContext.BaseDirectory, "Runtime", "uninstall-engine")) + ? InstallerInvocationMode.Uninstall + : InstallerInvocationMode.Install; +#endif + } +} diff --git a/src/YMhut.Box.InstallerBootstrap/UninstallerWindow.cs b/src/YMhut.Box.InstallerBootstrap/UninstallerWindow.cs new file mode 100644 index 0000000..c0932e5 --- /dev/null +++ b/src/YMhut.Box.InstallerBootstrap/UninstallerWindow.cs @@ -0,0 +1,233 @@ +using Microsoft.UI; +using Microsoft.UI.Text; +using Microsoft.UI.Windowing; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Automation; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Media; +using Windows.Graphics; +using WinRT.Interop; + +namespace YMhut.Box.InstallerBootstrap; + +public sealed class UninstallerWindow : Window +{ + private static readonly SolidColorBrush Background = Brush("#FFF3F1EC"); + private static readonly SolidColorBrush Surface = Brush("#FFFCFBF8"); + private static readonly SolidColorBrush Stroke = Brush("#FFD6D2CB"); + private static readonly SolidColorBrush Primary = Brush("#FF343330"); + private static readonly SolidColorBrush Secondary = Brush("#FF716E68"); + private static readonly SolidColorBrush Accent = Brush("#FF55514C"); + private static readonly SolidColorBrush Danger = Brush("#FFB42318"); + private readonly Border _dragArea = new(); + private readonly CheckBox _removeData = new() + { + Content = "同时删除设置、登录态、插件数据、缓存和日志", + IsChecked = false + }; + private readonly TextBlock _status = Text("默认保留全部用户数据。", 13, Secondary, 5); + private readonly ProgressRing _progress = new() { Width = 22, Height = 22, Visibility = Visibility.Collapsed }; + private readonly Button _uninstallButton; + private readonly Button _cancelButton; + private readonly UninstallOptions _options; + private bool _running; + private AppWindow? _appWindow; + + public UninstallerWindow(UninstallOptions options) + { + _options = options; + Title = "YMhut Box 卸载程序"; + _uninstallButton = CommandButton("卸载", "\uE74D", BeginUninstallAsync, true); + _cancelButton = CommandButton("取消", "\uE711", Close); + Content = BuildContent(); + ExtendsContentIntoTitleBar = true; + SetTitleBar(_dragArea); + Activated += (_, _) => ConfigureWindow(); + } + + private UIElement BuildContent() + { + var root = new Grid { Background = Background, RequestedTheme = ElementTheme.Light }; + root.RowDefinitions.Add(new RowDefinition { Height = new GridLength(48) }); + root.RowDefinitions.Add(new RowDefinition()); + _dragArea.Background = Surface; + _dragArea.BorderBrush = Stroke; + _dragArea.BorderThickness = new Thickness(0, 0, 0, 1); + _dragArea.Padding = new Thickness(18, 0, 148, 0); + _dragArea.Child = new StackPanel + { + Orientation = Orientation.Horizontal, + Spacing = 9, + VerticalAlignment = VerticalAlignment.Center, + Children = + { + new FontIcon { Glyph = "\uE74D", FontSize = 16, Foreground = Accent }, + Text("YMhut Box 卸载程序", 13, Primary, 1, FontWeights.SemiBold) + } + }; + root.Children.Add(_dragArea); + + var content = new StackPanel + { + Spacing = 18, + MaxWidth = 680, + HorizontalAlignment = HorizontalAlignment.Stretch, + Children = + { + Text("卸载 YMhut Box", 28, Primary, 2, FontWeights.SemiBold), + Text($"将从以下位置移除程序文件:\n{_options.InstallDirectory}", 13, Secondary, 4), + new InfoBar + { + IsOpen = true, + IsClosable = false, + Severity = InfoBarSeverity.Informational, + Title = "用户数据默认保留", + Message = "设置、登录态、插件数据、日志和下载记录不会随程序文件一起删除,重新安装后仍可继续使用。" + }, + new Border + { + Padding = new Thickness(16), + Background = Surface, + BorderBrush = Stroke, + BorderThickness = new Thickness(1), + CornerRadius = new CornerRadius(7), + Child = new StackPanel + { + Spacing = 8, + Children = + { + Text("数据清理", 16, Primary, 1, FontWeights.SemiBold), + _removeData, + Text("勾选后不可恢复。仅在确认不再需要本机配置和插件内容时使用。", 12, Danger, 3) + } + } + }, + new StackPanel + { + Orientation = Orientation.Horizontal, + Spacing = 10, + Children = { _progress, _status } + } + } + }; + var actions = new StackPanel + { + Orientation = Orientation.Horizontal, + Spacing = 8, + HorizontalAlignment = HorizontalAlignment.Right, + Children = { _cancelButton, _uninstallButton } + }; + var layout = new Grid { Padding = new Thickness(36, 32, 36, 24) }; + layout.RowDefinitions.Add(new RowDefinition()); + layout.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); + layout.Children.Add(new ScrollViewer + { + Content = content, + VerticalScrollMode = ScrollMode.Enabled, + VerticalScrollBarVisibility = ScrollBarVisibility.Auto, + HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled + }); + Grid.SetRow(actions, 1); + layout.Children.Add(actions); + Grid.SetRow(layout, 1); + root.Children.Add(layout); + return root; + } + + private async void BeginUninstallAsync() + { + if (_running) return; + _running = true; + _uninstallButton.IsEnabled = false; + _cancelButton.IsEnabled = false; + _removeData.IsEnabled = false; + _progress.Visibility = Visibility.Visible; + _progress.IsActive = true; + var options = _options with { RemoveUserData = _removeData.IsChecked == true }; + var progress = new Progress(value => _status.Text = value); + var result = await UninstallEngine.RunAsync(options, progress); + _progress.IsActive = false; + _progress.Visibility = Visibility.Collapsed; + _status.Text = result.Message; + _status.Foreground = result.Success ? Accent : Danger; + _cancelButton.Content = result.Success ? "关闭" : "返回"; + _cancelButton.IsEnabled = true; + if (result.Success) + { + _running = false; + } + if (!result.Success) + { + _uninstallButton.IsEnabled = true; + _removeData.IsEnabled = true; + _running = false; + } + } + + private void ConfigureWindow() + { + if (_appWindow is not null) return; + SystemBackdrop = null; + var hwnd = WindowNative.GetWindowHandle(this); + _appWindow = AppWindow.GetFromWindowId(Win32Interop.GetWindowIdFromWindow(hwnd)); + _appWindow.Resize(new SizeInt32(780, 570)); + if (AppWindowTitleBar.IsCustomizationSupported()) + { + _appWindow.TitleBar.ExtendsContentIntoTitleBar = true; + _appWindow.TitleBar.BackgroundColor = ColorHelper.FromArgb(255, 252, 251, 248); + _appWindow.TitleBar.ButtonBackgroundColor = ColorHelper.FromArgb(255, 252, 251, 248); + _appWindow.TitleBar.ButtonForegroundColor = ColorHelper.FromArgb(255, 52, 51, 48); + } + if (_appWindow.Presenter is OverlappedPresenter presenter) + { + presenter.IsResizable = true; + presenter.IsMaximizable = false; + presenter.IsMinimizable = true; + } + _appWindow.Closing += (_, args) => args.Cancel = _running; + } + + private static Button CommandButton(string label, string glyph, Action action, bool primary = false) + { + var button = new Button + { + MinWidth = 112, + Height = 38, + Padding = new Thickness(14, 0, 14, 0), + CornerRadius = new CornerRadius(6), + Background = primary ? Accent : Surface, + Foreground = primary ? new SolidColorBrush(Microsoft.UI.Colors.White) : Primary, + BorderBrush = primary ? Accent : Stroke, + BorderThickness = new Thickness(1), + Content = new StackPanel + { + Orientation = Orientation.Horizontal, + Spacing = 7, + Children = + { + new FontIcon { Glyph = glyph, FontSize = 14 }, + Text(label, 13, primary ? new SolidColorBrush(Microsoft.UI.Colors.White) : Primary, 1, FontWeights.SemiBold) + } + } + }; + AutomationProperties.SetName(button, label); + button.Click += (_, _) => action(); + return button; + } + + private static TextBlock Text(string value, double size, Brush foreground, int maxLines, Windows.UI.Text.FontWeight? weight = null) => new() + { + Text = value, + FontSize = size, + FontWeight = weight ?? FontWeights.Normal, + Foreground = foreground, + TextWrapping = TextWrapping.Wrap, + MaxLines = maxLines + }; + + private static SolidColorBrush Brush(string color) => new(Windows.UI.Color.FromArgb( + Convert.ToByte(color[1..3], 16), + Convert.ToByte(color[3..5], 16), + Convert.ToByte(color[5..7], 16), + Convert.ToByte(color[7..9], 16))); +} diff --git a/src/YMhut.Box.InstallerBootstrap/YMhut.Box.InstallerBootstrap.csproj b/src/YMhut.Box.InstallerBootstrap/YMhut.Box.InstallerBootstrap.csproj index f6d8818..0528259 100644 --- a/src/YMhut.Box.InstallerBootstrap/YMhut.Box.InstallerBootstrap.csproj +++ b/src/YMhut.Box.InstallerBootstrap/YMhut.Box.InstallerBootstrap.csproj @@ -23,6 +23,10 @@ ..\box-winUI\Assets\app_icon.ico app.manifest + + $(DefineConstants);UNINSTALL_BOOTSTRAP + unins000 + diff --git a/src/YMhut.Box.PluginHost/Program.cs b/src/YMhut.Box.PluginHost/Program.cs index 75eed6b..be9ba20 100644 --- a/src/YMhut.Box.PluginHost/Program.cs +++ b/src/YMhut.Box.PluginHost/Program.cs @@ -436,6 +436,7 @@ async Task DispatchBridgeAsync(LoadedPlugin plugin, string "clipboard.writeText" => AuthorizeUi(plugin, PluginPermission.Clipboard, "clipboard.writeText"), "file.openPicker" => AuthorizeUi(plugin, PluginPermission.FilePicker, "file.openPicker"), "file.savePicker" => AuthorizeUi(plugin, PluginPermission.FilePicker, "file.savePicker"), + "externalTool.launch" => AuthorizeUi(plugin, PluginPermission.ExternalTool, "externalTool.launch"), "openExternal" => ValidateExternal(plugin, payload), _ => Fail($"Unknown plugin bridge method: {method}") }; diff --git a/src/YMhut.Box.PluginHost/YMhut.Box.PluginHost.csproj b/src/YMhut.Box.PluginHost/YMhut.Box.PluginHost.csproj index f8ea68a..ad114bd 100644 --- a/src/YMhut.Box.PluginHost/YMhut.Box.PluginHost.csproj +++ b/src/YMhut.Box.PluginHost/YMhut.Box.PluginHost.csproj @@ -4,6 +4,7 @@ net10.0 enable enable + ..\box-winUI\Assets\app_icon.ico none diff --git a/src/YMhut.Box.PluginTauriHost/LICENSES.txt b/src/YMhut.Box.PluginTauriHost/LICENSES.txt new file mode 100644 index 0000000..b19ff15 --- /dev/null +++ b/src/YMhut.Box.PluginTauriHost/LICENSES.txt @@ -0,0 +1,10 @@ +YMhut Box controlled Tauri plugin host + +The host uses Tauri 2 and its transitive Rust dependencies. Tauri is available +under the Apache License 2.0 or MIT License. Complete dependency versions are +locked by src-tauri/Cargo.lock and the corresponding source remains in this +repository. See THIRD_PARTY_NOTICES.md in the application directory for the +project-wide notices and license links. + +Tauri: https://github.com/tauri-apps/tauri +License: Apache-2.0 OR MIT diff --git a/src/YMhut.Box.PluginTauriHost/runtime.json b/src/YMhut.Box.PluginTauriHost/runtime.json new file mode 100644 index 0000000..a0166eb --- /dev/null +++ b/src/YMhut.Box.PluginTauriHost/runtime.json @@ -0,0 +1,9 @@ +{ + "schemaVersion": 1, + "hostApiVersion": "2", + "templateVersion": "1", + "runtime": "YMhut.Box.PluginTauriHost", + "pluginBuildMode": "prebuilt", + "requiresSystemNode": false, + "requiresSystemRust": false +} diff --git a/src/YMhut.Box.PluginTauriHost/src-tauri/icons/icon.ico b/src/YMhut.Box.PluginTauriHost/src-tauri/icons/icon.ico index 08918bab258fb32f1e3daf7731536136652037dc..ab342b9811c2ba65336c3487347db4ea45da0f0c 100644 GIT binary patch literal 27338 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
    V=Xr5G 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%0DLbFOxa-xC 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 diff --git a/src/YMhut.Box.PluginTauriHost/src-tauri/src/main.rs b/src/YMhut.Box.PluginTauriHost/src-tauri/src/main.rs index b068c6b..4439a45 100644 --- a/src/YMhut.Box.PluginTauriHost/src-tauri/src/main.rs +++ b/src/YMhut.Box.PluginTauriHost/src-tauri/src/main.rs @@ -712,6 +712,7 @@ const BRIDGE_BOOTSTRAP: &str = r#" clipboard: { readText: () => call("clipboard.readText"), writeText: text => call("clipboard.writeText", text) }, file: { openPicker: () => call("file.openPicker"), savePicker: (name, value) => call("file.savePicker", { name, value }) }, tool: { run: (toolId, input) => call("tool.run", { toolId, input }) }, + externalTool: { launch: (bindingId, args = {}) => call("externalTool.launch", { bindingId, arguments: args }) }, openExternal: (url, options) => call("openExternal", { url, options }) }; Object.defineProperty(window, "ymhut", { value: Object.freeze(api), writable: false, configurable: false }); diff --git a/src/YMhut.Box.PluginTauriHost/template.ymtemplate b/src/YMhut.Box.PluginTauriHost/template.ymtemplate new file mode 100644 index 0000000..2547fea --- /dev/null +++ b/src/YMhut.Box.PluginTauriHost/template.ymtemplate @@ -0,0 +1,17 @@ +{ + "format": "ymhut-tauri-template", + "schemaVersion": 1, + "templateVersion": "1", + "hostApiVersion": "2", + "buildMode": "prebuilt", + "files": [ + { + "path": "dist/index.html", + "source": "template/dist/index.html" + }, + { + "path": "README.md", + "source": "template/README.md" + } + ] +} diff --git a/src/YMhut.Box.PluginTauriHost/template/README.md b/src/YMhut.Box.PluginTauriHost/template/README.md new file mode 100644 index 0000000..f14eeb0 --- /dev/null +++ b/src/YMhut.Box.PluginTauriHost/template/README.md @@ -0,0 +1,3 @@ +# YMhut Box prebuilt Tauri plugin + +Place production-ready HTML, CSS and JavaScript in `dist/`. The client supplies the controlled Tauri host. The installed plugin must not invoke Node, npm, Cargo or a private Tauri executable. diff --git a/src/YMhut.Box.PrivilegedHost/YMhut.Box.PrivilegedHost.csproj b/src/YMhut.Box.PrivilegedHost/YMhut.Box.PrivilegedHost.csproj index db906e5..bb77c4e 100644 --- a/src/YMhut.Box.PrivilegedHost/YMhut.Box.PrivilegedHost.csproj +++ b/src/YMhut.Box.PrivilegedHost/YMhut.Box.PrivilegedHost.csproj @@ -8,6 +8,7 @@ enable YMhut.Box.PrivilegedHost YMhut.Box.PrivilegedHost + ..\box-winUI\Assets\app_icon.ico diff --git a/src/YMhut.Box.Tests/ApplicationIconTests.cs b/src/YMhut.Box.Tests/ApplicationIconTests.cs new file mode 100644 index 0000000..20fac24 --- /dev/null +++ b/src/YMhut.Box.Tests/ApplicationIconTests.cs @@ -0,0 +1,140 @@ +using System.Buffers.Binary; +using System.Security.Cryptography; +using System.Xml.Linq; + +namespace YMhut.Box.Tests; + +[TestClass] +public sealed class ApplicationIconTests +{ + private static readonly int[] ExpectedFrameSizes = [16, 20, 24, 32, 40, 48, 64, 96, 128, 256]; + + [TestMethod] + public void SharedApplicationIconsContainEveryDpiFrameAndMatchExactly() + { + var root = FindRepositoryRoot(); + var paths = new[] + { + Path.Combine(root, "assets", "icon.ico"), + Path.Combine(root, "assets", "icons", "app_icon.ico"), + Path.Combine(root, "src", "box-winUI", "Assets", "app_icon.ico"), + Path.Combine(root, "src", "YMhut.Box.PluginTauriHost", "src-tauri", "icons", "icon.ico") + }; + var hashes = paths.Select(path => Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(path)))).ToArray(); + + Assert.IsTrue(hashes.All(hash => hash == hashes[0])); + foreach (var path in paths) + { + CollectionAssert.AreEqual(ExpectedFrameSizes, ReadIcoFrameSizes(path)); + } + } + + [TestMethod] + public void MsixLogosHaveStableNativeDimensions() + { + var assets = Path.Combine(FindRepositoryRoot(), "src", "box-winUI", "Assets"); + var expected = new Dictionary(StringComparer.OrdinalIgnoreCase) + { + ["StoreLogo.png"] = (50, 50), + ["Square44x44Logo.png"] = (44, 44), + ["Square150x150Logo.png"] = (150, 150), + ["LockScreenLogo.png"] = (70, 70), + ["Wide310x150Logo.png"] = (310, 150) + }; + + foreach (var item in expected) + { + Assert.AreEqual(item.Value, ReadPngDimensions(Path.Combine(assets, item.Key)), item.Key); + } + } + + [TestMethod] + public void EveryOwnedUserVisibleExecutableUsesTheSharedIcon() + { + var root = FindRepositoryRoot(); + var projects = new[] + { + "box-winUI/YMhut.Box.WinUI.csproj", + "YMhut.Box.InstallerBootstrap/YMhut.Box.InstallerBootstrap.csproj", + "YMhut.Box.DownloadHost/YMhut.Box.DownloadHost.csproj", + "YMhut.Box.HardwareMonitor/YMhut.Box.HardwareMonitor.csproj", + "YMhut.Box.PluginHost/YMhut.Box.PluginHost.csproj", + "YMhut.Box.PrivilegedHost/YMhut.Box.PrivilegedHost.csproj", + "YMhut.Box.Worker/YMhut.Box.Worker.csproj" + }; + + foreach (var relativePath in projects) + { + var document = XDocument.Load(Path.Combine(root, "src", relativePath.Replace('/', Path.DirectorySeparatorChar))); + var applicationIcon = document.Descendants().FirstOrDefault(element => element.Name.LocalName == "ApplicationIcon"); + Assert.IsNotNull(applicationIcon, relativePath); + StringAssert.EndsWith(applicationIcon.Value.Replace('/', '\\'), "app_icon.ico", relativePath); + } + } + + [TestMethod] + public void WindowIconServiceUsesEmbeddedHandlesWithoutTemporaryFiles() + { + var path = Path.Combine(FindRepositoryRoot(), "src", "box-winUI", "Services", "WindowIconService.cs"); + var source = File.ReadAllText(path); + + StringAssert.Contains(source, "GetManifestResourceStream"); + StringAssert.Contains(source, "WmSetIcon"); + StringAssert.Contains(source, "ConditionalWeakTable"); + Assert.IsFalse(source.Contains("GetTempPath", StringComparison.Ordinal)); + Assert.IsFalse(source.Contains("Delete(", StringComparison.Ordinal)); + } + + private static int[] ReadIcoFrameSizes(string path) + { + var bytes = File.ReadAllBytes(path); + Assert.IsGreaterThanOrEqualTo(6, bytes.Length, path); + Assert.AreEqual((ushort)0, BinaryPrimitives.ReadUInt16LittleEndian(bytes)); + Assert.AreEqual((ushort)1, BinaryPrimitives.ReadUInt16LittleEndian(bytes.AsSpan(2))); + var count = BinaryPrimitives.ReadUInt16LittleEndian(bytes.AsSpan(4)); + Assert.AreEqual(ExpectedFrameSizes.Length, count, path); + + var sizes = new int[count]; + for (var index = 0; index < count; index++) + { + var offset = 6 + index * 16; + Assert.IsGreaterThanOrEqualTo(offset + 16, bytes.Length, path); + var width = bytes[offset] == 0 ? 256 : bytes[offset]; + var height = bytes[offset + 1] == 0 ? 256 : bytes[offset + 1]; + Assert.AreEqual(width, height, path); + var payloadLength = BinaryPrimitives.ReadUInt32LittleEndian(bytes.AsSpan(offset + 8)); + var payloadOffset = BinaryPrimitives.ReadUInt32LittleEndian(bytes.AsSpan(offset + 12)); + Assert.IsTrue(payloadLength > 8 && payloadOffset + payloadLength <= bytes.Length, path); + Assert.IsTrue(bytes.AsSpan((int)payloadOffset, 8).SequenceEqual(new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }), path); + sizes[index] = width; + } + + return sizes; + } + + private static (int Width, int Height) ReadPngDimensions(string path) + { + var bytes = File.ReadAllBytes(path); + Assert.IsGreaterThanOrEqualTo(24, bytes.Length, path); + Assert.IsTrue(bytes.AsSpan(0, 8).SequenceEqual(new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }), path); + return ( + BinaryPrimitives.ReadInt32BigEndian(bytes.AsSpan(16, 4)), + BinaryPrimitives.ReadInt32BigEndian(bytes.AsSpan(20, 4))); + } + + private static string FindRepositoryRoot() + { + var current = new DirectoryInfo(AppContext.BaseDirectory); + while (current is not null) + { + if (File.Exists(Path.Combine(current.FullName, "YMhut.Box.Native.sln"))) + { + return current.FullName; + } + + current = current.Parent; + } + + throw new DirectoryNotFoundException("Repository root was not found."); + } +} diff --git a/src/YMhut.Box.Tests/AuthenticatedAssetPackageTests.cs b/src/YMhut.Box.Tests/AuthenticatedAssetPackageTests.cs new file mode 100644 index 0000000..4ac0069 --- /dev/null +++ b/src/YMhut.Box.Tests/AuthenticatedAssetPackageTests.cs @@ -0,0 +1,143 @@ +using System.IO.Compression; +using System.Security.Cryptography; +using System.Text; +using System.Text.Json; +using YMhut.Box.Core.App; +using YMhut.Box.Core.Data; + +namespace YMhut.Box.Tests; + +[TestClass] +public sealed class AuthenticatedAssetPackageTests +{ + [TestMethod] + public void ReadVerifiedEntriesAcceptsAuthenticatedContent() + { + var package = CreatePackage("runtime-assets", ("tool-pages/index.html", "ok")); + + var entries = AuthenticatedAssetPackage.ReadVerifiedEntries(package, "runtime-assets"); + + Assert.HasCount(1, entries); + Assert.AreEqual("tool-pages/index.html", entries[0].Path); + Assert.AreEqual("ok", Encoding.UTF8.GetString(entries[0].Content)); + } + + [TestMethod] + public void ReadVerifiedEntriesRejectsTampering() + { + var package = CreatePackage("runtime-assets", ("tool-pages/index.html", "ok")); + package[^40] ^= 0x5a; + + Assert.ThrowsExactly(() => + AuthenticatedAssetPackage.ReadVerifiedEntries(package, "runtime-assets")); + } + + [TestMethod] + public void ReadVerifiedEntriesRejectsPathTraversal() + { + var package = CreatePackage("runtime-assets", ("../replaced.png", "not-an-image")); + + Assert.ThrowsExactly(() => + AuthenticatedAssetPackage.ReadVerifiedEntries(package, "runtime-assets")); + } + + [TestMethod] + public void ReadVerifiedEntriesRejectsAbsolutePath() + { + var package = CreatePackage("runtime-assets", ("/replaced.png", "not-an-image")); + + Assert.ThrowsExactly(() => + AuthenticatedAssetPackage.ReadVerifiedEntries(package, "runtime-assets")); + } + + [TestMethod] + public async Task ReferenceDataServiceReadsAuthenticatedYbin() + { + var root = Path.Combine(Path.GetTempPath(), "ymhut-box-auth-assets", Guid.NewGuid().ToString("N")); + var assets = Path.Combine(root, "Assets"); + Directory.CreateDirectory(Path.Combine(assets, "data")); + try + { + var package = CreatePackage("reference-data", ("data/reference/sample.json", "{\"value\":42}")); + await File.WriteAllBytesAsync(Path.Combine(assets, "data", "ymhut-data.ybin"), package); + var service = new ReferenceDataService(AppPaths.ForCurrentUser(Path.Combine(root, "User"), assets)); + + var text = await service.ReadTextAsync("data/reference/sample.json"); + + Assert.AreEqual("{\"value\":42}", text); + } + finally + { + if (Directory.Exists(root)) + { + Directory.Delete(root, recursive: true); + } + } + } + + private static byte[] CreatePackage(string purpose, params (string Path, string Text)[] files) + { + var content = files.Select(file => (file.Path, Bytes: Encoding.UTF8.GetBytes(file.Text))).ToArray(); + using var plainStream = new MemoryStream(); + using (var archive = new ZipArchive(plainStream, ZipArchiveMode.Create, leaveOpen: true)) + { + foreach (var file in content) + { + var entry = archive.CreateEntry(file.Path, CompressionLevel.Fastest); + using var output = entry.Open(); + output.Write(file.Bytes); + } + + var manifest = new + { + schemaVersion = 2, + bundleId = purpose, + files = content.Select(file => new + { + path = file.Path, + length = file.Bytes.Length, + sha256 = Convert.ToHexString(SHA256.HashData(file.Bytes)).ToLowerInvariant() + }) + }; + var manifestEntry = archive.CreateEntry("_manifest.json", CompressionLevel.Fastest); + using var manifestOutput = manifestEntry.Open(); + JsonSerializer.Serialize(manifestOutput, manifest); + } + + var plain = plainStream.ToArray(); + var salt = RandomNumberGenerator.GetBytes(16); + var iv = RandomNumberGenerator.GetBytes(16); + var purposeBytes = Encoding.UTF8.GetBytes("YMhut.Box.AssetPackage.v2|" + purpose); + var material = new byte[purposeBytes.Length + salt.Length]; + purposeBytes.CopyTo(material, 0); + salt.CopyTo(material, purposeBytes.Length); + var keys = SHA512.HashData(material); + + byte[] cipher; + using (var aes = Aes.Create()) + { + aes.Key = keys[..32]; + aes.IV = iv; + aes.Mode = CipherMode.CBC; + aes.Padding = PaddingMode.PKCS7; + using var encryptor = aes.CreateEncryptor(); + cipher = encryptor.TransformFinalBlock(plain, 0, plain.Length); + } + + using var signedStream = new MemoryStream(); + using (var writer = new BinaryWriter(signedStream, Encoding.UTF8, leaveOpen: true)) + { + writer.Write(Encoding.ASCII.GetBytes("YMHUTAS2")); + writer.Write((byte)2); + writer.Write(salt); + writer.Write(iv); + writer.Write((long)plain.Length); + writer.Write((long)cipher.Length); + writer.Write(cipher); + } + + var signed = signedStream.ToArray(); + using var hmac = new HMACSHA256(keys[32..]); + return [.. signed, .. hmac.ComputeHash(signed)]; + } +} diff --git a/src/YMhut.Box.Tests/InstallLayoutPathsTests.cs b/src/YMhut.Box.Tests/InstallLayoutPathsTests.cs index 6fd174b..6ab0410 100644 --- a/src/YMhut.Box.Tests/InstallLayoutPathsTests.cs +++ b/src/YMhut.Box.Tests/InstallLayoutPathsTests.cs @@ -115,6 +115,88 @@ public sealed class InstallLayoutPathsTests Assert.IsTrue(manifest.RequiredFiles.SequenceEqual(["YMhutBox.exe", "YMhutBox.dll"])); Assert.IsTrue(manifest.ContainsFile(@"lang\zh-CN\Microsoft.ui.xaml.dll.mui")); Assert.IsTrue(manifest.ContainsFile("Tools/SampleTool/tool.exe")); + Assert.AreEqual(1, manifest.SchemaVersion); + } + + [TestMethod] + public void InstallManifestParserReadsVersionedManifestAndKeepsLegacyCompatibility() + { + var versioned = InstallManifest.Parse( + """ + [Release] + ManifestVersion=2 + Version=2.0.7.14 + + [Files] + YMhutBox.exe + """); + var legacy = InstallManifest.Parse("[Files]\nYMhutBox.exe"); + + Assert.AreEqual(2, versioned.SchemaVersion); + Assert.AreEqual(1, legacy.SchemaVersion); + Assert.IsTrue(versioned.ContainsFile("YMhutBox.exe")); + Assert.IsTrue(legacy.ContainsFile("YMhutBox.exe")); + } + + [TestMethod] + public void InnoUpgradeCleanupRunsOnlyAfterNewPayloadValidation() + { + var root = FindRepositoryRoot(); + var script = File.ReadAllText(Path.Combine(root, "installer", "ymhut_box_winui.iss")); + var installStep = script[script.IndexOf("procedure CurStepChanged", StringComparison.Ordinal)..]; + var filesStage = installStep[..installStep.IndexOf("else if CurStep = ssPostInstall", StringComparison.Ordinal)]; + var postInstall = installStep[installStep.IndexOf("else if CurStep = ssPostInstall", StringComparison.Ordinal)..]; + + Assert.DoesNotContain("[InstallDelete]", script, StringComparison.OrdinalIgnoreCase); + Assert.DoesNotContain("FinalizeLegacyInstallLayout", filesStage, StringComparison.Ordinal); + Assert.Contains("VerifyNewApplicationPayload", script, StringComparison.Ordinal); + Assert.Contains("FinalizeLegacyInstallLayout", postInstall, StringComparison.Ordinal); + Assert.Contains("data\\legacy-imports\\program-backup-", script, StringComparison.OrdinalIgnoreCase); + Assert.Contains("IsPreservedInstallPath", script, StringComparison.Ordinal); + Assert.Contains("if OldPayloadFiles.Count > 0 then", script, StringComparison.Ordinal); + Assert.Contains("DeleteKnownObsoletePayload(AppDir)", script, StringComparison.Ordinal); + Assert.Contains( + "else\n QuarantineUnknownLegacyFiles(AppDir, AppDir)", + script.Replace("\r\n", "\n", StringComparison.Ordinal), + StringComparison.Ordinal); + } + + [TestMethod] + public void CustomUninstallerOwnsThePublicEntryAndMsixExcludesIt() + { + var root = FindRepositoryRoot(); + var inno = File.ReadAllText(Path.Combine(root, "installer", "ymhut_box_winui.iss")); + var build = File.ReadAllText(Path.Combine(root, "scripts", "build-winui.ps1")); + var engine = File.ReadAllText(Path.Combine(root, "src", "YMhut.Box.InstallerBootstrap", "UninstallEngine.cs")); + + Assert.Contains("UninstallFilesDir={app}\\Runtime\\uninstall-engine", inno, StringComparison.Ordinal); + Assert.Contains("RegisterCustomUninstallEntry", inno, StringComparison.Ordinal); + Assert.Contains("QuietUninstallString", inno, StringComparison.Ordinal); + Assert.Contains("Runtime\\uninstall-engine\\unins000.dat", inno, StringComparison.Ordinal); + Assert.Contains("-p:BootstrapMode=Uninstall", build, StringComparison.Ordinal); + Assert.Contains("Join-Path $MsixStageRoot 'unins000.exe'", build, StringComparison.Ordinal); + Assert.Contains("RemoveUserData", engine, StringComparison.Ordinal); + Assert.Contains("/VERYSILENT", engine, StringComparison.Ordinal); + Assert.Contains("ScheduleBootstrapCleanup", engine, StringComparison.Ordinal); + Assert.Contains("UseShellExecute = false", engine, StringComparison.Ordinal); + var uninstallerWindow = File.ReadAllText(Path.Combine(root, "src", "YMhut.Box.InstallerBootstrap", "UninstallerWindow.cs")); + Assert.Contains("if (result.Success)", uninstallerWindow, StringComparison.Ordinal); + Assert.Contains("_running = false", uninstallerWindow, StringComparison.Ordinal); + Assert.IsLessThan( + inno.IndexOf("RegisterCustomUninstallEntry(ExpandConstant('{app}'));", StringComparison.Ordinal), + inno.IndexOf("FinalizeLegacyInstallLayout();", StringComparison.Ordinal)); + } + + [TestMethod] + public void RankBadgesUseCompiledPathIconsWithNumericFallback() + { + var root = FindRepositoryRoot(); + var source = File.ReadAllText(Path.Combine(root, "src", "box-winUI", "Controls", "RankBadgeFactory.cs")); + + Assert.Contains("new PathIcon", source, StringComparison.Ordinal); + Assert.Contains("CreateNumber(rank, size)", source, StringComparison.Ordinal); + Assert.DoesNotContain("http://", source, StringComparison.OrdinalIgnoreCase); + Assert.DoesNotContain("https://", source, StringComparison.OrdinalIgnoreCase); } [TestMethod] diff --git a/src/YMhut.Box.Tests/PearApiClientTests.cs b/src/YMhut.Box.Tests/PearApiClientTests.cs new file mode 100644 index 0000000..10f8fb4 --- /dev/null +++ b/src/YMhut.Box.Tests/PearApiClientTests.cs @@ -0,0 +1,344 @@ +using System.Net; +using System.Net.Http.Headers; +using System.Text; +using System.Text.RegularExpressions; +using YMhut.Box.Core.Api; + +namespace YMhut.Box.Tests; + +[TestClass] +public sealed class PearApiClientTests +{ + [TestMethod] + public void CatalogContainsTheVerified74DefinitionsAndOnlySafeEnabledPaths() + { + Assert.HasCount(74, PearApiCatalog.All); + Assert.HasCount(74, PearApiCatalog.All.Select(definition => definition.ToolId).Distinct(StringComparer.OrdinalIgnoreCase).ToArray()); + Assert.AreEqual("https://api.pearapi.ai/api/", PearApiClient.ServiceRoot.AbsoluteUri); + + var enabled = PearApiCatalog.All.Where(definition => definition.IsAvailableWithoutKey).ToArray(); + Assert.IsTrue(enabled.All(definition => definition.EndpointPath.StartsWith("/api/", StringComparison.Ordinal))); + Assert.IsTrue(enabled.All(definition => !definition.Parameters.Any(parameter => + parameter.Name.Replace("_", string.Empty, StringComparison.Ordinal).Replace("-", string.Empty, StringComparison.Ordinal) + .Equals("apikey", StringComparison.OrdinalIgnoreCase) || + parameter.Name.Equals("key", StringComparison.OrdinalIgnoreCase) || + parameter.Name.Equals("authorization", StringComparison.OrdinalIgnoreCase)))); + + var disabled = PearApiCatalog.All.Where(definition => !definition.IsAvailableWithoutKey) + .Select(definition => definition.ToolId) + .OrderBy(id => id, StringComparer.Ordinal) + .ToArray(); + CollectionAssert.AreEqual(new[] { "ai_latest_news", "pear_embeddings" }, disabled); + + CollectionAssert.AreEquivalent(new[] { "baidu_hot", "bili_hot", "zhihu_hot" }, PearApiCatalog.LegacyAliasToolIds.ToArray()); + Assert.AreEqual("百度", PearApiCatalog.GetRequired("baidu_hot").Parameters.Single(parameter => parameter.Name == "title").DefaultValue); + } + + [TestMethod] + public async Task RequestUsesOnlyFixedPearApiHostAndRemovesAuthenticationHeaders() + { + CapturedRequest? captured = null; + var handler = new StubHttpHandler(request => + { + captured = CapturedRequest.From(request); + return JsonResponse("{\"ok\":true}"); + }); + using var httpClient = new HttpClient(handler); + httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "secret"); + httpClient.DefaultRequestHeaders.Add("X-API-Key", "secret"); + using var client = new PearApiClient(httpClient); + + var response = await client.SendAsync(new PearApiRequest("pear_world_60")); + + Assert.IsTrue(response.Success); + Assert.IsNotNull(captured); + Assert.AreEqual("https", captured.Scheme); + Assert.AreEqual("api.pearapi.ai", captured.Host); + Assert.IsTrue(captured.Path.StartsWith("/api/", StringComparison.Ordinal)); + Assert.IsFalse(captured.HasAuthorization); + Assert.IsFalse(captured.HasApiKey); + } + + [TestMethod] + public async Task PublicParameterlessGetUsesMemoryCache() + { + var calls = 0; + using var httpClient = new HttpClient(new StubHttpHandler(_ => + { + calls++; + return JsonResponse("{\"data\":\"cached\"}"); + })); + using var client = new PearApiClient(httpClient); + + var first = await client.SendAsync(new PearApiRequest("pear_world_60")); + var second = await client.SendAsync(new PearApiRequest("pear_world_60")); + + Assert.IsTrue(first.Success); + Assert.IsTrue(second.Success); + Assert.IsFalse(first.IsFromCache); + Assert.IsTrue(second.IsFromCache); + Assert.AreEqual(1, calls); + } + + [TestMethod] + public async Task UserTextRequestsAreNeverCached() + { + var calls = 0; + using var httpClient = new HttpClient(new StubHttpHandler(_ => + { + calls++; + return JsonResponse("{\"data\":\"translated\"}"); + })); + using var client = new PearApiClient(httpClient); + var request = new PearApiRequest("pear_translation", new Dictionary { ["text"] = "hello" }); + + var first = await client.SendAsync(request); + var second = await client.SendAsync(request); + + Assert.IsTrue(first.Success); + Assert.IsTrue(second.Success); + Assert.IsFalse(first.IsFromCache); + Assert.IsFalse(second.IsFromCache); + Assert.AreEqual(2, calls); + } + + [TestMethod] + [DataRow("pear_short_recovery", "url", "http://127.0.0.1/private")] + [DataRow("pear_short_recovery", "url", "file:///C:/Windows/win.ini")] + [DataRow("pear_site_index", "url", "localhost")] + [DataRow("pear_site_index", "url", "example.com/path")] + public async Task PrivateOrInvalidUrlAndDomainParametersAreRejectedBeforeNetwork(string toolId, string name, string value) + { + var calls = 0; + using var httpClient = new HttpClient(new StubHttpHandler(_ => + { + calls++; + return JsonResponse("{}"); + })); + using var client = new PearApiClient(httpClient); + + var response = await client.SendAsync(new PearApiRequest(toolId, new Dictionary { [name] = value })); + + Assert.IsFalse(response.Success); + Assert.AreEqual(0, calls); + } + + [TestMethod] + public async Task UndeclaredParametersAreRejectedBeforeNetwork() + { + var calls = 0; + using var httpClient = new HttpClient(new StubHttpHandler(_ => + { + calls++; + return JsonResponse("{}"); + })); + using var client = new PearApiClient(httpClient); + + var response = await client.SendAsync(new PearApiRequest("pear_world_60", new Dictionary { ["key"] = "must-not-leave-device" })); + + Assert.IsFalse(response.Success); + StringAssert.Contains(response.Error ?? string.Empty, "未声明"); + Assert.AreEqual(0, calls); + } + + [TestMethod] + public async Task UploadRequiresConfirmationAndValidFileSignature() + { + var path = Path.GetTempFileName(); + await File.WriteAllTextAsync(path, "not an image"); + try + { + var calls = 0; + using var httpClient = new HttpClient(new StubHttpHandler(_ => + { + calls++; + return JsonResponse("{}"); + })); + using var client = new PearApiClient(httpClient); + + var unconfirmed = await client.SendAsync(new PearApiRequest("pear_ai_image_describe", FilePath: path)); + var invalidMime = await client.SendAsync(new PearApiRequest("pear_ai_image_describe", FilePath: path, UploadConfirmed: true)); + + Assert.IsFalse(unconfirmed.Success); + StringAssert.Contains(unconfirmed.Error ?? string.Empty, "确认"); + Assert.IsFalse(invalidMime.Success); + StringAssert.Contains(invalidMime.Error ?? string.Empty, "真实格式"); + Assert.AreEqual(0, calls); + } + finally + { + File.Delete(path); + } + } + + [TestMethod] + [DataRow("pear_ai_image_describe", 10, true)] + [DataRow("pear_audio_transcript", 50, false)] + public async Task UploadSizeLimitsAreEnforcedBeforeNetwork(string toolId, int limitMiB, bool image) + { + var path = Path.GetTempFileName(); + try + { + await using (var stream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None)) + { + var signature = image + ? new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A } + : "ID3"u8.ToArray(); + await stream.WriteAsync(signature); + stream.SetLength(limitMiB * 1024L * 1024L + 1); + } + + var calls = 0; + using var httpClient = new HttpClient(new StubHttpHandler(_ => + { + calls++; + return JsonResponse("{}"); + })); + using var client = new PearApiClient(httpClient); + + var response = await client.SendAsync(new PearApiRequest(toolId, FilePath: path, UploadConfirmed: true)); + + Assert.IsFalse(response.Success); + StringAssert.Contains(response.Error ?? string.Empty, $"{limitMiB} MiB"); + Assert.AreEqual(0, calls); + } + finally + { + File.Delete(path); + } + } + + [TestMethod] + public async Task CancellationDoesNotReachNetwork() + { + var calls = 0; + using var httpClient = new HttpClient(new StubHttpHandler(_ => + { + calls++; + return JsonResponse("{}"); + })); + using var client = new PearApiClient(httpClient); + using var cancellation = new CancellationTokenSource(); + cancellation.Cancel(); + + var response = await client.SendAsync( + new PearApiRequest("pear_translation", new Dictionary { ["text"] = "cancel" }), + cancellation.Token); + + Assert.IsFalse(response.Success); + StringAssert.Contains(response.Error ?? string.Empty, "取消"); + Assert.AreEqual(0, calls); + } + + [TestMethod] + public async Task OversizedResponseIsRejected() + { + using var httpClient = new HttpClient(new StubHttpHandler(_ => + { + var content = new ByteArrayContent([0]); + content.Headers.ContentLength = 8L * 1024 * 1024 + 1; + return new HttpResponseMessage(HttpStatusCode.OK) { Content = content }; + })); + using var client = new PearApiClient(httpClient); + + var response = await client.SendAsync(new PearApiRequest("pear_world_60")); + + Assert.IsFalse(response.Success); + Assert.IsNull(response.BinaryContent); + } + + [TestMethod] + public async Task ApiSourceIsRemovedRecursivelyFromResponsesAndNeverAcceptedAsInput() + { + CapturedRequest? captured = null; + using var httpClient = new HttpClient(new StubHttpHandler(request => + { + captured = CapturedRequest.From(request); + return JsonResponse(""" + { + "api_source": "https://brand.example/one", + "source": "kept", + "data": [ + { "apiSource": "https://brand.example/two", "title": "visible" }, + { "nested": { "API-SOURCE": "https://brand.example/three", "value": 7 } } + ] + } + """); + })); + using var client = new PearApiClient(httpClient); + + var response = await client.SendAsync(new PearApiRequest("pear_world_60")); + + Assert.IsTrue(response.Success, response.Error); + Assert.IsFalse(response.Content.Contains("brand.example", StringComparison.OrdinalIgnoreCase)); + Assert.IsFalse(response.Content.Contains("api_source", StringComparison.OrdinalIgnoreCase)); + Assert.IsFalse(response.Content.Contains("apiSource", StringComparison.Ordinal)); + Assert.IsTrue(response.Content.Contains("\"source\":\"kept\"", StringComparison.Ordinal)); + Assert.IsNotNull(captured); + Assert.IsTrue(PearApiPresentationSanitizer.IsHiddenField("api_source")); + Assert.IsTrue(PearApiPresentationSanitizer.IsHiddenField("apiSource")); + Assert.IsFalse(PearApiPresentationSanitizer.IsHiddenField("source")); + Assert.IsTrue(PearApiCatalog.All.All(definition => definition.Parameters.All(parameter => + !PearApiPresentationSanitizer.IsHiddenField(parameter.Name)))); + } + + [TestMethod] + public void GeneratedPearPagesAreDedicatedAndDoNotInheritAdaptiveToolPage() + { + var root = FindRepositoryRoot(); + var generated = File.ReadAllText(Path.Combine(root, "src", "box-winUI", "Views", "Tools", "GeneratedPearApiToolPages.cs")); + var pageMatches = Regex.Matches( + generated, + @"public sealed class \w+PearApiToolPage\([^\r\n]+\) : (?\w+)", + RegexOptions.CultureInvariant); + + Assert.HasCount(PearApiCatalog.All.Count + PearApiCatalog.LegacyAliasToolIds.Count, pageMatches); + Assert.IsTrue(pageMatches.Cast().All(match => match.Groups["base"].Value == "PearApiToolPageBase")); + Assert.IsFalse(generated.Contains(": AdaptiveToolPage", StringComparison.Ordinal)); + + var pageBase = File.ReadAllText(Path.Combine(root, "src", "box-winUI", "Views", "Tools", "PearApiToolPageBase.cs")); + Assert.IsFalse(pageBase.Contains(": AdaptiveToolPage", StringComparison.Ordinal)); + } + + private static HttpResponseMessage JsonResponse(string json) + => new(HttpStatusCode.OK) + { + Content = new StringContent(json, Encoding.UTF8, "application/json") + }; + + private static string FindRepositoryRoot() + { + var current = new DirectoryInfo(AppContext.BaseDirectory); + while (current is not null) + { + if (File.Exists(Path.Combine(current.FullName, "YMhut.Box.Native.sln"))) + { + return current.FullName; + } + + current = current.Parent; + } + + throw new DirectoryNotFoundException("Repository root was not found."); + } + + private sealed class StubHttpHandler(Func handler) : HttpMessageHandler + { + protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + return Task.FromResult(handler(request)); + } + } + + private sealed record CapturedRequest(string Scheme, string Host, string Path, bool HasAuthorization, bool HasApiKey) + { + public static CapturedRequest From(HttpRequestMessage request) + => new( + request.RequestUri?.Scheme ?? string.Empty, + request.RequestUri?.Host ?? string.Empty, + request.RequestUri?.AbsolutePath ?? string.Empty, + request.Headers.Authorization is not null || request.Headers.Contains("Authorization"), + request.Headers.Contains("X-API-Key")); + } +} diff --git a/src/YMhut.Box.Tests/PluginSecurityTests.cs b/src/YMhut.Box.Tests/PluginSecurityTests.cs index c6b0a60..bead2b7 100644 --- a/src/YMhut.Box.Tests/PluginSecurityTests.cs +++ b/src/YMhut.Box.Tests/PluginSecurityTests.cs @@ -1,5 +1,7 @@ using Microsoft.Data.Sqlite; using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.IO.Compression; +using System.Security.Cryptography; using YMhut.Box.Core.App; using YMhut.Box.Core.Plugins; using YMhut.Box.Core.Plugins.Runtime; @@ -200,7 +202,7 @@ public sealed class PluginSecurityTests File.WriteAllText(Path.Combine(created.Path!, "native.exe"), "not an executable"); var rejected = await service.ImportFolderAsync(created.Path!, targetRoot); Assert.IsFalse(rejected.Succeeded); - StringAssert.Contains(rejected.Message, "Unsafe"); + StringAssert.Contains(rejected.Message, "validation"); var clean = await service.CreateTemplateAsync(sourceRoot, "bridge-demo", "Bridge Demo", PluginTemplateKind.BridgeNetwork); var imported = await service.ImportFolderAsync(clean.Path!, targetRoot); @@ -220,6 +222,89 @@ public sealed class PluginSecurityTests Assert.IsFalse(uninstall.Succeeded); } + [TestMethod] + public void TauriToolBindingsRequireExactHashesAndRejectElevationOrInstallerRoles() + { + using var workspace = TempWorkspace(); + var root = CreatePackage(workspace.Path); + var executable = Path.Combine(root, "tool.exe"); + var library = Path.Combine(root, "tool.dll"); + File.WriteAllText(executable, "MZ controlled tool"); + File.WriteAllText(library, "MZ controlled library"); + var manifest = CreateTauriBindingManifest( + "tool.exe", + [ + new PluginToolFileSpec("tool.exe", Hash(executable)), + new PluginToolFileSpec("tool.dll", Hash(library)) + ]); + + Assert.IsEmpty(PluginRegistryService.ValidatePackage(manifest, root)); + + File.AppendAllText(library, "tampered"); + var tampered = PluginRegistryService.ValidatePackage(manifest, root); + Assert.IsTrue(tampered.Any(error => error.Contains("hash", StringComparison.OrdinalIgnoreCase))); + + File.WriteAllText(library, "MZ controlled library"); + File.WriteAllText(executable, "MZ "); + var elevatedManifest = CreateTauriBindingManifest( + "tool.exe", + [ + new PluginToolFileSpec("tool.exe", Hash(executable)), + new PluginToolFileSpec("tool.dll", Hash(library)) + ]); + Assert.IsTrue(PluginRegistryService.ValidatePackage(elevatedManifest, root) + .Any(error => error.Contains("elevation", StringComparison.OrdinalIgnoreCase))); + + var updater = Path.Combine(root, "updater.exe"); + File.Move(executable, updater, true); + var updaterManifest = CreateTauriBindingManifest( + "updater.exe", + [ + new PluginToolFileSpec("updater.exe", Hash(updater)), + new PluginToolFileSpec("tool.dll", Hash(library)) + ]); + Assert.IsTrue(PluginRegistryService.ValidatePackage(updaterManifest, root) + .Any(error => error.Contains("Installers", StringComparison.OrdinalIgnoreCase))); + } + + [TestMethod] + public async Task YmpluginInventoryDetectsArchiveTampering() + { + using var workspace = TempWorkspace(); + var paths = AppPaths.ForCurrentUser(Path.Combine(workspace.Path, "app")); + var service = new PluginPackageService(paths, new PluginStateStore(paths)); + var pluginRoot = CreatePackage(Path.Combine(workspace.Path, "source")); + var manifest = StrictManifest() with { Id = "inventory-demo" }; + await File.WriteAllTextAsync( + Path.Combine(pluginRoot, PluginManifest.FileName), + System.Text.Json.JsonSerializer.Serialize(manifest, new System.Text.Json.JsonSerializerOptions(System.Text.Json.JsonSerializerDefaults.Web) + { + Converters = + { + new System.Text.Json.Serialization.JsonStringEnumConverter(), + new System.Text.Json.Serialization.JsonStringEnumConverter(), + new System.Text.Json.Serialization.JsonStringEnumConverter() + } + })); + var state = new PluginRuntimeState(manifest.Id, false, new HashSet(), new HashSet(), null); + var plugin = new LoadedPlugin(manifest, pluginRoot, state, []); + var packagePath = Path.Combine(workspace.Path, "inventory-demo.ymplugin"); + var exported = await service.ExportPackageAsync(plugin, packagePath); + Assert.IsTrue(exported.Succeeded, exported.Message); + + using (var archive = ZipFile.Open(packagePath, ZipArchiveMode.Update)) + { + archive.GetEntry("index.html")!.Delete(); + var replacement = archive.CreateEntry("index.html"); + await using var writer = new StreamWriter(replacement.Open()); + await writer.WriteAsync("tampered"); + } + + var imported = await service.ImportPackageAsync(packagePath, Path.Combine(workspace.Path, "target")); + Assert.IsFalse(imported.Succeeded); + StringAssert.Contains(imported.Message, "integrity"); + } + [TestMethod] public void ProtocolV2RoundTripsSessionBindingAndErrorCode() { @@ -277,6 +362,7 @@ public sealed class PluginSecurityTests ["clipboard.writeText"] = PluginPermission.Clipboard, ["file.openPicker"] = PluginPermission.FilePicker, ["file.savePicker"] = PluginPermission.FilePicker, + ["externalTool.launch"] = PluginPermission.ExternalTool, ["openExternal"] = PluginPermission.OpenExternal }; CollectionAssert.AreEquivalent(expected.Keys.ToArray(), PluginBridgePolicy.MethodPermissions.Keys.ToArray()); @@ -304,6 +390,46 @@ public sealed class PluginSecurityTests PermissionReasons: new Dictionary(), Network: new PluginNetworkSpec([], [], [])); + private static PluginManifest CreateTauriBindingManifest(string executable, IReadOnlyList files) => new( + "tauri-binding-test", + "Tauri Binding Test", + "1.0.0", + "tester", + "Controlled native tool test", + "index.html", + [PluginPermission.ExternalRuntime, PluginPermission.ExternalTool], + [new PluginSurface(PluginSurfaceKind.ToolboxTool, "main", "Main", "Main surface")], + ["index.html", "README.md"], + PluginRuntimeKind.Tauri, + Security: new PluginSecuritySpec([PluginPermission.ExternalRuntime, PluginPermission.ExternalTool]), + Tauri: new PluginTauriSpec(BuildOnCreate: false, RebuildOnMissingOrChanged: false, DistDirectory: "."), + ManifestVersion: 3, + ApiVersion: "2", + PermissionReasons: new Dictionary + { + [PluginPermission.ExternalRuntime] = "Render the prebuilt plugin surface.", + [PluginPermission.ExternalTool] = "Launch the declared and hashed test tool." + }, + Network: new PluginNetworkSpec([], [], []), + ToolBindings: + [ + new PluginToolBindingSpec( + "tool", + "Tool", + executable, + files, + ["--value", "{value}"], + [new PluginToolArgumentSpec("value", PluginToolArgumentKind.Integer, Required: true)], + ".", + "x64") + ]); + + private static string Hash(string path) + { + using var stream = File.OpenRead(path); + return Convert.ToHexString(SHA256.HashData(stream)); + } + private static string CreatePackage(string root) { Directory.CreateDirectory(root); diff --git a/src/YMhut.Box.Tests/ToolCatalogTests.cs b/src/YMhut.Box.Tests/ToolCatalogTests.cs index 7a9f2d0..d6ca9f6 100644 --- a/src/YMhut.Box.Tests/ToolCatalogTests.cs +++ b/src/YMhut.Box.Tests/ToolCatalogTests.cs @@ -1,5 +1,6 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using System.Text.RegularExpressions; +using YMhut.Box.Core.Api; using YMhut.Box.Core.Tools; namespace YMhut.Box.Tests; @@ -48,13 +49,11 @@ public sealed class ToolCatalogTests public void GeneratedWinUiRegistrationsCoverEveryDefaultToolPage() { var repositoryRoot = FindRepositoryRoot(); - var source = File.ReadAllText(Path.Combine( - repositoryRoot, - "src", - "box-winUI", - "Views", - "Tools", - "GeneratedToolPages.cs")); + var toolsRoot = Path.Combine(repositoryRoot, "src", "box-winUI", "Views", "Tools"); + var source = string.Join( + Environment.NewLine, + File.ReadAllText(Path.Combine(toolsRoot, "GeneratedToolPages.cs")), + File.ReadAllText(Path.Combine(toolsRoot, "GeneratedPearApiToolPages.cs"))); var registered = Regex.Matches( source, "registry\\.Register<[^>]+>\\(\"(?[^\"]+)\"", @@ -69,6 +68,10 @@ public sealed class ToolCatalogTests .ToArray(); Assert.IsEmpty(missing, $"Missing WinUI tool registrations: {string.Join(", ", missing)}"); + foreach (var aliasId in PearApiCatalog.LegacyAliasToolIds) + { + Assert.DoesNotContain($"\"{aliasId}\"", File.ReadAllText(Path.Combine(toolsRoot, "GeneratedToolPages.cs")), StringComparison.Ordinal); + } } [TestMethod] diff --git a/src/YMhut.Box.Tests/ToolUiDefinitionTests.cs b/src/YMhut.Box.Tests/ToolUiDefinitionTests.cs index 611882e..c51ba30 100644 --- a/src/YMhut.Box.Tests/ToolUiDefinitionTests.cs +++ b/src/YMhut.Box.Tests/ToolUiDefinitionTests.cs @@ -70,8 +70,17 @@ public sealed class ToolUiDefinitionTests { var folder = Path.Combine(FindRepositoryRoot(), "assets", "data", "tool-ui"); var files = Directory.GetFiles(folder, "*.dat", SearchOption.TopDirectoryOnly); + var expectedIds = ToolCatalog.DefaultModules().Select(module => module.Id) + .Concat(NexNativeToolCatalog.Modules.Select(module => module.Id)) + .Concat(["plugin-host", "external-tool-host"]) + .Distinct(StringComparer.OrdinalIgnoreCase) + .OrderBy(id => id, StringComparer.OrdinalIgnoreCase) + .ToArray(); + var actualIds = files.Select(Path.GetFileNameWithoutExtension) + .OrderBy(id => id, StringComparer.OrdinalIgnoreCase) + .ToArray(); - Assert.IsGreaterThanOrEqualTo(202, files.Length); + CollectionAssert.AreEqual(expectedIds, actualIds); foreach (var file in files) { var bytes = File.ReadAllBytes(file); diff --git a/src/YMhut.Box.Tests/WeatherCapsuleLayoutTests.cs b/src/YMhut.Box.Tests/WeatherCapsuleLayoutTests.cs new file mode 100644 index 0000000..63bd9cb --- /dev/null +++ b/src/YMhut.Box.Tests/WeatherCapsuleLayoutTests.cs @@ -0,0 +1,25 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using YMhut.Box.WinUI.Controls; + +namespace YMhut.Box.Tests; + +[TestClass] +public sealed class WeatherCapsuleLayoutTests +{ + [TestMethod] + public void WeatherCapsuleDegradesThroughEveryStableMode() + { + Assert.AreEqual(WeatherCapsuleDisplayMode.Full, WeatherCapsuleLayout.SelectMode(168)); + Assert.AreEqual(WeatherCapsuleDisplayMode.Compact, WeatherCapsuleLayout.SelectMode(120)); + Assert.AreEqual(WeatherCapsuleDisplayMode.IconOnly, WeatherCapsuleLayout.SelectMode(40)); + Assert.AreEqual(WeatherCapsuleDisplayMode.Hidden, WeatherCapsuleLayout.SelectMode(39)); + } + + [TestMethod] + public void LargerFontScaleRequiresMoreRoomForTextModes() + { + Assert.AreEqual(WeatherCapsuleDisplayMode.Full, WeatherCapsuleLayout.SelectMode(210, 1)); + Assert.AreEqual(WeatherCapsuleDisplayMode.Compact, WeatherCapsuleLayout.SelectMode(210, 1.5)); + Assert.AreEqual(WeatherCapsuleDisplayMode.IconOnly, WeatherCapsuleLayout.SelectMode(90, 1.5)); + } +} diff --git a/src/YMhut.Box.Tests/YMhut.Box.Tests.csproj b/src/YMhut.Box.Tests/YMhut.Box.Tests.csproj index 2e4a393..bae30e0 100644 --- a/src/YMhut.Box.Tests/YMhut.Box.Tests.csproj +++ b/src/YMhut.Box.Tests/YMhut.Box.Tests.csproj @@ -15,6 +15,7 @@ + diff --git a/src/YMhut.Box.Worker/YMhut.Box.Worker.csproj b/src/YMhut.Box.Worker/YMhut.Box.Worker.csproj index bd334f4..164fccf 100644 --- a/src/YMhut.Box.Worker/YMhut.Box.Worker.csproj +++ b/src/YMhut.Box.Worker/YMhut.Box.Worker.csproj @@ -6,6 +6,7 @@ enable YMhut.Box.Worker YMhut.Box.Worker + ..\box-winUI\Assets\app_icon.ico none diff --git a/src/box-winUI/AgreementWindow.cs b/src/box-winUI/AgreementWindow.cs index 0b58614..ede10fb 100644 --- a/src/box-winUI/AgreementWindow.cs +++ b/src/box-winUI/AgreementWindow.cs @@ -266,7 +266,7 @@ public sealed class AgreementWindow : Window BorderThickness = new Thickness(1), Child = new Image { - Source = new BitmapImage(new Uri("ms-appx:///Assets/icons/app_icon.png")), + Source = AppServices.GetRequiredService().CreateBitmapImage("icons/app_icon.png"), Width = 34, Height = 34, HorizontalAlignment = HorizontalAlignment.Center, diff --git a/src/box-winUI/App.xaml.cs b/src/box-winUI/App.xaml.cs index 0a57940..da3f01b 100644 --- a/src/box-winUI/App.xaml.cs +++ b/src/box-winUI/App.xaml.cs @@ -50,11 +50,13 @@ public partial class App : Application Trace($"OnLaunched:independent-host:{hostOptions.Kind}"); AppServices.Configure( string.IsNullOrWhiteSpace(hostOptions.Root) ? null : hostOptions.Root); + await AppServices.GetRequiredService().EnsureLoadedAsync(); await LaunchIndependentWindowHostAsync(hostOptions); return; } AppServices.Configure(); + await AppServices.GetRequiredService().EnsureLoadedAsync(); CrashLog.Write("Launch started."); var startupInitialization = AppServices.GetRequiredService(); var settingsService = AppServices.GetRequiredService(); diff --git a/src/box-winUI/Assets/LockScreenLogo.png b/src/box-winUI/Assets/LockScreenLogo.png index c0e57c6d0b8ceb4a768a4357b6e2f158b1dbeeaa..9249487cb299623fe5e2eb175e5758adbf0887cc 100644 GIT binary patch delta 2186 zcmV;52zB?;5XTXaReuOvNkl9Fn~8wjBOP2Gqk~4`m(jO*;?9UEyX-WExw33Gg{3Q=4pIv#nY88KzBC!YyC~tK>Wp$QI$epi8oXw@ z*)L{kvBjQBA%8}++mr(!j*;%PaXJ{jd*t(=eYIcQ(!ucU>VUk`W;!4e48yxA#P2BN zLmIep_fmJ^Nm^rH<`=p6Y1#`Y#+c&>2}+E86t=G^bd6(YQOG+gt{Rm8rk{7pToM@G znN@E3k^m(brFD~+_)^8-r#b+agBbE&8rt)6U%Gh7-G3tEMcDxX-{wmTBD{$rKH@k` z1GSV~)5$H7J)*hHi3rjm=RO^Tc`seJ6kM}@{6dN`-oY)m_|gi^BWF;Ee`v1by5>e- zy7(~IQFROdhm3uLFYSmytKu4ir)bS%i+F~La6Uzy#+LS1eQ8%V*w<2se^y*$($D(R z#e>0}9e><%n9R}Hxh2Qo<_@kIrY-iRzO?^|#xl2*XO)w6OO6CG>@Y(aeA<`xKL+1% zT3Hv1I7}PydS5y#48BouO^7FG(4OK;`zW^!chv2pHpZC zMwd~{ztRCzxU{O z>wi?P+a>wWkhraVZ*hNMFQNz&MQ$X4lz}+1?=LicM_@NN6_$q=>xX!=e!p_pOUUr= zD?yQ!v$&_&^DTWR6_-66lZM6bnD!5yGQ@R;A1pmd9}(d+GWdJNEdk$EXoB>HN>H** zs1cps4YpE<`zS(NgC!eTqR}$(g6`D_&3}ovQ;fFb8tsl#mzSQXPiUq$Ir}G>TPCS7 z@zz3P_>ay8l)3{uDZs0ovSiSWvA+`JM!K%h1a_D6d-8X{yPR?s9NBU-7|D{Z(u0Qh zQK4BkdM+8BSvRR8`01_*TBH3jr#$U0_{GfkQz&q9Ykz~u z;L<`9;63{Ac}236{%)t7GHdOt$?&0KYR)pc3rw^9QD3Trc)S=;^9qLO3DdRJ=iuS4&(TwK8-QmPbaH9`PFMTV0yBB3(>?NaRDyFIoor{C(n2&_ zMOVj{oCK#=HqCY1DIMg^8zDA1t*>K7y04O~`564>MWgk$uY^ctvK;7>zVxIBcu)2MKt5<=9=9Vx-d+SoDkLpmUKh=V0lb1j-d#z~S~#Zr zzjMXlfg%&mwlse0OL~Xwo0J116$;=k0cL}AshB4!(`<|b)EvLSm(L2B_42@EEAsn& zN$&{K&p0iueHn9mPk%1J4O&({-pKT<$0F$ntsOhxm!A;HXUgjA z{I8V|cR9hy-6+44@IAWM+X+ei71g*(<`g zC}cTQdtL)4&T8rI-U`1sC7gbr#y=^@y2Ut!cz{g0k<8Q=Da0U!cvyp1-aOBze%UKp z5aeVa#-o+sNPnf|!K5;BX_qK{FO`thasx9PGZ}W?t zUkuKqm>(=&e=k?0(j1N#*_v~o#q8Y{w<%&_bq;&B7Y3{#VkBuz?l?bHO2fhitq#( zK0t=|Yla*1kEw-Kv~CXX$Hp=ezqLP+|94=G zJ=Ons&dAQ*CR|J*uA$IgM=@4VYjXMGeC4dBrlzK*rlzK*W+C}6zr5)QA{;4f00000 MNkvXXt^-0~g89Tz!TCoph1HH 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 AaR2}S delta 4854 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 diff --git a/src/box-winUI/Assets/Square44x44Logo.png b/src/box-winUI/Assets/Square44x44Logo.png index 3a37741b52bb72da55b4435c9de448d496455eb7..c424279908becb05456c243e168d39505ff79a27 100644 GIT binary patch delta 1385 zcmV-v1(y2!3a$%~R)0fDL_t(oN9|Z!XdG1-{_CYii#O^mc%?-xRA0P-ilFF2+ZU}B ztwP&}+DcnDJLk;Iw$(JLU}+T!Qd&wu5FZpDRMZzi5or-E7=u=^URt$50wz_{m?qim zobSm0&(7@3iM=G*O?}u8mTcz#|2hBp&VM^g)I<|aG%@|~aeq0Lu$TfAsf6XEaigp9 z|ACG+Qiy(f&RS}>mY%nkLX;`Q9`bR4tA1wTnH|(=EtRY#pB=6K4Xl;t8hfdLnXcKH zfx;ugXyWL4cF+vS|NLE9OC8pdXSceh(~k~&E-7=EHdLJrFh~kdQURBd8oQHxbkW8t z(}5{dapZdU6@SwUg{OsGU5(jdv?3=j;A#rYG1(03d1iM`KCLMHG?SG1MUI^rRyg3Q z2$bm*XN6^qkUxB#t1>-s+11fwu8Ls2y@-7DNkYaf?{ZZdk0f>zc0KbAk#)6d@S^sV zWgo+&agD3eSa{LO9J_vHiK~)>8n~3S`70C4J6x5Z^q z8bcJK)m3Q>v|Vw^*zK^h#x;t-UP(R%QCJ5IQC-4_&62%)0p*fhigg-`@~s}WfiT7pOtT+5Jui7bsWoGv#G(ud+|W- z#9gO7pEP>KS&mtahg?%q=n|PYjAiL_&wL=KlGgHiLED=tK$Nnp%!_$BzNj&X7jiNl zbbmC4Wuv^Q;@Dj^JA1D<%kO1-9}9A}lZL{sT2`CmQg5@+*pi9I!_;ZdPGvsU$wrd6 zcVpEvpNq51w8FcESB6D0?ct$1PX7bO#1kpihuTEdA`P8LfRaPj~+L;W^x(|-%COZA$ZAE znHZFLUyh4E9^P@qDT<@>C`2W#t)6)^l@&(jkY^vv>1Uy$)w0<*`MOVQkUAkWzD;W^ z-_=eAPDXAZN!#`iHTIW+Zn2wRUGQMPG!DFXJSK69OC{v+wzkjPX z4*Z*ihdxO@b~p*ANkQWyaUf2nO|Ezx6y{Qhqq0f>gJw2Osk#oZ>nj&nJ_H zinJVae1-pm+U&Ki$~Y8pAC)j72`F;}{*h{MB51so=8489u6SZlgR@EF&onGT{7imj z5qUi=G6$=XxfIx~q|Iw&Gs)71g?|)cEM~cC>tlEBx3)H1LE7w02P!7Ui&oWMGFcR( zrD>Ih`EMftba7>s>YP2?GQszri<})EeSWTQYpQe|ADWizh za?D(^61J0hmlx#)mDwkWmqi{yJO{%Wo2`j*>6k^~AX^fHP z`2zhE;zRQBgp8X11!g_KS_*MM988j!oi3r5LbHXI^t8BU^@E2N>3AV-lI#2Ff;Y6m r-bNvoQh;UT=>`=+Q4iWnnNb#~ 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 Eg1d>{wEzGB delta 1488 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 K2vno#`0_vAgPV8& diff --git a/src/box-winUI/Assets/app_icon.ico b/src/box-winUI/Assets/app_icon.ico index 08918bab258fb32f1e3daf7731536136652037dc..ab342b9811c2ba65336c3487347db4ea45da0f0c 100644 GIT binary patch literal 27338 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
    V=Xr5G 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%0DLbFOxa-xC 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 diff --git a/src/box-winUI/Controls/AppTitleBar.cs b/src/box-winUI/Controls/AppTitleBar.cs index 4e7239f..babd22d 100644 --- a/src/box-winUI/Controls/AppTitleBar.cs +++ b/src/box-winUI/Controls/AppTitleBar.cs @@ -2,6 +2,7 @@ using Microsoft.UI.Text; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Automation; using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Media; using Microsoft.UI.Xaml.Media.Imaging; using Windows.UI.Text; using YMhut.Box.WinUI.Services; @@ -53,6 +54,10 @@ internal sealed class AppTitleBar : Grid VerticalAlignment = VerticalAlignment.Center, Children = { WeatherCapsule, CloudButton, QuickSettingsButton, ThemeToggleButton } }; + ActionsPanel.SizeChanged += (_, args) => ActionsPanel.Clip = new RectangleGeometry + { + Rect = new Windows.Foundation.Rect(0, 0, Math.Max(0, args.NewSize.Width), Math.Max(0, args.NewSize.Height)) + }; Grid.SetColumn(ActionsPanel, 2); Children.Add(ActionsPanel); } @@ -103,7 +108,7 @@ internal sealed class AppTitleBar : Grid Background = ModernUi.Transparent, Child = new Image { - Source = new BitmapImage(new Uri("ms-appx:///Assets/icons/app_icon.png")), + Source = AppServices.GetRequiredService().CreateBitmapImage("icons/app_icon.png"), Width = 20, Height = 20, HorizontalAlignment = HorizontalAlignment.Center, diff --git a/src/box-winUI/Controls/RankBadgeFactory.cs b/src/box-winUI/Controls/RankBadgeFactory.cs new file mode 100644 index 0000000..1899c05 --- /dev/null +++ b/src/box-winUI/Controls/RankBadgeFactory.cs @@ -0,0 +1,85 @@ +using Microsoft.UI.Text; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Automation; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Markup; +using Microsoft.UI.Xaml.Media; + +namespace YMhut.Box.WinUI.Controls; + +internal static class RankBadgeFactory +{ + private const string MedalPath = "M12,1 C7.58,1 4,4.58 4,9 C4,11.79 5.43,14.25 7.6,15.68 L6,23 L12,19.8 L18,23 L16.4,15.68 C18.57,14.25 20,11.79 20,9 C20,4.58 16.42,1 12,1 Z"; + + public static FrameworkElement Create(int rank, double size = 32) + { + rank = Math.Max(1, rank); + FrameworkElement element = rank <= 3 ? CreateMedal(rank, size) : CreateNumber(rank, size); + AutomationProperties.SetName(element, AppLocalizer.T($"第 {rank} 名", $"Rank {rank}")); + return element; + } + + private static FrameworkElement CreateMedal(int rank, double size) + { + try + { + var foreground = rank switch + { + 1 => ModernUi.Warning, + 2 => ModernUi.TextSecondary, + _ => ModernUi.Brush("#B87333") + }; + return new Grid + { + Width = size, + Height = size, + Children = + { + new PathIcon + { + Data = (Geometry)XamlBindingHelper.ConvertValue(typeof(Geometry), MedalPath), + Foreground = foreground, + Width = size - 4, + Height = size - 4 + }, + new TextBlock + { + Text = rank.ToString(), + FontSize = Math.Max(9, size * 0.3), + FontWeight = FontWeights.Bold, + Foreground = ModernUi.Surface, + HorizontalAlignment = HorizontalAlignment.Center, + VerticalAlignment = VerticalAlignment.Center, + Margin = new Thickness(0, 0, 0, size * 0.17) + } + } + }; + } + catch + { + return CreateNumber(rank, size); + } + } + + private static FrameworkElement CreateNumber(int rank, double size) + { + return new Border + { + Width = size, + Height = size, + CornerRadius = new CornerRadius(Math.Min(6, size / 4)), + Background = ModernUi.SurfaceAlt, + BorderBrush = ModernUi.Stroke, + BorderThickness = new Thickness(1), + Child = new TextBlock + { + Text = rank.ToString(), + FontSize = Math.Max(10, size * 0.36), + FontWeight = FontWeights.SemiBold, + Foreground = ModernUi.TextSecondary, + HorizontalAlignment = HorizontalAlignment.Center, + VerticalAlignment = VerticalAlignment.Center + } + }; + } +} diff --git a/src/box-winUI/Controls/WeatherCapsuleControl.cs b/src/box-winUI/Controls/WeatherCapsuleControl.cs index b9332aa..d11e566 100644 --- a/src/box-winUI/Controls/WeatherCapsuleControl.cs +++ b/src/box-winUI/Controls/WeatherCapsuleControl.cs @@ -24,6 +24,8 @@ public sealed class WeatherCapsuleControl : UserControl private readonly TextBlock _locationText; private readonly TextBlock _tempText; private readonly TextBlock _conditionText; + private readonly Grid _visual; + private readonly Grid _detailsPanel; private readonly Flyout _flyout; private TitleWeatherSnapshot _snapshot = TitleWeatherSnapshot.Loading; @@ -57,7 +59,7 @@ public sealed class WeatherCapsuleControl : UserControl ConfigureCompactLine(_conditionText, 13); ConfigureCompactLine(_tempText, 18); - var visual = new Grid + _visual = new Grid { ColumnSpacing = 9, VerticalAlignment = VerticalAlignment.Center, @@ -69,8 +71,8 @@ public sealed class WeatherCapsuleControl : UserControl } }; var iconHost = new Grid { Width = 22, Height = 22, Children = { _weatherIcon, _loadingRing } }; - visual.Children.Add(iconHost); - var text = new Grid + _visual.Children.Add(iconHost); + _detailsPanel = new Grid { MinWidth = 76, MaxWidth = 130, @@ -81,13 +83,13 @@ public sealed class WeatherCapsuleControl : UserControl new RowDefinition { Height = GridLength.Auto } } }; - text.Children.Add(_locationText); + _detailsPanel.Children.Add(_locationText); Grid.SetRow(_conditionText, 1); - text.Children.Add(_conditionText); - Grid.SetColumn(text, 1); - visual.Children.Add(text); + _detailsPanel.Children.Add(_conditionText); + Grid.SetColumn(_detailsPanel, 1); + _visual.Children.Add(_detailsPanel); Grid.SetColumn(_tempText, 2); - visual.Children.Add(_tempText); + _visual.Children.Add(_tempText); var flyoutStyle = new Style(typeof(FlyoutPresenter)); flyoutStyle.Setters.Add(new Setter(Control.PaddingProperty, new Thickness(12))); @@ -113,17 +115,66 @@ public sealed class WeatherCapsuleControl : UserControl Background = ModernUi.Surface, BorderBrush = ModernUi.Stroke, BorderThickness = new Thickness(1), - Content = visual, + Content = _visual, Flyout = _flyout }; AutomationProperties.SetName(_button, AppLocalizer.T("天气", "Weather")); ToolTipService.SetToolTip(_button, AppLocalizer.T("查看天气详情", "Show weather details")); Content = _button; + SetDisplayMode(WeatherCapsuleDisplayMode.Full); ApplySnapshot(_snapshot); Loaded += WeatherCapsuleControl_Loaded; Unloaded += WeatherCapsuleControl_Unloaded; } + public WeatherCapsuleDisplayMode DisplayMode { get; private set; } + + public void SetDisplayMode(WeatherCapsuleDisplayMode mode) + { + DisplayMode = mode; + Visibility = mode == WeatherCapsuleDisplayMode.Hidden + ? Visibility.Collapsed + : Visibility.Visible; + + _detailsPanel.Visibility = mode == WeatherCapsuleDisplayMode.Full + ? Visibility.Visible + : Visibility.Collapsed; + _tempText.Visibility = mode is WeatherCapsuleDisplayMode.Full or WeatherCapsuleDisplayMode.Compact + ? Visibility.Visible + : Visibility.Collapsed; + _visual.ColumnSpacing = mode == WeatherCapsuleDisplayMode.Full ? 9 : 7; + _visual.ColumnDefinitions[1].Width = mode == WeatherCapsuleDisplayMode.Full + ? new GridLength(1, GridUnitType.Star) + : new GridLength(0); + _visual.ColumnDefinitions[2].Width = mode is WeatherCapsuleDisplayMode.Full or WeatherCapsuleDisplayMode.Compact + ? GridLength.Auto + : new GridLength(0); + + switch (mode) + { + case WeatherCapsuleDisplayMode.Full: + _button.Width = double.NaN; + _button.MinWidth = 172; + _button.MaxWidth = 248; + _button.Padding = new Thickness(12, 4, 12, 4); + break; + case WeatherCapsuleDisplayMode.Compact: + _button.Width = double.NaN; + _button.MinWidth = 76; + _button.MaxWidth = 108; + _button.Padding = new Thickness(10, 4, 10, 4); + break; + case WeatherCapsuleDisplayMode.IconOnly: + _button.Width = 40; + _button.MinWidth = 40; + _button.MaxWidth = 40; + _button.Padding = new Thickness(8); + break; + case WeatherCapsuleDisplayMode.Hidden: + break; + } + } + public async Task LoadAsync(CancellationToken cancellationToken = default) { await RefreshAsync(cancellationToken).ConfigureAwait(false); diff --git a/src/box-winUI/Controls/WeatherCapsuleDisplayMode.cs b/src/box-winUI/Controls/WeatherCapsuleDisplayMode.cs new file mode 100644 index 0000000..84605e1 --- /dev/null +++ b/src/box-winUI/Controls/WeatherCapsuleDisplayMode.cs @@ -0,0 +1,30 @@ +namespace YMhut.Box.WinUI.Controls; + +public enum WeatherCapsuleDisplayMode +{ + Full, + Compact, + IconOnly, + Hidden +} + +public static class WeatherCapsuleLayout +{ + public static WeatherCapsuleDisplayMode SelectMode(double availableWidth, double fontScale = 1) + { + var scale = Math.Clamp(fontScale, 1, 2); + if (availableWidth >= 168 * scale) + { + return WeatherCapsuleDisplayMode.Full; + } + + if (availableWidth >= 72 * scale) + { + return WeatherCapsuleDisplayMode.Compact; + } + + return availableWidth >= 40 + ? WeatherCapsuleDisplayMode.IconOnly + : WeatherCapsuleDisplayMode.Hidden; + } +} diff --git a/src/box-winUI/MainWindow.xaml.cs b/src/box-winUI/MainWindow.xaml.cs index defcb6f..65af391 100644 --- a/src/box-winUI/MainWindow.xaml.cs +++ b/src/box-winUI/MainWindow.xaml.cs @@ -74,6 +74,7 @@ public sealed partial class MainWindow : Window, IShellNavigationHost private string? _activePluginSurfaceId; private StackPanel? _titleActionsPanel; private WinDispatcherQueueTimer? _responsiveShellTimer; + private WinDispatcherQueueTimer? _moveRecoveryTimer; private WindowMovePerformanceHelper? _movePerformanceHelper; private IDisposable? _moveLightModeScope; private bool _hasResponsiveShellState; @@ -81,6 +82,8 @@ public sealed partial class MainWindow : Window, IShellNavigationHost private bool _lastResponsiveDesktop; private bool _lastResponsivePhone; private double _lastResponsiveWidth; + private double _lastResponsiveFontScale; + private double _lastResponsiveRasterizationScale; private bool _windowMoveLoopActive; private bool _responsiveShellUpdateDeferred; private AppShell? _shell; @@ -144,6 +147,7 @@ public sealed partial class MainWindow : Window, IShellNavigationHost _windowMoveLoopActive = active; if (active) { + _moveRecoveryTimer?.Stop(); _moveLightModeScope ??= _uiPerformanceCoordinator.EnterLightMode("main-window-move"); _responsiveShellTimer?.Stop(); _pageTransitionStoryboard?.Stop(); @@ -151,16 +155,31 @@ public sealed partial class MainWindow : Window, IShellNavigationHost } else { - _moveLightModeScope?.Dispose(); - _moveLightModeScope = null; - if (_responsiveShellUpdateDeferred) + _moveRecoveryTimer ??= CreateOneShotTimer( + TimeSpan.FromMilliseconds(72), + () => + { + if (_windowMoveLoopActive || _isClosed) + { + return; + } + + _moveLightModeScope?.Dispose(); + _moveLightModeScope = null; + ApplyShellTheme(); + if (_responsiveShellUpdateDeferred) + { + _responsiveShellUpdateDeferred = false; + ApplyResponsiveShell(); + } + }); + _moveRecoveryTimer.Stop(); + _moveRecoveryTimer.Start(); + if (!_responsiveShellUpdateDeferred) { - _responsiveShellUpdateDeferred = false; - ScheduleResponsiveShellUpdate(); + _responsiveShellUpdateDeferred = true; } } - - ApplyShellTheme(); }); ToastService.Attach(ToastPresenter); _shellNotificationService.Attach(ToastPresenter); @@ -203,6 +222,7 @@ public sealed partial class MainWindow : Window, IShellNavigationHost _settingsService.PropertyChanged -= _settingsChangedHandler; UnsubscribeSystemVisualEvents(); _glassIntensitySaveDebounce.Stop(); + _moveRecoveryTimer?.Stop(); _globalHotkeyService.Invoked -= GlobalHotkeyService_Invoked; _globalHotkeyService.Dispose(); _desktopOverlayService.Dispose(); @@ -227,6 +247,13 @@ public sealed partial class MainWindow : Window, IShellNavigationHost CrashLog.Write(exception); } }; + RootLayout.Loaded += (_, _) => + { + if (RootLayout.XamlRoot is not null) + { + RootLayout.XamlRoot.Changed += (_, _) => ScheduleResponsiveShellUpdate(); + } + }; StartupTrace.Write("MainWindow.ctor:after-build"); } @@ -2193,6 +2220,7 @@ public sealed partial class MainWindow : Window, IShellNavigationHost { await _settingsService.UpdateAsync(settings => settings.TopBarMaterial = material); ApplyShellTheme(); + ScheduleResponsiveShellUpdate(); RefreshQuickSettingsControls(); } @@ -2317,6 +2345,7 @@ public sealed partial class MainWindow : Window, IShellNavigationHost ? Math.Max(240, Math.Min(desiredQuickSettingsWidth, RootLayout.ActualWidth - 12)) : desiredQuickSettingsWidth; ApplyShellTheme(); + ScheduleResponsiveShellUpdate(); } private void AnimateQuickSettings(bool show) @@ -2490,10 +2519,14 @@ public sealed partial class MainWindow : Window, IShellNavigationHost var wide = width >= 1280; var desktop = width >= 760; var phone = width < 520; + var fontScale = _settingsService.Current.FontSize; + var rasterizationScale = AppTitleBar.XamlRoot?.RasterizationScale ?? 1; var bucketChanged = !_hasResponsiveShellState || wide != _lastResponsiveWide || desktop != _lastResponsiveDesktop || - phone != _lastResponsivePhone; + phone != _lastResponsivePhone || + Math.Abs(fontScale - _lastResponsiveFontScale) >= 0.01 || + Math.Abs(rasterizationScale - _lastResponsiveRasterizationScale) >= 0.01; var widthChangedEnough = !_hasResponsiveShellState || Math.Abs(width - _lastResponsiveWidth) >= 24; @@ -2518,15 +2551,24 @@ public sealed partial class MainWindow : Window, IShellNavigationHost GlobalSearchBox.Visibility = Visibility.Visible; GlobalSearchBox.MaxWidth = Math.Max(180, RootNavigation.OpenPaneLength - 32); - if (WeatherCapsule is not null) - { - WeatherCapsule.Visibility = desktop && width >= 960 ? Visibility.Visible : Visibility.Collapsed; - } if (_titleActionsPanel is not null) { var captionReserve = _windowChromeService.CaptionButtonReservedWidth(this, AppTitleBar.XamlRoot); _shell?.TitleBar.SetCaptionButtonReserve(captionReserve); _titleActionsPanel.Margin = new Thickness(0); + var brandReserve = phone ? 132d : 152d; + var dragReserve = phone ? 36d : 64d; + var availableActionsWidth = Math.Max( + 108, + width - captionReserve - brandReserve - dragReserve - 28); + _titleActionsPanel.MaxWidth = Math.Min(360, availableActionsWidth); + if (WeatherCapsule is not null) + { + const double fixedActionWidth = (32 * 3) + (6 * 3); + var weatherWidth = Math.Max(0, availableActionsWidth - fixedActionWidth); + var mode = WeatherCapsuleLayout.SelectMode(weatherWidth, fontScale); + WeatherCapsule.SetDisplayMode(mode); + } } _hasResponsiveShellState = true; @@ -2534,6 +2576,8 @@ public sealed partial class MainWindow : Window, IShellNavigationHost _lastResponsiveDesktop = desktop; _lastResponsivePhone = phone; _lastResponsiveWidth = width; + _lastResponsiveFontScale = fontScale; + _lastResponsiveRasterizationScale = rasterizationScale; if (bucketChanged) { diff --git a/src/box-winUI/Services/AppServices.cs b/src/box-winUI/Services/AppServices.cs index 09923df..723e222 100644 --- a/src/box-winUI/Services/AppServices.cs +++ b/src/box-winUI/Services/AppServices.cs @@ -44,7 +44,12 @@ public static class AppServices provider.GetRequiredService(), provider.GetService())); services.AddSingleton(); - services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(provider => provider.GetRequiredService()); + services.AddSingleton(provider => provider.GetRequiredService()); + services.AddSingleton(); + services.AddSingleton(provider => provider.GetRequiredService()); + services.AddSingleton(provider => provider.GetRequiredService()); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(provider => new TauriPluginProcessService( @@ -89,6 +94,8 @@ public static class AppServices provider.GetRequiredService(), provider.GetService(), provider.GetRequiredService())); + services.AddSingleton(provider => new PearApiClient( + logService: provider.GetService())); services.AddSingleton(provider => new RemoteMediaCatalogService( provider.GetRequiredService(), provider.GetRequiredService(), @@ -124,6 +131,9 @@ public static class AppServices provider.GetRequiredService(), provider.GetService())); services.AddSingleton(); + services.AddSingleton(provider => new RuntimeAssetService( + provider.GetRequiredService(), + provider.GetService())); services.AddSingleton(provider => new ToolUiDefinitionStore( provider.GetRequiredService(), provider.GetService())); @@ -165,7 +175,7 @@ public static class AppServices provider.GetService(), provider.GetService())); services.AddSingleton(provider => new LocalToolVendorAssetService( - provider.GetRequiredService(), + provider.GetRequiredService(), provider.GetService())); services.AddSingleton(); services.AddSingleton(provider => new ProcessToolWorkerService( diff --git a/src/box-winUI/Services/KillOnCloseJob.cs b/src/box-winUI/Services/KillOnCloseJob.cs new file mode 100644 index 0000000..dd50454 --- /dev/null +++ b/src/box-winUI/Services/KillOnCloseJob.cs @@ -0,0 +1,106 @@ +using System.ComponentModel; +using System.Diagnostics; +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + +namespace YMhut.Box.WinUI.Services; + +internal sealed class KillOnCloseJob : IDisposable +{ + private readonly SafeJobHandle _handle; + + public KillOnCloseJob() + { + _handle = CreateJobObject(nint.Zero, null); + if (_handle.IsInvalid) + { + throw new Win32Exception(Marshal.GetLastWin32Error(), "Unable to create a plugin process Job Object."); + } + var information = new JobObjectExtendedLimitInformation + { + BasicLimitInformation = new JobObjectBasicLimitInformation { LimitFlags = 0x00002000 } + }; + var size = Marshal.SizeOf(); + var pointer = Marshal.AllocHGlobal(size); + try + { + Marshal.StructureToPtr(information, pointer, false); + if (!SetInformationJobObject(_handle, 9, pointer, (uint)size)) + { + throw new Win32Exception(Marshal.GetLastWin32Error(), "Unable to configure a plugin process Job Object."); + } + } + finally + { + Marshal.FreeHGlobal(pointer); + } + } + + public void Add(Process process) + { + if (!AssignProcessToJobObject(_handle, process.Handle)) + { + throw new Win32Exception(Marshal.GetLastWin32Error(), "Unable to assign a plugin process to its Job Object."); + } + } + + public void Dispose() => _handle.Dispose(); + + [StructLayout(LayoutKind.Sequential)] + private struct JobObjectBasicLimitInformation + { + public long PerProcessUserTimeLimit; + public long PerJobUserTimeLimit; + public uint LimitFlags; + public nuint MinimumWorkingSetSize; + public nuint MaximumWorkingSetSize; + public uint ActiveProcessLimit; + public nuint Affinity; + public uint PriorityClass; + public uint SchedulingClass; + } + + [StructLayout(LayoutKind.Sequential)] + private struct IoCounters + { + public ulong ReadOperationCount; + public ulong WriteOperationCount; + public ulong OtherOperationCount; + public ulong ReadTransferCount; + public ulong WriteTransferCount; + public ulong OtherTransferCount; + } + + [StructLayout(LayoutKind.Sequential)] + private struct JobObjectExtendedLimitInformation + { + public JobObjectBasicLimitInformation BasicLimitInformation; + public IoCounters IoInfo; + public nuint ProcessMemoryLimit; + public nuint JobMemoryLimit; + public nuint PeakProcessMemoryUsed; + public nuint PeakJobMemoryUsed; + } + + private sealed class SafeJobHandle : SafeHandleZeroOrMinusOneIsInvalid + { + private SafeJobHandle() : base(true) { } + + protected override bool ReleaseHandle() => CloseHandle(handle); + } + + [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] + private static extern SafeJobHandle CreateJobObject(nint jobAttributes, string? name); + + [DllImport("kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool SetInformationJobObject(SafeJobHandle job, int informationClass, nint information, uint informationLength); + + [DllImport("kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool AssignProcessToJobObject(SafeJobHandle job, nint process); + + [DllImport("kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool CloseHandle(nint handle); +} diff --git a/src/box-winUI/Services/LocalToolVendorAssetService.cs b/src/box-winUI/Services/LocalToolVendorAssetService.cs index 878b41e..65140de 100644 --- a/src/box-winUI/Services/LocalToolVendorAssetService.cs +++ b/src/box-winUI/Services/LocalToolVendorAssetService.cs @@ -1,8 +1,3 @@ -using System.Reflection; -using System.Security.Cryptography; -using System.Text; -using System.Text.Json; -using YMhut.Box.Core.App; using YMhut.Box.Core.Logging; namespace YMhut.Box.WinUI.Services; @@ -36,15 +31,9 @@ public sealed record LocalJsToolRuntimeResult( string Runtime = "csharp-fallback"); public sealed class LocalToolVendorAssetService( - AppPaths paths, + IRuntimeAssetService runtimeAssets, ILogService? logService = null) : ILocalToolVendorAssetService { - private const string ResourcePrefix = "YMhut.Box.WinUI.Assets.tool-results.vendor."; - private static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web) - { - WriteIndented = false - }; - private readonly SemaphoreSlim _gate = new(1, 1); private LocalToolVendorAssetSnapshot? _snapshot; @@ -63,60 +52,21 @@ public sealed class LocalToolVendorAssetService( return _snapshot; } - var assembly = Assembly.GetExecutingAssembly(); - var resources = assembly.GetManifestResourceNames() - .Where(name => name.StartsWith(ResourcePrefix, StringComparison.OrdinalIgnoreCase)) - .OrderBy(name => name, StringComparer.OrdinalIgnoreCase) - .ToArray(); - if (resources.Length == 0) - { - _snapshot = await SnapshotFromContentFolderAsync(cancellationToken).ConfigureAwait(false); - return _snapshot; - } - - var manifestResource = resources.FirstOrDefault(name => name.EndsWith(".manifest.json", StringComparison.OrdinalIgnoreCase)) ?? - resources.FirstOrDefault(name => name.EndsWith("manifest.json", StringComparison.OrdinalIgnoreCase)); - var manifestHash = manifestResource is null - ? HashText(string.Join("|", resources)) - : await HashResourceAsync(assembly, manifestResource, cancellationToken).ConfigureAwait(false); - var cacheRoot = Path.Combine(paths.Cache, "tool-vendor", manifestHash); - Directory.CreateDirectory(cacheRoot); - - var extracted = new List(); - foreach (var resource in resources) - { - cancellationToken.ThrowIfCancellationRequested(); - var relative = ResourceToRelativePath(resource); - if (string.IsNullOrWhiteSpace(relative)) - { - continue; - } - - var target = Path.Combine(cacheRoot, relative); - Directory.CreateDirectory(Path.GetDirectoryName(target)!); - await using var source = assembly.GetManifestResourceStream(resource); - if (source is null) - { - continue; - } - - await using var output = File.Create(target); - await source.CopyToAsync(output, cancellationToken).ConfigureAwait(false); - extracted.Add(target); - } - + var runtime = await runtimeAssets.EnsureLoadedAsync(cancellationToken).ConfigureAwait(false); + var files = runtimeAssets.GetEntries("tool-results/vendor"); + const string manifestPath = "runtime-assets.dat!/tool-results/vendor/manifest.json"; _snapshot = new LocalToolVendorAssetSnapshot( - cacheRoot, - Path.Combine(cacheRoot, "manifest.json"), - manifestHash, - extracted); + "runtime-assets.dat!/tool-results/vendor", + manifestPath, + runtime.PackageHash, + files); if (logService is not null) { await logService.WriteAsync( "Information", "tool-vendor", - "Local JS vendor assets extracted", - $"files={extracted.Count}; hash={manifestHash}", + "Local JS vendor assets verified in authenticated package", + $"files={files.Count}; package={runtime.PackageHash[..12]}", cancellationToken).ConfigureAwait(false); } return _snapshot; @@ -127,41 +77,6 @@ public sealed class LocalToolVendorAssetService( } } - private async Task SnapshotFromContentFolderAsync(CancellationToken cancellationToken) - { - var sourceRoot = Path.Combine(paths.Assets, "tool-results", "vendor"); - var files = Directory.Exists(sourceRoot) - ? Directory.EnumerateFiles(sourceRoot, "*", SearchOption.AllDirectories).OrderBy(path => path, StringComparer.OrdinalIgnoreCase).ToArray() - : []; - var manifest = Path.Combine(sourceRoot, "manifest.json"); - var hash = HashText(string.Join("|", files.Select(Path.GetFileName))); - if (File.Exists(manifest)) - { - await using var manifestStream = File.OpenRead(manifest); - hash = Convert.ToHexString(await SHA256.HashDataAsync(manifestStream, cancellationToken).ConfigureAwait(false)).ToLowerInvariant(); - } - return new LocalToolVendorAssetSnapshot(sourceRoot, manifest, hash, files); - } - - private static string ResourceToRelativePath(string resource) - { - var name = resource[ResourcePrefix.Length..]; - if (name.StartsWith("vendor.", StringComparison.OrdinalIgnoreCase)) - { - name = name["vendor.".Length..]; - } - - return name; - } - - private static async Task HashResourceAsync(Assembly assembly, string resource, CancellationToken cancellationToken) - { - await using var stream = assembly.GetManifestResourceStream(resource) ?? new MemoryStream(); - return Convert.ToHexString(await SHA256.HashDataAsync(stream, cancellationToken).ConfigureAwait(false)).ToLowerInvariant(); - } - - private static string HashText(string value) - => Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(value))).ToLowerInvariant(); } public sealed class LocalJsToolRuntime(ILocalToolVendorAssetService vendorAssets) : ILocalJsToolRuntime diff --git a/src/box-winUI/Services/PluginHostProcessService.cs b/src/box-winUI/Services/PluginHostProcessService.cs index 20179b7..61036a8 100644 --- a/src/box-winUI/Services/PluginHostProcessService.cs +++ b/src/box-winUI/Services/PluginHostProcessService.cs @@ -36,6 +36,8 @@ public interface IPluginHostProcessService : IDisposable void ResetFailedState(); + PluginSnapshot InvalidateSnapshot(string? pluginsRoot = null); + void Stop(); } @@ -64,11 +66,6 @@ public sealed class PluginHostProcessService(ILogService? logService = null) : I public async Task GetSnapshotAsync(CancellationToken cancellationToken = default) { - if (CurrentSnapshot is not null && Status == PluginHostStatus.Failed) - { - return CurrentSnapshot; - } - var response = await SendRequestAsync(new PluginHostMessage(PluginHostProtocol.GetSnapshot), cancellationToken).ConfigureAwait(false); return ApplySnapshot(response.Snapshot); } @@ -173,6 +170,19 @@ public sealed class PluginHostProcessService(ILogService? logService = null) : I SetStatus(PluginHostStatus.Stopped); } + public PluginSnapshot InvalidateSnapshot(string? pluginsRoot = null) + { + var snapshot = new PluginSnapshot( + CurrentSnapshot?.PluginsEnabled ?? true, + string.IsNullOrWhiteSpace(pluginsRoot) ? CurrentSnapshot?.PluginsRoot ?? string.Empty : pluginsRoot, + [], + [], + DateTimeOffset.Now); + CurrentSnapshot = snapshot; + SnapshotChanged?.Invoke(this, snapshot); + return snapshot; + } + public void Dispose() { if (_disposed) diff --git a/src/box-winUI/Services/PluginRuntimeDependencyService.cs b/src/box-winUI/Services/PluginRuntimeDependencyService.cs new file mode 100644 index 0000000..a1cff29 --- /dev/null +++ b/src/box-winUI/Services/PluginRuntimeDependencyService.cs @@ -0,0 +1,55 @@ +using System.Text.Json; +using YMhut.Box.Core.Plugins.Runtime; + +namespace YMhut.Box.WinUI.Services; + +public sealed class PluginRuntimeDependencyService : IPluginRuntimeDependencyService, IPluginToolchainLocator +{ + public Task GetAsync(CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + var root = Path.Combine(AppContext.BaseDirectory, "tauri-host"); + var executable = Path.Combine(root, "ymhut-box-plugin-tauri-host.exe"); + var manifestPath = Path.Combine(root, "runtime.json"); + var templatePath = Path.Combine(root, "template.ymtemplate"); + var templateEntryPath = Path.Combine(root, "template", "dist", "index.html"); + var templateReadmePath = Path.Combine(root, "template", "README.md"); + var hostApiVersion = string.Empty; + var templateVersion = string.Empty; + try + { + if (File.Exists(manifestPath)) + { + using var document = JsonDocument.Parse(File.ReadAllText(manifestPath)); + hostApiVersion = document.RootElement.TryGetProperty("hostApiVersion", out var hostApi) ? hostApi.GetString() ?? string.Empty : string.Empty; + templateVersion = document.RootElement.TryGetProperty("templateVersion", out var template) ? template.GetString() ?? string.Empty : string.Empty; + } + } + catch (JsonException) + { + } + var ready = File.Exists(executable) && File.Exists(manifestPath) && File.Exists(templatePath) && + File.Exists(templateEntryPath) && File.Exists(templateReadmePath) && + !string.IsNullOrWhiteSpace(hostApiVersion) && !string.IsNullOrWhiteSpace(templateVersion); + return Task.FromResult(new PluginRuntimeDependencyInfo( + ready, + executable, + manifestPath, + templatePath, + hostApiVersion, + templateVersion, + ready ? null : "The bundled Tauri host, runtime manifest, or prebuilt template package is missing.")); + } + + public async Task GetBundledToolchainAsync(CancellationToken cancellationToken = default) + { + var dependency = await GetAsync(cancellationToken).ConfigureAwait(false); + return new PluginToolchainInfo( + null, + null, + null, + Path.GetDirectoryName(dependency.HostExecutable), + dependency.IsReady, + dependency.Diagnostic ?? "Prebuilt plugins use the bundled host and do not require Cargo, Node, or npm."); + } +} diff --git a/src/box-winUI/Services/RuntimeAssetService.cs b/src/box-winUI/Services/RuntimeAssetService.cs new file mode 100644 index 0000000..b3aa49a --- /dev/null +++ b/src/box-winUI/Services/RuntimeAssetService.cs @@ -0,0 +1,264 @@ +using System.Security.Cryptography; +using System.Text; +using Microsoft.Web.WebView2.Core; +using Microsoft.UI.Xaml.Media.Imaging; +using Windows.Storage.Streams; +using YMhut.Box.Core.App; +using YMhut.Box.Core.Data; +using YMhut.Box.Core.Logging; + +namespace YMhut.Box.WinUI.Services; + +public interface IRuntimeAssetService +{ + RuntimeAssetSnapshot? Current { get; } + + Task EnsureLoadedAsync(CancellationToken cancellationToken = default); + + void MapWebViewHost(CoreWebView2 webView, string hostName, string assetDirectory); + + IReadOnlyList GetEntries(string relativeDirectory); + + bool TryGetBytes(string relativePath, out byte[] content); + + BitmapImage? CreateBitmapImage(string relativePath); +} + +public sealed record RuntimeAssetSnapshot( + string PackagePath, + string PackageHash, + int EntryCount, + long ExpandedBytes); + +public sealed class RuntimeAssetService( + AppPaths paths, + ILogService? logService = null) : IRuntimeAssetService +{ + private const string PackagePurpose = "runtime-assets"; + private readonly SemaphoreSlim _gate = new(1, 1); + private IReadOnlyDictionary _entries = + new Dictionary(StringComparer.OrdinalIgnoreCase); + + public RuntimeAssetSnapshot? Current { get; private set; } + + public async Task EnsureLoadedAsync(CancellationToken cancellationToken = default) + { + if (Current is not null) + { + return Current; + } + + await _gate.WaitAsync(cancellationToken).ConfigureAwait(false); + try + { + if (Current is not null) + { + return Current; + } + + var packagePath = ResolvePackagePath(); + if (packagePath is null) + { + throw new FileNotFoundException("随包静态资源包缺失,请使用官方安装包重新安装。", "Assets/runtime-assets.dat"); + } + + var package = await File.ReadAllBytesAsync(packagePath, cancellationToken).ConfigureAwait(false); + IReadOnlyList verified; + try + { + verified = AuthenticatedAssetPackage.ReadVerifiedEntries(package, PackagePurpose, cancellationToken); + } + catch (Exception exception) when (exception is InvalidDataException or CryptographicException) + { + throw new InvalidDataException("随包静态资源包校验失败,应用已拒绝加载可能被替换的页面或图片,请重新安装。", exception); + } + + _entries = verified.ToDictionary( + entry => entry.Path, + entry => new RuntimeAssetEntry(entry.Content, ContentTypeFor(entry.Path), entry.Sha256), + StringComparer.OrdinalIgnoreCase); + var hash = Convert.ToHexString(SHA256.HashData(package)).ToLowerInvariant(); + Current = new RuntimeAssetSnapshot( + packagePath, + hash, + _entries.Count, + _entries.Values.Sum(entry => (long)entry.Content.Length)); + if (logService is not null) + { + await logService.WriteAsync( + "Information", + "runtime-assets", + "Authenticated runtime assets loaded", + $"entries={Current.EntryCount}; bytes={Current.ExpandedBytes}; package={hash[..12]}", + cancellationToken).ConfigureAwait(false); + } + + return Current; + } + finally + { + _gate.Release(); + } + } + + public void MapWebViewHost(CoreWebView2 webView, string hostName, string assetDirectory) + { + ArgumentNullException.ThrowIfNull(webView); + if (Current is null) + { + throw new InvalidOperationException("Authenticated runtime assets have not been loaded."); + } + + var normalizedHost = hostName.Trim().ToLowerInvariant(); + if (string.IsNullOrWhiteSpace(normalizedHost) || normalizedHost.Contains('/') || normalizedHost.Contains('\\')) + { + throw new ArgumentException("Invalid WebView asset host name.", nameof(hostName)); + } + + var directory = NormalizePrefix(assetDirectory); + webView.AddWebResourceRequestedFilter($"https://{normalizedHost}/*", CoreWebView2WebResourceContext.All); + webView.WebResourceRequested += (_, args) => + { + if (!Uri.TryCreate(args.Request.Uri, UriKind.Absolute, out var uri) || + !string.Equals(uri.Scheme, Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase) || + !string.Equals(uri.Host, normalizedHost, StringComparison.OrdinalIgnoreCase)) + { + return; + } + + var requestPath = Uri.UnescapeDataString(uri.AbsolutePath).TrimStart('/'); + string entryPath; + try + { + entryPath = AuthenticatedAssetPackage.NormalizeEntryPath(directory + requestPath); + } + catch (InvalidDataException) + { + args.Response = CreateResponse(webView, Array.Empty(), 400, "Bad Request", "text/plain; charset=utf-8"); + return; + } + + if (!_entries.TryGetValue(entryPath, out var entry)) + { + args.Response = CreateResponse(webView, Encoding.UTF8.GetBytes("Not found"), 404, "Not Found", "text/plain; charset=utf-8"); + return; + } + + args.Response = CreateResponse(webView, entry.Content, 200, "OK", entry.ContentType); + }; + } + + public IReadOnlyList GetEntries(string relativeDirectory) + { + var prefix = NormalizePrefix(relativeDirectory); + return _entries.Keys + .Where(path => path.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) + .Order(StringComparer.OrdinalIgnoreCase) + .ToArray(); + } + + public bool TryGetBytes(string relativePath, out byte[] content) + { + try + { + var normalized = AuthenticatedAssetPackage.NormalizeEntryPath(relativePath); + if (_entries.TryGetValue(normalized, out var entry)) + { + content = entry.Content; + return true; + } + } + catch (InvalidDataException) + { + } + + content = []; + return false; + } + + public BitmapImage? CreateBitmapImage(string relativePath) + { + if (!TryGetBytes(relativePath, out var content)) + { + return null; + } + + var stream = CreateStream(content); + var image = new BitmapImage(); + image.SetSource(stream); + stream.Dispose(); + return image; + } + + private string? ResolvePackagePath() + { + foreach (var candidate in new[] + { + Path.Combine(AppContext.BaseDirectory, "Assets", "runtime-assets.dat"), + Path.Combine(paths.Assets, "runtime-assets.dat") + }.Distinct(StringComparer.OrdinalIgnoreCase)) + { + if (File.Exists(candidate)) + { + return candidate; + } + } + + return null; + } + + private static CoreWebView2WebResourceResponse CreateResponse( + CoreWebView2 webView, + byte[] content, + int status, + string reason, + string contentType) + { + var headers = $"Content-Type: {contentType}\r\nContent-Length: {content.Length}\r\nCache-Control: no-store\r\nX-Content-Type-Options: nosniff"; + var stream = CreateStream(content); + return webView.Environment.CreateWebResourceResponse(stream, status, reason, headers); + } + + private static InMemoryRandomAccessStream CreateStream(byte[] content) + { + var stream = new InMemoryRandomAccessStream(); + using (var writer = new DataWriter(stream)) + { + writer.WriteBytes(content); + writer.StoreAsync().AsTask().GetAwaiter().GetResult(); + writer.DetachStream(); + } + stream.Seek(0); + return stream; + } + + private static string NormalizePrefix(string value) + { + var normalized = AuthenticatedAssetPackage.NormalizeEntryPath(value.TrimEnd('/', '\\')); + return normalized + "/"; + } + + private static string ContentTypeFor(string path) + => Path.GetExtension(path).ToLowerInvariant() switch + { + ".html" => "text/html; charset=utf-8", + ".css" => "text/css; charset=utf-8", + ".js" or ".mjs" => "text/javascript; charset=utf-8", + ".json" => "application/json; charset=utf-8", + ".svg" => "image/svg+xml", + ".png" => "image/png", + ".jpg" or ".jpeg" => "image/jpeg", + ".gif" => "image/gif", + ".ico" => "image/x-icon", + ".wasm" => "application/wasm", + ".glb" => "model/gltf-binary", + ".gltf" => "model/gltf+json", + ".woff" => "font/woff", + ".woff2" => "font/woff2", + ".ttf" => "font/ttf", + ".otf" => "font/otf", + _ => "application/octet-stream" + }; + + private sealed record RuntimeAssetEntry(byte[] Content, string ContentType, string Sha256); +} diff --git a/src/box-winUI/Services/StartupInitializationService.cs b/src/box-winUI/Services/StartupInitializationService.cs index ca9a89a..c607bdc 100644 --- a/src/box-winUI/Services/StartupInitializationService.cs +++ b/src/box-winUI/Services/StartupInitializationService.cs @@ -175,7 +175,8 @@ public sealed class StartupInitializationService( "data/sanguosha/十周年皮肤配置对应关系.xlsx"); context.Report(0.72, T("正在准备本地 JS 工具库缓存...", "Preparing local JS tool vendor cache...")); var vendor = await localToolVendorAssets.EnsureExtractedAsync(token).ConfigureAwait(false); - var vendorHealthy = vendor.Files.Count > 0 && File.Exists(vendor.ManifestPath); + var vendorHealthy = vendor.Files.Count > 0 && + vendor.Files.Any(path => path.EndsWith("/manifest.json", StringComparison.OrdinalIgnoreCase)); context.Report( 1, validation.IsHealthy && vendorHealthy diff --git a/src/box-winUI/Services/TauriPluginProcessService.cs b/src/box-winUI/Services/TauriPluginProcessService.cs index 90dee6c..350cdf5 100644 --- a/src/box-winUI/Services/TauriPluginProcessService.cs +++ b/src/box-winUI/Services/TauriPluginProcessService.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.IO.Pipes; using System.Text; using System.Text.Json; +using System.Security.Cryptography; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Windows.ApplicationModel.DataTransfer; @@ -409,6 +410,8 @@ public sealed class TauriPluginProcessService( plugin.Manifest.PermissionReasons, plugin.Manifest.Network, plugin.Manifest.Requirements, + plugin.Manifest.Tauri, + plugin.Manifest.ToolBindings, state.Enabled, Granted = state.GrantedPermissions.OrderBy(value => value).ToArray(), Fingerprints = state.PermissionPolicyFingerprints?.OrderBy(value => value.Key).ToArray(), @@ -527,7 +530,9 @@ public sealed class TauriPluginProcessService( if (response.UiAction is not null) { handled = true; - value = await ExecuteUiActionAsync(broker, response.UiAction, payload).ConfigureAwait(false); + value = response.UiAction == "externalTool.launch" + ? await LaunchBoundToolAsync(broker, payload).ConfigureAwait(false) + : await ExecuteUiActionAsync(broker, response.UiAction, payload).ConfigureAwait(false); } else if (request.Method is "output.set" or "output.append" or "output.clear") { @@ -568,6 +573,137 @@ public sealed class TauriPluginProcessService( }); } + private async Task LaunchBoundToolAsync(ExternalRuntimeBroker broker, JsonElement payload) + { + if (!settingsService.Current.PluginDeveloperMode) + { + throw new UnauthorizedAccessException("Native plugin tools require developer mode."); + } + var snapshot = await pluginHost.GetSnapshotAsync(broker.Cancellation.Token).ConfigureAwait(false); + var plugin = snapshot.Plugins.FirstOrDefault(candidate => + string.Equals(candidate.Manifest.Id, broker.PluginId, StringComparison.OrdinalIgnoreCase))?.ToLoadedPlugin() + ?? throw new InvalidOperationException("The plugin is no longer installed."); + if (!plugin.IsValid || !plugin.State.Enabled || + !PluginPermissionPolicy.IsGrantCurrent(plugin.Manifest, plugin.State, PluginPermission.ExternalRuntime) || + !PluginPermissionPolicy.IsGrantCurrent(plugin.Manifest, plugin.State, PluginPermission.ExternalTool) || + !string.Equals(plugin.State.ExternalRuntimeConfirmation, plugin.Manifest.Version, StringComparison.Ordinal)) + { + throw new UnauthorizedAccessException("The native plugin tool permission or version confirmation is not current."); + } + if (PluginRegistryService.ValidatePackage(plugin.Manifest, plugin.RootPath).Count > 0) + { + throw new InvalidDataException("The plugin package changed after it was approved."); + } + + var bindingId = ReadString(payload, "bindingId") ?? string.Empty; + var binding = (plugin.Manifest.ToolBindings ?? []).FirstOrDefault(candidate => + string.Equals(candidate.Id, bindingId, StringComparison.OrdinalIgnoreCase)) + ?? throw new InvalidOperationException("The requested native tool binding is not declared."); + var supplied = new Dictionary(StringComparer.OrdinalIgnoreCase); + if (payload.ValueKind == JsonValueKind.Object && payload.TryGetProperty("arguments", out var values) && values.ValueKind == JsonValueKind.Object) + { + foreach (var property in values.EnumerateObject()) + { + supplied[property.Name] = property.Value.ValueKind == JsonValueKind.String + ? property.Value.GetString() ?? string.Empty + : property.Value.ToString(); + } + } + var validated = ValidateBindingArguments(plugin.RootPath, binding, supplied); + var executable = Path.GetFullPath(Path.Combine(plugin.RootPath, binding.Executable)); + var workingDirectory = Path.GetFullPath(Path.Combine(plugin.RootPath, binding.WorkingDirectory)); + var startInfo = new ProcessStartInfo + { + FileName = executable, + WorkingDirectory = workingDirectory, + UseShellExecute = false, + CreateNoWindow = false + }; + foreach (var template in binding.Arguments ?? []) + { + var argument = template; + foreach (var value in validated) + { + argument = argument.Replace($"{{{value.Key}}}", value.Value, StringComparison.OrdinalIgnoreCase); + } + startInfo.ArgumentList.Add(argument); + } + var process = Process.Start(startInfo) ?? throw new InvalidOperationException("The declared native tool could not be started."); + try + { + broker.ToolJob.Add(process); + } + catch + { + try { process.Kill(entireProcessTree: true); } catch { } + process.Dispose(); + throw; + } + process.EnableRaisingEvents = true; + process.Exited += (_, _) => process.Dispose(); + if (binding.TimeoutMs > 0) + { + _ = Task.Run(async () => + { + try + { + await Task.Delay(binding.TimeoutMs, broker.Cancellation.Token).ConfigureAwait(false); + if (!process.HasExited) process.Kill(entireProcessTree: true); + } + catch + { + } + }); + } + await WriteLogAsync("Information", plugin.Manifest.Id, "Declared plugin tool started", $"binding={binding.Id}; pid={process.Id}", broker.Cancellation.Token).ConfigureAwait(false); + return new { bindingId = binding.Id, processId = process.Id }; + } + + private static IReadOnlyDictionary ValidateBindingArguments( + string pluginRoot, + PluginToolBindingSpec binding, + IReadOnlyDictionary supplied) + { + var result = new Dictionary(StringComparer.OrdinalIgnoreCase); + foreach (var parameter in binding.Parameters ?? []) + { + supplied.TryGetValue(parameter.Name, out var value); + value ??= string.Empty; + if (parameter.Required && string.IsNullOrWhiteSpace(value)) + { + throw new InvalidDataException($"A required native tool parameter is missing: {parameter.Name}"); + } + if (value.Length > parameter.MaxLength || value.Contains('\0') || value.Contains('\r') || value.Contains('\n')) + { + throw new InvalidDataException($"A native tool parameter is invalid: {parameter.Name}"); + } + switch (parameter.Kind) + { + case PluginToolArgumentKind.Integer when value.Length > 0 && !long.TryParse(value, out _): + throw new InvalidDataException($"A native tool integer parameter is invalid: {parameter.Name}"); + case PluginToolArgumentKind.Boolean when value.Length > 0 && !bool.TryParse(value, out _): + throw new InvalidDataException($"A native tool boolean parameter is invalid: {parameter.Name}"); + case PluginToolArgumentKind.Choice when value.Length > 0 && + !(parameter.Choices ?? []).Contains(value, StringComparer.OrdinalIgnoreCase): + throw new InvalidDataException($"A native tool choice parameter is outside its allowlist: {parameter.Name}"); + case PluginToolArgumentKind.FilePath when value.Length > 0: + var path = Path.GetFullPath(Path.Combine(pluginRoot, value)); + if (!PluginRegistryService.IsInside(pluginRoot, path) || !File.Exists(path)) + { + throw new InvalidDataException($"A native tool file parameter must resolve to an existing plugin file: {parameter.Name}"); + } + value = path; + break; + } + result[parameter.Name] = value; + } + if (supplied.Keys.Any(key => !result.ContainsKey(key))) + { + throw new InvalidDataException("The native tool request contains an undeclared parameter."); + } + return result; + } + private object UpdateExternalOutput(string sessionId, string method, JsonElement payload) { if (method == "output.clear") @@ -756,6 +892,7 @@ public sealed class TauriPluginProcessService( broker.Reader?.Dispose(); broker.Writer?.Dispose(); broker.Pipe.Dispose(); + broker.ToolJob.Dispose(); } catch { @@ -825,6 +962,7 @@ public sealed class TauriPluginProcessService( public NamedPipeServerStream Pipe { get; } = pipe; public CancellationTokenSource Cancellation { get; } = new(); public SemaphoreSlim WriteGate { get; } = new(1, 1); + public KillOnCloseJob ToolJob { get; } = new(); public StreamReader? Reader { get; set; } public StreamWriter? Writer { get; set; } public Task? LoopTask { get; set; } diff --git a/src/box-winUI/Services/WindowIconService.cs b/src/box-winUI/Services/WindowIconService.cs index e4fedcd..5ede2e4 100644 --- a/src/box-winUI/Services/WindowIconService.cs +++ b/src/box-winUI/Services/WindowIconService.cs @@ -1,30 +1,69 @@ -using Microsoft.UI; -using Microsoft.UI.Windowing; using Microsoft.UI.Xaml; +using System.Drawing; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using WinRT.Interop; namespace YMhut.Box.WinUI.Services; public static class WindowIconService { + private const string IconResourceName = "YMhut.Box.WinUI.Assets.app_icon.ico"; + private const uint WmSetIcon = 0x0080; + private const int IconSmall = 0; + private const int IconBig = 1; + private const int SmCxIcon = 11; + private const int SmCyIcon = 12; + private const int SmCxSmIcon = 49; + private const int SmCySmIcon = 50; + private static readonly ConditionalWeakTable ActiveIcons = new(); + public static void ApplyAppIcon(Window? window) { - if (window is null) + if (window is null || ActiveIcons.TryGetValue(window, out _)) { return; } try { - var iconPath = ResolveIconPath(); - if (iconPath is null) + var hwnd = WindowNative.GetWindowHandle(window); + if (hwnd == 0) { return; } - var hwnd = WindowNative.GetWindowHandle(window); - var id = Win32Interop.GetWindowIdFromWindow(hwnd); - AppWindow.GetFromWindowId(id).SetIcon(iconPath); + var dpi = GetDpiForWindow(hwnd); + if (dpi == 0) + { + dpi = 96; + } + var small = LoadIcon( + Math.Max(16, GetSystemMetricsForDpi(SmCxSmIcon, dpi)), + Math.Max(16, GetSystemMetricsForDpi(SmCySmIcon, dpi))); + var large = LoadIcon( + Math.Max(32, GetSystemMetricsForDpi(SmCxIcon, dpi)), + Math.Max(32, GetSystemMetricsForDpi(SmCyIcon, dpi))); + if (small is null || large is null) + { + small?.Dispose(); + large?.Dispose(); + return; + } + + var icons = new WindowIcons(small, large); + ActiveIcons.Add(window, icons); + SendMessage(hwnd, WmSetIcon, (nint)IconSmall, small.Handle); + SendMessage(hwnd, WmSetIcon, (nint)IconBig, large.Handle); + window.Closed += (_, _) => + { + if (ActiveIcons.TryGetValue(window, out var current)) + { + ActiveIcons.Remove(window); + current.Dispose(); + } + }; } catch (Exception exception) { @@ -32,21 +71,33 @@ public static class WindowIconService } } - public static string? ResolveIconPath() + private static Icon? LoadIcon(int width, int height) { - foreach (var path in new[] + using var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(IconResourceName); + if (stream is null) { - Path.Combine(AppContext.BaseDirectory, "Assets", "app_icon.ico"), - Path.Combine(AppContext.BaseDirectory, "Assets", "icons", "app_icon.ico"), - Path.Combine(AppContext.BaseDirectory, "app_icon.ico") - }) - { - if (File.Exists(path)) - { - return path; - } + return null; } - return null; + using var source = new Icon(stream, width, height); + return (Icon)source.Clone(); } + + private sealed class WindowIcons(Icon small, Icon large) : IDisposable + { + public void Dispose() + { + small.Dispose(); + large.Dispose(); + } + } + + [DllImport("user32.dll")] + private static extern uint GetDpiForWindow(nint hwnd); + + [DllImport("user32.dll")] + private static extern int GetSystemMetricsForDpi(int index, uint dpi); + + [DllImport("user32.dll", EntryPoint = "SendMessageW")] + private static extern nint SendMessage(nint hwnd, uint message, nint wParam, nint lParam); } diff --git a/src/box-winUI/Services/WindowMovePerformanceHelper.cs b/src/box-winUI/Services/WindowMovePerformanceHelper.cs index 22c4d60..d613f8f 100644 --- a/src/box-winUI/Services/WindowMovePerformanceHelper.cs +++ b/src/box-winUI/Services/WindowMovePerformanceHelper.cs @@ -1,4 +1,5 @@ using System.Runtime.InteropServices; +using Microsoft.UI.Dispatching; using Microsoft.UI.Xaml; using WinRT.Interop; @@ -15,12 +16,16 @@ public sealed class WindowMovePerformanceHelper : IDisposable private readonly Window _window; private readonly Func _backdropProvider; private readonly Action? _moveStateChanged; + private readonly DispatcherQueue _dispatcherQueue; + private readonly DispatcherQueueTimer _restoreTimer; private readonly SubclassProc _subclassProc; private readonly nuint _subclassId; private readonly nint _hwnd; private bool _subclassInstalled; private bool _disposed; private bool _inMoveLoop; + private int _nativeMoveState; + private int _dispatchQueued; private WindowMovePerformanceHelper( Window window, @@ -30,6 +35,11 @@ public sealed class WindowMovePerformanceHelper : IDisposable _window = window; _backdropProvider = backdropProvider ?? (() => "mica"); _moveStateChanged = moveStateChanged; + _dispatcherQueue = window.DispatcherQueue; + _restoreTimer = _dispatcherQueue.CreateTimer(); + _restoreTimer.Interval = TimeSpan.FromMilliseconds(120); + _restoreTimer.IsRepeating = false; + _restoreTimer.Tick += RestoreTimer_Tick; _subclassProc = WindowSubclassProc; _subclassId = (nuint)Interlocked.Increment(ref s_nextSubclassId); _hwnd = WindowNative.GetWindowHandle(window); @@ -59,9 +69,12 @@ public sealed class WindowMovePerformanceHelper : IDisposable _disposed = true; _window.Closed -= Window_Closed; + _restoreTimer.Stop(); + _restoreTimer.Tick -= RestoreTimer_Tick; if (_inMoveLoop) { - EndMoveLoop(); + _inMoveLoop = false; + _moveStateChanged?.Invoke(false); } if (_subclassInstalled && _hwnd != 0) @@ -78,13 +91,13 @@ public sealed class WindowMovePerformanceHelper : IDisposable switch (msg) { case WmEnterSizeMove: - BeginMoveLoop(); + QueueMoveState(active: true); break; case WmExitSizeMove: - EndMoveLoop(); + QueueMoveState(active: false); break; case WmNcDestroy: - Dispose(); + _dispatcherQueue.TryEnqueue(Dispose); break; } } @@ -96,13 +109,47 @@ public sealed class WindowMovePerformanceHelper : IDisposable return DefSubclassProc(hwnd, msg, wParam, lParam); } - private void BeginMoveLoop() + private void QueueMoveState(bool active) { - if (_disposed || _inMoveLoop) + Volatile.Write(ref _nativeMoveState, active ? 1 : 0); + if (Interlocked.Exchange(ref _dispatchQueued, 1) != 0) { return; } + if (!_dispatcherQueue.TryEnqueue(ApplyQueuedMoveState)) + { + Interlocked.Exchange(ref _dispatchQueued, 0); + } + } + + private void ApplyQueuedMoveState() + { + Interlocked.Exchange(ref _dispatchQueued, 0); + if (_disposed) + { + return; + } + + if (Volatile.Read(ref _nativeMoveState) != 0) + { + BeginMoveLoop(); + } + else + { + ScheduleEndMoveLoop(); + } + } + + private void BeginMoveLoop() + { + if (_disposed || _inMoveLoop) + { + _restoreTimer.Stop(); + return; + } + + _restoreTimer.Stop(); _inMoveLoop = true; _moveStateChanged?.Invoke(true); if (UsesCompositionBackdrop(_backdropProvider())) @@ -111,9 +158,21 @@ public sealed class WindowMovePerformanceHelper : IDisposable } } - private void EndMoveLoop() + private void ScheduleEndMoveLoop() { - if (!_inMoveLoop) + if (_disposed || !_inMoveLoop) + { + return; + } + + _restoreTimer.Stop(); + _restoreTimer.Start(); + } + + private void RestoreTimer_Tick(DispatcherQueueTimer sender, object args) + { + sender.Stop(); + if (_disposed || !_inMoveLoop || Volatile.Read(ref _nativeMoveState) != 0) { return; } diff --git a/src/box-winUI/Services/WindowsTrayService.cs b/src/box-winUI/Services/WindowsTrayService.cs index 621252b..751f3fb 100644 --- a/src/box-winUI/Services/WindowsTrayService.cs +++ b/src/box-winUI/Services/WindowsTrayService.cs @@ -1,4 +1,5 @@ using System.Drawing; +using System.Reflection; using System.Runtime.InteropServices; using Microsoft.UI; using Microsoft.UI.Dispatching; @@ -10,6 +11,7 @@ namespace YMhut.Box.WinUI.Services; public sealed class WindowsTrayService : ITrayService { + private const string IconResourceName = "YMhut.Box.WinUI.Assets.app_icon.ico"; private const int GwlWndProc = -4; private const uint NifMessage = 0x00000001; private const uint NifIcon = 0x00000002; @@ -194,20 +196,23 @@ public sealed class WindowsTrayService : ITrayService } } - private static Icon LoadIcon() + private Icon LoadIcon() { - foreach (var path in new[] + try { - Path.Combine(AppContext.BaseDirectory, "Assets", "app_icon.ico"), - Path.Combine(AppContext.BaseDirectory, "Assets", "icons", "app_icon.ico"), - Path.Combine(AppContext.BaseDirectory, "app_icon.ico") - }) - { - if (File.Exists(path)) + using var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(IconResourceName); + if (stream is not null) { - return new Icon(path); + var dpi = _hwnd == 0 ? 96u : GetDpiForWindow(_hwnd); + var size = Math.Max(16, GetSystemMetricsForDpi(49, dpi == 0 ? 96u : dpi)); + using var icon = new Icon(stream, size, size); + return (Icon)icon.Clone(); } } + catch (Exception exception) + { + CrashLog.Write(exception); + } return (Icon)SystemIcons.Application.Clone(); } @@ -291,4 +296,10 @@ public sealed class WindowsTrayService : ITrayService [DllImport("user32.dll", SetLastError = true)] private static extern bool PostMessage(nint hWnd, uint msg, nint wParam, nint lParam); + + [DllImport("user32.dll")] + private static extern uint GetDpiForWindow(nint hwnd); + + [DllImport("user32.dll")] + private static extern int GetSystemMetricsForDpi(int index, uint dpi); } diff --git a/src/box-winUI/StartupSplashWindow.cs b/src/box-winUI/StartupSplashWindow.cs index 0370d55..5ec22a6 100644 --- a/src/box-winUI/StartupSplashWindow.cs +++ b/src/box-winUI/StartupSplashWindow.cs @@ -27,6 +27,7 @@ public sealed class StartupSplashWindow : Window private const string SplashHostName = "startup-splash.ymhut.local"; private readonly WebView2EnvironmentFactory _webViewEnvironmentFactory = AppServices.GetRequiredService(); + private readonly IRuntimeAssetService _runtimeAssets = AppServices.GetRequiredService(); private readonly ISettingsService _settingsService = AppServices.GetRequiredService(); private readonly WindowChromeService _windowChromeService = AppServices.GetRequiredService(); private readonly WebView2 _webView = new() @@ -203,7 +204,7 @@ public sealed class StartupSplashWindow : Window BorderThickness = new Thickness(1), Child = new Image { - Source = new BitmapImage(new Uri("ms-appx:///Assets/icons/app_icon.png")), + Source = _runtimeAssets.CreateBitmapImage("icons/app_icon.png"), Width = 34, Height = 34, HorizontalAlignment = HorizontalAlignment.Center, @@ -312,13 +313,6 @@ public sealed class StartupSplashWindow : Window _webInitializationStarted = true; try { - var resourceFolder = Path.Combine(AppContext.BaseDirectory, "Assets", "startup-splash"); - if (!Directory.Exists(resourceFolder)) - { - ActivateNativeFallback(); - return; - } - var environment = await _webViewEnvironmentFactory.CreateAsync("StartupSplash").ConfigureAwait(true); await _webView.EnsureCoreWebView2Async(environment); _webView.DefaultBackgroundColor = Windows.UI.Color.FromArgb(0, 0, 0, 0); @@ -328,10 +322,7 @@ public sealed class StartupSplashWindow : Window _webView.CoreWebView2.Settings.IsStatusBarEnabled = false; _webView.CoreWebView2.Settings.IsZoomControlEnabled = false; _webView.CoreWebView2.WebMessageReceived += WebView_WebMessageReceived; - _webView.CoreWebView2.SetVirtualHostNameToFolderMapping( - SplashHostName, - resourceFolder, - CoreWebView2HostResourceAccessKind.Allow); + _runtimeAssets.MapWebViewHost(_webView.CoreWebView2, SplashHostName, "startup-splash"); _webView.Source = new Uri($"https://{SplashHostName}/index.html"); } catch (Exception exception) diff --git a/src/box-winUI/ViewModels/ToolCardViewModel.cs b/src/box-winUI/ViewModels/ToolCardViewModel.cs index 631a79a..92d8f3f 100644 --- a/src/box-winUI/ViewModels/ToolCardViewModel.cs +++ b/src/box-winUI/ViewModels/ToolCardViewModel.cs @@ -43,13 +43,15 @@ public sealed class ToolCardViewModel : INotifyPropertyChanged public string CapabilityLabel => AppLocalizer.Capability(Metadata.OfflineCapable); - public string SourceLabel => Module switch - { - ExternalToolModule => AppLocalizer.T("外部工具", "External"), - BuiltinReferenceToolModule => AppLocalizer.T("YMhut 内置", "YMhut built-in"), - PluginToolModule => AppLocalizer.T("插件工具", "Plugin"), - _ => AppLocalizer.T("原生工具", "Native") - }; + public string SourceLabel => !string.IsNullOrWhiteSpace(Metadata.Provider) + ? Metadata.Provider + : Module switch + { + ExternalToolModule => AppLocalizer.T("外部工具", "External"), + BuiltinReferenceToolModule => AppLocalizer.T("YMhut 内置", "YMhut built-in"), + PluginToolModule => AppLocalizer.T("插件工具", "Plugin"), + _ => AppLocalizer.T("原生工具", "Native") + }; public string SafetyLabel => Module switch { diff --git a/src/box-winUI/ViewModels/Tools/PearApiToolViewModel.cs b/src/box-winUI/ViewModels/Tools/PearApiToolViewModel.cs new file mode 100644 index 0000000..1d52b9c --- /dev/null +++ b/src/box-winUI/ViewModels/Tools/PearApiToolViewModel.cs @@ -0,0 +1,14 @@ +using YMhut.Box.Core.Api; +using YMhut.Box.Core.Tools; + +namespace YMhut.Box.WinUI.ViewModels.Tools; + +public abstract class PearApiToolViewModel(IToolModule module, PearApiToolDefinition definition) + : AdaptiveToolViewModel(module) +{ + public PearApiToolDefinition Definition { get; } = definition; + + public Dictionary Values { get; } = new(StringComparer.OrdinalIgnoreCase); + + public string? SelectedFilePath { get; set; } +} diff --git a/src/box-winUI/Views/AboutPage.cs b/src/box-winUI/Views/AboutPage.cs index 37235ba..f5e31d3 100644 --- a/src/box-winUI/Views/AboutPage.cs +++ b/src/box-winUI/Views/AboutPage.cs @@ -18,6 +18,7 @@ namespace YMhut.Box.WinUI.Views; public sealed class AboutPage : Page { private readonly IAppVersionService _versionService = AppServices.GetRequiredService(); + private readonly IRuntimeAssetService _runtimeAssets = AppServices.GetRequiredService(); private readonly IAppInstallerUpdateService _updateService = AppServices.GetRequiredService(); private readonly IOpenSourceReferenceService _referenceService = AppServices.GetRequiredService(); private readonly ISettingsService _settingsService = AppServices.GetRequiredService(); @@ -169,7 +170,7 @@ public sealed class AboutPage : Page Background = ModernUi.Transparent, Child = new Image { - Source = new BitmapImage(new Uri("ms-appx:///Assets/icons/app_icon.png")), + Source = _runtimeAssets.CreateBitmapImage("icons/app_icon.png"), Width = 48, Height = 48 } @@ -207,7 +208,7 @@ public sealed class AboutPage : Page { new Image { - Source = new BitmapImage(new Uri("ms-appx:///Assets/images/author_avatar.png")), + Source = _runtimeAssets.CreateBitmapImage("images/author_avatar.png"), Width = 48, Height = 48 }, @@ -240,13 +241,7 @@ public sealed class AboutPage : Page Children = { _updateProgress, - new Image - { - Source = new SvgImageSource(new Uri("ms-appx:///Assets/download.svg")), - Width = 18, - Height = 18, - Stretch = Microsoft.UI.Xaml.Media.Stretch.Uniform - }, + new SymbolIcon { Symbol = Symbol.Download, Width = 18, Height = 18 }, _updateButtonText } }; diff --git a/src/box-winUI/Views/HomePage.cs b/src/box-winUI/Views/HomePage.cs index 1975e4a..80a987c 100644 --- a/src/box-winUI/Views/HomePage.cs +++ b/src/box-winUI/Views/HomePage.cs @@ -28,6 +28,7 @@ public sealed class HomePage : Page private readonly Action _openServiceStatus; private readonly Action _openLogs; private readonly WebView2EnvironmentFactory _webViewEnvironmentFactory = AppServices.GetRequiredService(); + private readonly IRuntimeAssetService _runtimeAssets = AppServices.GetRequiredService(); private readonly ISolarEphemerisService _solarEphemerisService = AppServices.GetRequiredService(); private readonly ISettingsService _settingsService = AppServices.GetRequiredService(); private readonly IAppInstallerUpdateService _updateService = AppServices.GetRequiredService(); @@ -865,12 +866,6 @@ public sealed class HomePage : Page { try { - var resourceFolder = Path.Combine(AppContext.BaseDirectory, "Assets", "home-globe"); - if (!Directory.Exists(resourceFolder)) - { - throw new DirectoryNotFoundException(resourceFolder); - } - var environment = await _webViewEnvironmentFactory.CreateAsync("HomeGlobe"); await _globeView.EnsureCoreWebView2Async(environment); _globeView.CoreWebView2.Settings.AreDefaultContextMenusEnabled = false; @@ -878,10 +873,7 @@ public sealed class HomePage : Page _globeView.CoreWebView2.Settings.AreHostObjectsAllowed = false; _globeView.CoreWebView2.Settings.IsStatusBarEnabled = false; _globeView.CoreWebView2.Settings.IsZoomControlEnabled = false; - _globeView.CoreWebView2.SetVirtualHostNameToFolderMapping( - GlobeHostName, - resourceFolder, - CoreWebView2HostResourceAccessKind.Allow); + _runtimeAssets.MapWebViewHost(_globeView.CoreWebView2, GlobeHostName, "home-globe"); _ephemerisTask = _solarEphemerisService.GetCurrentAsync(); _preciseEphemerisTask = _solarEphemerisService.GetPreciseCurrentAsync(); _globeView.CoreWebView2.NavigationCompleted += GlobeView_NavigationCompleted; diff --git a/src/box-winUI/Views/OnlineToolsPage.cs b/src/box-winUI/Views/OnlineToolsPage.cs new file mode 100644 index 0000000..4564c61 --- /dev/null +++ b/src/box-winUI/Views/OnlineToolsPage.cs @@ -0,0 +1,188 @@ +using Microsoft.UI.Text; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Automation; +using Microsoft.UI.Xaml.Controls; +using YMhut.Box.Core.Api; +using YMhut.Box.Core.Tools; +using YMhut.Box.WinUI.Services; + +namespace YMhut.Box.WinUI.Views; + +public sealed class OnlineToolsPage : Page +{ + private static readonly string[] Categories = ["全部", "AI", "生活", "网络", "娱乐", "学习", "图像", "数据", "开发", "实用"]; + private readonly ToolCatalog _catalog = AppServices.GetRequiredService(); + private readonly Action _openTool; + private readonly AutoSuggestBox _search = new() + { + PlaceholderText = "搜索联网工具", + QueryIcon = new SymbolIcon(Symbol.Find), + MinWidth = 220, + MaxWidth = 420 + }; + private readonly ComboBox _category = new() + { + Header = "分类", + MinWidth = 150, + ItemsSource = Categories, + SelectedIndex = 0 + }; + private readonly StackPanel _items = new() { Spacing = 1 }; + private readonly TextBlock _count = ModernUi.Text(string.Empty, 12, FontWeights.SemiBold, ModernUi.TextSecondary, maxLines: 1); + + public OnlineToolsPage(Action openTool) + { + _openTool = openTool; + Background = ModernUi.AppBackground; + Content = BuildContent(); + _search.TextChanged += (_, _) => Refresh(); + _search.QuerySubmitted += (_, _) => Refresh(); + _category.SelectionChanged += (_, _) => Refresh(); + Loaded += (_, _) => Refresh(); + } + + private UIElement BuildContent() + { + var toolbar = new Grid { ColumnSpacing = 12 }; + toolbar.ColumnDefinitions.Add(new ColumnDefinition()); + toolbar.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); + toolbar.Children.Add(_search); + Grid.SetColumn(_category, 1); + toolbar.Children.Add(_category); + + var title = new Grid { ColumnSpacing = 12 }; + title.ColumnDefinitions.Add(new ColumnDefinition()); + title.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); + title.Children.Add(new StackPanel + { + Spacing = 3, + Children = + { + ModernUi.Text("联网工具", 24, FontWeights.SemiBold, maxLines: 1), + ModernUi.Text("固定 74 项 PearAPI 文档目录;只调用免 Key 允许路径,接口变更时不会转用付费服务。", 13, foreground: ModernUi.TextSecondary, maxLines: 3) + } + }); + Grid.SetColumn(_count, 1); + _count.VerticalAlignment = VerticalAlignment.Bottom; + title.Children.Add(_count); + + var listScroll = new ScrollViewer + { + Content = _items, + VerticalScrollBarVisibility = ScrollBarVisibility.Auto, + HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled, + VerticalScrollMode = ScrollMode.Enabled + }; + var root = new Grid { Padding = new Thickness(18), RowSpacing = 14 }; + root.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); + root.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); + root.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); + root.RowDefinitions.Add(new RowDefinition()); + root.Children.Add(title); + Grid.SetRow(toolbar, 1); + root.Children.Add(toolbar); + var notice = new InfoBar + { + IsOpen = true, + IsClosable = false, + Severity = InfoBarSeverity.Informational, + Title = "按需联网", + Message = "公共无输入请求可在内存短时缓存;文本、网址、金融查询和上传内容不持久化缓存。文件只会在二次确认后发送。" + }; + Grid.SetRow(notice, 2); + root.Children.Add(notice); + Grid.SetRow(listScroll, 3); + root.Children.Add(listScroll); + return root; + } + + private void Refresh() + { + var query = (_search.Text ?? string.Empty).Trim(); + var category = _category.SelectedItem?.ToString() ?? "全部"; + var definitions = PearApiCatalog.All + .Where(definition => category == "全部" || definition.Category == category) + .Where(definition => query.Length == 0 || + definition.Name.Contains(query, StringComparison.OrdinalIgnoreCase) || + definition.Description.Contains(query, StringComparison.OrdinalIgnoreCase) || + definition.Category.Contains(query, StringComparison.OrdinalIgnoreCase)) + .OrderByDescending(definition => definition.IsAvailableWithoutKey) + .ThenBy(definition => definition.Category, StringComparer.CurrentCulture) + .ThenBy(definition => definition.Name, StringComparer.CurrentCulture) + .ToArray(); + _items.Children.Clear(); + foreach (var definition in definitions) + { + _items.Children.Add(BuildRow(definition)); + } + _count.Text = $"{definitions.Length} / {PearApiCatalog.All.Count}"; + if (definitions.Length == 0) + { + _items.Children.Add(new InfoBar { IsOpen = true, IsClosable = false, Message = "没有匹配的联网工具。" }); + } + } + + private UIElement BuildRow(PearApiToolDefinition definition) + { + var grid = new Grid { Padding = new Thickness(12, 10, 12, 10), ColumnSpacing = 12, MinHeight = 68 }; + grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); + grid.ColumnDefinitions.Add(new ColumnDefinition()); + grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); + grid.Children.Add(ModernUi.IconTile(CategoryGlyph(definition.Category), 38, ModernUi.SurfaceAlt, ModernUi.Accent, 16)); + var body = new StackPanel + { + Spacing = 3, + VerticalAlignment = VerticalAlignment.Center, + Children = + { + ModernUi.Text(definition.Name, 14, FontWeights.SemiBold, maxLines: 1), + ModernUi.Text(definition.Description, 12, foreground: ModernUi.TextSecondary, maxLines: 2) + } + }; + Grid.SetColumn(body, 1); + grid.Children.Add(body); + var status = ModernUi.Badge( + definition.IsAvailableWithoutKey ? definition.Category : "需鉴权 / 已禁用", + definition.IsAvailableWithoutKey ? ModernUi.Accent : ModernUi.TextSecondary, + definition.IsAvailableWithoutKey ? ModernUi.AccentSoft : ModernUi.SurfaceAlt); + status.VerticalAlignment = VerticalAlignment.Center; + Grid.SetColumn(status, 2); + grid.Children.Add(status); + + var button = new Button + { + HorizontalAlignment = HorizontalAlignment.Stretch, + HorizontalContentAlignment = HorizontalAlignment.Stretch, + Background = ModernUi.Transparent, + BorderBrush = ModernUi.Stroke, + BorderThickness = new Thickness(0, 0, 0, 1), + CornerRadius = new CornerRadius(0), + Padding = new Thickness(0), + Content = grid, + UseSystemFocusVisuals = true + }; + ModernUi.ApplyHoverResources(button, ModernUi.HoverSurface, ModernUi.StrokeStrong); + button.Click += (_, _) => + { + var module = _catalog.GetById(definition.ToolId); + if (module is not null) _openTool(module); + }; + AutomationProperties.SetName(button, definition.Name); + AutomationProperties.SetHelpText(button, definition.Description); + ToolTipService.SetToolTip(button, definition.IsAvailableWithoutKey ? definition.Description : definition.AvailabilityNote); + return button; + } + + private static string CategoryGlyph(string category) => category switch + { + "AI" => "\uE99A", + "生活" => "\uE80F", + "网络" => "\uE774", + "娱乐" => "\uE8D6", + "学习" => "\uE82D", + "图像" => "\uEB9F", + "数据" => "\uE9D9", + "开发" => "\uE943", + _ => "\uE8EF" + }; +} diff --git a/src/box-winUI/Views/PluginDocsPage.cs b/src/box-winUI/Views/PluginDocsPage.cs index 99100d4..3ba64a4 100644 --- a/src/box-winUI/Views/PluginDocsPage.cs +++ b/src/box-winUI/Views/PluginDocsPage.cs @@ -2,12 +2,15 @@ using Microsoft.UI.Text; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Media; +using YMhut.Box.Core.Settings; +using YMhut.Box.WinUI.Services; namespace YMhut.Box.WinUI.Views; public sealed class PluginDocsPage : Page { private readonly Action? _goBack; + private readonly ISettingsService _settings = AppServices.GetRequiredService(); public PluginDocsPage(Action? goBack = null) { @@ -54,15 +57,24 @@ entry:默认 HTML 入口,相对插件目录。 permissions:希望使用的能力列表;声明不等于授权,用户仍需在插件页开启。 surfaces:挂载入口,当前支持 ToolboxTool 和 NavPage。 resources:插件资源白名单,路径必须留在插件目录内。 +tauri:预构建目录、固定宿主 API 和模板版本;不能声明私有 Tauri 宿主程序。 +toolBindings:受控第三方工具清单;每个 EXE/DLL 都必须提供 SHA-256,参数必须使用声明的类型化槽位。 builtIn:仅内置示例使用,第三方插件不要设置。 """)); - docs.Children.Add(Section("3. surface 与运行入口", """ + docs.Children.Add(Section("3. Tauri 预构建与 .ymplugin", """ +YMhut Box 随包提供固定 Tauri 宿主、运行时清单和模板,不在用户电脑上调用 Node、npm、Cargo 或 Rust 编译插件。 + +Tauri 插件应把生产构建产物放入 dist/,入口通常为 dist/index.html。插件页可以创建预构建示例、导入文件夹或 .ymplugin 包,并将验证通过的插件导出为 .ymplugin。 + +.ymplugin 是带版本、插件 ID、manifest SHA-256 和文件清单的本地包。导入时会在隔离临时目录解包,并拒绝越界路径、链接、损坏元数据和未声明原生文件。 +""")); + docs.Children.Add(Section("4. surface 与运行入口", """ ToolboxTool:挂载到工具箱,工具 ID 形如 plugin::。 NavPage:显示在插件页,可作为插件主页面或控制台。 surface.entry 可覆盖 manifest.entry;未填写时使用 manifest.entry。插件页面加载在独立 WebView 用户数据目录中,和安全浏览器、普通工具 WebView 分开。 """)); - docs.Children.Add(Section("4. 权限模型", """ + docs.Children.Add(Section("5. 权限模型", """ manifest v3 要求每项权限填写 permissionReasons。security.requiredPermissions 未授权时禁止启用,其余权限未授权时 Bridge 返回稳定错误码。 Input:读取/写入插件输入。 @@ -76,8 +88,10 @@ RunTool:调用允许的内置工具。 OpenExternal:仅打开 openExternalOrigins 声明的 HTTPS 来源,默认进入安全浏览器。 OpenSystemBrowser:打开已声明 HTTPS 来源,每次调用都由宿主确认。 NetworkDiagnostics:读取本机网络诊断、ping、DNS、trace route 等宿主诊断能力。 +ExternalRuntime:在固定随包 Tauri 宿主中呈现预构建页面。 +ExternalTool:按清单、哈希和参数规则启动绑定工具;只能在开发者模式和当前版本确认有效时使用。 """)); - docs.Children.Add(Section("5. JS Bridge", """ + docs.Children.Add(Section("6. JS Bridge", """ window.ymhut.input.get() window.ymhut.input.set(value) window.ymhut.output.set(value) @@ -100,26 +114,34 @@ window.ymhut.clipboard.writeText(text) window.ymhut.file.openPicker() window.ymhut.file.savePicker(name, value) window.ymhut.tool.run(toolId, input) +window.ymhut.externalTool.launch(bindingId, arguments) window.ymhut.openExternal(url, { target?: "safe" | "system" }) openExternal 默认打开应用内安全浏览器。显式传入 { target: "system" } 需要 OpenSystemBrowser 权限,且每次调用都由宿主确认。 """)); - docs.Children.Add(Section("6. 独立窗口、输出区与遮挡", """ + docs.Children.Add(Section("7. 第三方工具绑定", """ +绑定工具仅支持插件目录中的已声明 EXE,以及它依赖的已声明 DLL。清单必须列出每个文件的 SHA-256;工具文件变化后原确认立即失效。 + +宿主使用 UseShellExecute=false 启动,不允许提权、安装器、驱动、服务、脚本或任意命令行。参数通过 ArgumentList 传递,动态值必须匹配 manifest 中声明的 Text、Integer、Boolean、Choice 或插件内 FilePath 类型。 + +工具进程属于当前插件会话 Job Object。插件关闭、权限撤销、清单变化或主程序退出时,相关进程会被终止。 +""")); + docs.Children.Add(Section("8. 独立窗口、输出区与遮挡", """ 插件可以作为工具箱工具或插件页运行。需要脱离主窗口时,应使用宿主提供的独立窗口入口,而不是自行弹出浏览器或远程窗口。 插件的主要 UI 应在 WebView 内容区内完成。window.ymhut.output.* 写入的是宿主输出区,适合报告、日志摘要、可复制结果,不适合持续覆盖主操作面板。 避免使用全屏 fixed 遮罩、超高 z-index、透明点击层或模拟系统标题栏。确实需要模态交互时,应提供明显关闭按钮,并保证键盘焦点能返回主内容。 """)); - docs.Children.Add(Section("7. 安全边界", """ + docs.Children.Add(Section("9. 安全边界", """ 每个插件 surface 使用独立虚拟 HTTPS 原点和独立 WebView2 数据目录,不使用 file://。跨原点导航、新窗口、下载、iframe 与浏览器敏感权限会被拒绝。 插件不能覆盖内置工具 ID、应用图标、开发者信息、关于页核心身份或内置 Assets 路径。 插件不能通过相对路径逃逸插件目录,resources、entry 和 surface.entry 都会被校验。 文件能力只通过系统选择器提供,不开放静默任意路径读写。 页面直接 fetch/WebSocket 与宿主 fetch 使用同一精确来源白名单;HTTP、localhost、局域网、私网和越界重定向会被拒绝。 -旧清单以 LegacyWebOnly 运行,本地 HTML/CSS/JS 可用,Bridge、远程连接和外接运行时关闭。Shell/Script 和插件自带原生程序不受支持。 +旧清单以 LegacyWebOnly 运行,本地 HTML/CSS/JS 可用,Bridge、远程连接和外接运行时关闭。Shell/Script 仍不受支持;原生程序只能通过严格的 toolBindings 使用。 """)); - docs.Children.Add(Section("8. 常见问题", """ + docs.Children.Add(Section("10. 常见问题", """ 加载失败:检查 ymhut.plugin.json、README、entry 文件是否存在,路径是否在插件目录内。 权限拒绝:确认 manifest 声明了权限,并在插件页为该插件授权。 外链打不开:只支持清单 openExternalOrigins 中的绝对 HTTPS 来源;系统浏览器还需要逐次确认。 @@ -127,7 +149,7 @@ openExternal 默认打开应用内安全浏览器。显式传入 { target: "syst 独立窗口异常:确认插件入口没有依赖主窗口 DOM,也不要调用浏览器弹窗 API 创建 Edge/系统私密窗口。 网络结果为空:Http 或 NetworkDiagnostics 权限可能未授予,或远程端点不可用,插件应给出降级提示。 """)); - docs.Children.Add(Section("9. 给 AI/自动化实现者的约束", """ + docs.Children.Add(Section("11. 给 AI/自动化实现者的约束", """ 生成插件时请优先创建最小可运行包:manifest、README、index.html、style.css、main.js。 不要请求不需要的权限;每个权限都应在 README 中说明用途。 不要下载远程脚本作为运行依赖;可用远程 API 获取数据,但 UI 和核心逻辑应随插件包本地发布。 @@ -135,6 +157,20 @@ openExternal 默认打开应用内安全浏览器。显式传入 { target: "syst 链接跳转默认使用 window.ymhut.openExternal(url),系统浏览器仅作为显式动作。 为窄窗口、独立窗口和无网络状态提供清晰布局与空态。 """)); + var resetNotice = ModernUi.PillButton("重新显示第三方插件提示", "\uE72C", async () => + { + await _settings.UpdateAsync(settings => settings.PluginNoticeVersion = string.Empty); + ToastService.Show("下次进入插件页时会重新显示提示。", ToastKind.Success, TimeSpan.FromSeconds(3)); + }); + docs.Children.Add(Section("第三方内容提示", new StackPanel + { + Spacing = 10, + Children = + { + ModernUi.Text("插件内容和绑定工具由第三方提供。你可以随时重置提示状态,再次查看当前免责说明。", 13, foreground: ModernUi.TextSecondary, maxLines: 4), + resetNotice + } + })); var scroll = new ScrollViewer { @@ -167,4 +203,17 @@ openExternal 默认打开应用内安全浏览器。显式传入 { target: "syst } }, new Thickness(16), radius: ModernUi.PanelRadius); } + + private static Border Section(string title, UIElement body) + { + return ModernUi.Card(new StackPanel + { + Spacing = 8, + Children = + { + ModernUi.Text(title, 20, FontWeights.SemiBold), + body + } + }, new Thickness(16), radius: ModernUi.PanelRadius); + } } diff --git a/src/box-winUI/Views/PluginPage.cs b/src/box-winUI/Views/PluginPage.cs index 140e42c..e54f2d3 100644 --- a/src/box-winUI/Views/PluginPage.cs +++ b/src/box-winUI/Views/PluginPage.cs @@ -5,6 +5,7 @@ using Windows.Storage.Pickers; using WinRT.Interop; using YMhut.Box.Core.Logging; using YMhut.Box.Core.Plugins; +using YMhut.Box.Core.Plugins.Runtime; using YMhut.Box.Core.Settings; using YMhut.Box.WinUI.Services; @@ -20,6 +21,7 @@ public sealed class PluginPage : Page private readonly IPluginPackageService _pluginPackages = AppServices.GetRequiredService(); private readonly IBuiltInPluginInstallerService _builtInInstaller = AppServices.GetRequiredService(); private readonly ISettingsService _settingsService = AppServices.GetRequiredService(); + private readonly IPluginRuntimeDependencyService _runtimeDependencies = AppServices.GetRequiredService(); private readonly Action _openDocs; private readonly Action _openSurface; private readonly Func? _catalogChanged; @@ -30,6 +32,7 @@ public sealed class PluginPage : Page }; private readonly TextBlock _statusText = ModernUi.Text("正在加载插件...", 13, foreground: ModernUi.TextSecondary); private readonly TextBlock _rootText = ModernUi.Text("插件根目录:等待插件宿主启动", 14, foreground: ModernUi.TextSecondary, maxLines: 2); + private readonly TextBlock _runtimeText = ModernUi.Text("正在检查 Tauri 随包运行时...", 12, foreground: ModernUi.TextSecondary, maxLines: 2); private bool _scanInProgress; @@ -49,7 +52,11 @@ public sealed class PluginPage : Page Content = BuildContent(); _pluginHost.SnapshotChanged += PluginHost_SnapshotChanged; _pluginHost.StatusChanged += PluginHost_StatusChanged; - Loaded += async (_, _) => await LoadAsync(); + Loaded += async (_, _) => + { + await ShowPluginNoticeAsync(); + await LoadAsync(); + }; Unloaded += (_, _) => { _pluginHost.SnapshotChanged -= PluginHost_SnapshotChanged; @@ -72,13 +79,14 @@ public sealed class PluginPage : Page var scan = ModernUi.PillButton(AppLocalizer.T("扫描插件", "Scan plugins"), "\uE72C", async () => await ScanAsync()); var create = ModernUi.PillButton(AppLocalizer.T("新建示例", "New sample"), "\uE710", async () => await CreateTemplateAsync()); var import = ModernUi.PillButton(AppLocalizer.T("导入文件夹", "Import folder"), "\uE8B5", async () => await ImportFolderAsync()); + var importPackage = ModernUi.PillButton(AppLocalizer.T("导入插件包", "Import package"), "\uE7C3", async () => await ImportPackageAsync()); var actions = new StackPanel { Orientation = Orientation.Horizontal, Spacing = 8, HorizontalAlignment = HorizontalAlignment.Right, VerticalAlignment = VerticalAlignment.Top, - Children = { create, import, scan, help } + Children = { create, import, importPackage, scan, help } }; root.Children.Add(ModernUi.PageHeader( @@ -90,6 +98,7 @@ public sealed class PluginPage : Page var body = new StackPanel { Spacing = 12 }; body.Children.Add(_statusText); + body.Children.Add(_runtimeText); body.Children.Add(_pluginGrid); var scroll = new ScrollViewer { @@ -105,6 +114,11 @@ public sealed class PluginPage : Page private async Task LoadAsync() { + var runtime = await _runtimeDependencies.GetAsync(); + _runtimeText.Text = runtime.IsReady + ? $"Tauri 随包宿主已就绪 · Host API {runtime.HostApiVersion} · 模板 {runtime.TemplateVersion} · 无需系统 Node/Rust" + : $"Tauri 随包宿主不可用:{runtime.Diagnostic}"; + _runtimeText.Foreground = runtime.IsReady ? ModernUi.TextSecondary : ModernUi.Danger; var cached = _pluginHost.CurrentSnapshot; if (cached is not null) { @@ -130,13 +144,11 @@ public sealed class PluginPage : Page catch (Exception exception) { var safe = AppLocalizer.SanitizeSensitiveText(exception.Message, 180); - _statusText.Text = cached is null - ? $"插件宿主启动或读取失败:{safe}" - : $"插件宿主暂时不可用,已保留上次扫描结果:{safe}"; - if (cached is null) - { - _pluginGrid.Children.Add(BuildRetryCard()); - } + var empty = _pluginHost.InvalidateSnapshot(cached?.PluginsRoot); + _pluginGrid.Children.Clear(); + _pluginGrid.Children.Add(BuildRetryCard()); + _statusText.Text = $"插件宿主启动或读取失败,已清除过期显示:{safe}"; + await NotifyCatalogChangedAsync(empty); return; } @@ -170,13 +182,11 @@ public sealed class PluginPage : Page catch (Exception exception) { var safe = AppLocalizer.SanitizeSensitiveText(exception.Message, 180); - _statusText.Text = previous is null - ? AppLocalizer.T($"插件扫描失败:{safe}", $"Plugin scan failed: {safe}") - : AppLocalizer.T($"插件扫描失败,已保留上次结果:{safe}", $"Plugin scan failed; keeping the previous result: {safe}"); - if (previous is null) - { - _pluginGrid.Children.Add(BuildRetryCard()); - } + var empty = _pluginHost.InvalidateSnapshot(previous?.PluginsRoot); + _pluginGrid.Children.Clear(); + _pluginGrid.Children.Add(BuildRetryCard()); + _statusText.Text = AppLocalizer.T($"插件扫描失败,已清除过期显示:{safe}", $"Plugin scan failed; stale entries were cleared: {safe}"); + await NotifyCatalogChangedAsync(empty); await _logService.WriteAsync("Error", "plugin", "Plugin scan failed", safe); return; @@ -198,10 +208,13 @@ public sealed class PluginPage : Page { _pluginGrid.Children.Clear(); _rootText.Text = $"本地插件目录:{snapshot.PluginsRoot}"; - var plugins = snapshot.Plugins.Select(plugin => plugin.ToLoadedPlugin()).ToArray(); + var invalidCount = snapshot.Plugins.Count(plugin => !plugin.IsValid); + var plugins = snapshot.Plugins.Where(plugin => plugin.IsValid).Select(plugin => plugin.ToLoadedPlugin()).ToArray(); _statusText.Text = plugins.Length == 0 - ? "还没有安装本地插件。创建插件目录并放入 ymhut.plugin.json 后点击刷新。" - : $"已扫描 {plugins.Length} 个插件 · 插件宿主运行中 · {snapshot.LoadedAt:HH:mm:ss}"; + ? invalidCount == 0 + ? "还没有安装有效的本地插件。可以创建示例或导入 .ymplugin 包。" + : $"未发现有效插件,已从页面和工具目录移除 {invalidCount} 个损坏条目;详细原因已写入日志。" + : $"已扫描 {plugins.Length} 个有效插件{(invalidCount > 0 ? $" · 忽略 {invalidCount} 个损坏条目" : string.Empty)} · {snapshot.LoadedAt:HH:mm:ss}"; foreach (var plugin in plugins) { @@ -239,9 +252,11 @@ public sealed class PluginPage : Page } else if (status == PluginHostStatus.Failed) { - _statusText.Text = _pluginHost.CurrentSnapshot is null - ? "插件宿主进程异常,可点击刷新重试。" - : "插件宿主进程异常,已保留上次扫描结果,可点击刷新重试。"; + var empty = _pluginHost.InvalidateSnapshot(_pluginHost.CurrentSnapshot?.PluginsRoot); + _pluginGrid.Children.Clear(); + _pluginGrid.Children.Add(BuildRetryCard()); + _statusText.Text = "插件宿主进程异常,已清除过期插件显示,可点击刷新重试。"; + _ = NotifyCatalogChangedAsync(empty); } }); } @@ -340,6 +355,7 @@ public sealed class PluginPage : Page }; content.Children.Add(BuildStateSummary(plugin)); content.Children.Add(BuildSecuritySummary(plugin)); + content.Children.Add(BuildToolBindingsPanel(plugin)); content.Children.Add(BuildPermissionPanel(plugin)); content.Children.Add(BuildSurfacePanel(plugin)); content.Children.Add(BuildLocalManagementPanel(plugin)); @@ -388,6 +404,30 @@ public sealed class PluginPage : Page }); } + private static UIElement BuildToolBindingsPanel(LoadedPlugin plugin) + { + var bindings = plugin.Manifest.ToolBindings ?? []; + if (bindings.Count == 0) + { + return Section("绑定工具", ModernUi.Text("此插件未绑定第三方本地工具。", 13, foreground: ModernUi.TextSecondary)); + } + var panel = new StackPanel { Spacing = 8 }; + foreach (var binding in bindings) + { + panel.Children.Add(ModernUi.Card(new StackPanel + { + Spacing = 4, + Children = + { + ModernUi.Text(binding.Name, 14, FontWeights.SemiBold, maxLines: 1), + ModernUi.Text($"ID:{binding.Id} · {binding.Architecture} · {binding.Files.Count} 个哈希文件", 12, foreground: ModernUi.TextSecondary, maxLines: 2), + ModernUi.Text($"入口:{binding.Executable} · 参数槽:{binding.Parameters?.Count ?? 0}", 12, foreground: ModernUi.TextSecondary, maxLines: 2) + } + }, new Thickness(10), radius: 6, background: ModernUi.SurfaceAlt)); + } + return Section("绑定工具", panel); + } + private UIElement BuildLocalManagementPanel(LoadedPlugin plugin) { var clear = ModernUi.PillButton("清除插件数据", "\uE74D", async () => await ClearPluginDataAsync(plugin)); @@ -409,6 +449,7 @@ public sealed class PluginPage : Page confirm.IsEnabled = _settingsService.Current.PluginDeveloperMode && PluginPermissionPolicy.IsGrantCurrent(plugin.Manifest, plugin.State, PluginPermission.ExternalRuntime); actions.Children.Add(confirm); + actions.Children.Add(ModernUi.PillButton("导出 .ymplugin", "\uEDE1", async () => await ExportPackageAsync(plugin))); } return Section("本地管理", actions); } @@ -424,7 +465,8 @@ public sealed class PluginPage : Page Items = { "零权限 Web 示例", - "Bridge / 精确网络示例" + "Bridge / 精确网络示例", + "Tauri 预构建示例" } }; var dialog = new ContentDialog @@ -451,7 +493,12 @@ public sealed class PluginPage : Page root, id.Text, name.Text, - kind.SelectedIndex == 0 ? PluginTemplateKind.ZeroPermissionWeb : PluginTemplateKind.BridgeNetwork); + kind.SelectedIndex switch + { + 0 => PluginTemplateKind.ZeroPermissionWeb, + 1 => PluginTemplateKind.BridgeNetwork, + _ => PluginTemplateKind.TauriPrebuilt + }); _statusText.Text = result.Message; if (result.Succeeded) { @@ -482,6 +529,32 @@ public sealed class PluginPage : Page } } + private async Task ImportPackageAsync() + { + if (App.CurrentWindow is null) return; + var picker = new FileOpenPicker(); + picker.FileTypeFilter.Add(".ymplugin"); + InitializeWithWindow.Initialize(picker, WindowNative.GetWindowHandle(App.CurrentWindow)); + var file = await picker.PickSingleFileAsync(); + var root = _pluginHost.CurrentSnapshot?.PluginsRoot; + if (file is null || string.IsNullOrWhiteSpace(root)) return; + var result = await _pluginPackages.ImportPackageAsync(file.Path, root); + _statusText.Text = result.Message; + if (result.Succeeded) await ScanAsync(); + } + + private async Task ExportPackageAsync(LoadedPlugin plugin) + { + if (App.CurrentWindow is null) return; + var picker = new FileSavePicker { SuggestedFileName = $"{PluginIds.Normalize(plugin.Manifest.Id)}-{plugin.Manifest.Version}" }; + picker.FileTypeChoices.Add("YMhut 插件包", [".ymplugin"]); + InitializeWithWindow.Initialize(picker, WindowNative.GetWindowHandle(App.CurrentWindow)); + var file = await picker.PickSaveFileAsync(); + if (file is null) return; + var result = await _pluginPackages.ExportPackageAsync(plugin, file.Path); + _statusText.Text = result.Message; + } + private async Task ClearPluginDataAsync(LoadedPlugin plugin) { if (plugin.State.Enabled) @@ -534,7 +607,7 @@ public sealed class PluginPage : Page var dialog = new ContentDialog { Title = "确认受控外接运行时", - Content = $"仅确认 {plugin.Manifest.Name} v{plugin.Manifest.Version}。插件版本或权限策略变化后需要重新确认。外接宿主不会获得 Tauri 全局 API、任意文件读取或原生程序执行能力。", + Content = $"仅确认 {plugin.Manifest.Name} v{plugin.Manifest.Version}。插件版本、权限策略、预构建资源或绑定工具哈希变化后需要重新确认。绑定工具只能通过已声明参数启动,不能提权、安装驱动或执行任意命令行。", PrimaryButtonText = "确认此版本", CloseButtonText = "取消", DefaultButton = ContentDialogButton.Close, @@ -549,6 +622,39 @@ public sealed class PluginPage : Page await NotifyCatalogChangedAsync(snapshot); } + private async Task ShowPluginNoticeAsync() + { + if (string.Equals(_settingsService.Current.PluginNoticeVersion, AgreementDocument.PluginNoticeVersion, StringComparison.Ordinal)) + { + return; + } + var remember = new CheckBox { Content = AppLocalizer.T("不再提示当前版本条款", "Do not show this version again") }; + var content = new StackPanel + { + Spacing = 10, + MaxWidth = 560, + Children = + { + ModernUi.Text(AppLocalizer.T("插件页面、插件内容和插件绑定的第三方工具均由相应作者或第三方提供,与 YMhut Box 主程序及官方内容没有关联。", "Plugin pages, content, and bound third-party tools are supplied by their authors and are not affiliated with the YMhut Box application or its official content."), 13.5, maxLines: 6), + ModernUi.Text(AppLocalizer.T("插件可能按清单申请网络、剪贴板、文件选择、外部链接或受控本地工具权限。请自行判断来源、准确性、版权和安全风险;YMhut Box 不保证第三方内容持续可用或没有错误。", "Plugins may request network, clipboard, file picker, external-link, or controlled local-tool permissions. Evaluate their source, accuracy, copyright, and security risks yourself."), 13, foreground: ModernUi.TextSecondary, maxLines: 8), + remember + } + }; + var dialog = new ContentDialog + { + Title = AppLocalizer.T("第三方插件使用提示", "Third-party plugin notice"), + Content = content, + PrimaryButtonText = AppLocalizer.T("我已了解", "I understand"), + DefaultButton = ContentDialogButton.Primary, + XamlRoot = XamlRoot + }; + await dialog.ShowAsync(); + if (remember.IsChecked == true) + { + await _settingsService.UpdateAsync(settings => settings.PluginNoticeVersion = AgreementDocument.PluginNoticeVersion); + } + } + private static Button RoundIconButton(string glyph, string tooltip, Func? click = null) { var button = new Button diff --git a/src/box-winUI/Views/ToolboxPage.cs b/src/box-winUI/Views/ToolboxPage.cs index 8c4b419..0048d37 100644 --- a/src/box-winUI/Views/ToolboxPage.cs +++ b/src/box-winUI/Views/ToolboxPage.cs @@ -1495,6 +1495,11 @@ public sealed class ToolboxPage : Page private static string SourceLabel(IToolModule module) { + if (!string.IsNullOrWhiteSpace(module.Metadata.Provider)) + { + return module.Metadata.Provider; + } + return module switch { ExternalToolModule => AppLocalizer.T("外部工具", "External tools"), diff --git a/src/box-winUI/Views/ToolboxSurface.cs b/src/box-winUI/Views/ToolboxSurface.cs index 2f0bbd1..44f7667 100644 --- a/src/box-winUI/Views/ToolboxSurface.cs +++ b/src/box-winUI/Views/ToolboxSurface.cs @@ -10,7 +10,8 @@ internal enum ToolboxSurfaceKind { Hardware, Optimization, - Music + Music, + OnlineTools } internal sealed record ToolboxSurfaceDefinition( @@ -68,7 +69,18 @@ internal static class ToolboxSurfaceCatalog "在线媒体", "Online media", ToolboxSurfaceKind.Music, - ["music", "netease", "player", "playlist", "音乐", "网易云", "播放器"]) + ["music", "netease", "player", "playlist", "音乐", "网易云", "播放器"]), + new( + "online_tools", + "联网工具", + "Online tools", + "按 AI、生活、网络、娱乐、学习、图像、数据、开发和实用分类访问安全免 Key 接口。", + "Browse allowlisted no-key APIs across nine task-focused categories.", + "\uE774", + "PearAPI · 74 项", + "PearAPI · 74 tools", + ToolboxSurfaceKind.OnlineTools, + ["online", "pearapi", "api", "联网", "在线", "接口"]) ]; internal static ToolboxSurfaceDefinition? Find(string idOrQuery) @@ -97,6 +109,7 @@ internal sealed class ToolboxSurfacePageFactory ToolboxSurfaceKind.Hardware => new HardwarePage(), ToolboxSurfaceKind.Optimization => new OptimizationPage(openTool), ToolboxSurfaceKind.Music => new NetworkMusicPage(), + ToolboxSurfaceKind.OnlineTools => new OnlineToolsPage(openTool), _ => throw new ArgumentOutOfRangeException(nameof(definition)) }; diff --git a/src/box-winUI/Views/Tools/AdaptiveToolPage.ResultRenderers.cs b/src/box-winUI/Views/Tools/AdaptiveToolPage.ResultRenderers.cs index 121b0c6..df9a639 100644 --- a/src/box-winUI/Views/Tools/AdaptiveToolPage.ResultRenderers.cs +++ b/src/box-winUI/Views/Tools/AdaptiveToolPage.ResultRenderers.cs @@ -1,4 +1,5 @@ using System.Text.Json; +using YMhut.Box.WinUI.Controls; using System.Text.RegularExpressions; using Microsoft.UI.Text; using Microsoft.UI.Xaml; @@ -785,25 +786,7 @@ public abstract partial class AdaptiveToolPage private static Border BuildRankedItemCard(int rank, string title, string? meta, string? url) { - // Rank badge color: gold/silver/bronze for top 3, default for rest - var rankFg = rank switch - { - 1 => ModernUi.Brush("#CA5010"), // gold-ish / bronze - 2 => ModernUi.TextSecondary, - 3 => ModernUi.TextSecondary, - _ => ModernUi.TextSecondary - }; - var rankBg = rank switch - { - 1 => ModernUi.AccentSoft, - 2 => ModernUi.SurfaceAlt, - 3 => ModernUi.SurfaceAlt, - _ => ModernUi.SurfaceAlt - }; - - var rankBadge = ModernUi.Badge(rank.ToString(), rank == 1 ? ModernUi.Accent : rankFg, rankBg); - rankBadge.MinWidth = 32; - rankBadge.HorizontalAlignment = HorizontalAlignment.Center; + var rankBadge = RankBadgeFactory.Create(rank, 32); var text = new StackPanel { diff --git a/src/box-winUI/Views/Tools/AdaptiveToolPage.cs b/src/box-winUI/Views/Tools/AdaptiveToolPage.cs index d0067fe..943dd67 100644 --- a/src/box-winUI/Views/Tools/AdaptiveToolPage.cs +++ b/src/box-winUI/Views/Tools/AdaptiveToolPage.cs @@ -39,6 +39,7 @@ public abstract partial class AdaptiveToolPage : ToolPageBase private readonly ISettingsService _settingsService = AppServices.GetRequiredService(); private readonly IToolWorkerService _workerService = AppServices.GetRequiredService(); private readonly WebView2EnvironmentFactory _webViewEnvironmentFactory = AppServices.GetRequiredService(); + private readonly IRuntimeAssetService _runtimeAssets = AppServices.GetRequiredService(); private readonly ToolResultWebBridge _toolResultWebBridge = AppServices.GetRequiredService(); private readonly ToolPageWebBridge _toolPageWebBridge = AppServices.GetRequiredService(); private readonly IUiPerformanceCoordinator _uiPerformanceCoordinator = AppServices.GetRequiredService(); @@ -1803,21 +1804,6 @@ public abstract partial class AdaptiveToolPage : ToolPageBase try { - var assetsRoot = AppServices.GetRequiredService().Assets; - var resourceFolder = Path.Combine(assetsRoot, "tool-pages"); - if (!Directory.Exists(resourceFolder)) - { - resourceFolder = Path.Combine(AppContext.BaseDirectory, "Assets", "tool-pages"); - } - - if (!Directory.Exists(resourceFolder)) - { - _toolPageWebViewFailed = true; - loadingPlaceholder.Visibility = Visibility.Collapsed; - nativeFallback.Visibility = Visibility.Visible; - return; - } - var environment = await _webViewEnvironmentFactory.CreateAsync("ToolPages").ConfigureAwait(true); await _toolPageWebView.EnsureCoreWebView2Async(environment); _toolPageWebView.CoreWebView2.Settings.AreDefaultContextMenusEnabled = false; @@ -1826,10 +1812,7 @@ public abstract partial class AdaptiveToolPage : ToolPageBase _toolPageWebView.CoreWebView2.Settings.IsStatusBarEnabled = false; _toolPageWebView.CoreWebView2.Settings.IsZoomControlEnabled = false; _toolPageWebView.CoreWebView2.WebMessageReceived += async (_, args) => await ToolPageWebView_WebMessageReceived(args); - _toolPageWebView.CoreWebView2.SetVirtualHostNameToFolderMapping( - "tool-pages.ymhut.local", - resourceFolder, - CoreWebView2HostResourceAccessKind.Allow); + _runtimeAssets.MapWebViewHost(_toolPageWebView.CoreWebView2, "tool-pages.ymhut.local", "tool-pages"); _toolPageWebView.NavigationCompleted += (_, args) => { if (!args.IsSuccess) @@ -2095,19 +2078,6 @@ public abstract partial class AdaptiveToolPage : ToolPageBase { try { - var assetsRoot = AppServices.GetRequiredService().Assets; - var resourceFolder = Path.Combine(assetsRoot, "tool-results"); - if (!Directory.Exists(resourceFolder)) - { - resourceFolder = Path.Combine(AppContext.BaseDirectory, "Assets", "tool-results"); - } - - if (!Directory.Exists(resourceFolder)) - { - _resultWebViewFailed = true; - return; - } - var environment = await _webViewEnvironmentFactory.CreateAsync("ToolResults").ConfigureAwait(true); await _resultWebView.EnsureCoreWebView2Async(environment); _resultWebView.CoreWebView2.Settings.AreDefaultContextMenusEnabled = false; @@ -2116,10 +2086,7 @@ public abstract partial class AdaptiveToolPage : ToolPageBase _resultWebView.CoreWebView2.Settings.IsStatusBarEnabled = false; _resultWebView.CoreWebView2.Settings.IsZoomControlEnabled = false; _resultWebView.CoreWebView2.WebMessageReceived += async (_, args) => await _toolResultWebBridge.HandleMessageAsync(args); - _resultWebView.CoreWebView2.SetVirtualHostNameToFolderMapping( - "tool-results.ymhut.local", - resourceFolder, - CoreWebView2HostResourceAccessKind.Allow); + _runtimeAssets.MapWebViewHost(_resultWebView.CoreWebView2, "tool-results.ymhut.local", "tool-results"); _resultWebView.NavigationCompleted += (_, args) => { if (args.IsSuccess) diff --git a/src/box-winUI/Views/Tools/GeneratedPearApiToolPages.cs b/src/box-winUI/Views/Tools/GeneratedPearApiToolPages.cs new file mode 100644 index 0000000..170ed84 --- /dev/null +++ b/src/box-winUI/Views/Tools/GeneratedPearApiToolPages.cs @@ -0,0 +1,322 @@ +// +#nullable enable +using YMhut.Box.Core.Api; +using YMhut.Box.Core.Tools; +using YMhut.Box.WinUI.ViewModels.Tools; + +namespace YMhut.Box.WinUI.Views.Tools; + +public sealed partial class ToolPageRegistry +{ + private static partial void RegisterPearApi(ToolPageRegistry registry) + { + registry.Register("ai_latest_news", (module, goBack) => new AiLatestNewsPearApiToolPage(module, goBack)); + registry.Register("pear_ai_image_describe", (module, goBack) => new PearAiImageDescribePearApiToolPage(module, goBack)); + registry.Register("pear_embeddings", (module, goBack) => new PearEmbeddingsPearApiToolPage(module, goBack)); + registry.Register("pear_ai_image_detection", (module, goBack) => new PearAiImageDetectionPearApiToolPage(module, goBack)); + registry.Register("pear_ai_text_safety", (module, goBack) => new PearAiTextSafetyPearApiToolPage(module, goBack)); + registry.Register("pear_ai_dish_recognition", (module, goBack) => new PearAiDishRecognitionPearApiToolPage(module, goBack)); + registry.Register("pear_image_prompt", (module, goBack) => new PearImagePromptPearApiToolPage(module, goBack)); + registry.Register("ai_translation", (module, goBack) => new AiTranslationPearApiToolPage(module, goBack)); + registry.Register("pear_xf_spark", (module, goBack) => new PearXfSparkPearApiToolPage(module, goBack)); + registry.Register("pear_llm_reader", (module, goBack) => new PearLlmReaderPearApiToolPage(module, goBack)); + registry.Register("pear_hot_60_image", (module, goBack) => new PearHot60ImagePearApiToolPage(module, goBack)); + registry.Register("pear_daily_60_image", (module, goBack) => new PearDaily60ImagePearApiToolPage(module, goBack)); + registry.Register("hotboard", (module, goBack) => new HotboardPearApiToolPage(module, goBack)); + registry.Register("pear_world_60", (module, goBack) => new PearWorld60PearApiToolPage(module, goBack)); + registry.Register("oil_price", (module, goBack) => new OilPricePearApiToolPage(module, goBack)); + registry.Register("pear_life_calculator", (module, goBack) => new PearLifeCalculatorPearApiToolPage(module, goBack)); + registry.Register("pear_random_superpower", (module, goBack) => new PearRandomSuperpowerPearApiToolPage(module, goBack)); + registry.Register("pear_random_song", (module, goBack) => new PearRandomSongPearApiToolPage(module, goBack)); + registry.Register("pear_text_tts", (module, goBack) => new PearTextTtsPearApiToolPage(module, goBack)); + registry.Register("pear_ip_details", (module, goBack) => new PearIpDetailsPearApiToolPage(module, goBack)); + registry.Register("pear_gold_price", (module, goBack) => new PearGoldPricePearApiToolPage(module, goBack)); + registry.Register("movie_box_office", (module, goBack) => new MovieBoxOfficePearApiToolPage(module, goBack)); + registry.Register("pear_ruozhiba", (module, goBack) => new PearRuozhibaPearApiToolPage(module, goBack)); + registry.Register("pear_qq_level_image", (module, goBack) => new PearQqLevelImagePearApiToolPage(module, goBack)); + registry.Register("pear_historical_person", (module, goBack) => new PearHistoricalPersonPearApiToolPage(module, goBack)); + registry.Register("pear_countdown", (module, goBack) => new PearCountdownPearApiToolPage(module, goBack)); + registry.Register("pear_answers_book", (module, goBack) => new PearAnswersBookPearApiToolPage(module, goBack)); + registry.Register("city_route_query", (module, goBack) => new CityRouteQueryPearApiToolPage(module, goBack)); + registry.Register("pear_cookbook", (module, goBack) => new PearCookbookPearApiToolPage(module, goBack)); + registry.Register("pear_car_price", (module, goBack) => new PearCarPricePearApiToolPage(module, goBack)); + registry.Register("pear_lottery", (module, goBack) => new PearLotteryPearApiToolPage(module, goBack)); + registry.Register("pear_stock", (module, goBack) => new PearStockPearApiToolPage(module, goBack)); + registry.Register("pear_trademark", (module, goBack) => new PearTrademarkPearApiToolPage(module, goBack)); + registry.Register("pear_poem", (module, goBack) => new PearPoemPearApiToolPage(module, goBack)); + registry.Register("train_query", (module, goBack) => new TrainQueryPearApiToolPage(module, goBack)); + registry.Register("pear_certificate", (module, goBack) => new PearCertificatePearApiToolPage(module, goBack)); + registry.Register("pear_ssl", (module, goBack) => new PearSslPearApiToolPage(module, goBack)); + registry.Register("pear_icp", (module, goBack) => new PearIcpPearApiToolPage(module, goBack)); + registry.Register("pear_blood_type", (module, goBack) => new PearBloodTypePearApiToolPage(module, goBack)); + registry.Register("pear_brainteaser", (module, goBack) => new PearBrainteaserPearApiToolPage(module, goBack)); + registry.Register("pear_synonym_antonym", (module, goBack) => new PearSynonymAntonymPearApiToolPage(module, goBack)); + registry.Register("pear_surname_pun", (module, goBack) => new PearSurnamePunPearApiToolPage(module, goBack)); + registry.Register("pear_website_info", (module, goBack) => new PearWebsiteInfoPearApiToolPage(module, goBack)); + registry.Register("pear_baidu_place", (module, goBack) => new PearBaiduPlacePearApiToolPage(module, goBack)); + registry.Register("pear_audio_transcript", (module, goBack) => new PearAudioTranscriptPearApiToolPage(module, goBack)); + registry.Register("pear_question_search", (module, goBack) => new PearQuestionSearchPearApiToolPage(module, goBack)); + registry.Register("pear_funny_joke", (module, goBack) => new PearFunnyJokePearApiToolPage(module, goBack)); + registry.Register("pear_award", (module, goBack) => new PearAwardPearApiToolPage(module, goBack)); + registry.Register("pear_exchange_rate", (module, goBack) => new PearExchangeRatePearApiToolPage(module, goBack)); + registry.Register("pear_science_news", (module, goBack) => new PearScienceNewsPearApiToolPage(module, goBack)); + registry.Register("pear_kfc", (module, goBack) => new PearKfcPearApiToolPage(module, goBack)); + registry.Register("pear_sensitive_words", (module, goBack) => new PearSensitiveWordsPearApiToolPage(module, goBack)); + registry.Register("pear_ocr", (module, goBack) => new PearOcrPearApiToolPage(module, goBack)); + registry.Register("pear_chinese_conversion", (module, goBack) => new PearChineseConversionPearApiToolPage(module, goBack)); + registry.Register("history_today", (module, goBack) => new HistoryTodayPearApiToolPage(module, goBack)); + registry.Register("pear_rainbow", (module, goBack) => new PearRainbowPearApiToolPage(module, goBack)); + registry.Register("pear_couplet", (module, goBack) => new PearCoupletPearApiToolPage(module, goBack)); + registry.Register("pear_constellation", (module, goBack) => new PearConstellationPearApiToolPage(module, goBack)); + registry.Register("pear_mean_search", (module, goBack) => new PearMeanSearchPearApiToolPage(module, goBack)); + registry.Register("pear_country_population", (module, goBack) => new PearCountryPopulationPearApiToolPage(module, goBack)); + registry.Register("pear_world_population", (module, goBack) => new PearWorldPopulationPearApiToolPage(module, goBack)); + registry.Register("pear_keyword_guide", (module, goBack) => new PearKeywordGuidePearApiToolPage(module, goBack)); + registry.Register("pear_movie_lines", (module, goBack) => new PearMovieLinesPearApiToolPage(module, goBack)); + registry.Register("pear_today_food", (module, goBack) => new PearTodayFoodPearApiToolPage(module, goBack)); + registry.Register("pear_site_index", (module, goBack) => new PearSiteIndexPearApiToolPage(module, goBack)); + registry.Register("pear_short_recovery", (module, goBack) => new PearShortRecoveryPearApiToolPage(module, goBack)); + registry.Register("pear_college", (module, goBack) => new PearCollegePearApiToolPage(module, goBack)); + registry.Register("pear_love_reply", (module, goBack) => new PearLoveReplyPearApiToolPage(module, goBack)); + registry.Register("pear_quirky_dialogue", (module, goBack) => new PearQuirkyDialoguePearApiToolPage(module, goBack)); + registry.Register("pear_classic_joke", (module, goBack) => new PearClassicJokePearApiToolPage(module, goBack)); + registry.Register("pear_love_quote", (module, goBack) => new PearLoveQuotePearApiToolPage(module, goBack)); + registry.Register("pear_translation", (module, goBack) => new PearTranslationPearApiToolPage(module, goBack)); + registry.Register("pear_hitokoto", (module, goBack) => new PearHitokotoPearApiToolPage(module, goBack)); + registry.Register("pear_dujitang", (module, goBack) => new PearDujitangPearApiToolPage(module, goBack)); + registry.Register("baidu_hot", (module, goBack) => new BaiduHotPearApiToolPage(module, goBack)); + registry.Register("bili_hot", (module, goBack) => new BiliHotPearApiToolPage(module, goBack)); + registry.Register("zhihu_hot", (module, goBack) => new ZhihuHotPearApiToolPage(module, goBack)); + } +} + +public sealed class AiLatestNewsPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("ai_latest_news")); +public sealed class AiLatestNewsPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new AiLatestNewsPearApiToolViewModel(module), goBack); + +public sealed class PearAiImageDescribePearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_ai_image_describe")); +public sealed class PearAiImageDescribePearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearAiImageDescribePearApiToolViewModel(module), goBack); + +public sealed class PearEmbeddingsPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_embeddings")); +public sealed class PearEmbeddingsPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearEmbeddingsPearApiToolViewModel(module), goBack); + +public sealed class PearAiImageDetectionPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_ai_image_detection")); +public sealed class PearAiImageDetectionPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearAiImageDetectionPearApiToolViewModel(module), goBack); + +public sealed class PearAiTextSafetyPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_ai_text_safety")); +public sealed class PearAiTextSafetyPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearAiTextSafetyPearApiToolViewModel(module), goBack); + +public sealed class PearAiDishRecognitionPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_ai_dish_recognition")); +public sealed class PearAiDishRecognitionPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearAiDishRecognitionPearApiToolViewModel(module), goBack); + +public sealed class PearImagePromptPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_image_prompt")); +public sealed class PearImagePromptPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearImagePromptPearApiToolViewModel(module), goBack); + +public sealed class AiTranslationPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("ai_translation")); +public sealed class AiTranslationPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new AiTranslationPearApiToolViewModel(module), goBack); + +public sealed class PearXfSparkPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_xf_spark")); +public sealed class PearXfSparkPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearXfSparkPearApiToolViewModel(module), goBack); + +public sealed class PearLlmReaderPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_llm_reader")); +public sealed class PearLlmReaderPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearLlmReaderPearApiToolViewModel(module), goBack); + +public sealed class PearHot60ImagePearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_hot_60_image")); +public sealed class PearHot60ImagePearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearHot60ImagePearApiToolViewModel(module), goBack); + +public sealed class PearDaily60ImagePearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_daily_60_image")); +public sealed class PearDaily60ImagePearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearDaily60ImagePearApiToolViewModel(module), goBack); + +public sealed class HotboardPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("hotboard")); +public sealed class HotboardPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new HotboardPearApiToolViewModel(module), goBack); + +public sealed class PearWorld60PearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_world_60")); +public sealed class PearWorld60PearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearWorld60PearApiToolViewModel(module), goBack); + +public sealed class OilPricePearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("oil_price")); +public sealed class OilPricePearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new OilPricePearApiToolViewModel(module), goBack); + +public sealed class PearLifeCalculatorPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_life_calculator")); +public sealed class PearLifeCalculatorPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearLifeCalculatorPearApiToolViewModel(module), goBack); + +public sealed class PearRandomSuperpowerPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_random_superpower")); +public sealed class PearRandomSuperpowerPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearRandomSuperpowerPearApiToolViewModel(module), goBack); + +public sealed class PearRandomSongPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_random_song")); +public sealed class PearRandomSongPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearRandomSongPearApiToolViewModel(module), goBack); + +public sealed class PearTextTtsPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_text_tts")); +public sealed class PearTextTtsPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearTextTtsPearApiToolViewModel(module), goBack); + +public sealed class PearIpDetailsPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_ip_details")); +public sealed class PearIpDetailsPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearIpDetailsPearApiToolViewModel(module), goBack); + +public sealed class PearGoldPricePearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_gold_price")); +public sealed class PearGoldPricePearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearGoldPricePearApiToolViewModel(module), goBack); + +public sealed class MovieBoxOfficePearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("movie_box_office")); +public sealed class MovieBoxOfficePearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new MovieBoxOfficePearApiToolViewModel(module), goBack); + +public sealed class PearRuozhibaPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_ruozhiba")); +public sealed class PearRuozhibaPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearRuozhibaPearApiToolViewModel(module), goBack); + +public sealed class PearQqLevelImagePearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_qq_level_image")); +public sealed class PearQqLevelImagePearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearQqLevelImagePearApiToolViewModel(module), goBack); + +public sealed class PearHistoricalPersonPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_historical_person")); +public sealed class PearHistoricalPersonPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearHistoricalPersonPearApiToolViewModel(module), goBack); + +public sealed class PearCountdownPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_countdown")); +public sealed class PearCountdownPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearCountdownPearApiToolViewModel(module), goBack); + +public sealed class PearAnswersBookPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_answers_book")); +public sealed class PearAnswersBookPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearAnswersBookPearApiToolViewModel(module), goBack); + +public sealed class CityRouteQueryPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("city_route_query")); +public sealed class CityRouteQueryPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new CityRouteQueryPearApiToolViewModel(module), goBack); + +public sealed class PearCookbookPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_cookbook")); +public sealed class PearCookbookPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearCookbookPearApiToolViewModel(module), goBack); + +public sealed class PearCarPricePearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_car_price")); +public sealed class PearCarPricePearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearCarPricePearApiToolViewModel(module), goBack); + +public sealed class PearLotteryPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_lottery")); +public sealed class PearLotteryPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearLotteryPearApiToolViewModel(module), goBack); + +public sealed class PearStockPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_stock")); +public sealed class PearStockPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearStockPearApiToolViewModel(module), goBack); + +public sealed class PearTrademarkPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_trademark")); +public sealed class PearTrademarkPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearTrademarkPearApiToolViewModel(module), goBack); + +public sealed class PearPoemPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_poem")); +public sealed class PearPoemPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearPoemPearApiToolViewModel(module), goBack); + +public sealed class TrainQueryPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("train_query")); +public sealed class TrainQueryPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new TrainQueryPearApiToolViewModel(module), goBack); + +public sealed class PearCertificatePearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_certificate")); +public sealed class PearCertificatePearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearCertificatePearApiToolViewModel(module), goBack); + +public sealed class PearSslPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_ssl")); +public sealed class PearSslPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearSslPearApiToolViewModel(module), goBack); + +public sealed class PearIcpPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_icp")); +public sealed class PearIcpPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearIcpPearApiToolViewModel(module), goBack); + +public sealed class PearBloodTypePearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_blood_type")); +public sealed class PearBloodTypePearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearBloodTypePearApiToolViewModel(module), goBack); + +public sealed class PearBrainteaserPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_brainteaser")); +public sealed class PearBrainteaserPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearBrainteaserPearApiToolViewModel(module), goBack); + +public sealed class PearSynonymAntonymPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_synonym_antonym")); +public sealed class PearSynonymAntonymPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearSynonymAntonymPearApiToolViewModel(module), goBack); + +public sealed class PearSurnamePunPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_surname_pun")); +public sealed class PearSurnamePunPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearSurnamePunPearApiToolViewModel(module), goBack); + +public sealed class PearWebsiteInfoPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_website_info")); +public sealed class PearWebsiteInfoPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearWebsiteInfoPearApiToolViewModel(module), goBack); + +public sealed class PearBaiduPlacePearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_baidu_place")); +public sealed class PearBaiduPlacePearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearBaiduPlacePearApiToolViewModel(module), goBack); + +public sealed class PearAudioTranscriptPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_audio_transcript")); +public sealed class PearAudioTranscriptPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearAudioTranscriptPearApiToolViewModel(module), goBack); + +public sealed class PearQuestionSearchPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_question_search")); +public sealed class PearQuestionSearchPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearQuestionSearchPearApiToolViewModel(module), goBack); + +public sealed class PearFunnyJokePearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_funny_joke")); +public sealed class PearFunnyJokePearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearFunnyJokePearApiToolViewModel(module), goBack); + +public sealed class PearAwardPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_award")); +public sealed class PearAwardPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearAwardPearApiToolViewModel(module), goBack); + +public sealed class PearExchangeRatePearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_exchange_rate")); +public sealed class PearExchangeRatePearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearExchangeRatePearApiToolViewModel(module), goBack); + +public sealed class PearScienceNewsPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_science_news")); +public sealed class PearScienceNewsPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearScienceNewsPearApiToolViewModel(module), goBack); + +public sealed class PearKfcPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_kfc")); +public sealed class PearKfcPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearKfcPearApiToolViewModel(module), goBack); + +public sealed class PearSensitiveWordsPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_sensitive_words")); +public sealed class PearSensitiveWordsPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearSensitiveWordsPearApiToolViewModel(module), goBack); + +public sealed class PearOcrPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_ocr")); +public sealed class PearOcrPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearOcrPearApiToolViewModel(module), goBack); + +public sealed class PearChineseConversionPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_chinese_conversion")); +public sealed class PearChineseConversionPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearChineseConversionPearApiToolViewModel(module), goBack); + +public sealed class HistoryTodayPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("history_today")); +public sealed class HistoryTodayPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new HistoryTodayPearApiToolViewModel(module), goBack); + +public sealed class PearRainbowPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_rainbow")); +public sealed class PearRainbowPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearRainbowPearApiToolViewModel(module), goBack); + +public sealed class PearCoupletPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_couplet")); +public sealed class PearCoupletPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearCoupletPearApiToolViewModel(module), goBack); + +public sealed class PearConstellationPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_constellation")); +public sealed class PearConstellationPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearConstellationPearApiToolViewModel(module), goBack); + +public sealed class PearMeanSearchPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_mean_search")); +public sealed class PearMeanSearchPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearMeanSearchPearApiToolViewModel(module), goBack); + +public sealed class PearCountryPopulationPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_country_population")); +public sealed class PearCountryPopulationPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearCountryPopulationPearApiToolViewModel(module), goBack); + +public sealed class PearWorldPopulationPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_world_population")); +public sealed class PearWorldPopulationPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearWorldPopulationPearApiToolViewModel(module), goBack); + +public sealed class PearKeywordGuidePearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_keyword_guide")); +public sealed class PearKeywordGuidePearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearKeywordGuidePearApiToolViewModel(module), goBack); + +public sealed class PearMovieLinesPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_movie_lines")); +public sealed class PearMovieLinesPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearMovieLinesPearApiToolViewModel(module), goBack); + +public sealed class PearTodayFoodPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_today_food")); +public sealed class PearTodayFoodPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearTodayFoodPearApiToolViewModel(module), goBack); + +public sealed class PearSiteIndexPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_site_index")); +public sealed class PearSiteIndexPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearSiteIndexPearApiToolViewModel(module), goBack); + +public sealed class PearShortRecoveryPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_short_recovery")); +public sealed class PearShortRecoveryPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearShortRecoveryPearApiToolViewModel(module), goBack); + +public sealed class PearCollegePearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_college")); +public sealed class PearCollegePearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearCollegePearApiToolViewModel(module), goBack); + +public sealed class PearLoveReplyPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_love_reply")); +public sealed class PearLoveReplyPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearLoveReplyPearApiToolViewModel(module), goBack); + +public sealed class PearQuirkyDialoguePearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_quirky_dialogue")); +public sealed class PearQuirkyDialoguePearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearQuirkyDialoguePearApiToolViewModel(module), goBack); + +public sealed class PearClassicJokePearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_classic_joke")); +public sealed class PearClassicJokePearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearClassicJokePearApiToolViewModel(module), goBack); + +public sealed class PearLoveQuotePearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_love_quote")); +public sealed class PearLoveQuotePearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearLoveQuotePearApiToolViewModel(module), goBack); + +public sealed class PearTranslationPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_translation")); +public sealed class PearTranslationPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearTranslationPearApiToolViewModel(module), goBack); + +public sealed class PearHitokotoPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_hitokoto")); +public sealed class PearHitokotoPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearHitokotoPearApiToolViewModel(module), goBack); + +public sealed class PearDujitangPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("pear_dujitang")); +public sealed class PearDujitangPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new PearDujitangPearApiToolViewModel(module), goBack); + +public sealed class BaiduHotPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("baidu_hot")); +public sealed class BaiduHotPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new BaiduHotPearApiToolViewModel(module), goBack); + +public sealed class BiliHotPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("bili_hot")); +public sealed class BiliHotPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new BiliHotPearApiToolViewModel(module), goBack); + +public sealed class ZhihuHotPearApiToolViewModel(IToolModule module) : PearApiToolViewModel(module, PearApiCatalog.GetRequired("zhihu_hot")); +public sealed class ZhihuHotPearApiToolPage(IToolModule module, Action? goBack = null) : PearApiToolPageBase(module, new ZhihuHotPearApiToolViewModel(module), goBack); diff --git a/src/box-winUI/Views/Tools/GeneratedToolPages.cs b/src/box-winUI/Views/Tools/GeneratedToolPages.cs index a35d31c..157591d 100644 --- a/src/box-winUI/Views/Tools/GeneratedToolPages.cs +++ b/src/box-winUI/Views/Tools/GeneratedToolPages.cs @@ -70,9 +70,6 @@ public sealed partial class ToolPageRegistry registry.Register("dns_record_lookup", (module, goBack) => new DnsRecordLookupToolPage(module, goBack)); registry.Register("weather", (module, goBack) => new WeatherToolPage(module, goBack)); registry.Register("hotboard", (module, goBack) => new HotboardToolPage(module, goBack)); - registry.Register("bili_hot", (module, goBack) => new BiliHotToolPage(module, goBack)); - registry.Register("baidu_hot", (module, goBack) => new BaiduHotToolPage(module, goBack)); - registry.Register("zhihu_hot", (module, goBack) => new ZhihuHotToolPage(module, goBack)); registry.Register("cctv_news", (module, goBack) => new CctvNewsToolPage(module, goBack)); registry.Register("tech_news", (module, goBack) => new TechNewsToolPage(module, goBack)); registry.Register("ai_latest_news", (module, goBack) => new AiLatestNewsToolPage(module, goBack)); diff --git a/src/box-winUI/Views/Tools/PearApiToolPageBase.cs b/src/box-winUI/Views/Tools/PearApiToolPageBase.cs new file mode 100644 index 0000000..b81133d --- /dev/null +++ b/src/box-winUI/Views/Tools/PearApiToolPageBase.cs @@ -0,0 +1,768 @@ +using System.Text.Json; +using Microsoft.UI.Text; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Automation; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Media.Imaging; +using Windows.ApplicationModel.DataTransfer; +using Windows.Media.Core; +using Windows.Storage.Pickers; +using Windows.Storage.Streams; +using WinRT.Interop; +using YMhut.Box.Core.Api; +using YMhut.Box.Core.Settings; +using YMhut.Box.Core.Tools; +using YMhut.Box.WinUI.Services; +using YMhut.Box.WinUI.Controls; +using YMhut.Box.WinUI.ViewModels.Tools; + +namespace YMhut.Box.WinUI.Views.Tools; + +public abstract class PearApiToolPageBase : ToolPageBase +{ + private readonly Action? _goBack; + private readonly PearApiToolViewModel _viewModel; + private readonly PearApiToolDefinition _definition; + private readonly IPearApiClient _client = AppServices.GetRequiredService(); + private readonly ISettingsService _settings = AppServices.GetRequiredService(); + private readonly IToolUiDefinitionStore _definitionStore = AppServices.GetRequiredService(); + private readonly IShellDialogService _dialogService = AppServices.GetRequiredService(); + private readonly Dictionary _inputs = new(StringComparer.OrdinalIgnoreCase); + private readonly List _mediaStreams = []; + private readonly StackPanel _inputPanel = new() { Spacing = 12 }; + private readonly StackPanel _resultPanel = new() { Spacing = 8 }; + private readonly TextBlock _status = ModernUi.Text("等待查询", 12.5, FontWeights.SemiBold, ModernUi.TextSecondary, maxLines: 2); + private readonly ProgressRing _progress = new() { Width = 20, Height = 20, Visibility = Visibility.Collapsed }; + private readonly Button _runButton; + private readonly Button _cancelButton; + private readonly Grid _workGrid = new() { ColumnSpacing = 16, RowSpacing = 16 }; + private readonly Border _inputSurface; + private readonly Border _resultSurface; + private CancellationTokenSource? _requestCts; + private string _rawResult = string.Empty; + private bool _definitionValidated; + + protected PearApiToolPageBase( + IToolModule module, + PearApiToolViewModel viewModel, + Action? goBack = null) + { + _goBack = goBack; + _viewModel = viewModel; + _definition = viewModel.Definition; + BindModule(module); + Background = ModernUi.AppBackground; + + BuildInputs(); + _runButton = ModernUi.PillButton(ActionLabel(_definition.ResultKind), "\uE768", RunAsync, primary: true); + _cancelButton = ModernUi.PillButton("取消", "\uE711", CancelRequest); + _cancelButton.IsEnabled = false; + AutomationProperties.SetName(_runButton, $"运行{_definition.Name}"); + AutomationProperties.SetHelpText(_runButton, "仅访问固定的 PearAPI 免 Key 接口"); + + _inputSurface = BuildInputSurface(); + _resultSurface = BuildResultSurface(); + Content = BuildContent(); + Loaded += OnLoaded; + Unloaded += OnUnloaded; + SizeChanged += (_, e) => ApplyResponsiveLayout(e.NewSize.Width); + } + + public PearApiToolDefinition ApiDefinition => _definition; + + private IReadOnlyList VisibleParameters => + _definition.Parameters.Where(parameter => !PearApiPresentationSanitizer.IsHiddenField(parameter.Name)).ToArray(); + + private UIElement BuildContent() + { + var header = new Grid + { + MinHeight = 58, + Padding = new Thickness(16, 8, 18, 8), + ColumnSpacing = 12, + Background = ModernUi.Surface, + BorderBrush = ModernUi.Stroke, + BorderThickness = new Thickness(0, 0, 0, 1) + }; + header.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); + header.ColumnDefinitions.Add(new ColumnDefinition()); + header.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); + var back = ModernUi.IconButton("\uE72B", "返回联网工具", () => _goBack?.Invoke()); + back.Width = 36; + back.Height = 36; + header.Children.Add(back); + var title = new StackPanel + { + Spacing = 1, + VerticalAlignment = VerticalAlignment.Center, + Children = + { + ModernUi.Text(_definition.Name, 18, FontWeights.SemiBold, maxLines: 1), + ModernUi.Text($"PearAPI / {_definition.Category} / API {_definition.ApiId}", 11.5, foreground: ModernUi.TextSecondary, maxLines: 1) + } + }; + Grid.SetColumn(title, 1); + header.Children.Add(title); + var privacy = ModernUi.Badge(PrivacyLabel(_definition.PrivacyClass), ModernUi.Accent, ModernUi.AccentSoft); + privacy.VerticalAlignment = VerticalAlignment.Center; + Grid.SetColumn(privacy, 2); + header.Children.Add(privacy); + + _workGrid.ColumnDefinitions.Add(new ColumnDefinition()); + _workGrid.ColumnDefinitions.Add(new ColumnDefinition()); + _workGrid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); + _workGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) }); + _workGrid.Children.Add(_inputSurface); + Grid.SetColumn(_resultSurface, 1); + _workGrid.Children.Add(_resultSurface); + + var body = new ScrollViewer + { + Content = _workGrid, + Padding = new Thickness(18), + VerticalScrollBarVisibility = ScrollBarVisibility.Auto, + HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled, + VerticalScrollMode = ScrollMode.Enabled, + ZoomMode = ZoomMode.Disabled + }; + var root = new Grid(); + root.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); + root.RowDefinitions.Add(new RowDefinition()); + root.Children.Add(header); + Grid.SetRow(body, 1); + root.Children.Add(body); + return root; + } + + private Border BuildInputSurface() + { + var actions = new StackPanel { Orientation = Orientation.Horizontal, Spacing = 8 }; + actions.Children.Add(_runButton); + actions.Children.Add(_cancelButton); + actions.Children.Add(_progress); + var content = new StackPanel + { + Spacing = 14, + Children = + { + ModernUi.Text("查询与参数", 15, FontWeights.SemiBold, maxLines: 1), + ModernUi.Text(_definition.Description, 12.5, foreground: ModernUi.TextSecondary, maxLines: 4), + BuildPrivacyNotice(), + _inputPanel, + actions, + _status + } + }; + return ModernUi.Card(content, new Thickness(16), radius: 8, background: ModernUi.Surface); + } + + private Border BuildResultSurface() + { + var toolbar = new Grid { ColumnSpacing = 8 }; + toolbar.ColumnDefinitions.Add(new ColumnDefinition()); + toolbar.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); + toolbar.Children.Add(ModernUi.Text(ResultTitle(_definition.ResultKind), 15, FontWeights.SemiBold, maxLines: 1)); + var copy = ModernUi.IconButton("\uE8C8", "复制结果", CopyResult); + Grid.SetColumn(copy, 1); + toolbar.Children.Add(copy); + _resultPanel.Children.Add(BuildEmptyState()); + var resultScroll = new ScrollViewer + { + Content = _resultPanel, + MinHeight = 320, + VerticalScrollBarVisibility = ScrollBarVisibility.Auto, + HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled + }; + return ModernUi.Card(new StackPanel { Spacing = 12, Children = { toolbar, resultScroll } }, new Thickness(16), radius: 8, background: ModernUi.Surface); + } + + private UIElement BuildPrivacyNotice() + { + var message = _definition.PrivacyClass switch + { + PearApiPrivacyClass.Public => "无输入公共请求,可在本次运行期间短时缓存。", + PearApiPrivacyClass.FileUpload => "文件仅在你确认并点击运行后发送至 PearAPI,不写入本地缓存。", + PearApiPrivacyClass.UserUrl => "网址会发送至 PearAPI;回环、私网和非 HTTP(S) 地址会被拒绝。", + PearApiPrivacyClass.Financial => "查询条件会发送至 PearAPI,结果仅供参考且不会持久化缓存。", + _ => "输入内容会发送至 PearAPI,不写入参数日志或本地缓存。" + }; + return new InfoBar + { + IsOpen = true, + IsClosable = false, + Severity = _definition.PrivacyClass is PearApiPrivacyClass.FileUpload or PearApiPrivacyClass.Financial + ? InfoBarSeverity.Warning + : InfoBarSeverity.Informational, + Title = "数据边界", + Message = message + }; + } + + private void BuildInputs() + { + if (!_definition.IsAvailableWithoutKey) + { + _inputPanel.Children.Add(new InfoBar + { + IsOpen = true, + IsClosable = false, + Severity = InfoBarSeverity.Warning, + Title = "当前不可用", + Message = _definition.AvailabilityNote + }); + return; + } + + foreach (var parameter in VisibleParameters) + { + var control = CreateInput(parameter); + _inputs[parameter.Name] = control; + _inputPanel.Children.Add(control); + } + + if (VisibleParameters.Count == 0) + { + _inputPanel.Children.Add(ModernUi.Text("此接口无需输入,点击刷新即可获取最新结果。", 13, foreground: ModernUi.TextSecondary)); + } + } + + private FrameworkElement CreateInput(PearApiParameterDefinition parameter) + { + var label = parameter.Required ? $"{parameter.DisplayName} *" : parameter.DisplayName; + if (parameter.Kind == PearApiParameterKind.Choice) + { + var combo = new ComboBox + { + Header = label, + PlaceholderText = parameter.Description, + HorizontalAlignment = HorizontalAlignment.Stretch, + ItemsSource = parameter.Options, + SelectedItem = parameter.Options?.FirstOrDefault(option => string.Equals(option, parameter.DefaultValue, StringComparison.OrdinalIgnoreCase)) + }; + if (combo.SelectedItem is null && parameter.Options is { Count: > 0 }) combo.SelectedIndex = 0; + return combo; + } + + if (parameter.Kind == PearApiParameterKind.Date) + { + return new CalendarDatePicker + { + Header = label, + PlaceholderText = parameter.Description, + HorizontalAlignment = HorizontalAlignment.Stretch + }; + } + + if (parameter.Kind == PearApiParameterKind.Number) + { + _ = double.TryParse(parameter.DefaultValue, out var number); + return new NumberBox + { + Header = label, + PlaceholderText = parameter.Description, + Value = string.IsNullOrWhiteSpace(parameter.DefaultValue) ? double.NaN : number, + SpinButtonPlacementMode = NumberBoxSpinButtonPlacementMode.Compact, + HorizontalAlignment = HorizontalAlignment.Stretch + }; + } + + if (parameter.Kind == PearApiParameterKind.File) + { + var path = new TextBox + { + Header = label, + PlaceholderText = parameter.Description, + IsReadOnly = true, + HorizontalAlignment = HorizontalAlignment.Stretch + }; + var choose = ModernUi.PillButton("选择文件", "\uE8E5", async () => await ChooseFileAsync(path)); + choose.HorizontalAlignment = HorizontalAlignment.Left; + return new StackPanel { Spacing = 7, Children = { path, choose } }; + } + + return new TextBox + { + Header = label, + PlaceholderText = parameter.Description, + Text = parameter.DefaultValue, + AcceptsReturn = parameter.Kind == PearApiParameterKind.MultilineText, + TextWrapping = TextWrapping.Wrap, + MinHeight = parameter.Kind == PearApiParameterKind.MultilineText ? 112 : 0, + MaxLength = parameter.MaxLength, + HorizontalAlignment = HorizontalAlignment.Stretch + }; + } + + private async void OnLoaded(object sender, RoutedEventArgs e) + { + AttachDialogRoot(); + var uiDefinition = await _definitionStore.GetAsync(_viewModel.Module); + _definitionValidated = !uiDefinition.IsFallback; + RestoreState(); + UpdateRunState(); + } + + private void OnUnloaded(object sender, RoutedEventArgs e) + { + CancelRequest(); + _ = SaveStateAsync(); + foreach (var stream in _mediaStreams) stream.Dispose(); + _mediaStreams.Clear(); + } + + private async void RunAsync() + { + if (!_definitionValidated || !_definition.IsAvailableWithoutKey || !await EnsureNoticeAcceptedAsync()) + { + return; + } + + var values = CollectValues(); + var filePath = _viewModel.SelectedFilePath; + var uploadConfirmed = false; + if (!string.IsNullOrWhiteSpace(filePath)) + { + uploadConfirmed = await ConfirmUploadAsync(filePath); + if (!uploadConfirmed) return; + } + + await SaveStateAsync(); + _requestCts?.Cancel(); + _requestCts?.Dispose(); + _requestCts = new CancellationTokenSource(); + SetBusy(true); + try + { + var response = await _client.SendAsync(new PearApiRequest(_definition.ToolId, values, filePath, uploadConfirmed), _requestCts.Token); + var sanitizedContent = PearApiPresentationSanitizer.SanitizeJson(response.Content); + _rawResult = sanitizedContent; + if (!response.Success) + { + ShowError(response.Error ?? "请求失败。"); + return; + } + + await RenderResultAsync(response with { Content = sanitizedContent }); + _status.Text = response.IsFromCache + ? "已显示本次运行期间的短时缓存结果。" + : $"请求完成 · HTTP {response.StatusCode} · {response.Elapsed.TotalMilliseconds:0} ms"; + } + finally + { + SetBusy(false); + } + } + + private void CancelRequest() => _requestCts?.Cancel(); + + private void SetBusy(bool value) + { + _progress.IsActive = value; + _progress.Visibility = value ? Visibility.Visible : Visibility.Collapsed; + _runButton.IsEnabled = !value && _definitionValidated && _definition.IsAvailableWithoutKey; + _cancelButton.IsEnabled = value; + _status.Text = value ? "正在请求 PearAPI..." : _status.Text; + } + + private void UpdateRunState() + { + _runButton.IsEnabled = _definitionValidated && _definition.IsAvailableWithoutKey; + if (!_definitionValidated) + { + _status.Text = "页面定义缺失或损坏,已禁用联网动作。"; + } + else if (!_definition.IsAvailableWithoutKey) + { + _status.Text = _definition.AvailabilityNote; + } + } + + private Dictionary CollectValues() + { + var values = new Dictionary(StringComparer.OrdinalIgnoreCase); + foreach (var parameter in VisibleParameters) + { + if (!_inputs.TryGetValue(parameter.Name, out var input) || parameter.Kind == PearApiParameterKind.File) continue; + var value = input switch + { + TextBox text => text.Text, + ComboBox combo => combo.SelectedItem?.ToString() ?? string.Empty, + NumberBox number when !double.IsNaN(number.Value) => number.Value.ToString(System.Globalization.CultureInfo.InvariantCulture), + CalendarDatePicker date when date.Date is { } selected => selected.ToString("yyyy-MM-dd"), + _ => string.Empty + }; + values[parameter.Name] = value.Trim(); + _viewModel.Values[parameter.Name] = value.Trim(); + } + return values; + } + + private async Task ChooseFileAsync(TextBox pathBox) + { + var picker = new FileOpenPicker { SuggestedStartLocation = PickerLocationId.PicturesLibrary }; + picker.FileTypeFilter.Add(".png"); + picker.FileTypeFilter.Add(".jpg"); + picker.FileTypeFilter.Add(".jpeg"); + picker.FileTypeFilter.Add(".webp"); + picker.FileTypeFilter.Add(".gif"); + if (_definition.ToolId == "pear_audio_transcript") + { + picker.FileTypeFilter.Add(".mp3"); + picker.FileTypeFilter.Add(".wav"); + picker.FileTypeFilter.Add(".ogg"); + picker.FileTypeFilter.Add(".mp4"); + picker.FileTypeFilter.Add(".webm"); + } + InitializeWithWindow.Initialize(picker, WindowNative.GetWindowHandle(App.CurrentWindow)); + var file = await picker.PickSingleFileAsync(); + if (file is null) return; + _viewModel.SelectedFilePath = file.Path; + pathBox.Text = file.Name; + } + + private async Task EnsureNoticeAcceptedAsync() + { + if (string.Equals(_settings.Current.PearApiNoticeVersion, AgreementDocument.PearApiNoticeVersion, StringComparison.Ordinal)) + { + return true; + } + + AttachDialogRoot(); + + var content = new StackPanel + { + Spacing = 10, + Children = + { + ModernUi.Text("联网工具使用固定的 PearAPI 免费接口,不携带 API Key,也不会自动切换到付费服务。", 13, maxLines: 4), + ModernUi.Text("运行工具时,页面明确列出的文本、网址、金融查询条件或你主动选择的文件会发送至 PearAPI。请求参数、上传内容和响应正文不写入应用日志。", 13, foreground: ModernUi.TextSecondary, maxLines: 6), + ModernUi.Text("第三方服务可能变更、限流或返回不准确内容;请勿提交个人隐私、机密文件或受版权限制的内容,结果仅供学习和参考。", 13, foreground: ModernUi.TextSecondary, maxLines: 5) + } + }; + var dialog = new ContentDialog + { + Title = "PearAPI 联网工具使用须知", + Content = content, + PrimaryButtonText = "同意并继续", + CloseButtonText = "取消", + DefaultButton = ContentDialogButton.Primary + }; + if (await _dialogService.ShowAsync(dialog) != ContentDialogResult.Primary) return false; + await _settings.UpdateAsync(settings => settings.PearApiNoticeVersion = AgreementDocument.PearApiNoticeVersion); + return true; + } + + private async Task ConfirmUploadAsync(string path) + { + AttachDialogRoot(); + var info = new FileInfo(path); + var dialog = new ContentDialog + { + Title = "确认发送文件", + Content = ModernUi.Text($"文件“{info.Name}”({FormatBytes(info.Length)})将发送至 PearAPI 处理。请确认文件不包含个人隐私、账号凭据或机密内容。", 13, maxLines: 6), + PrimaryButtonText = "发送并处理", + CloseButtonText = "取消", + DefaultButton = ContentDialogButton.Close + }; + return await _dialogService.ShowAsync(dialog) == ContentDialogResult.Primary; + } + + private void AttachDialogRoot() + { + // PearAPI pages can be created by navigation after the main window's + // global dialog service was initialized. Bind the live page root so + // ContentDialog never falls back to the not-yet-loaded toast host. + if (XamlRoot is not null) + { + _dialogService.Attach(XamlRoot); + } + } + + private async Task RenderResultAsync(PearApiResponse response) + { + _resultPanel.Children.Clear(); + if (response.BinaryContent is { Length: > 0 }) + { + await RenderBinaryAsync(response.BinaryContent, response.ContentType); + return; + } + + if (string.IsNullOrWhiteSpace(response.Content)) + { + _resultPanel.Children.Add(BuildEmptyState("接口返回空结果。")); + return; + } + + try + { + using var document = JsonDocument.Parse(response.Content); + var value = Unwrap(document.RootElement); + if (_definition.ResultKind == PearApiResultKind.Text) + { + _resultPanel.Children.Add(BuildTextResult(ExtractText(value))); + } + else if (value.ValueKind == JsonValueKind.Array) + { + RenderArray(value); + } + else if (value.ValueKind == JsonValueKind.Object) + { + RenderObject(value); + } + else + { + _resultPanel.Children.Add(BuildTextResult(value.ToString())); + } + } + catch (JsonException) + { + _resultPanel.Children.Add(BuildTextResult(response.Content)); + } + } + + private async Task RenderBinaryAsync(byte[] bytes, string contentType) + { + var stream = new InMemoryRandomAccessStream(); + using (var writer = new DataWriter(stream)) + { + writer.WriteBytes(bytes); + await writer.StoreAsync(); + writer.DetachStream(); + } + stream.Seek(0); + _mediaStreams.Add(stream); + if (contentType.StartsWith("image/", StringComparison.OrdinalIgnoreCase)) + { + var image = new BitmapImage(); + await image.SetSourceAsync(stream); + _resultPanel.Children.Add(new Image { Source = image, MaxHeight = 620, Stretch = Microsoft.UI.Xaml.Media.Stretch.Uniform }); + return; + } + if (contentType.StartsWith("audio/", StringComparison.OrdinalIgnoreCase) || contentType.StartsWith("video/", StringComparison.OrdinalIgnoreCase)) + { + _resultPanel.Children.Add(new MediaPlayerElement + { + AreTransportControlsEnabled = true, + AutoPlay = false, + Source = MediaSource.CreateFromStream(stream, contentType), + MinHeight = 96 + }); + return; + } + _resultPanel.Children.Add(BuildTextResult($"收到 {FormatBytes(bytes.Length)} 二进制结果。")); + } + + private void RenderArray(JsonElement array) + { + var items = array.EnumerateArray().Take(200).ToArray(); + if (items.Length == 0) + { + _resultPanel.Children.Add(BuildEmptyState("未返回匹配项目。")); + return; + } + var index = 1; + foreach (var item in items) + { + var title = item.ValueKind == JsonValueKind.Object + ? FindString(item, "title", "name", "question", "content") + : item.ToString(); + var body = item.ValueKind == JsonValueKind.Object ? CompactObject(item, 8) : item.ToString(); + _resultPanel.Children.Add(BuildResultRow(index++, title, body)); + } + } + + private void RenderObject(JsonElement value) + { + var array = value.EnumerateObject().FirstOrDefault(property => property.Value.ValueKind == JsonValueKind.Array); + if (array.Value.ValueKind == JsonValueKind.Array) + { + RenderArray(array.Value); + return; + } + foreach (var property in value.EnumerateObject().Take(80)) + { + if (property.Value.ValueKind is JsonValueKind.Object or JsonValueKind.Array) + { + _resultPanel.Children.Add(BuildKeyValue(property.Name, CompactObject(property.Value, 12))); + } + else + { + _resultPanel.Children.Add(BuildKeyValue(property.Name, property.Value.ToString())); + } + } + } + + private static UIElement BuildResultRow(int index, string title, string body) + { + var grid = new Grid { ColumnSpacing = 10 }; + grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(32) }); + grid.ColumnDefinitions.Add(new ColumnDefinition()); + grid.Children.Add(RankBadgeFactory.Create(index, 30)); + var text = new StackPanel + { + Spacing = 3, + Children = + { + ModernUi.Text(string.IsNullOrWhiteSpace(title) ? $"项目 {index}" : title, 13.5, FontWeights.SemiBold, maxLines: 2), + ModernUi.Text(body, 12, foreground: ModernUi.TextSecondary, maxLines: 6) + } + }; + Grid.SetColumn(text, 1); + grid.Children.Add(text); + return ModernUi.Card(grid, new Thickness(10), radius: 6, background: ModernUi.SurfaceAlt); + } + + private static UIElement BuildKeyValue(string key, string value) + { + var grid = new Grid { ColumnSpacing = 12 }; + grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(128) }); + grid.ColumnDefinitions.Add(new ColumnDefinition()); + grid.Children.Add(ModernUi.Text(key, 12, FontWeights.SemiBold, ModernUi.TextSecondary, maxLines: 2)); + var result = ModernUi.Text(value, 12.5, maxLines: 10); + result.TextWrapping = TextWrapping.Wrap; + Grid.SetColumn(result, 1); + grid.Children.Add(result); + return grid; + } + + private static UIElement BuildTextResult(string text) + { + var block = ModernUi.Text(string.IsNullOrWhiteSpace(text) ? "接口返回空文本。" : text, 13.5, maxLines: 200); + block.TextWrapping = TextWrapping.Wrap; + block.IsTextSelectionEnabled = true; + return block; + } + + private static UIElement BuildEmptyState(string text = "运行工具后,结构化结果会显示在这里。") + => new InfoBar { IsOpen = true, IsClosable = false, Severity = InfoBarSeverity.Informational, Message = text }; + + private void ShowError(string message) + { + _resultPanel.Children.Clear(); + _resultPanel.Children.Add(new InfoBar { IsOpen = true, IsClosable = false, Severity = InfoBarSeverity.Error, Title = "请求未完成", Message = message }); + _status.Text = message; + } + + private void CopyResult() + { + if (string.IsNullOrWhiteSpace(_rawResult)) return; + var package = new DataPackage(); + package.SetText(_rawResult); + Clipboard.SetContent(package); + ToastService.Show("结果已复制", ToastKind.Success, TimeSpan.FromSeconds(2)); + } + + private void RestoreState() + { + var state = _settings.GetToolUiState(_definition.ToolId); + foreach (var parameter in VisibleParameters) + { + if (!state.Values.TryGetValue(parameter.Name, out var value) || !_inputs.TryGetValue(parameter.Name, out var input)) continue; + switch (input) + { + case TextBox text: + text.Text = value; + break; + case ComboBox combo: + combo.SelectedItem = combo.Items.FirstOrDefault(item => string.Equals(item?.ToString(), value, StringComparison.OrdinalIgnoreCase)); + break; + case NumberBox number when double.TryParse(value, System.Globalization.CultureInfo.InvariantCulture, out var parsed): + number.Value = parsed; + break; + case CalendarDatePicker date when DateTimeOffset.TryParse(value, out var parsedDate): + date.Date = parsedDate; + break; + } + } + } + + private Task SaveStateAsync() + => _settings.SaveToolUiStateAsync(_definition.ToolId, new ToolUiPageState { Values = CollectValues() }); + + private void ApplyResponsiveLayout(double width) + { + var wide = width >= 900; + _workGrid.ColumnDefinitions[0].Width = new GridLength(wide ? 0.92 : 1, GridUnitType.Star); + _workGrid.ColumnDefinitions[1].Width = wide ? new GridLength(1.28, GridUnitType.Star) : new GridLength(0); + Grid.SetColumn(_inputSurface, 0); + Grid.SetRow(_inputSurface, 0); + Grid.SetColumn(_resultSurface, wide ? 1 : 0); + Grid.SetRow(_resultSurface, wide ? 0 : 1); + _resultSurface.Margin = wide ? new Thickness(0) : new Thickness(0, 0, 0, 8); + } + + private static JsonElement Unwrap(JsonElement value) + { + if (value.ValueKind != JsonValueKind.Object) return value; + foreach (var name in new[] { "data", "result", "list", "items", "news" }) + { + if (value.TryGetProperty(name, out var nested) && nested.ValueKind is JsonValueKind.Object or JsonValueKind.Array) return nested; + } + return value; + } + + private static string ExtractText(JsonElement value) + { + if (value.ValueKind == JsonValueKind.String) return value.GetString() ?? string.Empty; + if (value.ValueKind == JsonValueKind.Object) + { + var candidate = FindString(value, "text", "content", "message", "msg", "answer", "translation", "result", "data"); + if (!string.IsNullOrWhiteSpace(candidate)) return candidate; + } + return value.ToString(); + } + + private static string FindString(JsonElement value, params string[] names) + { + if (value.ValueKind != JsonValueKind.Object) return string.Empty; + foreach (var name in names) + { + if (value.TryGetProperty(name, out var property) && property.ValueKind is JsonValueKind.String or JsonValueKind.Number) + return property.ToString(); + } + return string.Empty; + } + + private static string CompactObject(JsonElement value, int limit) + { + if (value.ValueKind == JsonValueKind.Object) + return string.Join(" · ", value.EnumerateObject().Take(limit).Select(property => $"{property.Name}: {property.Value}")); + if (value.ValueKind == JsonValueKind.Array) + return string.Join(" · ", value.EnumerateArray().Take(limit).Select(item => item.ToString())); + return value.ToString(); + } + + private static string ActionLabel(PearApiResultKind kind) => kind switch + { + PearApiResultKind.Audio => "生成音频", + PearApiResultKind.Image => "生成或查询", + PearApiResultKind.News or PearApiResultKind.RankedList => "刷新", + _ => "查询" + }; + + private static string ResultTitle(PearApiResultKind kind) => kind switch + { + PearApiResultKind.Audio => "音频结果", + PearApiResultKind.Image => "图像预览", + PearApiResultKind.News => "资讯列表", + PearApiResultKind.RankedList => "排行结果", + PearApiResultKind.Table => "数据表", + _ => "查询结果" + }; + + private static string PrivacyLabel(PearApiPrivacyClass privacy) => privacy switch + { + PearApiPrivacyClass.Public => "公共数据", + PearApiPrivacyClass.FileUpload => "文件上传", + PearApiPrivacyClass.UserUrl => "网址传输", + PearApiPrivacyClass.Financial => "金融参考", + _ => "文本传输" + }; + + private static string FormatBytes(long value) + { + if (value >= 1024 * 1024) return $"{value / 1024d / 1024d:0.##} MiB"; + if (value >= 1024) return $"{value / 1024d:0.##} KiB"; + return $"{value} B"; + } +} diff --git a/src/box-winUI/Views/Tools/ToolPageRegistry.cs b/src/box-winUI/Views/Tools/ToolPageRegistry.cs index bccd8d8..6029bf0 100644 --- a/src/box-winUI/Views/Tools/ToolPageRegistry.cs +++ b/src/box-winUI/Views/Tools/ToolPageRegistry.cs @@ -115,11 +115,14 @@ public sealed partial class ToolPageRegistry : IToolPageFactory { var registry = new ToolPageRegistry(); RegisterGenerated(registry); + RegisterPearApi(registry); return registry; } static partial void RegisterGenerated(ToolPageRegistry registry); + private static partial void RegisterPearApi(ToolPageRegistry registry); + private sealed record ToolPageDescriptor( string Id, Type PageType, diff --git a/src/box-winUI/YMhut.Box.WinUI.csproj b/src/box-winUI/YMhut.Box.WinUI.csproj index a56fb01..4d4d7f4 100644 --- a/src/box-winUI/YMhut.Box.WinUI.csproj +++ b/src/box-winUI/YMhut.Box.WinUI.csproj @@ -17,6 +17,7 @@ YMhutBox zh-CN $([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)..\..\build\music-api')) + $([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)..\..\build\runtime-assets')) zh-CN;en-US @@ -26,6 +27,19 @@ + + + + + + + + + + @@ -49,7 +63,7 @@ win-x64 MSIX - true + true false Never none @@ -71,50 +85,31 @@ - + - - - - - - - - - YMhut.Box.WinUI.Assets.tool-results.vendor.%(Filename)%(Extension) + + + YMhut.Box.WinUI.Assets.app_icon.ico - + + + + Assets\runtime-assets.dat + PreserveNewest + + + Assets\data\ymhut-data.ybin + PreserveNewest + YMhut.Box.WinUI.version.json - - Assets\download.svg - PreserveNewest - - - - - Assets\icons\%(RecursiveDir)%(FileName)%(Extension) - PreserveNewest - - - Assets\images\%(RecursiveDir)%(FileName)%(Extension) - PreserveNewest - - - - Assets\data\%(RecursiveDir)%(FileName)%(Extension) - PreserveNewest - - - Assets\data\sanguosha\%(RecursiveDir)%(FileName)%(Extension) - PreserveNewest - - - Assets\data\rankings\%(Filename)%(Extension) + + Assets\data\tool-ui\%(FileName)%(Extension) PreserveNewest @@ -134,6 +129,28 @@ PreserveNewest + + + tauri-host\runtime.json + PreserveNewest + PreserveNewest + + + tauri-host\template.ymtemplate + PreserveNewest + PreserveNewest + + + tauri-host\LICENSES.txt + PreserveNewest + PreserveNewest + + + tauri-host\template\%(RecursiveDir)%(FileName)%(Extension) + PreserveNewest + PreserveNewest + +

    @&8Gj61FM-)9|8dECMAt2tW3#^+5E+l*MC6cHFXO~kJz>1_fSZbd;1Vb5?h9PGjXLiJ z=eq)r7xfy=f6EUe!=0ztBY%qJ8i&exaR7I+HcaMXuRPUy-t%ra_7E3u>Ew71t%wv( zzW@!nMd2fO1!emJ(6q zFC-+Jx)bD>7jFiPc;I0+c$E1^X-SDBpFL2BZFx2o7?>~B@cqzoxE6^~5zV(>vZp*) zD4X7W;C$fzEVal2-_o6ga}enV)Oo}uQvmfRqA$G941YM#CDXeLQtlI+2SjEWiVFi~|BnuQIhbJ9ToNa?fZW|K;GNuS*oaoB$p8 z@S*0z(fmQkm*WuGVbTR^nZ%mj&0@8^F4aBXHh2h1InAiOBka z9(&;?0bAihsH(p$&tu4o|DY&2bt|GW?+LX)gYIbrrG(vqcjIW%+# F?$kWk=4Ai? literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_quirky_dialogue.dat b/assets/data/tool-ui/pear_quirky_dialogue.dat new file mode 100644 index 0000000000000000000000000000000000000000..c81a6474a919db6d736454b7e487b691eca94fb8 GIT binary patch literal 1471 zcmV;w1wi^)O-NN#RY@@d6aa8#VRBz_b!l>Id0%8{VQg<_b!DN_4miOYxWrDB*VVoR zPk9l~r04rdz%E2+-AZ-Kr(f^SIjSLHCFPR*i8lGhS?7bK?&q3m^^!HwSwT@eWTXwY zV1@@$C<5tx`g^RBgs;N;kuGZhDtjR;KWbh>RZSid1{M^GdIljF$%QM{3!!1I|J_d| zoo9ZX1-8YVf0xBHYB220Q|Vq!bo6?{2g@@)xe)(J*B*U~t^rZXSzGmT`_rX9qb0#z zV<2v(JTq?uF&?CXn*H0DTPlG25qzTfd+{vmX~YDF(9q<_HEpEQnAQMdRXdB<4eV&y z1E`TVc(<`ePRd{?m7u-CBOW8c2FC3-@p~D>puK6)lOYo)BB;5VBd@h^zkvkTY>0XD zmnm=&_jsq`65PQU^tCAH{48lm0US36tXq8A&hc)F4sNwyU!MOs&Ib;HM>52%HOQKA z2O_pZ(ZK>Lmd>&PkN}EOZ>ucHboemA4V|b4MqW7Y7J;*P&M%M-y584<48dc=&s}|q zRXFs4?_fE)4n5^Oj`-9n)9ws7eT3~6XU*jZ9DiUn`#DbX9dLHmAP2^FGt^1|Z>81- zN9o|1E0`1s)t{P54*1+iEB|4gQ#z&`j=A4iGB+~$2)9UZV2=@|*yeCZ`WEj%>DbCG z1;ke2+?zqA3bHI!1YqLXoVW#Fh%e}e3ZR+HBBsW?L{YzFIu9s2?Y6=y)>rYQ1~g61 z_1W-dQQS-StaNmSH9AHyGbM}HzNZmb%ST!nu{Wc$mMZY*l|&!VQ<(}`?br7qQUged zYNTYl52}gminqH}u!N#)I3J?nNO}1qV(Jkt+20h0$bu1K z(8ew*X`o=N(}|7ZlA^%6JTevruml?pnyJmQ!-S2w*iwaM^KNGs`Ox>{H4Em_@9;~w z-e1oT@Bf_6U8gUl8>1+8Qt4U%WCE_()9ik)qtZ|Wg_k{}>gOxbSy1N<*+?pg*FvmB z)f*3L@2}}Y(J&6AA$YIyMQK*!k&AJTuFi=Y!9}7it$Rq^cX`$OBgq$;>U*8j{ezgf zt8>{RIQA)5PqS%*o%cu^wae!9x>0ovy$EMgVb5K4mMhMG{z@kMEZk(FC22fT?x#C zt_k!G+BNXF!BNxt?Q!rHF>6*8o_Y?GjG6(b1)fQj!kP;{g-)dX4&5tFTJfS8XHabp zs!1N@XgN4_KE-%zvRsjiCMW1%RZ*dhuZ5L`^!Z)KiX?A&6*7XtQ)O2OTS)>Sz&YjT zQ=XB`9%b<8?wWC*?0G@Pxphodkdh6AE{1$lXJ;Sn@q=rj3N}oTd7)ffeZiqZ9`K)Y zvfkFauILD>lYq7yYp4Kw1wa`hW3j@gu@V^=2>%bcubZcjt=v$vh)0?Mk^8ht0_8A* zrCd}a>049Yk!Ld2mvGhdTFngQ&2rD-vUAeYM*YT(8QKjoz#&X5{mdB=as-`Lnb|Yq zR^VQk`_w9+nh&K=V!*eMd7FLbdZ~2M0aBY>wh#e+^uZ7tN%XH*Q6PXuKZ57!9I^IK z04e;?yp(-CA(5P4>~nk_u%g!I4MMO=;jprm`eq8}C6fpJ&HAHimG#Bk-2~H*RS3q` Z377e>JuHfN1=(Ze(<8kmbH-h7joz*&-hKc8 literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_rainbow.dat b/assets/data/tool-ui/pear_rainbow.dat new file mode 100644 index 0000000000000000000000000000000000000000..25c349e353015625c0ebefadc8853726b927453d GIT binary patch literal 1447 zcmV;Y1z7r7O-NN#RY@@d3;=LtVRBz`VQFq+Z+GO!$y=~;%JvXZ^2xkFF0g%Of19xK&(5zDNs~0V*QF3H3<$Se_iMpsk zKE?|1$^BJxu4vxR zaB7u02k-qHm`9YNeeZi=4L7V8bVgfwiO+=AE+eQ1Y!wKjM0_m9{f}yT3P)kZC@MgA zL`OFnTV$poBe~0vJSC*yiFZ}IjGsO(HH?V==AYYWM8^_U8kjn?>R(g@I3KXI@3L7IK7 zO7SLU3XilaXD+kIeZEcTT;PFN0fJYB?U5CmG~!N!vzWGyhYa=3BTLJZQa#y4_j{2t z$$}BtBo4Yd%u5AvZ^!+fjSjevvf8N&H56=;F~u>8(Y~%CBzh;gG_h*g5{&-6-^7cL zt-F~cV%Jkm+~T!!Nz?cfM^VZe8Ozj5M{hq%E__T<5`+gcd(4f@I_D`^y?j%7%8vV0 zFMOPggW$utNe1nwEIO_^=|=Kn+rn8dR=aZzp@~V*$U7-}!SM1A~>0 zB)9&eZ;}Uxum!?M+r>CN_)bM~>yAS{Ks@-us-Y8R&W%|G*uR{9AwRB)1NODIYN{x2 z>{9R9;oT$(Rl_06x8TN(#6hjD6OpMQ_rYrT>RS6m$k2KSP-qrX;w(DGl*bKH3?7*K zJ2iJ?*jsQ|skkhU>Jh@aV&Yg(HhdVkWdd64h;|B<+PCSL*mO0m*0+8_ZdfJ&Fbe2wf6X`R)o=QUT|%#nZeH56i;=-B zUbwv-e%s(8@?Hl{ReweWB5+5N)+Z^_y$rdNxj}-!(gIOE?XKcg7h@Uk zDmTCR(40s)!_X;o5_ser-g4!@D``}(Y(2@Rt(s?1I7XdP;Y22_}JDR#TZmCAEVjt3C}x_IKDiH7^!7QS5qhwnj| z`H&@1&4oeZD%;z33pYm&MvqzW%AziSV0!V3hVBM{oWmw!gZuP)kKcKeVMNL)>+-Y- z_sCO`LKY`BCxw343P9m={#!t)GLCL_fF9|M_e*SNXea<9aI^-`iHDHy6+===i${Yz zZ%`kVBEt`<;1XI*C-UeJT^~jge!an%eAtO#M7UUS6SzeuR0Trg`Vz)y+<@#Xk%gD- z6l`#32=Hly%bGhmc$@{^9FX4xOhvLBm8O{W2kz~!-?~1vNtL_ Byq*96 literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_random_song.dat b/assets/data/tool-ui/pear_random_song.dat new file mode 100644 index 0000000000000000000000000000000000000000..ee5028319b663bbea60716a4c23a4d0788563e66 GIT binary patch literal 1483 zcmV;+1vL6uO-NN#RY@@d5CCvxVRBz`VQyq^ZC`V5ZfD`Hnx}5a6}LlGVO%~-XN;eO zFj;C>=VY@_L_;j4m(ED_^Lk zCHL$Al0o2Yh?r$^6MUUiuQ_98S9Z(N$@HCmC9aYDS>yWrjm&C}GDmEULRX}7W`Ol?wQu!4zE}c>rNqy65PUhs zxyL*#A0~Gp#i-a37Om^T9l86IJj`r(PdOry!}|of@3RQ5;@3jkP>KzSq?_7{sSA_Q z=XuhY0p)7%rD{uc8wm%!qR@r;{jipdR+mI?R~9CeFdve`ur8q~Big0sDhr`KOOidy zKOKZA74zPKT%O}KIqN8e8YSTg!Q(86n-fm zZ~$+8!^h>b#?@JsF~Z5mJRL$!BYjD9a`silG>>-XGQs&HFGd6kY3t7zBkPOUz>-Yn z*CP$bLN= zG9we3skN_D{-%FPz#KE2aO-*8K_~bCgiA(1`$mtqM`xFpVnazL%%w{iTKS~SX zC+crKsDo>PGJWLlu5&y1d?b){Scp?g5BqmSV89o!x)nW!0Ns&ixL2CNO;f^t4=DQ* zheDDHPPVT`S-U+2`VwK1Mo1&a{mUC=*18$kJCit7EGq=v9`N;jZ0u+oxt%tj5US(s z0{hDSQBPI(0l~ux;ny~H!2Fk6dj3@!5^3tsO02n(QMDOB-2y{dOpNw>8AddM_#iNt zR_WgJN_K)b{|RyewSIOAS89BfIAs!AusTA?sWBa0^;7~o2+{!db%0d_) z+d6xc9b}?-*}Lf8End$UP2W_sVw@tIC7P%~20GVKJ76*x#MrohAvg2^Ta{OOt^k7` z)`m$FXen;%&j4XYY)*~26=B1_HC91hP%__$AuV|Y5=KbMOCns=*(j|#k?Ka+YWg&z llV*FBtp86;WMl0UNaJ8DsA*a-0v$Fx<7+W=8@DFXS+#$*#j*eZ literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_random_superpower.dat b/assets/data/tool-ui/pear_random_superpower.dat new file mode 100644 index 0000000000000000000000000000000000000000..350d3c2fe0825e139b9974f0609f9856fb19a99f GIT binary patch literal 1521 zcmV7a;34MKM?hT^)pXEvc&eJs-V_{Ek_#p z-{^v$^+&gn?oA5d#b@fz?pq%e5$j@RitV6AH&bz8Z0{xq9I63q&6F!kAF%p;oGkyZ zVWJ>wji(`=mWlk2W;P%X$F+Uma^qo6wtLSIVrPIm z$vD56?oXx4?;dUieN8VXZZ<3oTCoSa^RHaRxb}V)u0IUw6y(O6VFZ&21;u`1Y`efT zN#$^MbN?)%=nD90!jQa&Wl-8KI{kMJZCZB-w76<2<(yL4iqrZEmx60(kz_rRYX4siKO`K}Qh0N;_Osm0c(C1Yl~ z;+R5SrM&Xv{O=lKH0oz>mwrH&quAwm@Q)qcse5zB1=Nxm?t+$EJ1bkYM=aWfy3y9L z!c@A_$q45L(R_#}OG1j_c6V1JkEGG=B^v>EyUAQ+)*mB8)veHFSRB_$f{D~3ub!I# zpod0pXg=tWVet#TF6rO-C3(|$wsiJ|kHrFF`?8tG8b=T3=&Mu#Q=H1b=9y@d;%GmfxSr$xJg6ep)RKf^L{;1m9NB_O+(}0!W$v;Z}CY z8IS@#vD_9t+7}jb6C(Z2T>@GZC*$OVnPE54?x%$ni{Yee9mvPKpV+k?t4bf#n)n5el`}oo1Te_JbIG@|pt*hk;;Jf>A?cN%pb*lJpf2I#bcuLv65uNi!@;}5H=<2*9fKZ2A8IN!6#DN)8ezRC zknr-ObSASan$j!D21GX%qYAtY8jt{hkao)kM_=l!H~aiVAas zk2)W-#h)zpWqpA0@)H6sxoaW@qhN?ovh+N-Z9cxe`v1_v$P@6@vu!eTVc^4B4GCjn zRYpO1@p{-1eVw_DIL;~OAak13$=XE0)D&|Ou)*lwp1kFeAtz_R9!E|oM)R5&iy^ls z-~}7r$BY`GzYLxWTlY1~gF*fJg<1|+@g;qmVX(TDuBRj}cl&t$*U;j*Iwo+9TUq@0 z*vcx1m|90}<#Hxnak1a6vgkN|dMA}fn;u}ut2CL+F`3VVV)P@#rv;2xJ|hj$awi8H zC$?4NK!FZUg2(<#;^i)A{5EUAy-}hqmnU&p7eQBRlszd+8&l&Yz7&xD$*s}CClnJ+ X>4)BN!K)}5H4{$9tYj_%x0@+iHOT}^ literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_ruozhiba.dat b/assets/data/tool-ui/pear_ruozhiba.dat new file mode 100644 index 0000000000000000000000000000000000000000..c1ab6e13facdb29c9613d07f385d365fbe94ab87 GIT binary patch literal 1480 zcmV;(1vmOxO-NN#RY@@d4FGUuVRBz`b#HoTX<}jLuy1;gmhtt@`FOJ8dK6AQ(i0p- zotUPs!C^l@=?3kOEByN>F zj85JoPknOSiz2#$p$Mb$cP<0#u#IZRQ%;Y;s#Gw1jf3nnKurj>aOOgVN^iqpeZt`j3q1&2 z8nE|YF4S0LHnbsWYe@)80}RVEqZLa|%)gGS<=;wS-EJO!4iNME`?*V)>W)9qPc6gN z)gMz^KW^(VZBg28`aLTmf*n!; z;v1Y_sOu?gw+tGMMcE~Xq~eYM9KbS8yIvZSu8g^~>V(P?=Lq`lR>*UK9qVJlU8{X0 zEG}o7#W}xb8OuzC6c}Ar3cUY)a7{JlyXaXpAfmELdXnzWG}v)TJ{x*A`U!T{GXoi) zp%8OLeWq@mKvXW0^99YP$ds;%&cx?XjX`e0LA~VhKIKxOb~~1_&j$WSS5|enn&XSI ztrlQsh1S6~A?%%g#{py9&jkq*I3JR-&jHRn54!@{#eH%D1qeYc4UxC8rHwZy5~N6j z+tv5~SpJQ#o@0^g=cG8|Q*>DF^0Cb@Zid*Y$(#>r1oM*J8<)^TzuRtQeS2Ti8fEg$ znP}!HtLCDg8wS^=98f&d_xxLUa$)LmwRPc047)rTIhLz|n{Ls4Di}H0C22>UR^Fh= zt3*qtR44|Q0}RVwcO{OOO@Z5-dU=~gghS;{#t%!pj+?_eQtlms$s;x^`Xt5vxba3Q z=HhQxl7Nnn>T4m4Spyt+gl==CpSAACeOx+?9Ry17mOeA9WkGirBQF~_=O%2D7p!p& z*ELLhxVk{XS8mtY$ci&wI4_O(J3xZ9TzC}hU^E2o0p;q$e2KrG6P0w-mJU+u;V-o; zlx50YCdixVR11VtmRuoJTY#a)&~-{LmvxuB81~29LYG!y{ic_PgTpA1-(~#bXUMCr z(j5<6DqS^ckMk*FssNe%qB4-!1rd;E8iJtD3#a1gy|%r1C!y0x>dc!L`{_?ak>2N= z#?S`GEv|e}Qa$ymI$AdPW0WDNLLl!lYw1USId|>8gFV`EC>h_dX_h2KvtA+qJWifX zvG@)4<`6{p)f5_}DQkPzk=y(2y{OZBF_-jW;^d<}u=`E~Lb3?I-k%U14%P>$gTa(K zyA9^963{eI#duDFhBUjUaLt%uRTvxbED`dH#%=p{A9`1h?Q z5ZC3lU93n8*?s$^>*rFElSs%NX`~H3s6gpkGfVdE*B-)kToP2LOYy`?4()Bu;qGA~ z^suqX-OqLYpSv*O1>sbqFn8PWN=pIQ#B>Nl}j6n=K@Z5sx;=) zgFdDAF3R=ZJbE}*x@k9~i6A&CEIsz5m_07+Fg~I??RkcT38`QfJ^(XqB~|Zf`A&{@ z=QcXJ<-{kdJvT7{T|lD)+1c^*kpNbes)&8GJ*Og2X%Rc-190tv4@o_z`q#nXM*&zw zY!_?}?Ec-9b3}(*Xl_`CA96OQT)@dq+Joq987PBI!PJ}^7TqP6*l-+f+$Nt+V6Q;O i3kgPcG5$+uonv5aXS~G?{PYumsSmcqz6!_)m$zrE5a0*^ literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_science_news.dat b/assets/data/tool-ui/pear_science_news.dat new file mode 100644 index 0000000000000000000000000000000000000000..37e1126a030e22255c26c2362c71f8677e4e3cb6 GIT binary patch literal 1468 zcmV;t1w;B-O-NN#RY@@d5dd&yVRBz{V`*h>V`X1%Wp{I>IDqCf-nKuJ{Tty3#k$vY z0mdf3!cvXjXn&J&a1*#ib2x1m=5q{*wfcMX;;%fGH9gKC zEk+m2itw(VJx68{jvkN*UmljT&$ck%83#of(&iBA+QpuDVK+?i?jt^gyuk=cuxpNvktR5fV>6|NP!KjSsM;1x_(@nVQ_(RYlgg;4em z_%|^}zq+!fJ)3fLjOcDQYWPXyc8nr`_rSo{17?pqeCsAEksOv&l$B@{SNNzjl&hN* z-=UH9h`C$C86Bpp+of>VA)t9vL@y5b1>i?Rd5D+Y=O>&?iz03}j+(_>KL-RMxIqeUwIof{a`6$0o5+vObL-!>1JktCsBDG^ z?i-ksE#^-d3dV!L_X>G0KDS8m=Ge{1lI=i*@|2g?5z%no5G}jAbD_&u>Ua*-GDr{q zk&3H?ig1Oh0Ya#hjeT`x94B|kqCmPNLUtgDQ5T5@e0bG`0G-W`<^Az$BgPXOe1Sq_ zL~tD8g>tnZOzdRCn2%+}kQ@fCkJt7Bh#T~FYh}ymkAy%RGX~&cyd%hcxbBjItAGZ* z){W*l<2j)HJ#Wq;D-=Cywp&grk(_4VgH`dmO#nKs0zPT5hRW53Jv|vby!R7lzvX@> z+GyDRlu0su3F4)XAdW!+QEUnlS_-US6s#D8;38sM+YhIWWWzyHA7rOr(qckfnI3>p z+W72;kF!+>EQ9`jcu|c_j0Jr1h`nPS&f9?C^}(s0{~yh=*AQ8zQXVIb^j{0-r+|pV z)}qZretIkzLCGFt#5+d}v~{TFD*7Uiz0rp$CyRBxZ+IJ6dAdb)sc(5gD}lc9?QEzK zSO?421LJ)Zn&?6W-Gg*jPt@<-v?L8?>HQV?`ai`=R=5xunDRfXKb~U9J!+-Mz<)Ku z&8E!rfjAKs$^oomFbR}08?@7{2xmP%+-V1D+TCAv0XT2`)ip=)#Q;&0Dc|!XDli5ZO{$|f(uD*hB7J&z5cN?^X-yY@q>bv^aH=5 zW{UR{;x^*8Y3u}iC!#`d#zi2NlW$|z^7?B+csdm|R=-j4(DN4QUKBdZsUTjI-Gf*v zo8QIX8{z?Sq9?H)@>_$U?fUuCt)oFFj$1Z#CO&Yvg{0H}meoBM_z86&Ek6?_de~9g zgQm9W-&B3q!6KEp^KHkT(qG+>Ba&mtA8T+}=G2#R_b}8f^;gN{i~*F6>GLGIgGGI< z&nPk?;*JO5j$w6{V36V^@E2bpBeE)c?tirJ2Zx)=kY6|irCT`X=5GV9uhL5L$V?vh zNGA#@XYbJn(wBuLv00?e>w3{J(yc^MGGPT_*r-`UH)nK1FB}-NV2@;cU1&$^!F!?6X)BkUtz(?rv+-87lftbS&s?dsq zT86D*__4x#voBQmcGq*JSwKo1%R!2B1WHqHyswt@E`P;%QH$E3O4%A1)*%p!9rC-+nm^HepyhD zK8MOV1Ql=2Uq?QjIY=4x>R=Qw0?cPLSQDYl5mTNn+URhH@vmDBh)(Gl9ice#mBHRu WKEXwwsl*@z7Syl@rsIxPiwM~;uE;k4 literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_sensitive_words.dat b/assets/data/tool-ui/pear_sensitive_words.dat new file mode 100644 index 0000000000000000000000000000000000000000..da27be5d4c5b687829584fa1f7a198e30b825472 GIT binary patch literal 1551 zcmV+q2Jrb=O-NN#RY@@d6aa8#VRBz{Wo~n6bZK^FUw3bEWOH-|v0XVRc=x65NPb2x zib^gwcr4%VZInUW7#}lV|AjEX5uGNpRGeWFZ*~f_39CSOdvsSfo=Kj_6txZM0<(OT z&0>A^7R^ZRyhs%Fa-8Q@SgC9;wrW@1=y~;4yo`DxUA0nDHG(@4W~l6y`g5>kL!Cr~ znY7PW4-@}>og^5L{&l(4dk4kXOe_=#6PI#phD34nBh4jl4^pbEz7_!EJ^Cw~HYGy9 ziFkd%;>sh6G8czcF7ari7Q#a0x4&HB>KeV)i9Q`CO(aN~>k7X?e8E!ZhC7=|Eb4#PW-(Q)?=m5mg?N@Cl$g%Hy z6O9t37JMZswXEQXU7C#1Dt2mpEjfp0`2qUS^8Eth3_-9Kc+}s-uh>qnfo6ve{ zt+-|eb8(^GN z9!-T#GIrU993 z>))ztb`#IHn%`Vjp&*G#@=d;>%HDjM*(A!KKT+z}d< z>^}$b)R_WSwn~s8Qt$*!Q3&3J7S?Rvjn6(Ow27;-=A4KImZIc{VDrj8~-LcEZ)kE6$${{6pWULh%0X4 z`I;y00Z$QKZ?=};V|Ib46L`t24S=hL#MY~AklsxBr={hRX!+V&sk`xyc7C#u3K!8^ zJO2rk;NVM)6$obVQ<;DJG}D1+!t#ONvaoj+D(eET$~)P8UJd!u`6l*b+e5uzOHH?0 zi1z_)FrszYrpxydBx0RrwFjG%{#IvALI?B!Uw5`WW0Jhj|zlrXAxo0wVPp(41r=_HvLBJuOb|3$8Ce B`$hl& literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_short_recovery.dat b/assets/data/tool-ui/pear_short_recovery.dat new file mode 100644 index 0000000000000000000000000000000000000000..636c4cb3dd4705e9cd61900bf0e1ac479a8f84a5 GIT binary patch literal 1470 zcmV;v1wr~*O-NN#RY@@d698~!VRBz{Xm4_KUvgz*Z+2yJdAw#=BAFe;`O?N;Lzaxk z)#?^hh=Lq=@S?bECU%Rk{l3Nd8d2#Nz9rFgEKOBo9{DkZDbFcb^(_L;Sd5H@@4W3j zv*1l;Rj5}~ndKCa&CQ_UfqL2GSjUhbEtRDNO_0l!>g{`-HXwufd|A@5@r|whRdEfH zq(z5L>_aI*L)rH0!X$DosGf?Oh^z`km0_lw(VQ`SE2|~KHb}btmt`Vinzp}!h&N3P zZFAuRgd<)eR^Q#d2t?kZjtsR%_=ousstw&8&q=+))=P_InL(Yw6KJ{o^MXV>PvDjA z=qDGtROy_+6|ZVH-<9ujzalpslcoD87|i_(@zP~(OZ%cL`>b38ZJIZ6eFQ!eCtw(x z#&3?H)l6$tyz+%iEXF4V?WBM+ck1LZv%XxTWgQe65`P4n8icH z(wj!NOzb%l(cO}s-SF)!cGq_BYDRRGe;&0MvA$}>7D~)=&-(9w5D69PKcAz(fdAYi zE2c6vINzb+G@&9C&)l~C>2)C{(OQi!1;Q(dt8943M2{5m!zP0yS70fVr zY09s;_j!DI%`IGH%Xi`M_O4Qg{y`cH5vu0LIgBW7NnInUf_HrsKlsU*7@dL(kQm>= zk@<&+waK*H{o{H`2>~{NwtPcRKt#_>RxQ&=uomrWPMYTpQ=ip@$Hf?)gWK*4Z9AB*QZO|Yd z9agVtBn0OUUc?!}YHt)k9 zx$CoBck#yY)zKea$9O+2RcsLY>j+}F4x6fikBMRMx-Efe@2UfNoocZ{P$uJ)F0vB$Za4~p-kKjX??^cUD=(?;-?z@eLx^kvJo*CCJc zd}+CB?<5=8%O@iwPSym#%w|?LiP6%?c@sl;D3dbStJp1^Sz9Tjnb&5oikROq7qiHEd|PICTPAq z%|4S@X!)oWii<^a!@4F%0hcij>v*$BdI8LLul!5i^go61{&P&;TCSL}+Ktg-^YB7U)eDi=!($dEUBk`(w*M?K9H_xAy1p(GQZI8(7uUG4A5b!d2+CqtVDB;man$XlJ_ z@1uxLPXU?KHgT!eTK*Ze=u#zmWSnpqu*Mxx0dFjOwClv$191j8ZL+u8PSqVvz$Jy9 zKaH!4$4-zCmBC#8=s6`c|KvsG$(!ufe10NHP$yF*@w4KE5!Pdr$fdr*oMUPS*X^fl Yy5p7uF_^!fi9kDCCW9l26uBV7!}q4@#Q*>R literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_site_index.dat b/assets/data/tool-ui/pear_site_index.dat new file mode 100644 index 0000000000000000000000000000000000000000..62b9d946914f7ecdec9dec160219e23d1844abb5 GIT binary patch literal 1546 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 ZkQjU>8%&kS`wkoK`e!~%%`mRi?PK4v^V$Fa literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_stock.dat b/assets/data/tool-ui/pear_stock.dat new file mode 100644 index 0000000000000000000000000000000000000000..bb29f467d607f5b51f64325fe8178f0bce54b1f2 GIT binary patch literal 1509 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 literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_synonym_antonym.dat b/assets/data/tool-ui/pear_synonym_antonym.dat new file mode 100644 index 0000000000000000000000000000000000000000..332b16d9458167ef5c3b984bfd0cca3168d588ff GIT binary patch literal 1503 zcmV<51t9uaO-NN#RY@@d6aa8#VRBz{d2VlRd2L@|Zgg*Md2PnzK)jKJ8MYZ8BSCq! zBaxG#l<#ypc*Y&HCP&RfYQN6BfmtR<5e_I#kxXzd+0ab{ny(P*bH7UwNW#Fl#yVeh z0^YL%jd7p1U!(z5bsfo~2beEBYL|=~ERuP=tJ}ti=r*K*Oex~ zQCP<5$EgIKKT5mn5_xrf#EK_87QEYa)S&DaM?7KEf<*~|b23Tn`%3e5fU9Qy5!$$p zu(YKz=||1OCI?)q9HES!j`hN?ZkY@a2Go%E`%Frw4FgaO$6)IJ&@$16{flmfTYN9R za*^S({9hIea&9YHEX08i_$c|zrl5DA-Z@O#)TK@HW|4u0r`h zF@C1&83ya`)pY8Obl0)(3IT$|pUjvhp=trs5i{N?Tm~ed>0+~IYNTtdoUa(+gjb!6 z)L^xadt8hsmuMy9H`vbiDl)tZFnyNoVy9k*TF|!bUY3zISIsYI*T>F`G>nJgYHih2v#P221m>p zI|27i_xgVbTCGts^;^M8M-wJD`#rfPNRVltIY}OyQi=TsbL66pT@*QS4}kE90_WtS zwB60x9nNq6{X%Lh>|I;;CJ-th;q!uzyTMVTQtTw|4)<;6h0Uf%EC zQIN0j)smCF&xEgoIWQ-0Ps)D(`N5$2`Bfnvf6-}+}#Gl7CLF*q+HUF^i8F{o&rO|~$7CtP|=pbXgJ z*JFxyWKIYL1^GYlWlVM}v%Nq5lQ?RxPLeh1>+Q1A0o=yGD`@`d%rb^_YZVF%sV$^Z z=&*6&%bHor$IwPZWZv5lEpls25&^$atC% z94?$Wo!6Ir0ZTH%6o&EocJL0)=JNZE^{JTMoj!r~VI$@ue`etxXtWR8uGfqIP-rs@Qj@9gN`9M_QpXRUXT?uK@Zgpdl{ zz(ShJWPn1SyjNlOX7(3uQk{7gG&q1?5P!>yn%j%E_KeVxC(kqD1VA@teaI&KWTSZF z>|hEifX7zLuHKT&~wAYZHU~ FoRBG@?Z5y4 literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_text_tts.dat b/assets/data/tool-ui/pear_text_tts.dat new file mode 100644 index 0000000000000000000000000000000000000000..dbe4cc6007c1321f55797686a87ed515e24db222 GIT binary patch literal 1496 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 literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/pear_world_60.dat b/assets/data/tool-ui/pear_world_60.dat new file mode 100644 index 0000000000000000000000000000000000000000..617feb3be84847d4fbacc5e6f4cd0000646d5292 GIT binary patch literal 1464 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 literal 0 HcmV?d00001 diff --git a/assets/data/tool-ui/percentage_calculator.dat b/assets/data/tool-ui/percentage_calculator.dat index 738825684e2770f79f29a28015545ee6f97b6f73..fb0d6ac4464e82a1f7f1847fccaf050e9eb9539d 100644 GIT binary patch delta 2038 zcmVE*MvRLMdj#Zi)LFEept9%My*N|y0j%Yz649Mx;=RWgS+lwZTSmuk}bNB&v2 zLvfL3Z!^o$c+)z%q7VlH@vv0N#(qbH+axR_LE3wtqY0YZtbe9VP0sbB13(|YhwsIw zwfhx6Ag?CHJ=v+yMu6Tm1Hhi!=+ z(9{)&nq00waDi`OqAttLEB;S}ET<@8Z+-v5o+R{c3ZoK)OPYUIfEav)B?@QJZxpD{ zad4hf1b;A?u(9TFPR*6q%ytxQC@|Acm$Gt$!W{~}Fz!DsGbgI1xRu>b(qaBVSQGSZ zEeJCzUYG)r!!luTbCn2okfv93E(K7>&?11~6TG&p1`e03)sq0Py-(&Px?o?+?7pOX z+Y6K+3-Q=8;dzlzuQG^BjmYO2=6o6d>WP~HK7Z0_S#;hyddOTk8m+A*ALjGy|4Bj7 z4=(63^yx}uIoFNCAunU8x~CAZ7JS^6=H7+TIB`neB2}YD!uG6AA8o%uLmClC;H&Fv zEo)Vq3d37qI+R`Fhebk1Q3wL4!K^8RA3V5uq0R}kI!i0-CPh)zGXr|G@-vDr3Dx8! zzkkhe$8ny{tC~9zuFO?GIe?PODwHdz;haA8I3ix(^)BiMC7|d|rvTiZKnq4oUxKNb zW4XI*wb$3h5`YJcCp<6aQ%26`N=2kd%En`CRvdUvz$66*b>%UwECFT5Cfw=&C6QX1 zqb%da5#lm{Do2plhj$$i*nSKic!I&Zm47e27{HV|G#RlH5yO!q2&~)cVVcrT0~lz( zc`f{PbmC)Zw$x^AE$oAT410xnth!*UcK{37X*F1}awSnUAI;(Pl)lq}^Fl-Ew%BTv zpFu`fiArG`P#hojfdQPhiy_VWH$Lw${ArU3^Y)*hb62j#4Pf=_vz`J%YP^U=k8L{frx^;?djbeHFKl3?BccROL18T=Ly?c{PLzARBi_h1d~VD-M~Xrh>Q2W zhsFScQjb*27ClYC$ibvx?Xm9oWPda>h27Z1&nw&vR)F!J{&xQvKbTHOv50RJFsPli z;)IAYhx1wh4e%U30kq{BK`*>~pS%!Y${-I~S|K7iZ@kE}00!-}(Z0kX3h^N`YE`AM z*`FpDM#TaDo2Bil5nME!C%~~pEQ-)%{t8-?s{PjSlBeSsLjp5mxwhe*&wtQC8;Gh! z)9K3_p1ssUI`#|B=ND`xb%i$2k$axLs>iHoKt0fQQo&QRpm5?_H_%NUPv>=CG4zOE zHP6{klTPFMkSM@6tz8s6teH#~@lxE2}^uBG82gSLVJ7`Z5!z?!7dmHdL`f zX@R+N^7*d62w_n13SI4-jAWa{-cwA1o7)c+*2{DK3p-}Zv(jNxwGM!_0aNvxT2e%A zUsXVH)Fkk&3I~$ueEwahbsPAVjX@6A%D)mPX?hW_nt>t=q}lpno7uuDKf={+*PSyt31YnV(mupu!` z%l>h+ZUo%qY}et6b25ZL1fJ0DP?6$X{8Dk_@PDs{UEgCD20J@&8LRT{XC(fmGyOaja-YUUn>r(X9A19YnCt*zifn@Wh-v`+|5$+^ z>tc1usmaRyVE-uxLN1dzb{AY@?7B!h2dk5Ch+Fp?~K?+?XGYO0%fVNH3C6 z-K2+&MR}o238p^zyW_M=@itT#V~Db80#|(SpcFaYw=Z}TI*KB!C*}fnYAu_U5(|u& z@{ugQQ64+aVu!a$ela)5^m6FPp2{oA)|zDr?Dk#=6zsj*gsj8la5*h7xWx2Wa9?67 zdFwU<`Fu_J&~NIm{V)c&17)+^hDog7`);Aiz5cq#ncf9jPW1c^2qwMmMxTi#*o;!1 zo>NQdh*l{6k3nY1bmV4vCq8kwD|8v27NAFCM@V6ZQ}JE>oPd_rOb(!J#NlENNW3@D Unhalf0P&NxjjtYu6A!v5-|LU)H~;_u delta 2038 zcmV*QO%UYP{m>UL2_v3UjkHYJ95kj^^N z%GoKNz|PQ%EMKv~{0pu5lYq{o)H+VRwhyCL5VJgqVGTa&$rLtcdx~AzN)~0H=_W3;EyF%N4dJt$VhDAUjXf((B1(!h6g+s#R|LA>XK1@!PI(+P z7z43K+<$Hg=2vnmWOlEm!!$?pB!Uc4G=F{v7ZU6$c0cX$DIyskZN^-K3(gD4^uqMl zL|``AmxeFC5mndO>#u}?J>3hi=?Uo@_)UNHv$8&5rs*r@b&<7MZbPHVV-cW!?4PKP z4^<+~^r;$LzDN0DxU86wLVS|dFhP7##yBkn_kWI%bhyfcDNanT5ms4dH4(JLGbZS) z{P1%H#|oS>sIA_URB_l%b@ed_yz4HGcx4Q&eJL79W=yOJLko#ZX_BTD#~G0)f*rxl z6h)vM9W1J0Q-@|XlmxxqEH(FA!v7^SI=QomY)QiW+WkWQ%KhL9XW8JZi>Fl-ocwb%yO|H&^({@JQ{T?I8`_)ifyn)J^a5`0!?G#% zh$Wb~gXqNsW6})5Ec|{eK~<3dE+Vwc-XlSuOH~HFF-XdQ6EF0rWsb%hVY0 zOuNBs$;X>#U1iN<>eTWilVIL>&Hm+69-Kj-C7B?_1Lzm56n^Dbj#7o@)PeED29kfT zJt^KI70A0#=<6`Csf8`>##GmJ4f~}`W4=+1Sz%n5f9befPa>@CIh-N z9%IAuf_k#3PLe$M z0+Xlj)Rxk)%n&ZWu|;-!U2~}L&mktDVNoII6anYHBEIK&Zq-(AARX3%jLQGX?9&hA9!x0RSP1PM3AWMyEvXK@jA_4jo_!jh_%iZOy| zU+dI}K1;!X`_?C2&Xh*?9Me<=C zHHef<*bInV#G2fKm%Ql1^hx|np1NC`!~x9jN_A<{a1WKbuY%DZpSQr!~n=pLGg(F=4p(nyo)22rCDUKeH7>K zg)MlY@bne@k7_Ws_5Z~sU97Ovx{biY}E zG8%WrKrwA{G5idJ1If}; zB>c0H`EKJqjjKs~LF)T4^yX)(+cuz(FK5iMuQXT4rw?z{)uMqbfa@{{yt~h;A8*O` zY>QS{e}7cMjq$jogmih%MBH0!Or%4;5kG;97%W2piVxop$sv#)I|A%b5JIf?lf%CJ z`SL}I@_~&(h;PvlyP(OJfBv`VCMen8lW41nnpF~|iVb|_4zzqY*LYU4Rru_L0()HC zTCI7esC?*@tW@!b;GhHXn1sc=~U U3|(%0P6O8m8O3{g;p>ZBV|O#~iU0rr diff --git a/assets/data/tool-ui/percentage_change_calculator.dat b/assets/data/tool-ui/percentage_change_calculator.dat index 76d5f5dc1f12c383c2e60814bcaf37050d8701fa..80b7c00f0393a7cfdb504e340477dca648fd9ef2 100644 GIT binary patch delta 2071 zcmV+y2=+7jtmdWhMyxzuK;Kt$LR%Pp@t(h+*JXy&%rM-4qb=mS{iKRYBxh?%JWk0my~~ zubE0*9e(tOupJ`?BTBg>Jr)B~qZk^VsM|_%qHD{dQO#5A@_*i--+(h2wFRUZZRoqM zl?=})SleS4)-PeeNTKUIov5GBN0K+ z$01BA(P?k{hJO{3=FrryVNbRR)DtFmc{WXKz{}CD>&KV>db4c!dn0@#yV4{AIRY#7UzI%PPt{@8rp0>hY^>#(QZ-cWw+?q02j9p`Sk!G2b z;5lL63FHrO1$#X$RSH{q^bWvnZZy*Y)QmC&L{Via*>7f>BC?ubJ*set%PlyXbMLzx z7={hW?@U>ihJ2C>5;_QSM=i_ytbWWYY^i8zfq&WsxWu<*Gyx0#k*7`8F3anM)6AX< zQSICbeg*bm6dl7j3lOrjVEReb0GfOTe|-x1V}Fw?D64YAIz!keoH%(Rr}&1lq)DJZIXhb>I2T!pc#P`Y~N*pEPpfrrw{|R}ksLh9puEwtwDH zC5xu=pD>tjj+S%1RU85Rt2!o~a8P1lky`M8=D-#Oc?T2`Wwccqyi3Gi*2rs^y_vrB z=LQ5#kQ5K>#i<-gl~w#sX=>@+p6x|&qh8{3i#x_)FqgG8dsJNC?xuZhh=0LwVw2io zM$4qMad$;A>_<47$)1qM0>dw=>EyN~KuKL@SnWD1Fd-MJT|XSKib3+gp_5g%sAJ5Cm;sDow`>VZ{@*@l_J4Dx-APyw zP%sh|w!;*`v85X((Ea{)uv#xjVEb(x9?UivmG9gD{5HXs{rcB@j|>Tww=_Vhv(eLB zj3gPX{g%R^jOup>>8b8ll@0)Vl3To%)elQ|0p(&v?;ZlC&G9 zvGuM@hRE*g=0zA|a_id?0O^JO6X#mg6&5aLbFN1CFz`luk8{X_t@9Y7J?y^f%ikPa z(|Yn{OwUUV)8c)m9III^z|M7or#)=lW%d?P#eEtpcfF5EFZnDBsBXi#3(1vq z35PN%k%ns|&>Tjj%Okb+(;2;CNSe@eG72G%RBM7vicj;%{mJX5XLK>M8Z3wVj8pxK zRpsDLM{-7&b!#w&Q!ZOZBjcd)pDX{_Y z!Xsp=E(>mF53Ddo1C7z!yzz+W$_Z?X@vs@u&FGr5j4s=rYKyR7ys)=_6WFA7zYs>L zI5hb%)BNq-pwQx==uJNMt_C2cV4(o-rDUE5SWXJQ303WydViBDd^wMbIs#98FZ~Dw z!(49lY}EU)=!r~cEc_eeIhUevR=oV?rvJW7Dq#Xjt!0yEytOC(N^a<8_AZ;}wCw;0 z>1E%@FGM5WdxC0d-gI`*=DW-hQQw>_jG`^H)Nt*X7rhq`${iA>}#7iY}7 zqfOGNBGzhpmVc_wRfFrHs|kDK$319lyMso|VDFZvWAz|2@!W41mTxxB&mkV9pxtUT(l|4G4Li%+B%q3gb*748&w6_e~9s^z0V;SKmlu+ B{cHdL delta 2071 zcmV+y2CY)=0dy3>5^v0fN9Zb~du@Q}1jA*hD|9O#yl;AN0 zyh8oNGndCf{y{b(LUP~J-$(_P#0p9H9I17ve5~$e{NzoY0(9D z>M)RS!;bG74r6#BNpkg;=B6Z}Cw`+Vxr`HA`e_Agf-^bCP?(;I1q~m>E?u&e8;cD* z$AT4}!dqN(`+tKBQzwer^-ZzW3^h)<1oH_Ql&(zdZ@Dw^L@>r6|Sgo*WTKrEc z={jqcCHO{9ES=^|A11?r${eVq$c%Yv9#=4;b?@E1rA!;y@ z|BHRl*ngTr314iZUI_f{qKHghZrzb#@Zp_FVc-oIrarR2SVRHi$-AlqmTm1_`++{uEkL^!TKxZ>TWZ?9|EIt-Kx>pyi@ zFhn_sTeQluUcr}V%jy=A++RJOXGL?O{d@XXVt)#b*~YU8u1&CeQEdR`ja~qO2(T!Q zPCvCDK}!~Os+*W*Y#qJ`2LNX+LVJq|nnR|2h)he#kDR265@&PL79y}|yZY1~07?A8 zb&y^Iy#~OcBi&%-%=w52Q6yM)#A=sPWn^_+y~p4u@{l6SY|_>cShDLwE*t;Om_UPE zbbmnO5eZTqfAsI58QY2V@uUI!vBu@ffh2W$PZ`>ROLkV>6}$$uFvAhRm;dkwtZ4l(zcl$C{fs>r%!X;z3CWu4DH&!ZlLszS%a8X;{ z{L-h9=5B)12eyH}$;P7DP1z!sqUQ1R7b|&=%@}Bm zB4AQGa1P2p5?B{7@NOa+eL7JrM$Q{xTH46?M{mTV#w}0R_;iTo-TS6s_oj#jdU%4` z5{)~%O5wJ7M*DZV@9JJ3;&IyQa(^(wqDJA8z%q zdVDGgK(RLeXcZL=LI;d?HhJKR(B@D*_jJ+{9>QdMw){c zR908FJ|r=*$84$KK&;xNuv2l(f-%Sxfd1l$r^i;eHdF4^jDKN7xOcueC4bD;1{_SX zq3Te@h7K*NFPo<@ZC67~H#3yFtgXxH}0RFc&zxjGOyNk#oLxCFo)uqzLN2!uE%1eLL3>%RdPf zBL*M2Az8P`Xm|w9*2iX}#%EfNj_yt$=#R8^{tj|K{6AO%jaI@Eld7 z4hVd-g-dP3Yh_lUbbrFcCucWHDG7dNGRh`I(xmhvCbN>1a*qN=u}IZfMlYsOc0{7H zgLK7!gY*tk0P0+sypr1@A5A!$KcDRdDJl6|veC#hC=i8qrOJJQug*hhCs+&^Md!wE zwU*|a?%G_5MqP6u?tq?ajyJXxVqLm(bNdcD&Hw1x!4FtV92E_2RLx$akG7aXXi3{YYQ%H>k|9R3h8*9$X1y5B%aSfMAoW zrO(Z9>-$x|Ie%oGZewQ!*hvx-wZ?f`bhwb%5QajWLZk$pk?ELFq?dt-LrlM*KB7KW zr#jF+vM7=l@)kL~|4T3v0IIN<$402?VT9FfJra))kiROiQy@P&eZpKTF@!9CjdvE1T|}vx65#hcde#R}r=BjyT9MqY%U7i+uZ}QeEoFbRf*n24C*< B{3iea diff --git a/assets/data/tool-ui/permutation_calculator.dat b/assets/data/tool-ui/permutation_calculator.dat index 5179bfd9116554f2f1cf8c049d1e677a7633deca..e4a0d8ebf6b0c2f19336cec310a0a4357a688264 100644 GIT binary patch delta 2006 zcmV;{2Pyc05P=YoL4V^0Zx~H387)=cILAb((5JAb#EpS#%(Ie-vQ>{ybzB8g*2fvq z@O&w-vH|V-+D8%~hGF#~>~?KuS4NuLU)^Rfy(@a{DtXutmLxeA=dNYgZ1Veaf;0`a zZKBneWl?l2Kt)LR=;^-ytpIf-DCH==x+y|9w=O%7p@Wi1dVew6!rlKjQ7R!%(KE~1 zA6m>^>$UPi+=`oXOM3q*Ks{iP$;TXo1Ad_PSKJyrM@kz zEqnOh<=H#*N9LhBx8+YWx}!KM#Qr5&{71J*Gn_eKG`#%~&0)}-I9^WUoSh&|A+^92 zWevM`hiBkjd4J!b#ojX*IpTc;6NwWkSpyLRXXwK3V?|QN1%oXw-}MxA+;*k;izr#m z({4~gI-l`BG}vo9M90CHi;FFlbAxkH-45%mXSx6;%;oSDPzS?jLqiMe@K+`S2vuw! zJLCwn!jZns%V7D0CB|O`IxmmpE=+@}LeQ^U*w|alQGYL=Sqg=kL#qdP_n#KfPHzH{ z{7abo#8|Dv59+@vUAZFU6KJa??ZNW+Nn4k{13hQ@Ugvq`FJDdzt~<#AjnmNxUl5!k z2^Z$8c4qvFBF$fE%$+IF9cwhMRm2EZ?lYsAe1E7dSLCMvmwt=G-m8{?-d)bEwkMHc zld~e9W-rX|}b-s8)xDj}4W>1amrhk#dfglG1u9xw=E#DnsCsM?aP|Vn` zaj-*v%5TWqEj3C12oM&nC*})3T^RU|e2y3e=jslY^8P~*_<>EkDU=y)>UCVcaVEAz zY}{HYOV){B_#k)yPfE>L+?X+RcqMU^V)0$<5e>OhKu_0QR<73k{*k0jTYjVq9PFif z_kZhZU!M(AJROn%#h5woI{CMl$cUSrW*q>RGEu_-b- zhvW%?FZbi>>+}*BRXcbfDG@>Jt#P2&2!9_FjA127nC7UqoD^CMlo!jif$*tbR6|6y z(Q^s_Y5eL%5Fduy%7-HBj?!|exdt=hDCx8TJ=8Y_t_OGdf7d4|V&G08A`2^&^CkEC za-vHp&2yj<#I8Awi?~aSx?kY2AikFpaV0lsMGDAjB!72IoVog>R$`5#vrJT~? zWsO#*|1V8VMAnYyU#6M55t-66mVfcVkZ^2B6QE3>R2ipS6k77%AVG+BLsMf?GVU9V zIKJV~v$&H!QT z6nDS2BQk*P7VpQMfWQ()ip;rS$d7HOgF=t4f*V7XT-VA36P_AOKO&WHVvBGpGN4|V zr}ZiIFl>Mj$IGef5fxanxPK5{9wG5l5a4R>;M=M3CN^u#?uPgA2#aRKdH$d0m-yw? zBd!P-gpIkxd}1+_R|~>sd%k9?oDKS_I0#=rX#g+<*pj7fE-xiQF`+V$yIZ=S!uf$z zeuBm_mK0x6a3Pw{jkkX8(oKmxee9${AWpnPZ*Kk0hjr=Mm=kc>=zoi8wN7tRR)ZX( z4S1FfaU^GB2<@8m%@x~2irpL`&$^ZgIj;`Zq9lk~CGpTAIY)0c2;l>&Qy0SkdeXl5 zuo=yUoH6Xnd|ky!DJ?io*Q;BWx@A?V^^GU_r>C%pZWEva3%hMV*2f%%=sB*i0dJ04sd}rWJm0_Z_Ce|%qToKY)d%vXUT6Cn>wim5q9^w3)ds8UVPh=n z&Qguh>YkzRcakR#Wz(P_gNIgu%;%1Et2I}=-%%7XJ>uYhd`fcqC1w-a(ZK*w oe-TI~?PfmpH#mM0t^;*(nbRCUW5eWx8^kPrc>R=g0Zgar7fguHy#N3J delta 2006 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 delta 1442 zcmV;T1zq~a3&snOHh<+*Kp^Gnskc9R#ufILSI2f8$ahsK!T1C4@|xaw@wL(qhh=J2 zqk>s;a4BIhd}&@O80K$ol1}CdP6=e!4XM}0alAZ-Y-y#2qI$2v5m|v}g4oLSP7CMp z-xX05A{z%RI=mf;BzKT!5Sx*+6g6OGe|VN$@P<+8+3YP(^?%)n`pnisocO$MFKmU3 zt*;BAo0|~1I(p-C0C7pcU@a;98jrvq2HTb<-ERTzK_@_82g?Nlo&&m&96oc0FDtRY zqni}U1>;itjGHc{BPoW20nR3=e zT!r@`5lUhYTScf``;-I+ojt!;U`C$(HtuA^l&W7(eo;#PQD3sB7*GBO$`1vMz(rr&yo8 zs!kxonM~#Z){~WQh3U+7L*_3MxU6hO;YJ+>`l0m}!!PuZYB&R`S#A@*_Q~h3IAk^c2qp&EM5u6BdO0{7ttW7Y4F=G}`C{m=L^gG)saH!~tsSI>#t0&+ z_-S(X1{r+`D1KUqd7+8k-7jc!Td7C-s$nk30w zNduQNOK~7NCKP}ARyGc7a#oIqbLN+;SdVoEw~C7$gw6vYzFRH?lZ%gisWQ=jM{d_^xe8L| z9DlkZobL$EzhaGj-tB?Vs(yTm_89<$PY?c-qU_Dg77G4#(;eUC;CreGX`oyulh{(= ze^z8Jwi{>6Q{Ds7P^!+V(aK4J-|(cC(ALZnV4^IT(sGkuNC{;vE(TEMkn-i5VwwLu zf(Zyapr4*-QDY-xpPxAUdxfh-Zgg8L$A2ou;Xl~Y`LGYl1Y)u{u6HtMM!%iT#y?Qm z_i>d*xuhna6bnwk5JSN001rpxZ)ju!e| zk|8|M(bACqJJbkpewk=@60VEOw*C+6eg)e?uC9}W=#Od4)mGsd|I}0NkrXe6je*K` z?-)vfussC_s6&f&G*jEs7&UW0u7Bd22CPI#C@r{tv7$}RuQc!nAZFF8DS4o!B9b}Q zBaQ7IVIGkzp*1j(!s=fW7>{d51bVjOc6kUc##ukp0AO4cAG@G9E9N3EhLG8W!~2ZA z$^rc1=+yl(x*RA$pT^Mw>C0VC!9vhEsRJI#|Io(CX9&p(;cm=*&;&Pfqkpw*AVk9v zY`mma>d)e|vf84Hge!p|Kv0DtZ3H+sPf?yziR@)bw>~uO!#u?=U{&k_EuoXgkJ=cd zMD|NTX(-tK<_!AfLgI~V0w`{5eN(CRh5u&x;&>0oi0Q#)8a2Q1Qg1-D;4>atTu>)- wQBRn64176y8yT4xX_{Trw~*LyFo_$}g%S!D4C_|I5OD&B&C_y+fq)im0_n*aa+ diff --git a/assets/data/tool-ui/port_lookup.dat b/assets/data/tool-ui/port_lookup.dat index 89378ba68796ce39b37c01380aa2a95b1cba2d46..52714f452dc285a8f134ea713dc08f44b6af2f52 100644 GIT binary patch literal 2166 zcmV-+2#NPuO-NN#RY@@d3jlC$a&%v8Z*OaLa25AuaXL(ID@T?q78iI9pxKp#;M4~> zM-mTeL&sJX&4#;28i!C#dgx#lA1a;J2}%BRj-)5;NsoPtqpj%N2s*47T>cyNlc7jb zVc3QYKA15T`+YSp>mJ%d5VFfR(u9`8-|24vKSRxB1sYU}sx;!gsfM!nl!!K^sDDCx z6^Os$=66UA>sbI6a*x!~-`-JAiuu>SjjR>9E0(n+e_)ZiLvs%wku0t%=Fg3}#LaOk zl7GG}2-}7uL30*Qlb9B<&z5n`cVovGdmUGI_}=47F_kyegsx|q0JI_6=k?ZH$log$ z>ipz!9)tKgws{l@$g7v!o7G4hY5f>auc+}wtSuBX6f;6rBeE_V$A`|dyl&vMeiIJu zd^6gPAXO}QL|!Z5OVJv_SrA)_pXXfpE9-6IZ}x01;1}asP#Eh5Qf+e6CLsENho_xzzeCk=;=o2YGAMXj{y~Brp@1ZyXnHw{|*c`4)1)dZ=x!d2Z z5nxl=n1K9s9joiD&b@MT40P9;{EdD%vOWBR&NTYhEH+Z;NYlc;<-^V_z8byP{;kwk z7b(9r9n+TBAHl#_tMVO;^rnN|=PkPY@iCb5px7&nY8L?jwotUUSaZ6mSwb$mS|E{u z(mXibD*myFScwDd&wz~mZgN?b@GWTQ+7wMJ+d&`b{F~a%`M!!QOi^*wR^9$vP)uR~uu}wt(*-%aE!9PsX>TCG zM&lT@g~4!RxqDhp#z*$U1lu{H#k4N zq2zAVOl@QT$L`FS9n<*#9Ex-8WL^~Ced1QJaQnoF!!aIdPm5Ntn@z<(Bx3@IaC-Z}Xg~LRnF?~k#YO%C z_H|R8hs8qP2?pX+QS4s8$YgI$;*5tgu9Qq)T^-7!ZG$i}u%R9!&CN|0V~_mW);PQ>m@Yf@RDKe0t{VXN;>0~BK*j03=l-OVXl&0wgE+dT7`5mw67P7R;mywbIqXYw zq|pAdqTyY3v%iv9Iv-**vT`dML{y=tsVh0zF=w94e(IUiUb>W=zL;QYEOhaA{-C0C3Y% zrax(LWWOxltu?#=Y?eXb^$BT&$LRp^Hu@Sg&~-mrtL8IvTOk^LL*9I(0Wlz<`O|q+ zcLDw5e?ANB(ZO)83C-tzqCxN|o)P&Nl!x!;^f02Kkrr0u2tQ~iv&13!pj-jdvym_| zNGiP9UU~<9lfg=wcs>jXq%86*jwhgeObfXW!C`^-(kfh&Rx+YY=LqhGU&uy~6+9d@ z5HrJ(4&Ydrpq9-RMVzH5%C}9R40qmn+rHWDS*kJ3^E7@5zGN|bTFDm znZmzj@Zdzy6aUalLCXNq&>33*`7iHcs_BI`ALdoboaLu``ktqKfK3 z5XptKxIYx(0);V)N?>A1fE+#kM>^n{YKQmD8}RVib%p}?7n?_;*AaLg6N5VZ?k7pj z4!tR~ZUDnWqs#hpDl)~6&QYR>Xg_d154aD=_vdO!L$u{S3sGKxnxZY)J;xKd22b{ z*^qj09~R!|&X0`HR{R%pNk%`2*5G*t!8%K6g22VHHrna7bUDjtHDQ^J zj95dhdVggBsm7XD@rfELB${?aQ@q8Tx+5Ww682L4&?BJg!ro3yKyjipdU9uU36(en_R}Rw^w0G%?IMg=(BNIxoz6@2Gty77L@~@<8D0}=HrHY-$ zK0so&@Ok2hRb;(H&Gq$_!h$m0gSymhL_MhHv!@Yz>A66FrZ3~oeRUM+QCY)hAcJQ6Ny4Ok_%>`IUp-fB`Vg33g|Zqt|02mHyMf$cLwq2xXP2q~}xA}S7y@qxN}aZi{#u>b%7 literal 2150 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 delta 2119 zcmV-N2)Os|5bh9=K7UTS`s`9C-R12mc;9gO(&K4xEx5R4ef$d3^~VoOOT|He>n+)N z`Rb7yo^cGPzWCXACreiuz?h}c>)X)moCRf^am+m`s8FMh_TiWB5gbbDQwJmQzL$&; zaRGxa`3{lvXC8!dKoRBgGV)rCz{vX>pZhb{r5YAKgrL%9%71EbG9!E*D@S=$rB>#c z*C*7{?Wh_jiobLXOJwzCMFhvLm8EN3nr2_mo{oD$c))D!i{OfNnqLVE{7;&&m&MNM zBhw-+sJl95CeDiugNi z?&95>>!$#&9)F4PVr*ANDuLFjp;v~Ui3W3_>EP6S&wKw$m}?Va*mlmp z3`S&HL@r!Xp@Y>1j$vezP$iLMIO*O)>~vvHd~7)*)lIc9e4m_?C(Fs=%hhYa3Pci> z++>LZu&Vy_;bzdC-0_9vLI@`ncG3s=mzyJ zc)@PUkD_I5jkrUq357pgknYn+(avH%8USzh!j>S-{zXD+9+jKG3A;&tpo|ocqYxd^ z0mK$%&VL$wk7c8bD}r>d$X#AtyyCHXR=0rQka~cw62sHvvEcP68sx}=qfD?2z4w(0 zeam8}9~LVV7hUDAnk7y=_3hNYW?wdA)QRWyX3JYVXnkvlCOAvcS-p_#{tFL(juJXq zv-ch5(p#&+ZuL95+f5`MP_`UJzVYZXqAksJ$$vwIM+iaMwo!zn`7&%;^yEZ2Ilw5N zHW^F=#kVD=LhHfqu*;86Qig5wF2p{MK*$XadCL-N5iU*FMk2W*X20BVZm1;j-Lc&Aa;3+C5tKCMIIWh)aF1ed~Q*ZWl2&GnZ@b^^Z zc+F?(GEc2L($Oz{j+n#kt0n5!7F^h!#h1OO zG2HM4cNuD=Qk55xS=9Xo|D=YOYk$>yyOM4uU2pdylTO6co>c~rCa(!Ig*z{j=YPRs zF44+;p)`5YO*)eD$7N18@8WU?_J7!Nw}$eh_&wElOx~&!IWw_o=T> zrooMxZirw@Bi@`t28;Ak^9qL6>7)`*abF~DbNxIxDOUaGtq_7eE%CSid4F@uNYQ~} zDsNzI(!p#hN$>8LOSCAsP7;%92?_0_i5bEOF>ykyBNMC8zb#zHypP_S*T*MR7?Kn3 zpS|{*{{AfYfQ>L>zKSUm;%cZGR8FaHZQbEkD5K?hZX3hp7GP~_wA2S@6N@0A>QOlh z>v`FF;7-2+Bv zP^RiF2VMV_EOJiTyeUE$qS6r-NprGP64Ter#Qu2^D6VR6ns0U5q^|HZ1vyucRsFAOGe#((>e}7j8oF??I`hli}j*<7@Zxs}i}9;eelCyC6a?E7;&UTcJ<*!uvgJ(&TXmANZH zDmZq4)cEK<@P94Vgoe1qh?=xze2_Fp1DKKRjulCR3Bm90g0j?i|9UHtbot1RCSt0X zHTxzC4-Cf9NYogDcSzxy2;d#XBcb90JQ%yfu5+pq;oA&jOm?a^TT!vqyi9%&yjToJ z4cyCyu5RPlU(%*bfS9)WtFA)Ng20oJr)^-NY^aq?J3vOsLMa2;N@~ysgyH&ff#AbW xqGwm~uj5}rP~-~U4q7u!`ts*aKQbN)=4nusI9^=+ch4FNy#F diff --git a/assets/data/tool-ui/profanity_check.dat b/assets/data/tool-ui/profanity_check.dat index 535270a7b3771fcb876cf58c40e14e0c0284c2f9..bc89ee5d193968602dc30c49f382a74d43b523ec 100644 GIT binary patch delta 2119 zcmV-N2)Os^5b6++I)6@JuCvx5()6S7{~yPsiN$C}kGj&`h7#$t#Tl}*(VHBYqjue0 zRk2E~maR_dJjkR2c_Qlg3Kk_!=9>;#8wr^TR@0aJjo&uylZNxWBC;<7iUQ@I)6|p+ z%B=QVg-n@^rd#6DmHX{QLqCFDYY42Apj8{lBkrW;dId&dx_{wbQ(rn!6{cn?m;u@j zv-E2>wq8!fUgGe++9Qlc5?UZu#v%e^tsut-G@;kPU=8(_OWGr;>I2%XfBBokUY9f< z4GgaI`x53tK(GOm)G#gYm%-Za0hNz*Uh0$WjDWZYlm|K&(DyMkcLg4yCGk;{ePtkWO-aVC|WhKK!Lb|u2 z_1mMV8{UW(`87s81@T3*?-UYSdT}H(SBfvs^f+iVdzQwNBf&f6;bn-YxM4|8SqvAt zL7sC8*`D_U?N&?(=Rk{x_^EG=EpVhYAD5*4w+{pG>bs4WS{Ua~FzF7eT)szD6jLleNbxC(?SRJT(7U!V<{QycF1M9KuBOp3TpwKu@V zm9;^xWue?Au2aLVGaCjp1@N=qfs`z$%7)D8E{b+EmnLO41aaR&HL_F6VOzw?vFw?)aCNw8hf?HG5VV!&qR|-{6vcc#1Pa>zw^qFve zhJPz>q&)pT%40Yji!Oo4PVY0yOz;GA#ngd=m#82Fqi<*docww>+IEMT^Qutqq>M`n zgim=zUk`DIkBoYIF!}ZfDX2A}>h0{sek_hJSdEfoXGvSPz&DTS4&mS1SBA~8t?x%< z(z0M%9SqNVhhS7}x;XZq5D$UA3cNp#K!1wqVHJcXb{%XE649UM+DNQQG|;!CD8Vvu zI}}1#LE;6PZoXoq17dnAoymdU?ZE#da-a>Dx&}TA7xY0WRjL5m}Xy#>F(u? z$L(vq_l6;!Bk+G0aU&YoYXU+LHy3Z{kiz!Z2ogE@{8k8E{IZ1qx$Dzs9=~HXm-rX6 zL%OXxEN7cYAPcjTmjHo-dw=NRKh5?T0C7Nd{wGgva}IbQ9sb(k>^&?SySI01&`F=m z6Z*;+62SZ{)6-rtV5HDOd#dSM1#w1yW*S4@bju3$?Ad~t)huPJ%gm-bE|eqdA9S}? zWD7AU=|aj4ay1%q(&1AE;%RXdlSM`qufnY*-;o zi3lE!jbL8WFQDe@t$zb~P>BPYXbV6ci9&j^!)|Ob<7*`6mhyqe6}V<@rQ*OC5Fjm3 zXI0{YIhyFtca2Y<`YD^R!-%Q0ysAP>m!@5KTe*t6>qfo}ni)*mTysc&&bT&Oa~(bF zj{5oGXQ{6Ws}-?dk;mlg8PI3}{64?~XqMBI!0HGjDyGsYDzF$zoA^U%S=GuDDzv*-G@&YF zD-j%s`Vkv9sx{54%ZQ(4o7)YP`NM|KW##waA`e?Li5EL5f;wbu2$QaT<0i!eLxYFD z!Te`lj2@Dgff4}{%juy5nS#y_gbLlK&?xA;yG7D_Z$NjVR5wF2@^YXKZvvMYvh0?; xu9IxXh<}Mk6_Y<#;uDhTX=hbf72|w`haKEod71583$1vPTlzyhT-z^Zvv&-g36B5( delta 2119 zcmV-N2)Os^5b6++I)D452;RA-%5-MSrZ9is7u@dqOu99l5|)mdIs6y`%&TQcjCGQ( z>Q1l!w7f5oP9vj2Z*2wllK)kFpCbKt;)X?n~h+#1xQx$z*jUPIZ%V=e}7xSG0c{dD#xGA{9gi$v&;J<3M`+Q1x%9l0sne&E+N0YL|f-b{$Zfp zi5YN|?vF)&L>`(PJA39rt6ArkEy1V}y7=AkIgETZE>X|~*i0j(kmO1l91g|=6RY-& zu`2I}EAhD%VRWp}s9Ji(%5=i_F|Dm4EzW+_9?cEz6o1l6(Qp=Y9;+~~WpECemL##` zSRfq6as}iAPEBck{=G8y5)fG>=!+cC`fmp&4XV$4X@MH6*jUOvnL9z}q7cS_cE&Oc zzK!Mhz+`HU(UIj?fq^)Bs$NrHu26Z_om2aodg!U15MG2foZwiZCwU?NOLLN^U_tpT zJ2-{$m3#q#wI>LX8m6bucT>Q*3Xu`&jpiQ5Qmk#%(BYHF2;N!L!ZowSyH)r7g2#-0v)ezGbRQq~us+?J zCtPSFsjwaehcbo|1Aj#)J^h z!5$`dR>umV60&mYqA0X5*0j!$z7SBJaX95^W=qdmFpaar17G_O4%-~<`1v=-a?zQW zwneU){J8w3xI_w|tX3akGA+=K`*TF>j^aSB+Txl8s5e{MFwVnlP~nQ|Hqj?oe_gZ; zh3#zKO+n1)Jf0a%Xmma1O|*38}i9l~ke z9eVAB*M_lX<{27Z5>=MZi~NzflqfiM>i&>%X_|#}k_eptSPPdV9~eF3k;%j|GC6y- zp!IJl!@b49A@O?|Dz0Gk_Vq@yU%H12PG}qCF4^nB>%5lst(l7Hu zmLuErX$lHv%h|Xw!t6KATP+4` zyx3M@R$7cRtioIDm75yW8EdL-6Kn&dFfQ_<51)i?=T^c1K3}y8=8QuoX9kmg8FpN?o;Lq_pMGzI1!(T9DLokcD7m)8Z zDS8&V2-X)^8x#5XKDie@NFv)lmQA)D;sxTZ0r*HDh~YJ((y)$v5`tKA>QLwpX;EnVD9y~#nq0aqFI^2GwD8IENvM3#UHvrQ?uI;_v#eL7c)>lglT-6 zTBFx@zI#m%lEYf4HS?f6rYznbZsbj4z0$K0!9~BKBN{AtMt@fs8F0aSoUuoCh4{-R znIGuULF_E`OkjO)jtFEkG8URz&P_19YQX?>ifE~+5Q5Q@+Vk*C50!8#hn~i>V%hUb z2GMPPi5gL z$`F46I4FF1ntv=W`{`4zaDK%@snP*Hn6w;0rNq`FcSt86?^)cNX+1>%rnRpzZvppn z0rGWS<{Ddh#JgDz{JGMYQN@H6t${1bvIF*gn30{J+ zGa^e%N0HxW)EhI965cqwbnGY?7cnpUX<<8C)2UA5 diff --git a/assets/data/tool-ui/punycode_codec.dat b/assets/data/tool-ui/punycode_codec.dat index b6799b572ad73d6f1d8e0efa8492470dd042e901..a4fb8ff143ecb677ecdea7541fd9766b1775a442 100644 GIT binary patch delta 2135 zcmV-d2&nh@5cv?0Ie$k8TG3)_+`v)umu=07O{(=RA5qJXCiwldj2Nkiep#|OuNS;3 zFpFrcQT@SZy=&h#N0xx39xXuNrDh=ufeA`x-*;KQ{9$I$=2)rF*Ws<+_g8p1;T+<) z)~d9bcPc?2BSP<@LA$!Q>VeH+Nbl`j|=^9=6@GdXjbgTN%zgWAq}`H#GBv` zNXiTD7W`dNu9_LzR(m1yB{Y+z!y4%!4R zrf*ZWyML?1)m;6?99f66*oNx_%K9VXnsQiuXaNuNk2Kl4Sq0(_4&ZPel!tjd0hQrP zj#{l{ke2D)M9&v;JF=MfuRA!kPz9~M&$MHMABcKNHAIoavE2gultY3b$ke>0xY3{j zsxTpzUrsh>A&w@KO`h`ZTz3r=cRc$i2P)3gx_=4RN)v@V9B{$SL>!HvdfFAV(Y-rw z6Fa+8+4{t_Msff;vEunaRAB*kz%_)cXaZH27?P%Q=DGSm&#oy_Ubw6nRsTWwwZ7#? z`ysZ}Y|FAZ0}O0N3nFx3j#BU!b;eHcgxgyPTYq;?fAi1@!ASufu!?Ntv;ZqhUTEce zR)3q@R&HehaBu^Oq2=s(G7r2|of|qRCr0!I9iffN2XajFywm0G>`>g$ouOlX3`sdq2yYu>m+oTLc8xtEyUu}yZ*hEW91dV%-F*4m4ENQ zaaU{=U}5L79-X$>OJX+5D9j*+Yjg;-z;*<5&*+xF`0or%HNHNLa)V3M7ZUf?nWHicd%Qg6xk zHoVhs>Tko-6fZ*#^i^*M^;nEl-G6yIU9q-y-2;&}gumcHtv1a&7CP0^Bxg4kGm{xX z{Khs?ZlHh+LmTF}hLi$0umE_!-0Vna0mNN#n1U3ac;e!(h z^}vr^I|n0Nb8GmU2|ZOcmf5qQfBSd5i|0Ei&=x|b@J>TTD&oH6hz!2Fw`Wph$i;6q zIs7xBl>(bru_{)YSYLW@Y<~*&vfF-0dS}x>;tE}abW50_9sB=uH0|$w8E0lsf0C1k z!qG&|=d1-EDmSI+OHIe~HeTHE^|CmfakG^I`lV`D>_Cl#Aul=;8L!x^%p(k={$DvR z%PlQ=S5n<nikrhY##K0d(q;q#mOxO^$YSt_D~VT;DD5iZD&+W>)c(u9SbqE@L_?Z1uc^4>4I#<0%?r z`%6@9jkvqMDgWmgsekWr{D@BS5~>Or`ID@HS;nNw2!X$58=JrtP`~Vs{I}iBAzE*r zOs>9um>$RAHkB@L?D8-MTb@{+kzPV$TxKMa9}++~HWH`PE2RB*t_@kYHe4`Q^gACU zB@Hr|@~=qsnxdUkH) z0^sF_kcMSlSk zehVvxD>bt3-v*36fNlzo;rws970`S9;`Bg3ZvyzO+fZ+Qa~$&a{e2#4B%$Az*zGnP zf4JPq#Xi$fmgMgj*S9GPGo%OFU1J(xv+575pKm_kcS1Dt`$c{wJpdfo;y+NsvMT2N Nz2)&9^Sk{hNi>89B@zGt delta 2135 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 Ncq%#*tXh7I*hm7v>O zbqG#}x|~7CH;X;gTV>8bNc<&S&mw(%_f3!MriSMX85}j~G>Ibt+;3o7Gkmz{F4HMo zq)EkA5Xj{kW&vJQ!z#+LjO6*K(8Ux#FXwNgZHyK+SDE*xjel+hz2gR6od-+jEjPA& zx1soIWW2GRz7Fwf0`io4z8-{D6flSAd3?&9;XcD2h%Nkv`;6TDtA`h*t;tVIdC#`W zA+1K`ZI_Z|E~LA)7W?4Qzp zU5#65$1e>DhJ(W@5L#c{@$+WD2%USe&_b$&tTv!&_V)7$X#kRek7{=%RH2>|+)IBN zUc;5aQ-27V-_vQs&I+MeL{a}fewI*%0x`yr(BcqIq|7a4YOnSan2#8{V05RJc?R+O1^;Lm$m9YZsaa^!R zK?ng#E}?3WRG$f?;h@;37huET;vlJ^DtB`mH-9@9P|W+(^D)v!PfP+Of(WRDi3-Ls z^x9s#EE5qAn#vV6T0fLJ6CU*kBdK2GQ^$&I@2M7Wfiz}lKhXHOqx@tDD`H)4I%y4g z&XMt8u8`nCN!$A6s6$Jle((^Yx+3OLhs@hvwubO8OaZkvxPiFIMDjyNM(CD2KGZXJ z9)F?ow&2a-2?))?jdhs+hytycw41=jRw%4W&Jw*^L;PkPVyQ~lJ1?~ z63nDA1YT?gqAVKy9w?#NCm$8P@IfbNvkn$~gf#hfe>e26o7QZRbkEW|o2D)L`hSYZ z7SnQa;!0GENeLweuNHH-eRLQ-5w*HK(V$T@ft0hWXaYufOmxdrj|S zxfkQ{6YPghhP;fMQjSv{$ApC9()dGT{#?78c=2I2USbE!*Py7?+ju7l3R24!HQPsS zPR_GE^=3`T5tFMvb(?ToL=N{%s(;+vpsD2Z=_F9;CYdeOoM@}rOR|7Z2ztG>%Ogts zW~V5Vh9cAOKkaf~$a+{U%qUsWKR~g~l&v&ZeKWd7T7G1kmN|N|zgUkYOam#XZtc^| zzS+dSj0;}A;Jv|THzXb_f%I8xu5p*{)}}e&2r1Jn5yai6mu0Z< delta 1377 zcmV-n1)lnZ3xo@hG=FzzW79UvjGvZejyXY2_i&43AWDm>FuJKCBbRw|ToM?*5vXzU z3uoSz)tcHA+1-h?F1ZV!J7;j&o4zaY`i^y}iMkLUaXtZB*OW$lY=CO^#jsgoZZ8qK zz?I$Boh+vP@j=msG9ORr4NmWVx@0FicO(`T2fNu_sYY+wwSR|?4>K@+37C1Bsry3d z(riGe3!KS;CmD(k;Mb0dLJooyJz|JGdZ4rx?O*dJ{(5Ys@ED$a*~Yqq@H6*0Fvy@P?e2hVp7 zsFmBL?q_h)&VN7h0!Cm;o1~e|B(R}ZDEK%eytgp&(*wQl57;fW6V?>mc6p}YJ}`YA zOfLZkYT=|?GC!h}7{U(L&^S&PT8~zGBUmC7yv8Q2W!j&O=l9nOXU0o!xmPG~riR3k za17s)FJ$BJny%6PnDNlr(+#*xSmnCwOGCN3fZnV%WP<(fx0f|2f~WUeV9*0P{r+e5n8u=N$|v}riSgSACGQG2e9^OLCr5l7 zlQcq`f+ZL!ZLuC>n42>L#vz#CGwL~71)*_Dv})50efLDL>ko)%_ry)&c0r`9$y0)gyKYGzusj)yUH zdNUJ^-sqLNEwNSDt)L?`gkqM=WUhz%A-ctD9)GprStCgSMd94LEEAu4bHY3z40HbZ z(Vb6+!sUum0KYY7C}a5a2B=K&z?&nhe*i<*37XD$^>F`tP5#mZFn%Es>QiX=E)Ar( zf%&kor>Dx%PeDvZU^G_P|6;p0$18+#=yT&i67F?4zuwbuE)ykx2=id+Dnc1^as8uF zx_?29k^rCz?QMAW=I$RrzZKqItNS?zmuj07@f4J`mjBI3$4i!utL7a3a$Nei_=?!c2c50Z&9U_4inoZ}bngoZld^FC7vS0>=& z9X&tRI`#0rMY@HB1!ywVrBSh?`=aI=l7C|6ua-le1D$T>BcN3xj5hx^%)sblO32ry zsmBtq3V4&!9<;h8PvPIh#r|nL+d!`GHtLT*Q*)hu9B&4M`Ji?H_4J{;&9wLbI)@AwUciN!I>x)PpVsfhR)03P z%U1}Ss>dw7`*t=)GLR4@u4?UYORlkM(N;okq_GSO<^2BA+420hpa!rZIg*_b2hROHcg zSP${V|3$2AF7Ho`Lk|rw<#kLj(o+JO44`F0oe6KT3x&$Q4avO;?u%rbx}Ey(o(xhV zDsT6~nUEfd)e~#_Pu(kmOigmj`g^2piMfXvmc=Y+_#On}>~nkaV41EnfLbV`+_ghO z>AEl-pN~_6!v$?;{xB-a(DAU;v*fNA&5&8U3)sPC+WLYRDLXKXO>$^m3455_5zg>P jTH2!dx;`zsyxo|9H%S0A zv(7uTLwx}PV=KWM{|~0nh5bTgDOZr_so_W|1o=U^CX_^=hkLcH7F~JG($YzAYJN46 zh2~PqmDWR4yBIqwfn(yEL934+VxB@8WXr`L%>5f6yaS6elYeAlDY(TGazIO|sX)iC zWs+GJbs$8ZHmkq$#vFwJGl##wmW&;RlxQoa2a|XP=WD&HS>V@$`@`c zUPOwv!7x{&+JBNdus%U6i&EyeI(ggdQ=hqqhCB6EH`DFBY7JL_ICC6Enu}#?{_g&| znlY>@2(ts8w$G}HdN72$pHac5r6NafM*+kkomf2uP6^u`}mHz zj9ta}u*)7k=8wL}OS2hl+hP<%Xd1AcU`&7t@{S{_15~IBrKqk$EF_V?|HWdk_iQ*s z)@>98`$K@ow8{i?DN}F&wfbfEmq#?Uw^}aJFD)$HL%|PQDIOY|bCvRobjJpI-m?@S z0zl+MUVmfgnut(+8Q&;>2>dfz<@&6Tt9!nw2`?=*1r?$=m}`r0S!IT7xuaqj>Ik{F z>y2 z7+?P|(nMir4?(Wl>9qX(PbZ{{TD_7a0d>H){8x78=CG;+!*}R9S33agK@H=;O!2r2 z{~aZVpIMSd>|N2nRHOG9_FHnR>8(Lifbcp?5|;sxhR#ey3;pr@S=l3`MYYm17|v7G zo_{vVH2seQRTUJ zogCRi75oBbC5`3CWz8#_A~WSyeCX@nK!2w)jA27t25ybIMt__PCt_YII0YmUtt?q5 zV*DwyW#k{X-q^NkkdZag_tDSOP%t-l%K*7dh_C$OMOQ#mV(>Z@w_2F@i$7~Lk&SZ$ z9k|Q(cN+Zk+}lmHS1sY$a2>VwidhHO1LL1-#Rr0@wNjcwEb4t^fKPH*aPv1PL4TMN zn$`dDp7HNUCO7VRK89T5`jnlfZi?48R3Hw(xpg9->`vp$*bs!<-tH}S#)7aTsqJ#qJtC(bP7E7hNbplDUjs) z2yXPuEq2m0otyiK1K5`3|EB@H;D1w}dx$gNfX}|VB;za6ZEPgg^fiE^WsA$4y+`kS zf{OAFVdC+Y?-<=9nOoqde;;vyCl&WN-~fNuXb84N1E6*0nqly!f=VVn(OqPkgdP7y zsu#j)t+`!1SN0K~*yTyz(0JM4M8s$pL8SjPK#|*vh3ePVNK)Y7S8S`qM}JA8*W3DP zlX=EHGmsO9w03si`n(Z@+T?6h?gM>tg<9j_xtKS$)ZI*n5b8;Gx6{fttvCr7)d#BY z-{kY{tP_6nB{gb_`CUv)R=?uabo@B7m?2ZTViAPc<2lY`oP`NF@`4vokjFPQi+D^> zO(U2Mn=FOcFv#8!j0i)Plz)pTh(tG|5c34_c*TsqJfj#!tLE#!O!8tsi`UkESv4|e zpvy@eGl`)Ywck)qsFiG{IKE?)r;-7bc*!g!^mTB{f2J7qQX$B%i4UyUdnrpGlP{cu zvLUsuV4I_(2c}^NC$k|x93u%`BucDJcq$U>8uW|&4SjJ~aDpdx=zKO?y5MbJB=b;o z3^u(fBo*W}G4ExBEk=%>QWM_7< N64MtortGt+{T#=iM5+J) delta 1667 zcmV-}27LLa4W|u|H-AQDA-+bl8(|A%`y)-HwC0W9Uqh+NDt0?xzG}li)~(mQ?y=xn z4`k1cnAXIX3sKZT82B2JWsU6tXHId}#&=ws%toSh%67mgg)#GkEJ9koM)CBhNbSH` z2d^)(^t&roEAOubRcU&-_m3PUoDipZnm+vnvC{bL@5lw1^ncfF!Jql3#^^UaY93Qq zELF5W=|}i*yOGDX4ZJv*CI`e~AYqwks^>e?vODNPe3=F$2`$fRr7C#DMGp{OsNSBC zuI{{8qr!M8PXU;lrW6^EN5tf-1zK>pg~b{GGx40&sPf2%w+p!mT6;p$tvds&RML0~ zynnX7x9_R_41c%UknU$Q1xOBjRzx+3?QmQfMt~xbT33q_uuoa3bNn)RIGvvCQU%Lh zEJwCM1m0aS6@^E7hoBxQ*cqp}s-wC#AvD5d#V}Igg&w`zwG0F6`~Q*EkGODIw^Vqw z%7X!V_;=zRYt5>Yn74|jCr}|%f7ijC4Yz9b+Wi6@Jb$6LIzD)^emI-p#t^Mv~(yoXb zuu;gP_=jA8$CU;(Eg&b@XWrAl{EI|+EB|(an?<4_Y+s(IN$Q;KM0u_u%0LAs$rJ@^g&57pHL$W z!~r0oH`+L8+gwf#4v#4modd)fA(7G@(BfmkNUG%F*wN&7RwJWpnd))yUN87~3pcgK zz{7c@JAa-&a`uwX!1BV<2Gldu;I9VI-)R~~P(&m-W+xo-xEQXk8<NRh7Tp7N=isoPQ2i^^28(EYgnCA0#b@z8;oq!Rgi;F4prXTmea5obSWTmw z(|?q?uP@_Tc!%Ol=npE1f<~v-4_>S(&zDjI$y!mI;)q5bBHX7%+24DzqUIo88LqPS z7!c#K;eRYg=*S*=@!AI=q`vmw*(%z~wW{Ue=*foB0Mg=zCc#!pck8~4uAv0i6?OL> zVQ?6U{y!pX%i`_&f*JL$tHL{(o{Dp-fqz0(dcE|{`>}6fIs(WMTHN)S{{}e*j{ZU0{rzIzvNqcm%3%C=KQUjDH;( zg*Wt_O&Iv2Y@|QvzH!(*~2&d)Yi2TVSJ zmj`5G_6yoCDGA>0A|sJadJp*G&=2UHhOthDVcX%q(R>J-i_f}9WJ7qPITg5EJ&coz z@sA@+kd#`yfYLhR+^EOR$XoSZ$Q z^eW|Q6l7<(CO3CvUg1^ieaJ)1r0Mv(VP*@wHPk1t1k5@%%8>8YqxXGy5r@%%bj0F> zVhE;JQ_uHsLyFNmkVtAgWb3rvRMQF%m7#G6ChWXjKWlihwBmU2O6cXN`+o~$Xl=7N zfkuSIX8Fwo@UM;sI(Kk+_t)I%?ypPWTiT3Od-79C-=pa4Nw3fRuun9+TR1DxpW#|o zs2?f3qlFRDg)i)^#MIADNmUPb+6#whMviJu47}v2)9EBF!KbPfrEDUm#C{P=RDzM5 zj?{~JCmpdiWzDgNu_5`T(0@Tu2t*jzkoJ`zM$QMrMi{sbaDL0%b6loXfsCM z3q8b&Ed+U*jPHqn$drPWSdl!+RaW1qk#K0 zP|5p*oyQfhUFdeG*(cVhz-;5%QqD{;{@rU51N^ih0$S1!w5LAnIDC^|g`##>J1BA7 zrpS{*1!h2wk&_;6#G5K69~2Q41j1(`Ax99>(4GTH;0+ivg==Tn0Q3@w&+mwm8M0Kw zsPoff0jTNua@!=`@XkEjz@o8+-Ch0N(?18Y(F{?}h@JWFZXAUIWoZy?*ZCVK>>Eh4 N$pyPWT_t%`k8NblR;&O3 diff --git a/assets/data/tool-ui/qrcode_scanner.dat b/assets/data/tool-ui/qrcode_scanner.dat index eef28e60460932037c7bbf64da1982357ac38011..3af57fb566340312ca8ca05317758b198172234a 100644 GIT binary patch delta 1667 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 NHDKf7O;w`9Ex?#gF@XR8 diff --git a/assets/data/tool-ui/query_builder.dat b/assets/data/tool-ui/query_builder.dat index 65e45a51662a56e524a74da0ba77ecd468a3bee8..5f8fa1b23f6830440b2a7f4252f415719dbdf14a 100644 GIT binary patch delta 2135 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 NL<$IJC((lRpf`h8BiH}{ delta 2135 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 delta 2184 zcmV;32zU355seX$9e)jgPC<#ozJRdpoCiD)=<@m2{7%t3YF@2!*DW#QPH5-Jls$Nqai7*Y*HT#p@a!Q(-(tjNZ$}MT}tnf~!l3|rF zbc~DoelG8m61Ju9W51#Nwi+@Q7md7RZ(#tKL^X`(K1)6~Rl%2LK9$BZdQj}wyep7V zRbwI|857ZreWzmVe$y6S?Ua#|vT-zmhwVVY_m=s`7-Aah0~nyd^Vbd}UAU_NI;zhq z0{(yC?fkKwIe)+C7^oJKl*QFVaAF^*3>oJZbzouf|E+Gyio~h-;*<%n=tk1_RhAc~ z9Kr7n{X>oW`MFV6D=GNre%9MG7v}@oUK@@Tkok1B_^Y}~_9fCp?>p;N3a9n^up_lR z1mvpc!um4lF-DM-RTz?uUiM;+t5^jtT3A&h=WP4+k$(f6Dkpw&!NJ1PCu_``;tDl2 z7c-7(xHKf2ew@hSB+)T@_~PudW7Kw{gZ}(XrBW(}>_Zb+4)h1s^aVeWJ@8IbI*cg# z2nKfooJ|Hs6Kr;vr%-E!%3Y8rIO(_XrO*||k{r5Z+P}-}vO-K2$`n^!f;IP6$_(Z@ z5X>{*C&DDsw;XKJZnm6i0OBd(RQ ze~e`8XMtvNkVD!6D0i(&5iP#IfE7&iKHmmp8Gmc_WAV4#IE944bq3T_(_l(LPb#x;N=&N=TdaoQl@K7G3#cd&F8h zeg>+cDkR||6jat}++92*k*)HeB8rdIs{UK@w9spA0JI90pyHl3m#M7bonhIT$lW$_ zO@G|`ftSj3TehrsZKCJu*q5~Xm$X`zdZBH$D}(=S0~ypCFmG5QYuvrE{+uPHY8Keb zU>UKP_tQ)$VGbbKV$I_$wU00a%U3yPmJt=M;k0%738YunbjD`1MWC*`!97y%|nDoUpc)$JJt| zyjA{Q@lHuNpo_jJwZobq=}9Nt{d?P^w-lU?;(P8H^py7~DBtPfl6ciKDOzme(CxvJ zRQ&bpTlu!#9xmbm?>xY&Z%h)gvDjJPIlJN} zJ<;vgVOFp%j0l@K&h6D ze=9FhH~m8&CeNW=(mcnHi_-#Cy5|#I)E%Jgj8&L;mNU6}8w#Z^PhXa-rI2v=n)78; zY(=jop7pWi5!)TeA!!<`8Go1~y6=%G6UbAs|51OWOG&QHn86(#LE);NrE`%z zG-Br!1r-k z=gG-fKj`RiLg>Ch#Z^LV+2woS;BmHri02nIgOl1+0bLm!#&Yj6Y1-Gy0)P39brio~ z%&#Df6<>qc9Y+ulxp3oIX)fn>1{rR#;#uP1(LDJKKh%4#4aUI&f6e*mo9{eyW$^1o zn+qEzDV`@}`Ku?FZ!@GuifE!xarzb_{;BI6Wej7t!7kF&e`yD93irjG35x!=Bcj_H zXYOJp&5;fioCMq*NJ^&ant$ho&8z*UQ^lu7Z-@ZcahU=h&G21`M+q(bna|9?n)nQt z5~DGr)nNY~uAskbdv>&n;)Fcie>J7b}$TdWlezAIA($Y z9&fhHx*b-A;3ap-<$o{1*=xWFYMQrvL1JLW$cHo=os-d!XIg27=!L+S?>}7G)dJ$o zshO0BKR5p6{$#H62|dhvSt?|+WLoU4#a}`P2VSH&$i5ZWUARvMmwWjbuy4L~JRu}v zT>qKjtFRbnKe*94sTj#F4%ISmGb8u6#<+Sdq(KojKTosjtA96_i`X2aq12Q_qz(xK zRRc#3(rmIF#_)0gqy+-`HH!aIY^}m)y$FGz&hL?%u+uNa< z$6lHoS|$U{u_&8t4b%E|8nbM9xI%Z5T(rYlVaCFT6?H>3r>%5#o6-Q4>}b#uLPH<5 zhzgE96XUfFq*j7TE&iw`iW^y)9);Mjsw4~#Uw^Xj+nr2|h zj9A35_bb5M*RMd_JYXqAgf3NV`q@H$7Cv<;*^@@1xqn?!`k@)hrPtYTO>@DjpJWn7m>Q?Pp6}}E_@4^IdE6c_aluZIY3S&4GTded8 z&2QyP*{hu(U3?qM=CXfb{%=6f4}GgeL~St21CM0+n%(-&hkv%rC$O($Hd)s;hFHWx zZnw=6Q6ns40uz_KCCz(>Q@lh<^S0@#Pah5Z8g2;KmUXVI4?E5PqjjIggI{s1}b!g0CJbw}eymH#u*IsY*Y(?d5LE7}> zvD!M184okdb2eJn?`8>0Wz`XiZH<}v9L)T+FtaPm+U}~_dY`n!yXdk;4-COe zL>ypny;=>yz^R*Hwl;pyT5A-&bF8}1W|&` zeeE(<%mo%5ne^Y zMx$sf`+m}GeimRP$%h>!*ie=`n{IyD*MEgR;w{aYuBn@CIBANp7@%;T+{F5j|J;Lu z)*e|~oGfCQ5xzJSUHrLu>LP+SVNsdO$AQnz(!%@VoGwcDb1GSChX9F|$R-+$gw|=k|X_$s}{gOjsPIJMo0rW9+4H zmjdVtn5YCqX`f!7N3O2r-(kr~uzv@^l_Rng66rci4rxa5X9qOY5%o%bmK-KZ??-hJ zfBkId3WV1%&x`mb2lo)c!?!!N!;ph1p3cvEk}qnZgqR)5g)B};1E zK8@bP@g6$h<}Er0&C9YUn0f?%YYXw_&J+;Jr7S3(P0t&=kxR1O2Q`-PPpKtMcn6k{ zIRQ{t#E^qBaTSQXxkQ=-_8DP{af9#oZrz zQ@sF-j{`7b7@bhKgYGM;J%8=S&uqnB>KYaGnvWog=9kt+W0|y!k8?M{gcP!5J6%xw zmnCr=OEu+#ndoXA;L-C5XoJ=TFY6rN#O(|H%so%?!JHx&Wo2;xyyoDDFn8p6Rko-Y zl){8%vrnJAaMFACNb7@dS$yqy11hn;gaj}jOu{XmpK+zoXn4}t{ePwxD!|Xw%)c`y zSPa_7S+Da26M-x+Gf@+8>>=YLQo@ra|8j{L+K4klECr^1KKt++?A1v)=3g-LXh;Cv zR>*#vz~xsVc!}1anO19^J5MGSJ_0*J_+>-uMN}$?Lgh~P{?|o*8j1I%Qo|$@m$y5X zt?$=^T6}gyqp03!cYo<H%Rwo<_@!?@09&+2=i&9unPi~yOyojAQ{Fu|59Ax}yvj@ygm+HbF-X+H! z>u5MaZ?l!n`B0evt0x*`zmeahtHHZ%3OL1QeNJln5bD>4;D0Qhx?5qGTOFJBS2)F} z4D*?!g35kjZy|&xzK(t1y>2?Z_fbJh#8|&o0q7a2LE=>ev-g%6XV%hkK1sbr2HTYM zaTnGipeR&P zP!3S@ufls&cz>bxM*ZXyugUYX|GPgNt}^oj=`uK717MEP+SayX!9 zI`Mv_=bfiu_%ADc1!HEeSnM8P8R3Z~@$MqxL)ayT368G7+x5mTcd_cF%bI+=2i0Oo zydSh}4{J_*&-P7IB=rvYIA2%@g_X1VP`E#b1bV-=TYswkAkE2*DLWaS=RGQN3LLmy zUdR3v%?SKKIBaD}_9DD{7W(g=LdVH*fRG~G^AIR{eFbt0k8_S*8uY>|$;SeUzLd6< z#kL~K7IO`x>*h$mz~9dTFhE-!f)@c^M7MMxK=-g=PYfl!BOat{F_xj=(<7lKzwsJc K(jdW$n*r9FEklR^ delta 2167 zcmV--2#EKI5&0018Gk)+0>sE}T4_w@InRo3mOxXlG&xV#1c;fNpOHa7fOM8)SQyt3 zDVaFhAUL~j58Hm~anqgUsVFZaKm(p@&6eFbGV_$Sr7IZ_x@47aa26>K0VXhD=^CC~ z#IVkGfvL(`>e}I48=>#}q&4sd@ra}o4uNZ03p(oxLsHm8(TgpazM(t`?@G-#^6viW`OY-*LV z#i%Gt$5~0QGjW{+pu-7|VpAV)YOsJT%!Qf0L4h+3Du3T59+VZaFB}ec#s~tHDaTm- zLzQ+P$1VX7VO?ijfIdIl6oCj@1=F=aOe#3GypQe%fB6+wQ-_6}pKwQTnq6PAi{1LH zMkUuv>5$vqFb4)X7zM3n2;R^;6HFA`7hE3%R#!P`ea#0?u>q9yl9Lala|voyPZFFs zTi6-1w|_vH3T*$&=(Vgu+|@UMqz((5Pk0tmf&$>ylq1`eHxCek?(;P+QXZ*kpWZ^) zaMC;IIuB?h^}D-HE!Sk2hZ1beB;icZz6_R}m@OtmszDYBfI>!65sjt1r?@@XPlV$0 z3a}@%kV0`r7-Vw;_M0K) zWJ9u2v`aMM$H+z~+G^_ECfinLk&tcI)+9G&HQl;0)sgK~@zSnTDF+Yu3tDggAWY1? z5A%B+@sBhi8H|X>LP6wcJjZu5yf**YO9z<6XTnm~7tT)*?4&&slJpgvXyQz5&Ktis zUw@em%8hyitNCQe%V;KvvJLK+d_}(Zpo{*Du>(^f{R*~Qqal&))cuBqJbxV$Dguap z!ik-lV;RI|>fd)di_<^3o=!CKF}e?~Yd7FUVIZt)>%%n*VQtNFVuILPKjn8Y!f17m zl8f^{t`)NHMf2*n=bdV*1JLTjUM~i-E`RbQM!$!)DPIrJ6o6n9u0^S}OnM?daq_CJ z;QD$eyyi%W(^1K!NFJW-zsDaEN4ve*%sBxELl4*ZwSH0Vq9hYQ_at(Nn}n2Te`^Z4 zr>(vTk=^5gt7E%TDlTiXN~r`~Mf&o$3*|Wyn~f1UPEI7Wv5(R;&iLIUx}=u-D1T?O zxu%&t6pG;+1C+RW@jp@qo967aPCPGYEm4F!+DIjfW)+VwF{=zYNO0kbi7K;iEsCfX zd*u5TnSb>m;~xVZ0+p!sPnpj3FpK97XQAyjQztH+z`4{I(VZ}^8gf9wR?_OS5D_5X zd`@Nfow_R>jC`8Mi9us(x$4VIN`JNct6iv`9V4~*N<{o(GWz>QdX#A%#~gyBi?yEN zdL6uPm*Io9k6fAX5C;<6D}E#HWu5KsL((efJ}EGIfz$k@3GZ0%kttfoys>Hw73@Goym8OPmDbw&uj+N|p6p(0`Q_WD7=8 z9`e^6?}q_6NMK+(c$(&TILzNYLRk{40keWMgcj=n$Gy7@Yw`D%D(dCSE=a09M_M^R zn)h@B!HrLrXL6Wj=L8lf+bOtJiFaF##(U&wV86l-^Ts?JO&XN_*lW zHW00Orf0nV*6A>_+3N?g)E%&gO>xul)l={4bs8#7=EfO0mPHwE6uE{+|hJV3;9uDun)ZBj=(9d$cD^_UMf_JO#ar=s2Ee)8Qve*?HkcG zUgiJ{zXqdyB7`c;maAjl&|Q%I=XeQ+j`CT*R44B z!6(8Es~A)akAEQlPo|l98_RI4yQD0WyMNO({Hj;KdqKthDO>J4i+J%G1?HuHaOR1v z0RF(8iM4hEVAe|Tqgc|1H>{MX_yAgT1klK(2d9g2&>URbOAEu`TX>h>y^M z$FHXE{l|-oH&oyif2D`GH<*;0fIbK=$a^o1JOXZ3S#TKPMdw-)CrAisFoblz5y}S4?%C;fiJgPWn%HUe8Ki#Rw@xIGbyY(xzq#T&$*tM|K_1 t^Svuc5bEdMo!A}UUPKoyckY#Og>ku>9VZ>;{9HD7g4#5vV=V$R8+c9cGrRx* diff --git a/assets/data/tool-ui/regex_preset_lookup.dat b/assets/data/tool-ui/regex_preset_lookup.dat index c87e5a284cb3e0d980ec4139980843195e7a7650..c90aa5f099d5a16418b4090ad19fa7c3e5b04a43 100644 GIT binary patch delta 2135 zcmV-d2&nh|5dIL5K7aHk1>kU}I>FR8yPUrGW`k^Vi`oDswPTKRyUsPRly7*S)xF&n z(_KT3)0H{L zjw6({NtSrD?@8j$EF@UifS5CEG!k4p+h>q;Bl2i~16>@S+<(FW;@{YY)J6MK1F+W< z^=HO}#xx;eRUAD$`}KULw*sh|orQBI`#bnwA5hFjWb91}rhdYv-br*jQ*= zY)8>A0pC@hoPXSa36}wrTk$tFXKLr}7e2|)_o}ivx;t-lBkRUf8VGET$#fQ#L4Nxz zElUG8N71(I>5B;jphDAf)TbIqp^-Xs_qW?S!=wcM;?Qf=U_}oQE)=T}#|-lSmi}jP zGwX9$T)r#B)0~*hCbrZjDLK`-tQ_1cu!*6BKe{6-_J2wE;(!L@*4ud3Z1!2&v5zSS z{`atu6>r3C;~n5_K*faevb1r8e^ML2)u{oL{`aQ!p$yh`S{x;F@4psqAs_tOnntA} zM5=}y1SK3VDErhULHIERqLL=EDUhUQ82r>Dr;=rstM|W;U^MOtq#$dknl`qMNe{>- zKxs^do_`?>JoTA7u%9PZBXVhbnX|4s@O#uj7PYCgQb972yz&nsFp0kLG5}!5qibtS z(V~_$6uOwliV$M03SI^jH@6@vJ7zK!SoDn_-bP8P6ZPGLuYnJ60xo zIxLd#U&=yfcEm|Aer_7uB9>%;FM*syY+tV35q~3e+dTf)8>)7RyTMr*R>o4XzjuC7 z4cN@wYN?JJkE3#n`y#MVu3mtF@ejKzg&qYYpXbDVYYBy?MJoG>!T39boZVZF8~7*P zG$?@fq7k;NWU3u}lDM2wx8hT^&(Qws*kpfZ@z#@fq>GYKK+8|~MQ7CF1SCPtxw7eG z62j=^j2bH9I2~)TbkGYuR`b|IOMsn5P=DbvG6s3UDu$b;JH;+m?!D3YB zbH3{NTnm1oeu|^;99E~x7W`z=;je9bX23yI9qbj~UcS4PQ&{DF>96eqoOBrMpi?x~pWlsv|SYVmT zY`lf6INxWBp3Dcp4>${u-BP4L0-4!dJ&NKv7v4=?)2J3vLai4na0oRbb0*J?_(9TD z28qf{D`As#A@Hmf&7Owa{GOZ*=YQoA6mX2QU=h~@kj7;}=$%0UY5Qo-J!0}Af56R+ zevLw?$I^nB+0H*6_9T+Hl-dhu7c3aCy}}Ail1?`9lL+sH9~av3^=G1LS+19}gxCYG zjXwI~be383Ga8GE@UE{$AVPs>Wrb@?eFiJx`d}2G+o~jto>Z{;LtPU4EPplq*|9M> zXWXdx?PhvmQ7oDtk=?Nig;)xPYAAV~IHEry2R zl23d&toq>_DMN1Xo(V+sOX`ZoCG`=bYpTC@7YeC8kX1javyYUbStjn&6!Lgzst!gX z;9T`ZLl@{Y#fES&IQ%I!34aE5CFW)?1&$eZ{(q*^^SK3b6TSRL z$BIxVrNqlsvYm*dE^hM0q_1Fq-QukoJn<};<#ushJ%alK;e1GE1^R)Fl79{|*R*a_%_WHZLG=5_;5Nt17SCvkOo9Q-SrYSP&6xXlYD7S}@# z-wyGC6t*Ot9-oy(cz>zvt{zi~9y+VM(aAXzBk1CNaNJ%ik8FzqG`6vr$DUq}f9=<2 zT;aBOx2oIU1xXnMbc8_eXFQ8k%EQA5##6M2+Dkf0ox0p#26$%?EgLY^lsC}ILP;X) zXBmbB6~aq<>mzg9PtS6%#J&aIB6e+XUEVJ`6T&?ip_LWw0e`>$K%I>4Cw}gY(H+&F zOp-m~up?mKrfJrt56jslw%o?CO8l99t8S4bV$w+ps>N+~X#Hwo<_>yJj1%6s;7?Sm zzWgapZ`n3u(1HBQDO21@YNmUTz6{rdyOpOHW9;Y@v*1o@3(SCm=1C$m1KB%~kDZ93 zOp*nStSr0WpMOvXx%rX%GKM_MV6Cu@MY+5x;B+#$a1;|rPOuh2F{Ki NkMx2!=@9^t73Aa~b+#BwP8U}-@!_ZqODdx4+F0+{;Rz$C2nWR7o z1JY$(1Yt`|DfArZDiLVA-6zy)xSZRj56Jjzl+65Ie^1~&(SP-^Blk1#PjV5qEv;{; zS|h6f8WkyAvr9+u+IPYcqwN^Uy_o%e%k`Kl6hQ^d=H_Tv#(3Z35nIKB5OTk_4 z2}2FmWwm*DPZ3gmQ}zoJhjklP@ku3AJ)dCwVOq*7{(*+4lhY8qA$-Qm5?0#EPF@(j z7dh}5o0SFN6o3CZC?oM@XZGKK2V=`~l3HHa%GILx89YA-HMTL7>r}eiSB6Co`W>&` ztpU+=Lsf`$i^&UK$F$mciccxH)kq)P`2Jh#kWw>gJlqAZ$KVE1mrB}vlf1ufYA53o zj@x)9;oZNiB?!K+usDW#=%fG4;Q@5{X+Tzu=s~ae0Dq!7w@7un@cI4i(Nc0?^;sTo z=LV;;QdD9G>kIrL^_GPw2Lh4i4)`0=AChNIzzU6a$Kc~oH166-CyfV(U5RfkNlZo4UDCeR z$4=Pt?%44!<815AoSUD3SJTs9{dZtsm97P`une)Y6ImcBWEk#1!n!$yr_*5&fdw3b z2f^>MSlDgJ;=g%Y>#&BuL-lgxUt$TqAX*V#4b4N? z=UEk&td0Yo7B(g#JZ0eCsU#L(w0**XgvFf43~P`rR9_qk-=CCHf$X?gH0=PYx&uK% z2Y+yOum6iuu&{TiF@qEYSlI+QjeR$CT+mwM&Wti}q}=?9d$B7L>FiOK8w*)S;Jr?{Ti&YL?X+sCiTm`(8_QR2j;7bH#N z>gZZ1F87X{`ByMV1K#AgfkO|lM}PYn1ps8+??K)Wk+0g8gi=)eTdJ>B5?M3w&}v^6 z%nlM{6f+E3-ru*ct0bf4FGHdXebZq%UoMcjDYWnj=~?p68@xUo8>Swpcvy!xu+6*X zKbhHw(RIhHmdA({zwT^j@=VUUHuY&%;OYT)`0_)=E)husj_g#R&wpM>I?$25 zT}Akqo|snKIxy#C42wsTWWS@TN^^xk`(ZvRMsW2}55P0d&R}EKa21gv#C$ z#jQC3W7k>h^|Y2rcb9N4!1R@n1iG=m_qVp>LkHhZnrGLYfrvx#p^pG*Y zdMCC_$!gEqvgfX+aMr;C+bAgLE3(C zn2WKUYSPm0T_Q7j_M8~x3Fj|@i)5$cusUYY_@-S5;vS2~Ufl|-igKrZFN!`=@TE7O z7$GrGk14Y8#vpxo&@=CCk_jjZNFB|DY>#kQJM3w#{VH`(84V^|C4nrERqa zWUT*5cV`M>YXkhyvCZ5`31Dx&-*}rRMOrkYZT{@aWzuSed4CVR5;O^i5)sWRQf46; zO?k{L-w+#gqJihQU#tbW5>_%9nkI!@H}LSHe%3Ez5#gICG&Y;eT)#)W1LQtvX2xzd z|7F2x=n$E}pDG4)W9y3{z5$}0NDFQ^Bt@{^#u=Sq*CHyBaBJE}iP(-9>~a4~&rfIU zVBh1?1Ue_rY=4D+9_?Q?vPqO}kwDcyGl>EUo$!+3BzeP}@^SUq2FXb;9|Wh!i4DXn zxE5@CO;&ue49WDNPhnrf2}-X|f=%XapzzaB$eW_t@&>nTp&GcpyERjdepQ%kd6uC` z12IuF&9bTN!HpkBso4kT7eMM^MRqOPK53XsX^Z)`)==#NT)`|+7407lq_KIW`7~mf z#aD3Eq`Q32?6_@y-yA7Y{yIg~!f4iWin(BOMLz4+FE>bO)^p^n+($b^ieV>;)vs~HA#TpfO7q09=S_8tkW z-n7J>-mWp4?g#Hy(W-QIbc<&$oQknm@vJVB`9m(ru-;x;FZc)lv?+Sw;eN1$pypC+ zu>)h9l74|%^3tiM8G!}cCtGXxahLU_FK$u}?nnDkN8@*qb${MTgz3o9-fnK1sc4IE zcaB?xofUi^dx_Ru1?L_v*e;yf%t(k zNHHDpa`PlkXOT@0Ni|K4B~TZ`In}`LkU#kQ$F1G%s)rGA2fm@BbLRA&9tFl(;=7)Z zBHyZ&krOS@jQNDoM*E)%C!O^^KC@-c-haoVOoI1Tc=uyVg8RZU2(Q_7 zc6haWC*gRK$soJ7+1v6lC{TL#7{?Qp{Os7TjK#(wT50dUJ0U^gijC6ANz4G9e#B1@ z^#Q>zQ*a>`xeGE#OE1CI1guVmk#zbEFailP8I-Aq)kc zDHYs1Nf~DB5C`2bkj%#)k~V#+!$a+5YZ?D;Kz~E}LehuLaduJW{to&uB5UThOpG1T z1+vH>AJ)Iv?GwdwH~pao_q^K|mSq3ex^hDI(r@AraDD@A*i_g{dT~^cL#`v4+<2LZ z?Sd%lfUU2MBmD28*<^E%Iot{G=vraiFpMbZ7J1RBrYfK@)2d}M7Y>xIBO6=W%5qiC zZGZbmQw+IKe;7JMV-WtBRR75;dK8w1YAxK@Fx@8 z34RMp6W?%U2V%`Qw$SiE(ZcApcFNxj$N%nq8d5|4r9IFv5yfG zhtPP!JgMDV+pGHBVCPLUp9;3$(0LJItTk&3;rgB!v^U~i8;LLTx>qHn2zaDkqJCJe z_4IF7bi;VIT*s#;P0?awa74%E0$9S!L&E;=R6*&?M2u4^(5CSbgSxxOz(-|>tbc9> zz6vFZLk2`T#;KbBIyeV1^u9k`&;r}+Ku0~};Se3?zm<(7r;zf2wCSy_Y`5qIlqXNz zx;QuDkllLSW$a1Kud1;YjS*FvVJ!ubi`MKj@JdA2l2I5wfy$E1WT&c5EyzVs0iYUE zG33Bh;+D5E=WNYsV%fycpTCg9d zRVhZ@b)MInUWt@BBIkXE8ioOz0D6V-au=_Kr1avN7N?yyF6QC$3?hL=i+{qXnY=*N z!*Bb2raVm#W_2o7cHNP)&K-mLl^jf>vo59<^do)3+Owk@S&!?KCG&)b+kbC+cCwzi zNz^}54QFm<6tlbl&|^D#tTc}=t!;jd4EWIL0E{@6P6J-{BdoA9*IUv(Zchd&@`~dl zHjpw31v-eaAOoO6tzqkxfP716;Ko5@>>j)k% zu1ui++z&8~HJfovKf@}{~A=fDswLf$1- z=3h;8$UAfk`>}{>6NbQ%*rS8XGrbmU&>&y`IU939pLnfZ`Hwj20R+50!lR_m)`&7+ z#k|S|p~9f%`w)_5kT?Ens@RC~zOeJPuTX_9lKGO8eiOquNq?FuunTC2`zf5!JSTbgT_$F7Js`Qj9=1{9P_lKCHXz2@i*-LAf8Jye)MW8v+||xi|}ssEo>I1@ghX; z0A|x7D)_~n6F>yd&Fd)inJYsg$^4|e+2w+3an delta 2103 zcmV-72*~%<5Y-TnHGlZOK>M=2TpUNnj-95Ilo<2)gG{{#YhS~hZBq-et1GkS%M(f9 z3(0ng%nnRn)oQ&<-~}55;P{nt$%;4WZ#U@A-|Liuq9VU zDHI`bdEisY^2hPT(M=;*S;Pi0B^jZNN5rIiEtbiGm>o;jqDGt&i1=e&6v`%AcFXhm z>sYSYjZJuBMw(Nz;Awm&5PWEbSN&-+pYbiJ_K{6l)8{H3SZ8|k=7o>56|whie$<|( zh{7U&P+pJl1%L3}l7#$WBeFAwAVFZG40LY>b4*CPbPMb0F>2h&!@U{o2Y>57-g`7&MY6BIwoAZ{c9fb% z^@u>I0+`r@EIO;p=a*4sO+}@uzc}~cBgQgGu zhG>y+xqlJdR1fNvIfExQ`+|7*w3e7y_%J)ethsxGIcJ;cgtFfIH812`>!fX*p1t(^ z{&6oNl!^s~gr|THSh#LtW=)zkt#VO?Q$_i4Qkx>W_s2bVozcL!wnHQoD_m_$uHQc#j)18TI+axtkU#T(Fw z_kRG`eiDXJBD!R?k~Pb;^#|bc`hE8z7}K{u}8~@bDcL zWG-&6e_O|l%6p?Rp4|N0Y3U=C8)zv&Zlvut-#5S*?fH^`)6y`lVDCp!Mm7;(?|+`= zz_T=Bjt0p@$-ioh&EYF^#6k*-B(&jrnZKf_73r}RCrl`ygc~O%(U!K{pH`MvB?|8g zB|0}Kb(NX>bFEBGT30SB$xcM_Q+|>dl1xK|wpzl{N~P7r4ZcK%Fa7cB7CBcu4DJ%b zQvld{mH-guX{K{p^8gYS@yjU(IDbL$o z1N`$9-J@TgPkHwP9`|o&%HXkB7f{hc5jdS1t3LDO?UW0C!?O((KXL5kjKU8h@t{L@$NW zu)&5R2zRWx{G~G*jSa(xx}r{&(X4(3}shbS&pf7=K%ya8IB&ETN=` zUi6E!hteMJZ{1sK3PhTm5rnC9!u93>-42e_d7dl-6s%vN!L2)=tMGE&QrD9Z_WR(q zCXMHwMSn63QZ9XOESH0E-slX&Z$~Kx{x}wdD5CzJF`+@Jw0F&9uH@$NtC(CR!qs{7PL5=Pz_coA8c};Gxg?Q+ezL zaAaPKWebq1jCeQF7;gtVK=2ADSqamlaoXqc`!jZ+!3?Bn*= zl?^K%+m-4)AGB2=Nu3LNdLgjXXE@Fvsc$K}-brFkQww+M^nYI`^mhr4<9XtMRucfs zJqwrgccJ_I_EVLRe!#TUJ$~{(`FOUoNGPso#ZXcWs_)4jw}((`HrL^>TcO(PrdUy> z&hx88*8DDUla#IBYaLDuX$%vz`!R|9?JWr10{P-+^83qouhp4-BACzYae4m7TChHIA|`{MXQv*mNzX%Kd(K z9~TY1bh{tu4xajtUD^$&jIO%KI~;H6Uk7lliriHh1BB*cJDWgtDQ2p zs{3*@Q^_cq5 hT0vX?qGMPA&{Z3WTU_S-A74_i$q3wsv>?qIE(@bxGr9l( diff --git a/assets/data/tool-ui/safe_browser.dat b/assets/data/tool-ui/safe_browser.dat index 0955443157d2974041006ca1343bcfe347bd5969..2644184f854ff19cfaacce7388717f81738f50fe 100644 GIT binary patch literal 2199 zcmV;I2x#|NO-NN#RY@@d3;=UsW@TSua&LEYWpZQ{iK|xDB5#vC0ed>!bY-MlA2H<5 z)|Fa`Q7Ja(X;U+r;8ThX1&Iknp6I~q``s(`Nb|K$E#7dxPW?o`LODmQ8K|{-ap62) z!T~jm4m1Pu6QNI3SZsltwjj>Cq4s-wOE8*SzxuCtB|S|TiswGJ3onqA?t~@oGE~Yf z{$<+-6;}-D*d4IQO>i2=d*XUVFtAuZ`lYR_8!4=Ps*A%s23_1*(F&-Bbwu^QWnkXm zbcIRdJ98n%FQ2^k`zSUVFc)qt;W@h1nMl^uEZAZ+_#LjS$Bp0HbIlRIfDF@Boo}Du zM)hiJ7}j#ZyUfD)3{jO86E^T|EL zg-Gc3bg6`Uz#g#Q_v;9X*YY-`jRwLbpgf_c6mz>yvE04p~ZrYsRfvVPoqD@g^rf^-bF zoxjS=jEFc8FYWf52h-+qKCHa>AEG3()50qQhI8GtD*(pWzh-SgJ1L8ynquEktE$)l z_4O0nphA6J%O1_ft$dhvOzcm3b)_26U;#${T5w4RU#}LPg&beWJZ-5DwD(&EdtsMp ze-nkWKZUXpIT?L26H>i93#OaG0bQrKXg2rHH-M!XSKFq}qhU^XTonVf0FYP)K%y`N zq`9Y)iecs4m1QI>CZ6wGsFCZ{i&_6ZD43Ig<#BowJ5t85vO<2>OX}^gwl^%c(c$-s zUmQEjQXRdtN+o&=xLkk7S!4$UH2ONqPl^C>t3%Hga-;Pm$0xb*kCK|;q1UStvVz{_#MSzSz)6^}Z86Z|@T{q-CQX$kmu$J1yxTf;>8btJ zl0U4vJH~&b`cd+8mgCw@2n(m!073&1rCFr!BqAx8ad#zxU)Oa%xzWs#0uWk+On8k+#Mp;?coT zUOdwp!_5j%vlD8s-{`fxg=J2B3Hn};OO`~*RGE$?KbkaE?1!?7L1>HJglu66dT37{ zoq(EH)-JNfo0Q(6#N%PYs9p^4#^o0t`nx%A(?AwQF0?9SjzMZ33z-x$p34+SqRghm z1M)b|e6I+u>eCAlP{4MN2CN5&6yUc7j)z}GAsPqj+KxLRW?h~sl5%5{^L_$-INkTx z@u9rbo~*U;Bwfp5N_P)3R#9;~b&~Q=w%7`)cCGM_Rts*Xu+9GQy3Q%xWRb)b~ZxMLSinHml zHx-=~nO(s+_ykhirx1%Wo=b?L2SUX}D`Q*#D#DT%R9J38p;q&O8 o3sG{wPF9n~o<Q1jOWLr%^;%beFh@Qa6U zB<5ds#Vr=G@-yeg9csjC`v}J6)?`LZWy+aW{p^7F;wgTd1a} zgfL2ldW^B%KfS$b0k4X_Sg?Q8D{yAYXxu!)5jhWhYT$Gzl#){lDr^M1-%zkwut1w+ z#omeDvE9RxE)6*G#{fZPoU&)7d=xXM$y@|lb>&2*G*4gwNs&W!m;9%$0LM1(PugEX z((O_A&t*`jODy?APUG*dOi~n4F6Y%uCDOnw&~^z&Yl7!+20=F{cRvu2FX(`v!W9~x;g%eW3QfJ zO2tysK?^kf?DJ;i^*p6=JWB8|HKwj7SNmuMlrmOl_ZfY3c-bYhmbz|`w|dM=AKohS zG@$m7XbO??fnC2$ea;%?v8YSe=(T5`EdmaG&lst7#z{7;c zcf?M-^;v3Ud0%B}>+&yyx@JGyDn{{*+)hxU8l_pZ-G(G0qpALD3u66goj!1*8HHid z3nNTQpocFUbIafIqwxt7LBJa5_n5%GUIboFpJgqC_! z#g%nFbDIjA{K1t?|5`FW1IX5+SfNMmd1Pj4P8RJ#;54Xu>rYIGl-?2No(L}y-Lq~* zh@w=$v2Fp*OG52q5XLn8>G8)dxwetw34FC^Lb}LYO99)V55~)~6|_yx+4>-z;vu`b z5#?P#FanV7P{lX;B%*DM-CJ!U3F@81aM8*Bg-ivg=@P9y9QYju3>E;)lh1SY%v~Ik zt1OcE!Z52T@432m93O^K>Du4(pQ=j_QBjZ%ww>};rfRVaB|dI`%pkWEz5bqKjakCa z?$fOF7=m4NCoJVW^$Kk0*&^ap~tO_Rn4B`K0U#HLP_`6)91!2z_PQp2xG1ML}U6-0&{6cfPyA#VF` zYMe)k@Vq<5LFo(~%d$SElkTNs^?}L;s~a#Q0o-H83MMb4x0#B7`w)#|WQl;4N3@1- zFMFk8&|5dXY1y_V zNSj0O$3JWn@-x+^w(Fq4d6pvFp2fexzQHF-*TC=Vr;}vwu>lEHMLuL@nWAv-5DgSP z7z@jkFPFUY$``e21fRQJ3-spdu~OW}Gh{}K!Z__lnn3N5X4*%5kpCCOmv=p%k zYWf`eMJvLFjF73+wW*F+xLxISmP6qsjc4lVJKeh7yFOw2?9_rm4`urX?Q#W2QZ_2Z z=>5jGICS*Or}v<#4WWhtG01);p9xHyDDLKK@y>4)WWVs&c?iodM8GK!_7}^BsGOi9 zAwCdfN*=Svd&do0|Bqo|Z3H~(@iDo8b8?s6$In01c7nG8>#;-UBh~BKcDe-1--WQe z2jAEtj}=2RN`601(K}I?Z(-8|ryrw}6qOj2linW5#$1&DoMHx2Cv*^%%_`R!vVj?C z4z@u1#9LRthlS6MY(r1MXQW1VH>xgh>pm&WLj?vMdwe>6-Z3*35XDYd5?7n2fC%e3?CCBLQO zHJ?p-N0isQ;7CDTo@3q@tVsi3J!-pV*$Z#UBB@F+or2(!2ZuyvU`R3Xh_NT6c*4~t zQN)_e_CSP7HevtDK3@|ag0PvAT!%`~s^IhYQzQ*t$AU8#o`^BbS3UD7M<7Mp1?Klx z4i{@pyyKoqTpj&|qZ*f2@{XO@&4MQDZ0w=T*J`&bSSS(LD&d}_Z3Uq)P84v#{4(V@ z7Jnex5w4>9VrRQwdI5~V(Nf(Ei3!P$K*Mja4JA?o&6d1ovIi4KP2FQ14-Rj~-X+?l ze0w)=$!%>b@+x0~?K2T(aiK=GS|E5qAeFOcw<~KflOd2w`1g?UUs1$6v0!a-e%^=d zzd&z&v-qJA4K>*?=4WB-F^$lzyx#_BZl2(6*%p~rA^>t?R3lR6tl(DLJUv_kU+%*i zNUz3BIlUeCNBxyYQ{XIoed%~8IEfdAmhnRg#GH34)OqJ|(^lQC6-g+c2$p{|x;+KL zGVXf)9qPryhUB2MrvXgWWBgg-JDxa+Vr>OlvB>J=Jr1UH=CRw%bB~Sl!H=U=g;ph( zpo!09zWa$&ZQte;VjIe}6;~kal%JDJ0$bNmZAG41vyBg;Y0ixJyr>C}l=c2cvO9Ob zO`_pJA}*h7ka7&0O7NyBJ8`5{BacalY#R`(KPr=E#mPk4w%9>=gjHw@wG=2Mw9NgA~%XZszI) ZPKKAR_F7exB(!y%)*aS5tAIaR)$d|_MYl=xLc?mumLT6Dpz@MyO~al|VCP_8eoSst1*O+iXvm#cFKl0d}k(@9dY>`A*v* z;UF1-()rd1o!T@#i%<124ViTEM6N`jW=3MDTKuzGo zeUdmO!eHRq$$#a`tab*6OMTg~&A#>}xB2vD)>io{AEp9|3_h5nh0d2WpCqWjiXPF^ zZ>|ztLY$2!>t|3c+fr&4N|?7IagU}pyz=#({=Ol7{!7g!pBJUjPSlW@n2IfAL~Jl@ zPVUr2H{THouf%CBt8yK@-W6#-#YSOjhzXt@_D}tE(0{9eXh`PwRQW->h?-9C?v+V$ z8XF%-bfruYllS0X`Xd}8l`Z&jUz?@BQx(E{%8DG21B~|~b9VRdyZWwCM1Pr}ShbA0l6yjt6-8jzg|YMTP=6{wmI>uH z>bmlJ*MB_!sVuDKwk$Mw0N?T?8(*N_Dj#4+`1W?3{Gpd+Itc&G{ zEjqJl5$fDe?C|3+j7!nErW#nB$L@atm{b1IVt;kidRi`TI-`i7Ida{c zebYccnFJN7oyMu^3MmGKiv_29zvgrIVlqT=w7*7;ey{lwg|{+5wKaLAB&k{WR8E3p zsRj=?zJ~FYpz3EW^1HW=AREwO83AU+i+?LSh#s)r!l!0iz=q*%Kg@BJf>85zyYvjS zd@F9q5BgU#AeIshlu5*}?eErn)eU;Y$d3cFbrO)Q*VS`H5qFT4%bW0nF3DuWyv5bC zCDZX?OJ=oH=Aw~(tL#PhDZ5)$ABQNke888=6nj6+0}A{mE2{&0ud1-0&GjcP{eSu+ zHFsofO>c}4xi=lOB8{5<(+>{{Z&1oI6_;Qj7a62^YVvT{KAQ^#YuIZfLthK&JuZx0uqK52MN*%64reMc znjxF5elyqCqNh#MHc4R3Qof2v&3|Z8;uk*42hRj5G6?Tcy>t09Bp_)gi^J0QL1|3y z*%qhvRCLj|FeqaX#2-mAEa%hT^3Cni6{kD2nh606%nKTw?9tbzNY8#>QR`y-Cshtd z_*gYhyeEK63*I*Y5~MQ_vp}@)FLJCepA*u*Nr>)crar)vhH^+=1c6cJsaiv5iaV-2 zbo@VTGBa6HpEUMQTVQc*qsYUq(8HAcm$pe<%r}soNv$2o#;8vN8XQ0K2>Q;RFZ!q6 jpg9HN{mZzqwYeOQ2-WG{5fYvIo{#B0o4hkFKz|@A(9fq1 delta 1377 zcmV-n1)lne3yBMmIe#|d$U_$+ifa(|6IM5fVS=I!mI5ACtamsh(@ft04EG{7{*n%h z5PP+@VF7Eiz}Km(Uny*ewxYS~x7dWM)O~*vMM&#)-?~bHJ%*i`C9-?`rJJ*K9PtG- zwizI=dCh$qL4MajIfFejTv3F*V;Fed3v#k4l9QrgCpcAtM}G}C_T#u*gPTpDk>k#O{ovA*$0#hR!&-vBKSE=J$twv z!yei=P1-ytU|H`y!ppHW5t9#~rk>?Ww!gdSw|hFJ>j#*rIVz`D{)+Ue9GPV>+9tf^@Pd$U!g{1dc(6{4tGUUq<5M&l08sc7$V-aqB^ z)=;kD0e{RJI<%0bs)u^NY4v98xOWD|GRNy;QWKBEa@-1PsqiIggzfYHc%%}1m$38d z^y|^6iFM+HW!eY9_gA^dev=3ryKhQ9DW-QaJkGotJFAzgs;*DNDUr{LwsD?PxV%B{ zV0+LM&NrQq#wK^7-;xgO9nKvV>NW1Au6R=aN zSKj@+V)1ee(S4o{I`uNx$6`w97X3XP={whz?BAw2vDomxdV`eH_cw}JR>)qIYpd>i z)_>DH+=a-sc{pw#?>dchztR~G^yvArh5jZ-4hp<~KCI`R>_W_^;Od{*X%+X>n#$n3 z5FUxR%DHbJm@f@?Ziv%PA|pBrt&YJtKz-Dfqtfv0EWS_l8~3J?&{lwIkkb3TXZNg4 z7H2P%8HCkCD5FVlW4w9gph=^o$bEv?RImi}<8eGK*lRZ;a~+^7;zA481#w=>x0Z8Q6m z9qWa)t>F*i`8Qx+ZI@Eq9w5r2_K^v&4}bd3H(8??HPl5CPp!160}u}r{704-yng|} zlhqET5xsrxnWOx94Ra;jEiDBYYk<6EdYy+a#F${7QFn$+G7OM%5l2mc2GA0Fd8&h* z40F#Q7THc35Goti9}IGwoqbIip?k3@v3w=Lj)E6~-n(M22|8AME` zOKr=FNA;003Xn+_j2`8t<3LFyrGL+4OBqi*m4yZvk50Yznku@~A1HU%!!|p+IU|%R z>a7Gk>LDP@s_uGE#nWV8$E>C%n4it|74H6HfVj5Y`L@{Amvrqi)~q7k?>r)n`S^nN z*y)VPtJ|4|tiuw+Z4bcJ=+#(qPSD2%+X diff --git a/assets/data/tool-ui/serial_terminal.dat b/assets/data/tool-ui/serial_terminal.dat index aadc81cff24d760df8e0f64c204c50f6f8182487..b98299ffd5f160fb11168bfd253614cce62d7a94 100644 GIT binary patch delta 1506 zcmV<81s(c|42lepI)C;y9Y23ig+Q=PhHkGwsOt-w;{64ZpX4I-LEDHe1fVV$L+s}e zYv}Y(e$vxoeoC+!Xw5R#T+CKSDBwJ}UME$$x6l{ra0t9v4NT_C*UiQL%&sa ztYbAHTPgEk-Kx0?B~I)ujx%T{8&E}wDv7wWLLid{xVfo#Jmxyp!)I zRK;GOvPP9~T785Qk)OY<$a^|rAqE0^TsY{H)AQ*LcsT|WrvB3-3GU}PJZxH?eGrAr7*~0JCmu= zMD2ZTN*9o@r$upJTPluj1N64D{uj<5fiz~|!x57(?Xv%_dO22)RsmHon|pPi zD=`pv&rw~b-wT~cNN;lmGP+`}Ij@EJe2%MuG1_%D?d72c4ydt1Bj-M6ZmW>?=!&3S z_EG^79DifdKU6cJA|RNpDbxFQ3iAo2{#h(f{y5MG&JOw`18v06hfDXXi@rMoEp*CHbFEoE(SJ2%=YBew zm$>pC8|4!`6Z-qJ9qEBf?7xUBxI=5Z)+L}Gs()4XL9`$Xk<|lKCv3kv!; zn13S$=N8POWK01T$ZcX5VQx`R)OpBjf{*McTYVK-b~ zXD>CmH$Os+9VzfhX`y%&Z1lbAMUMBO+h~~r_If_-`G&>%8DEDhHNIf_yo2I&J&RE6+JXQb&x|Gr#l7Bb2y8zIjKY)B+k-ZZz@hGvmk{BCc3H!e< zcZ)#yndL*?ytRe1mKQGJh1#D^tJ%297fd(#li^tNSONDKBcr^?a9QdH>dTH4+(fe84oYy)J71(@XM(1C`$WFLDZ>I{>{#U<(i!UwSz5>gdvQ8Ha z0<%$q>JT2qmd(p2bSJ-VyX?uDFKHys@+L?;s$q7=N0%)lnMfT3Y$-jb`TRa0HDI_r(^Q&|PC<^rmZ5(|P0Q=+c7DMAFxLtbV~x2jYZk zQGXb)sr=6_$+=aW1i zMlVq7D=v3Xb?b`bBXpdWhPpBb^AFb5&n>)MKi;kRKl6V+411I+k>@+ zd5fs4-@RJ#xvcFff(uJ#uUq^R*&s~g86Y1uh$X8Y`f6_jSDu)+Uwj?G0LP%3os0z$ zazH!LjNjsFy0ooGArR5Lh2y3A^(l5~--viW;ba~AFNU?8&{`^O_Gpk^sOp}#bx!{n I^^!A?#8ay8vj6}9 delta 1506 zcmV<81s(c|42lepI)8^Cl}*{IBFfz0ywIH?wb`Tm&5UID?G+e+A1d^bDXXbiDLdx` zM3rIbmActo@;WkX4Mdck5Z=+Kr9rj`T-KvEWTw%aT!~}sWU~Xln2f+aNrL@6b4Gxb zYS~DEj};kldE@9}52?rkuWXq&2+C)hz_3+}k4rp>8DTbaW`9A75P`fH2Vi!z{Fc)m z@-{Py6;Y>6UNj_spbMmaV5SZMh;$kSMGKAJcUr7O0RZ~5Pi=b zrke(#>gAtmDVYq&bwLP>QAJ;szg0H*?z=s;=+Vy#!^-(wQwUmV>?}tBF%W;LCBE=e zHe2=1fYqKBm$yleI!*Rjs2_t`cV5Po(dPZH5&Yrj(SN8S$FJd2#MQ~Dl_pqB$mj09 zDc)7x=G&DY$>su<2t7bc{MD->{%%W)1imILj9U5lg#N{4GL%_=Cww$s=?^Cl2c>Fh zYF{;j<{#c0_~MYDmotA%E-sS=9_qU?pBKZR%^F|QBB7b@Gsq5ahDX>+M)YPZXISP@ zO|0q>=6~tL63d=YY=P9ocK(y;f0#8T(FCQFn&(zx1>srtl~YzP>=ma<3-XG9>1Yc- zf}=dO1lu`L$IxO^7qY}|%rTAz#juY{tQ_YKJM=@DY1UnkY@oj>(UK`c{d7aSZ=JX^ zV61PzP#e%k`m{AKvqzurvMez4?@>epw~7gi6@M-`SyO>-eZt46Z-n02feO#r%k-02 z>wp-^29^FH_1 z4xxz)r561z@t>_Q2fvl7W=W*6#(r->p4 zVu3VDiu(Uj^2JG4cxIW0aE)sv;ai_gzVs0dg7G_hf~(Q!34y@7E}<`rWa^4~&;`ZZ zV!5e)FWWZQ7F@kQ2FHZD_HDS&fo>_%a(+A#oyAr@8#M7_37+YAqGoJz8s5S_V2x~sy#1^g-5pg=yvVD;?IV8Me(_xs$~#?g z%VGaxqkGPe-hjS8#feB8;90g_k$>8T80_vsmX)q%mW;1p<1^EG%FgpEEbLcleF6Mo z0q)hHxD_lT&)+Hinrzb|XAa4VTBaOe%NxBE`DW$^KTyu3Hqb|M%QvaJAu?7=m;A}) zmh+En3c0S!I~`9}a@vJ8FmB0Lr*rY{l=HY?K@NVX8JX2$QQuQP>R7~Vn1BCFJBn%7 zDRRVgu_!&gTl-bK=HHv@J=ckT3 zU+SQZak%WIuZ+)%c$B{qj50OewOAWDN9nwpY&uGlomHEmoNXHodkFjE?7GwMplQg; zzPs-$4@ME|=O#;Nts9p~Nn3%w0P<~b!`a0On@xz7*3>34Tw}F2?p;5_S+#s!J+Qyz zR5i*cc@6*SbPGUUAP5-@({Fz04$&`IvZ4Y0Ju8o*<_%!A8K}OsN1SP&&mEB)Z7~cl I_x{0=sG-vMs{jB1 diff --git a/assets/data/tool-ui/shelf_life.dat b/assets/data/tool-ui/shelf_life.dat index 2e26bba17294596bde04d5f7a7dbc4bf93b27c04..852ce4254ca50302bfb4d3e05baeee5a122e2461 100644 GIT binary patch delta 1442 zcmV;T1zq~Z3&jhNHGkFPFCkv3d#{b!(|OMXGq`Exfz19}t~;P*)Y=bm;%Qs=^r)V_ z0wLtQj3^w{_0aS$m=#&|2&nJYf>7ZcU6O$viwwPA@D0Ko&|f>1dM;O!ff~+pT~#tR z?jJ#csePnwk0`=WAB{AhO&{4qjL>v%n>zRa~4$^0qnJhU`dB)quy1b z&r^W^>h}9XLO#ajYXOrTZNPY4`7Ta}k-f=6MR6VR^c{7H9`EBnO=O3_9zXgiCNK8R zBmv`=|JEbpq<^UQ)+GTn!Ooh6yV;VdsznUFbMfaBHCk%I$gXC*D2DZITBWEi`tO0N z(w03Pc!zbedtu%=dmS(RLW9!xBUYQ#n%P0}?V|2x?5N*v4lO#LR-sFlHuPaA-0o#7 z0``Z^Pd##)yNg%*tdqR;`d2P`k{Ske-*)AEkBRq^&3|16r-(v^^4ZvjA+!XdS5zWY>hc4(+HhySdEr7BazH*T73H|_UY)C>$eV%nZ^ewZpBq2=w zOSppI%zru^l^wmkiiSV=5D%@pFRALO#rH`*vSZH(FUv7~k!TK*6BCS)HMnqQv$>^R za~jDY0Ibj(fcb*7PBjrLdWmWMfQW-1XQk1Rogte$d7sOE{!X5%F&g(;IUaP0-pmy6 zOejD$nD^6lj^N^)=VkeUYIPNXc;P6Z<&Mm`A%Bf0+^baRqLx=F9cJU6o<2(|H)O96 zv9>i=S{2=*N2?>`M?Qu}cMP&AVf~YnAH%bsA>3g~XhFpEaf=;_7SgdXceNuMfmdI8 zEm2qU+5$T=_G!qKfAuY|OR3|>DL7YhrTrp>&^_lxebGl2#LT?IM|dxNli!am0iCn6 zWPff>LnvKbB=0?G(tOg|ui~+0Lnk4%SR|8sF{JhgW*!e%CrF26*J9^sEeuE6Hc5<| zVc#i|u$sm}7yJgLwpBiCGlAYsNe$SFhSEHAPC<|{v+#Mjet#zXzntN2Sls>pr}hFMqVVTuFu3j0ACPw< zy-qt?<{Lx6|B*O%7g=zk7!nrjxXcppyJ>A$pJXl1alVMMfi_}=B&eOL3e z!qK~38ibH0rN-2cueD1yBPr9N8a3YwC2bu34$1x+8sp8BAWkrJ8?9bMjqGit^?#=U z99BoDwk%?{w`OGYN#Cw&6wkZUJ#G;CjhCHJD-CFE9n}LkO_)_?k%(@B$B@HnY*f`) zhA82=`_lcG<1O{`R46rZq#DmWken+Pga_gL`zE$B+c82b_0FB*^eyL|3v&EjF)*^SsOHQJAX(?_HXE$Y0j)Rc3+v)@w z3=C~mu0;)Gt{@x|GWnsvtFx*Oe?$I6hU>zg8?uK11f9v6KliDo!HglEHh-r4l*og= zkjGHn=fuE}$ITmUs;M$ygrN}w7Z=c6GH;THBM>|Qc62d{5|`L<9q5f)!_v@BfvLX3>6GSyTw3GxjDj*7mTn-%iSI^6; wa273ju1O;LEniA>mi{*onHv_9JrH|0KCWE0CTr{3uGz#9T^dMtdxYi%bYT0;?*IS* delta 1442 zcmV;T1zq~Z3&jhNHGd>6@!!T+zrH*a=NUg+^eq$ar8|(Axb`knz-N~_!Kk>&?6{Dr zy<_FN*b*Z)F+PkjG0Nr$d{Q7CI&`+i=-bSQ&}mEEiK4z=Pe$f`%n^nN=B1+?&8>f0;-s@l?-Z0U4LK~}Rev`G?FLJ<2Y$pIiVD=p zLaTD)MdnCz)yE7E*KA6Eg^Fdql{ZIUnSXG-+|%eXQT0ibsJ%=*dhMfbjX|>!LE{WI z!l)!PA;3zd97m!Grb9=|fNPM(VnIj29L-!|@6{CZPUo3W;RpCz6`TdHSYCfjLuB(j#NDWah~U2_s+6c$gb_aN z+THGrt_s>+;`N@&i)`ZQfc`8ob@-IcoWJgdWulCyy=ssC4tXa(SavOh0*grZ2kR)0yl8JAzhgm-z=tK>9LL}A&s zBR=ZbhLHW^zi@5t>M=xDUYCu}F0NA*JtCQaNRCW;C|}Yp)ff)L)^rVPvd7SFQ!>Jf z*4dz6<6Dwoc|7x16q!_Us#F|l$r5%I;VXYE;xe7`BgyeYe9^T)QkQq~DHVm$jW#Z* zsNOx*6MwhcP_W3kwu%15ilyTvLyEBfJlx+@Olp)w+FVu8u`yh|B93_Z#3hqBzX$Si za3$XrSovYXK+DEOy-L$3oZoPFX5@B2H`Eu`I6DJ4Z7z+I%`3s59_7`Af{}XV#b)Qw zU!|Eh!*`TuExebNp6sESX!S-f)7{?mJ+BZ><$pRcf5k3_O!T-DGbIYdOoup0huqgA zb<3Cnnmu{UcdYOT&&*`~-vaUKg8|?@{ckUFp@eejtC+VjCn}ljU8tu?XXcFsk;mRH zAsLs1l*Ok1#{){vs-b4jCb*nInxKB;dZ#6{k4gac#czsGW30?*#9kMnO9G(ng0JOJ zM1P+EQHj4~y*|!5vLinE*(ZoxG0xQ1QzbJ%v~(ZICr{Bo~^0@ z!%KKbE^~R$sp8M1-=iX=#|jYQo0wJ!u1S|i=RuS{AUxVz1uBE8K+F2rVkWDK6{IMi zoEm6`0lL2Os6liu>o8?0yVc0 zg{m0}+ubpjfW`d{G`*I&*2PiH`MM@)w!#x;xVL|wwz|Ixvq5nV;oEb0tc$U|#o+%=Q!z4|q4(W96!#@L4d?I#_SDTyfx;~cH^IZAJl&97I)8Y|y*BIt ziX7NQ5rlL<=l2(qw8Y-ff2&eT1>bM9I5ezXpPJR@iFfW|9n^ii^%e}X;#6J!HWoDy zC=hx7O#G{5f=pI%4Kh0mQV!Z diff --git a/assets/data/tool-ui/simple_interest_calculator.dat b/assets/data/tool-ui/simple_interest_calculator.dat index 0f6dec6d901b4428588f812158604b860fa87048..1b040239b95039e5411019a9c25c38c1338d0775 100644 GIT binary patch delta 2071 zcmV+y2&8i1nc;J$nylF{GD;m<7mgW|h|FNYdB+4wYQ_+x{o0&lIM;j*$Ve{@9rOp+fl z6xr8$@MFih&89AapK0 zv~K_}>oU4X!c@6WCe2dGm}uL;8umArz>-FsR}g5^8y@(LFshhj zfE-Sw$7w4rI@eEo{OZ4S)atQ#q9lq)2 zQE!G4LH4Zx515G$NA@ZcOEzY09leQ~a?rC!Q&^lso@8t~#%Q}}gLm4Q?W8OA6uAR0 zYk>>;L3JUctmB1+x^ca-J#~nGq_Qd(sWO|N45dy~aeqbx>QS(@Jqc6|vh+LEHd$8a z?epzW8LbWw28>R;z4W`BLbM3z{fT=-x;!O^YEj6HtpJH;JLV&n_-+ z*Bk1QMVW+l^(zWxUBCqCZ3Iam8g9qn$D0T&s4n!q4%(zEkk=&g9qY(NAH67c$a?@F z@RF*WP=7d=)tat$R#f7kUUvq|l32(l)I5FfoE4!zG|P}VQGpi0gHG%~`6|)y7O{s# zp5u<92n(0{a*Wzz-ERsyq+c#jKJt}k4&rU}&kVjqD(_%9S>t+b{}7^1WXWR=g=fG_ z>0n|2hx+cc8pozvy^JNXAjPs>4`en%eivDyoPUD*)#Tq}!k7|P!55av3)mRvNgBa} zWU;=x)*8?~eM@@$pPfQqkdn^zwHUtHk%%A<%}T~V`|qS;Y5=*wQz3BF>% z{1|sPQb2kw0gS&3VHarMD{|-z--ZOGCI;ZM&2}j%`KyJmGwIao0rTdaCYbFsgki!O z;eR@56Krr!b#WPZ+$T(d?C?T(hc~iEP~RkEPq$EKp&<%fs}MEus1v+qL*b8nJ!^gm zH#;p^&oaf{MU4RW)btJ5l-z0`={^YRgaSUDnC?Ws@bzrtN;$ybW{b)02XEo84UbE1 zFuvu9>4nY?B*112i9wsF_jCkcM#rPp=Ye;<0M>f@D{M+=VA0g12|73arupNv zn?Ht@pKv;BO!ri{RSJ1OFvJv?o@_@?_f8xxW}bh)psdBDxdCv7K?}Ed0k4+-=681u6ra_O2id&VSi+_S%Hvsf5U&5M0 z16uog7VtqMxJpsK5?eUB27BZN<*Kr*6-Z!G-Ut9eHgx6my6h~H_*I05A~kd+3qNvA zZBK`^+&-$t0Tg0G4okql2BBe(3flL*sUUkvO-p3-kA&pyR`G*jvSb_vM}H5CJMBL_ z1f1Sc;)*2Tmtqo+cxS+^EtYkiA-)hrOhLnX-Lmg224y!j{@bt5drOVUAmM2|2> z6nVO;ltVtlX`N58e)RoNHGip>IVoD@?DT=KTC3qI9ER!RZ<1YX@sy1XaC;s&CkBd5k1E3oQbP1GNbIY7Cm=< zLhDArS8JC$oRI58on+rT5K4s1ZmDQIV@{ejQoTl7Qp=FZE_P}ieWT*L=&GD9lyk#z zhHBFN4z(m72D9*kc?f|Lx2*S!X6>tcO+*PJRnhTZjtm(Nl9hU9xql69MCQ7+0I3XO zQxgFw?Ena2a^50Le19+I)3u=EmhMPvY=3~Ol>shUt|m{O9BX8@`3`{>ANEiRX`b6C zx~`gik2QKoIDC7%PTE$U{F1x+CfwGeo8*$n@X`3!;2f0vJDloK($4Sq;R}Sv61~cR z5UBMa=7oXy;a%+ZVkpjYeZ$dt6P->h^$A|WunDt0Z|EIOXMai(y1rP8G~J4J_DPC( zkQ0F`6?P$M5H=35VYqHrt0`J=K2_L8bbMks>JIT=0S;I3lfs_6YYg|!#61p3rqa(d zGuLZM3>)E-ryw98YH~C?YE?3+>f70({FzIGc+hF1%zB>*>OxAy8R(W}MkF)lH_wW4 z^_4r%e6mlYD1XuqJza?Yn(@7DCT~dI)BQWmO;HY3nv)R2A9}T&V!%OCS^PK_*D=qI z2RZ%{*s9>HUjXq->=l#(5V{B6v*K156slq|12PYLZ?;c^B~3bKZk!5@id)hyW5D^O z*;BuD!kAAE{Nel)(tk&(6Xj*UQ<*u?p8PyUYw=n-6cC@G+KW9Sihb{Ie#*xcXc_I> B`lSE> delta 2071 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 diff --git a/assets/data/tool-ui/smart_search.dat b/assets/data/tool-ui/smart_search.dat index 7c5cf34b405783c3b512c87191714a60757fd5a9..561dd60c795617978cfe9c4676e501449f790b8e 100644 GIT binary patch literal 2167 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 diff --git a/assets/data/tool-ui/speed_converter.dat b/assets/data/tool-ui/speed_converter.dat index ce546c0a2974f6bd2b14f6c289e434623c602ab9..a253d3c672464db0bfd754fbae196785b8c44a9b 100644 GIT binary patch delta 2054 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 diff --git a/assets/data/tool-ui/sql_formatter.dat b/assets/data/tool-ui/sql_formatter.dat index f63f28f01dcac428680e71351900e8b4dc7e245d..4b5e8cef838ebad535bf58d38460c660aeffd9c2 100644 GIT binary patch delta 2103 zcmV-72*~%?5ZDlqIDg;B#VX45vKzKCL7SvJ;v-;PU>9x8LM$Yf#AE12aW`U@f+&-YV9~4K!nfD{)#{|Mo*@{b^HOMq-?E9%qSOW zucLle+bsi7x!2S9#VAV<>#SvqX#XgSJP-3@-MQ%Q_VOvc0DqXNM0h}i+Yk4E7G}tV ze^hzR<+(#SouELCF$-vKGx*BuYp~og$iiMH_aMO|xoy@$ang_9d?a4*AW%RdaZj5Wl8HNqO+|?djw+a-B7^EQ>{~a57FXf5wIZkV!CgEj*+y;Z z9L))Rj%;_+lHzY7#AmvKBl`e$swT5s-;52%U~E?QIe)S=V2|qTUrM}&a~N<#w+6)M z`#2L1gN{_b7%_23Ll+Vl{D$3>h2tO)ItAuqO~wjQptqtrZHD{iXzhQ>DXFTs_yUhw)iEcDh0q)0n_tZ&wS zE09D=@}+VhsUNNgrl>^$cr^gsQoA@@f@`KeI)BYgCjS~*&69_HZSgrye#5kcvBw4k z8k|Yyga{_w_0*2SVbS0$!i!d{oefhf$R*@E3?z#J5LliVloXOA8MB5dx&jp3(Q0S2b5iFLR85D-}Cb@`>t#>4i5U2cSZh2MQaB z6n|H}Dxb$e;G7TkoT*=Aatb_w0kVW9P|xI{PIVC4@sPm2QFCczwO^IOTngZsV5}Rq zcv9nTE2nj@zaaN?YSK!!3O!{~Jd8%QpEzX8N9FRD-& z+|aHlZIrj2)%iESGTm8~@SZKyM&>)M1Al6+g|O+6C)w&v%lPr&X;S#mHt1xPAR!(l zWF&T^IPqveq4i19PZo8nm+^ufK={TqeS-axNjuso=hPz9eLbYk=Ai56%6wL!Qp7I|rpJ*Qv*)~-N`IoK zOEBe$mFmnq7IgD)Ej${Qd_QmIk3o=pQgA$k?Rli|UJ;yaHO}E|?Wm!Jh&A?3mVwJ; zV55)5AqM(V8M6vxBGC&m4JY2aRza?J)L{enIy{%7z~E~|3w6XoqG8~{$w%8^TEg~j z6yJD8IkpfI${oT{>dD_c=d7U@S${KX!f2fP=)zZz!bTb!az3W-VYyp`cy-AoW(4%R z7#a?3U6}YvmlfMV__%tNDD2bSw4N}-oGEU4Al36K&=@o8n$hQZb_c6R_7nW{$PudC+|_v2LZqeD3$Z-S$g?;5RAN@7|CDM~^j+O1s_SG0qf{L*4BO5r zTr_0JULAP6z`K$RXsDcpu_#OV?L$5_e%ra&*&Z8>cfoiC5qn#Q7gGhdVdv8;t^xkU zmE$HA&Q^@_As728eLtrhrUw{7FPx{2Wsh$3* zuCZFx!8p7CR&Qv?g}(vCiikE383c zwQXTTA4TU3Nd^q#91SEy#=BH%G;BWG^tA{*Oz2C6^uyRN?MxE%+{57p1-%-#ULpFY z^bqUA6IVPO-{Z63SAT^v^s#H&h(SumrE0*d>R3>*^9eNWG~NfcrvJcHBu1{$KMOeq zaqf`wF|j-&oTdTf%?9zyw5FvfP*W%y5f*Am_BLxD!w0=yIr*By9y7x)YC*|VyT>O? z6PX${1zx0f1dN>2$e0p&Jtme4I zrpcrzV$f)-U< zn-YZDMgMa=6Mr(5dgDyx0+p5bxL#SKXs@hF3oK;!B$Y@rM6T_;0l*D0JH%#otZWMo z?uYub$LVl6=17&HpLwS;xWjFbR|@+;E%h#Xl<`yWB8vovI@Yhx%=1t?Mx!dj6c7La delta 2103 zcmV-72*~%?5ZDlqIDZB784SKKc0v;eLBJ)o9O7aL(_i-rvG3)RTJB0Tgh=(E$m;8= zTQ{@b^t18<^Zz&dSZNl{wTs-RvcnY4+zE^)K1-{`WGSuXT$K#7%Et2PE)8!ggR;n6 zUo3dd>3`@Bu@r2PUae*Xqr?HYwJsFvmBEt3H%I*TMTO6jK7Sr@7GFy1j?4Qnw52Md zGN=gpTzhI$wWkiOA<-FbQ?SM7Gk8WtjElM&?MjH7mPIc~j!}-V)6!%15^&>6UOt8lh=UHgNzK=v*HYH%D2es{mfD@Cpz2V7!9Q;~bEhXi(i1 zdO7n((0%UN5Sekzu5!~=wsxPxlRmOAlP`Cy6dWEmB33zt+aEq|k_9mZcTx^hlVq1=7I)mpCh z@fjG*$^8;#OXy25cJ{RqRnDq&@WyD7B_!Xxo9}t`N|NZxJM@G4dwY{GI|D~5>K~Wb zy&4uh)^h!Za8rFm!wZ*)?S;$B z_Q`Q29Dkv8yQVRY!4qR4_bJXn*cgUsbo}WJSUSTa!P1U%7U8ZCdS& zZwz3_kd$0p8~gP(3~=1^v`WhSHk->t1u2}B?uSk~;Wf;-JMFnicZhfT@3nyL?rR z{q}SkA8{s~tTFG|Ax@FX99b$oC07OYjND=*^>Jz&|AIH|!iAmyj`S^`I_>PD?>SlR zHuWHue!4$MMgF0kdaUX*)1$Ekd@8;=Uw^JZoHrjn{FK;cb+y>LLT=^xVTldK3LtZ} z2bY`@#?;dF@Id(}M$TCdiI#Wb7v8{%QuF_9+Q-mw_MnC4SGfZdsXB^Xtnw zNkOC0X`<#wu%c{*@D2Qz~^Nfer!b>n!TTq?r(Y1PD4MXeO_ii%fhAB0jGm+1gnGxR%!L@MnNF zk0VC0_h;{?JkmrEMM)oH6@PILfQ|J9gx!sA-lTHQT_w>_;U5Q!tNGF|nR7_TW3T4U zT52TRt5vedHH*SiplvmyT$up9^^$&bFw2M6Kv8C-@sxp*i4kAKs6Z_|A9Kd=Y> zM!YU7iE3B%unTOBrbUzp2zwqSILjk!5>oCaXzHNw{7Yg#Ky(Bs?*n#a zkHYKr+ez94LV@)qaXBPuIqqEoQShP|8k8P^5Su7o*&O5ET7(kdQF3s$pD0T%JsD2H zrXW5R$X}1>e*-6DpMP0|Hv1oTJ}z=0&e)Bbx%GA(<6LmNqO|x0=r&-Ni#0u<)@LNx z!*l8NuEc6euV$7N%27v}oT(aaxk$e%)VRE6ECoIs~Eq@5H=NDD7WRc7R$)b`B zcvG$=7lP8A$b_if{431aaV@p+5+^$?-W!7CvKX{kih zs=wmY0SyAI_{nI!yt)f=YwOnih(wdV9%yW0tQlJozA(?kJezm~tgBW3J2f@-Pz&w= h3df7g7;c_F*UF=TDu|9IaaHX~dkja6*S`|>n~$$Y64(F$ diff --git a/assets/data/tool-ui/system_info.dat b/assets/data/tool-ui/system_info.dat index be7284b2ace8e9376190aa255502f727ddf72e9b..a4e4d2276eb4bd2d0859edfedda2295975f00188 100644 GIT binary patch delta 1426 zcmV;D1#SAa3$_c8Hh)&otHc+V6&~w@&FLGCv_t!Zqdr2g((Z;)TCUSoMcYfiXhhw@ zbOR56`B_e03rl$Bcobq`sGMizv$-ab!R!o}?qv+F-6Kl}%H12H0Vv((RP8z%{;^3FOXEed$~ukuR|D%!TYs2 zs}{WlIhBGU?Yi^(LV9>aOXqA%eW{V9!NSH zve(hHT&@WGzB`XQ?&O%Y$73Zb{A)T`>M9TquYaKQs;b=vkI~?Li$%DcTN~LvpLQfD z(7(MAF)&Z|_I-kKZtcyd4&R{H=ksr|@{EIKY;TnRFBURPDpL=cE%;wwkR^BkUW4I-T4VNoXo?@3Z}iETfDMFO*6pxE^aCF( zeDRs&2X-+!4h+@}*|vDtWZcDe0Z`D@FS1ejZagWVDJ3jefE*66Nj)14Yq9?>d*0YM z(L=VMd2?IR-8Ug?2yoI2b=h#zO8G*KVSi~-`|Y?$5lwMy7SZ)r&ALNqHDY|g`ppjJ zMA2|gAa69*npv7#f&tedKKLO=mPTrXQRmwC^0F+HH5_f6=WhLee*NeW8;aaki)!M~ zT0M)-k)IT}V^*Vq)cw6d&0dMTVH+%P3KCBzHE{x3G;%=V{A2NJbp)ugY2o9@RDa%j zGy%^6{oRKI^ZQ?xCxvL`_}lQz9K-Dm^~PbPKS7BLBr!v(Eu9HM)E=lR6buj((P3x4vQk0R>9!eGw)5r!W}P>4_ar#O4=^Lz&)U9>*JJ-|+6Srjgf>5g4PZY{ z-4b1q!_sg)j^+aO305;HDKc3Yuz$*B`Dhwpd8Ja+2RxFQ*dIuQeTY!{e8>-Mg3Cjc z|A;x@ACDmZ{UV_AR68osC#YG02(%QU1D+}JT gC9Wf}SSGaFcssJhJ^=qrxeI@80IbtCnWI`N?yZ`^8UO$Q delta 1426 zcmV;D1#SAa3$_c8Hh(VV>^ju4gXLgCfi!;a%ma4nF`8zOHxBkXypz)|iIoGEBL0Y` z9`hUA!fGH1#k4GRTz^ARU5fne@{7?r3zyC9UCQ0oJ^x@%#w}nA2Vf*1^(~u5*na+g zd#SNj|I7Tqz>m2A=2$i=7>nRHU1r}iDn^tE8`!Jk z{2C$Nyu9A4J?^<<1w3HsHL}*b_lX!^>lgW~vb~%tP&((!C%NEndn+K-l?Oik3N65} zmUI*d^zhqe8GkjLNq@Swqg5=t*(7UTRE~pz2jpCG_RLw$(>--SmG#`*C$i9F1bk*D zUE_^>QtQ@gtAbV16}x~6G37TGVeX?Tw3*tb&}Nx6|GU@Emjq?H6ZCWDXLN1Bv6Poc zb=#>}|F&i4NX^6CsL)Z4m$nYBLDIEw5x31(H*u;TFexf1J^;SaAuU3eGCjyc9Z&CMeXblfz_IXK|U@ zdp}r^hkvjg6DN42P7j>!B`>nuGnb}FxWHN-4OoMaMTm5QH@WhD`HY{SuyDV8VgFB+ zAFUV9UYojGk5v=uoS3hdsKVu5!Lb4!4?`)SDN08nHd^XnLV+hQ&?z@9Z7U>Kh1)nW z4W^67nAeugTAQGbLM6-XNxr?caOs=JJ=lm(Z1*1kQS zLCg4Bh{ypugJ{w@XxR0f=PFuy5b=dp>cJ0PiiGXj0EI4XH0~CJdIgQ$I4aMFp0r7L z`IwijpgzmYO)Ej5?IuxU^edDDv#F;h=f;6_(k5)bB~_&2w_o)6D7V}$ssU6(jPxAi z*ndzny3sRC72w>^9sqNST-sM^y+(I{j~1IsmirU!>}zXx&;tAj2sm^*u@cb`?{u!C zQ!MFs+WbVU%m9W|LJPx;G-C2+wM;YQ$7ss*dK-Gi9kK9-I;&5YGOO zZeAIMc=mW@_w*S;9sTY|ijI+2DcEkJnsif7af>#6srnIw${* zmZFzVw0zZ17F#RFd&)~#ZMQdIX`{k!|NT?5UXUj)r=GVg5Hd0!Z|;Ee{C{D~{(o2j zj&x}`^VY!QA9u^oc&@vn4JMNb;f{ui$q@TkVtmof56a*RQ?Aigg--`Q%zdlt)NYP3 zC>(GQC6#;mt0E}z@=S}P0pp~~gHfOcRTcW28RSAXoucxH1sO|KWz_-4YXbpdgi|Id0<1Hb}Z8jbjt zzXON#eGM_>p*;F)K0?eFKIn)I(WO|Os!XI`nMGG$w9Hc&Bm5bo<~c(Uz=*`#Uhd&z zd||J)c5n6S=XZ)bm%D(tu{P7m27tKZpBBxRO8Vtc_SLIn9Nt~dD0jh-J%6)p{&&@j zT>H!Egw=KO5}577o%&%gRyrJE4X8%tO_t1? z6^Xm--;{gNF1SofFks{Yr&=Q|H8&W&Em8x9z#D}tu+C=pp?wlA78(uYlO6%UKIm(& gn0q14t!o%NQnI=*67eyPM+*kj890iMHjQA-7hWpRod5s; diff --git a/assets/data/tool-ui/system_tool.dat b/assets/data/tool-ui/system_tool.dat index 71ecba0493fcd4f233388d0f422515e2737d89d3..4b94f49d9ba1e81d8deb62ce56129490bf921669 100644 GIT binary patch delta 1377 zcmV-n1)lnb3x*4jHh*wBIC4aC<>WV6!Ef?r--wV<+VP&`${KWIY+(00cL{T!g{W^^w7IdlURh75EiS`nA3|nY7IiBgqS4n z@e-%v!H(>$@it080jAP&5ZVWjwUMHHe||32Al*?oM1ej!J%W1wC^&PeQCw-V%|iIL zV`ve5y8Lz%_kU~AXbmdgA%>^LW^2-+mbl;dmr$g%1%Y^v+ZL)l-wN;5_ad%MdM-K? z(Af6ugAgTtmR&DNUHTihr_R{jg4r9?X8` zbSxds?vt?5Y{(|m3FX)y>#GgtuTTcUa@FBn3x+t++xSwUC!^)UxZ2b0=+H3 zse`{Z8eZ;~@#^mGMKGxBsQ4S|RvAOjPrPjN^u$);{G?IMbLgnS3Y;tM;ASR|I%^=f zxiF|3u>$t?H{TS05$C0rsw+)C`v!vURjK3)N`E)90&quxx11TrsF8_e$rMcG_o~ft zGrGiiIx`^Lt4iqFNZEv(fCC6g@37e1{<4P~Es>jMkZpY9dGB+pcM2W;10xh>XS^cE zIBZx+ZeL?|a>n-fdGXT}q%>4$>TCd?COMx%yFa0k66X2L01TK(Ay|I9|E$KD2v?LU z0e^@Xp#aQ4Fn|vu=A3cuBVBrDLc1N8#HeO>)-zop$PKP#{^D8+LJ$jy%W3-hwOom; zu)0)+`u}2TUE~HH03KsVLk%O7ZVoo%0;N#8md#NQAGK8`S-Td~#?lEVdy1ADAZlI2 zr1|}H(0`Hy83DeCCjLZT-_g_dhBJh~#eZach7r_o@d#u4-@zq}t6eB>Na5#aa)2FS zS-DA2U~toP7L)%b^{(4g2hnA6%ksc6bJprsYP9HFz+c(It?P9a7Stx7k!P?14US$* z8fR-{2s+16FUI4E9I#$%Z9F8y=EykFwyk9S7kW$2jJ^mfl$Py+Ek_6aGU|WXKYvF& z!|`|U?S}2we-uMQD2*vp#}RV=I|1XF*LC jK}I$O*zQs7dCCKrvC4#i@9yEgnwFXpiksvj0{3g5lS{1M delta 1377 zcmV-n1)lnb3x*4jHh%|97wd;kBu+-!x}GNH`}E>f;T=i7;L=so2Ai^;)kbS)*3mNF zjIPzCYd~j3IK=h6=GMsRx+qYpUq*Y0C8TPUFPa}VoH<6)LF+LXrdQra7);#YG!|gl zXpqNy!NDQ3UtC-j{mPOKYV7d?WN$pSsnTU|*G}A+La$F(5Pyh2ZHDfur(j}m%V0PL zKL*GVc3T#=NgL39+%VCd#;fVH-|wApEbizY7_Ksrl1-S7KLG*RhL2tt06MsT{`!-{gmem6vBd9!(RrhRU z%7s0n@Hr0w=CqH^=D%^~0?_5{*g`}EZM?WD#VJO0b#&$c@J5FU?-^NDiwnee!*>Rv zi;r^=_l0~?kBUw?z!f1V=d9VTu1O(j#(=)|HysIT7Jsym`+qJeiX}?vEjU9)k3M^V zd4aRF$$x;kV{30jJ5bknWO#da_6N%nE$X~IA#`7;y1I!pmyyOn4EhJDflf6k3&^K| zfU8+DxB?cgDUEEd83NTAjl(DsgC!OC#KpV76(p@|aTU@I%xL4+0AdB)DC^ivol@(# zQqq~4+Hd@Ug22Hi_if4%a<0-PgpkmC91aOHEPr=XMxIr3ZjNM|R8Jf-?&{T>P+MK! zXvOU9iaM3Sx;w)bOk>?(Nomhxu$F68K0^HHP~8|3uHM8XJ=)l_t0QWPM?J2zCd z&}Th>fU4RsRGU_+-#ij3`$RL4Ru}m|?s5k@zkuo7n|E>y&fjxQo;0@n{{QB51Q!h* zaes4f@z*yI0}(H+^&?U*jeD@^->{fQB`X*VYKhkKC-|OC|A`?9v3f5037z89lv_SX zYXYIxQfdsQq4S}GFf%7Mz71*ogmcNKinJLN`n#yGH0!+XJ^0*pj%Wg+=a3bSJh6RH zrp0Z?S-X2QgwK@kWM{49$2+|w{r+^*OMi12hcXWn<4Fc4YGzJTjg|DNSHsP3GR{oB z;jY!vvBJF(jK1NeQ-7Ss=QtJ7Cje^_SI~a8zURjdm!B7VL z>lCDzA(EJh7p{Hl^w6m@aacEwcW9+?8}mR>oob_VUNfPbA*VEQ(YL6n8lq7*EXWJZET~$YL#pHyPy1)@)cxgq5;w-9%J1Gge#alCz>|D3%5cF<(+L#i%UbJ{C3n>9 zB5t?Am0YCU&PvLY6n4m;H_$kM&yPL`X}as(&=3YaQ)GGju7W?rYG*JBRC`eOA4X>h j0jj_6R#k8VLPIGd4t`^>{V135ZqO#R?aZiTcUccce{ZFn diff --git a/assets/data/tool-ui/tax_calculator.dat b/assets/data/tool-ui/tax_calculator.dat index c0e59ca5081321f336ea0479e2ff97d1756a2679..ffb54dce55d1a430babf2397379266bf5ed69e75 100644 GIT binary patch delta 2071 zcmV+y2UC)?eM1(I7+4Hn>N-a_22sdIj}D85g_CKF8xFl zXm97;YWx5uK2W-BAjQR3N3vqq@rt{=cYacMKuQ#j$4m}pgnwoy_sSerND+SU=fjcg zY6mFE*BL>5R$%wXvbhqO=JkKE!ZTRi~f*vIPfHzr$*T~rNwLUU7vs9$H zzskyGJOn(W(0^UYJ-L8MUyE`9gcM$rpNl}Ck!p>nO1{>Oz*3i_)36!p9F4PmJU`>=g=#x7baZMSr@er?D-i%mr?cZe!!mAi;dvLHEiEb{;7biOY1Yp$*RGJ9_zS?uaz^d5jfrK9n0pHSjU zQeB~zv;D)A>WDdIf_Q|ZF7vD;?*Rk)q)~4AQn9LaII!VyjyVC&>OBen+27~VDGgbL zG}KFf#D4}WV&QD|tApKW&`#^4$JerxLE1twfgBp}t2)~3rA zz;hOHyQzOYlOqkX?`V=~pr^%0E~$j)4i0^P*W=K|gTl>5$LumYt)t{j>6^r^8g4 z_E2!2b#xbzrNb;&?%b&`vuOq#toOoZiC9z4hGY1UYaHx5kZc$Z0=5atuZ*+wUS%Q# z;Qt=~h*fx0hdJN{0Gd}8<|mCNf0*v2KLvgCDMS1Xml`jLV$q`?*le8S!2U+oR^sjUS7p? zTC;$pMTrvf)XEW2)5xEf(zC)7^_>SZV}EK0$lA?^jNHYzVZ=X5FljG-4n0LsQ!($b zJ0Rsh|6zzENzv5qnR`I5B9h_ZfPW=tS~A^ey8LCoV2FnsF84FO&xYV3jw0UXaGwub zw$$-S%j*6WEytU5vi|d^`S@z-Ws~6j2HHbtI^Ki_c%v_;LbWuFH8X@Kk0>kuhkq}E zOwf&teO;o}Vl;^87&ukc%mozWjb*A4vB#8PyZmeHny(Q#+{EM`Wj;>V?qAZkVaHh| zRLO6q$qdP8L$%6Ng-unQ17|7{ZSbj~#8ye?xeR2^2{xrJd-lUYW5C4FuwnqS)aX91 zltAxJ`Q=`z)&hB!WN^}EsEsn>?0-#w)2jV6q)Hw8Lz<@v%EXVxLRlWFdTl1GxO3O+vT2P9gT(_)3Ag%s8#l_0K_j1|sZ zMbtkRoM25$IBAgaDt;*(bdL2IlSeX9Zr{im&Fs3RrBWDk*aA?1Yk$2LFh=51{;_-< zXP9soqmM~r%AH{P8T+%DSXSG1?&{hvFmufWAU7s2&G}&60)W(|`*BYa2w7!tD@5vR zI=+C0j}EcJL)kUsubd{bbAxBT|99{Pf>QKJsNRPhgyJwj^ZXzjX~YSyjbR49w*_>_ z(U`*osR5MEq>&3r7k^v{L)XH%*|J%bc>UcdP7+A*Aksa?U8~h9%iwn#yIW(Y<|Ql} z71K{gL2c|rbp1{xh4^6?on;kUhS#-3Pv9@lajBQ_ilf;fc&sF2%!w) z!vxA5$m`R+dsfk7CHO~ssRLe77$-9+&o2^VpOP!{*UHYtu`VE B9Blvq delta 2071 zcmV+y2%b8F&3205yh#`1)3nkl4ta#8%5ip`6DgoZXB-Q6= zJcR?T!=;m9l~wSt-IPkaLH4YtXv8vrX+*px$3SB&NeK{0j(-6KFXEI#Id6CKznKMx z^%1Z&-g&Vgd{FKdR36#K`EeUjfVC!kO?7Si$n2^zq^}`ip&%J?>IiGGVNdB|ZV4ha z(F7zx93Zdo+Jh6xBn#G~k}Hh0DJzxdBJ4M%rE$!cLlFpaQL-U?m1+L%X@6)ig?t*> zc=jZf463OgAAg5RPq^I{<>k+^yFBt0=SAq_Ie#@c>ZfE9I}Dm24b(qZ#p-@pTSS7I z9!mUOXwQ~yd$EKka>T@ph7j-DP=tNd!DR+|t>P+$$(z4$Gtr%u66edwx2bnzkdXqF zkMw5U%P>-{PX2WUZEKqy6PZ%iZ-th>7d@MrQ#aBxb$_pCigw$!wzXfs(XO4fRZPqs zZ}twDrAIn)yn7DeZu~#_sDPGawo5U78u_d@_7v>rwphMaJco4r}5gc7y^I2>KX!k-}9^C1i{Us z?XS|j%YSSH%%pR+Y47Y&BAyF?{PE+?ZCKW`vq zcNb-N?VIpR1NCCRd*N%!F^{@Y#^RF&a8my1MDyfmI7#J42Q38;X`>B* z+Sa@YsIawi4|7ghzR*5Bf07yMmdzGwW7gM@1N+9w?(WAFr(Bn@y{v7My(%pP!!pcL zEPp9myV~G;-UXx$PN{6e>9P3Pc6K#ZF?e?Y9=oTJ5U z95a2btMs|f40+kYthK*}`6_~vI!g14R2F;w>fqIv{LdgklR%V(yfZ9k+NyCcq^-;?7`DRd3bKch4%XebCg3-+xgH zS^99^e(@~)%1LO8@SnxoP<=cWqBcvxQd$D;t~gERdPJgrhcuND=xM6cmq0L(UY+9I zI>@>)IJUS=c{rI5=r#mjqTmb`UXZseK2TjHuVx$`&+=C{GYtcd7RxLz4q{G&YEBg< z$ITrds}FZ8Sl8FOO3>h)ii2A;Fn{I{^helM<;^=qim8Q;5Ol9NY-{7x1mS7hg(-$K z=l=Li{a^N?bGaiA1_bUp)~?^3k>bqr0dg)QW*LuOx(YwF0&cu}YEOPn>^j36<=(9ViiDEz-V^y5{&#HM!P(-89Ptk#Ejf zR<*IubUZPtrd@DLL|Y;lkT`tV7u*z7{!1%7`)x}5Pt*sye8||XZw}0NDL->1MU;vk zulE*s3^x@dX*3jl=U*>4ynjFZL-FLh0vQ$MhSHSrjU0!=Opk|Cth9G485F2O?ZIfD z&;zAMJdepi4dmZblET@|Y{V1*8)j!(@OQ2tIsTeJ-A_SXBQMTu@8~;CR?}M*?Bb#A?1xs^z(PJ+K}X=YKOFf0)}eqlw6q zg5f51Uigv5F0%V85vE$1#XgZ61w_lhag{QG zz2T|txy)DMpsugK;K~X&)Pl}M9U+wCboY7vaw>;5PjHn?p;UP&qw04H_gRU=7wZL% z;^uj7KHAa2IIBfI9yaH?>A!DrIdkg;bQSWmd3LVD$_&Grg?}-Bgb?8p_j(dVW#40_ z7$+@!XN08DNMv9s!Eb7iaWY7FP)r+mdg%8;iQ=fc9=#Bv?!Ta2ZAT=YA9eOQUocNu z0<;v&|5o7pKWfuiC9=LaVdys=wTobMB=vB0LUxwFpC!HYXeug}okC7bJ79>g!O!LK zX@WtVh6i1$b$=UjJHF~g3;3$7bnHm>A_xK%1zIm}x?8XYkF zx{xz~^acI1=7K94{x^G4?ZslD-GbR+h}fCqyB)B B05<>t diff --git a/assets/data/tool-ui/tech_news.dat b/assets/data/tool-ui/tech_news.dat index fd1a734aa9dd65aae51be8955962d2216a6278fe..d92310da3d59768e5b024903027bb6c9d97c5e03 100644 GIT binary patch delta 1329 zcmV-11Bo5G8#fUM0oLeN+`jR4b?N(xN%eIt_B*%ZMr8 zw#V$rUwqIk8U=H$ccAU`lX_qccR|_)m`#Y)TpM!xFEp+tuxy7YR$SZTi>vU7uYti1@g3kquSdKt8spE|fJe<0#dY1Iz(fe9~}*F&jjB)QI=11i5^=VjC5>h7}k!g+*xH zW$Rd6i5E<9j9?M+-(4=g;dlS9ANhAm#;h}tuKXpwtrbEgRSTv+5Vzuysq9|;JLjo< zAfB1{$i7a#H-9IuaNHHlzh>L=Yo1gF{ONcM{cb-3=Li>i9+NL+5QWEbB56`dgg4h! z!(Ee9iY)qYRykG@*xArT8tDS_(Y=R{U5medpVzcA=KLA2G0F0)i`YI5f)fi9zfTv# zz6ZjC(Xklw9Tu~|&{NXeYoUJ?j#)*YFW*rA&LL>4&VQYIBmU;|c^kw;iQ~fjJKaS4 z7L^H8eB&K1CUvQQ77)tRE#DA^pN*RZ!P4+K5Vl-z{(3#u?0ZP&WfP{^;Ln6ltP!16 z!n>jEO-tJLz8veM)FvdnSV3++n1kduORgtYh-G272cw>bi6<93Y?btJ_ADXtFI-Z> zI7+To9Dhd8?;75muR-JfFbn=pv;~NHdx*_=2P`){GpJIhCa}JdXw5#~tA~t03;C~V zqjJnFgrcTft8t?+hVmyQ<}1SX_^D4yS+|BANdwqQ-*;z+f1AYttnT=!2CBE+|X5*&SxrD7I;A=tuiSFwBeA~Ef&_z#uu(@Epot1&%PUU2CkbvVSMuQ3TYY3)p7A@Qf|jaV1&xD|w`0wt`2p%Rw#7=ZaGXZ9OJ3JRo-E+J7$XINpKsNS=*q={h|{@7cg%?rV#-vin* zm-s#P^ziUM&2qBb#+)Ntw5P8k);Sn%wiUF6>A-G&gLR9YN zF@sET/ocu+H~uh@5x>(|9q7c~$tS4_%DqjF&1=NfLVc{2z=Dd3o0>8{B{pd7Fe z=%gQEDR=x*CmD&evSF75EPo0&y??Xau2L>s(q>Gp%xh1ZPD+ zrJ?BPh8462j1!g}K!6sh-T%0M>xt9MdEM=Gj delta 1329 zcmV-11gz{1gDLqJc$Ha10a0|l#2a8;HIWu3w%cL8EJK%pzfxr6(&Tf zzk=3cEUwn?VyJ#LH;l&oDx~HD^y6 z?An-RdwG5HD-Ja<978ouv-6~slVuYOnJrg&e>SR3CWeLfjj5sec(G&+jvY~7&HSBr%b zoD%o`rfj=kn3s>pN3s6e#1guDaYfa0CNtC$QGe%w*z0L%KN@D!LsK`|$?@=TCbdbajSW@k&+Lq966J_+{>~9f6^`dSToOYZDqG+t2#eAB~LuB6UBpJaRsR z8M*CsG!h_k;Kj9x7y+C%)s9T=6jU&v9M^R-%jkO-7nJ*5ZFc;BdsAp1#=)zf#4FBv z(2vwfEXrC86XtA^7+?JX&JKsy;&_mFCVwtHJK<#%< zf}lS)fKA=5(4fufw1oNgUWXe9wqLnpnhQUg&L!4VSjmvK$yexsFFWJ*I};2wU4Q;w zJaK?DYjT+s1X~I$O%ISj?E4?3jP#J@^>DleLpEYhj_6!9gRXh_6BfT9}ptrh-F; zhq{9zsc(Rk%?QVKuV1c_qLO#anJRmV(ueokOv{~r@ctekd*6r_{y9lc@+v$=s7+-J nGNf8wqIm$ulVgaP;EOsR7TupfjbLsVruB^*_dvvC8tHRx4-J$g diff --git a/assets/data/tool-ui/temperature_converter.dat b/assets/data/tool-ui/temperature_converter.dat index 6ef79b2c52b361ff66c1f5ef3c6a9fab5503d829..3938097a316d91c22992080a19856430b0d5e97b 100644 GIT binary patch delta 2054 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 diff --git a/assets/data/tool-ui/template_filler.dat b/assets/data/tool-ui/template_filler.dat index 305ae2239b8350acf4a3895f42e61e9c36029bb9..c5faef70a1e1d7ef03a24c8286d972a9acd3b3e8 100644 GIT binary patch delta 2103 zcmV-72*~%^5ZVxsI)8XDiA1T4fXCje=qUt6A?M<4F=R^}I5#=fZEt;QHnz!R&cVpW zXtdDxZfnu07ELh-zdo7`_=YL=u8qqt&hALft|XXyA_^%j${t|RZN=Dt}%zD^r4O0O>neLIvgsT{>*`V~V-6n~xx*ZeG;vSpWzvYHJpvc3{D}Jd1s%` zVS@j$;pALI7Jqc4OeoXSsC21!ZV4IejX9HvGmR~`R+%QH&I!MvLA_Hb_l8vPDs_NS zA(~E&!I3=6$}cfY=v7oS#b@)U@=b#&Nxf|X8zpblsFZ1Heh)PlZ9OxfS_AjJK4`F@ z;jmuSgj%rSJ~`uS6Y{Zviz&WnE7r+>;)l&>;aiyd=6|DG{e`BIO4!X;?9-w&`JmyD zq}S$MmVAUw=%~ec3(grMimy&fU z6ubBt&N;|qvKc01j0;k9*50NIk^s05hDxbHJ%10&JW68}@xLT@0DvonK+&%g;qwHu z3Ctf3C%hnVg?lJu`Uwmvq2C>y{G|BG^Aj4gZ}^E0rri%=ALlMHM6?y}icvl%)AMa2 zs;cgc{KZrPh|2T7G<*9siJLW~z8z4}iZRfz@XC|o!8e`}u5OLtfd4R0=L7Fy3yaxR z*MEZ=iD=0lh#&!E6Vjt-hW;@^75Y&5kWvNPc8;%*|6Pq6`6emVwRGk zaVGRgE6@cJ85wuO47O?w@HHgaN!Nzfo&{Ne>Pl;qCC9ARiKDm!&FtGWdH3jP4ifQ+ zMQ@c^@jIN&dGrXvG^(;x7`2E#@4d784g{@|-JH(soqe|GOC)}efmtif;MAmD2Y({7 zWm;wtVF(+EE!Nuof2x%8+mvHO$ilYIJ46c@tg;t6Rj7MtRH^he13KY6 z6{UwX-wEnrz*qfDG@zwDsO%>VkAGQ%s1oWPb4v9>tECJ4gu@6+bDUN8M}HJXE1md(7*Yo$OAWnTE%qI`{i_p zMT5dT<*c0qAMbP6k@Z-*yUkbHtm}SWVT>-+XlZ)aE&{K~k=u+C6Q=<~K!0w587V~0 z@))PAPE!m`d2~_PO}{#L1;yzEUwy~2KW_JoR=(!d=(CTa+<)+8_JprUNH!r3=3?n4 zK1|H;XNk4;<1S^J*SIbC4Kt&9;R>WgY7uETC+7MgL7Xa^BOk>-fwQRFa2W{$drb2YWR(y zOwSA~m=qk7jFJ*MXFPLAnXULe3-fijPL9p7_W54L#0Hi+mn3&k+4p8#*Mkc!l~cz7 zo{k7M>w91tNAW&VWx3~xYElc$lwEOb@OA)EQfFZ&(l5kIKe&MJsegc|>XcSUY46=e zT|{RrcMVRaIh`6-bc(J_Xj^RrQ7o$Y7G zQw)K|s(k?v5l4Jr5y#oZzDy8}b~vo~QXko2J-D<>zVPuYF4bilx)S zi5F{)`Gv@6ue$FYFV-z@so8zeSDHZHSE$&fcF5sjvqWei?)M2GqWa;pCx5KVYLn92 zvUAv^P#+-KU`_#4x%7FLQZDB7no{;6XvA(FYF*2rQ;`Y%rhl&A7W%4b@JlI+!FsR% z$XQExTeJxZ|GFkri7MqFINCjjw{NJTl|)ozkSJ?R+;j=jYZZ5tWPRqEv~^U8rq~{?SgXK&yTeiqJq{FqmzlTWCs924Fg9< zhld0e38u({gn#?l^PPB2^q~oJ=-_)6f%szAA|VR71TE3tl!<~V8f|zxHoRwRwuqS) z*Yywm6+X2V#nFI&f2TFa$Wb6vy9Uz&83sC?7 delta 2103 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 delta 2087 zcmV+?2-x?`5X=yeJb%JMu+_i|-68PjU$i9C7P7V&z{DoYSLyv zk`&$sI?(?*s5_2}Q$2ZRD5pbucU3n8<6&0(I%3a%sH8oKyb$(Gs&n*iSlrBihdTAV zN(G0^C)D&Bpp8oozWjWQoKL_L?onmMz?+q5M>3Aq(xisck$-|V{lVfHVBzR22ozMW zy;{~oxu2y>vhQhY>l?}NW>lLwE=lElDOD)HjstUskgmV)HV9G_zNK|rQ?{*o)a^@ z)e}Apxx`mDu|^4xx_B>*bE$DAX=i}=buIM}gOX7sQGX4hEQ07tE__@Pe2ohsv((*C zK2H%(%yqtarZZ~(=g83aPgro(zZ@>Q`i2G;)7r(2x$cBKq`N%{S-O$8S6Ol=rzFH3 zYGVa?Vrg=P_WCzqtb~YII|MQ4j|Yw?6PF}MX2bW?wHIFIr{U)@GP_xefuR5Yxm}iX zM|*uGPk+{iP})D-5&rRhUCY?Ho5OZFFslc3o^zo8 zs9=#|mrwR{*e{!%fyrz;P7-7Tu}~`?PQN4&SV7F#`MX<)%-X@lC*kfGAq60vg9@Nr)Up~tYAG~enj zYx<>dyV>(Tgy=V_$reBIcj}S5kFi`~``|JtPr=GX+r|nyY3K{)dKoOlmA%cqUd3?|Z4ihxUSi z)zF63$->xOSM2&){tjof8_wcb7T(Po+I>V3d985SIDHx?D6%5svNJ>$G&ApGqQssf8qBAZT=!i12 z7{#M$PwE0Ng*m4Q6ARO}>CgHa8Gpv%HN&bls3{-Go+Tgu?Ve|nPcAL0OHGkKv5+z^uuH&Gne|Q$;{dHyi-cs6DNebF97Ok;Np`pBS8352acws zh4{8+iBq=_^J?ZysF_Vomxm%VrFjvP$Y`uK0tP5RY~u%jQz-L;XmQH50e`F8?k%#f z=NS$(Stk^N5pu6Q0$tsOo;~Gf8oO1W7?LM%t(^8Z|sWl%so=eyVCOBbulaRzHX#GbnuSs@6?yijy$% zSn#Lfy@_)S^9>#n{v>}>uBRYwBd$9CDN4=#i5LU&E>J-T5&fa~Gk>i>QutGP()vZ0 zWT7wksTGCAT546G#u@CucCmqh5Hv;X)ss0rw!AxkSR@QYn4to zIYzR-M{fti-qtNCgfmtaYd+A*-X(TQmAoi)Pv8b*Y)qk$u-kVXK_Ylh zeQG8avG9RsnAMjk6!Q_T{Zf;ap!x}sle66 zNIZWX{RKxX{1~Jq*!sz_R%WZ0v5}_q3Wd&#+U{6ubh&8OE9z@mI_;h;>xpEo8x*83 z3AES!&?~G^8;Hki2dzuNR^|dRT@2!HW|?Cd2z&!1Vu0M&Po%%#m(<|f zKe{ z=#zvtpucByJL~v5e4k;LsAFFkaOF@%HWWSRg@z_03%k$F3n^R7W5gTwHwG4k?X(?r z%`2s4FW`Zl2Kcp<6wW(>1ZB7uqKiTDL?2yR&4{NijUa=)LnoCwb$mu9Ec+;u;lKps RI$FM6rP9dK3W=JW$S$qi0o4Ei diff --git a/assets/data/tool-ui/text_diff.dat b/assets/data/tool-ui/text_diff.dat index 6b74f0ca97d8299cd80263fef4fe3fd43894182d..739a037639936abccc3ebf450ad2db1ff47d4f82 100644 GIT binary patch delta 2071 zcmV+y2vuVK>Gq@Oqv9CE4hSkDv}!OHm*5aGbf zAjcy|PRGic7VN>DEU*Bf21Z=qAEb=+BLM}vHQ6{g-Dz!8(SM}Bi_>A95KG@cYI6}l zqI}ag_-FfCMTc~lB{8?lp=jns(T@+TLlU)G0d7Oit*bE+KGJydE??cc`wqXfYeDzP0|F->%MOA}uHTCmOz58U~^D zhtd;ZGh3ZY1D9o?*UFHr$-<;iJ~|IslwF{#5=fSbqZ^@b>=Tv;fkI8IK-Sj`Q1p!%X5=W?M1Qv30CK?&=jAma7Xn0w$h z6`Eusg&ToBPw2ZssuB>m#;(SB8ms)O3%p()WkXoEvgfG_E?Fgks;cXR2u4Ulam&=JL5uiIjld3JMdmJ6?MytgLjAi!6DAKWINr zdw|W0Z|M!&BIUND<`m#+O3<~kd7HJ7v;*&jC4XHYlg=h8nA&^I0~Fl~KI63xH-8Dr z!yE;^7J)7w9tZ{RV=7QT5THEA?`m?x09??db~@sG-Z|K+=rzJPj zYy-M@5aygcf<8VM(x)14YY;aW*FK*o>~J*UlJ6NE5U9vuk2N}VhR?*o$$tVQB!B-i zR#PdCc2EoNo0Kfwd8JbF>_};_4LZ*i0=jc=UuQT~xZhZPgsh<;2aR_rLbu(O{;(|{ zULmDdiDdbN8SAmiMaJOFtk~^LVqZ(ZF`g;mWuW^dya6%e`5+F!isx3>t>x485bIH? z5Nu1m!5uadI}NkhBN(5W(ZV@^ zSIvb{JG!=Pz+M0e@veyAClTfvh^s6)FI(x(yOu}DhMT&B1&-olvb1?IEy7%Rv#-6a z3Sf|Kp9HQ5_6dNid0nZ$%d4!vQdW#|yv@N*d57CM?5y&G_83cZhJU_OYiHa+LJTol zJ$~&BVdJ13P|_Yb`A=#Zcn$-5TK{-NIepd+EmI9JDwXEl=BHSlOEC-DZ^ZzrR+<#d z=kUWuqT*m>w^zEj1BnLKLhS-QcME-fBPj&|TN)tCEK33Cy9iCPNsK(-=Qd&lEY`YW zXEj*nGo#2+_~<1`)PMHD5jyQRVRB4Adz`l?QVOT(lo#H<4*v7Yc)NSkI7lM+T2}=G zsWhXJ0+FFVCRX_ITUcG4$@%X zbLSPd7@o$QF?qaguT^F66a!mtb1r`R_S6>FrPUmVF_(uP(0^dKpj#EuXR4fttY=lZ z#FaD@&N?=ehB?74j6P<3WbhdhTNv4JQ320<#+l3#;RoZd1NBeX+Jksbj7yLVWmR!tNM+d8`v zVb9DK5R@x@Sbrgzbcji6wIyNqraCo9jCkUpNvd7s7|KUGBqG`U0roc-KRM?VLG;k| zll~uEro^@=ghI+vFX6g36bC_jbWiLyHMoQxN~5)37VBiUm(9UyJJBlnni845TUHEV z8gL;1i@-gzQfSXKUx{~Mg3Hi*1f}qrN#2*RW{k3L*AN9J>C?b_3AR!n|IiSFr3fQz B=VJf> delta 2071 zcmV+y2voy~~P1IfJVn|slgP(Yz zoE^FAgZ53wQLJIVWO)lVIJhNkq*Nxp5N8%`mHvsn2#yXDFXcO=H->Nt71R%RBKt_d z!n4vWJdlR(lJ7uM{{~jd_Ag5L?4k+du-Cx4-d-k+YJ7wYG=C7DXrsHbvtF$ zuEl@~Sg1L$c7N=Em5S|(#xJ}9q|bH4sI_IZUic@pVc}3e@Rq41PNbJ(@^TM!y1@APQno@U}oHQXJE8ot%z4AujvKc zAHE1~2h|XMYesd0k9nK%;%C6>@ca5!bDttYnZ=*=?|(#>>g%3n{mWv%&-*zS@#H`aP}DNO=v=*%#26M zw`^+OCxV!}Pl;3TGRBeL3h}L~pt&Y;*+3$^bK>TPq)8Zyx1(vfWfTUXO3){CDc}&f zlK<_|dw>79DSB@Y*g!Ko^qBT*fFL?~=3d3)Zbyx6TqiYkN9gy=DN;~T>qc&|rO5;Q z@fSgJ^{~9{%n2Gqs1k-(q+A`xjK4$@`cVS7b13|D0-i!SI`qJ9xn>aIG_OiX`OCD5 zAet25dEA-c!+4cy_GgMA(Pqd2or4Gcfs<(HoPRVSEe6cy8T@0hv|?}<{VN(y$w51? z+Y9%cmm}bOwh5HT5`T1Kzs!3pVL``pINAa6^tpVSH}Bib*^5bp z#8#j865Ov%>oTKOYfW->U9KcvxT^y!GQ{M3nrnniaduRU+_rDqy<@~QVzgc;Xix+E zf`3P30$Bdpo0V(=)gMv~+S6l>CdI5bo&?LDgtyq1W^MeOaw#qFj&4u6ax5%zQuoqehhimr#`Sp3!>k}8g(u;HfE z6=6NotyOac1PP|TRK(cq-W`ncsDPiz*8zr>-PGZJ8F1C{02)5iT;5Gb7k~DO z3+js;C2SzUGoT(bp^(*kLgj9aE)v*XOHFkOL*eHO6r7gCPQ_7=z`-AjHa=LycDkyn zmx}C9KqD6nn^2f@1DVFPCYnfx*RD6J3V?&-e%^t6pa%L51a85O6!)?J<_Fn$VS@;r zP42Zs#sFtR(Gg{ylXAl)@f4WSn}5J=J8?AkmDbus?=FUbJR3@Ocr1Uvu8W?sq}Go( zv1#nFcZJ;{^eqjO{dVC4REw|7=Gb;za;)fSWdh7s0sSod#@Kcjq@wGrWg+uHIcbrC zwie$60z;5bW;<3>HRCVc{a4#`Ox489vo`xIEtApO0|Mm2e+vSn`E1G6H-9J`B}@GN zgSpqw8D?7m&4`elg_ba0t5w94}V)2xXA}+b+XtWu5LZf6JgXJvkq}5T3E&N z!t%f@c=gR^Hi^_xOyi`kN6x44R~Q$7>sHp#O^X1jpDeMp1MABk!hh3B4+Dvrqs6E1 zwhYw#Ms`GkO34#b(2gu#d>8^ESlk^a^)-ZP!uGk)${NdgP0ts6{p}0*4qsE`r$009 zvP$#u{pjbwe1=d~5tyKS;gOb+H&Gj=iOTf0XYO<9^kpJ+g(m?!-|e+tsB@-OHrN7g8az!#M**?(W~gQd?bz9Dm`b%*?~bf(fJdPLX2|bVZPxHp zm_ch6>;(oIWaP;H2H=w)q5A>_6E3`hFlRc4EV8MVBqhAD4 zZf~R*$M>pJZd`bL8!LQUmaCwBt1scsVXl)k94$sAZ3EvyWF*V`V+uJb+yzR52Yo*P zBZ9thURjtjJ+-6!3EE@cKq23oCtEw3|NMVtqi_x=oo8gl9|s9xWQdB7feO4IvJHj zYF;rO0oe@fr9usWUY1EZUn4P-Kr~9#i@euF`~d0v_7JwRiSMZ&GJf{zutyvf*)xXR B1wa4* diff --git a/assets/data/tool-ui/text_filter.dat b/assets/data/tool-ui/text_filter.dat index 8d0af4e8c3f4917cbe425ca3e449374f5e7ca6e9..5b922ea228e33849ef38acf78a6f2d9bb8923656 100644 GIT binary patch delta 2103 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 UT`>D@_(rdu5w^5SwheJZdM$zb-~a#s delta 2038 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 RzovnZrf9UnmH%_J_B1nBD%Ai0 delta 2087 zcmV+?2-x?@5XlgbIe$+jrCBIH-13X{0C~~cn%m>O2xnb0>kGR*8p4#{Fbjcv5HEdy zAo}J|Ljk+mIW>>{pnW~Bel~40vytpaU6{qKYs!PEITPfpA+ArbdLNp9yuDoyv+~>& zDq%=A;&C^=F#z8Qc2F_9r2Pa*JB);gGQ`=#O6#ojBpEf;Wq+d7?GcP@y+355BM*uT zRplu<=RDFC1ML2e9v|OOFpKI`d2C3SGGv;+HEuc?+o7fx$_6FJ!4qjn95_%_y%drW&L6WVUyS@O#d#hZiI$7Z#A|XpIXc1l&60rX>khF zQ>)?qTS?ARqMoc0Pz;M(zbp1>(|B{mnbiuTz~OMkkYe5x$6qU~6Y$R#~KSAYd% zL)UvQ=XL-6{}>Gx+L7Juyd9UAmW{T88F>ZjMul{zP?c{za&q5}RBv4iV`Y#gn5CFj zD2F^8XvnRH=s!qlD;=`@D5~?81%j8Qr<2PIPyZF}{ zJPfbzy?;y`qTm3&M z!UGw7qJH5z2zG8ZYxh++4KDWj$!C4L;T%UFTP&<nOrGhY&ooE-EyjmB1W`2hq(%Ugr7E%rKzkhM}m>^UfQpySodHwhMIAo~)xxAOf zKprLQ4v71#<(-Avs`x7{+*%CbNePjUKy#f2D2dz^Ic0kt{dj8SaF^kbu3YaN%Vq1X zj<7cWcWUz8mIYDd3Xu+Cq!o(?n{-3PJ)KIJ197Jt%WPGfe8?L!QYp`_=9+)RFzHo@;J7_<}G z&H{ux{aUcJWE;PfqvS{j^mT3nu)~qk-4P=ZSOq(UYT`+{I=^}@>X;JU#A1F;U2I_(;^| zcRPdDmH>LOkEz z@EdJ;2n36-`8tfwfNZ39xPU^z6YJ)+sNIOI1jA!0d2Ao$+!Xb&7L_P>VSi&e^F{Me znk4mJ~2}a%kx2 zdp=V%6BNQ=TQjLj4NbGaGlX*o-9MY;zB$EM(+9&_r3F3;_qaOYG__U~`Zmd?utyos zFvx@{|#HM-UqmtG8NKUAl;Fu+_^i`0x(}jh*e$U`}WcB zC>K&-9Kc~32YWx#nnvaE0#;d0V_-IiEM}P7$Rh0+Fk{F)i!y**9)Fwwfo2vpy#Y-k zrEL1T+FzVd(VnSJsx+zjp)s%biE~Rs@5)wnSPvg{+H&#Ize{ZybjR@ z->ayibah7gRCh;|Zh!e6agOT|DwP%h!1lM}zz5KBjn11P83T`2V&g9GI`nCnptT4_ z0UVM5`)9n{TA)2)K*=sXi(OucgdE(b>SsO=B9QD@%#`gQPs9=@;Wkpkayo!Kl43`h z<lq#+t#g@1m3j54{u$6WE>i<7=2=w!=;N=z75im_z3JfUqvlX@3#Ol{4eGp8l2 zQ1&ImNrd;(Yk$;+De|R$T3zc&koN;-R|k;)Am(p~P|yCaIyN(Ksk2XNXi38xB0S9< zA^iaA3&it#Z5lvfm(rkzejvF4Uwk=oCU3LqEH6914CIdI)P?_X{uO~4`wQ$v2)(k| zFhV&zG7u;Oh=3bgjKeYELy%zIv_mb0>=OV diff --git a/assets/data/tool-ui/text_reverser.dat b/assets/data/tool-ui/text_reverser.dat index 5f686aeaa1111255d1791fb535d8eb5ef62c7d29..2dd020b6410200cd9fabaf8c005f135fa1926301 100644 GIT binary patch delta 2119 zcmV-N2)Os?5aTE*{Xrj3e&m4A7EFM#I8`rA(DLunU` zO5yn=`SZbwv~_`=nW;zn3ah0FlsXvmrl1CDK$2RAm-YKv&C3UxzmXt~8C?9^ctGz5 zfjG9>GKdhfXpX7~m!)&QUhdS!YqXEO)4wTTkjsl6)yMW_O3ptptEWeS<^MMtK@0?R zjp9tKuwo)ljen*NwgDbrs=+PhegBip)1c++LrNRpt(S;NP27kED2}QYtD)K)z)H!; zOccQ-ITses1@=`W=k7+z-@$xSH;fQ2K=#U_g>0T3RlBxLA#Z^K_BAg``L0a^?4O%F z*sl7MkTjD-QTh|rr@;DN9(S%+HiQq`qTv39OzhcW6n~T1MrVa=>dp;_!jgPJSCh0< zAs1qx@+)b7UBd*Ra>_~v%@*u_g#sj)3(H@&3R};n-7$Nu30+{VyZiw%7LvIUhDwUY zNUtAVIo&QNP#a846K>b8(Kzkhap`9fpb`TFH1ISZ)SRaVL{I5uqPFqSeFb@!KFtxD z>D+7Q(;GC-q3&J(7ffouYd5vE?aHYr?wW51-}q~*^RJ|iYdrmH$(=ZPbugoIpH8qR z5!;Uc_4Nx!wV@Q^;M+rwL~cZ-fL(KQ%^$VK@5n?DT=Q`JC1PQXHJp=hpL-K1Z;JH&!a_y9k)1ju zK<7kV!%xTNM*c1BGh9(Ng=py>DU}l3Pvr>W~w+ zy|=aGb2+Lz!3kdRyyRJW}O;Q;_r z#{0PEQ@J%^ZBZ#^1-mdDp77B^SrMe`r6kp>Mb;uttz?=q^30zd7lXH>1Fr=FQh$dP zh9cJ>Xb|??x!~?MM9`v?%d8~mMY$MiVo-m=2XZL3H->E{NQI5@)N}nAlgAFzkE9{2 zPx>h57OE!rBE-7&ORVe7JinA_JD}W{pPLjXxXctOWy%N0yX@lYfYODC zTF=)#xlR6h6Kl5~V?i2P!0A9vwtvi)^(;%N_lpaQLA;RyzK;2526Ee2VTKL!S>w4t zT7`XPjT}z&fY>SNW+E0@m<@1_WfJXH7%ECX_mVX8M(IP1y&9U=Bo+4!xy%o5{bktixCJ(_pvrbeUp89uy8_qjNw*$I;yN` z3Q_X7iJ533dY2)5RxH5)U?dJv@`*KBlx&T;?q$jOfyR^$1t{NY8GjN#3X(9c9qEY| zbl+N;LD=dtfTV#b34x}|^ZT(Je!_Ihl5rY{R3@0{sNn0^l^FgFxI3(xpp2ROZ(hw6 zMb@B?r)XfyTLRT!qiw~{3V9|}I_W_ok=z%GF7ZI3p!o{pm8XPKkJP&cUH$c6oY#olc{WL7MmsRkFO+$LR!b7ZL8^0_rSaZkJh7Bm3_)U&_ufvNLU8{{4fI#9 zXx|lmv=Sc93f`q$MAnF+TlnL+({Ox6ZR1dzycMJ9ILj~Sy?-}1k1gR@i%#0k7Y`CV zuR2l!WCh%YuMTYw4YGA>X+etrnJx?2+`q<*8R`G*r(i$o^i2GIevCK%ap}u?61+Zz zXSIU754{mJCpzBX6;DiBu-}uCk#PbX$p&d(oPh@r-l$Cw5@eP3hsij7iAy0?lW&ColYgP%VsSD(Q@T`>{oeeA$CEJ!w4GT~QE7pOZh8Nw2r6>c56_5Y` delta 2119 zcmV-N2)Os?5akW~0=P9tOTN%BFpU;05t#zm8#CE?LD!hWpX~olxwrrY z-Lq)wmPS}2)BP$AWfkt{#vWrdc$R>?Df$ot(oy9^n9_47j5!r29lEMxzn%*Z;?xM% z>$?9uO*~In+wIDQjb$m;X^EA~=qG+Qi|VyC@*(qIbVhCDGk*q?aRY}s^s7g<~TKrWpOlR}^BLZ3u(Pd>>}t^?nQ zc-ACOrbYEJiGRq0-{Mm9m3X$+g(=KY2B9i%D=u8s3Be=}kERL%H8N+5q6H$p+P=ZX z3(>rQ$7O)-p}+rB)>SI1))V)wEQF1$fIye9)5I$KVP zmtwpsN`KOIz*7(tyoX;(>-Fy6!jDjPw&%{lzVEWfAI`}d3?UqH$Ihz*`jAgxJ#ppk zS2-azFNJ%IiArY@tAsevi~w&OJ0KP-wM-cfz?eQ8^qwtwP_eysw2YE8(SaZ>Kky`(INKKmfG zRybbe&xWBLT8ihD?A%uH@%I_9Fb-}(c2|`so0F@9Eqz;T4>Wj`twFwamy)MYLtrut zsZ?nKyOa?p9!$>YslDt*SR}yQ`};&wL`FkLs3y_6q%oW#3X0C@Lf0B13t+GX>&dvt z=YJSv0dJRf5QCMRDE36^Kn!FLK=%poB|rlJ4qBaUr#bb4;Txmoq)r(0t zYo9x5>(o$P9qz?%yNp0orJw`9Ukd2WNPpao5V)8X<6&y;LT6Xbo~_SFYI8Kb%(~uQ zhj-W7H~K|-PT9G^dZav-FS$=WyAbShC>)lnDnDH?C{*%Vm<#d)bs1l#fB~EX!Q13P z;E_+@jzQtPm`N`e`ln+6-WGQErOw=V9B@*nF04cddDY?leH?z8^^<)2STPh>VSgH9 zLNnba!Y;d(Rcnb+IeZ>R%{Dk0=J5C65;Xt*OS#Z7X!cFCX6g~`ylk9 z7ti$Oqe>dl(5adM{Gse{TBo5b`neL~L+E`qDYqd)X&LhBuiSTb=Z=;}RG(cQXgz(8 z7X*th=NRvfI(&RpV8}Q|(n;w;DSsK)`S_(WdhQd(gc7q5n%2UgEiK6++ve8r_sLr1 zNNAip+J={2baptK=nVt->e4$*At9@lzHMa*7C-Bwk9zr(qKC>5y6sMV?tkIXvIJ7F2S2c$ z7^m+QaxcX+t_sK4G>FL?tvA@6%bs*|HGbib3sqiS5fX0vsN`d8WsqN?=oCrSDBD&A zPF@PbbK1FxZd}I(UbM=nUX^^5KL|uifyKO^&0>a?6Y77O&8$c`e8cN+k+VFhI&*1! zSE*>&-dTz5$hohQ=zqu~|0iFFL#gv(1NrP1vGgton7WCXxGPy#o~~^@Hcu*UfI-z+ z?@clm)v-L5f@^`jn=P-RgYtq$SYJ$Qr3)X@tZ`9Dde78%#dbdd)zqxm`J% zJelJwKed;O@;A%u5E*HRIZMsblK_$%j{m~bObn3}fi|DjkQ80qYUO#_-Wz6X6fU76 zK=&xmG95D>Dt{HtB=gB=zuibkxABk-zXf1Dm96uLE)~9`Hg}Nt4FuiFq|0%mtJ2L8 zC0|hTZ74l|U7Fd$dCm&`v563QUZEfy121Lq8G=lOCH;+ue!ZW7_JuwMPmAa_IM_Q(le{=km<>aJ9g-f7CWkgv|x2?UpNIAxV^89+jvt`kKklr^UFB9l^;(2~F$ x;*zxLzBtMAGM^LA88l==-fe`a&lUu|yT>pv_r7_&n4biyM}XHr%om7OU67(F9hd+B diff --git a/assets/data/tool-ui/text_sorter.dat b/assets/data/tool-ui/text_sorter.dat index 4b3b267a4daa2fa80b9fffea52bd1c4aef54770d..af1980e433fed72796c9855a98c7cc6698c732c0 100644 GIT binary patch delta 2087 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 RKpmdrE|a0Ne0k1T{9)WX4-fzV delta 2087 zcmV+?2-x?=5XKOYHh)fC3~ZTjYgm_b&r7tXY8zPF`(DvmYcBVA$C|xOLZk~*rBIG*?-!b=k4jS5#@M(iSfbRri-A6H zF*+KLui5AL7np@V0s%y#B_ImbXexDpBDh3gG%xprJ8Xa1$$!D2tnqHUPs^mXbX%j@ zM7mbmkycZG;Dk1zMdzp3@CSuMmDZ>49AB8d0r7Wy{AWX1{!ZX*+AFXD?)3Wl7ya53 zfqR87OL9a9qbnc6yOl1l@P&}nsg&9=!283R6;QxAoB(}c&Dy{bSkMy6eg(*t!kUXk zJ)luTFmQbk#DBkpk9?S_jQ^Pm{EJs6O;|Dr+&+Wh)X%^y>Ofn&?AQ!TH?-@b7mu$V zq}i#sy3-SrT_&bQWTAfZL|{5BwB3wSse2xwkf7!+^KX-E%kF}*YKX9Zg#1^?{Ui^4 zoS|2kt;nnam3lB6wRdfgQ>Y&#P~-TB=U~8VjB+$BAAjKhbcJgDgY9nB)|D7Q3Mru= zrkW9JcW>{eZZ&-}(t^Wbyd7vDC3=5TW$Z-j_lcq?cs`rBR{kL*rRj}T36Gj9-g^oH zm)7EEwt|9VxAP~a(yFAMqTUb3gpI{7JCW_y#@x+wWHxA-q|0bwj|_dYH}G&-6eUPR z2vEja?tdU1zv71bUCQG?XpFaPu9TetLz2^RFFRCb)EukYR1Kl3;P9nILTIGeO9jJUFAdeM8WZk*wpTJ<;#zq29ck$=E&D=j{OTynXOAQao3G#=+pi`szy z^+&4oF(>A$GGW)5G7CcBH7(3vB{x*}Bu!!t;;LfT#pWvKL3SuvLS+mP`@V9EY}z|j z9oDU!VWD1)6N*CIT!&6@5rdw^sUj_QEe=EWS=~{FhUR3gQ<6L4y29*1Yna;C=;>E4 zYkw$|X8%NV$_WizCk_=2#-axN z(2rS?a-AL!$y}>TD&Q*4;uXHgW{-`c;-2cv^$X+Pv9g1HS8AaXxMBS&Emc>;=LTa5 zC;MGbGFdS;iYiv9OxU>tl4rtI<2H$FqrtfIj9d+CuA4$aHY+)- zvW&_OGm&bVB0nDkpjp2HxThVmnYURF60Es0Sjv5BiU_O9lyglpC@U#DpR&D3gSOvO zI*sy|XBJ#!@5Olt~Rah17z45QndNP+42i}ckUrkzrx-z0g93uU~t zy4C;k;PzmcWbQ;A+$8_QybL#MfM@n*^-~vzuz@9Jk!4TV@K_455Tc&IN`GYZ%-L|Q zF)IIn7b{Y_KSD8|viG;x_9*X-aG!8#20&<$0Izk7`+y0@@DQI)whbOUoEOoM1Q%C` zAv&_Iq8KaJUh8-~H)RFXE&(_i6VZ}o1Kqkt-V}4u^k^(UC@nj88H^PrcqSyBuo0D6 z1wfJ9ZyKR$`fixKIh7p=5`SM2mN_jrfsAI<&N!(DwHYYDbALj#WnP88q0>3aeT=sJ$TynB zM9S2WN#2M2Y+Qp6l^rKA??N#DXON56N&uCY=WlePNrk;L=azbqMHLOCP7-<6uPV!1 z7j-|aI>ViNX82+$P=CjNg&1L(N+IMk3b#(8ovzx2IL6_zhO`;pKe&?x>#X#J8MOov z*jm+L<#h0mC(0Au)TT-+X)p34+gdtG(OpNV`#&l!dOTo^SLL-*p21{jumY)X8_Tti z$YHxiwpYhSv2P*=LqS=j8D?2S5huYl<-kYp9ljTYM~5`d&3~kf(F`I@o-^Pw09UHd zccYs;gsD1iWELZgmytESbr;ez88V6*_U@0RrPpH>P;eZ*Z|N$;v;*K2qkTO)jL}Bu zbCOlA0XmIy8Hsyk!?#XVUNOb(mq7fG`W*KdKS!Q{ehBFC$=`jsrF)z!@s>c|UFB7< zHKLi#1RD6A`tMX&Grq5LWm201 Ri)pceQNlY_9^OL%ISbz~0(k%c diff --git a/assets/data/tool-ui/text_splitter.dat b/assets/data/tool-ui/text_splitter.dat index 508f4ca15dfae6b03a9c536344a1b5e089884177..1bae7bb04a4ac19ea502e1c77ed5e5cc550e35e4 100644 GIT binary patch delta 2087 zcmV+?2-x??5XcaaIDh1jK>}jGaAAf;1XeKx+><c|S3wBeqO7l+^ zZhDlQ?1r{C3@4zyca7p#7bo}VLNF`l8tSD0Q(#;_;(Zf`EPvR?NTRIc^_k`*Fo2BD zfhTbyv=%D@XgiWkR(*3SFnX!yDCQ6jx!Sx0TLsspo!irx#3kxLQ!2atyT0Bwfl_XG zo!JR}3_#D0X&Pw4t@}A7`6TYQ7>RfI93E67{UFTU)G=8nmGayADta6K9MIU+^p{LN z%GBTTRphyr0DmT=ITgt_{naJpk6jK_BJD`VD!P$@4y)rN(i^)jD#Z*W4U>;}J`28J zCib5|lS=#JeK%$Me_|{jdm(Z2oDd|FouA8d>~F9Po4uoTE}>wf(>d|(#EjO}fGJ}c zA*Nm_9XiQc%OEuGxhoBM+U^(=^#_M%3Dp*dtCtv z_+6l>rvpuCIN?g7s(24XAFA8CH*85QAmF^Fxa!rtLVS@$G5dFu_9SSjd$Cr;>)MJU zd-~h*o~}6<-Yo~_`RgZ|CH9MuLcyip^RiI*I?{dN^i4i-9oJqxN63J+wZ(_u#VTRN zuVGRMyAb+|M+927ysZ9-iN{s$JmNR7H_o8N;=$MDse;#Mu>n3t&N4V zoW8uO>i%tLTu4$j31(k5@Z+~av?Mzjg~oB*SgQwujF7{<@OH52>)S>jh7ZW~Ixvpv*dk$D-OxL)=5Zh(42uha9%-%2GZkbeaF5I!;h%>~$TZ zM}JeSh9;YB-UOPjmxW7j6sqAB^-a`O1aW-c7&Rz`ycsB%hmq@~AeA`c5?*jJv4mnH zx|bjtw~)#b-{!lwjS)|S&I{H;YVliEmv!1!UYeab*QT7x6XXN9*KDlxV6uYlA2FSL zBP{E3o%Bi*!M7X$$Nhv(B7Y>wN9^P>K%d@M`%9#67Lk6ewuMBA<72-f zo`ICa?G0aC)Gij-G~Lj5Ek>{|bR0!D(an`F$9;*Xc1?dc)ow4xG*l@U)uqSm9}6MM zg>YS%y&vHWJ$6P$%F8d^W8CWSr~RC{2Y&u?=A&TE41w=l zvYwbQ)ssz13OiFN>DrEN{SUg%JOro&eno2)SII-XY*@GBK z<{n?LefMeoZ;EcS^@mB476q8n=5Hz4zR7r9j$gX4BiqYH{i(lLR;X0tqQSBIXYgAbxMz!-W zo!FcK1Y7b*jqqQDiY0=iQUG_5j!Gz^O#41+bbU^QnIE7$kiI{kBY)3k36V*O^-T0k zp{b{3JARN%I4*I?@L&$Z{Opa2xq~>vZV%)~lwjR+QNPoB=C+?cc>o*FI_5rloiWMFAQS=JWik!UI`D@7e zDa(0kdDf?1hr7@u=6?yzz9hiVB|-7O#i~De@_>zCRxoX1s`T=pb@~^wO}bUbG^+i! z-w#F}5+}ff2pS1Q+<-G70vV1evcSg|`Uf7P+eor}rmC`o8{?0S7dC0|~(>0rp8Rzf#M&wXns+PRO8D6jDr zKEA{?>o01ejemg`MWm5-VefU%&(C0@nDS7b{;1s{*pEksH8fC3Z0%E9&QhHymk~kU z9xywt6pGi&b&5c#K`UZ4FSCu0Me3S$i=8Y5iGgoQ{8r){;ct0_p2p0aiO8Gr@`l45 zYY!`hWEW~=?^!hiSuJz0>%W_?Qf*xA_k#6-!Ru`n>>yiPfr8@S4OZq5F`Ke~ps;$+ Rbuapn-(8qaryB8&^O%5v8}a}E delta 2087 zcmV+?2-x??5XcaaIDg7zK9+V@JrcxY@NZ4sOq^00zxzHnh!?tz?^xP#v#Ye#rhrWf z#I&C;4kSSZMELf+hgsInDn(tMG>2PMy-Pc(UzTvCv=^ej6^P?4_RiQ0;aY7dNBgz# zyyty~I8k9e(hD>$BA$?8W;iU5O@b+q2H6g8RGNl-&#hMj+JElR<7W`RY&kc4NeIzf zl?;8`c;>t>F;POzeHEv(v6B#hmJhYpUur!@0CF<{9nv6FeB86+eH%?X8Z=oCAaWLr zEk-H1K=nOv3_6FODdh0V{rIw4s%9-0rJQh%Tkf~(r9y58Ve_&quEvnn+OV~JRr>e2 zOs5z0c5+MZxqsM!8s>7!q}S0ey%E`c+I*Njrdn6v4$_%E#@{i&?mtX;XShWR^khN}|t>|RFZ{X6Ts|?pz_-QsL4Sz=1G85R9{N{-92ZhXSG?F5w zclCil|K=Cs4nV||K{-)~QIPCk0D=qjh`)H;m-a#0nHiolNZWw6^k^EvMktPR^*35K zLZ8WvoWy88l*KdqzBz4#UjHXm!RuJCER#UV60T6XwFV?9s2onUYw$u#oOVh>s4ee- z0+2nVNPk(@N@BeQp_v-5x5SV7yzp$wxZP=fpHEZvy4Gct4vwb0)BBA+^Foe|u8=N3oD6*jhm&@N{vv2HK@Y>>c z!+&S$^zJv1eZluQL`7ct_|1K_+Vq3BleIi7-U&)Y`o4@28EHIZX`$wIQED4t3~6?# zg#mpug+_LTBxn6*?fqxBrFzFYKg@QE7K!dN-*!6(a-n}kxpcF)&5xJ{wLqnAUOdykZ8v$Kw^CY8#Owy!z%0>(4?}& zTZS_x(?(p8POdo@;J?r=2?ge7=9?@074gA9W@OW*XX{!f>t^;5Z*>YG86op9>-rBN z7WTibDOD3IQ}H?UiZkq{LVfaHvGSWEV)l7mVw_MfoB$V% z4y2HgA?Cu^lR3s*<(DkHe0#u3?0(&xA6V@CVP^tOV`C~J3&x}2osZ2Lx(+@ro7t>&RF#bJusKmpahe0E!`-lKQWFn^x9S={6D zH7y97&MiKW*hQxE-h>t1s2#0F>0AslPu6SBZcrr`0T0PA{E0yNDw~uYBaib#Rp{vy zr(K_~#Gq7K%X@qNTHf*z1J04^zmnH-twaj<&Yn*fkn%#D_D&pqH^;G=q!OyF!#1-* zH?w>(oz(^R^GIEuyx5Y9YGrkKgZh_J>VOku? zeB1`LWio4hXteT=MP6^aYEbj*?$kId@A{f2DZoi z^aOX4V;YDi53nRbi0KUWG<_qbT|fw|%-7cU2e$1RmWgqJcZi+9$4@ot0VQF7BuZ`f zk`3rsO}b8RFRF!RQc|?2H9vp?dwxI5JhdqjG+lVjktc`|uIGGp-d`-$@iT!;OcD(_ zecK?0&+MHZUHUCONC`f4S|$md%!gwt_)R~5yI_klK+8JP5!NXLc@>Tj^J>9&7(ze4e0@}iK7OXB%1((oih?Dh%?De^mA=+$wRIP4|O@Q0r3C; diff --git a/assets/data/tool-ui/text_statistics.dat b/assets/data/tool-ui/text_statistics.dat index cff05a1e1c0d5b430e3f53aae31f69d82d2d82fb..c59f97357d74f05863edccd3b5390c762ac90f15 100644 GIT binary patch delta 2119 zcmV-N2)Os^5b6++I)C>q-7&WE&@|U|xxiwwGU{xZD7AZABP0eKhAoJMxU`1_cbOL3 zoH>@?rv_H19{^$YQT9?g5yBf`V3aP|cmh`^jZ&(9rJJ((_sUIkjTL}bd_$T$(tp{e zXnqFwA>eG7QlvXvJNoKXf(4f-teZey-EPSoVv*TPmUVo@TtMk8w#NflT*c7HXoQg2lM(StK|&|FX(?m^zO z?m#({3GFgAO9bi=mBiW+Y!(2y-6@O$ardgS zqZ3d3D$N40f#7 z+)TZ#=3cHarC-o_Q>IJJ0|_s4^x1BzALAU}&rwMul8Tg#BOa|g3W*BYVQVH=q3GiH zyrSJDi|IFXTR7LhY9*dt(O7N2bd`yAfCHetFMnF|w_Ql_r>0mh#1_*JldqMR)cz;( zL^NsER3|=08o8&QaTc@xCbtExk1zmSfQ`{k}tH6Z1g@b%tUZyWV| zoGqjBkE!Q4oB&WP+)S=UNujg&8im3*xwXp5wa$6(jFl1PG<&cv{^ggKb6R}=jhVo1H`Nb1J!IMLxD%A-aTG--4#mQ6w&~#_3H_ww8`OvWlg`jrT!o}qUa#sh){1};^KVzYX^uLeLh3^0Pw@apNFD1T|* zTk6k#+up!$kW^hn=&WYTc6|*|s!7xxYj7$>(tl#U z=!C^JBAqctRi1zBNmn*V9H%9U_b^|l$5I%mM{ZX6o)U;TDR^lRn`@1h^nZo=JejwH z4-_j8e>T%uzqv&hF8YuPStU0cTH)<{p`;W6qb@i^Ii}rZ8Z)4Sgq)&p>6;fSCVoAV zPt#NvoITDHoScgs&swHO(vt+~fL=-q=IOuHze%}w{oP|d76x$^L^OV6ZH6^UY!UC8 z`rBsP-c7MHyIX%G0Xq^2IHfbHTA_zQV4<@Ur#GMBJTQr$DCBbvhi7 zbK?P+>0O1Lh`H;7u$@60+pl&<{u4pxdq{e|;uF{&<|l^0y`Zl()qk;_EH$$9=eNn- zfO?CYk=5m8&MERrhjYxNo77K*Y}XKh|Kur>A4do|0=gworj)@!XfM;DBdXs~%*LR7 zhrc&+vILNFT&a|tDm5|11-u|?gAO9$;_W|B2uLo=;6lMG8WL!!VZUit6*&VpAc$cj zs+A-~S129mbHPk_Hh*UMOQ_E^>8G^k;gp2+lvy>amYISJ2!8ht*neUi?#^9xsZDIW zbVm#Ve+GNwCydljjP09f(?D$00Fx=Cu!Yp=dy-l*rk3Mzhb{x!WNld1b0dcCd32G` z56Jx#ebtjs2#^Eh|RS)IaDOj>m{Ab2z5`pyw`ozFEylTt*MK4zs@aTE`%v5 zgt4~5;2hE*?BK}V76_QWajGpvGd}dju2AD<8&H*$(Q0+22LZJrhBPp>AdH3TCMG5s zD0{+a92HO4P=C~yk~Vk;^ya#f955&oR52?6YM95vzB>=}zPpTC5s|A&<{;^jIacvJ zx#(Lq7Sb+Gi_n0+_`r+zx0~}bF&Wcha>jLVWDa@`u!t7vz@In;zW1f+F1vydOIxz` zi|A|DPS%+&cP3_FlGj3#c!QH)eh+4dF}Fc}hO-H`lt3Sqn}UeqeQ-mp>#tMzVvcLf xzIx`+gNJw5D3l+LalHlxxEi1%yEmaIE1FYXD9)YPY0Kvuv#8KkNZI@!?EoftFAx9# delta 2119 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 B^d$fQ diff --git a/assets/data/tool-ui/time_duration_converter.dat b/assets/data/tool-ui/time_duration_converter.dat index 340a86d3988fc76909e7238f80e343ea736c84e8..14401236f07d932bc3836980b878a6478da9303d 100644 GIT binary patch delta 2054 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 diff --git a/assets/data/tool-ui/timestamp_converter.dat b/assets/data/tool-ui/timestamp_converter.dat index 4e20d65e2cbef004261c9a3b13d11af00b57c5a8..bb467159d11b3d88b724af963236bc971e7539fc 100644 GIT binary patch delta 2135 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%0DHEr=yx$`EILhQ6=UlzZt zSiq~zMeNI!`+xIxG*Y5=Q{S{hH1@e^{!ulMx+J?$?DBmj*u_{V19|S*TvYG%j)O2* z?1uVNTawLn8n$AzS#6V*R0M;Oc)5ep+>2)V+nj!yYb)+ptkkq9s>a%bIGu zvV)|IV&GqAIqAxAl8!aBl#D&7?1tdu-IN2Z_8g55Y*3xDNS014!kcb}{d2HE>r%Z4 zdTO{#05Ui3IM(sGo!5!*v7*CuKDi=r)AIyGpPJQcQCWmDKZPgIsS@Q3#X^VzKA$a} N65OhK5sb79KMuzLH)sF= delta 2135 zcmV-d2&nh|5dIL5K7V@jls^|I+2XxkM31aCUMc^IrfI6FN3heV7Q}37*~wvRrta%OiN2j%s7+j$hrn6qOUoVwF$K`pemI&L@&4k!|E% z{B;8atFk_b6J*W^+i@YFxy-Fm=l?wj<-~I3A)UbH$ZZ8WGk>qI7%LxcGTO4{lH>$( zHajZB=W*3p5i@CHIQ&F>L45er{!ATgXR3GQ|ENxYpFFIlY4Bd~W3KH6dblbCD|%9B zyqT`}FE)n%O3F@Q#LZTn>uS}S#h>|wV6 zyO0D3z4XlQ=zqu`gnN`owVeJx3mHP!DV}uzIf3ScPF*o~YN;hVOU4IadeP5az=4 zsOLBF1?{}9Q5QP3<$FbVAgGPLz~Q|6!ggQfb~@~X`!^AMcyHZXP0Kz@&*#faRCxg= zfF_+yCt@%aFc092z!LeP)*ju!bFfXn`0EB%c9d4xb&idrFa*% ziD8%pRDTzi!iFmpf@cs1%kDJx-Rp3l2)_~=H$*0+YV)p|Y#usL41(F-2S0-vBB{q) z;<&UezvYkH_KH3@O1$Mn-=b8vjKaMmxwnbEI!f-xQz$V_$EUQ7%$?+wIXOk3@6b{H zQNNlQ(S59R@Su0hP_j3|WYyGK^2|+(Qh!ijs82d~#6W$8tqjI>sJJD`GTKH> zusFEtxz$$vgLQoK>^K%~-ls+qP79$k%LYtlskxVf-|S!VmURP zYkzl|WjIPHV>ywN0$a2X_R1a;KQX@UbwrV@=)bqPg;0V9wgJyDwTv=FAb97vX8?gE0*>$mm6otldzh+mu?RJTMyc_#r{OGgsa+;B;0w_cW zOKxj#Bg#ak=!E4^>ZrWQRNpzCbVXr#LnQ>815@K>ACE^Fn>lD!K<3$FmYh%jMOHp zrA|>3I7iYdS8}xN`BK#_l2JOh1M{zP@TE#LgQmgd`khuaJs<@tToX$7J#cX6y9A(c zoFf;PgNYTtB@32fRP(jF*dA-V3!>aQ)KODR8M@K?0YYNck>^eBY>*=QB!4=G6P3@= zq8=3LP*}7;+lnxzI)xjL_c`6~FafE>_`<_0)WHk2GQ1+i??`Asnd&EU=UV$&0S8{#3ZDt{jhLN2;8lw=*F?TLYKn; zj6Bai*RiPx5!i9n56BXMgq+;Emw`u@85=j*1Ye*%r-elLFksbL7Y>gPB#fG0SI#JiKwa zi4+^u*W$Llz2q{^CmW>6I}peeX5^Udab}{~&gpVk$oJj|x0mqH3KUP$t7qMHw*1)V zUePZ+^Jw9J2!qQ-i!FrL@U#F>)&PtVy?^+_AR=wp#Ca$}n1A1{{r!6O=$vkxSCMJ= z^uYPp^eyw}kAkM*TeXxMKCpO)_d#L>umDa$QZaWHDw4y#SZIkY)-*rqAuKZvesaq# z8S>DCuh*q{#UGUWfluAPCL!R{O@(@>IVq9D3Q%{Nw_e?;?My{DKx|n9(+H<5|Mi`H zEs7sEz@2cJx_>`RapCNJu4--GiavlPO-4E;>#b<1zf5}1$|D`^GP0(ZVVXXIutA0` ztOpN<$i>+%u!(8QKs0kW)ZnA&=#>;T9J8dil`5nMU4w-_HEv9Yml_S04EqGGF+hfrlWs91F^QX8d8TkWOW!S1Gg zbr}>UL{3PRK_)ETJa7WJ5;$WE%#1s39zf~<)lnMO--~SK8^?3p@QZ~=%2BP0dF2p3 NfA{y!QuS=u-aebBEdl@l diff --git a/assets/data/tool-ui/timezone_abbr_lookup.dat b/assets/data/tool-ui/timezone_abbr_lookup.dat index 4ad984f744fbeaf61129723fead433cc6ee7da1d..08cefeeef84721b571422d7cb385e713a42cc217 100644 GIT binary patch delta 1393 zcmV-%1&;ck3!e*+KYu($eB8;(YGsVu~4Hm7|%Z^L&{$JDELlliPxIrYl0D>B{o15e2d2lU?%I zw4Lex+~^0x$5Ng?WV;HiyG>A}of|@5Qc$eToIB&e0%QP6UVonc?4*!513N_Xe6j1o z0a4hM!FDQb0fo(_mIi>W+%zwGExOA6;;1M7%a7ZFA>nsHF&1NJPbq!VKSC$X6fQD&&}ulH-FE^!0j_Du2h7^(6PNGv?#9vUs6I10mI23^PIi3kwZLruQF;+GCj|iEPSRT`yYAEn(0vg&^V}hQK zpm@fmgz!=cN#UX@!1>$}NZ)ejs9Wyga!>U zXNvz1m1-;uB-rw^W1YawvGjM~b=GFBN0%d|?zrI==`*yGGFuYfzA)0N=}|Q!vQKJ7 zCJeHm<$F!*g|sUVpE)q>|Fm`Kv^#S;b7w<=U`wOf{Mjl(7HpMM=Dzke5E zloD5G#P|vlDelPNB;<%jC{#F57#z|`5?G}XOA*8_wi=yo^Rk?r#GH_796?-lPKadTO^}8|Tfy zlrr==^PYQXK=L+~fyh8iIOOEN?Pw9l$WTdOxm?_iR^xp(UmB-ajNf9~_+a`QL{Rn6 zG5cVL{+ey3AIO#1*$T#PZVVWH5{rL=;p~Wn^pc}=|EnM zZT{6}j`Qe7a7y)BYn7@pK$#f^|M$C}`hLs1)rIyQy*pT7Eq^HtJ#^+L)BI*tckZ#* zuiqAuGS`?*BT?t2Ip(&*V8-gHm1|2j4TaA6d;a=W`y(wqAvnINT4)azIi@gV+<*tW zH+d+w z6Y>uiS~JSd>VFp3n-%3Xgws%;i4&2>kj+Wzu(eYTt zxc((RY?=ua8>5K}Nj>1;sAmaPQG0#g9+_GV?6-GGUS?2Qq+PfvZPbqq_kZl9JzV7Z zgjcm1m;T+orskZct+i#|i&8aN`U+P>w`xW_gS5a=5A{m8b$emlaI1e@y7m{8aXKLj zACD(vVSmVhD9~E!i_pNPDS)|8E>M46tfj8t)n@;*{k3apxib|) zGL%f68@~zG-)?Q_UZcDyO6mJozG{8hjkJz>41a4Se3HChn2~=x^H%3Az=J8aZEF-} zRU>^Rbv#N81}uCbctUFM7L$u@MyfX%4R6d8BdooK0WCU=zDxGEUbr}3@) zKx-^osV`bsettYf)ua#`QW9?NZ~ZNP53CtJ%&9s|tFCIFl~6!7$INe{H;0KGl{D*y zRe$DLUYT8ZhhXr+(SU!^adP;D&*cv$Y~mqZ4kjKubo_CFd1u5wE%H4UY~W!b=r-7Y zZp#XPMOc!lB-lLvlC|xH544h6BX=%}0ljr@6P@=``yan}n~^GGY=4@fM&T?Q3XnO* zrP9OAXvP?&BsQV4)z(<=KJl}W4T=B_=YNBR-ryP1HrM8}A}i=z#%eRnMPhqQ;a)|x z9`UM$)?Wet6p>WjfvXZ*lgT@&qBQByA$SLOZBXIp^nh>R|MgjqB+dPHU@E?j`_PQ9qs(B&n zbHp-lgph!5-J74RT4%VKDDKT4wafIKuI-x!U#qD5Yr|BKmxHZRZznqdRI9u~Sr<0J zo@4dF$Yqn|HT8DzPuW}5s7pd`qVvc2u^^ktp)9x2D6 z`~`gMe=ioY`@m@@VDd5O`}sH=2w~Y4qKHQ5xTu=&9k2p6_^?)w5W(R_EEEmKsvJVr z=quMbsji95Rxl(H%oh%Jw7Hnk)4IBhnYkeye)=0)zLL$OH%G#c-f6GtGiphZO4h$k zVz@cPN5ZQWq&-E;s$hpl@OMIx1rm~-v<;{X55q^9?Lc$w-uP{Q<%;!UAQ9`ZJ;;WJ z;X$TAULnvsT$svAFCyHDg!;NB>PBwIDT681ZtvcwIY=D0E|t7|PC5xNjV_N77RIfa diff --git a/assets/data/tool-ui/totp_generator.dat b/assets/data/tool-ui/totp_generator.dat index 16da476f3249ec89d3708c9f582b2ed711df057a..35b120c170edf5b90c3d9a53dd65ddedb19b7332 100644 GIT binary patch delta 2184 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 Y^zW`6Dz-75Nqd%~eP{8yMqi4DgCkx9-~a#s delta 1426 zcmV;D1#SBF3ziFz7JqKdxebwiq29dXszAK>5nRb06iAc{%|0HVsyE?paUNDg(dDmz z7>_|=R^cCrefhdTYBrD@jzGUj4JP6rcGtbesC2p1Lnm^u^zi=|3n zcSp&yJ+~$674%H|irnUY8f7>E(X`mGa<7DA(1srCSi1s8%i*mDZ$r?TuJ z6Y;#y6lQF}+<%cc3?6vsMwJ%134~?vL;Al~j2%8KKLos{k%Ub+Ua&L3CO-P1n+tXg zKECU$g5-+W8<+_C88oxLTgzg&*r%ZH%S{U{8=tNecRKZ>q6UBS z%j5T|_D&SvPcV1TGe62YnJpraHd~<==s4+R`aviG=zp>6SRp3|nPahf!$k&EKj-$v zm25L`3lp&7tm=dLT_W|9pQ@RM&GWt`H?Yp&+f=D0l76rzsijFZx6iropbn%IJjaA% z)>?(&sgD4a!?U1tBzLi00>m$uM~mXx+fhQ6hXHPkF(2g%2(GH&;Z6Y(qsBj#*r&bo zTNpjlfPWH08G`{TuE`(5nJ;q6FWRC}J-z|CUhV&(Chv~UFcm1MPJMoFAtRgW_q~^1 zv!@b81W$&#Cq6GQ2Lfb16s?e;=(s6J9F^u!2>YS#?miNdY)+(BkBxnia@wf3m*yQM zrICz0mUr)8xI%V{q>KecmOaje{*Vq{H&EpKFMpF`CXe#R^J?0Jq9N;_X7T25G>W$z zz_cog5mQ087H$a8di+W1Dzczns|a{P@{_FDocD5@!_Nb|x~FNV1NYXw$I3a?^yt$4 z=;=^=|Jew|8dgg|>wjxp*H=gbgfK|9qEfDXGzmgCo7%%xh0&zOxrB!6LeFZ@$}_T` ztbhM{Nv(DRoT`H@iE{CGl5t}^gn1L#Lt+aKiy(g7(Q{?adsqXdCvt?~R6m3%`$q>5 zWv-w4`iDs2>hLvqP3<)w`VJ3^i41sVIp6!0f7?!WW=Sv~q!X4rp=<&nn@2G~uL#hI z&p-kDJ3ZdQ|7I$?q-zY+qyFhfPZW<|H5(>*O%Dj_V*!u%8#q0w4RoPTU@yz8&|R^VY< zqL3o$UC)SfDpbQK^=Zp-`okrQp=5rbT%XED3R3GQqy_oRYVXSVM*SF*7ss(uB7Yhc zw`=LG@to$i;+y4Ki#Y`?n?#d-^SLo+=oENxGeF`Ei(4F{YL*PdWGEUq)zXZ`*l#F(Fh0TC99AAL(~)zFO5vb@~ZY;rRSPXV4S2$R372!=BD`X%$q&;7PIcRQ9N1 z%nM^?idfEiLGL(>OUunyxaxE!vFvP diff --git a/assets/data/tool-ui/ulid_generator.dat b/assets/data/tool-ui/ulid_generator.dat index 67f4216facdb56b7910c93703c7e1cf61f5fd8fe..d7e1d92c413dcd6bc9b980e2647f260a703e6506 100644 GIT binary patch delta 2151 zcmV-t2$=VY5s49yIe)VQj*sPS0L&$gxH_q5lWJjac_!^A^#!E&;G0amY&l~Q>>UMm zI>WXNY;IsJR`u5?PYl@Dr|w*3V&`j));{&C*JO`F)j0Kg4gNsA(pYd1hJ)BILN~~w z9y&A*!aSG&YGjD>cA}88&6=V2dx>}%2LjfmqbEtQ%_?zQRDXw@9`ZJNl=ZFNx0nRH zAo1Lewa)cg3_zA-UE(N8fN^zkAomWe(8E^TK<(&?xW91EH;-7k|>p+1m?Lu`cOTMO}Vg)rE`Ji7fJ(m#!x*=r9A~IVoMLIET{eAqNk` zsMSJ_j}-YZpMrcMR>p#&Sozar*broLY{p*v0!shYAgwV><9w3aFv)1CB^0=R-8c}Yw5QJ@C-2NwuWhqjH_afZqmS^6uV3 zc^k$~$&6qZ>wxpW6u5s*R9F?^=p`dO-H1)(we;NIN=Wt&f2}m9q)i57jYgz@r}Fp- zeSiPR>Iw{2t+A=5Ci~SBd0G#b9NZIFftcL>8pj&DJ-oc?9v_uvxSC)bAjUk7wWIGk zy=WJKg(&rNmUNa@|4uMILy>j)-K6qh?D;9tlR`Hg`3$sSvLN+(nv&o}Jab)X_SVUomTsFl@XU3{pRsxJZ` z$Mceo4GSzcE3r!$kAY%N3=tPm_J{B2x4Znl?wj{<@m7%-kHK{Ft9nyr`wi!+>w z4d~#Yg2)^1LK3)|ky`XGd>(F2e;0@B$^e78@@e7gwH9&K!2~_(535)F}Is*S29*%1Yc-RyR#!H^G%YEThSoKsr5JVU`IU8wUQ3SGPZ zzU{Y?M(cM!r|UiFcSiqL!}+A~*d#;;jZw)=m#I{ei-WsZH-36d<(8h5$Z*}{pRm5%L>8Bo?QuL zzr!GN%2Z3J!e8$9Dr#HE5mG&Yx2{OQKz~!lyVT*<=&z1HsJ&2#*B4OWCAAv5_cS-eI2(9}mbc+l zLZTsqNI|h`B{fRyHvCE2nS>BKmfQnz2^-6Y%H{3rx<^AjDT#P6%zTGF@7rLjn9ZZG z4-iyZNkVa|ntsZO1ZPdBON`Mhgu`tb``@@Z8D+0MQp;QcQE>7BC4Wdq1gY!c^$V)8 zX$!X%y~6g8oR`bR?>}p_0*ka4+EW!)=K$K~3;y&Z{1toO)S9e3>^rjryR35^5*byt zglSdP;v^cJtTk9M$3NbVCjS=Z3bi;UGq%tfglVBx`Y7QgcY@;%fX{vPJqn@x(aPbU+4w<=^ro$&6nb2cC)(7mXnT>>R|QMTjqH00=5^nz z-H%#A3Qp2;KE!oLbUV4I*4Qwg_pJ=|K+v4`6{6q&#-gj!mVaY)w{$fR&jbFO#bIPy zLx#f$liTHTAdG63_h2H@1KIh8U)K4RH*1%!yknho_gr;R`yfcBqKy0JRpoBv|!1{KB5 z;%MtZcV<6+Kxpb%PUPQ!kpi@Fr3?7rJo1lJrwS!8dSD`ZtT^T+itz7kfcOTq#@yDM zOZ+`59hXh)K`GHQkcG7nA+qAW!e!B2EXtpbLX>jK;woyv2{ZF@Xlvn d-l{B0m4M01TJcM>PXS$U6|H2Zj}VueYRcdMGGhP$ delta 2151 zcmV-t2$=VY5s49yIe)%sp2G>jZ8ASEB2L47S=(GfeMR2R6Q=& zlA8>_CNM^!1xKk!-=u8XT=zysJLX2Mz#*#Zn$G1-mohf-L6*!AjjdD^S8?*NU4If7 z57JAs0~~%iRxjEEFe-0`#c+AVIb`fq%uG^K=EB(%HGdel%aX#YQ1g?4pYZN4!5uYk zVt3tZ4#AMn*J(y0$M49EW9+MtC?SgZ3>FBRku=i|C@d)xowb0*JMSB*Kg5(shr@C4 z-@-m*q{Gf^q@>>cja$w~QIKOF+$MYR0xN5(ym{mfyUbJnk{4LCFKboAz;MG|gw3Gj zN`FwdB!8(xz-%-C5Nt?Xp&c$X#-~yjv$MD)i z4RpGdKt3{sD9bQpp_#ZKJ!FK;M;=&GoO-^~<#`fo`O)Dxa@4&_({t4>(k86voq(Z> z^{NTlAY>(4205Nfd|%D|@-G{7a6#1Qf)E@UJ%7xZ8Ddtdln{^?G5>ud!oZVNA3rS~ zCG#YKe72d&pDcx2%NukU`^PAf2BQS9QwL}mqeJlTigFVeXNE@75kS)C*}ELunU6!m%vRf#fc(90Nfi)A0RG9hO%dVI`R??3dh*? zj{u+HQiV2?&c5aw@XqfXlP^4T=f+xtHAWLYT_Ecd7uYX-rGPG3qqz3M71EtMwHCh5dsuEE*zV$?q z_Euj$`M;1Dh@`~4@MY={#^5cÃ!5lCZ`4oAicyV^0a6YY^x)zhhh!?WdUp#aNT z0|qLvA4X9|thZDp#q%bqy(~Av3SImATE*HkRb{Z*fqeI|#4liv8k*=HzPX%1) zQfD5^Xp$Ai(azEjfXB}Vt9e1E&Y+KdhckgNF`x1gU5;Dz^%FYyPd&5lP7cSN0!f}L z;EkiW%MHkn4o>!s=~OU;W{WMcOMjj3#%M6dff8{TCgdbOXh|wa+}p({9baPp-M#1v zklP6St?U8wtvmHyT{jeD=Qy$l(6auoPO|%9LSJ*tnC*zvrB_4b;tWKEqkJHFRAI=t z0(rS?=sjA^W}w2+4YWTD$muFI&OjH~q6H)2okmz6nSAzFyB?IqWbi18R)3i)pzXP& z1sd-C>e{@4p3gJhN|aQK7R^+^A9`%+|A@@qgLZsM%!qpRjX8QjsT4rF2qKzqvThm< zgO~V@m({&{WT*m+;r!s*z1ML2ulp>cU7dyI65c(yq$q8LiYsNKPJCw!*#E*xIl+(C z%c4W(XgSKH*L8L!A1uuE2!A1yqAkF~!%J9$!L?!D5SrWuA3Al^zYROpO}GTkm(`>3 z7T*CtHH8|#GM)A>-jFj8tD~v0h-imu(%qGG2r*7FkSSFvFdVFoy<%toTL^*H3v25b0 zp)=z|4Vxv4hweIu-s-j=xQ}4?yPq!ax+%Gp2&JQ!UT?3tHyBNjm{uET2`{5ga#Y9E z^_2LP1qjbif2JB!LU4buw}-<`m&0@{eY8AoBLFi(F&ycE%zqw}&T_!p&MP46Y7;l^ zq3F;x4G8&$gSr>soM&UUnKVZp2ng0NKq)ZYJdFmhG~pdB@H8CdyK#3ZDA85W*F|2o zJpJs%M^RLxXE@~!*z!}9=Mra7hH=fysAxdaE|lTa#Tc}!))hk^5N!Hy>7BB%p8>5d zJP}SWyy;QtD1QP!dVI3Dj2~;$CyHg#JKo8B{c92P0s5V$z}JA@_3Ww}+r*ikiwgAPG{H6BmdB4FnO*%ErD+nfYyeH6jY51ce~ z+YYPUo^ezpBDC0`;twTM4Z^NVJRi`+r>?-;zc~N* dg)9z%K;>;d>{RN&l}`FE(&aS4_WtVNNYR6?GS2`2 diff --git a/assets/data/tool-ui/unicode_block_lookup.dat b/assets/data/tool-ui/unicode_block_lookup.dat index b6f6389fb240f3761731f97c6ca565db1557fef9..8d6cf33c0d36ba5494919173c08c47ad3526a858 100644 GIT binary patch delta 2135 zcmV-d2&nh}5dRR6KYwubW|&GyDH=@TgGREKekh^Im5!H6;tBWW$W~NY%fNkL-`o4Fl-geRg2#YkM>$&qoHalpk=krLnICuj=P(qX>LR7_yLOY%?BRX@4qT zzBt0jpI;aw`P5&y_g@iKyn^a!7w$i|xP1vlP;ea@xA744!+#zjU8nn6Vo(3tf zRzdT*`-h|1_CJuUW51oa;!_fGp%gn~Z*f1$uz&!!B4OZS{-gb^oeZ6|WM%vNf7*mO zwK%TkXfU0{O_vdKq8U*<;`!QRPVHU&MS2PK2VnUgkAIm;-zrQ5s5_8?vnPQ?JGwAX zo~F|+u=Sr3*vX<>_a@jfn!JrC1ttIo$*@Ds9zzLQ%A{X)wIE>5Y0OUTELdS3_jNIp z+bnrpcpD9fb~S9!(@EELGf6U1-#~CSo@#n?B&`H8&4t!Y6>-AP>LTs3cQgHeXJsiQ z!>f>|(SK>B(dusMjhIy7wBuT5ipH<4z<$uLT%>6PSA+R^!wS|73d842ell{V_#2fz zqzcyTSuQ-)k&c4WkN4xlYQVT#X!oba~7$I4`RsLGwl zcX-&ir%am)J#-5}SxIaVjrC^mX`Rde&5knC?a-Od<*%6F?+O^O?tPl^f zO$)j%!}*#I)w;lv_CH9pyTzAqFW(Dpc4mebCF!(O?|tON9gIfY5tDtx>>(^+CmsW9 zsDDP}#7g#dy%*q}(IwATXK8l_VUA#+^}FXq!mCv7^0zupR3tei5+U^1@5Qd>Q}Mu4N8btRuWgPk^L}?avRL3_3ojPTW^?rL zbiC@&+1H!YE)N9A{QTgIXW>#& z*FSt5bkgXyz^0h;NKb;pL!~eeM4y*wrk=9}$hQ<>wSqWxq`n^Ij+oN#(tnatrJ-*I zkFYu(YE~y^8K=hZGNKSFJj(C*`XwSxmGWRIjAJ|4WT*Et!yDSR@KP z(UW>3#wyej0mSfGE2M4xNPkEV1NO*>U@^w4tIe-}NpgJTc%BPr3bZ*o8ye)>A{}@z zye^?Y?AxF`w_k|+B4AHOCUd0Apl2Yxcw z^Y-b}P8Cgzk-1}ce|_LMxWll{F3oB=Lq6Jn(eU;{vnv)(jRs;B?0@#3=N6t7)uQiD z4Xbur2^B%bpTq@j0FyjwIYAmQN*;XBDHUHe!DgCT0YN@rY3TrzP;v3j`A4l1%+ zv&fc%{_deD09VOqq<a$DH-I(}-~#NTMSDSt>)wpL)y2c3`|kfzAAj@t=Iky)b!mxmV*h={ z?kjYq*($?d1l_?yB>~Y;L=OvIyMdUlAGd$We#zSp6^-8pQGC0DFrZf|V~BdinC*2Y zc<{EoW&uYGNmQ~%@p`olVME*UE+HfX;STIGJaAR4l5;YH@39K*G(ndIVMBvOZ^fv& z-go`AB_E&_xqr+iMf5EmYxH*-s4J?S_C56`zs$ZhL|JLV{DCHV+1aN+c{cuW)%u4d zeSiSxAA|-&5Vh`vy|#RCf`v7y=c>(+Aoat=45tJ}kIX(RIgi)hH|4VIy#sC&u0{(3 zc~4{zv?}3+S%HQ`9uew!!Ga&~g0LI!888rcBS+1&flwGB83Um%TGCK@rPM&Ac2db> zsQnw4)&_ItBsT*eM@T-{NJmE4L-!KcD5zBGZy5kL;|S;Bri+-6cm;GUElH@o$8<$R Nw;I=e3{IA%;6v-aBftOv delta 2135 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 delta 2119 zcmV-N2)Os?5adi@X!!y{6`>gw{bx_e}-5av@@hR zL=UKf1y#GAh2Zp?qIEdvK(9DWzkAj5@bYWH@1wbB8HePc0ZpBTSbYbeI> zjP&D9RtN6yoDfLOsA@H!jF}>VFrQ#4)Ja8JjE<9)y-}w=aL}So$+kXJZUlQ`0d2ZG z+M4KLE>#L!aeoqVf5KRs@*Jw)hQ}8YC@&80-l0!FKdk)|*;bx6qi%owDwV)eIgUiO z+8qwcKc)jx=PLn*urEKM|CI_=K(PX+;(`WXZ{5jWQH7n!dy%&Pj80?cUw~aLfjAQ> zg>q`7li8s*?U!AvG#h0#J4hWcr*b|N4uz`1C_=OH?|(SZriCmOZpXGYPcV^8?e^*~ zL{`ci1YwwQQ9purXFBvU>kn5Xj9`ql+_3?(<+bIg)Dn0Z1Dk{;*yz}?$*(VZ~&t9)~A|0~~} zisL{DPJaW(&6%D|0Ghk#ke93alVuXr+Jx8HAgkOPh@NBw1RTJQ5QDBoNSm8*{Ps+O z;(E0z2rOv`OT6X}W&rDFO7o;q(&4TcU-}D=9jk?N;Z5zFMuloUSOz0K6;_iqJMx@*v8JVFV3WapYxV=VG?%`dg}%C z28Nene|dIxyasx(c2SaP1?t7EnR(jTkg!clD*E^Mp%$nEhQA}Ulya(q{v_BKEtE9< zj6;H+AKa}+&%0y>m6?Tuj8kz5pN)!lqKTdSD>89TGtJ~X%_=2rDo*VPP7dH)`<+I> zZ-3Arg_Hu(s9N(G6RirGnZ#paUr<>c3|vZ=Hqf~+L<4L@j6vM+IDqhc`1NT!nu9%9 zbphW|dP^R^X$E>gM@K`v+I{>wC{QnpOJ!58IP4_~Y3LJeUi>d9KfpK16x_UI9$*g5 znww+y*0Rx=&)1{O*8vhEVb>fL8cA5iZhyiN;#z8Cyr<;yO!s_EYyc!|{yIKV+`4(9 zG0~u_oPE@#OU)L(ZtpzTddsgJ-GO7>EaDIf$?}od&|<0|8G4#5_LjDZlK3rB15}tG zfHh>2GoeDh0ykK?xwVp-LD}?Y8GxdB_;rTsbU>Kft!D2XZHg!<4kctrUqVi*?tcO_ zg^E;Y#;r2~P~EXOc#KhfRYP#~);FnRun!ewxr|JduCN~ye2v0l8T-p*!#&lG?}hTr zLdtvim`0e;JXO#8VM zPh&(pJt5#!)^d(OnjLmpaV78ZDu1a5-ex?Q4p&-$Gcz5_H4FK5uUr7r60-cl(5Vd+ zMvdY8Ju$(>Wx^sMkWP}E8G6Q5^3+!T;bT-hX43a9vTA-BSYsj5mfw4u)(D;g%iYUNx=YZ{cRp3Qd--0VoN$ZW$72Q7KQQr2dF`3-;pl*C z`+fSR)u(}9(h6-Yb*G`>5q~2;TTlpn4&`ze2IqWfWL|cixZ}-Y5@QiktY2{tA~lno z%H+<@UsZI*N=#Y(kln9Urd$N!77=&qrIH0~%8JIsMUB>(y0VZ=A1Qi%UMP9wF?~CU z_U;M@f>N|Nh%HCzW`O}<*CJ;emFQPE10y}3y7CZ9dzE=duBB;X`F|uvOun|Wi^fHD z3Fz(1Wtq21VLqs_4`iE6txywI#aWx0?37}cpwAon!1tNzL4ZE z?9GK7I|%CLS?TjvDDJw%oKJI8KT}EIeadf#sMbbKp~+H1=zj`TorzCB{XuP%8Yeu0 ziD9mdMxv;M!6}D`d5YAWw*BIzHK7*baLdn2#?p1STIDpIPDNaNp)*MYSqr#0d|!IR z;O4uuL;eSoemMq48^`wC1~ph5@^M>~kkPlbKC%wWBtu6#ZWeN%S2SD5#Ol;M)sfk% ze0rW+JV)WFqJME!glvqoS*1VoDHUioHsV13w3GZc!=6c15lAc5mnY#~tI$s8KzxV) z+04-rcDD8YbMl4~i`H&2-2uE2Mw)EDWyi+6^@ICzyHU!5-Q6VSg=E8;Dg#VhsG`_M zDa-g}Cx$i&+EBw+Kj$}nw$VZE-)x{T8%P1MG~^J<%s^#@cKiKjzUEI~%u~MKPtbtq x)TcEQz#EPhoLfi+)(+B2ZY5A(`HRwzp%x?VnQ!PW<9~7PVWcG+&|=X<9xiYyuZ zdj=i}c??RiS7IU3mSvVi3859za#R=@!e(L|`@sK^;E)=?(&aw?t0DWm^mVv6e?R~> zj2P{x&VMg42w3DLO?!A_>n4a)a*d4!`i8AFAha=>J*b&|f5lLcfjrr5NQ+Z6{4W8x z9{eN|PB0&hOFEUS3Z53P^?sH05)hr120Or{_lRCc*s)A9ytsTZFP%LiyE|$K@#@h; zWuMoDyA4V%+VSn$?xx{91S^(o%P+XtPy?hP8h_g@Gp~^!E7AAnS53@-d`1>%OYJG6 zR8cp5_YvsE;bCRpkdK&%6iZU1NR}Fes1Plplt{NKx^yNBgpN)xULN{;BgPJToQA|7 zx5P?qXmV|dG3nK(tweqSn#WM|dP)$EeVGoBAuVn%0T;dUnJE$cvaEGB5TF6+3{!IP zzJDo6uJb9$MTJ4pc9J)8uxO&NQ%{f z&lV6jv!{u^uccoTOQ5?r&#^l~8OZe|Y0IyLJ6nR4KcJc)>gid`#WPBCX%Q!~T2q?U zvaFNaH}*s8UMMS#&r+5HVs1sMI$q|2B7X)43_Egm0=h(#WRU8MRNE(Qn28_BwqjF! zj8XpMY2cmM14DJh^My$~+azXQO`~90jEuek8e&HJQ{DykfMq-B`swU$miH8qS=XAa z37&nnG0EUw=V9$Vo<&AM;(>^Oa}G({V!dK5g_~pzY?dQCHRd1j*26j^_}8Cipnn~I zsb51+{L=pgpiO@N%J=oTaCyM7Y7^DL`)Z?%77<^k4^m%?5fqa?;Oi6HWj*~f0bDig zmKx3`&Z1ydoEYOBlGr;3+E=+y&;YMLNHK=Zv5}RX;&$g0pUFp+96Ws;(`{tN%@VQctVE}XUx#?&l79+|n?Aw<7K#=-$=oqp_2sL~PRn5N*m?Az(Rb(S z=()stzZPQ*J`=*Iz|By^xdY{=g(~P4=DeN8?HTHJzto0@a$9Pl5@I`FtT_2u#6NeC`z7Y13#((>F6dF2v z{Hqc!jy8@j(Drw(XhG$yswmjApI&-%ffvcSL0LL+itpQ)3QNPpJF-ow+{DpZ#1J*^ zA#%)YLK#0dyJDKOAy=n$&uOC_ofe^@Sh_jmk13aw(O{RdaOLw^FMrJc_+3O^ zoP7P`KFDl^^YIM>dVc1gF)8CZ)2v2yZniMiLR%qRP5hv3^o)xhehX_&Lcz#7Do2XR ztNy*~60lSt72KvYIQl2&aO=EMkMAt0d^GigJ?22XoU1@kLAK6ycHx9Xq@HYLSa9v@q5$@r zGFwRHfgPzB0k||<-utPhviW4y1HmeDbVhq1;VG}Gs#0cy$l^vUFh{5VTr%n$uf5AR z8=VPz}LM39(kO|#DB`I&QKF~m+X+vYLbTy zWyDXE2D7XJrW}L{E!dONEgR&(1j_;Ax|W&)g`y=}O;%hDym#?-d@(;rOu~E-)%E~a z!gy$SsaZ2~?j(8tDkp(sG+|^slJ}#x9d6zg(tH`MyQNpmMCA#h<*N;XiBxmtt%!~q4sZ}7I>-dwP=SRT_(qdtE~lQh-$Wq^ zykyC~`ofozed7JV(u1ty6i>d4lI&lW4BMuZXT2351O(GO!P|%?o*PNle&l2fn_xb(-7T|0 z#3+OYu$iIs)t}F6f@D{Q+Dp3qT)urglNtWm^vSz*;%JZqu0e_W@l*VcjogCq^45yhK90Cg@*IYsK zC{VC14V(`81;GAs@Q9eq@~M@nM^3M- zmnsweLLV%4Vg089ck)bOq0kRS4%Se31AzXl+P3&X>9$;Z>``{bNWF%oT0nF;fRP4x zRexzi^YY?X_l9fiT%dVj0{_DhOSpS7@ zk^JLWLFQMjwS+=T{KhBO%F3l&{FvJK%}tD;qGX=4g|a4D>5Mr$w(j>8+smWR4!oCx zff~42$r3t7G$X%63!J-XKr!mCt%gD*1b=If&RPpW=CE&<8B7f91F5uZWZe-OeZ1%a zr;$ThxhG~&8L$rm=vo9wOi53%{TK0;RIcUxJP4UU^D4z&lu}Ot<030yHSp}!(crK~ z<;CfPE&qyLwiO=vvs~-8o!y=c)K#-hT$^ zoCSXImfSJOFISd04L_KR#*Gq)Fqa3o%dCw&r9N2QT0H1>9|WiPbbG>n;unShb8h78Lc6hs(Xvphm|K<8(Wy z{E-=Na4jjUS^mFV?E~*M@q0sn!GBdRUV$o0JU!rAJ=t~>@hUX*dhg&A5J2DmBl_>c zP}Iz6sMT_w*LobYT`7qC%O7P&jiraxS#}Vr2mBZ24Y9lpf}ZcoTld)JujO`16%v(7 zSvc4?h<`|g=`^;PiMm4YkL1E%;3zwe+OLOmp!%^*$B>dfY2EEgg695*PJi%SOlm!< zmyi(5Dnjd#uZFI*UrywQ)J|2p;f1Ysu|#!9kG*Sl7RLlfXt%^n_pwkS_?ZDXsa<%Yp_ZoNX8CEEbq6)ecMIm|x;PGOygZC< zA-KMd2%;&hY(nP3<0qu_BKt%hx8m zp=X&Ym3t)u?S+?Ni*Rnk#$2W@;EUJIs>h!cl(aJ}eg!oOIg*LPw`YeJOm=HE)F>X3EZyZi>k%*j$X+ zA#vEj&M_K~8ohpV1AerpwY;UO;*BDNGbGhKJI z90oKV|5}KT_lS+;=mh|kcMmp6or%a__d7wo4+e%JtlB7IGYbB?s(mYz)St-VEUQIR sbay!Fe}0vj79ULXSOThiA|e(hT}Wojedr( z>B*AqqL8fSIQ$qIgk6r`bpp^hT*K1K3T~FWtN7ZDXYVD96R9##Wd^1}$*ILHH6@92 z#D1SA!y8#@ghnHWSqB?BwnRVRF{VqG2m3`$Ne7y(RBY4ONPma(ELDh*7)J5e@M*o2 z$dB^^ay)2J7qmyhQgx==8kbkHQj3s?CSC+yZfh)JwkTqxM&O^P>`ZQb1E4?eXIei02soN9@&$A{)56dXdSESQ8RnYf0~fl;fg6-m_g zuQT-5^B#@ntA8A8@0T3N+1Dl^?Sq5Mz`QrvF7!w~&}M{D^eFOpd4+kFe<+vA2)m6f zK0^7ej)D7c#gdjLS~-$2T*kY=8VDq+|EVpNS26w};K3#D@A8K(DY@JU1{26d=(7NM zHmW3xPZWX8=tHSJ*^k`TL7gs-5(K+~hK+q8;M>XGihsOQS%H9WUXlx_mrh6S2f@sO z1!GzCwA0{Y!aG7h2Mn9=t~Q$rjdPXmg4_$HGvRe(b`y=n{=gDaO4#QHB#UpLh9oE` z8c~Q+F3?qIs7XBrz0XM1FG`fnjKcYv8XD0Y|noDR;Ut- zcLo)_7JsVFSqU}p$3$~h>Pk^x(WWnqMJ+cAxqr*(W4~K}n|?xNvUm@G*kdx{3mwp; zKdwcp+VD1rVk_{WU{5FP=oS_2ri3iMK11`XDThM;?@wASqA*1Yxg@BMLD&&M6@k~c^%1YPe9OS@{X&du<2 zgP*OLx+7(~!dORYF-4^`X^r!8=4ArWuL4e7TK!t--1l+O=MH`~`Ep0xQ?{RzvI$~m z4Sy>SIGFY$4`!e(sc=EMLUenqzhVNJ8GurdsQCA^Z>LG5htTr zmoRQ#Q@C^EZxU}NptDrz&!$nu`KVkV&84(fD9CeVveJh8B&H)J(wq4|45b}~j&nzL zzAV*rdPjTYnbm0c+Yb7g%^m^HrANN`7k_R?0Mr{jsf94o?;i*45bfke90^c`2s$^B zGV73k%0N10HZOykP}&)ES79TOKP>gzOHADVQc=4*yqcQ($PLH+eKmwfO(nRSSjG__LyXaa=1 zjA>-l+FA1@h~~C;G!_IuuX?N0K7X4i5Y*1j?}f{^`uwlO=cfo0N&5(1l?+2t$)3he zfy;x5O>i>#x7za^+>s-mx2Pm^A~dlLm>YZn!td>sw%VF#PQQ^_gd~b#dg+h6_JsYn zyiO9Z9>z{p%3n5%d;6$y!$bK+aXQB$RDx@id*Kjw^Hptt`{cJC%LqK?^`vH7`Y28X`ay1zK3}>q`t^H#-BN!#YobT5pBYc0_ZypBXVD;}M>G zFKeF^K@3j#`}*2>9I5`)^}BoA#D4sEI17SI@Q=Gzx@AuPkpir=fHXmmz~h>2?!Do1MPuDnuk6(kOX73UWRsSX)}$#~Ooc`WYm~Xn zp-NM<(=MeBPk(-N2uQ)P!B}qn#6|?!nEt+MI`aY8G}E&b+Vu_8C~BX5{% z7n0(NVb=AtdzJ{S}A5h3C&Yw^4Mi!x{ zfD7cF-Xo+hOFP0&j#_z;3&rkOb^s=0cbrjX+Ux?qkGFfy;EMi%%Ox^?D={+-bP5(H zfP@~~|ISRD9g^7zuZXgPBngu=W9y8Rnzlk!$aH(=P_AVjt$%#|SFT**M~>hh#*xp( zo`c_?gbAynPPz<>Yv`<+6CcLu32k{L$CX&z;~Y^%Nmkc@Z~zGVGOkfL*=iTRB0BPX zV23jbF8!JKAU#H(REA>oWgLO!8)HFN<8M#(HS)Di%)-4e0Th12Y;LgDqR87PDMX55 z^WQdmZpY35A%9!XH&7&%nIZx!UZb4yi(a3@Gd>-QWIDtzL2<%iy!8{8>E|m!{dlL_8`2IF+5;wetIZ*y zt^;BWqyc~I{od@>llCXU*N>prS2AmLgmlCKJI1c8yq^%bMyKF{iPkW%uLccra6M*0`!>^fpg1%t-Hadf+afg6!h&bY1Y2z`zNQL~e!B=oW@ zqVJYO&wXb^EHZhSNWGA5H4Lxsfh=^${auJ!&`KloSsV2^Q5e1%$=m4L?V;EejVNhI zo`2=h4lBa4c4ML*HEc+pK}*gTP{@@Iv9K?&Y<>YRYE455`xZIU&B!HIuljca^*Rvi zfDZg5fImQw=j9*!w}ES-kWMLka^1YMd@JUW1_=0@?1#)%X-nA#RL;fn&c$*xJPqmq zu1*OpQ}YpwrFNcw0f%`Ea;^b~IG8=_l7E0fI};6UAO?joBT`bNXn046$R)FB&ASsI zyrlT~N=n!;Kn3>#(s-tG%keicUeCk3oJ%TCLtf_QZBC(|(m$mM2V^$W)2p4Y-4mOZ z-L_@}IY__+lZ+iO9NAM)RlKaf3b|ACc&r<6h)02pQ2wM!jAxc)T@ziD0QlmmDt|ef zLFtrObPEQ<>(C=eT%HI`tj1hQE#S)x%=^Mu=4D?>*tDy!K>}RBF^l>>^iA1Dp|v@P zbWzG<6AHCx^fwW^ekLB4^MiHtW7-Z%i(Gm}!}y9kYycKzUi&kChqNDQHriCHCG=f_ zMpoQyQ`-(bW{|wqO3TMW378$-YJ^@n)=fY@? zKD`4j8k>b{WC>1no)})4brhTa+1kv>I3*q+)4-KzdGCFw3Esz)}!o~3!b5Fwh@bR zQ!n=3hPoFv=)Pwd%X?ihjDIC!C3AmEtmz_Y2*ZVji|VH=fUwTgb3A6$w08ts*P5{E zjVze`HGLW_2u1}h&~>R?!neov%%5}?1ABC5%IOjo;h=PF-@O?sdP?5@qNWTT~!EAL8lT^8;H1keF!z>@ zwOvfrkK$tus(CqJ!lUDcpUQ*zXFTMm1I*T2$!QiH7N-uMr0rW6hmeDLr&8E^!^;0Y zI7&ydzlRo0K>v()2r=~BR#y9m{wIrCtO04c?D=w)4E8Q@LXs zdWtEQhG@0!dw)ism@Egem2Dkb0kl>MGv&l!R{%6W*-^I2#IUSpYQluRI}BR zlU=VNCV6DA+%s0e<*J88o7?>aAU_C?Otc?IWp3VP>UgC)k&NFPj0*|&au_WQH9 zLHbkRnsA3SL2^sB;Sc{wmb*%JF%hpcMd)_bNKp*pLSU(NDA3bMsM~`t>7ks48AKAq zVxseexadtK)M*e9!-?%pUf)IWbv6I_Dw&O)$@=|mb|rx6&E>bQw?X|Ff=e+D!x7)! d?Fl;zOhR0v%*7)OO$*ben?v121Dw!c;Y=s&GG_n) diff --git a/assets/data/tool-ui/url_inspector.dat b/assets/data/tool-ui/url_inspector.dat index e00b2e3dbcafdf06d28f091e88a856d7d458b417..16efe9aca67d1aab34b0073724686b487c75045b 100644 GIT binary patch literal 2216 zcmV;Z2v_%6O-NN#RY@@d4FGj=Y+q?^b8uy2bZ>G9ukOkBJ&5MUqe9#A;I1@gHunrX z?d}~TJZ}ADtXs+kv_`)CBS7xOCkokZs~vt_LTu$umlV}V*zrcr*hA6TOhqo)JhW1U zEa7R5gxUYhnPdr5-1wrVm0Ey|e34Dgvd;o1-&<=sULZ!TUj;un2BRtk#E1yj&#KU{ zYBAk!A4dR^Dm>9b_T;F2$g`GjBlsA6+hSKQzjt{jGQ2sXxG-a;)9_-8k`HAk7@%V; zZM<0U6CV(LMS}%41aN1~CCNaJhDi4B)<*MKRc890N%M?b8~k!^ZiD6@fJ=f4DBmms z#2BwEq@Xo+Y>373v`b#8`Ve->vAeC5@v&c4m=b)_#E+OAh!(bYBn&YTXj#MS9@-z# zTx#~IBJN8BZ;e;V*ZdXnX6e^!`9FJtDYb7h_e7ZjMFHISaVg3+ma$WQI;|N{1ld^r z&_53_ylGZ*ms^v4!)01n+X2p+jZIl7JwFM;BqgOm9-)yXHaYlW|MYTdIO1iIRY$km z%h#z~f}nJ;VXoA)Zn#_$byRuJ1&zWw^XYZ;9NOA_iDDoVs5vJ1Yr4y>y$a+}E5e8d zmdt9C*on=wFE!TtVPK3Enn$^W;Dzi}>JGH~ROJpmiNGolj3HdE#^W9;VXqN0XEaW-QdNO=8T}A z2BB08Dz!>Kh~=L2JtD>!K-@X7FMk9RR<=TxqSw7amI$F>_?3>=d4eEzetT@H&uB0Q z3yYxq%nE^<@aHn~sxWco?JglLolPv&cc0}1y*r|?5zOBTC$&9vlAvaiv|+(`!e7kl zlcOAlTb^_Vyh$`>*C%93nzEFWo6K%N`Usbp{~hE)r69a`c|1$#Ou6zb9H=TRWc;WQly4qI(u6Jv>&!( zLN_8FCho82c5kh0cddHZZcu*P1m9%qGb>%`6f1iocL||Dw%yU;|3zX6DJ=aq;ESRx zi8PBC^eSFukFmqZFl{&Gc3OuDmo1Uv^4>xr4{91!~YzmnpcZKZW3}7i@8cZu$U*Wf2#4X~xCek!+}# z-B5<~DS1F}yeoxIuz5~eTwo`9sT?B!l7T$mOU7W`i}V|Mn-Ejn)L27nR8zXw=gz%4H<&HHe9s^HkV?)He6Ii`)y&<<&GkvvKN)_ zQAyY%G^qs9u6n}Qltcub`?J{dq~_{cDHE`)BafIoQL{adem%Od+0LEV$+3PPhc}X) z%q`xX1;rB?pnw-iZy0S|l_{_8z6Go{4O({OJa?ZQoziXv@GNYjy{2R@0{tn{amK+z zhWMLp_~max+XpP)fUcR)Y;w%;PRl@gm=&M zQg=>;E?M-y^LSJhMMw?MFc^M9|P*~-wu_e(po22{}{eWQxI2B{2$1h0e*yqsUv zdB?(nPfMNrfR*UPw$=;ywW)~g{o&8lab znF$%-#sk-+P0NBU<^!%A94j=#JTCU~s}`MVNX-ZlKUfady%uETn1y~Fb^63OJHCTU z-PswU7N*!0QyK9AF7f;Gcx}|;wV`C7I}W>h=de9S+6B6FUX8#UjvRqWrk03?!&(6| zkn01Tuyi_i;(|pG3Tgwy#pd8NJI+3*Ui?8#M1y8};ReND|3~CPHpTh~z8?kXI(T)J zB;Dh!*YSh@jhTfa;=;0TCFHFk+gBw8FMRO3ecxrKyv2p3VR<~30^E35`-c-!LjE&dK`bj{@D^OEO7hGxOw!vfumxV$^gdrW0@m#^1l36wJF1vQjFw;;%ui qrlTg9Whr{~h98h&kBk)HkCFqkvz=|}O}7dl0#I&}&b16+e<{a&ia}lg literal 2200 zcmV;J2xs?MO-NN#RY@@d4FGj=Y+q?^b8uy2bZ>Gl7VnNN3ymVThgZ$ii8`mqU<^5F z5()4#Ik@{QSo1Hj;Bfq4Y)Ux>`T)?Yt!o1w9BTl9sf;K?JD|* zP_K1*vpmyP8z&ce$NrEKZ%ohXIf9+lw~|%zNXQWNO@n+UsD6q7c)=8LZaYg73n@2$ zxn)7Y;@KmaeF4R`d6aqe8f*al>Uqhdq~JCU>rjt6N#NiuCYCN$MV}rXdBbSHh#3Wf2Y|(xEyAwH z(P3}nKhuP|T=*C8(*g;JS}XufU9?h4cDW!B1xON_-W*BOY|(H|7)8Tj%GVlPk;ix> zmvzpu>-z%LUF0zU+EDRkJ!_P?LRV=}qUnmcGnHBf2vKJe%835&y&zozW1g^X z#9m_8^yV$h60zf+qS4q#H#JXHTHqo^np@rX&0hkiL~x$AuE#mayO+P0?5kGmB73o< zNN_F<_OY%Q*Wx$+k=^zUU(Hn@II7b`8^4(lc2-(1l%*fwF_UWs3hjU)x?_AK)#%9$ znNShE0wj18_HR(BjqFP%QEJ}j?m)KKY;cmO&Whw!?2@g`KpGvDoro)Lt)F<2Oktas ze>^AB#~^x39@>r-fKM^O4#k!puVMHNp=Jh6;w;#RftZp&?}A$*0gfe&_`N6pxjFBr ztnx;vHL%u4(>w)0kQS*bl=>p8J*CzF&70@?uCNNvNsJhrg6;WCLBXr6ui zHV(aG>3&r&8eZ{@$t+}z420^c$bnKJ;UQf6bD1*v`-BZo0NWWh=B{uG04Y=4O(F<3 z$7-E~DFM$6c%hQ#?#+=#!QWHTg`k=-XMJ4L%lRY0k-@}d^Rw#eMbD6zET&4386aH; zZ%l=Mhre|z;d%6+zYo??43$2x&K%iy8$-jGCqI=;357)2uywy_Y&3b>x9$Q8R5)CB zk%90jjDBu-Y~|UY#%EJghfkq2onU^H2MpzvRK9)3jQDmuMhNS@lLT{0gb#_GRj+6W z+^scMEK;2pbD23gR`$n~`Xzu}$>&Q=EgGZt712_`qrqxUZnv%Ua)yaXv3fh>lxm65_-$ z&L(H-<)_R?|1`Z^G232akw`12C#kJTRCiPI%3-*n8(8ZxJkT}*vQIGhnlo8MEeZfL z-VQH!buHc2&0H9i86|`r@33%$%vPJ&8=vWJ3pUZD8@ex*tW%#6)+zL8cBoo272)bc z1lxxTYBeKd1xzNry9`dDsHYnJ-Lyg;1qn?wQ;O7X21{;-a-#SLt5fF)jnu_BMfvI| z(BMV+VcZ9-0rjcu)u_eGRZ4x@kYIj9c2xuPkAMwq(1Q~BCB2ES&JE-7>^)Gdz#8mH zw*+u9$YWr1EI*rLExvA_q~*Q70Uw4kq;Y9P!Bzd{F&Fs#yfPie%Ra^VLC2=jF-PKQ z2U8HwuMQTS;H2bO^(Q&~@1_6=I|C7PjGEf?8y2P!pJD9!>w|g*?1O@J{EdU4}>pWG?A~yBQ7-)&6-nm52*9j(h75i@flQy%T|HQB5@y a-UPd51qTF#?zrYS-%JzPvq10%T&IHP13*~- diff --git a/assets/data/tool-ui/url_redirect_trace.dat b/assets/data/tool-ui/url_redirect_trace.dat index 5fa506350841a350f2cd07f46af6a562b632b4d4..930f0814da6e552418daf1ad834760c1998a7a66 100644 GIT binary patch delta 2248 zcmV;(2sih=5zP^h9eB&&DNJ?xVk57Qg+trlRt_5jEK=d3oh8CZB zI&Co|(Iu^jD!2h)kak=!R1>rGLT(a(kUil|#)8OLa-gGnh>wXIGx|^|V4fWu$5L?J z_xR{<`q;10AzD1&Y|xg-d6}sonp_bez2Vd0yL{n1peCE65q}?_s_H@^%pemyRFkX$MC3P6e#n+f2aWXU^}E4BR! zntC17-kJVVt;dwf8P2AQ>ZpomovC$X@+Ht_wrTXJIm1iQIHD!jkCH;_Y_+w1E;aT1 z-T3xo)*2%@_(1|v4Dpy9R^<{?Eo8oIn#E~^Mg0kZD}O%?Cy?PtfrXtI#nln`#+mIC zP)n0*ciCqW_p+Z0DXYUiIwCB*E*dYT{TTBDq3aj(vL|wOW`R7_v++bJS&uKkt*mme zZh_iJ!WF}jzq6z+sFIVEDOo&gNvB4azP%Wp~B6HPp?wFuy;UAm6e! zAplskZ4?y2Tz2V|g}pklh%+(~@b{A76)FuxQqSPM?V|G8IxtBVU+?P~#&Q%av=61| z=$&u!>=Neu;$HuRRm)s;aK_y61(vJl)v+|>`u7T{$1d~|1Zf!&#=Q$1dux-j5)2&O zPw@I(IBxp@^?b_oPMy?4IV8C2-!b7@!8(oMcR;QRCbQvW%v_Vbh~>qb;7gD7BU#ge zc0W6wG@?f_cf}?5#3n7ae_IZ<$Y6I(?B}$8 zuOI!7*;J<6&n2V&N}%F_LQah zAQRhS-+k0r-tNLE8bPHXom2}%zzs6uXyBC*-gowye#b1i_ohXEN1&QRDbTjpiznGLHQ_yf=>SpV$TgH5XvCuC-42v{U7z8 z^6(h`AdLP&dKjU^$B_T5gdajGDowtmUNM(TEMnGS7H&ot1E=I0Dnj>#aqpT zj}dAdR`_)6A|<`DNy}_0?}Gjrh|_NHU)TAc?WyiZT8?hQrmSiAjxZ{A!gI{JOW{yp z-G@2QI;xSMo}T z)Q~RrhT@PGYX`|x?N44px_Ok4Z$A0CLpGJhb%qZ&DU668oGD3Efq&WQ*M=nTFo;Cf zTkRGrv|0`H^n@=Q3<4*Wdp7(>LzC1`7;CV}V|#Gj)F{ZpVFmum{>kBNMxQ55S{=;A zM#R8dP9V6DX|W(n%!=Vkyg-@LxQjZYj6jxj{ds>ezi^|7AOqstj!Xc-cbM!izY*8@ zx1{~i(EeONWH*>^C4U~K;RNfobD|LKs{tJ8PJR4G3pWjHxvYuD=$ZFR1KvY~h%em$ zB>aA5z9n@N(Y6MfepcG)qQU4Gm*V)JkTM}k?_fcza0+zAXvkV_83{eC{-_)BH)*%6(3iN@qdEsYf`N}*(rL#G_b7z zKq=7f1?OoDGh-_^#_k1Dk$8zyUi39h&iC=tM{{Qo4WrR?Z3*1sAu#eJcCHxlj$$WD zAR1p+b~iF=C4F0X3?qt?S^jqp^e8y^ZWIWw3DfAkaAqujNLi27LQVpN`tJb->R&;m zA0i@)hXE@A3V$Q_zplACYavmit|9bk#-}4>{$}I4o4c)rW;XVTMRhn7?7#bb?|LT- zar693=rkos;fvm~q?iRsHub?Isa!(*#O4)f(Q`pmIEw3AgxS@jAOOcGGgX7uhos(r ziB7zMAuj4QBg8YfOp(+qwG0hR!-X$0TuIVfL^qb*%TbhYdw}B}N+o?mGtgejq?nav9D6iKRPxk?;Mar3%VUJ z1<5JONOqt_!3|nF1%W_@E9zq`dhM;LBMsw}b!?fq0@=@wjnzXd WweOFZvO!o5SVdQ%QCt_K52YA$Y*h^a delta 2232 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 G%ho@x14Zrt diff --git a/assets/data/tool-ui/uuid_generator.dat b/assets/data/tool-ui/uuid_generator.dat index 93a9c46eb05179ff3615a1bf2d4646c7bfe7669a..a34c6c3a589552cd0bac80a372b058be70f90b48 100644 GIT binary patch delta 2087 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 Rg+~9n1=%GHJMK8eiIE^>_2bX?}2 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 UIfJXbgWhx1r+ud}%Yk^S@j{yTAOHXW delta 2038 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 YZa~8wB<9`((B#J`rWufktM%}+aN<=TDF6Tf literal 2130 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 delta 2119 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 PJ}x)#4ZDm^$rte{22j&s delta 1409 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 G_{WWb%tMF( diff --git a/assets/data/tool-ui/xml_formatter.dat b/assets/data/tool-ui/xml_formatter.dat index 91d0e092632f16f6430a734d98719cb6d03924e3..820788c0f7dde2252009bc39f3bcfd10e936c92a 100644 GIT binary patch delta 2087 zcmV+?2-x??5XcaaIDd*D5#SqlTp|t|sV$FnV|e?5IA!tC)9{* z?DjCf!_v3d5(#iytov1|uIt0qkZXM@@Bd85+5p|sHbG%-z?yo%+N&kHe!y2lH5pKM z;yf-6iSK&$MMvOXEcu=D+zAN!@CQ3NECoMWP%YkwGz?cuzn*Jc3t=DImYhzsZ+vDAcf@+hw2@B#@4Z zc2$L@;p+N!a*_hXma}%#HW8r1!e2#(A4iP7UjAp_ToHF^2O_`>$N82{ZUp$#jA6he z3Y@bWB!Bg3Wk17sc1MDN18UCACyooJ#YGs~cN-;dc6)+rDAhpq;64A8`KxhN%T;WJ zr!nqU>jwQx za;sSV#RIq%bn?VrfMuqn8#?I3t#D$l8=T$NK`o;!Ru_P9x^Ub-KT{Y(rhx@TGf0;% zaTWf@()Pqt9jY524o!XYTnsGUCJUq5J1zju7(nz#zoudLG|7X$=YQv&pa&R>$6IAP z-hYjL;Fa^#cA)3_RQ>)u^&xGMZRM`y2fJMpl9wFbb{D+n&t{AgH@;|mE;-)>jwX`- zc8a1_M4_cg+vPk~JiwLMUQRRv(MJ1u!SQVZ<0-2yB)WlWD8k${Z>*y%_v!~Ao3-au zzp{|Y$lDgSmoeeUhO~@pk`m6W$avlNu76pIyP>D1L|egsZs;R0NQHgp+n-M6Z}`;y z+pzIoOUJ{U($z446vrr9!klbnLIzWwl7|rzvy8$!Ed>ngI^UzbtL&FmdydAwOi3nj zaQa)5vj1WIGl>>UC1qsyY0usCal09kE)J{Q6A6yfBgh?s2wU;TgyXFpseHB0X@41x zU;G6J=7Y)spuzBQ+`<;Sg;5b30`PBD^EjnUvdNKQ$+=kIp4sDGZ||auKfh+&nv8)x zfjA9d$S5B;A|bVJPtG}(Wg|u-mlJk74BVtYzJjmRp{)YL8_DHni{36{<|P4}%H=5W zb(UBXuo*5X!Q>D@u*12}BuS%2cHZ&agK2&S=d=dI)oH^6<-%K#@JPv16ncv+%g zL2!kO*N^_q>`d=C^Z-tL$RqKCfq~NxkN+TsBRF(8b5*Ey95sl+C%TO6tS2S+iZ9f;r3h<|LR>Yv&P#@ggt z>(*d>V}=T4g{`S~Ed4E(M}#HvQsqEn!Re?=yoP?yfT1cTP7i|uKz9fW)Yc-IGDcIv zXeGAX^1kOWXRt$*XkB+~g4v9C{Kr7G`yjJ1Y#`ID;Ow;!-x3A7{_hhAw^J@}S{!L& zunN4Puczc*p zGCmcX#P|1d0iowcvw80v@X?xbFmryuTqCm4we`jyHGp z(z{KiIx~ts?px2aZQXd&56;8hHqn#KoU?JfPp5!x zo|mp&vy%7uvWY}B@44x4{V+^I>Q@O;tVJvV8g6qR%@htEcDmsQ3q*jnrWALN+h;D_ zd^L)_jCfqOEz6sGfNi^UQe`FGiW)90MQh+Tu|zvR8Rn1++BgeR1bU`NKQbiM%yH#0oMa~P)nj|Nm|d|K?``Z+5<(Ar6_W@u zJi->Pip;YQ&T)5lc^j!9+9nOu86B9W0&EL#sV>|+1s@`XJEqSz;eQC2@E)${K#dC2 zcqEt=Lrky1EPogDaN|(yz;(x&P=!Ar)|9rq>5FbZpcUA{;Xmn@&Dgq#@oVJr^MlMY zKi^!Ruda&>w1FYqTb>IAwDa!#r-as*OK}ziC(B(zRI-j=BdX?(McB)+qvM}6 zGiNCT$?iTmGgDe6bt3@n_h$tm~DQf zGfLj;kz0*MTMiu9?&rkzd?PnmtgH`Ty`?nvTg-TRo{PtOXK&XdK@_G|&pKsrPuf zX);fVeSa&(u&vV_&q2|+%vnnxw9E!EOm5d`%}&S(^KB6jA^{>6<6-x{ckK!cZLAWm zju#}mXQ`nBoRzcHT;hb8Skb=Pxm)TUHH({;Dbwa)&!q~`KZzE%vAl!b=_jkW@(Wk6 z9i&e=4Td4cw&RJ~Pw!-GS*3lz4fzRMJzYV=X@8_A43YmJ-fvLIn#&v&B>Yjpr~LYu zCE<9X2opiCSix%W+yqh)?jarH``E%lRaSp!m3`vOE8yOd(b%PG?xfZcWlN8a63p2V z=9Cwrzo07fYa=T6(g7qORc?L8NF?33iMAn7%?2!bCJMRftgz*TUZ?y*PUQ(MWYXgJ z+<&_1@A$b;6e}NIhT%0=Z#v$g5>;^kd;b#t3vcw5U0tAYJFH#K7H6U97WTT&*tI>6 zq7k!?E?dZ?Xb=&~0QBO_gIA=ji|sU4O>GBRJGOm^lG*u!$YR9T4@V5`*k;NH@Ll@9$k5!-?42prY!VQ-Z=)y+2O1*(;tPS?01U zJRS(^bN>JRni(nW(J*@Tdl~7qFQ1jM6jxJ$v^0wl=Cggs4E(_vds6X1>=bWH+kc9- zKnp%;HC7PSb8r2V{IT&C(!*=L`PA*t-LKPM%-5po7{jGTGk~}PwiS=vu{UZuwbT)Y zFV5SB*g4KoEvjN@gx`dA4wv%U=_n5h1dcGVXqQ0^yT6m%S%3bmrUGg%w05_|@`9hN zAtc158=|odX;kEyesYY;XO1FyzJEH8lTLnKFOT%9J5~XdnjWmSy%*U*sJ1dxW6052 zn|#87A-bmq=vH?UgUD2-9o*2fEb=)yFG=tOMCzg8$x|bPVmBpO(Xr{+E8@CTOo~%& zo#M4|u2zF}{M7^>HZbO@))zhRMXT|AaD?6@~=+73EofMY=o2GwxpmOeg5(uyPJHV^QtAT{qqqvZ1SEyXw>PO zMOwsjOWIMrox%`UoTdNW&g=5`Q0EBrcjzH^^4v50pEE0(JefrhiAX|iy(R%_-To&z ztdCr*w;gw#&aC1MK7~p7UVq6c)EyJox(PhJy<;vM93Vp~?97%W&&26Ty)<2t)!r7X z+QQ|36mEe~MrStya+zn|>e$FRBVW%b2@!CESH#}7#XZL*hu!_-J;fw0E8^PJkdke& z8AB5eIMjy@pSkQd-tjjalJW?ZIP3&i>YB07C*}jSu(Y3PlkcZFj|%~qOr&eg{fi>rtSs;c0xEC%`YJI`eR3+{S^4NgD*JY zr+Hs^Xc_^G_;05NO@EblsRcJTj>DTirrh_FLzCWU_l*A-?kQ%(Btm)IzJJ7rvwd3_ z&nAQq%z?&wQMEZOKxX{13GySD8!{vO`r zi5UvA?r~C=BM7aP@3=q$GBZ_IEho+yKMu-2^B!8;{Lokzcz*`69zxhQqbajcqZVM_D)fDk^)s?OjTb|;{PVTMyo zbQiQwkdR-CFUk|1Z1LR%DMr66_U;9_zvpJpW~SewdT>6FbmLFs43~B=jlp%-WnC4k zJc(n;x|Tbi4Sz@2C%O^ecIP!6azh^Z0&PK-f@65nmenQ?mr$_At6+qS_DBezG?-QCx**wBbIYzb~0b64(F5ilCUfL<(vcJ|@%n|4j;bF=PU z-ghKjUaSi2$C7{_!y`<|KKXVmbGfkk;yr2Q;H7^Lf*=jnILkH5HiAv<#e5h|cLPo? RE(G`orB?=t>%;Zm5*L~u5zGJp diff --git a/assets/data/tool-ui/yaml_json_converter.dat b/assets/data/tool-ui/yaml_json_converter.dat index f647fff2783597fdbb9580080af307e1c38e817f..047f073ebc5176ceeef03633617c5aecbe04f910 100644 GIT binary patch delta 2119 zcmV-N2)Os|5bh9=K7WG^K=~+oWEj;Tj|I-#Se5mFL3M8@T=D3&(8cp=Xjzsm-vZo| ztP{-e=i*a4R~6Sx=05boHVjgN4#5~XmjHBMv@9iZR*1))EvQvAson>2Vvkw$c-gkm zF(fOI^$=ftc8$g|`=Wf@05+RW6dkbdGY1?PP4cExt&!_7cz+`S>9#@C8@)*0g%PiK zKS6ffB70(6VY~TerS;Q{56Xw`$=zXWGHjeP2e+#iO}R1n^gagK#Y2F<=otAC@f-cR zJ||rM02(tmvQ($-Kz~WAxrfSrSyn8o?Vtl~t&(tUE6dlPm3GBse#J^%QGo^(jC$(s z#aO*eHAT;_BY&jVpU5b{mytL)VWPs!a}5WzaTV+UO-;V0=zBPGGBgGrOq$sDtVI%G zL6Gqv6~|ScexATDY3L$W=)t@ea$~5@*dvFB@xoYOx)|jPiAcMHh zc4PI~Whr@;K6_mGYW1B-yPaaHXkXt^mjQ%-pUlDDqBs**mCWL&@+JFFvKSk}=;!{w zf2*1(h+^=KAz2P>S}E(5r^}yZWDO)dhj1 zf3gnRM1LaC44!UwY(D<@8#9;N9H@tAs*yr10`+zAU4bsmK@>%W-40!LU`N3#Sfmg2 z$+=+Ht#B(qrRcIX9==R0uj+l!s7Oozt4)oGUazKkyjqLm#|^?u&&x0I-a@r{%@R_b zF(D6(7GE8<{p9&ZI5j8!eUK8*d1tMqcaW2?zs+vS^l zzm@sxY)`h}8Ft*0W@3Nb*YHW56tt^ukUIjqaW_9NX|;}Jqfg_lk@o#7oi3k4zjlqB z4u3t2#b$~^KL3&n;|olyBb21ThR_w{Wy8-PE9i>}*^%?wM8AH?9HqufIg^g? zm;{$g{B#IY=Fe$`TfVpgxl>3uyS_*}7Hdt{9u}l~duee601XQ`bERo3L7$seOFqu6 zpxlRSlJpc9R*ZFRu@S+;W$GI7zTJv`ycE`c}BGe&P04Ic5m zcN@eJMeOnfzN$_OMNG2R^q!#3nH2HSHZv-h17A(~cD>i4(r%?o8x6x16@3Vby?@)? zRB&y3A<4pTRVpDsgIWhLZKys(4~JFzb(upN-tMa4Kdia%_eR_@_E2T(<|)hQ)xKAu zg?PK^L{7U=tpbGAxCCYf_EqgpI!0mkujFwDc0zmd6styD^TnOTD=tx+2|r!Gw(4r; zrmo!;PzQ84aPkKk^Fv}^d|`sy%zw=I!k;&HJ$CEJaI6DF!`)`#Op@YhGhX#1`h;Em z5u3?~m%$@nKfIkTDn#Y~jIw>2eM7EWdk=}}T{-lMSpd+}8Kcv5hYn*O4L)Kt6(# z{)2zMW$BzAR$o4$KHEPkl$T2=kuGt{LpbWxzsA{i zjXhhkn$K3vYT2W)U!d049JG&Y15UYEcHeMZPNAhO>=u8V%< zb{vfR&<2>P>2dzR4S(S|L8^BWEJef3Qv`0a!E#qZZhXWd5+L9eY<|l9nZWCd?x-e4 z)PC4dG|-|p++K}|@B5p7mc#FopL7)Iu1Q{6v?$>Z%6_XAJ#smUkbhihZ#<*0xo}qPVrDmWs9pm%Zwy~9pSLd^sM^IXGDCr}Sbrjd3Z(}W;ea@z7aE!8 zFm~(>~2Ha?U2p zrnehtP_3;2Q~TvEKgD|%2r695Aex!^nW7i`NL`YM>TU;c#sS$t0o}W>|7vzAjGE6k zpjEu<*m(kiUVkf_Og$(x8HbTB8?9_ee1qOhdBz$w&h#{#7`vxwOMr;G`Q(H$+Yi-o zs6OkhQG}7_n)1xZ%Gufsft4Ip5_EGjq*<>;6i5!7sgM0E_B6WkQI!Lu45&afP zT8K!^$mg;ed-@4RcFK;|u?>gHM~qqMI74aa8He?=Xd3gi-vc@%-g;;TGhmQmHry_B^PEtN{k2-u0DH zz;r|-x~F?LMSu5@e2$9)gP0&uBwFkeahco?JlSK`Lix$hZ))2K&fs>bkbjvGFn!^0kujzDF7Kt2(aL)88z$G|XL?Idp6 zyXI5*u|y$n(tWbUSxA#VZTZAZ`2;zh4&AJgtc=BpN(M0PC5P4=yu=s|*)+&u0X^So zD3>}YuN@hxxjKqHi~vnqp#R^d*rRu4IYpcuxqr4qfdMoKb61)*)~^H;8DWZiIC|z_ zV%aTemp4P!SgdOiPCn~+lJ9}PdT8e|KZ6{N&@0ZDXrz|#iu5*C!DdQ~CjFz`Qg;|i z#I%yek_uvE+*wOPzp_a|4rXv-IxNP|&R4@{{O*T66hT=S_8Oy@w+r+%oJ3ZuOXH6z zUw88GL+^YDm#z2rL^ho1s|{5R`Ita~ zZT{(={e|}wz7(Y(%C?BRb3a%z&3)E#H= zAlfBsvhv9a5-wIlh+Lktby_zeG6D^pnLAld}q6G2bl-?gRhFSOH2 z*{8N0?5;(Lw;UUqgisE@(zSx((&symL%vR&HBAc#QrT&Ce$DZVA5Fk`GK!;VLCBd+ zFseg=#>El=DT^?HBDl5K*{wsR7j+t<-qO}OEgRuHK^h&(q5MyGKzg_x$C$04S${3N z&C#`4#~(G>ORJ>VnDnqu-|YfN3|1IB0WlO7I8?{N`t6O$CUU16cD9lnFL%<(iSi}7 zM&Wk2DJar+V|Cz*GDX-``GN~ zHL_1s5sV>HVH>0M+mU^}NHs*UM{dqPz@N-@-Jp2FEHVeZSq#lGXC(F-)L(% z6_;%oB|j;=*AOg?c7&Nc;0b!5P959j9(Mx;?7JkD)AZ^(YpcH~6`5$PXm9Ui<+xM{ zg#{pyC&t4jH{uG&f&t&ZJ>_ad2V*gvQe+p6dkP^#Gpb>R{T8 zEi}RCq)~V8dIWeRi`)FEe6(whQ0O@ZN)aeqCZB$;t>LYO92OQvUVyn*^-82_Zy{ig z)~)q@*ET5EV49dJO@G>8k^I00=KFC*q7Q3C6?GdXihr)7ba&oNQ|w7$4)W(ItN7be z4QS)+dZeoVetOpoAwXyHi2}vK1IJkHRi|50Ag>xRU5lT=jNNp>G0wywM^JuZ(0w$xmB?^fizD$blivx{ z70`yvPj9X&8g9)2o3k6ovow=?WG~T54${V0L_-yqmiwx++mKD43~?tYe)}i%mfUUJ zxDDdjyz!X7Zhv5Q6Bzh=#(R3>{LLNPG=%sDONriDLN?w^2Td85tkJePfD+h1Lk8|_ ziOA=x(q~MnWr>r6yBrk-K77d4!NoVm${Y&x2oM(O$y^B_-_{cWo#3hMkKGS85uf&g zMc)dsSUJqW&SCamK23(|tvh0U6}*Zxyj2k(Fy15PKtR3uEkp(4FrSX20`6DE#{SQi8#Q|EKasE;dENkICV*zs-=}?hvn;*d z$E31}tb`KTyEdq6Vp+C?^Jx%(cRi@N$^Ylg6~T`9b~B93)PG&SPgA0xTF)FXDfhRy zvVv$0ASC9=kIz)fHA(gzQo5fec;)|`;qAJ?8$^~iFD38>y^XwAUeo#q%1062;l{HqIAOJ~toU{WFtff)yS*|qh#`73rvObshIl)r)9wbo z=zf`*t~3hYfr;2>f!A-+qD^-ASp}i4cM{w&#Yq`y;(ubz@3fBeuVpl%AWVH^MfNu- zshh${7g+cYFV|Zu>Bfu_CKQqxX`fXAeks@`MUZ)`>EbT!YtM^9LkNoBn_HdSdjd;$ zUT8?{`0I70YG*vucvShP+c)jC(#sxY{l137%K{=RsLyXw@MRNzxCy;`R|izzfZBDe z7k0W8C4b?2naerO|k{ad+?bq zN=1XXV*JC-K&v&ixhUbHMG@5JljXa$V>UJ8MSqcJ;Af0#xZj=jUxQHb)T}*T z73Ni5jj}DZ-bo+G#wInuKKDM6fXw*jY& zKFFfa2as59Bp`XJzZj>G%ic6O|3<(~yB?H*DE9k2*yOd^MaiX>#)w+hujA<0U$Pnd zg0QM8DEIH&0{sC~qEpxA{zI)(lo)qo?|%i;lPIxtu;psu0Y$U*Jgmm8EhP*$I7au7VNnQH*KUi1P`!U!@F8jOYwmswsQ~QVH`kW*{-6a`oo41Yk%2%8i2qN zw9uGoe*QY{6TZ^UfB=w(=C*@yFVTwF<4IxY1fAlp;E=I$ZixYMC4V{QAy!+7;&_oU z@L>urs1avUSb}s4m99$Iebfen_!-_Q}9aipa1@ zq0%}R^{O@U=q*#$YiuW3=YK@I)8t~rl4<7IRyPaH-}Dt*2dr%VvMvxr!iIQt67GEG zs~BmhEQm-!;D2pgpaj(#dd4X={8)gOBk@EF&=%$|C|E%|MV}tPUJYESoeyz_I0R$z zJ<^5!!pGnpDi0@Yo7|P=?Y6r}Y9AD)^08>%h?Nu-6Z;p?%!nQ*l7HdG(AqFKrz#Z} zp+nq72r=y0cSyc@9u_=_B47N{}e@N(7)5e#Cb5<+L_ zKn9MkqAMtjFXzlWgoBr^*)@mw4)q*hhjHve{Y90Nois0qhGJ>l``%es;Ze#f4uTlV z=>I7FFw*@qdXP%5_J8JFEi+m{f2Z)m>v-7FvgWe=92OXYnEauxP2fDrDj14#!v%p- z0w7{WtcHXdv(?@jwQRv{y69xpmMuUWQ12x<`l`$6X#D?bj_SKP!$KcCv14cJ=W<=g zDTXbBVI_`=s(s;zJQIIhsBrK)@?mrZ-#sba=gN(!NO$({yMLT@EHi~t3v<^Q-roiE z3SL6dHxv6C@g-bTQ56!iKPV>OKyXD0oNGyT(xQxDY3A9lGIx@%y@;k_!o8?Ij;9o1 z9q4Gy6cYo2>ir)_07KWP!m%W6>|k0r{71*^Zj`8bnV1+Px^+;?tCFA0EoIpTn#k&r zn&P_%T~u?x34e~}sa5EUg5t!KzE=Yx!uG}6IVq6K0*ja)){<}iE@r;rP-Btfa*o0o z6s)#uv`<~djUZe+>Mej7FcCypaa-kD#I4S}ti=i;GEEq(t~O+7RbRGL30zVOx1o2? z0Rb@DVv(gA?MFic&Ms6jzMt31J2vz%TP~l`KU;^SO&};64}W%ztX_@$_=)*X7Nrk` R_>fybC$LN4^wj+$gH$@V9sB?Q delta 2087 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 T00SCe1&xgA|B%qgcCoc{5231$ delta 1361 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