From: Philipp Date: Sat, 26 Nov 2022 23:28:29 +0000 (+0100) Subject: Move FileBrowser to own namespace & Bugfix album usage X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=051253a745762cffc5ff165d9b8987171fb4912b;p=friendica.git Move FileBrowser to own namespace & Bugfix album usage --- diff --git a/src/App/Page.php b/src/App/Page.php index afc94fbdf0..37141426c3 100644 --- a/src/App/Page.php +++ b/src/App/Page.php @@ -241,7 +241,6 @@ class Page implements ArrayAccess * being first */ $this->page['htmlhead'] = Renderer::replaceMacros($tpl, [ - '$local_nickname' => $app->getLoggedInUserNickname(), '$local_user' => $localUID, '$generator' => 'Friendica' . ' ' . App::VERSION, '$delitem' => $l10n->t('Delete this item?'), diff --git a/src/Model/Photo.php b/src/Model/Photo.php index 12d0c2f92c..87a81069f8 100644 --- a/src/Model/Photo.php +++ b/src/Model/Photo.php @@ -207,7 +207,7 @@ class Photo public static function getBrowsablePhotosForUser(int $uid, string $album = null): array { if (!empty($album)) { - $sqlExtra = sprintf("AND `album` = '%S' ", DBA::escape($album)); + $sqlExtra = sprintf("AND `album` = '%s' ", DBA::escape($album)); $sqlExtra2 = ""; } else { $sqlExtra = ''; diff --git a/src/Module/Media/AttachmentBrowser.php b/src/Module/Media/AttachmentBrowser.php new file mode 100644 index 0000000000..c0ec1c5d9b --- /dev/null +++ b/src/Module/Media/AttachmentBrowser.php @@ -0,0 +1,101 @@ +. + * + */ + +namespace Friendica\Module\Media; + +use Friendica\App; +use Friendica\BaseModule; +use Friendica\Core\L10n; +use Friendica\Core\Renderer; +use Friendica\Core\Session\Capability\IHandleUserSessions; +use Friendica\Core\System; +use Friendica\Model\Attach; +use Friendica\Module\Response; +use Friendica\Network\HTTPException\UnauthorizedException; +use Friendica\Util\Profiler; +use Friendica\Util\Strings; +use Psr\Log\LoggerInterface; + +/** + * Browser for Attachments + */ +class AttachmentBrowser extends BaseModule +{ + /** @var IHandleUserSessions */ + protected $session; + /** @var App */ + protected $app; + + public function __construct(L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, IHandleUserSessions $session, App $app, array $server, array $parameters = []) + { + parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); + + $this->session = $session; + $this->app = $app; + } + + protected function content(array $request = []): string + { + if (!$this->session->getLocalUserId()) { + throw new UnauthorizedException($this->t('Permission denied.')); + } + + // Needed to match the correct template in a module that uses a different theme than the user/site/default + $theme = Strings::sanitizeFilePathItem($request['theme'] ?? ''); + if ($theme && is_file("view/theme/$theme/config.php")) { + $this->app->setCurrentTheme($theme); + } + + $files = Attach::selectToArray(['id', 'filename', 'filetype'], ['uid' => $this->session->getLocalUserId()]); + + + $fileArray = array_map([$this, 'map_files'], $files); + + $tpl = Renderer::getMarkupTemplate('media/filebrowser.tpl'); + $output = Renderer::replaceMacros($tpl, [ + '$type' => 'attachment', + '$path' => ['' => $this->t('Files')], + '$folders' => false, + '$files' => $fileArray, + '$cancel' => $this->t('Cancel'), + '$nickname' => $this->app->getLoggedInUserNickname(), + '$upload' => $this->t('Upload'), + ]); + + if (empty($request['mode'])) { + System::httpExit($output); + } + + return $output; + } + + protected function map_files(array $record): array + { + [$m1, $m2] = explode('/', $record['filetype']); + $filetype = file_exists(sprintf('images/icons/%s.png', $m1) ? $m1 : 'text'); + + return [ + sprintf('%s/attach/%s', $this->baseUrl, $record['id']), + $record['filename'], + sprintf('%s/images/icon/16/%s.png', $this->baseUrl, $filetype), + ]; + } +} diff --git a/src/Module/Media/PhotosBrowser.php b/src/Module/Media/PhotosBrowser.php new file mode 100644 index 0000000000..4c9803fc60 --- /dev/null +++ b/src/Module/Media/PhotosBrowser.php @@ -0,0 +1,125 @@ +. + * + */ + +namespace Friendica\Module\Media; + +use Friendica\App; +use Friendica\BaseModule; +use Friendica\Core\L10n; +use Friendica\Core\Renderer; +use Friendica\Core\Session\Capability\IHandleUserSessions; +use Friendica\Core\System; +use Friendica\Model\Photo; +use Friendica\Module\Response; +use Friendica\Network\HTTPException\UnauthorizedException; +use Friendica\Util\Images; +use Friendica\Util\Profiler; +use Friendica\Util\Strings; +use Psr\Log\LoggerInterface; + +/** + * Browser for Photos + */ +class PhotosBrowser extends BaseModule +{ + /** @var IHandleUserSessions */ + protected $session; + /** @var App */ + protected $app; + + public function __construct(L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, IHandleUserSessions $session, App $app, array $server, array $parameters = []) + { + parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); + + $this->session = $session; + $this->app = $app; + } + + protected function content(array $request = []): string + { + if (!$this->session->getLocalUserId()) { + throw new UnauthorizedException($this->t('Permission denied.')); + } + + // Needed to match the correct template in a module that uses a different theme than the user/site/default + $theme = Strings::sanitizeFilePathItem($request['theme'] ?? ''); + if ($theme && is_file("view/theme/$theme/config.php")) { + $this->app->setCurrentTheme($theme); + } + + $album = $this->parameters['album'] ?? null; + + $photos = Photo::getBrowsablePhotosForUser($this->session->getLocalUserId(), $album); + $albums = $album ? false : Photo::getBrowsableAlbumsForUser($this->session->getLocalUserId()); + + $path = [ + '' => $this->t('Photos'), + ]; + if (!empty($album)) { + $path[$album] = $album; + } + + $photosArray = array_map([$this, 'map_files'], $photos); + + $tpl = Renderer::getMarkupTemplate('media/filebrowser.tpl'); + $output = Renderer::replaceMacros($tpl, [ + '$type' => 'photos', + '$path' => $path, + '$folders' => $albums, + '$files' => $photosArray, + '$cancel' => $this->t('Cancel'), + '$nickname' => $this->app->getLoggedInUserNickname(), + '$upload' => $this->t('Upload'), + ]); + + if (empty($request['mode'])) { + System::httpExit($output); + } + + return $output; + } + + protected function map_files(array $record): array + { + $types = Images::supportedTypes(); + $ext = $types[$record['type']]; + $filename_e = $record['filename']; + + // Take the largest picture that is smaller or equal 640 pixels + $photo = Photo::selectFirst( + ['scale'], + [ + "`resource-id` = ? AND `height` <= ? AND `width` <= ?", + $record['resource-id'], + 640, + 640 + ], + ['order' => ['scale']]); + $scale = $photo['scale'] ?? $record['loq']; + + return [ + sprintf('%s/photos/%s/image/%s', $this->baseUrl, $this->app->getLoggedInUserNickname(), $record['resource-id']), + $filename_e, + sprintf('%s/photo/%s-%s.%s', $this->baseUrl, $record['resource-id'], $scale, $ext), + $record['desc'], + ]; + } +} diff --git a/src/Module/Profile/Attachment/Browser.php b/src/Module/Profile/Attachment/Browser.php deleted file mode 100644 index a6640bf5d2..0000000000 --- a/src/Module/Profile/Attachment/Browser.php +++ /dev/null @@ -1,100 +0,0 @@ -. - * - */ - -namespace Friendica\Module\Profile\Attachment; - -use Friendica\App; -use Friendica\BaseModule; -use Friendica\Core\L10n; -use Friendica\Core\Renderer; -use Friendica\Core\Session\Capability\IHandleUserSessions; -use Friendica\Core\System; -use Friendica\Model\Attach; -use Friendica\Module\Response; -use Friendica\Util\Profiler; -use Friendica\Util\Strings; -use Psr\Log\LoggerInterface; - -/** - * Browser for Attachments - */ -class Browser extends BaseModule -{ - /** @var IHandleUserSessions */ - protected $session; - /** @var App */ - protected $app; - - public function __construct(L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, IHandleUserSessions $session, App $app, array $server, array $parameters = []) - { - parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); - - $this->session = $session; - $this->app = $app; - } - - protected function content(array $request = []): string - { - if (!$this->session->getLocalUserId()) { - $this->baseUrl->redirect(); - } - - // Needed to match the correct template in a module that uses a different theme than the user/site/default - $theme = Strings::sanitizeFilePathItem($request['theme'] ?? ''); - if ($theme && is_file("view/theme/$theme/config.php")) { - $this->app->setCurrentTheme($theme); - } - - $files = Attach::selectToArray(['id', 'filename', 'filetype'], ['uid' => $this->session->getLocalUserId()]); - - - $fileArray = array_map([$this, 'map_files'], $files); - - $tpl = Renderer::getMarkupTemplate('profile/filebrowser.tpl'); - $output = Renderer::replaceMacros($tpl, [ - '$type' => 'attachment', - '$path' => ['' => $this->t('Files')], - '$folders' => false, - '$files' => $fileArray, - '$cancel' => $this->t('Cancel'), - '$nickname' => $this->app->getLoggedInUserNickname(), - '$upload' => $this->t('Upload'), - ]); - - if (empty($request['mode'])) { - System::httpExit($output); - } - - return $output; - } - - protected function map_files(array $record): array - { - list($m1, $m2) = explode('/', $record['filetype']); - $filetype = file_exists(sprintf('images/icons/%s.png', $m1) ? $m1 : 'zip'); - - return [ - sprintf('%s/attach/%s', $this->baseUrl, $record['id']), - $record['filename'], - sprintf('%s/images/icon/16/%s.png', $this->baseUrl, $filetype), - ]; - } -} diff --git a/src/Module/Profile/Photos/Browser.php b/src/Module/Profile/Photos/Browser.php deleted file mode 100644 index 2185aa7c78..0000000000 --- a/src/Module/Profile/Photos/Browser.php +++ /dev/null @@ -1,124 +0,0 @@ -. - * - */ - -namespace Friendica\Module\Profile\Photos; - -use Friendica\App; -use Friendica\BaseModule; -use Friendica\Core\L10n; -use Friendica\Core\Renderer; -use Friendica\Core\Session\Capability\IHandleUserSessions; -use Friendica\Core\System; -use Friendica\Model\Photo; -use Friendica\Module\Response; -use Friendica\Util\Images; -use Friendica\Util\Profiler; -use Friendica\Util\Strings; -use Psr\Log\LoggerInterface; - -/** - * Browser for Photos - */ -class Browser extends BaseModule -{ - /** @var IHandleUserSessions */ - protected $session; - /** @var App */ - protected $app; - - public function __construct(L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, IHandleUserSessions $session, App $app, array $server, array $parameters = []) - { - parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); - - $this->session = $session; - $this->app = $app; - } - - protected function content(array $request = []): string - { - if (!$this->session->getLocalUserId()) { - $this->baseUrl->redirect(); - } - - // Needed to match the correct template in a module that uses a different theme than the user/site/default - $theme = Strings::sanitizeFilePathItem($request['theme'] ?? ''); - if ($theme && is_file("view/theme/$theme/config.php")) { - $this->app->setCurrentTheme($theme); - } - - $album = $this->parameters['album'] ?? null; - - $photos = Photo::getBrowsablePhotosForUser($this->session->getLocalUserId(), $album); - $albums = $album ? false : Photo::getBrowsableAlbumsForUser($this->session->getLocalUserId()); - - $path = [ - '' => $this->t('Photos'), - ]; - if (!empty($album)) { - $path[$album] = $album; - } - - $photosArray = array_map([$this, 'map_files'], $photos); - - $tpl = Renderer::getMarkupTemplate('profile/filebrowser.tpl'); - $output = Renderer::replaceMacros($tpl, [ - '$type' => 'photos', - '$path' => $path, - '$folders' => $albums, - '$files' => $photosArray, - '$cancel' => $this->t('Cancel'), - '$nickname' => $this->app->getLoggedInUserNickname(), - '$upload' => $this->t('Upload'), - ]); - - if (empty($request['mode'])) { - System::httpExit($output); - } - - return $output; - } - - protected function map_files(array $record): array - { - $types = Images::supportedTypes(); - $ext = $types[$record['type']]; - $filename_e = $record['filename']; - - // Take the largest picture that is smaller or equal 640 pixels - $photo = Photo::selectFirst( - ['scale'], - [ - "`resource-id` = ? AND `height` <= ? AND `width` <= ?", - $record['resource-id'], - 640, - 640 - ], - ['order' => ['scale']]); - $scale = $photo['scale'] ?? $record['loq']; - - return [ - sprintf('%s/photos/%s/image/%s', $this->baseUrl, $this->app->getLoggedInUserNickname(), $record['resource-id']), - $filename_e, - sprintf('%s/photo/%s-%s.%s', $this->baseUrl, $record['resource-id'], $scale, $ext), - $record['desc'], - ]; - } -} diff --git a/static/routes.config.php b/static/routes.config.php index 794f705e40..542e31679b 100644 --- a/static/routes.config.php +++ b/static/routes.config.php @@ -31,20 +31,18 @@ use Friendica\App\Router as R; use Friendica\Module; $profileRoutes = [ - '' => [Module\Profile\Index::class, [R::GET]], - '/attachment/upload' => [Module\Profile\Attachment\Upload::class, [ R::POST]], - '/attachment/browser' => [Module\Profile\Attachment\Browser::class, [R::GET]], - '/contacts/common' => [Module\Profile\Common::class, [R::GET]], - '/contacts[/{type}]' => [Module\Profile\Contacts::class, [R::GET]], - '/media' => [Module\Profile\Media::class, [R::GET]], - '/photos' => [Module\Profile\Photos\Index::class, [R::GET ]], - '/photos/browser[/{album}]' => [Module\Profile\Photos\Browser::class, [R::GET]], - '/photos/upload' => [Module\Profile\Photos\Upload::class, [ R::POST]], - '/profile' => [Module\Profile\Profile::class, [R::GET]], - '/remote_follow' => [Module\Profile\RemoteFollow::class, [R::GET, R::POST]], - '/schedule' => [Module\Profile\Schedule::class, [R::GET, R::POST]], - '/status[/{category}[/{date1}[/{date2}]]]' => [Module\Profile\Status::class, [R::GET]], - '/unkmail' => [Module\Profile\UnkMail::class, [R::GET, R::POST]], + '' => [Module\Profile\Index::class, [R::GET]], + '/attachment/upload' => [Module\Profile\Attachment\Upload::class, [ R::POST]], + '/contacts/common' => [Module\Profile\Common::class, [R::GET]], + '/contacts[/{type}]' => [Module\Profile\Contacts::class, [R::GET]], + '/media' => [Module\Profile\Media::class, [R::GET]], + '/photos' => [Module\Profile\Photos\Index::class, [R::GET ]], + '/photos/upload' => [Module\Profile\Photos\Upload::class, [ R::POST]], + '/profile' => [Module\Profile\Profile::class, [R::GET]], + '/remote_follow' => [Module\Profile\RemoteFollow::class, [R::GET, R::POST]], + '/schedule' => [Module\Profile\Schedule::class, [R::GET, R::POST]], + '/status[/{category}[/{date1}[/{date2}]]]' => [Module\Profile\Status::class, [R::GET]], + '/unkmail' => [Module\Profile\UnkMail::class, [R::GET, R::POST]], ]; $apiRoutes = [ @@ -471,6 +469,12 @@ return [ '/magic' => [Module\Magic::class, [R::GET]], '/manifest' => [Module\Manifest::class, [R::GET]], '/friendica.webmanifest' => [Module\Manifest::class, [R::GET]], + + '/media' => [ + '/attachment/browser' => [Module\Media\AttachmentBrowser::class, [R::GET]], + '/photos/browser[/{album}]' => [Module\Media\PhotosBrowser::class, [R::GET]], + ], + '/moderation' => [ '[/]' => [Module\Moderation\Summary::class, [R::GET]], diff --git a/view/js/filebrowser.js b/view/js/filebrowser.js deleted file mode 100644 index a1ed09d24d..0000000000 --- a/view/js/filebrowser.js +++ /dev/null @@ -1,161 +0,0 @@ -// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPLv3-or-later -/** - * Filebrowser - Friendica Communications Server - * - * Copyright (c) 2010-2021, the Friendica project - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This code handle user interaction for image/file upload/browser dialog. - * Is loaded from filebrowser_plain.tpl - * - * To load filebrowser in colorbox, call - * - * Dialog.doImageBrowser(eventname, id); - * - * or - * - * Dialog.doFileBrowser(eventname, id); - * - * where: - * - * eventname: event name to catch return value - * id: id returned to event handler - * - * When user select an item, an event in fired in parent page, on body element - * The event is named - * - * fbrowser..[] - * - * will be one of "image" or "file", and the event handler will - * get the following params: - * - * filename: filename of item chosen by user - * embed: bbcode to embed element into posts - * id: id from caller code - * - * example: - * - * // open dialog for select an image for a textarea with id "myeditor" - * var id="myeditor"; - * Dialog.doImageBrowser("example", id); - * - * // setup event handler to get user selection - * $("body").on("fbrowser.image.example", function(event, filename, bbcode, id) { - * // close colorbox - * $.colorbox.close(); - * // replace textarea text with bbcode - * $(id).value = bbcode; - * }); - **/ -const FileBrowser = { - nickname: '', - type: '', - event: '', - id: null, - - init: function (nickname, type) { - FileBrowser.nickname = nickname; - FileBrowser.type = type; - FileBrowser.event = 'fbrowser.' + type; - if (location['hash'] !== '') { - const h = location['hash'].replace('#', ''); - FileBrowser.event = FileBrowser.event + '.' + h.split('-')[0]; - FileBrowser.id = h.split('-')[1]; - } - - console.log('FileBrowser:', nickname, type, FileBrowser.event, FileBrowser.id); - - $('.error a.close').on('click', function (e) { - e.preventDefault(); - $('.error').addClass('hidden'); - }); - - $('.folders a, .path a').on('click', function (e) { - e.preventDefault(); - location.href = FileBrowser._getUrl("minimal", location['hash'], this.dataset.folder); - location.reload(); - }); - - $(".photo-album-photo-link").on('click', function (e) { - e.preventDefault(); - - let embed = ''; - if (FileBrowser.type === "photos") { - embed = '[url=' + this.dataset.link + '][img=' + this.dataset.img + ']' + this.dataset.alt + '[/img][/url]'; - } - if (FileBrowser.type === "attachment") { - embed = '[attachment]' + this.dataset.link + '[/attachment]'; - } - console.log(FileBrowser.event, this.dataset.filename, embed, FileBrowser.id); - parent.$('body').trigger(FileBrowser.event, [ - this.dataset.filename, - embed, - FileBrowser.id - ]); - - }); - - if ($('#upload-photos').length) - { - new window.AjaxUpload( - 'upload-photos', - { - action: 'profile/' + FileBrowser.nickname + '/photos/upload?response=json', - name: 'userfile', - responseType: 'json', - onSubmit: function (file, ext) { - $('#profile-rotator').show(); - $('.error').addClass('hidden'); - }, - onComplete: function (file, response) { - if (response['error'] !== undefined) { - $('.error span').html(response['error']); - $('.error').removeClass('hidden'); - $('#profile-rotator').hide(); - return; - } - location.href = FileBrowser._getUrl("minimal", location['hash']); - location.reload(); - } - } - ); - } - - if ($('#upload-attachment').length) - { - new window.AjaxUpload( - 'upload-attachment', - { - action: 'profile/' + FileBrowser.nickname + '/attachment/upload?response=json', - name: 'userfile', - responseType: 'json', - onSubmit: function (file, ext) { - $('#profile-rotator').show(); - $('.error').addClass('hidden'); - }, - onComplete: function (file, response) { - if (response['error'] !== undefined) { - $('.error span').html(response['error']); - $('.error').removeClass('hidden'); - $('#profile-rotator').hide(); - return; - } - location.href = FileBrowser._getUrl("minimal", location['hash']); - location.reload(); - } - } - ); - } - }, - - _getUrl: function (mode, hash, folder) { - let folderValue = folder !== undefined ? folder : FileBrowser.folder; - let folderUrl = folderValue !== undefined ? '/' + encodeURIComponent(folderValue) : ''; - return 'profile/' + FileBrowser.nickname + '/' + FileBrowser.type + '/browser' + folderUrl + '?mode=' + mode + hash; - } -}; -// @license-end diff --git a/view/js/main.js b/view/js/main.js index 782eb4ec56..deaa450603 100644 --- a/view/js/main.js +++ b/view/js/main.js @@ -1095,7 +1095,7 @@ var Dialog = { if (id !== undefined) { hash = hash + "-" + id; } - return '/profile/' + localNickname + '/' + type + '/browser?mode=minimal#' + hash; + return 'media/' + type + '/browser?mode=minimal#' + hash; }, _get_size: function() { diff --git a/view/js/media/filebrowser.js b/view/js/media/filebrowser.js new file mode 100644 index 0000000000..2239de4f64 --- /dev/null +++ b/view/js/media/filebrowser.js @@ -0,0 +1,161 @@ +// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPLv3-or-later +/** + * Filebrowser - Friendica Communications Server + * + * Copyright (c) 2010-2021, the Friendica project + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This code handle user interaction for image/file upload/browser dialog. + * Is loaded from filebrowser_plain.tpl + * + * To load filebrowser in colorbox, call + * + * Dialog.doImageBrowser(eventname, id); + * + * or + * + * Dialog.doFileBrowser(eventname, id); + * + * where: + * + * eventname: event name to catch return value + * id: id returned to event handler + * + * When user select an item, an event in fired in parent page, on body element + * The event is named + * + * fbrowser..[] + * + * will be one of "image" or "file", and the event handler will + * get the following params: + * + * filename: filename of item chosen by user + * embed: bbcode to embed element into posts + * id: id from caller code + * + * example: + * + * // open dialog for select an image for a textarea with id "myeditor" + * var id="myeditor"; + * Dialog.doImageBrowser("example", id); + * + * // setup event handler to get user selection + * $("body").on("fbrowser.image.example", function(event, filename, bbcode, id) { + * // close colorbox + * $.colorbox.close(); + * // replace textarea text with bbcode + * $(id).value = bbcode; + * }); + **/ +const FileBrowser = { + nickname: '', + type: '', + event: '', + id: null, + + init: function (nickname, type) { + FileBrowser.nickname = nickname; + FileBrowser.type = type; + FileBrowser.event = 'fbrowser.' + type; + if (location['hash'] !== '') { + const h = location['hash'].replace('#', ''); + FileBrowser.event = FileBrowser.event + '.' + h.split('-')[0]; + FileBrowser.id = h.split('-')[1]; + } + + console.log('FileBrowser:', nickname, type, FileBrowser.event, FileBrowser.id); + + $('.error a.close').on('click', function (e) { + e.preventDefault(); + $('.error').addClass('hidden'); + }); + + $('.folders a, .path a').on('click', function (e) { + e.preventDefault(); + location.href = FileBrowser._getUrl("minimal", location['hash'], this.dataset.folder); + location.reload(); + }); + + $(".photo-album-photo-link").on('click', function (e) { + e.preventDefault(); + + let embed = ''; + if (FileBrowser.type === "photos") { + embed = '[url=' + this.dataset.link + '][img=' + this.dataset.img + ']' + this.dataset.alt + '[/img][/url]'; + } + if (FileBrowser.type === "attachment") { + embed = '[attachment]' + this.dataset.link + '[/attachment]'; + } + console.log(FileBrowser.event, this.dataset.filename, embed, FileBrowser.id); + parent.$('body').trigger(FileBrowser.event, [ + this.dataset.filename, + embed, + FileBrowser.id + ]); + + }); + + if ($('#upload-photos').length) + { + new window.AjaxUpload( + 'upload-photos', + { + action: 'profile/' + FileBrowser.nickname + '/photos/upload?response=json', + name: 'userfile', + responseType: 'json', + onSubmit: function (file, ext) { + $('#profile-rotator').show(); + $('.error').addClass('hidden'); + }, + onComplete: function (file, response) { + if (response['error'] !== undefined) { + $('.error span').html(response['error']); + $('.error').removeClass('hidden'); + $('#profile-rotator').hide(); + return; + } + location.href = FileBrowser._getUrl("minimal", location['hash']); + location.reload(); + } + } + ); + } + + if ($('#upload-attachment').length) + { + new window.AjaxUpload( + 'upload-attachment', + { + action: 'profile/' + FileBrowser.nickname + '/attachment/upload?response=json', + name: 'userfile', + responseType: 'json', + onSubmit: function (file, ext) { + $('#profile-rotator').show(); + $('.error').addClass('hidden'); + }, + onComplete: function (file, response) { + if (response['error'] !== undefined) { + $('.error span').html(response['error']); + $('.error').removeClass('hidden'); + $('#profile-rotator').hide(); + return; + } + location.href = FileBrowser._getUrl("minimal", location['hash']); + location.reload(); + } + } + ); + } + }, + + _getUrl: function (mode, hash, folder) { + let folderValue = folder !== undefined ? folder : FileBrowser.folder; + let folderUrl = folderValue !== undefined ? '/' + encodeURIComponent(folderValue) : ''; + return 'media/' + FileBrowser.type + '/browser' + folderUrl + '?mode=' + mode + hash; + } +}; +// @license-end diff --git a/view/templates/media/filebrowser.tpl b/view/templates/media/filebrowser.tpl new file mode 100644 index 0000000000..6c087a62be --- /dev/null +++ b/view/templates/media/filebrowser.tpl @@ -0,0 +1,51 @@ + + + + +
+ + +
+ {{foreach $path as $folder => $name}} + {{$name}} + {{/foreach}} +
+ + {{if $folders }} +
+
    + {{foreach $folders as $folder}} +
  • {{$folder}}
  • + {{/foreach}} +
+
+ {{/if}} + +
+ {{foreach $files as $f}} + + {{/foreach}} +
+ +
+ +
+
+ + + + + diff --git a/view/templates/profile/filebrowser.tpl b/view/templates/profile/filebrowser.tpl deleted file mode 100644 index ff25741a9b..0000000000 --- a/view/templates/profile/filebrowser.tpl +++ /dev/null @@ -1,51 +0,0 @@ - - - - -
- - -
- {{foreach $path as $folder => $name}} - {{$name}} - {{/foreach}} -
- - {{if $folders }} -
-
    - {{foreach $folders as $folder}} -
  • {{$folder}}
  • - {{/foreach}} -
-
- {{/if}} - -
- {{foreach $files as $f}} - - {{/foreach}} -
- -
- -
-
- - - - - diff --git a/view/theme/frio/js/filebrowser.js b/view/theme/frio/js/filebrowser.js deleted file mode 100644 index b8e5086450..0000000000 --- a/view/theme/frio/js/filebrowser.js +++ /dev/null @@ -1,252 +0,0 @@ -// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPLv3-or-later -/** - * Filebrowser - Friendica Communications Server - * - * Copyright (c) 2010-2021, the Friendica project - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This code handle user interaction for photo/file upload/browser dialog. - * Is loaded from filebrowser_plain.tpl - * - * To load filebrowser in colorbox, call - * - * Dialog.doImageBrowser(eventname, id); - * - * or - * - * Dialog.doFileBrowser(eventname, id); - * - * where: - * - * eventname: event name to catch return value - * id: id returned to event handler - * - * When user select an item, an event in fired in parent page, on body element - * The event is named - * - * fbrowser..[] - * - * will be one of "image" or "file", and the event handler will - * get the following params: - * - * filename: filename of item chosen by user - * embed: bbcode to embed element into posts - * id: id from caller code - * - * example: - * - * // open dialog for select an image for a textarea with id "myeditor" - * var id="myeditor"; - * Dialog.doImageBrowser("example", id); - * - * // setup event handler to get user selection - * $("body").on("fbrowser.image.example", function(event, filename, bbcode, id) { - * // close colorbox - * $.colorbox.close(); - * // replace textarea text with bbcode - * $(id).value = bbcode; - * }); - **/ - -/* - * IMPORTANT - * - * This is a modified version to work with - * the frio theme.and bootstrap modals - * - * The original file is under: - * js/filebrowser.js - * - */ - -var FileBrowser = { - nickname: '', - type: '', - event: '', - folder: '', - id: null, - - init: function (nickname, type, hash) { - FileBrowser.nickname = nickname; - FileBrowser.type = type; - FileBrowser.event = 'fbrowser.' + type; - - if (hash !== '') { - const h = hash.replace('#', ''); - const destination = h.split('-')[0]; - FileBrowser.id = h.split('-')[1]; - FileBrowser.event = FileBrowser.event + '.' + destination; - if (destination === 'comment') { - // Get the comment textinput field - var commentElm = document.getElementById('comment-edit-text-' + FileBrowser.id); - } - } - - console.log('FileBrowser: ' + nickname, type, FileBrowser.event, FileBrowser.id); - - FileBrowser.postLoad(); - - $('.error .close').on('click', function (e) { - e.preventDefault(); - $('.error').addClass('hidden'); - }); - - // Click on album link - $('.fbrowser').on('click', '.folders button, .path button', function (e) { - e.preventDefault(); - let url = FileBrowser._getUrl("none", this.dataset.folder); - FileBrowser.folder = this.dataset.folder; - - FileBrowser.loadContent(url); - }); - - //Embed on click - $('.fbrowser').on('click', '.photo-album-photo-link', function (e) { - e.preventDefault(); - - let embed = ''; - if (FileBrowser.type === 'photos') { - embed = '[url=' + this.dataset.link + '][img=' + this.dataset.img + ']' + this.dataset.alt + '[/img][/url]'; - } - if (FileBrowser.type === 'attachment') { - embed = '[attachment]' + this.dataset.link + '[/attachment]'; - } - - // Delete prefilled Text of the comment input - // Note: not the best solution but function commentOpenUI don't - // work as expected (we need a way to wait until commentOpenUI would be finished). - // As for now we insert pieces of this function here - if (commentElm !== null && typeof commentElm !== 'undefined') { - if (commentElm.value === '') { - $('#comment-edit-text-' + FileBrowser.id) - .addClass('comment-edit-text-full') - .removeClass('comment-edit-text-empty'); - $('#comment-edit-submit-wrapper-' + FileBrowser.id).show(); - $('#comment-edit-text-' + FileBrowser.id).attr('tabindex', '9'); - $('#comment-edit-submit-' + FileBrowser.id).attr('tabindex', '10'); - } - } - - console.log(FileBrowser.event, this.dataset.filename, embed, FileBrowser.id); - - $('body').trigger(FileBrowser.event, [this.dataset.filename, embed, FileBrowser.id, this.dataset.img]); - - // Close model - $('#modal').modal('hide'); - // Update autosize for this textarea - autosize.update($('.text-autosize')); - }); - - // EventListener for switching between photo and file mode - $('.fbrowser').on('click', '.fbswitcher .btn', function (e) { - e.preventDefault(); - FileBrowser.type = this.getAttribute('data-mode'); - $('.fbrowser') - .removeClass() - .addClass('fbrowser ' + FileBrowser.type); - - FileBrowser.loadContent(FileBrowser._getUrl("none")); - }); - }, - - // Initialize the AjaxUpload for the upload buttons - uploadButtons: function () { - if ($('#upload-photos').length) { - //AjaxUpload for photos - new window.AjaxUpload( - 'upload-photos', - { - action: 'profile/' + FileBrowser.nickname + '/photos/upload?response=json&album=' + encodeURIComponent(FileBrowser.folder), - name: 'userfile', - responseType: 'json', - onSubmit: function (file, ext) { - $('.fbrowser-content').hide(); - $('.fbrowser .profile-rotator-wrapper').show(); - $('.error').addClass('hidden'); - }, - onComplete: function (file, response) { - if (response['error'] !== undefined) { - $('.error span').html(response['error']); - $('.error').removeClass('hidden'); - $('.fbrowser .profile-rotator-wrapper').hide(); - $('.fbrowser-content').show(); - return; - } - // load new content to fbrowser window - FileBrowser.loadContent(FileBrowser._getUrl("none")); - }, - }); - } - - if ($('#upload-attachment').length) { - //AjaxUpload for files - new window.AjaxUpload( - 'upload-attachment', - { - action: 'profile/' + FileBrowser.nickname + '/attachment/upload?response=json', - name: 'userfile', - responseType: 'json', - onSubmit: function (file, ext) { - $('.fbrowser-content').hide(); - $('.fbrowser .profile-rotator-wrapper').show(); - $('.error').addClass('hidden'); - }, - onComplete: function (file, response) { - if (response["error"] !== undefined) { - $('.error span').html(response['error']); - $('.error').removeClass('hidden'); - $('.fbrowser .profile-rotator-wrapper').hide(); - $('.fbrowser-content').show(); - return; - } - // Load new content to fbrowser window - FileBrowser.loadContent(FileBrowser._getUrl("none")); - }, - }); - } - }, - - // Stuff which should be executed if no content was loaded - postLoad: function () { - FileBrowser.initGallery(); - $('.fbrowser .fbswitcher .btn').removeClass('active'); - $('.fbrowser .fbswitcher [data-mode=' + FileBrowser.type + ']').addClass('active'); - // We need to add the AjaxUpload to the button - FileBrowser.uploadButtons(); - }, - - // Load new content (e.g. change photo album) - loadContent: function (url) { - $('.fbrowser-content').hide(); - $('.fbrowser .profile-rotator-wrapper').show(); - - // load new content to fbrowser window - $('.fbrowser').load(url, function (responseText, textStatus) { - $('.profile-rotator-wrapper').hide(); - if (textStatus === 'success') { - $(".fbrowser_content").show(); - FileBrowser.postLoad(); - } - }); - }, - - // Initialize justified Gallery - initGallery: function () { - $('.fbrowser.photos .fbrowser-content-container').justifiedGallery({ - rowHeight: 80, - margins: 4, - border: 0, - }); - }, - - _getUrl: function (mode, folder) { - let folderValue = folder !== undefined ? folder : FileBrowser.folder; - let folderUrl = folderValue !== undefined ? '/' + encodeURIComponent(folderValue) : ''; - return 'profile/' + FileBrowser.nickname + '/' + FileBrowser.type + '/browser' + folderUrl + '?mode=' + mode + "&theme=frio"; - } -}; -// @license-end diff --git a/view/theme/frio/js/modal.js b/view/theme/frio/js/modal.js index d54bd40c97..d54a33e188 100644 --- a/view/theme/frio/js/modal.js +++ b/view/theme/frio/js/modal.js @@ -132,7 +132,7 @@ Dialog.show = function (url, title) { Dialog._get_url = function (type, name, id) { var hash = name; if (id !== undefined) hash = hash + "-" + id; - return 'profile/' + localNickname + '/' + type + '/browser?mode=none&theme=frio#' + hash; + return 'media/' + type + '/browser?mode=none&theme=frio#' + hash; }; // Does load the filebrowser into the jot modal. @@ -159,14 +159,14 @@ Dialog._load = function (url) { let filebrowser = document.getElementById("filebrowser"); // Try to fetch the hash form the url. - let match = url.match(/profile\/[a-z]+\/.*(#.*)/); + let match = url.match(/media\/[a-z]+\/.*(#.*)/); if (!filebrowser || match === null) { return; //not fbrowser } // Initialize the filebrowser. loadScript("view/js/ajaxupload.js"); - loadScript("view/theme/frio/js/filebrowser.js", function () { + loadScript("view/theme/frio/js/module/media/filebrowser.js", function () { FileBrowser.init(filebrowser.dataset.nickname, filebrowser.dataset.type, match[1]); }); }; diff --git a/view/theme/frio/js/module/media/filebrowser.js b/view/theme/frio/js/module/media/filebrowser.js new file mode 100644 index 0000000000..123861c4da --- /dev/null +++ b/view/theme/frio/js/module/media/filebrowser.js @@ -0,0 +1,252 @@ +// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPLv3-or-later +/** + * Filebrowser - Friendica Communications Server + * + * Copyright (c) 2010-2021, the Friendica project + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This code handle user interaction for photo/file upload/browser dialog. + * Is loaded from filebrowser_plain.tpl + * + * To load filebrowser in colorbox, call + * + * Dialog.doImageBrowser(eventname, id); + * + * or + * + * Dialog.doFileBrowser(eventname, id); + * + * where: + * + * eventname: event name to catch return value + * id: id returned to event handler + * + * When user select an item, an event in fired in parent page, on body element + * The event is named + * + * fbrowser..[] + * + * will be one of "image" or "file", and the event handler will + * get the following params: + * + * filename: filename of item chosen by user + * embed: bbcode to embed element into posts + * id: id from caller code + * + * example: + * + * // open dialog for select an image for a textarea with id "myeditor" + * var id="myeditor"; + * Dialog.doImageBrowser("example", id); + * + * // setup event handler to get user selection + * $("body").on("fbrowser.image.example", function(event, filename, bbcode, id) { + * // close colorbox + * $.colorbox.close(); + * // replace textarea text with bbcode + * $(id).value = bbcode; + * }); + **/ + +/* + * IMPORTANT + * + * This is a modified version to work with + * the frio theme.and bootstrap modals + * + * The original file is under: + * js/filebrowser.js + * + */ + +var FileBrowser = { + nickname: '', + type: '', + event: '', + folder: '', + id: null, + + init: function (nickname, type, hash) { + FileBrowser.nickname = nickname; + FileBrowser.type = type; + FileBrowser.event = 'fbrowser.' + type; + + if (hash !== '') { + const h = hash.replace('#', ''); + const destination = h.split('-')[0]; + FileBrowser.id = h.split('-')[1]; + FileBrowser.event = FileBrowser.event + '.' + destination; + if (destination === 'comment') { + // Get the comment textinput field + var commentElm = document.getElementById('comment-edit-text-' + FileBrowser.id); + } + } + + console.log('FileBrowser: ' + nickname, type, FileBrowser.event, FileBrowser.id); + + FileBrowser.postLoad(); + + $('.error .close').on('click', function (e) { + e.preventDefault(); + $('.error').addClass('hidden'); + }); + + // Click on album link + $('.fbrowser').on('click', '.folders button, .path button', function (e) { + e.preventDefault(); + let url = FileBrowser._getUrl("none", this.dataset.folder); + FileBrowser.folder = this.dataset.folder; + + FileBrowser.loadContent(url); + }); + + //Embed on click + $('.fbrowser').on('click', '.photo-album-photo-link', function (e) { + e.preventDefault(); + + let embed = ''; + if (FileBrowser.type === 'photos') { + embed = '[url=' + this.dataset.link + '][img=' + this.dataset.img + ']' + this.dataset.alt + '[/img][/url]'; + } + if (FileBrowser.type === 'attachment') { + embed = '[attachment]' + this.dataset.link + '[/attachment]'; + } + + // Delete prefilled Text of the comment input + // Note: not the best solution but function commentOpenUI don't + // work as expected (we need a way to wait until commentOpenUI would be finished). + // As for now we insert pieces of this function here + if (commentElm !== null && typeof commentElm !== 'undefined') { + if (commentElm.value === '') { + $('#comment-edit-text-' + FileBrowser.id) + .addClass('comment-edit-text-full') + .removeClass('comment-edit-text-empty'); + $('#comment-edit-submit-wrapper-' + FileBrowser.id).show(); + $('#comment-edit-text-' + FileBrowser.id).attr('tabindex', '9'); + $('#comment-edit-submit-' + FileBrowser.id).attr('tabindex', '10'); + } + } + + console.log(FileBrowser.event, this.dataset.filename, embed, FileBrowser.id); + + $('body').trigger(FileBrowser.event, [this.dataset.filename, embed, FileBrowser.id, this.dataset.img]); + + // Close model + $('#modal').modal('hide'); + // Update autosize for this textarea + autosize.update($('.text-autosize')); + }); + + // EventListener for switching between photo and file mode + $('.fbrowser').on('click', '.fbswitcher .btn', function (e) { + e.preventDefault(); + FileBrowser.type = this.getAttribute('data-mode'); + $('.fbrowser') + .removeClass() + .addClass('fbrowser ' + FileBrowser.type); + + FileBrowser.loadContent(FileBrowser._getUrl("none")); + }); + }, + + // Initialize the AjaxUpload for the upload buttons + uploadButtons: function () { + if ($('#upload-photos').length) { + //AjaxUpload for photos + new window.AjaxUpload( + 'upload-photos', + { + action: 'profile/' + FileBrowser.nickname + '/photos/upload?response=json&album=' + encodeURIComponent(FileBrowser.folder), + name: 'userfile', + responseType: 'json', + onSubmit: function (file, ext) { + $('.fbrowser-content').hide(); + $('.fbrowser .profile-rotator-wrapper').show(); + $('.error').addClass('hidden'); + }, + onComplete: function (file, response) { + if (response['error'] !== undefined) { + $('.error span').html(response['error']); + $('.error').removeClass('hidden'); + $('.fbrowser .profile-rotator-wrapper').hide(); + $('.fbrowser-content').show(); + return; + } + // load new content to fbrowser window + FileBrowser.loadContent(FileBrowser._getUrl("none")); + }, + }); + } + + if ($('#upload-attachment').length) { + //AjaxUpload for files + new window.AjaxUpload( + 'upload-attachment', + { + action: 'profile/' + FileBrowser.nickname + '/attachment/upload?response=json', + name: 'userfile', + responseType: 'json', + onSubmit: function (file, ext) { + $('.fbrowser-content').hide(); + $('.fbrowser .profile-rotator-wrapper').show(); + $('.error').addClass('hidden'); + }, + onComplete: function (file, response) { + if (response["error"] !== undefined) { + $('.error span').html(response['error']); + $('.error').removeClass('hidden'); + $('.fbrowser .profile-rotator-wrapper').hide(); + $('.fbrowser-content').show(); + return; + } + // Load new content to fbrowser window + FileBrowser.loadContent(FileBrowser._getUrl("none")); + }, + }); + } + }, + + // Stuff which should be executed if no content was loaded + postLoad: function () { + FileBrowser.initGallery(); + $('.fbrowser .fbswitcher .btn').removeClass('active'); + $('.fbrowser .fbswitcher [data-mode=' + FileBrowser.type + ']').addClass('active'); + // We need to add the AjaxUpload to the button + FileBrowser.uploadButtons(); + }, + + // Load new content (e.g. change photo album) + loadContent: function (url) { + $('.fbrowser-content').hide(); + $('.fbrowser .profile-rotator-wrapper').show(); + + // load new content to fbrowser window + $('.fbrowser').load(url, function (responseText, textStatus) { + $('.profile-rotator-wrapper').hide(); + if (textStatus === 'success') { + $(".fbrowser_content").show(); + FileBrowser.postLoad(); + } + }); + }, + + // Initialize justified Gallery + initGallery: function () { + $('.fbrowser.photos .fbrowser-content-container').justifiedGallery({ + rowHeight: 80, + margins: 4, + border: 0, + }); + }, + + _getUrl: function (mode, folder) { + let folderValue = folder !== undefined ? folder : FileBrowser.folder; + let folderUrl = folderValue !== undefined ? '/' + encodeURIComponent(folderValue) : ''; + return 'media/' + FileBrowser.type + '/browser' + folderUrl + '?mode=' + mode + "&theme=frio"; + } +}; +// @license-end diff --git a/view/theme/frio/templates/js_strings.tpl b/view/theme/frio/templates/js_strings.tpl index c422648a21..066e4bd585 100644 --- a/view/theme/frio/templates/js_strings.tpl +++ b/view/theme/frio/templates/js_strings.tpl @@ -5,7 +5,6 @@ They are loaded into the html so that js functions can use them *}} var updateInterval = {{$update_interval}}; var localUser = {{if $local_user}}{{$local_user}}{{else}}false{{/if}}; - var localNickname = {{if $local_nickname}}"{{$local_nickname|escape:'javascript' nofilter}}"{{else}}false{{/if}}; var aStr = { 'delitem' : "{{$delitem|escape:'javascript' nofilter}}", 'blockAuthor' : "{{$blockAuthor|escape:'javascript' nofilter}}", diff --git a/view/theme/frio/templates/media/filebrowser.tpl b/view/theme/frio/templates/media/filebrowser.tpl new file mode 100644 index 0000000000..7b24537cee --- /dev/null +++ b/view/theme/frio/templates/media/filebrowser.tpl @@ -0,0 +1,64 @@ + +
+
+ + + {{* The breadcrumb navigation *}} + + +
+ + {{* List of photo albums *}} + {{if $folders }} + + {{/if}} + + {{* The main content (images or files) *}} +
+
+ {{foreach $files as $f}} + + {{/foreach}} +
+
+
+ +
+ +
+
+ + {{* This part contains the conent loader icon which is visible when new conent is loaded *}} + +
diff --git a/view/theme/frio/templates/profile/filebrowser.tpl b/view/theme/frio/templates/profile/filebrowser.tpl deleted file mode 100644 index 7b24537cee..0000000000 --- a/view/theme/frio/templates/profile/filebrowser.tpl +++ /dev/null @@ -1,64 +0,0 @@ - -
-
- - - {{* The breadcrumb navigation *}} - - -
- - {{* List of photo albums *}} - {{if $folders }} - - {{/if}} - - {{* The main content (images or files) *}} -
-
- {{foreach $files as $f}} - - {{/foreach}} -
-
-
- -
- -
-
- - {{* This part contains the conent loader icon which is visible when new conent is loaded *}} - -