@mideind/netskrafl-react 1.0.0-beta.2 → 1.0.0-beta.3
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.
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/netskrafl/Netskrafl.tsx +5 -2
- package/src/css/skrafl-explo.css +26 -30
- package/src/mithril/board.ts +21 -18
- package/src/mithril/chat.ts +1 -1
- package/src/mithril/page.ts +0 -1
- package/src/mithril/tile.ts +4 -4
package/package.json
CHANGED
|
@@ -85,15 +85,17 @@ const NetskraflImpl: React.FC<INetskraflProps> = ({ state, tokenExpired }) => {
|
|
|
85
85
|
|
|
86
86
|
useEffect(() => {
|
|
87
87
|
// Load the Netskrafl (Mithril) UI for a new user
|
|
88
|
+
// console.log("Mounting Netskrafl UI for user", userEmail);
|
|
88
89
|
if (!userEmail) return;
|
|
89
90
|
const container = ref.current;
|
|
90
91
|
if (!container) {
|
|
91
|
-
|
|
92
|
+
console.error("No container for Netskrafl UI");
|
|
92
93
|
return;
|
|
93
94
|
}
|
|
94
95
|
const elemId = `netskrafl-user-${userEmail}`;
|
|
95
96
|
if (container.firstElementChild?.id === elemId) {
|
|
96
97
|
// Already exists and correctly mounted
|
|
98
|
+
// console.log("Netskrafl UI already mounted with elemId", elemId);
|
|
97
99
|
return;
|
|
98
100
|
}
|
|
99
101
|
try {
|
|
@@ -107,12 +109,13 @@ const NetskraflImpl: React.FC<INetskraflProps> = ({ state, tokenExpired }) => {
|
|
|
107
109
|
}
|
|
108
110
|
});
|
|
109
111
|
} catch (err) {
|
|
110
|
-
|
|
112
|
+
console.error("Failed to mount Netskrafl UI for user", userEmail);
|
|
111
113
|
const container = document.getElementById("netskrafl-container");
|
|
112
114
|
if (container)
|
|
113
115
|
container.innerHTML = "";
|
|
114
116
|
}
|
|
115
117
|
return () => {
|
|
118
|
+
// console.log("Dismounting Netskrafl UI for user", userEmail);
|
|
116
119
|
// Move the Netskrafl UI to a hidden div under the body element
|
|
117
120
|
// when the component is unmounted
|
|
118
121
|
const container = document.getElementById("netskrafl-container");
|
package/src/css/skrafl-explo.css
CHANGED
|
@@ -1489,7 +1489,7 @@ div.modal-dialog#spinner-dialog {
|
|
|
1489
1489
|
}
|
|
1490
1490
|
div.animated-spinner {
|
|
1491
1491
|
position: absolute;
|
|
1492
|
-
left:
|
|
1492
|
+
left: 50%;
|
|
1493
1493
|
top: 271.5px;
|
|
1494
1494
|
}
|
|
1495
1495
|
svg circle.shadow {
|
|
@@ -1841,25 +1841,18 @@ div.submitmove#move-mobile span.glyphicon {
|
|
|
1841
1841
|
margin-top: 2px;
|
|
1842
1842
|
}
|
|
1843
1843
|
div.force-resign {
|
|
1844
|
-
|
|
1845
|
-
|
|
1844
|
+
display: flex;
|
|
1845
|
+
flex-direction: column;
|
|
1846
|
+
align-items: center;
|
|
1847
|
+
justify-content: center;
|
|
1848
|
+
font-weight: normal;
|
|
1849
|
+
font-size: 13px;
|
|
1846
1850
|
margin: 0;
|
|
1847
1851
|
padding: 6px;
|
|
1848
|
-
padding-top: 9px;
|
|
1849
|
-
border-radius: 5px;
|
|
1850
1852
|
cursor: pointer;
|
|
1851
|
-
width: 32px;
|
|
1852
1853
|
height: 26px;
|
|
1853
|
-
|
|
1854
|
-
display: block;
|
|
1855
|
-
float: right;
|
|
1856
|
-
padding-top: 3px;
|
|
1857
|
-
padding-bottom: 12px;
|
|
1854
|
+
width: 122px;
|
|
1858
1855
|
margin-right: 1px;
|
|
1859
|
-
width: 96px;
|
|
1860
|
-
text-align: center;
|
|
1861
|
-
font-weight: normal;
|
|
1862
|
-
font-size: 13px;
|
|
1863
1856
|
color: white;
|
|
1864
1857
|
background-color: var(--cancel-button);
|
|
1865
1858
|
}
|
|
@@ -2920,7 +2913,7 @@ div.at-top-left div.tilecount div.oc {
|
|
|
2920
2913
|
padding-bottom: 2px;
|
|
2921
2914
|
background-color: transparent;
|
|
2922
2915
|
}
|
|
2923
|
-
div.chat {
|
|
2916
|
+
div.chat-container {
|
|
2924
2917
|
position: absolute;
|
|
2925
2918
|
top: 0px;
|
|
2926
2919
|
left: 0px;
|
|
@@ -3048,7 +3041,7 @@ div.gamestats {
|
|
|
3048
3041
|
width: 724px;
|
|
3049
3042
|
height: 580px;
|
|
3050
3043
|
left: 150px;
|
|
3051
|
-
top:
|
|
3044
|
+
top: 24px;
|
|
3052
3045
|
padding: 12px;
|
|
3053
3046
|
border-radius: 5px;
|
|
3054
3047
|
box-shadow: 3px 3px 5px 2px var(--dark-shadow);
|
|
@@ -3057,21 +3050,20 @@ div.statscol {
|
|
|
3057
3050
|
display: block;
|
|
3058
3051
|
float: left;
|
|
3059
3052
|
width: 50%;
|
|
3060
|
-
padding-top: 24px;
|
|
3061
3053
|
}
|
|
3062
3054
|
div.statscol p {
|
|
3063
|
-
margin-top: 0
|
|
3064
|
-
margin-bottom:
|
|
3055
|
+
margin-top: 0;
|
|
3056
|
+
margin-bottom: 12px;
|
|
3065
3057
|
}
|
|
3066
3058
|
div.gamestats p span {
|
|
3067
3059
|
font-weight: 700;
|
|
3068
3060
|
}
|
|
3069
|
-
div
|
|
3061
|
+
div#gamestarted {
|
|
3070
3062
|
width: 100%;
|
|
3071
3063
|
text-align: center;
|
|
3072
3064
|
position: relative;
|
|
3073
|
-
top:
|
|
3074
|
-
margin-bottom:
|
|
3065
|
+
margin-top: 16px;
|
|
3066
|
+
margin-bottom: 16px;
|
|
3075
3067
|
}
|
|
3076
3068
|
#gamestarted p {
|
|
3077
3069
|
font-style: italic;
|
|
@@ -3657,6 +3649,7 @@ div.listitem {
|
|
|
3657
3649
|
top: 0;
|
|
3658
3650
|
}
|
|
3659
3651
|
.listitem a {
|
|
3652
|
+
display: flex;
|
|
3660
3653
|
cursor: pointer;
|
|
3661
3654
|
}
|
|
3662
3655
|
.listitem a:link,
|
|
@@ -4157,7 +4150,7 @@ h1.usr-info-icon span.glyphicon-coffee-cup {
|
|
|
4157
4150
|
div.usr-info-fav {
|
|
4158
4151
|
display: inline-block;
|
|
4159
4152
|
position: absolute;
|
|
4160
|
-
top:
|
|
4153
|
+
top: 16px;
|
|
4161
4154
|
right: 20px;
|
|
4162
4155
|
color: var(--triple-letter-color);
|
|
4163
4156
|
font-size: 26px;
|
|
@@ -4654,7 +4647,7 @@ div.toggler div.option.small {
|
|
|
4654
4647
|
div.toggler div.option.x-small {
|
|
4655
4648
|
width: 30px;
|
|
4656
4649
|
height: 20px;
|
|
4657
|
-
line-height:
|
|
4650
|
+
line-height: 22px;
|
|
4658
4651
|
font-size: 15px;
|
|
4659
4652
|
padding-top: 1px;
|
|
4660
4653
|
padding-bottom: 3px;
|
|
@@ -4938,7 +4931,7 @@ div.signup-header {
|
|
|
4938
4931
|
height: 288px;
|
|
4939
4932
|
/* 8 lines @ 36px each */
|
|
4940
4933
|
}
|
|
4941
|
-
div.chat,
|
|
4934
|
+
div.chat-container,
|
|
4942
4935
|
div.twoletter {
|
|
4943
4936
|
height: 474px;
|
|
4944
4937
|
}
|
|
@@ -5038,6 +5031,9 @@ div.signup-header {
|
|
|
5038
5031
|
div.rack-left div.recallbtn {
|
|
5039
5032
|
display: none;
|
|
5040
5033
|
}
|
|
5034
|
+
div.force-resign {
|
|
5035
|
+
display: none;
|
|
5036
|
+
}
|
|
5041
5037
|
div.scramblebtn {
|
|
5042
5038
|
left: 376px;
|
|
5043
5039
|
top: 158px;
|
|
@@ -5148,7 +5144,7 @@ div.signup-header {
|
|
|
5148
5144
|
}
|
|
5149
5145
|
div.games,
|
|
5150
5146
|
div.twoletter,
|
|
5151
|
-
div.chat {
|
|
5147
|
+
div.chat-container {
|
|
5152
5148
|
display: none;
|
|
5153
5149
|
}
|
|
5154
5150
|
div.right-area {
|
|
@@ -5343,12 +5339,12 @@ div.signup-header {
|
|
|
5343
5339
|
}
|
|
5344
5340
|
div.games,
|
|
5345
5341
|
div.twoletter,
|
|
5346
|
-
div.chat {
|
|
5342
|
+
div.chat-container {
|
|
5347
5343
|
display: block;
|
|
5348
5344
|
border-radius: 0;
|
|
5349
5345
|
}
|
|
5350
5346
|
div.twoletter,
|
|
5351
|
-
div.chat {
|
|
5347
|
+
div.chat-container {
|
|
5352
5348
|
height: 420px;
|
|
5353
5349
|
}
|
|
5354
5350
|
div.board-area {
|
|
@@ -5990,7 +5986,7 @@ div.signup-header {
|
|
|
5990
5986
|
height: 380px;
|
|
5991
5987
|
}
|
|
5992
5988
|
div.right-area.with-clock div.twoletter,
|
|
5993
|
-
div.right-area.with-clock div.chat {
|
|
5989
|
+
div.right-area.with-clock div.chat-container {
|
|
5994
5990
|
/* Timed game */
|
|
5995
5991
|
height: 380px;
|
|
5996
5992
|
}
|
package/src/mithril/board.ts
CHANGED
|
@@ -147,8 +147,7 @@ export const ReviewTileSquare: ComponentFunc<ITileSquareAttributes> = (initialVn
|
|
|
147
147
|
let cls = game.squareClass(coord) || "";
|
|
148
148
|
if (cls)
|
|
149
149
|
cls = "." + cls;
|
|
150
|
-
|
|
151
|
-
cls += ".opp";
|
|
150
|
+
cls += vnode.attrs.opponent ? ".opp" : ".local";
|
|
152
151
|
return m("td" + cls, { id: "sq_" + coord }, vnode.children);
|
|
153
152
|
}
|
|
154
153
|
};
|
|
@@ -287,44 +286,48 @@ export const Board: ComponentFunc<IBoardAttributes> = (initialVnode) => {
|
|
|
287
286
|
};
|
|
288
287
|
}
|
|
289
288
|
|
|
290
|
-
export const Rack: ComponentFunc<IBoardAttributes> = (
|
|
289
|
+
export const Rack: ComponentFunc<IBoardAttributes> = () => {
|
|
291
290
|
// A rack of 7 tiles
|
|
292
|
-
const { view, review } = initialVnode.attrs;
|
|
293
|
-
const model = view.model;
|
|
294
291
|
return {
|
|
295
|
-
view: () => {
|
|
296
|
-
const
|
|
297
|
-
if (!game) return undefined;
|
|
298
|
-
let r: VnodeChildren = [];
|
|
292
|
+
view: (vnode) => {
|
|
293
|
+
const { view, review } = vnode.attrs;
|
|
299
294
|
// If review==true, this is a review rack
|
|
300
295
|
// that is not a drop target and whose color reflects the
|
|
301
296
|
// currently shown move.
|
|
302
|
-
|
|
297
|
+
const model = view.model;
|
|
298
|
+
const game = model.game;
|
|
299
|
+
if (!game) return undefined;
|
|
300
|
+
let r: VnodeChildren = [];
|
|
303
301
|
const reviewMove = model.reviewMove ?? 0;
|
|
302
|
+
// Avoid flicker when paging through game review screen,
|
|
303
|
+
// as model.reviewMove becomes undefined or 0 while we
|
|
304
|
+
// are fetching the next move to display
|
|
305
|
+
const waiting = review && (reviewMove === 0);
|
|
306
|
+
// If opponent==true, we're showing the opponent's rack
|
|
304
307
|
const opponent = review && (reviewMove > 0) && (reviewMove % 2 === game.player);
|
|
305
308
|
for (let i = 1; i <= RACK_SIZE; i++) {
|
|
306
|
-
const coord =
|
|
307
|
-
if (game && (coord in game.tiles)) {
|
|
309
|
+
const coord = `R${i}`;
|
|
310
|
+
if (!waiting && game && (coord in game.tiles)) {
|
|
308
311
|
// We have a tile in this rack slot, but it is a drop target anyway
|
|
309
312
|
if (review) {
|
|
310
313
|
r.push(
|
|
311
|
-
m(ReviewTileSquare, { view, coord
|
|
312
|
-
m(Tile, { view, coord
|
|
314
|
+
m(ReviewTileSquare, { key: coord, view, coord, opponent },
|
|
315
|
+
m(Tile, { view, coord, opponent })
|
|
313
316
|
)
|
|
314
317
|
);
|
|
315
318
|
} else {
|
|
316
319
|
r.push(
|
|
317
|
-
m(DropTargetSquare, { view, coord
|
|
318
|
-
m(Tile, { view, coord
|
|
320
|
+
m(DropTargetSquare, { key: coord, view, coord },
|
|
321
|
+
m(Tile, { view, coord, opponent: false })
|
|
319
322
|
)
|
|
320
323
|
);
|
|
321
324
|
}
|
|
322
325
|
}
|
|
323
326
|
else if (review) {
|
|
324
|
-
r.push(m(ReviewTileSquare, { view, coord
|
|
327
|
+
r.push(m(ReviewTileSquare, { key: coord, view, coord, opponent: false }));
|
|
325
328
|
}
|
|
326
329
|
else {
|
|
327
|
-
r.push(m(DropTargetSquare, { view, coord
|
|
330
|
+
r.push(m(DropTargetSquare, { key: coord, view, coord }));
|
|
328
331
|
}
|
|
329
332
|
}
|
|
330
333
|
return m(".rack-row", [
|
package/src/mithril/chat.ts
CHANGED
|
@@ -181,7 +181,7 @@ export const Chat: ComponentFunc<IAttributes> = (initialVnode) => {
|
|
|
181
181
|
const numMessages = game?.messages ? game.messages.length : 0;
|
|
182
182
|
|
|
183
183
|
return {
|
|
184
|
-
view: () => m(".chat",
|
|
184
|
+
view: () => m(".chat-container",
|
|
185
185
|
{
|
|
186
186
|
style: "z-index: 6" // Appear on top of board on mobile
|
|
187
187
|
// key: uuid
|
package/src/mithril/page.ts
CHANGED
package/src/mithril/tile.ts
CHANGED
|
@@ -26,7 +26,7 @@ interface IAttributes {
|
|
|
26
26
|
|
|
27
27
|
export const Tile: ComponentFunc<IAttributes> = (initialVnode) => {
|
|
28
28
|
// Display a tile on the board or in the rack
|
|
29
|
-
const { view, coord
|
|
29
|
+
const { view, coord } = initialVnode.attrs;
|
|
30
30
|
const model = view.model;
|
|
31
31
|
|
|
32
32
|
const dragHandler = (ev: MithrilMouseEvent | MithrilTouchEvent) => {
|
|
@@ -62,7 +62,8 @@ export const Tile: ComponentFunc<IAttributes> = (initialVnode) => {
|
|
|
62
62
|
};
|
|
63
63
|
|
|
64
64
|
return {
|
|
65
|
-
view: () => {
|
|
65
|
+
view: (vnode) => {
|
|
66
|
+
const { opponent } = vnode.attrs;
|
|
66
67
|
const game = model.game;
|
|
67
68
|
if (!game) return undefined;
|
|
68
69
|
const isRackTile = coord[0] === 'R';
|
|
@@ -94,8 +95,7 @@ export const Tile: ComponentFunc<IAttributes> = (initialVnode) => {
|
|
|
94
95
|
ev.preventDefault();
|
|
95
96
|
};
|
|
96
97
|
}
|
|
97
|
-
}
|
|
98
|
-
if (t.freshtile) {
|
|
98
|
+
} else if (t.freshtile) {
|
|
99
99
|
// A fresh tile on the board that has
|
|
100
100
|
// just been played by the opponent
|
|
101
101
|
classes.push("freshtile");
|