move into http://box own landing page; fix blind timer
This commit is contained in:
parent
350e1f31c6
commit
78e0c3c099
|
|
@ -1,131 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Safe Pocket Web</title>
|
|
||||||
<style>
|
|
||||||
/* Basic reset and background */
|
|
||||||
body {
|
|
||||||
margin: 0; padding: 0;
|
|
||||||
background-color: #F4F7F6;
|
|
||||||
font-family: 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
|
||||||
min-height: 100vh;
|
|
||||||
display: flex; flex-direction: column;
|
|
||||||
justify-content: center; align-items: center;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Header styles */
|
|
||||||
.top-header {
|
|
||||||
position: absolute;
|
|
||||||
top: 0; left: 0; width: 100%;
|
|
||||||
display: flex; align-items: center;
|
|
||||||
padding: 16px 20px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-logo {
|
|
||||||
width: 48px;
|
|
||||||
height: 48px;
|
|
||||||
object-fit: contain;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-title {
|
|
||||||
flex-grow: 1;
|
|
||||||
text-align: center;
|
|
||||||
margin: 0;
|
|
||||||
font-size: 22px;
|
|
||||||
font-weight: 900;
|
|
||||||
color: #2C3E50;
|
|
||||||
padding-right: 48px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Button container */
|
|
||||||
.menu-container {
|
|
||||||
width: 80%; display: flex;
|
|
||||||
flex-direction: column; gap: 20px;
|
|
||||||
margin-top: 60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Button styles */
|
|
||||||
.btn {
|
|
||||||
display: flex; align-items: center; justify-content: center;
|
|
||||||
padding: 18px; border-radius: 14px; text-decoration: none;
|
|
||||||
font-size: 20px; font-weight: bold;
|
|
||||||
box-shadow: 0 4px 10px rgba(0,0,0,0.15);
|
|
||||||
transition: transform 0.1s, box-shadow 0.1s;
|
|
||||||
}
|
|
||||||
.btn:active { transform: scale(0.96); box-shadow: 0 2px 5px rgba(0,0,0,0.2); }
|
|
||||||
|
|
||||||
/* App colors */
|
|
||||||
.btn-books { background-color: #00BCD4; color: #FFFFFF; }
|
|
||||||
.btn-kiwix { background-color: #FF9800; color: #FFFFFF; }
|
|
||||||
.btn-kolibri { background-color: #FFD54F; color: #333333; }
|
|
||||||
.btn-maps { background-color: #4CAF50; color: #FFFFFF; }
|
|
||||||
.btn-matomo { background-color: #1976D2; color: #FFFFFF; }
|
|
||||||
|
|
||||||
.btn span { margin-right: 12px; font-size: 26px; }
|
|
||||||
|
|
||||||
/* Spinner and Overlay styles */
|
|
||||||
#loadingOverlay {
|
|
||||||
display: none;
|
|
||||||
position: fixed; top: 0; left: 0; width: 100%; height: 100%;
|
|
||||||
background-color: rgba(244, 247, 246, 0.85);
|
|
||||||
z-index: 9999;
|
|
||||||
flex-direction: column; justify-content: center; align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.spinner {
|
|
||||||
width: 50px; height: 50px;
|
|
||||||
border: 6px solid #E0E0E0;
|
|
||||||
border-top: 6px solid #1976D2;
|
|
||||||
border-radius: 50%;
|
|
||||||
animation: spin 1s linear infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
|
|
||||||
.loading-text { margin-top: 15px; font-size: 18px; font-weight: bold; color: #333; }
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<header class="top-header">
|
|
||||||
<img src="logo.svg" alt="IIAB Logo" class="header-logo">
|
|
||||||
<h1 class="header-title">Internet-in-a-Box<br />on Android</h1>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<div id="loadingOverlay">
|
|
||||||
<div class="spinner"></div>
|
|
||||||
<div class="loading-text" id="loadingText">Loading...</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="menu-container">
|
|
||||||
<a href="http://box/books" class="btn btn-books"><span>📖</span> Books</a>
|
|
||||||
<a href="http://box/kiwix" class="btn btn-kiwix"><span>🥝</span> Kiwix</a>
|
|
||||||
<a href="http://box/kolibri" class="btn btn-kolibri"><span>📚</span> Kolibri</a>
|
|
||||||
<a href="http://box/maps" class="btn btn-maps"><span>🗺️</span> Maps</a>
|
|
||||||
<a href="http://box/matomo" class="btn btn-matomo"><span>📊</span> Matomo</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
const overlay = document.getElementById('loadingOverlay');
|
|
||||||
const textLabel = document.getElementById('loadingText');
|
|
||||||
const buttons = document.querySelectorAll('.btn');
|
|
||||||
|
|
||||||
buttons.forEach(btn => {
|
|
||||||
btn.addEventListener('click', function(e) {
|
|
||||||
const appName = this.innerText.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]|\uD83C[\uDF00-\uDFFF]|\uD83D[\uDC00-\uDE4F]/g, '').trim();
|
|
||||||
// Cambiado a Opening
|
|
||||||
textLabel.innerText = 'Opening ' + appName + '...';
|
|
||||||
overlay.style.display = 'flex';
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
window.addEventListener('pageshow', function(event) {
|
|
||||||
overlay.style.display = 'none';
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
|
||||||
|
|
||||||
// 1. Detect device language
|
|
||||||
let userLang = (navigator.language || navigator.userLanguage).substring(0, 2).toLowerCase();
|
|
||||||
|
|
||||||
// Function to detect the user's language
|
|
||||||
const applyTranslations = () => {
|
|
||||||
if (!window.i18n) return; // If something went wrong, we return
|
|
||||||
|
|
||||||
// Search for all elements with the data-i18n attribute
|
|
||||||
const elements = document.querySelectorAll("[data-i18n]");
|
|
||||||
|
|
||||||
elements.forEach(el => {
|
|
||||||
const key = el.getAttribute("data-i18n");
|
|
||||||
// Si la clave existe en el diccionario, reemplaza el texto
|
|
||||||
if (window.i18n[key]) {
|
|
||||||
el.innerText = window.i18n[key];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Function to load the .js file of the language
|
|
||||||
const loadScript = (langCode, isFallback = false) => {
|
|
||||||
const script = document.createElement("script");
|
|
||||||
script.src = `lang/${langCode}.js`;
|
|
||||||
|
|
||||||
// If the file exists, we apply the translations
|
|
||||||
script.onload = () => applyTranslations();
|
|
||||||
|
|
||||||
// If the file does NOT exist
|
|
||||||
script.onerror = () => {
|
|
||||||
if (!isFallback) {
|
|
||||||
console.log(`Idioma ${langCode} no encontrado. Cargando inglés...`);
|
|
||||||
loadScript("en", true); // Intentamos con el idioma por defecto
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
document.head.appendChild(script);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 2. Start the script loading
|
|
||||||
loadScript(userLang);
|
|
||||||
});
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
window.i18n = {
|
|
||||||
"title": "Choose Content",
|
|
||||||
"maps": "🗺️ Maps",
|
|
||||||
"kolibri": "📚 Kolibri",
|
|
||||||
"kiwix": "📖 Kiwix",
|
|
||||||
"books": "📕 Books"
|
|
||||||
};
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
window.i18n = {
|
|
||||||
"title": "Elige el Contenido",
|
|
||||||
"maps": "🗺️ Mapas",
|
|
||||||
"kolibri": "📚 Kolibri",
|
|
||||||
"kiwix": "📖 Kiwix",
|
|
||||||
"books": "📕 Libros"
|
|
||||||
};
|
|
||||||
|
|
@ -41,10 +41,54 @@ public class PortalActivity extends AppCompatActivity {
|
||||||
Button btnExit = findViewById(R.id.btnExit);
|
Button btnExit = findViewById(R.id.btnExit);
|
||||||
Button btnForward = findViewById(R.id.btnForward);
|
Button btnForward = findViewById(R.id.btnForward);
|
||||||
|
|
||||||
|
// --- PREPARE HIDDEN BAR ---
|
||||||
|
// Wait for Android to draw the screen to determine bar height
|
||||||
|
// and hide it exactly below the bottom edge.
|
||||||
|
bottomNav.post(() -> {
|
||||||
|
bottomNav.setTranslationY(bottomNav.getHeight()); // Move outside the screen
|
||||||
|
bottomNav.setVisibility(View.VISIBLE); // Remove invisibility
|
||||||
|
});
|
||||||
|
|
||||||
|
// --- AUTO-HIDE TIMER ---
|
||||||
|
Handler hideHandler = new Handler(Looper.getMainLooper());
|
||||||
|
|
||||||
|
// This is the hiding action packaged for later use
|
||||||
|
Runnable hideRunnable = () -> {
|
||||||
|
bottomNav.animate().translationY(bottomNav.getHeight()).setDuration(250);
|
||||||
|
btnHandle.setVisibility(View.VISIBLE);
|
||||||
|
btnHandle.animate().alpha(1f).setDuration(150);
|
||||||
|
};
|
||||||
|
|
||||||
|
// --- Restart timer ---
|
||||||
|
Runnable resetTimer = () -> {
|
||||||
|
hideHandler.removeCallbacks(hideRunnable);
|
||||||
|
hideHandler.postDelayed(hideRunnable, 5000); // Restarts new 5 sec
|
||||||
|
};
|
||||||
|
|
||||||
|
// --- HANDLE LOGIC (Show Bar) ---
|
||||||
|
btnHandle.setOnClickListener(v -> {
|
||||||
|
// 1. Animate entry
|
||||||
|
btnHandle.animate().alpha(0f).setDuration(150).withEndAction(() -> btnHandle.setVisibility(View.GONE));
|
||||||
|
bottomNav.animate().translationY(0).setDuration(250);
|
||||||
|
|
||||||
|
// 2. Starts countdown
|
||||||
|
resetTimer.run();
|
||||||
|
});
|
||||||
// Button actions
|
// Button actions
|
||||||
btnBack.setOnClickListener(v -> { if (webView.canGoBack()) webView.goBack(); });
|
btnBack.setOnClickListener(v -> {
|
||||||
btnForward.setOnClickListener(v -> { if (webView.canGoForward()) webView.goForward(); });
|
if (webView.canGoBack()) webView.goBack();
|
||||||
btnHome.setOnClickListener(v -> webView.loadUrl("file:///android_asset/index.html"));
|
resetTimer.run();
|
||||||
|
});
|
||||||
|
|
||||||
|
btnForward.setOnClickListener(v -> {
|
||||||
|
if (webView.canGoForward()) webView.goForward();
|
||||||
|
resetTimer.run();
|
||||||
|
});
|
||||||
|
|
||||||
|
btnHome.setOnClickListener(v -> {
|
||||||
|
webView.loadUrl("http://box/");
|
||||||
|
resetTimer.run();
|
||||||
|
});
|
||||||
|
|
||||||
// Dual logic: Forced reload or Stop
|
// Dual logic: Forced reload or Stop
|
||||||
btnReload.setOnClickListener(v -> {
|
btnReload.setOnClickListener(v -> {
|
||||||
|
|
@ -56,6 +100,7 @@ public class PortalActivity extends AppCompatActivity {
|
||||||
// 2. Force download from scratch
|
// 2. Force download from scratch
|
||||||
webView.reload();
|
webView.reload();
|
||||||
}
|
}
|
||||||
|
resetTimer.run();
|
||||||
});
|
});
|
||||||
|
|
||||||
// --- NEW: DETECT LOADING TO CHANGE BUTTON TO 'X' ---
|
// --- NEW: DETECT LOADING TO CHANGE BUTTON TO 'X' ---
|
||||||
|
|
@ -65,17 +110,12 @@ public class PortalActivity extends AppCompatActivity {
|
||||||
String url = request.getUrl().toString();
|
String url = request.getUrl().toString();
|
||||||
String host = request.getUrl().getHost();
|
String host = request.getUrl().getHost();
|
||||||
|
|
||||||
// 1. Local main menu
|
// 1. Internal server link (Box)
|
||||||
if (url.startsWith("file://")) {
|
|
||||||
return false; // return false means: "WebView, handle it yourself"
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Internal server link (Box)
|
|
||||||
if (host != null && (host.equals("box") || host.equals("127.0.0.1") || host.equals("localhost"))) {
|
if (host != null && (host.equals("box") || host.equals("127.0.0.1") || host.equals("localhost"))) {
|
||||||
return false; // Remains in our app and travels through the proxy
|
return false; // Remains in our app and travels through the proxy
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. External link (Real Internet)
|
// 2. External link (Real Internet)
|
||||||
try {
|
try {
|
||||||
// Tell Android to find the correct app to open this (Chrome, YouTube, etc.)
|
// Tell Android to find the correct app to open this (Chrome, YouTube, etc.)
|
||||||
Intent intent = new Intent(Intent.ACTION_VIEW, request.getUrl());
|
Intent intent = new Intent(Intent.ACTION_VIEW, request.getUrl());
|
||||||
|
|
@ -104,35 +144,6 @@ public class PortalActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// --- PREPARE HIDDEN BAR ---
|
|
||||||
// Wait for Android to draw the screen to determine bar height
|
|
||||||
// and hide it exactly below the bottom edge.
|
|
||||||
bottomNav.post(() -> {
|
|
||||||
bottomNav.setTranslationY(bottomNav.getHeight()); // Move outside the screen
|
|
||||||
bottomNav.setVisibility(View.VISIBLE); // Remove invisibility
|
|
||||||
});
|
|
||||||
|
|
||||||
// --- AUTO-HIDE TIMER ---
|
|
||||||
Handler hideHandler = new Handler(Looper.getMainLooper());
|
|
||||||
|
|
||||||
// This is the hiding action packaged for later use
|
|
||||||
Runnable hideRunnable = () -> {
|
|
||||||
bottomNav.animate().translationY(bottomNav.getHeight()).setDuration(250);
|
|
||||||
btnHandle.setVisibility(View.VISIBLE);
|
|
||||||
btnHandle.animate().alpha(1f).setDuration(150);
|
|
||||||
};
|
|
||||||
|
|
||||||
// --- HANDLE LOGIC (Show Bar) ---
|
|
||||||
btnHandle.setOnClickListener(v -> {
|
|
||||||
// 1. Animate entry
|
|
||||||
btnHandle.animate().alpha(0f).setDuration(150).withEndAction(() -> btnHandle.setVisibility(View.GONE));
|
|
||||||
bottomNav.animate().translationY(0).setDuration(250);
|
|
||||||
|
|
||||||
// 2. Start 5-second countdown (5000 ms)
|
|
||||||
hideHandler.removeCallbacks(hideRunnable); // Cancel if there was a previous countdown
|
|
||||||
hideHandler.postDelayed(hideRunnable, 5000); // Change 5000 to 7000 for 7 seconds
|
|
||||||
});
|
|
||||||
|
|
||||||
// --- MANUALLY CLOSE BAR LOGIC ---
|
// --- MANUALLY CLOSE BAR LOGIC ---
|
||||||
btnHideNav.setOnClickListener(v -> {
|
btnHideNav.setOnClickListener(v -> {
|
||||||
hideHandler.removeCallbacks(hideRunnable); // Cancel the timer so it doesn't conflict
|
hideHandler.removeCallbacks(hideRunnable); // Cancel the timer so it doesn't conflict
|
||||||
|
|
@ -163,13 +174,13 @@ public class PortalActivity extends AppCompatActivity {
|
||||||
ProxyController.getInstance().setProxyOverride(proxyConfig, executor, () -> {
|
ProxyController.getInstance().setProxyOverride(proxyConfig, executor, () -> {
|
||||||
Log.d(TAG, "Proxy configured on port: " + finalProxyPort);
|
Log.d(TAG, "Proxy configured on port: " + finalProxyPort);
|
||||||
// Load HTML only when proxy is ready
|
// Load HTML only when proxy is ready
|
||||||
webView.loadUrl("file:///android_asset/index.html");
|
webView.loadUrl("http://box/");
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// Fallback for older devices
|
// Fallback for older devices
|
||||||
Log.w(TAG, "Proxy Override not supported");
|
Log.w(TAG, "Proxy Override not supported");
|
||||||
}
|
}
|
||||||
webView.loadUrl("file:///android_asset/index.html");
|
webView.loadUrl("http://box/");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Cleanup (Important to not leave the proxy active)
|
// 4. Cleanup (Important to not leave the proxy active)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue