diff options
author | pluralcafe-docker <git@plural.cafe> | 2019-01-31 19:01:31 +0000 |
---|---|---|
committer | pluralcafe-docker <git@plural.cafe> | 2019-01-31 19:01:31 +0000 |
commit | 9e04595911a5565a38452061f7c573c4f8917766 (patch) | |
tree | 85bac2a16c9c2371679d43311d9d6b069c988e94 /app | |
parent | 50dc62ea3a36039463032aa2e712471859d9d9b6 (diff) | |
parent | 48d00ac0d9ad703fa3605337b0866c8ce6f21b28 (diff) |
Merge branch 'glitch'
Diffstat (limited to 'app')
19 files changed, 154 insertions, 19 deletions
diff --git a/app/controllers/settings/preferences_controller.rb b/app/controllers/settings/preferences_controller.rb index d4932afd6..241053261 100644 --- a/app/controllers/settings/preferences_controller.rb +++ b/app/controllers/settings/preferences_controller.rb @@ -45,6 +45,7 @@ class Settings::PreferencesController < Settings::BaseController :setting_hide_network, :setting_hide_followers_count, :setting_aggregate_reblogs, + :setting_show_application, notification_emails: %i(follow follow_request reblog favourite mention digest report), interactions: %i(must_be_follower must_be_following) ) diff --git a/app/javascript/flavours/glitch/features/direct_timeline/components/column_settings.js b/app/javascript/flavours/glitch/features/direct_timeline/components/column_settings.js index a992b27bb..5adb44f2c 100644 --- a/app/javascript/flavours/glitch/features/direct_timeline/components/column_settings.js +++ b/app/javascript/flavours/glitch/features/direct_timeline/components/column_settings.js @@ -26,7 +26,7 @@ export default class ColumnSettings extends React.PureComponent { <span className='column-settings__section'><FormattedMessage id='home.column_settings.advanced' defaultMessage='Advanced' /></span> <div className='column-settings__row'> - <SettingText settings={settings} settingKey={['regex', 'body']} onChange={onChange} label={intl.formatMessage(messages.filter_regex)} /> + <SettingText settings={settings} settingPath={['regex', 'body']} onChange={onChange} label={intl.formatMessage(messages.filter_regex)} /> </div> </div> ); diff --git a/app/javascript/flavours/glitch/features/video/index.js b/app/javascript/flavours/glitch/features/video/index.js index 30592707c..d8e8791a7 100644 --- a/app/javascript/flavours/glitch/features/video/index.js +++ b/app/javascript/flavours/glitch/features/video/index.js @@ -139,6 +139,9 @@ export default class Video extends React.PureComponent { setVideoRef = c => { this.video = c; + if (this.video) { + this.setState({ volume: this.video.volume, muted: this.video.muted }); + } } setSeekRef = c => { @@ -319,6 +322,10 @@ export default class Video extends React.PureComponent { } } + handleVolumeChange = () => { + this.setState({ volume: this.video.volume, muted: this.video.muted }); + } + handleOpenVideo = () => { const { src, preview, width, height, alt } = this.props; const media = fromJS({ @@ -407,6 +414,7 @@ export default class Video extends React.PureComponent { onTimeUpdate={this.handleTimeUpdate} onLoadedData={this.handleLoadedData} onProgress={this.handleProgress} + onVolumeChange={this.handleVolumeChange} /> <button type='button' className={classNames('video-player__spoiler', { active: !revealed })} onClick={this.toggleReveal}> @@ -429,7 +437,7 @@ export default class Video extends React.PureComponent { <div className='video-player__buttons-bar'> <div className='video-player__buttons left'> <button type='button' aria-label={intl.formatMessage(paused ? messages.play : messages.pause)} onClick={this.togglePlay}><i className={classNames('fa fa-fw', { 'fa-play': paused, 'fa-pause': !paused })} /></button> - <button type='button' aria-label={intl.formatMessage(muted ? messages.unmute : messages.mute)} onMouseEnter={this.volumeSlider} onMouseLeave={this.volumeSlider} onClick={this.toggleMute}><i className={classNames('fa fa-fw', { 'fa-volume-off': muted, 'fa-volume-up': !muted })} /></button> + <button type='button' aria-label={intl.formatMessage(muted ? messages.unmute : messages.mute)} onClick={this.toggleMute}><i className={classNames('fa fa-fw', { 'fa-volume-off': muted, 'fa-volume-up': !muted })} /></button> <div className='video-player__volume' onMouseDown={this.handleVolumeMouseDown} ref={this.setVolumeRef}> <div className='video-player__volume__current' style={{ width: `${volumeWidth}px` }} /> <span diff --git a/app/javascript/flavours/glitch/styles/about.scss b/app/javascript/flavours/glitch/styles/about.scss index e8f46766a..302de020b 100644 --- a/app/javascript/flavours/glitch/styles/about.scss +++ b/app/javascript/flavours/glitch/styles/about.scss @@ -847,6 +847,18 @@ $small-breakpoint: 960px; margin-bottom: 0; } + strong { + display: inline; + margin: 0; + padding: 0; + font-weight: 700; + background: transparent; + font-family: inherit; + font-size: inherit; + line-height: inherit; + color: lighten($darker-text-color, 10%); + } + .account { border-bottom: 0; padding: 0; diff --git a/app/javascript/flavours/glitch/styles/reset.scss b/app/javascript/flavours/glitch/styles/reset.scss index e24ba8c1c..f54ed5bc7 100644 --- a/app/javascript/flavours/glitch/styles/reset.scss +++ b/app/javascript/flavours/glitch/styles/reset.scss @@ -54,7 +54,7 @@ table { } html { - scrollbar-color: lighten($ui-base-color, 4%) transparent; + scrollbar-color: lighten($ui-base-color, 4%) rgba($base-overlay-background, 0.1); } ::-webkit-scrollbar { diff --git a/app/javascript/mastodon/features/notifications/components/notification.js b/app/javascript/mastodon/features/notifications/components/notification.js index 44da423ad..97efff69c 100644 --- a/app/javascript/mastodon/features/notifications/components/notification.js +++ b/app/javascript/mastodon/features/notifications/components/notification.js @@ -29,6 +29,10 @@ class Notification extends ImmutablePureComponent { onMoveUp: PropTypes.func.isRequired, onMoveDown: PropTypes.func.isRequired, onMention: PropTypes.func.isRequired, + onFavourite: PropTypes.func.isRequired, + onReblog: PropTypes.func.isRequired, + onToggleHidden: PropTypes.func.isRequired, + status: PropTypes.option, intl: PropTypes.object.isRequired, }; @@ -64,14 +68,32 @@ class Notification extends ImmutablePureComponent { onMention(notification.get('account'), this.context.router.history); } + handleHotkeyFavourite = () => { + const { status } = this.props; + if (status) this.props.onFavourite(status); + } + + handleHotkeyBoost = e => { + const { status } = this.props; + if (status) this.props.onReblog(status, e); + } + + handleHotkeyToggleHidden = () => { + const { status } = this.props; + if (status) this.props.onToggleHidden(status); + } + getHandlers () { return { - moveUp: this.handleMoveUp, - moveDown: this.handleMoveDown, + reply: this.handleMention, + favourite: this.handleHotkeyFavourite, + boost: this.handleHotkeyBoost, + mention: this.handleMention, open: this.handleOpen, openProfile: this.handleOpenProfile, - mention: this.handleMention, - reply: this.handleMention, + moveUp: this.handleMoveUp, + moveDown: this.handleMoveDown, + toggleHidden: this.handleHotkeyToggleHidden, }; } diff --git a/app/javascript/mastodon/features/notifications/containers/notification_container.js b/app/javascript/mastodon/features/notifications/containers/notification_container.js index 921aa460f..78576c760 100644 --- a/app/javascript/mastodon/features/notifications/containers/notification_container.js +++ b/app/javascript/mastodon/features/notifications/containers/notification_container.js @@ -1,14 +1,31 @@ import { connect } from 'react-redux'; -import { makeGetNotification } from '../../../selectors'; +import { makeGetNotification, makeGetStatus } from '../../../selectors'; import Notification from '../components/notification'; +import { openModal } from '../../../actions/modal'; import { mentionCompose } from '../../../actions/compose'; +import { + reblog, + favourite, + unreblog, + unfavourite, +} from '../../../actions/interactions'; +import { + hideStatus, + revealStatus, +} from '../../../actions/statuses'; +import { boostModal } from '../../../initial_state'; const makeMapStateToProps = () => { const getNotification = makeGetNotification(); + const getStatus = makeGetStatus(); - const mapStateToProps = (state, props) => ({ - notification: getNotification(state, props.notification, props.accountId), - }); + const mapStateToProps = (state, props) => { + const notification = getNotification(state, props.notification, props.accountId); + return { + notification: notification, + status: notification.get('status') ? getStatus(state, { id: notification.get('status') }) : null, + }; + }; return mapStateToProps; }; @@ -17,6 +34,38 @@ const mapDispatchToProps = dispatch => ({ onMention: (account, router) => { dispatch(mentionCompose(account, router)); }, + + onModalReblog (status) { + dispatch(reblog(status)); + }, + + onReblog (status, e) { + if (status.get('reblogged')) { + dispatch(unreblog(status)); + } else { + if (e.shiftKey || !boostModal) { + this.onModalReblog(status); + } else { + dispatch(openModal('BOOST', { status, onReblog: this.onModalReblog })); + } + } + }, + + onFavourite (status) { + if (status.get('favourited')) { + dispatch(unfavourite(status)); + } else { + dispatch(favourite(status)); + } + }, + + onToggleHidden (status) { + if (status.get('hidden')) { + dispatch(revealStatus(status.get('id'))); + } else { + dispatch(hideStatus(status.get('id'))); + } + }, }); export default connect(makeMapStateToProps, mapDispatchToProps)(Notification); diff --git a/app/javascript/mastodon/features/video/index.js b/app/javascript/mastodon/features/video/index.js index 3650fddb6..0d0c24d71 100644 --- a/app/javascript/mastodon/features/video/index.js +++ b/app/javascript/mastodon/features/video/index.js @@ -136,6 +136,9 @@ class Video extends React.PureComponent { setVideoRef = c => { this.video = c; + if (this.video) { + this.setState({ volume: this.video.volume, muted: this.video.muted }); + } } setSeekRef = c => { @@ -302,6 +305,10 @@ class Video extends React.PureComponent { } } + handleVolumeChange = () => { + this.setState({ volume: this.video.volume, muted: this.video.muted }); + } + handleOpenVideo = () => { const { src, preview, width, height, alt } = this.props; const media = fromJS({ @@ -387,6 +394,7 @@ class Video extends React.PureComponent { onTimeUpdate={this.handleTimeUpdate} onLoadedData={this.handleLoadedData} onProgress={this.handleProgress} + onVolumeChange={this.handleVolumeChange} /> <button type='button' className={classNames('video-player__spoiler', { active: !revealed })} onClick={this.toggleReveal}> @@ -409,7 +417,7 @@ class Video extends React.PureComponent { <div className='video-player__buttons-bar'> <div className='video-player__buttons left'> <button type='button' aria-label={intl.formatMessage(paused ? messages.play : messages.pause)} onClick={this.togglePlay}><i className={classNames('fa fa-fw', { 'fa-play': paused, 'fa-pause': !paused })} /></button> - <button type='button' aria-label={intl.formatMessage(muted ? messages.unmute : messages.mute)} onMouseEnter={this.volumeSlider} onMouseLeave={this.volumeSlider} onClick={this.toggleMute}><i className={classNames('fa fa-fw', { 'fa-volume-off': muted, 'fa-volume-up': !muted })} /></button> + <button type='button' aria-label={intl.formatMessage(muted ? messages.unmute : messages.mute)} onClick={this.toggleMute}><i className={classNames('fa fa-fw', { 'fa-volume-off': muted, 'fa-volume-up': !muted })} /></button> <div className='video-player__volume' onMouseDown={this.handleVolumeMouseDown} ref={this.setVolumeRef}> <div className='video-player__volume__current' style={{ width: `${volumeWidth}px` }} /> <span diff --git a/app/javascript/styles/mastodon/about.scss b/app/javascript/styles/mastodon/about.scss index c6f249fab..b6c92a09e 100644 --- a/app/javascript/styles/mastodon/about.scss +++ b/app/javascript/styles/mastodon/about.scss @@ -845,6 +845,18 @@ $small-breakpoint: 960px; margin-bottom: 0; } + strong { + display: inline; + margin: 0; + padding: 0; + font-weight: 700; + background: transparent; + font-family: inherit; + font-size: inherit; + line-height: inherit; + color: lighten($darker-text-color, 10%); + } + .account { border-bottom: 0; padding: 0; diff --git a/app/javascript/styles/mastodon/reset.scss b/app/javascript/styles/mastodon/reset.scss index e24ba8c1c..f54ed5bc7 100644 --- a/app/javascript/styles/mastodon/reset.scss +++ b/app/javascript/styles/mastodon/reset.scss @@ -54,7 +54,7 @@ table { } html { - scrollbar-color: lighten($ui-base-color, 4%) transparent; + scrollbar-color: lighten($ui-base-color, 4%) rgba($base-overlay-background, 0.1); } ::-webkit-scrollbar { diff --git a/app/lib/user_settings_decorator.rb b/app/lib/user_settings_decorator.rb index 569255f6e..367ba9a83 100644 --- a/app/lib/user_settings_decorator.rb +++ b/app/lib/user_settings_decorator.rb @@ -35,6 +35,7 @@ class UserSettingsDecorator user.settings['skin'] = skin_preference if change?('setting_skin') user.settings['hide_network'] = hide_network_preference if change?('setting_hide_network') user.settings['aggregate_reblogs'] = aggregate_reblogs_preference if change?('setting_aggregate_reblogs') + user.settings['show_application'] = show_application_preference if change?('setting_show_application') end def merged_notification_emails @@ -109,6 +110,10 @@ class UserSettingsDecorator boolean_cast_setting 'setting_hide_network' end + def show_application_preference + boolean_cast_setting 'setting_show_application' + end + def default_language_preference settings['setting_default_language'] end diff --git a/app/models/account.rb b/app/models/account.rb index 1ee63c738..c86c6fdb5 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -113,6 +113,7 @@ class Account < ApplicationRecord :staff?, :locale, :hides_network?, + :shows_application?, to: :user, prefix: true, allow_nil: true diff --git a/app/models/concerns/omniauthable.rb b/app/models/concerns/omniauthable.rb index f263fe7af..4dd2e9383 100644 --- a/app/models/concerns/omniauthable.rb +++ b/app/models/concerns/omniauthable.rb @@ -63,6 +63,7 @@ module Omniauthable { email: email || "#{TEMP_EMAIL_PREFIX}-#{auth.uid}-#{auth.provider}.com", password: Devise.friendly_token[0, 20], + agreement: true, account_attributes: { username: ensure_unique_username(auth.uid), display_name: display_name, diff --git a/app/models/user.rb b/app/models/user.rb index 0425c1772..ce9ef2a13 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -100,7 +100,7 @@ class User < ApplicationRecord delegate :auto_play_gif, :default_sensitive, :unfollow_modal, :boost_modal, :favourite_modal, :delete_modal, :reduce_motion, :system_font_ui, :noindex, :flavour, :skin, :display_media, :hide_network, :hide_followers_count, - :expand_spoilers, :default_language, :aggregate_reblogs, to: :settings, prefix: :setting, allow_nil: false + :expand_spoilers, :default_language, :aggregate_reblogs, :show_application, to: :settings, prefix: :setting, allow_nil: false attr_reader :invite_code @@ -244,6 +244,10 @@ class User < ApplicationRecord @aggregates_reblogs ||= settings.aggregate_reblogs end + def shows_application? + @shows_application ||= settings.shows_application + end + def token_for_app(a) return nil if a.nil? || a.owner != self Doorkeeper::AccessToken @@ -295,6 +299,7 @@ class User < ApplicationRecord def self.pam_get_user(attributes = {}) return nil unless attributes[:email] + resource = if Devise.check_at_sign && !attributes[:email].index('@') joins(:account).find_by(accounts: { username: attributes[:email] }) @@ -304,6 +309,7 @@ class User < ApplicationRecord if resource.blank? resource = new(email: attributes[:email], agreement: true) + if Devise.check_at_sign && !resource[:email].index('@') resource[:email] = Rpam2.getenv(resource.find_pam_service, attributes[:email], attributes[:password], 'email', false) resource[:email] = "#{attributes[:email]}@#{resource.find_pam_suffix}" unless resource[:email] diff --git a/app/serializers/rest/status_serializer.rb b/app/serializers/rest/status_serializer.rb index dd8482eea..b72eebb10 100644 --- a/app/serializers/rest/status_serializer.rb +++ b/app/serializers/rest/status_serializer.rb @@ -14,7 +14,7 @@ class REST::StatusSerializer < ActiveModel::Serializer attribute :local_only if :local? belongs_to :reblog, serializer: REST::StatusSerializer - belongs_to :application + belongs_to :application, if: :show_application? belongs_to :account, serializer: REST::AccountSerializer has_many :media_attachments, serializer: REST::MediaAttachmentSerializer @@ -40,6 +40,10 @@ class REST::StatusSerializer < ActiveModel::Serializer !current_user.nil? end + def show_application? + object.account.user_shows_application? || (current_user? && current_user.account_id == object.account_id) + end + def visibility # This visibility is masked behind "private" # to avoid API changes because there are no diff --git a/app/services/post_status_service.rb b/app/services/post_status_service.rb index 68cffe915..5d431c42a 100644 --- a/app/services/post_status_service.rb +++ b/app/services/post_status_service.rb @@ -69,7 +69,10 @@ class PostStatusService < BaseService end def schedule_status! - if @account.statuses.build(status_attributes).valid? + status_for_validation = @account.statuses.build(status_attributes) + if status_for_validation.valid? + status_for_validation.destroy + # The following transaction block is needed to wrap the UPDATEs to # the media attachments when the scheduled status is created @@ -95,7 +98,7 @@ class PostStatusService < BaseService raise Mastodon::ValidationError, I18n.t('media_attachments.validations.too_many') if @options[:media_ids].size > 4 - @media = MediaAttachment.where(status_id: nil).where(id: @options[:media_ids].take(4).map(&:to_i)) + @media = @account.media_attachments.where(status_id: nil).where(id: @options[:media_ids].take(4).map(&:to_i)) raise Mastodon::ValidationError, I18n.t('media_attachments.validations.images_and_video') if @media.size > 1 && @media.find(&:video?) end diff --git a/app/services/verify_link_service.rb b/app/services/verify_link_service.rb index c65578761..878a2188d 100644 --- a/app/services/verify_link_service.rb +++ b/app/services/verify_link_service.rb @@ -10,7 +10,7 @@ class VerifyLinkService < BaseService return unless link_back_present? field.mark_verified! - rescue HTTP::Error, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError => e + rescue OpenSSL::SSL::SSLError, HTTP::Error, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError => e Rails.logger.debug "Error fetching link #{@url}: #{e}" nil end diff --git a/app/views/settings/preferences/show.html.haml b/app/views/settings/preferences/show.html.haml index 6510e0560..c666bafb5 100644 --- a/app/views/settings/preferences/show.html.haml +++ b/app/views/settings/preferences/show.html.haml @@ -34,6 +34,9 @@ .fields-group = f.input :setting_hide_network, as: :boolean, wrapper: :with_label + .fields-group + = f.input :setting_show_application, as: :boolean, wrapper: :with_label + - unless Setting.hide_followers_count .fields-group = f.input :setting_hide_followers_count, as: :boolean, wrapper: :with_label diff --git a/app/views/stream_entries/_detailed_status.html.haml b/app/views/stream_entries/_detailed_status.html.haml index 18265e110..e123d657f 100644 --- a/app/views/stream_entries/_detailed_status.html.haml +++ b/app/views/stream_entries/_detailed_status.html.haml @@ -39,7 +39,7 @@ = link_to TagManager.instance.url_for(status), class: 'detailed-status__datetime u-url u-uid', target: stream_link_target, rel: 'noopener' do %time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at) · - - if status.application + - if status.application && @account.user&.setting_show_application - if status.application.website.blank? %strong.detailed-status__application= status.application.name - else |