@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.
- package/.eslintignore +8 -0
- package/.eslintrc.json +13 -0
- package/README.md +63 -0
- package/dist/cjs/index.css +6837 -0
- package/dist/cjs/index.js +3046 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/esm/index.css +6837 -0
- package/dist/esm/index.js +3046 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/types.d.ts +41 -0
- package/package.json +63 -0
- package/rollup.config.js +60 -0
- package/src/components/index.ts +2 -0
- package/src/components/netskrafl/Netskrafl.stories.tsx +66 -0
- package/src/components/netskrafl/Netskrafl.tsx +135 -0
- package/src/components/netskrafl/Netskrafl.types.ts +7 -0
- package/src/components/netskrafl/index.ts +2 -0
- package/src/css/fonts.css +4 -0
- package/src/css/glyphs.css +224 -0
- package/src/css/skrafl-explo.css +6616 -0
- package/src/fonts/glyphicons-regular.eot +0 -0
- package/src/fonts/glyphicons-regular.ttf +0 -0
- package/src/fonts/glyphicons-regular.woff +0 -0
- package/src/index.ts +2 -0
- package/src/messages/messages.json +1576 -0
- package/src/mithril/actions.ts +319 -0
- package/src/mithril/bag.ts +65 -0
- package/src/mithril/bestdisplay.ts +74 -0
- package/src/mithril/blankdialog.ts +94 -0
- package/src/mithril/board.ts +336 -0
- package/src/mithril/buttons.ts +303 -0
- package/src/mithril/challengedialog.ts +186 -0
- package/src/mithril/channel.ts +162 -0
- package/src/mithril/chat.ts +228 -0
- package/src/mithril/components.ts +496 -0
- package/src/mithril/dragdrop.ts +219 -0
- package/src/mithril/elopage.ts +180 -0
- package/src/mithril/friend.ts +227 -0
- package/src/mithril/game.ts +1378 -0
- package/src/mithril/gameview.ts +111 -0
- package/src/mithril/globalstate.ts +33 -0
- package/src/mithril/i18n.ts +186 -0
- package/src/mithril/localstorage.ts +133 -0
- package/src/mithril/login.ts +122 -0
- package/src/mithril/logo.ts +270 -0
- package/src/mithril/main.ts +737 -0
- package/src/mithril/mithril.ts +29 -0
- package/src/mithril/model.ts +817 -0
- package/src/mithril/movelistitem.ts +226 -0
- package/src/mithril/page.ts +852 -0
- package/src/mithril/playername.ts +91 -0
- package/src/mithril/promodialog.ts +82 -0
- package/src/mithril/recentlist.ts +148 -0
- package/src/mithril/request.ts +52 -0
- package/src/mithril/review.ts +634 -0
- package/src/mithril/rightcolumn.ts +398 -0
- package/src/mithril/searchbutton.ts +118 -0
- package/src/mithril/statsdisplay.ts +109 -0
- package/src/mithril/tabs.ts +169 -0
- package/src/mithril/tile.ts +145 -0
- package/src/mithril/twoletter.ts +76 -0
- package/src/mithril/types.ts +379 -0
- package/src/mithril/userinfodialog.ts +171 -0
- package/src/mithril/util.ts +304 -0
- package/src/mithril/wait.ts +246 -0
- package/src/mithril/wordcheck.ts +102 -0
- package/tsconfig.json +28 -0
- package/vite.config.ts +12 -0
|
@@ -0,0 +1,737 @@
|
|
|
1
|
+
/*
|
|
2
|
+
|
|
3
|
+
Main.ts
|
|
4
|
+
|
|
5
|
+
Main screen component
|
|
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 { ChallengeAction, ChallengeListItem, IView, UserListItem } from "./types";
|
|
17
|
+
import { VnodeChildren, ComponentFunc, m } from "./mithril";
|
|
18
|
+
import { gameUrl, glyph, glyphGrayed, nbsp } from "./util";
|
|
19
|
+
import { ExploLogoOnly } from "./logo";
|
|
20
|
+
import { mt, t, ts } from "./i18n";
|
|
21
|
+
import { ChallengeButton, Info, LeftLogo, TogglerReady, TogglerReadyTimed, UserId, UserInfoButton } from "./components";
|
|
22
|
+
import { logEvent } from "./channel";
|
|
23
|
+
import { RecentList } from "./recentlist";
|
|
24
|
+
import { EloPage } from "./elopage";
|
|
25
|
+
import { StatsDisplay } from "./statsdisplay";
|
|
26
|
+
import { SearchButton } from "./searchbutton";
|
|
27
|
+
import { makeTabs, updateSelection } from "./tabs";
|
|
28
|
+
import { BestDisplay } from "./bestdisplay";
|
|
29
|
+
|
|
30
|
+
interface IAttributes {
|
|
31
|
+
view: IView;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const Main: ComponentFunc<IAttributes> = () => {
|
|
35
|
+
// Main screen with tabs
|
|
36
|
+
|
|
37
|
+
function vwMainTabs(view: IView): VnodeChildren {
|
|
38
|
+
|
|
39
|
+
const model = view.model;
|
|
40
|
+
|
|
41
|
+
function vwMainTabHeader(): VnodeChildren {
|
|
42
|
+
const numGames = model.numGames;
|
|
43
|
+
const numChallenges = model.numChallenges;
|
|
44
|
+
return [
|
|
45
|
+
m(".header-logo",
|
|
46
|
+
m(m.route.Link,
|
|
47
|
+
{
|
|
48
|
+
href: "/page",
|
|
49
|
+
class: "backlink"
|
|
50
|
+
},
|
|
51
|
+
m(ExploLogoOnly)
|
|
52
|
+
)
|
|
53
|
+
),
|
|
54
|
+
m("ul", [
|
|
55
|
+
m("li",
|
|
56
|
+
m("a[href='#tabs-1']", [
|
|
57
|
+
glyph("th"), m("span.tab-legend", t("Viðureignir")),
|
|
58
|
+
m("span",
|
|
59
|
+
{
|
|
60
|
+
id: 'numgames',
|
|
61
|
+
style: numGames ? 'display: inline-block' : ''
|
|
62
|
+
},
|
|
63
|
+
numGames
|
|
64
|
+
)
|
|
65
|
+
])
|
|
66
|
+
),
|
|
67
|
+
m("li",
|
|
68
|
+
m("a[href='#tabs-2']", [
|
|
69
|
+
glyph("hand-right"), m("span.tab-legend", t("Áskoranir")),
|
|
70
|
+
// Blink if we have timed games where the opponent is ready
|
|
71
|
+
m("span" + (model.oppReady ? ".opp-ready" : ""),
|
|
72
|
+
{
|
|
73
|
+
id: "numchallenges",
|
|
74
|
+
style: numChallenges ? 'display: inline-block' : ''
|
|
75
|
+
},
|
|
76
|
+
numChallenges
|
|
77
|
+
)
|
|
78
|
+
])
|
|
79
|
+
),
|
|
80
|
+
m("li",
|
|
81
|
+
m("a[href='#tabs-3']",
|
|
82
|
+
[glyph("user"), m("span.tab-legend", t("Andstæðingar"))]
|
|
83
|
+
)
|
|
84
|
+
),
|
|
85
|
+
m("li.no-mobile-list",
|
|
86
|
+
m("a[href='#tabs-4']",
|
|
87
|
+
[glyph("bookmark"), m("span.tab-legend", t("Ferill"))]
|
|
88
|
+
)
|
|
89
|
+
)
|
|
90
|
+
])
|
|
91
|
+
];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function vwGamelist(): VnodeChildren {
|
|
95
|
+
|
|
96
|
+
function vwList(): VnodeChildren {
|
|
97
|
+
|
|
98
|
+
function viewGameList(): VnodeChildren {
|
|
99
|
+
|
|
100
|
+
if (!model.gameList)
|
|
101
|
+
return "";
|
|
102
|
+
return model.gameList.map((item, i: number) => {
|
|
103
|
+
|
|
104
|
+
// Show a list item about a game in progress (or recently finished)
|
|
105
|
+
|
|
106
|
+
function vwOpp(): VnodeChildren {
|
|
107
|
+
let arg = item.oppid === null ? [glyph("cog"), nbsp(), item.opp] : item.opp;
|
|
108
|
+
return m("span.list-opp", { title: item.fullname }, arg);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function vwTurn(): VnodeChildren {
|
|
112
|
+
let turnText = "";
|
|
113
|
+
let flagClass = "";
|
|
114
|
+
if (item.my_turn) {
|
|
115
|
+
turnText = ts("Þú átt leik");
|
|
116
|
+
}
|
|
117
|
+
else
|
|
118
|
+
if (item.zombie) {
|
|
119
|
+
turnText = ts("Viðureign lokið");
|
|
120
|
+
flagClass = ".zombie";
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
// {opponent}'s move
|
|
124
|
+
turnText = ts("opp_move", { opponent: item.opp });
|
|
125
|
+
flagClass = ".grayed";
|
|
126
|
+
}
|
|
127
|
+
return m("span.list-myturn",
|
|
128
|
+
m("span.glyphicon.glyphicon-flag" + flagClass, { title: turnText })
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function vwOverdue(): VnodeChildren {
|
|
133
|
+
if (item.overdue)
|
|
134
|
+
return glyph("hourglass",
|
|
135
|
+
{ title: item.my_turn ? "Er að renna út á tíma" : "Getur þvingað fram uppgjöf" }
|
|
136
|
+
);
|
|
137
|
+
return glyphGrayed("hourglass");
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function vwTileCount(): VnodeChildren {
|
|
141
|
+
const winLose = item.sc0 < item.sc1 ? ".losing" : "";
|
|
142
|
+
return m(".tilecount",
|
|
143
|
+
m(".tc" + winLose, { style: { width: item.tile_count.toString() + "%" } })
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return m(".listitem" + (i % 2 === 0 ? ".oddlist" : ".evenlist"),
|
|
148
|
+
[
|
|
149
|
+
m(m.route.Link,
|
|
150
|
+
{ href: gameUrl(item.url) },
|
|
151
|
+
[
|
|
152
|
+
vwTurn(),
|
|
153
|
+
m("span.list-overdue", vwOverdue()),
|
|
154
|
+
m("span.list-ts-short", item.ts),
|
|
155
|
+
vwOpp()
|
|
156
|
+
]
|
|
157
|
+
),
|
|
158
|
+
m(UserInfoButton, {
|
|
159
|
+
view,
|
|
160
|
+
item: { userid: item.oppid, nick: item.opp, fullname: item.fullname },
|
|
161
|
+
}),
|
|
162
|
+
m("span.list-s0", item.sc0),
|
|
163
|
+
m("span.list-colon", ":"),
|
|
164
|
+
m("span.list-s1", item.sc1),
|
|
165
|
+
m("span.list-tc", vwTileCount()),
|
|
166
|
+
m("span.list-manual",
|
|
167
|
+
item.manual
|
|
168
|
+
? glyph("lightbulb", { title: ts("Keppnishamur") })
|
|
169
|
+
: glyphGrayed("lightbulb")
|
|
170
|
+
)
|
|
171
|
+
]
|
|
172
|
+
);
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (model.gameList === null)
|
|
177
|
+
model.loadGameList();
|
|
178
|
+
return m("div", { id: 'gamelist' }, viewGameList());
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function vwHint(): VnodeChildren {
|
|
182
|
+
// Show some help if the user has no games in progress
|
|
183
|
+
if (model.loadingGameList || model.gameList === undefined ||
|
|
184
|
+
(model.gameList !== null && model.gameList.length > 0))
|
|
185
|
+
// Either we have games in progress or the game list is being loaded
|
|
186
|
+
return "";
|
|
187
|
+
return m(".hint", { style: { display: "block" } },
|
|
188
|
+
[
|
|
189
|
+
m("p",
|
|
190
|
+
[
|
|
191
|
+
"Ef þig vantar einhvern til að skrafla við, veldu flipann ",
|
|
192
|
+
m(m.route.Link,
|
|
193
|
+
{ href: "/main?tab=2" },
|
|
194
|
+
[glyph("user"), nbsp(), "Andstæðingar"]
|
|
195
|
+
),
|
|
196
|
+
" og skoraðu á tölvuþjarka - ",
|
|
197
|
+
glyph("cog"), nbsp(), m("b", "Amlóða"),
|
|
198
|
+
", ",
|
|
199
|
+
glyph("cog"), nbsp(), m("b", "Miðlung"),
|
|
200
|
+
" eða ",
|
|
201
|
+
glyph("cog"), nbsp(), m("b", "Fullsterkan"),
|
|
202
|
+
" - eða veldu þér annan leikmann úr stafrófs\u00ADlistunum " + // Soft hyphen
|
|
203
|
+
" sem þar er að finna til að skora á."
|
|
204
|
+
]
|
|
205
|
+
),
|
|
206
|
+
m("p",
|
|
207
|
+
[
|
|
208
|
+
"Þú stofnar áskorun með því að smella á bendi-teiknið ",
|
|
209
|
+
glyph("hand-right", { style: { "margin-left": "6px", "margin-right": "6px" } }),
|
|
210
|
+
" vinstra megin við nafn andstæðingsins."
|
|
211
|
+
]
|
|
212
|
+
),
|
|
213
|
+
m("p",
|
|
214
|
+
"Tölvuþjarkarnir eru ætíð reiðubúnir að skrafla og viðureign við þá " +
|
|
215
|
+
" hefst strax. Aðrir leikmenn þurfa að samþykkja áskorun áður en viðureign hefst."
|
|
216
|
+
),
|
|
217
|
+
m("p.no-mobile-block",
|
|
218
|
+
[
|
|
219
|
+
m(m.route.Link, { href: "/help" }, "Hjálp"),
|
|
220
|
+
" má fá með því að smella á bláa ",
|
|
221
|
+
glyph("info-sign"), nbsp(), "-", nbsp(),
|
|
222
|
+
"teiknið hér til vinstri."
|
|
223
|
+
]
|
|
224
|
+
),
|
|
225
|
+
m("p.no-mobile-block",
|
|
226
|
+
"Þú kemst alltaf aftur í þessa aðalsíðu með því að smella á " +
|
|
227
|
+
"örvarmerkið efst vinstra megin við skraflborðið."
|
|
228
|
+
)
|
|
229
|
+
]
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return [
|
|
234
|
+
m(".listitem.listheader",
|
|
235
|
+
[
|
|
236
|
+
m("span.list-myturn", glyphGrayed("flag", { title: ts('Átt þú leik?') })),
|
|
237
|
+
m("span.list-overdue",
|
|
238
|
+
glyphGrayed("hourglass", { title: ts('Langt frá síðasta leik?') })
|
|
239
|
+
),
|
|
240
|
+
mt("span.list-ts-short", "Síðasti leikur"),
|
|
241
|
+
mt("span.list-opp", "Andstæðingur"),
|
|
242
|
+
mt("span.list-info-hdr", "Ferill"),
|
|
243
|
+
mt("span.list-scorehdr", "Staða"),
|
|
244
|
+
mt("span.list-tc", "Framvinda"),
|
|
245
|
+
m("span.list-manual", glyphGrayed("lightbulb", { title: ts('Keppnishamur') }))
|
|
246
|
+
]
|
|
247
|
+
),
|
|
248
|
+
vwList(),
|
|
249
|
+
vwHint()
|
|
250
|
+
];
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function vwChallenges(showReceived: boolean): VnodeChildren {
|
|
254
|
+
|
|
255
|
+
function vwList(): VnodeChildren {
|
|
256
|
+
|
|
257
|
+
if (!model.state) return undefined;
|
|
258
|
+
const state = model.state;
|
|
259
|
+
|
|
260
|
+
function itemize(item: ChallengeListItem, i: number) {
|
|
261
|
+
|
|
262
|
+
// Generate a list item about a pending challenge (issued or received)
|
|
263
|
+
|
|
264
|
+
function challengeDescription(json: { duration?: number; }) {
|
|
265
|
+
/* Return a human-readable string describing a challenge
|
|
266
|
+
according to the enclosed preferences */
|
|
267
|
+
if (!json || json.duration === undefined || json.duration === 0)
|
|
268
|
+
/* Normal unbounded (untimed) game */
|
|
269
|
+
return t("Venjuleg ótímabundin viðureign");
|
|
270
|
+
return t("with_clock", { duration: json.duration.toString() });
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function markChallenge(ev: Event) {
|
|
274
|
+
// Clicked the icon at the beginning of the line,
|
|
275
|
+
// to decline a received challenge or retract an issued challenge
|
|
276
|
+
const action: ChallengeAction = item.received ? "decline" : "retract";
|
|
277
|
+
const param = { destuser: item.userid, action: action, key: item.key };
|
|
278
|
+
model.modifyChallenge(param);
|
|
279
|
+
ev.preventDefault();
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function clickChallenge(ev: Event) {
|
|
283
|
+
// Clicked the hotspot area to accept a received challenge
|
|
284
|
+
ev.preventDefault();
|
|
285
|
+
if (!model.moreGamesAllowed()) {
|
|
286
|
+
// User must be a friend to be able to accept more challenges
|
|
287
|
+
logEvent("hit_game_limit",
|
|
288
|
+
{
|
|
289
|
+
userid: state.userId,
|
|
290
|
+
locale: state.locale,
|
|
291
|
+
limit: model.maxFreeGames
|
|
292
|
+
}
|
|
293
|
+
);
|
|
294
|
+
// Promote a subscription to Netskrafl/Explo
|
|
295
|
+
view.showFriendPromo();
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
if (item.received) {
|
|
299
|
+
if (item.prefs && item.prefs.duration !== undefined && item.prefs.duration > 0)
|
|
300
|
+
// Timed game: display a modal wait dialog
|
|
301
|
+
view.pushDialog("wait", {
|
|
302
|
+
oppId: item.userid,
|
|
303
|
+
oppNick: item.opp,
|
|
304
|
+
oppName: item.fullname,
|
|
305
|
+
duration: item.prefs.duration,
|
|
306
|
+
challengeKey: item.key,
|
|
307
|
+
});
|
|
308
|
+
else
|
|
309
|
+
// Ask the server to create a new game and route to it
|
|
310
|
+
model.newGame(item.userid, false);
|
|
311
|
+
}
|
|
312
|
+
else {
|
|
313
|
+
// Clicking on a sent challenge, i.e. a timed game
|
|
314
|
+
// where the opponent is waiting and ready to start
|
|
315
|
+
view.showAcceptDialog(item.userid, item.opp, item.key);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const oppReady = !item.received && item.opp_ready &&
|
|
320
|
+
item.prefs && item.prefs.duration !== undefined &&
|
|
321
|
+
item.prefs.duration > 0;
|
|
322
|
+
const clickable = item.received || oppReady;
|
|
323
|
+
const descr = challengeDescription(item.prefs);
|
|
324
|
+
|
|
325
|
+
return m(".listitem" + (i % 2 === 0 ? ".oddlist" : ".evenlist"),
|
|
326
|
+
[
|
|
327
|
+
m("span.list-ch",
|
|
328
|
+
{ onclick: markChallenge },
|
|
329
|
+
item.received ?
|
|
330
|
+
glyph("thumbs-down", { title: ts("Hafna") })
|
|
331
|
+
:
|
|
332
|
+
glyph("hand-right", { title: ts("Afturkalla") })
|
|
333
|
+
),
|
|
334
|
+
m(clickable ? "a" : "span",
|
|
335
|
+
clickable ? {
|
|
336
|
+
href: "#",
|
|
337
|
+
onclick: clickChallenge,
|
|
338
|
+
class: oppReady ? "opp-ready" : ""
|
|
339
|
+
} : {},
|
|
340
|
+
[
|
|
341
|
+
m("span.list-ts", item.ts),
|
|
342
|
+
m("span.list-nick", { title: item.fullname }, item.opp),
|
|
343
|
+
m("span.list-chall",
|
|
344
|
+
[
|
|
345
|
+
item.prefs.fairplay ? m("span.fairplay-btn", { title: ts("Án hjálpartækja") }) : "",
|
|
346
|
+
item.prefs.manual ? m("span.manual-btn", { title: ts("Keppnishamur") }) : "",
|
|
347
|
+
descr
|
|
348
|
+
]
|
|
349
|
+
)
|
|
350
|
+
]
|
|
351
|
+
),
|
|
352
|
+
m(UserInfoButton,
|
|
353
|
+
{
|
|
354
|
+
view,
|
|
355
|
+
item: {
|
|
356
|
+
userid: item.userid,
|
|
357
|
+
nick: item.opp,
|
|
358
|
+
fullname: item.fullname,
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
),
|
|
362
|
+
]
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
let cList: ChallengeListItem[] = [];
|
|
367
|
+
if (model.challengeList)
|
|
368
|
+
cList = showReceived ?
|
|
369
|
+
model.challengeList.filter((item) => item.received) :
|
|
370
|
+
model.challengeList.filter((item) => !item.received);
|
|
371
|
+
|
|
372
|
+
return m("div",
|
|
373
|
+
{
|
|
374
|
+
id: showReceived ? 'chall-received' : 'chall-sent',
|
|
375
|
+
oninit: () => {
|
|
376
|
+
if (model.challengeList === null)
|
|
377
|
+
model.loadChallengeList();
|
|
378
|
+
}
|
|
379
|
+
},
|
|
380
|
+
cList.map(itemize)
|
|
381
|
+
);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
const n = vwList();
|
|
385
|
+
if (!n) return [];
|
|
386
|
+
|
|
387
|
+
if (showReceived)
|
|
388
|
+
// Challenges received
|
|
389
|
+
return [
|
|
390
|
+
m(".listitem.listheader",
|
|
391
|
+
[
|
|
392
|
+
m("span.list-icon", glyphGrayed("thumbs-down", { title: ts('Hafna') })),
|
|
393
|
+
mt("span.list-ts", "Hvenær"),
|
|
394
|
+
mt("span.list-nick", "Áskorandi"),
|
|
395
|
+
mt("span.list-chall", "Hvernig"),
|
|
396
|
+
mt("span.list-info-hdr", "Ferill"),
|
|
397
|
+
]
|
|
398
|
+
),
|
|
399
|
+
n
|
|
400
|
+
];
|
|
401
|
+
else
|
|
402
|
+
// Challenges sent
|
|
403
|
+
return [
|
|
404
|
+
m(".listitem.listheader",
|
|
405
|
+
[
|
|
406
|
+
m("span.list-icon", glyphGrayed("hand-right", { title: ts('Afturkalla') })),
|
|
407
|
+
mt("span.list-ts", "Hvenær"),
|
|
408
|
+
mt("span.list-nick", "Andstæðingur"),
|
|
409
|
+
mt("span.list-chall", "Hvernig"),
|
|
410
|
+
mt("span.list-info-hdr", "Ferill"),
|
|
411
|
+
]
|
|
412
|
+
),
|
|
413
|
+
n
|
|
414
|
+
];
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
function vwRecentList(): VnodeChildren {
|
|
418
|
+
|
|
419
|
+
function vwList(): VnodeChildren {
|
|
420
|
+
if (model.recentList === null)
|
|
421
|
+
model.loadRecentList();
|
|
422
|
+
return m(RecentList,
|
|
423
|
+
{
|
|
424
|
+
view,
|
|
425
|
+
id: "recentlist",
|
|
426
|
+
recentList: model.recentList || [],
|
|
427
|
+
}
|
|
428
|
+
);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
return [
|
|
432
|
+
m(".listitem.listheader",
|
|
433
|
+
[
|
|
434
|
+
m("span.list-win", glyphGrayed("bookmark", { title: ts('Sigur') })),
|
|
435
|
+
mt("span.list-ts-short", "Viðureign lauk"),
|
|
436
|
+
mt("span.list-nick", "Andstæðingur"),
|
|
437
|
+
mt("span.list-scorehdr", "Úrslit"),
|
|
438
|
+
m("span.list-elo-hdr",
|
|
439
|
+
[
|
|
440
|
+
m("span.glyphicon.glyphicon-user.elo-hdr-left", { title: ts('Mennskir andstæðingar') }),
|
|
441
|
+
t("Elo"),
|
|
442
|
+
m("span.glyphicon.glyphicon-cog.elo-hdr-right", { title: ts('Allir andstæðingar') })
|
|
443
|
+
]
|
|
444
|
+
),
|
|
445
|
+
mt("span.list-duration", "Lengd"),
|
|
446
|
+
m("span.list-manual", glyphGrayed("lightbulb", { title: ts('Keppnishamur') }))
|
|
447
|
+
]
|
|
448
|
+
),
|
|
449
|
+
vwList()
|
|
450
|
+
];
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
function vwUserButton(id: string, icon: string, text: string): VnodeChildren {
|
|
454
|
+
// Select the type of user list (robots, fav, alike, elo)
|
|
455
|
+
const sel = model.userListCriteria ? model.userListCriteria.query : "robots";
|
|
456
|
+
const spec = (id === "elo") ? "human" : "";
|
|
457
|
+
return m("span",
|
|
458
|
+
{
|
|
459
|
+
className: (id === sel ? "shown" : ""),
|
|
460
|
+
id: id,
|
|
461
|
+
onclick: (ev: Event) => {
|
|
462
|
+
model.loadUserList({ query: id, spec: spec }, true);
|
|
463
|
+
ev.preventDefault();
|
|
464
|
+
}
|
|
465
|
+
},
|
|
466
|
+
[glyph(icon, { style: { padding: 0 } }), nbsp(), text]
|
|
467
|
+
);
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
function vwUserList(): VnodeChildren {
|
|
471
|
+
|
|
472
|
+
function vwList(list: UserListItem[]) {
|
|
473
|
+
|
|
474
|
+
function itemize(item: UserListItem, i: number) {
|
|
475
|
+
|
|
476
|
+
// Generate a list item about a user
|
|
477
|
+
|
|
478
|
+
const isRobot = item.userid.indexOf("robot-") === 0;
|
|
479
|
+
let fullname: VnodeChildren = [];
|
|
480
|
+
|
|
481
|
+
// Online and accepting challenges
|
|
482
|
+
if (item.ready && !isRobot) {
|
|
483
|
+
fullname.push(m("span.ready-btn", { title: ts("Álínis og tekur við áskorunum") }));
|
|
484
|
+
fullname.push(nbsp());
|
|
485
|
+
}
|
|
486
|
+
// Willing to accept challenges for timed games
|
|
487
|
+
if (item.ready_timed) {
|
|
488
|
+
fullname.push(m("span.timed-btn", { title: ts("Til í viðureign með klukku") }));
|
|
489
|
+
fullname.push(nbsp());
|
|
490
|
+
}
|
|
491
|
+
// Fair play commitment
|
|
492
|
+
if (item.fairplay) {
|
|
493
|
+
fullname.push(m("span.fairplay-btn", { title: ts("Skraflar án hjálpartækja") }));
|
|
494
|
+
fullname.push(nbsp());
|
|
495
|
+
}
|
|
496
|
+
fullname.push(item.fullname);
|
|
497
|
+
|
|
498
|
+
function fav(): VnodeChildren {
|
|
499
|
+
if (isRobot)
|
|
500
|
+
return m("span.list-fav", { style: { cursor: "default" } }, glyph("star-empty"));
|
|
501
|
+
return m("span.list-fav",
|
|
502
|
+
{
|
|
503
|
+
title: ts("Uppáhald"),
|
|
504
|
+
onclick: (ev: Event) => {
|
|
505
|
+
item.fav = !item.fav;
|
|
506
|
+
model.markFavorite(item.userid, item.fav);
|
|
507
|
+
ev.preventDefault();
|
|
508
|
+
}
|
|
509
|
+
},
|
|
510
|
+
glyph(item.fav ? "star" : "star-empty")
|
|
511
|
+
);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
function userLink(): VnodeChildren {
|
|
515
|
+
if (isRobot)
|
|
516
|
+
return m("a",
|
|
517
|
+
{
|
|
518
|
+
href: "",
|
|
519
|
+
onclick: (ev: Event) => {
|
|
520
|
+
// Start a new game against the robot
|
|
521
|
+
model.newGame(item.userid, false);
|
|
522
|
+
ev.preventDefault();
|
|
523
|
+
}
|
|
524
|
+
},
|
|
525
|
+
[
|
|
526
|
+
m("span.list-nick", [glyph("cog"), nbsp(), item.nick]),
|
|
527
|
+
m("span.list-fullname-robot", fullname)
|
|
528
|
+
]
|
|
529
|
+
);
|
|
530
|
+
else
|
|
531
|
+
return m.fragment({}, [
|
|
532
|
+
m("span.list-nick", item.nick),
|
|
533
|
+
m("span.list-fullname", fullname),
|
|
534
|
+
m("span.list-human-elo", item.human_elo)
|
|
535
|
+
]);
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
return m(".listitem" + (i % 2 === 0 ? ".oddlist" : ".evenlist"),
|
|
539
|
+
[
|
|
540
|
+
m(ChallengeButton, { view, item }),
|
|
541
|
+
fav(),
|
|
542
|
+
userLink(),
|
|
543
|
+
m(UserInfoButton, { view, item }),
|
|
544
|
+
]
|
|
545
|
+
);
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
return m("div", { id: "userlist" }, list.map(itemize));
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
// The type of list to show; by default it's 'robots'
|
|
552
|
+
const query = model.userListCriteria?.query ?? "";
|
|
553
|
+
const spec = model.userListCriteria?.spec ?? "";
|
|
554
|
+
const listType = query || "robots";
|
|
555
|
+
if (listType === "elo")
|
|
556
|
+
// Show Elo list
|
|
557
|
+
return [ m(EloPage, { id: "elolist", view: view, key: "elolist" }) ];
|
|
558
|
+
// Show normal user list
|
|
559
|
+
let list: UserListItem[] = [];
|
|
560
|
+
if (model.userList === undefined) {
|
|
561
|
+
// We are loading a fresh user list
|
|
562
|
+
/* pass */
|
|
563
|
+
}
|
|
564
|
+
else
|
|
565
|
+
if (model.userList === null || query !== listType)
|
|
566
|
+
model.loadUserList({ query: listType, spec: "" }, true);
|
|
567
|
+
else
|
|
568
|
+
list = model.userList;
|
|
569
|
+
const nothingFound = list.length === 0 && listType === "search" && spec !== "";
|
|
570
|
+
const robotList = listType === "robots";
|
|
571
|
+
return [
|
|
572
|
+
m(".listitem.listheader",
|
|
573
|
+
[
|
|
574
|
+
m("span.list-ch", glyphGrayed("hand-right", { title: ts('Skora á') })),
|
|
575
|
+
m("span.list-fav", glyph("star-empty", { title: ts('Uppáhald') })),
|
|
576
|
+
mt("span.list-nick", "Einkenni"),
|
|
577
|
+
mt("span.list-fullname", "Nafn og merki"),
|
|
578
|
+
robotList ? "" : mt("span.list-human-elo[id='usr-list-elo']", "Elo"),
|
|
579
|
+
robotList ? "" : mt("span.list-info-hdr[id='usr-list-info']", "Ferill"),
|
|
580
|
+
]
|
|
581
|
+
),
|
|
582
|
+
vwList(list),
|
|
583
|
+
// Show indicator if search didn't find any users matching the criteria
|
|
584
|
+
nothingFound ?
|
|
585
|
+
m("div",
|
|
586
|
+
{ id: "user-no-match", style: { display: "block" } },
|
|
587
|
+
[
|
|
588
|
+
glyph("search"),
|
|
589
|
+
" ",
|
|
590
|
+
m("span", { id: "search-prefix" }, spec),
|
|
591
|
+
t(" finnst ekki")
|
|
592
|
+
]
|
|
593
|
+
)
|
|
594
|
+
: undefined
|
|
595
|
+
];
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
function vwStats(): VnodeChildren {
|
|
599
|
+
// View the user's own statistics summary
|
|
600
|
+
const ownStats = model.ownStats;
|
|
601
|
+
if (ownStats === null)
|
|
602
|
+
model.loadOwnStats();
|
|
603
|
+
return ownStats && m(StatsDisplay, { view, id: 'own-stats', ownStats });
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
function vwBest(): VnodeChildren {
|
|
607
|
+
// View the user's own best game and word scores
|
|
608
|
+
const ownStats = model.ownStats;
|
|
609
|
+
if (ownStats === null)
|
|
610
|
+
model.loadOwnStats();
|
|
611
|
+
return ownStats && m(BestDisplay, { id: 'own-best', ownStats, myself: true });
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
function tab1(): VnodeChildren {
|
|
615
|
+
// Ongoing games
|
|
616
|
+
return m("div", { id: 'tabs-1' },
|
|
617
|
+
[
|
|
618
|
+
mt("p.no-mobile-block",
|
|
619
|
+
[
|
|
620
|
+
mt("strong", "Viðureignir sem standa yfir"),
|
|
621
|
+
"click_on_game", // "Click on a game to view it and make a move if"
|
|
622
|
+
glyph("flag"),
|
|
623
|
+
" þú átt leik"
|
|
624
|
+
]
|
|
625
|
+
),
|
|
626
|
+
vwGamelist()
|
|
627
|
+
]
|
|
628
|
+
);
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
function tab2(): VnodeChildren {
|
|
632
|
+
// Challenges received and sent
|
|
633
|
+
return m("div", { id: 'tabs-2' },
|
|
634
|
+
[
|
|
635
|
+
mt("p.no-mobile-block",
|
|
636
|
+
[
|
|
637
|
+
mt("strong", "Skorað á þig"),
|
|
638
|
+
"click_on_challenge", // "Click on a challenge to accept it and start a game, or on"
|
|
639
|
+
glyph("thumbs-down", { style: { "margin-left": "6px", "margin-right": "6px" } }),
|
|
640
|
+
" til að hafna henni"
|
|
641
|
+
]
|
|
642
|
+
),
|
|
643
|
+
vwChallenges(true),
|
|
644
|
+
mt("p.no-mobile-block",
|
|
645
|
+
[
|
|
646
|
+
mt("strong", "Þú skorar á aðra"),
|
|
647
|
+
" - smelltu á ",
|
|
648
|
+
glyph("hand-right", { style: { "margin-left": "6px", "margin-right": "6px" } }),
|
|
649
|
+
" til að afturkalla áskorun"
|
|
650
|
+
]
|
|
651
|
+
),
|
|
652
|
+
vwChallenges(false)
|
|
653
|
+
]
|
|
654
|
+
);
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
function tab3(): VnodeChildren {
|
|
658
|
+
// Opponent lists
|
|
659
|
+
return m("div", { id: 'tabs-3' },
|
|
660
|
+
[
|
|
661
|
+
m("div", { id: 'initials' },
|
|
662
|
+
[
|
|
663
|
+
m(".user-cat[id='user-headings']",
|
|
664
|
+
[
|
|
665
|
+
vwUserButton("robots", "cog", ts("Þjarkar")),
|
|
666
|
+
" ",
|
|
667
|
+
vwUserButton("fav", "star", ts("Uppáhalds")),
|
|
668
|
+
" ",
|
|
669
|
+
vwUserButton("live", "flash", ts("Álínis")),
|
|
670
|
+
" ",
|
|
671
|
+
vwUserButton("alike", "resize-small", ts("Svipaðir")),
|
|
672
|
+
" ",
|
|
673
|
+
vwUserButton("elo", "crown", ts("Topp 100"))
|
|
674
|
+
]
|
|
675
|
+
),
|
|
676
|
+
m(SearchButton, { view })
|
|
677
|
+
]
|
|
678
|
+
),
|
|
679
|
+
vwUserList()
|
|
680
|
+
]
|
|
681
|
+
);
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
function tab4(): VnodeChildren {
|
|
685
|
+
// Recent games and statistics
|
|
686
|
+
return m("div", { id: 'tabs-4' },
|
|
687
|
+
[
|
|
688
|
+
vwStats(),
|
|
689
|
+
vwBest(),
|
|
690
|
+
mt("p.no-mobile-block",
|
|
691
|
+
[
|
|
692
|
+
mt("strong", "Nýlegar viðureignir þínar"),
|
|
693
|
+
"click_to_review" // "Click on a game to review it"
|
|
694
|
+
]
|
|
695
|
+
),
|
|
696
|
+
vwRecentList()
|
|
697
|
+
]
|
|
698
|
+
);
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
return m(".tabbed-page",
|
|
702
|
+
m("div", { id: 'main-tabs' },
|
|
703
|
+
[
|
|
704
|
+
vwMainTabHeader(),
|
|
705
|
+
m("div.tab-scroll-area", [
|
|
706
|
+
tab1(),
|
|
707
|
+
tab2(),
|
|
708
|
+
tab4(),
|
|
709
|
+
tab3(),
|
|
710
|
+
]),
|
|
711
|
+
]
|
|
712
|
+
)
|
|
713
|
+
);
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
return {
|
|
717
|
+
view: (vnode) => {
|
|
718
|
+
const view = vnode.attrs.view;
|
|
719
|
+
return m.fragment({}, [
|
|
720
|
+
m(LeftLogo), // No legend, scale up by 50%
|
|
721
|
+
m(UserId, { view }),
|
|
722
|
+
m(Info),
|
|
723
|
+
m(TogglerReady, { view }),
|
|
724
|
+
m(TogglerReadyTimed, { view }),
|
|
725
|
+
m("div",
|
|
726
|
+
{
|
|
727
|
+
oncreate: (vnode) => {
|
|
728
|
+
makeTabs(view, "main-tabs", undefined, false, vnode);
|
|
729
|
+
},
|
|
730
|
+
onupdate: updateSelection
|
|
731
|
+
},
|
|
732
|
+
vwMainTabs(view),
|
|
733
|
+
),
|
|
734
|
+
]);
|
|
735
|
+
}
|
|
736
|
+
};
|
|
737
|
+
};
|