dsh-mobile-plugin 0.5.28 → 0.5.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (350) hide show
  1. package/extensions/catalog.json +10 -1
  2. package/extensions/magpie/agentcompact.js +104 -0
  3. package/extensions/magpie/app.css +4902 -0
  4. package/extensions/magpie/app.js +24474 -0
  5. package/extensions/magpie/autobackup.js +185 -0
  6. package/extensions/magpie/autoresetown.js +151 -0
  7. package/extensions/magpie/balfound.js +38 -0
  8. package/extensions/magpie/boot.js +23 -0
  9. package/extensions/magpie/cfgblocked.js +39 -0
  10. package/extensions/magpie/checkinnow.js +111 -0
  11. package/extensions/magpie/claudemode.js +92 -0
  12. package/extensions/magpie/compat.js +41 -0
  13. package/extensions/magpie/context.css +433 -0
  14. package/extensions/magpie/context.js +1576 -0
  15. package/extensions/magpie/ctxtext.js +223 -0
  16. package/extensions/magpie/fonts.js +42 -0
  17. package/extensions/magpie/i18n.js +18942 -0
  18. package/extensions/magpie/icons/ai21.svg +1 -0
  19. package/extensions/magpie/icons/ai302-color.svg +1 -0
  20. package/extensions/magpie/icons/ai360-color.svg +1 -0
  21. package/extensions/magpie/icons/aihubmix-color.svg +1 -0
  22. package/extensions/magpie/icons/aionui.svg +1 -0
  23. package/extensions/magpie/icons/air.svg +4 -0
  24. package/extensions/magpie/icons/alibaba-color.svg +1 -0
  25. package/extensions/magpie/icons/alibabacloud-color.svg +1 -0
  26. package/extensions/magpie/icons/alma.png +0 -0
  27. package/extensions/magpie/icons/anthropic.svg +1 -0
  28. package/extensions/magpie/icons/antigravity-color.svg +1 -0
  29. package/extensions/magpie/icons/anyscale-color.svg +1 -0
  30. package/extensions/magpie/icons/app-alma.png +0 -0
  31. package/extensions/magpie/icons/app-cc-switch.png +0 -0
  32. package/extensions/magpie/icons/apple-touch-icon.png +0 -0
  33. package/extensions/magpie/icons/aside.svg +28 -0
  34. package/extensions/magpie/icons/astrbot.svg +1 -0
  35. package/extensions/magpie/icons/atomcode.png +0 -0
  36. package/extensions/magpie/icons/aws.svg +1 -0
  37. package/extensions/magpie/icons/azure-color.svg +1 -0
  38. package/extensions/magpie/icons/azureai-color.svg +1 -0
  39. package/extensions/magpie/icons/baichuan-color.svg +1 -0
  40. package/extensions/magpie/icons/baidu-color.svg +1 -0
  41. package/extensions/magpie/icons/baiducloud-color.svg +1 -0
  42. package/extensions/magpie/icons/bailian-color.svg +1 -0
  43. package/extensions/magpie/icons/baseten.svg +1 -0
  44. package/extensions/magpie/icons/bedrock-color.svg +1 -0
  45. package/extensions/magpie/icons/burncloud-color.svg +1 -0
  46. package/extensions/magpie/icons/bytedance-color.svg +1 -0
  47. package/extensions/magpie/icons/cerebras.svg +1 -0
  48. package/extensions/magpie/icons/chatglm-color.svg +1 -0
  49. package/extensions/magpie/icons/cherryin-color.svg +1 -0
  50. package/extensions/magpie/icons/chutes.svg +1 -0
  51. package/extensions/magpie/icons/cindy.png +0 -0
  52. package/extensions/magpie/icons/claude-color.svg +1 -0
  53. package/extensions/magpie/icons/claudecode-color.svg +1 -0
  54. package/extensions/magpie/icons/cline.svg +1 -0
  55. package/extensions/magpie/icons/cloudflare-color.svg +1 -0
  56. package/extensions/magpie/icons/codebuddy-color.svg +1 -0
  57. package/extensions/magpie/icons/codex-color.svg +1 -0
  58. package/extensions/magpie/icons/cohere-color.svg +1 -0
  59. package/extensions/magpie/icons/cometapi-color.svg +1 -0
  60. package/extensions/magpie/icons/commandcode.svg +1 -0
  61. package/extensions/magpie/icons/copilot-color.svg +1 -0
  62. package/extensions/magpie/icons/coze.svg +1 -0
  63. package/extensions/magpie/icons/crush.png +0 -0
  64. package/extensions/magpie/icons/curl.svg +1 -0
  65. package/extensions/magpie/icons/cursor.svg +1 -0
  66. package/extensions/magpie/icons/deepinfra-color.svg +1 -0
  67. package/extensions/magpie/icons/deepmind-color.svg +1 -0
  68. package/extensions/magpie/icons/deepseek-color.svg +1 -0
  69. package/extensions/magpie/icons/deveco-color.svg +12 -0
  70. package/extensions/magpie/icons/devin.svg +1 -0
  71. package/extensions/magpie/icons/doubao-color.svg +1 -0
  72. package/extensions/magpie/icons/empryo-color.svg +1 -0
  73. package/extensions/magpie/icons/factory.svg +1 -0
  74. package/extensions/magpie/icons/favicon.svg +1 -0
  75. package/extensions/magpie/icons/featherless-color.svg +1 -0
  76. package/extensions/magpie/icons/fireworks-color.svg +1 -0
  77. package/extensions/magpie/icons/friendli.svg +1 -0
  78. package/extensions/magpie/icons/fx.svg +1 -0
  79. package/extensions/magpie/icons/gemini-color.svg +1 -0
  80. package/extensions/magpie/icons/geminicli-color.svg +1 -0
  81. package/extensions/magpie/icons/gemma-color.svg +1 -0
  82. package/extensions/magpie/icons/giteeai.svg +1 -0
  83. package/extensions/magpie/icons/github.svg +1 -0
  84. package/extensions/magpie/icons/githubcopilot.svg +1 -0
  85. package/extensions/magpie/icons/glama.svg +1 -0
  86. package/extensions/magpie/icons/gmicloud.svg +1 -0
  87. package/extensions/magpie/icons/google-color.svg +1 -0
  88. package/extensions/magpie/icons/googlecloud-color.svg +1 -0
  89. package/extensions/magpie/icons/goose.svg +1 -0
  90. package/extensions/magpie/icons/grok.svg +1 -0
  91. package/extensions/magpie/icons/groq.svg +1 -0
  92. package/extensions/magpie/icons/hanako.png +0 -0
  93. package/extensions/magpie/icons/hermes.svg +1 -0
  94. package/extensions/magpie/icons/huawei-color.svg +1 -0
  95. package/extensions/magpie/icons/huaweicloud-color.svg +1 -0
  96. package/extensions/magpie/icons/huggingface-color.svg +1 -0
  97. package/extensions/magpie/icons/hunyuan-color.svg +1 -0
  98. package/extensions/magpie/icons/hyperbolic-color.svg +1 -0
  99. package/extensions/magpie/icons/icon-512.png +0 -0
  100. package/extensions/magpie/icons/iflytekcloud-color.svg +1 -0
  101. package/extensions/magpie/icons/inference.svg +1 -0
  102. package/extensions/magpie/icons/infinigence-color.svg +1 -0
  103. package/extensions/magpie/icons/internlm-color.svg +1 -0
  104. package/extensions/magpie/icons/jcode.svg +1 -0
  105. package/extensions/magpie/icons/jina.svg +1 -0
  106. package/extensions/magpie/icons/kilo.svg +1 -0
  107. package/extensions/magpie/icons/kilocode.svg +1 -0
  108. package/extensions/magpie/icons/kimi-code-desktop.png +0 -0
  109. package/extensions/magpie/icons/kimi.svg +1 -0
  110. package/extensions/magpie/icons/kiro-color.svg +1 -0
  111. package/extensions/magpie/icons/kling-color.svg +1 -0
  112. package/extensions/magpie/icons/lambda.svg +1 -0
  113. package/extensions/magpie/icons/leptonai-color.svg +1 -0
  114. package/extensions/magpie/icons/liquid.svg +1 -0
  115. package/extensions/magpie/icons/liveagent-color.svg +1 -0
  116. package/extensions/magpie/icons/llmapi.svg +1 -0
  117. package/extensions/magpie/icons/lmstudio.svg +1 -0
  118. package/extensions/magpie/icons/lody.png +0 -0
  119. package/extensions/magpie/icons/longcat.svg +1 -0
  120. package/extensions/magpie/icons/magpie.svg +1 -0
  121. package/extensions/magpie/icons/meta-color.svg +1 -0
  122. package/extensions/magpie/icons/metaai-color.svg +1 -0
  123. package/extensions/magpie/icons/microsoft-color.svg +1 -0
  124. package/extensions/magpie/icons/mimocode.svg +1 -0
  125. package/extensions/magpie/icons/minimax-color.svg +1 -0
  126. package/extensions/magpie/icons/mistermorph-color.svg +1 -0
  127. package/extensions/magpie/icons/mistral-color.svg +1 -0
  128. package/extensions/magpie/icons/mlx-serve.png +0 -0
  129. package/extensions/magpie/icons/modelscope-color.svg +1 -0
  130. package/extensions/magpie/icons/monica-color.svg +1 -0
  131. package/extensions/magpie/icons/moonshot.svg +1 -0
  132. package/extensions/magpie/icons/morph-color.svg +1 -0
  133. package/extensions/magpie/icons/mothx.png +0 -0
  134. package/extensions/magpie/icons/nebius.svg +1 -0
  135. package/extensions/magpie/icons/newapi-color.svg +1 -0
  136. package/extensions/magpie/icons/nousresearch.svg +1 -0
  137. package/extensions/magpie/icons/nova-color.svg +1 -0
  138. package/extensions/magpie/icons/novita-color.svg +1 -0
  139. package/extensions/magpie/icons/nvidia-color.svg +1 -0
  140. package/extensions/magpie/icons/ollama.svg +1 -0
  141. package/extensions/magpie/icons/omlx.svg +1 -0
  142. package/extensions/magpie/icons/omo.svg +1 -0
  143. package/extensions/magpie/icons/omp.svg +1 -0
  144. package/extensions/magpie/icons/openai.svg +1 -0
  145. package/extensions/magpie/icons/openchamber.svg +11 -0
  146. package/extensions/magpie/icons/openclaw.svg +1 -0
  147. package/extensions/magpie/icons/opencode.svg +1 -0
  148. package/extensions/magpie/icons/openmausbot.svg +1 -0
  149. package/extensions/magpie/icons/openrouter.svg +1 -0
  150. package/extensions/magpie/icons/openwebui.svg +1 -0
  151. package/extensions/magpie/icons/parasail.svg +1 -0
  152. package/extensions/magpie/icons/penguin-color.svg +1 -0
  153. package/extensions/magpie/icons/perplexity-color.svg +1 -0
  154. package/extensions/magpie/icons/phala-color.svg +1 -0
  155. package/extensions/magpie/icons/pi.svg +1 -0
  156. package/extensions/magpie/icons/pipellm-color.svg +5 -0
  157. package/extensions/magpie/icons/poe.svg +1 -0
  158. package/extensions/magpie/icons/ppio-color.svg +1 -0
  159. package/extensions/magpie/icons/prime-agent.svg +1 -0
  160. package/extensions/magpie/icons/qiniu-color.svg +1 -0
  161. package/extensions/magpie/icons/qoder.svg +1 -0
  162. package/extensions/magpie/icons/qwen-color.svg +1 -0
  163. package/extensions/magpie/icons/qwenpaw.svg +1 -0
  164. package/extensions/magpie/icons/raycast.svg +1 -0
  165. package/extensions/magpie/icons/reasonix-color.svg +48 -0
  166. package/extensions/magpie/icons/reka.svg +1 -0
  167. package/extensions/magpie/icons/replicate.svg +1 -0
  168. package/extensions/magpie/icons/roocode.svg +1 -0
  169. package/extensions/magpie/icons/rtk.png +0 -0
  170. package/extensions/magpie/icons/sambanova-color.svg +1 -0
  171. package/extensions/magpie/icons/sensenova-color.svg +1 -0
  172. package/extensions/magpie/icons/siliconcloud-color.svg +1 -0
  173. package/extensions/magpie/icons/snow.png +0 -0
  174. package/extensions/magpie/icons/snowflake-color.svg +1 -0
  175. package/extensions/magpie/icons/sophnet-color.svg +1 -0
  176. package/extensions/magpie/icons/spark-color.svg +1 -0
  177. package/extensions/magpie/icons/stepfun-color.svg +1 -0
  178. package/extensions/magpie/icons/straico-color.svg +1 -0
  179. package/extensions/magpie/icons/submodel-color.svg +1 -0
  180. package/extensions/magpie/icons/t3code.svg +4 -0
  181. package/extensions/magpie/icons/targon-color.svg +1 -0
  182. package/extensions/magpie/icons/tencent-color.svg +1 -0
  183. package/extensions/magpie/icons/tencentcloud-color.svg +1 -0
  184. package/extensions/magpie/icons/tiangong-color.svg +1 -0
  185. package/extensions/magpie/icons/together-color.svg +1 -0
  186. package/extensions/magpie/icons/trae.svg +1 -0
  187. package/extensions/magpie/icons/typesafe.png +0 -0
  188. package/extensions/magpie/icons/upstage-color.svg +1 -0
  189. package/extensions/magpie/icons/venice-color.svg +1 -0
  190. package/extensions/magpie/icons/vercel.svg +1 -0
  191. package/extensions/magpie/icons/vertexai-color.svg +1 -0
  192. package/extensions/magpie/icons/vllm-color.svg +1 -0
  193. package/extensions/magpie/icons/volcengine-color.svg +1 -0
  194. package/extensions/magpie/icons/voyage-color.svg +1 -0
  195. package/extensions/magpie/icons/vscode.svg +1 -0
  196. package/extensions/magpie/icons/wenxin-color.svg +1 -0
  197. package/extensions/magpie/icons/windsurf.svg +1 -0
  198. package/extensions/magpie/icons/workbuddy-color.svg +1 -0
  199. package/extensions/magpie/icons/workersai-color.svg +1 -0
  200. package/extensions/magpie/icons/xai.svg +1 -0
  201. package/extensions/magpie/icons/xiaomimimo.svg +1 -0
  202. package/extensions/magpie/icons/xinference-color.svg +1 -0
  203. package/extensions/magpie/icons/yi.svg +1 -0
  204. package/extensions/magpie/icons/yuanbao-color.svg +1 -0
  205. package/extensions/magpie/icons/yylx.svg +5 -0
  206. package/extensions/magpie/icons/zai.svg +1 -0
  207. package/extensions/magpie/icons/zcode.png +0 -0
  208. package/extensions/magpie/icons/zed.svg +1 -0
  209. package/extensions/magpie/icons/zenmux.svg +1 -0
  210. package/extensions/magpie/icons/zeroone.svg +1 -0
  211. package/extensions/magpie/icons/zhipu-color.svg +1 -0
  212. package/extensions/magpie/icons/zoo-code.png +0 -0
  213. package/extensions/magpie/index.html +572 -0
  214. package/extensions/magpie/kernel.js +274 -0
  215. package/extensions/magpie/keyspend.js +63 -0
  216. package/extensions/magpie/layout.js +26 -0
  217. package/extensions/magpie/manifest.json +37 -0
  218. package/extensions/magpie/navlamp.js +47 -0
  219. package/extensions/magpie/omarchy.css +72 -0
  220. package/extensions/magpie/omarchy.js +46 -0
  221. package/extensions/magpie/passerrors.js +21 -0
  222. package/extensions/magpie/pluginpages.js +405 -0
  223. package/extensions/magpie/plugins/gateway/client.js +1194 -0
  224. package/extensions/magpie/plugins/gateway/keys.js +972 -0
  225. package/extensions/magpie/plugins/gateway/settings.js +459 -0
  226. package/extensions/magpie/plugins/library/client.js +6788 -0
  227. package/extensions/magpie/plugins/library/i18n.js +3228 -0
  228. package/extensions/magpie/plugins/library/library.css +848 -0
  229. package/extensions/magpie/plugins/otel/i18n.js +48 -0
  230. package/extensions/magpie/plugins/otel/page.js +189 -0
  231. package/extensions/magpie/plugins/redact/client.js +46 -0
  232. package/extensions/magpie/plugins/redact/demo.js +461 -0
  233. package/extensions/magpie/plugins/redact/i18n.js +432 -0
  234. package/extensions/magpie/plugins/redact/page.js +985 -0
  235. package/extensions/magpie/plugins/redact/redact.css +385 -0
  236. package/extensions/magpie/plugins/redact/settings.js +248 -0
  237. package/extensions/magpie/plugins/redact/xq_dark.jpg +0 -0
  238. package/extensions/magpie/plugins/redact/xq_dark.webm +0 -0
  239. package/extensions/magpie/plugins/redact/xq_light.jpg +0 -0
  240. package/extensions/magpie/plugins/redact/xq_light.webm +0 -0
  241. package/extensions/magpie/plugins/routing/client.js +8593 -0
  242. package/extensions/magpie/plugins/routing/i18n.js +2696 -0
  243. package/extensions/magpie/plugins/routing/routing.css +1111 -0
  244. package/extensions/magpie/plugins/search/settings.js +460 -0
  245. package/extensions/magpie/plugins/sessions/client.js +1622 -0
  246. package/extensions/magpie/plugins/sessions/i18n.js +360 -0
  247. package/extensions/magpie/plugins/sessions/sessions.css +181 -0
  248. package/extensions/magpie/plugins/sessions/settings.js +100 -0
  249. package/extensions/magpie/plugins/usage/client.js +150 -0
  250. package/extensions/magpie/plugins/usage/i18n.js +984 -0
  251. package/extensions/magpie/plugins/usage/page.js +4307 -0
  252. package/extensions/magpie/plugins.css +319 -0
  253. package/extensions/magpie/plugins.js +1926 -0
  254. package/extensions/magpie/profilerename.js +27 -0
  255. package/extensions/magpie/purposes.js +2 -0
  256. package/extensions/magpie/quitask.js +79 -0
  257. package/extensions/magpie/quotaall.js +142 -0
  258. package/extensions/magpie/ratewindows.js +123 -0
  259. package/extensions/magpie/registry.js +87 -0
  260. package/extensions/magpie/resetask.js +137 -0
  261. package/extensions/magpie/ruleedit.js +53 -0
  262. package/extensions/magpie/scrollends.js +91 -0
  263. package/extensions/magpie/settingshints.js +75 -0
  264. package/extensions/magpie/signsheets.js +86 -0
  265. package/extensions/magpie/start.js +26 -0
  266. package/extensions/magpie/syncfiles.js +216 -0
  267. package/extensions/magpie/theme.js +29 -0
  268. package/extensions/magpie/traywindows.js +41 -0
  269. package/extensions/magpie/webfonts.js +130 -0
  270. package/extensions/magpie/whatsnew.js +252 -0
  271. package/extensions/magpie.zip +0 -0
  272. package/knowledge/apps/baijiahao.md +30 -0
  273. package/knowledge/apps/bilibili.md +1 -0
  274. package/knowledge/apps/dedao.md +33 -0
  275. package/knowledge/apps/feishu.md +35 -0
  276. package/knowledge/apps/gmail.md +33 -0
  277. package/knowledge/apps/jike.md +31 -0
  278. package/knowledge/apps/kuaishou.md +34 -0
  279. package/knowledge/apps/linkedin.md +33 -0
  280. package/knowledge/apps/qqmail.md +30 -0
  281. package/knowledge/apps/telegram.md +27 -0
  282. package/knowledge/apps/toutiao.md +32 -0
  283. package/knowledge/apps/uber-eats.md +26 -0
  284. package/knowledge/apps/uber.md +27 -0
  285. package/knowledge/apps/whatsapp.md +27 -0
  286. package/knowledge/apps/x.md +32 -0
  287. package/knowledge/apps/xiaohongshu.md +1 -0
  288. package/knowledge/apps/zhihu.md +1 -0
  289. package/knowledge/sites/bilibili.com/SITE.md +50 -0
  290. package/knowledge/sites/bilibili.com/references/view-fields.md +17 -0
  291. package/knowledge/sites/github.com/SITE.md +51 -0
  292. package/knowledge/sites/github.com/references/repo-fields.md +13 -0
  293. package/knowledge/sites/x.com/SITE.md +47 -0
  294. package/knowledge/sites/xiaohongshu.com/SITE.md +48 -0
  295. package/knowledge/sites/xiaohongshu.com/references/note-fields.md +18 -0
  296. package/knowledge/sites/youtube.com/SITE.md +49 -0
  297. package/knowledge/sites/youtube.com/references/innertube-fields.md +14 -0
  298. package/knowledge/sites/zhihu.com/SITE.md +47 -0
  299. package/knowledge/sites/zhihu.com/references/api-fields.md +21 -0
  300. package/lib/mobile/extension-catalog.js +41 -1
  301. package/lib/mobile/extension-data.js +224 -0
  302. package/lib/mobile/extension-dev.js +3 -1
  303. package/lib/mobile/file-ops.js +252 -0
  304. package/lib/mobile/history-derive.js +80 -4
  305. package/lib/mobile/host-bridge/endpoints.js +48 -6
  306. package/lib/mobile/host-bridge/event-synthesis.js +33 -6
  307. package/lib/mobile/jobs-control.js +118 -0
  308. package/lib/mobile/memory.js +635 -0
  309. package/lib/mobile/model-badges.js +77 -0
  310. package/lib/mobile/pet-tools.js +50 -4
  311. package/lib/mobile/pets.js +214 -18
  312. package/lib/mobile/phone/access.js +85 -0
  313. package/lib/mobile/phone/evidence.js +228 -0
  314. package/lib/mobile/phone/gate.js +290 -0
  315. package/lib/mobile/phone/grounding.js +314 -0
  316. package/lib/mobile/phone/guard.js +465 -0
  317. package/lib/mobile/phone/irreversible.js +88 -8
  318. package/lib/mobile/phone/knowledge-tools.js +665 -0
  319. package/lib/mobile/phone/learn.js +329 -0
  320. package/lib/mobile/phone/redact.js +237 -0
  321. package/lib/mobile/phone/risk.js +95 -0
  322. package/lib/mobile/phone/routes.js +28 -1
  323. package/lib/mobile/phone/service.js +23 -0
  324. package/lib/mobile/phone/site-commands.js +271 -0
  325. package/lib/mobile/phone/step-summary.js +201 -0
  326. package/lib/mobile/phone/stop-summary.js +235 -0
  327. package/lib/mobile/phone/tool-groups.js +125 -0
  328. package/lib/mobile/phone/tools.js +589 -0
  329. package/lib/mobile/phone/untrusted.js +65 -0
  330. package/lib/mobile/phone-knowledge.js +20 -4
  331. package/lib/mobile/schedule-edit.js +500 -0
  332. package/lib/mobile/schedule.js +5 -0
  333. package/lib/mobile/send-continuation.js +52 -0
  334. package/lib/mobile/session-models.js +27 -31
  335. package/lib/mobile/session-send.js +12 -12
  336. package/lib/mobile/skill-import.js +338 -0
  337. package/lib/mobile/skill-store.js +524 -0
  338. package/lib/routes/mobile-api.js +42 -0
  339. package/package.json +7 -6
  340. package/skills/skill-authoring/SKILL.md +46 -0
  341. package/skills/skill-authoring/references/examples.md +82 -0
  342. package/skills/skill-authoring/references/frontmatter-and-fields.md +46 -0
  343. package/skills/skill-authoring/scripts/check_skill.py +167 -0
  344. package/skills/skill-authoring/scripts/manifest.json +3 -0
  345. package/knowledge/sites/bilibili.com.md +0 -27
  346. package/knowledge/sites/github.com.md +0 -27
  347. package/knowledge/sites/x.com.md +0 -28
  348. package/knowledge/sites/xiaohongshu.com.md +0 -27
  349. package/knowledge/sites/youtube.com.md +0 -28
  350. package/knowledge/sites/zhihu.com.md +0 -27
@@ -0,0 +1,130 @@
1
+ // A browser tab's fonts: the ones on the computer the browser runs on,
2
+ // which may not be the one magpie runs on (Norcleeh on Discord: magpie in
3
+ // Docker, its web GUI listed the container's fonts, never his own). Only
4
+ // a tab loads this (app.js loadFonts imports it); the app's windows list the
5
+ // installed fonts magpie reads itself.
6
+ //
7
+ // A tab's list is the server's families it draws, plus:
8
+ // - its computer's own, from the Local Font Access API (Chromium, on
9
+ // https or localhost), asked the first time the family menu is opened,
10
+ // since it needs a press and asks the user's permission once; read at
11
+ // once when that permission is already given;
12
+ // - the families chosen in this tab (kept in localStorage by fonts.js);
13
+ // - any family typed into the menu's search that this browser draws, for
14
+ // Safari, Firefox, a plain-http address or a refused permission.
15
+ // "Draws" is a canvas probe: text in the family measures apart from
16
+ // monospace's or serif's.
17
+ window.webFonts = (() => {
18
+ let ctx, local = null, asked = false, base = [];
19
+ const extra = [], seen = new Map();
20
+ const quoted = window.desktopFonts.quoted;
21
+ // The two generics' widths are measured once: each family then costs one
22
+ // or two measures, not two or four.
23
+ let generic;
24
+ const width = (f) => (ctx.font = "72px " + f, ctx.measureText("mmmlli WwQ@ 0123 中文").width);
25
+ function drawn(name) {
26
+ if (!seen.has(name)) {
27
+ ctx ||= document.createElement("canvas").getContext("2d");
28
+ generic ||= ["monospace", "serif"].map((b) => [b, width(b)]);
29
+ seen.set(name, !!name && generic.some(([b, w]) => width(quoted(name) + "," + b) !== w));
30
+ }
31
+ return seen.get(name);
32
+ }
33
+ const face = (family, name = "Regular", weight = 400, style = "normal", stretch = 100) => ({ family, name, weight, style, stretch });
34
+ const regular = (family) => [face(family), face(family, "Bold", 700)];
35
+ const same = window.desktopFonts.same;
36
+ // a face's CSS traits from the style name the system gives it
37
+ // ("SemiBold Condensed Italic")
38
+ const first = (rules, s, d) => (rules.find(([re]) => re.test(s)) || [, d])[1];
39
+ const WEIGHTS = [[/thin|hairline/, 100], [/(extra|ultra)-?light/, 200], [/light/, 300], [/(semi|demi)-?bold/, 600],
40
+ [/(extra|ultra)-?bold/, 800], [/black|heavy/, 900], [/medium/, 500], [/bold/, 700]];
41
+ const STRETCHES = [[/ultra-?condensed/, 50], [/extra-?condensed/, 62.5], [/semi-?condensed/, 87.5], [/condensed|narrow/, 75],
42
+ [/semi-?expanded/, 112.5], [/extra-?expanded/, 150], [/ultra-?expanded/, 200], [/expanded|wide/, 125]];
43
+ function group(data) {
44
+ const fams = new Map();
45
+ for (const d of data) {
46
+ if (!d.family) continue;
47
+ const s = String(d.style || "").toLowerCase().replace(/\s+/g, "");
48
+ const f = face(d.family, d.style || "Regular", first(WEIGHTS, s, 400), /italic/.test(s) ? "italic" : /oblique/.test(s) ? "oblique" : "normal", first(STRETCHES, s, 100));
49
+ const styles = fams.get(d.family) || [];
50
+ if (!styles.some((o) => o.weight === f.weight && o.style === f.style && o.stretch === f.stretch)) styles.push(f);
51
+ fams.set(d.family, styles);
52
+ }
53
+ return [...fams].map(([name, styles]) => ({ name, styles: styles.sort((a, b) => a.weight - b.weight || (a.style > b.style) - (a.style < b.style) || a.stretch - b.stretch) }));
54
+ }
55
+ function merge() {
56
+ const out = new Map();
57
+ for (const f of [...base, ...(local || []), ...extra]) out.set(f.name, f);
58
+ const own = window.desktopFonts.own() || {};
59
+ for (const c of [own.uiFont, own.codeFont]) {
60
+ if (typeof c?.family !== "string" || !drawn(c.family)) continue;
61
+ const f = out.get(c.family) || { name: c.family, styles: regular(c.family) };
62
+ out.set(c.family, f.styles.some((s) => same(s, c)) ? f : { ...f, styles: [...f.styles, c] });
63
+ }
64
+ return [...out.values()].sort((a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase()));
65
+ }
66
+ // called in the press that opens the menu: queryLocalFonts needs it
67
+ async function read() {
68
+ local = group(await window.queryLocalFonts());
69
+ }
70
+ // list: the tab's families, from the server's (/api/fonts)
71
+ // The probe yields every few milliseconds: a measure of a family not yet
72
+ // drawn loads it, and probing a Mac's whole list at once held the click
73
+ // that opened Settings in one task, 2.6 s with the CPU slowed 4x.
74
+ async function list(server) {
75
+ const out = [];
76
+ let start = performance.now();
77
+ for (const f of server) {
78
+ if (drawn(f.name)) out.push(f);
79
+ if (performance.now() - start > 8) await new Promise((r) => setTimeout(r)), start = performance.now();
80
+ }
81
+ base = out;
82
+ if (!asked && window.queryLocalFonts) try {
83
+ if ((await navigator.permissions.query({ name: "local-fonts" })).state === "granted") await read(), asked = true;
84
+ } catch {}
85
+ return merge();
86
+ }
87
+ // ask: the first time a family menu opens where the browser can tell
88
+ // this computer's fonts, they join the list (app.js fontList)
89
+ const catalogue = () => window.desktopFonts.catalogue(fontList = merge());
90
+ function ask() {
91
+ if (asked || !window.queryLocalFonts) return;
92
+ asked = true; // a refusal isn't asked again on this page
93
+ return read().then(catalogue, () => {});
94
+ }
95
+ // typing: the open family menu's search also takes a family the list
96
+ // lacks; it is offered when this browser draws it, and chosen for key
97
+ function typing(key) {
98
+ const box = protoMenu?.box, q = box?.querySelector(".sc-q");
99
+ if (!q) return;
100
+ q.placeholder = t("Search or type a font name…");
101
+ q.setAttribute("aria-label", q.placeholder);
102
+ const b = el("button", "pm-item typed-font"), words = el("span", "pm-words"), name = el("span", "pm-name"), note = el("span", "pm-note");
103
+ b.type = "button";
104
+ b.hidden = true;
105
+ words.append(name, note);
106
+ b.append(el("span", "pm-tick"), words);
107
+ box.lastChild.before(b); // above Refresh fonts
108
+ hoverFocus(b);
109
+ let family = "";
110
+ q.addEventListener("input", () => {
111
+ family = q.value.trim();
112
+ const low = family.toLowerCase(), ok = drawn(family);
113
+ b.hidden = !family || (fontList || []).some((f) => f.name.toLowerCase() === low);
114
+ b.disabled = !ok;
115
+ name.textContent = t("Use “{name}”", { name: family });
116
+ note.textContent = ok ? "" : t("This browser can't find this font");
117
+ });
118
+ // Enter takes it when no listed family matched (app.js took that one)
119
+ q.addEventListener("keydown", (e) => { if (e.key === "Enter" && !e.defaultPrevented && !b.hidden && !b.disabled) b.click(); });
120
+ b.onclick = (e) => {
121
+ e.stopPropagation();
122
+ closeProtoMenu();
123
+ const styles = regular(family);
124
+ extra.push({ name: family, styles });
125
+ catalogue();
126
+ chooseFont(key, styles[0]);
127
+ };
128
+ }
129
+ return { list, ask, typing, drawn };
130
+ })();
@@ -0,0 +1,252 @@
1
+ // The release notes' dialogs: What's new (after an update, and Settings'
2
+ // row) and the ask before an update is put in. app.js imports this when
3
+ // one opens (notesJS), so it weighs nothing on the core.
4
+ // wnRange is Settings' pick of which notes (Linka): since the last update,
5
+ // or this version and 10, 20, 50 or 100 before it
6
+ function wnRange(last) {
7
+ const name = (v) => v ? t("This version and {n} before", { n: v }) : t("Since the last update");
8
+ const b = el("button", "sess-pick wn-range");
9
+ b.type = "button";
10
+ b.setAttribute("aria-haspopup", "menu");
11
+ b.append(el("span", "", name(last)), svg(CHEV, 11, 1.6));
12
+ b.onclick = (e) => {
13
+ e.stopPropagation();
14
+ if (b.classList.contains("open")) return closeProtoMenu();
15
+ openProtoMenu(b, ["", "10", "20", "50", "100"].map((v) => ({ v, name: name(v), note: "", literalName: true })), last, (v) => v !== last && openWhatsNew(b, v), "Release notes shown", "sess-menu", "right");
16
+ };
17
+ return b;
18
+ }
19
+
20
+ // auto: shown by itself after an update, with "Don't show again today"
21
+ // (#525: releases come many a day); Settings' row opens it without one.
22
+ // more (from Settings): failed, the current version's notes couldn't be
23
+ // had, retry asks again; current and url, the version and its release
24
+ // page, for a dialog with no notes.
25
+ function showWhatsNew(releases, auto, more = {}) {
26
+ const ed = el("div", "editor whatsnew");
27
+ const head = el("div", "ehead");
28
+ head.append(el("b", "", t("What's new in {v}", { v: "v" + (releases[0]?.version || more.current) })));
29
+ if (!auto) head.append(el("span", "grow"), wnRange(more.last || ""));
30
+ ed.append(head);
31
+ if (releases.length > 1) {
32
+ const sec = el("section", "wn-rel");
33
+ const wait = releases.filter((r) => r.pending);
34
+ if (wait.length) {
35
+ const h = el("div", "wn-ver");
36
+ h.append(el("b", "", "v" + wait.at(-1).version + (wait.length > 1 ? " – v" + wait[0].version : "")), el("span", "badge", t("Not installed yet")));
37
+ sec.append(h);
38
+ }
39
+ sec.append(mergedNotes(releases, more.total));
40
+ ed.append(sec);
41
+ }
42
+ else for (const r of releases) {
43
+ const sec = el("section", "wn-rel");
44
+ const h = el("div", "wn-ver");
45
+ h.append(el("b", "", "v" + r.version));
46
+ if (r.pending) h.append(el("span", "badge", t("Not installed yet")));
47
+ sec.append(h, noteBlocks(r.notes));
48
+ ed.append(sec);
49
+ }
50
+ if (more.failed || !releases.length) {
51
+ const sec = el("section", "wn-rel wn-none" + (more.failed ? " wn-failed" : ""));
52
+ const h = el("div", "wn-ver");
53
+ if (more.current) h.append(el("b", "", "v" + more.current));
54
+ const p = el("p", "wn-msg", more.failed ? t("Couldn't load the release notes") : t("No release notes provided."));
55
+ const acts = el("div", "wn-acts");
56
+ if (more.failed && more.retry) {
57
+ const again = el("button", "text", t("Try again"));
58
+ again.onclick = async (e) => {
59
+ e.stopPropagation();
60
+ again.disabled = true;
61
+ again.classList.add("busy");
62
+ await more.retry();
63
+ };
64
+ acts.append(again);
65
+ }
66
+ if (more.url) acts.append(noteLink(t("Open the release page"), more.url));
67
+ sec.append(h, p, acts);
68
+ head.after(sec); // above the notes kept from before
69
+ }
70
+ const bar = el("div", "bar");
71
+ const ok = el("button", "text primary", t("Close"));
72
+ ok.onclick = cancelAsk;
73
+ if (auto) {
74
+ // told at once, so Escape or a click outside keeps it as well as Close
75
+ const [quiet, box] = tick(t("Don't show again today"), false);
76
+ quiet.classList.add("wn-quiet");
77
+ box.onchange = () => api("whatsnew/today", { on: box.checked }).catch(statusErr);
78
+ bar.append(quiet);
79
+ }
80
+ bar.append(el("span", "grow"), ok);
81
+ ed.append(bar);
82
+ confirmAsk = ed;
83
+ openModal(ed);
84
+ $("#modal").classList.add("lib");
85
+ ok.focus(NO_SCROLL);
86
+ }
87
+
88
+ // noteBlocks draws a release's markdown as text: headings (tHeading),
89
+ // bullets, paragraphs, inline bold, code and links, never as HTML; #123
90
+ // links the issue.
91
+ function noteBlocks(md) {
92
+ const box = el("div", "wn-notes");
93
+ let list = null;
94
+ for (const line of String(md || "").split(/\r?\n/)) {
95
+ const h = /^\s{0,3}(#{1,6})\s+(.*?)\s*#*\s*$/.exec(line);
96
+ const li = /^\s*[-*+]\s+(.*)$/.exec(line);
97
+ if (h) {
98
+ list = null;
99
+ box.append(inlineMD(el("div", "wn-h wn-h" + Math.min(h[1].length, 4)), tHeading(h[2])));
100
+ } else if (li) {
101
+ if (!list) box.append(list = el("ul"));
102
+ list.append(inlineMD(el("li"), li[1]));
103
+ } else if (!line.trim()) {
104
+ list = null;
105
+ } else if (list && /^\s{2,}\S/.test(line)) {
106
+ inlineMD(list.lastElementChild, " " + line.trim());
107
+ } else {
108
+ list = null;
109
+ box.append(inlineMD(el("p"), line.trim()));
110
+ }
111
+ }
112
+ return box;
113
+ }
114
+
115
+ // NOTE_ORDER: the merged notes' sections, what's new first
116
+ const NOTE_ORDER = ["Features", "Improvements", "Performance Improvements", "Bug Fixes", "Security", "Provider Changes", "Changes", "Documentation"];
117
+
118
+ // mergedNotes draws many releases' notes as one (the owner: nine releases
119
+ // of a line each read as a scattered list): their bullets gathered under
120
+ // one heading per kind, New features first, each with the version it came
121
+ // in, newest first, and a line that says the range. A line outside a list
122
+ // is a bullet of its own; a release with no notes is left out.
123
+ // total: how many releases there are in all when the server kept only the
124
+ // newest (update.MostNotes), so 156 behind doesn't read "40 releases"
125
+ // (sujingshen on X).
126
+ function mergedNotes(releases, total = 0) {
127
+ const secs = new Map();
128
+ for (const r of releases) {
129
+ const of = (k) => secs.get(k) || secs.set(k, []).get(k);
130
+ let sec = null, li = null;
131
+ const put = (text) => {
132
+ sec ??= of(t("Changes"));
133
+ li = sec.some((b) => b.text === text) ? null : { text, v: r.version };
134
+ if (li) sec.push(li);
135
+ };
136
+ for (const line of String(r.notes || "").split(/\r?\n/)) {
137
+ const h = /^\s{0,3}#{1,6}\s+(.*?)\s*#*\s*$/.exec(line);
138
+ const b = /^\s*[-*+]\s+(.*)$/.exec(line);
139
+ if (h) {
140
+ sec = of(tHeading(h[1]));
141
+ li = null;
142
+ } else if (b) put(b[1]);
143
+ else if (!line.trim()) li = null;
144
+ else if (li && /^\s{2,}\S/.test(line)) li.text += " " + line.trim();
145
+ else put(line.trim());
146
+ }
147
+ }
148
+ const rank = (k) => { const i = NOTE_ORDER.findIndex((o) => t(o) === k); return i < 0 ? NOTE_ORDER.length : i; };
149
+ const box = el("div", "wn-notes wn-merged");
150
+ const vs = releases.map((r) => r.version);
151
+ const span = total > vs.length
152
+ ? t("{n} releases · the newest {m} shown, {from} – {to}", { n: total, m: vs.length, from: "v" + vs.at(-1), to: "v" + vs[0] })
153
+ : t("{n} releases · {from} – {to}", { n: vs.length, from: "v" + vs.at(-1), to: "v" + vs[0] });
154
+ box.append(el("div", "wn-span", span));
155
+ for (const [k, items] of [...secs].filter(([, x]) => x.length).sort((a, b) => rank(a[0]) - rank(b[0]))) {
156
+ const h = el("div", "wn-h wn-h2");
157
+ h.append(k, el("span", "wn-n", String(items.length)));
158
+ const list = el("ul");
159
+ for (const it of items) {
160
+ const e = inlineMD(el("li"), it.text);
161
+ e.append(el("span", "wn-v", "v" + it.v));
162
+ list.append(e);
163
+ }
164
+ box.append(h, list);
165
+ }
166
+ return box;
167
+ }
168
+
169
+ // inlineMD appends text to e with **bold**, `code`, [links](https://…),
170
+ // bare https:// links and #123 issue links; only http(s) addresses link.
171
+ function inlineMD(e, s) {
172
+ const re = /\*\*(.+?)\*\*|`([^`]+)`|\[([^\]]+)\]\((https?:\/\/[^\s)]+)\)|(https?:\/\/[^\s<>)]+)|(^|[\s(\[])#(\d+)\b/g;
173
+ let at = 0, m;
174
+ while ((m = re.exec(s))) {
175
+ if (m.index > at) e.append(s.slice(at, m.index));
176
+ if (m[1] !== undefined) e.append(inlineMD(el("b"), m[1]));
177
+ else if (m[2] !== undefined) e.append(el("code", "", m[2]));
178
+ else if (m[3] !== undefined) e.append(noteLink(m[3], m[4]));
179
+ else if (m[5] !== undefined) e.append(noteLink(m[5], m[5]));
180
+ else e.append(m[6], noteLink("#" + m[7], ISSUES + m[7]));
181
+ at = re.lastIndex;
182
+ }
183
+ if (at < s.length) e.append(s.slice(at));
184
+ return e;
185
+ }
186
+
187
+ // a link in the notes opens in the browser, as the app's other links do
188
+ function noteLink(text, url) {
189
+ const a = el("a", "wn-link", text);
190
+ a.href = url;
191
+ a.target = "_blank";
192
+ a.rel = "noopener";
193
+ a.onclick = (e) => { e.preventDefault(); e.stopPropagation(); api("open", { url }).catch(() => {}); };
194
+ return a;
195
+ }
196
+
197
+ // confirmUpdate shows what changed before an update downloaded is put in
198
+ // (Hu9956, #844: every update came unseen, its notes three clicks away in
199
+ // Settings › About): every release's notes after this one up to it, newest
200
+ // first, with Restart to update and Later. The update's own notes show at
201
+ // once; the releases between come in after. go restarts. The tray's panel,
202
+ // with no room for a dialog, restarts as before.
203
+ async function confirmUpdate(u, go) {
204
+ const ed = el("div", "editor whatsnew update-ask");
205
+ const head = el("div", "ehead");
206
+ const title = el("b", "", t("Update to {v}", { v: "v" + u.latest }));
207
+ head.append(title);
208
+ if (u.current) head.append(el("span", "wn-since", t("What changed since {v}", { v: "v" + u.current })));
209
+ const box = el("div", "wn-list");
210
+ const draw = (releases, total) => {
211
+ box.replaceChildren();
212
+ if (releases.length > 1) {
213
+ const sec = el("section", "wn-rel");
214
+ sec.append(mergedNotes(releases, total));
215
+ box.append(sec);
216
+ }
217
+ else for (const r of releases) {
218
+ const sec = el("section", "wn-rel");
219
+ const h = el("div", "wn-ver");
220
+ h.append(el("b", "", "v" + r.version));
221
+ sec.append(h, noteBlocks(r.notes));
222
+ box.append(sec);
223
+ }
224
+ if (!releases.length) {
225
+ const sec = el("section", "wn-rel wn-none");
226
+ sec.append(el("p", "wn-msg", t("No release notes provided.")));
227
+ if (u.url) sec.append(noteLink(t("Open the release page"), u.url));
228
+ box.append(sec);
229
+ }
230
+ };
231
+ draw(u.notes ? [{ version: u.latest, notes: u.notes }] : []);
232
+ const bar = el("div", "bar");
233
+ const later = el("button", "text", t("Later"));
234
+ later.onclick = cancelAsk;
235
+ const ok = el("button", "text primary", t("Restart to update"));
236
+ ok.onclick = (e) => { e.stopPropagation(); closeConfirmAsk(); go(); };
237
+ bar.append(el("span", "grow"), later, ok);
238
+ ed.append(head, box, bar);
239
+ confirmAsk = ed;
240
+ openModal(ed);
241
+ $("#modal").classList.add("lib");
242
+ ok.focus(NO_SCROLL);
243
+ // the notes' answer asks the feed again first, and names a release out
244
+ // since the one downloaded (#910), which the restart then waits for
245
+ const w = await api(updatePath("update/notes")).catch(() => null);
246
+ if (confirmAsk !== ed) return;
247
+ if (w?.latest && w.latest !== u.latest) title.textContent = t("Update to {v}", { v: "v" + w.latest });
248
+ if (w?.releases?.length) draw(w.releases, w.total);
249
+ }
250
+
251
+ window.wnShow = showWhatsNew;
252
+ window.wnConfirm = confirmUpdate;
Binary file
@@ -0,0 +1,30 @@
1
+ ---
2
+ name: baijiahao
3
+ display: 百家号
4
+ description: 百度创作者平台,发布内容、管理作品和看数据
5
+ packages: ["com.baidu.baijia"]
6
+ aliases: ["百家号", "Baijiahao", "baijiahao", "百度百家号"]
7
+ sites: ["baijiahao.baidu.com"]
8
+ open: 百家号
9
+ pace: careful
10
+ ---
11
+ ## 是什么
12
+ 百家号是百度的内容创作者 App,包名 `com.baidu.baijia`。用来发布和管理自己的图文、视频,看阅读、粉丝、收益数据,处理评论和通知。
13
+
14
+ ## 界面
15
+ 底部标签:首页、管理、中间「+」(发布)、消息、我的。
16
+ - 首页:标题「百家号」,下面「热门事件」,可按全网、城市、娱乐、体育等频道切换(右边按钮改频道)。
17
+ - 管理:上面数据卡片(累计阅读、本月收益、粉丝总数、消息分析);下面按全部、动态、图文、视频、小视频、直播分标签列自己的作品,每条有标题、发布时间、状态、几个互动数和「…」操作菜单,列表右上有搜索。
18
+ - 消息:分互动、通知、公告,右上角消息设置;互动里按评论、关注、点赞、收藏、分享分类。
19
+ - 我的:资料卡(粉丝、关注、活力值、信用分),右上角扫一扫和二维码;常用功能(我的权益、我的认证、我的信息、评论管理、素材管理、话题管理、橱窗管理、黑名单管理、我的收藏、主播中心、百+);更多功能(发文设置、消息设置、系统设置、帮助反馈)。
20
+
21
+ ## 功能
22
+ - 发布:底部「+」弹发布面板,显示今天还能发几篇;可选图文、动态、直播、图集、拍视频、上传视频、视频合集、草稿,下面是推荐活动,底部有关闭按钮。
23
+ - 管理作品:在管理页点某条进详情看数据,或点「…」编辑、删除、分享。
24
+ - 系统设置:清除缓存、关于(版本号)、已收集个人信息清单、第三方信息共享清单、退出登录。
25
+
26
+ ## 已知现象
27
+ - 打开时可能弹「检测到您尚未打开通知功能……」,按钮「取消」「去开启」。
28
+ - 不少按钮没有名字,只有资源 ID:返回(`left_button`)、扫一扫(`scan_it`)、二维码(`qr_code`)、作品操作菜单(`operation_menu_layout`)。
29
+ - 管理页作品下面几个数字在元素里只有数,没有说明是哪一项,要看画面上的图标。
30
+ - 发布有每日篇数上限,面板上会显示今天还能发几篇。
@@ -4,6 +4,7 @@ display: 哔哩哔哩
4
4
  description: 视频社区,看视频、弹幕与评论
5
5
  packages: ["tv.danmaku.bili"]
6
6
  aliases: ["哔哩哔哩", "B站", "bilibili", "b站"]
7
+ sites: ["bilibili.com"]
7
8
  open: 哔哩哔哩
8
9
  pace: careful
9
10
  ---
@@ -0,0 +1,33 @@
1
+ ---
2
+ name: dedao
3
+ display: 得到
4
+ description: 知识课程、听书、电子书和学习社区
5
+ packages: ["com.luojilab.player"]
6
+ aliases: ["得到", "Dedao", "dedao", "得到App"]
7
+ sites: ["dedao.cn"]
8
+ open: 得到
9
+ pace: careful
10
+ ---
11
+ ## 是什么
12
+ 得到是知识学习 App,包名 `com.luojilab.player`。有付费课程、听书、电子书、直播和学习社区。
13
+
14
+ ## 界面
15
+ 底部标签:首页、听书看书、知识城邦、学习、最右个人页(没登录显示「未登录」)。各标签顶部大多有搜索框,右边有积分、最近学习、消息或设置图标。
16
+ - 首页:搜索框右边成长任务/积分换礼、最近学习、消息中心;下面频道推荐、课程、长谈、AI 学习圈等;推荐页有运营横幅、一排入口(得到榜单、得到课程、听书看书、得到积分、全部分类)、栏目内容、直播预告。
17
+ - 听书看书:我的会员、听书、电子书;听书会员开通条、新书上架、名家讲书、镇馆之宝、知识地图、分类入口、每日上新、重磅新书。
18
+ - 知识城邦:社区动态,分视频、关注、推荐;每条有作者、时间、正文(可展开)、转发、评论、点赞、分享。
19
+ - 学习:自己的学习内容;没登录只有登录/注册。
20
+ - 个人页:头像(登录/注册)、学分、今日学习、勋章、证书;我的账户(余额、卡券、订单、购物车、会员、门票、积分);我的内容(笔记、最近学习、下载、收藏/清单、订阅通知);右上角齿轮是设置。
21
+
22
+ ## 功能
23
+ - 搜索:点顶部搜索框。有输入框、语音按钮、「取消」;下面历史搜索(带删除),再是热搜、发现、课程、听书、电子书几个标签的排行。
24
+ - 设置:帐号/绑定、地址管理、安全中心、个人身份认证、隐私设置、后台播放优化、夜间模式、消息通知、一键记笔记、软件升级、添加小组件、版本介绍、清除缓存、关于。
25
+ - 课程/听书详情页有目录、试听、购买入口;已购内容在「学习」里。
26
+
27
+ ## 已知现象
28
+ - 没登录时打开先进手机号登录页(验证码、密码登录、微信登录),左上角返回可跳过,不登录也能浏览。
29
+ - 打开后常弹整屏活动广告,底下有关闭按钮(资源 ID `close`,没有名字)。
30
+ - 第一次切到某些标签可能出引导提示(如「最近在学移到这里啦」),挡住点按,先点掉提示再切。
31
+ - 搜索框里的词在轮换,元素名跟着变,按元素点可能报元素已过期,按位置点即可。
32
+ - 顶部右边图标(积分、最近学习、设置)多数没有名字,只有资源 ID,如设置是 `settingImageView`。
33
+ - 底部标签在元素里看不出哪个被选中,要看画面。
@@ -0,0 +1,35 @@
1
+ ---
2
+ name: feishu
3
+ display: 飞书
4
+ description: 办公协作,即时通讯、日历、云文档和会议
5
+ packages: ["com.ss.android.lark"]
6
+ aliases: ["飞书", "Lark", "lark", "feishu"]
7
+ sites: ["feishu.cn", "larksuite.com"]
8
+ open: 飞书
9
+ pace: careful
10
+ ---
11
+ ## 是什么
12
+ 飞书是字节跳动的办公协作 App,包名 `com.ss.android.lark`。聊天、日历、云文档、视频会议、审批等都在里面;国际版叫 Lark,网页版在 `feishu.cn`。
13
+
14
+ ## 界面
15
+ 底部标签一般是「消息 / 日历 / 云文档 / 通讯录 / 工作台」(版本不同略有差异)。
16
+ - 消息:会话列表,顶部搜索,右上角「+」发起群聊、加好友、扫一扫。
17
+ - 通讯录:组织架构、部门、外部联系人。
18
+ - 云文档:我的文档、共享空间、知识库、最近访问。
19
+ - 工作台:审批、打卡、报销等企业自建应用。
20
+ - 日历:日程、会议室预订。
21
+ 顶部头像进「我的」设置。标签顺序和命名随企业配置与版本变化(待确认)。
22
+
23
+ ## 功能
24
+ - 聊天:单聊、群聊、话题群;输入框可发文字、表情、文件、图片,「+」更多面板里投票、日程、云文档卡片。
25
+ - 云文档:在线文档、表格、多维表格,可多人协同编辑。
26
+ - 会议:发起或加入视频会议,共享屏幕、录制。
27
+ - 日历:建日程、邀请参会人、看会议室。
28
+ - 工作台里是各企业接入的应用,入口因企业而不同。
29
+
30
+ ## 已知现象
31
+ - 首次登录要企业账号或手机号验证码,企业管理员可能限制登录方式。
32
+ - 消息里的「机器人」「应用通知」是自动消息,不是真人。
33
+ - 未读用红点和数字标出,群聊可设免打扰。
34
+ - 云文档在 App 内打开,复杂表格在手机上可能只显示部分列。
35
+ - 版本与企业配置不同,底部标签和工作台入口差别较大(具体机型待确认)。
@@ -0,0 +1,33 @@
1
+ ---
2
+ name: gmail
3
+ display: Gmail
4
+ description: 谷歌邮箱,收发邮件、按类别和标签整理
5
+ packages: ["com.google.android.gm"]
6
+ aliases: ["Gmail", "谷歌邮箱", "Google 邮箱", "gmail"]
7
+ sites: ["mail.google.com"]
8
+ open: Gmail
9
+ pace: careful
10
+ ---
11
+ ## 是什么
12
+ Gmail 是谷歌的邮件 App,包名 `com.google.android.gm`。除 Gmail 账号外,也能添加其他邮箱账号一起收。
13
+
14
+ ## 界面
15
+ 底部两个标签:「邮件」「会议」。
16
+ - 邮件:顶部左边是菜单按钮,中间搜索框,右边头像(账号和设置)。列表开头是当前收件箱名(如「主要」),下面是「推广」「社交」「动态」等类别汇总行,再是邮件;右下角「写邮件」。
17
+ - 抽屉:收件箱类别;「所有标签」下已加星标、已延后、重要邮件、已发送、已安排、发件箱、草稿、所有邮件、垃圾邮件、已删除邮件、管理订阅、创建标签及自建标签;「Google 应用」有日历、通讯录;最底下是「设置」「帮助和反馈」,要下滑才看得到。
18
+ - 会议:发起新会议、加入会议。
19
+
20
+ ## 功能
21
+ - 邮件列表每行是未读、发件人、主题、摘要,日期和星标单独一个元素。点发件人那头像只是选中这封,不是打开。
22
+ - 点顶部搜索框进入搜索,有返回、输入框和筛选(标签、发件人、收件人、附件)。
23
+ - 点头像弹出账号页:管理 Google 账号、切换账号、添加账号、存储空间用量。
24
+ - 设置从抽屉最底下进,第一层是常规设置、每个账号一行、添加帐号。
25
+
26
+ ## 已知现象
27
+ - 首次打开或更新后先后出现「Gmail 换新颜」介绍页(知道了)、管理邮箱地址页(转至 GMAIL)、系统通知权限询问(禁止/始终允许)、会议功能介绍卡(了解详情/知道了),列表顶上还有一张提示卡(关闭)。
28
+ - 系统通知权限弹窗读不到元素、返回键关不掉,只能点画面上的按钮。
29
+ - 首次进「会议」会弹「允许 Gmail 获取手机状态」(取消/授予权限),读不到元素。
30
+ - 账号页读不到元素,只能看画面。
31
+ - 抽屉或搜索页打开时,后面的邮件列表仍在元素列表里,抽屉项排在邮件后面。
32
+ - 在邮件列表按返回键会退出 App。
33
+ - 网页版 `mail.google.com`,未登录会跳到谷歌账号登录。
@@ -0,0 +1,31 @@
1
+ ---
2
+ name: jike
3
+ display: 即刻
4
+ description: 兴趣社区,圈子与动态
5
+ packages: ["com.ruguoapp.jike"]
6
+ aliases: ["即刻", "Jike", "jike"]
7
+ sites: ["okjike.com"]
8
+ open: 即刻
9
+ pace: careful
10
+ ---
11
+ ## 是什么
12
+ 即刻是兴趣社区 App,包名 `com.ruguoapp.jike`。用户按兴趣圈子和话题发布动态、评论互动,也有「圈子」和活动。
13
+
14
+ ## 界面
15
+ 底部标签一般是「首页 / 圈子 / 发布(+)/ 消息 / 我」(版本不同略有差异)。
16
+ - 首页:关注与推荐的动态流,顶部有搜索。
17
+ - 圈子:兴趣圈子列表与详情。
18
+ - 消息:评论、赞、关注、私信通知。
19
+ - 我:个人主页、动态、收藏。
20
+ 具体标签命名随版本变化(待确认)。
21
+
22
+ ## 功能
23
+ - 浏览:首页刷动态,点进单条看正文、图片和评论。
24
+ - 发布:底部「+」进编辑器,可发文字、图片、链接,选发到哪个圈子。
25
+ - 互动:动态下方有评论、转发、点赞、收藏。
26
+ - 搜索:顶部搜索框找圈子、用户和内容。
27
+
28
+ ## 已知现象
29
+ - 第一次打开先是「服务协议与隐私政策」弹窗,只有「不同意并退出」「同意」两个按钮,返回键关不掉;不点「同意」进不去 App。
30
+ - 未登录时只能浏览部分内容,互动会跳到登录。
31
+ - 动态里的外链在内置浏览器打开。
@@ -0,0 +1,34 @@
1
+ ---
2
+ name: kuaishou
3
+ display: 快手
4
+ description: 短视频、直播、私信和快手小店
5
+ packages: ["com.smile.gifmaker"]
6
+ aliases: ["快手", "Kuaishou", "kuaishou", "kwai"]
7
+ sites: ["kuaishou.com"]
8
+ open: 快手
9
+ pace: careful
10
+ ---
11
+ ## 是什么
12
+ 快手是短视频与直播 App,包名 `com.smile.gifmaker`。也有商城(快手小店)和私信。
13
+
14
+ ## 界面
15
+ 底部标签:首页、精选、中间「拍摄」、消息、我。
16
+ - 首页:顶部左边侧边栏按钮,中间频道(商城、关注、发现、同城、热门,右边编辑频道),最右「查找」;发现等频道是两列作品卡片。
17
+ - 精选:全屏竖屏视频,上下滑切换,右侧作者头像(关注)、点赞、评论、收藏、分享、音乐转盘,下方作者名和文案。
18
+ - 消息:上面常联系的人,下面新增粉丝、互动消息、私信会话,再往下「你可能感兴趣的人」。
19
+ - 我:资料、粉丝/关注/获赞;快手小店、常看的人、购物团、离线模式;作品、私密、推荐、收藏、赞;右上角搜索和侧边栏。
20
+
21
+ ## 功能
22
+ - 搜索:点首页右上角「查找」。顶部返回、输入框、「搜索」;下面历史搜索、搜索发现、想看的人(换一换),再往下热点、热搜人物、直播榜、购物榜。
23
+ - 首页侧边栏:扫一扫、快手小店、任务中心;系统消息;常用功能(历史记录、离线模式、设置、我的钱包、草稿箱);工具服务(官方客服、未成年人模式、内容偏好、稍后再看)。
24
+ - 「我」页侧边栏:我的钱包、我的群聊、购物车、二维码、扫一扫、分享主页、离线模式、稍后再看,底部管理主页、设置。
25
+ - 设置:账号(绑定手机号、账号与安全、隐私设置)、通用(通用设置、通知设置、播放设置、存储空间、深色模式)等。
26
+
27
+ ## 已知现象
28
+ - 打开后可能直接是全屏视频(精选),这时底部选中标签仍可能是「首页」,要看画面确认。
29
+ - 页面左上方常有红包挂件(带数字和关闭按钮),盖在内容上。
30
+ - 第一次进「消息」可能弹介绍群聊功能的提示,点「知道了」关掉。
31
+ - 系统消息不在「消息」标签,在首页侧边栏里。
32
+ - 首页侧边栏各项的可点元素名是「item_数字」,文字是旁边单独元素。
33
+ - 搜索输入框的元素名是框里预先显示的推荐词。
34
+ - 快手极速版是另一个包(`com.kuaishou.nebula`,待确认),与主包不同。
@@ -0,0 +1,33 @@
1
+ ---
2
+ name: linkedin
3
+ display: 领英
4
+ description: 职业社交与求职
5
+ packages: ["com.linkedin.android"]
6
+ aliases: ["领英", "LinkedIn", "linkedin", "Linkedin"]
7
+ sites: ["linkedin.com"]
8
+ open: LinkedIn
9
+ pace: careful
10
+ ---
11
+ ## 是什么
12
+ 领英(LinkedIn)是职业社交 App,包名 `com.linkedin.android`。用来维护职业档案、加人脉、看职位和行业动态;网页版在 `linkedin.com`。
13
+
14
+ ## 界面
15
+ 底部标签一般是「首页 / 人脉 / 发布(+)/ 通知 / 职位 / 消息 / 我」(版本不同略有差异)。
16
+ - 首页:动态流,顶部有搜索。
17
+ - 人脉:推荐连接、邀请管理。
18
+ - 职位:职位搜索与申请。
19
+ - 消息:站内私信。
20
+ - 我:个人档案、设置。
21
+ 具体标签命名随版本变化(待确认)。
22
+
23
+ ## 功能
24
+ - 浏览动态:首页刷关注的人和推荐内容,可点赞、评论、转发。
25
+ - 人脉:查看推荐、发送连接邀请、看对方档案。
26
+ - 职位:按关键词、地点搜职位,看详情并申请(部分会跳转到公司网站)。
27
+ - 消息:与联系人私信,InMail 可能需要会员。
28
+
29
+ ## 已知现象
30
+ - 没登录时打开是欢迎页:轮播介绍卡片、「使用邮箱登录」、「没有领英帐号?立即加入」。
31
+ - 欢迎页上可能先弹出谷歌的「登录 LinkedIn」底部面板(「继续以…的身份登录」),属于谷歌服务,读不到元素,右上角「×」关掉。
32
+ - 未登录能浏览部分内容,查看完整档案、加人脉、发消息会跳登录。
33
+ - 界面语言随系统,不一定是中文。