File size: 6,140 Bytes
0ce04f3
 
06fbe5b
0ce04f3
6e095c8
0ce04f3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6e095c8
 
 
 
0ce04f3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
06fbe5b
 
0ce04f3
 
 
 
 
6e095c8
0ce04f3
 
 
 
 
 
 
 
 
 
06fbe5b
0ce04f3
 
06fbe5b
0ce04f3
06fbe5b
0ce04f3
 
06fbe5b
 
 
 
 
 
 
 
 
 
 
0ce04f3
06fbe5b
 
 
 
 
6e095c8
 
 
 
06fbe5b
6e095c8
 
 
06fbe5b
 
 
 
 
 
 
 
 
 
 
0ce04f3
6e095c8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0ce04f3
06fbe5b
 
 
 
 
 
 
 
0ce04f3
 
 
 
 
 
 
06fbe5b
6e095c8
06fbe5b
 
0ce04f3
6e095c8
 
0ce04f3
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
// app/static/script.js
document.addEventListener('DOMContentLoaded', () => {
    // --- State ---
    let currentFile = null;
    let currentXHR = null;

    // --- DOM Elements ---
    const states = {
        initial: document.getElementById('state-initial'),
        uploading: document.getElementById('state-uploading'),
        complete: document.getElementById('state-complete'),
        error: document.getElementById('state-error'),
    };
    const dropZone = document.getElementById('drop-zone');
    const browseBtn = document.getElementById('browse-btn');
    const fileInput = document.getElementById('file-input');
    const fileNameEl = document.getElementById('file-name');
    const fileSizeEl = document.getElementById('file-size');
    const progressBar = document.getElementById('progress-bar');
    const statusText = document.getElementById('status-text');
    const downloadLink = document.getElementById('download-link');
    const uploadAnotherBtn = document.getElementById('upload-another-btn');
    const errorMessage = document.getElementById('error-message');
    const retryBtn = document.getElementById('retry-btn');
    
    // New elements for copy functionality
    const downloadUrlInput = document.getElementById('download-url-input');
    const copyLinkBtn = document.getElementById('copy-link-btn');

    // --- UI State Management ---
    function switchState(state) {
        Object.values(states).forEach(el => el.classList.remove('active'));
        if (states[state]) {
            states[state].classList.add('active');
        }
    }

    // --- Event Listeners ---
    browseBtn.addEventListener('click', () => fileInput.click());
    fileInput.addEventListener('change', handleFileSelect);
    
    dropZone.addEventListener('dragover', (e) => {
        e.preventDefault();
        dropZone.classList.add('drag-over');
    });
    dropZone.addEventListener('dragleave', () => dropZone.classList.remove('drag-over'));
    dropZone.addEventListener('drop', (e) => {
        e.preventDefault();
        dropZone.classList.remove('drag-over');
        if (e.dataTransfer.files.length > 0) {
            handleFileSelect({ target: { files: e.dataTransfer.files } });
        }
    });

    uploadAnotherBtn.addEventListener('click', resetUploader);
    retryBtn.addEventListener('click', resetUploader);
    copyLinkBtn.addEventListener('click', handleCopyLink);

    // --- Core Functions ---
    function handleFileSelect(event) {
        const file = event.target.files[0];
        if (!file) return;
        
        currentFile = file;
        fileNameEl.textContent = file.name;
        fileSizeEl.textContent = formatBytes(file.size);
        
        startUpload(file);
    }

    function startUpload(file) {
        switchState('uploading');
        statusText.textContent = 'Uploading...';
        progressBar.style.width = '0%';

        const formData = new FormData();
        formData.append('file', file);

        const xhr = new XMLHttpRequest();
        currentXHR = xhr;

        xhr.upload.addEventListener('progress', (event) => {
            if (event.lengthComputable) {
                const percentage = (event.loaded / event.total) * 100;
                progressBar.style.width = `${percentage}%`;
                statusText.textContent = `${formatBytes(event.loaded)} / ${formatBytes(event.total)}`;
            }
        });

        xhr.addEventListener('load', () => {
            if (xhr.status >= 200 && xhr.status < 300) {
                const response = JSON.parse(xhr.responseText);
                
                // Construct the full, absolute URL for sharing
                const fullUrl = `${window.location.origin}${response.download_url}`;
                
                downloadLink.href = response.download_url;
                downloadLink.download = response.filename;
                downloadUrlInput.value = fullUrl;

                switchState('complete');
            } else {
                handleUploadError(xhr);
            }
        });

        xhr.addEventListener('error', () => handleUploadError(xhr));
        xhr.addEventListener('abort', () => console.log('Upload aborted.'));

        xhr.open('POST', '/upload', true);
        xhr.send(formData);
    }
    
    // NEW: Function to handle copying the link
    function handleCopyLink() {
        // Use the modern Navigator Clipboard API
        navigator.clipboard.writeText(downloadUrlInput.value).then(() => {
            // Provide visual feedback
            copyLinkBtn.textContent = 'Copied!';
            copyLinkBtn.classList.add('copied');
            
            // Revert back after a couple of seconds
            setTimeout(() => {
                copyLinkBtn.textContent = 'Copy';
                copyLinkBtn.classList.remove('copied');
            }, 2000);
        }).catch(err => {
            console.error('Failed to copy text: ', err);
            // You could add an error state to the button here if needed
        });
    }

    function handleUploadError(xhr) {
        let message = 'An unknown network error occurred.';
        try {
            const errorData = JSON.parse(xhr.responseText);
            message = errorData.detail || 'Upload failed.';
        } catch (e) {
            if (xhr.statusText) {
                message = xhr.statusText;
            }
        }
        errorMessage.textContent = message;
        switchState('error');
    }

    function resetUploader() {
        if (currentXHR) {
            currentXHR.abort();
            currentXHR = null;
        }
        currentFile = null;
        fileInput.value = '';
        downloadUrlInput.value = ''; // Clear the URL input
        switchState('initial');
    }

    function formatBytes(bytes, decimals = 2) {
        if (bytes === 0) return '0 Bytes';
        const k = 1024;
        const dm = decimals < 0 ? 0 : decimals;
        const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
        const i = Math.floor(Math.log(bytes) / Math.log(k));
        return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
    }

    switchState('initial');
});