Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9e4c0524af | ||
|
|
3f0c008488 | ||
|
|
b24b641a8f | ||
|
|
9277303969 | ||
|
|
357ac871bf | ||
|
|
b7e704afc2 | ||
|
|
6646697b70 | ||
|
|
22106a76f1 | ||
|
|
1d0588fa69 | ||
|
|
d880520882 | ||
|
|
f0ab8eff41 | ||
|
|
0ae1664ce1 | ||
|
|
edfc4d833f | ||
|
|
c5214343c7 | ||
|
|
506b0ff09d | ||
|
|
d207a96ea5 | ||
|
|
f1232d639c | ||
|
|
a0c79989cd | ||
|
|
7df3a530ce | ||
|
|
7e2c27d165 |
@@ -0,0 +1,33 @@
|
|||||||
|
# .github/workflows/build-3ds.yml
|
||||||
|
|
||||||
|
name: Build 3DS CIA
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ "main", "master" ] # Se déclenche sur un push vers main ou master
|
||||||
|
pull_request:
|
||||||
|
branches: [ "main", "master" ] # Se déclenche aussi sur les pull requests
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Build CIA
|
||||||
|
runs-on: ubuntu-latest # Utilise un runner Linux standard
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Build with devkitPro Docker image
|
||||||
|
run: |
|
||||||
|
docker run --rm \
|
||||||
|
-v ${{ github.workspace }}:/project \
|
||||||
|
-w /project/3ds \
|
||||||
|
devkitpro/devkitarm:latest \
|
||||||
|
bash -c "source /etc/profile.d/devkit-env.sh && make cia"
|
||||||
|
|
||||||
|
- name: Upload CIA as artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: OpenPlanetsMaps-CIA
|
||||||
|
path: 3ds/OpenPlanetsMaps.cia
|
||||||
|
if-no-files-found: error # Fait échouer le workflow si le CIA n'est pas trouvé
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
name: Build Electron App
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- "AppPhoneAPK&IPA"
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: windows-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout du code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Configuration de Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: '22'
|
||||||
|
cache: 'npm' # Ajout du cache pour npm
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Build de l'application (Windows)
|
||||||
|
run: npm run build
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
name: Build Mobile Apps (APK & IPA)
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- "AppPhoneAPK&IPA"
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-android:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout du code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Configuration de Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: '22'
|
||||||
|
|
||||||
|
- name: Configuration de Java (Requis pour Android)
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: 'zulu'
|
||||||
|
java-version: '21'
|
||||||
|
|
||||||
|
- name: Installation des dépendances
|
||||||
|
run: npm install
|
||||||
|
|
||||||
|
- name: Génération propre du dossier Android
|
||||||
|
run: |
|
||||||
|
rm -rf android
|
||||||
|
npx cap add android
|
||||||
|
npx cap sync android
|
||||||
|
|
||||||
|
- name: Build de l'APK Android
|
||||||
|
run: |
|
||||||
|
cd android
|
||||||
|
chmod +x gradlew
|
||||||
|
./gradlew assembleDebug
|
||||||
|
|
||||||
|
- name: Upload de l'APK
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: OpenPlanetsMaps-Android-APK
|
||||||
|
path: android/app/build/outputs/apk/debug/app-debug.apk
|
||||||
|
|
||||||
|
build-android-playstore:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout du code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Configuration de Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: '22'
|
||||||
|
|
||||||
|
- name: Configuration de Java (Requis pour Android)
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: 'zulu'
|
||||||
|
java-version: '21'
|
||||||
|
|
||||||
|
- name: Installation des dépendances
|
||||||
|
run: npm install
|
||||||
|
|
||||||
|
- name: Génération propre du dossier Android
|
||||||
|
run: |
|
||||||
|
rm -rf android
|
||||||
|
npx cap add android
|
||||||
|
npx cap sync android
|
||||||
|
|
||||||
|
- name: Build du Bundle Play Store (AAB)
|
||||||
|
run: |
|
||||||
|
cd android
|
||||||
|
chmod +x gradlew
|
||||||
|
./gradlew bundleRelease
|
||||||
|
|
||||||
|
- name: Upload du Bundle Play Store (AAB)
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: OpenPlanetsMaps-Android-PlayStore-AAB
|
||||||
|
path: android/app/build/outputs/bundle/release/*.aab
|
||||||
|
|
||||||
|
build-ios:
|
||||||
|
runs-on: macos-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout du code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Configuration de Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: '22'
|
||||||
|
cache: 'npm' # Ajout du cache pour npm
|
||||||
|
|
||||||
|
- name: Installation des dépendances
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Génération propre du dossier iOS
|
||||||
|
run: |
|
||||||
|
rm -rf ios
|
||||||
|
npx cap add ios
|
||||||
|
npx cap sync ios
|
||||||
|
|
||||||
|
- name: Build iOS (Non signé)
|
||||||
|
run: |
|
||||||
|
cd ios/App
|
||||||
|
xcodebuild -project App.xcodeproj -scheme App -configuration Debug -sdk iphoneos build CODE_SIGNING_ALLOWED=NO CODE_SIGNING_REQUIRED=NO CODE_SIGNING_IDENTITY="" SYMROOT=$GITHUB_WORKSPACE/ios/App/build
|
||||||
|
|
||||||
|
# Création forcée de l'IPA (Non signé)
|
||||||
|
cd $GITHUB_WORKSPACE/ios/App/build/Debug-iphoneos
|
||||||
|
mkdir -p Payload
|
||||||
|
cp -R App.app Payload/
|
||||||
|
zip -r $GITHUB_WORKSPACE/OpenPlanetsMaps-iOS-Unsigned.ipa Payload
|
||||||
|
|
||||||
|
- name: Upload de l'IPA (Non signé)
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: OpenPlanetsMaps-iOS-IPA
|
||||||
|
path: OpenPlanetsMaps-iOS-Unsigned.ipa
|
||||||
@@ -1 +1,17 @@
|
|||||||
www/config.php
|
# Dépendances Node.js
|
||||||
|
node_modules/
|
||||||
|
npm-debug.log
|
||||||
|
|
||||||
|
# Fichiers de compilation Electron
|
||||||
|
dist/
|
||||||
|
dist-electron/
|
||||||
|
out/
|
||||||
|
release/
|
||||||
|
|
||||||
|
# Fichiers systèmes
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Fichiers d'environnement (si tu en as plus tard)
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"label": "3DS: Build CIA (Docker)",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "docker run --rm -v \"${workspaceFolder}:/project\" -w /project/3ds devkitpro/devkitarm:latest bash -c 'source /etc/profile.d/devkit-env.sh && make cia'",
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
"problemMatcher": [],
|
||||||
|
"presentation": {
|
||||||
|
"echo": true,
|
||||||
|
"reveal": "always",
|
||||||
|
"focus": false,
|
||||||
|
"panel": "shared",
|
||||||
|
"showReuseMessage": true,
|
||||||
|
"clear": false
|
||||||
|
},
|
||||||
|
"detail": "Compile le projet 3DS en .cia en utilisant l'image Docker de devkitPro."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "3DS: Clean Build (Docker)",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "docker run --rm -v \"${workspaceFolder}:/project\" -w /project/3ds devkitpro/devkitarm:latest bash -c 'source /etc/profile.d/devkit-env.sh && make clean'",
|
||||||
|
"group": "build",
|
||||||
|
"problemMatcher": [],
|
||||||
|
"presentation": {
|
||||||
|
"echo": true,
|
||||||
|
"reveal": "always",
|
||||||
|
"focus": false,
|
||||||
|
"panel": "shared",
|
||||||
|
"showReuseMessage": true,
|
||||||
|
"clear": true
|
||||||
|
},
|
||||||
|
"detail": "Nettoie les fichiers de build du projet 3DS."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
name: Build 3DS App (CIA)
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- "AppPhoneAPK&IPA" # Déclenché sur la même branche que les autres builds
|
||||||
|
paths:
|
||||||
|
- '3ds/**' # Uniquement si des fichiers dans 3ds/ sont modifiés
|
||||||
|
- 'SRC/**' # Ou si les sources web sont modifiées
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-3ds:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container: devkitpro/devkitarm:latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout du code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Préparation des fichiers RomFS
|
||||||
|
run: |
|
||||||
|
echo "Copie des fichiers web vers le dossier romfs..."
|
||||||
|
mkdir -p 3ds/romfs
|
||||||
|
cp -r SRC/* 3ds/romfs/
|
||||||
|
|
||||||
|
- name: Compilation de l'application 3DS
|
||||||
|
working-directory: ./3ds
|
||||||
|
run: |
|
||||||
|
echo "Lancement du build 3DS via make..."
|
||||||
|
make cia
|
||||||
|
|
||||||
|
- name: Upload de l'artefact CIA
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: OpenPlanetsMaps-3DS-CIA
|
||||||
|
path: 3ds/OpenPlanetsMaps.cia
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
# 3ds/Makefile
|
||||||
|
|
||||||
|
# --- Configuration du Projet ---
|
||||||
|
TARGET := OpenPlanetsMaps_3DS # Nom du .elf, .3dsx, .smdh
|
||||||
|
CIA_TARGET := OpenPlanetsMaps.cia # Nom du fichier .cia final
|
||||||
|
NAME := OpenPlanetsMaps
|
||||||
|
AUTHOR := Tezca
|
||||||
|
DESCRIPTION := Visionneur de données astronomiques
|
||||||
|
|
||||||
|
# --- Fichiers et Dossiers ---
|
||||||
|
SOURCES := source
|
||||||
|
DATA := romfs
|
||||||
|
INCLUDES := include
|
||||||
|
|
||||||
|
# --- Options de compilation ---
|
||||||
|
CXXFLAGS := -fno-rtti -fno-exceptions -std=gnu++17
|
||||||
|
|
||||||
|
# --- Bibliothèques ---
|
||||||
|
# Ajoutez des bibliothèques ici si nécessaire (ex: -lcitro2d)
|
||||||
|
LIBS := -lcitro2d -lctru -lm
|
||||||
|
|
||||||
|
# Variables d'environnement devkitPro
|
||||||
|
ifeq ($(strip $(DEVKITPRO)),)
|
||||||
|
$(error "Veuillez définir la variable d'environnement DEVKITPRO.")
|
||||||
|
endif
|
||||||
|
|
||||||
|
# --- Système de Build (ne pas modifier) ---
|
||||||
|
include $(DEVKITPRO)/lib/dkp-rules/dkp.mk
|
||||||
|
|
||||||
|
# --- Cibles de Build ---
|
||||||
|
# Les cibles 'all', 'cia', et 'clean' sont gérées automatiquement par dkp.mk
|
||||||
|
# Il n'est plus nécessaire de les définir manuellement.
|
||||||
|
After Width: | Height: | Size: 8.8 KiB |
|
After Width: | Height: | Size: 6.7 KiB |
@@ -0,0 +1,109 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
$error = '';
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'login') {
|
||||||
|
if ($_POST['username'] === 'admin' && $_POST['password'] === 'admin') {
|
||||||
|
$_SESSION['admin_logged_in'] = true;
|
||||||
|
header('Location: admin.php');
|
||||||
|
exit;
|
||||||
|
} else {
|
||||||
|
$error = 'Incorrect credentials.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($_GET['logout'])) {
|
||||||
|
session_destroy();
|
||||||
|
header('Location: admin.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$host = '172.22.0.3';
|
||||||
|
$dbname = 'OpenPlanetsMaps';
|
||||||
|
$db_user = 'root';
|
||||||
|
$db_pass = 'admin123';
|
||||||
|
|
||||||
|
$message = '';
|
||||||
|
if (isset($_SESSION['admin_logged_in']) && $_SESSION['admin_logged_in'] === true && $_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'add') {
|
||||||
|
try {
|
||||||
|
$options = [PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8", PDO::ATTR_EMULATE_PREPARES => false];
|
||||||
|
$pdo = new PDO("mysql:host=$host;port=3306;dbname=$dbname;charset=utf8;protocol=tcp", $db_user, $db_pass, $options);
|
||||||
|
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||||
|
|
||||||
|
$planete = $_POST['planete'];
|
||||||
|
$nom = $_POST['nom'];
|
||||||
|
$date = $_POST['date'];
|
||||||
|
$url = $_POST['url'];
|
||||||
|
$description = $_POST['description'];
|
||||||
|
|
||||||
|
$allowedTables = [
|
||||||
|
'mercury' => 'MERCURY', 'venus' => 'VENUS', 'earth' => 'EARTH',
|
||||||
|
'mars' => 'MARS', 'jupiter' => 'JUPITER', 'saturn' => 'SATURN',
|
||||||
|
'uranus' => 'URANUS', 'neptune' => 'NEPTUNE'
|
||||||
|
];
|
||||||
|
|
||||||
|
if (array_key_exists($planete, $allowedTables)) {
|
||||||
|
$nomTable = $allowedTables[$planete];
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO $nomTable (title, date, url, explanation) VALUES (?, ?, ?, ?)");
|
||||||
|
$stmt->execute([$nom, $date, $url, $description]);
|
||||||
|
|
||||||
|
$message = "<p style='color: #4ade80; text-align: center; margin-bottom: 1rem;'>Row successfully added to the $nomTable table!</p>";
|
||||||
|
}
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$message = "<p style='color: #f87171; text-align: center; margin-bottom: 1rem;'>SQL Error: " . $e->getMessage() . "</p>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Admin Panel - OpenPlanetsMaps</title>
|
||||||
|
<link rel="stylesheet" href="3ds/romfs/style.css">
|
||||||
|
<style>
|
||||||
|
body { background-color: #0f172a; color: #e0e0e0; display: flex; justify-content: center; align-items: center; padding: 2rem; min-height: 100vh; }
|
||||||
|
.admin-box { background-color: #1e293b; padding: 2rem; border-radius: 8px; box-shadow: 0 4px 15px rgba(0,0,0,0.5); width: 100%; max-width: 500px; border: 1px solid #334155; }
|
||||||
|
.admin-box h1 { color: #00bfff; text-align: center; margin-bottom: 1.5rem; }
|
||||||
|
.form-group { margin-bottom: 1rem; }
|
||||||
|
.form-group label { display: block; margin-bottom: 0.5rem; color: #b9bbbe; font-size: 0.9rem; }
|
||||||
|
.form-group input, .form-group select, .form-group textarea { width: 100%; padding: 0.75rem; background: #0f172a; border: 1px solid #334155; border-radius: 4px; color: white; font-family: inherit; }
|
||||||
|
.btn-submit { width: 100%; padding: 0.75rem; background-color: #00bfff; color: white; border: none; border-radius: 4px; font-weight: 600; cursor: pointer; margin-top: 1rem; transition: background 0.2s; }
|
||||||
|
.btn-submit:hover { background-color: #009acd; }
|
||||||
|
.links { text-align: center; margin-top: 1.5rem; display: flex; flex-direction: column; gap: 0.5rem; }
|
||||||
|
.links a { color: #94a3b8; text-decoration: none; font-size: 0.9rem; transition: color 0.2s; }
|
||||||
|
.links a:hover { color: #ffffff; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="admin-box">
|
||||||
|
<?php if (!isset($_SESSION['admin_logged_in']) || $_SESSION['admin_logged_in'] !== true): ?>
|
||||||
|
<h1>Admin Login</h1>
|
||||||
|
<?php if ($error): ?><p style="color: #f87171; text-align: center; margin-bottom: 1rem;"><?= $error ?></p><?php endif; ?>
|
||||||
|
<form method="POST">
|
||||||
|
<input type="hidden" name="action" value="login">
|
||||||
|
<div class="form-group"><label>Username</label><input type="text" name="username" required></div>
|
||||||
|
<div class="form-group"><label>Password</label><input type="password" name="password" required></div>
|
||||||
|
<button type="submit" class="btn-submit">Login</button>
|
||||||
|
</form>
|
||||||
|
<div class="links"><a href="3ds/romfs/index.html">← Back to site</a></div>
|
||||||
|
<?php else: ?>
|
||||||
|
<h1>Add a row</h1>
|
||||||
|
<?= $message ?>
|
||||||
|
<form method="POST">
|
||||||
|
<input type="hidden" name="action" value="add">
|
||||||
|
<div class="form-group"><label>Target planet</label><select name="planete" required>
|
||||||
|
<option value="mercury">Mercury</option><option value="venus">Venus</option><option value="earth">Earth</option>
|
||||||
|
<option value="mars">Mars</option><option value="jupiter">Jupiter</option><option value="saturn">Saturn</option>
|
||||||
|
<option value="uranus">Uranus</option><option value="neptune">Neptune</option>
|
||||||
|
</select></div>
|
||||||
|
<div class="form-group"><label>Mission / Element name</label><input type="text" name="nom" required></div>
|
||||||
|
<div class="form-group"><label>Date (e.g., 24/01/1986)</label><input type="text" name="date"></div>
|
||||||
|
<div class="form-group"><label>URL (Link to an image or site)</label><input type="url" name="url"></div>
|
||||||
|
<div class="form-group"><label>Description / Explanation</label><textarea name="description" rows="4"></textarea></div>
|
||||||
|
<button type="submit" class="btn-submit">Add to data</button>
|
||||||
|
</form>
|
||||||
|
<div class="links"><a href="admin.php?logout=1" style="color: #f87171;">Logout</a><a href="index.html">← Back to site</a></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -1,20 +1,16 @@
|
|||||||
<?php
|
<?php
|
||||||
header('Content-Type: application/json');
|
header('Content-Type: application/json');
|
||||||
|
|
||||||
/* --- CONFIGURATION & SETUP --- */
|
$host = '172.22.0.3';
|
||||||
$config = require_once 'config.php';
|
$dbname = 'OpenPlanetsMaps';
|
||||||
$host = $config['host'];
|
$username = 'root';
|
||||||
$dbname = $config['dbname'];
|
$password = 'admin123';
|
||||||
$username = $config['username'];
|
|
||||||
$password = $config['password'];
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
/* --- DATABASE CONNECTION --- */
|
|
||||||
$options = [PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8", PDO::ATTR_EMULATE_PREPARES => false];
|
$options = [PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8", PDO::ATTR_EMULATE_PREPARES => false];
|
||||||
$pdo = new PDO("mysql:host=$host;port=3306;dbname=$dbname;charset=utf8;protocol=tcp", $username, $password, $options);
|
$pdo = new PDO("mysql:host=$host;port=3306;dbname=$dbname;charset=utf8;protocol=tcp", $username, $password, $options);
|
||||||
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||||
|
|
||||||
/* --- REQUEST HANDLING --- */
|
|
||||||
$planetId = isset($_GET['planet']) ? $_GET['planet'] : '';
|
$planetId = isset($_GET['planet']) ? $_GET['planet'] : '';
|
||||||
|
|
||||||
$allowedTables = [
|
$allowedTables = [
|
||||||
@@ -31,7 +27,6 @@ try {
|
|||||||
];
|
];
|
||||||
|
|
||||||
if ($planetId === 'quiz') {
|
if ($planetId === 'quiz') {
|
||||||
/* --- QUIZ DATA GENERATION --- */
|
|
||||||
$queries = [];
|
$queries = [];
|
||||||
$seed = date('Ymd');
|
$seed = date('Ymd');
|
||||||
foreach ($allowedTables as $key => $table) {
|
foreach ($allowedTables as $key => $table) {
|
||||||
@@ -70,7 +65,6 @@ try {
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- PLANET DATA FETCHING --- */
|
|
||||||
if (!array_key_exists($planetId, $allowedTables)) {
|
if (!array_key_exists($planetId, $allowedTables)) {
|
||||||
echo json_encode([]);
|
echo json_encode([]);
|
||||||
exit;
|
exit;
|
||||||
@@ -83,7 +77,6 @@ try {
|
|||||||
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
echo json_encode($data);
|
echo json_encode($data);
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
/* --- ERROR HANDLING --- */
|
|
||||||
http_response_code(500);
|
http_response_code(500);
|
||||||
echo json_encode(['error' => 'Database error: ' . $e->getMessage()]);
|
echo json_encode(['error' => 'Database error: ' . $e->getMessage()]);
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
$message_status = '';
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
$email = filter_var($_POST['email'], FILTER_SANITIZE_EMAIL);
|
||||||
|
$subject = htmlspecialchars($_POST['objet']);
|
||||||
|
$message = htmlspecialchars($_POST['demande']);
|
||||||
|
|
||||||
|
$has_error = false;
|
||||||
|
$file_path = null;
|
||||||
|
|
||||||
|
if (isset($_FILES['televersement']) && $_FILES['televersement']['error'] == UPLOAD_ERR_OK) {
|
||||||
|
$file_tmp_name = $_FILES['televersement']['tmp_name'];
|
||||||
|
$file_name = $_FILES['televersement']['name'];
|
||||||
|
$file_size = $_FILES['televersement']['size'];
|
||||||
|
|
||||||
|
$file_type = mime_content_type($file_tmp_name);
|
||||||
|
$allowed_types = ['image/jpeg', 'image/png', 'application/pdf'];
|
||||||
|
$max_size = 5 * 1024 * 1024;
|
||||||
|
|
||||||
|
if (!in_array($file_type, $allowed_types)) {
|
||||||
|
$message_status = "<p style='color: #f87171; text-align: center; margin-bottom: 1rem;'>Format non autorisé. Seuls les fichiers JPG, PNG et PDF sont acceptés.</p>";
|
||||||
|
$has_error = true;
|
||||||
|
} elseif ($file_size > $max_size) {
|
||||||
|
$message_status = "<p style='color: #f87171; text-align: center; margin-bottom: 1rem;'>Le fichier est trop volumineux (maximum 5 Mo).</p>";
|
||||||
|
$has_error = true;
|
||||||
|
} else {
|
||||||
|
$upload_dir = 'UPLOADS/';
|
||||||
|
if (!is_dir($upload_dir)) {
|
||||||
|
mkdir($upload_dir, 0777, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$safe_file_name = time() . '_' . preg_replace('/[^a-zA-Z0-9.\-_]/', '', $file_name);
|
||||||
|
$target_path = $upload_dir . $safe_file_name;
|
||||||
|
|
||||||
|
if (move_uploaded_file($file_tmp_name, $target_path)) {
|
||||||
|
$file_path = $target_path;
|
||||||
|
} else {
|
||||||
|
$message_status = "<p style='color: #f87171; text-align: center; margin-bottom: 1rem;'>Erreur lors de la sauvegarde du fichier.</p>";
|
||||||
|
$has_error = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$has_error) {
|
||||||
|
try {
|
||||||
|
$host = '172.22.0.3';
|
||||||
|
$dbname = 'OpenPlanetsMaps';
|
||||||
|
$db_user = 'root';
|
||||||
|
$db_pass = 'admin123';
|
||||||
|
|
||||||
|
$options = [PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8", PDO::ATTR_EMULATE_PREPARES => false];
|
||||||
|
$pdo = new PDO("mysql:host=$host;port=3306;dbname=$dbname;charset=utf8;protocol=tcp", $db_user, $db_pass, $options);
|
||||||
|
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||||
|
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO CONTACT (email, objet, demande, fichier, date_demande) VALUES (?, ?, ?, ?, NOW())");
|
||||||
|
$stmt->execute([$email, $subject, $message, $file_path]);
|
||||||
|
|
||||||
|
$message_status = "<p style='color: #4ade80; text-align: center; margin-bottom: 1rem;'>Votre demande a été enregistrée avec succès dans la base de données !</p>";
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$message_status = "<p style='color: #f87171; text-align: center; margin-bottom: 1rem;'>Erreur de base de données : " . htmlspecialchars($e->getMessage()) . "</p>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Contact - OpenPlanetsMaps</title>
|
||||||
|
<link rel="stylesheet" href="3ds/romfs/style.css">
|
||||||
|
</head>
|
||||||
|
<body class="page-form">
|
||||||
|
<div class="admin-box">
|
||||||
|
<h1>Contact</h1>
|
||||||
|
<?= $message_status ?>
|
||||||
|
<form method="POST" action="contact.php" enctype="multipart/form-data">
|
||||||
|
<div class="form-group"><label>Votre E-mail</label><input type="email" name="email" placeholder="nom@exemple.com" required></div>
|
||||||
|
<div class="form-group"><label>Objet</label><input type="text" name="objet" placeholder="Sujet de votre demande" required></div>
|
||||||
|
<div class="form-group"><label>Demande / Message</label><textarea name="demande" rows="5" placeholder="Détaillez votre message ici..." required></textarea></div>
|
||||||
|
<div class="form-group"><label>Téléversement d'un fichier (Optionnel, Max 5Mo, JPG/PNG/PDF)</label><input type="file" name="televersement" accept=".jpg,.jpeg,.png,.pdf"></div>
|
||||||
|
<button type="submit" class="btn-submit">Envoyer</button>
|
||||||
|
</form>
|
||||||
|
<div class="links"><a href="3ds/romfs/index.html">← Retour au site</a></div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -3,15 +3,15 @@
|
|||||||
<head>
|
<head>
|
||||||
|
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
|
||||||
<title>OpenPlanetsMaps</title>
|
<title>OpenPlanetsMaps</title>
|
||||||
<link rel="icon" href="IMG/IMP_Gen_logo-removebg-preview.png" type="image/png">
|
<link rel="icon" href="IMG/IMP_Gen_logo-removebg-preview.png" type="image/png">
|
||||||
<link rel="stylesheet" href="style.css">
|
<link rel="stylesheet" href="style.css">
|
||||||
</head>
|
</head>
|
||||||
<body class="theme-home">
|
<body class="theme-home">
|
||||||
<div class="bg-animated"></div>
|
<div class="bg-animated"></div>
|
||||||
|
<div id="safe-area-block"></div>
|
||||||
|
|
||||||
<!-- HEADER -->
|
|
||||||
<header>
|
<header>
|
||||||
<div class="menu-icon" onclick="toggleSidebar()">☰</div>
|
<div class="menu-icon" onclick="toggleSidebar()">☰</div>
|
||||||
<h1>Open Planets Maps</h1>
|
<h1>Open Planets Maps</h1>
|
||||||
@@ -21,7 +21,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<!-- SIDEBAR -->
|
|
||||||
<nav id="sidebar" class="sidebar">
|
<nav id="sidebar" class="sidebar">
|
||||||
<ul>
|
<ul>
|
||||||
<li onclick="showLayer('home')">Home</li>
|
<li onclick="showLayer('home')">Home</li>
|
||||||
@@ -42,9 +41,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<!-- MAIN CONTENT -->
|
|
||||||
<main id="content-area">
|
<main id="content-area">
|
||||||
<!-- HOME SECTION -->
|
|
||||||
<section id="layer-home" class="layer active">
|
<section id="layer-home" class="layer active">
|
||||||
<div class="main-img">
|
<div class="main-img">
|
||||||
<iframe title="Solar System animation" frameborder="0" allow="autoplay; fullscreen; xr-spatial-tracking" src="https://sketchfab.com/models/b7c69a6b655b47c99f871d5ec5aee854/embed?autostart=1&ui_infos=0&ui_watermark=0&ui_controls=0"></iframe>
|
<iframe title="Solar System animation" frameborder="0" allow="autoplay; fullscreen; xr-spatial-tracking" src="https://sketchfab.com/models/b7c69a6b655b47c99f871d5ec5aee854/embed?autostart=1&ui_infos=0&ui_watermark=0&ui_controls=0"></iframe>
|
||||||
@@ -65,7 +62,6 @@
|
|||||||
<div class="desc-box">Ready for launch? Open the side menu (☰) and select a destination to begin your journey.</div>
|
<div class="desc-box">Ready for launch? Open the side menu (☰) and select a destination to begin your journey.</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- MERCURY SECTION -->
|
|
||||||
<section id="layer-mercury" class="layer">
|
<section id="layer-mercury" class="layer">
|
||||||
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
|
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
|
||||||
<div class="main-img">
|
<div class="main-img">
|
||||||
@@ -91,7 +87,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- VENUS SECTION -->
|
|
||||||
<section id="layer-venus" class="layer">
|
<section id="layer-venus" class="layer">
|
||||||
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
|
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
|
||||||
<div class="main-img">
|
<div class="main-img">
|
||||||
@@ -117,7 +112,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- EARTH SECTION -->
|
|
||||||
<section id="layer-earth" class="layer">
|
<section id="layer-earth" class="layer">
|
||||||
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
|
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
|
||||||
<div class="main-img">
|
<div class="main-img">
|
||||||
@@ -143,7 +137,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- MARS SECTION -->
|
|
||||||
<section id="layer-mars" class="layer">
|
<section id="layer-mars" class="layer">
|
||||||
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
|
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
|
||||||
<div class="main-img">
|
<div class="main-img">
|
||||||
@@ -169,7 +162,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- JUPITER SECTION -->
|
|
||||||
<section id="layer-jupiter" class="layer">
|
<section id="layer-jupiter" class="layer">
|
||||||
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
|
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
|
||||||
<div class="main-img">
|
<div class="main-img">
|
||||||
@@ -195,7 +187,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- SATURN SECTION -->
|
|
||||||
<section id="layer-saturn" class="layer">
|
<section id="layer-saturn" class="layer">
|
||||||
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
|
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
|
||||||
<div class="main-img">
|
<div class="main-img">
|
||||||
@@ -221,7 +212,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- URANUS SECTION -->
|
|
||||||
<section id="layer-uranus" class="layer">
|
<section id="layer-uranus" class="layer">
|
||||||
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
|
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
|
||||||
<div class="main-img">
|
<div class="main-img">
|
||||||
@@ -247,7 +237,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- NEPTUNE SECTION -->
|
|
||||||
<section id="layer-neptune" class="layer">
|
<section id="layer-neptune" class="layer">
|
||||||
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
|
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
|
||||||
<div class="main-img">
|
<div class="main-img">
|
||||||
@@ -273,7 +262,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- SUN SECTION -->
|
|
||||||
<section id="layer-sun" class="layer">
|
<section id="layer-sun" class="layer">
|
||||||
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
|
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
|
||||||
<div class="main-img">
|
<div class="main-img">
|
||||||
@@ -302,7 +290,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- MOON SECTION -->
|
|
||||||
<section id="layer-moon" class="layer">
|
<section id="layer-moon" class="layer">
|
||||||
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
|
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
|
||||||
<div class="main-img">
|
<div class="main-img">
|
||||||
@@ -331,7 +318,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- QUIZ SECTION -->
|
|
||||||
<section id="layer-Quiz" class="layer">
|
<section id="layer-Quiz" class="layer">
|
||||||
<div class="desc-box">Test your knowledge of the solar system! Answer the questions below to see if you are a true space expert.</div>
|
<div class="desc-box">Test your knowledge of the solar system! Answer the questions below to see if you are a true space expert.</div>
|
||||||
|
|
||||||
@@ -354,12 +340,10 @@
|
|||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<!-- FOOTER -->
|
|
||||||
<footer class="site-footer" onclick="openCredits()" title="Credits & About">
|
<footer class="site-footer" onclick="openCredits()" title="Credits & About">
|
||||||
© 2026 OpenPlanetsMaps. Royalty-free. <span class="footer-credits-hint">— Credits ↗</span>
|
© 2026 OpenPlanetsMaps. Royalty-free. <span class="footer-credits-hint">— Credits ↗</span>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<!-- CREDITS MODAL -->
|
|
||||||
<div id="credits-overlay"></div>
|
<div id="credits-overlay"></div>
|
||||||
<div id="credits-panel">
|
<div id="credits-panel">
|
||||||
<button class="credits-close" onclick="closeCredits()">✕</button>
|
<button class="credits-close" onclick="closeCredits()">✕</button>
|
||||||
@@ -407,7 +391,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- SCRIPTS -->
|
|
||||||
<script src="main.js"></script>
|
<script src="main.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
/* --- UI & NAVIGATION --- */
|
|
||||||
function toggleSidebar() {
|
function toggleSidebar() {
|
||||||
document.getElementById('sidebar').classList.toggle('open');
|
document.getElementById('sidebar').classList.toggle('open');
|
||||||
}
|
}
|
||||||
@@ -25,7 +24,6 @@ function showLayer(layerId) {
|
|||||||
const planetData = {};
|
const planetData = {};
|
||||||
const planetCols = {};
|
const planetCols = {};
|
||||||
|
|
||||||
/* --- SEARCH & FILTERING --- */
|
|
||||||
function wireSearch(planetId) {
|
function wireSearch(planetId) {
|
||||||
const layer = document.getElementById('layer-' + planetId);
|
const layer = document.getElementById('layer-' + planetId);
|
||||||
if (!layer) return;
|
if (!layer) return;
|
||||||
@@ -100,7 +98,6 @@ function filterTable(planetId, query) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- API & DATA FETCHING --- */
|
|
||||||
async function fetchData(planetId) {
|
async function fetchData(planetId) {
|
||||||
const tbody = document.getElementById('tbody-' + planetId);
|
const tbody = document.getElementById('tbody-' + planetId);
|
||||||
if (!tbody) return;
|
if (!tbody) return;
|
||||||
@@ -215,7 +212,6 @@ let quizQuestions = [];
|
|||||||
let currentQuizIndex = 0;
|
let currentQuizIndex = 0;
|
||||||
let quizScore = 0;
|
let quizScore = 0;
|
||||||
|
|
||||||
/* --- QUIZ SYSTEM --- */
|
|
||||||
async function initQuiz() {
|
async function initQuiz() {
|
||||||
currentQuizIndex = 0;
|
currentQuizIndex = 0;
|
||||||
quizScore = 0;
|
quizScore = 0;
|
||||||
@@ -343,7 +339,6 @@ function checkAnswer(selected, correct, btn) {
|
|||||||
}, 1800);
|
}, 1800);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- CREDITS MODAL --- */
|
|
||||||
function openCredits() {
|
function openCredits() {
|
||||||
document.getElementById('credits-panel').classList.add('open');
|
document.getElementById('credits-panel').classList.add('open');
|
||||||
document.getElementById('credits-overlay').classList.add('open');
|
document.getElementById('credits-overlay').classList.add('open');
|
||||||
@@ -356,7 +351,6 @@ function closeCredits() {
|
|||||||
document.body.style.overflow = '';
|
document.body.style.overflow = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- INITIALIZATION & MOBILE FALLBACK --- */
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
const overlay = document.getElementById('credits-overlay');
|
const overlay = document.getElementById('credits-overlay');
|
||||||
if (overlay) overlay.addEventListener('click', closeCredits);
|
if (overlay) overlay.addEventListener('click', closeCredits);
|
||||||
@@ -366,15 +360,33 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const isMobile = window.innerWidth <= 768 || /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
const isMobile = window.innerWidth <= 768 || /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
||||||
|
const isElectron = navigator.userAgent.toLowerCase().includes('electron');
|
||||||
|
const isCapacitor = window.Capacitor !== undefined; // Détecte l'application mobile native
|
||||||
|
|
||||||
if (isMobile) {
|
if (isCapacitor) {
|
||||||
|
document.body.classList.add('is-mobile-app');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isMobile || isElectron || isCapacitor) {
|
||||||
const iframes = document.querySelectorAll('iframe');
|
const iframes = document.querySelectorAll('iframe');
|
||||||
iframes.forEach(iframe => {
|
iframes.forEach(iframe => {
|
||||||
const fallback = document.createElement('div');
|
const fallback = document.createElement('div');
|
||||||
fallback.textContent = "functionality not available on mobile devices";
|
if (isElectron) {
|
||||||
|
fallback.textContent = "3D models are not compatible on the desktop app";
|
||||||
|
} else if (isCapacitor) {
|
||||||
|
fallback.textContent = "3D models are not compatible on the mobile app";
|
||||||
|
} else {
|
||||||
|
fallback.textContent = "functionality not available on mobile devices";
|
||||||
|
}
|
||||||
fallback.style.display = "flex";
|
fallback.style.display = "flex";
|
||||||
fallback.style.alignItems = "center";
|
fallback.style.alignItems = "center";
|
||||||
fallback.style.justifyContent = "center";
|
fallback.style.justifyContent = "center";
|
||||||
|
|
||||||
|
// Correction du responsive : on empêche la boîte de déborder de l'écran
|
||||||
|
fallback.style.width = "100%";
|
||||||
|
fallback.style.maxWidth = "100%";
|
||||||
|
fallback.style.boxSizing = "border-box";
|
||||||
|
|
||||||
fallback.style.minHeight = "200px";
|
fallback.style.minHeight = "200px";
|
||||||
fallback.style.backgroundColor = "#1e293b";
|
fallback.style.backgroundColor = "#1e293b";
|
||||||
fallback.style.color = "#f87171";
|
fallback.style.color = "#f87171";
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
/* --- FONTS & VARIABLES --- */
|
|
||||||
@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&family=Orbitron:wght@400;600;700;900&family=Space+Mono:wght@400;700&display=swap');
|
@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&family=Orbitron:wght@400;600;700;900&family=Space+Mono:wght@400;700&display=swap');
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
@@ -22,7 +21,6 @@ body.theme-sun { --theme-color:#ffcc44; --theme-glow:rgba(255,180,40,.55);
|
|||||||
body.theme-moon { --theme-color:#c8cfe8; --theme-glow:rgba(200,207,232,.35); --theme-subtle:rgba(200,207,232,.06); --bg-deep:#060608; --bg-mid:#0e0f14; --border:rgba(200,207,232,.12); --text-primary:#dde2f0; --text-secondary:#7e8ba8; --text-muted:#3c4258; }
|
body.theme-moon { --theme-color:#c8cfe8; --theme-glow:rgba(200,207,232,.35); --theme-subtle:rgba(200,207,232,.06); --bg-deep:#060608; --bg-mid:#0e0f14; --border:rgba(200,207,232,.12); --text-primary:#dde2f0; --text-secondary:#7e8ba8; --text-muted:#3c4258; }
|
||||||
body.theme-Quiz { --theme-color:#7eb8f7; --theme-glow:rgba(126,184,247,.35); --theme-subtle:rgba(126,184,247,.07); --bg-deep:#020510; --bg-mid:#060e24; --border:rgba(126,184,247,.13); --text-primary:#ddeeff; --text-secondary:#6a90b8; --text-muted:#2e4a6a; }
|
body.theme-Quiz { --theme-color:#7eb8f7; --theme-glow:rgba(126,184,247,.35); --theme-subtle:rgba(126,184,247,.07); --bg-deep:#020510; --bg-mid:#060e24; --border:rgba(126,184,247,.13); --text-primary:#ddeeff; --text-secondary:#6a90b8; --text-muted:#2e4a6a; }
|
||||||
|
|
||||||
/* --- GLOBAL STYLES --- */
|
|
||||||
*,*::before,*::after { margin:0; padding:0; box-sizing:border-box; }
|
*,*::before,*::after { margin:0; padding:0; box-sizing:border-box; }
|
||||||
|
|
||||||
html, body { max-width:100vw; overflow-x:hidden; }
|
html, body { max-width:100vw; overflow-x:hidden; }
|
||||||
@@ -33,7 +31,6 @@ body {
|
|||||||
transition:background-color .8s ease, color .3s ease;
|
transition:background-color .8s ease, color .3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- ANIMATED BACKGROUND --- */
|
|
||||||
.bg-animated {
|
.bg-animated {
|
||||||
position:fixed; inset:0; z-index:-2;
|
position:fixed; inset:0; z-index:-2;
|
||||||
background:radial-gradient(ellipse at 20% 10%, var(--bg-mid) 0%, var(--bg-deep) 60%);
|
background:radial-gradient(ellipse at 20% 10%, var(--bg-mid) 0%, var(--bg-deep) 60%);
|
||||||
@@ -96,13 +93,20 @@ body.theme-moon::before {
|
|||||||
100% { opacity:.65; }
|
100% { opacity:.65; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- HEADER --- */
|
#safe-area-block {
|
||||||
|
position: sticky; top: 0; z-index: 101;
|
||||||
|
width: 100%;
|
||||||
|
height: env(safe-area-inset-top);
|
||||||
|
background: var(--bg-deep);
|
||||||
|
}
|
||||||
|
|
||||||
header {
|
header {
|
||||||
display:flex; justify-content:space-between; align-items:center;
|
display:flex; justify-content:space-between; align-items:center;
|
||||||
padding:0 2rem; height:64px;
|
padding:0 2rem;
|
||||||
|
height:64px;
|
||||||
background:rgba(2,4,8,.75); backdrop-filter:blur(20px);
|
background:rgba(2,4,8,.75); backdrop-filter:blur(20px);
|
||||||
border-bottom:1px solid var(--border);
|
border-bottom:1px solid var(--border);
|
||||||
position:sticky; top:0; z-index:100;
|
position:sticky; top:env(safe-area-inset-top); z-index:100;
|
||||||
transition:border-color .6s ease;
|
transition:border-color .6s ease;
|
||||||
}
|
}
|
||||||
header::after {
|
header::after {
|
||||||
@@ -135,7 +139,6 @@ header h1:hover { animation:glitch .4s steps(1) forwards; }
|
|||||||
box-shadow:0 0 12px var(--theme-glow);
|
box-shadow:0 0 12px var(--theme-glow);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- SIDEBAR --- */
|
|
||||||
.sidebar {
|
.sidebar {
|
||||||
position:fixed; top:0; left:-300px; width:280px; height:100vh;
|
position:fixed; top:0; left:-300px; width:280px; height:100vh;
|
||||||
background:rgba(2,6,14,.96); backdrop-filter:blur(24px);
|
background:rgba(2,6,14,.96); backdrop-filter:blur(24px);
|
||||||
@@ -175,7 +178,6 @@ header h1:hover { animation:glitch .4s steps(1) forwards; }
|
|||||||
.sidebar li.menu-category::after { display:none; }
|
.sidebar li.menu-category::after { display:none; }
|
||||||
.sidebar li.menu-category:hover { background:none; padding-left:1.75rem; text-shadow:none; color:var(--text-muted); }
|
.sidebar li.menu-category:hover { background:none; padding-left:1.75rem; text-shadow:none; color:var(--text-muted); }
|
||||||
|
|
||||||
/* --- LAYOUT & MAIN CONTENT --- */
|
|
||||||
#content-area {
|
#content-area {
|
||||||
flex:1; padding:2.5rem; display:flex;
|
flex:1; padding:2.5rem; display:flex;
|
||||||
max-width:1400px; margin:0 auto; width:100%;
|
max-width:1400px; margin:0 auto; width:100%;
|
||||||
@@ -186,7 +188,6 @@ header h1:hover { animation:glitch .4s steps(1) forwards; }
|
|||||||
}
|
}
|
||||||
.layer.active { display:flex; }
|
.layer.active { display:flex; }
|
||||||
|
|
||||||
/* --- COMPONENTS (Images, Boxes, Tickers) --- */
|
|
||||||
.main-img {
|
.main-img {
|
||||||
margin-bottom:2.5rem; position:relative;
|
margin-bottom:2.5rem; position:relative;
|
||||||
border-radius:12px; overflow:hidden; border:1px solid var(--border);
|
border-radius:12px; overflow:hidden; border:1px solid var(--border);
|
||||||
@@ -266,7 +267,6 @@ header h1:hover { animation:glitch .4s steps(1) forwards; }
|
|||||||
}
|
}
|
||||||
.ticker:hover { animation-play-state:paused; }
|
.ticker:hover { animation-play-state:paused; }
|
||||||
|
|
||||||
/* --- SEARCH BAR --- */
|
|
||||||
.search-bar { margin-bottom:2rem; position:relative; display:flex; justify-content:center; }
|
.search-bar { margin-bottom:2rem; position:relative; display:flex; justify-content:center; }
|
||||||
.search-bar::before {
|
.search-bar::before {
|
||||||
content:'⌕'; position:absolute; left:calc(50% - 210px); top:50%;
|
content:'⌕'; position:absolute; left:calc(50% - 210px); top:50%;
|
||||||
@@ -287,7 +287,6 @@ header h1:hover { animation:glitch .4s steps(1) forwards; }
|
|||||||
box-shadow:0 0 20px var(--theme-glow);
|
box-shadow:0 0 20px var(--theme-glow);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- DATA TABLES --- */
|
|
||||||
.table-container { margin-bottom:3rem; }
|
.table-container { margin-bottom:3rem; }
|
||||||
.data-table { width:100%; max-width:1300px; margin:0 auto; border-collapse:collapse; font-size:.88rem; }
|
.data-table { width:100%; max-width:1300px; margin:0 auto; border-collapse:collapse; font-size:.88rem; }
|
||||||
.data-table thead tr { background:rgba(255,255,255,.03); }
|
.data-table thead tr { background:rgba(255,255,255,.03); }
|
||||||
@@ -345,7 +344,6 @@ header h1:hover { animation:glitch .4s steps(1) forwards; }
|
|||||||
.show-more-btn:hover::before { transform:scaleX(1); }
|
.show-more-btn:hover::before { transform:scaleX(1); }
|
||||||
.show-more-btn:hover { box-shadow:0 0 24px var(--theme-glow); transform:translateY(1px); }
|
.show-more-btn:hover { box-shadow:0 0 24px var(--theme-glow); transform:translateY(1px); }
|
||||||
|
|
||||||
/* --- FOOTER --- */
|
|
||||||
.site-footer {
|
.site-footer {
|
||||||
text-align:center; padding:1.25rem 2rem;
|
text-align:center; padding:1.25rem 2rem;
|
||||||
background:rgba(2,4,8,.7); backdrop-filter:blur(10px);
|
background:rgba(2,4,8,.7); backdrop-filter:blur(10px);
|
||||||
@@ -360,7 +358,6 @@ header h1:hover { animation:glitch .4s steps(1) forwards; }
|
|||||||
.footer-credits-hint { opacity:.5; font-style:italic; transition:opacity .2s; }
|
.footer-credits-hint { opacity:.5; font-style:italic; transition:opacity .2s; }
|
||||||
.site-footer:hover .footer-credits-hint { opacity:1; color:var(--theme-color); }
|
.site-footer:hover .footer-credits-hint { opacity:1; color:var(--theme-color); }
|
||||||
|
|
||||||
/* --- QUIZ SYSTEM --- */
|
|
||||||
.daily-challenge-box {
|
.daily-challenge-box {
|
||||||
margin:0 auto 2rem; max-width:680px; padding:1rem 1.5rem;
|
margin:0 auto 2rem; max-width:680px; padding:1rem 1.5rem;
|
||||||
background:var(--theme-subtle); border:1px solid var(--border);
|
background:var(--theme-subtle); border:1px solid var(--border);
|
||||||
@@ -458,7 +455,6 @@ header h1:hover { animation:glitch .4s steps(1) forwards; }
|
|||||||
white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
|
white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- CREDITS MODAL --- */
|
|
||||||
#credits-overlay {
|
#credits-overlay {
|
||||||
position:fixed; inset:0; z-index:2000;
|
position:fixed; inset:0; z-index:2000;
|
||||||
background:rgba(0,0,0,.7); backdrop-filter:blur(6px);
|
background:rgba(0,0,0,.7); backdrop-filter:blur(6px);
|
||||||
@@ -522,13 +518,11 @@ header h1:hover { animation:glitch .4s steps(1) forwards; }
|
|||||||
|
|
||||||
.credits-footer { padding:1rem 2rem; border-top:1px solid var(--border); font-family:'Space Mono',monospace; font-size:.62rem; letter-spacing:.15em; color:var(--text-muted); flex-shrink:0; }
|
.credits-footer { padding:1rem 2rem; border-top:1px solid var(--border); font-family:'Space Mono',monospace; font-size:.62rem; letter-spacing:.15em; color:var(--text-muted); flex-shrink:0; }
|
||||||
|
|
||||||
/* --- SCROLLBAR & SELECTION --- */
|
|
||||||
::-webkit-scrollbar { width:6px; }
|
::-webkit-scrollbar { width:6px; }
|
||||||
::-webkit-scrollbar-track { background:var(--bg-deep); }
|
::-webkit-scrollbar-track { background:var(--bg-deep); }
|
||||||
::-webkit-scrollbar-thumb { background:var(--theme-color); border-radius:3px; }
|
::-webkit-scrollbar-thumb { background:var(--theme-color); border-radius:3px; }
|
||||||
::selection { background:var(--theme-glow); color:#fff; }
|
::selection { background:var(--theme-glow); color:#fff; }
|
||||||
|
|
||||||
/* --- KEYFRAMES --- */
|
|
||||||
@keyframes layerReveal {
|
@keyframes layerReveal {
|
||||||
from { opacity:0; transform:translateY(16px); filter:blur(4px); }
|
from { opacity:0; transform:translateY(16px); filter:blur(4px); }
|
||||||
to { opacity:1; transform:translateY(0); filter:blur(0); }
|
to { opacity:1; transform:translateY(0); filter:blur(0); }
|
||||||
@@ -558,8 +552,6 @@ header h1:hover { animation:glitch .4s steps(1) forwards; }
|
|||||||
50% { transform:translateX(5px); }
|
50% { transform:translateX(5px); }
|
||||||
75% { transform:translateX(-3px); }
|
75% { transform:translateX(-3px); }
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- MEDIA QUERIES --- */
|
|
||||||
@media (max-width:768px) {
|
@media (max-width:768px) {
|
||||||
#layer-Quiz .desc-box, #layer-Quiz .daily-challenge-box { display:none; }
|
#layer-Quiz .desc-box, #layer-Quiz .daily-challenge-box { display:none; }
|
||||||
}
|
}
|
||||||
@@ -578,7 +570,6 @@ header h1:hover { animation:glitch .4s steps(1) forwards; }
|
|||||||
#quiz-img-preview img, #quiz-img-preview video { max-height:160px; width:auto; max-width:100%; margin:0 auto; }
|
#quiz-img-preview img, #quiz-img-preview video { max-height:160px; width:auto; max-width:100%; margin:0 auto; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- ADMIN & FORM PAGES --- */
|
|
||||||
body.page-form { background-color: #0f172a; color: #e0e0e0; display: flex; flex-direction: row; justify-content: center; align-items: center; padding: 2rem; min-height: 100vh; overflow-x: auto; }
|
body.page-form { background-color: #0f172a; color: #e0e0e0; display: flex; flex-direction: row; justify-content: center; align-items: center; padding: 2rem; min-height: 100vh; overflow-x: auto; }
|
||||||
.admin-box { background-color: #1e293b; padding: 2rem; border-radius: 8px; box-shadow: 0 4px 15px rgba(0,0,0,0.5); width: 100%; max-width: 500px; border: 1px solid #334155; }
|
.admin-box { background-color: #1e293b; padding: 2rem; border-radius: 8px; box-shadow: 0 4px 15px rgba(0,0,0,0.5); width: 100%; max-width: 500px; border: 1px solid #334155; }
|
||||||
.admin-box h1 { color: #00bfff; text-align: center; margin-bottom: 1.5rem; }
|
.admin-box h1 { color: #00bfff; text-align: center; margin-bottom: 1.5rem; }
|
||||||
@@ -593,3 +584,10 @@ body.page-form { background-color: #0f172a; color: #e0e0e0; display: flex; flex-
|
|||||||
input[type="file"] { cursor: pointer; padding: 0.6rem; }
|
input[type="file"] { cursor: pointer; padding: 0.6rem; }
|
||||||
input[type="file"]::file-selector-button { background: #334155; color: white; border: none; padding: 0.5rem 1rem; border-radius: 4px; cursor: pointer; margin-right: 1rem; transition: background 0.2s; }
|
input[type="file"]::file-selector-button { background: #334155; color: white; border: none; padding: 0.5rem 1rem; border-radius: 4px; cursor: pointer; margin-right: 1rem; transition: background 0.2s; }
|
||||||
input[type="file"]::file-selector-button:hover { background: #475569; }
|
input[type="file"]::file-selector-button:hover { background: #475569; }
|
||||||
|
|
||||||
|
/* Correction absolue pour App Mobile Native (Capacitor) */
|
||||||
|
body.is-mobile-app #safe-area-block { height: max(env(safe-area-inset-top), 45px); }
|
||||||
|
body.is-mobile-app header { top: max(env(safe-area-inset-top), 45px); }
|
||||||
|
body.is-mobile-app .sidebar { padding-top: calc(5rem + max(env(safe-area-inset-top), 45px)); }
|
||||||
|
body.is-mobile-app .sidebar::before { top: calc(1.5rem + max(env(safe-area-inset-top), 45px)); }
|
||||||
|
body.is-mobile-app .credits-close { top: calc(1rem + max(env(safe-area-inset-top), 45px)); }
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
// 3ds/source/main.cpp
|
||||||
|
#include <3ds.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <citro2d.h>
|
||||||
|
|
||||||
|
// Définition des couleurs pour plus de clarté (Format: RGBA)
|
||||||
|
#define CLR_BG C2D_Color32(0x06, 0x0d, 0x18, 0xFF) // #060d18
|
||||||
|
#define CLR_TEXT C2D_Color32(0xe8, 0xf0, 0xff, 0xFF) // #e8f0ff
|
||||||
|
#define CLR_PRIMARY C2D_Color32(0x4f, 0x8e, 0xff, 0xFF) // #4f8eff
|
||||||
|
|
||||||
|
// Fonction pour lire un fichier depuis le romfs
|
||||||
|
char* readFile(const char* path) {
|
||||||
|
FILE* file = fopen(path, "r");
|
||||||
|
if (!file) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(file, 0, SEEK_END);
|
||||||
|
long size = ftell(file);
|
||||||
|
fseek(file, 0, SEEK_SET);
|
||||||
|
|
||||||
|
char* buffer = (char*)malloc(size + 1);
|
||||||
|
if (!buffer) {
|
||||||
|
fclose(file);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fread(buffer, 1, size, file);
|
||||||
|
buffer[size] = '\0';
|
||||||
|
fclose(file);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
// --- Initialisation ---
|
||||||
|
romfsInit();
|
||||||
|
gfxInitDefault();
|
||||||
|
C3D_Init(C3D_DEFAULT_CMDBUF_SIZE);
|
||||||
|
C2D_Init(C2D_DEFAULT_MAX_OBJECTS);
|
||||||
|
C2D_Prepare();
|
||||||
|
|
||||||
|
// Crée un "canevas" pour l'écran supérieur
|
||||||
|
C3D_RenderTarget* top = C2D_CreateScreenTarget(GFX_TOP, GFX_LEFT);
|
||||||
|
|
||||||
|
// Prépare un buffer pour le texte
|
||||||
|
C2D_TextBuf textBuf = C2D_TextBufNew(4096);
|
||||||
|
C2D_Text text;
|
||||||
|
|
||||||
|
// Lecture du fichier main.js
|
||||||
|
char* js_content = readFile("romfs:/main.js");
|
||||||
|
|
||||||
|
// --- Boucle principale de l'application ---
|
||||||
|
while (aptMainLoop()) {
|
||||||
|
hidScanInput();
|
||||||
|
u32 kDown = hidKeysDown();
|
||||||
|
|
||||||
|
if (kDown & KEY_START) {
|
||||||
|
free(js_content); // Libère la mémoire avant de quitter
|
||||||
|
break; // Quitte l'application
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Phase de dessin ---
|
||||||
|
C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
|
||||||
|
|
||||||
|
// Dessin sur l'écran du haut
|
||||||
|
C2D_TargetClear(top, CLR_BG);
|
||||||
|
C2D_SceneBegin(top);
|
||||||
|
|
||||||
|
// Dessine du texte
|
||||||
|
C2D_TextBufClear(textBuf);
|
||||||
|
C2D_TextParse(&text, textBuf, "Lecture de romfs:/main.js reussie !");
|
||||||
|
C2D_TextOptimize(&text);
|
||||||
|
C2D_DrawText(&text, C2D_WithColor, 20.0f, 20.0f, 0.5f, 0.5f, 0.5f, CLR_PRIMARY);
|
||||||
|
|
||||||
|
if (js_content) {
|
||||||
|
C2D_TextParse(&text, textBuf, js_content);
|
||||||
|
C2D_TextOptimize(&text);
|
||||||
|
C2D_DrawText(&text, C2D_WithColor, 20.0f, 50.0f, 0.5f, 0.4f, 0.4f, CLR_TEXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
C3D_FrameEnd(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Libération des ressources ---
|
||||||
|
C2D_TextBufDelete(textBuf);
|
||||||
|
C2D_Fini();
|
||||||
|
C3D_Fini();
|
||||||
|
romfsExit();
|
||||||
|
gfxExit();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@ OpenPlanetsMaps is a project that gathers and structures astronomical data (imag
|
|||||||
## Context and Hosting
|
## Context and Hosting
|
||||||
This project was carried out as part of an exam presided over by **F. LEFEVRE**.
|
This project was carried out as part of an exam presided over by **F. LEFEVRE**.
|
||||||
It is hosted and accessible online at the following address: [opm.nhkyllian.fr](https://opm.nhkyllian.fr)
|
It is hosted and accessible online at the following address: [opm.nhkyllian.fr](https://opm.nhkyllian.fr)
|
||||||
|
Secondary URL: [openplanetsmaps.alwaysdata.net](http://openplanetsmaps.alwaysdata.net)
|
||||||
|
|
||||||
## Database Structure
|
## Database Structure
|
||||||
|
|
||||||
@@ -25,21 +25,24 @@ The core of the project relies on a MySQL/MariaDB database named `OpenPlanetsMap
|
|||||||
|
|
||||||
The system also includes a `CONTACT` table intended to store messages and requests from a potential contact form (email, subject, request, attached file).
|
The system also includes a `CONTACT` table intended to store messages and requests from a potential contact form (email, subject, request, attached file).
|
||||||
|
|
||||||
|
## Installation and Configuration
|
||||||
|
|
||||||
|
To set up the database locally (for example, with XAMPP, WAMP, or directly via MariaDB/MySQL):
|
||||||
|
|
||||||
|
1. Create a new database named `OpenPlanetsMaps` (recommended encoding: `utf8mb4_general_ci`).
|
||||||
|
2. Import the structure file to initialize the tables:
|
||||||
|
```bash
|
||||||
|
mysql -u user -p OpenPlanetsMaps < SRC/DATA/Structure.sql
|
||||||
|
```
|
||||||
|
3. Then import the data file to populate the database (currently contains Earth data):
|
||||||
|
```bash
|
||||||
|
mysql -u user -p OpenPlanetsMaps < SRC/DATA/DATA.sql
|
||||||
|
```
|
||||||
|
|
||||||
## Technologies
|
## Technologies
|
||||||
- Database: MySQL / MariaDB (generated via phpMyAdmin)
|
- Database: MySQL / MariaDB (generated via phpMyAdmin)
|
||||||
- Frontend: HTML, CSS, JavaScript
|
|
||||||
- Packaging: Electron Packager
|
|
||||||
- CI/CD: GitHub Actions
|
|
||||||
- Data format: JSON
|
|
||||||
|
|
||||||
## Releases (Mobile Apps)
|
## Releases (Mobile Apps)
|
||||||
Native mobile applications for this project are now available. You can download them directly from the **Releases** tab of this GitHub repository:
|
Native mobile applications for this project are now available. You can download them directly from the **Releases** tab of this GitHub repository:
|
||||||
- **Android**: Download the `.apk` file to install the app on your Android device.
|
- 📱 **Android**: Download the `.apk` file to install the app on your Android device.
|
||||||
- **iOS**: Download the `.ipa` file to install the app on your iOS device.
|
- 🍏 **iOS**: Download the `.ipa` file to install the app on your iOS device.
|
||||||
|
|
||||||
## Data Source & License
|
|
||||||
The astronomical data (images, videos, and descriptions) provided in this project is sourced from the public NASA API.
|
|
||||||
As per NASA's media guidelines, these materials are in the **public domain** and are completely free to use without any royalties.
|
|
||||||
|
|
||||||
The code and structure of this project are open-source and entirely free to use.
|
|
||||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
@@ -1,12 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
/* --- SESSION & AUTHENTICATION --- */
|
|
||||||
session_start();
|
session_start();
|
||||||
|
|
||||||
$config = require_once './config.php';
|
|
||||||
|
|
||||||
$error = '';
|
$error = '';
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'login') {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'login') {
|
||||||
if ($_POST['username'] === $config['admin_user'] && $_POST['password'] === $config['admin_pass']) {
|
if ($_POST['username'] === 'admin' && $_POST['password'] === 'admin') {
|
||||||
$_SESSION['admin_logged_in'] = true;
|
$_SESSION['admin_logged_in'] = true;
|
||||||
header('Location: admin.php');
|
header('Location: admin.php');
|
||||||
exit;
|
exit;
|
||||||
@@ -21,14 +18,12 @@ if (isset($_GET['logout'])) {
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- DATABASE CONFIGURATION --- */
|
$host = '172.22.0.3';
|
||||||
$host = $config['host'];
|
$dbname = 'OpenPlanetsMaps';
|
||||||
$dbname = $config['dbname'];
|
$db_user = 'root';
|
||||||
$db_user = $config['username'];
|
$db_pass = 'admin123';
|
||||||
$db_pass = $config['password'];
|
|
||||||
|
|
||||||
$message = '';
|
$message = '';
|
||||||
/* --- FORM PROCESSING & DB INSERTION --- */
|
|
||||||
if (isset($_SESSION['admin_logged_in']) && $_SESSION['admin_logged_in'] === true && $_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'add') {
|
if (isset($_SESSION['admin_logged_in']) && $_SESSION['admin_logged_in'] === true && $_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'add') {
|
||||||
try {
|
try {
|
||||||
$options = [PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8", PDO::ATTR_EMULATE_PREPARES => false];
|
$options = [PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8", PDO::ATTR_EMULATE_PREPARES => false];
|
||||||
@@ -62,7 +57,6 @@ if (isset($_SESSION['admin_logged_in']) && $_SESSION['admin_logged_in'] === true
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<!-- --- HEAD & STYLES --- -->
|
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>Admin Panel - OpenPlanetsMaps</title>
|
<title>Admin Panel - OpenPlanetsMaps</title>
|
||||||
<link rel="stylesheet" href="style.css">
|
<link rel="stylesheet" href="style.css">
|
||||||
@@ -81,10 +75,8 @@ if (isset($_SESSION['admin_logged_in']) && $_SESSION['admin_logged_in'] === true
|
|||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<!-- --- BODY & ADMIN PANEL --- -->
|
|
||||||
<div class="admin-box">
|
<div class="admin-box">
|
||||||
<?php if (!isset($_SESSION['admin_logged_in']) || $_SESSION['admin_logged_in'] !== true): ?>
|
<?php if (!isset($_SESSION['admin_logged_in']) || $_SESSION['admin_logged_in'] !== true): ?>
|
||||||
<!-- --- LOGIN FORM --- -->
|
|
||||||
<h1>Admin Login</h1>
|
<h1>Admin Login</h1>
|
||||||
<?php if ($error): ?><p style="color: #f87171; text-align: center; margin-bottom: 1rem;"><?= $error ?></p><?php endif; ?>
|
<?php if ($error): ?><p style="color: #f87171; text-align: center; margin-bottom: 1rem;"><?= $error ?></p><?php endif; ?>
|
||||||
<form method="POST">
|
<form method="POST">
|
||||||
@@ -95,7 +87,6 @@ if (isset($_SESSION['admin_logged_in']) && $_SESSION['admin_logged_in'] === true
|
|||||||
</form>
|
</form>
|
||||||
<div class="links"><a href="index.html">← Back to site</a></div>
|
<div class="links"><a href="index.html">← Back to site</a></div>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<!-- --- ADD DATA FORM --- -->
|
|
||||||
<h1>Add a row</h1>
|
<h1>Add a row</h1>
|
||||||
<?= $message ?>
|
<?= $message ?>
|
||||||
<form method="POST">
|
<form method="POST">
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
<?php
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
|
||||||
|
$host = '172.22.0.3';
|
||||||
|
$dbname = 'OpenPlanetsMaps';
|
||||||
|
$username = 'root';
|
||||||
|
$password = 'admin123';
|
||||||
|
|
||||||
|
try {
|
||||||
|
$options = [PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8", PDO::ATTR_EMULATE_PREPARES => false];
|
||||||
|
$pdo = new PDO("mysql:host=$host;port=3306;dbname=$dbname;charset=utf8;protocol=tcp", $username, $password, $options);
|
||||||
|
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||||
|
|
||||||
|
$planetId = isset($_GET['planet']) ? $_GET['planet'] : '';
|
||||||
|
|
||||||
|
$allowedTables = [
|
||||||
|
'mercury' => 'MERCURY',
|
||||||
|
'venus' => 'VENUS',
|
||||||
|
'earth' => 'EARTH',
|
||||||
|
'mars' => 'MARS',
|
||||||
|
'jupiter' => 'JUPITER',
|
||||||
|
'saturn' => 'SATURN',
|
||||||
|
'uranus' => 'URANUS',
|
||||||
|
'neptune' => 'NEPTUNE',
|
||||||
|
'sun' => 'SUN',
|
||||||
|
'moon' => 'MOON',
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($planetId === 'quiz') {
|
||||||
|
$queries = [];
|
||||||
|
$seed = date('Ymd');
|
||||||
|
foreach ($allowedTables as $key => $table) {
|
||||||
|
$planetName = ucfirst($key);
|
||||||
|
$queries[] = "(SELECT explanation, '$planetName' AS planete_nom, url FROM $table WHERE explanation IS NOT NULL AND explanation != '' ORDER BY RAND($seed) LIMIT 3)";
|
||||||
|
}
|
||||||
|
$unionQuery = implode(' UNION ALL ', $queries);
|
||||||
|
|
||||||
|
$stmt = $pdo->prepare("SELECT * FROM ($unionQuery) as all_data ORDER BY RAND($seed) LIMIT 10");
|
||||||
|
$stmt->execute();
|
||||||
|
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
$questions = [];
|
||||||
|
$allPlanets = ['Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter', 'Saturn', 'Uranus', 'Neptune','Sun' , 'Moon'];
|
||||||
|
|
||||||
|
foreach ($results as $row) {
|
||||||
|
$correctEn = $row['planete_nom'];
|
||||||
|
|
||||||
|
$optionsEn = [$correctEn];
|
||||||
|
$others = array_diff($allPlanets, [$correctEn]);
|
||||||
|
shuffle($others);
|
||||||
|
$optionsEn = array_merge($optionsEn, array_slice($others, 0, 3));
|
||||||
|
shuffle($optionsEn);
|
||||||
|
|
||||||
|
$text = substr($row['explanation'], 0, 200) . '...';
|
||||||
|
|
||||||
|
$questions[] = [
|
||||||
|
'q' => "Which celestial body does this description refer to? « " . $text . " »",
|
||||||
|
'options' => $optionsEn,
|
||||||
|
'a' => $correctEn,
|
||||||
|
'img' => isset($row['url']) ? $row['url'] : ''
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
echo json_encode($questions);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!array_key_exists($planetId, $allowedTables)) {
|
||||||
|
echo json_encode([]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$tableName = $allowedTables[$planetId];
|
||||||
|
$stmt = $pdo->prepare("SELECT * FROM $tableName");
|
||||||
|
$stmt->execute();
|
||||||
|
|
||||||
|
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
echo json_encode($data);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
http_response_code(500);
|
||||||
|
echo json_encode(['error' => 'Database error: ' . $e->getMessage()]);
|
||||||
|
}
|
||||||
@@ -1,10 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
/* --- SESSION & INITIALIZATION --- */
|
|
||||||
session_start();
|
session_start();
|
||||||
|
|
||||||
$message_status = '';
|
$message_status = '';
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
/* --- FORM PROCESSING --- */
|
|
||||||
$email = filter_var($_POST['email'], FILTER_SANITIZE_EMAIL);
|
$email = filter_var($_POST['email'], FILTER_SANITIZE_EMAIL);
|
||||||
$subject = htmlspecialchars($_POST['objet']);
|
$subject = htmlspecialchars($_POST['objet']);
|
||||||
$message = htmlspecialchars($_POST['demande']);
|
$message = htmlspecialchars($_POST['demande']);
|
||||||
@@ -13,7 +11,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
$file_path = null;
|
$file_path = null;
|
||||||
|
|
||||||
if (isset($_FILES['televersement']) && $_FILES['televersement']['error'] == UPLOAD_ERR_OK) {
|
if (isset($_FILES['televersement']) && $_FILES['televersement']['error'] == UPLOAD_ERR_OK) {
|
||||||
/* --- FILE UPLOAD --- */
|
|
||||||
$file_tmp_name = $_FILES['televersement']['tmp_name'];
|
$file_tmp_name = $_FILES['televersement']['tmp_name'];
|
||||||
$file_name = $_FILES['televersement']['name'];
|
$file_name = $_FILES['televersement']['name'];
|
||||||
$file_size = $_FILES['televersement']['size'];
|
$file_size = $_FILES['televersement']['size'];
|
||||||
@@ -47,7 +44,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!$has_error) {
|
if (!$has_error) {
|
||||||
/* --- DATABASE INSERTION --- */
|
|
||||||
try {
|
try {
|
||||||
$host = '172.22.0.3';
|
$host = '172.22.0.3';
|
||||||
$dbname = 'OpenPlanetsMaps';
|
$dbname = 'OpenPlanetsMaps';
|
||||||
@@ -71,13 +67,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="fr">
|
<html lang="fr">
|
||||||
<head>
|
<head>
|
||||||
<!-- --- HEAD --- -->
|
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>Contact - OpenPlanetsMaps</title>
|
<title>Contact - OpenPlanetsMaps</title>
|
||||||
<link rel="stylesheet" href="style.css">
|
<link rel="stylesheet" href="style.css">
|
||||||
</head>
|
</head>
|
||||||
<body class="page-form">
|
<body class="page-form">
|
||||||
<!-- --- BODY & FORM --- -->
|
|
||||||
<div class="admin-box">
|
<div class="admin-box">
|
||||||
<h1>Contact</h1>
|
<h1>Contact</h1>
|
||||||
<?= $message_status ?>
|
<?= $message_status ?>
|
||||||
@@ -0,0 +1,396 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
|
||||||
|
<title>OpenPlanetsMaps</title>
|
||||||
|
<link rel="icon" href="IMG/IMP_Gen_logo-removebg-preview.png" type="image/png">
|
||||||
|
<link rel="stylesheet" href="style.css">
|
||||||
|
</head>
|
||||||
|
<body class="theme-home">
|
||||||
|
<div class="bg-animated"></div>
|
||||||
|
<div id="safe-area-block"></div>
|
||||||
|
|
||||||
|
<header>
|
||||||
|
<div class="menu-icon" onclick="toggleSidebar()">☰</div>
|
||||||
|
<h1>Open Planets Maps</h1>
|
||||||
|
<div style="display: flex; gap: 10px;">
|
||||||
|
<button class="help-btn" onclick="window.location.href='contact.php'">Contact</button>
|
||||||
|
<button class="help-btn" onclick="window.location.href='admin.php'">Admin</button>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<nav id="sidebar" class="sidebar">
|
||||||
|
<ul>
|
||||||
|
<li onclick="showLayer('home')">Home</li>
|
||||||
|
<li class="menu-category">Planets</li>
|
||||||
|
<li onclick="showLayer('mercury')">Mercury</li>
|
||||||
|
<li onclick="showLayer('venus')">Venus</li>
|
||||||
|
<li onclick="showLayer('earth')">Earth</li>
|
||||||
|
<li onclick="showLayer('mars')">Mars</li>
|
||||||
|
<li onclick="showLayer('jupiter')">Jupiter</li>
|
||||||
|
<li onclick="showLayer('saturn')">Saturn</li>
|
||||||
|
<li onclick="showLayer('uranus')">Uranus</li>
|
||||||
|
<li onclick="showLayer('neptune')">Neptune</li>
|
||||||
|
<li class="menu-category">Celestial Bodies</li>
|
||||||
|
<li onclick="showLayer('sun')">Sun</li>
|
||||||
|
<li onclick="showLayer('moon')">Moon</li>
|
||||||
|
<li class="menu-category">Activities</li>
|
||||||
|
<li onclick="showLayer('Quiz')">Quiz</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<main id="content-area">
|
||||||
|
<section id="layer-home" class="layer active">
|
||||||
|
<div class="main-img">
|
||||||
|
<iframe title="Solar System animation" frameborder="0" allow="autoplay; fullscreen; xr-spatial-tracking" src="https://sketchfab.com/models/b7c69a6b655b47c99f871d5ec5aee854/embed?autostart=1&ui_infos=0&ui_watermark=0&ui_controls=0"></iframe>
|
||||||
|
</div>
|
||||||
|
<div class="flex-row">
|
||||||
|
<div class="box">
|
||||||
|
<h2>Space Exploration</h2>
|
||||||
|
<p>Navigate through the solar system and discover the unique characteristics of each planet with our interactive maps.</p>
|
||||||
|
</div>
|
||||||
|
<div class="box">
|
||||||
|
<h2>Open Data</h2>
|
||||||
|
<p>Access a topographic database from space agencies, centralized in an open source tool.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ticker-wrap">
|
||||||
|
<div class="ticker">Solar System - 8 Planets - Open Source Mapping - Topographic Data - Interactive Exploration...</div>
|
||||||
|
</div>
|
||||||
|
<div class="desc-box">Ready for launch? Open the side menu (☰) and select a destination to begin your journey.</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="layer-mercury" class="layer">
|
||||||
|
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
|
||||||
|
<div class="main-img">
|
||||||
|
<iframe title="Mercury" frameborder="0" allow="autoplay; fullscreen; xr-spatial-tracking" src="https://sketchfab.com/models/0930a4f0405243f6a9f93a4da79c66b6/embed?autostart=1&ui_infos=0&ui_watermark=0&ui_controls=0"></iframe>
|
||||||
|
</div>
|
||||||
|
<div class="desc-box">Mercury is the closest planet to the Sun and the smallest in the solar system. Its surface is heavily cratered, resembling our Moon, and it experiences extreme temperature variations.</div>
|
||||||
|
<div class="ticker-wrap">
|
||||||
|
<div class="ticker">Distance from the Sun: 58 million km • Temperature: -180°C to 430°C • Surface area: 74.8 million km² • Length of day: 59 Earth days</div>
|
||||||
|
</div>
|
||||||
|
<div class="table-container">
|
||||||
|
<table class="data-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Image</th>
|
||||||
|
<th>Date</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="tbody-mercury">
|
||||||
|
<tr><td colspan="3">Waiting for data...</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="layer-venus" class="layer">
|
||||||
|
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
|
||||||
|
<div class="main-img">
|
||||||
|
<iframe title="Venus" frameborder="0" allow="autoplay; fullscreen; xr-spatial-tracking" src="https://sketchfab.com/models/d497ce25553447f3b7b679110c85cfa1/embed?autostart=1&ui_infos=0&ui_watermark=0&ui_controls=0"></iframe>
|
||||||
|
</div>
|
||||||
|
<div class="desc-box">Venus is the second planet in the solar system and the hottest. Its highly dense atmosphere causes an extreme greenhouse effect, and its surface is masked by thick clouds of sulfuric acid.</div>
|
||||||
|
<div class="ticker-wrap">
|
||||||
|
<div class="ticker">Distance from the Sun: 108 million km • Average temperature: 462°C • Surface area: 460 million km² • Length of day: 243 Earth days</div>
|
||||||
|
</div>
|
||||||
|
<div class="table-container">
|
||||||
|
<table class="data-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Image</th>
|
||||||
|
<th>Date</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="tbody-venus">
|
||||||
|
<tr><td colspan="3">Waiting for data...</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="layer-earth" class="layer">
|
||||||
|
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
|
||||||
|
<div class="main-img">
|
||||||
|
<iframe title="Earth : Planets / Solar System" frameborder="0" allow="autoplay; fullscreen; xr-spatial-tracking" src="https://sketchfab.com/models/cb636fdd7f124125a3b7d194da9942e1/embed?autostart=1&ui_infos=0&ui_watermark=0&ui_controls=0"></iframe>
|
||||||
|
</div>
|
||||||
|
<div class="desc-box">Our home planet, Earth, is the third planet in the solar system and the only one known to harbor life. It is distinguished by its vast oceans of liquid water that cover more than 70% of its surface.</div>
|
||||||
|
<div class="ticker-wrap">
|
||||||
|
<div class="ticker">Distance from the Sun: 150 million km (1 AU) • Average temperature: 15°C • Surface area: 510 million km² • Natural satellites: 1 (The Moon)</div>
|
||||||
|
</div>
|
||||||
|
<div class="table-container">
|
||||||
|
<table class="data-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Image</th>
|
||||||
|
<th>Date</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="tbody-earth">
|
||||||
|
<tr><td colspan="3">Waiting for data...</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="layer-mars" class="layer">
|
||||||
|
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
|
||||||
|
<div class="main-img">
|
||||||
|
<iframe title="Mars: InSight Lander and Volcanic Regions" frameborder="0" allow="autoplay; fullscreen; xr-spatial-tracking" src="https://sketchfab.com/models/50bb6eb0d1104d43bf684d2b0f70de1d/embed?autostart=1&ui_infos=0&ui_watermark=0&ui_controls=0"></iframe>
|
||||||
|
</div>
|
||||||
|
<div class="desc-box">Nicknamed the « Red Planet » due to the iron oxide on its surface, Mars has polar ice caps, the largest volcano in the solar system (Olympus Mons), and an immense canyon (Valles Marineris).</div>
|
||||||
|
<div class="ticker-wrap">
|
||||||
|
<div class="ticker">Distance from the Sun: 227.9 million km • Average temperature: -63°C • Surface area: 144.8 million km² • Gravity: 3.72 m/s²</div>
|
||||||
|
</div>
|
||||||
|
<div class="table-container">
|
||||||
|
<table class="data-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Image</th>
|
||||||
|
<th>Date</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="tbody-mars">
|
||||||
|
<tr><td colspan="3">Waiting for data...</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="layer-jupiter" class="layer">
|
||||||
|
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
|
||||||
|
<div class="main-img">
|
||||||
|
<iframe title="jupiter" frameborder="0" allow="autoplay; fullscreen; xr-spatial-tracking" src="https://sketchfab.com/models/c5275eb96af245e4a8453837ac728a62/embed?autostart=1&ui_infos=0&ui_watermark=0&ui_controls=0"></iframe>
|
||||||
|
</div>
|
||||||
|
<div class="desc-box">Jupiter is the largest planet in our solar system. This gas giant is famous for its Great Red Spot, a gigantic anticyclonic storm, and possesses dozens of fascinating moons.</div>
|
||||||
|
<div class="ticker-wrap">
|
||||||
|
<div class="ticker">Distance from the Sun: 778 million km • Average temperature: -110°C • Surface area: 61.4 billion km² • Natural satellites: 95 known</div>
|
||||||
|
</div>
|
||||||
|
<div class="table-container">
|
||||||
|
<table class="data-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Image</th>
|
||||||
|
<th>Date</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="tbody-jupiter">
|
||||||
|
<tr><td colspan="3">Waiting for data...</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="layer-saturn" class="layer">
|
||||||
|
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
|
||||||
|
<div class="main-img">
|
||||||
|
<iframe title="Saturn" frameborder="0" allow="autoplay; fullscreen; xr-spatial-tracking" src="https://sketchfab.com/models/c09a1970148c43ad99db134a9d6d00b5/embed?autostart=1&ui_infos=0&ui_watermark=0&ui_controls=0"></iframe>
|
||||||
|
</div>
|
||||||
|
<div class="desc-box">Instantly recognizable by its spectacular system of rings composed of ice and rock particles, Saturn is a vast gas giant with extremely violent winds.</div>
|
||||||
|
<div class="ticker-wrap">
|
||||||
|
<div class="ticker">Distance from the Sun: 1.43 billion km • Average temperature: -140°C • Surface area: 42.7 billion km² • Natural satellites: 146 known</div>
|
||||||
|
</div>
|
||||||
|
<div class="table-container">
|
||||||
|
<table class="data-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Image</th>
|
||||||
|
<th>Date</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="tbody-saturn">
|
||||||
|
<tr><td colspan="3">Waiting for data...</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="layer-uranus" class="layer">
|
||||||
|
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
|
||||||
|
<div class="main-img">
|
||||||
|
<iframe title="Uranus" frameborder="0" allow="autoplay; fullscreen; xr-spatial-tracking" src="https://sketchfab.com/models/0009a69dbace44608c0bd09af9ba20db/embed?autostart=1&ui_infos=0&ui_watermark=0&ui_controls=0"></iframe>
|
||||||
|
</div>
|
||||||
|
<div class="desc-box">Uranus is an ice giant whose axis of rotation is highly tilted, making it appear to « roll » along its orbit. Its beautiful cyan tint is due to the presence of methane.</div>
|
||||||
|
<div class="ticker-wrap">
|
||||||
|
<div class="ticker">Distance from the Sun: 2.87 billion km • Average temperature: -195°C • Surface area: 8.1 billion km² • Length of year: 84 Earth years</div>
|
||||||
|
</div>
|
||||||
|
<div class="table-container">
|
||||||
|
<table class="data-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Image</th>
|
||||||
|
<th>Date</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="tbody-uranus">
|
||||||
|
<tr><td colspan="3">Waiting for data...</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="layer-neptune" class="layer">
|
||||||
|
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
|
||||||
|
<div class="main-img">
|
||||||
|
<iframe title="Neptune" frameborder="0" allow="autoplay; fullscreen; xr-spatial-tracking" src="https://sketchfab.com/models/2a6f9ccc5c724a709912774caa197b77/embed?autostart=1&ui_infos=0&ui_watermark=0&ui_controls=0"></iframe>
|
||||||
|
</div>
|
||||||
|
<div class="desc-box">The farthest planet from the Sun is another ice giant, Neptune. It is known for its deep azure blue color and its supersonic winds, the fastest in the entire solar system.</div>
|
||||||
|
<div class="ticker-wrap">
|
||||||
|
<div class="ticker">Distance from the Sun: 4.5 billion km • Average temperature: -200°C • Surface area: 7.6 billion km² • Wind speed: up to 2,100 km/h</div>
|
||||||
|
</div>
|
||||||
|
<div class="table-container">
|
||||||
|
<table class="data-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Image</th>
|
||||||
|
<th>Date</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="tbody-neptune">
|
||||||
|
<tr><td colspan="3">Waiting for data...</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="layer-sun" class="layer">
|
||||||
|
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
|
||||||
|
<div class="main-img">
|
||||||
|
<div class="sketchfab-embed-wrapper">
|
||||||
|
<iframe title="Photorealistic Sun" frameborder="0" allowfullscreen mozallowfullscreen="true" webkitallowfullscreen="true" allow="autoplay; fullscreen; xr-spatial-tracking" xr-spatial-tracking execution-while-out-of-viewport execution-while-not-rendered web-share src="https://sketchfab.com/models/7556485516804d0db3960b834e4b3f98/embed"> </iframe>
|
||||||
|
<p> <a href="https://sketchfab.com/3d-models/photorealistic-sun-7556485516804d0db3960b834e4b3f98?utm_medium=embed&utm_campaign=share-popup&utm_content=7556485516804d0db3960b834e4b3f98" target="_blank" rel="nofollow"> Photorealistic Sun </a> by <a href="https://sketchfab.com/cesar_salcedo?utm_medium=embed&utm_campaign=share-popup&utm_content=7556485516804d0db3960b834e4b3f98" target="_blank" rel="nofollow"> Cesar Salcedo CG </a> on <a href="https://sketchfab.com?utm_medium=embed&utm_campaign=share-popup&utm_content=7556485516804d0db3960b834e4b3f98" target="_blank" rel="nofollow">Sketchfab</a></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="desc-box">The Sun is the star at the center of our solar system. It alone accounts for about 99.8% of the solar system's mass and provides the energy necessary to sustain life on Earth.</div>
|
||||||
|
<div class="ticker-wrap">
|
||||||
|
<div class="ticker">Type: Yellow dwarf • Surface temperature: 5,500°C • Distance to Earth: 150 million km (1 AU) • Age: 4.6 billion years</div>
|
||||||
|
</div>
|
||||||
|
<div class="table-container">
|
||||||
|
<table class="data-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Image</th>
|
||||||
|
<th>Date</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="tbody-sun">
|
||||||
|
<tr><td colspan="3">Waiting for data...</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="layer-moon" class="layer">
|
||||||
|
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
|
||||||
|
<div class="main-img">
|
||||||
|
<div class="sketchfab-embed-wrapper">
|
||||||
|
<iframe title="Moon" frameborder="0" allowfullscreen mozallowfullscreen="true" webkitallowfullscreen="true" allow="autoplay; fullscreen; xr-spatial-tracking" xr-spatial-tracking execution-while-out-of-viewport execution-while-not-rendered web-share src="https://sketchfab.com/models/870de693475d436c8e925ab0bcda4ca4/embed"> </iframe>
|
||||||
|
<p> <a href="https://sketchfab.com/3d-models/moon-870de693475d436c8e925ab0bcda4ca4?utm_medium=embed&utm_campaign=share-popup&utm_content=870de693475d436c8e925ab0bcda4ca4" target="_blank" rel="nofollow"> Moon </a> by <a href="https://sketchfab.com/miekeroth?utm_medium=embed&utm_campaign=share-popup&utm_content=870de693475d436c8e925ab0bcda4ca4" target="_blank" rel="nofollow"> Mieke Roth </a> on <a href="https://sketchfab.com?utm_medium=embed&utm_campaign=share-popup&utm_content=870de693475d436c8e925ab0bcda4ca4" target="_blank" rel="nofollow">Sketchfab</a></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="desc-box">The Moon is Earth's only natural satellite. It is the fifth largest satellite in the solar system and the only non-terrestrial celestial body to have been visited by humans.</div>
|
||||||
|
<div class="ticker-wrap">
|
||||||
|
<div class="ticker">Distance to Earth: 384,400 km • Temperature: -173°C to 127°C • Gravity: 1.62 m/s² • Orbit duration: 27.3 days</div>
|
||||||
|
</div>
|
||||||
|
<div class="table-container">
|
||||||
|
<table class="data-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Image</th>
|
||||||
|
<th>Date</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="tbody-moon">
|
||||||
|
<tr><td colspan="3">Waiting for data...</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="layer-Quiz" class="layer">
|
||||||
|
<div class="desc-box">Test your knowledge of the solar system! Answer the questions below to see if you are a true space expert.</div>
|
||||||
|
|
||||||
|
<div class="daily-challenge-box">
|
||||||
|
<strong class="daily-challenge-title">◈ DAILY CHALLENGE</strong>
|
||||||
|
<p class="daily-challenge-desc">Every day at midnight, the onboard computer compiles our archives to generate a new unique 10-question Quiz. Practice daily to perfect your knowledge!</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="quiz-container" class="box">
|
||||||
|
<h2 id="quiz-question">Loading the Quiz...</h2>
|
||||||
|
<div id="quiz-options"></div>
|
||||||
|
<div id="quiz-img-preview">
|
||||||
|
<div class="quiz-img-label">◈ SOURCE — MISSION IMAGE</div>
|
||||||
|
<img src="" alt="" />
|
||||||
|
<div class="quiz-img-caption"></div>
|
||||||
|
</div>
|
||||||
|
<p id="quiz-score"></p>
|
||||||
|
<button id="quiz-restart-btn" onclick="initQuiz()">Restart the Quiz</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer class="site-footer" onclick="openCredits()" title="Credits & About">
|
||||||
|
© 2026 OpenPlanetsMaps. Royalty-free. <span class="footer-credits-hint">— Credits ↗</span>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<div id="credits-overlay"></div>
|
||||||
|
<div id="credits-panel">
|
||||||
|
<button class="credits-close" onclick="closeCredits()">✕</button>
|
||||||
|
<div class="credits-header">
|
||||||
|
<span class="credits-tag">◈ SYSTEM / ABOUT</span>
|
||||||
|
<h2 class="credits-title">OpenPlanetsMaps</h2>
|
||||||
|
<p class="credits-version">v1.0 — 2026</p>
|
||||||
|
</div>
|
||||||
|
<div class="credits-body">
|
||||||
|
<div class="credits-section">
|
||||||
|
<h3>Project</h3>
|
||||||
|
<p>OpenPlanetsMaps is an open source tool for interactive mapping of the solar system. Topographic data comes from the main global space agencies.</p>
|
||||||
|
</div>
|
||||||
|
<div class="credits-section">
|
||||||
|
<h3>Data & Sources</h3>
|
||||||
|
<ul>
|
||||||
|
<li><span>NASA</span> — National Aeronautics and Space Administration</li>
|
||||||
|
<li><span>ESA</span> — European Space Agency</li>
|
||||||
|
<li><span>JAXA</span> — Japan Aerospace Exploration Agency</li>
|
||||||
|
<li><span>USGS</span> — Astrogeology Science Center</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="credits-section">
|
||||||
|
<h3>3D Models</h3>
|
||||||
|
<ul>
|
||||||
|
<li><span>Sketchfab</span> — Hosting & rendering of interactive models</li>
|
||||||
|
<li>Models under Creative Commons licenses</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="credits-section">
|
||||||
|
<h3>Technologies</h3>
|
||||||
|
<ul>
|
||||||
|
<li><span>HTML / CSS / JS</span> — Front-end</li>
|
||||||
|
<li><span>PHP + MySQL</span> — Back-end & database</li>
|
||||||
|
<li><span>Orbitron, Space Grotesk, Space Mono</span> — Google Fonts</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="credits-section">
|
||||||
|
<h3>License</h3>
|
||||||
|
<p>This project is freely distributed. Scientific data remains the property of their respective organizations.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="credits-footer">
|
||||||
|
<span>◈ OpenPlanetsMaps — Royalty-free — 2026</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,401 @@
|
|||||||
|
function toggleSidebar() {
|
||||||
|
document.getElementById('sidebar').classList.toggle('open');
|
||||||
|
}
|
||||||
|
|
||||||
|
function showLayer(layerId) {
|
||||||
|
document.querySelectorAll('.layer').forEach(layer => {
|
||||||
|
layer.classList.remove('active');
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('layer-' + layerId).classList.add('active');
|
||||||
|
|
||||||
|
document.body.className = '';
|
||||||
|
document.body.classList.add('theme-' + layerId);
|
||||||
|
|
||||||
|
if (layerId === 'Quiz') {
|
||||||
|
initQuiz();
|
||||||
|
} else if (layerId !== 'home') {
|
||||||
|
fetchData(layerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleSidebar();
|
||||||
|
}
|
||||||
|
|
||||||
|
const planetData = {};
|
||||||
|
const planetCols = {};
|
||||||
|
|
||||||
|
function wireSearch(planetId) {
|
||||||
|
const layer = document.getElementById('layer-' + planetId);
|
||||||
|
if (!layer) return;
|
||||||
|
const input = layer.querySelector('.search-bar input');
|
||||||
|
if (!input) return;
|
||||||
|
|
||||||
|
const fresh = input.cloneNode(true);
|
||||||
|
input.parentNode.replaceChild(fresh, input);
|
||||||
|
|
||||||
|
fresh.addEventListener('input', () => {
|
||||||
|
filterTable(planetId, fresh.value.trim());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterTable(planetId, query) {
|
||||||
|
const tbody = document.getElementById('tbody-' + planetId);
|
||||||
|
if (!tbody) return;
|
||||||
|
|
||||||
|
const rows = Array.from(tbody.querySelectorAll('tr'));
|
||||||
|
const cols = planetCols[planetId] || [];
|
||||||
|
const data = planetData[planetId] || [];
|
||||||
|
|
||||||
|
const titleIndices = cols.reduce((acc, col, i) => {
|
||||||
|
const c = col.toLowerCase();
|
||||||
|
if (c === 'name' || c.includes('title')) {
|
||||||
|
acc.push(i);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const searchIndices = titleIndices.length > 0
|
||||||
|
? titleIndices
|
||||||
|
: cols.reduce((acc, col, i) => {
|
||||||
|
const c = col.toLowerCase();
|
||||||
|
if (!c.includes('url') && !c.includes('desc') && !c.includes('expl') && c !== 'image' && c !== 'img') {
|
||||||
|
acc.push(i);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const tokens = query.toLowerCase().split(/\s+/).filter(Boolean);
|
||||||
|
|
||||||
|
const tableContainer = tbody.closest('.table-container');
|
||||||
|
const showMoreBtn = tableContainer ? tableContainer.querySelector('.show-more-btn') : null;
|
||||||
|
|
||||||
|
if (tokens.length === 0) {
|
||||||
|
rows.forEach((tr, index) => {
|
||||||
|
tr.style.display = '';
|
||||||
|
if (data.length > 10) {
|
||||||
|
if (index >= 10) tr.classList.add('hidden-row');
|
||||||
|
else tr.classList.remove('hidden-row');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (showMoreBtn) showMoreBtn.style.display = '';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showMoreBtn) showMoreBtn.style.display = 'none';
|
||||||
|
|
||||||
|
rows.forEach((tr, index) => {
|
||||||
|
const rowObj = data[index];
|
||||||
|
if (!rowObj) { tr.style.display = 'none'; return; }
|
||||||
|
|
||||||
|
const haystack = searchIndices
|
||||||
|
.map(i => String(rowObj[cols[i]] || '').toLowerCase())
|
||||||
|
.join(' ');
|
||||||
|
|
||||||
|
const matches = tokens.every(token => haystack.includes(token));
|
||||||
|
|
||||||
|
tr.classList.remove('hidden-row');
|
||||||
|
tr.style.display = matches ? '' : 'none';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchData(planetId) {
|
||||||
|
const tbody = document.getElementById('tbody-' + planetId);
|
||||||
|
if (!tbody) return;
|
||||||
|
|
||||||
|
if (tbody.getAttribute('data-loaded') === 'true') {
|
||||||
|
wireSearch(planetId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody.innerHTML = '<tr><td colspan="3">Loading data from the database...</td></tr>';
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(`api.php?planet=${planetId}`);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
const errorData = await response.json().catch(() => ({}));
|
||||||
|
throw new Error(errorData.error || `HTTP Error: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
tbody.innerHTML = '';
|
||||||
|
|
||||||
|
if (data.length === 0) {
|
||||||
|
tbody.innerHTML = '<tr><td colspan="3">No data available at the moment.</td></tr>';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const columns = Object.keys(data[0]).filter(col => col.toLowerCase() !== 'copyright');
|
||||||
|
|
||||||
|
planetData[planetId] = data;
|
||||||
|
planetCols[planetId] = columns;
|
||||||
|
|
||||||
|
const thead = tbody.parentElement.querySelector('thead');
|
||||||
|
thead.innerHTML = '<tr>' + columns.map(col => {
|
||||||
|
const colLower = col.toLowerCase();
|
||||||
|
const isDesc = colLower.includes('desc') || colLower.includes('expl');
|
||||||
|
const isUrl = colLower.includes('url') || colLower === 'image' || colLower === 'img';
|
||||||
|
|
||||||
|
let className = '';
|
||||||
|
if (isDesc) className = ' class="col-desc"';
|
||||||
|
else if (isUrl) className = ' class="col-url"';
|
||||||
|
return `<th${className}>${col.toUpperCase()}</th>`;
|
||||||
|
}).join('') + '</tr>';
|
||||||
|
|
||||||
|
data.forEach((row, index) => {
|
||||||
|
const tr = document.createElement('tr');
|
||||||
|
|
||||||
|
if (index >= 10) tr.classList.add('hidden-row');
|
||||||
|
|
||||||
|
let rowHtml = '';
|
||||||
|
columns.forEach(col => {
|
||||||
|
const colLower = col.toLowerCase();
|
||||||
|
const colLabel = col.toUpperCase();
|
||||||
|
if (colLower.includes('url') || colLower === 'image' || colLower === 'img') {
|
||||||
|
const url = row[col];
|
||||||
|
if (url && url.trim() !== '') {
|
||||||
|
rowHtml += `<td class="col-url" data-label="${colLabel}">
|
||||||
|
<a href="${url}" target="_blank" rel="noopener noreferrer">
|
||||||
|
${url}
|
||||||
|
</a>
|
||||||
|
</td>`;
|
||||||
|
} else {
|
||||||
|
rowHtml += `<td class="col-url" data-label="${colLabel}">N/A</td>`;
|
||||||
|
}
|
||||||
|
} else if (colLower.includes('desc') || colLower.includes('expl')) {
|
||||||
|
const text = row[col] || '';
|
||||||
|
let fontSizeStyle = '';
|
||||||
|
if (text.length > 200) fontSizeStyle = ' font-size: 0.75rem;';
|
||||||
|
else if (text.length > 100) fontSizeStyle = ' font-size: 0.85rem;';
|
||||||
|
rowHtml += `<td class="col-desc" style="${fontSizeStyle}" data-label="${colLabel}">${text}</td>`;
|
||||||
|
} else {
|
||||||
|
rowHtml += `<td data-label="${colLabel}">${row[col]}</td>`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
tr.innerHTML = rowHtml;
|
||||||
|
tbody.appendChild(tr);
|
||||||
|
});
|
||||||
|
|
||||||
|
const tableContainer = tbody.closest('.table-container');
|
||||||
|
if (tableContainer) {
|
||||||
|
tableContainer.style.overflowX = 'auto';
|
||||||
|
tableContainer.style.maxWidth = '100%';
|
||||||
|
tableContainer.style.WebkitOverflowScrolling = 'touch';
|
||||||
|
}
|
||||||
|
const existingBtn = tableContainer.querySelector('.show-more-btn');
|
||||||
|
if (existingBtn) existingBtn.remove();
|
||||||
|
|
||||||
|
if (data.length > 10) {
|
||||||
|
const btn = document.createElement('button');
|
||||||
|
btn.innerHTML = 'Show more ⬇';
|
||||||
|
btn.className = 'show-more-btn';
|
||||||
|
btn.onclick = () => {
|
||||||
|
tbody.querySelectorAll('.hidden-row').forEach(row => row.classList.remove('hidden-row'));
|
||||||
|
btn.remove();
|
||||||
|
};
|
||||||
|
tableContainer.appendChild(btn);
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody.setAttribute('data-loaded', 'true');
|
||||||
|
|
||||||
|
wireSearch(planetId);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Database connection error:", error);
|
||||||
|
tbody.innerHTML = `<tr><td colspan="3" style="color: #ff4444;">Technical error: ${error.message}</td></tr>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let quizQuestions = [];
|
||||||
|
let currentQuizIndex = 0;
|
||||||
|
let quizScore = 0;
|
||||||
|
|
||||||
|
async function initQuiz() {
|
||||||
|
currentQuizIndex = 0;
|
||||||
|
quizScore = 0;
|
||||||
|
document.getElementById('quiz-restart-btn').style.display = 'none';
|
||||||
|
document.getElementById('quiz-score').textContent = '';
|
||||||
|
|
||||||
|
if (quizQuestions.length === 0) {
|
||||||
|
document.getElementById('quiz-question').textContent = "Loading today's Quiz...";
|
||||||
|
document.getElementById('quiz-options').innerHTML = '';
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(`api.php?planet=quiz`);
|
||||||
|
if (!response.ok) {
|
||||||
|
let errMsg = "Network error";
|
||||||
|
try {
|
||||||
|
const errData = await response.json();
|
||||||
|
if (errData.error) errMsg = errData.error;
|
||||||
|
} catch (e) {}
|
||||||
|
throw new Error(errMsg);
|
||||||
|
}
|
||||||
|
quizQuestions = await response.json();
|
||||||
|
|
||||||
|
if (quizQuestions.length === 0) {
|
||||||
|
document.getElementById('quiz-question').textContent = "Not enough data in the database to generate a quiz.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Quiz Error:", error);
|
||||||
|
document.getElementById('quiz-question').textContent = "Error: " + error.message;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
showQuizQuestion();
|
||||||
|
}
|
||||||
|
|
||||||
|
function showQuizQuestion() {
|
||||||
|
const preview = document.getElementById('quiz-img-preview');
|
||||||
|
|
||||||
|
if (currentQuizIndex >= quizQuestions.length) {
|
||||||
|
document.getElementById('quiz-question').textContent = "Today's Quiz finished!";
|
||||||
|
document.getElementById('quiz-options').innerHTML = "";
|
||||||
|
document.getElementById('quiz-score').textContent = `Your score: ${quizScore} / ${quizQuestions.length}`;
|
||||||
|
document.getElementById('quiz-restart-btn').style.display = 'inline-block';
|
||||||
|
if (preview) preview.classList.remove('visible');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const qObj = quizQuestions[currentQuizIndex];
|
||||||
|
document.getElementById('quiz-question').innerText = `Question ${currentQuizIndex + 1}/${quizQuestions.length}:\n\n${qObj.q}`;
|
||||||
|
|
||||||
|
const optionsContainer = document.getElementById('quiz-options');
|
||||||
|
optionsContainer.innerHTML = '';
|
||||||
|
|
||||||
|
qObj.options.forEach(opt => {
|
||||||
|
const btn = document.createElement('button');
|
||||||
|
btn.className = 'quiz-btn';
|
||||||
|
btn.textContent = opt;
|
||||||
|
btn.onclick = () => checkAnswer(opt, qObj.a, btn);
|
||||||
|
optionsContainer.appendChild(btn);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (preview) {
|
||||||
|
preview.classList.remove('visible');
|
||||||
|
const oldImg = preview.querySelector('img');
|
||||||
|
const oldVid = preview.querySelector('video');
|
||||||
|
if (oldImg) { oldImg.src = ''; oldImg.style.display = 'none'; }
|
||||||
|
if (oldVid) { oldVid.pause(); oldVid.src = ''; oldVid.style.display = 'none'; }
|
||||||
|
|
||||||
|
if (qObj.img && qObj.img.trim() !== '') {
|
||||||
|
const url = qObj.img.trim();
|
||||||
|
const isVideo = /\.(mp4|webm|ogg|mov)(\?.*)?$/i.test(url);
|
||||||
|
const caption = preview.querySelector('.quiz-img-caption');
|
||||||
|
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
if (isVideo) {
|
||||||
|
let vid = preview.querySelector('video');
|
||||||
|
if (!vid) {
|
||||||
|
vid = document.createElement('video');
|
||||||
|
vid.controls = true;
|
||||||
|
vid.preload = 'metadata';
|
||||||
|
vid.style.display = 'none';
|
||||||
|
preview.querySelector('.quiz-img-label').insertAdjacentElement('afterend', vid);
|
||||||
|
}
|
||||||
|
vid.src = url;
|
||||||
|
vid.style.display = 'block';
|
||||||
|
if (oldImg) oldImg.style.display = 'none';
|
||||||
|
} else {
|
||||||
|
if (oldImg) {
|
||||||
|
oldImg.src = url;
|
||||||
|
oldImg.alt = 'Image associated with the question';
|
||||||
|
oldImg.style.display = 'block';
|
||||||
|
}
|
||||||
|
if (oldVid) oldVid.style.display = 'none';
|
||||||
|
}
|
||||||
|
caption.textContent = url;
|
||||||
|
preview.classList.add('visible');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkAnswer(selected, correct, btn) {
|
||||||
|
const optionsContainer = document.getElementById('quiz-options');
|
||||||
|
const buttons = optionsContainer.querySelectorAll('.quiz-btn');
|
||||||
|
|
||||||
|
buttons.forEach(b => {
|
||||||
|
b.disabled = true;
|
||||||
|
b.style.cursor = 'default';
|
||||||
|
});
|
||||||
|
|
||||||
|
if (selected === correct) {
|
||||||
|
btn.classList.add('correct');
|
||||||
|
quizScore++;
|
||||||
|
} else {
|
||||||
|
btn.classList.add('wrong');
|
||||||
|
buttons.forEach(b => {
|
||||||
|
if (b.textContent === correct) b.classList.add('correct');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
currentQuizIndex++;
|
||||||
|
showQuizQuestion();
|
||||||
|
}, 1800);
|
||||||
|
}
|
||||||
|
|
||||||
|
function openCredits() {
|
||||||
|
document.getElementById('credits-panel').classList.add('open');
|
||||||
|
document.getElementById('credits-overlay').classList.add('open');
|
||||||
|
document.body.style.overflow = 'hidden';
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeCredits() {
|
||||||
|
document.getElementById('credits-panel').classList.remove('open');
|
||||||
|
document.getElementById('credits-overlay').classList.remove('open');
|
||||||
|
document.body.style.overflow = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
const overlay = document.getElementById('credits-overlay');
|
||||||
|
if (overlay) overlay.addEventListener('click', closeCredits);
|
||||||
|
|
||||||
|
document.addEventListener('keydown', e => {
|
||||||
|
if (e.key === 'Escape') closeCredits();
|
||||||
|
});
|
||||||
|
|
||||||
|
const isMobile = window.innerWidth <= 768 || /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
||||||
|
const isElectron = navigator.userAgent.toLowerCase().includes('electron');
|
||||||
|
const isCapacitor = window.Capacitor !== undefined; // Détecte l'application mobile native
|
||||||
|
|
||||||
|
if (isCapacitor) {
|
||||||
|
document.body.classList.add('is-mobile-app');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isMobile || isElectron || isCapacitor) {
|
||||||
|
const iframes = document.querySelectorAll('iframe');
|
||||||
|
iframes.forEach(iframe => {
|
||||||
|
const fallback = document.createElement('div');
|
||||||
|
if (isElectron) {
|
||||||
|
fallback.textContent = "3D models are not compatible on the desktop app";
|
||||||
|
} else if (isCapacitor) {
|
||||||
|
fallback.textContent = "3D models are not compatible on the mobile app";
|
||||||
|
} else {
|
||||||
|
fallback.textContent = "functionality not available on mobile devices";
|
||||||
|
}
|
||||||
|
fallback.style.display = "flex";
|
||||||
|
fallback.style.alignItems = "center";
|
||||||
|
fallback.style.justifyContent = "center";
|
||||||
|
|
||||||
|
// Correction du responsive : on empêche la boîte de déborder de l'écran
|
||||||
|
fallback.style.width = "100%";
|
||||||
|
fallback.style.maxWidth = "100%";
|
||||||
|
fallback.style.boxSizing = "border-box";
|
||||||
|
|
||||||
|
fallback.style.minHeight = "200px";
|
||||||
|
fallback.style.backgroundColor = "#1e293b";
|
||||||
|
fallback.style.color = "#f87171";
|
||||||
|
fallback.style.border = "1px solid #334155";
|
||||||
|
fallback.style.borderRadius = "8px";
|
||||||
|
fallback.style.padding = "20px";
|
||||||
|
fallback.style.textAlign = "center";
|
||||||
|
|
||||||
|
iframe.parentNode.replaceChild(fallback, iframe);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -0,0 +1,593 @@
|
|||||||
|
@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&family=Orbitron:wght@400;600;700;900&family=Space+Mono:wght@400;700&display=swap');
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--theme-color: #4f8eff;
|
||||||
|
--theme-glow: rgba(79,142,255,.35);
|
||||||
|
--theme-subtle:rgba(79,142,255,.08);
|
||||||
|
--bg-deep: #020408; --bg-mid: #060d18;
|
||||||
|
--text-primary: #e8f0ff; --text-secondary: #7a9bc4; --text-muted: #3d5478;
|
||||||
|
--border: rgba(79,142,255,.15);
|
||||||
|
}
|
||||||
|
body.theme-home { --theme-color:#4f8eff; --theme-glow:rgba(79,142,255,.4); --bg-deep:#020408; --bg-mid:#060d18; }
|
||||||
|
body.theme-mercury { --theme-color:#c0a080; --theme-glow:rgba(192,160,128,.4); --bg-deep:#0c0906; --bg-mid:#1a1008; }
|
||||||
|
body.theme-venus { --theme-color:#ff9230; --theme-glow:rgba(255,146,48,.4); --bg-deep:#0d0600; --bg-mid:#1e0e00; }
|
||||||
|
body.theme-earth { --theme-color:#00cfff; --theme-glow:rgba(0,207,255,.4); --bg-deep:#010b10; --bg-mid:#031520; }
|
||||||
|
body.theme-mars { --theme-color:#ff5040; --theme-glow:rgba(255,80,64,.4); --bg-deep:#0d0200; --bg-mid:#1e0600; }
|
||||||
|
body.theme-jupiter { --theme-color:#ffb347; --theme-glow:rgba(255,179,71,.4); --bg-deep:#0d0800; --bg-mid:#1e1200; }
|
||||||
|
body.theme-saturn { --theme-color:#f5d060; --theme-glow:rgba(245,208,96,.4); --bg-deep:#0c0900; --bg-mid:#1c1500; }
|
||||||
|
body.theme-uranus { --theme-color:#40e8d0; --theme-glow:rgba(64,232,208,.4); --bg-deep:#000c0b; --bg-mid:#001a18; }
|
||||||
|
body.theme-neptune { --theme-color:#2060ff; --theme-glow:rgba(32,96,255,.4); --bg-deep:#000208; --bg-mid:#000510; }
|
||||||
|
body.theme-sun { --theme-color:#ffcc44; --theme-glow:rgba(255,180,40,.55); --theme-subtle:rgba(255,180,40,.09); --bg-deep:#0d0500; --bg-mid:#200c00; --border:rgba(255,180,40,.2); --text-primary:#fff5dc; --text-secondary:#c4923a; --text-muted:#6b4010; }
|
||||||
|
body.theme-moon { --theme-color:#c8cfe8; --theme-glow:rgba(200,207,232,.35); --theme-subtle:rgba(200,207,232,.06); --bg-deep:#060608; --bg-mid:#0e0f14; --border:rgba(200,207,232,.12); --text-primary:#dde2f0; --text-secondary:#7e8ba8; --text-muted:#3c4258; }
|
||||||
|
body.theme-Quiz { --theme-color:#7eb8f7; --theme-glow:rgba(126,184,247,.35); --theme-subtle:rgba(126,184,247,.07); --bg-deep:#020510; --bg-mid:#060e24; --border:rgba(126,184,247,.13); --text-primary:#ddeeff; --text-secondary:#6a90b8; --text-muted:#2e4a6a; }
|
||||||
|
|
||||||
|
*,*::before,*::after { margin:0; padding:0; box-sizing:border-box; }
|
||||||
|
|
||||||
|
html, body { max-width:100vw; overflow-x:hidden; }
|
||||||
|
body {
|
||||||
|
background:var(--bg-deep); color:var(--text-primary);
|
||||||
|
font-family:'Space Grotesk',sans-serif;
|
||||||
|
display:flex; flex-direction:column; min-height:100vh; overflow-x:hidden;
|
||||||
|
transition:background-color .8s ease, color .3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-animated {
|
||||||
|
position:fixed; inset:0; z-index:-2;
|
||||||
|
background:radial-gradient(ellipse at 20% 10%, var(--bg-mid) 0%, var(--bg-deep) 60%);
|
||||||
|
transition:background 1s ease;
|
||||||
|
}
|
||||||
|
.bg-animated::before, .bg-animated::after {
|
||||||
|
content:''; position:absolute; inset:0;
|
||||||
|
}
|
||||||
|
.bg-animated::before {
|
||||||
|
background-image:
|
||||||
|
radial-gradient(1px 1px at 10% 15%,rgba(255,255,255,.8) 0%,transparent 100%),
|
||||||
|
radial-gradient(1px 1px at 25% 40%,rgba(255,255,255,.5) 0%,transparent 100%),
|
||||||
|
radial-gradient(1.5px 1.5px at 40% 8%,rgba(255,255,255,.9) 0%,transparent 100%),
|
||||||
|
radial-gradient(1px 1px at 55% 60%,rgba(255,255,255,.4) 0%,transparent 100%),
|
||||||
|
radial-gradient(1px 1px at 70% 25%,rgba(255,255,255,.7) 0%,transparent 100%),
|
||||||
|
radial-gradient(1.5px 1.5px at 80% 70%,rgba(255,255,255,.6) 0%,transparent 100%),
|
||||||
|
radial-gradient(1px 1px at 90% 45%,rgba(255,255,255,.5) 0%,transparent 100%),
|
||||||
|
radial-gradient(1px 1px at 15% 80%,rgba(255,255,255,.6) 0%,transparent 100%),
|
||||||
|
radial-gradient(1px 1px at 35% 90%,rgba(255,255,255,.4) 0%,transparent 100%),
|
||||||
|
radial-gradient(1.5px 1.5px at 60% 85%,rgba(255,255,255,.7) 0%,transparent 100%),
|
||||||
|
radial-gradient(1px 1px at 82% 15%,rgba(255,255,255,.8) 0%,transparent 100%),
|
||||||
|
radial-gradient(1px 1px at 5% 55%,rgba(255,255,255,.5) 0%,transparent 100%),
|
||||||
|
radial-gradient(1.5px 1.5px at 92% 88%,rgba(255,255,255,.6) 0%,transparent 100%),
|
||||||
|
radial-gradient(1px 1px at 67% 5%,rgba(255,255,255,.9) 0%,transparent 100%);
|
||||||
|
animation:starTwinkle 8s ease-in-out infinite alternate;
|
||||||
|
}
|
||||||
|
.bg-animated::after {
|
||||||
|
background-image:
|
||||||
|
radial-gradient(1px 1px at 18% 30%,rgba(255,255,255,.6) 0%,transparent 100%),
|
||||||
|
radial-gradient(1px 1px at 33% 65%,rgba(255,255,255,.4) 0%,transparent 100%),
|
||||||
|
radial-gradient(1.5px 1.5px at 48% 22%,rgba(255,255,255,.7) 0%,transparent 100%),
|
||||||
|
radial-gradient(1px 1px at 63% 75%,rgba(255,255,255,.5) 0%,transparent 100%),
|
||||||
|
radial-gradient(1px 1px at 75% 48%,rgba(255,255,255,.8) 0%,transparent 100%),
|
||||||
|
radial-gradient(1px 1px at 88% 30%,rgba(255,255,255,.4) 0%,transparent 100%),
|
||||||
|
radial-gradient(1.5px 1.5px at 12% 68%,rgba(255,255,255,.6) 0%,transparent 100%),
|
||||||
|
radial-gradient(1px 1px at 96% 60%,rgba(255,255,255,.5) 0%,transparent 100%),
|
||||||
|
radial-gradient(1px 1px at 52% 38%,rgba(255,255,255,.3) 0%,transparent 100%);
|
||||||
|
animation:starTwinkle 12s ease-in-out infinite alternate-reverse;
|
||||||
|
}
|
||||||
|
body::before {
|
||||||
|
content:''; position:fixed; inset:0; z-index:-1; pointer-events:none;
|
||||||
|
background:
|
||||||
|
radial-gradient(ellipse 40% 30% at 15% 20%, var(--theme-glow), transparent),
|
||||||
|
radial-gradient(ellipse 25% 35% at 85% 75%, var(--theme-glow), transparent);
|
||||||
|
transition:background 1s ease;
|
||||||
|
}
|
||||||
|
body.theme-sun::before {
|
||||||
|
background:
|
||||||
|
radial-gradient(ellipse 50% 35% at 80% 15%,rgba(255,150,20,.3),transparent),
|
||||||
|
radial-gradient(ellipse 35% 50% at 10% 80%,rgba(255,100,0,.2),transparent);
|
||||||
|
}
|
||||||
|
body.theme-moon::before {
|
||||||
|
background:
|
||||||
|
radial-gradient(ellipse 45% 30% at 85% 10%,rgba(200,207,232,.18),transparent),
|
||||||
|
radial-gradient(ellipse 30% 45% at 5% 90%,rgba(150,160,200,.12),transparent);
|
||||||
|
}
|
||||||
|
@keyframes starTwinkle {
|
||||||
|
0% { opacity:.5; }
|
||||||
|
50% { opacity:1; }
|
||||||
|
100% { opacity:.65; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#safe-area-block {
|
||||||
|
position: sticky; top: 0; z-index: 101;
|
||||||
|
width: 100%;
|
||||||
|
height: env(safe-area-inset-top);
|
||||||
|
background: var(--bg-deep);
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
display:flex; justify-content:space-between; align-items:center;
|
||||||
|
padding:0 2rem;
|
||||||
|
height:64px;
|
||||||
|
background:rgba(2,4,8,.75); backdrop-filter:blur(20px);
|
||||||
|
border-bottom:1px solid var(--border);
|
||||||
|
position:sticky; top:env(safe-area-inset-top); z-index:100;
|
||||||
|
transition:border-color .6s ease;
|
||||||
|
}
|
||||||
|
header::after {
|
||||||
|
content:''; position:absolute; bottom:0; left:0; right:0; height:1px;
|
||||||
|
background:linear-gradient(90deg,transparent,var(--theme-color),transparent);
|
||||||
|
opacity:.6; transition:background .6s ease;
|
||||||
|
}
|
||||||
|
header h1 {
|
||||||
|
font-family:'Orbitron',monospace; font-size:1.1rem; font-weight:700;
|
||||||
|
letter-spacing:.15em; text-transform:uppercase;
|
||||||
|
color:var(--theme-color); text-shadow:0 0 20px var(--theme-glow);
|
||||||
|
transition:color .6s ease, text-shadow .6s ease;
|
||||||
|
}
|
||||||
|
header h1:hover { animation:glitch .4s steps(1) forwards; }
|
||||||
|
|
||||||
|
.menu-icon, .help-btn {
|
||||||
|
cursor:pointer; background:transparent;
|
||||||
|
border:1px solid var(--border); border-radius:6px; padding:.45rem 1rem;
|
||||||
|
color:var(--text-secondary); font-family:'Space Mono',monospace;
|
||||||
|
font-size:.8rem; letter-spacing:.08em;
|
||||||
|
transition:all .2s ease; position:relative; overflow:hidden;
|
||||||
|
}
|
||||||
|
.menu-icon::before, .help-btn::before {
|
||||||
|
content:''; position:absolute; inset:0;
|
||||||
|
background:var(--theme-subtle); opacity:0; transition:opacity .2s ease;
|
||||||
|
}
|
||||||
|
.menu-icon:hover::before, .help-btn:hover::before { opacity:1; }
|
||||||
|
.menu-icon:hover, .help-btn:hover {
|
||||||
|
border-color:var(--theme-color); color:var(--theme-color);
|
||||||
|
box-shadow:0 0 12px var(--theme-glow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar {
|
||||||
|
position:fixed; top:0; left:-300px; width:280px; height:100vh;
|
||||||
|
background:rgba(2,6,14,.96); backdrop-filter:blur(24px);
|
||||||
|
border-right:1px solid var(--border);
|
||||||
|
transition:left .35s cubic-bezier(.4,0,.2,1), border-color .6s ease;
|
||||||
|
z-index:1000; padding-top:5rem; overflow-y:auto;
|
||||||
|
}
|
||||||
|
.sidebar::before {
|
||||||
|
content:'NAVIGATION'; position:absolute; top:1.5rem; left:1.5rem;
|
||||||
|
font-family:'Space Mono',monospace; font-size:.65rem; letter-spacing:.25em;
|
||||||
|
color:var(--text-muted);
|
||||||
|
}
|
||||||
|
.sidebar.open { left:0; }
|
||||||
|
.sidebar ul { list-style:none; }
|
||||||
|
.sidebar li {
|
||||||
|
padding:.9rem 1.75rem; cursor:pointer;
|
||||||
|
font-family:'Orbitron',monospace; font-size:.7rem; font-weight:600;
|
||||||
|
letter-spacing:.12em; text-transform:uppercase; color:var(--text-secondary);
|
||||||
|
transition:all .2s ease; border-left:2px solid transparent; position:relative;
|
||||||
|
}
|
||||||
|
.sidebar li::after {
|
||||||
|
content:'→'; position:absolute; right:1.5rem; top:50%;
|
||||||
|
transform:translateY(-50%) translateX(-4px);
|
||||||
|
opacity:0; transition:all .2s ease; font-family:monospace;
|
||||||
|
}
|
||||||
|
.sidebar li:hover {
|
||||||
|
color:var(--theme-color); border-left-color:var(--theme-color);
|
||||||
|
background:var(--theme-subtle); padding-left:2.25rem;
|
||||||
|
text-shadow:0 0 10px var(--theme-glow);
|
||||||
|
}
|
||||||
|
.sidebar li:hover::after { opacity:1; transform:translateY(-50%) translateX(0); }
|
||||||
|
.sidebar li.menu-category {
|
||||||
|
font-family:'Space Mono',monospace; font-size:.6rem; letter-spacing:.3em;
|
||||||
|
color:var(--text-muted); cursor:default; border-left:none;
|
||||||
|
padding:1.2rem 1.75rem .4rem; pointer-events:none;
|
||||||
|
}
|
||||||
|
.sidebar li.menu-category::after { display:none; }
|
||||||
|
.sidebar li.menu-category:hover { background:none; padding-left:1.75rem; text-shadow:none; color:var(--text-muted); }
|
||||||
|
|
||||||
|
#content-area {
|
||||||
|
flex:1; padding:2.5rem; display:flex;
|
||||||
|
max-width:1400px; margin:0 auto; width:100%;
|
||||||
|
}
|
||||||
|
.layer {
|
||||||
|
display:none; width:100%; flex-direction:column; flex:1; text-align:center;
|
||||||
|
animation:layerReveal .5s cubic-bezier(.4,0,.2,1) both;
|
||||||
|
}
|
||||||
|
.layer.active { display:flex; }
|
||||||
|
|
||||||
|
.main-img {
|
||||||
|
margin-bottom:2.5rem; position:relative;
|
||||||
|
border-radius:12px; overflow:hidden; border:1px solid var(--border);
|
||||||
|
box-shadow:0 20px 60px rgba(0,0,0,.6), 0 0 60px var(--theme-glow);
|
||||||
|
transition:box-shadow .6s ease, border-color .6s ease, transform .4s ease;
|
||||||
|
}
|
||||||
|
.main-img:hover { transform:perspective(1200px) rotateX(1deg) scale(1.005); }
|
||||||
|
.main-img::before {
|
||||||
|
content:''; position:absolute; inset:0; border-radius:12px;
|
||||||
|
box-shadow:inset 0 0 30px rgba(0,0,0,.3); z-index:1; pointer-events:none;
|
||||||
|
}
|
||||||
|
.main-img iframe, .main-img img { width:100%; height:70vh; border:none; display:block; }
|
||||||
|
.main-img img { object-fit:cover; }
|
||||||
|
.sketchfab-embed-wrapper p { font-family:'Space Mono',monospace; font-size:.65rem; color:var(--text-muted); padding:.4rem .75rem; text-align:right; }
|
||||||
|
.sketchfab-embed-wrapper a { color:var(--theme-color); text-decoration:none; }
|
||||||
|
|
||||||
|
.flex-row {
|
||||||
|
display:flex; flex-wrap:wrap; justify-content:center;
|
||||||
|
gap:1.5rem; margin:0 auto 2.5rem; max-width:900px;
|
||||||
|
}
|
||||||
|
.flex-row .box { flex:1; min-width:280px; }
|
||||||
|
.box {
|
||||||
|
padding:1.75rem; background:rgba(255,255,255,.02);
|
||||||
|
border:1px solid var(--border); border-radius:10px;
|
||||||
|
text-align:left; position:relative; overflow:hidden;
|
||||||
|
transition:border-color .3s, box-shadow .3s, transform .3s;
|
||||||
|
}
|
||||||
|
.box::before {
|
||||||
|
content:''; position:absolute; top:0; left:-100%; right:100%; height:2px;
|
||||||
|
background:linear-gradient(90deg,transparent,var(--theme-color),transparent);
|
||||||
|
transition:left .4s ease, right .4s ease;
|
||||||
|
}
|
||||||
|
.box:hover::before { left:0; right:0; }
|
||||||
|
.box:hover { border-color:var(--theme-color); box-shadow:0 8px 30px var(--theme-glow); transform:translateY(-2px); }
|
||||||
|
.box h2 {
|
||||||
|
font-family:'Orbitron',monospace; font-size:.75rem; font-weight:700;
|
||||||
|
letter-spacing:.2em; text-transform:uppercase;
|
||||||
|
color:var(--theme-color); margin-bottom:.85rem; text-shadow:0 0 15px var(--theme-glow);
|
||||||
|
}
|
||||||
|
.box p { line-height:1.7; color:var(--text-secondary); font-size:.9rem; }
|
||||||
|
|
||||||
|
.desc-box {
|
||||||
|
max-width:780px; margin:0 auto 2.5rem; line-height:1.75;
|
||||||
|
color:var(--text-secondary); font-size:.95rem; padding:1.25rem 1.75rem;
|
||||||
|
background:rgba(255,255,255,.02); border:1px solid var(--border); border-radius:8px;
|
||||||
|
border-left:3px solid var(--theme-color); text-align:left;
|
||||||
|
transition:border-color .6s ease;
|
||||||
|
}
|
||||||
|
#layer-home .desc-box {
|
||||||
|
font-family:'Space Mono',monospace; font-size:.85rem;
|
||||||
|
color:var(--theme-color); text-align:center;
|
||||||
|
background:var(--theme-subtle); border:1px solid var(--theme-color);
|
||||||
|
letter-spacing:.05em; opacity:.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ticker-wrap {
|
||||||
|
width:100%; overflow:hidden; padding:.65rem 0; margin-bottom:2.5rem;
|
||||||
|
border-top:1px solid var(--border); border-bottom:1px solid var(--border);
|
||||||
|
position:relative; transition:border-color .6s ease;
|
||||||
|
}
|
||||||
|
.ticker-wrap::before {
|
||||||
|
content:'◈ TELEMETRY'; position:absolute; left:0; top:50%; transform:translateY(-50%);
|
||||||
|
font-family:'Space Mono',monospace; font-size:.6rem; letter-spacing:.2em;
|
||||||
|
color:var(--theme-color); background:var(--bg-deep); padding:0 .75rem; z-index:1;
|
||||||
|
transition:color .6s, background .6s;
|
||||||
|
}
|
||||||
|
.ticker-wrap::after {
|
||||||
|
content:''; position:absolute; right:0; top:0; bottom:0; width:80px;
|
||||||
|
background:linear-gradient(90deg,transparent,var(--bg-deep)); z-index:1;
|
||||||
|
transition:background .6s;
|
||||||
|
}
|
||||||
|
.ticker {
|
||||||
|
display:inline-block; white-space:nowrap;
|
||||||
|
animation:marquee 20s linear infinite;
|
||||||
|
font-family:'Space Mono',monospace; font-size:.75rem;
|
||||||
|
letter-spacing:.08em; color:var(--text-secondary); padding-left:7rem;
|
||||||
|
}
|
||||||
|
.ticker:hover { animation-play-state:paused; }
|
||||||
|
|
||||||
|
.search-bar { margin-bottom:2rem; position:relative; display:flex; justify-content:center; }
|
||||||
|
.search-bar::before {
|
||||||
|
content:'⌕'; position:absolute; left:calc(50% - 210px); top:50%;
|
||||||
|
transform:translateY(-50%); font-size:1.1rem; color:var(--text-muted);
|
||||||
|
pointer-events:none; z-index:1; transition:color .2s;
|
||||||
|
}
|
||||||
|
.search-bar:focus-within::before { color:var(--theme-color); }
|
||||||
|
.search-bar input {
|
||||||
|
width:100%; max-width:460px; padding:.7rem 1.25rem .7rem 2.5rem;
|
||||||
|
background:rgba(255,255,255,.03); border:1px solid var(--border); border-radius:6px;
|
||||||
|
color:var(--text-primary); font-family:'Space Mono',monospace;
|
||||||
|
font-size:.8rem; letter-spacing:.05em; outline:none;
|
||||||
|
transition:border-color .2s, box-shadow .2s, background .2s;
|
||||||
|
}
|
||||||
|
.search-bar input::placeholder { color:var(--text-muted); }
|
||||||
|
.search-bar input:focus {
|
||||||
|
border-color:var(--theme-color); background:var(--theme-subtle);
|
||||||
|
box-shadow:0 0 20px var(--theme-glow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-container { margin-bottom:3rem; }
|
||||||
|
.data-table { width:100%; max-width:1300px; margin:0 auto; border-collapse:collapse; font-size:.88rem; }
|
||||||
|
.data-table thead tr { background:rgba(255,255,255,.03); }
|
||||||
|
.data-table th {
|
||||||
|
padding:.85rem 1.1rem; text-align:center;
|
||||||
|
font-family:'Space Mono',monospace; font-size:.65rem; font-weight:700;
|
||||||
|
letter-spacing:.2em; text-transform:uppercase; color:var(--theme-color);
|
||||||
|
border-bottom:1px solid var(--theme-color); border-right:1px solid var(--border);
|
||||||
|
position:relative; transition:color .6s, border-color .6s;
|
||||||
|
}
|
||||||
|
.data-table th::after {
|
||||||
|
content:''; position:absolute; bottom:-1px; left:0; right:0; height:2px;
|
||||||
|
background:var(--theme-color); transform:scaleX(0); transition:transform .3s;
|
||||||
|
box-shadow:0 0 8px var(--theme-glow);
|
||||||
|
}
|
||||||
|
.data-table th:hover::after { transform:scaleX(1); }
|
||||||
|
.data-table th:last-child, .data-table td:last-child { border-right:none; }
|
||||||
|
.data-table td {
|
||||||
|
padding:.85rem 1.1rem; border-bottom:1px solid var(--border);
|
||||||
|
border-right:1px solid var(--border); color:var(--text-secondary);
|
||||||
|
transition:all .2s ease; vertical-align:middle;
|
||||||
|
}
|
||||||
|
.data-table tbody tr { transition:background .2s; animation:rowFadeIn .4s both; }
|
||||||
|
.data-table tbody tr:nth-child(1) { animation-delay:.05s; }
|
||||||
|
.data-table tbody tr:nth-child(2) { animation-delay:.10s; }
|
||||||
|
.data-table tbody tr:nth-child(3) { animation-delay:.15s; }
|
||||||
|
.data-table tbody tr:nth-child(4) { animation-delay:.20s; }
|
||||||
|
.data-table tbody tr:nth-child(5) { animation-delay:.25s; }
|
||||||
|
.data-table tbody tr:nth-child(6) { animation-delay:.30s; }
|
||||||
|
.data-table tbody tr:nth-child(7) { animation-delay:.35s; }
|
||||||
|
.data-table tbody tr:nth-child(8) { animation-delay:.40s; }
|
||||||
|
.data-table tbody tr:nth-child(9) { animation-delay:.45s; }
|
||||||
|
.data-table tbody tr:nth-child(10) { animation-delay:.50s; }
|
||||||
|
.data-table tbody tr:hover td { background:var(--theme-subtle); color:var(--text-primary); }
|
||||||
|
.data-table tbody tr:hover td:first-child { border-left:2px solid var(--theme-color); padding-left:calc(1.1rem - 2px); }
|
||||||
|
.col-desc { width:40%; min-width:280px; text-align:left !important; font-size:.85rem; line-height:1.55; }
|
||||||
|
.col-url { width:15%; max-width:320px; word-break:break-all; font-family:'Space Mono',monospace; font-size:.72rem; }
|
||||||
|
.col-url a { color:var(--theme-color) !important; text-decoration:none !important; opacity:.85; transition:opacity .2s, text-shadow .2s; }
|
||||||
|
.col-url a:hover { opacity:1; text-shadow:0 0 10px var(--theme-glow); text-decoration:underline !important; }
|
||||||
|
.hidden-row { display:none !important; }
|
||||||
|
|
||||||
|
.show-more-btn {
|
||||||
|
display:inline-flex; align-items:center; gap:.5rem;
|
||||||
|
margin:1.5rem auto 0; padding:.6rem 1.75rem;
|
||||||
|
background:transparent; color:var(--theme-color);
|
||||||
|
border:1px solid var(--theme-color); border-radius:4px; cursor:pointer;
|
||||||
|
font-family:'Space Mono',monospace; font-size:.75rem;
|
||||||
|
letter-spacing:.15em; text-transform:uppercase;
|
||||||
|
position:relative; overflow:hidden; transition:all .25s ease;
|
||||||
|
}
|
||||||
|
.show-more-btn::before {
|
||||||
|
content:''; position:absolute; inset:0;
|
||||||
|
background:var(--theme-subtle); transform:scaleX(0); transform-origin:left; transition:transform .3s;
|
||||||
|
}
|
||||||
|
.show-more-btn:hover::before { transform:scaleX(1); }
|
||||||
|
.show-more-btn:hover { box-shadow:0 0 24px var(--theme-glow); transform:translateY(1px); }
|
||||||
|
|
||||||
|
.site-footer {
|
||||||
|
text-align:center; padding:1.25rem 2rem;
|
||||||
|
background:rgba(2,4,8,.7); backdrop-filter:blur(10px);
|
||||||
|
color:var(--text-muted); font-family:'Space Mono',monospace;
|
||||||
|
font-size:.7rem; letter-spacing:.15em;
|
||||||
|
border-top:1px solid var(--border);
|
||||||
|
cursor:pointer; user-select:none;
|
||||||
|
transition:border-color .6s, background .2s;
|
||||||
|
}
|
||||||
|
.site-footer::before { content:'◈ '; color:var(--theme-color); transition:color .6s; }
|
||||||
|
.site-footer:hover { background:rgba(255,255,255,.03); }
|
||||||
|
.footer-credits-hint { opacity:.5; font-style:italic; transition:opacity .2s; }
|
||||||
|
.site-footer:hover .footer-credits-hint { opacity:1; color:var(--theme-color); }
|
||||||
|
|
||||||
|
.daily-challenge-box {
|
||||||
|
margin:0 auto 2rem; max-width:680px; padding:1rem 1.5rem;
|
||||||
|
background:var(--theme-subtle); border:1px solid var(--border);
|
||||||
|
border-left:3px solid var(--theme-color); border-radius:8px; text-align:left;
|
||||||
|
}
|
||||||
|
.daily-challenge-title {
|
||||||
|
display:block; font-family:'Orbitron',monospace; font-size:.7rem; font-weight:700;
|
||||||
|
letter-spacing:.25em; text-transform:uppercase;
|
||||||
|
color:var(--theme-color); text-shadow:0 0 12px var(--theme-glow); margin-bottom:.5rem;
|
||||||
|
}
|
||||||
|
.daily-challenge-desc { font-size:.85rem; line-height:1.6; color:var(--text-secondary); }
|
||||||
|
|
||||||
|
#quiz-container {
|
||||||
|
margin:0 auto 3rem; max-width:680px; padding:2.25rem 2.5rem;
|
||||||
|
background:rgba(255,255,255,.02); border:1px solid var(--border); border-radius:12px;
|
||||||
|
text-align:center; position:relative; overflow:hidden;
|
||||||
|
box-shadow:0 0 40px var(--theme-glow), inset 0 0 60px rgba(0,0,0,.3);
|
||||||
|
display:flex; flex-direction:column; min-height:400px;
|
||||||
|
}
|
||||||
|
#quiz-container::before {
|
||||||
|
content:''; position:absolute; top:0; left:0; right:0; height:2px;
|
||||||
|
background:linear-gradient(90deg,transparent,var(--theme-color),transparent);
|
||||||
|
}
|
||||||
|
#quiz-question {
|
||||||
|
font-size:.95rem; font-weight:500; line-height:1.6;
|
||||||
|
color:var(--text-primary); margin-bottom:1.5rem;
|
||||||
|
white-space:pre-line; text-align:left; flex-grow:1;
|
||||||
|
display:flex; align-items:center; min-height:120px;
|
||||||
|
}
|
||||||
|
#quiz-options { display:grid; grid-template-columns:1fr 1fr; gap:.75rem; margin-bottom:1rem; width:100%; }
|
||||||
|
|
||||||
|
.quiz-btn {
|
||||||
|
background:rgba(255,255,255,.03); color:var(--text-primary);
|
||||||
|
border:1px solid var(--border); border-radius:8px; padding:.9rem 1.1rem;
|
||||||
|
font-family:'Space Grotesk',sans-serif; font-size:.9rem; font-weight:500;
|
||||||
|
cursor:pointer; text-align:left; position:relative; overflow:hidden;
|
||||||
|
transition:all .2s ease;
|
||||||
|
display:flex; align-items:center; min-height:54px;
|
||||||
|
}
|
||||||
|
.quiz-btn::before {
|
||||||
|
content:''; position:absolute; inset:0;
|
||||||
|
background:var(--theme-subtle); opacity:0; transition:opacity .2s;
|
||||||
|
}
|
||||||
|
.quiz-btn:hover:not(:disabled) {
|
||||||
|
border-color:var(--theme-color); box-shadow:0 0 16px var(--theme-glow); transform:translateY(-1px);
|
||||||
|
}
|
||||||
|
.quiz-btn:hover:not(:disabled)::before { opacity:1; }
|
||||||
|
.quiz-btn.correct {
|
||||||
|
background:rgba(74,222,128,.15) !important; border-color:#4ade80 !important;
|
||||||
|
color:#86efac !important; box-shadow:0 0 20px rgba(74,222,128,.3) !important;
|
||||||
|
animation:correctPulse .35s ease forwards;
|
||||||
|
}
|
||||||
|
.quiz-btn.correct::after { content:'✓'; position:absolute; right:1rem; top:50%; transform:translateY(-50%); color:#4ade80; pointer-events:none; }
|
||||||
|
.quiz-btn.wrong {
|
||||||
|
background:rgba(248,113,113,.15) !important; border-color:#f87171 !important;
|
||||||
|
color:#fca5a5 !important; box-shadow:0 0 20px rgba(248,113,113,.25) !important;
|
||||||
|
animation:shake .3s ease forwards;
|
||||||
|
}
|
||||||
|
.quiz-btn.wrong::after { content:'✗'; position:absolute; right:1rem; top:50%; transform:translateY(-50%); color:#f87171; pointer-events:none; }
|
||||||
|
|
||||||
|
#quiz-score {
|
||||||
|
margin-top:1.5rem; font-family:'Orbitron',monospace; font-size:1.1rem; font-weight:700;
|
||||||
|
letter-spacing:.1em; color:var(--theme-color); text-shadow:0 0 20px var(--theme-glow);
|
||||||
|
}
|
||||||
|
#quiz-restart-btn {
|
||||||
|
display:none; margin-top:1.25rem; padding:.65rem 2rem;
|
||||||
|
background:transparent; color:var(--theme-color);
|
||||||
|
border:1px solid var(--theme-color); border-radius:6px; cursor:pointer;
|
||||||
|
font-family:'Space Mono',monospace; font-size:.75rem;
|
||||||
|
letter-spacing:.15em; text-transform:uppercase; transition:all .25s;
|
||||||
|
}
|
||||||
|
#quiz-restart-btn:hover { background:var(--theme-subtle); box-shadow:0 0 20px var(--theme-glow); transform:translateY(-1px); }
|
||||||
|
|
||||||
|
#quiz-img-preview {
|
||||||
|
max-width:640px; margin:1.5rem auto 0;
|
||||||
|
border:1px solid var(--border); border-radius:10px; overflow:hidden;
|
||||||
|
background:rgba(0,0,0,.3); opacity:0; max-height:0; text-align:left;
|
||||||
|
transition:opacity .5s, max-height .5s, border-color .6s;
|
||||||
|
}
|
||||||
|
#quiz-img-preview.visible { opacity:1; max-height:480px; }
|
||||||
|
.quiz-img-label {
|
||||||
|
padding:.5rem 1rem; font-family:'Space Mono',monospace; font-size:.6rem;
|
||||||
|
letter-spacing:.2em; color:var(--theme-color);
|
||||||
|
border-bottom:1px solid var(--border); background:rgba(255,255,255,.02);
|
||||||
|
}
|
||||||
|
#quiz-img-preview img, #quiz-img-preview video {
|
||||||
|
display:block; width:100%; max-height:320px; background:#000;
|
||||||
|
}
|
||||||
|
#quiz-img-preview img { object-fit:contain; }
|
||||||
|
#quiz-img-preview video { outline:none; }
|
||||||
|
#quiz-img-preview img[src=""], #quiz-img-preview video[src=""] { display:none; }
|
||||||
|
.quiz-img-caption {
|
||||||
|
padding:.5rem 1rem; font-family:'Space Mono',monospace; font-size:.65rem;
|
||||||
|
color:var(--text-muted); word-break:break-all; border-top:1px solid var(--border);
|
||||||
|
white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
#credits-overlay {
|
||||||
|
position:fixed; inset:0; z-index:2000;
|
||||||
|
background:rgba(0,0,0,.7); backdrop-filter:blur(6px);
|
||||||
|
opacity:0; pointer-events:none; transition:opacity .35s;
|
||||||
|
}
|
||||||
|
#credits-overlay.open { opacity:1; pointer-events:all; }
|
||||||
|
|
||||||
|
#credits-panel {
|
||||||
|
position:fixed; top:0; right:-480px; z-index:2001;
|
||||||
|
width:min(460px,95vw); height:100vh;
|
||||||
|
background:rgba(4,8,18,.97); backdrop-filter:blur(24px);
|
||||||
|
border-left:1px solid var(--border);
|
||||||
|
display:flex; flex-direction:column;
|
||||||
|
transition:right .4s cubic-bezier(.4,0,.2,1), border-color .6s;
|
||||||
|
overflow:hidden;
|
||||||
|
}
|
||||||
|
#credits-panel::before {
|
||||||
|
content:''; position:absolute; top:0; left:0; bottom:0; width:2px;
|
||||||
|
background:linear-gradient(180deg,transparent,var(--theme-color),transparent);
|
||||||
|
opacity:.6;
|
||||||
|
}
|
||||||
|
#credits-panel.open { right:0; }
|
||||||
|
|
||||||
|
.credits-close {
|
||||||
|
position:absolute; top:1rem; right:1rem;
|
||||||
|
background:transparent; border:1px solid var(--border); border-radius:6px;
|
||||||
|
color:var(--text-muted); width:32px; height:32px; font-size:.8rem; cursor:pointer;
|
||||||
|
display:flex; align-items:center; justify-content:center;
|
||||||
|
transition:all .2s; z-index:1;
|
||||||
|
}
|
||||||
|
.credits-close:hover { border-color:var(--theme-color); color:var(--theme-color); box-shadow:0 0 10px var(--theme-glow); }
|
||||||
|
|
||||||
|
.credits-header { padding:2.5rem 2rem 1.5rem; border-bottom:1px solid var(--border); flex-shrink:0; }
|
||||||
|
.credits-tag {
|
||||||
|
display:block; font-family:'Space Mono',monospace; font-size:.6rem;
|
||||||
|
letter-spacing:.25em; color:var(--theme-color); margin-bottom:.75rem;
|
||||||
|
text-shadow:0 0 10px var(--theme-glow);
|
||||||
|
}
|
||||||
|
.credits-title {
|
||||||
|
font-family:'Orbitron',monospace; font-size:1.4rem; font-weight:900;
|
||||||
|
letter-spacing:.1em; color:var(--text-primary);
|
||||||
|
text-shadow:0 0 30px var(--theme-glow); margin-bottom:.25rem;
|
||||||
|
}
|
||||||
|
.credits-version { font-family:'Space Mono',monospace; font-size:.7rem; color:var(--text-muted); letter-spacing:.1em; }
|
||||||
|
|
||||||
|
.credits-body { flex:1; overflow-y:auto; padding:1.5rem 2rem; scrollbar-width:thin; scrollbar-color:var(--theme-color) transparent; }
|
||||||
|
.credits-section { margin-bottom:2rem; }
|
||||||
|
.credits-section h3 {
|
||||||
|
font-family:'Space Mono',monospace; font-size:.65rem; font-weight:700;
|
||||||
|
letter-spacing:.2em; text-transform:uppercase; color:var(--theme-color);
|
||||||
|
margin-bottom:.75rem; padding-bottom:.4rem; border-bottom:1px solid var(--border);
|
||||||
|
}
|
||||||
|
.credits-section p { font-size:.88rem; line-height:1.7; color:var(--text-secondary); }
|
||||||
|
.credits-section ul { list-style:none; display:flex; flex-direction:column; gap:.4rem; }
|
||||||
|
.credits-section ul li {
|
||||||
|
font-size:.85rem; color:var(--text-secondary); padding:.35rem .6rem;
|
||||||
|
border-left:1px solid var(--border); transition:border-color .2s, background .2s;
|
||||||
|
}
|
||||||
|
.credits-section ul li:hover { border-left-color:var(--theme-color); background:var(--theme-subtle); }
|
||||||
|
.credits-section ul li span { font-family:'Space Mono',monospace; font-size:.75rem; color:var(--theme-color); margin-right:.5rem; text-shadow:0 0 8px var(--theme-glow); }
|
||||||
|
|
||||||
|
.credits-footer { padding:1rem 2rem; border-top:1px solid var(--border); font-family:'Space Mono',monospace; font-size:.62rem; letter-spacing:.15em; color:var(--text-muted); flex-shrink:0; }
|
||||||
|
|
||||||
|
::-webkit-scrollbar { width:6px; }
|
||||||
|
::-webkit-scrollbar-track { background:var(--bg-deep); }
|
||||||
|
::-webkit-scrollbar-thumb { background:var(--theme-color); border-radius:3px; }
|
||||||
|
::selection { background:var(--theme-glow); color:#fff; }
|
||||||
|
|
||||||
|
@keyframes layerReveal {
|
||||||
|
from { opacity:0; transform:translateY(16px); filter:blur(4px); }
|
||||||
|
to { opacity:1; transform:translateY(0); filter:blur(0); }
|
||||||
|
}
|
||||||
|
@keyframes rowFadeIn {
|
||||||
|
from { opacity:0; transform:translateX(-8px); }
|
||||||
|
to { opacity:1; transform:translateX(0); }
|
||||||
|
}
|
||||||
|
@keyframes marquee {
|
||||||
|
from { transform:translateX(100vw); }
|
||||||
|
to { transform:translateX(-100%); }
|
||||||
|
}
|
||||||
|
@keyframes glitch {
|
||||||
|
0%,30%,50%,100% { text-shadow:0 0 20px var(--theme-glow); transform:translate(0); }
|
||||||
|
10% { text-shadow:-2px 0 var(--theme-color),2px 0 rgba(255,0,100,.6); transform:translate(-1px,0); }
|
||||||
|
20% { text-shadow:2px 0 var(--theme-color),-2px 0 rgba(0,200,255,.6); transform:translate(1px,0); }
|
||||||
|
40% { text-shadow:-3px 0 rgba(255,0,100,.5),3px 0 var(--theme-color); transform:translate(2px,-1px); }
|
||||||
|
60% { text-shadow:2px 0 rgba(0,200,255,.6),-1px 0 var(--theme-color); transform:translate(-1px,1px); }
|
||||||
|
}
|
||||||
|
@keyframes correctPulse {
|
||||||
|
0%,100% { transform:scale(1); }
|
||||||
|
40% { transform:scale(1.025); }
|
||||||
|
}
|
||||||
|
@keyframes shake {
|
||||||
|
0%,100% { transform:translateX(0); }
|
||||||
|
25% { transform:translateX(-5px); }
|
||||||
|
50% { transform:translateX(5px); }
|
||||||
|
75% { transform:translateX(-3px); }
|
||||||
|
}
|
||||||
|
@media (max-width:768px) {
|
||||||
|
#layer-Quiz .desc-box, #layer-Quiz .daily-challenge-box { display:none; }
|
||||||
|
}
|
||||||
|
@media (max-width:520px) {
|
||||||
|
header { padding:0 1rem; }
|
||||||
|
header h1 { font-size:.85rem; letter-spacing:.05em; text-align:center; }
|
||||||
|
.menu-icon, .help-btn { padding:.4rem .6rem; font-size:.7rem; }
|
||||||
|
#content-area { padding:1.5rem 1rem; }
|
||||||
|
.flex-row .box { min-width:100%; }
|
||||||
|
.desc-box { padding:1.25rem 1rem; font-size:.85rem; }
|
||||||
|
#quiz-options { grid-template-columns:1fr; gap:0.6rem; }
|
||||||
|
#quiz-container { padding:1.25rem 1rem; height:auto; min-height:auto; justify-content:center; overflow:visible; margin-bottom:1rem; }
|
||||||
|
#quiz-question { min-height:auto; font-size:.88rem; align-items:center; justify-content:center; text-align:center; margin-top:0; margin-bottom:1rem; }
|
||||||
|
.quiz-btn { min-height:44px; font-size:.8rem; padding:.6rem .75rem; justify-content:center; text-align:center; }
|
||||||
|
#quiz-img-preview.visible { max-height:none; margin-bottom:1rem; text-align:center; }
|
||||||
|
#quiz-img-preview img, #quiz-img-preview video { max-height:160px; width:auto; max-width:100%; margin:0 auto; }
|
||||||
|
}
|
||||||
|
|
||||||
|
body.page-form { background-color: #0f172a; color: #e0e0e0; display: flex; flex-direction: row; justify-content: center; align-items: center; padding: 2rem; min-height: 100vh; overflow-x: auto; }
|
||||||
|
.admin-box { background-color: #1e293b; padding: 2rem; border-radius: 8px; box-shadow: 0 4px 15px rgba(0,0,0,0.5); width: 100%; max-width: 500px; border: 1px solid #334155; }
|
||||||
|
.admin-box h1 { color: #00bfff; text-align: center; margin-bottom: 1.5rem; }
|
||||||
|
.form-group { margin-bottom: 1rem; }
|
||||||
|
.form-group label { display: block; margin-bottom: 0.5rem; color: #b9bbbe; font-size: 0.9rem; }
|
||||||
|
.form-group input, .form-group select, .form-group textarea { width: 100%; padding: 0.75rem; background: #0f172a; border: 1px solid #334155; border-radius: 4px; color: white; font-family: inherit; }
|
||||||
|
.btn-submit { width: 100%; padding: 0.75rem; background-color: #00bfff; color: white; border: none; border-radius: 4px; font-weight: 600; cursor: pointer; margin-top: 1rem; transition: background 0.2s; }
|
||||||
|
.btn-submit:hover { background-color: #009acd; }
|
||||||
|
.links { text-align: center; margin-top: 1.5rem; display: flex; flex-direction: column; gap: 0.5rem; }
|
||||||
|
.links a { color: #94a3b8; text-decoration: none; font-size: 0.9rem; transition: color 0.2s; }
|
||||||
|
.links a:hover { color: #ffffff; }
|
||||||
|
input[type="file"] { cursor: pointer; padding: 0.6rem; }
|
||||||
|
input[type="file"]::file-selector-button { background: #334155; color: white; border: none; padding: 0.5rem 1rem; border-radius: 4px; cursor: pointer; margin-right: 1rem; transition: background 0.2s; }
|
||||||
|
input[type="file"]::file-selector-button:hover { background: #475569; }
|
||||||
|
|
||||||
|
/* Correction absolue pour App Mobile Native (Capacitor) */
|
||||||
|
body.is-mobile-app #safe-area-block { height: max(env(safe-area-inset-top), 45px); }
|
||||||
|
body.is-mobile-app header { top: max(env(safe-area-inset-top), 45px); }
|
||||||
|
body.is-mobile-app .sidebar { padding-top: calc(5rem + max(env(safe-area-inset-top), 45px)); }
|
||||||
|
body.is-mobile-app .sidebar::before { top: calc(1.5rem + max(env(safe-area-inset-top), 45px)); }
|
||||||
|
body.is-mobile-app .credits-close { top: calc(1rem + max(env(safe-area-inset-top), 45px)); }
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
# Using Android gitignore template: https://github.com/github/gitignore/blob/HEAD/Android.gitignore
|
||||||
|
|
||||||
|
# Built application files
|
||||||
|
*.apk
|
||||||
|
*.aar
|
||||||
|
*.ap_
|
||||||
|
*.aab
|
||||||
|
|
||||||
|
# Files for the ART/Dalvik VM
|
||||||
|
*.dex
|
||||||
|
|
||||||
|
# Java class files
|
||||||
|
*.class
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
bin/
|
||||||
|
gen/
|
||||||
|
out/
|
||||||
|
# Uncomment the following line in case you need and you don't have the release build type files in your app
|
||||||
|
# release/
|
||||||
|
|
||||||
|
# Gradle files
|
||||||
|
.gradle/
|
||||||
|
build/
|
||||||
|
|
||||||
|
# Local configuration file (sdk path, etc)
|
||||||
|
local.properties
|
||||||
|
|
||||||
|
# Proguard folder generated by Eclipse
|
||||||
|
proguard/
|
||||||
|
|
||||||
|
# Log Files
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Android Studio Navigation editor temp files
|
||||||
|
.navigation/
|
||||||
|
|
||||||
|
# Android Studio captures folder
|
||||||
|
captures/
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
*.iml
|
||||||
|
.idea/workspace.xml
|
||||||
|
.idea/tasks.xml
|
||||||
|
.idea/gradle.xml
|
||||||
|
.idea/assetWizardSettings.xml
|
||||||
|
.idea/dictionaries
|
||||||
|
.idea/libraries
|
||||||
|
# Android Studio 3 in .gitignore file.
|
||||||
|
.idea/caches
|
||||||
|
.idea/modules.xml
|
||||||
|
# Comment next line if keeping position of elements in Navigation Editor is relevant for you
|
||||||
|
.idea/navEditor.xml
|
||||||
|
|
||||||
|
# Keystore files
|
||||||
|
# Uncomment the following lines if you do not want to check your keystore files in.
|
||||||
|
#*.jks
|
||||||
|
#*.keystore
|
||||||
|
|
||||||
|
# External native build folder generated in Android Studio 2.2 and later
|
||||||
|
.externalNativeBuild
|
||||||
|
.cxx/
|
||||||
|
|
||||||
|
# Google Services (e.g. APIs or Firebase)
|
||||||
|
# google-services.json
|
||||||
|
|
||||||
|
# Freeline
|
||||||
|
freeline.py
|
||||||
|
freeline/
|
||||||
|
freeline_project_description.json
|
||||||
|
|
||||||
|
# fastlane
|
||||||
|
fastlane/report.xml
|
||||||
|
fastlane/Preview.html
|
||||||
|
fastlane/screenshots
|
||||||
|
fastlane/test_output
|
||||||
|
fastlane/readme.md
|
||||||
|
|
||||||
|
# Version control
|
||||||
|
vcs.xml
|
||||||
|
|
||||||
|
# lint
|
||||||
|
lint/intermediates/
|
||||||
|
lint/generated/
|
||||||
|
lint/outputs/
|
||||||
|
lint/tmp/
|
||||||
|
# lint/reports/
|
||||||
|
|
||||||
|
# Android Profiling
|
||||||
|
*.hprof
|
||||||
|
|
||||||
|
# Cordova plugins for Capacitor
|
||||||
|
capacitor-cordova-android-plugins
|
||||||
|
|
||||||
|
# Copied web assets
|
||||||
|
app/src/main/assets/public
|
||||||
|
|
||||||
|
# Generated Config files
|
||||||
|
app/src/main/assets/capacitor.config.json
|
||||||
|
app/src/main/assets/capacitor.plugins.json
|
||||||
|
app/src/main/res/xml/config.xml
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
/build/*
|
||||||
|
!/build/.npmkeep
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
apply plugin: 'com.android.application'
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "com.openplanetsmaps.app"
|
||||||
|
compileSdk = rootProject.ext.compileSdkVersion
|
||||||
|
defaultConfig {
|
||||||
|
applicationId "com.openplanetsmaps.app"
|
||||||
|
minSdkVersion rootProject.ext.minSdkVersion
|
||||||
|
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||||
|
versionCode 1
|
||||||
|
versionName "1.0"
|
||||||
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
aaptOptions {
|
||||||
|
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
|
||||||
|
// Default: https://android.googlesource.com/platform/frameworks/base/+/282e181b58cf72b6ca770dc7ca5f91f135444502/tools/aapt/AaptAssets.cpp#61
|
||||||
|
ignoreAssetsPattern = '!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
minifyEnabled false
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
flatDir{
|
||||||
|
dirs '../capacitor-cordova-android-plugins/src/main/libs', 'libs'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||||
|
implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
|
||||||
|
implementation "androidx.coordinatorlayout:coordinatorlayout:$androidxCoordinatorLayoutVersion"
|
||||||
|
implementation "androidx.core:core-splashscreen:$coreSplashScreenVersion"
|
||||||
|
implementation project(':capacitor-android')
|
||||||
|
testImplementation "junit:junit:$junitVersion"
|
||||||
|
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
|
||||||
|
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
|
||||||
|
implementation project(':capacitor-cordova-android-plugins')
|
||||||
|
}
|
||||||
|
|
||||||
|
apply from: 'capacitor.build.gradle'
|
||||||
|
|
||||||
|
try {
|
||||||
|
def servicesJSON = file('google-services.json')
|
||||||
|
if (servicesJSON.text) {
|
||||||
|
apply plugin: 'com.google.gms.google-services'
|
||||||
|
}
|
||||||
|
} catch(Exception e) {
|
||||||
|
logger.info("google-services.json not found, google-services plugin not applied. Push Notifications won't work")
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_21
|
||||||
|
targetCompatibility JavaVersion.VERSION_21
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle"
|
||||||
|
dependencies {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (hasProperty('postBuildExtras')) {
|
||||||
|
postBuildExtras()
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# You can control the set of applied configuration files using the
|
||||||
|
# proguardFiles setting in build.gradle.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following
|
||||||
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
|
# class:
|
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
|
# public *;
|
||||||
|
#}
|
||||||
|
|
||||||
|
# Uncomment this to preserve the line number information for
|
||||||
|
# debugging stack traces.
|
||||||
|
#-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
||||||
|
# If you keep the line number information, uncomment this to
|
||||||
|
# hide the original source file name.
|
||||||
|
#-renamesourcefileattribute SourceFile
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package com.getcapacitor.myapp;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
import androidx.test.platform.app.InstrumentationRegistry;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instrumented test, which will execute on an Android device.
|
||||||
|
*
|
||||||
|
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||||
|
*/
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
public class ExampleInstrumentedTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void useAppContext() throws Exception {
|
||||||
|
// Context of the app under test.
|
||||||
|
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
|
||||||
|
|
||||||
|
assertEquals("com.getcapacitor.app", appContext.getPackageName());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:allowBackup="true"
|
||||||
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
|
android:supportsRtl="true"
|
||||||
|
android:theme="@style/AppTheme">
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode|navigation|density"
|
||||||
|
android:name=".MainActivity"
|
||||||
|
android:label="@string/title_activity_main"
|
||||||
|
android:theme="@style/AppTheme.NoActionBarLaunch"
|
||||||
|
android:launchMode="singleTask"
|
||||||
|
android:exported="true">
|
||||||
|
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
</activity>
|
||||||
|
|
||||||
|
<provider
|
||||||
|
android:name="androidx.core.content.FileProvider"
|
||||||
|
android:authorities="${applicationId}.fileprovider"
|
||||||
|
android:exported="false"
|
||||||
|
android:grantUriPermissions="true">
|
||||||
|
<meta-data
|
||||||
|
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||||
|
android:resource="@xml/file_paths"></meta-data>
|
||||||
|
</provider>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
<!-- Permissions -->
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
</manifest>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package com.openplanetsmaps.app;
|
||||||
|
|
||||||
|
import com.getcapacitor.BridgeActivity;
|
||||||
|
|
||||||
|
public class MainActivity extends BridgeActivity {}
|
||||||
|
After Width: | Height: | Size: 7.5 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 7.7 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 9.6 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 17 KiB |
@@ -0,0 +1,34 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:aapt="http://schemas.android.com/aapt"
|
||||||
|
android:width="108dp"
|
||||||
|
android:height="108dp"
|
||||||
|
android:viewportHeight="108"
|
||||||
|
android:viewportWidth="108">
|
||||||
|
<path
|
||||||
|
android:fillType="evenOdd"
|
||||||
|
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
|
||||||
|
android:strokeColor="#00000000"
|
||||||
|
android:strokeWidth="1">
|
||||||
|
<aapt:attr name="android:fillColor">
|
||||||
|
<gradient
|
||||||
|
android:endX="78.5885"
|
||||||
|
android:endY="90.9159"
|
||||||
|
android:startX="48.7653"
|
||||||
|
android:startY="61.0927"
|
||||||
|
android:type="linear">
|
||||||
|
<item
|
||||||
|
android:color="#44000000"
|
||||||
|
android:offset="0.0" />
|
||||||
|
<item
|
||||||
|
android:color="#00000000"
|
||||||
|
android:offset="1.0" />
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFF"
|
||||||
|
android:fillType="nonZero"
|
||||||
|
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
|
||||||
|
android:strokeColor="#00000000"
|
||||||
|
android:strokeWidth="1" />
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,170 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="108dp"
|
||||||
|
android:height="108dp"
|
||||||
|
android:viewportHeight="108"
|
||||||
|
android:viewportWidth="108">
|
||||||
|
<path
|
||||||
|
android:fillColor="#26A69A"
|
||||||
|
android:pathData="M0,0h108v108h-108z" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M9,0L9,108"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,0L19,108"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M29,0L29,108"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M39,0L39,108"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M49,0L49,108"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M59,0L59,108"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M69,0L69,108"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M79,0L79,108"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M89,0L89,108"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M99,0L99,108"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,9L108,9"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,19L108,19"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,29L108,29"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,39L108,39"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,49L108,49"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,59L108,59"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,69L108,69"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,79L108,79"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,89L108,89"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,99L108,99"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,29L89,29"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,39L89,39"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,49L89,49"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,59L89,59"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,69L89,69"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,79L89,79"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M29,19L29,89"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M39,19L39,89"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M49,19L49,89"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M59,19L59,89"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M69,19L69,89"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M79,19L79,89"
|
||||||
|
android:strokeColor="#33FFFFFF"
|
||||||
|
android:strokeWidth="0.8" />
|
||||||
|
</vector>
|
||||||
|
After Width: | Height: | Size: 3.9 KiB |
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".MainActivity">
|
||||||
|
|
||||||
|
<WebView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/ic_launcher_background"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/ic_launcher_background"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
||||||
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 6.4 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 9.6 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 9.2 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 16 KiB |
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<color name="ic_launcher_background">#FFFFFF</color>
|
||||||
|
</resources>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<resources>
|
||||||
|
<string name="app_name">OpenPlanetsMaps</string>
|
||||||
|
<string name="title_activity_main">OpenPlanetsMaps</string>
|
||||||
|
<string name="package_name">com.openplanetsmaps.app</string>
|
||||||
|
<string name="custom_url_scheme">com.openplanetsmaps.app</string>
|
||||||
|
</resources>
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<!-- Base application theme. -->
|
||||||
|
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||||
|
<!-- Customize your theme here. -->
|
||||||
|
<item name="colorPrimary">@color/colorPrimary</item>
|
||||||
|
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||||
|
<item name="colorAccent">@color/colorAccent</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="AppTheme.NoActionBar" parent="Theme.AppCompat.DayNight.NoActionBar">
|
||||||
|
<item name="windowActionBar">false</item>
|
||||||
|
<item name="windowNoTitle">true</item>
|
||||||
|
<item name="android:background">@null</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
<style name="AppTheme.NoActionBarLaunch" parent="Theme.SplashScreen">
|
||||||
|
<item name="android:background">@drawable/splash</item>
|
||||||
|
</style>
|
||||||
|
</resources>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<paths xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<external-path name="my_images" path="." />
|
||||||
|
<cache-path name="my_cache_images" path="." />
|
||||||
|
</paths>
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.getcapacitor.myapp;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Example local unit test, which will execute on the development machine (host).
|
||||||
|
*
|
||||||
|
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||||
|
*/
|
||||||
|
public class ExampleUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void addition_isCorrect() throws Exception {
|
||||||
|
assertEquals(4, 2 + 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
|
|
||||||
|
buildscript {
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath 'com.android.tools.build:gradle:8.13.0'
|
||||||
|
classpath 'com.google.gms:google-services:4.4.4'
|
||||||
|
|
||||||
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
|
// in the individual module build.gradle files
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apply from: "variables.gradle"
|
||||||
|
|
||||||
|
allprojects {
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task clean(type: Delete) {
|
||||||
|
delete rootProject.buildDir
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN
|
||||||
|
include ':capacitor-android'
|
||||||
|
project(':capacitor-android').projectDir = new File('../node_modules/@capacitor/android/capacitor')
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
# Project-wide Gradle settings.
|
||||||
|
|
||||||
|
# IDE (e.g. Android Studio) users:
|
||||||
|
# Gradle settings configured through the IDE *will override*
|
||||||
|
# any settings specified in this file.
|
||||||
|
|
||||||
|
# For more details on how to configure your build environment visit
|
||||||
|
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||||
|
|
||||||
|
# Specifies the JVM arguments used for the daemon process.
|
||||||
|
# The setting is particularly useful for tweaking memory settings.
|
||||||
|
org.gradle.jvmargs=-Xmx1536m
|
||||||
|
|
||||||
|
# When configured, Gradle will run in incubating parallel mode.
|
||||||
|
# This option should only be used with decoupled projects. More details, visit
|
||||||
|
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||||
|
# org.gradle.parallel=true
|
||||||
|
|
||||||
|
# AndroidX package structure to make it clearer which packages are bundled with the
|
||||||
|
# Android operating system, and which are packaged with your app's APK
|
||||||
|
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
||||||
|
android.useAndroidX=true
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-all.zip
|
||||||
|
networkTimeout=10000
|
||||||
|
validateDistributionUrl=true
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
||||||
@@ -0,0 +1,251 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright © 2015-2021 the original authors.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
#
|
||||||
|
# Gradle start up script for POSIX generated by Gradle.
|
||||||
|
#
|
||||||
|
# Important for running:
|
||||||
|
#
|
||||||
|
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||||
|
# noncompliant, but you have some other compliant shell such as ksh or
|
||||||
|
# bash, then to run this script, type that shell name before the whole
|
||||||
|
# command line, like:
|
||||||
|
#
|
||||||
|
# ksh Gradle
|
||||||
|
#
|
||||||
|
# Busybox and similar reduced shells will NOT work, because this script
|
||||||
|
# requires all of these POSIX shell features:
|
||||||
|
# * functions;
|
||||||
|
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||||
|
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||||
|
# * compound commands having a testable exit status, especially «case»;
|
||||||
|
# * various built-in commands including «command», «set», and «ulimit».
|
||||||
|
#
|
||||||
|
# Important for patching:
|
||||||
|
#
|
||||||
|
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||||
|
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||||
|
#
|
||||||
|
# The "traditional" practice of packing multiple parameters into a
|
||||||
|
# space-separated string is a well documented source of bugs and security
|
||||||
|
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||||
|
# options in "$@", and eventually passing that to Java.
|
||||||
|
#
|
||||||
|
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||||
|
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||||
|
# see the in-line comments for details.
|
||||||
|
#
|
||||||
|
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||||
|
# Darwin, MinGW, and NonStop.
|
||||||
|
#
|
||||||
|
# (3) This script is generated from the Groovy template
|
||||||
|
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||||
|
# within the Gradle project.
|
||||||
|
#
|
||||||
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
|
#
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Attempt to set APP_HOME
|
||||||
|
|
||||||
|
# Resolve links: $0 may be a link
|
||||||
|
app_path=$0
|
||||||
|
|
||||||
|
# Need this for daisy-chained symlinks.
|
||||||
|
while
|
||||||
|
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||||
|
[ -h "$app_path" ]
|
||||||
|
do
|
||||||
|
ls=$( ls -ld "$app_path" )
|
||||||
|
link=${ls#*' -> '}
|
||||||
|
case $link in #(
|
||||||
|
/*) app_path=$link ;; #(
|
||||||
|
*) app_path=$APP_HOME$link ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# This is normally unused
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
APP_BASE_NAME=${0##*/}
|
||||||
|
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||||
|
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
|
MAX_FD=maximum
|
||||||
|
|
||||||
|
warn () {
|
||||||
|
echo "$*"
|
||||||
|
} >&2
|
||||||
|
|
||||||
|
die () {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
} >&2
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
nonstop=false
|
||||||
|
case "$( uname )" in #(
|
||||||
|
CYGWIN* ) cygwin=true ;; #(
|
||||||
|
Darwin* ) darwin=true ;; #(
|
||||||
|
MSYS* | MINGW* ) msys=true ;; #(
|
||||||
|
NONSTOP* ) nonstop=true ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
CLASSPATH="\\\"\\\""
|
||||||
|
|
||||||
|
|
||||||
|
# Determine the Java command to use to start the JVM.
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||||
|
else
|
||||||
|
JAVACMD=$JAVA_HOME/bin/java
|
||||||
|
fi
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD=java
|
||||||
|
if ! command -v java >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Increase the maximum file descriptors if we can.
|
||||||
|
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||||
|
case $MAX_FD in #(
|
||||||
|
max*)
|
||||||
|
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||||
|
# shellcheck disable=SC2039,SC3045
|
||||||
|
MAX_FD=$( ulimit -H -n ) ||
|
||||||
|
warn "Could not query maximum file descriptor limit"
|
||||||
|
esac
|
||||||
|
case $MAX_FD in #(
|
||||||
|
'' | soft) :;; #(
|
||||||
|
*)
|
||||||
|
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||||
|
# shellcheck disable=SC2039,SC3045
|
||||||
|
ulimit -n "$MAX_FD" ||
|
||||||
|
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Collect all arguments for the java command, stacking in reverse order:
|
||||||
|
# * args from the command line
|
||||||
|
# * the main class name
|
||||||
|
# * -classpath
|
||||||
|
# * -D...appname settings
|
||||||
|
# * --module-path (only if needed)
|
||||||
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||||
|
|
||||||
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||||
|
if "$cygwin" || "$msys" ; then
|
||||||
|
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||||
|
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||||
|
|
||||||
|
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||||
|
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
for arg do
|
||||||
|
if
|
||||||
|
case $arg in #(
|
||||||
|
-*) false ;; # don't mess with options #(
|
||||||
|
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||||
|
[ -e "$t" ] ;; #(
|
||||||
|
*) false ;;
|
||||||
|
esac
|
||||||
|
then
|
||||||
|
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||||
|
fi
|
||||||
|
# Roll the args list around exactly as many times as the number of
|
||||||
|
# args, so each arg winds up back in the position where it started, but
|
||||||
|
# possibly modified.
|
||||||
|
#
|
||||||
|
# NB: a `for` loop captures its iteration list before it begins, so
|
||||||
|
# changing the positional parameters here affects neither the number of
|
||||||
|
# iterations, nor the values presented in `arg`.
|
||||||
|
shift # remove old arg
|
||||||
|
set -- "$@" "$arg" # push replacement arg
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
|
# Collect all arguments for the java command:
|
||||||
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||||
|
# and any embedded shellness will be escaped.
|
||||||
|
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||||
|
# treated as '${Hostname}' itself on the command line.
|
||||||
|
|
||||||
|
set -- \
|
||||||
|
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||||
|
-classpath "$CLASSPATH" \
|
||||||
|
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||||
|
"$@"
|
||||||
|
|
||||||
|
# Stop when "xargs" is not available.
|
||||||
|
if ! command -v xargs >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "xargs is not available"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Use "xargs" to parse quoted args.
|
||||||
|
#
|
||||||
|
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||||
|
#
|
||||||
|
# In Bash we could simply go:
|
||||||
|
#
|
||||||
|
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||||
|
# set -- "${ARGS[@]}" "$@"
|
||||||
|
#
|
||||||
|
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||||
|
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||||
|
# character that might be a shell metacharacter, then use eval to reverse
|
||||||
|
# that process (while maintaining the separation between arguments), and wrap
|
||||||
|
# the whole thing up as a single "set" statement.
|
||||||
|
#
|
||||||
|
# This will of course break if any of these variables contains a newline or
|
||||||
|
# an unmatched quote.
|
||||||
|
#
|
||||||
|
|
||||||
|
eval "set -- $(
|
||||||
|
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||||
|
xargs -n1 |
|
||||||
|
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||||
|
tr '\n' ' '
|
||||||
|
)" '"$@"'
|
||||||
|
|
||||||
|
exec "$JAVACMD" "$@"
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
@rem
|
||||||
|
@rem Copyright 2015 the original author or authors.
|
||||||
|
@rem
|
||||||
|
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@rem you may not use this file except in compliance with the License.
|
||||||
|
@rem You may obtain a copy of the License at
|
||||||
|
@rem
|
||||||
|
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
@rem
|
||||||
|
@rem Unless required by applicable law or agreed to in writing, software
|
||||||
|
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@rem See the License for the specific language governing permissions and
|
||||||
|
@rem limitations under the License.
|
||||||
|
@rem
|
||||||
|
@rem SPDX-License-Identifier: Apache-2.0
|
||||||
|
@rem
|
||||||
|
|
||||||
|
@if "%DEBUG%"=="" @echo off
|
||||||
|
@rem ##########################################################################
|
||||||
|
@rem
|
||||||
|
@rem Gradle startup script for Windows
|
||||||
|
@rem
|
||||||
|
@rem ##########################################################################
|
||||||
|
|
||||||
|
@rem Set local scope for the variables with windows NT shell
|
||||||
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
|
set DIRNAME=%~dp0
|
||||||
|
if "%DIRNAME%"=="" set DIRNAME=.
|
||||||
|
@rem This is normally unused
|
||||||
|
set APP_BASE_NAME=%~n0
|
||||||
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||||
|
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||||
|
|
||||||
|
@rem Find java.exe
|
||||||
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
|
set JAVA_EXE=java.exe
|
||||||
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
|
if %ERRORLEVEL% equ 0 goto execute
|
||||||
|
|
||||||
|
echo. 1>&2
|
||||||
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||||
|
echo. 1>&2
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:findJavaFromJavaHome
|
||||||
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
|
echo. 1>&2
|
||||||
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||||
|
echo. 1>&2
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:execute
|
||||||
|
@rem Setup the command line
|
||||||
|
|
||||||
|
set CLASSPATH=
|
||||||
|
|
||||||
|
|
||||||
|
@rem Execute Gradle
|
||||||
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||||
|
|
||||||
|
:end
|
||||||
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||||
|
|
||||||
|
:fail
|
||||||
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
|
rem the _cmd.exe /c_ return code!
|
||||||
|
set EXIT_CODE=%ERRORLEVEL%
|
||||||
|
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||||
|
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||||
|
exit /b %EXIT_CODE%
|
||||||
|
|
||||||
|
:mainEnd
|
||||||
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
|
:omega
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
include ':app'
|
||||||
|
include ':capacitor-cordova-android-plugins'
|
||||||
|
project(':capacitor-cordova-android-plugins').projectDir = new File('./capacitor-cordova-android-plugins/')
|
||||||
|
|
||||||
|
apply from: 'capacitor.settings.gradle'
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
ext {
|
||||||
|
minSdkVersion = 24
|
||||||
|
compileSdkVersion = 36
|
||||||
|
targetSdkVersion = 36
|
||||||
|
androidxActivityVersion = '1.11.0'
|
||||||
|
androidxAppCompatVersion = '1.7.1'
|
||||||
|
androidxCoordinatorLayoutVersion = '1.3.0'
|
||||||
|
androidxCoreVersion = '1.17.0'
|
||||||
|
androidxFragmentVersion = '1.8.9'
|
||||||
|
coreSplashScreenVersion = '1.2.0'
|
||||||
|
androidxWebkitVersion = '1.14.0'
|
||||||
|
junitVersion = '4.13.2'
|
||||||
|
androidxJunitVersion = '1.3.0'
|
||||||
|
androidxEspressoCoreVersion = '3.7.0'
|
||||||
|
cordovaAndroidVersion = '14.0.1'
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "3DS DevkitARM",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/**",
|
||||||
|
"C:/devkitPro/libctru/include", // Chemin Windows standard
|
||||||
|
"/opt/devkitpro/libctru/include" // Chemin Linux/macOS standard
|
||||||
|
],
|
||||||
|
"defines": [
|
||||||
|
"__3DS__"
|
||||||
|
],
|
||||||
|
"compilerPath": "C:/devkitPro/devkitARM/bin/arm-none-eabi-g++.exe", // Aide l'intellisense
|
||||||
|
"cStandard": "c11",
|
||||||
|
"cppStandard": "c++11",
|
||||||
|
"intelliSenseMode": "windows-gcc-arm"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": 4
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"appId": "com.openplanetsmaps.app",
|
||||||
|
"appName": "OpenPlanetsMaps",
|
||||||
|
"webDir": "SRC",
|
||||||
|
"server": {
|
||||||
|
"url": "https://opm.nhkyllian.fr",
|
||||||
|
"cleartext": true
|
||||||
|
},
|
||||||
|
"plugins": {
|
||||||
|
"StatusBar": {
|
||||||
|
"overlaysWebView": false,
|
||||||
|
"backgroundColor": "#020408",
|
||||||
|
"style": "DARK"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
const { app, BrowserWindow } = require('electron');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const createWindow = () => {
|
||||||
|
const mainWindow = new BrowserWindow({
|
||||||
|
width: 1280,
|
||||||
|
height: 800,
|
||||||
|
icon: path.join(__dirname, 'SRC/IMG/IMP_Gen_logo-removebg-preview.png'),
|
||||||
|
webPreferences: {
|
||||||
|
nodeIntegration: false,
|
||||||
|
contextIsolation: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
mainWindow.loadURL('https://opm.nhkyllian.fr');
|
||||||
|
};
|
||||||
|
|
||||||
|
app.whenReady().then(() => {
|
||||||
|
createWindow();
|
||||||
|
|
||||||
|
app.on('activate', () => {
|
||||||
|
if (BrowserWindow.getAllWindows().length === 0) createWindow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
app.on('window-all-closed', () => {
|
||||||
|
if (process.platform !== 'darwin') app.quit();
|
||||||
|
});
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
# Environnement de Déploiement : AlwaysData
|
|
||||||
|
|
||||||
Ce document explique la façon dont j'ai déployé et configuré le projet OpenPlanetsMaps sur mon espace d'hébergement AlwaysData.
|
|
||||||
|
|
||||||
## 1. Hébergement et Transfert de fichiers (FTP)
|
|
||||||
Le site est configuré en tant que site **PHP (version 8.x)** sur AlwaysData.
|
|
||||||
Pour la mise en ligne, j'ai utilisé le client FTP **FileZilla**. J'ai transféré l'intégralité du contenu de mon dossier local `www/` vers le répertoire racine web de mon serveur AlwaysData à l'aide des accès FTP fournis par l'hébergeur.
|
|
||||||
|
|
||||||
## 2. Base de données
|
|
||||||
L'API et le site s'appuient sur une base de données MySQL/MariaDB hébergée sur AlwaysData.
|
|
||||||
- J'ai créé la base de données directement depuis le panel AlwaysData.
|
|
||||||
- J'ai ensuite utilisé l'outil **phpMyAdmin** fourni par l'hébergeur pour importer le script de structure `doc/Structure.sql`, ce qui a généré toutes les tables nécessaires (`EARTH`, `MARS`, ..., `CONTACT`).
|
|
||||||
- J'ai également importé le fichier `data.sql` via phpMyAdmin afin de peupler la base avec les données astronomiques de chaque planètes.
|
|
||||||
|
|
||||||
## 3. Configuration et Variables d'environnement
|
|
||||||
Pour des raisons de sécurité, les identifiants de la base de données ne sont pas codés en dur dans mes scripts publics. J'ai créé un fichier de configuration `config.php` directement sur le serveur distant, à la racine du site (`www/config.php`).
|
|
||||||
|
|
||||||
Ce fichier (non versionné sur GitHub) contient mes variables de production :
|
|
||||||
|
|
||||||
le fichier vous sera montré lors de la présentation.
|
|
||||||
|
|
||||||
## 4. Vérification finale
|
|
||||||
Une fois le déploiement terminé, j'ai effectué une série de tests sur ma version finale en production pour m'assurer que tout fonctionnait correctement :
|
|
||||||
- Accès à l'URL de mon site (ex: `https://openplanetsmaps.alwaysdata.net`).
|
|
||||||
- Vérification du bon affichage des données des planètes provenant de l'API.
|
|
||||||
- Test du formulaire de contact (l'insertion en base de données et le téléversement de fichiers sont opérationnels).
|
|
||||||
- Connexion à la page `/admin.php` avec mes identifiants pour tester l'ajout d'une entrée.
|
|
||||||
- Test du versionnage téléphone du site pour garantir une bonne adaptabilité sur mobile.
|
|
||||||
- Vérification minutieuse de l'ensemble du backlog fourni pour m'assurer de la totale conformité du livrable vis-à-vis des attentes de l'examen.
|
|
||||||
|
|
||||||
La version finale actuellement en ligne est parfaitement fonctionnelle.
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
App/build
|
||||||
|
App/Pods
|
||||||
|
App/output
|
||||||
|
App/App/public
|
||||||
|
DerivedData
|
||||||
|
xcuserdata
|
||||||
|
|
||||||
|
# Cordova plugins for Capacitor
|
||||||
|
capacitor-cordova-ios-plugins
|
||||||
|
|
||||||
|
# Generated Config files
|
||||||
|
App/App/capacitor.config.json
|
||||||
|
App/App/config.xml
|
||||||
@@ -0,0 +1,376 @@
|
|||||||
|
// !$*UTF8*$!
|
||||||
|
{
|
||||||
|
archiveVersion = 1;
|
||||||
|
classes = {
|
||||||
|
};
|
||||||
|
objectVersion = 60;
|
||||||
|
objects = {
|
||||||
|
|
||||||
|
/* Begin PBXBuildFile section */
|
||||||
|
2FAD9763203C412B000D30F8 /* config.xml in Resources */ = {isa = PBXBuildFile; fileRef = 2FAD9762203C412B000D30F8 /* config.xml */; };
|
||||||
|
4D22ABE92AF431CB00220026 /* CapApp-SPM in Frameworks */ = {isa = PBXBuildFile; productRef = 4D22ABE82AF431CB00220026 /* CapApp-SPM */; };
|
||||||
|
50379B232058CBB4000EE86E /* capacitor.config.json in Resources */ = {isa = PBXBuildFile; fileRef = 50379B222058CBB4000EE86E /* capacitor.config.json */; };
|
||||||
|
504EC3081FED79650016851F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504EC3071FED79650016851F /* AppDelegate.swift */; };
|
||||||
|
504EC30D1FED79650016851F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30B1FED79650016851F /* Main.storyboard */; };
|
||||||
|
504EC30F1FED79650016851F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30E1FED79650016851F /* Assets.xcassets */; };
|
||||||
|
504EC3121FED79650016851F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC3101FED79650016851F /* LaunchScreen.storyboard */; };
|
||||||
|
50B271D11FEDC1A000F3C39B /* public in Resources */ = {isa = PBXBuildFile; fileRef = 50B271D01FEDC1A000F3C39B /* public */; };
|
||||||
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
|
/* Begin PBXFileReference section */
|
||||||
|
2FAD9762203C412B000D30F8 /* config.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = config.xml; sourceTree = "<group>"; };
|
||||||
|
50379B222058CBB4000EE86E /* capacitor.config.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = capacitor.config.json; sourceTree = "<group>"; };
|
||||||
|
504EC3041FED79650016851F /* App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = App.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
504EC3071FED79650016851F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
|
504EC30C1FED79650016851F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||||
|
504EC30E1FED79650016851F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
|
504EC3111FED79650016851F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||||
|
504EC3131FED79650016851F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
50B271D01FEDC1A000F3C39B /* public */ = {isa = PBXFileReference; lastKnownFileType = folder; path = public; sourceTree = "<group>"; };
|
||||||
|
958DCC722DB07C7200EA8C5F /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = debug.xcconfig; path = ../debug.xcconfig; sourceTree = SOURCE_ROOT; };
|
||||||
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
504EC3011FED79650016851F /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
4D22ABE92AF431CB00220026 /* CapApp-SPM in Frameworks */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXGroup section */
|
||||||
|
504EC2FB1FED79650016851F = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
958DCC722DB07C7200EA8C5F /* debug.xcconfig */,
|
||||||
|
504EC3061FED79650016851F /* App */,
|
||||||
|
504EC3051FED79650016851F /* Products */,
|
||||||
|
);
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
504EC3051FED79650016851F /* Products */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
504EC3041FED79650016851F /* App.app */,
|
||||||
|
);
|
||||||
|
name = Products;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
504EC3061FED79650016851F /* App */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
50379B222058CBB4000EE86E /* capacitor.config.json */,
|
||||||
|
504EC3071FED79650016851F /* AppDelegate.swift */,
|
||||||
|
504EC30B1FED79650016851F /* Main.storyboard */,
|
||||||
|
504EC30E1FED79650016851F /* Assets.xcassets */,
|
||||||
|
504EC3101FED79650016851F /* LaunchScreen.storyboard */,
|
||||||
|
504EC3131FED79650016851F /* Info.plist */,
|
||||||
|
2FAD9762203C412B000D30F8 /* config.xml */,
|
||||||
|
50B271D01FEDC1A000F3C39B /* public */,
|
||||||
|
);
|
||||||
|
path = App;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
/* End PBXGroup section */
|
||||||
|
|
||||||
|
/* Begin PBXNativeTarget section */
|
||||||
|
504EC3031FED79650016851F /* App */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 504EC3161FED79650016851F /* Build configuration list for PBXNativeTarget "App" */;
|
||||||
|
buildPhases = (
|
||||||
|
504EC3001FED79650016851F /* Sources */,
|
||||||
|
504EC3011FED79650016851F /* Frameworks */,
|
||||||
|
504EC3021FED79650016851F /* Resources */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
name = App;
|
||||||
|
packageProductDependencies = (
|
||||||
|
4D22ABE82AF431CB00220026 /* CapApp-SPM */,
|
||||||
|
);
|
||||||
|
productName = App;
|
||||||
|
productReference = 504EC3041FED79650016851F /* App.app */;
|
||||||
|
productType = "com.apple.product-type.application";
|
||||||
|
};
|
||||||
|
/* End PBXNativeTarget section */
|
||||||
|
|
||||||
|
/* Begin PBXProject section */
|
||||||
|
504EC2FC1FED79650016851F /* Project object */ = {
|
||||||
|
isa = PBXProject;
|
||||||
|
attributes = {
|
||||||
|
LastSwiftUpdateCheck = 0920;
|
||||||
|
LastUpgradeCheck = 0920;
|
||||||
|
TargetAttributes = {
|
||||||
|
504EC3031FED79650016851F = {
|
||||||
|
CreatedOnToolsVersion = 9.2;
|
||||||
|
LastSwiftMigration = 1100;
|
||||||
|
ProvisioningStyle = Automatic;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
buildConfigurationList = 504EC2FF1FED79650016851F /* Build configuration list for PBXProject "App" */;
|
||||||
|
compatibilityVersion = "Xcode 8.0";
|
||||||
|
developmentRegion = en;
|
||||||
|
hasScannedForEncodings = 0;
|
||||||
|
knownRegions = (
|
||||||
|
en,
|
||||||
|
Base,
|
||||||
|
);
|
||||||
|
mainGroup = 504EC2FB1FED79650016851F;
|
||||||
|
packageReferences = (
|
||||||
|
D4C12C0A2AAA248700AAC8A2 /* XCLocalSwiftPackageReference "CapApp-SPM" */,
|
||||||
|
);
|
||||||
|
productRefGroup = 504EC3051FED79650016851F /* Products */;
|
||||||
|
projectDirPath = "";
|
||||||
|
projectRoot = "";
|
||||||
|
targets = (
|
||||||
|
504EC3031FED79650016851F /* App */,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
/* End PBXProject section */
|
||||||
|
|
||||||
|
/* Begin PBXResourcesBuildPhase section */
|
||||||
|
504EC3021FED79650016851F /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
504EC3121FED79650016851F /* LaunchScreen.storyboard in Resources */,
|
||||||
|
50B271D11FEDC1A000F3C39B /* public in Resources */,
|
||||||
|
504EC30F1FED79650016851F /* Assets.xcassets in Resources */,
|
||||||
|
50379B232058CBB4000EE86E /* capacitor.config.json in Resources */,
|
||||||
|
504EC30D1FED79650016851F /* Main.storyboard in Resources */,
|
||||||
|
2FAD9763203C412B000D30F8 /* config.xml in Resources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
|
504EC3001FED79650016851F /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
504EC3081FED79650016851F /* AppDelegate.swift in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXVariantGroup section */
|
||||||
|
504EC30B1FED79650016851F /* Main.storyboard */ = {
|
||||||
|
isa = PBXVariantGroup;
|
||||||
|
children = (
|
||||||
|
504EC30C1FED79650016851F /* Base */,
|
||||||
|
);
|
||||||
|
name = Main.storyboard;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
504EC3101FED79650016851F /* LaunchScreen.storyboard */ = {
|
||||||
|
isa = PBXVariantGroup;
|
||||||
|
children = (
|
||||||
|
504EC3111FED79650016851F /* Base */,
|
||||||
|
);
|
||||||
|
name = LaunchScreen.storyboard;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
/* End PBXVariantGroup section */
|
||||||
|
|
||||||
|
/* Begin XCBuildConfiguration section */
|
||||||
|
504EC3141FED79650016851F /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 958DCC722DB07C7200EA8C5F /* debug.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_COMMA = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
ENABLE_TESTABILITY = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
|
GCC_DYNAMIC_NO_PIC = NO;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_OPTIMIZATION_LEVEL = 0;
|
||||||
|
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||||
|
"DEBUG=1",
|
||||||
|
"$(inherited)",
|
||||||
|
);
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = YES;
|
||||||
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
504EC3151FED79650016851F /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_COMMA = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
SWIFT_COMPILATION_MODE = wholemodule;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||||
|
VALIDATE_PRODUCT = YES;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
504EC3171FED79650016851F /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 958DCC722DB07C7200EA8C5F /* debug.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
INFOPLIST_FILE = App/Info.plist;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
);
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = com.openplanetsmaps.app;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
504EC3181FED79650016851F /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
INFOPLIST_FILE = App/Info.plist;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
);
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = com.openplanetsmaps.app;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
|
/* Begin XCConfigurationList section */
|
||||||
|
504EC2FF1FED79650016851F /* Build configuration list for PBXProject "App" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
504EC3141FED79650016851F /* Debug */,
|
||||||
|
504EC3151FED79650016851F /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
504EC3161FED79650016851F /* Build configuration list for PBXNativeTarget "App" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
504EC3171FED79650016851F /* Debug */,
|
||||||
|
504EC3181FED79650016851F /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
/* End XCConfigurationList section */
|
||||||
|
|
||||||
|
/* Begin XCLocalSwiftPackageReference section */
|
||||||
|
D4C12C0A2AAA248700AAC8A2 /* XCLocalSwiftPackageReference "CapApp-SPM" */ = {
|
||||||
|
isa = XCLocalSwiftPackageReference;
|
||||||
|
relativePath = "CapApp-SPM";
|
||||||
|
};
|
||||||
|
/* End XCLocalSwiftPackageReference section */
|
||||||
|
|
||||||
|
/* Begin XCSwiftPackageProductDependency section */
|
||||||
|
4D22ABE82AF431CB00220026 /* CapApp-SPM */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
package = D4C12C0A2AAA248700AAC8A2 /* XCLocalSwiftPackageReference "CapApp-SPM" */;
|
||||||
|
productName = "CapApp-SPM";
|
||||||
|
};
|
||||||
|
/* End XCSwiftPackageProductDependency section */
|
||||||
|
};
|
||||||
|
rootObject = 504EC2FC1FED79650016851F /* Project object */;
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>IDEDidComputeMac32BitWarning</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import UIKit
|
||||||
|
import Capacitor
|
||||||
|
|
||||||
|
@UIApplicationMain
|
||||||
|
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||||
|
|
||||||
|
var window: UIWindow?
|
||||||
|
|
||||||
|
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||||
|
// Override point for customization after application launch.
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func applicationWillResignActive(_ application: UIApplication) {
|
||||||
|
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
|
||||||
|
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
|
||||||
|
}
|
||||||
|
|
||||||
|
func applicationDidEnterBackground(_ application: UIApplication) {
|
||||||
|
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
|
||||||
|
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
|
||||||
|
}
|
||||||
|
|
||||||
|
func applicationWillEnterForeground(_ application: UIApplication) {
|
||||||
|
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
|
||||||
|
}
|
||||||
|
|
||||||
|
func applicationDidBecomeActive(_ application: UIApplication) {
|
||||||
|
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
|
||||||
|
}
|
||||||
|
|
||||||
|
func applicationWillTerminate(_ application: UIApplication) {
|
||||||
|
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
|
||||||
|
}
|
||||||
|
|
||||||
|
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
|
||||||
|
// Called when the app was launched with a url. Feel free to add additional processing here,
|
||||||
|
// but if you want the App API to support tracking app url opens, make sure to keep this call
|
||||||
|
return ApplicationDelegateProxy.shared.application(app, open: url, options: options)
|
||||||
|
}
|
||||||
|
|
||||||
|
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
|
||||||
|
// Called when the app was launched with an activity, including Universal Links.
|
||||||
|
// Feel free to add additional processing here, but if you want the App API to support
|
||||||
|
// tracking app url opens, make sure to keep this call
|
||||||
|
return ApplicationDelegateProxy.shared.application(application, continue: userActivity, restorationHandler: restorationHandler)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 108 KiB |
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "AppIcon-512@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"size" : "1024x1024"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"filename" : "splash-2732x2732-2.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"filename" : "splash-2732x2732-1.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"filename" : "splash-2732x2732.png",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 40 KiB |
@@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17132" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||||
|
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||||
|
<dependencies>
|
||||||
|
<deployment identifier="iOS"/>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17105"/>
|
||||||
|
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
||||||
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
|
</dependencies>
|
||||||
|
<scenes>
|
||||||
|
<!--View Controller-->
|
||||||
|
<scene sceneID="EHf-IW-A2E">
|
||||||
|
<objects>
|
||||||
|
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||||
|
<imageView key="view" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Splash" id="snD-IY-ifK">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||||
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||||
|
</imageView>
|
||||||
|
</viewController>
|
||||||
|
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
|
</objects>
|
||||||
|
<point key="canvasLocation" x="53" y="375"/>
|
||||||
|
</scene>
|
||||||
|
</scenes>
|
||||||
|
<resources>
|
||||||
|
<image name="Splash" width="1366" height="1366"/>
|
||||||
|
<systemColor name="systemBackgroundColor">
|
||||||
|
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
</systemColor>
|
||||||
|
</resources>
|
||||||
|
</document>
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14111" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
|
||||||
|
<device id="retina4_7" orientation="portrait">
|
||||||
|
<adaptation id="fullscreen"/>
|
||||||
|
</device>
|
||||||
|
<dependencies>
|
||||||
|
<deployment identifier="iOS"/>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/>
|
||||||
|
</dependencies>
|
||||||
|
<scenes>
|
||||||
|
<!--Bridge View Controller-->
|
||||||
|
<scene sceneID="tne-QT-ifu">
|
||||||
|
<objects>
|
||||||
|
<viewController id="BYZ-38-t0r" customClass="CAPBridgeViewController" customModule="Capacitor" sceneMemberID="viewController"/>
|
||||||
|
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||||
|
</objects>
|
||||||
|
</scene>
|
||||||
|
</scenes>
|
||||||
|
</document>
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CAPACITOR_DEBUG</key>
|
||||||
|
<string>$(CAPACITOR_DEBUG)</string>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleDisplayName</key>
|
||||||
|
<string>OpenPlanetsMaps</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>$(PRODUCT_NAME)</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>APPL</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>$(MARKETING_VERSION)</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||||
|
<key>LSRequiresIPhoneOS</key>
|
||||||
|
<true/>
|
||||||
|
<key>UILaunchStoryboardName</key>
|
||||||
|
<string>LaunchScreen</string>
|
||||||
|
<key>UIMainStoryboardFile</key>
|
||||||
|
<string>Main</string>
|
||||||
|
<key>UIRequiredDeviceCapabilities</key>
|
||||||
|
<array>
|
||||||
|
<string>armv7</string>
|
||||||
|
</array>
|
||||||
|
<key>UISupportedInterfaceOrientations</key>
|
||||||
|
<array>
|
||||||
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
|
</array>
|
||||||
|
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||||
|
<array>
|
||||||
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
|
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
|
</array>
|
||||||
|
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
.DS_Store
|
||||||
|
/.build
|
||||||
|
/Packages
|
||||||
|
/*.xcodeproj
|
||||||
|
xcuserdata/
|
||||||
|
DerivedData/
|
||||||
|
.swiftpm/config/registries.json
|
||||||
|
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
|
||||||
|
.netrc
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
// swift-tools-version: 5.9
|
||||||
|
import PackageDescription
|
||||||
|
|
||||||
|
// DO NOT MODIFY THIS FILE - managed by Capacitor CLI commands
|
||||||
|
let package = Package(
|
||||||
|
name: "CapApp-SPM",
|
||||||
|
platforms: [.iOS(.v15)],
|
||||||
|
products: [
|
||||||
|
.library(
|
||||||
|
name: "CapApp-SPM",
|
||||||
|
targets: ["CapApp-SPM"])
|
||||||
|
],
|
||||||
|
dependencies: [
|
||||||
|
.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", exact: "8.3.4")
|
||||||
|
],
|
||||||
|
targets: [
|
||||||
|
.target(
|
||||||
|
name: "CapApp-SPM",
|
||||||
|
dependencies: [
|
||||||
|
.product(name: "Capacitor", package: "capacitor-swift-pm"),
|
||||||
|
.product(name: "Cordova", package: "capacitor-swift-pm")
|
||||||
|
]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||