feat: 统一 Commilitia Drop 全客户端命名与分发
This commit is contained in:
+1
-1
@@ -6,7 +6,7 @@
|
||||
传输引擎。仅由原生 iOS 壳的离屏 WKWebView 从安全源(https)加载;原生须在本
|
||||
模块执行前经 WKUserScript 注入 window.__CDROP_BOOT__(session / device_name /
|
||||
api_base / device_type:"ios"),见 src/engine/main.ts。 -->
|
||||
<title>cdrop engine</title>
|
||||
<title>Commilitia Drop</title>
|
||||
</head>
|
||||
<body>
|
||||
<script type="module" src="/src/engine/main.ts"></script>
|
||||
|
||||
+2
-2
@@ -19,8 +19,8 @@
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
|
||||
<meta name="apple-mobile-web-app-title" content="cdrop" />
|
||||
<meta name="application-name" content="cdrop" />
|
||||
<meta name="apple-mobile-web-app-title" content="Commilitia Drop" />
|
||||
<meta name="application-name" content="Commilitia Drop" />
|
||||
<!-- 预取品牌 logo:登录跳转回来后首页 header 立即用到;早取 + 后端一周缓存,
|
||||
避免那一刻才发起请求导致的闪烁重载。 -->
|
||||
<link rel="preload" as="image" href="/logo-mark.png" />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "/",
|
||||
"name": "Commilitia Drop",
|
||||
"short_name": "cdrop",
|
||||
"short_name": "Commilitia Drop",
|
||||
"description": "跨设备剪贴板同步与点对点文件传输",
|
||||
"lang": "zh-CN",
|
||||
"start_url": "/",
|
||||
|
||||
+1
-1
@@ -72,7 +72,7 @@ self.addEventListener("push", (event) =>
|
||||
try { data = event.data ? event.data.json() : {}; }
|
||||
catch (_e) { data = {}; }
|
||||
|
||||
const title = data.title || "cdrop";
|
||||
const title = data.title || "Commilitia Drop";
|
||||
const options = {
|
||||
body: data.body || "",
|
||||
tag: data.tag || undefined, // same tag replaces a stale notification in place
|
||||
|
||||
@@ -179,7 +179,7 @@ function subscribeStore(): void
|
||||
});
|
||||
}
|
||||
|
||||
// handleSendFile:原生把待发文件经 payload.url(cdrop-file://<id>)暴露。R-iOS-4:用
|
||||
// handleSendFile:原生把待发文件经 payload.url(commilitia-drop-file://<id>)暴露。R-iOS-4:用
|
||||
// bridgeFileSource 经桥按块取片(原生据 [start,end) seek 文件、回 base64),整文件永不整体进
|
||||
// WebView 内存——大文件不再有 jetsam 风险,传输层 p2p / relay 透明复用。改走桥而非跨 origin
|
||||
// fetch,绕开自定义 scheme 的 CORS 拦截(否则发送在读文件即失败)。
|
||||
@@ -520,7 +520,7 @@ function boot(): void
|
||||
{
|
||||
// 非 iOS 壳(误加载 engine.html)——保持惰性,不触发任何网络 / 引擎行为。
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn("cdrop engine: not running inside the iOS shell, idle");
|
||||
console.warn("Commilitia Drop engine: not running inside the iOS shell, idle");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import type { FileSource } from "./source";
|
||||
// - iceServers: pulled from lib/iceServers (Cloudflare Realtime TURN over
|
||||
// TLS when CDROP_CF_TURN_* is configured; STUN-only fallback otherwise).
|
||||
// Refreshed on login by RootLayout.
|
||||
// - DataChannel "cdrop-file", ordered:true
|
||||
// - DataChannel "commilitia-drop-file", ordered:true
|
||||
// - chunk size 64 KiB, backpressure thresholds 16 MiB / 4 MiB
|
||||
// - 接收端流式写 OPFS(lib/incomingSink),避免 iOS Safari 内存压力
|
||||
// - control frames as JSON strings (head meta + tail done), payload bytes binary
|
||||
@@ -36,7 +36,7 @@ import type { FileSource } from "./source";
|
||||
// Same-LAN Restricted Cone NAT 排查依据:iceCandidatePoolSize=4 预热候选;
|
||||
// 收集本/远端 host/mdns/srflx/prflx/relay 计数 + 选中候选对类型推到 store,
|
||||
// 让 UI 暴露"实际通过哪条路径连上"(host:host = 真直连,relay:* = 走了 TURN)。
|
||||
const CHANNEL_NAME = "cdrop-file";
|
||||
const CHANNEL_NAME = "commilitia-drop-file";
|
||||
const CHUNK_SIZE = 64 * 1024;
|
||||
const HIGH_WATERMARK = 16 * 1024 * 1024;
|
||||
const LOW_WATERMARK = 4 * 1024 * 1024;
|
||||
@@ -971,7 +971,7 @@ export function p2pStartOutgoing(
|
||||
{
|
||||
return nativeStartOutgoing(sessionId, receiverName, src.path, src.size);
|
||||
}
|
||||
// iOS 无头壳:源带 cdrop-file://<id> 引用(path)即走 libwebrtc 原生数据面(Swift 侧解析回沙盒
|
||||
// iOS 无头壳:源带 commilitia-drop-file://<id> 引用(path)即走 libwebrtc 原生数据面(Swift 侧解析回沙盒
|
||||
// 绝对路径直接读盘)。IOS_NATIVE 关闭时回退下方 JS Session(WebKit WebRTC)。
|
||||
if (IOS_NATIVE && isIOSShell() && src.path)
|
||||
{
|
||||
|
||||
@@ -235,7 +235,7 @@ function register(s: NativeSess): void
|
||||
idByPeer.set(s.peerName, s.sessionId);
|
||||
}
|
||||
|
||||
// nativeIosStartOutgoing 经 Go 引擎发送 filePath(cdrop-file://<id> 引用,原生解析回沙盒绝对
|
||||
// nativeIosStartOutgoing 经 Go 引擎发送 filePath(commilitia-drop-file://<id> 引用,原生解析回沙盒绝对
|
||||
// 路径)到 peerName。total 用于进度事件的分母(store 的 bytesTransferred 仍是 UI 真值源)。
|
||||
export function nativeIosStartOutgoing(
|
||||
sessionId: string, peerName: string, filePath: string, total: number,
|
||||
|
||||
@@ -35,7 +35,7 @@ export function fileSource(file: File): FileSource
|
||||
|
||||
// rangeSource:经 HTTP Range 向原生 WKURLSchemeHandler 惰性拉取文件片(iOS 大文件流式发送)。
|
||||
// 每次 slice 只取 [start, end) 一段,WebView 常驻内存上限即单块大小(p2p 的
|
||||
// READ_BLOCK_SIZE = 4 MiB)。url 形如 `cdrop-file://<id>`;原生据 Range 头 seek 文件、
|
||||
// READ_BLOCK_SIZE = 4 MiB)。url 形如 `commilitia-drop-file://<id>`;原生据 Range 头 seek 文件、
|
||||
// 回 206 Partial Content 仅含该区间字节。
|
||||
export function rangeSource(
|
||||
url: string,
|
||||
|
||||
@@ -123,7 +123,7 @@ export const enUS: Partial<TranslationDict> = {
|
||||
"qr.show.nameHint": "Shown to your other devices. ASCII characters only.",
|
||||
"qr.show.generate": "Generate code",
|
||||
"qr.show.scanTitle": "Scan to approve",
|
||||
"qr.show.howto1": "Open the camera or cdrop on another signed-in device.",
|
||||
"qr.show.howto1": "Open the camera or Commilitia Drop on another signed-in device.",
|
||||
"qr.show.howto2": "Scan the code above and approve this device.",
|
||||
"qr.show.waiting": "Waiting for approval…",
|
||||
"qr.show.approved": "Approved — signing you in…",
|
||||
@@ -225,11 +225,11 @@ export const enUS: Partial<TranslationDict> = {
|
||||
"notify.transfer.failedTitle": "Transfer failed",
|
||||
"settings.account.title": "Account",
|
||||
"settings.account.signOut": "Sign out",
|
||||
"settings.desktop.title": "Desktop",
|
||||
"settings.desktop.title": "App settings",
|
||||
"settings.desktop.clipboardSync": "Auto-sync clipboard",
|
||||
"settings.desktop.clipboardSyncHint": "Copies are uploaded to the cloud, and clipboard updates from your other devices are applied here.",
|
||||
"settings.desktop.launchAtLogin": "Launch at login",
|
||||
"settings.desktop.launchAtLoginHint": "Start cdrop in the background after you sign in (lives in the menu bar).",
|
||||
"settings.desktop.launchAtLoginHint": "Start Commilitia Drop in the background after you sign in (lives in the menu bar or system tray).",
|
||||
"settings.desktop.downloadDir": "Download folder",
|
||||
"settings.desktop.downloadDirHint": "Received files are saved here. Leave unset to use the system Downloads folder.",
|
||||
"settings.desktop.downloadDirChoose": "Change…",
|
||||
@@ -344,7 +344,7 @@ export const enUS: Partial<TranslationDict> = {
|
||||
"errors.messageOverflow": "Message exceeds 4 KB; send a file instead",
|
||||
"errors.noReceiver": "No receiver selected",
|
||||
"errors.devTokenMissing":
|
||||
"Dev mode: VITE_CDROP_DEV_TOKEN is not set in .env.local",
|
||||
"Dev mode: the development token is not configured in .env.local",
|
||||
"errors.noAccessToken": "No access token; user must log in",
|
||||
"errors.clipboardUnavailable": "Browser clipboard API unavailable (requires HTTPS + permission)",
|
||||
"errors.clipboardOverflow": "Content too large; exceeds {{max}} byte limit",
|
||||
|
||||
@@ -120,7 +120,7 @@ export const zhCN = {
|
||||
"qr.show.nameHint": "此名称会展示给你的其他设备,仅可使用 ASCII 字符。",
|
||||
"qr.show.generate": "生成二维码",
|
||||
"qr.show.scanTitle": "用手机扫码批准",
|
||||
"qr.show.howto1": "在另一台已登录的设备上打开相机或 cdrop。",
|
||||
"qr.show.howto1": "在另一台已登录的设备上打开相机或 Commilitia Drop。",
|
||||
"qr.show.howto2": "扫描上方二维码,按提示批准此设备。",
|
||||
"qr.show.waiting": "等待批准…",
|
||||
"qr.show.approved": "已批准,正在进入…",
|
||||
@@ -221,11 +221,11 @@ export const zhCN = {
|
||||
"notify.transfer.failedTitle": "传输失败",
|
||||
"settings.account.title": "账号",
|
||||
"settings.account.signOut": "退出登录",
|
||||
"settings.desktop.title": "桌面",
|
||||
"settings.desktop.title": "应用设置",
|
||||
"settings.desktop.clipboardSync": "剪贴板自动同步",
|
||||
"settings.desktop.clipboardSyncHint": "复制即上传到云端,并接收其他设备的剪贴板更新。",
|
||||
"settings.desktop.launchAtLogin": "开机自启",
|
||||
"settings.desktop.launchAtLoginHint": "登录系统后自动在后台启动 cdrop(菜单栏常驻)。",
|
||||
"settings.desktop.launchAtLoginHint": "登录系统后自动在后台启动 Commilitia Drop(常驻菜单栏或系统托盘)。",
|
||||
"settings.desktop.downloadDir": "下载目录",
|
||||
"settings.desktop.downloadDirHint": "接收到的文件保存到此目录;留空则使用系统下载目录。",
|
||||
"settings.desktop.downloadDirChoose": "更改…",
|
||||
@@ -340,7 +340,7 @@ export const zhCN = {
|
||||
"errors.messageOverflow": "消息超过4 KB;请改用文件传输",
|
||||
"errors.noReceiver": "未选择接收方",
|
||||
"errors.devTokenMissing":
|
||||
"Dev模式:未在.env.local设置VITE_CDROP_DEV_TOKEN",
|
||||
"Dev 模式:未在 .env.local 配置开发令牌",
|
||||
"errors.noAccessToken": "无访问令牌:用户必须先登录",
|
||||
"errors.clipboardUnavailable": "浏览器不支持剪贴板API(需HTTPS与权限)",
|
||||
"errors.clipboardOverflow": "内容过大,超过 {{max}} 字节上限",
|
||||
|
||||
@@ -124,7 +124,7 @@ export const zhTW: Partial<TranslationDict> = {
|
||||
"qr.show.nameHint": "此名稱會顯示給你的其他裝置,僅可使用 ASCII 字元。",
|
||||
"qr.show.generate": "產生 QR 碼",
|
||||
"qr.show.scanTitle": "用手機掃碼批准",
|
||||
"qr.show.howto1": "在另一部已登入的裝置上開啟相機或 cdrop。",
|
||||
"qr.show.howto1": "在另一部已登入的裝置上開啟相機或 Commilitia Drop。",
|
||||
"qr.show.howto2": "掃描上方 QR 碼,依提示批准此裝置。",
|
||||
"qr.show.waiting": "等待批准…",
|
||||
"qr.show.approved": "已批准,正在進入…",
|
||||
@@ -225,11 +225,11 @@ export const zhTW: Partial<TranslationDict> = {
|
||||
"notify.transfer.failedTitle": "傳輸失敗",
|
||||
"settings.account.title": "帳號",
|
||||
"settings.account.signOut": "登出",
|
||||
"settings.desktop.title": "桌面",
|
||||
"settings.desktop.title": "應用程式設定",
|
||||
"settings.desktop.clipboardSync": "剪貼簿自動同步",
|
||||
"settings.desktop.clipboardSyncHint": "複製後即上傳雲端,並接收其他裝置的剪貼簿更新。",
|
||||
"settings.desktop.launchAtLogin": "開機自動啟動",
|
||||
"settings.desktop.launchAtLoginHint": "登入系統後自動在背景啟動 cdrop(常駐選單列)。",
|
||||
"settings.desktop.launchAtLoginHint": "登入系統後自動在背景啟動 Commilitia Drop(常駐選單列或系統匣)。",
|
||||
"settings.desktop.downloadDir": "下載資料夾",
|
||||
"settings.desktop.downloadDirHint": "接收到的檔案會儲存至此資料夾;留空則使用系統下載資料夾。",
|
||||
"settings.desktop.downloadDirChoose": "變更…",
|
||||
@@ -344,7 +344,7 @@ export const zhTW: Partial<TranslationDict> = {
|
||||
"errors.messageOverflow": "訊息超過4 KB;請改用檔案傳輸",
|
||||
"errors.noReceiver": "未選擇接收方",
|
||||
"errors.devTokenMissing":
|
||||
"Dev模式:未在.env.local設定VITE_CDROP_DEV_TOKEN",
|
||||
"Dev 模式:未在 .env.local 設定開發權杖",
|
||||
"errors.noAccessToken": "無存取權杖:使用者必須先登入",
|
||||
"errors.clipboardUnavailable": "瀏覽器不支援剪貼簿API(需HTTPS與權限)",
|
||||
"errors.clipboardOverflow": "內容過大,超過 {{max}} 位元組上限",
|
||||
|
||||
+3
-3
@@ -196,7 +196,7 @@ export async function abortIncomingDownloadIOS(sessionId: string): Promise<void>
|
||||
const BRIDGE_SLICE_MAX = 512 * 1024;
|
||||
|
||||
// readFileSliceIOS:经桥让原生按 [start, end) seek 读暂存的待发文件、回 base64,再解回字节。
|
||||
// 取代原先「fetch(cdrop-file://) + Range」——引擎在 https origin 下跨 origin fetch 自定义 scheme
|
||||
// 取代原先「fetch(commilitia-drop-file://) + Range」——引擎在 https origin 下跨 origin fetch 自定义 scheme
|
||||
// 被 CORS 拦死(Range 头触发预检、scheme handler 无 CORS 头)→ 发送在读文件即失败。改走桥与
|
||||
// 接收落盘同形,绕开 CORS;整文件仍永不整体进 WebView 内存(按需取片)。
|
||||
async function readFileSliceIOS(url: string, start: number, end: number): Promise<Uint8Array<ArrayBuffer>>
|
||||
@@ -214,7 +214,7 @@ export function bridgeFileSource(url: string, name: string, size: number, type:
|
||||
name,
|
||||
size,
|
||||
type: type || "application/octet-stream",
|
||||
// path 带 cdrop-file://<id> 引用:iOS 原生数据面(gomobile/pion)据此让原生侧解析回沙盒
|
||||
// path 带 commilitia-drop-file://<id> 引用:iOS 原生数据面据此让原生侧解析回沙盒
|
||||
// 绝对路径、由 Go 直接读盘发送(见 p2pIos.ts / EngineController.p2pStartOutgoing)。JS 收发
|
||||
// 路径不读 path,故对回退到 JS 引擎的传输无影响(与桌面 nativeFileSource 同范式)。
|
||||
path: url,
|
||||
@@ -246,7 +246,7 @@ export function bridgeFileSource(url: string, name: string, size: number, type:
|
||||
// 四个入口走 callNative(RPC,原生回 resolve);进度 / 状态 / 出站信令 / 落盘 / 候选对经
|
||||
// onNativeEvent 反向回来。原生侧契约见 ios/CDrop/Sources/Engine/EngineController.swift。
|
||||
|
||||
// nativeP2PStartOutgoing:发起原生发送。filePath 为 cdrop-file://<id> 引用,原生解析回沙盒
|
||||
// nativeP2PStartOutgoing:发起原生发送。filePath 为 commilitia-drop-file://<id> 引用,原生解析回沙盒
|
||||
// 绝对路径后交 Go 直接读盘(不经 base64 桥 / 不整文件进内存)。
|
||||
export async function nativeP2PStartOutgoing(
|
||||
sessionId: string, peerName: string, filePath: string, iceServersJSON: string,
|
||||
|
||||
@@ -262,7 +262,7 @@ function suggestDeviceName(): string
|
||||
else if (ua.includes("Chrome/")) { browser = "Chrome"; }
|
||||
else if (ua.includes("Safari/")) { browser = "Safari"; }
|
||||
|
||||
let os = "Desktop";
|
||||
let os = "Computer";
|
||||
if (ua.includes("Mac")) { os = "macOS"; }
|
||||
else if (ua.includes("Windows")) { os = "Windows"; }
|
||||
else if (ua.includes("Linux")) { os = "Linux"; }
|
||||
|
||||
@@ -104,7 +104,7 @@ function suggestDefault(): string
|
||||
else if (ua.includes("Chrome/")) { browser = "Chrome"; }
|
||||
else if (ua.includes("Safari/")) { browser = "Safari"; }
|
||||
|
||||
let os = "Desktop";
|
||||
let os = "Computer";
|
||||
if (ua.includes("Mac")) { os = "macOS"; }
|
||||
else if (ua.includes("Windows")) { os = "Windows"; }
|
||||
else if (ua.includes("Linux")) { os = "Linux"; }
|
||||
|
||||
@@ -31,7 +31,7 @@ function StyleGuide()
|
||||
<Container size="lg" py="lg">
|
||||
<Stack gap="lg">
|
||||
<Group justify="space-between" align="baseline">
|
||||
<Title order={3} fw={600}>cdrop · UI 原子组件总览</Title>
|
||||
<Title order={3} fw={600}>Commilitia Drop · UI 原子组件总览</Title>
|
||||
<Group gap="xs">
|
||||
<Text size="xs" c="dimmed">当前主题:</Text>
|
||||
<Tabs<ThemeMode>
|
||||
|
||||
Reference in New Issue
Block a user