20 Commits
Author SHA1 Message Date
tezcat 9e4c0524af TETST 2026-06-28 16:59:50 +02:00
tezcat 3f0c008488 TESTé 2026-06-28 16:58:05 +02:00
tezcat b24b641a8f TEST 2026-06-28 16:55:55 +02:00
tezcat 9277303969 fix: Synchronize package-lock.json 2026-06-28 16:53:05 +02:00
tezcat 357ac871bf 3ds inte. 2026-06-28 16:51:45 +02:00
tezcat b7e704afc2 feat: Add GitHub Action to build 3DS CIA 2026-06-28 16:49:28 +02:00
tezcat 6646697b70 Update Readme
Actualise The Readme With Recents Informations
2026-05-17 23:48:44 +02:00
tezcat 22106a76f1 update with aab config
a config for play store android
2026-05-17 21:33:51 +02:00
tezcat 1d0588fa69 fix barphone ios 2026-05-17 21:06:34 +02:00
tezcat d880520882 update responsive ios vers. 2026-05-17 20:59:02 +02:00
tezcat f0ab8eff41 fix header responsive 2026-05-17 20:50:59 +02:00
tezcat 0ae1664ce1 fix responsive for IPA & APK 2026-05-17 20:45:41 +02:00
tezcat edfc4d833f delete podfile 2026-05-17 20:30:46 +02:00
tezcat c5214343c7 update java vers. 2026-05-17 20:26:38 +02:00
tezcat 506b0ff09d update build 2026-05-17 20:03:43 +02:00
tezcat d207a96ea5 update vers. 2026-05-17 19:59:57 +02:00
tezcat f1232d639c fix error 66 and 2 for builds 2026-05-17 19:56:28 +02:00
tezcat a0c79989cd update way 2026-05-17 19:53:16 +02:00
tezcat 7df3a530ce Correction de l'emplacement des workflows GitHub Actions 2026-05-17 19:47:26 +02:00
tezcat 7e2c27d165 Add Electron & Setup Github Actions 2026-05-17 19:44:15 +02:00
106 changed files with 5731 additions and 123 deletions
+33
View File
@@ -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é
+29
View File
@@ -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 }}
+122
View File
@@ -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
+17 -1
View File
@@ -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
+40
View File
@@ -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."
}
]
}
+37
View File
@@ -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
+32
View File
@@ -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.
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

View File
+109
View File
@@ -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>
+4 -11
View File
@@ -1,20 +1,16 @@
<?php
header('Content-Type: application/json');
/* --- CONFIGURATION & SETUP --- */
$config = require_once 'config.php';
$host = $config['host'];
$dbname = $config['dbname'];
$username = $config['username'];
$password = $config['password'];
$host = '172.22.0.3';
$dbname = 'OpenPlanetsMaps';
$username = 'root';
$password = 'admin123';
try {
/* --- DATABASE CONNECTION --- */
$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);
/* --- REQUEST HANDLING --- */
$planetId = isset($_GET['planet']) ? $_GET['planet'] : '';
$allowedTables = [
@@ -31,7 +27,6 @@ try {
];
if ($planetId === 'quiz') {
/* --- QUIZ DATA GENERATION --- */
$queries = [];
$seed = date('Ymd');
foreach ($allowedTables as $key => $table) {
@@ -70,7 +65,6 @@ try {
exit;
}
/* --- PLANET DATA FETCHING --- */
if (!array_key_exists($planetId, $allowedTables)) {
echo json_encode([]);
exit;
@@ -83,7 +77,6 @@ try {
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode($data);
} catch (PDOException $e) {
/* --- ERROR HANDLING --- */
http_response_code(500);
echo json_encode(['error' => 'Database error: ' . $e->getMessage()]);
}
+88
View File
@@ -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 -19
View File
@@ -3,15 +3,15 @@
<head>
<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>
<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 -->
<header>
<div class="menu-icon" onclick="toggleSidebar()"></div>
<h1>Open Planets Maps</h1>
@@ -21,7 +21,6 @@
</div>
</header>
<!-- SIDEBAR -->
<nav id="sidebar" class="sidebar">
<ul>
<li onclick="showLayer('home')">Home</li>
@@ -42,9 +41,7 @@
</ul>
</nav>
<!-- MAIN CONTENT -->
<main id="content-area">
<!-- HOME SECTION -->
<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>
@@ -65,7 +62,6 @@
<div class="desc-box">Ready for launch? Open the side menu (☰) and select a destination to begin your journey.</div>
</section>
<!-- MERCURY SECTION -->
<section id="layer-mercury" class="layer">
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
<div class="main-img">
@@ -91,7 +87,6 @@
</div>
</section>
<!-- VENUS SECTION -->
<section id="layer-venus" class="layer">
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
<div class="main-img">
@@ -117,7 +112,6 @@
</div>
</section>
<!-- EARTH SECTION -->
<section id="layer-earth" class="layer">
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
<div class="main-img">
@@ -143,7 +137,6 @@
</div>
</section>
<!-- MARS SECTION -->
<section id="layer-mars" class="layer">
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
<div class="main-img">
@@ -169,7 +162,6 @@
</div>
</section>
<!-- JUPITER SECTION -->
<section id="layer-jupiter" class="layer">
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
<div class="main-img">
@@ -195,7 +187,6 @@
</div>
</section>
<!-- SATURN SECTION -->
<section id="layer-saturn" class="layer">
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
<div class="main-img">
@@ -221,7 +212,6 @@
</div>
</section>
<!-- URANUS SECTION -->
<section id="layer-uranus" class="layer">
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
<div class="main-img">
@@ -247,7 +237,6 @@
</div>
</section>
<!-- NEPTUNE SECTION -->
<section id="layer-neptune" class="layer">
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
<div class="main-img">
@@ -273,7 +262,6 @@
</div>
</section>
<!-- SUN SECTION -->
<section id="layer-sun" class="layer">
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
<div class="main-img">
@@ -302,7 +290,6 @@
</div>
</section>
<!-- MOON SECTION -->
<section id="layer-moon" class="layer">
<div class="search-bar"><input type="text" placeholder="Multi-criteria search..."></div>
<div class="main-img">
@@ -331,7 +318,6 @@
</div>
</section>
<!-- QUIZ 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>
@@ -354,12 +340,10 @@
</section>
</main>
<!-- FOOTER -->
<footer class="site-footer" onclick="openCredits()" title="Credits & About">
&copy; 2026 OpenPlanetsMaps. Royalty-free. <span class="footer-credits-hint">— Credits ↗</span>
</footer>
<!-- CREDITS MODAL -->
<div id="credits-overlay"></div>
<div id="credits-panel">
<button class="credits-close" onclick="closeCredits()"></button>
@@ -407,7 +391,7 @@
</div>
</div>
<!-- SCRIPTS -->
<script src="main.js"></script>
</body>
</html>
+19 -7
View File
@@ -1,4 +1,3 @@
/* --- UI & NAVIGATION --- */
function toggleSidebar() {
document.getElementById('sidebar').classList.toggle('open');
}
@@ -25,7 +24,6 @@ function showLayer(layerId) {
const planetData = {};
const planetCols = {};
/* --- SEARCH & FILTERING --- */
function wireSearch(planetId) {
const layer = document.getElementById('layer-' + planetId);
if (!layer) return;
@@ -100,7 +98,6 @@ function filterTable(planetId, query) {
});
}
/* --- API & DATA FETCHING --- */
async function fetchData(planetId) {
const tbody = document.getElementById('tbody-' + planetId);
if (!tbody) return;
@@ -215,7 +212,6 @@ let quizQuestions = [];
let currentQuizIndex = 0;
let quizScore = 0;
/* --- QUIZ SYSTEM --- */
async function initQuiz() {
currentQuizIndex = 0;
quizScore = 0;
@@ -343,7 +339,6 @@ function checkAnswer(selected, correct, btn) {
}, 1800);
}
/* --- CREDITS MODAL --- */
function openCredits() {
document.getElementById('credits-panel').classList.add('open');
document.getElementById('credits-overlay').classList.add('open');
@@ -356,7 +351,6 @@ function closeCredits() {
document.body.style.overflow = '';
}
/* --- INITIALIZATION & MOBILE FALLBACK --- */
document.addEventListener('DOMContentLoaded', () => {
const overlay = document.getElementById('credits-overlay');
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 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');
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";
+17 -19
View File
@@ -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');
: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-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; }
html, body { max-width:100vw; overflow-x:hidden; }
@@ -33,7 +31,6 @@ body {
transition:background-color .8s ease, color .3s ease;
}
/* --- ANIMATED BACKGROUND --- */
.bg-animated {
position:fixed; inset:0; z-index:-2;
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; }
}
/* --- HEADER --- */
#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;
padding:0 2rem;
height:64px;
background:rgba(2,4,8,.75); backdrop-filter:blur(20px);
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;
}
header::after {
@@ -135,7 +139,6 @@ header h1:hover { animation:glitch .4s steps(1) forwards; }
box-shadow:0 0 12px var(--theme-glow);
}
/* --- SIDEBAR --- */
.sidebar {
position:fixed; top:0; left:-300px; width:280px; height:100vh;
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:hover { background:none; padding-left:1.75rem; text-shadow:none; color:var(--text-muted); }
/* --- LAYOUT & MAIN CONTENT --- */
#content-area {
flex:1; padding:2.5rem; display:flex;
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; }
/* --- COMPONENTS (Images, Boxes, Tickers) --- */
.main-img {
margin-bottom:2.5rem; position:relative;
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; }
/* --- SEARCH BAR --- */
.search-bar { margin-bottom:2rem; position:relative; display:flex; justify-content:center; }
.search-bar::before {
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);
}
/* --- DATA TABLES --- */
.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); }
@@ -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 { box-shadow:0 0 24px var(--theme-glow); transform:translateY(1px); }
/* --- FOOTER --- */
.site-footer {
text-align:center; padding:1.25rem 2rem;
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; }
.site-footer:hover .footer-credits-hint { opacity:1; color:var(--theme-color); }
/* --- QUIZ SYSTEM --- */
.daily-challenge-box {
margin:0 auto 2rem; max-width:680px; padding:1rem 1.5rem;
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;
}
/* --- CREDITS MODAL --- */
#credits-overlay {
position:fixed; inset:0; z-index:2000;
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; }
/* --- SCROLLBAR & SELECTION --- */
::-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 --- */
@keyframes layerReveal {
from { opacity:0; transform:translateY(16px); filter:blur(4px); }
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); }
75% { transform:translateX(-3px); }
}
/* --- MEDIA QUERIES --- */
@media (max-width:768px) {
#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; }
}
/* --- 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; }
.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; }
@@ -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"]::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)); }
+92
View File
@@ -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;
}
+16 -13
View File
@@ -6,7 +6,7 @@ OpenPlanetsMaps is a project that gathers and structures astronomical data (imag
## Context and Hosting
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)
Secondary URL: [openplanetsmaps.alwaysdata.net](http://openplanetsmaps.alwaysdata.net)
## 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).
## 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
- Database: MySQL / MariaDB (generated via phpMyAdmin)
- Frontend: HTML, CSS, JavaScript
- Packaging: Electron Packager
- CI/CD: GitHub Actions
- Data format: JSON
## 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:
- **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.
## 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.
- 📱 **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.
View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

+5 -14
View File
@@ -1,12 +1,9 @@
<?php
/* --- SESSION & AUTHENTICATION --- */
session_start();
$config = require_once './config.php';
$error = '';
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;
header('Location: admin.php');
exit;
@@ -21,14 +18,12 @@ if (isset($_GET['logout'])) {
exit;
}
/* --- DATABASE CONFIGURATION --- */
$host = $config['host'];
$dbname = $config['dbname'];
$db_user = $config['username'];
$db_pass = $config['password'];
$host = '172.22.0.3';
$dbname = 'OpenPlanetsMaps';
$db_user = 'root';
$db_pass = 'admin123';
$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') {
try {
$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>
<html lang="en">
<head>
<!-- --- HEAD & STYLES --- -->
<meta charset="UTF-8">
<title>Admin Panel - OpenPlanetsMaps</title>
<link rel="stylesheet" href="style.css">
@@ -81,10 +75,8 @@ if (isset($_SESSION['admin_logged_in']) && $_SESSION['admin_logged_in'] === true
</style>
</head>
<body>
<!-- --- BODY & ADMIN PANEL --- -->
<div class="admin-box">
<?php if (!isset($_SESSION['admin_logged_in']) || $_SESSION['admin_logged_in'] !== true): ?>
<!-- --- LOGIN FORM --- -->
<h1>Admin Login</h1>
<?php if ($error): ?><p style="color: #f87171; text-align: center; margin-bottom: 1rem;"><?= $error ?></p><?php endif; ?>
<form method="POST">
@@ -95,7 +87,6 @@ if (isset($_SESSION['admin_logged_in']) && $_SESSION['admin_logged_in'] === true
</form>
<div class="links"><a href="index.html"> Back to site</a></div>
<?php else: ?>
<!-- --- ADD DATA FORM --- -->
<h1>Add a row</h1>
<?= $message ?>
<form method="POST">
Executable
+82
View File
@@ -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()]);
}
-6
View File
@@ -1,10 +1,8 @@
<?php
/* --- SESSION & INITIALIZATION --- */
session_start();
$message_status = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
/* --- FORM PROCESSING --- */
$email = filter_var($_POST['email'], FILTER_SANITIZE_EMAIL);
$subject = htmlspecialchars($_POST['objet']);
$message = htmlspecialchars($_POST['demande']);
@@ -13,7 +11,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$file_path = null;
if (isset($_FILES['televersement']) && $_FILES['televersement']['error'] == UPLOAD_ERR_OK) {
/* --- FILE UPLOAD --- */
$file_tmp_name = $_FILES['televersement']['tmp_name'];
$file_name = $_FILES['televersement']['name'];
$file_size = $_FILES['televersement']['size'];
@@ -47,7 +44,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
}
if (!$has_error) {
/* --- DATABASE INSERTION --- */
try {
$host = '172.22.0.3';
$dbname = 'OpenPlanetsMaps';
@@ -71,13 +67,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
<!DOCTYPE html>
<html lang="fr">
<head>
<!-- --- HEAD --- -->
<meta charset="UTF-8">
<title>Contact - OpenPlanetsMaps</title>
<link rel="stylesheet" href="style.css">
</head>
<body class="page-form">
<!-- --- BODY & FORM --- -->
<div class="admin-box">
<h1>Contact</h1>
<?= $message_status ?>
Executable
+396
View File
@@ -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 &nbsp;&bull;&nbsp; Temperature: -180°C to 430°C &nbsp;&bull;&nbsp; Surface area: 74.8 million km² &nbsp;&bull;&nbsp; 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 &nbsp;&bull;&nbsp; Average temperature: 462°C &nbsp;&bull;&nbsp; Surface area: 460 million km² &nbsp;&bull;&nbsp; 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) &nbsp;&bull;&nbsp; Average temperature: 15°C &nbsp;&bull;&nbsp; Surface area: 510 million km² &nbsp;&bull;&nbsp; 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 &nbsp;&bull;&nbsp; Average temperature: -63°C &nbsp;&bull;&nbsp; Surface area: 144.8 million km² &nbsp;&bull;&nbsp; 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 &nbsp;&bull;&nbsp; Average temperature: -110°C &nbsp;&bull;&nbsp; Surface area: 61.4 billion km² &nbsp;&bull;&nbsp; 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 &nbsp;&bull;&nbsp; Average temperature: -140°C &nbsp;&bull;&nbsp; Surface area: 42.7 billion km² &nbsp;&bull;&nbsp; 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 &nbsp;&bull;&nbsp; Average temperature: -195°C &nbsp;&bull;&nbsp; Surface area: 8.1 billion km² &nbsp;&bull;&nbsp; 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 &nbsp;&bull;&nbsp; Average temperature: -200°C &nbsp;&bull;&nbsp; Surface area: 7.6 billion km² &nbsp;&bull;&nbsp; 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&amp;utm_campaign=share-popup&amp;utm_content=7556485516804d0db3960b834e4b3f98" target="_blank" rel="nofollow"> Photorealistic Sun </a> by <a href="https://sketchfab.com/cesar_salcedo?utm_medium=embed&amp;utm_campaign=share-popup&amp;utm_content=7556485516804d0db3960b834e4b3f98" target="_blank" rel="nofollow"> Cesar Salcedo CG </a> on <a href="https://sketchfab.com?utm_medium=embed&amp;utm_campaign=share-popup&amp;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 &nbsp;&bull;&nbsp; Surface temperature: 5,500°C &nbsp;&bull;&nbsp; Distance to Earth: 150 million km (1 AU) &nbsp;&bull;&nbsp; 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&amp;utm_campaign=share-popup&amp;utm_content=870de693475d436c8e925ab0bcda4ca4" target="_blank" rel="nofollow"> Moon </a> by <a href="https://sketchfab.com/miekeroth?utm_medium=embed&amp;utm_campaign=share-popup&amp;utm_content=870de693475d436c8e925ab0bcda4ca4" target="_blank" rel="nofollow"> Mieke Roth </a> on <a href="https://sketchfab.com?utm_medium=embed&amp;utm_campaign=share-popup&amp;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 &nbsp;&bull;&nbsp; Temperature: -173°C to 127°C &nbsp;&bull;&nbsp; Gravity: 1.62 m/s² &nbsp;&bull;&nbsp; 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">
&copy; 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>
Executable
+401
View File
@@ -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);
});
}
});
Executable
+593
View File
@@ -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)); }
+101
View File
@@ -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
+2
View File
@@ -0,0 +1,2 @@
/build/*
!/build/.npmkeep
+54
View File
@@ -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")
}
+19
View File
@@ -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()
}
+21
View File
@@ -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());
}
}
+41
View File
@@ -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 {}
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

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>
Binary file not shown.

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>
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

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);
}
}
+29
View File
@@ -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
}
+3
View File
@@ -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')
+22
View File
@@ -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
Binary file not shown.
+7
View File
@@ -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
Vendored Executable
+251
View File
@@ -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" "$@"
+94
View File
@@ -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
+5
View File
@@ -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'
+16
View File
@@ -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'
}
+20
View File
@@ -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
}
+16
View File
@@ -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"
}
}
}
+28
View File
@@ -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();
});
-31
View File
@@ -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.
+13
View File
@@ -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
+376
View File
@@ -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>
+49
View File
@@ -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)
}
}
Binary file not shown.

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"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

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>
+19
View File
@@ -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>
+51
View File
@@ -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>
+9
View File
@@ -0,0 +1,9 @@
.DS_Store
/.build
/Packages
/*.xcodeproj
xcuserdata/
DerivedData/
.swiftpm/config/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc
+25
View File
@@ -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")
]
)
]
)

Some files were not shown because too many files have changed in this diff Show More