@@ -74,22 +60,17 @@ const PageTwo = ({ myAccount }) => (
);
PageTwo.propTypes = {
+ intl: PropTypes.object.isRequired,
myAccount: ImmutablePropTypes.map.isRequired,
};
-const PageThree = ({ myAccount }) => (
+const PageThree = ({ intl, myAccount }) => (
@@ -99,6 +80,7 @@ const PageThree = ({ myAccount }) => (
);
PageThree.propTypes = {
+ intl: PropTypes.object.isRequired,
myAccount: ImmutablePropTypes.map.isRequired,
};
@@ -192,8 +174,8 @@ export default class OnboardingModal extends React.PureComponent {
const { myAccount, admin, domain, intl } = this.props;
this.pages = [
,
-
,
-
,
+
,
+
,
,
,
];
diff --git a/app/javascript/flavours/glitch/features/ui/index.js b/app/javascript/flavours/glitch/features/ui/index.js
index 5c80ea07bb..fae705deb7 100644
--- a/app/javascript/flavours/glitch/features/ui/index.js
+++ b/app/javascript/flavours/glitch/features/ui/index.js
@@ -17,7 +17,7 @@ import UploadArea from './components/upload_area';
import ColumnsAreaContainer from './containers/columns_area_container';
import classNames from 'classnames';
import {
- Compose,
+ Drawer,
Status,
GettingStarted,
KeyboardShortcuts,
@@ -56,7 +56,6 @@ const messages = defineMessages({
});
const mapStateToProps = state => ({
- isComposing: state.getIn(['compose', 'is_composing']),
hasComposingText: state.getIn(['compose', 'text']) !== '',
layout: state.getIn(['local_settings', 'layout']),
isWide: state.getIn(['local_settings', 'stretch']),
@@ -120,9 +119,9 @@ export default class UI extends React.Component {
};
handleBeforeUnload = (e) => {
- const { intl, isComposing, hasComposingText } = this.props;
+ const { intl, hasComposingText } = this.props;
- if (isComposing && hasComposingText) {
+ if (hasComposingText) {
// Setting returnValue to any string causes confirmation dialog.
// Many browsers no longer display this text to users,
// but we set user-friendly message for other browsers, e.g. Edge.
@@ -227,9 +226,8 @@ export default class UI extends React.Component {
}
shouldComponentUpdate (nextProps) {
- if (nextProps.isComposing !== this.props.isComposing) {
+ if (nextProps.navbarUnder !== this.props.navbarUnder) {
// Avoid expensive update just to toggle a class
- this.node.classList.toggle('is-composing', nextProps.isComposing);
this.node.classList.toggle('navbar-under', nextProps.navbarUnder);
return false;
@@ -427,7 +425,7 @@ export default class UI extends React.Component {
-
+
diff --git a/app/javascript/flavours/glitch/reducers/compose.js b/app/javascript/flavours/glitch/reducers/compose.js
index aaa36b6961..e1f811f6f2 100644
--- a/app/javascript/flavours/glitch/reducers/compose.js
+++ b/app/javascript/flavours/glitch/reducers/compose.js
@@ -21,7 +21,6 @@ import {
COMPOSE_SPOILERNESS_CHANGE,
COMPOSE_SPOILER_TEXT_CHANGE,
COMPOSE_VISIBILITY_CHANGE,
- COMPOSE_COMPOSING_CHANGE,
COMPOSE_EMOJI_INSERT,
COMPOSE_UPLOAD_CHANGE_REQUEST,
COMPOSE_UPLOAD_CHANGE_SUCCESS,
@@ -48,7 +47,6 @@ const initialState = ImmutableMap({
focusDate: null,
preselectDate: null,
in_reply_to: null,
- is_composing: false,
is_submitting: false,
is_uploading: false,
progress: 0,
@@ -134,7 +132,7 @@ function removeMedia(state, mediaId) {
const insertSuggestion = (state, position, token, completion) => {
return state.withMutations(map => {
- map.update('text', oldText => `${oldText.slice(0, position)}${completion}\u200B${oldText.slice(position + token.length)}`);
+ map.update('text', oldText => `${oldText.slice(0, position)}${completion}${completion[0] === ':' ? '\u200B' : ' '}${oldText.slice(position + token.length)}`);
map.set('suggestion_token', null);
map.update('suggestions', ImmutableList(), list => list.clear());
map.set('focusDate', new Date());
@@ -181,9 +179,7 @@ export default function compose(state = initialState, action) {
case COMPOSE_MOUNT:
return state.set('mounted', true);
case COMPOSE_UNMOUNT:
- return state
- .set('mounted', false)
- .set('is_composing', false);
+ return state.set('mounted', false);
case COMPOSE_ADVANCED_OPTIONS_CHANGE:
return state
.set('advanced_options',
@@ -219,8 +215,6 @@ 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/flavours/glitch/styles/components/composer.scss b/app/javascript/flavours/glitch/styles/components/composer.scss
new file mode 100644
index 0000000000..46df79906f
--- /dev/null
+++ b/app/javascript/flavours/glitch/styles/components/composer.scss
@@ -0,0 +1,419 @@
+.composer { padding: 10px }
+
+.composer--spoiler {
+ input {
+ display: block;
+ box-sizing: border-box;
+ margin: 0;
+ border: none;
+ border-radius: 4px;
+ padding: 10px;
+ width: 100%;
+ outline: 0;
+ color: $ui-base-color;
+ background: $simple-background-color;
+ font-size: 14px;
+ font-family: inherit;
+ resize: vertical;
+
+ &:focus { outline: 0 }
+ @include single-column('screen and (max-width: 630px)') { font-size: 16px }
+ }
+}
+
+.composer--warning {
+ color: darken($ui-secondary-color, 65%);
+ margin-bottom: 15px;
+ background: $ui-primary-color;
+ box-shadow: 0 2px 6px rgba($base-shadow-color, 0.3);
+ padding: 8px 10px;
+ border-radius: 4px;
+ font-size: 13px;
+ font-weight: 400;
+
+ a {
+ color: darken($ui-primary-color, 33%);
+ font-weight: 500;
+ text-decoration: underline;
+
+ &:active,
+ &:focus,
+ &:hover { text-decoration: none }
+ }
+}
+
+.composer--reply {
+ margin: 0 0 -2px;
+ border-radius: 4px 4px 0 0;
+ padding: 10px;
+ background: $ui-primary-color;
+
+ & > header {
+ margin-bottom: 5px;
+ overflow: hidden;
+
+ & > .account {
+ & > .avatar {
+ float: left;
+ margin-right: 5px;
+ }
+
+ & > .display_name {
+ color: $ui-base-color;
+ display: block;
+ padding-right: 25px;
+ max-width: 100%;
+ line-height: 24px;
+ text-decoration: none;
+ overflow: hidden;
+ }
+ }
+
+ & > .cancel {
+ float: right;
+ line-height: 24px;
+ }
+ }
+
+ & > .content {
+ position: relative;
+ margin: 10px 0;
+ padding: 0 12px;
+ font-size: 14px;
+ line-height: 20px;
+ color: $ui-base-color;
+ word-wrap: break-word;
+ font-weight: 400;
+ overflow: visible;
+ white-space: pre-wrap;
+ padding-top: 5px;
+ }
+
+ .emojione {
+ width: 20px;
+ height: 20px;
+ margin: -5px 0 0;
+ }
+
+ p {
+ margin-bottom: 20px;
+
+ &:last-child { margin-bottom: 0 }
+ }
+
+ a {
+ color: lighten($ui-base-color, 20%);
+ text-decoration: none;
+
+ &:hover { text-decoration: underline }
+
+ &.mention {
+ &:hover {
+ text-decoration: none;
+
+ span { text-decoration: underline }
+ }
+ }
+ }
+}
+
+.composer--textarea {
+ position: relative;
+
+ & > label {
+ .textarea {
+ display: block;
+ box-sizing: border-box;
+ margin: 0;
+ border: none;
+ border-radius: 4px 4px 0 0;
+ padding: 10px 32px 0 10px;
+ width: 100%;
+ min-height: 100px;
+ outline: 0;
+ color: $ui-base-color;
+ background: $simple-background-color;
+ font-size: 14px;
+ font-family: inherit;
+ resize: none;
+
+ &:disabled { background: $ui-secondary-color }
+ &:focus { outline: 0 }
+ @include single-column('screen and (max-width: 630px)') { font-size: 16px }
+
+ @include limited-single-column('screen and (max-width: 600px)') {
+ height: 100px !important; // prevent auto-resize textarea
+ resize: vertical;
+ }
+ }
+ }
+}
+
+.composer--textarea--suggestions {
+ display: block;
+ position: absolute;
+ box-sizing: border-box;
+ top: 100%;
+ border-radius: 0 0 4px 4px;
+ padding: 6px;
+ width: 100%;
+ color: $ui-base-color;
+ background: $ui-secondary-color;
+ box-shadow: 4px 4px 6px rgba($base-shadow-color, 0.4);
+ font-size: 14px;
+ z-index: 99;
+
+ &[hidden] { display: none }
+}
+
+.composer--textarea--suggestions--item {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: flex-start;
+ border-radius: 4px;
+ padding: 10px;
+ font-size: 14px;
+ line-height: 18px;
+ cursor: pointer;
+
+ &:hover,
+ &:focus,
+ &:active,
+ &.selected { background: darken($ui-secondary-color, 10%) }
+
+ & > .emoji {
+ img {
+ display: block;
+ float: left;
+ margin-right: 8px;
+ width: 18px;
+ height: 18px;
+ }
+ }
+}
+
+.composer--upload_form {
+ padding: 5px;
+ color: $ui-base-color;
+ background: $simple-background-color;
+ font-size: 14px;
+
+ & > .content {
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ font-family: inherit;
+ overflow: hidden;
+ }
+}
+
+.composer--upload_form--item {
+ flex: 1 1 0;
+ margin: 5px;
+ min-width: 40%;
+
+ & > div {
+ position: relative;
+ border-radius: 4px;
+ height: 100px;
+ width: 100%;
+ background-position: center;
+ background-size: cover;
+ background-repeat: no-repeat;
+
+ input {
+ display: block;
+ position: absolute;
+ box-sizing: border-box;
+ bottom: 0;
+ left: 0;
+ margin: 0;
+ border: 0;
+ padding: 10px;
+ width: 100%;
+ color: $ui-secondary-color;
+ background: linear-gradient(0deg, rgba($base-shadow-color, 0.8) 0, rgba($base-shadow-color, 0.35) 80%, transparent);
+ font-size: 14px;
+ font-family: inherit;
+ font-weight: 500;
+ opacity: 0;
+ z-index: 2;
+ transition: opacity .1s ease;
+
+ &:focus { color: $white }
+
+ &::placeholder {
+ opacity: 0.54;
+ color: $ui-secondary-color;
+ }
+ }
+
+ & > .close { mix-blend-mode: difference }
+ }
+
+ &.active {
+ & > div {
+ input { opacity: 1 }
+ }
+ }
+}
+
+.composer--upload_form--progress {
+ display: flex;
+ padding: 10px;
+ color: $ui-base-lighter-color;
+ overflow: hidden;
+
+ & > .fa {
+ font-size: 34px;
+ margin-right: 10px;
+ }
+
+ & > .message {
+ flex: 1 1 auto;
+
+ & > span {
+ display: block;
+ font-size: 12px;
+ font-weight: 500;
+ text-transform: uppercase;
+ }
+
+ & > .backdrop {
+ position: relative;
+ margin-top: 5px;
+ border-radius: 6px;
+ width: 100%;
+ height: 6px;
+ background: $ui-base-lighter-color;
+
+ & > .tracker {
+ position: absolute;
+ top: 0;
+ left: 0;
+ height: 6px;
+ border-radius: 6px;
+ background: $ui-highlight-color;
+ }
+ }
+ }
+}
+
+.composer--options {
+ padding: 10px;
+ background: darken($simple-background-color, 8%);
+ box-shadow: inset 0 5px 5px rgba($base-shadow-color, 0.05);
+ border-radius: 0 0 4px 4px;
+ height: 27px;
+
+ & > * {
+ display: inline-block;
+ box-sizing: content-box;
+ padding: 0 3px;
+ height: 27px;
+ line-height: 27px;
+ vertical-align: bottom;
+ }
+
+ & > hr {
+ display: inline-block;
+ margin: 0 3px;
+ border-width: 0 0 0 1px;
+ border-style: none none none solid;
+ border-color: transparent transparent transparent darken($simple-background-color, 24%);
+ padding: 0;
+ width: 0;
+ height: 27px;
+ background: transparent;
+ }
+}
+
+.composer--options--dropdown {
+ &.open {
+ & > .value {
+ border-radius: 4px 4px 0 0;
+ box-shadow: 0 -4px 4px rgba($base-shadow-color, 0.1);
+ color: $primary-text-color;
+ background: $ui-highlight-color;
+ transition: none;
+ }
+ }
+}
+
+.composer--options--dropdown--content {
+ position: absolute;
+ border-radius: 4px;
+ box-shadow: 2px 4px 15px rgba($base-shadow-color, 0.4);
+ background: $simple-background-color;
+ overflow: hidden;
+ transform-origin: 50% 0;
+}
+
+.composer--options--dropdown--content--item {
+ display: flex;
+ align-items: center;
+ padding: 10px;
+ color: $ui-base-color;
+ cursor: pointer;
+
+ & > .content {
+ flex: 1 1 auto;
+ color: darken($ui-primary-color, 24%);
+
+ &:not(:first-child) { margin-left: 10px }
+
+ strong {
+ display: block;
+ color: $ui-base-color;
+ font-weight: 500;
+ }
+ }
+
+ &:hover,
+ &.active {
+ background: $ui-highlight-color;
+ color: $primary-text-color;
+
+ & > .content {
+ color: $primary-text-color;
+
+ strong { color: $primary-text-color }
+ }
+ }
+
+ &.active:hover { background: lighten($ui-highlight-color, 4%) }
+}
+
+.composer--publisher {
+ padding-top: 10px;
+ text-align: right;
+ white-space: nowrap;
+ overflow: hidden;
+
+ & > .count {
+ display: inline-block;
+ margin: 0 16px 0 8px;
+ font-size: 16px;
+ line-height: 36px;
+ }
+
+ & > .primary {
+ display: inline-block;
+ margin: 0;
+ padding: 0 10px;
+ text-align: center;
+ }
+
+ & > .side_arm {
+ display: inline-block;
+ margin: 0 2px 0 0;
+ padding: 0;
+ width: 36px;
+ text-align: center;
+ }
+
+ &.over {
+ & > .count { color: $warning-red }
+ }
+}
diff --git a/app/javascript/flavours/glitch/styles/components/drawer.scss b/app/javascript/flavours/glitch/styles/components/drawer.scss
new file mode 100644
index 0000000000..ebf9969072
--- /dev/null
+++ b/app/javascript/flavours/glitch/styles/components/drawer.scss
@@ -0,0 +1,223 @@
+.drawer {
+ display: flex;
+ flex-direction: column;
+ box-sizing: border-box;
+ padding: 10px 5px;
+ width: 300px;
+ flex: none;
+ contain: strict;
+
+ &:first-child {
+ padding-left: 10px;
+ }
+
+ &:last-child {
+ padding-right: 10px;
+ }
+
+ @include single-column('screen and (max-width: 630px)') { flex: auto }
+
+ @include limited-single-column('screen and (max-width: 630px)') {
+ &, &:first-child, &:last-child { padding: 0 }
+ }
+
+ .wide & {
+ min-width: 300px;
+ max-width: 400px;
+ flex: 1 1 200px;
+ }
+
+ @include single-column('screen and (max-width: 630px)') {
+ :root & { // Overrides `.wide` for single-column view
+ flex: auto;
+ width: 100%;
+ min-width: 0;
+ max-width: none;
+ padding: 0;
+ }
+ }
+
+ .react-swipeable-view-container & { height: 100% }
+
+ & > .contents {
+ position: relative;
+ padding: 0;
+ width: 100%;
+ height: 100%;
+ background: lighten($ui-base-color, 13%);
+ overflow-x: hidden;
+ overflow-y: auto;
+ contain: strict;
+ }
+}
+
+.drawer--header {
+ display: flex;
+ flex-direction: row;
+ margin-bottom: 10px;
+ flex: none;
+ background: lighten($ui-base-color, 8%);
+ font-size: 16px;
+
+ & > * {
+ display: block;
+ box-sizing: border-box;
+ border-bottom: 2px solid transparent;
+ padding: 15px 5px 13px;
+ height: 48px;
+ flex: 1 1 auto;
+ color: $ui-primary-color;
+ text-align: center;
+ text-decoration: none;
+ cursor: pointer;
+ }
+
+ a {
+ transition: background 100ms ease-in;
+
+ &:focus,
+ &:hover {
+ outline: none;
+ background: lighten($ui-base-color, 3%);
+ transition: background 200ms ease-out;
+ }
+ }
+}
+
+.drawer--search {
+ position: relative;
+ margin-bottom: 10px;
+ flex: none;
+
+ @include limited-single-column('screen and (max-width: 360px)') { margin-bottom: 0 }
+ @include single-column('screen and (max-width: 630px)') { font-size: 16px }
+
+ input {
+ display: block;
+ box-sizing: border-box;
+ margin: 0;
+ border: none;
+ padding: 10px 30px 10px 10px;
+ width: 100%;
+ height: 36px;
+ outline: 0;
+ color: $ui-primary-color;
+ background: $ui-base-color;
+ font-size: 14px;
+ font-family: inherit;
+ line-height: 16px;
+
+ &:focus {
+ outline: 0;
+ background: lighten($ui-base-color, 4%);
+ }
+ }
+
+ & > .icon {
+ .fa {
+ display: inline-block;
+ position: absolute;
+ top: 10px;
+ right: 10px;
+ width: 18px;
+ height: 18px;
+ color: $ui-secondary-color;
+ font-size: 18px;
+ opacity: 0;
+ cursor: default;
+ pointer-events: none;
+ z-index: 2;
+ transition: all 100ms linear;
+ }
+
+ .fa-search {
+ opacity: 0.3;
+ transform: rotate(0deg);
+ }
+
+ .fa-times-circle {
+ top: 11px;
+ transform: rotate(-90deg);
+ cursor: pointer;
+
+ &:hover { color: $primary-text-color }
+ }
+
+ &.active {
+ .fa-search {
+ opacity: 0;
+ transform: rotate(90deg);
+ }
+
+ .fa-times-circle {
+ opacity: 0.3;
+ pointer-events: auto;
+ transform: rotate(0deg);
+ }
+ }
+ }
+}
+
+.drawer--account {
+ padding: 10px;
+ color: $ui-primary-color;
+
+ & > a {
+ color: inherit;
+ text-decoration: none;
+ }
+
+ & > .avatar {
+ float: left;
+ margin-right: 10px;
+ }
+
+ & > .acct {
+ display: block;
+ color: $primary-text-color;
+ font-weight: 500;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+}
+
+.drawer--results {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ padding: 0;
+ background: $ui-base-color;
+ overflow-x: hidden;
+ overflow-y: auto;
+ contain: strict;
+
+ & > header {
+ border-bottom: 1px solid darken($ui-base-color, 4%);
+ padding: 15px 10px;
+ color: $ui-base-lighter-color;
+ background: lighten($ui-base-color, 2%);
+ font-size: 14px;
+ font-weight: 500;
+ }
+
+ & > section {
+ background: $ui-base-color;
+
+ & > .hashtag {
+ display: block;
+ padding: 10px;
+ color: $ui-secondary-color;
+ text-decoration: none;
+
+ &:hover,
+ &:active,
+ &:focus {
+ color: lighten($ui-secondary-color, 4%);
+ text-decoration: underline;
+ }
+ }
+ }
+}
diff --git a/app/javascript/flavours/glitch/styles/components/index.scss b/app/javascript/flavours/glitch/styles/components/index.scss
index b947c082d8..ab1359108f 100644
--- a/app/javascript/flavours/glitch/styles/components/index.scss
+++ b/app/javascript/flavours/glitch/styles/components/index.scss
@@ -264,172 +264,6 @@
color: $ui-base-color;
}
-.compose-form {
- padding: 10px;
-}
-
-.compose-form__warning {
- color: darken($ui-secondary-color, 65%);
- margin-bottom: 15px;
- background: $ui-primary-color;
- box-shadow: 0 2px 6px rgba($base-shadow-color, 0.3);
- padding: 8px 10px;
- border-radius: 4px;
- font-size: 13px;
- font-weight: 400;
-
- strong {
- color: darken($ui-secondary-color, 65%);
- font-weight: 500;
- }
-
- a {
- color: darken($ui-primary-color, 33%);
- font-weight: 500;
- text-decoration: underline;
-
- &:hover,
- &:active,
- &:focus {
- text-decoration: none;
- }
- }
-}
-
-.compose-form__modifiers {
- color: $ui-base-color;
- font-family: inherit;
- font-size: 14px;
- background: $simple-background-color;
-}
-
-.compose-form__buttons-wrapper {
- display: flex;
- justify-content: space-between;
-}
-
-.compose-form__buttons {
- padding: 10px;
- background: darken($simple-background-color, 8%);
- box-shadow: inset 0 5px 5px rgba($base-shadow-color, 0.05);
- border-radius: 0 0 4px 4px;
- display: flex;
-
- .icon-button {
- box-sizing: content-box;
- padding: 0 3px;
- }
-}
-
-.compose-form__buttons-separator {
- border-left: 1px solid #c3c3c3;
- margin: 0 3px;
-}
-
-.compose-form__upload-button-icon {
- line-height: 27px;
-}
-
-.compose-form__sensitive-button {
- display: none;
-
- &.compose-form__sensitive-button--visible {
- display: block;
- }
-
- .compose-form__sensitive-button__icon {
- line-height: 27px;
- }
-}
-
-.compose-form__upload-wrapper {
- overflow: hidden;
-}
-
-.compose-form__uploads-wrapper {
- display: flex;
- flex-direction: row;
- padding: 5px;
- flex-wrap: wrap;
-}
-
-.compose-form__upload {
- flex: 1 1 0;
- min-width: 40%;
- margin: 5px;
-
- &-description {
- position: absolute;
- z-index: 2;
- bottom: 0;
- left: 0;
- right: 0;
- box-sizing: border-box;
- background: linear-gradient(0deg, rgba($base-shadow-color, 0.8) 0, rgba($base-shadow-color, 0.35) 80%, transparent);
- padding: 10px;
- opacity: 0;
- transition: opacity .1s ease;
-
- input {
- background: transparent;
- color: $ui-secondary-color;
- border: 0;
- padding: 0;
- margin: 0;
- width: 100%;
- font-family: inherit;
- font-size: 14px;
- font-weight: 500;
-
- &:focus {
- color: $white;
- }
-
- &::placeholder {
- opacity: 0.54;
- color: $ui-secondary-color;
- }
- }
-
- &.active {
- opacity: 1;
- }
- }
-
- .icon-button {
- mix-blend-mode: difference;
- }
-}
-
-.compose-form__upload-thumbnail {
- border-radius: 4px;
- background-position: center;
- background-size: cover;
- background-repeat: no-repeat;
- height: 100px;
- width: 100%;
-}
-
-.compose-form__label {
- display: block;
- line-height: 24px;
- vertical-align: middle;
-
- &.with-border {
- border-top: 1px solid $ui-base-color;
- padding-top: 10px;
- }
-
- .compose-form__label__text {
- display: inline-block;
- vertical-align: middle;
- margin-bottom: 14px;
- margin-left: 8px;
- color: $ui-primary-color;
- }
-}
-
-.compose-form__textarea,
.follow-form__input {
background: $simple-background-color;
@@ -438,49 +272,17 @@
}
}
-.compose-form__autosuggest-wrapper {
- position: relative;
+.emoji-picker-dropdown {
+ position: absolute;
+ right: 5px;
+ top: 5px;
- .emoji-picker-dropdown {
- position: absolute;
- right: 5px;
- top: 5px;
-
- ::-webkit-scrollbar-track:hover,
- ::-webkit-scrollbar-track:active {
- background-color: rgba($base-overlay-background, 0.3);
- }
+ ::-webkit-scrollbar-track:hover,
+ ::-webkit-scrollbar-track:active {
+ background-color: rgba($base-overlay-background, 0.3);
}
}
-.compose-form__publish {
- display: flex;
- justify-content: flex-end;
- min-width: 0;
-}
-
-.compose-form__publish-button-wrapper {
- overflow: hidden;
- padding-top: 10px;
- white-space: nowrap;
- display: flex;
-
- button {
- text-overflow: unset;
- }
-}
-
-.compose-form__publish__side-arm {
- padding: 0 !important;
- width: 36px;
- text-align: center;
- margin-right: 2px;
-}
-
-.compose-form__publish__primary {
- padding: 0 10px !important;
-}
-
.emojione {
display: inline-block;
font-size: inherit;
@@ -495,46 +297,12 @@
}
}
-.reply-indicator {
- border-radius: 4px 4px 0 0;
- position: relative;
- bottom: -2px;
- background: $ui-primary-color;
- padding: 10px;
-}
-
-.reply-indicator__header {
- margin-bottom: 5px;
- overflow: hidden;
-}
-
-.reply-indicator__cancel {
- float: right;
- line-height: 24px;
-}
-
-.reply-indicator__display-name {
- color: $ui-base-color;
- display: block;
- max-width: 100%;
- line-height: 24px;
- overflow: hidden;
- padding-right: 25px;
- text-decoration: none;
-}
-
-.reply-indicator__display-avatar {
- float: left;
- margin-right: 5px;
-}
-
.status__content--with-action {
cursor: pointer;
}
.status-check-box {
- .status__content,
- .reply-indicator__content {
+ .status__content {
color: #3a3a3a;
a {
color: #005aa9;
@@ -542,8 +310,7 @@
}
}
-.status__content,
-.reply-indicator__content {
+.status__content {
position: relative;
margin: 10px 0;
padding: 0 12px;
@@ -975,15 +742,6 @@
margin-left: 6px;
}
-.reply-indicator__content {
- color: $ui-base-color;
- font-size: 14px;
-
- a {
- color: lighten($ui-base-color, 20%);
- }
-}
-
.account {
padding: 10px;
border-bottom: 1px solid lighten($ui-base-color, 8%);
@@ -996,6 +754,37 @@
text-decoration: none;
font-size: 14px;
}
+
+ &.small {
+ border: none;
+ padding: 0;
+
+ & > .account__avatar-wrapper { margin: 0 8px 0 0 }
+
+ & > .display-name {
+ display: block;
+ padding: 0;
+ height: auto;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ white-space: nowrap;
+
+ & > strong {
+ display: inline;
+ font-size: inherit;
+ line-height: inherit;
+ }
+
+ & > span {
+ display: inline;
+ color: lighten($ui-base-color, 36%);
+ font-size: inherit;
+ line-height: inherit;
+
+ &::before { content: " " }
+ }
+ }
+ }
}
.account__wrapper {
@@ -1497,45 +1286,6 @@
}
}
-.navigation-bar {
- padding: 10px;
- display: flex;
- flex-shrink: 0;
- cursor: default;
- color: $ui-primary-color;
-
- strong {
- color: $primary-text-color;
- }
-
- .permalink {
- text-decoration: none;
- }
-
- .icon-button {
- pointer-events: none;
- opacity: 0;
- }
-}
-
-.navigation-bar__profile {
- flex: 1 1 auto;
- margin-left: 8px;
- overflow: hidden;
-}
-
-.navigation-bar__profile-account {
- display: block;
- font-weight: 500;
- overflow: hidden;
- text-overflow: ellipsis;
-}
-
-.navigation-bar__profile-edit {
- color: inherit;
- text-decoration: none;
-}
-
.dropdown {
display: inline-block;
}
@@ -1718,7 +1468,6 @@
.react-swipeable-view-container {
&,
.columns-area,
- .drawer,
.column {
height: 100%;
}
@@ -1759,36 +1508,7 @@
background: darken($ui-base-color, 7%);
}
-.drawer {
- width: 300px;
- box-sizing: border-box;
- display: flex;
- flex-direction: column;
- overflow-y: auto;
-
- .wide & {
- flex: 1 1 200px;
- min-width: 300px;
- max-width: 400px;
- }
-}
-
-.drawer__tab {
- display: block;
- flex: 1 1 auto;
- padding: 15px 5px 13px;
- color: $ui-primary-color;
- text-decoration: none;
- text-align: center;
- font-size: 16px;
- border-bottom: 2px solid transparent;
- outline: none;
- cursor: pointer;
-}
-
-.column,
-.drawer {
- flex: 1 1 100%;
+.column {
overflow: hidden;
}
@@ -1796,16 +1516,11 @@
.tabs-bar {
margin: 0;
}
-
- .search {
- margin-bottom: 0;
- }
}
:root { // Overrides .wide stylings for mobile view
@include single-column('screen and (max-width: 630px)', $parent: null) {
- .column,
- .drawer {
+ .column {
flex: auto;
width: 100%;
min-width: 0;
@@ -1816,11 +1531,6 @@
.columns-area {
flex-direction: column;
}
-
- .search__input,
- .autosuggest-textarea__textarea {
- font-size: 16px;
- }
}
}
@@ -1829,8 +1539,7 @@
padding: 0;
}
- .column,
- .drawer {
+ .column {
padding: 10px;
padding-left: 5px;
padding-right: 5px;
@@ -1845,63 +1554,19 @@
}
.columns-area > div {
- .column,
- .drawer {
+ .column {
padding-left: 5px;
padding-right: 5px;
}
}
}
-.drawer__pager {
- box-sizing: border-box;
- padding: 0;
- flex: 1 1 auto;
- position: relative;
-}
-
-.drawer__inner {
- background: lighten($ui-base-color, 13%);
- box-sizing: border-box;
- padding: 0;
- position: absolute;
- height: 100%;
- width: 100%;
-
- &.darker {
- position: absolute;
- top: 0;
- left: 0;
- background: $ui-base-color;
- width: 100%;
- height: 100%;
- }
-}
-
.pseudo-drawer {
background: lighten($ui-base-color, 13%);
font-size: 13px;
text-align: left;
}
-.drawer__header {
- flex: 0 0 auto;
- font-size: 16px;
- background: lighten($ui-base-color, 8%);
- margin-bottom: 10px;
- display: flex;
- flex-direction: row;
-
- a {
- transition: background 100ms ease-in;
-
- &:hover {
- background: lighten($ui-base-color, 3%);
- transition: background 200ms ease-out;
- }
- }
-}
-
.tabs-bar {
display: flex;
background: lighten($ui-base-color, 8%);
@@ -2176,121 +1841,6 @@
cursor: default;
}
-.autosuggest-textarea,
-.spoiler-input {
- position: relative;
-}
-
-.autosuggest-textarea__textarea,
-.spoiler-input__input {
- display: block;
- box-sizing: border-box;
- width: 100%;
- margin: 0;
- color: $ui-base-color;
- background: $simple-background-color;
- padding: 10px;
- font-family: inherit;
- font-size: 14px;
- resize: vertical;
- border: 0;
- outline: 0;
-
- &:focus {
- outline: 0;
- }
-
- @include limited-single-column('screen and (max-width: 600px)') {
- font-size: 16px;
- }
-}
-
-.spoiler-input__input {
- border-radius: 4px;
-}
-
-.autosuggest-textarea__textarea {
- min-height: 100px;
- border-radius: 4px 4px 0 0;
- padding-bottom: 0;
- padding-right: 10px + 22px;
- resize: none;
-
- @include limited-single-column('screen and (max-width: 600px)') {
- height: 100px !important; // prevent auto-resize textarea
- resize: vertical;
- }
-}
-
-.autosuggest-textarea__suggestions {
- box-sizing: border-box;
- display: none;
- position: absolute;
- top: 100%;
- width: 100%;
- z-index: 99;
- box-shadow: 4px 4px 6px rgba($base-shadow-color, 0.4);
- background: $ui-secondary-color;
- border-radius: 0 0 4px 4px;
- color: $ui-base-color;
- font-size: 14px;
- padding: 6px;
-
- &.autosuggest-textarea__suggestions--visible {
- display: block;
- }
-}
-
-.autosuggest-textarea__suggestions__item {
- padding: 10px;
- cursor: pointer;
- border-radius: 4px;
-
- &:hover,
- &:focus,
- &:active,
- &.selected {
- background: darken($ui-secondary-color, 10%);
- }
-}
-
-.autosuggest-account,
-.autosuggest-emoji {
- display: flex;
- flex-direction: row;
- align-items: center;
- justify-content: flex-start;
- line-height: 18px;
- font-size: 14px;
-}
-
-.autosuggest-account-icon,
-.autosuggest-emoji img {
- display: block;
- margin-right: 8px;
- width: 16px;
- height: 16px;
-}
-
-.autosuggest-account .display-name__account {
- color: lighten($ui-base-color, 36%);
-}
-
-.character-counter__wrapper {
- line-height: 36px;
- margin: 0 16px 0 8px;
- padding-top: 10px;
-}
-
-.character-counter {
- cursor: default;
- font-size: 16px;
-}
-
-.character-counter--over {
- color: $warning-red;
-}
-
.getting-started__wrapper {
position: relative;
overflow-y: auto;
@@ -3185,47 +2735,6 @@
border-radius: 4px;
}
-.upload-progress {
- padding: 10px;
- color: $ui-base-lighter-color;
- overflow: hidden;
- display: flex;
-
- .fa {
- font-size: 34px;
- margin-right: 10px;
- }
-
- span {
- font-size: 12px;
- text-transform: uppercase;
- font-weight: 500;
- display: block;
- }
-}
-
-.upload-progess__message {
- flex: 1 1 auto;
-}
-
-.upload-progress__backdrop {
- width: 100%;
- height: 6px;
- border-radius: 6px;
- background: $ui-base-lighter-color;
- position: relative;
- margin-top: 5px;
-}
-
-.upload-progress__tracker {
- position: absolute;
- left: 0;
- top: 0;
- height: 6px;
- background: $ui-highlight-color;
- border-radius: 6px;
-}
-
.emoji-button {
display: block;
font-size: 24px;
@@ -3265,268 +2774,6 @@
filter: none;
}
-.privacy-dropdown__dropdown {
- position: absolute;
- background: $simple-background-color;
- box-shadow: 2px 4px 15px rgba($base-shadow-color, 0.4);
- border-radius: 4px;
- margin-left: 40px;
- overflow: hidden;
- transform-origin: 50% 0;
-}
-
-.privacy-dropdown__option {
- color: $ui-base-color;
- padding: 10px;
- cursor: pointer;
- display: flex;
-
- &:hover,
- &.active {
- background: $ui-highlight-color;
- color: $primary-text-color;
-
- .privacy-dropdown__option__content {
- color: $primary-text-color;
-
- strong {
- color: $primary-text-color;
- }
- }
- }
-
- &.active:hover {
- background: lighten($ui-highlight-color, 4%);
- }
-}
-
-.privacy-dropdown__option__icon {
- display: flex;
- align-items: center;
- justify-content: center;
- margin-right: 10px;
-}
-
-.privacy-dropdown__option__content {
- flex: 1 1 auto;
- color: darken($ui-primary-color, 24%);
-
- strong {
- font-weight: 500;
- display: block;
- color: $ui-base-color;
- }
-}
-
-.privacy-dropdown.active {
- .privacy-dropdown__value {
- background: $simple-background-color;
- border-radius: 4px 4px 0 0;
- box-shadow: 0 -4px 4px rgba($base-shadow-color, 0.1);
-
- .icon-button {
- transition: none;
- }
-
- &.active {
- background: $ui-highlight-color;
-
- .icon-button {
- color: $primary-text-color;
- }
- }
- }
-
- .privacy-dropdown__dropdown {
- display: block;
- box-shadow: 2px 4px 6px rgba($base-shadow-color, 0.1);
- }
-}
-
-.advanced-options-dropdown {
- position: relative;
-}
-
-.advanced-options-dropdown__dropdown {
- display: none;
- position: absolute;
- left: 0;
- top: 27px;
- width: 210px;
- background: $simple-background-color;
- border-radius: 0 4px 4px;
- z-index: 2;
- overflow: hidden;
-}
-
-.advanced-options-dropdown__option {
- color: $ui-base-color;
- padding: 10px;
- cursor: pointer;
- display: flex;
-
- &:hover,
- &.active {
- background: $ui-highlight-color;
- color: $primary-text-color;
-
- .advanced-options-dropdown__option__content {
- color: $primary-text-color;
-
- strong {
- color: $primary-text-color;
- }
- }
- }
-
- &.active:hover {
- background: lighten($ui-highlight-color, 4%);
- }
-}
-
-.advanced-options-dropdown__option__toggle {
- display: flex;
- align-items: center;
- justify-content: center;
- margin-right: 10px;
-}
-
-.advanced-options-dropdown__option__content {
- flex: 1 1 auto;
- color: darken($ui-primary-color, 24%);
-
- strong {
- font-weight: 500;
- display: block;
- color: $ui-base-color;
- }
-}
-
-.advanced-options-dropdown.open {
- .advanced-options-dropdown__value {
- background: $simple-background-color;
- border-radius: 4px 4px 0 0;
- box-shadow: 0 -4px 4px rgba($base-shadow-color, 0.1);
- }
-
- .advanced-options-dropdown__dropdown {
- display: block;
- box-shadow: 2px 4px 6px rgba($base-shadow-color, 0.1);
- }
-}
-
-
-.search {
- position: relative;
- margin-bottom: 10px;
-}
-
-.search__input {
- outline: 0;
- box-sizing: border-box;
- display: block;
- width: 100%;
- border: none;
- padding: 10px;
- padding-right: 30px;
- font-family: inherit;
- background: $ui-base-color;
- color: $ui-primary-color;
- font-size: 14px;
- margin: 0;
-
- &::-moz-focus-inner {
- border: 0;
- }
-
- &::-moz-focus-inner,
- &:focus,
- &:active {
- outline: 0 !important;
- }
-
- &:focus {
- background: lighten($ui-base-color, 4%);
- }
-
- @include limited-single-column('screen and (max-width: 600px)') {
- font-size: 16px;
- }
-}
-
-.search__icon {
- .fa {
- position: absolute;
- top: 10px;
- right: 10px;
- z-index: 2;
- display: inline-block;
- opacity: 0;
- transition: all 100ms linear;
- font-size: 18px;
- width: 18px;
- height: 18px;
- color: $ui-secondary-color;
- cursor: default;
- pointer-events: none;
-
- &.active {
- pointer-events: auto;
- opacity: 0.3;
- }
- }
-
- .fa-search {
- transform: rotate(90deg);
-
- &.active {
- pointer-events: none;
- transform: rotate(0deg);
- }
- }
-
- .fa-times-circle {
- top: 11px;
- transform: rotate(0deg);
- cursor: pointer;
-
- &.active {
- transform: rotate(90deg);
- }
-
- &:hover {
- color: $primary-text-color;
- }
- }
-}
-
-.search-results__header {
- color: $ui-base-lighter-color;
- background: lighten($ui-base-color, 2%);
- border-bottom: 1px solid darken($ui-base-color, 4%);
- padding: 15px 10px;
- font-size: 14px;
- font-weight: 500;
-}
-
-.search-results__section {
- background: $ui-base-color;
-}
-
-.search-results__hashtag {
- display: block;
- padding: 10px;
- color: $ui-secondary-color;
- text-decoration: none;
-
- &:hover,
- &:active,
- &:focus {
- color: lighten($ui-secondary-color, 4%);
- text-decoration: underline;
- }
-}
-
.modal-root {
transition: opacity 0.3s linear;
will-change: opacity;
@@ -4081,7 +3328,8 @@
max-height: 80vh;
max-width: 80vw;
- .actions-modal__item-label {
+ strong {
+ display: block;
font-weight: 500;
}
@@ -4094,31 +3342,25 @@
}
li:not(:empty) {
- a {
+ & > .link {
color: $ui-base-color;
display: flex;
padding: 12px 16px;
font-size: 15px;
align-items: center;
text-decoration: none;
-
- &,
- button {
- transition: none;
- }
+ transition: none;
&.active,
&:hover,
&:active,
&:focus {
- &,
- button {
- background: $ui-highlight-color;
- color: $primary-text-color;
- }
+ background: $ui-highlight-color;
+ color: $primary-text-color;
}
- button:first-child {
+ & > .react-toggle,
+ & > .icon {
margin-right: 10px;
}
}
@@ -4732,80 +3974,6 @@ noscript {
100% { opacity: 1; }
}
-@media screen and (max-width: 630px) and (max-height: 400px) {
- $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;
- }
- }
- }
-
- // fixes for the navbar-under mode
- .is-composing.navbar-under {
- .search {
- margin-top: -20px;
- margin-bottom: -20px;
- .search__icon {
- display: none;
- }
- }
- }
-}
-
// more fixes for the navbar-under mode
@mixin fix-margins-for-navbar-under {
.tabs-bar {
@@ -4984,6 +4152,8 @@ noscript {
}
}
+@import 'composer';
@import 'doodle';
+@import 'drawer';
@import 'emoji_picker';
@import 'local_settings';
diff --git a/app/javascript/flavours/glitch/theme.yml b/app/javascript/flavours/glitch/theme.yml
index 435fa23293..8ccd8fa656 100644
--- a/app/javascript/flavours/glitch/theme.yml
+++ b/app/javascript/flavours/glitch/theme.yml
@@ -11,8 +11,8 @@ pack:
home:
filename: packs/home.js
preload:
+ - flavours/glitch/async/drawer
- flavours/glitch/async/getting_started
- - flavours/glitch/async/compose
- flavours/glitch/async/home_timeline
- flavours/glitch/async/notifications
modal:
diff --git a/app/javascript/flavours/glitch/util/async-components.js b/app/javascript/flavours/glitch/util/async-components.js
index 5d21ccca2a..b90f1b8c86 100644
--- a/app/javascript/flavours/glitch/util/async-components.js
+++ b/app/javascript/flavours/glitch/util/async-components.js
@@ -2,8 +2,8 @@ export function EmojiPicker () {
return import(/* webpackChunkName: "flavours/glitch/async/emoji_picker" */'flavours/glitch/util/emoji/emoji_picker');
}
-export function Compose () {
- return import(/* webpackChunkName: "flavours/glitch/async/compose" */'flavours/glitch/features/compose');
+export function Drawer () {
+ return import(/* webpackChunkName: "flavours/glitch/async/drawer" */'flavours/glitch/features/drawer');
}
export function Notifications () {
diff --git a/app/javascript/flavours/glitch/util/dom_helpers.js b/app/javascript/flavours/glitch/util/dom_helpers.js
new file mode 100644
index 0000000000..3e1f4a26d7
--- /dev/null
+++ b/app/javascript/flavours/glitch/util/dom_helpers.js
@@ -0,0 +1,14 @@
+// Package imports.
+import detectPassiveEvents from 'detect-passive-events';
+
+// This will either be a passive lister options object (if passive
+// events are supported), or `false`.
+export const withPassive = detectPassiveEvents.hasSupport ? { passive: true } : false;
+
+// Focuses the root element.
+export function focusRoot () {
+ let e;
+ if (document && (e = document.querySelector('.ui')) && (e = e.parentElement)) {
+ e.focus();
+ }
+}
diff --git a/app/javascript/flavours/glitch/util/emoji/index.js b/app/javascript/flavours/glitch/util/emoji/index.js
index 31c3e14cac..c6416db2d3 100644
--- a/app/javascript/flavours/glitch/util/emoji/index.js
+++ b/app/javascript/flavours/glitch/util/emoji/index.js
@@ -70,6 +70,7 @@ const emojify = (str, customEmojis = {}) => {
};
export default emojify;
+export { unicodeMapping };
export const buildCustomEmojis = (customEmojis) => {
const emojis = [];
diff --git a/app/javascript/flavours/glitch/util/initial_state.js b/app/javascript/flavours/glitch/util/initial_state.js
index 607d6b9b04..530bca7ef6 100644
--- a/app/javascript/flavours/glitch/util/initial_state.js
+++ b/app/javascript/flavours/glitch/util/initial_state.js
@@ -18,5 +18,6 @@ export const boostModal = getMeta('boost_modal');
export const favouriteModal = getMeta('favourite_modal');
export const deleteModal = getMeta('delete_modal');
export const me = getMeta('me');
+export const maxChars = getMeta('max_toot_chars') || 500;
export default initialState;
diff --git a/app/javascript/flavours/glitch/util/react_helpers.js b/app/javascript/flavours/glitch/util/react_helpers.js
new file mode 100644
index 0000000000..082a58e626
--- /dev/null
+++ b/app/javascript/flavours/glitch/util/react_helpers.js
@@ -0,0 +1,21 @@
+// This function binds the given `handlers` to the `target`.
+export function assignHandlers (target, handlers) {
+ if (!target || !handlers) {
+ return;
+ }
+
+ // We just bind each handler to the `target`.
+ const handle = target.handlers = {};
+ Object.keys(handlers).forEach(
+ key => handle[key] = handlers[key].bind(target)
+ );
+}
+
+// This function only returns the component if the result of calling
+// `test` with `data` is `true`. Useful with funciton binding.
+export function conditionalRender (test, data, component) {
+ return test(data) ? component : null;
+}
+
+// This object provides props to make the component not visible.
+export const hiddenComponent = { style: { display: 'none' } };
diff --git a/app/javascript/flavours/glitch/util/redux_helpers.js b/app/javascript/flavours/glitch/util/redux_helpers.js
new file mode 100644
index 0000000000..8eb338da70
--- /dev/null
+++ b/app/javascript/flavours/glitch/util/redux_helpers.js
@@ -0,0 +1,8 @@
+import { injectIntl } from 'react-intl';
+import { connect } from 'react-redux';
+
+// Connects a component.
+export function wrap (Component, mapStateToProps, mapDispatchToProps, options) {
+ const withIntl = typeof options === 'object' ? options.withIntl : !!options;
+ return (withIntl ? injectIntl : i => i)(connect(mapStateToProps, mapDispatchToProps)(Component));
+}