mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
FIX: Quoting a quote preserves the original post information (#8746)
Let's say post #2 quotes post number #1. If a user decides to quote the quote in post #2, it should keep the information of post #1 ("user_1, post: 1, topic: X"), instead of replacing with current post info ("user_2, post: 2, topic: X").
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { scheduleOnce } from "@ember/runloop";
|
||||
import Component from "@ember/component";
|
||||
import discourseDebounce from "discourse/lib/debounce";
|
||||
import { selectedText } from "discourse/lib/utilities";
|
||||
import { selectedText, selectedElement } from "discourse/lib/utilities";
|
||||
|
||||
export default Component.extend({
|
||||
classNames: ["quote-button"],
|
||||
@@ -48,8 +48,28 @@ export default Component.extend({
|
||||
}
|
||||
}
|
||||
|
||||
let opts;
|
||||
for (
|
||||
let element = selectedElement();
|
||||
element && element.tagName !== "ARTICLE";
|
||||
element = element.parentElement
|
||||
) {
|
||||
if (element.tagName === "ASIDE" && element.classList.contains("quote")) {
|
||||
opts = {
|
||||
username:
|
||||
element.dataset.username ||
|
||||
element
|
||||
.querySelector(".title")
|
||||
.textContent.trim()
|
||||
.replace(/:$/, ""),
|
||||
post: element.dataset.post,
|
||||
topic: element.dataset.topic
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const _selectedText = selectedText();
|
||||
quoteState.selected(postId, _selectedText);
|
||||
quoteState.selected(postId, _selectedText, opts);
|
||||
this.set("visible", quoteState.buffer.length > 0);
|
||||
|
||||
// avoid hard loops in quote selection unconditionally
|
||||
@@ -165,8 +185,8 @@ export default Component.extend({
|
||||
},
|
||||
|
||||
click() {
|
||||
const { postId, buffer } = this.quoteState;
|
||||
this.attrs.selectText(postId, buffer).then(() => this._hideButton());
|
||||
const { postId, buffer, opts } = this.quoteState;
|
||||
this.attrs.selectText(postId, buffer, opts).then(() => this._hideButton());
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -266,7 +266,7 @@ export default Controller.extend(bufferedProperty("model"), {
|
||||
this.send("showFeatureTopic");
|
||||
},
|
||||
|
||||
selectText(postId, buffer) {
|
||||
selectText(postId, buffer, opts) {
|
||||
const loadedPost = this.get("model.postStream").findLoadedPost(postId);
|
||||
const promise = loadedPost
|
||||
? Promise.resolve(loadedPost)
|
||||
@@ -275,7 +275,7 @@ export default Controller.extend(bufferedProperty("model"), {
|
||||
return promise.then(post => {
|
||||
const composer = this.composer;
|
||||
const viewOpen = composer.get("model.viewOpen");
|
||||
const quotedText = Quote.build(post, buffer);
|
||||
const quotedText = Quote.build(post, buffer, opts);
|
||||
|
||||
// If we can't create a post, delegate to reply as new topic
|
||||
if (!viewOpen && !this.get("model.details.can_create_post")) {
|
||||
|
||||
@@ -3,13 +3,15 @@ export default class QuoteState {
|
||||
this.clear();
|
||||
}
|
||||
|
||||
selected(postId, buffer) {
|
||||
selected(postId, buffer, opts) {
|
||||
this.postId = postId;
|
||||
this.buffer = buffer;
|
||||
this.opts = opts;
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.buffer = "";
|
||||
this.postId = null;
|
||||
this.opts = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ export default {
|
||||
}
|
||||
|
||||
if (!contents) contents = "";
|
||||
if (!opts) opts = {};
|
||||
|
||||
const sansQuotes = contents.replace(this.REGEXP, "").trim();
|
||||
if (sansQuotes.length === 0) {
|
||||
@@ -26,9 +27,9 @@ export default {
|
||||
stripped.replace(/\W/g, "") === contents.replace(/\W/g, "");
|
||||
|
||||
const params = [
|
||||
post.get("username"),
|
||||
`post:${post.get("post_number")}`,
|
||||
`topic:${post.get("topic_id")}`
|
||||
opts.username || post.username,
|
||||
`post:${opts.post || post.post_number}`,
|
||||
`topic:${opts.topic || post.topic_id}`
|
||||
];
|
||||
|
||||
opts = opts || {};
|
||||
|
||||
@@ -143,6 +143,13 @@ export function selectedText() {
|
||||
return toMarkdown($div.html());
|
||||
}
|
||||
|
||||
export function selectedElement() {
|
||||
const selection = window.getSelection();
|
||||
if (selection.rangeCount > 0) {
|
||||
return selection.getRangeAt(0).startContainer.parentElement;
|
||||
}
|
||||
}
|
||||
|
||||
// Determine the row and col of the caret in an element
|
||||
export function caretRowCol(el) {
|
||||
var cp = caretPosition(el);
|
||||
|
||||
@@ -73,6 +73,10 @@ const rule = {
|
||||
token.attrs.push(["class", "quote no-group"]);
|
||||
}
|
||||
|
||||
if (username) {
|
||||
token.attrs.push(["data-username", username]);
|
||||
}
|
||||
|
||||
if (postNumber) {
|
||||
token.attrs.push(["data-post", postNumber]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user