Compare commits

..

47 commits

Author SHA1 Message Date
novenary
37b419a9f6 conversation: scrollIntoView when collapsed
This helps find the original context when collapsing a thread on the
timeline.
2024-10-08 14:58:47 +02:00
novenary
2fcaae4c05 post_status_form: inherit language from parent
If I'm replying to a post in Klingon, chances are I'm going to write in
Klingon. This reduces friction for properly marking post language in a
conversation.
2024-10-08 14:58:37 +02:00
novenary
6669fe0cfa post_status_form: reset all to defaults on clear 2024-10-08 14:58:17 +02:00
novenary
4bcc905731 emoji_input: implement fuzzy suggestions
This makes it a lot easier to find what you're looking for with fewer
keystrokes.
2024-10-08 14:52:24 +02:00
novenary
0a458d261c post_status_form: inherit language from parent
If I'm replying to a post in Klingon, chances are I'm going to write in
Klingon. This reduces friction for properly marking post language in a
conversation.
2024-10-08 14:50:52 +02:00
novenary
9c5c048763 post_status_form: inherit language from parent
If I'm replying to a post in Klingon, chances are I'm going to write in
Klingon. This reduces friction for properly marking post language in a
conversation.
2024-10-08 14:50:30 +02:00
novenary
a1017bc8a6 post_status_form: reset all to defaults on clear 2024-10-08 14:50:30 +02:00
novenary
cb80e39c00 emoji_input: show more suggestions
5 suggestions is really too little, so increase the limit and make the
list scrollable.
2024-10-08 14:50:30 +02:00
novenary
2799fe345f emoji_picker: select recents tab by default
This saves a click to get at your most commonly used emoji.
2024-10-08 14:50:30 +02:00
novenary
40e0b74a3d post_status_form: fix enter key in subject field
This fixes random actions being triggered by the enter key while the
subject field is focused.

When pressing enter, the browser simulates a click on the first "submit"
button it finds in the form.
A submit button is a button without `type="button"` set.
Remediate this by setting the type attribute on all but the "Post"
button.

Additionally, inhibit the enter key in the subject field (ctrl+enter
still works).
2024-10-08 14:50:30 +02:00
novenary
e20291bc92 post_status_form: enable sync flush for watcher
This fixes drafts not clearing after posting a reply.

Vue 3.3.11 changed watchers to stop firing after component unmount.
After posting a reply, the post form is removed, now causing the queued
event to be discarded.
Synchronous flush causes the handler to be called immediately when
changes happen, solving the problem.

See: https://github.com/vuejs/core/pull/7181
See: 80e2128d52
Fixes: a7dea2f70f
Fixes: #413
2024-10-08 14:50:28 +02:00
c601e6ce26 update repo url 2024-10-08 14:39:31 +02:00
f838e2be20 Revert "mod-loader"
This reverts commit 267dfa2cca.
2024-10-08 14:39:31 +02:00
18f9fab432 move quote button to a more appropriate place 2024-10-08 14:39:31 +02:00
b24d46d148 mod-loader 2024-10-08 14:39:31 +02:00
836b3eb7ee bruh 2024-10-08 14:39:31 +02:00
5ce6144759 why the fuck are these buttons so widely spaced who thought this is a good idea 2024-10-08 14:39:31 +02:00
a0ac45ba0a static changes 2024-10-08 14:39:31 +02:00
RiedleroD
87efc2f294 reverted 2e83ccefdc and clarified that compact user info is only used with enough room 2024-10-08 14:39:31 +02:00
RiedleroD
8e63c228be only flatten top of post body textarea if subject line is visible 2024-10-08 14:39:31 +02:00
RiedleroD
b3164766f0 smushed subject line and post body together, kinda 2024-10-08 14:39:31 +02:00
RiedleroD
83f093b9b9 expand underlay to screen edges when TL is widened 2024-10-08 14:39:31 +02:00
RiedleroD
a15e7ff003 reverted visual changes to underlay 2024-10-08 14:39:31 +02:00
RiedleroD
28c34c5790 oops, unfucked username placement 2024-10-08 14:39:31 +02:00
RiedleroD
c9ae0edbd0 fixed stuff overflowing in user popup e.g. in notifs 2024-10-08 14:39:31 +02:00
RiedleroD
e7e7285923 stopped user handle from overflowing from its boundaries in user card 2024-10-08 14:39:31 +02:00
RiedleroD
73abdbebeb disabled "compact user info" setting in mobile layout 2024-10-08 14:39:31 +02:00
RiedleroD
df48e9e7da disabled compact user card in mobile layout 2024-10-08 14:39:31 +02:00
RiedleroD
4e5b1ff8ce added setting for user info compactness 2024-10-08 14:39:31 +02:00
RiedleroD
83e86e9ad5 added setting to switch between center and left-aligned user bio 2024-10-08 14:39:31 +02:00
sdomi
8c4a1b26a3 more granular picker for the wide-timeline 2024-10-08 14:39:31 +02:00
RiedleroD
9c63e954f2 only flatten top of post body textarea if subject line is visible 2024-10-08 14:39:31 +02:00
RiedleroD
5dab10a117 made wide column layout optional 2024-10-08 14:39:31 +02:00
RiedleroD
77925728ec reverted audio attachments to 4:1 aspect ratio 2024-10-08 14:39:31 +02:00
RiedleroD
826c684fea fixed sizing issues with attachments in some non-status containers 2024-10-08 14:39:31 +02:00
RiedleroD
e340735136 fixed media attachment heights 2024-10-08 14:39:31 +02:00
RiedleroD
9cea046abd made attached images max size scale with font size
meta-comment: eliminated corner-case weirdness by replaced cursed CSS with slightly less cursed CSS
2024-10-08 14:39:31 +02:00
RiedleroD
ffd7411ca8 slightly adjusted edit button spacing 2024-10-08 14:39:31 +02:00
RiedleroD
cab1f7d79c removed min-width statements that were messing up my layouts 2024-10-08 14:39:31 +02:00
RiedleroD
84516cc1bd stopped username from wrapping… 2024-10-08 14:39:31 +02:00
RiedleroD
6c6b51d133 smushed subject line and post body together, kinda 2024-10-08 14:39:31 +02:00
RiedleroD
2c5973f24a oops, removed unneeded spacing 2024-10-08 14:39:31 +02:00
RiedleroD
5dabeb4e1b left-aligned bio text
why the fuck was it centered in the first place?!?
2024-10-08 14:39:31 +02:00
RiedleroD
50a3364897 moved user stats to between user info and user actions 2024-10-08 14:39:31 +02:00
RiedleroD
782bf543be made columns use more space, fixed minor bug 2024-10-08 14:39:31 +02:00
e6585644ad explainer 2024-10-08 14:39:31 +02:00
Laura Hausmann
0b53b63797
fix erroneous 'reply target is nonexistent' errors when using the user profile mention button 2024-09-30 23:57:07 +02:00
14 changed files with 113 additions and 20 deletions

View file

@ -32,6 +32,7 @@
"cropperjs": "^1.6.2",
"diff": "^5.2.0",
"escape-html": "^1.0.3",
"fzy.js": "^0.4.1",
"iso-639-1": "^2.1.15",
"js-cookie": "^3.0.1",
"localforage": "^1.10.0",

View file

@ -267,11 +267,11 @@ const conversation = {
},
replies () {
let i = 1
return reduce(this.conversation, (result, { id, in_reply_to_status_id }) => {
const irid = in_reply_to_status_id
if (irid) {
result[irid] = result[irid] || []
result[irid].push({
@ -414,6 +414,11 @@ const conversation = {
},
toggleExpanded () {
this.expanded = !this.expanded
this.$nextTick(() => {
if (!this.expanded) {
this.$el.scrollIntoView({ block: 'nearest' })
}
})
},
getConversationId (statusId) {
const status = this.$store.state.statuses.allStatusesObject[statusId]

View file

@ -278,5 +278,8 @@
&.-expanded.status-fadein {
margin: calc(var(--status-margin, $status-margin) / 2);
}
/* HACK: this value was picked arbitrarily and this is likely not even the right place */
scroll-margin-block-start: calc(var(--navbar-height) * 2);
}
</style>

View file

@ -183,7 +183,7 @@ const EmojiInput = {
// Async: cancel if textAtCaret has changed during wait
if (this.textAtCaret !== newWord) return
if (matchedSuggestions.length <= 0) return
this.suggestions = take(matchedSuggestions, 5)
this.suggestions = take(matchedSuggestions, 25)
.map(({ imageUrl, ...rest }) => ({
...rest,
img: imageUrl || ''
@ -300,6 +300,9 @@ const EmojiInput = {
if (this.highlighted < 0) {
this.highlighted = this.suggestions.length - 1
}
const panelBody = this.$refs['panel-body']
const highlighted = panelBody.children[this.highlighted]
highlighted.scrollIntoView({ block: 'nearest' })
e.preventDefault()
} else {
this.highlighted = 0
@ -312,6 +315,9 @@ const EmojiInput = {
if (this.highlighted >= len) {
this.highlighted = 0
}
const panelBody = this.$refs['panel-body']
const highlighted = panelBody.children[this.highlighted]
highlighted.scrollIntoView({ block: 'nearest' })
e.preventDefault()
} else {
this.highlighted = 0

View file

@ -128,6 +128,12 @@
--postLink: var(--popoverPostLink, $fallback--link);
--postFaintLink: var(--popoverPostFaintLink, $fallback--link);
--icon: var(--popoverIcon, $fallback--icon);
overflow-y: scroll;
scrollbar-gutter: stable;
scrollbar-width: thin;
max-height: calc((0.2em * 2 + 1px + 32px) * 5);
scroll-padding-block: calc((0.2em * 2 + 1px + 32px) * 2);
}
}

View file

@ -1,3 +1,6 @@
import * as fzy from 'fzy.js'
import { sortBy } from 'lodash'
const MFM_TAGS = ['blur', 'bounce', 'flip', 'font', 'jelly', 'jump', 'rainbow', 'rotate', 'shake', 'sparkle', 'spin', 'tada', 'twitch', 'x2', 'x3', 'x4']
.map(tag => ({ displayText: tag, detailText: '$[' + tag + ' ]', replacement: '$[' + tag + ' ]', mfm: true }))
@ -34,6 +37,20 @@ export default data => {
export const suggestEmoji = emojis => input => {
const noPrefix = input.toLowerCase().substr(1)
if (true) { // TODO check option setting
const matches = emojis.filter(({ displayText }) => fzy.hasMatch(noPrefix, displayText))
return sortBy(matches, m => {
let score = fzy.score(noPrefix, m.displayText)
// Prioritize custom emoji a lot
score += m.imageUrl ? 100 : 0
// Sort in descending order
return -score
})
}
return emojis
.filter(({ displayText }) => displayText.toLowerCase().match(noPrefix))
.sort((a, b) => {
@ -122,14 +139,14 @@ export const suggestUsers = ({ dispatch, state }) => {
const screenNameAlphabetically = a.screen_name > b.screen_name ? 1 : -1
return diff + nameAlphabetically + screenNameAlphabetically
}).map(({ screen_name, screen_name_ui, name, profile_image_url_original }) => ({
displayText: screen_name_ui,
detailText: name,
imageUrl: profile_image_url_original,
replacement: '@' + screen_name + ' '
}))
suggestions = newSuggestions || []
return suggestions

View file

@ -31,7 +31,7 @@ const EmojiPicker = {
data () {
return {
keyword: '',
activeGroup: 'standard',
activeGroup: 'recent',
showingStickers: false,
keepOpen: false
}

View file

@ -24,6 +24,7 @@
<button
v-if="options.length > 2"
class="delete-option button-unstyled -hover-highlight"
type="button"
@click="deleteOption(index)"
>
<FAIcon icon="times" />
@ -32,6 +33,7 @@
<button
v-if="options.length < maxOptions"
class="add-option faint button-unstyled -hover-highlight"
type="button"
@click="addOption"
>
<FAIcon

View file

@ -85,6 +85,7 @@ const PostStatusForm = {
'quoteId',
'repliedUser',
'attentions',
'copyMessageLanguage',
'copyMessageScope',
'subject',
'disableSubject',
@ -153,8 +154,7 @@ const PostStatusForm = {
statusText = buildMentionsString({ user: this.repliedUser, attentions: this.attentions }, currentUser)
}
const { postContentType: contentType, postLanguage: defaultPostLanguage, sensitiveByDefault, sensitiveIfSubject, interfaceLanguage, alwaysShowSubjectInput } = this.$store.getters.mergedConfig
const postLanguage = defaultPostLanguage || interfaceToISOLanguage(interfaceLanguage)
const { postContentType: contentType, sensitiveByDefault, sensitiveIfSubject, alwaysShowSubjectInput } = this.$store.getters.mergedConfig
let statusParams = {
spoilerText: this.subject || '',
@ -165,7 +165,7 @@ const PostStatusForm = {
poll: {},
mediaDescriptions: {},
visibility: this.suggestedVisibility(),
language: postLanguage,
language: this.suggestedLanguage(),
contentType
}
@ -180,7 +180,7 @@ const PostStatusForm = {
poll: this.statusPoll || {},
mediaDescriptions: this.statusMediaDescriptions || {},
visibility: this.statusScope || this.suggestedVisibility(),
language: this.statusLanguage || postLanguage,
language: this.statusLanguage || this.suggestedLanguage(),
contentType: statusContentType
}
}
@ -329,6 +329,7 @@ const PostStatusForm = {
watch: {
'newStatus': {
deep: true,
flush: 'sync',
handler () {
this.statusChanged()
}
@ -341,17 +342,22 @@ const PostStatusForm = {
this.saveDraft()
},
clearStatus () {
const newStatus = this.newStatus
const config = this.$store.getters.mergedConfig
this.newStatus = {
status: '',
spoilerText: '',
files: [],
visibility: newStatus.visibility,
contentType: newStatus.contentType,
language: newStatus.language,
nsfw: !!config.sensitiveByDefault,
visibility: this.suggestedVisibility(),
contentType: config.postContentType,
language: this.suggestedLanguage(),
poll: {},
mediaDescriptions: {}
}
const scopeselector = this.$refs.scopeselector
if (scopeselector) {
scopeselector.currentScope = this.newStatus.visibility
}
this.pollFormVisible = false
this.$refs.mediaUpload && this.$refs.mediaUpload.clearFile()
this.clearPollForm()
@ -760,6 +766,15 @@ const PostStatusForm = {
openProfileTab () {
this.$store.dispatch('openSettingsModalTab', 'profile')
},
suggestedLanguage () {
// Make sure the inherited language is actually valid
if (this.postLanguageOptions.find(o => o.value === this.copyMessageLanguage)) {
return this.copyMessageLanguage
}
const { postLanguage: defaultPostLanguage, interfaceLanguage } = this.$store.getters.mergedConfig
const postLanguage = defaultPostLanguage || interfaceToISOLanguage(interfaceLanguage)
return postLanguage
},
suggestedVisibility () {
if (this.copyMessageScope) {
if (this.copyMessageScope === 'direct') {

View file

@ -18,6 +18,7 @@
>
<button
class="button-unstyled -link"
type="button"
@click="openProfileTab"
>
{{ $t('post_status.account_not_locked_warning_link') }}
@ -136,6 +137,7 @@
class="form-post-subject"
@input="onSubjectInput"
@focus="focusSubjectInput()"
@keydown.exact.enter.prevent
>
</EmojiInput>
<i18n-t
@ -193,6 +195,7 @@
:class="{ 'visibility-tray-edit': isEdit }"
>
<scope-selector
ref="scopeselector"
v-if="!disableVisibilitySelector"
:user-default="userDefaultScope"
:original-scope="copyMessageScope"
@ -272,6 +275,7 @@
<button
class="emoji-icon button-unstyled"
:title="$t('emoji.add_emoji')"
type="button"
@click="showEmojiPicker"
>
<FAIcon icon="smile-beam" />
@ -281,6 +285,7 @@
class="poll-icon button-unstyled"
:class="{ selected: pollFormVisible }"
:title="$t('polls.add_poll')"
type="button"
@click="togglePollForm"
>
<FAIcon icon="poll-h" />
@ -290,6 +295,7 @@
class="spoiler-icon button-unstyled"
:class="{ selected: subjectVisible }"
:title="$t('post_status.toggle_content_warning')"
type="button"
@click="toggleSubjectVisible"
>
<FAIcon icon="eye-slash" />

View file

@ -519,6 +519,7 @@
:reply-to="status.id"
:attentions="status.attentions"
:replied-user="status.user"
:copy-message-language="status.language"
:copy-message-scope="status.visibility"
:subject="replySubject"
@posted="toggleReplying"
@ -533,6 +534,7 @@
:quote-id="status.id"
:attentions="[status.user]"
:replied-user="status.user"
:copy-message-language="status.language"
:copy-message-scope="status.visibility"
:subject="replySubject"
@posted="toggleQuoting"

View file

@ -901,7 +901,7 @@ const postStatus = ({
form.append('poll[options][]', option)
})
}
if (inReplyToStatusId) {
if (inReplyToStatusId && typeof inReplyToStatusId === 'string') {
form.append('in_reply_to_id', inReplyToStatusId)
}
if (quoteId) {

View file

@ -326,6 +326,7 @@ export const parseStatus = (data) => {
}
output.pinned = data.pinned
output.muted = data.muted
output.language = data.language
} else {
output.favorited = data.favorited
output.fave_num = data.fave_num

View file

@ -4283,6 +4283,11 @@ functions-have-names@^1.2.3:
resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834"
integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==
fzy.js@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/fzy.js/-/fzy.js-0.4.1.tgz#695bf87cc0bbdda9cbcf22bc318a74c4aca6b758"
integrity sha512-4sPVXf+9oGhzg2tYzgWe4hgAY0wEbkqeuKVEgdnqX8S8VcLosQsDjb0jV+f5uoQlf8INWId1w0IGoufAoik1TA==
gensync@^1.0.0-beta.2:
version "1.0.0-beta.2"
resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
@ -7390,7 +7395,16 @@ streamroller@^3.1.5:
debug "^4.3.4"
fs-extra "^8.1.0"
"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3:
"string-width-cjs@npm:string-width@^4.2.0":
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"
string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@ -7477,7 +7491,14 @@ stringify-object@^3.3.0:
is-obj "^1.0.1"
is-regexp "^1.0.0"
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1:
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"
strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@ -8577,8 +8598,7 @@ workerpool@6.2.1:
resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343"
integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
name wrap-ansi-cjs
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
@ -8596,6 +8616,15 @@ wrap-ansi@^6.2.0:
string-width "^4.1.0"
strip-ansi "^6.0.0"
wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"
wrap-ansi@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"