forked from AkkomaGang/akkoma-fe
Merge pull request 'Merge stable 2023.03' (#8) from AkkomaGang/akkoma-fe:stable into stable
Reviewed-on: fedward/pleroma-fe#8
This commit is contained in:
commit
b0c636d57c
12 changed files with 162 additions and 16 deletions
|
@ -51,6 +51,7 @@ const EmojiPicker = {
|
||||||
onEmoji (emoji) {
|
onEmoji (emoji) {
|
||||||
const value = emoji.imageUrl ? `:${emoji.displayText}:` : emoji.replacement
|
const value = emoji.imageUrl ? `:${emoji.displayText}:` : emoji.replacement
|
||||||
this.$emit('emoji', { insertion: value, keepOpen: this.keepOpen })
|
this.$emit('emoji', { insertion: value, keepOpen: this.keepOpen })
|
||||||
|
this.$store.commit('emojiUsed', emoji)
|
||||||
},
|
},
|
||||||
onWheel (e) {
|
onWheel (e) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
@ -96,6 +97,7 @@ const EmojiPicker = {
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
emojis () {
|
emojis () {
|
||||||
|
const recentEmojis = this.$store.getters.recentEmojis
|
||||||
const standardEmojis = this.$store.state.instance.emoji || []
|
const standardEmojis = this.$store.state.instance.emoji || []
|
||||||
const customEmojis = this.sortedEmoji
|
const customEmojis = this.sortedEmoji
|
||||||
const emojiPacks = []
|
const emojiPacks = []
|
||||||
|
@ -108,6 +110,15 @@ const EmojiPicker = {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
return [
|
return [
|
||||||
|
{
|
||||||
|
id: 'recent',
|
||||||
|
text: this.$t('emoji.recent'),
|
||||||
|
first: {
|
||||||
|
imageUrl: '',
|
||||||
|
replacement: '🕒',
|
||||||
|
},
|
||||||
|
emojis: this.filterByKeyword(recentEmojis)
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'standard',
|
id: 'standard',
|
||||||
text: this.$t('emoji.unicode'),
|
text: this.$t('emoji.unicode'),
|
||||||
|
|
|
@ -3,6 +3,11 @@ import UserListPopover from '../user_list_popover/user_list_popover.vue'
|
||||||
|
|
||||||
const EMOJI_REACTION_COUNT_CUTOFF = 12
|
const EMOJI_REACTION_COUNT_CUTOFF = 12
|
||||||
|
|
||||||
|
const findEmojiByReplacement = (state, replacement) => {
|
||||||
|
const allEmojis = state.instance.emoji.concat(state.instance.customEmoji)
|
||||||
|
return allEmojis.find(emoji => emoji.replacement === replacement)
|
||||||
|
}
|
||||||
|
|
||||||
const EmojiReactions = {
|
const EmojiReactions = {
|
||||||
name: 'EmojiReactions',
|
name: 'EmojiReactions',
|
||||||
components: {
|
components: {
|
||||||
|
@ -54,6 +59,8 @@ const EmojiReactions = {
|
||||||
},
|
},
|
||||||
reactWith (emoji) {
|
reactWith (emoji) {
|
||||||
this.$store.dispatch('reactWithEmoji', { id: this.status.id, emoji })
|
this.$store.dispatch('reactWithEmoji', { id: this.status.id, emoji })
|
||||||
|
const emojiObject = findEmojiByReplacement(this.$store.state, emoji)
|
||||||
|
this.$store.commit('emojiUsed', emojiObject)
|
||||||
},
|
},
|
||||||
unreact (emoji) {
|
unreact (emoji) {
|
||||||
this.$store.dispatch('unreactWithEmoji', { id: this.status.id, emoji })
|
this.$store.dispatch('unreactWithEmoji', { id: this.status.id, emoji })
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
:src="reaction.url"
|
:src="reaction.url"
|
||||||
:title="reaction.name"
|
:title="reaction.name"
|
||||||
class="reaction-emoji"
|
class="reaction-emoji"
|
||||||
width="2.55em"
|
|
||||||
height="2.55em"
|
height="2.55em"
|
||||||
>
|
>
|
||||||
{{ reaction.count }}
|
{{ reaction.count }}
|
||||||
|
@ -50,6 +49,7 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
margin-top: 0.25em;
|
margin-top: 0.25em;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
container-type: inline-size;
|
||||||
}
|
}
|
||||||
|
|
||||||
.unicode-emoji {
|
.unicode-emoji {
|
||||||
|
@ -65,7 +65,8 @@
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
.reaction-emoji {
|
.reaction-emoji {
|
||||||
width: 2.55em !important;
|
width: auto;
|
||||||
|
max-width: 96cqw;
|
||||||
height: 2.55em !important;
|
height: 2.55em !important;
|
||||||
margin-right: 0.25em;
|
margin-right: 0.25em;
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,14 @@ const pxStringToNumber = (str) => {
|
||||||
return Number(str.substring(0, str.length - 2))
|
return Number(str.substring(0, str.length - 2))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const deleteDraft = (draftKey) => {
|
||||||
|
const draftData = JSON.parse(localStorage.getItem('drafts') || '{}');
|
||||||
|
|
||||||
|
delete draftData[draftKey];
|
||||||
|
|
||||||
|
localStorage.setItem('drafts', JSON.stringify(draftData));
|
||||||
|
}
|
||||||
|
|
||||||
const PostStatusForm = {
|
const PostStatusForm = {
|
||||||
props: [
|
props: [
|
||||||
'statusId',
|
'statusId',
|
||||||
|
@ -161,6 +169,34 @@ const PostStatusForm = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let draftKey = 'status';
|
||||||
|
if (this.replyTo) {
|
||||||
|
draftKey = 'reply:' + this.replyTo;
|
||||||
|
} else if (this.quoteId) {
|
||||||
|
draftKey = 'quote:' + this.quoteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
const draft = JSON.parse(localStorage.getItem('drafts') || '{}')[draftKey];
|
||||||
|
|
||||||
|
if (draft) {
|
||||||
|
statusParams = {
|
||||||
|
spoilerText: draft.data.spoilerText,
|
||||||
|
status: draft.data.status,
|
||||||
|
sensitiveIfSubject,
|
||||||
|
nsfw: draft.data.nsfw,
|
||||||
|
files: draft.data.files,
|
||||||
|
poll: draft.data.poll,
|
||||||
|
mediaDescriptions: draft.data.mediaDescriptions,
|
||||||
|
visibility: draft.data.visibility,
|
||||||
|
language: draft.data.language,
|
||||||
|
contentType: draft.data.contentType
|
||||||
|
}
|
||||||
|
|
||||||
|
if (draft.data.poll) {
|
||||||
|
this.togglePollForm();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
dropFiles: [],
|
dropFiles: [],
|
||||||
uploadingFiles: false,
|
uploadingFiles: false,
|
||||||
|
@ -280,6 +316,7 @@ const PostStatusForm = {
|
||||||
statusChanged () {
|
statusChanged () {
|
||||||
this.autoPreview()
|
this.autoPreview()
|
||||||
this.updateIdempotencyKey()
|
this.updateIdempotencyKey()
|
||||||
|
this.saveDraft()
|
||||||
},
|
},
|
||||||
clearStatus () {
|
clearStatus () {
|
||||||
const newStatus = this.newStatus
|
const newStatus = this.newStatus
|
||||||
|
@ -401,8 +438,38 @@ const PostStatusForm = {
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
this.previewLoading = false
|
this.previewLoading = false
|
||||||
})
|
})
|
||||||
|
|
||||||
|
let draftKey = 'status';
|
||||||
|
if (this.replyTo) {
|
||||||
|
draftKey = 'reply:' + this.replyTo;
|
||||||
|
} else if (this.quoteId) {
|
||||||
|
draftKey = 'quote:' + this.quoteId;
|
||||||
|
}
|
||||||
|
deleteDraft(draftKey)
|
||||||
},
|
},
|
||||||
debouncePreviewStatus: debounce(function () { this.previewStatus() }, 500),
|
debouncePreviewStatus: debounce(function () { this.previewStatus() }, 500),
|
||||||
|
saveDraft() {
|
||||||
|
const draftData = JSON.parse(localStorage.getItem('drafts') || '{}');
|
||||||
|
|
||||||
|
let draftKey = 'status';
|
||||||
|
if (this.replyTo) {
|
||||||
|
draftKey = 'reply:' + this.replyTo;
|
||||||
|
} else if (this.quoteId) {
|
||||||
|
draftKey = 'quote:' + this.quoteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.newStatus.status || this.newStatus.spoilerText || this.newStatus.files.length > 0 || this.newStatus.poll.length > 0) {
|
||||||
|
draftData[draftKey] = {
|
||||||
|
updatedAt: new Date(),
|
||||||
|
data: this.newStatus,
|
||||||
|
};
|
||||||
|
|
||||||
|
localStorage.setItem('drafts', JSON.stringify(draftData));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
deleteDraft(draftKey);
|
||||||
|
}
|
||||||
|
},
|
||||||
autoPreview () {
|
autoPreview () {
|
||||||
if (!this.preview) return
|
if (!this.preview) return
|
||||||
this.previewLoading = true
|
this.previewLoading = true
|
||||||
|
|
|
@ -50,7 +50,6 @@
|
||||||
|
|
||||||
.emoji {
|
.emoji {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: var(--emoji-size, 32px);
|
|
||||||
height: var(--emoji-size, 32px);
|
height: var(--emoji-size, 32px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,21 +22,18 @@
|
||||||
|
|
||||||
._mfm_x2_ {
|
._mfm_x2_ {
|
||||||
.emoji {
|
.emoji {
|
||||||
width: 100px;
|
|
||||||
height: 100px;
|
height: 100px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
._mfm_x3_ {
|
._mfm_x3_ {
|
||||||
.emoji {
|
.emoji {
|
||||||
width: 150px;
|
|
||||||
height: 150px;
|
height: 150px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
._mfm_x4_ {
|
._mfm_x4_ {
|
||||||
.emoji {
|
.emoji {
|
||||||
width: 200px;
|
|
||||||
height: 200px;
|
height: 200px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,7 +71,7 @@
|
||||||
|
|
||||||
img, video {
|
img, video {
|
||||||
&.emoji {
|
&.emoji {
|
||||||
width: 50px;
|
max-width: 100%;
|
||||||
height: 50px;
|
height: 50px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,6 @@
|
||||||
animation: none !important;
|
animation: none !important;
|
||||||
}
|
}
|
||||||
.emoji {
|
.emoji {
|
||||||
width: 32px !important;
|
|
||||||
height: 32px !important;
|
height: 32px !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,7 +86,8 @@
|
||||||
"load_all_hint": "Loaded first {saneAmount} emoji, loading all emoji may cause performance issues.",
|
"load_all_hint": "Loaded first {saneAmount} emoji, loading all emoji may cause performance issues.",
|
||||||
"search_emoji": "Search for an emoji",
|
"search_emoji": "Search for an emoji",
|
||||||
"stickers": "Stickers",
|
"stickers": "Stickers",
|
||||||
"unicode": "Unicode emoji"
|
"unicode": "Unicode emoji",
|
||||||
|
"recent": "Recently used"
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"storage_unavailable": "Pleroma could not access browser storage. Your login or your local settings won't be saved and you might encounter unexpected issues. Try enabling cookies."
|
"storage_unavailable": "Pleroma could not access browser storage. Your login or your local settings won't be saved and you might encounter unexpected issues. Try enabling cookies."
|
||||||
|
|
|
@ -19,7 +19,8 @@ const saveImmedeatelyActions = [
|
||||||
'setOption',
|
'setOption',
|
||||||
'setClientData',
|
'setClientData',
|
||||||
'setToken',
|
'setToken',
|
||||||
'clearToken'
|
'clearToken',
|
||||||
|
'emojiUsed',
|
||||||
]
|
]
|
||||||
|
|
||||||
const defaultStorage = (() => {
|
const defaultStorage = (() => {
|
||||||
|
|
|
@ -22,6 +22,7 @@ import announcementsModule from './modules/announcements.js'
|
||||||
import editStatusModule from './modules/editStatus.js'
|
import editStatusModule from './modules/editStatus.js'
|
||||||
import statusHistoryModule from './modules/statusHistory.js'
|
import statusHistoryModule from './modules/statusHistory.js'
|
||||||
import tagModule from './modules/tags.js'
|
import tagModule from './modules/tags.js'
|
||||||
|
import recentEmojisModule from './modules/recentEmojis.js'
|
||||||
|
|
||||||
import { createI18n } from 'vue-i18n'
|
import { createI18n } from 'vue-i18n'
|
||||||
|
|
||||||
|
@ -47,7 +48,8 @@ const persistedStateOptions = {
|
||||||
paths: [
|
paths: [
|
||||||
'config',
|
'config',
|
||||||
'users.lastLoginName',
|
'users.lastLoginName',
|
||||||
'oauth'
|
'oauth',
|
||||||
|
'recentEmojis.emojis',
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -98,7 +100,8 @@ const persistedStateOptions = {
|
||||||
announcements: announcementsModule,
|
announcements: announcementsModule,
|
||||||
editStatus: editStatusModule,
|
editStatus: editStatusModule,
|
||||||
statusHistory: statusHistoryModule,
|
statusHistory: statusHistoryModule,
|
||||||
tags: tagModule
|
tags: tagModule,
|
||||||
|
recentEmojis: recentEmojisModule,
|
||||||
},
|
},
|
||||||
plugins,
|
plugins,
|
||||||
strict: false // Socket modifies itself, let's ignore this for now.
|
strict: false // Socket modifies itself, let's ignore this for now.
|
||||||
|
|
|
@ -5,15 +5,25 @@ import { map } from 'lodash'
|
||||||
const retryTimeout = (multiplier) => 1000 * multiplier
|
const retryTimeout = (multiplier) => 1000 * multiplier
|
||||||
|
|
||||||
const isVisible = (store, message, visibility) => {
|
const isVisible = (store, message, visibility) => {
|
||||||
if (visibility === 'all') {
|
if (visibility == 'all') {
|
||||||
return true
|
return true
|
||||||
} else if (visibility === 'following') {
|
}
|
||||||
return store.getters.relationship(message.in_reply_to_user_id).following
|
|
||||||
} else if (visibility === 'self') {
|
if (visibility == 'following') {
|
||||||
|
if (message.in_reply_to_user_id === null) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return store.getters.relationship(message.in_reply_to_user_id).following
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (visibility == 'self') {
|
||||||
return message.in_reply_to_user_id === store.rootState.users.currentUser.id
|
return message.in_reply_to_user_id === store.rootState.users.currentUser.id
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
const api = {
|
const api = {
|
||||||
state: {
|
state: {
|
||||||
retryMultiplier: 1,
|
retryMultiplier: 1,
|
||||||
|
|
50
src/modules/recentEmojis.js
Normal file
50
src/modules/recentEmojis.js
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
// each row is 7 emojis, 6 rows chosen arbitrarily. i don't think more than
|
||||||
|
// that are going to be useful.
|
||||||
|
const RECENT_MAX = 7 * 6
|
||||||
|
|
||||||
|
const defaultState = {
|
||||||
|
emojis: [],
|
||||||
|
}
|
||||||
|
|
||||||
|
const recentEmojis = {
|
||||||
|
state: defaultState,
|
||||||
|
|
||||||
|
mutations: {
|
||||||
|
emojiUsed ({ emojis }, emoji) {
|
||||||
|
if (emoji.displayText === undefined || emoji.displayText === null) {
|
||||||
|
console.error('emojiUsed was called with a bad emoji object: ', emoji)
|
||||||
|
return
|
||||||
|
} else if (emoji.displayText.includes('@')) {
|
||||||
|
console.error('emojiUsed was called with a remote emoji: ', emoji)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const i = emojis.indexOf(emoji.displayText)
|
||||||
|
|
||||||
|
if (i === -1) {
|
||||||
|
// not in `emojis` yet, insert and truncate if necessary
|
||||||
|
const newLength = emojis.unshift(emoji.displayText)
|
||||||
|
if (newLength > RECENT_MAX) {
|
||||||
|
emojis.pop()
|
||||||
|
}
|
||||||
|
} else if (i !== 0) {
|
||||||
|
// emoji is already in `emojis` but needs to be bumped to the top
|
||||||
|
emojis.splice(i, 1)
|
||||||
|
emojis.unshift(emoji.displayText)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
getters: {
|
||||||
|
recentEmojis: (state, getters, rootState) => state.emojis.reduce((objects, displayText) => {
|
||||||
|
const allEmojis = rootState.instance.emoji.concat(rootState.instance.customEmoji)
|
||||||
|
let emojiObject = allEmojis.find(emoji => emoji.displayText === displayText)
|
||||||
|
if (emojiObject !== undefined) {
|
||||||
|
objects.push(emojiObject)
|
||||||
|
}
|
||||||
|
return objects
|
||||||
|
}, []),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export default recentEmojis
|
Loading…
Reference in a new issue