Skip to content

Commit 0983c43

Browse files
authored
Merge pull request #8798 from google/develop-v12-merge
chore: Merge develop into rc/v12.0.0
2 parents 00d7745 + b8f71b8 commit 0983c43

25 files changed

Lines changed: 780 additions & 455 deletions

.github/workflows/appengine_deploy.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ jobs:
4242
path: _deploy/
4343

4444
- name: Deploy to App Engine
45-
uses: google-github-actions/deploy-appengine@v2.1.4
45+
uses: google-github-actions/deploy-appengine@v2.1.5
4646
# For parameters see:
4747
# https://github.com/google-github-actions/deploy-appengine#inputs
4848
with:

core/block_animations.ts

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -176,30 +176,38 @@ export function disconnectUiEffect(block: BlockSvg) {
176176
}
177177
// Start the animation.
178178
wobblingBlock = block;
179-
disconnectUiStep(block, magnitude, new Date());
179+
disconnectUiStep(block, magnitude, new Date(), 0);
180180
}
181181

182182
/**
183183
* Animate a brief wiggle of a disconnected block.
184184
*
185185
* @param block Block to animate.
186186
* @param magnitude Maximum degrees skew (reversed for RTL).
187-
* @param start Date of animation's start.
187+
* @param start Date of animation's start for deciding when to stop.
188+
* @param step Which step of the animation we're on.
188189
*/
189-
function disconnectUiStep(block: BlockSvg, magnitude: number, start: Date) {
190+
function disconnectUiStep(
191+
block: BlockSvg,
192+
magnitude: number,
193+
start: Date,
194+
step: number,
195+
) {
190196
const DURATION = 200; // Milliseconds.
191-
const WIGGLES = 3; // Half oscillations.
192-
193-
const ms = new Date().getTime() - start.getTime();
194-
const percent = ms / DURATION;
197+
const WIGGLES = [0.66, 1, 0.66, 0, -0.66, -1, -0.66, 0]; // Single cycle
195198

196199
let skew = '';
197-
if (percent <= 1) {
198-
const val = Math.round(
199-
Math.sin(percent * Math.PI * WIGGLES) * (1 - percent) * magnitude,
200-
);
200+
if (start.getTime() + DURATION > new Date().getTime()) {
201+
const val = Math.round(WIGGLES[step % WIGGLES.length] * magnitude);
201202
skew = `skewX(${val})`;
202-
disconnectPid = setTimeout(disconnectUiStep, 10, block, magnitude, start);
203+
disconnectPid = setTimeout(
204+
disconnectUiStep,
205+
15,
206+
block,
207+
magnitude,
208+
start,
209+
step + 1,
210+
);
203211
}
204212

205213
block

core/bubbles/text_bubble.ts

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {Bubble} from './bubble.js';
1616
* A bubble that displays non-editable text. Used by the warning icon.
1717
*/
1818
export class TextBubble extends Bubble {
19-
private paragraph: SVGTextElement;
19+
private paragraph: SVGGElement;
2020

2121
constructor(
2222
private text: string,
@@ -49,43 +49,52 @@ export class TextBubble extends Bubble {
4949
*/
5050
private stringToSvg(text: string, container: SVGGElement) {
5151
const paragraph = this.createParagraph(container);
52-
const spans = this.createSpans(paragraph, text);
52+
const fragments = this.createTextFragments(paragraph, text);
5353
if (this.workspace.RTL)
54-
this.rightAlignSpans(paragraph.getBBox().width, spans);
54+
this.rightAlignTextFragments(paragraph.getBBox().width, fragments);
5555
return paragraph;
5656
}
5757

58-
/** Creates the paragraph container for this bubble's view's spans. */
59-
private createParagraph(container: SVGGElement): SVGTextElement {
58+
/** Creates the paragraph container for this bubble's view's text fragments. */
59+
private createParagraph(container: SVGGElement): SVGGElement {
6060
return dom.createSvgElement(
61-
Svg.TEXT,
61+
Svg.G,
6262
{
6363
'class': 'blocklyText blocklyBubbleText blocklyNoPointerEvents',
64-
'y': Bubble.BORDER_WIDTH,
64+
'transform': `translate(0,${Bubble.BORDER_WIDTH})`,
65+
'style': `direction: ${this.workspace.RTL ? 'rtl' : 'ltr'}`,
6566
},
6667
container,
6768
);
6869
}
6970

70-
/** Creates the spans visualizing the text of this bubble. */
71-
private createSpans(parent: SVGTextElement, text: string): SVGTSpanElement[] {
71+
/** Creates the text fragments visualizing the text of this bubble. */
72+
private createTextFragments(
73+
parent: SVGGElement,
74+
text: string,
75+
): SVGTextElement[] {
76+
let lineNum = 1;
7277
return text.split('\n').map((line) => {
73-
const tspan = dom.createSvgElement(
74-
Svg.TSPAN,
75-
{'dy': '1em', 'x': Bubble.BORDER_WIDTH},
78+
const fragment = dom.createSvgElement(
79+
Svg.TEXT,
80+
{'y': `${lineNum}em`, 'x': Bubble.BORDER_WIDTH},
7681
parent,
7782
);
7883
const textNode = document.createTextNode(line);
79-
tspan.appendChild(textNode);
80-
return tspan;
84+
fragment.appendChild(textNode);
85+
lineNum += 1;
86+
return fragment;
8187
});
8288
}
8389

84-
/** Right aligns the given spans. */
85-
private rightAlignSpans(maxWidth: number, spans: SVGTSpanElement[]) {
86-
for (const span of spans) {
87-
span.setAttribute('text-anchor', 'end');
88-
span.setAttribute('x', `${maxWidth + Bubble.BORDER_WIDTH}`);
90+
/** Right aligns the given text fragments. */
91+
private rightAlignTextFragments(
92+
maxWidth: number,
93+
fragments: SVGTextElement[],
94+
) {
95+
for (const text of fragments) {
96+
text.setAttribute('text-anchor', 'start');
97+
text.setAttribute('x', `${maxWidth + Bubble.BORDER_WIDTH}`);
8998
}
9099
}
91100

core/comments/rendered_workspace_comment.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,8 +213,14 @@ export class RenderedWorkspaceComment
213213
private startGesture(e: PointerEvent) {
214214
const gesture = this.workspace.getGesture(e);
215215
if (gesture) {
216-
gesture.handleCommentStart(e, this);
217-
this.workspace.getLayerManager()?.append(this, layers.BLOCK);
216+
if (browserEvents.isTargetInput(e)) {
217+
// If the text area was the focus, don't allow this event to bubble up
218+
// and steal focus away from the editor/comment.
219+
e.stopPropagation();
220+
} else {
221+
gesture.handleCommentStart(e, this);
222+
this.workspace.getLayerManager()?.append(this, layers.BLOCK);
223+
}
218224
common.setSelected(this);
219225
}
220226
}

core/css.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,7 @@ input[type=number] {
321321
322322
.blocklyScrollbarBackground {
323323
opacity: 0;
324+
pointer-events: none;
324325
}
325326
326327
.blocklyScrollbarHandle {

core/field_dropdown.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import {Coordinate} from './utils/coordinate.js';
3030
import * as dom from './utils/dom.js';
3131
import * as parsing from './utils/parsing.js';
3232
import * as utilsString from './utils/string.js';
33+
import * as style from './utils/style.js';
3334
import {Svg} from './utils/svg.js';
3435

3536
/**
@@ -302,6 +303,11 @@ export class FieldDropdown extends Field<string> {
302303

303304
if (this.selectedMenuItem) {
304305
this.menu_!.setHighlighted(this.selectedMenuItem);
306+
style.scrollIntoContainerView(
307+
this.selectedMenuItem.getElement()!,
308+
dropDownDiv.getContentDiv(),
309+
true,
310+
);
305311
}
306312

307313
this.applyColour();

core/inject.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,16 @@ export function inject(
7777
});
7878

7979
browserEvents.conditionalBind(subContainer, 'keydown', null, onKeyDown);
80+
browserEvents.conditionalBind(
81+
dropDownDiv.getContentDiv(),
82+
'keydown',
83+
null,
84+
onKeyDown,
85+
);
86+
const widgetContainer = WidgetDiv.getDiv();
87+
if (widgetContainer) {
88+
browserEvents.conditionalBind(widgetContainer, 'keydown', null, onKeyDown);
89+
}
8090

8191
return workspace;
8292
}

0 commit comments

Comments
 (0)