diff --git a/framework/core/js/forum/src/components/composer-body.js b/framework/core/js/forum/src/components/composer-body.js index e2fbd0ce4..bc46b0203 100644 --- a/framework/core/js/forum/src/components/composer-body.js +++ b/framework/core/js/forum/src/components/composer-body.js @@ -21,8 +21,8 @@ export default class ComposerBody extends Component { }); } - view() { - return m('div', {config: this.element}, [ + view(className) { + return m('div', {className, config: this.element}, [ avatar(this.props.user, {className: 'composer-avatar'}), m('div.composer-body', [ m('ul.composer-header', listItems(this.headerItems().toArray())), diff --git a/framework/core/js/forum/src/components/composer-discussion.js b/framework/core/js/forum/src/components/composer-discussion.js index e78b4c896..93d5ee8b6 100644 --- a/framework/core/js/forum/src/components/composer-discussion.js +++ b/framework/core/js/forum/src/components/composer-discussion.js @@ -10,6 +10,7 @@ import ActionButton from 'flarum/components/action-button'; */ export default class ComposerDiscussion extends ComposerBody { constructor(props) { + props.placeholder = props.placeholder || 'Write a post...'; props.submitLabel = props.submitLabel || 'Post Discussion'; props.confirmExit = props.confirmExit || 'You have not posted your discussion. Do you wish to discard it?'; props.titlePlaceholder = props.titlePlaceholder || 'Discussion Title'; @@ -26,7 +27,7 @@ export default class ComposerDiscussion extends ComposerBody { items.add('title', m('h3', m('input', { className: 'form-control', value: this.title(), - onchange: m.withAttr('value', this.title), + oninput: m.withAttr('value', this.title), placeholder: this.props.titlePlaceholder, disabled: !!this.props.disabled, config: function(element, isInitialized) { diff --git a/framework/core/js/forum/src/components/composer-edit.js b/framework/core/js/forum/src/components/composer-edit.js index ab06f128c..3f1695fba 100644 --- a/framework/core/js/forum/src/components/composer-edit.js +++ b/framework/core/js/forum/src/components/composer-edit.js @@ -22,7 +22,11 @@ export default class ComposerEdit extends ComposerBody { var items = new ItemList(); var post = this.props.post; - items.add('title', m('h3', ['Editing Post #'+post.number()+' in ', m('em', post.discussion().title())])); + items.add('title', m('h3', [ + 'Editing ', + m('a', {href: app.route.discussion(post.discussion(), post.number()), config: m.route}, 'Post #'+post.number()), + ' in ', post.discussion().title() + ])); return items; } diff --git a/framework/core/js/forum/src/components/composer-reply.js b/framework/core/js/forum/src/components/composer-reply.js index 6f33c7d68..632be4ce9 100644 --- a/framework/core/js/forum/src/components/composer-reply.js +++ b/framework/core/js/forum/src/components/composer-reply.js @@ -2,19 +2,33 @@ import ItemList from 'flarum/utils/item-list'; import ComposerBody from 'flarum/components/composer-body'; import Alert from 'flarum/components/alert'; import ActionButton from 'flarum/components/action-button'; +import Composer from 'flarum/components/composer'; export default class ComposerReply extends ComposerBody { constructor(props) { + props.placeholder = props.placeholder || 'Write your reply...'; props.submitLabel = props.submitLabel || 'Post Reply'; props.confirmExit = props.confirmExit || 'You have not posted your reply. Do you wish to discard it?'; super(props); } + view() { + return super.view('composer-reply'); + } + headerItems() { var items = new ItemList(); - items.add('title', m('h3', ['Replying to ', m('em', this.props.discussion.title())])); + if (app.composer.position() === Composer.PositionEnum.MINIMIZED || + // https://github.com/babel/babel/issues/1150 + !app.current.discussion || + app.current.discussion() !== this.props.discussion) { + items.add('title', m('h3', [ + 'Replying to ', + m('a', {href: app.route.discussion(this.props.discussion), config: m.route}, this.props.discussion.title()) + ])); + } return items; } diff --git a/framework/core/js/forum/src/components/composer.js b/framework/core/js/forum/src/components/composer.js index 4a6dc64ff..6f1cf8fe1 100644 --- a/framework/core/js/forum/src/components/composer.js +++ b/framework/core/js/forum/src/components/composer.js @@ -133,19 +133,16 @@ class Composer extends Component { } render(anchorToBottom) { - // @todo this function's logic could probably use some reworking. The - // following line is bad because it prevents focusing on the composer - // input when the composer is shown when it's already being shown if (this.position() === this.oldPosition) { return; } - var $composer = this.$(); + var $composer = this.$().stop(true); var oldHeight = $composer.is(':visible') ? $composer.outerHeight() : 0; if (this.position() !== Composer.PositionEnum.HIDDEN) { m.redraw(true); } - this.updateHeight(); + this.$().height(this.computedHeight()); var newHeight = $composer.outerHeight(); switch (this.position()) { @@ -178,7 +175,10 @@ class Composer extends Component { } $('body').toggleClass('composer-open', this.position() !== Composer.PositionEnum.HIDDEN); this.oldPosition = this.position(); - this.setContentHeight(this.computedHeight()); + + if (this.position() !== Composer.PositionEnum.HIDDEN) { + this.setContentHeight(this.computedHeight()); + } } // Update the amount of padding-bottom on the body so that the page's @@ -203,12 +203,12 @@ class Composer extends Component { // to fill up the height of the composer, minus the space taken up by the // composer's header/footer/etc. setContentHeight(height) { - var content = this.$('.composer-content'); - this.$('.flexible-height').height(height - - parseInt(content.css('padding-top')) - - parseInt(content.css('padding-bottom')) - - this.$('.composer-header').outerHeight(true) - - this.$('.text-editor-controls').outerHeight(true)); + var flexible = this.$('.flexible-height'); + if (flexible.length) { + flexible.height(height - + (flexible.offset().top - this.$().offset().top) - + this.$('.text-editor-controls').outerHeight(true)); + } } load(component) { @@ -225,8 +225,7 @@ class Composer extends Component { if ([Composer.PositionEnum.MINIMIZED, Composer.PositionEnum.HIDDEN].indexOf(this.position()) !== -1) { this.position(Composer.PositionEnum.NORMAL); } - // work around https://github.com/lhorie/mithril.js/issues/603 - setTimeout(() => this.render(anchorToBottom)); + this.render(anchorToBottom); } hide() { @@ -276,7 +275,7 @@ class Composer extends Component { items.add('minimize', this.control({ icon: 'minus minimize', title: 'Minimize', onclick: this.minimize.bind(this) })); items.add('fullScreen', this.control({ icon: 'expand', title: 'Full Screen', onclick: this.fullScreen.bind(this) })); } - items.add('close', this.control({ icon: 'times', title: 'Close', wrapperClass: 'back-control', onclick: this.close.bind(this) })); + items.add('close', this.control({ icon: 'times', title: 'Close', onclick: this.close.bind(this) })); } return items; diff --git a/framework/core/js/lib/components/text-editor.js b/framework/core/js/lib/components/text-editor.js index 56b806b93..b81cca45d 100644 --- a/framework/core/js/lib/components/text-editor.js +++ b/framework/core/js/lib/components/text-editor.js @@ -25,7 +25,7 @@ export default class TextEditor extends Component { disabled: !!this.props.disabled, value: this.value() }), - m('ul.text-editor-controls.fade', listItems(this.controlItems().toArray())) + m('ul.text-editor-controls', listItems(this.controlItems().toArray())) ]); } @@ -43,7 +43,6 @@ export default class TextEditor extends Component { label: this.props.submitLabel, icon: 'check', className: 'btn btn-primary', - wrapperClass: 'primary-control', onclick: this.onsubmit.bind(this) }) ); @@ -76,7 +75,6 @@ export default class TextEditor extends Component { oninput(value) { this.value(value); this.props.onchange(this.value()); - this.$('.text-editor-controls').toggleClass('in', !!value); m.redraw.strategy('none'); } diff --git a/framework/core/less/forum/composer.less b/framework/core/less/forum/composer.less index d12700529..7af2580a7 100644 --- a/framework/core/less/forum/composer.less +++ b/framework/core/less/forum/composer.less @@ -23,10 +23,15 @@ margin: 0 0 10px; line-height: 1.5em; - &, & input { + &, & input, & a { color: @fl-body-muted-color; - font-size: 16px; + font-size: 15px; font-weight: normal; + transition: color 0.2s; + + .active & { + color: @fl-body-primary-color; + } } & input, & input[disabled] { background: none; @@ -36,6 +41,19 @@ } } } +.composer-controls { + position: absolute; + right: 10px; + top: 10px; + z-index: 1; + + & li { + display: inline-block; + } + .minimized & { + top: 7px; + } +} .composer-loading { position: absolute; top: 0; @@ -58,35 +76,16 @@ // screen. The controls are hidden (except for the 'x', which is the back- // control), and the avatar hidden. @media @phone { - .composer-open { - overflow: hidden; - } .composer { - position: fixed; - top: 0; - bottom: 0; + position: absolute; left: 0; right: 0; - z-index: @zindex-composer; - background: @fl-body-bg; - height: 100vh !important; - padding-top: @mobile-header-height; - - &:before { - content: " "; - .toolbar(); - opacity: 0; - - .visible& { - opacity: 1; - } - } } .composer-content { - padding: 15px; + padding: 15px 15px 0; } .composer-controls { - & li:not(.back-control) { + & li:not(:last-child) { display: none; } } @@ -117,11 +116,14 @@ transform: translateZ(0); // Fix for Chrome bug where a transparent white background is actually gray position: relative; height: 300px; - .transition(~"background 0.2s"); + .transition(~"background 0.2s, box-shadow 0.2s"); &.active, &.full-screen { background: @fl-body-bg; } + &.active:not(.full-screen) { + box-shadow: 0 2px 6px @fl-shadow-color, 0 0 0 2px @fl-body-primary-color; + } &.minimized { height: 50px; cursor: pointer; @@ -142,10 +144,10 @@ } } .composer-content { - padding: 20px 20px 15px; + padding: 20px 20px 0; .minimized & { - padding: 10px 20px; + padding: 12px 20px; } .full-screen & { max-width: 900px; @@ -154,26 +156,14 @@ } } .composer-handle { - height: 20px; - margin-bottom: -20px; + height: 15px; + margin-bottom: -17px; position: relative; .minimized &, .full-screen & { display: none; } } - .composer-controls { - position: absolute; - right: 10px; - top: 10px; - - & li { - display: inline-block; - } - .minimized & { - top: 7px; - } - } .fa-minus.minimize { vertical-align: -5px; } @@ -204,14 +194,13 @@ margin-left: -20px; margin-right: 180px; - .index-page & { + .index-page &:not(.full-screen) { margin-left: 205px; margin-right: -20px; } } } - // ------------------------------------ // Text Editor @@ -223,7 +212,7 @@ resize: none; color: @fl-body-color; font-size: 14px; - line-height: 1.6; + line-height: 1.7; &, &:focus, &[disabled] { background: none; @@ -231,8 +220,8 @@ } } .text-editor-controls { - margin: 10px 0 0; - padding: 0; + margin: 0; + padding: 15px 0; list-style-type: none; & li { @@ -240,10 +229,15 @@ } } -// On phones, since one of the text editor controls will probably be the -// primary-control, we shouldn't hide it completely when it's "disabled". -@media @phone { +@media @tablet, @desktop, @desktop-hd { .text-editor-controls { - opacity: 0.5; + margin: 0 -20px 0 -110px; + padding: 15px 20px; + border-top: 1px solid @fl-body-secondary-color; + + & .btn-primary { + padding-left: 20px; + padding-right: 20px; + } } }