forked from spitkov/sxbin
ctrl + v when file modal is open and drag file to instantly upload
This commit is contained in:
parent
fa373d6b46
commit
29e26aa647
12
app.py
12
app.py
@ -668,17 +668,23 @@ def shorten_url():
|
|||||||
return jsonify({'success': False, 'error': 'URL is required'}), 400
|
return jsonify({'success': False, 'error': 'URL is required'}), 400
|
||||||
|
|
||||||
long_url = data['url']
|
long_url = data['url']
|
||||||
|
password = data.get('password') # Get the password if provided
|
||||||
vanity = shortuuid.uuid()[:8]
|
vanity = shortuuid.uuid()[:8]
|
||||||
|
|
||||||
user_id = current_user.id if current_user.is_authenticated else None
|
user_id = current_user.id if current_user.is_authenticated else None
|
||||||
|
|
||||||
db = get_db()
|
db = get_db()
|
||||||
cursor = db.cursor()
|
cursor = db.cursor()
|
||||||
cursor.execute("INSERT INTO content (vanity, type, data, created_at, user_id) VALUES (?, ?, ?, ?, ?)",
|
|
||||||
(vanity, 'url', long_url, datetime.now(), user_id))
|
is_private = 1 if password else 0
|
||||||
|
|
||||||
|
cursor.execute("""
|
||||||
|
INSERT INTO content (vanity, type, data, created_at, user_id, is_private, password)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||||
|
""", (vanity, 'url', long_url, datetime.now(), user_id, is_private, password))
|
||||||
|
|
||||||
db.commit()
|
db.commit()
|
||||||
|
|
||||||
# Return only the vanity code, not the full URL
|
|
||||||
return jsonify({'success': True, 'vanity': vanity}), 200
|
return jsonify({'success': True, 'vanity': vanity}), 200
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("Exception occurred:", str(e))
|
print("Exception occurred:", str(e))
|
||||||
|
@ -66,7 +66,13 @@
|
|||||||
</br>
|
</br>
|
||||||
</br>
|
</br>
|
||||||
</br>
|
</br>
|
||||||
<p>Source code on: </p><a href="https://github.com/realcgcristi/aCloud" target="_blank">GitHub</a> | <a href="https://git.spitkov.hu/cgcristi/aCloud" target="_blank">Spitkov's Git</a>
|
<div class="footer">
|
||||||
|
<p>
|
||||||
|
Source code on: <a href="https://git.spitkov.hu/cgcristi/aCloud" target="_blank">Spitkov's Git</a> |
|
||||||
|
<a href="https://office.bence.lol/form/#/2/form/view/z5Cf3CL6tZtPjzKsbcEPync6JE3iyMl22h6thUQg1a4/" target="_blank">Suggestions & Bugs</a> |
|
||||||
|
<a href="https://office.bence.lol/kanban/#/2/kanban/view/hx6RTcpN0pR7hc1HHkMzG4awMoMdHjR2zbHjG7Xh+wU/embed/" target="_blank">Todo List</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -258,6 +258,40 @@
|
|||||||
.other-links.show {
|
.other-links.show {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.global-drop-area {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
z-index: 9999;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.global-drop-box {
|
||||||
|
border: 3px dashed #4CAF50;
|
||||||
|
border-radius: 20px;
|
||||||
|
padding: 50px;
|
||||||
|
text-align: center;
|
||||||
|
background-color: rgba(0, 0, 0, 0.7);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.instant-upload-result {
|
||||||
|
position: fixed;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
background-color: #2a2a2a;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 10px;
|
||||||
|
z-index: 10000;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@ -329,15 +363,37 @@
|
|||||||
<span class="close" onclick="closeModal('urlModal')">×</span>
|
<span class="close" onclick="closeModal('urlModal')">×</span>
|
||||||
<h2>Shorten URL</h2>
|
<h2>Shorten URL</h2>
|
||||||
<input type="text" id="urlInput" placeholder="Enter URL here...">
|
<input type="text" id="urlInput" placeholder="Enter URL here...">
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" id="urlIsPrivate" name="urlIsPrivate">
|
||||||
|
<label for="urlIsPrivate">Add password protection</label>
|
||||||
|
</div>
|
||||||
|
<div id="urlPasswordField" style="display: none;">
|
||||||
|
<input type="password" id="urlPassword" placeholder="Enter password">
|
||||||
|
</div>
|
||||||
<button onclick="shortenUrl()">Shorten URL</button>
|
<button onclick="shortenUrl()">Shorten URL</button>
|
||||||
<div id="urlResult"></div>
|
<div id="urlResult"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="global-drop-area">
|
||||||
|
<div class="global-drop-box">
|
||||||
|
<h2>Drop file to instantly upload</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="instant-upload-result">
|
||||||
|
<h3>File Uploaded</h3>
|
||||||
|
<p>Direct download URL: <a id="directDownloadUrl" href="#" target="_blank"></a></p>
|
||||||
|
<p>Normal URL: <a id="normalUrl" href="#" target="_blank"></a></p>
|
||||||
|
<button onclick="closeInstantUploadResult()">Close</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<footer class="footer">
|
<footer class="footer">
|
||||||
<p>Source code available on:
|
<p>Source code available on:
|
||||||
<a href="https://github.com/realcgcristi/order" target="_blank">GitHub (not up-to-date)</a> |
|
|
||||||
<a href="https://git.spitkov.hu/cgcristi/aCloud" target="_blank">Spitkov's Git (main)</a>
|
<a href="https://git.spitkov.hu/cgcristi/aCloud" target="_blank">Spitkov's Git (main)</a> |
|
||||||
|
<a href="https://office.bence.lol/form/#/2/form/view/z5Cf3CL6tZtPjzKsbcEPync6JE3iyMl22h6thUQg1a4/" target="_blank">Suggestions & Bugs</a> |
|
||||||
|
<a href="https://office.bence.lol/kanban/#/2/kanban/view/hx6RTcpN0pR7hc1HHkMzG4awMoMdHjR2zbHjG7Xh+wU/embed/" target="_blank">Todo List</a>
|
||||||
</p>
|
</p>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
@ -433,6 +489,10 @@
|
|||||||
document.getElementById('filePasswordField').style.display = this.checked ? 'block' : 'none';
|
document.getElementById('filePasswordField').style.display = this.checked ? 'block' : 'none';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
document.getElementById('urlIsPrivate').addEventListener('change', function() {
|
||||||
|
document.getElementById('urlPasswordField').style.display = this.checked ? 'block' : 'none';
|
||||||
|
});
|
||||||
|
|
||||||
function uploadText() {
|
function uploadText() {
|
||||||
const content = document.getElementById('textContent').value;
|
const content = document.getElementById('textContent').value;
|
||||||
const isPrivate = document.getElementById('isPrivate').checked;
|
const isPrivate = document.getElementById('isPrivate').checked;
|
||||||
@ -608,13 +668,20 @@
|
|||||||
|
|
||||||
function shortenUrl() {
|
function shortenUrl() {
|
||||||
const url = document.getElementById('urlInput').value;
|
const url = document.getElementById('urlInput').value;
|
||||||
|
const isPrivate = document.getElementById('urlIsPrivate').checked;
|
||||||
|
const password = isPrivate ? document.getElementById('urlPassword').value : null;
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
url: url,
|
||||||
|
password: password
|
||||||
|
};
|
||||||
|
|
||||||
fetch('/shorten', {
|
fetch('/shorten', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
body: JSON.stringify({ url: url }),
|
body: JSON.stringify(data),
|
||||||
})
|
})
|
||||||
.then(response => {
|
.then(response => {
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
@ -625,7 +692,11 @@
|
|||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
const shortUrl = `${window.location.origin}/${data.vanity}`;
|
const shortUrl = `${window.location.origin}/${data.vanity}`;
|
||||||
document.getElementById('urlResult').innerHTML = `URL shortened. Access it <a href="${shortUrl}" target="_blank">${shortUrl}</a>`;
|
let resultHtml = `URL shortened. Access it <a href="${shortUrl}" target="_blank">${shortUrl}</a>`;
|
||||||
|
if (isPrivate) {
|
||||||
|
resultHtml += `<br>Password-protected link: <a href="${shortUrl}/${password}" target="_blank">${shortUrl}/${password}</a>`;
|
||||||
|
}
|
||||||
|
document.getElementById('urlResult').innerHTML = resultHtml;
|
||||||
} else {
|
} else {
|
||||||
document.getElementById('urlResult').innerHTML = `Error: ${data.error}`;
|
document.getElementById('urlResult').innerHTML = `Error: ${data.error}`;
|
||||||
}
|
}
|
||||||
@ -635,6 +706,70 @@
|
|||||||
document.getElementById('urlResult').innerHTML = `An error occurred: ${error.message}`;
|
document.getElementById('urlResult').innerHTML = `An error occurred: ${error.message}`;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Global drag and drop
|
||||||
|
document.addEventListener('dragover', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
document.querySelector('.global-drop-area').style.display = 'flex';
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener('dragleave', function(e) {
|
||||||
|
if (e.clientX === 0 || e.clientY === 0) {
|
||||||
|
document.querySelector('.global-drop-area').style.display = 'none';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener('drop', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
document.querySelector('.global-drop-area').style.display = 'none';
|
||||||
|
if (e.dataTransfer.files.length > 0) {
|
||||||
|
instantUploadFile(e.dataTransfer.files[0]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function instantUploadFile(file) {
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('file', file);
|
||||||
|
|
||||||
|
fetch('/upload/file', {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
document.getElementById('directDownloadUrl').href = data.download_url;
|
||||||
|
document.getElementById('directDownloadUrl').textContent = data.download_url;
|
||||||
|
document.getElementById('normalUrl').href = data.url;
|
||||||
|
document.getElementById('normalUrl').textContent = data.url;
|
||||||
|
document.querySelector('.instant-upload-result').style.display = 'block';
|
||||||
|
} else {
|
||||||
|
alert('Error uploading file: ' + data.error);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
alert('An error occurred while uploading the file');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeInstantUploadResult() {
|
||||||
|
document.querySelector('.instant-upload-result').style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Paste functionality for file upload
|
||||||
|
document.addEventListener('paste', function(e) {
|
||||||
|
if (document.getElementById('fileModal').style.display === 'block') {
|
||||||
|
const items = e.clipboardData.items;
|
||||||
|
for (let i = 0; i < items.length; i++) {
|
||||||
|
if (items[i].kind === 'file') {
|
||||||
|
const file = items[i].getAsFile();
|
||||||
|
filesToUpload.push(file);
|
||||||
|
updateSelectedFilesList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -11,12 +11,17 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
flex-direction: column;
|
||||||
align-items: center;
|
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
background-color: #1a1a1a;
|
background-color: #1a1a1a;
|
||||||
color: #f0f0f0;
|
color: #f0f0f0;
|
||||||
}
|
}
|
||||||
|
.content {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
.container {
|
.container {
|
||||||
background-color: #2a2a2a;
|
background-color: #2a2a2a;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
@ -75,27 +80,54 @@
|
|||||||
a:hover {
|
a:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
.back-button {
|
||||||
|
position: absolute;
|
||||||
|
top: 20px;
|
||||||
|
left: 20px;
|
||||||
|
font-size: 24px;
|
||||||
|
color: #4CAF50;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.back-button:hover {
|
||||||
|
color: #45a049;
|
||||||
|
}
|
||||||
|
.footer {
|
||||||
|
text-align: center;
|
||||||
|
padding: 10px;
|
||||||
|
background-color: #2a2a2a;
|
||||||
|
color: #f0f0f0;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<a href="/" class="back-button">←</a>
|
||||||
<h2>Login</h2>
|
<div class="content">
|
||||||
<form method="POST">
|
<div class="container">
|
||||||
<div>
|
<h2>Login</h2>
|
||||||
<label for="username">Username:</label>
|
<form method="POST">
|
||||||
<input type="text" id="username" name="username" required>
|
<div>
|
||||||
</div>
|
<label for="username">Username:</label>
|
||||||
<div>
|
<input type="text" id="username" name="username" required>
|
||||||
<label for="password">Password:</label>
|
</div>
|
||||||
<input type="password" id="password" name="password" required>
|
<div>
|
||||||
</div>
|
<label for="password">Password:</label>
|
||||||
<div class="remember-me">
|
<input type="password" id="password" name="password" required>
|
||||||
<input type="checkbox" id="remember" name="remember">
|
</div>
|
||||||
<label for="remember">Remember me</label>
|
<div class="remember-me">
|
||||||
</div>
|
<input type="checkbox" id="remember" name="remember">
|
||||||
<button type="submit">Login</button>
|
<label for="remember">Remember me</label>
|
||||||
</form>
|
</div>
|
||||||
<p>Don't have an account? <a href="{{ url_for('register') }}">Register here</a></p>
|
<button type="submit">Login</button>
|
||||||
|
</form>
|
||||||
|
<p>Don't have an account? <a href="{{ url_for('register') }}">Register here</a></p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<footer class="footer">
|
||||||
|
<p>
|
||||||
|
Source code: <a href="https://git.spitkov.hu/cgcristi/aCloud" target="_blank">Spitkov's Git</a> |
|
||||||
|
<a href="https://office.bence.lol/form/#/2/form/view/z5Cf3CL6tZtPjzKsbcEPync6JE3iyMl22h6thUQg1a4/" target="_blank">Suggestions & Bugs</a> |
|
||||||
|
<a href="https://office.bence.lol/kanban/#/2/kanban/view/hx6RTcpN0pR7hc1HHkMzG4awMoMdHjR2zbHjG7Xh+wU/embed/" target="_blank">Todo List</a>
|
||||||
|
</p>
|
||||||
|
</footer>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
@ -185,10 +185,25 @@
|
|||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.home-button {
|
||||||
|
position: fixed;
|
||||||
|
top: 20px;
|
||||||
|
left: 20px;
|
||||||
|
font-size: 24px;
|
||||||
|
color: var(--text-color);
|
||||||
|
text-decoration: none;
|
||||||
|
z-index: 1001;
|
||||||
|
}
|
||||||
|
|
||||||
|
.home-button:hover {
|
||||||
|
color: #4CAF50;
|
||||||
|
}
|
||||||
|
|
||||||
{{ css|safe }}
|
{{ css|safe }}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<a href="/" class="home-button">⌂</a>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h2>Content</h2>
|
<h2>Content</h2>
|
||||||
<p>Uploaded by: {{ content.username }}</p>
|
<p>Uploaded by: {{ content.username }}</p>
|
||||||
@ -229,6 +244,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<footer style="text-align: center; margin-top: 20px; padding: 10px; background-color: #2a2a2a; color: #f0f0f0;">
|
||||||
|
<p>
|
||||||
|
Source code: <a href="https://git.spitkov.hu/cgcristi/aCloud" target="_blank">Spitkov's Git</a> |
|
||||||
|
<a href="https://office.bence.lol/form/#/2/form/view/z5Cf3CL6tZtPjzKsbcEPync6JE3iyMl22h6thUQg1a4/" target="_blank">Suggestions & Bugs</a> |
|
||||||
|
<a href="https://office.bence.lol/kanban/#/2/kanban/view/hx6RTcpN0pR7hc1HHkMzG4awMoMdHjR2zbHjG7Xh+wU/embed/" target="_blank">Todo List</a>
|
||||||
|
</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const rawContent = {{ raw_content|tojson }};
|
const rawContent = {{ raw_content|tojson }};
|
||||||
|
|
||||||
|
@ -11,12 +11,17 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
flex-direction: column;
|
||||||
align-items: center;
|
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
background-color: #1a1a1a;
|
background-color: #1a1a1a;
|
||||||
color: #f0f0f0;
|
color: #f0f0f0;
|
||||||
}
|
}
|
||||||
|
.content {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
.container {
|
.container {
|
||||||
background-color: #2a2a2a;
|
background-color: #2a2a2a;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
@ -67,23 +72,50 @@
|
|||||||
a:hover {
|
a:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
.back-button {
|
||||||
|
position: absolute;
|
||||||
|
top: 20px;
|
||||||
|
left: 20px;
|
||||||
|
font-size: 24px;
|
||||||
|
color: #4CAF50;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.back-button:hover {
|
||||||
|
color: #45a049;
|
||||||
|
}
|
||||||
|
.footer {
|
||||||
|
text-align: center;
|
||||||
|
padding: 10px;
|
||||||
|
background-color: #2a2a2a;
|
||||||
|
color: #f0f0f0;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<a href="/" class="back-button">←</a>
|
||||||
<h2>Register</h2>
|
<div class="content">
|
||||||
<form method="POST">
|
<div class="container">
|
||||||
<div>
|
<h2>Register</h2>
|
||||||
<label for="username">Username:</label>
|
<form method="POST">
|
||||||
<input type="text" id="username" name="username" required>
|
<div>
|
||||||
</div>
|
<label for="username">Username:</label>
|
||||||
<div>
|
<input type="text" id="username" name="username" required>
|
||||||
<label for="password">Password:</label>
|
</div>
|
||||||
<input type="password" id="password" name="password" required>
|
<div>
|
||||||
</div>
|
<label for="password">Password:</label>
|
||||||
<button type="submit">Register</button>
|
<input type="password" id="password" name="password" required>
|
||||||
</form>
|
</div>
|
||||||
<p>Already have an account? <a href="{{ url_for('login') }}">Login here</a></p>
|
<button type="submit">Register</button>
|
||||||
|
</form>
|
||||||
|
<p>Already have an account? <a href="{{ url_for('login') }}">Login here</a></p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<footer class="footer">
|
||||||
|
<p>
|
||||||
|
Source code: <a href="https://git.spitkov.hu/cgcristi/aCloud" target="_blank">Spitkov's Git</a> |
|
||||||
|
<a href="https://office.bence.lol/form/#/2/form/view/z5Cf3CL6tZtPjzKsbcEPync6JE3iyMl22h6thUQg1a4/" target="_blank">Suggestions & Bugs</a> |
|
||||||
|
<a href="https://office.bence.lol/kanban/#/2/kanban/view/hx6RTcpN0pR7hc1HHkMzG4awMoMdHjR2zbHjG7Xh+wU/embed/" target="_blank">Todo List</a>
|
||||||
|
</p>
|
||||||
|
</footer>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
Loading…
Reference in New Issue
Block a user