Merge remote-tracking branch 'parent/main' into kb_migration
This commit is contained in:
commit
979292d950
56 changed files with 774 additions and 277 deletions
113
.github/workflows/test-ruby.yml
vendored
113
.github/workflows/test-ruby.yml
vendored
|
@ -250,3 +250,116 @@ jobs:
|
||||||
with:
|
with:
|
||||||
name: e2e-screenshots
|
name: e2e-screenshots
|
||||||
path: tmp/screenshots/
|
path: tmp/screenshots/
|
||||||
|
|
||||||
|
test-search:
|
||||||
|
name: Testing search
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
needs:
|
||||||
|
- build
|
||||||
|
|
||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: postgres:14-alpine
|
||||||
|
env:
|
||||||
|
POSTGRES_PASSWORD: postgres
|
||||||
|
POSTGRES_USER: postgres
|
||||||
|
options: >-
|
||||||
|
--health-cmd pg_isready
|
||||||
|
--health-interval 10s
|
||||||
|
--health-timeout 5s
|
||||||
|
--health-retries 5
|
||||||
|
ports:
|
||||||
|
- 5432:5432
|
||||||
|
|
||||||
|
redis:
|
||||||
|
image: redis:7-alpine
|
||||||
|
options: >-
|
||||||
|
--health-cmd "redis-cli ping"
|
||||||
|
--health-interval 10s
|
||||||
|
--health-timeout 5s
|
||||||
|
--health-retries 5
|
||||||
|
ports:
|
||||||
|
- 6379:6379
|
||||||
|
|
||||||
|
elasticsearch:
|
||||||
|
image: docker.elastic.co/elasticsearch/elasticsearch:7.17.9
|
||||||
|
env:
|
||||||
|
discovery.type: single-node
|
||||||
|
xpack.security.enabled: false
|
||||||
|
options: >-
|
||||||
|
--health-cmd "curl http://localhost:9200/_cluster/health"
|
||||||
|
--health-interval 10s
|
||||||
|
--health-timeout 5s
|
||||||
|
--health-retries 10
|
||||||
|
ports:
|
||||||
|
- 9200:9200
|
||||||
|
|
||||||
|
env:
|
||||||
|
DB_HOST: localhost
|
||||||
|
DB_USER: postgres
|
||||||
|
DB_PASS: postgres
|
||||||
|
DISABLE_SIMPLECOV: true
|
||||||
|
RAILS_ENV: test
|
||||||
|
BUNDLE_WITH: test
|
||||||
|
ES_ENABLED: true
|
||||||
|
ES_HOST: localhost
|
||||||
|
ES_PORT: 9200
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
ruby-version:
|
||||||
|
- '3.0'
|
||||||
|
- '3.1'
|
||||||
|
- '.ruby-version'
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
path: './public'
|
||||||
|
name: ${{ github.sha }}
|
||||||
|
|
||||||
|
- name: Update package index
|
||||||
|
run: sudo apt-get update
|
||||||
|
|
||||||
|
- name: Set up Node.js
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
cache: yarn
|
||||||
|
node-version-file: '.nvmrc'
|
||||||
|
|
||||||
|
- name: Install native Ruby dependencies
|
||||||
|
run: sudo apt-get install -y libicu-dev libidn11-dev
|
||||||
|
|
||||||
|
- name: Install additional system dependencies
|
||||||
|
run: sudo apt-get install -y ffmpeg imagemagick
|
||||||
|
|
||||||
|
- name: Set up bundler cache
|
||||||
|
uses: ruby/setup-ruby@v1
|
||||||
|
with:
|
||||||
|
ruby-version: ${{ matrix.ruby-version}}
|
||||||
|
bundler-cache: true
|
||||||
|
|
||||||
|
- run: yarn --frozen-lockfile
|
||||||
|
|
||||||
|
- name: Load database schema
|
||||||
|
run: './bin/rails db:create db:schema:load db:seed'
|
||||||
|
|
||||||
|
- run: bundle exec rake spec:search
|
||||||
|
|
||||||
|
- name: Archive logs
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
if: failure()
|
||||||
|
with:
|
||||||
|
name: test-search-logs-${{ matrix.ruby-version }}
|
||||||
|
path: log/
|
||||||
|
|
||||||
|
- name: Archive test screenshots
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
if: failure()
|
||||||
|
with:
|
||||||
|
name: test-search-screenshots
|
||||||
|
path: tmp/screenshots/
|
||||||
|
|
2
.nvmrc
2
.nvmrc
|
@ -1 +1 @@
|
||||||
16.20
|
20.6
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# syntax=docker/dockerfile:1.4
|
# syntax=docker/dockerfile:1.4
|
||||||
# This needs to be bookworm-slim because the Ruby image is built on bookworm-slim
|
# This needs to be bookworm-slim because the Ruby image is built on bookworm-slim
|
||||||
ARG NODE_VERSION="16.20-bookworm-slim"
|
ARG NODE_VERSION="20.6-bookworm-slim"
|
||||||
|
|
||||||
FROM ghcr.io/moritzheiber/ruby-jemalloc:3.2.2-slim as ruby
|
FROM ghcr.io/moritzheiber/ruby-jemalloc:3.2.2-slim as ruby
|
||||||
FROM node:${NODE_VERSION} as build
|
FROM node:${NODE_VERSION} as build
|
||||||
|
|
|
@ -27,4 +27,5 @@ More information on HTTP Signatures, as well as examples, can be found here: htt
|
||||||
|
|
||||||
- Linked-Data Signatures: https://docs.joinmastodon.org/spec/security/#ld
|
- Linked-Data Signatures: https://docs.joinmastodon.org/spec/security/#ld
|
||||||
- Bearcaps: https://docs.joinmastodon.org/spec/bearcaps/
|
- Bearcaps: https://docs.joinmastodon.org/spec/bearcaps/
|
||||||
- Followers collection synchronization: https://git.activitypub.dev/ActivityPubDev/Fediverse-Enhancement-Proposals/src/branch/main/feps/fep-8fcf.md
|
- Followers collection synchronization: https://codeberg.org/fediverse/fep/src/branch/main/fep/8fcf/fep-8fcf.md
|
||||||
|
- Search indexing consent for actors: https://codeberg.org/fediverse/fep/src/branch/main/fep/5feb/fep-5feb.md
|
||||||
|
|
|
@ -520,7 +520,7 @@ GEM
|
||||||
pastel (0.8.0)
|
pastel (0.8.0)
|
||||||
tty-color (~> 0.5)
|
tty-color (~> 0.5)
|
||||||
pg (1.5.4)
|
pg (1.5.4)
|
||||||
pghero (3.3.3)
|
pghero (3.3.4)
|
||||||
activerecord (>= 6)
|
activerecord (>= 6)
|
||||||
posix-spawn (0.3.15)
|
posix-spawn (0.3.15)
|
||||||
premailer (1.21.0)
|
premailer (1.21.0)
|
||||||
|
|
12
SECURITY.md
12
SECURITY.md
|
@ -13,9 +13,9 @@ A "vulnerability in Mastodon" is a vulnerability in the code distributed through
|
||||||
|
|
||||||
## Supported Versions
|
## Supported Versions
|
||||||
|
|
||||||
| Version | Supported |
|
| Version | Supported |
|
||||||
| ------- | --------- |
|
| ------- | ---------------- |
|
||||||
| 4.1.x | Yes |
|
| 4.1.x | Yes |
|
||||||
| 4.0.x | Yes |
|
| 4.0.x | Until 2023-10-31 |
|
||||||
| 3.5.x | Yes |
|
| 3.5.x | Until 2023-12-31 |
|
||||||
| < 3.5 | No |
|
| < 3.5 | No |
|
||||||
|
|
3
Vagrantfile
vendored
3
Vagrantfile
vendored
|
@ -76,7 +76,8 @@ path.logs: /var/log/elasticsearch
|
||||||
network.host: 0.0.0.0
|
network.host: 0.0.0.0
|
||||||
http.port: 9200
|
http.port: 9200
|
||||||
discovery.seed_hosts: ["localhost"]
|
discovery.seed_hosts: ["localhost"]
|
||||||
cluster.initial_master_nodes: ["node-1"]' > /etc/elasticsearch/elasticsearch.yml
|
cluster.initial_master_nodes: ["node-1"]
|
||||||
|
xpack.security.enabled: false' > /etc/elasticsearch/elasticsearch.yml
|
||||||
|
|
||||||
sudo systemctl restart elasticsearch
|
sudo systemctl restart elasticsearch
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,9 @@ class Api::V1::DirectoriesController < Api::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_accounts
|
def set_accounts
|
||||||
@accounts = accounts_scope.offset(params[:offset]).limit(limit_param(DEFAULT_ACCOUNTS_LIMIT))
|
with_read_replica do
|
||||||
|
@accounts = accounts_scope.offset(params[:offset]).limit(limit_param(DEFAULT_ACCOUNTS_LIMIT))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def accounts_scope
|
def accounts_scope
|
||||||
|
|
|
@ -119,7 +119,7 @@ module SignatureVerification
|
||||||
private
|
private
|
||||||
|
|
||||||
def fail_with!(message, **options)
|
def fail_with!(message, **options)
|
||||||
Rails.logger.warn { "Signature verification failed: #{message}" }
|
Rails.logger.debug { "Signature verification failed: #{message}" }
|
||||||
|
|
||||||
@signature_verification_failure_reason = { error: message }.merge(options)
|
@signature_verification_failure_reason = { error: message }.merge(options)
|
||||||
@signed_request_actor = nil
|
@signed_request_actor = nil
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
import { fromJS } from 'immutable';
|
||||||
|
|
||||||
|
import { searchHistory } from 'mastodon/settings';
|
||||||
|
|
||||||
import api from '../api';
|
import api from '../api';
|
||||||
|
|
||||||
import { fetchRelationships } from './accounts';
|
import { fetchRelationships } from './accounts';
|
||||||
|
@ -15,8 +19,7 @@ export const SEARCH_EXPAND_REQUEST = 'SEARCH_EXPAND_REQUEST';
|
||||||
export const SEARCH_EXPAND_SUCCESS = 'SEARCH_EXPAND_SUCCESS';
|
export const SEARCH_EXPAND_SUCCESS = 'SEARCH_EXPAND_SUCCESS';
|
||||||
export const SEARCH_EXPAND_FAIL = 'SEARCH_EXPAND_FAIL';
|
export const SEARCH_EXPAND_FAIL = 'SEARCH_EXPAND_FAIL';
|
||||||
|
|
||||||
export const SEARCH_RESULT_CLICK = 'SEARCH_RESULT_CLICK';
|
export const SEARCH_HISTORY_UPDATE = 'SEARCH_HISTORY_UPDATE';
|
||||||
export const SEARCH_RESULT_FORGET = 'SEARCH_RESULT_FORGET';
|
|
||||||
|
|
||||||
export function changeSearch(value) {
|
export function changeSearch(value) {
|
||||||
return {
|
return {
|
||||||
|
@ -170,16 +173,34 @@ export const openURL = (value, history, onFailure) => (dispatch, getState) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const clickSearchResult = (q, type) => ({
|
export const clickSearchResult = (q, type) => (dispatch, getState) => {
|
||||||
type: SEARCH_RESULT_CLICK,
|
const previous = getState().getIn(['search', 'recent']);
|
||||||
|
const me = getState().getIn(['meta', 'me']);
|
||||||
|
const current = previous.add(fromJS({ type, q })).takeLast(4);
|
||||||
|
|
||||||
result: {
|
searchHistory.set(me, current.toJS());
|
||||||
type,
|
dispatch(updateSearchHistory(current));
|
||||||
q,
|
};
|
||||||
},
|
|
||||||
|
export const forgetSearchResult = q => (dispatch, getState) => {
|
||||||
|
const previous = getState().getIn(['search', 'recent']);
|
||||||
|
const me = getState().getIn(['meta', 'me']);
|
||||||
|
const current = previous.filterNot(result => result.get('q') === q);
|
||||||
|
|
||||||
|
searchHistory.set(me, current.toJS());
|
||||||
|
dispatch(updateSearchHistory(current));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateSearchHistory = recent => ({
|
||||||
|
type: SEARCH_HISTORY_UPDATE,
|
||||||
|
recent,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const forgetSearchResult = q => ({
|
export const hydrateSearch = () => (dispatch, getState) => {
|
||||||
type: SEARCH_RESULT_FORGET,
|
const me = getState().getIn(['meta', 'me']);
|
||||||
q,
|
const history = searchHistory.get(me);
|
||||||
});
|
|
||||||
|
if (history !== null) {
|
||||||
|
dispatch(updateSearchHistory(history));
|
||||||
|
}
|
||||||
|
};
|
|
@ -2,6 +2,7 @@ import { Iterable, fromJS } from 'immutable';
|
||||||
|
|
||||||
import { hydrateCompose } from './compose';
|
import { hydrateCompose } from './compose';
|
||||||
import { importFetchedAccounts } from './importer';
|
import { importFetchedAccounts } from './importer';
|
||||||
|
import { hydrateSearch } from './search';
|
||||||
|
|
||||||
export const STORE_HYDRATE = 'STORE_HYDRATE';
|
export const STORE_HYDRATE = 'STORE_HYDRATE';
|
||||||
export const STORE_HYDRATE_LAZY = 'STORE_HYDRATE_LAZY';
|
export const STORE_HYDRATE_LAZY = 'STORE_HYDRATE_LAZY';
|
||||||
|
@ -20,6 +21,7 @@ export function hydrateStore(rawState) {
|
||||||
});
|
});
|
||||||
|
|
||||||
dispatch(hydrateCompose());
|
dispatch(hydrateCompose());
|
||||||
|
dispatch(hydrateSearch());
|
||||||
dispatch(importFetchedAccounts(Object.values(rawState.accounts)));
|
dispatch(importFetchedAccounts(Object.values(rawState.accounts)));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -205,11 +205,11 @@ class Audio extends PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
toggleMute = () => {
|
toggleMute = () => {
|
||||||
const muted = !this.state.muted;
|
const muted = !(this.state.muted || this.state.volume === 0);
|
||||||
|
|
||||||
this.setState({ muted }, () => {
|
this.setState((state) => ({ muted, volume: Math.max(state.volume || 0.5, 0.05) }), () => {
|
||||||
if (this.gainNode) {
|
if (this.gainNode) {
|
||||||
this.gainNode.gain.value = muted ? 0 : this.state.volume;
|
this.gainNode.gain.value = this.state.muted ? 0 : this.state.volume;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -287,7 +287,7 @@ class Audio extends PureComponent {
|
||||||
const { x } = getPointerPosition(this.volume, e);
|
const { x } = getPointerPosition(this.volume, e);
|
||||||
|
|
||||||
if(!isNaN(x)) {
|
if(!isNaN(x)) {
|
||||||
this.setState({ volume: x }, () => {
|
this.setState((state) => ({ volume: x, muted: state.muted && x === 0 }), () => {
|
||||||
if (this.gainNode) {
|
if (this.gainNode) {
|
||||||
this.gainNode.gain.value = this.state.muted ? 0 : x;
|
this.gainNode.gain.value = this.state.muted ? 0 : x;
|
||||||
}
|
}
|
||||||
|
@ -466,8 +466,9 @@ class Audio extends PureComponent {
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { src, intl, alt, lang, editable, autoPlay, sensitive, blurhash } = this.props;
|
const { src, intl, alt, lang, editable, autoPlay, sensitive, blurhash } = this.props;
|
||||||
const { paused, muted, volume, currentTime, duration, buffer, dragging, revealed } = this.state;
|
const { paused, volume, currentTime, duration, buffer, dragging, revealed } = this.state;
|
||||||
const progress = Math.min((currentTime / duration) * 100, 100);
|
const progress = Math.min((currentTime / duration) * 100, 100);
|
||||||
|
const muted = this.state.muted || volume === 0;
|
||||||
|
|
||||||
let warning;
|
let warning;
|
||||||
|
|
||||||
|
@ -557,12 +558,12 @@ class Audio extends PureComponent {
|
||||||
<button type='button' title={intl.formatMessage(muted ? messages.unmute : messages.mute)} aria-label={intl.formatMessage(muted ? messages.unmute : messages.mute)} className='player-button' onClick={this.toggleMute}><Icon id={muted ? 'volume-off' : 'volume-up'} fixedWidth /></button>
|
<button type='button' title={intl.formatMessage(muted ? messages.unmute : messages.mute)} aria-label={intl.formatMessage(muted ? messages.unmute : messages.mute)} className='player-button' onClick={this.toggleMute}><Icon id={muted ? 'volume-off' : 'volume-up'} fixedWidth /></button>
|
||||||
|
|
||||||
<div className={classNames('video-player__volume', { active: this.state.hovered })} ref={this.setVolumeRef} onMouseDown={this.handleVolumeMouseDown}>
|
<div className={classNames('video-player__volume', { active: this.state.hovered })} ref={this.setVolumeRef} onMouseDown={this.handleVolumeMouseDown}>
|
||||||
<div className='video-player__volume__current' style={{ width: `${volume * 100}%`, backgroundColor: this._getAccentColor() }} />
|
<div className='video-player__volume__current' style={{ width: `${muted ? 0 : volume * 100}%`, backgroundColor: this._getAccentColor() }} />
|
||||||
|
|
||||||
<span
|
<span
|
||||||
className='video-player__volume__handle'
|
className='video-player__volume__handle'
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
style={{ left: `${volume * 100}%`, backgroundColor: this._getAccentColor() }}
|
style={{ left: `${muted ? 0 : volume * 100}%`, backgroundColor: this._getAccentColor() }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ import classNames from 'classnames';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
|
|
||||||
import { Icon } from 'mastodon/components/icon';
|
import { Icon } from 'mastodon/components/icon';
|
||||||
import { searchEnabled } from 'mastodon/initial_state';
|
import { domain, searchEnabled } from 'mastodon/initial_state';
|
||||||
import { HASHTAG_REGEX } from 'mastodon/utils/hashtags';
|
import { HASHTAG_REGEX } from 'mastodon/utils/hashtags';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
|
@ -16,6 +16,17 @@ const messages = defineMessages({
|
||||||
placeholderSignedIn: { id: 'search.search_or_paste', defaultMessage: 'Search or paste URL' },
|
placeholderSignedIn: { id: 'search.search_or_paste', defaultMessage: 'Search or paste URL' },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const labelForRecentSearch = search => {
|
||||||
|
switch(search.get('type')) {
|
||||||
|
case 'account':
|
||||||
|
return `@${search.get('q')}`;
|
||||||
|
case 'hashtag':
|
||||||
|
return `#${search.get('q')}`;
|
||||||
|
default:
|
||||||
|
return search.get('q');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class Search extends PureComponent {
|
class Search extends PureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
|
@ -54,6 +65,7 @@ class Search extends PureComponent {
|
||||||
{ label: <><mark>before:</mark> <FormattedMessage id='search_popout.specific_date' defaultMessage='specific date' /></>, action: e => { e.preventDefault(); this._insertText('before:') } },
|
{ label: <><mark>before:</mark> <FormattedMessage id='search_popout.specific_date' defaultMessage='specific date' /></>, action: e => { e.preventDefault(); this._insertText('before:') } },
|
||||||
{ label: <><mark>during:</mark> <FormattedMessage id='search_popout.specific_date' defaultMessage='specific date' /></>, action: e => { e.preventDefault(); this._insertText('during:') } },
|
{ label: <><mark>during:</mark> <FormattedMessage id='search_popout.specific_date' defaultMessage='specific date' /></>, action: e => { e.preventDefault(); this._insertText('during:') } },
|
||||||
{ label: <><mark>after:</mark> <FormattedMessage id='search_popout.specific_date' defaultMessage='specific date' /></>, action: e => { e.preventDefault(); this._insertText('after:') } },
|
{ label: <><mark>after:</mark> <FormattedMessage id='search_popout.specific_date' defaultMessage='specific date' /></>, action: e => { e.preventDefault(); this._insertText('after:') } },
|
||||||
|
{ label: <><mark>in:</mark> <FormattedList type='disjunction' value={['all', 'library']} /></>, action: e => { e.preventDefault(); this._insertText('in:') } }
|
||||||
];
|
];
|
||||||
|
|
||||||
setRef = c => {
|
setRef = c => {
|
||||||
|
@ -187,12 +199,16 @@ class Search extends PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
handleRecentSearchClick = search => {
|
handleRecentSearchClick = search => {
|
||||||
|
const { onChange } = this.props;
|
||||||
const { router } = this.context;
|
const { router } = this.context;
|
||||||
|
|
||||||
if (search.get('type') === 'account') {
|
if (search.get('type') === 'account') {
|
||||||
router.history.push(`/@${search.get('q')}`);
|
router.history.push(`/@${search.get('q')}`);
|
||||||
} else if (search.get('type') === 'hashtag') {
|
} else if (search.get('type') === 'hashtag') {
|
||||||
router.history.push(`/tags/${search.get('q')}`);
|
router.history.push(`/tags/${search.get('q')}`);
|
||||||
|
} else {
|
||||||
|
onChange(search.get('q'));
|
||||||
|
this._submit(search.get('type'));
|
||||||
}
|
}
|
||||||
|
|
||||||
this._unfocus();
|
this._unfocus();
|
||||||
|
@ -221,11 +237,15 @@ class Search extends PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
_submit (type) {
|
_submit (type) {
|
||||||
const { onSubmit, openInRoute } = this.props;
|
const { onSubmit, openInRoute, value, onClickSearchResult } = this.props;
|
||||||
const { router } = this.context;
|
const { router } = this.context;
|
||||||
|
|
||||||
onSubmit(type);
|
onSubmit(type);
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
onClickSearchResult(value, type);
|
||||||
|
}
|
||||||
|
|
||||||
if (openInRoute) {
|
if (openInRoute) {
|
||||||
router.history.push('/search');
|
router.history.push('/search');
|
||||||
}
|
}
|
||||||
|
@ -243,7 +263,7 @@ class Search extends PureComponent {
|
||||||
const { recent } = this.props;
|
const { recent } = this.props;
|
||||||
|
|
||||||
return recent.toArray().map(search => ({
|
return recent.toArray().map(search => ({
|
||||||
label: search.get('type') === 'account' ? `@${search.get('q')}` : `#${search.get('q')}`,
|
label: labelForRecentSearch(search),
|
||||||
|
|
||||||
action: () => this.handleRecentSearchClick(search),
|
action: () => this.handleRecentSearchClick(search),
|
||||||
|
|
||||||
|
@ -354,18 +374,20 @@ class Search extends PureComponent {
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{searchEnabled && (
|
<h4><FormattedMessage id='search_popout.options' defaultMessage='Search options' /></h4>
|
||||||
<>
|
|
||||||
<h4><FormattedMessage id='search_popout.options' defaultMessage='Search options' /></h4>
|
|
||||||
|
|
||||||
<div className='search__popout__menu'>
|
{searchEnabled ? (
|
||||||
{this.defaultOptions.map(({ key, label, action }, i) => (
|
<div className='search__popout__menu'>
|
||||||
<button key={key} onMouseDown={action} className={classNames('search__popout__menu__item', { selected: selectedOption === (options.length + i) })}>
|
{this.defaultOptions.map(({ key, label, action }, i) => (
|
||||||
{label}
|
<button key={key} onMouseDown={action} className={classNames('search__popout__menu__item', { selected: selectedOption === ((options.length || recent.size) + i) })}>
|
||||||
</button>
|
{label}
|
||||||
))}
|
</button>
|
||||||
</div>
|
))}
|
||||||
</>
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className='search__popout__menu__message'>
|
||||||
|
<FormattedMessage id='search_popout.full_text_search_disabled_message' defaultMessage='Not available on {domain}.' values={{ domain }} />
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -15,7 +15,7 @@ import Search from '../components/search';
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
value: state.getIn(['search', 'value']),
|
value: state.getIn(['search', 'value']),
|
||||||
submitted: state.getIn(['search', 'submitted']),
|
submitted: state.getIn(['search', 'submitted']),
|
||||||
recent: state.getIn(['search', 'recent']),
|
recent: state.getIn(['search', 'recent']).reverse(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => ({
|
const mapDispatchToProps = dispatch => ({
|
||||||
|
|
|
@ -217,8 +217,9 @@ class Video extends PureComponent {
|
||||||
const { x } = getPointerPosition(this.volume, e);
|
const { x } = getPointerPosition(this.volume, e);
|
||||||
|
|
||||||
if(!isNaN(x)) {
|
if(!isNaN(x)) {
|
||||||
this.setState({ volume: x }, () => {
|
this.setState((state) => ({ volume: x, muted: state.muted && x === 0 }), () => {
|
||||||
this.video.volume = x;
|
this.video.volume = x;
|
||||||
|
this.video.muted = this.state.muted;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, 15);
|
}, 15);
|
||||||
|
@ -425,10 +426,11 @@ class Video extends PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
toggleMute = () => {
|
toggleMute = () => {
|
||||||
const muted = !this.video.muted;
|
const muted = !(this.video.muted || this.state.volume === 0);
|
||||||
|
|
||||||
this.setState({ muted }, () => {
|
this.setState((state) => ({ muted, volume: Math.max(state.volume || 0.5, 0.05) }), () => {
|
||||||
this.video.muted = muted;
|
this.video.volume = this.state.volume;
|
||||||
|
this.video.muted = this.state.muted;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -501,8 +503,9 @@ class Video extends PureComponent {
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { preview, src, aspectRatio, onOpenVideo, onCloseVideo, intl, alt, lang, detailed, sensitive, editable, blurhash, autoFocus } = this.props;
|
const { preview, src, aspectRatio, onOpenVideo, onCloseVideo, intl, alt, lang, detailed, sensitive, editable, blurhash, autoFocus } = this.props;
|
||||||
const { currentTime, duration, volume, buffer, dragging, paused, fullscreen, hovered, muted, revealed } = this.state;
|
const { currentTime, duration, volume, buffer, dragging, paused, fullscreen, hovered, revealed } = this.state;
|
||||||
const progress = Math.min((currentTime / duration) * 100, 100);
|
const progress = Math.min((currentTime / duration) * 100, 100);
|
||||||
|
const muted = this.state.muted || volume === 0;
|
||||||
|
|
||||||
let preload;
|
let preload;
|
||||||
|
|
||||||
|
@ -593,12 +596,12 @@ class Video extends PureComponent {
|
||||||
<button type='button' title={intl.formatMessage(muted ? messages.unmute : messages.mute)} aria-label={intl.formatMessage(muted ? messages.unmute : messages.mute)} className='player-button' onClick={this.toggleMute}><Icon id={muted ? 'volume-off' : 'volume-up'} fixedWidth /></button>
|
<button type='button' title={intl.formatMessage(muted ? messages.unmute : messages.mute)} aria-label={intl.formatMessage(muted ? messages.unmute : messages.mute)} className='player-button' onClick={this.toggleMute}><Icon id={muted ? 'volume-off' : 'volume-up'} fixedWidth /></button>
|
||||||
|
|
||||||
<div className={classNames('video-player__volume', { active: this.state.hovered })} onMouseDown={this.handleVolumeMouseDown} ref={this.setVolumeRef}>
|
<div className={classNames('video-player__volume', { active: this.state.hovered })} onMouseDown={this.handleVolumeMouseDown} ref={this.setVolumeRef}>
|
||||||
<div className='video-player__volume__current' style={{ width: `${volume * 100}%` }} />
|
<div className='video-player__volume__current' style={{ width: `${muted ? 0 : volume * 100}%` }} />
|
||||||
|
|
||||||
<span
|
<span
|
||||||
className={classNames('video-player__volume__handle')}
|
className={classNames('video-player__volume__handle')}
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
style={{ left: `${volume * 100}%` }}
|
style={{ left: `${muted ? 0 : volume * 100}%` }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -621,6 +621,7 @@
|
||||||
"searchability.public.short": "Public",
|
"searchability.public.short": "Public",
|
||||||
"searchability.unlisted.long": "Your followers and reactionners can find",
|
"searchability.unlisted.long": "Your followers and reactionners can find",
|
||||||
"searchability.unlisted.short": "Followers and reactionners",
|
"searchability.unlisted.short": "Followers and reactionners",
|
||||||
|
"search_popout.full_text_search_disabled_message": "Not available on {domain}.",
|
||||||
"search_popout.language_code": "ISO language code",
|
"search_popout.language_code": "ISO language code",
|
||||||
"search_popout.options": "Search options",
|
"search_popout.options": "Search options",
|
||||||
"search_popout.quick_actions": "Quick actions",
|
"search_popout.quick_actions": "Quick actions",
|
||||||
|
|
|
@ -14,8 +14,7 @@ import {
|
||||||
SEARCH_SHOW,
|
SEARCH_SHOW,
|
||||||
SEARCH_EXPAND_REQUEST,
|
SEARCH_EXPAND_REQUEST,
|
||||||
SEARCH_EXPAND_SUCCESS,
|
SEARCH_EXPAND_SUCCESS,
|
||||||
SEARCH_RESULT_CLICK,
|
SEARCH_HISTORY_UPDATE,
|
||||||
SEARCH_RESULT_FORGET,
|
|
||||||
} from '../actions/search';
|
} from '../actions/search';
|
||||||
|
|
||||||
const initialState = ImmutableMap({
|
const initialState = ImmutableMap({
|
||||||
|
@ -80,10 +79,8 @@ export default function search(state = initialState, action) {
|
||||||
case SEARCH_EXPAND_SUCCESS:
|
case SEARCH_EXPAND_SUCCESS:
|
||||||
const results = action.searchType === 'hashtags' ? ImmutableOrderedSet(fromJS(action.results.hashtags)) : action.results[action.searchType].map(item => item.id);
|
const results = action.searchType === 'hashtags' ? ImmutableOrderedSet(fromJS(action.results.hashtags)) : action.results[action.searchType].map(item => item.id);
|
||||||
return state.updateIn(['results', action.searchType], list => list.union(results)).setIn(['noMoreResults', action.searchType], results.size <= 0);
|
return state.updateIn(['results', action.searchType], list => list.union(results)).setIn(['noMoreResults', action.searchType], results.size <= 0);
|
||||||
case SEARCH_RESULT_CLICK:
|
case SEARCH_HISTORY_UPDATE:
|
||||||
return state.update('recent', set => set.add(fromJS(action.result)));
|
return state.set('recent', ImmutableOrderedSet(fromJS(action.recent)));
|
||||||
case SEARCH_RESULT_FORGET:
|
|
||||||
return state.update('recent', set => set.filterNot(result => result.get('q') === action.q));
|
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,3 +46,4 @@ export default class Settings {
|
||||||
export const pushNotificationsSetting = new Settings('mastodon_push_notification_data');
|
export const pushNotificationsSetting = new Settings('mastodon_push_notification_data');
|
||||||
export const tagHistory = new Settings('mastodon_tag_history');
|
export const tagHistory = new Settings('mastodon_tag_history');
|
||||||
export const bannerSettings = new Settings('mastodon_banner_settings');
|
export const bannerSettings = new Settings('mastodon_banner_settings');
|
||||||
|
export const searchHistory = new Settings('mastodon_search_history');
|
|
@ -845,7 +845,7 @@ body > [data-popper-placement] {
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 22px;
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
unicode-bidi: plaintext;
|
unicode-bidi: plaintext;
|
||||||
|
|
||||||
|
@ -9236,7 +9236,6 @@ noscript {
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
border: 1px solid $highlight-text-color;
|
border: 1px solid $highlight-text-color;
|
||||||
background: rgba($highlight-text-color, 0.15);
|
background: rgba($highlight-text-color, 0.15);
|
||||||
padding-inline-end: 45px;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
&__background-image {
|
&__background-image {
|
||||||
|
@ -9299,7 +9298,7 @@ noscript {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset-inline-end: 0;
|
inset-inline-end: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
padding: 10px;
|
padding: 15px 10px;
|
||||||
|
|
||||||
.icon-button {
|
.icon-button {
|
||||||
color: $highlight-text-color;
|
color: $highlight-text-color;
|
||||||
|
|
|
@ -65,7 +65,14 @@ class AccountStatusesFilter
|
||||||
end
|
end
|
||||||
|
|
||||||
def filtered_reblogs_scope
|
def filtered_reblogs_scope
|
||||||
Status.left_outer_joins(:reblog).where(reblog_of_id: nil).or(Status.where.not(reblogs_statuses: { account_id: current_account.excluded_from_timeline_account_ids }))
|
scope = Status.left_outer_joins(reblog: :account)
|
||||||
|
scope
|
||||||
|
.where(reblog_of_id: nil)
|
||||||
|
.or(
|
||||||
|
scope
|
||||||
|
.where.not(reblog: { account_id: current_account.excluded_from_timeline_account_ids })
|
||||||
|
.where.not(reblog: { accounts: { domain: current_account.excluded_from_timeline_domains } })
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def only_media_scope
|
def only_media_scope
|
9
app/lib/admin/account_statuses_filter.rb
Normal file
9
app/lib/admin/account_statuses_filter.rb
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Admin::AccountStatusesFilter < AccountStatusesFilter
|
||||||
|
private
|
||||||
|
|
||||||
|
def blocked?
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end
|
|
@ -8,7 +8,7 @@ class SearchQueryParser < Parslet::Parser
|
||||||
rule(:operator) { (str('+') | str('-')).as(:operator) }
|
rule(:operator) { (str('+') | str('-')).as(:operator) }
|
||||||
rule(:prefix) { term >> colon }
|
rule(:prefix) { term >> colon }
|
||||||
rule(:shortcode) { (colon >> term >> colon.maybe).as(:shortcode) }
|
rule(:shortcode) { (colon >> term >> colon.maybe).as(:shortcode) }
|
||||||
rule(:phrase) { (quote >> (term >> space.maybe).repeat >> quote).as(:phrase) }
|
rule(:phrase) { (quote >> (match('[^\s"]').repeat(1).as(:term) >> space.maybe).repeat >> quote).as(:phrase) }
|
||||||
rule(:clause) { (operator.maybe >> prefix.maybe.as(:prefix) >> (phrase | term | shortcode)).as(:clause) | prefix.as(:clause) | quote.as(:junk) }
|
rule(:clause) { (operator.maybe >> prefix.maybe.as(:prefix) >> (phrase | term | shortcode)).as(:clause) | prefix.as(:clause) | quote.as(:junk) }
|
||||||
rule(:query) { (clause >> space.maybe).repeat.as(:query) }
|
rule(:query) { (clause >> space.maybe).repeat.as(:query) }
|
||||||
root(:query)
|
root(:query)
|
||||||
|
|
|
@ -10,6 +10,7 @@ class SearchQueryTransformer < Parslet::Transform
|
||||||
after
|
after
|
||||||
during
|
during
|
||||||
in
|
in
|
||||||
|
domain
|
||||||
).freeze
|
).freeze
|
||||||
|
|
||||||
class Query
|
class Query
|
||||||
|
@ -72,7 +73,7 @@ class SearchQueryTransformer < Parslet::Transform
|
||||||
searchability_limited,
|
searchability_limited,
|
||||||
]
|
]
|
||||||
definition_should << searchability_public if %i(public).include?(@searchability)
|
definition_should << searchability_public if %i(public).include?(@searchability)
|
||||||
definition_should << searchability_private if %i(public private).include?(@searchability)
|
definition_should << searchability_private if %i(public unlisted private).include?(@searchability)
|
||||||
|
|
||||||
{
|
{
|
||||||
bool: {
|
bool: {
|
||||||
|
@ -95,9 +96,7 @@ class SearchQueryTransformer < Parslet::Transform
|
||||||
bool: {
|
bool: {
|
||||||
must: [
|
must: [
|
||||||
{
|
{
|
||||||
term: {
|
term: { _index: StatusesIndex.index_name },
|
||||||
_index: StatusesIndex.index_name,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
term: {
|
term: {
|
||||||
|
@ -117,12 +116,7 @@ class SearchQueryTransformer < Parslet::Transform
|
||||||
term: { _index: StatusesIndex.index_name },
|
term: { _index: StatusesIndex.index_name },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
exists: {
|
term: { searchable_by: @options[:current_account].id },
|
||||||
field: 'searchability',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
term: { searchable_by: @account.id },
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
must_not: [
|
must_not: [
|
||||||
|
@ -139,9 +133,7 @@ class SearchQueryTransformer < Parslet::Transform
|
||||||
bool: {
|
bool: {
|
||||||
must: [
|
must: [
|
||||||
{
|
{
|
||||||
exists: {
|
term: { _index: StatusesIndex.index_name },
|
||||||
field: 'searchability',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
term: { searchability: 'public' },
|
term: { searchability: 'public' },
|
||||||
|
@ -156,9 +148,7 @@ class SearchQueryTransformer < Parslet::Transform
|
||||||
bool: {
|
bool: {
|
||||||
must: [
|
must: [
|
||||||
{
|
{
|
||||||
exists: {
|
term: { _index: StatusesIndex.index_name },
|
||||||
field: 'searchability',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
term: { searchability: 'private' },
|
term: { searchability: 'private' },
|
||||||
|
@ -176,20 +166,27 @@ class SearchQueryTransformer < Parslet::Transform
|
||||||
bool: {
|
bool: {
|
||||||
must: [
|
must: [
|
||||||
{
|
{
|
||||||
exists: {
|
term: { _index: StatusesIndex.index_name },
|
||||||
field: 'searchability',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
term: { searchability: 'limited' },
|
term: { searchability: 'limited' },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
term: { account_id: @account.id },
|
term: { account_id: @options[:current_account].id },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def following_account_ids
|
||||||
|
return @following_account_ids if defined?(@following_account_ids)
|
||||||
|
|
||||||
|
account_exists_sql = Account.where('accounts.id = follows.target_account_id').where(searchability: %w(public private)).reorder(nil).select(1).to_sql
|
||||||
|
status_exists_sql = Status.where('statuses.account_id = follows.target_account_id').where(reblog_of_id: nil).where(searchability: %w(public private)).reorder(nil).select(1).to_sql
|
||||||
|
following_accounts = Follow.where(account_id: @options[:current_account].id).merge(Account.where("EXISTS (#{account_exists_sql})").or(Account.where("EXISTS (#{status_exists_sql})")))
|
||||||
|
@following_account_ids = following_accounts.pluck(:target_account_id)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class Operator
|
class Operator
|
||||||
|
@ -217,7 +214,7 @@ class SearchQueryTransformer < Parslet::Transform
|
||||||
|
|
||||||
def to_query
|
def to_query
|
||||||
if @term.start_with?('#')
|
if @term.start_with?('#')
|
||||||
{ match: { tags: { query: @term } } }
|
{ match: { tags: { query: @term, operator: 'and' } } }
|
||||||
else
|
else
|
||||||
# { multi_match: { type: 'most_fields', query: @term, fields: ['text', 'text.stemmed'], operator: 'and' } }
|
# { multi_match: { type: 'most_fields', query: @term, fields: ['text', 'text.stemmed'], operator: 'and' } }
|
||||||
{ match_phrase: { text: { query: @term } } }
|
{ match_phrase: { text: { query: @term } } }
|
||||||
|
@ -332,17 +329,16 @@ class SearchQueryTransformer < Parslet::Transform
|
||||||
rule(clause: subtree(:clause)) do
|
rule(clause: subtree(:clause)) do
|
||||||
prefix = clause[:prefix][:term].to_s if clause[:prefix]
|
prefix = clause[:prefix][:term].to_s if clause[:prefix]
|
||||||
operator = clause[:operator]&.to_s
|
operator = clause[:operator]&.to_s
|
||||||
|
term = clause[:phrase] ? clause[:phrase].map { |term| term[:term].to_s }.join(' ') : clause[:term].to_s
|
||||||
|
|
||||||
if clause[:prefix] && SUPPORTED_PREFIXES.include?(prefix)
|
if clause[:prefix] && SUPPORTED_PREFIXES.include?(prefix)
|
||||||
PrefixClause.new(prefix, operator, clause[:term].to_s, current_account: current_account)
|
PrefixClause.new(prefix, operator, term, current_account: current_account)
|
||||||
elsif clause[:prefix]
|
elsif clause[:prefix]
|
||||||
TermClause.new(operator, "#{prefix} #{clause[:term]}")
|
TermClause.new(operator, "#{prefix} #{term}")
|
||||||
elsif clause[:term]
|
elsif clause[:term]
|
||||||
TermClause.new(operator, clause[:term].to_s)
|
TermClause.new(operator, term)
|
||||||
elsif clause[:shortcode]
|
|
||||||
TermClause.new(operator, ":#{clause[:term]}:")
|
|
||||||
elsif clause[:phrase]
|
elsif clause[:phrase]
|
||||||
PhraseClause.new(operator, clause[:phrase].is_a?(Array) ? clause[:phrase].map { |p| p[:term].to_s }.join(' ') : clause[:phrase].to_s)
|
PhraseClause.new(operator, term)
|
||||||
else
|
else
|
||||||
raise "Unexpected clause type: #{clause}"
|
raise "Unexpected clause type: #{clause}"
|
||||||
end
|
end
|
||||||
|
|
|
@ -29,7 +29,7 @@ class TagManager
|
||||||
domain = uri.host + (uri.port ? ":#{uri.port}" : '')
|
domain = uri.host + (uri.port ? ":#{uri.port}" : '')
|
||||||
|
|
||||||
TagManager.instance.web_domain?(domain)
|
TagManager.instance.web_domain?(domain)
|
||||||
rescue Addressable::URI::InvalidURIError
|
rescue Addressable::URI::InvalidURIError, IDN::Idna::IdnaError
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -130,10 +130,10 @@ class Account < ApplicationRecord
|
||||||
scope :matches_domain, ->(value) { where(arel_table[:domain].matches("%#{value}%")) }
|
scope :matches_domain, ->(value) { where(arel_table[:domain].matches("%#{value}%")) }
|
||||||
scope :without_unapproved, -> { left_outer_joins(:user).merge(User.approved.confirmed).or(remote) }
|
scope :without_unapproved, -> { left_outer_joins(:user).merge(User.approved.confirmed).or(remote) }
|
||||||
scope :searchable, -> { without_unapproved.without_suspended.where(moved_to_account_id: nil) }
|
scope :searchable, -> { without_unapproved.without_suspended.where(moved_to_account_id: nil) }
|
||||||
scope :discoverable, -> { searchable.without_silenced.where(discoverable: true).left_outer_joins(:account_stat) }
|
scope :discoverable, -> { searchable.without_silenced.where(discoverable: true).joins(:account_stat) }
|
||||||
scope :followable_by, ->(account) { joins(arel_table.join(Follow.arel_table, Arel::Nodes::OuterJoin).on(arel_table[:id].eq(Follow.arel_table[:target_account_id]).and(Follow.arel_table[:account_id].eq(account.id))).join_sources).where(Follow.arel_table[:id].eq(nil)).joins(arel_table.join(FollowRequest.arel_table, Arel::Nodes::OuterJoin).on(arel_table[:id].eq(FollowRequest.arel_table[:target_account_id]).and(FollowRequest.arel_table[:account_id].eq(account.id))).join_sources).where(FollowRequest.arel_table[:id].eq(nil)) }
|
scope :followable_by, ->(account) { joins(arel_table.join(Follow.arel_table, Arel::Nodes::OuterJoin).on(arel_table[:id].eq(Follow.arel_table[:target_account_id]).and(Follow.arel_table[:account_id].eq(account.id))).join_sources).where(Follow.arel_table[:id].eq(nil)).joins(arel_table.join(FollowRequest.arel_table, Arel::Nodes::OuterJoin).on(arel_table[:id].eq(FollowRequest.arel_table[:target_account_id]).and(FollowRequest.arel_table[:account_id].eq(account.id))).join_sources).where(FollowRequest.arel_table[:id].eq(nil)) }
|
||||||
scope :by_recent_status, -> { order(Arel.sql('(case when account_stats.last_status_at is null then 1 else 0 end) asc, account_stats.last_status_at desc, accounts.id desc')) }
|
scope :by_recent_status, -> { order(Arel.sql('account_stats.last_status_at DESC NULLS LAST')) }
|
||||||
scope :by_recent_sign_in, -> { order(Arel.sql('(case when users.current_sign_in_at is null then 1 else 0 end) asc, users.current_sign_in_at desc, accounts.id desc')) }
|
scope :by_recent_sign_in, -> { order(Arel.sql('users.current_sign_in_at DESC NULLS LAST')) }
|
||||||
scope :popular, -> { order('account_stats.followers_count desc') }
|
scope :popular, -> { order('account_stats.followers_count desc') }
|
||||||
scope :by_domain_and_subdomains, ->(domain) { where(domain: Instance.by_domain_and_subdomains(domain).select(:domain)) }
|
scope :by_domain_and_subdomains, ->(domain) { where(domain: Instance.by_domain_and_subdomains(domain).select(:domain)) }
|
||||||
scope :not_excluded_by_account, ->(account) { where.not(id: account.excluded_from_timeline_account_ids) }
|
scope :not_excluded_by_account, ->(account) { where.not(id: account.excluded_from_timeline_account_ids) }
|
||||||
|
|
|
@ -183,6 +183,6 @@ class Admin::StatusBatchAction
|
||||||
end
|
end
|
||||||
|
|
||||||
def allowed_status_ids
|
def allowed_status_ids
|
||||||
AccountStatusesFilter.new(@report.target_account, current_account).results.with_discarded.where(id: status_ids).pluck(:id)
|
Admin::AccountStatusesFilter.new(@report.target_account, current_account).results.with_discarded.where(id: status_ids).pluck(:id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -176,7 +176,7 @@ class MediaAttachment < ApplicationRecord
|
||||||
DEFAULT_STYLES = [:original].freeze
|
DEFAULT_STYLES = [:original].freeze
|
||||||
|
|
||||||
GLOBAL_CONVERT_OPTIONS = {
|
GLOBAL_CONVERT_OPTIONS = {
|
||||||
all: '-quality 90 +profile "!icc,*" +set modify-date +set create-date',
|
all: '-quality 90 +profile "!icc,*" +set modify-date -define jpeg:dct-method=float +set create-date',
|
||||||
}.freeze
|
}.freeze
|
||||||
|
|
||||||
belongs_to :account, inverse_of: :media_attachments, optional: true
|
belongs_to :account, inverse_of: :media_attachments, optional: true
|
||||||
|
|
|
@ -12,7 +12,7 @@ class Admin::StatusPolicy < ApplicationPolicy
|
||||||
end
|
end
|
||||||
|
|
||||||
def show?
|
def show?
|
||||||
role.can?(:manage_reports, :manage_users) && (record.public_visibility? || record.unlisted_visibility? || record.public_unlisted_visibility? || record.reported?)
|
role.can?(:manage_reports, :manage_users) && (record.public_visibility? || record.unlisted_visibility? || record.public_unlisted_visibility? || record.reported? || viewable_through_normal_policy?)
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy?
|
def destroy?
|
||||||
|
@ -26,4 +26,10 @@ class Admin::StatusPolicy < ApplicationPolicy
|
||||||
def review?
|
def review?
|
||||||
role.can?(:manage_taxonomies)
|
role.can?(:manage_taxonomies)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def viewable_through_normal_policy?
|
||||||
|
StatusPolicy.new(current_account, record, @preloaded_relations).show?
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,6 +9,7 @@ class StatusesSearchService < BaseService
|
||||||
@offset = options[:offset].to_i
|
@offset = options[:offset].to_i
|
||||||
@searchability = options[:searchability]&.to_sym
|
@searchability = options[:searchability]&.to_sym
|
||||||
|
|
||||||
|
convert_deprecated_options!
|
||||||
status_search_results
|
status_search_results
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -26,16 +27,28 @@ class StatusesSearchService < BaseService
|
||||||
[]
|
[]
|
||||||
end
|
end
|
||||||
|
|
||||||
def following_account_ids
|
|
||||||
return @following_account_ids if defined?(@following_account_ids)
|
|
||||||
|
|
||||||
account_exists_sql = Account.where('accounts.id = follows.target_account_id').where(searchability: %w(public private)).reorder(nil).select(1).to_sql
|
|
||||||
status_exists_sql = Status.where('statuses.account_id = follows.target_account_id').where(reblog_of_id: nil).where(searchability: %w(public private)).reorder(nil).select(1).to_sql
|
|
||||||
following_accounts = Follow.where(account_id: @account.id).merge(Account.where("EXISTS (#{account_exists_sql})").or(Account.where("EXISTS (#{status_exists_sql})")))
|
|
||||||
@following_account_ids = following_accounts.pluck(:target_account_id)
|
|
||||||
end
|
|
||||||
|
|
||||||
def parsed_query
|
def parsed_query
|
||||||
SearchQueryTransformer.new.apply(SearchQueryParser.new.parse(@query), current_account: @account, searchability: @searchability)
|
SearchQueryTransformer.new.apply(SearchQueryParser.new.parse(@query), current_account: @account, searchability: @searchability)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def convert_deprecated_options!
|
||||||
|
syntax_options = []
|
||||||
|
|
||||||
|
if @options[:account_id]
|
||||||
|
username = Account.select(:username, :domain).find(@options[:account_id]).acct
|
||||||
|
syntax_options << "from:@#{username}"
|
||||||
|
end
|
||||||
|
|
||||||
|
if @options[:min_id]
|
||||||
|
timestamp = Mastodon::Snowflake.to_time(@options[:min_id])
|
||||||
|
syntax_options << "after:\"#{timestamp.iso8601}\""
|
||||||
|
end
|
||||||
|
|
||||||
|
if @options[:max_id]
|
||||||
|
timestamp = Mastodon::Snowflake.to_time(@options[:max_id])
|
||||||
|
syntax_options << "before:\"#{timestamp.iso8601}\""
|
||||||
|
end
|
||||||
|
|
||||||
|
@query = "#{@query} #{syntax_options.join(' ')}".strip if syntax_options.any?
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,7 +10,8 @@
|
||||||
|
|
||||||
%br/
|
%br/
|
||||||
|
|
||||||
= t('admin.trends.tags.used_by_over_week', count: tag.history.reduce(0) { |sum, day| sum + day.accounts })
|
= link_to tag_path(tag), target: '_blank' do
|
||||||
|
= t('admin.trends.tags.used_by_over_week', count: tag.history.reduce(0) { |sum, day| sum + day.accounts })
|
||||||
|
|
||||||
- if tag.trendable? && (rank = Trends.tags.rank(tag.id))
|
- if tag.trendable? && (rank = Trends.tags.rank(tag.id))
|
||||||
·
|
·
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<%= raw t('application_mailer.salutation', name: display_name(@me)) %>
|
<%= raw t('application_mailer.salutation', name: display_name(@me)) %>
|
||||||
|
|
||||||
<%= raw t('admin_mailer.new_appeal.body', target: @appeal.account.username, action_taken_by: @appeal.strike.account.username, date: l(@appeal.strike.created_at), type: t(@appeal.strike.action, scope: 'admin_mailer.new_appeal.actions')) %>
|
<%= raw t('admin_mailer.new_appeal.body', target: @appeal.account.username, action_taken_by: @appeal.strike.account.username, date: l(@appeal.strike.created_at, format: :with_time_zone), type: t(@appeal.strike.action, scope: 'admin_mailer.new_appeal.actions')) %>
|
||||||
|
|
||||||
> <%= raw word_wrap(@appeal.text, break_sequence: "\n> ") %>
|
> <%= raw word_wrap(@appeal.text, break_sequence: "\n> ") %>
|
||||||
|
|
||||||
|
|
|
@ -42,4 +42,4 @@
|
||||||
= link_to a.remote_url, a.remote_url
|
= link_to a.remote_url, a.remote_url
|
||||||
|
|
||||||
%p.status-footer
|
%p.status-footer
|
||||||
= link_to l(status.created_at.in_time_zone(time_zone.presence)), web_url("@#{status.account.pretty_acct}/#{status.id}")
|
= link_to l(status.created_at.in_time_zone(time_zone.presence), format: :with_time_zone), web_url("@#{status.account.pretty_acct}/#{status.id}")
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
%tr
|
||||||
%td.column-cell.text-center
|
%td.column-cell.text-center
|
||||||
%p= t 'user_mailer.appeal_approved.explanation', appeal_date: l(@appeal.created_at.in_time_zone(@resource.time_zone.presence)), strike_date: l(@appeal.strike.created_at.in_time_zone(@resource.time_zone.presence))
|
%p= t 'user_mailer.appeal_approved.explanation', appeal_date: l(@appeal.created_at.in_time_zone(@resource.time_zone.presence), format: :with_time_zone), strike_date: l(@appeal.strike.created_at.in_time_zone(@resource.time_zone.presence), format: :with_time_zone)
|
||||||
|
|
||||||
%table.email-table{ cellspacing: 0, cellpadding: 0 }
|
%table.email-table{ cellspacing: 0, cellpadding: 0 }
|
||||||
%tbody
|
%tbody
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
|
|
||||||
===
|
===
|
||||||
|
|
||||||
<%= t 'user_mailer.appeal_approved.explanation', appeal_date: l(@appeal.created_at.in_time_zone(@resource.time_zone.presence)), strike_date: l(@appeal.strike.created_at.in_time_zone(@resource.time_zone.presence)) %>
|
<%= t 'user_mailer.appeal_approved.explanation', appeal_date: l(@appeal.created_at.in_time_zone(@resource.time_zone.presence), format: :with_time_zone), strike_date: l(@appeal.strike.created_at.in_time_zone(@resource.time_zone.presence), format: :with_time_zone) %>
|
||||||
|
|
||||||
=> <%= root_url %>
|
=> <%= root_url %>
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
%tr
|
||||||
%td.column-cell.text-center
|
%td.column-cell.text-center
|
||||||
%p= t 'user_mailer.appeal_rejected.explanation', appeal_date: l(@appeal.created_at.in_time_zone(@resource.time_zone.presence)), strike_date: l(@appeal.strike.created_at.in_time_zone(@resource.time_zone.presence))
|
%p= t 'user_mailer.appeal_rejected.explanation', appeal_date: l(@appeal.created_at.in_time_zone(@resource.time_zone.presence), format: :with_time_zone), strike_date: l(@appeal.strike.created_at.in_time_zone(@resource.time_zone.presence), format: :with_time_zone)
|
||||||
|
|
||||||
%table.email-table{ cellspacing: 0, cellpadding: 0 }
|
%table.email-table{ cellspacing: 0, cellpadding: 0 }
|
||||||
%tbody
|
%tbody
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
|
|
||||||
===
|
===
|
||||||
|
|
||||||
<%= t 'user_mailer.appeal_rejected.explanation', appeal_date: l(@appeal.created_at.in_time_zone(@resource.time_zone.presence)), strike_date: l(@appeal.strike.created_at.in_time_zone(@resource.time_zone.presence)) %>
|
<%= t 'user_mailer.appeal_rejected.explanation', appeal_date: l(@appeal.created_at.in_time_zone(@resource.time_zone.presence), format: :with_time_zone), strike_date: l(@appeal.strike.created_at.in_time_zone(@resource.time_zone.presence), format: :with_time_zone) %>
|
||||||
|
|
||||||
=> <%= root_url %>
|
=> <%= root_url %>
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
%strong= "#{t('sessions.browser')}:"
|
%strong= "#{t('sessions.browser')}:"
|
||||||
%span{ title: @user_agent }= t 'sessions.description', browser: t("sessions.browsers.#{@detection.id}", default: @detection.id.to_s), platform: t("sessions.platforms.#{@detection.platform.id}", default: @detection.platform.id.to_s)
|
%span{ title: @user_agent }= t 'sessions.description', browser: t("sessions.browsers.#{@detection.id}", default: @detection.id.to_s), platform: t("sessions.platforms.#{@detection.platform.id}", default: @detection.platform.id.to_s)
|
||||||
%br/
|
%br/
|
||||||
= l(@timestamp.in_time_zone(@resource.time_zone.presence))
|
= l(@timestamp.in_time_zone(@resource.time_zone.presence), format: :with_time_zone)
|
||||||
|
|
||||||
%table.email-table{ cellspacing: 0, cellpadding: 0 }
|
%table.email-table{ cellspacing: 0, cellpadding: 0 }
|
||||||
%tbody
|
%tbody
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
<%= t('sessions.ip') %>: <%= @remote_ip %>
|
<%= t('sessions.ip') %>: <%= @remote_ip %>
|
||||||
<%= t('sessions.browser') %>: <%= t('sessions.description', browser: t("sessions.browsers.#{@detection.id}", default: "#{@detection.id}"), platform: t("sessions.platforms.#{@detection.platform.id}", default: "#{@detection.platform.id}")) %>
|
<%= t('sessions.browser') %>: <%= t('sessions.description', browser: t("sessions.browsers.#{@detection.id}", default: "#{@detection.id}"), platform: t("sessions.platforms.#{@detection.platform.id}", default: "#{@detection.platform.id}")) %>
|
||||||
<%= l(@timestamp.in_time_zone(@resource.time_zone.presence)) %>
|
<%= l(@timestamp.in_time_zone(@resource.time_zone.presence), format: :with_time_zone) %>
|
||||||
|
|
||||||
<%= t 'user_mailer.suspicious_sign_in.further_actions_html', action: t('user_mailer.suspicious_sign_in.change_password') %>
|
<%= t 'user_mailer.suspicious_sign_in.further_actions_html', action: t('user_mailer.suspicious_sign_in.change_password') %>
|
||||||
|
|
||||||
|
|
|
@ -1888,6 +1888,7 @@ en:
|
||||||
default: "%b %d, %Y, %H:%M"
|
default: "%b %d, %Y, %H:%M"
|
||||||
month: "%b %Y"
|
month: "%b %Y"
|
||||||
time: "%H:%M"
|
time: "%H:%M"
|
||||||
|
with_time_zone: "%b %d, %Y, %H:%M %Z"
|
||||||
translation:
|
translation:
|
||||||
errors:
|
errors:
|
||||||
quota_exceeded: The server-wide usage quota for the translation service has been exceeded.
|
quota_exceeded: The server-wide usage quota for the translation service has been exceeded.
|
||||||
|
|
|
@ -4,7 +4,7 @@ const { createHash } = require('crypto');
|
||||||
const { readFileSync } = require('fs');
|
const { readFileSync } = require('fs');
|
||||||
const { resolve } = require('path');
|
const { resolve } = require('path');
|
||||||
|
|
||||||
const CompressionPlugin = require('compression-webpack-plugin');
|
const CompressionPlugin = require('@renchap/compression-webpack-plugin');
|
||||||
const TerserPlugin = require('terser-webpack-plugin');
|
const TerserPlugin = require('terser-webpack-plugin');
|
||||||
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
|
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
|
||||||
const { merge } = require('webpack-merge');
|
const { merge } = require('webpack-merge');
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class AddIndexAccountStatsOnLastStatusAtAndAccountId < ActiveRecord::Migration[7.0]
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
def change
|
||||||
|
add_index :account_stats, [:last_status_at, :account_id], order: { last_status_at: 'DESC NULLS LAST' }, algorithm: :concurrently
|
||||||
|
end
|
||||||
|
end
|
|
@ -10,7 +10,7 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema[7.0].define(version: 2023_09_04_134623) do
|
ActiveRecord::Schema[7.0].define(version: 2023_09_07_150100) do
|
||||||
# These are extensions that must be enabled in order to support this database
|
# These are extensions that must be enabled in order to support this database
|
||||||
enable_extension "plpgsql"
|
enable_extension "plpgsql"
|
||||||
|
|
||||||
|
@ -100,6 +100,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_09_04_134623) do
|
||||||
t.datetime "last_status_at", precision: nil
|
t.datetime "last_status_at", precision: nil
|
||||||
t.integer "group_activitypub_count"
|
t.integer "group_activitypub_count"
|
||||||
t.index ["account_id"], name: "index_account_stats_on_account_id", unique: true
|
t.index ["account_id"], name: "index_account_stats_on_account_id", unique: true
|
||||||
|
t.index ["last_status_at", "account_id"], name: "index_account_stats_on_last_status_at_and_account_id", order: { last_status_at: "DESC NULLS LAST" }
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "account_statuses_cleanup_policies", force: :cascade do |t|
|
create_table "account_statuses_cleanup_policies", force: :cascade do |t|
|
||||||
|
|
|
@ -16,7 +16,7 @@ class Mastodon::SidekiqMiddleware
|
||||||
private
|
private
|
||||||
|
|
||||||
def limit_backtrace_and_raise(exception)
|
def limit_backtrace_and_raise(exception)
|
||||||
exception.set_backtrace(exception.backtrace.first(BACKTRACE_LIMIT))
|
exception.set_backtrace(exception.backtrace.first(BACKTRACE_LIMIT)) unless ENV['BACKTRACE']
|
||||||
raise exception
|
raise exception
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -104,6 +104,10 @@ module Mastodon::Snowflake
|
||||||
id
|
id
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_time(id)
|
||||||
|
Time.at((id >> 16) / 1000).utc
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def already_defined?
|
def already_defined?
|
||||||
|
|
|
@ -9,3 +9,13 @@ if Rake::Task.task_defined?('spec:system')
|
||||||
|
|
||||||
Rake::Task['spec:system'].enhance ['spec:enable_system_specs']
|
Rake::Task['spec:system'].enhance ['spec:enable_system_specs']
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if Rake::Task.task_defined?('spec:search')
|
||||||
|
namespace :spec do
|
||||||
|
task :enable_search_specs do # rubocop:disable Rails/RakeEnvironment
|
||||||
|
ENV['RUN_SEARCH_SPECS'] = 'true'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Rake::Task['spec:search'].enhance ['spec:enable_search_specs']
|
||||||
|
end
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
"@material-design-icons/svg": "^0.14.10",
|
"@material-design-icons/svg": "^0.14.10",
|
||||||
"@rails/ujs": "^7.0.6",
|
"@rails/ujs": "^7.0.6",
|
||||||
"@reduxjs/toolkit": "^1.9.5",
|
"@reduxjs/toolkit": "^1.9.5",
|
||||||
|
"@renchap/compression-webpack-plugin": "^6.1.4",
|
||||||
"@svgr/webpack": "^5.5.0",
|
"@svgr/webpack": "^5.5.0",
|
||||||
"abortcontroller-polyfill": "^1.7.5",
|
"abortcontroller-polyfill": "^1.7.5",
|
||||||
"arrow-key-navigation": "^1.2.0",
|
"arrow-key-navigation": "^1.2.0",
|
||||||
|
@ -63,7 +64,6 @@
|
||||||
"classnames": "^2.3.2",
|
"classnames": "^2.3.2",
|
||||||
"cocoon-js-vanilla": "^1.3.0",
|
"cocoon-js-vanilla": "^1.3.0",
|
||||||
"color-blend": "^4.0.0",
|
"color-blend": "^4.0.0",
|
||||||
"compression-webpack-plugin": "^6.1.1",
|
|
||||||
"core-js": "^3.30.2",
|
"core-js": "^3.30.2",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"css-loader": "^5.2.7",
|
"css-loader": "^5.2.7",
|
||||||
|
@ -137,7 +137,7 @@
|
||||||
"tiny-queue": "^0.2.1",
|
"tiny-queue": "^0.2.1",
|
||||||
"twitter-text": "3.1.0",
|
"twitter-text": "3.1.0",
|
||||||
"uuid": "^9.0.0",
|
"uuid": "^9.0.0",
|
||||||
"webpack": "^4.46.0",
|
"webpack": "^4.47.0",
|
||||||
"webpack-assets-manifest": "^4.0.6",
|
"webpack-assets-manifest": "^4.0.6",
|
||||||
"webpack-bundle-analyzer": "^4.8.0",
|
"webpack-bundle-analyzer": "^4.8.0",
|
||||||
"webpack-cli": "^3.3.12",
|
"webpack-cli": "^3.3.12",
|
||||||
|
|
|
@ -52,24 +52,36 @@ describe Admin::StatusesController do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'POST #batch' do
|
describe 'POST #batch' do
|
||||||
before do
|
subject { post :batch, params: { :account_id => account.id, action => '', :admin_status_batch_action => { status_ids: status_ids } } }
|
||||||
post :batch, params: { :account_id => account.id, action => '', :admin_status_batch_action => { status_ids: status_ids } }
|
|
||||||
end
|
|
||||||
|
|
||||||
let(:status_ids) { [media_attached_status.id] }
|
let(:status_ids) { [media_attached_status.id] }
|
||||||
|
|
||||||
context 'when action is report' do
|
shared_examples 'when action is report' do
|
||||||
let(:action) { 'report' }
|
let(:action) { 'report' }
|
||||||
|
|
||||||
it 'creates a report' do
|
it 'creates a report' do
|
||||||
|
subject
|
||||||
|
|
||||||
report = Report.last
|
report = Report.last
|
||||||
expect(report.target_account_id).to eq account.id
|
expect(report.target_account_id).to eq account.id
|
||||||
expect(report.status_ids).to eq status_ids
|
expect(report.status_ids).to eq status_ids
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'redirects to report page' do
|
it 'redirects to report page' do
|
||||||
|
subject
|
||||||
|
|
||||||
expect(response).to redirect_to(admin_report_path(Report.last.id))
|
expect(response).to redirect_to(admin_report_path(Report.last.id))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'when action is report'
|
||||||
|
|
||||||
|
context 'when the moderator is blocked by the author' do
|
||||||
|
before do
|
||||||
|
account.block!(user.account)
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'when action is report'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -15,12 +15,13 @@ describe Api::V1::DirectoriesController do
|
||||||
describe 'GET #show' do
|
describe 'GET #show' do
|
||||||
context 'with no params' do
|
context 'with no params' do
|
||||||
before do
|
before do
|
||||||
_local_unconfirmed_account = Fabricate(
|
local_unconfirmed_account = Fabricate(
|
||||||
:account,
|
:account,
|
||||||
domain: nil,
|
domain: nil,
|
||||||
user: Fabricate(:user, confirmed_at: nil, approved: true),
|
user: Fabricate(:user, confirmed_at: nil, approved: true),
|
||||||
username: 'local_unconfirmed'
|
username: 'local_unconfirmed'
|
||||||
)
|
)
|
||||||
|
local_unconfirmed_account.create_account_stat!
|
||||||
|
|
||||||
local_unapproved_account = Fabricate(
|
local_unapproved_account = Fabricate(
|
||||||
:account,
|
:account,
|
||||||
|
@ -28,15 +29,17 @@ describe Api::V1::DirectoriesController do
|
||||||
user: Fabricate(:user, confirmed_at: 10.days.ago),
|
user: Fabricate(:user, confirmed_at: 10.days.ago),
|
||||||
username: 'local_unapproved'
|
username: 'local_unapproved'
|
||||||
)
|
)
|
||||||
|
local_unapproved_account.create_account_stat!
|
||||||
local_unapproved_account.user.update(approved: false)
|
local_unapproved_account.user.update(approved: false)
|
||||||
|
|
||||||
_local_undiscoverable_account = Fabricate(
|
local_undiscoverable_account = Fabricate(
|
||||||
:account,
|
:account,
|
||||||
domain: nil,
|
domain: nil,
|
||||||
user: Fabricate(:user, confirmed_at: 10.days.ago, approved: true),
|
user: Fabricate(:user, confirmed_at: 10.days.ago, approved: true),
|
||||||
discoverable: false,
|
discoverable: false,
|
||||||
username: 'local_undiscoverable'
|
username: 'local_undiscoverable'
|
||||||
)
|
)
|
||||||
|
local_undiscoverable_account.create_account_stat!
|
||||||
|
|
||||||
excluded_from_timeline_account = Fabricate(
|
excluded_from_timeline_account = Fabricate(
|
||||||
:account,
|
:account,
|
||||||
|
@ -44,18 +47,20 @@ describe Api::V1::DirectoriesController do
|
||||||
discoverable: true,
|
discoverable: true,
|
||||||
username: 'remote_excluded_from_timeline'
|
username: 'remote_excluded_from_timeline'
|
||||||
)
|
)
|
||||||
|
excluded_from_timeline_account.create_account_stat!
|
||||||
Fabricate(:block, account: user.account, target_account: excluded_from_timeline_account)
|
Fabricate(:block, account: user.account, target_account: excluded_from_timeline_account)
|
||||||
|
|
||||||
_domain_blocked_account = Fabricate(
|
domain_blocked_account = Fabricate(
|
||||||
:account,
|
:account,
|
||||||
domain: 'test.example',
|
domain: 'test.example',
|
||||||
discoverable: true,
|
discoverable: true,
|
||||||
username: 'remote_domain_blocked'
|
username: 'remote_domain_blocked'
|
||||||
)
|
)
|
||||||
|
domain_blocked_account.create_account_stat!
|
||||||
Fabricate(:account_domain_block, account: user.account, domain: 'test.example')
|
Fabricate(:account_domain_block, account: user.account, domain: 'test.example')
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns only the local discoverable account' do
|
it 'returns the local discoverable account and the remote discoverable account' do
|
||||||
local_discoverable_account = Fabricate(
|
local_discoverable_account = Fabricate(
|
||||||
:account,
|
:account,
|
||||||
domain: nil,
|
domain: nil,
|
||||||
|
@ -63,6 +68,7 @@ describe Api::V1::DirectoriesController do
|
||||||
discoverable: true,
|
discoverable: true,
|
||||||
username: 'local_discoverable'
|
username: 'local_discoverable'
|
||||||
)
|
)
|
||||||
|
local_discoverable_account.create_account_stat!
|
||||||
|
|
||||||
eligible_remote_account = Fabricate(
|
eligible_remote_account = Fabricate(
|
||||||
:account,
|
:account,
|
||||||
|
@ -70,13 +76,13 @@ describe Api::V1::DirectoriesController do
|
||||||
discoverable: true,
|
discoverable: true,
|
||||||
username: 'eligible_remote'
|
username: 'eligible_remote'
|
||||||
)
|
)
|
||||||
|
eligible_remote_account.create_account_stat!
|
||||||
|
|
||||||
get :show
|
get :show
|
||||||
|
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
expect(body_as_json.size).to eq(2)
|
expect(body_as_json.size).to eq(2)
|
||||||
expect(body_as_json.first[:id]).to include(eligible_remote_account.id.to_s)
|
expect(body_as_json.pluck(:id)).to contain_exactly(eligible_remote_account.id.to_s, local_discoverable_account.id.to_s)
|
||||||
expect(body_as_json.second[:id]).to include(local_discoverable_account.id.to_s)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -85,6 +91,8 @@ describe Api::V1::DirectoriesController do
|
||||||
user = Fabricate(:user, confirmed_at: 10.days.ago, approved: true)
|
user = Fabricate(:user, confirmed_at: 10.days.ago, approved: true)
|
||||||
local_account = Fabricate(:account, domain: nil, user: user)
|
local_account = Fabricate(:account, domain: nil, user: user)
|
||||||
remote_account = Fabricate(:account, domain: 'host.example')
|
remote_account = Fabricate(:account, domain: 'host.example')
|
||||||
|
local_account.create_account_stat!
|
||||||
|
remote_account.create_account_stat!
|
||||||
|
|
||||||
get :show, params: { local: '1' }
|
get :show, params: { local: '1' }
|
||||||
|
|
||||||
|
@ -97,24 +105,23 @@ describe Api::V1::DirectoriesController do
|
||||||
|
|
||||||
context 'when ordered by active' do
|
context 'when ordered by active' do
|
||||||
it 'returns accounts in order of most recent status activity' do
|
it 'returns accounts in order of most recent status activity' do
|
||||||
status_old = Fabricate(:status)
|
old_stat = Fabricate(:account_stat, last_status_at: 1.day.ago)
|
||||||
travel_to 10.seconds.from_now
|
new_stat = Fabricate(:account_stat, last_status_at: 1.minute.ago)
|
||||||
status_new = Fabricate(:status)
|
|
||||||
|
|
||||||
get :show, params: { order: 'active' }
|
get :show, params: { order: 'active' }
|
||||||
|
|
||||||
expect(response).to have_http_status(200)
|
expect(response).to have_http_status(200)
|
||||||
expect(body_as_json.size).to eq(2)
|
expect(body_as_json.size).to eq(2)
|
||||||
expect(body_as_json.first[:id]).to include(status_new.account.id.to_s)
|
expect(body_as_json.first[:id]).to include(new_stat.account_id.to_s)
|
||||||
expect(body_as_json.second[:id]).to include(status_old.account.id.to_s)
|
expect(body_as_json.second[:id]).to include(old_stat.account_id.to_s)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when ordered by new' do
|
context 'when ordered by new' do
|
||||||
it 'returns accounts in order of creation' do
|
it 'returns accounts in order of creation' do
|
||||||
account_old = Fabricate(:account)
|
account_old = Fabricate(:account_stat).account
|
||||||
travel_to 10.seconds.from_now
|
travel_to 10.seconds.from_now
|
||||||
account_new = Fabricate(:account)
|
account_new = Fabricate(:account_stat).account
|
||||||
|
|
||||||
get :show, params: { order: 'new' }
|
get :show, params: { order: 'new' }
|
||||||
|
|
||||||
|
|
|
@ -57,4 +57,24 @@ describe SearchQueryTransformer do
|
||||||
expect(subject.send(:filter_clauses)).to be_empty
|
expect(subject.send(:filter_clauses)).to be_empty
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'with \'"hello world"\'' do
|
||||||
|
let(:query) { '"hello world"' }
|
||||||
|
|
||||||
|
it 'transforms clauses' do
|
||||||
|
expect(subject.send(:must_clauses).map(&:phrase)).to contain_exactly('hello world')
|
||||||
|
expect(subject.send(:must_not_clauses)).to be_empty
|
||||||
|
expect(subject.send(:filter_clauses)).to be_empty
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with \'before:"2022-01-01 23:00"\'' do
|
||||||
|
let(:query) { 'before:"2022-01-01 23:00"' }
|
||||||
|
|
||||||
|
it 'transforms clauses' do
|
||||||
|
expect(subject.send(:must_clauses)).to be_empty
|
||||||
|
expect(subject.send(:must_not_clauses)).to be_empty
|
||||||
|
expect(subject.send(:filter_clauses).map(&:term)).to contain_exactly(lt: '2022-01-01 23:00', time_zone: 'UTC')
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -228,6 +228,20 @@ RSpec.describe AccountStatusesFilter do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when blocking a reblogged domain' do
|
||||||
|
let(:other_account) { Fabricate(:account, domain: 'example.com') }
|
||||||
|
let(:reblogging_status) { Fabricate(:status, account: other_account) }
|
||||||
|
let(:reblog) { Fabricate(:status, account: account, visibility: 'public', reblog: reblogging_status) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
current_account.block_domain!(other_account.domain)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not return reblog of blocked domain' do
|
||||||
|
expect(subject.results.pluck(:id)).to_not include(reblog.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context 'when muting a reblogged account' do
|
context 'when muting a reblogged account' do
|
||||||
let(:reblog) { status_with_reblog!('public') }
|
let(:reblog) { status_with_reblog!('public') }
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,8 @@ describe Admin::StatusPolicy do
|
||||||
let(:policy) { described_class }
|
let(:policy) { described_class }
|
||||||
let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account }
|
let(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account }
|
||||||
let(:john) { Fabricate(:account) }
|
let(:john) { Fabricate(:account) }
|
||||||
let(:status) { Fabricate(:status) }
|
let(:status) { Fabricate(:status, visibility: status_visibility) }
|
||||||
|
let(:status_visibility) { :public }
|
||||||
|
|
||||||
permissions :index?, :update?, :review?, :destroy? do
|
permissions :index?, :update?, :review?, :destroy? do
|
||||||
context 'with an admin' do
|
context 'with an admin' do
|
||||||
|
@ -26,7 +27,7 @@ describe Admin::StatusPolicy do
|
||||||
permissions :show? do
|
permissions :show? do
|
||||||
context 'with an admin' do
|
context 'with an admin' do
|
||||||
context 'with a public visible status' do
|
context 'with a public visible status' do
|
||||||
before { allow(status).to receive(:public_visibility?).and_return(true) }
|
let(:status_visibility) { :public }
|
||||||
|
|
||||||
it 'permits' do
|
it 'permits' do
|
||||||
expect(policy).to permit(admin, status)
|
expect(policy).to permit(admin, status)
|
||||||
|
@ -34,11 +35,21 @@ describe Admin::StatusPolicy do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with a not public visible status' do
|
context 'with a not public visible status' do
|
||||||
before { allow(status).to receive(:public_visibility?).and_return(false) }
|
let(:status_visibility) { :direct }
|
||||||
|
|
||||||
it 'denies' do
|
it 'denies' do
|
||||||
expect(policy).to_not permit(admin, status)
|
expect(policy).to_not permit(admin, status)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when the status mentions the admin' do
|
||||||
|
before do
|
||||||
|
status.mentions.create!(account: admin)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'permits' do
|
||||||
|
expect(policy).to permit(admin, status)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -4,11 +4,17 @@ ENV['RAILS_ENV'] ||= 'test'
|
||||||
|
|
||||||
# This needs to be defined before Rails is initialized
|
# This needs to be defined before Rails is initialized
|
||||||
RUN_SYSTEM_SPECS = ENV.fetch('RUN_SYSTEM_SPECS', false)
|
RUN_SYSTEM_SPECS = ENV.fetch('RUN_SYSTEM_SPECS', false)
|
||||||
|
RUN_SEARCH_SPECS = ENV.fetch('RUN_SEARCH_SPECS', false)
|
||||||
|
|
||||||
if RUN_SYSTEM_SPECS
|
if RUN_SYSTEM_SPECS
|
||||||
STREAMING_PORT = ENV.fetch('TEST_STREAMING_PORT', '4020')
|
STREAMING_PORT = ENV.fetch('TEST_STREAMING_PORT', '4020')
|
||||||
ENV['STREAMING_API_BASE_URL'] = "http://localhost:#{STREAMING_PORT}"
|
ENV['STREAMING_API_BASE_URL'] = "http://localhost:#{STREAMING_PORT}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if RUN_SEARCH_SPECS
|
||||||
|
# Include any configuration or setups specific to search tests here
|
||||||
|
end
|
||||||
|
|
||||||
require File.expand_path('../config/environment', __dir__)
|
require File.expand_path('../config/environment', __dir__)
|
||||||
|
|
||||||
abort('The Rails environment is running in production mode!') if Rails.env.production?
|
abort('The Rails environment is running in production mode!') if Rails.env.production?
|
||||||
|
@ -30,6 +36,7 @@ Sidekiq.logger = nil
|
||||||
# System tests config
|
# System tests config
|
||||||
DatabaseCleaner.strategy = [:deletion]
|
DatabaseCleaner.strategy = [:deletion]
|
||||||
streaming_server_manager = StreamingServerManager.new
|
streaming_server_manager = StreamingServerManager.new
|
||||||
|
search_data_manager = SearchDataManager.new
|
||||||
|
|
||||||
Devise::Test::ControllerHelpers.module_eval do
|
Devise::Test::ControllerHelpers.module_eval do
|
||||||
alias_method :original_sign_in, :sign_in
|
alias_method :original_sign_in, :sign_in
|
||||||
|
@ -69,7 +76,14 @@ end
|
||||||
|
|
||||||
RSpec.configure do |config|
|
RSpec.configure do |config|
|
||||||
# This is set before running spec:system, see lib/tasks/tests.rake
|
# This is set before running spec:system, see lib/tasks/tests.rake
|
||||||
config.filter_run_excluding type: :system unless RUN_SYSTEM_SPECS
|
config.filter_run_excluding type: lambda { |type|
|
||||||
|
case type
|
||||||
|
when :system
|
||||||
|
!RUN_SYSTEM_SPECS
|
||||||
|
when :search
|
||||||
|
!RUN_SEARCH_SPECS
|
||||||
|
end
|
||||||
|
}
|
||||||
config.fixture_path = Rails.root.join('spec', 'fixtures')
|
config.fixture_path = Rails.root.join('spec', 'fixtures')
|
||||||
config.use_transactional_fixtures = true
|
config.use_transactional_fixtures = true
|
||||||
config.order = 'random'
|
config.order = 'random'
|
||||||
|
@ -113,10 +127,17 @@ RSpec.configure do |config|
|
||||||
Webpacker.compile
|
Webpacker.compile
|
||||||
streaming_server_manager.start(port: STREAMING_PORT)
|
streaming_server_manager.start(port: STREAMING_PORT)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if RUN_SEARCH_SPECS
|
||||||
|
Chewy.strategy(:urgent)
|
||||||
|
search_data_manager.prepare_test_data
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
config.after :suite do
|
config.after :suite do
|
||||||
streaming_server_manager.stop
|
streaming_server_manager.stop
|
||||||
|
|
||||||
|
search_data_manager.cleanup_test_data if RUN_SEARCH_SPECS
|
||||||
end
|
end
|
||||||
|
|
||||||
config.around :each, type: :system do |example|
|
config.around :each, type: :system do |example|
|
||||||
|
@ -137,6 +158,12 @@ RSpec.configure do |config|
|
||||||
self.use_transactional_tests = true
|
self.use_transactional_tests = true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
config.around :each, type: :search do |example|
|
||||||
|
search_data_manager.populate_indexes
|
||||||
|
example.run
|
||||||
|
search_data_manager.remove_indexes
|
||||||
|
end
|
||||||
|
|
||||||
config.before(:each) do |example|
|
config.before(:each) do |example|
|
||||||
unless example.metadata[:paperclip_processing]
|
unless example.metadata[:paperclip_processing]
|
||||||
allow_any_instance_of(Paperclip::Attachment).to receive(:post_process).and_return(true) # rubocop:disable RSpec/AnyInstance
|
allow_any_instance_of(Paperclip::Attachment).to receive(:post_process).and_return(true) # rubocop:disable RSpec/AnyInstance
|
||||||
|
|
51
spec/search/models/concerns/account_search_spec.rb
Normal file
51
spec/search/models/concerns/account_search_spec.rb
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
describe AccountSearch do
|
||||||
|
describe 'a non-discoverable account becoming discoverable' do
|
||||||
|
let(:account) { Account.find_by(username: 'search_test_account_1') }
|
||||||
|
|
||||||
|
context 'when picking a non-discoverable account' do
|
||||||
|
it 'its bio is not in the AccountsIndex' do
|
||||||
|
results = AccountsIndex.filter(term: { username: account.username })
|
||||||
|
expect(results.count).to eq(1)
|
||||||
|
expect(results.first.text).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the non-discoverable account becomes discoverable' do
|
||||||
|
it 'its bio is added to the AccountsIndex' do
|
||||||
|
account.discoverable = true
|
||||||
|
account.save!
|
||||||
|
|
||||||
|
results = AccountsIndex.filter(term: { username: account.username })
|
||||||
|
expect(results.count).to eq(1)
|
||||||
|
expect(results.first.text).to eq(account.note)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'a discoverable account becoming non-discoverable' do
|
||||||
|
let(:account) { Account.find_by(username: 'search_test_account_0') }
|
||||||
|
|
||||||
|
context 'when picking an discoverable account' do
|
||||||
|
it 'has its bio in the AccountsIndex' do
|
||||||
|
results = AccountsIndex.filter(term: { username: account.username })
|
||||||
|
expect(results.count).to eq(1)
|
||||||
|
expect(results.first.text).to eq(account.note)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the discoverable account becomes non-discoverable' do
|
||||||
|
it 'its bio is removed from the AccountsIndex' do
|
||||||
|
account.discoverable = false
|
||||||
|
account.save!
|
||||||
|
|
||||||
|
results = AccountsIndex.filter(term: { username: account.username })
|
||||||
|
expect(results.count).to eq(1)
|
||||||
|
expect(results.first.text).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
53
spec/search/models/concerns/account_statuses_search_spec.rb
Normal file
53
spec/search/models/concerns/account_statuses_search_spec.rb
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
describe AccountStatusesSearch do
|
||||||
|
describe 'a non-indexable account becoming indexable' do
|
||||||
|
let(:account) { Account.find_by(username: 'search_test_account_1') }
|
||||||
|
|
||||||
|
context 'when picking a non-indexable account' do
|
||||||
|
it 'has no statuses in the PublicStatusesIndex' do
|
||||||
|
expect(PublicStatusesIndex.filter(term: { account_id: account.id }).count).to eq(0)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'has statuses in the StatusesIndex' do
|
||||||
|
expect(StatusesIndex.filter(term: { account_id: account.id }).count).to eq(account.statuses.count)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the non-indexable account becomes indexable' do
|
||||||
|
it 'adds the public statuses to the PublicStatusesIndex' do
|
||||||
|
account.indexable = true
|
||||||
|
account.save!
|
||||||
|
|
||||||
|
expect(PublicStatusesIndex.filter(term: { account_id: account.id }).count).to eq(account.statuses.where(visibility: :public).count)
|
||||||
|
expect(StatusesIndex.filter(term: { account_id: account.id }).count).to eq(account.statuses.count)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'an indexable account becoming non-indexable' do
|
||||||
|
let(:account) { Account.find_by(username: 'search_test_account_0') }
|
||||||
|
|
||||||
|
context 'when picking an indexable account' do
|
||||||
|
it 'has statuses in the PublicStatusesIndex' do
|
||||||
|
expect(PublicStatusesIndex.filter(term: { account_id: account.id }).count).to eq(account.statuses.where(visibility: :public).count)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'has statuses in the StatusesIndex' do
|
||||||
|
expect(StatusesIndex.filter(term: { account_id: account.id }).count).to eq(account.statuses.count)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the indexable account becomes non-indexable' do
|
||||||
|
it 'removes the statuses from the PublicStatusesIndex' do
|
||||||
|
account.indexable = false
|
||||||
|
account.save!
|
||||||
|
|
||||||
|
expect(PublicStatusesIndex.filter(term: { account_id: account.id }).count).to eq(0)
|
||||||
|
expect(StatusesIndex.filter(term: { account_id: account.id }).count).to eq(account.statuses.count)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -135,3 +135,45 @@ class StreamingServerManager
|
||||||
@running_thread.join
|
@running_thread.join
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class SearchDataManager
|
||||||
|
def prepare_test_data
|
||||||
|
4.times do |i|
|
||||||
|
username = "search_test_account_#{i}"
|
||||||
|
account = Fabricate.create(:account, username: username, indexable: i.even?, discoverable: i.even?, note: "Lover of #{i}.")
|
||||||
|
2.times do |j|
|
||||||
|
Fabricate.create(:status, account: account, text: "#{username}'s #{j} post", visibility: j.even? ? :public : :private)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
3.times do |i|
|
||||||
|
Fabricate.create(:tag, name: "search_test_tag_#{i}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def indexes
|
||||||
|
[
|
||||||
|
AccountsIndex,
|
||||||
|
PublicStatusesIndex,
|
||||||
|
StatusesIndex,
|
||||||
|
TagsIndex,
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
def populate_indexes
|
||||||
|
indexes.each do |index_class|
|
||||||
|
index_class.purge!
|
||||||
|
index_class.import!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def remove_indexes
|
||||||
|
indexes.each(&:delete!)
|
||||||
|
end
|
||||||
|
|
||||||
|
def cleanup_test_data
|
||||||
|
Status.destroy_all
|
||||||
|
Account.destroy_all
|
||||||
|
Tag.destroy_all
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
307
yarn.lock
307
yarn.lock
|
@ -88,7 +88,7 @@
|
||||||
"@jridgewell/trace-mapping" "^0.3.17"
|
"@jridgewell/trace-mapping" "^0.3.17"
|
||||||
jsesc "^2.5.1"
|
jsesc "^2.5.1"
|
||||||
|
|
||||||
"@babel/generator@^7.22.5", "@babel/generator@^7.7.2":
|
"@babel/generator@^7.7.2":
|
||||||
version "7.22.10"
|
version "7.22.10"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.10.tgz#c92254361f398e160645ac58831069707382b722"
|
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.10.tgz#c92254361f398e160645ac58831069707382b722"
|
||||||
integrity sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==
|
integrity sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==
|
||||||
|
@ -262,7 +262,7 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/types" "^7.22.5"
|
"@babel/types" "^7.22.5"
|
||||||
|
|
||||||
"@babel/helper-split-export-declaration@^7.22.5", "@babel/helper-split-export-declaration@^7.22.6":
|
"@babel/helper-split-export-declaration@^7.22.6":
|
||||||
version "7.22.6"
|
version "7.22.6"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c"
|
resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c"
|
||||||
integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==
|
integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==
|
||||||
|
@ -320,16 +320,16 @@
|
||||||
chalk "^2.4.2"
|
chalk "^2.4.2"
|
||||||
js-tokens "^4.0.0"
|
js-tokens "^4.0.0"
|
||||||
|
|
||||||
"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7":
|
"@babel/parser@^7.1.0", "@babel/parser@^7.20.7", "@babel/parser@^7.22.15", "@babel/parser@^7.22.5":
|
||||||
|
version "7.22.16"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.16.tgz#180aead7f247305cce6551bea2720934e2fa2c95"
|
||||||
|
integrity sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==
|
||||||
|
|
||||||
|
"@babel/parser@^7.14.7":
|
||||||
version "7.22.10"
|
version "7.22.10"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.10.tgz#e37634f9a12a1716136c44624ef54283cabd3f55"
|
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.10.tgz#e37634f9a12a1716136c44624ef54283cabd3f55"
|
||||||
integrity sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ==
|
integrity sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ==
|
||||||
|
|
||||||
"@babel/parser@^7.22.15", "@babel/parser@^7.22.5":
|
|
||||||
version "7.22.15"
|
|
||||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.15.tgz#d34592bfe288a32e741aa0663dbc4829fcd55160"
|
|
||||||
integrity sha512-RWmQ/sklUN9BvGGpCDgSubhHWfAx24XDTDObup4ffvxaYsptOg2P3KG0j+1eWKLxpkX0j0uHxmpq2Z1SP/VhxA==
|
|
||||||
|
|
||||||
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.22.15":
|
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.22.15":
|
||||||
version "7.22.15"
|
version "7.22.15"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.15.tgz#02dc8a03f613ed5fdc29fb2f728397c78146c962"
|
resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.15.tgz#02dc8a03f613ed5fdc29fb2f728397c78146c962"
|
||||||
|
@ -1112,23 +1112,7 @@
|
||||||
"@babel/parser" "^7.22.5"
|
"@babel/parser" "^7.22.5"
|
||||||
"@babel/types" "^7.22.5"
|
"@babel/types" "^7.22.5"
|
||||||
|
|
||||||
"@babel/traverse@7":
|
"@babel/traverse@7", "@babel/traverse@^7.22.15":
|
||||||
version "7.22.5"
|
|
||||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.5.tgz#44bd276690db6f4940fdb84e1cb4abd2f729ccd1"
|
|
||||||
integrity sha512-7DuIjPgERaNo6r+PZwItpjCZEa5vyw4eJGufeLxrPdBXBoLcCJCIasvK6pK/9DVNrLZTLFhUGqaC6X/PA007TQ==
|
|
||||||
dependencies:
|
|
||||||
"@babel/code-frame" "^7.22.5"
|
|
||||||
"@babel/generator" "^7.22.5"
|
|
||||||
"@babel/helper-environment-visitor" "^7.22.5"
|
|
||||||
"@babel/helper-function-name" "^7.22.5"
|
|
||||||
"@babel/helper-hoist-variables" "^7.22.5"
|
|
||||||
"@babel/helper-split-export-declaration" "^7.22.5"
|
|
||||||
"@babel/parser" "^7.22.5"
|
|
||||||
"@babel/types" "^7.22.5"
|
|
||||||
debug "^4.1.0"
|
|
||||||
globals "^11.1.0"
|
|
||||||
|
|
||||||
"@babel/traverse@^7.22.15":
|
|
||||||
version "7.22.15"
|
version "7.22.15"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.15.tgz#75be4d2d6e216e880e93017f4e2389aeb77ef2d9"
|
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.15.tgz#75be4d2d6e216e880e93017f4e2389aeb77ef2d9"
|
||||||
integrity sha512-DdHPwvJY0sEeN4xJU5uRLmZjgMMDIvMPniLuYzUVXj/GGzysPl0/fwt44JBkyUIzGJPV8QgHMcQdQ34XFuKTYQ==
|
integrity sha512-DdHPwvJY0sEeN4xJU5uRLmZjgMMDIvMPniLuYzUVXj/GGzysPl0/fwt44JBkyUIzGJPV8QgHMcQdQ34XFuKTYQ==
|
||||||
|
@ -1144,16 +1128,16 @@
|
||||||
debug "^4.1.0"
|
debug "^4.1.0"
|
||||||
globals "^11.1.0"
|
globals "^11.1.0"
|
||||||
|
|
||||||
"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.3.3":
|
"@babel/types@^7.0.0", "@babel/types@^7.12.11", "@babel/types@^7.20.7", "@babel/types@^7.22.10", "@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.4.4":
|
||||||
version "7.22.10"
|
version "7.22.15"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.10.tgz#4a9e76446048f2c66982d1a989dd12b8a2d2dc03"
|
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.15.tgz#266cb21d2c5fd0b3931e7a91b6dd72d2f617d282"
|
||||||
integrity sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==
|
integrity sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/helper-string-parser" "^7.22.5"
|
"@babel/helper-string-parser" "^7.22.5"
|
||||||
"@babel/helper-validator-identifier" "^7.22.5"
|
"@babel/helper-validator-identifier" "^7.22.15"
|
||||||
to-fast-properties "^2.0.0"
|
to-fast-properties "^2.0.0"
|
||||||
|
|
||||||
"@babel/types@^7.0.0-beta.49", "@babel/types@^7.12.11", "@babel/types@^7.12.6":
|
"@babel/types@^7.0.0-beta.49", "@babel/types@^7.12.6":
|
||||||
version "7.22.5"
|
version "7.22.5"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.5.tgz#cd93eeaab025880a3a47ec881f4b096a5b786fbe"
|
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.5.tgz#cd93eeaab025880a3a47ec881f4b096a5b786fbe"
|
||||||
integrity sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==
|
integrity sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==
|
||||||
|
@ -1162,13 +1146,13 @@
|
||||||
"@babel/helper-validator-identifier" "^7.22.5"
|
"@babel/helper-validator-identifier" "^7.22.5"
|
||||||
to-fast-properties "^2.0.0"
|
to-fast-properties "^2.0.0"
|
||||||
|
|
||||||
"@babel/types@^7.22.10", "@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.4.4":
|
"@babel/types@^7.3.3":
|
||||||
version "7.22.15"
|
version "7.22.10"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.15.tgz#266cb21d2c5fd0b3931e7a91b6dd72d2f617d282"
|
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.10.tgz#4a9e76446048f2c66982d1a989dd12b8a2d2dc03"
|
||||||
integrity sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==
|
integrity sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/helper-string-parser" "^7.22.5"
|
"@babel/helper-string-parser" "^7.22.5"
|
||||||
"@babel/helper-validator-identifier" "^7.22.15"
|
"@babel/helper-validator-identifier" "^7.22.5"
|
||||||
to-fast-properties "^2.0.0"
|
to-fast-properties "^2.0.0"
|
||||||
|
|
||||||
"@bcoe/v8-coverage@^0.2.3":
|
"@bcoe/v8-coverage@^0.2.3":
|
||||||
|
@ -1355,6 +1339,14 @@
|
||||||
"@formatjs/intl-localematcher" "0.4.0"
|
"@formatjs/intl-localematcher" "0.4.0"
|
||||||
tslib "^2.4.0"
|
tslib "^2.4.0"
|
||||||
|
|
||||||
|
"@formatjs/ecma402-abstract@1.17.1":
|
||||||
|
version "1.17.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@formatjs/ecma402-abstract/-/ecma402-abstract-1.17.1.tgz#6ac7d6a1d1c9c8eff76ab6ed949f2a5cbe424030"
|
||||||
|
integrity sha512-N2sjSUrmsEoynG8Q61pkrKlJ9PxcUGxJke1x3301aGyprGgl58wHWhgGUnzTfS4OHNNNQDxzjcXVp1t5fGW6yQ==
|
||||||
|
dependencies:
|
||||||
|
"@formatjs/intl-localematcher" "0.4.1"
|
||||||
|
tslib "^2.4.0"
|
||||||
|
|
||||||
"@formatjs/fast-memoize@2.2.0":
|
"@formatjs/fast-memoize@2.2.0":
|
||||||
version "2.2.0"
|
version "2.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/@formatjs/fast-memoize/-/fast-memoize-2.2.0.tgz#33bd616d2e486c3e8ef4e68c99648c196887802b"
|
resolved "https://registry.yarnpkg.com/@formatjs/fast-memoize/-/fast-memoize-2.2.0.tgz#33bd616d2e486c3e8ef4e68c99648c196887802b"
|
||||||
|
@ -1371,6 +1363,15 @@
|
||||||
"@formatjs/icu-skeleton-parser" "1.6.0"
|
"@formatjs/icu-skeleton-parser" "1.6.0"
|
||||||
tslib "^2.4.0"
|
tslib "^2.4.0"
|
||||||
|
|
||||||
|
"@formatjs/icu-messageformat-parser@2.6.1":
|
||||||
|
version "2.6.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.6.1.tgz#ca497d5a2bff641dc0978bd9b64d1d02597980cb"
|
||||||
|
integrity sha512-dTDNupwdovxT1xDXC96zzPUua/XrxTQTOulJZSvaJP0pt3rr/cGR/tq4d7BnxY9oqPZpc4fjWBmrRlhcUyBSiw==
|
||||||
|
dependencies:
|
||||||
|
"@formatjs/ecma402-abstract" "1.17.1"
|
||||||
|
"@formatjs/icu-skeleton-parser" "1.6.1"
|
||||||
|
tslib "^2.4.0"
|
||||||
|
|
||||||
"@formatjs/icu-skeleton-parser@1.6.0":
|
"@formatjs/icu-skeleton-parser@1.6.0":
|
||||||
version "1.6.0"
|
version "1.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.6.0.tgz#0728be8b6b3656f1a4b8e6e5b0e02dffffc23c6c"
|
resolved "https://registry.yarnpkg.com/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.6.0.tgz#0728be8b6b3656f1a4b8e6e5b0e02dffffc23c6c"
|
||||||
|
@ -1379,22 +1380,30 @@
|
||||||
"@formatjs/ecma402-abstract" "1.17.0"
|
"@formatjs/ecma402-abstract" "1.17.0"
|
||||||
tslib "^2.4.0"
|
tslib "^2.4.0"
|
||||||
|
|
||||||
"@formatjs/intl-displaynames@6.5.0":
|
"@formatjs/icu-skeleton-parser@1.6.1":
|
||||||
version "6.5.0"
|
version "1.6.1"
|
||||||
resolved "https://registry.yarnpkg.com/@formatjs/intl-displaynames/-/intl-displaynames-6.5.0.tgz#32737088e7d943fb3e22140e64bb634e0ba05fcf"
|
resolved "https://registry.yarnpkg.com/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.6.1.tgz#3647f41b82e362c08bb80bd9b653c7eb6ff31118"
|
||||||
integrity sha512-sg/nR8ILEdUl+2sWu6jc1nQ5s04yucGlH1RVfatW8TSJ5uG3Yy3vgigi8NNC/BuhcncUNPWqSpTCSI1hA+rhiw==
|
integrity sha512-/LQ6ovxYd8FQjVLmbV+WmuFy86o+JTc0cIQuWixuLuUMfRRif8eUQw3vPK5hx7C/g1UVmKAaOcYRTEsvyEGz9g==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@formatjs/ecma402-abstract" "1.17.0"
|
"@formatjs/ecma402-abstract" "1.17.1"
|
||||||
"@formatjs/intl-localematcher" "0.4.0"
|
|
||||||
tslib "^2.4.0"
|
tslib "^2.4.0"
|
||||||
|
|
||||||
"@formatjs/intl-listformat@7.4.0":
|
"@formatjs/intl-displaynames@6.5.1":
|
||||||
version "7.4.0"
|
version "6.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/@formatjs/intl-listformat/-/intl-listformat-7.4.0.tgz#fa8ac535d82fc716f052f2fd60eeaa7331362357"
|
resolved "https://registry.yarnpkg.com/@formatjs/intl-displaynames/-/intl-displaynames-6.5.1.tgz#d25d260b81845abf6f35a13dbc87c25b0ec22a33"
|
||||||
integrity sha512-ifupb+balZUAF/Oh3QyGRqPRWGSKwWoMPR0cYZEG7r61SimD+m38oFQqVx/3Fp7LfQFF11m7IS+MlxOo2sKINA==
|
integrity sha512-BD+coSUka8fppErGnXbWthd6YxTXdCGvQzGR/rSEdPgiZO5sh+0gVLjp0FgXi6cOf9C2z2axqhGifFsqyTVhkw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@formatjs/ecma402-abstract" "1.17.0"
|
"@formatjs/ecma402-abstract" "1.17.1"
|
||||||
"@formatjs/intl-localematcher" "0.4.0"
|
"@formatjs/intl-localematcher" "0.4.1"
|
||||||
|
tslib "^2.4.0"
|
||||||
|
|
||||||
|
"@formatjs/intl-listformat@7.4.1":
|
||||||
|
version "7.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@formatjs/intl-listformat/-/intl-listformat-7.4.1.tgz#cb6f1399a41b9fd568cc4b4b80fc815d0c5b37ab"
|
||||||
|
integrity sha512-mWd30ndvYw8JydOIVb5Y1ElK2iwsaDY+ajPR5aWWgEZaH04aL+4hzX/8VXPsilu7CF3DN1IP5ZSwJuj7ZyBIHw==
|
||||||
|
dependencies:
|
||||||
|
"@formatjs/ecma402-abstract" "1.17.1"
|
||||||
|
"@formatjs/intl-localematcher" "0.4.1"
|
||||||
tslib "^2.4.0"
|
tslib "^2.4.0"
|
||||||
|
|
||||||
"@formatjs/intl-localematcher@0.4.0":
|
"@formatjs/intl-localematcher@0.4.0":
|
||||||
|
@ -1404,26 +1413,33 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib "^2.4.0"
|
tslib "^2.4.0"
|
||||||
|
|
||||||
"@formatjs/intl-pluralrules@^5.2.2":
|
"@formatjs/intl-localematcher@0.4.1":
|
||||||
version "5.2.4"
|
version "0.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/@formatjs/intl-pluralrules/-/intl-pluralrules-5.2.4.tgz#b417aa503186c2cbb4715f47114ed65211b4ada9"
|
resolved "https://registry.yarnpkg.com/@formatjs/intl-localematcher/-/intl-localematcher-0.4.1.tgz#af63e2c065731a33f6fed36dc85058009a7f8062"
|
||||||
integrity sha512-6meo376d8I4zikRFSUxATLnqzGwezmc57SmToP4z1/NQwTHXGe0yIG/ABPbO3QMx7IUkofH/ROP3A4DhtPTpnA==
|
integrity sha512-Fs4MhhHlLC0RrspX2u2KP7zlwL9eHrBZsOBxaPOeqrCZYLaOUK4cYXQ1ErpAB0HnGV/GUXNa5smzV/7jCuRzxg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@formatjs/ecma402-abstract" "1.17.0"
|
|
||||||
"@formatjs/intl-localematcher" "0.4.0"
|
|
||||||
tslib "^2.4.0"
|
tslib "^2.4.0"
|
||||||
|
|
||||||
"@formatjs/intl@2.9.0":
|
"@formatjs/intl-pluralrules@^5.2.2":
|
||||||
version "2.9.0"
|
version "5.2.5"
|
||||||
resolved "https://registry.yarnpkg.com/@formatjs/intl/-/intl-2.9.0.tgz#e1335572af3ca8a53e136a78e866f1851a9718c2"
|
resolved "https://registry.yarnpkg.com/@formatjs/intl-pluralrules/-/intl-pluralrules-5.2.5.tgz#72ff79bec4c3383a46e6b3d6b0af73534e544302"
|
||||||
integrity sha512-Ym0trUoC/VO6wQu4YHa0H1VR2tEixFRmwZgADkDLm7nD+vv1Ob+/88mUAoT0pwvirFqYKgUKEwp1tFepqyqvVA==
|
integrity sha512-od9KJzKB5CF9Hfq3g6CJzWA0rW9yaNrF2hMZK3/26aTuZ4Fm3mPm/JI6QReF9qZSC1qkJyqS1GN0JtTm2sVyGQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@formatjs/ecma402-abstract" "1.17.0"
|
"@formatjs/ecma402-abstract" "1.17.1"
|
||||||
|
"@formatjs/intl-localematcher" "0.4.1"
|
||||||
|
tslib "^2.4.0"
|
||||||
|
|
||||||
|
"@formatjs/intl@2.9.1":
|
||||||
|
version "2.9.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@formatjs/intl/-/intl-2.9.1.tgz#f224109620b71f48c049bd42df770f202e4b6d29"
|
||||||
|
integrity sha512-NsDMke+lAiu+c6/9KXrp8aldd7sFeyxgQZqFUJSZIeaKrN+gEoYKqWgsiRa7/mxlWqWNJSGuNQnF1P2ChC/yaA==
|
||||||
|
dependencies:
|
||||||
|
"@formatjs/ecma402-abstract" "1.17.1"
|
||||||
"@formatjs/fast-memoize" "2.2.0"
|
"@formatjs/fast-memoize" "2.2.0"
|
||||||
"@formatjs/icu-messageformat-parser" "2.6.0"
|
"@formatjs/icu-messageformat-parser" "2.6.1"
|
||||||
"@formatjs/intl-displaynames" "6.5.0"
|
"@formatjs/intl-displaynames" "6.5.1"
|
||||||
"@formatjs/intl-listformat" "7.4.0"
|
"@formatjs/intl-listformat" "7.4.1"
|
||||||
intl-messageformat "10.5.0"
|
intl-messageformat "10.5.1"
|
||||||
tslib "^2.4.0"
|
tslib "^2.4.0"
|
||||||
|
|
||||||
"@formatjs/ts-transformer@3.13.3":
|
"@formatjs/ts-transformer@3.13.3":
|
||||||
|
@ -1439,6 +1455,19 @@
|
||||||
tslib "^2.4.0"
|
tslib "^2.4.0"
|
||||||
typescript "^4.7 || 5"
|
typescript "^4.7 || 5"
|
||||||
|
|
||||||
|
"@formatjs/ts-transformer@3.13.4":
|
||||||
|
version "3.13.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@formatjs/ts-transformer/-/ts-transformer-3.13.4.tgz#586582ab3aee75b7e24d37f7090ab270062a9bf5"
|
||||||
|
integrity sha512-AOOHpHBJyjcNLkJcT82zeU7IlaogHI4qBjPlFgyeqcSbGwR4b+LGY7Frf7N5eM8Y9yGnTDVIUA/u3gHUA3SHQg==
|
||||||
|
dependencies:
|
||||||
|
"@formatjs/icu-messageformat-parser" "2.6.1"
|
||||||
|
"@types/json-stable-stringify" "^1.0.32"
|
||||||
|
"@types/node" "14 || 16 || 17"
|
||||||
|
chalk "^4.0.0"
|
||||||
|
json-stable-stringify "^1.0.1"
|
||||||
|
tslib "^2.4.0"
|
||||||
|
typescript "^4.7 || 5"
|
||||||
|
|
||||||
"@gamestdio/websocket@^0.3.2":
|
"@gamestdio/websocket@^0.3.2":
|
||||||
version "0.3.2"
|
version "0.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/@gamestdio/websocket/-/websocket-0.3.2.tgz#321ba0976ee30fd14e51dbf8faa85ce7b325f76a"
|
resolved "https://registry.yarnpkg.com/@gamestdio/websocket/-/websocket-0.3.2.tgz#321ba0976ee30fd14e51dbf8faa85ce7b325f76a"
|
||||||
|
@ -1718,9 +1747,9 @@
|
||||||
integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==
|
integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==
|
||||||
|
|
||||||
"@jridgewell/source-map@^0.3.3":
|
"@jridgewell/source-map@^0.3.3":
|
||||||
version "0.3.3"
|
version "0.3.5"
|
||||||
resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.3.tgz#8108265659d4c33e72ffe14e33d6cc5eb59f2fda"
|
resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.5.tgz#a3bb4d5c6825aab0d281268f47f6ad5853431e91"
|
||||||
integrity sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==
|
integrity sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jridgewell/gen-mapping" "^0.3.0"
|
"@jridgewell/gen-mapping" "^0.3.0"
|
||||||
"@jridgewell/trace-mapping" "^0.3.9"
|
"@jridgewell/trace-mapping" "^0.3.9"
|
||||||
|
@ -1739,9 +1768,9 @@
|
||||||
"@jridgewell/sourcemap-codec" "^1.4.14"
|
"@jridgewell/sourcemap-codec" "^1.4.14"
|
||||||
|
|
||||||
"@material-design-icons/svg@^0.14.10":
|
"@material-design-icons/svg@^0.14.10":
|
||||||
version "0.14.11"
|
version "0.14.12"
|
||||||
resolved "https://registry.yarnpkg.com/@material-design-icons/svg/-/svg-0.14.11.tgz#f90a2c8de801523c3b17e606c89313121c8bb3b4"
|
resolved "https://registry.yarnpkg.com/@material-design-icons/svg/-/svg-0.14.12.tgz#b3dd27b4c2a93e0310f51acfb311846b0212f987"
|
||||||
integrity sha512-jpAksWZIVLB5/qTAeqANns7pH/faIQR3jgV2yROUNKZkzpJ428h7e1/byJB+rFZNI0hgZpY9nOVMLhc1J41HtA==
|
integrity sha512-hVEMICFvG26SKDXatPmz+vY5BAqLPCDiyXnw+KN46FXOtY4PcpeAfzFZvwt6D9ywNnVJd4EvmLdlWgLmtOWxbA==
|
||||||
|
|
||||||
"@nodelib/fs.scandir@2.1.5":
|
"@nodelib/fs.scandir@2.1.5":
|
||||||
version "2.1.5"
|
version "2.1.5"
|
||||||
|
@ -1822,6 +1851,17 @@
|
||||||
redux-thunk "^2.4.2"
|
redux-thunk "^2.4.2"
|
||||||
reselect "^4.1.8"
|
reselect "^4.1.8"
|
||||||
|
|
||||||
|
"@renchap/compression-webpack-plugin@^6.1.4":
|
||||||
|
version "6.1.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@renchap/compression-webpack-plugin/-/compression-webpack-plugin-6.1.4.tgz#5ff528ae9edf83de7447b72f5b52a05f860bb899"
|
||||||
|
integrity sha512-Ij43bj/jhKiMKOZVT9b3DJvr4R+dNs9ZbH7QV3kLfloavt4GhNo4Jw86tVwmP5d+seZtSwTL1NG8/c6dM1V0vw==
|
||||||
|
dependencies:
|
||||||
|
cacache "^15.0.5"
|
||||||
|
find-cache-dir "^3.3.1"
|
||||||
|
schema-utils "^3.0.0"
|
||||||
|
serialize-javascript "^5.0.1"
|
||||||
|
webpack-sources "^1.4.3"
|
||||||
|
|
||||||
"@restart/hooks@^0.4.7":
|
"@restart/hooks@^0.4.7":
|
||||||
version "0.4.9"
|
version "0.4.9"
|
||||||
resolved "https://registry.yarnpkg.com/@restart/hooks/-/hooks-0.4.9.tgz#ad858fb39d99e252cccce19416adc18fc3f18fcb"
|
resolved "https://registry.yarnpkg.com/@restart/hooks/-/hooks-0.4.9.tgz#ad858fb39d99e252cccce19416adc18fc3f18fcb"
|
||||||
|
@ -2913,16 +2953,11 @@ acorn@^6.4.1:
|
||||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6"
|
resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6"
|
||||||
integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==
|
integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==
|
||||||
|
|
||||||
acorn@^8.0.4, acorn@^8.1.0, acorn@^8.8.1, acorn@^8.9.0:
|
acorn@^8.0.4, acorn@^8.1.0, acorn@^8.8.1, acorn@^8.8.2, acorn@^8.9.0:
|
||||||
version "8.10.0"
|
version "8.10.0"
|
||||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5"
|
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5"
|
||||||
integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==
|
integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==
|
||||||
|
|
||||||
acorn@^8.8.2:
|
|
||||||
version "8.8.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a"
|
|
||||||
integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==
|
|
||||||
|
|
||||||
agent-base@6:
|
agent-base@6:
|
||||||
version "6.0.2"
|
version "6.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
|
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
|
||||||
|
@ -3383,17 +3418,17 @@ babel-loader@^8.3.0:
|
||||||
schema-utils "^2.6.5"
|
schema-utils "^2.6.5"
|
||||||
|
|
||||||
babel-plugin-formatjs@^10.5.1:
|
babel-plugin-formatjs@^10.5.1:
|
||||||
version "10.5.3"
|
version "10.5.4"
|
||||||
resolved "https://registry.yarnpkg.com/babel-plugin-formatjs/-/babel-plugin-formatjs-10.5.3.tgz#718e47f4f3aad663ad4f901274aedd7be0a86380"
|
resolved "https://registry.yarnpkg.com/babel-plugin-formatjs/-/babel-plugin-formatjs-10.5.4.tgz#98837caedcdb64f118048f19e59ad0c94f55b5aa"
|
||||||
integrity sha512-PBeryWyN2HY2VUGNFPQS6+DPNQ/I9zDZ97y38i1+LzIpIyTHBePECq/ehEABE73PvvF2irFiN7TCYBrQQw5+lA==
|
integrity sha512-6JSpDS/YVjMu74NzHkuEduWqDsmUbUm1qc6sNeccgknixW9Z3hbQqv3Fvfjrh4opBzJ+CRaAZaUlQQL+xDTQzw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/core" "^7.10.4"
|
"@babel/core" "^7.10.4"
|
||||||
"@babel/helper-plugin-utils" "^7.10.4"
|
"@babel/helper-plugin-utils" "^7.10.4"
|
||||||
"@babel/plugin-syntax-jsx" "7"
|
"@babel/plugin-syntax-jsx" "7"
|
||||||
"@babel/traverse" "7"
|
"@babel/traverse" "7"
|
||||||
"@babel/types" "^7.12.11"
|
"@babel/types" "^7.12.11"
|
||||||
"@formatjs/icu-messageformat-parser" "2.6.0"
|
"@formatjs/icu-messageformat-parser" "2.6.1"
|
||||||
"@formatjs/ts-transformer" "3.13.3"
|
"@formatjs/ts-transformer" "3.13.4"
|
||||||
"@types/babel__core" "^7.1.7"
|
"@types/babel__core" "^7.1.7"
|
||||||
"@types/babel__helper-plugin-utils" "^7.10.0"
|
"@types/babel__helper-plugin-utils" "^7.10.0"
|
||||||
"@types/babel__traverse" "^7.1.7"
|
"@types/babel__traverse" "^7.1.7"
|
||||||
|
@ -3932,9 +3967,9 @@ caniuse-lite@^1.0.30001502:
|
||||||
integrity sha512-eEFDwUOZbE24sb+Ecsx3+OvNETqjWIdabMy52oOkIgcUtAsQifjUG9q4U9dgTHJM2mfk4uEPxc0+xuFdJ629QA==
|
integrity sha512-eEFDwUOZbE24sb+Ecsx3+OvNETqjWIdabMy52oOkIgcUtAsQifjUG9q4U9dgTHJM2mfk4uEPxc0+xuFdJ629QA==
|
||||||
|
|
||||||
caniuse-lite@^1.0.30001517:
|
caniuse-lite@^1.0.30001517:
|
||||||
version "1.0.30001525"
|
version "1.0.30001528"
|
||||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001525.tgz#d2e8fdec6116ffa36284ca2c33ef6d53612fe1c8"
|
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001528.tgz#479972fc705b996f1114336c0032418a215fd0aa"
|
||||||
integrity sha512-/3z+wB4icFt3r0USMwxujAqRvaD/B7rvGTsKhbhSQErVrJvkZCLhgNLJxU8MevahQVH6hCU9FsHdNUFbiwmE7Q==
|
integrity sha512-0Db4yyjR9QMNlsxh+kKWzQtkyflkG/snYheSzkjmvdEtEXB1+jt7A2HmSEiO6XIJPIbo92lHNGNySvE5pZcs5Q==
|
||||||
|
|
||||||
caniuse-lite@^1.0.30001520:
|
caniuse-lite@^1.0.30001520:
|
||||||
version "1.0.30001520"
|
version "1.0.30001520"
|
||||||
|
@ -4248,17 +4283,6 @@ compressible@~2.0.16:
|
||||||
dependencies:
|
dependencies:
|
||||||
mime-db ">= 1.43.0 < 2"
|
mime-db ">= 1.43.0 < 2"
|
||||||
|
|
||||||
compression-webpack-plugin@^6.1.1:
|
|
||||||
version "6.1.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/compression-webpack-plugin/-/compression-webpack-plugin-6.1.1.tgz#ae8e4b2ffdb7396bb776e66918d751a20d8ccf0e"
|
|
||||||
integrity sha512-BEHft9M6lwOqVIQFMS/YJGmeCYXVOakC5KzQk05TFpMBlODByh1qNsZCWjUBxCQhUP9x0WfGidxTbGkjbWO/TQ==
|
|
||||||
dependencies:
|
|
||||||
cacache "^15.0.5"
|
|
||||||
find-cache-dir "^3.3.1"
|
|
||||||
schema-utils "^3.0.0"
|
|
||||||
serialize-javascript "^5.0.1"
|
|
||||||
webpack-sources "^1.4.3"
|
|
||||||
|
|
||||||
compression@^1.7.4:
|
compression@^1.7.4:
|
||||||
version "1.7.4"
|
version "1.7.4"
|
||||||
resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f"
|
resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f"
|
||||||
|
@ -4347,9 +4371,9 @@ core-js@^2.5.0:
|
||||||
integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==
|
integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==
|
||||||
|
|
||||||
core-js@^3.30.2:
|
core-js@^3.30.2:
|
||||||
version "3.32.1"
|
version "3.32.2"
|
||||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.32.1.tgz#a7d8736a3ed9dd05940c3c4ff32c591bb735be77"
|
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.32.2.tgz#172fb5949ef468f93b4be7841af6ab1f21992db7"
|
||||||
integrity sha512-lqufgNn9NLnESg5mQeYsxQP5w7wrViSj0jr/kv6ECQiByzQkrn1MKvV0L3acttpDqfQrHLwr2KCMgX5b8X+lyQ==
|
integrity sha512-pxXSw1mYZPDGvTQqEc5vgIb83jGQKFGYWY76z4a7weZXUolw3G+OvpZqSRcfYOoOVUQJYEPsWeQK8pKEnUtWxQ==
|
||||||
|
|
||||||
core-util-is@~1.0.0:
|
core-util-is@~1.0.0:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
|
@ -5097,9 +5121,9 @@ electron-to-chromium@^1.4.428:
|
||||||
integrity sha512-/g3UyNDmDd6ebeWapmAoiyy+Sy2HyJ+/X8KyvNeHfKRFfHaA2W8oF5fxD5F3tjBDcjpwo0iek6YNgxNXDBoEtA==
|
integrity sha512-/g3UyNDmDd6ebeWapmAoiyy+Sy2HyJ+/X8KyvNeHfKRFfHaA2W8oF5fxD5F3tjBDcjpwo0iek6YNgxNXDBoEtA==
|
||||||
|
|
||||||
electron-to-chromium@^1.4.477:
|
electron-to-chromium@^1.4.477:
|
||||||
version "1.4.508"
|
version "1.4.510"
|
||||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.508.tgz#5641ff2f5ba11df4bd960fe6a2f9f70aa8b9af96"
|
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.510.tgz#446c50d7533c1e71a84b00a3b37ab06dd601d890"
|
||||||
integrity sha512-FFa8QKjQK/A5QuFr2167myhMesGrhlOBD+3cYNxO9/S4XzHEXesyTD/1/xF644gC8buFPz3ca6G1LOQD0tZrrg==
|
integrity sha512-xPfLIPFcN/WLXBpQ/K4UgE98oUBO5Tia6BD4rkSR0wE7ep/PwBVlgvPJQrIBpmJGVAmUzwPKuDbVt9XV6+uC2g==
|
||||||
|
|
||||||
elliptic@^6.5.3:
|
elliptic@^6.5.3:
|
||||||
version "6.5.4"
|
version "6.5.4"
|
||||||
|
@ -6109,11 +6133,16 @@ fsevents@^1.2.7:
|
||||||
bindings "^1.5.0"
|
bindings "^1.5.0"
|
||||||
nan "^2.12.1"
|
nan "^2.12.1"
|
||||||
|
|
||||||
fsevents@^2.3.2, fsevents@~2.3.2:
|
fsevents@^2.3.2:
|
||||||
version "2.3.2"
|
version "2.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
|
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
|
||||||
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
|
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
|
||||||
|
|
||||||
|
fsevents@~2.3.2:
|
||||||
|
version "2.3.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
|
||||||
|
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
|
||||||
|
|
||||||
function-bind@^1.1.1:
|
function-bind@^1.1.1:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
|
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
|
||||||
|
@ -6815,14 +6844,14 @@ intersection-observer@^0.12.0:
|
||||||
resolved "https://registry.yarnpkg.com/intersection-observer/-/intersection-observer-0.12.2.tgz#4a45349cc0cd91916682b1f44c28d7ec737dc375"
|
resolved "https://registry.yarnpkg.com/intersection-observer/-/intersection-observer-0.12.2.tgz#4a45349cc0cd91916682b1f44c28d7ec737dc375"
|
||||||
integrity sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg==
|
integrity sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg==
|
||||||
|
|
||||||
intl-messageformat@10.5.0, intl-messageformat@^10.3.5:
|
intl-messageformat@10.5.1, intl-messageformat@^10.3.5:
|
||||||
version "10.5.0"
|
version "10.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/intl-messageformat/-/intl-messageformat-10.5.0.tgz#86d11b15913ac954075b25253f5e669359f89538"
|
resolved "https://registry.yarnpkg.com/intl-messageformat/-/intl-messageformat-10.5.1.tgz#40304cbde01c8cb2236e11ac8c827642bed474d0"
|
||||||
integrity sha512-AvojYuOaRb6r2veOKfTVpxH9TrmjSdc5iR9R5RgBwrDZYSmAAFVT+QLbW3C4V7Qsg0OguMp67Q/EoUkxZzXRGw==
|
integrity sha512-irEmjxHq0f1MHviQr3Q4ToF9EgYbnXDq2/R9MRTTveGKHgy6VZ29hQxswu4trqWaX7T6njKxSoKVG92OSz0U5Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@formatjs/ecma402-abstract" "1.17.0"
|
"@formatjs/ecma402-abstract" "1.17.1"
|
||||||
"@formatjs/fast-memoize" "2.2.0"
|
"@formatjs/fast-memoize" "2.2.0"
|
||||||
"@formatjs/icu-messageformat-parser" "2.6.0"
|
"@formatjs/icu-messageformat-parser" "2.6.1"
|
||||||
tslib "^2.4.0"
|
tslib "^2.4.0"
|
||||||
|
|
||||||
invariant@^2.2.2, invariant@^2.2.4:
|
invariant@^2.2.2, invariant@^2.2.4:
|
||||||
|
@ -10031,19 +10060,19 @@ react-immutable-pure-component@^2.2.2:
|
||||||
integrity sha512-vkgoMJUDqHZfXXnjVlG3keCxSO/U6WeDQ5/Sl0GK2cH8TOxEzQ5jXqDXHEL/jqk6fsNxV05oH5kD7VNMUE2k+A==
|
integrity sha512-vkgoMJUDqHZfXXnjVlG3keCxSO/U6WeDQ5/Sl0GK2cH8TOxEzQ5jXqDXHEL/jqk6fsNxV05oH5kD7VNMUE2k+A==
|
||||||
|
|
||||||
react-intl@^6.4.2:
|
react-intl@^6.4.2:
|
||||||
version "6.4.4"
|
version "6.4.5"
|
||||||
resolved "https://registry.yarnpkg.com/react-intl/-/react-intl-6.4.4.tgz#14b45ce046bfbb60c0e6d392d8ddc30e9ead5a4f"
|
resolved "https://registry.yarnpkg.com/react-intl/-/react-intl-6.4.5.tgz#d8f61fce2fb3be08ef58deb35d96b964e1ef013a"
|
||||||
integrity sha512-/C9Sl/5//ohfkNG6AWlJuf4BhTXsbzyk93K62A4zRhSPANyOGpKZ+fWhN+TLfFd5YjDUHy+exU/09y0w1bO4Xw==
|
integrity sha512-nUO2W57Tmdu6ErhsOFpsgkEtfQ4Lo7hPrXn8gGJQx59NRC0FNUxRc6+Ah3G8j6vqBiYRmxsLJpVZtIhLZjhYLA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@formatjs/ecma402-abstract" "1.17.0"
|
"@formatjs/ecma402-abstract" "1.17.1"
|
||||||
"@formatjs/icu-messageformat-parser" "2.6.0"
|
"@formatjs/icu-messageformat-parser" "2.6.1"
|
||||||
"@formatjs/intl" "2.9.0"
|
"@formatjs/intl" "2.9.1"
|
||||||
"@formatjs/intl-displaynames" "6.5.0"
|
"@formatjs/intl-displaynames" "6.5.1"
|
||||||
"@formatjs/intl-listformat" "7.4.0"
|
"@formatjs/intl-listformat" "7.4.1"
|
||||||
"@types/hoist-non-react-statics" "^3.3.1"
|
"@types/hoist-non-react-statics" "^3.3.1"
|
||||||
"@types/react" "16 || 17 || 18"
|
"@types/react" "16 || 17 || 18"
|
||||||
hoist-non-react-statics "^3.3.2"
|
hoist-non-react-statics "^3.3.2"
|
||||||
intl-messageformat "10.5.0"
|
intl-messageformat "10.5.1"
|
||||||
tslib "^2.4.0"
|
tslib "^2.4.0"
|
||||||
|
|
||||||
"react-is@^16.12.0 || ^17.0.0 || ^18.0.0", react-is@^18.0.0, react-is@^18.2.0:
|
"react-is@^16.12.0 || ^17.0.0 || ^18.0.0", react-is@^18.0.0, react-is@^18.2.0:
|
||||||
|
@ -11744,9 +11773,9 @@ tapable@^2.2.0:
|
||||||
integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==
|
integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==
|
||||||
|
|
||||||
tar@^6.0.2:
|
tar@^6.0.2:
|
||||||
version "6.1.15"
|
version "6.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.15.tgz#c9738b0b98845a3b344d334b8fa3041aaba53a69"
|
resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.0.tgz#b14ce49a79cb1cd23bc9b016302dea5474493f73"
|
||||||
integrity sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==
|
integrity sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
chownr "^2.0.0"
|
chownr "^2.0.0"
|
||||||
fs-minipass "^2.0.0"
|
fs-minipass "^2.0.0"
|
||||||
|
@ -11792,7 +11821,7 @@ terser-webpack-plugin@^1.4.3, terser-webpack-plugin@^4.2.3:
|
||||||
terser "^5.3.4"
|
terser "^5.3.4"
|
||||||
webpack-sources "^1.4.3"
|
webpack-sources "^1.4.3"
|
||||||
|
|
||||||
terser@^5.0.0, terser@^5.3.4:
|
terser@^5.0.0:
|
||||||
version "5.18.0"
|
version "5.18.0"
|
||||||
resolved "https://registry.yarnpkg.com/terser/-/terser-5.18.0.tgz#dc811fb8e3481a875d545bda247c8730ee4dc76b"
|
resolved "https://registry.yarnpkg.com/terser/-/terser-5.18.0.tgz#dc811fb8e3481a875d545bda247c8730ee4dc76b"
|
||||||
integrity sha512-pdL757Ig5a0I+owA42l6tIuEycRuM7FPY4n62h44mRLRfnOxJkkOHd6i89dOpwZlpF6JXBwaAHF6yWzFrt+QyA==
|
integrity sha512-pdL757Ig5a0I+owA42l6tIuEycRuM7FPY4n62h44mRLRfnOxJkkOHd6i89dOpwZlpF6JXBwaAHF6yWzFrt+QyA==
|
||||||
|
@ -11802,6 +11831,16 @@ terser@^5.0.0, terser@^5.3.4:
|
||||||
commander "^2.20.0"
|
commander "^2.20.0"
|
||||||
source-map-support "~0.5.20"
|
source-map-support "~0.5.20"
|
||||||
|
|
||||||
|
terser@^5.3.4:
|
||||||
|
version "5.19.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/terser/-/terser-5.19.4.tgz#941426fa482bf9b40a0308ab2b3cd0cf7c775ebd"
|
||||||
|
integrity sha512-6p1DjHeuluwxDXcuT9VR8p64klWJKo1ILiy19s6C9+0Bh2+NWTX6nD9EPppiER4ICkHDVB1RkVpin/YW2nQn/g==
|
||||||
|
dependencies:
|
||||||
|
"@jridgewell/source-map" "^0.3.3"
|
||||||
|
acorn "^8.8.2"
|
||||||
|
commander "^2.20.0"
|
||||||
|
source-map-support "~0.5.20"
|
||||||
|
|
||||||
tesseract.js-core@^2.2.0:
|
tesseract.js-core@^2.2.0:
|
||||||
version "2.2.0"
|
version "2.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/tesseract.js-core/-/tesseract.js-core-2.2.0.tgz#6ef78051272a381969fac3e45a226e85022cffef"
|
resolved "https://registry.yarnpkg.com/tesseract.js-core/-/tesseract.js-core-2.2.0.tgz#6ef78051272a381969fac3e45a226e85022cffef"
|
||||||
|
@ -12005,7 +12044,12 @@ tslib@^2.1.0:
|
||||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.1.tgz#fd8c9a0ff42590b25703c0acb3de3d3f4ede0410"
|
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.1.tgz#fd8c9a0ff42590b25703c0acb3de3d3f4ede0410"
|
||||||
integrity sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==
|
integrity sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==
|
||||||
|
|
||||||
tslib@^2.4.0, tslib@^2.5.0:
|
tslib@^2.4.0:
|
||||||
|
version "2.6.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae"
|
||||||
|
integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==
|
||||||
|
|
||||||
|
tslib@^2.5.0:
|
||||||
version "2.5.3"
|
version "2.5.3"
|
||||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.3.tgz#24944ba2d990940e6e982c4bea147aba80209913"
|
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.3.tgz#24944ba2d990940e6e982c4bea147aba80209913"
|
||||||
integrity sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==
|
integrity sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==
|
||||||
|
@ -12116,12 +12160,7 @@ typed-array-length@^1.0.4:
|
||||||
for-each "^0.3.3"
|
for-each "^0.3.3"
|
||||||
is-typed-array "^1.1.9"
|
is-typed-array "^1.1.9"
|
||||||
|
|
||||||
"typescript@^4.7 || 5":
|
"typescript@^4.7 || 5", typescript@^5.0.4:
|
||||||
version "5.1.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.1.3.tgz#8d84219244a6b40b6fb2b33cc1c062f715b9e826"
|
|
||||||
integrity sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==
|
|
||||||
|
|
||||||
typescript@^5.0.4:
|
|
||||||
version "5.2.2"
|
version "5.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.2.tgz#5ebb5e5a5b75f085f22bc3f8460fba308310fa78"
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.2.tgz#5ebb5e5a5b75f085f22bc3f8460fba308310fa78"
|
||||||
integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==
|
integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==
|
||||||
|
@ -12603,10 +12642,10 @@ webpack-sources@^1.0, webpack-sources@^1.1.0, webpack-sources@^1.4.1, webpack-so
|
||||||
source-list-map "^2.0.0"
|
source-list-map "^2.0.0"
|
||||||
source-map "~0.6.1"
|
source-map "~0.6.1"
|
||||||
|
|
||||||
webpack@^4.46.0:
|
webpack@^4.47.0:
|
||||||
version "4.46.0"
|
version "4.47.0"
|
||||||
resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.46.0.tgz#bf9b4404ea20a073605e0a011d188d77cb6ad542"
|
resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.47.0.tgz#8b8a02152d7076aeb03b61b47dad2eeed9810ebc"
|
||||||
integrity sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==
|
integrity sha512-td7fYwgLSrky3fI1EuU5cneU4+pbH6GgOfuKNS1tNPcfdGinGELAqsb/BP4nnvZyKSG2i/xFGU7+n2PvZA8HJQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@webassemblyjs/ast" "1.9.0"
|
"@webassemblyjs/ast" "1.9.0"
|
||||||
"@webassemblyjs/helper-module-context" "1.9.0"
|
"@webassemblyjs/helper-module-context" "1.9.0"
|
||||||
|
@ -13017,9 +13056,9 @@ ws@^7.3.1:
|
||||||
integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==
|
integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==
|
||||||
|
|
||||||
ws@^8.11.0, ws@^8.12.1, ws@^8.13.0:
|
ws@^8.11.0, ws@^8.12.1, ws@^8.13.0:
|
||||||
version "8.13.0"
|
version "8.14.0"
|
||||||
resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0"
|
resolved "https://registry.yarnpkg.com/ws/-/ws-8.14.0.tgz#6c5792c5316dc9266ba8e780433fc45e6680aecd"
|
||||||
integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==
|
integrity sha512-WR0RJE9Ehsio6U4TuM+LmunEsjQ5ncHlw4sn9ihD6RoJKZrVyH9FWV3dmnwu8B2aNib1OvG2X6adUCyFpQyWcg==
|
||||||
|
|
||||||
xml-name-validator@^4.0.0:
|
xml-name-validator@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue