Compare commits
5 Commits
10a2731caf
...
729ca0f968
Author | SHA1 | Date |
---|---|---|
|
729ca0f968 | |
|
385dfb9f75 | |
|
afbae24f43 | |
|
eb7009832a | |
|
d1480da076 |
|
@ -36,6 +36,7 @@
|
||||||
>Log in</button>
|
>Log in</button>
|
||||||
|
|
||||||
<router-link
|
<router-link
|
||||||
|
v-if="$store.state.auth.signup"
|
||||||
:to="{ name: 'signup', query: { ref: $route.query.ref } }"
|
:to="{ name: 'signup', query: { ref: $route.query.ref } }"
|
||||||
class="link link-external signup"
|
class="link link-external signup"
|
||||||
>Sign up</router-link>
|
>Sign up</router-link>
|
||||||
|
@ -65,7 +66,7 @@ async function login() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function mounted() {
|
function mounted() {
|
||||||
if (!this.$store.state.auth.enabled) {
|
if (!this.$store.state.auth.login) {
|
||||||
this.$router.replace({ name: 'not-found' });
|
this.$router.replace({ name: 'not-found' });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
>Sign up</button>
|
>Sign up</button>
|
||||||
|
|
||||||
<router-link
|
<router-link
|
||||||
|
v-if="$store.state.auth.login"
|
||||||
:to="{ name: 'login', query: { ref: $route.query.ref } }"
|
:to="{ name: 'login', query: { ref: $route.query.ref } }"
|
||||||
class="link link-external login"
|
class="link link-external login"
|
||||||
>Log in</router-link>
|
>Log in</router-link>
|
||||||
|
@ -74,7 +75,7 @@ async function signup() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function mounted() {
|
function mounted() {
|
||||||
if (!this.$store.state.auth.enabled) {
|
if (!this.$store.state.auth.signup) {
|
||||||
this.$router.replace({ name: 'not-found' });
|
this.$router.replace({ name: 'not-found' });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
<template>
|
||||||
|
<a
|
||||||
|
v-if="campaign"
|
||||||
|
:href="campaign.url"
|
||||||
|
target="_blank"
|
||||||
|
class="campaign"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
v-if="campaign.banner.entity.type === 'network'"
|
||||||
|
:src="`/img/banners/${campaign.banner.entity.slug}/${campaign.banner.id}.jpeg`"
|
||||||
|
class="campaign-banner"
|
||||||
|
>
|
||||||
|
|
||||||
|
<img
|
||||||
|
v-if="campaign.banner.entity.type === 'channel' && campaign.banner.entity.parent?.type === 'network'"
|
||||||
|
:src="`/img/banners/${campaign.banner.entity.parent.slug}/${campaign.banner.entity.slug}/${campaign.banner.id}.jpeg`"
|
||||||
|
class="campaign-banner"
|
||||||
|
>
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function entityCampaign() {
|
||||||
|
const bannerCampaigns = this.entity.campaigns
|
||||||
|
.concat(this.entity.children?.flatMap(child => child.campaigns))
|
||||||
|
.concat(this.entity.parent?.campaigns)
|
||||||
|
.filter(campaignX => campaignX.banner?.ratio > 3);
|
||||||
|
|
||||||
|
if (bannerCampaigns.length > 0) {
|
||||||
|
return bannerCampaigns[Math.floor(Math.random() * bannerCampaigns.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function tagCampaign() {
|
||||||
|
const campaignBanners = this.tag.banners.filter(banner => banner.campaigns.length > 0 && banner.ratio > 3);
|
||||||
|
const banner = campaignBanners[Math.floor(Math.random() * campaignBanners.length)];
|
||||||
|
|
||||||
|
if (banner?.campaigns.length > 0) {
|
||||||
|
return {
|
||||||
|
...banner.campaigns[Math.floor(Math.random() * banner.campaigns.length)],
|
||||||
|
banner,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function campaign() {
|
||||||
|
if (this.entity) {
|
||||||
|
return this.entityCampaign();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.tag) {
|
||||||
|
return this.tagCampaign();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
entity: {
|
||||||
|
type: Object,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
tag: {
|
||||||
|
type: Object,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
campaign,
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
entityCampaign,
|
||||||
|
tagCampaign,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.campaign {
|
||||||
|
height: 100%;
|
||||||
|
display: inline-flex;
|
||||||
|
flex-grow: 1;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.campaign-banner {
|
||||||
|
max-height: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -67,12 +67,13 @@ export default {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
background: var(--darken-censor);
|
background: var(--background-censor);
|
||||||
|
backdrop-filter: blur(.25rem);
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.warning {
|
.warning {
|
||||||
color: var(--text-light);
|
color: var(--text);
|
||||||
width: 50rem;
|
width: 50rem;
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
@ -87,8 +88,8 @@ export default {
|
||||||
.title {
|
.title {
|
||||||
display: block;
|
display: block;
|
||||||
font-size: 2rem;
|
font-size: 2rem;
|
||||||
margin: 1rem 0 0 0;
|
margin: 1rem 0;
|
||||||
color: var(--text-light);
|
color: var(--text);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +114,7 @@ export default {
|
||||||
.rules {
|
.rules {
|
||||||
margin: 0 0 0 1rem;
|
margin: 0 0 0 1rem;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
text-shadow: 0 0 3px var(--darken-extreme);
|
text-shadow: 0 0 3px var(--highlight-strong);
|
||||||
}
|
}
|
||||||
|
|
||||||
.rule {
|
.rule {
|
||||||
|
@ -134,16 +135,16 @@ export default {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
border: none;
|
border: none;
|
||||||
|
border-radius: .25rem;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
border-radius: 1rem;
|
|
||||||
color: var(--lighten-strong);
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
transition: border .5s ease;
|
transition: border-radius .2s ease;
|
||||||
|
|
||||||
&.leave {
|
&.leave {
|
||||||
|
color: var(--shadow-strong);
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
|
|
||||||
|
@ -151,7 +152,11 @@ export default {
|
||||||
width: 1.5rem;
|
width: 1.5rem;
|
||||||
height: 1.5rem;
|
height: 1.5rem;
|
||||||
margin: 0 1rem 0 0;
|
margin: 0 1rem 0 0;
|
||||||
fill: var(--lighten);
|
fill: var(--shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,6 +166,7 @@ export default {
|
||||||
|
|
||||||
&.straight,
|
&.straight,
|
||||||
&.queer {
|
&.queer {
|
||||||
|
color: var(--lighten-strong);
|
||||||
background: var(--darken-censor);
|
background: var(--darken-censor);
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
|
@ -169,10 +175,18 @@ export default {
|
||||||
height: calc(100% + .25rem);
|
height: calc(100% + .25rem);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
border-radius: 1.1rem;
|
|
||||||
filter: blur(.25rem);
|
filter: blur(.25rem);
|
||||||
transition: filter .2s ease;
|
transition: filter .2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--text-light);
|
||||||
|
border-radius: 0;
|
||||||
|
|
||||||
|
.button-sub {
|
||||||
|
color: var(--text-light);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.straight:before {
|
&.straight:before {
|
||||||
|
@ -188,14 +202,8 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: var(--text-light);
|
|
||||||
|
|
||||||
.button-sub {
|
|
||||||
color: var(--lighten-strong);
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
fill: var(--text-light);
|
fill: var(--text);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.straight:before,
|
&.straight:before,
|
||||||
|
@ -225,7 +233,7 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.preferences {
|
.preferences {
|
||||||
color: var(--lighten);
|
color: var(--shadow);
|
||||||
display: block;
|
display: block;
|
||||||
padding: .5rem 0 1rem 0;
|
padding: .5rem 0 1rem 0;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -234,11 +242,11 @@ export default {
|
||||||
|
|
||||||
@media(max-width: $breakpoint) {
|
@media(max-width: $breakpoint) {
|
||||||
.title {
|
.title {
|
||||||
font-size: 1.5rem;
|
font-size: 1.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo {
|
.logo {
|
||||||
width: 5rem;
|
width: 5.75rem;
|
||||||
margin: 0 .5rem 0 0;
|
margin: 0 .5rem 0 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
>
|
>
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<a
|
<a
|
||||||
:href="entity.url"
|
:href="entityUrl"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener"
|
rel="noopener"
|
||||||
class="link link-child"
|
class="link link-child"
|
||||||
|
@ -72,6 +72,8 @@
|
||||||
v-else
|
v-else
|
||||||
class="name parent-name"
|
class="name parent-name"
|
||||||
>{{ entity.parent.name }}</h3>
|
>{{ entity.parent.name }}</h3>
|
||||||
|
|
||||||
|
<Icon icon="device_hub" />
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -94,6 +96,10 @@
|
||||||
/>
|
/>
|
||||||
</Scroll>
|
</Scroll>
|
||||||
|
|
||||||
|
<div class="campaign-container">
|
||||||
|
<Campaign :entity="entity" />
|
||||||
|
</div>
|
||||||
|
|
||||||
<FilterBar
|
<FilterBar
|
||||||
ref="filter"
|
ref="filter"
|
||||||
:fetch-releases="fetchEntity"
|
:fetch-releases="fetchEntity"
|
||||||
|
@ -122,8 +128,11 @@ import Pagination from '../pagination/pagination.vue';
|
||||||
import Releases from '../releases/releases.vue';
|
import Releases from '../releases/releases.vue';
|
||||||
import Children from './children.vue';
|
import Children from './children.vue';
|
||||||
import Scroll from '../scroll/scroll.vue';
|
import Scroll from '../scroll/scroll.vue';
|
||||||
|
import Campaign from '../campaigns/campaign.vue';
|
||||||
|
|
||||||
async function fetchEntity(scroll = true) {
|
async function fetchEntity(scroll = true) {
|
||||||
|
this.entityUrl = null;
|
||||||
|
|
||||||
const { entity, totalCount } = await this.$store.dispatch('fetchEntityBySlugAndType', {
|
const { entity, totalCount } = await this.$store.dispatch('fetchEntityBySlugAndType', {
|
||||||
entitySlug: this.$route.params.entitySlug,
|
entitySlug: this.$route.params.entitySlug,
|
||||||
entityType: this.$route.name,
|
entityType: this.$route.name,
|
||||||
|
@ -136,6 +145,7 @@ async function fetchEntity(scroll = true) {
|
||||||
this.totalCount = totalCount;
|
this.totalCount = totalCount;
|
||||||
|
|
||||||
this.pageTitle = entity.name;
|
this.pageTitle = entity.name;
|
||||||
|
this.entityUrl = entity.campaigns.find(campaign => !campaign.banner)?.url || entity.url;
|
||||||
|
|
||||||
if (scroll && this.$refs.filter?.$el) {
|
if (scroll && this.$refs.filter?.$el) {
|
||||||
this.$refs.filter.$el.scrollIntoView();
|
this.$refs.filter.$el.scrollIntoView();
|
||||||
|
@ -160,6 +170,7 @@ export default {
|
||||||
Children,
|
Children,
|
||||||
Releases,
|
Releases,
|
||||||
Scroll,
|
Scroll,
|
||||||
|
Campaign,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -168,6 +179,7 @@ export default {
|
||||||
totalCount: null,
|
totalCount: null,
|
||||||
limit: Number(this.$route.query.limit) || 20,
|
limit: Number(this.$route.query.limit) || 20,
|
||||||
expanded: false,
|
expanded: false,
|
||||||
|
entityUrl: null,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
@ -192,15 +204,17 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.link {
|
.link {
|
||||||
max-width: 20rem;
|
max-width: 15rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: 1rem;
|
padding: .5rem 1rem;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.link-child {
|
.link-child {
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
fill: var(--lighten);
|
fill: var(--lighten);
|
||||||
margin: 0 0 0 1rem;
|
margin: 0 0 0 1rem;
|
||||||
|
@ -213,7 +227,15 @@ export default {
|
||||||
|
|
||||||
.link-parent {
|
.link-parent {
|
||||||
flex-direction: row-reverse;
|
flex-direction: row-reverse;
|
||||||
|
flex-shrink: 0;
|
||||||
margin: 0 0 0 3rem;
|
margin: 0 0 0 3rem;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
width: 1.25rem;
|
||||||
|
height: 1.25rem;
|
||||||
|
fill: var(--lighten);
|
||||||
|
margin: 0 .5rem 0 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo {
|
.logo {
|
||||||
|
@ -223,7 +245,7 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo-child {
|
.logo-child {
|
||||||
height: 2rem;
|
height: 3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo-parent {
|
.logo-parent {
|
||||||
|
@ -232,6 +254,7 @@ export default {
|
||||||
|
|
||||||
.favicon {
|
.favicon {
|
||||||
height: 1rem;
|
height: 1rem;
|
||||||
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-inner {
|
.content-inner {
|
||||||
|
@ -243,6 +266,12 @@ export default {
|
||||||
background: var(--profile);
|
background: var(--profile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.campaign-container {
|
||||||
|
background: var(--background-dim);
|
||||||
|
text-align: center;
|
||||||
|
padding: .5rem;
|
||||||
|
}
|
||||||
|
|
||||||
.releases {
|
.releases {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,13 +2,13 @@
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
<ul class="menu-items noselect">
|
<ul class="menu-items noselect">
|
||||||
<router-link
|
<router-link
|
||||||
v-if="auth && me"
|
v-if="login && me"
|
||||||
:to="{ name: 'user', params: { username: me.username } }"
|
:to="{ name: 'user', params: { username: me.username } }"
|
||||||
class="menu-username"
|
class="menu-username"
|
||||||
>{{ me.username }}</router-link>
|
>{{ me.username }}</router-link>
|
||||||
|
|
||||||
<router-link
|
<router-link
|
||||||
v-else-if="auth"
|
v-else-if="login"
|
||||||
:to="{ name: 'login', query: { ref: $route.path } }"
|
:to="{ name: 'login', query: { ref: $route.path } }"
|
||||||
class="menu-item"
|
class="menu-item"
|
||||||
@click.stop
|
@click.stop
|
||||||
|
@ -17,7 +17,7 @@
|
||||||
</router-link>
|
</router-link>
|
||||||
|
|
||||||
<li
|
<li
|
||||||
v-if="auth && me"
|
v-if="login && me"
|
||||||
class="menu-item"
|
class="menu-item"
|
||||||
@click.stop="$store.dispatch('logout')"
|
@click.stop="$store.dispatch('logout')"
|
||||||
>
|
>
|
||||||
|
@ -89,8 +89,12 @@ function theme(state) {
|
||||||
return state.ui.theme;
|
return state.ui.theme;
|
||||||
}
|
}
|
||||||
|
|
||||||
function auth(state) {
|
function login(state) {
|
||||||
return state.auth.enabled;
|
return state.auth.login;
|
||||||
|
}
|
||||||
|
|
||||||
|
function signup(state) {
|
||||||
|
return state.auth.signup;
|
||||||
}
|
}
|
||||||
|
|
||||||
function me(state) {
|
function me(state) {
|
||||||
|
@ -108,7 +112,8 @@ function setSfw(enabled) {
|
||||||
export default {
|
export default {
|
||||||
computed: {
|
computed: {
|
||||||
...mapState({
|
...mapState({
|
||||||
auth,
|
login,
|
||||||
|
signup,
|
||||||
sfw,
|
sfw,
|
||||||
theme,
|
theme,
|
||||||
me,
|
me,
|
||||||
|
|
|
@ -47,6 +47,10 @@
|
||||||
@close="$router.replace({ hash: undefined })"
|
@close="$router.replace({ hash: undefined })"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<div class="campaign-container">
|
||||||
|
<Campaign :tag="tag" />
|
||||||
|
</div>
|
||||||
|
|
||||||
<FilterBar
|
<FilterBar
|
||||||
ref="filter"
|
ref="filter"
|
||||||
:fetch-releases="fetchReleases"
|
:fetch-releases="fetchReleases"
|
||||||
|
@ -76,6 +80,7 @@ import Album from '../album/album.vue';
|
||||||
import Releases from '../releases/releases.vue';
|
import Releases from '../releases/releases.vue';
|
||||||
import Pagination from '../pagination/pagination.vue';
|
import Pagination from '../pagination/pagination.vue';
|
||||||
import Scroll from '../scroll/scroll.vue';
|
import Scroll from '../scroll/scroll.vue';
|
||||||
|
import Campaign from '../campaigns/campaign.vue';
|
||||||
|
|
||||||
const converter = new Converter();
|
const converter = new Converter();
|
||||||
|
|
||||||
|
@ -122,6 +127,7 @@ export default {
|
||||||
Photos,
|
Photos,
|
||||||
Pagination,
|
Pagination,
|
||||||
Scroll,
|
Scroll,
|
||||||
|
Campaign,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -172,12 +178,14 @@ export default {
|
||||||
@import 'theme';
|
@import 'theme';
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
|
display: flex;
|
||||||
background: var(--profile);
|
background: var(--profile);
|
||||||
color: var(--text-light);
|
color: var(--text-light);
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
|
display: inline-block;
|
||||||
padding: .5rem 1rem;
|
padding: .5rem 1rem;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
@ -200,4 +208,11 @@ export default {
|
||||||
.scroll {
|
.scroll {
|
||||||
background: var(--background-dim);
|
background: var(--background-dim);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.campaign-container {
|
||||||
|
max-height: 90px;
|
||||||
|
padding: .5rem 1rem 0 1rem;
|
||||||
|
background: var(--background-dim);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -21,16 +21,17 @@ $breakpoint4: 1500px;
|
||||||
--background-dark: #222;
|
--background-dark: #222;
|
||||||
|
|
||||||
--darken: rgba(0, 0, 0, .5);
|
--darken: rgba(0, 0, 0, .5);
|
||||||
--darken-strong: rgba(0, 0, 0, .7);
|
|
||||||
--darken-extreme: rgba(0, 0, 0, .9);
|
|
||||||
--darken-censor: rgba(0, 0, 0, .95);
|
--darken-censor: rgba(0, 0, 0, .95);
|
||||||
|
--darken-extreme: rgba(0, 0, 0, .9);
|
||||||
|
--darken-strong: rgba(0, 0, 0, .7);
|
||||||
--darken-weak: rgba(0, 0, 0, .2);
|
--darken-weak: rgba(0, 0, 0, .2);
|
||||||
--darken-hint: rgba(0, 0, 0, .1);
|
--darken-hint: rgba(0, 0, 0, .1);
|
||||||
--darken-touch: rgba(0, 0, 0, .05);
|
--darken-touch: rgba(0, 0, 0, .05);
|
||||||
|
|
||||||
--lighten: rgba(255, 255, 255, .5);
|
--lighten-censor: rgba(255, 255, 255, .95);
|
||||||
--lighten-strong: rgba(255, 255, 255, .7);
|
|
||||||
--lighten-extreme: rgba(255, 255, 255, .9);
|
--lighten-extreme: rgba(255, 255, 255, .9);
|
||||||
|
--lighten-strong: rgba(255, 255, 255, .7);
|
||||||
|
--lighten: rgba(255, 255, 255, .5);
|
||||||
--lighten-weak: rgba(255, 255, 255, .2);
|
--lighten-weak: rgba(255, 255, 255, .2);
|
||||||
--lighten-hint: rgba(255, 255, 255, .05);
|
--lighten-hint: rgba(255, 255, 255, .05);
|
||||||
--lighten-touch: rgba(255, 255, 255, .03);
|
--lighten-touch: rgba(255, 255, 255, .03);
|
||||||
|
@ -58,6 +59,7 @@ $breakpoint4: 1500px;
|
||||||
--text-contrast: #fff;
|
--text-contrast: #fff;
|
||||||
|
|
||||||
--background: var(--background-light);
|
--background: var(--background-light);
|
||||||
|
--background-censor: rgba(255, 255, 255, .95);
|
||||||
--background-dim: #f5f5f5;
|
--background-dim: #f5f5f5;
|
||||||
--background-soft: #fdfdfd;
|
--background-soft: #fdfdfd;
|
||||||
|
|
||||||
|
@ -71,6 +73,7 @@ $breakpoint4: 1500px;
|
||||||
--crease: #eaeaea;
|
--crease: #eaeaea;
|
||||||
|
|
||||||
--shadow: rgba(0, 0, 0, .5);
|
--shadow: rgba(0, 0, 0, .5);
|
||||||
|
--shadow-censor: rgba(0, 0, 0, .95);
|
||||||
--shadow-extreme: rgba(0, 0, 0, .9);
|
--shadow-extreme: rgba(0, 0, 0, .9);
|
||||||
--shadow-strong: rgba(0, 0, 0, .7);
|
--shadow-strong: rgba(0, 0, 0, .7);
|
||||||
--shadow-modest: rgba(0, 0, 0, .3);
|
--shadow-modest: rgba(0, 0, 0, .3);
|
||||||
|
@ -91,6 +94,7 @@ $breakpoint4: 1500px;
|
||||||
--text-contrast: #222;
|
--text-contrast: #222;
|
||||||
|
|
||||||
--background: #181818;
|
--background: #181818;
|
||||||
|
--background-censor: rgba(0, 0, 0, .95);
|
||||||
--background-dim: #111;
|
--background-dim: #111;
|
||||||
--background-soft: #000;
|
--background-soft: #000;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
export default {
|
export default {
|
||||||
enabled: window.env.auth,
|
login: window.env.login,
|
||||||
|
signup: window.env.signup,
|
||||||
user: null,
|
user: null,
|
||||||
};
|
};
|
||||||
|
|
|
@ -126,6 +126,7 @@ function curateTag(tag) {
|
||||||
};
|
};
|
||||||
|
|
||||||
if (tag.releases) curatedTag.releases = tag.releases.map(({ release }) => curateRelease(release));
|
if (tag.releases) curatedTag.releases = tag.releases.map(({ release }) => curateRelease(release));
|
||||||
|
if (tag.banners) curatedTag.banners = tag.banners.map(({ banner }) => banner);
|
||||||
if (tag.photos) curatedTag.photos = tag.photos.map(({ media }) => media);
|
if (tag.photos) curatedTag.photos = tag.photos.map(({ media }) => media);
|
||||||
if (tag.poster) curatedTag.poster = tag.poster.media;
|
if (tag.poster) curatedTag.poster = tag.poster.media;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { graphql } from '../api';
|
import { graphql } from '../api';
|
||||||
// import { sitesFragment, releaseFields } from '../fragments';
|
// import { sitesFragment, releaseFields } from '../fragments';
|
||||||
import { releaseFields } from '../fragments';
|
import { releaseFields, campaignsFragment } from '../fragments';
|
||||||
import { curateEntity } from '../curate';
|
import { curateEntity } from '../curate';
|
||||||
import getDateRange from '../get-date-range';
|
import getDateRange from '../get-date-range';
|
||||||
|
|
||||||
|
@ -63,8 +63,10 @@ function initEntitiesActions(store, router) {
|
||||||
priority
|
priority
|
||||||
independent
|
independent
|
||||||
hasLogo
|
hasLogo
|
||||||
|
${campaignsFragment}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
${campaignsFragment}
|
||||||
parent {
|
parent {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
|
@ -73,6 +75,7 @@ function initEntitiesActions(store, router) {
|
||||||
url
|
url
|
||||||
independent
|
independent
|
||||||
hasLogo
|
hasLogo
|
||||||
|
${campaignsFragment}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
connection: releasesConnection(
|
connection: releasesConnection(
|
||||||
|
|
|
@ -96,6 +96,62 @@ const actorFields = `
|
||||||
${actorStashesFields}
|
${actorStashesFields}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const campaignsFragment = `
|
||||||
|
campaigns(filter: {
|
||||||
|
or: [
|
||||||
|
{
|
||||||
|
banner: {
|
||||||
|
bannersTagsConnection: {
|
||||||
|
none: {
|
||||||
|
tag: {
|
||||||
|
slug: {
|
||||||
|
in: $exclude
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
bannerExists: false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}) {
|
||||||
|
id
|
||||||
|
url
|
||||||
|
banner {
|
||||||
|
id
|
||||||
|
width
|
||||||
|
height
|
||||||
|
ratio
|
||||||
|
entity {
|
||||||
|
id
|
||||||
|
type
|
||||||
|
name
|
||||||
|
slug
|
||||||
|
parent {
|
||||||
|
id
|
||||||
|
type
|
||||||
|
name
|
||||||
|
slug
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
entity {
|
||||||
|
id
|
||||||
|
type
|
||||||
|
name
|
||||||
|
slug
|
||||||
|
parent {
|
||||||
|
id
|
||||||
|
type
|
||||||
|
name
|
||||||
|
slug
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
const releaseActorsFragment = `
|
const releaseActorsFragment = `
|
||||||
actors: releasesActors(orderBy: ACTOR_BY_ACTOR_ID__GENDER_ASC) {
|
actors: releasesActors(orderBy: ACTOR_BY_ACTOR_ID__GENDER_ASC) {
|
||||||
actor {
|
actor {
|
||||||
|
@ -480,6 +536,7 @@ function getIncludedActors(router) {
|
||||||
export {
|
export {
|
||||||
actorFields,
|
actorFields,
|
||||||
actorStashesFields,
|
actorStashesFields,
|
||||||
|
campaignsFragment,
|
||||||
releaseActorsFragment,
|
releaseActorsFragment,
|
||||||
releaseFields,
|
releaseFields,
|
||||||
releaseTagsFragment,
|
releaseTagsFragment,
|
||||||
|
|
|
@ -26,6 +26,31 @@ const dateRanges = {
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* requires PostgreSQL 12.x> not available in production yet
|
||||||
|
const dateRanges = {
|
||||||
|
latest: () => ({
|
||||||
|
after: '1900-01-01',
|
||||||
|
before: dayjs.utc().toDate(),
|
||||||
|
orderBy: ['EFFECTIVE_DATE_DESC'],
|
||||||
|
}),
|
||||||
|
upcoming: () => ({
|
||||||
|
after: dayjs.utc().toDate(),
|
||||||
|
before: '2100-01-01',
|
||||||
|
orderBy: ['EFFECTIVE_DATE_DESC'],
|
||||||
|
}),
|
||||||
|
new: () => ({
|
||||||
|
after: '1900-01-01 00:00:00',
|
||||||
|
before: '2100-01-01',
|
||||||
|
orderBy: ['CREATED_AT_DESC', 'EFFECTIVE_DATE_ASC'],
|
||||||
|
}),
|
||||||
|
all: () => ({
|
||||||
|
after: '1900-01-01',
|
||||||
|
before: '2100-01-01',
|
||||||
|
orderBy: ['EFFECTIVE_DATE_DESC'],
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
function getDateRange(range) {
|
function getDateRange(range) {
|
||||||
return (dateRanges[range] || dateRanges.all)();
|
return (dateRanges[range] || dateRanges.all)();
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,6 +103,56 @@ function initTagsActions(store, _router) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
banners: bannersTags(filter: {
|
||||||
|
banner: {
|
||||||
|
bannersTagsConnection: {
|
||||||
|
none: {
|
||||||
|
tag: {
|
||||||
|
slug: {
|
||||||
|
in: $exclude
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
banner {
|
||||||
|
id
|
||||||
|
width
|
||||||
|
height
|
||||||
|
ratio
|
||||||
|
entity {
|
||||||
|
id
|
||||||
|
type
|
||||||
|
name
|
||||||
|
slug
|
||||||
|
independent
|
||||||
|
parent {
|
||||||
|
id
|
||||||
|
type
|
||||||
|
name
|
||||||
|
slug
|
||||||
|
independent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
campaigns {
|
||||||
|
id
|
||||||
|
url
|
||||||
|
entity {
|
||||||
|
id
|
||||||
|
type
|
||||||
|
name
|
||||||
|
slug
|
||||||
|
parent {
|
||||||
|
id
|
||||||
|
type
|
||||||
|
name
|
||||||
|
slug
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
scenesConnection(
|
scenesConnection(
|
||||||
filter: {
|
filter: {
|
||||||
date: {
|
date: {
|
||||||
|
|
|
@ -35,7 +35,8 @@ module.exports = {
|
||||||
secretKey: 'abcdefghijklmnopqrstuvwxyz1234567890ABCD',
|
secretKey: 'abcdefghijklmnopqrstuvwxyz1234567890ABCD',
|
||||||
},
|
},
|
||||||
auth: {
|
auth: {
|
||||||
enabled: true,
|
login: true,
|
||||||
|
signup: true,
|
||||||
},
|
},
|
||||||
exclude: {
|
exclude: {
|
||||||
channels: [
|
channels: [
|
||||||
|
|
|
@ -1274,11 +1274,78 @@ exports.up = knex => Promise.resolve()
|
||||||
.notNullable()
|
.notNullable()
|
||||||
.defaultTo(knex.fn.now());
|
.defaultTo(knex.fn.now());
|
||||||
}))
|
}))
|
||||||
// SEARCH
|
.then(() => knex.schema.createTable('banners', (table) => {
|
||||||
|
table.string('id')
|
||||||
|
.primary()
|
||||||
|
.unique()
|
||||||
|
.notNullable();
|
||||||
|
|
||||||
|
table.integer('width')
|
||||||
|
.notNullable();
|
||||||
|
|
||||||
|
table.integer('height')
|
||||||
|
.notNullable();
|
||||||
|
|
||||||
|
table.integer('entity_id', 12)
|
||||||
|
.references('id')
|
||||||
|
.inTable('entities');
|
||||||
|
|
||||||
|
table.text('comment');
|
||||||
|
|
||||||
|
table.datetime('created_at')
|
||||||
|
.notNullable()
|
||||||
|
.defaultTo(knex.fn.now());
|
||||||
|
}))
|
||||||
|
.then(() => knex.schema.createTable('banners_tags', (table) => {
|
||||||
|
table.increments('id');
|
||||||
|
|
||||||
|
table.string('banner_id')
|
||||||
|
.notNullable()
|
||||||
|
.references('id')
|
||||||
|
.inTable('banners');
|
||||||
|
|
||||||
|
table.integer('tag_id')
|
||||||
|
.notNullable()
|
||||||
|
.references('id')
|
||||||
|
.inTable('tags');
|
||||||
|
|
||||||
|
table.unique(['banner_id', 'tag_id']);
|
||||||
|
|
||||||
|
table.datetime('created_at')
|
||||||
|
.notNullable()
|
||||||
|
.defaultTo(knex.fn.now());
|
||||||
|
}))
|
||||||
|
.then(() => knex.schema.createTable('campaigns', (table) => {
|
||||||
|
table.increments('id');
|
||||||
|
|
||||||
|
table.integer('entity_id', 12)
|
||||||
|
.notNullable()
|
||||||
|
.references('id')
|
||||||
|
.inTable('entities');
|
||||||
|
|
||||||
|
table.string('banner_id')
|
||||||
|
.references('id')
|
||||||
|
.inTable('banners');
|
||||||
|
|
||||||
|
table.text('url')
|
||||||
|
.notNullable();
|
||||||
|
|
||||||
|
table.text('comment');
|
||||||
|
|
||||||
|
table.datetime('created_at')
|
||||||
|
.notNullable()
|
||||||
|
.defaultTo(knex.fn.now());
|
||||||
|
}))
|
||||||
|
// SEARCH AND SORT
|
||||||
.then(() => { // eslint-disable-line arrow-body-style
|
.then(() => { // eslint-disable-line arrow-body-style
|
||||||
// allow vim fold
|
// allow vim fold
|
||||||
return knex.raw(`
|
return knex.raw(`
|
||||||
ALTER TABLE releases_search ADD COLUMN document tsvector;
|
ALTER TABLE releases_search ADD COLUMN document tsvector;
|
||||||
|
|
||||||
|
/* allow scenes without dates to be mixed inbetween scenes with dates */
|
||||||
|
ALTER TABLE releases
|
||||||
|
ADD COLUMN effective_date timestamptz
|
||||||
|
GENERATED ALWAYS AS (COALESCE(date, created_at)) STORED;
|
||||||
`);
|
`);
|
||||||
})
|
})
|
||||||
// INDEXES
|
// INDEXES
|
||||||
|
@ -1288,6 +1355,9 @@ exports.up = knex => Promise.resolve()
|
||||||
CREATE UNIQUE INDEX unique_actor_slugs_network ON actors (slug, entity_id, entry_id);
|
CREATE UNIQUE INDEX unique_actor_slugs_network ON actors (slug, entity_id, entry_id);
|
||||||
CREATE UNIQUE INDEX unique_actor_slugs ON actors (slug) WHERE entity_id IS NULL;
|
CREATE UNIQUE INDEX unique_actor_slugs ON actors (slug) WHERE entity_id IS NULL;
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX unique_entity_campaigns_banner ON campaigns (entity_id, url, banner_id);
|
||||||
|
CREATE UNIQUE INDEX unique_entity_campaigns ON campaigns (entity_id, url) WHERE banner_id IS NULL;
|
||||||
|
|
||||||
CREATE UNIQUE INDEX releases_search_unique ON releases_search (release_id);
|
CREATE UNIQUE INDEX releases_search_unique ON releases_search (release_id);
|
||||||
CREATE INDEX releases_search_index ON releases_search USING GIN (document);
|
CREATE INDEX releases_search_index ON releases_search USING GIN (document);
|
||||||
`);
|
`);
|
||||||
|
@ -1476,6 +1546,10 @@ exports.up = knex => Promise.resolve()
|
||||||
CREATE FUNCTION releases_is_new(release releases) RETURNS boolean AS $$
|
CREATE FUNCTION releases_is_new(release releases) RETURNS boolean AS $$
|
||||||
SELECT EXISTS(SELECT true WHERE (SELECT id FROM batches ORDER BY created_at DESC LIMIT 1) = release.created_batch_id);
|
SELECT EXISTS(SELECT true WHERE (SELECT id FROM batches ORDER BY created_at DESC LIMIT 1) = release.created_batch_id);
|
||||||
$$ LANGUAGE sql STABLE;
|
$$ LANGUAGE sql STABLE;
|
||||||
|
|
||||||
|
CREATE FUNCTION banners_ratio(banner banners) RETURNS real AS $$
|
||||||
|
SELECT ROUND(banner.width::decimal / banner.height::decimal, 2);
|
||||||
|
$$ LANGUAGE SQL STABLE;
|
||||||
`);
|
`);
|
||||||
})
|
})
|
||||||
// POLICIES
|
// POLICIES
|
||||||
|
@ -1642,6 +1716,9 @@ exports.down = (knex) => { // eslint-disable-line arrow-body-style
|
||||||
DROP TABLE IF EXISTS chapters_posters CASCADE;
|
DROP TABLE IF EXISTS chapters_posters CASCADE;
|
||||||
DROP TABLE IF EXISTS chapters_photos CASCADE;
|
DROP TABLE IF EXISTS chapters_photos CASCADE;
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS banners_tags CASCADE;
|
||||||
|
DROP TABLE IF EXISTS banners CASCADE;
|
||||||
|
DROP TABLE IF EXISTS campaigns CASCADE;
|
||||||
DROP TABLE IF EXISTS batches CASCADE;
|
DROP TABLE IF EXISTS batches CASCADE;
|
||||||
|
|
||||||
DROP TABLE IF EXISTS actors_avatars CASCADE;
|
DROP TABLE IF EXISTS actors_avatars CASCADE;
|
||||||
|
@ -1654,6 +1731,7 @@ exports.down = (knex) => { // eslint-disable-line arrow-body-style
|
||||||
|
|
||||||
DROP TABLE IF EXISTS entities_tags CASCADE;
|
DROP TABLE IF EXISTS entities_tags CASCADE;
|
||||||
DROP TABLE IF EXISTS entities_social CASCADE;
|
DROP TABLE IF EXISTS entities_social CASCADE;
|
||||||
|
|
||||||
DROP TABLE IF EXISTS sites_tags CASCADE;
|
DROP TABLE IF EXISTS sites_tags CASCADE;
|
||||||
DROP TABLE IF EXISTS sites_social CASCADE;
|
DROP TABLE IF EXISTS sites_social CASCADE;
|
||||||
DROP TABLE IF EXISTS networks_social CASCADE;
|
DROP TABLE IF EXISTS networks_social CASCADE;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "traxxx",
|
"name": "traxxx",
|
||||||
"version": "1.195.0",
|
"version": "1.196.1",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "traxxx",
|
"name": "traxxx",
|
||||||
"version": "1.195.0",
|
"version": "1.196.1",
|
||||||
"description": "All the latest porn releases in one place",
|
"description": "All the latest porn releases in one place",
|
||||||
"main": "src/app.js",
|
"main": "src/app.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
After Width: | Height: | Size: 48 KiB |
After Width: | Height: | Size: 85 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 87 KiB |
After Width: | Height: | Size: 83 KiB |
After Width: | Height: | Size: 90 KiB |
After Width: | Height: | Size: 70 KiB |
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 81 KiB |
After Width: | Height: | Size: 72 KiB |
After Width: | Height: | Size: 72 KiB |
After Width: | Height: | Size: 72 KiB |
After Width: | Height: | Size: 27 KiB |
After Width: | Height: | Size: 47 KiB |
After Width: | Height: | Size: 65 KiB |
After Width: | Height: | Size: 127 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 148 KiB |
After Width: | Height: | Size: 6.9 KiB |
After Width: | Height: | Size: 3.7 MiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 9.4 KiB |
After Width: | Height: | Size: 2.3 MiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 12 MiB |
After Width: | Height: | Size: 8.1 KiB |
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 6.0 MiB |
After Width: | Height: | Size: 5.1 MiB |
After Width: | Height: | Size: 3.9 MiB |
After Width: | Height: | Size: 6.8 KiB |
After Width: | Height: | Size: 6.4 KiB |
After Width: | Height: | Size: 7.1 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 31 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 5.9 MiB |
After Width: | Height: | Size: 2.5 MiB |
After Width: | Height: | Size: 4.1 MiB |
After Width: | Height: | Size: 2.0 MiB |
After Width: | Height: | Size: 3.9 MiB |
After Width: | Height: | Size: 3.2 MiB |
After Width: | Height: | Size: 4.3 MiB |
After Width: | Height: | Size: 6.4 KiB |
After Width: | Height: | Size: 7.0 KiB |
After Width: | Height: | Size: 6.5 KiB |
After Width: | Height: | Size: 6.9 KiB |
After Width: | Height: | Size: 7.1 KiB |
After Width: | Height: | Size: 6.9 KiB |
After Width: | Height: | Size: 7.0 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 31 KiB |
After Width: | Height: | Size: 444 KiB |
After Width: | Height: | Size: 9.1 KiB |
After Width: | Height: | Size: 48 KiB |
After Width: | Height: | Size: 11 MiB |
After Width: | Height: | Size: 9.9 KiB |
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 2.0 MiB |
After Width: | Height: | Size: 1.4 MiB |
After Width: | Height: | Size: 9.4 KiB |
After Width: | Height: | Size: 8.9 KiB |
After Width: | Height: | Size: 44 KiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 7.8 KiB |
After Width: | Height: | Size: 3.0 MiB |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 12 MiB |
After Width: | Height: | Size: 14 MiB |
After Width: | Height: | Size: 13 MiB |
After Width: | Height: | Size: 11 MiB |
After Width: | Height: | Size: 11 MiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 9.7 KiB |
After Width: | Height: | Size: 9.8 KiB |
After Width: | Height: | Size: 49 KiB |