diff --git a/app/assets/javascripts/components/components/button.jsx b/app/assets/javascripts/components/components/button.jsx
index 19c52550a..6790cc6cb 100644
--- a/app/assets/javascripts/components/components/button.jsx
+++ b/app/assets/javascripts/components/components/button.jsx
@@ -9,6 +9,7 @@ const Button = React.createClass({
block: React.PropTypes.bool,
secondary: React.PropTypes.bool,
size: React.PropTypes.number,
+ children: React.PropTypes.node
},
getDefaultProps () {
@@ -38,7 +39,6 @@ const Button = React.createClass({
fontSize: '14px',
fontWeight: '500',
letterSpacing: '0',
- textTransform: 'uppercase',
padding: `0 ${this.props.size / 2.25}px`,
height: `${this.props.size}px`,
cursor: 'pointer',
diff --git a/app/assets/javascripts/components/features/compose/components/compose_form.jsx b/app/assets/javascripts/components/features/compose/components/compose_form.jsx
index a8b03b3a6..48939054d 100644
--- a/app/assets/javascripts/components/features/compose/components/compose_form.jsx
+++ b/app/assets/javascripts/components/features/compose/components/compose_form.jsx
@@ -117,9 +117,10 @@ const ComposeForm = React.createClass({
},
render () {
- const { intl } = this.props;
- let replyArea = '';
- const disabled = this.props.is_submitting || this.props.is_uploading;
+ const { intl } = this.props;
+ let replyArea = '';
+ let publishText = '';
+ const disabled = this.props.is_submitting || this.props.is_uploading;
if (this.props.in_reply_to) {
replyArea = ;
@@ -127,6 +128,12 @@ const ComposeForm = React.createClass({
let reply_to_other = !!this.props.in_reply_to && (this.props.in_reply_to.getIn(['account', 'id']) !== this.props.me);
+ if (this.props.private) {
+ publishText = {intl.formatMessage(messages.publish)};
+ } else {
+ publishText = intl.formatMessage(messages.publish) + (!this.props.unlisted ? '!' : '');
+ }
+
return (
@@ -154,7 +161,7 @@ const ComposeForm = React.createClass({
/>
diff --git a/app/assets/javascripts/components/features/compose/containers/compose_form_container.jsx b/app/assets/javascripts/components/features/compose/containers/compose_form_container.jsx
index 8ccfce059..c027875cd 100644
--- a/app/assets/javascripts/components/features/compose/containers/compose_form_container.jsx
+++ b/app/assets/javascripts/components/features/compose/containers/compose_form_container.jsx
@@ -26,14 +26,14 @@ const makeMapStateToProps = () => {
sensitive: state.getIn(['compose', 'sensitive']),
spoiler: state.getIn(['compose', 'spoiler']),
spoiler_text: state.getIn(['compose', 'spoiler_text']),
- unlisted: state.getIn(['compose', 'unlisted']),
+ unlisted: state.getIn(['compose', 'unlisted'], ),
private: state.getIn(['compose', 'private']),
fileDropDate: state.getIn(['compose', 'fileDropDate']),
is_submitting: state.getIn(['compose', 'is_submitting']),
is_uploading: state.getIn(['compose', 'is_uploading']),
in_reply_to: getStatus(state, state.getIn(['compose', 'in_reply_to'])),
media_count: state.getIn(['compose', 'media_attachments']).size,
- me: state.getIn(['compose', 'me'])
+ me: state.getIn(['compose', 'me']),
};
};
diff --git a/app/assets/javascripts/components/features/getting_started/index.jsx b/app/assets/javascripts/components/features/getting_started/index.jsx
index 502b5c9d1..a0bf3a694 100644
--- a/app/assets/javascripts/components/features/getting_started/index.jsx
+++ b/app/assets/javascripts/components/features/getting_started/index.jsx
@@ -12,7 +12,8 @@ const messages = defineMessages({
follow_requests: { id: 'navigation_bar.follow_requests', defaultMessage: 'Follow requests' },
sign_out: { id: 'navigation_bar.logout', defaultMessage: 'Sign out' },
favourites: { id: 'navigation_bar.favourites', defaultMessage: 'Favourites' },
- blocks: { id: 'navigation_bar.blocks', defaultMessage: 'Blocked users' }
+ blocks: { id: 'navigation_bar.blocks', defaultMessage: 'Blocked users' },
+ info: { id: 'navigation_bar.info', defaultMessage: 'Extended information' }
});
const mapStateToProps = state => ({
@@ -34,6 +35,7 @@ const GettingStarted = ({ intl, me }) => {
{followRequests}
+
diff --git a/app/assets/javascripts/components/reducers/compose.jsx b/app/assets/javascripts/components/reducers/compose.jsx
index d3a84842f..1b903ed44 100644
--- a/app/assets/javascripts/components/reducers/compose.jsx
+++ b/app/assets/javascripts/components/reducers/compose.jsx
@@ -43,6 +43,7 @@ const initialState = Immutable.Map({
suggestion_token: null,
suggestions: Immutable.List(),
me: null,
+ default_privacy: 'public',
resetFileKey: Math.floor((Math.random() * 0x10000))
});
@@ -64,6 +65,8 @@ function clearAll(state) {
map.set('spoiler_text', '');
map.set('is_submitting', false);
map.set('in_reply_to', null);
+ map.set('unlisted', state.get('default_privacy') === 'unlisted');
+ map.set('private', state.get('default_privacy') === 'private');
map.update('media_attachments', list => list.clear());
});
};
@@ -97,7 +100,7 @@ const insertSuggestion = (state, position, token, completion) => {
export default function compose(state = initialState, action) {
switch(action.type) {
case STORE_HYDRATE:
- return state.merge(action.state.get('compose'));
+ return clearAll(state.merge(action.state.get('compose')));
case COMPOSE_MOUNT:
return state.set('mounted', true);
case COMPOSE_UNMOUNT:
diff --git a/app/assets/stylesheets/components.scss b/app/assets/stylesheets/components.scss
index 85d34c531..40c39678f 100644
--- a/app/assets/stylesheets/components.scss
+++ b/app/assets/stylesheets/components.scss
@@ -28,15 +28,7 @@
}
&.button-secondary {
- background-color: $color1;
-
- &:hover {
- background-color: $color1;
- }
-
- &:disabled {
- background-color: $color3;
- }
+ //
}
}
diff --git a/app/assets/stylesheets/variables.scss b/app/assets/stylesheets/variables.scss
index de4157af8..cdf81c818 100644
--- a/app/assets/stylesheets/variables.scss
+++ b/app/assets/stylesheets/variables.scss
@@ -2,7 +2,7 @@ $color1: #282c37; // darkest
$color2: #d9e1e8; // lightest
$color3: #9baec8; // lighter
$color4: #2b90d9; // vibrant
-$color5: #fff; // white
+$color5: #ffffff; // white
$color6: #df405a; // error red
$color7: #79bd9a; // succ green
-$color8: #000; // black
+$color8: #000000; // black
diff --git a/app/controllers/api/v1/timelines_controller.rb b/app/controllers/api/v1/timelines_controller.rb
index 854ca13e6..a8cc2b288 100644
--- a/app/controllers/api/v1/timelines_controller.rb
+++ b/app/controllers/api/v1/timelines_controller.rb
@@ -23,7 +23,7 @@ class Api::V1::TimelinesController < ApiController
end
def public
- @statuses = Status.as_public_timeline(current_account).paginate_by_max_id(limit_param(DEFAULT_STATUSES_LIMIT), params[:max_id], params[:since_id])
+ @statuses = Status.as_public_timeline(current_account, params[:local]).paginate_by_max_id(limit_param(DEFAULT_STATUSES_LIMIT), params[:max_id], params[:since_id])
@statuses = cache_collection(@statuses)
set_maps(@statuses)
@@ -40,7 +40,7 @@ class Api::V1::TimelinesController < ApiController
def tag
@tag = Tag.find_by(name: params[:id].downcase)
- @statuses = @tag.nil? ? [] : Status.as_tag_timeline(@tag, current_account).paginate_by_max_id(limit_param(DEFAULT_STATUSES_LIMIT), params[:max_id], params[:since_id])
+ @statuses = @tag.nil? ? [] : Status.as_tag_timeline(@tag, current_account, params[:local]).paginate_by_max_id(limit_param(DEFAULT_STATUSES_LIMIT), params[:max_id], params[:since_id])
@statuses = cache_collection(@statuses)
set_maps(@statuses)
diff --git a/app/controllers/settings/preferences_controller.rb b/app/controllers/settings/preferences_controller.rb
index 5ad825675..40888963e 100644
--- a/app/controllers/settings/preferences_controller.rb
+++ b/app/controllers/settings/preferences_controller.rb
@@ -21,7 +21,9 @@ class Settings::PreferencesController < ApplicationController
must_be_following: user_params[:interactions][:must_be_following] == '1',
}
- if current_user.update(user_params.except(:notification_emails, :interactions))
+ current_user.settings['default_privacy'] = user_params[:settings][:default_privacy]
+
+ if current_user.update(user_params.except(:notification_emails, :interactions, :settings))
redirect_to settings_preferences_path, notice: I18n.t('generic.changes_saved_msg')
else
render action: :show
@@ -31,6 +33,6 @@ class Settings::PreferencesController < ApplicationController
private
def user_params
- params.require(:user).permit(:locale, notification_emails: [:follow, :follow_request, :reblog, :favourite, :mention], interactions: [:must_be_follower, :must_be_following])
+ params.require(:user).permit(:locale, settings: [:default_privacy], notification_emails: [:follow, :follow_request, :reblog, :favourite, :mention], interactions: [:must_be_follower, :must_be_following])
end
end
diff --git a/app/models/status.rb b/app/models/status.rb
index ab68f4e69..142dec64e 100644
--- a/app/models/status.rb
+++ b/app/models/status.rb
@@ -102,21 +102,25 @@ class Status < ApplicationRecord
where(account: [account] + account.following)
end
- def as_public_timeline(account = nil)
+ def as_public_timeline(account = nil, local_only = false)
query = joins('LEFT OUTER JOIN accounts ON statuses.account_id = accounts.id')
.where(visibility: :public)
.where('(statuses.in_reply_to_id IS NULL OR statuses.in_reply_to_account_id = statuses.account_id)')
.where('statuses.reblog_of_id IS NULL')
+ query = query.where('accounts.domain IS NULL') if local_only
+
account.nil? ? filter_timeline_default(query) : filter_timeline_default(filter_timeline(query, account))
end
- def as_tag_timeline(tag, account = nil)
+ def as_tag_timeline(tag, account = nil, local_only = false)
query = tag.statuses
.joins('LEFT OUTER JOIN accounts ON statuses.account_id = accounts.id')
.where(visibility: :public)
.where('statuses.reblog_of_id IS NULL')
+ query = query.where('accounts.domain IS NULL') if local_only
+
account.nil? ? filter_timeline_default(query) : filter_timeline_default(filter_timeline(query, account))
end
diff --git a/app/models/user.rb b/app/models/user.rb
index b34144f2c..08aac2679 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -21,4 +21,8 @@ class User < ApplicationRecord
def send_devise_notification(notification, *args)
devise_mailer.send(notification, self, *args).deliver_later
end
+
+ def setting_default_privacy
+ settings.default_privacy || (account.locked? ? 'private' : 'public')
+ end
end
diff --git a/app/views/home/initial_state.json.rabl b/app/views/home/initial_state.json.rabl
index 0e9736f5f..71949ab0e 100644
--- a/app/views/home/initial_state.json.rabl
+++ b/app/views/home/initial_state.json.rabl
@@ -1,24 +1,24 @@
object false
-node(:meta) {
+node(:meta) do
{
access_token: @token,
locale: I18n.locale,
me: current_account.id,
}
-}
+end
-node(:compose) {
+node(:compose) do
{
me: current_account.id,
- private: current_account.locked?,
+ default_privacy: current_account.user.setting_default_privacy,
}
-}
+end
-node(:accounts) {
+node(:accounts) do
{
current_account.id => partial('api/v1/accounts/show', object: current_account),
}
-}
+end
node(:settings) { @web_settings }
diff --git a/app/views/settings/preferences/show.html.haml b/app/views/settings/preferences/show.html.haml
index 747977f9c..aee0540d2 100644
--- a/app/views/settings/preferences/show.html.haml
+++ b/app/views/settings/preferences/show.html.haml
@@ -7,6 +7,8 @@
.fields-group
= f.input :locale, collection: I18n.available_locales, wrapper: :with_label, include_blank: false, label_method: lambda { |locale| human_locale(locale) }
+ = f.input :setting_default_privacy, collection: Status.visibilities.keys, wrapper: :with_label, include_blank: false, label_method: lambda { |visibility| I18n.t("statuses.visibilities.#{visibility}") }, required: false
+
.fields-group
= f.simple_fields_for :notification_emails, hash_to_object(current_user.settings.notification_emails) do |ff|
= ff.input :follow, as: :boolean, wrapper: :with_label
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 16b406745..b1b1e7995 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -97,8 +97,12 @@ en:
settings: Settings
two_factor_auth: Two-factor Authentication
statuses:
- over_character_limit: character limit of %{max} exceeded
open_in_web: Open in web
+ over_character_limit: character limit of %{max} exceeded
+ visibilities:
+ private: Only show to followers
+ public: Public
+ unlisted: Public, but do not display on the public timeline
stream_entries:
click_to_show: Click to show
favourited: favourited a post by
diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml
index 09957c914..4d1758f82 100644
--- a/config/locales/simple_form.en.yml
+++ b/config/locales/simple_form.en.yml
@@ -23,6 +23,7 @@ en:
note: Bio
otp_attempt: Two-factor code
password: Password
+ setting_default_privacy: Post privacy
username: Username
interactions:
must_be_follower: Block notifications from non-followers