GameSentenceMiner 2.15.8__py3-none-any.whl → 2.15.10__py3-none-any.whl
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.
- GameSentenceMiner/ocr/gsm_ocr_config.py +1 -1
- GameSentenceMiner/ocr/owocr_helper.py +21 -12
- GameSentenceMiner/owocr/owocr/run.py +2 -2
- GameSentenceMiner/util/configuration.py +3 -0
- GameSentenceMiner/util/text_log.py +2 -2
- GameSentenceMiner/vad.py +1 -1
- GameSentenceMiner/web/database_api.py +783 -0
- GameSentenceMiner/web/events.py +178 -0
- GameSentenceMiner/web/stats.py +582 -0
- GameSentenceMiner/web/templates/database.html +277 -0
- GameSentenceMiner/web/templates/search.html +103 -0
- GameSentenceMiner/web/templates/stats.html +330 -0
- GameSentenceMiner/web/templates/text_replacements.html +211 -0
- GameSentenceMiner/web/templates/utility.html +2 -2
- GameSentenceMiner/web/texthooking_page.py +58 -316
- GameSentenceMiner/web/websockets.py +120 -0
- {gamesentenceminer-2.15.8.dist-info → gamesentenceminer-2.15.10.dist-info}/METADATA +1 -1
- {gamesentenceminer-2.15.8.dist-info → gamesentenceminer-2.15.10.dist-info}/RECORD +22 -16
- GameSentenceMiner/web/templates/__init__.py +0 -0
- {gamesentenceminer-2.15.8.dist-info → gamesentenceminer-2.15.10.dist-info}/WHEEL +0 -0
- {gamesentenceminer-2.15.8.dist-info → gamesentenceminer-2.15.10.dist-info}/entry_points.txt +0 -0
- {gamesentenceminer-2.15.8.dist-info → gamesentenceminer-2.15.10.dist-info}/licenses/LICENSE +0 -0
- {gamesentenceminer-2.15.8.dist-info → gamesentenceminer-2.15.10.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,330 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="UTF-8">
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6
|
+
<title>GSM Dashboard</title>
|
7
|
+
<!-- Include Chart.js from a CDN -->
|
8
|
+
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
9
|
+
|
10
|
+
<!-- Include shared theme styles -->
|
11
|
+
{% include 'components/theme-styles.html' %}
|
12
|
+
|
13
|
+
<!-- Include shared CSS -->
|
14
|
+
<link rel="stylesheet" href="/static/css/shared.css">
|
15
|
+
|
16
|
+
<!-- Include stats-specific CSS -->
|
17
|
+
<link rel="stylesheet" href="/static/css/stats.css">
|
18
|
+
</head>
|
19
|
+
<body>
|
20
|
+
|
21
|
+
<div class="container">
|
22
|
+
<h1>Game Sentence Miner - Statistics</h1>
|
23
|
+
|
24
|
+
<!-- Include shared navigation -->
|
25
|
+
{% include 'components/navigation.html' %}
|
26
|
+
|
27
|
+
<!-- Dashboard Statistics Sections -->
|
28
|
+
<div class="dashboard-container">
|
29
|
+
<!-- Current Game Statistics Panel -->
|
30
|
+
<div class="dashboard-card current-game" id="currentGameCard">
|
31
|
+
<div class="dashboard-card-header">
|
32
|
+
<div>
|
33
|
+
<h3 class="dashboard-card-title">
|
34
|
+
<span class="dashboard-card-icon">🎮</span>
|
35
|
+
Current Game Statistics
|
36
|
+
</h3>
|
37
|
+
<p class="dashboard-card-subtitle" id="currentGameName">Loading...</p>
|
38
|
+
</div>
|
39
|
+
<div class="dashboard-streak-indicator" id="currentGameStreak" style="display: none;">
|
40
|
+
<span id="currentStreakValue">0</span> day streak
|
41
|
+
</div>
|
42
|
+
</div>
|
43
|
+
|
44
|
+
<div class="dashboard-stats-grid" id="currentGameStats">
|
45
|
+
<div class="dashboard-stat-item tooltip" data-tooltip="Total characters read in this game">
|
46
|
+
<span class="dashboard-stat-value" id="currentTotalChars">-</span>
|
47
|
+
<span class="dashboard-stat-label">Characters</span>
|
48
|
+
</div>
|
49
|
+
<div class="dashboard-stat-item tooltip" data-tooltip="Total time spent reading this game">
|
50
|
+
<span class="dashboard-stat-value" id="currentTotalTime">-</span>
|
51
|
+
<span class="dashboard-stat-label">Time Spent</span>
|
52
|
+
</div>
|
53
|
+
<div class="dashboard-stat-item tooltip" data-tooltip="Average reading speed for this game">
|
54
|
+
<span class="dashboard-stat-value" id="currentReadingSpeed">-</span>
|
55
|
+
<span class="dashboard-stat-label">Chars/Hour</span>
|
56
|
+
</div>
|
57
|
+
<div class="dashboard-stat-item tooltip" data-tooltip="Number of reading sessions for this game">
|
58
|
+
<span class="dashboard-stat-value" id="currentSessions">-</span>
|
59
|
+
<span class="dashboard-stat-label">Sessions</span>
|
60
|
+
</div>
|
61
|
+
</div>
|
62
|
+
|
63
|
+
<div class="dashboard-progress-section">
|
64
|
+
<div class="dashboard-progress-title">Recent Progress</div>
|
65
|
+
<div class="dashboard-progress-items">
|
66
|
+
<div class="dashboard-progress-item">
|
67
|
+
<div class="dashboard-progress-value positive" id="currentMonthlyChars">-</div>
|
68
|
+
<div class="dashboard-progress-label">Monthly Characters</div>
|
69
|
+
</div>
|
70
|
+
<div class="dashboard-progress-item">
|
71
|
+
<div class="dashboard-progress-value neutral" id="currentFirstDate">-</div>
|
72
|
+
<div class="dashboard-progress-label">Started</div>
|
73
|
+
</div>
|
74
|
+
<div class="dashboard-progress-item">
|
75
|
+
<div class="dashboard-progress-value neutral" id="currentLastDate">-</div>
|
76
|
+
<div class="dashboard-progress-label">Last Activity</div>
|
77
|
+
</div>
|
78
|
+
</div>
|
79
|
+
</div>
|
80
|
+
</div>
|
81
|
+
|
82
|
+
<!-- All Games Historical Overview -->
|
83
|
+
<div class="dashboard-card all-games" id="allGamesCard">
|
84
|
+
<div class="dashboard-card-header">
|
85
|
+
<div>
|
86
|
+
<h3 class="dashboard-card-title">
|
87
|
+
<span class="dashboard-card-icon">📚</span>
|
88
|
+
All Games Overview
|
89
|
+
</h3>
|
90
|
+
<p class="dashboard-card-subtitle" id="totalGamesCount">Loading...</p>
|
91
|
+
</div>
|
92
|
+
<div class="dashboard-streak-indicator" id="allGamesStreak" style="display: none;">
|
93
|
+
<span id="allStreakValue">0</span> day streak
|
94
|
+
</div>
|
95
|
+
</div>
|
96
|
+
|
97
|
+
<div class="dashboard-stats-grid" id="allGamesStats">
|
98
|
+
<div class="dashboard-stat-item tooltip" data-tooltip="Total characters read across all games">
|
99
|
+
<span class="dashboard-stat-value" id="allTotalChars">-</span>
|
100
|
+
<span class="dashboard-stat-label">Characters</span>
|
101
|
+
</div>
|
102
|
+
<div class="dashboard-stat-item tooltip" data-tooltip="Total time spent reading across all games">
|
103
|
+
<span class="dashboard-stat-value" id="allTotalTime">-</span>
|
104
|
+
<span class="dashboard-stat-label">Time Spent</span>
|
105
|
+
</div>
|
106
|
+
<div class="dashboard-stat-item tooltip" data-tooltip="Overall average reading speed">
|
107
|
+
<span class="dashboard-stat-value" id="allReadingSpeed">-</span>
|
108
|
+
<span class="dashboard-stat-label">Chars/Hour</span>
|
109
|
+
</div>
|
110
|
+
<div class="dashboard-stat-item tooltip" data-tooltip="Total number of reading sessions">
|
111
|
+
<span class="dashboard-stat-value" id="allSessions">-</span>
|
112
|
+
<span class="dashboard-stat-label">Sessions</span>
|
113
|
+
</div>
|
114
|
+
</div>
|
115
|
+
|
116
|
+
<div class="dashboard-progress-section">
|
117
|
+
<div class="dashboard-progress-title">Overall Progress</div>
|
118
|
+
<div class="dashboard-progress-items">
|
119
|
+
<div class="dashboard-progress-item">
|
120
|
+
<div class="dashboard-progress-value positive" id="allMonthlyChars">-</div>
|
121
|
+
<div class="dashboard-progress-label">Monthly Characters</div>
|
122
|
+
</div>
|
123
|
+
<div class="dashboard-progress-item">
|
124
|
+
<div class="dashboard-progress-value neutral" id="allUniqueGames">-</div>
|
125
|
+
<div class="dashboard-progress-label">Games Played</div>
|
126
|
+
</div>
|
127
|
+
<div class="dashboard-progress-item">
|
128
|
+
<div class="dashboard-progress-value neutral" id="allTotalSentences">-</div>
|
129
|
+
<div class="dashboard-progress-label">Total Sentences</div>
|
130
|
+
</div>
|
131
|
+
</div>
|
132
|
+
</div>
|
133
|
+
</div>
|
134
|
+
</div>
|
135
|
+
|
136
|
+
<!-- Loading/Error states for dashboard -->
|
137
|
+
<div class="dashboard-loading" id="dashboardLoading" style="display: none;">
|
138
|
+
<div class="spinner"></div>
|
139
|
+
<span>Loading dashboard statistics...</span>
|
140
|
+
</div>
|
141
|
+
|
142
|
+
<div class="dashboard-error" id="dashboardError" style="display: none;">
|
143
|
+
<div class="dashboard-error-icon">⚠️</div>
|
144
|
+
<div class="dashboard-error-message">Failed to load dashboard statistics</div>
|
145
|
+
<button class="dashboard-retry-btn" data-action="loadDashboardData">Retry</button>
|
146
|
+
</div>
|
147
|
+
|
148
|
+
|
149
|
+
<!-- Today's Overview Card -->
|
150
|
+
<div class="dashboard-card today-overview" id="todayOverviewCard" style="margin-bottom: 24px;">
|
151
|
+
<div class="dashboard-card-header">
|
152
|
+
<h3 class="dashboard-card-title">
|
153
|
+
<span class="dashboard-card-icon">📅</span>
|
154
|
+
Today's Overview
|
155
|
+
</h3>
|
156
|
+
<p class="dashboard-card-subtitle" id="todayDate">Loading...</p>
|
157
|
+
</div>
|
158
|
+
<div class="dashboard-stats-grid" id="todayStats">
|
159
|
+
<div class="dashboard-stat-item tooltip" data-tooltip="Total hours spent reading today">
|
160
|
+
<span class="dashboard-stat-value" id="todayTotalHours">-</span>
|
161
|
+
<span class="dashboard-stat-label">Hours Spent</span>
|
162
|
+
</div>
|
163
|
+
<div class="dashboard-stat-item tooltip" data-tooltip="Total characters read today">
|
164
|
+
<span class="dashboard-stat-value" id="todayTotalChars">-</span>
|
165
|
+
<span class="dashboard-stat-label">Characters</span>
|
166
|
+
</div>
|
167
|
+
<div class="dashboard-stat-item tooltip" data-tooltip="Number of reading sessions today">
|
168
|
+
<span class="dashboard-stat-value" id="todaySessions">-</span>
|
169
|
+
<span class="dashboard-stat-label">Sessions</span>
|
170
|
+
</div>
|
171
|
+
<div class="dashboard-stat-item tooltip" data-tooltip="Average reading speed today">
|
172
|
+
<span class="dashboard-stat-value" id="todayCharsPerHour">-</span>
|
173
|
+
<span class="dashboard-stat-label">Chars/Hour</span>
|
174
|
+
</div>
|
175
|
+
</div>
|
176
|
+
</div>
|
177
|
+
|
178
|
+
<div class="chart-container">
|
179
|
+
<h2>Lines Received Over Time</h2>
|
180
|
+
<canvas id="linesChart"></canvas>
|
181
|
+
</div>
|
182
|
+
|
183
|
+
<div class="chart-container">
|
184
|
+
<h2>Characters Read Over Time</h2>
|
185
|
+
<canvas id="charsChart"></canvas>
|
186
|
+
</div>
|
187
|
+
|
188
|
+
<div class="chart-container">
|
189
|
+
<h2>Reading Activity Heatmap</h2>
|
190
|
+
<div id="heatmapContainer"></div>
|
191
|
+
</div>
|
192
|
+
|
193
|
+
|
194
|
+
<div class="chart-container">
|
195
|
+
<h2>Reading Chars Quantity</h2>
|
196
|
+
<canvas id="readingCharsChart"></canvas>
|
197
|
+
</div>
|
198
|
+
|
199
|
+
<div class="chart-container">
|
200
|
+
<h2>Reading Time Quantity</h2>
|
201
|
+
<canvas id="readingTimeChart"></canvas>
|
202
|
+
</div>
|
203
|
+
|
204
|
+
<div class="chart-container">
|
205
|
+
<h2>Reading Speed Improvement</h2>
|
206
|
+
<canvas id="readingSpeedPerGameChart"></canvas>
|
207
|
+
</div>
|
208
|
+
|
209
|
+
<div class="chart-container">
|
210
|
+
<h2>Kanji Grid</h2>
|
211
|
+
<div id="kanjiGridContainer">
|
212
|
+
<div id="kanjiCounter" class="kanji-counter">
|
213
|
+
Unique Kanji Seen: <span id="kanjiCount">0</span>
|
214
|
+
</div>
|
215
|
+
<div id="kanjiGrid" class="kanji-grid"></div>
|
216
|
+
<div class="kanji-legend">
|
217
|
+
<span>Rarely Seen</span>
|
218
|
+
<div class="kanji-legend-item" style="background-color: #ebedf0;" title="No encounters"></div>
|
219
|
+
<div class="kanji-legend-item" style="background-color: #e6342e;" title="Seen once"></div>
|
220
|
+
<div class="kanji-legend-item" style="background-color: #e6dc2e;" title="Occasionally seen"></div>
|
221
|
+
<div class="kanji-legend-item" style="background-color: #3be62f;" title="Frequently seen"></div>
|
222
|
+
<div class="kanji-legend-item" style="background-color: #2ee6e0;" title="Most frequently seen"></div>
|
223
|
+
<span>Frequently Seen</span>
|
224
|
+
</div>
|
225
|
+
</div>
|
226
|
+
</div>
|
227
|
+
|
228
|
+
<!-- Settings Modal -->
|
229
|
+
<div id="settingsModal" class="modal">
|
230
|
+
<div class="modal-content">
|
231
|
+
<div class="modal-header">
|
232
|
+
<h3>Statistics Settings</h3>
|
233
|
+
<span class="close-btn" id="closeSettingsModal">×</span>
|
234
|
+
</div>
|
235
|
+
<div class="modal-body">
|
236
|
+
<p style="color: var(--text-secondary); margin-bottom: 20px;">
|
237
|
+
Configure how reading time and sessions are calculated for your statistics.
|
238
|
+
</p>
|
239
|
+
|
240
|
+
<form id="settingsForm">
|
241
|
+
<div style="margin-bottom: 20px;">
|
242
|
+
<label for="afkTimer" style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
|
243
|
+
AFK Timer (seconds)
|
244
|
+
</label>
|
245
|
+
<input
|
246
|
+
type="number"
|
247
|
+
id="afkTimer"
|
248
|
+
name="afk_timer_seconds"
|
249
|
+
min="30"
|
250
|
+
max="600"
|
251
|
+
style="width: 100%; padding: 10px; border: 1px solid var(--border-color); border-radius: 5px; background: var(--bg-tertiary); color: var(--text-primary); font-size: 14px;"
|
252
|
+
placeholder="120"
|
253
|
+
>
|
254
|
+
<small style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
|
255
|
+
Maximum time between activities that still counts as active reading (30-600 seconds)
|
256
|
+
</small>
|
257
|
+
</div>
|
258
|
+
|
259
|
+
<div style="margin-bottom: 20px;">
|
260
|
+
<label for="sessionGap" style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
|
261
|
+
Session Gap (seconds)
|
262
|
+
</label>
|
263
|
+
<input
|
264
|
+
type="number"
|
265
|
+
id="sessionGap"
|
266
|
+
name="session_gap_seconds"
|
267
|
+
min="300"
|
268
|
+
max="7200"
|
269
|
+
style="width: 100%; padding: 10px; border: 1px solid var(--border-color); border-radius: 5px; background: var(--bg-tertiary); color: var(--text-primary); font-size: 14px;"
|
270
|
+
placeholder="3600"
|
271
|
+
>
|
272
|
+
<small style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
|
273
|
+
Time gap that triggers a new reading session (5 minutes to 2 hours)
|
274
|
+
</small>
|
275
|
+
</div>
|
276
|
+
|
277
|
+
<div style="margin-bottom: 20px;">
|
278
|
+
<label for="heatmapYear" style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
|
279
|
+
Heatmap Display Year
|
280
|
+
</label>
|
281
|
+
<select
|
282
|
+
id="heatmapYear"
|
283
|
+
name="heatmap_year"
|
284
|
+
style="width: 100%; padding: 10px; border: 1px solid var(--border-color); border-radius: 5px; background: var(--bg-tertiary); color: var(--text-primary); font-size: 14px;"
|
285
|
+
>
|
286
|
+
<option value="all">All Years</option>
|
287
|
+
</select>
|
288
|
+
<small style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
|
289
|
+
Select which year to display in the reading activity heatmap
|
290
|
+
</small>
|
291
|
+
</div>
|
292
|
+
|
293
|
+
<div style="margin-bottom: 20px;">
|
294
|
+
<label for="streakRequirement" style="display: block; font-weight: 600; margin-bottom: 8px; color: var(--text-primary);">
|
295
|
+
Streak Requirement (hours)
|
296
|
+
</label>
|
297
|
+
<input
|
298
|
+
type="number"
|
299
|
+
id="streakRequirement"
|
300
|
+
name="streak_requirement_hours"
|
301
|
+
min="0.01"
|
302
|
+
max="24"
|
303
|
+
step="0.01"
|
304
|
+
style="width: 100%; padding: 10px; border: 1px solid var(--border-color); border-radius: 5px; background: var(--bg-tertiary); color: var(--text-primary); font-size: 14px;"
|
305
|
+
placeholder="1.0"
|
306
|
+
>
|
307
|
+
<small style="color: var(--text-tertiary); font-size: 12px; margin-top: 4px; display: block;">
|
308
|
+
Minimum hours of reading activity required to maintain streak (0.01-24 hours)
|
309
|
+
</small>
|
310
|
+
</div>
|
311
|
+
</form>
|
312
|
+
|
313
|
+
<div id="settingsError" style="display: none; background: var(--danger-color); color: white; padding: 10px; border-radius: 5px; margin-bottom: 15px; font-size: 14px;"></div>
|
314
|
+
<div id="settingsSuccess" style="display: none; background: var(--success-color); color: white; padding: 10px; border-radius: 5px; margin-bottom: 15px; font-size: 14px;"></div>
|
315
|
+
</div>
|
316
|
+
<div class="modal-footer">
|
317
|
+
<button id="cancelSettingsBtn" class="cancel-btn">Cancel</button>
|
318
|
+
<button id="saveSettingsBtn" class="confirm-delete-btn">Save Settings</button>
|
319
|
+
</div>
|
320
|
+
</div>
|
321
|
+
</div>
|
322
|
+
</div>
|
323
|
+
|
324
|
+
|
325
|
+
<!-- Include shared JavaScript first (required dependency for stats.js) -->
|
326
|
+
<script src="/static/js/shared.js"></script>
|
327
|
+
<script src="/static/js/stats.js"></script>
|
328
|
+
|
329
|
+
</body>
|
330
|
+
</html>
|
@@ -6,9 +6,158 @@
|
|
6
6
|
<title>Text Error Fixes (Electron)</title>
|
7
7
|
<link rel="stylesheet" href="/static/style.css">
|
8
8
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap" rel="stylesheet">
|
9
|
+
<style>
|
10
|
+
:root {
|
11
|
+
/* Light theme colors */
|
12
|
+
--bg-primary: #f8f9fa;
|
13
|
+
--bg-secondary: #ffffff;
|
14
|
+
--bg-tertiary: #e9ecef;
|
15
|
+
--text-primary: #212529;
|
16
|
+
--text-secondary: #495057;
|
17
|
+
--text-tertiary: #6c757d;
|
18
|
+
--border-color: #dee2e6;
|
19
|
+
--shadow-color: rgba(0, 0, 0, 0.08);
|
20
|
+
--accent-color: #007bff;
|
21
|
+
--success-color: #28a745;
|
22
|
+
--warning-color: #ffc107;
|
23
|
+
--danger-color: #dc3545;
|
24
|
+
--info-color: #17a2b8;
|
25
|
+
}
|
26
|
+
|
27
|
+
[data-theme="dark"] {
|
28
|
+
/* Dark theme colors */
|
29
|
+
--bg-primary: #1a1a1a;
|
30
|
+
--bg-secondary: #2d2d2d;
|
31
|
+
--bg-tertiary: #3a3a3a;
|
32
|
+
--text-primary: #e1e1e1;
|
33
|
+
--text-secondary: #b8b8b8;
|
34
|
+
--text-tertiary: #8a8a8a;
|
35
|
+
--border-color: #404040;
|
36
|
+
--shadow-color: rgba(0, 0, 0, 0.3);
|
37
|
+
--accent-color: #4dabf7;
|
38
|
+
--success-color: #51cf66;
|
39
|
+
--warning-color: #ffd43b;
|
40
|
+
--danger-color: #ff6b6b;
|
41
|
+
--info-color: #22b8cf;
|
42
|
+
}
|
43
|
+
|
44
|
+
@media (prefers-color-scheme: dark) {
|
45
|
+
:root:not([data-theme="light"]) {
|
46
|
+
/* Auto dark mode colors */
|
47
|
+
--bg-primary: #1a1a1a;
|
48
|
+
--bg-secondary: #2d2d2d;
|
49
|
+
--bg-tertiary: #3a3a3a;
|
50
|
+
--text-primary: #e1e1e1;
|
51
|
+
--text-secondary: #b8b8b8;
|
52
|
+
--text-tertiary: #8a8a8a;
|
53
|
+
--border-color: #404040;
|
54
|
+
--shadow-color: rgba(0, 0, 0, 0.3);
|
55
|
+
--accent-color: #4dabf7;
|
56
|
+
--success-color: #51cf66;
|
57
|
+
--warning-color: #ffd43b;
|
58
|
+
--danger-color: #ff6b6b;
|
59
|
+
--info-color: #22b8cf;
|
60
|
+
}
|
61
|
+
}
|
62
|
+
|
63
|
+
.nav-link {
|
64
|
+
display: inline-block;
|
65
|
+
padding: 8px 16px;
|
66
|
+
background-color: var(--bg-tertiary);
|
67
|
+
color: var(--text-primary);
|
68
|
+
text-decoration: none;
|
69
|
+
border-radius: 5px;
|
70
|
+
transition: all 0.3s ease;
|
71
|
+
border: 1px solid var(--border-color);
|
72
|
+
}
|
73
|
+
|
74
|
+
.nav-link:hover {
|
75
|
+
background-color: var(--accent-color);
|
76
|
+
color: var(--bg-secondary);
|
77
|
+
transform: translateY(-1px);
|
78
|
+
}
|
79
|
+
|
80
|
+
.theme-toggle {
|
81
|
+
background: var(--bg-tertiary);
|
82
|
+
border: 2px solid var(--border-color);
|
83
|
+
border-radius: 50%;
|
84
|
+
width: 40px;
|
85
|
+
height: 40px;
|
86
|
+
display: flex;
|
87
|
+
align-items: center;
|
88
|
+
justify-content: center;
|
89
|
+
cursor: pointer;
|
90
|
+
transition: all 0.3s ease;
|
91
|
+
color: var(--text-primary);
|
92
|
+
font-size: 18px;
|
93
|
+
margin-left: 15px;
|
94
|
+
}
|
95
|
+
|
96
|
+
.theme-toggle:hover {
|
97
|
+
background: var(--bg-primary);
|
98
|
+
transform: scale(1.1);
|
99
|
+
}
|
100
|
+
|
101
|
+
.theme-toggle:active {
|
102
|
+
transform: scale(0.95);
|
103
|
+
}
|
104
|
+
|
105
|
+
@media (max-width: 768px) {
|
106
|
+
.navigation {
|
107
|
+
padding: 10px;
|
108
|
+
flex-direction: column;
|
109
|
+
gap: 10px;
|
110
|
+
}
|
111
|
+
|
112
|
+
.navigation > div {
|
113
|
+
flex-direction: column;
|
114
|
+
gap: 10px;
|
115
|
+
}
|
116
|
+
|
117
|
+
.navigation .nav-link {
|
118
|
+
display: block !important;
|
119
|
+
text-align: center;
|
120
|
+
width: 100%;
|
121
|
+
}
|
122
|
+
|
123
|
+
.theme-toggle {
|
124
|
+
margin-left: 0;
|
125
|
+
align-self: center;
|
126
|
+
}
|
127
|
+
}
|
128
|
+
</style>
|
9
129
|
</head>
|
10
130
|
<body> <div class="container">
|
11
131
|
<h1>Text Error Fixes</h1>
|
132
|
+
|
133
|
+
<div class="navigation" style="display: flex; justify-content: center; align-items: center; margin-bottom: 30px; padding: 15px; background: var(--bg-secondary); border-radius: 8px; box-shadow: 0 2px 8px var(--shadow-color); border: 1px solid var(--border-color);">
|
134
|
+
<div style="display: flex; gap: 15px;">
|
135
|
+
<a href="/" class="nav-link">Home</a>
|
136
|
+
<a href="/stats" class="nav-link">Statistics</a>
|
137
|
+
<a href="/search" class="nav-link">Search</a>
|
138
|
+
<a href="/text_replacements_page" class="nav-link">Text Replacements</a>
|
139
|
+
</div>
|
140
|
+
<button class="theme-toggle" id="themeToggle" title="Toggle dark mode">
|
141
|
+
<span id="themeIcon">🌙</span>
|
142
|
+
</button>
|
143
|
+
</div>
|
144
|
+
|
145
|
+
<!-- Explanation Section -->
|
146
|
+
<div style="background: var(--bg-secondary); padding: 20px; border-radius: 8px; box-shadow: 0 2px 8px var(--shadow-color); margin-bottom: 30px; border: 1px solid var(--border-color);">
|
147
|
+
<h2 style="color: var(--text-secondary); margin-bottom: 15px;">What are Text Replacements?</h2>
|
148
|
+
<p style="color: var(--text-primary); line-height: 1.6; margin-bottom: 10px;">
|
149
|
+
Text replacements help you automatically fix common errors and clean up text captured from games. This is especially useful for:
|
150
|
+
</p>
|
151
|
+
<ul style="color: var(--text-primary); line-height: 1.6; margin-left: 20px; margin-bottom: 15px;">
|
152
|
+
<li><strong>OCR Error Correction:</strong> Fix text recognition mistakes from screenshots</li>
|
153
|
+
<li><strong>Text Standardization:</strong> Replace inconsistent character names or terms</li>
|
154
|
+
<li><strong>Regex Pattern Support:</strong> Use "re:" prefix for advanced pattern matching (e.g., "re:.{3,}" for sequences)</li>
|
155
|
+
<li><strong>Game-Specific Fixes:</strong> Handle unique formatting issues from different games</li>
|
156
|
+
</ul>
|
157
|
+
<p style="color: var(--text-tertiary); font-size: 14px; margin: 0;">
|
158
|
+
<strong>Pro Tip:</strong> Replacements are applied in the order they appear. Use regex patterns for complex transformations.
|
159
|
+
</p>
|
160
|
+
</div>
|
12
161
|
|
13
162
|
<div class="control"> <button id="add-new-btn" class="button-blue">Add New Entry</button> <div class="search-container"> <input type="text" id="search-input" placeholder="Search key or value..." class="inputField"> <button id="search-button" class="button-green">Search</button> </div>
|
14
163
|
<button id="go-back-btn" class="button-gray">Go Back</button>
|
@@ -233,6 +382,68 @@
|
|
233
382
|
|
234
383
|
loadData();
|
235
384
|
|
385
|
+
// Dark mode toggle functionality
|
386
|
+
function initializeThemeToggle() {
|
387
|
+
const themeToggle = document.getElementById('themeToggle');
|
388
|
+
const themeIcon = document.getElementById('themeIcon');
|
389
|
+
const documentElement = document.documentElement;
|
390
|
+
|
391
|
+
// Check for saved theme preference or default to browser preference
|
392
|
+
function getPreferredTheme() {
|
393
|
+
const savedTheme = localStorage.getItem('theme');
|
394
|
+
if (savedTheme) {
|
395
|
+
return savedTheme;
|
396
|
+
}
|
397
|
+
|
398
|
+
// Check browser preference
|
399
|
+
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
400
|
+
return 'dark';
|
401
|
+
}
|
402
|
+
|
403
|
+
return 'light';
|
404
|
+
}
|
405
|
+
|
406
|
+
// Apply theme
|
407
|
+
function applyTheme(theme) {
|
408
|
+
if (theme === 'dark') {
|
409
|
+
documentElement.setAttribute('data-theme', 'dark');
|
410
|
+
themeIcon.textContent = '☀️';
|
411
|
+
themeToggle.title = 'Switch to light mode';
|
412
|
+
} else {
|
413
|
+
documentElement.setAttribute('data-theme', 'light');
|
414
|
+
themeIcon.textContent = '🌙';
|
415
|
+
themeToggle.title = 'Switch to dark mode';
|
416
|
+
}
|
417
|
+
}
|
418
|
+
|
419
|
+
// Initialize theme
|
420
|
+
const currentTheme = getPreferredTheme();
|
421
|
+
applyTheme(currentTheme);
|
422
|
+
|
423
|
+
// Toggle theme on button click
|
424
|
+
themeToggle.addEventListener('click', () => {
|
425
|
+
const currentTheme = documentElement.getAttribute('data-theme');
|
426
|
+
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
|
427
|
+
|
428
|
+
applyTheme(newTheme);
|
429
|
+
localStorage.setItem('theme', newTheme);
|
430
|
+
});
|
431
|
+
|
432
|
+
// Listen for browser theme changes
|
433
|
+
if (window.matchMedia) {
|
434
|
+
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
435
|
+
mediaQuery.addEventListener('change', (e) => {
|
436
|
+
// Only auto-switch if user hasn't manually set a preference
|
437
|
+
if (!localStorage.getItem('theme')) {
|
438
|
+
applyTheme(e.matches ? 'dark' : 'light');
|
439
|
+
}
|
440
|
+
});
|
441
|
+
}
|
442
|
+
}
|
443
|
+
|
444
|
+
// Initialize theme toggle
|
445
|
+
initializeThemeToggle();
|
446
|
+
|
236
447
|
</script>
|
237
448
|
</body>
|
238
449
|
</html>
|
@@ -109,8 +109,8 @@
|
|
109
109
|
</head>
|
110
110
|
<body>
|
111
111
|
<div style="position: fixed; top: 20px; right: 20px; display: flex; gap: 10px;">
|
112
|
-
<button onclick="window.location.href='/
|
113
|
-
|
112
|
+
<button onclick="window.location.href='/database'" style="background-color: #1a73e8; color: #ffffff; border: none; padding: 10px 20px; font-size: 12px; cursor: pointer; transition: background-color 0.3s; border-radius: 5px;">
|
113
|
+
Database Management
|
114
114
|
</button>
|
115
115
|
<button id="delete-history" style="background-color: #1a73e8; color: #ffffff; border: none; padding: 10px 20px; font-size: 12px; cursor: pointer; transition: background-color 0.3s; border-radius: 5px;">
|
116
116
|
Clear History
|