用一鍵套用)
web-to-app 配置模板將 WebViewConfig 通用配置存為命名快照并跨應(yīng)用一鍵套用在 web-to-appWebToApp中每個(gè)應(yīng)用都擁有一份獨(dú)立的通用配置WebViewConfig涵蓋瀏覽器行為、界面、網(wǎng)絡(luò)、隱私、工具欄等設(shè)置。當(dāng)你為一套瀏覽器環(huán)境反復(fù)調(diào)參后往往不希望為每個(gè)新應(yīng)用重新配置一遍——配置模板Config Templates功能正是為此設(shè)計(jì)把整套通用配置保存為命名快照之后任何應(yīng)用一鍵套用。讀完本文你將理解模板的快照邊界、UI 操作路徑、底層存儲(chǔ)實(shí)現(xiàn)ConfigTemplateStore.kt、Agent 工具接口以及測試對(duì)該機(jī)制的驗(yàn)證。模板是什么WebViewConfig 的完整快照模板是通用配置WebViewConfig的完整快照——即編輯通用配置編輯器里的全部設(shè)置JavaScript 開關(guān)、DOM Storage、緩存、User-Agent、桌面模式、縮放、刷新、全屏行為、下載、瀏覽器工具欄各按鈕、狀態(tài)欄樣式、長按菜單等。這一點(diǎn)可以從WebViewConfig的數(shù)據(jù)類定義得到印證它定義在 WebApp.kt 中是一個(gè)帶大量默認(rèn)值的data class字段從javaScriptEnabled、domStorageEnabled一直延伸到狀態(tài)欄、方向、注入腳本injectScripts等模板保存的就是這個(gè)對(duì)象的完整拷貝而非個(gè)別字段的差異。套用模板是整體替換而不是局部合并目標(biāo)應(yīng)用的WebViewConfig會(huì)被快照整體覆蓋結(jié)果與保存時(shí)完全一致不會(huì)出現(xiàn)新舊值混雜。Agent 工具的描述字符串中也明確寫了這一點(diǎn)Applying a template ... replacing its whole WebViewConfig with the template snapshot (a template is a full snapshot, never a partial merge). —— ConfigTemplateTools.kt邊界說明應(yīng)用類型相關(guān)設(shè)置入口文件、端口、依賴和 APK 導(dǎo)出設(shè)置不屬于模板。模板快照的載體是一個(gè)專門的輕量數(shù)據(jù)類data class ConfigTemplate( val name: String, val createdAt: Long, val webViewConfig: WebViewConfig )—— 定義于 ConfigTemplateStore.kt每條模板由名稱、創(chuàng)建時(shí)間戳和完整配置三部分組成。使用方法保存、套用與管理入口位于編輯通用配置編輯器頂欄的配置模板按鈕書庫圖標(biāo)Icons.Outlined.LibraryAddCheck。該按鈕的 Composable 實(shí)現(xiàn)是 ConfigTemplateMenuButton.kt它被掛載在通用配置編輯器的固定頂欄中而非滾動(dòng)配置列表內(nèi)因?yàn)樗饔糜谡菖渲?。保存為模板點(diǎn)擊頂欄按鈕后下拉菜單第一項(xiàng)為保存為模板輸入模板名稱長度1–40 字符輸入框?qū)崟r(shí)顯示n/40計(jì)數(shù)超過 40 字符無法繼續(xù)輸入若名稱與已有模板重名忽略大小寫輸入框下方會(huì)顯示覆蓋提示保存即覆蓋舊快照保存成功后編輯器以 Snackbar 提示已保存。對(duì)應(yīng)源碼中保存對(duì)話框直接調(diào)用ConfigTemplateStore.save(context, trimmed, config)見 ConfigTemplateMenuButton.kt。套用模板兩種入口下拉菜單已保存的模板按名稱不區(qū)分大小寫排序直接列在菜單中點(diǎn)擊即把當(dāng)前應(yīng)用的通用配置整體替換為該快照并提示已套用 xxx管理對(duì)話框點(diǎn)擊卡片中的模板名同樣觸發(fā)套用。從源碼結(jié)構(gòu)看套用的 UI 實(shí)現(xiàn)是回調(diào)onApplyConfig(template.webViewConfig)ConfigTemplateMenuButton.kt將快照作為新配置裝載回編輯器改動(dòng)與手動(dòng)編輯一樣落在編輯器里確認(rèn)無誤后照常保存即可。管理模板下拉菜單底部的管理模板打開一個(gè)對(duì)話框以卡片列表展示所有模板名稱 x 天前式相對(duì)創(chuàng)建時(shí)間每張卡片提供點(diǎn)擊卡片套用該模板重命名彈出輸入框同樣受 40 字符上限約束若新名與另一個(gè)已存在模板重名忽略大小寫重命名會(huì)被拒絕并顯示錯(cuò)誤提示刪除紅色刪除圖標(biāo)點(diǎn)擊即移除。存儲(chǔ)實(shí)現(xiàn)config_templates.json模板保存在本地app 存儲(chǔ)目錄context.filesDir中的config_templates.json應(yīng)用升級(jí)不會(huì)丟失。實(shí)現(xiàn)上有一個(gè)值得注意的設(shè)計(jì)決策——它刻意沒有做成 Room 實(shí)體而是 schema-free 的純 JSON 文件。源碼注釋解釋了原因隨著WebViewConfig持續(xù)演進(jìn)字段不斷增加用 Gson 直接序列化整個(gè)列表可以免去數(shù)據(jù)庫遷移成本見 ConfigTemplateStore.kt 的類注釋。關(guān)鍵行為均可在 ConfigTemplateStore.kt 中逐一對(duì)照行為規(guī)則名稱校驗(yàn)去除首尾空白后空名或超過MAX_NAME_LENGTH 40字符直接返回false拒絕同名覆蓋save按忽略大小寫匹配過濾后追加新快照即同名再次保存會(huì)覆蓋舊值查找/刪除/重命名全部按trim()ignoreCase匹配未命中時(shí)返回false而不拋異常重命名沖突新名若與其他模板重名忽略大小寫rename返回false列表排序按名稱小寫排序返回容錯(cuò)降級(jí)文件不存在或 JSON 損壞時(shí)list通過runCatching { ... }.getOrDefault(emptyList())降級(jí)為空列表而不是崩潰寫入采用整文件覆蓋private fun write(context: Context, templates: ListConfigTemplate): Boolean runCatching { storeFile(context).writeText(Converters.gson.toJson(templates)) true }.getOrDefault(false)測試驗(yàn)證ConfigTemplateStoreTest單元測試 ConfigTemplateStoreTest.kt 基于 Robolectricsdk 33對(duì)上述每一條規(guī)則都有對(duì)應(yīng)斷言可作為行為契約參考保存后列出與讀取保存WebViewConfig(zoomEnabled false, toolbarShowConsole false)后get能按忽略大小寫的名稱如my setup匹配My Setup取回且兩個(gè)字段值與快照一致測試同名忽略大小寫覆蓋先存BasezoomEnabled true再存BASEzoomEnabled false列表只剩一條且值是新值測試非法名稱拒絕純空白名與 41 字符名均保存失敗測試刪除/重命名的忽略大小寫與未命中報(bào)告刪除不存在的模板返回false重命名到已存在名稱被拒絕測試損壞文件降級(jí)向config_templates.json寫入{not json后list返回空列表而非拋出異常測試。Agent 工具程序化管理模板應(yīng)用內(nèi) Agent 也可以管理模板四個(gè)內(nèi)置工具定義在 ConfigTemplateTools.kt 中由 ToolRegistryFactory.kt 注冊工具參數(shù)只讀行為ListConfigTemplates無是返回所有模板的名稱與創(chuàng)建時(shí)間yyyy-MM-dd HH:mm格式SaveConfigTemplatename1–40 字符、appId否以指定應(yīng)用的當(dāng)前WebViewConfig保存為命名快照同名忽略大小寫覆蓋ApplyConfigTemplatename、appId否用快照整體替換目標(biāo)應(yīng)用的WebViewConfigapp.copy(webViewConfig template.webViewConfig)后寫回?cái)?shù)據(jù)庫DeleteConfigTemplatename否按名稱刪除模板不存在時(shí)報(bào)錯(cuò)與 UI 入口不同Agent 工具以appId定位目標(biāo)應(yīng)用可先用ListApps/GetApp查詢且保存時(shí)直接讀取數(shù)據(jù)庫中該應(yīng)用的webViewConfig字段做快照。小結(jié)配置模板的機(jī)制可以歸納為三條快照語義模板 WebViewConfig完整拷貝套用即整體替換不合并、不含類型相關(guān)設(shè)置與 APK 導(dǎo)出設(shè)置輕量存儲(chǔ)單文件config_templates.jsonGson 序列化schema-free 設(shè)計(jì)讓W(xué)ebViewConfig新增字段時(shí)無需數(shù)據(jù)遷移損壞時(shí)降級(jí)為空列表雙入口一致編輯器頂欄 UIConfigTemplateMenuButton.kt與 Agent 工具ConfigTemplateTools.kt都收斂到同一份 ConfigTemplateStore 實(shí)現(xiàn)名稱規(guī)則1–40 字符、忽略大小寫、重名覆蓋在兩個(gè)入口保持一致并由單元測試完整約束。創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考