mirror of
https://github.com/philomena-dev/philomena.git
synced 2024-11-30 14:57:59 +01:00
progress today
This commit is contained in:
parent
0de3d98c82
commit
f04666037c
46 changed files with 672 additions and 321 deletions
|
@ -32,7 +32,7 @@
|
||||||
@import "elements/form";
|
@import "elements/form";
|
||||||
@import "elements/heading";
|
@import "elements/heading";
|
||||||
@import "elements/input";
|
@import "elements/input";
|
||||||
@import "elements/interaction";
|
@import "elements/label";
|
||||||
@import "elements/layout";
|
@import "elements/layout";
|
||||||
@import "elements/list";
|
@import "elements/list";
|
||||||
@import "elements/media";
|
@import "elements/media";
|
||||||
|
@ -48,9 +48,11 @@
|
||||||
@import "views/footer";
|
@import "views/footer";
|
||||||
@import "views/header";
|
@import "views/header";
|
||||||
@import "views/image";
|
@import "views/image";
|
||||||
|
@import "views/interaction";
|
||||||
@import "views/markdown";
|
@import "views/markdown";
|
||||||
@import "views/metabar";
|
@import "views/metabar";
|
||||||
@import "views/pagination";
|
@import "views/pagination";
|
||||||
@import "views/staff";
|
@import "views/staff";
|
||||||
@import "views/statistics";
|
@import "views/statistics";
|
||||||
@import "views/tag";
|
@import "views/tag";
|
||||||
|
@import "views/user";
|
||||||
|
|
|
@ -51,13 +51,16 @@ $font-family-monospace: "Droid Sans Mono", monospace;
|
||||||
|
|
||||||
--media-container-width: 225px;
|
--media-container-width: 225px;
|
||||||
--media-tiny-container-width: 50px;
|
--media-tiny-container-width: 50px;
|
||||||
--media-small-container-width: 125px;
|
--media-small-container-width: 150px;
|
||||||
--media-medium-container-width: 250px;
|
--media-medium-container-width: 250px;
|
||||||
--media-large-container-width: 500px;
|
--media-large-container-width: 500px;
|
||||||
--media-full-container-width: 100%;
|
--media-full-container-width: 100%;
|
||||||
--media-featured-width: 358px;
|
--media-featured-width: 358px;
|
||||||
--media-header-height: 2rem;
|
--media-header-height: 2rem;
|
||||||
|
|
||||||
|
--badge-small-size: 1.1rem;
|
||||||
|
--badge-normal-size: 2rem;
|
||||||
|
|
||||||
--number-badge-size: 0.6rem;
|
--number-badge-size: 0.6rem;
|
||||||
--number-badge-padding: 0.1rem;
|
--number-badge-padding: 0.1rem;
|
||||||
--number-badge-border: 2px;
|
--number-badge-border: 2px;
|
||||||
|
|
|
@ -8,11 +8,11 @@
|
||||||
.button--$(type).button--important {
|
.button--$(type).button--important {
|
||||||
color: var(--text-color) !important;
|
color: var(--text-color) !important;
|
||||||
background: var(--$(type)-color);
|
background: var(--$(type)-color);
|
||||||
box-shadow: 0 -1px var(--$(type)-dark-color) inset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.button--$(type):hover {
|
.button--$(type):hover, .button--$(type):active, .button--$(type).selected {
|
||||||
background: var(--$(type)-muted-color) !important;
|
background: var(--$(type)-dark-color) !important;
|
||||||
|
border-radius: var(--border-radius-inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
.button__group--$(type) {
|
.button__group--$(type) {
|
||||||
|
@ -28,6 +28,7 @@
|
||||||
@mixin animated-transition;
|
@mixin animated-transition;
|
||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
background: var(--$(type)-color);
|
background: var(--$(type)-color);
|
||||||
|
border-radius: var(--border-radius-inner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,17 +41,18 @@
|
||||||
font-size: var(--font-size);
|
font-size: var(--font-size);
|
||||||
background: var(--primary-dark-color);
|
background: var(--primary-dark-color);
|
||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
border: 0;
|
|
||||||
border-radius: var(--border-radius-inner);
|
border-radius: var(--border-radius-inner);
|
||||||
padding: 0 var(--padding-small);
|
padding: 0 var(--padding-small);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
line-height: var(--button-height);
|
line-height: var(--button-height);
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
border-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button:hover {
|
.button:hover, .button:active {
|
||||||
@mixin animated-transition;
|
@mixin animated-transition;
|
||||||
background: var(--primary-muted-color);
|
background: var(--primary-dark-color);
|
||||||
|
border-radius: var(--border-radius-inner);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +72,6 @@
|
||||||
|
|
||||||
.button--important {
|
.button--important {
|
||||||
background: var(--primary-color);
|
background: var(--primary-color);
|
||||||
box-shadow: 0 -1px var(--primary-dark-color) inset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.button__row {
|
.button__row {
|
||||||
|
@ -85,7 +86,6 @@
|
||||||
.button__group, .button__group--single, .button__group--standalone {
|
.button__group, .button__group--single, .button__group--standalone {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
border: 0;
|
|
||||||
border-radius: var(--border-radius-inner);
|
border-radius: var(--border-radius-inner);
|
||||||
margin-right: var(--padding-normal);
|
margin-right: var(--padding-normal);
|
||||||
background: var(--secondary-dark-color);
|
background: var(--secondary-dark-color);
|
||||||
|
@ -126,6 +126,7 @@
|
||||||
.button__group--standalone a:hover {
|
.button__group--standalone a:hover {
|
||||||
@mixin animated-transition;
|
@mixin animated-transition;
|
||||||
background: var(--secondary-muted-color);
|
background: var(--secondary-muted-color);
|
||||||
|
border-radius: var(--border-radius-inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
.button--borderless {
|
.button--borderless {
|
||||||
|
@ -139,6 +140,7 @@
|
||||||
|
|
||||||
.block__header__buttons .button:hover {
|
.block__header__buttons .button:hover {
|
||||||
background: var(--primary-muted-color);
|
background: var(--primary-muted-color);
|
||||||
|
border-radius: var(--border-radius-inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin button-type primary;
|
@mixin button-type primary;
|
||||||
|
|
|
@ -67,6 +67,18 @@
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.flex--small-gap {
|
||||||
|
gap: var(--padding-small);
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex--normal-gap {
|
||||||
|
gap: var(--padding-normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex--large-gap {
|
||||||
|
gap: var(--padding-large);
|
||||||
|
}
|
||||||
|
|
||||||
.flex--start-bunched {
|
.flex--start-bunched {
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,36 @@ form .form--two-column > .field, form .form--two-column > li {
|
||||||
gap: var(--padding-normal);
|
gap: var(--padding-normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
form .form--three-items {
|
||||||
|
display: grid;
|
||||||
|
grid: inherit;
|
||||||
|
grid-template-columns: 1 / -1;
|
||||||
|
gap: var(--padding-normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
form .form--three-items > .field {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto 1fr;
|
||||||
|
grid-template-rows: 1fr auto;
|
||||||
|
gap: var(--padding-normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
form .form--three-items > .field > *:nth-child(1) {
|
||||||
|
grid-area: 1 / 1 / 2 / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
form .form--three-items > .field > *:nth-child(2) {
|
||||||
|
grid-area: 1 / 2 / 2 / 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
form .form--three-items > .field > *:nth-child(3) {
|
||||||
|
grid-area: 2 / 1 / 3 / 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
form .form--three-items select {
|
||||||
|
width: fit-content;
|
||||||
|
}
|
||||||
|
|
||||||
form .with-error {
|
form .with-error {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
26
assets/css/elements/label.css
Normal file
26
assets/css/elements/label.css
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
@define-mixin label-type $type {
|
||||||
|
.label--$(type) {
|
||||||
|
background-color: var(--$(type)-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
display: flex;
|
||||||
|
background: var(--primary-color);
|
||||||
|
padding: var(--padding-tiny) var(--padding-small);
|
||||||
|
border-radius: var(--border-radius-inner);
|
||||||
|
width: fit-content;
|
||||||
|
gap: var(--padding-tiny);
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label--block {
|
||||||
|
margin: var(--padding-small) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin label-type secondary;
|
||||||
|
@mixin label-type danger;
|
||||||
|
@mixin label-type warning;
|
||||||
|
@mixin label-type success;
|
||||||
|
@mixin label-type special;
|
||||||
|
@mixin label-type information;
|
38
assets/css/options/compatibility.css
Normal file
38
assets/css/options/compatibility.css
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/* An attempt to make stylesheets less broken on
|
||||||
|
* pre-2020 browsers like Chrome 67.
|
||||||
|
*
|
||||||
|
* Note: browsers newer than Chrome 84 will not need this.
|
||||||
|
*
|
||||||
|
* The main thing about those is that they don't support
|
||||||
|
* the "gap" property in flexboxes, so that has to be polyfilled
|
||||||
|
* with margin tags.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@import "common/measurements";
|
||||||
|
@import "common/mixins";
|
||||||
|
|
||||||
|
@define-mixin legacy-flex-gap $classname, $size {
|
||||||
|
.$(classname) > * {
|
||||||
|
margin-bottom: $(size);
|
||||||
|
margin-right: $(size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
header > *, nav.header__secondary > * {
|
||||||
|
margin-left: var(--padding-large);
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin if-mobile {
|
||||||
|
header > * {
|
||||||
|
margin-left: var(--padding-normal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin legacy-flex-gap block__header__buttons, var(--padding-normal);
|
||||||
|
@mixin legacy-flex-gap block__header--js-tabbed, var(--padding-normal);
|
||||||
|
@mixin legacy-flex-gap field, var(--padding-normal);
|
||||||
|
@mixin legacy-flex-gap horizontal-list, var(--padding-normal);
|
||||||
|
@mixin legacy-flex-gap communication-edit__actions, var(--padding-normal);
|
||||||
|
@mixin legacy-flex-gap header__link--user, var(--padding-normal);
|
||||||
|
@mixin legacy-flex-gap tag-list, var(--padding-small);
|
||||||
|
@mixin legacy-flex-gap tagsinput, var(--padding-small);
|
|
@ -4,7 +4,7 @@ $text-color: #e0e0e0;
|
||||||
$primary-color: #284371;
|
$primary-color: #284371;
|
||||||
$secondary-color: #546c99;
|
$secondary-color: #546c99;
|
||||||
$danger-color: #6d2a20;
|
$danger-color: #6d2a20;
|
||||||
$warning-color: #715227;
|
$warning-color: #6d421a;
|
||||||
$success-color: #25603e;
|
$success-color: #25603e;
|
||||||
$information-color: #1c606a;
|
$information-color: #1c606a;
|
||||||
$special-color: #65206e;
|
$special-color: #65206e;
|
||||||
|
|
92
assets/css/themes/dark-purple.css
Normal file
92
assets/css/themes/dark-purple.css
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
$background-color: #15121a;
|
||||||
|
$text-color: #e0e0e0;
|
||||||
|
|
||||||
|
$primary-color: #36274e;
|
||||||
|
$secondary-color: #785b99;
|
||||||
|
$danger-color: #6d2a20;
|
||||||
|
$warning-color: #715227;
|
||||||
|
$success-color: #25603e;
|
||||||
|
$information-color: #1c606a;
|
||||||
|
$special-color: #65206e;
|
||||||
|
|
||||||
|
$upvote-color: #5b9b26;
|
||||||
|
$downvote-color: #da3412;
|
||||||
|
$fave-color: #a18e27;
|
||||||
|
$comment-color: #b099dd;
|
||||||
|
$hide-color: #da3412;
|
||||||
|
|
||||||
|
$tag-default-color: #1b3c21;
|
||||||
|
$tag-error-color: #4f181d;
|
||||||
|
$tag-rating-color: #113456;
|
||||||
|
$tag-origin-color: #1d1858;
|
||||||
|
$tag-character-color: #193f47;
|
||||||
|
$tag-oc-color: #451f47;
|
||||||
|
$tag-species-color: #362118;
|
||||||
|
$tag-body-type-color: #393939;
|
||||||
|
$tag-content-fanmade-color: #622c4e;
|
||||||
|
$tag-content-official-color: #4b491c;
|
||||||
|
$tag-spoiler-color: #4f3811;
|
||||||
|
|
||||||
|
$spoiler-color: #0f0f0f;
|
||||||
|
|
||||||
|
@define-mixin tag-color $tagname, $color, $text-percentage: 35, $border-percentage: 15 {
|
||||||
|
--tag-$(tagname)-color: $(color);
|
||||||
|
--tag-$(tagname)-border-color: hsl(from $color h s calc(l + $border-percentage));
|
||||||
|
--tag-$(tagname)-text-color: hsl(from $color h s calc(l + $text-percentage));
|
||||||
|
}
|
||||||
|
|
||||||
|
@define-mixin type-color $type, $color {
|
||||||
|
--$(type)-color: $color;
|
||||||
|
--$(type)-border-color: hsl(from $color h calc(s - 20) calc(l + 10));
|
||||||
|
--$(type)-muted-color: hsl(from $color h calc(s - 10) calc(l - 7));
|
||||||
|
--$(type)-dark-color: hsl(from $color h calc(s - 30) calc(l - 11));
|
||||||
|
--$(type)-link-color: hsl(from $color h calc(s + 10) calc(l + 45));
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--background-color: $background-color;
|
||||||
|
--text-color: $text-color;
|
||||||
|
--text-light-color: $text-color;
|
||||||
|
|
||||||
|
--link-color: hsl(from $primary-color h calc(s + 10) calc(l + 50));
|
||||||
|
--link-hover-color: $text-color;
|
||||||
|
|
||||||
|
--primary-color: $primary-color;
|
||||||
|
--primary-border-color: hsl(from $primary-color h calc(s - 20) calc(l + 5));
|
||||||
|
--primary-muted-color: hsl(from $primary-color h calc(s - 10) calc(l - 5));
|
||||||
|
--primary-dark-color: hsl(from $primary-color h calc(s - 15) calc(l - 9));
|
||||||
|
--primary-link-color: var(--link-color); /* for consistency */
|
||||||
|
|
||||||
|
--secondary-color: $secondary-color;
|
||||||
|
--secondary-border-color: hsl(from $secondary-color h s calc(l + 5));
|
||||||
|
--secondary-muted-color: hsl(from $secondary-color h s calc(l - 17));
|
||||||
|
--secondary-dark-color: hsl(from $secondary-color h calc(s - 5) calc(l - 25));
|
||||||
|
--secondary-link-color: hsl(from $secondary-color h s calc(l + 40));
|
||||||
|
|
||||||
|
--upvote-color: $upvote-color;
|
||||||
|
--downvote-color: $downvote-color;
|
||||||
|
--fave-color: $fave-color;
|
||||||
|
--comment-color: $comment-color;
|
||||||
|
--hide-color: $hide-color;
|
||||||
|
|
||||||
|
--spoiler-color: $spoiler-color;
|
||||||
|
--spoiler-revealed-color: hsl(from $spoiler-color h s calc(l + 20));
|
||||||
|
|
||||||
|
@mixin type-color success, $success-color;
|
||||||
|
@mixin type-color warning, $warning-color;
|
||||||
|
@mixin type-color danger, $danger-color;
|
||||||
|
@mixin type-color information, $information-color;
|
||||||
|
@mixin type-color special, $special-color;
|
||||||
|
|
||||||
|
@mixin tag-color default, $tag-default-color;
|
||||||
|
@mixin tag-color error, $tag-error-color, 37;
|
||||||
|
@mixin tag-color rating, $tag-rating-color, 37;
|
||||||
|
@mixin tag-color origin, $tag-origin-color, 42;
|
||||||
|
@mixin tag-color character, $tag-character-color;
|
||||||
|
@mixin tag-color oc, $tag-oc-color, 40;
|
||||||
|
@mixin tag-color species, $tag-species-color, 37;
|
||||||
|
@mixin tag-color body-type, $tag-body-type-color, 45, 12;
|
||||||
|
@mixin tag-color content-fanmade, $tag-content-fanmade-color, 40;
|
||||||
|
@mixin tag-color content-official, $tag-content-official-color;
|
||||||
|
@mixin tag-color spoiler, $tag-spoiler-color;
|
||||||
|
}
|
|
@ -45,3 +45,101 @@
|
||||||
.communication__anonymous--label {
|
.communication__anonymous--label {
|
||||||
padding: 0 var(--padding-small);
|
padding: 0 var(--padding-small);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.communication > .block__content:first-of-type {
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.communication > .block__content:last-of-type {
|
||||||
|
background: var(--primary-muted-color);
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.communication__body {
|
||||||
|
display: block;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.communication__body__text {
|
||||||
|
border-radius: var(--border-radius-inner);
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.communication__sender-name {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--padding-normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
.communication__sender-block {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background: var(--primary-muted-color);
|
||||||
|
border-radius: var(--border-radius-inner);
|
||||||
|
padding: var(--padding-small);
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin if-mobile {
|
||||||
|
.communication__body__text {
|
||||||
|
margin-top: var(--padding-normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
.communication__sender-block {
|
||||||
|
flex-direction: row;
|
||||||
|
gap: var(--padding-normal);
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.communication__sender-block > .image-constrained {
|
||||||
|
min-height: var(--avatar-small-size);
|
||||||
|
min-width: var(--avatar-small-size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.communication__interaction {
|
||||||
|
display: inline-block;
|
||||||
|
background: var(--secondary-muted-color);
|
||||||
|
color: var(--secondary-link-color) !important;
|
||||||
|
padding: var(--padding-tiny);
|
||||||
|
border-radius: var(--border-radius-inner);
|
||||||
|
margin-left: var(--padding-small);
|
||||||
|
}
|
||||||
|
|
||||||
|
.communication__interaction:first-child {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.communication__info {
|
||||||
|
display: inline-block;
|
||||||
|
background: var(--information-muted-color);
|
||||||
|
padding: var(--padding-tiny);
|
||||||
|
border-radius: var(--border-radius-inner);
|
||||||
|
margin-left: var(--padding-small);
|
||||||
|
}
|
||||||
|
|
||||||
|
.communication__info > a {
|
||||||
|
color: var(--information-link-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.togglable-delete-form, .togglable-delete-form-link {
|
||||||
|
margin-top: var(--padding-small) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.togglable-delete-form-link {
|
||||||
|
background: var(--danger-muted-color);
|
||||||
|
color: var(--danger-link-color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.owner-options {
|
||||||
|
margin-left: var(--padding-small);
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin if-mobile {
|
||||||
|
.communication__options > *:first-child {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--padding-small);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -30,3 +30,7 @@
|
||||||
.spoiler-revealed a, .spoiler:hover a {
|
.spoiler-revealed a, .spoiler:hover a {
|
||||||
color: var(--link-color);
|
color: var(--link-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.walloftext {
|
||||||
|
line-height: var(--readable-line-height);
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,16 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.metabar__interactions {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metabar__interactions .comments_count {
|
||||||
|
background: 0;
|
||||||
|
border: 0;
|
||||||
|
position: static;
|
||||||
|
}
|
||||||
|
|
||||||
@mixin if-phone {
|
@mixin if-phone {
|
||||||
.metabar__interactions {
|
.metabar__interactions {
|
||||||
display: grid;
|
display: grid;
|
||||||
|
@ -55,7 +65,25 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.metabar__user-credit {
|
.metabar__user-credit {
|
||||||
|
display: flex;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
gap: var(--padding-small);
|
||||||
|
}
|
||||||
|
|
||||||
|
.metabar__user-credit .image_uploader {
|
||||||
|
display: flex;
|
||||||
|
align-self: center;
|
||||||
|
align-items: center;
|
||||||
|
vertical-align: center;
|
||||||
|
gap: var(--padding-small);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For some bizarre reason the icon appears to have
|
||||||
|
* comically large gap on desktop */
|
||||||
|
@mixin if-desktop {
|
||||||
|
.image_uploader > .username-with-icon {
|
||||||
|
gap: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.metabar__mobile-info td {
|
.metabar__mobile-info td {
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
font-size: 0.8rem !important;
|
font-size: 0.8rem !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pagination a {
|
.pagination a, .pagination span {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: auto;
|
grid-template-columns: auto;
|
||||||
gap: var(--padding-tiny);
|
gap: var(--padding-tiny);
|
||||||
|
|
35
assets/css/views/user.css
Normal file
35
assets/css/views/user.css
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
.badges {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(6, var(--badge-small-size));
|
||||||
|
gap: var(--padding-small);
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge {
|
||||||
|
width: var(--badge-small-size);
|
||||||
|
height: var(--badge-small-size);
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge__overflow {
|
||||||
|
background: var(--information-color);
|
||||||
|
border-radius: var(--border-radius-inner);
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: center;
|
||||||
|
line-height: calc(var(--badge-small-size) * 1.2);
|
||||||
|
width: calc(var(--badge-small-size) * 1.2);
|
||||||
|
height: calc(var(--badge-small-size) * 1.2);
|
||||||
|
font-size: calc(var(--font-size) * 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.username-with-icon {
|
||||||
|
display: inline-flex;
|
||||||
|
gap: var(--padding-tiny);
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-title {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
gap: var(--padding-small);
|
||||||
|
flex-wrap: wrap;
|
||||||
|
margin-top: var(--padding-small);
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* Fingerprints
|
* Thanks uBlock for breaking our JS!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// http://stackoverflow.com/a/34842797
|
// http://stackoverflow.com/a/34842797
|
||||||
|
@ -8,7 +8,7 @@ function hashCode(str) {
|
||||||
((prevHash << 5) - prevHash) + currVal.charCodeAt(0), 0) >>> 0;
|
((prevHash << 5) - prevHash) + currVal.charCodeAt(0), 0) >>> 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createFingerprint() {
|
function createFp() {
|
||||||
const prints = [
|
const prints = [
|
||||||
navigator.userAgent,
|
navigator.userAgent,
|
||||||
navigator.cpuClass,
|
navigator.cpuClass,
|
||||||
|
@ -33,19 +33,19 @@ function createFingerprint() {
|
||||||
return hashCode(prints.join(''));
|
return hashCode(prints.join(''));
|
||||||
}
|
}
|
||||||
|
|
||||||
function setFingerprintCookie() {
|
function setFpCookie() {
|
||||||
let fingerprint;
|
let fp;
|
||||||
|
|
||||||
// The prepended 'c' acts as a crude versioning mechanism.
|
// The prepended 'c' acts as a crude versioning mechanism.
|
||||||
try {
|
try {
|
||||||
fingerprint = `c${createFingerprint()}`;
|
fp = `c${createFp()}`;
|
||||||
}
|
}
|
||||||
// If fingerprinting fails, use fakeprint "c1836832948" as a last resort.
|
// If it fails, use fakeprint "c1836832948" as a last resort.
|
||||||
catch (err) {
|
catch (err) {
|
||||||
fingerprint = 'c1836832948';
|
fp = 'c1836832948';
|
||||||
}
|
}
|
||||||
|
|
||||||
document.cookie = `_ses=${fingerprint}; path=/; SameSite=Lax`;
|
document.cookie = `_ses=${fp}; path=/; SameSite=Lax`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export { setFingerprintCookie };
|
export { setFpCookie };
|
|
@ -14,7 +14,7 @@ import { setupBurgerMenu } from './burger';
|
||||||
import { bindCaptchaLinks } from './captcha';
|
import { bindCaptchaLinks } from './captcha';
|
||||||
import { setupComments } from './comment';
|
import { setupComments } from './comment';
|
||||||
import { setupDupeReports } from './duplicate_reports';
|
import { setupDupeReports } from './duplicate_reports';
|
||||||
import { setFingerprintCookie } from './fingerprint';
|
import { setFpCookie } from './fp';
|
||||||
import { setupGalleryEditing } from './galleries';
|
import { setupGalleryEditing } from './galleries';
|
||||||
import { initImagesClientside } from './imagesclientside';
|
import { initImagesClientside } from './imagesclientside';
|
||||||
import { bindImageTarget } from './image_expansion';
|
import { bindImageTarget } from './image_expansion';
|
||||||
|
@ -48,7 +48,7 @@ whenReady(() => {
|
||||||
initImagesClientside();
|
initImagesClientside();
|
||||||
setupComments();
|
setupComments();
|
||||||
setupDupeReports();
|
setupDupeReports();
|
||||||
setFingerprintCookie();
|
setFpCookie();
|
||||||
setupGalleryEditing();
|
setupGalleryEditing();
|
||||||
bindImageTarget();
|
bindImageTarget();
|
||||||
setupEvents();
|
setupEvents();
|
||||||
|
|
126
assets/package-lock.json
generated
126
assets/package-lock.json
generated
|
@ -2682,29 +2682,6 @@
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/execa": {
|
|
||||||
"version": "8.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz",
|
|
||||||
"integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"cross-spawn": "^7.0.3",
|
|
||||||
"get-stream": "^8.0.1",
|
|
||||||
"human-signals": "^5.0.0",
|
|
||||||
"is-stream": "^3.0.0",
|
|
||||||
"merge-stream": "^2.0.0",
|
|
||||||
"npm-run-path": "^5.1.0",
|
|
||||||
"onetime": "^6.0.0",
|
|
||||||
"signal-exit": "^4.1.0",
|
|
||||||
"strip-final-newline": "^3.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=16.17"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sindresorhus/execa?sponsor=1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/fast-deep-equal": {
|
"node_modules/fast-deep-equal": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||||
|
@ -2861,18 +2838,6 @@
|
||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/get-stream": {
|
|
||||||
"version": "8.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz",
|
|
||||||
"integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=16"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/glob": {
|
"node_modules/glob": {
|
||||||
"version": "7.2.3",
|
"version": "7.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||||
|
@ -3018,15 +2983,6 @@
|
||||||
"node": ">= 14"
|
"node": ">= 14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/human-signals": {
|
|
||||||
"version": "5.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz",
|
|
||||||
"integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=16.17.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/iconv-lite": {
|
"node_modules/iconv-lite": {
|
||||||
"version": "0.6.3",
|
"version": "0.6.3",
|
||||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||||
|
@ -3132,18 +3088,6 @@
|
||||||
"resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
|
||||||
"integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ=="
|
"integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ=="
|
||||||
},
|
},
|
||||||
"node_modules/is-stream": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/isexe": {
|
"node_modules/isexe": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||||
|
@ -3846,33 +3790,6 @@
|
||||||
"resolved": "https://registry.npmjs.org/normalize.css/-/normalize.css-8.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/normalize.css/-/normalize.css-8.0.1.tgz",
|
||||||
"integrity": "sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg=="
|
"integrity": "sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg=="
|
||||||
},
|
},
|
||||||
"node_modules/npm-run-path": {
|
|
||||||
"version": "5.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz",
|
|
||||||
"integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"path-key": "^4.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/npm-run-path/node_modules/path-key": {
|
|
||||||
"version": "4.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
|
|
||||||
"integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/nwsapi": {
|
"node_modules/nwsapi": {
|
||||||
"version": "2.2.9",
|
"version": "2.2.9",
|
||||||
"resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.9.tgz",
|
"resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.9.tgz",
|
||||||
|
@ -3886,21 +3803,6 @@
|
||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/onetime": {
|
|
||||||
"version": "6.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
|
|
||||||
"integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"mimic-fn": "^4.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/optionator": {
|
"node_modules/optionator": {
|
||||||
"version": "0.9.4",
|
"version": "0.9.4",
|
||||||
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
|
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
|
||||||
|
@ -4210,17 +4112,6 @@
|
||||||
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
|
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/readdirp": {
|
|
||||||
"version": "3.6.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
|
||||||
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
|
|
||||||
"dependencies": {
|
|
||||||
"picomatch": "^2.2.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8.10.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/redent": {
|
"node_modules/redent": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz",
|
||||||
|
@ -4393,18 +4284,6 @@
|
||||||
"integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==",
|
"integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/signal-exit": {
|
|
||||||
"version": "4.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
|
|
||||||
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=14"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/isaacs"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/slash": {
|
"node_modules/slash": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
|
||||||
|
@ -5254,6 +5133,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
|
||||||
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw=="
|
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/yallist": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||||
|
},
|
||||||
"node_modules/yocto-queue": {
|
"node_modules/yocto-queue": {
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
||||||
|
|
|
@ -353,7 +353,10 @@ defmodule Philomena.Users.User do
|
||||||
:show_sidebar_and_watched_images
|
:show_sidebar_and_watched_images
|
||||||
])
|
])
|
||||||
|> TagList.propagate_tag_list(:watched_tag_list, :watched_tag_ids)
|
|> TagList.propagate_tag_list(:watched_tag_list, :watched_tag_ids)
|
||||||
|> validate_inclusion(:theme, ~W(default dark red))
|
|> validate_inclusion(
|
||||||
|
:theme,
|
||||||
|
~W(dark-blue dark-red dark-green dark-purple dark-pink dark-yellow dark-cyan dark-grey light-blue light-red light-green light-purple light-pink light-yellow light-cyan light-grey)
|
||||||
|
)
|
||||||
|> validate_inclusion(:images_per_page, 1..50)
|
|> validate_inclusion(:images_per_page, 1..50)
|
||||||
|> validate_inclusion(:comments_per_page, 1..100)
|
|> validate_inclusion(:comments_per_page, 1..100)
|
||||||
|> validate_inclusion(:scale_large_images, ["false", "partscaled", "true"])
|
|> validate_inclusion(:scale_large_images, ["false", "partscaled", "true"])
|
||||||
|
|
|
@ -56,10 +56,18 @@ defmodule PhilomenaWeb.SettingController do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp determine_theme(%{"theme" => "light", "light_theme" => name} = attrs) when name != nil,
|
||||||
|
do: Map.replace(attrs, "theme", name)
|
||||||
|
|
||||||
|
defp determine_theme(%{"dark_theme" => name} = attrs) when name != nil,
|
||||||
|
do: Map.replace(attrs, "theme", name)
|
||||||
|
|
||||||
|
defp determine_theme(attrs), do: Map.replace(attrs, "theme", "dark-blue")
|
||||||
|
|
||||||
defp maybe_update_user(conn, nil, _user_params), do: {:ok, conn}
|
defp maybe_update_user(conn, nil, _user_params), do: {:ok, conn}
|
||||||
|
|
||||||
defp maybe_update_user(conn, user, user_params) do
|
defp maybe_update_user(conn, user, user_params) do
|
||||||
case Users.update_settings(user, user_params) do
|
case Users.update_settings(user, determine_theme(user_params)) do
|
||||||
{:ok, _user} ->
|
{:ok, _user} ->
|
||||||
{:ok, conn}
|
{:ok, conn}
|
||||||
|
|
||||||
|
|
|
@ -70,12 +70,12 @@ defmodule PhilomenaWeb.ContentSecurityPolicyPlug do
|
||||||
defp cdn_uri, do: Application.get_env(:philomena, :cdn_host) |> to_uri()
|
defp cdn_uri, do: Application.get_env(:philomena, :cdn_host) |> to_uri()
|
||||||
defp camo_uri, do: Application.get_env(:philomena, :camo_host) |> to_uri()
|
defp camo_uri, do: Application.get_env(:philomena, :camo_host) |> to_uri()
|
||||||
|
|
||||||
defp default_script_src, do: vite_hmr?(do: "'self' localhost:5173", else: "'self'")
|
defp default_script_src, do: vite_hmr?(do: "*", else: "'self'")
|
||||||
|
|
||||||
defp default_connect_src,
|
defp default_connect_src,
|
||||||
do: vite_hmr?(do: "'self' localhost:5173 ws://localhost:5173", else: "'self'")
|
do: vite_hmr?(do: "*", else: "'self'")
|
||||||
|
|
||||||
defp default_style_src, do: vite_hmr?(do: "'self' 'unsafe-inline'", else: "'self'")
|
defp default_style_src, do: vite_hmr?(do: "*", else: "'self'")
|
||||||
|
|
||||||
defp to_uri(host) when host in [nil, ""], do: ""
|
defp to_uri(host) when host in [nil, ""], do: ""
|
||||||
defp to_uri(host), do: URI.to_string(%URI{scheme: "https", host: host})
|
defp to_uri(host), do: URI.to_string(%URI{scheme: "https", host: host})
|
||||||
|
|
|
@ -4,14 +4,7 @@ p
|
||||||
|
|
||||||
article.block.communication
|
article.block.communication
|
||||||
.block__content.flex.flex--no-wrap
|
.block__content.flex.flex--no-wrap
|
||||||
.flex__fixed.spacing--right
|
= render PhilomenaWeb.CommunicationView, "_body.html", object: @report, body: @body, conn: @conn
|
||||||
= render PhilomenaWeb.UserAttributionView, "_anon_user_avatar.html", object: @report, conn: @conn
|
|
||||||
.flex__grow.communication__body
|
|
||||||
span.communication__body__sender-name = render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: @report, awards: true, conn: @conn
|
|
||||||
br
|
|
||||||
= render PhilomenaWeb.UserAttributionView, "_anon_user_title.html", object: @report, conn: @conn
|
|
||||||
.communication__body__text
|
|
||||||
=<> @body
|
|
||||||
|
|
||||||
.block__content.communication__options
|
.block__content.communication__options
|
||||||
.flex.flex--wrap.flex--spaced-out
|
.flex.flex--wrap.flex--spaced-out
|
||||||
|
|
|
@ -22,33 +22,7 @@ article.block.communication id="comment_#{@comment.id}"
|
||||||
= submit "Delete", class: "button"
|
= submit "Delete", class: "button"
|
||||||
|
|
||||||
.block__content.flex.flex--no-wrap class=communication_body_class(@comment)
|
.block__content.flex.flex--no-wrap class=communication_body_class(@comment)
|
||||||
.flex__fixed.spacing--right
|
= render PhilomenaWeb.CommunicationView, "_body.html", object: @comment, body: @body, conn: @conn, name: "comment"
|
||||||
= render PhilomenaWeb.UserAttributionView, "_anon_user_avatar.html", object: @comment, conn: @conn
|
|
||||||
.flex__grow.communication__body
|
|
||||||
span.communication__body__sender-name = render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: @comment, awards: true, conn: @conn
|
|
||||||
br
|
|
||||||
= render PhilomenaWeb.UserAttributionView, "_anon_user_title.html", object: @comment, conn: @conn
|
|
||||||
.communication__body__text
|
|
||||||
= if @comment.hidden_from_users do
|
|
||||||
strong.comment_deleted
|
|
||||||
' Deletion reason:
|
|
||||||
=<> @comment.deletion_reason
|
|
||||||
= if can?(@conn, :hide, @comment) and not is_nil(@comment.deleted_by) do
|
|
||||||
| (
|
|
||||||
= @comment.deleted_by.name
|
|
||||||
| )
|
|
||||||
|
|
||||||
= if can?(@conn, :hide, @comment) do
|
|
||||||
= if @comment.destroyed_content do
|
|
||||||
br
|
|
||||||
strong.comment_deleted>
|
|
||||||
| This comment's contents have been destroyed.
|
|
||||||
- else
|
|
||||||
br
|
|
||||||
=<> @body
|
|
||||||
|
|
||||||
- else
|
|
||||||
=<> @body
|
|
||||||
|
|
||||||
.block__content.communication__options
|
.block__content.communication__options
|
||||||
.flex.flex--wrap.flex--spaced-out
|
.flex.flex--wrap.flex--spaced-out
|
||||||
|
|
|
@ -1,37 +1,6 @@
|
||||||
article.block.communication id="comment_#{@comment.id}"
|
article.block.communication id="comment_#{@comment.id}"
|
||||||
.block__content.flex.flex--no-wrap class=communication_body_class(@comment)
|
.block__content.flex.flex--no-wrap class=communication_body_class(@comment)
|
||||||
.flex__fixed.spacing--right
|
= render PhilomenaWeb.CommunicationView, "_body.html", object: @comment, image: @comment.image, body: @body, conn: @conn, name: "comment"
|
||||||
.post-image-container
|
|
||||||
= render PhilomenaWeb.ImageView, "_image_container.html", image: @comment.image, size: :thumb_tiny, conn: @conn
|
|
||||||
|
|
||||||
.flex__grow.communication__body
|
|
||||||
span.communication__body__sender-name = render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: @comment, awards: true, conn: @conn
|
|
||||||
br
|
|
||||||
|
|
||||||
= render PhilomenaWeb.UserAttributionView, "_anon_user_title.html", object: @comment, conn: @conn
|
|
||||||
|
|
||||||
.communication__body__text
|
|
||||||
= if @comment.hidden_from_users do
|
|
||||||
strong.comment_deleted
|
|
||||||
' Deletion reason:
|
|
||||||
=<> @comment.deletion_reason
|
|
||||||
|
|
||||||
= if can?(@conn, :hide, @comment) and not is_nil(@comment.deleted_by) do
|
|
||||||
| (
|
|
||||||
= @comment.deleted_by.name
|
|
||||||
| )
|
|
||||||
|
|
||||||
= if can?(@conn, :hide, @comment) do
|
|
||||||
= if @comment.destroyed_content do
|
|
||||||
br
|
|
||||||
strong.comment_deleted>
|
|
||||||
| This comment's contents have been destroyed.
|
|
||||||
- else
|
|
||||||
br
|
|
||||||
=<> @body
|
|
||||||
|
|
||||||
- else
|
|
||||||
=<> @body
|
|
||||||
|
|
||||||
.block__content.communication__options
|
.block__content.communication__options
|
||||||
.flex.flex--wrap.flex--spaced-out
|
.flex.flex--wrap.flex--spaced-out
|
||||||
|
|
60
lib/philomena_web/templates/communication/_body.html.slime
Normal file
60
lib/philomena_web/templates/communication/_body.html.slime
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
- anon = is_nil(assigns[:noanon]) or @noanon == false
|
||||||
|
|
||||||
|
- avatar = cond do
|
||||||
|
- not is_nil(assigns[:image]) ->
|
||||||
|
.post-image-container
|
||||||
|
= render PhilomenaWeb.ImageView, "_image_container.html", image: @image, size: :thumb_tiny, conn: @conn
|
||||||
|
- anon ->
|
||||||
|
= render PhilomenaWeb.UserAttributionView, "_anon_user_avatar.html", object: @object, conn: @conn
|
||||||
|
- true ->
|
||||||
|
= render PhilomenaWeb.UserAttributionView, "_user_avatar.html", object: @object, conn: @conn, class: "avatar--small"
|
||||||
|
|
||||||
|
- username = if anon do
|
||||||
|
= render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: @object, awards: true, conn: @conn
|
||||||
|
- else
|
||||||
|
= render PhilomenaWeb.UserAttributionView, "_user.html", object: @object, badges: true, conn: @conn
|
||||||
|
|
||||||
|
- title = if anon do
|
||||||
|
= render PhilomenaWeb.UserAttributionView, "_anon_user_title.html", object: @object, conn: @conn
|
||||||
|
- else
|
||||||
|
= render PhilomenaWeb.UserAttributionView, "_user_title.html", object: @object, conn: @conn
|
||||||
|
|
||||||
|
- contents = if Map.has_key?(@object, :hidden_from_users) and @object.hidden_from_users == true do
|
||||||
|
strong.comment_deleted
|
||||||
|
' Deletion reason:
|
||||||
|
=<> @object.deletion_reason
|
||||||
|
= if can?(@conn, :hide, @object) and not is_nil(@object.deleted_by) do
|
||||||
|
| (
|
||||||
|
= @object.deleted_by.name
|
||||||
|
| )
|
||||||
|
= if can?(@conn, :hide, @object) do
|
||||||
|
= if @object.destroyed_content do
|
||||||
|
br
|
||||||
|
strong.comment_deleted>
|
||||||
|
| This #{@name}'s contents have been destroyed.
|
||||||
|
- else
|
||||||
|
br
|
||||||
|
=<> @body
|
||||||
|
- else
|
||||||
|
=<> @body
|
||||||
|
|
||||||
|
.flex.flex__grow.hidden--mobile
|
||||||
|
.flex.flex__fixed.spacing--right
|
||||||
|
= avatar
|
||||||
|
.flex__grow.communication__body
|
||||||
|
.communication__sender-block
|
||||||
|
span.communication__sender-name
|
||||||
|
= username
|
||||||
|
= title
|
||||||
|
.communication__body__text
|
||||||
|
= contents
|
||||||
|
.flex.flex__column.flex__grow.hidden--desktop
|
||||||
|
.communication__sender-block
|
||||||
|
= avatar
|
||||||
|
.flex__column.flex--small-gap
|
||||||
|
span.communication__sender-name
|
||||||
|
= username
|
||||||
|
= title
|
||||||
|
.communication__body.communication__body__text
|
||||||
|
= contents
|
||||||
|
|
|
@ -9,7 +9,7 @@ html lang="en"
|
||||||
=> @status
|
=> @status
|
||||||
| - Philomena
|
| - Philomena
|
||||||
link rel="stylesheet" href=stylesheet_path(@conn, nil)
|
link rel="stylesheet" href=stylesheet_path(@conn, nil)
|
||||||
link rel="stylesheet" href=dark_stylesheet_path(@conn) media="(prefers-color-scheme: dark)"
|
link rel="stylesheet" href=light_stylesheet_path(@conn) media="(prefers-color-scheme: light)"
|
||||||
link rel="icon" href="/favicon.ico" type="image/x-icon"
|
link rel="icon" href="/favicon.ico" type="image/x-icon"
|
||||||
link rel="icon" href="/favicon.svg" type="image/svg+xml"
|
link rel="icon" href="/favicon.svg" type="image/svg+xml"
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,6 @@
|
||||||
a href="#{pretty_url(@image, true, true)}" title="Download (no tags in filename)"
|
a href="#{pretty_url(@image, true, true)}" title="Download (no tags in filename)"
|
||||||
i.fa.fa-download
|
i.fa.fa-download
|
||||||
.metabar.metabar__user-credit.hidden--phone.layout--centered#extrameta
|
.metabar.metabar__user-credit.hidden--phone.layout--centered#extrameta
|
||||||
div
|
|
||||||
' Uploaded
|
' Uploaded
|
||||||
=> pretty_time(@image.created_at)
|
=> pretty_time(@image.created_at)
|
||||||
= render PhilomenaWeb.ImageView, "_uploader.html", assigns
|
= render PhilomenaWeb.ImageView, "_uploader.html", assigns
|
||||||
|
|
|
@ -14,7 +14,7 @@ elixir:
|
||||||
.block__header.page__header
|
.block__header.page__header
|
||||||
=> header
|
=> header
|
||||||
|
|
||||||
.block.block--borderless.flex__row.flex--spaced-out
|
.block.block--borderless.flex__row.flex--spaced-out.flex--wrap
|
||||||
= if @images.total_pages > 1 do
|
= if @images.total_pages > 1 do
|
||||||
.button__group--standalone
|
.button__group--standalone
|
||||||
.page__pagination = pagination
|
.page__pagination = pagination
|
||||||
|
@ -41,17 +41,15 @@ elixir:
|
||||||
- image ->
|
- image ->
|
||||||
= render PhilomenaWeb.ImageView, "_image_box.html", image: image, link: image_url.(image), size: assigns[:size] || :thumb, conn: @conn
|
= render PhilomenaWeb.ImageView, "_image_box.html", image: image, link: image_url.(image), size: assigns[:size] || :thumb, conn: @conn
|
||||||
|
|
||||||
.block.block--borderless.block--spaced-top.flex__row
|
br
|
||||||
|
|
||||||
|
.block.block--borderless.flex__row.flex--normal-gap.flex--wrap
|
||||||
.button__group--standalone
|
.button__group--standalone
|
||||||
.page__pagination = pagination
|
.page__pagination = pagination
|
||||||
|
|
||||||
span.page__info
|
|
||||||
= info
|
|
||||||
|
|
||||||
.flex__spacer
|
|
||||||
|
|
||||||
.page__info.button__group--standalone
|
.page__info.button__group--standalone
|
||||||
a href="/settings/edit" title="Display Settings"
|
a href="/settings/edit" title="Display Settings"
|
||||||
i.fa.fa-cog
|
i.fa.fa-cog
|
||||||
span.hidden--mobile<>
|
span.hidden--mobile<>
|
||||||
' Display Settings
|
' Display Settings
|
||||||
|
span.page__info
|
||||||
|
= info
|
||||||
|
|
|
@ -13,7 +13,7 @@ html lang="en"
|
||||||
link rel="stylesheet" href="/css/application.css"
|
link rel="stylesheet" href="/css/application.css"
|
||||||
link rel="stylesheet" href=stylesheet_path(@conn, @current_user)
|
link rel="stylesheet" href=stylesheet_path(@conn, @current_user)
|
||||||
= if is_nil(@current_user) do
|
= if is_nil(@current_user) do
|
||||||
link rel="stylesheet" href=dark_stylesheet_path(@conn) media="(prefers-color-scheme: dark)"
|
link rel="stylesheet" href=light_stylesheet_path(@conn) media="(prefers-color-scheme: light)"
|
||||||
link rel="icon" href="/favicon.ico" type="image/x-icon"
|
link rel="icon" href="/favicon.ico" type="image/x-icon"
|
||||||
link rel="icon" href="/favicon.svg" type="image/svg+xml"
|
link rel="icon" href="/favicon.svg" type="image/svg+xml"
|
||||||
meta name="generator" content="philomena"
|
meta name="generator" content="philomena"
|
||||||
|
|
|
@ -7,7 +7,7 @@ html lang="en"
|
||||||
|
|
||||||
title Two Factor Authentication - Derpibooru
|
title Two Factor Authentication - Derpibooru
|
||||||
link rel="stylesheet" href=stylesheet_path(@conn, nil)
|
link rel="stylesheet" href=stylesheet_path(@conn, nil)
|
||||||
link rel="stylesheet" href=dark_stylesheet_path(@conn) media="(prefers-color-scheme: dark)"
|
link rel="stylesheet" href=light_stylesheet_path(@conn) media="(prefers-color-scheme: light)"
|
||||||
link rel="icon" href="/favicon.ico" type="image/x-icon"
|
link rel="icon" href="/favicon.ico" type="image/x-icon"
|
||||||
link rel="icon" href="/favicon.svg" type="image/svg+xml"
|
link rel="icon" href="/favicon.svg" type="image/svg+xml"
|
||||||
|
|
||||||
|
|
|
@ -14,18 +14,7 @@ article.block.communication
|
||||||
' Approve
|
' Approve
|
||||||
|
|
||||||
.block__content.flex.flex--no-wrap
|
.block__content.flex.flex--no-wrap
|
||||||
.flex__fixed.spacing--right
|
= render PhilomenaWeb.CommunicationView, "_body.html", object: %{user: @message.from}, noanon: true, body: @body, conn: @conn, name: "message"
|
||||||
= render PhilomenaWeb.UserAttributionView, "_user_avatar.html", object: %{user: @message.from}, conn: @conn, class: "avatar--small"
|
|
||||||
|
|
||||||
.flex__grow.communication__body
|
|
||||||
|
|
||||||
span.communication__body__sender-name = render PhilomenaWeb.UserAttributionView, "_user.html", object: %{user: @message.from}, badges: true, conn: @conn
|
|
||||||
br
|
|
||||||
|
|
||||||
= render PhilomenaWeb.UserAttributionView, "_user_title.html", object: %{user: @message.from}, conn: @conn
|
|
||||||
|
|
||||||
.communication__body__text
|
|
||||||
= @body
|
|
||||||
|
|
||||||
.block__content.communication__options
|
.block__content.communication__options
|
||||||
.flex.flex--wrap.flex--spaced-out
|
.flex.flex--wrap.flex--spaced-out
|
||||||
|
|
|
@ -40,11 +40,11 @@
|
||||||
|
|
||||||
nav.pagination.hidden--desktop
|
nav.pagination.hidden--desktop
|
||||||
= if first_page?(@page) do
|
= if first_page?(@page) do
|
||||||
span
|
span.with-icon
|
||||||
i.fa.fa-backward>
|
i.fa.fa-backward>
|
||||||
' First
|
' First
|
||||||
.separator--vertical.separator--secondary
|
.separator--vertical.separator--secondary
|
||||||
span
|
span.with-icon
|
||||||
i.fa.fa-chevron-left>
|
i.fa.fa-chevron-left>
|
||||||
' Prev
|
' Prev
|
||||||
.separator--vertical.separator--secondary
|
.separator--vertical.separator--secondary
|
||||||
|
@ -52,12 +52,14 @@
|
||||||
= link to: first_page_path(@page, @route, params), class: "with-icon" do
|
= link to: first_page_path(@page, @route, params), class: "with-icon" do
|
||||||
i.fa.fa-backward>
|
i.fa.fa-backward>
|
||||||
' First
|
' First
|
||||||
|
.separator--vertical.separator--secondary
|
||||||
= link to: prev_page_path(@page, @route, params), class: "js-prev with-icon" do
|
= link to: prev_page_path(@page, @route, params), class: "js-prev with-icon" do
|
||||||
i.fa.fa-chevron-left>
|
i.fa.fa-chevron-left>
|
||||||
' Prev
|
' Prev
|
||||||
|
.separator--vertical.separator--secondary
|
||||||
|
|
||||||
.dropdown
|
.dropdown
|
||||||
a.page-current.pagination__dropdown
|
a.with-icon.page-current.pagination__dropdown
|
||||||
=> @page.page_number
|
=> @page.page_number
|
||||||
i.fa.fa-caret-down
|
i.fa.fa-caret-down
|
||||||
|
|
||||||
|
@ -80,11 +82,11 @@
|
||||||
|
|
||||||
= if last_page?(@page) do
|
= if last_page?(@page) do
|
||||||
.separator--vertical.separator--secondary
|
.separator--vertical.separator--secondary
|
||||||
span
|
span.with-icon
|
||||||
' Next
|
' Next
|
||||||
i.fa.fa-chevron-right
|
i.fa.fa-chevron-right
|
||||||
.separator--vertical.separator--secondary
|
.separator--vertical.separator--secondary
|
||||||
span
|
span.with-icon
|
||||||
' Last
|
' Last
|
||||||
i.fa.fa-fast-forward
|
i.fa.fa-fast-forward
|
||||||
- else
|
- else
|
||||||
|
|
|
@ -22,33 +22,7 @@ article.block.communication id="post_#{@post.id}"
|
||||||
= submit "Delete", class: "button"
|
= submit "Delete", class: "button"
|
||||||
|
|
||||||
.block__content.flex.flex--no-wrap class=communication_body_class(@post)
|
.block__content.flex.flex--no-wrap class=communication_body_class(@post)
|
||||||
.flex__fixed.spacing--right
|
= render PhilomenaWeb.CommunicationView, "_body.html", object: @post, body: @body, conn: @conn, name: "post"
|
||||||
= render PhilomenaWeb.UserAttributionView, "_anon_user_avatar.html", object: @post, conn: @conn
|
|
||||||
.flex__grow.communication__body
|
|
||||||
span.communication__body__sender-name = render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: @post, awards: true, conn: @conn
|
|
||||||
br
|
|
||||||
= render PhilomenaWeb.UserAttributionView, "_anon_user_title.html", object: @post, conn: @conn
|
|
||||||
.communication__body__text
|
|
||||||
= if @post.hidden_from_users do
|
|
||||||
strong.comment_deleted
|
|
||||||
' Deletion reason:
|
|
||||||
=> @post.deletion_reason
|
|
||||||
= if can?(@conn, :hide, @post) and not is_nil(@post.deleted_by) do
|
|
||||||
| (
|
|
||||||
= @post.deleted_by.name
|
|
||||||
| )
|
|
||||||
|
|
||||||
= if can?(@conn, :hide, @post) do
|
|
||||||
= if @post.destroyed_content do
|
|
||||||
br
|
|
||||||
strong.comment_deleted>
|
|
||||||
| This post's contents have been destroyed.
|
|
||||||
- else
|
|
||||||
br
|
|
||||||
=<> @body
|
|
||||||
|
|
||||||
- else
|
|
||||||
=<> @body
|
|
||||||
|
|
||||||
.block__content.communication__options
|
.block__content.communication__options
|
||||||
.flex.flex--wrap.flex--spaced-out
|
.flex.flex--wrap.flex--spaced-out
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
= cond do
|
= cond do
|
||||||
- @user.description not in [nil, ""] ->
|
- @user.description not in [nil, ""] ->
|
||||||
= @about_me
|
= @about_me
|
||||||
|
- true ->
|
||||||
|
| No description provided.
|
||||||
|
|
||||||
= if can?(@conn, :edit_description, @user) do
|
= if can?(@conn, :edit_description, @user) do
|
||||||
= if @user.description not in [nil, ""] do
|
= if @user.description not in [nil, ""] do
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
.badges
|
.badges
|
||||||
- awards = award_order(@awards)
|
- awards = award_order(@awards)
|
||||||
- {awards, overflow} = Enum.split(awards, 10)
|
- {awards, overflow} = Enum.split(awards, 5)
|
||||||
|
|
||||||
= for award <- awards do
|
= for award <- awards do
|
||||||
- title = [award_title(award), award.label] |> Enum.join(" - ")
|
- title = [award_title(award), award.label] |> Enum.join(" - ")
|
||||||
|
@ -8,11 +8,6 @@
|
||||||
= badge_image(award.badge, alt: title, title: title, width: "18", height: "18")
|
= badge_image(award.badge, alt: title, title: title, width: "18", height: "18")
|
||||||
|
|
||||||
= if Enum.any?(overflow) do
|
= if Enum.any?(overflow) do
|
||||||
.dropdown
|
span.badge__overflow
|
||||||
i.fa.fa-caret-down
|
| +
|
||||||
.dropdown__content.block__header
|
= Enum.count(overflow)
|
||||||
.badges.flex--column
|
|
||||||
= for award <- overflow do
|
|
||||||
- title = [award_title(award), award.label] |> Enum.join(" - ")
|
|
||||||
.badge
|
|
||||||
= badge_image(award.badge, alt: title, title: title, width: "18", height: "18")
|
|
||||||
|
|
|
@ -56,21 +56,25 @@ h1 Content Settings
|
||||||
' Do not share this URL with anyone, it may allow an attacker to compromise your account.
|
' Do not share this URL with anyone, it may allow an attacker to compromise your account.
|
||||||
|
|
||||||
.block__tab.hidden.flex.flex--maybe-wrap data-tab="display"
|
.block__tab.hidden.flex.flex--maybe-wrap data-tab="display"
|
||||||
div
|
.form--three-items
|
||||||
.field
|
.field
|
||||||
=> label f, :use_centered_layout
|
=> label f, :use_centered_layout
|
||||||
|
.with-error
|
||||||
=> checkbox f, :use_centered_layout, class: "checkbox"
|
=> checkbox f, :use_centered_layout, class: "checkbox"
|
||||||
.fieldlabel: i Align content to the center of the page - try this option out if you browse the site on a tablet or a fairly wide screen.
|
.fieldlabel: i Align content to the center of the page - try this option out if you browse the site on a tablet or a fairly wide screen.
|
||||||
.field
|
.field
|
||||||
=> label f, :show_sidebar_and_watched_images
|
=> label f, :show_sidebar_and_watched_images
|
||||||
|
.with-error
|
||||||
=> checkbox f, :show_sidebar_and_watched_images, class: "checkbox"
|
=> checkbox f, :show_sidebar_and_watched_images, class: "checkbox"
|
||||||
.fieldlabel: i Show the sidebar and new watched images on the homepage (the default) or hide it.
|
.fieldlabel: i Show the sidebar and new watched images on the homepage (the default) or hide it.
|
||||||
.field
|
.field
|
||||||
=> label f, :hide_vote_counts
|
=> label f, :hide_vote_counts
|
||||||
|
.with-error
|
||||||
=> checkbox f, :hide_vote_counts, class: "checkbox"
|
=> checkbox f, :hide_vote_counts, class: "checkbox"
|
||||||
.fieldlabel: i Hide upvote and downvote counts on images, showing only the overall score
|
.fieldlabel: i Hide upvote and downvote counts on images, showing only the overall score
|
||||||
.field
|
.field
|
||||||
=> label f, :images_per_page
|
=> label f, :images_per_page
|
||||||
|
.with-error
|
||||||
=> number_input f, :images_per_page, min: 1, max: 50, step: 1, class: "input"
|
=> number_input f, :images_per_page, min: 1, max: 50, step: 1, class: "input"
|
||||||
= error_tag f, :images_per_page
|
= error_tag f, :images_per_page
|
||||||
.fieldlabel
|
.fieldlabel
|
||||||
|
@ -78,12 +82,26 @@ h1 Content Settings
|
||||||
' This is the number of images per page that are displayed on image listings and searches, up to a maximum of 50.
|
' This is the number of images per page that are displayed on image listings and searches, up to a maximum of 50.
|
||||||
' For 1080p monitors, try 24.
|
' For 1080p monitors, try 24.
|
||||||
.field
|
.field
|
||||||
=> label f, :theme
|
label Theme
|
||||||
=> select f, :theme, theme_options(@conn), class: "input"
|
select.input#js-theme-selector name="user[theme]" id="user_theme"
|
||||||
= error_tag f, :theme
|
option value="dark" Dark
|
||||||
|
option value="light" Light
|
||||||
|
.fieldlabel: i General appearance of the theme
|
||||||
|
.field#js-theme-dark
|
||||||
|
label Theme color
|
||||||
|
.with-error
|
||||||
|
=> select f, :dark_theme, theme_options(@conn), class: "input"
|
||||||
|
= error_tag f, :dark_theme
|
||||||
|
.fieldlabel: i Color of the theme, don't forget to save settings to apply the theme
|
||||||
|
.field.hidden#js-theme-light
|
||||||
|
label Theme color
|
||||||
|
.with-error
|
||||||
|
=> select f, :light_theme, light_theme_options(@conn), class: "input"
|
||||||
|
= error_tag f, :light_theme
|
||||||
.fieldlabel: i Preview themes by selecting one from the dropdown. Saving sets the currently selected theme.
|
.fieldlabel: i Preview themes by selecting one from the dropdown. Saving sets the currently selected theme.
|
||||||
.field
|
.field
|
||||||
=> label f, :scale_large_images
|
=> label f, :scale_large_images
|
||||||
|
.with-error
|
||||||
=> select f, :scale_large_images, scale_options(), class: "input"
|
=> select f, :scale_large_images, scale_options(), class: "input"
|
||||||
= error_tag f, :scale_large_images
|
= error_tag f, :scale_large_images
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
= cond do
|
= cond do
|
||||||
- not is_nil(@object.user) and not anonymous?(@object) ->
|
- not is_nil(@object.user) and not anonymous?(@object) ->
|
||||||
strong<>
|
strong.username-with-icon<>
|
||||||
|
- icon = user_icon(@object.user)
|
||||||
|
= if icon do
|
||||||
|
i class="fa #{icon}"
|
||||||
= link(@object.user.name, to: Routes.profile_path(@conn, :show, @object.user))
|
= link(@object.user.name, to: Routes.profile_path(@conn, :show, @object.user))
|
||||||
= if assigns[:awards] do
|
= if assigns[:awards] do
|
||||||
= render PhilomenaWeb.ProfileView, "_awards.html", awards: @object.user.awards
|
= render PhilomenaWeb.ProfileView, "_awards.html", awards: @object.user.awards
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
= if !!@object.user and !anonymous?(@object) do
|
= if !!@object.user and !anonymous?(@object) do
|
||||||
|
.user-title
|
||||||
= for {class, label} <- user_labels(@object) do
|
= for {class, label} <- user_labels(@object) do
|
||||||
= if assigns[:large] do
|
= if assigns[:large] do
|
||||||
.label.label--block class=class = label
|
.label class=class = label
|
||||||
- else
|
- else
|
||||||
.label.label--block.label--small class=class = label
|
.label.label--small class=class = label
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
= if !!@object.user do
|
= if !!@object.user do
|
||||||
strong<>
|
strong<>
|
||||||
|
- icon = user_icon(@object.user)
|
||||||
|
= if icon do
|
||||||
|
i class="fa #{icon}">
|
||||||
= link(@object.user.name, to: Routes.profile_path(@conn, :show, @object.user))
|
= link(@object.user.name, to: Routes.profile_path(@conn, :show, @object.user))
|
||||||
= if assigns[:awards] do
|
= if assigns[:awards] do
|
||||||
= render PhilomenaWeb.ProfileView, "_awards.html", awards: @object.user.awards
|
= render PhilomenaWeb.ProfileView, "_awards.html", awards: @object.user.awards
|
|
@ -1,5 +1,6 @@
|
||||||
= for {class, label} <- user_labels(@object) do
|
.user-title
|
||||||
|
= for {class, label} <- user_labels(@object) do
|
||||||
= if assigns[:large] do
|
= if assigns[:large] do
|
||||||
.label.label--block class=class = label
|
.label class=class = label
|
||||||
- else
|
- else
|
||||||
.label.label--block.label--small class=class = label
|
.label.label--small class=class = label
|
||||||
|
|
|
@ -46,7 +46,9 @@ defmodule PhilomenaWeb.Admin.UserView do
|
||||||
|
|
||||||
def description("moderator", "Tag"), do: "Manage tag details"
|
def description("moderator", "Tag"), do: "Manage tag details"
|
||||||
def description("admin", "Tag"), do: "Alias tags"
|
def description("admin", "Tag"), do: "Alias tags"
|
||||||
def description("batch_update", "Tag"), do: "Update tags in batches (do not issue to staff members)"
|
|
||||||
|
def description("batch_update", "Tag"),
|
||||||
|
do: "Update tags in batches (do not issue to staff members)"
|
||||||
|
|
||||||
def description("moderator", "User"), do: "Manage users and wipe votes"
|
def description("moderator", "User"), do: "Manage users and wipe votes"
|
||||||
def description("admin", "Role"), do: "Manage permissions"
|
def description("admin", "Role"), do: "Manage permissions"
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
defmodule PhilomenaWeb.CommunicationView do
|
||||||
|
use PhilomenaWeb, :view
|
||||||
|
end
|
|
@ -4,7 +4,7 @@ defmodule PhilomenaWeb.ErrorView do
|
||||||
import PhilomenaWeb.LayoutView,
|
import PhilomenaWeb.LayoutView,
|
||||||
only: [
|
only: [
|
||||||
stylesheet_path: 2,
|
stylesheet_path: 2,
|
||||||
dark_stylesheet_path: 1,
|
light_stylesheet_path: 1,
|
||||||
viewport_meta_tag: 1
|
viewport_meta_tag: 1
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -69,17 +69,32 @@ defmodule PhilomenaWeb.LayoutView do
|
||||||
Config.get(:footer)
|
Config.get(:footer)
|
||||||
end
|
end
|
||||||
|
|
||||||
# def stylesheet_path(conn, %{theme: "dark"}),
|
def stylesheet_path(conn, %{theme: theme})
|
||||||
# do: Routes.static_path(conn, "/css/dark.css")
|
when theme in [
|
||||||
|
"dark-blue",
|
||||||
# def stylesheet_path(conn, %{theme: "red"}),
|
"dark-red",
|
||||||
# do: Routes.static_path(conn, "/css/red.css")
|
"dark-green",
|
||||||
|
"dark-purple",
|
||||||
|
"dark-pink",
|
||||||
|
"dark-yellow",
|
||||||
|
"dark-cyan",
|
||||||
|
"dark-grey",
|
||||||
|
"light-blue",
|
||||||
|
"light-red",
|
||||||
|
"light-green",
|
||||||
|
"light-purple",
|
||||||
|
"light-pink",
|
||||||
|
"light-yellow",
|
||||||
|
"light-cyan",
|
||||||
|
"light-grey"
|
||||||
|
],
|
||||||
|
do: Routes.static_path(conn, "/css/#{theme}.css")
|
||||||
|
|
||||||
def stylesheet_path(conn, _user),
|
def stylesheet_path(conn, _user),
|
||||||
do: Routes.static_path(conn, "/css/dark-blue.css")
|
do: Routes.static_path(conn, "/css/dark-blue.css")
|
||||||
|
|
||||||
def dark_stylesheet_path(conn),
|
def light_stylesheet_path(conn),
|
||||||
do: Routes.static_path(conn, "/css/dark-blue.css")
|
do: Routes.static_path(conn, "/css/light-blue.css")
|
||||||
|
|
||||||
def theme_name(%{theme: theme}), do: theme
|
def theme_name(%{theme: theme}), do: theme
|
||||||
def theme_name(_user), do: "default"
|
def theme_name(_user), do: "default"
|
||||||
|
|
|
@ -4,12 +4,90 @@ defmodule PhilomenaWeb.SettingView do
|
||||||
def theme_options(conn) do
|
def theme_options(conn) do
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
key: "Default",
|
key: "Blue (default)",
|
||||||
value: "default",
|
value: "dark-blue",
|
||||||
data: [theme_path: Routes.static_path(conn, "/css/default.css")]
|
data: [theme_path: Routes.static_path(conn, "/css/dark-blue.css")]
|
||||||
],
|
],
|
||||||
[key: "Dark", value: "dark", data: [theme_path: Routes.static_path(conn, "/css/dark.css")]],
|
[
|
||||||
[key: "Red", value: "red", data: [theme_path: Routes.static_path(conn, "/css/red.css")]]
|
key: "Red",
|
||||||
|
value: "dark-red",
|
||||||
|
data: [theme_path: Routes.static_path(conn, "/css/dark-red.css")]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
key: "Green",
|
||||||
|
value: "dark-green",
|
||||||
|
data: [theme_path: Routes.static_path(conn, "/css/dark-green.css")]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
key: "Purple",
|
||||||
|
value: "dark-purple",
|
||||||
|
data: [theme_path: Routes.static_path(conn, "/css/dark-purple.css")]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
key: "Pink",
|
||||||
|
value: "dark-pink",
|
||||||
|
data: [theme_path: Routes.static_path(conn, "/css/dark-pink.css")]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
key: "Yellow",
|
||||||
|
value: "dark-yellow",
|
||||||
|
data: [theme_path: Routes.static_path(conn, "/css/dark-yellow.css")]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
key: "Cyan",
|
||||||
|
value: "dark-cyan",
|
||||||
|
data: [theme_path: Routes.static_path(conn, "/css/dark-cyan.css")]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
key: "Grey",
|
||||||
|
value: "dark-grey",
|
||||||
|
data: [theme_path: Routes.static_path(conn, "/css/dark-grey.css")]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
def light_theme_options(conn) do
|
||||||
|
[
|
||||||
|
[
|
||||||
|
key: "Blue (default)",
|
||||||
|
value: "light-blue",
|
||||||
|
data: [theme_path: Routes.static_path(conn, "/css/light-blue.css")]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
key: "Red",
|
||||||
|
value: "light-red",
|
||||||
|
data: [theme_path: Routes.static_path(conn, "/css/light-red.css")]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
key: "Green",
|
||||||
|
value: "light-green",
|
||||||
|
data: [theme_path: Routes.static_path(conn, "/css/light-green.css")]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
key: "Purple",
|
||||||
|
value: "light-purple",
|
||||||
|
data: [theme_path: Routes.static_path(conn, "/css/light-purple.css")]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
key: "Pink",
|
||||||
|
value: "light-pink",
|
||||||
|
data: [theme_path: Routes.static_path(conn, "/css/light-pink.css")]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
key: "Yellow",
|
||||||
|
value: "light-yellow",
|
||||||
|
data: [theme_path: Routes.static_path(conn, "/css/light-yellow.css")]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
key: "Cyan",
|
||||||
|
value: "light-cyan",
|
||||||
|
data: [theme_path: Routes.static_path(conn, "/css/light-cyan.css")]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
key: "Grey",
|
||||||
|
value: "light-grey",
|
||||||
|
data: [theme_path: Routes.static_path(conn, "/css/light-grey.css")]
|
||||||
|
]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -81,6 +81,13 @@ defmodule PhilomenaWeb.UserAttributionView do
|
||||||
"data:image/svg+xml;base64," <> Base.encode64(svg)
|
"data:image/svg+xml;base64," <> Base.encode64(svg)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def user_icon(%{secondary_role: sr}) when sr in ["Site Developer", "Devops"], do: "fa-screwdriver-wrench"
|
||||||
|
def user_icon(%{secondary_role: sr}) when sr in ["Public Relations"], do: "fa-bullhorn"
|
||||||
|
def user_icon(%{hide_default_role: true}), do: nil
|
||||||
|
def user_icon(%{role: role}) when role in ["admin", "moderator"], do: "fa-gavel"
|
||||||
|
def user_icon(%{role: "assistant"}), do: "fa-handshake-angle"
|
||||||
|
def user_icon(_), do: nil
|
||||||
|
|
||||||
def user_labels(%{user: user}) do
|
def user_labels(%{user: user}) do
|
||||||
[]
|
[]
|
||||||
|> personal_title(user)
|
|> personal_title(user)
|
||||||
|
|
Loading…
Reference in a new issue