diff --git a/assets/javascripts/discourse/components/solved-accepted-answer.gjs b/assets/javascripts/discourse/components/solved-accepted-answer.gjs
new file mode 100644
index 0000000..5d53a80
--- /dev/null
+++ b/assets/javascripts/discourse/components/solved-accepted-answer.gjs
@@ -0,0 +1,96 @@
+import Component from "@glimmer/component";
+import { service } from "@ember/service";
+import { htmlSafe } from "@ember/template";
+import concatClass from "discourse/helpers/concat-class";
+import { iconHTML } from "discourse/lib/icon-library";
+import { formatUsername } from "discourse/lib/utilities";
+import { i18n } from "discourse-i18n";
+
+export default class SolvedAcceptedAnswer extends Component {
+ @service siteSettings;
+ @service store;
+
+ get topic() {
+ return this.args.post.topic;
+ }
+
+ get hasExcerpt() {
+ return !!this.topic.accepted_answer.excerpt;
+ }
+
+ get htmlAccepter() {
+ const username = this.topic.accepted_answer.accepter_username;
+ const name = this.topic.accepted_answer.accepter_name;
+
+ if (!this.siteSettings.show_who_marked_solved) {
+ return;
+ }
+
+ const formattedUsername =
+ this.siteSettings.display_name_on_posts && name
+ ? name
+ : formatUsername(username);
+
+ return htmlSafe(
+ i18n("solved.marked_solved_by", {
+ username: formattedUsername,
+ username_lower: username.toLowerCase(),
+ })
+ );
+ }
+
+ get htmlExcerpt() {
+ return htmlSafe(this.topic.accepted_answer.excerpt);
+ }
+
+ get htmlSolvedBy() {
+ const username = this.topic.accepted_answer.username;
+ const name = this.topic.accepted_answer.name;
+ const postNumber = this.topic.accepted_answer.post_number;
+
+ if (!username || !postNumber) {
+ return;
+ }
+
+ const displayedUser =
+ this.siteSettings.display_name_on_posts && name
+ ? name
+ : formatUsername(username);
+
+ const data = {
+ icon: iconHTML("square-check", { class: "accepted" }),
+ username_lower: username.toLowerCase(),
+ username: displayedUser,
+ post_path: `${this.topic.url}/${postNumber}`,
+ post_number: postNumber,
+ user_path: this.store.createRecord("user", { username }).path,
+ };
+
+ return htmlSafe(i18n("solved.accepted_html", data));
+ }
+
+
+
+
+}
diff --git a/assets/javascripts/discourse/initializers/extend-for-solved-button.gjs b/assets/javascripts/discourse/initializers/extend-for-solved-button.gjs
new file mode 100644
index 0000000..207d73f
--- /dev/null
+++ b/assets/javascripts/discourse/initializers/extend-for-solved-button.gjs
@@ -0,0 +1,136 @@
+import Component from "@glimmer/component";
+import { computed } from "@ember/object";
+import { withSilencedDeprecations } from "discourse/lib/deprecated";
+import { iconHTML } from "discourse/lib/icon-library";
+import { withPluginApi } from "discourse/lib/plugin-api";
+import { formatUsername } from "discourse/lib/utilities";
+import Topic from "discourse/models/topic";
+import User from "discourse/models/user";
+import PostCooked from "discourse/widgets/post-cooked";
+import RenderGlimmer from "discourse/widgets/render-glimmer";
+import { i18n } from "discourse-i18n";
+import SolvedAcceptAnswerButton from "../components/solved-accept-answer-button";
+import SolvedAcceptedAnswer from "../components/solved-accepted-answer";
+import SolvedUnacceptAnswerButton from "../components/solved-unaccept-answer-button";
+
+function initializeWithApi(api) {
+ customizePost(api);
+ customizePostMenu(api);
+
+ if (api.addDiscoveryQueryParam) {
+ api.addDiscoveryQueryParam("solved", { replace: true, refreshModel: true });
+ }
+}
+
+function customizePost(api) {
+ api.addTrackedPostProperties(
+ "can_accept_answer",
+ "can_unaccept_answer",
+ "accepted_answer",
+ "topic_accepted_answer"
+ );
+
+ api.renderAfterWrapperOutlet(
+ "post-content-cooked-html",
+ class extends Component {
+ static shouldRender(args) {
+ return args.post.post_number === 1 && args.post.topic.accepted_answer;
+ }
+
+
+ }
+ );
+
+ withSilencedDeprecations("discourse.post-stream-widget-overrides", () =>
+ customizeWidgetPost(api)
+ );
+}
+
+function customizeWidgetPost(api) {
+ api.decorateWidget("post-contents:after-cooked", (helper) => {
+ let post = helper.getModel();
+
+ if (helper.attrs.post_number === 1 && post?.topic?.accepted_answer) {
+ return new RenderGlimmer(
+ helper.widget,
+ "div",
+ ,
+ { post }
+ );
+ }
+ });
+}
+
+function customizePostMenu(api) {
+ api.registerValueTransformer(
+ "post-menu-buttons",
+ ({
+ value: dag,
+ context: {
+ post,
+ firstButtonKey,
+ secondLastHiddenButtonKey,
+ lastHiddenButtonKey,
+ },
+ }) => {
+ let solvedButton;
+
+ if (post.can_accept_answer) {
+ solvedButton = SolvedAcceptAnswerButton;
+ } else if (post.accepted_answer) {
+ solvedButton = SolvedUnacceptAnswerButton;
+ }
+
+ solvedButton &&
+ dag.add(
+ "solved",
+ solvedButton,
+ post.topic_accepted_answer && !post.accepted_answer
+ ? {
+ before: lastHiddenButtonKey,
+ after: secondLastHiddenButtonKey,
+ }
+ : {
+ before: [
+ "assign", // button added by the assign plugin
+ firstButtonKey,
+ ],
+ }
+ );
+ }
+ );
+}
+
+export default {
+ name: "extend-for-solved-button",
+ initialize() {
+ withPluginApi("1.34.0", initializeWithApi);
+
+ withPluginApi("0.8.10", (api) => {
+ api.replaceIcon(
+ "notification.solved.accepted_notification",
+ "square-check"
+ );
+ });
+
+ withPluginApi("0.11.0", (api) => {
+ api.addAdvancedSearchOptions({
+ statusOptions: [
+ {
+ name: i18n("search.advanced.statuses.solved"),
+ value: "solved",
+ },
+ {
+ name: i18n("search.advanced.statuses.unsolved"),
+ value: "unsolved",
+ },
+ ],
+ });
+ });
+
+ withPluginApi("0.11.7", (api) => {
+ api.addSearchSuggestion("status:solved");
+ api.addSearchSuggestion("status:unsolved");
+ });
+ },
+};
diff --git a/assets/javascripts/discourse/initializers/extend-for-solved-button.js b/assets/javascripts/discourse/initializers/extend-for-solved-button.js
deleted file mode 100644
index fff26d8..0000000
--- a/assets/javascripts/discourse/initializers/extend-for-solved-button.js
+++ /dev/null
@@ -1,186 +0,0 @@
-import { computed } from "@ember/object";
-import { iconHTML } from "discourse/lib/icon-library";
-import { withPluginApi } from "discourse/lib/plugin-api";
-import { formatUsername } from "discourse/lib/utilities";
-import Topic from "discourse/models/topic";
-import User from "discourse/models/user";
-import PostCooked from "discourse/widgets/post-cooked";
-import { i18n } from "discourse-i18n";
-import SolvedAcceptAnswerButton, {
- acceptAnswer,
-} from "../components/solved-accept-answer-button";
-import SolvedUnacceptAnswerButton, {
- unacceptAnswer,
-} from "../components/solved-unaccept-answer-button";
-
-function initializeWithApi(api) {
- customizePostMenu(api);
-
- api.includePostAttributes(
- "can_accept_answer",
- "can_unaccept_answer",
- "accepted_answer",
- "topic_accepted_answer"
- );
-
- if (api.addDiscoveryQueryParam) {
- api.addDiscoveryQueryParam("solved", { replace: true, refreshModel: true });
- }
-
- api.decorateWidget("post-contents:after-cooked", (dec) => {
- if (dec.attrs.post_number === 1) {
- const postModel = dec.getModel();
- if (postModel) {
- const topic = postModel.topic;
- if (topic.accepted_answer) {
- const hasExcerpt = !!topic.accepted_answer.excerpt;
- const excerpt = hasExcerpt
- ? `
${topic.accepted_answer.excerpt}
`
- : "";
- const solvedQuote = `
-