mirror of
https://github.com/zarfadev/MobaXterm-Keygen.git
synced 2026-08-29 00:00:49 +00:00
v3.0
Refined UI using a completely reconstructed Glassmorphism aesthetic and modern UX updates. Updated support for up to 26.3.
This commit is contained in:
@@ -1,145 +1,98 @@
|
|||||||
# MobaXterm Keygen & Customizer 🚀
|
<div align="center">
|
||||||
|
<img src="https://i.imgur.com/FtcF9ZP.png" alt="MobaXterm Keygen Logo" width="120" />
|
||||||
|
<h1>MobaXterm Keygen & Customizer 🚀</h1>
|
||||||
|
<p><strong>Fast, and secure license generator and customizer.</strong></p>
|
||||||
|
|
||||||

|
<p>
|
||||||

|
<a href="#"><img src="https://img.shields.io/badge/License-MIT-blue.svg?style=for-the-badge" alt="License" /></a>
|
||||||

|
<a href="#"><img src="https://img.shields.io/badge/Version-v3.0-green.svg?style=for-the-badge" alt="Version" /></a>
|
||||||
|
<a href="#"><img src="https://img.shields.io/badge/Compatible-v20.X%20|%20v26.2%20|%20v26.3-orange?style=for-the-badge" alt="Compatibility" /></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
> ⭐ **Please star this repository if you find it helpful!** ⭐
|
<p><em>⭐ Please star this repository if you find it helpful! ⭐</em></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
## Overview
|
---
|
||||||
|
|
||||||
A modern, user-friendly web tool for generating activation keys and customizing MobaXterm, the ultimate terminal emulator for Windows with an integrated X11 server, SSH client, and comprehensive network toolset.
|
## 🔥 Overview
|
||||||
|
|
||||||
## Features
|
A modern, user-friendly, and beautifully designed web tool for generating activation keys and customizing **MobaXterm**—the ultimate terminal emulator for Windows with an integrated X11 server, SSH client, and comprehensive network toolset.
|
||||||
|
|
||||||
- **✨ Clean, Modern UI** - Responsive design optimized for both desktop and mobile
|
All processes run **100% locally** in your browser, ensuring maximum privacy and security.
|
||||||
- **🌓 Dark/Light Mode** - Toggle between themes with a click
|
|
||||||
- **🔒 Multiple Editions Support** - Generate keys for different MobaXterm editions
|
|
||||||
- **👥 Custom User Count** - Specify the number of concurrent users
|
|
||||||
- **💾 One-Click Downloads** - Instantly download your custom activation file
|
|
||||||
- **🔧 Complete Customizer** - Create personalized settings without the official customizer tool
|
|
||||||
- **🖼️ Custom Logo Support** - Replace the default MobaXterm logo with your own
|
|
||||||
- **📑 Bookmarks Manager** - Pre-define SSH, FTP, and other connection profiles
|
|
||||||
- **🔌 Plugin Integration** - Include plugins in your custom configuration
|
|
||||||
|
|
||||||
## Compatibility
|
## ✨ Key Features
|
||||||
|
|
||||||
- Works with **MobaXterm versions 20.X, 25.4, and 26.0**
|
- **💎 Premium Glassmorphism UI** - Enjoy a sleek, modern, and completely responsive experience.
|
||||||
- Supports both portable and installer editions
|
- **🌓 Adaptive Theme** - Seamless dark and light mode toggle.
|
||||||
|
- **🔒 Multi-Edition Support** - Generate licenses for various MobaXterm editions effortlessly.
|
||||||
|
- **👥 Flexible User Allocation** - Define your own custom concurrent user limit.
|
||||||
|
- **💾 One-Click Downloads** - Get your `.mxtpro` files instantly in a neat package.
|
||||||
|
- **🔧 Built-in Customizer Integration** - No need for the official cli tool; apply advanced setups visually.
|
||||||
|
- **🖼️ Brand Personalization** - Easily switch the default MobaXterm logo with your company's own.
|
||||||
|
- **🔌 Plugins & Bookmarks** - Embed `.mxt3` plugins and predefined SSH/FTP profiles instantly.
|
||||||
|
|
||||||
## How to Use
|
## 🚀 Compatibility
|
||||||
|
|
||||||
### Key Generator
|
- Official support tested extensively with MobaXterm versions **20.X, 26.2, and 26.3**.
|
||||||
|
- Compatible with both **Portable** and **Installer (Desktop)** editions.
|
||||||
|
|
||||||
1. **Visit the Generator**: Go to the [MobaXterm Key Generator](https://moba-xterm-keygen.vercel.app/)
|
## 📖 How to Use
|
||||||
2. **Fill in the Form**:
|
|
||||||
- Select the desired MobaXterm edition
|
### 1️⃣ The Key Generator
|
||||||
- Enter a username (letters only)
|
|
||||||
- Choose your MobaXterm version (20.X or 26.X)
|
1. **Access the Generator**: Open the [MobaXterm Key Generator](https://moba-xterm-keygen.vercel.app/) web application.
|
||||||
- Specify the number of users
|
2. **Setup your License**:
|
||||||
3. **Download**: Click "Download Key" to get your Custom.mxtpro file
|
- Choose your preferred MobaXterm Edition from the dropdown.
|
||||||
4. **Activate**: Place the generated file in your MobaXterm installation directory:
|
- Enter your username (alphabetical characters only).
|
||||||
```
|
- Input your current target version (e.g., `26.3`).
|
||||||
|
- Define your desired number of users.
|
||||||
|
3. **Generate**: Click the big **"Generate License"** button to start downloading your `Custom.mxtpro` key.
|
||||||
|
4. **Deploy**: Drop this file inside your MobaXterm installation folder:
|
||||||
|
```text
|
||||||
C:\Program Files (x86)\Mobatek\MobaXterm
|
C:\Program Files (x86)\Mobatek\MobaXterm
|
||||||
```
|
```
|
||||||
|
|
||||||
### Customizer
|
### 2️⃣ Advanced: Settings Merger
|
||||||
|
|
||||||
1. **Go to the Customizer Tab** in the web interface
|
If you have personalized MobaXterm preferences (Customizer tweaks, logos, bash profiles):
|
||||||
2. **Configure Your Settings**:
|
|
||||||
- **Banner**: Create a personalized welcome message
|
|
||||||
- **Profile**: Configure a custom bash profile (similar to /etc/profile in Linux)
|
|
||||||
- **Settings**: Toggle MobaXterm features on/off
|
|
||||||
- **Logo**: Upload your custom logo image
|
|
||||||
- **Bookmarks**: Create predefined connections for your users
|
|
||||||
- **Plugins**: Add optional MobaXterm plugins (.mxt3 files)
|
|
||||||
3. **Generate Settings**: Click "Generate Configuration File" to download your settings
|
|
||||||
4. **Apply Settings**: Use either method below to apply your customization
|
|
||||||
|
|
||||||
### Settings Merger
|
1. Switch to the **Settings Merger** tab inside our web app.
|
||||||
|
2. **Export your settings**: Run `.\MobaXterm.exe -customizer` and select the option to export to `MobaXterm customization.custom`.
|
||||||
|
3. **Upload both files**:
|
||||||
|
- The license key file (`Custom.mxtpro`).
|
||||||
|
- The exported configuration file (`MobaXterm customization.custom`).
|
||||||
|
4. Click **Merge Files** to inject everything into a single, unified `Custom.mxtpro` file to deploy normally.
|
||||||
|
|
||||||
1. **Go to the Custom Settings Merger Tab**
|
## 🛠 Troubleshooting
|
||||||
2. **Upload Files**:
|
|
||||||
- Your license key file (Custom.mxtpro)
|
|
||||||
- Your customization file (MobaXterm customization.custom)
|
|
||||||
3. **Merge**: Create a single file with both your license and custom settings
|
|
||||||
4. **Deploy**: Copy the merged Custom.mxtpro to your MobaXterm installation directory
|
|
||||||
|
|
||||||
## Installation Guide
|
<details>
|
||||||
|
<summary><strong>Activation isn't being recognized?</strong></summary>
|
||||||
|
Ensure you are running a supported version range (v20.X, 26.2, or 26.3). Also, make sure the file is strictly named `Custom.mxtpro` without any duplicates like `Custom (1).mxtpro`.
|
||||||
|
</details>
|
||||||
|
|
||||||
### Step 1: Download MobaXterm
|
<details>
|
||||||
Download the latest version from the [official MobaXterm website](https://mobaxterm.mobatek.net/download-home-edition.html).
|
<summary><strong>File generation fails?</strong></summary>
|
||||||
|
Double check that your provided username only encompasses letters. Spaces and unique symbols are currently not supported by the underlying cryptography validation checks.
|
||||||
|
</details>
|
||||||
|
|
||||||
### Step 2: Generate Your Key & Customization
|
## 🔐 Technical & Security Details
|
||||||
Use our tool to:
|
|
||||||
1. Create your activation key
|
|
||||||
2. Customize your settings (optional)
|
|
||||||
3. Merge your license with your customization (optional)
|
|
||||||
|
|
||||||
### Step 3: Activate MobaXterm
|
This tool operates completely **Client-Side** leveraging `Vue.js` and pure DOM manipulations. **Not a single byte of your data or generated licenses travels to any backend server.**
|
||||||
1. Locate your MobaXterm installation folder:
|
|
||||||
- **Default Path**: `C:\Program Files (x86)\Mobatek\MobaXterm`
|
|
||||||
- Or right-click the MobaXterm shortcut and select "Open file location"
|
|
||||||
2. Copy the `Custom.mxtpro` file to this directory
|
|
||||||
3. Start MobaXterm - your license and customizations should now be applied!
|
|
||||||
|
|
||||||
### Alternative Customization Method
|
> **Disclaimer:** This project is provided exclusively for educational concepts and reverse-engineering study cases. For commercial environments, please consider supporting the official developers by purchasing an enterprise license.
|
||||||
|
|
||||||
MobaXterm.exe has a customizer mode that you can access by adding the parameter "-customizer":
|
## 📈 Version History
|
||||||
|
|
||||||
```
|
- **v3.0** - Refined UI using a completely reconstructed Glassmorphism aesthetic and modern UX updates. Updated support for up to `26.3`.
|
||||||
.\MobaXterm.exe -customizer
|
- **v2.7** - Added support for version 26.0
|
||||||
```
|
|
||||||
|
|
||||||
This official tool also allows you to export your settings to a file named "MobaXterm customization.custom". Our web-based customizer provides similar functionality but is accessible directly in your browser.
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
1. **Activation Not Working?**
|
|
||||||
- Verify you're using a compatible version (20.X, 25.4, or 26.0)
|
|
||||||
- Make sure the file is in the correct location
|
|
||||||
- Check that the file is named exactly `Custom.mxtpro`
|
|
||||||
|
|
||||||
2. **Error During Key Generation?**
|
|
||||||
- Ensure all form fields are filled correctly
|
|
||||||
- Username must contain only letters (no spaces, numbers, or special characters)
|
|
||||||
- Try refreshing the page and generating again
|
|
||||||
|
|
||||||
3. **Customization Not Applying?**
|
|
||||||
- Verify that you've merged the customization with your license file
|
|
||||||
- Make sure the merged file is named exactly `Custom.mxtpro`
|
|
||||||
- Try restarting MobaXterm after placing the file in the installation directory
|
|
||||||
|
|
||||||
## Technical Details
|
|
||||||
|
|
||||||
This tool uses client-side processing to generate valid license keys and customization files based on your inputs. Everything is generated directly in your browser - no data is sent to any server, ensuring your privacy and security.
|
|
||||||
|
|
||||||
## Disclaimer
|
|
||||||
|
|
||||||
This tool is provided for educational purposes only. Please support the developers by purchasing a license for commercial use.
|
|
||||||
|
|
||||||
## Development
|
|
||||||
|
|
||||||
### Built With
|
|
||||||
- Vue.js
|
|
||||||
- Tailwind CSS
|
|
||||||
- Modern JavaScript
|
|
||||||
|
|
||||||
### Version History
|
|
||||||
- **v2.7** - Added support for version 26,0
|
|
||||||
- **v2.6** - Added support for version 25.4
|
- **v2.6** - Added support for version 25.4
|
||||||
- **v2.5** - Added support for version 25.3
|
- **v2.5** - Added support for version 25.3
|
||||||
- **v2.4** - Added full MobaXterm customizer functionality
|
- **v2.4** - Brought full MobaXterm customizer functionality
|
||||||
- **v2.3** - Added custom settings merger
|
|
||||||
- **v2.2** - Dark mode and mobile optimization
|
|
||||||
- **v2.1** - Added support for version 25.2
|
|
||||||
- **v2.0** - Major UI redesign
|
- **v2.0** - Major UI redesign
|
||||||
- **v1.0** - Initial release
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Created with ❤️ by Zarfala
|
<div align="center">
|
||||||
|
<strong>Crafted with ❤️ by Zarfala</strong><br>
|
||||||
---
|
<a href="https://github.com/zarfadev/MobaXterm-Keygen">⭐ Star us on GitHub</a>
|
||||||
|
</div>
|
||||||
⭐ [Star this repository on GitHub!](https://github.com/zarfadev/MobaXterm-Keygen) ⭐
|
|
||||||
|
|||||||
+17
-37
@@ -1,19 +1,7 @@
|
|||||||
/*
|
/* VIP Aurora Stripes Background */
|
||||||
NOTE: This is just an experiment and
|
@import url('https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&display=swap');
|
||||||
could use some changes to improve performance:
|
|
||||||
|
|
||||||
https://x.com/actualTimWilson/status/1730753841795158313
|
@keyframes aurora {
|
||||||
|
|
||||||
See a production optimized version here: https://charmui.com
|
|
||||||
*/
|
|
||||||
|
|
||||||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap');
|
|
||||||
|
|
||||||
body {
|
|
||||||
font-family: Inter, sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes jumbo {
|
|
||||||
from {
|
from {
|
||||||
background-position: 50% 50%, 50% 50%;
|
background-position: 50% 50%, 50% 50%;
|
||||||
}
|
}
|
||||||
@@ -22,22 +10,18 @@ body {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* New Styles for Form Isolation */
|
|
||||||
.box-main {
|
.box-main {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
.jumbo {
|
.jumbo {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
inset: 0;
|
||||||
left: 0;
|
width: 100vw;
|
||||||
width: 100%;
|
height: 100vh;
|
||||||
height: 100%;
|
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
}
|
pointer-events: none;
|
||||||
|
|
||||||
.jumbo {
|
|
||||||
--stripes: repeating-linear-gradient(
|
--stripes: repeating-linear-gradient(
|
||||||
100deg,
|
100deg,
|
||||||
#fff 0%,
|
#fff 0%,
|
||||||
@@ -62,15 +46,16 @@ body {
|
|||||||
#5eead4 25%,
|
#5eead4 25%,
|
||||||
#60a5fa 30%
|
#60a5fa 30%
|
||||||
);
|
);
|
||||||
|
|
||||||
|
mask-image: radial-gradient(ellipse at center, black 40%, transparent 80%);
|
||||||
|
-webkit-mask-image: radial-gradient(ellipse at center, black 40%, transparent 80%);
|
||||||
|
|
||||||
background-image: var(--stripes), var(--rainbow);
|
background-image: var(--stripes), var(--rainbow);
|
||||||
background-size: 300%, 200%;
|
background-size: 300%, 200%;
|
||||||
background-position: 50% 50%, 50% 50%;
|
background-position: 50% 50%, 50% 50%;
|
||||||
|
|
||||||
filter: blur(10px) invert(100%);
|
filter: blur(15px) invert(100%);
|
||||||
|
opacity: 0.9;
|
||||||
mask-image: radial-gradient(ellipse at 100% 0%, black 40%, transparent 70%);
|
|
||||||
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.jumbo::after {
|
.jumbo::after {
|
||||||
@@ -79,20 +64,15 @@ body {
|
|||||||
inset: 0;
|
inset: 0;
|
||||||
background-image: var(--stripes), var(--rainbow);
|
background-image: var(--stripes), var(--rainbow);
|
||||||
background-size: 200%, 100%;
|
background-size: 200%, 100%;
|
||||||
animation: jumbo 60s linear infinite;
|
animation: aurora 40s linear infinite;
|
||||||
background-attachment: fixed;
|
|
||||||
mix-blend-mode: difference;
|
mix-blend-mode: difference;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark .jumbo {
|
.dark .jumbo {
|
||||||
background-image: var(--stripesDark), var(--rainbow);
|
background-image: var(--stripesDark), var(--rainbow);
|
||||||
filter: blur(10px) opacity(50%) saturate(200%);
|
filter: blur(15px) opacity(60%) saturate(200%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark .jumbo::after {
|
.dark .jumbo::after {
|
||||||
background-image: var(--stripesDark), var(--rainbow);
|
background-image: var(--stripesDark), var(--rainbow);
|
||||||
}
|
}
|
||||||
|
|
||||||
.bg-white {
|
|
||||||
--tw-bg-opacity: 1;
|
|
||||||
background-color: rgb(255 255 255);
|
|
||||||
}
|
|
||||||
|
|||||||
+547
-183
@@ -1,12 +1,16 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en" class="antialiased">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>MobaXterm Keygen</title>
|
<title>MobaXterm Keygen</title>
|
||||||
<meta name="description" content="Website created with love by Zarfala" />
|
<meta name="description" content="Professional Key Generator for MobaXterm - Designed by Zarfala" />
|
||||||
<link rel="icon" href="https://i.imgur.com/FtcF9ZP.png" />
|
<link rel="icon" href="https://i.imgur.com/FtcF9ZP.png" />
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
||||||
<link href="./css/pure-min.css?=2" rel="stylesheet" />
|
<link href="./css/pure-min.css?=2" rel="stylesheet" />
|
||||||
<link href="./css/style.css" rel="stylesheet" />
|
<link href="./css/style.css" rel="stylesheet" />
|
||||||
<link href="./css/fire.css" rel="stylesheet" />
|
<link href="./css/fire.css" rel="stylesheet" />
|
||||||
@@ -16,261 +20,623 @@
|
|||||||
darkMode: "class",
|
darkMode: "class",
|
||||||
theme: {
|
theme: {
|
||||||
extend: {
|
extend: {
|
||||||
screens: {
|
fontFamily: {
|
||||||
'xs': '475px',
|
sans: ['Outfit', 'sans-serif'],
|
||||||
},
|
},
|
||||||
colors: {
|
colors: {
|
||||||
primary: {
|
primary: {
|
||||||
50: '#eef2ff',
|
50: '#eef2ff',
|
||||||
100: '#e0e7ff',
|
100: '#e0e7ff',
|
||||||
500: '#6366f1',
|
200: '#c3dafe',
|
||||||
600: '#4f46e5',
|
300: '#a3bffa',
|
||||||
700: '#4338ca',
|
400: '#7f9cf5',
|
||||||
|
500: '#667eea',
|
||||||
|
600: '#5a67d8',
|
||||||
|
700: '#4c51bf',
|
||||||
|
800: '#434190',
|
||||||
|
900: '#3c366b',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
animation: {
|
animation: {
|
||||||
'pulse-slow': 'pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite',
|
'blob': 'blob 7s infinite',
|
||||||
|
'fade-in-up': 'fadeInUp 0.8s cubic-bezier(0.16, 1, 0.3, 1) forwards',
|
||||||
|
'float': 'float 6s ease-in-out infinite',
|
||||||
|
},
|
||||||
|
keyframes: {
|
||||||
|
blob: {
|
||||||
|
'0%': { transform: 'translate(0px, 0px) scale(1)' },
|
||||||
|
'33%': { transform: 'translate(30px, -50px) scale(1.1)' },
|
||||||
|
'66%': { transform: 'translate(-20px, 20px) scale(0.9)' },
|
||||||
|
'100%': { transform: 'translate(0px, 0px) scale(1)' },
|
||||||
|
},
|
||||||
|
fadeInUp: {
|
||||||
|
'0%': { opacity: '0', transform: 'translateY(40px)' },
|
||||||
|
'100%': { opacity: '1', transform: 'translateY(0)' },
|
||||||
|
},
|
||||||
|
float: {
|
||||||
|
'0%, 100%': { transform: 'translateY(0)' },
|
||||||
|
'50%': { transform: 'translateY(-10px)' },
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<!-- Preloader style -->
|
|
||||||
<style>
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: 'Outfit', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Custom modern scrollbar */
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background: rgba(156, 163, 175, 0.5);
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: rgba(107, 114, 128, 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Preloader */
|
||||||
#preloader {
|
#preloader {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
inset: 0;
|
||||||
left: 0;
|
background: #f8fafc;
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background: #111;
|
|
||||||
z-index: 9999;
|
z-index: 9999;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
transition: opacity 0.5s ease-in-out, visibility 0.5s ease-in-out;
|
transition: background-color 0.3s, opacity 0.6s cubic-bezier(0.16, 1, 0.3, 1), visibility 0.6s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dark #preloader {
|
||||||
|
background: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
#preloader.fade-out {
|
#preloader.fade-out {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.spinner {
|
.spinner {
|
||||||
width: 60px;
|
width: 60px;
|
||||||
height: 60px;
|
height: 60px;
|
||||||
border: 5px solid rgba(255, 255, 255, 0.3);
|
position: relative;
|
||||||
border-radius: 50%;
|
|
||||||
border-top-color: #6366f1;
|
|
||||||
animation: spin 1s ease-in-out infinite;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.spinner::before,
|
||||||
|
.spinner::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 4px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner::before {
|
||||||
|
border-top-color: #667eea;
|
||||||
|
border-right-color: #667eea;
|
||||||
|
animation: spin 1.5s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner::after {
|
||||||
|
border-bottom-color: #ed64a6;
|
||||||
|
border-left-color: #ed64a6;
|
||||||
|
animation: spin 1s linear infinite reverse;
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes spin {
|
@keyframes spin {
|
||||||
to {
|
100% {
|
||||||
transform: rotate(360deg);
|
transform: rotate(360deg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-hidden {
|
.content-hidden {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: opacity 0.5s ease-in-out, visibility 0.5s ease-in-out;
|
transition: opacity 0.8s ease-in-out, visibility 0.8s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-visible {
|
.content-visible {
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Glass panel effect */
|
||||||
|
.glass-panel {
|
||||||
|
background: rgba(255, 255, 255, 0.85);
|
||||||
|
backdrop-filter: blur(40px);
|
||||||
|
-webkit-backdrop-filter: blur(40px);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.6);
|
||||||
|
box-shadow: 0 20px 40px -10px rgba(0, 0, 0, 0.1), 0 0 0 1px rgba(255, 255, 255, 0.4) inset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .glass-panel {
|
||||||
|
background: rgba(15, 23, 42, 0.75);
|
||||||
|
backdrop-filter: blur(40px);
|
||||||
|
-webkit-backdrop-filter: blur(40px);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
box-shadow: 0 30px 60px -12px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.05) inset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Modern Forms */
|
||||||
|
.input-modern {
|
||||||
|
background: rgba(255, 255, 255, 0.7);
|
||||||
|
border: 2px solid rgba(209, 213, 219, 0.6);
|
||||||
|
color: #1f2937;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-modern:focus {
|
||||||
|
background: #ffffff;
|
||||||
|
border-color: #667eea;
|
||||||
|
box-shadow: 0 0 0 4px rgba(102, 126, 234, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .input-modern {
|
||||||
|
background: rgba(15, 23, 42, 0.7);
|
||||||
|
border: 2px solid rgba(71, 85, 105, 0.6);
|
||||||
|
color: #f8fafc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .input-modern:focus {
|
||||||
|
background: rgba(15, 23, 42, 0.95);
|
||||||
|
border-color: #7f9cf5;
|
||||||
|
box-shadow: 0 0 0 4px rgba(127, 156, 245, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Button Gradient */
|
||||||
|
.btn-gradient {
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
background-size: 200% auto;
|
||||||
|
color: white;
|
||||||
|
transition: 0.5s ease;
|
||||||
|
box-shadow: 0 10px 20px -5px rgba(102, 126, 234, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-gradient:hover {
|
||||||
|
background-position: right center;
|
||||||
|
box-shadow: 0 15px 25px -5px rgba(102, 126, 234, 0.5);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-gradient:active {
|
||||||
|
transform: translateY(1px);
|
||||||
|
box-shadow: 0 5px 10px -5px rgba(102, 126, 234, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Toggle Active Tab */
|
||||||
|
.tab-active {
|
||||||
|
position: relative;
|
||||||
|
color: #667eea;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .tab-active {
|
||||||
|
color: #a3bffa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-active::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
bottom: -2px;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 3px;
|
||||||
|
background: linear-gradient(90deg, #667eea, #ed64a6);
|
||||||
|
border-radius: 3px 3px 0 0;
|
||||||
|
animation: tabSlide 0.3s ease-out forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes tabSlide {
|
||||||
|
from {
|
||||||
|
width: 0;
|
||||||
|
opacity: 0;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
width: 100%;
|
||||||
|
opacity: 1;
|
||||||
|
left: 0;
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
select option {
|
||||||
|
background-color: white;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark select option {
|
||||||
|
background-color: #1e293b;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-gradient-text {
|
||||||
|
background-size: 300%;
|
||||||
|
animation: gradientText 6s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes gradientText {
|
||||||
|
0% { background-position: 0% 50%; }
|
||||||
|
50% { background-position: 100% 50%; }
|
||||||
|
100% { background-position: 0% 50%; }
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<!-- Meta tags for better SEO and sharing -->
|
<!-- Meta tags for better SEO and sharing -->
|
||||||
<meta property="og:title" content="MobaXterm Keygen" />
|
<meta property="og:title" content="MobaXterm Keygen" />
|
||||||
<meta property="og:type" content="website" />
|
<meta property="og:type" content="website" />
|
||||||
<meta property="og:description" content="Website created with love by Zarfala" />
|
<meta property="og:description" content="Professional Key Generator for MobaXterm" />
|
||||||
<meta property="og:image" content="https://i.imgur.com/FtcF9ZP.png" />
|
|
||||||
<meta property="og:site_name" content="MobaXterm Keygen" />
|
<meta property="og:site_name" content="MobaXterm Keygen" />
|
||||||
<meta name="twitter:card" content="summary">
|
<meta name="twitter:card" content="summary">
|
||||||
<meta name="twitter:title" content="MobaXterm Keygen">
|
<meta name="twitter:title" content="MobaXterm Keygen">
|
||||||
<meta name="twitter:description" content="Website created with love by Zarfala">
|
<meta name="twitter:description" content="Professional Key Generator for MobaXterm created by Zarfala">
|
||||||
<meta name="twitter:image" content="https://i.imgur.com/FtcF9ZP.png">
|
<script>
|
||||||
|
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
||||||
|
document.documentElement.classList.add('dark');
|
||||||
|
} else {
|
||||||
|
document.documentElement.classList.remove('dark');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body class="transition-colors duration-300">
|
|
||||||
|
<body class="transition-colors duration-500 bg-slate-50 dark:bg-black font-sans text-slate-800 dark:text-slate-200">
|
||||||
<!-- Preloader -->
|
<!-- Preloader -->
|
||||||
<div id="preloader">
|
<div id="preloader">
|
||||||
<div class="spinner"></div>
|
<div class="spinner"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<main id="main-content" class="content-hidden">
|
<main id="main-content" class="content-hidden antialiased">
|
||||||
<div class="relative flex min-h-screen flex-col items-center justify-center bg-white dark:bg-black transition-colors duration-300 overflow-hidden px-4">
|
<div
|
||||||
<!-- Background effect -->
|
class="relative flex min-h-screen flex-col items-center justify-center overflow-hidden px-4 sm:px-6 py-12 lg:py-24">
|
||||||
<div class="flex inset-0 overflow-hidden">
|
|
||||||
<div class="jumbo absolute opacity-60"></div>
|
<!-- Abstract Animated Background Elements -->
|
||||||
|
<div class="absolute inset-0 overflow-hidden pointer-events-none">
|
||||||
|
<!-- Enhanced original VIP Jumbo effect -->
|
||||||
|
<div class="jumbo"></div>
|
||||||
|
|
||||||
|
<!-- Modern animated blobs -->
|
||||||
|
<div
|
||||||
|
class="absolute top-0 -left-4 w-72 h-72 bg-purple-400 rounded-full mix-blend-multiply filter blur-2xl opacity-20 dark:opacity-20 animate-blob">
|
||||||
</div>
|
</div>
|
||||||
<div class="box-main w-full max-w-xl mx-auto">
|
<div
|
||||||
<div id="app" class="relative z-10 p-6 sm:p-10 w-full text-left shadow-lg rounded-xl bg-white dark:bg-slate-900/80 dark:backdrop-blur dark:ring-1 dark:ring-inset dark:ring-white/10 transition-all duration-300">
|
class="absolute top-0 -right-4 w-72 h-72 bg-blue-400 rounded-full mix-blend-multiply filter blur-2xl opacity-20 dark:opacity-20 animate-blob animate-delay-2000">
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="absolute -bottom-8 left-20 w-72 h-72 bg-pink-400 rounded-full mix-blend-multiply filter blur-2xl opacity-20 dark:opacity-20 animate-blob animate-delay-4000">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="z-10 w-full max-w-2xl mx-auto animate-fade-in-up">
|
||||||
|
<div id="app" class="glass-panel rounded-3xl p-8 md:p-12 transition-all duration-300 relative overflow-hidden">
|
||||||
|
|
||||||
|
<!-- Shimmer effect inside card -->
|
||||||
|
<div
|
||||||
|
class="absolute inset-0 bg-gradient-to-tr from-white/5 to-white/0 dark:from-white/5 dark:to-transparent pointer-events-none rounded-3xl">
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Header Section -->
|
<!-- Header Section -->
|
||||||
<header class="mb-8 text-center">
|
<header class="mb-10 text-center relative z-10">
|
||||||
<h1 class="relative flex flex-col xs:flex-row items-center justify-center text-4xl sm:text-5xl font-bold text-gray-800 dark:text-white dark:opacity-95 transition-colors">
|
|
||||||
|
<!-- Top Badge -->
|
||||||
|
<div
|
||||||
|
class="inline-flex items-center justify-center space-x-2 px-3 py-1 mb-6 rounded-full bg-primary-100 dark:bg-primary-900/40 border border-primary-200 dark:border-primary-800 text-xs font-semibold text-primary-700 dark:text-primary-300">
|
||||||
|
<span class="flex h-2 w-2 relative">
|
||||||
|
<span
|
||||||
|
class="animate-ping absolute inline-flex h-full w-full rounded-full bg-primary-400 opacity-75"></span>
|
||||||
|
<span class="relative inline-flex rounded-full h-2 w-2 bg-primary-500"></span>
|
||||||
|
</span>
|
||||||
|
<span>v20.X, 26.2 & 26.3 Compatible</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Main Title -->
|
||||||
|
<h1 class="flex flex-wrap items-center justify-center gap-x-3 text-4xl sm:text-5xl md:text-6xl font-extrabold tracking-tight text-slate-900 dark:text-white mb-2">
|
||||||
<span>MobaXterm</span>
|
<span>MobaXterm</span>
|
||||||
<span class="mt-2 xs:mt-0 xs:ml-2 rounded-xl bg-current p-2 text-[0.7em] leading-none">
|
<span class="text-transparent bg-clip-text bg-gradient-to-r from-blue-600 via-pink-500 to-indigo-600 animate-gradient-text inline-block py-2 pr-2">
|
||||||
<span class="text-white dark:text-black">Keygen</span>
|
Keygen
|
||||||
</span>
|
</span>
|
||||||
</h1>
|
</h1>
|
||||||
<!-- Version Badge -->
|
<p class="text-slate-500 dark:text-slate-400 mt-2 text-sm sm:text-base max-w-sm mx-auto">
|
||||||
<div class="mt-4 inline-flex items-center px-3 py-1 rounded-full bg-gradient-to-r from-indigo-500 via-purple-500 to-pink-500 text-sm font-medium text-white"> Compatible with versions 20.X, 25.4 and 26.0 </div>
|
Fast, and secure license generator.
|
||||||
|
</p>
|
||||||
|
|
||||||
<!-- Theme Toggle -->
|
<!-- Theme Toggle -->
|
||||||
<div class="mt-4">
|
<div class="absolute top-0 right-0 sm:-top-4 sm:-right-4 p-2 sm:p-0">
|
||||||
<button onclick="toggleTheme()" class="px-3 py-1 border border-stone-200 rounded-full drop-shadow-sm text-sm text-stone-800 dark:text-white bg-white/40 dark:bg-black/40 backdrop-blur-lg hover:border-stone-300 transition-colors dark:border-stone-500 dark:hover:border-stone-400"> Toggle Theme </button>
|
<button onclick="toggleTheme()"
|
||||||
</div>
|
class="p-3 rounded-full bg-white/60 dark:bg-slate-800/60 border border-slate-200 dark:border-slate-700 shadow-sm text-slate-600 dark:text-slate-300 hover:bg-white dark:hover:bg-slate-800 transition-all focus:outline-none focus:ring-2 focus:ring-primary-500"
|
||||||
<!-- Tab Navigation -->
|
aria-label="Toggle Theme">
|
||||||
<div class="mt-6 border-b border-gray-200 dark:border-gray-700">
|
<svg id="theme-icon-dark" class="hidden w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<nav class="flex space-x-4" aria-label="Tabs">
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
<button @click="activeTab = 'keyGenerator'"
|
d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" />
|
||||||
:class="[activeTab === 'keyGenerator' ? 'border-primary-500 text-primary-600 dark:text-primary-400' : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 dark:text-gray-400 dark:hover:text-gray-300', 'px-1 pb-4 text-sm font-medium border-b-2']">
|
</svg>
|
||||||
Key Generator
|
<svg id="theme-icon-light" class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
|
d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z" />
|
||||||
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<button @click="activeTab = 'customMerger'"
|
|
||||||
:class="[activeTab === 'customMerger' ? 'border-primary-500 text-primary-600 dark:text-primary-400' : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 dark:text-gray-400 dark:hover:text-gray-300', 'px-1 pb-4 text-sm font-medium border-b-2']">
|
|
||||||
Custom Settings Merger
|
|
||||||
</button>
|
|
||||||
</nav>
|
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
<!-- Tab Navigation -->
|
||||||
|
<div class="mb-10 relative z-10 flex justify-center w-full">
|
||||||
|
<nav
|
||||||
|
class="flex space-x-2 bg-slate-200/60 dark:bg-slate-800/60 p-1.5 rounded-2xl w-full max-w-sm mx-auto shadow-inner border border-slate-300/30 dark:border-slate-700/50"
|
||||||
|
aria-label="Tabs">
|
||||||
|
<button @click="activeTab = 'keyGenerator'"
|
||||||
|
:class="[activeTab === 'keyGenerator' ? 'bg-white dark:bg-slate-700 text-primary-600 dark:text-primary-400 shadow-sm' : 'text-slate-500 hover:text-slate-700 dark:text-slate-400 dark:hover:text-slate-200', 'w-1/2 py-2.5 text-sm sm:text-base font-bold transition-all duration-300 rounded-xl tracking-wide']">
|
||||||
|
Key Generator
|
||||||
|
</button>
|
||||||
|
<button @click="activeTab = 'customMerger'"
|
||||||
|
:class="[activeTab === 'customMerger' ? 'bg-white dark:bg-slate-700 text-primary-600 dark:text-primary-400 shadow-sm' : 'text-slate-500 hover:text-slate-700 dark:text-slate-400 dark:hover:text-slate-200', 'w-1/2 py-2.5 text-sm sm:text-base font-bold transition-all duration-300 rounded-xl tracking-wide']">
|
||||||
|
Merger
|
||||||
|
</button>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Key Generator Tab -->
|
<!-- Key Generator Tab -->
|
||||||
<div v-if="activeTab === 'keyGenerator'">
|
<div v-show="activeTab === 'keyGenerator'" class="relative z-10 animate-fade-in-up"
|
||||||
|
style="animation-duration: 0.4s;">
|
||||||
<form @submit.prevent="validateAndGenerate">
|
<form @submit.prevent="validateAndGenerate">
|
||||||
<div class="space-y-6">
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||||
<div>
|
|
||||||
<label for="licenseType" class="block text-lg text-gray-700 dark:text-gray-300">Edition:</label>
|
<!-- Edition selection -->
|
||||||
|
<div class="col-span-1 md:col-span-2 group">
|
||||||
|
<label for="licenseType"
|
||||||
|
class="block text-sm font-semibold text-slate-700 dark:text-slate-300 mb-1.5 ml-1">Edition
|
||||||
|
Type</label>
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<select name="licenseType" id="licenseType" v-model="licenseType" class="w-full mt-1 p-2 pr-8 rounded-lg border border-gray-300 dark:border-gray-600 dark:bg-slate-800 dark:text-white focus:ring-2 focus:ring-primary-500 focus:border-transparent outline-none transition-colors appearance-none">
|
<div
|
||||||
<option value="" disabled>Select an option</option>
|
class="absolute inset-y-0 left-0 flex items-center pl-4 pointer-events-none text-slate-400 group-focus-within:text-primary-500 transition-colors">
|
||||||
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
|
d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z">
|
||||||
|
</path>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<select name="licenseType" id="licenseType" v-model="licenseType"
|
||||||
|
class="input-modern block w-full pl-11 pr-10 py-3.5 rounded-xl outline-none appearance-none font-medium cursor-pointer">
|
||||||
|
<option value="" disabled>Select Edition</option>
|
||||||
<option v-for="(val, key) in LICENSE_TYPES" :value="val">{{key}}</option>
|
<option v-for="(val, key) in LICENSE_TYPES" :value="val">{{key}}</option>
|
||||||
</select>
|
</select>
|
||||||
<div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 mt-1 text-gray-700 dark:text-gray-300">
|
<div
|
||||||
<svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
|
class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-4 text-slate-400 group-focus-within:text-primary-500 transition-colors">
|
||||||
<path d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"></path>
|
<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p v-if="errors.licenseType" class="mt-1 text-red-500 text-sm">{{ errors.licenseType }}</p>
|
<p v-if="errors.licenseType" class="mt-1.5 ml-1 text-red-500 text-xs font-medium">{{
|
||||||
|
errors.licenseType }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
|
||||||
<label for="userName" class="block text-lg text-gray-700 dark:text-gray-300">Username:</label>
|
<!-- Username -->
|
||||||
|
<div class="group">
|
||||||
|
<label for="userName"
|
||||||
|
class="block text-sm font-semibold text-slate-700 dark:text-slate-300 mb-1.5 ml-1">Username</label>
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<input type="text" id="userName" v-model="userName" @input="validateUserName" placeholder="Example defaultUser" class="w-full mt-1 p-2 rounded-lg border border-gray-300 dark:border-gray-600 dark:bg-slate-800 dark:text-white focus:ring-2 focus:ring-primary-500 focus:border-transparent outline-none transition-colors" />
|
<div
|
||||||
<p v-if="errors.userName" class="mt-1 text-red-500 text-sm">{{ errors.userName }}</p>
|
class="absolute inset-y-0 left-0 flex items-center pl-4 pointer-events-none text-slate-400 group-focus-within:text-primary-500 transition-colors">
|
||||||
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
|
d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"></path>
|
||||||
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
|
<input type="text" id="userName" v-model="userName" @input="validateUserName"
|
||||||
|
placeholder="e.g. JohnDoe"
|
||||||
|
class="input-modern block w-full pl-11 pr-4 py-3.5 rounded-xl outline-none" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<p v-if="errors.userName" class="mt-1.5 ml-1 text-red-500 text-xs font-medium">{{ errors.userName }}
|
||||||
<label for="versionName" class="block text-lg text-gray-700 dark:text-gray-300">Version:</label>
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Version -->
|
||||||
|
<div class="group">
|
||||||
|
<label for="versionName"
|
||||||
|
class="block text-sm font-semibold text-slate-700 dark:text-slate-300 mb-1.5 ml-1">Version</label>
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<input type="text" id="versionName" v-model="versionName" @input="validateVersion" placeholder="Example 26.0" class="w-full mt-1 p-2 rounded-lg border border-gray-300 dark:border-gray-600 dark:bg-slate-800 dark:text-white focus:ring-2 focus:ring-primary-500 focus:border-transparent outline-none transition-colors" />
|
<div
|
||||||
<p v-if="errors.versionName" class="mt-1 text-red-500 text-sm">{{ errors.versionName }}</p>
|
class="absolute inset-y-0 left-0 flex items-center pl-4 pointer-events-none text-slate-400 group-focus-within:text-primary-500 transition-colors">
|
||||||
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
|
d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"></path>
|
||||||
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
|
<input type="text" id="versionName" v-model="versionName" @input="validateVersion"
|
||||||
|
placeholder="26.3" class="input-modern block w-full pl-11 pr-4 py-3.5 rounded-xl outline-none" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<p v-if="errors.versionName" class="mt-1.5 ml-1 text-red-500 text-xs font-medium">{{
|
||||||
<label for="userNum" class="block text-lg text-gray-700 dark:text-gray-300">Number of users:</label>
|
errors.versionName }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Number of Users -->
|
||||||
|
<div class="col-span-1 md:col-span-2 group">
|
||||||
|
<label for="userNum"
|
||||||
|
class="block text-sm font-semibold text-slate-700 dark:text-slate-300 mb-1.5 ml-1">Number of
|
||||||
|
Users</label>
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<input type="number" id="userNum" v-model="userNum" @input="validateUserNum" placeholder="Example 1" min="1" class="w-full mt-1 p-2 rounded-lg border border-gray-300 dark:border-gray-600 dark:bg-slate-800 dark:text-white focus:ring-2 focus:ring-primary-500 focus:border-transparent outline-none transition-colors" />
|
<div
|
||||||
<p v-if="errors.userNum" class="mt-1 text-red-500 text-sm">{{ errors.userNum }}</p>
|
class="absolute inset-y-0 left-0 flex items-center pl-4 pointer-events-none text-slate-400 group-focus-within:text-primary-500 transition-colors">
|
||||||
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
|
d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z">
|
||||||
|
</path>
|
||||||
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
|
<input type="number" id="userNum" v-model="userNum" @input="validateUserNum" placeholder="1" min="1"
|
||||||
|
class="input-modern block w-full pl-11 pr-4 py-3.5 rounded-xl outline-none" />
|
||||||
</div>
|
</div>
|
||||||
<!-- Download Button -->
|
<p v-if="errors.userNum" class="mt-1.5 ml-1 text-red-500 text-xs font-medium">{{ errors.userNum }}</p>
|
||||||
<div class="text-center pt-4">
|
|
||||||
<button type="submit" class="w-full sm:w-auto px-6 py-3 bg-primary-600 text-white rounded-lg shadow-md hover:bg-primary-700 focus:outline-none focus:ring-2 focus:ring-primary-500 transition-colors duration-200"> Download Key </button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Submit Button -->
|
||||||
|
<div class="col-span-1 md:col-span-2 pt-2">
|
||||||
|
<button type="submit"
|
||||||
|
class="btn-gradient w-full py-4 px-6 rounded-xl text-lg font-bold uppercase tracking-wider flex items-center justify-center gap-2 focus:outline-none focus:ring-4 focus:ring-primary-500/50">
|
||||||
|
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
|
d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"></path>
|
||||||
|
</svg>
|
||||||
|
Generate License
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Custom Settings Merger Tab -->
|
<!-- Custom Settings Merger Tab -->
|
||||||
<div v-if="activeTab === 'customMerger'" class="space-y-6">
|
<div v-show="activeTab === 'customMerger'" class="relative z-10 space-y-8 animate-fade-in-up"
|
||||||
<div class="bg-slate-100 dark:bg-slate-800 p-4 rounded-lg mb-4">
|
style="animation-duration: 0.4s;">
|
||||||
<h3 class="text-lg font-semibold text-gray-900 dark:text-white mb-2">How to Use Custom Settings Merger</h3>
|
|
||||||
<ol class="list-decimal list-inside space-y-2 text-sm text-gray-700 dark:text-gray-300">
|
<!-- Info Box -->
|
||||||
<li>Generate a license key file using the Key Generator tab</li>
|
<div
|
||||||
<li>Run MobaXterm with the <code class="bg-slate-200 dark:bg-slate-700 px-1 py-0.5 rounded">-customizer</code> parameter: <br>
|
class="bg-primary-50/80 dark:bg-primary-900/10 border border-primary-100 dark:border-primary-800/30 p-5 rounded-2xl">
|
||||||
<code class="bg-slate-200 dark:bg-slate-700 px-2 py-1 rounded block mt-1">.\MobaXterm.exe -customizer</code>
|
<div class="flex items-start gap-4">
|
||||||
|
<div
|
||||||
|
class="bg-primary-100 dark:bg-primary-800 p-2 rounded-lg text-primary-600 dark:text-primary-300 shrink-0">
|
||||||
|
<svg class="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
|
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 class="text-base font-bold text-primary-900 dark:text-primary-100 mb-1">How it works</h3>
|
||||||
|
<ul
|
||||||
|
class="text-sm text-primary-700 dark:text-primary-300 space-y-1.5 ml-4 list-decimal marker:text-primary-500 font-medium">
|
||||||
|
<li>Generate a license using the <span class="font-bold">Key Generator</span>.</li>
|
||||||
|
<li>Run <code
|
||||||
|
class="bg-white/60 dark:bg-black/40 px-1.5 py-0.5 rounded font-mono text-xs">.\MobaXterm.exe -customizer</code>
|
||||||
</li>
|
</li>
|
||||||
<li>Export your custom settings to a file named <code class="bg-slate-200 dark:bg-slate-700 px-1 py-0.5 rounded">MobaXterm customization.custom</code></li>
|
<li>Export settings to <code
|
||||||
<li>Upload both your license key file and custom settings file below</li>
|
class="bg-white/60 dark:bg-black/40 px-1.5 py-0.5 rounded font-mono text-xs">MobaXterm customization.custom</code>
|
||||||
<li>Click "Merge Files" to create a combined activation file</li>
|
</li>
|
||||||
</ol>
|
<li>Upload both files below to merge.</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="space-y-6">
|
||||||
|
<!-- License File Upload -->
|
||||||
<div>
|
<div>
|
||||||
<label for="licenseFileInput" class="block text-lg font-medium text-gray-700 dark:text-gray-300 mb-2">
|
<label class="block text-sm font-semibold text-slate-700 dark:text-slate-300 mb-2 ml-1">
|
||||||
License Key File (Custom.mxtpro):
|
License (.mxtpro)
|
||||||
</label>
|
</label>
|
||||||
<div class="relative">
|
<label for="licenseFileInput"
|
||||||
<input
|
class="flex flex-col items-center justify-center w-full h-32 border-2 border-dashed border-slate-300 dark:border-slate-600 rounded-2xl cursor-pointer bg-white/30 dark:bg-slate-800/30 hover:bg-white/60 dark:hover:bg-slate-800/60 transition-colors group">
|
||||||
type="file"
|
<div class="flex flex-col items-center justify-center pt-5 pb-6">
|
||||||
id="licenseFileInput"
|
<svg class="w-8 h-8 mb-3 text-slate-400 group-hover:text-primary-500 transition-colors" fill="none"
|
||||||
@change="handleLicenseFileUpload"
|
stroke="currentColor" viewBox="0 0 24 24">
|
||||||
accept=".mxtpro"
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
class="block w-full text-sm text-gray-700 dark:text-gray-300
|
d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12">
|
||||||
file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0
|
</path>
|
||||||
file:text-sm file:font-semibold
|
</svg>
|
||||||
file:bg-primary-50 file:text-primary-700
|
<p class="mb-1 text-sm text-slate-500 dark:text-slate-400 font-semibold truncate px-4 max-w-full">
|
||||||
hover:file:bg-primary-100 hover:file:text-primary-800
|
<span class="text-primary-600 dark:text-primary-400">{{ licenseFile ? licenseFile.name : 'Click to upload' }}</span></p>
|
||||||
focus:outline-none focus:border-primary-500 focus:ring-2 focus:ring-primary-200
|
<p v-if="!licenseFile" class="text-xs text-slate-400 dark:text-slate-500">MAX size 10MB</p>
|
||||||
transition-colors duration-200
|
|
||||||
dark:file:bg-slate-700 dark:file:text-slate-100
|
|
||||||
dark:hover:file:bg-slate-600 dark:hover:file:text-white"
|
|
||||||
/>
|
|
||||||
<p v-if="errors.licenseFile" class="mt-1 text-red-500 text-sm">{{ errors.licenseFile }}</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
<input type="file" id="licenseFileInput" @change="handleLicenseFileUpload" accept=".mxtpro"
|
||||||
|
class="hidden" />
|
||||||
|
</label>
|
||||||
|
<p v-if="errors.licenseFile" class="mt-1.5 ml-1 text-red-500 text-xs font-medium">{{ errors.licenseFile
|
||||||
|
}}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Custom File Upload -->
|
||||||
<div>
|
<div>
|
||||||
<label for="customSettingsFileInput" class="block text-lg text-gray-700 dark:text-gray-300">Custom Settings File (.custom):</label>
|
<label class="block text-sm font-semibold text-slate-700 dark:text-slate-300 mb-2 ml-1">
|
||||||
<input type="file" id="customSettingsFileInput" @change="handleCustomSettingsFileUpload" accept=".custom" class="block w-full text-sm text-gray-700 dark:text-gray-300
|
Custom Settings (.custom)
|
||||||
file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0
|
</label>
|
||||||
file:text-sm file:font-semibold
|
<label for="customSettingsFileInput"
|
||||||
file:bg-primary-50 file:text-primary-700
|
class="flex flex-col items-center justify-center w-full h-32 border-2 border-dashed border-slate-300 dark:border-slate-600 rounded-2xl cursor-pointer bg-white/30 dark:bg-slate-800/30 hover:bg-white/60 dark:hover:bg-slate-800/60 transition-colors group">
|
||||||
hover:file:bg-primary-100 hover:file:text-primary-800
|
<div class="flex flex-col items-center justify-center pt-5 pb-6">
|
||||||
focus:outline-none focus:border-primary-500 focus:ring-2 focus:ring-primary-200
|
<svg class="w-8 h-8 mb-3 text-slate-400 group-hover:text-primary-500 transition-colors" fill="none"
|
||||||
transition-colors duration-200
|
stroke="currentColor" viewBox="0 0 24 24">
|
||||||
dark:file:bg-slate-700 dark:file:text-slate-100
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
dark:hover:file:bg-slate-600 dark:hover:file:text-white" />
|
d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z">
|
||||||
<p v-if="errors.customSettingsFile" class="mt-1 text-red-500 text-sm">{{ errors.customSettingsFile }}</p>
|
</path>
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
|
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
|
||||||
|
</svg>
|
||||||
|
<p class="mb-1 text-sm text-slate-500 dark:text-slate-400 font-semibold truncate px-4 max-w-full">
|
||||||
|
<span class="text-primary-600 dark:text-primary-400">{{ customSettingsFile ? customSettingsFile.name : 'Click to upload' }}</span></p>
|
||||||
|
<p v-if="!customSettingsFile" class="text-xs text-slate-400 dark:text-slate-500">MAX size 10MB</p>
|
||||||
|
</div>
|
||||||
|
<input type="file" id="customSettingsFileInput" @change="handleCustomSettingsFileUpload"
|
||||||
|
accept=".custom" class="hidden" />
|
||||||
|
</label>
|
||||||
|
<p v-if="errors.customSettingsFile" class="mt-1.5 ml-1 text-red-500 text-xs font-medium">{{
|
||||||
|
errors.customSettingsFile }}</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="text-center pt-4">
|
<div class="pt-2">
|
||||||
<button @click="mergeFiles" :disabled="!licenseFile || !customSettingsFile" class="w-full sm:w-auto px-6 py-3 bg-primary-600 text-white rounded-lg shadow-md hover:bg-primary-700 focus:outline-none focus:ring-2 focus:ring-primary-500 transition-colors duration-200 disabled:bg-gray-400 disabled:cursor-not-allowed"> Merge Files </button>
|
<button @click="mergeFiles" :disabled="!licenseFile || !customSettingsFile"
|
||||||
|
class="btn-gradient w-full py-4 px-6 rounded-xl text-lg font-bold uppercase tracking-wider flex items-center justify-center gap-2 focus:outline-none focus:ring-4 focus:ring-primary-500/50 disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:translate-y-0 disabled:hover:shadow-none">
|
||||||
|
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
|
d="M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4"></path>
|
||||||
|
</svg>
|
||||||
|
Merge Files
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Footer -->
|
<!-- Footer -->
|
||||||
<footer class="mt-8 pt-6 border-t border-slate-200 dark:border-slate-700">
|
<footer class="mt-14 relative z-10">
|
||||||
<div class="flex flex-col items-center space-y-4">
|
<div class="flex flex-col items-center space-y-3">
|
||||||
<div class="flex items-center space-x-2">
|
<div
|
||||||
<span class="text-sm text-slate-600 dark:text-slate-400">Created with</span>
|
class="flex items-center space-x-2 bg-white/40 dark:bg-slate-800/40 px-4 py-1.5 rounded-full border border-slate-200 dark:border-slate-700 backdrop-blur-sm">
|
||||||
|
<span class="text-xs font-medium text-slate-600 dark:text-slate-400">Handcrafted with</span>
|
||||||
<span class="animate-pulse text-red-500">❤</span>
|
<span class="animate-pulse text-red-500">❤</span>
|
||||||
<span class="text-sm text-slate-600 dark:text-slate-400">by</span>
|
<span class="text-xs font-medium text-slate-600 dark:text-slate-400">by</span>
|
||||||
<span class="text-sm font-semibold bg-clip-text text-transparent bg-gradient-to-r from-purple-500 to-pink-500"> Zarfala </span>
|
<span
|
||||||
|
class="text-xs font-extrabold bg-clip-text text-transparent bg-gradient-to-r from-purple-500 to-pink-500">
|
||||||
|
Zarfala </span>
|
||||||
|
</div>
|
||||||
|
<div class="text-[11px] font-medium text-slate-500 tracking-wide">
|
||||||
|
v3.0 © 2026 All rights reserved
|
||||||
</div>
|
</div>
|
||||||
<p class="text-sm text-slate-600 dark:text-slate-400" style="margin-top: 0;"> UI/UX Design optimized for <span class="inline-block">
|
|
||||||
<span class="text-blue-500 font-semibold">Computer</span>
|
|
||||||
<span class="text-green-500 font-semibold">& Mobile</span>
|
|
||||||
</span>
|
|
||||||
</p>
|
|
||||||
<div class="text-xs text-slate-500 dark:text-slate-500" style="margin-top: 5px;"> v2.6 © 2025 All rights reserved </div>
|
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Toast notification -->
|
<!-- Toast notification -->
|
||||||
<div id="toast" class="fixed bottom-4 right-4 px-4 py-2 rounded-lg bg-green-500 text-white transform translate-y-16 opacity-0 transition-all duration-300 z-50 hidden">
|
<div id="toast"
|
||||||
License generated successfully!
|
class="fixed bottom-6 right-6 px-6 py-4 rounded-xl shadow-2xl transform translate-y-24 opacity-0 transition-all duration-400 cubic-bezier(0.16, 1, 0.3, 1) z-50 hidden flex items-center gap-3 backdrop-blur-md font-semibold text-sm">
|
||||||
|
<svg id="toast-icon-success" class="w-5 h-5 hidden" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
|
||||||
|
</svg>
|
||||||
|
<svg id="toast-icon-error" class="w-5 h-5 hidden" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
|
||||||
|
</svg>
|
||||||
|
<span id="toast-text"></span>
|
||||||
</div>
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
<!-- Scripts -->
|
<!-- Scripts -->
|
||||||
<script src="./js/vue.min-2.6.12.js"></script>
|
<script src="./js/vue.min-2.6.12.js"></script>
|
||||||
<script src="./js/FileSaver.js"></script>
|
<script src="./js/FileSaver.js"></script>
|
||||||
<script src="./js/jszip.js"></script>
|
<script src="./js/jszip.js"></script>
|
||||||
<script src="./js/fire.js"></script>
|
<script src="./js/fire.js"></script>
|
||||||
<script src="./js/alert.js"></script>
|
<script src="./js/alert.js"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Preloader functionality
|
// Preloader functionality
|
||||||
window.addEventListener('load', function () {
|
window.addEventListener('load', function () {
|
||||||
// Hide preloader
|
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
const preloader = document.getElementById('preloader');
|
const preloader = document.getElementById('preloader');
|
||||||
const mainContent = document.getElementById('main-content');
|
const mainContent = document.getElementById('main-content');
|
||||||
@@ -279,14 +645,19 @@
|
|||||||
mainContent.classList.remove('content-hidden');
|
mainContent.classList.remove('content-hidden');
|
||||||
mainContent.classList.add('content-visible');
|
mainContent.classList.add('content-visible');
|
||||||
|
|
||||||
// Remove preloader from DOM after transition completes
|
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
preloader.style.display = 'none';
|
preloader.style.display = 'none';
|
||||||
}, 500);
|
}, 600);
|
||||||
}, 300);
|
}, 400); // slight artificial delay for premium feel
|
||||||
});
|
});
|
||||||
|
|
||||||
// Theme toggle functionality
|
// Theme toggle functionality
|
||||||
|
function updateThemeIcons() {
|
||||||
|
const isDark = document.documentElement.classList.contains('dark');
|
||||||
|
document.getElementById('theme-icon-dark').classList.toggle('hidden', isDark);
|
||||||
|
document.getElementById('theme-icon-light').classList.toggle('hidden', !isDark);
|
||||||
|
}
|
||||||
|
|
||||||
function toggleTheme() {
|
function toggleTheme() {
|
||||||
if (document.documentElement.classList.contains('dark')) {
|
if (document.documentElement.classList.contains('dark')) {
|
||||||
document.documentElement.classList.remove('dark');
|
document.documentElement.classList.remove('dark');
|
||||||
@@ -295,49 +666,55 @@
|
|||||||
document.documentElement.classList.add('dark');
|
document.documentElement.classList.add('dark');
|
||||||
localStorage.theme = 'dark';
|
localStorage.theme = 'dark';
|
||||||
}
|
}
|
||||||
|
updateThemeIcons();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for saved theme preference or prefer-color-scheme
|
// Theme is initialized in the <head> to prevent loader flash
|
||||||
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
updateThemeIcons();
|
||||||
document.documentElement.classList.add('dark');
|
|
||||||
} else {
|
|
||||||
document.documentElement.classList.remove('dark');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Toast notification function
|
// Toast notification function
|
||||||
function showToast(message, type = 'success') {
|
function showToast(message, type = 'success') {
|
||||||
const toast = document.getElementById('toast');
|
const toast = document.getElementById('toast');
|
||||||
toast.textContent = message;
|
const text = document.getElementById('toast-text');
|
||||||
|
const iconSuccess = document.getElementById('toast-icon-success');
|
||||||
|
const iconError = document.getElementById('toast-icon-error');
|
||||||
|
|
||||||
|
text.textContent = message;
|
||||||
toast.classList.remove('hidden');
|
toast.classList.remove('hidden');
|
||||||
|
|
||||||
if (type === 'success') {
|
if (type === 'success') {
|
||||||
toast.classList.add('bg-green-500');
|
toast.className = toast.className.replace(/bg-\w+-50\/\d+/g, '');
|
||||||
toast.classList.remove('bg-red-500');
|
toast.className = toast.className.replace(/text-\w+-600/g, '');
|
||||||
|
toast.classList.add('bg-green-50/90', 'dark:bg-green-900/90', 'text-green-700', 'dark:text-green-100', 'border', 'border-green-200', 'dark:border-green-800');
|
||||||
|
toast.classList.remove('bg-red-50/90', 'dark:bg-red-900/90', 'text-red-700', 'dark:text-red-100', 'border-red-200', 'dark:border-red-800');
|
||||||
|
iconSuccess.classList.remove('hidden');
|
||||||
|
iconError.classList.add('hidden');
|
||||||
} else {
|
} else {
|
||||||
toast.classList.add('bg-red-500');
|
toast.className = toast.className.replace(/bg-\w+-50\/\d+/g, '');
|
||||||
toast.classList.remove('bg-green-500');
|
toast.className = toast.className.replace(/text-\w+-600/g, '');
|
||||||
|
toast.classList.add('bg-red-50/90', 'dark:bg-red-900/90', 'text-red-700', 'dark:text-red-100', 'border', 'border-red-200', 'dark:border-red-800');
|
||||||
|
toast.classList.remove('bg-green-50/90', 'dark:bg-green-900/90', 'text-green-700', 'dark:text-green-100', 'border-green-200', 'dark:border-green-800');
|
||||||
|
iconError.classList.remove('hidden');
|
||||||
|
iconSuccess.classList.add('hidden');
|
||||||
}
|
}
|
||||||
|
|
||||||
setTimeout(() => {
|
// Trigger animation
|
||||||
toast.classList.remove('translate-y-16', 'opacity-0');
|
requestAnimationFrame(() => {
|
||||||
}, 100);
|
toast.classList.remove('translate-y-24', 'opacity-0');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Hide after delay
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
toast.classList.add('translate-y-16', 'opacity-0');
|
toast.classList.add('translate-y-24', 'opacity-0');
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
toast.classList.add('hidden');
|
toast.classList.add('hidden');
|
||||||
}, 300);
|
}, 400);
|
||||||
}, 3000);
|
}, 4000);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import {
|
import { LicenseType, generateLicense } from './js/mobaXtermGenerater.js'
|
||||||
LicenseType,
|
import { mergeZipFiles } from './js/mergeZipFiles.js'
|
||||||
generateLicense
|
|
||||||
} from './js/mobaXtermGenerater.js'
|
|
||||||
import {
|
|
||||||
mergeZipFiles
|
|
||||||
} from './js/mergeZipFiles.js'
|
|
||||||
|
|
||||||
new Vue({
|
new Vue({
|
||||||
el: '#app',
|
el: '#app',
|
||||||
@@ -346,7 +723,7 @@
|
|||||||
LICENSE_TYPES: LicenseType,
|
LICENSE_TYPES: LicenseType,
|
||||||
licenseType: '',
|
licenseType: '',
|
||||||
userName: '',
|
userName: '',
|
||||||
versionName: '',
|
versionName: '26.3',
|
||||||
userNum: '',
|
userNum: '',
|
||||||
activeTab: 'keyGenerator',
|
activeTab: 'keyGenerator',
|
||||||
licenseFile: null,
|
licenseFile: null,
|
||||||
@@ -375,10 +752,9 @@
|
|||||||
this.errors.userName = 'Username is required';
|
this.errors.userName = 'Username is required';
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const regex = /^[a-zA-Z]+$/;
|
const regex = /^[a-zA-Z]+$/;
|
||||||
if (!regex.test(this.userName)) {
|
if (!regex.test(this.userName)) {
|
||||||
this.errors.userName = 'Only letters are allowed (no spaces, numbers or special characters)';
|
this.errors.userName = 'Only letters allowed (no spaces, numbers or special chars)';
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this.errors.userName = '';
|
this.errors.userName = '';
|
||||||
@@ -389,20 +765,17 @@
|
|||||||
this.errors.versionName = 'Version is required';
|
this.errors.versionName = 'Version is required';
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const regex = /^[1-9][0-9]*\.?\d{0,1}$/;
|
const regex = /^[1-9][0-9]*\.?\d{0,1}$/;
|
||||||
if (!regex.test(this.versionName)) {
|
if (!regex.test(this.versionName)) {
|
||||||
this.errors.versionName = 'Enter a valid version format (e.g., 26.0)';
|
this.errors.versionName = 'Enter a valid version format (e.g., 26.3)';
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if version is supported
|
// Check if version is supported
|
||||||
const majorVersion = parseInt(this.versionName.split('.')[0]);
|
const majorVersion = parseInt(this.versionName.split('.')[0]);
|
||||||
if (majorVersion !== 20 && majorVersion !== 25 && majorVersion !== 26) {
|
if (majorVersion !== 20 && majorVersion !== 25 && majorVersion !== 26) {
|
||||||
this.errors.versionName = 'Currently only versions 20.X, 25.X and 26 are supported';
|
this.errors.versionName = 'Currently only versions 20.X, 25.X and 26.X are supported';
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.errors.versionName = '';
|
this.errors.versionName = '';
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
@@ -411,7 +784,6 @@
|
|||||||
this.errors.userNum = 'Number of users is required';
|
this.errors.userNum = 'Number of users is required';
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const regex = /^[1-9]+\d*$/;
|
const regex = /^[1-9]+\d*$/;
|
||||||
if (!regex.test(this.userNum)) {
|
if (!regex.test(this.userNum)) {
|
||||||
this.errors.userNum = 'Enter a valid number greater than 0';
|
this.errors.userNum = 'Enter a valid number greater than 0';
|
||||||
@@ -421,13 +793,11 @@
|
|||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
validateAndGenerate() {
|
validateAndGenerate() {
|
||||||
// Validate all fields
|
|
||||||
const isLicenseTypeValid = this.validateLicenseType();
|
const isLicenseTypeValid = this.validateLicenseType();
|
||||||
const isUserNameValid = this.validateUserName();
|
const isUserNameValid = this.validateUserName();
|
||||||
const isVersionValid = this.validateVersion();
|
const isVersionValid = this.validateVersion();
|
||||||
const isUserNumValid = this.validateUserNum();
|
const isUserNumValid = this.validateUserNum();
|
||||||
|
|
||||||
// Only generate if all validations pass
|
|
||||||
if (isLicenseTypeValid && isUserNameValid && isVersionValid && isUserNumValid) {
|
if (isLicenseTypeValid && isUserNameValid && isVersionValid && isUserNumValid) {
|
||||||
try {
|
try {
|
||||||
let versionNameArr = this.versionName.split('.');
|
let versionNameArr = this.versionName.split('.');
|
||||||
@@ -446,11 +816,9 @@
|
|||||||
generateLicenseFile(licenseStr) {
|
generateLicenseFile(licenseStr) {
|
||||||
let zip = new JSZip();
|
let zip = new JSZip();
|
||||||
zip.file("Pro.key", licenseStr);
|
zip.file("Pro.key", licenseStr);
|
||||||
zip.generateAsync({
|
zip.generateAsync({ type: "blob" }).then((content) => {
|
||||||
type: "blob"
|
|
||||||
}).then(function(content) {
|
|
||||||
saveAs(content, "Custom.mxtpro");
|
saveAs(content, "Custom.mxtpro");
|
||||||
}).catch(function(error) {
|
}).catch((error) => {
|
||||||
console.error('Error creating zip file:', error);
|
console.error('Error creating zip file:', error);
|
||||||
showToast('Error creating license file. Please try again.', 'error');
|
showToast('Error creating license file. Please try again.', 'error');
|
||||||
});
|
});
|
||||||
@@ -484,7 +852,6 @@
|
|||||||
showToast('Please upload both required files', 'error');
|
showToast('Please upload both required files', 'error');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mergeZipFiles(this.licenseFile, this.customSettingsFile)
|
mergeZipFiles(this.licenseFile, this.customSettingsFile)
|
||||||
.then((mergedContent) => {
|
.then((mergedContent) => {
|
||||||
saveAs(mergedContent, "Custom.mxtpro");
|
saveAs(mergedContent, "Custom.mxtpro");
|
||||||
@@ -495,12 +862,9 @@
|
|||||||
showToast('Error merging files. Please try again.', 'error');
|
showToast('Error merging files. Please try again.', 'error');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
// Set default version to 26.0
|
|
||||||
this.versionName = '26.0';
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
+55
-25
@@ -1,16 +1,4 @@
|
|||||||
var estiloConsola = `
|
const asciiArt = `
|
||||||
font-size: 16px;
|
|
||||||
font-family: "Courier New", monospace;
|
|
||||||
color: red;
|
|
||||||
white-space: pre;
|
|
||||||
`;
|
|
||||||
|
|
||||||
var estiloZarfala = `
|
|
||||||
color: red;
|
|
||||||
white-space: pre;
|
|
||||||
`;
|
|
||||||
|
|
||||||
var mensajeZarfala = `
|
|
||||||
@@@@@@@@ @@@@@@ @@@@@@@ @@@@@@@@ @@@@@@ @@@ @@@@@@
|
@@@@@@@@ @@@@@@ @@@@@@@ @@@@@@@@ @@@@@@ @@@ @@@@@@
|
||||||
@@@@@@@@ @@@@@@@@ @@@@@@@@ @@@@@@@@ @@@@@@@@ @@@ @@@@@@@@
|
@@@@@@@@ @@@@@@@@ @@@@@@@@ @@@@@@@@ @@@@@@@@ @@@ @@@@@@@@
|
||||||
@@! @@! @@@ @@! @@@ @@! @@! @@@ @@! @@! @@@
|
@@! @@! @@@ @@! @@@ @@! @@! @@@ @@! @@! @@@
|
||||||
@@ -23,18 +11,60 @@ var mensajeZarfala = `
|
|||||||
: :: : : : : : : : : : : : : : :: : : : : :
|
: :: : : : : : : : : : : : : : :: : : : : :
|
||||||
`;
|
`;
|
||||||
|
|
||||||
function mostrarMensaje() {
|
const asciiAuraStyle = `
|
||||||
|
font-family: "Courier New", monospace;
|
||||||
|
font-weight: 900;
|
||||||
|
background: linear-gradient(90deg, #60a5fa, #ec4899, #8b5cf6);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
color: transparent;
|
||||||
|
display: block;
|
||||||
|
white-space: pre;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const warningHeadingStyle = `
|
||||||
|
color: #ff0055;
|
||||||
|
font-size: 44px;
|
||||||
|
font-weight: 900;
|
||||||
|
font-family: 'Outfit', sans-serif, system-ui;
|
||||||
|
text-shadow: 0px 4px 15px rgba(255, 0, 85, 0.4);
|
||||||
|
padding: 10px 0;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const warningBodyStyle = `
|
||||||
|
font-size: 16px;
|
||||||
|
color: #d1d5db;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 1.6;
|
||||||
|
font-family: system-ui, -apple-system, sans-serif;
|
||||||
|
padding: 10px 0 20px 0;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const signatureStyle = `
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
background: linear-gradient(90deg, #10b981, #3b82f6);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
color: transparent;
|
||||||
|
font-family: 'Outfit', sans-serif;
|
||||||
|
`;
|
||||||
|
|
||||||
|
function renderSecureAura() {
|
||||||
|
// Clear any existing logs to present a clean canvas
|
||||||
console.clear();
|
console.clear();
|
||||||
console.log('%c' + mensajeZarfala, estiloZarfala);
|
|
||||||
console.log("%cSTOP!", "color:red;font-size:xx-large;font-weight:bold;"),
|
// Print Aura-style ASCII Art
|
||||||
console.log(`%cThis is a browser feature intended for developers. Do not enter or paste code which you don't understand. It may allow attackers to steal your information or impersonate you. See https://en.wikipedia.org/wiki/Self-XSS for more details`, "font-size:large;"),
|
console.log('%c' + asciiArt, asciiAuraStyle);
|
||||||
localStorage.do_NOT_share_jwt || localStorage.setItem("do_NOT_share_jwt", "do NOT share the JWT value. someone could steal your account");
|
|
||||||
|
// Print Warning Message
|
||||||
|
console.log("%cSTOP! SECURE ZONE", warningHeadingStyle);
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
"%cThis is a browser feature intended strictly for developers.\nDo not enter or paste any code you do not fully understand.\nDoing so could grant attackers access to hijack your session, steal your licenses, or impersonate you.\n\nProtect your data and stay safe! 🔒",
|
||||||
|
warningBodyStyle
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log("%c✨ MobaXterm Keygen System - Shield Active", signatureStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
var intermitente = true;
|
// Render the protective aura once
|
||||||
setInterval(function () {
|
renderSecureAura();
|
||||||
mostrarMensaje();
|
|
||||||
intermitente = !intermitente;
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
mostrarMensaje();
|
|
||||||
|
|||||||
Reference in New Issue
Block a user