Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
0fec9f1
refactor: 初步完成重构游离的playerConfig + 启动构架
apades Apr 11, 2026
0cca365
fix: 一些bug
apades Apr 21, 2026
5a920d3
feat: add additional STUN servers for improved WebRTC connectivity
apades Apr 21, 2026
986d2aa
feat: add debug information display in VideoPlayerV2 for development …
apades Apr 21, 2026
0812e20
feat: enhance video encoding capabilities in WebRTC with adjustable b…
apades Apr 21, 2026
11cbdc5
feat: introduce dynamic video bitrate suggestion for WebRTC based on …
apades Apr 21, 2026
adff844
feat: implement user activation check for PIP functionality and enhan…
apades Apr 21, 2026
0d4b605
fix: handleStartPIP not correct from data
apades Apr 21, 2026
c445b7d
refactor: 优化注入画中画API的效果,对原生播放器的画中画相关逻辑进行兼容处理
apades Apr 21, 2026
5bb6e35
feat: add 'entry-inject-top' to NEED_PAGE_RELOAD for enhanced injecti…
apades Apr 21, 2026
d2f8740
fix: ensure container class reflects media play state by removing 'pa…
apades Apr 21, 2026
7f6fdc0
fix: update video pause logic to consider document visibility state w…
apades Apr 21, 2026
8c140a1
feat: integrate new PIP window offset configuration and enhance local…
apades Apr 22, 2026
1f3ac26
refactor: reorganize configuration settings by moving main settings t…
apades Apr 22, 2026
dd6e530
feat: add @apades/logger package with core logging functionality
apades Apr 24, 2026
c244b80
feat: enhance logger functionality with persistent entry handling and…
apades Apr 26, 2026
6ff8b85
fix: update logger documentation references and improve type handling…
apades Apr 26, 2026
e9283f6
1
apades Apr 28, 2026
505578a
1
apades May 4, 2026
141d8da
完成 adapter 和 injection packages, 并接入主dev脚本
apades May 14, 2026
0fc8e8b
refactor: 重构到可用状态
apades May 18, 2026
e4c4e82
chore: update nodemon configuration schema and adjust package scripts…
apades May 18, 2026
ae114d9
refactor: simplify client setup logic and improve type definitions fo…
apades May 18, 2026
0ef3b56
e2e: add packages/injection
apades May 18, 2026
e483b7a
refactor: 优化adapter打包 + 读取config.json
apades May 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .cursor/commands/translate-with-context.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# 根据上下文翻译

根据上下文翻译成英文
14 changes: 14 additions & 0 deletions .cursor/rules/adapter-plugin-system.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
description: Reuse adapter user script workflow prompt
globs: packages/adapter/**/*
alwaysApply: false
---

# Adapter Workflow

When working in `packages/adapter`, read `packages/adapter/prompt.md` first and follow it as the task checklist.

- Keep each site adapter in a standalone `official/*.ts` file.
- Each site adapter must export `regexSite`.
- Keep permissions declarations aligned with runtime setup calls.
- Regenerate `official/generated-registry.ts` after script changes.
7 changes: 7 additions & 0 deletions .cursor/rules/logger.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
description: @apades/logger 约定(见 packages/logger/prompt.md)
globs: packages/logger/**
alwaysApply: false
---

Follow the file `packages/logger/prompt.md`
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ assets/temp.mp4
.turbo
.next
.vercel
.temp

# misc
.DS_Store
Expand Down Expand Up @@ -62,4 +63,6 @@ metafile-*.json

tsup.*.bundled_*.mjs

vite.client.dev.js
vite.client.dev.js

.last-run.json
89 changes: 89 additions & 0 deletions e2e/injection/fetch.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { test, expect } from '@playwright/test'
import type { Page } from '@playwright/test'
import type { FetchTestEvent } from '../../src/playground/injection/fetch/index'
import { gotoInjectionModule } from './helpers'

const TEST_API_PATH = '/api/test/data'
const MOCK_BODY = '{"ok":true}'

async function getFetchTestEvents(page: Page): Promise<FetchTestEvent[]> {
return page.evaluate(() => window.testFetchEvents?.slice() ?? [])
}

async function waitForFetchModuleReady(page: Page) {
await gotoInjectionModule(page, 'fetch')
await page.evaluate(() => {
window.testFetchEvents = []
})
}

function mockTestApi(page: Page) {
return page.route(`**${TEST_API_PATH}`, (route) =>
route.fulfill({
status: 200,
contentType: 'application/json',
body: MOCK_BODY,
}),
)
}

test.describe('Fetch injection', () => {
test('should intercept fetch when URL matches listener', async ({ page }) => {
await mockTestApi(page)
await waitForFetchModuleReady(page)

await page.evaluate((url) => window.runFetchRequest!(url), TEST_API_PATH)

await expect
.poll(async () => getFetchTestEvents(page), { timeout: 5000 })
.toEqual(
expect.arrayContaining([
expect.objectContaining({
source: 'fetch',
url: TEST_API_PATH,
res: MOCK_BODY,
}),
]),
)
})

test('should intercept XMLHttpRequest when URL matches listener', async ({
page,
}) => {
await mockTestApi(page)
await waitForFetchModuleReady(page)

await page.evaluate((url) => window.runXHRRequest!(url), TEST_API_PATH)

await expect
.poll(async () => getFetchTestEvents(page), { timeout: 5000 })
.toEqual(
expect.arrayContaining([
expect.objectContaining({
source: 'xhr',
url: TEST_API_PATH,
res: MOCK_BODY,
}),
]),
)
})

test('should not trigger listener for non-matching URLs', async ({
page,
}) => {
await page.route('**/api/other/data', (route) =>
route.fulfill({
status: 200,
contentType: 'application/json',
body: '{"ignored":true}',
}),
)
await waitForFetchModuleReady(page)

await page.evaluate(() => window.runFetchRequest!('/api/other/data'))

await page.waitForTimeout(300)
const events = await getFetchTestEvents(page)
expect(events).toHaveLength(0)
})
})
15 changes: 15 additions & 0 deletions e2e/injection/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type { Page } from '@playwright/test'

export const INJECTION_PLAYGROUND_URL =
process.env.PLAYGROUND_URL || 'http://localhost:5173'

export function injectionPagePath(moduleName: string) {
return `${INJECTION_PLAYGROUND_URL}/injection/${moduleName}/index.html`
}

export async function gotoInjectionModule(page: Page, moduleName: string) {
await page.goto(injectionPagePath(moduleName))
await page.waitForFunction(() => window.testReady === true, {
timeout: 10000,
})
}
48 changes: 48 additions & 0 deletions e2e/injection/run-code.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { test, expect } from '@playwright/test'
import type { Page } from '@playwright/test'
import type { RunCodeTestEvent } from '../../src/playground/injection/run-code/index'
import { gotoInjectionModule } from './helpers'

async function getRunCodeTestEvents(page: Page): Promise<RunCodeTestEvent[]> {
return page.evaluate(() => window.testRunCodeEvents?.slice() ?? [])
}

async function waitForRunCodeModuleReady(page: Page) {
await gotoInjectionModule(page, 'run-code')
}

test.describe('Run-code injection', () => {
test('should run code in page context and return result', async ({
page,
}) => {
await waitForRunCodeModuleReady(page)

const result = await page.evaluate(() => window.runCodeRunTest!())

expect(result).toEqual({ first: 10, second: 10 })
})

test('should forward page events to client callbacks via runWithCallback', async ({
page,
}) => {
await waitForRunCodeModuleReady(page)

await page.evaluate(() => window.runCodeCallbackTest!())

await expect
.poll(async () => getRunCodeTestEvents(page), { timeout: 5000 })
.toEqual(
expect.arrayContaining([
{ type: 'callback', payload: 'ping' },
{ type: 'cleared' },
]),
)

const events = await getRunCodeTestEvents(page)
expect(
events.filter(
(e) => e.type === 'callback' && e.payload === 'after-clear',
),
).toHaveLength(0)
})
})
43 changes: 43 additions & 0 deletions e2e/injection/visibility-helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import type { BrowserContext, Page } from '@playwright/test'

export type NativeVisibilitySource = 'browser' | 'simulated'

/**
* Playwright keeps every page "visible" (see playwright#3570). We first try a real
* background tab via bringToFront; if visibilityState does not change, fall back to
* the playground test hook that feeds inject's native path.
*/
export async function ensureNativeVisibilityState(
page: Page,
context: BrowserContext,
target: DocumentVisibilityState,
): Promise<NativeVisibilitySource> {
await page.evaluate(() => window.visibilityClearNativeState?.())

if (target === 'hidden') {
const blocker = await context.newPage()
try {
await blocker.goto('about:blank')
await blocker.bringToFront()
await page.waitForTimeout(300)
} finally {
await blocker.close().catch(() => undefined)
}
} else {
await page.bringToFront()
await page.waitForTimeout(300)
}

const actual = await page.evaluate(() => document.visibilityState)
if (actual === target) return 'browser'

await page.evaluate((state) => {
window.visibilitySetNativeState!(state)
}, target)

return 'simulated'
}

export async function readPageVisibilityState(page: Page) {
return page.evaluate(() => document.visibilityState)
}
46 changes: 46 additions & 0 deletions e2e/injection/visibility.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { test, expect } from '@playwright/test'
import { gotoInjectionModule } from './helpers'

async function readVisibilityState(page: import('@playwright/test').Page) {
return page.evaluate(() => window.readVisibilityState!())
}

test.describe('Visibility injection', () => {
test('should force document.visibilityState to visible', async ({ page }) => {
await gotoInjectionModule(page, 'visibility')

await page.evaluate(() => window.visibilityAlwaysVisibleTest!())

await expect
.poll(() => readVisibilityState(page), { timeout: 5000 })
.toBe('visible')
})

test('should force document.visibilityState to hidden', async ({ page }) => {
await gotoInjectionModule(page, 'visibility')

await page.evaluate(() => window.visibilityAlwaysHiddenTest!())

await expect
.poll(() => readVisibilityState(page), { timeout: 5000 })
.toBe('hidden')
})

test('should restore native visibilityState after restore()', async ({
page,
}) => {
await gotoInjectionModule(page, 'visibility')

const nativeState = await readVisibilityState(page)

await page.evaluate(() => window.visibilityAlwaysHiddenTest!())
await expect
.poll(() => readVisibilityState(page), { timeout: 5000 })
.toBe('hidden')

await page.evaluate(() => window.visibilityRestoreTest!())
await expect
.poll(() => readVisibilityState(page), { timeout: 5000 })
.toBe(nativeState)
})
})
4 changes: 3 additions & 1 deletion nodemon.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"$schema": "https://json.schemastore.org/nodemon.json",
"watch": [
"assets/lib",
"src/locales-ext",
Expand All @@ -11,6 +12,7 @@
"scripts/shared.ts",
"nodemon.json",
"docs",
"package.json"
"package.json",
"packages/adapter/dist/*"
]
}
17 changes: 11 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@
},
"scripts": {
"predev": "pnpm auto-use-node",
"dev": "cross-env NODE_ENV=development nodemon --exec \"rm -rf dist && run-p dev:*\"",
"dev:esm": "tsup --config scripts/dev.tsup.esm.ts",
"dev:hmr": "vite --config scripts/dev.vite.hmr.ts",
"dev": "cross-env NODE_ENV=development run-p dev:package:adapter dev:main",
"dev:package:adapter": "pnpm --filter @dmMiniPlayer/adapter run dev",
"dev:main": "nodemon --exec \"rm -rf dist && run-p dev:main:*\"",
"dev:main:esm": "tsup --config scripts/dev.tsup.esm.ts",
"dev:main:hmr": "vite --config scripts/dev.vite.hmr.ts",
"prebuild": "pnpm auto-use-node",
"build": "cross-env NODE_ENV=production run-s build:*",
"build:esm-chunks": "tsup --config scripts/prod.tsup.esm-chunks.ts --metafile && mv ./dist/metafile-esm.json ./dist/metafile-esm-chunks.json",
Expand Down Expand Up @@ -75,17 +77,19 @@
"protobufjs": "^7.5.4",
"tailwindcss": "^3.4.18",
"tailwindcss-rem-to-px": "^0.1.1",
"tsup": "^8.5.0",
"tsx": "^4.20.6",
"tsup": "catalog:",
"tsx": "catalog:",
"type-fest": "^5.2.0",
"typescript": "5.9.3",
"typescript-eslint": "^8.46.4",
"vite": "^7.2.2"
},
"dependencies": {
"@apades/logger": "link:packages/logger",
"@ant-design/icons": "^6.1.0",
"@apad/rc-slider": "^10.5.0",
"@apad/setting-panel": "^0.6.6",
"@dmMiniPlayer/adapter": "link:packages/adapter",
"@rc-component/trigger": "^3.6.15",
"ahooks": "^3.9.6",
"ass-compiler": "^0.1.16",
Expand All @@ -103,9 +107,10 @@
"react-dom": "^19.2.1",
"react-draggable": "^4.5.0",
"react-hot-toast": "^2.6.0",
"serialize": "link:packages/serialize",
"uuid": "^13.0.0",
"webext-bridge": "^6.0.1",
"webextension-polyfill": "^0.9.0",
"ws": "^8.18.3"
}
}
}
1 change: 1 addition & 0 deletions packages/adapter/core/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './site-adapter'
Loading
Loading