From 3758f60458f8431a3428ade214ab958dd31217d8 Mon Sep 17 00:00:00 2001 From: "fennoai[bot]" <231223108+fennoai[bot]@users.noreply.github.com> Date: Fri, 24 Jul 2026 11:30:18 +0800 Subject: [PATCH 1/8] feat(spx-gui): raise sb upload limit to 128 MiB (#3352) Raise the hardcoded local pre-check for Scratch (.sb2/.sb3) project conversion from 64 MiB to 128 MiB so larger projects can be uploaded. The general upload path in cloud.ts already follows the backend-provided maxSize, so no change is needed there. Update the openapi.yaml project-conversions description to match. Fixes #3351 Generated with [FennoAI](https://github.com/apps/fennoai) Co-authored-by: fennoai[bot] <231223108+fennoai[bot]@users.noreply.github.com> Co-authored-by: go-wyvern <15845637+go-wyvern@users.noreply.github.com> --- docs/openapi.yaml | 2 +- spx-gui/src/apis/project-conversion.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/openapi.yaml b/docs/openapi.yaml index 5d191d7dc..ad4805613 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -4600,7 +4600,7 @@ paths: description: | Scratch project file, such as .sb2, .sb3, or project zip. Form field name must be `file`. - Maximum size is 64 MiB. + Maximum size is 128 MiB. type: string format: binary responses: diff --git a/spx-gui/src/apis/project-conversion.ts b/spx-gui/src/apis/project-conversion.ts index b0284de42..25a5287ab 100644 --- a/spx-gui/src/apis/project-conversion.ts +++ b/spx-gui/src/apis/project-conversion.ts @@ -2,7 +2,7 @@ import { DefaultException } from '@/utils/exception' import { client } from './common' import { humanizeFileSize } from '@/utils/utils' -const maxFileSize = 64 * 1024 * 1024 // 64MB +const maxFileSize = 128 * 1024 * 1024 // 128MB const convertTimeout = 60 * 1000 // 60s /** From c23d9b241e6b8de8ce8b60552e3b983ef472ee18 Mon Sep 17 00:00:00 2001 From: Hanxing Yang Date: Fri, 24 Jul 2026 12:13:36 +0800 Subject: [PATCH 2/8] chore(deps): bump spx to 3.0.0 (#3369) * chore(deps): bump spx to 3.0.0 * refactor(spx): reuse package path * chore(deps): pin xgolsw spx v3 branch * chore(deps): update xgolsw pseudo version * chore(deps): refresh xgolsw checksum * chore(deps): use merged xgolsw version --- .github/agents/spx-upgrader.md | 2 +- docs/develop/code-editor/base.ts | 2 +- spx-gui/package.json | 2 +- spx-gui/pnpm-lock.yaml | 10 +-- spx-gui/pnpm-workspace.yaml | 2 + .../editor/spx-code-editor/spx-project.ts | 5 +- .../components/xgo-code-editor/common.test.ts | 10 +-- .../src/components/xgo-code-editor/common.ts | 4 +- spx-gui/src/utils/spx/index.ts | 2 +- tools/ai/ai.go | 2 +- tools/ai/command.go | 2 +- tools/ai/go.mod | 2 +- tools/ai/go.sum | 4 +- tools/ispx/go.mod | 25 ++++---- tools/ispx/go.sum | 64 +++++++++++-------- .../goplus/builder/tools/ai/export.go | 2 +- tools/ispx/main.go | 4 +- tools/spxls/go.mod | 12 ++-- tools/spxls/go.sum | 24 +++---- 19 files changed, 98 insertions(+), 82 deletions(-) diff --git a/.github/agents/spx-upgrader.md b/.github/agents/spx-upgrader.md index c8b818bc7..b44b5b98a 100644 --- a/.github/agents/spx-upgrader.md +++ b/.github/agents/spx-upgrader.md @@ -9,7 +9,7 @@ You are a release specialist dedicated to upgrading spx across goplus/builder sa - For released versions, verify they exist by running `gh release view --repo goplus/spx v` - Verify the matching web package exists by running `npm view @xgo-pkgs/spx@ version` - Run `pnpm add @xgo-pkgs/spx@ --save-exact` in `spx-gui/` to update `spx-gui/package.json` and `spx-gui/pnpm-lock.yaml` -- Refresh Go modules in `tools/ai/`, `tools/spxls/`, and `tools/ispx/` via `go get github.com/goplus/spx/v2@v` followed by `go mod tidy` in each directory +- Refresh Go modules in `tools/ai/`, `tools/spxls/`, and `tools/ispx/` via `go get github.com/goplus/spx/v3@v` followed by `go mod tidy` in each directory - Execute `pnpm install --frozen-lockfile` in `spx-gui/` to install dependencies and expose the installed runtime assets under `spx-gui/public/` via `postinstall` - Execute `bash build-wasm.sh` in `spx-gui/` to build Wasm components - Run `pnpm run lint`, `pnpm run test -- --run` in `spx-gui/`, plus `go test ./...` inside `tools/ai/`, `tools/spxls/`, and `tools/ispx/` if there are packages to test diff --git a/docs/develop/code-editor/base.ts b/docs/develop/code-editor/base.ts index a79ce81b9..71322fd72 100644 --- a/docs/develop/code-editor/base.ts +++ b/docs/develop/code-editor/base.ts @@ -68,7 +68,7 @@ interface DefinitionIdentifier { * If `main`, it's the current user package. * Exmples: * - `fmt` - * - `github.com/goplus/spx/v2` + * - `github.com/goplus/spx/v3` * - `main` */ package?: string diff --git a/spx-gui/package.json b/spx-gui/package.json index c5c7bf759..a4f27156e 100644 --- a/spx-gui/package.json +++ b/spx-gui/package.json @@ -43,7 +43,7 @@ "@vue/runtime-core": "3.5.25", "@vue/test-utils": "^2.4.5", "@vue/tsconfig": "^0.8.1", - "@xgo-pkgs/spx": "2.0.4", + "@xgo-pkgs/spx": "3.0.0", "bowser": "^2.14.1", "browserslist": "^4.28.0", "browserslist-to-esbuild": "^2.1.1", diff --git a/spx-gui/pnpm-lock.yaml b/spx-gui/pnpm-lock.yaml index 47037b526..a10186b43 100644 --- a/spx-gui/pnpm-lock.yaml +++ b/spx-gui/pnpm-lock.yaml @@ -81,8 +81,8 @@ importers: specifier: ^0.8.1 version: 0.8.1(typescript@5.9.3)(vue@3.5.25(typescript@5.9.3)) '@xgo-pkgs/spx': - specifier: 2.0.4 - version: 2.0.4 + specifier: 3.0.0 + version: 3.0.0 bowser: specifier: ^2.14.1 version: 2.14.1 @@ -1224,8 +1224,8 @@ packages: peerDependencies: vue: ^3.5.0 - '@xgo-pkgs/spx@2.0.4': - resolution: {integrity: sha512-aV6L7UD/6GXH6dEUjzSTU/7kpLXsN/L8Wy8rnFzR4gez0otKlmxjX8Ogft9COaQR1hQ5N0AvhXw0jPJdN+5FjA==} + '@xgo-pkgs/spx@3.0.0': + resolution: {integrity: sha512-+aLj+XSXJZpuBJcAGgOqhHDEBs7qcer3xQ/ZkiSvNPDdXEfn1006V1X8VS6avXsGyr/eKSHV4ep4rpuKMgQrRg==} abbrev@2.0.0: resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==} @@ -4195,7 +4195,7 @@ snapshots: dependencies: vue: 3.5.25(typescript@5.9.3) - '@xgo-pkgs/spx@2.0.4': {} + '@xgo-pkgs/spx@3.0.0': {} abbrev@2.0.0: {} diff --git a/spx-gui/pnpm-workspace.yaml b/spx-gui/pnpm-workspace.yaml index bc26a2df3..e6ef30d6e 100644 --- a/spx-gui/pnpm-workspace.yaml +++ b/spx-gui/pnpm-workspace.yaml @@ -2,3 +2,5 @@ packages: - . allowBuilds: vue-demi: true +minimumReleaseAgeExclude: + - '@xgo-pkgs/spx' diff --git a/spx-gui/src/components/editor/spx-code-editor/spx-project.ts b/spx-gui/src/components/editor/spx-code-editor/spx-project.ts index 9215892cc..e3a5b4192 100644 --- a/spx-gui/src/components/editor/spx-code-editor/spx-project.ts +++ b/spx-gui/src/components/editor/spx-code-editor/spx-project.ts @@ -4,6 +4,7 @@ * consumed by the generic CodeEditor core. */ +import { packageSpx } from '@/utils/spx' import type { Files } from '@/models/common/file' import type { SpxProject } from '@/models/spx/project' import type { History } from '@/components/editor/history' @@ -25,8 +26,8 @@ export const spxClassFramework: ClassFramework = { className: 'Sprite' } ], - pkgPaths: ['github.com/goplus/spx/v2'], - autoImports: [{ path: 'github.com/goplus/spx/v2' }] + pkgPaths: [packageSpx], + autoImports: [{ path: packageSpx }] } /** diff --git a/spx-gui/src/components/xgo-code-editor/common.test.ts b/spx-gui/src/components/xgo-code-editor/common.test.ts index 2aa12342f..ffcea2813 100644 --- a/spx-gui/src/components/xgo-code-editor/common.test.ts +++ b/spx-gui/src/components/xgo-code-editor/common.test.ts @@ -4,8 +4,8 @@ import { stringifyDefinitionId, parseDefinitionId } from './common' describe('stringifyDefinitionId', () => { it('should stringify definition identifier', () => { expect(stringifyDefinitionId({ package: 'fmt', name: 'Println' })).toBe('xgo:fmt?Println') - expect(stringifyDefinitionId({ package: 'github.com/goplus/spx/v2', name: 'Sprite.Clone', overloadId: '1' })).toBe( - 'xgo:github.com/goplus/spx/v2?Sprite.Clone#1' + expect(stringifyDefinitionId({ package: 'github.com/goplus/spx/v3', name: 'Sprite.Clone', overloadId: '1' })).toBe( + 'xgo:github.com/goplus/spx/v3?Sprite.Clone#1' ) expect(stringifyDefinitionId({ name: 'for_statement_with_single_condition' })).toBe( 'xgo:?for_statement_with_single_condition' @@ -17,8 +17,8 @@ describe('stringifyDefinitionId', () => { describe('parseDefinitionId', () => { it('should parse definition identifier correctly', () => { expect(parseDefinitionId('xgo:fmt?Println')).toEqual({ package: 'fmt', name: 'Println' }) - expect(parseDefinitionId('xgo:github.com/goplus/spx/v2?Sprite.Clone#1')).toEqual({ - package: 'github.com/goplus/spx/v2', + expect(parseDefinitionId('xgo:github.com/goplus/spx/v3?Sprite.Clone#1')).toEqual({ + package: 'github.com/goplus/spx/v3', name: 'Sprite.Clone', overloadId: '1' }) @@ -31,7 +31,7 @@ describe('parseDefinitionId', () => { it('should stringify & parse correctly', () => { ;[ { package: 'fmt', name: 'Println' }, - { package: 'github.com/goplus/spx/v2', name: 'Sprite.Clone', overloadId: '1' }, + { package: 'github.com/goplus/spx/v3', name: 'Sprite.Clone', overloadId: '1' }, { name: 'for_statement_with_single_condition' }, { package: 'main', name: 'foo' } ].forEach((defId) => { diff --git a/spx-gui/src/components/xgo-code-editor/common.ts b/spx-gui/src/components/xgo-code-editor/common.ts index fec99a579..e3862fd7b 100644 --- a/spx-gui/src/components/xgo-code-editor/common.ts +++ b/spx-gui/src/components/xgo-code-editor/common.ts @@ -121,7 +121,7 @@ export type DefinitionIdentifier = { * If `main`, it's the current user package. * Exmples: * - `fmt` - * - `github.com/goplus/spx/v2` + * - `github.com/goplus/spx/v3` * - `main` */ package?: string @@ -277,7 +277,7 @@ export type CommandIconType = 'explain' | 'fix' | 'goto' | 'modify' | 'rename' | * Documentation string for a definition. Typically: * ```mdx * func turn(dDirection float64) - * + * * ``` */ export type DefinitionDocumentationString = BasicMarkdownString | AdvancedMarkdownString diff --git a/spx-gui/src/utils/spx/index.ts b/spx-gui/src/utils/spx/index.ts index df49879cd..f26b8c2af 100644 --- a/spx-gui/src/utils/spx/index.ts +++ b/spx-gui/src/utils/spx/index.ts @@ -26,7 +26,7 @@ import { import spxApisDoc from './skills/spx-project/references/apis.md?raw' import spxProjectSkillMainDoc from './skills/spx-project/SKILL.md?raw' -export const packageSpx = 'github.com/goplus/spx/v2' +export const packageSpx = 'github.com/goplus/spx/v3' /** * Audio file formats supported by spx. diff --git a/tools/ai/ai.go b/tools/ai/ai.go index f3d48cbd7..d9b9aba84 100644 --- a/tools/ai/ai.go +++ b/tools/ai/ai.go @@ -16,7 +16,7 @@ import ( "sync" "time" - "github.com/goplus/spx/v2/pkg/spx" + "github.com/goplus/spx/v3/pkg/spx" ) // GopPackage indicates that this package is a XGo package. diff --git a/tools/ai/command.go b/tools/ai/command.go index 43e6770c7..5c3b548b3 100644 --- a/tools/ai/command.go +++ b/tools/ai/command.go @@ -6,7 +6,7 @@ import ( "fmt" "reflect" - "github.com/goplus/spx/v2/pkg/spx" + "github.com/goplus/spx/v3/pkg/spx" ) // CommandSpec describes an available AI command, derived from a command registration. diff --git a/tools/ai/go.mod b/tools/ai/go.mod index 547a32071..b0031922a 100644 --- a/tools/ai/go.mod +++ b/tools/ai/go.mod @@ -2,7 +2,7 @@ module github.com/goplus/builder/tools/ai go 1.25.0 -require github.com/goplus/spx/v2 v2.0.4 +require github.com/goplus/spx/v3 v3.0.0 require ( github.com/goplus/spbase v0.1.0 // indirect diff --git a/tools/ai/go.sum b/tools/ai/go.sum index 9a9881592..60b991bbf 100644 --- a/tools/ai/go.sum +++ b/tools/ai/go.sum @@ -1,7 +1,7 @@ github.com/goplus/spbase v0.1.0 h1:JNZ0D/65DerYyv9/9IfrXHZZbd0WNK0jHiVvgCtZhwY= github.com/goplus/spbase v0.1.0/go.mod h1:brnD3OJnHtipqob2IsJ3/QzGBf+eOnqXNnHGKpv1irQ= -github.com/goplus/spx/v2 v2.0.4 h1:4hyCM5XH3DMRjFeoTxCndrqcFZTeCWHkEicyp7wYTSs= -github.com/goplus/spx/v2 v2.0.4/go.mod h1:mF2kCvUNw97ku2PYHMEwbCENv24b5EwnlXOLiVMRbHM= +github.com/goplus/spx/v3 v3.0.0 h1:qy+NXFm3rGh2llWg+/koTyMwN56Gzpovg/ONJ1mTpqk= +github.com/goplus/spx/v3 v3.0.0/go.mod h1:wi1iUwx9g44B5wqGG6SusaGthOSz1YYYol/JkAM/pRs= github.com/petermattis/goid v0.0.0-20250721140440-ea1c0173183e h1:D0bJD+4O3G4izvrQUmzCL80zazlN7EwJ0PPDhpJWC/I= github.com/petermattis/goid v0.0.0-20250721140440-ea1c0173183e/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= golang.org/x/image v0.23.0 h1:HseQ7c2OpPKTPVzNjG5fwJsOTCiiwS4QdsYi5XU6H68= diff --git a/tools/ispx/go.mod b/tools/ispx/go.mod index 02be1abff..33f0f6e2e 100644 --- a/tools/ispx/go.mod +++ b/tools/ispx/go.mod @@ -6,25 +6,26 @@ tool github.com/goplus/ixgo/cmd/qexp require ( github.com/goplus/builder/tools/ai v0.0.0 - github.com/goplus/ixgo v1.1.0 - github.com/goplus/mod v0.20.2 - github.com/goplus/spx/v2 v2.0.4 + github.com/goplus/ixgo v1.1.1 + github.com/goplus/mod v0.21.1 + github.com/goplus/spx/v3 v3.0.0 ) require ( - github.com/goplus/gogen v1.23.0-pre.3.0.20260414234848-6641c10c9d6f // indirect - github.com/goplus/reflectx v1.7.0 // indirect + github.com/goplus/gogen v1.23.5 // indirect + github.com/goplus/reflectx v1.7.2 // indirect github.com/goplus/spbase v0.1.0 // indirect - github.com/goplus/xgo v1.7.2-0.20260414235301-df19f4a1b7c2 // indirect + github.com/goplus/xgo v1.7.5 // indirect github.com/petermattis/goid v0.0.0-20250721140440-ea1c0173183e // indirect - github.com/qiniu/x v1.17.0 // indirect - github.com/timandy/routine v1.1.5 // indirect - github.com/visualfc/funcval v0.1.4 // indirect - github.com/visualfc/xtype v0.3.0 // indirect + github.com/qiniu/x v1.18.0 // indirect + github.com/timandy/routine v1.1.6 // indirect + github.com/visualfc/funcval v0.1.5 // indirect + github.com/visualfc/gid v0.3.1 // indirect + github.com/visualfc/xtype v0.3.2 // indirect golang.org/x/image v0.23.0 // indirect golang.org/x/mobile v0.0.0-20220518205345-8578da9835fd // indirect - golang.org/x/mod v0.29.0 // indirect - golang.org/x/tools v0.38.0 // indirect + golang.org/x/mod v0.32.0 // indirect + golang.org/x/tools v0.41.0 // indirect ) replace github.com/goplus/builder/tools/ai => ../ai diff --git a/tools/ispx/go.sum b/tools/ispx/go.sum index 1d7e881d1..fc0160838 100644 --- a/tools/ispx/go.sum +++ b/tools/ispx/go.sum @@ -1,40 +1,50 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/goplus/gogen v1.23.0-pre.3.0.20260414234848-6641c10c9d6f h1:qb3VcmljqvrIgEVbs83cbZkckszvtHl3OnO/ums8Zoc= -github.com/goplus/gogen v1.23.0-pre.3.0.20260414234848-6641c10c9d6f/go.mod h1:Y7ulYW3wonQ3d9er00b0uGFEV/IUZa6okWJZh892ACQ= -github.com/goplus/ixgo v1.1.0 h1:Lrp3xTzN+xUsrb7H3bIsGMHna1GTmoCrljDhFBF8OOs= -github.com/goplus/ixgo v1.1.0/go.mod h1:fhd/bwm497c66k7hZJJ2WmmvPiKEAJUQR3f2oQiAANQ= -github.com/goplus/mod v0.20.2 h1:YX72E6AhhRLvlkVnI9cBK6PZvUwtge2hwROh7w9N6Yk= -github.com/goplus/mod v0.20.2/go.mod h1:lWW62tH7L3Vm42Lr6wlUMYHvsm5w3TkEpE2ulKTgmU8= -github.com/goplus/reflectx v1.7.0 h1:52l0Si+vDc6CvT7Y+h47h2QUs5HQp6qxPlmvLsMzo38= -github.com/goplus/reflectx v1.7.0/go.mod h1:EXX8KSPTmnb2W1PfyVkDC0Qwet0lYX2h2/S06Vhwrhw= +github.com/goplus/gogen v1.23.5 h1:76w3zmAHI+ECI7bPr0enUd0du9+t1IYyXmp43CbIpSs= +github.com/goplus/gogen v1.23.5/go.mod h1:Y7ulYW3wonQ3d9er00b0uGFEV/IUZa6okWJZh892ACQ= +github.com/goplus/ixgo v1.1.1 h1:fwrz6xRxdBd0TVsi/ySMtooolH6gvGpL6PVNPLFu84Q= +github.com/goplus/ixgo v1.1.1/go.mod h1:mjgTDzNVDpu1B7zp/Oo3pBsOneEfzJzFQPR7CKeY2wk= +github.com/goplus/mod v0.21.1 h1:thTyYvCVFEQr8bilNW2DvgI6UwuCYqCWF7DaA/dhf/c= +github.com/goplus/mod v0.21.1/go.mod h1:VTyNmzzePgy99A2VQnxIBfoG1x097xilag/t0F0zuTg= +github.com/goplus/reflectx v1.7.2 h1:NXpQ7SzEQKaTdivP3HsHpfLJQC3avhvyYg9ziyR8jPU= +github.com/goplus/reflectx v1.7.2/go.mod h1:EXX8KSPTmnb2W1PfyVkDC0Qwet0lYX2h2/S06Vhwrhw= github.com/goplus/spbase v0.1.0 h1:JNZ0D/65DerYyv9/9IfrXHZZbd0WNK0jHiVvgCtZhwY= github.com/goplus/spbase v0.1.0/go.mod h1:brnD3OJnHtipqob2IsJ3/QzGBf+eOnqXNnHGKpv1irQ= -github.com/goplus/spx/v2 v2.0.4 h1:4hyCM5XH3DMRjFeoTxCndrqcFZTeCWHkEicyp7wYTSs= -github.com/goplus/spx/v2 v2.0.4/go.mod h1:mF2kCvUNw97ku2PYHMEwbCENv24b5EwnlXOLiVMRbHM= -github.com/goplus/xgo v1.7.2-0.20260414235301-df19f4a1b7c2 h1:kXIGYlJUTii+7nv1XTKR0ctMZSeTcgYMoQuEexZPr7A= -github.com/goplus/xgo v1.7.2-0.20260414235301-df19f4a1b7c2/go.mod h1:fX3+ZaYEzBE6qkgFcJx83D6DbUo/vMO8Y1Allydy2ws= +github.com/goplus/spx/v3 v3.0.0 h1:qy+NXFm3rGh2llWg+/koTyMwN56Gzpovg/ONJ1mTpqk= +github.com/goplus/spx/v3 v3.0.0/go.mod h1:wi1iUwx9g44B5wqGG6SusaGthOSz1YYYol/JkAM/pRs= +github.com/goplus/xgo v1.7.5 h1:biSNkiyWe3e+YmOmDRSs1Z6K4RLkLpzN6mTp1WbryAw= +github.com/goplus/xgo v1.7.5/go.mod h1:TRIPQ1bRVkq1x0+Ve/gWGS+qcb3ACPIZHNcmuiKzYkE= github.com/petermattis/goid v0.0.0-20250721140440-ea1c0173183e h1:D0bJD+4O3G4izvrQUmzCL80zazlN7EwJ0PPDhpJWC/I= github.com/petermattis/goid v0.0.0-20250721140440-ea1c0173183e/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/qiniu/x v1.17.0 h1:OsyDKXzYp5vw9Hc7VAe4Cso1Sp50fLKGsBuDteyTevE= -github.com/qiniu/x v1.17.0/go.mod h1:AiovSOCaRijaf3fj+0CBOpR1457pn24b0Vdb1JpwhII= +github.com/qiniu/x v1.18.0 h1:iMfc7Gqy1au+akr+Tl5Z40px7TR8VBLLkJsIeajKIbc= +github.com/qiniu/x v1.18.0/go.mod h1:Sx3Wy+0GI9OsX4a53mYj6A0o7mHJ94PUvraqGYb4EIs= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/timandy/routine v1.1.5 h1:LSpm7Iijwb9imIPlucl4krpr2EeCeAUvifiQ9Uf5X+M= -github.com/timandy/routine v1.1.5/go.mod h1:kXslgIosdY8LW0byTyPnenDgn4/azt2euufAq9rK51w= -github.com/visualfc/funcval v0.1.4 h1:lAI88zQYfRzmC7mKF4+swXeCZvb8wb1f3lMSDRAY2mQ= -github.com/visualfc/funcval v0.1.4/go.mod h1:3Izv+irhArmrTvy+lmL6pIq16gSOzx73CIka51J9eR0= +github.com/timandy/routine v1.1.6 h1:cueNRVPutK8O6387LL7dmYPLNyS6aKlPCPi5qWCLdc8= +github.com/timandy/routine v1.1.6/go.mod h1:kXslgIosdY8LW0byTyPnenDgn4/azt2euufAq9rK51w= +github.com/visualfc/funcval v0.1.5 h1:jR21zdx0pFk4nUzmutrFZL6EiRuMYR/ZaD+KOzTwyEk= +github.com/visualfc/funcval v0.1.5/go.mod h1:3Izv+irhArmrTvy+lmL6pIq16gSOzx73CIka51J9eR0= +github.com/visualfc/gid v0.3.1 h1:wWnU17tIBISc7sbbfRxNIg0rdfJUqANZYeX04KbbhlU= +github.com/visualfc/gid v0.3.1/go.mod h1:vpt7mMzO6Mst8v6T4vCSTPKzrNwfVsaDZQ12T4eQT8o= github.com/visualfc/goembed v0.3.4 h1:foORJ0KT/pKwA23dStPFOtxaW7F96PnNSiLXHVXrfVk= github.com/visualfc/goembed v0.3.4/go.mod h1:jCVCz/yTJGyslo6Hta+pYxWWBuq9ADCcIVZBTQ0/iVI= -github.com/visualfc/xtype v0.3.0 h1:K0Oo5XMcSjv+ohqn8L6RjgOZ9dNwfzPv3/AIV1SXRfA= -github.com/visualfc/xtype v0.3.0/go.mod h1:VYIH9S2bmdWKlBb7c725ES6yKF9+pyHBU2SFNqGVMGM= +github.com/visualfc/xtype v0.3.2 h1:VUyIQhYhOlwYfiRCraEYYQoSsUnKNc6EUpD+ZwFFhJ4= +github.com/visualfc/xtype v0.3.2/go.mod h1:VYIH9S2bmdWKlBb7c725ES6yKF9+pyHBU2SFNqGVMGM= github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -49,8 +59,8 @@ golang.org/x/mobile v0.0.0-20220518205345-8578da9835fd h1:x1GptNaTtxPAlTVIAJk61f golang.org/x/mobile v0.0.0-20220518205345-8578da9835fd/go.mod h1:pe2sM7Uk+2Su1y7u/6Z8KJ24D7lepUjFZbhFOrmDfuQ= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA= -golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= +golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c= +golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -59,8 +69,8 @@ golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60= golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= -golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= +golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -73,10 +83,12 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.8-0.20211022200916-316ba0b74098/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= -golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ= -golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= +golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc= +golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/tools/ispx/internal/pkg/github.com/goplus/builder/tools/ai/export.go b/tools/ispx/internal/pkg/github.com/goplus/builder/tools/ai/export.go index 2f8e75ee6..0627dfc9f 100755 --- a/tools/ispx/internal/pkg/github.com/goplus/builder/tools/ai/export.go +++ b/tools/ispx/internal/pkg/github.com/goplus/builder/tools/ai/export.go @@ -19,7 +19,7 @@ func init() { "context": "context", "errors": "errors", "fmt": "fmt", - "github.com/goplus/spx/v2/pkg/spx": "spx", + "github.com/goplus/spx/v3/pkg/spx": "spx", "iter": "iter", "log": "log", "math": "math", diff --git a/tools/ispx/main.go b/tools/ispx/main.go index 0d4cdede0..5c2f6d528 100644 --- a/tools/ispx/main.go +++ b/tools/ispx/main.go @@ -8,7 +8,7 @@ import ( "github.com/goplus/ixgo" "github.com/goplus/ixgo/xgobuild" "github.com/goplus/mod/modfile" - "github.com/goplus/spx/v2/pkg/ispx" + "github.com/goplus/spx/v3/pkg/ispx" ) func init() { @@ -17,7 +17,7 @@ func init() { Ext: ".spx", Class: "Game", Works: []*modfile.Class{{Ext: ".spx", Class: "SpriteImpl", Embedded: true}}, - PkgPaths: []string{"github.com/goplus/spx/v2", "math"}, + PkgPaths: []string{"github.com/goplus/spx/v3", "math"}, Import: []*modfile.Import{{Name: "ai", Path: "github.com/goplus/builder/tools/ai"}}, }) } diff --git a/tools/spxls/go.mod b/tools/spxls/go.mod index 31f44b7bd..09235935d 100644 --- a/tools/spxls/go.mod +++ b/tools/spxls/go.mod @@ -6,17 +6,17 @@ tool github.com/goplus/xgolsw/cmd/pkgdatagen require ( github.com/goplus/builder/tools/ai v0.0.0 - github.com/goplus/xgolsw v0.21.1-0.20260630012157-8eb11678c926 + github.com/goplus/xgolsw v0.21.1-0.20260724040048-01cb10f4b21f ) require ( - github.com/goplus/gogen v1.23.0-pre.5 // indirect - github.com/goplus/mod v0.20.2 // indirect + github.com/goplus/gogen v1.23.5 // indirect + github.com/goplus/mod v0.21.1 // indirect github.com/goplus/spbase v0.1.0 // indirect - github.com/goplus/spx/v2 v2.0.4 // indirect - github.com/goplus/xgo v1.7.2 // indirect + github.com/goplus/spx/v3 v3.0.0 // indirect + github.com/goplus/xgo v1.7.5 // indirect github.com/petermattis/goid v0.0.0-20250721140440-ea1c0173183e // indirect - github.com/qiniu/x v1.17.0 // indirect + github.com/qiniu/x v1.18.0 // indirect golang.org/x/image v0.23.0 // indirect golang.org/x/mobile v0.0.0-20220518205345-8578da9835fd // indirect golang.org/x/mod v0.36.0 // indirect diff --git a/tools/spxls/go.sum b/tools/spxls/go.sum index edaab8934..fac72d27e 100644 --- a/tools/spxls/go.sum +++ b/tools/spxls/go.sum @@ -5,24 +5,24 @@ github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/goplus/gogen v1.23.0-pre.5 h1:0JD3RkuIWbgFPC5kNmNXZeWdXXujTqKxPQZ9uKz6Gsc= -github.com/goplus/gogen v1.23.0-pre.5/go.mod h1:Y7ulYW3wonQ3d9er00b0uGFEV/IUZa6okWJZh892ACQ= -github.com/goplus/mod v0.20.2 h1:YX72E6AhhRLvlkVnI9cBK6PZvUwtge2hwROh7w9N6Yk= -github.com/goplus/mod v0.20.2/go.mod h1:lWW62tH7L3Vm42Lr6wlUMYHvsm5w3TkEpE2ulKTgmU8= +github.com/goplus/gogen v1.23.5 h1:76w3zmAHI+ECI7bPr0enUd0du9+t1IYyXmp43CbIpSs= +github.com/goplus/gogen v1.23.5/go.mod h1:Y7ulYW3wonQ3d9er00b0uGFEV/IUZa6okWJZh892ACQ= +github.com/goplus/mod v0.21.1 h1:thTyYvCVFEQr8bilNW2DvgI6UwuCYqCWF7DaA/dhf/c= +github.com/goplus/mod v0.21.1/go.mod h1:VTyNmzzePgy99A2VQnxIBfoG1x097xilag/t0F0zuTg= github.com/goplus/spbase v0.1.0 h1:JNZ0D/65DerYyv9/9IfrXHZZbd0WNK0jHiVvgCtZhwY= github.com/goplus/spbase v0.1.0/go.mod h1:brnD3OJnHtipqob2IsJ3/QzGBf+eOnqXNnHGKpv1irQ= -github.com/goplus/spx/v2 v2.0.4 h1:4hyCM5XH3DMRjFeoTxCndrqcFZTeCWHkEicyp7wYTSs= -github.com/goplus/spx/v2 v2.0.4/go.mod h1:mF2kCvUNw97ku2PYHMEwbCENv24b5EwnlXOLiVMRbHM= -github.com/goplus/xgo v1.7.2 h1:leAinbUiz+oUukKfdYIXyYZlxm/gh6TkEg5/dzvevQk= -github.com/goplus/xgo v1.7.2/go.mod h1:QR2TaWixDRCYQfv0F7xpZbUPvuclcgg0oUFmcq5nNn0= -github.com/goplus/xgolsw v0.21.1-0.20260630012157-8eb11678c926 h1:LDYoxTq7UxoZppnHfCPQswH30MevNyoLTX8l0hrKFzo= -github.com/goplus/xgolsw v0.21.1-0.20260630012157-8eb11678c926/go.mod h1:ANgB42yf5ul2VDNMxp6v2yxbcwyNu1wV9IWekAgGSG4= +github.com/goplus/spx/v3 v3.0.0 h1:qy+NXFm3rGh2llWg+/koTyMwN56Gzpovg/ONJ1mTpqk= +github.com/goplus/spx/v3 v3.0.0/go.mod h1:wi1iUwx9g44B5wqGG6SusaGthOSz1YYYol/JkAM/pRs= +github.com/goplus/xgo v1.7.5 h1:biSNkiyWe3e+YmOmDRSs1Z6K4RLkLpzN6mTp1WbryAw= +github.com/goplus/xgo v1.7.5/go.mod h1:TRIPQ1bRVkq1x0+Ve/gWGS+qcb3ACPIZHNcmuiKzYkE= +github.com/goplus/xgolsw v0.21.1-0.20260724040048-01cb10f4b21f h1:dETdoNYT23EkXhlnqj8z0+QzQOUV1ua7H0tP4ixUZJI= +github.com/goplus/xgolsw v0.21.1-0.20260724040048-01cb10f4b21f/go.mod h1:PORsG7DeYrYngVVJuCmUxmTHihtXL0dytSWu6yZcNDc= github.com/petermattis/goid v0.0.0-20250721140440-ea1c0173183e h1:D0bJD+4O3G4izvrQUmzCL80zazlN7EwJ0PPDhpJWC/I= github.com/petermattis/goid v0.0.0-20250721140440-ea1c0173183e/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/qiniu/x v1.17.0 h1:OsyDKXzYp5vw9Hc7VAe4Cso1Sp50fLKGsBuDteyTevE= -github.com/qiniu/x v1.17.0/go.mod h1:AiovSOCaRijaf3fj+0CBOpR1457pn24b0Vdb1JpwhII= +github.com/qiniu/x v1.18.0 h1:iMfc7Gqy1au+akr+Tl5Z40px7TR8VBLLkJsIeajKIbc= +github.com/qiniu/x v1.18.0/go.mod h1:Sx3Wy+0GI9OsX4a53mYj6A0o7mHJ94PUvraqGYb4EIs= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= From eaae2ed4cce799a91b6a3904d67fd4166205d9df Mon Sep 17 00:00:00 2001 From: "fennoai[bot]" <231223108+fennoai[bot]@users.noreply.github.com> Date: Fri, 24 Jul 2026 14:39:28 +0800 Subject: [PATCH 3/8] feat(ispx): support setting username before running (xbuilder_set_username) (#3365) * feat(ispx): support setting username before running (xbuilder_set_username) Add `tools/ispx/username.go` exposing a JS-callable `xbuilder_set_username` that injects the current logged-in username into the spx runtime via `spx.User` (goplus/spx#1689). Call it in `ProjectRunner.vue` before running so Scratch-converted projects depending on the `username` capability work. Bump spx to the PR head commit that exposes `spx.User`; realign after goplus/spx#1689 is released. Closes #3364 Co-authored-by: fennoai[bot] <231223108+fennoai[bot]@users.noreply.github.com> Co-authored-by: go-wyvern <15845637+go-wyvern@users.noreply.github.com> * refactor(runner): resolve username via useSignedInStateQuery Address review feedback (goplus/builder#3365): replace the discouraged `getUnresolvedSignedInUsername()` (a best-effort local hint) with the canonical `useSignedInStateQuery()` when injecting the username into the spx runtime. Await the resolved signed-in state before running and pass the canonical username; for signed-out users pass an empty string, which spx treats as an anonymous user. Co-authored-by: fennoai[bot] <231223108+fennoai[bot]@users.noreply.github.com> Co-authored-by: go-wyvern <15845637+go-wyvern@users.noreply.github.com> --------- Co-authored-by: fennoai[bot] <231223108+fennoai[bot]@users.noreply.github.com> Co-authored-by: go-wyvern <15845637+go-wyvern@users.noreply.github.com> --- .../project/runner/ProjectRunner.vue | 12 +++++++++- tools/ispx/username.go | 24 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 tools/ispx/username.go diff --git a/spx-gui/src/components/project/runner/ProjectRunner.vue b/spx-gui/src/components/project/runner/ProjectRunner.vue index 4528ce249..d3c549774 100644 --- a/spx-gui/src/components/project/runner/ProjectRunner.vue +++ b/spx-gui/src/components/project/runner/ProjectRunner.vue @@ -56,6 +56,8 @@ interface RunnerIframeWindow extends Window { xbuilder_set_ai_interaction_api_endpoint: (endpoint: string) => void xbuilder_set_ai_interaction_api_token_provider: (provider: () => Promise) => void xbuilder_set_ai_description: (description: string) => void + /** Set the current logged-in username, injected into the spx runtime before running. */ + xbuilder_set_username: (username: string) => void /** Init the engine. Can be called early; project-agnostic. */ initEngine(assetURLs: Record, config?: EngineConfig): Promise /** Init the game with project files. Should be called after `initEngine`, before `startGame` or earlier (when files change, etc.). */ @@ -153,7 +155,7 @@ import type { Files } from '@/models/common/file' import { hashFiles } from '@/models/common/hash' import type { SpxProject } from '@/models/spx/project' import { UIImg, UIDetailedLoading } from '@/components/ui' -import { ensureAccessToken } from '@/stores/user' +import { ensureAccessToken, useSignedInStateQuery } from '@/stores/user' import { isProjectUsingAIInteraction } from '@/utils/project' import { capture, Cancelled } from '@/utils/exception' import { client } from '@/apis/common' @@ -172,6 +174,7 @@ const emit = defineEmits<{ }>() const [thumbnailUrl, thumbnailUrlLoading] = useRenderableImageUrl(() => props.project.thumbnail) +const signedInStateQuery = useSignedInStateQuery() const state = shallowRef({ type: 'initial' }) const runnerIframeRef = ref() const runnerIframeWindowRef = ref(null) @@ -342,6 +345,13 @@ async function runInternal(ctrl: AbortController) { await uiUpdated(ctrl.signal) + // Inject the current logged-in username into the spx runtime before running. + // Some projects (e.g. Scratch-converted ones) rely on Scratch's `username` capability. + // For signed-out users we set an empty string, which spx treats as an anonymous user. + // See https://github.com/goplus/builder/issues/3364. + const signedInState = await untilNotNull(signedInStateQuery.data, ctrl.signal) + iframeWindow.xbuilder_set_username(signedInState.isSignedIn ? signedInState.user.username : '') + // TODO: get progress for engine-loading, which is now included in `startGame` startGameReporter.startAutoReport(10_000) await iframeWindow.startGame() diff --git a/tools/ispx/username.go b/tools/ispx/username.go new file mode 100644 index 000000000..941333931 --- /dev/null +++ b/tools/ispx/username.go @@ -0,0 +1,24 @@ +//go:build js && wasm + +package main + +import ( + "syscall/js" + + "github.com/goplus/spx/v3/pkg/spx" +) + +func init() { + js.Global().Set("xbuilder_set_username", js.FuncOf(setUsername)) +} + +// setUsername sets the spx runtime username from JavaScript. It should be +// called before the game runs so that the spx runtime reports the current +// logged-in username via `Game.Username`. An empty string represents an +// anonymous user. See https://github.com/goplus/builder/issues/3364. +func setUsername(this js.Value, args []js.Value) any { + if len(args) > 0 { + spx.SetUsername(args[0].String()) + } + return nil +} From 9fd9f3d46a8cac2fa68a434f30f5d9144d823eb6 Mon Sep 17 00:00:00 2001 From: Hanxing Yang Date: Fri, 24 Jul 2026 15:38:49 +0800 Subject: [PATCH 4/8] fix: bundle DotLottie WASM asset (#3373) --- spx-gui/package.json | 1 + spx-gui/pnpm-lock.yaml | 3 +++ 2 files changed, 4 insertions(+) diff --git a/spx-gui/package.json b/spx-gui/package.json index a4f27156e..4a054b2f6 100644 --- a/spx-gui/package.json +++ b/spx-gui/package.json @@ -21,6 +21,7 @@ "dependencies": { "@floating-ui/dom": "^1.7.6", "@jridgewell/resolve-uri": "^3.1.2", + "@lottiefiles/dotlottie-web": "0.41.0", "@lottiefiles/dotlottie-vue": "^0.5.8", "@nighca/fflate": "^0.8.3", "@scalar/api-reference": "^1.40.0", diff --git a/spx-gui/pnpm-lock.yaml b/spx-gui/pnpm-lock.yaml index a10186b43..57528b344 100644 --- a/spx-gui/pnpm-lock.yaml +++ b/spx-gui/pnpm-lock.yaml @@ -17,6 +17,9 @@ importers: '@lottiefiles/dotlottie-vue': specifier: ^0.5.8 version: 0.5.8(vue@3.5.25(typescript@5.9.3)) + '@lottiefiles/dotlottie-web': + specifier: 0.41.0 + version: 0.41.0 '@nighca/fflate': specifier: ^0.8.3 version: 0.8.3 From 08a636207383d65be16924bad4132a2234a9e7ad Mon Sep 17 00:00:00 2001 From: Aofei Sheng Date: Mon, 27 Jul 2026 16:52:18 +0800 Subject: [PATCH 5/8] fix(api): expose user avatars as public URLs (#3319) Document user avatar responses as public HTTP URLs so the API contract matches backend display behavior while storage can continue using Kodo universal URLs internally. Remove the frontend Kodo avatar resolver and consume returned avatar URLs through existing external URL handling. Keep test data aligned with the public response contract. Signed-off-by: Aofei Sheng --- docs/openapi.yaml | 4 +-- spx-gui/src/apis/user.ts | 2 +- .../community/project/OwnerInfo.vue | 4 +-- .../community/user/EditProfileModal.vue | 4 +-- .../components/community/user/UserAvatar.vue | 4 +-- .../components/community/user/UserHeader.vue | 5 ++- .../src/components/copilot/UserMessage.vue | 4 +-- .../src/components/navbar/NavbarProfile.vue | 4 +-- spx-gui/src/stores/user/avatar.ts | 31 ------------------- spx-gui/src/stores/user/test.ts | 2 +- 10 files changed, 16 insertions(+), 48 deletions(-) delete mode 100644 spx-gui/src/stores/user/avatar.ts diff --git a/docs/openapi.yaml b/docs/openapi.yaml index ad4805613..263fb44b0 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -6357,12 +6357,12 @@ components: examples: - John Doe avatar: - description: Public HTTP URL or Kodo universal URL of the user's avatar image. + description: Public HTTP URL of the user's avatar image. type: string format: uri + pattern: "^https?://" examples: - https://avatars.example.com/users/10137.png - - kodo://xbuilder-usercontent-test/files/avatar.png description: description: Brief bio or description of the user. type: string diff --git a/spx-gui/src/apis/user.ts b/spx-gui/src/apis/user.ts index b5fd4a17e..bb9e3a926 100644 --- a/spx-gui/src/apis/user.ts +++ b/spx-gui/src/apis/user.ts @@ -16,7 +16,7 @@ export type User = { username: string /** Display name of the user */ displayName: string - /** URL of the user's avatar image */ + /** Public HTTP URL of the user's avatar image */ avatar: string /** Brief bio or description of the user */ description: string diff --git a/spx-gui/src/components/community/project/OwnerInfo.vue b/spx-gui/src/components/community/project/OwnerInfo.vue index 211ec91aa..d03d923a3 100644 --- a/spx-gui/src/components/community/project/OwnerInfo.vue +++ b/spx-gui/src/components/community/project/OwnerInfo.vue @@ -1,6 +1,6 @@ diff --git a/spx-gui/src/components/community/user/EditProfileModal.vue b/spx-gui/src/components/community/user/EditProfileModal.vue index b20651752..4c7915a22 100644 --- a/spx-gui/src/components/community/user/EditProfileModal.vue +++ b/spx-gui/src/components/community/user/EditProfileModal.vue @@ -4,6 +4,7 @@ import { userDescriptionMaxLength, userDisplayNameMaxLength, type User } from '@ import { selectFile } from '@/utils/file' import { DefaultException, useMessageHandle } from '@/utils/exception' import { useI18n } from '@/utils/i18n' +import { useExternalUrl } from '@/utils/utils' import { UIButton, UIForm, @@ -17,7 +18,6 @@ import { } from '@/components/ui' import { getCoverImgUrl } from './cover' import { useUpdateSignedInUser } from '@/stores/user' -import { useAvatarUrl } from '@/stores/user/avatar' import EditAvatarModal from './EditAvatarModal.vue' import UserUsernameInline from './UserUsernameInline.vue' @@ -38,7 +38,7 @@ const acceptedAvatarFileExts = ['png', 'jpg', 'jpeg', 'webp'] const coverImgUrl = computed(() => getCoverImgUrl(props.user.username)) const pendingAvatarRef = ref(null) const currentAvatar = computed(() => pendingAvatarRef.value ?? props.user.avatar) -const avatarUrl = useAvatarUrl(() => currentAvatar.value) +const avatarUrl = useExternalUrl(() => currentAvatar.value) const form = useForm({ displayName: [props.user.displayName, validateDisplayName], diff --git a/spx-gui/src/components/community/user/UserAvatar.vue b/spx-gui/src/components/community/user/UserAvatar.vue index 580520f46..c7cc28647 100644 --- a/spx-gui/src/components/community/user/UserAvatar.vue +++ b/spx-gui/src/components/community/user/UserAvatar.vue @@ -8,8 +8,8 @@ diff --git a/spx-gui/src/components/community/user/UserHeader.vue b/spx-gui/src/components/community/user/UserHeader.vue index c56133912..ce8a62c96 100644 --- a/spx-gui/src/components/community/user/UserHeader.vue +++ b/spx-gui/src/components/community/user/UserHeader.vue @@ -2,10 +2,9 @@ import { computed } from 'vue' import { useRoute, useRouter } from 'vue-router' import { type User } from '@/apis/user' -import { useAvatarUrl } from '@/stores/user/avatar' import { useMessageHandle } from '@/utils/exception' import { useI18n } from '@/utils/i18n' -import { timeout } from '@/utils/utils' +import { timeout, useExternalUrl } from '@/utils/utils' import { useSignIn, useSignedInUser } from '@/stores/user' import { UIButton, UICard, UIImg, useMessage, useModal } from '@/components/ui' import TextView from '../TextView.vue' @@ -23,7 +22,7 @@ const router = useRouter() const route = useRoute() const signedInUser = useSignedInUser() const isSignedInUser = computed(() => props.user.username === signedInUser.value?.username) -const avatarUrl = useAvatarUrl(() => props.user.avatar) +const avatarUrl = useExternalUrl(() => props.user.avatar) const coverImgUrl = computed(() => getCoverImgUrl(props.user.username)) const invokeEditProfileModal = useModal(EditProfileModal) diff --git a/spx-gui/src/components/copilot/UserMessage.vue b/spx-gui/src/components/copilot/UserMessage.vue index 31fd53159..3cc28d7d9 100644 --- a/spx-gui/src/components/copilot/UserMessage.vue +++ b/spx-gui/src/components/copilot/UserMessage.vue @@ -1,6 +1,6 @@