diff --git a/adm/style/acp_mchat_globalsettings.html b/adm/style/acp_mchat_globalsettings.html index 4418b95..8f6702a 100644 --- a/adm/style/acp_mchat_globalsettings.html +++ b/adm/style/acp_mchat_globalsettings.html @@ -40,8 +40,7 @@
-

- {L_MCHAT_CUSTOM_PAGE_EXPLAIN}
+
@@ -82,6 +81,14 @@ +
+
+
+
+
+ +
+
{L_MCHAT_SETTINGS_MESSAGES} diff --git a/composer.json b/composer.json index a5851af..e159c45 100644 --- a/composer.json +++ b/composer.json @@ -1,10 +1,10 @@ { "name": "dmzx/mchat", "type": "phpbb-extension", - "description": "mChat Extension", + "description": "mChat", "homepage": "https://github.com/kasimi/mChat", - "version": "2.0.0", - "time": "2016-10-20", + "version": "2.0.1", + "time": "2017-02-03", "keywords": ["phpbb", "extension", "mchat"], "license": "GPL-2.0", "authors": [ @@ -39,10 +39,9 @@ "phpbb/phpbb": ">=3.1.8-RC1,<3.3.0@dev" }, "version-check": { - "host": "kasimi.github.io", - "directory": "/mChat", - "filename": "mchat_version.json", - "ssl": true + "host": "www.phpbb.com", + "directory": "/customise/db/extension/mchat_extension", + "filename": "version_check" } } } diff --git a/config/services.yml b/config/services.yml index f992450..33dd677 100644 --- a/config/services.yml +++ b/config/services.yml @@ -76,6 +76,7 @@ services: - '@request' - '@user' - '@dmzx.mchat.settings' + - '@dmzx.mchat.functions' - '%core.root_path%' - '%core.php_ext%' tags: diff --git a/controller/acp_controller.php b/controller/acp_controller.php index 2bc97ee..2541600 100644 --- a/controller/acp_controller.php +++ b/controller/acp_controller.php @@ -91,7 +91,8 @@ class acp_controller settings $settings, $mchat_table, $mchat_log_table, - $root_path, $php_ext + $root_path, + $php_ext ) { $this->functions = $functions; @@ -137,6 +138,9 @@ class acp_controller } } + // Remove leading & trailing | characters to not break allowed BBCodes + $mchat_new_config['mchat_bbcode_disallowed'] = trim($mchat_new_config['mchat_bbcode_disallowed'], '|'); + // Don't allow changing pruning settings for non founders if (!$is_founder) { @@ -194,8 +198,8 @@ class acp_controller { if ($is_founder && $this->request->is_set_post('mchat_purge') && $this->request->variable('mchat_purge_confirm', false) && check_form_key('acp_mchat')) { - $this->db->sql_query('TRUNCATE TABLE ' . $this->mchat_table); - $this->db->sql_query('TRUNCATE TABLE ' . $this->mchat_log_table); + $this->db->sql_query('DELETE FROM ' . $this->mchat_table); + $this->db->sql_query('DELETE FROM ' . $this->mchat_log_table); $this->cache->destroy('sql', $this->mchat_log_table); $this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_MCHAT_TABLE_PURGED', false, array($this->user->data['username'])); trigger_error($this->user->lang('MCHAT_PURGED') . adm_back_link($u_action)); diff --git a/core/functions.php b/core/functions.php index fe186d7..c10d4c1 100644 --- a/core/functions.php +++ b/core/functions.php @@ -308,9 +308,10 @@ class functions /** * Prune messages * + * @param int|array $user_ids * @return array */ - public function mchat_prune() + public function mchat_prune($user_ids = array()) { $prune_num = (int) $this->settings->cfg('mchat_prune_num'); $prune_mode = (int) $this->settings->cfg('mchat_prune_mode'); @@ -325,7 +326,17 @@ class functions 'FROM' => array($this->mchat_table => 'm'), ); - if ($this->settings->prune_modes[$prune_mode] === 'messages') + if ($user_ids) + { + if (!is_array($user_ids)) + { + $user_ids = array($user_ids); + } + + $sql_array['WHERE'] = $this->db->sql_in_set('m.user_id', $user_ids); + $offset = 0; + } + else if ($this->settings->prune_modes[$prune_mode] === 'messages') { // Skip fixed number of messages, delete all others $sql_array['ORDER_BY'] = 'm.message_id DESC'; @@ -355,10 +366,13 @@ class functions * * @event dmzx.mchat.prune_before * @var array prune_ids Array of message IDs that are about to be pruned + * @var array user_ids Array of user IDs that are being pruned * @since 2.0.0-RC6 + * @changed 2.0.1 Added user_ids */ $vars = array( 'prune_ids', + 'user_ids', ); extract($this->dispatcher->trigger_event('dmzx.mchat.prune_before', compact($vars))); @@ -368,7 +382,11 @@ class functions $this->db->sql_query('DELETE FROM ' . $this->mchat_log_table . ' WHERE ' . $this->db->sql_in_set('message_id', $prune_ids)); $this->cache->destroy('sql', $this->mchat_log_table); - $this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_MCHAT_TABLE_PRUNED', false, array($this->user->data['username'], count($prune_ids))); + // Only add a log entry if message pruning was not triggered by user pruning + if (!$user_ids) + { + $this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_MCHAT_TABLE_PRUNED', false, array($this->user->data['username'], count($prune_ids))); + } } return $prune_ids; @@ -672,7 +690,7 @@ class functions return array(); } - $sql = 'SELECT p.post_id, p.post_subject, f.forum_name + $sql = 'SELECT p.post_id, p.post_subject, f.forum_id, f.forum_name FROM ' . POSTS_TABLE . ' p, ' . FORUMS_TABLE . ' f WHERE p.forum_id = f.forum_id AND ' . $this->db->sql_in_set('p.post_id', $post_ids); @@ -687,6 +705,7 @@ class functions { $post_subjects[$row['post_id']] = array( 'post_subject' => $row['post_subject'], + 'forum_id' => $row['forum_id'], 'forum_name' => $row['forum_name'], ); } @@ -812,14 +831,13 @@ class functions /** * Returns user ID & name of the specified message * - * @param $message_id + * @param int $message_id * @return array */ public function mchat_author_for_message($message_id) { - $sql = 'SELECT u.user_id, u.username, m.message_time, m.forum_id, m.post_id + $sql = 'SELECT m.user_id, m.message_time, m.post_id FROM ' . $this->mchat_table . ' m - LEFT JOIN ' . USERS_TABLE . ' u ON m.user_id = u.user_id WHERE m.message_id = ' . (int) $message_id; $result = $this->db->sql_query($sql); $row = $this->db->sql_fetchrow($result); diff --git a/core/mchat.php b/core/mchat.php index 1008def..c227b70 100644 --- a/core/mchat.php +++ b/core/mchat.php @@ -423,7 +423,13 @@ class mchat $author = $this->functions->mchat_author_for_message($message_id); - if (!$author || $author['post_id'] || !$this->auth_message('edit', $author['user_id'], $author['message_time'])) + if (!$author) + { + throw new http_exception(410, 'MCHAT_MESSAGE_DELETED'); + } + + // If post_id is not 0 it's a notification and notifications can't be edited + if ($author['post_id'] || !$this->auth_message('edit', $author['user_id'], $author['message_time'])) { throw new http_exception(403, 'NO_AUTH_OPERATION'); } @@ -483,7 +489,12 @@ class mchat $author = $this->functions->mchat_author_for_message($message_id); - if (!$author || !$this->auth_message('delete', $author['user_id'], $author['message_time'])) + if (!$author) + { + throw new http_exception(410, 'MCHAT_MESSAGE_DELETED'); + } + + if (!$this->auth_message('delete', $author['user_id'], $author['message_time'])) { throw new http_exception(403, 'NO_AUTH_OPERATION'); } @@ -797,7 +808,7 @@ class mchat 'MCHAT_ARCHIVE' => $this->auth->acl_get('u_mchat_archive'), 'MCHAT_RULES' => $this->user->lang('MCHAT_RULES_MESSAGE') || $this->settings->cfg('mchat_rules'), 'MCHAT_WHOIS_REFRESH_EXPLAIN' => $this->user->lang('MCHAT_WHO_IS_REFRESH_EXPLAIN', $this->settings->cfg('mchat_whois_refresh')), - 'MCHAT_SESSION_TIMELEFT' => $this->user->lang('MCHAT_SESSION_ENDS', gmdate('H:i:s', (int) $this->settings->cfg('mchat_timeout'))), + 'MCHAT_SESSION_TIMELEFT' => $this->user->lang('MCHAT_SESSION_ENDS', gmdate($this->settings->cfg('mchat_timeout') >= 3600 ? 'H:i:s' : 'i:s', $this->settings->cfg('mchat_timeout'))), 'MCHAT_LOG_ID' => $this->functions->get_latest_log_id(), 'MCHAT_STATIC_MESS' => htmlspecialchars_decode($static_message), 'A_MCHAT_MESS_LONG' => addslashes($this->user->lang('MCHAT_MESS_LONG', $this->settings->cfg('mchat_max_message_lngth'))), @@ -835,7 +846,7 @@ class mchat { $this->template->assign_block_vars('mchaturl', array( 'ACTION' => $action, - 'URL' => $this->helper->route('dmzx_mchat_action_' . $action . '_controller'), + 'URL' => $this->helper->route('dmzx_mchat_action_' . $action . '_controller', array(), false), 'IS_LAST' => $i + 1 === count($actions), )); } @@ -926,18 +937,15 @@ class mchat $md_manager = $this->extension_manager->create_extension_metadata_manager('dmzx/mchat', $this->template); $meta = $md_manager->get_metadata(); - $author_names = array(); $author_homepages = array(); foreach (array_slice($meta['authors'], 0, 2) as $author) { - $author_names[] = $author['name']; $author_homepages[] = sprintf('%2$s', $author['homepage'], $author['name']); } $this->template->assign_vars(array( 'MCHAT_DISPLAY_NAME' => $meta['extra']['display-name'], - 'MCHAT_AUTHOR_NAMES' => implode(' & ', $author_names), 'MCHAT_AUTHOR_HOMEPAGES' => implode(' & ', $author_homepages), )); } @@ -1004,8 +1012,24 @@ class mchat return; } - // Reverse the array if messages appear at the bottom - if ($page !== 'archive' && !$this->settings->cfg('mchat_message_top')) + // 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->settings->cfg('mchat_message_top'); + if ($page === 'archive') + { + $mchat_archive_sort = $this->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) { $rows = array_reverse($rows); } @@ -1021,12 +1045,12 @@ class mchat $user_avatars = array(); // Cache avatars + $display_avatar = $this->display_avatars(); foreach ($rows as $row) { if (!isset($user_avatars[$row['user_id']])) { - $display_avatar = $this->display_avatars() && $row['user_avatar']; - $user_avatars[$row['user_id']] = !$display_avatar ? '' : phpbb_get_user_avatar(array( + $user_avatars[$row['user_id']] = !$display_avatar || !$row['user_avatar'] ? '' : phpbb_get_user_avatar(array( 'avatar' => $row['user_avatar'], 'avatar_type' => $row['user_avatar_type'], 'avatar_width' => $row['user_avatar_width'] >= $row['user_avatar_height'] ? 40 : 0, @@ -1056,7 +1080,16 @@ class mchat $message_age = time() - $row['message_time']; $minutes_ago = $this->get_minutes_ago($message_age); - $datetime = $this->user->format_date($row['message_time'], $this->settings->cfg('mchat_date'), true); + $absolute_datetime = $this->user->format_date($row['message_time'], $this->settings->cfg('mchat_date'), true); + // If relative time is selected, also display "today" / "yesterday", else display absolute time. + if ($this->settings->cfg('mchat_relative_time')) + { + $datetime = $this->user->format_date($row['message_time'], $this->settings->cfg('mchat_date'), false); + } + else + { + $datetime = $this->user->format_date($row['message_time'], $this->settings->cfg('mchat_date'), true); + } $is_poster = $row['user_id'] != ANONYMOUS && $this->user->data['user_id'] == $row['user_id']; @@ -1080,7 +1113,7 @@ class mchat 'MCHAT_U_PERMISSIONS' => append_sid("{$board_url}{$this->root_path}adm/index.{$this->php_ext}", 'i=permissions&mode=setting_user_global&user_id%5B0%5D=' . $row['user_id'], true, $this->user->session_id), 'MCHAT_MESSAGE' => generate_text_for_display($row['message'], $row['bbcode_uid'], $row['bbcode_bitfield'], $row['bbcode_options']), 'MCHAT_TIME' => $minutes_ago === -1 ? $datetime : $this->user->lang('MCHAT_MINUTES_AGO', $minutes_ago), - 'MCHAT_DATETIME' => $datetime, + 'MCHAT_DATETIME' => $absolute_datetime, 'MCHAT_MINUTES_AGO' => $minutes_ago, 'MCHAT_RELATIVE_UPDATE' => 60 - $message_age % 60, 'MCHAT_MESSAGE_TIME' => $row['message_time'], @@ -1215,8 +1248,12 @@ class mchat '#' => 'p' . $row['post_id'], )); + // We prefer $post_data because it was fetched from the forums table just now. + // $row might contain outdated data if a post was moved to a new forum. + $forum_id = isset($post_data['forum_id']) ? $post_data['forum_id'] : $row['forum_id']; + $viewforum_url = append_sid($board_url . 'viewforum.' . $this->php_ext, array( - 'f' => $row['forum_id'], + 'f' => $forum_id, )); if ($post_data) @@ -1491,7 +1528,8 @@ class mchat // Must not exceed character limit if ($this->settings->cfg('mchat_max_message_lngth')) { - if (utf8_strlen($message) > $this->settings->cfg('mchat_max_message_lngth')) + $message_without_entities = htmlspecialchars_decode($message, ENT_COMPAT); + if (utf8_strlen($message_without_entities) > $this->settings->cfg('mchat_max_message_lngth')) { throw new http_exception(400, 'MCHAT_MESS_LONG', array($this->settings->cfg('mchat_max_message_lngth'))); } diff --git a/core/settings.php b/core/settings.php index 24b9e64..6bfe327 100644 --- a/core/settings.php +++ b/core/settings.php @@ -68,6 +68,13 @@ class settings /** @var bool */ public $is_phpbb32; + /** + * Possible values of the global setting mchat_archive_sort + */ + const ARCHIVE_SORT_TOP_BOTTOM = 0; + const ARCHIVE_SORT_BOTTOM_TOP = 1; + const ARCHIVE_SORT_USER = 2; + /** * Constructor * @@ -98,6 +105,7 @@ class settings public function initialize_global_settings() { $global_settings = array( + 'mchat_archive_sort' => array('default' => self::ARCHIVE_SORT_BOTTOM_TOP), 'mchat_bbcode_disallowed' => array('default' => '', 'validation' => array('string', false, 0, 255)), 'mchat_custom_height' => array('default' => 350, 'validation' => array('num', false, 50, 1000)), 'mchat_custom_page' => array('default' => 1), diff --git a/event/acp_listener.php b/event/acp_listener.php index e5369ca..2872906 100644 --- a/event/acp_listener.php +++ b/event/acp_listener.php @@ -11,6 +11,7 @@ namespace dmzx\mchat\event; +use dmzx\mchat\core\functions; use dmzx\mchat\core\settings; use phpbb\auth\auth; use phpbb\request\request_interface; @@ -33,6 +34,9 @@ class acp_listener implements EventSubscriberInterface /** @var settings */ protected $settings; + /** @var functions */ + protected $functions; + /** @var string */ protected $root_path; @@ -46,6 +50,7 @@ class acp_listener implements EventSubscriberInterface * @param request_interface $request * @param user $user * @param settings $settings + * @param functions $functions * @param string $root_path * @param string $php_ext */ @@ -54,6 +59,7 @@ class acp_listener implements EventSubscriberInterface request_interface $request, user $user, settings $settings, + functions $functions, $root_path, $php_ext ) @@ -62,6 +68,7 @@ class acp_listener implements EventSubscriberInterface $this->request = $request; $this->user = $user; $this->settings = $settings; + $this->functions = $functions; $this->root_path = $root_path; $this->php_ext = $php_ext; } @@ -75,6 +82,8 @@ class acp_listener implements EventSubscriberInterface 'core.permissions' => 'permissions', 'core.acp_users_prefs_modify_sql' => 'acp_users_prefs_modify_sql', 'core.acp_users_prefs_modify_template_data' => 'acp_users_prefs_modify_template_data', + 'core.acp_users_overview_before' => 'acp_users_overview_before', + 'core.delete_user_after' => 'delete_user_after', ); } @@ -200,4 +209,28 @@ class acp_listener implements EventSubscriberInterface )); } } + + /** + * @param Event $event + */ + public function acp_users_overview_before($event) + { + $this->user->add_lang_ext('dmzx/mchat', 'mchat_acp'); + + $this->template->assign_vars(array( + 'L_RETAIN_POSTS' => $this->user->lang('MCHAT_RETAIN_MESSAGES', $this->user->lang('RETAIN_POSTS')), + 'L_DELETE_POSTS' => $this->user->lang('MCHAT_DELETE_MESSAGES', $this->user->lang('DELETE_POSTS')), + )); + } + + /** + * @param Event $event + */ + public function delete_user_after($event) + { + if ($event['mode'] == 'remove') + { + $this->functions->mchat_prune($event['user_ids']); + } + } } diff --git a/language/en/mchat.php b/language/en/mchat.php index a5b3b48..f5379c3 100644 --- a/language/en/mchat.php +++ b/language/en/mchat.php @@ -59,6 +59,7 @@ $lang = array_merge($lang, array( 'MCHAT_NOJAVASCRIPT' => 'Please enable JavaScript to use mChat.', 'MCHAT_NOMESSAGE' => 'No messages', 'MCHAT_NOMESSAGEINPUT' => 'You have not entered a message', + 'MCHAT_MESSAGE_DELETED' => 'This message has been deleted.', 'MCHAT_OK' => 'OK', 'MCHAT_PAUSE' => 'Paused', 'MCHAT_PERMISSIONS' => 'Change user’s permissions', @@ -83,6 +84,7 @@ $lang = array_merge($lang, array( 'MCHAT_CHARACTER_COUNT' => '{current} characters', 'MCHAT_CHARACTER_COUNT_LIMIT' => '{current} out of {max} characters', 'MCHAT_SESSION_ENDS_JS' => 'Chat session ends in {timeleft}', + 'MCHAT_MENTION' => ' @{username} ', // Custom translations for administrators 'MCHAT_RULES_MESSAGE' => '', diff --git a/language/en/mchat_acp.php b/language/en/mchat_acp.php index 9b1db64..f718135 100644 --- a/language/en/mchat_acp.php +++ b/language/en/mchat_acp.php @@ -62,7 +62,7 @@ $lang = array_merge($lang, array( 'MCHAT_ACP_GLOBALUSERSETTINGS_TITLE' => 'mChat Global user settings', 'MCHAT_VERSION' => 'Version', 'MCHAT_RULES' => 'Rules', - 'MCHAT_RULES_EXPLAIN' => 'Enter the rules of the forum here. HTML code is allowed. You are limited to 255 characters.
This message can be translated: edit the MCHAT_RULES_MESSAGE language key in /ext/dmzx/mchat/language/XX/mchat.php.', + 'MCHAT_RULES_EXPLAIN' => 'Enter the rules here. HTML code is allowed. You are limited to 255 characters.
This message can be translated: edit the MCHAT_RULES_MESSAGE language key in /ext/dmzx/mchat/language/XX/mchat.php.', 'MCHAT_CONFIG_SAVED' => 'mChat configuration has been updated', 'MCHAT_AVATARS' => 'Display avatars', 'MCHAT_AVATARS_EXPLAIN' => 'If set to yes, resized user avatars will be displayed', @@ -91,14 +91,17 @@ $lang = array_merge($lang, array( 'MCHAT_MESSAGE_NUM_INDEX_EXPLAIN' => 'You are limited from 5 to 50. Default is 10.', 'MCHAT_MESSAGE_NUM_ARCHIVE' => 'Number of messages to display on the archive page', 'MCHAT_MESSAGE_NUM_ARCHIVE_EXPLAIN' => 'The maximum number of messages to show per page on the archive page.
You are limited from 10 to 100. Default is 25.', + 'MCHAT_ARCHIVE_SORT' => 'Message sorting', + 'MCHAT_ARCHIVE_SORT_TOP_BOTTOM' => 'Always sort messages top to bottom', + 'MCHAT_ARCHIVE_SORT_BOTTOM_TOP' => 'Always sort messages bottom to top', + 'MCHAT_ARCHIVE_SORT_USER' => 'Sort messages depending on the user’s Location of new messages preference', 'MCHAT_FLOOD_TIME' => 'Flood time', 'MCHAT_FLOOD_TIME_EXPLAIN' => 'The number of seconds a user must wait before posting another message in the chat.
You are limited from 0 to 60 seconds. Default is 0. Set to 0 to disable.', 'MCHAT_EDIT_DELETE_LIMIT' => 'Time limit for editing and deleting messages', 'MCHAT_EDIT_DELETE_LIMIT_EXPLAIN' => 'Messages older than the specified number of seconds cannot be edited or deleted by the author any more.
Users who have edit/delete permission as well as moderator permission are exempt from this time limit.
Set to 0 to allow unlimited editing and deleting.', 'MCHAT_MAX_MESSAGE_LENGTH' => 'Maximum message length', 'MCHAT_MAX_MESSAGE_LENGTH_EXPLAIN' => 'Maximum number of characters allowed per message posted.
You are limited from 0 to 1000. Default is 500. Set to 0 to disable.', - 'MCHAT_CUSTOM_PAGE' => 'Enable custom Page', - 'MCHAT_CUSTOM_PAGE_EXPLAIN' => 'Allow the use of the custom page', + 'MCHAT_CUSTOM_PAGE' => 'Enable custom page', 'MCHAT_CUSTOM_HEIGHT' => 'Custom page height', 'MCHAT_CUSTOM_HEIGHT_EXPLAIN' => 'The height of the chat box in pixels on the custom page.
You are limited from 50 to 1000. Default is 350.', 'MCHAT_BBCODES_DISALLOWED' => 'Disallowed bbcodes', @@ -119,6 +122,10 @@ $lang = array_merge($lang, array( 'MCHAT_PURGE_CONFIRM' => 'Confirm deleting all messages', 'MCHAT_PURGED' => 'All mChat messages have been successfully deleted', + // '%1$s' contains 'Retain posts' and 'Delete posts' respectively + 'MCHAT_RETAIN_MESSAGES' => '%1$s and retain mChat messages', + 'MCHAT_DELETE_MESSAGES' => '%1$s and delete mChat messages', + // Error reporting 'TOO_LONG_MCHAT_BBCODE_DISALLOWED' => 'The disallowed bbcodes value is too long.', 'TOO_SMALL_MCHAT_CUSTOM_HEIGHT' => 'The custom height value is too small.', @@ -145,5 +152,5 @@ $lang = array_merge($lang, array( 'TOO_SMALL_MCHAT_WHOIS_REFRESH' => 'The whois refresh value is too small.', 'TOO_LARGE_MCHAT_WHOIS_REFRESH' => 'The whois refresh value is too large.', - 'MCHAT_30X_REMNANTS' => 'The installation as been aborted.
There are remnant modules from the mChat MOD for phpBB 3.0.x in the database. The mChat extension does not work correctly with these modules present.
You need to entirely uninstall the mChat MOD before being able to install the mChat extension. Specifically, the modules with the following IDs need to be deleted from the %1$smodules table: %2$s', + 'MCHAT_30X_REMNANTS' => 'The installation has been aborted.
There are remnant modules from the mChat MOD for phpBB 3.0.x in the database. The mChat extension does not work correctly with these modules present.
You need to entirely uninstall the mChat MOD before being able to install the mChat extension. Specifically, the modules with the following IDs need to be deleted from the %1$smodules table: %2$s', )); diff --git a/language/en/permissions_mchat.php b/language/en/permissions_mchat.php index 7b5767f..1834312 100644 --- a/language/en/permissions_mchat.php +++ b/language/en/permissions_mchat.php @@ -60,7 +60,7 @@ $lang = array_merge($lang, array( '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_PAUSE_ON_INPUT' => 'Can customise Pause on input', - 'ACL_U_MCHAT_POSTS' => 'Can customise Display new post', + 'ACL_U_MCHAT_POSTS' => 'Can customise Display new posts', 'ACL_U_MCHAT_RELATIVE_TIME' => 'Can customise Display relative time', 'ACL_U_MCHAT_SOUND' => 'Can customise Play sounds', 'ACL_U_MCHAT_WHOIS_INDEX' => 'Can customise Display who is chatting below the chat', diff --git a/migrations/mchat_2_0_0.php b/migrations/mchat_2_0_0.php index 353148e..7fccf2c 100644 --- a/migrations/mchat_2_0_0.php +++ b/migrations/mchat_2_0_0.php @@ -11,7 +11,7 @@ namespace dmzx\mchat\migrations; -use \phpbb\db\migration\migration; +use phpbb\db\migration\migration; class mchat_2_0_0 extends migration { diff --git a/migrations/mchat_2_0_0_rc3.php b/migrations/mchat_2_0_0_rc3.php index 57eb5b3..6903dcc 100644 --- a/migrations/mchat_2_0_0_rc3.php +++ b/migrations/mchat_2_0_0_rc3.php @@ -135,28 +135,39 @@ class mchat_2_0_0_rc3 extends migration array('module.add', array( 'acp', 'ACP_CAT_DOT_MODS', - 'ACP_CAT_MCHAT' + 'ACP_CAT_MCHAT', )), // Add ACP preferences module array('module.add', array( 'acp', 'ACP_CAT_MCHAT', - array('module_basename' => '\dmzx\mchat\acp\acp_mchat_module'), + array( + 'module_basename' => '\dmzx\mchat\acp\acp_mchat_module', + 'modes' => array( + 'globalsettings', + 'globalusersettings', + ), + ), )), // Add UCP category array('module.add', array( 'ucp', 0, - 'UCP_MCHAT_CONFIG' + 'UCP_MCHAT_CONFIG', )), // Add UCP preferences module array('module.add', array( 'ucp', 'UCP_MCHAT_CONFIG', - array('module_basename' => '\dmzx\mchat\ucp\ucp_mchat_module'), + array( + 'module_basename' => '\dmzx\mchat\ucp\ucp_mchat_module', + 'modes' => array( + 'configuration', + ), + ), )), ); } diff --git a/migrations/mchat_2_0_1.php b/migrations/mchat_2_0_1.php new file mode 100644 index 0000000..3f66b7a --- /dev/null +++ b/migrations/mchat_2_0_1.php @@ -0,0 +1,32 @@ + diff --git a/styles/Black_Star/template/event/dmzx_mchat_messages_define_icons.html b/styles/Black_Star/template/event/dmzx_mchat_messages_define_icons.html new file mode 100644 index 0000000..4be4b10 --- /dev/null +++ b/styles/Black_Star/template/event/dmzx_mchat_messages_define_icons.html @@ -0,0 +1 @@ + diff --git a/styles/Blue-Night/template/event/dmzx_mchat_messages_define_icons.html b/styles/Blue-Night/template/event/dmzx_mchat_messages_define_icons.html new file mode 100644 index 0000000..4be4b10 --- /dev/null +++ b/styles/Blue-Night/template/event/dmzx_mchat_messages_define_icons.html @@ -0,0 +1 @@ + diff --git a/styles/Brown/template/event/dmzx_mchat_messages_define_icons.html b/styles/Brown/template/event/dmzx_mchat_messages_define_icons.html new file mode 100644 index 0000000..4be4b10 --- /dev/null +++ b/styles/Brown/template/event/dmzx_mchat_messages_define_icons.html @@ -0,0 +1 @@ + diff --git a/styles/Cynthia/template/event/dmzx_mchat_messages_define_icons.html b/styles/Cynthia/template/event/dmzx_mchat_messages_define_icons.html new file mode 100644 index 0000000..4be4b10 --- /dev/null +++ b/styles/Cynthia/template/event/dmzx_mchat_messages_define_icons.html @@ -0,0 +1 @@ + diff --git a/styles/DVGFX/template/event/dmzx_mchat_messages_define_icons.html b/styles/DVGFX/template/event/dmzx_mchat_messages_define_icons.html new file mode 100644 index 0000000..4be4b10 --- /dev/null +++ b/styles/DVGFX/template/event/dmzx_mchat_messages_define_icons.html @@ -0,0 +1 @@ + diff --git a/styles/Modern-silver/template/event/overall_header_head_append.html b/styles/Modern-silver/template/event/overall_header_head_append.html new file mode 100644 index 0000000..22a6a0f --- /dev/null +++ b/styles/Modern-silver/template/event/overall_header_head_append.html @@ -0,0 +1,2 @@ + + diff --git a/styles/Modern-silver/theme/mchat_custom.css b/styles/Modern-silver/theme/mchat_custom.css new file mode 100644 index 0000000..318a316 --- /dev/null +++ b/styles/Modern-silver/theme/mchat_custom.css @@ -0,0 +1,11 @@ +/** + * + * @package phpBB Extension - mChat + * @copyright (c) 2016 kasimi - https://kasimi.net + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 + * + */ + +.mchat-wrapper { + height: 100%; +} diff --git a/styles/Rainbow-AOP/template/event/dmzx_mchat_messages_define_icons.html b/styles/Rainbow-AOP/template/event/dmzx_mchat_messages_define_icons.html new file mode 100644 index 0000000..4be4b10 --- /dev/null +++ b/styles/Rainbow-AOP/template/event/dmzx_mchat_messages_define_icons.html @@ -0,0 +1 @@ + diff --git a/styles/all/template/javascript/mchat.js b/styles/all/template/javascript/mchat.js index 160a8f2..e6bc0f5 100644 --- a/styles/all/template/javascript/mchat.js +++ b/styles/all/template/javascript/mchat.js @@ -4,7 +4,7 @@ * @copyright (c) 2009 Shapoval Andrey Vladimirovich (AllCity) ~ http://allcity.net.ru/ * @copyright (c) 2013 Rich McGirr (RMcGirr83) http://rmcgirr83.org * @copyright (c) 2015 dmzx - http://www.dmzx-web.net - * @copyright (c) 2016 kasimi - mail@kasimi.net + * @copyright (c) 2016 kasimi - https://kasimi.net * @license http://opensource.org/licenses/gpl-license.php GNU Public License * */ @@ -72,11 +72,35 @@ jQuery.fn.reverse = function(reverse) { return reverse === 'undefined' || reverse ? jQuery(this.toArray().reverse()) : this; }; +function StorageWrapper(storage, prefix) { + this.prefix = prefix; + try { + this.storage = window[storage]; + this.storage.setItem(prefix, prefix); + this.storage.removeItem(prefix); + } catch (e) { + this.storage = false; + } +} + +StorageWrapper.prototype.get = function(key) { + return this.storage && this.storage.getItem(this.prefix + key); +}; + +StorageWrapper.prototype.set = function(key, value) { + this.storage && this.storage.setItem(this.prefix + key, value); +}; + +StorageWrapper.prototype.remove = function(key) { + return this.storage && this.storage.removeItem(this.prefix + key); +}; + jQuery(function($) { "use strict"; $.extend(mChat, { + storage: new StorageWrapper('localStorage', mChat.cookie + 'mchat_'), ajaxRequest: function(mode, sendHiddenFields, data) { var deferred = $.Deferred(); if (sendHiddenFields) { @@ -88,73 +112,77 @@ jQuery(function($) { timeout: Math.min(mChat.refreshTime, 10000), type: 'POST', dataType: 'json', - data: data - }).done(function(json, status, xhr) { - var data = { + data: data, + additionalData: { mode: mode, - json: json, - status: status, - xhr: xhr, - handle: true - }; - $(mChat).trigger('mchat_ajax_done_before', [data]); - if (data.handle) { - if (json[mode]) { - deferred.resolve(data.json, data.status, data.xhr); - } else { - deferred.reject(data.xhr, data.status, mChat.lang.parserErr); + deferred: deferred + } + }).done(mChat.ajaxDone).fail(deferred.reject); + return deferred.promise().fail(mChat.ajaxFail); + }, + ajaxDone: function(json, status, xhr) { + var data = { + mode: this.additionalData.mode, + json: json, + status: status, + xhr: xhr, + handle: true + }; + $(mChat).trigger('mchat_ajax_done_before', [data]); + if (data.handle) { + if (json[this.additionalData.mode]) { + this.additionalData.deferred.resolve(data.json, data.status, data.xhr); + } else { + this.additionalData.deferred.reject(data.xhr, data.status, mChat.lang.parserErr); + } + } + }, + ajaxFail: function(xhr, textStatus, errorThrown) { + if (mChat.pageIsUnloading) { + return; + } + if (typeof console !== 'undefined' && console.log) { + console.log('AJAX error. status: ' + textStatus + ', message: ' + errorThrown + ' (' + xhr.responseText + ')'); + } + var data = { + mode: this.additionalData.mode, + xhr: xhr, + textStatus: textStatus, + errorThrown: errorThrown, + updateSession: function() { + if (this.xhr.status == 403) { + mChat.endSession(true); + } else if (this.xhr.status == 400) { + mChat.resetSession(); } } - }).fail(deferred.reject); - return deferred.promise().fail(function(xhr, textStatus, errorThrown) { - if (mChat.pageIsUnloading) { - return; - } - if (typeof console !== 'undefined' && console.log) { - console.log('AJAX error. status: ' + textStatus + ', message: ' + errorThrown + ' (' + xhr.responseText + ')'); - } - var data = { - mode: mode, - xhr: xhr, - textStatus: textStatus, - errorThrown: errorThrown, - updateSession: function() { - if (this.xhr.status == 403) { - mChat.endSession(true); - } else if (this.xhr.status == 400) { - mChat.resetSession(); - } - } - }; - $(mChat).trigger('mchat_ajax_fail_before', [data]); - mChat.sound('error'); - mChat.cached('status-load', 'status-ok', 'status-paused').hide(); - mChat.cached('status-error').show(); - var responseText; - try { - responseText = data.xhr.responseJSON.message || data.errorThrown; - } catch (e) { - responseText = data.errorThrown; - } - if (responseText && responseText !== 'timeout') { - phpbb.alert(mChat.lang.err, responseText); - } - data.updateSession(); - }); + }; + $(mChat).trigger('mchat_ajax_fail_before', [data]); + mChat.sound('error'); + mChat.cached('status-load', 'status-ok', 'status-paused').hide(); + mChat.cached('status-error').show(); + var responseText; + try { + responseText = data.xhr.responseJSON.message || data.errorThrown; + } catch (e) { + responseText = data.errorThrown; + } + if (responseText && responseText !== 'timeout') { + phpbb.alert(mChat.lang.err, responseText); + } + data.updateSession(); }, sound: function(file) { - if (!mChat.pageIsUnloading && !localStorage.getItem(mChat.cookie + 'mchat_no_sound')) { - var data = { - audio: mChat.cached('sound-' + file).get(0), - file: file, - play: true - }; - $(mChat).trigger('mchat_sound_before', [data]); - if (data.play && data.audio.duration) { - data.audio.pause(); - data.audio.currentTime = 0; - data.audio.play(); - } + var data = { + audio: mChat.cached('sound-' + file).get(0), + file: file, + play: !mChat.pageIsUnloading && mChat.cached('user-sound').is(':checked') + }; + $(mChat).trigger('mchat_sound_before', [data]); + if (data.play && data.audio && data.audio.duration) { + data.audio.pause(); + data.audio.currentTime = 0; + data.audio.play(); } }, titleAlert: function() { @@ -171,9 +199,9 @@ jQuery(function($) { var $elem = mChat.cached(name); $elem.stop().slideToggle(200, function() { if ($elem.is(':visible')) { - localStorage.setItem(mChat.cookie + 'mchat_show_' + name, 'yes'); + mChat.storage.set('show_' + name, 'yes'); } else { - localStorage.removeItem(mChat.cookie + 'mchat_show_' + name); + mChat.storage.remove('show_' + name); } }); }, @@ -214,15 +242,15 @@ jQuery(function($) { mChat.pauseSession(); var originalInputValue = mChat.cached('input').val(); var inputValue = originalInputValue; - var color = localStorage.getItem(mChat.cookie + 'mchat_color'); + var color = mChat.storage.get('color'); if (color && inputValue.indexOf('[color=') === -1) { inputValue = '[color=#' + color + '] ' + inputValue + ' [/color]'; } - mChat.cached('input').val('').focus(); + mChat.cached('input').val('').trigger('update.autogrow').focus(); mChat.refresh(inputValue).done(function() { mChat.resetSession(); }).fail(function() { - mChat.cached('input').val(originalInputValue); + mChat.cached('input').val(originalInputValue).trigger('update.autogrow'); }).always(function() { mChat.cached('add').prop('disabled', false); setTimeout(function() { @@ -320,7 +348,7 @@ jQuery(function($) { handleWhoisResponse: function(json) { var $whois = $(json.whois); var $userlist = $whois.find('#mchat-userlist'); - if (localStorage.getItem(mChat.cookie + 'mchat_show_userlist')) { + if (mChat.storage.get('show_userlist')) { $userlist.show(); } mChat.cached('whois').replaceWith($whois); @@ -484,8 +512,9 @@ jQuery(function($) { var selector = '.mchat-time[data-mchat-relative-update]'; clearInterval($message.find(selector).addBack(selector).data('mchat-relative-interval')); }, + timeLeftRegex: /\d\d:(\d\d:\d\d)/, timeLeft: function(sessionTime) { - return (new Date(sessionTime * 1000)).toUTCString().match(/(\d\d:\d\d:\d\d)/)[0]; + return (new Date(sessionTime * 1000)).toUTCString().match(mChat.timeLeftRegex)[mChat.timeout >= 3600000 ? 0 : 1]; }, countDown: function() { mChat.sessionTime -= 1; @@ -562,25 +591,30 @@ jQuery(function($) { mention: function() { var $container = $(this).closest('.mchat-message'); var username = $container.data('mchat-username'); - var usercolor = $container.data('mchat-usercolor'); - if (usercolor) { - username = '[b][color=' + usercolor + ']' + username + '[/color][/b]'; - } else if (mChat.allowBBCodes) { - username = '[b]' + username + '[/b]'; + if (mChat.allowBBCodes) { + var usercolor = $container.data('mchat-usercolor'); + var profileUrl = $container.find(".mchat-message-header a[class^='username']").prop('href'); + if (usercolor) { + username = '[url=' + profileUrl + '][b][color=' + usercolor + ']' + username + '[/color][/b][/url]'; + } else { + username = '[url=' + profileUrl + '][b]' + username + '[/b][/url]'; + } } - insert_text('@ ' + username + ', '); + insert_text(mChat.lang.mention.format({username: username})); }, quote: function() { var $container = $(this).closest('.mchat-message'); var username = $container.data('mchat-username'); var quote = $container.data('mchat-message'); insert_text('[quote="' + username + '"] ' + quote + '[/quote]'); + mChat.cached('input').trigger('update.autogrow'); }, like: function() { var $container = $(this).closest('.mchat-message'); var username = $container.data('mchat-username'); var quote = $container.data('mchat-message'); insert_text('[i]' + mChat.lang.likes + '[/i][quote="' + username + '"] ' + quote + '[/quote]'); + mChat.cached('input').trigger('update.autogrow'); }, ip: function() { popup(this.href, 750, 500); @@ -618,13 +652,13 @@ jQuery(function($) { }, 1); } - mChat.cached('user-sound').prop('checked', mChat.playSound && !localStorage.getItem(mChat.cookie + 'mchat_no_sound')).change(function() { + mChat.cached('user-sound').prop('checked', mChat.playSound && !mChat.storage.get('no_sound')).change(function() { if (this.checked) { - localStorage.removeItem(mChat.cookie + 'mchat_no_sound'); + mChat.storage.remove('no_sound'); } else { - localStorage.setItem(mChat.cookie + 'mchat_no_sound', 'yes'); + mChat.storage.set('no_sound', 'yes'); } - }).change(); + }); $.each(mChat.removeBBCodes.split('|'), function(i, bbcode) { var bbCodeClass = '.bbcode-' + bbcode.replaceMany({ @@ -639,7 +673,7 @@ jQuery(function($) { $('#bbpalette,#abbc3_bbpalette,#color_wheel').prop('onclick', null).attr('data-mchat-toggle', 'colour'); $.each(['userlist', 'smilies', 'bbcodes', 'colour'], function(i, elem) { - if (localStorage.getItem(mChat.cookie + 'mchat_show_' + elem)) { + if (mChat.storage.get('show_' + elem)) { mChat.cached(elem).toggle(); } }); @@ -693,17 +727,17 @@ jQuery(function($) { e.stopImmediatePropagation(); var $this = $(this); var newColor = $this.data('color'); - if (localStorage.getItem(mChat.cookie + 'mchat_color') === newColor) { - localStorage.removeItem(mChat.cookie + 'mchat_color'); + if (mChat.storage.get('color') === newColor) { + mChat.storage.remove('color'); } else { - localStorage.setItem(mChat.cookie + 'mchat_color', newColor); + mChat.storage.set('color', newColor); mChat.cached('colour').find('.colour-palette a').removeClass('remember-color'); } $this.toggleClass('remember-color'); } }); - var color = localStorage.getItem(mChat.cookie + 'mchat_color'); + var color = mChat.storage.get('color'); if (color) { mChat.cached('colour').find('.colour-palette a[data-color="' + color + '"]').addClass('remember-color'); } diff --git a/styles/all/template/mchat_script_data.html b/styles/all/template/mchat_script_data.html index 9767783..76208a2 100644 --- a/styles/all/template/mchat_script_data.html +++ b/styles/all/template/mchat_script_data.html @@ -53,6 +53,7 @@ delConfirm : '{LA_MCHAT_DELCONFIRM}', sessOut : '{LA_MCHAT_SESSION_OUT}', sessEnds : '{LA_MCHAT_SESSION_ENDS_JS}', + mention : '{LA_MCHAT_MENTION}', refreshYes : '{A_MCHAT_REFRESH_YES}', refreshNo : '{LA_MCHAT_REFRESH_NO}', charCount : '{LA_MCHAT_CHARACTER_COUNT_LIMIT}{LA_MCHAT_CHARACTER_COUNT}', diff --git a/styles/blue_lagoon/template/event/dmzx_mchat_messages_define_icons.html b/styles/blue_lagoon/template/event/dmzx_mchat_messages_define_icons.html new file mode 100644 index 0000000..4be4b10 --- /dev/null +++ b/styles/blue_lagoon/template/event/dmzx_mchat_messages_define_icons.html @@ -0,0 +1 @@ + diff --git a/styles/bubbleogd/template/event/dmzx_mchat_messages_define_icons.html b/styles/bubbleogd/template/event/dmzx_mchat_messages_define_icons.html new file mode 100644 index 0000000..4be4b10 --- /dev/null +++ b/styles/bubbleogd/template/event/dmzx_mchat_messages_define_icons.html @@ -0,0 +1 @@ + diff --git a/styles/canvas/theme/mchat_custom.css b/styles/canvas/theme/mchat_custom.css index ce48dc0..0da9002 100644 --- a/styles/canvas/theme/mchat_custom.css +++ b/styles/canvas/theme/mchat_custom.css @@ -30,3 +30,11 @@ ul.mchat-buttons > li { .mchat-footer label { padding-left: 3px; } + +@media only screen and (max-width: 700px), only screen and (max-device-width: 700px) { + + #mchat-body { + overflow: auto; + } + +} diff --git a/styles/conan/template/event/dmzx_mchat_messages_define_icons.html b/styles/conan/template/event/dmzx_mchat_messages_define_icons.html new file mode 100644 index 0000000..4be4b10 --- /dev/null +++ b/styles/conan/template/event/dmzx_mchat_messages_define_icons.html @@ -0,0 +1 @@ + diff --git a/styles/dark_vision/template/event/dmzx_mchat_messages_define_icons.html b/styles/dark_vision/template/event/dmzx_mchat_messages_define_icons.html new file mode 100644 index 0000000..4be4b10 --- /dev/null +++ b/styles/dark_vision/template/event/dmzx_mchat_messages_define_icons.html @@ -0,0 +1 @@ + diff --git a/styles/digi/template/event/dmzx_mchat_messages_define_icons.html b/styles/digi/template/event/dmzx_mchat_messages_define_icons.html new file mode 100644 index 0000000..4be4b10 --- /dev/null +++ b/styles/digi/template/event/dmzx_mchat_messages_define_icons.html @@ -0,0 +1 @@ + diff --git a/styles/honour/template/event/dmzx_mchat_messages_define_icons.html b/styles/honour/template/event/dmzx_mchat_messages_define_icons.html new file mode 100644 index 0000000..4be4b10 --- /dev/null +++ b/styles/honour/template/event/dmzx_mchat_messages_define_icons.html @@ -0,0 +1 @@ + diff --git a/styles/lucid_lime/template/event/dmzx_mchat_messages_define_icons.html b/styles/lucid_lime/template/event/dmzx_mchat_messages_define_icons.html new file mode 100644 index 0000000..4be4b10 --- /dev/null +++ b/styles/lucid_lime/template/event/dmzx_mchat_messages_define_icons.html @@ -0,0 +1 @@ + diff --git a/styles/ne-blackgreen/template/event/dmzx_mchat_messages_define_icons.html b/styles/ne-blackgreen/template/event/dmzx_mchat_messages_define_icons.html new file mode 100644 index 0000000..4be4b10 --- /dev/null +++ b/styles/ne-blackgreen/template/event/dmzx_mchat_messages_define_icons.html @@ -0,0 +1 @@ + diff --git a/styles/ongraydark/template/event/dmzx_mchat_messages_define_icons.html b/styles/ongraydark/template/event/dmzx_mchat_messages_define_icons.html new file mode 100644 index 0000000..4be4b10 --- /dev/null +++ b/styles/ongraydark/template/event/dmzx_mchat_messages_define_icons.html @@ -0,0 +1 @@ + diff --git a/styles/ongraydark_footballact/template/event/dmzx_mchat_messages_define_icons.html b/styles/ongraydark_footballact/template/event/dmzx_mchat_messages_define_icons.html new file mode 100644 index 0000000..4be4b10 --- /dev/null +++ b/styles/ongraydark_footballact/template/event/dmzx_mchat_messages_define_icons.html @@ -0,0 +1 @@ + diff --git a/styles/pbwow3/theme/mchat_custom.css b/styles/pbwow3/theme/mchat_custom.css index 036210f..12060ff 100644 --- a/styles/pbwow3/theme/mchat_custom.css +++ b/styles/pbwow3/theme/mchat_custom.css @@ -7,6 +7,18 @@ * */ +.forabg.mchat-wrapper { + padding: 0; +} + +.mchat-wrapper .collapse-box h2 a { + color: #888; +} + +.mchat-wrapper .collapse-box h2 a:before { + content: '' !important; +} + .icon-mchat > a:before { content: '\f086'; font-family: 'FontAwesome'; diff --git a/styles/proDVGFX/template/event/dmzx_mchat_messages_define_icons.html b/styles/proDVGFX/template/event/dmzx_mchat_messages_define_icons.html new file mode 100644 index 0000000..4be4b10 --- /dev/null +++ b/styles/proDVGFX/template/event/dmzx_mchat_messages_define_icons.html @@ -0,0 +1 @@ + diff --git a/styles/prosilver/template/event/overall_header_stylesheets_after.html b/styles/prosilver/template/event/overall_header_stylesheets_after.html index dcbe4c7..fc6000b 100644 --- a/styles/prosilver/template/event/overall_header_stylesheets_after.html +++ b/styles/prosilver/template/event/overall_header_stylesheets_after.html @@ -1,4 +1,4 @@ - +