FEATURE: Replace share post popup with share modal (#15875)

This uniformizes the topic share modal and the post link popup. It also
introduces a new feature which can notify the user of a post.
This commit is contained in:
Bianca Nenciu 2022-02-21 22:14:28 +02:00 committed by GitHub
parent 5c9ca07119
commit ae1d2d957f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 62 additions and 25 deletions

View File

@ -16,19 +16,31 @@ export default Controller.extend(
bufferedProperty("invite"), bufferedProperty("invite"),
{ {
topic: null, topic: null,
post: null,
allowInvites: false,
showNotifyUsers: false,
restrictedGroups: null, restrictedGroups: null,
onShow() { onShow() {
this.set("showNotifyUsers", false); this.setProperties({
topic: null,
post: null,
allowInvites: false,
showNotifyUsers: false,
});
if (this.model && this.model.read_restricted) { if (this.model && this.model.read_restricted) {
this.restrictedGroupWarning(); this.restrictedGroupWarning();
} }
}, },
@discourseComputed("topic.shareUrl") @discourseComputed("post.shareUrl", "topic.shareUrl")
topicUrl(url) { url(postUrl, topicUrl) {
return url ? getAbsoluteURL(url) : null; if (postUrl) {
return getAbsoluteURL(postUrl);
} else if (topicUrl) {
return getAbsoluteURL(topicUrl);
}
}, },
@discourseComputed( @discourseComputed(
@ -57,7 +69,7 @@ export default Controller.extend(
this.set("showNotifyUsers", false); this.set("showNotifyUsers", false);
Sharing.shareSource(source, { Sharing.shareSource(source, {
title: this.topic.title, title: this.topic.title,
url: this.topicUrl, url: this.url,
}); });
}, },
@ -81,7 +93,10 @@ export default Controller.extend(
ajax(`/t/${this.topic.id}/invite-notify`, { ajax(`/t/${this.topic.id}/invite-notify`, {
type: "POST", type: "POST",
data: { usernames: this.users }, data: {
usernames: this.users,
post_number: this.post ? this.post.post_number : undefined,
},
}) })
.then(() => { .then(() => {
this.setProperties({ showNotifyUsers: false }); this.setProperties({ showNotifyUsers: false });

View File

@ -18,7 +18,7 @@ export default {
priority: SHARE_PRIORITY, priority: SHARE_PRIORITY,
label() { label() {
if (!this.get("topic.isPrivateMessage") || this.site.mobileView) { if (!this.get("topic.isPrivateMessage") || this.site.mobileView) {
return "topic.share.title"; return "footer_nav.share";
} }
}, },
title: "topic.share.help", title: "topic.share.help",

View File

@ -1,12 +1,14 @@
{{#d-modal-body title="topic.share.title"}} {{#d-modal-body rawTitle=(if post (i18n "post.share.title" post_number=post.post_number) (i18n "topic.share.title"))}}
<form> <form>
<div class="input-group invite-link"> <div class="input-group invite-link">
<label for="invite-link">{{i18n "topic.share.instructions"}}</label> <label for="invite-link">
{{if post (i18n "post.share.instructions" post_number=post.post_number) (i18n "topic.share.instructions")}}
</label>
<div class="link-share-container"> <div class="link-share-container">
{{input {{input
name="invite-link" name="invite-link"
class="invite-link" class="invite-link"
value=topicUrl value=url
readonly=true readonly=true
}} }}
{{copy-button selector="input.invite-link"}} {{copy-button selector="input.invite-link"}}

View File

@ -414,6 +414,5 @@
editPost=(action "editPost") editPost=(action "editPost")
topic=model topic=model
composerVisible=composer.visible composerVisible=composer.visible
}} }}
{{/discourse-topic}} {{/discourse-topic}}

View File

@ -271,16 +271,12 @@ registerButton("replies", (attrs, state, siteSettings) => {
}; };
}); });
registerButton("share", (attrs) => { registerButton("share", () => {
return { return {
action: "share", action: "share",
className: "share", className: "share",
title: "post.controls.share", title: "post.controls.share",
icon: "d-post-share", icon: "d-post-share",
data: {
"share-url": attrs.shareUrl,
"post-number": attrs.post_number,
},
}; };
}); });

View File

@ -21,6 +21,8 @@ import { prioritizeNameInUx } from "discourse/lib/settings";
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";
function transformWithCallbacks(post) { function transformWithCallbacks(post) {
let transformed = transformBasicPost(post); let transformed = transformBasicPost(post);
@ -537,6 +539,15 @@ createWidget("post-contents", {
const post = this.findAncestorModel(); const post = this.findAncestorModel();
return post.expand().then(() => (this.state.expandedFirstPost = true)); return post.expand().then(() => (this.state.expandedFirstPost = true));
}, },
share() {
const post = this.findAncestorModel();
nativeShare(this.capabilities, { url: post.shareUrl }).catch(() => {
const topic = post.topic;
const controller = showModal("share-topic", { model: topic.category });
controller.setProperties({ topic, post });
});
},
}); });
createWidget("post-notice", { createWidget("post-notice", {

View File

@ -229,10 +229,7 @@ discourseModule("Integration | Component | Widget | post", function (hooks) {
this.set("args", { shareUrl: "http://share-me.example.com" }); this.set("args", { shareUrl: "http://share-me.example.com" });
}, },
test(assert) { test(assert) {
assert.ok( assert.ok(exists(".actions button.share"), "it renders a share button");
exists(".actions button[data-share-url]"),
"it renders a share button"
);
}, },
}); });

View File

@ -688,6 +688,10 @@ class TopicsController < ApplicationController
users = User.where(username_lower: usernames.map(&:downcase)) users = User.where(username_lower: usernames.map(&:downcase))
raise Discourse::InvalidParameters.new(:usernames) if usernames.size != users.size raise Discourse::InvalidParameters.new(:usernames) if usernames.size != users.size
post_number = 1
post_number = params[:post_number].to_i if params[:post_number].present?
raise Discourse::InvalidParameters.new(:post_number) if post_number < 1 || post_number > topic.highest_post_number
topic.rate_limit_topic_invitation(current_user) topic.rate_limit_topic_invitation(current_user)
users.find_each do |user| users.find_each do |user|
@ -700,11 +704,16 @@ class TopicsController < ApplicationController
last_notification = user.notifications last_notification = user.notifications
.where(notification_type: Notification.types[:invited_to_topic]) .where(notification_type: Notification.types[:invited_to_topic])
.where(topic_id: topic.id) .where(topic_id: topic.id)
.where(post_number: 1) .where(post_number: post_number)
.where('created_at > ?', 1.hour.ago) .where('created_at > ?', 1.hour.ago)
if !last_notification.exists? if !last_notification.exists?
topic.create_invite_notification!(user, Notification.types[:invited_to_topic], current_user.username) topic.create_invite_notification!(
user,
Notification.types[:invited_to_topic],
current_user.username,
post_number: post_number
)
end end
end end

View File

@ -1756,14 +1756,14 @@ class Topic < ActiveRecord::Base
email_addresses.to_a email_addresses.to_a
end end
def create_invite_notification!(target_user, notification_type, username) def create_invite_notification!(target_user, notification_type, username, post_number: 1)
invited_by = User.find_by_username(username) invited_by = User.find_by_username(username)
ensure_can_invite!(target_user, invited_by) ensure_can_invite!(target_user, invited_by)
target_user.notifications.create!( target_user.notifications.create!(
notification_type: notification_type, notification_type: notification_type,
topic_id: self.id, topic_id: self.id,
post_number: 1, post_number: post_number,
data: { data: {
topic_title: self.title, topic_title: self.title,
display_username: username, display_username: username,

View File

@ -2840,7 +2840,7 @@ en:
help: "begin composing a reply to this topic" help: "begin composing a reply to this topic"
share: share:
title: "Share" title: "Share Topic"
extended_title: "Share a link" extended_title: "Share a link"
help: "share a link to this topic" help: "share a link to this topic"
instructions: "Share a link to this topic:" instructions: "Share a link to this topic:"
@ -3282,6 +3282,10 @@ en:
post_number: "%{username}, post #%{post_number}" post_number: "%{username}, post #%{post_number}"
show_all: "Show all" show_all: "Show all"
share:
title: "Share Post #%{post_number}"
instructions: "Share a link to this post:"
category: category:
none: "(no category)" none: "(no category)"
all: "All categories" all: "All categories"

View File

@ -2853,6 +2853,10 @@ RSpec.describe TopicsController do
end end
describe '#invite_notify' do describe '#invite_notify' do
before do
topic.update!(highest_post_number: 1)
end
it 'does not notify same user multiple times' do it 'does not notify same user multiple times' do
sign_in(user) sign_in(user)