torrent-downloader-react 1.1.10__py3-none-any.whl → 1.2.0__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.
@@ -75,10 +75,13 @@ DOWNLOAD_PATH = get_downloads_dir()
75
75
  session = lt.session()
76
76
  settings = session.get_settings()
77
77
  settings['listen_interfaces'] = '0.0.0.0:6881'
78
+ settings['auto_manage_interval'] = 30 # Reduce auto-management frequency
79
+ settings['auto_manage_startup'] = 60 # Delay auto-management on startup
78
80
  session.apply_settings(settings)
79
81
 
80
- # Store active torrents
82
+ # Store active torrents and their pause state
81
83
  active_torrents: Dict[str, lt.torrent_handle] = {}
84
+ paused_torrents: set = set() # Track manually paused torrents
82
85
 
83
86
  class TorrentRequest(BaseModel):
84
87
  magnet_link: str
@@ -139,9 +142,15 @@ async def list_torrents() -> List[TorrentInfo]:
139
142
  for torrent_id, handle in active_torrents.items():
140
143
  status = handle.status()
141
144
 
145
+ # Enforce pause state for manually paused torrents
146
+ if torrent_id in paused_torrents and not status.paused:
147
+ handle.pause() # Re-pause if libtorrent auto-resumed it
148
+
142
149
  # Get the state string
143
150
  state_str = "unknown"
144
- if status.state == lt.torrent_status.downloading:
151
+ if torrent_id in paused_torrents or status.paused:
152
+ state_str = "paused"
153
+ elif status.state == lt.torrent_status.downloading:
145
154
  state_str = "downloading"
146
155
  elif status.state == lt.torrent_status.seeding:
147
156
  state_str = "seeding"
@@ -194,9 +203,32 @@ async def remove_torrent(torrent_id: str, delete_files: bool = False):
194
203
  handle = active_torrents[torrent_id]
195
204
  session.remove_torrent(handle, 1 if delete_files else 0)
196
205
  del active_torrents[torrent_id]
206
+ paused_torrents.discard(torrent_id) # Clean up pause state
197
207
 
198
208
  return {"message": "Torrent removed successfully"}
199
209
 
210
+ @app.post("/api/torrent/{torrent_id}/pause")
211
+ async def pause_torrent(torrent_id: str):
212
+ if torrent_id not in active_torrents:
213
+ raise HTTPException(status_code=404, detail="Torrent not found")
214
+
215
+ handle = active_torrents[torrent_id]
216
+ handle.pause()
217
+ paused_torrents.add(torrent_id) # Track that this torrent was manually paused
218
+
219
+ return {"message": "Torrent paused successfully"}
220
+
221
+ @app.post("/api/torrent/{torrent_id}/resume")
222
+ async def resume_torrent(torrent_id: str):
223
+ if torrent_id not in active_torrents:
224
+ raise HTTPException(status_code=404, detail="Torrent not found")
225
+
226
+ handle = active_torrents[torrent_id]
227
+ handle.resume()
228
+ paused_torrents.discard(torrent_id) # Remove from manually paused set
229
+
230
+ return {"message": "Torrent resumed successfully"}
231
+
200
232
  @app.get("/api/downloads/path")
201
233
  async def get_downloads_path():
202
234
  return {"path": str(DOWNLOAD_PATH)}
@@ -0,0 +1 @@
1
+ :root{font-family:Inter,system-ui,Avenir,Helvetica,Arial,sans-serif;line-height:1.5;font-weight:400;color-scheme:light dark;color:#213547;background-color:#fff;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}*{box-sizing:border-box;margin:0;padding:0}body{margin:0;min-width:320px;min-height:100vh}h1{font-size:3.2em;line-height:1.1}button{border-radius:8px;border:1px solid transparent;padding:.6em 1.2em;font-size:1em;font-weight:500;font-family:inherit;background-color:#1a1a1a;cursor:pointer;transition:border-color .25s}button:hover{border-color:#646cff}button:focus,button:focus-visible{outline:4px auto -webkit-focus-ring-color}@media (prefers-color-scheme: dark){:root{color:#ffffffde;background-color:#242424}.torrent-item{background-color:#2a2a2a!important;border-color:#404040!important}.torrent-info h3{color:#e2e8f0!important}.torrent-info p{color:#94a3b8!important}.progress-bar{background-color:#404040!important}input{background-color:#2a2a2a;color:#fff;border-color:#404040!important}input::placeholder{color:#94a3b8}}:root{--text-primary: #1e293b;--text-secondary: #64748b;--text-muted: #94a3b8;--border-color: #e2e8f0;--background-primary: #ffffff;--background-secondary: #f8fafc;--background-tertiary: #f1f5f9;--accent-color: #2563eb;--accent-hover: #1d4ed8;--success-color: #16a34a;--error-color: #dc2626;--warning-color: #ea580c;--spacing-xs: .25rem;--spacing-sm: .5rem;--spacing-md: 1rem;--spacing-lg: 1.5rem;--spacing-xl: 2rem;--spacing-2xl: 3rem;--radius-sm: .25rem;--radius-md: .5rem;--radius-lg: .75rem;--radius-xl: 1rem;--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / .05);--shadow-md: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1)}@media (prefers-color-scheme: dark){:root{--text-primary: #e2e8f0;--text-secondary: #94a3b8;--text-muted: #64748b;--border-color: #334155;--background-primary: #0f172a;--background-secondary: #1e293b;--background-tertiary: #334155;--accent-color: #3b82f6;--accent-hover: #2563eb}}*{box-sizing:border-box}body{font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;line-height:1.6;color:var(--text-primary);background-color:var(--background-primary);margin:0;padding:0}.app{min-height:100vh;display:flex;flex-direction:column}.app-header{background-color:var(--background-secondary);border-bottom:1px solid var(--border-color);padding:var(--spacing-lg) var(--spacing-xl);position:sticky;top:0;z-index:100;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}.header-main{max-width:1200px;margin:0 auto;display:flex;align-items:center;justify-content:space-between;gap:var(--spacing-xl)}.header-brand{display:flex;align-items:center;gap:var(--spacing-lg)}.header-brand h1{margin:0;font-size:1.75rem;font-weight:700;color:var(--text-primary)}.connection-status{display:flex;align-items:center;gap:var(--spacing-xs);font-size:.875rem;color:var(--text-secondary)}.status-icon.online{color:var(--success-color)}.header-stats{display:flex;gap:var(--spacing-xl)}.stat-group{display:flex;gap:var(--spacing-lg)}.stat-item-header{display:flex;align-items:center;gap:var(--spacing-xs);font-size:.875rem}.stat-icon.download{color:var(--accent-color)}.stat-icon.upload{color:var(--success-color)}.stat-label{color:var(--text-secondary)}.stat-value{font-weight:600;color:var(--text-primary)}.stat-count{font-weight:700;font-size:1.25rem;color:var(--text-primary)}.header-actions{display:flex;gap:var(--spacing-md)}.main-content{flex:1;max-width:1200px;margin:0 auto;padding:var(--spacing-xl);width:100%}.error-banner{background-color:#fee2e2;border:1px solid #fecaca;color:var(--error-color);padding:var(--spacing-md);border-radius:var(--radius-md);margin-bottom:var(--spacing-lg)}@media (prefers-color-scheme: dark){.error-banner{background-color:#450a0a;border-color:#7f1d1d;color:#fecaca}}.add-torrent-container{background-color:var(--background-secondary);border:1px solid var(--border-color);border-radius:var(--radius-lg);padding:var(--spacing-lg);margin-bottom:var(--spacing-xl);box-shadow:var(--shadow-sm)}.tab-selector{display:flex;gap:var(--spacing-xs);margin-bottom:var(--spacing-lg);background-color:var(--background-tertiary);border-radius:var(--radius-md);padding:var(--spacing-xs)}.tab-button{flex:1;display:flex;align-items:center;justify-content:center;gap:var(--spacing-xs);padding:var(--spacing-sm) var(--spacing-md);border:none;background:transparent;color:var(--text-secondary);border-radius:var(--radius-sm);cursor:pointer;transition:all .2s ease;font-size:.875rem;font-weight:500}.tab-button.active{background-color:var(--background-primary);color:var(--text-primary);box-shadow:var(--shadow-sm)}.add-torrent-form{width:100%}.input-group{display:flex;gap:var(--spacing-md);align-items:flex-start}.torrent-input{flex:1;padding:var(--spacing-md);border:1px solid var(--border-color);border-radius:var(--radius-md);font-size:1rem;background-color:var(--background-primary);color:var(--text-primary);transition:border-color .2s ease}.torrent-input:focus{outline:none;border-color:var(--accent-color);box-shadow:0 0 0 3px #2563eb1a}.torrent-input.invalid{border-color:var(--error-color)}.torrent-input.invalid:focus{box-shadow:0 0 0 3px #dc26261a}.input-error{margin-top:var(--spacing-sm);color:var(--error-color);font-size:.875rem}.add-button{display:flex;align-items:center;gap:var(--spacing-xs);padding:var(--spacing-md) var(--spacing-lg);background-color:var(--accent-color);color:#fff;border:none;border-radius:var(--radius-md);cursor:pointer;font-size:1rem;font-weight:500;transition:background-color .2s ease;white-space:nowrap}.add-button:hover:not(:disabled){background-color:var(--accent-hover)}.add-button:disabled{background-color:var(--text-muted);cursor:not-allowed}.file-upload-section{text-align:center}.file-input{display:none}.file-upload-label{display:flex;flex-direction:column;align-items:center;gap:var(--spacing-md);padding:var(--spacing-xl);border:2px dashed var(--border-color);border-radius:var(--radius-lg);cursor:pointer;transition:all .2s ease;color:var(--text-secondary)}.file-upload-label:hover{border-color:var(--accent-color);color:var(--accent-color)}.file-upload-notice{margin-top:var(--spacing-md);color:var(--text-muted);font-size:.875rem}.status-message{padding:var(--spacing-md);border-radius:var(--radius-md);margin-bottom:var(--spacing-lg);animation:slideIn .3s ease}.status-loading{background-color:#dbeafe;border:1px solid #bfdbfe;color:#1e40af}.status-success{background-color:#dcfce7;border:1px solid #bbf7d0;color:#166534}.status-error{background-color:#fee2e2;border:1px solid #fecaca;color:#dc2626}@media (prefers-color-scheme: dark){.status-loading{background-color:#1e3a8a;border-color:#1d4ed8;color:#bfdbfe}.status-success{background-color:#14532d;border-color:#16a34a;color:#bbf7d0}.status-error{background-color:#7f1d1d;border-color:#dc2626;color:#fecaca}}.status-content{display:flex;align-items:center;gap:var(--spacing-md)}.status-text{margin:0;font-weight:500}.torrents-section{flex:1}.empty-state{display:flex;align-items:center;justify-content:center;min-height:300px;text-align:center}.empty-state-content h3{margin:0 0 var(--spacing-md) 0;color:var(--text-primary);font-size:1.5rem}.empty-state-content p{margin:0;color:var(--text-secondary)}.torrents-grid{display:grid;gap:var(--spacing-lg);grid-template-columns:repeat(auto-fill,minmax(400px,1fr))}.torrent-card{background-color:var(--background-secondary);border:1px solid var(--border-color);border-radius:var(--radius-lg);padding:var(--spacing-lg);box-shadow:var(--shadow-sm);transition:all .2s ease;position:relative}.torrent-card:hover{box-shadow:var(--shadow-md);transform:translateY(-1px)}.torrent-card-header{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:var(--spacing-lg);gap:var(--spacing-md)}.torrent-title-section{flex:1;min-width:0}.torrent-title{margin:0 0 var(--spacing-sm) 0;font-size:1.125rem;font-weight:600;color:var(--text-primary);line-height:1.4;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}.torrent-actions{position:relative}.torrent-progress-section{margin-bottom:var(--spacing-lg)}.progress-bar-container{display:flex;align-items:center;gap:var(--spacing-md)}.progress-bar{flex:1;height:8px;background-color:var(--background-tertiary);border-radius:var(--radius-sm);overflow:hidden}.progress-fill{height:100%;transition:width .3s ease;border-radius:var(--radius-sm)}.progress-text{font-size:.875rem;font-weight:600;color:var(--text-primary);min-width:48px;text-align:right}.torrent-stats{display:grid;grid-template-columns:repeat(2,1fr);gap:var(--spacing-md)}.stat-item{display:flex;align-items:center;gap:var(--spacing-xs);font-size:.875rem}.stat-icon{color:var(--text-secondary);flex-shrink:0}.stat-value{color:var(--text-primary);font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.action-button{display:flex;align-items:center;gap:var(--spacing-xs);padding:var(--spacing-sm) var(--spacing-md);border:1px solid var(--border-color);border-radius:var(--radius-md);background-color:var(--background-primary);color:var(--text-primary);cursor:pointer;font-size:.875rem;font-weight:500;transition:all .2s ease}.action-button:hover:not(:disabled){background-color:var(--background-secondary);border-color:var(--accent-color)}.action-button.secondary{background-color:var(--background-secondary)}.action-button:disabled{opacity:.5;cursor:not-allowed}.action-menu{position:absolute;top:100%;right:0;margin-top:var(--spacing-xs);background-color:var(--background-primary);border:1px solid var(--border-color);border-radius:var(--radius-md);box-shadow:var(--shadow-lg);z-index:10;min-width:140px;overflow:hidden}.menu-item{display:flex;align-items:center;gap:var(--spacing-xs);width:100%;padding:var(--spacing-sm) var(--spacing-md);border:none;background:transparent;color:var(--text-primary);text-align:left;cursor:pointer;font-size:.875rem;transition:background-color .2s ease}.menu-item:hover:not(:disabled){background-color:var(--background-secondary)}.menu-item.danger{color:var(--error-color)}.menu-item.danger:hover:not(:disabled){background-color:#fee2e2}@media (prefers-color-scheme: dark){.menu-item.danger:hover:not(:disabled){background-color:#450a0a}}.loading-spinner{width:20px;height:20px;border:2px solid var(--border-color);border-top:2px solid var(--accent-color);border-radius:50%;animation:spin 1s linear infinite}.loading-spinner.small{width:16px;height:16px}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes slideIn{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.animate-spin{animation:spin 1s linear infinite}@media (max-width: 768px){.header-main{flex-direction:column;gap:var(--spacing-md);text-align:center}.header-stats{flex-direction:column;gap:var(--spacing-md)}.main-content{padding:var(--spacing-md)}.input-group{flex-direction:column}.torrents-grid,.torrent-stats{grid-template-columns:1fr}.stat-group{justify-content:center}}@media (max-width: 480px){.torrent-card-header{flex-direction:column;align-items:stretch}.torrent-actions{align-self:flex-end}.progress-bar-container{flex-direction:column;gap:var(--spacing-sm)}.progress-text{text-align:center}}