Compare commits

...

10 commits

Author SHA1 Message Date
6f48569e59
Apply wordfilters to attachment alt-texts 2024-04-03 22:32:48 +02:00
ed0b403c33 Merge pull request 'Auto-approve followbacks (frontend part)' (#365) from Oneric/akkoma-fe:followbacks-fe into develop
Reviewed-on: AkkomaGang/akkoma-fe#365
2024-02-20 16:24:37 +00:00
0f842b300b Merge pull request 'Display profile background of other users' (#371) from Oneric/akkoma-fe:profile-backgrounds into develop
Reviewed-on: AkkomaGang/akkoma-fe#371
2024-02-20 16:20:14 +00:00
865cb6f96a Merge pull request 'Add Indonesian translation' (#366) from leap123/akkoma-fe:leap123-patch-1 into develop
Reviewed-on: AkkomaGang/akkoma-fe#366
2024-02-19 14:04:34 +00:00
050c7df2e6 Display profile background of other users
And add a new frontend setting to hide other people's background.
2024-02-14 18:44:57 +01:00
a77a9e04d9 Expose new server-side permit_followback setting
Added to backend in AkkomaGang/akkoma#674
2024-02-04 22:19:14 +01:00
a57334991e Add Indonesian translation
The Indonesian translation is technically almost complete, just not added to messages.js
2024-01-19 04:27:26 +00:00
8dce31d0ad Merge pull request 'Improve UX of subject / Content Warning field' (#362) from hazelnoot/akkoma-fe:develop into develop
Reviewed-on: AkkomaGang/akkoma-fe#362
2023-12-20 18:49:40 +00:00
ea9ad4d600 fix "always show content warning" setting 2023-12-20 12:39:31 -05:00
34e2800f59 add button to toggle the spoiler / CW field 2023-12-16 14:44:26 -05:00
14 changed files with 98 additions and 7 deletions

View file

@ -64,6 +64,11 @@ export default {
'-' + this.layoutType
]
},
pageBackground () {
return this.mergedConfig.displayPageBackgrounds
? this.$store.state.users.displayBackground
: null
},
currentUser () { return this.$store.state.users.currentUser },
userBackground () { return this.currentUser.background_image },
instanceBackground () {
@ -71,7 +76,7 @@ export default {
? null
: this.$store.state.instance.background
},
background () { return this.userBackground || this.instanceBackground },
background () { return this.pageBackground || this.userBackground || this.instanceBackground },
bgStyle () {
if (this.background) {
return {

View file

@ -138,7 +138,7 @@ const PostStatusForm = {
statusText = buildMentionsString({ user: this.repliedUser, attentions: this.attentions }, currentUser)
}
const { postContentType: contentType, sensitiveByDefault, sensitiveIfSubject, interfaceLanguage } = this.$store.getters.mergedConfig
const { postContentType: contentType, sensitiveByDefault, sensitiveIfSubject, interfaceLanguage, alwaysShowSubjectInput } = this.$store.getters.mergedConfig
let statusParams = {
spoilerText: this.subject || '',
@ -199,6 +199,10 @@ const PostStatusForm = {
}
}
// When first loading the form, hide the subject (CW) field if it's disabled or doesn't have a starting value.
// "disableSubject" seems to take priority over "alwaysShowSubjectInput".
const showSubject = !this.disableSubject && (statusParams.spoilerText || alwaysShowSubjectInput)
return {
dropFiles: [],
uploadingFiles: false,
@ -215,7 +219,8 @@ const PostStatusForm = {
emojiInputShown: false,
idempotencyKey: '',
activeEmojiInput: undefined,
activeTextInput: undefined
activeTextInput: undefined,
subjectVisible: showSubject
}
},
computed: {
@ -690,6 +695,20 @@ const PostStatusForm = {
this.activeEmojiInput = 'subject-emoji-input'
this.activeTextInput = 'subject-input'
},
toggleSubjectVisible() {
// If hiding CW, then we need to clear the subject and reset focus
if (this.subjectVisible)
{
this.focusStatusInput()
// "nsfw" property is normally set by the @change listener, but this bypasses it.
// We need to clear it manually instead.
this.newStatus.spoilerText = ''
this.newStatus.nsfw = false
}
this.subjectVisible = !this.subjectVisible
},
clearError () {
this.error = null
},

View file

@ -119,7 +119,7 @@
</div>
<EmojiInput
ref="subject-emoji-input"
v-if="!disableSubject && (newStatus.spoilerText || alwaysShowSubject)"
v-if="subjectVisible"
v-model="newStatus.spoilerText"
enable-emoji-picker
hide-emoji-button
@ -281,6 +281,15 @@
>
<FAIcon icon="poll-h" />
</button>
<button
v-if="!disableSubject"
class="spoiler-icon button-unstyled"
:class="{ selected: subjectVisible }"
:title="$t('post_status.toggle_content_warning')"
@click="toggleSubjectVisible"
>
<FAIcon icon="eye-slash" />
</button>
</div>
<button
v-if="posting"
@ -461,7 +470,7 @@
}
}
.media-upload-icon, .poll-icon, .emoji-icon {
.media-upload-icon, .poll-icon, .emoji-icon, .spoiler-icon {
font-size: 1.85em;
line-height: 1.1;
flex: 1;
@ -504,6 +513,11 @@
.poll-icon {
order: 3;
justify-content: center;
}
.spoiler-icon {
order: 4;
justify-content: right;
}

View file

@ -146,6 +146,11 @@
{{ $t('settings.show_wider_shortcuts') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting path="displayPageBackgrounds">
{{ $t('settings.show_page_backgrounds') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting path="stopGifs">
{{ $t('settings.stop_gifs') }}

View file

@ -33,6 +33,7 @@ const ProfileTab = {
newName: this.$store.state.users.currentUser.name_unescaped,
newBio: unescape(this.$store.state.users.currentUser.description),
newLocked: this.$store.state.users.currentUser.locked,
newPermitFollowback: this.$store.state.users.currentUser.permit_followback,
newFields: this.$store.state.users.currentUser.fields.map(field => ({ name: field.name, value: field.value })),
showRole: this.$store.state.users.currentUser.show_role,
role: this.$store.state.users.currentUser.role,
@ -135,6 +136,7 @@ const ProfileTab = {
bot: this.bot,
show_role: this.showRole,
status_ttl_days: this.expirePosts ? this.newPostTTLDays : -1,
permit_followback: this.permit_followback,
accepts_direct_messages_from: this.userAcceptsDirectMessagesFrom
/* eslint-enable camelcase */
}

View file

@ -259,6 +259,19 @@
<BooleanSetting path="serverSide_locked">
{{ $t('settings.lock_account_description') }}
</BooleanSetting>
<ul
class="setting-list suboptions"
:class="[{disabled: !serverSide_locked}]"
>
<li>
<BooleanSetting
path="serverSide_permitFollowback"
:disabled="!serverSide_locked"
>
{{ $t('settings.permit_followback_description') }}
</BooleanSetting>
</li>
</ul>
</li>
<li>
<BooleanSetting path="serverSide_discoverable">

View file

@ -145,10 +145,12 @@ const UserProfile = {
if (user) {
loadById(user.id)
this.note = user.relationship.note
this.$store.dispatch('setDisplayBackground', user.background_image)
} else {
this.$store.dispatch('fetchUser', userNameOrId)
.then(({ id, relationship }) => {
.then(({ id, relationship, background_image }) => {
this.note = relationship.note
this.$store.dispatch('setDisplayBackground', background_image)
return loadById(id)
})
.catch((reason) => {
@ -225,6 +227,9 @@ const UserProfile = {
Conversation,
RichContent,
FollowedTagList
},
beforeRouteLeave(to, from) {
this.$store.dispatch('setDisplayBackground', null)
}
}

View file

@ -380,6 +380,7 @@
"text/x.misskeymarkdown": "MFM"
},
"content_warning": "Content Warning (optional)",
"toggle_content_warning": "Toggle content warning",
"default": "Just arrived at Luna Nova Academy",
"direct_warning_to_all": "This post will be visible to all the mentioned users.",
"direct_warning_to_first_only": "This post will only be visible to the mentioned users at the beginning of the message.",
@ -600,6 +601,7 @@
"list_aliases_error": "Error fetching aliases: {error}",
"list_backups_error": "Error fetching backup list: {error}",
"lock_account_description": "Restrict your account to approved followers only",
"permit_followback_description": "Automatically approve requests from already followed users",
"loop_video": "Loop videos",
"loop_video_silent_only": "Loop only videos without sound (i.e. Mastodon's \"gifs\")",
"mascot": "Mastodon FE Mascot",
@ -749,6 +751,7 @@
"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_scrollbars": "Show side column's scrollbars",
"show_page_backgrounds": "Show page-specific backgrounds, e.g. for user profiles",
"show_wider_shortcuts": "Show wider gap between top panel shortcuts",
"show_yous": "Show (You)s",
"stop_gifs": "Pause animated images until you hover on them",

View file

@ -21,6 +21,7 @@ const loaders = {
ga: () => import('./ga.json'),
he: () => import('./he.json'),
hu: () => import('./hu.json'),
id: () => import('./id.json'),
it: () => import('./it.json'),
ja: () => import('./ja_pedantic.json'),
ja_easy: () => import('./ja_easy.json'),

View file

@ -55,6 +55,7 @@ export const defaultState = {
alwaysShowNewPostButton: false,
autohideFloatingPostButton: false,
pauseOnUnfocused: true,
displayPageBackgrounds: true,
stopGifs: undefined,
replyVisibility: 'all',
thirdColumnMode: 'notifications',

View file

@ -47,6 +47,10 @@ export const settingsMap = {
},
// Privacy
'locked': 'locked',
'permitFollowback': {
get: 'akkoma.permit_followback',
set: 'permit_followback'
},
'allowFollowingMove': {
get: 'pleroma.allow_following_move',
set: 'allow_following_move'

View file

@ -135,6 +135,10 @@ export const mutations = {
const user = state.usersObject[id]
user['deactivated'] = deactivated
},
setDisplayBackground(state, url) {
console.log("Commiting user profile bg mutation")
state.displayBackground = url
},
setCurrentUser (state, user) {
state.lastLoginName = user.screen_name
state.currentUser = mergeWith(state.currentUser || {}, user, mergeArrayLength)
@ -307,6 +311,7 @@ export const defaultState = {
currentUser: false,
users: [],
usersObject: {},
displayBackground: null,
signUpPending: false,
signUpErrors: [],
relationships: {},
@ -319,6 +324,10 @@ const users = {
mutations,
getters,
actions: {
setDisplayBackground (store, url) {
console.log("Performing user profile bg action...")
store.commit('setDisplayBackground', url)
},
fetchUserIfMissing (store, id) {
if (!store.getters.findUser(id)) {
store.dispatch('fetchUser', id)

View file

@ -95,6 +95,7 @@ export const parseUser = (data) => {
if (data.akkoma) {
output.instance = data.akkoma.instance
output.status_ttl_days = data.akkoma.status_ttl_days
output.permit_followback = data.akkoma.permit_followback
}
if (data.pleroma) {

View file

@ -3,8 +3,17 @@ import { filter } from 'lodash'
export const muteWordHits = (status, muteWords) => {
const statusText = status.text.toLowerCase()
const statusSummary = status.summary.toLowerCase()
const hits = filter(muteWords, (muteWord) => {
return statusText.includes(muteWord.toLowerCase()) || statusSummary.includes(muteWord.toLowerCase())
muteWord = muteWord.toLowerCase()
let res = statusText.includes(muteWord) || statusSummary.includes(muteWord)
for (let attachment of status.attachments) {
res |= attachment.description?.toLowerCase().includes(muteWord)
}
return res
})
return hits