Merge remote-tracking branch 'upstream/2023.03-rc' into remove-tab

This commit is contained in:
Michael 2023-03-20 04:16:52 +00:00
commit b7288b2bfd
23 changed files with 777 additions and 166 deletions

View File

@ -29,6 +29,7 @@
"asika/simple-console": "^1.0", "asika/simple-console": "^1.0",
"bacon/bacon-qr-code": "^2.0.0", "bacon/bacon-qr-code": "^2.0.0",
"divineomega/password_exposed": "^2.8", "divineomega/password_exposed": "^2.8",
"enyo/dropzone": "^5.9",
"ezyang/htmlpurifier": "^4.7", "ezyang/htmlpurifier": "^4.7",
"friendica/json-ld": "^1.0", "friendica/json-ld": "^1.0",
"geekwright/po": "^2.0", "geekwright/po": "^2.0",

38
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "5af9ac9003f4653f3aa1860dd5a4d821", "content-hash": "c9e005c79c8556215c30a66c470659eb",
"packages": [ "packages": [
{ {
"name": "asika/simple-console", "name": "asika/simple-console",
@ -550,6 +550,42 @@
"description": "This PHP package provides a `password_exposed` helper function, that uses the haveibeenpwned.com API to check if a password has been exposed in a data breach.", "description": "This PHP package provides a `password_exposed` helper function, that uses the haveibeenpwned.com API to check if a password has been exposed in a data breach.",
"time": "2019-01-25T12:00:28+00:00" "time": "2019-01-25T12:00:28+00:00"
}, },
{
"name": "enyo/dropzone",
"version": "v5.9.3",
"source": {
"type": "git",
"url": "https://github.com/dropzone/dropzone-packagist.git",
"reference": "286b2dc1f1195bd12169e4c9d5f91cfbe46e245f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/dropzone/dropzone-packagist/zipball/286b2dc1f1195bd12169e4c9d5f91cfbe46e245f",
"reference": "286b2dc1f1195bd12169e4c9d5f91cfbe46e245f",
"shasum": ""
},
"type": "library",
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Matias Meno",
"email": "m@tias.me",
"homepage": "http://www.yesmeno.com"
}
],
"description": "Handles drag and drop of files for you.",
"homepage": "http://www.dropzonejs.com",
"keywords": [
"drag and drop",
"dragndrop",
"file upload",
"upload"
],
"time": "2021-09-21T17:03:36+00:00"
},
{ {
"name": "ezyang/htmlpurifier", "name": "ezyang/htmlpurifier",
"version": "v4.14.0", "version": "v4.14.0",

View File

@ -1139,7 +1139,7 @@ function photos_content(App $a)
'$preview' => DI::l10n()->t('Preview'), '$preview' => DI::l10n()->t('Preview'),
'$loading' => DI::l10n()->t('Loading...'), '$loading' => DI::l10n()->t('Loading...'),
'$qcomment' => $qcomment, '$qcomment' => $qcomment,
'$rand_num' => Crypto::randomDigits(12) '$rand_num' => Crypto::randomDigits(12),
]); ]);
} }
} }
@ -1194,7 +1194,7 @@ function photos_content(App $a)
'$submit' => DI::l10n()->t('Submit'), '$submit' => DI::l10n()->t('Submit'),
'$preview' => DI::l10n()->t('Preview'), '$preview' => DI::l10n()->t('Preview'),
'$qcomment' => $qcomment, '$qcomment' => $qcomment,
'$rand_num' => Crypto::randomDigits(12) '$rand_num' => Crypto::randomDigits(12),
]); ]);
} }
@ -1268,7 +1268,7 @@ function photos_content(App $a)
'$submit' => DI::l10n()->t('Submit'), '$submit' => DI::l10n()->t('Submit'),
'$preview' => DI::l10n()->t('Preview'), '$preview' => DI::l10n()->t('Preview'),
'$qcomment' => $qcomment, '$qcomment' => $qcomment,
'$rand_num' => Crypto::randomDigits(12) '$rand_num' => Crypto::randomDigits(12),
]); ]);
} }
} }

View File

@ -258,6 +258,9 @@ class Page implements ArrayAccess
'$announceError' => $l10n->t('Sharing not successfull'), '$announceError' => $l10n->t('Sharing not successfull'),
'$srvError' => $l10n->t('Backend error'), '$srvError' => $l10n->t('Backend error'),
'$netError' => $l10n->t('Network error'), '$netError' => $l10n->t('Network error'),
// Dropzone
'$max_imagesize' => round(\Friendica\Util\Strings::getBytesFromShorthand($config->get('system', 'maximagesize')) / 1000000, 1),
]) . $this->page['htmlhead']; ]) . $this->page['htmlhead'];
} }

View File

@ -1475,8 +1475,8 @@ class BBCode
$text = preg_replace("/\[list=((?-i)I)\](.*?)\[\/list\]/ism", '</p><ul class="listupperroman" style="list-style-type: upper-roman;">$2</ul><p>', $text); $text = preg_replace("/\[list=((?-i)I)\](.*?)\[\/list\]/ism", '</p><ul class="listupperroman" style="list-style-type: upper-roman;">$2</ul><p>', $text);
$text = preg_replace("/\[list=((?-i)a)\](.*?)\[\/list\]/ism", '</p><ul class="listloweralpha" style="list-style-type: lower-alpha;">$2</ul><p>', $text); $text = preg_replace("/\[list=((?-i)a)\](.*?)\[\/list\]/ism", '</p><ul class="listloweralpha" style="list-style-type: lower-alpha;">$2</ul><p>', $text);
$text = preg_replace("/\[list=((?-i)A)\](.*?)\[\/list\]/ism", '</p><ul class="listupperalpha" style="list-style-type: upper-alpha;">$2</ul><p>', $text); $text = preg_replace("/\[list=((?-i)A)\](.*?)\[\/list\]/ism", '</p><ul class="listupperalpha" style="list-style-type: upper-alpha;">$2</ul><p>', $text);
$text = preg_replace("/\[ul\](.*?)\[\/ul\]/ism", '</p><ul class="listbullet" style="list-style-type: circle;">$1</ul><p>', $text); $text = preg_replace("/\[ul\](.*?)\[\/ul\]/ism", '</p><ul>$1</ul><p>', $text);
$text = preg_replace("/\[ol\](.*?)\[\/ol\]/ism", '</p><ul class="listdecimal" style="list-style-type: decimal;">$1</ul><p>', $text); $text = preg_replace("/\[ol\](.*?)\[\/ol\]/ism", '</p><ol>$1</ol><p>', $text);
$text = preg_replace("/\[li\](.*?)\[\/li\]/ism", '<li>$1</li>', $text); $text = preg_replace("/\[li\](.*?)\[\/li\]/ism", '<li>$1</li>', $text);
} }

View File

@ -281,9 +281,9 @@ class HTML
self::tagToBBCode($doc, 'div', [], "\r", "\r"); self::tagToBBCode($doc, 'div', [], "\r", "\r");
self::tagToBBCode($doc, 'p', [], "\n", "\n"); self::tagToBBCode($doc, 'p', [], "\n", "\n");
self::tagToBBCode($doc, 'ul', [], "[list]", "[/list]"); self::tagToBBCode($doc, 'ul', [], "[ul]", "\n[/ul]");
self::tagToBBCode($doc, 'ol', [], "[list=1]", "[/list]"); self::tagToBBCode($doc, 'ol', [], "[ol]", "\n[/ol]");
self::tagToBBCode($doc, 'li', [], "[*]", ""); self::tagToBBCode($doc, 'li', [], "\n[*]", "");
self::tagToBBCode($doc, 'hr', [], "[hr]", ""); self::tagToBBCode($doc, 'hr', [], "[hr]", "");
@ -349,33 +349,6 @@ class HTML
$message = str_replace("\n\n\n", "\n\n", $message); $message = str_replace("\n\n\n", "\n\n", $message);
} while ($oldmessage != $message); } while ($oldmessage != $message);
do {
$oldmessage = $message;
$message = str_replace(
[
"[/size]\n\n",
"\n[hr]",
"[hr]\n",
"\n[list",
"[/list]\n",
"\n[/",
"[list]\n",
"[list=1]\n",
"\n[*]"],
[
"[/size]\n",
"[hr]",
"[hr]",
"[list",
"[/list]",
"[/",
"[list]",
"[list=1]",
"[*]"],
$message
);
} while ($message != $oldmessage);
$message = str_replace( $message = str_replace(
['[b][b]', '[/b][/b]', '[i][i]', '[/i][/i]'], ['[b][b]', '[/b][/b]', '[i][i]', '[/i][/i]'],
['[b]', '[/b]', '[i]', '[/i]'], ['[b]', '[/b]', '[i]', '[/i]'],

View File

@ -55,19 +55,17 @@ class Session
* @param LoggerInterface $logger * @param LoggerInterface $logger
* @param Profiler $profiler * @param Profiler $profiler
* @param array $server * @param array $server
* @return IHandleSessions
*/ */
public function createSession(App\Mode $mode, App\BaseURL $baseURL, IManageConfigValues $config, Database $dba, Cache $cacheFactory, LoggerInterface $logger, Profiler $profiler, array $server = []): IHandleSessions public function create(App\Mode $mode, App\BaseURL $baseURL, IManageConfigValues $config, Database $dba, Cache $cacheFactory, LoggerInterface $logger, Profiler $profiler, array $server = []): IHandleSessions
{ {
$profiler->startRecording('session'); $profiler->startRecording('session');
$session = null; $session_handler = $config->get('system', 'session_handler', self::HANDLER_DEFAULT);
try { try {
if ($mode->isInstall() || $mode->isBackend()) { if ($mode->isInstall() || $mode->isBackend()) {
$session = new Type\Memory(); $session = new Type\Memory();
} else { } else {
$session_handler = $config->get('system', 'session_handler', self::HANDLER_DEFAULT);
$handler = null;
switch ($session_handler) { switch ($session_handler) {
case self::HANDLER_DATABASE: case self::HANDLER_DATABASE:
$handler = new Handler\Database($dba, $logger, $server); $handler = new Handler\Database($dba, $logger, $server);
@ -82,10 +80,15 @@ class Session
$handler = new Handler\Cache($cache, $logger); $handler = new Handler\Cache($cache, $logger);
} }
break; break;
default:
$handler = null;
} }
$session = new Type\Native($baseURL, $handler); $session = new Type\Native($baseURL, $handler);
} }
} catch (\Throwable $e) {
$logger->notice('Unable to create session', ['mode' => $mode, 'session_handler' => $session_handler, 'exception' => $e]);
$session = new Type\Memory();
} finally { } finally {
$profiler->stopRecording(); $profiler->stopRecording();
return $session; return $session;

View File

@ -589,7 +589,7 @@ class Item
public static function isValid(array $item): bool public static function isValid(array $item): bool
{ {
// When there is no content then we don't post it // When there is no content then we don't post it
if (($item['body'] . $item['title'] == '') && empty($item['quote-uri-id']) && (empty($item['uri-id']) || !Post\Media::existsByURIId($item['uri-id']))) { if (($item['body'] . $item['title'] == '') && empty($item['quote-uri-id']) && empty($item['attachments']) && (empty($item['uri-id']) || !Post\Media::existsByURIId($item['uri-id']))) {
Logger::notice('No body, no title.'); Logger::notice('No body, no title.');
return false; return false;
} }

View File

@ -334,7 +334,7 @@ class Profile
if (!$local_user_is_self) { if (!$local_user_is_self) {
if (!$visitor_is_authenticated) { if (!$visitor_is_authenticated) {
// Remote follow is only available for local profiles // Remote follow is only available for local profiles
if (!empty($profile['nickname']) && strpos($profile_url, DI::baseUrl()) === 0) { if (!empty($profile['nickname']) && strpos($profile_url, (string)DI::baseUrl()) === 0) {
$follow_link = 'profile/' . $profile['nickname'] . '/remote_follow'; $follow_link = 'profile/' . $profile['nickname'] . '/remote_follow';
} }
} else { } else {

View File

@ -25,7 +25,7 @@ use Friendica\App;
use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\L10n; use Friendica\Core\L10n;
use Friendica\Core\Session\Capability\IHandleUserSessions; use Friendica\Core\Session\Capability\IHandleUserSessions;
use Friendica\Database\Database; use Friendica\Core\System;
use Friendica\Model\Attach; use Friendica\Model\Attach;
use Friendica\Model\User; use Friendica\Model\User;
use Friendica\Module\Response; use Friendica\Module\Response;
@ -42,9 +42,6 @@ use Psr\Log\LoggerInterface;
*/ */
class Upload extends \Friendica\BaseModule class Upload extends \Friendica\BaseModule
{ {
/** @var Database */
private $database;
/** @var IHandleUserSessions */ /** @var IHandleUserSessions */
private $userSession; private $userSession;
@ -57,31 +54,32 @@ class Upload extends \Friendica\BaseModule
/** @var bool */ /** @var bool */
private $isJson; private $isJson;
public function __construct(SystemMessages $systemMessages, IManageConfigValues $config, IHandleUserSessions $userSession, Database $database, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = []) /** @var App\Page */
private $page;
public function __construct(App\Page $page, SystemMessages $systemMessages, IManageConfigValues $config, IHandleUserSessions $userSession, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = [])
{ {
parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters);
$this->database = $database;
$this->userSession = $userSession; $this->userSession = $userSession;
$this->config = $config; $this->config = $config;
$this->systemMessages = $systemMessages; $this->systemMessages = $systemMessages;
$this->page = $page;
} }
protected function post(array $request = []) protected function post(array $request = [])
{ {
if ($this->isJson = !empty($request['response']) && $request['response'] == 'json') { $this->isJson = !empty($request['response']) && $request['response'] == 'json';
$this->response->setType(Response::TYPE_JSON, 'application/json');
}
$owner = User::getOwnerDataById($this->userSession->getLocalUserId()); $owner = User::getOwnerDataById($this->userSession->getLocalUserId());
if (!$owner) { if (!$owner) {
$this->logger->warning('Owner not found.', ['uid' => $this->userSession->getLocalUserId()]); $this->logger->warning('Owner not found.', ['uid' => $this->userSession->getLocalUserId()]);
return $this->return(401, $this->t('Invalid request.')); $this->return(401, $this->t('Invalid request.'));
} }
if (empty($_FILES['userfile'])) { if (empty($_FILES['userfile'])) {
$this->logger->warning('No file uploaded (empty userfile)'); $this->logger->warning('No file uploaded (empty userfile)');
return $this->return(401, $this->t('Invalid request.'), true); $this->return(401, $this->t('Invalid request.'), true);
} }
$tempFileName = $_FILES['userfile']['tmp_name']; $tempFileName = $_FILES['userfile']['tmp_name'];
@ -98,14 +96,14 @@ class Upload extends \Friendica\BaseModule
@unlink($tempFileName); @unlink($tempFileName);
$msg = $this->t('Sorry, maybe your upload is bigger than the PHP configuration allows') . '<br />' . $this->t('Or - did you try to upload an empty file?'); $msg = $this->t('Sorry, maybe your upload is bigger than the PHP configuration allows') . '<br />' . $this->t('Or - did you try to upload an empty file?');
$this->logger->warning($msg, ['fileSize' => $fileSize]); $this->logger->warning($msg, ['fileSize' => $fileSize]);
return $this->return(401, $msg, true); $this->return(401, $msg, true);
} }
if ($maxFileSize && $fileSize > $maxFileSize) { if ($maxFileSize && $fileSize > $maxFileSize) {
@unlink($tempFileName); @unlink($tempFileName);
$msg = $this->t('File exceeds size limit of %s', Strings::formatBytes($maxFileSize)); $msg = $this->t('File exceeds size limit of %s', Strings::formatBytes($maxFileSize));
$this->logger->warning($msg, ['fileSize' => $fileSize]); $this->logger->warning($msg, ['fileSize' => $fileSize]);
return $this->return(401, $msg); $this->return(401, $msg);
} }
$newid = Attach::storeFile($tempFileName, $owner['uid'], $fileName, '<' . $owner['id'] . '>'); $newid = Attach::storeFile($tempFileName, $owner['uid'], $fileName, '<' . $owner['id'] . '>');
@ -115,16 +113,16 @@ class Upload extends \Friendica\BaseModule
if ($newid === false) { if ($newid === false) {
$msg = $this->t('File upload failed.'); $msg = $this->t('File upload failed.');
$this->logger->warning($msg); $this->logger->warning($msg);
return $this->return(500, $msg); $this->return(500, $msg);
} }
if ($this->isJson) { if ($this->isJson) {
$content = json_encode(['ok' => true, 'id' => $newid], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); $content = $newid;
} else { } else {
$content = "\n\n" . '[attachment]' . $newid . '[/attachment]' . "\n"; $content = "\n\n" . '[attachment]' . $newid . '[/attachment]' . "\n";
} }
return $this->response->addContent($content); $this->return(200, $content);
} }
/** /**
@ -136,16 +134,23 @@ class Upload extends \Friendica\BaseModule
*/ */
private function return(int $httpCode, string $message, bool $systemMessage = false): void private function return(int $httpCode, string $message, bool $systemMessage = false): void
{ {
$this->response->setStatus($httpCode, $message);
if ($this->isJson) { if ($this->isJson) {
$this->response->addContent(json_encode(['error' => $message], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)); $message = $httpCode >= 400 ? ['error' => $message] : ['ok' => true, 'id' => $message];
$this->response->setType(Response::TYPE_JSON, 'application/json');
$this->response->addContent(json_encode($message, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
} else { } else {
if ($systemMessage) { if ($systemMessage) {
$this->systemMessages->addNotice($message); $this->systemMessages->addNotice($message);
} }
if ($httpCode >= 400) {
$this->response->setStatus($httpCode, $message);
}
$this->response->addContent($message); $this->response->addContent($message);
} }
$this->page->exit($this->response->generate());
System::exit();
} }
} }

View File

@ -25,10 +25,9 @@ use Friendica\App;
use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\L10n; use Friendica\Core\L10n;
use Friendica\Core\Session\Capability\IHandleUserSessions; use Friendica\Core\Session\Capability\IHandleUserSessions;
use Friendica\Database\Database; use Friendica\Core\System;
use Friendica\Model\Photo; use Friendica\Model\Photo;
use Friendica\Model\User; use Friendica\Model\User;
use Friendica\Module\BaseApi;
use Friendica\Module\Response; use Friendica\Module\Response;
use Friendica\Navigation\SystemMessages; use Friendica\Navigation\SystemMessages;
use Friendica\Network\HTTPException\InternalServerErrorException; use Friendica\Network\HTTPException\InternalServerErrorException;
@ -45,9 +44,6 @@ use Psr\Log\LoggerInterface;
*/ */
class Upload extends \Friendica\BaseModule class Upload extends \Friendica\BaseModule
{ {
/** @var Database */
private $database;
/** @var IHandleUserSessions */ /** @var IHandleUserSessions */
private $userSession; private $userSession;
@ -60,14 +56,17 @@ class Upload extends \Friendica\BaseModule
/** @var bool */ /** @var bool */
private $isJson = false; private $isJson = false;
public function __construct(IManageConfigValues $config, SystemMessages $systemMessages, IHandleUserSessions $userSession, Database $database, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = []) /** @var App\Page */
private $page;
public function __construct(App\Page $page, IManageConfigValues $config, SystemMessages $systemMessages, IHandleUserSessions $userSession, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = [])
{ {
parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters);
$this->database = $database;
$this->userSession = $userSession; $this->userSession = $userSession;
$this->systemMessages = $systemMessages; $this->systemMessages = $systemMessages;
$this->config = $config; $this->config = $config;
$this->page = $page;
} }
protected function post(array $request = []) protected function post(array $request = [])
@ -80,12 +79,12 @@ class Upload extends \Friendica\BaseModule
if (!$owner) { if (!$owner) {
$this->logger->warning('Owner not found.', ['uid' => $this->userSession->getLocalUserId()]); $this->logger->warning('Owner not found.', ['uid' => $this->userSession->getLocalUserId()]);
return $this->return(401, $this->t('Invalid request.')); $this->return(401, $this->t('Invalid request.'));
} }
if (empty($_FILES['userfile']) && empty($_FILES['media'])) { if (empty($_FILES['userfile']) && empty($_FILES['media'])) {
$this->logger->warning('Empty "userfile" and "media" field'); $this->logger->warning('Empty "userfile" and "media" field');
return $this->return(401, $this->t('Invalid request.')); $this->return(401, $this->t('Invalid request.'));
} }
$src = ''; $src = '';
@ -134,7 +133,7 @@ class Upload extends \Friendica\BaseModule
if ($src == '') { if ($src == '') {
$this->logger->warning('File source (temporary file) cannot be determined', ['$_FILES' => $_FILES]); $this->logger->warning('File source (temporary file) cannot be determined', ['$_FILES' => $_FILES]);
return $this->return(401, $this->t('Invalid request.'), true); $this->return(401, $this->t('Invalid request.'), true);
} }
$filetype = Images::getMimeTypeBySource($src, $filename, $filetype); $filetype = Images::getMimeTypeBySource($src, $filename, $filetype);
@ -152,7 +151,7 @@ class Upload extends \Friendica\BaseModule
if (!$image->isValid()) { if (!$image->isValid()) {
@unlink($src); @unlink($src);
$this->logger->warning($this->t('Unable to process image.'), ['imagedata[]' => gettype($imagedata), 'filetype' => $filetype]); $this->logger->warning($this->t('Unable to process image.'), ['imagedata[]' => gettype($imagedata), 'filetype' => $filetype]);
return $this->return(401, $this->t('Unable to process image.')); $this->return(401, $this->t('Unable to process image.'));
} }
$image->orient($src); $image->orient($src);
@ -185,7 +184,7 @@ class Upload extends \Friendica\BaseModule
if ($filesize > $maximagesize) { if ($filesize > $maximagesize) {
@unlink($src); @unlink($src);
$this->logger->notice('Image size is too big', ['size' => $filesize, 'max' => $maximagesize]); $this->logger->notice('Image size is too big', ['size' => $filesize, 'max' => $maximagesize]);
return $this->return(401, $this->t('Image exceeds size limit of %s', Strings::formatBytes($maximagesize))); $this->return(401, $this->t('Image exceeds size limit of %s', Strings::formatBytes($maximagesize)));
} }
} }
@ -203,7 +202,7 @@ class Upload extends \Friendica\BaseModule
$result = Photo::store($image, $owner['uid'], 0, $resource_id, $filename, $album, 0, Photo::DEFAULT, $allow_cid); $result = Photo::store($image, $owner['uid'], 0, $resource_id, $filename, $album, 0, Photo::DEFAULT, $allow_cid);
if (!$result) { if (!$result) {
$this->logger->warning('Photo::store() failed', ['result' => $result]); $this->logger->warning('Photo::store() failed', ['result' => $result]);
return $this->return(401, $this->t('Image upload failed.')); $this->return(401, $this->t('Image upload failed.'));
} }
if ($width > 640 || $height > 640) { if ($width > 640 || $height > 640) {
@ -223,7 +222,7 @@ class Upload extends \Friendica\BaseModule
} }
$this->logger->info('upload done'); $this->logger->info('upload done');
return $this->return(200, "\n\n" . '[url=' . $this->baseUrl . '/photos/' . $owner['nickname'] . '/image/' . $resource_id . '][img]' . $this->baseUrl . "/photo/$resource_id-$smallest." . $image->getExt() . "[/img][/url]\n\n"); $this->return(200, "\n\n" . '[url=' . $this->baseUrl . '/photos/' . $owner['nickname'] . '/image/' . $resource_id . '][img]' . $this->baseUrl . "/photo/$resource_id-$smallest." . $image->getExt() . "[/img][/url]\n\n");
} }
/** /**
@ -250,5 +249,8 @@ class Upload extends \Friendica\BaseModule
$this->response->addContent($message); $this->response->addContent($message);
} }
$this->page->exit($this->response->generate());
System::exit();
} }
} }

View File

@ -237,7 +237,7 @@ return [
IHandleSessions::class => [ IHandleSessions::class => [
'instanceOf' => \Friendica\Core\Session\Factory\Session::class, 'instanceOf' => \Friendica\Core\Session\Factory\Session::class,
'call' => [ 'call' => [
['createSession', [$_SERVER], Dice::CHAIN_CALL], ['create', [$_SERVER], Dice::CHAIN_CALL],
['start', [], Dice::CHAIN_CALL], ['start', [], Dice::CHAIN_CALL],
], ],
], ],

View File

@ -158,21 +158,21 @@ class BBCodeTest extends FixtureTest
{ {
return [ return [
'bug-7271-condensed-space' => [ 'bug-7271-condensed-space' => [
'expectedHtml' => '<ul class="listdecimal" style="list-style-type:decimal;"><li> <a href="http://example.com/" target="_blank" rel="noopener noreferrer">http://example.com/</a></li></ul>', 'expectedHtml' => '<ol><li> <a href="http://example.com/" target="_blank" rel="noopener noreferrer">http://example.com/</a></li></ol>',
'text' => '[ol][*] http://example.com/[/ol]', 'text' => '[ol][*] http://example.com/[/ol]',
], ],
'bug-7271-condensed-nospace' => [ 'bug-7271-condensed-nospace' => [
'expectedHtml' => '<ul class="listdecimal" style="list-style-type:decimal;"><li><a href="http://example.com/" target="_blank" rel="noopener noreferrer">http://example.com/</a></li></ul>', 'expectedHtml' => '<ol><li><a href="http://example.com/" target="_blank" rel="noopener noreferrer">http://example.com/</a></li></ol>',
'text' => '[ol][*]http://example.com/[/ol]', 'text' => '[ol][*]http://example.com/[/ol]',
], ],
'bug-7271-indented-space' => [ 'bug-7271-indented-space' => [
'expectedHtml' => '<ul class="listbullet" style="list-style-type:circle;"><li> <a href="http://example.com/" target="_blank" rel="noopener noreferrer">http://example.com/</a></li></ul>', 'expectedHtml' => '<ul><li> <a href="http://example.com/" target="_blank" rel="noopener noreferrer">http://example.com/</a></li></ul>',
'text' => '[ul] 'text' => '[ul]
[*] http://example.com/ [*] http://example.com/
[/ul]', [/ul]',
], ],
'bug-7271-indented-nospace' => [ 'bug-7271-indented-nospace' => [
'expectedHtml' => '<ul class="listbullet" style="list-style-type:circle;"><li><a href="http://example.com/" target="_blank" rel="noopener noreferrer">http://example.com/</a></li></ul>', 'expectedHtml' => '<ul><li><a href="http://example.com/" target="_blank" rel="noopener noreferrer">http://example.com/</a></li></ul>',
'text' => '[ul] 'text' => '[ul]
[*]http://example.com/ [*]http://example.com/
[/ul]', [/ul]',
@ -259,13 +259,21 @@ Karl Marx - Die ursprüngliche Akkumulation
'text' => '[emoji=https://fedi.underscore.world/emoji/custom/custom/heart_nb.png]:heart_nb:[/emoji]', 'text' => '[emoji=https://fedi.underscore.world/emoji/custom/custom/heart_nb.png]:heart_nb:[/emoji]',
], ],
'task-12900-multiple-paragraphs' => [ 'task-12900-multiple-paragraphs' => [
'expectedHTML' => '<h1>Header</h1><ul class="listbullet" style="list-style-type:circle;"><li>One</li><li>Two</li></ul><p>This is a paragraph<br>with a line feed.</p><p>Second Chapter</p>', 'expectedHTML' => '<h1>Header</h1><ul><li>One</li><li>Two</li></ul><p>This is a paragraph<br>with a line feed.</p><p>Second Chapter</p>',
'text' => "[h1]Header[/h1][ul][*]One[*]Two[/ul]\n\nThis is a paragraph\nwith a line feed.\n\nSecond Chapter", 'text' => "[h1]Header[/h1][ul][*]One[*]Two[/ul]\n\nThis is a paragraph\nwith a line feed.\n\nSecond Chapter",
], ],
'task-12900-header-with-paragraphs' => [ 'task-12900-header-with-paragraphs' => [
'expectedHTML' => '<h1>Header</h1><p>Some Chapter</p>', 'expectedHTML' => '<h1>Header</h1><p>Some Chapter</p>',
'text' => '[h1]Header[/h1]Some Chapter', 'text' => '[h1]Header[/h1]Some Chapter',
] ],
'bug-12842-ul-newlines' => [
'expectedHTML' => '<p>This is:</p><ul><li>some<br></li><li>amazing<br></li><li>list</li></ul>',
'text' => "This is:\r\n[ul]\r\n[*]some\r\n[*]amazing\r\n[*]list\r\n[/ul]",
],
'bug-12842-ol-newlines' => [
'expectedHTML' => '<p>This is:</p><ol><li>some<br></li><li>amazing<br></li><li>list</li></ol>',
'text' => "This is:\r\n[ol]\r\n[*]some\r\n[*]amazing\r\n[*]list\r\n[/ol]",
],
]; ];
} }
@ -282,8 +290,9 @@ Karl Marx - Die ursprüngliche Akkumulation
* *
* @throws InternalServerErrorException * @throws InternalServerErrorException
*/ */
public function testConvert(string $expectedHtml, string $text, $try_oembed = false, int $simpleHtml = 0, bool $forPlaintext = false) public function testConvert(string $expectedHtml, string $text, bool $try_oembed = true, int $simpleHtml = BBCode::INTERNAL, bool $forPlaintext = false)
{ {
// This assumes system.remove_multiplicated_lines = false
$actual = BBCode::convert($text, $try_oembed, $simpleHtml, $forPlaintext); $actual = BBCode::convert($text, $try_oembed, $simpleHtml, $forPlaintext);
self::assertEquals($expectedHtml, $actual); self::assertEquals($expectedHtml, $actual);

View File

@ -88,6 +88,24 @@ its surprisingly good",
'expectedBBCode' => '[url=https://dev-friendica.mrpetovan.com/profile/hypolite]@hypolite[/url] 0', 'expectedBBCode' => '[url=https://dev-friendica.mrpetovan.com/profile/hypolite]@hypolite[/url] 0',
'html' => '<p><span class="h-card"><a href="https://dev-friendica.mrpetovan.com/profile/hypolite" class="u-url mention">@<span>hypolite</span></a></span> 0</p>', 'html' => '<p><span class="h-card"><a href="https://dev-friendica.mrpetovan.com/profile/hypolite" class="u-url mention">@<span>hypolite</span></a></span> 0</p>',
], ],
'bug-12842-ul-new-lines' => [
'expectedBBCode' => 'This is:
[ul]
[*]some
[*]amazing
[*]list
[/ul]',
'html'=> '<p>This is:</p><ul><li>some</li><li>amazing</li><li>list</li></ul>',
],
'bug-12842-ol-new-lines' => [
'expectedBBCode' => 'This is:
[ol]
[*]some
[*]amazing
[*]list
[/ol]',
'html'=> '<p>This is:</p><ol><li>some</li><li>amazing</li><li>list</li></ol>',
],
]; ];
} }

View File

@ -80,6 +80,6 @@ class DBKeyValueStorageTest extends KeyValueStorageTest
$updateAtAfter = $entry['updated_at']; $updateAtAfter = $entry['updated_at'];
self::assertLessThanOrEqual($updateAt, $updateAtAfter); self::assertGreaterThanOrEqual($updateAt, $updateAtAfter);
} }
} }

View File

@ -0,0 +1,63 @@
var DzFactory = function () {
this.createDropzone = function(dropSelector, textareaElementId) {
return new Dropzone(dropSelector, {
paramName: 'userfile', // The name that will be used to transfer the file
maxFilesize: max_imagesize, // MB
url: '/media/photo/upload?album=',
acceptedFiles: 'image/*',
clickable: true,
accept: function(file, done) {
done();
},
init: function() {
this.on('success', function(file, serverResponse) {
const targetTextarea = document.getElementById(textareaElementId);
if (targetTextarea.setRangeText) {
//if setRangeText function is supported by current browser
targetTextarea.setRangeText(' ' + $.trim(serverResponse) + ' ');
} else {
targetTextarea.focus();
document.execCommand('insertText', false /*no UI*/, '\n' + $.trim(serverResponse) + '\n');
}
});
this.on('complete', function(file) {
const dz = this;
// Remove just uploaded file from dropzone, makes interface more clear.
// Image can be seen in posting-preview
// We need preview to get optical feedback about upload-progress.
// you see success, when the bb-code link for image is inserted
setTimeout(function(){
dz.removeFile(file);
},5000);
});
},
paste: function(event){
const items = (event.clipboardData || event.originalEvent.clipboardData).items;
items.forEach((item) => {
if (item.kind === 'file') {
// adds the file to your dropzone instance
dz.addFile(item.getAsFile());
}
})
},
});
};
this.copyPaste = function(event, dz) {
const items = (event.clipboardData || event.originalEvent.clipboardData).items;
items.forEach((item) => {
if (item.kind === 'file') {
// adds the file to your dropzone instance
dz.addFile(item.getAsFile());
}
})
};
this.setupDropzone = function(dropSelector, textareaElementId) {
var dropzone = this.createDropzone(dropSelector, textareaElementId);
$(dropSelector).on('paste', function(event) {
dzFactory.copyPaste(event, dropzone);
})
};
}

View File

@ -46,10 +46,11 @@
</button> </button>
</span> </span>
</p> </p>
<div id="dropzone-{{$id}}" class="dropzone" style="overflow:scroll">
<p> <p>
<textarea id="comment-edit-text-{{$id}}" class="comment-edit-text form-control text-autosize" name="body" placeholder="{{$l10n.default}}" rows="7" tabindex="3" dir="auto" dir="auto">{{$body}}</textarea> <textarea id="comment-edit-text-{{$id}}" class="comment-edit-text form-control text-autosize" name="body" placeholder="{{$l10n.default}}" rows="7" tabindex="3" dir="auto" dir="auto">{{$body}}</textarea>
</p> </p>
</div>
<p class="comment-edit-submit-wrapper"> <p class="comment-edit-submit-wrapper">
{{if $type == 'post'}} {{if $type == 'post'}}
<span role="presentation" class="form-inline"> <span role="presentation" class="form-inline">
@ -94,3 +95,6 @@
</form> </form>
</div> </div>
</div> </div>
<script>
dzFactory.setupDropzone('#dropzone-{{$id}}', 'comment-edit-text-{{$id}}');
</script>

View File

@ -0,0 +1,467 @@
@-webkit-keyframes passing-through {
0% {
opacity: 0;
-webkit-transform: translateY(40px);
-moz-transform: translateY(40px);
-ms-transform: translateY(40px);
-o-transform: translateY(40px);
transform: translateY(40px);
}
30%, 70% {
opacity: 1;
-webkit-transform: translateY(0px);
-moz-transform: translateY(0px);
-ms-transform: translateY(0px);
-o-transform: translateY(0px);
transform: translateY(0px);
}
100% {
opacity: 0;
-webkit-transform: translateY(-40px);
-moz-transform: translateY(-40px);
-ms-transform: translateY(-40px);
-o-transform: translateY(-40px);
transform: translateY(-40px);
}
}
@-moz-keyframes passing-through {
0% {
opacity: 0;
-webkit-transform: translateY(40px);
-moz-transform: translateY(40px);
-ms-transform: translateY(40px);
-o-transform: translateY(40px);
transform: translateY(40px);
}
30%, 70% {
opacity: 1;
-webkit-transform: translateY(0px);
-moz-transform: translateY(0px);
-ms-transform: translateY(0px);
-o-transform: translateY(0px);
transform: translateY(0px);
}
100% {
opacity: 0;
-webkit-transform: translateY(-40px);
-moz-transform: translateY(-40px);
-ms-transform: translateY(-40px);
-o-transform: translateY(-40px);
transform: translateY(-40px);
}
}
@keyframes passing-through {
0% {
opacity: 0;
-webkit-transform: translateY(40px);
-moz-transform: translateY(40px);
-ms-transform: translateY(40px);
-o-transform: translateY(40px);
transform: translateY(40px);
}
30%, 70% {
opacity: 1;
-webkit-transform: translateY(0px);
-moz-transform: translateY(0px);
-ms-transform: translateY(0px);
-o-transform: translateY(0px);
transform: translateY(0px);
}
100% {
opacity: 0;
-webkit-transform: translateY(-40px);
-moz-transform: translateY(-40px);
-ms-transform: translateY(-40px);
-o-transform: translateY(-40px);
transform: translateY(-40px);
}
}
@-webkit-keyframes slide-in {
0% {
opacity: 0;
-webkit-transform: translateY(40px);
-moz-transform: translateY(40px);
-ms-transform: translateY(40px);
-o-transform: translateY(40px);
transform: translateY(40px);
}
30% {
opacity: 1;
-webkit-transform: translateY(0px);
-moz-transform: translateY(0px);
-ms-transform: translateY(0px);
-o-transform: translateY(0px);
transform: translateY(0px);
}
}
@-moz-keyframes slide-in {
0% {
opacity: 0;
-webkit-transform: translateY(40px);
-moz-transform: translateY(40px);
-ms-transform: translateY(40px);
-o-transform: translateY(40px);
transform: translateY(40px);
}
30% {
opacity: 1;
-webkit-transform: translateY(0px);
-moz-transform: translateY(0px);
-ms-transform: translateY(0px);
-o-transform: translateY(0px);
transform: translateY(0px);
}
}
@keyframes slide-in {
0% {
opacity: 0;
-webkit-transform: translateY(40px);
-moz-transform: translateY(40px);
-ms-transform: translateY(40px);
-o-transform: translateY(40px);
transform: translateY(40px);
}
30% {
opacity: 1;
-webkit-transform: translateY(0px);
-moz-transform: translateY(0px);
-ms-transform: translateY(0px);
-o-transform: translateY(0px);
transform: translateY(0px);
}
}
@-webkit-keyframes pulse {
0% {
-webkit-transform: scale(1);
-moz-transform: scale(1);
-ms-transform: scale(1);
-o-transform: scale(1);
transform: scale(1);
}
10% {
-webkit-transform: scale(1.1);
-moz-transform: scale(1.1);
-ms-transform: scale(1.1);
-o-transform: scale(1.1);
transform: scale(1.1);
}
20% {
-webkit-transform: scale(1);
-moz-transform: scale(1);
-ms-transform: scale(1);
-o-transform: scale(1);
transform: scale(1);
}
}
@-moz-keyframes pulse {
0% {
-webkit-transform: scale(1);
-moz-transform: scale(1);
-ms-transform: scale(1);
-o-transform: scale(1);
transform: scale(1);
}
10% {
-webkit-transform: scale(1.1);
-moz-transform: scale(1.1);
-ms-transform: scale(1.1);
-o-transform: scale(1.1);
transform: scale(1.1);
}
20% {
-webkit-transform: scale(1);
-moz-transform: scale(1);
-ms-transform: scale(1);
-o-transform: scale(1);
transform: scale(1);
}
}
@keyframes pulse {
0% {
-webkit-transform: scale(1);
-moz-transform: scale(1);
-ms-transform: scale(1);
-o-transform: scale(1);
transform: scale(1);
}
10% {
-webkit-transform: scale(1.1);
-moz-transform: scale(1.1);
-ms-transform: scale(1.1);
-o-transform: scale(1.1);
transform: scale(1.1);
}
20% {
-webkit-transform: scale(1);
-moz-transform: scale(1);
-ms-transform: scale(1);
-o-transform: scale(1);
transform: scale(1);
}
}
.dropzone, .dropzone * {
box-sizing: border-box;
}
.dropzone {
min-height: 150px;
border: 1px solid rgba(0, 0, 0, 0.3);
background: white;
padding: 2px 2px;
}
.dropzone.dz-clickable {
cursor: pointer;
}
.dropzone.dz-clickable * {
cursor: default;
}
.dropzone.dz-clickable .dz-message, .dropzone.dz-clickable .dz-message * {
cursor: pointer;
}
.dropzone.dz-started .dz-message {
display: none;
}
.dropzone.dz-drag-hover {
border-style: solid;
}
.dropzone.dz-drag-hover .dz-message {
opacity: 0.5;
}
.dropzone .dz-message {
text-align: center;
}
.dropzone .dz-message .dz-button {
background: none;
color: inherit;
border: none;
padding: 0;
font: inherit;
cursor: pointer;
outline: inherit;
}
.dropzone .dz-preview {
position: relative;
display: inline-block;
vertical-align: top;
margin: 16px;
min-height: 100px;
}
.dropzone .dz-preview:hover {
z-index: 1000;
}
.dropzone .dz-preview:hover .dz-details {
opacity: 1;
}
.dropzone .dz-preview.dz-file-preview .dz-image {
border-radius: 20px;
background: #999;
background: linear-gradient(to bottom, #eee, #ddd);
}
.dropzone .dz-preview.dz-file-preview .dz-details {
opacity: 1;
}
.dropzone .dz-preview.dz-image-preview {
background: white;
}
.dropzone .dz-preview.dz-image-preview .dz-details {
-webkit-transition: opacity 0.2s linear;
-moz-transition: opacity 0.2s linear;
-ms-transition: opacity 0.2s linear;
-o-transition: opacity 0.2s linear;
transition: opacity 0.2s linear;
}
.dropzone .dz-preview .dz-remove {
font-size: 14px;
text-align: center;
display: block;
cursor: pointer;
border: none;
}
.dropzone .dz-preview .dz-remove:hover {
text-decoration: underline;
}
.dropzone .dz-preview:hover .dz-details {
opacity: 1;
}
.dropzone .dz-preview .dz-details {
z-index: 20;
position: absolute;
top: 0;
left: 0;
opacity: 0;
font-size: 13px;
min-width: 100%;
max-width: 100%;
padding: 2em 1em;
text-align: center;
color: rgba(0, 0, 0, 0.9);
line-height: 150%;
}
.dropzone .dz-preview .dz-details .dz-size {
margin-bottom: 1em;
font-size: 16px;
}
.dropzone .dz-preview .dz-details .dz-filename {
white-space: nowrap;
}
.dropzone .dz-preview .dz-details .dz-filename:hover span {
border: 1px solid rgba(200, 200, 200, 0.8);
background-color: rgba(255, 255, 255, 0.8);
}
.dropzone .dz-preview .dz-details .dz-filename:not(:hover) {
overflow: hidden;
text-overflow: ellipsis;
}
.dropzone .dz-preview .dz-details .dz-filename:not(:hover) span {
border: 1px solid transparent;
}
.dropzone .dz-preview .dz-details .dz-filename span, .dropzone .dz-preview .dz-details .dz-size span {
background-color: rgba(255, 255, 255, 0.4);
padding: 0 0.4em;
border-radius: 3px;
}
.dropzone .dz-preview:hover .dz-image img {
-webkit-transform: scale(1.05, 1.05);
-moz-transform: scale(1.05, 1.05);
-ms-transform: scale(1.05, 1.05);
-o-transform: scale(1.05, 1.05);
transform: scale(1.05, 1.05);
-webkit-filter: blur(8px);
filter: blur(8px);
}
.dropzone .dz-preview .dz-image {
border-radius: 20px;
overflow: hidden;
width: 120px;
height: 120px;
position: relative;
display: block;
z-index: 10;
}
.dropzone .dz-preview .dz-image img {
display: block;
}
.dropzone .dz-preview.dz-success .dz-success-mark {
-webkit-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
-moz-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
-ms-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
-o-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
}
.dropzone .dz-preview.dz-error .dz-error-mark {
opacity: 1;
-webkit-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
-moz-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
-ms-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
-o-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
}
.dropzone .dz-preview .dz-success-mark, .dropzone .dz-preview .dz-error-mark {
pointer-events: none;
opacity: 0;
z-index: 500;
position: absolute;
display: block;
top: 50%;
left: 50%;
margin-left: -27px;
margin-top: -27px;
}
.dropzone .dz-preview .dz-success-mark svg, .dropzone .dz-preview .dz-error-mark svg {
display: block;
width: 54px;
height: 54px;
}
.dropzone .dz-preview.dz-processing .dz-progress {
opacity: 1;
-webkit-transition: all 0.2s linear;
-moz-transition: all 0.2s linear;
-ms-transition: all 0.2s linear;
-o-transition: all 0.2s linear;
transition: all 0.2s linear;
}
.dropzone .dz-preview.dz-complete .dz-progress {
opacity: 0;
-webkit-transition: opacity 0.4s ease-in;
-moz-transition: opacity 0.4s ease-in;
-ms-transition: opacity 0.4s ease-in;
-o-transition: opacity 0.4s ease-in;
transition: opacity 0.4s ease-in;
}
.dropzone .dz-preview:not(.dz-processing) .dz-progress {
-webkit-animation: pulse 6s ease infinite;
-moz-animation: pulse 6s ease infinite;
-ms-animation: pulse 6s ease infinite;
-o-animation: pulse 6s ease infinite;
animation: pulse 6s ease infinite;
}
.dropzone .dz-preview .dz-progress {
opacity: 1;
z-index: 1000;
pointer-events: none;
position: absolute;
height: 16px;
left: 50%;
top: 50%;
margin-top: -8px;
width: 80px;
margin-left: -40px;
background: rgba(255, 255, 255, 0.9);
-webkit-transform: scale(1);
border-radius: 8px;
overflow: hidden;
}
.dropzone .dz-preview .dz-progress .dz-upload {
background: #333;
background: linear-gradient(to bottom, #666, #444);
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 0;
-webkit-transition: width 300ms ease-in-out;
-moz-transition: width 300ms ease-in-out;
-ms-transition: width 300ms ease-in-out;
-o-transition: width 300ms ease-in-out;
transition: width 300ms ease-in-out;
}
.dropzone .dz-preview.dz-error .dz-error-message {
display: block;
}
.dropzone .dz-preview.dz-error:hover .dz-error-message {
opacity: 1;
pointer-events: auto;
}
.dropzone .dz-preview .dz-error-message {
pointer-events: none;
z-index: 1000;
position: absolute;
display: block;
display: none;
opacity: 0;
-webkit-transition: opacity 0.3s ease;
-moz-transition: opacity 0.3s ease;
-ms-transition: opacity 0.3s ease;
-o-transition: opacity 0.3s ease;
transition: opacity 0.3s ease;
border-radius: 8px;
font-size: 13px;
top: 130px;
left: -10px;
width: 140px;
background: #be2626;
background: linear-gradient(to bottom, #be2626, #a92222);
padding: 0.5em 1.2em;
color: white;
}
.dropzone .dz-preview .dz-error-message:after {
content: "";
position: absolute;
top: -6px;
left: 64px;
width: 0;
height: 0;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
border-bottom: 6px solid #be2626;
}

File diff suppressed because one or more lines are too long

View File

@ -291,6 +291,10 @@ function editpost(url) {
$("#profile-jot-form #jot-category-wrap").hide(); $("#profile-jot-form #jot-category-wrap").hide();
} }
// To make dropzone fileupload work on editing a comment, we need to
// attach a new dropzone to modal
dzFactory.setupDropzone('#jot-text-wrap', 'profile-jot-text');
modal.show(); modal.show();
$("#jot-popup").show(); $("#jot-popup").show();
linkPreview = $("#profile-jot-text").linkPreview(); linkPreview = $("#profile-jot-text").linkPreview();

View File

@ -38,9 +38,11 @@
</button> </button>
</span> </span>
</p> </p>
<div id="dropzone-{{$id}}" class="dropzone" style="overflow:scroll">
<p> <p>
<textarea id="comment-edit-text-{{$id}}" class="comment-edit-text-empty form-control text-autosize" name="body" placeholder="{{$comment}}" rows="3" data-default="{{$default}}" dir="auto">{{$default}}</textarea> <textarea id="comment-edit-text-{{$id}}" class="dropzone comment-edit-text-empty form-control text-autosize" name="body" placeholder="{{$comment}}" rows="3" data-default="{{$default}}" dir="auto">{{$default}}</textarea>
</p> </p>
</div>
{{if $qcomment}} {{if $qcomment}}
<p> <p>
<select id="qcomment-select-{{$id}}" name="qcomment-{{$id}}" class="qcomment" onchange="qCommentInsert(this,{{$id}});"> <select id="qcomment-select-{{$id}}" name="qcomment-{{$id}}" class="qcomment" onchange="qCommentInsert(this,{{$id}});">
@ -51,7 +53,6 @@
</select> </select>
</p> </p>
{{/if}} {{/if}}
<p class="comment-edit-submit-wrapper"> <p class="comment-edit-submit-wrapper">
{{if $preview}} {{if $preview}}
<button type="button" class="btn btn-default comment-edit-preview" onclick="preview_comment({{$id}});" id="comment-edit-preview-link-{{$id}}"><i class="fa fa-eye"></i> {{$preview}}</button> <button type="button" class="btn btn-default comment-edit-preview" onclick="preview_comment({{$id}});" id="comment-edit-preview-link-{{$id}}"><i class="fa fa-eye"></i> {{$preview}}</button>
@ -64,3 +65,15 @@
<div id="comment-edit-preview-{{$id}}" class="comment-edit-preview" style="display:none;"></div> <div id="comment-edit-preview-{{$id}}" class="comment-edit-preview" style="display:none;"></div>
</div> </div>
<script>
$('[id=comment-fake-text-{{$id}}]').on('focus', function() {
dzFactory.setupDropzone('#dropzone-{{$id}}', 'comment-edit-text-{{$id}}');
$('[id=comment-fake-text-{{$id}}]').prop('focus', null).off('focus');
$('[id=comment-{{$id}}]').prop('click', null).off('click');
});
$('[id=comment-{{$id}}]').on('click', function() {
dzFactory.setupDropzone('#dropzone-{{$id}}', 'comment-edit-text-{{$id}}');
$('[id=comment-fake-text-{{$id}}]').prop('focus', null).off('focus');
$('[id=comment-{{$id}}]').prop('click', null).off('click');
});
</script>

View File

@ -55,6 +55,8 @@
media="screen" /> media="screen" />
<link rel="stylesheet" href="view/theme/frio/css/font-awesome.custom.css?v={{$smarty.const.FRIENDICA_VERSION}}" <link rel="stylesheet" href="view/theme/frio/css/font-awesome.custom.css?v={{$smarty.const.FRIENDICA_VERSION}}"
type="text/css" media="screen" /> type="text/css" media="screen" />
<link rel="stylesheet" href="view/theme/frio/css/dropzone.min.frio.css?v={{$smarty.const.FRIENDICA_VERSION}}"
type="text/css" media="screen" />
{{foreach $stylesheets as $stylesheetUrl => $media}} {{foreach $stylesheets as $stylesheetUrl => $media}}
<link rel="stylesheet" href="{{$stylesheetUrl}}" type="text/css" media="{{$media}}" /> <link rel="stylesheet" href="{{$stylesheetUrl}}" type="text/css" media="{{$media}}" />
@ -137,6 +139,9 @@
<script type="text/javascript" src="view/theme/frio/js/hovercard.js?v={{$smarty.const.FRIENDICA_VERSION}}"></script> <script type="text/javascript" src="view/theme/frio/js/hovercard.js?v={{$smarty.const.FRIENDICA_VERSION}}"></script>
{{/if}} {{/if}}
<script type="text/javascript" src="view/theme/frio/js/textedit.js?v={{$smarty.const.FRIENDICA_VERSION}}"></script> <script type="text/javascript" src="view/theme/frio/js/textedit.js?v={{$smarty.const.FRIENDICA_VERSION}}"></script>
<script type="text/javascript" src="vendor/enyo/dropzone/dist/min/dropzone.min.js?v={{$smarty.const.FRIENDICA_VERSION}}"></script>
<script type="text/javascript" src="view/js/dropzone-factory.js?v={{$smarty.const.FRIENDICA_VERSION}}"></script>
<script type="text/javascript"> max_imagesize = {{$max_imagesize}}; var dzFactory = new DzFactory(); Dropzone.autoDiscover = false; </script>
{{* Include the strings which are needed for some js functions (e.g. translation) {{* Include the strings which are needed for some js functions (e.g. translation)
They are loaded into the html <head> so that js functions can use them *}} They are loaded into the html <head> so that js functions can use them *}}

View File

@ -99,7 +99,7 @@
{{/if}} {{/if}}
{{* The jot text field in which the post text is inserted *}} {{* The jot text field in which the post text is inserted *}}
<div id="jot-text-wrap"> <div id="jot-text-wrap" class="dropzone" style="overflow:scroll">
<textarea rows="2" cols="64" class="profile-jot-text form-control text-autosize" id="profile-jot-text" name="body" placeholder="{{$share}}" onFocus="jotTextOpenUI(this);" onBlur="jotTextCloseUI(this);" style="min-width:100%; max-width:100%;" dir="auto">{{if $content}}{{$content nofilter}}{{/if}}</textarea> <textarea rows="2" cols="64" class="profile-jot-text form-control text-autosize" id="profile-jot-text" name="body" placeholder="{{$share}}" onFocus="jotTextOpenUI(this);" onBlur="jotTextCloseUI(this);" style="min-width:100%; max-width:100%;" dir="auto">{{if $content}}{{$content nofilter}}{{/if}}</textarea>
</div> </div>
@ -152,6 +152,7 @@
<div id="jot-fbrowser-wrapper" class="minimize" aria-labelledby="jot-browser-link" role="tabpanel" aria-hidden="true"></div> <div id="jot-fbrowser-wrapper" class="minimize" aria-labelledby="jot-browser-link" role="tabpanel" aria-hidden="true"></div>
</form> </form>
<div id="dz-preview-jot" class="dropzone-preview"></div>
{{if $content}}<script type="text/javascript">initEditor();</script>{{/if}} {{if $content}}<script type="text/javascript">initEditor();</script>{{/if}}
</div> </div>
@ -162,9 +163,9 @@
{{* The jot modal - We use a own modal for the jot and not the standard modal {{* The jot modal - We use a own modal for the jot and not the standard modal
from the page template. This is because the special structure of the jot from the page template. This is because the special structure of the jot
(e.g.jot navigation tabs in the modal titel area). (e.g.jot navigation tabs in the modal titel area).
The in the frio theme the jot will loaded regulary and is hidden by default.) Then in the frio theme the jot will loaded regulary and is hidden by default.)
The js function jotShow() loads the jot into the modal. With this structure we The js function jotShow() loads the jot into the modal. With this structure we
can load different content into the jot moadl (e.g. the item edit jot) can load different content into the jot modal (e.g. the item edit jot)
*}} *}}
<div id="jot-modal" class="modal fade" role="dialog"> <div id="jot-modal" class="modal fade" role="dialog">
<div class="modal-dialog"> <div class="modal-dialog">
@ -172,9 +173,12 @@ can load different content into the jot moadl (e.g. the item edit jot)
</div> </div>
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
$('iframe').load(function() { $('iframe').load(function() {
this.style.height = this.contentWindow.document.body.offsetHeight + 'px'; this.style.height = this.contentWindow.document.body.offsetHeight + 'px';
}); });
</script> </script>
<script>
dzFactory.setupDropzone('#jot-text-wrap', 'profile-jot-text');
</script>