Compare commits

..

6 Commits
0.3 ... main

17 changed files with 558 additions and 47 deletions

View File

@ -1,8 +1,10 @@
[default] [default]
template_dir = "static/html" template_dir = "static/html"
ip_header = "Proxy-Real-IP"
[debug] [debug]
address = "127.0.0.1" # address = "127.0.0.1"
address = "192.168.2.169"
port = 8000 port = 8000
[release] [release]

View File

@ -1,8 +1,19 @@
#[macro_use] extern crate rocket; #[macro_use] extern crate rocket;
use rocket::form::Form; use rocket::{form::Form, shield::{Hsts, NoSniff}, time::Duration};
use rocket_dyn_templates::{Template, context}; use rocket_dyn_templates::{Template, context};
use rocket::fs::FileServer; use rocket::fs::FileServer;
use rocket::shield::Shield;
use std::net::{IpAddr, Ipv4Addr};
fn ip_to_ipv4(ip: IpAddr) -> Option<Ipv4Addr> {
if let IpAddr::V4(v4_addr) = ip {
Some(v4_addr)
} else {
None
}
}
#[derive(FromForm)] #[derive(FromForm)]
struct LoginData { struct LoginData {
@ -25,15 +36,28 @@ fn login(login_data: Form<LoginData>) -> Template {
} }
#[get("/")] #[get("/")]
fn index() -> Template { fn index(ip: IpAddr) -> Template {
if let Some(ipv4) = ip_to_ipv4(ip) {
if ipv4.is_private() || ipv4.is_loopback() {
Template::render("index", context! {
local: true,
})
} else {
Template::render("index", context! {}) Template::render("index", context! {})
} }
} else {
Template::render("index", context! {})
}
}
#[launch] #[launch]
fn rocket() -> _ { fn rocket() -> _ {
let shield = Shield::new()
.enable(Hsts::Enable(Duration::MAX))
.enable(NoSniff::Enable);
rocket::build() rocket::build()
.mount("/", routes![index, login]) .mount("/", routes![index, login])
.mount("/static", FileServer::from("static")) // Serves files in the `static` directory .mount("/static", FileServer::from("static"))
.attach(shield)
.attach(Template::fairing()) .attach(Template::fairing())
} }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -0,0 +1,92 @@
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.navbar {
background-color: #333;
padding: 0.5rem 1rem;
position: relative;
}
.navbar-container {
display: flex;
justify-content: space-between;
align-items: center;
position: relative;
}
.logo {
font-size: 1.5rem;
text-decoration: none;
color: white;
}
.nav-links {
list-style: none;
display: flex;
gap: 1rem;
position: relative;
overflow: hidden;
}
.nav-links.active {
height: auto; /* Expand naturally */
visibility: visible;
opacity: 1;
}
.nav-links a {
text-decoration: none;
color: white;
transition: color 0.3s ease;
padding: 10px 12px;
}
.nav-links a:hover {
background-color: #888;
}
.menu-toggle {
display: none;
font-size: 1.5rem;
color: white;
background: none;
border: none;
cursor: pointer;
}
/* Responsive Styles */
/* Mobile View Styles */
@media (max-width: 768px) {
.menu-toggle {
display: block;
}
.nav-links {
flex-direction: column;
background-color: #444;
position: absolute;
top: 100%;
left: 0;
width: 100%;
opacify: 0;
overflow: hidden;
height: 0;
visibility: hidden;
display: flex;
}
/* .nav-links.active { */
/* height: 2rem; /* Expanded state */ */
/* visibility: visible; */
/* opacity: 1; */
/* } */
/**/
/* .nav-links a { */
/* padding: 0.5rem 1rem; */
/* text-align: center; */
/* height: 1rem; */
/* } */
}

View File

@ -0,0 +1,84 @@
* {
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
}
.navbar {
background-color: #333;
color: white;
padding: 0.5rem 1rem;
position: relative; /* Ensure the navbar remains anchored */
}
.navbar-container {
display: flex;
justify-content: space-between;
align-items: center;
max-width: 1200px;
margin: 0 auto;
position: relative; /* Key to make dropdown align properly */
}
.logo {
font-size: 1.5rem;
text-decoration: none;
color: white;
}
.nav-links {
list-style: none;
display: flex;
gap: 1rem;
position: absolute; /* Align it below the navbar */
top: 100%; /* Start right below the navbar */
left: 0;
width: 100%; /* Full width of the navbar */
background-color: #444;
flex-direction: column;
overflow: hidden;
height: 0;
visibility: hidden;
opacity: 0;
z-index: 10; /* Ensure it's on top */
}
.nav-links.active {
height: auto; /* Expand naturally */
visibility: visible;
opacity: 1;
}
.nav-links a {
padding: 0.5rem 1rem;
text-align: center;
text-decoration: none;
color: white;
transition: background-color 0.3s ease;
}
.nav-links a:hover {
background-color: #555;
}
.menu-toggle {
display: none;
font-size: 1.5rem;
color: white;
background: none;
border: none;
cursor: pointer;
}
/* Responsive Styles */
@media (max-width: 768px) {
.menu-toggle {
display: block;
}
.nav-links {
display: flex;
}
}

View File

@ -0,0 +1,30 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Responsive Navbar</title>
<link rel="stylesheet" href="/static/css/styles.css">
</head>
<body>
<nav class="navbar">
<div class="navbar-container">
<a href="#" class="logo">MyWebsite</a>
<button class="menu-toggle" id="menu-toggle" aria-label="Toggle menu">
</button>
<ul class="nav-links" id="nav-links">
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
{% if local %}
<li><a href="#">Services</a></li>
{% endif %}
<li><a href="#">Contact</a></li>
</ul>
</div>
</nav>
<script src="/static/js/script.js"></script>
</body>
</html>

14
static-old2/js/script.js Normal file
View File

@ -0,0 +1,14 @@
document.getElementById("menu-toggle").addEventListener("click", function () {
const navLinks = document.getElementById("nav-links");
navLinks.classList.toggle("active");
});
// const navLinks = document.getElementById("nav-links");
// window.addEventListener("resize", () => {
// if (window.innerWidth > 768) {
// navLinks.classList.remove("active"); // Ensure mobile styles are removed
// navLinks.style.height = ""; // Reset height
// navLinks.style.visibility = ""; // Reset visibility
// navLinks.style.opacity = ""; // Reset opacity
// }
// });

99
static/css/styles.css Normal file
View File

@ -0,0 +1,99 @@
* {
margin: 0;
padding: 0;
}
body {
margin: 0;
font-family: Arial, sans-serif;
}
.navbar {
background-color: #333;
color: #fff;
padding-left: 5px;
padding-right: 7px;
position: relative;
z-index: 1000;
}
.navbar-container {
display: flex;
justify-content: space-between;
align-items: center;
}
.logo {
width: 5%;
height: 5%;
margin-top: 2px;
}
.nav-links {
list-style: none;
display: flex;
gap: 1.5rem;
margin: 1rem;
}
.nav-links a {
color: #fff;
text-decoration: none;
font-size: 1.3rem;
cursor: pointer;
}
.nav-toggle {
display: none;
flex-direction: column;
gap: 5px;
background: none;
border: none;
cursor: pointer;
margin: 20px;
}
.iframe-container {
width: 100%;
height: 100vh;
border: none;
display: block;
}
@media (max-width: 768px) {
.nav-links {
display: none;
flex-direction: column;
gap: 0;
position: absolute;
background-color: #333;
width: 100%;
top: 100%;
left: 0;
margin: 0;
}
.nav-links.active {
display: flex;
}
.nav-toggle {
display: flex;
margin-right: 10px;
}
.nav-links li {
text-align: center;
margin-bottom: 1rem;
}
.nav-links a {
display: block;
width: 100%;
}
.logo {
width: 10%;
height: 10%;
}
}

File diff suppressed because one or more lines are too long

22
static/icons/logo.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 25 KiB

5
static/icons/menu.svg Normal file
View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" fill="none">
<path fill="#F8F8F2" fill-rule="evenodd" d="M19 4a1 1 0 01-1 1H2a1 1 0 010-2h16a1 1 0 011 1zm0 6a1 1 0 01-1 1H2a1 1 0 110-2h16a1 1 0 011 1zm-1 7a1 1 0 100-2H2a1 1 0 100 2h16z"/>
</svg>

After

Width:  |  Height:  |  Size: 339 B

52
static/js/scripts.js Normal file
View File

@ -0,0 +1,52 @@
function loadIframe(url) {
const iframeWrapper = document.getElementById("iframe-wrapper");
iframeWrapper.innerHTML = "";
const iframe = document.createElement("iframe");
iframe.src = url;
iframe.className = "iframe-container";
iframeWrapper.appendChild(iframe);
iframe.addEventListener("load", function() {
try {
iframe.contentWindow.document.addEventListener("click", function() {
window.scrollTo({ top: document.body.scrollHeight, behavior: "smooth" });
});
} catch (error) {
console.warn("Cross-origin iframe: Cannot access iframe content.");
}
});
const navLinks = document.getElementById('nav-links');
navLinks.classList.remove('active');
}
function clearIframe() {
document.getElementById("iframe-wrapper").innerHTML = "";
const navLinks = document.getElementById('nav-links');
navLinks.classList.remove('active');
}
document.addEventListener('DOMContentLoaded', () => {
//const navToggle = document.querySelector('.nav-toggle');
//const navLinks = document.querySelector('.nav-links');
//
//navToggle.addEventListener('click', () => {
// navLinks.classList.toggle('active');
//});
document.addEventListener("click", function (event) {
const navLinks = document.getElementById("nav-links");
const toggleButton = document.getElementById("nav-toggle");
if (navLinks.classList.contains("active")) {
if (!navLinks.contains(event.target) && !toggleButton.contains(event.target)) {
navLinks.classList.remove("expanded");
}
}
const button = event.target.closest("button");
if (button && button.className === "nav-toggle") {
navLinks.classList.toggle('active');
}
});
});