<?php
/**
* Datei: stonebreaker-pwa.php
* Version: 1.7 (Mit Auto-Redirect für eingeloggte User)
* Beschreibung: PWA Management inkl. Weiterleitung beim App-Start.
*/

if ( ! defined( ‘ABSPATH’ ) ) { exit; }

class Stonebreaker_PWA_Manager {

public function __construct() {
add_action( ‘admin_menu’, array( $this, ‘add_admin_menu’ ) );
add_action( ‘admin_init’, array( $this, ‘register_settings’ ) );

add_action( ‘wp_head’, array( $this, ‘add_pwa_headers’ ) );
add_action( ‘wp_footer’, array( $this, ‘register_service_worker’ ) );
add_action( ‘wp_footer’, array( $this, ‘render_login_popup’ ), 100 );

add_action( ‘init’, array( $this, ‘serve_dynamic_files’ ) );

// NEU: Weiterleitung beim App-Start, wenn schon eingeloggt
add_action( ‘template_redirect’, array( $this, ‘handle_already_logged_in’ ) );
}

// — NEU: AUTO-REDIRECT BEIM ÖFFNEN —
public function handle_already_logged_in() {
// Wir prüfen: Kommt der Aufruf von der App (Start-Icon)?
if ( isset($_GET[‘app_mode’]) && $_GET[‘app_mode’] === ‘true’ ) {

// Ist der User schon eingeloggt?
if ( is_user_logged_in() ) {

// Wohin sollen mobile User?
$mobile_target = get_option(‘sb_pwa_redirect_mobile’);

// Wenn ein Ziel definiert ist -> Sofort hin da!
if ( ! empty($mobile_target) ) {
wp_redirect( $mobile_target );
exit;
}
}
}
}

// — 1. BACKEND EINSTELLUNGEN —
public function add_admin_menu() {
add_submenu_page(‘stonebreaker-app’,’App Einstellungen (PWA)’,’App / PWA’,’manage_options’,’stonebreaker-pwa’,array( $this, ‘render_settings_page’ ));
}

public function register_settings() {
register_setting( ‘sb_pwa_group’, ‘sb_pwa_name’ );
register_setting( ‘sb_pwa_group’, ‘sb_pwa_short_name’ );
register_setting( ‘sb_pwa_group’, ‘sb_pwa_icon_url’ );
register_setting( ‘sb_pwa_group’, ‘sb_pwa_theme_color’ );
register_setting( ‘sb_pwa_group’, ‘sb_pwa_bg_color’ );
register_setting( ‘sb_pwa_group’, ‘sb_pwa_bg_image’ );
register_setting( ‘sb_pwa_group’, ‘sb_pwa_redirect_mobile’ );
register_setting( ‘sb_pwa_group’, ‘sb_pwa_redirect_desktop’ );
}

public function render_settings_page() {
?>
<div class=”wrap”>
<h1>App & PWA Einstellungen</h1>
<form method=”post” action=”options.php”>
<?php settings_fields( ‘sb_pwa_group’ ); ?>
<table class=”form-table”>
<tr><th>App Name (Lang)</th><td><input type=”text” name=”sb_pwa_name” value=”<?php echo esc_attr(get_option(‘sb_pwa_name’, get_bloginfo(‘name’))); ?>” class=”regular-text”></td></tr>
<tr><th>App Name (Kurz)</th><td><input type=”text” name=”sb_pwa_short_name” value=”<?php echo esc_attr(get_option(‘sb_pwa_short_name’, ‘Stonebreaker’)); ?>” class=”regular-text”></td></tr>
<tr><th>App Icon URL</th><td><input type=”text” name=”sb_pwa_icon_url” value=”<?php echo esc_attr(get_option(‘sb_pwa_icon_url’)); ?>” class=”large-text” placeholder=”https://…”><p class=”description”>Pfad zu einem PNG-Bild (mind. 512×512 Pixel). Wird für das Homescreen-Symbol genutzt.</p></td></tr>
<tr><th>Login Hintergrundbild</th><td><input type=”text” name=”sb_pwa_bg_image” value=”<?php echo esc_attr(get_option(‘sb_pwa_bg_image’)); ?>” class=”large-text”><p class=”description”>Hintergrundbild nur für das Login-Popup.</p></td></tr>

<tr style=”background:#e0f7fa;”>
<th>Weiterleitung (Mobil / App)</th>
<td>
<input type=”text” name=”sb_pwa_redirect_mobile” value=”<?php echo esc_attr(get_option(‘sb_pwa_redirect_mobile’)); ?>” class=”large-text” placeholder=”https://deine-seite.de/dashboard/”>
<p class=”description”><strong>Wichtig:</strong> Hierhin werden App-Nutzer geleitet (nach Login UND beim Öffnen der App).</p>
</td>
</tr>
<tr style=”background:#e0f7fa;”>
<th>Weiterleitung (PC / Desktop)</th>
<td>
<input type=”text” name=”sb_pwa_redirect_desktop” value=”<?php echo esc_attr(get_option(‘sb_pwa_redirect_desktop’)); ?>” class=”large-text” placeholder=”https://deine-seite.de/”>
<p class=”description”>Ziel für normale Desktop-Computer.</p>
</td>
</tr>

<tr>
<th>Design Farben</th>
<td>
<label>Theme Color: <input type=”color” name=”sb_pwa_theme_color” value=”<?php echo esc_attr(get_option(‘sb_pwa_theme_color’, ‘#0073aa’)); ?>”></label><br><br>
<label>Ladescreen Farbe: <input type=”color” name=”sb_pwa_bg_color” value=”<?php echo esc_attr(get_option(‘sb_pwa_bg_color’, ‘#ffffff’)); ?>”></label>
</td>
</tr>
</table>
<?php submit_button(); ?>
</form>
</div>
<?php
}

// — 2. FRONTEND HEADER —
public function add_pwa_headers() {
$manifest_url = site_url(‘/?sb_pwa=manifest’);
$theme_color = get_option(‘sb_pwa_theme_color’, ‘#0073aa’);
$icon = get_option(‘sb_pwa_icon_url’);

echo ‘<link rel=”manifest” href=”‘ . esc_url($manifest_url) . ‘”>’ . “\n”;
echo ‘<meta name=”theme-color” content=”‘ . esc_attr($theme_color) . ‘”>’ . “\n”;
echo ‘<meta name=”apple-mobile-web-app-capable” content=”yes”>’ . “\n”;
echo ‘<meta name=”apple-mobile-web-app-status-bar-style” content=”black-translucent”>’ . “\n”;
if($icon) echo ‘<link rel=”apple-touch-icon” href=”‘ . esc_url($icon) . ‘”>’ . “\n”;
}

// — 3. LOGIN POPUP —
public function render_login_popup() {
if ( is_user_logged_in() ) return;

$bg_image = get_option(‘sb_pwa_bg_image’);

// Logik: Welches Gerät?
if ( wp_is_mobile() ) {
$redirect_to = get_option(‘sb_pwa_redirect_mobile’) ?: home_url();
} else {
$redirect_to = get_option(‘sb_pwa_redirect_desktop’) ?: home_url();
}

// App Mode Prüfung
$is_app_mode_php = (isset($_GET[‘app_mode’]) && $_GET[‘app_mode’] == ‘true’);

?>
<style>
#sb-pwa-login-overlay {
position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 999999;
background-color: #f0f0f0;
<?php if($bg_image): ?>
background: url(‘<?php echo esc_url($bg_image); ?>’) no-repeat center center fixed;
background-size: cover;
<?php endif; ?>
justify-content: center; align-items: center;
backdrop-filter: blur(4px);
display: none;
}
.sb-login-box {
background: rgba(255, 255, 255, 0.98); padding: 60px 50px; border-radius: 12px;
box-shadow: 0 25px 60px rgba(0,0,0,0.5); width: 95%; max-width: 800px; text-align: center;
animation: sbFadeIn 0.4s ease-out;
}
@keyframes sbFadeIn { from { opacity: 0; transform: scale(0.95); } to { opacity: 1; transform: scale(1); } }
.sb-login-box h2 { margin-top: 0; color: #333; font-size: 36px; margin-bottom: 15px; }
.sb-login-box p { color: #666; margin-bottom: 40px; font-size: 20px; }
.sb-login-box .login-username, .sb-login-box .login-password { margin-bottom: 25px; text-align: left; }
.sb-login-box label { font-weight: bold; font-size: 18px; color: #333; display: block; margin-bottom: 10px; }
.sb-login-box input[type=”text”], .sb-login-box input[type=”password”] { width: 100%; padding: 18px; border: 1px solid #ccc; border-radius: 8px; font-size: 20px; background:#fdfdfd; box-sizing: border-box; height: auto; }
.sb-login-box .login-submit { margin-top: 40px; }
.sb-login-box input[type=”submit”] { background: <?php echo get_option(‘sb_pwa_theme_color’, ‘#0073aa’); ?>; color: #fff; border: none; padding: 20px 0; width: 100%; border-radius: 8px; font-size: 24px; font-weight: bold; cursor: pointer; transition: opacity 0.2s; text-transform: uppercase; letter-spacing: 1px; }
.sb-login-box input[type=”submit”]:hover { opacity: 0.9; }
.sb-login-box .login-remember { margin-top: 25px; font-size: 16px; text-align: left; color:#555; }
.sb-login-box input[type=”checkbox”] { transform: scale(1.5); margin-right: 10px; }
</style>

<div id=”sb-pwa-login-overlay”>
<div class=”sb-login-box”>
<h2>Willkommen</h2>
<p>Bitte melde dich an.</p>
<?php
wp_login_form(array(
‘echo’ => true,
‘redirect’ => $redirect_to,
‘remember’ => true,
‘value_remember’ => true,
‘label_username’ => ‘Benutzername / E-Mail’,
‘label_password’ => ‘Passwort’
));
?>
</div>
</div>

<script>
document.addEventListener(“DOMContentLoaded”, function() {
var isStandalone = window.matchMedia(‘(display-mode: standalone)’).matches || window.navigator.standalone === true;
var isAppModeParam = window.location.search.includes(‘app_mode=true’);

if ( isStandalone || isAppModeParam ) {
var overlay = document.getElementById(‘sb-pwa-login-overlay’);
if(overlay) {
overlay.style.display = ‘flex’;
document.body.style.overflow = ‘hidden’;
}
}
});
</script>
<?php
}

// — 4. SERVICE WORKER —
public function register_service_worker() {
$sw_url = site_url(‘/?sb_pwa=sw’);
echo “<script>if(‘serviceWorker’ in navigator){window.addEventListener(‘load’,function(){navigator.serviceWorker.register(‘$sw_url’);});}</script>”;
}

// — 5. VIRTUELLE DATEIEN —
public function serve_dynamic_files() {
if ( ! isset( $_GET[‘sb_pwa’] ) ) return;
$mode = $_GET[‘sb_pwa’];

if ( $mode === ‘manifest’ ) {
header(‘Content-Type: application/json’);
$name = get_option(‘sb_pwa_name’, get_bloginfo(‘name’));
$short = get_option(‘sb_pwa_short_name’, ‘Stonebreaker’);
$theme = get_option(‘sb_pwa_theme_color’, ‘#0073aa’);
$bg = get_option(‘sb_pwa_bg_color’, ‘#ffffff’);
$icon_url = get_option(‘sb_pwa_icon_url’);
$start_url = site_url(‘/?app_mode=true’); // Hierhin startet die App immer

$manifest = array(
‘name’ => $name,
‘short_name’ => $short,
‘start_url’ => $start_url,
‘display’ => ‘standalone’,
‘background_color’ => $bg,
‘theme_color’ => $theme,
‘icons’ => array()
);

if ( $icon_url ) {
$manifest[‘icons’][] = array(‘src’ => $icon_url, ‘sizes’ => ‘192×192’, ‘type’ => ‘image/png’);
$manifest[‘icons’][] = array(‘src’ => $icon_url, ‘sizes’ => ‘512×512’, ‘type’ => ‘image/png’);
}
echo json_encode($manifest); exit;
}

if ( $mode === ‘sw’ ) {
header(‘Content-Type: application/javascript’);
echo “const CACHE_NAME=’sb-v1′; self.addEventListener(‘install’,(e)=>{self.skipWaiting();}); self.addEventListener(‘activate’,(e)=>{e.waitUntil(clients.claim());}); self.addEventListener(‘fetch’,(e)=>{e.respondWith(fetch(e.request).catch(()=>{return new Response(‘Offline.’);}));});”;
exit;
}
}
}

new Stonebreaker_PWA_Manager();

This entry was posted in Allgemein. Bookmark the permalink.

Comments are closed.