merge upstream
This commit is contained in:
commit
5a43928be4
20 changed files with 309 additions and 14 deletions
15
README.md
15
README.md
|
|
@ -46,13 +46,28 @@ Upstream README is below.
|
||||||
- emojis are sourced from discord's list of emojis
|
- emojis are sourced from discord's list of emojis
|
||||||
- emojis are now sorted by category (like on every other emoji picker) instead of alphabetically
|
- emojis are now sorted by category (like on every other emoji picker) instead of alphabetically
|
||||||
- script to get new emojis is included for future unicode versions
|
- script to get new emojis is included for future unicode versions
|
||||||
|
- cat stuff!!
|
||||||
|
- toggles for:
|
||||||
|
- showing "cat" badge on user profiles
|
||||||
|
- showing cat ears behind users' avatars
|
||||||
|
- "nyaize"-ing posts from authors with "Speak as Cat" enabled
|
||||||
|
- this requires [a backend patch](https://git.notfire.cc/notfire/iceshrimp-patches/src/branch/main/0007-cat-fields-in-akko-api.patch)
|
||||||
- add toggle for showing post edit notifications
|
- add toggle for showing post edit notifications
|
||||||
- add support for accepted follow request notifications
|
- add support for accepted follow request notifications
|
||||||
|
- this requires [a backend patch](https://git.notfire.cc/notfire/iceshrimp-patches/src/branch/main/0005-previews-in-mastoapi.patch)
|
||||||
- add option to prevent page from getting pushed when making a new post with streaming api enabled (similar to 3rd "for unreads" option)
|
- add option to prevent page from getting pushed when making a new post with streaming api enabled (similar to 3rd "for unreads" option)
|
||||||
- add link on user card to open profiles in iceshrimp-fe
|
- add link on user card to open profiles in iceshrimp-fe
|
||||||
|
- add option to open conversation view by clicking empty space in posts
|
||||||
|
- add ability to close the reply box under posts that were deleted
|
||||||
|
- also an option to close it automatically
|
||||||
- add a script to download ruffle for flash support (requires python3 and requests library)
|
- add a script to download ruffle for flash support (requires python3 and requests library)
|
||||||
- download by entering `tools/` and running `python3 download_ruffle.py`
|
- download by entering `tools/` and running `python3 download_ruffle.py`
|
||||||
|
|
||||||
|
### also of note for anyone running this fork
|
||||||
|
- aside from the stuff mentioned above, the following features will require patches to work:
|
||||||
|
- mfm ([patch](https://git.notfire.cc/notfire/iceshrimp-patches/src/branch/main/0004-mfm-in-mastoapi.patch))
|
||||||
|
- previewing posts ([patch](https://git.notfire.cc/notfire/iceshrimp-patches/src/branch/main/0005-previews-in-mastoapi.patch))
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# Akkoma-FE
|
# Akkoma-FE
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@
|
||||||
"cropperjs": "^1.6.2",
|
"cropperjs": "^1.6.2",
|
||||||
"diff": "^5.2.0",
|
"diff": "^5.2.0",
|
||||||
"escape-html": "^1.0.3",
|
"escape-html": "^1.0.3",
|
||||||
|
"fast-average-color": "^9.5.0",
|
||||||
"iso-639-1": "^2.1.15",
|
"iso-639-1": "^2.1.15",
|
||||||
"js-cookie": "^3.0.1",
|
"js-cookie": "^3.0.1",
|
||||||
"localforage": "^1.10.0",
|
"localforage": "^1.10.0",
|
||||||
|
|
|
||||||
|
|
@ -180,6 +180,7 @@ const setSettings = async ({ apiConfig, staticConfig, store }) => {
|
||||||
copyInstanceOption('alwaysShowSubjectInput')
|
copyInstanceOption('alwaysShowSubjectInput')
|
||||||
copyInstanceOption('showFeaturesPanel')
|
copyInstanceOption('showFeaturesPanel')
|
||||||
copyInstanceOption('hideSitename')
|
copyInstanceOption('hideSitename')
|
||||||
|
copyInstanceOption('showCatFields')
|
||||||
copyInstanceOption('renderMisskeyMarkdown')
|
copyInstanceOption('renderMisskeyMarkdown')
|
||||||
copyInstanceOption('sidebarRight')
|
copyInstanceOption('sidebarRight')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -295,6 +295,16 @@
|
||||||
<FAIcon icon="eye-slash" />
|
<FAIcon icon="eye-slash" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
v-if="replyTo !== undefined && $parent.deleted"
|
||||||
|
class="poll-icon button-unstyled"
|
||||||
|
:title="$t('nav.close')"
|
||||||
|
@click="$parent.toggleReplying()"
|
||||||
|
>
|
||||||
|
<FAIcon icon="xmark" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<button
|
<button
|
||||||
v-if="posting"
|
v-if="posting"
|
||||||
disabled
|
disabled
|
||||||
|
|
|
||||||
|
|
@ -135,6 +135,9 @@ const GeneralTab = {
|
||||||
this.$store.dispatch('setOption', { name: 'postLanguage', value: val })
|
this.$store.dispatch('setOption', { name: 'postLanguage', value: val })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
catOptsAvail: {
|
||||||
|
get: function () { return this.$store.getters.mergedConfig.showCatFields }
|
||||||
|
},
|
||||||
...SharedComputedObject()
|
...SharedComputedObject()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
|
||||||
|
|
@ -240,6 +240,14 @@
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting
|
||||||
|
path="autoCloseReplyUIWhenPostDeleted"
|
||||||
|
expert="1"
|
||||||
|
>
|
||||||
|
{{ $t('settings.auto_close_reply_ui_when_post_deleted') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<BooleanSetting
|
<BooleanSetting
|
||||||
path="virtualScrolling"
|
path="virtualScrolling"
|
||||||
|
|
@ -311,6 +319,35 @@
|
||||||
{{ $t('settings.search_pagination_limit') }}
|
{{ $t('settings.search_pagination_limit') }}
|
||||||
</IntegerSetting>
|
</IntegerSetting>
|
||||||
</li>
|
</li>
|
||||||
|
<li
|
||||||
|
v-if="catOptsAvail"
|
||||||
|
>
|
||||||
|
<h3>{{ $t('settings.cat_settings') }}</h3>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting
|
||||||
|
path="showIsCatOnUserCard"
|
||||||
|
v-if="catOptsAvail"
|
||||||
|
>
|
||||||
|
{{ $t('settings.show_is_cat_on_user_card') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting
|
||||||
|
path="showCatEars"
|
||||||
|
v-if="catOptsAvail"
|
||||||
|
>
|
||||||
|
{{ $t('settings.show_cat_ears') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting
|
||||||
|
path="nyaizePosts"
|
||||||
|
v-if="catOptsAvail"
|
||||||
|
>
|
||||||
|
{{ $t('settings.nyaize_posts') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<h3>{{ $t('settings.columns') }}</h3>
|
<h3>{{ $t('settings.columns') }}</h3>
|
||||||
</li>
|
</li>
|
||||||
|
|
@ -495,6 +532,14 @@
|
||||||
{{ $t('settings.no_rich_text_description') }}
|
{{ $t('settings.no_rich_text_description') }}
|
||||||
</BooleanSetting>
|
</BooleanSetting>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<BooleanSetting
|
||||||
|
path="clickEmptyToOpenConversation"
|
||||||
|
expert="1"
|
||||||
|
>
|
||||||
|
{{ $t('settings.click_empty_to_open_conversation') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
<h3>{{ $t('settings.attachments') }}</h3>
|
<h3>{{ $t('settings.attachments') }}</h3>
|
||||||
<li>
|
<li>
|
||||||
<BooleanSetting
|
<BooleanSetting
|
||||||
|
|
|
||||||
|
|
@ -187,6 +187,8 @@ const Status = {
|
||||||
return highlightClass(user)
|
return highlightClass(user)
|
||||||
},
|
},
|
||||||
deleted () {
|
deleted () {
|
||||||
|
if (this.$store.getters.mergedConfig.autoCloseReplyUIWhenPostDeleted && this.statusoid.deleted && this.replying)
|
||||||
|
this.toggleReplying()
|
||||||
return this.statusoid.deleted
|
return this.statusoid.deleted
|
||||||
},
|
},
|
||||||
getDeletedWSSOption () {
|
getDeletedWSSOption () {
|
||||||
|
|
@ -531,6 +533,15 @@ const Status = {
|
||||||
window.scrollBy(0, rect.bottom - window.innerHeight + 50)
|
window.scrollBy(0, rect.bottom - window.innerHeight + 50)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
goToThread (id, e) {
|
||||||
|
if (this.$store.getters.mergedConfig.clickEmptyToOpenConversation) {
|
||||||
|
let targetType = e.target.tagName
|
||||||
|
let targetClasses = e.target.className
|
||||||
|
if ((targetType !== "DIV" && targetType !== "SPAN") || (targetType === "SPAN" && targetClasses.length === 0) || (targetClasses.includes("userName") || targetClasses.includes("form-bottom") || targetClasses.includes("visibility-tray") || targetClasses.includes("reply-form") || targetClasses.includes("post-status-form") || targetClasses.includes("form-group") || targetClasses.includes("preview-status")))
|
||||||
|
return
|
||||||
|
this.$router.push({ name: 'conversation', params: { id: id } })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
ref="root"
|
ref="root"
|
||||||
class="Status"
|
class="Status"
|
||||||
:class="[{ '-focused': isFocused }, { '-conversation': inlineExpanded }]"
|
:class="[{ '-focused': isFocused }, { '-conversation': inlineExpanded }]"
|
||||||
|
@click="(event) => { goToThread(status.id, event) }"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-if="error"
|
v-if="error"
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,9 @@ const StatusContent = {
|
||||||
translationLanguages () {
|
translationLanguages () {
|
||||||
return (this.$store.state.instance.supportedTranslationLanguages.source || []).map(lang => ({ key: lang.code, value: lang.code, label: lang.name }))
|
return (this.$store.state.instance.supportedTranslationLanguages.source || []).map(lang => ({ key: lang.code, value: lang.code, label: lang.name }))
|
||||||
},
|
},
|
||||||
|
canSpeakAsCat () {
|
||||||
|
return (this.$store.getters.mergedConfig.nyaizePosts && this.status.user.speak_as_cat)
|
||||||
|
},
|
||||||
...mapGetters(['mergedConfig'])
|
...mapGetters(['mergedConfig'])
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
|
@ -140,6 +143,16 @@ const StatusContent = {
|
||||||
this.$store.dispatch(
|
this.$store.dispatch(
|
||||||
'translateStatus', { id: this.status.id, language: translateTo, from: this.translateFrom }
|
'translateStatus', { id: this.status.id, language: translateTo, from: this.translateFrom }
|
||||||
).finally(() => { this.translating = false })
|
).finally(() => { this.translating = false })
|
||||||
|
},
|
||||||
|
speakAsCat () {
|
||||||
|
// taken from https://github.com/misskey-dev/misskey/blob/develop/packages/misskey-js/src/nyaize.ts
|
||||||
|
const enRegex1 = /(?<=n)a/gi
|
||||||
|
const enRegex2 = /(?<=morn)ing/gi
|
||||||
|
const enRegex3 = /(?<=every)one/gi
|
||||||
|
return this.status.text
|
||||||
|
.replace(enRegex1, x => x === 'A' ? 'YA' : 'ya')
|
||||||
|
.replace(enRegex2, x => x === 'ING' ? 'YAN' : 'yan')
|
||||||
|
.replace(enRegex3, x => x === 'ONE' ? 'NYAN' : 'nyan')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@
|
||||||
<RichContent
|
<RichContent
|
||||||
:class="{ '-single-line': singleLine }"
|
:class="{ '-single-line': singleLine }"
|
||||||
class="text media-body"
|
class="text media-body"
|
||||||
:html="status.raw_html"
|
:html="canSpeakAsCat ? speakAsCat() : status.raw_html"
|
||||||
:emoji="status.emojis"
|
:emoji="status.emojis"
|
||||||
:handle-links="true"
|
:handle-links="true"
|
||||||
:mfm="renderMisskeyMarkdown && (status.media_type === 'text/x.misskeymarkdown')"
|
:mfm="renderMisskeyMarkdown && (status.media_type === 'text/x.misskeymarkdown')"
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,13 @@ const StillImage = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
detectAnimationWithFetch (image) {
|
detectAnimationWithFetch (image) {
|
||||||
|
if (!this.$store.fetchedimgs)
|
||||||
|
this.$store.fetchedimgs = []
|
||||||
|
else
|
||||||
|
if (this.$store.fetchedimgs.indexOf(image.src) === -1)
|
||||||
|
this.$store.fetchedimgs.push(image.src)
|
||||||
|
else
|
||||||
|
return
|
||||||
// Browser Cache should ensure image doesn't get loaded twice if cache exists
|
// Browser Cache should ensure image doesn't get loaded twice if cache exists
|
||||||
fetch(image.src, {
|
fetch(image.src, {
|
||||||
referrerPolicy: 'same-origin'
|
referrerPolicy: 'same-origin'
|
||||||
|
|
@ -110,7 +117,7 @@ const StillImage = {
|
||||||
// this.setLabel('PNG')
|
// this.setLabel('PNG')
|
||||||
// return
|
// return
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// Hail mary for extensionless
|
// Hail mary for extensionless
|
||||||
if (extension.includes('/')) {
|
if (extension.includes('/')) {
|
||||||
// Don't mind the CORS error barrage
|
// Don't mind the CORS error barrage
|
||||||
|
|
@ -170,14 +177,14 @@ const StillImage = {
|
||||||
drawThumbnail() {
|
drawThumbnail() {
|
||||||
const canvas = this.$refs.canvas;
|
const canvas = this.$refs.canvas;
|
||||||
if (!canvas) return;
|
if (!canvas) return;
|
||||||
|
|
||||||
const context = canvas.getContext('2d');
|
const context = canvas.getContext('2d');
|
||||||
const image = this.$refs.src;
|
const image = this.$refs.src;
|
||||||
const parentElement = canvas.parentElement;
|
const parentElement = canvas.parentElement;
|
||||||
|
|
||||||
// Draw the quick, unscaled version first
|
// Draw the quick, unscaled version first
|
||||||
context.drawImage(image, 0, 0, parentElement.clientWidth, parentElement.clientHeight);
|
context.drawImage(image, 0, 0, parentElement.clientWidth, parentElement.clientHeight);
|
||||||
|
|
||||||
// Use requestAnimationFrame to schedule the scaling to the next frame
|
// Use requestAnimationFrame to schedule the scaling to the next frame
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
// Compute scaling ratio between the natural dimensions of the image and its display dimensions
|
// Compute scaling ratio between the natural dimensions of the image and its display dimensions
|
||||||
|
|
@ -191,13 +198,13 @@ const StillImage = {
|
||||||
canvas.style.width = `${parentElement.clientWidth}px`;
|
canvas.style.width = `${parentElement.clientWidth}px`;
|
||||||
canvas.style.height = `${parentElement.clientHeight}px`;
|
canvas.style.height = `${parentElement.clientHeight}px`;
|
||||||
context.scale(ratio, ratio);
|
context.scale(ratio, ratio);
|
||||||
|
|
||||||
// Maintain the aspect ratio of the image
|
// Maintain the aspect ratio of the image
|
||||||
const imgAspectRatio = image.naturalWidth / image.naturalHeight;
|
const imgAspectRatio = image.naturalWidth / image.naturalHeight;
|
||||||
const canvasAspectRatio = parentElement.clientWidth / parentElement.clientHeight;
|
const canvasAspectRatio = parentElement.clientWidth / parentElement.clientHeight;
|
||||||
|
|
||||||
let drawWidth, drawHeight;
|
let drawWidth, drawHeight;
|
||||||
|
|
||||||
if (imgAspectRatio > canvasAspectRatio) {
|
if (imgAspectRatio > canvasAspectRatio) {
|
||||||
drawWidth = parentElement.clientWidth;
|
drawWidth = parentElement.clientWidth;
|
||||||
drawHeight = parentElement.clientWidth / imgAspectRatio;
|
drawHeight = parentElement.clientWidth / imgAspectRatio;
|
||||||
|
|
@ -205,7 +212,7 @@ const StillImage = {
|
||||||
drawHeight = parentElement.clientHeight;
|
drawHeight = parentElement.clientHeight;
|
||||||
drawWidth = parentElement.clientHeight * imgAspectRatio;
|
drawWidth = parentElement.clientHeight * imgAspectRatio;
|
||||||
}
|
}
|
||||||
|
|
||||||
context.clearRect(0, 0, canvas.width, canvas.height); // Clear the previous unscaled image
|
context.clearRect(0, 0, canvas.width, canvas.height); // Clear the previous unscaled image
|
||||||
context.imageSmoothingEnabled = true;
|
context.imageSmoothingEnabled = true;
|
||||||
context.imageSmoothingQuality = 'high';
|
context.imageSmoothingQuality = 'high';
|
||||||
|
|
@ -215,7 +222,7 @@ const StillImage = {
|
||||||
const dy = (parentElement.clientHeight - drawHeight) / 2;
|
const dy = (parentElement.clientHeight - drawHeight) / 2;
|
||||||
context.drawImage(image, dx, dy, drawWidth, drawHeight);
|
context.drawImage(image, dx, dy, drawWidth, drawHeight);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
updated () {
|
updated () {
|
||||||
// On computed animated change
|
// On computed animated change
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import StillImage from '../still-image/still-image.vue'
|
import StillImage from '../still-image/still-image.vue'
|
||||||
|
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
|
import { FastAverageColor } from "fast-average-color";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
faRobot
|
faRobot
|
||||||
|
|
@ -20,7 +21,9 @@ const UserAvatar = {
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
showPlaceholder: false,
|
showPlaceholder: false,
|
||||||
defaultAvatar: `${this.$store.state.instance.server + this.$store.state.instance.defaultAvatar}`
|
defaultAvatar: `${this.$store.state.instance.server + this.$store.state.instance.defaultAvatar}`,
|
||||||
|
earsReady: false,
|
||||||
|
earsColor: "white"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
|
@ -33,6 +36,26 @@ const UserAvatar = {
|
||||||
imageLoadError () {
|
imageLoadError () {
|
||||||
this.showPlaceholder = true
|
this.showPlaceholder = true
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
canShowEars () {
|
||||||
|
return this.$store.getters.mergedConfig.showCatEars
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
if (this.canShowEars) {
|
||||||
|
const fac = new FastAverageColor()
|
||||||
|
for (let child of this.$el.children) {
|
||||||
|
let img = child.querySelector("img")
|
||||||
|
if (img) {
|
||||||
|
img.crossOrigin = "anonymous";
|
||||||
|
img.onload = () => {
|
||||||
|
this.earsColor = fac.getColor(img).hex;
|
||||||
|
this.earsReady = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,14 @@
|
||||||
class="Avatar"
|
class="Avatar"
|
||||||
:class="{ '-compact': compact }"
|
:class="{ '-compact': compact }"
|
||||||
>
|
>
|
||||||
|
<div
|
||||||
|
v-if="user && user.is_cat && canShowEars && !showPlaceholder && earsReady"
|
||||||
|
class="ears"
|
||||||
|
:style="{'color': earsColor}"
|
||||||
|
>
|
||||||
|
<div class="earLeft" />
|
||||||
|
<div class="earRight" />
|
||||||
|
</div>
|
||||||
<StillImage
|
<StillImage
|
||||||
v-if="user"
|
v-if="user"
|
||||||
class="avatar"
|
class="avatar"
|
||||||
|
|
@ -17,6 +25,7 @@
|
||||||
class="avatar -placeholder"
|
class="avatar -placeholder"
|
||||||
:class="{ '-compact': compact }"
|
:class="{ '-compact': compact }"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<FAIcon
|
<FAIcon
|
||||||
v-if="bot"
|
v-if="bot"
|
||||||
icon="robot"
|
icon="robot"
|
||||||
|
|
@ -29,6 +38,7 @@
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@import '../../_variables.scss';
|
@import '../../_variables.scss';
|
||||||
|
|
||||||
|
/* ears ripped from https://github.com/ihateblueb/aster/blob/main/packages/frontend/src/lib/components/Avatar.svelte */
|
||||||
.Avatar {
|
.Avatar {
|
||||||
--_avatarShadowBox: var(--avatarStatusShadow);
|
--_avatarShadowBox: var(--avatarStatusShadow);
|
||||||
--_avatarShadowFilter: var(--avatarStatusShadowFilter);
|
--_avatarShadowFilter: var(--avatarStatusShadowFilter);
|
||||||
|
|
@ -40,6 +50,17 @@
|
||||||
width: 48px;
|
width: 48px;
|
||||||
height: 48px;
|
height: 48px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
.ears {
|
||||||
|
.earLeft {
|
||||||
|
animation: earwiggleleft 1s infinite;
|
||||||
|
}
|
||||||
|
.earRight {
|
||||||
|
animation: earwiggleright 1s infinite;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&.-compact {
|
&.-compact {
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
|
|
@ -90,5 +111,116 @@
|
||||||
border-radius: var(--tooltipRadius);
|
border-radius: var(--tooltipRadius);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ears {
|
||||||
|
contain: strict;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 0;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
top: -50%;
|
||||||
|
left: -50%;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 50%;
|
||||||
|
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
|
.earLeft,
|
||||||
|
.earRight {
|
||||||
|
contain: strict;
|
||||||
|
display: inline-block;
|
||||||
|
height: 50%;
|
||||||
|
width: 50%;
|
||||||
|
background: currentColor;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
contain: strict;
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
width: 60%;
|
||||||
|
height: 60%;
|
||||||
|
margin: 20%;
|
||||||
|
background: #df548f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.earLeft {
|
||||||
|
transform: rotate(37.5deg) skew(30deg);
|
||||||
|
|
||||||
|
&,
|
||||||
|
&::after {
|
||||||
|
border-radius: 25% 75% 75%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.earRight {
|
||||||
|
transform: rotate(-37.5deg) skew(-30deg);
|
||||||
|
|
||||||
|
&,
|
||||||
|
&::after {
|
||||||
|
border-radius: 75% 25% 75% 75%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes earwiggleleft {
|
||||||
|
from {
|
||||||
|
transform: rotate(37.6deg) skew(30deg);
|
||||||
|
}
|
||||||
|
25% {
|
||||||
|
transform: rotate(10deg) skew(30deg);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: rotate(20deg) skew(30deg);
|
||||||
|
}
|
||||||
|
75% {
|
||||||
|
transform: rotate(0deg) skew(30deg);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: rotate(37.6deg) skew(30deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes earwiggleright {
|
||||||
|
from {
|
||||||
|
transform: rotate(-37.6deg) skew(-30deg);
|
||||||
|
}
|
||||||
|
30% {
|
||||||
|
transform: rotate(-10deg) skew(-30deg);
|
||||||
|
}
|
||||||
|
55% {
|
||||||
|
transform: rotate(-20deg) skew(-30deg);
|
||||||
|
}
|
||||||
|
75% {
|
||||||
|
transform: rotate(0deg) skew(-30deg);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: rotate(-37.6deg) skew(-30deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes eartightleft {
|
||||||
|
from {
|
||||||
|
transform: rotate(37.6deg) skew(30deg);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: rotate(37.4deg) skew(30deg);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: rotate(37.6deg) skew(30deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes eartightright {
|
||||||
|
from {
|
||||||
|
transform: rotate(-37.6deg) skew(-30deg);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: rotate(-37.4deg) skew(-30deg);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: rotate(-37.6deg) skew(-30deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@
|
||||||
>
|
>
|
||||||
@{{ user.screen_name_ui }}
|
@{{ user.screen_name_ui }}
|
||||||
</router-link>
|
</router-link>
|
||||||
<span class="user-roles" v-if="!hideBio && (user.deactivated || !!visibleRole || user.bot)">
|
<span class="user-roles" v-if="(!hideBio && (user.deactivated || !!visibleRole || user.bot)) || (user.is_cat)">
|
||||||
<span
|
<span
|
||||||
v-if="user.deactivated"
|
v-if="user.deactivated"
|
||||||
class="alert user-role"
|
class="alert user-role"
|
||||||
|
|
@ -73,6 +73,12 @@
|
||||||
>
|
>
|
||||||
{{ $t('user_card.bot') }}
|
{{ $t('user_card.bot') }}
|
||||||
</span>
|
</span>
|
||||||
|
<span
|
||||||
|
v-if="mergedConfig.showIsCatOnUserCard && user.is_cat"
|
||||||
|
class="alert user-role"
|
||||||
|
>
|
||||||
|
{{ $t('user_card.is_cat') }}
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<span class="user-locked" v-if="user.locked">
|
<span class="user-locked" v-if="user.locked">
|
||||||
<FAIcon
|
<FAIcon
|
||||||
|
|
|
||||||
|
|
@ -306,6 +306,7 @@
|
||||||
"bubble_timeline": "Bubble timeline",
|
"bubble_timeline": "Bubble timeline",
|
||||||
"bubble_timeline_description": "Posts from instances close to yours, as recommended by the admins",
|
"bubble_timeline_description": "Posts from instances close to yours, as recommended by the admins",
|
||||||
"chats": "Chats",
|
"chats": "Chats",
|
||||||
|
"close": "Close",
|
||||||
"dms": "Direct messages",
|
"dms": "Direct messages",
|
||||||
"friend_requests": "Follow requests",
|
"friend_requests": "Follow requests",
|
||||||
"home_timeline": "Home timeline",
|
"home_timeline": "Home timeline",
|
||||||
|
|
@ -482,6 +483,7 @@
|
||||||
"app_name": "App name",
|
"app_name": "App name",
|
||||||
"attachmentRadius": "Attachments",
|
"attachmentRadius": "Attachments",
|
||||||
"attachments": "Attachments",
|
"attachments": "Attachments",
|
||||||
|
"auto_close_reply_ui_when_post_deleted": "Automatically close the reply box when the post you're replying to is deleted",
|
||||||
"auto_refresh_on_required": "Automatically refresh when one of the below options are changed",
|
"auto_refresh_on_required": "Automatically refresh when one of the below options are changed",
|
||||||
"autohide_floating_post_button": "Automatically hide New Post button (mobile)",
|
"autohide_floating_post_button": "Automatically hide New Post button (mobile)",
|
||||||
"avatar": "Avatar",
|
"avatar": "Avatar",
|
||||||
|
|
@ -500,6 +502,7 @@
|
||||||
"boosts_follow_def_vis": "Make boosts follow default visibility",
|
"boosts_follow_def_vis": "Make boosts follow default visibility",
|
||||||
"bot": "This is a bot account",
|
"bot": "This is a bot account",
|
||||||
"btnRadius": "Buttons",
|
"btnRadius": "Buttons",
|
||||||
|
"cat_settings": "Cat settings",
|
||||||
"center_align_bio": "Center text in user bio",
|
"center_align_bio": "Center text in user bio",
|
||||||
"cBlue": "Blue (Reply, follow)",
|
"cBlue": "Blue (Reply, follow)",
|
||||||
"cGreen": "Green (Retweet)",
|
"cGreen": "Green (Retweet)",
|
||||||
|
|
@ -513,6 +516,7 @@
|
||||||
"changed_password": "Password changed successfully!",
|
"changed_password": "Password changed successfully!",
|
||||||
"chatMessageRadius": "Chat message",
|
"chatMessageRadius": "Chat message",
|
||||||
"checkboxRadius": "Checkboxes",
|
"checkboxRadius": "Checkboxes",
|
||||||
|
"click_empty_to_open_conversation": "Open conversation view by clicking empty parts of posts",
|
||||||
"collapse_subject": "Collapse posts with content warnings",
|
"collapse_subject": "Collapse posts with content warnings",
|
||||||
"columns": "Columns",
|
"columns": "Columns",
|
||||||
"compact_user_info": "Compact user info when enough space",
|
"compact_user_info": "Compact user info when enough space",
|
||||||
|
|
@ -705,6 +709,7 @@
|
||||||
"notification_visibility_repeats": "Boosts",
|
"notification_visibility_repeats": "Boosts",
|
||||||
"notifications": "Notifications",
|
"notifications": "Notifications",
|
||||||
"nsfw_clickthrough": "Hide sensitive/NSFW media",
|
"nsfw_clickthrough": "Hide sensitive/NSFW media",
|
||||||
|
"nyaize_posts": "\"nyaize\" posts from authors with \"Speak as Cat\" enabled",
|
||||||
"oauth_tokens": "OAuth tokens",
|
"oauth_tokens": "OAuth tokens",
|
||||||
"pad_emoji": "Pad emoji with spaces when adding from picker",
|
"pad_emoji": "Pad emoji with spaces when adding from picker",
|
||||||
"panelRadius": "Panels",
|
"panelRadius": "Panels",
|
||||||
|
|
@ -783,7 +788,9 @@
|
||||||
"settings_profiles_show": "Show all settings profiles",
|
"settings_profiles_show": "Show all settings profiles",
|
||||||
"settings_profiles_unshow": "Hide all settings profiles",
|
"settings_profiles_unshow": "Hide all settings profiles",
|
||||||
"show_admin_badge": "Show \"Admin\" badge in my profile",
|
"show_admin_badge": "Show \"Admin\" badge in my profile",
|
||||||
|
"show_cat_ears": "Show cat ears behind users' avatars",
|
||||||
"show_favicon_badge": "Show a badge on the page's favicon when there are unread notifications",
|
"show_favicon_badge": "Show a badge on the page's favicon when there are unread notifications",
|
||||||
|
"show_is_cat_on_user_card": "Show \"Cat\" badge on user profiles",
|
||||||
"show_moderator_badge": "Show \"Moderator\" badge in my profile",
|
"show_moderator_badge": "Show \"Moderator\" badge in my profile",
|
||||||
"show_nav_shortcuts": "Show extra navigation shortcuts in top panel",
|
"show_nav_shortcuts": "Show extra navigation shortcuts in top panel",
|
||||||
"show_panel_nav_shortcuts": "Show timeline navigation shortcuts at the top of the panel",
|
"show_panel_nav_shortcuts": "Show timeline navigation shortcuts at the top of the panel",
|
||||||
|
|
@ -1209,6 +1216,7 @@
|
||||||
"striped": "Striped bg"
|
"striped": "Striped bg"
|
||||||
},
|
},
|
||||||
"its_you": "It's you!",
|
"its_you": "It's you!",
|
||||||
|
"is_cat": "Cat",
|
||||||
"media": "Media",
|
"media": "Media",
|
||||||
"mention": "Mention",
|
"mention": "Mention",
|
||||||
"message": "Message",
|
"message": "Message",
|
||||||
|
|
|
||||||
|
|
@ -133,6 +133,11 @@ export const defaultState = {
|
||||||
showFaviconBadge: true,
|
showFaviconBadge: true,
|
||||||
autoRefreshOnRequired: true,
|
autoRefreshOnRequired: true,
|
||||||
showUnreadInTitle: true,
|
showUnreadInTitle: true,
|
||||||
|
clickEmptyToOpenConversation: false,
|
||||||
|
showCatFields: undefined,
|
||||||
|
showIsCatOnUserCard: false,
|
||||||
|
showCatEars: false,
|
||||||
|
nyaizePosts: false,
|
||||||
renderMisskeyMarkdown: undefined,
|
renderMisskeyMarkdown: undefined,
|
||||||
renderMfmOnHover: undefined, // instance default
|
renderMfmOnHover: undefined, // instance default
|
||||||
conversationDisplay: undefined, // instance default
|
conversationDisplay: undefined, // instance default
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,11 @@ const defaultState = {
|
||||||
showFaviconBadge: true,
|
showFaviconBadge: true,
|
||||||
autoRefreshOnRequired: true,
|
autoRefreshOnRequired: true,
|
||||||
showUnreadInTitle: true,
|
showUnreadInTitle: true,
|
||||||
|
clickEmptyToOpenConversation: false,
|
||||||
|
showCatFields: false,
|
||||||
|
showIsCatOnUserCard: false,
|
||||||
|
showCatEars: false,
|
||||||
|
nyaizePosts: false,
|
||||||
renderMisskeyMarkdown: true,
|
renderMisskeyMarkdown: true,
|
||||||
renderMfmOnHover: false,
|
renderMfmOnHover: false,
|
||||||
conversationDisplay: 'linear',
|
conversationDisplay: 'linear',
|
||||||
|
|
|
||||||
|
|
@ -467,8 +467,10 @@ export const mutations = {
|
||||||
newStatus.bookmarked = status.bookmarked
|
newStatus.bookmarked = status.bookmarked
|
||||||
},
|
},
|
||||||
setDeleted (state, { status }) {
|
setDeleted (state, { status }) {
|
||||||
const newStatus = state.allStatusesObject[status.id]
|
if (status) {
|
||||||
if (newStatus) newStatus.deleted = true
|
const newStatus = state.allStatusesObject[status.id]
|
||||||
|
if (newStatus) newStatus.deleted = true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
setManyDeleted (state, condition) {
|
setManyDeleted (state, condition) {
|
||||||
Object.values(state.allStatusesObject).forEach(status => {
|
Object.values(state.allStatusesObject).forEach(status => {
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,8 @@ export const parseUser = (data) => {
|
||||||
output.friends_count = data.following_count
|
output.friends_count = data.following_count
|
||||||
|
|
||||||
output.bot = data.bot
|
output.bot = data.bot
|
||||||
|
output.is_cat = typeof data.is_cat !== 'undefined' ? data.is_cat : false
|
||||||
|
output.speak_as_cat = typeof data.speak_as_cat !== 'undefined' ? data.speak_as_cat : false
|
||||||
output.accepts_direct_messages_from = data.accepts_direct_messages_from
|
output.accepts_direct_messages_from = data.accepts_direct_messages_from
|
||||||
output.follow_requests_count = data.follow_requests_count
|
output.follow_requests_count = data.follow_requests_count
|
||||||
if (data.akkoma) {
|
if (data.akkoma) {
|
||||||
|
|
|
||||||
|
|
@ -3998,6 +3998,11 @@ extract-zip@^2.0.1:
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
"@types/yauzl" "^2.9.1"
|
"@types/yauzl" "^2.9.1"
|
||||||
|
|
||||||
|
fast-average-color@^9.5.0:
|
||||||
|
version "9.5.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/fast-average-color/-/fast-average-color-9.5.0.tgz"
|
||||||
|
integrity sha512-nC6x2YIlJ9xxgkMFMd1BNoM1ctMjNoRKfRliPmiEWW3S6rLTHiQcy9g3pt/xiKv/D0NAAkhb9VyV+WJFvTqMGg==
|
||||||
|
|
||||||
fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
|
fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
|
||||||
version "3.1.3"
|
version "3.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
|
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue