Skip to content

Commit

Permalink
Improve .my-mention style
Browse files Browse the repository at this point in the history
  • Loading branch information
kohler committed Jan 4, 2025
1 parent e73ed78 commit febc4a2
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 71 deletions.
4 changes: 3 additions & 1 deletion src/commentinfo.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php
// commentinfo.php -- HotCRP helper class for comments
// Copyright (c) 2006-2024 Eddie Kohler; see LICENSE.
// Copyright (c) 2006-2025 Eddie Kohler; see LICENSE.

class CommentInfo {
/** @var Conf
Expand Down Expand Up @@ -567,6 +567,8 @@ function unparse_commenter_html(Contact $viewer) {
if (($this->commentType & self::CT_RESPONSE) !== 0) {
$n = "<i>" . $this->unparse_response_text() . "</i>"
. ($n === "Author" ? "" : " ({$n})");
} else if ($this->contactId === $viewer->contactId) {
$n = "<span class=\"my-mention\" title=\"This is you\">{$n}</span>";
}
return $n;
}
Expand Down
141 changes: 102 additions & 39 deletions src/contact.php
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
<?php
// contact.php -- HotCRP helper class representing system users
// Copyright (c) 2006-2024 Eddie Kohler; see LICENSE.
// Copyright (c) 2006-2025 Eddie Kohler; see LICENSE.

class ContactDecorations {
/** @var string */
public $colors;
public $rn_classes;
/** @var ?string */
public $ra_classes;
/** @var string */
public $decorations;

/** @param string $colors
/** @param string $rn_classes
* @param ?string $ra_classes
* @param string $decorations */
function __construct($colors, $decorations) {
$this->colors = $colors;
function __construct($rn_classes, $ra_classes, $decorations) {
$this->rn_classes = $rn_classes;
$this->ra_classes = $ra_classes;
$this->decorations = $decorations;
}
}
Expand Down Expand Up @@ -140,6 +144,8 @@ class Contact implements JsonSerializable {
private $_topic_interest_map;
/** @var array<int,ContactDecorations> */
private $_name_decorations_map = [];
/** @var ?int */
private $_name_decorations_flags;

// Roles
const ROLE_PC = 0x0001; // value matters
Expand Down Expand Up @@ -1218,6 +1224,75 @@ function completion_items() {
return $items;
}

/** @param int $uid
* @param Contact $u
* @return ?ContactDecorations */
private function _name_decorations($uid, $u) {
if (array_key_exists($uid, $this->_name_decorations_map)) {
return $this->_name_decorations_map[$uid];
}

if (!$this->can_view_user_tags()) {
if ($u->contactXid === $this->contactXid) {
return new ContactDecorations("my-mention", null, "");
}
return null;
}

$fl = $this->_name_decorations_flags;
if ($fl === null) {
$dt = $this->conf->tags();
$test = ($dt->has_role_decoration ? " pc#0" : "") . " dim#0";
$test = $dt->censor(TagMap::CENSOR_VIEW, $test, $this, null);
$this->_name_decorations_flags = $fl = (str_contains($test, "pc") ? 1 : 0)
| (str_contains($test, "dim") ? 2 : 0);
}
$pc = ($fl & 1) !== 0 && ($u->roles & self::ROLE_PC) !== 0;
$disabled = ($fl & 2) !== 0 && $u->disabled_flags() !== 0;
if ($u->contactTags === null
&& !$pc
&& !$disabled
&& $uid !== $this->contactId) {
return null;
}

$dt = $this->conf->tags();
if ($u->contactTags !== null) {
$aut = $dt->censor(TagMap::CENSOR_VIEW, $u->contactTags, $this, null);
} else {
$aut = "";
}
if ($pc) {
$aut .= " pc#0";
}

$cc_rn = $aut !== "" ? $dt->color_classes($aut) : "";
if ($disabled) {
$cc_ra = $cc_rn !== "" ? "{$cc_rn} tag-dim" : "tag-dim";
} else {
$cc_ra = $cc_rn;
}
$c_rn = $cc_rn !== "" ? "{$cc_rn} taghh" : "";
$c_ra = $cc_ra !== "" ? "{$cc_ra} taghh" : "";
if ($uid === $this->contactId) {
$c_rn = $c_rn !== "" ? "{$c_rn} my-mention" : "my-mention";
$c_ra = $c_ra !== "" ? "{$c_ra} my-mention" : "my-mention";
}
if ($cc_rn !== "" && $dt->has(TagInfo::TFM_DECORATION)) {
$decor = (new Tagger($this))->unparse_decoration_html($aut, Tagger::DECOR_USER);
} else {
$decor = "";
}

if ($c_rn !== "" || $c_ra !== "" || $decor !== "") {
$nd = new ContactDecorations($c_rn, $c_rn === $c_ra ? null : $c_ra, $decor);
} else {
$nd = null;
}
$this->_name_decorations_map[$uid] = $nd;
return $nd;
}

/** @param 'n'|'t'|'r'|'ra'|'rn' $type
* @param ReviewInfo|Contact|int $x
* @param int $flags
Expand All @@ -1230,8 +1305,8 @@ function name_for($type, $x, $flags = 0) {
$u = $this->conf->user_by_id($uid, USER_SLICE);
} else if ($x instanceof ReviewInfo) {
$u = $x->reviewer();
if ($x->nameAmbiguous && $type === "r" && !$u->nameAmbiguous) {
$type = "ra";
if ($x->nameAmbiguous && $type === "r") {
$flags |= NAME_E;
}
} else {
$u = $x;
Expand All @@ -1241,33 +1316,6 @@ function name_for($type, $x, $flags = 0) {
return "";
}

$userdecor = null;
if ($type[0] === "r"
&& ($this->isPC || $this->tracker_kiosk_state > 0)
&& $this->can_view_user_tags()) {
if (array_key_exists($uid, $this->_name_decorations_map)) {
$userdecor = $this->_name_decorations_map[$uid];
} else {
$dt = $this->conf->tags();
$ctflags = ($dt->has_role_decoration ? self::CTFLAG_ROLES : 0)
| ($type !== "rn" ? self::CTFLAG_DISABLED : 0);
$act = self::all_user_tags_for($u, $ctflags);
if ($act !== ""
&& ($viewable = $dt->censor(TagMap::CENSOR_VIEW, $act, $this, null))) {
$colors = $dt->color_classes($viewable);
if ($dt->has(TagInfo::TFM_DECORATION)) {
$decorations = (new Tagger($this))->unparse_decoration_html($viewable, Tagger::DECOR_USER);
} else {
$decorations = "";
}
if ($colors !== "" || $decorations !== "") {
$userdecor = new ContactDecorations($colors, $decorations);
}
}
$this->_name_decorations_map[$uid] = $userdecor;
}
}

$flags |= NAME_P;
if (($u->nameAmbiguous ?? false) || $type === "ra") {
$flags |= NAME_E;
Expand All @@ -1277,12 +1325,19 @@ function name_for($type, $x, $flags = 0) {
if ($type !== "t") {
$n = htmlspecialchars($n);
}
if ($userdecor !== null) {
if ($userdecor->colors !== "") {
$n = "<span class=\"{$userdecor->colors} taghh\">{$n}</span>";
}
$n .= $userdecor->decorations;

if ($type[0] === "r"
&& ($this->isPC || $this->tracker_kiosk_state > 0)
&& ($nd = $this->_name_decorations($uid, $u))) {
$k = $type === "rn" ? $nd->rn_classes : $nd->ra_classes ?? $nd->rn_classes;
$n = ($k !== "" ? "<span class=\"{$k}\">{$n}</span>" : $n) . $nd->decorations;
}

if ($type === "rx") {
$t = $uid === $this->contactId ? "This is you" : $u->email;
$n = "<span class=\"taghl\" title=\"{$t}\">{$n}</span>";
}

return $n;
}

Expand All @@ -1304,6 +1359,12 @@ function reviewer_html_for($x) {
return $this->name_for($this->isPC ? "r" : "n", $x);
}

/** @param int|Contact|ReviewInfo $x
* @return string */
function reviewer_extended_html_for($x) {
return $this->name_for($this->isPC ? "rx" : "n", $x);
}

/** @param int|Contact|ReviewInfo $x
* @return string */
function reviewer_text_for($x) {
Expand Down Expand Up @@ -1477,6 +1538,8 @@ function perm_tag_allows($perm) {
* @param 0|1|2|3 $ctags
* @return string */
static function all_user_tags_for($x, $ctags) {
// See also _name_decorations, which depends on the tags used for roles
// and disablement
$tags = $x->contactTags ?? "";
if (($ctags & self::CTFLAG_ROLES) !== 0
&& ($x->roles & self::ROLE_PC) !== 0) {
Expand Down
33 changes: 17 additions & 16 deletions src/options/o_pcconflicts.php
Original file line number Diff line number Diff line change
Expand Up @@ -339,23 +339,24 @@ function render(FieldRender $fr, PaperValue $ov) {
$confset = $this->selectors ? $this->conf->conflict_set() : null;
$names = [];
foreach ($ov->prow->conflict_type_list() as $cflt) {
if (Conflict::is_conflicted($cflt->conflictType)
&& ($p = $pcm[$cflt->contactId] ?? null)) {
$t = $user->reviewer_html_for($p);
if ($p->affiliation) {
$t .= " <span class=\"auaff\">(" . htmlspecialchars($p->affiliation) . ")</span>";
}
$ch = "";
if (Conflict::is_author($cflt->conflictType)) {
$ch = "<strong>Author</strong>";
} else if ($confset) {
$ch = $confset->unparse_html($cflt->conflictType);
}
if ($ch !== "") {
$t .= " - {$ch}";
}
$names[$p->pc_index] = "<li class=\"odname\">{$t}</li>";
if (!Conflict::is_conflicted($cflt->conflictType)
|| !($p = $pcm[$cflt->contactId] ?? null)) {
continue;
}
$t = $user->reviewer_extended_html_for($p);
if ($p->affiliation) {
$t .= " <span class=\"auaff\">(" . htmlspecialchars($p->affiliation) . ")</span>";
}
$ch = "";
if (Conflict::is_author($cflt->conflictType)) {
$ch = "<strong>Author</strong>";
} else if ($confset) {
$ch = $confset->unparse_html($cflt->conflictType);
}
if ($ch !== "") {
$t .= " - {$ch}";
}
$names[$p->pc_index] = "<li class=\"odname\">{$t}</li>";
}
if (empty($names)) {
$names[] = "<li class=\"odname\">None</li>";
Expand Down
19 changes: 11 additions & 8 deletions src/papertable.php
Original file line number Diff line number Diff line change
Expand Up @@ -1494,8 +1494,8 @@ private function _print_ps_pc_conflicts() {
|| !Conflict::is_conflicted($cu->conflictType)) {
continue;
}
$h = $this->user->reviewer_html_for($cu->user);
$pcconf[$cu->user->pc_index] = "<li class=\"odname\"><span class=\"taghl\" title=\"{$cu->user->email}\">{$h}</span></li>";
$h = $this->user->reviewer_extended_html_for($cu->user);
$pcconf[$cu->user->pc_index] = "<li class=\"odname\">{$h}</li>";
}
if (empty($pcconf)) {
$pcconf[] = '<li class="od">None</li>';
Expand Down Expand Up @@ -2611,19 +2611,22 @@ function review_table() {
// reviewer identity
$showtoken = $rr->reviewToken && $user->can_edit_review($prow, $rr);
if (!$user->can_view_review_identity($prow, $rr)) {
$t .= ($rtype ? "<td class=\"rl\">{$rtype}</td>" : '<td></td>');
$t .= $rtype ? "<td class=\"rl\">{$rtype}</td>" : '<td></td>';
} else {
$reviewer = $rr->reviewer();
if (!$showtoken || !Contact::is_anonymous_email($reviewer->email)) {
$n = $user->reviewer_html_for($rr);
if ($showtoken && Contact::is_anonymous_email($reviewer->email)) {
$n = "[Token " . encode_token($rr->reviewToken) . "]";
if ($user->is_my_review($rr)) {
$n = "<span class=\"my-mention\" title=\"You have this review token\">{$n}</span>";
}
} else {
$n = "[Token " . encode_token((int) $rr->reviewToken) . "]";
$n = $user->reviewer_extended_html_for($rr);
}
if ($allow_actas) {
$n .= $this->_review_table_actas($reviewer);
}
$rtypex = $rtype ? " {$rtype}" : "";
$t .= "<td class=\"rl\"><span class=\"taghl\" title=\"{$reviewer->email}\">{$n}</span>{$rtypex}</td>";
$t .= "<td class=\"rl\">{$n}{$rtypex}</td>";
}

// requester
Expand Down Expand Up @@ -2746,7 +2749,7 @@ private function _review_links() {
$tclass = "cmtlink";
if (($tags = $cx[0]->viewable_tags($this->user))
&& ($color = $cx[0]->conf->tags()->color_classes($tags))) {
$tclass .= " $color taghh";
$tclass .= " {$color} taghh";
}
$cid = $cx[0]->unparse_html_id();
return "<span class=\"nb\"><a class=\"{$tclass} track\" href=\"#{$cid}\">"
Expand Down
19 changes: 12 additions & 7 deletions stylesheets/style.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* -*- mode: css; indent-tabs-mode: t; css-indent-offset: 8 -*- */
/* style.css -- HotCRP CSS styles */
/* Copyright (c) 2006-2024 Eddie Kohler; see LICENSE. */
/* Copyright (c) 2006-2025 Eddie Kohler; see LICENSE. */

/* theme colors and widths */
@layer theme {
Expand Down Expand Up @@ -3524,6 +3524,10 @@ tr.plx {
background-position: top left;
}

.my-mention {
color: #a16300;
}

.tagbg, .badge {
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
Expand Down Expand Up @@ -4585,14 +4589,15 @@ a:hover .t-editor,
font-size: 200%;
line-height: 1.125;
}
.my-mention {
.my-mention::after {
content: "✪";
padding-left: 0.1em;
font-size: 95%;
display: inline-block;
position: relative;
bottom: 0.3em;
text-indent: 0;
color: #a16300;
text-decoration-line: underline;
text-decoration-thickness: 1px;
text-decoration-color: #a16300;
text-decoration-style: dashed;
text-underline-offset: 2px;
}
.preview {
margin-bottom: 24px;
Expand Down

0 comments on commit febc4a2

Please sign in to comment.