Enhanced Conceptual Web VPN

An improved conceptual Web VPN interface

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Enhanced Conceptual Web VPN
// @namespace    https://greasyfork.org/users/123456
// @version      2.0
// @description  An improved conceptual Web VPN interface
// @author       You
// @match        *://*/*
// @grant        none
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // Inject Tailwind CSS (you'll need to include this in your actual userscript)
    const tailwindCss = `
      @tailwind base;
      @tailwind components;
      @tailwind utilities;
    `;
    const styleElement = document.createElement('style');
    styleElement.textContent = tailwindCss;
    document.head.appendChild(styleElement);

    const vpnHtml = `
        <div id="vpn-container" class="fixed top-0 left-0 bg-gray-100 border border-gray-300 p-4 shadow-md z-50 w-64">
          <h1 class="text-lg font-bold mb-2">Conceptual Web VPN</h1>
          <select id="serverList" class="w-full p-2 border border-gray-300 rounded">
            <option value="">Select Server</option>
            <option value="us-ny">US - New York</option>
            <option value="us-la">US - Los Angeles</option>
            <option value="us-chi">US - Chicago</option>
            <option value="us-sf">US - San Francisco</option>
            <option value="uk-london">UK - London</option>
            <option value="ca-toronto">CA - Toronto</option>
            <option value="au-sydney">AU - Sydney</option>
            <option value="de-berlin">DE - Berlin</option>
            <option value="fr-paris">FR - Paris</option>
            <option value="jp-tokyo">JP - Tokyo</option>
            <option value="sg-singapore">SG - Singapore</option>
            <option value="in-mumbai">IN - Mumbai</option>
            <option value="br-sao-paulo">BR - Sao Paulo</option>
            <option value="za-johannesburg">ZA - Johannesburg</option> 
          </select>
          <button id="connectBtn" class="mt-2 w-full p-2 bg-blue-500 text-white rounded hover:bg-blue-600">Connect</button>
          <div id="status" class="mt-2 font-bold">Disconnected</div>
          <button id="fullscreenBtn" class="mt-2 w-full p-2 bg-green-500 text-white rounded hover:bg-green-600">Fullscreen</button>
        </div>
    `;

    const div = document.createElement('div');
    div.innerHTML = vpnHtml;
    document.body.appendChild(div);

    const vpnContainer = document.getElementById('vpn-container');
    const serverList = document.getElementById('serverList');
    const connectBtn = document.getElementById('connectBtn');
    const statusDiv = document.getElementById('status');
    const fullscreenBtn = document.getElementById('fullscreenBtn');

    connectBtn.addEventListener('click', () => {
        if (serverList.value) {
            statusDiv.textContent = 'Connecting...';
            setTimeout(() => {
                statusDiv.textContent = 'Connected to ' + serverList.value;
            }, 1000);
        } else {
            statusDiv.textContent = 'Please select a server.';
        }
    });

    let isFullscreen = false;
    fullscreenBtn.addEventListener('click', () => {
        isFullscreen = !isFullscreen;
        if (isFullscreen) {
            vpnContainer.classList.add('w-screen', 'h-screen');
            vpnContainer.style.top = '0';
            vpnContainer.style.left = '0';
            vpnContainer.style.transform = '';

        } else {
            vpnContainer.classList.remove('w-screen', 'h-screen');
            vpnContainer.style.width = '64px';
            vpnContainer.style.height = 'auto';

        }
    });


    let isDragging = false;
    let offsetX, offsetY;

    vpnContainer.addEventListener('mousedown', (e) => {
        if (!isFullscreen) return;
        isDragging = true;
        offsetX = e.clientX - vpnContainer.offsetLeft;
        offsetY = e.clientY - vpnContainer.offsetTop;
    });

    document.addEventListener('mousemove', (e) => {
        if (!isDragging || !isFullscreen) return;
        vpnContainer.style.left = (e.clientX - offsetX) + 'px';
        vpnContainer.style.top = (e.clientY - offsetY) + 'px';
    });

    document.addEventListener('mouseup', () => {
        isDragging = false;
    });

    document.addEventListener('keydown', (e) => {
        if (e.ctrlKey && e.key === 'l' && e.repeatCount === 2) {
            fullscreenBtn.click(); // Toggle fullscreen on Ctrl+L+L
        }
    });
})();