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