Skip to content

Commit c6b59a7

Browse files
committed
update
1 parent ff59323 commit c6b59a7

19 files changed

+767
-163
lines changed

css/activities.css

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,72 @@
9090
font-size: large;
9191
}
9292

93+
.trash-view {
94+
position: relative;
95+
background-color: white;
96+
max-width: 396px;
97+
max-height: 200px;
98+
overflow-y: auto;
99+
font-size: 16px;
100+
color: black;
101+
border: 2px solid #87cefa;
102+
list-style-type: none;
103+
margin: 0;
104+
padding: 0;
105+
text-align: left;
106+
}
107+
108+
.button-container {
109+
position: sticky;
110+
display: flex;
111+
justify-content: space-between;
112+
top: 0;
113+
z-index: 10;
114+
display: flex;
115+
gap: 10px;
116+
background: #2196F3;
117+
margin: 0;
118+
padding: 5px;
119+
border-bottom: 1px solid #d9d9d9;
120+
}
121+
122+
.trash-item {
123+
padding: 2px 12px;
124+
margin: 1px 0;
125+
border-radius: 4px;
126+
transition: background-color 0.3s;
127+
}
128+
129+
.trash-item.hover {
130+
background-color: #d9d9d9;
131+
}
132+
133+
.trash-item-icon {
134+
width: 30px;
135+
height: 30px;
136+
margin-right: 10px;
137+
vertical-align: middle;
138+
}
139+
140+
#restoreLastIcon, #restoreAllIcon {
141+
display: flex;
142+
align-items: center;
143+
justify-content: center;
144+
width: 48px;
145+
height: 48px;
146+
cursor: pointer;
147+
}
148+
149+
150+
.material-icons.md-48 {
151+
font-size: 32px;
152+
}
153+
154+
155+
.hidden {
156+
display: none;
157+
}
158+
93159
.ui-menu {
94160
position: relative;
95161
background-color: rgba(255, 255, 255, 1);
@@ -982,6 +1048,7 @@ table {
9821048
#helpBodyDiv .message {
9831049
text-align: center;
9841050
line-height: 1.2;
1051+
margin: auto;
9851052
}
9861053

9871054
#helpBodyDiv .icon-container {

index.html

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -175,21 +175,26 @@
175175
</script>
176176
<div class="loading-text" id="loadingText" style="margin-top:1.5rem;"></div>
177177
<script>
178-
document.addEventListener("DOMContentLoaded", function() {
179-
setTimeout(function() {
180-
const loadingText = document.getElementById("loadingText");
181-
const texts = ["Do, Re, Mi, Fa, Sol, La, Ti, Do", "Loading Music Blocks...", "Reading Music..."];
182-
183-
let index = 0;
184-
setInterval(function() {
185-
loadingText.textContent = texts[index];
186-
index = (index + 1) % texts.length;
187-
}, 2000); // Change 2000 to adjust cycle duration (in milliseconds)
188-
189-
// Show the loading text after 6 seconds
190-
loadingText.style.opacity = 1;
191-
}, 4000); // Change 6000 to adjust the delay (in milliseconds)
192-
});
178+
document.addEventListener("DOMContentLoaded", function () {
179+
setTimeout(function () {
180+
const loadingText = document.getElementById("loadingText");
181+
const texts = [_("Do, Re, Mi, Fa, Sol, La, Ti, Do"), _("Loading Music Blocks..."), _("Reading Music...")];
182+
let index = 0;
183+
184+
const intervalId = setInterval(function () {
185+
loadingText.textContent = texts[index];
186+
index = (index + 1) % texts.length;
187+
}, 1500);
188+
189+
// Stop changing text and finalize loading after 6 seconds
190+
setTimeout(function () {
191+
clearInterval(intervalId);
192+
loadingText.textContent = _("Loading Complete!");
193+
loadingText.style.opacity = 1;
194+
}, 6000);
195+
}, 4000);
196+
});
197+
193198
</script>
194199
</div>
195200

@@ -515,7 +520,7 @@
515520
<div
516521
id="mb-logo"
517522
class="logo left tooltipped"
518-
style="line-height: 0; height: 100%; padding-right: 0;"
523+
style="display: flex; align-items: center; line-height: 0; height: 100%; padding-right: 0;"
519524
data-position="bottom"
520525
>
521526
<amp-img
@@ -780,6 +785,7 @@
780785
>
781786
<a style="color: transparent;">space&nbsp;&nbsp;&nbsp;</a>
782787
</li>
788+
783789
<li>
784790
<a
785791
id="restoreIcon"
@@ -789,6 +795,7 @@
789795
>restore_from_trash</i
790796
></a
791797
>
798+
<div id="trashList"></div>
792799
</li>
793800
<li>
794801
<a

js/SaveInterface.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,7 @@ class SaveInterface {
533533
* @instance
534534
*/
535535
afterSaveLilypond(filename) {
536+
filename = docById("fileName").value;
536537
const ly = saveLilypondOutput(this.activity);
537538
switch (this.notationConvert) {
538539
case "pdf":
@@ -559,6 +560,7 @@ class SaveInterface {
559560
*/
560561

561562
afterSaveLilypondLY(lydata, filename) {
563+
filename = docById("fileName").value;
562564
if (platform.FF) {
563565
// eslint-disable-next-line no-console
564566
console.debug('execCommand("copy") does not work on FireFox');

js/__tests__/basicblocks.test.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
const { initBasicProtoBlocks, BACKWARDCOMPATIBILIYDICT } = require('../basicblocks');
2+
3+
const mockActivity = {
4+
blocks: {
5+
palettes: {},
6+
protoBlockDict: {
7+
block1: { palette: { add: jest.fn() } },
8+
block2: { palette: { add: jest.fn() } },
9+
blockWithoutPalette: {}
10+
}
11+
},
12+
palettes: {},
13+
};
14+
15+
const setupFunctions = [
16+
'setupRhythmBlockPaletteBlocks', 'setupRhythmBlocks', 'setupMeterBlocks',
17+
'setupPitchBlocks', 'setupIntervalsBlocks', 'setupToneBlocks',
18+
'setupOrnamentBlocks', 'setupVolumeBlocks', 'setupDrumBlocks',
19+
'setupWidgetBlocks', 'setupFlowBlocks', 'setupNumberBlocks',
20+
'setupActionBlocks', 'setupBoxesBlocks', 'setupBooleanBlocks',
21+
'setupHeapBlocks', 'setupDictBlocks', 'setupExtrasBlocks',
22+
'setupProgramBlocks', 'setupGraphicsBlocks', 'setupPenBlocks',
23+
'setupMediaBlocks', 'setupSensorsBlocks', 'setupEnsembleBlocks'
24+
];
25+
26+
setupFunctions.forEach(fnName => {
27+
global[fnName] = jest.fn();
28+
});
29+
30+
describe('initBasicProtoBlocks', () => {
31+
beforeEach(() => {
32+
jest.clearAllMocks();
33+
});
34+
35+
it('should assign palettes to activity.blocks.palettes', () => {
36+
initBasicProtoBlocks(mockActivity);
37+
expect(mockActivity.blocks.palettes).toBe(mockActivity.palettes);
38+
});
39+
40+
it('should call all setup functions with activity', () => {
41+
initBasicProtoBlocks(mockActivity);
42+
setupFunctions.forEach(fnName => {
43+
expect(global[fnName]).toHaveBeenCalledWith(mockActivity);
44+
});
45+
});
46+
47+
it('should add blocks with palettes to their respective palettes', () => {
48+
initBasicProtoBlocks(mockActivity);
49+
50+
expect(mockActivity.blocks.protoBlockDict.block1.palette.add).toHaveBeenCalledWith(
51+
mockActivity.blocks.protoBlockDict.block1
52+
);
53+
expect(mockActivity.blocks.protoBlockDict.block2.palette.add).toHaveBeenCalledWith(
54+
mockActivity.blocks.protoBlockDict.block2
55+
);
56+
expect(mockActivity.blocks.protoBlockDict.blockWithoutPalette.palette).toBeUndefined();
57+
});
58+
});
59+
60+
describe('BACKWARDCOMPATIBILIYDICT', () => {
61+
it('should be defined and not empty', () => {
62+
expect(BACKWARDCOMPATIBILIYDICT).toBeDefined();
63+
expect(Object.keys(BACKWARDCOMPATIBILIYDICT).length).toBeGreaterThan(0);
64+
});
65+
66+
it('should correctly map old block names to new block names', () => {
67+
expect(BACKWARDCOMPATIBILIYDICT.fullscreen).toBe('vspace');
68+
expect(BACKWARDCOMPATIBILIYDICT.seth).toBe('setheading');
69+
expect(BACKWARDCOMPATIBILIYDICT.random2).toBe('random');
70+
});
71+
});

js/__tests__/boundary.test.js

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
global.base64Encode = jest.fn((str) => str);
2+
global.createjs = {
3+
Container: jest.fn(() => ({
4+
children: [],
5+
addChild: jest.fn(),
6+
removeChild: jest.fn(),
7+
visible: true,
8+
})),
9+
Bitmap: jest.fn(),
10+
};
11+
12+
global.window = {
13+
btoa: jest.fn((str) => Buffer.from(str).toString("base64")),
14+
};
15+
16+
global.BOUNDARY = `
17+
<svg xmlns="http://www.w3.org/2000/svg" width="WIDTH" height="HEIGHT">
18+
<rect x="X" y="Y" width="DX" height="DY" stroke="stroke_color" fill="none" stroke-width="2"/>
19+
</svg>
20+
`;
21+
22+
const Boundary = require('../boundary');
23+
24+
describe('Boundary Class', () => {
25+
let stage;
26+
let boundary;
27+
28+
beforeEach(() => {
29+
stage = {
30+
addChild: jest.fn(),
31+
setChildIndex: jest.fn(),
32+
};
33+
34+
boundary = new Boundary(stage);
35+
});
36+
37+
afterEach(() => {
38+
jest.clearAllMocks();
39+
});
40+
41+
it('should initialize with a container and add it to the stage', () => {
42+
expect(stage.addChild).toHaveBeenCalledWith(boundary._container);
43+
expect(stage.setChildIndex).toHaveBeenCalledWith(boundary._container, 0);
44+
});
45+
46+
it('should call create and destroy methods when setting scale', () => {
47+
const createSpy = jest.spyOn(boundary, 'create');
48+
const destroySpy = jest.spyOn(boundary, 'destroy');
49+
50+
boundary.setScale(800, 600, 2);
51+
52+
expect(destroySpy).toHaveBeenCalled();
53+
expect(createSpy).toHaveBeenCalledWith(800, 600, 2);
54+
});
55+
56+
it('should correctly determine if a point is off-screen', () => {
57+
boundary.create(800, 600, 2);
58+
59+
expect(boundary.offScreen(50, 50)).toBe(true);
60+
expect(boundary.offScreen(boundary.x + 1, boundary.y + 1)).toBe(false);
61+
expect(boundary.offScreen(boundary.x + boundary.dx + 1, boundary.y + boundary.dy + 1)).toBe(true);
62+
});
63+
64+
it('should hide and show the container', () => {
65+
boundary.hide();
66+
expect(boundary._container.visible).toBe(false);
67+
68+
boundary.show();
69+
expect(boundary._container.visible).toBe(true);
70+
});
71+
72+
it('should destroy the first child in the container', () => {
73+
const childMock = {};
74+
boundary._container.children.push(childMock);
75+
76+
boundary.destroy();
77+
expect(boundary._container.removeChild).toHaveBeenCalledWith(childMock);
78+
});
79+
80+
it('should create a boundary with the correct dimensions and add it to the container', () => {
81+
const mockImage = { onload: null, src: '' };
82+
const imgMock = jest.spyOn(global, 'Image').mockImplementation(() => mockImage);
83+
84+
boundary.create(800, 600, 2);
85+
86+
expect(mockImage.onload).not.toBeNull();
87+
expect(mockImage.src).toContain('data:image/svg+xml;base64,');
88+
imgMock.mockRestore();
89+
});
90+
});

0 commit comments

Comments
 (0)