mirror of https://github.com/ppy/osu
Properly disable comment box on beatmaps that cannot be commented on
Closes https://github.com/ppy/osu/issues/30052. Compare: -83816dbe24/resources/js/components/comment-editor.tsx (L54-L60)
-83816dbe24/resources/js/components/comment-editor.tsx (L47-L52)
This commit is contained in:
parent
a258059d43
commit
e91c8fb4bd
|
@ -12,6 +12,7 @@
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
using osu.Game.Overlays;
|
using osu.Game.Overlays;
|
||||||
using osu.Game.Overlays.Comments;
|
using osu.Game.Overlays.Comments;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
@ -133,6 +134,34 @@ void assertLoggedOutState()
|
||||||
assertLoggedInState();
|
assertLoggedInState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestCommentsDisabled()
|
||||||
|
{
|
||||||
|
AddStep("no reason for disable", () => commentEditor.CommentableMeta.Value = new CommentableMeta
|
||||||
|
{
|
||||||
|
CurrentUserAttributes = new CommentableMeta.CommentableCurrentUserAttributes(),
|
||||||
|
});
|
||||||
|
AddAssert("textbox enabled", () => commentEditor.ChildrenOfType<TextBox>().Single().ReadOnly, () => Is.False);
|
||||||
|
|
||||||
|
AddStep("specific reason for disable", () => commentEditor.CommentableMeta.Value = new CommentableMeta
|
||||||
|
{
|
||||||
|
CurrentUserAttributes = new CommentableMeta.CommentableCurrentUserAttributes
|
||||||
|
{
|
||||||
|
CanNewCommentReason = "This comment section is disabled. For reasons.",
|
||||||
|
}
|
||||||
|
});
|
||||||
|
AddAssert("textbox disabled", () => commentEditor.ChildrenOfType<TextBox>().Single().ReadOnly, () => Is.True);
|
||||||
|
|
||||||
|
AddStep("entire commentable meta missing", () => commentEditor.CommentableMeta.Value = null);
|
||||||
|
AddAssert("textbox enabled", () => commentEditor.ChildrenOfType<TextBox>().Single().ReadOnly, () => Is.False);
|
||||||
|
|
||||||
|
AddStep("current user attributes missing", () => commentEditor.CommentableMeta.Value = new CommentableMeta
|
||||||
|
{
|
||||||
|
CurrentUserAttributes = null,
|
||||||
|
});
|
||||||
|
AddAssert("textbox enabled", () => commentEditor.ChildrenOfType<TextBox>().Single().ReadOnly, () => Is.True);
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestCancelAction()
|
public void TestCancelAction()
|
||||||
{
|
{
|
||||||
|
@ -167,8 +196,7 @@ protected override void OnCommit(string value)
|
||||||
protected override LocalisableString GetButtonText(bool isLoggedIn) =>
|
protected override LocalisableString GetButtonText(bool isLoggedIn) =>
|
||||||
isLoggedIn ? @"Commit" : "You're logged out!";
|
isLoggedIn ? @"Commit" : "You're logged out!";
|
||||||
|
|
||||||
protected override LocalisableString GetPlaceholderText(bool isLoggedIn) =>
|
protected override LocalisableString GetPlaceholderText() => @"This text box is empty";
|
||||||
isLoggedIn ? @"This text box is empty" : "Still empty, but now you can't type in it.";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private partial class TestCancellableCommentEditor : CancellableCommentEditor
|
private partial class TestCancellableCommentEditor : CancellableCommentEditor
|
||||||
|
@ -189,7 +217,7 @@ protected override void OnCommit(string text)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override LocalisableString GetButtonText(bool isLoggedIn) => @"Save";
|
protected override LocalisableString GetButtonText(bool isLoggedIn) => @"Save";
|
||||||
protected override LocalisableString GetPlaceholderText(bool isLoggedIn) => @"Multiline textboxes soon";
|
protected override LocalisableString GetPlaceholderText() => @"Multiline textboxes soon";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,5 +24,14 @@ public class CommentableMeta
|
||||||
|
|
||||||
[JsonProperty("url")]
|
[JsonProperty("url")]
|
||||||
public string Url { get; set; } = string.Empty;
|
public string Url { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[JsonProperty("current_user_attributes")]
|
||||||
|
public CommentableCurrentUserAttributes? CurrentUserAttributes { get; set; }
|
||||||
|
|
||||||
|
public struct CommentableCurrentUserAttributes
|
||||||
|
{
|
||||||
|
[JsonProperty("can_new_comment_reason")]
|
||||||
|
public string? CanNewCommentReason { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Graphics.UserInterfaceV2;
|
using osu.Game.Graphics.UserInterfaceV2;
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
|
using osu.Game.Resources.Localisation.Web;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
@ -21,6 +23,8 @@ namespace osu.Game.Overlays.Comments
|
||||||
{
|
{
|
||||||
public abstract partial class CommentEditor : CompositeDrawable
|
public abstract partial class CommentEditor : CompositeDrawable
|
||||||
{
|
{
|
||||||
|
public Bindable<CommentableMeta?> CommentableMeta { get; set; } = new Bindable<CommentableMeta?>();
|
||||||
|
|
||||||
private const int side_padding = 8;
|
private const int side_padding = 8;
|
||||||
|
|
||||||
protected abstract LocalisableString FooterText { get; }
|
protected abstract LocalisableString FooterText { get; }
|
||||||
|
@ -53,8 +57,7 @@ public abstract partial class CommentEditor : CompositeDrawable
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the placeholder text for the comment box.
|
/// Returns the placeholder text for the comment box.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="isLoggedIn">Whether the current user is logged in.</param>
|
protected abstract LocalisableString GetPlaceholderText();
|
||||||
protected abstract LocalisableString GetPlaceholderText(bool isLoggedIn);
|
|
||||||
|
|
||||||
protected bool ShowLoadingSpinner
|
protected bool ShowLoadingSpinner
|
||||||
{
|
{
|
||||||
|
@ -168,7 +171,8 @@ protected override void LoadComplete()
|
||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
Current.BindValueChanged(_ => updateCommitButtonState(), true);
|
Current.BindValueChanged(_ => updateCommitButtonState(), true);
|
||||||
apiState.BindValueChanged(updateStateForLoggedIn, true);
|
apiState.BindValueChanged(_ => updateEnabledState());
|
||||||
|
CommentableMeta.BindValueChanged(_ => updateEnabledState(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void OnCommit(string text);
|
protected abstract void OnCommit(string text);
|
||||||
|
@ -176,16 +180,25 @@ protected override void LoadComplete()
|
||||||
private void updateCommitButtonState() =>
|
private void updateCommitButtonState() =>
|
||||||
commitButton.Enabled.Value = loadingSpinner.State.Value == Visibility.Hidden && !string.IsNullOrEmpty(Current.Value);
|
commitButton.Enabled.Value = loadingSpinner.State.Value == Visibility.Hidden && !string.IsNullOrEmpty(Current.Value);
|
||||||
|
|
||||||
private void updateStateForLoggedIn(ValueChangedEvent<APIState> state) => Schedule(() =>
|
private void updateEnabledState() => Schedule(() =>
|
||||||
{
|
{
|
||||||
bool isAvailable = state.NewValue > APIState.Offline;
|
bool isOnline = apiState.Value > APIState.Offline;
|
||||||
|
var canNewCommentReason = CommentEditor.canNewCommentReason(CommentableMeta.Value);
|
||||||
|
bool commentsDisabled = canNewCommentReason != null;
|
||||||
|
bool canComment = isOnline && !commentsDisabled;
|
||||||
|
|
||||||
TextBox.PlaceholderText = GetPlaceholderText(isAvailable);
|
if (!isOnline)
|
||||||
TextBox.ReadOnly = !isAvailable;
|
TextBox.PlaceholderText = AuthorizationStrings.RequireLogin;
|
||||||
|
else if (canNewCommentReason != null)
|
||||||
|
TextBox.PlaceholderText = canNewCommentReason.Value;
|
||||||
|
else
|
||||||
|
TextBox.PlaceholderText = GetPlaceholderText();
|
||||||
|
TextBox.ReadOnly = !canComment;
|
||||||
|
|
||||||
if (isAvailable)
|
if (isOnline)
|
||||||
{
|
{
|
||||||
commitButton.Show();
|
commitButton.Show();
|
||||||
|
commitButton.Enabled.Value = !commentsDisabled;
|
||||||
logInButton.Hide();
|
logInButton.Hide();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -195,6 +208,24 @@ private void updateStateForLoggedIn(ValueChangedEvent<APIState> state) => Schedu
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// https://github.com/ppy/osu-web/blob/83816dbe24ad2927273cba968f2fcd2694a121a9/resources/js/components/comment-editor.tsx#L54-L60
|
||||||
|
// careful here, logic is VERY finicky.
|
||||||
|
private static LocalisableString? canNewCommentReason(CommentableMeta? meta)
|
||||||
|
{
|
||||||
|
if (meta == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (meta.CurrentUserAttributes != null)
|
||||||
|
{
|
||||||
|
if (meta.CurrentUserAttributes.Value.CanNewCommentReason is string reason)
|
||||||
|
return reason;
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return AuthorizationStrings.CommentStoreDisabled;
|
||||||
|
}
|
||||||
|
|
||||||
private partial class EditorTextBox : OsuTextBox
|
private partial class EditorTextBox : OsuTextBox
|
||||||
{
|
{
|
||||||
protected override float LeftRightPadding => side_padding;
|
protected override float LeftRightPadding => side_padding;
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using osu.Framework.Localisation;
|
using osu.Framework.Localisation;
|
||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
|
using osu.Game.Extensions;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Resources.Localisation.Web;
|
using osu.Game.Resources.Localisation.Web;
|
||||||
using osu.Game.Users.Drawables;
|
using osu.Game.Users.Drawables;
|
||||||
|
@ -49,6 +50,7 @@ public partial class CommentsContainer : CompositeDrawable
|
||||||
private int currentPage;
|
private int currentPage;
|
||||||
|
|
||||||
private FillFlowContainer pinnedContent;
|
private FillFlowContainer pinnedContent;
|
||||||
|
private NewCommentEditor newCommentEditor;
|
||||||
private FillFlowContainer content;
|
private FillFlowContainer content;
|
||||||
private DeletedCommentsCounter deletedCommentsCounter;
|
private DeletedCommentsCounter deletedCommentsCounter;
|
||||||
private CommentsShowMoreButton moreButton;
|
private CommentsShowMoreButton moreButton;
|
||||||
|
@ -114,7 +116,7 @@ private void load(OverlayColourProvider colourProvider)
|
||||||
Padding = new MarginPadding { Left = 60 },
|
Padding = new MarginPadding { Left = 60 },
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
AutoSizeAxes = Axes.Y,
|
AutoSizeAxes = Axes.Y,
|
||||||
Child = new NewCommentEditor
|
Child = newCommentEditor = new NewCommentEditor
|
||||||
{
|
{
|
||||||
OnPost = prependPostedComments
|
OnPost = prependPostedComments
|
||||||
}
|
}
|
||||||
|
@ -242,6 +244,7 @@ protected void ClearComments()
|
||||||
protected void OnSuccess(CommentBundle response)
|
protected void OnSuccess(CommentBundle response)
|
||||||
{
|
{
|
||||||
commentCounter.Current.Value = response.Total;
|
commentCounter.Current.Value = response.Total;
|
||||||
|
newCommentEditor.CommentableMeta.Value = response.CommentableMeta.SingleOrDefault(m => m.Id == id.Value && m.Type == type.Value.ToString().ToSnakeCase().ToLowerInvariant());
|
||||||
|
|
||||||
if (!response.Comments.Any())
|
if (!response.Comments.Any())
|
||||||
{
|
{
|
||||||
|
@ -413,8 +416,7 @@ private partial class NewCommentEditor : CommentEditor
|
||||||
protected override LocalisableString GetButtonText(bool isLoggedIn) =>
|
protected override LocalisableString GetButtonText(bool isLoggedIn) =>
|
||||||
isLoggedIn ? CommonStrings.ButtonsPost : CommentsStrings.GuestButtonNew;
|
isLoggedIn ? CommonStrings.ButtonsPost : CommentsStrings.GuestButtonNew;
|
||||||
|
|
||||||
protected override LocalisableString GetPlaceholderText(bool isLoggedIn) =>
|
protected override LocalisableString GetPlaceholderText() => CommentsStrings.PlaceholderNew;
|
||||||
isLoggedIn ? CommentsStrings.PlaceholderNew : AuthorizationStrings.RequireLogin;
|
|
||||||
|
|
||||||
protected override void OnCommit(string text)
|
protected override void OnCommit(string text)
|
||||||
{
|
{
|
||||||
|
|
|
@ -428,7 +428,7 @@ private void toggleReply()
|
||||||
if (replyEditorContainer.Count == 0)
|
if (replyEditorContainer.Count == 0)
|
||||||
{
|
{
|
||||||
replyEditorContainer.Show();
|
replyEditorContainer.Show();
|
||||||
replyEditorContainer.Add(new ReplyCommentEditor(Comment)
|
replyEditorContainer.Add(new ReplyCommentEditor(Comment, Meta)
|
||||||
{
|
{
|
||||||
OnPost = comments =>
|
OnPost = comments =>
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Localisation;
|
using osu.Framework.Localisation;
|
||||||
|
@ -26,12 +27,12 @@ public partial class ReplyCommentEditor : CancellableCommentEditor
|
||||||
protected override LocalisableString GetButtonText(bool isLoggedIn) =>
|
protected override LocalisableString GetButtonText(bool isLoggedIn) =>
|
||||||
isLoggedIn ? CommonStrings.ButtonsReply : CommentsStrings.GuestButtonReply;
|
isLoggedIn ? CommonStrings.ButtonsReply : CommentsStrings.GuestButtonReply;
|
||||||
|
|
||||||
protected override LocalisableString GetPlaceholderText(bool isLoggedIn) =>
|
protected override LocalisableString GetPlaceholderText() => CommentsStrings.PlaceholderReply;
|
||||||
isLoggedIn ? CommentsStrings.PlaceholderReply : AuthorizationStrings.RequireLogin;
|
|
||||||
|
|
||||||
public ReplyCommentEditor(Comment parent)
|
public ReplyCommentEditor(Comment parent, IEnumerable<CommentableMeta> meta)
|
||||||
{
|
{
|
||||||
parentComment = parent;
|
parentComment = parent;
|
||||||
|
CommentableMeta.Value = meta.SingleOrDefault(m => m.Id == parent.CommentableId && m.Type == parent.CommentableType);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
|
|
Loading…
Reference in New Issue