v1.6.25 — intégration IA éditeur, onglet admin IA, corrections CSP #98
@@ -5,6 +5,14 @@ Format : [Keep a Changelog](https://keepachangelog.com/fr/1.0.0/) — versionnag
|
||||
|
||||
---
|
||||
|
||||
## [1.6.20] - 2026-05-16
|
||||
|
||||
### Ajouté
|
||||
- Barre de partage sur les articles publiés : mail, X, LinkedIn, Mastodon, copie de lien, Web Share API mobile (#47)
|
||||
- Déduplication des images uploadées par hardlink si même hash+taille existe déjà dans un autre article (#35)
|
||||
|
||||
---
|
||||
|
||||
## [1.6.19] - 2026-05-16
|
||||
|
||||
### Ajouté
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var bar = document.getElementById('share-bar');
|
||||
if (!bar) { return; }
|
||||
|
||||
var url = bar.getAttribute('data-url') || window.location.href;
|
||||
var title = bar.getAttribute('data-title') || document.title;
|
||||
|
||||
var copyBtn = document.getElementById('share-copy');
|
||||
if (copyBtn) {
|
||||
copyBtn.addEventListener('click', function () {
|
||||
if (!navigator.clipboard) {
|
||||
var ta = document.createElement('textarea');
|
||||
ta.value = url;
|
||||
document.body.appendChild(ta);
|
||||
ta.select();
|
||||
document.execCommand('copy');
|
||||
document.body.removeChild(ta);
|
||||
copyBtn.textContent = 'Copié !';
|
||||
setTimeout(function () { copyBtn.textContent = 'Copier le lien'; }, 2000);
|
||||
return;
|
||||
}
|
||||
navigator.clipboard.writeText(url).then(function () {
|
||||
copyBtn.textContent = 'Copié !';
|
||||
setTimeout(function () { copyBtn.textContent = 'Copier le lien'; }, 2000);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
var nativeBtn = document.getElementById('share-native');
|
||||
if (nativeBtn) {
|
||||
if (navigator.share) {
|
||||
nativeBtn.hidden = false;
|
||||
nativeBtn.addEventListener('click', function () {
|
||||
navigator.share({ title: title, url: url }).catch(function () {});
|
||||
});
|
||||
}
|
||||
}
|
||||
}());
|
||||
+1
-1
@@ -1 +1 @@
|
||||
1.6.19
|
||||
1.6.20
|
||||
|
||||
+10
-1
@@ -1197,7 +1197,16 @@ class ArticleManager
|
||||
$size = filesize($uploadedFile['tmp_name']);
|
||||
$name = "{$hash}-{$size}.{$ext}";
|
||||
$dest = $dir . '/' . $name;
|
||||
if (!rename($uploadedFile['tmp_name'], $dest) && !move_uploaded_file($uploadedFile['tmp_name'], $dest)) {
|
||||
// Déduplication : si ce fichier identique existe déjà dans un autre article, crée un hardlink
|
||||
if (!file_exists($dest)) {
|
||||
$existing = glob($this->dataDir . '/*/files/' . $name);
|
||||
if (!empty($existing) && is_file($existing[0])) {
|
||||
link($existing[0], $dest) || copy($existing[0], $dest);
|
||||
@unlink($uploadedFile['tmp_name']);
|
||||
return $name;
|
||||
}
|
||||
}
|
||||
if (!file_exists($dest) && !rename($uploadedFile['tmp_name'], $dest) && !move_uploaded_file($uploadedFile['tmp_name'], $dest)) {
|
||||
return null;
|
||||
}
|
||||
return $name;
|
||||
|
||||
@@ -163,6 +163,9 @@ $_layoutCurrentCat = trim($_GET['cat'] ?? '');
|
||||
<?php if (isset($reactionStats)): ?>
|
||||
<script src="<?= _av($_pub, 'js/reactions.js') ?>"></script>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($shareBar ?? false)): ?>
|
||||
<script src="<?= _av($_pub, 'js/share.js') ?>" defer></script>
|
||||
<?php endif; ?>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -261,6 +261,28 @@ $hasSources = (!empty($externalLinks) || !empty($files))
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if ($article['published'] ?? false): ?>
|
||||
<?php
|
||||
$_shareUrl = rtrim(defined('APP_URL') ? APP_URL : '', '/') . '/post/' . rawurlencode($article['slug'] ?? '');
|
||||
$_shareTitle = $article['title'] ?? '';
|
||||
?>
|
||||
<div class="d-flex flex-wrap align-items-center gap-2 my-3 py-2 border-top"
|
||||
id="share-bar"
|
||||
data-url="<?= htmlspecialchars($_shareUrl) ?>"
|
||||
data-title="<?= htmlspecialchars($_shareTitle) ?>">
|
||||
<span class="text-muted small me-1">Partager :</span>
|
||||
<a href="mailto:?subject=<?= rawurlencode($_shareTitle) ?>&body=<?= rawurlencode($_shareUrl) ?>"
|
||||
class="btn btn-outline-secondary btn-sm" title="Par e-mail">✉ Mail</a>
|
||||
<a href="https://x.com/intent/tweet?text=<?= rawurlencode($_shareTitle) ?>&url=<?= rawurlencode($_shareUrl) ?>"
|
||||
class="btn btn-outline-secondary btn-sm" target="_blank" rel="noopener noreferrer" title="X / Twitter">X</a>
|
||||
<a href="https://www.linkedin.com/sharing/share-offsite/?url=<?= rawurlencode($_shareUrl) ?>"
|
||||
class="btn btn-outline-secondary btn-sm" target="_blank" rel="noopener noreferrer" title="LinkedIn">in</a>
|
||||
<a href="https://mastodon.social/share?text=<?= rawurlencode($_shareTitle . ' ' . $_shareUrl) ?>"
|
||||
class="btn btn-outline-secondary btn-sm" target="_blank" rel="noopener noreferrer" title="Mastodon">🐘</a>
|
||||
<button type="button" class="btn btn-outline-secondary btn-sm" id="share-copy">Copier le lien</button>
|
||||
<button type="button" class="btn btn-outline-primary btn-sm" id="share-native" hidden>⬆ Partager</button>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php include __DIR__ . '/comments_section.php'; ?>
|
||||
|
||||
@@ -397,6 +419,7 @@ $hasSources = (!empty($externalLinks) || !empty($files))
|
||||
|
||||
<?php
|
||||
$content = ob_get_clean();
|
||||
$shareBar = (bool)($article['published'] ?? false);
|
||||
$title = htmlspecialchars($article['title']);
|
||||
$seoTitle = ($article['seo_title'] ?? '') ?: $article['title'];
|
||||
$ogType = 'article';
|
||||
|
||||
Reference in New Issue
Block a user