general improvements
This commit is contained in:
13
.dockerignore
Normal file
13
.dockerignore
Normal file
@@ -0,0 +1,13 @@
|
||||
/credentials.json
|
||||
/test.py
|
||||
/venv
|
||||
/downloads/
|
||||
/creds/
|
||||
/Test.py
|
||||
/prgs/
|
||||
/flask_server.log
|
||||
/routes/__pycache__/
|
||||
/routes/utils/__pycache__/
|
||||
/test.sh
|
||||
/__pycache__/
|
||||
/Dockerfile
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -9,3 +9,4 @@
|
||||
routes/__pycache__/
|
||||
routes/utils/__pycache__/
|
||||
test.sh
|
||||
__pycache__/
|
||||
|
||||
23
Dockerfile
Normal file
23
Dockerfile
Normal file
@@ -0,0 +1,23 @@
|
||||
# Use an official Python runtime as a parent image
|
||||
FROM python:3.12-slim
|
||||
|
||||
# Set the working directory in the container
|
||||
WORKDIR /app
|
||||
|
||||
# Install git
|
||||
RUN apt-get update && apt-get install -y git
|
||||
|
||||
# Copy the requirements file into the container
|
||||
COPY requirements.txt .
|
||||
|
||||
# Install any needed packages specified in requirements.txt
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# Copy the current directory contents into the container at /app
|
||||
COPY . .
|
||||
|
||||
# Make port 5000 available to the world outside this container
|
||||
EXPOSE 7171
|
||||
|
||||
# Run app.py when the container launches
|
||||
CMD ["python", "app.py"]
|
||||
9
app.py
9
app.py
@@ -46,6 +46,11 @@ def create_app():
|
||||
def serve_static(path):
|
||||
return send_from_directory('static', path)
|
||||
|
||||
# Serve favicon.ico from the same directory as index.html (templates)
|
||||
@app.route('/favicon.ico')
|
||||
def serve_favicon():
|
||||
return send_from_directory('templates', 'favicon.ico')
|
||||
|
||||
# Add request logging middleware
|
||||
@app.before_request
|
||||
def log_request():
|
||||
@@ -72,6 +77,6 @@ if __name__ == '__main__':
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
app = create_app()
|
||||
logging.info("Starting Flask server on port 5000")
|
||||
logging.info("Starting Flask server on port 7171")
|
||||
from waitress import serve
|
||||
serve(app, host='0.0.0.0', port=5000)
|
||||
serve(app, host='0.0.0.0', port=7171)
|
||||
@@ -142,10 +142,6 @@ body {
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
|
||||
.settings-icon:hover {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
@@ -368,43 +364,61 @@ input:checked + .slider:before {
|
||||
}
|
||||
/* Add these styles to your existing CSS */
|
||||
|
||||
/* Download Queue styles */
|
||||
#downloadQueue {
|
||||
#downloadQueue.sidebar {
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
top: 0;
|
||||
right: -350px;
|
||||
width: 350px;
|
||||
height: 100vh;
|
||||
background: #181818;
|
||||
border-radius: 8px;
|
||||
padding: 15px;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
|
||||
transform: translateX(120%);
|
||||
transition: transform 0.3s ease;
|
||||
z-index: 1002;
|
||||
padding: 20px;
|
||||
transition: right 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
z-index: 1001;
|
||||
box-shadow: -20px 0 30px rgba(0,0,0,0.4);
|
||||
}
|
||||
|
||||
#downloadQueue.active {
|
||||
transform: translateX(0);
|
||||
#downloadQueue.sidebar.active {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.queue-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 15px;
|
||||
padding-bottom: 15px;
|
||||
border-bottom: 1px solid #2a2a2a;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.queue-title {
|
||||
font-size: 18px;
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.queue-item .title {
|
||||
font-size: 14px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.queue-item .log {
|
||||
font-size: 12px;
|
||||
color: #b3b3b3;
|
||||
}
|
||||
|
||||
.queue-close {
|
||||
background: none;
|
||||
border: none;
|
||||
color: #b3b3b3;
|
||||
cursor: pointer;
|
||||
padding: 5px;
|
||||
background: #2a2a2a;
|
||||
border-radius: 50%;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
.queue-close:hover {
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
#queueItems {
|
||||
@@ -412,12 +426,29 @@ input:checked + .slider:before {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
#queueItems::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
#queueItems::-webkit-scrollbar-track {
|
||||
background: #181818;
|
||||
}
|
||||
|
||||
#queueItems::-webkit-scrollbar-thumb {
|
||||
background: #2a2a2a;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.queue-item {
|
||||
background: #2a2a2a;
|
||||
padding: 12px;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 6px;
|
||||
transition: transform 0.2s ease;
|
||||
padding: 15px;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 15px;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
.queue-item:hover {
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
.queue-item .title {
|
||||
@@ -982,4 +1013,62 @@ html {
|
||||
.sidebar.active {
|
||||
box-shadow: 0 0 30px rgba(0,0,0,0.4);
|
||||
}
|
||||
}
|
||||
|
||||
.retry-btn {
|
||||
padding: 4px 12px;
|
||||
margin: 0 8px;
|
||||
background-color: #4CAF50; /* Green color for positive action */
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 0.9em;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
.retry-btn:hover {
|
||||
background-color: #45a049; /* Darker green on hover */
|
||||
}
|
||||
|
||||
.retry-btn:active {
|
||||
background-color: #3d8b40;
|
||||
transform: translateY(1px);
|
||||
}
|
||||
|
||||
/* Close button with matching size */
|
||||
.close-btn {
|
||||
padding: 4px 12px; /* Match the retry button's padding */
|
||||
margin: 0 8px; /* Match the retry button's margin */
|
||||
background-color: #ff4444;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 0.9em; /* Match the retry button's font size */
|
||||
transition: background-color 0.3s ease;
|
||||
line-height: 1; /* Ensure the "×" is vertically centered */
|
||||
}
|
||||
|
||||
.close-btn:hover {
|
||||
background-color: #cc0000;
|
||||
}
|
||||
|
||||
.close-btn:active {
|
||||
background-color: #b30000;
|
||||
transform: translateY(1px);
|
||||
}
|
||||
|
||||
.settings-icon img,
|
||||
.queue-icon img {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
vertical-align: middle;
|
||||
filter: invert(1); /* Makes icons white */
|
||||
}
|
||||
|
||||
/* Optional: Add hover effects */
|
||||
.settings-icon:hover img,
|
||||
.queue-icon:hover img {
|
||||
opacity: 0.8;
|
||||
}
|
||||
7
static/images/queue.svg
Normal file
7
static/images/queue.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<rect x="43.93" y="68.27" width="36.07" height="7.99" rx="2" ry="2"/>
|
||||
<path d="M33.82 76.26h-4a2 2 0 0 1-2-2v-4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v4a1.9 1.9 0 0 1-2 2zm0-17.85h-4a2 2 0 0 1-2-2v-4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v4a1.9 1.9 0 0 1-2 2z"/>
|
||||
<rect x="43.93" y="50.42" width="36.07" height="7.99" rx="2" ry="2"/>
|
||||
<rect x="49.92" y="32.57" width="30.08" height="7.99" rx="2" ry="2"/>
|
||||
<path d="M47.55 26.33l-2.12-2.12a1.44 1.44 0 0 0-2.12 0L30.08 37.32l-5.37-5.24a1.44 1.44 0 0 0-2.12 0L20.47 34.2a1.44 1.44 0 0 0 0 2.12l7.36 7.36a3 3 0 0 0 4.24 0L47.55 28.46a1.69 1.69 0 0 0 0-2.13z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 666 B |
3
static/images/settings.svg
Normal file
3
static/images/settings.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 48 48">
|
||||
<path d="M38.86 25.95c.08-.64.14-1.29.14-1.95s-.06-1.31-.14-1.95l4.23-3.31c.38-.3.49-.84.24-1.28l-4-6.93c-.25-.43-.77-.61-1.22-.43l-4.98 2.01c-1.03-.79-2.16-1.46-3.38-1.97L29 4.84c-.09-.47-.5-.84-1-.84h-8c-.5 0-.91.37-.99.84l-.75 5.3a14.8 14.8 0 0 0-3.38 1.97L9.9 10.1a1 1 0 0 0-1.22.43l-4 6.93c-.25.43-.14.97.24 1.28l4.22 3.31C9.06 22.69 9 23.34 9 24s.06 1.31.14 1.95l-4.22 3.31c-.38.3-.49.84-.24 1.28l4 6.93c.25.43.77.61 1.22.43l4.98-2.01c1.03.79 2.16 1.46 3.38 1.97l.75 5.3c.08.47.49.84.99.84h8c.5 0 .91-.37.99-.84l.75-5.3a14.8 14.8 0 0 0 3.38-1.97l4.98 2.01a1 1 0 0 0 1.22-.43l4-6.93c.25-.43.14-.97-.24-1.28l-4.22-3.31zM24 31c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 778 B |
@@ -48,9 +48,16 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
// Settings functionality
|
||||
settingsIcon.addEventListener('click', () => {
|
||||
sidebar.classList.add('active');
|
||||
loadCredentials(currentService);
|
||||
updateFormFields();
|
||||
if (sidebar.classList.contains('active')) {
|
||||
// Collapse sidebar if already expanded
|
||||
sidebar.classList.remove('active');
|
||||
resetForm();
|
||||
} else {
|
||||
// Expand sidebar and load credentials
|
||||
sidebar.classList.add('active');
|
||||
loadCredentials(currentService);
|
||||
updateFormFields();
|
||||
}
|
||||
});
|
||||
|
||||
closeSidebar.addEventListener('click', () => {
|
||||
@@ -151,10 +158,6 @@ async function updateAccountSelectors() {
|
||||
function toggleDownloadQueue() {
|
||||
const queueSidebar = document.getElementById('downloadQueue');
|
||||
queueSidebar.classList.toggle('active');
|
||||
|
||||
// Update button state
|
||||
const queueIcon = document.getElementById('queueIcon');
|
||||
queueIcon.textContent = queueSidebar.classList.contains('active') ? '📭' : '📥';
|
||||
}
|
||||
|
||||
function performSearch() {
|
||||
|
||||
BIN
templates/favicon.ico
Normal file
BIN
templates/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Spotify Search</title>
|
||||
<title>Spotizerr</title>
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
|
||||
</head>
|
||||
<body>
|
||||
@@ -58,7 +58,9 @@
|
||||
|
||||
<div class="container">
|
||||
<div class="search-header">
|
||||
<button id="settingsIcon" class="settings-icon">⚙️</button>
|
||||
<button id="settingsIcon" class="settings-icon">
|
||||
<img src="{{ url_for('static', filename='images/settings.svg') }}" alt="Settings">
|
||||
</button>
|
||||
<input type="text" class="search-input" placeholder="Search tracks, albums, or playlists..." id="searchInput">
|
||||
<select class="search-type" id="searchType">
|
||||
<option value="track">Tracks</option>
|
||||
@@ -66,7 +68,9 @@
|
||||
<option value="playlist">Playlists</option>
|
||||
</select>
|
||||
<button class="search-button" id="searchButton">Search</button>
|
||||
<button id="queueIcon" class="queue-icon" onclick="toggleDownloadQueue()">📥</button>
|
||||
<button id="queueIcon" class="queue-icon" onclick="toggleDownloadQueue()">
|
||||
<img src="{{ url_for('static', filename='images/queue.svg') }}" alt="Download Queue">
|
||||
</button>
|
||||
</div>
|
||||
<div id="resultsContainer" class="results-grid"></div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user