Enhanced Conceptual Web VPN

An improved conceptual Web VPN interface

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 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
        }
    });
})();