@mideind/netskrafl-react 1.0.0-beta.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.
Files changed (68) hide show
  1. package/.eslintignore +8 -0
  2. package/.eslintrc.json +13 -0
  3. package/README.md +63 -0
  4. package/dist/cjs/index.css +6837 -0
  5. package/dist/cjs/index.js +3046 -0
  6. package/dist/cjs/index.js.map +1 -0
  7. package/dist/esm/index.css +6837 -0
  8. package/dist/esm/index.js +3046 -0
  9. package/dist/esm/index.js.map +1 -0
  10. package/dist/types.d.ts +41 -0
  11. package/package.json +63 -0
  12. package/rollup.config.js +60 -0
  13. package/src/components/index.ts +2 -0
  14. package/src/components/netskrafl/Netskrafl.stories.tsx +66 -0
  15. package/src/components/netskrafl/Netskrafl.tsx +135 -0
  16. package/src/components/netskrafl/Netskrafl.types.ts +7 -0
  17. package/src/components/netskrafl/index.ts +2 -0
  18. package/src/css/fonts.css +4 -0
  19. package/src/css/glyphs.css +224 -0
  20. package/src/css/skrafl-explo.css +6616 -0
  21. package/src/fonts/glyphicons-regular.eot +0 -0
  22. package/src/fonts/glyphicons-regular.ttf +0 -0
  23. package/src/fonts/glyphicons-regular.woff +0 -0
  24. package/src/index.ts +2 -0
  25. package/src/messages/messages.json +1576 -0
  26. package/src/mithril/actions.ts +319 -0
  27. package/src/mithril/bag.ts +65 -0
  28. package/src/mithril/bestdisplay.ts +74 -0
  29. package/src/mithril/blankdialog.ts +94 -0
  30. package/src/mithril/board.ts +336 -0
  31. package/src/mithril/buttons.ts +303 -0
  32. package/src/mithril/challengedialog.ts +186 -0
  33. package/src/mithril/channel.ts +162 -0
  34. package/src/mithril/chat.ts +228 -0
  35. package/src/mithril/components.ts +496 -0
  36. package/src/mithril/dragdrop.ts +219 -0
  37. package/src/mithril/elopage.ts +180 -0
  38. package/src/mithril/friend.ts +227 -0
  39. package/src/mithril/game.ts +1378 -0
  40. package/src/mithril/gameview.ts +111 -0
  41. package/src/mithril/globalstate.ts +33 -0
  42. package/src/mithril/i18n.ts +186 -0
  43. package/src/mithril/localstorage.ts +133 -0
  44. package/src/mithril/login.ts +122 -0
  45. package/src/mithril/logo.ts +270 -0
  46. package/src/mithril/main.ts +737 -0
  47. package/src/mithril/mithril.ts +29 -0
  48. package/src/mithril/model.ts +817 -0
  49. package/src/mithril/movelistitem.ts +226 -0
  50. package/src/mithril/page.ts +852 -0
  51. package/src/mithril/playername.ts +91 -0
  52. package/src/mithril/promodialog.ts +82 -0
  53. package/src/mithril/recentlist.ts +148 -0
  54. package/src/mithril/request.ts +52 -0
  55. package/src/mithril/review.ts +634 -0
  56. package/src/mithril/rightcolumn.ts +398 -0
  57. package/src/mithril/searchbutton.ts +118 -0
  58. package/src/mithril/statsdisplay.ts +109 -0
  59. package/src/mithril/tabs.ts +169 -0
  60. package/src/mithril/tile.ts +145 -0
  61. package/src/mithril/twoletter.ts +76 -0
  62. package/src/mithril/types.ts +379 -0
  63. package/src/mithril/userinfodialog.ts +171 -0
  64. package/src/mithril/util.ts +304 -0
  65. package/src/mithril/wait.ts +246 -0
  66. package/src/mithril/wordcheck.ts +102 -0
  67. package/tsconfig.json +28 -0
  68. package/vite.config.ts +12 -0
@@ -0,0 +1,226 @@
1
+ /*
2
+
3
+ MovelistItem.ts
4
+
5
+ An item in a move list
6
+
7
+ Copyright (C) 2024 Miðeind ehf.
8
+ Author: Vilhjalmur Thorsteinsson
9
+
10
+ The Creative Commons Attribution-NonCommercial 4.0
11
+ International Public License (CC-BY-NC 4.0) applies to this software.
12
+ For further information, see https://github.com/mideind/Netskrafl
13
+
14
+ */
15
+
16
+ import { IView, Move, MoveInfo } from "./types";
17
+ import { t, ts } from "./i18n";
18
+ import { nbsp, coord, toVector } from "./util";
19
+ import { VnodeChildren, ComponentFunc, m, VnodeAttrs } from "./mithril";
20
+ import { logEvent } from "./channel";
21
+
22
+ interface IAttributes {
23
+ view: IView;
24
+ move: Move;
25
+ info: MoveInfo;
26
+ }
27
+
28
+ export const MoveListItem: ComponentFunc<IAttributes> = (initialVnode) => {
29
+ // Displays a single move
30
+
31
+ const { view } = initialVnode.attrs;
32
+ const model = view.model;
33
+ const game = model.game!;
34
+ const state = model.state!;
35
+
36
+ function highlightMove(co: string, tiles: string, playerColor: 0 | 1, show: boolean) {
37
+ /* Highlight a move's tiles when hovering over it in the move list */
38
+ const vec = toVector(co);
39
+ let col = vec.col;
40
+ let row = vec.row;
41
+ for (const tile of tiles) {
42
+ if (tile == '?')
43
+ continue;
44
+ const sq = coord(row, col);
45
+ if (sq && game.tiles.hasOwnProperty(sq))
46
+ game.tiles[sq].highlight = show ? playerColor : undefined;
47
+ col += vec.dx;
48
+ row += vec.dy;
49
+ }
50
+ }
51
+
52
+ function gameOverMove(tiles: string): VnodeChildren {
53
+ // Add a 'game over' div at the bottom of the move list
54
+ // of a completed game. The div includes a button to
55
+ // open a review of the game, if the user is a subscriber.
56
+ return m(".move.gameover",
57
+ [
58
+ m("span.gameovermsg", tiles),
59
+ m("span.statsbutton",
60
+ {
61
+ onclick: (ev: Event) => {
62
+ ev.preventDefault();
63
+ if (state.hasPaid) {
64
+ // Show the game review
65
+ m.route.set("/review/" + game.uuid);
66
+ if (game !== null && game !== undefined) {
67
+ // Log an event for this action
68
+ logEvent("game_review",
69
+ {
70
+ locale: game.locale,
71
+ uuid: game.uuid
72
+ }
73
+ );
74
+ }
75
+ }
76
+ else {
77
+ // Show a friend promotion dialog
78
+ logEvent("click_review",
79
+ {
80
+ userid: state.userId, locale: state.locale
81
+ }
82
+ );
83
+ view.showFriendPromo();
84
+ }
85
+ }
86
+ },
87
+ t("Skoða yfirlit")
88
+ )
89
+ ]
90
+ );
91
+ }
92
+
93
+ function createItem(move: Move, info: MoveInfo): VnodeChildren {
94
+ // Add a single move to the move list
95
+ const { leftTotal, rightTotal, player } = info;
96
+ let { co, tiles } = info;
97
+ let score: string | number = info.score;
98
+ let wrdclass = "wordmove";
99
+ let rawCoord = co;
100
+ let tileMoveIncrement = 0; // +1 for tile moves, -1 for successful challenges
101
+ if (co === "") {
102
+ /* Not a regular tile move */
103
+ wrdclass = "othermove";
104
+ if (tiles == "PASS") {
105
+ /* Pass move */
106
+ tiles = " " + ts("Pass") + " ";
107
+ score = "";
108
+ }
109
+ else
110
+ if (tiles.indexOf("EXCH") === 0) {
111
+ /* Exchange move - we don't show the actual tiles exchanged, only their count */
112
+ let numtiles = tiles.slice(5).length;
113
+ const letters = ts(numtiles == 1 ? "letter" : "letters");
114
+ // Exchanged {numtiles} {letters}
115
+ tiles = " " + ts("exchanged", { numtiles: numtiles.toString(), letters: letters }) + " ";
116
+ score = "";
117
+ }
118
+ else
119
+ if (tiles == "RSGN")
120
+ /* Resigned from game */
121
+ tiles = " " + ts("Gaf viðureign") + " ";
122
+ else
123
+ if (tiles == "CHALL") {
124
+ /* Challenge issued */
125
+ tiles = " " + ts("Véfengdi lögn") + " ";
126
+ score = "";
127
+ }
128
+ else
129
+ if (tiles == "RESP") {
130
+ /* Challenge response */
131
+ if (score < 0) {
132
+ // Invalid move
133
+ tiles = " " + ts("Óleyfileg lögn") + " ";
134
+ tileMoveIncrement = -1; // Subtract one from the actual tile moves on the board
135
+ }
136
+ else
137
+ // Unsuccessful challenge
138
+ tiles = " " + ts("Röng véfenging") + " ";
139
+ }
140
+ else
141
+ if (tiles == "TIME") {
142
+ /* Overtime adjustment, 'Extra time' */
143
+ tiles = " " + ts("Umframtími") + " ";
144
+ }
145
+ else
146
+ if (tiles == "OVER") {
147
+ /* Game over */
148
+ tiles = ts("Viðureign lokið");
149
+ wrdclass = "gameover";
150
+ }
151
+ else {
152
+ /* The rack leave at the end of the game (which is always in lowercase
153
+ and thus cannot be confused with the above abbreviations) */
154
+ wrdclass = "wordmove";
155
+ }
156
+ }
157
+ else {
158
+ // Normal tile move
159
+ co = "(" + co + ")";
160
+ // Note: String.replace() will not work here since there may be two question marks in the string
161
+ tiles = tiles.split("?").join(""); /* TBD: Display wildcard characters differently? */
162
+ tileMoveIncrement = 1;
163
+ }
164
+ if (wrdclass == "gameover") {
165
+ // Game over message at bottom of move list
166
+ return gameOverMove(tiles);
167
+ }
168
+ // Normal game move
169
+ let title = (tileMoveIncrement > 0 && !game.manual) ? ts("Smelltu til að fletta upp") : "";
170
+ let playerColor: 0 | 1 = 0;
171
+ let lcp = game.player;
172
+ let cls: string;
173
+ if (player === lcp || (lcp === null && player === 0))
174
+ cls = "humangrad" + (player === 0 ? "_left" : "_right"); /* Local player or player 0 */
175
+ else {
176
+ cls = "autoplayergrad" + (player === 0 ? "_left" : "_right"); /* Remote player or player 1 */
177
+ playerColor = 1;
178
+ }
179
+ const attribs: VnodeAttrs = { };
180
+ if (state.uiFullscreen && tileMoveIncrement > 0) {
181
+ if (!game.manual) {
182
+ if (game.locale == "is_IS") {
183
+ // Tile move and not a manual game: allow word lookup for Icelandic
184
+ attribs.onclick = () => { window.open('https://malid.is/leit/' + tiles, 'malid'); };
185
+ attribs.title = title;
186
+ }
187
+ }
188
+ // Highlight the move on the board while hovering over it
189
+ attribs.onmouseout = () => {
190
+ move[2] = false; // highlighted
191
+ highlightMove(rawCoord, tiles, playerColor, false);
192
+ };
193
+ attribs.onmouseover = () => {
194
+ move[2] = true; // highlighted
195
+ highlightMove(rawCoord, tiles, playerColor, true);
196
+ };
197
+ }
198
+ if (player === 0) {
199
+ // Move by left side player
200
+ return m(".move.leftmove." + cls, attribs,
201
+ [
202
+ m("span.total" + (player == lcp ? ".human" : ".autoplayer"), leftTotal),
203
+ m("span.score" + (move[2] ? ".highlight" : ""), score),
204
+ m("span." + wrdclass, [m("i", tiles), nbsp(), co])
205
+ ]
206
+ );
207
+ }
208
+ else {
209
+ // Move by right side player
210
+ return m(".move.rightmove." + cls, attribs,
211
+ [
212
+ m("span." + wrdclass, [co, nbsp(), m("i", tiles)]),
213
+ m("span.score" + (move[2] ? ".highlight" : ""), score),
214
+ m("span.total" + (player == lcp ? ".human" : ".autoplayer"), rightTotal)
215
+ ]
216
+ );
217
+ }
218
+ }
219
+
220
+ return {
221
+ view: (vnode) => {
222
+ const { move, info } = vnode.attrs;
223
+ return createItem(move, info);
224
+ }
225
+ };
226
+ };