Skip to content
This repository was archived by the owner on Dec 30, 2022. It is now read-only.

Commit bb4884f

Browse files
authored
Merge branch 'features/mild-master' into 3.1.3
2 parents 85f0e0a + 7a35fdd commit bb4884f

File tree

25 files changed

+1149
-49
lines changed

25 files changed

+1149
-49
lines changed

Gemfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ gem 'json-ld'
104104
gem 'json-ld-preloaded', '~> 3.1'
105105
gem 'rdf-normalize', '~> 0.4'
106106

107+
gem 'redcarpet', "~> 3.4.0"
108+
107109
group :development, :test do
108110
gem 'fabrication', '~> 2.21'
109111
gem 'fuubar', '~> 2.5'

Gemfile.lock

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,7 @@ GEM
491491
link_header (~> 0.0, >= 0.0.8)
492492
rdf-normalize (0.4.0)
493493
rdf (~> 3.1)
494+
redcarpet (3.4.0)
494495
redis (4.1.3)
495496
redis-actionpack (5.0.2)
496497
actionpack (>= 4.0, < 6)
@@ -757,6 +758,7 @@ DEPENDENCIES
757758
rails-i18n (~> 5.1)
758759
rails-settings-cached (~> 0.6)
759760
rdf-normalize (~> 0.4)
761+
redcarpet (~> 3.4.0)
760762
redis (~> 4.1)
761763
redis-namespace (~> 1.7)
762764
redis-rails (~> 5.0)
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { changeCompose } from '../actions/compose';
2+
3+
4+
5+
export const UTILBTNS_GOJI = 'UTILBTNS_GOJI';
6+
export const UTILBTNS_HARUKIN = 'UTILBTNS_HARUKIN';
7+
8+
9+
10+
export function submitGoji (textarea) {
11+
return function (dispatch, getState) {
12+
if (!textarea.value) {
13+
let text = [
14+
"#ゴジモリィィィィイイ",
15+
":goji:"
16+
].join("\r\n");
17+
18+
dispatch(submitGojiRequest());
19+
dispatch(changeCompose(text));
20+
21+
textarea.focus();
22+
}
23+
}
24+
}
25+
26+
export function submitGojiRequest () {
27+
return {
28+
type: UTILBTNS_GOJI
29+
}
30+
}
31+
32+
export function submitHarukin (textarea) {
33+
return function (dispatch, getState) {
34+
const HARUKINS = [":harukin: ", ":harukin_old: ", ":harukin_ika: ", ":harukin_tako: "];
35+
const MAX = 6;
36+
37+
if (!textarea.value) {
38+
let text = "";
39+
40+
let quantity = Math.round(Math.random() * MAX + 1);
41+
let type = Math.round(Math.random() * (HARUKINS.length - 1));
42+
43+
let harukin = HARUKINS[type];
44+
45+
switch (quantity) {
46+
default:
47+
text = [
48+
harukin.repeat(quantity),
49+
"🔥 ".repeat(quantity)
50+
].join("\r\n");
51+
52+
break;
53+
54+
case MAX + 1:
55+
text = `${harukin}💕\r\n`.repeat(6);
56+
break;
57+
}
58+
59+
dispatch(submitHarukinRequest());
60+
dispatch(changeCompose(text));
61+
62+
textarea.focus();
63+
}
64+
}
65+
}
66+
67+
export function submitHarukinRequest () {
68+
return {
69+
type: UTILBTNS_HARUKIN
70+
}
71+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import React from 'react';
2+
import Motion from 'react-motion/lib/Motion';
3+
import spring from 'react-motion/lib/spring';
4+
import PropTypes from 'prop-types';
5+
6+
class IconButton extends React.PureComponent {
7+
8+
static propTypes = {
9+
className: PropTypes.string,
10+
title: PropTypes.string.isRequired,
11+
icon: PropTypes.string.isRequired,
12+
onClick: PropTypes.func,
13+
size: PropTypes.number,
14+
active: PropTypes.bool,
15+
style: PropTypes.object,
16+
activeStyle: PropTypes.object,
17+
disabled: PropTypes.bool,
18+
inverted: PropTypes.bool,
19+
animate: PropTypes.bool,
20+
overlay: PropTypes.bool,
21+
};
22+
23+
static defaultProps = {
24+
size: 18,
25+
active: false,
26+
disabled: false,
27+
animate: false,
28+
overlay: false,
29+
};
30+
31+
handleClick = (e) => {
32+
e.preventDefault();
33+
34+
if (!this.props.disabled) {
35+
this.props.onClick(e);
36+
}
37+
}
38+
39+
render () {
40+
const style = {
41+
fontSize: `${this.props.size}px`,
42+
width: `${this.props.size * 1.28571429}px`,
43+
height: `${this.props.size * 1.28571429}px`,
44+
lineHeight: `${this.props.size}px`,
45+
...this.props.style,
46+
...(this.props.active ? this.props.activeStyle : {}),
47+
};
48+
49+
const classes = ['icon-button'];
50+
51+
if (this.props.active) {
52+
classes.push('active');
53+
}
54+
55+
if (this.props.disabled) {
56+
classes.push('disabled');
57+
}
58+
59+
if (this.props.inverted) {
60+
classes.push('inverted');
61+
}
62+
63+
if (this.props.overlay) {
64+
classes.push('overlayed');
65+
}
66+
67+
if (this.props.className) {
68+
classes.push(this.props.className);
69+
}
70+
71+
return (
72+
<Motion defaultStyle={{ rotate: this.props.active ? 180 : 0 }} style={{ rotate: this.props.animate ? spring(this.props.active ? 0 : 180) : 0 }}>
73+
{({ rotate }) =>
74+
<button
75+
aria-label={this.props.title}
76+
title={this.props.title}
77+
className={classes.join(' ')}
78+
onClick={this.handleClick}
79+
style={style}
80+
>
81+
<i style={{ transform: `rotate(${rotate}deg)` }} className={`fa fa-fw fa-${this.props.icon}`} aria-hidden='true' />
82+
</button>
83+
}
84+
</Motion>
85+
);
86+
}
87+
88+
}
89+
90+
export default IconButton;

app/javascript/mastodon/components/status_action_bar.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,14 @@ class StatusActionBar extends ImmutablePureComponent {
129129
}
130130
}
131131

132+
handleBookmarkClick = () => {
133+
this.props.onBookmark(this.props.status);
134+
}
135+
136+
handleReblogClick = (e) => {
137+
this.props.onReblog(this.props.status, e);
138+
}
139+
132140
_openInteractionDialog = type => {
133141
window.open(`/interact/${this.props.status.get('id')}?type=${type}`, 'mastodon-intent', 'width=445,height=600,resizable=no,menubar=no,status=no,scrollbars=yes');
134142
}
@@ -329,6 +337,7 @@ class StatusActionBar extends ImmutablePureComponent {
329337
<IconButton className='status__action-bar-button' disabled={!publicStatus} active={status.get('reblogged')} pressed={status.get('reblogged')} title={!publicStatus ? intl.formatMessage(messages.cannot_reblog) : intl.formatMessage(messages.reblog)} icon={reblogIcon} onClick={this.handleReblogClick} />
330338
<IconButton className='status__action-bar-button star-icon' animate active={status.get('favourited')} pressed={status.get('favourited')} title={intl.formatMessage(messages.favourite)} icon='star' onClick={this.handleFavouriteClick} />
331339
{shareButton}
340+
<IconButton className='status__action-bar-button' disabled={anonymousAccess} active={status.get('bookmarked')} pressed={status.get('bookmarked')} title={intl.formatMessage(messages.bookmark)} icon='bookmark' onClick={this.handleBookmarkClick} />
332341

333342
<div className='status__action-bar-dropdown'>
334343
<DropdownMenuContainer disabled={anonymousAccess} status={status} items={menu} icon='ellipsis-h' size={18} direction='right' title={intl.formatMessage(messages.more)} />
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
import React from 'react';
2+
import Immutable from 'immutable';
3+
import PropTypes from 'prop-types';
4+
import Link from 'react-router-dom/Link';
5+
import { defineMessages, injectIntl } from 'react-intl';
6+
import IconButton from '../../../components/announcement_icon_button';
7+
import Motion from 'react-motion/lib/Motion';
8+
import spring from 'react-motion/lib/spring';
9+
10+
const Collapsable = ({ fullHeight, minHeight, isVisible, children }) => (
11+
<Motion defaultStyle={{ height: isVisible ? fullHeight : minHeight }} style={{ height: spring(!isVisible ? minHeight : fullHeight) }}>
12+
{({ height }) =>
13+
<div style={{ height: `${height}px`, overflow: 'hidden' }}>
14+
{children}
15+
</div>
16+
}
17+
</Motion>
18+
);
19+
20+
Collapsable.propTypes = {
21+
fullHeight: PropTypes.number.isRequired,
22+
minHeight: PropTypes.number.isRequired,
23+
isVisible: PropTypes.bool.isRequired,
24+
children: PropTypes.node.isRequired,
25+
};
26+
27+
const messages = defineMessages({
28+
toggle_visible: { id: 'media_gallery.toggle_visible', defaultMessage: 'Toggle visibility' },
29+
welcome: { id: 'welcome.message', defaultMessage: '{domain}へようこそ!' },
30+
markdown: { id: 'markdown.list', defaultMessage: 'markdown一覧' },
31+
});
32+
33+
const hashtags = Immutable.fromJS([
34+
'神崎ドン自己紹介',
35+
]);
36+
37+
class Announcements extends React.PureComponent {
38+
39+
static propTypes = {
40+
intl: PropTypes.object.isRequired,
41+
homeSize: PropTypes.number,
42+
isLoading: PropTypes.bool,
43+
};
44+
45+
state = {
46+
showId: null,
47+
isLoaded: false,
48+
};
49+
50+
onClick = (announcementId, currentState) => {
51+
this.setState({ showId: currentState.showId === announcementId ? null : announcementId });
52+
}
53+
nl2br (text) {
54+
return text.split(/(\n)/g).map((line, i) => {
55+
if (line.match(/(\n)/g)) {
56+
return React.createElement('br', { key: i });
57+
}
58+
return line;
59+
});
60+
}
61+
62+
render () {
63+
const { intl } = this.props;
64+
65+
return (
66+
<ul className='announcements'>
67+
<li>
68+
<Collapsable isVisible={this.state.showId === 'markdown'} fullHeight={1240} minHeight={20} >
69+
<div className='announcements__body'>
70+
<p>{ this.nl2br(intl.formatMessage(messages.markdown, { domain: document.title }))}<br />
71+
<br />
72+
(半角)は半角スペースを入力する必要がある場所です。(半角)だけの列は半角スペースのみが入力された列が必要であるを指します。<br /><br />
73+
〜〜〜〜〜〜見出し〜〜〜〜〜〜<br /><br />
74+
#(半角)見出しテキスト<br /><br />
75+
#は1〜6個重ねることができます。<br /><br />
76+
〜〜〜〜コードブロック〜〜〜〜<br /><br />
77+
`コード`<br /><br />
78+
〜〜〜〜〜〜引用〜〜〜〜〜〜<br /><br />
79+
>引用文<br />
80+
(半角)<br />
81+
ここから先は引用が切れます<br />
82+
引用は複数回重ねることが可能です。<br /><br />
83+
〜〜〜〜〜〜リスト〜〜〜〜〜〜<br /><br />
84+
(半角)<br />
85+
+(半角)内容1<br />
86+
+(半角)内容2<br />
87+
(半角)<br /><br />
88+
内容の数に制限はありません。<br />
89+
投稿トップにリストを持ってくる場合に限り1行目の(半角)は必要ありません。<br />
90+
+(半角)を1.(半角)に置き換えることで数字付きリストになります。<br /><br />
91+
〜〜〜〜〜上付き文字〜〜〜〜〜<br /><br />
92+
_上付き文字_<br /><br />
93+
〜〜〜〜〜下付き文字〜〜〜〜〜<br /><br />
94+
__下付き文字__<br /><br />
95+
〜〜〜〜〜小さい文字〜〜〜〜〜<br /><br />
96+
___小さい文字___<br /><br />
97+
〜〜〜〜〜取り消し線〜〜〜〜〜<br /><br />
98+
~~取り消したい文字列~~<br /><br />
99+
〜〜〜〜〜〜横罫線〜〜〜〜〜〜<br /><br />
100+
___<br /><br />
101+
〜〜〜〜〜〜リンク〜〜〜〜〜〜<br /><br />
102+
[リンク文章](https://・・・)<br /><br />
103+
〜〜〜〜〜〜画像〜〜〜〜〜〜<br /><br />
104+
![画像説明](https://・・・)<br /><br />
105+
リンク、画像ともにURLにはhttps://から始まる物のみご利用可能です。
106+
</p>
107+
</div>
108+
</Collapsable>
109+
<div className='announcements__icon'>
110+
<IconButton title={intl.formatMessage(messages.toggle_visible)} icon='caret-up' onClick={() => this.onClick('markdown', this.state)} size={20} animate active={this.state.showId === 'markdown'} />
111+
</div>
112+
</li>
113+
</ul>
114+
);
115+
}
116+
117+
componentWillReceiveProps (nextProps) {
118+
if (!this.state.isLoaded) {
119+
if (!nextProps.isLoading && (nextProps.homeSize === 0 || this.props.homeSize !== nextProps.homeSize)) {
120+
this.setState({ isLoaded: true });
121+
}
122+
}
123+
}
124+
125+
}
126+
127+
export default injectIntl(Announcements);

0 commit comments

Comments
 (0)