share + pwa + fixes
This commit is contained in:
@ -39,7 +39,7 @@ if ( ! defined( 'CONFIG_DIRECTORY' ) ) {
|
||||
define( 'CANARY_SECURE_HASH', 'd73ed7591a30f0ca7d686a0e780f0d05' );
|
||||
# Tempus Project Core
|
||||
define( 'APP_NAME', 'The Tempus Project');
|
||||
define( 'TP_DEFAULT_LOGO', 'images/logo.png');
|
||||
define( 'TP_DEFAULT_LOGO', 'images/logoWhite.png');
|
||||
// Check
|
||||
define( 'MINIMUM_PHP_VERSION', 8.1);
|
||||
// Cookies
|
||||
|
@ -76,25 +76,6 @@ class Images extends AdminController {
|
||||
Views::view( 'admin.images.upload' );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private function getFolderObject( $folder, $subdirs = '' ) {
|
||||
$names = explode( DIRECTORY_SEPARATOR, $folder );
|
||||
$folderName = array_pop( $names );
|
||||
@ -155,28 +136,6 @@ class Images extends AdminController {
|
||||
return $dirs;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
self::$title = 'Admin - Images';
|
||||
@ -204,25 +163,6 @@ class Images extends AdminController {
|
||||
Debug::error( 'There was an error with your upload.');
|
||||
Issues::add( 'error', [ 'There was an error with your upload.' => Check::userErrors() ] );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// if ( self::$token->create(
|
||||
// Input::post( 'name' ),
|
||||
// Input::post( 'notes' ),
|
||||
// Input::post( 'token_type' )
|
||||
// ) ) {
|
||||
// Session::flash( 'success', 'Token Created' );
|
||||
// Redirect::to( 'admin/images' );
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
Views::view( 'admin.images.create' );
|
||||
}
|
||||
@ -261,7 +201,6 @@ class Images extends AdminController {
|
||||
}
|
||||
|
||||
public function rename() {
|
||||
|
||||
if ( ! Input::exists( 'fileLocation' ) ) {
|
||||
Session::flash( 'warning', 'Unknown image.' );
|
||||
Redirect::to( 'admin/images' );
|
||||
@ -274,7 +213,6 @@ class Images extends AdminController {
|
||||
Issues::add( 'error', [ 'There was an error renaming the image.' => Check::userErrors() ] );
|
||||
} else {
|
||||
$result = $this->renameFile( Input::post( 'filelocation' ), Input::post( 'newname' ) );
|
||||
|
||||
if ( ! empty( $result ) ) {
|
||||
Session::flash( 'success', 'Image has been renamed.' );
|
||||
Redirect::to( 'admin/images' );
|
||||
|
@ -8,6 +8,14 @@
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
.context-popover {
|
||||
background-color: #383838;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.context-popover .popover-header {
|
||||
background-color: #2c2c2c;
|
||||
}
|
||||
|
||||
.context-main-border {
|
||||
border-color: #f5f5f5!important;
|
||||
|
@ -8,6 +8,40 @@
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
.facebook {
|
||||
border-color: #1877F2 !important; /* Facebook Blue */
|
||||
color: #1877F2 !important;
|
||||
}
|
||||
|
||||
.x-black {
|
||||
border-color: #000000 !important; /* X (formerly Twitter) Black */
|
||||
color: #000000 !important;
|
||||
}
|
||||
|
||||
.reddit {
|
||||
border-color: #FF4500 !important; /* Reddit Orange */
|
||||
color: #FF4500 !important;
|
||||
}
|
||||
|
||||
.opera {
|
||||
border-color: #FF1B2D !important; /* Opera Red */
|
||||
color: #FF1B2D !important;
|
||||
}
|
||||
|
||||
.firefox {
|
||||
border-color: #FF7139 !important; /* Firefox Orange */
|
||||
color: #FF7139 !important;
|
||||
}
|
||||
|
||||
.edge {
|
||||
border-color: #0078D7 !important; /* Microsoft Edge Blue */
|
||||
color: #0078D7 !important;
|
||||
}
|
||||
|
||||
.safari {
|
||||
border-color: #0B78E3 !important; /* Safari Blue */
|
||||
color: #0B78E3 !important;
|
||||
}
|
||||
|
||||
.context-main-border {
|
||||
border-color: #1e1e1e!important;
|
||||
|
@ -8,6 +8,94 @@
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
/**
|
||||
* Progressive Web-App
|
||||
**/
|
||||
let deferredPrompt;
|
||||
const installPrompt = document.getElementById("install-prompt");
|
||||
const chromeMessage = document.getElementById("chrome-install-message");
|
||||
const iosMessage = document.getElementById("ios-install-message");
|
||||
const installButton = document.getElementById("install-button");
|
||||
const dismissButton = document.querySelector("#install-prompt .btn-close");
|
||||
|
||||
// Check if the user previously dismissed the prompt
|
||||
if ( ! localStorage.getItem("pwaInstallDismissed") ) {
|
||||
window.addEventListener("beforeinstallprompt", (event) => {
|
||||
event.preventDefault();
|
||||
deferredPrompt = event;
|
||||
installPrompt.classList.remove("d-none");
|
||||
installPrompt.classList.add("d-block"); // Show the alert
|
||||
chromeMessage.classList.remove("d-none");
|
||||
chromeMessage.classList.add("d-block"); // Show the prompt
|
||||
});
|
||||
|
||||
if ( isIos() && ! isInStandaloneMode() ) {
|
||||
installPrompt.classList.remove("d-none");
|
||||
installPrompt.classList.add("d-block"); // Show the alert
|
||||
iosMessage.classList.remove("d-none");
|
||||
iosMessage.classList.add("d-block"); // Show the prompt
|
||||
}
|
||||
}
|
||||
|
||||
// ios REQUIRES a service worker
|
||||
if ( 'serviceWorker' in navigator ) {
|
||||
navigator.serviceWorker.register('app/js/sw.js')
|
||||
.then(() => console.log('Service Worker Registered'));
|
||||
}
|
||||
// self.addEventListener('install', () => self.skipWaiting());
|
||||
// self.addEventListener('activate', () => self.clients.claim());
|
||||
// self.addEventListener('fetch', () => {}); // No file interception
|
||||
|
||||
// Handle Install Button Click
|
||||
if ( installButton ) {
|
||||
installButton.addEventListener("click", async () => {
|
||||
if ( deferredPrompt ) {
|
||||
deferredPrompt.prompt();
|
||||
const { outcome } = await deferredPrompt.userChoice;
|
||||
|
||||
if (outcome === "dismissed") {
|
||||
setInstallDismissed(); // Store that the user dismissed the prompt
|
||||
}
|
||||
|
||||
deferredPrompt = null; // Reset prompt
|
||||
installPrompt.classList.remove("d-block");
|
||||
installPrompt.classList.add("d-none");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Handle Close Button Click
|
||||
if ( dismissButton ) {
|
||||
dismissButton.addEventListener("click", () => {
|
||||
setInstallDismissed(); // Store that the user dismissed the prompt
|
||||
});
|
||||
}
|
||||
|
||||
// Function to remember user choice for 7 days
|
||||
function setInstallDismissed() {
|
||||
localStorage.setItem("pwaInstallDismissed", Date.now() + 7 * 24 * 60 * 60 * 1000);
|
||||
installPrompt.classList.remove("d-block"); // Hide the prompt
|
||||
installPrompt.classList.add("d-none");
|
||||
}
|
||||
|
||||
// Check if the 7-day period has passed
|
||||
if (localStorage.getItem("pwaInstallDismissed")) {
|
||||
const dismissUntil = parseInt(localStorage.getItem("pwaInstallDismissed"), 10);
|
||||
if (Date.now() < dismissUntil) {
|
||||
//
|
||||
} else {
|
||||
localStorage.removeItem("pwaInstallDismissed"); // Reset after 7 days
|
||||
}
|
||||
}
|
||||
|
||||
function isIos() {
|
||||
return /iphone|ipad|ipod/i.test(navigator.userAgent);
|
||||
}
|
||||
|
||||
function isInStandaloneMode() {
|
||||
return window.matchMedia('(display-mode: standalone)').matches || window.navigator.standalone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatically selects/de-selects all check boxes associated with that field
|
||||
**/
|
||||
@ -215,6 +303,8 @@ document.querySelectorAll('[data-bs-toggle="collapse"]').forEach(button => {
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
var popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'));
|
||||
var popoverList = popoverTriggerList.map(function (popoverTriggerEl) {
|
||||
return new bootstrap.Popover(popoverTriggerEl);
|
||||
return new bootstrap.Popover(popoverTriggerEl, {
|
||||
customClass: 'context-popover',
|
||||
});
|
||||
});
|
||||
});
|
1
app/js/sw.js
Normal file
1
app/js/sw.js
Normal file
@ -0,0 +1 @@
|
||||
self.addEventListener('fetch', () => {});
|
@ -59,7 +59,7 @@ class Sessions extends DatabaseModel {
|
||||
public function checkSession( $sessionID ) {
|
||||
$user = new User;
|
||||
// @todo lets put this on some sort of realistic checking regime other than check everything every time
|
||||
if ( $sessionID == false ) {
|
||||
if ( empty( $sessionID ) ) {
|
||||
Debug::log( 'sessionID false' );
|
||||
return false;
|
||||
}
|
||||
|
@ -19,6 +19,15 @@ use TheTempusProject\Houdini\Classes\Components;
|
||||
use TheTempusProject\Bedrock\Classes\Config;
|
||||
use TheTempusProject\Bedrock\Functions\Input;
|
||||
use TheTempusProject\TheTempusProject as App;
|
||||
use Endroid\QrCode\Builder\Builder;
|
||||
use Endroid\QrCode\Encoding\Encoding;
|
||||
use Endroid\QrCode\ErrorCorrectionLevel;
|
||||
use Endroid\QrCode\Label\LabelAlignment;
|
||||
use Endroid\QrCode\Label\Font\OpenSans;
|
||||
use Endroid\QrCode\RoundBlockSizeMode;
|
||||
use Endroid\QrCode\Writer\PngWriter;
|
||||
use TheTempusProject\Hermes\Functions\Route as Routes;
|
||||
use TheTempusProject\Canary\Bin\Canary as Debug;
|
||||
|
||||
class DefaultLoader extends Loader {
|
||||
private static $loaded = false;
|
||||
@ -41,12 +50,61 @@ class DefaultLoader extends Loader {
|
||||
}
|
||||
$this->addJs( '<script language="JavaScript" crossorigin="anonymous" type="text/javascript" src="{ROOT_URL}app/js/main.js"></script>' );
|
||||
Components::setIfNull( 'LOGO', Config::getValue( 'main/logo' ) ?? TP_DEFAULT_LOGO );
|
||||
|
||||
if ( ! empty( Config::getValue( 'share/enabled' ) ) ) {
|
||||
$currentUrl = Routes::getAddress() . Input::get( 'url' );
|
||||
$folder = IMAGE_DIRECTORY . 'qr-codes' . DIRECTORY_SEPARATOR ;
|
||||
$filename = md5( $currentUrl ) . '.png';
|
||||
|
||||
if ( ! file_exists( $folder ) ) {
|
||||
Debug::Info( 'Creating Directory because it does not exist' );
|
||||
mkdir( $folder, 0777, true );
|
||||
}
|
||||
if ( ! empty( Config::getValue( 'share/qr' ) ) ) {
|
||||
if ( ! file_exists( $folder . $filename ) ) {
|
||||
Debug::Info( 'Creating qr-image because it does not exist' );
|
||||
$builder = new Builder(
|
||||
writer: new PngWriter(),
|
||||
writerOptions: [],
|
||||
validateResult: false,
|
||||
data: Routes::getAddress() . Input::get( 'url' ),
|
||||
encoding: new Encoding('UTF-8'),
|
||||
errorCorrectionLevel: ErrorCorrectionLevel::High,
|
||||
size: 200,
|
||||
margin: 10,
|
||||
roundBlockSizeMode: RoundBlockSizeMode::Margin,
|
||||
logoPath: APP_ROOT_DIRECTORY . DIRECTORY_SEPARATOR . Config::getValue( 'main/logo' ),
|
||||
logoResizeToWidth: 30,
|
||||
logoPunchoutBackground: true,
|
||||
labelText: Config::getValue( 'main/name' ),
|
||||
labelFont: new OpenSans(14),
|
||||
labelAlignment: LabelAlignment::Center
|
||||
);
|
||||
$result = $builder->build();
|
||||
$result->saveToFile( $folder . $filename );
|
||||
}
|
||||
Components::set( 'QR_CODE','<img src="{ROOT_URL}images/qr-codes/' . $filename . '" alt="QR Code" class="img-fluid mb-2">' );
|
||||
} else {
|
||||
Components::setIfNull( 'QR_CODE', '' );
|
||||
}
|
||||
Components::setIfNull( 'SHARE_IMAGE', Views::simpleView( 'footer.share' ) );
|
||||
} else {
|
||||
Components::setIfNull( 'SHARE_IMAGE', '' );
|
||||
}
|
||||
|
||||
if ( ! empty( Config::getValue( 'main/pwa' ) ) ) {
|
||||
Components::setIfNull( 'PWA', Views::simpleView( 'pwa') );
|
||||
} else {
|
||||
Components::setIfNull( 'PWA', '' );
|
||||
}
|
||||
|
||||
Components::setIfNull( 'COPY', Views::simpleView( 'footer.copy') );
|
||||
Components::setIfNull( 'SOCIAL', Views::simpleView( 'footer.social') );
|
||||
Components::prepend( 'FOOTER_LEFT', Views::simpleView( 'footer.left', Navigation::getMenuLinks( App::CONTACT_FOOTER_MENU_NAME ) ) );
|
||||
Components::prepend( 'FOOTER_CENTER', Views::simpleView( 'footer.center', Navigation::getMenuLinks( App::INFO_FOOTER_MENU_NAME ) ) );
|
||||
Components::prepend( 'FOOTER_RIGHT', Views::simpleView( 'footer.right') );
|
||||
Components::setIfNull( 'FOOT', Views::simpleView( 'footer.container') );
|
||||
|
||||
/**
|
||||
* Top-Nav
|
||||
*/
|
||||
|
@ -28,7 +28,12 @@
|
||||
{AUTHOR}
|
||||
{ROBOT}
|
||||
<link rel="icon" href="{ROOT_URL}images/favicon.ico" sizes="32x32">
|
||||
<!-- Apple PWA -->
|
||||
<link rel="apple-touch-icon" href="{ROOT_URL}images/apple-touch-icon.png"><!-- 180×180 -->
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||
<meta name="apple-mobile-web-app-title" content="{SITENAME}">
|
||||
<!-- PWA -->
|
||||
<link rel="manifest" href="{ROOT_URL}manifest.webmanifest">
|
||||
<!-- Required CSS -->
|
||||
<!-- <link rel="stylesheet" href="{FONT_AWESOME_URL}fontawesome.min.css" crossorigin="anonymous"> -->
|
||||
@ -91,6 +96,7 @@
|
||||
</div>
|
||||
</div>
|
||||
{/ISSUES}
|
||||
{PWA}
|
||||
<!-- Main Page Content -->
|
||||
{CONTENT}
|
||||
</div>
|
||||
|
@ -56,8 +56,8 @@
|
||||
<div id="collapse3" class="accordion-collapse collapse" aria-labelledby="generalHeading3" data-bs-parent="#generalAccordion">
|
||||
<div class="accordion-body context-main context-other-bg" id="general3">
|
||||
<span class="text-lead text-primary">
|
||||
{SITENAME} is open source and available free of charge through <a href="{ROOT_URL}libraries/ttp/git" class="text-decoration-none">GitLab</a> and <a href="{ROOT_URL}libraries/ttp/packagist" class="text-decoration-none">Packagist</a>.
|
||||
The developer behind the project is <a href="https://joeykimsey.com/" class="text-decoration-none">Joey Kimsey</a> and he can be contacted through his website for development services.
|
||||
{SITENAME} is open source and available free of charge through <a href="{ROOT_URL}libraries/ttp/git" class="text-decoration-none context-main">GitLab</a> and <a href="{ROOT_URL}libraries/ttp/packagist" class="text-decoration-none context-main">Packagist</a>.
|
||||
The developer behind the project is <a href="https://joeykimsey.com/" class="text-decoration-none context-main">Joey Kimsey</a> and he can be contacted through his website for development services.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,4 +1,5 @@
|
||||
<div class="col-12 col-sm-6 col-md-3 col-lg-2 mb-3 text-center">
|
||||
{SHARE_IMAGE}
|
||||
<h5>Dark Mode</h5>
|
||||
<div class="material-switch px-4 mt-2">
|
||||
<input name="dark-mode-toggle" type="checkbox" id="dark-mode-toggle" class="form-check-input">
|
||||
|
17
app/views/footer/share.html
Normal file
17
app/views/footer/share.html
Normal file
@ -0,0 +1,17 @@
|
||||
<div class="text-center mb-3">
|
||||
<h5 class="mb-3">Share</h5>
|
||||
<div class="px-4 mt-2">
|
||||
<!-- Share Button (visible only on medium+ screens) -->
|
||||
<button type="button" class="btn btn-outline-primary"
|
||||
data-bs-toggle="popover" data-bs-html="true" title="Share" data-bs-placement="top" data-bs-trigger="focus"
|
||||
data-bs-content='
|
||||
{QR_CODE}
|
||||
<div class="d-flex justify-content-between">
|
||||
<a href="https://www.reddit.com/submit?type=LINK&url={CURRENT_URL_SAFE}" target="_blank" class="mx-1 btn btn-lg reddit"><i class="fa-brands fa-fw fa-reddit"></i></a>
|
||||
<a href="https://www.facebook.com/sharer/sharer.php?u={CURRENT_URL_SAFE}" target="_blank" class="mx-1 btn btn-lg facebook"><i class="fa-brands fa-fw fa-facebook"></i></a>
|
||||
<a href="https://x.com/intent/tweet?url={CURRENT_URL_SAFE}" target="_blank" class="mx-1 btn btn-lg x-black"><i class="fa-brands fa-fw fa-x"></i></a>
|
||||
</div>'>
|
||||
Share
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
@ -101,21 +101,21 @@
|
||||
<i class="fa-solid fa-inbox fa-3x"></i>
|
||||
<div class="ps-3">
|
||||
<h3 class="fw-bold mb-0 fs-4">Subscribe</h3>
|
||||
<p>Building your list should always be a part of your application and services and it made as simple as can be with this plugin.</p>
|
||||
<p>Building your list should always be a part of your business. Our subscriptions plugin makes it as simple as can be.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col d-flex align-items-start">
|
||||
<i class="fa-solid fa-list fa-3x"></i>
|
||||
<div class="ps-3">
|
||||
<h3 class="fw-bold mb-0 fs-4">WIP (Work in Progress)</h3>
|
||||
<p>A light-weight and simple plugin that allows you to keep a running list of works in progress to share with site visitors..</p>
|
||||
<p>A light-weight and simple plugin that allows you to keep a running list of work in progress to share with site visitors.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col d-flex align-items-start">
|
||||
<i class="fa-brands fa-stripe fa-3x"></i>
|
||||
<div class="ps-3">
|
||||
<h3 class="fw-bold mb-0 fs-4">Memberships / Payments</h3>
|
||||
<p>Our membership plugin integrates with Stripe to allow incredibly simple membership setup and can be easily expanded to sell any of your products.</p>
|
||||
<p>Our membership plugin integrates with Stripe to allow incredibly simple membership setup and can be easily expanded to sell any of your products. We also have a donations integration with stripe to allow you to accept donation right from the app.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
18
app/views/pwa.html
Normal file
18
app/views/pwa.html
Normal file
@ -0,0 +1,18 @@
|
||||
<div class="container pt-4 d-none" id="install-prompt">
|
||||
<div class="row">
|
||||
<div class="alert alert-success alert-dismissible w-100 d-none" role="alert" id="chrome-install-message">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
{SITENAME} is now available as a Progressive Web App, click the button to install now.
|
||||
<button class="btn btn-md btn-outline-primary mx-2" id="install-button">Install App</button>
|
||||
</div>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-success alert-dismissible w-100 d-none" role="alert" id="ios-install-message">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
{SITENAME} is now available as a Progressive-Web-App, tap the share icon and then "Add to Home Screen".
|
||||
</div>
|
||||
<img src="/images/share-icon.png" class="iimg-fluid">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
Reference in New Issue
Block a user