mirror of
https://github.com/mastodon/mastodon.git
synced 2025-07-14 08:18:15 +00:00
Compare commits
6 Commits
ec386eba6a
...
fabd675951
Author | SHA1 | Date | |
---|---|---|---|
![]() |
fabd675951 | ||
![]() |
3a232d9626 | ||
![]() |
3e1e6762aa | ||
![]() |
0733590c3b | ||
![]() |
c50cf3b544 | ||
![]() |
429ab8d210 |
|
@ -10,7 +10,10 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
|
|
||||||
import { length } from 'stringz';
|
import { length } from 'stringz';
|
||||||
|
|
||||||
|
import debounce from 'lodash.debounce';
|
||||||
|
|
||||||
import { missingAltTextModal } from 'mastodon/initial_state';
|
import { missingAltTextModal } from 'mastodon/initial_state';
|
||||||
|
import { changeComposeLanguage } from 'mastodon/actions/compose';
|
||||||
|
|
||||||
import AutosuggestInput from 'mastodon/components/autosuggest_input';
|
import AutosuggestInput from 'mastodon/components/autosuggest_input';
|
||||||
import AutosuggestTextarea from 'mastodon/components/autosuggest_textarea';
|
import AutosuggestTextarea from 'mastodon/components/autosuggest_textarea';
|
||||||
|
@ -32,6 +35,8 @@ import { ReplyIndicator } from './reply_indicator';
|
||||||
import { UploadForm } from './upload_form';
|
import { UploadForm } from './upload_form';
|
||||||
import { Warning } from './warning';
|
import { Warning } from './warning';
|
||||||
|
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
const allowedAroundShortCode = '><\u0085\u0020\u00a0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029\u0009\u000a\u000b\u000c\u000d';
|
const allowedAroundShortCode = '><\u0085\u0020\u00a0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029\u0009\u000a\u000b\u000c\u000d';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
|
@ -42,6 +47,28 @@ const messages = defineMessages({
|
||||||
reply: { id: 'compose_form.reply', defaultMessage: 'Reply' },
|
reply: { id: 'compose_form.reply', defaultMessage: 'Reply' },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const mapStateToProps = (state) => ({
|
||||||
|
currentLanguage: state.meta.get('locale'),
|
||||||
|
});
|
||||||
|
|
||||||
|
const languageDetectorInGlobalThis = 'LanguageDetector' in globalThis;
|
||||||
|
let supportsLanguageDetector = languageDetectorInGlobalThis && await globalThis.LanguageDetector.availability() === 'available';
|
||||||
|
let languageDetector;
|
||||||
|
// If the API is supported, but the model not loaded yet…
|
||||||
|
if (languageDetectorInGlobalThis && !supportsLanguageDetector) {
|
||||||
|
// …trigger the model download
|
||||||
|
LanguageDetector.create().then((_languageDetector) => {
|
||||||
|
supportsLanguageDetector = true
|
||||||
|
languageDetector = _languageDetector
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function countLetters(text) {
|
||||||
|
const segmenter = new Intl.Segmenter('und', { granularity: 'grapheme' })
|
||||||
|
const letters = [...segmenter.segment(text)]
|
||||||
|
return letters.length
|
||||||
|
}
|
||||||
|
|
||||||
class ComposeForm extends ImmutablePureComponent {
|
class ComposeForm extends ImmutablePureComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
|
@ -86,6 +113,7 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.textareaRef = createRef(null);
|
this.textareaRef = createRef(null);
|
||||||
|
this.debouncedHandleKeyUp = debounce(this._handleKeyUp.bind(this), 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleChange = (e) => {
|
handleChange = (e) => {
|
||||||
|
@ -98,6 +126,34 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
handleKeyUp = (e) => {
|
||||||
|
this.debouncedHandleKeyUp(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
_handleKeyUp = async (e) => {
|
||||||
|
if (!supportsLanguageDetector) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!languageDetector) {
|
||||||
|
languageDetector = await globalThis.LanguageDetector.create();
|
||||||
|
}
|
||||||
|
const text = this.getFulltextForCharacterCounting().trim();
|
||||||
|
const currentLanguage = this.props.currentLanguage;
|
||||||
|
if (!text || countLetters(text) <= 5) {
|
||||||
|
this.props.dispatch(changeComposeLanguage(currentLanguage));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
let detectedLanguage = (await languageDetector.detect(text))[0].detectedLanguage
|
||||||
|
detectedLanguage = detectedLanguage === 'und' ? currentLanguage : detectedLanguage.substring(0, 2);
|
||||||
|
this.props.dispatch(changeComposeLanguage(detectedLanguage));
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
this.props.dispatch(changeComposeLanguage(currentLanguage));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
getFulltextForCharacterCounting = () => {
|
getFulltextForCharacterCounting = () => {
|
||||||
return [this.props.spoiler? this.props.spoilerText: '', countableText(this.props.text)].join('');
|
return [this.props.spoiler? this.props.spoilerText: '', countableText(this.props.text)].join('');
|
||||||
};
|
};
|
||||||
|
@ -163,6 +219,7 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
|
|
||||||
componentWillUnmount () {
|
componentWillUnmount () {
|
||||||
if (this.timeout) clearTimeout(this.timeout);
|
if (this.timeout) clearTimeout(this.timeout);
|
||||||
|
this.debouncedHandleKeyUp.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate (prevProps) {
|
componentDidUpdate (prevProps) {
|
||||||
|
@ -274,6 +331,7 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
suggestions={this.props.suggestions}
|
suggestions={this.props.suggestions}
|
||||||
onFocus={this.handleFocus}
|
onFocus={this.handleFocus}
|
||||||
onKeyDown={this.handleKeyDown}
|
onKeyDown={this.handleKeyDown}
|
||||||
|
onKeyUp={this.handleKeyUp}
|
||||||
onSuggestionsFetchRequested={this.onSuggestionsFetchRequested}
|
onSuggestionsFetchRequested={this.onSuggestionsFetchRequested}
|
||||||
onSuggestionsClearRequested={this.onSuggestionsClearRequested}
|
onSuggestionsClearRequested={this.onSuggestionsClearRequested}
|
||||||
onSuggestionSelected={this.onSuggestionSelected}
|
onSuggestionSelected={this.onSuggestionSelected}
|
||||||
|
@ -324,4 +382,4 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default injectIntl(ComposeForm);
|
export default injectIntl(connect(mapStateToProps)(ComposeForm));
|
||||||
|
|
Loading…
Reference in New Issue
Block a user