diff --git a/adm/style/acp_mchat_globalsettings.html b/adm/style/acp_mchat_globalsettings.html index 5655ec1..53402be 100644 --- a/adm/style/acp_mchat_globalsettings.html +++ b/adm/style/acp_mchat_globalsettings.html @@ -80,9 +80,9 @@
-
-
- +
+
+
diff --git a/adm/style/acp_mchat_globalusersettings_content.html b/adm/style/acp_mchat_globalusersettings_content.html index 8e0cdf8..6b8b172 100644 --- a/adm/style/acp_mchat_globalusersettings_content.html +++ b/adm/style/acp_mchat_globalusersettings_content.html @@ -63,13 +63,6 @@ -
-
-
- - -
-
diff --git a/composer.json b/composer.json index a65c00d..a49f221 100644 --- a/composer.json +++ b/composer.json @@ -3,8 +3,8 @@ "type": "phpbb-extension", "description": "mChat", "homepage": "https://www.phpbb.com/customise/db/extension/mchat_extension/", - "version": "2.1.0", - "time": "2018-06-22", + "version": "2.1.1", + "time": "2018-09-01", "keywords": ["phpbb", "extension", "mchat"], "license": "GPL-2.0-only", "authors": [ diff --git a/config/services.yml b/config/services.yml index 1cc5b91..0d6c01e 100644 --- a/config/services.yml +++ b/config/services.yml @@ -67,6 +67,7 @@ services: - '@ext.manager' - '@text_formatter.parser' - '@?phpbb.collapsiblecategories.operator' + - '@?rmcgirr83.authorizedforurls.listener' dmzx.mchat.functions: class: dmzx\mchat\core\functions diff --git a/core/functions.php b/core/functions.php index 50d0b82..afff00d 100644 --- a/core/functions.php +++ b/core/functions.php @@ -397,25 +397,35 @@ class functions /** * Returns the total number of messages * + * @param string $sql_where + * @param string $sql_order_by * @return int */ - public function mchat_total_message_count() + public function mchat_total_message_count($sql_where = '', $sql_order_by = '') { + $sql_where_array = array_filter([$sql_where, $this->mchat_notifications->get_sql_where()]); + $sql_array = [ 'SELECT' => 'COUNT(*) AS rows_total', 'FROM' => [$this->mchat_settings->get_table_mchat() => 'm'], - 'WHERE' => $this->mchat_notifications->get_sql_where(), + 'WHERE' => $sql_where_array ? ('(' . implode(') AND (', $sql_where_array) . ')') : '', + 'ORDER_BY' => $sql_order_by, ]; /** * Event to modifying the SQL query that fetches the total number of mChat messages * * @event dmzx.mchat.total_message_count_modify_sql - * @var array sql_array Array with SQL query data to fetch the total message count + * @var array sql_array Array with SQL query data to fetch the total message count + * @var string sql_where Additional SQL where condition passed to this method + * @var string sql_order_by Additional SQL order by statement passed to this method * @since 2.0.0-RC6 + * @changed 2.1.1 Added sql_where, sql_order_by */ $vars = [ 'sql_array', + 'sql_where', + 'sql_order_by', ]; extract($this->dispatcher->trigger_event('dmzx.mchat.total_message_count_modify_sql', compact($vars))); @@ -454,7 +464,7 @@ class functions $message_ids = [$message_ids]; } - $sql_where_message_id[] = $this->db->sql_in_set('m.message_id', array_map('intval', $message_ids)); + $sql_where_message_id[] = $this->db->sql_in_set('m.message_id', $message_ids); } $sql_where_ary = array_filter([ diff --git a/core/mchat.php b/core/mchat.php index bcf5a34..6ea79f2 100644 --- a/core/mchat.php +++ b/core/mchat.php @@ -23,6 +23,7 @@ use phpbb\request\request_interface; use phpbb\template\template; use phpbb\textformatter\parser_interface; use phpbb\user; +use rmcgirr83\authorizedforurls\event\listener as authorizedforurls; use Symfony\Component\HttpFoundation\JsonResponse; class mchat @@ -72,6 +73,9 @@ class mchat /** @var cc_operator */ protected $cc_operator; + /** @var authorizedforurls */ + protected $authorized_for_urls; + /** @var boolean */ protected $remove_disallowed_bbcodes = false; @@ -102,6 +106,7 @@ class mchat * @param manager $extension_manager * @param parser_interface $textformatter_parser * @param cc_operator $cc_operator + * @param authorizedforurls $authorized_for_urls */ public function __construct( functions $mchat_functions, @@ -118,7 +123,8 @@ class mchat dispatcher_interface $dispatcher, manager $extension_manager, parser_interface $textformatter_parser, - cc_operator $cc_operator = null + cc_operator $cc_operator = null, + authorizedforurls $authorized_for_urls = null ) { $this->mchat_functions = $mchat_functions; @@ -136,6 +142,7 @@ class mchat $this->extension_manager = $extension_manager; $this->textformatter_parser = $textformatter_parser; $this->cc_operator = $cc_operator; + $this->authorized_for_urls = $authorized_for_urls; } /** @@ -314,12 +321,6 @@ class mchat throw new http_exception(403, 'NO_AUTH_OPERATION'); } - // Fix avatars & smilies - if (!defined('PHPBB_USE_BOARD_URL_PATH')) - { - define('PHPBB_USE_BOARD_URL_PATH', true); - } - $this->lang->add_lang('mchat', 'dmzx/mchat'); } @@ -757,14 +758,17 @@ class mchat // Add lang file $this->lang->add_lang('posting'); + $is_archive = $page == 'archive'; + $jump_to_id = $is_archive ? $this->request->variable('jumpto', 0) : 0; + // If the static message is not empty in the language file, use it, else ise the static message in the database $static_message = $this->lang->lang('MCHAT_STATIC_MESSAGE') ?: $this->mchat_settings->cfg('mchat_static_message'); $whois_refresh = $this->mchat_settings->cfg('mchat_whois_index') || $this->mchat_settings->cfg('mchat_navbar_link_count'); - $this->template->assign_vars([ + $template_data = [ 'MCHAT_PAGE' => $page, + 'MCHAT_CURRENT_URL' => '.' . $this->user->page['script_path'] . $this->user->page['page'], 'MCHAT_ALLOW_SMILES' => $this->mchat_settings->cfg('allow_smilies') && $this->auth->acl_get('u_mchat_smilies'), - 'MCHAT_INPUT_AREA' => $this->mchat_settings->cfg('mchat_input_area'), 'MCHAT_MESSAGE_TOP' => $this->mchat_settings->cfg('mchat_message_top'), 'MCHAT_INDEX_HEIGHT' => $this->mchat_settings->cfg('mchat_index_height'), 'MCHAT_CUSTOM_HEIGHT' => $this->mchat_settings->cfg('mchat_custom_height'), @@ -783,22 +787,23 @@ class mchat 'MCHAT_STATIC_MESS' => htmlspecialchars_decode($static_message), 'MCHAT_MAX_INPUT_HEIGHT' => $this->mchat_settings->cfg('mchat_max_input_height'), 'MCHAT_MAX_MESSAGE_LENGTH' => $this->mchat_settings->cfg('mchat_max_message_lngth'), + 'MCHAT_JUMP_TO' => $jump_to_id, 'COOKIE_NAME' => $this->mchat_settings->cfg('cookie_name', true) . '_', - ]); + ]; // The template needs some language variables if we display relative time for messages if ($this->mchat_settings->cfg('mchat_relative_time')) { - $this->template->assign_var('MCHAT_MINUTES_AGO_LIMIT', $this->get_relative_minutes_limit()); + $template_data['MCHAT_MINUTES_AGO_LIMIT'] = $this->get_relative_minutes_limit(); } // Get actions which the user is allowed to perform on the current page $actions = array_keys(array_filter([ 'edit' => $this->auth_message('edit', true, time()), 'del' => $this->auth_message('delete', true, time()), - 'refresh' => $page !== 'archive' && $this->auth->acl_get('u_mchat_view'), - 'add' => $page !== 'archive' && $this->auth->acl_get('u_mchat_use'), - 'whois' => $page !== 'archive' && $whois_refresh, + 'refresh' => !$is_archive && $this->auth->acl_get('u_mchat_view'), + 'add' => !$is_archive && $this->auth->acl_get('u_mchat_use'), + 'whois' => !$is_archive && $whois_refresh, ])); foreach ($actions as $action) @@ -810,14 +815,62 @@ class mchat } $limit = $this->mchat_settings->cfg('mchat_message_num_' . $page); - $start = $page === 'archive' ? $this->request->variable('start', 0) : 0; - $rows = $this->mchat_functions->mchat_get_messages([], 0, $limit, $start); + + if ($is_archive) + { + if ($jump_to_id) + { + $sql_where_jump_to_id = 'm.message_id > ' . (int) $jump_to_id; + $sql_order_by = 'm.message_id ASC'; + $num_subsequent_messages = $this->mchat_functions->mchat_total_message_count($sql_where_jump_to_id, $sql_order_by); + $start = (int) floor($num_subsequent_messages / $limit) * $limit; + } + else + { + $start = $this->request->variable('start', 0); + } + } + else + { + $start = 0; + } + + $message_ids = []; + $last_id = 0; + + /** + * Event to modify arguments before fetching messages from the database + * + * @event dmzx.mchat.render_page_get_messages_before + * @var string page The page that is rendered, one of index|custom|archive + * @var array message_ids IDs of specific messages to fetch, should be an empty array + * @var int last_id The ID of the latest message that the user has, should be 0 + * @var int limit Number of messages to display per page + * @var int start The message which should be considered currently active, used to determine the page we're on + * @var int jump_to_id The ID of the message that is being jumped to in the archive, usually when a user clicked on a quote reference + * @var array actions Array containing URLs to actions the user is allowed to perform (read only) + * @var array template_data The data that is about to be assigned to the template + * @since 2.1.1 + */ + $vars = [ + 'page', + 'message_ids', + 'last_id', + 'limit', + 'start', + 'jump_to_id', + 'actions', + 'template_data', + ]; + extract($this->dispatcher->trigger_event('dmzx.mchat.render_page_get_messages_before', compact($vars))); + + $rows = $this->mchat_functions->mchat_get_messages($message_ids, $last_id, $limit, $start); $this->assign_global_template_data(); $this->assign_messages($rows, $page); // Render pagination - if ($page === 'archive') + if ($is_archive) { $archive_url = $this->helper->route('dmzx_mchat_page_archive_controller'); $total_messages = $this->mchat_functions->mchat_total_message_count(); @@ -830,38 +883,40 @@ class mchat * @var int total_messages Total number of messages * @var int limit Number of messages to display per page * @var int start The message which should be considered currently active, used to determine the page we're on + * @var int jump_to_id The ID of the message that is being jumped to in the archive, usually when a user clicked on a quote reference + * @var array template_data The data that is about to be assigned to the template * @since 2.0.0-RC6 + * @changed 2.1.1 added jump_to_id, template_data */ $vars = [ 'archive_url', 'total_messages', 'limit', 'start', + 'jump_to_id', + 'template_data', ]; extract($this->dispatcher->trigger_event('dmzx.mchat.render_page_pagination_before', compact($vars))); $this->pagination->generate_template_pagination($archive_url, 'pagination', 'start', $total_messages, $limit, $start); - $this->template->assign_var('MCHAT_TOTAL_MESSAGES', $this->lang->lang('MCHAT_TOTALMESSAGES', $total_messages)); + $template_data['MCHAT_TOTAL_MESSAGES'] = $this->lang->lang('MCHAT_TOTALMESSAGES', $total_messages); } // Render legend if ($page !== 'index') { $legend = $this->mchat_functions->mchat_legend(); - $this->template->assign_var('LEGEND', implode($this->lang->lang('COMMA_SEPARATOR'), $legend)); + $template_data['LEGEND'] = implode($this->lang->lang('COMMA_SEPARATOR'), $legend); } // Make mChat collapsible if ($page === 'index' && $this->cc_operator !== null) { $cc_fid = 'mchat'; - $this->template->assign_vars([ + $template_data = array_merge($template_data, [ 'MCHAT_IS_COLLAPSIBLE' => true, - 'S_MCHAT_HIDDEN' => in_array($cc_fid, $this->cc_operator->get_user_categories()), - 'U_MCHAT_COLLAPSE_URL' => $this->helper->route('phpbb_collapsiblecategories_main_controller', [ - 'forum_id' => $cc_fid, - 'hash' => generate_link_hash('collapsible_' . $cc_fid), - ]), + 'S_MCHAT_HIDDEN' => $this->cc_operator->is_collapsed($cc_fid), + 'U_MCHAT_COLLAPSE_URL' => $this->cc_operator->get_collapsible_link($cc_fid), ]); } @@ -876,15 +931,20 @@ class mchat * Event that is triggered after mChat was rendered * * @event dmzx.mchat.render_page_after - * @var string page The page that was rendered, one of index|custom|archive - * @var array actions Array containing URLs to actions the user is allowed to perform + * @var string page The page that was rendered, one of index|custom|archive + * @var array actions Array containing URLs to actions the user is allowed to perform (read only) + * @var array template_data The data that is about to be assigned to the template * @since 2.0.0-RC6 + * @changed 2.1.1 Added template_data */ $vars = [ 'page', 'actions', + 'template_data', ]; extract($this->dispatcher->trigger_event('dmzx.mchat.render_page_after', compact($vars))); + + $this->template->assign_vars($template_data); } /** @@ -970,24 +1030,7 @@ class mchat return; } - // At this point the rows are sorted by ID bottom to top. - // We need to reverse the array if they need to be sorted top to bottom. - $reverse = false; - $mchat_message_top = $this->mchat_settings->cfg('mchat_message_top'); - if ($page === 'archive') - { - $mchat_archive_sort = $this->mchat_settings->cfg('mchat_archive_sort'); - if ($mchat_archive_sort == settings::ARCHIVE_SORT_TOP_BOTTOM || $mchat_archive_sort == settings::ARCHIVE_SORT_USER && !$mchat_message_top) - { - $reverse = true; - } - } - else if (!$mchat_message_top) - { - $reverse = true; - } - - if ($reverse) + if ($this->messages_need_reversing($page)) { $rows = array_reverse($rows); } @@ -1017,20 +1060,12 @@ class mchat } } - $board_url = generate_board_url() . '/'; - $rows = $this->mchat_notifications->process($rows); foreach ($rows as $row) { $username_full = get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'], $this->lang->lang('GUEST')); - // Fix profile link root path by replacing relative paths with absolute board URL - if ($this->request->is_ajax()) - { - $username_full = preg_replace('#(?<=href=")[\./]+?/(?=\w)#', $board_url, $username_full); - } - if (in_array($row['user_id'], $this->foes)) { $row['message'] = $this->lang->lang('MCHAT_FOE', $username_full); @@ -1047,6 +1082,7 @@ class mchat $message_for_edit = generate_text_for_edit($row['message'], $row['bbcode_uid'], $row['bbcode_options']); $template_data = [ + 'MCHAT_USER_ID' => $row['user_id'], 'MCHAT_ALLOW_EDIT' => $this->auth_message('edit', $row['user_id'], $row['message_time']), 'MCHAT_ALLOW_DEL' => $this->auth_message('delete', $row['user_id'], $row['message_time']), 'MCHAT_USER_AVATAR' => $user_avatars[$row['user_id']], @@ -1100,6 +1136,34 @@ class mchat } } + /** + * By default, rows are fetched by message ID descending. This method returns true if + * the user wants them to be displayed ascending, otherwise false. + * + * @param string $page + * @return bool + */ + protected function messages_need_reversing($page) + { + $mchat_message_top = $this->mchat_settings->cfg('mchat_message_top'); + + if ($page === 'archive') + { + $mchat_archive_sort = $this->mchat_settings->cfg('mchat_archive_sort'); + + if ($mchat_archive_sort == settings::ARCHIVE_SORT_TOP_BOTTOM || $mchat_archive_sort == settings::ARCHIVE_SORT_USER && !$mchat_message_top) + { + return true; + } + } + else if (!$mchat_message_top) + { + return true; + } + + return false; + } + /** * Returns true if the user is allowed to read the given message row * @@ -1359,6 +1423,19 @@ class mchat } } + // Compatibility with Authorized for URLs by RMcGirr83 - requires at least 1.0.5 + // https://www.phpbb.com/customise/db/extension/authorized_for_urls_2/ + if ($this->authorized_for_urls !== null && is_callable([$this->authorized_for_urls, 'check_text'])) + { + $authorized_for_urls_lang_args = $this->authorized_for_urls->check_text($message, true); + + if ($authorized_for_urls_lang_args) + { + $authorized_for_urls_lang_key = array_shift($authorized_for_urls_lang_args); + throw new http_exception(400, $authorized_for_urls_lang_key, $authorized_for_urls_lang_args); + } + } + if ($this->mchat_settings->cfg('mchat_override_min_post_chars')) { $this->mchat_settings->set_cfg('min_post_chars', 0, true); diff --git a/core/settings.php b/core/settings.php index d43c91a..a27ae15 100644 --- a/core/settings.php +++ b/core/settings.php @@ -241,7 +241,6 @@ class settings 'mchat_character_count' => ['default' => 1], 'mchat_date' => ['default' => 'D M d, Y g:i a', 'validation' => ['string', false, 0, 64]], 'mchat_index' => ['default' => 1], - 'mchat_input_area' => ['default' => 1], 'mchat_location' => ['default' => 1], 'mchat_message_top' => ['default' => 1], 'mchat_posts' => ['default' => 1], diff --git a/language/en/mchat_ucp.php b/language/en/mchat_ucp.php index 8a02340..258ebde 100644 --- a/language/en/mchat_ucp.php +++ b/language/en/mchat_ucp.php @@ -45,9 +45,6 @@ $lang = array_merge($lang, [ 'MCHAT_STATS_INDEX_EXPLAIN' => 'Displays who is chatting below the Who is online section on the index page.', 'MCHAT_AVATARS' => 'Display avatars', 'MCHAT_CAPITAL_LETTER' => 'Capital first letter in your messages', - 'MCHAT_CHAT_AREA' => 'Input type', - 'MCHAT_INPUT_AREA' => 'Input field', - 'MCHAT_TEXT_AREA' => 'Text area', 'MCHAT_POSTS' => 'Display new posts (currently all disabled, can be enabled in the mChat Global Settings section in the ACP)', 'MCHAT_DISPLAY_CHARACTER_COUNT' => 'Display number of characters when typing a message', 'MCHAT_RELATIVE_TIME' => 'Display relative time for new messages', diff --git a/language/en/permissions_mchat.php b/language/en/permissions_mchat.php index f89e828..53b64c5 100644 --- a/language/en/permissions_mchat.php +++ b/language/en/permissions_mchat.php @@ -56,7 +56,6 @@ $lang = array_merge($lang, [ 'ACL_U_MCHAT_CHARACTER_COUNT' => 'Can customise Display number of characters', 'ACL_U_MCHAT_DATE' => 'Can customise Date format', 'ACL_U_MCHAT_INDEX' => 'Can customise Display on index', - 'ACL_U_MCHAT_INPUT_AREA' => 'Can customise Input type', 'ACL_U_MCHAT_LOCATION' => 'Can customise Location of mChat on the index page', 'ACL_U_MCHAT_MESSAGE_TOP' => 'Can customise Location of new chat messages', 'ACL_U_MCHAT_POSTS' => 'Can customise Display new posts', diff --git a/migrations/mchat_2_1_1.php b/migrations/mchat_2_1_1.php new file mode 100644 index 0000000..d353c3b --- /dev/null +++ b/migrations/mchat_2_1_1.php @@ -0,0 +1,55 @@ + [ + $this->table_prefix . 'users' => [ + 'user_mchat_input_area', + ], + ], + ]; + } + + public function revert_schema() + { + return [ + 'add_columns' => [ + $this->table_prefix . 'users' => [ + 'user_mchat_input_area' => ['BOOL', 1], + ], + ], + ]; + } +} diff --git a/styles/all/template/javascript/mchat.js b/styles/all/template/javascript/mchat.js index 76bdceb..f828786 100644 --- a/styles/all/template/javascript/mchat.js +++ b/styles/all/template/javascript/mchat.js @@ -106,9 +106,10 @@ jQuery(function($) { return; } var deferred = $.Deferred(); - if (sendHiddenFields) { - $.extend(data, mChat.hiddenFields); - } + $.extend(data, + {_referer: mChat.currentUrl}, + sendHiddenFields ? mChat.hiddenFields : {} + ); $(mChat).trigger('mchat_send_request_before', [mode, data]); $.ajax({ url: mChat.actionUrls[mode], @@ -427,6 +428,7 @@ jQuery(function($) { playSound = false; } mChat.messageIds.push($message.data('mchat-id')); + mChat.fixJumpToUrl.call($message); setTimeout(function() { var dataAddMessageAnimateBefore = { container: mChat.cached('messages'), @@ -453,7 +455,7 @@ jQuery(function($) { } else { animateOptions.complete = function() { var scrollHeight = container.get(0).scrollHeight; - if (container.scrollTop() + container.height() < scrollHeight) { + if (container.scrollTop() + container.innerHeight() < scrollHeight) { container.animate({scrollTop: scrollHeight}, animateOptions); } }; @@ -480,7 +482,7 @@ jQuery(function($) { }); }, mChat.editDeleteLimit); } - mChat.startRelativeTimeUpdate($message); + mChat.startRelativeTimeUpdate.call($message); }); }, updateMessages: function($messages) { @@ -494,7 +496,8 @@ jQuery(function($) { }; $(mChat).trigger('mchat_edit_message_before', [data]); mChat.stopRelativeTimeUpdate(data.oldMessage); - mChat.startRelativeTimeUpdate(data.newMessage); + mChat.startRelativeTimeUpdate.call(data.newMessage); + mChat.fixJumpToUrl.call(data.newMessage); data.oldMessage.fadeOut(function() { data.oldMessage.replaceWith(data.newMessage.hide().fadeIn()); }); @@ -527,9 +530,9 @@ jQuery(function($) { } }); }, - startRelativeTimeUpdate: function($messages) { + startRelativeTimeUpdate: function() { if (mChat.relativeTime) { - $messages.find('.mchat-time[data-mchat-relative-update]').each(function() { + $(this).find('.mchat-time[data-mchat-relative-update]').each(function() { var $time = $(this); setTimeout(function() { mChat.relativeTimeUpdate($time); @@ -634,27 +637,67 @@ jQuery(function($) { } mChat.appendText(mChat.lang.mention.format({username: username})); }, - quote: function() { - var $container = $(this).closest('.mchat-message'); - var username = $container.data('mchat-username'); + fixJumpToUrl: function() { + var $message = $(this); + var $elem = $message.find('blockquote [data-post-id]'); + var messageId = $elem.data('post-id'); + var data = { + message: $message, + elem: $elem, + url: mChat.getArchiveQuoteUrl(messageId) + }; + $(mChat).trigger('mchat_fix_jump_to_url_before', [data]); + if (data.url) { + data.elem.attr('href', data.url); + } + }, + getArchiveQuoteUrl: function(messageId) { + var archiveUrl = $('.mchat-nav-archive').find('a').prop('href'); + return archiveUrl ? mChat.addUrlParam(archiveUrl, 'jumpto=' + messageId) : false; + }, + jumpToMessage: function() { + var messageId = $(this).data('post-id'); + var data = { + container: mChat.cached('messages'), + messageId: messageId, + message: $('#mchat-message-' + messageId), + jump: function() { + if (data.message.length) { + var scrollTop = data.message.offset().top - data.container.offset().top + data.container.scrollTop(); + data.container.scrollTop(scrollTop); + data.message.removeClass('mchat-message-flash'); + data.message.offset(); + data.message.addClass('mchat-message-flash'); + } else { + var url = mChat.getArchiveQuoteUrl(data.messageId); + if (url) { + window.open(url, '_blank'); + } + } + } + }; + $(mChat).trigger('mchat_jump_to_message_before', [data]); + data.jump(); + }, + getQuoteText: function($container) { var quote = $container.data('mchat-message'); - mChat.appendText('[quote="' + username + '"] ' + quote + '[/quote]'); + var quoteAttributes = [ + '"' + $container.data('mchat-username') + '"', + 'post_id=' + $container.data('mchat-id'), + 'time=' + $container.data('mchat-message-time'), + 'user_id=' + $container.data('mchat-user-id') + ]; + return '[quote=' + quoteAttributes.join(' ') + '] ' + quote + ' [/quote]'; + }, + quote: function() { + mChat.appendText(mChat.getQuoteText($(this).closest('.mchat-message'))); }, like: function() { - var $container = $(this).closest('.mchat-message'); - var username = $container.data('mchat-username'); - var quote = $container.data('mchat-message'); - mChat.appendText('[i]' + mChat.lang.likes + '[/i][quote="' + username + '"] ' + quote + '[/quote]'); + mChat.appendText('[i]' + mChat.lang.likes + '[/i]' + mChat.getQuoteText($(this).closest('.mchat-message'))); }, ip: function() { popup(this.href, 750, 500); }, - custom: function() { - window.location.href = this.href; - }, - archive: function() { - window.location.href = this.href; - }, setText: function(text) { mChat.cached('input').val(''); mChat.appendText(text); @@ -670,6 +713,9 @@ jQuery(function($) { $input.scrollLeft($input[0].scrollWidth - $input[0].clientWidth); } }, + addUrlParam: function(url, keyEqualsValue) { + return url + (url.indexOf('?') === -1 ? '?' : '&') + keyEqualsValue; + }, cached: function(name) { if (!mChat.cache) { mChat.cache = {}; @@ -681,16 +727,24 @@ jQuery(function($) { } }); - mChat.messageIds = mChat.cached('messages').children().map(function() { - return $(this).data('mchat-id'); - }).get(); + mChat.messageIds = mChat.cached('messages').children() + .each(mChat.startRelativeTimeUpdate) + .each(mChat.fixJumpToUrl) + .map(function() { return $(this).data('mchat-id'); }).get(); mChat.hiddenFields = {}; mChat.cached('form').find('input[type=hidden]').each(function() { mChat.hiddenFields[this.name] = this.value; }); - if (mChat.page !== 'archive') { + if (mChat.page === 'archive') { + if (mChat.jumpTo) { + var fragment = '#mchat-message-' + mChat.jumpTo; + if ($(fragment).addClass('mchat-message-flash').length) { + window.location.hash = fragment; + } + } + } else { mChat.resetSession(); if (!mChat.messageTop) { @@ -768,8 +822,6 @@ jQuery(function($) { } } - mChat.startRelativeTimeUpdate(mChat.cached('messages')); - mChat.registerNavItem('sound', mChat.playSound); if (mChat.maxInputHeight) { mChat.registerNavItem('enter', true); @@ -783,6 +835,9 @@ jQuery(function($) { e.preventDefault(); var action = $(this).data('mchat-action'); mChat[action].call(this, e); + }).on('click', '#mchat-messages blockquote [data-post-id]', function(e) { + e.preventDefault(); + mChat.jumpToMessage.call(this); }).on('click', '.mchat-panel-buttons button', function() { var $this = $(this).blur(); if ($this.hasClass('mchat-button-down')) { diff --git a/styles/all/template/mchat_script_data.html b/styles/all/template/mchat_script_data.html index a5ce86a..60612d3 100644 --- a/styles/all/template/mchat_script_data.html +++ b/styles/all/template/mchat_script_data.html @@ -14,10 +14,11 @@ // General settings actionUrls : { {% for mchaturl in loops.mchaturl %} - {{ mchaturl.ACTION }}: '{{ mchaturl.URL }}'{{ loop.last ? '' : ',' }} + {{ mchaturl.ACTION }}: '{{ mchaturl.URL }}'{{ not loop.last ? ',' }} {% endfor %} }, page : '{{ MCHAT_PAGE | escape('js') }}', + currentUrl : '{{ MCHAT_CURRENT_URL | escape('js') }}', cookie : '{{ COOKIE_NAME | escape('js') }}', playSound : {{ MCHAT_SOUND ? 'true' : 'false' }}, messageTop : {{ MCHAT_MESSAGE_TOP ? 'true' : 'false' }}, @@ -25,6 +26,7 @@ liveUpdates : {{ MCHAT_LIVE_UPDATES ? 'true' : 'false' }}, relativeTime : {{ MCHAT_RELATIVE_TIME ? 'true' : 'false' }}, showCharCount : {{ MCHAT_CHARACTER_COUNT ? 'true' : 'false' }}, + jumpTo : {{ MCHAT_JUMP_TO }}, // Limits & timeouts refreshTime : {{ MCHAT_REFRESH_JS }}, @@ -41,7 +43,7 @@ minutesAgo : { {% if MCHAT_RELATIVE_TIME %} {% for minute in 0..MCHAT_MINUTES_AGO_LIMIT-1 %} - {{ minute }}: '{{ lang('MCHAT_MINUTES_AGO', minute) | escape('js') }}'{{ loop.last ? '' : ',' }} + {{ minute }}: '{{ lang('MCHAT_MINUTES_AGO', minute) | escape('js') }}'{{ not loop.last ? ',' }} {% endfor %} {% endif %} }, diff --git a/styles/prosilver/template/mchat_body.html b/styles/prosilver/template/mchat_body.html index 3c2e1e4..381a568 100644 --- a/styles/prosilver/template/mchat_body.html +++ b/styles/prosilver/template/mchat_body.html @@ -107,7 +107,7 @@ {% EVENT dmzx_mchat_after %} -{% if MCHAT_PAGE == 'archive' %} +{% if MCHAT_PAGE == 'archive' and (loops.pagination|length or MCHAT_TOTAL_MESSAGES) %}
{% EVENT dmzx_mchat_action_bar_bottom_before %}
{% endif %} - {% if MCHAT_INPUT_AREA_AUTH and MCHAT_ALLOW_USE %} -
-
-
- - -
-
- {% endif %} {% if MCHAT_CHARACTER_COUNT_AUTH and MCHAT_ALLOW_USE %}
diff --git a/styles/prosilver/theme/mchat.css b/styles/prosilver/theme/mchat.css index d1057f1..0cfa63a 100644 --- a/styles/prosilver/theme/mchat.css +++ b/styles/prosilver/theme/mchat.css @@ -77,16 +77,18 @@ animation-timing-function: ease-out; } +.mchat-message-flash:target { + animation-duration: 2s; +} + @keyframes flash-message { 0% { - background-color: #FFD070; - opacity: 0; + background-color: #FFDC95; } 100% { background-color: transparent; - opacity: 1; } } @@ -143,6 +145,10 @@ font-size: 1.2em; } +.mchat-text .postlink { + display: unset; +} + .mchat-notification-message .mchat-text { font-style: italic; }