messages.qtpl (24576B)
1 {% import "dkforest/pkg/database" %} 2 {% import "dkforest/pkg/managers" %} 3 {% import humanize "github.com/dustin/go-humanize" %} 4 5 {%- func GenerateStyle(AuthUser *database.User, Data ChatMessagesData) -%} 6 <style> 7 /* http://meyerweb.com/eric/tools/css/reset/ 8 v2.0 | 20110126 9 License: none (public domain) 10 */ 11 html, body, div, span, applet, object, iframe, 12 h1, h2, h3, h4, h5, h6, p, blockquote, pre, 13 a, abbr, acronym, address, big, cite, code, 14 del, dfn, em, img, ins, kbd, q, s, samp, 15 small, strike, strong, sub, sup, tt, var, 16 b, u, i, center, 17 dl, dt, dd, ol, ul, li, 18 fieldset, form, label, legend, 19 table, caption, tbody, tfoot, thead, tr, th, td, 20 article, aside, canvas, details, embed, 21 figure, figcaption, footer, header, hgroup, 22 menu, nav, output, ruby, section, summary, 23 time, mark, audio, video { 24 margin: 0; 25 padding: 0; 26 border: 0; 27 font-size: 100%; 28 font: inherit; 29 vertical-align: baseline; 30 } 31 /* HTML5 display-role reset for older browsers */ 32 article, aside, details, figcaption, figure, 33 footer, header, hgroup, menu, nav, section { 34 display: block; 35 } 36 body { 37 line-height: 1; 38 } 39 ol, ul { 40 list-style: none; 41 } 42 blockquote, q { 43 quotes: none; 44 } 45 blockquote:before, blockquote:after, 46 q:before, q:after { 47 content: ''; 48 content: none; 49 } 50 table { 51 border-collapse: collapse; 52 border-spacing: 0; 53 } 54 /* --- end --- */ 55 56 i { font-style: italic; } 57 58 /* Remove button padding in FF */ 59 button::-moz-focus-inner { 60 border:0; 61 padding:0; 62 } 63 64 body { font-family: Lato,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"; } 65 a { color: #00bc8c; text-decoration: none; } 66 a:hover { color: #007053; text-decoration: underline; } 67 .unread_room { color: #2392da; text-decoration: none; } 68 .unread_room:hover { color: #004970; text-decoration: underline; } 69 .emoji { 70 font-family: "Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji", Times, Symbola, Aegyptus, Code2000, Code2001, Code2002, Musica, serif, LastResort; 71 font-size: 17px; 72 } 73 .mod-btn { 74 width: 16px; height: 16px; 75 margin: 0; padding: 0; 76 border: 1px solid gray; 77 display: inline; 78 text-align: center; 79 vertical-align: middle; 80 user-select: none; 81 background-color: #444; 82 color: #ea2a2a; 83 -webkit-box-shadow: 1px 1px 1px rgba(0,0,0,0.25); 84 -moz-box-shadow: 1px 1px 1px rgba(0,0,0,0.25); 85 -webkit-border-radius: 3px; 86 -moz-border-radius: 3px; 87 } 88 .mod-btn:hover { 89 background-color: #222; 90 } 91 .delete_msg_btn { 92 font-size: 15px; 93 line-height: 1; 94 } 95 @keyframes hide_btn { 96 100% { visibility: hidden; } 97 } 98 @keyframes orange_btn { 99 99% { color: ea2a2a; } 100% { color: orange; } 100 } 101 .delete_msg_btn::after { content: "×"; } 102 .hb_btn { 103 font-size: 10px; 104 line-height: 1.4; 105 } 106 .hb_btn::after { content: "hb"; } 107 .k_btn { 108 font-size: 10px; 109 line-height: 1.4; 110 } 111 .k_btn::after { content: "k"; } 112 .connection-closed { 113 color: #bf2718; 114 display: block; 115 position: fixed; 116 text-align: center; 117 top: 0; 118 left: calc(50% - 200px); 119 width: 400px; 120 z-index: 2; 121 background-color: #500000; 122 border: 2px solid #ff0000; 123 } 124 #manualrefresh { 125 {% if !Data.ForceManualRefresh %} 126 top: -200%; 127 animation: timeout_messages {%dl Data.ManualRefreshTimeout %}s forwards; 128 {% endif %} 129 color: #bf2718; 130 display: block; 131 position: fixed; 132 text-align: center; 133 left: calc(50% - 200px); 134 width: 400px; 135 z-index: 2; 136 background-color: #500000; 137 border: 2px solid #ff0000; 138 } 139 @keyframes timeout_messages { 140 0% { top: -200%; } 141 99% { top: -200%; } 142 100% { top: 0; } 143 } 144 .date { color: #999; font-family: 'Courier New', Courier, monospace; font-size: 14px; } 145 .date-link:hover { color: #999; text-decoration: underline; } 146 .sysmsg { color: #fff; font-family: 'Courier New', Courier, monospace; font-size: 14px; } 147 small { font-size: 80%; font-weight: 400; } 148 .msg { padding: 3px 0 3px 8px; border-bottom: 1px solid #444; color: #888; position: relative; } 149 .msg p:first-of-type { display: inline; } 150 strong { font-weight: bold; } 151 em { font-style: italic; } 152 pre { border: 1px solid #2b442b; padding: 2px; margin: 2px 0; max-height: {%dl AuthUser.CodeBlockHeight %}px; overflow: auto; background-color: rgba(39,40,34,0.6) !important; 153 font-family: SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace; } 154 .fullscreen { position: absolute; margin-top: -19px; right: 3px; } 155 code { border: 1px solid #2b442b; color: #f92672; padding: 0 2px; margin: 0px 0; background-color: rgba(39,40,34,0.6) !important; } 156 .censored { background-color: black; color: black; padding: 0 3px; } 157 .censored:hover { background-color: black; color: white; } 158 .censored > a { color: black; } 159 .censored > a:hover { color: #007053; text-decoration: underline; } 160 ul { list-style-type: disc; margin: 0 0 0 15px; } 161 * { 162 -webkit-font-smoothing: antialiased; 163 -moz-osx-font-smoothing: grayscale; 164 } 165 .afk-indicator { color: #ff9a27; } 166 .spacer16 { display: inline-block; width: 16px; } 167 .spacer36 { display: inline-block; width: 36px; } 168 .spacer56 { display: inline-block; width: 56px; } 169 .d-inline { display: inline; } 170 .o-wrap { overflow-wrap: break-word; } 171 .f-def-clr { color: #888; } 172 .f-orange-clr { color: orange; } 173 .f-white-clr, .f-white-clr:hover { color: white; } 174 .line-through { text-decoration: line-through; } 175 .hb-row { background-color: rgba(0, 0, 0, 0.7); opacity: {%f AuthUser.GetHellbanOpacityF64() %}; } 176 .own-highlight { background-color: rgba(255,241,176,0.05); } 177 .read-marker { border-style: outset; border-top: {%dl AuthUser.ChatReadMarkerSize %}px solid {%s AuthUser.ChatReadMarkerColor %}; } 178 #msgs { {% if !Data.HideRightColumn %}width: calc(100% - 185px); float: left; {% endif %}line-height: 1.2; } 179 #no-msg { padding-left: 10px; color: #ddd; } 180 #rgt-pane-w { width: 150px; height: 100%; position: fixed; right: 15px; overflow-y: auto; } 181 #rgt-pane { line-height: 1.15; } 182 .rgt-title { font-weight: bolder; color: #ced4da; } 183 .mb-20px { margin-bottom: 20px; } 184 .mb-30px { margin-bottom: 30px; } 185 .mt-5px { margin-top: 5px; } 186 .mt-10px { margin-top: 10px; } 187 .notif, .notif:hover { color: #e74c3c; } 188 #msg-err { background-color: #8f2d2d; color: #ffffff; padding: 1px 5px 2px 5px; display: block; text-decoration: none; } 189 #i { 190 background-color: #006400; 191 width: 18px; 192 height: 18px; 193 position: fixed; 194 top: 1px; 195 right: {% if !Data.HideRightColumn %}35px{% else %}8px{% endif %}; 196 border-radius: 9px; 197 animation: i1 30s forwards; 198 } 199 @keyframes i1 { 0% { background-color: #006400; } 32% { background-color: #006400; } 33% { background-color: #626400; } 99% { background-color: #626400; } 100% { background-color: #8b0000; } } 200 @keyframes i2 { 0% { background-color: #006400; } 32% { background-color: #006400; } 33% { background-color: #626400; } 99% { background-color: #626400; } 100% { background-color: #8b0000; } } 201 @keyframes horizontal-shaking1 { 202 0% { transform: translateX(0) } 203 25% { transform: translateX(9px) } 204 50% { transform: translateX(-9px) } 205 75% { transform: translateX(9px) } 206 100% { transform: translateX(0) } 207 } 208 @keyframes horizontal-shaking2 { 209 0% { transform: translateX(0) } 210 25% { transform: translateX(9px) } 211 50% { transform: translateX(-9px) } 212 75% { transform: translateX(9px) } 213 100% { transform: translateX(0) } 214 } 215 </style> 216 {%- endfunc -%} 217 218 {% func Messages(VERSION, CSRF, NullUsername string, AuthUser *database.User, Data ChatMessagesData) -%} 219 <html lang="en"> 220 <head> 221 <title></title> 222 {%- if !Data.ChatMenuData.PreventRefresh && !Data.ForceManualRefresh -%}<meta http-equiv="refresh" content="{%dl AuthUser.RefreshRate %}">{%- endif -%} 223 {%- if AuthUser.CollectMetadata -%}<link rel="stylesheet" type="text/css" href="/public/css/meta.css?v={%s VERSION %}" />{%- endif -%} 224 {%-= GenerateStyle(AuthUser, Data) -%} 225 <style>#btn_delete_useless:active { background-image: url('/api/v1/chat/messages/delete/useless'); }</style> 226 </head> 227 <body> 228 229 {%- if Data.ForceManualRefresh -%} 230 <div id="manualrefresh"> 231 <h4>Manual refresh required</h4> 232 <form method="get" action="/chat/{%s Data.ChatMenuData.RoomName %}" target="_top"> 233 <input type="submit" value="Reload" /> 234 </form> 235 </div> 236 {%- elseif !Data.ChatMenuData.PreventRefresh -%} 237 <div id="manualrefresh"> 238 <h4>Manual refresh required</h4> 239 <form method="get"> 240 <input type="submit" value="Reload" /> 241 </form> 242 </div> 243 {%- endif -%} 244 245 {%- if Data.Error != "" -%} 246 <a href="/api/v1/chat/messages/{%s Data.ChatMenuData.RoomName %}" id="msg-err">× {%s Data.Error %}</a> 247 {%- endif -%} 248 249 {%- if Data.PmSound || Data.TaggedSound -%} 250 <audio src="/public/mp3/sound5.mp3" autoplay></audio> 251 {%- elseif Data.NewMessageSound -%} 252 <audio src="/public/mp3/sound6.mp3" autoplay></audio> 253 {%- endif -%} 254 255 <div id="msgs"> 256 {%-= RenderMessages(AuthUser, Data, CSRF, NullUsername, nil, false) -%} 257 </div> 258 259 {% if !AuthUser.HideRightColumn %} 260 <div id="rgt-pane-w"> 261 {%-= RenderRightColumn(AuthUser, Data.ChatMenuData) -%} 262 </div> 263 {%- endif -%} 264 {%- if AuthUser.CollectMetadata -%} 265 <div class="div_1"></div> 266 <div class="div_2"></div> 267 <div class="div_f0">a</div> 268 {%- endif -%} 269 </body> 270 </html> 271 {% endfunc %} 272 273 274 {%- func RenderRightColumn(AuthUser *database.User, Data ChatMenuData) -%} 275 <div id="rgt-pane"> 276 <div class="mb-20px"> 277 <div class="rgt-title">Inbox (<a href="/settings/inbox" target="_top"{% if Data.InboxCount > 0 %}class="notif"{% endif %}>{%dl Data.InboxCount %}</a>)</div> 278 </div> 279 <div class="mb-20px"> 280 <div class="rgt-title">Rooms:</div> 281 {%- for _, e := range Data.OfficialRooms -%} 282 {%- if e.Name == "club" -%} 283 {%- if AuthUser.IsClubMember -%} 284 <div><a href="/chat/club" target="_top"{% if e.IsUnread %} class="unread_room"{% endif %}>#club</a></div> 285 {%- endif -%} 286 {%- elseif e.Name == "moderators" -%} 287 {%- if AuthUser.IsModerator() -%} 288 <div><a href="/chat/moderators" target="_top"{% if e.IsUnread %} class="unread_room"{% endif %}>#moderators</a></div> 289 {%- endif -%} 290 {%- else -%} 291 <div><a href="/chat/{%s e.Name %}" target="_top"{% if e.IsUnread %} class="unread_room"{% endif %}>#{%s e.Name %}</a></div> 292 {%- endif -%} 293 {%- endfor -%} 294 {%- if len(Data.SubscribedRooms) > 0 -%} 295 <div class="mt-10px"></div> 296 {%- for _, e := range Data.SubscribedRooms -%} 297 <div><a href="/chat/{%s e.Name %}" target="_top"{% if e.IsUnread %} class="unread_room"{% endif %}>#{%s e.Name %}</a></div> 298 {%- endfor -%} 299 {%- endif -%} 300 <div class="mt-5px"><a href="/rooms" target="_top">[...]</a></div> 301 </div> 302 <div class="mb-20px"> 303 <div class="rgt-title">In this room:</div> 304 {%- for _, e := range Data.Members -%} 305 {%= Member(AuthUser, Data, e) %} 306 {%- endfor -%} 307 </div> 308 {%- if Data.VisibleMemberInChat || AuthUser.DisplayHellbanned -%} 309 <div class="mb-30px"> 310 {%- if len(Data.MembersInChat) > 0 -%} 311 <div class="rgt-title">In other rooms:</div> 312 {%- for _, e := range Data.MembersInChat -%} 313 {%= Member(AuthUser, Data, e) %} 314 {%- endfor -%} 315 {%- endif -%} 316 </div> 317 {%- endif -%} 318 </div> 319 {%- endfunc -%} 320 321 {%- func RenderMessages(AuthUser database.IUserRenderMessage, Data ChatMessagesData, CSRF, NullUsername string, readMarkerRev *int, isEdit bool) -%} 322 {%- code 323 baseTopBarURL := "/api/v1/chat/top-bar/" + Data.ChatMenuData.RoomName 324 readMarkerRendered := false 325 isFirstMsg := true 326 -%} 327 <style>#btn_delete_useless:active { background-image: url('/api/v1/chat/messages/delete/useless'); }</style> 328 {%- for idx, e := range Data.Messages -%} 329 {%-= RenderMessage(idx, e, AuthUser, Data, baseTopBarURL, &readMarkerRendered, &isFirstMsg, CSRF, NullUsername, readMarkerRev, isEdit) -%} 330 {% endfor %} 331 {% if len(Data.Messages) == 0 %} 332 <div id="no-msg"><em>No message yet</em></div> 333 {% endif %} 334 {%- endfunc -%} 335 336 {%- func RenderMessage(idx int, e database.ChatMessage, AuthUser database.IUserRenderMessage, 337 Data ChatMessagesData, baseTopBarURL string, readMarkerRendered, isFirstMsg *bool, CSRF, NullUsername string, readMarkerRev *int, isEdit bool) -%} 338 {%- if e.UserCanSee(AuthUser) -%} 339 {%- if AuthUser.GetChatReadMarkerEnabled() && e.CreatedAt.Before(Data.ReadMarker.ReadAt) && !*readMarkerRendered && !isEdit%} 340 <div class="read-marker read-marker-0"{% if idx == 0 %} style="display:none;"{% endif %}></div> 341 {%- code *readMarkerRendered = true -%} 342 {%- elseif AuthUser.GetChatReadMarkerEnabled() && e.CreatedAt.After(Data.ReadMarker.ReadAt) && !*readMarkerRendered && isEdit && readMarkerRev != nil -%} 343 <style>.read-marker-{%d (*readMarkerRev) %}{display:none !important;}</style> 344 {%- code *readMarkerRev++ -%} 345 <div class="read-marker read-marker-{%d *readMarkerRev %}"></div> 346 {%- code *readMarkerRendered = true -%} 347 {% endif %} 348 <div id="msgid-{%s e.UUID %}" class="msgidc-{%s e.UUID %}-{%dl e.Rev %} msg 349 {%- if (e.User.IsHellbanned || e.IsHellbanned) && AuthUser.GetDisplayHellbanned() %} hb-row 350 {%- elseif AuthUser.GetID() == e.User.ID && AuthUser.GetHighlightOwnMessages() %} own-highlight{%- endif -%} 351 "> 352 {%- if e.UserCanDelete(AuthUser) -%} 353 {%- if AuthUser.GetDisplayDeleteButton() -%} 354 {%- if e.TooOldToDelete() -%} 355 <button id="btn_delete_{%s e.UUID %}" class="mod-btn delete_msg_btn f-orange-clr" title="delete"></button> 356 {%- else -%} 357 <button id="btn_delete_{%s e.UUID %}" class="mod-btn delete_msg_btn" title="delete" 358 style=" 359 {%- if string(e.User.Username) != NullUsername -%} 360 {%- if (AuthUser.IsModerator() && e.UserID != AuthUser.GetID()) || AuthUser.GetIsAdmin() || e.IsRoomOwner(AuthUser.GetID()) -%} 361 animation: {%dl e.DeleteSecondsRemaining() %}s 1s forwards orange_btn; 362 {%- else -%} 363 animation: {%dl e.DeleteSecondsRemaining() %}s 1s forwards hide_btn; 364 {%- endif -%} 365 {%- endif -%} 366 " 367 ></button> 368 {%- endif -%} 369 <style>#btn_delete_{%s e.UUID %}:active { background-image: url('/api/v1/chat/messages/delete/{%s e.UUID %}'); }</style> 370 {%- endif -%} 371 {%- if AuthUser.IsModerator() -%} 372 {%- if !e.OwnMessage(AuthUser.GetID()) -%} 373 {%- if AuthUser.GetDisplayHellbanButton() -%} 374 {%- if string(e.User.Username) == NullUsername -%} 375 <div class="spacer16"></div> 376 {%- else -%} 377 {%- if e.User.IsHellbanned -%} 378 <form method="post" action="/api/v1/users/{%s e.UserID.String() %}/unhellban" class="d-inline"> 379 <input type="hidden" name="csrf" value="{%s CSRF %}" /> 380 <button class="mod-btn hb_btn f-orange-clr line-through" title="unhellban"></button> 381 </form> 382 {%- else -%} 383 <form method="post" action="/api/v1/users/{%s e.UserID.String() %}/hellban" class="d-inline"> 384 <input type="hidden" name="csrf" value="{%s CSRF %}" /> 385 <button class="mod-btn hb_btn f-orange-clr" title="hellban"></button> 386 </form> 387 {%- endif -%} 388 {%- endif -%} 389 {%- endif -%} 390 {%- if AuthUser.GetDisplayKickButton() -%} 391 <form method="post" action="/api/v1/users/{%s e.UserID.String() %}/kick" class="d-inline"> 392 <input type="hidden" name="csrf" value="{%s CSRF %}" /> 393 <button class="mod-btn k_btn f-orange-clr" title="kick"></button> 394 </form> 395 {%- endif -%} 396 {%- else -%} 397 {%- if AuthUser.GetDisplayKickButton() && AuthUser.GetDisplayHellbanButton() -%} 398 <div class="spacer36"></div> 399 {%- elseif AuthUser.GetDisplayKickButton() || AuthUser.GetDisplayHellbanButton() -%} 400 <div class="spacer16"></div> 401 {%- endif -%} 402 {%- endif -%} 403 {%- endif -%} 404 {%- else -%} 405 {%- if Data.NbButtons == 3 -%} 406 <div class="spacer56"></div> 407 {%- elseif Data.NbButtons == 2 -%} 408 <div class="spacer36"></div> 409 {%- elseif Data.NbButtons == 1 -%} 410 <div class="spacer16"></div> 411 {%- endif -%} 412 {%- endif -%} 413 {%- if !Data.HideTimestamps -%} 414 <a href="{%s baseTopBarURL %}?quote={%s e.UUID %}{%= unesc(Data.TopBarQueryParams) %}" target="iframe1" class="date date-link" title="{%s e.CreatedAt.Format("01-02 15:04:05") %}{% if *isFirstMsg %} ({%s humanize.Time(e.CreatedAt) %}){% endif %}">{%s e.CreatedAt.Format(AuthUser.GetDateFormat()) %}</a> 415 {% code *isFirstMsg = false %} 416 {%- endif -%} 417 <a href="/u/{%s string(e.GetProfile(AuthUser.GetID())) %}" target="_blank" class="f-def-clr">-</a> 418 {%- if e.System -%} 419 <span class="sysmsg">{%= unesc(e.Message) %}</span> 420 {%- else -%} 421 {%- if e.Moderators -%}<span class="sysmsg">[<a href="{%s baseTopBarURL %}?m=1{%= unesc(Data.TopBarQueryParams) %}" target="iframe1" class="sysmsg f-white-clr">M</a>]</span> {%- endif -%} 422 {%- if e.GroupID != nil -%}<span class="sysmsg">[<a href="{%s baseTopBarURL %}?g={%s e.Group.Name %}{%= unesc(Data.TopBarQueryParams) %}" target="iframe1" class="sysmsg f-white-clr">{%s e.Group.Name %}</a>]</span> {%- endif -%} 423 {%- if e.ToUserID != nil -%} 424 [{%-= fromUsername(AuthUser, Data, e, baseTopBarURL) -%} 425 → 426 {%- if e.ToUser.ID == AuthUser.GetID() -%}<span {%= unesc(e.ToUser.GenerateChatStyle()) %}>{%s string(e.ToUser.Username) %}</span>{%- else -%}<a {%= unesc(e.ToUser.GenerateChatStyle()) %} href="{%s baseTopBarURL %}?pm={%s string(e.ToUser.Username) %}{%s Data.TopBarQueryParams %}" target="iframe1">{%s string(e.ToUser.Username) %}</a>{%- endif -%}] - 427 {%- else -%} 428 {%-= fromUsername(AuthUser, Data, e, baseTopBarURL) -%} 429 {%- if !e.IsMe() -%} 430 {%- if AuthUser.CanSeeHB() && (e.IsHellbanned || e.User.IsHellbanned) && (e.ToUserID == nil) -%} 431 <a href="{%s baseTopBarURL %}?hbm=1{%= unesc(Data.TopBarQueryParams) %}" target="iframe1" class="f-def-clr">-</a> 432 {%- else -%} 433 - 434 {%- endif -%} 435 {%- endif -%} 436 {%- endif -%} 437 <span {%= unesc(e.User.GenerateChatStyle()) %}><span class="o-wrap">{%s= unesc(e.MsgToDisplay(AuthUser)) %}</span></span> 438 {%- endif -%} 439 </div> 440 {%- endif -%} 441 {%- endfunc -%} 442 443 444 {% func Member(AuthUser *database.User, Data ChatMenuData, El managers.UserInfo) %} 445 {%- code baseTopBarURL := "/api/v1/chat/top-bar/" + Data.RoomName -%} 446 {%- if El.Username == AuthUser.GetUsername() -%} 447 <div> 448 <span style="color: {%s El.Color %};">{%s string(El.Username) %}</span> 449 {%- if El.AfkIndicatorEnabled -%} 450 <small class="afk-indicator">afk</small> 451 {%- endif -%} 452 </div> 453 {%- elseif len(El.Username) > 0 -%} 454 {%- if !El.IsHellbanned || AuthUser.GetID() == El.UserID || (El.IsHellbanned && AuthUser.GetIsHellbanned()) || AuthUser.GetDisplayHellbanned() -%} 455 <div> 456 {%- code tagType := "tag" -%} 457 {%- if AuthUser.CanSeeHB() && El.IsHellbanned -%} 458 {%- code tagType = "htag" -%} 459 {%- endif -%} 460 {%- stripspace -%} 461 <a href="{%s baseTopBarURL %}?{%s tagType %}={%s string(El.Username) %}{%= unesc(Data.TopBarQueryParams) %}" 462 target="iframe1" 463 {% if El.IsHellbanned && AuthUser.GetDisplayHellbanned() %}class="hb-row"{% endif %} 464 style="color: {%s El.Color %};">{%s string(El.Username[0]) %}</a> 465 <a href="{%s baseTopBarURL %}?pm={%s string(El.Username) %}{%= unesc(Data.TopBarQueryParams) %}" 466 target="iframe1" 467 {% if El.IsHellbanned && AuthUser.GetDisplayHellbanned() %}class="hb-row"{% endif %} 468 style="color: {%s El.Color %};">{%s string(El.Username[1 : len(El.Username)-1]) %}</a> 469 <a href="/u/{%s string(El.Username) %}" 470 rel="noopener noreferrer" target="_blank" 471 {% if El.IsHellbanned && AuthUser.GetDisplayHellbanned() %}class="hb-row"{% endif %} 472 style="color: {%s El.Color %};">{%s string(El.Username[len(El.Username)-1]) %}</a> 473 {%- endstripspace -%} 474 {%- if El.AfkIndicatorEnabled -%} 475 <small class="afk-indicator">afk</small> 476 {%- endif -%} 477 </div> 478 {%- endif -%} 479 {%- endif -%} 480 {% endfunc %} 481 482 483 {%- func fromUsername(AuthUser database.IUserRenderMessage, Data ChatMessagesData, El database.ChatMessage, baseTopBarURL string) -%} 484 {%- code tagType := "tag" -%} 485 {%- if El.ToUserID != nil -%} 486 {%- code tagType = "pm" -%} 487 {%- elseif AuthUser.CanSeeHB() && (El.IsHellbanned || El.User.IsHellbanned) -%} 488 {%- code tagType = "htag" -%} 489 {%- elseif AuthUser.IsModerator() && El.Moderators -%} 490 {%- code tagType = "mtag" -%} 491 {%- endif -%} 492 {%- if El.User.ID == AuthUser.GetID() -%} 493 {%- if El.CanBeEdited() -%}<a {%= unesc(El.User.GenerateChatStyle()) %} href="{%s baseTopBarURL %}?e={%s El.CreatedAt.Format("15:04:05") %}{%= unesc(Data.TopBarQueryParams) %}" target="iframe1">{%s string(El.User.Username) %}</a>{%- else -%}<span {%= unesc(El.User.GenerateChatStyle()) %}>{%s string(El.User.Username) %}</span>{%- endif -%} 494 {%- else -%}<a {%= unesc(El.User.GenerateChatStyle()) %} href="{%s baseTopBarURL %}?{%s tagType %}={%s string(El.User.Username) %}{%= unesc(Data.TopBarQueryParams) %}" target="iframe1">{%s string(El.User.Username) %}</a>{%- endif -%} 495 {%- endfunc -%}