clapp-pm 1.0.44__py3-none-any.whl → 1.0.46__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.
- {clapp_pm-1.0.44.data → clapp_pm-1.0.46.data}/data/version.json +1 -1
- {clapp_pm-1.0.44.dist-info → clapp_pm-1.0.46.dist-info}/METADATA +1 -1
- {clapp_pm-1.0.44.dist-info → clapp_pm-1.0.46.dist-info}/RECORD +13 -29
- manifest_schema.py +1 -1
- manifest_validator.py +1 -1
- package_runner.py +1 -0
- packages/luaozgur-moba/README.md +159 -0
- packages/luaozgur-moba/manifest.json +8 -0
- version.py +1 -1
- packages/pycloudos/README.md +0 -279
- packages/pycloudos/core/appmon.py +0 -0
- packages/pycloudos/main.py +0 -193
- packages/pycloudos/manifest.json +0 -15
- packages/pycloudos/rain/__init__.py +0 -7
- packages/pycloudos/rain/contextmenu.py +0 -1370
- packages/pycloudos/rain/desktop.py +0 -556
- packages/pycloudos/rain/dock.py +0 -722
- packages/pycloudos/rain/flet_html_widgets.py +0 -1448
- packages/pycloudos/rain/theme.py +0 -930
- packages/pycloudos/rain/topbar.py +0 -1421
- packages/pycloudos/rain/ui.py +0 -381
- packages/pycloudos/rain/wallpaper.py +0 -830
- packages/pycloudos/rain/widgets.py +0 -688
- packages/pycloudos/rain/windowmanager.py +0 -605
- packages/pycloudos/requirements-dev.txt +0 -43
- packages/pycloudos/requirements.txt +0 -43
- packages/pycloudos/setup_deps.py +0 -422
- {clapp_pm-1.0.44.dist-info → clapp_pm-1.0.46.dist-info}/WHEEL +0 -0
- {clapp_pm-1.0.44.dist-info → clapp_pm-1.0.46.dist-info}/entry_points.txt +0 -0
- {clapp_pm-1.0.44.dist-info → clapp_pm-1.0.46.dist-info}/licenses/LICENSE +0 -0
- {clapp_pm-1.0.44.dist-info → clapp_pm-1.0.46.dist-info}/top_level.txt +0 -0
@@ -1,1448 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Rain Flet HTML Widgets - Flet Widget'larını HTML olarak PyQt6'da göster
|
3
|
-
Flet widget'larını HTML'e çevirip QWebEngineView'de gösterir
|
4
|
-
"""
|
5
|
-
|
6
|
-
import logging
|
7
|
-
import tempfile
|
8
|
-
import os
|
9
|
-
import json
|
10
|
-
from pathlib import Path
|
11
|
-
from typing import Optional
|
12
|
-
from datetime import datetime
|
13
|
-
|
14
|
-
try:
|
15
|
-
from PyQt6.QtWidgets import QWidget, QVBoxLayout, QApplication
|
16
|
-
from PyQt6.QtCore import Qt, QUrl, QTimer, pyqtSignal
|
17
|
-
from PyQt6.QtWebEngineWidgets import QWebEngineView
|
18
|
-
from PyQt6.QtWebEngineCore import QWebEngineSettings
|
19
|
-
from PyQt6.QtGui import QMouseEvent
|
20
|
-
PYQT_AVAILABLE = True
|
21
|
-
except ImportError:
|
22
|
-
PYQT_AVAILABLE = False
|
23
|
-
|
24
|
-
class FletHTMLWidget(QWidget):
|
25
|
-
"""Flet widget'ını HTML olarak gösteren base sınıf"""
|
26
|
-
|
27
|
-
# Widget kapanma sinyali
|
28
|
-
widget_closed = pyqtSignal()
|
29
|
-
|
30
|
-
def __init__(self, widget_name: str, width: int = 400, height: int = 500):
|
31
|
-
super().__init__()
|
32
|
-
self.widget_name = widget_name
|
33
|
-
self.logger = logging.getLogger(f"FletHTML_{widget_name}")
|
34
|
-
|
35
|
-
if not PYQT_AVAILABLE:
|
36
|
-
self.logger.error("PyQt6 not available")
|
37
|
-
return
|
38
|
-
|
39
|
-
self.setFixedSize(width, height)
|
40
|
-
self.setWindowFlags(Qt.WindowType.FramelessWindowHint | Qt.WindowType.WindowStaysOnTopHint)
|
41
|
-
self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
|
42
|
-
|
43
|
-
# Global mouse event filter'ı kur
|
44
|
-
self.installEventFilter(self)
|
45
|
-
|
46
|
-
self.setup_ui()
|
47
|
-
|
48
|
-
def setup_ui(self):
|
49
|
-
"""UI kurulumu"""
|
50
|
-
layout = QVBoxLayout(self)
|
51
|
-
layout.setContentsMargins(0, 0, 0, 0)
|
52
|
-
|
53
|
-
# Web view oluştur
|
54
|
-
self.web_view = QWebEngineView()
|
55
|
-
self.web_view.setStyleSheet("""
|
56
|
-
QWebEngineView {
|
57
|
-
background: transparent;
|
58
|
-
border: none;
|
59
|
-
}
|
60
|
-
""")
|
61
|
-
|
62
|
-
# Web engine ayarları
|
63
|
-
settings = self.web_view.settings()
|
64
|
-
settings.setAttribute(QWebEngineSettings.WebAttribute.LocalContentCanAccessRemoteUrls, True)
|
65
|
-
settings.setAttribute(QWebEngineSettings.WebAttribute.LocalContentCanAccessFileUrls, True)
|
66
|
-
|
67
|
-
layout.addWidget(self.web_view)
|
68
|
-
|
69
|
-
def load_html_content(self, html_content: str):
|
70
|
-
"""HTML içeriğini yükle"""
|
71
|
-
try:
|
72
|
-
# Geçici HTML dosyası oluştur
|
73
|
-
temp_file = tempfile.NamedTemporaryFile(mode='w', suffix='.html', delete=False, encoding='utf-8')
|
74
|
-
temp_file.write(html_content)
|
75
|
-
temp_file.close()
|
76
|
-
|
77
|
-
# HTML dosyasını yükle
|
78
|
-
file_url = QUrl.fromLocalFile(temp_file.name)
|
79
|
-
self.web_view.load(file_url)
|
80
|
-
|
81
|
-
self.logger.info(f"Loaded HTML content for {self.widget_name}")
|
82
|
-
|
83
|
-
except Exception as e:
|
84
|
-
self.logger.error(f"Failed to load HTML content: {e}")
|
85
|
-
|
86
|
-
def showEvent(self, event):
|
87
|
-
"""Widget gösterildiğinde global mouse event'leri dinlemeye başla"""
|
88
|
-
super().showEvent(event)
|
89
|
-
if QApplication.instance():
|
90
|
-
QApplication.instance().installEventFilter(self)
|
91
|
-
|
92
|
-
def hideEvent(self, event):
|
93
|
-
"""Widget gizlendiğinde global mouse event'leri dinlemeyi bırak"""
|
94
|
-
super().hideEvent(event)
|
95
|
-
if QApplication.instance():
|
96
|
-
QApplication.instance().removeEventFilter(self)
|
97
|
-
|
98
|
-
def eventFilter(self, obj, event):
|
99
|
-
"""Global event filter - dış tıklamaları yakala"""
|
100
|
-
if event.type() == event.Type.MouseButtonPress:
|
101
|
-
# Eğer tıklama bu widget'ın dışındaysa kapat
|
102
|
-
if not self.geometry().contains(event.globalPosition().toPoint()):
|
103
|
-
self.close_widget()
|
104
|
-
return True
|
105
|
-
return super().eventFilter(obj, event)
|
106
|
-
|
107
|
-
def close_widget(self):
|
108
|
-
"""Widget'ı kapat"""
|
109
|
-
self.widget_closed.emit()
|
110
|
-
self.hide()
|
111
|
-
self.logger.info(f"{self.widget_name} widget closed by outside click")
|
112
|
-
|
113
|
-
class HTMLNotificationWidget(FletHTMLWidget):
|
114
|
-
"""HTML bildirim widget'ı"""
|
115
|
-
|
116
|
-
def __init__(self):
|
117
|
-
super().__init__("Notification", 380, 450)
|
118
|
-
self.notifications_data = self.get_notifications_data()
|
119
|
-
|
120
|
-
def get_notifications_data(self):
|
121
|
-
"""Bildirim verilerini al"""
|
122
|
-
return [
|
123
|
-
{
|
124
|
-
"title": "Sistem Bildirimi",
|
125
|
-
"message": "PyCloud OS başarıyla başlatıldı ve tüm servisler çalışıyor",
|
126
|
-
"time": "2 dakika önce",
|
127
|
-
"icon": "📢"
|
128
|
-
},
|
129
|
-
{
|
130
|
-
"title": "Uygulama Güncellemesi",
|
131
|
-
"message": "Cloud Files v2.1.0 güncellendi",
|
132
|
-
"time": "1 saat önce",
|
133
|
-
"icon": "🔄"
|
134
|
-
},
|
135
|
-
{
|
136
|
-
"title": "Güvenlik Uyarısı",
|
137
|
-
"message": "Yeni giriş denemesi tespit edildi",
|
138
|
-
"time": "3 saat önce",
|
139
|
-
"icon": "⚠️"
|
140
|
-
},
|
141
|
-
{
|
142
|
-
"title": "Yedekleme Tamamlandı",
|
143
|
-
"message": "Haftalık sistem yedeklemesi başarıyla tamamlandı",
|
144
|
-
"time": "1 gün önce",
|
145
|
-
"icon": "✅"
|
146
|
-
}
|
147
|
-
]
|
148
|
-
|
149
|
-
def show_widget(self):
|
150
|
-
"""Widget'ı göster"""
|
151
|
-
html_content = self.generate_notification_html()
|
152
|
-
self.load_html_content(html_content)
|
153
|
-
self.show()
|
154
|
-
|
155
|
-
def generate_notification_html(self):
|
156
|
-
"""Bildirim HTML'ini oluştur"""
|
157
|
-
notifications_html = ""
|
158
|
-
|
159
|
-
for notif in self.notifications_data:
|
160
|
-
notifications_html += f"""
|
161
|
-
<div class="notification-item">
|
162
|
-
<div class="notification-icon">{notif['icon']}</div>
|
163
|
-
<div class="notification-content">
|
164
|
-
<div class="notification-title">{notif['title']}</div>
|
165
|
-
<div class="notification-message">{notif['message']}</div>
|
166
|
-
</div>
|
167
|
-
<div class="notification-time">{notif['time']}</div>
|
168
|
-
</div>
|
169
|
-
"""
|
170
|
-
|
171
|
-
return f"""
|
172
|
-
<!DOCTYPE html>
|
173
|
-
<html>
|
174
|
-
<head>
|
175
|
-
<meta charset="UTF-8">
|
176
|
-
<title>Bildirimler</title>
|
177
|
-
<style>
|
178
|
-
body {{
|
179
|
-
margin: 0;
|
180
|
-
padding: 20px;
|
181
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
182
|
-
background: rgba(30, 30, 30, 0.98);
|
183
|
-
color: white;
|
184
|
-
border-radius: 18px;
|
185
|
-
border: 2px solid rgba(80, 80, 80, 0.9);
|
186
|
-
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.3);
|
187
|
-
width: 340px;
|
188
|
-
height: 410px;
|
189
|
-
overflow: hidden;
|
190
|
-
}}
|
191
|
-
|
192
|
-
.header {{
|
193
|
-
display: flex;
|
194
|
-
justify-content: space-between;
|
195
|
-
align-items: center;
|
196
|
-
margin-bottom: 16px;
|
197
|
-
}}
|
198
|
-
|
199
|
-
.title {{
|
200
|
-
font-size: 20px;
|
201
|
-
font-weight: bold;
|
202
|
-
color: white;
|
203
|
-
}}
|
204
|
-
|
205
|
-
.count {{
|
206
|
-
background: rgba(0, 120, 255, 0.8);
|
207
|
-
color: white;
|
208
|
-
padding: 4px 8px;
|
209
|
-
border-radius: 10px;
|
210
|
-
font-size: 12px;
|
211
|
-
font-weight: bold;
|
212
|
-
}}
|
213
|
-
|
214
|
-
.notifications-list {{
|
215
|
-
max-height: 280px;
|
216
|
-
overflow-y: auto;
|
217
|
-
margin-bottom: 16px;
|
218
|
-
}}
|
219
|
-
|
220
|
-
.notification-item {{
|
221
|
-
background: rgba(45, 45, 45, 0.9);
|
222
|
-
border: 1px solid rgba(100, 100, 100, 0.5);
|
223
|
-
border-radius: 12px;
|
224
|
-
padding: 12px;
|
225
|
-
margin-bottom: 8px;
|
226
|
-
display: flex;
|
227
|
-
align-items: flex-start;
|
228
|
-
gap: 12px;
|
229
|
-
transition: background 0.2s;
|
230
|
-
}}
|
231
|
-
|
232
|
-
.notification-item:hover {{
|
233
|
-
background: rgba(55, 55, 55, 0.9);
|
234
|
-
}}
|
235
|
-
|
236
|
-
.notification-icon {{
|
237
|
-
background: rgba(0, 120, 255, 0.3);
|
238
|
-
border-radius: 20px;
|
239
|
-
width: 40px;
|
240
|
-
height: 40px;
|
241
|
-
display: flex;
|
242
|
-
align-items: center;
|
243
|
-
justify-content: center;
|
244
|
-
font-size: 20px;
|
245
|
-
flex-shrink: 0;
|
246
|
-
}}
|
247
|
-
|
248
|
-
.notification-content {{
|
249
|
-
flex: 1;
|
250
|
-
min-width: 0;
|
251
|
-
}}
|
252
|
-
|
253
|
-
.notification-title {{
|
254
|
-
font-size: 14px;
|
255
|
-
font-weight: bold;
|
256
|
-
color: white;
|
257
|
-
margin-bottom: 4px;
|
258
|
-
white-space: nowrap;
|
259
|
-
overflow: hidden;
|
260
|
-
text-overflow: ellipsis;
|
261
|
-
}}
|
262
|
-
|
263
|
-
.notification-message {{
|
264
|
-
font-size: 12px;
|
265
|
-
color: #cccccc;
|
266
|
-
line-height: 1.4;
|
267
|
-
display: -webkit-box;
|
268
|
-
-webkit-line-clamp: 2;
|
269
|
-
-webkit-box-orient: vertical;
|
270
|
-
overflow: hidden;
|
271
|
-
}}
|
272
|
-
|
273
|
-
.notification-time {{
|
274
|
-
font-size: 10px;
|
275
|
-
color: #888888;
|
276
|
-
flex-shrink: 0;
|
277
|
-
text-align: right;
|
278
|
-
}}
|
279
|
-
|
280
|
-
.buttons {{
|
281
|
-
display: flex;
|
282
|
-
gap: 12px;
|
283
|
-
}}
|
284
|
-
|
285
|
-
.button {{
|
286
|
-
background: rgba(60, 60, 60, 0.8);
|
287
|
-
border: 1px solid rgba(120, 120, 120, 0.6);
|
288
|
-
border-radius: 10px;
|
289
|
-
padding: 10px 16px;
|
290
|
-
color: white;
|
291
|
-
font-weight: 600;
|
292
|
-
font-size: 13px;
|
293
|
-
cursor: pointer;
|
294
|
-
transition: background 0.2s;
|
295
|
-
text-decoration: none;
|
296
|
-
display: inline-block;
|
297
|
-
}}
|
298
|
-
|
299
|
-
.button:hover {{
|
300
|
-
background: rgba(80, 80, 80, 0.9);
|
301
|
-
}}
|
302
|
-
|
303
|
-
.button.clear {{
|
304
|
-
background: rgba(200, 60, 60, 0.8);
|
305
|
-
}}
|
306
|
-
|
307
|
-
.button.clear:hover {{
|
308
|
-
background: rgba(220, 80, 80, 0.9);
|
309
|
-
}}
|
310
|
-
|
311
|
-
.button.settings {{
|
312
|
-
background: rgba(0, 120, 255, 0.8);
|
313
|
-
}}
|
314
|
-
|
315
|
-
.button.settings:hover {{
|
316
|
-
background: rgba(0, 140, 255, 0.9);
|
317
|
-
}}
|
318
|
-
|
319
|
-
/* Scrollbar styling */
|
320
|
-
.notifications-list::-webkit-scrollbar {{
|
321
|
-
width: 8px;
|
322
|
-
}}
|
323
|
-
|
324
|
-
.notifications-list::-webkit-scrollbar-track {{
|
325
|
-
background: rgba(60, 60, 60, 0.5);
|
326
|
-
border-radius: 4px;
|
327
|
-
}}
|
328
|
-
|
329
|
-
.notifications-list::-webkit-scrollbar-thumb {{
|
330
|
-
background: rgba(120, 120, 120, 0.8);
|
331
|
-
border-radius: 4px;
|
332
|
-
}}
|
333
|
-
|
334
|
-
.notifications-list::-webkit-scrollbar-thumb:hover {{
|
335
|
-
background: rgba(140, 140, 140, 0.9);
|
336
|
-
}}
|
337
|
-
</style>
|
338
|
-
</head>
|
339
|
-
<body>
|
340
|
-
<div class="header">
|
341
|
-
<div class="title">🔔 Bildirimler</div>
|
342
|
-
<div class="count">{len(self.notifications_data)}</div>
|
343
|
-
</div>
|
344
|
-
|
345
|
-
<div class="notifications-list">
|
346
|
-
{notifications_html}
|
347
|
-
</div>
|
348
|
-
|
349
|
-
<div class="buttons">
|
350
|
-
<div class="button clear" onclick="clearNotifications()">🗑️ Temizle</div>
|
351
|
-
<div class="button settings" onclick="openSettings()">⚙️ Ayarlar</div>
|
352
|
-
</div>
|
353
|
-
|
354
|
-
<script>
|
355
|
-
function clearNotifications() {{
|
356
|
-
alert('🗑️ Bildirimler temizlendi');
|
357
|
-
}}
|
358
|
-
|
359
|
-
function openSettings() {{
|
360
|
-
alert('⚙️ Bildirim ayarları açılıyor...');
|
361
|
-
}}
|
362
|
-
</script>
|
363
|
-
</body>
|
364
|
-
</html>
|
365
|
-
"""
|
366
|
-
|
367
|
-
class HTMLClockWidget(FletHTMLWidget):
|
368
|
-
"""HTML saat widget'ı"""
|
369
|
-
|
370
|
-
def __init__(self):
|
371
|
-
super().__init__("Clock", 330, 400)
|
372
|
-
|
373
|
-
def show_widget(self):
|
374
|
-
"""Widget'ı göster"""
|
375
|
-
html_content = self.generate_clock_html()
|
376
|
-
self.load_html_content(html_content)
|
377
|
-
self.show()
|
378
|
-
|
379
|
-
# Saati her saniye güncelle
|
380
|
-
self.timer = QTimer()
|
381
|
-
self.timer.timeout.connect(self.update_clock)
|
382
|
-
self.timer.start(1000)
|
383
|
-
|
384
|
-
def update_clock(self):
|
385
|
-
"""Saati güncelle"""
|
386
|
-
try:
|
387
|
-
# JavaScript ile saati güncelle
|
388
|
-
now = datetime.now()
|
389
|
-
time_str = now.strftime("%H:%M:%S")
|
390
|
-
js_code = f"document.getElementById('current-time').textContent = '{time_str}';"
|
391
|
-
self.web_view.page().runJavaScript(js_code)
|
392
|
-
except Exception as e:
|
393
|
-
self.logger.error(f"Failed to update clock: {e}")
|
394
|
-
|
395
|
-
def generate_clock_html(self):
|
396
|
-
"""Saat HTML'ini oluştur"""
|
397
|
-
now = datetime.now()
|
398
|
-
|
399
|
-
return f"""
|
400
|
-
<!DOCTYPE html>
|
401
|
-
<html>
|
402
|
-
<head>
|
403
|
-
<meta charset="UTF-8">
|
404
|
-
<title>Saat & Takvim</title>
|
405
|
-
<style>
|
406
|
-
body {{
|
407
|
-
margin: 0;
|
408
|
-
padding: 20px;
|
409
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
410
|
-
background: rgba(30, 30, 30, 0.98);
|
411
|
-
color: white;
|
412
|
-
border-radius: 18px;
|
413
|
-
border: 2px solid rgba(80, 80, 80, 0.9);
|
414
|
-
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.3);
|
415
|
-
width: 290px;
|
416
|
-
height: 360px;
|
417
|
-
overflow: hidden;
|
418
|
-
}}
|
419
|
-
|
420
|
-
.title {{
|
421
|
-
font-size: 20px;
|
422
|
-
font-weight: bold;
|
423
|
-
color: white;
|
424
|
-
text-align: center;
|
425
|
-
margin-bottom: 16px;
|
426
|
-
}}
|
427
|
-
|
428
|
-
.card {{
|
429
|
-
background: rgba(45, 45, 45, 0.9);
|
430
|
-
border: 1px solid rgba(100, 100, 100, 0.5);
|
431
|
-
border-radius: 16px;
|
432
|
-
padding: 16px;
|
433
|
-
margin-bottom: 16px;
|
434
|
-
}}
|
435
|
-
|
436
|
-
.time-card {{
|
437
|
-
text-align: center;
|
438
|
-
}}
|
439
|
-
|
440
|
-
.big-time {{
|
441
|
-
font-size: 36px;
|
442
|
-
font-weight: bold;
|
443
|
-
color: white;
|
444
|
-
margin-bottom: 8px;
|
445
|
-
}}
|
446
|
-
|
447
|
-
.date {{
|
448
|
-
font-size: 16px;
|
449
|
-
color: #cccccc;
|
450
|
-
}}
|
451
|
-
|
452
|
-
.calendar-title {{
|
453
|
-
font-size: 16px;
|
454
|
-
font-weight: bold;
|
455
|
-
color: white;
|
456
|
-
margin-bottom: 12px;
|
457
|
-
}}
|
458
|
-
|
459
|
-
.month-year {{
|
460
|
-
font-size: 15px;
|
461
|
-
font-weight: bold;
|
462
|
-
text-align: center;
|
463
|
-
color: white;
|
464
|
-
margin-bottom: 12px;
|
465
|
-
}}
|
466
|
-
|
467
|
-
.days-header {{
|
468
|
-
display: flex;
|
469
|
-
justify-content: space-around;
|
470
|
-
background: rgba(60, 60, 60, 0.6);
|
471
|
-
border-radius: 8px;
|
472
|
-
padding: 8px;
|
473
|
-
margin-bottom: 12px;
|
474
|
-
}}
|
475
|
-
|
476
|
-
.day-name {{
|
477
|
-
font-size: 11px;
|
478
|
-
color: #bbbbbb;
|
479
|
-
text-align: center;
|
480
|
-
flex: 1;
|
481
|
-
}}
|
482
|
-
|
483
|
-
.today-highlight {{
|
484
|
-
background: rgba(0, 200, 100, 0.3);
|
485
|
-
border: 2px solid rgba(0, 200, 100, 0.6);
|
486
|
-
border-radius: 10px;
|
487
|
-
padding: 12px;
|
488
|
-
display: flex;
|
489
|
-
align-items: center;
|
490
|
-
gap: 12px;
|
491
|
-
}}
|
492
|
-
|
493
|
-
.today-icon {{
|
494
|
-
font-size: 24px;
|
495
|
-
color: #00ff88;
|
496
|
-
}}
|
497
|
-
|
498
|
-
.today-text {{
|
499
|
-
font-size: 14px;
|
500
|
-
color: white;
|
501
|
-
font-weight: bold;
|
502
|
-
}}
|
503
|
-
|
504
|
-
.timezone-card {{
|
505
|
-
display: flex;
|
506
|
-
align-items: center;
|
507
|
-
gap: 12px;
|
508
|
-
}}
|
509
|
-
|
510
|
-
.timezone-icon {{
|
511
|
-
font-size: 20px;
|
512
|
-
color: white;
|
513
|
-
}}
|
514
|
-
|
515
|
-
.timezone-text {{
|
516
|
-
font-size: 14px;
|
517
|
-
color: #cccccc;
|
518
|
-
}}
|
519
|
-
</style>
|
520
|
-
</head>
|
521
|
-
<body>
|
522
|
-
<div class="title">🕐 Saat & Takvim</div>
|
523
|
-
|
524
|
-
<div class="card time-card">
|
525
|
-
<div class="big-time" id="current-time">{now.strftime("%H:%M:%S")}</div>
|
526
|
-
<div class="date">{now.strftime("%A, %d %B %Y")}</div>
|
527
|
-
</div>
|
528
|
-
|
529
|
-
<div class="card">
|
530
|
-
<div class="calendar-title">📅 Bu Ay</div>
|
531
|
-
<div class="month-year">{now.strftime("%B %Y")}</div>
|
532
|
-
|
533
|
-
<div class="days-header">
|
534
|
-
<div class="day-name">Pzt</div>
|
535
|
-
<div class="day-name">Sal</div>
|
536
|
-
<div class="day-name">Çar</div>
|
537
|
-
<div class="day-name">Per</div>
|
538
|
-
<div class="day-name">Cum</div>
|
539
|
-
<div class="day-name">Cmt</div>
|
540
|
-
<div class="day-name">Paz</div>
|
541
|
-
</div>
|
542
|
-
|
543
|
-
<div class="today-highlight">
|
544
|
-
<div class="today-icon">📅</div>
|
545
|
-
<div class="today-text">Bugün: {now.day} {now.strftime('%B')}</div>
|
546
|
-
</div>
|
547
|
-
</div>
|
548
|
-
|
549
|
-
<div class="card">
|
550
|
-
<div class="timezone-card">
|
551
|
-
<div class="timezone-icon">🌍</div>
|
552
|
-
<div class="timezone-text">Türkiye Saati (UTC+3)</div>
|
553
|
-
</div>
|
554
|
-
</div>
|
555
|
-
</body>
|
556
|
-
</html>
|
557
|
-
"""
|
558
|
-
|
559
|
-
class HTMLControlCenterWidget(FletHTMLWidget):
|
560
|
-
"""HTML denetim merkezi widget'ı"""
|
561
|
-
|
562
|
-
def __init__(self):
|
563
|
-
super().__init__("ControlCenter", 360, 520)
|
564
|
-
|
565
|
-
def show_widget(self):
|
566
|
-
"""Widget'ı göster"""
|
567
|
-
html_content = self.generate_control_center_html()
|
568
|
-
self.load_html_content(html_content)
|
569
|
-
self.show()
|
570
|
-
|
571
|
-
def generate_control_center_html(self):
|
572
|
-
"""Denetim merkezi HTML'ini oluştur - ListView yapısı"""
|
573
|
-
return """
|
574
|
-
<!DOCTYPE html>
|
575
|
-
<html>
|
576
|
-
<head>
|
577
|
-
<meta charset="UTF-8">
|
578
|
-
<title>Denetim Merkezi</title>
|
579
|
-
<style>
|
580
|
-
body {
|
581
|
-
margin: 0;
|
582
|
-
padding: 20px;
|
583
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
584
|
-
background: rgba(30, 30, 30, 0.98);
|
585
|
-
color: white;
|
586
|
-
border-radius: 18px;
|
587
|
-
border: 2px solid rgba(80, 80, 80, 0.9);
|
588
|
-
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.3);
|
589
|
-
width: 320px;
|
590
|
-
height: 480px;
|
591
|
-
overflow: hidden;
|
592
|
-
display: flex;
|
593
|
-
flex-direction: column;
|
594
|
-
}
|
595
|
-
|
596
|
-
.title {
|
597
|
-
font-size: 20px;
|
598
|
-
font-weight: bold;
|
599
|
-
color: white;
|
600
|
-
text-align: center;
|
601
|
-
margin-bottom: 16px;
|
602
|
-
flex-shrink: 0;
|
603
|
-
}
|
604
|
-
|
605
|
-
.content {
|
606
|
-
flex: 1;
|
607
|
-
overflow-y: auto;
|
608
|
-
padding-right: 5px;
|
609
|
-
}
|
610
|
-
|
611
|
-
.content::-webkit-scrollbar {
|
612
|
-
width: 6px;
|
613
|
-
}
|
614
|
-
|
615
|
-
.content::-webkit-scrollbar-track {
|
616
|
-
background: rgba(60, 60, 60, 0.3);
|
617
|
-
border-radius: 3px;
|
618
|
-
}
|
619
|
-
|
620
|
-
.content::-webkit-scrollbar-thumb {
|
621
|
-
background: rgba(120, 120, 120, 0.6);
|
622
|
-
border-radius: 3px;
|
623
|
-
}
|
624
|
-
|
625
|
-
.content::-webkit-scrollbar-thumb:hover {
|
626
|
-
background: rgba(140, 140, 140, 0.8);
|
627
|
-
}
|
628
|
-
|
629
|
-
.section-title {
|
630
|
-
font-size: 16px;
|
631
|
-
font-weight: bold;
|
632
|
-
color: rgba(255, 255, 255, 0.8);
|
633
|
-
margin: 16px 0 12px 0;
|
634
|
-
padding-left: 8px;
|
635
|
-
border-left: 3px solid rgba(0, 120, 255, 0.8);
|
636
|
-
}
|
637
|
-
|
638
|
-
.list-item {
|
639
|
-
background: rgba(45, 45, 45, 0.9);
|
640
|
-
border: 1px solid rgba(100, 100, 100, 0.5);
|
641
|
-
border-radius: 12px;
|
642
|
-
padding: 12px 16px;
|
643
|
-
margin-bottom: 8px;
|
644
|
-
display: flex;
|
645
|
-
align-items: center;
|
646
|
-
justify-content: space-between;
|
647
|
-
cursor: pointer;
|
648
|
-
transition: all 0.2s;
|
649
|
-
}
|
650
|
-
|
651
|
-
.list-item:hover {
|
652
|
-
background: rgba(55, 55, 55, 0.9);
|
653
|
-
transform: translateX(2px);
|
654
|
-
}
|
655
|
-
|
656
|
-
.item-left {
|
657
|
-
display: flex;
|
658
|
-
align-items: center;
|
659
|
-
gap: 12px;
|
660
|
-
}
|
661
|
-
|
662
|
-
.item-icon {
|
663
|
-
font-size: 20px;
|
664
|
-
width: 24px;
|
665
|
-
text-align: center;
|
666
|
-
}
|
667
|
-
|
668
|
-
.item-info {
|
669
|
-
display: flex;
|
670
|
-
flex-direction: column;
|
671
|
-
}
|
672
|
-
|
673
|
-
.item-title {
|
674
|
-
font-size: 14px;
|
675
|
-
font-weight: bold;
|
676
|
-
color: white;
|
677
|
-
margin-bottom: 2px;
|
678
|
-
}
|
679
|
-
|
680
|
-
.item-subtitle {
|
681
|
-
font-size: 12px;
|
682
|
-
color: rgba(255, 255, 255, 0.7);
|
683
|
-
}
|
684
|
-
|
685
|
-
.item-right {
|
686
|
-
display: flex;
|
687
|
-
align-items: center;
|
688
|
-
gap: 8px;
|
689
|
-
}
|
690
|
-
|
691
|
-
.toggle-switch {
|
692
|
-
width: 44px;
|
693
|
-
height: 24px;
|
694
|
-
background: rgba(80, 80, 80, 0.8);
|
695
|
-
border-radius: 12px;
|
696
|
-
position: relative;
|
697
|
-
cursor: pointer;
|
698
|
-
transition: background 0.2s;
|
699
|
-
}
|
700
|
-
|
701
|
-
.toggle-switch.on {
|
702
|
-
background: rgba(0, 200, 100, 0.8);
|
703
|
-
}
|
704
|
-
|
705
|
-
.toggle-switch::after {
|
706
|
-
content: '';
|
707
|
-
position: absolute;
|
708
|
-
width: 20px;
|
709
|
-
height: 20px;
|
710
|
-
background: white;
|
711
|
-
border-radius: 10px;
|
712
|
-
top: 2px;
|
713
|
-
left: 2px;
|
714
|
-
transition: transform 0.2s;
|
715
|
-
}
|
716
|
-
|
717
|
-
.toggle-switch.on::after {
|
718
|
-
transform: translateX(20px);
|
719
|
-
}
|
720
|
-
|
721
|
-
.slider-item {
|
722
|
-
background: rgba(45, 45, 45, 0.9);
|
723
|
-
border: 1px solid rgba(100, 100, 100, 0.5);
|
724
|
-
border-radius: 12px;
|
725
|
-
padding: 16px;
|
726
|
-
margin-bottom: 8px;
|
727
|
-
}
|
728
|
-
|
729
|
-
.slider-header {
|
730
|
-
display: flex;
|
731
|
-
justify-content: space-between;
|
732
|
-
align-items: center;
|
733
|
-
margin-bottom: 12px;
|
734
|
-
}
|
735
|
-
|
736
|
-
.slider-title {
|
737
|
-
font-size: 14px;
|
738
|
-
font-weight: bold;
|
739
|
-
color: white;
|
740
|
-
display: flex;
|
741
|
-
align-items: center;
|
742
|
-
gap: 8px;
|
743
|
-
}
|
744
|
-
|
745
|
-
.slider-value {
|
746
|
-
font-size: 14px;
|
747
|
-
color: white;
|
748
|
-
font-weight: bold;
|
749
|
-
min-width: 40px;
|
750
|
-
text-align: right;
|
751
|
-
}
|
752
|
-
|
753
|
-
.slider {
|
754
|
-
width: 100%;
|
755
|
-
height: 8px;
|
756
|
-
border-radius: 4px;
|
757
|
-
background: rgba(80, 80, 80, 0.8);
|
758
|
-
outline: none;
|
759
|
-
cursor: pointer;
|
760
|
-
appearance: none;
|
761
|
-
}
|
762
|
-
|
763
|
-
.slider::-webkit-slider-thumb {
|
764
|
-
appearance: none;
|
765
|
-
width: 20px;
|
766
|
-
height: 20px;
|
767
|
-
border-radius: 10px;
|
768
|
-
background: white;
|
769
|
-
border: 2px solid rgba(0, 120, 255, 0.8);
|
770
|
-
cursor: pointer;
|
771
|
-
}
|
772
|
-
|
773
|
-
.system-item {
|
774
|
-
background: rgba(60, 60, 60, 0.8);
|
775
|
-
border: 1px solid rgba(120, 120, 120, 0.6);
|
776
|
-
}
|
777
|
-
|
778
|
-
.system-item.danger {
|
779
|
-
background: rgba(200, 60, 60, 0.8);
|
780
|
-
border: 1px solid rgba(200, 60, 60, 0.9);
|
781
|
-
}
|
782
|
-
|
783
|
-
.system-item:hover {
|
784
|
-
background: rgba(80, 80, 80, 0.9);
|
785
|
-
}
|
786
|
-
|
787
|
-
.system-item.danger:hover {
|
788
|
-
background: rgba(220, 80, 80, 0.9);
|
789
|
-
}
|
790
|
-
|
791
|
-
.status-badge {
|
792
|
-
background: rgba(0, 200, 100, 0.8);
|
793
|
-
color: white;
|
794
|
-
padding: 2px 8px;
|
795
|
-
border-radius: 10px;
|
796
|
-
font-size: 11px;
|
797
|
-
font-weight: bold;
|
798
|
-
}
|
799
|
-
|
800
|
-
.status-badge.off {
|
801
|
-
background: rgba(120, 120, 120, 0.8);
|
802
|
-
}
|
803
|
-
</style>
|
804
|
-
</head>
|
805
|
-
<body>
|
806
|
-
<div class="title">⚙️ Denetim Merkezi</div>
|
807
|
-
|
808
|
-
<div class="content">
|
809
|
-
<div class="section-title">🔧 Hızlı Ayarlar</div>
|
810
|
-
|
811
|
-
<div class="list-item" onclick="toggleWifi()">
|
812
|
-
<div class="item-left">
|
813
|
-
<div class="item-icon">📶</div>
|
814
|
-
<div class="item-info">
|
815
|
-
<div class="item-title">WiFi</div>
|
816
|
-
<div class="item-subtitle">Bağlı: PyCloud-Network</div>
|
817
|
-
</div>
|
818
|
-
</div>
|
819
|
-
<div class="item-right">
|
820
|
-
<div class="toggle-switch on" id="wifi-toggle"></div>
|
821
|
-
</div>
|
822
|
-
</div>
|
823
|
-
|
824
|
-
<div class="list-item" onclick="toggleBluetooth()">
|
825
|
-
<div class="item-left">
|
826
|
-
<div class="item-icon">🔵</div>
|
827
|
-
<div class="item-info">
|
828
|
-
<div class="item-title">Bluetooth</div>
|
829
|
-
<div class="item-subtitle">Kapalı</div>
|
830
|
-
</div>
|
831
|
-
</div>
|
832
|
-
<div class="item-right">
|
833
|
-
<div class="toggle-switch" id="bluetooth-toggle"></div>
|
834
|
-
</div>
|
835
|
-
</div>
|
836
|
-
|
837
|
-
<div class="list-item" onclick="toggleDarkMode()">
|
838
|
-
<div class="item-left">
|
839
|
-
<div class="item-icon">🌙</div>
|
840
|
-
<div class="item-info">
|
841
|
-
<div class="item-title">Gece Modu</div>
|
842
|
-
<div class="item-subtitle">Koyu tema aktif</div>
|
843
|
-
</div>
|
844
|
-
</div>
|
845
|
-
<div class="item-right">
|
846
|
-
<div class="toggle-switch on" id="darkmode-toggle"></div>
|
847
|
-
</div>
|
848
|
-
</div>
|
849
|
-
|
850
|
-
<div class="list-item" onclick="toggleSilent()">
|
851
|
-
<div class="item-left">
|
852
|
-
<div class="item-icon">🔕</div>
|
853
|
-
<div class="item-info">
|
854
|
-
<div class="item-title">Sessiz Mod</div>
|
855
|
-
<div class="item-subtitle">Bildirimler kapalı</div>
|
856
|
-
</div>
|
857
|
-
</div>
|
858
|
-
<div class="item-right">
|
859
|
-
<div class="toggle-switch" id="silent-toggle"></div>
|
860
|
-
</div>
|
861
|
-
</div>
|
862
|
-
|
863
|
-
<div class="section-title">🎚️ Ses & Görüntü</div>
|
864
|
-
|
865
|
-
<div class="slider-item">
|
866
|
-
<div class="slider-header">
|
867
|
-
<div class="slider-title">
|
868
|
-
<span>🔊</span>
|
869
|
-
<span>Ses Seviyesi</span>
|
870
|
-
</div>
|
871
|
-
<div class="slider-value" id="volume-value">70%</div>
|
872
|
-
</div>
|
873
|
-
<input type="range" min="0" max="100" value="70" class="slider" id="volume-slider" oninput="updateVolume(this.value)">
|
874
|
-
</div>
|
875
|
-
|
876
|
-
<div class="slider-item">
|
877
|
-
<div class="slider-header">
|
878
|
-
<div class="slider-title">
|
879
|
-
<span>☀️</span>
|
880
|
-
<span>Parlaklık</span>
|
881
|
-
</div>
|
882
|
-
<div class="slider-value" id="brightness-value">80%</div>
|
883
|
-
</div>
|
884
|
-
<input type="range" min="0" max="100" value="80" class="slider" id="brightness-slider" oninput="updateBrightness(this.value)">
|
885
|
-
</div>
|
886
|
-
|
887
|
-
<div class="section-title">⚙️ Sistem</div>
|
888
|
-
|
889
|
-
<div class="list-item system-item" onclick="openSettings()">
|
890
|
-
<div class="item-left">
|
891
|
-
<div class="item-icon">⚙️</div>
|
892
|
-
<div class="item-info">
|
893
|
-
<div class="item-title">Sistem Ayarları</div>
|
894
|
-
<div class="item-subtitle">Tüm ayarları yönet</div>
|
895
|
-
</div>
|
896
|
-
</div>
|
897
|
-
<div class="item-right">
|
898
|
-
<div style="color: rgba(255, 255, 255, 0.5);">›</div>
|
899
|
-
</div>
|
900
|
-
</div>
|
901
|
-
|
902
|
-
<div class="list-item system-item" onclick="openTaskManager()">
|
903
|
-
<div class="item-left">
|
904
|
-
<div class="item-icon">📊</div>
|
905
|
-
<div class="item-info">
|
906
|
-
<div class="item-title">Görev Yöneticisi</div>
|
907
|
-
<div class="item-subtitle">CPU: 23% | RAM: 45%</div>
|
908
|
-
</div>
|
909
|
-
</div>
|
910
|
-
<div class="item-right">
|
911
|
-
<div style="color: rgba(255, 255, 255, 0.5);">›</div>
|
912
|
-
</div>
|
913
|
-
</div>
|
914
|
-
|
915
|
-
<div class="list-item system-item" onclick="restartSystem()">
|
916
|
-
<div class="item-left">
|
917
|
-
<div class="item-icon">🔄</div>
|
918
|
-
<div class="item-info">
|
919
|
-
<div class="item-title">Yeniden Başlat</div>
|
920
|
-
<div class="item-subtitle">Sistemi yeniden başlat</div>
|
921
|
-
</div>
|
922
|
-
</div>
|
923
|
-
<div class="item-right">
|
924
|
-
<div style="color: rgba(255, 255, 255, 0.5);">›</div>
|
925
|
-
</div>
|
926
|
-
</div>
|
927
|
-
|
928
|
-
<div class="list-item system-item danger" onclick="shutdownSystem()">
|
929
|
-
<div class="item-left">
|
930
|
-
<div class="item-icon">⏻</div>
|
931
|
-
<div class="item-info">
|
932
|
-
<div class="item-title">Sistemi Kapat</div>
|
933
|
-
<div class="item-subtitle">Güvenli kapatma</div>
|
934
|
-
</div>
|
935
|
-
</div>
|
936
|
-
<div class="item-right">
|
937
|
-
<div style="color: rgba(255, 255, 255, 0.8);">›</div>
|
938
|
-
</div>
|
939
|
-
</div>
|
940
|
-
</div>
|
941
|
-
|
942
|
-
<script>
|
943
|
-
function toggleWifi() {
|
944
|
-
const toggle = document.getElementById('wifi-toggle');
|
945
|
-
toggle.classList.toggle('on');
|
946
|
-
const subtitle = toggle.closest('.list-item').querySelector('.item-subtitle');
|
947
|
-
if (toggle.classList.contains('on')) {
|
948
|
-
subtitle.textContent = 'Bağlı: PyCloud-Network';
|
949
|
-
console.log('📶 WiFi açıldı');
|
950
|
-
} else {
|
951
|
-
subtitle.textContent = 'Kapalı';
|
952
|
-
console.log('📶 WiFi kapatıldı');
|
953
|
-
}
|
954
|
-
}
|
955
|
-
|
956
|
-
function toggleBluetooth() {
|
957
|
-
const toggle = document.getElementById('bluetooth-toggle');
|
958
|
-
toggle.classList.toggle('on');
|
959
|
-
const subtitle = toggle.closest('.list-item').querySelector('.item-subtitle');
|
960
|
-
if (toggle.classList.contains('on')) {
|
961
|
-
subtitle.textContent = 'Açık - Cihaz aranıyor';
|
962
|
-
console.log('🔵 Bluetooth açıldı');
|
963
|
-
} else {
|
964
|
-
subtitle.textContent = 'Kapalı';
|
965
|
-
console.log('🔵 Bluetooth kapatıldı');
|
966
|
-
}
|
967
|
-
}
|
968
|
-
|
969
|
-
function toggleDarkMode() {
|
970
|
-
const toggle = document.getElementById('darkmode-toggle');
|
971
|
-
toggle.classList.toggle('on');
|
972
|
-
const subtitle = toggle.closest('.list-item').querySelector('.item-subtitle');
|
973
|
-
if (toggle.classList.contains('on')) {
|
974
|
-
subtitle.textContent = 'Koyu tema aktif';
|
975
|
-
console.log('🌙 Gece modu açıldı');
|
976
|
-
} else {
|
977
|
-
subtitle.textContent = 'Açık tema aktif';
|
978
|
-
console.log('🌙 Gece modu kapatıldı');
|
979
|
-
}
|
980
|
-
}
|
981
|
-
|
982
|
-
function toggleSilent() {
|
983
|
-
const toggle = document.getElementById('silent-toggle');
|
984
|
-
toggle.classList.toggle('on');
|
985
|
-
const subtitle = toggle.closest('.list-item').querySelector('.item-subtitle');
|
986
|
-
if (toggle.classList.contains('on')) {
|
987
|
-
subtitle.textContent = 'Bildirimler kapalı';
|
988
|
-
console.log('🔕 Sessiz mod açıldı');
|
989
|
-
} else {
|
990
|
-
subtitle.textContent = 'Bildirimler açık';
|
991
|
-
console.log('🔕 Sessiz mod kapatıldı');
|
992
|
-
}
|
993
|
-
}
|
994
|
-
|
995
|
-
function updateVolume(value) {
|
996
|
-
document.getElementById('volume-value').textContent = value + '%';
|
997
|
-
console.log('🔊 Ses seviyesi: ' + value + '%');
|
998
|
-
}
|
999
|
-
|
1000
|
-
function updateBrightness(value) {
|
1001
|
-
document.getElementById('brightness-value').textContent = value + '%';
|
1002
|
-
console.log('☀️ Parlaklık: ' + value + '%');
|
1003
|
-
}
|
1004
|
-
|
1005
|
-
function openSettings() {
|
1006
|
-
console.log('⚙️ Sistem ayarları açılıyor...');
|
1007
|
-
}
|
1008
|
-
|
1009
|
-
function openTaskManager() {
|
1010
|
-
console.log('📊 Görev yöneticisi açılıyor...');
|
1011
|
-
}
|
1012
|
-
|
1013
|
-
function restartSystem() {
|
1014
|
-
if (confirm('Sistemi yeniden başlatmak istediğinizden emin misiniz?')) {
|
1015
|
-
console.log('🔄 Sistem yeniden başlatılıyor...');
|
1016
|
-
}
|
1017
|
-
}
|
1018
|
-
|
1019
|
-
function shutdownSystem() {
|
1020
|
-
if (confirm('Sistemi kapatmak istediğinizden emin misiniz?')) {
|
1021
|
-
console.log('⏻ Sistem kapatılıyor...');
|
1022
|
-
}
|
1023
|
-
}
|
1024
|
-
</script>
|
1025
|
-
</body>
|
1026
|
-
</html>
|
1027
|
-
"""
|
1028
|
-
|
1029
|
-
class HTMLCloudSearchWidget(FletHTMLWidget):
|
1030
|
-
"""HTML CloudSearch widget'ı"""
|
1031
|
-
|
1032
|
-
def __init__(self):
|
1033
|
-
super().__init__("CloudSearch", 420, 480)
|
1034
|
-
|
1035
|
-
def show_widget(self):
|
1036
|
-
"""Widget'ı göster"""
|
1037
|
-
html_content = self.generate_cloudsearch_html()
|
1038
|
-
self.load_html_content(html_content)
|
1039
|
-
self.show()
|
1040
|
-
|
1041
|
-
def generate_cloudsearch_html(self):
|
1042
|
-
"""CloudSearch HTML'ini oluştur"""
|
1043
|
-
return """
|
1044
|
-
<!DOCTYPE html>
|
1045
|
-
<html>
|
1046
|
-
<head>
|
1047
|
-
<meta charset="UTF-8">
|
1048
|
-
<title>CloudSearch</title>
|
1049
|
-
<style>
|
1050
|
-
body {
|
1051
|
-
margin: 0;
|
1052
|
-
padding: 20px;
|
1053
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
1054
|
-
background: rgba(30, 30, 30, 0.98);
|
1055
|
-
color: white;
|
1056
|
-
border-radius: 18px;
|
1057
|
-
border: 2px solid rgba(80, 80, 80, 0.9);
|
1058
|
-
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.3);
|
1059
|
-
width: 380px;
|
1060
|
-
height: 440px;
|
1061
|
-
overflow: hidden;
|
1062
|
-
}
|
1063
|
-
|
1064
|
-
.header {
|
1065
|
-
display: flex;
|
1066
|
-
justify-content: space-between;
|
1067
|
-
align-items: center;
|
1068
|
-
margin-bottom: 16px;
|
1069
|
-
}
|
1070
|
-
|
1071
|
-
.title {
|
1072
|
-
font-size: 20px;
|
1073
|
-
font-weight: bold;
|
1074
|
-
color: white;
|
1075
|
-
}
|
1076
|
-
|
1077
|
-
.open-app-btn {
|
1078
|
-
background: rgba(156, 39, 176, 0.8);
|
1079
|
-
border: none;
|
1080
|
-
border-radius: 8px;
|
1081
|
-
padding: 8px 12px;
|
1082
|
-
color: white;
|
1083
|
-
font-size: 12px;
|
1084
|
-
cursor: pointer;
|
1085
|
-
transition: background 0.2s;
|
1086
|
-
}
|
1087
|
-
|
1088
|
-
.open-app-btn:hover {
|
1089
|
-
background: rgba(176, 59, 196, 0.9);
|
1090
|
-
}
|
1091
|
-
|
1092
|
-
.search-container {
|
1093
|
-
margin-bottom: 16px;
|
1094
|
-
}
|
1095
|
-
|
1096
|
-
.search-input {
|
1097
|
-
width: 100%;
|
1098
|
-
padding: 12px 16px;
|
1099
|
-
background: rgba(45, 45, 45, 0.9);
|
1100
|
-
border: 1px solid rgba(100, 100, 100, 0.5);
|
1101
|
-
border-radius: 12px;
|
1102
|
-
color: white;
|
1103
|
-
font-size: 16px;
|
1104
|
-
outline: none;
|
1105
|
-
box-sizing: border-box;
|
1106
|
-
}
|
1107
|
-
|
1108
|
-
.search-input::placeholder {
|
1109
|
-
color: rgba(255, 255, 255, 0.54);
|
1110
|
-
}
|
1111
|
-
|
1112
|
-
.search-input:focus {
|
1113
|
-
border-color: rgba(0, 120, 255, 0.8);
|
1114
|
-
}
|
1115
|
-
|
1116
|
-
.filters {
|
1117
|
-
display: flex;
|
1118
|
-
gap: 8px;
|
1119
|
-
margin-bottom: 16px;
|
1120
|
-
overflow-x: auto;
|
1121
|
-
}
|
1122
|
-
|
1123
|
-
.filter-btn {
|
1124
|
-
background: rgba(60, 60, 60, 0.8);
|
1125
|
-
border: 1px solid rgba(120, 120, 120, 0.6);
|
1126
|
-
border-radius: 15px;
|
1127
|
-
padding: 6px 12px;
|
1128
|
-
color: white;
|
1129
|
-
font-size: 11px;
|
1130
|
-
cursor: pointer;
|
1131
|
-
transition: background 0.2s;
|
1132
|
-
white-space: nowrap;
|
1133
|
-
}
|
1134
|
-
|
1135
|
-
.filter-btn:hover {
|
1136
|
-
background: rgba(80, 80, 80, 0.9);
|
1137
|
-
}
|
1138
|
-
|
1139
|
-
.filter-btn.active {
|
1140
|
-
background: rgba(0, 120, 255, 0.8);
|
1141
|
-
}
|
1142
|
-
|
1143
|
-
.results-title {
|
1144
|
-
font-size: 14px;
|
1145
|
-
font-weight: bold;
|
1146
|
-
color: rgba(255, 255, 255, 0.7);
|
1147
|
-
margin-bottom: 8px;
|
1148
|
-
}
|
1149
|
-
|
1150
|
-
.results-list {
|
1151
|
-
max-height: 240px;
|
1152
|
-
overflow-y: auto;
|
1153
|
-
margin-bottom: 16px;
|
1154
|
-
}
|
1155
|
-
|
1156
|
-
.result-item {
|
1157
|
-
background: rgba(45, 45, 45, 0.9);
|
1158
|
-
border: 1px solid rgba(100, 100, 100, 0.5);
|
1159
|
-
border-radius: 10px;
|
1160
|
-
padding: 10px;
|
1161
|
-
margin-bottom: 8px;
|
1162
|
-
display: flex;
|
1163
|
-
align-items: center;
|
1164
|
-
gap: 12px;
|
1165
|
-
cursor: pointer;
|
1166
|
-
transition: background 0.2s;
|
1167
|
-
}
|
1168
|
-
|
1169
|
-
.result-item:hover {
|
1170
|
-
background: rgba(55, 55, 55, 0.9);
|
1171
|
-
}
|
1172
|
-
|
1173
|
-
.result-icon {
|
1174
|
-
background: rgba(0, 120, 255, 0.8);
|
1175
|
-
border-radius: 8px;
|
1176
|
-
width: 32px;
|
1177
|
-
height: 32px;
|
1178
|
-
display: flex;
|
1179
|
-
align-items: center;
|
1180
|
-
justify-content: center;
|
1181
|
-
font-size: 16px;
|
1182
|
-
flex-shrink: 0;
|
1183
|
-
}
|
1184
|
-
|
1185
|
-
.result-content {
|
1186
|
-
flex: 1;
|
1187
|
-
min-width: 0;
|
1188
|
-
}
|
1189
|
-
|
1190
|
-
.result-name {
|
1191
|
-
font-size: 13px;
|
1192
|
-
font-weight: bold;
|
1193
|
-
color: white;
|
1194
|
-
margin-bottom: 2px;
|
1195
|
-
white-space: nowrap;
|
1196
|
-
overflow: hidden;
|
1197
|
-
text-overflow: ellipsis;
|
1198
|
-
}
|
1199
|
-
|
1200
|
-
.result-path {
|
1201
|
-
font-size: 10px;
|
1202
|
-
color: rgba(255, 255, 255, 0.6);
|
1203
|
-
white-space: nowrap;
|
1204
|
-
overflow: hidden;
|
1205
|
-
text-overflow: ellipsis;
|
1206
|
-
}
|
1207
|
-
|
1208
|
-
.result-meta {
|
1209
|
-
font-size: 9px;
|
1210
|
-
color: rgba(255, 255, 255, 0.54);
|
1211
|
-
display: flex;
|
1212
|
-
gap: 4px;
|
1213
|
-
}
|
1214
|
-
|
1215
|
-
.open-btn {
|
1216
|
-
background: rgba(0, 120, 255, 0.8);
|
1217
|
-
border: none;
|
1218
|
-
border-radius: 6px;
|
1219
|
-
padding: 6px 10px;
|
1220
|
-
color: white;
|
1221
|
-
font-size: 10px;
|
1222
|
-
cursor: pointer;
|
1223
|
-
transition: background 0.2s;
|
1224
|
-
}
|
1225
|
-
|
1226
|
-
.open-btn:hover {
|
1227
|
-
background: rgba(0, 140, 255, 0.9);
|
1228
|
-
}
|
1229
|
-
|
1230
|
-
.bottom-buttons {
|
1231
|
-
display: flex;
|
1232
|
-
gap: 12px;
|
1233
|
-
}
|
1234
|
-
|
1235
|
-
.bottom-btn {
|
1236
|
-
background: rgba(60, 60, 60, 0.8);
|
1237
|
-
border: 1px solid rgba(120, 120, 120, 0.6);
|
1238
|
-
border-radius: 10px;
|
1239
|
-
padding: 10px 16px;
|
1240
|
-
color: white;
|
1241
|
-
font-weight: 600;
|
1242
|
-
font-size: 13px;
|
1243
|
-
cursor: pointer;
|
1244
|
-
transition: background 0.2s;
|
1245
|
-
flex: 1;
|
1246
|
-
text-align: center;
|
1247
|
-
}
|
1248
|
-
|
1249
|
-
.bottom-btn:hover {
|
1250
|
-
background: rgba(80, 80, 80, 0.9);
|
1251
|
-
}
|
1252
|
-
|
1253
|
-
.empty-state {
|
1254
|
-
text-align: center;
|
1255
|
-
padding: 40px 20px;
|
1256
|
-
color: rgba(255, 255, 255, 0.54);
|
1257
|
-
}
|
1258
|
-
|
1259
|
-
.empty-icon {
|
1260
|
-
font-size: 48px;
|
1261
|
-
margin-bottom: 16px;
|
1262
|
-
color: rgba(255, 255, 255, 0.3);
|
1263
|
-
}
|
1264
|
-
|
1265
|
-
/* Scrollbar styling */
|
1266
|
-
.results-list::-webkit-scrollbar {
|
1267
|
-
width: 8px;
|
1268
|
-
}
|
1269
|
-
|
1270
|
-
.results-list::-webkit-scrollbar-track {
|
1271
|
-
background: rgba(60, 60, 60, 0.5);
|
1272
|
-
border-radius: 4px;
|
1273
|
-
}
|
1274
|
-
|
1275
|
-
.results-list::-webkit-scrollbar-thumb {
|
1276
|
-
background: rgba(120, 120, 120, 0.8);
|
1277
|
-
border-radius: 4px;
|
1278
|
-
}
|
1279
|
-
|
1280
|
-
.results-list::-webkit-scrollbar-thumb:hover {
|
1281
|
-
background: rgba(140, 140, 140, 0.9);
|
1282
|
-
}
|
1283
|
-
</style>
|
1284
|
-
</head>
|
1285
|
-
<body>
|
1286
|
-
<div class="header">
|
1287
|
-
<div class="title">🔍 CloudSearch</div>
|
1288
|
-
<button class="open-app-btn" onclick="openCloudSearchApp()">Tam Uygulama</button>
|
1289
|
-
</div>
|
1290
|
-
|
1291
|
-
<div class="search-container">
|
1292
|
-
<input type="text" class="search-input" placeholder="Dosya, klasör veya içerik ara..." oninput="performSearch(this.value)">
|
1293
|
-
</div>
|
1294
|
-
|
1295
|
-
<div class="filters">
|
1296
|
-
<div class="filter-btn active" onclick="setFilter('all')">📄 Tümü</div>
|
1297
|
-
<div class="filter-btn" onclick="setFilter('documents')">📝 Belgeler</div>
|
1298
|
-
<div class="filter-btn" onclick="setFilter('images')">🖼️ Resimler</div>
|
1299
|
-
<div class="filter-btn" onclick="setFilter('code')">💻 Kod</div>
|
1300
|
-
</div>
|
1301
|
-
|
1302
|
-
<div class="results-title" id="results-title">Arama sonuçları burada görünecek</div>
|
1303
|
-
|
1304
|
-
<div class="results-list" id="results-list">
|
1305
|
-
<div class="empty-state">
|
1306
|
-
<div class="empty-icon">🔍</div>
|
1307
|
-
<div>Arama yapmak için yukarıdaki kutuya yazın</div>
|
1308
|
-
</div>
|
1309
|
-
</div>
|
1310
|
-
|
1311
|
-
<div class="bottom-buttons">
|
1312
|
-
<div class="bottom-btn" onclick="openCloudSearchApp()">🔍 Gelişmiş Arama</div>
|
1313
|
-
<div class="bottom-btn" onclick="openFileManager()">📁 Dosya Yöneticisi</div>
|
1314
|
-
</div>
|
1315
|
-
|
1316
|
-
<script>
|
1317
|
-
let currentFilter = 'all';
|
1318
|
-
let searchResults = [];
|
1319
|
-
|
1320
|
-
const mockResults = [
|
1321
|
-
{
|
1322
|
-
name: 'document.txt',
|
1323
|
-
path: '/users/documents/document.txt',
|
1324
|
-
type: 'text',
|
1325
|
-
size: '2.4 KB',
|
1326
|
-
modified: '2 saat önce',
|
1327
|
-
icon: '📄'
|
1328
|
-
},
|
1329
|
-
{
|
1330
|
-
name: 'project.py',
|
1331
|
-
path: '/users/projects/project.py',
|
1332
|
-
type: 'python',
|
1333
|
-
size: '15.7 KB',
|
1334
|
-
modified: '1 gün önce',
|
1335
|
-
icon: '🐍'
|
1336
|
-
},
|
1337
|
-
{
|
1338
|
-
name: 'image.png',
|
1339
|
-
path: '/users/pictures/image.png',
|
1340
|
-
type: 'image',
|
1341
|
-
size: '1.2 MB',
|
1342
|
-
modified: '3 gün önce',
|
1343
|
-
icon: '🖼️'
|
1344
|
-
}
|
1345
|
-
];
|
1346
|
-
|
1347
|
-
function performSearch(query) {
|
1348
|
-
if (query.length < 2) {
|
1349
|
-
showEmptyState();
|
1350
|
-
return;
|
1351
|
-
}
|
1352
|
-
|
1353
|
-
// Simüle edilmiş arama
|
1354
|
-
searchResults = mockResults.filter(item =>
|
1355
|
-
item.name.toLowerCase().includes(query.toLowerCase())
|
1356
|
-
);
|
1357
|
-
|
1358
|
-
displayResults();
|
1359
|
-
}
|
1360
|
-
|
1361
|
-
function setFilter(filter) {
|
1362
|
-
currentFilter = filter;
|
1363
|
-
|
1364
|
-
// Filter butonlarını güncelle
|
1365
|
-
document.querySelectorAll('.filter-btn').forEach(btn => {
|
1366
|
-
btn.classList.remove('active');
|
1367
|
-
});
|
1368
|
-
event.target.classList.add('active');
|
1369
|
-
|
1370
|
-
displayResults();
|
1371
|
-
}
|
1372
|
-
|
1373
|
-
function displayResults() {
|
1374
|
-
const resultsList = document.getElementById('results-list');
|
1375
|
-
const resultsTitle = document.getElementById('results-title');
|
1376
|
-
|
1377
|
-
if (searchResults.length === 0) {
|
1378
|
-
showEmptyState();
|
1379
|
-
return;
|
1380
|
-
}
|
1381
|
-
|
1382
|
-
resultsTitle.textContent = `Sonuçlar (${searchResults.length})`;
|
1383
|
-
|
1384
|
-
let html = '';
|
1385
|
-
searchResults.forEach(result => {
|
1386
|
-
html += `
|
1387
|
-
<div class="result-item" onclick="openFile('${result.path}')">
|
1388
|
-
<div class="result-icon">${result.icon}</div>
|
1389
|
-
<div class="result-content">
|
1390
|
-
<div class="result-name">${result.name}</div>
|
1391
|
-
<div class="result-path">${result.path}</div>
|
1392
|
-
<div class="result-meta">
|
1393
|
-
<span>${result.size}</span>
|
1394
|
-
<span>•</span>
|
1395
|
-
<span>${result.modified}</span>
|
1396
|
-
</div>
|
1397
|
-
</div>
|
1398
|
-
<button class="open-btn" onclick="event.stopPropagation(); openFile('${result.path}')">Aç</button>
|
1399
|
-
</div>
|
1400
|
-
`;
|
1401
|
-
});
|
1402
|
-
|
1403
|
-
resultsList.innerHTML = html;
|
1404
|
-
}
|
1405
|
-
|
1406
|
-
function showEmptyState() {
|
1407
|
-
const resultsList = document.getElementById('results-list');
|
1408
|
-
const resultsTitle = document.getElementById('results-title');
|
1409
|
-
|
1410
|
-
resultsTitle.textContent = 'Arama sonuçları burada görünecek';
|
1411
|
-
resultsList.innerHTML = `
|
1412
|
-
<div class="empty-state">
|
1413
|
-
<div class="empty-icon">🔍</div>
|
1414
|
-
<div>Arama yapmak için yukarıdaki kutuya yazın</div>
|
1415
|
-
</div>
|
1416
|
-
`;
|
1417
|
-
}
|
1418
|
-
|
1419
|
-
function openFile(path) {
|
1420
|
-
alert('📂 ' + path + ' açılıyor...');
|
1421
|
-
}
|
1422
|
-
|
1423
|
-
function openCloudSearchApp() {
|
1424
|
-
alert('🔍 CloudSearch uygulaması açılıyor...');
|
1425
|
-
}
|
1426
|
-
|
1427
|
-
function openFileManager() {
|
1428
|
-
alert('📁 Dosya yöneticisi açılıyor...');
|
1429
|
-
}
|
1430
|
-
</script>
|
1431
|
-
</body>
|
1432
|
-
</html>
|
1433
|
-
"""
|
1434
|
-
|
1435
|
-
# Widget factory fonksiyonu
|
1436
|
-
def create_html_widget(widget_type: str) -> Optional[FletHTMLWidget]:
|
1437
|
-
"""HTML widget oluştur"""
|
1438
|
-
widgets = {
|
1439
|
-
"notification": HTMLNotificationWidget,
|
1440
|
-
"clock": HTMLClockWidget,
|
1441
|
-
"control_center": HTMLControlCenterWidget,
|
1442
|
-
"cloudsearch": HTMLCloudSearchWidget
|
1443
|
-
}
|
1444
|
-
|
1445
|
-
widget_class = widgets.get(widget_type)
|
1446
|
-
if widget_class:
|
1447
|
-
return widget_class()
|
1448
|
-
return None
|