Final push for project

Change-Id: I9103078156eca93df2482b9fe3854d9301bb98b3
diff --git a/frontend/my-app/src/pages/Home.jsx b/frontend/my-app/src/pages/Home.jsx
index 6bca4b8..e2f7f8e 100644
--- a/frontend/my-app/src/pages/Home.jsx
+++ b/frontend/my-app/src/pages/Home.jsx
@@ -1,12 +1,10 @@
 import React, { useState, useEffect } from 'react';
 import {
   Box, Container, Typography, Paper,
-  List, ListItem, ListItemText, Chip, Stack, CircularProgress, Alert
+  List, ListItem, ListItemText, Chip, Stack, CircularProgress, Alert, Button
 } from '@mui/material';
 import { Link } from 'react-router-dom'; // 假设你已经配置了 React Router
 
-// import '../styles/base/base.css'; // ✅ 引入统一样式 - 我们将尝试用 sx prop 替代
-
 // 模拟从API获取数据
 const fetchTorrents = () => {
   return new Promise((resolve) => {
@@ -63,7 +61,7 @@
 
   return (
     <Box sx={{ minHeight: '100vh', py: 4, background: 'linear-gradient(135deg, #2c3e50, #4ca1af)', color: 'white' }}>
-      <Container maxWidth="md" sx={{ position: 'relative', zIndex: 10 }}> {/* Changed to md for wider content */}
+      <Container maxWidth="md" sx={{ position: 'relative', zIndex: 10 }}>
         <Typography variant="h4" sx={{ textAlign: 'center', mb: 3, fontWeight: 'bold' }}>
           🌐 首页 · Mini-Tracker
         </Typography>
@@ -90,36 +88,41 @@
                   key={torrent.id}
                   component={Link} // react-router-dom Link
                   to={`/detail/${torrent.id}`} // 假设的详情页路由
-                  sx={{ 
-                    color: 'white', 
+                  sx={{
+                    color: 'white',
                     textDecoration: 'none',
-                    mb: 1.5, // 增加列表项间距
-                    p: 1.5, // 增加列表项内边距
+                    mb: 1.5,
+                    p: 1.5,
                     borderBottom: '1px solid rgba(255, 255, 255, 0.1)',
                     '&:last-child': {
-                        borderBottom: 'none' // 移除最后一个元素的边框
+                      borderBottom: 'none'
                     },
-                    display: 'flex', // 确保内部元素正确对齐
-                    flexDirection: { xs: 'column', sm: 'row' }, // 响应式布局
+                    display: 'flex',
+                    flexDirection: { xs: 'column', sm: 'row' },
                     alignItems: { xs: 'flex-start', sm: 'center' }
                   }}
-                  divider={false} // 使用自定义边框代替
+                  divider={false}
                 >
                   <ListItemText
                     primary={torrent.title}
                     secondary={`大小: ${torrent.size} · 上传者: ${torrent.uploader}`}
-                    primaryTypographyProps={{ variant: 'h6', component: 'div', sx: { mb: 0.5, color: '#f5f5f5', fontWeight: 500 } }}
+                    primaryTypographyProps={{
+                      variant: 'h6',
+                      component: 'div',
+                      sx: { mb: 0.5, color: '#f5f5f5', fontWeight: 500 }
+                    }}
                     secondaryTypographyProps={{ sx: { color: '#bbb', fontSize: '0.85rem' } }}
-                    sx={{ flexGrow: 1, mb: { xs: 1, sm: 0 }, mr: { sm: 2 } }} // 响应式边距
+                    sx={{ flexGrow: 1, mb: { xs: 1, sm: 0 }, mr: { sm: 2 } }}
                   />
-                  <Stack direction="row" spacing={1} sx={{ flexWrap: 'wrap', gap: 0.5 }}> {/* 允许标签换行 */}
+
+                  <Stack direction="row" spacing={1} sx={{ flexWrap: 'wrap', gap: 0.5 }}>
                     {torrent.tags.map(tag => (
                       <Chip
                         key={tag}
                         label={tag}
                         size="small"
-                        sx={{ 
-                          backgroundColor: 'rgba(255, 255, 255, 0.2)', // upload-chip 样式
+                        sx={{
+                          backgroundColor: 'rgba(255, 255, 255, 0.2)',
                           color: 'white',
                           cursor: 'pointer',
                           '&:hover': {
@@ -129,6 +132,29 @@
                       />
                     ))}
                   </Stack>
+
+                  {/* ——— 在此处添加“下载”按钮 —— */}
+                  <Button
+                    variant="outlined"
+                    component="a"
+                    href={`http://localhost:8080/api/downloads/${torrent.id}/${encodeURIComponent(torrent.title)}.torrent`}
+                    download={`${torrent.title}.torrent`}
+                    sx={{
+                      ml: { xs: 0, sm: 2 }, // 小屏幕时居中;大屏幕时与右边距留空
+                      mt: { xs: 1, sm: 0 }, // 小屏时在下方,留一点间距
+                      color: '#4caf50',
+                      borderColor: '#4caf50',
+                      fontSize: '0.85rem',
+                      '&:hover': {
+                        backgroundColor: 'rgba(76, 175, 80, 0.15)',
+                        borderColor: '#388e3c'
+                      }
+                    }}
+                  >
+                    下载
+                  </Button>
+                  {/* ——— 下载按钮结束 ——— */}
+
                 </ListItem>
               ))}
             </List>
@@ -136,7 +162,7 @@
         </Paper>
       </Container>
 
-      {/* 背景泡泡动画复用 - 这些类名 (.bubbles, .bubble) 和 @keyframes rise 应该在全局CSS或者下面的 <style> 标签中定义 */}
+      {/* 背景泡泡动画复用 */}
       <Box className="bubbles" sx={{
          pointerEvents: 'none',
          position: 'fixed',
@@ -145,7 +171,7 @@
          width: '100%',
          height: '100%',
          overflow: 'hidden',
-         zIndex: 1, 
+         zIndex: 1,
       }}>
         {[...Array(40)].map((_, i) => (
           <Box
@@ -153,48 +179,43 @@
             className="bubble"
             sx={{
               position: 'absolute',
-              bottom: '-150px', // 确保从屏幕外开始
-              background: `hsla(${Math.random() * 360}, 70%, 80%, 0.15)`, // 增加颜色多样性
+              bottom: '-150px',
+              background: `hsla(${Math.random() * 360}, 70%, 80%, 0.15)`,
               borderRadius: '50%',
               animation: 'rise 20s infinite ease-in',
-              width: `${Math.random() * 25 + 10}px`, // 调整大小范围
+              width: `${Math.random() * 25 + 10}px`,
               height: `${Math.random() * 25 + 10}px`,
               left: `${Math.random() * 100}%`,
-              animationDuration: `${15 + Math.random() * 20}s`, // 调整动画时长
-              animationDelay: `${Math.random() * 10}s`, // 调整动画延迟
-              opacity: 0, // 初始透明
+              animationDuration: `${15 + Math.random() * 20}s`,
+              animationDelay: `${Math.random() * 10}s`,
+              opacity: 0,
             }}
           />
         ))}
       </Box>
-      {/* 定义动画和其他全局可能需要的样式 */}
       <style>
         {`
-          body { /* 基本重置 */
+          body {
             margin: 0;
-            font-family: 'Roboto', sans-serif; /* 确保字体一致 */
+            font-family: 'Roboto', sans-serif;
           }
 
           @keyframes rise {
             0% {
               transform: translateY(0) scale(0.8);
-              opacity: 0; /* 从透明开始 */
+              opacity: 0;
             }
             10% {
-                opacity: 1; /* 渐显 */
+              opacity: 1;
             }
             90% {
-                opacity: 1; /* 保持可见 */
+              opacity: 1;
             }
             100% {
-              transform: translateY(-130vh) scale(0.3); /* 飘得更高更小 */
-              opacity: 0; /* 渐隐 */
+              transform: translateY(-130vh) scale(0.3);
+              opacity: 0;
             }
           }
-
-          /* 如果 .bubbles 和 .bubble 样式没有在 sx 中完全覆盖,可以在这里补充 */
-          /* .bubbles { ... } */
-          /* .bubble { ... } */
         `}
       </style>
     </Box>
@@ -202,4 +223,3 @@
 }
 
 export default Home;
-