add sekretaerbaer Addons

This commit is contained in:
oldkid 2025-06-01 16:05:03 +02:00
parent 97b09d34e9
commit 4cc0229c9e
33 changed files with 1399 additions and 16 deletions

View file

@ -2,3 +2,5 @@ invidious Addon for Friendica
==========================
This addon will replace "youtube.com" with the chosen Invidious instance
These addons are not intended to be used on productive systems. The use of these addons is at your own risk.

View file

@ -2,10 +2,10 @@
/*
* Name: invidious
* Description: Replaces links to youtube.com to an invidious instance in all displays of postings on a node.
* Version: 0.4
* Version: 0.7
* Author: Matthias Ebers <https://loma.ml/profile/feb>
* Author: Michael Vogel <https://pirati.ca/profile/heluecht>
* Status: Unsupported
* Status:
* Note: Please use the URL Replace addon instead
*/
@ -26,7 +26,11 @@ function invidious_install()
*/
function invidious_addon_admin_post()
{
DI::config()->set('invidious', 'server', trim($_POST['invidiousserver'], " \n\r\t\v\x00/"));
// Sanitize and validate the input as a valid URL
$url = filter_var(trim($_POST['invidiousserver'], " \n\r\t\v\x00/"), FILTER_VALIDATE_URL);
if ($url !== false) {
DI::config()->set('invidious', 'server', $url);
}
}
/* Hook into the admin settings to let the admin choose an
@ -54,8 +58,8 @@ function invidious_settings(array &$data)
$t = Renderer::getMarkupTemplate('settings.tpl', 'addon/invidious/');
$html = Renderer::replaceMacros($t, [
'$enabled' => ['invidious-enabled', DI::l10n()->t('Replace Youtube links with links to an Invidious server'), $enabled, DI::l10n()->t('If enabled, Youtube links are replaced with the links to the specified Invidious server.')],
'$server' => ['invidious-server', DI::l10n()->t('Invidious server'), $server, DI::l10n()->t('See %s for a list of available Invidious servers.', '<a href="https://api.invidious.io/">https://api.invidious.io/</a>')],
'$enabled' => ['enabled', DI::l10n()->t('Replace Youtube links with links to an Invidious server'), $enabled, DI::l10n()->t('If enabled, Youtube links are replaced with the links to the specified Invidious server.')],
'$server' => ['server', DI::l10n()->t('Invidious server'), $server, DI::l10n()->t('See %s for a list of available Invidious servers.', '<a href="https://api.invidious.io/">https://api.invidious.io/</a>')],
]);
$data = [
@ -71,11 +75,13 @@ function invidious_settings_post(array &$b)
return;
}
DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'invidious', 'enabled', (bool)$_POST['invidious-enabled']);
DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'invidious', 'enabled', (bool)$_POST['enabled']);
$server = trim($_POST['invidious-server'], " \n\r\t\v\x00/");
if ($server != DI::config()->get('invidious', 'server', INVIDIOUS_DEFAULT) && !empty($server)) {
DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'invidious', 'server', $server);
$server = trim($_POST['server'], " \n\r\t\v\x00/");
// Sanitize and validate the server URL before saving
$validatedServer = filter_var($server, FILTER_VALIDATE_URL);
if ($validatedServer !== false && $validatedServer != DI::config()->get('invidious', 'server', INVIDIOUS_DEFAULT)) {
DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'invidious', 'server', $validatedServer);
} else {
DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'invidious', 'server');
}
@ -93,14 +99,12 @@ function invidious_render(array &$b)
$original = $b['html'];
$server = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'invidious', 'server', DI::config()->get('invidious', 'server', INVIDIOUS_DEFAULT));
$b['html'] = preg_replace("~https?://(?:www\.)?youtube\.com/watch\?v=(.*?)~ism", $server . '/watch?v=$1', $b['html']);
$b['html'] = preg_replace("~https?://(?:www\.)?youtube\.com/embed/(.*?)~ism", $server . '/embed/$1', $b['html']);
$b['html'] = preg_replace("~https?://(?:www\.)?youtube\.com/shorts/(.*?)~ism", $server . '/shorts/$1', $b['html']);
$b['html'] = preg_replace ("/https?:\/\/music.youtube.com\/(.*?)/ism", $server . '/watch?v=$1', $b['html']);
$b['html'] = preg_replace ("/https?:\/\/m.youtube.com\/(.*?)/ism", $server . '/watch?v=$1', $b['html']);
$b['html'] = preg_replace("/https?:\/\/youtu.be\/(.*?)/ism", $server . '/watch?v=$1', $b['html']);
// Use optimized regex to replace different YouTube URL formats
$b['html'] = preg_replace("~https?://(?:www\.|m\.)?youtube\.com/(watch|embed|shorts)\?v=([a-zA-Z0-9_-]+)~ism", $server . '/$1?v=$2', $b['html']);
$b['html'] = preg_replace("~https?://(?:music\.)?youtube\.com/watch\?v=([a-zA-Z0-9_-]+)~ism", $server . '/watch?v=$1', $b['html']);
$b['html'] = preg_replace("~https?://?youtu\.be/([a-zA-Z0-9_-]+)~ism", $server . '/watch?v=$1', $b['html']);
if ($original != $b['html']) {
$b['html'] .= '<hr><p><small>' . DI::l10n()->t('(Invidious addon enabled: YouTube links via %s)', $server) . '</small></p>';
$b['html'] .= '<hr><p><small class="invidious-note">' . DI::l10n()->t('(Invidious addon enabled: YouTube links via %s)', $server) . '</small></p>';
}
}

108
postbox/README.md Normal file
View file

@ -0,0 +1,108 @@
# Postbox
This is a Friendica add-on that adds a stylesheet to the HEAD element to support showing Postbox styling.
It does not add any interface for creating Postboxes, but users can still create them with BBcode.
_**NOTE:** Support for Postbox is built into Bookface 1.6+. This adddon adds support to Friendica regardless of what theme/scheme is being used._
## Getting started
1. Place the "postbox" folder in your _friendica/addons_ subfolder.
2. Go to the Main _Menu > Admin > Addons_ and enable "Postbox"
3. Any posts using Postbox will now display the colorful backgrounds.
## Using Zen Postbox
1. Open the message Compose modal or Page
2. Type `[class=postbox-red]Wrapped text goes here[/class]` (substitute "-red" with any of the available styles)
3. Press the "Preview" tab to see what it will look like.
While Postbox allows more content than the Facebook version (which is text only), there are limitations due to how Friendica parses BBcode.
**It is STRONGLY recommended you only use Postboxes with text and emoji.**
BBcodes you CANNOT put inside a Postbox:
* [class] (which means you cant nest Postboxes)
* [hr]
* [h1],[h2],[h3], etc…
* [table],[tr],[th],[td]
* [list],[ul],[ol]
* [abstract]
* [spoiler]
* [map]
* [code]
BBcodes that do not work as intended inside a Postbox:
* [pre]
* [noparse]
* [nobb]
The text will show but will be styled and centered.
BBcodes that **CAN BE INSIDE** a Postbox:
* [i], [b], [u], [o], [s] _(bold has no visible effect)_
* [url]
* [img]
* [audio]
* [video]
And any plain text, including emoji
If you are using Markdown formatting what you can and cant put in a Postbox is similar, with the exception that (because of how Markdown is parsed into BBcode) you cant have both a URL and an image in the same Postbox. You *can* however put inline `code` in a Postbox with Markdown where BBcode cannot.
### Available Postbox styles
**Solid Color Backgrounds:**
- .postbox-black
- .postbox-red
- .postbox-green
- .postbox-blue
- .postbox-orange
- .postbox-purple
- .postbox-forest
- .postbox-ocean
- .postbox-pink
- .postbox-salmon
**Gradient Backgrounds:**
- .postbox-darkgray
- .postbox-minty
- .postbox-mintgray
- .postbox-redblue
- .postbox-violets
- .postbox-grayblack
- .postbox-tealblue
- .postbox-greengray
- .postbox-tealgray
- .postbox-bluegray
- .postbox-lavendergray
- .postbox-sunset
- .postbox-sherbert
## Known Issues
- Postboxes are not shown on other platforms when your post is shared.
- Postboxes are not shown in third-party apps (at least none do yet)
## Changelog
1.0 (25 March 2025)
* Initial Release for Friendica 'Interrupted Fern' 2024.12
## Authors and acknowledgment
Random Penguin <https://gitlab.com/randompenguin>
## License
AGPL
## Project status
Unsupported by Friendica devs.

120
postbox/postbox.css Normal file
View file

@ -0,0 +1,120 @@
/* Post Backgrounds
================
Solid and Gradient backgrounds with larger text
to grab reader attention
*/
[class^="postbox-"]{
display: table-cell;
height: 350px;
width: 1000px;
max-width: 100%;
vertical-align: middle;
font-family: Arial, sans-serif;
font-size: 30px;
font-weight: 700;
line-height: 35px;
text-align: center;
padding: 50px 30px;
box-sizing: border-box;
}
[class^="postbox-"] a {
color: inherit !important;
}
[class^="postbox-"]:hover a,
[class^="postbox-"]:focus a {
text-decoration: underline;
}
/* Solid Color Backgrounds */
.postbox-black {
background-color: black;
color: white;
}
.postbox-red {
background-color: rgb(226, 1, 59);
color: white;
}
.postbox-green {
background-color: rgb(38, 146, 127);
color: white;
}
.postbox-blue {
background-color: rgb(32, 136, 175);
color: black;
}
.postbox-orange {
background-color: rgb(255, 99, 35);
color: black;
}
.postbox-purple {
background-color: rgb(115, 33, 173);
color: white;
}
.postbox-forest {
background-color: rgb(22, 83, 72);
color: white;
}
.postbox-ocean {
background-color: rgb(36, 55, 98);
color: white;
}
.postbox-pink {
background-color: rgb(243, 83, 105);
color: black;
}
.postbox-salmon {
background-color: rgb(250, 128, 114);
color: black;
}
/* Gradient Backgrounds */
.postbox-darkgray {
background-image: linear-gradient(135deg, rgb(119, 125, 136), rgb(79, 87, 102));
color: white;
}
.postbox-minty {
background-image: linear-gradient(135deg, rgb(143, 199, 173), rgb(72, 229, 169));
color: black;
}
.postbox-mintgray {
background-image: linear-gradient(135deg, rgb(143, 199, 173), rgb(72, 229, 169));
color: black;
}
.postbox-redblue {
background-image: linear-gradient(45deg, rgb(255, 0, 71), rgb(44, 52, 199));
color: white;
}
.postbox-violets {
background-image: linear-gradient(45deg, rgb(93, 63, 218), rgb(252, 54, 253));
color: white;
}
.postbox-grayblack {
background-image: linear-gradient(45deg, rgb(93, 99, 116), rgb(22, 24, 29));
color: white;
}
.postbox-tealblue {
background-image: linear-gradient(to bottom, #4bdfdf 0%,#207cca 50%,#19094a 100%);
color: white;
}
.postbox-greengray {
background-image: linear-gradient(to right, #c8dbbd 0%,#dedede 100%);
color: black;
}
.postbox-tealgray {
background-image: linear-gradient(to right, #8dcad0 0%,#dedede 100%);
color: black;
}
.postbox-bluegray {
background-image: linear-gradient(to right, #94bbeb 0%,#dedede 100%);
color: black;
}
.postbox-lavendergray {
background-image: linear-gradient(to right, #cfbfda 0%,#dedede 100%);
color: black;
}
.postbox-sunset {
background-image: linear-gradient(to bottom, #fecf41 0%,#fd7440 50%,#b623b1 100%);
color: white;
}
.postbox-sherbert {
background-image: linear-gradient(45deg, #fcd6cd 6%,#f8bc44 25%,#fb7d88 44%,#fb7d88 64%,#fb7d88 64%,#fed640 100%);
color: black;
}

1
postbox/postbox.min.css vendored Normal file
View file

@ -0,0 +1 @@
[class^=postbox-]{display:table-cell;height:350px;width:1000px;max-width:100%;vertical-align:middle;font-family:Arial,sans-serif;font-size:30px;font-weight:700;line-height:35px;text-align:center;padding:50px 30px;box-sizing:border-box}[class^=postbox-] a{color:inherit!important}[class^=postbox-]:focus a,[class^=postbox-]:hover a{text-decoration:underline}.postbox-black{background-color:#000;color:#fff}.postbox-red{background-color:#e2013b;color:#fff}.postbox-green{background-color:#26927f;color:#fff}.postbox-blue{background-color:#2088af;color:#000}.postbox-orange{background-color:#ff6323;color:#000}.postbox-purple{background-color:#7321ad;color:#fff}.postbox-forest{background-color:#165348;color:#fff}.postbox-ocean{background-color:#243762;color:#fff}.postbox-pink{background-color:#f35369;color:#000}.postbox-salmon{background-color:salmon;color:#000}.postbox-darkgray{background-image:linear-gradient(135deg,#777d88,#4f5766);color:#fff}.postbox-mintgray,.postbox-minty{background-image:linear-gradient(135deg,#8fc7ad,#48e5a9);color:#000}.postbox-redblue{background-image:linear-gradient(45deg,#ff0047,#2c34c7);color:#fff}.postbox-violets{background-image:linear-gradient(45deg,#5d3fda,#fc36fd);color:#fff}.postbox-grayblack{background-image:linear-gradient(45deg,#5d6374,#16181d);color:#fff}.postbox-tealblue{background-image:linear-gradient(to bottom,#4bdfdf 0,#207cca 50%,#19094a 100%);color:#fff}.postbox-greengray{background-image:linear-gradient(to right,#c8dbbd 0,#dedede 100%);color:#000}.postbox-tealgray{background-image:linear-gradient(to right,#8dcad0 0,#dedede 100%);color:#000}.postbox-bluegray{background-image:linear-gradient(to right,#94bbeb 0,#dedede 100%);color:#000}.postbox-lavendergray{background-image:linear-gradient(to right,#cfbfda 0,#dedede 100%);color:#000}.postbox-sunset{background-image:linear-gradient(to bottom,#fecf41 0,#fd7440 50%,#b623b1 100%);color:#fff}.postbox-sherbert{background-image:linear-gradient(45deg,#fcd6cd 6%,#f8bc44 25%,#fb7d88 44%,#fb7d88 64%,#fb7d88 64%,#fed640 100%);color:#000}

21
postbox/postbox.php Normal file
View file

@ -0,0 +1,21 @@
<?php
/**
* Name: Postbox
* Description: Adds support for showing Postbox backgrounds but does NOT add an interface for making them (but users can still make them with BBcode)
* Version: 1.0
* Author: Random Penguin <https://gitlab.com/randompenguin>
*/
use Friendica\Core\Hook;
use Friendica\DI;
function postbox_install()
{
Hook::register('head', __FILE__, 'postbox_head');
}
function postbox_head(string &$b)
{
// Add Postbox Styling to Header
$box_styles = __DIR__ . '/postbox.min.css';
DI::page()->registerStylesheet($box_styles);
}

View file

@ -0,0 +1,46 @@
# ADDON signatur
# Copyright (C)
# This file is distributed under the same license as the Friendica signatur addon package.
#
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-12-16 11:08+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: signatur.php:114
msgid "BETA Version - Add a signature to your posts. This addon automatically appends a customizable signature to posts in Friendica. Users can enable or disable it, define personal signatures, and optionally include them in comments."
msgstr ""
#: signatur.php:115
msgid "Enable Signature"
msgstr ""
#: signatur.php:116
msgid "Your Signature"
msgstr ""
#: signatur.php:116
msgid "Enter your custom signature. (Multiline allowed)"
msgstr ""
#: signatur.php:117
msgid "Enable Signature in Comments"
msgstr ""
#: signatur.php:118
msgid "Save"
msgstr ""
#: signatur.php:123
msgid "Signature Settings"
msgstr ""

147
signatur/signatur.php Normal file
View file

@ -0,0 +1,147 @@
<?php
/**
* Name: signatur
* Description: Automatically adds a signature to new posts. Admins can define a default signature, and users can configure their own.
* Version: 1.6
* Author: Matthias Ebers <https://loma.ml/profile/feb>
* Status: Beta
*/
use Friendica\Core\Hook;
use Friendica\Core\Renderer;
use Friendica\DI;
const SIGNATURE_MARKER = "[hr]";
function signatur_install()
{
Hook::register('post_local', __FILE__, 'signatur_add_signature');
Hook::register('addon_settings', __FILE__, 'signatur_user_settings');
Hook::register('addon_settings_post', __FILE__, 'signatur_user_settings_post');
}
/**
* Adds a signature to new posts.
*
* @param array &$b Post data.
*/
function signatur_add_signature(array &$b)
{
if (empty($b['uid'])) {
return;
}
$enabled = DI::pConfig()->get($b['uid'], 'signatur', 'enabled', false);
if (!$enabled) {
return;
}
$isComment = !empty($b['parent']) && ($b['parent'] != ($b['uri-id'] ?? null));
$enableSignatureInComments = DI::pConfig()->get($b['uid'], 'signatur', 'enable_signature_in_comments', true);
if ($isComment && !$enableSignatureInComments) {
return;
}
$signature = DI::pConfig()->get($b['uid'], 'signatur', 'text', '');
if (strpos($b['body'], SIGNATURE_MARKER) !== false) {
return;
}
if (!empty($b['body'])) {
$b['body'] = insert_signature_before_images($b['body'], SIGNATURE_MARKER, $signature);
}
}
/**
* Inserts the signature based on the content structure.
*
* @param string $body The post body.
* @param string $signature_marker The signature marker.
* @param string $signature The signature text.
* @return string The modified post body.
*/
function insert_signature_before_images($body, $signature_marker, $signature)
{
$lines = explode("\n", $body);
$image_count = 0;
$text_end_index = -1;
foreach ($lines as $index => $line) {
if (strpos($line, '[url=') !== false) {
$image_count++;
if ($image_count === 1 && $text_end_index === -1) {
$text_end_index = $index;
}
}
}
if ($image_count <= 1) {
return $body . "\n\n{$signature_marker}\n{$signature}";
}
if ($image_count >= 2 && $text_end_index !== -1) {
$lines_before_first_image = array_slice($lines, 0, $text_end_index);
$lines_after_first_image = array_slice($lines, $text_end_index);
return implode("\n", $lines_before_first_image) .
"\n\n{$signature_marker}\n{$signature}\n\n" .
implode("\n", $lines_after_first_image);
}
return $body . "\n\n{$signature_marker}\n{$signature}";
}
/**
* User settings for the app.
*
* @param array &$data Settings data for rendering.
*/
function signatur_user_settings(array &$data)
{
$uid = DI::userSession()->getLocalUserId();
if (!$uid) {
return;
}
$enabled = DI::pConfig()->get($uid, 'signatur', 'enabled', false);
$signature = DI::pConfig()->get($uid, 'signatur', 'text', '');
$enable_signature_in_comments = DI::pConfig()->get($uid, 'signatur', 'enable_signature_in_comments', true);
$t = Renderer::getMarkupTemplate('settings.tpl', 'addon/signatur/');
$html = Renderer::replaceMacros($t, [
'$description' => DI::l10n()->t('BETA Version - Add a signature to your posts. This addon automatically appends a customizable signature to posts in Friendica. Users can enable or disable it, define personal signatures, and optionally include them in comments.'),
'$enabled' => ['enabled', DI::l10n()->t('Enable Signature'), $enabled],
'$signature' => ['text', DI::l10n()->t('Your Signature'), $signature, DI::l10n()->t('Enter your custom signature. (Multiline allowed)')],
'$enable_signature_in_comments' => ['enable_signature_in_comments', DI::l10n()->t('Enable Signature in Comments'), $enable_signature_in_comments],
'$submit' => DI::l10n()->t('Save'),
]);
$data = [
'addon' => 'signatur',
'title' => DI::l10n()->t('Signature Settings'),
'html' => $html,
];
}
/**
* Saves user settings.
*
* @param array &$b Submitted data.
*/
function signatur_user_settings_post(array &$b)
{
$uid = DI::userSession()->getLocalUserId();
if (!$uid || empty($_POST['signatur-submit'])) {
return;
}
$enabled = !empty($_POST['enabled']);
$signature = trim($_POST['text']);
$enable_signature_in_comments = !empty($_POST['enable_signature_in_comments']);
DI::pConfig()->set($uid, 'signatur', 'enabled', $enabled);
DI::pConfig()->set($uid, 'signatur', 'text', $signature);
DI::pConfig()->set($uid, 'signatur', 'enable_signature_in_comments', $enable_signature_in_comments);
}

View file

@ -0,0 +1,6 @@
<p>{{$description}}</p>
{{include file="field_textarea.tpl" field=$default_text}}

View file

@ -0,0 +1,4 @@
<p>{{$description}}</p>
{{include file="field_checkbox.tpl" field=$enabled}}
{{include file="field_textarea.tpl" field=$signature}}
{{include file="field_checkbox.tpl" field=$enable_signature_in_comments}}

View file

@ -0,0 +1,72 @@
/* Modal Container */
.usernotice-modal {
display: none; /* Modal standardmäßig verstecken */
position: fixed; /* Fest positioniert */
z-index: 1000; /* Über anderen Elementen angezeigt */
left: 52.5%; /* Horizontale Zentrierung */
top: 10%; /* Abstand von der oberen Seite */
transform: translateX(-50%); /* Modal horizontal zentrieren */
width: 90%; /* Breite für Mobilgeräte anpassen */
max-width: 650px; /* Maximale Breite des Modals */
max-height: 80%; /* Maximale Höhe des Modals */
overflow-y: auto; /* Scrollen, wenn der Inhalt zu groß ist */
}
/* Modal Inhalt */
.usernotice-modal-content {
background-color: #2196f3; /* Hintergrundfarbe */
color: white; /* Textfarbe */
padding: 20px; /* Innenabstand */
border-radius: 8px; /* Abgerundete Ecken */
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); /* Schatteneffekt */
margin: 0 auto; /* Zentrieren des Modalinhalts */
width: 100%; /* 100% Breite des Containers */
max-width: 650px; /* Maximale Breite */
}
/* Schließen-Button */
.usernotice-close {
color: white; /* Farbe des Schließen-Buttons */
float: right; /* Button nach rechts ausrichten */
font-size: 28px; /* Größe des Schließen-Buttons */
font-weight: bold; /* Gewicht des Schließen-Buttons */
cursor: pointer; /* Zeiger-Style beim Hover */
}
.usernotice-close:hover {
color: darkred; /* Farbe beim Hover über den Schließen-Button */
}
/* Modal Header */
.usernotice-modal-content h3 {
font-size: 2rem; /* Entspricht der typischen Größe von <h2> */
margin: 0 0 10px 0; /* Abstand nach unten */
color: white; /* Schriftfarbe */
}
/* Responsive Design für kleinere Bildschirme */
@media (max-width: 600px) {
.usernotice-modal {
top: 15%; /* Etwas weiter unten auf Mobilgeräten */
left: 50%;
transform: translateX(-50%);
width: 95%; /* Breitere Darstellung auf kleineren Bildschirmen */
}
.usernotice-modal-content {
padding: 15px; /* Weniger Padding auf Mobilgeräten */
max-width: 100%; /* Keine feste Breite auf Mobilgeräten */
}
.usernotice-close {
font-size: 24px; /* Kleinere Schließen-Schaltfläche */
}
/* Dezenter Trennstrich */
.usernotice-divider {
border: none;
border-top: 1px solid rgba(244, 244, 244, 0.98);
margin: 10px 0;
width: 100%;
}
}

View file

@ -0,0 +1,5 @@
{{include file="field_textarea.tpl" field=$noticeText}}
<div class="settings-submit-wrapper">
<input type="submit" id="usernotice-submit" name="usernotice-submit" class="settings-submit" value="{{$submit}}" />
</div>

105
usernotice/usernotice.php Normal file
View file

@ -0,0 +1,105 @@
<?php
/**
* Name: User Notice
* Description: Displays a one-time notification in a blue modal for logged-in users. Use the addon to inform your users about important things on your node.
* Version: 1.0
* Author: Matthias Ebers <https://loma.ml/profile/feb>
*/
use Friendica\App;
use Friendica\Core\Hook;
use Friendica\Core\Renderer;
use Friendica\DI;
function usernotice_install() {
// Registriere das Hook, um das Modal in den Seiteninhalt einzufügen
Hook::register('page_content_top', __FILE__, 'usernotice_fetch');
}
function usernotice_addon_admin(string &$s)
{
// Überprüfe, ob der Benutzer ein Administrator ist
if (!DI::userSession()->isSiteAdmin()) {
return;
}
// Lade das Stylesheet für die Admin-Seite
DI::page()->registerStylesheet(__DIR__ . '/css/usernotice.css');
// Hole den aktuellen Text aus der Konfiguration
$noticeText = DI::config()->get('usernotice', 'text', '');
// Lade das Admin-Template
$t = Renderer::getMarkupTemplate('admin.tpl', 'addon/usernotice');
if (!$t) {
throw new \Exception('Template admin.tpl could not be loaded.');
}
// Admin-Seite rendern
$s .= Renderer::replaceMacros($t, [
'$title' => DI::l10n()->t('"usernotice" Settings'),
'$noticeText' => ['usernotice-text', DI::l10n()->t('Message'), $noticeText, DI::l10n()->t('Notification message to display in a modal')],
'$submit' => DI::l10n()->t('Save Settings')
]);
}
function usernotice_addon_admin_post()
{
// Nur Administratoren dürfen die Einstellungen ändern
if (!DI::userSession()->isSiteAdmin()) {
return;
}
// Speichere den neuen Text, wenn das Formular abgeschickt wurde
if (!empty($_POST['usernotice-submit']) && isset($_POST['usernotice-text'])) {
DI::config()->set('usernotice', 'text', trim(strip_tags($_POST['usernotice-text'])));
}
}
function usernotice_fetch(string &$b)
{
// Überprüfe, ob der Benutzer eingeloggt ist
if (!DI::userSession()->getLocalUserId()) {
return; // Modal wird nur für angemeldete Benutzer angezeigt
}
// Hole den Benachrichtigungstext aus der Konfiguration
$noticeText = DI::config()->get('usernotice', 'text');
// Wenn ein Text vorhanden ist, zeige das Modal an
if ($noticeText) {
// Lade das Stylesheet
DI::page()->registerStylesheet(__DIR__ . '/css/usernotice.css');
// HTML und JavaScript für das Modal hinzufügen
$b .= '
<div id="usernotice-modal" class="usernotice-modal">
<div class="usernotice-modal-content">
<span class="usernotice-close">&times;</span>
<h2>' . DI::l10n()->t('User-Notice') . '</h2>
<hr class="usernotice-divider">
<p>' . htmlspecialchars($noticeText) . '</p>
</div>
</div>
<script>
document.addEventListener("DOMContentLoaded", function () {
var modal = document.getElementById("usernotice-modal");
var closeBtn = document.getElementsByClassName("usernotice-close")[0];
var currentText = "' . addslashes($noticeText) . '";
// Zeige das Modal an, wenn es noch nicht geschlossen wurde oder der Text sich geändert hat
if (!localStorage.getItem("usernoticeClosed") || localStorage.getItem("usernoticeText") !== currentText) {
modal.style.display = "block";
}
// Schließe das Modal und speichere den Zustand in localStorage
closeBtn.onclick = function() {
modal.style.display = "none";
localStorage.setItem("usernoticeClosed", "true");
localStorage.setItem("usernoticeText", currentText);
}
});
</script>';
}
}

79
zen_postbox/README.md Normal file
View file

@ -0,0 +1,79 @@
# Zen Postbox
This is a Friendica add-on that adds a Jot Plugin tool button to the Compose editor allowing users to easily select any of the "Postbox" color backgrounds.
Postbox color backgrounds are similar to a Facebook feature for text-only posts, except Friendica's allows any arbitrary content and users may have more than on Postbox per post. Support for Postbox is built into the Bookface 1.6+ scheme for Frio, but this addon will enable it regardless of what theme/scheme is being used.
This add-on also adds support for displaying Postbox content in all feeds no matter what theeme is in use.
_**Note**: It has "zen" on the beginning of the name just to make the add-on load AFTER other Jot Plugins. In particular the "Smileybutton" add-on which has a typo that clears any Jot Plugins that load before it._
## Getting started
1. Place the "zen_postbox" folder in your _friendica/addons_ subfolder.
2. Go to the Main _Menu > Admin > Addons_ and enable "Zen Postbox"
3. On the Compose Modal or Compose Page you should see a rainbox button that opens a background selector.
## Using Zen Postbox
1. Open the message Compose modal or Page
2. To wrap text, etc., in a Postbox select it in the message editor.
3. Press the rainbow button at the bottom of the editor.
4. Select which Postbox background you'd like to wrap the text in.
5. Press the "Preview" tab to see what it will look like.
If no text is selected in the editor a Postbox will be appeneded to the text area with "..." for content. Replace the "..." with your text, etc.
While Postbox allows more content than the Facebook version (which is text only), there are limitations due to how Friendica parses BBcode.
**It is STRONGLY recommended you only use Postboxes with text and emoji.**
BBcodes you CANNOT put inside a Postbox:
* [class] (which means you cant nest Postboxes)
* [hr]
* [h1],[h2],[h3], etc…
* [table],[tr],[th],[td]
* [list],[ul],[ol]
* [quote]
* [abstract]
* [spoiler]
* [map]
* [code]
BBcodes that do not work as intended inside a Postbox:
* [pre]
* [noparse]
* [nobb]
The text will show but will be styled and centered.
BBcodes that **CAN BE INSIDE** a Postbox:
* [i], [b], [u], [o], [s] _(bold has no visible effect)_
* [url]
* [img]
* [audio]
* [video]
And any plain text, including emoji
If you are using Markdown formatting what you can and cant put in a Postbox is similar, with the exception that (because of how Markdown is parsed into BBcode) you cant have both a URL and an image in the same Postbox. You *can* however put inline `code` in a Postbox with Markdown where BBcode cannot.
## Known Issues
- Postboxes are not shown on other platforms when your post is shared.
- Postboxes are not shown in third-party apps (at least none do yet)
## Changelog
1.0 (25 March 2025)
* Initial Release for Friendica 'Interrupted Fern' 2024.12
## Authors and acknowledgment
Random Penguin <https://gitlab.com/randompenguin>
## License
Assuming AGPL for add-ons since that's the license Friendica is under
## Project status
Unsupported by Friendica devs.

View file

1
zen_postbox/view/default.min.css vendored Normal file
View file

@ -0,0 +1 @@
#profile-postbox-wrapper{display:block}#postboxbutton{display:none}.postbox_button>img{height:32px;width:32px;cursor:pointer}div.preview-postbox div.pick-postbox{height:100%;width:100%;display:block}div.preview-postbox>button{ms-appearance:none;moz-appearance:none;webkit-appearance:none;appearance:none;cursor:pointer;height:32px;width:32px;margin:0 5px 5px 0;float:left;border-radius:8px;background:0 0;border:none;padding:0;overflow:hidden}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

View file

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><g id="layer1"><path d="M32,8l0,16c0,4.415 -3.585,8 -8,8l-16,0c-4.415,0 -8,-3.585 -8,-8l0,-16c0,-4.415 3.585,-8 8,-8l16,0c4.415,0 8,3.585 8,8Z" style="fill:url(#_Linear1);"/></g><defs><linearGradient id="_Linear1" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(32,0,0,32,0,16)"><stop offset="0" style="stop-color:#f20d0d;stop-opacity:1"/><stop offset="0.23" style="stop-color:#f2af0d;stop-opacity:1"/><stop offset="0.38" style="stop-color:#e5f20d;stop-opacity:1"/><stop offset="0.5" style="stop-color:#40bf4f;stop-opacity:1"/><stop offset="0.62" style="stop-color:#0d28f2;stop-opacity:1"/><stop offset="0.76" style="stop-color:#930df2;stop-opacity:1"/><stop offset="1" style="stop-color:#e40df2;stop-opacity:1"/></linearGradient></defs></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

1
zen_postbox/view/duepuntozero.min.css vendored Normal file
View file

@ -0,0 +1 @@
#profile-postbox-wrapper{display:block}#postboxbutton{display:none}.postbox_button{height:18px;width:18px;position:relative;left:285px;top:-62px;padding:0;border:0;background:0 0}.postbox_button>img{height:100%;width:100%}div.preview-postbox{border:1px solid #aaa;-moz-border-radius:3px;border-radius:3px;position:relative;left:285px;top:-62px;padding:5px;width:fit-content}div.preview-postbox div.pick-postbox{height:100%;width:100%;display:block}div.preview-postbox>button{ms-appearance:none;moz-appearance:none;webkit-appearance:none;appearance:none;cursor:pointer;height:32px;width:32px;margin:0 5px 5px 0;float:left;border-radius:8px;background:0 0;border:none;padding:0;overflow:hidden}#profile-jot-plugin-wrapper>div,.jotplugins>div{float:left}#profile-jot-plugin-wrapper::after,.jotplugins::after{content:'';display:block;clear:both}

1
zen_postbox/view/frio.min.css vendored Normal file
View file

@ -0,0 +1 @@
#profile-postbox-wrapper{display:block}#postboxbutton{display:none;position:fixed;background-color:#eee;width:auto;border-radius:8px;padding:10px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.jotplugins #postboxbutton{position:absolute}.postbox_button{border:none!important;-webkit-box-shadow:none!important;-moz-box-shadow:none!important;box-shadow:none!important}.postbox_button>img{height:18px;width:18px;cursor:pointer}div.preview-postbox div.pick-postbox{height:100%;width:100%;display:block}div.preview-postbox>button{ms-appearance:none;moz-appearance:none;webkit-appearance:none;appearance:none;cursor:pointer;height:32px;width:32px;margin:0 5px 5px 0;float:left;border-radius:8px;background:0 0;border:none;padding:0;overflow:hidden}div.preview-postbox>button:focus>div,div.preview-postbox>button:hover>div{box-shadow:inset 0 0 100px rgba(255,255,255,.2)}#profile-jot-plugin-wrapper>div,.jotplugins>div{float:left}#profile-jot-plugin-wrapper::after,.jotplugins::after{content:'';display:block;clear:both}

1
zen_postbox/view/postbox.min.css vendored Normal file
View file

@ -0,0 +1 @@
[class^=postbox-]{display:table-cell;height:350px;width:1000px;max-width:100%;vertical-align:middle;font-family:Arial,sans-serif;font-size:30px;font-weight:700;line-height:35px;text-align:center;padding:50px 30px;box-sizing:border-box}[class^=postbox-] a{color:inherit!important}[class^=postbox-]:focus a,[class^=postbox-]:hover a{text-decoration:underline}.postbox-black{background-color:#000;color:#fff}.postbox-red{background-color:#e2013b;color:#fff}.postbox-green{background-color:#26927f;color:#fff}.postbox-blue{background-color:#2088af;color:#000}.postbox-orange{background-color:#ff6323;color:#000}.postbox-purple{background-color:#7321ad;color:#fff}.postbox-forest{background-color:#165348;color:#fff}.postbox-ocean{background-color:#243762;color:#fff}.postbox-pink{background-color:#f35369;color:#000}.postbox-salmon{background-color:salmon;color:#000}.postbox-darkgray{background-image:linear-gradient(135deg,#777d88,#4f5766);color:#fff}.postbox-mintgray,.postbox-minty{background-image:linear-gradient(135deg,#8fc7ad,#48e5a9);color:#000}.postbox-redblue{background-image:linear-gradient(45deg,#ff0047,#2c34c7);color:#fff}.postbox-violets{background-image:linear-gradient(45deg,#5d3fda,#fc36fd);color:#fff}.postbox-grayblack{background-image:linear-gradient(45deg,#5d6374,#16181d);color:#fff}.postbox-tealblue{background-image:linear-gradient(to bottom,#4bdfdf 0,#207cca 50%,#19094a 100%);color:#fff}.postbox-greengray{background-image:linear-gradient(to right,#c8dbbd 0,#dedede 100%);color:#000}.postbox-tealgray{background-image:linear-gradient(to right,#8dcad0 0,#dedede 100%);color:#000}.postbox-bluegray{background-image:linear-gradient(to right,#94bbeb 0,#dedede 100%);color:#000}.postbox-lavendergray{background-image:linear-gradient(to right,#cfbfda 0,#dedede 100%);color:#000}.postbox-sunset{background-image:linear-gradient(to bottom,#fecf41 0,#fd7440 50%,#b623b1 100%);color:#fff}.postbox-sherbert{background-image:linear-gradient(45deg,#fcd6cd 6%,#f8bc44 25%,#fb7d88 44%,#fb7d88 64%,#fb7d88 64%,#fed640 100%);color:#000}

1
zen_postbox/view/quattro.min.css vendored Normal file
View file

@ -0,0 +1 @@
#profile-postbox-wrapper{display:block;margin-bottom:-50px}#postboxbutton{position:absolute;margin-top:12px;z-index:99;display:none;padding:10px;background-color:#fff;box-shadow:0 5px 10px rgba(0,0,0,.7)}.postbox_button{border:none;background:0 0;height:24px;width:24px;box-shadow:none;padding:0;position:relative;top:8px}.postbox_button>img{height:24px;width:24px}div.preview-postbox div.pick-postbox{height:100%;width:100%;display:block}div.preview-postbox>button{ms-appearance:none;moz-appearance:none;webkit-appearance:none;appearance:none;cursor:pointer;height:32px;width:32px;margin:0 5px 5px 0;float:left;border-radius:8px;background:0 0;border:none;padding:0;overflow:hidden}

1
zen_postbox/view/smoothly.min.css vendored Normal file
View file

@ -0,0 +1 @@
#profile-postbox-wrapper{display:block}#postboxbutton{display:none;position:fixed;background-color:#eee;width:auto;width:fit-content;border-radius:8px;padding:10px;z-index:99;box-shadow:0 0 5px rgba(0,0,0,.7)}.postbox_button>img{height:22px;width:22px;position:relative;margin:4px;-moz-border-radius:0;border-radius:0}div.preview-postbox div.pick-postbox{height:100%;width:100%;display:block}div.preview-postbox>button{ms-appearance:none;moz-appearance:none;webkit-appearance:none;appearance:none;cursor:pointer;height:32px;width:32px;margin:0 5px 5px 0;float:left;border-radius:8px;background:0 0;border:none;padding:0;overflow:hidden}#profile-jot-plugin-wrapper{padding:10px 1px}#profile-jot-plugin-wrapper>div,.jotplugins>div{float:left}#profile-jot-plugin-wrapper::after,.jotplugins::after{content:'';display:block;clear:both}

View file

View file

@ -0,0 +1,37 @@
#profile-postbox-wrapper {
display: block;
}
#postboxbutton {
display: none;
}
.postbox_button > img {
height: 32px;
width: 32px;
cursor: pointer;
}
div.preview-postbox div.pick-postbox {
height: 100%;
width: 100%;
display: block;
}
div.preview-postbox > button {
ms-appearance: none;
moz-appearance: none;
webkit-appearance: none;
appearance: none;
cursor: pointer;
height: 32px;
width: 32px;
margin: 5px;
float: left;
border-radius: 8px;
margin: 0 5px 5px 0;
background: none;
border: none;
padding: 0;
overflow: hidden;
}

View file

@ -0,0 +1,68 @@
#profile-postbox-wrapper {
display: block;
}
#postboxbutton {
display: none;
}
.postbox_button {
height: 18px;
width: 18px;
position: relative;
left: 285px;
top: -62px;
padding: 0;
border: 0;
background: none;
}
.postbox_button > img {
height: 100%;
width: 100%;
}
div.preview-postbox {
border: 1px solid #AAA;
-moz-border-radius: 3px;
border-radius: 3px;
position: relative;
left: 285px;
top: -62px;
padding: 5px;
width: fit-content;
}
div.preview-postbox div.pick-postbox {
height: 100%;
width: 100%;
display: block;
}
div.preview-postbox > button {
ms-appearance: none;
moz-appearance: none;
webkit-appearance: none;
appearance: none;
cursor: pointer;
height: 32px;
width: 32px;
margin: 5px;
float: left;
border-radius: 8px;
margin: 0 5px 5px 0;
background: none;
border: none;
padding: 0;
overflow: hidden;
}
/* fix positioning if more than one jot tool */
.jotplugins > div,
#profile-jot-plugin-wrapper > div {
float: left;
}
.jotplugins::after,
#profile-jot-plugin-wrapper::after {
content: '';
display: block;
clear: both;
}

View file

@ -0,0 +1,69 @@
#profile-postbox-wrapper {
display: block;
}
#postboxbutton {
display: none;
position: fixed;
background-color: #eee;
width: auto;
border-radius: 8px;
padding: 10px;
-webkit-box-shadow: 0 6px 12px rgba(0,0,0,.175);
box-shadow: 0 6px 12px rgba(0,0,0,.175);
}
.jotplugins #postboxbutton {
position: absolute;
}
.postbox_button {
border: none !important;
-webkit-box-shadow: none !important;
-moz-box-shadow: none !important;
box-shadow: none !important;
}
.postbox_button > img {
height: 18px;
width: 18px;
cursor: pointer;
}
div.preview-postbox div.pick-postbox {
height: 100%;
width: 100%;
display: block;
}
div.preview-postbox > button {
ms-appearance: none;
moz-appearance: none;
webkit-appearance: none;
appearance: none;
cursor: pointer;
height: 32px;
width: 32px;
margin: 5px;
float: left;
border-radius: 8px;
margin: 0 5px 5px 0;
background: none;
border: none;
padding: 0;
overflow: hidden;
}
div.preview-postbox > button:hover > div,
div.preview-postbox > button:focus > div {
box-shadow: inset 0 0 100px rgba(255,255,255,.2);
}
/* fix positioning if more than one jot tool */
.jotplugins > div,
#profile-jot-plugin-wrapper > div {
float: left;
}
.jotplugins::after,
#profile-jot-plugin-wrapper::after {
content: '';
display: block;
clear: both;
}

View file

@ -0,0 +1,120 @@
/* Post Backgrounds
================
Solid and Gradient backgrounds with larger text
to grab reader attention
*/
[class^="postbox-"]{
display: table-cell;
height: 350px;
width: 1000px;
max-width: 100%;
vertical-align: middle;
font-family: Arial, sans-serif;
font-size: 30px;
font-weight: 700;
line-height: 35px;
text-align: center;
padding: 50px 30px;
box-sizing: border-box;
}
[class^="postbox-"] a {
color: inherit !important;
}
[class^="postbox-"]:hover a,
[class^="postbox-"]:focus a {
text-decoration: underline;
}
/* Solid Color Backgrounds */
.postbox-black {
background-color: black;
color: white;
}
.postbox-red {
background-color: rgb(226, 1, 59);
color: white;
}
.postbox-green {
background-color: rgb(38, 146, 127);
color: white;
}
.postbox-blue {
background-color: rgb(32, 136, 175);
color: black;
}
.postbox-orange {
background-color: rgb(255, 99, 35);
color: black;
}
.postbox-purple {
background-color: rgb(115, 33, 173);
color: white;
}
.postbox-forest {
background-color: rgb(22, 83, 72);
color: white;
}
.postbox-ocean {
background-color: rgb(36, 55, 98);
color: white;
}
.postbox-pink {
background-color: rgb(243, 83, 105);
color: black;
}
.postbox-salmon {
background-color: rgb(250, 128, 114);
color: black;
}
/* Gradient Backgrounds */
.postbox-darkgray {
background-image: linear-gradient(135deg, rgb(119, 125, 136), rgb(79, 87, 102));
color: white;
}
.postbox-minty {
background-image: linear-gradient(135deg, rgb(143, 199, 173), rgb(72, 229, 169));
color: black;
}
.postbox-mintgray {
background-image: linear-gradient(135deg, rgb(143, 199, 173), rgb(72, 229, 169));
color: black;
}
.postbox-redblue {
background-image: linear-gradient(45deg, rgb(255, 0, 71), rgb(44, 52, 199));
color: white;
}
.postbox-violets {
background-image: linear-gradient(45deg, rgb(93, 63, 218), rgb(252, 54, 253));
color: white;
}
.postbox-grayblack {
background-image: linear-gradient(45deg, rgb(93, 99, 116), rgb(22, 24, 29));
color: white;
}
.postbox-tealblue {
background-image: linear-gradient(to bottom, #4bdfdf 0%,#207cca 50%,#19094a 100%);
color: white;
}
.postbox-greengray {
background-image: linear-gradient(to right, #c8dbbd 0%,#dedede 100%);
color: black;
}
.postbox-tealgray {
background-image: linear-gradient(to right, #8dcad0 0%,#dedede 100%);
color: black;
}
.postbox-bluegray {
background-image: linear-gradient(to right, #94bbeb 0%,#dedede 100%);
color: black;
}
.postbox-lavendergray {
background-image: linear-gradient(to right, #cfbfda 0%,#dedede 100%);
color: black;
}
.postbox-sunset {
background-image: linear-gradient(to bottom, #fecf41 0%,#fd7440 50%,#b623b1 100%);
color: white;
}
.postbox-sherbert {
background-image: linear-gradient(45deg, #fcd6cd 6%,#f8bc44 25%,#fb7d88 44%,#fb7d88 64%,#fb7d88 64%,#fed640 100%);
color: black;
}

View file

@ -0,0 +1,54 @@
#profile-postbox-wrapper {
display: block;
margin-bottom: -50px;
}
#postboxbutton {
position: absolute;
margin-top: 12px;
z-index: 99;
display: none;
padding: 10px;
background-color: #FFF;
box-shadow: 0px 5px 10px rgba(0, 0, 0, 0.7);
}
.postbox_button {
border: none;
background: none;
height: 24px;
width: 24px;
box-shadow: none;
padding: 0;
position: relative;
top: 8px;
}
.postbox_button > img {
height: 24px;
width: 24px;
}
div.preview-postbox div.pick-postbox {
height: 100%;
width: 100%;
display: block;
}
div.preview-postbox > button {
ms-appearance: none;
moz-appearance: none;
webkit-appearance: none;
appearance: none;
cursor: pointer;
height: 32px;
width: 32px;
margin: 5px;
float: left;
border-radius: 8px;
margin: 0 5px 5px 0;
background: none;
border: none;
padding: 0;
overflow: hidden;
}

View file

@ -0,0 +1,63 @@
#profile-postbox-wrapper {
display: block;
}
#postboxbutton {
display: none;
position: fixed;
background-color: #eee;
width: auto;
width: fit-content;
border-radius: 8px;
padding: 10px;
z-index: 99;
box-shadow: 0 0 5px rgba(0,0,0,.7);
}
.postbox_button > img {
height: 22px;
width: 22px;
position: relative;
margin: 4px;
-moz-border-radius: 0px;
border-radius: 0px;
}
div.preview-postbox div.pick-postbox {
height: 100%;
width: 100%;
display: block;
}
div.preview-postbox > button {
ms-appearance: none;
moz-appearance: none;
webkit-appearance: none;
appearance: none;
cursor: pointer;
height: 32px;
width: 32px;
margin: 5px;
float: left;
border-radius: 8px;
margin: 0 5px 5px 0;
background: none;
border: none;
padding: 0;
overflow: hidden;
}
/* fix positioning if more than one jot tool */
#profile-jot-plugin-wrapper {
padding: 10px 1px;
}
/* fix positioning if more than one jot tool */
.jotplugins > div,
#profile-jot-plugin-wrapper > div {
float: left;
}
.jotplugins::after,
#profile-jot-plugin-wrapper::after {
content: '';
display: block;
clear: both;
}

View file

@ -0,0 +1,60 @@
#profile-postbox-wrapper {
float: left;
margin-left: 15px;
cursor: pointer;
height: 10px;
display: inline-block;
}
#profile-postbox-wrapper .btn {
padding: 0;
margin: 0;
border: 0;
background: none;
width: 20px;
height: 20px;
line-height: inherit;
display: inline-block;
overflow: hidden;
padding: 1px;
color: #999;
vertical-align: text-top;
}
#postboxbutton {
position: absolute;
z-index: 99;
display: none;
padding: 10px;
background-color: #FFF;
box-shadow: 0px 5px 10px rgba(0, 0, 0, 0.7);
}
.postbox_button > img {
height: 18px;
width: 18px;
margin-right: 18px;
}
div.preview-postbox div.pick-postbox {
height: 100%;
width: 100%;
display: block;
}
div.preview-postbox > button {
ms-appearance: none;
moz-appearance: none;
webkit-appearance: none;
appearance: none;
cursor: pointer;
height: 32px;
width: 32px;
margin: 5px;
float: left;
border-radius: 8px;
margin: 0 5px 5px 0;
background: none;
border: none;
padding: 0;
overflow: hidden;
}

1
zen_postbox/view/vier.min.css vendored Normal file
View file

@ -0,0 +1 @@
#profile-postbox-wrapper{float:left;margin-left:15px;cursor:pointer;height:10px;display:inline-block}#profile-postbox-wrapper .btn{padding:1px;margin:0;border:0;background:0 0;width:20px;height:20px;line-height:inherit;display:inline-block;overflow:hidden;color:#999;vertical-align:text-top}#postboxbutton{position:absolute;z-index:99;display:none;padding:10px;background-color:#fff;box-shadow:0 5px 10px rgba(0,0,0,.7)}.postbox_button>img{height:18px;width:18px;margin-right:18px}div.preview-postbox div.pick-postbox{height:100%;width:100%;display:block}div.preview-postbox>button{ms-appearance:none;moz-appearance:none;webkit-appearance:none;appearance:none;cursor:pointer;height:32px;width:32px;margin:0 5px 5px 0;float:left;border-radius:8px;background:0 0;border:none;padding:0;overflow:hidden}

184
zen_postbox/zen_postbox.php Normal file
View file

@ -0,0 +1,184 @@
<?php
/**
* Name: Zen Postbox
* Description: Adds a button to editor to insert color background. Called Zen to load last.
* Version: 1.0
* Author: Random Penguin <https://gitlab.com/randompenguin>
*/
use Friendica\App;
use Friendica\Core\Hook;
use Friendica\DI;
function zen_postbox_install()
{
//Register hooks
Hook::register('jot_tool', 'addon/zen_postbox/zen_postbox.php', 'zen_postbox_jot_tool');
}
function zen_postbox_jot_tool(string &$body)
{
$labels = [
'Black',
'Red',
'Green',
'Blue',
'Orange',
'Purple',
'Forest',
'Ocean',
'Pink',
'Salmon',
'Dark Gray',
'Minty',
'Mint Gray',
'Red-Blue',
'Violets',
'Gray-Black',
'Teal Blue',
'Green Gray',
'Teal Gray',
'Blue Gray',
'Lavender Gray',
'Sunset',
'Sherbert',
];
$texts = [
'[class=postbox-black]',
'[class=postbox-red]',
'[class=postbox-green]',
'[class=postbox-blue]',
'[class=postbox-orange]',
'[class=postbox-purple]',
'[class=postbox-forest]',
'[class=postbox-ocean]',
'[class=postbox-pink]',
'[class=postbox-salmon]',
'[class=postbox-darkgray]',
'[class=postbox-minty]',
'[class=postbox-mintgray]',
'[class=postbox-redblue]',
'[class=postbox-violets]',
'[class=postbox-grayblack]',
'[class=postbox-tealblue]',
'[class=postbox-greengray]',
'[class=postbox-tealgray]',
'[class=postbox-bluegray]',
'[class=postbox-lavendergray]',
'[class=postbox-sunset]',
'[class=postbox-sherbert]',
];
$icons = [
'<div class="pick-postbox postbox-black"></div>',
'<div class="pick-postbox postbox-red"></div>',
'<div class="pick-postbox postbox-green"></div>',
'<div class="pick-postbox postbox-blue"></div>',
'<div class="pick-postbox postbox-orange"></div>',
'<div class="pick-postbox postbox-purple"></div>',
'<div class="pick-postbox postbox-forest"></div>',
'<div class="pick-postbox postbox-ocean"></div>',
'<div class="pick-postbox postbox-pink"></div>',
'<div class="pick-postbox postbox-salmon"></div>',
'<div class="pick-postbox postbox-darkgray"></div>',
'<div class="pick-postbox postbox-minty"></div>',
'<div class="pick-postbox postbox-mintgray"></div>',
'<div class="pick-postbox postbox-redblue"></div>',
'<div class="pick-postbox postbox-violets"></div>',
'<div class="pick-postbox postbox-grayblack"></div>',
'<div class="pick-postbox postbox-tealblue"></div>',
'<div class="pick-postbox postbox-greengray"></div>',
'<div class="pick-postbox postbox-tealgray"></div>',
'<div class="pick-postbox postbox-bluegray"></div>',
'<div class="pick-postbox postbox-lavendergray"></div>',
'<div class="pick-postbox postbox-sunset"></div>',
'<div class="pick-postbox postbox-sherbert"></div>',
];
$params = ['texts' => $texts, 'icons' => $icons, 'string' => '', 'labels' => $labels];
//Generate html for smiley list
$s = '<div class="preview-postbox"><tr>';
for ($x = 0; $x < count($params['texts']); $x++) {
$icon = $params['icons'][$x];
$s .= '<button type="button" title="' . $params['labels'][$x] . '" onclick="postbox_addbox(\'' . $params['texts'][$x] . '\')">' . $icon . '</button>';
}
$s .= '</div>';
//Add control css to header
$css_file = __DIR__ . '/view/' . DI::app()->getCurrentTheme() . '.min.css';
if (!file_exists($css_file)) {
$css_file = __DIR__ . '/view/default.min.css';
}
DI::page()->registerStylesheet($css_file);
// Add zen_postbox Styling to Header
$box_styles = __DIR__ . '/view/postbox.min.css';
DI::page()->registerStylesheet($box_styles);
//Get the correct image for the theme
$image = 'addon/zen_postbox/view/default.png';
$image_url = DI::baseUrl() . '/' . $image;
//Append the hmtl and script to the page
$body .= <<< EOT
<div id="profile-postbox-wrapper">
<button type="button" class="btn btn-link postbox_button" onclick="toggle_postboxbutton()"><img src="$image_url" alt="postbox"></button>
<div id="postboxbutton">
$s
</div>
</div>
<script>
// store states
var postboxbutton_is_shown = 0;
var sel_start, sel_end;
var selected_text = "";
var area = {};
// open/close background choices
function toggle_postboxbutton() {
postbox_selection();
if (! postboxbutton_is_shown) {
$("#postboxbutton").show();
postboxbutton_is_shown = 1;
} else {
$("#postboxbutton").hide();
postboxbutton_is_shown = 0;
}
}
// get textarea selected text (if any)
function postbox_selection(){
// modal or compose?
if (document.getElementsByTagName('body')[0].className.match(/mod-compose/)){
area = document.getElementById('comment-edit-text-0');
} else {
area = document.getElementById('profile-jot-text');
}
var val = area.value;
sel_start = area.selectionStart;
sel_end = area.selectionEnd;
selected_text = val.substr( sel_start, sel_end - sel_start );
area.focus();
area.setSelectionRange(sel_start,sel_end);
}
// select and apply postbox
function postbox_addbox(bbcode){
postbox_selection();
if (selected_text != ""){
area.value = area.value.substr(0, sel_start)+bbcode+selected_text+'[/class]'+area.value.substr(sel_end);
} else {
area.value += bbcode+'...[/class]';
}
// clear out selection
selected_text = "";
sel_start = stel_end = null;
// close background box and shift focus back to textarea
toggle_postboxbutton();
area.focus();
}
</script>
EOT;
}