import { default as computed, observes } from 'ember-addons/ember-computed-decorators'; import InputValidation from 'discourse/models/input-validation'; import { load, lookupCache } from 'pretty-text/oneboxer'; import { ajax } from 'discourse/lib/ajax'; import afterTransition from 'discourse/lib/after-transition'; export default Ember.Component.extend({ classNames: ['title-input'], watchForLink: Ember.computed.alias('composer.canEditTopicFeaturedLink'), didInsertElement() { this._super(); if (this.get('focusTarget') === 'title') { const $input = this.$("input"); afterTransition(this.$().closest("#reply-control"), () => { $input.putCursorAtEnd(); }); } if (this.get('composer.titleLength') > 0) { Ember.run.debounce(this, this._titleChanged, 10); } }, @computed('composer.titleLength', 'composer.missingTitleCharacters', 'composer.minimumTitleLength', 'lastValidatedAt') validation(titleLength, missingTitleChars, minimumTitleLength, lastValidatedAt) { let reason; if (titleLength < 1) { reason = I18n.t('composer.error.title_missing'); } else if (missingTitleChars > 0) { reason = I18n.t('composer.error.title_too_short', {min: minimumTitleLength}); } else if (titleLength > this.siteSettings.max_topic_title_length) { reason = I18n.t('composer.error.title_too_long', {max: this.siteSettings.max_topic_title_length}); } if (reason) { return InputValidation.create({ failed: true, reason, lastShownAt: lastValidatedAt }); } }, @computed('watchForLink') titleMaxLength() { // maxLength gets in the way of pasting long links, so don't use it if featured links are allowed. // Validation will display a message if titles are too long. return this.get('watchForLink') ? null : this.siteSettings.max_topic_title_length; }, @observes('composer.titleLength', 'watchForLink') _titleChanged() { if (this.get('composer.titleLength') === 0) { this.set('autoPosted', false); } if (this.get('autoPosted') || !this.get('watchForLink')) { return; } if (Ember.testing) { this._checkForUrl(); } else { Ember.run.debounce(this, this._checkForUrl, 500); } }, @observes('composer.replyLength') _clearFeaturedLink() { if (this.get('watchForLink') && this.bodyIsDefault()) { this.set('composer.featuredLink', null); } }, _checkForUrl() { if (!this.element || this.isDestroying || this.isDestroyed) { return; } if (this.get('isAbsoluteUrl') && this.bodyIsDefault()) { // only feature links to external sites if (this.get('composer.title').match(new RegExp("^https?:\\/\\/" + window.location.hostname, "i"))) { return; } // Try to onebox. If success, update post body and title. this.set('composer.loading', true); const link = document.createElement('a'); link.href = this.get('composer.title'); const loadOnebox = load({ elem: link, refresh: false, ajax, synchronous: true, categoryId: this.get('composer.category.id'), topicId: this.get('composer.topic.id') }); if (loadOnebox && loadOnebox.then) { loadOnebox.then( () => { const v = lookupCache(this.get('composer.title')); this._updatePost(v ? v : link); }).finally(() => { this.set('composer.loading', false); Ember.run.schedule('afterRender', () => { this.$('input').putCursorAtEnd(); }); }); } else { this._updatePost(loadOnebox); this.set('composer.loading', false); Ember.run.schedule('afterRender', () => { this.$('input').putCursorAtEnd(); }); } } }, _updatePost(html) { if (html) { this.set('autoPosted', true); this.set('composer.featuredLink', this.get('composer.title')); const $h = $(html), heading = $h.find('h3').length > 0 ? $h.find('h3') : $h.find('h4'), composer = this.get('composer'); composer.appendText(this.get('composer.title'), null, {block: true}); if (heading.length > 0 && heading.text().length > 0) { this.changeTitle(heading.text()); } else { const firstTitle = $h.attr('title') || $h.find("[title]").attr("title"); if (firstTitle && firstTitle.length > 0) { this.changeTitle(firstTitle); } } } }, changeTitle(val) { if (val && val.length > 0) { this.set('composer.title', val.trim()); } }, @computed('composer.title', 'composer.titleLength') isAbsoluteUrl(title, titleLength) { return titleLength > 0 && /^(https?:)?\/\/[\w\.\-]+/i.test(title) && !/\s/.test(title); }, bodyIsDefault() { const reply = this.get('composer.reply')||""; return (reply.length === 0 || (reply === (this.get("composer.category.topic_template")||""))); } });