Merge remote-tracking branch 'upstream/master'
commit
7a1ca8b0df
|
@ -6,6 +6,7 @@ cache:
|
||||||
- node_modules
|
- node_modules
|
||||||
- public/assets
|
- public/assets
|
||||||
- public/packs-test
|
- public/packs-test
|
||||||
|
- tmp/cache/babel-loader
|
||||||
dist: trusty
|
dist: trusty
|
||||||
sudo: required
|
sudo: required
|
||||||
|
|
||||||
|
|
22
Dockerfile
22
Dockerfile
|
@ -7,6 +7,9 @@ ENV UID=991 GID=991 \
|
||||||
RAILS_SERVE_STATIC_FILES=true \
|
RAILS_SERVE_STATIC_FILES=true \
|
||||||
RAILS_ENV=production NODE_ENV=production
|
RAILS_ENV=production NODE_ENV=production
|
||||||
|
|
||||||
|
ARG LIBICONV_VERSION=1.15
|
||||||
|
ARG LIBICONV_DOWNLOAD_SHA256=ccf536620a45458d26ba83887a983b96827001e92a13847b45e4925cc8913178
|
||||||
|
|
||||||
EXPOSE 3000 4000
|
EXPOSE 3000 4000
|
||||||
|
|
||||||
WORKDIR /mastodon
|
WORKDIR /mastodon
|
||||||
|
@ -18,8 +21,7 @@ RUN echo "@edge https://nl.alpinelinux.org/alpine/edge/main" >> /etc/apk/reposit
|
||||||
build-base \
|
build-base \
|
||||||
icu-dev \
|
icu-dev \
|
||||||
libidn-dev \
|
libidn-dev \
|
||||||
libxml2-dev \
|
libtool \
|
||||||
libxslt-dev \
|
|
||||||
postgresql-dev \
|
postgresql-dev \
|
||||||
protobuf-dev \
|
protobuf-dev \
|
||||||
python \
|
python \
|
||||||
|
@ -32,8 +34,6 @@ RUN echo "@edge https://nl.alpinelinux.org/alpine/edge/main" >> /etc/apk/reposit
|
||||||
imagemagick@edge \
|
imagemagick@edge \
|
||||||
libidn \
|
libidn \
|
||||||
libpq \
|
libpq \
|
||||||
libxml2 \
|
|
||||||
libxslt \
|
|
||||||
nodejs-npm@edge \
|
nodejs-npm@edge \
|
||||||
nodejs@edge \
|
nodejs@edge \
|
||||||
protobuf \
|
protobuf \
|
||||||
|
@ -41,11 +41,23 @@ RUN echo "@edge https://nl.alpinelinux.org/alpine/edge/main" >> /etc/apk/reposit
|
||||||
tini \
|
tini \
|
||||||
yarn@edge \
|
yarn@edge \
|
||||||
&& update-ca-certificates \
|
&& update-ca-certificates \
|
||||||
|
&& wget -O libiconv.tar.gz "http://ftp.gnu.org/pub/gnu/libiconv/libiconv-$LIBICONV_VERSION.tar.gz" \
|
||||||
|
&& echo "$LIBICONV_DOWNLOAD_SHA256 *libiconv.tar.gz" | sha256sum -c - \
|
||||||
|
&& mkdir -p /tmp/src \
|
||||||
|
&& tar -xzf libiconv.tar.gz -C /tmp/src \
|
||||||
|
&& rm libiconv.tar.gz \
|
||||||
|
&& cd /tmp/src/libiconv-$LIBICONV_VERSION \
|
||||||
|
&& ./configure --prefix=/usr/local \
|
||||||
|
&& make -j$(getconf _NPROCESSORS_ONLN)\
|
||||||
|
&& make install \
|
||||||
|
&& libtool --finish /usr/local/lib \
|
||||||
|
&& cd /mastodon \
|
||||||
&& rm -rf /tmp/* /var/cache/apk/*
|
&& rm -rf /tmp/* /var/cache/apk/*
|
||||||
|
|
||||||
COPY Gemfile Gemfile.lock package.json yarn.lock /mastodon/
|
COPY Gemfile Gemfile.lock package.json yarn.lock /mastodon/
|
||||||
|
|
||||||
RUN bundle install --deployment --without test development \
|
RUN bundle config build.nokogiri --with-iconv-lib=/usr/local/lib --with-iconv-include=/usr/local/include \
|
||||||
|
&& bundle install -j$(getconf _NPROCESSORS_ONLN) --deployment --without test development \
|
||||||
&& yarn --ignore-optional --pure-lockfile
|
&& yarn --ignore-optional --pure-lockfile
|
||||||
|
|
||||||
COPY . /mastodon
|
COPY . /mastodon
|
||||||
|
|
120
Gemfile.lock
120
Gemfile.lock
|
@ -1,25 +1,25 @@
|
||||||
GEM
|
GEM
|
||||||
remote: https://rubygems.org/
|
remote: https://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
actioncable (5.1.2)
|
actioncable (5.1.3)
|
||||||
actionpack (= 5.1.2)
|
actionpack (= 5.1.3)
|
||||||
nio4r (~> 2.0)
|
nio4r (~> 2.0)
|
||||||
websocket-driver (~> 0.6.1)
|
websocket-driver (~> 0.6.1)
|
||||||
actionmailer (5.1.2)
|
actionmailer (5.1.3)
|
||||||
actionpack (= 5.1.2)
|
actionpack (= 5.1.3)
|
||||||
actionview (= 5.1.2)
|
actionview (= 5.1.3)
|
||||||
activejob (= 5.1.2)
|
activejob (= 5.1.3)
|
||||||
mail (~> 2.5, >= 2.5.4)
|
mail (~> 2.5, >= 2.5.4)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.0)
|
||||||
actionpack (5.1.2)
|
actionpack (5.1.3)
|
||||||
actionview (= 5.1.2)
|
actionview (= 5.1.3)
|
||||||
activesupport (= 5.1.2)
|
activesupport (= 5.1.3)
|
||||||
rack (~> 2.0)
|
rack (~> 2.0)
|
||||||
rack-test (~> 0.6.3)
|
rack-test (~> 0.6.3)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.0)
|
||||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||||
actionview (5.1.2)
|
actionview (5.1.3)
|
||||||
activesupport (= 5.1.2)
|
activesupport (= 5.1.3)
|
||||||
builder (~> 3.1)
|
builder (~> 3.1)
|
||||||
erubi (~> 1.4)
|
erubi (~> 1.4)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.0)
|
||||||
|
@ -30,16 +30,16 @@ GEM
|
||||||
case_transform (>= 0.2)
|
case_transform (>= 0.2)
|
||||||
jsonapi-renderer (>= 0.1.1.beta1, < 0.2)
|
jsonapi-renderer (>= 0.1.1.beta1, < 0.2)
|
||||||
active_record_query_trace (1.5.4)
|
active_record_query_trace (1.5.4)
|
||||||
activejob (5.1.2)
|
activejob (5.1.3)
|
||||||
activesupport (= 5.1.2)
|
activesupport (= 5.1.3)
|
||||||
globalid (>= 0.3.6)
|
globalid (>= 0.3.6)
|
||||||
activemodel (5.1.2)
|
activemodel (5.1.3)
|
||||||
activesupport (= 5.1.2)
|
activesupport (= 5.1.3)
|
||||||
activerecord (5.1.2)
|
activerecord (5.1.3)
|
||||||
activemodel (= 5.1.2)
|
activemodel (= 5.1.3)
|
||||||
activesupport (= 5.1.2)
|
activesupport (= 5.1.3)
|
||||||
arel (~> 8.0)
|
arel (~> 8.0)
|
||||||
activesupport (5.1.2)
|
activesupport (5.1.3)
|
||||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||||
i18n (~> 0.7)
|
i18n (~> 0.7)
|
||||||
minitest (~> 5.1)
|
minitest (~> 5.1)
|
||||||
|
@ -57,14 +57,14 @@ GEM
|
||||||
encryptor (~> 3.0.0)
|
encryptor (~> 3.0.0)
|
||||||
av (0.9.0)
|
av (0.9.0)
|
||||||
cocaine (~> 0.5.3)
|
cocaine (~> 0.5.3)
|
||||||
aws-sdk (2.10.6)
|
aws-sdk (2.10.21)
|
||||||
aws-sdk-resources (= 2.10.6)
|
aws-sdk-resources (= 2.10.21)
|
||||||
aws-sdk-core (2.10.6)
|
aws-sdk-core (2.10.21)
|
||||||
aws-sigv4 (~> 1.0)
|
aws-sigv4 (~> 1.0)
|
||||||
jmespath (~> 1.0)
|
jmespath (~> 1.0)
|
||||||
aws-sdk-resources (2.10.6)
|
aws-sdk-resources (2.10.21)
|
||||||
aws-sdk-core (= 2.10.6)
|
aws-sdk-core (= 2.10.21)
|
||||||
aws-sigv4 (1.0.0)
|
aws-sigv4 (1.0.1)
|
||||||
bcrypt (3.1.11)
|
bcrypt (3.1.11)
|
||||||
better_errors (2.1.1)
|
better_errors (2.1.1)
|
||||||
coderay (>= 1.0.0)
|
coderay (>= 1.0.0)
|
||||||
|
@ -72,7 +72,7 @@ GEM
|
||||||
rack (>= 0.9.0)
|
rack (>= 0.9.0)
|
||||||
binding_of_caller (0.7.2)
|
binding_of_caller (0.7.2)
|
||||||
debug_inspector (>= 0.0.1)
|
debug_inspector (>= 0.0.1)
|
||||||
bootsnap (1.1.1)
|
bootsnap (1.1.2)
|
||||||
msgpack (~> 1.0)
|
msgpack (~> 1.0)
|
||||||
brakeman (3.6.2)
|
brakeman (3.6.2)
|
||||||
browser (2.4.0)
|
browser (2.4.0)
|
||||||
|
@ -155,7 +155,7 @@ GEM
|
||||||
et-orbi (1.0.5)
|
et-orbi (1.0.5)
|
||||||
tzinfo
|
tzinfo
|
||||||
execjs (2.7.0)
|
execjs (2.7.0)
|
||||||
fabrication (2.16.1)
|
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)
|
||||||
|
@ -165,7 +165,7 @@ GEM
|
||||||
ruby-progressbar (~> 1.4)
|
ruby-progressbar (~> 1.4)
|
||||||
globalid (0.4.0)
|
globalid (0.4.0)
|
||||||
activesupport (>= 4.2.0)
|
activesupport (>= 4.2.0)
|
||||||
goldfinger (2.0.0)
|
goldfinger (2.0.1)
|
||||||
addressable (~> 2.5)
|
addressable (~> 2.5)
|
||||||
http (~> 2.2)
|
http (~> 2.2)
|
||||||
nokogiri (~> 1.8)
|
nokogiri (~> 1.8)
|
||||||
|
@ -179,7 +179,7 @@ GEM
|
||||||
activesupport (>= 4.0.1)
|
activesupport (>= 4.0.1)
|
||||||
hamlit (>= 1.2.0)
|
hamlit (>= 1.2.0)
|
||||||
railties (>= 4.0.1)
|
railties (>= 4.0.1)
|
||||||
hashdiff (0.3.4)
|
hashdiff (0.3.5)
|
||||||
highline (1.7.8)
|
highline (1.7.8)
|
||||||
hiredis (0.6.1)
|
hiredis (0.6.1)
|
||||||
hkdf (0.3.0)
|
hkdf (0.3.0)
|
||||||
|
@ -194,11 +194,11 @@ GEM
|
||||||
http-form_data (1.0.3)
|
http-form_data (1.0.3)
|
||||||
http_accept_language (2.1.1)
|
http_accept_language (2.1.1)
|
||||||
http_parser.rb (0.6.0)
|
http_parser.rb (0.6.0)
|
||||||
httplog (0.99.4)
|
httplog (0.99.7)
|
||||||
colorize
|
colorize
|
||||||
rack
|
rack
|
||||||
i18n (0.8.4)
|
i18n (0.8.6)
|
||||||
i18n-tasks (0.9.15)
|
i18n-tasks (0.9.16)
|
||||||
activesupport (>= 4.0.2)
|
activesupport (>= 4.0.2)
|
||||||
ast (>= 2.1.0)
|
ast (>= 2.1.0)
|
||||||
easy_translate (>= 0.5.0)
|
easy_translate (>= 0.5.0)
|
||||||
|
@ -211,7 +211,7 @@ GEM
|
||||||
idn-ruby (0.1.0)
|
idn-ruby (0.1.0)
|
||||||
jmespath (1.3.1)
|
jmespath (1.3.1)
|
||||||
json (2.1.0)
|
json (2.1.0)
|
||||||
jsonapi-renderer (0.1.2)
|
jsonapi-renderer (0.1.3)
|
||||||
jwt (1.5.6)
|
jwt (1.5.6)
|
||||||
kaminari (1.0.1)
|
kaminari (1.0.1)
|
||||||
activesupport (>= 4.1.0)
|
activesupport (>= 4.1.0)
|
||||||
|
@ -253,7 +253,7 @@ GEM
|
||||||
mime-types-data (3.2016.0521)
|
mime-types-data (3.2016.0521)
|
||||||
mimemagic (0.3.2)
|
mimemagic (0.3.2)
|
||||||
mini_portile2 (2.2.0)
|
mini_portile2 (2.2.0)
|
||||||
minitest (5.10.2)
|
minitest (5.10.3)
|
||||||
msgpack (1.1.0)
|
msgpack (1.1.0)
|
||||||
multi_json (1.12.1)
|
multi_json (1.12.1)
|
||||||
net-scp (1.2.1)
|
net-scp (1.2.1)
|
||||||
|
@ -264,7 +264,7 @@ GEM
|
||||||
mini_portile2 (~> 2.2.0)
|
mini_portile2 (~> 2.2.0)
|
||||||
nokogumbo (1.4.13)
|
nokogumbo (1.4.13)
|
||||||
nokogiri
|
nokogiri
|
||||||
oj (3.2.0)
|
oj (3.3.4)
|
||||||
openssl (2.0.4)
|
openssl (2.0.4)
|
||||||
orm_adapter (0.5.0)
|
orm_adapter (0.5.0)
|
||||||
ostatus2 (2.0.1)
|
ostatus2 (2.0.1)
|
||||||
|
@ -283,14 +283,14 @@ GEM
|
||||||
av (~> 0.9.0)
|
av (~> 0.9.0)
|
||||||
paperclip (>= 2.5.2)
|
paperclip (>= 2.5.2)
|
||||||
parallel (1.11.2)
|
parallel (1.11.2)
|
||||||
parallel_tests (2.14.1)
|
parallel_tests (2.14.2)
|
||||||
parallel
|
parallel
|
||||||
parser (2.4.0.0)
|
parser (2.4.0.0)
|
||||||
ast (~> 2.2)
|
ast (~> 2.2)
|
||||||
pg (0.21.0)
|
pg (0.21.0)
|
||||||
pghero (1.7.0)
|
pghero (1.7.0)
|
||||||
activerecord
|
activerecord
|
||||||
pkg-config (1.2.3)
|
pkg-config (1.2.4)
|
||||||
powerpack (0.1.1)
|
powerpack (0.1.1)
|
||||||
pry (0.10.4)
|
pry (0.10.4)
|
||||||
coderay (~> 1.1.0)
|
coderay (~> 1.1.0)
|
||||||
|
@ -313,17 +313,17 @@ GEM
|
||||||
rack-test (0.6.3)
|
rack-test (0.6.3)
|
||||||
rack (>= 1.0)
|
rack (>= 1.0)
|
||||||
rack-timeout (0.4.2)
|
rack-timeout (0.4.2)
|
||||||
rails (5.1.2)
|
rails (5.1.3)
|
||||||
actioncable (= 5.1.2)
|
actioncable (= 5.1.3)
|
||||||
actionmailer (= 5.1.2)
|
actionmailer (= 5.1.3)
|
||||||
actionpack (= 5.1.2)
|
actionpack (= 5.1.3)
|
||||||
actionview (= 5.1.2)
|
actionview (= 5.1.3)
|
||||||
activejob (= 5.1.2)
|
activejob (= 5.1.3)
|
||||||
activemodel (= 5.1.2)
|
activemodel (= 5.1.3)
|
||||||
activerecord (= 5.1.2)
|
activerecord (= 5.1.3)
|
||||||
activesupport (= 5.1.2)
|
activesupport (= 5.1.3)
|
||||||
bundler (>= 1.3.0, < 2.0)
|
bundler (>= 1.3.0)
|
||||||
railties (= 5.1.2)
|
railties (= 5.1.3)
|
||||||
sprockets-rails (>= 2.0.0)
|
sprockets-rails (>= 2.0.0)
|
||||||
rails-controller-testing (1.0.2)
|
rails-controller-testing (1.0.2)
|
||||||
actionpack (~> 5.x, >= 5.0.1)
|
actionpack (~> 5.x, >= 5.0.1)
|
||||||
|
@ -337,11 +337,11 @@ GEM
|
||||||
rails-i18n (5.0.4)
|
rails-i18n (5.0.4)
|
||||||
i18n (~> 0.7)
|
i18n (~> 0.7)
|
||||||
railties (~> 5.0)
|
railties (~> 5.0)
|
||||||
rails-settings-cached (0.6.5)
|
rails-settings-cached (0.6.6)
|
||||||
rails (>= 4.2.0)
|
rails (>= 4.2.0)
|
||||||
railties (5.1.2)
|
railties (5.1.3)
|
||||||
actionpack (= 5.1.2)
|
actionpack (= 5.1.3)
|
||||||
activesupport (= 5.1.2)
|
activesupport (= 5.1.3)
|
||||||
method_source
|
method_source
|
||||||
rake (>= 0.8.7)
|
rake (>= 0.8.7)
|
||||||
thor (>= 0.18.1, < 2.0)
|
thor (>= 0.18.1, < 2.0)
|
||||||
|
@ -353,7 +353,7 @@ GEM
|
||||||
actionpack (>= 4.0, < 6)
|
actionpack (>= 4.0, < 6)
|
||||||
redis-rack (>= 1, < 3)
|
redis-rack (>= 1, < 3)
|
||||||
redis-store (>= 1.1.0, < 1.4.0)
|
redis-store (>= 1.1.0, < 1.4.0)
|
||||||
redis-activesupport (5.0.2)
|
redis-activesupport (5.0.3)
|
||||||
activesupport (>= 3, < 6)
|
activesupport (>= 3, < 6)
|
||||||
redis-store (~> 1.3.0)
|
redis-store (~> 1.3.0)
|
||||||
redis-namespace (1.5.3)
|
redis-namespace (1.5.3)
|
||||||
|
@ -413,7 +413,7 @@ GEM
|
||||||
scss_lint (0.54.0)
|
scss_lint (0.54.0)
|
||||||
rake (>= 0.9, < 13)
|
rake (>= 0.9, < 13)
|
||||||
sass (~> 3.4.20)
|
sass (~> 3.4.20)
|
||||||
sidekiq (5.0.3)
|
sidekiq (5.0.4)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
connection_pool (~> 2.2, >= 2.2.0)
|
connection_pool (~> 2.2, >= 2.2.0)
|
||||||
rack-protection (>= 1.5.0)
|
rack-protection (>= 1.5.0)
|
||||||
|
@ -421,12 +421,12 @@ GEM
|
||||||
sidekiq-bulk (0.1.1)
|
sidekiq-bulk (0.1.1)
|
||||||
activesupport
|
activesupport
|
||||||
sidekiq
|
sidekiq
|
||||||
sidekiq-scheduler (2.1.7)
|
sidekiq-scheduler (2.1.8)
|
||||||
redis (~> 3)
|
redis (~> 3)
|
||||||
rufus-scheduler (~> 3.2)
|
rufus-scheduler (~> 3.2)
|
||||||
sidekiq (>= 3)
|
sidekiq (>= 3)
|
||||||
tilt (>= 1.4.0)
|
tilt (>= 1.4.0)
|
||||||
sidekiq-unique-jobs (5.0.8)
|
sidekiq-unique-jobs (5.0.9)
|
||||||
sidekiq (>= 4.0, <= 6.0)
|
sidekiq (>= 4.0, <= 6.0)
|
||||||
thor (~> 0)
|
thor (~> 0)
|
||||||
simple-navigation (4.0.5)
|
simple-navigation (4.0.5)
|
||||||
|
@ -450,15 +450,15 @@ GEM
|
||||||
sshkit (1.13.1)
|
sshkit (1.13.1)
|
||||||
net-scp (>= 1.1.2)
|
net-scp (>= 1.1.2)
|
||||||
net-ssh (>= 2.8.0)
|
net-ssh (>= 2.8.0)
|
||||||
statsd-instrument (2.1.2)
|
statsd-instrument (2.1.4)
|
||||||
temple (0.8.0)
|
temple (0.8.0)
|
||||||
terminal-table (1.8.0)
|
terminal-table (1.8.0)
|
||||||
unicode-display_width (~> 1.1, >= 1.1.1)
|
unicode-display_width (~> 1.1, >= 1.1.1)
|
||||||
thor (0.19.4)
|
thor (0.19.4)
|
||||||
thread (0.2.2)
|
thread (0.2.2)
|
||||||
thread_safe (0.3.6)
|
thread_safe (0.3.6)
|
||||||
tilt (2.0.7)
|
tilt (2.0.8)
|
||||||
twitter-text (1.14.6)
|
twitter-text (1.14.7)
|
||||||
unf (~> 0.1.0)
|
unf (~> 0.1.0)
|
||||||
tzinfo (1.2.3)
|
tzinfo (1.2.3)
|
||||||
thread_safe (~> 0.1)
|
thread_safe (~> 0.1)
|
||||||
|
@ -590,4 +590,4 @@ RUBY VERSION
|
||||||
ruby 2.4.1p111
|
ruby 2.4.1p111
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
1.15.2
|
1.15.3
|
||||||
|
|
|
@ -43,6 +43,10 @@ class ApplicationController < ActionController::Base
|
||||||
forbidden if current_user.account.suspended?
|
forbidden if current_user.account.suspended?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def after_sign_out_path_for(_resource_or_scope)
|
||||||
|
new_user_session_path
|
||||||
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def forbidden
|
def forbidden
|
||||||
|
|
|
@ -1,5 +1,20 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Auth::PasswordsController < Devise::PasswordsController
|
class Auth::PasswordsController < Devise::PasswordsController
|
||||||
|
before_action :check_validity_of_reset_password_token, only: :edit
|
||||||
|
|
||||||
layout 'auth'
|
layout 'auth'
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def check_validity_of_reset_password_token
|
||||||
|
unless reset_password_token_is_valid?
|
||||||
|
flash[:error] = I18n.t('auth.invalid_reset_password_token')
|
||||||
|
redirect_to new_password_path(resource_name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def reset_password_token_is_valid?
|
||||||
|
resource_class.with_reset_password_token(params[:reset_password_token]).present?
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class AuthorizeFollowsController < ApplicationController
|
class AuthorizeFollowsController < ApplicationController
|
||||||
layout 'public'
|
layout 'modal'
|
||||||
|
|
||||||
before_action :authenticate_user!
|
before_action :authenticate_user!
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class RemoteFollowController < ApplicationController
|
class RemoteFollowController < ApplicationController
|
||||||
layout 'public'
|
layout 'modal'
|
||||||
|
|
||||||
before_action :set_account
|
before_action :set_account
|
||||||
before_action :gone, if: :suspended_account?
|
before_action :gone, if: :suspended_account?
|
||||||
|
|
|
@ -23,6 +23,9 @@ export const STATUS_UNMUTE_REQUEST = 'STATUS_UNMUTE_REQUEST';
|
||||||
export const STATUS_UNMUTE_SUCCESS = 'STATUS_UNMUTE_SUCCESS';
|
export const STATUS_UNMUTE_SUCCESS = 'STATUS_UNMUTE_SUCCESS';
|
||||||
export const STATUS_UNMUTE_FAIL = 'STATUS_UNMUTE_FAIL';
|
export const STATUS_UNMUTE_FAIL = 'STATUS_UNMUTE_FAIL';
|
||||||
|
|
||||||
|
export const STATUS_SET_HEIGHT = 'STATUS_SET_HEIGHT';
|
||||||
|
export const STATUSES_CLEAR_HEIGHT = 'STATUSES_CLEAR_HEIGHT';
|
||||||
|
|
||||||
export function fetchStatusRequest(id, skipLoading) {
|
export function fetchStatusRequest(id, skipLoading) {
|
||||||
return {
|
return {
|
||||||
type: STATUS_FETCH_REQUEST,
|
type: STATUS_FETCH_REQUEST,
|
||||||
|
@ -215,3 +218,17 @@ export function unmuteStatusFail(id, error) {
|
||||||
error,
|
error,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function setStatusHeight (id, height) {
|
||||||
|
return {
|
||||||
|
type: STATUS_SET_HEIGHT,
|
||||||
|
id,
|
||||||
|
height,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export function clearStatusesHeight () {
|
||||||
|
return {
|
||||||
|
type: STATUSES_CLEAR_HEIGHT,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import detectPassiveEvents from 'detect-passive-events';
|
import detectPassiveEvents from 'detect-passive-events';
|
||||||
import scrollTop from '../scroll';
|
import { scrollTop } from '../scroll';
|
||||||
|
|
||||||
export default class Column extends React.PureComponent {
|
export default class Column extends React.PureComponent {
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import escapeTextContentForBrowser from 'escape-html';
|
|
||||||
import emojify from '../emoji';
|
|
||||||
|
|
||||||
export default class DisplayName extends React.PureComponent {
|
export default class DisplayName extends React.PureComponent {
|
||||||
|
|
||||||
|
@ -10,12 +8,11 @@ export default class DisplayName extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const displayName = this.props.account.get('display_name').length === 0 ? this.props.account.get('username') : this.props.account.get('display_name');
|
const displayNameHtml = { __html: this.props.account.get('display_name_html') };
|
||||||
const displayNameHTML = { __html: emojify(escapeTextContentForBrowser(displayName)) };
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span className='display-name'>
|
<span className='display-name'>
|
||||||
<strong className='display-name__html' dangerouslySetInnerHTML={displayNameHTML} /> <span className='display-name__account'>@{this.props.account.get('acct')}</span>
|
<strong className='display-name__html' dangerouslySetInnerHTML={displayNameHtml} /> <span className='display-name__account'>@{this.props.account.get('acct')}</span>
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,6 @@ import DisplayName from './display_name';
|
||||||
import StatusContent from './status_content';
|
import StatusContent from './status_content';
|
||||||
import StatusActionBar from './status_action_bar';
|
import StatusActionBar from './status_action_bar';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import emojify from '../emoji';
|
|
||||||
import escapeTextContentForBrowser from 'escape-html';
|
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import scheduleIdleTask from '../features/ui/util/schedule_idle_task';
|
import scheduleIdleTask from '../features/ui/util/schedule_idle_task';
|
||||||
import { MediaGallery, VideoPlayer } from '../features/ui/util/async-components';
|
import { MediaGallery, VideoPlayer } from '../features/ui/util/async-components';
|
||||||
|
@ -39,6 +37,7 @@ export default class Status extends ImmutablePureComponent {
|
||||||
onOpenMedia: PropTypes.func,
|
onOpenMedia: PropTypes.func,
|
||||||
onOpenVideo: PropTypes.func,
|
onOpenVideo: PropTypes.func,
|
||||||
onBlock: PropTypes.func,
|
onBlock: PropTypes.func,
|
||||||
|
onHeightChange: PropTypes.func,
|
||||||
me: PropTypes.number,
|
me: PropTypes.number,
|
||||||
boostModal: PropTypes.bool,
|
boostModal: PropTypes.bool,
|
||||||
autoPlayGif: PropTypes.bool,
|
autoPlayGif: PropTypes.bool,
|
||||||
|
@ -50,7 +49,6 @@ export default class Status extends ImmutablePureComponent {
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
isExpanded: false,
|
isExpanded: false,
|
||||||
isIntersecting: true, // assume intersecting until told otherwise
|
|
||||||
isHidden: false, // set to true in requestIdleCallback to trigger un-render
|
isHidden: false, // set to true in requestIdleCallback to trigger un-render
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,6 +109,10 @@ export default class Status extends ImmutablePureComponent {
|
||||||
if (this.node && this.node.children.length !== 0) {
|
if (this.node && this.node.children.length !== 0) {
|
||||||
// save the height of the fully-rendered element
|
// save the height of the fully-rendered element
|
||||||
this.height = getRectFromEntry(entry).height;
|
this.height = getRectFromEntry(entry).height;
|
||||||
|
|
||||||
|
if (this.props.onHeightChange) {
|
||||||
|
this.props.onHeightChange(this.props.status, this.height);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState((prevState) => {
|
this.setState((prevState) => {
|
||||||
|
@ -182,9 +184,13 @@ export default class Status extends ImmutablePureComponent {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isIntersecting && isHidden) {
|
const hasIntersectionObserverWrapper = !!this.props.intersectionObserverWrapper;
|
||||||
|
const isHiddenForSure = isIntersecting === false && isHidden;
|
||||||
|
const visibilityUnknownButHeightIsCached = isIntersecting === undefined && status.has('height');
|
||||||
|
|
||||||
|
if (hasIntersectionObserverWrapper && (isHiddenForSure || visibilityUnknownButHeightIsCached)) {
|
||||||
return (
|
return (
|
||||||
<article ref={this.handleRef} data-id={status.get('id')} aria-posinset={index} aria-setsize={listLength} tabIndex='0' style={{ height: `${this.height}px`, opacity: 0, overflow: 'hidden' }}>
|
<article ref={this.handleRef} data-id={status.get('id')} aria-posinset={index} aria-setsize={listLength} tabIndex='0' style={{ height: `${this.height || status.get('height')}px`, opacity: 0, overflow: 'hidden' }}>
|
||||||
{status.getIn(['account', 'display_name']) || status.getIn(['account', 'username'])}
|
{status.getIn(['account', 'display_name']) || status.getIn(['account', 'username'])}
|
||||||
{status.get('content')}
|
{status.get('content')}
|
||||||
</article>
|
</article>
|
||||||
|
@ -192,19 +198,13 @@ export default class Status extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status.get('reblog', null) !== null && typeof status.get('reblog') === 'object') {
|
if (status.get('reblog', null) !== null && typeof status.get('reblog') === 'object') {
|
||||||
let displayName = status.getIn(['account', 'display_name']);
|
const display_name_html = { __html: status.getIn(['account', 'display_name_html']) };
|
||||||
|
|
||||||
if (displayName.length === 0) {
|
|
||||||
displayName = status.getIn(['account', 'username']);
|
|
||||||
}
|
|
||||||
|
|
||||||
const displayNameHTML = { __html: emojify(escapeTextContentForBrowser(displayName)) };
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<article className='status__wrapper' ref={this.handleRef} data-id={status.get('id')} aria-posinset={index} aria-setsize={listLength} tabIndex='0'>
|
<article className='status__wrapper' ref={this.handleRef} data-id={status.get('id')} aria-posinset={index} aria-setsize={listLength} tabIndex='0'>
|
||||||
<div className='status__prepend'>
|
<div className='status__prepend'>
|
||||||
<div className='status__prepend-icon-wrapper'><i className='fa fa-fw fa-retweet status__prepend-icon' /></div>
|
<div className='status__prepend-icon-wrapper'><i className='fa fa-fw fa-retweet status__prepend-icon' /></div>
|
||||||
<FormattedMessage id='status.reblogged_by' defaultMessage='{name} boosted' values={{ name: <a onClick={this.handleAccountClick} data-id={status.getIn(['account', 'id'])} href={status.getIn(['account', 'url'])} className='status__display-name muted'><strong dangerouslySetInnerHTML={displayNameHTML} /></a> }} />
|
<FormattedMessage id='status.reblogged_by' defaultMessage='{name} boosted' values={{ name: <a onClick={this.handleAccountClick} data-id={status.getIn(['account', 'id'])} href={status.getIn(['account', 'url'])} className='status__display-name muted'><strong dangerouslySetInnerHTML={display_name_html} /></a> }} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Status {...other} wrapped status={status.get('reblog')} account={status.get('account')} />
|
<Status {...other} wrapped status={status.get('reblog')} account={status.get('account')} />
|
||||||
|
|
|
@ -3,9 +3,7 @@
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import escapeTextContentForBrowser from 'escape-html';
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import emojify from '../emoji';
|
|
||||||
import { isRtl } from '../rtl';
|
import { isRtl } from '../rtl';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import Permalink from './permalink';
|
import Permalink from './permalink';
|
||||||
|
@ -122,8 +120,8 @@ export default class StatusContent extends React.PureComponent {
|
||||||
|
|
||||||
const hidden = this.props.onExpandedToggle ? !this.props.expanded : this.state.hidden;
|
const hidden = this.props.onExpandedToggle ? !this.props.expanded : this.state.hidden;
|
||||||
|
|
||||||
const content = { __html: emojify(status.get('content')) };
|
const content = { __html: status.get('contentHtml') };
|
||||||
const spoilerContent = { __html: emojify(escapeTextContentForBrowser(status.get('spoiler_text', ''))) };
|
const spoilerContent = { __html: status.get('spoilerHtml') };
|
||||||
const directionStyle = { direction: 'ltr' };
|
const directionStyle = { direction: 'ltr' };
|
||||||
const classNames = classnames('status__content', {
|
const classNames = classnames('status__content', {
|
||||||
'status__content--with-action': this.props.onClick && this.context.router,
|
'status__content--with-action': this.props.onClick && this.context.router,
|
||||||
|
|
|
@ -105,7 +105,7 @@ export default class StatusList extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
handleKeyDown = (e) => {
|
handleKeyDown = (e) => {
|
||||||
if (['PageDown', 'PageUp', 'End', 'Home'].includes(e.key)) {
|
if (['PageDown', 'PageUp'].includes(e.key) || (e.ctrlKey && ['End', 'Home'].includes(e.key))) {
|
||||||
const article = (() => {
|
const article = (() => {
|
||||||
switch (e.key) {
|
switch (e.key) {
|
||||||
case 'PageDown':
|
case 'PageDown':
|
||||||
|
|
|
@ -19,7 +19,7 @@ import {
|
||||||
blockAccount,
|
blockAccount,
|
||||||
muteAccount,
|
muteAccount,
|
||||||
} from '../actions/accounts';
|
} from '../actions/accounts';
|
||||||
import { muteStatus, unmuteStatus, deleteStatus } from '../actions/statuses';
|
import { muteStatus, unmuteStatus, deleteStatus, setStatusHeight } from '../actions/statuses';
|
||||||
import { initReport } from '../actions/reports';
|
import { initReport } from '../actions/reports';
|
||||||
import { openModal } from '../actions/modal';
|
import { openModal } from '../actions/modal';
|
||||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||||
|
@ -127,6 +127,10 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onHeightChange (status, height) {
|
||||||
|
dispatch(setStatusHeight(status.get('id'), height));
|
||||||
|
},
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default injectIntl(connect(makeMapStateToProps, mapDispatchToProps)(Status));
|
export default injectIntl(connect(makeMapStateToProps, mapDispatchToProps)(Status));
|
||||||
|
|
|
@ -3,34 +3,28 @@ import Trie from 'substring-trie';
|
||||||
|
|
||||||
const trie = new Trie(Object.keys(unicodeMapping));
|
const trie = new Trie(Object.keys(unicodeMapping));
|
||||||
|
|
||||||
const excluded = ['™', '©', '®'];
|
const emojify = str => {
|
||||||
|
let rtn = '';
|
||||||
function emojify(str) {
|
for (;;) {
|
||||||
// This walks through the string from start to end, ignoring any tags (<p>, <br>, etc.)
|
let match, i = 0;
|
||||||
// and replacing valid unicode strings
|
while (i < str.length && str[i] !== '<' && !(match = trie.search(str.slice(i)))) {
|
||||||
// that _aren't_ within tags with an <img> version.
|
i += str.codePointAt(i) < 65536 ? 1 : 2;
|
||||||
// The goal is to be the same as an emojione.regUnicode replacement, but faster.
|
}
|
||||||
let i = -1;
|
if (i === str.length)
|
||||||
let insideTag = false;
|
break;
|
||||||
let match;
|
else if (str[i] === '<') {
|
||||||
while (++i < str.length) {
|
let tagend = str.indexOf('>', i + 1) + 1;
|
||||||
const char = str.charAt(i);
|
if (!tagend)
|
||||||
if (insideTag && char === '>') {
|
break;
|
||||||
insideTag = false;
|
rtn += str.slice(0, tagend);
|
||||||
} else if (char === '<') {
|
str = str.slice(tagend);
|
||||||
insideTag = true;
|
} else {
|
||||||
} else if (!insideTag && (match = trie.search(str.substring(i)))) {
|
const [filename, shortCode] = unicodeMapping[match];
|
||||||
const unicodeStr = match;
|
rtn += str.slice(0, i) + `<img draggable="false" class="emojione" alt="${match}" title=":${shortCode}:" src="/emoji/${filename}.svg" />`;
|
||||||
if (unicodeStr in unicodeMapping && excluded.indexOf(unicodeStr) === -1) {
|
str = str.slice(i + match.length);
|
||||||
const [filename, shortCode] = unicodeMapping[unicodeStr];
|
|
||||||
const alt = unicodeStr;
|
|
||||||
const replacement = `<img draggable="false" class="emojione" alt="${alt}" title=":${shortCode}:" src="/emoji/${filename}.svg" />`;
|
|
||||||
str = str.substring(0, i) + replacement + str.substring(i + unicodeStr.length);
|
|
||||||
i += (replacement.length - unicodeStr.length); // jump ahead the length we've added to the string
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return str;
|
return rtn + str;
|
||||||
}
|
};
|
||||||
|
|
||||||
export default emojify;
|
export default emojify;
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
const emojione = require('emojione');
|
const emojione = require('emojione');
|
||||||
|
|
||||||
const mappedUnicode = emojione.mapUnicodeToShort();
|
const mappedUnicode = emojione.mapUnicodeToShort();
|
||||||
|
const excluded = ['®', '©', '™'];
|
||||||
|
|
||||||
module.exports.unicodeMapping = Object.keys(emojione.jsEscapeMap)
|
module.exports.unicodeMapping = Object.keys(emojione.jsEscapeMap)
|
||||||
|
.filter(c => !excluded.includes(c))
|
||||||
.map(unicodeStr => [unicodeStr, mappedUnicode[emojione.jsEscapeMap[unicodeStr]]])
|
.map(unicodeStr => [unicodeStr, mappedUnicode[emojione.jsEscapeMap[unicodeStr]]])
|
||||||
.map(([unicodeStr, shortCode]) => ({ [unicodeStr]: [emojione.emojioneList[shortCode].fname, shortCode.slice(1, shortCode.length - 1)] }))
|
.map(([unicodeStr, shortCode]) => ({ [unicodeStr]: [emojione.emojioneList[shortCode].fname, shortCode.slice(1, shortCode.length - 1)] }))
|
||||||
.reduce((x, y) => Object.assign(x, y), { });
|
.reduce((x, y) => Object.assign(x, y), { });
|
||||||
|
|
|
@ -4,8 +4,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import emojify from '../../../emoji';
|
|
||||||
import escapeTextContentForBrowser from 'escape-html';
|
|
||||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||||
import IconButton from '../../../components/icon_button';
|
import IconButton from '../../../components/icon_button';
|
||||||
import Motion from 'react-motion/lib/Motion';
|
import Motion from 'react-motion/lib/Motion';
|
||||||
|
@ -95,15 +93,10 @@ export default class Header extends ImmutablePureComponent {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let displayName = account.get('display_name');
|
|
||||||
let info = '';
|
let info = '';
|
||||||
let actionBtn = '';
|
let actionBtn = '';
|
||||||
let lockedIcon = '';
|
let lockedIcon = '';
|
||||||
|
|
||||||
if (displayName.length === 0) {
|
|
||||||
displayName = account.get('username');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (me !== account.get('id') && account.getIn(['relationship', 'followed_by'])) {
|
if (me !== account.get('id') && account.getIn(['relationship', 'followed_by'])) {
|
||||||
info = <span className='account--follows-info'><FormattedMessage id='account.follows_you' defaultMessage='Follows you' /></span>;
|
info = <span className='account--follows-info'><FormattedMessage id='account.follows_you' defaultMessage='Follows you' /></span>;
|
||||||
}
|
}
|
||||||
|
@ -128,15 +121,15 @@ export default class Header extends ImmutablePureComponent {
|
||||||
lockedIcon = <i className='fa fa-lock' />;
|
lockedIcon = <i className='fa fa-lock' />;
|
||||||
}
|
}
|
||||||
|
|
||||||
const content = { __html: emojify(account.get('note')) };
|
const content = { __html: account.get('note_emojified') };
|
||||||
const displayNameHTML = { __html: emojify(escapeTextContentForBrowser(displayName)) };
|
const displayNameHtml = { __html: account.get('display_name_html') };
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='account__header' style={{ backgroundImage: `url(${account.get('header')})` }}>
|
<div className='account__header' style={{ backgroundImage: `url(${account.get('header')})` }}>
|
||||||
<div>
|
<div>
|
||||||
<Avatar account={account} autoPlayGif={this.props.autoPlayGif} />
|
<Avatar account={account} autoPlayGif={this.props.autoPlayGif} />
|
||||||
|
|
||||||
<span className='account__header__display-name' dangerouslySetInnerHTML={displayNameHTML} />
|
<span className='account__header__display-name' dangerouslySetInnerHTML={displayNameHtml} />
|
||||||
<span className='account__header__username'>@{account.get('acct')} {lockedIcon}</span>
|
<span className='account__header__username'>@{account.get('acct')} {lockedIcon}</span>
|
||||||
<div className='account__header__content' dangerouslySetInnerHTML={content} />
|
<div className='account__header__content' dangerouslySetInnerHTML={content} />
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@ import PropTypes from 'prop-types';
|
||||||
import Avatar from '../../../components/avatar';
|
import Avatar from '../../../components/avatar';
|
||||||
import IconButton from '../../../components/icon_button';
|
import IconButton from '../../../components/icon_button';
|
||||||
import DisplayName from '../../../components/display_name';
|
import DisplayName from '../../../components/display_name';
|
||||||
import emojify from '../../../emoji';
|
|
||||||
import { defineMessages, injectIntl } from 'react-intl';
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
|
|
||||||
|
@ -43,7 +42,7 @@ export default class ReplyIndicator extends ImmutablePureComponent {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const content = { __html: emojify(status.get('content')) };
|
const content = { __html: status.get('contentHtml') };
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='reply-indicator'>
|
<div className='reply-indicator'>
|
||||||
|
|
|
@ -4,7 +4,6 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import Permalink from '../../../components/permalink';
|
import Permalink from '../../../components/permalink';
|
||||||
import Avatar from '../../../components/avatar';
|
import Avatar from '../../../components/avatar';
|
||||||
import DisplayName from '../../../components/display_name';
|
import DisplayName from '../../../components/display_name';
|
||||||
import emojify from '../../../emoji';
|
|
||||||
import IconButton from '../../../components/icon_button';
|
import IconButton from '../../../components/icon_button';
|
||||||
import { defineMessages, injectIntl } from 'react-intl';
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
|
@ -26,7 +25,7 @@ export default class AccountAuthorize extends ImmutablePureComponent {
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { intl, account, onAuthorize, onReject } = this.props;
|
const { intl, account, onAuthorize, onReject } = this.props;
|
||||||
const content = { __html: emojify(account.get('note')) };
|
const content = { __html: account.get('note_emojified') };
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='account-authorize__wrapper'>
|
<div className='account-authorize__wrapper'>
|
||||||
|
|
|
@ -7,8 +7,6 @@ import StatusContainer from '../../../containers/status_container';
|
||||||
import AccountContainer from '../../../containers/account_container';
|
import AccountContainer from '../../../containers/account_container';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import Permalink from '../../../components/permalink';
|
import Permalink from '../../../components/permalink';
|
||||||
import emojify from '../../../emoji';
|
|
||||||
import escapeTextContentForBrowser from 'escape-html';
|
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
|
|
||||||
export default class Notification extends ImmutablePureComponent {
|
export default class Notification extends ImmutablePureComponent {
|
||||||
|
@ -70,9 +68,8 @@ export default class Notification extends ImmutablePureComponent {
|
||||||
render () {
|
render () {
|
||||||
const { notification } = this.props;
|
const { notification } = this.props;
|
||||||
const account = notification.get('account');
|
const account = notification.get('account');
|
||||||
const displayName = account.get('display_name').length > 0 ? account.get('display_name') : account.get('username');
|
const displayNameHtml = { __html: account.get('display_name_html') };
|
||||||
const displayNameHTML = { __html: emojify(escapeTextContentForBrowser(displayName)) };
|
const link = <Permalink className='notification__display-name' href={account.get('url')} title={account.get('acct')} to={`/accounts/${account.get('id')}`} dangerouslySetInnerHTML={displayNameHtml} />;
|
||||||
const link = <Permalink className='notification__display-name' href={account.get('url')} title={account.get('acct')} to={`/accounts/${account.get('id')}`} dangerouslySetInnerHTML={displayNameHTML} />;
|
|
||||||
|
|
||||||
switch(notification.get('type')) {
|
switch(notification.get('type')) {
|
||||||
case 'follow':
|
case 'follow':
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import emojify from '../../../emoji';
|
|
||||||
import Toggle from 'react-toggle';
|
import Toggle from 'react-toggle';
|
||||||
|
|
||||||
export default class StatusCheckBox extends React.PureComponent {
|
export default class StatusCheckBox extends React.PureComponent {
|
||||||
|
@ -15,7 +14,7 @@ export default class StatusCheckBox extends React.PureComponent {
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { status, checked, onToggle, disabled } = this.props;
|
const { status, checked, onToggle, disabled } = this.props;
|
||||||
const content = { __html: emojify(status.get('content')) };
|
const content = { __html: status.get('contentHtml') };
|
||||||
|
|
||||||
if (status.get('reblog')) {
|
if (status.get('reblog')) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||||
import ColumnHeader from './column_header';
|
import ColumnHeader from './column_header';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
import scrollTop from '../../../scroll';
|
import { scrollTop } from '../../../scroll';
|
||||||
import { isMobile } from '../../../is_mobile';
|
import { isMobile } from '../../../is_mobile';
|
||||||
|
|
||||||
export default class Column extends React.PureComponent {
|
export default class Column extends React.PureComponent {
|
||||||
|
|
|
@ -12,6 +12,8 @@ import ColumnLoading from './column_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';
|
||||||
|
|
||||||
|
import { scrollRight } from '../../../scroll';
|
||||||
|
|
||||||
const componentMap = {
|
const componentMap = {
|
||||||
'COMPOSE': Compose,
|
'COMPOSE': Compose,
|
||||||
'HOME': HomeTimeline,
|
'HOME': HomeTimeline,
|
||||||
|
@ -49,9 +51,13 @@ export default class ColumnsArea extends ImmutablePureComponent {
|
||||||
this.setState({ shouldAnimate: true });
|
this.setState({ shouldAnimate: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate() {
|
componentDidUpdate(prevProps) {
|
||||||
this.lastIndex = getIndex(this.context.router.history.location.pathname);
|
this.lastIndex = getIndex(this.context.router.history.location.pathname);
|
||||||
this.setState({ shouldAnimate: true });
|
this.setState({ shouldAnimate: true });
|
||||||
|
|
||||||
|
if (this.props.children !== prevProps.children && !this.props.singleColumn) {
|
||||||
|
scrollRight(this.node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSwipe = (index) => {
|
handleSwipe = (index) => {
|
||||||
|
@ -74,6 +80,10 @@ export default class ColumnsArea extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setRef = (node) => {
|
||||||
|
this.node = node;
|
||||||
|
}
|
||||||
|
|
||||||
renderView = (link, index) => {
|
renderView = (link, index) => {
|
||||||
const columnIndex = getIndex(this.context.router.history.location.pathname);
|
const columnIndex = getIndex(this.context.router.history.location.pathname);
|
||||||
const title = this.props.intl.formatMessage({ id: link.props['data-preview-title-id'] });
|
const title = this.props.intl.formatMessage({ id: link.props['data-preview-title-id'] });
|
||||||
|
@ -114,7 +124,7 @@ export default class ColumnsArea extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='columns-area'>
|
<div className='columns-area' ref={this.setRef}>
|
||||||
{columns.map(column => {
|
{columns.map(column => {
|
||||||
const params = column.get('params', null) === null ? null : column.get('params').toJS();
|
const params = column.get('params', null) === null ? null : column.get('params').toJS();
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ import { debounce } from 'lodash';
|
||||||
import { uploadCompose } from '../../actions/compose';
|
import { uploadCompose } from '../../actions/compose';
|
||||||
import { refreshHomeTimeline } from '../../actions/timelines';
|
import { refreshHomeTimeline } from '../../actions/timelines';
|
||||||
import { refreshNotifications } from '../../actions/notifications';
|
import { refreshNotifications } from '../../actions/notifications';
|
||||||
|
import { clearStatusesHeight } from '../../actions/statuses';
|
||||||
import { WrappedSwitch, WrappedRoute } from './util/react_router_helpers';
|
import { WrappedSwitch, WrappedRoute } from './util/react_router_helpers';
|
||||||
import UploadArea from './components/upload_area';
|
import UploadArea from './components/upload_area';
|
||||||
import ColumnsAreaContainer from './containers/columns_area_container';
|
import ColumnsAreaContainer from './containers/columns_area_container';
|
||||||
|
@ -72,6 +73,9 @@ export default class UI extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
handleResize = debounce(() => {
|
handleResize = debounce(() => {
|
||||||
|
// The cached heights are no longer accurate, invalidate
|
||||||
|
this.props.dispatch(clearStatusesHeight());
|
||||||
|
|
||||||
this.setState({ width: window.innerWidth });
|
this.setState({ width: window.innerWidth });
|
||||||
}, 500, {
|
}, 500, {
|
||||||
trailing: true,
|
trailing: true,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"account.block": "مسدودسازی @{name}",
|
"account.block": "مسدودسازی @{name}",
|
||||||
"account.block_domain": "پنهانسازی همه چیز از سرور {domain}",
|
"account.block_domain": "پنهانسازی همه چیز از سرور {domain}",
|
||||||
"account.disclaimer_full": "Information below may reflect the user's profile incompletely.",
|
"account.disclaimer_full": "اطلاعات زیر ممکن است نمایهٔ این کاربر را به تمامی نشان ندهد.",
|
||||||
"account.edit_profile": "ویرایش نمایه",
|
"account.edit_profile": "ویرایش نمایه",
|
||||||
"account.follow": "پی بگیرید",
|
"account.follow": "پی بگیرید",
|
||||||
"account.followers": "پیگیران",
|
"account.followers": "پیگیران",
|
||||||
|
@ -13,7 +13,7 @@
|
||||||
"account.posts": "نوشتهها",
|
"account.posts": "نوشتهها",
|
||||||
"account.report": "گزارش @{name}",
|
"account.report": "گزارش @{name}",
|
||||||
"account.requested": "در انتظار پذیرش",
|
"account.requested": "در انتظار پذیرش",
|
||||||
"account.share": "Share @{name}'s profile",
|
"account.share": "همرسانی نمایهٔ @{name}",
|
||||||
"account.unblock": "رفع انسداد @{name}",
|
"account.unblock": "رفع انسداد @{name}",
|
||||||
"account.unblock_domain": "رفع پنهانسازی از {domain}",
|
"account.unblock_domain": "رفع پنهانسازی از {domain}",
|
||||||
"account.unfollow": "پایان پیگیری",
|
"account.unfollow": "پایان پیگیری",
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
"account.posts": "Statuts",
|
"account.posts": "Statuts",
|
||||||
"account.report": "Signaler",
|
"account.report": "Signaler",
|
||||||
"account.requested": "Invitation envoyée",
|
"account.requested": "Invitation envoyée",
|
||||||
"account.share": "Share @{name}'s profile",
|
"account.share": "Partager le profil de @{name}",
|
||||||
"account.unblock": "Débloquer",
|
"account.unblock": "Débloquer",
|
||||||
"account.unblock_domain": "Ne plus masquer {domain}",
|
"account.unblock_domain": "Ne plus masquer {domain}",
|
||||||
"account.unfollow": "Ne plus suivre",
|
"account.unfollow": "Ne plus suivre",
|
||||||
|
@ -35,11 +35,11 @@
|
||||||
"column.notifications": "Notifications",
|
"column.notifications": "Notifications",
|
||||||
"column.public": "Fil public global",
|
"column.public": "Fil public global",
|
||||||
"column_back_button.label": "Retour",
|
"column_back_button.label": "Retour",
|
||||||
"column_header.hide_settings": "Hide settings",
|
"column_header.hide_settings": "Masquer les paramètres",
|
||||||
"column_header.moveLeft_settings": "Move column to the left",
|
"column_header.moveLeft_settings": "Déplacer la colonne vers la gauche",
|
||||||
"column_header.moveRight_settings": "Move column to the right",
|
"column_header.moveRight_settings": "Déplacer la colonne vers la droite",
|
||||||
"column_header.pin": "Épingler",
|
"column_header.pin": "Épingler",
|
||||||
"column_header.show_settings": "Show settings",
|
"column_header.show_settings": "Afficher les paramètres",
|
||||||
"column_header.unpin": "Retirer",
|
"column_header.unpin": "Retirer",
|
||||||
"column_subheading.navigation": "Navigation",
|
"column_subheading.navigation": "Navigation",
|
||||||
"column_subheading.settings": "Paramètres",
|
"column_subheading.settings": "Paramètres",
|
||||||
|
@ -94,8 +94,8 @@
|
||||||
"home.column_settings.show_replies": "Afficher les réponses",
|
"home.column_settings.show_replies": "Afficher les réponses",
|
||||||
"home.settings": "Paramètres de la colonne",
|
"home.settings": "Paramètres de la colonne",
|
||||||
"lightbox.close": "Fermer",
|
"lightbox.close": "Fermer",
|
||||||
"lightbox.next": "Next",
|
"lightbox.next": "Suivant",
|
||||||
"lightbox.previous": "Previous",
|
"lightbox.previous": "Précédent",
|
||||||
"loading_indicator.label": "Chargement…",
|
"loading_indicator.label": "Chargement…",
|
||||||
"media_gallery.toggle_visible": "Modifier la visibilité",
|
"media_gallery.toggle_visible": "Modifier la visibilité",
|
||||||
"missing_indicator.label": "Non trouvé",
|
"missing_indicator.label": "Non trouvé",
|
||||||
|
@ -175,7 +175,7 @@
|
||||||
"status.report": "Signaler @{name}",
|
"status.report": "Signaler @{name}",
|
||||||
"status.sensitive_toggle": "Cliquer pour afficher",
|
"status.sensitive_toggle": "Cliquer pour afficher",
|
||||||
"status.sensitive_warning": "Contenu sensible",
|
"status.sensitive_warning": "Contenu sensible",
|
||||||
"status.share": "Share",
|
"status.share": "Partager",
|
||||||
"status.show_less": "Replier",
|
"status.show_less": "Replier",
|
||||||
"status.show_more": "Déplier",
|
"status.show_more": "Déplier",
|
||||||
"status.unmute_conversation": "Ne plus masquer la conversation",
|
"status.unmute_conversation": "Ne plus masquer la conversation",
|
||||||
|
|
|
@ -73,7 +73,7 @@
|
||||||
"emoji_button.search": "Szukaj...",
|
"emoji_button.search": "Szukaj...",
|
||||||
"emoji_button.symbols": "Symbole",
|
"emoji_button.symbols": "Symbole",
|
||||||
"emoji_button.travel": "Podróże i miejsca",
|
"emoji_button.travel": "Podróże i miejsca",
|
||||||
"empty_column.community": "Lokalna oś czasu jest pusta. Napisz coś publicznie, aby odbić piłeczkę!",
|
"empty_column.community": "Lokalna oś czasu jest pusta. Napisz coś publicznie, aby zagaić!",
|
||||||
"empty_column.hashtag": "Nie ma postów oznaczonych tym hashtagiem. Możesz napisać pierwszy!",
|
"empty_column.hashtag": "Nie ma postów oznaczonych tym hashtagiem. Możesz napisać pierwszy!",
|
||||||
"empty_column.home": "Nie śledzisz nikogo. Odwiedź publiczną oś czasu lub użyj wyszukiwarki, aby znaleźć interesujące Cię profile.",
|
"empty_column.home": "Nie śledzisz nikogo. Odwiedź publiczną oś czasu lub użyj wyszukiwarki, aby znaleźć interesujące Cię profile.",
|
||||||
"empty_column.home.inactivity": "Strumień jest pusty. Jeżeli nie było Cię tu ostatnio, zostanie on wypełniony wkrótce.",
|
"empty_column.home.inactivity": "Strumień jest pusty. Jeżeli nie było Cię tu ostatnio, zostanie on wypełniony wkrótce.",
|
||||||
|
@ -159,7 +159,7 @@
|
||||||
"report.target": "Zgłaszanie {target}",
|
"report.target": "Zgłaszanie {target}",
|
||||||
"search.placeholder": "Szukaj",
|
"search.placeholder": "Szukaj",
|
||||||
"search_results.total": "{count, number} {count, plural, one {wynik} more {wyniki}}",
|
"search_results.total": "{count, number} {count, plural, one {wynik} more {wyniki}}",
|
||||||
"standalone.public_title": "Spojrzenie wgłąb…",
|
"standalone.public_title": "Spojrzenie w głąb…",
|
||||||
"status.cannot_reblog": "Ten post nie może zostać podbity",
|
"status.cannot_reblog": "Ten post nie może zostać podbity",
|
||||||
"status.delete": "Usuń",
|
"status.delete": "Usuń",
|
||||||
"status.favourite": "Ulubione",
|
"status.favourite": "Ulubione",
|
||||||
|
@ -178,7 +178,7 @@
|
||||||
"status.share": "Udostępnij",
|
"status.share": "Udostępnij",
|
||||||
"status.show_less": "Pokaż mniej",
|
"status.show_less": "Pokaż mniej",
|
||||||
"status.show_more": "Pokaż więcej",
|
"status.show_more": "Pokaż więcej",
|
||||||
"status.unmute_conversation": "Cofnij wyciezenie konwersacji",
|
"status.unmute_conversation": "Cofnij wyciszenie konwersacji",
|
||||||
"tabs_bar.compose": "Napisz",
|
"tabs_bar.compose": "Napisz",
|
||||||
"tabs_bar.federated_timeline": "Globalne",
|
"tabs_bar.federated_timeline": "Globalne",
|
||||||
"tabs_bar.home": "Strona główna",
|
"tabs_bar.home": "Strona główna",
|
||||||
|
|
|
@ -44,7 +44,9 @@ import {
|
||||||
FAVOURITED_STATUSES_EXPAND_SUCCESS,
|
FAVOURITED_STATUSES_EXPAND_SUCCESS,
|
||||||
} from '../actions/favourites';
|
} from '../actions/favourites';
|
||||||
import { STORE_HYDRATE } from '../actions/store';
|
import { STORE_HYDRATE } from '../actions/store';
|
||||||
|
import emojify from '../emoji';
|
||||||
import { Map as ImmutableMap, fromJS } from 'immutable';
|
import { Map as ImmutableMap, fromJS } from 'immutable';
|
||||||
|
import escapeTextContentForBrowser from 'escape-html';
|
||||||
|
|
||||||
const normalizeAccount = (state, account) => {
|
const normalizeAccount = (state, account) => {
|
||||||
account = { ...account };
|
account = { ...account };
|
||||||
|
@ -53,6 +55,10 @@ const normalizeAccount = (state, account) => {
|
||||||
delete account.following_count;
|
delete account.following_count;
|
||||||
delete account.statuses_count;
|
delete account.statuses_count;
|
||||||
|
|
||||||
|
const displayName = account.display_name.length === 0 ? account.username : account.display_name;
|
||||||
|
account.display_name_html = emojify(escapeTextContentForBrowser(displayName));
|
||||||
|
account.note_emojified = emojify(account.note);
|
||||||
|
|
||||||
return state.set(account.id, fromJS(account));
|
return state.set(account.id, fromJS(account));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,8 @@ import {
|
||||||
CONTEXT_FETCH_SUCCESS,
|
CONTEXT_FETCH_SUCCESS,
|
||||||
STATUS_MUTE_SUCCESS,
|
STATUS_MUTE_SUCCESS,
|
||||||
STATUS_UNMUTE_SUCCESS,
|
STATUS_UNMUTE_SUCCESS,
|
||||||
|
STATUS_SET_HEIGHT,
|
||||||
|
STATUSES_CLEAR_HEIGHT,
|
||||||
} from '../actions/statuses';
|
} from '../actions/statuses';
|
||||||
import {
|
import {
|
||||||
TIMELINE_REFRESH_SUCCESS,
|
TIMELINE_REFRESH_SUCCESS,
|
||||||
|
@ -33,7 +35,11 @@ import {
|
||||||
FAVOURITED_STATUSES_EXPAND_SUCCESS,
|
FAVOURITED_STATUSES_EXPAND_SUCCESS,
|
||||||
} from '../actions/favourites';
|
} from '../actions/favourites';
|
||||||
import { SEARCH_FETCH_SUCCESS } from '../actions/search';
|
import { SEARCH_FETCH_SUCCESS } from '../actions/search';
|
||||||
|
import emojify from '../emoji';
|
||||||
import { Map as ImmutableMap, fromJS } from 'immutable';
|
import { Map as ImmutableMap, fromJS } from 'immutable';
|
||||||
|
import escapeTextContentForBrowser from 'escape-html';
|
||||||
|
|
||||||
|
const domParser = new DOMParser();
|
||||||
|
|
||||||
const normalizeStatus = (state, status) => {
|
const normalizeStatus = (state, status) => {
|
||||||
if (!status) {
|
if (!status) {
|
||||||
|
@ -49,7 +55,9 @@ const normalizeStatus = (state, status) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const searchContent = [status.spoiler_text, status.content].join(' ').replace(/<br \/>/g, '\n').replace(/<\/p><p>/g, '\n\n');
|
const searchContent = [status.spoiler_text, status.content].join(' ').replace(/<br \/>/g, '\n').replace(/<\/p><p>/g, '\n\n');
|
||||||
normalStatus.search_index = new DOMParser().parseFromString(searchContent, 'text/html').documentElement.textContent;
|
normalStatus.search_index = domParser.parseFromString(searchContent, 'text/html').documentElement.textContent;
|
||||||
|
normalStatus.contentHtml = emojify(normalStatus.content);
|
||||||
|
normalStatus.spoilerHtml = emojify(escapeTextContentForBrowser(normalStatus.spoiler_text || ''));
|
||||||
|
|
||||||
return state.update(status.id, ImmutableMap(), map => map.mergeDeep(fromJS(normalStatus)));
|
return state.update(status.id, ImmutableMap(), map => map.mergeDeep(fromJS(normalStatus)));
|
||||||
};
|
};
|
||||||
|
@ -82,6 +90,18 @@ const filterStatuses = (state, relationship) => {
|
||||||
return state;
|
return state;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const setHeight = (state, id, height) => {
|
||||||
|
return state.update(id, ImmutableMap(), map => map.set('height', height));
|
||||||
|
};
|
||||||
|
|
||||||
|
const clearHeights = (state) => {
|
||||||
|
state.forEach(status => {
|
||||||
|
state = state.deleteIn([status.get('id'), 'height']);
|
||||||
|
});
|
||||||
|
|
||||||
|
return state;
|
||||||
|
};
|
||||||
|
|
||||||
const initialState = ImmutableMap();
|
const initialState = ImmutableMap();
|
||||||
|
|
||||||
export default function statuses(state = initialState, action) {
|
export default function statuses(state = initialState, action) {
|
||||||
|
@ -120,6 +140,10 @@ export default function statuses(state = initialState, action) {
|
||||||
return deleteStatus(state, action.id, action.references);
|
return deleteStatus(state, action.id, action.references);
|
||||||
case ACCOUNT_BLOCK_SUCCESS:
|
case ACCOUNT_BLOCK_SUCCESS:
|
||||||
return filterStatuses(state, action.relationship);
|
return filterStatuses(state, action.relationship);
|
||||||
|
case STATUS_SET_HEIGHT:
|
||||||
|
return setHeight(state, action.id, action.height);
|
||||||
|
case STATUSES_CLEAR_HEIGHT:
|
||||||
|
return clearHeights(state);
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
const easingOutQuint = (x, t, b, c, d) => c * ((t = t / d - 1) * t * t * t * t + 1) + b;
|
const easingOutQuint = (x, t, b, c, d) => c * ((t = t / d - 1) * t * t * t * t + 1) + b;
|
||||||
|
|
||||||
const scrollTop = (node) => {
|
const scroll = (node, key, target) => {
|
||||||
const startTime = Date.now();
|
const startTime = Date.now();
|
||||||
const offset = node.scrollTop;
|
const offset = node[key];
|
||||||
const targetY = -offset;
|
const gap = target - offset;
|
||||||
const duration = 1000;
|
const duration = 1000;
|
||||||
let interrupt = false;
|
let interrupt = false;
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ const scrollTop = (node) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
node.scrollTop = easingOutQuint(0, elapsed, offset, targetY, duration);
|
node[key] = easingOutQuint(0, elapsed, offset, gap, duration);
|
||||||
requestAnimationFrame(step);
|
requestAnimationFrame(step);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -26,4 +26,5 @@ const scrollTop = (node) => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default scrollTop;
|
export const scrollRight = (node) => scroll(node, 'scrollLeft', node.scrollWidth);
|
||||||
|
export const scrollTop = (node) => scroll(node, 'scrollTop', 0);
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
|
box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
@media screen and (max-width: 700px) {
|
@media screen and (max-width: 740px) {
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
@ -298,7 +298,7 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|
||||||
@media screen and (max-width: 700px) {
|
@media screen and (max-width: 740px) {
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ body {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 360px) {
|
@media screen and (max-width: 400px) {
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,15 @@
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
line-height: 28px;
|
line-height: 28px;
|
||||||
color: $ui-primary-color;
|
color: $ui-primary-color;
|
||||||
overflow: hidden;
|
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
|
padding: 0 10px;
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
|
||||||
|
@media screen and (max-width: 740px) {
|
||||||
|
text-align: center;
|
||||||
|
padding: 20px 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
|
|
|
@ -1835,7 +1835,6 @@
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
backface-visibility: hidden;
|
|
||||||
-webkit-overflow-scrolling: touch;
|
-webkit-overflow-scrolling: touch;
|
||||||
@supports(display: grid) { // hack to fix Chrome <57
|
@supports(display: grid) { // hack to fix Chrome <57
|
||||||
contain: strict;
|
contain: strict;
|
||||||
|
@ -1853,8 +1852,9 @@
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
border: 0;
|
border: 0;
|
||||||
text-align: start;
|
text-align: unset;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
|
margin: 0;
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
margin-top: 40px;
|
margin-top: 40px;
|
||||||
|
|
||||||
@media screen and (max-width: 700px) {
|
@media screen and (max-width: 740px) {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
@ -13,8 +13,9 @@
|
||||||
margin: 100px auto;
|
margin: 100px auto;
|
||||||
margin-bottom: 50px;
|
margin-bottom: 50px;
|
||||||
|
|
||||||
@media screen and (max-width: 360px) {
|
@media screen and (max-width: 400px) {
|
||||||
margin: 30px auto;
|
margin: 30px auto;
|
||||||
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
|
@ -42,3 +43,54 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.account-header {
|
||||||
|
width: 400px;
|
||||||
|
margin: 0 auto;
|
||||||
|
display: flex;
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 18px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 20px 0;
|
||||||
|
padding-bottom: 0;
|
||||||
|
margin-bottom: -30px;
|
||||||
|
margin-top: 40px;
|
||||||
|
|
||||||
|
@media screen and (max-width: 400px) {
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
padding: 20px;
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
margin-right: 8px;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: block;
|
||||||
|
margin: 0;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.name {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
color: $ui-secondary-color;
|
||||||
|
|
||||||
|
.username {
|
||||||
|
display: block;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.logout-link {
|
||||||
|
display: block;
|
||||||
|
font-size: 32px;
|
||||||
|
line-height: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -317,7 +317,7 @@ code {
|
||||||
}
|
}
|
||||||
|
|
||||||
.flash-message {
|
.flash-message {
|
||||||
background: $ui-base-color;
|
background: lighten($ui-base-color, 8%);
|
||||||
color: $ui-primary-color;
|
color: $ui-primary-color;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
padding: 15px 10px;
|
padding: 15px 10px;
|
||||||
|
|
|
@ -104,7 +104,7 @@ class Formatter
|
||||||
html_attrs = { target: '_blank', rel: 'nofollow noopener' }
|
html_attrs = { target: '_blank', rel: 'nofollow noopener' }
|
||||||
|
|
||||||
Twitter::Autolink.send(:link_to_text, entity, link_html(entity[:url]), normalized_url, html_attrs)
|
Twitter::Autolink.send(:link_to_text, entity, link_html(entity[:url]), normalized_url, html_attrs)
|
||||||
rescue Addressable::URI::InvalidURIError
|
rescue Addressable::URI::InvalidURIError, IDN::Idna::IdnaError
|
||||||
encode(entity[:url])
|
encode(entity[:url])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ module AccountAvatar
|
||||||
class_methods do
|
class_methods do
|
||||||
def avatar_styles(file)
|
def avatar_styles(file)
|
||||||
styles = { original: '120x120#' }
|
styles = { original: '120x120#' }
|
||||||
styles[:static] = { format: 'png' } if file.content_type == 'image/gif'
|
styles[:static] = { animated: false } if file.content_type == 'image/gif'
|
||||||
styles
|
styles
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ module AccountHeader
|
||||||
class_methods do
|
class_methods do
|
||||||
def header_styles(file)
|
def header_styles(file)
|
||||||
styles = { original: '700x335#' }
|
styles = { original: '700x335#' }
|
||||||
styles[:static] = { format: 'png' } if file.content_type == 'image/gif'
|
styles[:static] = { animated: false } if file.content_type == 'image/gif'
|
||||||
styles
|
styles
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -3,10 +3,9 @@
|
||||||
|
|
||||||
.form-container
|
.form-container
|
||||||
.follow-prompt
|
.follow-prompt
|
||||||
%h2= t('authorize_follow.prompt_html', self: current_account.username)
|
|
||||||
|
|
||||||
= render 'card', account: @account
|
= render 'card', account: @account
|
||||||
|
|
||||||
= form_tag authorize_follow_path, method: :post, class: 'simple_form' do
|
- unless current_account.following?(@account)
|
||||||
= hidden_field_tag :acct, @account.acct
|
= form_tag authorize_follow_path, method: :post, class: 'simple_form' do
|
||||||
= button_tag t('authorize_follow.follow'), type: :submit
|
= hidden_field_tag :acct, @account.acct
|
||||||
|
= button_tag t('authorize_follow.follow'), type: :submit
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
- content_for :header_tags do
|
||||||
|
= javascript_pack_tag 'public', integrity: true, crossorigin: 'anonymous'
|
||||||
|
|
||||||
|
- content_for :content do
|
||||||
|
- if user_signed_in?
|
||||||
|
.account-header
|
||||||
|
.avatar= image_tag current_account.avatar.url(:original)
|
||||||
|
.name
|
||||||
|
= t 'users.signed_in_as'
|
||||||
|
%span.username @#{current_account.local_username_and_domain}
|
||||||
|
= link_to destroy_user_session_path, method: :delete, class: 'logout-link icon-button' do
|
||||||
|
= fa_icon 'sign-out'
|
||||||
|
|
||||||
|
.container= yield
|
||||||
|
|
||||||
|
= render template: 'layouts/application'
|
|
@ -4,6 +4,7 @@
|
||||||
.compact-header
|
.compact-header
|
||||||
%h1<
|
%h1<
|
||||||
= link_to site_title, root_path
|
= link_to site_title, root_path
|
||||||
|
%br
|
||||||
%small ##{@tag.name}
|
%small ##{@tag.name}
|
||||||
|
|
||||||
- if @statuses.empty?
|
- if @statuses.empty?
|
||||||
|
|
|
@ -86,7 +86,7 @@ module Mastodon
|
||||||
config.middleware.use Rack::Deflater
|
config.middleware.use Rack::Deflater
|
||||||
|
|
||||||
config.to_prepare do
|
config.to_prepare do
|
||||||
Doorkeeper::AuthorizationsController.layout 'public'
|
Doorkeeper::AuthorizationsController.layout 'modal'
|
||||||
Doorkeeper::AuthorizedApplicationsController.layout 'admin'
|
Doorkeeper::AuthorizedApplicationsController.layout 'admin'
|
||||||
Doorkeeper::Application.send :include, ApplicationExtension
|
Doorkeeper::Application.send :include, ApplicationExtension
|
||||||
end
|
end
|
||||||
|
|
|
@ -42,7 +42,9 @@ ignore_missing:
|
||||||
- 'simple_form.{error_notification,required}.:'
|
- 'simple_form.{error_notification,required}.:'
|
||||||
- 'errors.messages.*'
|
- 'errors.messages.*'
|
||||||
- 'activerecord.errors.models.doorkeeper/*'
|
- 'activerecord.errors.models.doorkeeper/*'
|
||||||
|
- 'sessions.{browsers,platforms}.*'
|
||||||
|
- 'terms.body_html'
|
||||||
|
- 'application_mailer.salutation'
|
||||||
ignore_unused:
|
ignore_unused:
|
||||||
- 'activemodel.errors.*'
|
- 'activemodel.errors.*'
|
||||||
- 'activerecord.attributes.*'
|
- 'activerecord.attributes.*'
|
||||||
|
|
|
@ -34,6 +34,11 @@ Doorkeeper.configure do
|
||||||
# https://github.com/doorkeeper-gem/doorkeeper#custom-access-token-generator
|
# https://github.com/doorkeeper-gem/doorkeeper#custom-access-token-generator
|
||||||
# access_token_generator "::Doorkeeper::JWT"
|
# access_token_generator "::Doorkeeper::JWT"
|
||||||
|
|
||||||
|
# The controller Doorkeeper::ApplicationController inherits from.
|
||||||
|
# Defaults to ActionController::Base.
|
||||||
|
# https://github.com/doorkeeper-gem/doorkeeper#custom-base-controller
|
||||||
|
base_controller 'ApplicationController'
|
||||||
|
|
||||||
# Reuse access token for the same resource owner within an application (disabled by default)
|
# Reuse access token for the same resource owner within an application (disabled by default)
|
||||||
# Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/383
|
# Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/383
|
||||||
reuse_access_token
|
reuse_access_token
|
||||||
|
|
|
@ -43,7 +43,6 @@ ar:
|
||||||
authorize_follow:
|
authorize_follow:
|
||||||
error: Unfortunately, there was an error looking up the remote account
|
error: Unfortunately, there was an error looking up the remote account
|
||||||
follow: إتبع
|
follow: إتبع
|
||||||
prompt_html: 'You (<strong>%{self}</strong>) have requested to follow:'
|
|
||||||
title: إتباع %{acct}
|
title: إتباع %{acct}
|
||||||
datetime:
|
datetime:
|
||||||
distance_in_words:
|
distance_in_words:
|
||||||
|
|
|
@ -43,7 +43,6 @@ bg:
|
||||||
authorize_follow:
|
authorize_follow:
|
||||||
error: Възникна грешка в откриването на потребителя
|
error: Възникна грешка в откриването на потребителя
|
||||||
follow: Последвай
|
follow: Последвай
|
||||||
prompt_html: "(<strong>%{self}</strong>), молбата ти беше изпратена до:"
|
|
||||||
title: Последвай %{acct}
|
title: Последвай %{acct}
|
||||||
datetime:
|
datetime:
|
||||||
distance_in_words:
|
distance_in_words:
|
||||||
|
|
|
@ -185,7 +185,6 @@ ca:
|
||||||
authorize_follow:
|
authorize_follow:
|
||||||
error: Malauradament, ha ocorregut un error buscant el compte remot
|
error: Malauradament, ha ocorregut un error buscant el compte remot
|
||||||
follow: Seguir
|
follow: Seguir
|
||||||
prompt_html: 'Tú (<strong>%{self}</strong>) has solicitat seguir:'
|
|
||||||
title: Seguir %{acct}
|
title: Seguir %{acct}
|
||||||
datetime:
|
datetime:
|
||||||
distance_in_words:
|
distance_in_words:
|
||||||
|
|
|
@ -166,7 +166,6 @@ de:
|
||||||
authorize_follow:
|
authorize_follow:
|
||||||
error: Das Profil konnte nicht geladen werden
|
error: Das Profil konnte nicht geladen werden
|
||||||
follow: Folgen
|
follow: Folgen
|
||||||
prompt_html: 'Du (<strong>%{self}</strong>) möchtest dieser Person folgen:'
|
|
||||||
title: "%{acct} folgen"
|
title: "%{acct} folgen"
|
||||||
datetime:
|
datetime:
|
||||||
distance_in_words:
|
distance_in_words:
|
||||||
|
|
|
@ -12,9 +12,9 @@ pl:
|
||||||
last_attempt: Masz jeszcze jedną próbę; Twoje konto zostanie zablokowane jeśli się nie powiedzie.
|
last_attempt: Masz jeszcze jedną próbę; Twoje konto zostanie zablokowane jeśli się nie powiedzie.
|
||||||
locked: Twoje konto zostało zablokowane.
|
locked: Twoje konto zostało zablokowane.
|
||||||
not_found_in_database: Nieprawidłowy %{authentication_keys} lub hasło.
|
not_found_in_database: Nieprawidłowy %{authentication_keys} lub hasło.
|
||||||
timeout: Twoja sesja wygasła. Zaloguj się ponownie aby kontynuować..
|
timeout: Twoja sesja wygasła. Zaloguj się ponownie, aby kontynuować..
|
||||||
unauthenticated: Zapisz się lub zaloguj aby kontynuować.
|
unauthenticated: Zapisz się lub zaloguj, aby kontynuować.
|
||||||
unconfirmed: Zweryfikuj adres e-mail aby kontynuować.
|
unconfirmed: Zweryfikuj adres e-mail, aby kontynuować.
|
||||||
mailer:
|
mailer:
|
||||||
confirmation_instructions:
|
confirmation_instructions:
|
||||||
subject: 'Mastodon: Instrukcje weryfikacji adresu e-mail'
|
subject: 'Mastodon: Instrukcje weryfikacji adresu e-mail'
|
||||||
|
@ -38,7 +38,7 @@ pl:
|
||||||
signed_up: Twoje konto zostało utworzone. Witamy!
|
signed_up: Twoje konto zostało utworzone. Witamy!
|
||||||
signed_up_but_inactive: Twoje konto zostało utworzone. Nie mogliśmy Cię jednak zalogować, ponieważ konto nie zostało jeszcze aktywowane.
|
signed_up_but_inactive: Twoje konto zostało utworzone. Nie mogliśmy Cię jednak zalogować, ponieważ konto nie zostało jeszcze aktywowane.
|
||||||
signed_up_but_locked: Twoje konto zostało utworzone. Nie mogliśmy Cię jednak zalogować, ponieważ konto jest zablokowane.
|
signed_up_but_locked: Twoje konto zostało utworzone. Nie mogliśmy Cię jednak zalogować, ponieważ konto jest zablokowane.
|
||||||
signed_up_but_unconfirmed: Na Twój adres e-mail została wysłana wiadomosć z odnośnikiem potwierdzającym. Kliknij w odnośnik aby aktywować konto. Jeżeli nie otrzymano wiadomości, sprawdź folder ze spamem.
|
signed_up_but_unconfirmed: Na Twój adres e-mail została wysłana wiadomosć z odnośnikiem potwierdzającym. Kliknij w odnośnik, aby aktywować konto. Jeżeli nie otrzymano wiadomości, sprawdź folder ze spamem.
|
||||||
update_needs_confirmation: Konto zostało zaktualizowane, musimy jednak zweryfikować Twój nowy adres e-mail. Została na niego wysłana wiadomość z odnośnikiem potwierdzającym. Jeżeli nie otrzymano wiadomości, sprawdź folder ze spamem.
|
update_needs_confirmation: Konto zostało zaktualizowane, musimy jednak zweryfikować Twój nowy adres e-mail. Została na niego wysłana wiadomość z odnośnikiem potwierdzającym. Jeżeli nie otrzymano wiadomości, sprawdź folder ze spamem.
|
||||||
updated: Konto zostało zaktualizowane.
|
updated: Konto zostało zaktualizowane.
|
||||||
sessions:
|
sessions:
|
||||||
|
@ -48,7 +48,7 @@ pl:
|
||||||
unlocks:
|
unlocks:
|
||||||
send_instructions: W ciągu kilku minut otrzymasz wiadomość e-mail z instrukcjami odblokowania konta. Jeżeli nie otrzymano wiadomości, sprawdź folder ze spamem.
|
send_instructions: W ciągu kilku minut otrzymasz wiadomość e-mail z instrukcjami odblokowania konta. Jeżeli nie otrzymano wiadomości, sprawdź folder ze spamem.
|
||||||
send_paranoid_instructions: Jeśli Twoje konto istnieje, instrukcje odblokowania go otrzymasz w wiadomości e-mail w ciągu kilku minut. Jeżeli nie otrzymano wiadomości, sprawdź folder ze spamem.
|
send_paranoid_instructions: Jeśli Twoje konto istnieje, instrukcje odblokowania go otrzymasz w wiadomości e-mail w ciągu kilku minut. Jeżeli nie otrzymano wiadomości, sprawdź folder ze spamem.
|
||||||
unlocked: Twoje konto zostało odblokowane. Zaloguj się aby kontynuować.
|
unlocked: Twoje konto zostało odblokowane. Zaloguj się, aby kontynuować.
|
||||||
errors:
|
errors:
|
||||||
messages:
|
messages:
|
||||||
already_confirmed: był już potwierdzony, spróbuj się zalogować
|
already_confirmed: był już potwierdzony, spróbuj się zalogować
|
||||||
|
|
|
@ -31,7 +31,7 @@ pl:
|
||||||
help:
|
help:
|
||||||
native_redirect_uri: Użyj %{native_redirect_uri} do lokalnych testów
|
native_redirect_uri: Użyj %{native_redirect_uri} do lokalnych testów
|
||||||
redirect_uri: Jeden adres na linię tekstu
|
redirect_uri: Jeden adres na linię tekstu
|
||||||
scopes: Rozdziel zakresy (scopes) spacjami. Zostaw puste aby użyć domyślnych zakresów.
|
scopes: Rozdziel zakresy (scopes) spacjami. Zostaw puste, aby użyć domyślnych zakresów.
|
||||||
index:
|
index:
|
||||||
callback_url: URL wywołania zwrotnego (callback)
|
callback_url: URL wywołania zwrotnego (callback)
|
||||||
name: Nazwa
|
name: Nazwa
|
||||||
|
|
|
@ -215,7 +215,7 @@ en:
|
||||||
body: "%{reporter} has reported %{target}"
|
body: "%{reporter} has reported %{target}"
|
||||||
subject: New report for %{instance} (#%{id})
|
subject: New report for %{instance} (#%{id})
|
||||||
application_mailer:
|
application_mailer:
|
||||||
salutation: '%{name},'
|
salutation: "%{name},"
|
||||||
settings: 'Change e-mail preferences: %{link}'
|
settings: 'Change e-mail preferences: %{link}'
|
||||||
signature: Mastodon notifications from %{instance}
|
signature: Mastodon notifications from %{instance}
|
||||||
view: 'View:'
|
view: 'View:'
|
||||||
|
@ -228,6 +228,7 @@ en:
|
||||||
delete_account_html: If you wish to delete your account, you can <a href="%{path}">proceed here</a>. You will be asked for confirmation.
|
delete_account_html: If you wish to delete your account, you can <a href="%{path}">proceed here</a>. You will be asked for confirmation.
|
||||||
didnt_get_confirmation: Didn't receive confirmation instructions?
|
didnt_get_confirmation: Didn't receive confirmation instructions?
|
||||||
forgot_password: Forgot your password?
|
forgot_password: Forgot your password?
|
||||||
|
invalid_reset_password_token: Password reset token is invalid or expired. Please request a new one.
|
||||||
login: Log in
|
login: Log in
|
||||||
logout: Logout
|
logout: Logout
|
||||||
register: Sign up
|
register: Sign up
|
||||||
|
@ -243,7 +244,6 @@ en:
|
||||||
close: Or, you can just close this window.
|
close: Or, you can just close this window.
|
||||||
return: Return to the user's profile
|
return: Return to the user's profile
|
||||||
web: Go to web
|
web: Go to web
|
||||||
prompt_html: 'You (<strong>%{self}</strong>) have requested to follow:'
|
|
||||||
title: Follow %{acct}
|
title: Follow %{acct}
|
||||||
datetime:
|
datetime:
|
||||||
distance_in_words:
|
distance_in_words:
|
||||||
|
@ -523,3 +523,4 @@ en:
|
||||||
users:
|
users:
|
||||||
invalid_email: The e-mail address is invalid
|
invalid_email: The e-mail address is invalid
|
||||||
invalid_otp_token: Invalid two-factor code
|
invalid_otp_token: Invalid two-factor code
|
||||||
|
signed_in_as: 'Signed in as:'
|
||||||
|
|
|
@ -42,7 +42,6 @@ eo:
|
||||||
authorize_follow:
|
authorize_follow:
|
||||||
error: Bedaŭrinde, okazis eraro provante konsulti la foran konton
|
error: Bedaŭrinde, okazis eraro provante konsulti la foran konton
|
||||||
follow: Sekvi
|
follow: Sekvi
|
||||||
prompt_html: 'Vi (<strong>%{self}</strong>) petis sekvi:'
|
|
||||||
title: Sekvi %{acct}
|
title: Sekvi %{acct}
|
||||||
datetime:
|
datetime:
|
||||||
distance_in_words:
|
distance_in_words:
|
||||||
|
|
|
@ -43,7 +43,6 @@ es:
|
||||||
authorize_follow:
|
authorize_follow:
|
||||||
error: Desafortunadamente, ha ocurrido un error buscando la cuenta remota
|
error: Desafortunadamente, ha ocurrido un error buscando la cuenta remota
|
||||||
follow: Seguir
|
follow: Seguir
|
||||||
prompt_html: 'Tú (<strong>%{self}</strong>) has solicitado seguir:'
|
|
||||||
title: Seguir %{acct}
|
title: Seguir %{acct}
|
||||||
datetime:
|
datetime:
|
||||||
distance_in_words:
|
distance_in_words:
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
fa:
|
fa:
|
||||||
about:
|
about:
|
||||||
about_mastodon_html: ماستدون (Mastodon) یک شبکهٔ اجتماعی است که بر اساس پروتکلهای آزاد وب و نرمافزارهای آزاد و کدباز ساخته شده است. این شبکه مانند ایمیل غیرمتمرکز است.
|
about_mastodon_html: ماستدون (Mastodon) یک شبکهٔ اجتماعی است که بر اساس پروتکلهای آزاد وب و نرمافزارهای آزاد و کدباز ساخته شده است. این شبکه مانند ایمیل غیرمتمرکز است.
|
||||||
about_this: درباره.
|
about_this: درباره
|
||||||
closed_registrations: ثبتنام روی این سرور هماینک فعال نیست. اما شما میتوانید سرور دیگری بیابید و با حسابی که آنجا میسازید دقیقاً به همین شبکه دسترسی داشته باشید.
|
closed_registrations: ثبتنام روی این سرور هماینک فعال نیست. اما شما میتوانید سرور دیگری بیابید و با حسابی که آنجا میسازید دقیقاً به همین شبکه دسترسی داشته باشید.
|
||||||
contact: تماس
|
contact: تماس
|
||||||
contact_missing: تعیین نشده
|
contact_missing: تعیین نشده
|
||||||
|
@ -20,11 +20,11 @@ fa:
|
||||||
not_a_product_title: شما یک انسان هستید، نه یک محصول
|
not_a_product_title: شما یک انسان هستید، نه یک محصول
|
||||||
real_conversation_body: با ۵۰۰ نویسه برای هر نوشته و با پشتیبانی از هشدارهای موردی برای نوشتهها و تصاویر، میتوانید خود را همان گونه که میخواهید ابراز کنید.
|
real_conversation_body: با ۵۰۰ نویسه برای هر نوشته و با پشتیبانی از هشدارهای موردی برای نوشتهها و تصاویر، میتوانید خود را همان گونه که میخواهید ابراز کنید.
|
||||||
real_conversation_title: برای گفتگوهای واقعی
|
real_conversation_title: برای گفتگوهای واقعی
|
||||||
within_reach_body: اپهای متنوع برای iOS، اندروید، و سیستمهای دیگر به خاطر وحود یک اکوسیستم API دوستانه برای برنامهنویسان. از همه جا با دوستان خود ارتباط داشته باشید.
|
within_reach_body: اپهای متنوع برای iOS، اندروید، و سیستمهای دیگر به خاطر وجود یک اکوسیستم API دوستانه برای برنامهنویسان. از همه جا با دوستان خود ارتباط داشته باشید.
|
||||||
within_reach_title: همیشه در دسترس
|
within_reach_title: همیشه در دسترس
|
||||||
find_another_instance: یافتن سرورهای دیگر
|
find_another_instance: یافتن سرورهای دیگر
|
||||||
generic_description: "%{domain} یک سرور روی شبکه است"
|
generic_description: "%{domain} یک سرور روی شبکه است"
|
||||||
hosted_on: ماستدون میزبانیشده روی %{domain}
|
hosted_on: ماستدون، میزبانیشده روی %{domain}
|
||||||
learn_more: بیشتر بدانید
|
learn_more: بیشتر بدانید
|
||||||
other_instances: فهرست سرورها
|
other_instances: فهرست سرورها
|
||||||
source_code: کدهای منبع
|
source_code: کدهای منبع
|
||||||
|
@ -212,10 +212,10 @@ fa:
|
||||||
title: مدیریت
|
title: مدیریت
|
||||||
admin_mailer:
|
admin_mailer:
|
||||||
new_report:
|
new_report:
|
||||||
body: "کاربر %{reporter} کاربر %{target} را گزارش داد"
|
body: کاربر %{reporter} کاربر %{target} را گزارش داد
|
||||||
subject: گزارش تازهای برای %{instance} (#%{id})
|
subject: گزارش تازهای برای %{instance} (#%{id})
|
||||||
application_mailer:
|
application_mailer:
|
||||||
salutation: '%{name},'
|
salutation: "%{name},"
|
||||||
settings: 'تغییر تنظیمات ایمیل: %{link}'
|
settings: 'تغییر تنظیمات ایمیل: %{link}'
|
||||||
signature: اعلانهای ماستدون از %{instance}
|
signature: اعلانهای ماستدون از %{instance}
|
||||||
view: 'نمایش:'
|
view: 'نمایش:'
|
||||||
|
@ -243,7 +243,6 @@ fa:
|
||||||
close: یا این پنجره را ببندید.
|
close: یا این پنجره را ببندید.
|
||||||
return: به نمایهٔ این کاربر بازگردید
|
return: به نمایهٔ این کاربر بازگردید
|
||||||
web: رفتن به وب
|
web: رفتن به وب
|
||||||
prompt_html: 'شما (<strong>%{self}</strong>) میخواهید این حساب را پی بگیرید:'
|
|
||||||
title: پیگیری %{acct}
|
title: پیگیری %{acct}
|
||||||
datetime:
|
datetime:
|
||||||
distance_in_words:
|
distance_in_words:
|
||||||
|
@ -433,7 +432,7 @@ fa:
|
||||||
sensitive_content: محتوای حساس
|
sensitive_content: محتوای حساس
|
||||||
terms:
|
terms:
|
||||||
body_html: |
|
body_html: |
|
||||||
<h2>Privacy Policy</h2>
|
<h2>سیاست رازداری (Privacy Policy)</h2>
|
||||||
|
|
||||||
<h3 id="collect">ما چه اطلاعاتی را گردآوری میکنیم؟</h3>
|
<h3 id="collect">ما چه اطلاعاتی را گردآوری میکنیم؟</h3>
|
||||||
|
|
||||||
|
@ -451,7 +450,7 @@ fa:
|
||||||
<li>برای شخصیسازی تجربهٔ کاربری شما — ما به کمک اطلاعات شما بهتر میتوانیم نیازهای شما را برآورده کنیم.</li>
|
<li>برای شخصیسازی تجربهٔ کاربری شما — ما به کمک اطلاعات شما بهتر میتوانیم نیازهای شما را برآورده کنیم.</li>
|
||||||
<li>برای بهتر کردن سایت — ما پیوسته میکوشیم تا خدمات این سایت را به کمک اطلاعات و بازخوردی که از شما میگیریم بهتر کنیم.</li>
|
<li>برای بهتر کردن سایت — ما پیوسته میکوشیم تا خدمات این سایت را به کمک اطلاعات و بازخوردی که از شما میگیریم بهتر کنیم.</li>
|
||||||
<li>برای بهتر کردن خدمات به کاربران — ما به کمک اطلاعات شما به طور مؤثرتری میتوانیم به درخواستهای پشتیبانی شما پاسخ دهیم.</li>
|
<li>برای بهتر کردن خدمات به کاربران — ما به کمک اطلاعات شما به طور مؤثرتری میتوانیم به درخواستهای پشتیبانی شما پاسخ دهیم.</li>
|
||||||
<li>برای فرستادن ایمیلهای دورهای — ما گاهی به نشانی ایمیلی که وارد کردهاید نامه میفرستیم تا درخواستهای شما پاسخ دهیم یا شما را در جریان پاسخ دیگران به شما قرار دهیم.</li>
|
<li>برای فرستادن ایمیلهای دورهای — ما گاهی به نشانی ایمیلی که وارد کردهاید نامه میفرستیم تا به درخواستهای شما پاسخ دهیم یا شما را در جریان پاسخ دیگران به شما قرار دهیم.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h3 id="protect">ما چگونه از اطلاعات شما محافظت میکنیم؟</h3>
|
<h3 id="protect">ما چگونه از اطلاعات شما محافظت میکنیم؟</h3>
|
||||||
|
@ -500,7 +499,7 @@ fa:
|
||||||
<p>این نوشته تحت اجازهنامهٔ CC-BY-SA قرار دارد. تاریخ آخرین بهروزرسانی آن ۱۰ خرداد ۱۳۹۲ است.</p>
|
<p>این نوشته تحت اجازهنامهٔ CC-BY-SA قرار دارد. تاریخ آخرین بهروزرسانی آن ۱۰ خرداد ۱۳۹۲ است.</p>
|
||||||
|
|
||||||
<p>این نوشته اقتباسی است از <a href="https://github.com/discourse/discourse">سیاست رازداری Discourse</a>.</p>
|
<p>این نوشته اقتباسی است از <a href="https://github.com/discourse/discourse">سیاست رازداری Discourse</a>.</p>
|
||||||
title: "شرایط استفاده و سیاست رازداری %{instance}"
|
title: شرایط استفاده و سیاست رازداری %{instance}
|
||||||
time:
|
time:
|
||||||
formats:
|
formats:
|
||||||
default: "%d %b %Y, %H:%M"
|
default: "%d %b %Y, %H:%M"
|
||||||
|
|
|
@ -42,7 +42,6 @@ fi:
|
||||||
authorize_follow:
|
authorize_follow:
|
||||||
error: Valitettavasti tapahtui virhe etätilin haussa.
|
error: Valitettavasti tapahtui virhe etätilin haussa.
|
||||||
follow: Seuraa
|
follow: Seuraa
|
||||||
prompt_html: 'Sinä (<strong>%{self}</strong>) olet pyytänyt lupaa seurata:'
|
|
||||||
title: Seuraa %{acct}
|
title: Seuraa %{acct}
|
||||||
datetime:
|
datetime:
|
||||||
distance_in_words:
|
distance_in_words:
|
||||||
|
|
|
@ -220,6 +220,7 @@ fr:
|
||||||
delete_account_html: Si vous désirez supprimer votre compte, vous pouvez cliquer ici. Il vous sera demandé de confirmer cette action.
|
delete_account_html: Si vous désirez supprimer votre compte, vous pouvez cliquer ici. Il vous sera demandé de confirmer cette action.
|
||||||
didnt_get_confirmation: Vous n’avez pas reçu les consignes de confirmation ?
|
didnt_get_confirmation: Vous n’avez pas reçu les consignes de confirmation ?
|
||||||
forgot_password: Mot de passe oublié ?
|
forgot_password: Mot de passe oublié ?
|
||||||
|
invalid_reset_password_token: Le lien de réinitialisation du mot de passe est invalide ou a expiré. Merci de réessayer.
|
||||||
login: Se connecter
|
login: Se connecter
|
||||||
logout: Se déconnecter
|
logout: Se déconnecter
|
||||||
register: S’inscrire
|
register: S’inscrire
|
||||||
|
@ -235,7 +236,6 @@ fr:
|
||||||
close: Ou bien, vous pouvez fermer cette fenêtre.
|
close: Ou bien, vous pouvez fermer cette fenêtre.
|
||||||
return: Retour au profil de l'utilisateur⋅trice
|
return: Retour au profil de l'utilisateur⋅trice
|
||||||
web: Retour à l'interface web
|
web: Retour à l'interface web
|
||||||
prompt_html: 'Vous (<strong>%{self}</strong>) avez demandé à suivre :'
|
|
||||||
title: Suivre %{acct}
|
title: Suivre %{acct}
|
||||||
datetime:
|
datetime:
|
||||||
distance_in_words:
|
distance_in_words:
|
||||||
|
@ -278,7 +278,7 @@ fr:
|
||||||
blocks: Vous bloquez
|
blocks: Vous bloquez
|
||||||
csv: CSV
|
csv: CSV
|
||||||
follows: Vous suivez
|
follows: Vous suivez
|
||||||
mutes: Vous faites taire
|
mutes: Vous masquez
|
||||||
storage: Médias stockés
|
storage: Médias stockés
|
||||||
followers:
|
followers:
|
||||||
domain: Domaine
|
domain: Domaine
|
||||||
|
@ -305,7 +305,7 @@ fr:
|
||||||
types:
|
types:
|
||||||
blocking: Liste d’utilisateur⋅ice⋅s bloqué⋅es
|
blocking: Liste d’utilisateur⋅ice⋅s bloqué⋅es
|
||||||
following: Liste d’utilisateur⋅ice⋅s suivi⋅es
|
following: Liste d’utilisateur⋅ice⋅s suivi⋅es
|
||||||
muting: Liste d’utilisateur⋅ice⋅s que vous faites taire
|
muting: Liste d’utilisateur⋅ice⋅s que vous masquez
|
||||||
upload: Importer
|
upload: Importer
|
||||||
landing_strip_html: <strong>%{name}</strong> utilise %{link_to_root_path}. Vous pouvez le/la suivre et interagir si vous possédez un compte quelque part dans le "fediverse".
|
landing_strip_html: <strong>%{name}</strong> utilise %{link_to_root_path}. Vous pouvez le/la suivre et interagir si vous possédez un compte quelque part dans le "fediverse".
|
||||||
landing_strip_signup_html: Si ce n’est pas le cas, vous pouvez <a href="%{sign_up_path}">en créer un ici</a>.
|
landing_strip_signup_html: Si ce n’est pas le cas, vous pouvez <a href="%{sign_up_path}">en créer un ici</a>.
|
||||||
|
@ -451,3 +451,4 @@ fr:
|
||||||
users:
|
users:
|
||||||
invalid_email: L’adresse courriel est invalide
|
invalid_email: L’adresse courriel est invalide
|
||||||
invalid_otp_token: Le code d’authentification à deux facteurs est invalide
|
invalid_otp_token: Le code d’authentification à deux facteurs est invalide
|
||||||
|
signed_in_as: 'Connecté·e en tant que :'
|
||||||
|
|
|
@ -177,7 +177,6 @@ he:
|
||||||
authorize_follow:
|
authorize_follow:
|
||||||
error: למרבה הצער, היתה שגיאה בחיפוש החשבון המרוחק
|
error: למרבה הצער, היתה שגיאה בחיפוש החשבון המרוחק
|
||||||
follow: לעקוב
|
follow: לעקוב
|
||||||
prompt_html: 'בקשת מעקב ממך (<strong>%{self}</strong>) אחרי:'
|
|
||||||
title: לעקוב אחרי %{acct}
|
title: לעקוב אחרי %{acct}
|
||||||
datetime:
|
datetime:
|
||||||
distance_in_words:
|
distance_in_words:
|
||||||
|
|
|
@ -43,7 +43,6 @@ hr:
|
||||||
authorize_follow:
|
authorize_follow:
|
||||||
error: Nažalost, došlo je do greške looking up the remote račun
|
error: Nažalost, došlo je do greške looking up the remote račun
|
||||||
follow: Slijedi
|
follow: Slijedi
|
||||||
prompt_html: 'Ti si (<strong>%{self}</strong>) poslao zahtjev za sljeđenje:'
|
|
||||||
title: Slijedi %{acct}
|
title: Slijedi %{acct}
|
||||||
datetime:
|
datetime:
|
||||||
distance_in_words:
|
distance_in_words:
|
||||||
|
|
|
@ -168,7 +168,6 @@ id:
|
||||||
authorize_follow:
|
authorize_follow:
|
||||||
error: Sayangnya, ada error saat melihat akun remote
|
error: Sayangnya, ada error saat melihat akun remote
|
||||||
follow: Ikuti
|
follow: Ikuti
|
||||||
prompt_html: 'Anda (<strong>%{self}</strong>) telah diminta untuk mengikuti:'
|
|
||||||
title: Mengikuti %{acct}
|
title: Mengikuti %{acct}
|
||||||
datetime:
|
datetime:
|
||||||
distance_in_words:
|
distance_in_words:
|
||||||
|
|
|
@ -166,7 +166,6 @@ io:
|
||||||
authorize_follow:
|
authorize_follow:
|
||||||
error: Regretinde, eventis eraro probante konsultar la fora konto
|
error: Regretinde, eventis eraro probante konsultar la fora konto
|
||||||
follow: Sequar
|
follow: Sequar
|
||||||
prompt_html: 'Tu (<strong>%{self}</strong>) demandis sequar:'
|
|
||||||
title: Sequar %{acct}
|
title: Sequar %{acct}
|
||||||
datetime:
|
datetime:
|
||||||
distance_in_words:
|
distance_in_words:
|
||||||
|
|
|
@ -43,7 +43,6 @@ it:
|
||||||
authorize_follow:
|
authorize_follow:
|
||||||
error: Sfortunatamente c'è stato un errore nel consultare l'account remoto
|
error: Sfortunatamente c'è stato un errore nel consultare l'account remoto
|
||||||
follow: Segui
|
follow: Segui
|
||||||
prompt_html: 'Tu, (<strong>%{self}</strong>), hai richiesto di seguire:'
|
|
||||||
title: Segui %{acct}
|
title: Segui %{acct}
|
||||||
datetime:
|
datetime:
|
||||||
distance_in_words:
|
distance_in_words:
|
||||||
|
|
|
@ -234,7 +234,7 @@ ja:
|
||||||
reset_password: パスワードを再発行
|
reset_password: パスワードを再発行
|
||||||
set_new_password: 新しいパスワード
|
set_new_password: 新しいパスワード
|
||||||
authorize_follow:
|
authorize_follow:
|
||||||
error: 残念ながら、リモートアカウントにエラーが発生しました。
|
error: 残念ながら、リモートアカウント情報の取得中にエラーが発生しました。
|
||||||
follow: フォロー
|
follow: フォロー
|
||||||
follow_request: 'あなたは以下のアカウントにフォローリクエストを送信しました:'
|
follow_request: 'あなたは以下のアカウントにフォローリクエストを送信しました:'
|
||||||
following: '成功! あなたは現在以下のアカウントをフォローしています:'
|
following: '成功! あなたは現在以下のアカウントをフォローしています:'
|
||||||
|
@ -242,7 +242,6 @@ ja:
|
||||||
close: またはこのウィンドウを閉じます
|
close: またはこのウィンドウを閉じます
|
||||||
return: ユーザーのプロフィールに戻る
|
return: ユーザーのプロフィールに戻る
|
||||||
web: Web を開く
|
web: Web を開く
|
||||||
prompt_html: 'あなた(<strong>%{self}</strong>)は以下のアカウントのフォローをリクエストしました:'
|
|
||||||
title: "%{acct} をフォロー"
|
title: "%{acct} をフォロー"
|
||||||
datetime:
|
datetime:
|
||||||
distance_in_words:
|
distance_in_words:
|
||||||
|
@ -522,3 +521,4 @@ ja:
|
||||||
users:
|
users:
|
||||||
invalid_email: メールアドレスが無効です
|
invalid_email: メールアドレスが無効です
|
||||||
invalid_otp_token: 二段階認証コードが間違っています
|
invalid_otp_token: 二段階認証コードが間違っています
|
||||||
|
signed_in_as: '下記でログイン中:'
|
||||||
|
|
|
@ -189,7 +189,6 @@ ko:
|
||||||
authorize_follow:
|
authorize_follow:
|
||||||
error: 리모트 팔로우 도중 오류가 발생했습니다.
|
error: 리모트 팔로우 도중 오류가 발생했습니다.
|
||||||
follow: 팔로우
|
follow: 팔로우
|
||||||
prompt_html: '나(<strong>%{self}</strong>) 는 아래 계정의 팔로우를 요청했습니다:'
|
|
||||||
title: "%{acct} 를 팔로우"
|
title: "%{acct} 를 팔로우"
|
||||||
datetime:
|
datetime:
|
||||||
distance_in_words:
|
distance_in_words:
|
||||||
|
|
|
@ -106,7 +106,7 @@ nl:
|
||||||
domain: Domein
|
domain: Domein
|
||||||
new:
|
new:
|
||||||
create: Blokkade aanmaken
|
create: Blokkade aanmaken
|
||||||
hint: Een domeinblokkade voorkomt niet dat accountgegevens van dit domein aan de database worden toegevoegd, maar dat er met terugwerkende kracht en automatisch bepaalde moderatiemethoden op deze accounts worden toegepast.
|
hint: Een domeinblokkade voorkomt niet dat accountgegevens van dit domein aan de database worden toegevoegd, maar dat er met terugwerkende kracht en automatisch bepaalde moderatiemethoden op deze accounts worden toegepast.
|
||||||
severity:
|
severity:
|
||||||
desc_html: "<strong>Negeren</strong> zorgt ervoor dat berichten van accounts van dit domein voor iedereen onzichtbaar zijn, behalve als een account wordt gevolgd. <strong>Opschorten</strong> zorgt ervoor dat alle berichten, media en profielgegevens van accounts van dit domein worden verwijderd. Gebruik <strong>Geen</strong> wanneer je alleen mediabestanden wilt weigeren."
|
desc_html: "<strong>Negeren</strong> zorgt ervoor dat berichten van accounts van dit domein voor iedereen onzichtbaar zijn, behalve als een account wordt gevolgd. <strong>Opschorten</strong> zorgt ervoor dat alle berichten, media en profielgegevens van accounts van dit domein worden verwijderd. Gebruik <strong>Geen</strong> wanneer je alleen mediabestanden wilt weigeren."
|
||||||
noop: Geen
|
noop: Geen
|
||||||
|
@ -129,7 +129,7 @@ nl:
|
||||||
suspend: Alle opgeschorste accounts van dit domein niet meer opschorten
|
suspend: Alle opgeschorste accounts van dit domein niet meer opschorten
|
||||||
title: Domeinblokkade voor %{domain} ongedaan maken
|
title: Domeinblokkade voor %{domain} ongedaan maken
|
||||||
undo: Ongedaan maken
|
undo: Ongedaan maken
|
||||||
title: Domeinblokkades
|
title: Domeinblokkades
|
||||||
undo: Ongedaan maken
|
undo: Ongedaan maken
|
||||||
instances:
|
instances:
|
||||||
account_count: Bekende accounts
|
account_count: Bekende accounts
|
||||||
|
@ -169,7 +169,7 @@ nl:
|
||||||
title: Bericht wanneer registratie is uitgeschakeld
|
title: Bericht wanneer registratie is uitgeschakeld
|
||||||
deletion:
|
deletion:
|
||||||
desc_html: Toestaan dat iedereen hun eigen account kan verwijderen
|
desc_html: Toestaan dat iedereen hun eigen account kan verwijderen
|
||||||
title: Verwijderen account toestaan
|
title: Verwijderen account toestaan
|
||||||
open:
|
open:
|
||||||
desc_html: Toestaan dat iedereen een account kan registereren
|
desc_html: Toestaan dat iedereen een account kan registereren
|
||||||
title: Open registratie
|
title: Open registratie
|
||||||
|
@ -220,7 +220,7 @@ nl:
|
||||||
applications:
|
applications:
|
||||||
invalid_url: De opgegeven URL is ongeldig
|
invalid_url: De opgegeven URL is ongeldig
|
||||||
auth:
|
auth:
|
||||||
agreement_html: Wanneer je op registeren klikt ga je akkoord met <a href="%{rules_path}">onze gebruikersvoorwaarden</a> en <a href="%{terms_path}">ons privacybeleid</a>.
|
agreement_html: Wanneer je op registreren klikt ga je akkoord met <a href="%{rules_path}">onze gebruikersvoorwaarden</a> en <a href="%{terms_path}">ons privacybeleid</a>.
|
||||||
change_password: Beveiliging
|
change_password: Beveiliging
|
||||||
delete_account: Account verwijderen
|
delete_account: Account verwijderen
|
||||||
delete_account_html: Wanneer je jouw account graag wilt verwijderen, kan je dat <a href="%{path}">hier doen</a>. We vragen jou daar om een bevestiging.
|
delete_account_html: Wanneer je jouw account graag wilt verwijderen, kan je dat <a href="%{path}">hier doen</a>. We vragen jou daar om een bevestiging.
|
||||||
|
@ -241,7 +241,6 @@ nl:
|
||||||
close: Of je kan dit venster gewoon sluiten.
|
close: Of je kan dit venster gewoon sluiten.
|
||||||
return: Ga terug naar het profiel van de gebruiker
|
return: Ga terug naar het profiel van de gebruiker
|
||||||
web: Ga naar de webapp
|
web: Ga naar de webapp
|
||||||
prompt_html: 'Je (<strong>%{self}</strong>) hebt toestemming gevraagd om iemand te mogen volgen:'
|
|
||||||
title: Volg %{acct}
|
title: Volg %{acct}
|
||||||
datetime:
|
datetime:
|
||||||
distance_in_words:
|
distance_in_words:
|
||||||
|
@ -307,7 +306,7 @@ nl:
|
||||||
following: Volglijst
|
following: Volglijst
|
||||||
muting: Negeerlijst
|
muting: Negeerlijst
|
||||||
upload: Uploaden
|
upload: Uploaden
|
||||||
landing_strip_html: <strong>%{name}</strong> is een gebruiker op %{link_to_root_path}. Je kunt deze volgen en ermee communiceren als je ergens in deze fediverse een account hebt.
|
landing_strip_html: "<strong>%{name}</strong> is een gebruiker op %{link_to_root_path}. Je kunt deze volgen en ermee communiceren als je ergens in deze fediverse een account hebt."
|
||||||
landing_strip_signup_html: Als je dat niet hebt, kun je je <a href="%{sign_up_path}">hier registreren</a>.
|
landing_strip_signup_html: Als je dat niet hebt, kun je je <a href="%{sign_up_path}">hier registreren</a>.
|
||||||
media_attachments:
|
media_attachments:
|
||||||
validations:
|
validations:
|
||||||
|
@ -510,7 +509,7 @@ nl:
|
||||||
generate_recovery_codes: Herstelcodes genereren
|
generate_recovery_codes: Herstelcodes genereren
|
||||||
instructions_html: "<strong>Scan deze QR-code in Google Authenticator of een soortgelijke app op jouw mobiele telefoon</strong>. Van nu af aan genereert deze app aanmeldcodes die je bij het aanmelden moet invoeren."
|
instructions_html: "<strong>Scan deze QR-code in Google Authenticator of een soortgelijke app op jouw mobiele telefoon</strong>. Van nu af aan genereert deze app aanmeldcodes die je bij het aanmelden moet invoeren."
|
||||||
lost_recovery_codes: Met herstelcodes kun je toegang tot jouw account krijgen wanneer je jouw telefoon bent kwijtgeraakt. Wanneer je jouw herstelcodes bent kwijtgeraakt, kan je ze hier opnieuw genereren. Jouw oude herstelcodes zijn daarna ongeldig.
|
lost_recovery_codes: Met herstelcodes kun je toegang tot jouw account krijgen wanneer je jouw telefoon bent kwijtgeraakt. Wanneer je jouw herstelcodes bent kwijtgeraakt, kan je ze hier opnieuw genereren. Jouw oude herstelcodes zijn daarna ongeldig.
|
||||||
manual_instructions: 'Hieronder vind je de geheime code in platte tekst. Voor het geval je de QR-code niet kunt scannen en het handmatig moet invoeren.'
|
manual_instructions: Hieronder vind je de geheime code in platte tekst. Voor het geval je de QR-code niet kunt scannen en het handmatig moet invoeren.
|
||||||
recovery_codes: Herstelcodes back-uppen
|
recovery_codes: Herstelcodes back-uppen
|
||||||
recovery_codes_regenerated: Opnieuw genereren herstelcodes geslaagd
|
recovery_codes_regenerated: Opnieuw genereren herstelcodes geslaagd
|
||||||
recovery_instructions_html: Wanneer je ooit de toegang verliest tot jouw telefoon, kan je met behulp van een van de herstelcodes hieronder opnieuw toegang krijgen tot jouw account. Zorg ervoor dat je de herstelcodes op een veilige plek bewaard. (Je kunt ze bijvoorbeeld printen en ze samen met andere belangrijke documenten bewaren.)
|
recovery_instructions_html: Wanneer je ooit de toegang verliest tot jouw telefoon, kan je met behulp van een van de herstelcodes hieronder opnieuw toegang krijgen tot jouw account. Zorg ervoor dat je de herstelcodes op een veilige plek bewaard. (Je kunt ze bijvoorbeeld printen en ze samen met andere belangrijke documenten bewaren.)
|
||||||
|
|
|
@ -170,7 +170,6 @@
|
||||||
authorize_follow:
|
authorize_follow:
|
||||||
error: Uheldigvis så skjedde det en feil da vi prøvde å få tak i en bruker fra en annen instans.
|
error: Uheldigvis så skjedde det en feil da vi prøvde å få tak i en bruker fra en annen instans.
|
||||||
follow: Følg
|
follow: Følg
|
||||||
prompt_html: 'Du (<strong>%{self}</strong>) har spurt om å følge:'
|
|
||||||
title: Følg %{acct}
|
title: Følg %{acct}
|
||||||
datetime:
|
datetime:
|
||||||
distance_in_words:
|
distance_in_words:
|
||||||
|
|
|
@ -31,7 +31,7 @@ oc:
|
||||||
status_count_after: estatuts
|
status_count_after: estatuts
|
||||||
status_count_before: qu’an escrich
|
status_count_before: qu’an escrich
|
||||||
user_count_after: personas
|
user_count_after: personas
|
||||||
user_count_before: Ostal de
|
user_count_before: Ostal de
|
||||||
what_is_mastodon: Qu’es Mastodon ?
|
what_is_mastodon: Qu’es Mastodon ?
|
||||||
accounts:
|
accounts:
|
||||||
follow: Sègre
|
follow: Sègre
|
||||||
|
@ -214,6 +214,7 @@ oc:
|
||||||
body: "%{reporter} a senhalat %{target}"
|
body: "%{reporter} a senhalat %{target}"
|
||||||
subject: Novèl senhalament per %{instance} (#%{id})
|
subject: Novèl senhalament per %{instance} (#%{id})
|
||||||
application_mailer:
|
application_mailer:
|
||||||
|
salutation: '%{name},'
|
||||||
settings: 'Cambiar las preferéncias de corrièl : %{link}'
|
settings: 'Cambiar las preferéncias de corrièl : %{link}'
|
||||||
signature: Notificacion de Mastodon sus %{instance}
|
signature: Notificacion de Mastodon sus %{instance}
|
||||||
view: 'Veire :'
|
view: 'Veire :'
|
||||||
|
@ -232,6 +233,7 @@ oc:
|
||||||
resend_confirmation: Tornar mandar las instruccions de confirmacion
|
resend_confirmation: Tornar mandar las instruccions de confirmacion
|
||||||
reset_password: Reïnicializar lo senhal
|
reset_password: Reïnicializar lo senhal
|
||||||
set_new_password: Picar un nòu senhal
|
set_new_password: Picar un nòu senhal
|
||||||
|
invalid_reset_password_token: Ligam de reïnicializacion invalid o acabat. Tornatz ensajar se vos plai.
|
||||||
authorize_follow:
|
authorize_follow:
|
||||||
error: O planhèm, i a agut una error al moment de cercar lo compte
|
error: O planhèm, i a agut una error al moment de cercar lo compte
|
||||||
follow: Sègre
|
follow: Sègre
|
||||||
|
@ -241,7 +243,6 @@ oc:
|
||||||
close: O podètz tampar aquesta fenèstra.
|
close: O podètz tampar aquesta fenèstra.
|
||||||
return: Tornar al perfil
|
return: Tornar al perfil
|
||||||
web: Tornar a l’interfàcia Web
|
web: Tornar a l’interfàcia Web
|
||||||
prompt_html: 'Avètz (<strong>%{self}</strong>) demandat de sègre :'
|
|
||||||
title: Sègre %{acct}
|
title: Sègre %{acct}
|
||||||
date:
|
date:
|
||||||
abbr_day_names:
|
abbr_day_names:
|
||||||
|
@ -579,3 +580,4 @@ oc:
|
||||||
users:
|
users:
|
||||||
invalid_email: L’adreça de corrièl es invalida
|
invalid_email: L’adreça de corrièl es invalida
|
||||||
invalid_otp_token: Còdi d’autentificacion en dos temps invalid
|
invalid_otp_token: Còdi d’autentificacion en dos temps invalid
|
||||||
|
signed_in_as: 'Session a'
|
||||||
|
|
|
@ -109,12 +109,14 @@ pl:
|
||||||
hint: Blokada domen nie zabroni tworzenia wpisów kont w bazie danych, ale pozwoli na automatyczną moderację kont do nich należących.
|
hint: Blokada domen nie zabroni tworzenia wpisów kont w bazie danych, ale pozwoli na automatyczną moderację kont do nich należących.
|
||||||
severity:
|
severity:
|
||||||
desc_html: "<strong>Wyciszenie</strong> uczyni wpisy użytkownika widoczne tylko dla osób, które go śledzą. <strong>Zawieszenie</strong> spowoduje usunięcie całej zawartości dodanej przez użytkownika."
|
desc_html: "<strong>Wyciszenie</strong> uczyni wpisy użytkownika widoczne tylko dla osób, które go śledzą. <strong>Zawieszenie</strong> spowoduje usunięcie całej zawartości dodanej przez użytkownika."
|
||||||
|
noop: Nic nie rób
|
||||||
silence: Wycisz
|
silence: Wycisz
|
||||||
suspend: Zawieś
|
suspend: Zawieś
|
||||||
title: Nowa blokada domen
|
title: Nowa blokada domen
|
||||||
reject_media: Odrzucaj pliki multimedialne
|
reject_media: Odrzucaj pliki multimedialne
|
||||||
reject_media_hint: Usuwa przechowywane lokalnie pliki multimedialne i nie pozwala na ich pobieranie. Nieprzydatne przy zawieszeniu
|
reject_media_hint: Usuwa przechowywane lokalnie pliki multimedialne i nie pozwala na ich pobieranie. Nieprzydatne przy zawieszeniu
|
||||||
severities:
|
severities:
|
||||||
|
noop: Nic nie rób
|
||||||
silence: Wycisz
|
silence: Wycisz
|
||||||
suspend: Zawieś
|
suspend: Zawieś
|
||||||
severity: Priorytet
|
severity: Priorytet
|
||||||
|
@ -175,8 +177,8 @@ pl:
|
||||||
desc_html: Akapit wprowadzający, widoczny na stronie głównej i znacznikach meta. Możesz korzystać z tagów HTML, w szczególności <code><a></code> i <code><em></code>.
|
desc_html: Akapit wprowadzający, widoczny na stronie głównej i znacznikach meta. Możesz korzystać z tagów HTML, w szczególności <code><a></code> i <code><em></code>.
|
||||||
title: Opis instancji
|
title: Opis instancji
|
||||||
site_description_extended:
|
site_description_extended:
|
||||||
desc_html: Dobre miejsce na zasady użytkowania, wprowadzenie i inne rzeczy, które wyróżniają tą instancję. Możesz korzystać z tagów HTML
|
desc_html: Dobre miejsce na zasady użytkowania, wprowadzenie i inne rzeczy, które wyróżniają tę instancję. Możesz korzystać z tagów HTML
|
||||||
title: Niestandrdowy opis strony
|
title: Niestandardowy opis strony
|
||||||
site_terms:
|
site_terms:
|
||||||
desc_html: Miejsce na własną politykę prywatności, zasady użytkowania i inne unormowania prawne. Możesz używać tagów HTML
|
desc_html: Miejsce na własną politykę prywatności, zasady użytkowania i inne unormowania prawne. Możesz używać tagów HTML
|
||||||
title: Niestandardowe zasady użytkowania
|
title: Niestandardowe zasady użytkowania
|
||||||
|
@ -213,6 +215,7 @@ pl:
|
||||||
body: Użytkownik %{reporter} zgłosił %{target}
|
body: Użytkownik %{reporter} zgłosił %{target}
|
||||||
subject: Nowe zgłoszenie na %{instance} (#%{id})
|
subject: Nowe zgłoszenie na %{instance} (#%{id})
|
||||||
application_mailer:
|
application_mailer:
|
||||||
|
salutation: "%{name},"
|
||||||
settings: 'Zmień ustawienia powiadamiania: %{link}'
|
settings: 'Zmień ustawienia powiadamiania: %{link}'
|
||||||
signature: Powiadomienie Mastodona z instancji %{instance}
|
signature: Powiadomienie Mastodona z instancji %{instance}
|
||||||
view: 'Zobacz:'
|
view: 'Zobacz:'
|
||||||
|
@ -225,6 +228,7 @@ pl:
|
||||||
delete_account_html: Jeżeli chcesz usunąć konto, <a href="%{path}">przejdź tutaj</a>. Otrzymasz prośbę o potwierdzenie.
|
delete_account_html: Jeżeli chcesz usunąć konto, <a href="%{path}">przejdź tutaj</a>. Otrzymasz prośbę o potwierdzenie.
|
||||||
didnt_get_confirmation: Nie otrzymałeś instrukcji weryfikacji?
|
didnt_get_confirmation: Nie otrzymałeś instrukcji weryfikacji?
|
||||||
forgot_password: Nie pamiętasz hasła?
|
forgot_password: Nie pamiętasz hasła?
|
||||||
|
invalid_reset_password_token: Token do resetowania hasła jest nieprawidłowy lub utracił ważność. Spróbuj uzyskać nowy.
|
||||||
login: Zaloguj się
|
login: Zaloguj się
|
||||||
logout: Wyloguj się
|
logout: Wyloguj się
|
||||||
register: Rejestracja
|
register: Rejestracja
|
||||||
|
@ -237,10 +241,9 @@ pl:
|
||||||
follow_request: 'Wysłano prośbę o pozwolenie na śledzenie:'
|
follow_request: 'Wysłano prośbę o pozwolenie na śledzenie:'
|
||||||
following: 'Pomyślnie! Od teraz śledzisz:'
|
following: 'Pomyślnie! Od teraz śledzisz:'
|
||||||
post_follow:
|
post_follow:
|
||||||
close: Ewentualnie, możesz po prostu zamknąć tą stronę.
|
close: Ewentualnie, możesz po prostu zamknąć tę stronę.
|
||||||
return: Powróć do strony użytkownika
|
return: Powróć do strony użytkownika
|
||||||
web: Przejdź do sieci
|
web: Przejdź do sieci
|
||||||
prompt_html: 'Ty (<strong>%{self}</strong>) chcesz śledzić:'
|
|
||||||
title: Śledź %{acct}
|
title: Śledź %{acct}
|
||||||
datetime:
|
datetime:
|
||||||
distance_in_words:
|
distance_in_words:
|
||||||
|
@ -262,10 +265,10 @@ pl:
|
||||||
description_html: Ta opcja usunie <strong>bezpowrotnie i nieodwracalnie</strong> całą zawartość konta i zdezaktywuje je. Twoja nazwa użytkownika pozostanie zarezerwowana, aby zapobiec nadużyciom.
|
description_html: Ta opcja usunie <strong>bezpowrotnie i nieodwracalnie</strong> całą zawartość konta i zdezaktywuje je. Twoja nazwa użytkownika pozostanie zarezerwowana, aby zapobiec nadużyciom.
|
||||||
proceed: Usuń konto
|
proceed: Usuń konto
|
||||||
success_msg: Twoje konto zostało pomyślnie usunięte
|
success_msg: Twoje konto zostało pomyślnie usunięte
|
||||||
warning_html: Możemy usunąć zawartość jedynie w obrębie tej instancji. Zawartość udostępniona publicznie pozostawia trwałe ślady. Serwery niepodłączone do sieci, bądź nieśledzące Twoich aktualizacji mogą zachować Twoje dane.
|
warning_html: Możemy usunąć zawartość jedynie w obrębie tej instancji. Zawartość udostępniona publicznie pozostawia trwałe ślady. Serwery niepodłączone do sieci bądź nieśledzące Twoich aktualizacji mogą zachować Twoje dane.
|
||||||
warning_title: Dostępność usuniętej zawartości
|
warning_title: Dostępność usuniętej zawartości
|
||||||
errors:
|
errors:
|
||||||
'403': Nie masz uprawnień, aby wyświetlić tą stronę.
|
'403': Nie masz uprawnień, aby wyświetlić tę stronę.
|
||||||
'404': Strona, którą próbujesz odwiedzić, nie istnieje.
|
'404': Strona, którą próbujesz odwiedzić, nie istnieje.
|
||||||
'410': Strona, którą próbujesz odwiedzić, już nie istnieje.
|
'410': Strona, którą próbujesz odwiedzić, już nie istnieje.
|
||||||
'422':
|
'422':
|
||||||
|
@ -336,8 +339,8 @@ pl:
|
||||||
body: "%{name} poprosił o możliwość śledzenia Cię"
|
body: "%{name} poprosił o możliwość śledzenia Cię"
|
||||||
subject: 'Prośba o możliwość śledzenia: %{name}'
|
subject: 'Prośba o możliwość śledzenia: %{name}'
|
||||||
mention:
|
mention:
|
||||||
body: "%{name} wspomniał Cię w:"
|
body: "%{name} wspomniał o Tobie w:"
|
||||||
subject: "%{name} Cię wspomniał"
|
subject: "%{name} wspomniał o Tobie"
|
||||||
reblog:
|
reblog:
|
||||||
body: 'Twój wpis został podbity przez %{name}:'
|
body: 'Twój wpis został podbity przez %{name}:'
|
||||||
subject: Twój wpis został podbity przez %{name}
|
subject: Twój wpis został podbity przez %{name}
|
||||||
|
@ -524,3 +527,4 @@ pl:
|
||||||
users:
|
users:
|
||||||
invalid_email: Adres e-mail jest niepoprawny
|
invalid_email: Adres e-mail jest niepoprawny
|
||||||
invalid_otp_token: Kod uwierzytelniający jest niepoprawny
|
invalid_otp_token: Kod uwierzytelniający jest niepoprawny
|
||||||
|
signed_in_as: 'Zalogowany jako:'
|
||||||
|
|
|
@ -169,7 +169,6 @@ pt-BR:
|
||||||
authorize_follow:
|
authorize_follow:
|
||||||
error: Infelizmente houve um erro olhando uma conta remota
|
error: Infelizmente houve um erro olhando uma conta remota
|
||||||
follow: Seguir
|
follow: Seguir
|
||||||
prompt_html: 'Você (<strong>%{self}</strong>) pediu pra seguir:'
|
|
||||||
title: Seguir %{acct}
|
title: Seguir %{acct}
|
||||||
datetime:
|
datetime:
|
||||||
distance_in_words:
|
distance_in_words:
|
||||||
|
|
|
@ -162,7 +162,6 @@ ru:
|
||||||
authorize_follow:
|
authorize_follow:
|
||||||
error: К сожалению, при поиске удаленного аккаунта возникла ошибка
|
error: К сожалению, при поиске удаленного аккаунта возникла ошибка
|
||||||
follow: Подписаться
|
follow: Подписаться
|
||||||
prompt_html: 'Вы (<strong>%{self}</strong>) запросили подписку:'
|
|
||||||
title: Подписаться на %{acct}
|
title: Подписаться на %{acct}
|
||||||
datetime:
|
datetime:
|
||||||
distance_in_words:
|
distance_in_words:
|
||||||
|
@ -269,14 +268,14 @@ ru:
|
||||||
truncate: "…"
|
truncate: "…"
|
||||||
push_notifications:
|
push_notifications:
|
||||||
favourite:
|
favourite:
|
||||||
title: "Ваш статус понравился %{name}"
|
title: Ваш статус понравился %{name}
|
||||||
follow:
|
follow:
|
||||||
title: "%{name} теперь подписан(а) на Вас"
|
title: "%{name} теперь подписан(а) на Вас"
|
||||||
mention:
|
mention:
|
||||||
action_boost: Продвинуть
|
action_boost: Продвинуть
|
||||||
action_expand: Развернуть
|
action_expand: Развернуть
|
||||||
action_favourite: Нравится
|
action_favourite: Нравится
|
||||||
title: "Вас упомянул(а) %{name}"
|
title: Вас упомянул(а) %{name}
|
||||||
reblog:
|
reblog:
|
||||||
title: "%{name} продвинул(а) Ваш статус"
|
title: "%{name} продвинул(а) Ваш статус"
|
||||||
subscribed:
|
subscribed:
|
||||||
|
@ -351,7 +350,7 @@ ru:
|
||||||
reblogged: продвинул(а)
|
reblogged: продвинул(а)
|
||||||
sensitive_content: Чувствительный контент
|
sensitive_content: Чувствительный контент
|
||||||
terms:
|
terms:
|
||||||
title: "Условия обслуживания и политика конфиденциальности %{instance}"
|
title: Условия обслуживания и политика конфиденциальности %{instance}
|
||||||
time:
|
time:
|
||||||
formats:
|
formats:
|
||||||
default: "%b %d, %Y, %H:%M"
|
default: "%b %d, %Y, %H:%M"
|
||||||
|
|
|
@ -40,7 +40,7 @@ fa:
|
||||||
setting_boost_modal: نمایش پیغام تأیید پیش از بازبوقیدن
|
setting_boost_modal: نمایش پیغام تأیید پیش از بازبوقیدن
|
||||||
setting_default_privacy: حریم خصوصی نوشتهها
|
setting_default_privacy: حریم خصوصی نوشتهها
|
||||||
setting_default_sensitive: همیشه تصاویر را به عنوان حساس علامت بزن
|
setting_default_sensitive: همیشه تصاویر را به عنوان حساس علامت بزن
|
||||||
setting_delete_modal: پیش از پاک کردن یک بوق پیغام تأیید نشان بده
|
setting_delete_modal: پیش از پاک کردن یک نوشته پیغام تأیید نشان بده
|
||||||
setting_noindex: درخواست از موتورهای جستجو برای لغو فهرستسازی
|
setting_noindex: درخواست از موتورهای جستجو برای لغو فهرستسازی
|
||||||
setting_system_font_ui: بهکاربردن قلم پیشفرض سیستم
|
setting_system_font_ui: بهکاربردن قلم پیشفرض سیستم
|
||||||
setting_unfollow_modal: نمایش پیغام تأیید پیش از لغو پیگیری دیگران
|
setting_unfollow_modal: نمایش پیغام تأیید پیش از لغو پیگیری دیگران
|
||||||
|
|
|
@ -170,7 +170,6 @@ th:
|
||||||
authorize_follow:
|
authorize_follow:
|
||||||
error: Unfortunately, there was an error looking up the remote account
|
error: Unfortunately, there was an error looking up the remote account
|
||||||
follow: ติดตาม
|
follow: ติดตาม
|
||||||
prompt_html: 'คุณ (<strong>%{self}</strong>) ขอติดตาม:'
|
|
||||||
title: ติดตาม %{acct}
|
title: ติดตาม %{acct}
|
||||||
datetime:
|
datetime:
|
||||||
distance_in_words:
|
distance_in_words:
|
||||||
|
|
|
@ -169,7 +169,6 @@ tr:
|
||||||
authorize_follow:
|
authorize_follow:
|
||||||
error: Uzak hesap aranırken bir hata oluştu.
|
error: Uzak hesap aranırken bir hata oluştu.
|
||||||
follow: Takip et
|
follow: Takip et
|
||||||
prompt_html: 'Siz (<strong>%{self}</strong>) bu kullanıcıyı takip etmek istiyor musunuz?:'
|
|
||||||
title: "%{acct}'i takip et"
|
title: "%{acct}'i takip et"
|
||||||
datetime:
|
datetime:
|
||||||
distance_in_words:
|
distance_in_words:
|
||||||
|
|
|
@ -160,7 +160,6 @@ uk:
|
||||||
authorize_follow:
|
authorize_follow:
|
||||||
error: На жаль, при пошуку віддаленого аккаунту виникла помилка
|
error: На жаль, при пошуку віддаленого аккаунту виникла помилка
|
||||||
follow: Підписатися
|
follow: Підписатися
|
||||||
prompt_html: 'Ви (<strong>%{self}</strong>) запитали про підписку:'
|
|
||||||
title: Підписатися на %{acct}
|
title: Підписатися на %{acct}
|
||||||
datetime:
|
datetime:
|
||||||
distance_in_words:
|
distance_in_words:
|
||||||
|
|
|
@ -176,7 +176,6 @@ zh-CN:
|
||||||
authorize_follow:
|
authorize_follow:
|
||||||
error: 对不起,寻找这个跨站用户时出错
|
error: 对不起,寻找这个跨站用户时出错
|
||||||
follow: 关注
|
follow: 关注
|
||||||
prompt_html: 你 (<strong>%{self}</strong>) 正准备关注︰
|
|
||||||
title: 关注 %{acct}
|
title: 关注 %{acct}
|
||||||
datetime:
|
datetime:
|
||||||
distance_in_words:
|
distance_in_words:
|
||||||
|
|
|
@ -169,7 +169,6 @@ zh-HK:
|
||||||
authorize_follow:
|
authorize_follow:
|
||||||
error: 對不起,尋找這個跨站用戶的過程發生錯誤
|
error: 對不起,尋找這個跨站用戶的過程發生錯誤
|
||||||
follow: 關注
|
follow: 關注
|
||||||
prompt_html: 你 (<strong>%{self}</strong>) 正準備關注︰
|
|
||||||
title: 關注 %{acct}
|
title: 關注 %{acct}
|
||||||
datetime:
|
datetime:
|
||||||
distance_in_words:
|
distance_in_words:
|
||||||
|
|
|
@ -140,7 +140,6 @@ zh-TW:
|
||||||
authorize_follow:
|
authorize_follow:
|
||||||
error: 對不起,尋找這個跨站使用者的過程發生錯誤
|
error: 對不起,尋找這個跨站使用者的過程發生錯誤
|
||||||
follow: 關注
|
follow: 關注
|
||||||
prompt_html: 您 (<strong>%{self}</strong>) 正準備關注︰
|
|
||||||
title: 關注 %{acct}
|
title: 關注 %{acct}
|
||||||
datetime:
|
datetime:
|
||||||
distance_in_words:
|
distance_in_words:
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
const { resolve } = require('path');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
test: /\.js$/,
|
test: /\.js$/,
|
||||||
// include react-intl because transform-react-remove-prop-types needs to apply to it
|
// include react-intl because transform-react-remove-prop-types needs to apply to it
|
||||||
|
@ -9,5 +11,6 @@ module.exports = {
|
||||||
options: {
|
options: {
|
||||||
forceEnv: process.env.NODE_ENV || 'development',
|
forceEnv: process.env.NODE_ENV || 'development',
|
||||||
sourceRoot: 'app/javascript',
|
sourceRoot: 'app/javascript',
|
||||||
|
cacheDirectory: resolve(__dirname, '..', '..', '..', 'tmp', 'cache', 'babel-loader'),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,7 +13,7 @@ module Mastodon
|
||||||
end
|
end
|
||||||
|
|
||||||
def patch
|
def patch
|
||||||
0
|
1
|
||||||
end
|
end
|
||||||
|
|
||||||
def pre
|
def pre
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
|
||||||
describe Auth::PasswordsController, type: :controller do
|
describe Auth::PasswordsController, type: :controller do
|
||||||
|
include Devise::Test::ControllerHelpers
|
||||||
|
|
||||||
describe 'GET #new' do
|
describe 'GET #new' do
|
||||||
it 'returns http success' do
|
it 'returns http success' do
|
||||||
@request.env['devise.mapping'] = Devise.mappings[:user]
|
@request.env['devise.mapping'] = Devise.mappings[:user]
|
||||||
|
@ -10,4 +12,27 @@ describe Auth::PasswordsController, type: :controller do
|
||||||
expect(response).to have_http_status(:success)
|
expect(response).to have_http_status(:success)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'GET #edit' do
|
||||||
|
let(:user) { Fabricate(:user) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
request.env['devise.mapping'] = Devise.mappings[:user]
|
||||||
|
@token = user.send_reset_password_instructions
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with valid reset_password_token' do
|
||||||
|
it 'returns http success' do
|
||||||
|
get :edit, params: { reset_password_token: @token }
|
||||||
|
expect(response).to have_http_status(:success)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with invalid reset_password_token' do
|
||||||
|
it 'redirects to #new' do
|
||||||
|
get :edit, params: { reset_password_token: 'some_invalid_value' }
|
||||||
|
expect(response).to redirect_to subject.new_password_path(subject.send(:resource_name))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -28,7 +28,7 @@ RSpec.describe Auth::SessionsController, type: :controller do
|
||||||
sign_in(user, scope: :user)
|
sign_in(user, scope: :user)
|
||||||
delete :destroy
|
delete :destroy
|
||||||
|
|
||||||
expect(response).to redirect_to(root_path)
|
expect(response).to redirect_to(new_user_session_path)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ RSpec.describe Auth::SessionsController, type: :controller do
|
||||||
sign_in(user, scope: :user)
|
sign_in(user, scope: :user)
|
||||||
delete :destroy
|
delete :destroy
|
||||||
|
|
||||||
expect(response).to redirect_to(root_path)
|
expect(response).to redirect_to(new_user_session_path)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,19 +9,9 @@ describe('<DisplayName />', () => {
|
||||||
const account = fromJS({
|
const account = fromJS({
|
||||||
username: 'bar',
|
username: 'bar',
|
||||||
acct: 'bar@baz',
|
acct: 'bar@baz',
|
||||||
display_name: 'Foo',
|
display_name_html: '<p>Foo</p>',
|
||||||
});
|
});
|
||||||
const wrapper = render(<DisplayName account={account} />);
|
const wrapper = render(<DisplayName account={account} />);
|
||||||
expect(wrapper).to.have.text('Foo @bar@baz');
|
expect(wrapper).to.have.text('Foo @bar@baz');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders the username + account name if display name is empty', () => {
|
|
||||||
const account = fromJS({
|
|
||||||
username: 'bar',
|
|
||||||
acct: 'bar@baz',
|
|
||||||
display_name: '',
|
|
||||||
});
|
|
||||||
const wrapper = render(<DisplayName account={account} />);
|
|
||||||
expect(wrapper).to.have.text('bar @bar@baz');
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue