Mini Shell
Direktori : /home/ukubnwwt/ |
|
Current File : /home/ukubnwwt/uviewerdownload |
<!-- uviewerdownload.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Download UViewer</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Inter:400,500,600,700&display=swap">
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/1.10.0/axios.min.js" integrity="sha512-WkZrEcQ5LMyNy6Y2PQf+Tu3vMcsmKKRKuPXtJSTHQJ3mpuvLRlA5dlDDhrrcXfyWr6Z/y3wIMfjfqVFO/gDZYQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<style>
body {
font-family: 'Inter', sans-serif;
margin: 0;
padding: 0;
background: #f8fafc;
}
.container {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
min-height: 100vh;
padding: 1rem;
}
.download-message {
background: #e0f2fe;
color: #0369a1;
padding: 1rem 1.5rem;
border-radius: 0.5rem;
margin-bottom: 2rem;
font-size: 1.125rem;
}
.hidden-link {
display: none;
}
</style>
</head>
<body>
<div class="container">
<div class="download-message">
Please create an account or log in to download UViewer
</div>
<div id="app"></div>
<!-- Hidden download link -->
<a id="uviewerDownloadLink" class="hidden-link" href="https://ukubona.cloud/viewers/UViewer_Installer.exe" download></a>
</div>
<script type="module">
import { createApp, ref, reactive, computed } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js';
const app = {
setup() {
const isLogin = ref(true);
const message = ref('');
const loading = ref(false);
const form = reactive({ email: '', password: '', name: '' });
const confirmPassword = ref('');
const showPassword = ref(false);
const error = ref('');
const baseURL = 'https://backend.ukubona.cloud/';
const deviceID = crypto.randomUUID();
const passwordMismatch = computed(() => isLogin.value ? false : form.password !== confirmPassword.value);
const clearForm = () => {
form.email = '';
form.password = '';
form.name = '';
confirmPassword.value = '';
error.value = '';
};
const saveAccessToken = (token) => {
sessionStorage.setItem('access_token', token);
setTimeout(() => sessionStorage.removeItem('access_token'), 15 * 60 * 1000); // Clear in 15 mins
};
const triggerDownload = () => {
const link = document.getElementById('uviewerDownloadLink');
if (link) link.click();
};
const validateAndDownload = async () => {
const token = sessionStorage.getItem('access_token');
if (!token) return;
try {
const res = await axios.get(baseURL + 'accounts/userdata', {
headers: {
Authorization: `Bearer ${token}`,
'Device-ID': deviceID
}
});
if (res.status === 200) {
triggerDownload();
}
} catch (err) {
error.value = 'Access expired or invalid.';
sessionStorage.removeItem('access_token');
}
};
const handleSubmit = async () => {
error.value = '';
if (!form.email || !form.password || (!isLogin.value && !form.name)) {
error.value = 'All fields are required';
return;
}
if (!isLogin.value && passwordMismatch.value) {
error.value = 'Passwords do not match';
return;
}
loading.value = true;
try {
if (isLogin.value) {
const res = await axios.post(baseURL + 'accounts/token/', {
email: form.email,
password: form.password
}, {
headers: { 'Device-ID': deviceID }
});
saveAccessToken(res.data.access);
await validateAndDownload();
} else {
await axios.post(baseURL + 'accounts/user-create/', {
email: form.email,
password: form.password,
name: form.name
}, {
headers: { 'Device-ID': deviceID }
});
isLogin.value = true;
clearForm();
message.value = 'Signup successful. Please log in to continue.';
}
} catch (err) {
error.value = err?.response?.data?.detail || 'Something went wrong.';
} finally {
loading.value = false;
}
};
return {
isLogin,
message,
loading,
form,
confirmPassword,
showPassword,
passwordMismatch,
error,
handleSubmit
};
},
template: `
<div class="card">
<h2>{{ isLogin ? 'Login' : 'Sign Up' }}</h2>
<p v-if="message" style="color: green">{{ message }}</p>
<form @submit.prevent="handleSubmit">
<div v-if="!isLogin">
<input v-model="form.name" placeholder="Full Name" required />
</div>
<input v-model="form.email" placeholder="Email" type="email" required />
<input :type="showPassword ? 'text' : 'password'" v-model="form.password" placeholder="Password" required />
<div v-if="!isLogin">
<input :type="showPassword ? 'text' : 'password'" v-model="confirmPassword" placeholder="Confirm Password" required />
<p v-if="passwordMismatch" style="color:red">Passwords do not match</p>
</div>
<label>
<input type="checkbox" v-model="showPassword" /> Show Password
</label>
<button type="submit" :disabled="loading">{{ loading ? 'Processing...' : (isLogin ? 'Login' : 'Sign Up') }}</button>
<p v-if="error" style="color:red">{{ error }}</p>
</form>
<button @click="isLogin = !isLogin" style="margin-top: 1rem">
{{ isLogin ? 'Create an account' : 'Already have an account? Login' }}
</button>
</div>
`
};
createApp(app).mount('#app');
</script>
</body>
</html>