-
-
Notifications
You must be signed in to change notification settings - Fork 339
feat: create/remove iframe command #895
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
xiaoxustudio
wants to merge
24
commits into
OpenWebGAL:dev
Choose a base branch
from
xiaoxustudio:feat/createFrame-command
base: dev
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 5 commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
010696c
feat: add createFrame and removeFrame
xiaoxustudio ab43666
feat: add iframe api and reactive store
xiaoxustudio 8d5c075
refactor: extract iframe interfaces
xiaoxustudio a073635
feat: add iframe wait and return value support
xiaoxustudio 2a83f74
fix: handle iframe load error
xiaoxustudio e1976ee
chore: resolve some issues
xiaoxustudio dd454ff
fix: restrict iframe postMessage origin
xiaoxustudio 3b82c42
feat: add iframe setGameVar and closeFrame API
xiaoxustudio d422882
refactor: simplify iframe component logic
xiaoxustudio 3f00f64
feat: add iframe nextSentence and isBlockSentence API
xiaoxustudio 029788c
feat: add iframe save and load events
xiaoxustudio 3722839
fix: iframe width and height is invalid
xiaoxustudio a10af41
chore: unified name
xiaoxustudio 33aee01
fix: unified function name
xiaoxustudio 0cc054f
fix: build error
xiaoxustudio 36b6017
fix: rename closeFrame to closeIframe
xiaoxustudio 3545310
fix: reset iframe state when continue game
xiaoxustudio e65cc77
fix: isBlockSentence always return false when the second
xiaoxustudio d43cdb4
feat: add iframe persistent data API
xiaoxustudio 32f6aee
feat: add iframe open/close and isActive state
xiaoxustudio ddbce3f
fix: set iframe isActive to true when adding
xiaoxustudio 60440ed
feat: add command input parameters
xiaoxustudio ea691a8
feat: add postIframeMessage API
xiaoxustudio 8ba8618
feat: add hidden parameter and style support for iframe
xiaoxustudio File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| const frameApiManager = new (class { | ||
| private apis: Record<string, Function>; | ||
| public constructor() { | ||
| this.apis = {}; | ||
| } | ||
| public registerFrameApi(fnName: string, fn: Function) { | ||
| this.apis[fnName] = fn; | ||
| } | ||
| public callFrameApi(fnName: string, ...args: any[]) { | ||
| if (this.apis[fnName]) { | ||
| this.apis[fnName](...args); | ||
| } | ||
| } | ||
| public clearFrameApi() { | ||
| this.apis = {}; | ||
| } | ||
| public getFrameApi(fnName: string) { | ||
| return this.apis[fnName]; | ||
| } | ||
| })(); | ||
| export default frameApiManager; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,120 @@ | ||
| import { ISentence } from '@/Core/controller/scene/sceneInterface'; | ||
| import { IPerform } from '@/Core/Modules/perform/performInterface'; | ||
| import { getBooleanArgByKey, getNumberArgByKey, getStringArgByKey } from '../util/getSentenceArg'; | ||
| import { IIFrame } from '@/store/stageInterface'; | ||
| import { webgalStore } from '@/store/store'; | ||
| import { stageActions } from '@/store/stageReducer'; | ||
|
|
||
| const allSandboxProperties = { | ||
| 'allow-forms': 'allowForms', // 允许iframe内提交表单 | ||
| 'allow-scripts': 'allowScripts', // 允许iframe内执行JavaScript脚本(包括定时器、事件等) | ||
| 'allow-same-origin': 'allowSameOrigin', // 允许iframe内容拥有同源身份,可访问自身Cookie/LocalStorage等 | ||
| 'allow-top-navigation': 'allowTopNavigation', // 允许iframe内的链接跳转到父页面(主页面)的上下文 | ||
| 'allow-popups': 'allowPopups', // 允许iframe通过window.open()等方式弹出新窗口 | ||
| 'allow-modals': 'allowModals', // 允许iframe弹出模态窗口(如alert()、confirm()、prompt()) | ||
| 'allow-pointer-lock': 'allowPointerLock', // 允许iframe使用Pointer Lock API(如游戏鼠标锁定) | ||
| 'allow-popups-to-escape-sandbox': 'allowPopupsToEscapeSandbox', // 允许iframe弹出的新窗口不受当前沙箱限制 | ||
| 'allow-downloads': 'allowDownloads', // 允许iframe内触发文件下载操作 | ||
| 'allow-presentation': 'allowPresentation', // 允许iframe使用Presentation API(投屏/演示功能) | ||
| 'allow-top-navigation-by-user-activation': 'allowTopNavigationByUserActivation', // 仅允许用户主动触发(如点击)的顶级导航操作 | ||
| 'allow-storage-access-by-user-activation': 'allowStorageAccessByUserActivation', // 允许用户主动触发后访问父页面的存储权限 | ||
| 'allow-orientation-lock': 'allowOrientationLock', // 允许iframe使用Screen Orientation API锁定屏幕方向 | ||
| }; | ||
|
|
||
| /** | ||
| * 创建框架 | ||
| * @param sentence | ||
| */ | ||
| export const createFrame = (sentence: ISentence): IPerform => { | ||
| const src = sentence.content; | ||
| const id = getStringArgByKey(sentence, 'id') ?? ''; | ||
| const wait = getBooleanArgByKey(sentence, 'wait') ?? false; | ||
| const returnValue = getStringArgByKey(sentence, 'returnValue') ?? null; | ||
| const width = getNumberArgByKey(sentence, 'width') ?? undefined; | ||
| const height = getNumberArgByKey(sentence, 'height') ?? undefined; | ||
| if (!id || !src) { | ||
| return { | ||
| performName: 'none', | ||
| duration: 0, | ||
| isHoldOn: false, | ||
| stopFunction: () => {}, | ||
| blockingNext: () => false, | ||
| blockingAuto: () => true, | ||
| stopTimeout: undefined, | ||
| }; | ||
| } | ||
|
|
||
| let rawSrc = src; | ||
| // 处理src | ||
| if (!rawSrc.startsWith('http') || !rawSrc.startsWith('https')) { | ||
| rawSrc = './game/' + rawSrc; | ||
| } | ||
|
xiaoxustudio marked this conversation as resolved.
Outdated
|
||
|
|
||
| const frameData: IIFrame = { | ||
| id, | ||
| src: rawSrc, | ||
| sandbox: '', | ||
| width, | ||
| height, | ||
| isActive: true, | ||
| isDestroy: false, | ||
| wait, | ||
| returnValue, | ||
| }; | ||
|
|
||
| for (const [key, value] of Object.entries(allSandboxProperties)) { | ||
| const v = getStringArgByKey(sentence, value) ?? ''; | ||
| if (v) { | ||
| frameData.sandbox += key + ' '; | ||
| } | ||
| } | ||
|
|
||
| webgalStore.dispatch(stageActions.addFrame(frameData)); | ||
|
|
||
| // 如果需要等待iframe完成,则返回阻塞的perform | ||
| if (wait) { | ||
| let isCompleted = false; | ||
| // 监听iframe完成消息 | ||
| const handleFrameComplete = (event: MessageEvent) => { | ||
| if (event.data.type === 'webgal-frame-complete' && event.data.frameId === id) { | ||
|
xiaoxustudio marked this conversation as resolved.
Outdated
|
||
| isCompleted = true; | ||
| // 如果有returnValue,则存储到游戏变量中 | ||
| if (returnValue && event.data.returnValue !== undefined) { | ||
| webgalStore.dispatch( | ||
| stageActions.setStageVar({ | ||
| key: returnValue, | ||
| value: event.data.returnValue, | ||
| }), | ||
| ); | ||
| } | ||
| // 移除事件监听器 | ||
| window.removeEventListener('message', handleFrameComplete); | ||
| } | ||
| }; | ||
|
|
||
| // 添加事件监听器 | ||
| window.addEventListener('message', handleFrameComplete); | ||
|
|
||
| return { | ||
| performName: `frame-wait-${id}`, | ||
| duration: 0, | ||
| isHoldOn: true, | ||
| stopFunction: () => { | ||
| window.removeEventListener('message', handleFrameComplete); | ||
| }, | ||
| blockingNext: () => !isCompleted, | ||
| blockingAuto: () => !isCompleted, | ||
| stopTimeout: undefined, | ||
| }; | ||
| } | ||
|
|
||
| return { | ||
| performName: 'none', | ||
| duration: 0, | ||
| isHoldOn: false, | ||
| stopFunction: () => {}, | ||
| blockingNext: () => false, | ||
| blockingAuto: () => true, | ||
| stopTimeout: undefined, | ||
| }; | ||
| }; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| import { ISentence } from '@/Core/controller/scene/sceneInterface'; | ||
| import { IPerform } from '@/Core/Modules/perform/performInterface'; | ||
| import { stageActions } from '@/store/stageReducer'; | ||
| import { webgalStore } from '@/store/store'; | ||
|
|
||
| /** | ||
| * 移除框架 | ||
| * @param sentence | ||
| */ | ||
| export const removeFrame = (sentence: ISentence): IPerform => { | ||
| const id = sentence.content; | ||
| if (!id) { | ||
| return { | ||
| performName: 'none', | ||
| duration: 0, | ||
| isHoldOn: false, | ||
| stopFunction: () => {}, | ||
| blockingNext: () => false, | ||
| blockingAuto: () => true, | ||
| stopTimeout: undefined, | ||
| }; | ||
| } | ||
| webgalStore.dispatch(stageActions.removeFrame(id)); | ||
|
|
||
| return { | ||
| performName: 'none', | ||
| duration: 0, | ||
| isHoldOn: false, | ||
| stopFunction: () => {}, | ||
| blockingNext: () => false, | ||
| blockingAuto: () => true, | ||
| stopTimeout: undefined, | ||
| }; | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.