forked from AkkomaGang/akkoma-fe
Compare commits
11 Commits
5a4315384e
...
e9f47509ae
Author | SHA1 | Date |
---|---|---|
Sol Fisher Romanoff | e9f47509ae | |
floatingghost | dfba8be134 | |
FloatingGhost | 313ddcebcb | |
FloatingGhost | 236b19e854 | |
FloatingGhost | ea941d7cfa | |
Beefox | 2e5001e5de | |
Norm | 014f8b0dd2 | |
floatingghost | dd403b295f | |
Sol Fisher Romanoff | 9cd62fe08d | |
FloatingGhost | f668455dff | |
FloatingGhost | da491f3278 |
|
@ -25,6 +25,7 @@
|
||||||
"@kazvmoe-infra/pinch-zoom-element": "1.2.0",
|
"@kazvmoe-infra/pinch-zoom-element": "1.2.0",
|
||||||
"@vuelidate/core": "^2.0.0",
|
"@vuelidate/core": "^2.0.0",
|
||||||
"@vuelidate/validators": "^2.0.0",
|
"@vuelidate/validators": "^2.0.0",
|
||||||
|
"blurhash": "^2.0.4",
|
||||||
"body-scroll-lock": "2.7.1",
|
"body-scroll-lock": "2.7.1",
|
||||||
"chromatism": "3.0.0",
|
"chromatism": "3.0.0",
|
||||||
"click-outside-vue3": "4.0.1",
|
"click-outside-vue3": "4.0.1",
|
||||||
|
|
|
@ -18,6 +18,7 @@ import {
|
||||||
faPencilAlt,
|
faPencilAlt,
|
||||||
faAlignRight
|
faAlignRight
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
import Blurhash from '../blurhash/Blurhash.vue'
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
faFile,
|
faFile,
|
||||||
|
@ -63,7 +64,8 @@ const Attachment = {
|
||||||
components: {
|
components: {
|
||||||
Flash,
|
Flash,
|
||||||
StillImage,
|
StillImage,
|
||||||
VideoAttachment
|
VideoAttachment,
|
||||||
|
Blurhash
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
classNames () {
|
classNames () {
|
||||||
|
@ -84,6 +86,9 @@ const Attachment = {
|
||||||
useContainFit () {
|
useContainFit () {
|
||||||
return this.$store.getters.mergedConfig.useContainFit
|
return this.$store.getters.mergedConfig.useContainFit
|
||||||
},
|
},
|
||||||
|
useBlurhash () {
|
||||||
|
return this.$store.getters.mergedConfig.useBlurhash
|
||||||
|
},
|
||||||
placeholderName () {
|
placeholderName () {
|
||||||
if (this.attachment.description === '' || !this.attachment.description) {
|
if (this.attachment.description === '' || !this.attachment.description) {
|
||||||
return this.type.toUpperCase()
|
return this.type.toUpperCase()
|
||||||
|
|
|
@ -64,7 +64,15 @@
|
||||||
:title="attachment.description"
|
:title="attachment.description"
|
||||||
@click.prevent.stop="toggleHidden"
|
@click.prevent.stop="toggleHidden"
|
||||||
>
|
>
|
||||||
|
<Blurhash
|
||||||
|
v-if="useBlurhash && attachment.blurhash"
|
||||||
|
:height="512"
|
||||||
|
:width="1024"
|
||||||
|
:hash="attachment.blurhash"
|
||||||
|
:punch="1"
|
||||||
|
/>
|
||||||
<img
|
<img
|
||||||
|
v-else
|
||||||
:key="nsfwImage"
|
:key="nsfwImage"
|
||||||
class="nsfw"
|
class="nsfw"
|
||||||
:src="nsfwImage"
|
:src="nsfwImage"
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
<template>
|
||||||
|
<canvas
|
||||||
|
ref="canvas"
|
||||||
|
class="blurhash"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { decode } from "blurhash";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Blurhash',
|
||||||
|
props: {
|
||||||
|
hash: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
width: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
punch: {
|
||||||
|
type: Number,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
canvas: null,
|
||||||
|
ctx: null,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.canvas = this.$refs.canvas;
|
||||||
|
this.ctx = this.canvas.getContext('2d');
|
||||||
|
this.canvas.width = 1024;
|
||||||
|
this.canvas.height = 512;
|
||||||
|
this.draw();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
draw() {
|
||||||
|
const pixels = decode(this.hash, this.width, this.height, this.punch);
|
||||||
|
const imageData = this.ctx.createImageData(this.width, this.height);
|
||||||
|
imageData.data.set(pixels);
|
||||||
|
this.ctx.putImageData(imageData, 0, 0);
|
||||||
|
fetch("/static/blurhash-overlay.png")
|
||||||
|
.then((response) => response.blob())
|
||||||
|
.then((blob) => {
|
||||||
|
const img = new Image();
|
||||||
|
img.src = URL.createObjectURL(blob);
|
||||||
|
img.onload = () => {
|
||||||
|
this.ctx.drawImage(img, 0, 0, this.width, this.height);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -18,6 +18,7 @@
|
||||||
<EmojiPicker
|
<EmojiPicker
|
||||||
v-if="enableEmojiPicker"
|
v-if="enableEmojiPicker"
|
||||||
ref="picker"
|
ref="picker"
|
||||||
|
show-keep-open
|
||||||
:class="{ hide: !showPicker }"
|
:class="{ hide: !showPicker }"
|
||||||
:enable-sticker-picker="enableStickerPicker"
|
:enable-sticker-picker="enableStickerPicker"
|
||||||
class="emoji-picker-panel"
|
class="emoji-picker-panel"
|
||||||
|
|
|
@ -27,6 +27,11 @@ const EmojiPicker = {
|
||||||
required: false,
|
required: false,
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
|
},
|
||||||
|
showKeepOpen: {
|
||||||
|
required: false,
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
left: -70%;
|
left: -70%;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
@media (min-width: 800px) and (max-width: 1300px) {
|
@media (min-width: 800px) and (max-width: 1280px) {
|
||||||
left: -50%;
|
left: -50%;
|
||||||
min-width: 50%;
|
min-width: 50%;
|
||||||
max-width: 130%;
|
max-width: 130%;
|
||||||
|
|
|
@ -84,7 +84,10 @@
|
||||||
<span :ref="'group-end-' + group.id" />
|
<span :ref="'group-end-' + group.id" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="keep-open">
|
<div
|
||||||
|
v-if="showKeepOpen"
|
||||||
|
class="keep-open"
|
||||||
|
>
|
||||||
<Checkbox v-model="keepOpen">
|
<Checkbox v-model="keepOpen">
|
||||||
{{ $t('emoji.keep_open') }}
|
{{ $t('emoji.keep_open') }}
|
||||||
</Checkbox>
|
</Checkbox>
|
||||||
|
|
|
@ -407,6 +407,15 @@
|
||||||
{{ $t('settings.preload_images') }}
|
{{ $t('settings.preload_images') }}
|
||||||
</BooleanSetting>
|
</BooleanSetting>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting
|
||||||
|
path="useBlurhash"
|
||||||
|
expert="1"
|
||||||
|
:disabled="!hideNsfw"
|
||||||
|
>
|
||||||
|
{{ $t('settings.use_blurhash') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<BooleanSetting
|
<BooleanSetting
|
||||||
path="useOneClickNsfw"
|
path="useOneClickNsfw"
|
||||||
|
|
|
@ -10,11 +10,13 @@ import withLoadMore from '../../hocs/with_load_more/with_load_more'
|
||||||
import { debounce } from 'lodash'
|
import { debounce } from 'lodash'
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import {
|
import {
|
||||||
faCircleNotch
|
faCircleNotch,
|
||||||
|
faCircleCheck
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
faCircleNotch
|
faCircleNotch,
|
||||||
|
faCircleCheck
|
||||||
)
|
)
|
||||||
|
|
||||||
const FollowerList = withLoadMore({
|
const FollowerList = withLoadMore({
|
||||||
|
|
|
@ -37,6 +37,15 @@
|
||||||
:html="field.value"
|
:html="field.value"
|
||||||
:emoji="user.emoji"
|
:emoji="user.emoji"
|
||||||
/>
|
/>
|
||||||
|
<span
|
||||||
|
v-if="field.verified_at"
|
||||||
|
class="user-profile-field-validated"
|
||||||
|
>
|
||||||
|
<FAIcon
|
||||||
|
icon="check-circle"
|
||||||
|
:title="$t('user_profile.field_validated')"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
|
@ -95,10 +104,9 @@
|
||||||
v-if="followsTabVisible"
|
v-if="followsTabVisible"
|
||||||
key="followees"
|
key="followees"
|
||||||
:label="$t('user_card.followees')"
|
:label="$t('user_card.followees')"
|
||||||
:disabled="!user.friends_count"
|
|
||||||
>
|
>
|
||||||
<FriendList :user-id="userId">
|
<FriendList :user-id="userId">
|
||||||
<template v-slot:item="{item}">
|
<template #item="{item}">
|
||||||
<FollowCard :user="item" />
|
<FollowCard :user="item" />
|
||||||
</template>
|
</template>
|
||||||
</FriendList>
|
</FriendList>
|
||||||
|
@ -107,10 +115,9 @@
|
||||||
v-if="followersTabVisible"
|
v-if="followersTabVisible"
|
||||||
key="followers"
|
key="followers"
|
||||||
:label="$t('user_card.followers')"
|
:label="$t('user_card.followers')"
|
||||||
:disabled="!user.followers_count"
|
|
||||||
>
|
>
|
||||||
<FollowerList :user-id="userId">
|
<FollowerList :user-id="userId">
|
||||||
<template v-slot:item="{item}">
|
<template #item="{item}">
|
||||||
<FollowCard
|
<FollowCard
|
||||||
:user="item"
|
:user="item"
|
||||||
:no-follows-you="isUs"
|
:no-follows-you="isUs"
|
||||||
|
@ -225,6 +232,11 @@
|
||||||
padding: 0.5em 1.5em;
|
padding: 0.5em 1.5em;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.user-profile-field-validated {
|
||||||
|
margin-left: 1rem;
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -939,6 +939,7 @@
|
||||||
"title": "Version"
|
"title": "Version"
|
||||||
},
|
},
|
||||||
"virtual_scrolling": "Optimize timeline rendering",
|
"virtual_scrolling": "Optimize timeline rendering",
|
||||||
|
"use_blurhash": "Use blurhashes for NSFW thumbnails",
|
||||||
"word_filter": "Word filter",
|
"word_filter": "Word filter",
|
||||||
"wordfilter": "Wordfilter"
|
"wordfilter": "Wordfilter"
|
||||||
},
|
},
|
||||||
|
@ -1183,7 +1184,8 @@
|
||||||
"user_profile": {
|
"user_profile": {
|
||||||
"profile_does_not_exist": "Sorry, this profile does not exist.",
|
"profile_does_not_exist": "Sorry, this profile does not exist.",
|
||||||
"profile_loading_error": "Sorry, there was an error loading this profile.",
|
"profile_loading_error": "Sorry, there was an error loading this profile.",
|
||||||
"timeline_title": "User timeline"
|
"timeline_title": "User timeline",
|
||||||
|
"field_validated": "Link Verified"
|
||||||
},
|
},
|
||||||
"user_reporting": {
|
"user_reporting": {
|
||||||
"add_comment_description": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
|
"add_comment_description": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
|
||||||
|
|
|
@ -117,7 +117,8 @@ export const defaultState = {
|
||||||
maxDepthInThread: undefined, // instance default
|
maxDepthInThread: undefined, // instance default
|
||||||
translationLanguage: undefined, // instance default,
|
translationLanguage: undefined, // instance default,
|
||||||
supportedTranslationLanguages: {}, // instance default
|
supportedTranslationLanguages: {}, // instance default
|
||||||
userProfileDefaultTab: 'statuses'
|
userProfileDefaultTab: 'statuses',
|
||||||
|
useBlurhash: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
// caching the instance default properties
|
// caching the instance default properties
|
||||||
|
|
|
@ -186,7 +186,7 @@ const interfaceMod = {
|
||||||
if (thirdColumnMode === 'none' || !rootState.users.currentUser) {
|
if (thirdColumnMode === 'none' || !rootState.users.currentUser) {
|
||||||
commit('setLayoutType', normalOrMobile)
|
commit('setLayoutType', normalOrMobile)
|
||||||
} else {
|
} else {
|
||||||
const wideLayout = width >= 1300
|
const wideLayout = width >= 1280
|
||||||
commit('setLayoutType', wideLayout ? 'wide' : normalOrMobile)
|
commit('setLayoutType', wideLayout ? 'wide' : normalOrMobile)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -68,13 +68,15 @@ export const parseUser = (data) => {
|
||||||
output.fields_html = data.fields.map(field => {
|
output.fields_html = data.fields.map(field => {
|
||||||
return {
|
return {
|
||||||
name: escape(field.name),
|
name: escape(field.name),
|
||||||
value: field.value
|
value: field.value,
|
||||||
|
verified_at: field.verified_at
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
output.fields_text = data.fields.map(field => {
|
output.fields_text = data.fields.map(field => {
|
||||||
return {
|
return {
|
||||||
name: unescape(field.name.replace(/<[^>]*>/g, '')),
|
name: unescape(field.name.replace(/<[^>]*>/g, '')),
|
||||||
value: unescape(field.value.replace(/<[^>]*>/g, ''))
|
value: unescape(field.value.replace(/<[^>]*>/g, '')),
|
||||||
|
verified_at: field.verified_at
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -232,13 +234,14 @@ export const parseAttachment = (data) => {
|
||||||
if (masto) {
|
if (masto) {
|
||||||
// Not exactly same...
|
// Not exactly same...
|
||||||
output.mimetype = data.pleroma ? data.pleroma.mime_type : data.type
|
output.mimetype = data.pleroma ? data.pleroma.mime_type : data.type
|
||||||
output.meta = data.meta // not present in BE yet
|
output.meta = data.meta
|
||||||
output.id = data.id
|
output.id = data.id
|
||||||
} else {
|
} else {
|
||||||
output.mimetype = data.mimetype
|
output.mimetype = data.mimetype
|
||||||
// output.meta = ??? missing
|
// output.meta = ??? missing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
output.blurhash = data.blurhash
|
||||||
output.url = data.url
|
output.url = data.url
|
||||||
output.large_thumb_url = data.preview_url
|
output.large_thumb_url = data.preview_url
|
||||||
output.description = data.description
|
output.description = data.description
|
||||||
|
|
45
static/.tos
45
static/.tos
|
@ -1,45 +0,0 @@
|
||||||
<h4>Terms of Service</h4>
|
|
||||||
|
|
||||||
<p>It's mainly "be nice"</p>
|
|
||||||
|
|
||||||
<ol>
|
|
||||||
<li>
|
|
||||||
<h3>Don't be a big meanie</h4>
|
|
||||||
<p>Arguments are cool and all but don't make them into flamewars. Try to act in good faith - we want to be at least on good terms with people. Please act with understanding towards others on this instance. Most people here are probably struggling with a lot, be mindful of that.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<h3>Mark your lewds!</h3>
|
|
||||||
<p>Reminder that lewd is bad and nobody wants to be forced to see that. Just mark it sensitive, and post unlisted. That is to say, anything suggestive/ecchi upwards should be marked. If you wouldn't look at it with your parents/boss in the room, mark it. It goes without saying that if you're <em>going</em> to post lewd stuff, keep it sensible. Obviously nothing underaged or otherwise questionable. Or you could just not post lewd stuff. Either/or.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<h3>This is a <b>Kink Shame Zone</b></h3>
|
|
||||||
<p>Being a lewdie will be met with many anime girl reaction images shaming you for your lewdness. Go think about icky things on someone else's webzone™</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<h3>Keep it legal!</h3>
|
|
||||||
<p>Server is hosted in france, keep content legal for there (+ wherever you're browsing from)</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<h3>No ads/spambots</h3>
|
|
||||||
<p>I didn't think I'd have to specify this, but please do not set up bots solely for trying to advertise.</h3>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<h3>Non-TOS recommendations</h3>
|
|
||||||
<p>This is stuff that'd I'd <em>like</em> you to do, but I won't outright ban you if you don't follow them</p>
|
|
||||||
<ul>
|
|
||||||
<li>If someone is sadposting, don't antagonise them - they probably just want to vent</li>
|
|
||||||
<li>Put walls of text behind a subject (CW) - helps the timeline not get flooded with text</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li>
|
|
||||||
<h3>Other</h3>
|
|
||||||
<p>If you're here and you happen to play minecraft, feel free to message me with your username and come play with us sometime!</p>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
</ol>
|
|
||||||
|
|
||||||
<p>So I guess yeah, that's about it. Try to be nice, eh? We're probably all sad here.</p>
|
|
||||||
|
|
||||||
<br>
|
|
||||||
<img src="/static/logo.png" style="display: block; margin: auto; max-width: 100%; height: 50px; object-fit: contain;" />
|
|
Binary file not shown.
After Width: | Height: | Size: 27 KiB |
BIN
static/logo.png
BIN
static/logo.png
Binary file not shown.
Before Width: | Height: | Size: 5.8 KiB |
|
@ -2494,6 +2494,11 @@ binary-extensions@^2.0.0:
|
||||||
resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz"
|
resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz"
|
||||||
integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
|
integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
|
||||||
|
|
||||||
|
blurhash@^2.0.4:
|
||||||
|
version "2.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/blurhash/-/blurhash-2.0.4.tgz#60642a823b50acaaf3732ddb6c7dfd721bdfef2a"
|
||||||
|
integrity sha512-r/As72u2FbucLoK5NTegM/GucxJc3d8GvHc4ngo13IO/nt2HU4gONxNLq1XPN6EM/V8Y9URIa7PcSz2RZu553A==
|
||||||
|
|
||||||
body-parser@1.19.2:
|
body-parser@1.19.2:
|
||||||
version "1.19.2"
|
version "1.19.2"
|
||||||
resolved "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz"
|
resolved "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz"
|
||||||
|
|
Loading…
Reference in New Issue