Compare commits
65 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
ab71cf4593 | ||
|
c450ddb613 | ||
|
15b886a6f0 | ||
|
4819e2913d | ||
|
72e662bb0d | ||
|
7d7844a47f | ||
|
f2cbfb2eb3 | ||
|
3f333a8d31 | ||
|
bc077018b8 | ||
|
90712d4293 | ||
|
6867681c7c | ||
|
bdc8b4fd91 | ||
|
2ff7146b6d | ||
|
c7908e2d09 | ||
|
c9d04f1c39 | ||
|
9e15eeec63 | ||
|
3c45d3963a | ||
|
baa8b82179 | ||
|
4b460bc571 | ||
|
7ca173be47 | ||
|
1ae5d49a71 | ||
|
a12572e074 | ||
|
dabc309ca3 | ||
|
1caf11ddcc | ||
|
95f018a3d4 | ||
|
a4caa7eb62 | ||
|
7c2d84910c | ||
|
b00cc4b9bd | ||
|
dd6ede554f | ||
|
6859d4c028 | ||
|
7d853b514a | ||
|
85c7c42098 | ||
|
8185f98872 | ||
|
5264496240 | ||
|
be75b13d68 | ||
|
9417c9bb8f | ||
|
11bddd31ce | ||
|
dd5cb5085c | ||
|
e7adbf572a | ||
|
13ffa3c59e | ||
|
aec5097d44 | ||
|
1646f622a5 | ||
|
e0cda4a851 | ||
|
d8d2a54741 | ||
|
fa21d004c7 | ||
|
6994664a13 | ||
|
be7ffa2d75 | ||
|
e821c00e74 | ||
|
9b994c4aee | ||
|
4c3dd0b254 | ||
|
672df4ecc0 | ||
|
aefb4719bc | ||
|
4d67bf18fe | ||
|
f09a250a7c | ||
|
9b50a9dd83 | ||
|
2293466edd | ||
|
b6f3869f8d | ||
|
09cffaaf04 | ||
|
334a633c2a | ||
|
8b12e3cc7f | ||
|
d3f46a77c3 | ||
|
a789315361 | ||
|
579c7a88e0 | ||
|
8538170c2d | ||
|
249bdc169c |
@@ -26,7 +26,7 @@ LOCAL_HTTPS=true
|
|||||||
# ALTERNATE_DOMAINS=example1.com,example2.com
|
# ALTERNATE_DOMAINS=example1.com,example2.com
|
||||||
|
|
||||||
# Application secrets
|
# Application secrets
|
||||||
# Generate each with the `rake secret` task (`docker-compose run --rm web rake secret` if you use docker compose)
|
# Generate each with the `RAILS_ENV=production bundle exec rake secret` task (`docker-compose run --rm web rake secret` if you use docker compose)
|
||||||
PAPERCLIP_SECRET=
|
PAPERCLIP_SECRET=
|
||||||
SECRET_KEY_BASE=
|
SECRET_KEY_BASE=
|
||||||
OTP_SECRET=
|
OTP_SECRET=
|
||||||
@@ -36,7 +36,7 @@ OTP_SECRET=
|
|||||||
# You should only generate this once per instance. If you later decide to change it, all push subscription will
|
# You should only generate this once per instance. If you later decide to change it, all push subscription will
|
||||||
# be invalidated, requiring the users to access the website again to resubscribe.
|
# be invalidated, requiring the users to access the website again to resubscribe.
|
||||||
#
|
#
|
||||||
# Generate with `rake mastodon:webpush:generate_vapid_key` task (`docker-compose run --rm web rake mastodon:webpush:generate_vapid_key` if you use docker compose)
|
# Generate with `RAILS_ENV=production bundle exec rake mastodon:webpush:generate_vapid_key` task (`docker-compose run --rm web rake mastodon:webpush:generate_vapid_key` if you use docker compose)
|
||||||
#
|
#
|
||||||
# For more information visit https://rossta.net/blog/using-the-web-push-api-with-vapid.html
|
# For more information visit https://rossta.net/blog/using-the-web-push-api-with-vapid.html
|
||||||
VAPID_PRIVATE_KEY=
|
VAPID_PRIVATE_KEY=
|
||||||
@@ -98,6 +98,15 @@ SMTP_FROM_ADDRESS=notifications@example.com
|
|||||||
# S3_ENDPOINT=
|
# S3_ENDPOINT=
|
||||||
# S3_SIGNATURE_VERSION=
|
# S3_SIGNATURE_VERSION=
|
||||||
|
|
||||||
|
# Swift (optional)
|
||||||
|
# SWIFT_ENABLED=true
|
||||||
|
# SWIFT_USERNAME=
|
||||||
|
# SWIFT_TENANT=
|
||||||
|
# SWIFT_PASSWORD=
|
||||||
|
# SWIFT_AUTH_URL=
|
||||||
|
# SWIFT_CONTAINER=
|
||||||
|
# SWIFT_OBJECT_URL=
|
||||||
|
|
||||||
# Optional alias for S3 if you want to use Cloudfront or Cloudflare in front
|
# Optional alias for S3 if you want to use Cloudfront or Cloudflare in front
|
||||||
# S3_CLOUDFRONT_HOST=
|
# S3_CLOUDFRONT_HOST=
|
||||||
|
|
||||||
|
2
Gemfile
2
Gemfile
@@ -15,6 +15,7 @@ gem 'pghero', '~> 1.7'
|
|||||||
gem 'dotenv-rails', '~> 2.2'
|
gem 'dotenv-rails', '~> 2.2'
|
||||||
|
|
||||||
gem 'aws-sdk', '~> 2.9'
|
gem 'aws-sdk', '~> 2.9'
|
||||||
|
gem 'fog-openstack', '~> 0.1'
|
||||||
gem 'paperclip', '~> 5.1'
|
gem 'paperclip', '~> 5.1'
|
||||||
gem 'paperclip-av-transcoder', '~> 0.6'
|
gem 'paperclip-av-transcoder', '~> 0.6'
|
||||||
|
|
||||||
@@ -23,6 +24,7 @@ gem 'addressable', '~> 2.5'
|
|||||||
gem 'bootsnap'
|
gem 'bootsnap'
|
||||||
gem 'browser'
|
gem 'browser'
|
||||||
gem 'charlock_holmes', '~> 0.7.5'
|
gem 'charlock_holmes', '~> 0.7.5'
|
||||||
|
gem 'iso-639'
|
||||||
gem 'cld3', '~> 3.1'
|
gem 'cld3', '~> 3.1'
|
||||||
gem 'devise', '~> 4.2'
|
gem 'devise', '~> 4.2'
|
||||||
gem 'devise-two-factor', '~> 3.0'
|
gem 'devise-two-factor', '~> 3.0'
|
||||||
|
17
Gemfile.lock
17
Gemfile.lock
@@ -154,12 +154,25 @@ GEM
|
|||||||
erubis (2.7.0)
|
erubis (2.7.0)
|
||||||
et-orbi (1.0.5)
|
et-orbi (1.0.5)
|
||||||
tzinfo
|
tzinfo
|
||||||
|
excon (0.58.0)
|
||||||
execjs (2.7.0)
|
execjs (2.7.0)
|
||||||
fabrication (2.16.2)
|
fabrication (2.16.2)
|
||||||
faker (1.7.3)
|
faker (1.7.3)
|
||||||
i18n (~> 0.5)
|
i18n (~> 0.5)
|
||||||
fast_blank (1.0.0)
|
fast_blank (1.0.0)
|
||||||
ffi (1.9.18)
|
ffi (1.9.18)
|
||||||
|
fog-core (1.45.0)
|
||||||
|
builder
|
||||||
|
excon (~> 0.58)
|
||||||
|
formatador (~> 0.2)
|
||||||
|
fog-json (1.0.2)
|
||||||
|
fog-core (~> 1.0)
|
||||||
|
multi_json (~> 1.10)
|
||||||
|
fog-openstack (0.1.21)
|
||||||
|
fog-core (>= 1.40)
|
||||||
|
fog-json (>= 1.0)
|
||||||
|
ipaddress (>= 0.8)
|
||||||
|
formatador (0.2.5)
|
||||||
fuubar (2.2.0)
|
fuubar (2.2.0)
|
||||||
rspec-core (~> 3.0)
|
rspec-core (~> 3.0)
|
||||||
ruby-progressbar (~> 1.4)
|
ruby-progressbar (~> 1.4)
|
||||||
@@ -211,6 +224,8 @@ GEM
|
|||||||
rainbow (~> 2.2)
|
rainbow (~> 2.2)
|
||||||
terminal-table (>= 1.5.1)
|
terminal-table (>= 1.5.1)
|
||||||
idn-ruby (0.1.0)
|
idn-ruby (0.1.0)
|
||||||
|
ipaddress (0.8.3)
|
||||||
|
iso-639 (0.2.8)
|
||||||
jmespath (1.3.1)
|
jmespath (1.3.1)
|
||||||
json (2.1.0)
|
json (2.1.0)
|
||||||
json-ld (2.1.5)
|
json-ld (2.1.5)
|
||||||
@@ -535,6 +550,7 @@ DEPENDENCIES
|
|||||||
fabrication (~> 2.16)
|
fabrication (~> 2.16)
|
||||||
faker (~> 1.7)
|
faker (~> 1.7)
|
||||||
fast_blank (~> 1.0)
|
fast_blank (~> 1.0)
|
||||||
|
fog-openstack (~> 0.1)
|
||||||
fuubar (~> 2.2)
|
fuubar (~> 2.2)
|
||||||
goldfinger (~> 2.0)
|
goldfinger (~> 2.0)
|
||||||
hamlit-rails (~> 0.2)
|
hamlit-rails (~> 0.2)
|
||||||
@@ -545,6 +561,7 @@ DEPENDENCIES
|
|||||||
httplog (~> 0.99)
|
httplog (~> 0.99)
|
||||||
i18n-tasks (~> 0.9)
|
i18n-tasks (~> 0.9)
|
||||||
idn-ruby
|
idn-ruby
|
||||||
|
iso-639
|
||||||
json-ld-preloaded (~> 2.2.1)
|
json-ld-preloaded (~> 2.2.1)
|
||||||
kaminari (~> 1.0)
|
kaminari (~> 1.0)
|
||||||
letter_opener (~> 1.4)
|
letter_opener (~> 1.4)
|
||||||
|
@@ -14,7 +14,7 @@ class AccountsController < ApplicationController
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@pinned_statuses = cache_collection(@account.pinned_statuses, Status) unless media_requested?
|
@pinned_statuses = cache_collection(@account.pinned_statuses, Status) if show_pinned_statuses?
|
||||||
@statuses = filtered_statuses.paginate_by_max_id(20, params[:max_id], params[:since_id])
|
@statuses = filtered_statuses.paginate_by_max_id(20, params[:max_id], params[:since_id])
|
||||||
@statuses = cache_collection(@statuses, Status)
|
@statuses = cache_collection(@statuses, Status)
|
||||||
@next_url = next_url unless @statuses.empty?
|
@next_url = next_url unless @statuses.empty?
|
||||||
@@ -22,7 +22,7 @@ class AccountsController < ApplicationController
|
|||||||
|
|
||||||
format.atom do
|
format.atom do
|
||||||
@entries = @account.stream_entries.where(hidden: false).with_includes.paginate_by_max_id(20, params[:max_id], params[:since_id])
|
@entries = @account.stream_entries.where(hidden: false).with_includes.paginate_by_max_id(20, params[:max_id], params[:since_id])
|
||||||
render xml: OStatus::AtomSerializer.render(OStatus::AtomSerializer.new.feed(@account, @entries.to_a))
|
render xml: OStatus::AtomSerializer.render(OStatus::AtomSerializer.new.feed(@account, @entries.reject { |entry| entry.status.nil? }))
|
||||||
end
|
end
|
||||||
|
|
||||||
format.json do
|
format.json do
|
||||||
@@ -33,6 +33,10 @@ class AccountsController < ApplicationController
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def show_pinned_statuses?
|
||||||
|
[replies_requested?, media_requested?, params[:max_id].present?, params[:since_id].present?].none?
|
||||||
|
end
|
||||||
|
|
||||||
def filtered_statuses
|
def filtered_statuses
|
||||||
default_statuses.tap do |statuses|
|
default_statuses.tap do |statuses|
|
||||||
statuses.merge!(only_media_scope) if media_requested?
|
statuses.merge!(only_media_scope) if media_requested?
|
||||||
|
@@ -13,6 +13,7 @@ module Admin
|
|||||||
closed_registrations_message
|
closed_registrations_message
|
||||||
open_deletion
|
open_deletion
|
||||||
timeline_preview
|
timeline_preview
|
||||||
|
bootstrap_timeline_accounts
|
||||||
).freeze
|
).freeze
|
||||||
|
|
||||||
BOOLEAN_SETTINGS = %w(
|
BOOLEAN_SETTINGS = %w(
|
||||||
|
@@ -14,6 +14,16 @@ class Api::V1::AccountsController < Api::BaseController
|
|||||||
|
|
||||||
def follow
|
def follow
|
||||||
FollowService.new.call(current_user.account, @account.acct)
|
FollowService.new.call(current_user.account, @account.acct)
|
||||||
|
|
||||||
|
unless @account.locked?
|
||||||
|
relationships = AccountRelationshipsPresenter.new(
|
||||||
|
[@account.id],
|
||||||
|
current_user.account_id,
|
||||||
|
following_map: { @account.id => true },
|
||||||
|
requested_map: { @account.id => false }
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
|
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@@ -10,6 +10,12 @@ class Api::V1::FollowsController < Api::BaseController
|
|||||||
raise ActiveRecord::RecordNotFound if follow_params[:uri].blank?
|
raise ActiveRecord::RecordNotFound if follow_params[:uri].blank?
|
||||||
|
|
||||||
@account = FollowService.new.call(current_user.account, target_uri).try(:target_account)
|
@account = FollowService.new.call(current_user.account, target_uri).try(:target_account)
|
||||||
|
|
||||||
|
if @account.nil?
|
||||||
|
username, domain = target_uri.split('@')
|
||||||
|
@account = Account.find_remote!(username, domain)
|
||||||
|
end
|
||||||
|
|
||||||
render json: @account, serializer: REST::AccountSerializer
|
render json: @account, serializer: REST::AccountSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@@ -2,4 +2,10 @@
|
|||||||
|
|
||||||
class Auth::ConfirmationsController < Devise::ConfirmationsController
|
class Auth::ConfirmationsController < Devise::ConfirmationsController
|
||||||
layout 'auth'
|
layout 'auth'
|
||||||
|
|
||||||
|
def show
|
||||||
|
super do |user|
|
||||||
|
BootstrapTimelineWorker.perform_async(user.account_id) if user.errors.empty?
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@@ -12,8 +12,14 @@ module RoutingHelper
|
|||||||
end
|
end
|
||||||
|
|
||||||
def full_asset_url(source, options = {})
|
def full_asset_url(source, options = {})
|
||||||
source = ActionController::Base.helpers.asset_url(source, options) unless Rails.configuration.x.use_s3
|
source = ActionController::Base.helpers.asset_url(source, options) unless use_storage?
|
||||||
|
|
||||||
URI.join(root_url, source).to_s
|
URI.join(root_url, source).to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def use_storage?
|
||||||
|
Rails.configuration.x.use_s3 || Rails.configuration.x.use_swift
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@@ -30,6 +30,7 @@ module SettingsHelper
|
|||||||
th: 'ภาษาไทย',
|
th: 'ภาษาไทย',
|
||||||
tr: 'Türkçe',
|
tr: 'Türkçe',
|
||||||
uk: 'Українська',
|
uk: 'Українська',
|
||||||
|
zh: '中文',
|
||||||
'zh-CN': '简体中文',
|
'zh-CN': '简体中文',
|
||||||
'zh-HK': '繁體中文(香港)',
|
'zh-HK': '繁體中文(香港)',
|
||||||
'zh-TW': '繁體中文(臺灣)',
|
'zh-TW': '繁體中文(臺灣)',
|
||||||
@@ -39,6 +40,10 @@ module SettingsHelper
|
|||||||
HUMAN_LOCALES[locale]
|
HUMAN_LOCALES[locale]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def filterable_languages
|
||||||
|
I18n.available_locales.map { |locale| locale.to_s.split('-').first.to_sym }.uniq
|
||||||
|
end
|
||||||
|
|
||||||
def hash_to_object(hash)
|
def hash_to_object(hash)
|
||||||
HashObject.new(hash)
|
HashObject.new(hash)
|
||||||
end
|
end
|
||||||
|
@@ -1,6 +1,11 @@
|
|||||||
import api from '../api';
|
import api from '../api';
|
||||||
|
|
||||||
import { updateTimeline } from './timelines';
|
import {
|
||||||
|
updateTimeline,
|
||||||
|
refreshHomeTimeline,
|
||||||
|
refreshCommunityTimeline,
|
||||||
|
refreshPublicTimeline,
|
||||||
|
} from './timelines';
|
||||||
|
|
||||||
export const COMPOSE_CHANGE = 'COMPOSE_CHANGE';
|
export const COMPOSE_CHANGE = 'COMPOSE_CHANGE';
|
||||||
export const COMPOSE_SUBMIT_REQUEST = 'COMPOSE_SUBMIT_REQUEST';
|
export const COMPOSE_SUBMIT_REQUEST = 'COMPOSE_SUBMIT_REQUEST';
|
||||||
@@ -95,16 +100,20 @@ export function submitCompose() {
|
|||||||
dispatch(submitComposeSuccess({ ...response.data }));
|
dispatch(submitComposeSuccess({ ...response.data }));
|
||||||
|
|
||||||
// To make the app more responsive, immediately get the status into the columns
|
// To make the app more responsive, immediately get the status into the columns
|
||||||
dispatch(updateTimeline('home', { ...response.data }));
|
|
||||||
|
const insertOrRefresh = (timelineId, refreshAction) => {
|
||||||
|
if (getState().getIn(['timelines', timelineId, 'online'])) {
|
||||||
|
dispatch(updateTimeline(timelineId, { ...response.data }));
|
||||||
|
} else if (getState().getIn(['timelines', timelineId, 'loaded'])) {
|
||||||
|
dispatch(refreshAction());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
insertOrRefresh('home', refreshHomeTimeline);
|
||||||
|
|
||||||
if (response.data.in_reply_to_id === null && response.data.visibility === 'public') {
|
if (response.data.in_reply_to_id === null && response.data.visibility === 'public') {
|
||||||
if (getState().getIn(['timelines', 'community', 'loaded'])) {
|
insertOrRefresh('community', refreshCommunityTimeline);
|
||||||
dispatch(updateTimeline('community', { ...response.data }));
|
insertOrRefresh('public', refreshPublicTimeline);
|
||||||
}
|
|
||||||
|
|
||||||
if (getState().getIn(['timelines', 'public', 'loaded'])) {
|
|
||||||
dispatch(updateTimeline('public', { ...response.data }));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}).catch(function (error) {
|
}).catch(function (error) {
|
||||||
dispatch(submitComposeFail(error));
|
dispatch(submitComposeFail(error));
|
||||||
|
39
app/javascript/mastodon/actions/pin_statuses.js
Normal file
39
app/javascript/mastodon/actions/pin_statuses.js
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import api from '../api';
|
||||||
|
|
||||||
|
export const PINNED_STATUSES_FETCH_REQUEST = 'PINNED_STATUSES_FETCH_REQUEST';
|
||||||
|
export const PINNED_STATUSES_FETCH_SUCCESS = 'PINNED_STATUSES_FETCH_SUCCESS';
|
||||||
|
export const PINNED_STATUSES_FETCH_FAIL = 'PINNED_STATUSES_FETCH_FAIL';
|
||||||
|
|
||||||
|
export function fetchPinnedStatuses() {
|
||||||
|
return (dispatch, getState) => {
|
||||||
|
dispatch(fetchPinnedStatusesRequest());
|
||||||
|
|
||||||
|
const accountId = getState().getIn(['meta', 'me']);
|
||||||
|
api(getState).get(`/api/v1/accounts/${accountId}/statuses`, { params: { pinned: true } }).then(response => {
|
||||||
|
dispatch(fetchPinnedStatusesSuccess(response.data, null));
|
||||||
|
}).catch(error => {
|
||||||
|
dispatch(fetchPinnedStatusesFail(error));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export function fetchPinnedStatusesRequest() {
|
||||||
|
return {
|
||||||
|
type: PINNED_STATUSES_FETCH_REQUEST,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export function fetchPinnedStatusesSuccess(statuses, next) {
|
||||||
|
return {
|
||||||
|
type: PINNED_STATUSES_FETCH_SUCCESS,
|
||||||
|
statuses,
|
||||||
|
next,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export function fetchPinnedStatusesFail(error) {
|
||||||
|
return {
|
||||||
|
type: PINNED_STATUSES_FETCH_FAIL,
|
||||||
|
error,
|
||||||
|
};
|
||||||
|
};
|
@@ -5,6 +5,7 @@ import IntersectionObserverArticle from './intersection_observer_article';
|
|||||||
import LoadMore from './load_more';
|
import LoadMore from './load_more';
|
||||||
import IntersectionObserverWrapper from '../features/ui/util/intersection_observer_wrapper';
|
import IntersectionObserverWrapper from '../features/ui/util/intersection_observer_wrapper';
|
||||||
import { throttle } from 'lodash';
|
import { throttle } from 'lodash';
|
||||||
|
import { List as ImmutableList } from 'immutable';
|
||||||
|
|
||||||
export default class ScrollableList extends PureComponent {
|
export default class ScrollableList extends PureComponent {
|
||||||
|
|
||||||
@@ -26,6 +27,10 @@ export default class ScrollableList extends PureComponent {
|
|||||||
trackScroll: true,
|
trackScroll: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
state = {
|
||||||
|
lastMouseMove: null,
|
||||||
|
};
|
||||||
|
|
||||||
intersectionObserverWrapper = new IntersectionObserverWrapper();
|
intersectionObserverWrapper = new IntersectionObserverWrapper();
|
||||||
|
|
||||||
handleScroll = throttle(() => {
|
handleScroll = throttle(() => {
|
||||||
@@ -46,6 +51,14 @@ export default class ScrollableList extends PureComponent {
|
|||||||
trailing: true,
|
trailing: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
handleMouseMove = throttle(() => {
|
||||||
|
this._lastMouseMove = new Date();
|
||||||
|
}, 300);
|
||||||
|
|
||||||
|
handleMouseLeave = () => {
|
||||||
|
this._lastMouseMove = null;
|
||||||
|
}
|
||||||
|
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
this.attachScrollListener();
|
this.attachScrollListener();
|
||||||
this.attachIntersectionObserver();
|
this.attachIntersectionObserver();
|
||||||
@@ -55,17 +68,20 @@ export default class ScrollableList extends PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate (prevProps) {
|
componentDidUpdate (prevProps) {
|
||||||
|
const someItemInserted = React.Children.count(prevProps.children) > 0 &&
|
||||||
|
React.Children.count(prevProps.children) < React.Children.count(this.props.children) &&
|
||||||
|
this.getFirstChildKey(prevProps) !== this.getFirstChildKey(this.props);
|
||||||
|
|
||||||
// Reset the scroll position when a new child comes in in order not to
|
// Reset the scroll position when a new child comes in in order not to
|
||||||
// jerk the scrollbar around if you're already scrolled down the page.
|
// jerk the scrollbar around if you're already scrolled down the page.
|
||||||
if (React.Children.count(prevProps.children) < React.Children.count(this.props.children) && this._oldScrollPosition && this.node.scrollTop > 0) {
|
if (someItemInserted && this._oldScrollPosition && this.node.scrollTop > 0) {
|
||||||
if (this.getFirstChildKey(prevProps) !== this.getFirstChildKey(this.props)) {
|
const newScrollTop = this.node.scrollHeight - this._oldScrollPosition;
|
||||||
const newScrollTop = this.node.scrollHeight - this._oldScrollPosition;
|
|
||||||
if (this.node.scrollTop !== newScrollTop) {
|
if (this.node.scrollTop !== newScrollTop) {
|
||||||
this.node.scrollTop = newScrollTop;
|
this.node.scrollTop = newScrollTop;
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this._oldScrollPosition = this.node.scrollHeight - this.node.scrollTop;
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
this._oldScrollPosition = this.node.scrollHeight - this.node.scrollTop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,7 +111,12 @@ export default class ScrollableList extends PureComponent {
|
|||||||
|
|
||||||
getFirstChildKey (props) {
|
getFirstChildKey (props) {
|
||||||
const { children } = props;
|
const { children } = props;
|
||||||
const firstChild = Array.isArray(children) ? children[0] : children;
|
let firstChild = children;
|
||||||
|
if (children instanceof ImmutableList) {
|
||||||
|
firstChild = children.get(0);
|
||||||
|
} else if (Array.isArray(children)) {
|
||||||
|
firstChild = children[0];
|
||||||
|
}
|
||||||
return firstChild && firstChild.key;
|
return firstChild && firstChild.key;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,6 +129,10 @@ export default class ScrollableList extends PureComponent {
|
|||||||
this.props.onScrollToBottom();
|
this.props.onScrollToBottom();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_recentlyMoved () {
|
||||||
|
return this._lastMouseMove !== null && ((new Date()) - this._lastMouseMove < 600);
|
||||||
|
}
|
||||||
|
|
||||||
handleKeyDown = (e) => {
|
handleKeyDown = (e) => {
|
||||||
if (['PageDown', 'PageUp'].includes(e.key) || (e.ctrlKey && ['End', 'Home'].includes(e.key))) {
|
if (['PageDown', 'PageUp'].includes(e.key) || (e.ctrlKey && ['End', 'Home'].includes(e.key))) {
|
||||||
const article = (() => {
|
const article = (() => {
|
||||||
@@ -143,7 +168,7 @@ export default class ScrollableList extends PureComponent {
|
|||||||
|
|
||||||
if (isLoading || childrenCount > 0 || !emptyMessage) {
|
if (isLoading || childrenCount > 0 || !emptyMessage) {
|
||||||
scrollableArea = (
|
scrollableArea = (
|
||||||
<div className='scrollable' ref={this.setRef}>
|
<div className='scrollable' ref={this.setRef} onMouseMove={this.handleMouseMove} onMouseLeave={this.handleMouseLeave}>
|
||||||
<div role='feed' className='item-list' onKeyDown={this.handleKeyDown}>
|
<div role='feed' className='item-list' onKeyDown={this.handleKeyDown}>
|
||||||
{prepend}
|
{prepend}
|
||||||
|
|
||||||
|
@@ -134,7 +134,7 @@ export default class StatusActionBar extends ImmutablePureComponent {
|
|||||||
|
|
||||||
menu.push(null);
|
menu.push(null);
|
||||||
|
|
||||||
if (withDismiss) {
|
if (status.getIn(['account', 'id']) === me || withDismiss) {
|
||||||
menu.push({ text: intl.formatMessage(mutingConversation ? messages.unmuteConversation : messages.muteConversation), action: this.handleConversationMuteClick });
|
menu.push({ text: intl.formatMessage(mutingConversation ? messages.unmuteConversation : messages.muteConversation), action: this.handleConversationMuteClick });
|
||||||
menu.push(null);
|
menu.push(null);
|
||||||
}
|
}
|
||||||
|
@@ -146,29 +146,29 @@ export default class VideoPlayer extends React.PureComponent {
|
|||||||
if (!this.state.visible) {
|
if (!this.state.visible) {
|
||||||
if (sensitive) {
|
if (sensitive) {
|
||||||
return (
|
return (
|
||||||
<div role='button' tabIndex='0' style={{ width: `${width}px`, height: `${height}px`, marginTop: '8px' }} className='media-spoiler' onClick={this.handleVisibility}>
|
<button style={{ width: `${width}px`, height: `${height}px`, marginTop: '8px' }} className='media-spoiler' onClick={this.handleVisibility}>
|
||||||
{spoilerButton}
|
{spoilerButton}
|
||||||
<span className='media-spoiler__warning'><FormattedMessage id='status.sensitive_warning' defaultMessage='Sensitive content' /></span>
|
<span className='media-spoiler__warning'><FormattedMessage id='status.sensitive_warning' defaultMessage='Sensitive content' /></span>
|
||||||
<span className='media-spoiler__trigger'><FormattedMessage id='status.sensitive_toggle' defaultMessage='Click to view' /></span>
|
<span className='media-spoiler__trigger'><FormattedMessage id='status.sensitive_toggle' defaultMessage='Click to view' /></span>
|
||||||
</div>
|
</button>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<div role='button' tabIndex='0' style={{ width: `${width}px`, height: `${height}px`, marginTop: '8px' }} className='media-spoiler' onClick={this.handleVisibility}>
|
<button style={{ width: `${width}px`, height: `${height}px`, marginTop: '8px' }} className='media-spoiler' onClick={this.handleVisibility}>
|
||||||
{spoilerButton}
|
{spoilerButton}
|
||||||
<span className='media-spoiler__warning'><FormattedMessage id='status.media_hidden' defaultMessage='Media hidden' /></span>
|
<span className='media-spoiler__warning'><FormattedMessage id='status.media_hidden' defaultMessage='Media hidden' /></span>
|
||||||
<span className='media-spoiler__trigger'><FormattedMessage id='status.sensitive_toggle' defaultMessage='Click to view' /></span>
|
<span className='media-spoiler__trigger'><FormattedMessage id='status.sensitive_toggle' defaultMessage='Click to view' /></span>
|
||||||
</div>
|
</button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.state.preview && !autoplay) {
|
if (this.state.preview && !autoplay) {
|
||||||
return (
|
return (
|
||||||
<div role='button' tabIndex='0' className='media-spoiler-video' style={{ width: `${width}px`, height: `${height}px`, backgroundImage: `url(${media.get('preview_url')})` }} onClick={this.handleOpen}>
|
<button className='media-spoiler-video' style={{ width: `${width}px`, height: `${height}px`, backgroundImage: `url(${media.get('preview_url')})` }} onClick={this.handleOpen}>
|
||||||
{spoilerButton}
|
{spoilerButton}
|
||||||
<div className='media-spoiler-video-play-icon'><i className='fa fa-play' /></div>
|
<div className='media-spoiler-video-play-icon'><i className='fa fa-play' /></div>
|
||||||
</div>
|
</button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -77,6 +77,7 @@ export default class Favourites extends ImmutablePureComponent {
|
|||||||
onClick={this.handleHeaderClick}
|
onClick={this.handleHeaderClick}
|
||||||
pinned={pinned}
|
pinned={pinned}
|
||||||
multiColumn={multiColumn}
|
multiColumn={multiColumn}
|
||||||
|
showBackButton
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<StatusList
|
<StatusList
|
||||||
|
@@ -23,6 +23,7 @@ const messages = defineMessages({
|
|||||||
blocks: { id: 'navigation_bar.blocks', defaultMessage: 'Blocked users' },
|
blocks: { id: 'navigation_bar.blocks', defaultMessage: 'Blocked users' },
|
||||||
mutes: { id: 'navigation_bar.mutes', defaultMessage: 'Muted users' },
|
mutes: { id: 'navigation_bar.mutes', defaultMessage: 'Muted users' },
|
||||||
info: { id: 'navigation_bar.info', defaultMessage: 'Extended information' },
|
info: { id: 'navigation_bar.info', defaultMessage: 'Extended information' },
|
||||||
|
pins: { id: 'navigation_bar.pins', defaultMessage: 'Pinned toots' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
@@ -66,15 +67,16 @@ export default class GettingStarted extends ImmutablePureComponent {
|
|||||||
|
|
||||||
navItems = navItems.concat([
|
navItems = navItems.concat([
|
||||||
<ColumnLink key='4' icon='star' text={intl.formatMessage(messages.favourites)} to='/favourites' />,
|
<ColumnLink key='4' icon='star' text={intl.formatMessage(messages.favourites)} to='/favourites' />,
|
||||||
|
<ColumnLink key='5' icon='thumb-tack' text={intl.formatMessage(messages.pins)} to='/pinned' />,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (me.get('locked')) {
|
if (me.get('locked')) {
|
||||||
navItems.push(<ColumnLink key='5' icon='users' text={intl.formatMessage(messages.follow_requests)} to='/follow_requests' />);
|
navItems.push(<ColumnLink key='6' icon='users' text={intl.formatMessage(messages.follow_requests)} to='/follow_requests' />);
|
||||||
}
|
}
|
||||||
|
|
||||||
navItems = navItems.concat([
|
navItems = navItems.concat([
|
||||||
<ColumnLink key='6' icon='volume-off' text={intl.formatMessage(messages.mutes)} to='/mutes' />,
|
<ColumnLink key='7' icon='volume-off' text={intl.formatMessage(messages.mutes)} to='/mutes' />,
|
||||||
<ColumnLink key='7' icon='ban' text={intl.formatMessage(messages.blocks)} to='/blocks' />,
|
<ColumnLink key='8' icon='ban' text={intl.formatMessage(messages.blocks)} to='/blocks' />,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@@ -106,6 +106,7 @@ export default class Notifications extends React.PureComponent {
|
|||||||
const scrollContainer = (
|
const scrollContainer = (
|
||||||
<ScrollableList
|
<ScrollableList
|
||||||
scrollKey={`notifications-${columnId}`}
|
scrollKey={`notifications-${columnId}`}
|
||||||
|
trackScroll={!pinned}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
hasMore={hasMore}
|
hasMore={hasMore}
|
||||||
emptyMessage={emptyMessage}
|
emptyMessage={emptyMessage}
|
||||||
|
59
app/javascript/mastodon/features/pinned_statuses/index.js
Normal file
59
app/javascript/mastodon/features/pinned_statuses/index.js
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
|
import { fetchPinnedStatuses } from '../../actions/pin_statuses';
|
||||||
|
import Column from '../ui/components/column';
|
||||||
|
import ColumnBackButtonSlim from '../../components/column_back_button_slim';
|
||||||
|
import StatusList from '../../components/status_list';
|
||||||
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
heading: { id: 'column.pins', defaultMessage: 'Pinned toot' },
|
||||||
|
});
|
||||||
|
|
||||||
|
const mapStateToProps = state => ({
|
||||||
|
statusIds: state.getIn(['status_lists', 'pins', 'items']),
|
||||||
|
hasMore: !!state.getIn(['status_lists', 'pins', 'next']),
|
||||||
|
});
|
||||||
|
|
||||||
|
@connect(mapStateToProps)
|
||||||
|
@injectIntl
|
||||||
|
export default class PinnedStatuses extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
dispatch: PropTypes.func.isRequired,
|
||||||
|
statusIds: ImmutablePropTypes.list.isRequired,
|
||||||
|
intl: PropTypes.object.isRequired,
|
||||||
|
hasMore: PropTypes.bool.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
componentWillMount () {
|
||||||
|
this.props.dispatch(fetchPinnedStatuses());
|
||||||
|
}
|
||||||
|
|
||||||
|
handleHeaderClick = () => {
|
||||||
|
this.column.scrollTop();
|
||||||
|
}
|
||||||
|
|
||||||
|
setRef = c => {
|
||||||
|
this.column = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { intl, statusIds, hasMore } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Column icon='thumb-tack' heading={intl.formatMessage(messages.heading)} ref={this.setRef}>
|
||||||
|
<ColumnBackButtonSlim />
|
||||||
|
<StatusList
|
||||||
|
statusIds={statusIds}
|
||||||
|
scrollKey='pinned_statuses'
|
||||||
|
hasMore={hasMore}
|
||||||
|
/>
|
||||||
|
</Column>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -9,6 +9,7 @@ import { links, getIndex, getLink } from './tabs_bar';
|
|||||||
|
|
||||||
import BundleContainer from '../containers/bundle_container';
|
import BundleContainer from '../containers/bundle_container';
|
||||||
import ColumnLoading from './column_loading';
|
import ColumnLoading from './column_loading';
|
||||||
|
import DrawerLoading from './drawer_loading';
|
||||||
import BundleColumnError from './bundle_column_error';
|
import BundleColumnError from './bundle_column_error';
|
||||||
import { Compose, Notifications, HomeTimeline, CommunityTimeline, PublicTimeline, HashtagTimeline, FavouritedStatuses } from '../../ui/util/async-components';
|
import { Compose, Notifications, HomeTimeline, CommunityTimeline, PublicTimeline, HashtagTimeline, FavouritedStatuses } from '../../ui/util/async-components';
|
||||||
|
|
||||||
@@ -129,8 +130,8 @@ export default class ColumnsArea extends ImmutablePureComponent {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderLoading = () => {
|
renderLoading = columnId => () => {
|
||||||
return <ColumnLoading />;
|
return columnId === 'COMPOSE' ? <DrawerLoading /> : <ColumnLoading />;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderError = (props) => {
|
renderError = (props) => {
|
||||||
@@ -158,7 +159,7 @@ export default class ColumnsArea extends ImmutablePureComponent {
|
|||||||
const params = column.get('params', null) === null ? null : column.get('params').toJS();
|
const params = column.get('params', null) === null ? null : column.get('params').toJS();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BundleContainer key={column.get('uuid')} fetchComponent={componentMap[column.get('id')]} loading={this.renderLoading} error={this.renderError}>
|
<BundleContainer key={column.get('uuid')} fetchComponent={componentMap[column.get('id')]} loading={this.renderLoading(column.get('id'))} error={this.renderError}>
|
||||||
{SpecificComponent => <SpecificComponent columnId={column.get('uuid')} params={params} multiColumn />}
|
{SpecificComponent => <SpecificComponent columnId={column.get('uuid')} params={params} multiColumn />}
|
||||||
</BundleContainer>
|
</BundleContainer>
|
||||||
);
|
);
|
||||||
|
@@ -0,0 +1,11 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
const DrawerLoading = () => (
|
||||||
|
<div className='drawer'>
|
||||||
|
<div className='drawer__pager'>
|
||||||
|
<div className='drawer__inner' />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default DrawerLoading;
|
@@ -33,7 +33,8 @@ export default class EmbedModal extends ImmutablePureComponent {
|
|||||||
iframeDocument.close();
|
iframeDocument.close();
|
||||||
|
|
||||||
iframeDocument.body.style.margin = 0;
|
iframeDocument.body.style.margin = 0;
|
||||||
this.iframe.height = iframeDocument.body.scrollHeight + 'px';
|
this.iframe.width = iframeDocument.body.scrollWidth;
|
||||||
|
this.iframe.height = iframeDocument.body.scrollHeight;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,7 +72,6 @@ export default class EmbedModal extends ImmutablePureComponent {
|
|||||||
|
|
||||||
<iframe
|
<iframe
|
||||||
className='embed-modal__iframe'
|
className='embed-modal__iframe'
|
||||||
scrolling='no'
|
|
||||||
frameBorder='0'
|
frameBorder='0'
|
||||||
ref={this.setIframeRef}
|
ref={this.setIframeRef}
|
||||||
title='preview'
|
title='preview'
|
||||||
|
@@ -5,23 +5,23 @@ import spring from 'react-motion/lib/spring';
|
|||||||
import BundleContainer from '../containers/bundle_container';
|
import BundleContainer from '../containers/bundle_container';
|
||||||
import BundleModalError from './bundle_modal_error';
|
import BundleModalError from './bundle_modal_error';
|
||||||
import ModalLoading from './modal_loading';
|
import ModalLoading from './modal_loading';
|
||||||
import ActionsModal from '../components/actions_modal';
|
import ActionsModal from './actions_modal';
|
||||||
|
import MediaModal from './media_modal';
|
||||||
|
import VideoModal from './video_modal';
|
||||||
|
import BoostModal from './boost_modal';
|
||||||
|
import ConfirmationModal from './confirmation_modal';
|
||||||
import {
|
import {
|
||||||
MediaModal,
|
|
||||||
OnboardingModal,
|
OnboardingModal,
|
||||||
VideoModal,
|
|
||||||
BoostModal,
|
|
||||||
ConfirmationModal,
|
|
||||||
ReportModal,
|
ReportModal,
|
||||||
EmbedModal,
|
EmbedModal,
|
||||||
} from '../../../features/ui/util/async-components';
|
} from '../../../features/ui/util/async-components';
|
||||||
|
|
||||||
const MODAL_COMPONENTS = {
|
const MODAL_COMPONENTS = {
|
||||||
'MEDIA': MediaModal,
|
'MEDIA': () => Promise.resolve({ default: MediaModal }),
|
||||||
'ONBOARDING': OnboardingModal,
|
'ONBOARDING': OnboardingModal,
|
||||||
'VIDEO': VideoModal,
|
'VIDEO': () => Promise.resolve({ default: VideoModal }),
|
||||||
'BOOST': BoostModal,
|
'BOOST': () => Promise.resolve({ default: BoostModal }),
|
||||||
'CONFIRM': ConfirmationModal,
|
'CONFIRM': () => Promise.resolve({ default: ConfirmationModal }),
|
||||||
'REPORT': ReportModal,
|
'REPORT': ReportModal,
|
||||||
'ACTIONS': () => Promise.resolve({ default: ActionsModal }),
|
'ACTIONS': () => Promise.resolve({ default: ActionsModal }),
|
||||||
'EMBED': EmbedModal,
|
'EMBED': EmbedModal,
|
||||||
@@ -82,8 +82,8 @@ export default class ModalRoot extends React.PureComponent {
|
|||||||
return { opacity: spring(0), scale: spring(0.98) };
|
return { opacity: spring(0), scale: spring(0.98) };
|
||||||
}
|
}
|
||||||
|
|
||||||
renderLoading = () => {
|
renderLoading = modalId => () => {
|
||||||
return <ModalLoading />;
|
return ['MEDIA', 'VIDEO', 'BOOST', 'CONFIRM', 'ACTIONS'].indexOf(modalId) === -1 ? <ModalLoading /> : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderError = (props) => {
|
renderError = (props) => {
|
||||||
@@ -117,7 +117,7 @@ export default class ModalRoot extends React.PureComponent {
|
|||||||
<div key={key} style={{ pointerEvents: visible ? 'auto' : 'none' }}>
|
<div key={key} style={{ pointerEvents: visible ? 'auto' : 'none' }}>
|
||||||
<div role='presentation' className='modal-root__overlay' style={{ opacity: style.opacity }} onClick={onClose} />
|
<div role='presentation' className='modal-root__overlay' style={{ opacity: style.opacity }} onClick={onClose} />
|
||||||
<div role='dialog' className='modal-root__container' style={{ opacity: style.opacity, transform: `translateZ(0px) scale(${style.scale})` }}>
|
<div role='dialog' className='modal-root__container' style={{ opacity: style.opacity, transform: `translateZ(0px) scale(${style.scale})` }}>
|
||||||
<BundleContainer fetchComponent={MODAL_COMPONENTS[type]} loading={this.renderLoading} error={this.renderError} renderDelay={200}>
|
<BundleContainer fetchComponent={MODAL_COMPONENTS[type]} loading={this.renderLoading(type)} error={this.renderError} renderDelay={200}>
|
||||||
{(SpecificComponent) => <SpecificComponent {...props} onClose={onClose} />}
|
{(SpecificComponent) => <SpecificComponent {...props} onClose={onClose} />}
|
||||||
</BundleContainer>
|
</BundleContainer>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -35,6 +35,7 @@ import {
|
|||||||
FavouritedStatuses,
|
FavouritedStatuses,
|
||||||
Blocks,
|
Blocks,
|
||||||
Mutes,
|
Mutes,
|
||||||
|
PinnedStatuses,
|
||||||
} from './util/async-components';
|
} from './util/async-components';
|
||||||
|
|
||||||
// Dummy import, to make sure that <Status /> ends up in the application bundle.
|
// Dummy import, to make sure that <Status /> ends up in the application bundle.
|
||||||
@@ -208,6 +209,7 @@ export default class UI extends React.PureComponent {
|
|||||||
|
|
||||||
<WrappedRoute path='/notifications' component={Notifications} content={children} />
|
<WrappedRoute path='/notifications' component={Notifications} content={children} />
|
||||||
<WrappedRoute path='/favourites' component={FavouritedStatuses} content={children} />
|
<WrappedRoute path='/favourites' component={FavouritedStatuses} content={children} />
|
||||||
|
<WrappedRoute path='/pinned' component={PinnedStatuses} content={children} />
|
||||||
|
|
||||||
<WrappedRoute path='/statuses/new' component={Compose} content={children} />
|
<WrappedRoute path='/statuses/new' component={Compose} content={children} />
|
||||||
<WrappedRoute path='/statuses/:statusId' exact component={Status} content={children} />
|
<WrappedRoute path='/statuses/:statusId' exact component={Status} content={children} />
|
||||||
|
@@ -34,6 +34,10 @@ export function GettingStarted () {
|
|||||||
return import(/* webpackChunkName: "features/getting_started" */'../../getting_started');
|
return import(/* webpackChunkName: "features/getting_started" */'../../getting_started');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function PinnedStatuses () {
|
||||||
|
return import(/* webpackChunkName: "features/pinned_statuses" */'../../pinned_statuses');
|
||||||
|
}
|
||||||
|
|
||||||
export function AccountTimeline () {
|
export function AccountTimeline () {
|
||||||
return import(/* webpackChunkName: "features/account_timeline" */'../../account_timeline');
|
return import(/* webpackChunkName: "features/account_timeline" */'../../account_timeline');
|
||||||
}
|
}
|
||||||
@@ -78,26 +82,10 @@ export function Mutes () {
|
|||||||
return import(/* webpackChunkName: "features/mutes" */'../../mutes');
|
return import(/* webpackChunkName: "features/mutes" */'../../mutes');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function MediaModal () {
|
|
||||||
return import(/* webpackChunkName: "modals/media_modal" */'../components/media_modal');
|
|
||||||
}
|
|
||||||
|
|
||||||
export function OnboardingModal () {
|
export function OnboardingModal () {
|
||||||
return import(/* webpackChunkName: "modals/onboarding_modal" */'../components/onboarding_modal');
|
return import(/* webpackChunkName: "modals/onboarding_modal" */'../components/onboarding_modal');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function VideoModal () {
|
|
||||||
return import(/* webpackChunkName: "modals/video_modal" */'../components/video_modal');
|
|
||||||
}
|
|
||||||
|
|
||||||
export function BoostModal () {
|
|
||||||
return import(/* webpackChunkName: "modals/boost_modal" */'../components/boost_modal');
|
|
||||||
}
|
|
||||||
|
|
||||||
export function ConfirmationModal () {
|
|
||||||
return import(/* webpackChunkName: "modals/confirmation_modal" */'../components/confirmation_modal');
|
|
||||||
}
|
|
||||||
|
|
||||||
export function ReportModal () {
|
export function ReportModal () {
|
||||||
return import(/* webpackChunkName: "modals/report_modal" */'../components/report_modal');
|
return import(/* webpackChunkName: "modals/report_modal" */'../components/report_modal');
|
||||||
}
|
}
|
||||||
|
@@ -26,12 +26,12 @@
|
|||||||
"bundle_modal_error.close": "Schließen",
|
"bundle_modal_error.close": "Schließen",
|
||||||
"bundle_modal_error.message": "Etwas ist beim Laden schiefgelaufen.",
|
"bundle_modal_error.message": "Etwas ist beim Laden schiefgelaufen.",
|
||||||
"bundle_modal_error.retry": "Erneut versuchen",
|
"bundle_modal_error.retry": "Erneut versuchen",
|
||||||
"column.blocks": "Blockierte Benutzer",
|
"column.blocks": "Blockierte Profile",
|
||||||
"column.community": "Lokale Zeitleiste",
|
"column.community": "Lokale Zeitleiste",
|
||||||
"column.favourites": "Favoriten",
|
"column.favourites": "Favoriten",
|
||||||
"column.follow_requests": "Folgeanfragen",
|
"column.follow_requests": "Folgeanfragen",
|
||||||
"column.home": "Startseite",
|
"column.home": "Startseite",
|
||||||
"column.mutes": "Stummgeschaltete Benutzer",
|
"column.mutes": "Stummgeschaltete Profile",
|
||||||
"column.notifications": "Mitteilungen",
|
"column.notifications": "Mitteilungen",
|
||||||
"column.public": "Gesamtes bekanntes Netz",
|
"column.public": "Gesamtes bekanntes Netz",
|
||||||
"column_back_button.label": "Zurück",
|
"column_back_button.label": "Zurück",
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
"compose_form.lock_disclaimer": "Dein Profil ist nicht {locked}. Jeder kann dir jederzeit folgen, um deine privaten Beiträge einzusehen.",
|
"compose_form.lock_disclaimer": "Dein Profil ist nicht {locked}. Jeder kann dir jederzeit folgen, um deine privaten Beiträge einzusehen.",
|
||||||
"compose_form.lock_disclaimer.lock": "gesperrt",
|
"compose_form.lock_disclaimer.lock": "gesperrt",
|
||||||
"compose_form.placeholder": "Worüber möchtest du schreiben?",
|
"compose_form.placeholder": "Worüber möchtest du schreiben?",
|
||||||
"compose_form.privacy_disclaimer": "Dein privater Status wird an die genannten Benutzer auf den Domains {domains} zugestellt. Vertraust du {domainsCount, plural, one {diesem Server} other {diesen Servern}}? Private Beiträge funktionieren nur auf Mastodon-Instanzen. Wenn {domains} {domainsCount, plural, one {keine Mastodon-Instanz ist} other {keine Mastodon-Instanzen sind}}, wird es dort kein Anzeichen geben, dass dein Beitrag privat ist und er könnte geteilt oder anderweitig für unerwünschte Empfänger sichtbar gemacht werden.",
|
"compose_form.privacy_disclaimer": "Dein privater Status wird an die genannten Profile auf den Domains {domains} zugestellt. Vertraust du {domainsCount, plural, one {diesem Server} other {diesen Servern}}? Private Beiträge funktionieren nur auf Mastodon-Instanzen. Wenn {domains} {domainsCount, plural, one {keine Mastodon-Instanz ist} other {keine Mastodon-Instanzen sind}}, wird es dort kein Anzeichen geben, dass dein Beitrag privat ist und er könnte geteilt oder anderweitig für unerwünschte Empfänger sichtbar gemacht werden.",
|
||||||
"compose_form.publish": "Tröt",
|
"compose_form.publish": "Tröt",
|
||||||
"compose_form.publish_loud": "{publish}!",
|
"compose_form.publish_loud": "{publish}!",
|
||||||
"compose_form.sensitive": "Medien als heikel markieren",
|
"compose_form.sensitive": "Medien als heikel markieren",
|
||||||
@@ -77,18 +77,18 @@
|
|||||||
"emoji_button.travel": "Reise und Orte",
|
"emoji_button.travel": "Reise und Orte",
|
||||||
"empty_column.community": "Die lokale Zeitleiste ist leer. Schreibe etwas öffentlich, um den Ball ins Rollen zu bringen!",
|
"empty_column.community": "Die lokale Zeitleiste ist leer. Schreibe etwas öffentlich, um den Ball ins Rollen zu bringen!",
|
||||||
"empty_column.hashtag": "Es gibt noch nichts unter diesem Hashtag.",
|
"empty_column.hashtag": "Es gibt noch nichts unter diesem Hashtag.",
|
||||||
"empty_column.home": "Du folgst noch niemandem. Besuche {public} oder benutze die Suche, um zu starten oder andere Benutzer anzutreffen.",
|
"empty_column.home": "Du folgst noch niemandem. Besuche {public} oder benutze die Suche, um zu starten oder andere Profile zu finden.",
|
||||||
"empty_column.home.inactivity": "Deine Zeitleiste ist leer. Falls du eine längere Zeit inaktiv gewesen bist, wird sie für dich so schnell wie möglich wiedererstellt.",
|
"empty_column.home.inactivity": "Deine Zeitleiste ist leer. Falls du eine längere Zeit inaktiv gewesen bist, wird sie für dich so schnell wie möglich wiedererstellt.",
|
||||||
"empty_column.home.public_timeline": "die öffentliche Zeitleiste",
|
"empty_column.home.public_timeline": "die öffentliche Zeitleiste",
|
||||||
"empty_column.notifications": "Du hast noch keine Mitteilungen. Interagiere mit anderen, um die Konversation zu starten.",
|
"empty_column.notifications": "Du hast noch keine Mitteilungen. Interagiere mit anderen, um die Konversation zu starten.",
|
||||||
"empty_column.public": "Hier ist nichts zu sehen! Schreibe etwas öffentlich oder folge Benutzern von anderen Instanzen, um es aufzufüllen.",
|
"empty_column.public": "Hier ist nichts zu sehen! Schreibe etwas öffentlich oder folge Profilen von anderen Instanzen, um es aufzufüllen.",
|
||||||
"follow_request.authorize": "Erlauben",
|
"follow_request.authorize": "Erlauben",
|
||||||
"follow_request.reject": "Ablehnen",
|
"follow_request.reject": "Ablehnen",
|
||||||
"getting_started.appsshort": "Anwendungen",
|
"getting_started.appsshort": "Anwendungen",
|
||||||
"getting_started.faq": "Häufig gestellte Fragen",
|
"getting_started.faq": "Häufig gestellte Fragen",
|
||||||
"getting_started.heading": "Erste Schritte",
|
"getting_started.heading": "Erste Schritte",
|
||||||
"getting_started.open_source_notice": "Mastodon ist quelloffene Software. Du kannst auf {github} dazu beitragen oder Probleme melden.",
|
"getting_started.open_source_notice": "Mastodon ist quelloffene Software. Du kannst auf {github} dazu beitragen oder Probleme melden.",
|
||||||
"getting_started.userguide": "Nutzeranleitung",
|
"getting_started.userguide": "Bedienungsanleitung",
|
||||||
"home.column_settings.advanced": "Fortgeschritten",
|
"home.column_settings.advanced": "Fortgeschritten",
|
||||||
"home.column_settings.basic": "Einfach",
|
"home.column_settings.basic": "Einfach",
|
||||||
"home.column_settings.filter_regex": "Filter durch reguläre Ausdrücke",
|
"home.column_settings.filter_regex": "Filter durch reguläre Ausdrücke",
|
||||||
@@ -101,14 +101,14 @@
|
|||||||
"loading_indicator.label": "Lade…",
|
"loading_indicator.label": "Lade…",
|
||||||
"media_gallery.toggle_visible": "Sichtbarkeit einstellen",
|
"media_gallery.toggle_visible": "Sichtbarkeit einstellen",
|
||||||
"missing_indicator.label": "Nicht gefunden",
|
"missing_indicator.label": "Nicht gefunden",
|
||||||
"navigation_bar.blocks": "Blockierte Benutzer",
|
"navigation_bar.blocks": "Blockierte Profile",
|
||||||
"navigation_bar.community_timeline": "Lokale Zeitleiste",
|
"navigation_bar.community_timeline": "Lokale Zeitleiste",
|
||||||
"navigation_bar.edit_profile": "Profil bearbeiten",
|
"navigation_bar.edit_profile": "Profil bearbeiten",
|
||||||
"navigation_bar.favourites": "Favoriten",
|
"navigation_bar.favourites": "Favoriten",
|
||||||
"navigation_bar.follow_requests": "Folgeanfragen",
|
"navigation_bar.follow_requests": "Folgeanfragen",
|
||||||
"navigation_bar.info": "Erweiterte Informationen",
|
"navigation_bar.info": "Erweiterte Informationen",
|
||||||
"navigation_bar.logout": "Abmelden",
|
"navigation_bar.logout": "Abmelden",
|
||||||
"navigation_bar.mutes": "Stummgeschaltete Benutzer",
|
"navigation_bar.mutes": "Stummgeschaltete Profile",
|
||||||
"navigation_bar.preferences": "Einstellungen",
|
"navigation_bar.preferences": "Einstellungen",
|
||||||
"navigation_bar.public_timeline": "Föderierte Zeitleiste",
|
"navigation_bar.public_timeline": "Föderierte Zeitleiste",
|
||||||
"notification.favourite": "{name} favorisierte deinen Status",
|
"notification.favourite": "{name} favorisierte deinen Status",
|
||||||
@@ -132,7 +132,7 @@
|
|||||||
"onboarding.page_four.home": "Die Startseite zeigt dir Beiträge von Leuten, denen du folgst.",
|
"onboarding.page_four.home": "Die Startseite zeigt dir Beiträge von Leuten, denen du folgst.",
|
||||||
"onboarding.page_four.notifications": "Wenn jemand mir dir interagiert, bekommst du eine Mitteilung.",
|
"onboarding.page_four.notifications": "Wenn jemand mir dir interagiert, bekommst du eine Mitteilung.",
|
||||||
"onboarding.page_one.federation": "Mastodon ist ein soziales Netzwerk, das aus unabhängigen Servern besteht. Diese Server nennen wir auch Instanzen.",
|
"onboarding.page_one.federation": "Mastodon ist ein soziales Netzwerk, das aus unabhängigen Servern besteht. Diese Server nennen wir auch Instanzen.",
|
||||||
"onboarding.page_one.handle": "Du bist auf der Instanz {domain}, also ist dein vollständiger Nutzername im Netzwerk {handle}",
|
"onboarding.page_one.handle": "Du bist auf der Instanz {domain}, also ist dein vollständiger Profilname im Netzwerk {handle}",
|
||||||
"onboarding.page_one.welcome": "Willkommen bei Mastodon!",
|
"onboarding.page_one.welcome": "Willkommen bei Mastodon!",
|
||||||
"onboarding.page_six.admin": "Für deine Instanz ist {admin} zuständig.",
|
"onboarding.page_six.admin": "Für deine Instanz ist {admin} zuständig.",
|
||||||
"onboarding.page_six.almost_done": "Fast fertig…",
|
"onboarding.page_six.almost_done": "Fast fertig…",
|
||||||
@@ -143,11 +143,11 @@
|
|||||||
"onboarding.page_six.read_guidelines": "Bitte mach dich mit den {guidelines} von {domain} vertraut!",
|
"onboarding.page_six.read_guidelines": "Bitte mach dich mit den {guidelines} von {domain} vertraut!",
|
||||||
"onboarding.page_six.various_app": "mobile Anwendungen",
|
"onboarding.page_six.various_app": "mobile Anwendungen",
|
||||||
"onboarding.page_three.profile": "Bearbeite dein Profil, um dein Bild, deinen Namen oder deine Beschreibung anzupassen. Dort findest du auch andere Einstellungen.",
|
"onboarding.page_three.profile": "Bearbeite dein Profil, um dein Bild, deinen Namen oder deine Beschreibung anzupassen. Dort findest du auch andere Einstellungen.",
|
||||||
"onboarding.page_three.search": "Benutze die Suchfunktion, um Leute oder Themen zu finden. Zum Beispiel, die Hashtags {illustration} oder {introductions}. Um eine Person zu finden, die auf einer anderen Instanz ist, benutze den vollständigen Nutzernamen.",
|
"onboarding.page_three.search": "Benutze die Suchfunktion, um Leute oder Themen zu finden. Zum Beispiel, die Hashtags {illustration} oder {introductions}. Um eine Person zu finden, die auf einer anderen Instanz ist, benutze den vollständigen Profilnamen.",
|
||||||
"onboarding.page_two.compose": "Schreibe Beiträge aus der Schreiben-Spalte. Du kannst Bilder und kurze Videos hochladen, Sichtbarkeitseinstellungen ändern und Inhaltswarnungen hinzufügen.",
|
"onboarding.page_two.compose": "Schreibe Beiträge aus der Schreiben-Spalte. Du kannst Bilder und kurze Videos hochladen, Sichtbarkeitseinstellungen ändern und Inhaltswarnungen hinzufügen.",
|
||||||
"onboarding.skip": "Überspringen",
|
"onboarding.skip": "Überspringen",
|
||||||
"privacy.change": "Privatsphäre des Status anpassen",
|
"privacy.change": "Privatsphäre des Status anpassen",
|
||||||
"privacy.direct.long": "Beitrag nur an erwähnte Benutzer",
|
"privacy.direct.long": "Beitrag nur an erwähnte Profile",
|
||||||
"privacy.direct.short": "Direkt",
|
"privacy.direct.short": "Direkt",
|
||||||
"privacy.private.long": "Beitrag nur an Folgende",
|
"privacy.private.long": "Beitrag nur an Folgende",
|
||||||
"privacy.private.short": "Privat",
|
"privacy.private.short": "Privat",
|
||||||
|
@@ -34,6 +34,7 @@
|
|||||||
"column.mutes": "Muted users",
|
"column.mutes": "Muted users",
|
||||||
"column.notifications": "Notifications",
|
"column.notifications": "Notifications",
|
||||||
"column.public": "Federated timeline",
|
"column.public": "Federated timeline",
|
||||||
|
"column.pins": "Pinned toots",
|
||||||
"column_back_button.label": "Back",
|
"column_back_button.label": "Back",
|
||||||
"column_header.hide_settings": "Hide settings",
|
"column_header.hide_settings": "Hide settings",
|
||||||
"column_header.moveLeft_settings": "Move column to the left",
|
"column_header.moveLeft_settings": "Move column to the left",
|
||||||
@@ -111,6 +112,7 @@
|
|||||||
"navigation_bar.mutes": "Muted users",
|
"navigation_bar.mutes": "Muted users",
|
||||||
"navigation_bar.preferences": "Preferences",
|
"navigation_bar.preferences": "Preferences",
|
||||||
"navigation_bar.public_timeline": "Federated timeline",
|
"navigation_bar.public_timeline": "Federated timeline",
|
||||||
|
"navigation_bar.pins": "Pinned toots",
|
||||||
"notification.favourite": "{name} favourited your status",
|
"notification.favourite": "{name} favourited your status",
|
||||||
"notification.follow": "{name} followed you",
|
"notification.follow": "{name} followed you",
|
||||||
"notification.mention": "{name} mentioned you",
|
"notification.mention": "{name} mentioned you",
|
||||||
|
@@ -63,8 +63,8 @@
|
|||||||
"confirmations.mute.message": "آیا واقعاً میخواهید {name} را بیصدا کنید؟",
|
"confirmations.mute.message": "آیا واقعاً میخواهید {name} را بیصدا کنید؟",
|
||||||
"confirmations.unfollow.confirm": "لغو پیگیری",
|
"confirmations.unfollow.confirm": "لغو پیگیری",
|
||||||
"confirmations.unfollow.message": "آیا واقعاً میخواهید به پیگیری از {name} پایان دهید؟",
|
"confirmations.unfollow.message": "آیا واقعاً میخواهید به پیگیری از {name} پایان دهید؟",
|
||||||
"embed.instructions": "Embed this status on your website by copying the code below.",
|
"embed.instructions": "برای جاگذاری این نوشته در سایت خودتان، کد زیر را کپی کنید.",
|
||||||
"embed.preview": "Here is what it will look like:",
|
"embed.preview": "نوشتهٔ جاگذاریشده این گونه به نظر خواهد رسید:",
|
||||||
"emoji_button.activity": "فعالیت",
|
"emoji_button.activity": "فعالیت",
|
||||||
"emoji_button.flags": "پرچمها",
|
"emoji_button.flags": "پرچمها",
|
||||||
"emoji_button.food": "غذا و نوشیدنی",
|
"emoji_button.food": "غذا و نوشیدنی",
|
||||||
@@ -164,14 +164,14 @@
|
|||||||
"standalone.public_title": "نگاهی به کاربران این سرور...",
|
"standalone.public_title": "نگاهی به کاربران این سرور...",
|
||||||
"status.cannot_reblog": "این نوشته را نمیشود بازبوقید",
|
"status.cannot_reblog": "این نوشته را نمیشود بازبوقید",
|
||||||
"status.delete": "پاککردن",
|
"status.delete": "پاککردن",
|
||||||
"status.embed": "Embed",
|
"status.embed": "جاگذاری",
|
||||||
"status.favourite": "پسندیدن",
|
"status.favourite": "پسندیدن",
|
||||||
"status.load_more": "بیشتر نشان بده",
|
"status.load_more": "بیشتر نشان بده",
|
||||||
"status.media_hidden": "تصویر پنهان شده",
|
"status.media_hidden": "تصویر پنهان شده",
|
||||||
"status.mention": "نامبردن از @{name}",
|
"status.mention": "نامبردن از @{name}",
|
||||||
"status.mute_conversation": "بیصداکردن گفتگو",
|
"status.mute_conversation": "بیصداکردن گفتگو",
|
||||||
"status.open": "این نوشته را باز کن",
|
"status.open": "این نوشته را باز کن",
|
||||||
"status.pin": "Pin on profile",
|
"status.pin": "نوشتهٔ ثابت نمایه",
|
||||||
"status.reblog": "بازبوقیدن",
|
"status.reblog": "بازبوقیدن",
|
||||||
"status.reblogged_by": "{name} بازبوقید",
|
"status.reblogged_by": "{name} بازبوقید",
|
||||||
"status.reply": "پاسخ",
|
"status.reply": "پاسخ",
|
||||||
@@ -183,7 +183,7 @@
|
|||||||
"status.show_less": "نهفتن",
|
"status.show_less": "نهفتن",
|
||||||
"status.show_more": "نمایش",
|
"status.show_more": "نمایش",
|
||||||
"status.unmute_conversation": "باصداکردن گفتگو",
|
"status.unmute_conversation": "باصداکردن گفتگو",
|
||||||
"status.unpin": "Unpin from profile",
|
"status.unpin": "برداشتن نوشتهٔ ثابت نمایه",
|
||||||
"tabs_bar.compose": "بنویسید",
|
"tabs_bar.compose": "بنویسید",
|
||||||
"tabs_bar.federated_timeline": "همگانی",
|
"tabs_bar.federated_timeline": "همگانی",
|
||||||
"tabs_bar.home": "خانه",
|
"tabs_bar.home": "خانه",
|
||||||
|
@@ -34,6 +34,7 @@
|
|||||||
"column.mutes": "Comptes masqués",
|
"column.mutes": "Comptes masqués",
|
||||||
"column.notifications": "Notifications",
|
"column.notifications": "Notifications",
|
||||||
"column.public": "Fil public global",
|
"column.public": "Fil public global",
|
||||||
|
"column.pins": "Pouets épinglés",
|
||||||
"column_back_button.label": "Retour",
|
"column_back_button.label": "Retour",
|
||||||
"column_header.hide_settings": "Masquer les paramètres",
|
"column_header.hide_settings": "Masquer les paramètres",
|
||||||
"column_header.moveLeft_settings": "Déplacer la colonne vers la gauche",
|
"column_header.moveLeft_settings": "Déplacer la colonne vers la gauche",
|
||||||
@@ -62,9 +63,9 @@
|
|||||||
"confirmations.mute.confirm": "Masquer",
|
"confirmations.mute.confirm": "Masquer",
|
||||||
"confirmations.mute.message": "Confirmez vous le masquage de {name} ?",
|
"confirmations.mute.message": "Confirmez vous le masquage de {name} ?",
|
||||||
"confirmations.unfollow.confirm": "Ne plus suivre",
|
"confirmations.unfollow.confirm": "Ne plus suivre",
|
||||||
"confirmations.unfollow.message": "Vous voulez-vous arrêter de suivre {name} ?",
|
"confirmations.unfollow.message": "Voulez-vous arrêter de suivre {name} ?",
|
||||||
"embed.instructions": "Embed this status on your website by copying the code below.",
|
"embed.instructions": "Intégrez ce statut à votre site en copiant ce code ci-dessous.",
|
||||||
"embed.preview": "Here is what it will look like:",
|
"embed.preview": "Il apparaîtra comme cela : ",
|
||||||
"emoji_button.activity": "Activités",
|
"emoji_button.activity": "Activités",
|
||||||
"emoji_button.flags": "Drapeaux",
|
"emoji_button.flags": "Drapeaux",
|
||||||
"emoji_button.food": "Boire et manger",
|
"emoji_button.food": "Boire et manger",
|
||||||
@@ -111,6 +112,7 @@
|
|||||||
"navigation_bar.mutes": "Comptes masqués",
|
"navigation_bar.mutes": "Comptes masqués",
|
||||||
"navigation_bar.preferences": "Préférences",
|
"navigation_bar.preferences": "Préférences",
|
||||||
"navigation_bar.public_timeline": "Fil public global",
|
"navigation_bar.public_timeline": "Fil public global",
|
||||||
|
"navigation_bar.pins": "Pouets épinglés",
|
||||||
"notification.favourite": "{name} a ajouté à ses favoris :",
|
"notification.favourite": "{name} a ajouté à ses favoris :",
|
||||||
"notification.follow": "{name} vous suit.",
|
"notification.follow": "{name} vous suit.",
|
||||||
"notification.mention": "{name} vous a mentionné⋅e :",
|
"notification.mention": "{name} vous a mentionné⋅e :",
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"account.block": "Blokiraj @{name}",
|
"account.block": "Blokiraj @{name}",
|
||||||
"account.block_domain": "Sakrij sve sa {domain}",
|
"account.block_domain": "Sakrij sve sa {domain}",
|
||||||
"account.disclaimer_full": "Information below may reflect the user's profile incompletely.",
|
"account.disclaimer_full": "Ovaj korisnik je sa druge instance. Ovaj broj bi mogao biti veći.",
|
||||||
"account.edit_profile": "Uredi profil",
|
"account.edit_profile": "Uredi profil",
|
||||||
"account.follow": "Slijedi",
|
"account.follow": "Slijedi",
|
||||||
"account.followers": "Sljedbenici",
|
"account.followers": "Sljedbenici",
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
"account.requested": "Čeka pristanak",
|
"account.requested": "Čeka pristanak",
|
||||||
"account.share": "Share @{name}'s profile",
|
"account.share": "Share @{name}'s profile",
|
||||||
"account.unblock": "Deblokiraj @{name}",
|
"account.unblock": "Deblokiraj @{name}",
|
||||||
"account.unblock_domain": "Otkrij {domain}",
|
"account.unblock_domain": "Poništi sakrivanje {domain}",
|
||||||
"account.unfollow": "Prestani slijediti",
|
"account.unfollow": "Prestani slijediti",
|
||||||
"account.unmute": "Poništi utišavanje @{name}",
|
"account.unmute": "Poništi utišavanje @{name}",
|
||||||
"account.view_full_profile": "View full profile",
|
"account.view_full_profile": "View full profile",
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
"column_header.unpin": "Unpin",
|
"column_header.unpin": "Unpin",
|
||||||
"column_subheading.navigation": "Navigacija",
|
"column_subheading.navigation": "Navigacija",
|
||||||
"column_subheading.settings": "Postavke",
|
"column_subheading.settings": "Postavke",
|
||||||
"compose_form.lock_disclaimer": "Tvoj račun nije {locked}. Svatko te može slijediti i vidjeti tvoje postove namijenjene samo sljedbenicima.",
|
"compose_form.lock_disclaimer": "Tvoj račun nije {locked}. Svatko te može slijediti kako bi vidio postove namijenjene samo tvojim sljedbenicima.",
|
||||||
"compose_form.lock_disclaimer.lock": "zaključan",
|
"compose_form.lock_disclaimer.lock": "zaključan",
|
||||||
"compose_form.placeholder": "Što ti je na umu?",
|
"compose_form.placeholder": "Što ti je na umu?",
|
||||||
"compose_form.privacy_disclaimer": "Tvoj privatni status će biti dostavljen spomenutim korisnicima na {domains}. Vjeruješ li {domainsCount, plural, one {that server} drugim {those servers}}? Privatnost postova radi samo na Mastodon instancama. Ako {domains} {domainsCount, plural, one {is not a Mastodon instance} other {are not Mastodon instances}}, neće biti indikacije da je tvoj post privatan, i mogao bi biti podignut ili biti učinjen vidljivim na drugi način neželjenim primateljima.",
|
"compose_form.privacy_disclaimer": "Tvoj privatni status će biti dostavljen spomenutim korisnicima na {domains}. Vjeruješ li {domainsCount, plural, one {that server} drugim {those servers}}? Privatnost postova radi samo na Mastodon instancama. Ako {domains} {domainsCount, plural, one {is not a Mastodon instance} other {are not Mastodon instances}}, neće biti indikacije da je tvoj post privatan, i mogao bi biti podignut ili biti učinjen vidljivim na drugi način neželjenim primateljima.",
|
||||||
@@ -54,13 +54,14 @@
|
|||||||
"compose_form.spoiler_placeholder": "Upozorenje o sadržaju",
|
"compose_form.spoiler_placeholder": "Upozorenje o sadržaju",
|
||||||
"confirmation_modal.cancel": "Otkaži",
|
"confirmation_modal.cancel": "Otkaži",
|
||||||
"confirmations.block.confirm": "Blokiraj",
|
"confirmations.block.confirm": "Blokiraj",
|
||||||
"confirmations.block.message": "Jesi li siguran da želiš blokirati {name}?",
|
"confirmations.block.message": "Želiš li sigurno blokirati {name}?",
|
||||||
"confirmations.delete.confirm": "Obriši",
|
"confirmations.delete.confirm": "Obriši",
|
||||||
"confirmations.delete.message": "Jesi li siguran da želiš obrisati ovaj status?",
|
"confirmations.delete.message": "Želiš li stvarno obrisati ovaj status?",
|
||||||
"confirmations.domain_block.confirm": "Sakrij cijelu domenu",
|
"confirmations.domain_block.confirm": "Sakrij cijelu domenu",
|
||||||
"confirmations.domain_block.message": "Jesi li zaista, zaista siguran da želiš blokirati sve sa {domain}? U većini slučajeva nekoliko ciljanih blokiranja ili utišavanja je dostatno i poželjnije.",
|
"confirmations.domain_block.message": "Jesi li zaista, zaista siguran da želiš potpuno blokirati {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.",
|
||||||
"confirmations.mute.confirm": "Utišaj",
|
"confirmations.mute.confirm": "Utišaj",
|
||||||
"confirmations.mute.message": "Jesi li siguran da želiš utišati {name}?",
|
"confirmations.mute.message": "Jesi li siguran da želiš utišati {name}?",
|
||||||
|
"confirmations.mute.message": "Jesi li siguran da želiš utišati {name}?",
|
||||||
"confirmations.unfollow.confirm": "Unfollow",
|
"confirmations.unfollow.confirm": "Unfollow",
|
||||||
"confirmations.unfollow.message": "Are you sure you want to unfollow {name}?",
|
"confirmations.unfollow.message": "Are you sure you want to unfollow {name}?",
|
||||||
"embed.instructions": "Embed this status on your website by copying the code below.",
|
"embed.instructions": "Embed this status on your website by copying the code below.",
|
||||||
@@ -69,16 +70,16 @@
|
|||||||
"emoji_button.flags": "Zastave",
|
"emoji_button.flags": "Zastave",
|
||||||
"emoji_button.food": "Hrana & Piće",
|
"emoji_button.food": "Hrana & Piće",
|
||||||
"emoji_button.label": "Umetni smajlije",
|
"emoji_button.label": "Umetni smajlije",
|
||||||
"emoji_button.nature": "Nature",
|
"emoji_button.nature": "Priroda",
|
||||||
"emoji_button.objects": "Objekti",
|
"emoji_button.objects": "Objekti",
|
||||||
"emoji_button.people": "Ljudi",
|
"emoji_button.people": "Ljudi",
|
||||||
"emoji_button.search": "Traži...",
|
"emoji_button.search": "Traži...",
|
||||||
"emoji_button.symbols": "Simboli",
|
"emoji_button.symbols": "Simboli",
|
||||||
"emoji_button.travel": "Putovanja i Mjesta",
|
"emoji_button.travel": "Putovanja & Mjesta",
|
||||||
"empty_column.community": "Lokalni timeline je prazan. Napiši nešto javno kako bi pokrenuo stvari!",
|
"empty_column.community": "Lokalni timeline je prazan. Napiši nešto javno kako bi pokrenuo stvari!",
|
||||||
"empty_column.hashtag": "Još ne postoji ništa s ovim hashtagom.",
|
"empty_column.hashtag": "Još ne postoji ništa s ovim hashtagom.",
|
||||||
"empty_column.home": "Još ne slijediš nikoga. Posjeti {public} ili koristi tražilicu kako bi počeo i upoznao druge korisnike.",
|
"empty_column.home": "Još ne slijediš nikoga. Posjeti {public} ili koristi tražilicu kako bi počeo i upoznao druge korisnike.",
|
||||||
"empty_column.home.inactivity": "Tvoj home feed je prazan. Ako si neko vrijeme bio neaktivan, regenerirat će se uskoro.",
|
"empty_column.home.inactivity": "Tvoj home feed je prazan. Ako si neko vrijeme bio neaktivan, uskoro ćese regenerirati.",
|
||||||
"empty_column.home.public_timeline": "javni timeline",
|
"empty_column.home.public_timeline": "javni timeline",
|
||||||
"empty_column.notifications": "Još nemaš notifikacija. Komuniciraj sa drugima kako bi započeo razgovor.",
|
"empty_column.notifications": "Još nemaš notifikacija. Komuniciraj sa drugima kako bi započeo razgovor.",
|
||||||
"empty_column.public": "Ovdje nema ništa! Napiši nešto javno, ili ručno slijedi korisnike sa drugih instanci kako bi popunio",
|
"empty_column.public": "Ovdje nema ništa! Napiši nešto javno, ili ručno slijedi korisnike sa drugih instanci kako bi popunio",
|
||||||
@@ -88,11 +89,11 @@
|
|||||||
"getting_started.faq": "FAQ",
|
"getting_started.faq": "FAQ",
|
||||||
"getting_started.heading": "Počnimo",
|
"getting_started.heading": "Počnimo",
|
||||||
"getting_started.open_source_notice": "Mastodon je softver otvorenog koda. Možeš pridonijeti ili prijaviti probleme na GitHubu {github}.",
|
"getting_started.open_source_notice": "Mastodon je softver otvorenog koda. Možeš pridonijeti ili prijaviti probleme na GitHubu {github}.",
|
||||||
"getting_started.userguide": "Vodič za korisnike",
|
"getting_started.userguide": "Upute za korištenje",
|
||||||
"home.column_settings.advanced": "Napredno",
|
"home.column_settings.advanced": "Napredno",
|
||||||
"home.column_settings.basic": "Osnovno",
|
"home.column_settings.basic": "Osnovno",
|
||||||
"home.column_settings.filter_regex": "Filtriraj s regularnim izrazima",
|
"home.column_settings.filter_regex": "Filtriraj s regularnim izrazima",
|
||||||
"home.column_settings.show_reblogs": "Pokaži boosts",
|
"home.column_settings.show_reblogs": "Pokaži boostove",
|
||||||
"home.column_settings.show_replies": "Pokaži odgovore",
|
"home.column_settings.show_replies": "Pokaži odgovore",
|
||||||
"home.settings": "Postavke Stupca",
|
"home.settings": "Postavke Stupca",
|
||||||
"lightbox.close": "Zatvori",
|
"lightbox.close": "Zatvori",
|
||||||
@@ -113,7 +114,7 @@
|
|||||||
"navigation_bar.public_timeline": "Federalni timeline",
|
"navigation_bar.public_timeline": "Federalni timeline",
|
||||||
"notification.favourite": "{name} je lajkao tvoj status",
|
"notification.favourite": "{name} je lajkao tvoj status",
|
||||||
"notification.follow": "{name} te sada slijedi",
|
"notification.follow": "{name} te sada slijedi",
|
||||||
"notification.mention": "{name} mentioned you",
|
"notification.mention": "{name} te je spomenuo",
|
||||||
"notification.reblog": "{name} je podigao tvoj status",
|
"notification.reblog": "{name} je podigao tvoj status",
|
||||||
"notifications.clear": "Očisti notifikacije",
|
"notifications.clear": "Očisti notifikacije",
|
||||||
"notifications.clear_confirmation": "Želiš li zaista obrisati sve svoje notifikacije?",
|
"notifications.clear_confirmation": "Želiš li zaista obrisati sve svoje notifikacije?",
|
||||||
@@ -123,28 +124,28 @@
|
|||||||
"notifications.column_settings.mention": "Spominjanja:",
|
"notifications.column_settings.mention": "Spominjanja:",
|
||||||
"notifications.column_settings.push": "Push notifications",
|
"notifications.column_settings.push": "Push notifications",
|
||||||
"notifications.column_settings.push_meta": "This device",
|
"notifications.column_settings.push_meta": "This device",
|
||||||
"notifications.column_settings.reblog": "Boosts:",
|
"notifications.column_settings.reblog": "Boostovi:",
|
||||||
"notifications.column_settings.show": "Prikaži u stupcu",
|
"notifications.column_settings.show": "Prikaži u stupcu",
|
||||||
"notifications.column_settings.sound": "Sviraj zvuk",
|
"notifications.column_settings.sound": "Sviraj zvuk",
|
||||||
"onboarding.done": "Učinjeno",
|
"onboarding.done": "Učinjeno",
|
||||||
"onboarding.next": "Sljedeća",
|
"onboarding.next": "Sljedeće",
|
||||||
"onboarding.page_five.public_timelines": "The local timeline prikazuje javne postove svih na {domain}. Federalni timeline pokazuje javne postove svih sa {domain} domena koje slijediš. To je sjajan način da otkriješ nove ljude.",
|
"onboarding.page_five.public_timelines": "Lokalni timeline prikazuje javne postove sviju od svakog na {domain}. Federalni timeline prikazuje javne postove svakog koga ljudi na {domain} slijede. To su Javni Timelineovi, sjajan način za otkriti nove ljude.",
|
||||||
"onboarding.page_four.home": "The home timeline prikazuje samo postove ljudi koje slijediš.",
|
"onboarding.page_four.home": "The home timeline prikazuje postove ljudi koje slijediš.",
|
||||||
"onboarding.page_four.notifications": "Stupac notifikacija pokazuje kada je netko u interakciji s tobom.",
|
"onboarding.page_four.notifications": "Stupac za notifikacije pokazuje poruke drugih upućene tebi.",
|
||||||
"onboarding.page_one.federation": "Mastodon je mreža nezavisnih servera udruženih kako bi stvorili veću socijalnu mrežu. Te servere zovemo instance.",
|
"onboarding.page_one.federation": "Mastodon čini mreža neovisnih servera udruženih u jednu veću socialnu mrežu. Te servere nazivamo instancama.",
|
||||||
"onboarding.page_one.handle": "Ti si na {domain}, tako da je tvoj potpuni opis {handle}",
|
"onboarding.page_one.handle": "Ti si na {domain}, i tvoja puna handle je {handle}",
|
||||||
"onboarding.page_one.welcome": "Dobro došli u Mastodon!",
|
"onboarding.page_one.welcome": "Dobro došli na Mastodon!",
|
||||||
"onboarding.page_six.admin": "Administrator tvoje instance je {admin}.",
|
"onboarding.page_six.admin": "Administrator tvoje instance je {admin}.",
|
||||||
"onboarding.page_six.almost_done": "Još malo pa gotovo...",
|
"onboarding.page_six.almost_done": "Još malo pa gotovo...",
|
||||||
"onboarding.page_six.appetoot": "Živjeli!",
|
"onboarding.page_six.appetoot": "Živjeli!",
|
||||||
"onboarding.page_six.apps_available": "Postoje {apps} dostupne za iOS, Android i druge platforme.",
|
"onboarding.page_six.apps_available": "Postoje {apps} dostupne za iOS, Android i druge platforme.",
|
||||||
"onboarding.page_six.github": "Mastodon je besplatan softver otvorenog koda. Možeš prijaviti greške, zahtijevati mogućnosti, ili pridonijeti kodu na {github}.",
|
"onboarding.page_six.github": "Mastodon je besplatan softver otvorenog koda. You can report bugs, request features, or contribute to the code on {github}.",
|
||||||
"onboarding.page_six.guidelines": "smjernice zajednice",
|
"onboarding.page_six.guidelines": "smjernice zajednice",
|
||||||
"onboarding.page_six.read_guidelines": "Molimo, pročitaj {domain}'s {guidelines}!",
|
"onboarding.page_six.read_guidelines": "Molimo pročitaj {domain}'s {guidelines}!",
|
||||||
"onboarding.page_six.various_app": "mobilne aplikacije",
|
"onboarding.page_six.various_app": "mobilne aplikacije",
|
||||||
"onboarding.page_three.profile": "Uredi svoj profil mijenjanjem avatara, biografije i imena koje će biti prikazano. Naći ćeš i druge korisne postavke.",
|
"onboarding.page_three.profile": "Uredi svoj profil promjenom svog avatara, biografije, i imena. Ovdje ćeš isto tako pronaći i druge postavke.",
|
||||||
"onboarding.page_three.search": "Koristi tražilicu kako bi pronašao ljude i sadržaj sa određenim hashtagovima, kao što su {illustration} i {introductions}. Da bi našao osobu koja nije na ovoj instanci, upotrijebi njihov puni opis.",
|
"onboarding.page_three.search": "Koristi tražilicu kako bi pronašao ljude i tražio hashtags, kao što su {illustration} i {introductions}. Kako bi pronašao osobu koja nije na ovoj instanci, upotrijebi njen pun handle.",
|
||||||
"onboarding.page_two.compose": "Piši postove u stupcu za njihovo sastavljanje. Možeš uploadati slike, promijeniti postavke privatnosti, i dodati upozorenja o sadržaju s ikonama ispod.",
|
"onboarding.page_two.compose": "Piši postove u stupcu za sastavljanje. Možeš uploadati slike, promijeniti postavke privatnosti, i dodati upozorenja o sadržaju s ikonama ispod.",
|
||||||
"onboarding.skip": "Preskoči",
|
"onboarding.skip": "Preskoči",
|
||||||
"privacy.change": "Podesi status privatnosti",
|
"privacy.change": "Podesi status privatnosti",
|
||||||
"privacy.direct.long": "Prikaži samo spomenutim korisnicima",
|
"privacy.direct.long": "Prikaži samo spomenutim korisnicima",
|
||||||
@@ -162,7 +163,7 @@
|
|||||||
"search.placeholder": "Traži",
|
"search.placeholder": "Traži",
|
||||||
"search_results.total": "{count, number} {count, plural, one {result} other {results}}",
|
"search_results.total": "{count, number} {count, plural, one {result} other {results}}",
|
||||||
"standalone.public_title": "A look inside...",
|
"standalone.public_title": "A look inside...",
|
||||||
"status.cannot_reblog": "Ovaj post ne može biti podignut",
|
"status.cannot_reblog": "Ovaj post ne može biti boostan",
|
||||||
"status.delete": "Obriši",
|
"status.delete": "Obriši",
|
||||||
"status.embed": "Embed",
|
"status.embed": "Embed",
|
||||||
"status.favourite": "Označi omiljenim",
|
"status.favourite": "Označi omiljenim",
|
||||||
@@ -196,5 +197,5 @@
|
|||||||
"video_player.expand": "Proširi video",
|
"video_player.expand": "Proširi video",
|
||||||
"video_player.toggle_sound": "Toggle zvuk",
|
"video_player.toggle_sound": "Toggle zvuk",
|
||||||
"video_player.toggle_visible": "Preklopi vidljivost",
|
"video_player.toggle_visible": "Preklopi vidljivost",
|
||||||
"video_player.video_error": "Video nije mogao biti prikazan"
|
"video_player.video_error": "Video ne može biti reproduciran"
|
||||||
}
|
}
|
||||||
|
@@ -34,6 +34,7 @@
|
|||||||
"column.mutes": "ミュートしたユーザー",
|
"column.mutes": "ミュートしたユーザー",
|
||||||
"column.notifications": "通知",
|
"column.notifications": "通知",
|
||||||
"column.public": "連合タイムライン",
|
"column.public": "連合タイムライン",
|
||||||
|
"column.pins": "固定されたトゥート",
|
||||||
"column_back_button.label": "戻る",
|
"column_back_button.label": "戻る",
|
||||||
"column_header.hide_settings": "設定を隠す",
|
"column_header.hide_settings": "設定を隠す",
|
||||||
"column_header.moveLeft_settings": "カラムを左に移動する",
|
"column_header.moveLeft_settings": "カラムを左に移動する",
|
||||||
@@ -111,6 +112,7 @@
|
|||||||
"navigation_bar.mutes": "ミュートしたユーザー",
|
"navigation_bar.mutes": "ミュートしたユーザー",
|
||||||
"navigation_bar.preferences": "ユーザー設定",
|
"navigation_bar.preferences": "ユーザー設定",
|
||||||
"navigation_bar.public_timeline": "連合タイムライン",
|
"navigation_bar.public_timeline": "連合タイムライン",
|
||||||
|
"navigation_bar.pins": "固定されたトゥート",
|
||||||
"notification.favourite": "{name}さんがあなたのトゥートをお気に入りに登録しました",
|
"notification.favourite": "{name}さんがあなたのトゥートをお気に入りに登録しました",
|
||||||
"notification.follow": "{name}さんにフォローされました",
|
"notification.follow": "{name}さんにフォローされました",
|
||||||
"notification.mention": "{name}さんがあなたに返信しました",
|
"notification.mention": "{name}さんがあなたに返信しました",
|
||||||
|
@@ -34,6 +34,7 @@
|
|||||||
"column.mutes": "뮤트 중인 사용자",
|
"column.mutes": "뮤트 중인 사용자",
|
||||||
"column.notifications": "알림",
|
"column.notifications": "알림",
|
||||||
"column.public": "연합 타임라인",
|
"column.public": "연합 타임라인",
|
||||||
|
"column.pins": "고정된 Toot",
|
||||||
"column_back_button.label": "돌아가기",
|
"column_back_button.label": "돌아가기",
|
||||||
"column_header.hide_settings": "Hide settings",
|
"column_header.hide_settings": "Hide settings",
|
||||||
"column_header.moveLeft_settings": "Move column to the left",
|
"column_header.moveLeft_settings": "Move column to the left",
|
||||||
@@ -111,6 +112,7 @@
|
|||||||
"navigation_bar.mutes": "뮤트 중인 사용자",
|
"navigation_bar.mutes": "뮤트 중인 사용자",
|
||||||
"navigation_bar.preferences": "사용자 설정",
|
"navigation_bar.preferences": "사용자 설정",
|
||||||
"navigation_bar.public_timeline": "연합 타임라인",
|
"navigation_bar.public_timeline": "연합 타임라인",
|
||||||
|
"navigation_bar.pins": "고정된 Toot",
|
||||||
"notification.favourite": "{name}님이 즐겨찾기 했습니다",
|
"notification.favourite": "{name}님이 즐겨찾기 했습니다",
|
||||||
"notification.follow": "{name}님이 나를 팔로우 했습니다",
|
"notification.follow": "{name}님이 나를 팔로우 했습니다",
|
||||||
"notification.mention": "{name}님이 답글을 보냈습니다",
|
"notification.mention": "{name}님이 답글을 보냈습니다",
|
||||||
|
@@ -12,7 +12,7 @@
|
|||||||
"account.mute": "Rescondre @{name}",
|
"account.mute": "Rescondre @{name}",
|
||||||
"account.posts": "Estatuts",
|
"account.posts": "Estatuts",
|
||||||
"account.report": "Senhalar @{name}",
|
"account.report": "Senhalar @{name}",
|
||||||
"account.requested": "Invitacion mandada",
|
"account.requested": "Invitacion mandada. Clicatz per anullar.",
|
||||||
"account.share": "Partejar lo perfil a @{name}",
|
"account.share": "Partejar lo perfil a @{name}",
|
||||||
"account.unblock": "Desblocar @{name}",
|
"account.unblock": "Desblocar @{name}",
|
||||||
"account.unblock_domain": "Desblocar {domain}",
|
"account.unblock_domain": "Desblocar {domain}",
|
||||||
@@ -34,6 +34,7 @@
|
|||||||
"column.mutes": "Personas en silenci",
|
"column.mutes": "Personas en silenci",
|
||||||
"column.notifications": "Notificacions",
|
"column.notifications": "Notificacions",
|
||||||
"column.public": "Flux public global",
|
"column.public": "Flux public global",
|
||||||
|
"column.pins": "Tuts penjats",
|
||||||
"column_back_button.label": "Tornar",
|
"column_back_button.label": "Tornar",
|
||||||
"column_header.hide_settings": "Amagar los paramètres",
|
"column_header.hide_settings": "Amagar los paramètres",
|
||||||
"column_header.moveLeft_settings": "Desplaçar la colomna a man drecha",
|
"column_header.moveLeft_settings": "Desplaçar la colomna a man drecha",
|
||||||
@@ -63,8 +64,8 @@
|
|||||||
"confirmations.mute.message": "Sètz segur de voler metre en silenci {name} ?",
|
"confirmations.mute.message": "Sètz segur de voler metre en silenci {name} ?",
|
||||||
"confirmations.unfollow.confirm": "Quitar de sègre",
|
"confirmations.unfollow.confirm": "Quitar de sègre",
|
||||||
"confirmations.unfollow.message": "Volètz vertadièrament quitar de sègre {name} ?",
|
"confirmations.unfollow.message": "Volètz vertadièrament quitar de sègre {name} ?",
|
||||||
"embed.instructions": "Embed this status on your website by copying the code below.",
|
"embed.instructions": "Embarcar aqueste estatut per o far veire sus un site Internet en copiar lo còdi çai-jos.",
|
||||||
"embed.preview": "Here is what it will look like:",
|
"embed.preview": "Semblarà aquò : ",
|
||||||
"emoji_button.activity": "Activitats",
|
"emoji_button.activity": "Activitats",
|
||||||
"emoji_button.flags": "Drapèus",
|
"emoji_button.flags": "Drapèus",
|
||||||
"emoji_button.food": "Beure e manjar",
|
"emoji_button.food": "Beure e manjar",
|
||||||
@@ -87,7 +88,7 @@
|
|||||||
"getting_started.appsshort": "Apps",
|
"getting_started.appsshort": "Apps",
|
||||||
"getting_started.faq": "FAQ",
|
"getting_started.faq": "FAQ",
|
||||||
"getting_started.heading": "Per començar",
|
"getting_started.heading": "Per començar",
|
||||||
"getting_started.open_source_notice": "Mastodon es un logicial liure. Podètz contribuir e mandar vòstres comentaris e rapòrt de bug via{github} sus GitHub.",
|
"getting_started.open_source_notice": "Mastodon es un logicial liure. Podètz contribuir e mandar vòstres comentaris e rapòrt de bug via {github} sus GitHub.",
|
||||||
"getting_started.userguide": "Guida d’utilizacion",
|
"getting_started.userguide": "Guida d’utilizacion",
|
||||||
"home.column_settings.advanced": "Avançat",
|
"home.column_settings.advanced": "Avançat",
|
||||||
"home.column_settings.basic": "Basic",
|
"home.column_settings.basic": "Basic",
|
||||||
@@ -111,6 +112,7 @@
|
|||||||
"navigation_bar.mutes": "Personas rescondudas",
|
"navigation_bar.mutes": "Personas rescondudas",
|
||||||
"navigation_bar.preferences": "Preferéncias",
|
"navigation_bar.preferences": "Preferéncias",
|
||||||
"navigation_bar.public_timeline": "Flux public global",
|
"navigation_bar.public_timeline": "Flux public global",
|
||||||
|
"navigation_bar.pins": "Tuts penjats",
|
||||||
"notification.favourite": "{name} a ajustat a sos favorits :",
|
"notification.favourite": "{name} a ajustat a sos favorits :",
|
||||||
"notification.follow": "{name} vos sèc",
|
"notification.follow": "{name} vos sèc",
|
||||||
"notification.mention": "{name} vos a mencionat :",
|
"notification.mention": "{name} vos a mencionat :",
|
||||||
@@ -126,21 +128,21 @@
|
|||||||
"notifications.column_settings.reblog": "Partatges :",
|
"notifications.column_settings.reblog": "Partatges :",
|
||||||
"notifications.column_settings.show": "Mostrar dins la colomna",
|
"notifications.column_settings.show": "Mostrar dins la colomna",
|
||||||
"notifications.column_settings.sound": "Emetre un son",
|
"notifications.column_settings.sound": "Emetre un son",
|
||||||
"onboarding.done": "Fach",
|
"onboarding.done": "Sortir",
|
||||||
"onboarding.next": "Seguent",
|
"onboarding.next": "Seguent",
|
||||||
"onboarding.page_five.public_timelines": "Lo flux local mòstra los estatuts publics del monde de vòstra instància, aquí {domain}. Lo flux federat mòstra los estatuts publics de tot lo mond sus {domain} sègon. Son los fluxes publics, un bon biais de trobar de mond.",
|
"onboarding.page_five.public_timelines": "Lo flux local mòstra los estatuts publics del monde de vòstra instància, aquí {domain}. Lo flux federat mòstra los estatuts publics de la gent que los de {domain} sègon. Son los fluxes publics, un bon biais de trobar de mond.",
|
||||||
"onboarding.page_four.home": "Lo flux d’acuèlh mòstra los estatuts del mond que seguètz.",
|
"onboarding.page_four.home": "Lo flux d’acuèlh mòstra los estatuts del mond que seguètz.",
|
||||||
"onboarding.page_four.notifications": "La colomna de notificacions vos fa veire quand qualqu’un interagís amb vos",
|
"onboarding.page_four.notifications": "La colomna de notificacions vos fa veire quand qualqu’un interagís amb vos",
|
||||||
"onboarding.page_one.federation": "Mastodon es un malhum de servidors independents que comunican per bastir un malhum ma larg. Òm los apèla instàncias.",
|
"onboarding.page_one.federation": "Mastodon es un malhum de servidors independents que comunican per bastir un malhum mai larg. Òm los apèla instàncias.",
|
||||||
"onboarding.page_one.handle": "Sètz sus {domain}, doncas vòstre identificant complet es {handle}",
|
"onboarding.page_one.handle": "Sètz sus {domain}, doncas vòstre identificant complet es {handle}",
|
||||||
"onboarding.page_one.welcome": "Benvengut a Mastodon !",
|
"onboarding.page_one.welcome": "Benvengut a Mastodon !",
|
||||||
"onboarding.page_six.admin": "Vòstre administrator d’instància es {admin}.",
|
"onboarding.page_six.admin": "Vòstre administrator d’instància es {admin}.",
|
||||||
"onboarding.page_six.almost_done": "Gaireben acabat…",
|
"onboarding.page_six.almost_done": "Gaireben acabat…",
|
||||||
"onboarding.page_six.appetoot": "Bon Appetut!",
|
"onboarding.page_six.appetoot": "Bon Appetut !",
|
||||||
"onboarding.page_six.apps_available": "I a d’aplicacions per mobil per iOS, Android e mai.",
|
"onboarding.page_six.apps_available": "I a d’aplicacions per mobil per iOS, Android e mai.",
|
||||||
"onboarding.page_six.github": "Mastodon es un logicial liure e open-source. Podètz senhalar de bugs, demandar de foncionalitats e contribuir al còdi sus {github}.",
|
"onboarding.page_six.github": "Mastodon es un logicial liure e open-source. Podètz senhalar de bugs, demandar de foncionalitats e contribuir al còdi sus {github}.",
|
||||||
"onboarding.page_six.guidelines": "guida de la comunitat",
|
"onboarding.page_six.guidelines": "guida de la comunitat",
|
||||||
"onboarding.page_six.read_guidelines": "Mercés de legir la {guidelines} a {domain} !",
|
"onboarding.page_six.read_guidelines": "Mercés de legir la {guidelines} de {domain} !",
|
||||||
"onboarding.page_six.various_app": "aplicacions per mobil",
|
"onboarding.page_six.various_app": "aplicacions per mobil",
|
||||||
"onboarding.page_three.profile": "Modificatz vòstre perfil per cambiar vòstre avatar, bio e escais-nom. I a enlà totas las preferéncias.",
|
"onboarding.page_three.profile": "Modificatz vòstre perfil per cambiar vòstre avatar, bio e escais-nom. I a enlà totas las preferéncias.",
|
||||||
"onboarding.page_three.search": "Emplegatz la barra de recèrca per trobar de mond e engachatz las etiquetas coma {illustration} e {introductions}. Per trobar una persona d’una autra instància, picatz son identificant complet.",
|
"onboarding.page_three.search": "Emplegatz la barra de recèrca per trobar de mond e engachatz las etiquetas coma {illustration} e {introductions}. Per trobar una persona d’una autra instància, picatz son identificant complet.",
|
||||||
@@ -164,7 +166,7 @@
|
|||||||
"standalone.public_title": "Una ulhada dedins…",
|
"standalone.public_title": "Una ulhada dedins…",
|
||||||
"status.cannot_reblog": "Aqueste estatut pòt pas èsser partejat",
|
"status.cannot_reblog": "Aqueste estatut pòt pas èsser partejat",
|
||||||
"status.delete": "Escafar",
|
"status.delete": "Escafar",
|
||||||
"status.embed": "Embed",
|
"status.embed": "Embarcar",
|
||||||
"status.favourite": "Apondre als favorits",
|
"status.favourite": "Apondre als favorits",
|
||||||
"status.load_more": "Cargar mai",
|
"status.load_more": "Cargar mai",
|
||||||
"status.media_hidden": "Mèdia rescondut",
|
"status.media_hidden": "Mèdia rescondut",
|
||||||
@@ -183,7 +185,7 @@
|
|||||||
"status.show_less": "Tornar plegar",
|
"status.show_less": "Tornar plegar",
|
||||||
"status.show_more": "Desplegar",
|
"status.show_more": "Desplegar",
|
||||||
"status.unmute_conversation": "Conversacions amb silenci levat",
|
"status.unmute_conversation": "Conversacions amb silenci levat",
|
||||||
"status.unpin": "Despenjar del perfil",
|
"status.unpin": "Tirar del perfil",
|
||||||
"tabs_bar.compose": "Compausar",
|
"tabs_bar.compose": "Compausar",
|
||||||
"tabs_bar.federated_timeline": "Flux public global",
|
"tabs_bar.federated_timeline": "Flux public global",
|
||||||
"tabs_bar.home": "Acuèlh",
|
"tabs_bar.home": "Acuèlh",
|
||||||
|
@@ -12,7 +12,7 @@
|
|||||||
"account.mute": "Wycisz @{name}",
|
"account.mute": "Wycisz @{name}",
|
||||||
"account.posts": "Wpisy",
|
"account.posts": "Wpisy",
|
||||||
"account.report": "Zgłoś @{name}",
|
"account.report": "Zgłoś @{name}",
|
||||||
"account.requested": "Oczekująca prośba",
|
"account.requested": "Oczekująca prośba, kliknij aby anulować",
|
||||||
"account.share": "Udostępnij profil @{name}",
|
"account.share": "Udostępnij profil @{name}",
|
||||||
"account.unblock": "Odblokuj @{name}",
|
"account.unblock": "Odblokuj @{name}",
|
||||||
"account.unblock_domain": "Odblokuj domenę {domain}",
|
"account.unblock_domain": "Odblokuj domenę {domain}",
|
||||||
@@ -33,6 +33,7 @@
|
|||||||
"column.home": "Strona główna",
|
"column.home": "Strona główna",
|
||||||
"column.mutes": "Wyciszeni użytkownicy",
|
"column.mutes": "Wyciszeni użytkownicy",
|
||||||
"column.notifications": "Powiadomienia",
|
"column.notifications": "Powiadomienia",
|
||||||
|
"column.pins": "Przypięte wpisy",
|
||||||
"column.public": "Globalna oś czasu",
|
"column.public": "Globalna oś czasu",
|
||||||
"column_back_button.label": "Wróć",
|
"column_back_button.label": "Wróć",
|
||||||
"column_header.hide_settings": "Ukryj ustawienia",
|
"column_header.hide_settings": "Ukryj ustawienia",
|
||||||
@@ -109,6 +110,7 @@
|
|||||||
"navigation_bar.info": "Szczegółowe informacje",
|
"navigation_bar.info": "Szczegółowe informacje",
|
||||||
"navigation_bar.logout": "Wyloguj",
|
"navigation_bar.logout": "Wyloguj",
|
||||||
"navigation_bar.mutes": "Wyciszeni użytkownicy",
|
"navigation_bar.mutes": "Wyciszeni użytkownicy",
|
||||||
|
"navigation_bar.pins": "Przypięte wpisy",
|
||||||
"navigation_bar.preferences": "Preferencje",
|
"navigation_bar.preferences": "Preferencje",
|
||||||
"navigation_bar.public_timeline": "Oś czasu federacji",
|
"navigation_bar.public_timeline": "Oś czasu federacji",
|
||||||
"notification.favourite": "{name} dodał Twój status do ulubionych",
|
"notification.favourite": "{name} dodał Twój status do ulubionych",
|
||||||
@@ -153,8 +155,8 @@
|
|||||||
"privacy.private.short": "Tylko dla śledzących",
|
"privacy.private.short": "Tylko dla śledzących",
|
||||||
"privacy.public.long": "Widoczny na publicznych osiach czasu",
|
"privacy.public.long": "Widoczny na publicznych osiach czasu",
|
||||||
"privacy.public.short": "Publiczny",
|
"privacy.public.short": "Publiczny",
|
||||||
"privacy.unlisted.long": "Niewidoczne na publicznych osiach czasu",
|
"privacy.unlisted.long": "Niewidoczny na publicznych osiach czasu",
|
||||||
"privacy.unlisted.short": "Niewidoczne",
|
"privacy.unlisted.short": "Niewidoczny",
|
||||||
"reply_indicator.cancel": "Anuluj",
|
"reply_indicator.cancel": "Anuluj",
|
||||||
"report.placeholder": "Dodatkowe komentarze",
|
"report.placeholder": "Dodatkowe komentarze",
|
||||||
"report.submit": "Wyślij",
|
"report.submit": "Wyślij",
|
||||||
|
@@ -28,7 +28,7 @@ export default function reports(state = initialState, action) {
|
|||||||
if (state.getIn(['new', 'account_id']) !== action.account.get('id')) {
|
if (state.getIn(['new', 'account_id']) !== action.account.get('id')) {
|
||||||
map.setIn(['new', 'status_ids'], action.status ? ImmutableSet([action.status.getIn(['reblog', 'id'], action.status.get('id'))]) : ImmutableSet());
|
map.setIn(['new', 'status_ids'], action.status ? ImmutableSet([action.status.getIn(['reblog', 'id'], action.status.get('id'))]) : ImmutableSet());
|
||||||
map.setIn(['new', 'comment'], '');
|
map.setIn(['new', 'comment'], '');
|
||||||
} else {
|
} else if (action.status) {
|
||||||
map.updateIn(['new', 'status_ids'], ImmutableSet(), set => set.add(action.status.getIn(['reblog', 'id'], action.status.get('id'))));
|
map.updateIn(['new', 'status_ids'], ImmutableSet(), set => set.add(action.status.getIn(['reblog', 'id'], action.status.get('id'))));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@@ -2,10 +2,15 @@ import {
|
|||||||
FAVOURITED_STATUSES_FETCH_SUCCESS,
|
FAVOURITED_STATUSES_FETCH_SUCCESS,
|
||||||
FAVOURITED_STATUSES_EXPAND_SUCCESS,
|
FAVOURITED_STATUSES_EXPAND_SUCCESS,
|
||||||
} from '../actions/favourites';
|
} from '../actions/favourites';
|
||||||
|
import {
|
||||||
|
PINNED_STATUSES_FETCH_SUCCESS,
|
||||||
|
} from '../actions/pin_statuses';
|
||||||
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
||||||
import {
|
import {
|
||||||
FAVOURITE_SUCCESS,
|
FAVOURITE_SUCCESS,
|
||||||
UNFAVOURITE_SUCCESS,
|
UNFAVOURITE_SUCCESS,
|
||||||
|
PIN_SUCCESS,
|
||||||
|
UNPIN_SUCCESS,
|
||||||
} from '../actions/interactions';
|
} from '../actions/interactions';
|
||||||
|
|
||||||
const initialState = ImmutableMap({
|
const initialState = ImmutableMap({
|
||||||
@@ -14,6 +19,11 @@ const initialState = ImmutableMap({
|
|||||||
loaded: false,
|
loaded: false,
|
||||||
items: ImmutableList(),
|
items: ImmutableList(),
|
||||||
}),
|
}),
|
||||||
|
pins: ImmutableMap({
|
||||||
|
next: null,
|
||||||
|
loaded: false,
|
||||||
|
items: ImmutableList(),
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
const normalizeList = (state, listType, statuses, next) => {
|
const normalizeList = (state, listType, statuses, next) => {
|
||||||
@@ -53,6 +63,12 @@ export default function statusLists(state = initialState, action) {
|
|||||||
return prependOneToList(state, 'favourites', action.status);
|
return prependOneToList(state, 'favourites', action.status);
|
||||||
case UNFAVOURITE_SUCCESS:
|
case UNFAVOURITE_SUCCESS:
|
||||||
return removeOneFromList(state, 'favourites', action.status);
|
return removeOneFromList(state, 'favourites', action.status);
|
||||||
|
case PINNED_STATUSES_FETCH_SUCCESS:
|
||||||
|
return normalizeList(state, 'pins', action.statuses, action.next);
|
||||||
|
case PIN_SUCCESS:
|
||||||
|
return prependOneToList(state, 'pins', action.status);
|
||||||
|
case UNPIN_SUCCESS:
|
||||||
|
return removeOneFromList(state, 'pins', action.status);
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
@@ -36,6 +36,9 @@ import {
|
|||||||
FAVOURITED_STATUSES_FETCH_SUCCESS,
|
FAVOURITED_STATUSES_FETCH_SUCCESS,
|
||||||
FAVOURITED_STATUSES_EXPAND_SUCCESS,
|
FAVOURITED_STATUSES_EXPAND_SUCCESS,
|
||||||
} from '../actions/favourites';
|
} from '../actions/favourites';
|
||||||
|
import {
|
||||||
|
PINNED_STATUSES_FETCH_SUCCESS,
|
||||||
|
} from '../actions/pin_statuses';
|
||||||
import { SEARCH_FETCH_SUCCESS } from '../actions/search';
|
import { SEARCH_FETCH_SUCCESS } from '../actions/search';
|
||||||
import emojify from '../emoji';
|
import emojify from '../emoji';
|
||||||
import { Map as ImmutableMap, fromJS } from 'immutable';
|
import { Map as ImmutableMap, fromJS } from 'immutable';
|
||||||
@@ -138,6 +141,7 @@ export default function statuses(state = initialState, action) {
|
|||||||
case NOTIFICATIONS_EXPAND_SUCCESS:
|
case NOTIFICATIONS_EXPAND_SUCCESS:
|
||||||
case FAVOURITED_STATUSES_FETCH_SUCCESS:
|
case FAVOURITED_STATUSES_FETCH_SUCCESS:
|
||||||
case FAVOURITED_STATUSES_EXPAND_SUCCESS:
|
case FAVOURITED_STATUSES_EXPAND_SUCCESS:
|
||||||
|
case PINNED_STATUSES_FETCH_SUCCESS:
|
||||||
case SEARCH_FETCH_SUCCESS:
|
case SEARCH_FETCH_SUCCESS:
|
||||||
return normalizeStatuses(state, action.statuses);
|
return normalizeStatuses(state, action.statuses);
|
||||||
case TIMELINE_DELETE:
|
case TIMELINE_DELETE:
|
||||||
|
@@ -1,4 +1,21 @@
|
|||||||
import loadPolyfills from '../mastodon/load_polyfills';
|
import loadPolyfills from '../mastodon/load_polyfills';
|
||||||
|
import ready from '../mastodon/ready';
|
||||||
|
|
||||||
|
window.addEventListener('message', e => {
|
||||||
|
const data = e.data || {};
|
||||||
|
|
||||||
|
if (!window.parent || data.type !== 'setHeight') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ready(() => {
|
||||||
|
window.parent.postMessage({
|
||||||
|
type: 'setHeight',
|
||||||
|
id: data.id,
|
||||||
|
height: document.getElementsByTagName('html')[0].scrollHeight,
|
||||||
|
}, '*');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
function main() {
|
function main() {
|
||||||
const { length } = require('stringz');
|
const { length } = require('stringz');
|
||||||
@@ -6,13 +23,13 @@ function main() {
|
|||||||
const { delegate } = require('rails-ujs');
|
const { delegate } = require('rails-ujs');
|
||||||
const emojify = require('../mastodon/emoji').default;
|
const emojify = require('../mastodon/emoji').default;
|
||||||
const { getLocale } = require('../mastodon/locales');
|
const { getLocale } = require('../mastodon/locales');
|
||||||
const ready = require('../mastodon/ready').default;
|
|
||||||
|
|
||||||
const { localeData } = getLocale();
|
const { localeData } = getLocale();
|
||||||
|
|
||||||
localeData.forEach(IntlRelativeFormat.__addLocaleData);
|
localeData.forEach(IntlRelativeFormat.__addLocaleData);
|
||||||
|
|
||||||
ready(() => {
|
ready(() => {
|
||||||
const locale = document.documentElement.lang;
|
const locale = document.documentElement.lang;
|
||||||
|
|
||||||
const dateTimeFormat = new Intl.DateTimeFormat(locale, {
|
const dateTimeFormat = new Intl.DateTimeFormat(locale, {
|
||||||
year: 'numeric',
|
year: 'numeric',
|
||||||
month: 'long',
|
month: 'long',
|
||||||
@@ -20,6 +37,7 @@ function main() {
|
|||||||
hour: 'numeric',
|
hour: 'numeric',
|
||||||
minute: 'numeric',
|
minute: 'numeric',
|
||||||
});
|
});
|
||||||
|
|
||||||
const relativeFormat = new IntlRelativeFormat(locale);
|
const relativeFormat = new IntlRelativeFormat(locale);
|
||||||
|
|
||||||
[].forEach.call(document.querySelectorAll('.emojify'), (content) => {
|
[].forEach.call(document.querySelectorAll('.emojify'), (content) => {
|
||||||
@@ -29,12 +47,14 @@ function main() {
|
|||||||
[].forEach.call(document.querySelectorAll('time.formatted'), (content) => {
|
[].forEach.call(document.querySelectorAll('time.formatted'), (content) => {
|
||||||
const datetime = new Date(content.getAttribute('datetime'));
|
const datetime = new Date(content.getAttribute('datetime'));
|
||||||
const formattedDate = dateTimeFormat.format(datetime);
|
const formattedDate = dateTimeFormat.format(datetime);
|
||||||
|
|
||||||
content.title = formattedDate;
|
content.title = formattedDate;
|
||||||
content.textContent = formattedDate;
|
content.textContent = formattedDate;
|
||||||
});
|
});
|
||||||
|
|
||||||
[].forEach.call(document.querySelectorAll('time.time-ago'), (content) => {
|
[].forEach.call(document.querySelectorAll('time.time-ago'), (content) => {
|
||||||
const datetime = new Date(content.getAttribute('datetime'));
|
const datetime = new Date(content.getAttribute('datetime'));
|
||||||
|
|
||||||
content.title = dateTimeFormat.format(datetime);
|
content.title = dateTimeFormat.format(datetime);
|
||||||
content.textContent = relativeFormat.format(datetime);
|
content.textContent = relativeFormat.format(datetime);
|
||||||
});
|
});
|
||||||
@@ -45,10 +65,6 @@ function main() {
|
|||||||
window.open(e.target.href, 'mastodon-intent', 'width=400,height=400,resizable=no,menubar=no,status=no,scrollbars=yes');
|
window.open(e.target.href, 'mastodon-intent', 'width=400,height=400,resizable=no,menubar=no,status=no,scrollbars=yes');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
if (window.parent) {
|
|
||||||
window.parent.postMessage(['setHeight', document.getElementsByTagName('html')[0].scrollHeight], '*');
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
delegate(document, '.video-player video', 'click', ({ target }) => {
|
delegate(document, '.video-player video', 'click', ({ target }) => {
|
||||||
@@ -77,6 +93,7 @@ function main() {
|
|||||||
|
|
||||||
delegate(document, '.status__content__spoiler-link', 'click', ({ target }) => {
|
delegate(document, '.status__content__spoiler-link', 'click', ({ target }) => {
|
||||||
const contentEl = target.parentNode.parentNode.querySelector('.e-content');
|
const contentEl = target.parentNode.parentNode.querySelector('.e-content');
|
||||||
|
|
||||||
if (contentEl.style.display === 'block') {
|
if (contentEl.style.display === 'block') {
|
||||||
contentEl.style.display = 'none';
|
contentEl.style.display = 'none';
|
||||||
target.parentNode.style.marginBottom = 0;
|
target.parentNode.style.marginBottom = 0;
|
||||||
@@ -84,11 +101,13 @@ function main() {
|
|||||||
contentEl.style.display = 'block';
|
contentEl.style.display = 'block';
|
||||||
target.parentNode.style.marginBottom = null;
|
target.parentNode.style.marginBottom = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
delegate(document, '.account_display_name', 'input', ({ target }) => {
|
delegate(document, '.account_display_name', 'input', ({ target }) => {
|
||||||
const nameCounter = document.querySelector('.name-counter');
|
const nameCounter = document.querySelector('.name-counter');
|
||||||
|
|
||||||
if (nameCounter) {
|
if (nameCounter) {
|
||||||
nameCounter.textContent = 30 - length(target.value);
|
nameCounter.textContent = 30 - length(target.value);
|
||||||
}
|
}
|
||||||
@@ -96,6 +115,7 @@ function main() {
|
|||||||
|
|
||||||
delegate(document, '.account_note', 'input', ({ target }) => {
|
delegate(document, '.account_note', 'input', ({ target }) => {
|
||||||
const noteCounter = document.querySelector('.note-counter');
|
const noteCounter = document.querySelector('.note-counter');
|
||||||
|
|
||||||
if (noteCounter) {
|
if (noteCounter) {
|
||||||
noteCounter.textContent = 160 - length(target.value);
|
noteCounter.textContent = 160 - length(target.value);
|
||||||
}
|
}
|
||||||
@@ -105,6 +125,7 @@ function main() {
|
|||||||
const avatar = document.querySelector('.card.compact .avatar img');
|
const avatar = document.querySelector('.card.compact .avatar img');
|
||||||
const [file] = target.files || [];
|
const [file] = target.files || [];
|
||||||
const url = URL.createObjectURL(file);
|
const url = URL.createObjectURL(file);
|
||||||
|
|
||||||
avatar.src = url;
|
avatar.src = url;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -112,6 +133,7 @@ function main() {
|
|||||||
const header = document.querySelector('.card.compact');
|
const header = document.querySelector('.card.compact');
|
||||||
const [file] = target.files || [];
|
const [file] = target.files || [];
|
||||||
const url = URL.createObjectURL(file);
|
const url = URL.createObjectURL(file);
|
||||||
|
|
||||||
header.style.backgroundImage = `url(${url})`;
|
header.style.backgroundImage = `url(${url})`;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -190,11 +190,15 @@
|
|||||||
|
|
||||||
.filters {
|
.filters {
|
||||||
display: flex;
|
display: flex;
|
||||||
margin-bottom: 20px;
|
flex-wrap: wrap;
|
||||||
|
|
||||||
.filter-subset {
|
.filter-subset {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
margin-right: 40px;
|
margin: 0 40px 10px 0;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
|
@@ -45,6 +45,7 @@ body {
|
|||||||
&.embed {
|
&.embed {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
padding-bottom: 0;
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@@ -1622,6 +1622,10 @@
|
|||||||
&:hover {
|
&:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
padding: 0 15px 0 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.column-back-button__icon {
|
.column-back-button__icon {
|
||||||
@@ -3801,6 +3805,8 @@ button.icon-button.active i.fa-retweet {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
border: 0;
|
||||||
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.media-spoiler-video-play-icon {
|
.media-spoiler-video-play-icon {
|
||||||
@@ -3966,41 +3972,10 @@ noscript {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.embed-modal__html {
|
|
||||||
color: $ui-secondary-color;
|
|
||||||
outline: 0;
|
|
||||||
box-sizing: border-box;
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
border: none;
|
|
||||||
padding: 10px;
|
|
||||||
font-family: 'mastodon-font-monospace', monospace;
|
|
||||||
background: $ui-base-color;
|
|
||||||
color: $ui-primary-color;
|
|
||||||
font-size: 14px;
|
|
||||||
margin: 0;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
|
|
||||||
&::-moz-focus-inner {
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&::-moz-focus-inner,
|
|
||||||
&:focus,
|
|
||||||
&:active {
|
|
||||||
outline: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
background: lighten($ui-base-color, 4%);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 600px) {
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.embed-modal {
|
.embed-modal {
|
||||||
|
max-width: 80vw;
|
||||||
|
max-height: 80vh;
|
||||||
|
|
||||||
h4 {
|
h4 {
|
||||||
padding: 30px;
|
padding: 30px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
@@ -4008,18 +3983,52 @@ noscript {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hint {
|
.embed-modal__container {
|
||||||
margin-bottom: 15px;
|
padding: 10px;
|
||||||
|
|
||||||
|
.hint {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed-modal__html {
|
||||||
|
color: $ui-secondary-color;
|
||||||
|
outline: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
border: none;
|
||||||
|
padding: 10px;
|
||||||
|
font-family: 'mastodon-font-monospace', monospace;
|
||||||
|
background: $ui-base-color;
|
||||||
|
color: $ui-primary-color;
|
||||||
|
font-size: 14px;
|
||||||
|
margin: 0;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
|
||||||
|
&::-moz-focus-inner {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-moz-focus-inner,
|
||||||
|
&:focus,
|
||||||
|
&:active {
|
||||||
|
outline: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
background: lighten($ui-base-color, 4%);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 600px) {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed-modal__iframe {
|
||||||
|
width: 400px;
|
||||||
|
max-width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.embed-modal__container {
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.embed-modal__iframe {
|
|
||||||
width: 100%;
|
|
||||||
min-width: 400px;
|
|
||||||
overflow: hidden;
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
|
@@ -403,51 +403,54 @@
|
|||||||
|
|
||||||
.embed {
|
.embed {
|
||||||
.activity-stream {
|
.activity-stream {
|
||||||
border-radius: 4px;
|
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
|
|
||||||
.entry {
|
.entry {
|
||||||
&:last-child {
|
|
||||||
border-radius: 0 0 4px 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:first-child {
|
.detailed-status.light {
|
||||||
border-radius: 4px 4px 0 0;
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
&:last-child {
|
.detailed-status__display-name {
|
||||||
border-radius: 4px;
|
flex: 1;
|
||||||
|
margin: 0 5px 15px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button.button-secondary.logo-button {
|
||||||
|
flex: 0 auto;
|
||||||
|
font-size: 14px;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
width: 20px;
|
||||||
|
height: auto;
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-right: 5px;
|
||||||
|
|
||||||
|
path:first-child {
|
||||||
|
fill: $ui-primary-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
path:last-child {
|
||||||
|
fill: $simple-background-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active,
|
||||||
|
&:focus,
|
||||||
|
&:hover {
|
||||||
|
svg path:first-child {
|
||||||
|
fill: lighten($ui-primary-color, 4%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.status__content,
|
||||||
|
.detailed-status__meta {
|
||||||
|
flex: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.button.button-secondary.logo-button {
|
|
||||||
position: absolute;
|
|
||||||
right: 14px;
|
|
||||||
top: 14px;
|
|
||||||
font-size: 14px;
|
|
||||||
|
|
||||||
svg {
|
|
||||||
width: 20px;
|
|
||||||
height: auto;
|
|
||||||
vertical-align: middle;
|
|
||||||
margin-right: 5px;
|
|
||||||
|
|
||||||
path:first-child {
|
|
||||||
fill: $ui-primary-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
path:last-child {
|
|
||||||
fill: $simple-background-color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active,
|
|
||||||
&:focus,
|
|
||||||
&:hover {
|
|
||||||
svg path:first-child {
|
|
||||||
fill: lighten($ui-primary-color, 4%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@@ -3,7 +3,6 @@
|
|||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
border-spacing: 0;
|
border-spacing: 0;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
margin-bottom: 20px;
|
|
||||||
|
|
||||||
th,
|
th,
|
||||||
td {
|
td {
|
||||||
@@ -43,19 +42,17 @@
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.inline-table {
|
&.inline-table > tbody > tr:nth-child(odd) > td,
|
||||||
td,
|
&.inline-table > tbody > tr:nth-child(odd) > th {
|
||||||
th {
|
background: transparent;
|
||||||
padding: 8px 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
& > tbody > tr:nth-child(odd) > td,
|
|
||||||
& > tbody > tr:nth-child(odd) > th {
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.table-wrapper {
|
||||||
|
overflow: auto;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
samp {
|
samp {
|
||||||
font-family: 'mastodon-font-monospace', monospace;
|
font-family: 'mastodon-font-monospace', monospace;
|
||||||
}
|
}
|
||||||
|
@@ -33,7 +33,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
|
|||||||
def status_params
|
def status_params
|
||||||
{
|
{
|
||||||
uri: @object['id'],
|
uri: @object['id'],
|
||||||
url: @object['url'] || @object['id'],
|
url: object_url || @object['id'],
|
||||||
account: @account,
|
account: @account,
|
||||||
text: text_from_content || '',
|
text: text_from_content || '',
|
||||||
language: language_from_content,
|
language: language_from_content,
|
||||||
@@ -147,6 +147,16 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
|
|||||||
@object['contentMap'].keys.first
|
@object['contentMap'].keys.first
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def object_url
|
||||||
|
return if @object['url'].blank?
|
||||||
|
|
||||||
|
value = first_of_value(@object['url'])
|
||||||
|
|
||||||
|
return value if value.is_a?(String)
|
||||||
|
|
||||||
|
value['href']
|
||||||
|
end
|
||||||
|
|
||||||
def language_map?
|
def language_map?
|
||||||
@object['contentMap'].is_a?(Hash) && !@object['contentMap'].empty?
|
@object['contentMap'].is_a?(Hash) && !@object['contentMap'].empty?
|
||||||
end
|
end
|
||||||
|
@@ -96,12 +96,14 @@ class ActivityPub::TagManager
|
|||||||
when 'Account'
|
when 'Account'
|
||||||
klass.find_local(uri_to_local_id(uri, :username))
|
klass.find_local(uri_to_local_id(uri, :username))
|
||||||
else
|
else
|
||||||
klass.find_by(id: uri_to_local_id(uri))
|
StatusFinder.new(uri).status
|
||||||
end
|
end
|
||||||
elsif ::TagManager.instance.local_id?(uri)
|
elsif ::TagManager.instance.local_id?(uri)
|
||||||
klass.find_by(id: ::TagManager.instance.unique_tag_to_local_id(uri, klass.to_s))
|
klass.find_by(id: ::TagManager.instance.unique_tag_to_local_id(uri, klass.to_s))
|
||||||
else
|
else
|
||||||
klass.find_by(uri: uri.split('#').first)
|
klass.find_by(uri: uri.split('#').first)
|
||||||
end
|
end
|
||||||
|
rescue ActiveRecord::RecordNotFound
|
||||||
|
nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@@ -20,7 +20,16 @@ class LanguageDetector
|
|||||||
private
|
private
|
||||||
|
|
||||||
def detected_language_code
|
def detected_language_code
|
||||||
result.language.to_sym if detected_language_reliable?
|
iso6391(result.language).to_sym if detected_language_reliable?
|
||||||
|
end
|
||||||
|
|
||||||
|
def iso6391(bcp47)
|
||||||
|
iso639 = bcp47.split('-').first
|
||||||
|
|
||||||
|
# CLD3 returns grandfathered language code for Hebrew
|
||||||
|
return 'he' if iso639 == 'iw'
|
||||||
|
|
||||||
|
ISO_639.find(iso639).alpha2
|
||||||
end
|
end
|
||||||
|
|
||||||
def result
|
def result
|
||||||
|
@@ -65,7 +65,7 @@ class OStatus::AtomSerializer
|
|||||||
|
|
||||||
add_namespaces(entry) if root
|
add_namespaces(entry) if root
|
||||||
|
|
||||||
append_element(entry, 'id', TagManager.instance.unique_tag(stream_entry.created_at, stream_entry.activity_id, stream_entry.activity_type))
|
append_element(entry, 'id', TagManager.instance.uri_for(stream_entry.status))
|
||||||
append_element(entry, 'published', stream_entry.created_at.iso8601)
|
append_element(entry, 'published', stream_entry.created_at.iso8601)
|
||||||
append_element(entry, 'updated', stream_entry.updated_at.iso8601)
|
append_element(entry, 'updated', stream_entry.updated_at.iso8601)
|
||||||
append_element(entry, 'title', stream_entry&.status&.title || "#{stream_entry.account.acct} deleted status")
|
append_element(entry, 'title', stream_entry&.status&.title || "#{stream_entry.account.acct} deleted status")
|
||||||
@@ -86,7 +86,7 @@ class OStatus::AtomSerializer
|
|||||||
serialize_status_attributes(entry, stream_entry.status)
|
serialize_status_attributes(entry, stream_entry.status)
|
||||||
end
|
end
|
||||||
|
|
||||||
append_element(entry, 'link', nil, rel: :alternate, type: 'text/html', href: account_stream_entry_url(stream_entry.account, stream_entry))
|
append_element(entry, 'link', nil, rel: :alternate, type: 'text/html', href: TagManager.instance.url_for(stream_entry.status))
|
||||||
append_element(entry, 'link', nil, rel: :self, type: 'application/atom+xml', href: account_stream_entry_url(stream_entry.account, stream_entry, format: 'atom'))
|
append_element(entry, 'link', nil, rel: :self, type: 'application/atom+xml', href: account_stream_entry_url(stream_entry.account, stream_entry, format: 'atom'))
|
||||||
append_element(entry, 'thr:in-reply-to', nil, ref: TagManager.instance.uri_for(stream_entry.thread), href: TagManager.instance.url_for(stream_entry.thread)) if stream_entry.threaded?
|
append_element(entry, 'thr:in-reply-to', nil, ref: TagManager.instance.uri_for(stream_entry.thread), href: TagManager.instance.url_for(stream_entry.thread)) if stream_entry.threaded?
|
||||||
append_element(entry, 'ostatus:conversation', nil, ref: conversation_uri(stream_entry.status.conversation)) unless stream_entry&.status&.conversation_id.nil?
|
append_element(entry, 'ostatus:conversation', nil, ref: conversation_uri(stream_entry.status.conversation)) unless stream_entry&.status&.conversation_id.nil?
|
||||||
|
@@ -49,12 +49,17 @@ class TagManager
|
|||||||
|
|
||||||
def unique_tag_to_local_id(tag, expected_type)
|
def unique_tag_to_local_id(tag, expected_type)
|
||||||
return nil unless local_id?(tag)
|
return nil unless local_id?(tag)
|
||||||
matches = Regexp.new("objectId=([\\d]+):objectType=#{expected_type}").match(tag)
|
|
||||||
return matches[1] unless matches.nil?
|
if ActivityPub::TagManager.instance.local_uri?(tag)
|
||||||
|
ActivityPub::TagManager.instance.uri_to_local_id(tag)
|
||||||
|
else
|
||||||
|
matches = Regexp.new("objectId=([\\d]+):objectType=#{expected_type}").match(tag)
|
||||||
|
return matches[1] unless matches.nil?
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def local_id?(id)
|
def local_id?(id)
|
||||||
id.start_with?("tag:#{Rails.configuration.x.local_domain}")
|
id.start_with?("tag:#{Rails.configuration.x.local_domain}") || ActivityPub::TagManager.instance.local_uri?(id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def web_domain?(domain)
|
def web_domain?(domain)
|
||||||
@@ -92,7 +97,7 @@ class TagManager
|
|||||||
when :person
|
when :person
|
||||||
account_url(target)
|
account_url(target)
|
||||||
when :note, :comment, :activity
|
when :note, :comment, :activity
|
||||||
unique_tag(target.created_at, target.id, 'Status')
|
target.uri || unique_tag(target.created_at, target.id, 'Status')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@@ -24,6 +24,8 @@ class Form::AdminSettings
|
|||||||
:open_deletion=,
|
:open_deletion=,
|
||||||
:timeline_preview,
|
:timeline_preview,
|
||||||
:timeline_preview=,
|
:timeline_preview=,
|
||||||
|
:bootstrap_timeline_accounts,
|
||||||
|
:bootstrap_timeline_accounts=,
|
||||||
to: Setting
|
to: Setting
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
@@ -22,6 +22,8 @@ class Report < ApplicationRecord
|
|||||||
scope :unresolved, -> { where(action_taken: false) }
|
scope :unresolved, -> { where(action_taken: false) }
|
||||||
scope :resolved, -> { where(action_taken: true) }
|
scope :resolved, -> { where(action_taken: true) }
|
||||||
|
|
||||||
|
validates :comment, length: { maximum: 1000 }
|
||||||
|
|
||||||
def statuses
|
def statuses
|
||||||
Status.where(id: status_ids).includes(:account, :media_attachments, :mentions)
|
Status.where(id: status_ids).includes(:account, :media_attachments, :mentions)
|
||||||
end
|
end
|
||||||
|
@@ -22,6 +22,7 @@
|
|||||||
# reblogs_count :integer default(0), not null
|
# reblogs_count :integer default(0), not null
|
||||||
# language :string
|
# language :string
|
||||||
# conversation_id :integer
|
# conversation_id :integer
|
||||||
|
# local :boolean
|
||||||
#
|
#
|
||||||
|
|
||||||
class Status < ApplicationRecord
|
class Status < ApplicationRecord
|
||||||
@@ -62,8 +63,8 @@ class Status < ApplicationRecord
|
|||||||
default_scope { recent }
|
default_scope { recent }
|
||||||
|
|
||||||
scope :recent, -> { reorder(id: :desc) }
|
scope :recent, -> { reorder(id: :desc) }
|
||||||
scope :remote, -> { where.not(uri: nil) }
|
scope :remote, -> { where(local: false).or(where.not(uri: nil)) }
|
||||||
scope :local, -> { where(uri: nil) }
|
scope :local, -> { where(local: true).or(where(uri: nil)) }
|
||||||
|
|
||||||
scope :without_replies, -> { where('statuses.reply = FALSE OR statuses.in_reply_to_account_id = statuses.account_id') }
|
scope :without_replies, -> { where('statuses.reply = FALSE OR statuses.in_reply_to_account_id = statuses.account_id') }
|
||||||
scope :without_reblogs, -> { where('statuses.reblog_of_id IS NULL') }
|
scope :without_reblogs, -> { where('statuses.reblog_of_id IS NULL') }
|
||||||
@@ -84,7 +85,7 @@ class Status < ApplicationRecord
|
|||||||
end
|
end
|
||||||
|
|
||||||
def local?
|
def local?
|
||||||
uri.nil?
|
attributes['local'] || uri.nil?
|
||||||
end
|
end
|
||||||
|
|
||||||
def reblog?
|
def reblog?
|
||||||
@@ -131,11 +132,14 @@ class Status < ApplicationRecord
|
|||||||
!sensitive? && media_attachments.any?
|
!sensitive? && media_attachments.any?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
after_create :store_uri, if: :local?
|
||||||
|
|
||||||
before_validation :prepare_contents, if: :local?
|
before_validation :prepare_contents, if: :local?
|
||||||
before_validation :set_reblog
|
before_validation :set_reblog
|
||||||
before_validation :set_visibility
|
before_validation :set_visibility
|
||||||
before_validation :set_conversation
|
before_validation :set_conversation
|
||||||
before_validation :set_sensitivity
|
before_validation :set_sensitivity
|
||||||
|
before_validation :set_local
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
def not_in_filtered_languages(account)
|
def not_in_filtered_languages(account)
|
||||||
@@ -253,6 +257,10 @@ class Status < ApplicationRecord
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def store_uri
|
||||||
|
update_attribute(:uri, ActivityPub::TagManager.instance.uri_for(self)) if uri.nil?
|
||||||
|
end
|
||||||
|
|
||||||
def prepare_contents
|
def prepare_contents
|
||||||
text&.strip!
|
text&.strip!
|
||||||
spoiler_text&.strip!
|
spoiler_text&.strip!
|
||||||
@@ -292,4 +300,8 @@ class Status < ApplicationRecord
|
|||||||
thread.account_id
|
thread.account_id
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_local
|
||||||
|
self.local = account.local?
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@@ -4,12 +4,12 @@ class AccountRelationshipsPresenter
|
|||||||
attr_reader :following, :followed_by, :blocking,
|
attr_reader :following, :followed_by, :blocking,
|
||||||
:muting, :requested, :domain_blocking
|
:muting, :requested, :domain_blocking
|
||||||
|
|
||||||
def initialize(account_ids, current_account_id)
|
def initialize(account_ids, current_account_id, options = {})
|
||||||
@following = Account.following_map(account_ids, current_account_id)
|
@following = Account.following_map(account_ids, current_account_id).merge(options[:following_map] || {})
|
||||||
@followed_by = Account.followed_by_map(account_ids, current_account_id)
|
@followed_by = Account.followed_by_map(account_ids, current_account_id).merge(options[:followed_by_map] || {})
|
||||||
@blocking = Account.blocking_map(account_ids, current_account_id)
|
@blocking = Account.blocking_map(account_ids, current_account_id).merge(options[:blocking_map] || {})
|
||||||
@muting = Account.muting_map(account_ids, current_account_id)
|
@muting = Account.muting_map(account_ids, current_account_id).merge(options[:muting_map] || {})
|
||||||
@requested = Account.requested_map(account_ids, current_account_id)
|
@requested = Account.requested_map(account_ids, current_account_id).merge(options[:requested_map] || {})
|
||||||
@domain_blocking = Account.domain_blocking_map(account_ids, current_account_id)
|
@domain_blocking = Account.domain_blocking_map(account_ids, current_account_id).merge(options[:domain_blocking_map] || {})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@@ -4,7 +4,7 @@ class ActivityPub::ActorSerializer < ActiveModel::Serializer
|
|||||||
include RoutingHelper
|
include RoutingHelper
|
||||||
|
|
||||||
attributes :id, :type, :following, :followers,
|
attributes :id, :type, :following, :followers,
|
||||||
:inbox, :outbox, :shared_inbox,
|
:inbox, :outbox,
|
||||||
:preferred_username, :name, :summary,
|
:preferred_username, :name, :summary,
|
||||||
:url, :manually_approves_followers
|
:url, :manually_approves_followers
|
||||||
|
|
||||||
@@ -24,6 +24,18 @@ class ActivityPub::ActorSerializer < ActiveModel::Serializer
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class EndpointsSerializer < ActiveModel::Serializer
|
||||||
|
include RoutingHelper
|
||||||
|
|
||||||
|
attributes :shared_inbox
|
||||||
|
|
||||||
|
def shared_inbox
|
||||||
|
inbox_url
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
has_one :endpoints, serializer: EndpointsSerializer
|
||||||
|
|
||||||
has_one :icon, serializer: ImageSerializer, if: :avatar_exists?
|
has_one :icon, serializer: ImageSerializer, if: :avatar_exists?
|
||||||
has_one :image, serializer: ImageSerializer, if: :header_exists?
|
has_one :image, serializer: ImageSerializer, if: :header_exists?
|
||||||
|
|
||||||
@@ -51,8 +63,8 @@ class ActivityPub::ActorSerializer < ActiveModel::Serializer
|
|||||||
account_outbox_url(object)
|
account_outbox_url(object)
|
||||||
end
|
end
|
||||||
|
|
||||||
def shared_inbox
|
def endpoints
|
||||||
inbox_url
|
object
|
||||||
end
|
end
|
||||||
|
|
||||||
def preferred_username
|
def preferred_username
|
||||||
|
@@ -40,13 +40,12 @@ class OEmbedSerializer < ActiveModel::Serializer
|
|||||||
attributes = {
|
attributes = {
|
||||||
src: embed_short_account_status_url(object.account, object),
|
src: embed_short_account_status_url(object.account, object),
|
||||||
class: 'mastodon-embed',
|
class: 'mastodon-embed',
|
||||||
frameborder: '0',
|
style: 'max-width: 100%; border: 0',
|
||||||
scrolling: 'no',
|
|
||||||
width: width,
|
width: width,
|
||||||
height: height,
|
height: height,
|
||||||
}
|
}
|
||||||
|
|
||||||
content_tag :iframe, nil, attributes
|
content_tag(:iframe, nil, attributes) + content_tag(:script, nil, src: full_asset_url('embed.js'), async: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
def width
|
def width
|
||||||
|
@@ -6,13 +6,14 @@ class ActivityPub::ProcessAccountService < BaseService
|
|||||||
# Should be called with confirmed valid JSON
|
# Should be called with confirmed valid JSON
|
||||||
# and WebFinger-resolved username and domain
|
# and WebFinger-resolved username and domain
|
||||||
def call(username, domain, json)
|
def call(username, domain, json)
|
||||||
return unless json['inbox'].present?
|
return if json['inbox'].blank?
|
||||||
|
|
||||||
@json = json
|
@json = json
|
||||||
@uri = @json['id']
|
@uri = @json['id']
|
||||||
@username = username
|
@username = username
|
||||||
@domain = domain
|
@domain = domain
|
||||||
@account = Account.find_by(uri: @uri)
|
@account = Account.find_by(uri: @uri)
|
||||||
|
@collections = {}
|
||||||
|
|
||||||
create_account if @account.nil?
|
create_account if @account.nil?
|
||||||
upgrade_account if @account.ostatus?
|
upgrade_account if @account.ostatus?
|
||||||
@@ -42,16 +43,19 @@ class ActivityPub::ProcessAccountService < BaseService
|
|||||||
@account.protocol = :activitypub
|
@account.protocol = :activitypub
|
||||||
@account.inbox_url = @json['inbox'] || ''
|
@account.inbox_url = @json['inbox'] || ''
|
||||||
@account.outbox_url = @json['outbox'] || ''
|
@account.outbox_url = @json['outbox'] || ''
|
||||||
@account.shared_inbox_url = @json['sharedInbox'] || ''
|
@account.shared_inbox_url = (@json['endpoints'].is_a?(Hash) ? @json['endpoints']['sharedInbox'] : @json['sharedInbox']) || ''
|
||||||
@account.followers_url = @json['followers'] || ''
|
@account.followers_url = @json['followers'] || ''
|
||||||
@account.url = @json['url'] || @uri
|
@account.url = url || @uri
|
||||||
@account.display_name = @json['name'] || ''
|
@account.display_name = @json['name'] || ''
|
||||||
@account.note = @json['summary'] || ''
|
@account.note = @json['summary'] || ''
|
||||||
@account.avatar_remote_url = image_url('icon')
|
@account.avatar_remote_url = image_url('icon') unless skip_download?
|
||||||
@account.header_remote_url = image_url('image')
|
@account.header_remote_url = image_url('image') unless skip_download?
|
||||||
@account.public_key = public_key || ''
|
@account.public_key = public_key || ''
|
||||||
@account.locked = @json['manuallyApprovesFollowers'] || false
|
@account.locked = @json['manuallyApprovesFollowers'] || false
|
||||||
@account.save!
|
@account.statuses_count = outbox_total_items if outbox_total_items.present?
|
||||||
|
@account.following_count = following_total_items if following_total_items.present?
|
||||||
|
@account.followers_count = followers_total_items if followers_total_items.present?
|
||||||
|
@account.save_with_optional_media!
|
||||||
end
|
end
|
||||||
|
|
||||||
def upgrade_account
|
def upgrade_account
|
||||||
@@ -62,7 +66,7 @@ class ActivityPub::ProcessAccountService < BaseService
|
|||||||
value = first_of_value(@json[key])
|
value = first_of_value(@json[key])
|
||||||
|
|
||||||
return if value.nil?
|
return if value.nil?
|
||||||
return @json[key]['url'] if @json[key].is_a?(Hash)
|
return value['url'] if value.is_a?(Hash)
|
||||||
|
|
||||||
image = fetch_resource(value)
|
image = fetch_resource(value)
|
||||||
image['url'] if image
|
image['url'] if image
|
||||||
@@ -78,6 +82,43 @@ class ActivityPub::ProcessAccountService < BaseService
|
|||||||
key['publicKeyPem'] if key
|
key['publicKeyPem'] if key
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def url
|
||||||
|
return if @json['url'].blank?
|
||||||
|
|
||||||
|
value = first_of_value(@json['url'])
|
||||||
|
|
||||||
|
return value if value.is_a?(String)
|
||||||
|
|
||||||
|
value['href']
|
||||||
|
end
|
||||||
|
|
||||||
|
def outbox_total_items
|
||||||
|
collection_total_items('outbox')
|
||||||
|
end
|
||||||
|
|
||||||
|
def following_total_items
|
||||||
|
collection_total_items('following')
|
||||||
|
end
|
||||||
|
|
||||||
|
def followers_total_items
|
||||||
|
collection_total_items('followers')
|
||||||
|
end
|
||||||
|
|
||||||
|
def collection_total_items(type)
|
||||||
|
return if @json[type].blank?
|
||||||
|
return @collections[type] if @collections.key?(type)
|
||||||
|
|
||||||
|
collection = fetch_resource(@json[type])
|
||||||
|
|
||||||
|
@collections[type] = collection.is_a?(Hash) && collection['totalItems'].present? && collection['totalItems'].is_a?(Numeric) ? collection['totalItems'] : nil
|
||||||
|
rescue HTTP::Error, OpenSSL::SSL::SSLError
|
||||||
|
@collections[type] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def skip_download?
|
||||||
|
@account.suspended? || domain_block&.reject_media?
|
||||||
|
end
|
||||||
|
|
||||||
def auto_suspend?
|
def auto_suspend?
|
||||||
domain_block && domain_block.suspend?
|
domain_block && domain_block.suspend?
|
||||||
end
|
end
|
||||||
|
34
app/services/bootstrap_timeline_service.rb
Normal file
34
app/services/bootstrap_timeline_service.rb
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class BootstrapTimelineService < BaseService
|
||||||
|
def call(source_account)
|
||||||
|
bootstrap_timeline_accounts.each do |target_account|
|
||||||
|
FollowService.new.call(source_account, target_account)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def bootstrap_timeline_accounts
|
||||||
|
return @bootstrap_timeline_accounts if defined?(@bootstrap_timeline_accounts)
|
||||||
|
|
||||||
|
@bootstrap_timeline_accounts = bootstrap_timeline_accounts_usernames.empty? ? admin_accounts : local_unlocked_accounts(bootstrap_timeline_accounts_usernames)
|
||||||
|
end
|
||||||
|
|
||||||
|
def bootstrap_timeline_accounts_usernames
|
||||||
|
@bootstrap_timeline_accounts_usernames ||= (Setting.bootstrap_timeline_accounts || '').split(',').map { |str| str.strip.gsub(/\A@/, '') }.reject(&:blank?)
|
||||||
|
end
|
||||||
|
|
||||||
|
def admin_accounts
|
||||||
|
User.admins
|
||||||
|
.includes(:account)
|
||||||
|
.where(accounts: { locked: false })
|
||||||
|
.map(&:account)
|
||||||
|
end
|
||||||
|
|
||||||
|
def local_unlocked_accounts(usernames)
|
||||||
|
Account.local
|
||||||
|
.where(username: usernames)
|
||||||
|
.where(locked: false)
|
||||||
|
end
|
||||||
|
end
|
@@ -5,14 +5,14 @@ class FollowService < BaseService
|
|||||||
|
|
||||||
# Follow a remote user, notify remote user about the follow
|
# Follow a remote user, notify remote user about the follow
|
||||||
# @param [Account] source_account From which to follow
|
# @param [Account] source_account From which to follow
|
||||||
# @param [String] uri User URI to follow in the form of username@domain
|
# @param [String, Account] uri User URI to follow in the form of username@domain (or account record)
|
||||||
def call(source_account, uri)
|
def call(source_account, uri)
|
||||||
target_account = ResolveRemoteAccountService.new.call(uri)
|
target_account = uri.is_a?(Account) ? uri : ResolveRemoteAccountService.new.call(uri)
|
||||||
|
|
||||||
raise ActiveRecord::RecordNotFound if target_account.nil? || target_account.id == source_account.id || target_account.suspended?
|
raise ActiveRecord::RecordNotFound if target_account.nil? || target_account.id == source_account.id || target_account.suspended?
|
||||||
raise Mastodon::NotPermittedError if target_account.blocking?(source_account) || source_account.blocking?(target_account)
|
raise Mastodon::NotPermittedError if target_account.blocking?(source_account) || source_account.blocking?(target_account)
|
||||||
|
|
||||||
return if source_account.following?(target_account)
|
return if source_account.following?(target_account) || source_account.requested?(target_account)
|
||||||
|
|
||||||
if target_account.locked? || target_account.activitypub?
|
if target_account.locked? || target_account.activitypub?
|
||||||
request_follow(source_account, target_account)
|
request_follow(source_account, target_account)
|
||||||
|
@@ -27,9 +27,10 @@ class PostStatusService < BaseService
|
|||||||
thread: in_reply_to,
|
thread: in_reply_to,
|
||||||
sensitive: options[:sensitive],
|
sensitive: options[:sensitive],
|
||||||
spoiler_text: options[:spoiler_text] || '',
|
spoiler_text: options[:spoiler_text] || '',
|
||||||
visibility: options[:visibility],
|
visibility: options[:visibility] || account.user&.setting_default_privacy,
|
||||||
language: detect_language_for(text, account),
|
language: detect_language_for(text, account),
|
||||||
application: options[:application])
|
application: options[:application])
|
||||||
|
|
||||||
attach_media(status, media)
|
attach_media(status, media)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@@ -41,7 +41,7 @@ class ProcessMentionsService < BaseService
|
|||||||
NotifyService.new.call(mentioned_account, mention)
|
NotifyService.new.call(mentioned_account, mention)
|
||||||
elsif mentioned_account.ostatus? && (Rails.configuration.x.use_ostatus_privacy || !status.stream_entry.hidden?)
|
elsif mentioned_account.ostatus? && (Rails.configuration.x.use_ostatus_privacy || !status.stream_entry.hidden?)
|
||||||
NotificationWorker.perform_async(stream_entry_to_xml(status.stream_entry), status.account_id, mentioned_account.id)
|
NotificationWorker.perform_async(stream_entry_to_xml(status.stream_entry), status.account_id, mentioned_account.id)
|
||||||
elsif mentioned_account.activitypub? && !mentioned_account.following?(status.account)
|
elsif mentioned_account.activitypub?
|
||||||
ActivityPub::DeliveryWorker.perform_async(build_json(mention.status), mention.status.account_id, mentioned_account.inbox_url)
|
ActivityPub::DeliveryWorker.perform_async(build_json(mention.status), mention.status.account_id, mentioned_account.inbox_url)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@@ -4,16 +4,19 @@ class UnsubscribeService < BaseService
|
|||||||
def call(account)
|
def call(account)
|
||||||
return if account.hub_url.blank?
|
return if account.hub_url.blank?
|
||||||
|
|
||||||
@account = account
|
@account = account
|
||||||
@response = build_request.perform
|
|
||||||
|
|
||||||
Rails.logger.debug "PuSH unsubscribe for #{@account.acct} failed: #{@response.status}" unless @response.status.success?
|
begin
|
||||||
|
@response = build_request.perform
|
||||||
|
|
||||||
|
Rails.logger.debug "PuSH unsubscribe for #{@account.acct} failed: #{@response.status}" unless @response.status.success?
|
||||||
|
rescue HTTP::Error, OpenSSL::SSL::SSLError => e
|
||||||
|
Rails.logger.debug "PuSH unsubscribe for #{@account.acct} failed: #{e}"
|
||||||
|
end
|
||||||
|
|
||||||
@account.secret = ''
|
@account.secret = ''
|
||||||
@account.subscription_expires_at = nil
|
@account.subscription_expires_at = nil
|
||||||
@account.save!
|
@account.save!
|
||||||
rescue HTTP::Error, OpenSSL::SSL::SSLError
|
|
||||||
Rails.logger.debug "PuSH subscription request for #{@account.acct} could not be made due to HTTP or SSL error"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@@ -1,16 +1,17 @@
|
|||||||
%table.table
|
.table-wrapper
|
||||||
%tbody
|
%table.table
|
||||||
%tr
|
%tbody
|
||||||
%td= t('admin.accounts.show.created_reports')
|
|
||||||
%td= link_to pluralize(account.reports.count, t('admin.accounts.show.report')), admin_reports_path(account_id: account.id)
|
|
||||||
%tr
|
|
||||||
%td= t('admin.accounts.show.targeted_reports')
|
|
||||||
%td= link_to pluralize(account.targeted_reports.count, t('admin.accounts.show.report')), admin_reports_path(target_account_id: account.id)
|
|
||||||
- if account.silenced? || account.suspended?
|
|
||||||
%tr
|
%tr
|
||||||
%td= t('admin.accounts.moderation.title')
|
%td= t('admin.accounts.show.created_reports')
|
||||||
%td
|
%td= link_to pluralize(account.reports.count, t('admin.accounts.show.report')), admin_reports_path(account_id: account.id)
|
||||||
- if account.silenced?
|
%tr
|
||||||
%p= t('admin.accounts.moderation.silenced')
|
%td= t('admin.accounts.show.targeted_reports')
|
||||||
- if account.suspended?
|
%td= link_to pluralize(account.targeted_reports.count, t('admin.accounts.show.report')), admin_reports_path(target_account_id: account.id)
|
||||||
%p= t('admin.accounts.moderation.suspended')
|
- if account.silenced? || account.suspended?
|
||||||
|
%tr
|
||||||
|
%td= t('admin.accounts.moderation.title')
|
||||||
|
%td
|
||||||
|
- if account.silenced?
|
||||||
|
%p= t('admin.accounts.moderation.silenced')
|
||||||
|
- if account.suspended?
|
||||||
|
%p= t('admin.accounts.moderation.suspended')
|
||||||
|
@@ -50,16 +50,17 @@
|
|||||||
%button= t('admin.accounts.search')
|
%button= t('admin.accounts.search')
|
||||||
= link_to t('admin.accounts.reset'), admin_accounts_path, class: 'button negative'
|
= link_to t('admin.accounts.reset'), admin_accounts_path, class: 'button negative'
|
||||||
|
|
||||||
%table.table
|
.table-wrapper
|
||||||
%thead
|
%table.table
|
||||||
%tr
|
%thead
|
||||||
%th= t('admin.accounts.username')
|
%tr
|
||||||
%th= t('admin.accounts.domain')
|
%th= t('admin.accounts.username')
|
||||||
%th= t('admin.accounts.protocol')
|
%th= t('admin.accounts.domain')
|
||||||
%th= t('admin.accounts.confirmed')
|
%th= t('admin.accounts.protocol')
|
||||||
%th= fa_icon 'paper-plane-o'
|
%th= t('admin.accounts.confirmed')
|
||||||
%th
|
%th= fa_icon 'paper-plane-o'
|
||||||
%tbody
|
%th
|
||||||
= render @accounts
|
%tbody
|
||||||
|
= render @accounts
|
||||||
|
|
||||||
= paginate @accounts
|
= paginate @accounts
|
||||||
|
@@ -1,86 +1,86 @@
|
|||||||
- content_for :page_title do
|
- content_for :page_title do
|
||||||
= @account.acct
|
= @account.acct
|
||||||
|
|
||||||
%table.table
|
.table-wrapper
|
||||||
%tbody
|
%table.table
|
||||||
%tr
|
%tbody
|
||||||
%th= t('admin.accounts.username')
|
%tr
|
||||||
%td= @account.username
|
%th= t('admin.accounts.username')
|
||||||
%tr
|
%td= @account.username
|
||||||
%th= t('admin.accounts.domain')
|
%tr
|
||||||
%td= @account.domain
|
%th= t('admin.accounts.domain')
|
||||||
%tr
|
%td= @account.domain
|
||||||
%th= t('admin.accounts.display_name')
|
%tr
|
||||||
%td= @account.display_name
|
%th= t('admin.accounts.display_name')
|
||||||
|
%td= @account.display_name
|
||||||
|
|
||||||
- if @account.local?
|
- if @account.local?
|
||||||
%tr
|
|
||||||
%th= t('admin.accounts.email')
|
|
||||||
%td= @account.user_email
|
|
||||||
%tr
|
|
||||||
%th= t('admin.accounts.most_recent_ip')
|
|
||||||
%td= @account.user_current_sign_in_ip
|
|
||||||
%tr
|
|
||||||
%th= t('admin.accounts.most_recent_activity')
|
|
||||||
%td
|
|
||||||
- if @account.user_current_sign_in_at
|
|
||||||
%time.formatted{ datetime: @account.user_current_sign_in_at.iso8601, title: l(@account.user_current_sign_in_at) }
|
|
||||||
= l @account.user_current_sign_in_at
|
|
||||||
- else
|
|
||||||
Never
|
|
||||||
- else
|
|
||||||
%tr
|
|
||||||
%th= t('admin.accounts.profile_url')
|
|
||||||
%td= link_to @account.url, @account.url
|
|
||||||
%tr
|
|
||||||
%th= t('admin.accounts.protocol')
|
|
||||||
%td= @account.protocol.humanize
|
|
||||||
|
|
||||||
- if @account.ostatus?
|
|
||||||
%tr
|
%tr
|
||||||
%th= t('admin.accounts.feed_url')
|
%th= t('admin.accounts.email')
|
||||||
%td= link_to @account.remote_url, @account.remote_url
|
%td= @account.user_email
|
||||||
%tr
|
%tr
|
||||||
%th= t('admin.accounts.push_subscription_expires')
|
%th= t('admin.accounts.most_recent_ip')
|
||||||
|
%td= @account.user_current_sign_in_ip
|
||||||
|
%tr
|
||||||
|
%th= t('admin.accounts.most_recent_activity')
|
||||||
%td
|
%td
|
||||||
- if @account.subscribed?
|
- if @account.user_current_sign_in_at
|
||||||
%time.formatted{ datetime: @account.subscription_expires_at.iso8601, title: l(@account.subscription_expires_at) }
|
%time.formatted{ datetime: @account.user_current_sign_in_at.iso8601, title: l(@account.user_current_sign_in_at) }
|
||||||
= l @account.subscription_expires_at
|
= l @account.user_current_sign_in_at
|
||||||
- else
|
- else
|
||||||
= t('admin.accounts.not_subscribed')
|
Never
|
||||||
|
- else
|
||||||
%tr
|
%tr
|
||||||
%th= t('admin.accounts.salmon_url')
|
%th= t('admin.accounts.profile_url')
|
||||||
%td= link_to @account.salmon_url, @account.salmon_url
|
%td= link_to @account.url, @account.url
|
||||||
- elsif @account.activitypub?
|
|
||||||
%tr
|
%tr
|
||||||
%th= t('admin.accounts.inbox_url')
|
%th= t('admin.accounts.protocol')
|
||||||
%td= link_to @account.inbox_url, @account.inbox_url
|
%td= @account.protocol.humanize
|
||||||
%tr
|
|
||||||
%th= t('admin.accounts.outbox_url')
|
|
||||||
%td= link_to @account.outbox_url, @account.outbox_url
|
|
||||||
|
|
||||||
%tr
|
- if @account.ostatus?
|
||||||
%th= t('admin.accounts.follows')
|
%tr
|
||||||
%td= @account.following_count
|
%th= t('admin.accounts.feed_url')
|
||||||
%tr
|
%td= link_to @account.remote_url, @account.remote_url
|
||||||
%th= t('admin.accounts.followers')
|
%tr
|
||||||
%td= @account.followers_count
|
%th= t('admin.accounts.push_subscription_expires')
|
||||||
%tr
|
%td
|
||||||
%th= t('admin.accounts.statuses')
|
- if @account.subscribed?
|
||||||
%td= link_to @account.statuses_count, admin_account_statuses_path(@account.id)
|
%time.formatted{ datetime: @account.subscription_expires_at.iso8601, title: l(@account.subscription_expires_at) }
|
||||||
%tr
|
= l @account.subscription_expires_at
|
||||||
%th= t('admin.accounts.media_attachments')
|
- else
|
||||||
%td
|
= t('admin.accounts.not_subscribed')
|
||||||
= link_to @account.media_attachments.count, admin_account_statuses_path(@account.id, { media: true })
|
%tr
|
||||||
= surround '(', ')' do
|
%th= t('admin.accounts.salmon_url')
|
||||||
= number_to_human_size @account.media_attachments.sum('file_file_size')
|
%td= link_to @account.salmon_url, @account.salmon_url
|
||||||
%tr
|
- elsif @account.activitypub?
|
||||||
%th= t('.created_reports')
|
%tr
|
||||||
%td= link_to pluralize(@account.reports.count, t('.report')), admin_reports_path(account_id: @account.id)
|
%th= t('admin.accounts.inbox_url')
|
||||||
%tr
|
%td= link_to @account.inbox_url, @account.inbox_url
|
||||||
%th= t('.targeted_reports')
|
%tr
|
||||||
%td= link_to pluralize(@account.targeted_reports.count, t('.report')), admin_reports_path(target_account_id: @account.id)
|
%th= t('admin.accounts.outbox_url')
|
||||||
|
%td= link_to @account.outbox_url, @account.outbox_url
|
||||||
|
|
||||||
|
%tr
|
||||||
|
%th= t('admin.accounts.follows')
|
||||||
|
%td= @account.following_count
|
||||||
|
%tr
|
||||||
|
%th= t('admin.accounts.followers')
|
||||||
|
%td= @account.followers_count
|
||||||
|
%tr
|
||||||
|
%th= t('admin.accounts.statuses')
|
||||||
|
%td= link_to @account.statuses_count, admin_account_statuses_path(@account.id)
|
||||||
|
%tr
|
||||||
|
%th= t('admin.accounts.media_attachments')
|
||||||
|
%td
|
||||||
|
= link_to @account.media_attachments.count, admin_account_statuses_path(@account.id, { media: true })
|
||||||
|
= surround '(', ')' do
|
||||||
|
= number_to_human_size @account.media_attachments.sum('file_file_size')
|
||||||
|
%tr
|
||||||
|
%th= t('.created_reports')
|
||||||
|
%td= link_to pluralize(@account.reports.count, t('.report')), admin_reports_path(account_id: @account.id)
|
||||||
|
%tr
|
||||||
|
%th= t('.targeted_reports')
|
||||||
|
%td= link_to pluralize(@account.targeted_reports.count, t('.report')), admin_reports_path(target_account_id: @account.id)
|
||||||
|
|
||||||
%div{ style: 'float: right' }
|
%div{ style: 'float: right' }
|
||||||
- if @account.local?
|
- if @account.local?
|
||||||
|
@@ -1,15 +1,16 @@
|
|||||||
- content_for :page_title do
|
- content_for :page_title do
|
||||||
= t('admin.domain_blocks.title')
|
= t('admin.domain_blocks.title')
|
||||||
|
|
||||||
%table.table
|
.table-wrapper
|
||||||
%thead
|
%table.table
|
||||||
%tr
|
%thead
|
||||||
%th= t('admin.domain_blocks.domain')
|
%tr
|
||||||
%th= t('admin.domain_blocks.severity')
|
%th= t('admin.domain_blocks.domain')
|
||||||
%th= t('admin.domain_blocks.reject_media')
|
%th= t('admin.domain_blocks.severity')
|
||||||
%th
|
%th= t('admin.domain_blocks.reject_media')
|
||||||
%tbody
|
%th
|
||||||
= render @domain_blocks
|
%tbody
|
||||||
|
= render @domain_blocks
|
||||||
|
|
||||||
= paginate @domain_blocks
|
= paginate @domain_blocks
|
||||||
= link_to t('admin.domain_blocks.add_new'), new_admin_domain_block_path, class: 'button'
|
= link_to t('admin.domain_blocks.add_new'), new_admin_domain_block_path, class: 'button'
|
||||||
|
@@ -1,12 +1,13 @@
|
|||||||
- content_for :page_title do
|
- content_for :page_title do
|
||||||
= t('admin.instances.title')
|
= t('admin.instances.title')
|
||||||
|
|
||||||
%table.table
|
.table-wrapper
|
||||||
%thead
|
%table.table
|
||||||
%tr
|
%thead
|
||||||
%th= t('admin.instances.domain_name')
|
%tr
|
||||||
%th= t('admin.instances.account_count')
|
%th= t('admin.instances.domain_name')
|
||||||
%tbody
|
%th= t('admin.instances.account_count')
|
||||||
= render @instances
|
%tbody
|
||||||
|
= render @instances
|
||||||
|
|
||||||
= paginate paginated_instances
|
= paginate paginated_instances
|
||||||
|
@@ -10,17 +10,18 @@
|
|||||||
|
|
||||||
= form_tag do
|
= form_tag do
|
||||||
|
|
||||||
%table.table
|
.table-wrapper
|
||||||
%thead
|
%table.table
|
||||||
%tr
|
%thead
|
||||||
-# %th
|
%tr
|
||||||
%th= t('admin.reports.id')
|
-# %th
|
||||||
%th= t('admin.reports.target')
|
%th= t('admin.reports.id')
|
||||||
%th= t('admin.reports.reported_by')
|
%th= t('admin.reports.target')
|
||||||
%th= t('admin.reports.comment.label')
|
%th= t('admin.reports.reported_by')
|
||||||
%th= t('admin.reports.report_contents')
|
%th= t('admin.reports.comment.label')
|
||||||
%th
|
%th= t('admin.reports.report_contents')
|
||||||
%tbody
|
%th
|
||||||
= render @reports
|
%tbody
|
||||||
|
= render @reports
|
||||||
|
|
||||||
= paginate @reports
|
= paginate @reports
|
||||||
|
@@ -28,5 +28,10 @@
|
|||||||
= f.input :site_extended_description, wrapper: :with_block_label, as: :text, label: t('admin.settings.site_description_extended.title'), hint: t('admin.settings.site_description_extended.desc_html'), input_html: { rows: 8 }
|
= f.input :site_extended_description, wrapper: :with_block_label, as: :text, label: t('admin.settings.site_description_extended.title'), hint: t('admin.settings.site_description_extended.desc_html'), input_html: { rows: 8 }
|
||||||
= f.input :site_terms, wrapper: :with_block_label, as: :text, label: t('admin.settings.site_terms.title'), hint: t('admin.settings.site_terms.desc_html'), input_html: { rows: 8 }
|
= f.input :site_terms, wrapper: :with_block_label, as: :text, label: t('admin.settings.site_terms.title'), hint: t('admin.settings.site_terms.desc_html'), input_html: { rows: 8 }
|
||||||
|
|
||||||
|
%hr/
|
||||||
|
|
||||||
|
.fields-group
|
||||||
|
= f.input :bootstrap_timeline_accounts, wrapper: :with_block_label, label: t('admin.settings.bootstrap_timeline_accounts.title'), hint: t('admin.settings.bootstrap_timeline_accounts.desc_html')
|
||||||
|
|
||||||
.actions
|
.actions
|
||||||
= f.button :button, t('generic.save_changes'), type: :submit
|
= f.button :button, t('generic.save_changes'), type: :submit
|
||||||
|
@@ -1,15 +1,16 @@
|
|||||||
- content_for :page_title do
|
- content_for :page_title do
|
||||||
= t('admin.subscriptions.title')
|
= t('admin.subscriptions.title')
|
||||||
|
|
||||||
%table.table
|
.table-wrapper
|
||||||
%thead
|
%table.table
|
||||||
%tr
|
%thead
|
||||||
%th= t('admin.subscriptions.topic')
|
%tr
|
||||||
%th= t('admin.subscriptions.callback_url')
|
%th= t('admin.subscriptions.topic')
|
||||||
%th= t('admin.subscriptions.confirmed')
|
%th= t('admin.subscriptions.callback_url')
|
||||||
%th= t('admin.subscriptions.expires_in')
|
%th= t('admin.subscriptions.confirmed')
|
||||||
%th= t('admin.subscriptions.last_delivery')
|
%th= t('admin.subscriptions.expires_in')
|
||||||
%tbody
|
%th= t('admin.subscriptions.last_delivery')
|
||||||
= render @subscriptions
|
%tbody
|
||||||
|
= render @subscriptions
|
||||||
|
|
||||||
= paginate @subscriptions
|
= paginate @subscriptions
|
||||||
|
@@ -1,28 +1,29 @@
|
|||||||
%h6= t 'sessions.title'
|
%h6= t 'sessions.title'
|
||||||
%p.muted-hint= t 'sessions.explanation'
|
%p.muted-hint= t 'sessions.explanation'
|
||||||
|
|
||||||
%table.table.inline-table
|
.table-wrapper
|
||||||
%thead
|
%table.table.inline-table
|
||||||
%tr
|
%thead
|
||||||
%th= t 'sessions.browser'
|
|
||||||
%th= t 'sessions.ip'
|
|
||||||
%th= t 'sessions.activity'
|
|
||||||
%td
|
|
||||||
%tbody
|
|
||||||
- @sessions.each do |session|
|
|
||||||
%tr
|
%tr
|
||||||
|
%th= t 'sessions.browser'
|
||||||
|
%th= t 'sessions.ip'
|
||||||
|
%th= t 'sessions.activity'
|
||||||
%td
|
%td
|
||||||
%span{ title: session.user_agent }<
|
%tbody
|
||||||
= fa_icon "#{session_device_icon(session)} fw", 'aria-label' => session_device_icon(session)
|
- @sessions.each do |session|
|
||||||
= ' '
|
%tr
|
||||||
= t 'sessions.description', browser: t("sessions.browsers.#{session.browser}"), platform: t("sessions.platforms.#{session.platform}")
|
%td
|
||||||
%td
|
%span{ title: session.user_agent }<
|
||||||
%samp= session.ip
|
= fa_icon "#{session_device_icon(session)} fw", 'aria-label' => session_device_icon(session)
|
||||||
%td
|
= ' '
|
||||||
- if current_session.session_id == session.session_id
|
= t 'sessions.description', browser: t("sessions.browsers.#{session.browser}"), platform: t("sessions.platforms.#{session.platform}")
|
||||||
= t 'sessions.current_session'
|
%td
|
||||||
- else
|
%samp= session.ip
|
||||||
%time.time-ago{ datetime: session.updated_at.iso8601, title: l(session.updated_at) }= l(session.updated_at)
|
%td
|
||||||
%td
|
- if current_session.session_id == session.session_id
|
||||||
- if current_session.session_id != session.session_id
|
= t 'sessions.current_session'
|
||||||
= table_link_to 'times', t('sessions.revoke'), settings_session_path(session), method: :delete
|
- else
|
||||||
|
%time.time-ago{ datetime: session.updated_at.iso8601, title: l(session.updated_at) }= l(session.updated_at)
|
||||||
|
%td
|
||||||
|
- if current_session.session_id != session.session_id
|
||||||
|
= table_link_to 'times', t('sessions.revoke'), settings_session_path(session), method: :delete
|
||||||
|
@@ -21,13 +21,13 @@
|
|||||||
= stylesheet_pack_tag 'common', media: 'all'
|
= stylesheet_pack_tag 'common', media: 'all'
|
||||||
= javascript_pack_tag 'common', integrity: true, crossorigin: 'anonymous'
|
= javascript_pack_tag 'common', integrity: true, crossorigin: 'anonymous'
|
||||||
|
|
||||||
= javascript_pack_tag 'features/getting_started', integrity: true, crossorigin: 'anonymous', rel: 'preload', as: 'script'
|
%link{ href: asset_pack_path('features/getting_started.js'), crossorigin: 'anonymous', rel: 'preload', as: 'script' }/
|
||||||
= javascript_pack_tag 'features/compose', integrity: true, crossorigin: 'anonymous', rel: 'preload', as: 'script'
|
%link{ href: asset_pack_path('features/compose.js'), crossorigin: 'anonymous', rel: 'preload', as: 'script' }/
|
||||||
= javascript_pack_tag 'features/home_timeline', integrity: true, crossorigin: 'anonymous', rel: 'preload', as: 'script'
|
%link{ href: asset_pack_path('features/home_timeline.js'), crossorigin: 'anonymous', rel: 'preload', as: 'script' }/
|
||||||
= javascript_pack_tag 'features/notifications', integrity: true, crossorigin: 'anonymous', rel: 'preload', as: 'script'
|
%link{ href: asset_pack_path('features/notifications.js'), crossorigin: 'anonymous', rel: 'preload', as: 'script' }/
|
||||||
= javascript_pack_tag 'features/community_timeline', integrity: true, crossorigin: 'anonymous', rel: 'preload', as: 'script'
|
%link{ href: asset_pack_path('features/community_timeline.js'), crossorigin: 'anonymous', rel: 'preload', as: 'script' }/
|
||||||
= javascript_pack_tag 'features/public_timeline', integrity: true, crossorigin: 'anonymous', rel: 'preload', as: 'script'
|
%link{ href: asset_pack_path('features/public_timeline.js'), crossorigin: 'anonymous', rel: 'preload', as: 'script' }/
|
||||||
= javascript_pack_tag 'emojione_picker', integrity: true, crossorigin: 'anonymous', rel: 'preload', as: 'script'
|
%link{ href: asset_pack_path('emojione_picker.js'), crossorigin: 'anonymous', rel: 'preload', as: 'script' }/
|
||||||
|
|
||||||
= javascript_pack_tag "locale_#{I18n.locale}", integrity: true, crossorigin: 'anonymous'
|
= javascript_pack_tag "locale_#{I18n.locale}", integrity: true, crossorigin: 'anonymous'
|
||||||
= csrf_meta_tags
|
= csrf_meta_tags
|
||||||
|
@@ -1,23 +1,24 @@
|
|||||||
- content_for :page_title do
|
- content_for :page_title do
|
||||||
= t('doorkeeper.authorized_applications.index.title')
|
= t('doorkeeper.authorized_applications.index.title')
|
||||||
|
|
||||||
%table.table
|
.table-wrapper
|
||||||
%thead
|
%table.table
|
||||||
%tr
|
%thead
|
||||||
%th= t('doorkeeper.authorized_applications.index.application')
|
|
||||||
%th= t('doorkeeper.authorized_applications.index.scopes')
|
|
||||||
%th= t('doorkeeper.authorized_applications.index.created_at')
|
|
||||||
%th
|
|
||||||
%tbody
|
|
||||||
- @applications.each do |application|
|
|
||||||
%tr
|
%tr
|
||||||
%td
|
%th= t('doorkeeper.authorized_applications.index.application')
|
||||||
- if application.website.blank?
|
%th= t('doorkeeper.authorized_applications.index.scopes')
|
||||||
= application.name
|
%th= t('doorkeeper.authorized_applications.index.created_at')
|
||||||
- else
|
%th
|
||||||
= link_to application.name, application.website, target: '_blank', rel: 'noopener'
|
%tbody
|
||||||
%th!= application.scopes.map { |scope| t(scope, scope: [:doorkeeper, :scopes]) }.join('<br />')
|
- @applications.each do |application|
|
||||||
%td= l application.created_at
|
%tr
|
||||||
%td
|
%td
|
||||||
- unless application.superapp?
|
- if application.website.blank?
|
||||||
= table_link_to 'times', t('doorkeeper.authorized_applications.buttons.revoke'), oauth_authorized_application_path(application), method: :delete, data: { confirm: t('doorkeeper.authorized_applications.confirmations.revoke') }
|
= application.name
|
||||||
|
- else
|
||||||
|
= link_to application.name, application.website, target: '_blank', rel: 'noopener'
|
||||||
|
%th!= application.scopes.map { |scope| t(scope, scope: [:doorkeeper, :scopes]) }.join('<br />')
|
||||||
|
%td= l application.created_at
|
||||||
|
%td
|
||||||
|
- unless application.superapp?
|
||||||
|
= table_link_to 'times', t('doorkeeper.authorized_applications.buttons.revoke'), oauth_authorized_application_path(application), method: :delete, data: { confirm: t('doorkeeper.authorized_applications.confirmations.revoke') }
|
||||||
|
@@ -1,19 +1,20 @@
|
|||||||
- content_for :page_title do
|
- content_for :page_title do
|
||||||
= t('doorkeeper.applications.index.title')
|
= t('doorkeeper.applications.index.title')
|
||||||
|
|
||||||
%table.table
|
.table-wrapper
|
||||||
%thead
|
%table.table
|
||||||
%tr
|
%thead
|
||||||
%th= t('doorkeeper.applications.index.application')
|
|
||||||
%th= t('doorkeeper.applications.index.scopes')
|
|
||||||
%th
|
|
||||||
%tbody
|
|
||||||
- @applications.each do |application|
|
|
||||||
%tr
|
%tr
|
||||||
%td= link_to application.name, settings_application_path(application)
|
%th= t('doorkeeper.applications.index.application')
|
||||||
%th= application.scopes
|
%th= t('doorkeeper.applications.index.scopes')
|
||||||
%td
|
%th
|
||||||
= table_link_to 'times', t('doorkeeper.applications.index.delete'), settings_application_path(application), method: :delete, data: { confirm: t('doorkeeper.applications.confirmations.destroy') }
|
%tbody
|
||||||
|
- @applications.each do |application|
|
||||||
|
%tr
|
||||||
|
%td= link_to application.name, settings_application_path(application)
|
||||||
|
%th= application.scopes
|
||||||
|
%td
|
||||||
|
= table_link_to 'times', t('doorkeeper.applications.index.delete'), settings_application_path(application), method: :delete, data: { confirm: t('doorkeeper.applications.confirmations.destroy') }
|
||||||
|
|
||||||
= paginate @applications
|
= paginate @applications
|
||||||
= link_to t('doorkeeper.applications.index.new'), new_settings_application_path, class: 'button'
|
= link_to t('doorkeeper.applications.index.new'), new_settings_application_path, class: 'button'
|
||||||
|
@@ -3,22 +3,23 @@
|
|||||||
|
|
||||||
%p.hint= t('applications.warning')
|
%p.hint= t('applications.warning')
|
||||||
|
|
||||||
%table.table
|
.table-wrapper
|
||||||
%tbody
|
%table.table
|
||||||
%tr
|
%tbody
|
||||||
%th= t('doorkeeper.applications.show.application_id')
|
%tr
|
||||||
%td
|
%th= t('doorkeeper.applications.show.application_id')
|
||||||
%code= @application.uid
|
%td
|
||||||
%tr
|
%code= @application.uid
|
||||||
%th= t('doorkeeper.applications.show.secret')
|
%tr
|
||||||
%td
|
%th= t('doorkeeper.applications.show.secret')
|
||||||
%code= @application.secret
|
%td
|
||||||
%tr
|
%code= @application.secret
|
||||||
%th{ rowspan: 2}= t('applications.your_token')
|
%tr
|
||||||
%td
|
%th{ rowspan: 2}= t('applications.your_token')
|
||||||
%code= current_user.token_for_app(@application).token
|
%td
|
||||||
%tr
|
%code= current_user.token_for_app(@application).token
|
||||||
%td= table_link_to 'refresh', t('applications.regenerate_token'), regenerate_settings_application_path(@application), method: :post
|
%tr
|
||||||
|
%td= table_link_to 'refresh', t('applications.regenerate_token'), regenerate_settings_application_path(@application), method: :post
|
||||||
|
|
||||||
%hr/
|
%hr/
|
||||||
|
|
||||||
|
@@ -1,21 +1,22 @@
|
|||||||
- content_for :page_title do
|
- content_for :page_title do
|
||||||
= t('settings.export')
|
= t('settings.export')
|
||||||
|
|
||||||
%table.table
|
.table-wrapper
|
||||||
%tbody
|
%table.table
|
||||||
%tr
|
%tbody
|
||||||
%th= t('exports.storage')
|
%tr
|
||||||
%td= number_to_human_size @export.total_storage
|
%th= t('exports.storage')
|
||||||
%td
|
%td= number_to_human_size @export.total_storage
|
||||||
%tr
|
%td
|
||||||
%th= t('exports.follows')
|
%tr
|
||||||
%td= @export.total_follows
|
%th= t('exports.follows')
|
||||||
%td= table_link_to 'download', t('exports.csv'), settings_exports_follows_path(format: :csv)
|
%td= @export.total_follows
|
||||||
%tr
|
%td= table_link_to 'download', t('exports.csv'), settings_exports_follows_path(format: :csv)
|
||||||
%th= t('exports.blocks')
|
%tr
|
||||||
%td= @export.total_blocks
|
%th= t('exports.blocks')
|
||||||
%td= table_link_to 'download', t('exports.csv'), settings_exports_blocks_path(format: :csv)
|
%td= @export.total_blocks
|
||||||
%tr
|
%td= table_link_to 'download', t('exports.csv'), settings_exports_blocks_path(format: :csv)
|
||||||
%th= t('exports.mutes')
|
%tr
|
||||||
%td= @export.total_mutes
|
%th= t('exports.mutes')
|
||||||
%td= table_link_to 'download', t('exports.csv'), settings_exports_mutes_path(format: :csv)
|
%td= @export.total_mutes
|
||||||
|
%td= table_link_to 'download', t('exports.csv'), settings_exports_mutes_path(format: :csv)
|
||||||
|
@@ -12,20 +12,21 @@
|
|||||||
%p= t('followers.explanation_html')
|
%p= t('followers.explanation_html')
|
||||||
%p= t('followers.true_privacy_html')
|
%p= t('followers.true_privacy_html')
|
||||||
|
|
||||||
%table.table
|
.table-wrapper
|
||||||
%thead
|
%table.table
|
||||||
%tr
|
%thead
|
||||||
%th
|
|
||||||
%th= t('followers.domain')
|
|
||||||
%th= t('followers.followers_count')
|
|
||||||
%tbody
|
|
||||||
- @domains.each do |domain|
|
|
||||||
%tr
|
%tr
|
||||||
%td
|
%th
|
||||||
= check_box_tag 'select[]', domain.domain, false, disabled: !@account.locked? unless domain.domain.nil?
|
%th= t('followers.domain')
|
||||||
%td
|
%th= t('followers.followers_count')
|
||||||
%samp= domain.domain.presence || Rails.configuration.x.local_domain
|
%tbody
|
||||||
%td= number_with_delimiter domain.accounts_from_domain
|
- @domains.each do |domain|
|
||||||
|
%tr
|
||||||
|
%td
|
||||||
|
= check_box_tag 'select[]', domain.domain, false, disabled: !@account.locked? unless domain.domain.nil?
|
||||||
|
%td
|
||||||
|
%samp= domain.domain.presence || Rails.configuration.x.local_domain
|
||||||
|
%td= number_with_delimiter domain.accounts_from_domain
|
||||||
|
|
||||||
.action-pagination
|
.action-pagination
|
||||||
.actions
|
.actions
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
selected: I18n.locale
|
selected: I18n.locale
|
||||||
|
|
||||||
= f.input :filtered_languages,
|
= f.input :filtered_languages,
|
||||||
collection: I18n.available_locales,
|
collection: filterable_languages,
|
||||||
wrapper: :with_block_label,
|
wrapper: :with_block_label,
|
||||||
include_blank: false,
|
include_blank: false,
|
||||||
label_method: lambda { |locale| human_locale(locale) },
|
label_method: lambda { |locale| human_locale(locale) },
|
||||||
|
@@ -1,9 +1,4 @@
|
|||||||
.detailed-status.light
|
.detailed-status.light
|
||||||
- if embedded_view?
|
|
||||||
= link_to "web+mastodon://follow?uri=#{status.account.local_username_and_domain}", class: 'button button-secondary logo-button', target: '_new' do
|
|
||||||
= render file: Rails.root.join('app', 'javascript', 'images', 'logo.svg')
|
|
||||||
= t('accounts.follow')
|
|
||||||
|
|
||||||
= link_to TagManager.instance.url_for(status.account), class: 'detailed-status__display-name p-author h-card', target: stream_link_target, rel: 'noopener' do
|
= link_to TagManager.instance.url_for(status.account), class: 'detailed-status__display-name p-author h-card', target: stream_link_target, rel: 'noopener' do
|
||||||
%div
|
%div
|
||||||
.avatar
|
.avatar
|
||||||
@@ -12,6 +7,11 @@
|
|||||||
%strong.p-name.emojify= display_name(status.account)
|
%strong.p-name.emojify= display_name(status.account)
|
||||||
%span= acct(status.account)
|
%span= acct(status.account)
|
||||||
|
|
||||||
|
- if embedded_view?
|
||||||
|
= link_to "web+mastodon://follow?uri=#{status.account.local_username_and_domain}", class: 'button button-secondary logo-button', target: '_new' do
|
||||||
|
= render file: Rails.root.join('app', 'javascript', 'images', 'logo.svg')
|
||||||
|
= t('accounts.follow')
|
||||||
|
|
||||||
.status__content.p-name.emojify<
|
.status__content.p-name.emojify<
|
||||||
- if status.spoiler_text?
|
- if status.spoiler_text?
|
||||||
%p{ style: 'margin-bottom: 0' }<
|
%p{ style: 'margin-bottom: 0' }<
|
||||||
|
@@ -1,13 +1,13 @@
|
|||||||
<p>Bonjorn <%= @resource.email %> !<p>
|
<p>Bonjorn <%= @resource.email %> !<p>
|
||||||
|
|
||||||
<p>Venètz de vos crear un compte sus <%= @instance %> e vos mercegem :)</p>
|
<p>Venètz de vos crear un compte sus <%= @instance %> e vos mercegem :)</p>
|
||||||
|
|
||||||
<p>Per confirmar vòstre inscripcion, mercés de clicar sul ligam seguent : <br>
|
<p>Per confirmar vòstra inscripcion, mercés de clicar sul ligam seguent : <br>
|
||||||
<%= link_to 'Confirmar mon compte', confirmation_url(@resource, confirmation_token: @token) %></p>
|
<%= link_to 'Confirmar mon compte', confirmation_url(@resource, confirmation_token: @token) %></p>
|
||||||
|
|
||||||
<p>Aprèp vòstra primièra connexion, poiretz accedir a la documentacion de l’aisina.</p>
|
<p>Aprèp vòstra primièra connexion, poiretz accedir a la documentacion de l’aisina.</p>
|
||||||
|
|
||||||
<p>Pensatz tanben a gaitar nòstras <%= link_to 'conditions d\'utilisation', terms_url %>.</p>
|
<p>Pensatz tanben de gaitar nòstras <%= link_to 'conditions d\'utilisation', terms_url %>.</p>
|
||||||
|
|
||||||
<p>Amistosament,</p>
|
<p>Amistosament,</p>
|
||||||
|
|
||||||
|
@@ -1,13 +1,13 @@
|
|||||||
Bonjorn <%= @resource.email %> !
|
Bonjorn <%= @resource.email %> !
|
||||||
|
|
||||||
Venètz de vos crear un compte sus <%= @instance %> e vos mercegem :)
|
Venètz de vos crear un compte sus <%= @instance %> e vos mercegem :)
|
||||||
|
|
||||||
er confirmar vòstre inscripcion, mercés de clicar sul ligam seguent :
|
er confirmar vòstra inscripcion, mercés de clicar sul ligam seguent :
|
||||||
<%= link_to 'Confirmar mon compte', confirmation_url(@resource, confirmation_token: @token) %>
|
<%= link_to 'Confirmar mon compte', confirmation_url(@resource, confirmation_token: @token) %>
|
||||||
|
|
||||||
Aprèp vòstra primièra connexion, poiretz accedir a la documentacion de l’aisina.
|
Aprèp vòstra primièra connexion, poiretz accedir a la documentacion de l’aisina.
|
||||||
|
|
||||||
Pensatz tanben a gaitar nòstras <%= link_to 'conditions d\'utilisation', terms_url %>.
|
Pensatz tanben de gaitar nòstras <%= link_to 'conditions d\'utilisation', terms_url %>.
|
||||||
|
|
||||||
Amistosament,
|
Amistosament,
|
||||||
|
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
<p>Bonjorn <%= @resource.email %> !</p>
|
<p>Bonjorn <%= @resource.email %> !</p>
|
||||||
|
|
||||||
<p>Vos contactem per vos avisar que vòstre senhal per Mastodon es ben estat cambiat.</p>
|
<p>Vos contactem per vos avisar qu’avèm ben cambiat vòstre senhal Mastodon.</p>
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
Bonjorn <%= @resource.email %> !
|
Bonjorn <%= @resource.email %> !
|
||||||
|
|
||||||
Vos contactem per vos avisar que vòstre senhal per Mastodon es ben estat cambiat.
|
Vos contactem per vos avisar qu’avèm ben cambiat vòstre senhal Mastodon.
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
<p>Bonjorn <%= @resource.email %> !</p>
|
<p>Bonjorn <%= @resource.email %> !</p>
|
||||||
|
|
||||||
<p>Qualqu’un a demandat una reĩnicializacion de vòstre senhal per Mastodon. Podètz realizar la reĩnicializacion en clicant sul ligam çai-jos.</p>
|
<p>Qualqu’un a demandat la reĩnicializacion de vòstre senhal per Mastodon. Podètz realizar la reĩnicializacion en clicant sul ligam çai-jos.</p>
|
||||||
|
|
||||||
<p><%= link_to 'Modificar mon senhal', edit_password_url(@resource, reset_password_token: @token) %></p>
|
<p><%= link_to 'Modificar mon senhal', edit_password_url(@resource, reset_password_token: @token) %></p>
|
||||||
|
|
||||||
<p>S’avètz pas res demandat, fasquètz pas cas a aqueste corrièl.</p>
|
<p>S’avètz pas res demandat, fasquètz pas cas a aqueste corrièl.</p>
|
||||||
<p>Vòstre senhal cambiarà pas se clicatz pas sul ligam e que ne causissètz pas un nòu.</p>
|
<p>Vòstre senhal cambiarà pas se clicatz pas sul ligam e que ne causissètz pas un novèl.</p>
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
Bonjorn <%= @resource.email %> !
|
Bonjorn <%= @resource.email %> !
|
||||||
|
|
||||||
Qualqu’un a demandat una reĩnicializacion de vòstre senhal per Mastodon. Podètz realizar la reĩnicializacion en clicant sul ligam çai-jos.</p>
|
Qualqu’un a demandat la reĩnicializacion de vòstre senhal per Mastodon. Podètz realizar la reĩnicializacion en clicant sul ligam çai-jos.</p>
|
||||||
|
|
||||||
<%= link_to 'Modificar mon senhal', edit_password_url(@resource, reset_password_token: @token) %>
|
<%= link_to 'Modificar mon senhal', edit_password_url(@resource, reset_password_token: @token) %>
|
||||||
|
|
||||||
S’avètz pas res demandat, fasquètz pas cas a aqueste corrièl.
|
S’avètz pas res demandat, fasquètz pas cas a aqueste corrièl.
|
||||||
Vòstre senhal cambiarà pas se clicatz pas sul ligam e que ne causissètz pas un nòu.
|
Vòstre senhal cambiarà pas se clicatz pas sul ligam e que ne causissètz pas un novèl.
|
||||||
|
9
app/workers/bootstrap_timeline_worker.rb
Normal file
9
app/workers/bootstrap_timeline_worker.rb
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class BootstrapTimelineWorker
|
||||||
|
include Sidekiq::Worker
|
||||||
|
|
||||||
|
def perform(account_id)
|
||||||
|
BootstrapTimelineService.new.call(Account.find(account_id))
|
||||||
|
end
|
||||||
|
end
|
@@ -6,7 +6,7 @@ class Pubsubhubbub::DistributionWorker
|
|||||||
sidekiq_options queue: 'push'
|
sidekiq_options queue: 'push'
|
||||||
|
|
||||||
def perform(stream_entry_ids)
|
def perform(stream_entry_ids)
|
||||||
stream_entries = StreamEntry.where(id: stream_entry_ids).includes(:status).reject { |e| e.status&.direct_visibility? }
|
stream_entries = StreamEntry.where(id: stream_entry_ids).includes(:status).reject { |e| e.status.nil? || e.status.direct_visibility? }
|
||||||
|
|
||||||
return if stream_entries.empty?
|
return if stream_entries.empty?
|
||||||
|
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
class Pubsubhubbub::SubscribeWorker
|
class Pubsubhubbub::SubscribeWorker
|
||||||
include Sidekiq::Worker
|
include Sidekiq::Worker
|
||||||
|
|
||||||
sidekiq_options queue: 'push', retry: 10, unique: :until_executed, dead: false
|
sidekiq_options queue: 'push', retry: 10, unique: :until_executed, dead: false, unique_retry: true
|
||||||
|
|
||||||
sidekiq_retry_in do |count|
|
sidekiq_retry_in do |count|
|
||||||
case count
|
case count
|
||||||
|
@@ -10,6 +10,7 @@ require_relative '../app/lib/exceptions'
|
|||||||
require_relative '../lib/paperclip/gif_transcoder'
|
require_relative '../lib/paperclip/gif_transcoder'
|
||||||
require_relative '../lib/paperclip/video_transcoder'
|
require_relative '../lib/paperclip/video_transcoder'
|
||||||
require_relative '../lib/mastodon/version'
|
require_relative '../lib/mastodon/version'
|
||||||
|
require_relative '../lib/mastodon/unique_retry_job_middleware'
|
||||||
|
|
||||||
Dotenv::Railtie.load
|
Dotenv::Railtie.load
|
||||||
|
|
||||||
|
@@ -73,7 +73,7 @@ Rails.application.configure do
|
|||||||
config.action_mailer.perform_caching = false
|
config.action_mailer.perform_caching = false
|
||||||
|
|
||||||
# E-mails
|
# E-mails
|
||||||
config.action_mailer.default_options = { from: ENV.fetch('SMTP_FROM_ADDRESS') }
|
config.action_mailer.default_options = { from: ENV.fetch('SMTP_FROM_ADDRESS', 'notifications@localhost') }
|
||||||
|
|
||||||
config.action_mailer.smtp_settings = {
|
config.action_mailer.smtp_settings = {
|
||||||
:port => ENV['SMTP_PORT'],
|
:port => ENV['SMTP_PORT'],
|
||||||
|
@@ -12,6 +12,7 @@ Rails.application.configure do
|
|||||||
config.x.web_domain = web_host
|
config.x.web_domain = web_host
|
||||||
config.x.use_https = https
|
config.x.use_https = https
|
||||||
config.x.use_s3 = ENV['S3_ENABLED'] == 'true'
|
config.x.use_s3 = ENV['S3_ENABLED'] == 'true'
|
||||||
|
config.x.use_swift = ENV['SWIFT_ENABLED'] == 'true'
|
||||||
|
|
||||||
config.x.alternate_domains = alternate_domains.split(/\s*,\s*/)
|
config.x.alternate_domains = alternate_domains.split(/\s*,\s*/)
|
||||||
|
|
||||||
|
@@ -40,6 +40,21 @@ if ENV['S3_ENABLED'] == 'true'
|
|||||||
Paperclip::Attachment.default_options[:url] = ':s3_alias_url'
|
Paperclip::Attachment.default_options[:url] = ':s3_alias_url'
|
||||||
Paperclip::Attachment.default_options[:s3_host_alias] = ENV['S3_CLOUDFRONT_HOST']
|
Paperclip::Attachment.default_options[:s3_host_alias] = ENV['S3_CLOUDFRONT_HOST']
|
||||||
end
|
end
|
||||||
|
elsif ENV['SWIFT_ENABLED'] == 'true'
|
||||||
|
Paperclip::Attachment.default_options.merge!(
|
||||||
|
path: ':class/:attachment/:id_partition/:style/:filename',
|
||||||
|
storage: :fog,
|
||||||
|
fog_credentials: {
|
||||||
|
provider: 'OpenStack',
|
||||||
|
openstack_username: ENV.fetch('SWIFT_USERNAME'),
|
||||||
|
openstack_tenant: ENV.fetch('SWIFT_TENANT'),
|
||||||
|
openstack_api_key: ENV.fetch('SWIFT_PASSWORD'),
|
||||||
|
openstack_auth_url: ENV.fetch('SWIFT_AUTH_URL'),
|
||||||
|
},
|
||||||
|
fog_directory: ENV.fetch('SWIFT_CONTAINER'),
|
||||||
|
fog_host: ENV.fetch('SWIFT_OBJECT_URL'),
|
||||||
|
fog_public: true
|
||||||
|
)
|
||||||
else
|
else
|
||||||
Paperclip::Attachment.default_options[:path] = (ENV['PAPERCLIP_ROOT_PATH'] || ':rails_root/public/system') + '/:class/:attachment/:id_partition/:style/:filename'
|
Paperclip::Attachment.default_options[:path] = (ENV['PAPERCLIP_ROOT_PATH'] || ':rails_root/public/system') + '/:class/:attachment/:id_partition/:style/:filename'
|
||||||
Paperclip::Attachment.default_options[:url] = (ENV['PAPERCLIP_ROOT_URL'] || '/system') + '/:class/:attachment/:id_partition/:style/:filename'
|
Paperclip::Attachment.default_options[:url] = (ENV['PAPERCLIP_ROOT_URL'] || '/system') + '/:class/:attachment/:id_partition/:style/:filename'
|
||||||
|
@@ -9,8 +9,14 @@ end
|
|||||||
|
|
||||||
Sidekiq.configure_server do |config|
|
Sidekiq.configure_server do |config|
|
||||||
config.redis = redis_params
|
config.redis = redis_params
|
||||||
|
config.client_middleware do |chain|
|
||||||
|
chain.add Mastodon::UniqueRetryJobMiddleware
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Sidekiq.configure_client do |config|
|
Sidekiq.configure_client do |config|
|
||||||
config.redis = redis_params
|
config.redis = redis_params
|
||||||
|
config.client_middleware do |chain|
|
||||||
|
chain.add Mastodon::UniqueRetryJobMiddleware
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@@ -47,16 +47,16 @@ ar:
|
|||||||
datetime:
|
datetime:
|
||||||
distance_in_words:
|
distance_in_words:
|
||||||
about_x_hours: "%{count}سا"
|
about_x_hours: "%{count}سا"
|
||||||
about_x_months: "%{count}شهر"
|
about_x_months: "%{count} شهر"
|
||||||
about_x_years: "%{count}سنة"
|
about_x_years: "%{count} سنة"
|
||||||
almost_x_years: "%{count}سنوات"
|
almost_x_years: "%{count} سنوات"
|
||||||
half_a_minute: Just now
|
half_a_minute: الآن
|
||||||
less_than_x_minutes: "%{count}د"
|
less_than_x_minutes: "%{count} د"
|
||||||
less_than_x_seconds: الآن
|
less_than_x_seconds: الآن
|
||||||
over_x_years: "%{count}سنين"
|
over_x_years: "%{count} سنين"
|
||||||
x_days: "%{count}أيام"
|
x_days: "%{count} أيام"
|
||||||
x_minutes: "%{count}د"
|
x_minutes: "%{count}د"
|
||||||
x_months: "%{count}شه"
|
x_months: "%{count} شه"
|
||||||
x_seconds: "%{count}ث"
|
x_seconds: "%{count}ث"
|
||||||
exports:
|
exports:
|
||||||
blocks: قمت بحظر
|
blocks: قمت بحظر
|
||||||
@@ -94,7 +94,7 @@ ar:
|
|||||||
one: "إشعار واحد منذ زيارتك الأخيرة \U0001F418"
|
one: "إشعار واحد منذ زيارتك الأخيرة \U0001F418"
|
||||||
other: "%{count} إشعارات جديدة منذ زيارتك الأخيرة \U0001F418"
|
other: "%{count} إشعارات جديدة منذ زيارتك الأخيرة \U0001F418"
|
||||||
favourite:
|
favourite:
|
||||||
body: 'Your status was favourited by %{name}:'
|
body: 'أُعجب %{name} بمنشورك'
|
||||||
subject: "%{name} favourited your status"
|
subject: "%{name} favourited your status"
|
||||||
follow:
|
follow:
|
||||||
body: "%{name} من متتبعيك الآن !"
|
body: "%{name} من متتبعيك الآن !"
|
||||||
@@ -108,6 +108,17 @@ ar:
|
|||||||
reblog:
|
reblog:
|
||||||
body: 'Your status was boosted by %{name}:'
|
body: 'Your status was boosted by %{name}:'
|
||||||
subject: "%{name} boosted your status"
|
subject: "%{name} boosted your status"
|
||||||
|
number:
|
||||||
|
human:
|
||||||
|
decimal_units:
|
||||||
|
format: "%n%u"
|
||||||
|
units:
|
||||||
|
billion: B
|
||||||
|
million: M
|
||||||
|
quadrillion: Q
|
||||||
|
thousand: K
|
||||||
|
trillion: T
|
||||||
|
unit: ''
|
||||||
pagination:
|
pagination:
|
||||||
next: التالي
|
next: التالي
|
||||||
prev: السابق
|
prev: السابق
|
||||||
@@ -148,7 +159,7 @@ ar:
|
|||||||
enabled_success: تم تفعيل إثبات الهوية المزدوج بنجاح
|
enabled_success: تم تفعيل إثبات الهوية المزدوج بنجاح
|
||||||
instructions_html: "<strong>Scan this QR code into Google Authenticator or a similiar TOTP app on your phone</strong>. From now on, that app will generate tokens that you will have to enter when logging in."
|
instructions_html: "<strong>Scan this QR code into Google Authenticator or a similiar TOTP app on your phone</strong>. From now on, that app will generate tokens that you will have to enter when logging in."
|
||||||
manual_instructions: 'If you can''t scan the QR code and need to enter it manually, here is the plain-text secret:'
|
manual_instructions: 'If you can''t scan the QR code and need to enter it manually, here is the plain-text secret:'
|
||||||
setup: Set up
|
setup: تنشيط
|
||||||
wrong_code: الرمز الذي أدخلته غير صالح. تحقق من صحة الوقت على الخادم و الجهاز.
|
wrong_code: الرمز الذي أدخلته غير صالح. تحقق من صحة الوقت على الخادم و الجهاز.
|
||||||
users:
|
users:
|
||||||
invalid_email: عنوان البريد الإلكتروني غير صالح
|
invalid_email: عنوان البريد الإلكتروني غير صالح
|
||||||
|
@@ -108,6 +108,17 @@ bg:
|
|||||||
reblog:
|
reblog:
|
||||||
body: 'Твоята публикация беше споделена от %{name}:'
|
body: 'Твоята публикация беше споделена от %{name}:'
|
||||||
subject: "%{name} сподели публикацията ти"
|
subject: "%{name} сподели публикацията ти"
|
||||||
|
number:
|
||||||
|
human:
|
||||||
|
decimal_units:
|
||||||
|
format: "%n%u"
|
||||||
|
units:
|
||||||
|
billion: B
|
||||||
|
million: M
|
||||||
|
quadrillion: Q
|
||||||
|
thousand: K
|
||||||
|
trillion: T
|
||||||
|
unit: ''
|
||||||
pagination:
|
pagination:
|
||||||
next: Напред
|
next: Напред
|
||||||
prev: Назад
|
prev: Назад
|
||||||
|
@@ -340,6 +340,17 @@ ca:
|
|||||||
reblog:
|
reblog:
|
||||||
body: "%{name} ha retootejat el teu estat"
|
body: "%{name} ha retootejat el teu estat"
|
||||||
subject: "%{name} ha retootejat el teu estat"
|
subject: "%{name} ha retootejat el teu estat"
|
||||||
|
number:
|
||||||
|
human:
|
||||||
|
decimal_units:
|
||||||
|
format: "%n%u"
|
||||||
|
units:
|
||||||
|
billion: B
|
||||||
|
million: M
|
||||||
|
quadrillion: Q
|
||||||
|
thousand: K
|
||||||
|
trillion: T
|
||||||
|
unit: ''
|
||||||
pagination:
|
pagination:
|
||||||
next: Pròxim
|
next: Pròxim
|
||||||
prev: Anterior
|
prev: Anterior
|
||||||
|
@@ -12,15 +12,15 @@ de:
|
|||||||
source_code: Quellcode
|
source_code: Quellcode
|
||||||
status_count_after: Beiträge verfassten
|
status_count_after: Beiträge verfassten
|
||||||
status_count_before: die
|
status_count_before: die
|
||||||
user_count_after: Benutzer
|
user_count_after: Profile
|
||||||
user_count_before: Heimat für
|
user_count_before: Heimat für
|
||||||
accounts:
|
accounts:
|
||||||
follow: Folgen
|
follow: Folgen
|
||||||
followers: Folgende
|
followers: Folgende
|
||||||
following: Folgt
|
following: Folgt
|
||||||
nothing_here: Hier gibt es nichts!
|
nothing_here: Hier gibt es nichts!
|
||||||
people_followed_by: Nutzer, denen %{name} folgt
|
people_followed_by: Profile, denen %{name} folgt
|
||||||
people_who_follow: Nutzer, die %{name} folgen
|
people_who_follow: Profile, die %{name} folgen
|
||||||
posts: Beiträge
|
posts: Beiträge
|
||||||
remote_follow: Folgen
|
remote_follow: Folgen
|
||||||
unfollow: Entfolgen
|
unfollow: Entfolgen
|
||||||
@@ -67,7 +67,7 @@ de:
|
|||||||
title: Konten
|
title: Konten
|
||||||
undo_silenced: Stummschaltung zurücknehmen
|
undo_silenced: Stummschaltung zurücknehmen
|
||||||
undo_suspension: Sperre zurücknehmen
|
undo_suspension: Sperre zurücknehmen
|
||||||
username: Benutzername
|
username: Profilname
|
||||||
web: Web
|
web: Web
|
||||||
domain_blocks:
|
domain_blocks:
|
||||||
add_new: Neu hinzufügen
|
add_new: Neu hinzufügen
|
||||||
@@ -124,7 +124,7 @@ de:
|
|||||||
settings:
|
settings:
|
||||||
contact_information:
|
contact_information:
|
||||||
email: Eine öffentliche E-Mail-Adresse angeben
|
email: Eine öffentliche E-Mail-Adresse angeben
|
||||||
username: Einen Benutzernamen angeben
|
username: Einen Profilnamen angeben
|
||||||
registrations:
|
registrations:
|
||||||
closed_message:
|
closed_message:
|
||||||
desc_html: Wird auf der Frontseite angezeigt, wenn die Registrierung geschlossen ist<br>Du kannst HTML-Tags benutzen
|
desc_html: Wird auf der Frontseite angezeigt, wenn die Registrierung geschlossen ist<br>Du kannst HTML-Tags benutzen
|
||||||
@@ -208,7 +208,7 @@ de:
|
|||||||
following: Folgeliste
|
following: Folgeliste
|
||||||
muting: Stummschaltungsliste
|
muting: Stummschaltungsliste
|
||||||
upload: Hochladen
|
upload: Hochladen
|
||||||
landing_strip_html: "<strong>%{name}</strong> ist ein Benutzer auf %{link_to_root_path}. Du kannst ihm folgen oder mit ihm interagieren, sofern du ein Konto irgendwo in der Fediverse hast."
|
landing_strip_html: "<strong>%{name}</strong> hat ein Profil auf %{link_to_root_path}. Du kannst folgen oder interagieren, sofern du ein Konto irgendwo im Fediversum hast."
|
||||||
landing_strip_signup_html: Wenn nicht, kannst du dich <a href="%{sign_up_path}">hier anmelden</a>.
|
landing_strip_signup_html: Wenn nicht, kannst du dich <a href="%{sign_up_path}">hier anmelden</a>.
|
||||||
media_attachments:
|
media_attachments:
|
||||||
validations:
|
validations:
|
||||||
@@ -239,12 +239,23 @@ de:
|
|||||||
reblog:
|
reblog:
|
||||||
body: 'Dein Beitrag wurde von %{name} geteilt:'
|
body: 'Dein Beitrag wurde von %{name} geteilt:'
|
||||||
subject: "%{name} teilte deinen Beitrag."
|
subject: "%{name} teilte deinen Beitrag."
|
||||||
|
number:
|
||||||
|
human:
|
||||||
|
decimal_units:
|
||||||
|
format: "%n%u"
|
||||||
|
units:
|
||||||
|
billion: B
|
||||||
|
million: M
|
||||||
|
quadrillion: Q
|
||||||
|
thousand: K
|
||||||
|
trillion: T
|
||||||
|
unit: ''
|
||||||
pagination:
|
pagination:
|
||||||
next: Vorwärts
|
next: Vorwärts
|
||||||
prev: Zurück
|
prev: Zurück
|
||||||
truncate: "…"
|
truncate: "…"
|
||||||
remote_follow:
|
remote_follow:
|
||||||
acct: Dein Nutzername@Domain, von dem aus du dieser Person folgen möchtest.
|
acct: Dein Profilname@Domain, von dem aus du dieser Person folgen möchtest.
|
||||||
missing_resource: Die erforderliche Weiterleitungs-URL konnte leider in deinem Profil nicht gefunden werden.
|
missing_resource: Die erforderliche Weiterleitungs-URL konnte leider in deinem Profil nicht gefunden werden.
|
||||||
proceed: Weiter
|
proceed: Weiter
|
||||||
prompt: 'Du wirst dieser Person folgen:'
|
prompt: 'Du wirst dieser Person folgen:'
|
||||||
|
@@ -77,7 +77,7 @@ de:
|
|||||||
invalid_grant: Die bereitgestellte Autorisierung ist inkorrekt, abgelaufen, widerrufen, ist mit einem anderen Client verknüpft oder der Redirection URI stimmt nicht mit der Autorisierungs-Anfrage überein.
|
invalid_grant: Die bereitgestellte Autorisierung ist inkorrekt, abgelaufen, widerrufen, ist mit einem anderen Client verknüpft oder der Redirection URI stimmt nicht mit der Autorisierungs-Anfrage überein.
|
||||||
invalid_redirect_uri: Der Redirect-URI in der Anfrage ist ungültig.
|
invalid_redirect_uri: Der Redirect-URI in der Anfrage ist ungültig.
|
||||||
invalid_request: Die Anfrage enthält einen nicht-unterstützten Parameter, ein Parameter fehlt oder sie ist anderweitig fehlerhaft.
|
invalid_request: Die Anfrage enthält einen nicht-unterstützten Parameter, ein Parameter fehlt oder sie ist anderweitig fehlerhaft.
|
||||||
invalid_resource_owner: Die angegebenen Zugangsdaten für den "Resource Owner" sind inkorrekt oder dieser Benutzer existiert nicht.
|
invalid_resource_owner: Die angegebenen Zugangsdaten für den "Resource Owner" sind inkorrekt oder dieses Profil existiert nicht.
|
||||||
invalid_scope: Der angeforderte Scope ist inkorrekt, unbekannt oder fehlerhaft.
|
invalid_scope: Der angeforderte Scope ist inkorrekt, unbekannt oder fehlerhaft.
|
||||||
invalid_token:
|
invalid_token:
|
||||||
expired: Der Zugriffstoken ist abgelaufen
|
expired: Der Zugriffstoken ist abgelaufen
|
||||||
@@ -108,6 +108,6 @@ de:
|
|||||||
application:
|
application:
|
||||||
title: OAuth-Autorisierung nötig
|
title: OAuth-Autorisierung nötig
|
||||||
scopes:
|
scopes:
|
||||||
follow: Nutzer folgen, blocken, entblocken und entfolgen
|
follow: Profil folgen, blocken, entblocken und entfolgen
|
||||||
read: deine Daten lesen
|
read: deine Daten lesen
|
||||||
write: Beiträge von deinem Konto aus veröffentlichen
|
write: Beiträge von deinem Konto aus veröffentlichen
|
||||||
|
@@ -3,8 +3,10 @@ fa:
|
|||||||
activerecord:
|
activerecord:
|
||||||
attributes:
|
attributes:
|
||||||
doorkeeper/application:
|
doorkeeper/application:
|
||||||
name: Name
|
name: Application name
|
||||||
redirect_uri: Redirect URI
|
redirect_uri: Redirect URI
|
||||||
|
scopes: Scopes
|
||||||
|
website: Application website
|
||||||
errors:
|
errors:
|
||||||
models:
|
models:
|
||||||
doorkeeper/application:
|
doorkeeper/application:
|
||||||
@@ -33,18 +35,22 @@ fa:
|
|||||||
redirect_uri: Use one line per URI
|
redirect_uri: Use one line per URI
|
||||||
scopes: Separate scopes with spaces. Leave blank to use the default scopes.
|
scopes: Separate scopes with spaces. Leave blank to use the default scopes.
|
||||||
index:
|
index:
|
||||||
|
application: Application
|
||||||
callback_url: Callback URL
|
callback_url: Callback URL
|
||||||
|
delete: Delete
|
||||||
name: Name
|
name: Name
|
||||||
new: New Application
|
new: New application
|
||||||
|
scopes: Scopes
|
||||||
|
show: Show
|
||||||
title: Your applications
|
title: Your applications
|
||||||
new:
|
new:
|
||||||
title: New Application
|
title: New application
|
||||||
show:
|
show:
|
||||||
actions: Actions
|
actions: Actions
|
||||||
application_id: Application Id
|
application_id: Client key
|
||||||
callback_urls: Callback urls
|
callback_urls: Callback URLs
|
||||||
scopes: Scopes
|
scopes: Scopes
|
||||||
secret: Secret
|
secret: Client secret
|
||||||
title: 'Application: %{name}'
|
title: 'Application: %{name}'
|
||||||
authorizations:
|
authorizations:
|
||||||
buttons:
|
buttons:
|
||||||
|
@@ -5,6 +5,8 @@ oc:
|
|||||||
doorkeeper/application:
|
doorkeeper/application:
|
||||||
name: Nom
|
name: Nom
|
||||||
redirect_uri: URL de redireccion
|
redirect_uri: URL de redireccion
|
||||||
|
scopes: Encastres
|
||||||
|
website: Aplicacion web
|
||||||
errors:
|
errors:
|
||||||
models:
|
models:
|
||||||
doorkeeper/application:
|
doorkeeper/application:
|
||||||
@@ -33,9 +35,13 @@ oc:
|
|||||||
redirect_uri: Utilizatz una linha per URI
|
redirect_uri: Utilizatz una linha per URI
|
||||||
scopes: Separatz los encastres amb d’espacis. Daissatz void per utilizar l’encastre per defaut.
|
scopes: Separatz los encastres amb d’espacis. Daissatz void per utilizar l’encastre per defaut.
|
||||||
index:
|
index:
|
||||||
|
application: Aplicacion
|
||||||
callback_url: URL de rapèl
|
callback_url: URL de rapèl
|
||||||
|
delete: Suprimir
|
||||||
name: Nom
|
name: Nom
|
||||||
new: Nòva aplicacion
|
new: Nòva aplicacion
|
||||||
|
scopes: Encastres
|
||||||
|
show: Veire
|
||||||
title: Vòstras aplicacions
|
title: Vòstras aplicacions
|
||||||
new:
|
new:
|
||||||
title: Nòva aplicacion
|
title: Nòva aplicacion
|
||||||
|
@@ -167,6 +167,9 @@ en:
|
|||||||
unresolved: Unresolved
|
unresolved: Unresolved
|
||||||
view: View
|
view: View
|
||||||
settings:
|
settings:
|
||||||
|
bootstrap_timeline_accounts:
|
||||||
|
desc_html: Separate multiple usernames by comma. Only local and unlocked accounts will work. Default when empty is all local admins.
|
||||||
|
title: Default follows for new users
|
||||||
contact_information:
|
contact_information:
|
||||||
email: Business e-mail
|
email: Business e-mail
|
||||||
username: Contact username
|
username: Contact username
|
||||||
|
@@ -103,6 +103,17 @@ eo:
|
|||||||
reblog:
|
reblog:
|
||||||
body: "%{name} diskonigis vian mesaĝon:"
|
body: "%{name} diskonigis vian mesaĝon:"
|
||||||
subject: "%{name} diskonigis vian mesaĝon"
|
subject: "%{name} diskonigis vian mesaĝon"
|
||||||
|
number:
|
||||||
|
human:
|
||||||
|
decimal_units:
|
||||||
|
format: "%n%u"
|
||||||
|
units:
|
||||||
|
billion: B
|
||||||
|
million: M
|
||||||
|
quadrillion: Q
|
||||||
|
thousand: K
|
||||||
|
trillion: T
|
||||||
|
unit: ''
|
||||||
pagination:
|
pagination:
|
||||||
next: Sekva
|
next: Sekva
|
||||||
prev: Malsekva
|
prev: Malsekva
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user