mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 10:24:02 +00:00
Merge branch 'main' into codex/fix-share-style-keys
This commit is contained in:
118 files changed
+18492
-593
No files matched your search
@@ -374,6 +374,15 @@ renderer, persistence or services. The facade retains panel visibility, share
|
||||
restore claims and render scheduling. Both controls are destroyed before the
|
||||
facade's asynchronous teardown can yield.
|
||||
|
||||
## Ordinary action buttons
|
||||
|
||||
`src/ui/actionButton.js` is a native, listener-free view helper used by Scene
|
||||
presentation and sharing-toolbar owners. It receives translated text and explicit
|
||||
presentation/accessibility properties. Feature controllers own action dispatch,
|
||||
state, persistence and cleanup. Static Scenes/CCTV templates use the same CSS
|
||||
surface and preserve IDs and layout hooks. The helper imports no application,
|
||||
renderer, storage or services; it belongs to the consuming package closures.
|
||||
|
||||
## Display controls
|
||||
|
||||
`ui/display` owns Display button, selector and slider subscriptions. It receives
|
||||
@@ -729,3 +738,32 @@ sources supply `{records, droppedCount, status, saturated}`; viewport filtering,
|
||||
exact-bound retry and rendering stay in the layer. Legacy cache saturation is
|
||||
decoded in the source. Source and geometry modules remain independent of Cesium,
|
||||
DOM and platform middleware.
|
||||
|
||||
### Native form fields
|
||||
|
||||
`src/ui/formField.js` constructs native numeric inputs without listeners or
|
||||
application state. Static selects and number inputs use the same `gev-field`
|
||||
surface, with explicit compact and inline densities. Feature owners retain
|
||||
option identity/order, bounds, parsing, draft values, input/change timing and
|
||||
teardown. CCTV effective-pose conversion and tuner/device operations remain
|
||||
feature responsibilities. A Vue replacement can reuse this contract and CSS;
|
||||
it replaces DOM construction, rather than adding a second state owner.
|
||||
|
||||
The shared stylesheet owns field surfaces and disabled opacity; feature and theme
|
||||
palettes use `--gev-field-background`, `--gev-field-border-color`,
|
||||
`--gev-field-color` and `--gev-field-disabled-opacity`. Radio retains its own
|
||||
compact density and arrow space. CCTV owns calibration editor width in
|
||||
`cctv.css`; the shared inline density does not impose a feature-specific width.
|
||||
Cyber supplies a shared-field palette explicitly and keeps its legacy native
|
||||
field rules separate, so Radio's palette remains an intentional exception.
|
||||
|
||||
### Read-only status badges
|
||||
|
||||
`src/ui/statusBadge.js` constructs/updates ordinary badges without listeners,
|
||||
status inference or live-region policy. It consumes translated text and controlled
|
||||
visibility; appearance variants share CSS rather than mapping machine states to
|
||||
universal severity. CCTV owns frame/source and calibration rules and their data
|
||||
attributes, while Weather owns coverage labels. The keyed rail-card owner keeps
|
||||
node identity, header focus, disclosure and teardown. The shared adapter never
|
||||
creates another state store or announces all card updates. A Vue view can replace
|
||||
this adapter and retain these presentation inputs and styles.
|
||||
+126
-8
@@ -35,6 +35,16 @@ time. This clears obsolete contacts and settles startup without manufacturing
|
||||
position timestamps. Stale, incomplete and malformed empty results retain the
|
||||
existing recovery behavior.
|
||||
|
||||
Every `/api` response on the dev and preview servers carries
|
||||
`Content-Security-Policy: default-src 'none'; sandbox` and
|
||||
`X-Content-Type-Options: nosniff`. `apiResponseHeadersPlugin` sets them ahead of
|
||||
the Host check and matches `/api` the way the router mounts it (any letter case, a
|
||||
`/` or `.` boundary, absolute-form targets), so errors, partial responses, Host
|
||||
refusals and unknown routes are covered too; a route's own policy is sent as an
|
||||
additional policy, never in place of it. The app document's policy is unchanged.
|
||||
The GBFS proxy relays only bodies that parse as JSON, re-serialized as
|
||||
`application/json; charset=utf-8`; anything else answers 502.
|
||||
|
||||
Catalog source contracts and their consuming layers are declared in
|
||||
`src/app/sourceComposition.js`. Omitted or null acquisition sources preserve layer
|
||||
registration and serialization, report unavailable, and are refused by the existing
|
||||
@@ -817,6 +827,15 @@ standalone entry supplies application-owned scene, ground and activation service
|
||||
Each layer owns its state and visibility listener; destruction cancels source
|
||||
reads and pending initialization. Malformed health responses retain prior health.
|
||||
Existing catalog fallback, camera poses, frame pacing and coverage controls remain.
|
||||
CCTV frames and the Street View fallback accept only JPEG, PNG, GIF, WebP and
|
||||
AVIF, sent under the canonical type; any other type falls through to the next
|
||||
fallback. Live media must match its feed kind (`video/mp4`, `video/webm`, or
|
||||
`multipart/x-mixed-replace` with a boundary) before health reports it connected,
|
||||
and follows redirects only on the camera's origin. Catalog image URLs, and
|
||||
redirects on those hosts, are pinned by parsed URL to the agency's image
|
||||
directory. Every `/api/cctv` route refuses cross-site browser requests but
|
||||
accepts forwarding headers, so cameras work behind a reverse proxy; a forwarded
|
||||
request skips the key-bearing Street View fallback and gets the placeholder.
|
||||
|
||||
Traffic owns its rendered-surface observer only while enabled, removes it on disable/destroy, and caches surface identity without allocating on unchanged frames.
|
||||
|
||||
@@ -1184,6 +1203,24 @@ snapshots, lifecycle actions and row descriptors. Remount and teardown remove
|
||||
listeners and row subscriptions; obsolete completions do not repaint old rows.
|
||||
The clear control presents busy state while its existing action owns the transaction.
|
||||
|
||||
## Sky background
|
||||
|
||||
`src/sky/starrySky.js` fills Cesium's `Scene#skyBox` slot with 9,096 Yale
|
||||
Bright Star Catalogue stars and a soft ESO/S. Brunier Milky Way. Both layers
|
||||
rotate from ICRF/J2000 into the Earth-fixed frame at the scene clock, with
|
||||
a TEME fallback while Cesium's IAU 2006 tables load. Bundled assets and
|
||||
their provenance are documented in `src/data/local_data/sky/README.md`.
|
||||
|
||||
Anime fades out the Milky Way with its style intensity to avoid cel-shaded
|
||||
bands; the catalogue stars remain. A separate black 1×1 cube map preserves
|
||||
model environment lighting independently of the visible sky. The adapter
|
||||
is validated against Cesium 1.138.0 and must be revalidated on upgrades.
|
||||
|
||||
`scripts/qa-anime-sky.mjs` checks asset readiness, visible Normal sky and
|
||||
Anime band coverage against a Vite dev server.
|
||||
`scripts/qa-sky-model-lighting.mjs` compares a lit `airplane.glb` against
|
||||
black and white environment maps in isolated scenes.
|
||||
|
||||
## Model atmosphere on Apple Metal
|
||||
|
||||
Cesium's per-vertex model atmosphere is kept out of the pipeline on devices
|
||||
@@ -1238,6 +1275,58 @@ Feature owners retain bounds, steps, formatted values, input/change timing and
|
||||
listener cleanup. The radio tuning dial, imagery comparison divider and event
|
||||
comparison/progression controls keep their specialized presentation and behavior.
|
||||
|
||||
## Shared control CSS ownership
|
||||
|
||||
Shared styles own ordinary control surfaces and interaction states; feature CSS
|
||||
owns surrounding layout and context-specific sizing. CCTV's calibration editor
|
||||
width lives in `ui/styles/cctv.css`, while the shared inline field variant owns
|
||||
only density and spinner treatment. Radio supplies its field palette and disabled
|
||||
opacity through the `--gev-field-*` variables, retaining compact typography and
|
||||
arrow space locally. Cyber supplies shared-field palette variables explicitly;
|
||||
its legacy native-field palette rules exclude `.gev-field`. These ownership
|
||||
boundaries preserve the current Tactical/Cyber appearance and native behavior.
|
||||
|
||||
## Ordinary status badges
|
||||
|
||||
CCTV source/frame labels, calibration provenance and Weather coverage labels use
|
||||
`ui/statusBadge.js` and the `gev-status-badge` CSS surface. The listener-free
|
||||
adapter accepts already-translated `label` and `hidden` values; pill, box and plain
|
||||
appearances describe shape/density only. Static CCTV markup uses the same classes
|
||||
as generated rail-card badges. Repeated identical updates do not rewrite text or
|
||||
replace nodes. Empty coverage remains hidden.
|
||||
|
||||
Feature owners retain the status rules, machine-state attributes, translations
|
||||
and announcement policy. CCTV frame acquisition (`idle/loading/error/ready`)
|
||||
remains separate from provider status: retained pixels do not imply a healthy
|
||||
feed. Calibration still distinguishes manually saved, catalog-curated and raw
|
||||
prior poses; unsaved edits override the label until save/reset. Coverage labels
|
||||
remain geographic scope, not health claims. Existing colors and the source
|
||||
badge's polite live region are preserved; coverage and calibration do not gain
|
||||
live regions. Interactive layer toggles, progress indicators and world overlays
|
||||
retain their specialized ownership. Vue can reuse the view contract and CSS while
|
||||
replacing DOM construction. Browser acceptance:
|
||||
`QA_BASE_URL=http://127.0.0.1:4189 node scripts/qa-status-badges.mjs`.
|
||||
|
||||
## Ordinary action buttons
|
||||
|
||||
Scene panel actions, shot LOAD/DEL actions, the EDIT DETAILS / SHARE SCENE
|
||||
bar and one-shot CCTV actions use `ui/actionButton.js` and the shared
|
||||
`gev-action-button` surface in `ui/styles/action-button.css`. Static templates
|
||||
apply the same classes as generated buttons. The native builder accepts translated
|
||||
text, default/danger variants, default/compact sizes and disabled/accessibility
|
||||
properties; it installs no listeners and owns no application state. Feature
|
||||
controllers retain callbacks, enable/disable rules, confirmation prompts,
|
||||
persistence and teardown. The smaller shot actions retain their existing sizing
|
||||
and hover treatment. Feature CSS still owns panel layout and translated wrapping.
|
||||
|
||||
CCTV enable, coverage, auto-hop, projection and adjustment toggles, editable
|
||||
calibration-value chips and the scene authoring dialogs retain their specialized
|
||||
controls. Existing `scene-btn` hooks remain compatible with Street Level and
|
||||
legacy toggles. The shared CSS, explicit input/action boundary and behavior tests
|
||||
can carry to a Vue view while Vue replaces native DOM construction.
|
||||
Browser acceptance: `QA_BASE_URL=http://127.0.0.1:4179 node scripts/qa-action-buttons.mjs`;
|
||||
`qa-scene-controls.mjs` also covers real Scene authoring/playback with native Space capture.
|
||||
|
||||
## Segmented selectors
|
||||
|
||||
Segmented selectors use the controlled DOM adapter in `ui/segmentedControl.js`
|
||||
@@ -2804,11 +2893,16 @@ down | auth-failed` (plus the unchanged `missing-key`/`unsupported`) with
|
||||
> first later successful fetch. Smaller chunks reduce timeout risk; complete
|
||||
> camera batches still wait for their sequential requests, and unresolved
|
||||
> placement continues to use the existing prior until real heights arrive.
|
||||
> - **Overpass cache admission:** `/api/overpass` parses and sanitizes requests,
|
||||
> then checks fresh memory, identical in-flight work, and fresh disk entries
|
||||
> before invoking its local 90/min limiter. Cache and single-flight responses
|
||||
> therefore do not spend quota; upstream-bound misses retain the existing
|
||||
> limiter, configured-upstream, stale, and sanitization behavior. An unconfigured transport serves dated stale data or a non-retryable capability error.
|
||||
> - **Overpass cache admission:** `/api/overpass` refuses cross-site and forwarded
|
||||
> POSTs through the shared local-request gate, then limits requests to 300/min
|
||||
> per socket peer and 900/min globally before reading or validating bodies.
|
||||
> Tag-filter brackets are scanned once; nested or unmatched brackets return 400.
|
||||
> It then checks fresh memory, identical in-flight work, and fresh disk entries
|
||||
> before invoking its separate local 90/min upstream limiter. Cache and
|
||||
> single-flight responses therefore do not spend upstream quota; upstream-bound
|
||||
> misses retain the existing limiter, configured-upstream, stale, and sanitization
|
||||
> behavior. An unconfigured transport serves dated stale data or a non-retryable
|
||||
> capability error.
|
||||
> - **CCTV world-click focus:** clicking an in-world CCTV icon or ambient card
|
||||
> activates it and routes the camera flight through the panel FOCUS policy.
|
||||
> Aircraft/satellite tracking releases outside cockpit; cockpit retains the
|
||||
@@ -3449,7 +3543,7 @@ test:track` 43 tracking invariants · headless QA harnesses under
|
||||
|
||||
### Interface localization (October 2026)
|
||||
|
||||
Shipped locales: **en** (source and fallback), **es** and **ru**. The code lives in
|
||||
Shipped locales: **en** (source and fallback), **es**, **ru** and **zh-CN**. The code lives in
|
||||
`src/i18n/`. How to mark UI text: [`docs/I18N.md`](./I18N.md); translator workflow:
|
||||
[`docs/TRANSLATORS.md`](./TRANSLATORS.md).
|
||||
|
||||
@@ -3460,7 +3554,8 @@ Shipped locales: **en** (source and fallback), **es** and **ru**. The code lives
|
||||
value). English has no catalog; every other locale is
|
||||
`src/i18n/locales/<code>.json`, and a missing entry falls back to English.
|
||||
- **Locale choice.** `?lang=` → stored choice (`gev:locale:v1`) →
|
||||
`navigator.languages` → English. `?lang=` is not stored, and share links drop
|
||||
`navigator.languages` → English. Chinese tags map to `zh-CN`; tags containing
|
||||
`Hant`, `TW`, `HK` or `MO` are skipped. `?lang=` is not stored, and share links drop
|
||||
it, so a recipient keeps their own language. The globe picker in the
|
||||
bottom-right corner (`src/ui/localePicker.js`) stores the choice, drops
|
||||
`?lang=` (keeps it only when storage is blocked) and reloads. It asks first
|
||||
@@ -4624,6 +4719,12 @@ Retry-After; absent delays back off from 30 seconds to five minutes. Empty
|
||||
remain. Malformed capability-probe responses remain unknown and are retried after the existing 30-second backoff; valid configured decisions remain memoized.
|
||||
Consumer capability misses never schedule automatic retries.
|
||||
|
||||
Keyless browser validation also probes the optional Google tiles-token route.
|
||||
The token client cancels rejected response bodies before returning unavailable,
|
||||
so they do not remain pending in browser network observation. The Overpass gate
|
||||
accepts only that same-origin route's expected 404 console diagnostic; other
|
||||
HTTP and JavaScript errors still fail acceptance.
|
||||
|
||||
Operator-configured Overpass area and focus-footprint queries use body-level
|
||||
`out geom` (with `center` for focus), preserving relation member outlines.
|
||||
Member geometry is printed only inside a box around the point (6 km for
|
||||
@@ -5072,7 +5173,7 @@ pins and share links already supply complete boxes.
|
||||
- Fleet model eligibility is distance-based with on-screen priority and hard caps (`MODEL_MAX`, `MODEL_MAX_ALL`) to avoid draw-call explosions. Each model owns its own `modelMatrix`; shared scratch matrices are forbidden because they caused stacking/flicker.
|
||||
- Tracked aircraft use standalone model primitives driven from the already-settled dead-reckoned display position, while the tracked Cesium entity remains billboard-backed so `viewer.trackedEntity` always has a ready bounding sphere.
|
||||
- Flights and military layers mirror the same tracking invariants: no warm-up freeze/jump, altitude-scaled framing, trail head glued to the displayed plane, no pull-out when switching targets, and no cross-layer orphan when switching between commercial and military tracks.
|
||||
- Regression surface: `npm run test:track` drives the real app headless with synthetic aircraft feeds and asserts the tracking invariants without depending on live OpenSky/adsb data. `src/data/trackedModelRegime.test.mjs` pins the tracked contact's threshold math, the enter/exit asymmetry, and the default-on / cockpit / TR-3B / deselect wiring in both layers.
|
||||
- Regression surface: `npm run test:track` drives the real app headless with synthetic aircraft feeds and asserts the tracking invariants without depending on live OpenSky/adsb data. Arrival-rotation checks observe the first reveal within a bounded wall-clock window before the one-second idle fallback, rather than assuming the 80 ms fleet cadence fits inside four rendered frames; an incorrect first orientation fails immediately. `src/data/trackedModelRegime.test.mjs` pins the tracked contact's threshold math, the enter/exit asymmetry, and the default-on / cockpit / TR-3B / deselect wiring in both layers.
|
||||
|
||||
### TR-3B conversion Easter egg (August 2026)
|
||||
|
||||
@@ -5943,3 +6044,20 @@ datacenters, dams and the Nepal locator retain that shared credit while displaye
|
||||
|
||||
Military fragments stitch by source identity. Different mapped parcels merge only
|
||||
when their footprints touch or contain one another, never across a seam tolerance gap.
|
||||
|
||||
### Shared native dropdowns and numeric fields
|
||||
|
||||
- Scene and CCTV selects share the default `gev-field` surface. HUD layout and
|
||||
draw colour retain compact density. Radio filter, tuner gain and FM frequency
|
||||
use the same base while retaining their feature-specific skins and layout.
|
||||
- The CCTV inline number editor uses `createNumberInput` with its existing
|
||||
precision and inline density. Enter/blur commit, Escape cancellation, frozen
|
||||
camera base, camera-switch guards and disposal remain with CCTV controls.
|
||||
- Options, values, native keyboard/typeahead, disabled attributes and browser
|
||||
validity remain native. Frequency bounds, tuner commit timing and calibration
|
||||
parsing are unchanged. Specialized tuner graphics and calibration chips
|
||||
retain their own controls. Provider settings and scene-authoring dialogs are
|
||||
outside this change.
|
||||
- `scripts/qa-form-fields.mjs` exercises native selections, number validity,
|
||||
calibration commit/cancel and stale-camera/disposal guards against an installed
|
||||
controller with fixture ports, plus default/Cyber and narrow translated layouts.
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
# Translating God's Eye View
|
||||
|
||||
Shipped languages: **English** (source and fallback), **Spanish** (`es`) and **Russian** (`ru`).
|
||||
Shipped languages: **English** (source and fallback), **Spanish** (`es`), **Russian** (`ru`) and **Simplified Chinese** (`zh-CN`).
|
||||
|
||||
## How it works
|
||||
|
||||
@@ -63,4 +63,4 @@ These are contracts, not copy: layer ids and registry keys, status enums and oth
|
||||
|
||||
## Language notes
|
||||
|
||||
Each language keeps its glossary, plural forms, units and style in its own file, `docs/translations/<code>.md`: [Spanish](./translations/es.md), [Russian](./translations/ru.md). Read it before translating, and add a term there when you settle on one.
|
||||
Each language keeps its glossary, plural forms, units and style in its own file, `docs/translations/<code>.md`: [Spanish](./translations/es.md), [Russian](./translations/ru.md), [Simplified Chinese](./translations/zh-CN.md). Read it before translating, and add a term there when you settle on one.
|
||||
@@ -0,0 +1,77 @@
|
||||
# Simplified Chinese (`zh-CN`)
|
||||
|
||||
Catalog: `src/i18n/locales/zh-CN.json`. General rules: [TRANSLATORS.md](../TRANSLATORS.md).
|
||||
|
||||
Translation sources: abiyeenzo (#914) and EDIT-Aeterna (#979).
|
||||
|
||||
## Style
|
||||
|
||||
- Mainland usage and Simplified characters. Address the user neutrally, without 您/你 where a plain imperative works: 「点击地图」, 「重试」.
|
||||
- Chinese has no case: an UPPERCASE English HUD label becomes the same short Chinese label. Keep labels as short as the English: 「实时」, 「过期」, 「关」.
|
||||
- Full-width punctuation in Chinese text: ,。:;?!()“”. A dash is 「——」 without spaces; keep `·` as the HUD separator and `…` for ellipsis.
|
||||
- One space between Chinese and Latin letters or digits: 「AIS 船舶」, 「24 小时」, 「{count} 个」. No space next to full-width punctuation.
|
||||
- Units: km, m, km/h, m/s, kn, ft, MW, °, % stay as written; time words are 小时, 分钟, 秒 after a number (「5 分钟前」).
|
||||
- Product names, provider names and codes stay as they are: Google, Cesium, CelesTrak, NOAA, FIRMS, AIS, ADS-B, GNSS, CCTV, HUD, CRT, NVG, FLIR, WHOT/BHOT, Ironbow, CONUS.
|
||||
|
||||
## Plurals
|
||||
|
||||
`Intl.PluralRules('zh-CN')` has one category, `other`: a `tn()` entry has only that form. Use a measure word next to the number where Chinese needs one: 「{count} 个密钥」, 「{count} 架飞机」, 「{count} 艘船」.
|
||||
|
||||
## Glossary
|
||||
|
||||
| English | 中文 |
|
||||
| ------------------------------------- | --------------------------- |
|
||||
| layer / data layer | 图层 / 数据图层 |
|
||||
| feed | 数据源 |
|
||||
| source / data source | 来源 / 数据源 |
|
||||
| LIVE (status) / live data | 实时 / 实时数据 |
|
||||
| SIMULATED | 模拟 |
|
||||
| stale / degraded / unavailable | 过期 / 降级 / 不可用 |
|
||||
| retry | 重试 |
|
||||
| key (API key) / POWER UP | 密钥(API 密钥)/ 增强 |
|
||||
| Provider Settings | 服务商设置 |
|
||||
| globe / map / map source / basemap | 地球 / 地图 / 地图源 / 底图 |
|
||||
| aircraft / flight / military flights | 飞机 / 航班 / 军用航班 |
|
||||
| vessel, ship | 船舶 |
|
||||
| satellite | 卫星 |
|
||||
| launch (rocket) / space mission | 发射 / 太空任务 |
|
||||
| contact (tracked object) | 目标 |
|
||||
| installation, site | 设施 |
|
||||
| camera / CCTV camera | 摄像头 / CCTV 摄像头 |
|
||||
| earthquake / active fire | 地震 / 活跃火点 |
|
||||
| scene / shot | 场景 / 镜头 |
|
||||
| briefing / panel / dock | 简报 / 面板 / 停靠栏 |
|
||||
| preset / visual preset | 预设 / 视觉预设 |
|
||||
| Display / HUD layout | 显示 / HUD 布局 |
|
||||
| Tactical / Operator / Minimal / Cyber | 战术 / 操作员 / 精简 / 赛博 |
|
||||
| Scope (circular viewport mask) / keyhole | 视域 |
|
||||
| Clean UI | 纯净界面 |
|
||||
| cockpit | 座舱 |
|
||||
| heading / altitude / ground speed | 航向 / 高度 / 地速 |
|
||||
| map heading / North up | 方位 / 正北朝上 |
|
||||
| Street Level / Street View (Google) | 街景 / 街景(Google) |
|
||||
| Recent Imagery | 近期影像 |
|
||||
| Global Context / Context (panel) | 全局态势 / 态势 |
|
||||
| radio (station) | 电台 |
|
||||
| transit / bikeshare | 公共交通 / 共享单车 |
|
||||
| Previous / Next | 上一个 / 下一个 |
|
||||
| compass points (N, NNE, …) | 北, 北东北, … |
|
||||
| weather field / FIELD (selector) | 气象场 / 要素 |
|
||||
| weather model / forecast lead hours | 模式 / 预报时效 |
|
||||
| valid (forecast time) | 有效时间 |
|
||||
| scene cloud / mosaic | 整景云量 / 镶嵌图 |
|
||||
| pin (Recent Imagery) | 固定 |
|
||||
| THIS (voice pointer) | 所指 |
|
||||
| outline / trace an outline | 轮廓 / 绘制轮廓 |
|
||||
| mark (map annotation) | 标注 |
|
||||
| camera badge | 摄像头标记 |
|
||||
| provider / embedded provider controls | 服务商 / 平台控件 |
|
||||
| share (a view or link) | 分享 |
|
||||
| AI agent | AI 智能体 |
|
||||
| stage (rocket) / downrange | 子级 / 航程 |
|
||||
| capture shot / camera move | 保存镜头 / 运镜 |
|
||||
| story beat / evidence beat | 事件节点 / 证据节点 |
|
||||
| camera pose | 位姿 |
|
||||
| forecast uncertainty cone | 预报不确定范围 |
|
||||
| seed (catalog data) | 预置 |
|
||||
| frame (bring into view) | 将…纳入视野 |
|
||||
Reference in new issue
Block a user