@mideind/netskrafl-react 1.0.1 → 1.0.2
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/css/netskrafl.css +272 -9
- package/dist/cjs/index.js +273 -68
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/css/netskrafl.css +272 -9
- package/dist/esm/index.js +273 -68
- package/dist/esm/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cjs/index.js
CHANGED
|
@@ -3,6 +3,98 @@
|
|
|
3
3
|
var jsxRuntime = require('react/jsx-runtime');
|
|
4
4
|
var React = require('react');
|
|
5
5
|
|
|
6
|
+
// Key for storing auth settings in sessionStorage
|
|
7
|
+
const AUTH_SETTINGS_KEY = "netskrafl_auth_settings";
|
|
8
|
+
// Save authentication settings to sessionStorage
|
|
9
|
+
const saveAuthSettings = (settings) => {
|
|
10
|
+
if (!settings) {
|
|
11
|
+
clearAuthSettings();
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
try {
|
|
15
|
+
// Filter to only include properties defined in PersistedAuthSettings interface
|
|
16
|
+
const filteredSettings = {
|
|
17
|
+
userEmail: settings.userEmail, // Required field
|
|
18
|
+
};
|
|
19
|
+
// Only add optional fields if they are defined
|
|
20
|
+
if (settings.userId !== undefined)
|
|
21
|
+
filteredSettings.userId = settings.userId;
|
|
22
|
+
if (settings.userNick !== undefined)
|
|
23
|
+
filteredSettings.userNick = settings.userNick;
|
|
24
|
+
if (settings.firebaseAPIKey !== undefined)
|
|
25
|
+
filteredSettings.firebaseAPIKey = settings.firebaseAPIKey;
|
|
26
|
+
if (settings.beginner !== undefined)
|
|
27
|
+
filteredSettings.beginner = settings.beginner;
|
|
28
|
+
if (settings.fairPlay !== undefined)
|
|
29
|
+
filteredSettings.fairPlay = settings.fairPlay;
|
|
30
|
+
if (settings.ready !== undefined)
|
|
31
|
+
filteredSettings.ready = settings.ready;
|
|
32
|
+
if (settings.readyTimed !== undefined)
|
|
33
|
+
filteredSettings.readyTimed = settings.readyTimed;
|
|
34
|
+
// Only save if we have actual settings to persist
|
|
35
|
+
if (Object.keys(filteredSettings).length > 1) {
|
|
36
|
+
sessionStorage.setItem(AUTH_SETTINGS_KEY, JSON.stringify(filteredSettings));
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
clearAuthSettings();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
// SessionStorage might be unavailable or full
|
|
44
|
+
console.warn("Could not save auth settings to sessionStorage:", error);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
// Retrieve authentication settings from sessionStorage
|
|
48
|
+
const loadAuthSettings = () => {
|
|
49
|
+
try {
|
|
50
|
+
const stored = sessionStorage.getItem(AUTH_SETTINGS_KEY);
|
|
51
|
+
if (stored) {
|
|
52
|
+
return JSON.parse(stored);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
// SessionStorage might be unavailable or data might be corrupted
|
|
57
|
+
console.warn("Could not load auth settings from sessionStorage:", error);
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
60
|
+
};
|
|
61
|
+
// Clear authentication settings from sessionStorage
|
|
62
|
+
const clearAuthSettings = () => {
|
|
63
|
+
try {
|
|
64
|
+
sessionStorage.removeItem(AUTH_SETTINGS_KEY);
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
console.warn("Could not clear auth settings from sessionStorage:", error);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
// Apply persisted settings to a GlobalState object
|
|
71
|
+
const applyPersistedSettings = (state) => {
|
|
72
|
+
var _a, _b, _c, _d;
|
|
73
|
+
const persisted = loadAuthSettings();
|
|
74
|
+
if (!persisted) {
|
|
75
|
+
return state;
|
|
76
|
+
}
|
|
77
|
+
// CRITICAL SECURITY CHECK: Only apply persisted settings if they belong to the current user
|
|
78
|
+
// This prevents data leakage between different users in the same browser session
|
|
79
|
+
if (persisted.userEmail !== state.userEmail) {
|
|
80
|
+
// Different user detected - clear the old user's settings
|
|
81
|
+
clearAuthSettings();
|
|
82
|
+
return state;
|
|
83
|
+
}
|
|
84
|
+
// Apply persisted settings, but don't override values explicitly passed in props
|
|
85
|
+
return {
|
|
86
|
+
...state,
|
|
87
|
+
// Only apply persisted values if current values are defaults
|
|
88
|
+
userId: state.userId || persisted.userId || state.userId,
|
|
89
|
+
userNick: state.userNick || persisted.userNick || state.userNick,
|
|
90
|
+
firebaseAPIKey: state.firebaseAPIKey || persisted.firebaseAPIKey || state.firebaseAPIKey,
|
|
91
|
+
beginner: (_a = persisted.beginner) !== null && _a !== void 0 ? _a : state.beginner,
|
|
92
|
+
fairPlay: (_b = persisted.fairPlay) !== null && _b !== void 0 ? _b : state.fairPlay,
|
|
93
|
+
ready: (_c = persisted.ready) !== null && _c !== void 0 ? _c : state.ready,
|
|
94
|
+
readyTimed: (_d = persisted.readyTimed) !== null && _d !== void 0 ? _d : state.readyTimed,
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
|
|
6
98
|
const DEFAULT_STATE = {
|
|
7
99
|
projectId: "netskrafl",
|
|
8
100
|
firebaseAPIKey: "",
|
|
@@ -23,12 +115,12 @@ const DEFAULT_STATE = {
|
|
|
23
115
|
loginUrl: "",
|
|
24
116
|
loginMethod: "",
|
|
25
117
|
newUser: false,
|
|
26
|
-
beginner:
|
|
27
|
-
fairPlay:
|
|
118
|
+
beginner: true,
|
|
119
|
+
fairPlay: false,
|
|
28
120
|
plan: "", // Not a friend
|
|
29
121
|
hasPaid: false,
|
|
30
|
-
ready:
|
|
31
|
-
readyTimed:
|
|
122
|
+
ready: true,
|
|
123
|
+
readyTimed: true,
|
|
32
124
|
uiFullscreen: true,
|
|
33
125
|
uiLandscape: false,
|
|
34
126
|
runningLocal: false,
|
|
@@ -52,7 +144,9 @@ const makeGlobalState = (overrides) => {
|
|
|
52
144
|
...DEFAULT_STATE,
|
|
53
145
|
...overrides,
|
|
54
146
|
};
|
|
55
|
-
|
|
147
|
+
const stateWithUrls = { ...state, ...makeServerUrls(state.serverUrl, state.movesUrl) };
|
|
148
|
+
// Apply any persisted authentication settings from sessionStorage
|
|
149
|
+
return applyPersistedSettings(stateWithUrls);
|
|
56
150
|
};
|
|
57
151
|
|
|
58
152
|
function getDefaultExportFromCjs (x) {
|
|
@@ -27405,6 +27499,7 @@ class AuthenticationError extends Error {
|
|
|
27405
27499
|
}
|
|
27406
27500
|
// Internal function to ensure authentication
|
|
27407
27501
|
const ensureAuthenticated = async (state) => {
|
|
27502
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
27408
27503
|
// If login is already in progress, wait for it to complete
|
|
27409
27504
|
if (authPromise) {
|
|
27410
27505
|
await authPromise;
|
|
@@ -27417,11 +27512,37 @@ const ensureAuthenticated = async (state) => {
|
|
|
27417
27512
|
if (result.status === "expired") {
|
|
27418
27513
|
// Token has expired, notify the React component if callback is set
|
|
27419
27514
|
state.tokenExpired && state.tokenExpired();
|
|
27515
|
+
// Clear any persisted settings since they're no longer valid
|
|
27516
|
+
clearAuthSettings();
|
|
27420
27517
|
throw new Error("Token expired");
|
|
27421
27518
|
}
|
|
27422
27519
|
else if (result.status !== "success") {
|
|
27520
|
+
// Clear any persisted settings on auth failure
|
|
27521
|
+
clearAuthSettings();
|
|
27423
27522
|
throw new Error(`Authentication failed: ${result.message || result.status}`);
|
|
27424
27523
|
}
|
|
27524
|
+
// Update the user's ID to the internal one used by the backend and Firebase
|
|
27525
|
+
state.userId = result.user_id || state.userId;
|
|
27526
|
+
// Update the user's nickname
|
|
27527
|
+
state.userNick = result.nickname || state.userNick;
|
|
27528
|
+
// Use the server's Firebase API key, if provided
|
|
27529
|
+
state.firebaseAPIKey = result.firebase_api_key || state.firebaseAPIKey;
|
|
27530
|
+
// Load state flags and preferences
|
|
27531
|
+
state.beginner = (_b = (_a = result.prefs) === null || _a === void 0 ? void 0 : _a.beginner) !== null && _b !== void 0 ? _b : true;
|
|
27532
|
+
state.fairPlay = (_d = (_c = result.prefs) === null || _c === void 0 ? void 0 : _c.fairplay) !== null && _d !== void 0 ? _d : false;
|
|
27533
|
+
state.ready = (_f = (_e = result.prefs) === null || _e === void 0 ? void 0 : _e.ready) !== null && _f !== void 0 ? _f : true;
|
|
27534
|
+
state.readyTimed = (_h = (_g = result.prefs) === null || _g === void 0 ? void 0 : _g.ready_timed) !== null && _h !== void 0 ? _h : true;
|
|
27535
|
+
// Save the authentication settings to sessionStorage for persistence
|
|
27536
|
+
saveAuthSettings({
|
|
27537
|
+
userEmail: state.userEmail, // CRITICAL: Include email to validate ownership
|
|
27538
|
+
userId: state.userId,
|
|
27539
|
+
userNick: state.userNick,
|
|
27540
|
+
firebaseAPIKey: state.firebaseAPIKey,
|
|
27541
|
+
beginner: state.beginner,
|
|
27542
|
+
fairPlay: state.fairPlay,
|
|
27543
|
+
ready: state.ready,
|
|
27544
|
+
readyTimed: state.readyTimed,
|
|
27545
|
+
});
|
|
27425
27546
|
// Success: Log in to Firebase with the token passed from the server
|
|
27426
27547
|
await loginFirebase(state, result.firebase_token);
|
|
27427
27548
|
}
|
|
@@ -35126,6 +35247,7 @@ class Model {
|
|
|
35126
35247
|
state.userNick = user.nickname;
|
|
35127
35248
|
state.beginner = user.beginner;
|
|
35128
35249
|
state.fairPlay = user.fairplay;
|
|
35250
|
+
saveAuthSettings(state);
|
|
35129
35251
|
}
|
|
35130
35252
|
// Note that state.plan is updated via a Firebase notification
|
|
35131
35253
|
// Give the game instance a chance to update its state
|
|
@@ -35160,41 +35282,22 @@ class Model {
|
|
|
35160
35282
|
return false;
|
|
35161
35283
|
}
|
|
35162
35284
|
handleUserMessage(json, firstAttach) {
|
|
35163
|
-
var _a;
|
|
35164
35285
|
// Handle an incoming Firebase user message, i.e. a message
|
|
35165
35286
|
// on the /user/[userid] path
|
|
35166
|
-
if (firstAttach || !this.state)
|
|
35287
|
+
if (firstAttach || !this.state || !json)
|
|
35167
35288
|
return;
|
|
35168
35289
|
let redraw = false;
|
|
35169
|
-
if (json.
|
|
35170
|
-
// Potential change of user friendship status
|
|
35171
|
-
const newFriend = json.friend ? true : false;
|
|
35172
|
-
if (this.user && this.user.friend != newFriend) {
|
|
35173
|
-
this.user.friend = newFriend;
|
|
35174
|
-
redraw = true;
|
|
35175
|
-
}
|
|
35176
|
-
}
|
|
35177
|
-
if (json.plan !== undefined) {
|
|
35290
|
+
if (typeof json.plan === "string") {
|
|
35178
35291
|
// Potential change of user subscription plan
|
|
35179
|
-
if (this.state.plan
|
|
35292
|
+
if (this.state.plan !== json.plan) {
|
|
35180
35293
|
this.state.plan = json.plan;
|
|
35181
35294
|
redraw = true;
|
|
35182
35295
|
}
|
|
35183
|
-
if (this.user && !this.user.friend && this.state.plan == "friend") {
|
|
35184
|
-
// plan == "friend" implies that user.friend should be true
|
|
35185
|
-
this.user.friend = true;
|
|
35186
|
-
redraw = true;
|
|
35187
|
-
}
|
|
35188
|
-
if (this.state.plan == "" && ((_a = this.user) === null || _a === void 0 ? void 0 : _a.friend)) {
|
|
35189
|
-
// Conversely, an empty plan string means that the user is not a friend
|
|
35190
|
-
this.user.friend = false;
|
|
35191
|
-
redraw = true;
|
|
35192
|
-
}
|
|
35193
35296
|
}
|
|
35194
35297
|
if (json.hasPaid !== undefined) {
|
|
35195
35298
|
// Potential change of payment status
|
|
35196
|
-
const newHasPaid = (this.state.plan
|
|
35197
|
-
if (this.state.hasPaid
|
|
35299
|
+
const newHasPaid = (this.state.plan !== "" && json.hasPaid) ? true : false;
|
|
35300
|
+
if (this.state.hasPaid !== newHasPaid) {
|
|
35198
35301
|
this.state.hasPaid = newHasPaid;
|
|
35199
35302
|
redraw = true;
|
|
35200
35303
|
}
|
|
@@ -35698,6 +35801,8 @@ class Actions {
|
|
|
35698
35801
|
url: "/setuserpref",
|
|
35699
35802
|
body: pref
|
|
35700
35803
|
}); // No result required or expected
|
|
35804
|
+
// Update the persisted settings in sessionStorage
|
|
35805
|
+
saveAuthSettings(this.model.state);
|
|
35701
35806
|
}
|
|
35702
35807
|
catch (e) {
|
|
35703
35808
|
// A future TODO might be to signal an error in the UI
|
|
@@ -35994,6 +36099,10 @@ const RiddleScore = {
|
|
|
35994
36099
|
else {
|
|
35995
36100
|
classes.push(".hot");
|
|
35996
36101
|
}
|
|
36102
|
+
// Add celebration class if the player achieved the best possible score
|
|
36103
|
+
if (score >= riddle.bestPossibleScore) {
|
|
36104
|
+
classes.push(".celebrate");
|
|
36105
|
+
}
|
|
35997
36106
|
}
|
|
35998
36107
|
return m("div" + classes.join(""), m("span.gata-dagsins-legend", displayText));
|
|
35999
36108
|
}
|
|
@@ -36335,6 +36444,84 @@ const GataDagsinsRightSide = {
|
|
|
36335
36444
|
}
|
|
36336
36445
|
};
|
|
36337
36446
|
|
|
36447
|
+
/*
|
|
36448
|
+
|
|
36449
|
+
gatadagsins-help.ts
|
|
36450
|
+
|
|
36451
|
+
Help dialog for Gáta Dagsins
|
|
36452
|
+
|
|
36453
|
+
Copyright (C) 2025 Miðeind ehf.
|
|
36454
|
+
Author: Vilhjálmur Þorsteinsson
|
|
36455
|
+
|
|
36456
|
+
The Creative Commons Attribution-NonCommercial 4.0
|
|
36457
|
+
International Public License (CC-BY-NC 4.0) applies to this software.
|
|
36458
|
+
For further information, see https://github.com/mideind/Netskrafl
|
|
36459
|
+
|
|
36460
|
+
*/
|
|
36461
|
+
const GataDagsinsHelp = {
|
|
36462
|
+
view: (vnode) => {
|
|
36463
|
+
const closeHelp = vnode.attrs.onClose;
|
|
36464
|
+
return m(".modal-dialog.gatadagsins-help", m(".modal-content", [
|
|
36465
|
+
// Header with close button
|
|
36466
|
+
m(".modal-header", [
|
|
36467
|
+
m("h2", "Um Gátu dagsins"),
|
|
36468
|
+
m("button.close", {
|
|
36469
|
+
onclick: closeHelp,
|
|
36470
|
+
"aria-label": "Loka"
|
|
36471
|
+
}, m("span", { "aria-hidden": "true" }, "×"))
|
|
36472
|
+
]),
|
|
36473
|
+
// Body with help content
|
|
36474
|
+
m(".modal-body", [
|
|
36475
|
+
m("p", "Gáta dagsins er dagleg krossgátuþraut, svipuð skrafli, þar sem þú reynir að finna " +
|
|
36476
|
+
"stigahæsta orðið sem hægt er að mynda með gefnum stöfum."),
|
|
36477
|
+
m("h3", "Hvernig á að spila"),
|
|
36478
|
+
m("ul", [
|
|
36479
|
+
m("li", "Þú færð borð með allmörgum stöfum sem þegar hafa verið lagðir."),
|
|
36480
|
+
m("li", "Neðst á skjánum eru stafaflísar sem þú getur notað til að mynda orð."),
|
|
36481
|
+
m("li", "Dragðu flísar á borðið til að mynda orð, annaðhvort lárétt eða lóðrétt."),
|
|
36482
|
+
m("li", "Orðin verða að tengjast við stafi sem fyrir eru á borðinu."),
|
|
36483
|
+
m("li", "Þú sérð jafnóðum hvort lögnin á borðinu er gild og hversu mörg stig hún gefur."),
|
|
36484
|
+
m("li", "Þú getur prófað eins mörg orð og þú vilt - besta skorið þitt er vistað."),
|
|
36485
|
+
]),
|
|
36486
|
+
m("h3", "Stigagjöf"),
|
|
36487
|
+
m("p", "Þú færð stig fyrir hvern staf í orðinu, auk bónusstiga fyrir lengri orð:"),
|
|
36488
|
+
m("ul", [
|
|
36489
|
+
m("li", "Hver stafur gefur 1-10 stig eftir gildi hans"),
|
|
36490
|
+
m("li", "Orð sem nota allar 7 stafaflísarnar gefa 50 stiga bónus"),
|
|
36491
|
+
m("li", "Sumir reitir á borðinu tvöfalda eða þrefalda stafagildið"),
|
|
36492
|
+
m("li", "Sumir reitir tvöfalda eða þrefalda heildarorðagildið"),
|
|
36493
|
+
]),
|
|
36494
|
+
m("h3", "Hitamælir"),
|
|
36495
|
+
m("p", "Hitamælirinn hægra megin (eða efst á farsímum) sýnir:"),
|
|
36496
|
+
m("ul", [
|
|
36497
|
+
m("li", m("strong", "Besta mögulega skor:"), " Hæstu stig sem hægt er að ná á þessu borði."),
|
|
36498
|
+
m("li", m("strong", "Besta skor dagsins:"), " Hæstu stig sem einhver leikmaður hefur náð í dag."),
|
|
36499
|
+
m("li", m("strong", "Þín bestu orð:"), " Orðin sem þú hefur lagt og stigin fyrir þau."),
|
|
36500
|
+
m("li", "Þú getur smellt á orð á hitamælinum til að fá þá lögn aftur á borðið."),
|
|
36501
|
+
]),
|
|
36502
|
+
m("h3", "Ábendingar"),
|
|
36503
|
+
m("ul", [
|
|
36504
|
+
m("li", "Reyndu að nota dýra stafi (eins og X, Ý, Þ) á tvöföldunar- eða þreföldunarreitum."),
|
|
36505
|
+
m("li", "Lengri orð gefa mun fleiri stig vegna bónussins."),
|
|
36506
|
+
m("li", "Þú getur dregið allar flísar til baka með bláa endurkalls-hnappnum."),
|
|
36507
|
+
m("li", "Ný gáta birtist á hverjum nýjum degi - klukkan 00:00!"),
|
|
36508
|
+
]),
|
|
36509
|
+
m("h3", "Um leikinn"),
|
|
36510
|
+
m("p", [
|
|
36511
|
+
"Gáta dagsins er systkini ",
|
|
36512
|
+
m("a", { href: "https://netskrafl.is", target: "_blank" }, "Netskrafls"),
|
|
36513
|
+
", hins sívinsæla íslenska krossgátuleiks á netinu. ",
|
|
36514
|
+
"Leikurinn er þróaður af Miðeind ehf."
|
|
36515
|
+
]),
|
|
36516
|
+
]),
|
|
36517
|
+
// Footer with close button
|
|
36518
|
+
m(".modal-footer", m("button.btn.btn-primary", {
|
|
36519
|
+
onclick: closeHelp
|
|
36520
|
+
}, "Loka"))
|
|
36521
|
+
]));
|
|
36522
|
+
}
|
|
36523
|
+
};
|
|
36524
|
+
|
|
36338
36525
|
/*
|
|
36339
36526
|
|
|
36340
36527
|
GataDagsins.ts
|
|
@@ -36403,47 +36590,65 @@ const currentMoveState = (riddle) => {
|
|
|
36403
36590
|
}
|
|
36404
36591
|
return { selectedMoves, bestMove };
|
|
36405
36592
|
};
|
|
36406
|
-
const GataDagsins$1 = {
|
|
36593
|
+
const GataDagsins$1 = () => {
|
|
36407
36594
|
// A view of the Gáta Dagsins page
|
|
36408
|
-
|
|
36409
|
-
|
|
36410
|
-
|
|
36411
|
-
|
|
36412
|
-
const {
|
|
36413
|
-
|
|
36414
|
-
|
|
36595
|
+
let showHelp = false;
|
|
36596
|
+
return {
|
|
36597
|
+
oninit: (vnode) => {
|
|
36598
|
+
const { model, actions } = vnode.attrs.view;
|
|
36599
|
+
const { riddle } = model;
|
|
36600
|
+
if (!riddle) {
|
|
36601
|
+
const { date, locale } = vnode.attrs;
|
|
36602
|
+
// Initialize a fresh riddle object if it doesn't exist
|
|
36603
|
+
actions.fetchRiddle(date, locale);
|
|
36604
|
+
}
|
|
36605
|
+
// Initialize help dialog state
|
|
36606
|
+
showHelp = false;
|
|
36607
|
+
},
|
|
36608
|
+
view: (vnode) => {
|
|
36609
|
+
var _a;
|
|
36610
|
+
const { view } = vnode.attrs;
|
|
36611
|
+
const { model } = view;
|
|
36612
|
+
const { riddle } = model;
|
|
36613
|
+
const { selectedMoves, bestMove } = (riddle
|
|
36614
|
+
? currentMoveState(riddle)
|
|
36615
|
+
: { selectedMoves: [], bestMove: undefined });
|
|
36616
|
+
const toggleHelp = () => {
|
|
36617
|
+
showHelp = !showHelp;
|
|
36618
|
+
m.redraw();
|
|
36619
|
+
};
|
|
36620
|
+
return m("div.drop-target", {
|
|
36621
|
+
id: "gatadagsins-background",
|
|
36622
|
+
}, [
|
|
36623
|
+
// The main content area
|
|
36624
|
+
riddle ? m(".gatadagsins-container", [
|
|
36625
|
+
// Main display area with flex layout
|
|
36626
|
+
m(".gatadagsins-main", [
|
|
36627
|
+
// Board and rack component (left side)
|
|
36628
|
+
m(GataDagsinsBoardAndRack, { view }),
|
|
36629
|
+
// Right-side component with scores and comparisons
|
|
36630
|
+
m(GataDagsinsRightSide, { view, selectedMoves, bestMove }),
|
|
36631
|
+
// Blank dialog
|
|
36632
|
+
riddle.askingForBlank
|
|
36633
|
+
? m(BlankDialog, { game: riddle })
|
|
36634
|
+
: "",
|
|
36635
|
+
])
|
|
36636
|
+
]) : "",
|
|
36637
|
+
// The left margin elements: back button and info/help button
|
|
36638
|
+
// These elements appear after the main container for proper z-order
|
|
36639
|
+
// m(LeftLogo), // Currently no need for the logo for Gáta Dagsins
|
|
36640
|
+
// Show the Beginner component if the user is a beginner
|
|
36641
|
+
((_a = model.state) === null || _a === void 0 ? void 0 : _a.beginner) ? m(Beginner, { view }) : "",
|
|
36642
|
+
// Custom Info button for GataDagsins that shows help dialog
|
|
36643
|
+
m(".info", { title: ts("Upplýsingar og hjálp") }, m("a.iconlink", { href: "#", onclick: (e) => { e.preventDefault(); toggleHelp(); } }, glyph("info-sign"))),
|
|
36644
|
+
// Help dialog and backdrop
|
|
36645
|
+
showHelp ? [
|
|
36646
|
+
m(".modal-backdrop", { onclick: (e) => { e.preventDefault(); } }),
|
|
36647
|
+
m(GataDagsinsHelp, { onClose: toggleHelp })
|
|
36648
|
+
] : "",
|
|
36649
|
+
]);
|
|
36415
36650
|
}
|
|
36416
|
-
}
|
|
36417
|
-
view: (vnode) => {
|
|
36418
|
-
const { view } = vnode.attrs;
|
|
36419
|
-
const { model } = view;
|
|
36420
|
-
const { riddle } = model;
|
|
36421
|
-
const { selectedMoves, bestMove } = (riddle
|
|
36422
|
-
? currentMoveState(riddle)
|
|
36423
|
-
: { selectedMoves: [], bestMove: undefined });
|
|
36424
|
-
return m("div.drop-target", {
|
|
36425
|
-
id: "gatadagsins-background",
|
|
36426
|
-
}, [
|
|
36427
|
-
// The main content area
|
|
36428
|
-
riddle ? m(".gatadagsins-container", [
|
|
36429
|
-
// Main display area with flex layout
|
|
36430
|
-
m(".gatadagsins-main", [
|
|
36431
|
-
// Board and rack component (left side)
|
|
36432
|
-
m(GataDagsinsBoardAndRack, { view }),
|
|
36433
|
-
// Right-side component with scores and comparisons
|
|
36434
|
-
m(GataDagsinsRightSide, { view, selectedMoves, bestMove }),
|
|
36435
|
-
// Blank dialog
|
|
36436
|
-
riddle.askingForBlank
|
|
36437
|
-
? m(BlankDialog, { game: riddle })
|
|
36438
|
-
: "",
|
|
36439
|
-
])
|
|
36440
|
-
]) : "",
|
|
36441
|
-
// The left margin elements: back button and info/help button
|
|
36442
|
-
// These elements appear after the main container for proper z-order
|
|
36443
|
-
m(LeftLogo),
|
|
36444
|
-
m(Info),
|
|
36445
|
-
]);
|
|
36446
|
-
}
|
|
36651
|
+
};
|
|
36447
36652
|
};
|
|
36448
36653
|
|
|
36449
36654
|
/*
|