sondakika 2.0.0 → 2.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.
@@ -1,649 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="tr">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:;">
7
- <title>Sondakika</title>
8
- <link rel="preconnect" href="https://fonts.googleapis.com">
9
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10
- <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
11
- <style>
12
- * { margin:0; padding:0; box-sizing: border-box; }
13
-
14
- :root {
15
- --bg-primary: #0f0f1a;
16
- --bg-secondary: #1a1a2e;
17
- --bg-card: #252542;
18
- --bg-elevated: #2d2d4a;
19
- --accent: #6366f1;
20
- --accent-sec: #818cf8;
21
- --accent-hover: #4f46e5;
22
- --text-primary: #f1f5f9;
23
- --text-sec: #94a3b8;
24
- --text-muted: #64748b;
25
- --border: #334155;
26
- --breaking: #ef4444;
27
- --error: #ef4444;
28
- }
29
-
30
- body {
31
- font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
32
- background: var(--bg-primary);
33
- color: var(--text-primary);
34
- height: 100vh;
35
- overflow: hidden;
36
- display: flex;
37
- flex-direction: column;
38
- }
39
-
40
- /* ── Top bar ── */
41
- .topbar {
42
- display: flex;
43
- align-items: center;
44
- gap: 12px;
45
- padding: 10px 24px;
46
- background: var(--bg-secondary);
47
- border-bottom: 1px solid var(--border);
48
- flex-shrink: 0;
49
- -webkit-app-region: drag;
50
- flex-wrap: wrap;
51
- }
52
-
53
- .topbar > * { -webkit-app-region: no-drag; }
54
-
55
- .topbar-source {
56
- padding: 4px 10px;
57
- background: var(--bg-card);
58
- border-radius: 6px;
59
- font-size: 11px;
60
- font-weight: 600;
61
- color: var(--text-sec);
62
- text-transform: uppercase;
63
- letter-spacing: 0.5px;
64
- }
65
- .topbar-source.breaking {
66
- background: rgba(239,68,68,0.15);
67
- color: var(--breaking);
68
- }
69
-
70
- .topbar-title {
71
- flex: 1;
72
- font-size: 14px;
73
- font-weight: 600;
74
- color: var(--text-primary);
75
- white-space: nowrap;
76
- overflow: hidden;
77
- text-overflow: ellipsis;
78
- }
79
-
80
- .topbar-date {
81
- font-size: 12px;
82
- color: var(--accent-sec);
83
- background: rgba(99,102,241,0.15);
84
- padding: 5px 12px;
85
- border-radius: 6px;
86
- font-weight: 600;
87
- white-space: nowrap;
88
- flex-shrink: 0;
89
- }
90
-
91
- .topbar-counter {
92
- font-size: 12px;
93
- color: var(--text-muted);
94
- background: var(--bg-card);
95
- padding: 5px 12px;
96
- border-radius: 6px;
97
- font-weight: 600;
98
- white-space: nowrap;
99
- flex-shrink: 0;
100
- border: 1px solid var(--border);
101
- }
102
-
103
- /* ── Font Control Bar ── */
104
- .font-bar {
105
- display: flex;
106
- align-items: center;
107
- gap: 16px;
108
- padding: 8px 24px;
109
- background: var(--bg-elevated);
110
- border-bottom: 1px solid var(--border);
111
- flex-shrink: 0;
112
- }
113
-
114
- .font-group {
115
- display: flex;
116
- align-items: center;
117
- gap: 8px;
118
- }
119
-
120
- .font-group-label {
121
- font-size: 11px;
122
- font-weight: 600;
123
- color: var(--text-muted);
124
- text-transform: uppercase;
125
- letter-spacing: 0.5px;
126
- white-space: nowrap;
127
- }
128
-
129
- .font-btn {
130
- width: 28px;
131
- height: 28px;
132
- display: flex;
133
- align-items: center;
134
- justify-content: center;
135
- background: var(--bg-card);
136
- border: 1px solid var(--border);
137
- border-radius: 6px;
138
- color: var(--text-primary);
139
- font-size: 12px;
140
- font-weight: 600;
141
- cursor: pointer;
142
- transition: all 0.2s ease;
143
- font-family: inherit;
144
- }
145
- .font-btn:hover {
146
- background: var(--accent);
147
- border-color: var(--accent);
148
- color: white;
149
- }
150
-
151
- .font-value {
152
- font-size: 12px;
153
- font-weight: 600;
154
- color: var(--accent-sec);
155
- min-width: 36px;
156
- text-align: center;
157
- }
158
-
159
- .font-separator {
160
- width: 1px;
161
- height: 20px;
162
- background: var(--border);
163
- }
164
-
165
- /* ── Scrollable content area ── */
166
- .article-scroll {
167
- flex: 1;
168
- overflow-y: auto;
169
- overflow-x: hidden;
170
- scroll-behavior: smooth;
171
- }
172
-
173
- .article-inner {
174
- max-width: 820px;
175
- margin: 0 auto;
176
- padding: 40px 48px 60px;
177
- }
178
-
179
- .article-hero {
180
- margin-bottom: 32px;
181
- }
182
-
183
- .article-headline {
184
- font-size: 28px;
185
- font-weight: 700;
186
- line-height: 1.4;
187
- color: var(--text-primary);
188
- margin-bottom: 20px;
189
- }
190
-
191
- .article-meta-row {
192
- display: flex;
193
- align-items: center;
194
- gap: 12px;
195
- flex-wrap: wrap;
196
- margin-bottom: 24px;
197
- }
198
-
199
- .tag {
200
- padding: 5px 12px;
201
- border-radius: 6px;
202
- font-size: 11px;
203
- font-weight: 700;
204
- letter-spacing: 0.5px;
205
- text-transform: uppercase;
206
- }
207
- .tag-source {
208
- background: var(--bg-card);
209
- color: var(--text-sec);
210
- border: 1px solid var(--border);
211
- }
212
- .tag-breaking {
213
- background: rgba(239,68,68,0.15);
214
- color: var(--breaking);
215
- }
216
-
217
- .article-image {
218
- width: 100%;
219
- max-height: 360px;
220
- object-fit: cover;
221
- border-radius: 16px;
222
- border: 1px solid var(--border);
223
- box-shadow: 0 8px 40px rgba(0,0,0,0.5);
224
- margin-bottom: 32px;
225
- display: block;
226
- }
227
-
228
- .article-body {
229
- font-size: 17px;
230
- line-height: 2;
231
- color: var(--text-sec);
232
- white-space: pre-wrap;
233
- }
234
- .article-body::first-letter { margin-left: 28px; }
235
-
236
- /* ── Bottom nav bar ── */
237
- .bottombar {
238
- display: flex;
239
- align-items: center;
240
- justify-content: space-between;
241
- gap: 12px;
242
- padding: 14px 24px;
243
- background: var(--bg-secondary);
244
- border-top: 1px solid var(--border);
245
- flex-shrink: 0;
246
- }
247
-
248
- .nav-btn {
249
- display: flex;
250
- align-items: center;
251
- gap: 8px;
252
- padding: 10px 20px;
253
- background: var(--bg-card);
254
- border: 1px solid var(--border);
255
- border-radius: 10px;
256
- color: var(--text-primary);
257
- font-size: 13px;
258
- font-weight: 600;
259
- cursor: pointer;
260
- transition: all 0.2s ease;
261
- font-family: inherit;
262
- min-width: 110px;
263
- justify-content: center;
264
- }
265
- .nav-btn:hover {
266
- background: var(--bg-elevated);
267
- border-color: var(--accent);
268
- color: var(--accent-sec);
269
- }
270
- .nav-btn:disabled {
271
- opacity: 0.35;
272
- cursor: not-allowed;
273
- }
274
-
275
- .return-btn {
276
- display: flex;
277
- align-items: center;
278
- gap: 8px;
279
- padding: 10px 20px;
280
- background: rgba(99,102,241,0.15);
281
- border: 1px solid rgba(99,102,241,0.4);
282
- border-radius: 10px;
283
- color: var(--accent-sec);
284
- font-size: 13px;
285
- font-weight: 600;
286
- cursor: pointer;
287
- transition: all 0.2s ease;
288
- font-family: inherit;
289
- }
290
- .return-btn:hover {
291
- background: var(--accent);
292
- border-color: var(--accent);
293
- color: white;
294
- }
295
-
296
- .open-browser-btn {
297
- display: flex;
298
- align-items: center;
299
- gap: 8px;
300
- padding: 10px 20px;
301
- background: var(--bg-card);
302
- border: 1px solid var(--border);
303
- border-radius: 10px;
304
- color: var(--text-sec);
305
- font-size: 13px;
306
- font-weight: 600;
307
- cursor: pointer;
308
- transition: all 0.2s ease;
309
- font-family: inherit;
310
- }
311
- .open-browser-btn:hover {
312
- background: var(--accent);
313
- border-color: var(--accent);
314
- color: white;
315
- }
316
-
317
- .center-group {
318
- display: flex;
319
- align-items: center;
320
- gap: 10px;
321
- }
322
-
323
- /* Keys hint */
324
- .keys-hint {
325
- font-size: 11px;
326
- color: var(--text-muted);
327
- text-align: center;
328
- }
329
- .keys-hint kbd {
330
- display: inline-block;
331
- padding: 1px 6px;
332
- background: var(--bg-elevated);
333
- border: 1px solid var(--border);
334
- border-radius: 4px;
335
- font-family: inherit;
336
- font-size: 10px;
337
- margin: 0 2px;
338
- }
339
-
340
- /* Slide animations */
341
- @keyframes slideInRight {
342
- from { opacity: 0; transform: translateX(60px); }
343
- to { opacity: 1; transform: translateX(0); }
344
- }
345
- @keyframes slideInLeft {
346
- from { opacity: 0; transform: translateX(-60px); }
347
- to { opacity: 1; transform: translateX(0); }
348
- }
349
- .slide-right { animation: slideInRight 0.25s cubic-bezier(0.22,1,0.36,1); }
350
- .slide-left { animation: slideInLeft 0.25s cubic-bezier(0.22,1,0.36,1); }
351
-
352
- ::-webkit-scrollbar { width: 8px; }
353
- ::-webkit-scrollbar-track { background: var(--bg-secondary); }
354
- ::-webkit-scrollbar-thumb { background: var(--border); border-radius: 4px; }
355
- ::-webkit-scrollbar-thumb:hover { background: var(--text-muted); }
356
- </style>
357
- </head>
358
- <body>
359
-
360
- <!-- Top bar -->
361
- <div class="topbar">
362
- <span class="topbar-source" id="tbSource"></span>
363
- <span class="topbar-title" id="tbTitle"></span>
364
- <span class="topbar-date" id="tbDate"></span>
365
- <span class="topbar-counter" id="tbCounter"></span>
366
- </div>
367
-
368
- <!-- Font Control Bar -->
369
- <div class="font-bar">
370
- <div class="font-group">
371
- <span class="font-group-label">Başlık <kbd>1</kbd><kbd>2</kbd></span>
372
- <button class="font-btn" onclick="changeTitleFont(-1)">−</button>
373
- <span class="font-value" id="titleFontVal">28px</span>
374
- <button class="font-btn" onclick="changeTitleFont(1)">+</button>
375
- </div>
376
- <div class="font-separator"></div>
377
- <div class="font-group">
378
- <span class="font-group-label">İçerik <kbd>3</kbd><kbd>4</kbd></span>
379
- <button class="font-btn" onclick="changeContentFont(-1)">−</button>
380
- <span class="font-value" id="contentFontVal">17px</span>
381
- <button class="font-btn" onclick="changeContentFont(1)">+</button>
382
- </div>
383
- </div>
384
-
385
- <!-- Scrollable article -->
386
- <div class="article-scroll" id="articleScroll">
387
- <div class="article-inner" id="articleInner">
388
- <div class="article-hero">
389
- <h1 class="article-headline" id="artHeadline"></h1>
390
- <div class="article-meta-row" id="artMeta"></div>
391
- </div>
392
- <img id="artImage" class="article-image" style="display:none" />
393
- <div class="article-body" id="artBody"></div>
394
- </div>
395
- </div>
396
-
397
- <!-- Bottom bar -->
398
- <div class="bottombar">
399
- <button class="nav-btn" id="prevBtn">← Önceki</button>
400
-
401
- <div class="center-group">
402
- <button class="return-btn" id="returnBtn">↩ Listeye Dön</button>
403
- <button class="open-browser-btn" id="browserBtn">🌐 Tarayıcıda Aç</button>
404
- <div class="keys-hint">
405
- <kbd>↑</kbd><kbd>↓</kbd> Kaydır &nbsp;
406
- <kbd>←</kbd><kbd>→</kbd> Haber &nbsp;
407
- <kbd>1</kbd><kbd>2</kbd> Başlık &nbsp;
408
- <kbd>3</kbd><kbd>4</kbd> İçerik &nbsp;
409
- <kbd>`</kbd> Tarayıcı &nbsp;
410
- <kbd>Enter</kbd> Listeye dön
411
- </div>
412
- </div>
413
-
414
- <button class="nav-btn" id="nextBtn">Sonraki →</button>
415
- </div>
416
-
417
- <script>
418
- let newsItems = [];
419
- let currentIdx = 0;
420
- let currentUrl = '';
421
- let titleFontSize = 28;
422
- let contentFontSize = 17;
423
-
424
- function el(id) {
425
- return document.getElementById(id);
426
- }
427
-
428
- function formatDate(dateStr) {
429
- if (!dateStr) return '';
430
- const d = new Date(dateStr);
431
- if (isNaN(d.getTime())) return '';
432
- return d.toLocaleDateString('tr-TR', {
433
- day: '2-digit', month: '2-digit', year: 'numeric',
434
- hour: '2-digit', minute: '2-digit'
435
- });
436
- }
437
-
438
- function renderArticle(idx, slideDir) {
439
- const news = newsItems[idx];
440
- if (!news) return;
441
- currentIdx = idx;
442
- currentUrl = news.link || '';
443
-
444
- const inner = el('articleInner');
445
- if (inner) {
446
- inner.classList.remove('slide-right', 'slide-left');
447
- void inner.offsetWidth;
448
- if (slideDir === 'right') inner.classList.add('slide-right');
449
- else if (slideDir === 'left') inner.classList.add('slide-left');
450
- }
451
-
452
- const scroll = el('articleScroll');
453
- if (scroll) scroll.scrollTop = 0;
454
-
455
- const tbSource = el('tbSource');
456
- if (tbSource) {
457
- tbSource.textContent = news.sourceName || '';
458
- tbSource.className = 'topbar-source' + (news.isSondakika ? ' breaking' : '');
459
- }
460
- const tbTitle = el('tbTitle');
461
- if (tbTitle) tbTitle.textContent = news.title || '';
462
- const tbDate = el('tbDate');
463
- if (tbDate) tbDate.textContent = formatDate(news.pubDate || news.isoDate);
464
- const tbCounter = el('tbCounter');
465
- if (tbCounter) tbCounter.textContent = (idx + 1) + ' / ' + newsItems.length;
466
-
467
- const headline = el('artHeadline');
468
- if (headline) {
469
- headline.textContent = news.title || '';
470
- headline.style.fontSize = titleFontSize + 'px';
471
- }
472
-
473
- const metaRow = el('artMeta');
474
- if (metaRow) {
475
- metaRow.innerHTML =
476
- '<span class="tag tag-source">' + (news.sourceName || '') + '</span>' +
477
- (news.isSondakika ? '<span class="tag tag-breaking">SON DAKİKA</span>' : '') +
478
- '<span style="font-size:12px;color:var(--accent-sec);background:rgba(99,102,241,0.15);padding:5px 12px;border-radius:6px;font-weight:600;">🕒 ' +
479
- formatDate(news.pubDate || news.isoDate) + '</span>';
480
- }
481
-
482
- const img = el('artImage');
483
- if (img) {
484
- if (news.imageUrl) {
485
- img.src = news.imageUrl;
486
- img.style.display = 'block';
487
- img.onerror = () => { img.style.display = 'none'; };
488
- } else {
489
- img.style.display = 'none';
490
- }
491
- }
492
-
493
- let content = news.fullContent || news.content || news.summary ||
494
- news.contentSnippet || news.description || news.title || 'İçerik bulunmuyor.';
495
- content = content.replace(/<img[^>]*>/gi, '')
496
- .replace(/<a[^>]*>/gi, '')
497
- .replace(/<\/a>/gi, '')
498
- .trim();
499
- const body = el('artBody');
500
- if (body) {
501
- body.textContent = content;
502
- body.style.fontSize = contentFontSize + 'px';
503
- }
504
-
505
- const prevBtn = el('prevBtn');
506
- if (prevBtn) prevBtn.disabled = idx === 0;
507
- const nextBtn = el('nextBtn');
508
- if (nextBtn) nextBtn.disabled = idx === newsItems.length - 1;
509
- }
510
-
511
- function navigate(direction) {
512
- const next = currentIdx + direction;
513
- if (next >= 0 && next < newsItems.length) {
514
- renderArticle(next, direction > 0 ? 'right' : 'left');
515
- }
516
- }
517
-
518
- function returnToMain() {
519
- window.electronAPI.close(currentIdx);
520
- }
521
-
522
- function changeTitleFont(delta) {
523
- titleFontSize = Math.max(16, Math.min(48, titleFontSize + delta));
524
- const tf = el('titleFontVal');
525
- if (tf) tf.textContent = titleFontSize + 'px';
526
- const headline = el('artHeadline');
527
- if (headline) headline.style.fontSize = titleFontSize + 'px';
528
- window.electronAPI.setTitleFontSize(titleFontSize);
529
- }
530
-
531
- function changeContentFont(delta) {
532
- contentFontSize = Math.max(12, Math.min(32, contentFontSize + delta));
533
- const cf = el('contentFontVal');
534
- if (cf) cf.textContent = contentFontSize + 'px';
535
- const body = el('artBody');
536
- if (body) body.style.fontSize = contentFontSize + 'px';
537
- window.electronAPI.setContentFontSize(contentFontSize);
538
- }
539
-
540
- // Keyboard
541
- document.addEventListener('keydown', (e) => {
542
- const scroll = el('articleScroll');
543
- if (!scroll) return;
544
-
545
- switch (e.key) {
546
- case 'ArrowDown':
547
- case ' ':
548
- e.preventDefault();
549
- scroll.scrollBy({ top: 140, behavior: 'smooth' });
550
- break;
551
- case 'ArrowUp':
552
- e.preventDefault();
553
- scroll.scrollBy({ top: -140, behavior: 'smooth' });
554
- break;
555
- case 'PageDown':
556
- e.preventDefault();
557
- scroll.scrollBy({ top: scroll.clientHeight * 0.85, behavior: 'smooth' });
558
- break;
559
- case 'PageUp':
560
- e.preventDefault();
561
- scroll.scrollBy({ top: -scroll.clientHeight * 0.85, behavior: 'smooth' });
562
- break;
563
- case 'Home':
564
- e.preventDefault();
565
- scroll.scrollTo({ top: 0, behavior: 'smooth' });
566
- break;
567
- case 'End':
568
- e.preventDefault();
569
- scroll.scrollTo({ top: scroll.scrollHeight, behavior: 'smooth' });
570
- break;
571
- case 'ArrowRight':
572
- e.preventDefault();
573
- navigate(1);
574
- break;
575
- case 'ArrowLeft':
576
- e.preventDefault();
577
- navigate(-1);
578
- break;
579
- case 'Enter':
580
- case 'Escape':
581
- e.preventDefault();
582
- returnToMain();
583
- break;
584
- case '1':
585
- e.preventDefault();
586
- changeTitleFont(-1);
587
- break;
588
- case '2':
589
- e.preventDefault();
590
- changeTitleFont(1);
591
- break;
592
- case '3':
593
- e.preventDefault();
594
- changeContentFont(-1);
595
- break;
596
- case '4':
597
- e.preventDefault();
598
- changeContentFont(1);
599
- break;
600
-
601
- case '`':
602
- e.preventDefault();
603
- if (currentUrl) window.electronAPI.openExternal(currentUrl);
604
- break;
605
- }
606
- });
607
-
608
- // Button wiring
609
- const prevBtn = el('prevBtn');
610
- if (prevBtn) prevBtn.addEventListener('click', () => navigate(-1));
611
- const nextBtn = el('nextBtn');
612
- if (nextBtn) nextBtn.addEventListener('click', () => navigate(1));
613
- const returnBtn = el('returnBtn');
614
- if (returnBtn) returnBtn.addEventListener('click', returnToMain);
615
- const browserBtn = el('browserBtn');
616
- if (browserBtn) browserBtn.addEventListener('click', () => {
617
- if (currentUrl) window.electronAPI.openExternal(currentUrl);
618
- });
619
-
620
- // Bootstrap
621
- async function init() {
622
- const data = await window.electronAPI.getData();
623
- newsItems = data.newsItems || [];
624
- const startIdx = data.currentIndex || 0;
625
- if (data.fontSize) {
626
- document.body.style.fontSize = data.fontSize + 'px';
627
- }
628
- if (data.titleFontSize) {
629
- titleFontSize = data.titleFontSize;
630
- const tf = el('titleFontVal');
631
- if (tf) tf.textContent = titleFontSize + 'px';
632
- }
633
- if (data.contentFontSize) {
634
- contentFontSize = data.contentFontSize;
635
- const cf = el('contentFontVal');
636
- if (cf) cf.textContent = contentFontSize + 'px';
637
- }
638
- renderArticle(startIdx);
639
- }
640
-
641
- if (document.readyState === 'loading') {
642
- document.addEventListener('DOMContentLoaded', init);
643
- } else {
644
- init();
645
- }
646
- </script>
647
- </body>
648
- </html>
649
-