Stuff i guess ?

This commit is contained in:
Lars Behrends
2025-10-31 00:24:17 +01:00
parent db0fd4e728
commit 04140786a7
40 changed files with 5411 additions and 525 deletions

118
public/css/app.css Normal file
View File

@@ -0,0 +1,118 @@
.items,
.item {
flex-flow: row wrap;
}
.items .item,
.item .item {
margin: 20px;
width: 120px;
height: 180px;
overflow: hidden;
box-shadow: 0 5px 10px rgba(0,0,0,0.8);
transform-origin: center top;
transform-style: preserve-3d;
transform: translateZ(0);
transition: 0.3s;
}
.items .item img,
.item .item img {
width: 100%;
min-height: 100%;
}
.items .item figcaption,
.item .item figcaption {
bottom: 0;
left: 0;
right: 0;
padding: 20px;
padding-bottom: 10px;
font-size: 20px;
background: none;
color: #fff;
transform: translateY(100%);
transition: 0.3s;
}
.items .item:after,
.item .item:after {
content: '';
z-index: 10;
width: 200%;
height: 100%;
top: -90%;
left: -20px;
opacity: 0.1;
transform: rotate(45deg);
background: linear-gradient(to top, transparent, #fff 15%, rgba(255,255,255,0.5));
transition: 0.3s;
}
.items .item:hover,
.item .item:hover,
.items .item:focus,
.item .item:focus,
.items .item:active,
.item .item:active {
box-shadow: 0 8px 16px 3px rgba(0,0,0,0.6);
transform: translateY(-3px) scale(1.05) rotateX(15deg);
}
.items .item:hover figcaption,
.item .item:hover figcaption,
.items .item:focus figcaption,
.item .item:focus figcaption,
.items .item:active figcaption,
.item .item:active figcaption {
transform: none;
}
.items .item:hover:after,
.item .item:hover:after,
.items .item:focus:after,
.item .item:focus:after,
.items .item:active:after,
.item .item:active:after {
transform: rotate(25deg);
top: -40%;
opacity: 0.15;
}
.item .article {
overflow: hidden;
width: 350px;
height: 235px;
margin: 20px;
}
.item .article img {
width: 100%;
min-height: 100%;
transition: 0.2s;
}
.item .article figcaption {
font-size: 14px;
text-shadow: 0 1px 0 rgba(51,51,51,0.3);
color: #fff;
left: 0;
right: 0;
top: 0;
bottom: 0;
padding: 40px;
box-shadow: 0 0 2px rgba(0,0,0,0.2);
background: rgba(6,18,53,0.6);
opacity: 0;
transform: scale(1.15);
transition: 0.2s;
}
.item .article figcaption h3 {
color: #3792e3;
font-size: 16px;
margin-bottom: 0;
font-weight: bold;
}
.item .article:hover img,
.item .article:focus img,
.item .article:active img {
filter: blur(3px);
transform: scale(0.97);
}
.item .article:hover figcaption,
.item .article:focus figcaption,
.item .article:active figcaption {
opacity: 1;
transform: none;
}

View File

@@ -263,13 +263,13 @@ $container->set(\App\Controllers\SettingsController::class, function ($c) {
return new \App\Controllers\SettingsController($c->get(PDO::class), $c->get('view'));
});
// Register PlayniteImportController
$container->set(\App\Controllers\PlayniteImportController::class, function ($c) {
return new \App\Controllers\PlayniteImportController(
$c->get(PDO::class),
$c->get('view'),
$c->get(\App\Services\AuthService::class)
);
// Register API controllers
$container->set(\App\Controllers\Api\PlayniteController::class, function ($c) {
return new \App\Controllers\Api\PlayniteController($c->get(PDO::class));
});
$container->set(\App\Controllers\Api\AuthController::class, function ($c) {
return new \App\Controllers\Api\AuthController($c->get(\App\Services\AuthService::class));
});
// Register PlayniteImportService
@@ -298,6 +298,69 @@ $app = AppFactory::create();
$twig = $container->get('view');
$app->add(TwigMiddleware::create($app, $twig));
// PHP DebugBar Setup (only in development)
if ($_ENV['APP_DEBUG'] === 'true') {
$debugbar = new \DebugBar\StandardDebugBar();
// Set up the debug bar renderer with the correct base URL
$baseUrl = rtrim($app->getBasePath(), '/');
$debugbarRenderer = $debugbar->getJavascriptRenderer($baseUrl . '/phpdebugbar');
// Add DebugBar to Twig globals
$twig->getEnvironment()->addGlobal('debugbarRenderer', $debugbarRenderer);
// Add route to serve DebugBar assets
$app->get('/phpdebugbar/{path:.*}', function ($request, $response, $args) use ($debugbar) {
$debugbarRenderer = $debugbar->getJavascriptRenderer();
$path = $args['path'];
// Serve CSS files
if (preg_match('/\.css$/', $path)) {
$content = file_get_contents($debugbarRenderer->getBasePath() . '/' . $path);
$response->getBody()->write($content);
return $response->withHeader('Content-Type', 'text/css');
}
// Serve JS files
if (preg_match('/\.js$/', $path)) {
$content = file_get_contents($debugbarRenderer->getBasePath() . '/' . $path);
$response->getBody()->write($content);
return $response->withHeader('Content-Type', 'application/javascript');
}
// Serve other assets (fonts, etc.)
$content = @file_get_contents($debugbarRenderer->getBasePath() . '/' . $path);
if ($content !== false) {
$response->getBody()->write($content);
return $response;
}
return $response->withStatus(404);
});
// Add middleware to collect data
$app->add(function ($request, $handler) use ($debugbar) {
// Start timing the request
$debugbar['time']->startMeasure('app', 'Application');
try {
$response = $handler->handle($request);
// Stop timing if it was started
if ($debugbar['time']->hasStartedMeasure('app')) {
$debugbar['time']->stopMeasure('app');
}
return $response;
} catch (\Exception $e) {
// Make sure to stop timing even if an exception occurs
if ($debugbar['time']->hasStartedMeasure('app')) {
$debugbar['time']->stopMeasure('app');
}
throw $e;
}
});
}
// Add Error Middleware
$errorMiddleware = $app->addErrorMiddleware(
$_ENV['APP_DEBUG'] === 'true',
@@ -307,5 +370,6 @@ $errorMiddleware = $app->addErrorMiddleware(
// Register routes
require __DIR__ . '/../routes/web.php';
require __DIR__ . '/../routes/api.php';
$app->run();

View File

@@ -0,0 +1,125 @@
document.addEventListener('DOMContentLoaded', function() {
const videoId = document.getElementById('video-id').value;
const actorSearch = document.getElementById('actor-search');
const actorResults = document.getElementById('actor-results');
const actorsList = document.getElementById('actors-list');
// Debounce search
let searchTimeout;
actorSearch.addEventListener('input', function(e) {
clearTimeout(searchTimeout);
const query = e.target.value.trim();
if (query.length < 2) {
actorResults.innerHTML = '';
actorResults.classList.add('d-none');
return;
}
searchTimeout = setTimeout(() => {
searchActors(query);
}, 300);
});
// Search for actors
function searchActors(query) {
fetch(`/admin/adult-videos/search-actors?q=${encodeURIComponent(query)}`)
.then(response => response.json())
.then(data => {
actorResults.innerHTML = '';
if (data.data && data.data.length > 0) {
data.data.forEach(actor => {
const item = document.createElement('div');
item.className = 'list-group-item list-group-item-action';
item.textContent = actor.name;
item.addEventListener('click', () => addActorToVideo(actor.id, actor.name));
actorResults.appendChild(item);
});
actorResults.classList.remove('d-none');
} else {
const noResults = document.createElement('div');
noResults.className = 'list-group-item';
noResults.textContent = 'No actors found';
actorResults.appendChild(noResults);
actorResults.classList.remove('d-none');
}
});
}
// Add actor to video
function addActorToVideo(actorId, actorName) {
fetch(`/admin/adult-videos/${videoId}/actors`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest'
},
body: JSON.stringify({ actor_id: actorId })
})
.then(response => response.json())
.then(data => {
if (data.success) {
addActorToList(actorId, actorName);
actorSearch.value = '';
actorResults.innerHTML = '';
actorResults.classList.add('d-none');
} else {
alert('Failed to add actor: ' + (data.error || 'Unknown error'));
}
});
}
// Add actor to the UI list
function addActorToList(actorId, actorName) {
const item = document.createElement('div');
item.className = 'd-flex justify-content-between align-items-center mb-2';
item.dataset.actorId = actorId;
item.innerHTML = `
<span>${actorName}</span>
<button type="button" class="btn btn-sm btn-danger remove-actor" data-actor-id="${actorId}">
<i class="fas fa-times"></i> Remove
</button>
`;
actorsList.appendChild(item);
// Add event listener to the remove button
item.querySelector('.remove-actor').addEventListener('click', () => removeActor(actorId, item));
}
// Remove actor from video
function removeActor(actorId, element) {
if (confirm('Are you sure you want to remove this actor?')) {
fetch(`/admin/adult-videos/${videoId}/actors/${actorId}`, {
method: 'DELETE',
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
element.remove();
} else {
alert('Failed to remove actor: ' + (data.error || 'Unknown error'));
}
});
}
}
// Load existing actors
function loadActors() {
fetch(`/admin/adult/${videoId}/actors`)
.then(response => response.json())
.then(data => {
if (data.data && data.data.length > 0) {
data.data.forEach(actor => {
addActorToList(actor.id, actor.name);
});
}
});
}
// Initialize
loadActors();
});