New plugins!

- Media BBCode tags
- Use youtube-nocookie.com for YouTube embeds
- Topic muting
This commit is contained in:
snow flurry 2025-03-01 15:04:58 -08:00
parent e4e438ba89
commit 0d2ba42dea
21 changed files with 388 additions and 6 deletions

View file

@ -1,7 +1,10 @@
MODS := \
f9_buttons \
f9_emotes \
f9_theme
f9_theme \
media_bbc \
yt_nocookie \
topic_mute
PKGDIR := $(PWD)/../packages

View file

@ -4172,7 +4172,7 @@ tr[id^='list_news_lists_'] textarea {
}
/* Responsive Youtube embed */
.videocontainer {
.videocontainer, .media-video, .media-audio {
max-width: 560px;
}
.centertext .videocontainer,
@ -4196,11 +4196,15 @@ tr[id^='list_news_lists_'] textarea {
width: 100% !important;
height: 100% !important;
}
.videocontainer video {
.videocontainer video, .media-video video {
object-fit: contain;
background: black;
max-width: 100%;
}
.media-video video, .media-audio audio {
width: 100%;
}
.backtrace:not(:last-child) {
padding-bottom: 0.5em;

View file

@ -113,7 +113,7 @@ img[data-sceditor-emoticon] {
}
/* Responsive Youtube embed */
.videocontainer {
.videocontainer, .media-video, .media-audio {
max-width: 560px;
}
.videocontainer div {
@ -128,6 +128,10 @@ img[data-sceditor-emoticon] {
height: 100% !important;
}
.media-video video, .media-audio audio {
width: 100%;
}
.floatleft, .floatright {
max-width: 45%;
border: 1px dashed var(--separator);

View file

@ -26,6 +26,10 @@ div.sceditor-dropdown a:link {
color: var(--bold-body-text);
}
div.sceditor-dropdown label {
color: var(--bold-body-text);
}
div.sceditor-dropdown .button {
background: var(--main-background);
color: var(--bold-body-text);

View file

@ -0,0 +1,3 @@
PROJECT := media_bbc
include ../plugin.mk

View file

@ -0,0 +1,68 @@
<?php
function hook_media_bbcode(&$codes, &$no_autolink_tags) {
$codes[] = array(
'tag' => 'video',
'type' => 'unparsed_content',
'content' => '<div class="media-video"><video data-src="$1" controls><source src="$1" /></video></div>',
'disabled_content' => '<a href="$1" target="_blank" rel="noopener">$1</a>',
'block_level' => true,
);
$codes[] = array(
'tag' => 'audio',
'type' => 'unparsed_content',
'content' => '<div class="media-audio"><audio data-src="$1" controls><source src="$1" /></audio></div>',
'disabled_content' => '<a href="$1" target="_blank" rel="noopener">$1</a>',
'block_level' => true,
);
$no_autolink_tags[] = 'video';
$no_autolink_tags[] = 'audio';
}
function hook_media_bbcode_buttons(&$bbc_tags) {
$group_idx = 0;
$idx = 0;
// We want to put our media buttons next to the yt/image/etc group, so find
// the image button
foreach ($bbc_tags as $group) {
$idx = 0;
foreach ($group as $item) {
if (isset($item['code']) && $item['code'] == 'image') {
// done!
break 2;
}
$idx++;
}
$group_idx++;
}
$media_btns = array(
array(
'code' => 'video',
'description' => 'Insert a video',
),
array(
'code' => 'audio',
'description' => 'Insert audio',
),
);
$bbc_tags[$group_idx] = array_merge(
array_slice($bbc_tags[$group_idx], 0, $idx, true),
$media_btns,
array_slice($bbc_tags[$group_idx], $idx, null, true),
);
}
function media_sce_options(&$sce_options) {
loadJavaScriptFile('sceditor.mediabbc.js', array('minimize' => true), 'smf_sceditor_media');
loadCSSFile('sceditor.mediabbc.css', array('minimize' => true));
}
function media_bbc_credits() {
global $context;
$context['credits_modifications'][] = 'Silk SVG icons by <a href="https://github.com/frhun">@frhun</a>, licensed under CC-BY-SA';
}
?>

View file

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg width="64" height="64" viewBox="0 0 64 64" version="1.1" id="svg8" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/"><defs id="defs2"><linearGradient id="linearGradient1267"><stop style="stop-color:#3f3f3f;stop-opacity:1" offset="0" id="stop1263"/><stop style="stop-color:#838383;stop-opacity:1" offset="1" id="stop1265"/></linearGradient><linearGradient id="linearGradient1259"><stop style="stop-color:#646460;stop-opacity:1" offset="0" id="stop1255"/><stop style="stop-color:#838381;stop-opacity:1" offset="1" id="stop1257"/></linearGradient><linearGradient id="linearGradient1251"><stop style="stop-color:#858580;stop-opacity:1" offset="0" id="stop1247"/><stop style="stop-color:#c3c3c2;stop-opacity:1" offset="1" id="stop1249"/></linearGradient><linearGradient xlink:href="#linearGradient1251" id="linearGradient1253" x1="32" y1="44" x2="16" y2="20" gradientUnits="userSpaceOnUse"/><linearGradient xlink:href="#linearGradient1259" id="linearGradient1261" x1="4" y1="52" x2="4" y2="16" gradientUnits="userSpaceOnUse"/><linearGradient xlink:href="#linearGradient1267" id="linearGradient1269" x1="24" y1="40" x2="24" y2="24" gradientUnits="userSpaceOnUse"/></defs><metadata id="metadata5"><rdf:RDF><cc:Work rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/><dc:title/></cc:Work></rdf:RDF></metadata><g id="layer1"><path style="fill:url(#linearGradient1253);fill-opacity:1;stroke:url(#linearGradient1261);stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;paint-order:markers fill stroke" d="M 2,22 V 42 H 14 L 30,52 V 12 L 14,22 Z" id="path1182"/><path id="path1184" style="fill:#e1293b;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;paint-order:markers fill stroke" d="m 35.999996,27.999998 a 4,4 0 0 1 4,4 4,4 0 0 1 -4,4"/><path id="path1184-5" style="fill:#e1293b;stroke:#e1293b;stroke-width:6;stroke-linecap:round;stroke-linejoin:round;paint-order:markers fill stroke" d="m 46.392301,25.999998 a 12,12 0 0 1 0,12"/><path id="path1184-5-6" style="fill:#e1293b;stroke:#e1293b;stroke-width:6;stroke-linecap:round;stroke-linejoin:round;paint-order:markers fill stroke" d="m 56.784605,17.999997 a 24,28 0 0 1 10e-7,28.000001"/><path id="path1182-2" style="fill:url(#linearGradient1269);stroke-width:4;stroke-linecap:round;stroke-linejoin:round;paint-order:markers fill stroke" d="m 24,22.824219 -6.820312,4.263672 A 6.0006,6.0006 0 0 1 14,28 H 8 v 8 h 6 a 6.0006,6.0006 0 0 1 3.179688,0.912109 L 24,41.175781 Z"/></g></svg>

After

(image error) Size: 2.7 KiB

File diff suppressed because one or more lines are too long

After

(image error) Size: 5.4 KiB

View file

@ -0,0 +1,33 @@
<?xml version="1.0"?>
<!DOCTYPE package-info SYSTEM "http://www.simplemachines.org/xml/package-info">
<package-info xmlns="http://www.simplemachines.org/xml/package-info" xmlns:smf="http://www.simplemachines.org/">
<id>@flurry:media_bbc</id>
<name>Media BBCode Tags</name>
<version>1.0</version>
<type>modification</type>
<install for="2.1.* - 2.1.99">
<readme parsebbc="true">readme.txt</readme>
<require-file name="Subs-MediaCode.php" destination="$sourcedir" />
<require-file name="sceditor.mediabbc.css" destination="Themes/default/css" />
<require-file name="sceditor.mediabbc.js" destination="Themes/default/scripts" />
<require-file name="asset/icon_audio.svg" destination="Themes/default/images" />
<require-file name="asset/icon_video.svg" destination="Themes/default/images" />
<hook hook="integrate_bbc_codes" function="hook_media_bbcode" file="$sourcedir/Subs-MediaCode.php" />
<hook hook="integrate_bbc_buttons" function="hook_media_bbcode_buttons" file="$sourcedir/Subs-MediaCode.php" />
<hook hook="integrate_sceditor_options" function="media_sce_options" file="$sourcedir/Subs-MediaCode.php" />
<hook hook="integrate_credits" function="media_bbc_credits" file="$sourcedir/Subs-MediaCode.php" />
</install>
<uninstall for="2.1.* - 2.1.99">
<remove-file name="$sourcedir/Subs-MediaCode.php" />
<remove-file name="Themes/default/scripts/sceditor.mediabbc.js" />
<remove-file name="Themes/default/css/sceditor.mediabbc.css" />
<remove-file name="Themes/default/images/icon_audio.svg" />
<remove-file name="Themes/default/images/icon_video.svg" />
<hook hook="integrate_bbc_codes" function="hook_media_bbcode" file="$sourcedir/Subs-MediaCode.php" reverse="true" />
<hook hook="integrate_bbc_buttons" function="hook_media_bbcode_buttons" file="$sourcedir/Subs-MediaCode.php" reverse="true" />
<hook hook="integrate_sceditor_options" function="media_sce_options" file="$sourcedir/Subs-MediaCode.php" reverse="true" />
<hook hook="integrate_credits" function="media_bbc_credits" file="$sourcedir/Subs-MediaCode.php" reverse="true" />
</uninstall>
</package-info>

View file

@ -0,0 +1,3 @@
[size=x-large][b]BBCode Media Tags[/b][/size]
This adds the [nobbc][video][/nobbc] and [nobbc][audio][/nobbc] tags to SMF.

View file

@ -0,0 +1,11 @@
.sceditor-button-video div {
background-image: url('../../default/images/icon_video.svg');
background-size: contain;
background-repeat: no-repeat;
}
.sceditor-button-audio div {
background-image: url('../../default/images/icon_audio.svg');
background-size: contain;
background-repeat: no-repeat;
}

View file

@ -0,0 +1,176 @@
(function (sceditor) {
// Checks if the provided input is a URL we can use for our media tags.
function isValidURL(candidate) {
// technically URL.canParse exists, but I'm not sure if other browsers
// I expect users to use (e.g. Pale Moon) support it. So let's do the
// old method.
try {
const url = new URL(candidate);
if (url.protocol == 'http:' || url.protocol == 'https:') {
return true;
}
throw "Invalid protocol";
} catch (e) {
return false;
}
}
function makeMediaHtml(url, mediatype) {
if (!isValidUrl(url)) {
return '';
}
return '<div class="media-' + mediatype + '">' +
'<' + mediatype + ' data-src="' + url + '" controls>' +
'<source src="' + url + '" />' +
'</' + mediatype + '></div>';
}
// This creates a dropdown, similar to the existing YouTube button
function mediaDropDown(editor, caller, mediatype, urlCallback) {
// e.g. 'video' -> 'Video'
const mediaTitle = mediatype.charAt(0).toUpperCase() + mediatype.substring(1).toLowerCase();
// Container for the text input
const inputForm = document.createElement("form");
function clickAction(ev) {
const medialink = document.getElementById('medialink');
if (medialink != null && medialink.value != null) {
// At this point, medialink.value is either a string, or something is very wrong
if (isValidURL(medialink.value)) {
urlCallback(medialink.value);
}
}
editor.closeDropDown(true);
ev.preventDefault();
}
inputForm.addEventListener('submit', clickAction);
const inputLabel = document.createElement('label');
inputLabel.htmlFor = 'medialink';
inputLabel.innerText = mediaTitle + ' URL:';
inputForm.appendChild(inputLabel);
const inputElem = document.createElement('input');
inputElem.id = 'medialink';
/*
* It's unlikely users will be repeatedly sending the same audio, and
* the dropdown will just get in the way.
*/
inputElem.autocomplete = 'off';
inputElem.type = 'text';
inputElem.dir = 'ltr';
inputElem.placeholder = 'https://';
inputForm.appendChild(inputElem);
// "INSERT" button
const insertDiv = document.createElement("div");
const insertBtn = document.createElement("input");
insertBtn.className = 'button';
insertBtn.type = 'button';
insertBtn.value = 'Insert';
insertDiv.appendChild(insertBtn);
insertBtn.addEventListener('click', clickAction);
// div to tie the elements together
const containerDiv = document.createElement("div");
containerDiv.appendChild(inputForm);
containerDiv.appendChild(insertDiv);
editor.createDropDown(caller, 'insertlink', containerDiv);
}
// "Converts" the HTML back, by finding the data-src attribute of the media tag
function htmlToBBCode(element, content, mediatype) {
const media = element.getElementsByTagName(mediatype);
if (media.length == 0 || !media[0].attributes.hasOwnProperty('data-src')) {
return content;
}
return '[' + mediatype + ']' + media[0].attributes['data-src'].value + '[/' + mediatype + ']';
}
sceditor.formats.bbcode.set(
'video', {
tags: {
div: {
class: 'media-video'
}
},
isInline: false,
allowedChildren: ['#'],
breakBefore: true,
breakAfter: true,
skipLastLineBreak: true,
format: function (element, content) {
return htmlToBBCode(element, content, 'video');
},
html: function (token, attrs, content) {
makeMediaHtml(content, 'video');
}
});
sceditor.formats.bbcode.set(
'audio', {
tags: {
div: {
class: 'media-audio'
}
},
isInline: false,
allowedChildren: ['#'],
breakBefore: true,
breakAfter: true,
skipLastLineBreak: true,
format: function (element, content) {
return htmlToBBCode(element, content, 'audio');
},
html: function (token, attrs, content) {
makeMediaHtml(content, 'audio');
}
});
sceditor.command.set(
'video', {
exec: function (caller) {
const editor = this;
mediaDropDown(this, caller, 'video', function (url) {
editor.wysiwygEditorInsertHtml(makeMediaHtml(url, 'video'));
});
},
txtExec: function (caller, selected) {
const editor = this;
if (isValidURL(selected)) {
editor.insertText('[video]' + selected + '[/video]');
} else {
mediaDropDown(this, caller, 'video', function (url) {
editor.insertText('[video]' + url + '[/video]');
});
}
}
}
);
sceditor.command.set(
'audio', {
exec: function (caller) {
const editor = this;
mediaDropDown(this, caller, 'audio', function (url) {
editor.wysiwygEditorInsertHtml(makeMediaHtml(url, 'audio'));
});
},
txtExec: function (caller, selected) {
const editor = this;
if (isValidURL(selected)) {
editor.insertText('[audio]' + selected + '[/audio]');
} else {
mediaDropDown(this, caller, 'audio', function (url) {
editor.insertText('[audio]' + url + '[/audio]');
});
}
}
}
);
})(sceditor);

View file

@ -25,6 +25,7 @@ function topic_is_muted($topic, $user = -1)
{
global $context, $smcFunc, $user_info;
if ($user_info['is_guest']) {
die('lol');
return false;
}
@ -126,4 +127,8 @@ function mute_theme_option()
);
}
function add_topic_mute_js() {
loadJavaScriptFile('topic-mute.js', array('minimize' => true), 'topic_mute_ajax');
}
?>

View file

@ -7,7 +7,7 @@
*/
function TopicMute()
{
global $smcFunc, $user_info, $topic, $scripturl;
global $smcFunc, $user_info, $topic, $scripturl, $context;
is_not_guest();
checkSession('get');
@ -43,6 +43,7 @@ function TopicMute()
// Handle AJAX requests
if (isset($_GET['xml']))
{
loadTemplate('Xml');
$context['xml_data']['errors'] = array(
'identifier' => 'error',
'children' => array(
@ -52,6 +53,8 @@ function TopicMute()
),
);
$context['sub_template'] = 'generic_xml';
// TODO: is this the best way to do it?
obExit(false, false);
} else {
redirectexit('topic=' . $topic . '.' . $_REQUEST['start']);
}

View file

@ -26,7 +26,7 @@ $columns = array(
$indexes = array(
array(
'type' => 'primary',
'columns' => array('id_member'),
'columns' => array('id_member', 'id_topic'),
),
);

View file

@ -10,21 +10,25 @@
<readme parsebbc="true">readme.txt</readme>
<require-file name="Subs-TopicMute.php" destination="$sourcedir" />
<require-file name="languages/TopicMute.english.php" destination="$languagedir" />
<require-file name="topic-mute.js" destination="Themes/default/scripts" />
<require-file name="TopicMute.php" destination="$sourcedir" />
<database>dbinstall.php</database>
<hook hook="integrate_message_index" function="hide_muted_topics" file="$sourcedir/Subs-TopicMute.php" />
<hook hook="integrate_theme_options" function="mute_theme_option" file="$sourcedir/Subs-TopicMute.php" />
<hook hook="integrate_display_buttons" function="add_mute_button" file="$sourcedir/Subs-TopicMute.php" />
<hook hook="integrate_load_theme" function="add_topic_mute_js" file="$sourcedir/Subs-TopicMute.php" />
<hook hook="integrate_actions" function="add_topicmute_action" file="$sourcedir/Subs-TopicMute.php" />
</install>
<uninstall for="2.1.* - 2.1.99">
<remove-file name="$sourcedir/Subs-TopicMute.php" />
<remove-file name="$sourcedir/TopicMute.php" />
<remove-file name="Themes/default/scripts/topic-mute.js" />
<remove-file name="$languagedir/TopicMute.english.php" />
<hook hook="integrate_message_index" function="hide_muted_topics" file="$sourcedir/Subs-TopicMute.php" reverse="true" />
<hook hook="integrate_theme_options" function="mute_theme_option" file="$sourcedir/Subs-TopicMute.php" reverse="true" />
<hook hook="integrate_display_buttons" function="add_mute_button" file="$sourcedir/Subs-TopicMute.php" reverse="true" />
<hook hook="integrate_load_theme" function="add_topic_mute_js" file="$sourcedir/Subs-TopicMute.php" reverse="true" />
<hook hook="integrate_actions" function="add_topicmute_action" file="$sourcedir/Subs-TopicMute.php" reverse="true" />
</uninstall>
</package-info>

View file

@ -0,0 +1,15 @@
$(function() {
$('.button_strip_mute_topic').click(function (e) {
var $obj = $(this);
e.preventDefault();
ajax_indicator(true);
$.get($obj.attr('href') + ';xml', function () {
ajax_indicator(false);
let text = 'Unmute Topic';
if ($obj.text() == text) {
text = 'Mute Topic';
}
$('.button_strip_mute_topic').text(text);
});
});
});

View file

@ -0,0 +1,3 @@
PROJECT := yt_nocookie
include ../plugin.mk

View file

@ -0,0 +1,19 @@
<?php
function hook_yt_noorigin(&$codes, &$no_autolink_tags) {
$found = false;
$idx = 0;
foreach ($codes as $code) {
if ($code['tag'] == 'youtube') {
$found = true;
break;
}
$idx++;
}
if ($found) {
// Everything except ?origin=
$codes[$idx]['content'] = '<div class="videocontainer"><div><iframe frameborder="0" src="https://www.youtube-nocookie.com/embed/$1?wmode=opaque" data-youtube-id="$1" allowfullscreen loading="lazy"></iframe></div></div>';
}
}
?>

View file

@ -0,0 +1,19 @@
<?xml version="1.0"?>
<!DOCTYPE package-info SYSTEM "http://www.simplemachines.org/xml/package-info">
<package-info xmlns="http://www.simplemachines.org/xml/package-info" xmlns:smf="http://www.simplemachines.org/">
<id>@flurry:yt_nocookie</id>
<name>Use youtube-nocookie for YouTube</name>
<version>1.0</version>
<type>modification</type>
<install for="2.1.* - 2.1.99">
<readme parsebbc="true">readme.txt</readme>
<require-file name="Subs-YtNoOrigin.php" destination="$sourcedir" />
<hook hook="integrate_bbc_codes" function="hook_yt_noorigin" file="$sourcedir/Subs-YtNoOrigin.php" />
</install>
<uninstall for="2.1.* - 2.1.99">
<remove-file name="$sourcedir/Subs-YtNoOrigin.php" />
<hook hook="integrate_bbc_codes" function="hook_yt_noorigin" file="$sourcedir/Subs-YtNoOrigin.php" reverse="true" />
</uninstall>
</package-info>

View file

@ -0,0 +1,3 @@
[size=x-large][b]Use youtube-nocookie for YouTube[/b][/size]
This removes the [b]origin=[/b] query parameter from YouTube embeds, and uses https://www.youtube-nocookie.com for embeds.