Skip to content

sync dev to ui#3189

Merged
qingqing-ux merged 13 commits into
goplus:uifrom
qingqing-ux:issues-3137-2
May 19, 2026
Merged

sync dev to ui#3189
qingqing-ux merged 13 commits into
goplus:uifrom
qingqing-ux:issues-3137-2

Conversation

@qingqing-ux
Copy link
Copy Markdown
Collaborator

@qingqing-ux qingqing-ux commented May 19, 2026

Summary

Sync the latest changes from dev into ui as a structural sync for the real frontend code.

Issue

Related to #3137

Background

This merged PR brought the real frontend code structure from dev into ui, so follow-up design and implementation work for #3137 can continue on top of the updated ui branch.

Conflict Resolution

ui/prototype exists on both branches:

  • dev has placeholder files with not implemented content.
  • ui has the full Vite/Vue prototype implementation.

This PR kept the existing ui implementation and applied the rest of the dev changes on top.

Verification

  • Confirmed the PR was mergeable on GitHub before merge.
  • Confirmed the local working tree was clean.

cn0809 and others added 13 commits May 14, 2026 09:11
* update ui empty/error default images

* compress svg size

* rename image

* adjust svg size
…goplus#3150)

* optimize video cut preview during animation generation

* use css variables for track padding

* fix details

* remove page for test

* optimize code

* queue video seeks to keep animation preview responsive during dragging
* chore(deps): bump spx to 2.0.0 (goplus#3127)

Agent-Logs-Url: https://github.com/goplus/builder/sessions/147d2d8e-4bf8-4ae7-b66e-b8a41c970f3a

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: nighca <1492263+nighca@users.noreply.github.com>

* Widget `<unstable-xgo-code-editor>` (goplus#3089)

* Add widget `<unstable-xgo-code-editor>`

* Address widget review feedback

* Stabilize layer order workarounds

* Provide SPX knowledge from frontend (goplus#3097)

* UI update for tutorial pages (goplus#3122)

* update tutorial pages styles

* compress tutorials banner

* refine tutorials banner layout

* show updated time for course series

* details

* Handle invalid image stalls in editor (goplus#3136)

* feat: add title attribute to sprite name in list items (goplus#3140)

* feat: add title attribute to sprite name in list items

Add HTML title attribute to the sprite name span in UIEditorSpriteItem
so users can hover to see the full name when it is truncated.

Generated with [codeagent](https://github.com/qbox/codeagent)
Co-authored-by: nighca <1492263+nighca@users.noreply.github.com>

* refactor: move title tooltip to UIBlockItemTitle component

Add optional `title` prop to UIBlockItemTitle and forward it to the
inner truncation span, then use it in UIEditorSpriteItem to avoid the
extra wrapper span.

Generated with [codeagent](https://github.com/qbox/codeagent)
Co-authored-by: nighca <1492263+nighca@users.noreply.github.com>

* feat: add title attribute to name in all block item components

Add :title="name" to UIBlockItemTitle in UIEditorBackdropItem,
UIEditorSoundItem, UIEditorWidgetItem, and UISpriteItem so truncated
names show a hover tooltip consistently across all item panels.

Generated with [codeagent](https://github.com/qbox/codeagent)
Co-authored-by: nighca <1492263+nighca@users.noreply.github.com>

* feat: add title attribute to sprite name in list items

Add :title="name" to UIBlockItemTitle in UISoundItem and UIBackdropItem.

Generated with [codeagent](https://github.com/qbox/codeagent)
Co-authored-by: nighca <1492263+nighca@users.noreply.github.com>

* refactor: make title prop required in UIBlockItemTitle

Change title from optional to required prop to ensure all callers
provide a tooltip value for truncated text.

Generated with [codeagent](https://github.com/qbox/codeagent)
Co-authored-by: nighca <1492263+nighca@users.noreply.github.com>

* feat: add title attribute to sprite name in list items

Add missing :title prop to all UIBlockItemTitle callers to satisfy
the newly-required title prop: AnimationGenItem, BackdropGenItem,
ParamSelector, CostumeGenItem, SpriteGenItem, SpxEffectKindItem,
and the ui-design docs page.

Generated with [codeagent](https://github.com/qbox/codeagent)
Co-authored-by: nighca <1492263+nighca@users.noreply.github.com>

* fix: use $t() instead of t() in ParamSelector template

Replace t(item.label) with $t(item.label) in the :title binding
to be consistent with the template-level i18n helper usage.

Generated with [codeagent](https://github.com/qbox/codeagent)
Co-authored-by: nighca <1492263+nighca@users.noreply.github.com>

* style: fix formatting in CostumeGenItem.vue

Run Prettier to fix line-length formatting issue flagged by CI.

Generated with [codeagent](https://github.com/qbox/codeagent)
Co-authored-by: nighca <1492263+nighca@users.noreply.github.com>

---------

Co-authored-by: xgopilot <noreply@goplus.org>
Co-authored-by: nighca <1492263+nighca@users.noreply.github.com>

* feat(code-editor): support sprite instance input helpers (goplus#3123)

Handle `spx-sprite-instance` with the existing resource input helper so
sprite instance slots can use the sprite resource selector.

Write selected sprite instances as bare identifiers while keeping
resource name slots as string literals.

Fixes goplus#3110
Updates goplus/xgolsw#317

Signed-off-by: Aofei Sheng <aofei@aofeisheng.com>

* Update UI empty/error default images (goplus#3134)

* update ui empty/error default images

* compress svg size

* rename image

* adjust svg size

* chore(deps): bump github.com/goplus/xgolsw to 0.20.0 in /tools/spxls (goplus#3163)

Signed-off-by: Aofei Sheng <aofei@aofeisheng.com>

* feat(spx-gui): optimize video cut preview during animation generation (goplus#3150)

* optimize video cut preview during animation generation

* use css variables for track padding

* fix details

* remove page for test

* optimize code

* queue video seeks to keep animation preview responsive during dragging

---------

Signed-off-by: Aofei Sheng <aofei@aofeisheng.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: nighca <1492263+nighca@users.noreply.github.com>
Co-authored-by: chennan <chennan@qiniu.com>
Co-authored-by: fennoai[bot] <231223108+fennoai[bot]@users.noreply.github.com>
Co-authored-by: xgopilot <noreply@goplus.org>
Co-authored-by: Aofei Sheng <aofei@aofeisheng.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: nighca <1492263+nighca@users.noreply.github.com>
…3164)

* Add empty ui/prototype/ to avoid Vercel deployment failure

* Update ui/prototype/package.json

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
…#3168)

* feat(animation): migrate sound binding from onStart to onPlay

- Export animation sound binding using `onPlay` instead of `onStart`
  to align with the animation lifecycle semantics in spx v2.0.0
- Load sound binding from `onPlay` as the primary field; fall back to
  legacy `onStart` for backward compatibility with existing projects
- Update `RawAnimationConfig`: `onPlay` is now the current API field,
  `onStart` is moved to the legacy section
- Add tests for the new export behavior and legacy onStart loading

Fixes goplus#3116

Generated with [codeagent](https://github.com/qbox/codeagent)
Co-authored-by: nighca <1492263+nighca@users.noreply.github.com>

* fix(animation): add missing blank line between test cases

Generated with [codeagent](https://github.com/qbox/codeagent)
Co-authored-by: nighca <1492263+nighca@users.noreply.github.com>

* feat(animation): add loop field to ActionConfig type

Generated with [codeagent](https://github.com/qbox/codeagent)
Co-authored-by: nighca <1492263+nighca@users.noreply.github.com>

* feat(animation): add soundLoop field with default false, parse loop from raw config

- Add soundLoop boolean field (default false) to AnimationInits and Animation class
- Add setSoundLoop() method to Animation
- Parse loop from onPlay/onStart in load() for backward compatibility
- Export loop: true in onPlay only when soundLoop is true (omitting it preserves old behavior)
- Preserve soundLoop in clone()
- Add tests for load/export/clone of soundLoop field

Generated with [codeagent](https://github.com/qbox/codeagent)
Co-authored-by: nighca <1492263+nighca@users.noreply.github.com>

* fix(animation): always export loop field in onPlay, including loop: false

Export loop: false when soundLoop is false so the exported config is
explicit. "default false" only applies during loading when loop is absent
from the raw config.

Generated with [codeagent](https://github.com/qbox/codeagent)
Co-authored-by: nighca <1492263+nighca@users.noreply.github.com>

* fix(animation): remove onStart.loop handling, no legacy loop field

onStart is a legacy field predating the loop feature; old configs using
onStart never contain loop. Only read loop from onPlay.

Generated with [codeagent](https://github.com/qbox/codeagent)
Co-authored-by: nighca <1492263+nighca@users.noreply.github.com>

* fix(animation): only set soundLoop when sound is valid

soundLoop is now set inside the else branch so it is only assigned
when the sound lookup succeeds and soundId is set.

Generated with [codeagent](https://github.com/qbox/codeagent)
Co-authored-by: nighca <1492263+nighca@users.noreply.github.com>

* fix(animation): assert soundLoop is false in legacy onStart load test

Generated with [codeagent](https://github.com/qbox/codeagent)
Co-authored-by: nighca <1492263+nighca@users.noreply.github.com>

* fix(animation): remove duplicate loop export test case

'should export loop: false in onPlay when soundLoop is false (default)'
is fully covered by 'should export sound binding using onPlay' which
already asserts { play: ..., loop: false }.

Generated with [codeagent](https://github.com/qbox/codeagent)
Co-authored-by: nighca <1492263+nighca@users.noreply.github.com>

---------

Co-authored-by: xgopilot <noreply@goplus.org>
Co-authored-by: nighca <1492263+nighca@users.noreply.github.com>
)

* fix(animation): revert sound binding to onStart temporarily

* test(animation): document temporary skipped onPlay cases

* docs(animation): clarify temporary onStart export comment
* Sync SPX overload documentation mappings

* Address review feedback

* Handle fennoai review feedback
Replace the existing product API paths with the new resource-oriented
contract. Move authenticated-user collections under `/user/*`, public
user collections under `/users/{username}/*`, and relationship
membership operations to idempotent `PUT` routes.

Add operation IDs, specific path parameter names, and `Location`
headers for created resources while preserving moved-resource response
semantics for renamed resources.

Updates goplus#3144

Signed-off-by: Aofei Sheng <aofei@aofeisheng.com>
# Conflicts:
#	ui/prototype/index.html
#	ui/prototype/package-lock.json
#	ui/prototype/package.json
@qingqing-ux qingqing-ux merged commit 0bcac69 into goplus:ui May 19, 2026
4 checks passed
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the SPX version to 2.0.1, increases the maximum file size for conversions, and significantly refines the AnimationVideoPreview component with improved seek handling and a more robust dragging implementation. The SPX documentation and API references are updated to reflect command overload changes and the support for top-level startup statements. Additionally, the Animation model now supports sound looping. Review feedback focused on replacing risky non-null assertions in the video preview component, correcting default value documentation for sound looping, and ensuring the loop property is correctly loaded from both current and legacy configuration blocks.

Comment on lines +323 to +325
} else {
cutEndRef.value = adjustEndTime(cutEndRef.value, videoDurationRef.value!, true)
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The use of the non-null assertion operator (!) on videoDurationRef.value is risky. Although it is checked at the start of the drag, the duration could theoretically become null if the video source changes or the component state updates during the drag. It is safer to add an explicit null check.

    } else if (videoDurationRef.value != null) {
      cutEndRef.value = adjustEndTime(cutEndRef.value, videoDurationRef.value, true)
    }

Comment on lines +14 to +15
/** Whether to loop the sound; for onStart defaults to false, for onPlay defaults to true */
loop?: boolean
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The comment indicates that onPlay defaults to true, but the implementation in Animation.load (line 191) and the corresponding tests (line 177 of animation.test.ts) default it to false. Please update the comment to reflect the actual behavior.

Suggested change
/** Whether to loop the sound; for onStart defaults to false, for onPlay defaults to true */
loop?: boolean
/** Whether to loop the sound; defaults to false */
loop?: boolean

Comment on lines +185 to +192
const soundName = onPlay?.play ?? onStart?.play
if (soundName != null) {
const sound = sounds.find((s) => s.name === soundName)
if (sound == null) console.warn(`Sound ${soundName} not found when creating animation ${name}`)
else {
soundId = sound.id
soundLoop = onPlay?.loop ?? false
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The loop field from the legacy onStart configuration is currently ignored during loading, even though soundName correctly falls back to it. The logic should be updated to check the loop property on whichever configuration block (onPlay or onStart) is being used.

    const actionConfig = onPlay ?? onStart
    const soundName = actionConfig?.play
    if (soundName != null) {
      const sound = sounds.find((s) => s.name === soundName)
      if (sound == null) console.warn(`Sound ${soundName} not found when creating animation ${name}`)
      else {
        soundId = sound.id
        soundLoop = actionConfig.loop ?? false
      }
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants