studio-engine 0.25.0 → 0.25.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +32 -1
- data/app/views/studio/_leveling_activity_assets.html.erb +38 -5
- data/lib/studio/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d87b5711dd0833ea78e20b6f3174dd57e5cc3b0311e56f962e8954a408943963
|
|
4
|
+
data.tar.gz: 81708f5604bdebaa3f08504169e4bf1a55ba8ea9d8856f04594dbe49295d553c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b3ffce4a4ba6b91444902123ee106f9f88fec2be0606d69f310ff464bfe336ca444de94f85c2c81873feb335080e2a9fc01390ff48df7f87977e645e0c3397ac
|
|
7
|
+
data.tar.gz: 6584381c67a206525171c7195ded0999f8ce20ad896196aa8259b116e450c7db2a23ed95193dcb8281e49f57f09c5010817ce67e127bcc3d10c517ca4a67ca16
|
data/CHANGELOG.md
CHANGED
|
@@ -2,7 +2,38 @@
|
|
|
2
2
|
|
|
3
3
|
The format is [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). This project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html) — `MAJOR.MINOR.PATCH`. Consumer Rails apps install the released RubyGems package with `gem "studio-engine", "~> 0.6"`; bumping the gem version and updating consumer lockfiles is a release.
|
|
4
4
|
|
|
5
|
-
## 0.25.
|
|
5
|
+
## 0.25.1 — 2026-07-28
|
|
6
|
+
|
|
7
|
+
**Fix the Profile Leveling save-close regression 0.25.0 introduced.** The 0.25.0
|
|
8
|
+
rebuild made `_finishSaved` ALWAYS advance to the engine's own updated view (the
|
|
9
|
+
seeds celebration or the plain confirmation), on the belief that Turf Monster's
|
|
10
|
+
live usage was "unaffected." It was not: TM's change-username modal
|
|
11
|
+
(`leveling: false`, `saved_event: "studio:username-saved"`) drives its OWN
|
|
12
|
+
post-save follow-on — its listener runs `completeQuest` and closes/swaps. With
|
|
13
|
+
the engine now also advancing to its own confirm view, the next quest step
|
|
14
|
+
("Send Your First Message") rendered TWICE at once — once in the post-save modal
|
|
15
|
+
dialog, once in the inline quest card behind it — which TM's Playwright e2e
|
|
16
|
+
caught as a strict-mode double-render (`quest_ladder_web2`, `quest_ladder_web3`,
|
|
17
|
+
and the web3 step-dedup contract). In 0.24 a `leveling: false` modal rendered no
|
|
18
|
+
celebrate view and let the app close it, so the step rendered once.
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- **`studio/_leveling_activity_assets`** (factory) — `_finishSaved` now CLOSES on
|
|
23
|
+
save (fires the `saved_event`, then stops — the 0.24 contract) instead of
|
|
24
|
+
advancing to the engine's own confirm/celebrate WHEN the consuming app drives
|
|
25
|
+
its own follow-on. A new `appDrivenFollowOn` getter is that signal: a **non-demo**
|
|
26
|
+
caller that wired its OWN (non-default) `saved_event` owns the after-save UI, so
|
|
27
|
+
the engine yields (it never force-closes — the app's listener owns close-vs-swap,
|
|
28
|
+
which TM relies on: close on the contest page, swap to `quest-success` on
|
|
29
|
+
`/account`). **Demo** previews (`/admin/style`) and **standalone** callers on the
|
|
30
|
+
DEFAULT `saved_event` are unchanged — they still advance to the seeds celebration
|
|
31
|
+
(TM shape) or the plain confirmation (MS shape), and the "Great Username" /
|
|
32
|
+
"Subscribed!" specimen cards still open straight at their celebrate state via
|
|
33
|
+
`props.celebrate`. No consumer change is required; TM's existing wiring restores
|
|
34
|
+
its own contract.
|
|
35
|
+
|
|
36
|
+
|
|
6
37
|
|
|
7
38
|
**Profile Leveling** — the `/admin/style` "Leveling activities" section is rebuilt
|
|
8
39
|
into a single toggle-driven "Profile Leveling" flow, and the with-leveling /
|
|
@@ -37,6 +37,10 @@
|
|
|
37
37
|
if none); it owns EVERY app-side detail of that step.
|
|
38
38
|
savedEvent DOM event dispatched on success, carrying the app payload, so
|
|
39
39
|
the app can run its own follow-on. Default "studio:activity-saved".
|
|
40
|
+
A non-demo caller that supplies its OWN (non-default) saved_event
|
|
41
|
+
is declaring it drives that follow-on: the engine then CLOSES on
|
|
42
|
+
save (fires the event, stops) rather than rendering its own
|
|
43
|
+
confirm/celebrate, so the app's follow-on never renders twice.
|
|
40
44
|
store Alpine modal store name backing close(). Default "modals".
|
|
41
45
|
leveling the render-time DEFAULT for the seeds celebration. The live
|
|
42
46
|
value is read at RUNTIME from the modal store's current
|
|
@@ -56,6 +60,11 @@
|
|
|
56
60
|
<script>
|
|
57
61
|
(function () {
|
|
58
62
|
if (window.levelingActionModal) return;
|
|
63
|
+
// The default saved event. A non-demo caller that wires its OWN (non-default)
|
|
64
|
+
// saved_event is declaring it drives the post-save follow-on itself — see the
|
|
65
|
+
// appDrivenFollowOn getter, which then makes the engine close on save instead of
|
|
66
|
+
// rendering its own confirm/celebrate.
|
|
67
|
+
var DEFAULT_SAVED_EVENT = "studio:activity-saved";
|
|
59
68
|
window.levelingActionModal = function (opts) {
|
|
60
69
|
opts = opts || {};
|
|
61
70
|
return {
|
|
@@ -66,7 +75,7 @@
|
|
|
66
75
|
submitUrl: opts.submitUrl || "",
|
|
67
76
|
finalizeUrl: opts.finalizeUrl || "",
|
|
68
77
|
finalizeHook: opts.finalizeHook || "",
|
|
69
|
-
savedEvent: opts.savedEvent ||
|
|
78
|
+
savedEvent: opts.savedEvent || DEFAULT_SAVED_EVENT,
|
|
70
79
|
store: opts.store || "modals",
|
|
71
80
|
// leveling is a RUNTIME getter (below) reading props.leveling off the modal
|
|
72
81
|
// store, so ONE modal id flips TM <-> MS shape live as a section toggle
|
|
@@ -129,6 +138,21 @@
|
|
|
129
138
|
return v !== (this.original || "").trim();
|
|
130
139
|
},
|
|
131
140
|
|
|
141
|
+
// appDrivenFollowOn — a real (non-demo) consumer that wired its OWN saved_event
|
|
142
|
+
// owns the after-save UI: its listener runs the follow-on (e.g. Turf Monster's
|
|
143
|
+
// completeQuest / quest-success on 'studio:username-saved'), including whether
|
|
144
|
+
// to close, swap, or advance. For those the engine must NOT advance to its own
|
|
145
|
+
// confirm/celebrate on save — that double-renders the app's follow-on step
|
|
146
|
+
// (once in this dialog, once in the app's own inline card: the strict-mode
|
|
147
|
+
// double-render TM's e2e caught). The engine yields: it fires the saved event,
|
|
148
|
+
// then STOPS (the 0.24 contract), letting the app drive. Demo previews (self-
|
|
149
|
+
// contained) and standalone callers on the DEFAULT event keep the engine's own
|
|
150
|
+
// confirm/celebrate.
|
|
151
|
+
get appDrivenFollowOn() {
|
|
152
|
+
if (this.demo) return false;
|
|
153
|
+
return this.savedEvent !== DEFAULT_SAVED_EVENT;
|
|
154
|
+
},
|
|
155
|
+
|
|
132
156
|
_dispatch: function (payload) {
|
|
133
157
|
// In demo mode (the /admin/style preview) do NOT fire the app-facing
|
|
134
158
|
// saved event: the host app may listen for it and open its OWN follow-on
|
|
@@ -149,10 +173,19 @@
|
|
|
149
173
|
this.progressLabel = "";
|
|
150
174
|
if (this.hasInput) this.original = (this.value || "").trim();
|
|
151
175
|
this._dispatch(payload);
|
|
152
|
-
//
|
|
153
|
-
//
|
|
154
|
-
//
|
|
155
|
-
//
|
|
176
|
+
// App-driven follow-on: the consumer wired its own saved_event and owns
|
|
177
|
+
// what comes next (its listener advances/closes/swaps). Dispatch fired
|
|
178
|
+
// above; STOP here — the 0.24 contract — instead of advancing to the
|
|
179
|
+
// engine's own confirm/celebrate, which would render the app's follow-on
|
|
180
|
+
// step twice. The engine never force-closes here: the app's listener owns
|
|
181
|
+
// close-vs-swap (TM closes on the contest page, swaps to quest-success on
|
|
182
|
+
// /account), so a force-close would clobber that swap.
|
|
183
|
+
if (this.appDrivenFollowOn) return;
|
|
184
|
+
// Otherwise (a demo preview, or a standalone caller on the DEFAULT event
|
|
185
|
+
// with no app follow-on): advance to the updated state; the view gate
|
|
186
|
+
// (celebrate && leveling vs celebrate && !leveling) picks the seeds
|
|
187
|
+
// celebration (TM shape) or the plain confirmation (MS shape). Seeds are
|
|
188
|
+
// set either way — only the leveling view reads them.
|
|
156
189
|
this.seedsEarned = parseInt(payload.seeds_earned, 10) || 0;
|
|
157
190
|
this.seedsTotal = parseInt(payload.seeds_total, 10) || 0;
|
|
158
191
|
this.celebrate = true;
|
data/lib/studio/version.rb
CHANGED