Improve admin message seen/dismiss state. (#26223)

Fixes #26211

Admin messages now have separate "seen" and "dismissed" fields. The idea is that an admin should be able to tell whether a user pressed the "dismiss for now" button. Instead of using "seen" as "show this message to players when they join", "dismissed" is now used for this.

Existing notes in the database will automatically be marked as dismissed on migration. A note cannot be dismissed without being seen (enforced via constraint in the database too, aren't I fancy).

As part of this, it has become impossible for a player to play without dismissing the message in some form. Instead of a shitty popup window, the popup is now a fullscreen overlay that blocks clicks behind it, making the game unplayable. Also, if a user somehow has multiple messages they will be combined into one popup.

Also I had enough respect for the codebase to make it look better and clean up the code somewhat. Yippee.
This commit is contained in:
Pieter-Jan Briers
2024-03-21 16:15:46 +01:00
committed by GitHub
parent f87480dd36
commit d776c4b392
21 changed files with 3748 additions and 108 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,40 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Content.Server.Database.Migrations.Postgres
{
/// <inheritdoc />
public partial class AdminMessageDismiss : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "dismissed",
table: "admin_messages",
type: "boolean",
nullable: false,
defaultValue: false);
migrationBuilder.Sql("UPDATE admin_messages SET dismissed = seen");
migrationBuilder.AddCheckConstraint(
name: "NotDismissedAndSeen",
table: "admin_messages",
sql: "NOT dismissed OR seen");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropCheckConstraint(
name: "NotDismissedAndSeen",
table: "admin_messages");
migrationBuilder.DropColumn(
name: "dismissed",
table: "admin_messages");
}
}
}

View File

@@ -183,6 +183,10 @@ namespace Content.Server.Database.Migrations.Postgres
.HasColumnType("uuid")
.HasColumnName("deleted_by_id");
b.Property<bool>("Dismissed")
.HasColumnType("boolean")
.HasColumnName("dismissed");
b.Property<DateTime?>("ExpirationTime")
.HasColumnType("timestamp with time zone")
.HasColumnName("expiration_time");
@@ -232,7 +236,10 @@ namespace Content.Server.Database.Migrations.Postgres
b.HasIndex("RoundId")
.HasDatabaseName("IX_admin_messages_round_id");
b.ToTable("admin_messages", (string)null);
b.ToTable("admin_messages", null, t =>
{
t.HasCheckConstraint("NotDismissedAndSeen", "NOT dismissed OR seen");
});
});
modelBuilder.Entity("Content.Server.Database.AdminNote", b =>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,40 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Content.Server.Database.Migrations.Sqlite
{
/// <inheritdoc />
public partial class AdminMessageDismiss : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "dismissed",
table: "admin_messages",
type: "INTEGER",
nullable: false,
defaultValue: false);
migrationBuilder.Sql("UPDATE admin_messages SET dismissed = seen");
migrationBuilder.AddCheckConstraint(
name: "NotDismissedAndSeen",
table: "admin_messages",
sql: "NOT dismissed OR seen");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropCheckConstraint(
name: "NotDismissedAndSeen",
table: "admin_messages");
migrationBuilder.DropColumn(
name: "dismissed",
table: "admin_messages");
}
}
}

View File

@@ -166,6 +166,10 @@ namespace Content.Server.Database.Migrations.Sqlite
.HasColumnType("TEXT")
.HasColumnName("deleted_by_id");
b.Property<bool>("Dismissed")
.HasColumnType("INTEGER")
.HasColumnName("dismissed");
b.Property<DateTime?>("ExpirationTime")
.HasColumnType("TEXT")
.HasColumnName("expiration_time");
@@ -215,7 +219,10 @@ namespace Content.Server.Database.Migrations.Sqlite
b.HasIndex("RoundId")
.HasDatabaseName("IX_admin_messages_round_id");
b.ToTable("admin_messages", (string)null);
b.ToTable("admin_messages", null, t =>
{
t.HasCheckConstraint("NotDismissedAndSeen", "NOT dismissed OR seen");
});
});
modelBuilder.Entity("Content.Server.Database.AdminNote", b =>

View File

@@ -268,6 +268,11 @@ namespace Content.Server.Database
.HasPrincipalKey(author => author.UserId)
.OnDelete(DeleteBehavior.SetNull);
// A message cannot be "dismissed" without also being "seen".
modelBuilder.Entity<AdminMessage>().ToTable(t =>
t.HasCheckConstraint("NotDismissedAndSeen",
"NOT dismissed OR seen"));
modelBuilder.Entity<ServerBan>()
.HasOne(ban => ban.CreatedBy)
.WithMany(author => author.AdminServerBansCreated)
@@ -969,6 +974,15 @@ namespace Content.Server.Database
[ForeignKey("DeletedBy")] public Guid? DeletedById { get; set; }
public Player? DeletedBy { get; set; }
public DateTime? DeletedAt { get; set; }
/// <summary>
/// Whether the message has been seen at least once by the player.
/// </summary>
public bool Seen { get; set; }
/// <summary>
/// Whether the message has been dismissed permanently by the player.
/// </summary>
public bool Dismissed { get; set; }
}
}