PowerGlove (OP)
|
|
June 10, 2024, 04:02:29 AM Merited by theymos (25), LoyceV (24), ABCbits (17), vapourminer (10), Mitchell (10), hosseinimr93 (10), NotATether (9), hugeblack (8), bitmover (8), dkbit98 (7), tranthidung (3), ibminer (3), suchmoon (2), Lafu (2), Halab (2), mole0815 (2), DdmrDdmr (2), hd49728 (2), joker_josue (2), un_rank (2), yahoo62278 (1), davis196 (1), ChiBitCTy (1), TheBeardedBaby (1), Mahdirakib (1), Rikafip (1), shahzadafzal (1), Charles-Tim (1), SquirrelJulietGarden (1), KingsDen (1), _BlackStar (1), Plaguedeath (1), Rizzrack (1) |
|
I've been working on this one for a while now. It was most recently raised by garlonicon, but I'm guessing that this issue has been discussed a great many times over the years. This is something that's handled neatly by the BPIP extension, but there are a lot of people (me included) that prefer not to install extensions, so something built-in would be nice... I was very tempted to take the same (clever) approach that the BPIP extension took, and build things around the endpoint that SMF's insert-quote feature uses ( /index.php?action=quotefast), but, after weighing the pros and cons, I ended up settling on an approach that doesn't introduce new UI elements, feels more SMFish (to me), and avoids depending on JavaScript. Basically, the approach I took began with a thought that I have to imagine more than a few people have had: Why not just make the existing "quote" button visible in locked threads? If you go poking around in SMF and make that button appear even in locked threads, you'll quickly discover that it doesn't actually work: So, the next thing to do is to find a way to (safely) bypass that error: I did that by selectively tacking a ;peek onto the end of the quote button's URL, and then allowing such requests to avoid that lock-check. This turns out to be safe (in terms of not allowing everyone to actually post in locked threads) because (conveniently) there's another lock-check deeper in the code. Mission accomplished then, right? Well, kind of, but, if the concept is that you're only "peeking" at some post's BBCode, then the "Post reply" page that you land on could definitely use some adjustments: (*) There's no point in showing the post/preview buttons (in this context), because they'll only error-out if you try to use them (courtesy of that remaining, deeper lock-check). (*) There's no point in showing things like the old-topic warning, because, as before, you can't actually post anything. (*) The page title ("Post reply") is now misleading. (*) The "Topic Summary" at the bottom of the page is unnecessary. So, I took care of all of that by hiding the things that aren't relevant, and changing the page title to "Inspect message": To help distinguish this different "kind" of quote button (compared to the kind that shows up in not-locked threads), I made the button render at 50% grayscale and added a tooltip to it: Here are the diffs for @theymos: --- baseline/Themes/default/Display.template.php 2010-10-22 01:38:35.000000000 +0000 +++ modified/Themes/default/Display.template.php 2024-06-09 23:32:16.000000000 +0000 @@ -382,30 +382,35 @@ // If this is the first post, (#0) just say when it was posted - otherwise give the reply #. echo ' <div class="smalltext">« <b>', !empty($message['counter']) ? $txt[146] . ' #' . $message['counter'] : '', ' ', $txt[30], ':</b> ', $message['time'], ' »</div></td> <td align="', !$context['right_to_left'] ? 'right' : 'left', '" valign="bottom" height="20" style="font-size: smaller;">'; // Can they reply? Have they turned on quick reply? if ($context['can_reply'] && !empty($options['display_quick_reply'])) echo ' <a href="', $scripturl, '?action=post;quote=', $message['id'], ';topic=', $context['current_topic'], '.', $context['start'], ';num_replies=', $context['num_replies'], ';sesc=', $context['session_id'], '" onclick="doQuote(', $message['id'], ', \'', $context['session_id'], '\'); return false;">', $reply_button, '</a>'; // So... quick reply is off, but they *can* reply? elseif ($context['can_reply']) echo ' <a href="', $scripturl, '?action=post;quote=', $message['id'], ';topic=', $context['current_topic'], '.', $context['start'], ';num_replies=', $context['num_replies'], ';sesc=', $context['session_id'], '">', $reply_button, '</a>'; + // So... they *can't* reply, but if they're logged-in then we should emit a button that at least lets them see/copy the BBCode if needed. + elseif (!$context['user']['is_guest']) + echo ' + <a href="', $scripturl, '?action=post;quote=', $message['id'], ';topic=', $context['current_topic'], '.', $context['start'], ';num_replies=', $context['num_replies'], ';sesc=', $context['session_id'], ';peek" style="filter: grayscale(0.5);" title="Inspect message">', $reply_button, '</a>'; + // Can the user modify the contents of this post? if ($message['can_modify']) echo ' <a href="', $scripturl, '?action=post;msg=', $message['id'], ';topic=', $context['current_topic'], '.', $context['start'], ';sesc=', $context['session_id'], '">', $modify_button, '</a>'; // How about... even... remove it entirely?! if ($message['can_remove']) echo ' <a href="', $scripturl, '?action=deletemsg;topic=', $context['current_topic'], '.', $context['start'], ';msg=', $message['id'], ';sesc=', $context['session_id'], '" onclick="return confirm(\'', $txt[154], '?\');">', $remove_button, '</a>'; // What about splitting it off the rest of the topic? if ($context['can_split']) echo ' <a href="', $scripturl, '?action=splittopics;topic=', $context['current_topic'], '.0;at=', $message['id'], '">', $split_button, '</a>';
--- baseline/Sources/Post.php 2011-02-07 16:45:09.000000000 +0000 +++ modified/Sources/Post.php 2024-06-09 23:43:55.000000000 +0000 @@ -183,32 +183,36 @@ $context['can_sticky'] = allowedTo('make_sticky') && !empty($modSettings['enableStickyTopics']); $context['notify'] = !empty($context['notify']); $context['sticky'] = !empty($_REQUEST['sticky']); } // !!! These won't work if you're posting an event! $context['can_notify'] = allowedTo('mark_any_notify'); $context['can_move'] = allowedTo('move_any'); $context['can_announce'] = allowedTo('announce_topic'); $context['locked'] = !empty($locked) || !empty($_REQUEST['lock']); // An array to hold all the attachments for this topic. $context['current_attachments'] = array(); + // Is this a "peek" request? (That is, one that's intended to only see/copy the BBCode of a post.) + $context['only_peeking'] = !isset($_GET['msg']) && !empty($_GET['quote']) && isset($_GET['peek']); + // Don't allow a post if it's locked and you aren't all powerful. - if ($locked && !allowedTo('moderate_board')) + // But make an exception for "peek" requests (and rely on the similar check in Post2() to pick up the slack). + if ($locked && !allowedTo('moderate_board') && !$context['only_peeking']) fatal_lang_error(90, false); // Check the users permissions - is the user allowed to add or post a poll? if (isset($_REQUEST['poll']) && $modSettings['pollMode'] == '1') { // New topic, new poll. if (empty($topic)) isAllowedTo('poll_post'); // This is an old topic - but it is yours! Can you add to it? elseif ($ID_MEMBER == $ID_MEMBER_POSTER && !allowedTo('poll_add_any')) isAllowedTo('poll_add_own'); // If you're not the owner, can you add to any poll? else isAllowedTo('poll_add_any'); @@ -947,31 +951,31 @@ $context['error_type'] = 'minor'; } // What are you doing? Posting a poll, modifying, previewing, new post, or reply... if (isset($_REQUEST['poll'])) $context['page_title'] = $txt['smf20']; elseif ($context['make_event']) $context['page_title'] = $context['event']['id'] == -1 ? $txt['calendar23'] : $txt['calendar20']; elseif (isset($_REQUEST['msg'])) $context['page_title'] = $txt[66]; elseif (isset($_REQUEST['subject'], $context['preview_subject'])) $context['page_title'] = $txt[507] . ' - ' . strip_tags($context['preview_subject']); elseif (empty($topic)) $context['page_title'] = $txt[33]; else - $context['page_title'] = $txt[25]; + $context['page_title'] = $context['only_peeking'] ? 'Inspect message' : $txt[25]; // Build the link tree. if (empty($topic)) $context['linktree'][] = array( 'name' => '<i>' . $txt[33] . '</i>' ); else $context['linktree'][] = array( 'url' => $scripturl . '?topic=' . $topic . '.' . $_REQUEST['start'], 'name' => $form_subject, 'extra_before' => '<span' . ($settings['linktree_inline'] ? ' class="smalltext"' : '') . '><b class="nav">' . $context['page_title'] . ' ( </b></span>', 'extra_after' => '<span' . ($settings['linktree_inline'] ? ' class="smalltext"' : '') . '><b class="nav"> )</b></span>' ); // If they've unchecked an attachment, they may still want to attach that many more files, but don't allow more than num_allowed_attachments. @@ -2027,30 +2031,33 @@ // Get the topic for display purposes. function getTopic() { global $topic, $db_prefix, $modSettings, $context; // Calculate the amount of new replies. $newReplies = empty($_REQUEST['num_replies']) || $context['num_replies'] <= $_REQUEST['num_replies'] ? 0 : $context['num_replies'] - $_REQUEST['num_replies']; if (isset($_REQUEST['xml'])) $limit = " LIMIT " . (empty($newReplies) ? '0' : $newReplies); else $limit = empty($modSettings['topicSummaryPosts']) ? '' : ' LIMIT ' . (int) $modSettings['topicSummaryPosts']; + // Previous posts won't be displayed by the template when $context['only_peeking'] is true, so save some cycles... + $limit = $context['only_peeking'] ? ' LIMIT 0' : $limit; + // If you're modifying, get only those posts before the current one. (otherwise get all.) $request = db_query(" SELECT IFNULL(mem.realName, m.posterName) AS posterName, m.posterTime, m.body, m.smileysEnabled, m.ID_MSG FROM {$db_prefix}messages AS m LEFT JOIN {$db_prefix}members AS mem ON (mem.ID_MEMBER = m.ID_MEMBER) WHERE m.ID_TOPIC = $topic" . (isset($_REQUEST['msg']) ? " AND m.ID_MSG < " . (int) $_REQUEST['msg'] : '') . " ORDER BY m.ID_MSG DESC$limit", __FILE__, __LINE__); $context['previous_posts'] = array(); while ($row = mysql_fetch_assoc($request)) { // Censor, BBC, ... censorText($row['body']); $row['body'] = parse_bbc($row['body'], $row['smileysEnabled'], $row['ID_MSG']);
--- baseline/Themes/default/Post.template.php 2008-04-30 18:30:34.000000000 +0000 +++ modified/Themes/default/Post.template.php 2024-06-09 23:53:13.000000000 +0000 @@ -278,45 +278,49 @@ echo ' <input type="hidden" name="eventid" value="', $context['event']['id'], '" />'; // Start the main table. echo ' <table border="0" width="100%" align="center" cellspacing="1" cellpadding="3" class="bordercolor"> <tr class="titlebg"> <td>', $context['page_title'], '</td> </tr> <tr> <td class="windowbg">', isset($context['current_topic']) ? ' <input type="hidden" name="topic" value="' . $context['current_topic'] . '" />' : '', ' <table border="0" cellpadding="3" width="100%">'; // If an error occurred, explain what happened. - echo ' + // Skip this if we're in the context of a "peek" request. (These errors/warnings aren't relevant in this context: the user can't post anything, that's why they're "peeking" in the first place.) + if (!$context['only_peeking']) + echo ' <tr', empty($context['post_error']['messages']) ? ' style="display: none"' : '', ' id="errors"> <td></td> <td align="left"> <div style="padding: 0px; font-weight: bold;', empty($context['error_type']) || $context['error_type'] != 'serious' ? ' display: none;' : '', '" id="error_serious"> ', $txt['error_while_submitting'], ' </div> <div style="color: red; margin: 1ex 0 2ex 3ex;" id="error_list"> ', empty($context['post_error']['messages']) ? '' : implode('<br />', $context['post_error']['messages']), ' </div> </td> </tr>'; // If it's locked, show a message to warn the replyer. - echo ' + // Skip this if we're in the context of a "peek" request. (This warning *seems* germane in this context, but it's not: the whole point of "peek" requests is to allow messages to be inspected from inside locked topics, so warning the user about something that they already know, and against an action that they're unable to take, is pretty silly.) + if (!$context['only_peeking']) + echo ' <tr', $context['locked'] ? '' : ' style="display: none"', ' id="lock_warning"> <td></td> <td align="left"> ', $txt['smf287'], ' </td> </tr>'; // Guests have to put in their name and email... if (isset($context['name']) && isset($context['email'])) { echo ' <tr> <td align="right" style="font-weight: bold;', isset($context['post_error']['long_name']) || isset($context['post_error']['no_name']) || isset($context['post_error']['bad_name']) ? 'color: red;' : '', '" id="caption_guestname"> ', $txt[68], ': </td> @@ -495,30 +499,43 @@ </tr> <tr> <td align="right"></td> <td class="smalltext"> <input type="radio" id="poll_hide" name="poll_hide" value="0"', $context['poll_options']['hide'] == 0 ? ' checked="checked"' : '', ' class="check" /> ', $txt['poll_options2'], '<br /> <input type="radio" id="poll_hide" name="poll_hide" value="1"', $context['poll_options']['hide'] == 1 ? ' checked="checked"' : '', ' class="check" /> ', $txt['poll_options3'], '<br /> <input type="radio" id="poll_hide" name="poll_hide" value="2"', $context['poll_options']['hide'] == 2 ? ' checked="checked"' : '', empty($context['poll_options']['expire']) ? ' disabled="disabled"' : '', ' class="check" /> ', $txt['poll_options4'], '<br /> <br /> </td> </tr>'; } // The below function prints the BBC, smileys and the message itself out. theme_postbox($context['message']); + // If we're in the context of a "peek" request, avoid emitting what follows past this point... just close off the markup and return. + if ($context['only_peeking']) + { + echo ' + </table> + </td> + </tr> + </table> + </form>'; + + return; + } + // If this message has been edited in the past - display when it was. if (isset($context['last_modified'])) echo ' <tr> <td valign="top" align="right"> <b>', $txt[211], ':</b> </td> <td> ', $context['last_modified'], ' </td> </tr>'; // If the admin has enabled the hiding of the additional options - show a link and image for it. if (!empty($settings['additional_options_collapsable'])) echo '
(There are one or two other bits of polish/functionality that I could have pursued, like preventing the template from emitting a few unnecessary background things, and adding the ability to "peek" directly from someone's post/topic history, but, the patch as it stands is kind of in a "sweet spot" complexity-wise, so I'm reluctant to push it further. Also, it's difficult to get theymos to come down from the mountain, so to speak, and when he does, I don't want him put off by a sprawling patch that touches too many files and makes too many changes.)
|