clapp-pm 1.0.33__py3-none-any.whl → 1.0.35__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.
Files changed (31) hide show
  1. {clapp_pm-1.0.33.data → clapp_pm-1.0.35.data}/data/version.json +1 -1
  2. {clapp_pm-1.0.33.dist-info → clapp_pm-1.0.35.dist-info}/METADATA +1 -1
  3. {clapp_pm-1.0.33.dist-info → clapp_pm-1.0.35.dist-info}/RECORD +31 -11
  4. publish_command.py +25 -14
  5. test-app/clapp-packages-repo/README.md +46 -0
  6. test-app/clapp-packages-repo/index.json +40 -0
  7. test-app/clapp-packages-repo/packages/cloud-finder/README.md +164 -0
  8. test-app/clapp-packages-repo/packages/cloud-finder/main.py +985 -0
  9. test-app/clapp-packages-repo/packages/cloud-finder/manifest.json +8 -0
  10. test-app/clapp-packages-repo/packages/cloud-finder/requirements.txt +2 -0
  11. test-app/clapp-packages-repo/packages/cloud-web-browser/README.md +160 -0
  12. test-app/clapp-packages-repo/packages/cloud-web-browser/cloud_browser.py +1031 -0
  13. test-app/clapp-packages-repo/packages/cloud-web-browser/manifest.json +13 -0
  14. test-app/clapp-packages-repo/packages/cloud-web-browser/requirements.txt +4 -0
  15. test-app/clapp-packages-repo/packages/test-app/README.md +51 -0
  16. test-app/clapp-packages-repo/packages/test-app/main.py +1 -0
  17. test-app/clapp-packages-repo/packages/test-app/manifest.json +1 -0
  18. test-app/clapp-packages-repo/packages/test-app-2/README.md +51 -0
  19. test-app/clapp-packages-repo/packages/test-app-2/main.py +55 -0
  20. test-app/clapp-packages-repo/packages/test-app-2/manifest.json +15 -0
  21. test-app/clapp-packages-repo/packages.json +40 -0
  22. test-app/main.py +1 -55
  23. test-app/manifest.json +1 -15
  24. test-app/packages/test-app/README.md +51 -0
  25. test-app/packages/test-app/main.py +1 -0
  26. test-app/packages/test-app/manifest.json +1 -0
  27. version.py +1 -1
  28. {clapp_pm-1.0.33.dist-info → clapp_pm-1.0.35.dist-info}/WHEEL +0 -0
  29. {clapp_pm-1.0.33.dist-info → clapp_pm-1.0.35.dist-info}/entry_points.txt +0 -0
  30. {clapp_pm-1.0.33.dist-info → clapp_pm-1.0.35.dist-info}/licenses/LICENSE +0 -0
  31. {clapp_pm-1.0.33.dist-info → clapp_pm-1.0.35.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,985 @@
1
+ import flet as ft
2
+ import os
3
+ import shutil
4
+ import subprocess
5
+ from pathlib import Path
6
+ from datetime import datetime
7
+ import mimetypes
8
+ import platform
9
+ import json
10
+ import threading
11
+
12
+ class FileHistory:
13
+ def __init__(self):
14
+ self.recent_files = []
15
+ self.favorites = []
16
+ self.load_history()
17
+
18
+ def add_recent(self, path):
19
+ if path not in self.recent_files:
20
+ self.recent_files.insert(0, path)
21
+ self.recent_files = self.recent_files[:10]
22
+ self.save_history()
23
+
24
+ def add_favorite(self, path):
25
+ if path not in self.favorites:
26
+ self.favorites.append(path)
27
+ self.save_history()
28
+
29
+ def remove_favorite(self, path):
30
+ if path in self.favorites:
31
+ self.favorites.remove(path)
32
+ self.save_history()
33
+
34
+ def load_history(self):
35
+ try:
36
+ with open('file_history.json', 'r', encoding='utf-8') as f:
37
+ data = json.load(f)
38
+ self.recent_files = data.get('recent', [])
39
+ self.favorites = data.get('favorites', [])
40
+ except (FileNotFoundError, json.JSONDecodeError):
41
+ # Dosya yoksa veya bozuksa varsayılan değerler kullan
42
+ self.recent_files = []
43
+ self.favorites = []
44
+
45
+ def save_history(self):
46
+ try:
47
+ with open('file_history.json', 'w', encoding='utf-8') as f:
48
+ json.dump({
49
+ 'recent': self.recent_files,
50
+ 'favorites': self.favorites
51
+ }, f, ensure_ascii=False, indent=2)
52
+ except Exception as e:
53
+ print(f"Geçmiş kaydetme hatası: {e}")
54
+
55
+ class CloudFinder:
56
+ def __init__(self):
57
+ self.current_path = str(Path.home())
58
+ self.selected_items = set()
59
+ self.clipboard = []
60
+ self.clipboard_mode = None # 'copy' or 'cut'
61
+ self.view_mode = "list" # "list" or "grid"
62
+ self.show_hidden = False
63
+ self.sort_by = "name" # "name", "size", "date", "type"
64
+ self.sort_reverse = False
65
+ self.search_term = ""
66
+ self.file_history = FileHistory()
67
+ self.drag_source = None
68
+ self.ctrl_pressed = False
69
+ self.shift_pressed = False
70
+ self.last_selected = None
71
+
72
+ def main(self, page: ft.Page):
73
+ self.page = page
74
+ page.title = "Cloud Finder"
75
+ page.theme_mode = ft.ThemeMode.LIGHT
76
+ page.padding = 0
77
+ page.spacing = 0
78
+ page.on_keyboard_event = self._handle_keyboard
79
+
80
+ # Ana container
81
+ self.main_container = ft.Container(
82
+ expand=True,
83
+ bgcolor="#FFFFFF",
84
+ content=ft.Column(
85
+ expand=True,
86
+ spacing=0,
87
+ controls=[
88
+ self._build_toolbar(),
89
+ self._build_sidebar_and_content()
90
+ ]
91
+ )
92
+ )
93
+
94
+ page.add(self.main_container)
95
+ self._load_current_directory()
96
+
97
+ def _build_toolbar(self):
98
+ """Üst toolbar'ı oluştur"""
99
+ return ft.Container(
100
+ height=50,
101
+ bgcolor="#E3F2FD",
102
+ border=ft.border.only(bottom=ft.border.BorderSide(1, "#E0E0E0")),
103
+ content=ft.Row(
104
+ alignment=ft.MainAxisAlignment.SPACE_BETWEEN,
105
+ controls=[
106
+ # Sol taraf - navigasyon butonları
107
+ ft.Row(
108
+ controls=[
109
+ ft.IconButton(
110
+ icon="arrow_back",
111
+ icon_color="#1976D2",
112
+ tooltip="Geri",
113
+ on_click=self._go_back
114
+ ),
115
+ ft.IconButton(
116
+ icon="arrow_forward",
117
+ icon_color="#1976D2",
118
+ tooltip="İleri",
119
+ on_click=self._go_forward
120
+ ),
121
+ ft.IconButton(
122
+ icon="arrow_upward",
123
+ icon_color="#1976D2",
124
+ tooltip="Üst Klasör",
125
+ on_click=self._go_up
126
+ ),
127
+ ]
128
+ ),
129
+
130
+ # Orta - yol gösterici ve arama
131
+ ft.Container(
132
+ expand=True,
133
+ margin=ft.margin.only(left=20, right=20),
134
+ content=ft.Row(
135
+ controls=[
136
+ ft.Text(
137
+ self.current_path,
138
+ size=14,
139
+ color="#424242",
140
+ weight=ft.FontWeight.W_500,
141
+ expand=True
142
+ ),
143
+ ft.TextField(
144
+ hint_text="Dosya ara...",
145
+ width=200,
146
+ on_change=self._on_search_change,
147
+ on_submit=self._perform_search
148
+ )
149
+ ]
150
+ )
151
+ ),
152
+
153
+ # Sağ taraf - görünüm ve ayarlar
154
+ ft.Row(
155
+ controls=[
156
+ ft.IconButton(
157
+ icon="view_list" if self.view_mode == "list" else "grid_view",
158
+ icon_color="#1976D2",
159
+ tooltip="Görünüm Değiştir",
160
+ on_click=self._toggle_view
161
+ ),
162
+ ft.IconButton(
163
+ icon="visibility_off" if self.show_hidden else "visibility",
164
+ icon_color="#1976D2",
165
+ tooltip="Gizli Dosyaları Göster/Gizle",
166
+ on_click=self._toggle_hidden
167
+ ),
168
+ ft.PopupMenuButton(
169
+ icon="sort",
170
+ tooltip="Sıralama",
171
+ items=[
172
+ ft.PopupMenuItem(text="İsme Göre", on_click=lambda e: self._sort_by("name")),
173
+ ft.PopupMenuItem(text="Boyuta Göre", on_click=lambda e: self._sort_by("size")),
174
+ ft.PopupMenuItem(text="Tarihe Göre", on_click=lambda e: self._sort_by("date")),
175
+ ft.PopupMenuItem(text="Türe Göre", on_click=lambda e: self._sort_by("type")),
176
+ ]
177
+ ),
178
+ ]
179
+ )
180
+ ]
181
+ )
182
+ )
183
+
184
+ def _build_sidebar_and_content(self):
185
+ """Sidebar ve ana içerik alanını oluştur"""
186
+ return ft.Row(
187
+ expand=True,
188
+ spacing=0,
189
+ controls=[
190
+ # Sidebar
191
+ ft.Container(
192
+ width=250,
193
+ bgcolor="#FAFAFA",
194
+ border=ft.border.only(right=ft.border.BorderSide(1, "#E0E0E0")),
195
+ content=ft.Column(
196
+ expand=True,
197
+ controls=[
198
+ # Favoriler
199
+ ft.Container(
200
+ padding=ft.padding.all(10),
201
+ content=ft.Text(
202
+ "Favoriler",
203
+ size=12,
204
+ weight=ft.FontWeight.W_600,
205
+ color="#757575"
206
+ )
207
+ ),
208
+ ft.Container(
209
+ padding=ft.padding.only(left=10, right=10, bottom=10),
210
+ content=ft.Column(
211
+ controls=[
212
+ self._build_sidebar_item("🏠 Ana Sayfa", str(Path.home()), "home"),
213
+ self._build_sidebar_item("📁 Masaüstü", str(Path.home() / "Desktop"), "desktop_windows"),
214
+ self._build_sidebar_item("📄 Belgeler", str(Path.home() / "Documents"), "description"),
215
+ self._build_sidebar_item("🖼️ Resimler", str(Path.home() / "Pictures"), "image"),
216
+ self._build_sidebar_item("🎵 Müzik", str(Path.home() / "Music"), "music_note"),
217
+ self._build_sidebar_item("🎬 Videolar", str(Path.home() / "Videos"), "video_library"),
218
+ self._build_sidebar_item("📥 İndirilenler", str(Path.home() / "Downloads"), "download"),
219
+ ]
220
+ )
221
+ ),
222
+
223
+ ft.Divider(height=1, color="#E0E0E0"),
224
+
225
+ # Son Kullanılanlar
226
+ ft.Container(
227
+ padding=ft.padding.all(10),
228
+ content=ft.Text(
229
+ "Son Kullanılanlar",
230
+ size=12,
231
+ weight=ft.FontWeight.W_600,
232
+ color="#757575"
233
+ )
234
+ ),
235
+ ft.Container(
236
+ padding=ft.padding.only(left=10, right=10, bottom=10),
237
+ content=ft.Column(
238
+ controls=[self._build_recent_item(path) for path in self.file_history.recent_files[:5]]
239
+ )
240
+ ),
241
+
242
+ ft.Divider(height=1, color="#E0E0E0"),
243
+
244
+ # Cihazlar
245
+ ft.Container(
246
+ padding=ft.padding.all(10),
247
+ content=ft.Text(
248
+ "Cihazlar",
249
+ size=12,
250
+ weight=ft.FontWeight.W_600,
251
+ color="#757575"
252
+ )
253
+ ),
254
+ ft.Container(
255
+ padding=ft.padding.only(left=10, right=10, bottom=10),
256
+ content=ft.Column(
257
+ controls=[
258
+ self._build_sidebar_item("💾 Bu Mac", "/", "computer"),
259
+ ]
260
+ )
261
+ )
262
+ ]
263
+ )
264
+ ),
265
+
266
+ # Ana içerik alanı
267
+ ft.Container(
268
+ expand=True,
269
+ content=ft.Column(
270
+ expand=True,
271
+ controls=[
272
+ # Dosya işlemleri toolbar'ı
273
+ self._build_file_toolbar(),
274
+
275
+ # Dosya listesi
276
+ ft.Container(
277
+ expand=True,
278
+ content=self._build_file_list()
279
+ )
280
+ ]
281
+ )
282
+ )
283
+ ]
284
+ )
285
+
286
+ def _build_sidebar_item(self, text, path, icon):
287
+ """Sidebar öğesi oluştur"""
288
+ return ft.Container(
289
+ margin=ft.margin.only(bottom=2),
290
+ content=ft.ListTile(
291
+ leading=ft.Icon(icon, size=16, color="#757575"),
292
+ title=ft.Text(
293
+ text,
294
+ size=12,
295
+ color="#424242"
296
+ ),
297
+ dense=True,
298
+ on_click=lambda e: self._navigate_to_path(path)
299
+ )
300
+ )
301
+
302
+ def _build_recent_item(self, path):
303
+ """Son kullanılan öğe oluştur"""
304
+ name = os.path.basename(path)
305
+ icon = "folder" if os.path.isdir(path) else self._get_file_icon(name)
306
+ return ft.Container(
307
+ margin=ft.margin.only(bottom=2),
308
+ content=ft.ListTile(
309
+ leading=ft.Icon(icon, size=16, color="#757575"),
310
+ title=ft.Text(
311
+ name,
312
+ size=12,
313
+ color="#424242"
314
+ ),
315
+ subtitle=ft.Text(
316
+ path,
317
+ size=10,
318
+ color="#9E9E9E"
319
+ ),
320
+ dense=True,
321
+ on_click=lambda e: self._navigate_to_path(path)
322
+ )
323
+ )
324
+
325
+ def _build_file_toolbar(self):
326
+ """Dosya işlemleri toolbar'ı"""
327
+ return ft.Container(
328
+ height=40,
329
+ bgcolor="#FFFFFF",
330
+ border=ft.border.only(bottom=ft.border.BorderSide(1, "#E0E0E0")),
331
+ content=ft.Row(
332
+ alignment=ft.MainAxisAlignment.SPACE_BETWEEN,
333
+ controls=[
334
+ # Sol taraf - dosya işlemleri
335
+ ft.Row(
336
+ controls=[
337
+ ft.IconButton(
338
+ icon="create_new_folder",
339
+ icon_color="#1976D2",
340
+ tooltip="Yeni Klasör",
341
+ on_click=self._create_new_folder
342
+ ),
343
+ ft.IconButton(
344
+ icon="create",
345
+ icon_color="#1976D2",
346
+ tooltip="Yeni Dosya",
347
+ on_click=self._create_new_file
348
+ ),
349
+ ft.IconButton(
350
+ icon="content_copy",
351
+ icon_color="#1976D2",
352
+ tooltip="Kopyala (Ctrl+C)",
353
+ on_click=self._copy_selected
354
+ ),
355
+ ft.IconButton(
356
+ icon="content_cut",
357
+ icon_color="#1976D2",
358
+ tooltip="Kes (Ctrl+X)",
359
+ on_click=self._cut_selected
360
+ ),
361
+ ft.IconButton(
362
+ icon="content_paste",
363
+ icon_color="#1976D2",
364
+ tooltip="Yapıştır (Ctrl+V)",
365
+ on_click=self._paste_items
366
+ ),
367
+ ft.IconButton(
368
+ icon="delete",
369
+ icon_color="#D32F2F",
370
+ tooltip="Sil (Delete)",
371
+ on_click=self._delete_selected
372
+ ),
373
+ ]
374
+ ),
375
+
376
+ # Sağ taraf - seçim bilgisi
377
+ ft.Container(
378
+ padding=ft.padding.only(right=10),
379
+ content=ft.Text(
380
+ f"{len(self.selected_items)} öğe seçili" if self.selected_items else "",
381
+ size=12,
382
+ color="#757575"
383
+ )
384
+ )
385
+ ]
386
+ )
387
+ )
388
+
389
+ def _build_file_list(self):
390
+ """Dosya listesi oluştur"""
391
+ if self.view_mode == "list":
392
+ self.file_list = ft.ListView(
393
+ expand=True,
394
+ spacing=2,
395
+ padding=ft.padding.all(10)
396
+ )
397
+ else:
398
+ self.file_list = ft.GridView(
399
+ expand=True,
400
+ runs_count=5,
401
+ max_extent=150,
402
+ child_aspect_ratio=1.0,
403
+ spacing=10,
404
+ run_spacing=10,
405
+ padding=ft.padding.all(10)
406
+ )
407
+ return self.file_list
408
+
409
+ def _load_current_directory(self):
410
+ """Mevcut dizini yükle"""
411
+ try:
412
+ self._show_loading("Yükleniyor...")
413
+ self.file_list.controls.clear()
414
+
415
+ # Üst dizine git butonu
416
+ if self.current_path != "/":
417
+ self.file_list.controls.append(
418
+ self._build_file_item("..", "..", True, "folder_open")
419
+ )
420
+
421
+ # Dizin içeriğini listele
422
+ items = []
423
+ for item in os.listdir(self.current_path):
424
+ item_path = os.path.join(self.current_path, item)
425
+
426
+ # Gizli dosyaları filtrele
427
+ if not self.show_hidden and item.startswith('.'):
428
+ continue
429
+
430
+ try:
431
+ if os.path.isdir(item_path):
432
+ items.append((item, item_path, True, "folder"))
433
+ else:
434
+ items.append((item, item_path, False, self._get_file_icon(item)))
435
+ except PermissionError:
436
+ continue
437
+
438
+ # Arama filtresi uygula
439
+ if self.search_term:
440
+ items = self._filter_items(items)
441
+
442
+ # Sıralama uygula
443
+ items = self._sort_items(items)
444
+
445
+ # Görünüm moduna göre oluştur
446
+ for item in items:
447
+ if self.view_mode == "list":
448
+ self.file_list.controls.append(
449
+ self._build_file_item(item[0], item[1], item[2], item[3])
450
+ )
451
+ else:
452
+ self.file_list.controls.append(
453
+ self._build_grid_item(item[0], item[1], item[2], item[3])
454
+ )
455
+
456
+ self.file_list.update()
457
+ self._hide_loading()
458
+
459
+ except Exception as e:
460
+ self._show_notification(f"Hata: {e}", "#F44336")
461
+
462
+ def _build_file_item(self, name, path, is_dir, icon):
463
+ """Dosya öğesi oluştur (liste görünümü)"""
464
+ return ft.Container(
465
+ bgcolor="#FFFFFF",
466
+ border=ft.border.all(1, "#FFFFFF"),
467
+ border_radius=ft.border_radius.all(4),
468
+ padding=ft.padding.all(8),
469
+ content=ft.ListTile(
470
+ leading=ft.Icon(icon, color="#1976D2" if is_dir else "#757575"),
471
+ title=ft.Text(
472
+ name,
473
+ size=14,
474
+ weight=ft.FontWeight.W_500,
475
+ color="#212121"
476
+ ),
477
+ subtitle=ft.Text(
478
+ self._get_file_info(path),
479
+ size=12,
480
+ color="#757575"
481
+ ),
482
+ trailing=ft.PopupMenuButton(
483
+ icon="more_vert",
484
+ tooltip="Daha fazla",
485
+ items=[
486
+ ft.PopupMenuItem(text="Aç", on_click=lambda e: self._open_file(path)),
487
+ ft.PopupMenuItem(text="Kopyala", on_click=lambda e: self._copy_item(path)),
488
+ ft.PopupMenuItem(text="Kes", on_click=lambda e: self._cut_item(path)),
489
+ ft.PopupMenuItem(text="Sil", on_click=lambda e: self._delete_item(path)),
490
+ ft.PopupMenuItem(text="Favorilere Ekle", on_click=lambda e: self._add_to_favorites(path)),
491
+ ]
492
+ ),
493
+ on_click=lambda e: self._on_file_click(path, is_dir),
494
+ on_long_press=lambda e: self._on_file_long_press(path),
495
+ selected=path in self.selected_items,
496
+ selected_color="#E3F2FD",
497
+ )
498
+ )
499
+
500
+ def _build_grid_item(self, name, path, is_dir, icon):
501
+ """Dosya öğesi oluştur (grid görünümü)"""
502
+ return ft.Container(
503
+ bgcolor="#FFFFFF",
504
+ border=ft.border.all(1, "#E0E0E0"),
505
+ border_radius=ft.border_radius.all(8),
506
+ padding=ft.padding.all(10),
507
+ content=ft.Column(
508
+ horizontal_alignment=ft.CrossAxisAlignment.CENTER,
509
+ controls=[
510
+ ft.Icon(
511
+ icon,
512
+ size=48,
513
+ color="#1976D2" if is_dir else "#757575"
514
+ ),
515
+ ft.Text(
516
+ name,
517
+ size=12,
518
+ weight=ft.FontWeight.W_500,
519
+ color="#212121",
520
+ text_align=ft.TextAlign.CENTER,
521
+ max_lines=2,
522
+ overflow=ft.TextOverflow.ELLIPSIS
523
+ ),
524
+ ft.Text(
525
+ self._get_file_info(path),
526
+ size=10,
527
+ color="#757575",
528
+ text_align=ft.TextAlign.CENTER
529
+ )
530
+ ]
531
+ ),
532
+ on_click=lambda e: self._on_file_click(path, is_dir),
533
+ on_long_press=lambda e: self._on_file_long_press(path),
534
+ )
535
+
536
+ def _get_file_icon(self, filename):
537
+ """Dosya türüne göre ikon döndür"""
538
+ ext = Path(filename).suffix.lower()
539
+ icon_map = {
540
+ '.txt': 'description',
541
+ '.pdf': 'picture_as_pdf',
542
+ '.doc': 'description',
543
+ '.docx': 'description',
544
+ '.xls': 'table_chart',
545
+ '.xlsx': 'table_chart',
546
+ '.ppt': 'slides',
547
+ '.pptx': 'slides',
548
+ '.jpg': 'image',
549
+ '.jpeg': 'image',
550
+ '.png': 'image',
551
+ '.gif': 'image',
552
+ '.mp3': 'music_note',
553
+ '.mp4': 'video_file',
554
+ '.avi': 'video_file',
555
+ '.zip': 'archive',
556
+ '.rar': 'archive',
557
+ '.py': 'code',
558
+ '.js': 'code',
559
+ '.html': 'code',
560
+ '.css': 'code',
561
+ }
562
+ return icon_map.get(ext, 'insert_drive_file')
563
+
564
+ def _get_file_info(self, path):
565
+ """Dosya bilgilerini al"""
566
+ try:
567
+ stat = os.stat(path)
568
+ size = stat.st_size
569
+ modified = datetime.fromtimestamp(stat.st_mtime)
570
+
571
+ if os.path.isdir(path):
572
+ return f"Klasör • {modified.strftime('%d.%m.%Y %H:%M')}"
573
+ else:
574
+ if size < 1024:
575
+ size_str = f"{size} B"
576
+ elif size < 1024 * 1024:
577
+ size_str = f"{size // 1024} KB"
578
+ else:
579
+ size_str = f"{size // (1024 * 1024)} MB"
580
+
581
+ return f"{size_str} • {modified.strftime('%d.%m.%Y %H:%M')}"
582
+ except:
583
+ return "Bilinmeyen"
584
+
585
+ def _on_file_click(self, path, is_dir):
586
+ """Dosya tıklama olayı"""
587
+ if self.ctrl_pressed:
588
+ # Ctrl + tıklama - çoklu seçim
589
+ if path in self.selected_items:
590
+ self.selected_items.remove(path)
591
+ else:
592
+ self.selected_items.add(path)
593
+ self.last_selected = path
594
+ elif self.shift_pressed and self.last_selected:
595
+ # Shift + tıklama - aralık seçimi
596
+ self._select_range(self.last_selected, path)
597
+ else:
598
+ # Normal tıklama
599
+ if is_dir:
600
+ # Navigasyon geçmişini başlat
601
+ if not hasattr(self, 'navigation_history'):
602
+ self.navigation_history = []
603
+ self.current_history_index = -1
604
+
605
+ # Mevcut yolu geçmişe ekle
606
+ if self.current_path != path:
607
+ # Geçmişteki mevcut konumdan sonraki tüm geçmişi sil
608
+ self.navigation_history = self.navigation_history[:self.current_history_index + 1]
609
+ self.navigation_history.append(self.current_path)
610
+ self.current_history_index = len(self.navigation_history) - 1
611
+
612
+ self.current_path = path
613
+ self._load_current_directory()
614
+ else:
615
+ self._open_file(path)
616
+ self.file_history.add_recent(path)
617
+
618
+ self._load_current_directory()
619
+
620
+ def _on_file_long_press(self, path):
621
+ """Dosya uzun basma olayı"""
622
+ if path in self.selected_items:
623
+ self.selected_items.remove(path)
624
+ else:
625
+ self.selected_items.add(path)
626
+ self._load_current_directory()
627
+
628
+ def _select_range(self, start_path, end_path):
629
+ """İki dosya arasındaki tüm dosyaları seç"""
630
+ try:
631
+ # Mevcut dosya listesini al
632
+ current_items = []
633
+ for item in os.listdir(self.current_path):
634
+ item_path = os.path.join(self.current_path, item)
635
+ if not self.show_hidden and item.startswith('.'):
636
+ continue
637
+ try:
638
+ if os.path.exists(item_path):
639
+ current_items.append((item, item_path))
640
+ except PermissionError:
641
+ continue
642
+
643
+ # Dosyaları sırala
644
+ current_items.sort(key=lambda x: x[0].lower())
645
+
646
+ # Başlangıç ve bitiş indekslerini bul
647
+ start_index = -1
648
+ end_index = -1
649
+
650
+ for i, (name, path) in enumerate(current_items):
651
+ if path == start_path:
652
+ start_index = i
653
+ if path == end_path:
654
+ end_index = i
655
+
656
+ if start_index != -1 and end_index != -1:
657
+ # İndeksleri düzenle (küçük olan başlangıç olsun)
658
+ if start_index > end_index:
659
+ start_index, end_index = end_index, start_index
660
+
661
+ # Aralıktaki tüm dosyaları seç
662
+ for i in range(start_index, end_index + 1):
663
+ _, path = current_items[i]
664
+ self.selected_items.add(path)
665
+
666
+ self._show_notification(f"{end_index - start_index + 1} dosya seçildi", "#4CAF50")
667
+
668
+ except Exception as e:
669
+ self._show_notification(f"Aralık seçimi hatası: {e}", "#F44336")
670
+
671
+ def _navigate_to_path(self, path):
672
+ """Belirtilen yola git"""
673
+ if os.path.exists(path):
674
+ # Navigasyon geçmişini başlat
675
+ if not hasattr(self, 'navigation_history'):
676
+ self.navigation_history = []
677
+ self.current_history_index = -1
678
+
679
+ # Mevcut yolu geçmişe ekle
680
+ if self.current_path != path:
681
+ # Geçmişteki mevcut konumdan sonraki tüm geçmişi sil
682
+ self.navigation_history = self.navigation_history[:self.current_history_index + 1]
683
+ self.navigation_history.append(self.current_path)
684
+ self.current_history_index = len(self.navigation_history) - 1
685
+
686
+ self.current_path = path
687
+ self._load_current_directory()
688
+
689
+ def _go_back(self, e):
690
+ """Geri git"""
691
+ if not hasattr(self, 'navigation_history'):
692
+ self.navigation_history = []
693
+ self.current_history_index = -1
694
+
695
+ if self.current_history_index > 0:
696
+ self.current_history_index -= 1
697
+ self.current_path = self.navigation_history[self.current_history_index]
698
+ self._load_current_directory()
699
+ self._show_notification("Geri gidildi", "#4CAF50")
700
+ else:
701
+ self._show_notification("Geri gidilecek geçmiş yok", "#FF9800")
702
+
703
+ def _go_forward(self, e):
704
+ """İleri git"""
705
+ if not hasattr(self, 'navigation_history'):
706
+ self.navigation_history = []
707
+ self.current_history_index = -1
708
+
709
+ if self.current_history_index < len(self.navigation_history) - 1:
710
+ self.current_history_index += 1
711
+ self.current_path = self.navigation_history[self.current_history_index]
712
+ self._load_current_directory()
713
+ self._show_notification("İleri gidildi", "#4CAF50")
714
+ else:
715
+ self._show_notification("İleri gidilecek geçmiş yok", "#FF9800")
716
+
717
+ def _go_up(self, e):
718
+ """Üst dizine git"""
719
+ parent = os.path.dirname(self.current_path)
720
+ if parent != self.current_path:
721
+ self.current_path = parent
722
+ self._load_current_directory()
723
+
724
+ def _on_search_change(self, e):
725
+ """Arama terimi değiştiğinde"""
726
+ self.search_term = e.control.value
727
+ self._load_current_directory()
728
+
729
+ def _perform_search(self, e):
730
+ """Arama yap"""
731
+ self._load_current_directory()
732
+
733
+ def _toggle_view(self, e):
734
+ """Görünüm değiştir"""
735
+ self.view_mode = "grid" if self.view_mode == "list" else "list"
736
+ self._load_current_directory()
737
+
738
+ def _toggle_hidden(self, e):
739
+ """Gizli dosyaları göster/gizle"""
740
+ self.show_hidden = not self.show_hidden
741
+ self._load_current_directory()
742
+
743
+ def _sort_by(self, sort_type):
744
+ """Sıralama türünü değiştir"""
745
+ if self.sort_by == sort_type:
746
+ self.sort_reverse = not self.sort_reverse
747
+ else:
748
+ self.sort_by = sort_type
749
+ self.sort_reverse = False
750
+ self._load_current_directory()
751
+
752
+ def _filter_items(self, items):
753
+ """Arama filtresi uygula"""
754
+ filtered = []
755
+ for item in items:
756
+ if self.search_term.lower() in item[0].lower():
757
+ filtered.append(item)
758
+ return filtered
759
+
760
+ def _sort_items(self, items):
761
+ """Dosyaları sırala"""
762
+ if self.sort_by == "name":
763
+ items.sort(key=lambda x: x[0].lower(), reverse=self.sort_reverse)
764
+ elif self.sort_by == "size":
765
+ items.sort(key=lambda x: os.path.getsize(x[1]) if os.path.exists(x[1]) else 0, reverse=self.sort_reverse)
766
+ elif self.sort_by == "date":
767
+ items.sort(key=lambda x: os.path.getmtime(x[1]) if os.path.exists(x[1]) else 0, reverse=self.sort_reverse)
768
+ elif self.sort_by == "type":
769
+ items.sort(key=lambda x: Path(x[0]).suffix.lower(), reverse=self.sort_reverse)
770
+
771
+ # Klasörleri önce göster
772
+ folders = [item for item in items if item[2]]
773
+ files = [item for item in items if not item[2]]
774
+ return folders + files
775
+
776
+ def _handle_keyboard(self, e: ft.KeyboardEvent):
777
+ """Klavye olaylarını işle"""
778
+ try:
779
+ # Basit klavye kısayolları
780
+ if e.key == "Delete":
781
+ self._delete_selected()
782
+ elif e.key == "c" and hasattr(e, 'ctrl') and e.ctrl:
783
+ self._copy_selected()
784
+ elif e.key == "v" and hasattr(e, 'ctrl') and e.ctrl:
785
+ self._paste_items()
786
+ elif e.key == "x" and hasattr(e, 'ctrl') and e.ctrl:
787
+ self._cut_selected()
788
+ elif e.key == "a" and hasattr(e, 'ctrl') and e.ctrl:
789
+ self._select_all()
790
+ elif e.key == "Escape":
791
+ self.selected_items.clear()
792
+ self._load_current_directory()
793
+ except Exception as ex:
794
+ print(f"Klavye olayı hatası: {ex}")
795
+
796
+ def _select_all(self):
797
+ """Tüm dosyaları seç"""
798
+ try:
799
+ self.selected_items.clear()
800
+
801
+ # Mevcut dizindeki tüm dosyaları al
802
+ for item in os.listdir(self.current_path):
803
+ item_path = os.path.join(self.current_path, item)
804
+
805
+ # Gizli dosyaları filtrele
806
+ if not self.show_hidden and item.startswith('.'):
807
+ continue
808
+
809
+ try:
810
+ if os.path.exists(item_path):
811
+ self.selected_items.add(item_path)
812
+ except PermissionError:
813
+ continue
814
+
815
+ self._load_current_directory()
816
+ self._show_notification(f"{len(self.selected_items)} dosya seçildi", "#4CAF50")
817
+
818
+ except Exception as e:
819
+ self._show_notification(f"Tümünü seçme hatası: {e}", "#F44336")
820
+
821
+ def _create_new_folder(self, e):
822
+ """Yeni klasör oluştur"""
823
+ try:
824
+ folder_name = "Yeni Klasör"
825
+ counter = 1
826
+ while os.path.exists(os.path.join(self.current_path, folder_name)):
827
+ folder_name = f"Yeni Klasör ({counter})"
828
+ counter += 1
829
+
830
+ os.makedirs(os.path.join(self.current_path, folder_name))
831
+ self._load_current_directory()
832
+ self._show_notification(f"'{folder_name}' klasörü oluşturuldu", "#4CAF50")
833
+ except Exception as e:
834
+ self._show_notification(f"Klasör oluşturma hatası: {e}", "#F44336")
835
+
836
+ def _create_new_file(self, e):
837
+ """Yeni dosya oluştur"""
838
+ try:
839
+ file_name = "Yeni Dosya.txt"
840
+ counter = 1
841
+ while os.path.exists(os.path.join(self.current_path, file_name)):
842
+ file_name = f"Yeni Dosya ({counter}).txt"
843
+ counter += 1
844
+
845
+ with open(os.path.join(self.current_path, file_name), 'w') as f:
846
+ f.write("")
847
+
848
+ self._load_current_directory()
849
+ self._show_notification(f"'{file_name}' dosyası oluşturuldu", "#4CAF50")
850
+ except Exception as e:
851
+ self._show_notification(f"Dosya oluşturma hatası: {e}", "#F44336")
852
+
853
+ def _copy_selected(self, e=None):
854
+ """Seçili öğeleri kopyala"""
855
+ if self.selected_items:
856
+ self.clipboard = list(self.selected_items)
857
+ self.clipboard_mode = 'copy'
858
+ self._show_notification(f"{len(self.selected_items)} öğe kopyalandı", "#4CAF50")
859
+
860
+ def _cut_selected(self, e=None):
861
+ """Seçili öğeleri kes"""
862
+ if self.selected_items:
863
+ self.clipboard = list(self.selected_items)
864
+ self.clipboard_mode = 'cut'
865
+ self._show_notification(f"{len(self.selected_items)} öğe kesildi", "#FF9800")
866
+
867
+ def _copy_item(self, path):
868
+ """Tek dosyayı kopyala"""
869
+ self.selected_items = {path}
870
+ self._copy_selected()
871
+
872
+ def _cut_item(self, path):
873
+ """Tek dosyayı kes"""
874
+ self.selected_items = {path}
875
+ self._cut_selected()
876
+
877
+ def _delete_item(self, path):
878
+ """Tek dosyayı sil"""
879
+ self.selected_items = {path}
880
+ self._delete_selected()
881
+
882
+ def _paste_items(self, e=None):
883
+ """Pano öğelerini yapıştır"""
884
+ if not self.clipboard:
885
+ return
886
+
887
+ success_count = 0
888
+ for source_path in self.clipboard:
889
+ try:
890
+ source_name = os.path.basename(source_path)
891
+ dest_path = os.path.join(self.current_path, source_name)
892
+
893
+ # Aynı isimde dosya varsa numara ekle
894
+ counter = 1
895
+ while os.path.exists(dest_path):
896
+ name, ext = os.path.splitext(source_name)
897
+ dest_path = os.path.join(self.current_path, f"{name} ({counter}){ext}")
898
+ counter += 1
899
+
900
+ if os.path.isdir(source_path):
901
+ shutil.copytree(source_path, dest_path)
902
+ else:
903
+ shutil.copy2(source_path, dest_path)
904
+
905
+ # Kesme işlemi ise kaynak dosyayı sil
906
+ if self.clipboard_mode == 'cut':
907
+ if os.path.isdir(source_path):
908
+ shutil.rmtree(source_path)
909
+ else:
910
+ os.remove(source_path)
911
+
912
+ success_count += 1
913
+
914
+ except Exception as e:
915
+ self._show_notification(f"Yapıştırma hatası: {e}", "#F44336")
916
+
917
+ self.clipboard.clear()
918
+ self.clipboard_mode = None
919
+ self.selected_items.clear()
920
+ self._load_current_directory()
921
+
922
+ if success_count > 0:
923
+ action = "yapıştırıldı" if self.clipboard_mode == 'copy' else "taşındı"
924
+ self._show_notification(f"{success_count} öğe {action}", "#4CAF50")
925
+
926
+ def _delete_selected(self, e=None):
927
+ """Seçili öğeleri sil"""
928
+ if not self.selected_items:
929
+ return
930
+
931
+ success_count = 0
932
+ for path in self.selected_items:
933
+ try:
934
+ if os.path.isdir(path):
935
+ shutil.rmtree(path)
936
+ else:
937
+ os.remove(path)
938
+ success_count += 1
939
+ except Exception as e:
940
+ self._show_notification(f"Silme hatası: {e}", "#F44336")
941
+
942
+ self.selected_items.clear()
943
+ self._load_current_directory()
944
+
945
+ if success_count > 0:
946
+ self._show_notification(f"{success_count} öğe silindi", "#4CAF50")
947
+
948
+ def _add_to_favorites(self, path):
949
+ """Favorilere ekle"""
950
+ self.file_history.add_favorite(path)
951
+ self._show_notification("Favorilere eklendi", "#4CAF50")
952
+
953
+ def _open_file(self, path):
954
+ """Dosyayı varsayılan uygulamada aç"""
955
+ try:
956
+ if platform.system() == "Darwin": # macOS
957
+ subprocess.run(["open", path])
958
+ elif platform.system() == "Windows":
959
+ os.startfile(path)
960
+ else: # Linux
961
+ subprocess.run(["xdg-open", path])
962
+ except Exception as e:
963
+ self._show_notification(f"Dosya açma hatası: {e}", "#F44336")
964
+
965
+ def _show_notification(self, message, color="#4CAF50"):
966
+ """Bildirim göster"""
967
+ # Basit bildirim - geliştirilecek
968
+ print(f"Bildirim: {message}")
969
+
970
+ def _show_loading(self, message="Yükleniyor..."):
971
+ """Yükleme göstergesi göster"""
972
+ # Basit yükleme göstergesi
973
+ print(f"⏳ {message}")
974
+
975
+ def _hide_loading(self):
976
+ """Yükleme göstergesini gizle"""
977
+ # Yükleme tamamlandı
978
+ print("✅ Yükleme tamamlandı")
979
+
980
+ def main():
981
+ app = CloudFinder()
982
+ ft.app(target=app.main)
983
+
984
+ if __name__ == "__main__":
985
+ main()