diff --git a/README.md b/README.md index 0b02e0cb..bcac27c9 100644 --- a/README.md +++ b/README.md @@ -32,8 +32,15 @@ - emojis are sourced from discord's list of emojis - 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 +- 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 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 link on user card to open profiles in iceshrimp-fe - add option to open conversation view by clicking empty space in posts @@ -42,6 +49,11 @@ - add a script to download ruffle for flash support (requires python3 and requests library) - 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 diff --git a/package.json b/package.json index 5f8574dd..f087fb51 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "cropperjs": "^1.6.2", "diff": "^5.2.0", "escape-html": "^1.0.3", + "fast-average-color": "^9.5.0", "iso-639-1": "^2.1.15", "js-cookie": "^3.0.1", "localforage": "^1.10.0", diff --git a/src/boot/after_store.js b/src/boot/after_store.js index 90bcdab3..7af0458d 100644 --- a/src/boot/after_store.js +++ b/src/boot/after_store.js @@ -180,6 +180,7 @@ const setSettings = async ({ apiConfig, staticConfig, store }) => { copyInstanceOption('alwaysShowSubjectInput') copyInstanceOption('showFeaturesPanel') copyInstanceOption('hideSitename') + copyInstanceOption('showCatFields') copyInstanceOption('renderMisskeyMarkdown') copyInstanceOption('sidebarRight') diff --git a/src/components/settings_modal/tabs/general_tab.js b/src/components/settings_modal/tabs/general_tab.js index a829b0bf..3ce90bd1 100644 --- a/src/components/settings_modal/tabs/general_tab.js +++ b/src/components/settings_modal/tabs/general_tab.js @@ -135,6 +135,9 @@ const GeneralTab = { this.$store.dispatch('setOption', { name: 'postLanguage', value: val }) } }, + catOptsAvail: { + get: function () { return this.$store.getters.mergedConfig.showCatFields } + }, ...SharedComputedObject() }, methods: { diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue index dc64d348..b6c7e626 100644 --- a/src/components/settings_modal/tabs/general_tab.vue +++ b/src/components/settings_modal/tabs/general_tab.vue @@ -319,6 +319,35 @@ {{ $t('settings.search_pagination_limit') }} +
  • +

    {{ $t('settings.cat_settings') }}

    +
  • +
  • + + {{ $t('settings.show_is_cat_on_user_card') }} + +
  • +
  • + + {{ $t('settings.show_cat_ears') }} + +
  • +
  • + + {{ $t('settings.nyaize_posts') }} + +
  • {{ $t('settings.columns') }}

  • diff --git a/src/components/status_body/status_body.js b/src/components/status_body/status_body.js index 7ff6c3aa..2a1cbaed 100644 --- a/src/components/status_body/status_body.js +++ b/src/components/status_body/status_body.js @@ -86,6 +86,9 @@ const StatusContent = { translationLanguages () { 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']) }, components: { @@ -140,6 +143,16 @@ const StatusContent = { this.$store.dispatch( 'translateStatus', { id: this.status.id, language: translateTo, from: this.translateFrom } ).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') } } } diff --git a/src/components/status_body/status_body.vue b/src/components/status_body/status_body.vue index 068c6c1b..1bc48909 100644 --- a/src/components/status_body/status_body.vue +++ b/src/components/status_body/status_body.vue @@ -48,7 +48,7 @@ { + this.earsColor = fac.getColor(img).hex; + this.earsReady = true; + } + } + } + } } } diff --git a/src/components/user_avatar/user_avatar.vue b/src/components/user_avatar/user_avatar.vue index e64b54df..4bddd55b 100644 --- a/src/components/user_avatar/user_avatar.vue +++ b/src/components/user_avatar/user_avatar.vue @@ -3,6 +3,14 @@ class="Avatar" :class="{ '-compact': compact }" > +
    +
    +
    +
    + @import '../../_variables.scss'; +/* ears ripped from https://github.com/ihateblueb/aster/blob/main/packages/frontend/src/lib/components/Avatar.svelte */ .Avatar { --_avatarShadowBox: var(--avatarStatusShadow); --_avatarShadowFilter: var(--avatarStatusShadowFilter); @@ -40,6 +50,17 @@ width: 48px; height: 48px; + &:hover { + .ears { + .earLeft { + animation: earwiggleleft 1s infinite; + } + .earRight { + animation: earwiggleright 1s infinite; + } + } + } + &.-compact { width: 32px; height: 32px; @@ -90,5 +111,116 @@ 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); + } + } } diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue index dc876522..cfc9eac6 100644 --- a/src/components/user_card/user_card.vue +++ b/src/components/user_card/user_card.vue @@ -54,7 +54,7 @@ > @{{ user.screen_name_ui }} - + {{ $t('user_card.bot') }} + + {{ $t('user_card.is_cat') }} + { output.friends_count = data.following_count 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.follow_requests_count = data.follow_requests_count if (data.akkoma) { diff --git a/yarn.lock b/yarn.lock index 6abf579f..17ef3fbf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3998,6 +3998,11 @@ extract-zip@^2.0.1: optionalDependencies: "@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: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"