From c1bc5e14ebbecd8ffc6b4188fbf608e11f64422e Mon Sep 17 00:00:00 2001 From: Sorin Davidoi Date: Fri, 21 Jul 2017 01:38:24 +0200 Subject: feat(compose): More space on mobile devices (#4282) * feat(compose): More space on mobile devices * feat(compose): Hide navigation when typing on mobile devices * fix(compose): Make animation faster * fix(navigation_bar): Remove hardcoded title * fix(compose): Prevent accidental bluring * fix(compose): Increase max-height to 600px --- app/javascript/mastodon/actions/compose.js | 8 +++ .../features/compose/components/navigation_bar.js | 5 ++ app/javascript/mastodon/features/compose/index.js | 13 ++++- app/javascript/mastodon/features/ui/index.js | 15 +++++ app/javascript/mastodon/reducers/compose.js | 8 ++- app/javascript/styles/components.scss | 68 ++++++++++++++++++++++ 6 files changed, 114 insertions(+), 3 deletions(-) (limited to 'app/javascript') diff --git a/app/javascript/mastodon/actions/compose.js b/app/javascript/mastodon/actions/compose.js index 9f05a53e9..ebb75f36e 100644 --- a/app/javascript/mastodon/actions/compose.js +++ b/app/javascript/mastodon/actions/compose.js @@ -27,6 +27,7 @@ export const COMPOSE_SPOILERNESS_CHANGE = 'COMPOSE_SPOILERNESS_CHANGE'; export const COMPOSE_SPOILER_TEXT_CHANGE = 'COMPOSE_SPOILER_TEXT_CHANGE'; export const COMPOSE_VISIBILITY_CHANGE = 'COMPOSE_VISIBILITY_CHANGE'; export const COMPOSE_LISTABILITY_CHANGE = 'COMPOSE_LISTABILITY_CHANGE'; +export const COMPOSE_COMPOSING_CHANGE = 'COMPOSE_COMPOSING_CHANGE'; export const COMPOSE_EMOJI_INSERT = 'COMPOSE_EMOJI_INSERT'; @@ -278,3 +279,10 @@ export function insertEmojiCompose(position, emoji) { emoji, }; }; + +export function changeComposing(value) { + return { + type: COMPOSE_COMPOSING_CHANGE, + value, + }; +} diff --git a/app/javascript/mastodon/features/compose/components/navigation_bar.js b/app/javascript/mastodon/features/compose/components/navigation_bar.js index fa4f560f3..c76210c85 100644 --- a/app/javascript/mastodon/features/compose/components/navigation_bar.js +++ b/app/javascript/mastodon/features/compose/components/navigation_bar.js @@ -1,6 +1,8 @@ import React from 'react'; +import PropTypes from 'prop-types'; import ImmutablePropTypes from 'react-immutable-proptypes'; import Avatar from '../../../components/avatar'; +import IconButton from '../../../components/icon_button'; import Permalink from '../../../components/permalink'; import { FormattedMessage } from 'react-intl'; import ImmutablePureComponent from 'react-immutable-pure-component'; @@ -9,6 +11,7 @@ export default class NavigationBar extends ImmutablePureComponent { static propTypes = { account: ImmutablePropTypes.map.isRequired, + onClose: PropTypes.func.isRequired, }; render () { @@ -25,6 +28,8 @@ export default class NavigationBar extends ImmutablePureComponent { + + ); } diff --git a/app/javascript/mastodon/features/compose/index.js b/app/javascript/mastodon/features/compose/index.js index 6aa5de96c..e3cf2d33b 100644 --- a/app/javascript/mastodon/features/compose/index.js +++ b/app/javascript/mastodon/features/compose/index.js @@ -11,6 +11,7 @@ import SearchContainer from './containers/search_container'; import Motion from 'react-motion/lib/Motion'; import spring from 'react-motion/lib/spring'; import SearchResultsContainer from './containers/search_results_container'; +import { changeComposing } from '../../actions/compose'; const messages = defineMessages({ start: { id: 'getting_started.heading', defaultMessage: 'Getting started' }, @@ -47,6 +48,14 @@ export default class Compose extends React.PureComponent { this.props.dispatch(unmountCompose()); } + onFocus = () => { + this.props.dispatch(changeComposing(true)); + } + + onBlur = () => { + this.props.dispatch(changeComposing(false)); + } + render () { const { multiColumn, showSearch, intl } = this.props; @@ -82,8 +91,8 @@ export default class Compose extends React.PureComponent {
-
- +
+
diff --git a/app/javascript/mastodon/features/ui/index.js b/app/javascript/mastodon/features/ui/index.js index 3baf09b93..e667b390b 100644 --- a/app/javascript/mastodon/features/ui/index.js +++ b/app/javascript/mastodon/features/ui/index.js @@ -43,6 +43,7 @@ import '../../components/status'; const mapStateToProps = state => ({ systemFontUi: state.getIn(['meta', 'system_font_ui']), + isComposing: state.getIn(['compose', 'is_composing']), }); @connect(mapStateToProps) @@ -52,6 +53,7 @@ export default class UI extends React.PureComponent { dispatch: PropTypes.func.isRequired, children: PropTypes.node, systemFontUi: PropTypes.bool, + isComposing: PropTypes.bool, }; state = { @@ -133,6 +135,19 @@ export default class UI extends React.PureComponent { this.props.dispatch(refreshNotifications()); } + shouldComponentUpdate (nextProps) { + if (nextProps.isComposing !== this.props.isComposing) { + // Avoid expensive update just to toggle a class + this.node.classList.toggle('is-composing', nextProps.isComposing); + + return false; + } + + // Why isn't this working?!? + // return super.shouldComponentUpdate(nextProps, nextState); + return true; + } + componentWillUnmount () { window.removeEventListener('resize', this.handleResize); document.removeEventListener('dragenter', this.handleDragEnter); diff --git a/app/javascript/mastodon/reducers/compose.js b/app/javascript/mastodon/reducers/compose.js index 781e6e11b..534022000 100644 --- a/app/javascript/mastodon/reducers/compose.js +++ b/app/javascript/mastodon/reducers/compose.js @@ -20,6 +20,7 @@ import { COMPOSE_SPOILERNESS_CHANGE, COMPOSE_SPOILER_TEXT_CHANGE, COMPOSE_VISIBILITY_CHANGE, + COMPOSE_COMPOSING_CHANGE, COMPOSE_EMOJI_INSERT, } from '../actions/compose'; import { TIMELINE_DELETE } from '../actions/timelines'; @@ -37,6 +38,7 @@ const initialState = ImmutableMap({ focusDate: null, preselectDate: null, in_reply_to: null, + is_composing: false, is_submitting: false, is_uploading: false, progress: 0, @@ -146,7 +148,9 @@ export default function compose(state = initialState, action) { case COMPOSE_MOUNT: return state.set('mounted', true); case COMPOSE_UNMOUNT: - return state.set('mounted', false); + return state + .set('mounted', false) + .set('is_composing', false); case COMPOSE_SENSITIVITY_CHANGE: return state .set('sensitive', !state.get('sensitive')) @@ -169,6 +173,8 @@ export default function compose(state = initialState, action) { return state .set('text', action.text) .set('idempotencyKey', uuid()); + case COMPOSE_COMPOSING_CHANGE: + return state.set('is_composing', action.value); case COMPOSE_REPLY: return state.withMutations(map => { map.set('in_reply_to', action.status.get('id')); diff --git a/app/javascript/styles/components.scss b/app/javascript/styles/components.scss index 8c930ad11..b376f3a30 100644 --- a/app/javascript/styles/components.scss +++ b/app/javascript/styles/components.scss @@ -1177,6 +1177,11 @@ .permalink { text-decoration: none; } + + .icon-button { + pointer-events: none; + opacity: 0; + } } .navigation-bar__profile { @@ -3723,3 +3728,66 @@ noscript { margin: 20px 0; } } + +@media screen and (max-width: 1024px) and (max-height: 600px) { + $duration: 400ms; + $delay: 100ms; + + .tabs-bar, + .search { + will-change: margin-top; + transition: margin-top $duration $delay; + } + + .navigation-bar { + will-change: padding-bottom; + transition: padding-bottom $duration $delay; + } + + .navigation-bar { + & > a:first-child { + will-change: margin-top, margin-left, width; + transition: margin-top $duration $delay, margin-left $duration ($duration + $delay); + } + + & > .navigation-bar__profile-edit { + will-change: margin-top; + transition: margin-top $duration $delay; + } + + & > .icon-button { + will-change: opacity; + transition: opacity $duration $delay; + } + } + + .is-composing { + .tabs-bar, + .search { + margin-top: -50px; + } + + .navigation-bar { + padding-bottom: 0; + + & > a:first-child { + margin-top: -50px; + margin-left: -40px; + } + + .navigation-bar__profile { + padding-top: 2px; + } + + .navigation-bar__profile-edit { + position: absolute; + margin-top: -50px; + } + + .icon-button { + pointer-events: auto; + opacity: 1; + } + } + } +} -- cgit From 7bf7ed6123ad6e29f1356f58be0dbe89deed841b Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 21 Jul 2017 05:28:51 +0200 Subject: Fix #3220 - Show avatar/header on edit profile page (#4288) --- app/javascript/styles/accounts.scss | 9 +++++++++ app/javascript/styles/forms.scss | 4 ++++ app/views/settings/profiles/show.html.haml | 9 ++++++++- 3 files changed, 21 insertions(+), 1 deletion(-) (limited to 'app/javascript') diff --git a/app/javascript/styles/accounts.scss b/app/javascript/styles/accounts.scss index 801817d80..d5c18e1e3 100644 --- a/app/javascript/styles/accounts.scss +++ b/app/javascript/styles/accounts.scss @@ -26,6 +26,15 @@ z-index: 1; } + &.compact { + padding: 30px 0; + border-radius: 4px; + + .avatar { + margin-bottom: 0; + } + } + .name { display: block; font-size: 20px; diff --git a/app/javascript/styles/forms.scss b/app/javascript/styles/forms.scss index e1de36d55..c467aa7db 100644 --- a/app/javascript/styles/forms.scss +++ b/app/javascript/styles/forms.scss @@ -40,6 +40,10 @@ code { } } + .card { + margin-bottom: 15px; + } + strong { font-weight: 500; } diff --git a/app/views/settings/profiles/show.html.haml b/app/views/settings/profiles/show.html.haml index 2b846006f..e0fb613f8 100644 --- a/app/views/settings/profiles/show.html.haml +++ b/app/views/settings/profiles/show.html.haml @@ -7,10 +7,17 @@ .fields-group = f.input :display_name, placeholder: t('simple_form.labels.defaults.display_name'), hint: t('simple_form.hints.defaults.display_name', count: 30 - @account.display_name.size).html_safe = f.input :note, placeholder: t('simple_form.labels.defaults.note'), hint: t('simple_form.hints.defaults.note', count: 160 - @account.note.size).html_safe + + .card.compact{ style: "background-image: url(#{@account.header.url(:original)})" } + .avatar= image_tag @account.avatar.url(:original) + + .fields-group = f.input :avatar, wrapper: :with_label, input_html: { accept: AccountAvatar::IMAGE_MIME_TYPES.join(',') }, hint: t('simple_form.hints.defaults.avatar') + = f.input :header, wrapper: :with_label, input_html: { accept: AccountHeader::IMAGE_MIME_TYPES.join(',') }, hint: t('simple_form.hints.defaults.header') - = f.input :locked, as: :boolean, wrapper: :with_label, hint: t('simple_form.hints.defaults.locked') + .fields-group + = f.input :locked, as: :boolean, wrapper: :with_label, hint: t('simple_form.hints.defaults.locked') .actions = f.button :button, t('generic.save_changes'), type: :submit -- cgit From f2390e2803248ba8e37ee5bd50c36051552773e3 Mon Sep 17 00:00:00 2001 From: Yamagishi Kazutoshi Date: Fri, 21 Jul 2017 19:47:16 +0900 Subject: Dynamicaly change avatar and header bg from account setting (#4289) --- app/javascript/packs/public.js | 14 ++++++++++++++ app/javascript/styles/accounts.scss | 4 ++++ 2 files changed, 18 insertions(+) (limited to 'app/javascript') diff --git a/app/javascript/packs/public.js b/app/javascript/packs/public.js index a2ed086f1..da1f550fc 100644 --- a/app/javascript/packs/public.js +++ b/app/javascript/packs/public.js @@ -88,6 +88,20 @@ function main() { noteCounter.textContent = 160 - length(target.value); } }); + + delegate(document, '#account_avatar', 'change', ({ target }) => { + const avatar = document.querySelector('.card.compact .avatar img'); + const [file] = target.files || []; + const url = URL.createObjectURL(file); + avatar.src = url; + }); + + delegate(document, '#account_header', 'change', ({ target }) => { + const header = document.querySelector('.card.compact'); + const [file] = target.files || []; + const url = URL.createObjectURL(file); + header.style.backgroundImage = `url(${url})`; + }); } loadPolyfills().then(main).catch(error => { diff --git a/app/javascript/styles/accounts.scss b/app/javascript/styles/accounts.scss index d5c18e1e3..99eb5ebea 100644 --- a/app/javascript/styles/accounts.scss +++ b/app/javascript/styles/accounts.scss @@ -32,6 +32,10 @@ .avatar { margin-bottom: 0; + + img { + object-fit: cover; + } } } -- cgit From 38177048068ec9448f53cf9cc531637de2248bb1 Mon Sep 17 00:00:00 2001 From: Sorin Davidoi Date: Fri, 21 Jul 2017 14:22:29 +0200 Subject: feat(compose): Change media query for compact mode to max-height: 400px (#4291) --- app/javascript/styles/components.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/javascript') diff --git a/app/javascript/styles/components.scss b/app/javascript/styles/components.scss index b376f3a30..d9e5a9bad 100644 --- a/app/javascript/styles/components.scss +++ b/app/javascript/styles/components.scss @@ -3729,7 +3729,7 @@ noscript { } } -@media screen and (max-width: 1024px) and (max-height: 600px) { +@media screen and (max-width: 1024px) and (max-height: 400px) { $duration: 400ms; $delay: 100ms; -- cgit