DEV: Convert share-topic modal to new component-based API (#22154)
This commit is contained in:
parent
5134b28d83
commit
c6cd3af5b5
|
@ -2,7 +2,13 @@
|
||||||
<ComposerMessage
|
<ComposerMessage
|
||||||
@message={{message}}
|
@message={{message}}
|
||||||
@closeMessage={{action "closeMessage"}}
|
@closeMessage={{action "closeMessage"}}
|
||||||
@shareModal={{action "shareModal"}}
|
@shareModal={{fn (mut this.showShareModal) true}}
|
||||||
@switchPM={{action "switchPM"}}
|
@switchPM={{action "switchPM"}}
|
||||||
/>
|
/>
|
||||||
|
{{#if this.showShareModal}}
|
||||||
|
<Modal::ShareTopic
|
||||||
|
@closeModal={{fn (mut this.showShareModal) false}}
|
||||||
|
@model={{this.shareModalData}}
|
||||||
|
/>
|
||||||
|
{{/if}}
|
||||||
{{/each}}
|
{{/each}}
|
|
@ -4,14 +4,18 @@ import EmberObject, { action } from "@ember/object";
|
||||||
import I18n from "I18n";
|
import I18n from "I18n";
|
||||||
import LinkLookup from "discourse/lib/link-lookup";
|
import LinkLookup from "discourse/lib/link-lookup";
|
||||||
import { not } from "@ember/object/computed";
|
import { not } from "@ember/object/computed";
|
||||||
import showModal from "discourse/lib/show-modal";
|
|
||||||
import { ajax } from "discourse/lib/ajax";
|
import { ajax } from "discourse/lib/ajax";
|
||||||
|
import { inject as service } from "@ember/service";
|
||||||
|
import { tracked } from "@glimmer/tracking";
|
||||||
|
|
||||||
let _messagesCache = {};
|
let _messagesCache = {};
|
||||||
let _recipient_names = [];
|
let _recipient_names = [];
|
||||||
|
|
||||||
@classNameBindings(":composer-popup-container", "hidden")
|
@classNameBindings(":composer-popup-container", "hidden")
|
||||||
export default class ComposerMessages extends Component {
|
export default class ComposerMessages extends Component {
|
||||||
|
@service modal;
|
||||||
|
@tracked showShareModal;
|
||||||
|
|
||||||
checkedMessages = false;
|
checkedMessages = false;
|
||||||
messages = null;
|
messages = null;
|
||||||
messagesByTemplate = null;
|
messagesByTemplate = null;
|
||||||
|
@ -309,19 +313,17 @@ export default class ComposerMessages extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
get shareModalData() {
|
||||||
shareModal() {
|
|
||||||
const { topic } = this.composer;
|
const { topic } = this.composer;
|
||||||
const controller = showModal("share-topic", { model: topic.category });
|
return {
|
||||||
|
topic,
|
||||||
controller.setProperties({
|
category: topic.category,
|
||||||
allowInvites:
|
allowInvites:
|
||||||
topic.details.can_invite_to &&
|
topic.details.can_invite_to &&
|
||||||
!topic.archived &&
|
!topic.archived &&
|
||||||
!topic.closed &&
|
!topic.closed &&
|
||||||
!topic.deleted,
|
!topic.deleted,
|
||||||
topic,
|
};
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
<DModalBody
|
<DModal
|
||||||
@rawTitle={{if
|
@title={{if
|
||||||
this.post
|
this.post
|
||||||
(i18n "post.share.title" post_number=this.post.post_number)
|
(i18n "post.share.title" post_number=this.post.post_number)
|
||||||
(i18n "topic.share.title")
|
(i18n "topic.share.title")
|
||||||
}}
|
}}
|
||||||
@rawSubtitle={{if this.post this.displayDate}}
|
@subtitle={{if this.post this.displayDate}}
|
||||||
|
@closeModal={{@closeModal}}
|
||||||
|
@flash={{this.flash}}
|
||||||
|
@flashType={{this.flashType}}
|
||||||
|
class="share-topic-modal"
|
||||||
>
|
>
|
||||||
<form>
|
<form>
|
||||||
<div class="input-group invite-link">
|
<div class="input-group invite-link">
|
||||||
|
@ -74,4 +78,4 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</DModalBody>
|
</DModal>
|
|
@ -0,0 +1,121 @@
|
||||||
|
import Component from "@ember/component";
|
||||||
|
import { action } from "@ember/object";
|
||||||
|
import { getAbsoluteURL } from "discourse-common/lib/get-url";
|
||||||
|
import discourseComputed, {
|
||||||
|
afterRender,
|
||||||
|
} from "discourse-common/utils/decorators";
|
||||||
|
import { readOnly } from "@ember/object/computed";
|
||||||
|
import { longDateNoYear } from "discourse/lib/formatter";
|
||||||
|
import Sharing from "discourse/lib/sharing";
|
||||||
|
import showModal from "discourse/lib/show-modal";
|
||||||
|
import { bufferedProperty } from "discourse/mixins/buffered-content";
|
||||||
|
import I18n from "I18n";
|
||||||
|
import Category from "discourse/models/category";
|
||||||
|
import { getOwner } from "discourse-common/lib/get-owner";
|
||||||
|
|
||||||
|
const ShareTopicModal = Component.extend(bufferedProperty("invite"), {
|
||||||
|
topic: readOnly("model.topic"),
|
||||||
|
post: readOnly("model.post"),
|
||||||
|
category: readOnly("model.category"),
|
||||||
|
allowInvites: readOnly("model.allowInvites"),
|
||||||
|
|
||||||
|
didInsertElement() {
|
||||||
|
this._showRestrictedGroupWarning();
|
||||||
|
this._selectUrl();
|
||||||
|
this._super();
|
||||||
|
},
|
||||||
|
|
||||||
|
@afterRender
|
||||||
|
_showRestrictedGroupWarning() {
|
||||||
|
if (!this.category) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Category.fetchVisibleGroups(this.category.id).then((result) => {
|
||||||
|
if (result.groups.length > 0) {
|
||||||
|
this.setProperties({
|
||||||
|
flash: I18n.t("topic.share.restricted_groups", {
|
||||||
|
count: result.groups.length,
|
||||||
|
groupNames: result.groups.join(", "),
|
||||||
|
}),
|
||||||
|
flashType: "warning",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
@afterRender
|
||||||
|
_selectUrl() {
|
||||||
|
const input = document.querySelector("input.invite-link");
|
||||||
|
if (input && !this.site.mobileView) {
|
||||||
|
// if the input is auto-focused on mobile, iOS requires two taps of the copy button
|
||||||
|
input.setSelectionRange(0, this.url.length);
|
||||||
|
input.focus();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
@discourseComputed("post.shareUrl", "topic.shareUrl")
|
||||||
|
url(postUrl, topicUrl) {
|
||||||
|
if (postUrl) {
|
||||||
|
return getAbsoluteURL(postUrl);
|
||||||
|
} else if (topicUrl) {
|
||||||
|
return getAbsoluteURL(topicUrl);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
@discourseComputed("post.created_at", "post.wiki", "post.last_wiki_edit")
|
||||||
|
displayDate(createdAt, wiki, lastWikiEdit) {
|
||||||
|
const date = wiki && lastWikiEdit ? lastWikiEdit : createdAt;
|
||||||
|
return longDateNoYear(new Date(date));
|
||||||
|
},
|
||||||
|
|
||||||
|
@discourseComputed(
|
||||||
|
"topic.{isPrivateMessage,invisible,category.read_restricted}"
|
||||||
|
)
|
||||||
|
sources(topic) {
|
||||||
|
const privateContext =
|
||||||
|
this.siteSettings.login_required ||
|
||||||
|
topic?.isPrivateMessage ||
|
||||||
|
topic?.invisible ||
|
||||||
|
topic?.category?.read_restricted;
|
||||||
|
|
||||||
|
return Sharing.activeSources(this.siteSettings.share_links, privateContext);
|
||||||
|
},
|
||||||
|
|
||||||
|
@action
|
||||||
|
share(source) {
|
||||||
|
Sharing.shareSource(source, {
|
||||||
|
title: this.topic.title,
|
||||||
|
url: this.url,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
@action
|
||||||
|
inviteUsers() {
|
||||||
|
const controller = showModal("create-invite");
|
||||||
|
controller.setProperties({
|
||||||
|
inviteToTopic: true,
|
||||||
|
topics: [this.topic],
|
||||||
|
});
|
||||||
|
controller.buffered.setProperties({
|
||||||
|
topicId: this.topic.id,
|
||||||
|
topicTitle: this.topic.title,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
@action
|
||||||
|
replyAsNewTopic() {
|
||||||
|
const postStream = this.topic.postStream;
|
||||||
|
const postId = this.post?.id || postStream.findPostIdForPostNumber(1);
|
||||||
|
const post = postStream.findLoadedPost(postId);
|
||||||
|
const topicController = getOwner(this).lookup("controller:topic");
|
||||||
|
topicController.actions.replyAsNewTopic.call(topicController, post);
|
||||||
|
this.closeModal();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
ShareTopicModal.reopenClass({
|
||||||
|
modalClass: "share-topic-modal",
|
||||||
|
});
|
||||||
|
|
||||||
|
export default ShareTopicModal;
|
|
@ -1,126 +0,0 @@
|
||||||
import Controller from "@ember/controller";
|
|
||||||
import { action } from "@ember/object";
|
|
||||||
import { getAbsoluteURL } from "discourse-common/lib/get-url";
|
|
||||||
import discourseComputed, {
|
|
||||||
afterRender,
|
|
||||||
} from "discourse-common/utils/decorators";
|
|
||||||
import { longDateNoYear } from "discourse/lib/formatter";
|
|
||||||
import Sharing from "discourse/lib/sharing";
|
|
||||||
import showModal from "discourse/lib/show-modal";
|
|
||||||
import { bufferedProperty } from "discourse/mixins/buffered-content";
|
|
||||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
|
||||||
import I18n from "I18n";
|
|
||||||
import Category from "discourse/models/category";
|
|
||||||
import { getOwner } from "discourse-common/lib/get-owner";
|
|
||||||
|
|
||||||
export default Controller.extend(
|
|
||||||
ModalFunctionality,
|
|
||||||
bufferedProperty("invite"),
|
|
||||||
{
|
|
||||||
topic: null,
|
|
||||||
post: null,
|
|
||||||
allowInvites: false,
|
|
||||||
|
|
||||||
onShow() {
|
|
||||||
this.setProperties({
|
|
||||||
topic: null,
|
|
||||||
post: null,
|
|
||||||
allowInvites: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
this._showRestrictedGroupWarning();
|
|
||||||
this._selectUrl();
|
|
||||||
},
|
|
||||||
|
|
||||||
@afterRender
|
|
||||||
_showRestrictedGroupWarning() {
|
|
||||||
if (!this.model) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Category.fetchVisibleGroups(this.model.id).then((result) => {
|
|
||||||
if (result.groups.length > 0) {
|
|
||||||
this.flash(
|
|
||||||
I18n.t("topic.share.restricted_groups", {
|
|
||||||
count: result.groups.length,
|
|
||||||
groupNames: result.groups.join(", "),
|
|
||||||
}),
|
|
||||||
"warning"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
@afterRender
|
|
||||||
_selectUrl() {
|
|
||||||
const input = document.querySelector("input.invite-link");
|
|
||||||
if (input && !this.site.mobileView) {
|
|
||||||
// if the input is auto-focused on mobile, iOS requires two taps of the copy button
|
|
||||||
input.setSelectionRange(0, this.url.length);
|
|
||||||
input.focus();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
@discourseComputed("post.shareUrl", "topic.shareUrl")
|
|
||||||
url(postUrl, topicUrl) {
|
|
||||||
if (postUrl) {
|
|
||||||
return getAbsoluteURL(postUrl);
|
|
||||||
} else if (topicUrl) {
|
|
||||||
return getAbsoluteURL(topicUrl);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
@discourseComputed("post.created_at", "post.wiki", "post.last_wiki_edit")
|
|
||||||
displayDate(createdAt, wiki, lastWikiEdit) {
|
|
||||||
const date = wiki && lastWikiEdit ? lastWikiEdit : createdAt;
|
|
||||||
return longDateNoYear(new Date(date));
|
|
||||||
},
|
|
||||||
|
|
||||||
@discourseComputed(
|
|
||||||
"topic.{isPrivateMessage,invisible,category.read_restricted}"
|
|
||||||
)
|
|
||||||
sources(topic) {
|
|
||||||
const privateContext =
|
|
||||||
this.siteSettings.login_required ||
|
|
||||||
topic?.isPrivateMessage ||
|
|
||||||
topic?.invisible ||
|
|
||||||
topic?.category?.read_restricted;
|
|
||||||
|
|
||||||
return Sharing.activeSources(
|
|
||||||
this.siteSettings.share_links,
|
|
||||||
privateContext
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
@action
|
|
||||||
share(source) {
|
|
||||||
Sharing.shareSource(source, {
|
|
||||||
title: this.topic.title,
|
|
||||||
url: this.url,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
@action
|
|
||||||
inviteUsers() {
|
|
||||||
const controller = showModal("create-invite");
|
|
||||||
controller.setProperties({
|
|
||||||
inviteToTopic: true,
|
|
||||||
topics: [this.topic],
|
|
||||||
});
|
|
||||||
controller.buffered.setProperties({
|
|
||||||
topicId: this.topic.id,
|
|
||||||
topicTitle: this.topic.title,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
@action
|
|
||||||
replyAsNewTopic() {
|
|
||||||
const postStream = this.topic.postStream;
|
|
||||||
const postId = this.post?.id || postStream.findPostIdForPostNumber(1);
|
|
||||||
const post = postStream.findLoadedPost(postId);
|
|
||||||
const topicController = getOwner(this).lookup("controller:topic");
|
|
||||||
topicController.actions.replyAsNewTopic.call(topicController, post);
|
|
||||||
this.send("closeModal");
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
|
@ -4,7 +4,7 @@ import {
|
||||||
WITH_REMINDER_ICON,
|
WITH_REMINDER_ICON,
|
||||||
} from "discourse/models/bookmark";
|
} from "discourse/models/bookmark";
|
||||||
import { registerTopicFooterButton } from "discourse/lib/register-topic-footer-button";
|
import { registerTopicFooterButton } from "discourse/lib/register-topic-footer-button";
|
||||||
import showModal from "discourse/lib/show-modal";
|
import ShareTopicModal from "discourse/components/modal/share-topic";
|
||||||
|
|
||||||
const SHARE_PRIORITY = 1000;
|
const SHARE_PRIORITY = 1000;
|
||||||
const BOOKMARK_PRIORITY = 900;
|
const BOOKMARK_PRIORITY = 900;
|
||||||
|
@ -13,7 +13,7 @@ const FLAG_PRIORITY = 700;
|
||||||
const DEFER_PRIORITY = 500;
|
const DEFER_PRIORITY = 500;
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
initialize() {
|
initialize(owner) {
|
||||||
registerTopicFooterButton({
|
registerTopicFooterButton({
|
||||||
id: "share-and-invite",
|
id: "share-and-invite",
|
||||||
icon: "d-topic-share",
|
icon: "d-topic-share",
|
||||||
|
@ -25,15 +25,15 @@ export default {
|
||||||
},
|
},
|
||||||
title: "topic.share.help",
|
title: "topic.share.help",
|
||||||
action() {
|
action() {
|
||||||
const controller = showModal("share-topic", {
|
owner.lookup("service:modal").show(ShareTopicModal, {
|
||||||
model: this.topic.category,
|
model: {
|
||||||
});
|
category: this.topic.category,
|
||||||
controller.setProperties({
|
topic: this.topic,
|
||||||
allowInvites:
|
allowInvites:
|
||||||
this.currentUser.can_invite_to_forum &&
|
this.currentUser.can_invite_to_forum &&
|
||||||
this.canInviteTo &&
|
this.canInviteTo &&
|
||||||
!this.inviteDisabled,
|
!this.inviteDisabled,
|
||||||
topic: this.topic,
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
dropdown() {
|
dropdown() {
|
||||||
|
|
|
@ -23,9 +23,10 @@ import {
|
||||||
import { relativeAgeMediumSpan } from "discourse/lib/formatter";
|
import { relativeAgeMediumSpan } from "discourse/lib/formatter";
|
||||||
import { transformBasicPost } from "discourse/lib/transform-post";
|
import { transformBasicPost } from "discourse/lib/transform-post";
|
||||||
import autoGroupFlairForUser from "discourse/lib/avatar-flair";
|
import autoGroupFlairForUser from "discourse/lib/avatar-flair";
|
||||||
import showModal from "discourse/lib/show-modal";
|
|
||||||
import { nativeShare } from "discourse/lib/pwa-utils";
|
import { nativeShare } from "discourse/lib/pwa-utils";
|
||||||
import { hideUserTip } from "discourse/lib/user-tips";
|
import { hideUserTip } from "discourse/lib/user-tips";
|
||||||
|
import ShareTopicModal from "discourse/components/modal/share-topic";
|
||||||
|
import { getOwner } from "@ember/application";
|
||||||
|
|
||||||
function transformWithCallbacks(post) {
|
function transformWithCallbacks(post) {
|
||||||
let transformed = transformBasicPost(post);
|
let transformed = transformBasicPost(post);
|
||||||
|
@ -410,8 +411,11 @@ createWidget("post-date", {
|
||||||
showShareModal() {
|
showShareModal() {
|
||||||
const post = this.findAncestorModel();
|
const post = this.findAncestorModel();
|
||||||
const topic = post.topic;
|
const topic = post.topic;
|
||||||
const controller = showModal("share-topic", { model: topic.category });
|
getOwner(this)
|
||||||
controller.setProperties({ topic, post });
|
.lookup("service:modal")
|
||||||
|
.show(ShareTopicModal, {
|
||||||
|
model: { category: topic.category, topic, post },
|
||||||
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -627,8 +631,11 @@ createWidget("post-contents", {
|
||||||
const post = this.findAncestorModel();
|
const post = this.findAncestorModel();
|
||||||
nativeShare(this.capabilities, { url: post.shareUrl }).catch(() => {
|
nativeShare(this.capabilities, { url: post.shareUrl }).catch(() => {
|
||||||
const topic = post.topic;
|
const topic = post.topic;
|
||||||
const controller = showModal("share-topic", { model: topic.category });
|
getOwner(this)
|
||||||
controller.setProperties({ topic, post });
|
.lookup("service:modal")
|
||||||
|
.show(ShareTopicModal, {
|
||||||
|
model: { category: topic.category, topic, post },
|
||||||
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue