Add Fishbowl archive (#41)
Refs #33 Co-authored-by: Ben Visness <bvisness@gmail.com> Co-authored-by: ilidemi <belk94@gmail.com> Reviewed-on: hmn/hmn#41
|
@ -14,3 +14,4 @@ adminmailer/config.go
|
||||||
adminmailer/adminmailer
|
adminmailer/adminmailer
|
||||||
local/backups
|
local/backups
|
||||||
/tmp
|
/tmp
|
||||||
|
*.exe
|
||||||
|
|
|
@ -0,0 +1,618 @@
|
||||||
|
.fishbowl {
|
||||||
|
background-color: #36393e;
|
||||||
|
color: #dcddde;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl a {
|
||||||
|
color: #00aff4;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl img {
|
||||||
|
object-fit: contain;
|
||||||
|
image-rendering: high-quality;
|
||||||
|
image-rendering: -webkit-optimize-contrast;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .preamble {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto 1fr;
|
||||||
|
max-width: 100%;
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .preamble__guild-icon-container {
|
||||||
|
grid-column: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .preamble__guild-icon {
|
||||||
|
max-width: 88px;
|
||||||
|
max-height: 88px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .preamble__entries-container {
|
||||||
|
grid-column: 2;
|
||||||
|
margin-left: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .preamble__entry {
|
||||||
|
margin-bottom: 0.15rem;
|
||||||
|
color: #ffffff;
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .preamble__entry--small {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog {
|
||||||
|
padding: 1rem 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__message-group {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__message-container {
|
||||||
|
background-color: transparent;
|
||||||
|
transition: background-color 1s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__message-container--highlighted {
|
||||||
|
background-color: rgba(114, 137, 218, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__message-container--pinned {
|
||||||
|
background-color: rgba(249, 168, 37, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__message {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto 1fr;
|
||||||
|
padding: 0.15rem 0;
|
||||||
|
direction: ltr;
|
||||||
|
unicode-bidi: bidi-override;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__message:hover {
|
||||||
|
background-color: #32353b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__message:hover .chatlog__short-timestamp {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__message-aside {
|
||||||
|
grid-column: 1;
|
||||||
|
width: 72px;
|
||||||
|
padding: 0.15rem 0.15rem 0 0.15rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__reference-symbol {
|
||||||
|
height: 10px;
|
||||||
|
margin: 6px 4px 4px 36px;
|
||||||
|
border-left: 2px solid #4f545c;
|
||||||
|
border-top: 2px solid #4f545c;
|
||||||
|
border-radius: 8px 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__avatar {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__short-timestamp {
|
||||||
|
display: none;
|
||||||
|
color: #a3a6aa;
|
||||||
|
font-size: 0.7em;
|
||||||
|
line-height: 1.4em;
|
||||||
|
direction: ltr;
|
||||||
|
unicode-bidi: bidi-override;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__message-primary {
|
||||||
|
grid-column: 2;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__reference {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 0.15rem;
|
||||||
|
align-items: center;
|
||||||
|
color: #b5b6b8;
|
||||||
|
font-size: 0.85em;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__reference-avatar {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
margin-right: 0.25rem;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__reference-author {
|
||||||
|
margin-right: 0.3rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__reference-content {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__reference-link {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__reference-link * {
|
||||||
|
display: inline;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__reference-link .hljs {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__reference-link:hover {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__reference-link:hover *:not(.chatlog__markdown-spoiler) {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__reference-edited-timestamp {
|
||||||
|
margin-left: 0.25rem;
|
||||||
|
color: #a3a6aa;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
font-weight: 500;
|
||||||
|
direction: ltr;
|
||||||
|
unicode-bidi: bidi-override;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__header {
|
||||||
|
margin-bottom: 0.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__author {
|
||||||
|
font-weight: 500;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__bot-label {
|
||||||
|
position: relative;
|
||||||
|
top: -0.1rem;
|
||||||
|
margin-left: 0.3rem;
|
||||||
|
padding: 0.05rem 0.3rem;
|
||||||
|
border-radius: 3px;
|
||||||
|
background-color: #5865F2;
|
||||||
|
color: #ffffff;
|
||||||
|
font-size: 0.625rem;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__timestamp {
|
||||||
|
margin-left: 0.3rem;
|
||||||
|
color: #a3a6aa;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
direction: ltr;
|
||||||
|
unicode-bidi: bidi-override;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__content {
|
||||||
|
padding-right: 1rem;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__edited-timestamp {
|
||||||
|
margin-left: 0.15rem;
|
||||||
|
color: #a3a6aa;
|
||||||
|
font-size: 0.7em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__attachment {
|
||||||
|
position: relative;
|
||||||
|
width: fit-content;
|
||||||
|
margin-top: 0.3rem;
|
||||||
|
border-radius: 3px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__attachment--hidden {
|
||||||
|
cursor: pointer;
|
||||||
|
box-shadow: 0 0 1px 1px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__attachment--hidden * {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__attachment-spoiler-caption {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
z-index: 999;
|
||||||
|
padding: 0.4rem 0.8rem;
|
||||||
|
border-radius: 20px;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
background-color: rgba(0, 0, 0, 0.9);
|
||||||
|
color: #dcddde;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: 0.05rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__attachment--hidden .chatlog__attachment-spoiler-caption {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__attachment--hidden:hover .chatlog__attachment-spoiler-caption {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__attachment-media {
|
||||||
|
max-width: 45vw;
|
||||||
|
max-height: 500px;
|
||||||
|
vertical-align: top;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__attachment--hidden .chatlog__attachment-media {
|
||||||
|
filter: blur(44px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__attachment-generic {
|
||||||
|
max-width: 520px;
|
||||||
|
width: 100%;
|
||||||
|
height: 40px;
|
||||||
|
padding: 10px;
|
||||||
|
border: 1px solid #292b2f;
|
||||||
|
border-radius: 3px;
|
||||||
|
background-color: #2f3136;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__attachment--hidden .chatlog__attachment-generic {
|
||||||
|
filter: blur(44px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__attachment-generic-icon {
|
||||||
|
float: left;
|
||||||
|
width: 30px;
|
||||||
|
height: 100%;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__attachment-generic-size {
|
||||||
|
color: #72767d;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__attachment-generic-name {
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed {
|
||||||
|
display: flex;
|
||||||
|
margin-top: 0.3rem;
|
||||||
|
max-width: 520px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-color-pill {
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: 0.25rem;
|
||||||
|
border-top-left-radius: 3px;
|
||||||
|
border-bottom-left-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-color-pill--default {
|
||||||
|
background-color: #202225;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-content-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 0.5rem 0.6rem;
|
||||||
|
border: 1px solid rgba(46, 48, 54, 0.6);
|
||||||
|
border-top-right-radius: 3px;
|
||||||
|
border-bottom-right-radius: 3px;
|
||||||
|
background-color: rgba(46, 48, 54, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-content {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-text {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-author-container {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-author-icon {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-author {
|
||||||
|
color: #ffffff;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 600;
|
||||||
|
direction: ltr;
|
||||||
|
unicode-bidi: bidi-override;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-author-link {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-title {
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
color: #ffffff;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-description {
|
||||||
|
color: #dcddde;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-fields {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-field {
|
||||||
|
flex: 0;
|
||||||
|
min-width: 100%;
|
||||||
|
max-width: 506px;
|
||||||
|
padding-top: 0.6rem;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-field--inline {
|
||||||
|
flex: 1;
|
||||||
|
flex-basis: auto;
|
||||||
|
min-width: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-field-name {
|
||||||
|
margin-bottom: 0.2rem;
|
||||||
|
color: #ffffff;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-field-value {
|
||||||
|
color: #dcddde;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-thumbnail {
|
||||||
|
flex: 0;
|
||||||
|
max-width: 80px;
|
||||||
|
max-height: 80px;
|
||||||
|
margin-left: 1.2rem;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-image-container {
|
||||||
|
margin-top: 0.6rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-image {
|
||||||
|
max-width: 500px;
|
||||||
|
max-height: 400px;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-footer {
|
||||||
|
margin-top: 0.6rem;
|
||||||
|
color: #dcddde;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-footer-icon {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
margin-right: 0.2rem;
|
||||||
|
border-radius: 50%;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-footer-text {
|
||||||
|
vertical-align: middle;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-plainimage {
|
||||||
|
max-width: 45vw;
|
||||||
|
max-height: 500px;
|
||||||
|
vertical-align: top;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-spotify {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-youtube-container {
|
||||||
|
margin-top: 0.6rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-youtube {
|
||||||
|
border: 0;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__sticker {
|
||||||
|
width: 180px;
|
||||||
|
height: 180px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__sticker--media {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__reactions {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__reaction {
|
||||||
|
display: flex;
|
||||||
|
margin: 0.35rem 0.1rem 0.1rem 0;
|
||||||
|
padding: 0.125rem 0.375rem;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-radius: 8px;
|
||||||
|
background-color: #2f3136;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__reaction:hover {
|
||||||
|
border: 1px solid hsla(0,0%,100%,.2);
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__reaction-count {
|
||||||
|
min-width: 9px;
|
||||||
|
margin-left: 0.35rem;
|
||||||
|
color: #b9bbbe;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__reaction:hover .chatlog__reaction-count {
|
||||||
|
color: #dcddde;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__markdown {
|
||||||
|
max-width: 100%;
|
||||||
|
line-height: 1.3;
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__markdown-preserve {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__markdown-spoiler {
|
||||||
|
background-color: rgba(255, 255, 255, 0.1);
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__markdown-spoiler--hidden {
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: #202225;
|
||||||
|
color: rgba(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__markdown-spoiler--hidden:hover {
|
||||||
|
background-color: rgba(32, 34, 37, 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__markdown-spoiler--hidden::selection {
|
||||||
|
color: rgba(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__markdown-quote {
|
||||||
|
display: flex;
|
||||||
|
margin: 0.05rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__markdown-quote-border {
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
border: 2px solid #4f545c;
|
||||||
|
border-radius: 3px;
|
||||||
|
background-color: #4f545c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__markdown-pre {
|
||||||
|
background-color: #2f3136;
|
||||||
|
font-family: "Consolas", "Courier New", Courier, monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__markdown-pre--multiline {
|
||||||
|
margin-top: 0.25rem;
|
||||||
|
padding: 0.5rem;
|
||||||
|
border: 2px solid #282b30;
|
||||||
|
border-radius: 5px;
|
||||||
|
color: #b9bbbe;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__markdown-pre--multiline.hljs {
|
||||||
|
background-color: inherit;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__markdown-pre--inline {
|
||||||
|
padding: 2px;
|
||||||
|
border-radius: 3px;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__markdown-mention {
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 0 2px;
|
||||||
|
background-color: rgba(88, 101, 242, .3);
|
||||||
|
color: #dee0fc;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__markdown-mention:hover {
|
||||||
|
background-color: #5865f2;
|
||||||
|
color: #ffffff
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__markdown-timestamp {
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 0 2px;
|
||||||
|
color: #a3a6aa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__emoji {
|
||||||
|
width: 1.325rem;
|
||||||
|
height: 1.325rem;
|
||||||
|
margin: 0 0.06rem;
|
||||||
|
vertical-align: -0.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__emoji--small {
|
||||||
|
width: 1rem;
|
||||||
|
height: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__emoji--large {
|
||||||
|
width: 2.8rem;
|
||||||
|
height: 2.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .postamble {
|
||||||
|
padding: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .postamble__entry {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
|
@ -0,0 +1,619 @@
|
||||||
|
.fishbowl {
|
||||||
|
background-color: #ffffff;
|
||||||
|
color: #23262a;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl a {
|
||||||
|
color: #0068e0;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl img {
|
||||||
|
object-fit: contain;
|
||||||
|
image-rendering: high-quality;
|
||||||
|
image-rendering: -webkit-optimize-contrast;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .preamble {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto 1fr;
|
||||||
|
max-width: 100%;
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .preamble__guild-icon-container {
|
||||||
|
grid-column: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .preamble__guild-icon {
|
||||||
|
max-width: 88px;
|
||||||
|
max-height: 88px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .preamble__entries-container {
|
||||||
|
grid-column: 2;
|
||||||
|
margin-left: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .preamble__entry {
|
||||||
|
margin-bottom: 0.15rem;
|
||||||
|
color: #2f3136;
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .preamble__entry--small {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog {
|
||||||
|
padding: 1rem 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__message-group {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__message-container {
|
||||||
|
background-color: transparent;
|
||||||
|
transition: background-color 1s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__message-container--highlighted {
|
||||||
|
background-color: rgba(114, 137, 218, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__message-container--pinned {
|
||||||
|
background-color: rgba(249, 168, 37, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__message {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto 1fr;
|
||||||
|
padding: 0.15rem 0;
|
||||||
|
direction: ltr;
|
||||||
|
unicode-bidi: bidi-override;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__message:hover {
|
||||||
|
background-color: #fafafa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__message:hover .chatlog__short-timestamp {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__message-aside {
|
||||||
|
grid-column: 1;
|
||||||
|
width: 72px;
|
||||||
|
padding: 0.15rem 0.15rem 0 0.15rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__reference-symbol {
|
||||||
|
height: 10px;
|
||||||
|
margin: 6px 4px 4px 36px;
|
||||||
|
border-left: 2px solid #c7ccd1;
|
||||||
|
border-top: 2px solid #c7ccd1;
|
||||||
|
border-radius: 8px 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__avatar {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__short-timestamp {
|
||||||
|
display: none;
|
||||||
|
color: #5e6772;
|
||||||
|
font-size: 0.7em;
|
||||||
|
line-height: 1.4em;
|
||||||
|
direction: ltr;
|
||||||
|
unicode-bidi: bidi-override;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__message-primary {
|
||||||
|
grid-column: 2;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__reference {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 0.15rem;
|
||||||
|
align-items: center;
|
||||||
|
color: #5f5f60;
|
||||||
|
font-size: 0.85em;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__reference-avatar {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
margin-right: 0.25rem;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__reference-author {
|
||||||
|
margin-right: 0.3rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__reference-content {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__reference-link {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__reference-link * {
|
||||||
|
display: inline;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__reference-link .hljs {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__reference-link:hover {
|
||||||
|
color: #2f3136;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__reference-link:hover *:not(.chatlog__markdown-spoiler) {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__reference-edited-timestamp {
|
||||||
|
margin-left: 0.25rem;
|
||||||
|
color: #5e6772;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
font-weight: 500;
|
||||||
|
direction: ltr;
|
||||||
|
unicode-bidi: bidi-override;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__header {
|
||||||
|
margin-bottom: 0.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__author {
|
||||||
|
font-weight: 600;
|
||||||
|
color: #2f3136;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__bot-label {
|
||||||
|
position: relative;
|
||||||
|
top: -0.1rem;
|
||||||
|
margin-left: 0.3rem;
|
||||||
|
padding: 0.05rem 0.3rem;
|
||||||
|
border-radius: 3px;
|
||||||
|
background-color: #5865F2;
|
||||||
|
color: #ffffff;
|
||||||
|
font-size: 0.625rem;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__timestamp {
|
||||||
|
margin-left: 0.3rem;
|
||||||
|
color: #5e6772;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
direction: ltr;
|
||||||
|
unicode-bidi: bidi-override;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__content {
|
||||||
|
padding-right: 1rem;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__edited-timestamp {
|
||||||
|
margin-left: 0.15rem;
|
||||||
|
color: #5e6772;
|
||||||
|
font-size: 0.7em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__attachment {
|
||||||
|
position: relative;
|
||||||
|
width: fit-content;
|
||||||
|
margin-top: 0.3rem;
|
||||||
|
border-radius: 3px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__attachment--hidden {
|
||||||
|
cursor: pointer;
|
||||||
|
box-shadow: 0 0 1px 1px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__attachment--hidden * {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__attachment-spoiler-caption {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
z-index: 999;
|
||||||
|
padding: 0.4rem 0.8rem;
|
||||||
|
border-radius: 20px;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
background-color: rgba(0, 0, 0, 0.9);
|
||||||
|
color: #dcddde;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: 0.05rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__attachment--hidden .chatlog__attachment-spoiler-caption {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__attachment--hidden:hover .chatlog__attachment-spoiler-caption {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__attachment-media {
|
||||||
|
max-width: 45vw;
|
||||||
|
max-height: 500px;
|
||||||
|
vertical-align: top;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__attachment--hidden .chatlog__attachment-media {
|
||||||
|
filter: blur(44px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__attachment-generic {
|
||||||
|
max-width: 520px;
|
||||||
|
width: 100%;
|
||||||
|
height: 40px;
|
||||||
|
padding: 10px;
|
||||||
|
border: 1px solid #ebedef;
|
||||||
|
border-radius: 3px;
|
||||||
|
background-color: #f2f3f5;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__attachment--hidden .chatlog__attachment-generic {
|
||||||
|
filter: blur(44px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__attachment-generic-icon {
|
||||||
|
float: left;
|
||||||
|
width: 30px;
|
||||||
|
height: 100%;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__attachment-generic-size {
|
||||||
|
color: #72767d;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__attachment-generic-name {
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed {
|
||||||
|
display: flex;
|
||||||
|
margin-top: 0.3rem;
|
||||||
|
max-width: 520px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-color-pill {
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: 0.25rem;
|
||||||
|
border-top-left-radius: 3px;
|
||||||
|
border-bottom-left-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-color-pill--default {
|
||||||
|
background-color: rgba(227, 229, 232, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-content-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 0.5rem 0.6rem;
|
||||||
|
border: 1px solid rgba(204, 204, 204, 0.3);
|
||||||
|
border-top-right-radius: 3px;
|
||||||
|
border-bottom-right-radius: 3px;
|
||||||
|
background-color: rgba(249, 249, 249, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-content {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-text {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-author-container {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-author-icon {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-author {
|
||||||
|
color: #4f545c;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 600;
|
||||||
|
direction: ltr;
|
||||||
|
unicode-bidi: bidi-override;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-author-link {
|
||||||
|
color: #4f545c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-title {
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
color: #4f545c;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-description {
|
||||||
|
color: #2e3338;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-fields {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-field {
|
||||||
|
flex: 0;
|
||||||
|
min-width: 100%;
|
||||||
|
max-width: 506px;
|
||||||
|
padding-top: 0.6rem;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-field--inline {
|
||||||
|
flex: 1;
|
||||||
|
flex-basis: auto;
|
||||||
|
min-width: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-field-name {
|
||||||
|
margin-bottom: 0.2rem;
|
||||||
|
color: #36393e;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-field-value {
|
||||||
|
color: #2e3338;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-thumbnail {
|
||||||
|
flex: 0;
|
||||||
|
max-width: 80px;
|
||||||
|
max-height: 80px;
|
||||||
|
margin-left: 1.2rem;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-image-container {
|
||||||
|
margin-top: 0.6rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-image {
|
||||||
|
max-width: 500px;
|
||||||
|
max-height: 400px;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-footer {
|
||||||
|
margin-top: 0.6rem;
|
||||||
|
color: #2e3338;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-footer-icon {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
margin-right: 0.2rem;
|
||||||
|
border-radius: 50%;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-footer-text {
|
||||||
|
vertical-align: middle;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-plainimage {
|
||||||
|
max-width: 45vw;
|
||||||
|
max-height: 500px;
|
||||||
|
vertical-align: top;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-spotify {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-youtube-container {
|
||||||
|
margin-top: 0.6rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__embed-youtube {
|
||||||
|
border: 0;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__sticker {
|
||||||
|
width: 180px;
|
||||||
|
height: 180px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__sticker--media {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__reactions {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__reaction {
|
||||||
|
display: flex;
|
||||||
|
margin: 0.35rem 0.1rem 0.1rem 0;
|
||||||
|
padding: 0.125rem 0.375rem;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-radius: 8px;
|
||||||
|
background-color: #f2f3f5;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__reaction:hover {
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__reaction-count {
|
||||||
|
min-width: 9px;
|
||||||
|
margin-left: 0.35rem;
|
||||||
|
color: #4f5660;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__reaction:hover .chatlog__reaction-count {
|
||||||
|
color: #2e3338;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__markdown {
|
||||||
|
max-width: 100%;
|
||||||
|
line-height: 1.3;
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__markdown-preserve {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__markdown-spoiler {
|
||||||
|
background-color: rgba(0, 0, 0, 0.1);
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__markdown-spoiler--hidden {
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: #b9bbbe;
|
||||||
|
color: rgba(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__markdown-spoiler--hidden:hover {
|
||||||
|
background-color: rgba(185, 187, 190, 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__markdown-spoiler--hidden::selection {
|
||||||
|
color: rgba(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__markdown-quote {
|
||||||
|
display: flex;
|
||||||
|
margin: 0.05rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__markdown-quote-border {
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
border: 2px solid #c7ccd1;
|
||||||
|
border-radius: 3px;
|
||||||
|
background-color: #c7ccd1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__markdown-pre {
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
font-family: "Consolas", "Courier New", Courier, monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__markdown-pre--multiline {
|
||||||
|
margin-top: 0.25rem;
|
||||||
|
padding: 0.5rem;
|
||||||
|
border: 2px solid #f3f3f3;
|
||||||
|
border-radius: 5px;
|
||||||
|
color: #657b83;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__markdown-pre--multiline.hljs {
|
||||||
|
background-color: inherit;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__markdown-pre--inline {
|
||||||
|
padding: 2px;
|
||||||
|
border-radius: 3px;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__markdown-mention {
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 0 2px;
|
||||||
|
background-color: rgba(88, 101, 242, .15);
|
||||||
|
color: #505cdc;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__markdown-mention:hover {
|
||||||
|
background-color: #5865f2;
|
||||||
|
color: #ffffff
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__markdown-timestamp {
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 0 2px;
|
||||||
|
color: #5e6772;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__emoji {
|
||||||
|
width: 1.325rem;
|
||||||
|
height: 1.325rem;
|
||||||
|
margin: 0 0.06rem;
|
||||||
|
vertical-align: -0.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__emoji--small {
|
||||||
|
width: 1rem;
|
||||||
|
height: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__emoji--large {
|
||||||
|
width: 2.8rem;
|
||||||
|
height: 2.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .postamble {
|
||||||
|
padding: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .postamble__entry {
|
||||||
|
color: #2f3136;
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg width="100%" height="100%" viewBox="0 0 734 30" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||||
|
<g transform="matrix(0.412851,0,0,0.412851,-164.727,-144.911)">
|
||||||
|
<path d="M399,404C477.667,404 563.667,422.167 640,421C712.766,419.888 784.237,398.26 857,397C934,395.667 1021,413.167 1102,413C1182.53,412.834 1262.47,395.225 1343,396C1482.5,397.343 1719.83,418.976 1861,421.056C1915.68,421.862 2097.72,404.026 2176.88,404.026L2176.88,351.026L399,351L399,404Z" style="fill:rgb(255,0,0);"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 859 B |
|
@ -36,14 +36,6 @@ var BgWhite = "\033[47m"
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
Reset = ""
|
Reset = BgBlack + Reset
|
||||||
Red = ""
|
|
||||||
Green = ""
|
|
||||||
Yellow = ""
|
|
||||||
Blue = ""
|
|
||||||
Purple = ""
|
|
||||||
Cyan = ""
|
|
||||||
Gray = ""
|
|
||||||
White = ""
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ type UsersQuery struct {
|
||||||
// Ignored when using FetchUser
|
// Ignored when using FetchUser
|
||||||
UserIDs []int // if empty, all users
|
UserIDs []int // if empty, all users
|
||||||
Usernames []string // if empty, all users
|
Usernames []string // if empty, all users
|
||||||
|
DiscordUserIDs []string // if empty, no Discord filtering
|
||||||
|
|
||||||
// Flags to modify behavior
|
// Flags to modify behavior
|
||||||
AnyStatus bool // Bypasses shadowban system
|
AnyStatus bool // Bypasses shadowban system
|
||||||
|
@ -46,6 +47,7 @@ func FetchUsers(
|
||||||
type userRow struct {
|
type userRow struct {
|
||||||
User models.User `db:"hmn_user"`
|
User models.User `db:"hmn_user"`
|
||||||
AvatarAsset *models.Asset `db:"avatar"`
|
AvatarAsset *models.Asset `db:"avatar"`
|
||||||
|
DiscordUser *models.DiscordUser `db:"discord_user"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var qb db.QueryBuilder
|
var qb db.QueryBuilder
|
||||||
|
@ -54,6 +56,7 @@ func FetchUsers(
|
||||||
FROM
|
FROM
|
||||||
hmn_user
|
hmn_user
|
||||||
LEFT JOIN asset AS avatar ON avatar.id = hmn_user.avatar_asset_id
|
LEFT JOIN asset AS avatar ON avatar.id = hmn_user.avatar_asset_id
|
||||||
|
LEFT JOIN discord_user ON discord_user.hmn_user_id = hmn_user.id
|
||||||
WHERE
|
WHERE
|
||||||
TRUE
|
TRUE
|
||||||
`)
|
`)
|
||||||
|
@ -63,6 +66,9 @@ func FetchUsers(
|
||||||
if len(q.Usernames) > 0 {
|
if len(q.Usernames) > 0 {
|
||||||
qb.Add(`AND LOWER(hmn_user.username) = ANY($?)`, q.Usernames)
|
qb.Add(`AND LOWER(hmn_user.username) = ANY($?)`, q.Usernames)
|
||||||
}
|
}
|
||||||
|
if len(q.DiscordUserIDs) > 0 {
|
||||||
|
qb.Add(`AND discord_user.userid = ANY($?)`, q.DiscordUserIDs)
|
||||||
|
}
|
||||||
if !q.AnyStatus {
|
if !q.AnyStatus {
|
||||||
if currentUser == nil {
|
if currentUser == nil {
|
||||||
qb.Add(`AND hmn_user.status = $?`, models.UserStatusApproved)
|
qb.Add(`AND hmn_user.status = $?`, models.UserStatusApproved)
|
||||||
|
@ -89,6 +95,7 @@ func FetchUsers(
|
||||||
for i, row := range userRows {
|
for i, row := range userRows {
|
||||||
user := row.User
|
user := row.User
|
||||||
user.AvatarAsset = row.AvatarAsset
|
user.AvatarAsset = row.AvatarAsset
|
||||||
|
user.DiscordUser = row.DiscordUser
|
||||||
result[i] = &user
|
result[i] = &user
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -172,6 +172,15 @@ func TestPodcastRSS(t *testing.T) {
|
||||||
AssertRegexMatch(t, BuildPodcastRSS(), RegexPodcastRSS, nil)
|
AssertRegexMatch(t, BuildPodcastRSS(), RegexPodcastRSS, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFishbowlIndex(t *testing.T) {
|
||||||
|
AssertRegexMatch(t, BuildFishbowlIndex(), RegexFishbowlIndex, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFishbowl(t *testing.T) {
|
||||||
|
AssertRegexMatch(t, BuildFishbowl("oop"), RegexFishbowl, map[string]string{"slug": "oop"})
|
||||||
|
AssertRegexNoMatch(t, BuildFishbowl("oop")+"/otherfiles/whatever", RegexFishbowl)
|
||||||
|
}
|
||||||
|
|
||||||
func TestForum(t *testing.T) {
|
func TestForum(t *testing.T) {
|
||||||
AssertRegexMatch(t, hmn.BuildForum(nil, 1), RegexForum, nil)
|
AssertRegexMatch(t, hmn.BuildForum(nil, 1), RegexForum, nil)
|
||||||
AssertRegexMatch(t, hmn.BuildForum([]string{"wip"}, 2), RegexForum, map[string]string{"subforums": "wip", "page": "2"})
|
AssertRegexMatch(t, hmn.BuildForum([]string{"wip"}, 2), RegexForum, map[string]string{"subforums": "wip", "page": "2"})
|
||||||
|
|
|
@ -365,6 +365,26 @@ func BuildPodcastEpisodeFile(filename string) string {
|
||||||
return BuildUserFile(fmt.Sprintf("podcast/%s/%s", models.HMNProjectSlug, filename))
|
return BuildUserFile(fmt.Sprintf("podcast/%s/%s", models.HMNProjectSlug, filename))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fishbowls
|
||||||
|
*/
|
||||||
|
|
||||||
|
var RegexFishbowlIndex = regexp.MustCompile(`^/fishbowl$`)
|
||||||
|
|
||||||
|
func BuildFishbowlIndex() string {
|
||||||
|
defer CatchPanic()
|
||||||
|
return Url("/fishbowl", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
var RegexFishbowl = regexp.MustCompile(`^/fishbowl/(?P<slug>[^/]+)/?$`)
|
||||||
|
|
||||||
|
func BuildFishbowl(slug string) string {
|
||||||
|
defer CatchPanic()
|
||||||
|
return Url(fmt.Sprintf("/fishbowl/%s/", slug), nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
var RegexFishbowlFiles = regexp.MustCompile(`^/fishbowl/(?P<slug>[^/]+)(?P<path>/.+)$`)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Forums
|
* Forums
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -50,6 +50,7 @@ type User struct {
|
||||||
|
|
||||||
// Non-db fields, to be filled in by fetch helpers
|
// Non-db fields, to be filled in by fetch helpers
|
||||||
AvatarAsset *Asset
|
AvatarAsset *Asset
|
||||||
|
DiscordUser *DiscordUser
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *User) BestName() string {
|
func (u *User) BestName() string {
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
{{ template "base.html" . }}
|
||||||
|
|
||||||
|
{{ define "extrahead" }}
|
||||||
|
<link rel="stylesheet" href="{{ static (eq .Theme "dark" | ternary "fishbowl-dark.css" "fishbowl-light.css") }}">
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function scrollToMessage(event, id) {
|
||||||
|
var element = document.getElementById('chatlog__message-container-' + id);
|
||||||
|
if (!element)
|
||||||
|
return;
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
element.classList.add('chatlog__message-container--highlighted');
|
||||||
|
|
||||||
|
window.scrollTo({
|
||||||
|
top: element.getBoundingClientRect().top - document.body.getBoundingClientRect().top - (window.innerHeight / 2),
|
||||||
|
behavior: 'smooth'
|
||||||
|
});
|
||||||
|
|
||||||
|
window.setTimeout(function() {
|
||||||
|
element.classList.remove('chatlog__message-container--highlighted');
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function showSpoiler(event, element) {
|
||||||
|
if (!element)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (element.classList.contains('chatlog__attachment--hidden')) {
|
||||||
|
event.preventDefault();
|
||||||
|
element.classList.remove('chatlog__attachment--hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element.classList.contains('chatlog__markdown-spoiler--hidden')) {
|
||||||
|
event.preventDefault();
|
||||||
|
element.classList.remove('chatlog__markdown-spoiler--hidden');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.fishbowl-banner {
|
||||||
|
background-color: {{ eq .Theme "dark" | ternary "#254464" "#a0c8f2" }};
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
padding-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl-banner::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0; left: 0; right: 0; bottom: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
background-image: url({{ static "waterline.svg" }});
|
||||||
|
background-size: 734px 30px;
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
{{ if eq .Theme "dark" }}
|
||||||
|
filter: hue-rotate(210deg) saturate(0.3) brightness(1.1);
|
||||||
|
{{ else }}
|
||||||
|
filter: hue-rotate(210deg) saturate(0.15) brightness(2.9);
|
||||||
|
{{ end }}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl-banner a {
|
||||||
|
color: {{ eq .Theme "dark" | ternary "#9ad0ff" "#1f4f99" }};
|
||||||
|
}
|
||||||
|
|
||||||
|
.fishbowl .chatlog__author a {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ define "content" }}
|
||||||
|
<div class="ph3 ph0-ns">
|
||||||
|
<h2>{{ .Info.Title }}</h2>
|
||||||
|
<p>{{ .Info.Description }}</p>
|
||||||
|
|
||||||
|
<div class="fishbowl-banner br3 mb3">
|
||||||
|
<div class="pa3">
|
||||||
|
This is a <b>fishbowl</b>: a panel conversation held on the Handmade Network Discord where a select few participants discuss a topic with depth and nuance. We host them every two months, so if you want to catch the next one, <a href="https://discord.gg/hmn" target="_blank">join the Discord!</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="fishbowl br3">
|
||||||
|
{{- .Contents -}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
|
@ -0,0 +1,33 @@
|
||||||
|
{{ template "base.html" . }}
|
||||||
|
|
||||||
|
{{ define "content" }}
|
||||||
|
<div class="ph3 ph0-ns">
|
||||||
|
<h2>Fishbowls</h2>
|
||||||
|
|
||||||
|
<p>Every two months on the Discord, we host a <b>fishbowl</b>: a panel conversation where a select few community members can discuss a topic in detail. Fishbowls give us the opportunity to discuss difficult subjects with more nuance and detail than you can find anywhere else on the Internet. In many ways, they're a distillation of everything the network is about.</p>
|
||||||
|
|
||||||
|
<p>This is an archive of those conversations. If you would like to catch one live, <a href="https://discord.gg/hmn" target="_blank">join the Discord!</a></p>
|
||||||
|
|
||||||
|
<p class="c--dim i">We're still working through our backlog of fishbowls, so not all of these are available yet. We'll publish them as we finish them.</p>
|
||||||
|
|
||||||
|
<div class="mt3 mw7">
|
||||||
|
{{ range .Fishbowls }}
|
||||||
|
<div class="br2 bg--dim pa3 mb2">
|
||||||
|
{{ if .Valid }}
|
||||||
|
<a href="{{ .Url }}"><h3 class="f4 ma0">{{ .Fishbowl.Title }}</h3></a>
|
||||||
|
{{ else }}
|
||||||
|
<h3 class="f4 ma0">{{ .Fishbowl.Title }}</h3>
|
||||||
|
{{ end }}
|
||||||
|
<div class="c--dim b">
|
||||||
|
{{ .Fishbowl.Month }} {{ .Fishbowl.Year }}
|
||||||
|
</div>
|
||||||
|
{{ with .Fishbowl.Description }}
|
||||||
|
<div class="mt2">{{ . }}</div>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="c--dim i">If you'd like to help us plan more fishbowls, join the discussion over on <a href="https://github.com/HandmadeNetwork/hmn_fishbowl/discussions/categories/ideas" target="_blank">GitHub</a>.</p>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
|
@ -0,0 +1 @@
|
||||||
|
Make sure to name these folders according to the URL slugs of the fishbowls. Otherwise, static files for fishbowls will not work.
|
After Width: | Height: | Size: 89 KiB |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#31373D" d="M32 5H4C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><circle fill="#31373D" cx="15.5" cy="12.5" r="1.5"/><circle fill="#31373D" cx="20.5" cy="12.5" r="1.5"/><ellipse fill="#292F33" cx="18" cy="15.5" rx="1" ry=".5"/><path fill="#E6E7E8" d="M29.021 24.883c-.52-.189-1.093.078-1.282.598L20.923 23l6.816-2.48c.189.52.762.786 1.281.598.52-.19.787-.762.598-1.281-.188-.519-.762-.787-1.281-.599.519-.189.787-.762.598-1.281-.19-.52-.762-.787-1.281-.598-.519.188-.787.763-.598 1.282L18 21.937l-9.056-3.296c.189-.52-.078-1.094-.598-1.282-.52-.19-1.092.078-1.281.598-.189.519.078 1.093.598 1.281-.52-.189-1.093.079-1.281.599-.189.52.078 1.092.598 1.281.52.188 1.092-.078 1.281-.598L15.077 23l-6.815 2.48c-.189-.52-.763-.787-1.282-.598-.519.189-.786.762-.598 1.281.189.519.763.787 1.282.598-.52.19-.787.763-.598 1.282.188.52.763.786 1.281.598.519-.189.787-.763.598-1.282L18 24.065l9.055 3.295c-.19.52.079 1.093.598 1.282.519.188 1.093-.078 1.281-.598.189-.519-.078-1.093-.598-1.282.52.19 1.093-.078 1.282-.598.189-.519-.079-1.093-.597-1.281z"/><path fill="#E6E7E8" d="M18 7c-4 0-6 3.239-6 6 0 1.394.827 2.399 2 3.054V18c0 .553.448 1 1 1s1-.447 1-1v-1.216c.33.072.665.127 1 .162V18c0 .553.448 1 1 1s1-.447 1-1v-1.054c.335-.036.67-.09 1-.162V18c0 .553.447 1 1 1s1-.447 1-1v-1.946c1.173-.654 2-1.659 2-3.054 0-2.761-2-6-6-6zm-2.5 7c-.829 0-1.5 0-1.5-1.5 0-.829.671-1.5 1.5-1.5 1.5 0 1.5.671 1.5 1.5s-.671 1.5-1.5 1.5zm2.5 2c-.552 0-1-.224-1-.5s.448-.5 1-.5 1 .224 1 .5-.448.5-1 .5zm2.5-2c-.828 0-1.5-.671-1.5-1.5s0-1.5 1.5-1.5c.828 0 1.5.671 1.5 1.5 0 1.5-.672 1.5-1.5 1.5z"/></svg>
|
After Width: | Height: | Size: 1.7 KiB |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFDB5E" d="M34.956 17.916c0-.503-.12-.975-.321-1.404-1.341-4.326-7.619-4.01-16.549-4.221-1.493-.035-.639-1.798-.115-5.668.341-2.517-1.282-6.382-4.01-6.382-4.498 0-.171 3.548-4.148 12.322-2.125 4.688-6.875 2.062-6.875 6.771v10.719c0 1.833.18 3.595 2.758 3.885C8.195 34.219 7.633 36 11.238 36h18.044c1.838 0 3.333-1.496 3.333-3.334 0-.762-.267-1.456-.698-2.018 1.02-.571 1.72-1.649 1.72-2.899 0-.76-.266-1.454-.696-2.015 1.023-.57 1.725-1.649 1.725-2.901 0-.909-.368-1.733-.961-2.336.757-.611 1.251-1.535 1.251-2.581z"/><path fill="#EE9547" d="M23.02 21.249h8.604c1.17 0 2.268-.626 2.866-1.633.246-.415.109-.952-.307-1.199-.415-.247-.952-.108-1.199.307-.283.479-.806.775-1.361.775h-8.81c-.873 0-1.583-.71-1.583-1.583s.71-1.583 1.583-1.583H28.7c.483 0 .875-.392.875-.875s-.392-.875-.875-.875h-5.888c-1.838 0-3.333 1.495-3.333 3.333 0 1.025.475 1.932 1.205 2.544-.615.605-.998 1.445-.998 2.373 0 1.028.478 1.938 1.212 2.549-.611.604-.99 1.441-.99 2.367 0 1.12.559 2.108 1.409 2.713-.524.589-.852 1.356-.852 2.204 0 1.838 1.495 3.333 3.333 3.333h5.484c1.17 0 2.269-.625 2.867-1.632.247-.415.11-.952-.305-1.199-.416-.245-.953-.11-1.199.305-.285.479-.808.776-1.363.776h-5.484c-.873 0-1.583-.71-1.583-1.583s.71-1.583 1.583-1.583h6.506c1.17 0 2.27-.626 2.867-1.633.247-.416.11-.953-.305-1.199-.419-.251-.954-.11-1.199.305-.289.487-.799.777-1.363.777h-7.063c-.873 0-1.583-.711-1.583-1.584s.71-1.583 1.583-1.583h8.091c1.17 0 2.269-.625 2.867-1.632.247-.415.11-.952-.305-1.199-.417-.246-.953-.11-1.199.305-.289.486-.799.776-1.363.776H23.02c-.873 0-1.583-.71-1.583-1.583s.709-1.584 1.583-1.584z"/></svg>
|
After Width: | Height: | Size: 1.6 KiB |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFD983" d="M29 11.06c0 6.439-5 7.439-5 13.44 0 3.098-3.123 3.359-5.5 3.359-2.053 0-6.586-.779-6.586-3.361C11.914 18.5 7 17.5 7 11.06 7 5.029 12.285.14 18.083.14 23.883.14 29 5.029 29 11.06z"/><path fill="#CCD6DD" d="M22.167 32.5c0 .828-2.234 2.5-4.167 2.5-1.933 0-4.167-1.672-4.167-2.5 0-.828 2.233-.5 4.167-.5 1.933 0 4.167-.328 4.167.5z"/><path fill="#FFCC4D" d="M22.707 10.293c-.391-.391-1.023-.391-1.414 0L18 13.586l-3.293-3.293c-.391-.391-1.023-.391-1.414 0s-.391 1.023 0 1.414L17 15.414V26c0 .553.448 1 1 1s1-.447 1-1V15.414l3.707-3.707c.391-.391.391-1.023 0-1.414z"/><path fill="#99AAB5" d="M24 31c0 1.104-.896 2-2 2h-8c-1.104 0-2-.896-2-2v-6h12v6z"/><path fill="#CCD6DD" d="M11.999 32c-.48 0-.904-.347-.985-.836-.091-.544.277-1.06.822-1.15l12-2c.544-.098 1.06.277 1.15.822.091.544-.277 1.06-.822 1.15l-12 2c-.055.01-.111.014-.165.014zm0-4c-.48 0-.904-.347-.985-.836-.091-.544.277-1.06.822-1.15l12-2c.544-.097 1.06.277 1.15.822.091.544-.277 1.06-.822 1.15l-12 2c-.055.01-.111.014-.165.014z"/></svg>
|
After Width: | Height: | Size: 1.1 KiB |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#BB1A34" d="M22 0l-4 8.028-5-5.018v7.024L3 8.028l8 8.028-11 6.02h12L6 34.118l12-8.028 11 10.035-3-14.049h10l-8-6.021 8-9.031-12 3.01L22 0z"/><path fill="#FCAB40" d="M22.914 12.924l1.86-.467L30 11.146l-3.381 3.816-1.319 1.49 1.59 1.195 2.925 2.202h-5.918l.473 2.218 1.551 7.26-5.845-5.332-1.056-.964-1.188.795-5.24 3.506 2.406-4.828 1.322-2.655H9.564l3.759-2.059 2.145-1.172-1.727-1.735-3.044-3.053 3.221.646 2.186.439V8.686l1.45 1.455 1.794 1.799 1.133-2.276 1.273-2.556"/><path fill="#F5F8FA" d="M21.512 14.301l.767-.193 2.158-.541-1.396 1.576-.545.615.656.493 1.208.909h-2.443l.195.916.641 2.997-2.413-2.201-.437-.398-.49.328-2.163 1.448.993-1.994.546-1.096H16l1.553-.85.885-.484-.713-.716-1.257-1.261 1.329.267.903.181v-1.745l.599.6.74.743.468-.939.525-1.056"/></svg>
|
After Width: | Height: | Size: 842 B |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#BB1A34" d="M1.728 21c-.617 0-.953-.256-1.127-.471-.171-.211-.348-.585-.225-1.165L3.104 6.658l-1.714.097h-.013c-.517 0-.892-.168-1.127-.459-.22-.272-.299-.621-.221-.98.15-.702.883-1.286 1.667-1.329l4.008-.227c.078-.005.15-.008.217-.008.147 0 .536 0 .783.306.252.312.167.709.139.839L3.719 19.454c-.187.884-.919 1.489-1.866 1.542L1.728 21zm10.743-2c-1.439 0-2.635-.539-3.459-1.559-1.163-1.439-1.467-3.651-.878-6.397 1.032-4.812 4.208-8.186 7.902-8.395 1.59-.089 2.906.452 3.793 1.549 1.163 1.439 1.467 3.651.878 6.397-1.032 4.81-4.208 8.184-7.904 8.394-.112.008-.223.011-.332.011zm3.414-13.746l-.137.004c-1.94.111-3.555 2.304-4.32 5.866-.478 2.228-.381 3.899.272 4.707.297.368.717.555 1.249.555l.14-.004c1.94-.109 3.554-2.301 4.318-5.864.478-2.228.382-3.9-.27-4.708-.296-.369-.718-.556-1.252-.556zm11.591 12.107c-1.439 0-2.637-.539-3.462-1.56-1.163-1.439-1.467-3.651-.878-6.397 1.033-4.813 4.209-8.186 7.903-8.394 1.603-.09 2.903.453 3.79 1.549 1.163 1.439 1.467 3.651.878 6.396-1.031 4.809-4.206 8.183-7.902 8.396-.112.008-.221.01-.329.01zm3.411-13.747l-.136.004c-1.941.111-3.556 2.304-4.32 5.865-.478 2.229-.381 3.901.272 4.708.297.368.719.555 1.251.555l.14-.004c1.939-.109 3.554-2.302 4.318-5.864.479-2.227.383-3.899-.27-4.707-.298-.37-.72-.557-1.255-.557zM11 35.001c-.81 0-1.572-.496-1.873-1.299-.388-1.034.136-2.187 1.17-2.575.337-.126 8.399-3.108 20.536-4.12 1.101-.096 2.067.727 2.159 1.827.092 1.101-.727 2.067-1.827 2.159-11.59.966-19.386 3.851-19.464 3.88-.23.086-.468.128-.701.128zM2.001 29c-.804 0-1.563-.488-1.868-1.283-.396-1.031.118-2.188 1.149-2.583.542-.209 13.516-5.126 32.612-6.131 1.113-.069 2.045.789 2.103 1.892.059 1.103-.789 2.045-1.892 2.103-18.423.97-31.261 5.821-31.389 5.87-.235.089-.477.132-.715.132z"/></svg>
|
After Width: | Height: | Size: 1.8 KiB |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#66757F" d="M4 5s0-1 1-1h6s1 0 1 1v2H4V5z"/><path fill="#31373D" d="M0 10s0-4 4-4h28s4 0 4 4v18s0 4-4 4H4s-4 0-4-4V10z"/><circle fill="#CCD6DD" cx="21" cy="19" r="10"/><circle fill="#31373D" cx="21" cy="19" r="8"/><circle fill="#3B88C3" cx="21" cy="19" r="5"/><circle fill="#FFF" cx="32.5" cy="9.5" r="1.5"/><path fill="#F5F8FA" d="M12 9.5c0 .829-.671 1.5-1.5 1.5h-5C4.671 11 4 10.329 4 9.5S4.671 8 5.5 8h5c.829 0 1.5.671 1.5 1.5z"/></svg>
|
After Width: | Height: | Size: 511 B |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#9AAAB4" d="M23.378 19.029C22.67 19.736 16.305 31.757.75 36c1.414-1.415 19.54-21.691 19.54-21.691l3.088 4.72z"/><path fill="#CCD6DD" d="M17.72 13.371C17.013 14.078 4.992 20.444.75 36l21.213-21.214-4.243-1.415z"/><path fill="#D99E82" d="M20.549 11.957c-.781.781-.655 2.174.283 3.112l.848.849c.938.937 2.33 1.063 3.112.282l7.778-7.778c.781-.781.654-2.174-.283-3.111l-.848-.848c-.938-.938-2.331-1.064-3.111-.283l-7.779 7.777z"/><path d="M28.892 12.1l-7.071-1.414-1.271 1.271c-.133.133-.23.288-.311.452l6.954 1.391 1.699-1.7zm-7.212 3.818c.938.938 2.331 1.063 3.112.282l.826-.826-5.328-1.065c.131.27.312.529.543.76l.847.849zm8.911-5.518l1.7-1.699-7.071-1.414-1.7 1.699zm2.423-3.793c-.107-.46-.346-.916-.727-1.297l-.848-.848c-.103-.103-.213-.192-.325-.275l-2.11-.422c-.252.084-.483.22-.676.414l-1.242 1.242 5.928 1.186z" fill="#BF6952"/><circle fill="#8A4633" cx="31.858" cy="4.896" r="4"/><path fill="#FFAC33" d="M16.306 9.836c.586-.586 1.536-.586 2.121 0l8.839 8.839c.586.586.586 1.536 0 2.121-.586.586-1.535.586-2.121 0l-8.839-8.839c-.586-.584-.586-1.535 0-2.121z"/><circle fill="#FFAC33" cx="27.266" cy="20.796" r="2.5"/><circle fill="#FFAC33" cx="16.306" cy="9.836" r="2.5"/><circle fill="#FFCC4D" cx="27.266" cy="20.796" r="1.5"/><circle fill="#FFCC4D" cx="16.306" cy="9.836" r="1.5"/><path fill="#FFAC33" d="M26.566 3.803c.417-.417 1.093-.417 1.509 0l4.865 4.866c.417.417.417 1.092 0 1.509-.417.417-1.092.417-1.509 0l-4.865-4.866c-.417-.416-.417-1.092 0-1.509z"/></svg>
|
After Width: | Height: | Size: 1.5 KiB |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFCC4D" d="M36 18c0 9.941-8.059 18-18 18-9.94 0-18-8.059-18-18C0 8.06 8.06 0 18 0c9.941 0 18 8.06 18 18"/><path fill="#664500" d="M28.457 17.797c-.06-.135-1.499-3.297-4.457-3.297-2.957 0-4.397 3.162-4.457 3.297-.092.207-.032.449.145.591.175.142.426.147.61.014.012-.009 1.262-.902 3.702-.902 2.426 0 3.674.881 3.702.901.088.066.194.099.298.099.11 0 .221-.037.312-.109.177-.142.238-.386.145-.594zm-12 0c-.06-.135-1.499-3.297-4.457-3.297-2.957 0-4.397 3.162-4.457 3.297-.092.207-.032.449.144.591.176.142.427.147.61.014.013-.009 1.262-.902 3.703-.902 2.426 0 3.674.881 3.702.901.088.066.194.099.298.099.11 0 .221-.037.312-.109.178-.142.237-.386.145-.594zM31 16c-.396 0-.772-.238-.929-.629-1.778-4.445-6.223-5.381-6.268-5.391-.541-.108-.893-.635-.784-1.177.108-.542.635-.891 1.177-.784.226.045 5.556 1.168 7.732 6.608.205.513-.045 1.095-.558 1.3-.12.05-.246.073-.37.073zM5 16c-.124 0-.249-.023-.371-.072-.513-.205-.762-.787-.557-1.3 2.176-5.44 7.506-6.563 7.732-6.608.543-.106 1.068.243 1.177.784.108.54-.242 1.066-.781 1.176-.185.038-4.506.98-6.271 5.391-.157.391-.533.629-.929.629zm13 6c-3.623 0-6.027-.422-9-1-.679-.131-2 0-2 2 0 4 4.595 9 11 9 6.404 0 11-5 11-9 0-2-1.321-2.132-2-2-2.973.578-5.377 1-9 1z"/><path fill="#FFF" d="M9 23s3 1 9 1 9-1 9-1-2 4-9 4-9-4-9-4z"/><path fill="#5DADEC" d="M10.847 28.229c-.68 2.677-3.4 4.295-6.077 3.615-2.676-.679-4.295-3.399-3.616-6.076.679-2.677 6.337-8.708 7.307-8.462.97.247 3.065 8.247 2.386 10.923zm14.286 0c.68 2.677 3.4 4.295 6.077 3.615 2.677-.679 4.296-3.399 3.616-6.076-.68-2.677-6.338-8.708-7.308-8.462-.968.247-3.064 8.247-2.385 10.923z"/></svg>
|
After Width: | Height: | Size: 1.6 KiB |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFCC4D" d="M36 18c0 9.941-8.059 18-18 18-9.94 0-18-8.059-18-18C0 8.06 8.06 0 18 0c9.941 0 18 8.06 18 18"/><path fill="#664500" d="M28.457 17.797c-.06-.135-1.499-3.297-4.457-3.297-2.957 0-4.397 3.162-4.457 3.297-.092.207-.032.449.145.591.175.142.426.147.61.014.012-.009 1.262-.902 3.702-.902 2.426 0 3.674.881 3.702.901.088.066.194.099.298.099.11 0 .221-.037.312-.109.177-.142.238-.386.145-.594zm-12 0c-.06-.135-1.499-3.297-4.457-3.297-2.957 0-4.397 3.162-4.457 3.297-.092.207-.032.449.144.591.176.142.427.147.61.014.013-.009 1.262-.902 3.703-.902 2.426 0 3.674.881 3.702.901.088.066.194.099.298.099.11 0 .221-.037.312-.109.178-.142.237-.386.145-.594zM18 22c-3.623 0-6.027-.422-9-1-.679-.131-2 0-2 2 0 4 4.595 9 11 9 6.404 0 11-5 11-9 0-2-1.321-2.132-2-2-2.973.578-5.377 1-9 1z"/><path fill="#FFF" d="M9 23s3 1 9 1 9-1 9-1-2 4-9 4-9-4-9-4z"/></svg>
|
After Width: | Height: | Size: 920 B |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><circle fill="#FFCB4C" cx="18" cy="17.018" r="17"/><path fill="#65471B" d="M14.524 21.036c-.145-.116-.258-.274-.312-.464-.134-.46.13-.918.59-1.021 4.528-1.021 7.577 1.363 7.706 1.465.384.306.459.845.173 1.205-.286.358-.828.401-1.211.097-.11-.084-2.523-1.923-6.182-1.098-.274.061-.554-.016-.764-.184z"/><ellipse fill="#65471B" cx="13.119" cy="11.174" rx="2.125" ry="2.656"/><ellipse fill="#65471B" cx="24.375" cy="12.236" rx="2.125" ry="2.656"/><path fill="#F19020" d="M17.276 35.149s1.265-.411 1.429-1.352c.173-.972-.624-1.167-.624-1.167s1.041-.208 1.172-1.376c.123-1.101-.861-1.363-.861-1.363s.97-.4 1.016-1.539c.038-.959-.995-1.428-.995-1.428s5.038-1.221 5.556-1.341c.516-.12 1.32-.615 1.069-1.694-.249-1.08-1.204-1.118-1.697-1.003-.494.115-6.744 1.566-8.9 2.068l-1.439.334c-.54.127-.785-.11-.404-.512.508-.536.833-1.129.946-2.113.119-1.035-.232-2.313-.433-2.809-.374-.921-1.005-1.649-1.734-1.899-1.137-.39-1.945.321-1.542 1.561.604 1.854.208 3.375-.833 4.293-2.449 2.157-3.588 3.695-2.83 6.973.828 3.575 4.377 5.876 7.952 5.048l3.152-.681z"/><path fill="#65471B" d="M9.296 6.351c-.164-.088-.303-.224-.391-.399-.216-.428-.04-.927.393-1.112 4.266-1.831 7.699-.043 7.843.034.433.231.608.747.391 1.154-.216.405-.74.546-1.173.318-.123-.063-2.832-1.432-6.278.047-.257.109-.547.085-.785-.042zm12.135 3.75c-.156-.098-.286-.243-.362-.424-.187-.442.023-.927.468-1.084 4.381-1.536 7.685.48 7.823.567.415.26.555.787.312 1.178-.242.39-.776.495-1.191.238-.12-.072-2.727-1.621-6.267-.379-.266.091-.553.046-.783-.096z"/></svg>
|
After Width: | Height: | Size: 1.5 KiB |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#EF9645" d="M26.992 19.016c-.255-.255-.799-.611-1.44-.962l-1.911-2-2.113 2h-.58l-2.509-3.634c-1.379.01-2.497 1.136-2.487 2.515l-3.556-2.112c-.817.364-1.389 1.18-1.389 2.133v.96l-4 4.168.016 2.185 9.984 10.729S27.525 19.71 27.55 19.74c-.129-.223-.513-.702-.558-.724z"/><g fill="#FFDC5D"><path d="M25.552 5.81c0-1.107-.906-2.013-2.013-2.013-1.107 0-2.013.906-2.013 2.013v12.245h4.025V5.81zm-4.605 12.244V16.01c-.008-1.103-.909-1.991-2.012-1.983-1.103.008-1.991.909-1.983 2.012l.012 2.016h3.983zM8.916 16h.168c1.059 0 1.916.858 1.916 1.917v4.166C11 23.142 10.143 24 9.084 24h-.168C7.857 24 7 23.142 7 22.083v-4.166C7 16.858 7.857 16 8.916 16zm6.918 2.96l-.056.062C15.304 19.551 15 20.233 15 21c0 .063.013.123.018.185.044.678.308 1.292.728 1.774-.071.129-.163.243-.259.353-.366.417-.89.688-1.487.688-1.104 0-2-.896-2-2v-6c0-.441.147-.845.389-1.176.364-.497.947-.824 1.611-.824 1.104 0 2 .896 2 2v2.778c-.061.055-.109.123-.166.182z"/><path d="M9.062 25c1.024 0 1.925-.526 2.45-1.322.123.183.271.346.431.497 1.185 1.115 3.034 1.044 4.167-.086.152-.152.303-.305.419-.488l-.003-.003C16.727 23.713 17 24 18 24h2.537c-.37.279-.708.623-1.024 1-1.228 1.467-2.013 3.606-2.013 6 0 .276.224.5.5.5s.5-.224.5-.5c0-2.548.956-4.775 2.377-6 .732-.631 1.584-1 2.498-1 .713.079.847-1 .125-1H18c-1.104 0-2-.896-2-2s.896-2 2-2h8c.858 0 1.66.596 1.913 1.415L29 24c.103.335.479 1.871.411 2.191C29.411 31 24.715 36 19 36c-6.537 0-11.844-5.231-11.986-11.734l.014.01c.515.445 1.176.724 1.91.724h.124z"/></g></svg>
|
After Width: | Height: | Size: 1.5 KiB |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><circle fill="#31373D" cx="18" cy="18" r="18"/></svg>
|
After Width: | Height: | Size: 113 B |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><circle fill="#BE1931" cx="18" cy="32" r="3"/><path fill="#BE1931" d="M21 24c0 1.657-1.344 3-3 3-1.657 0-3-1.343-3-3V5c0-1.657 1.343-3 3-3 1.656 0 3 1.343 3 3v19z"/></svg>
|
After Width: | Height: | Size: 231 B |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#DD2E44" d="M35.885 11.833c0-5.45-4.418-9.868-9.867-9.868-3.308 0-6.227 1.633-8.018 4.129-1.791-2.496-4.71-4.129-8.017-4.129-5.45 0-9.868 4.417-9.868 9.868 0 .772.098 1.52.266 2.241C1.751 22.587 11.216 31.568 18 34.034c6.783-2.466 16.249-11.447 17.617-19.959.17-.721.268-1.469.268-2.242z"/></svg>
|
After Width: | Height: | Size: 368 B |
After Width: | Height: | Size: 415 KiB |
After Width: | Height: | Size: 9.6 KiB |
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 8.7 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 194 KiB |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFDB5E" d="M34.956 17.916c0-.503-.12-.975-.321-1.404-1.341-4.326-7.619-4.01-16.549-4.221-1.493-.035-.639-1.798-.115-5.668.341-2.517-1.282-6.382-4.01-6.382-4.498 0-.171 3.548-4.148 12.322-2.125 4.688-6.875 2.062-6.875 6.771v10.719c0 1.833.18 3.595 2.758 3.885C8.195 34.219 7.633 36 11.238 36h18.044c1.838 0 3.333-1.496 3.333-3.334 0-.762-.267-1.456-.698-2.018 1.02-.571 1.72-1.649 1.72-2.899 0-.76-.266-1.454-.696-2.015 1.023-.57 1.725-1.649 1.725-2.901 0-.909-.368-1.733-.961-2.336.757-.611 1.251-1.535 1.251-2.581z"/><path fill="#EE9547" d="M23.02 21.249h8.604c1.17 0 2.268-.626 2.866-1.633.246-.415.109-.952-.307-1.199-.415-.247-.952-.108-1.199.307-.283.479-.806.775-1.361.775h-8.81c-.873 0-1.583-.71-1.583-1.583s.71-1.583 1.583-1.583H28.7c.483 0 .875-.392.875-.875s-.392-.875-.875-.875h-5.888c-1.838 0-3.333 1.495-3.333 3.333 0 1.025.475 1.932 1.205 2.544-.615.605-.998 1.445-.998 2.373 0 1.028.478 1.938 1.212 2.549-.611.604-.99 1.441-.99 2.367 0 1.12.559 2.108 1.409 2.713-.524.589-.852 1.356-.852 2.204 0 1.838 1.495 3.333 3.333 3.333h5.484c1.17 0 2.269-.625 2.867-1.632.247-.415.11-.952-.305-1.199-.416-.245-.953-.11-1.199.305-.285.479-.808.776-1.363.776h-5.484c-.873 0-1.583-.71-1.583-1.583s.71-1.583 1.583-1.583h6.506c1.17 0 2.27-.626 2.867-1.633.247-.416.11-.953-.305-1.199-.419-.251-.954-.11-1.199.305-.289.487-.799.777-1.363.777h-7.063c-.873 0-1.583-.711-1.583-1.584s.71-1.583 1.583-1.583h8.091c1.17 0 2.269-.625 2.867-1.632.247-.415.11-.952-.305-1.199-.417-.246-.953-.11-1.199.305-.289.486-.799.776-1.363.776H23.02c-.873 0-1.583-.71-1.583-1.583s.709-1.584 1.583-1.584z"/></svg>
|
After Width: | Height: | Size: 1.6 KiB |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#BB1A34" d="M1.728 21c-.617 0-.953-.256-1.127-.471-.171-.211-.348-.585-.225-1.165L3.104 6.658l-1.714.097h-.013c-.517 0-.892-.168-1.127-.459-.22-.272-.299-.621-.221-.98.15-.702.883-1.286 1.667-1.329l4.008-.227c.078-.005.15-.008.217-.008.147 0 .536 0 .783.306.252.312.167.709.139.839L3.719 19.454c-.187.884-.919 1.489-1.866 1.542L1.728 21zm10.743-2c-1.439 0-2.635-.539-3.459-1.559-1.163-1.439-1.467-3.651-.878-6.397 1.032-4.812 4.208-8.186 7.902-8.395 1.59-.089 2.906.452 3.793 1.549 1.163 1.439 1.467 3.651.878 6.397-1.032 4.81-4.208 8.184-7.904 8.394-.112.008-.223.011-.332.011zm3.414-13.746l-.137.004c-1.94.111-3.555 2.304-4.32 5.866-.478 2.228-.381 3.899.272 4.707.297.368.717.555 1.249.555l.14-.004c1.94-.109 3.554-2.301 4.318-5.864.478-2.228.382-3.9-.27-4.708-.296-.369-.718-.556-1.252-.556zm11.591 12.107c-1.439 0-2.637-.539-3.462-1.56-1.163-1.439-1.467-3.651-.878-6.397 1.033-4.813 4.209-8.186 7.903-8.394 1.603-.09 2.903.453 3.79 1.549 1.163 1.439 1.467 3.651.878 6.396-1.031 4.809-4.206 8.183-7.902 8.396-.112.008-.221.01-.329.01zm3.411-13.747l-.136.004c-1.941.111-3.556 2.304-4.32 5.865-.478 2.229-.381 3.901.272 4.708.297.368.719.555 1.251.555l.14-.004c1.939-.109 3.554-2.302 4.318-5.864.479-2.227.383-3.899-.27-4.707-.298-.37-.72-.557-1.255-.557zM11 35.001c-.81 0-1.572-.496-1.873-1.299-.388-1.034.136-2.187 1.17-2.575.337-.126 8.399-3.108 20.536-4.12 1.101-.096 2.067.727 2.159 1.827.092 1.101-.727 2.067-1.827 2.159-11.59.966-19.386 3.851-19.464 3.88-.23.086-.468.128-.701.128zM2.001 29c-.804 0-1.563-.488-1.868-1.283-.396-1.031.118-2.188 1.149-2.583.542-.209 13.516-5.126 32.612-6.131 1.113-.069 2.045.789 2.103 1.892.059 1.103-.789 2.045-1.892 2.103-18.423.97-31.261 5.821-31.389 5.87-.235.089-.477.132-.715.132z"/></svg>
|
After Width: | Height: | Size: 1.8 KiB |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFCC4D" d="M36 18c0 9.941-8.059 18-18 18-9.94 0-18-8.059-18-18C0 8.06 8.06 0 18 0c9.941 0 18 8.06 18 18"/><path fill="#664500" d="M28.457 17.797c-.06-.135-1.499-3.297-4.457-3.297-2.957 0-4.397 3.162-4.457 3.297-.092.207-.032.449.145.591.175.142.426.147.61.014.012-.009 1.262-.902 3.702-.902 2.426 0 3.674.881 3.702.901.088.066.194.099.298.099.11 0 .221-.037.312-.109.177-.142.238-.386.145-.594zm-12 0c-.06-.135-1.499-3.297-4.457-3.297-2.957 0-4.397 3.162-4.457 3.297-.092.207-.032.449.144.591.176.142.427.147.61.014.013-.009 1.262-.902 3.703-.902 2.426 0 3.674.881 3.702.901.088.066.194.099.298.099.11 0 .221-.037.312-.109.178-.142.237-.386.145-.594zM18 22c-3.623 0-6.027-.422-9-1-.679-.131-2 0-2 2 0 4 4.595 9 11 9 6.404 0 11-5 11-9 0-2-1.321-2.132-2-2-2.973.578-5.377 1-9 1z"/><path fill="#FFF" d="M9 23s3 1 9 1 9-1 9-1-2 4-9 4-9-4-9-4z"/></svg>
|
After Width: | Height: | Size: 920 B |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFCC4D" d="M36 18c0 9.941-8.059 18-18 18-9.94 0-18-8.059-18-18C0 8.06 8.06 0 18 0c9.941 0 18 8.06 18 18"/><path fill="#664500" d="M28.457 17.797c-.06-.135-1.499-3.297-4.457-3.297-2.957 0-4.397 3.162-4.457 3.297-.092.207-.032.449.145.591.175.142.426.147.61.014.012-.009 1.262-.902 3.702-.902 2.426 0 3.674.881 3.702.901.088.066.194.099.298.099.11 0 .221-.037.312-.109.177-.142.238-.386.145-.594zm-12 0c-.06-.135-1.499-3.297-4.457-3.297-2.957 0-4.397 3.162-4.457 3.297-.092.207-.032.449.144.591.176.142.427.147.61.014.013-.009 1.262-.902 3.703-.902 2.426 0 3.674.881 3.702.901.088.066.194.099.298.099.11 0 .221-.037.312-.109.178-.142.237-.386.145-.594zM18 22c-3.623 0-6.027-.422-9-1-.679-.131-2 0-2 2 0 4 4.595 9 11 9 6.404 0 11-5 11-9 0-2-1.321-2.132-2-2-2.973.578-5.377 1-9 1z"/><path fill="#FFF" d="M9 23s3 1 9 1 9-1 9-1-2 4-9 4-9-4-9-4z"/><path fill="#5DADEC" d="M35 11c0 2.762-2.238 5-5 5s-5-2.238-5-5 4-10 5-10 5 7.238 5 10z"/></svg>
|
After Width: | Height: | Size: 1010 B |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><circle fill="#AA8DD8" cx="18" cy="18" r="18"/><path fill="#AA8DD8" d="M10 4C7.42 4 4.369 1.534 3.414.586 2.843.014 1.981-.157 1.235.153.487.462 0 1.191 0 2c0 3.459 1.672 10 8 10 .757 0 1.45-.428 1.789-1.106l2-4c.31-.62.277-1.356-.088-1.946C11.337 4.359 10.693 4 10 4zM34.766.153c-.75-.311-1.607-.139-2.18.434C31.7 1.472 28.589 4 26 4c-.693 0-1.337.359-1.701.949-.364.589-.397 1.326-.088 1.946l2 4C26.55 11.572 27.242 12 28 12c6.328 0 8-6.541 8-10 0-.809-.487-1.538-1.234-1.847z"/><path fill="#553986" d="M27.335 25.629c-.178-.161-.444-.171-.635-.029-.039.029-3.922 2.9-8.7 2.9-4.766 0-8.662-2.871-8.7-2.9-.191-.142-.457-.13-.635.029-.177.16-.217.424-.094.628C8.7 26.472 11.788 31.5 18 31.5s9.301-5.028 9.429-5.243c.123-.205.084-.468-.094-.628zm-11.628-7.336C12.452 15.038 7.221 15 7 15c-.552 0-.999.447-.999.998-.001.552.446 1.001.998 1.002.029 0 1.925.022 3.983.737-.593.64-.982 1.634-.982 2.763 0 1.934 1.119 3.5 2.5 3.5s2.5-1.566 2.5-3.5c0-.174-.019-.34-.037-.507.013 0 .025.007.037.007.256 0 .512-.098.707-.293.391-.391.391-1.023 0-1.414zM29 15c-.221 0-5.451.038-8.707 3.293-.391.391-.391 1.023 0 1.414.195.195.451.293.707.293.013 0 .024-.007.036-.007-.016.167-.036.333-.036.507 0 1.934 1.119 3.5 2.5 3.5s2.5-1.566 2.5-3.5c0-1.129-.389-2.123-.982-2.763 2.058-.715 3.954-.737 3.984-.737.551-.001.998-.45.997-1.002-.001-.551-.447-.998-.999-.998z"/></svg>
|
After Width: | Height: | Size: 1.4 KiB |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFCC4D" d="M36 18c0 9.941-8.059 18-18 18-9.94 0-18-8.059-18-18C0 8.06 8.06 0 18 0c9.941 0 18 8.06 18 18"/><ellipse fill="#66471B" cx="11.5" cy="14.5" rx="2.5" ry="3.5"/><ellipse fill="#66471B" cx="24.5" cy="14.5" rx="2.5" ry="3.5"/><path fill="#66471B" d="M7 21.262c0 3.964 4.596 9 11 9s11-5 11-9c0 0-10.333 2.756-22 0z"/><path fill="#E8596E" d="M18.545 23.604l-1.091-.005c-3.216-.074-5.454-.596-5.454-.596v6.961c0 3 2 6 6 6s6-3 6-6v-6.92c-1.922.394-3.787.542-5.455.56z"/><path fill="#DD2F45" d="M18 31.843c.301 0 .545-.244.545-.545v-7.694l-1.091-.005v7.699c.001.301.245.545.546.545z"/></svg>
|
After Width: | Height: | Size: 665 B |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><circle fill="#FFCC4D" cx="18" cy="18" r="18"/><path fill="#664500" d="M10.515 23.621C10.56 23.8 11.683 28 18 28c6.318 0 7.44-4.2 7.485-4.379.055-.217-.043-.442-.237-.554-.195-.111-.439-.078-.6.077C24.629 23.163 22.694 25 18 25s-6.63-1.837-6.648-1.855C11.256 23.05 11.128 23 11 23c-.084 0-.169.021-.246.064-.196.112-.294.339-.239.557z"/><ellipse fill="#664500" cx="12" cy="13.5" rx="2.5" ry="3.5"/><ellipse fill="#664500" cx="24" cy="13.5" rx="2.5" ry="3.5"/></svg>
|
After Width: | Height: | Size: 525 B |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><circle fill="#FFCB4C" cx="18" cy="17.018" r="17"/><path fill="#65471B" d="M14.524 21.036c-.145-.116-.258-.274-.312-.464-.134-.46.13-.918.59-1.021 4.528-1.021 7.577 1.363 7.706 1.465.384.306.459.845.173 1.205-.286.358-.828.401-1.211.097-.11-.084-2.523-1.923-6.182-1.098-.274.061-.554-.016-.764-.184z"/><ellipse fill="#65471B" cx="13.119" cy="11.174" rx="2.125" ry="2.656"/><ellipse fill="#65471B" cx="24.375" cy="12.236" rx="2.125" ry="2.656"/><path fill="#F19020" d="M17.276 35.149s1.265-.411 1.429-1.352c.173-.972-.624-1.167-.624-1.167s1.041-.208 1.172-1.376c.123-1.101-.861-1.363-.861-1.363s.97-.4 1.016-1.539c.038-.959-.995-1.428-.995-1.428s5.038-1.221 5.556-1.341c.516-.12 1.32-.615 1.069-1.694-.249-1.08-1.204-1.118-1.697-1.003-.494.115-6.744 1.566-8.9 2.068l-1.439.334c-.54.127-.785-.11-.404-.512.508-.536.833-1.129.946-2.113.119-1.035-.232-2.313-.433-2.809-.374-.921-1.005-1.649-1.734-1.899-1.137-.39-1.945.321-1.542 1.561.604 1.854.208 3.375-.833 4.293-2.449 2.157-3.588 3.695-2.83 6.973.828 3.575 4.377 5.876 7.952 5.048l3.152-.681z"/><path fill="#65471B" d="M9.296 6.351c-.164-.088-.303-.224-.391-.399-.216-.428-.04-.927.393-1.112 4.266-1.831 7.699-.043 7.843.034.433.231.608.747.391 1.154-.216.405-.74.546-1.173.318-.123-.063-2.832-1.432-6.278.047-.257.109-.547.085-.785-.042zm12.135 3.75c-.156-.098-.286-.243-.362-.424-.187-.442.023-.927.468-1.084 4.381-1.536 7.685.48 7.823.567.415.26.555.787.312 1.178-.242.39-.776.495-1.191.238-.12-.072-2.727-1.621-6.267-.379-.266.091-.553.046-.783-.096z"/></svg>
|
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 100 B |
|
@ -73,6 +73,7 @@
|
||||||
<a>Media <div class="dib svgicon ml1">{{ svg "chevron-down-thick" }}</div></a>
|
<a>Media <div class="dib svgicon ml1">{{ svg "chevron-down-thick" }}</div></a>
|
||||||
<div class="submenu b--theme-dark">
|
<div class="submenu b--theme-dark">
|
||||||
<a href="{{ .Header.PodcastUrl }}">Podcast</a>
|
<a href="{{ .Header.PodcastUrl }}">Podcast</a>
|
||||||
|
<a href="{{ .Header.FishbowlUrl }}">Fishbowls</a>
|
||||||
<a href="https://handmadedev.show/" target="_blank">Handmade Dev Show</a>
|
<a href="https://handmadedev.show/" target="_blank">Handmade Dev Show</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -90,7 +91,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="dn flex-ns items-center f3">
|
<div class="dn flex-ns items-center f3">
|
||||||
<a class="svgicon svgicon-nofix" href="https://twitter.com/handmade_net/" target="_blank">{{ svg "twitter" }}</a>
|
<a class="svgicon svgicon-nofix" href="https://twitter.com/handmade_net/" target="_blank">{{ svg "twitter" }}</a>
|
||||||
<a class="svgicon svgicon-nofix ml2" href="https://discord.gg/hxWxDee" target="_blank">{{ svg "discord" }}</a>
|
<a class="svgicon svgicon-nofix ml2" href="https://discord.gg/hmn" target="_blank">{{ svg "discord" }}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
|
@ -169,7 +169,7 @@
|
||||||
<div id="welcome-actions" class="flex flex-column flex-row-ns justify-center">
|
<div id="welcome-actions" class="flex flex-column flex-row-ns justify-center">
|
||||||
<a class="ba b--white br2 pa3 ph4-ns" href="{{ .ManifestoUrl }}">Read our manifesto</a>
|
<a class="ba b--white br2 pa3 ph4-ns" href="{{ .ManifestoUrl }}">Read our manifesto</a>
|
||||||
<a class="ba b--white br2 pa3 ph4-ns mt3 mt0-ns ml3-ns" href="{{ .Header.ProjectIndexUrl }}">View Handmade projects</a>
|
<a class="ba b--white br2 pa3 ph4-ns mt3 mt0-ns ml3-ns" href="{{ .Header.ProjectIndexUrl }}">View Handmade projects</a>
|
||||||
<a class="ba b--white br2 pa3 ph4-ns mt3 mt0-ns ml3-ns" target="_blank" href="https://discord.gg/hxWxDee">Join our Discord</a>
|
<a class="ba b--white br2 pa3 ph4-ns mt3 mt0-ns ml3-ns" target="_blank" href="https://discord.gg/hmn">Join our Discord</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -220,7 +220,7 @@
|
||||||
<h2>Community Showcase</h2>
|
<h2>Community Showcase</h2>
|
||||||
<div class="bg--card pa3 br3">
|
<div class="bg--card pa3 br3">
|
||||||
<div class="mb3">
|
<div class="mb3">
|
||||||
This is a selection of recent work done by community members. Want to participate? <a href="https://discord.gg/hxWxDee" target="_blank">Join us on Discord.</a>
|
This is a selection of recent work done by community members. Want to participate? <a href="https://discord.gg/hmn" target="_blank">Join us on Discord.</a>
|
||||||
</div>
|
</div>
|
||||||
<div id="showcase-container"></div>
|
<div id="showcase-container"></div>
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -243,7 +243,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div id="actions" class="flex justify-center">
|
<div id="actions" class="flex justify-center">
|
||||||
<a class="ba b--white br2 pv2 pv3-ns ph3 ph4-ns" target="_blank" href="https://handmade.network/forums/jam">See the submissions</a>
|
<a class="ba b--white br2 pv2 pv3-ns ph3 ph4-ns" target="_blank" href="https://handmade.network/forums/jam">See the submissions</a>
|
||||||
<a class="ba b--white br2 pv2 pv3-ns ph3 ph4-ns ml3" target="_blank" href="https://discord.gg/hxWxDee">Join the Discord</a>
|
<a class="ba b--white br2 pv2 pv3-ns ph3 ph4-ns ml3" target="_blank" href="https://discord.gg/hmn">Join the Discord</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -263,7 +263,7 @@
|
||||||
<div class="section mw8 margin-center ph3 ph4-l">
|
<div class="section mw8 margin-center ph3 ph4-l">
|
||||||
<h2>Showcase</h2>
|
<h2>Showcase</h2>
|
||||||
<p>
|
<p>
|
||||||
These screenshots and videos were shared in #jam-showcase on our <a href="https://discord.gg/hxWxDee" target="_blank">Discord</a>. Join us!
|
These screenshots and videos were shared in #jam-showcase on our <a href="https://discord.gg/hmn" target="_blank">Discord</a>. Join us!
|
||||||
</p>
|
</p>
|
||||||
<div id="showcase-container" class="mw8 center-layout mh2 mh0-ns"></div>
|
<div id="showcase-container" class="mw8 center-layout mh2 mh0-ns"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"git.handmade.network/hmn/hmn/src/auth"
|
"git.handmade.network/hmn/hmn/src/auth"
|
||||||
"git.handmade.network/hmn/hmn/src/hmnurl"
|
"git.handmade.network/hmn/hmn/src/hmnurl"
|
||||||
"git.handmade.network/hmn/hmn/src/logging"
|
"git.handmade.network/hmn/hmn/src/logging"
|
||||||
|
"git.handmade.network/hmn/hmn/src/utils"
|
||||||
"github.com/Masterminds/sprig"
|
"github.com/Masterminds/sprig"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/teacat/noire"
|
"github.com/teacat/noire"
|
||||||
|
@ -26,10 +27,13 @@ const (
|
||||||
var templateFs embed.FS
|
var templateFs embed.FS
|
||||||
var Templates map[string]*template.Template
|
var Templates map[string]*template.Template
|
||||||
|
|
||||||
|
//go:embed src/fishbowls
|
||||||
|
var FishbowlFS embed.FS
|
||||||
|
|
||||||
func Init() {
|
func Init() {
|
||||||
Templates = make(map[string]*template.Template)
|
Templates = make(map[string]*template.Template)
|
||||||
|
|
||||||
files, _ := templateFs.ReadDir("src")
|
files := utils.Must1(templateFs.ReadDir("src"))
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
if hasSuffix(f.Name(), ".html") {
|
if hasSuffix(f.Name(), ".html") {
|
||||||
t := template.New(f.Name())
|
t := template.New(f.Name())
|
||||||
|
|
|
@ -49,6 +49,7 @@ type Header struct {
|
||||||
HMNHomepageUrl string
|
HMNHomepageUrl string
|
||||||
ProjectIndexUrl string
|
ProjectIndexUrl string
|
||||||
PodcastUrl string
|
PodcastUrl string
|
||||||
|
FishbowlUrl string
|
||||||
ForumsUrl string
|
ForumsUrl string
|
||||||
LibraryUrl string
|
LibraryUrl string
|
||||||
|
|
||||||
|
@ -337,7 +338,6 @@ type ImageSelectorData struct {
|
||||||
|
|
||||||
type Breadcrumb struct {
|
type Breadcrumb struct {
|
||||||
Name, Url string
|
Name, Url string
|
||||||
Current bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Pagination struct {
|
type Pagination struct {
|
||||||
|
|
|
@ -72,6 +72,7 @@ func getBaseData(c *RequestContext, title string, breadcrumbs []templates.Breadc
|
||||||
HMNHomepageUrl: hmnurl.BuildHomepage(),
|
HMNHomepageUrl: hmnurl.BuildHomepage(),
|
||||||
ProjectIndexUrl: hmnurl.BuildProjectIndex(1),
|
ProjectIndexUrl: hmnurl.BuildProjectIndex(1),
|
||||||
PodcastUrl: hmnurl.BuildPodcast(),
|
PodcastUrl: hmnurl.BuildPodcast(),
|
||||||
|
FishbowlUrl: hmnurl.BuildFishbowlIndex(),
|
||||||
ForumsUrl: hmnurl.HMNProjectContext.BuildForum(nil, 1),
|
ForumsUrl: hmnurl.HMNProjectContext.BuildForum(nil, 1),
|
||||||
LibraryUrl: hmnurl.BuildLibrary(),
|
LibraryUrl: hmnurl.BuildLibrary(),
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,247 @@
|
||||||
|
package website
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"html/template"
|
||||||
|
"io"
|
||||||
|
"io/fs"
|
||||||
|
"net/http"
|
||||||
|
"regexp"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.handmade.network/hmn/hmn/src/db"
|
||||||
|
"git.handmade.network/hmn/hmn/src/hmndata"
|
||||||
|
"git.handmade.network/hmn/hmn/src/hmnurl"
|
||||||
|
"git.handmade.network/hmn/hmn/src/models"
|
||||||
|
"git.handmade.network/hmn/hmn/src/oops"
|
||||||
|
"git.handmade.network/hmn/hmn/src/templates"
|
||||||
|
"git.handmade.network/hmn/hmn/src/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This will skip the common path prefix for fishbowl files.
|
||||||
|
// We unfortunately need to do this because we want to use http.FileServer,
|
||||||
|
// but _that_ needs an http.FS, but _that_ needs an fs.FS...
|
||||||
|
var fishbowlFS = utils.Must1(fs.Sub(templates.FishbowlFS, "src/fishbowls"))
|
||||||
|
var fishbowlHTTPFS = http.StripPrefix("/fishbowl", http.FileServer(http.FS(fishbowlFS)))
|
||||||
|
|
||||||
|
type fishbowlInfo struct {
|
||||||
|
Slug string
|
||||||
|
Title, Description string // The description is used for OpenGraph, so it must be plain text, no HTML.
|
||||||
|
Month time.Month
|
||||||
|
Year int
|
||||||
|
ContentsPath string
|
||||||
|
}
|
||||||
|
|
||||||
|
var fishbowls = [...]fishbowlInfo{
|
||||||
|
{
|
||||||
|
Slug: "internet-os",
|
||||||
|
Title: "The future of operating systems in an Internet world",
|
||||||
|
Description: `Despite the web's technical problems, it dominates software development today, largely due to its cross-platform support and ease of distribution. At the same time, our discussions about the future of programming tend to involve new "operating systems", but those discussions rarely take the Internet into account. What could future operating systems look like in a world defined by the Internet?`,
|
||||||
|
Month: time.May, Year: 2020,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Slug: "metaprogramming",
|
||||||
|
Title: "Compile-time introspection and metaprogramming",
|
||||||
|
Description: `Thanks to new languages like Zig and Jai, compile-time execution and metaprogramming are a popular topic of discussion in the community. This fishbowl explores metaprogramming in more detail, and discusses to what extent it is actually necessary, or just a waste of time.`,
|
||||||
|
Month: time.June, Year: 2020,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Slug: "lisp-jam",
|
||||||
|
Title: "Lessons from the Lisp Jam",
|
||||||
|
Description: `In the summer of 2020 we held a Lisp jam, where many community members made exploratory Lisp-inspired projects. We held this fishbowl as a recap, as a time for the participants to share what they learned and explore how those lessons relate to our day-to-day programming.`,
|
||||||
|
Month: time.August, Year: 2020,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Slug: "parallel-programming",
|
||||||
|
Title: "Approaches to parallel programming",
|
||||||
|
Description: `A discussion of many aspects of parallelism and concurrency in programming, and the pros and cons of different programming methodologies.`,
|
||||||
|
Month: time.November, Year: 2020,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Slug: "skimming",
|
||||||
|
Title: "Code skimmability as the root cause for bad code structure decisions", // real snappy, this one
|
||||||
|
Description: `Programmers tend to care a lot about "readability". This usually means having small classes, small functions, small files. This code might be "readable" at a glance, but this doesn't really help you understand the program—it's just "skimmable". How can we think about "readability" in a more productive way?`,
|
||||||
|
Month: time.January, Year: 2021,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Slug: "config",
|
||||||
|
Title: "How to design to avoid configuration",
|
||||||
|
Description: `Configuration sucks. How can we avoid it, while still making software that supports a wide range of behaviors? What is the essence of "configuration", and how can we identify it? How can we identify what is "bad config", and design our software to avoid it?`,
|
||||||
|
Month: time.March, Year: 2021,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Slug: "simplicity-performance",
|
||||||
|
Title: "The relationship of simplicity and performance",
|
||||||
|
Description: "In the community, we talk a lot about performance. We also talk a lot about having simple code—and the two feel somewhat intertwined. What relationship is there between simplicity and performance? Are there better ways to reason about \"simplicity\" with this in mind?",
|
||||||
|
Month: time.May, Year: 2021,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Slug: "teaching-software",
|
||||||
|
Title: "How software development is taught",
|
||||||
|
Description: "The Handmade Network exists because we are unhappy with the software status quo. To a large extent, this is because of how software development is taught. What are the good parts of software education today, what are the flaws, and how might we change things to improve the state of software?",
|
||||||
|
Month: time.June, Year: 2021,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Slug: "flexible-software",
|
||||||
|
Title: "How to design flexible software",
|
||||||
|
Description: "We previously held a fishbowl about how to design to avoid configuration. But when you can't avoid configuration, how do you do it well? And if we want our software to be flexible, what other options do we have besides configuration? What other ways are there to make software flexible?",
|
||||||
|
Month: time.December, Year: 2021,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Slug: "oop",
|
||||||
|
Title: "What, if anything, is OOP?",
|
||||||
|
Description: "Is object-oriented programming bad? Is it good? What even is it, anyway? This fishbowl explores OOP more carefully—what is the essence of it, what are the good parts, why did it take over the world, and why do we criticize it so much?",
|
||||||
|
Month: time.May, Year: 2022,
|
||||||
|
ContentsPath: "oop/OOP.html",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func FishbowlIndex(c *RequestContext) ResponseData {
|
||||||
|
type fishbowlTmpl struct {
|
||||||
|
Fishbowl fishbowlInfo
|
||||||
|
Url string
|
||||||
|
Valid bool
|
||||||
|
|
||||||
|
date time.Time
|
||||||
|
}
|
||||||
|
type tmpl struct {
|
||||||
|
templates.BaseData
|
||||||
|
Fishbowls []fishbowlTmpl
|
||||||
|
}
|
||||||
|
|
||||||
|
tmplData := tmpl{
|
||||||
|
BaseData: getBaseData(c, "Fishbowls", []templates.Breadcrumb{
|
||||||
|
{Name: "Fishbowls", Url: hmnurl.BuildFishbowlIndex()},
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
var fishbowlTmpls []fishbowlTmpl
|
||||||
|
for _, f := range fishbowls {
|
||||||
|
fishbowlTmpls = append(fishbowlTmpls, fishbowlTmpl{
|
||||||
|
Fishbowl: f,
|
||||||
|
Url: hmnurl.BuildFishbowl(f.Slug),
|
||||||
|
Valid: f.ContentsPath != "",
|
||||||
|
|
||||||
|
date: time.Date(f.Year, f.Month, 0, 0, 0, 0, 0, time.UTC),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
sort.Slice(fishbowlTmpls, func(i, j int) bool {
|
||||||
|
return fishbowlTmpls[j].date.Before(fishbowlTmpls[i].date) // reverse
|
||||||
|
})
|
||||||
|
tmplData.Fishbowls = fishbowlTmpls
|
||||||
|
|
||||||
|
var res ResponseData
|
||||||
|
err := res.WriteTemplate("fishbowl_index.html", tmplData, c.Perf)
|
||||||
|
if err != nil {
|
||||||
|
return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to render fishbowl index page"))
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func Fishbowl(c *RequestContext) ResponseData {
|
||||||
|
slug := c.PathParams["slug"]
|
||||||
|
var info fishbowlInfo
|
||||||
|
|
||||||
|
// Only serve up valid fishbowls (with content)
|
||||||
|
exists := false
|
||||||
|
for _, fishbowl := range fishbowls {
|
||||||
|
if fishbowl.Slug == slug && fishbowl.ContentsPath != "" {
|
||||||
|
exists = true
|
||||||
|
info = fishbowl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !exists {
|
||||||
|
return FourOhFour(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure trailing slash (it matters for relative URLs in the HTML)
|
||||||
|
if !strings.HasSuffix(c.URL().Path, "/") {
|
||||||
|
return c.Redirect(c.URL().Path+"/", http.StatusFound)
|
||||||
|
}
|
||||||
|
|
||||||
|
type FishbowlData struct {
|
||||||
|
templates.BaseData
|
||||||
|
Slug string
|
||||||
|
Info fishbowlInfo
|
||||||
|
Contents template.HTML
|
||||||
|
}
|
||||||
|
|
||||||
|
contentsFile := utils.Must1(fishbowlFS.Open(info.ContentsPath))
|
||||||
|
contents := string(utils.Must1(io.ReadAll(contentsFile)))
|
||||||
|
contents, err := linkifyDiscordContent(c, c.Conn, contents)
|
||||||
|
if err != nil {
|
||||||
|
return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to linkify fishbowl content"))
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpl := FishbowlData{
|
||||||
|
BaseData: getBaseData(c, info.Title, []templates.Breadcrumb{
|
||||||
|
{Name: "Fishbowls", Url: hmnurl.BuildFishbowlIndex()},
|
||||||
|
{Name: info.Title, Url: hmnurl.BuildFishbowl(slug)},
|
||||||
|
}),
|
||||||
|
Slug: slug,
|
||||||
|
Info: info,
|
||||||
|
Contents: template.HTML(contents),
|
||||||
|
}
|
||||||
|
tmpl.BaseData.OpenGraphItems = append(tmpl.BaseData.OpenGraphItems, templates.OpenGraphItem{
|
||||||
|
Property: "og:description",
|
||||||
|
Value: info.Description,
|
||||||
|
})
|
||||||
|
|
||||||
|
var res ResponseData
|
||||||
|
err = res.WriteTemplate("fishbowl.html", tmpl, c.Perf)
|
||||||
|
if err != nil {
|
||||||
|
return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to render fishbowl index page"))
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func FishbowlFiles(c *RequestContext) ResponseData {
|
||||||
|
var res ResponseData
|
||||||
|
fishbowlHTTPFS.ServeHTTP(&res, c.Req)
|
||||||
|
AddCORSHeaders(c, &res)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
var reFishbowlDiscordUserId = regexp.MustCompile(`data-user-id="(\d+)"`)
|
||||||
|
var reFishbowlDiscordAuthorHeader = regexp.MustCompile(`(?s:(<div class="chatlog__message">.*?)(<img class="chatlog__avatar".*?>)(.*?<span class="chatlog__author".*?data-user-id="(\d+)".*?>)(.*?)(</span>))`)
|
||||||
|
|
||||||
|
func linkifyDiscordContent(c *RequestContext, dbConn db.ConnOrTx, content string) (string, error) {
|
||||||
|
discordUserIdSet := make(map[string]struct{})
|
||||||
|
userIdMatches := reFishbowlDiscordUserId.FindAllStringSubmatch(content, -1)
|
||||||
|
for _, m := range userIdMatches {
|
||||||
|
discordUserIdSet[m[1]] = struct{}{}
|
||||||
|
}
|
||||||
|
discordUserIds := make([]string, 0, len(discordUserIdSet))
|
||||||
|
for id := range discordUserIdSet {
|
||||||
|
discordUserIds = append(discordUserIds, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
hmnUsers, err := hmndata.FetchUsers(c.Context(), dbConn, c.CurrentUser, hmndata.UsersQuery{
|
||||||
|
DiscordUserIDs: discordUserIds,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return reFishbowlDiscordAuthorHeader.ReplaceAllStringFunc(content, func(s string) string {
|
||||||
|
m := reFishbowlDiscordAuthorHeader.FindStringSubmatch(s)
|
||||||
|
discordUserID := m[4]
|
||||||
|
|
||||||
|
var matchingUser *models.User
|
||||||
|
for _, u := range hmnUsers {
|
||||||
|
if u.DiscordUser.UserID == discordUserID {
|
||||||
|
matchingUser = u
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if matchingUser == nil {
|
||||||
|
return s
|
||||||
|
} else {
|
||||||
|
link := fmt.Sprintf(`<a href="%s" target="_blank">`, hmnurl.BuildUserProfile(matchingUser.Username))
|
||||||
|
return m[1] + link + m[2] + "</a>" + m[3] + link + m[5] + "</a>" + m[6]
|
||||||
|
}
|
||||||
|
}), nil
|
||||||
|
}
|
|
@ -222,6 +222,10 @@ func NewWebsiteRoutes(longRequestContext context.Context, conn *pgxpool.Pool) ht
|
||||||
hmnOnly.GET(hmnurl.RegexPodcastEpisode, PodcastEpisode)
|
hmnOnly.GET(hmnurl.RegexPodcastEpisode, PodcastEpisode)
|
||||||
hmnOnly.GET(hmnurl.RegexPodcastRSS, PodcastRSS)
|
hmnOnly.GET(hmnurl.RegexPodcastRSS, PodcastRSS)
|
||||||
|
|
||||||
|
hmnOnly.GET(hmnurl.RegexFishbowlIndex, FishbowlIndex)
|
||||||
|
hmnOnly.GET(hmnurl.RegexFishbowl, Fishbowl)
|
||||||
|
hmnOnly.GET(hmnurl.RegexFishbowlFiles, FishbowlFiles)
|
||||||
|
|
||||||
hmnOnly.POST(hmnurl.RegexAPICheckUsername, csrfMiddleware(APICheckUsername))
|
hmnOnly.POST(hmnurl.RegexAPICheckUsername, csrfMiddleware(APICheckUsername))
|
||||||
|
|
||||||
hmnOnly.GET(hmnurl.RegexLibraryAny, LibraryNotPortedYet)
|
hmnOnly.GET(hmnurl.RegexLibraryAny, LibraryNotPortedYet)
|
||||||
|
|