diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index c4cd48878..000000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,22 +0,0 @@ -# To get started with Dependabot version updates, you'll need to specify which -# package ecosystems to update and where the package manifests are located. -# Please see the documentation for all configuration options: -# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates - -version: 2 -updates: - - package-ecosystem: npm - directory: "/" - schedule: - interval: weekly - open-pull-requests-limit: 99 - allow: - - dependency-type: direct - - - package-ecosystem: bundler - directory: "/" - schedule: - interval: weekly - open-pull-requests-limit: 99 - allow: - - dependency-type: direct diff --git a/Gemfile b/Gemfile index 614aeb205..0c23d08d8 100644 --- a/Gemfile +++ b/Gemfile @@ -99,6 +99,8 @@ gem 'json-ld' gem 'json-ld-preloaded', '~> 3.1' gem 'rdf-normalize', '~> 0.4' +gem 'redcarpet', "~> 3.4.0" + group :development, :test do gem 'fabrication', '~> 2.22' gem 'fuubar', '~> 2.5' diff --git a/Gemfile.lock b/Gemfile.lock index 8cd4a97f1..378333036 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -486,6 +486,14 @@ GEM rdf-normalize (0.4.0) rdf (~> 3.1) redis (4.2.5) + redcarpet (3.4.0) + redis-actionpack (5.2.0) + actionpack (>= 5, < 7) + redis-rack (>= 2.1.0, < 3) + redis-store (>= 1.1.0, < 2) + redis-activesupport (5.2.0) + activesupport (>= 3, < 7) + redis-store (>= 1.3, < 2) redis-namespace (1.8.1) redis (>= 3.0.4) regexp_parser (2.1.1) @@ -762,6 +770,7 @@ DEPENDENCIES rails-i18n (~> 6.0) rails-settings-cached (~> 0.6) rdf-normalize (~> 0.4) + redcarpet (~> 3.4.0) redis (~> 4.2) redis-namespace (~> 1.8) resolv (~> 0.1.0) diff --git a/app/controllers/api/v2/media_controller.rb b/app/controllers/api/v2/media_controller.rb index 0c1baf01d..de2c72313 100644 --- a/app/controllers/api/v2/media_controller.rb +++ b/app/controllers/api/v2/media_controller.rb @@ -1,5 +1,8 @@ # frozen_string_literal: true +class Api::V2::MediaController < Api::V1::MediaController +end +__END__ class Api::V2::MediaController < Api::V1::MediaController def create @media_attachment = current_account.media_attachments.create!({ delay_processing: true }.merge(media_attachment_params)) diff --git a/app/javascript/fonts/MaterialIcons-Regular.ttf b/app/javascript/fonts/MaterialIcons-Regular.ttf new file mode 100644 index 000000000..e50801b3b Binary files /dev/null and b/app/javascript/fonts/MaterialIcons-Regular.ttf differ diff --git a/app/javascript/images/logo.svg b/app/javascript/images/logo.svg index 034a9c221..82a6025a7 100644 --- a/app/javascript/images/logo.svg +++ b/app/javascript/images/logo.svg @@ -1 +1,17 @@ - + + + + + + + diff --git a/app/javascript/images/logo_alt.svg b/app/javascript/images/logo_alt.svg index 102d4c787..4c04c93b8 100644 --- a/app/javascript/images/logo_alt.svg +++ b/app/javascript/images/logo_alt.svg @@ -1 +1,16 @@ - + + + + + + + diff --git a/app/javascript/mastodon/actions/UtilBtns.js b/app/javascript/mastodon/actions/UtilBtns.js new file mode 100644 index 000000000..52ccc6877 --- /dev/null +++ b/app/javascript/mastodon/actions/UtilBtns.js @@ -0,0 +1,71 @@ +import { changeCompose } from '../actions/compose'; + + + +export const UTILBTNS_GOJI = 'UTILBTNS_GOJI'; +export const UTILBTNS_HARUKIN = 'UTILBTNS_HARUKIN'; + + + +export function submitGoji (textarea) { + return function (dispatch, getState) { + if (!textarea.value) { + let text = [ + "#ゴジモリィィィィイイ", + ":goji:" + ].join("\r\n"); + + dispatch(submitGojiRequest()); + dispatch(changeCompose(text)); + + textarea.focus(); + } + } +} + +export function submitGojiRequest () { + return { + type: UTILBTNS_GOJI + } +} + +export function submitHarukin (textarea) { + return function (dispatch, getState) { + const HARUKINS = [":harukin: ", ":harukin_old: ", ":harukin_ika: ", ":harukin_tako: "]; + const MAX = 6; + + if (!textarea.value) { + let text = ""; + + let quantity = Math.round(Math.random() * MAX + 1); + let type = Math.round(Math.random() * (HARUKINS.length - 1)); + + let harukin = HARUKINS[type]; + + switch (quantity) { + default: + text = [ + harukin.repeat(quantity), + "🔥 ".repeat(quantity) + ].join("\r\n"); + + break; + + case MAX + 1: + text = `${harukin}💕\r\n`.repeat(6); + break; + } + + dispatch(submitHarukinRequest()); + dispatch(changeCompose(text)); + + textarea.focus(); + } + } +} + +export function submitHarukinRequest () { + return { + type: UTILBTNS_HARUKIN + } +} diff --git a/app/javascript/mastodon/components/announcement_icon_button.js b/app/javascript/mastodon/components/announcement_icon_button.js new file mode 100644 index 000000000..0de58c6f7 --- /dev/null +++ b/app/javascript/mastodon/components/announcement_icon_button.js @@ -0,0 +1,90 @@ +import React from 'react'; +import Motion from 'react-motion/lib/Motion'; +import spring from 'react-motion/lib/spring'; +import PropTypes from 'prop-types'; + +class IconButton extends React.PureComponent { + + static propTypes = { + className: PropTypes.string, + title: PropTypes.string.isRequired, + icon: PropTypes.string.isRequired, + onClick: PropTypes.func, + size: PropTypes.number, + active: PropTypes.bool, + style: PropTypes.object, + activeStyle: PropTypes.object, + disabled: PropTypes.bool, + inverted: PropTypes.bool, + animate: PropTypes.bool, + overlay: PropTypes.bool, + }; + + static defaultProps = { + size: 18, + active: false, + disabled: false, + animate: false, + overlay: false, + }; + + handleClick = (e) => { + e.preventDefault(); + + if (!this.props.disabled) { + this.props.onClick(e); + } + } + + render () { + const style = { + fontSize: `${this.props.size}px`, + width: `${this.props.size * 1.28571429}px`, + height: `${this.props.size * 1.28571429}px`, + lineHeight: `${this.props.size}px`, + ...this.props.style, + ...(this.props.active ? this.props.activeStyle : {}), + }; + + const classes = ['icon-button']; + + if (this.props.active) { + classes.push('active'); + } + + if (this.props.disabled) { + classes.push('disabled'); + } + + if (this.props.inverted) { + classes.push('inverted'); + } + + if (this.props.overlay) { + classes.push('overlayed'); + } + + if (this.props.className) { + classes.push(this.props.className); + } + + return ( + + {({ rotate }) => +