From d202f2ceec0edf6c6d5740569a1fc1a637177ca1 Mon Sep 17 00:00:00 2001 From: JianFeeeee Date: Fri, 18 Sep 2026 12:01:33 +0800 Subject: [PATCH] =?UTF-8?q?feat(ohos):=20screensue=20=E6=94=B9=E7=94=A8=20?= =?UTF-8?q?Web=20=E7=BB=84=E4=BB=B6=E6=B8=B2=E6=9F=93=20HTML=EF=BC=88RichT?= =?UTF-8?q?ext=20=E6=92=91=E4=B8=8D=E4=BD=8F=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 用户实测截图:推送内容把整段 HTML 源码当字符串显示(含 ' + + fragment + ''; + return base64Utf8(wrapped); +} + +/** 内容是否已是完整 HTML 文档(有 或 ),不必再包壳。 */ +function hasHtmlShell(s: string): boolean { + const head: string = s.substring(0, 400).toLowerCase(); + return head.indexOf('= 0 || head.indexOf('= 0; +} + +/** + * UTF-8 字符串 → base64。 + * + * 不能把 UTF-16 码元直接交给 Base64Helper:那样中文会变成乱码。 + * 这里手写 UTF-8 字节序列(按码点,含代理对合成)后再编码。 + */ +export function base64Utf8(s: string): string { + const bytes: number[] = []; + for (let i = 0; i < s.length; i++) { + let code: number = s.charCodeAt(i); + // 代理对(emoji 等)合成成一个码点。 + if (code >= 0xD800 && code <= 0xDBFF && i + 1 < s.length) { + const next: number = s.charCodeAt(i + 1); + if (next >= 0xDC00 && next <= 0xDFFF) { + code = ((code - 0xD800) << 10) + (next - 0xDC00) + 0x10000; + i++; + } + } + if (code < 0x80) { + bytes.push(code); + } else if (code < 0x800) { + bytes.push(0xC0 | (code >> 6), 0x80 | (code & 0x3F)); + } else if (code < 0x10000) { + bytes.push(0xE0 | (code >> 12), 0x80 | ((code >> 6) & 0x3F), 0x80 | (code & 0x3F)); + } else { + bytes.push(0xF0 | (code >> 18), 0x80 | ((code >> 12) & 0x3F), + 0x80 | ((code >> 6) & 0x3F), 0x80 | (code & 0x3F)); + } + } + const helper: util.Base64Helper = new util.Base64Helper(); + return helper.encodeToStringSync(new Uint8Array(bytes)); +} diff --git a/cmd/ohos/HomeAgent/entry/src/main/ets/components/ScreensuePage.ets b/cmd/ohos/HomeAgent/entry/src/main/ets/components/ScreensuePage.ets index 45f9d9b..893fe6a 100644 --- a/cmd/ohos/HomeAgent/entry/src/main/ets/components/ScreensuePage.ets +++ b/cmd/ohos/HomeAgent/entry/src/main/ets/components/ScreensuePage.ets @@ -2,7 +2,8 @@ import { ThemePalette, DARK_PALETTE, LIGHT_PALETTE, ANIM_NORMAL } from '../commo import { GradientBackground } from './GradientBackground'; import { PageTopBar } from './PageTopBar'; import { MotionBase } from './MotionBase'; -import { looksLikeHtml, screensueHtml } from '../common/BridgeCaps'; +import { looksLikeHtml, screensueWebData } from '../common/ScreensueHtml'; +import { webview } from '@kit.ArkWeb'; /** * agent 主动推送的前台内容页。 @@ -10,9 +11,15 @@ import { looksLikeHtml, screensueHtml } from '../common/BridgeCaps'; * 调用方负责决定页面宽度:窄屏占满窗口,宽屏只占右侧内容栏, * 从而让左侧一级页面和主导航保持可见、可操作。 * - * 内容可能是纯文本,也可能是 HTML(服务端两侧协议都允许,见 BridgeCaps 的 - * screensueHtml)。HTML 用 RichText 渲染:它只解析 HTML 子集、无脚本、无网络, - * 对 agent 下发的远端内容比 Web 组件安全(Web 默认带 JS 与网络能力)。 + * 内容可能是纯文本,也可能是 HTML(服务端两侧协议都允许,见 ScreensueHtml)。 + * + * HTML 走 **Web 组件**(用户明确要求):agent 推的常是完整文档 —— 带