diff --git a/assets/javascripts/discourse/initializers/url-to-article.js b/assets/javascripts/discourse/initializers/url-to-article.js
index 34b710c..8344e23 100644
--- a/assets/javascripts/discourse/initializers/url-to-article.js
+++ b/assets/javascripts/discourse/initializers/url-to-article.js
@@ -41,6 +41,7 @@ export default apiInitializer("1.8.0", (api) => {
const composer = this.get("composer");
if (!composer) return;
composer.removeObserver("model.title", this, "_titleObserver");
+ this._restoreNativeTitleLookup();
},
_onTitleChanged() {
@@ -48,6 +49,7 @@ export default apiInitializer("1.8.0", (api) => {
const match = title.trim().match(URL_REGEX);
if (!match) {
+ this._restoreNativeTitleLookup();
this._hideArticleBar();
return;
}
@@ -57,6 +59,9 @@ export default apiInitializer("1.8.0", (api) => {
if (this._lastDetectedUrl === url) return; // Same URL — no-op
this._lastDetectedUrl = url;
+ // Suppress Discourse's native title lookup so it doesn't race our bar
+ this._suppressNativeTitleLookup();
+
const autoPopulate = api.container
.lookup("site-settings:main")
.url_to_article_auto_populate;
@@ -68,6 +73,32 @@ export default apiInitializer("1.8.0", (api) => {
}
},
+ // ---- Native title-lookup suppression ------------------------------
+
+ _suppressNativeTitleLookup() {
+ const model = this.get("composer.model");
+ if (!model || this._originalTitleLookup) return;
+ if (typeof model._titleLookup === "function") {
+ this._originalTitleLookup = model._titleLookup.bind(model);
+ model._titleLookup = () => {};
+ }
+ },
+
+ _restoreNativeTitleLookup() {
+ const model = this.get("composer.model");
+ if (!model || !this._originalTitleLookup) return;
+ model._titleLookup = this._originalTitleLookup;
+ this._originalTitleLookup = null;
+ },
+
+ _triggerNativeTitleLookup() {
+ this._restoreNativeTitleLookup();
+ const model = this.get("composer.model");
+ if (model && typeof model._titleLookup === "function") {
+ model._titleLookup();
+ }
+ },
+
// ---- Bar UI -------------------------------------------------------
_showArticleBar(url) {
@@ -82,6 +113,9 @@ export default apiInitializer("1.8.0", (api) => {
+
`;
@@ -89,8 +123,15 @@ export default apiInitializer("1.8.0", (api) => {
this._fetchAndPopulate(url);
});
+ bar.querySelector(".url-to-article-onebox-btn").addEventListener("click", () => {
+ this._hideArticleBar();
+ this._lastDetectedUrl = null;
+ this._triggerNativeTitleLookup();
+ });
+
bar.querySelector(".url-to-article-dismiss").addEventListener("click", () => {
this._hideArticleBar();
+ this._restoreNativeTitleLookup();
this._lastDetectedUrl = null; // Allow re-detection if title changes
});
@@ -141,6 +182,7 @@ export default apiInitializer("1.8.0", (api) => {
}
this._populateComposer(data);
+ this._restoreNativeTitleLookup();
this._setStatus(I18n.t("url_to_article.success"), "success");
// Auto-hide bar after 3 seconds on success
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index b4fb857..153e8a9 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -2,6 +2,7 @@ en:
url_to_article:
bar_label: "URL detected — import as article?"
fetch_button: "Import Article"
+ onebox_button: "Use Onebox"
retry_button: "Retry"
fetching: "Fetching…"
dismiss: "Dismiss"
diff --git a/plugin.rb b/plugin.rb
index b11f95f..37462f3 100644
--- a/plugin.rb
+++ b/plugin.rb
@@ -3,8 +3,8 @@
# name: discourse-url-to-article
# about: Scrapes a URL pasted into the topic title and populates the composer body with the article content
# version: 0.1.0
-# authors: Your Name
-# url: https://github.com/yourname/discourse-url-to-article
+# authors: Robert Johnson
+# url: https://code.draft13.com/robert/discourse-url-to-article
enabled_site_setting :url_to_article_enabled