forked from AkkomaGang/akkoma-fe
Compare commits
7 commits
b39143413c
...
bd4e8271df
Author | SHA1 | Date | |
---|---|---|---|
bd4e8271df | |||
08d4b3b885 | |||
e7c21ffbd7 | |||
9b4cddd2e9 | |||
cd20e45157 | |||
48a11cb9d1 | |||
e67d94f73d |
15 changed files with 106 additions and 6 deletions
|
@ -275,6 +275,7 @@ const getNodeInfo = async ({ store }) => {
|
||||||
store.dispatch('setInstanceOption', { name: 'pollsAvailable', value: features.includes('polls') })
|
store.dispatch('setInstanceOption', { name: 'pollsAvailable', value: features.includes('polls') })
|
||||||
store.dispatch('setInstanceOption', { name: 'pollLimits', value: metadata.pollLimits })
|
store.dispatch('setInstanceOption', { name: 'pollLimits', value: metadata.pollLimits })
|
||||||
store.dispatch('setInstanceOption', { name: 'mailerEnabled', value: metadata.mailerEnabled })
|
store.dispatch('setInstanceOption', { name: 'mailerEnabled', value: metadata.mailerEnabled })
|
||||||
|
store.dispatch('setInstanceOption', { name: 'translationEnabled', value: features.includes('akkoma:machine_translation') })
|
||||||
|
|
||||||
const uploadLimits = metadata.uploadLimits
|
const uploadLimits = metadata.uploadLimits
|
||||||
store.dispatch('setInstanceOption', { name: 'uploadlimit', value: parseInt(uploadLimits.general) })
|
store.dispatch('setInstanceOption', { name: 'uploadlimit', value: parseInt(uploadLimits.general) })
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
<button
|
<button
|
||||||
class="emoji-reaction btn button-default"
|
class="emoji-reaction btn button-default"
|
||||||
:class="{ 'picked-reaction': reactedWith(reaction.name), 'not-clickable': !loggedIn }"
|
:class="{ 'picked-reaction': reactedWith(reaction.name), 'not-clickable': !loggedIn }"
|
||||||
:disabled="!isLocalReaction(reaction.url)"
|
|
||||||
@click="emojiOnClick(reaction.name, $event)"
|
@click="emojiOnClick(reaction.name, $event)"
|
||||||
@mouseenter="fetchEmojiReactionsByIfMissing()"
|
@mouseenter="fetchEmojiReactionsByIfMissing()"
|
||||||
>
|
>
|
||||||
|
|
|
@ -55,6 +55,13 @@ const ExtraButtons = {
|
||||||
hideDeleteStatusConfirmDialog () {
|
hideDeleteStatusConfirmDialog () {
|
||||||
this.showingDeleteDialog = false
|
this.showingDeleteDialog = false
|
||||||
},
|
},
|
||||||
|
|
||||||
|
translateStatus () {
|
||||||
|
const translateTo = this.$store.getters.mergedConfig.translationLanguage || this.$store.state.instance.interfaceLanguage
|
||||||
|
this.$store.dispatch('translateStatus', { id: this.status.id, language: translateTo })
|
||||||
|
.then(() => this.$emit('onSuccess'))
|
||||||
|
.catch(err => this.$emit('onError', err.error.error))
|
||||||
|
},
|
||||||
pinStatus () {
|
pinStatus () {
|
||||||
this.$store.dispatch('pinStatus', this.status.id)
|
this.$store.dispatch('pinStatus', this.status.id)
|
||||||
.then(() => this.$emit('onSuccess'))
|
.then(() => this.$emit('onSuccess'))
|
||||||
|
@ -110,8 +117,15 @@ const ExtraButtons = {
|
||||||
canMute () {
|
canMute () {
|
||||||
return !!this.currentUser
|
return !!this.currentUser
|
||||||
},
|
},
|
||||||
|
canTranslate () {
|
||||||
|
return this.$store.state.instance.translationEnabled === true
|
||||||
|
},
|
||||||
statusLink () {
|
statusLink () {
|
||||||
return `${this.$store.state.instance.server}${this.$router.resolve({ name: 'conversation', params: { id: this.status.id } }).href}`
|
if (this.status.is_local) {
|
||||||
|
return `${this.$store.state.instance.server}${this.$router.resolve({ name: 'conversation', params: { id: this.status.id } }).href}`
|
||||||
|
} else {
|
||||||
|
return this.status.external_url
|
||||||
|
}
|
||||||
},
|
},
|
||||||
shouldConfirmDelete () {
|
shouldConfirmDelete () {
|
||||||
return this.$store.getters.mergedConfig.modalOnDelete
|
return this.$store.getters.mergedConfig.modalOnDelete
|
||||||
|
|
|
@ -116,6 +116,17 @@
|
||||||
:icon="['far', 'flag']"
|
:icon="['far', 'flag']"
|
||||||
/><span>{{ $t("user_card.report") }}</span>
|
/><span>{{ $t("user_card.report") }}</span>
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
v-if="canTranslate"
|
||||||
|
class="button-default dropdown-item dropdown-item-icon"
|
||||||
|
@click.prevent="translateStatus"
|
||||||
|
@click="close"
|
||||||
|
>
|
||||||
|
<FAIcon
|
||||||
|
fixed-width
|
||||||
|
icon="globe"
|
||||||
|
/><span>{{ $t("status.translate") }}</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:trigger>
|
<template v-slot:trigger>
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<FAIcon icon="globe" /> {{ ' ' }}
|
<FAIcon
|
||||||
|
v-if="globeIcon"
|
||||||
|
icon="globe"
|
||||||
|
/>
|
||||||
|
{{ ' ' }}
|
||||||
<label for="interface-language-switcher">
|
<label for="interface-language-switcher">
|
||||||
{{ promptText }}
|
{{ promptText }}
|
||||||
</label>
|
</label>
|
||||||
|
@ -40,6 +44,10 @@ export default {
|
||||||
setLanguage: {
|
setLanguage: {
|
||||||
type: Function,
|
type: Function,
|
||||||
required: true
|
required: true
|
||||||
|
},
|
||||||
|
globeIcon: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
v-if="federationPolicy"
|
v-if="hasInstanceSpecificPolicies"
|
||||||
class="mrf-transparency-panel"
|
class="mrf-transparency-panel"
|
||||||
>
|
>
|
||||||
<div class="panel panel-default base01-background">
|
<div class="panel panel-default base01-background">
|
||||||
|
|
|
@ -50,6 +50,7 @@ const GeneralTab = {
|
||||||
Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'webkitAudioDecodedByteCount') ||
|
Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'webkitAudioDecodedByteCount') ||
|
||||||
// Future spec, still not supported in Nightly 63 as of 08/2018
|
// Future spec, still not supported in Nightly 63 as of 08/2018
|
||||||
Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'audioTracks')
|
Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'audioTracks')
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
@ -82,11 +83,20 @@ const GeneralTab = {
|
||||||
this.$store.dispatch('setOption', { name: 'interfaceLanguage', value: val })
|
this.$store.dispatch('setOption', { name: 'interfaceLanguage', value: val })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
translationLanguage: {
|
||||||
|
get: function () { return this.$store.getters.mergedConfig.translationLanguage },
|
||||||
|
set: function (val) {
|
||||||
|
this.$store.dispatch('setOption', { name: 'translationLanguage', value: val })
|
||||||
|
}
|
||||||
|
},
|
||||||
...SharedComputedObject()
|
...SharedComputedObject()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
changeDefaultScope (value) {
|
changeDefaultScope (value) {
|
||||||
this.$store.dispatch('setServerSideOption', { name: 'defaultScope', value })
|
this.$store.dispatch('setServerSideOption', { name: 'defaultScope', value })
|
||||||
|
},
|
||||||
|
setTranslationLanguage (value) {
|
||||||
|
this.$store.dispatch('setOption', { name: 'translationLanguage', value })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -156,6 +156,16 @@
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>
|
||||||
|
<interface-language-switcher
|
||||||
|
:globe-icon="false"
|
||||||
|
:prompt-text="$t('settings.translation_language')"
|
||||||
|
:language="translationLanguage"
|
||||||
|
:set-language="setTranslationLanguage"
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<BooleanSetting
|
<BooleanSetting
|
||||||
path="alwaysShowNewPostButton"
|
path="alwaysShowNewPostButton"
|
||||||
|
|
|
@ -4,6 +4,12 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
|
.translation {
|
||||||
|
border: 1px solid var(--accent, $fallback--link);
|
||||||
|
border-radius: var(--panelRadius, $fallback--panelRadius);
|
||||||
|
margin-top: 1em;
|
||||||
|
padding: 0.5em;
|
||||||
|
}
|
||||||
.emoji {
|
.emoji {
|
||||||
--_still_image-label-scale: 0.5;
|
--_still_image-label-scale: 0.5;
|
||||||
--emoji-size: 38px;
|
--emoji-size: 38px;
|
||||||
|
|
|
@ -56,6 +56,23 @@
|
||||||
:attentions="status.attentions"
|
:attentions="status.attentions"
|
||||||
@parseReady="onParseReady"
|
@parseReady="onParseReady"
|
||||||
/>
|
/>
|
||||||
|
<div
|
||||||
|
v-if="status.translation"
|
||||||
|
class="translation"
|
||||||
|
>
|
||||||
|
<h4>{{ $t('status.translated_from', { language: status.translation.detected_language }) }}</h4>
|
||||||
|
<RichContent
|
||||||
|
:class="{ '-single-line': singleLine }"
|
||||||
|
class="text media-body"
|
||||||
|
:html="status.translation.text"
|
||||||
|
:emoji="status.emojis"
|
||||||
|
:handle-links="true"
|
||||||
|
:mfm="renderMisskeyMarkdown && (status.media_type === 'text/x.misskeymarkdown')"
|
||||||
|
:greentext="mergedConfig.greentext"
|
||||||
|
:attentions="status.attentions"
|
||||||
|
@parseReady="onParseReady"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
v-show="hideSubjectStatus"
|
v-show="hideSubjectStatus"
|
||||||
|
|
|
@ -794,6 +794,7 @@
|
||||||
"third_column_mode_postform": "Main post form and navigation",
|
"third_column_mode_postform": "Main post form and navigation",
|
||||||
"token": "Token",
|
"token": "Token",
|
||||||
"tooltipRadius": "Tooltips/alerts",
|
"tooltipRadius": "Tooltips/alerts",
|
||||||
|
"translation_language": "Automatic Translation Language",
|
||||||
"tree_advanced": "Allow more flexible navigation in tree view",
|
"tree_advanced": "Allow more flexible navigation in tree view",
|
||||||
"tree_fade_ancestors": "Display ancestors of the current post in faint text",
|
"tree_fade_ancestors": "Display ancestors of the current post in faint text",
|
||||||
"type_domains_to_mute": "Search domains to mute",
|
"type_domains_to_mute": "Search domains to mute",
|
||||||
|
@ -875,6 +876,8 @@
|
||||||
"thread_show": "Show this thread",
|
"thread_show": "Show this thread",
|
||||||
"thread_show_full": "Show everything under this thread ({numStatus} post in total, max depth {depth}) | Show everything under this thread ({numStatus} posts in total, max depth {depth})",
|
"thread_show_full": "Show everything under this thread ({numStatus} post in total, max depth {depth}) | Show everything under this thread ({numStatus} posts in total, max depth {depth})",
|
||||||
"thread_show_full_with_icon": "{icon} {text}",
|
"thread_show_full_with_icon": "{icon} {text}",
|
||||||
|
"translate": "Translate",
|
||||||
|
"translated_from": "Translated from {language}",
|
||||||
"unbookmark": "Unbookmark",
|
"unbookmark": "Unbookmark",
|
||||||
"unmute_conversation": "Unmute conversation",
|
"unmute_conversation": "Unmute conversation",
|
||||||
"unpin": "Unpin from profile",
|
"unpin": "Unpin from profile",
|
||||||
|
|
|
@ -791,6 +791,8 @@
|
||||||
"status_unavailable": "利用できません",
|
"status_unavailable": "利用できません",
|
||||||
"thread_muted": "ミュートされたスレッド",
|
"thread_muted": "ミュートされたスレッド",
|
||||||
"thread_muted_and_words": "以下の単語を含むため:",
|
"thread_muted_and_words": "以下の単語を含むため:",
|
||||||
|
"translate": "翻訳",
|
||||||
|
"translated_from": "{language}から翻訳されました",
|
||||||
"unbookmark": "ブックマーク解除",
|
"unbookmark": "ブックマーク解除",
|
||||||
"unmute_conversation": "スレッドのミュートを解除",
|
"unmute_conversation": "スレッドのミュートを解除",
|
||||||
"unpin": "プロフィールのピン留めを外す",
|
"unpin": "プロフィールのピン留めを外す",
|
||||||
|
|
|
@ -114,7 +114,8 @@ export const defaultState = {
|
||||||
conversationTreeAdvanced: undefined, // instance default
|
conversationTreeAdvanced: undefined, // instance default
|
||||||
conversationOtherRepliesButton: undefined, // instance default
|
conversationOtherRepliesButton: undefined, // instance default
|
||||||
conversationTreeFadeAncestors: undefined, // instance default
|
conversationTreeFadeAncestors: undefined, // instance default
|
||||||
maxDepthInThread: undefined // instance default
|
maxDepthInThread: undefined, // instance default
|
||||||
|
translationLanguage: undefined // instance default
|
||||||
}
|
}
|
||||||
|
|
||||||
// caching the instance default properties
|
// caching the instance default properties
|
||||||
|
@ -187,6 +188,7 @@ const config = {
|
||||||
case 'interfaceLanguage':
|
case 'interfaceLanguage':
|
||||||
messages.setLanguage(this.getters.i18n, value)
|
messages.setLanguage(this.getters.i18n, value)
|
||||||
Cookies.set(BACKEND_LANGUAGE_COOKIE_NAME, localeService.internalToBackendLocale(value))
|
Cookies.set(BACKEND_LANGUAGE_COOKIE_NAME, localeService.internalToBackendLocale(value))
|
||||||
|
dispatch('setInstanceOption', { name: 'interfaceLanguage', value })
|
||||||
break
|
break
|
||||||
case 'thirdColumnMode':
|
case 'thirdColumnMode':
|
||||||
dispatch('setLayoutWidth', undefined)
|
dispatch('setLayoutWidth', undefined)
|
||||||
|
|
|
@ -425,6 +425,10 @@ export const mutations = {
|
||||||
state.conversationsObject[newStatus.statusnet_conversation_id].forEach(status => { status.thread_muted = newStatus.thread_muted })
|
state.conversationsObject[newStatus.statusnet_conversation_id].forEach(status => { status.thread_muted = newStatus.thread_muted })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
setTranslatedStatus (state, { id, translation }) {
|
||||||
|
const newStatus = state.allStatusesObject[id]
|
||||||
|
newStatus.translation = translation
|
||||||
|
},
|
||||||
setRetweeted (state, { status, value }) {
|
setRetweeted (state, { status, value }) {
|
||||||
const newStatus = state.allStatusesObject[status.id]
|
const newStatus = state.allStatusesObject[status.id]
|
||||||
|
|
||||||
|
@ -637,6 +641,10 @@ const statuses = {
|
||||||
rootState.api.backendInteractor.unpinOwnStatus({ id: statusId })
|
rootState.api.backendInteractor.unpinOwnStatus({ id: statusId })
|
||||||
.then((status) => dispatch('addNewStatuses', { statuses: [status] }))
|
.then((status) => dispatch('addNewStatuses', { statuses: [status] }))
|
||||||
},
|
},
|
||||||
|
translateStatus ({ rootState, commit }, { id, translation, language }) {
|
||||||
|
return rootState.api.backendInteractor.translateStatus({ id: id, translation, language })
|
||||||
|
.then((translation) => commit('setTranslatedStatus', { id, translation }))
|
||||||
|
},
|
||||||
muteConversation ({ rootState, commit }, statusId) {
|
muteConversation ({ rootState, commit }, statusId) {
|
||||||
return rootState.api.backendInteractor.muteConversation({ id: statusId })
|
return rootState.api.backendInteractor.muteConversation({ id: statusId })
|
||||||
.then((status) => commit('setMutedStatus', status))
|
.then((status) => commit('setMutedStatus', status))
|
||||||
|
|
|
@ -31,6 +31,7 @@ const MASTODON_LOGIN_URL = '/api/v1/accounts/verify_credentials'
|
||||||
const MASTODON_REGISTRATION_URL = '/api/v1/accounts'
|
const MASTODON_REGISTRATION_URL = '/api/v1/accounts'
|
||||||
const MASTODON_USER_FAVORITES_TIMELINE_URL = '/api/v1/favourites'
|
const MASTODON_USER_FAVORITES_TIMELINE_URL = '/api/v1/favourites'
|
||||||
const MASTODON_USER_NOTIFICATIONS_URL = '/api/v1/notifications'
|
const MASTODON_USER_NOTIFICATIONS_URL = '/api/v1/notifications'
|
||||||
|
const AKKOMA_TRANSLATE_URL = (id, lang) => `/api/v1/statuses/${id}/translations/${lang}`
|
||||||
const MASTODON_DISMISS_NOTIFICATION_URL = id => `/api/v1/notifications/${id}/dismiss`
|
const MASTODON_DISMISS_NOTIFICATION_URL = id => `/api/v1/notifications/${id}/dismiss`
|
||||||
const MASTODON_FAVORITE_URL = id => `/api/v1/statuses/${id}/favourite`
|
const MASTODON_FAVORITE_URL = id => `/api/v1/statuses/${id}/favourite`
|
||||||
const MASTODON_UNFAVORITE_URL = id => `/api/v1/statuses/${id}/unfavourite`
|
const MASTODON_UNFAVORITE_URL = id => `/api/v1/statuses/${id}/unfavourite`
|
||||||
|
@ -738,6 +739,13 @@ const unretweet = ({ id, credentials }) => {
|
||||||
.then((data) => parseStatus(data))
|
.then((data) => parseStatus(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const translateStatus = ({ id, credentials, language }) => {
|
||||||
|
return promisedRequest({ url: AKKOMA_TRANSLATE_URL(id, language), method: 'GET', credentials })
|
||||||
|
.then((data) => {
|
||||||
|
return data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const bookmarkStatus = ({ id, credentials }) => {
|
const bookmarkStatus = ({ id, credentials }) => {
|
||||||
return promisedRequest({
|
return promisedRequest({
|
||||||
url: MASTODON_BOOKMARK_STATUS_URL(id),
|
url: MASTODON_BOOKMARK_STATUS_URL(id),
|
||||||
|
@ -1576,7 +1584,8 @@ const apiService = {
|
||||||
postAnnouncement,
|
postAnnouncement,
|
||||||
editAnnouncement,
|
editAnnouncement,
|
||||||
deleteAnnouncement,
|
deleteAnnouncement,
|
||||||
adminFetchAnnouncements
|
adminFetchAnnouncements,
|
||||||
|
translateStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
export default apiService
|
export default apiService
|
||||||
|
|
Loading…
Reference in a new issue