From 53b69c584683356c7e6fcd2508c9156b51c73215 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Thu, 23 Jun 2022 17:28:28 +0900 Subject: [PATCH 001/127] prevent cursor from going out of bounds when deleting nodes --- resources/assets/lib/beatmap-discussions/editor.tsx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/resources/assets/lib/beatmap-discussions/editor.tsx b/resources/assets/lib/beatmap-discussions/editor.tsx index 450aac99e45..6e80297debe 100644 --- a/resources/assets/lib/beatmap-discussions/editor.tsx +++ b/resources/assets/lib/beatmap-discussions/editor.tsx @@ -10,7 +10,7 @@ import { route } from 'laroute'; import * as _ from 'lodash'; import core from 'osu-core-singleton'; import * as React from 'react'; -import { createEditor, Element as SlateElement, Node as SlateNode, NodeEntry, Range, Text, Transforms } from 'slate'; +import { createEditor, Editor as SlateEditor, Element as SlateElement, Node as SlateNode, NodeEntry, Range, Text, Transforms } from 'slate'; import { withHistory } from 'slate-history'; import { Editable, ReactEditor, RenderElementProps, RenderLeafProps, Slate, withReact } from 'slate-react'; import { onError } from 'utils/ajax'; @@ -182,8 +182,10 @@ export default class Editor extends React.Component { ); onChange = (value: SlateElement[]) => { - // prevent document from becoming empty (and invalid) - ideally this would be handled in `withNormalization`, but that isn't run on every change + // Prevent document from becoming empty (and invalid) - ideally this would be handled in `withNormalization`, but that isn't run on every change + // This is a final resort and should be avoided; anything that triggers this needs to be fixed! if (value.length === 0) { + console.error('value is empty in Editor.onChange'); value = this.emptyDocTemplate; } @@ -227,6 +229,11 @@ export default class Editor extends React.Component { } else if (isHotkey('delete', event) || isHotkey('backspace', event)) { if (insideEmptyNode(this.slateEditor)) { event.preventDefault(); + if (this.slateEditor.children.length === 1) { + // Insert a blank paragraph to prevent Slate's cursor from going OOB and other weird things. + Transforms.insertNodes(this.slateEditor, { children: [{ text: '' }], type: 'paragraph' }, { at: SlateEditor.start(this.slateEditor, []) }); + } + Transforms.removeNodes(this.slateEditor); } } From 36f497b4bb889bf563f46aee1676c101f4380643 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Thu, 23 Jun 2022 17:43:42 +0900 Subject: [PATCH 002/127] make default empty paragraph readonly. empty document needs to be mutable for initialValue assignment --- resources/assets/lib/beatmap-discussions/editor.tsx | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/resources/assets/lib/beatmap-discussions/editor.tsx b/resources/assets/lib/beatmap-discussions/editor.tsx index 6e80297debe..f3eb3545e94 100644 --- a/resources/assets/lib/beatmap-discussions/editor.tsx +++ b/resources/assets/lib/beatmap-discussions/editor.tsx @@ -63,6 +63,9 @@ interface TimestampRange extends Range { timestamp: string; } +const emptyParagraph = Object.freeze({ children: [{ text: '' }], type: 'paragraph' }); +const emptyDocTemplate = [emptyParagraph]; + export default class Editor extends React.Component { static contextType = ReviewEditorConfigContext; static defaultProps = { @@ -72,7 +75,6 @@ export default class Editor extends React.Component { bn = 'beatmap-discussion-editor'; cache: CacheInterface = {}; declare context: React.ContextType; - emptyDocTemplate = [{ children: [{ text: '' }], type: 'paragraph' }]; insertMenuRef: React.RefObject; localStorageKey: string; scrollContainerRef: React.RefObject; @@ -89,7 +91,7 @@ export default class Editor extends React.Component { this.insertMenuRef = React.createRef(); this.localStorageKey = `newDiscussion-${this.props.beatmapset.id}`; - let initialValue: SlateElement[] = this.emptyDocTemplate; + let initialValue: SlateElement[] = emptyDocTemplate; if (props.editMode) { initialValue = this.valueFromProps(); @@ -186,7 +188,7 @@ export default class Editor extends React.Component { // This is a final resort and should be avoided; anything that triggers this needs to be fixed! if (value.length === 0) { console.error('value is empty in Editor.onChange'); - value = this.emptyDocTemplate; + value = emptyDocTemplate; } if (!this.props.editMode) { @@ -231,7 +233,7 @@ export default class Editor extends React.Component { event.preventDefault(); if (this.slateEditor.children.length === 1) { // Insert a blank paragraph to prevent Slate's cursor from going OOB and other weird things. - Transforms.insertNodes(this.slateEditor, { children: [{ text: '' }], type: 'paragraph' }, { at: SlateEditor.start(this.slateEditor, []) }); + Transforms.insertNodes(this.slateEditor, emptyParagraph, { at: SlateEditor.start(this.slateEditor, []) }); } Transforms.removeNodes(this.slateEditor); @@ -398,7 +400,7 @@ export default class Editor extends React.Component { } Transforms.deselect(this.slateEditor); - this.onChange(this.emptyDocTemplate); + this.onChange(emptyDocTemplate); }; serialize = () => serializeSlateDocument(this.state.value); From af95d016e21469843cb313a338d7c35bb345dc6f Mon Sep 17 00:00:00 2001 From: bakaneko Date: Thu, 23 Jun 2022 18:35:06 +0900 Subject: [PATCH 003/127] add a note about resetInput (onChange should not be triggered directly) --- resources/assets/lib/beatmap-discussions/editor.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/assets/lib/beatmap-discussions/editor.tsx b/resources/assets/lib/beatmap-discussions/editor.tsx index f3eb3545e94..65eade2383e 100644 --- a/resources/assets/lib/beatmap-discussions/editor.tsx +++ b/resources/assets/lib/beatmap-discussions/editor.tsx @@ -399,6 +399,7 @@ export default class Editor extends React.Component { } } + // FIXME: should use Tranforms to delete content instead of triggering onChange. Transforms.deselect(this.slateEditor); this.onChange(emptyDocTemplate); }; From af0e7846cc6af2b3e38e93da4d7182902c44d558 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Thu, 23 Jun 2022 18:45:21 +0900 Subject: [PATCH 004/127] update slate --- package.json | 6 ++--- yarn.lock | 67 +++++++++++++++++++++++----------------------------- 2 files changed, 33 insertions(+), 40 deletions(-) diff --git a/package.json b/package.json index a216b397cff..860aa5c64aa 100644 --- a/package.json +++ b/package.json @@ -76,9 +76,9 @@ "react-transition-group": "^4.4.2", "remark-parse": "^7.0.1", "shopify-buy": "^2.6.1", - "slate": "^0.58.4", - "slate-history": "^0.58.4", - "slate-react": "^0.58.4", + "slate": "^0.81.1", + "slate-history": "^0.66.0", + "slate-react": "^0.81.0", "terser": "^3.11.0", "terser-webpack-plugin": "^1.4.1", "timeago": "^1.5.0", diff --git a/yarn.lock b/yarn.lock index b0ada3e11c7..79c048c6d77 100644 --- a/yarn.lock +++ b/yarn.lock @@ -509,11 +509,6 @@ "@types/d3-transition" "*" "@types/d3-zoom" "*" -"@types/esrever@^0.2.0": - version "0.2.0" - resolved "https://registry.yarnpkg.com/@types/esrever/-/esrever-0.2.0.tgz#96404a2284b2c7527f08a1e957f8a31705f9880f" - integrity sha512-5NI6TeGzVEy/iBcuYtcPzzIC6EqlfQ2+UZ54vT0ulq8bPNGAy8UJD+XcsAyEOcnYFUjOVWuUV+k4/rVkxt9/XQ== - "@types/geojson@*": version "7946.0.7" resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.7.tgz#c8fa532b60a0042219cdf173ca21a975ef0666ad" @@ -3356,11 +3351,6 @@ esrecurse@^4.1.0, esrecurse@^4.3.0: dependencies: estraverse "^5.2.0" -esrever@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/esrever/-/esrever-0.2.0.tgz#96e9d28f4f1b1a76784cd5d490eaae010e7407b8" - integrity sha1-lunSj08bGnZ4TNXUkOquAQ50B7g= - estraverse@^4.1.1: version "4.3.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" @@ -4275,10 +4265,10 @@ img-loader@^3.0.1: dependencies: loader-utils "^1.1.0" -immer@^5.0.0: - version "5.3.6" - resolved "https://registry.yarnpkg.com/immer/-/immer-5.3.6.tgz#51eab8cbbeb13075fe2244250f221598818cac04" - integrity sha512-pqWQ6ozVfNOUDjrLfm4Pt7q4Q12cGw2HUZgry4Q5+Myxu9nmHRkWBpI0J4+MK0AxbdFtdMTwEGVl7Vd+vEiK+A== +immer@^9.0.6: + version "9.0.15" + resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.15.tgz#0b9169e5b1d22137aba7d43f8a81a495dd1b62dc" + integrity sha512-2eB/sswms9AEUSkOm4SbV5Y7Vmt/bKRwByd52jfLkW4OLYeaTP3EEiJ9agqU0O/tq6Dk62Zfj+TJSqfm1rLVGQ== import-cwd@^2.0.0: version "2.1.0" @@ -4697,10 +4687,10 @@ is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" -is-plain-object@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-3.0.1.tgz#662d92d24c0aa4302407b0d45d21f2251c85f85b" - integrity sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g== +is-plain-object@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" + integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== is-regex@^1.1.4: version "1.1.4" @@ -7546,36 +7536,34 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -slate-history@^0.58.4: - version "0.58.4" - resolved "https://registry.yarnpkg.com/slate-history/-/slate-history-0.58.4.tgz#f24f4745f192e8eb16975037536bdc22f6d1c03b" - integrity sha512-QWmVvB02R+Z+I8sC7Hb+27Zqtm1vDt9kulHjmqRk8ixPp7052S04q4WEjNsk0StrgmEOEd+POvzNGfOYELXitw== +slate-history@^0.66.0: + version "0.66.0" + resolved "https://registry.yarnpkg.com/slate-history/-/slate-history-0.66.0.tgz#ac63fddb903098ceb4c944433e3f75fe63acf940" + integrity sha512-6MWpxGQZiMvSINlCbMW43E2YBSVMCMCIwQfBzGssjWw4kb0qfvj0pIdblWNRQZD0hR6WHP+dHHgGSeVdMWzfng== dependencies: - immer "^5.0.0" - is-plain-object "^3.0.0" + is-plain-object "^5.0.0" -slate-react@^0.58.4: - version "0.58.4" - resolved "https://registry.yarnpkg.com/slate-react/-/slate-react-0.58.4.tgz#ecde34dd322af8413c2f23f0f0a577fed2422f46" - integrity sha512-3JXWHVPmYrR/EMcH1qtmwXZtYxxCtuokQg+r/4wD1Ab9J3zRmW4UGLoaRP9/uQrZOAOvr8mMh4IgmrxV2dQskw== +slate-react@^0.81.0: + version "0.81.0" + resolved "https://registry.yarnpkg.com/slate-react/-/slate-react-0.81.0.tgz#248eb688ce01f23680ce2554625fd60676614962" + integrity sha512-bwryad4EvOmc7EFKb8aGg9DWNDh3KvToaggGieIgGTTbHJYHc9ADFC3A87Ittlpd5XUVopR0MpChQ3g3ODyvqw== dependencies: "@types/is-hotkey" "^0.1.1" "@types/lodash" "^4.14.149" direction "^1.0.3" is-hotkey "^0.1.6" - is-plain-object "^3.0.0" + is-plain-object "^5.0.0" lodash "^4.17.4" scroll-into-view-if-needed "^2.2.20" + tiny-invariant "1.0.6" -slate@^0.58.4: - version "0.58.4" - resolved "https://registry.yarnpkg.com/slate/-/slate-0.58.4.tgz#4259387e632b45b00cf88bcecf5570d7d16ddd8b" - integrity sha512-XxKwNJgCMf7S2sDT8CVJy0zYm95MiYorJo9Hah05zKjItrw0VVeCc2BGKDZSlNGcaIfM3xcfFUN7XE+c8ehAbA== +slate@^0.81.1: + version "0.81.1" + resolved "https://registry.yarnpkg.com/slate/-/slate-0.81.1.tgz#98d9f87b1ea2d648bfbab2739dcb1ba897f3bba0" + integrity sha512-nmqphQb2qnlJpPMKsoxeWShpa+pOlKfy6XVdmlTuOtgWeGethM6SMPSRTrhh5UF/G+3/IoXhfbKF7o3iDZCbWw== dependencies: - "@types/esrever" "^0.2.0" - esrever "^0.2.0" - immer "^5.0.0" - is-plain-object "^3.0.0" + immer "^9.0.6" + is-plain-object "^5.0.0" tiny-warning "^1.0.3" slice-ansi@^4.0.0: @@ -8119,6 +8107,11 @@ timsort@^0.3.0: resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= +tiny-invariant@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.0.6.tgz#b3f9b38835e36a41c843a3b0907a5a7b3755de73" + integrity sha512-FOyLWWVjG+aC0UqG76V53yAWdXfH8bO6FNmyZOuUrzDzK8DI3/JRY25UD7+g49JWM1LXwymsKERB+DzI0dTEQA== + tiny-warning@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" From 46c2e1bc1bbb50e1491ba35ecb1dc0c03036c46a Mon Sep 17 00:00:00 2001 From: bakaneko Date: Thu, 23 Jun 2022 18:47:53 +0900 Subject: [PATCH 005/127] clear nodes the proper way --- resources/assets/lib/beatmap-discussions/editor.tsx | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/resources/assets/lib/beatmap-discussions/editor.tsx b/resources/assets/lib/beatmap-discussions/editor.tsx index 65eade2383e..1f21b97c36f 100644 --- a/resources/assets/lib/beatmap-discussions/editor.tsx +++ b/resources/assets/lib/beatmap-discussions/editor.tsx @@ -399,9 +399,14 @@ export default class Editor extends React.Component { } } - // FIXME: should use Tranforms to delete content instead of triggering onChange. - Transforms.deselect(this.slateEditor); - this.onChange(emptyDocTemplate); + Transforms.delete(this.slateEditor, { + at: { + anchor: SlateEditor.start(this.slateEditor, []), + focus: SlateEditor.end(this.slateEditor, []), + }, + hanging: true, + voids: true, + }); }; serialize = () => serializeSlateDocument(this.state.value); From 78d047b51466d4fb330f4dd6db6c8c720a04cc5f Mon Sep 17 00:00:00 2001 From: bakaneko Date: Thu, 23 Jun 2022 19:06:57 +0900 Subject: [PATCH 006/127] placeholder too wide --- resources/assets/less/bem/beatmap-discussion-editor.less | 2 ++ 1 file changed, 2 insertions(+) diff --git a/resources/assets/less/bem/beatmap-discussion-editor.less b/resources/assets/less/bem/beatmap-discussion-editor.less index 690e4cae1b5..f10c01e5a53 100644 --- a/resources/assets/less/bem/beatmap-discussion-editor.less +++ b/resources/assets/less/bem/beatmap-discussion-editor.less @@ -16,6 +16,8 @@ } &__block { + position: relative; // Slate's placeholder element has width: 100% directly set on it... + .@{_top}--readonly & { &:hover .@{_top}__hover-menu { display: none; From 0656e5f13f018d50f0c0c4f0636d8843cde11a34 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Thu, 23 Jun 2022 19:44:52 +0900 Subject: [PATCH 007/127] update editor typing --- .../assets/lib/beatmap-discussions/editor.tsx | 8 +++--- resources/assets/lib/editor.d.ts | 27 +++++++++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 resources/assets/lib/editor.d.ts diff --git a/resources/assets/lib/beatmap-discussions/editor.tsx b/resources/assets/lib/beatmap-discussions/editor.tsx index 1f21b97c36f..c1c7838609a 100644 --- a/resources/assets/lib/beatmap-discussions/editor.tsx +++ b/resources/assets/lib/beatmap-discussions/editor.tsx @@ -78,14 +78,16 @@ export default class Editor extends React.Component { insertMenuRef: React.RefObject; localStorageKey: string; scrollContainerRef: React.RefObject; - slateEditor: ReactEditor; + slateEditor: SlateEditor; toolbarRef: React.RefObject; private xhr?: JQueryXHR | null; constructor(props: Props) { super(props); - this.slateEditor = this.withNormalization(withHistory(withReact(createEditor()))); + // Slate editor typing is weird + // https://docs.slatejs.org/concepts/12-typescript#defining-editor-element-and-text-types + this.slateEditor = this.withNormalization(withReact(withHistory(createEditor()))); this.scrollContainerRef = React.createRef(); this.toolbarRef = React.createRef(); this.insertMenuRef = React.createRef(); @@ -446,7 +448,7 @@ export default class Editor extends React.Component { this.cache.draftEmbeds = this.state.value.filter((block) => block.type === 'embed' && !block.discussion_id); }; - withNormalization = (editor: ReactEditor) => { + withNormalization = (editor: SlateEditor) => { const { insertData, normalizeNode } = editor; editor.insertData = (data) => { diff --git a/resources/assets/lib/editor.d.ts b/resources/assets/lib/editor.d.ts new file mode 100644 index 00000000000..928ce66e42f --- /dev/null +++ b/resources/assets/lib/editor.d.ts @@ -0,0 +1,27 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the GNU Affero General Public License v3.0. +// See the LICENCE file in the repository root for full licence text. + +import { BaseEditor, BaseElement } from 'slate'; +import { HistoryEditor } from 'slate-history'; +import { ReactEditor } from 'slate-react'; + +interface EmbedElement extends BaseElement { + beatmapId: number; + discussionId?: number; + discussionType: string; + type: 'embed'; +} + +interface ParagraphElement extends BaseElement { + type: 'paragraph'; +} + +type CustomEditor = BaseEditor & ReactEditor & HistoryEditor; +type CustomElement = EmbedElement | ParagraphElement; + +declare module 'slate' { + interface CustomTypes { + Editor: CustomEditor; + Element: CustomElement; + } +} From 0be241c0b32507829f54f02f5092c47a29d98470 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Thu, 23 Jun 2022 20:50:38 +0900 Subject: [PATCH 008/127] update context type --- .../assets/lib/beatmap-discussions/editor-insertion-menu.tsx | 2 +- resources/assets/lib/beatmap-discussions/slate-context.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/assets/lib/beatmap-discussions/editor-insertion-menu.tsx b/resources/assets/lib/beatmap-discussions/editor-insertion-menu.tsx index 18cde89d9fb..687012ab695 100644 --- a/resources/assets/lib/beatmap-discussions/editor-insertion-menu.tsx +++ b/resources/assets/lib/beatmap-discussions/editor-insertion-menu.tsx @@ -154,7 +154,7 @@ export class EditorInsertionMenu extends React.Component { }; private insertBlock = (event: React.MouseEvent) => { - const ed: ReactEditor = this.context; + const ed = this.context; const slateNodeElement = this.hoveredBlock?.lastChild; const type = event.currentTarget.dataset.discussionType; const beatmapId = this.props.currentBeatmap?.id; diff --git a/resources/assets/lib/beatmap-discussions/slate-context.ts b/resources/assets/lib/beatmap-discussions/slate-context.ts index 504a5f033cb..a277c6244c7 100644 --- a/resources/assets/lib/beatmap-discussions/slate-context.ts +++ b/resources/assets/lib/beatmap-discussions/slate-context.ts @@ -2,9 +2,9 @@ // See the LICENCE file in the repository root for full licence text. import * as React from 'react'; -import { ReactEditor } from 'slate-react'; +import { Editor } from 'slate'; // null! is a workaround to remove the optional/nullable type for the context. // SlateContext should always be assigned a ReactEditor value before being used. // TODO: figure out how to remove the props dependency in editor.tsx when for initializing? -export const SlateContext = React.createContext(null!); +export const SlateContext = React.createContext(null!); From 1f744dbf32d478347479f0cb846916eda7c48cec Mon Sep 17 00:00:00 2001 From: bakaneko Date: Thu, 23 Jun 2022 21:02:22 +0900 Subject: [PATCH 009/127] EditorDiscussionComponent only takes embeds --- .../beatmap-discussions/editor-discussion-component.tsx | 2 ++ resources/assets/lib/beatmap-discussions/editor.tsx | 8 +++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/resources/assets/lib/beatmap-discussions/editor-discussion-component.tsx b/resources/assets/lib/beatmap-discussions/editor-discussion-component.tsx index fe54f4e3bbb..048478adeed 100644 --- a/resources/assets/lib/beatmap-discussions/editor-discussion-component.tsx +++ b/resources/assets/lib/beatmap-discussions/editor-discussion-component.tsx @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the GNU Affero General Public License v3.0. // See the LICENCE file in the repository root for full licence text. +import { EmbedElement } from 'editor'; import { BeatmapReviewDiscussionType } from 'interfaces/beatmap-discussion-review'; import BeatmapExtendedJson from 'interfaces/beatmap-extended-json'; import BeatmapsetJson from 'interfaces/beatmapset-json'; @@ -31,6 +32,7 @@ interface Props extends RenderElementProps { discussionId?: number; discussions: Partial>; editMode?: boolean; + element: EmbedElement; readOnly?: boolean; } diff --git a/resources/assets/lib/beatmap-discussions/editor.tsx b/resources/assets/lib/beatmap-discussions/editor.tsx index c1c7838609a..5adf8f02c9e 100644 --- a/resources/assets/lib/beatmap-discussions/editor.tsx +++ b/resources/assets/lib/beatmap-discussions/editor.tsx @@ -352,7 +352,8 @@ export default class Editor extends React.Component { let el; switch (props.element.type) { - case 'embed': + case 'embed': { + const { element, ...otherProps } = props; // spreading ..props doesn't use the narrower type. el = ( { currentBeatmap={this.props.currentBeatmap} discussions={this.props.discussions} editMode={this.props.editMode} + element={element} readOnly={this.state.posting} - {...props} + {...otherProps} /> ); break; - + } default: el = props.children; } From 62f7b2ca6386ca41ebf52b8fe561dcf12c2dbb90 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Fri, 24 Jun 2022 18:23:40 +0900 Subject: [PATCH 010/127] mostly EditorDiscussionComponent type fixes --- .../editor-beatmap-selector.tsx | 5 ++- .../editor-discussion-component.tsx | 38 ++++++++----------- .../editor-issue-type-selector.tsx | 7 ++-- resources/assets/lib/editor.d.ts | 4 +- 4 files changed, 26 insertions(+), 28 deletions(-) diff --git a/resources/assets/lib/beatmap-discussions/editor-beatmap-selector.tsx b/resources/assets/lib/beatmap-discussions/editor-beatmap-selector.tsx index bed22ecd631..7ca5dd0a9ee 100644 --- a/resources/assets/lib/beatmap-discussions/editor-beatmap-selector.tsx +++ b/resources/assets/lib/beatmap-discussions/editor-beatmap-selector.tsx @@ -3,9 +3,10 @@ import { BeatmapIcon } from 'components/beatmap-icon'; import BeatmapListItem from 'components/beatmap-list-item'; +import { EmbedElement } from 'editor'; import BeatmapExtendedJson from 'interfaces/beatmap-extended-json'; import * as React from 'react'; -import { Node, Transforms } from 'slate'; +import { Transforms } from 'slate'; import { ReactEditor } from 'slate-react'; import { classWithModifiers } from 'utils/css'; import IconDropdownMenu, { MenuItem } from './icon-dropdown-menu'; @@ -14,7 +15,7 @@ import { SlateContext } from './slate-context'; interface Props { beatmaps: BeatmapExtendedJson[]; disabled: boolean; - element: Node; + element: EmbedElement; } export default class EditorBeatmapSelector extends React.Component { diff --git a/resources/assets/lib/beatmap-discussions/editor-discussion-component.tsx b/resources/assets/lib/beatmap-discussions/editor-discussion-component.tsx index 048478adeed..3b3e2ac6498 100644 --- a/resources/assets/lib/beatmap-discussions/editor-discussion-component.tsx +++ b/resources/assets/lib/beatmap-discussions/editor-discussion-component.tsx @@ -2,12 +2,11 @@ // See the LICENCE file in the repository root for full licence text. import { EmbedElement } from 'editor'; -import { BeatmapReviewDiscussionType } from 'interfaces/beatmap-discussion-review'; import BeatmapExtendedJson from 'interfaces/beatmap-extended-json'; import BeatmapsetJson from 'interfaces/beatmapset-json'; -import * as _ from 'lodash'; +import { filter } from 'lodash'; import * as React from 'react'; -import { Element as SlateElement, Path, Transforms } from 'slate'; +import { Element as SlateElement, Transforms } from 'slate'; import { RenderElementProps } from 'slate-react'; import { ReactEditor } from 'slate-react'; import { classWithModifiers } from 'utils/css'; @@ -148,7 +147,7 @@ export default class EditorDiscussionComponent extends React.Component { }; // FIXME: element should be typed properly instead. - discussionType = () => this.props.element.discussionType as BeatmapReviewDiscussionType; + discussionType = () => this.props.element.discussionType; editable = () => !(this.props.editMode && this.props.element.discussionId); @@ -163,7 +162,7 @@ export default class EditorDiscussionComponent extends React.Component { } if (!this.cache.nearbyDiscussions || this.cache.nearbyDiscussions.timestamp !== timestamp || (this.cache.nearbyDiscussions.beatmap_id !== this.selectedBeatmap())) { - const relevantDiscussions = _.filter(this.props.discussions, this.isRelevantDiscussion); + const relevantDiscussions = filter(this.props.discussions, this.isRelevantDiscussion); this.cache.nearbyDiscussions = { beatmap_id: this.selectedBeatmap(), discussions: BeatmapDiscussionHelper.nearbyDiscussions(relevantDiscussions, timestamp), @@ -174,7 +173,7 @@ export default class EditorDiscussionComponent extends React.Component { return this.cache.nearbyDiscussions?.discussions; }; - nearbyDraftEmbeds = (drafts: SlateElement[]) => { + nearbyDraftEmbeds = (drafts: EmbedElement[]) => { const timestamp = this.timestamp(); if (timestamp == null || drafts.length === 0) { return; @@ -185,7 +184,7 @@ export default class EditorDiscussionComponent extends React.Component { return false; } - const ts = BeatmapDiscussionHelper.parseTimestamp(embed.timestamp as string); + const ts = BeatmapDiscussionHelper.parseTimestamp(embed.timestamp); if (ts == null) { return false; } @@ -250,20 +249,13 @@ export default class EditorDiscussionComponent extends React.Component { } }; - path = (): Path => ReactEditor.findPath(this.context, this.props.element); + path = () => ReactEditor.findPath(this.context, this.props.element); - render(): React.ReactNode { + render() { const canEdit = this.editable(); const classMods = canEdit ? [] : ['read-only']; - let timestamp = this.props.element.timestamp as string | undefined; - let timestampTooltipType: string; - if (this.props.element.beatmapId != null) { - timestampTooltipType = 'diff'; - } else { - timestampTooltipType = 'all-diff'; - timestamp = undefined; - } + const timestampTooltipType = this.props.element.beatmapId != null ? 'diff' : 'all-diff'; const timestampTooltip = osu.trans(`beatmaps.discussions.review.embed.timestamp.${timestampTooltipType}`, { type: osu.trans(`beatmaps.discussions.message_type.${this.discussionType()}`), @@ -298,6 +290,8 @@ export default class EditorDiscussionComponent extends React.Component { ) : null; + const disabled = this.props.readOnly || !canEdit; + return (
{ className={`${this.bn}__selectors`} contentEditable={false} // workaround for slatejs 'Cannot resolve a Slate point from DOM point' nonsense > - - + +
- {timestamp ?? osu.trans('beatmap_discussions.timestamp_display.general')} + {this.selectedBeatmap() != null ? this.props.element.timestamp : osu.trans('beatmap_discussions.timestamp_display.general')}
{unsavedIndicator} @@ -340,7 +334,7 @@ export default class EditorDiscussionComponent extends React.Component { ); } - selectedBeatmap = () => this.props.element.beatmapId as number; + selectedBeatmap = () => this.props.element.beatmapId; - timestamp = () => BeatmapDiscussionHelper.parseTimestamp(this.props.element.timestamp as string | undefined); + timestamp = () => BeatmapDiscussionHelper.parseTimestamp(this.props.element.timestamp); } diff --git a/resources/assets/lib/beatmap-discussions/editor-issue-type-selector.tsx b/resources/assets/lib/beatmap-discussions/editor-issue-type-selector.tsx index 7b982f283cf..d227cdc5136 100644 --- a/resources/assets/lib/beatmap-discussions/editor-issue-type-selector.tsx +++ b/resources/assets/lib/beatmap-discussions/editor-issue-type-selector.tsx @@ -2,10 +2,11 @@ // See the LICENCE file in the repository root for full licence text. import { DiscussionType, discussionTypeIcons } from 'beatmap-discussions/discussion-type'; +import { EmbedElement } from 'editor'; import { BeatmapReviewDiscussionType } from 'interfaces/beatmap-discussion-review'; import BeatmapExtendedJson from 'interfaces/beatmap-extended-json'; import * as React from 'react'; -import { Element, Transforms } from 'slate'; +import { Transforms } from 'slate'; import { ReactEditor } from 'slate-react'; import IconDropdownMenu, { MenuItem } from './icon-dropdown-menu'; import { SlateContext } from './slate-context'; @@ -15,7 +16,7 @@ const selectableTypes: DiscussionType[] = ['praise', 'problem', 'suggestion']; interface Props { beatmaps: BeatmapExtendedJson[]; disabled: boolean; - element: Element; + element: EmbedElement; } export default class EditorIssueTypeSelector extends React.Component { @@ -34,7 +35,7 @@ export default class EditorIssueTypeSelector extends React.Component { disabled={this.props.disabled} menuOptions={menuOptions} onSelect={this.select} - selected={this.props.element.discussionType as BeatmapReviewDiscussionType} + selected={this.props.element.discussionType} /> ); } diff --git a/resources/assets/lib/editor.d.ts b/resources/assets/lib/editor.d.ts index 928ce66e42f..e782813d0e2 100644 --- a/resources/assets/lib/editor.d.ts +++ b/resources/assets/lib/editor.d.ts @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the GNU Affero General Public License v3.0. // See the LICENCE file in the repository root for full licence text. +import { BeatmapReviewDiscussionType } from 'interfaces/beatmap-discussion-review'; import { BaseEditor, BaseElement } from 'slate'; import { HistoryEditor } from 'slate-history'; import { ReactEditor } from 'slate-react'; @@ -8,7 +9,8 @@ import { ReactEditor } from 'slate-react'; interface EmbedElement extends BaseElement { beatmapId: number; discussionId?: number; - discussionType: string; + discussionType: BeatmapReviewDiscussionType; + timestamp?: string; type: 'embed'; } From d4069c07a4eceffa48eaae5675980053cc245a96 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Fri, 24 Jun 2022 18:54:53 +0900 Subject: [PATCH 011/127] import function directly --- resources/assets/lib/beatmap-discussions/editor.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/assets/lib/beatmap-discussions/editor.tsx b/resources/assets/lib/beatmap-discussions/editor.tsx index 5adf8f02c9e..f88616559fa 100644 --- a/resources/assets/lib/beatmap-discussions/editor.tsx +++ b/resources/assets/lib/beatmap-discussions/editor.tsx @@ -7,7 +7,7 @@ import BeatmapExtendedJson from 'interfaces/beatmap-extended-json'; import BeatmapsetJson from 'interfaces/beatmapset-json'; import isHotkey from 'is-hotkey'; import { route } from 'laroute'; -import * as _ from 'lodash'; +import { filter } from 'lodash'; import core from 'osu-core-singleton'; import * as React from 'react'; import { createEditor, Editor as SlateEditor, Element as SlateElement, Node as SlateNode, NodeEntry, Range, Text, Transforms } from 'slate'; @@ -439,7 +439,7 @@ export default class Editor extends React.Component { sortedBeatmaps = () => { if (this.cache.sortedBeatmaps == null) { // filter to only include beatmaps from the current discussion's beatmapset (for the modding profile page) - const beatmaps = _.filter(this.props.beatmaps, this.isCurrentBeatmap); + const beatmaps = filter(this.props.beatmaps, this.isCurrentBeatmap); this.cache.sortedBeatmaps = sortWithMode(beatmaps); } From 1390786c7d301427854ba8542080b08b9c0bc2e7 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Fri, 24 Jun 2022 18:56:37 +0900 Subject: [PATCH 012/127] fix DraftsContext type. Also fix the filtering --- .../assets/lib/beatmap-discussions/drafts-context.ts | 4 ++-- .../beatmap-discussions/editor-discussion-component.tsx | 4 ++-- resources/assets/lib/beatmap-discussions/editor.tsx | 9 +++++++-- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/resources/assets/lib/beatmap-discussions/drafts-context.ts b/resources/assets/lib/beatmap-discussions/drafts-context.ts index 22ec7102f5d..c2b0b4d53e4 100644 --- a/resources/assets/lib/beatmap-discussions/drafts-context.ts +++ b/resources/assets/lib/beatmap-discussions/drafts-context.ts @@ -1,7 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the GNU Affero General Public License v3.0. // See the LICENCE file in the repository root for full licence text. +import { EmbedElement } from 'editor'; import * as React from 'react'; -import { Element as SlateElement } from 'slate'; -export const DraftsContext = React.createContext([]); +export const DraftsContext = React.createContext([]); diff --git a/resources/assets/lib/beatmap-discussions/editor-discussion-component.tsx b/resources/assets/lib/beatmap-discussions/editor-discussion-component.tsx index 3b3e2ac6498..b14fa164b79 100644 --- a/resources/assets/lib/beatmap-discussions/editor-discussion-component.tsx +++ b/resources/assets/lib/beatmap-discussions/editor-discussion-component.tsx @@ -6,7 +6,7 @@ import BeatmapExtendedJson from 'interfaces/beatmap-extended-json'; import BeatmapsetJson from 'interfaces/beatmapset-json'; import { filter } from 'lodash'; import * as React from 'react'; -import { Element as SlateElement, Transforms } from 'slate'; +import { Transforms } from 'slate'; import { RenderElementProps } from 'slate-react'; import { ReactEditor } from 'slate-react'; import { classWithModifiers } from 'utils/css'; @@ -193,7 +193,7 @@ export default class EditorDiscussionComponent extends React.Component { }); }; - nearbyIndicator = (drafts: SlateElement[]) => { + nearbyIndicator = (drafts: EmbedElement[]) => { if (this.timestamp() == null || this.discussionType() === 'praise') { return; } diff --git a/resources/assets/lib/beatmap-discussions/editor.tsx b/resources/assets/lib/beatmap-discussions/editor.tsx index f88616559fa..d320da79c1c 100644 --- a/resources/assets/lib/beatmap-discussions/editor.tsx +++ b/resources/assets/lib/beatmap-discussions/editor.tsx @@ -3,6 +3,7 @@ import { CircularProgress } from 'components/circular-progress'; import { Spinner } from 'components/spinner'; +import { EmbedElement } from 'editor'; import BeatmapExtendedJson from 'interfaces/beatmap-extended-json'; import BeatmapsetJson from 'interfaces/beatmapset-json'; import isHotkey from 'is-hotkey'; @@ -35,7 +36,7 @@ import { ReviewEditorConfigContext } from './review-editor-config-context'; import { SlateContext } from './slate-context'; interface CacheInterface { - draftEmbeds?: SlateElement[]; + draftEmbeds?: EmbedElement[]; sortedBeatmaps?: BeatmapExtendedJson[]; } @@ -66,6 +67,10 @@ interface TimestampRange extends Range { const emptyParagraph = Object.freeze({ children: [{ text: '' }], type: 'paragraph' }); const emptyDocTemplate = [emptyParagraph]; +function isDraftEmbed(block: SlateElement): block is EmbedElement { + return block.type === 'embed' && block.discussionId == null; +} + export default class Editor extends React.Component { static contextType = ReviewEditorConfigContext; static defaultProps = { @@ -447,7 +452,7 @@ export default class Editor extends React.Component { }; updateDrafts = () => { - this.cache.draftEmbeds = this.state.value.filter((block) => block.type === 'embed' && !block.discussion_id); + this.cache.draftEmbeds = this.state.value.filter(isDraftEmbed); }; withNormalization = (editor: SlateEditor) => { From 288e64c63ace673a3ff5921136f6c7f7d298ac48 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Fri, 24 Jun 2022 20:19:34 +0900 Subject: [PATCH 013/127] correct typing for review document node parsing --- .../beatmap-discussions/review-document.ts | 55 ++++++++++--------- resources/assets/lib/editor.d.ts | 6 ++ 2 files changed, 35 insertions(+), 26 deletions(-) diff --git a/resources/assets/lib/beatmap-discussions/review-document.ts b/resources/assets/lib/beatmap-discussions/review-document.ts index 938fe941d9b..6e496f4b6f7 100644 --- a/resources/assets/lib/beatmap-discussions/review-document.ts +++ b/resources/assets/lib/beatmap-discussions/review-document.ts @@ -2,14 +2,29 @@ // See the LICENCE file in the repository root for full licence text. import * as markdown from 'remark-parse'; -import { Node as SlateNode } from 'slate'; +import { Element, Text } from 'slate'; import * as unified from 'unified'; -import type { Node as UnistNode } from 'unist'; +import type { Parent, Node as UnistNode } from 'unist'; import { BeatmapDiscussionReview, PersistedDocumentIssueEmbed } from '../interfaces/beatmap-discussion-review'; import { disableTokenizersPlugin } from './disable-tokenizers-plugin'; interface ParsedDocumentNode extends UnistNode { - children: SlateNode[]; + children: UnistNode[]; + // position: we don't care about position + type: 'root'; +} + +interface TextNode extends UnistNode { + type: 'text'; + value: string; +} + +function isParentNode(node: UnistNode): node is Parent { + return Array.isArray(node.children); +} + +function isText(node: UnistNode): node is TextNode { + return node.type === 'text'; } export function parseFromJson(json: string, discussions: Partial>) { @@ -31,7 +46,7 @@ export function parseFromJson(json: string, discussions: Partial { switch (block.type) { // paragraph @@ -96,40 +111,28 @@ export function parseFromJson(json: string, discussions: Partial text (with bold and italic properties set) // -function squash(items: SlateNode[], currentMarks?: {bold: boolean; italic: boolean}) { - let flat: SlateNode[] = []; +function squash(items: (UnistNode | Parent)[], currentMarks?: { bold: boolean; italic: boolean }) { + let flat: Text[] = []; const marks = currentMarks ?? { bold: false, italic: false, }; - if (!items) { - return [{text: ''}]; - } - - items.forEach((item: SlateNode) => { + items.forEach((item) => { const newMarks = { bold: marks.bold || item.type === 'strong', italic: marks.italic || item.type === 'emphasis', }; - if (Array.isArray(item.children)) { + if (isParentNode(item)) { flat = flat.concat(squash(item.children, newMarks)); - } else { - const newItem: SlateNode = { - text: (item.value as string) || '', - }; - - if (newMarks.bold) { - newItem.bold = true; - } - - if (newMarks.italic) { - newItem.italic = true; - } - flat.push(newItem); + } else if (isText(item)) { + flat.push({ + bold: newMarks.bold, + italic: newMarks.italic, + text: item.value, + }); } - }); return flat; diff --git a/resources/assets/lib/editor.d.ts b/resources/assets/lib/editor.d.ts index e782813d0e2..00f81e38ea6 100644 --- a/resources/assets/lib/editor.d.ts +++ b/resources/assets/lib/editor.d.ts @@ -20,10 +20,16 @@ interface ParagraphElement extends BaseElement { type CustomEditor = BaseEditor & ReactEditor & HistoryEditor; type CustomElement = EmbedElement | ParagraphElement; +interface CustomText { + bold?: boolean; + italic?: boolean; + text: string; +} declare module 'slate' { interface CustomTypes { Editor: CustomEditor; Element: CustomElement; + Text: CustomText; } } From 68e71bb26e7213ffc9bae0fc56a36de00c2ccb3e Mon Sep 17 00:00:00 2001 From: bakaneko Date: Fri, 24 Jun 2022 20:23:05 +0900 Subject: [PATCH 014/127] beatmapId is nullable --- resources/assets/lib/editor.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/assets/lib/editor.d.ts b/resources/assets/lib/editor.d.ts index 00f81e38ea6..6d9067cd1e2 100644 --- a/resources/assets/lib/editor.d.ts +++ b/resources/assets/lib/editor.d.ts @@ -7,7 +7,7 @@ import { HistoryEditor } from 'slate-history'; import { ReactEditor } from 'slate-react'; interface EmbedElement extends BaseElement { - beatmapId: number; + beatmapId?: number | null; discussionId?: number; discussionType: BeatmapReviewDiscussionType; timestamp?: string; From 2accf7e0f715b41c64ca3a83d92db383fd347a47 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Fri, 24 Jun 2022 20:35:19 +0900 Subject: [PATCH 015/127] fix parsing embed typings --- .../lib/beatmap-discussions/review-document.ts | 12 +++++++++--- .../lib/interfaces/beatmap-discussion-review.ts | 8 +++++++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/resources/assets/lib/beatmap-discussions/review-document.ts b/resources/assets/lib/beatmap-discussions/review-document.ts index 6e496f4b6f7..48522c0f6d2 100644 --- a/resources/assets/lib/beatmap-discussions/review-document.ts +++ b/resources/assets/lib/beatmap-discussions/review-document.ts @@ -5,7 +5,7 @@ import * as markdown from 'remark-parse'; import { Element, Text } from 'slate'; import * as unified from 'unified'; import type { Parent, Node as UnistNode } from 'unist'; -import { BeatmapDiscussionReview, PersistedDocumentIssueEmbed } from '../interfaces/beatmap-discussion-review'; +import { BeatmapDiscussionReview, isBeatmapReviewDiscussionType, PersistedDocumentIssueEmbed } from '../interfaces/beatmap-discussion-review'; import { disableTokenizersPlugin } from './disable-tokenizers-plugin'; interface ParsedDocumentNode extends UnistNode { @@ -31,7 +31,7 @@ export function parseFromJson(json: string, discussions: Partial).includes(type); +} From 70df69d95485bb4f0ca64e548dfc6271c6bd8cf4 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Mon, 27 Jun 2022 14:46:07 +0900 Subject: [PATCH 016/127] only text nodes in our custom elements --- .../beatmap-discussions/editor-discussion-component.tsx | 4 ++-- resources/assets/lib/editor.d.ts | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/resources/assets/lib/beatmap-discussions/editor-discussion-component.tsx b/resources/assets/lib/beatmap-discussions/editor-discussion-component.tsx index b14fa164b79..c1ef765e110 100644 --- a/resources/assets/lib/beatmap-discussions/editor-discussion-component.tsx +++ b/resources/assets/lib/beatmap-discussions/editor-discussion-component.tsx @@ -59,8 +59,8 @@ export default class EditorDiscussionComponent extends React.Component { const path = this.path(); let purgeCache = false; - if (this.props.element.beatmapId) { - const content = this.props.element.children[0].text as string; + if (this.props.element.type === 'embed' && this.props.element.beatmapId != null) { + const content = this.props.element.children[0].text; const matches = BeatmapDiscussionHelper.TIMESTAMP_REGEX.exec(content); let timestamp: string | undefined; diff --git a/resources/assets/lib/editor.d.ts b/resources/assets/lib/editor.d.ts index 6d9067cd1e2..07aab58415e 100644 --- a/resources/assets/lib/editor.d.ts +++ b/resources/assets/lib/editor.d.ts @@ -2,19 +2,21 @@ // See the LICENCE file in the repository root for full licence text. import { BeatmapReviewDiscussionType } from 'interfaces/beatmap-discussion-review'; -import { BaseEditor, BaseElement } from 'slate'; +import { BaseEditor } from 'slate'; import { HistoryEditor } from 'slate-history'; import { ReactEditor } from 'slate-react'; -interface EmbedElement extends BaseElement { +interface EmbedElement { beatmapId?: number | null; + children: CustomText[]; discussionId?: number; discussionType: BeatmapReviewDiscussionType; timestamp?: string; type: 'embed'; } -interface ParagraphElement extends BaseElement { +interface ParagraphElement { + children: CustomText[]; type: 'paragraph'; } From 49d837062b2ef0ee107cc28daeeeb894e78b5456 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Mon, 27 Jun 2022 15:20:41 +0900 Subject: [PATCH 017/127] no nearbyDiscussions if no beatmapId --- .../editor-discussion-component.tsx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/resources/assets/lib/beatmap-discussions/editor-discussion-component.tsx b/resources/assets/lib/beatmap-discussions/editor-discussion-component.tsx index c1ef765e110..21257bc98a9 100644 --- a/resources/assets/lib/beatmap-discussions/editor-discussion-component.tsx +++ b/resources/assets/lib/beatmap-discussions/editor-discussion-component.tsx @@ -157,20 +157,23 @@ export default class EditorDiscussionComponent extends React.Component { nearbyDiscussions = () => { const timestamp = this.timestamp(); - if (timestamp == null) { + const beatmapId = this.selectedBeatmap(); + if (timestamp == null || beatmapId == null) { return []; } - if (!this.cache.nearbyDiscussions || this.cache.nearbyDiscussions.timestamp !== timestamp || (this.cache.nearbyDiscussions.beatmap_id !== this.selectedBeatmap())) { + if (this.cache.nearbyDiscussions == null + || this.cache.nearbyDiscussions.timestamp !== timestamp + || this.cache.nearbyDiscussions.beatmap_id !== beatmapId) { const relevantDiscussions = filter(this.props.discussions, this.isRelevantDiscussion); this.cache.nearbyDiscussions = { - beatmap_id: this.selectedBeatmap(), + beatmap_id: beatmapId, discussions: BeatmapDiscussionHelper.nearbyDiscussions(relevantDiscussions, timestamp), timestamp, }; } - return this.cache.nearbyDiscussions?.discussions; + return this.cache.nearbyDiscussions.discussions; }; nearbyDraftEmbeds = (drafts: EmbedElement[]) => { @@ -199,7 +202,7 @@ export default class EditorDiscussionComponent extends React.Component { } const nearbyDiscussions = this.editable() ? this.nearbyDiscussions() : []; - const nearbyUnsaved = this.nearbyDraftEmbeds(drafts) || []; + const nearbyUnsaved = this.nearbyDraftEmbeds(drafts) ?? []; if (nearbyDiscussions.length > 0 || nearbyUnsaved.length > 1) { const timestamps = From e59cf1eb8666a7463b1a4c9da38171c182275499 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Mon, 27 Jun 2022 15:22:38 +0900 Subject: [PATCH 018/127] add note --- resources/assets/lib/editor.d.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/assets/lib/editor.d.ts b/resources/assets/lib/editor.d.ts index 07aab58415e..7e98111bea1 100644 --- a/resources/assets/lib/editor.d.ts +++ b/resources/assets/lib/editor.d.ts @@ -11,6 +11,7 @@ interface EmbedElement { children: CustomText[]; discussionId?: number; discussionType: BeatmapReviewDiscussionType; + // TODO: timestamp should imply/require beatmapId timestamp?: string; type: 'embed'; } From 9711fffdda3c40246aaa2e330276df7e262d9219 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Mon, 27 Jun 2022 16:10:55 +0900 Subject: [PATCH 019/127] editor-helper typing --- .../lib/beatmap-discussions/editor-helpers.ts | 48 +++++++++++-------- .../editor-toolbar-button.tsx | 4 +- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/resources/assets/lib/beatmap-discussions/editor-helpers.ts b/resources/assets/lib/beatmap-discussions/editor-helpers.ts index 953cb1a60ce..e729ff7acf7 100644 --- a/resources/assets/lib/beatmap-discussions/editor-helpers.ts +++ b/resources/assets/lib/beatmap-discussions/editor-helpers.ts @@ -1,49 +1,55 @@ // Copyright (c) ppy Pty Ltd . Licensed under the GNU Affero General Public License v3.0. // See the LICENCE file in the repository root for full licence text. +import { EmbedElement, ParagraphElement } from 'editor'; import { BeatmapDiscussionReview, - BeatmapReviewDiscussionType, DocumentIssueEmbed, } from 'interfaces/beatmap-discussion-review'; import { Editor, Element as SlateElement, Node as SlateNode, Range as SlateRange, Text, Transforms } from 'slate'; -import { ReactEditor } from 'slate-react'; export const blockCount = (input: SlateElement[]) => input.length; -export const slateDocumentIsEmpty = (doc: SlateElement[]): boolean => doc.length === 0 || ( +export const slateDocumentIsEmpty = (doc: SlateElement[]) => doc.length === 0 || ( doc.length === 1 && doc[0].type === 'paragraph' && doc[0].children.length === 1 && doc[0].children[0].text === '' ); -export const insideEmbed = (editor: ReactEditor) => getCurrentNode(editor)?.type === 'embed'; +export const insideEmbed = (editor: Editor) => { + const node = getCurrentNode(editor); + if (node == null) return false; -export const insideEmptyNode = (editor: ReactEditor) => { + return 'type' in node && node.type === 'embed'; +}; + +export const insideEmptyNode = (editor: Editor) => { const parent = getCurrentNode(editor); - if (!parent) { - return false; + if (parent == null) return false; + + if ('type' in parent) { + return Editor.isEmpty(editor, parent); } - return Editor.isEmpty(editor, parent); + return false; }; -export const isFormatActive = (editor: ReactEditor, format: string) => { +export const isFormatActive = (editor: Editor, format: 'bold' | 'italic') => { const [match] = Editor.nodes(editor, { - match: (n) => n[format] === true, + match: (node) => Text.isText(node) && node[format] === true, mode: 'all', }); return !!match; }; -export const getCurrentNode = (editor: ReactEditor) => { +const getCurrentNode = (editor: Editor) => { if (editor.selection) { return SlateNode.parent(editor, SlateRange.start(editor.selection).path); } }; -export const toggleFormat = (editor: ReactEditor, format: string) => { +export const toggleFormat = (editor: Editor, format: 'bold' | 'italic') => { Transforms.setNodes( editor, { [format]: isFormatActive(editor, format) ? null : true }, @@ -52,24 +58,24 @@ export const toggleFormat = (editor: ReactEditor, format: string) => { }; // TODO: check typing -function serializeEmbed(node: SlateElement): DocumentIssueEmbed { - if (node.discussionId) { +function serializeEmbed(node: EmbedElement): DocumentIssueEmbed { + if (node.discussionId != null) { return { - discussion_id: node.discussionId as number, + discussion_id: node.discussionId, type: 'embed', }; } else { return { - beatmap_id: node.beatmapId as number, - discussion_type: node.discussionType as BeatmapReviewDiscussionType, - text: node.children[0].text as string, - timestamp: node.timestamp ? BeatmapDiscussionHelper.parseTimestamp(node.timestamp as string) : null, + beatmap_id: node.beatmapId ?? null, + discussion_type: node.discussionType, + text: node.children[0].text, + timestamp: node.timestamp ? BeatmapDiscussionHelper.parseTimestamp(node.timestamp) : null, type: 'embed', }; } } -function serializeParagraph(node: SlateElement) { +function serializeParagraph(node: ParagraphElement) { const childOutput: string[] = []; const currentMarks = { bold: false, @@ -89,7 +95,7 @@ function serializeParagraph(node: SlateElement) { } } - childOutput.push((child.text as string).replace('*', '\\*')); + childOutput.push((child.text).replace('*', '\\*')); }); // ensure closing of open tags diff --git a/resources/assets/lib/beatmap-discussions/editor-toolbar-button.tsx b/resources/assets/lib/beatmap-discussions/editor-toolbar-button.tsx index d22744fd080..ea872faa788 100644 --- a/resources/assets/lib/beatmap-discussions/editor-toolbar-button.tsx +++ b/resources/assets/lib/beatmap-discussions/editor-toolbar-button.tsx @@ -7,7 +7,7 @@ import { isFormatActive, toggleFormat } from './editor-helpers'; import { SlateContext } from './slate-context'; interface Props { - format: string; + format: 'bold' | 'italic'; } export const EditorToolbarButton = (props: Props) => { @@ -19,7 +19,7 @@ export const EditorToolbarButton = (props: Props) => { return (
{unsavedIndicator} From 23e497f416fbaad7ae6f32992a681905dfd936b6 Mon Sep 17 00:00:00 2001 From: nanaya Date: Tue, 6 Sep 2022 18:19:59 +0900 Subject: [PATCH 029/127] Add support for is_legacy solo score index field --- app/Http/Controllers/BeatmapsController.php | 1 + app/Libraries/Search/ScoreSearch.php | 3 + app/Libraries/Search/ScoreSearchParams.php | 2 + app/Models/BeatmapLeader.php | 1 + .../BeatmapsControllerSoloScoresTest.php | 272 ++++++++++-------- 5 files changed, 152 insertions(+), 127 deletions(-) diff --git a/app/Http/Controllers/BeatmapsController.php b/app/Http/Controllers/BeatmapsController.php index 3844c5c88bf..6390b5da195 100644 --- a/app/Http/Controllers/BeatmapsController.php +++ b/app/Http/Controllers/BeatmapsController.php @@ -369,6 +369,7 @@ public function soloScores($id) $esFetch = new BeatmapScores([ 'beatmap_ids' => [$beatmap->getKey()], + 'is_legacy' => false, 'mods' => $mods, 'ruleset_id' => $rulesetId, 'type' => $type, diff --git a/app/Libraries/Search/ScoreSearch.php b/app/Libraries/Search/ScoreSearch.php index ccfa893e874..755eedac5a2 100644 --- a/app/Libraries/Search/ScoreSearch.php +++ b/app/Libraries/Search/ScoreSearch.php @@ -36,6 +36,9 @@ public function getQuery(): BoolQuery { $query = new BoolQuery(); + if ($this->params->isLegacy !== null) { + $query->filter(['term' => ['is_legacy' => $this->params->isLegacy]]); + } if ($this->params->rulesetId !== null) { $query->filter(['term' => ['ruleset_id' => $this->params->rulesetId]]); } diff --git a/app/Libraries/Search/ScoreSearchParams.php b/app/Libraries/Search/ScoreSearchParams.php index 258a10f2883..221b57c1db0 100644 --- a/app/Libraries/Search/ScoreSearchParams.php +++ b/app/Libraries/Search/ScoreSearchParams.php @@ -22,6 +22,7 @@ public static function fromArray(array $rawParams): static $params = new static(); $params->beatmapIds = $rawParams['beatmap_ids'] ?? null; $params->excludeMods = $rawParams['exclude_mods'] ?? null; + $params->isLegacy = $rawParams['is_legacy'] ?? null; $params->mods = $rawParams['mods'] ?? null; $params->rulesetId = $rawParams['ruleset_id'] ?? null; $params->userId = $rawParams['user_id'] ?? null; @@ -42,6 +43,7 @@ public static function fromArray(array $rawParams): static public ?Score $beforeScore = null; public ?int $beforeTotalScore = null; public ?array $excludeMods = null; + public ?bool $isLegacy = null; public ?array $mods = null; public ?int $rulesetId = null; public $size = 50; diff --git a/app/Models/BeatmapLeader.php b/app/Models/BeatmapLeader.php index 26085fc1918..c1ea03334af 100644 --- a/app/Models/BeatmapLeader.php +++ b/app/Models/BeatmapLeader.php @@ -26,6 +26,7 @@ public static function sync(int $beatmapId, int $rulesetId): void { $searchParams = ScoreSearchParams::fromArray([ 'beatmap_ids' => [$beatmapId], + 'is_legacy' => false, 'limit' => 1, 'ruleset_id' => $rulesetId, 'sort' => 'score_desc', diff --git a/tests/Controllers/BeatmapsControllerSoloScoresTest.php b/tests/Controllers/BeatmapsControllerSoloScoresTest.php index 989bd6a7cc6..914d4f62dc0 100644 --- a/tests/Controllers/BeatmapsControllerSoloScoresTest.php +++ b/tests/Controllers/BeatmapsControllerSoloScoresTest.php @@ -36,113 +36,122 @@ public static function setUpBeforeClass(): void (new static())->refreshApplication(); static::$user = User::factory()->create(['osu_subscriber' => true]); static::$otherUser = User::factory()->create(['country_acronym' => Country::factory()]); + $friend = User::factory()->create(['country_acronym' => Country::factory()]); static::$beatmap = Beatmap::factory()->qualified()->create(); $countryAcronym = static::$user->country_acronym; - static::$scores = [ - 'user' => SoloScore::factory()->withData(['total_score' => 1100])->create([ - 'beatmap_id' => static::$beatmap, - 'preserve' => true, - 'user_id' => static::$user, - ]), - 'userMods' => SoloScore::factory()->withData([ - 'total_score' => 1050, - 'mods' => static::defaultMods(['DT', 'HD']), - ])->create([ - 'beatmap_id' => static::$beatmap, - 'preserve' => true, - 'user_id' => static::$user, - ]), - 'userModsNC' => SoloScore::factory()->withData([ - 'total_score' => 1050, - 'mods' => static::defaultMods(['NC']), - ])->create([ - 'beatmap_id' => static::$beatmap, - 'preserve' => true, - 'user_id' => static::$user, - ]), - 'otherUserModsNCPFHigherScore' => SoloScore::factory()->withData([ - 'total_score' => 1010, - 'mods' => static::defaultMods(['NC', 'PF']), - ])->create([ - 'beatmap_id' => static::$beatmap, - 'preserve' => true, - 'user_id' => static::$otherUser, - ]), - 'userModsLowerScore' => SoloScore::factory()->withData([ - 'total_score' => 1000, - 'mods' => static::defaultMods(['DT', 'HD']), - ])->create([ - 'beatmap_id' => static::$beatmap, - 'preserve' => true, - 'user_id' => static::$user, - ]), - 'friend' => SoloScore::factory()->withData(['total_score' => 1000])->create([ - 'beatmap_id' => static::$beatmap, - 'preserve' => true, - 'user_id' => User::factory()->state(['country_acronym' => Country::factory()]), - ]), - // With preference mods - 'otherUser' => SoloScore::factory()->withData([ - 'total_score' => 1000, - 'mods' => static::defaultMods(['PF']), - ])->create([ - 'beatmap_id' => static::$beatmap, - 'preserve' => true, - 'user_id' => static::$otherUser, - ]), - 'otherUserMods' => SoloScore::factory()->withData([ - 'total_score' => 1000, - 'mods' => static::defaultMods(['HD', 'PF', 'NC']), - ])->create([ - 'beatmap_id' => static::$beatmap, - 'preserve' => true, - 'user_id' => static::$otherUser, - ]), - 'otherUserModsExtraNonPreferences' => SoloScore::factory()->withData([ - 'total_score' => 1000, - 'mods' => static::defaultMods(['DT', 'HD', 'HR']), - ])->create([ - 'beatmap_id' => static::$beatmap, - 'preserve' => true, - 'user_id' => static::$otherUser, - ]), - 'otherUserModsUnrelated' => SoloScore::factory()->withData([ - 'total_score' => 1000, - 'mods' => static::defaultMods(['FL']), - ])->create([ - 'beatmap_id' => static::$beatmap, - 'preserve' => true, - 'user_id' => static::$otherUser, - ]), - // Same total score but achieved later so it should come up after earlier score - 'otherUser2Later' => SoloScore::factory()->withData(['total_score' => 1000])->create([ - 'beatmap_id' => static::$beatmap, - 'preserve' => true, - 'user_id' => User::factory()->state(['country_acronym' => Country::factory()]), - ]), - 'otherUser3SameCountry' => SoloScore::factory()->withData(['total_score' => 1000])->create([ - 'beatmap_id' => static::$beatmap, - 'preserve' => true, - 'user_id' => User::factory()->state(['country_acronym' => $countryAcronym]), - ]), - // Non-preserved score should be filtered out - 'nonPreserved' => SoloScore::factory()->create([ - 'beatmap_id' => static::$beatmap, - 'preserve' => false, - 'user_id' => User::factory()->state(['country_acronym' => Country::factory()]), - ]), - // Unrelated score - 'unrelated' => SoloScore::factory()->create([ - 'user_id' => User::factory()->state(['country_acronym' => Country::factory()]), - ]), - ]; + static::$scores = []; + $scoreFactory = SoloScore::factory(); + foreach (['solo' => 0, 'legacy' => null] as $type => $buildId) { + $withDefaultData = fn (array $data): array => array_merge([ + 'build_id' => $buildId, + ], $data); + + static::$scores = array_merge(static::$scores, [ + "{$type}:user" => $scoreFactory->withData($withDefaultData(['total_score' => 1100]))->create([ + 'beatmap_id' => static::$beatmap, + 'preserve' => true, + 'user_id' => static::$user, + ]), + "{$type}:userMods" => $scoreFactory->withData($withDefaultData([ + 'total_score' => 1050, + 'mods' => static::defaultMods(['DT', 'HD']), + ]))->create([ + 'beatmap_id' => static::$beatmap, + 'preserve' => true, + 'user_id' => static::$user, + ]), + "{$type}:userModsNC" => $scoreFactory->withData($withDefaultData([ + 'total_score' => 1050, + 'mods' => static::defaultMods(['NC']), + ]))->create([ + 'beatmap_id' => static::$beatmap, + 'preserve' => true, + 'user_id' => static::$user, + ]), + "{$type}:otherUserModsNCPFHigherScore" => $scoreFactory->withData($withDefaultData([ + 'total_score' => 1010, + 'mods' => static::defaultMods(['NC', 'PF']), + ]))->create([ + 'beatmap_id' => static::$beatmap, + 'preserve' => true, + 'user_id' => static::$otherUser, + ]), + "{$type}:userModsLowerScore" => $scoreFactory->withData($withDefaultData([ + 'total_score' => 1000, + 'mods' => static::defaultMods(['DT', 'HD']), + ]))->create([ + 'beatmap_id' => static::$beatmap, + 'preserve' => true, + 'user_id' => static::$user, + ]), + "{$type}:friend" => $scoreFactory->withData($withDefaultData(['total_score' => 1000]))->create([ + 'beatmap_id' => static::$beatmap, + 'preserve' => true, + 'user_id' => $friend, + ]), + // With preference mods + "{$type}:otherUser" => $scoreFactory->withData($withDefaultData([ + 'total_score' => 1000, + 'mods' => static::defaultMods(['PF']), + ]))->create([ + 'beatmap_id' => static::$beatmap, + 'preserve' => true, + 'user_id' => static::$otherUser, + ]), + "{$type}:otherUserMods" => $scoreFactory->withData($withDefaultData([ + 'total_score' => 1000, + 'mods' => static::defaultMods(['HD', 'PF', 'NC']), + ]))->create([ + 'beatmap_id' => static::$beatmap, + 'preserve' => true, + 'user_id' => static::$otherUser, + ]), + "{$type}:otherUserModsExtraNonPreferences" => $scoreFactory->withData($withDefaultData([ + 'total_score' => 1000, + 'mods' => static::defaultMods(['DT', 'HD', 'HR']), + ]))->create([ + 'beatmap_id' => static::$beatmap, + 'preserve' => true, + 'user_id' => static::$otherUser, + ]), + "{$type}:otherUserModsUnrelated" => $scoreFactory->withData($withDefaultData([ + 'total_score' => 1000, + 'mods' => static::defaultMods(['FL']), + ]))->create([ + 'beatmap_id' => static::$beatmap, + 'preserve' => true, + 'user_id' => static::$otherUser, + ]), + // Same total score but achieved later so it should come up after earlier score + "{$type}:otherUser2Later" => $scoreFactory->withData($withDefaultData(['total_score' => 1000]))->create([ + 'beatmap_id' => static::$beatmap, + 'preserve' => true, + 'user_id' => User::factory()->state(['country_acronym' => Country::factory()]), + ]), + "{$type}:otherUser3SameCountry" => $scoreFactory->withData($withDefaultData(['total_score' => 1000]))->create([ + 'beatmap_id' => static::$beatmap, + 'preserve' => true, + 'user_id' => User::factory()->state(['country_acronym' => $countryAcronym]), + ]), + // Non-preserved score should be filtered out + "{$type}:nonPreserved" => $scoreFactory->withData($withDefaultData([]))->create([ + 'beatmap_id' => static::$beatmap, + 'preserve' => false, + 'user_id' => User::factory()->state(['country_acronym' => Country::factory()]), + ]), + // Unrelated score + "{$type}:unrelated" => $scoreFactory->withData($withDefaultData([]))->create([ + 'user_id' => User::factory()->state(['country_acronym' => Country::factory()]), + ]), + ]); + } UserRelation::create([ 'friend' => true, 'user_id' => static::$user->getKey(), - 'zebra_id' => static::$scores['friend']->user_id, + 'zebra_id' => $friend->getKey(), ]); Artisan::call('es:index-scores:queue', [ @@ -200,34 +209,43 @@ public function testQuery(array $scoreKeys, array $params) public function dataProviderForTestQuery(): array { return [ - 'no parameters' => [ - ['user', 'otherUserModsNCPFHigherScore', 'friend', 'otherUser2Later', 'otherUser3SameCountry'], - [], - ], - 'by country' => [ - ['user', 'otherUser3SameCountry'], - ['type' => 'country'], - ], - 'by friend' => [ - ['user', 'friend'], - ['type' => 'friend'], - ], - 'mods filter' => [ - ['userMods', 'otherUserMods'], - ['mods' => ['DT', 'HD']], - ], - 'mods with implied filter' => [ - ['userModsNC', 'otherUserModsNCPFHigherScore'], - ['mods' => ['NC']], - ], - 'mods with nomods' => [ - ['user', 'otherUserModsNCPFHigherScore', 'friend', 'otherUser2Later', 'otherUser3SameCountry'], - ['mods' => ['NC', 'NM']], - ], - 'nomods filter' => [ - ['user', 'friend', 'otherUser', 'otherUser2Later', 'otherUser3SameCountry'], - ['mods' => ['NM']], - ], + 'no parameters' => [[ + 'solo:user', + 'solo:otherUserModsNCPFHigherScore', + 'solo:friend', + 'solo:otherUser2Later', + 'solo:otherUser3SameCountry', + ], []], + 'by country' => [[ + 'solo:user', + 'solo:otherUser3SameCountry', + ], ['type' => 'country']], + 'by friend' => [[ + 'solo:user', + 'solo:friend', + ], ['type' => 'friend']], + 'mods filter' => [[ + 'solo:userMods', + 'solo:otherUserMods', + ], ['mods' => ['DT', 'HD']]], + 'mods with implied filter' => [[ + 'solo:userModsNC', + 'solo:otherUserModsNCPFHigherScore', + ], ['mods' => ['NC']]], + 'mods with nomods' => [[ + 'solo:user', + 'solo:otherUserModsNCPFHigherScore', + 'solo:friend', + 'solo:otherUser2Later', + 'solo:otherUser3SameCountry', + ], ['mods' => ['NC', 'NM']]], + 'nomods filter' => [[ + 'solo:user', + 'solo:friend', + 'solo:otherUser', + 'solo:otherUser2Later', + 'solo:otherUser3SameCountry', + ], ['mods' => ['NM']]], ]; } } From 57c4e3a82a9574d188759b0fa112f57b9ed2327c Mon Sep 17 00:00:00 2001 From: nanaya Date: Tue, 13 Sep 2022 19:16:29 +0900 Subject: [PATCH 030/127] Support multiple data arrays instead --- database/factories/Solo/ScoreFactory.php | 4 +- .../BeatmapsControllerSoloScoresTest.php | 48 +++++++++---------- 2 files changed, 25 insertions(+), 27 deletions(-) diff --git a/database/factories/Solo/ScoreFactory.php b/database/factories/Solo/ScoreFactory.php index c7bcb45a80e..15cf23519cb 100644 --- a/database/factories/Solo/ScoreFactory.php +++ b/database/factories/Solo/ScoreFactory.php @@ -31,10 +31,10 @@ public function definition(): array ]; } - public function withData(?array $overrides = null): static + public function withData(array ...$overrides): static { return $this->state([ - 'data' => $this->makeData($overrides), + 'data' => $this->makeData(array_merge(...$overrides)), ]); } diff --git a/tests/Controllers/BeatmapsControllerSoloScoresTest.php b/tests/Controllers/BeatmapsControllerSoloScoresTest.php index 914d4f62dc0..145001e5677 100644 --- a/tests/Controllers/BeatmapsControllerSoloScoresTest.php +++ b/tests/Controllers/BeatmapsControllerSoloScoresTest.php @@ -44,105 +44,103 @@ public static function setUpBeforeClass(): void static::$scores = []; $scoreFactory = SoloScore::factory(); foreach (['solo' => 0, 'legacy' => null] as $type => $buildId) { - $withDefaultData = fn (array $data): array => array_merge([ - 'build_id' => $buildId, - ], $data); + $defaultData = ['build_id' => $buildId]; static::$scores = array_merge(static::$scores, [ - "{$type}:user" => $scoreFactory->withData($withDefaultData(['total_score' => 1100]))->create([ + "{$type}:user" => $scoreFactory->withData($defaultData, ['total_score' => 1100])->create([ 'beatmap_id' => static::$beatmap, 'preserve' => true, 'user_id' => static::$user, ]), - "{$type}:userMods" => $scoreFactory->withData($withDefaultData([ + "{$type}:userMods" => $scoreFactory->withData($defaultData, [ 'total_score' => 1050, 'mods' => static::defaultMods(['DT', 'HD']), - ]))->create([ + ])->create([ 'beatmap_id' => static::$beatmap, 'preserve' => true, 'user_id' => static::$user, ]), - "{$type}:userModsNC" => $scoreFactory->withData($withDefaultData([ + "{$type}:userModsNC" => $scoreFactory->withData($defaultData, [ 'total_score' => 1050, 'mods' => static::defaultMods(['NC']), - ]))->create([ + ])->create([ 'beatmap_id' => static::$beatmap, 'preserve' => true, 'user_id' => static::$user, ]), - "{$type}:otherUserModsNCPFHigherScore" => $scoreFactory->withData($withDefaultData([ + "{$type}:otherUserModsNCPFHigherScore" => $scoreFactory->withData($defaultData, [ 'total_score' => 1010, 'mods' => static::defaultMods(['NC', 'PF']), - ]))->create([ + ])->create([ 'beatmap_id' => static::$beatmap, 'preserve' => true, 'user_id' => static::$otherUser, ]), - "{$type}:userModsLowerScore" => $scoreFactory->withData($withDefaultData([ + "{$type}:userModsLowerScore" => $scoreFactory->withData($defaultData, [ 'total_score' => 1000, 'mods' => static::defaultMods(['DT', 'HD']), - ]))->create([ + ])->create([ 'beatmap_id' => static::$beatmap, 'preserve' => true, 'user_id' => static::$user, ]), - "{$type}:friend" => $scoreFactory->withData($withDefaultData(['total_score' => 1000]))->create([ + "{$type}:friend" => $scoreFactory->withData($defaultData, ['total_score' => 1000])->create([ 'beatmap_id' => static::$beatmap, 'preserve' => true, 'user_id' => $friend, ]), // With preference mods - "{$type}:otherUser" => $scoreFactory->withData($withDefaultData([ + "{$type}:otherUser" => $scoreFactory->withData($defaultData, [ 'total_score' => 1000, 'mods' => static::defaultMods(['PF']), - ]))->create([ + ])->create([ 'beatmap_id' => static::$beatmap, 'preserve' => true, 'user_id' => static::$otherUser, ]), - "{$type}:otherUserMods" => $scoreFactory->withData($withDefaultData([ + "{$type}:otherUserMods" => $scoreFactory->withData($defaultData, [ 'total_score' => 1000, 'mods' => static::defaultMods(['HD', 'PF', 'NC']), - ]))->create([ + ])->create([ 'beatmap_id' => static::$beatmap, 'preserve' => true, 'user_id' => static::$otherUser, ]), - "{$type}:otherUserModsExtraNonPreferences" => $scoreFactory->withData($withDefaultData([ + "{$type}:otherUserModsExtraNonPreferences" => $scoreFactory->withData($defaultData, [ 'total_score' => 1000, 'mods' => static::defaultMods(['DT', 'HD', 'HR']), - ]))->create([ + ])->create([ 'beatmap_id' => static::$beatmap, 'preserve' => true, 'user_id' => static::$otherUser, ]), - "{$type}:otherUserModsUnrelated" => $scoreFactory->withData($withDefaultData([ + "{$type}:otherUserModsUnrelated" => $scoreFactory->withData($defaultData, [ 'total_score' => 1000, 'mods' => static::defaultMods(['FL']), - ]))->create([ + ])->create([ 'beatmap_id' => static::$beatmap, 'preserve' => true, 'user_id' => static::$otherUser, ]), // Same total score but achieved later so it should come up after earlier score - "{$type}:otherUser2Later" => $scoreFactory->withData($withDefaultData(['total_score' => 1000]))->create([ + "{$type}:otherUser2Later" => $scoreFactory->withData($defaultData, ['total_score' => 1000])->create([ 'beatmap_id' => static::$beatmap, 'preserve' => true, 'user_id' => User::factory()->state(['country_acronym' => Country::factory()]), ]), - "{$type}:otherUser3SameCountry" => $scoreFactory->withData($withDefaultData(['total_score' => 1000]))->create([ + "{$type}:otherUser3SameCountry" => $scoreFactory->withData($defaultData, ['total_score' => 1000])->create([ 'beatmap_id' => static::$beatmap, 'preserve' => true, 'user_id' => User::factory()->state(['country_acronym' => $countryAcronym]), ]), // Non-preserved score should be filtered out - "{$type}:nonPreserved" => $scoreFactory->withData($withDefaultData([]))->create([ + "{$type}:nonPreserved" => $scoreFactory->withData($defaultData)->create([ 'beatmap_id' => static::$beatmap, 'preserve' => false, 'user_id' => User::factory()->state(['country_acronym' => Country::factory()]), ]), // Unrelated score - "{$type}:unrelated" => $scoreFactory->withData($withDefaultData([]))->create([ + "{$type}:unrelated" => $scoreFactory->withData($defaultData)->create([ 'user_id' => User::factory()->state(['country_acronym' => Country::factory()]), ]), ]); From 9aacae282cf0eb31f6a0a55bd0ec0f28d2ae0021 Mon Sep 17 00:00:00 2001 From: nanaya Date: Tue, 13 Sep 2022 19:32:07 +0900 Subject: [PATCH 031/127] Use default error handler on invalid option Allows the error to be visible in test. --- app/Console/Commands/EsIndexScoresQueue.php | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/app/Console/Commands/EsIndexScoresQueue.php b/app/Console/Commands/EsIndexScoresQueue.php index d02b4c4397d..babf3e26d7a 100644 --- a/app/Console/Commands/EsIndexScoresQueue.php +++ b/app/Console/Commands/EsIndexScoresQueue.php @@ -54,13 +54,7 @@ public function handle() { $this->search = new ScoreSearch(); - try { - $this->parseOptions(); - } catch (InvariantException $e) { - $this->error($e->getMessage()); - - return 1; - } + $this->parseOptions(); if (!$this->confirm('This will queue scores for indexing to schema '.implode(', ', $this->schemas).', continue?', true)) { return $this->info('User aborted'); From 7226ea30ce3edb709d0195f7829af0817044e79d Mon Sep 17 00:00:00 2001 From: nanaya Date: Tue, 13 Sep 2022 19:58:33 +0900 Subject: [PATCH 032/127] Fix test to check exception instead of return code --- tests/Commands/EsIndexScoresQueueTest.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/Commands/EsIndexScoresQueueTest.php b/tests/Commands/EsIndexScoresQueueTest.php index 6807a8d4471..d3cb2b9bd50 100644 --- a/tests/Commands/EsIndexScoresQueueTest.php +++ b/tests/Commands/EsIndexScoresQueueTest.php @@ -5,6 +5,7 @@ namespace Tests\Commands; +use App\Exceptions\InvariantException; use App\Models\Solo\Score; use Artisan; use LaravelRedis; @@ -34,12 +35,15 @@ private static function queueSize(): int */ public function testParameterValidity(array $params, bool $isValid) { + if (!$isValid) { + $this->expectException(InvariantException::class); + } + $command = $this->artisan('es:index-scores:queue', array_merge($params, ['--schema' => static::SCHEMA])); if ($isValid) { $command->expectsQuestion('This will queue scores for indexing to schema '.static::SCHEMA.', continue?', 'yes'); } - $command->assertExitCode($isValid ? 0 : 1); } /** From 0d9f229cc7d0b68794f47f8ff5572a4340e88534 Mon Sep 17 00:00:00 2001 From: nanaya Date: Thu, 15 Sep 2022 20:02:30 +0900 Subject: [PATCH 033/127] Fix userRank on solo score --- app/Models/Solo/Score.php | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/app/Models/Solo/Score.php b/app/Models/Solo/Score.php index 7dcd7bec129..297e6e7a8de 100644 --- a/app/Models/Solo/Score.php +++ b/app/Models/Solo/Score.php @@ -7,7 +7,8 @@ namespace App\Models\Solo; -use App\Libraries\Score\UserRankCache; +use App\Libraries\Score\UserRank; +use App\Libraries\Search\ScoreSearchParams; use App\Models\Beatmap; use App\Models\Model; use App\Models\Score as LegacyScore; @@ -128,6 +129,11 @@ public function getMode(): string return Beatmap::modeStr($this->ruleset_id); } + public function isLegacy(): bool + { + return $this->data->buildId === null; + } + public function legacyScore(): ?LegacyScore\Best\Model { $id = $this->data->legacyScoreId; @@ -190,9 +196,14 @@ public function trashed(): bool return false; } - public function userRank(): ?int + public function userRank(): int { - return UserRankCache::fetch([], $this->beatmap_id, $this->ruleset_id, $this->data->totalScore); + return UserRank::getRank(ScoreSearchParams::fromArray([ + 'beatmap_ids' => [$this->beatmap_id], + 'before_score' => $this, + 'is_legacy' => $this->isLegacy(), + 'ruleset_id' => $this->ruleset_id, + ])); } protected function newReportableExtraParams(): array From d96f3ec5231d0102012e3b5ab6d4775178f1ff8b Mon Sep 17 00:00:00 2001 From: nanaya Date: Fri, 16 Sep 2022 21:32:57 +0900 Subject: [PATCH 034/127] Add test and add support for country rank --- app/Models/Solo/Score.php | 7 +- app/Transformers/ScoreTransformer.php | 2 +- .../BeatmapsControllerSoloScoresTest.php | 7 + tests/Models/Solo/ScoreEsIndexTest.php | 127 ++++++++++++++++++ tests/TestCase.php | 14 ++ 5 files changed, 153 insertions(+), 4 deletions(-) create mode 100644 tests/Models/Solo/ScoreEsIndexTest.php diff --git a/app/Models/Solo/Score.php b/app/Models/Solo/Score.php index 297e6e7a8de..6b671b16eca 100644 --- a/app/Models/Solo/Score.php +++ b/app/Models/Solo/Score.php @@ -196,14 +196,15 @@ public function trashed(): bool return false; } - public function userRank(): int + public function userRank(?array $params = null): int { - return UserRank::getRank(ScoreSearchParams::fromArray([ + return UserRank::getRank(ScoreSearchParams::fromArray(array_merge($params ?? [], [ 'beatmap_ids' => [$this->beatmap_id], 'before_score' => $this, 'is_legacy' => $this->isLegacy(), 'ruleset_id' => $this->ruleset_id, - ])); + 'user' => $this->user, + ]))); } protected function newReportableExtraParams(): array diff --git a/app/Transformers/ScoreTransformer.php b/app/Transformers/ScoreTransformer.php index e1cf899e1bb..06b1a72d793 100644 --- a/app/Transformers/ScoreTransformer.php +++ b/app/Transformers/ScoreTransformer.php @@ -182,7 +182,7 @@ public function includeMatch(LegacyMatch\Score $score) ]); } - public function includeRankCountry(ScoreModel $score) + public function includeRankCountry(ScoreModel|SoloScore $score) { return $this->primitive($score->userRank(['type' => 'country'])); } diff --git a/tests/Controllers/BeatmapsControllerSoloScoresTest.php b/tests/Controllers/BeatmapsControllerSoloScoresTest.php index 145001e5677..63f26a59193 100644 --- a/tests/Controllers/BeatmapsControllerSoloScoresTest.php +++ b/tests/Controllers/BeatmapsControllerSoloScoresTest.php @@ -204,6 +204,13 @@ public function testQuery(array $scoreKeys, array $params) } } + public function testUserRank() + { + $this->actingAs(static::$otherUser) + ->json('GET', route('beatmaps.solo-scores', static::$beatmap), $params) + ->assertJsonPath('user_score.position', 2); + } + public function dataProviderForTestQuery(): array { return [ diff --git a/tests/Models/Solo/ScoreEsIndexTest.php b/tests/Models/Solo/ScoreEsIndexTest.php new file mode 100644 index 00000000000..0653b8b7666 --- /dev/null +++ b/tests/Models/Solo/ScoreEsIndexTest.php @@ -0,0 +1,127 @@ +. Licensed under the GNU Affero General Public License v3.0. +// See the LICENCE file in the repository root for full licence text. + +declare(strict_types=1); + +namespace Tests\Models\Solo; + +use App\Libraries\Search\ScoreSearch; +use App\Models\Beatmap; +use App\Models\Country; +use App\Models\Group; +use App\Models\Solo\Score; +use App\Models\User; +use Tests\TestCase; + +/** + * @group EsSoloScores + */ +class ScoreEsIndexTest extends TestCase +{ + private static Beatmap $beatmap; + private static array $scores; + private static User $user; + + protected $connectionsToTransact = []; + + public static function setUpBeforeClass(): void + { + (new static())->refreshApplication(); + static::$user = User::factory()->create(['osu_subscriber' => true]); + $otherUser = User::factory()->create(['country_acronym' => Country::factory()]); + static::$beatmap = Beatmap::factory()->qualified()->create(); + + $scoreFactory = Score::factory()->state(['preserve' => true]); + $defaultData = ['build_id' => 1]; + + $mods = [ + ['acronym' => 'DT', 'settings' => []], + ['acronym' => 'HD', 'settings' => []], + ]; + $unrelatedMods = [ + ['acronym' => 'NC', 'settings' => []], + ]; + + static::$scores = [ + 'otherUser' => $scoreFactory->withData($defaultData, [ + 'total_score' => 1150, + 'mods' => $unrelatedMods, + ])->create([ + 'beatmap_id' => static::$beatmap, + 'user_id' => $otherUser, + ]), + 'otherUserMods' => $scoreFactory->withData($defaultData, [ + 'total_score' => 1140, + 'mods' => $mods, + ])->create([ + 'beatmap_id' => static::$beatmap, + 'user_id' => $otherUser, + ]), + 'otherUser2' => $scoreFactory->withData($defaultData, [ + 'total_score' => 1150, + 'mods' => $mods, + ])->create([ + 'beatmap_id' => static::$beatmap, + 'user_id' => User::factory()->state(['country_acronym' => Country::factory()]), + ]), + 'otherUser3SameCountry' => $scoreFactory->withData($defaultData, [ + 'total_score' => 1130, + 'mods' => $unrelatedMods, + ])->create([ + 'beatmap_id' => static::$beatmap, + 'user_id' => User::factory()->state(['country_acronym' => static::$user->country_acronym]), + ]), + 'user' => $scoreFactory->withData($defaultData, ['total_score' => 1100])->create([ + 'beatmap_id' => static::$beatmap, + 'user_id' => static::$user, + ]), + 'userMods' => $scoreFactory->withData($defaultData, [ + 'total_score' => 1050, + 'mods' => $mods, + ])->create([ + 'beatmap_id' => static::$beatmap, + 'user_id' => static::$user, + ]), + ]; + + static::reindexScores(); + } + + public static function tearDownAfterClass(): void + { + (new static())->refreshApplication(); + Beatmap::truncate(); + Beatmapset::truncate(); + Country::truncate(); + Genre::truncate(); + Group::truncate(); + Language::truncate(); + Score::truncate(); + User::truncate(); + UserGroup::truncate(); + UserGroupEvent::truncate(); + UserRelation::truncate(); + (new ScoreSearch())->deleteAll(); + } + + /** + * @dataProvider dataProviderForTestUserRank + */ + public function testUserRank(string $key, ?array $params, int $rank): void + { + $score = static::$scores[$key]->fresh(); + + $this->assertSame($rank, $score->userRank($params)); + } + + public function dataProviderForTestUserRank(): array + { + return [ + ['user', null, 4], + ['user', ['type' => 'country'], 2], + ['userMods', ['mods' => ['DT', 'HD']], 3], + ]; + } +} diff --git a/tests/TestCase.php b/tests/TestCase.php index 4b7d9e54d8f..727c6fa0a01 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -9,9 +9,11 @@ use App\Http\Middleware\AuthApi; use App\Jobs\Notifications\BroadcastNotificationBase; use App\Libraries\BroadcastsPendingForTests; +use App\Libraries\Search\ScoreSearch; use App\Models\Beatmapset; use App\Models\OAuth\Client; use App\Models\User; +use Artisan; use DMS\PHPUnitExtensions\ArraySubset\ArraySubsetAsserts; use Firebase\JWT\JWT; use Illuminate\Database\Eloquent\Model; @@ -30,6 +32,18 @@ class TestCase extends BaseTestCase { use ArraySubsetAsserts, CreatesApplication, DatabaseTransactions; + protected static function reindexScores() + { + $search = new ScoreSearch(); + $search->deleteAll(); + $search->refresh(); + Artisan::call('es:index-scores:queue', [ + '--all' => true, + '--no-interaction' => true, + ]); + $search->indexWait(); + } + protected $connectionsToTransact = [ 'mysql', 'mysql-chat', From d4026b9c77a40aed71c851ca2042303f54ee9a1c Mon Sep 17 00:00:00 2001 From: nanaya Date: Fri, 16 Sep 2022 21:52:46 +0900 Subject: [PATCH 035/127] Incorrectly committed unused code --- tests/Controllers/BeatmapsControllerSoloScoresTest.php | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tests/Controllers/BeatmapsControllerSoloScoresTest.php b/tests/Controllers/BeatmapsControllerSoloScoresTest.php index 63f26a59193..145001e5677 100644 --- a/tests/Controllers/BeatmapsControllerSoloScoresTest.php +++ b/tests/Controllers/BeatmapsControllerSoloScoresTest.php @@ -204,13 +204,6 @@ public function testQuery(array $scoreKeys, array $params) } } - public function testUserRank() - { - $this->actingAs(static::$otherUser) - ->json('GET', route('beatmaps.solo-scores', static::$beatmap), $params) - ->assertJsonPath('user_score.position', 2); - } - public function dataProviderForTestQuery(): array { return [ From f75e9ef65f3a04899c3f76ba75b66a925439b89f Mon Sep 17 00:00:00 2001 From: nanaya Date: Fri, 16 Sep 2022 22:06:06 +0900 Subject: [PATCH 036/127] Add missing imports --- tests/Models/Solo/ScoreEsIndexTest.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/Models/Solo/ScoreEsIndexTest.php b/tests/Models/Solo/ScoreEsIndexTest.php index 0653b8b7666..295d77c3bbc 100644 --- a/tests/Models/Solo/ScoreEsIndexTest.php +++ b/tests/Models/Solo/ScoreEsIndexTest.php @@ -9,10 +9,16 @@ use App\Libraries\Search\ScoreSearch; use App\Models\Beatmap; +use App\Models\Beatmapset; use App\Models\Country; +use App\Models\Genre; use App\Models\Group; +use App\Models\Language; use App\Models\Solo\Score; use App\Models\User; +use App\Models\UserGroup; +use App\Models\UserGroupEvent; +use App\Models\UserRelation; use Tests\TestCase; /** From 740402af52bff5cc5998d4144222fa8199b59b16 Mon Sep 17 00:00:00 2001 From: nanaya Date: Fri, 16 Sep 2022 22:07:11 +0900 Subject: [PATCH 037/127] Call parent tearDown --- tests/Models/Solo/ScoreEsIndexTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/Models/Solo/ScoreEsIndexTest.php b/tests/Models/Solo/ScoreEsIndexTest.php index 295d77c3bbc..b3e4aa8b162 100644 --- a/tests/Models/Solo/ScoreEsIndexTest.php +++ b/tests/Models/Solo/ScoreEsIndexTest.php @@ -97,6 +97,8 @@ public static function setUpBeforeClass(): void public static function tearDownAfterClass(): void { + parent::tearDownAfterClass(); + (new static())->refreshApplication(); Beatmap::truncate(); Beatmapset::truncate(); From b75d27313ff1f2a1ae10da5a6327ade8dcb25a70 Mon Sep 17 00:00:00 2001 From: nanaya Date: Tue, 20 Sep 2022 23:27:27 +0900 Subject: [PATCH 038/127] Only ScoreBest has userRank --- app/Transformers/ScoreTransformer.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Transformers/ScoreTransformer.php b/app/Transformers/ScoreTransformer.php index 06b1a72d793..93a60273580 100644 --- a/app/Transformers/ScoreTransformer.php +++ b/app/Transformers/ScoreTransformer.php @@ -182,12 +182,12 @@ public function includeMatch(LegacyMatch\Score $score) ]); } - public function includeRankCountry(ScoreModel|SoloScore $score) + public function includeRankCountry(ScoreBest|SoloScore $score) { return $this->primitive($score->userRank(['type' => 'country'])); } - public function includeRankGlobal(ScoreModel|SoloScore $score) + public function includeRankGlobal(ScoreBest|SoloScore $score) { return $this->primitive($score->userRank([])); } From e26c87f2d3b644c9194494aaf7ea3bce0e73c257 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Wed, 28 Sep 2022 17:06:19 +0900 Subject: [PATCH 039/127] always trigger native scrollIntoView instead --- .../assets/lib/beatmap-discussions/editor.tsx | 25 ++++++------------- 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/resources/assets/lib/beatmap-discussions/editor.tsx b/resources/assets/lib/beatmap-discussions/editor.tsx index 74ee6ef27e9..825f8684765 100644 --- a/resources/assets/lib/beatmap-discussions/editor.tsx +++ b/resources/assets/lib/beatmap-discussions/editor.tsx @@ -12,7 +12,6 @@ import { route } from 'laroute'; import { filter } from 'lodash'; import core from 'osu-core-singleton'; import * as React from 'react'; -import scrollIntoView from 'scroll-into-view-if-needed'; import { createEditor, Editor as SlateEditor, Element as SlateElement, Node as SlateNode, NodeEntry, Range, Text, Transforms } from 'slate'; import { withHistory } from 'slate-history'; import { Editable, ReactEditor, RenderElementProps, RenderLeafProps, Slate, withReact } from 'slate-react'; @@ -418,24 +417,14 @@ export default class Editor extends React.Component { this.resetEditorValue(); }; - // overrides slate Editable's defaultScrollSelectionIntoView with a boundary to stop body from scrolling on input. - // https://github.com/ianstormtaylor/slate/blob/ca9e2147c17cc22bb24c098651c12da60d44d8b9/packages/slate-react/src/components/editable.tsx#L1170 + // Overrides slate Editable's defaultScrollSelectionIntoView and always use browser's version + // There's something wrong with slate's range detection in the prior calling function that causes + // letters and numbers to be differently. scrollSelectionIntoView = (editor: ReactEditor, domRange: DOMRange) => { - if (!editor.selection - || (editor.selection && Range.isCollapsed(editor.selection)) - ) { - const leafEl = domRange.startContainer.parentElement; - if (leafEl != null) { - leafEl.getBoundingClientRect = () => domRange.getBoundingClientRect(); - scrollIntoView(leafEl, { - boundary: this.scrollContainerRef.current, - scrollMode: 'if-needed', - }); - - // @ts-expect-error an unorthodox delete D: - delete leafEl.getBoundingClientRect; - } - } + domRange.startContainer.parentElement?.scrollIntoView({ + block: 'nearest', + inline: 'nearest' , + }); }; serialize = () => serializeSlateDocument(this.state.value); From b8a5221c0cd6511a32535c220d9e6ebab681f76a Mon Sep 17 00:00:00 2001 From: bakaneko Date: Wed, 28 Sep 2022 17:15:47 +0900 Subject: [PATCH 040/127] add some extra scroll-padding so it's not right on the edge of the screen --- resources/assets/less/layout.less | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/resources/assets/less/layout.less b/resources/assets/less/layout.less index c369592c14c..bd2d823d63b 100644 --- a/resources/assets/less/layout.less +++ b/resources/assets/less/layout.less @@ -48,10 +48,11 @@ html, body { } html { - scroll-padding-top: @nav2-height--pinned; + scroll-padding-top: calc(@nav2-height--pinned + 1em); + scroll-padding-bottom: 1em; @media @mobile { - scroll-padding-top: @navbar-height; + scroll-padding-top: calc(@navbar-height + 1em); } } From 4312af21f2cc5e3147f7729a6d5b1d2147cc8078 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Wed, 28 Sep 2022 19:30:09 +0900 Subject: [PATCH 041/127] bump slate version --- package.json | 2 +- yarn.lock | 125 +++++++++++---------------------------------------- 2 files changed, 27 insertions(+), 100 deletions(-) diff --git a/package.json b/package.json index 5ef32a7e826..6cee2143649 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "react-transition-group": "^4.4.2", "remark-parse": "^7.0.1", "shopify-buy": "^2.6.1", - "slate": "^0.81.1", + "slate": "^0.81.3", "slate-history": "^0.66.0", "slate-react": "^0.81.0", "terser": "^4.8.1", diff --git a/yarn.lock b/yarn.lock index dcf9cf412ab..1db8a88fe2e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -570,12 +570,7 @@ resolved "https://registry.yarnpkg.com/@types/js-cookie/-/js-cookie-2.2.6.tgz#f1a1cb35aff47bc5cfb05cb0c441ca91e914c26f" integrity sha512-+oY0FDTO2GYKEV0YPvSshGq9t7YozVkgvXLty7zogQNuCxBhT9/3INX9Q7H1aRZ4SUDRXAKlJuA4EA5nTt7SNw== -"@types/json-schema@^7.0.3", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.6": - version "7.0.9" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" - integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== - -"@types/json-schema@^7.0.9": +"@types/json-schema@^7.0.3", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.6", "@types/json-schema@^7.0.9": version "7.0.11" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== @@ -586,9 +581,9 @@ integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= "@types/lodash@^4.14.149", "@types/lodash@^4.14.151": - version "4.14.151" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.151.tgz#7d58cac32bedb0ec37cb7f99094a167d6176c9d5" - integrity sha512-Zst90IcBX5wnwSu7CAS0vvJkTjTELY4ssKbHiTnGcJgi170uiS8yQDdc3v6S77bRqYQIN1App5a1Pc2lceE5/g== + version "4.14.185" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.185.tgz#c9843f5a40703a8f5edfd53358a58ae729816908" + integrity sha512-evMDG1bC4rgQg4ku9tKpuMh5iBNEwNa3tf9zRHdP1qlv+1WUg44xat4IxCE14gIpZRGUUWAx2VhItCZc25NfMA== "@types/minimatch@*": version "3.0.3" @@ -1452,7 +1447,7 @@ braces@^2.3.1, braces@^2.3.2: split-string "^3.0.2" to-regex "^3.0.1" -braces@^3.0.1, braces@^3.0.2, braces@~3.0.2: +braces@^3.0.2, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== @@ -1993,10 +1988,10 @@ component-emitter@^1.2.1, component-emitter@~1.3.0: resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== -compute-scroll-into-view@^1.0.16: - version "1.0.16" - resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.16.tgz#5b7bf4f7127ea2c19b750353d7ce6776a90ee088" - integrity sha512-a85LHKY81oQnikatZYA90pufpZ6sQx++BoCxOEMsjpZx+ZnaKGQnCyCehTRr/1p9GBIAHTjcU9k71kSYWloLiQ== +compute-scroll-into-view@^1.0.17: + version "1.0.17" + resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.17.tgz#6a88f18acd9d42e9cf4baa6bec7e0522607ab7ab" + integrity sha512-j4dx+Fb0URmzbwwMUrhqWM2BEWHdFGx+qZ9qqASHRPqvTYdqvWnHg0H1hIbcyLnvgnoNAVMlwkepyqM3DaIFUg== computed-style@~0.1.3: version "0.1.4" @@ -2691,14 +2686,7 @@ debug@^3.2.6, debug@^3.2.7: dependencies: ms "^2.1.1" -debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.3, debug@~4.3.1, debug@~4.3.2: - version "4.3.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" - integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== - dependencies: - ms "2.1.2" - -debug@^4.3.4: +debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.3, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -3511,19 +3499,7 @@ fast-glob@^2.0.2: merge2 "^1.2.3" micromatch "^3.1.10" -fast-glob@^3.1.1, fast-glob@^3.2.4: - version "3.2.5" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.5.tgz#7939af2a656de79a4f1901903ee8adcaa7cb9661" - integrity sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.0" - merge2 "^1.3.0" - micromatch "^4.0.2" - picomatch "^2.2.1" - -fast-glob@^3.2.9: +fast-glob@^3.2.4, fast-glob@^3.2.9: version "3.2.11" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== @@ -3905,7 +3881,7 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" -glob-parent@^5.0.0, glob-parent@^5.1.0, glob-parent@^5.1.1, glob-parent@^5.1.2, glob-parent@~5.1.2: +glob-parent@^5.0.0, glob-parent@^5.1.1, glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== @@ -3984,19 +3960,7 @@ globals@^13.6.0: dependencies: type-fest "^0.20.2" -globby@^11.0.1: - version "11.0.3" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.3.tgz#9b1f0cb523e171dd1ad8c7b2a9fb4b644b9593cb" - integrity sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg== - dependencies: - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.1.1" - ignore "^5.1.4" - merge2 "^1.3.0" - slash "^3.0.0" - -globby@^11.1.0: +globby@^11.0.1, globby@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== @@ -4280,11 +4244,6 @@ ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -ignore@^5.1.4: - version "5.1.8" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" - integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== - ignore@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" @@ -4656,14 +4615,7 @@ is-glob@^3.1.0: dependencies: is-extglob "^2.1.0" -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" - integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== - dependencies: - is-extglob "^2.1.1" - -is-glob@^4.0.3: +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== @@ -5564,15 +5516,7 @@ micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: snapdragon "^0.8.1" to-regex "^3.0.2" -micromatch@^4.0.0, micromatch@^4.0.2: - version "4.0.4" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" - integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== - dependencies: - braces "^3.0.1" - picomatch "^2.2.3" - -micromatch@^4.0.4: +micromatch@^4.0.0, micromatch@^4.0.4: version "4.0.5" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== @@ -6416,12 +6360,7 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3: - version "2.3.0" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" - integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== - -picomatch@^2.3.1: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -7143,12 +7082,7 @@ regexp.prototype.flags@^1.3.1: call-bind "^1.0.2" define-properties "^1.1.3" -regexpp@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" - integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== - -regexpp@^3.2.0: +regexpp@^3.1.0, regexpp@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== @@ -7487,11 +7421,11 @@ schema-utils@^3.0.0: ajv-keywords "^3.5.2" scroll-into-view-if-needed@^2.2.20: - version "2.2.26" - resolved "https://registry.yarnpkg.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.26.tgz#e4917da0c820135ff65ad6f7e4b7d7af568c4f13" - integrity sha512-SQ6AOKfABaSchokAmmaxVnL9IArxEnLEX9j4wAZw+x4iUTb40q7irtHG3z4GtAWz5veVZcCnubXDBRyLVQaohw== + version "2.2.29" + resolved "https://registry.yarnpkg.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.29.tgz#551791a84b7e2287706511f8c68161e4990ab885" + integrity sha512-hxpAR6AN+Gh53AdAimHM6C8oTN1ppwVZITihix+WqalywBeFcQ6LdQP5ABNl26nX8GTEL7VT+b8lKpdqq65wXg== dependencies: - compute-scroll-into-view "^1.0.16" + compute-scroll-into-view "^1.0.17" "semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: version "5.7.1" @@ -7503,14 +7437,7 @@ semver@^6.0.0, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@^7.2.1, semver@^7.3.2, semver@^7.3.4: - version "7.3.5" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" - integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== - dependencies: - lru-cache "^6.0.0" - -semver@^7.3.7: +semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.7: version "7.3.7" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== @@ -7645,10 +7572,10 @@ slate-react@^0.81.0: scroll-into-view-if-needed "^2.2.20" tiny-invariant "1.0.6" -slate@^0.81.1: - version "0.81.1" - resolved "https://registry.yarnpkg.com/slate/-/slate-0.81.1.tgz#98d9f87b1ea2d648bfbab2739dcb1ba897f3bba0" - integrity sha512-nmqphQb2qnlJpPMKsoxeWShpa+pOlKfy6XVdmlTuOtgWeGethM6SMPSRTrhh5UF/G+3/IoXhfbKF7o3iDZCbWw== +slate@^0.81.3: + version "0.81.3" + resolved "https://registry.yarnpkg.com/slate/-/slate-0.81.3.tgz#47563c50a094274112bd46a856dcb1e3ddf94dab" + integrity sha512-9rME3rSOsR76BsTGezNp6kiwjJL4yVJLwVQawj9xUf8wEZqoPU8d38hyQ3Jeg1SG6me2aS43m6H+n163/BhGWw== dependencies: immer "^9.0.6" is-plain-object "^5.0.0" From 6daddd4b26462201b539c636effb4b48a2437668 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Wed, 28 Sep 2022 19:46:13 +0900 Subject: [PATCH 042/127] lodash types now has DebouncedFunc which can be type infered --- package.json | 2 +- .../beatmap-discussions/editor-insertion-menu.tsx | 12 ++++++------ yarn.lock | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 6cee2143649..54035efc188 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "@types/jquery.scrollto": "^1.4.29", "@types/jqueryui": "^1.12.16", "@types/js-cookie": "^2.2.6", - "@types/lodash": "^4.14.151", + "@types/lodash": "^4.14.185", "@types/react": "^17.0.40", "@types/react-dom": "^17.0.13", "@types/react-transition-group": "^4.4.4", diff --git a/resources/assets/lib/beatmap-discussions/editor-insertion-menu.tsx b/resources/assets/lib/beatmap-discussions/editor-insertion-menu.tsx index 687012ab695..2d8be3642fa 100644 --- a/resources/assets/lib/beatmap-discussions/editor-insertion-menu.tsx +++ b/resources/assets/lib/beatmap-discussions/editor-insertion-menu.tsx @@ -4,7 +4,7 @@ import { discussionTypeIcons } from 'beatmap-discussions/discussion-type'; import { Portal } from 'components/portal'; import BeatmapExtendedJson from 'interfaces/beatmap-extended-json'; -import { Cancelable, throttle } from 'lodash'; +import { throttle } from 'lodash'; import * as React from 'react'; import { Editor as SlateEditor, Element as SlateElement, Node as SlateNode, Point, Text as SlateText, Transforms } from 'slate'; import { ReactEditor } from 'slate-react'; @@ -26,11 +26,11 @@ export class EditorInsertionMenu extends React.Component { private readonly insertRef: React.RefObject = React.createRef(); private mouseOver = false; private scrollContainer: HTMLElement | undefined; - private readonly throttledContainerMouseExit: (() => void) & Cancelable; - private readonly throttledContainerMouseMove: ((event: JQuery.MouseMoveEvent) => void) & Cancelable; - private readonly throttledMenuMouseEnter: (() => void) & Cancelable; - private readonly throttledMenuMouseExit: (() => void) & Cancelable; - private readonly throttledScroll: (() => void) & Cancelable; + private readonly throttledContainerMouseExit; + private readonly throttledContainerMouseMove; + private readonly throttledMenuMouseEnter; + private readonly throttledMenuMouseExit; + private readonly throttledScroll; constructor(props: Props) { super(props); diff --git a/yarn.lock b/yarn.lock index 1db8a88fe2e..a33c29cf5b2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -580,7 +580,7 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= -"@types/lodash@^4.14.149", "@types/lodash@^4.14.151": +"@types/lodash@^4.14.149", "@types/lodash@^4.14.185": version "4.14.185" resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.185.tgz#c9843f5a40703a8f5edfd53358a58ae729816908" integrity sha512-evMDG1bC4rgQg4ku9tKpuMh5iBNEwNa3tf9zRHdP1qlv+1WUg44xat4IxCE14gIpZRGUUWAx2VhItCZc25NfMA== From 6e8102500d50b4e9e84bdf6cb9d7dea5e8ec8154 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Wed, 28 Sep 2022 22:49:36 +0900 Subject: [PATCH 043/127] bump version some more --- package.json | 4 ++-- yarn.lock | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 54035efc188..f053cb09ab6 100644 --- a/package.json +++ b/package.json @@ -76,9 +76,9 @@ "react-transition-group": "^4.4.2", "remark-parse": "^7.0.1", "shopify-buy": "^2.6.1", - "slate": "^0.81.3", + "slate": "^0.82.1", "slate-history": "^0.66.0", - "slate-react": "^0.81.0", + "slate-react": "^0.83.0", "terser": "^4.8.1", "terser-webpack-plugin": "^1.4.1", "timeago": "^1.5.0", diff --git a/yarn.lock b/yarn.lock index a33c29cf5b2..8c22bb83320 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7558,10 +7558,10 @@ slate-history@^0.66.0: dependencies: is-plain-object "^5.0.0" -slate-react@^0.81.0: - version "0.81.0" - resolved "https://registry.yarnpkg.com/slate-react/-/slate-react-0.81.0.tgz#248eb688ce01f23680ce2554625fd60676614962" - integrity sha512-bwryad4EvOmc7EFKb8aGg9DWNDh3KvToaggGieIgGTTbHJYHc9ADFC3A87Ittlpd5XUVopR0MpChQ3g3ODyvqw== +slate-react@^0.83.0: + version "0.83.0" + resolved "https://registry.yarnpkg.com/slate-react/-/slate-react-0.83.0.tgz#ef48ef54bb9c61dc318431cf0a60e79c490a0e2d" + integrity sha512-P+Pv7oPcd1CebRYOGziGM0fqwUrGEqophrb3XnxCN3HbNTIll70dbAsJZxkXIDxp727a+8FcLl8X105tGw7WRA== dependencies: "@types/is-hotkey" "^0.1.1" "@types/lodash" "^4.14.149" @@ -7572,10 +7572,10 @@ slate-react@^0.81.0: scroll-into-view-if-needed "^2.2.20" tiny-invariant "1.0.6" -slate@^0.81.3: - version "0.81.3" - resolved "https://registry.yarnpkg.com/slate/-/slate-0.81.3.tgz#47563c50a094274112bd46a856dcb1e3ddf94dab" - integrity sha512-9rME3rSOsR76BsTGezNp6kiwjJL4yVJLwVQawj9xUf8wEZqoPU8d38hyQ3Jeg1SG6me2aS43m6H+n163/BhGWw== +slate@^0.82.1: + version "0.82.1" + resolved "https://registry.yarnpkg.com/slate/-/slate-0.82.1.tgz#cf43cb828c980734dab01c9bbb517fd4d20892f7" + integrity sha512-3mdRdq7U3jSEoyFrGvbeb28hgrvrr4NdFCtJX+IjaNvSFozY0VZd/CGHF0zf/JDx7aEov864xd5uj0HQxxEWTQ== dependencies: immer "^9.0.6" is-plain-object "^5.0.0" From ddb3229fe9da45a7a60a383d512148feb279d1d4 Mon Sep 17 00:00:00 2001 From: Matheus Filipe dos Santos Reinert Date: Fri, 14 Oct 2022 17:16:44 -0300 Subject: [PATCH 044/127] Add getForcedWidth and getForcedHeight methods --- app/Models/Contest.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/app/Models/Contest.php b/app/Models/Contest.php index 16c3f7963b5..0a393b58d22 100644 --- a/app/Models/Contest.php +++ b/app/Models/Contest.php @@ -360,4 +360,22 @@ public function getExtraOptions() return $this->extra_options; }); } + + public function getForcedWidth() + { + if ($this->type !== 'art') { + return false; + } + + return $this->getExtraOptions()['forced_width'] ?? false; + } + + public function getForcedHeight() + { + if ($this->type !== 'art') { + return false; + } + + return $this->getExtraOptions()['forced_height'] ?? false; + } } From 2e4397153dc39cfe92dd2f8f6d4d02d33b0f7991 Mon Sep 17 00:00:00 2001 From: Matheus Filipe dos Santos Reinert Date: Fri, 14 Oct 2022 17:17:27 -0300 Subject: [PATCH 045/127] Add server-side image size validation for art contests --- app/Http/Controllers/ContestEntriesController.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/app/Http/Controllers/ContestEntriesController.php b/app/Http/Controllers/ContestEntriesController.php index 244b2b85695..d89d4398dab 100644 --- a/app/Http/Controllers/ContestEntriesController.php +++ b/app/Http/Controllers/ContestEntriesController.php @@ -65,6 +65,18 @@ public function store() abort(413); } + if ($contest->type === 'art') { + if (empty(Request::file('entry')->getContent())) { + abort(400); + } + + [$width, $height] = getimagesizefromstring(Request::file('entry')->getContent()); + + if ($contest->getForcedWidth() !== $width || $contest->getForcedHeight() !== $height) { + abort(400); + } + } + UserContestEntry::upload( Request::file('entry'), $user, From b900988bc43973cad52363652c9ca6ac009cf713 Mon Sep 17 00:00:00 2001 From: Matheus Filipe dos Santos Reinert Date: Fri, 14 Oct 2022 17:18:06 -0300 Subject: [PATCH 046/127] Add forced_width and forced_height to transform --- app/Transformers/ContestTransformer.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/Transformers/ContestTransformer.php b/app/Transformers/ContestTransformer.php index 714157625fe..49f5b6fbf5f 100644 --- a/app/Transformers/ContestTransformer.php +++ b/app/Transformers/ContestTransformer.php @@ -32,6 +32,8 @@ public function transform(Contest $contest) 'submitted_beatmaps' => $contest->isSubmittedBeatmaps(), 'thumbnail_shape' => $contest->thumbnail_shape, 'type' => $contest->type, + 'forced_width' => $contest->getForcedWidth(), + 'forced_height' => $contest->getForcedHeight(), 'voting_ends_at' => json_time($contest->voting_ends_at), ]; } From a14ce9740e984dfc6e092c1343225daf288d9479 Mon Sep 17 00:00:00 2001 From: Matheus Filipe dos Santos Reinert Date: Fri, 14 Oct 2022 17:18:26 -0300 Subject: [PATCH 047/127] Add string to be displayed as error --- resources/lang/en/contest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/en/contest.php b/resources/lang/en/contest.php index bdf449dddf4..cdabbd82cd4 100644 --- a/resources/lang/en/contest.php +++ b/resources/lang/en/contest.php @@ -50,6 +50,7 @@ 'beatmap' => 'Only .osu files are accepted for this contest.', 'music' => 'Only .mp3 files are accepted for this contest.', ], + 'wrong_dimensions' => 'Entries for this contest must be :widthx:height', 'too_big' => 'Entries for this contest can only be up to :limit.', ], 'beatmaps' => [ From bb2a1164be235f9a9afbb3202b833caa5a4d7bb7 Mon Sep 17 00:00:00 2001 From: Matheus Filipe dos Santos Reinert Date: Fri, 14 Oct 2022 17:19:05 -0300 Subject: [PATCH 048/127] Add client-side validation for entries with wrong image dimensions --- .../assets/lib/contest-entry/uploader.coffee | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/resources/assets/lib/contest-entry/uploader.coffee b/resources/assets/lib/contest-entry/uploader.coffee index 23af943d864..82ca1192317 100644 --- a/resources/assets/lib/contest-entry/uploader.coffee +++ b/resources/assets/lib/contest-entry/uploader.coffee @@ -78,6 +78,15 @@ export class Uploader extends React.Component osu.popup osu.trans('contest.entry.too_big', limit: osu.formatBytes(maxSize, 0)), 'danger' return + if @props.contest.type == 'art' + image = await @convertFileToImage file + + if image.width != @props.contest.forced_width || image.height != @props.contest.forced_height + osu.popup osu.trans('contest.entry.wrong_dimensions', + width: @props.contest.forced_width, + height: @props.contest.forced_height), 'danger' + return + data.submit() submit: -> @@ -95,6 +104,16 @@ export class Uploader extends React.Component .fileupload 'destroy' .remove() + convertFileToImage: (file) => + new Promise (resolve, reject) -> + image = new Image() + reader = new FileReader() + reader.onload = () -> image.src = reader.result + reader.onerror = (error) -> reject(error) + image.onload = () -> resolve(image) + reader.readAsDataURL(file) + + render: => div className: classWithModifiers 'contest-userentry', From 725b7910f33de48e508de4f7b51d6f6268022f0c Mon Sep 17 00:00:00 2001 From: Matheus Filipe dos Santos Reinert Date: Sun, 16 Oct 2022 14:55:21 -0300 Subject: [PATCH 049/127] Remove unnecessary if statement --- app/Models/Contest.php | 8 -------- 1 file changed, 8 deletions(-) diff --git a/app/Models/Contest.php b/app/Models/Contest.php index 0a393b58d22..6cd3869d351 100644 --- a/app/Models/Contest.php +++ b/app/Models/Contest.php @@ -363,19 +363,11 @@ public function getExtraOptions() public function getForcedWidth() { - if ($this->type !== 'art') { - return false; - } - return $this->getExtraOptions()['forced_width'] ?? false; } public function getForcedHeight() { - if ($this->type !== 'art') { - return false; - } - return $this->getExtraOptions()['forced_height'] ?? false; } } From 8752d2db8b69ca9185f670ef5486215e8fa8c4b1 Mon Sep 17 00:00:00 2001 From: Matheus Filipe dos Santos Reinert Date: Sun, 16 Oct 2022 14:56:00 -0300 Subject: [PATCH 050/127] Check type of forced dimensions to avoid eventual bugs caused by type juggling --- app/Http/Controllers/ContestEntriesController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/ContestEntriesController.php b/app/Http/Controllers/ContestEntriesController.php index d89d4398dab..0674110fd22 100644 --- a/app/Http/Controllers/ContestEntriesController.php +++ b/app/Http/Controllers/ContestEntriesController.php @@ -65,7 +65,7 @@ public function store() abort(413); } - if ($contest->type === 'art') { + if ($contest->type === 'art' && $contest->getForcedWidth() !== false && $contest->getForcedHeight() !== false) { if (empty(Request::file('entry')->getContent())) { abort(400); } From b3925915370b8df50143a3deb5ee96dc038baca8 Mon Sep 17 00:00:00 2001 From: Matheus Filipe dos Santos Reinert Date: Sun, 16 Oct 2022 14:56:21 -0300 Subject: [PATCH 051/127] Create test case for ContestEntriesController --- .../ContestEntriesControllerTest.php | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 tests/Controllers/ContestEntriesControllerTest.php diff --git a/tests/Controllers/ContestEntriesControllerTest.php b/tests/Controllers/ContestEntriesControllerTest.php new file mode 100644 index 00000000000..63b4a1372f5 --- /dev/null +++ b/tests/Controllers/ContestEntriesControllerTest.php @@ -0,0 +1,80 @@ +prepareForStore(); + $file = File::fake()->create('entry.osz'); + + $this + ->actingAsVerified($this->user) + ->postJson('/community/contest-entries', ['entry' => $file, 'contest_id' => $this->contest->id]) + ->assertStatus(422); + } + + public function testStoreEntryExceedingMaxFileSize() + { + $this->prepareForStore(); + $file = File::fake()->create('test.png', 8 * 1024 * 1024 * 2); + + $this + ->actingAsVerified($this->user) + ->postJson('/community/contest-entries', ['entry' => $file, 'contest_id' => $this->contest->id]) + ->assertStatus(413); + } + + public function testStoreEntryWithWrongForcedDimensions() + { + $this->prepareForStore(); + $file = File::image('entry.png', 1600, 900); + + $this + ->actingAsVerified($this->user) + ->postJson('/community/contest-entries', ['entry' => $file, 'contest_id' => $this->contest->id]) + ->assertStatus(400); + } + + public function testStoreEntryWithCorrectRequirements() + { + $this->prepareForStore(); + $file = File::image('test.png', 1920, 1080); + + $this + ->actingAsVerified($this->user) + ->postJson('/community/contest-entries', ['entry' => $file, 'contest_id' => $this->contest->id]) + ->assertStatus(200); + } + + private function prepareForStore() + { + $this->user = User::factory()->create(); + $this->contest = Contest::create([ + 'name' => 'Test', + 'description_enter' => 'This is just a test!', + 'description_voting' => 'This is just a test!', + 'entry_starts_at' => new DateTime(), + 'entry_ends_at' => (new DateTime())->modify('+1 day'), + 'extra_options' => ['forced_width' => 1920, 'forced_height' => 1080], + 'header_url' => 'https://assets.ppy.sh/contests/154/header.jpg', + 'max_entries' => 1, + 'max_votes' => 1, + 'show_votes' => true, + 'type' => 'art', + 'visible' => true, + 'voting_ends_at' => (new DateTime())->modify('+2 day'), + 'voting_starts_at' => (new DateTime())->modify('+3 day'), + ]); + } +} From baa3d35302689fcf2ceaba9939da68b428aa1d75 Mon Sep 17 00:00:00 2001 From: nanaya Date: Tue, 18 Oct 2022 15:42:05 +0900 Subject: [PATCH 052/127] Keep original controller/action info for datadog Having all errors logged under "error" controller/action isn't very useful. The `getCurrent` function is still used for rendering correct error page. --- app/Http/Middleware/DatadogMetrics.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Middleware/DatadogMetrics.php b/app/Http/Middleware/DatadogMetrics.php index 21a65c10d8d..4548d760f14 100644 --- a/app/Http/Middleware/DatadogMetrics.php +++ b/app/Http/Middleware/DatadogMetrics.php @@ -32,7 +32,7 @@ protected static function logDuration(Request $request, Response $response, $sta 'status_code_extra' => $request->attributes->get('status_code_extra'), ]; - $tags = array_merge($tags, app('route-section')->getCurrent()); + $tags = array_merge($tags, app('route-section')->getOriginal()); Datadog::timing(config('datadog-helper.prefix_web').'.request_time', $duration, 1, $tags); } From a032fe397ba635f9a138b59b99b22c30d769dada Mon Sep 17 00:00:00 2001 From: nanaya Date: Thu, 20 Oct 2022 21:51:55 +0900 Subject: [PATCH 053/127] Remove duplicated page titles --- app/helpers.php | 30 +++++++++++++++-- resources/assets/lib/components/header-v4.tsx | 33 +++++++++++++++++-- resources/lang/en/page_title.php | 30 ----------------- 3 files changed, 57 insertions(+), 36 deletions(-) diff --git a/app/helpers.php b/app/helpers.php index 98e46b8df6f..785074e507c 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -822,14 +822,38 @@ function page_description($extra) return blade_safe(implode(' » ', array_map('e', $parts))); } +// sync with pageTitleMap in header-v4.tsx function page_title() { $currentRoute = app('route-section')->getCurrent(); $checkLocale = config('app.fallback_locale'); + + $actionKey = "{$currentRoute['namespace']}.{$currentRoute['controller']}.{$currentRoute['action']}"; + $actionKey = match ($actionKey) { + 'forum.topic_watches_controller.index' => 'main.home_controller.index', + 'main.account_controller.edit' => 'main.home_controller.index', + 'main.beatmapset_watches_controller.index' => 'main.home_controller.index', + 'main.follows_controller.index' => 'main.home_controller.index', + 'main.friends_controller.index' => 'main.home_controller.index', + default => $actionKey, + }; + $controllerKey = "{$currentRoute['namespace']}.{$currentRoute['controller']}._"; + $controllerKey = match ($controllerKey) { + 'main.artist_tracks_controller._' => 'main.artists_controller._', + 'main.store_controller._' => 'store._', + 'multiplayer.rooms_controller._' => 'main.ranking_controller._', + default => $controllerKey, + }; + $namespaceKey = "{$currentRoute['namespace']}._"; + $namespaceKey = match ($namespaceKey) { + 'admin_forum._' => 'admin._', + 'admin_store._' => 'admin._', + default => $namespaceKey, + }; $keys = [ - "page_title.{$currentRoute['namespace']}.{$currentRoute['controller']}.{$currentRoute['action']}", - "page_title.{$currentRoute['namespace']}.{$currentRoute['controller']}._", - "page_title.{$currentRoute['namespace']}._", + "page_title.{$actionKey}", + "page_title.{$controllerKey}", + "page_title.{$namespaceKey}", ]; foreach ($keys as $key) { diff --git a/resources/assets/lib/components/header-v4.tsx b/resources/assets/lib/components/header-v4.tsx index d5ad00645b5..8663d92afdb 100644 --- a/resources/assets/lib/components/header-v4.tsx +++ b/resources/assets/lib/components/header-v4.tsx @@ -26,6 +26,26 @@ interface RouteSection { section: string; } +// sync with page_title in helpers.php +const pageTitleMap: Record<`${'action' | 'controller' | 'namespace'}Key`, Partial>> = { + actionKey: { + 'forum.topic_watches_controller.index': 'main.home_controller.index', + 'main.account_controller.edit': 'main.home_controller.index', + 'main.beatmapset_watches_controller.index': 'main.home_controller.index', + 'main.follows_controller.index': 'main.home_controller.index', + 'main.friends_controller.index': 'main.home_controller.index', + }, + controllerKey: { + 'main.artist_tracks_controller._': 'main.artists_controller._', + 'main.store_controller._': 'store._', + 'multiplayer.rooms_controller._': 'main.ranking_controller._', + }, + namespaceKey: { + 'admin_forum._': 'admin._', + 'admin_store._': 'admin._', + }, +} + export default class HeaderV4 extends React.Component { static defaultProps = { links: [], @@ -173,10 +193,17 @@ export default class HeaderV4 extends React.Component { private title() { const routeSection = parseJson('json-route-section'); + let actionKey = `${routeSection.namespace}.${routeSection.controller}.${routeSection.action}`; + actionKey = pageTitleMap.actionKey[actionKey] ?? actionKey; + let controllerKey = `${routeSection.namespace}.${routeSection.controller}._`; + controllerKey = pageTitleMap.controllerKey[controllerKey] ?? controllerKey; + let namespaceKey = `${routeSection.namespace}._`; + namespaceKey = pageTitleMap.namespaceKey[namespaceKey] ?? namespaceKey; + const keys = [ - `page_title.${routeSection.namespace}.${routeSection.controller}.${routeSection.action}`, - `page_title.${routeSection.namespace}.${routeSection.controller}._`, - `page_title.${routeSection.namespace}._`, + `page_title.${actionKey}`, + `page_title.${controllerKey}`, + `page_title.${namespaceKey}`, ]; for (const key of keys) { diff --git a/resources/lang/en/page_title.php b/resources/lang/en/page_title.php index 38770702fbc..61ec48a4453 100644 --- a/resources/lang/en/page_title.php +++ b/resources/lang/en/page_title.php @@ -7,12 +7,6 @@ 'admin' => [ '_' => 'admin', ], - 'admin_forum' => [ - '_' => 'admin', - ], - 'admin_store' => [ - '_' => 'admin', - ], 'error' => [ 'error' => [ '400' => 'invalid request', @@ -32,18 +26,11 @@ 'topic_logs_controller' => [ 'index' => 'topic logs', ], - 'topic_watches_controller' => [ - 'index' => 'dashboard', - ], ], 'main' => [ 'account_controller' => [ - 'edit' => 'dashboard', 'verify_link' => 'account verification', ], - 'artist_tracks_controller' => [ - '_' => 'featured artists', - ], 'artists_controller' => [ '_' => 'featured artists', ], @@ -62,9 +49,6 @@ 'beatmapset_events_controller' => [ '_' => 'beatmap history', ], - 'beatmapset_watches_controller' => [ - 'index' => 'dashboard', - ], 'beatmapsets_controller' => [ 'discussion' => 'beatmap discussion', 'index' => 'beatmap listing', @@ -82,12 +66,6 @@ 'contests_controller' => [ '_' => 'contests', ], - 'follows_controller' => [ - 'index' => 'dashboard', - ], - 'friends_controller' => [ - 'index' => 'dashboard', - ], 'groups_controller' => [ 'show' => 'groups', ], @@ -122,9 +100,6 @@ 'scores_controller' => [ '_' => 'performance', ], - 'store_controller' => [ - '_' => 'store', - ], 'tournaments_controller' => [ '_' => 'tournaments', ], @@ -136,11 +111,6 @@ '_' => 'wiki', ], ], - 'multiplayer' => [ - 'rooms_controller' => [ - '_' => 'rankings', - ], - ], 'passport' => [ 'authorization_controller' => [ '_' => 'authorize app', From 4674af0b6b0cf3e4224a7d38b80ed210c8880094 Mon Sep 17 00:00:00 2001 From: nanaya Date: Thu, 20 Oct 2022 22:00:22 +0900 Subject: [PATCH 054/127] There's no more Admin\Store namespace --- app/helpers.php | 1 - resources/assets/lib/components/header-v4.tsx | 1 - 2 files changed, 2 deletions(-) diff --git a/app/helpers.php b/app/helpers.php index 785074e507c..fac5afbc69e 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -847,7 +847,6 @@ function page_title() $namespaceKey = "{$currentRoute['namespace']}._"; $namespaceKey = match ($namespaceKey) { 'admin_forum._' => 'admin._', - 'admin_store._' => 'admin._', default => $namespaceKey, }; $keys = [ diff --git a/resources/assets/lib/components/header-v4.tsx b/resources/assets/lib/components/header-v4.tsx index 8663d92afdb..38738a1bf2c 100644 --- a/resources/assets/lib/components/header-v4.tsx +++ b/resources/assets/lib/components/header-v4.tsx @@ -42,7 +42,6 @@ const pageTitleMap: Record<`${'action' | 'controller' | 'namespace'}Key`, Partia }, namespaceKey: { 'admin_forum._': 'admin._', - 'admin_store._': 'admin._', }, } From c21c536c62be0465175545501d98a6a74625833a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 22 Jun 2022 16:14:53 +0900 Subject: [PATCH 055/127] Fix incorrect override function signatures --- app/Console/Commands/SilentEnabledCommand.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Console/Commands/SilentEnabledCommand.php b/app/Console/Commands/SilentEnabledCommand.php index a542e90bcf7..ea60ab3ea8c 100644 --- a/app/Console/Commands/SilentEnabledCommand.php +++ b/app/Console/Commands/SilentEnabledCommand.php @@ -10,14 +10,14 @@ abstract class SilentEnabledCommand extends Command { - public function info($string) + public function info($string, $verbosity = null) { if (!$this->option('silent')) { parent::info($string); } } - public function comment($string) + public function comment($string, $verbosity = null) { if (!$this->option('silent')) { parent::comment($string); From bf49edaba835537dfaab51bde92830ea60de217f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 22 Jun 2022 16:46:36 +0900 Subject: [PATCH 056/127] Fix deprecated calls to `abs` and `str_replace` PHP Deprecated: abs(): Passing null to parameter #1 ($num) of type int|float is deprecated in /Users/dean/Projects/osu-web/c onfig/osu.php on line 144 Deprecated: abs(): Passing null to parameter #1 ($num) of type int|float is deprecated in /Users/dean/Projects/osu-web/config /osu.php on line 144 PHP Deprecated: str_replace(): Passing null to parameter #3 ($subject) of type array|string is deprecated in /Users/dean/Pro jects/osu-web/config/osu.php on line 179 Deprecated: str_replace(): Passing null to parameter #3 ($subject) of type array|string is deprecated in /Users/dean/Projects /osu-web/config/osu.php on line 179 --- config/osu.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/osu.php b/config/osu.php index 8c252ec17c1..0545b1b0d45 100644 --- a/config/osu.php +++ b/config/osu.php @@ -143,7 +143,7 @@ ], ], 'oauth' => [ - 'retain_expired_tokens_days' => abs(get_int(env('OAUTH_RETAIN_EXPIRED_TOKENS_DAYS'))) ?? 30, + 'retain_expired_tokens_days' => abs(get_int(env('OAUTH_RETAIN_EXPIRED_TOKENS_DAYS')) ?? 30), 'max_user_clients' => get_int(env('OAUTH_MAX_USER_CLIENTS')) ?? 1, ], 'octane' => [ @@ -178,7 +178,7 @@ ], 'store' => [ - 'notice' => presence(str_replace('\n', "\n", env('STORE_NOTICE'))), + 'notice' => presence(str_replace('\n', "\n", env('STORE_NOTICE') ?? '')), ], 'twitch_client_id' => presence(env('TWITCH_CLIENT_ID')), 'twitch_client_secret' => presence(env('TWITCH_CLIENT_SECRET')), From 51bb43a18982bc591565851fffd77d74084bb4f5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 22 Jun 2022 17:06:09 +0900 Subject: [PATCH 057/127] Fix incorrect usage of `void` return methods --- app/Console/Commands/BuildsCreate.php | 6 ++++-- app/Console/Commands/EsIndexDocuments.php | 3 ++- app/Console/Commands/EsIndexWiki.php | 3 ++- app/Console/Commands/FixForumDisplayOrder.php | 3 ++- app/Console/Commands/FixMissingUserChannels.php | 6 ++++-- app/Console/Commands/FixUsernameChangeTopicCache.php | 6 ++++-- app/Console/Commands/ForumTopicCoversCleanup.php | 3 ++- app/Console/Commands/MigrateFreshAllCommand.php | 3 ++- app/Console/Commands/UserRecalculateRankCounts.php | 3 ++- app/Exceptions/Handler.php | 2 +- app/Http/Controllers/Payments/XsollaController.php | 4 +--- .../Notifications/BeatmapsetDiscussionPostNotification.php | 2 +- app/Jobs/Notifications/BeatmapsetDiscussionReviewNew.php | 2 +- app/Jobs/Notifications/BeatmapsetNotification.php | 2 +- app/Libraries/Session/Store.php | 2 +- app/Models/Forum/Topic.php | 3 ++- app/Models/UserClient.php | 3 ++- 17 files changed, 34 insertions(+), 22 deletions(-) diff --git a/app/Console/Commands/BuildsCreate.php b/app/Console/Commands/BuildsCreate.php index 4c1cd8f1586..ac4affd2c6f 100644 --- a/app/Console/Commands/BuildsCreate.php +++ b/app/Console/Commands/BuildsCreate.php @@ -34,7 +34,8 @@ public function handle() $streamId = get_int($this->option('stream-id')); if ($streamId === null) { - return $this->error('Missing stream-id'); + $this->error('Missing stream-id'); + return; } $stream = UpdateStream::findOrFail($streamId); @@ -42,7 +43,8 @@ public function handle() $build = $stream->createBuild(); if ($build === null) { - return $this->info('No build created (probably no orphan changelog entry).'); + $this->info('No build created (probably no orphan changelog entry).'); + return; } $this->info("Created build {$build->displayVersion()}"); diff --git a/app/Console/Commands/EsIndexDocuments.php b/app/Console/Commands/EsIndexDocuments.php index 60e9295a7ea..f89990fb07c 100644 --- a/app/Console/Commands/EsIndexDocuments.php +++ b/app/Console/Commands/EsIndexDocuments.php @@ -60,7 +60,8 @@ public function handle() $continue = $this->starterMessage($oldIndices); if (!$continue) { - return $this->error('User aborted!'); + $this->error('User aborted!'); + return; } $start = time(); diff --git a/app/Console/Commands/EsIndexWiki.php b/app/Console/Commands/EsIndexWiki.php index e19b80e3a0c..3d70d1ff913 100644 --- a/app/Console/Commands/EsIndexWiki.php +++ b/app/Console/Commands/EsIndexWiki.php @@ -58,7 +58,8 @@ public function handle() $continue = $this->starterMessage(); if (!$continue) { - return $this->error('User aborted!'); + $this->error('User aborted!'); + return; } if (!Es::getClient()->indices()->exists(['index' => [$this->indexName]])) { diff --git a/app/Console/Commands/FixForumDisplayOrder.php b/app/Console/Commands/FixForumDisplayOrder.php index 3e6f57cd7ee..00a49ae20e1 100644 --- a/app/Console/Commands/FixForumDisplayOrder.php +++ b/app/Console/Commands/FixForumDisplayOrder.php @@ -34,7 +34,8 @@ public function handle() $continue = $this->confirm('Proceed?'); if (!$continue) { - return $this->error('Aborted.'); + $this->error('Aborted.'); + return; } $this->startReorder(); diff --git a/app/Console/Commands/FixMissingUserChannels.php b/app/Console/Commands/FixMissingUserChannels.php index 222ca93dbef..425aa348bcb 100644 --- a/app/Console/Commands/FixMissingUserChannels.php +++ b/app/Console/Commands/FixMissingUserChannels.php @@ -35,7 +35,8 @@ public function handle() $continue = $this->confirm('Proceed?'); if (!$continue) { - return $this->error('Aborted.'); + $this->error('Aborted.'); + return; } $start = time(); @@ -60,7 +61,8 @@ public function handle() // reconfirm if (!$this->confirm("{$count} channels need to be repaired, proceed?")) { - return $this->error('Aborted.'); + $this->error('Aborted.'); + return; } $start = time(); diff --git a/app/Console/Commands/FixUsernameChangeTopicCache.php b/app/Console/Commands/FixUsernameChangeTopicCache.php index d0a9603b1df..838f34df510 100644 --- a/app/Console/Commands/FixUsernameChangeTopicCache.php +++ b/app/Console/Commands/FixUsernameChangeTopicCache.php @@ -39,7 +39,8 @@ public function handle() $continue = $this->confirm('WARNING! This will refresh the cache for forum topics effected by username changes after 2017/08/09'); if (!$continue) { - return $this->error('User aborted!'); + $this->error('User aborted!'); + return; } $start = time(); @@ -74,7 +75,8 @@ public function handle() // reconfirm. if (!$this->confirm("This will affect an estimated {$count} Topics.")) { - return $this->error('User aborted!'); + $this->error('User aborted!'); + return; } $start = time(); diff --git a/app/Console/Commands/ForumTopicCoversCleanup.php b/app/Console/Commands/ForumTopicCoversCleanup.php index 29a5a7ad90a..1e11f192b33 100644 --- a/app/Console/Commands/ForumTopicCoversCleanup.php +++ b/app/Console/Commands/ForumTopicCoversCleanup.php @@ -35,7 +35,8 @@ public function handle() $this->line("This will delete unused topic covers before {$createdBefore}."); if (!$this->option('yes') && !$this->confirm('Proceed?')) { - return $this->error('Aborted.'); + $this->error('Aborted.'); + return; } $progress = $this->output->createProgressBar(); diff --git a/app/Console/Commands/MigrateFreshAllCommand.php b/app/Console/Commands/MigrateFreshAllCommand.php index 48d28d5bbcf..e00f28f90ba 100644 --- a/app/Console/Commands/MigrateFreshAllCommand.php +++ b/app/Console/Commands/MigrateFreshAllCommand.php @@ -31,7 +31,8 @@ public function handle() $continue = $this->option('yes') || $this->confirm('continue?'); if (!$continue) { - return $this->error('User aborted!'); + $this->error('User aborted!'); + return; } foreach (array_keys($connections) as $database) { diff --git a/app/Console/Commands/UserRecalculateRankCounts.php b/app/Console/Commands/UserRecalculateRankCounts.php index f04d6159f22..a485d2b7bfd 100644 --- a/app/Console/Commands/UserRecalculateRankCounts.php +++ b/app/Console/Commands/UserRecalculateRankCounts.php @@ -40,7 +40,8 @@ public function handle() $continue = $this->confirm('This will recalculate and update the rank counts for user statistics, continue?'); if (!$continue) { - return $this->error('User aborted!'); + $this->error('User aborted!'); + return; } $start = time(); diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 7b7e638afe0..c2bfb2aa3c2 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -103,7 +103,7 @@ public function report(Throwable $e) $this->reportWithSentry($e); } - return parent::report($e); + parent::report($e); } /** diff --git a/app/Http/Controllers/Payments/XsollaController.php b/app/Http/Controllers/Payments/XsollaController.php index 3787631bdb9..687d0d17980 100644 --- a/app/Http/Controllers/Payments/XsollaController.php +++ b/app/Http/Controllers/Payments/XsollaController.php @@ -80,7 +80,7 @@ public function callback(HttpRequest $request) return ['ok']; } - $result = $processor->run(); + $processor->run(); } catch (ValidationException $exception) { Log::error($exception->getMessage()); @@ -100,8 +100,6 @@ public function callback(HttpRequest $request) // status code needs to be a 4xx code to make Xsolla an error to the user. return $this->errorResponse('Something went wrong.', 'FATAL_ERROR', 422); } - - return $result; } // After user has approved payment and redirected here by xsolla diff --git a/app/Jobs/Notifications/BeatmapsetDiscussionPostNotification.php b/app/Jobs/Notifications/BeatmapsetDiscussionPostNotification.php index 068185ac034..d4af3c64ded 100644 --- a/app/Jobs/Notifications/BeatmapsetDiscussionPostNotification.php +++ b/app/Jobs/Notifications/BeatmapsetDiscussionPostNotification.php @@ -65,6 +65,6 @@ public function handle() { $this->beatmapsetDiscussionPost->beatmapset->watches()->update(['last_notified' => $this->getTimestamp()]); - return parent::handle(); + parent::handle(); } } diff --git a/app/Jobs/Notifications/BeatmapsetDiscussionReviewNew.php b/app/Jobs/Notifications/BeatmapsetDiscussionReviewNew.php index 340622a8494..2a03c133f83 100644 --- a/app/Jobs/Notifications/BeatmapsetDiscussionReviewNew.php +++ b/app/Jobs/Notifications/BeatmapsetDiscussionReviewNew.php @@ -68,6 +68,6 @@ public function handle() { $this->beatmapsetDiscussion->beatmapset->watches()->update(['last_notified' => $this->getTimestamp()]); - return parent::handle(); + parent::handle(); } } diff --git a/app/Jobs/Notifications/BeatmapsetNotification.php b/app/Jobs/Notifications/BeatmapsetNotification.php index 9990848a1cb..bea9c025905 100644 --- a/app/Jobs/Notifications/BeatmapsetNotification.php +++ b/app/Jobs/Notifications/BeatmapsetNotification.php @@ -51,6 +51,6 @@ public function handle() { $this->beatmapset->watches()->update(['last_notified' => $this->getTimestamp()]); - return parent::handle(); + parent::handle(); } } diff --git a/app/Libraries/Session/Store.php b/app/Libraries/Session/Store.php index 38e80a0b83f..d86389a393b 100644 --- a/app/Libraries/Session/Store.php +++ b/app/Libraries/Session/Store.php @@ -73,7 +73,7 @@ public static function parseKey($key) public static function removeFullId($userId, $fullId) { - return static::removeKey($userId, config('cache.prefix').':'.$fullId); + static::removeKey($userId, config('cache.prefix').':'.$fullId); } public static function removeKey($userId, $key) diff --git a/app/Models/Forum/Topic.php b/app/Models/Forum/Topic.php index 4aa6c80e832..98eee96eb08 100644 --- a/app/Models/Forum/Topic.php +++ b/app/Models/Forum/Topic.php @@ -530,7 +530,8 @@ public function markRead($user, $markTime) // Duplicate entry. // Retry, hoping $status now contains something. if (is_sql_unique_exception($ex)) { - return $this->markRead($user, $markTime); + $this->markRead($user, $markTime); + return; } throw $ex; diff --git a/app/Models/UserClient.php b/app/Models/UserClient.php index beed50f8507..8f0b3c568d4 100644 --- a/app/Models/UserClient.php +++ b/app/Models/UserClient.php @@ -57,7 +57,8 @@ public static function markVerified($userId, $hash) $client->fill(['verified' => true])->save(); } catch (Exception $e) { if (is_sql_unique_exception($e)) { - return static::markVerified($userId, $hash); + static::markVerified($userId, $hash); + return; } throw $e; From 76dd07c7f3adfa34f7a1bd8c523b7d4ddff7f41e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 22 Jun 2022 17:50:29 +0900 Subject: [PATCH 058/127] Remove incorrect second parameter from `repairExtrasOrder` call --- app/Models/UserProfileCustomization.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Models/UserProfileCustomization.php b/app/Models/UserProfileCustomization.php index e9ba2bca802..d160c0b145a 100644 --- a/app/Models/UserProfileCustomization.php +++ b/app/Models/UserProfileCustomization.php @@ -246,7 +246,7 @@ public function getExtrasOrderAttribute($value) return static::SECTIONS; } - return static::repairExtrasOrder($newValue, true); + return static::repairExtrasOrder($newValue); } public function setExtrasOrderAttribute($value) From f7815d68e6d58fef8599bd506e4eb8035b29bae2 Mon Sep 17 00:00:00 2001 From: nanaya Date: Thu, 20 Oct 2022 22:03:34 +0900 Subject: [PATCH 059/127] Lint fix --- resources/assets/lib/components/header-v4.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/assets/lib/components/header-v4.tsx b/resources/assets/lib/components/header-v4.tsx index 38738a1bf2c..9f8eb139ecd 100644 --- a/resources/assets/lib/components/header-v4.tsx +++ b/resources/assets/lib/components/header-v4.tsx @@ -43,7 +43,7 @@ const pageTitleMap: Record<`${'action' | 'controller' | 'namespace'}Key`, Partia namespaceKey: { 'admin_forum._': 'admin._', }, -} +}; export default class HeaderV4 extends React.Component { static defaultProps = { From 473565f4ae58ac9b64ba94f895c9a1819074474a Mon Sep 17 00:00:00 2001 From: Matheus Filipe dos Santos Reinert Date: Thu, 20 Oct 2022 10:26:39 -0300 Subject: [PATCH 060/127] Return null if forced dimension is not set --- app/Models/Contest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Models/Contest.php b/app/Models/Contest.php index 6cd3869d351..df1477b0e8e 100644 --- a/app/Models/Contest.php +++ b/app/Models/Contest.php @@ -363,11 +363,11 @@ public function getExtraOptions() public function getForcedWidth() { - return $this->getExtraOptions()['forced_width'] ?? false; + return $this->getExtraOptions()['forced_width'] ?? null; } public function getForcedHeight() { - return $this->getExtraOptions()['forced_height'] ?? false; + return $this->getExtraOptions()['forced_height'] ?? null; } } From 666e8e8b1d660a2a55acee2e481c756ee14d6957 Mon Sep 17 00:00:00 2001 From: Matheus Filipe dos Santos Reinert Date: Thu, 20 Oct 2022 10:34:48 -0300 Subject: [PATCH 061/127] Extract Request::file('entry') to a variable and remove unnecessary condition --- .../Controllers/ContestEntriesController.php | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/app/Http/Controllers/ContestEntriesController.php b/app/Http/Controllers/ContestEntriesController.php index 0674110fd22..bf1cb318bf3 100644 --- a/app/Http/Controllers/ContestEntriesController.php +++ b/app/Http/Controllers/ContestEntriesController.php @@ -34,6 +34,7 @@ public function store() $user = Auth::user(); $contest = Contest::findOrFail(Request::input('contest_id')); + $file = Request::file('entry'); priv_check('ContestEntryStore', $contest)->ensureCan(); @@ -57,31 +58,27 @@ public function store() break; } - if (!in_array(strtolower(Request::file('entry')->getClientOriginalExtension()), $allowedExtensions, true)) { + if (!in_array(strtolower($file->getClientOriginalExtension()), $allowedExtensions, true)) { abort(422); } - if (Request::file('entry')->getSize() > $maxFilesize) { + if ($file->getSize() > $maxFilesize) { abort(413); } - if ($contest->type === 'art' && $contest->getForcedWidth() !== false && $contest->getForcedHeight() !== false) { - if (empty(Request::file('entry')->getContent())) { + if ($contest->type === 'art') { + if (empty($file->getContent())) { abort(400); } - [$width, $height] = getimagesizefromstring(Request::file('entry')->getContent()); + [$width, $height] = getimagesizefromstring($file->getContent()); if ($contest->getForcedWidth() !== $width || $contest->getForcedHeight() !== $height) { abort(400); } } - UserContestEntry::upload( - Request::file('entry'), - $user, - $contest - ); + UserContestEntry::upload($file, $user, $contest); return $contest->userEntries($user); } From 99c063fcb4f379a963dfefe38fdbfa1c6bad431c Mon Sep 17 00:00:00 2001 From: Matheus Filipe dos Santos Reinert Date: Thu, 20 Oct 2022 10:35:26 -0300 Subject: [PATCH 062/127] Return status code 422 if image doesn't match requirements --- app/Http/Controllers/ContestEntriesController.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/ContestEntriesController.php b/app/Http/Controllers/ContestEntriesController.php index bf1cb318bf3..2b69a9e01e6 100644 --- a/app/Http/Controllers/ContestEntriesController.php +++ b/app/Http/Controllers/ContestEntriesController.php @@ -68,13 +68,13 @@ public function store() if ($contest->type === 'art') { if (empty($file->getContent())) { - abort(400); + abort(422); } [$width, $height] = getimagesizefromstring($file->getContent()); if ($contest->getForcedWidth() !== $width || $contest->getForcedHeight() !== $height) { - abort(400); + abort(422); } } From 3ebdb3a7cea990107f4099e5df7e3a2b3fd524c7 Mon Sep 17 00:00:00 2001 From: Matheus Filipe dos Santos Reinert Date: Thu, 20 Oct 2022 10:36:27 -0300 Subject: [PATCH 063/127] Use read_image_properties_from_string coalescing with [null, null] instead of readimagefromstring --- app/Http/Controllers/ContestEntriesController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/ContestEntriesController.php b/app/Http/Controllers/ContestEntriesController.php index 2b69a9e01e6..d5a0a609536 100644 --- a/app/Http/Controllers/ContestEntriesController.php +++ b/app/Http/Controllers/ContestEntriesController.php @@ -71,7 +71,7 @@ public function store() abort(422); } - [$width, $height] = getimagesizefromstring($file->getContent()); + [$width, $height] = read_image_properties_from_string($file->getContent()) ?? [null, null]; if ($contest->getForcedWidth() !== $width || $contest->getForcedHeight() !== $height) { abort(422); From 584b85ab53c1075e8e4b460e444da92348072c2c Mon Sep 17 00:00:00 2001 From: Matheus Filipe dos Santos Reinert Date: Thu, 20 Oct 2022 18:09:35 -0300 Subject: [PATCH 064/127] Replace false check with null check --- app/Http/Controllers/ContestEntriesController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/ContestEntriesController.php b/app/Http/Controllers/ContestEntriesController.php index d5a0a609536..c8ac74b65a9 100644 --- a/app/Http/Controllers/ContestEntriesController.php +++ b/app/Http/Controllers/ContestEntriesController.php @@ -66,7 +66,7 @@ public function store() abort(413); } - if ($contest->type === 'art') { + if ($contest->type === 'art' && !is_null($contest->getForcedWidth()) && !is_null($contest->getForcedHeight())) { if (empty($file->getContent())) { abort(422); } From 2c373f5dc5bdd628cbe8c0c4f6f14b0e7e383367 Mon Sep 17 00:00:00 2001 From: Matheus Filipe dos Santos Reinert Date: Thu, 20 Oct 2022 18:15:09 -0300 Subject: [PATCH 065/127] Add error messages to error status codes --- .../Controllers/ContestEntriesController.php | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/app/Http/Controllers/ContestEntriesController.php b/app/Http/Controllers/ContestEntriesController.php index c8ac74b65a9..5bdf85a9541 100644 --- a/app/Http/Controllers/ContestEntriesController.php +++ b/app/Http/Controllers/ContestEntriesController.php @@ -29,7 +29,7 @@ public function vote($id) public function store() { if (Request::hasFile('entry') !== true) { - abort(422); + abort(422, 'No file uploaded'); } $user = Auth::user(); @@ -59,22 +59,28 @@ public function store() } if (!in_array(strtolower($file->getClientOriginalExtension()), $allowedExtensions, true)) { - abort(422); + abort( + 422, + 'File for this contest must have one of the following extensions: '.implode(', ', $allowedExtensions) + ); } if ($file->getSize() > $maxFilesize) { - abort(413); + abort(413, 'File exceeds max size'); } if ($contest->type === 'art' && !is_null($contest->getForcedWidth()) && !is_null($contest->getForcedHeight())) { if (empty($file->getContent())) { - abort(422); + abort(422, 'File must not be empty'); } [$width, $height] = read_image_properties_from_string($file->getContent()) ?? [null, null]; if ($contest->getForcedWidth() !== $width || $contest->getForcedHeight() !== $height) { - abort(422); + abort( + 422, + "Images for this contest must be {$contest->getForcedWidth()}x{$contest->getForcedHeight()}" + ); } } From 41273fd8164729bcbd0fd933f9a276e302c2190f Mon Sep 17 00:00:00 2001 From: Matheus Filipe dos Santos Reinert Date: Thu, 20 Oct 2022 18:33:22 -0300 Subject: [PATCH 066/127] Improve error message for wrong file extensions --- app/Http/Controllers/ContestEntriesController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/ContestEntriesController.php b/app/Http/Controllers/ContestEntriesController.php index 5bdf85a9541..df6975ab4d9 100644 --- a/app/Http/Controllers/ContestEntriesController.php +++ b/app/Http/Controllers/ContestEntriesController.php @@ -61,7 +61,7 @@ public function store() if (!in_array(strtolower($file->getClientOriginalExtension()), $allowedExtensions, true)) { abort( 422, - 'File for this contest must have one of the following extensions: '.implode(', ', $allowedExtensions) + 'Files for this contest must have one of the following extensions: '.implode(', ', $allowedExtensions) ); } From 9c941fab6e62fd503d865ec3a77051d267b33a64 Mon Sep 17 00:00:00 2001 From: Matheus Filipe dos Santos Reinert Date: Thu, 20 Oct 2022 18:34:34 -0300 Subject: [PATCH 067/127] Assert error messages along-side status codes --- .../Controllers/ContestEntriesControllerTest.php | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/tests/Controllers/ContestEntriesControllerTest.php b/tests/Controllers/ContestEntriesControllerTest.php index 63b4a1372f5..bdefa6997a9 100644 --- a/tests/Controllers/ContestEntriesControllerTest.php +++ b/tests/Controllers/ContestEntriesControllerTest.php @@ -20,8 +20,9 @@ public function testStoreEntryWithWrongFileExtension() $this ->actingAsVerified($this->user) - ->postJson('/community/contest-entries', ['entry' => $file, 'contest_id' => $this->contest->id]) - ->assertStatus(422); + ->postJson(route('contest-entries.store'), ['entry' => $file, 'contest_id' => $this->contest->id]) + ->assertStatus(422) + ->assertJson(['error' => 'Files for this contest must have one of the following extensions: jpg, jpeg, png']); } public function testStoreEntryExceedingMaxFileSize() @@ -32,7 +33,8 @@ public function testStoreEntryExceedingMaxFileSize() $this ->actingAsVerified($this->user) ->postJson('/community/contest-entries', ['entry' => $file, 'contest_id' => $this->contest->id]) - ->assertStatus(413); + ->assertStatus(413) + ->assertJson(['error' => 'File exceeds max size']); } public function testStoreEntryWithWrongForcedDimensions() @@ -42,8 +44,9 @@ public function testStoreEntryWithWrongForcedDimensions() $this ->actingAsVerified($this->user) - ->postJson('/community/contest-entries', ['entry' => $file, 'contest_id' => $this->contest->id]) - ->assertStatus(400); + ->postJson(route('contest-entries.store'), ['entry' => $file, 'contest_id' => $this->contest->id]) + ->assertStatus(422) + ->assertJson(['error' => 'Images for this contest must be 1920x1080']); } public function testStoreEntryWithCorrectRequirements() @@ -53,7 +56,7 @@ public function testStoreEntryWithCorrectRequirements() $this ->actingAsVerified($this->user) - ->postJson('/community/contest-entries', ['entry' => $file, 'contest_id' => $this->contest->id]) + ->postJson(route('contest-entries.store'), ['entry' => $file, 'contest_id' => $this->contest->id]) ->assertStatus(200); } From 260e99daad636425704976cc2a0cfb88530a4402 Mon Sep 17 00:00:00 2001 From: Matheus Filipe dos Santos Reinert Date: Thu, 20 Oct 2022 18:36:01 -0300 Subject: [PATCH 068/127] Use Carbon instead of DateTime --- tests/Controllers/ContestEntriesControllerTest.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/Controllers/ContestEntriesControllerTest.php b/tests/Controllers/ContestEntriesControllerTest.php index bdefa6997a9..dfd383225ed 100644 --- a/tests/Controllers/ContestEntriesControllerTest.php +++ b/tests/Controllers/ContestEntriesControllerTest.php @@ -4,6 +4,7 @@ use App\Models\Contest; use App\Models\User; +use Carbon\Carbon; use DateTime; use Illuminate\Http\Testing\File; use Tests\TestCase; @@ -67,8 +68,8 @@ private function prepareForStore() 'name' => 'Test', 'description_enter' => 'This is just a test!', 'description_voting' => 'This is just a test!', - 'entry_starts_at' => new DateTime(), - 'entry_ends_at' => (new DateTime())->modify('+1 day'), + 'entry_starts_at' => Carbon::now(), + 'entry_ends_at' => Carbon::now()->addDay(), 'extra_options' => ['forced_width' => 1920, 'forced_height' => 1080], 'header_url' => 'https://assets.ppy.sh/contests/154/header.jpg', 'max_entries' => 1, From 91adae6b3d5959ba243bde03fcef395d052b9948 Mon Sep 17 00:00:00 2001 From: Matheus Filipe dos Santos Reinert Date: Thu, 20 Oct 2022 20:50:34 -0300 Subject: [PATCH 069/127] Fix validation not working if contest didn't have forced dimensions set and convert async/await syntax to promise --- .../assets/lib/contest-entry/uploader.coffee | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/resources/assets/lib/contest-entry/uploader.coffee b/resources/assets/lib/contest-entry/uploader.coffee index 82ca1192317..e4eeab9e6d5 100644 --- a/resources/assets/lib/contest-entry/uploader.coffee +++ b/resources/assets/lib/contest-entry/uploader.coffee @@ -78,16 +78,18 @@ export class Uploader extends React.Component osu.popup osu.trans('contest.entry.too_big', limit: osu.formatBytes(maxSize, 0)), 'danger' return - if @props.contest.type == 'art' - image = await @convertFileToImage file + if @props.contest.type != 'art' || !@props.contest.forced_width && !@props.contest.forced_height + data.submit() + return - if image.width != @props.contest.forced_width || image.height != @props.contest.forced_height - osu.popup osu.trans('contest.entry.wrong_dimensions', - width: @props.contest.forced_width, - height: @props.contest.forced_height), 'danger' + @convertFileToImage(file).then (image) => + if image.width == @props.contest.forced_width && image.height == @props.contest.forced_height + data.submit() return - data.submit() + osu.popup osu.trans('contest.entry.wrong_dimensions', + width: @props.contest.forced_width, + height: @props.contest.forced_height), 'danger' submit: -> $.publish 'dragendGlobal' From ed7f69a36d1882c2ddc91cf747ac8e05a2b571c9 Mon Sep 17 00:00:00 2001 From: Matheus Filipe dos Santos Reinert Date: Thu, 20 Oct 2022 20:53:36 -0300 Subject: [PATCH 070/127] Use Carbon::now instead of DateTime --- tests/Controllers/ContestEntriesControllerTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Controllers/ContestEntriesControllerTest.php b/tests/Controllers/ContestEntriesControllerTest.php index dfd383225ed..2b18990d152 100644 --- a/tests/Controllers/ContestEntriesControllerTest.php +++ b/tests/Controllers/ContestEntriesControllerTest.php @@ -77,8 +77,8 @@ private function prepareForStore() 'show_votes' => true, 'type' => 'art', 'visible' => true, - 'voting_ends_at' => (new DateTime())->modify('+2 day'), - 'voting_starts_at' => (new DateTime())->modify('+3 day'), + 'voting_ends_at' => Carbon::now()->addDays(2), + 'voting_starts_at' => Carbon::now()->addDays(3), ]); } } From 388182ce43515e200eb0dc33fbd69ef844ac4d13 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Fri, 21 Oct 2022 15:21:27 +0900 Subject: [PATCH 071/127] return null not optional for typehints --- app/Libraries/Search/BeatmapsetSearchRequestParams.php | 2 ++ app/Models/Score/Model.php | 2 ++ app/Models/User.php | 2 ++ 3 files changed, 6 insertions(+) diff --git a/app/Libraries/Search/BeatmapsetSearchRequestParams.php b/app/Libraries/Search/BeatmapsetSearchRequestParams.php index f1bd2cce64e..d048f7b3c8d 100644 --- a/app/Libraries/Search/BeatmapsetSearchRequestParams.php +++ b/app/Libraries/Search/BeatmapsetSearchRequestParams.php @@ -182,6 +182,8 @@ public function getSort(): ?string if ($this->sortField !== null && $this->sortOrder !== null) { return "{$this->sortField}_{$this->sortOrder}"; } + + return null; } public function isLoginRequired(): bool diff --git a/app/Models/Score/Model.php b/app/Models/Score/Model.php index a6571646719..4fb0a9e90e7 100644 --- a/app/Models/Score/Model.php +++ b/app/Models/Score/Model.php @@ -38,6 +38,8 @@ public static function getClassByRulesetId(int $rulesetId): ?string if ($ruleset !== null) { return static::getClass($ruleset); } + + return null; } public static function getClass(string $ruleset): string diff --git a/app/Models/User.php b/app/Models/User.php index 1d8519920e6..ff50ffba120 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -298,6 +298,8 @@ public function renameIfInactive(): ?UsernameChangeHistory return $this->tryUpdateUsername(0, $newUsername, 'inactive'); } + + return null; } private function tryUpdateUsername(int $try, string $newUsername, string $type): UsernameChangeHistory From 2a06027a5f1523a1dd99007800127aeff0745e17 Mon Sep 17 00:00:00 2001 From: nanaya Date: Fri, 21 Oct 2022 18:20:00 +0900 Subject: [PATCH 072/127] Remove null values from score data json --- app/Models/Solo/ScoreData.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/app/Models/Solo/ScoreData.php b/app/Models/Solo/ScoreData.php index f12ff967763..9df8365f185 100644 --- a/app/Models/Solo/ScoreData.php +++ b/app/Models/Solo/ScoreData.php @@ -111,7 +111,7 @@ public function assertCompleted(): void public function jsonSerialize(): array { - return [ + $ret = [ 'accuracy' => $this->accuracy, 'beatmap_id' => $this->beatmapId, 'build_id' => $this->buildId, @@ -129,5 +129,13 @@ public function jsonSerialize(): array 'total_score' => $this->totalScore, 'user_id' => $this->userId, ]; + + foreach ($ret as $field => $value) { + if ($value === null) { + unset($ret[$field]); + } + } + + return $ret; } } From 9ff5eaaf362b3a6fb4ccdfc505b3709e8d08e3fd Mon Sep 17 00:00:00 2001 From: nanaya Date: Fri, 21 Oct 2022 18:53:37 +0900 Subject: [PATCH 073/127] Remove empty settings --- app/Models/Solo/ScoreData.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/app/Models/Solo/ScoreData.php b/app/Models/Solo/ScoreData.php index 9df8365f185..471691fedb6 100644 --- a/app/Models/Solo/ScoreData.php +++ b/app/Models/Solo/ScoreData.php @@ -36,12 +36,17 @@ class ScoreData implements Castable, JsonSerializable public function __construct(array $data) { $mods = []; - foreach ($data['mods'] ?? [] as $mod) { + // TODO: create proper Mod object $mod = (array) $mod; if (is_array($mod) && isset($mod['acronym'])) { - if (isset($mod['settings'])) { + $settings = $mod['settings'] ?? null; + if (is_object($settings) && !empty((array) $settings)) { + // already in expected format; do nothing + } elseif (is_array($settings) && !empty($settings)) { $mod['settings'] = (object) $mod['settings']; + } else { + unset($mod['settings']); } $mods[] = (object) $mod; } @@ -55,7 +60,6 @@ public function __construct(array $data) $this->legacyTotalScore = $data['legacy_total_score'] ?? null; $this->maxCombo = $data['max_combo'] ?? 0; $this->maximumStatistics = new ScoreDataStatistics($data['maximum_statistics'] ?? []); - // TODO: create a proper Mod object $this->mods = $mods; $this->passed = $data['passed'] ?? false; $this->rank = $data['rank'] ?? 'F'; From 94478306eef0bdadaf231c23933a28742410be35 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Oct 2022 19:37:46 +0900 Subject: [PATCH 074/127] Update translations from crowdin --- resources/lang/bg/scores.php | 2 +- resources/lang/ca-ES/accounts.php | 126 +++---- resources/lang/ca-ES/api.php | 18 +- resources/lang/ca-ES/artist.php | 58 +-- resources/lang/ca-ES/authorization.php | 156 ++++---- resources/lang/ca-ES/bbcode.php | 28 +- .../lang/ca-ES/beatmap_discussion_posts.php | 6 +- resources/lang/ca-ES/beatmap_discussions.php | 102 ++--- resources/lang/ca-ES/beatmappacks.php | 36 +- resources/lang/ca-ES/beatmaps.php | 350 +++++++++--------- .../ca-ES/beatmapset_discussion_votes.php | 2 +- resources/lang/ca-ES/beatmapset_events.php | 30 +- resources/lang/ca-ES/beatmapset_watches.php | 10 +- resources/lang/ca-ES/beatmapsets.php | 144 +++---- resources/lang/ca-ES/changelog.php | 2 +- resources/lang/ca-ES/chat.php | 2 +- resources/lang/ca-ES/common.php | 88 ++--- resources/lang/ca-ES/community.php | 2 +- resources/lang/ca-ES/contest.php | 20 +- resources/lang/ca-ES/errors.php | 2 +- resources/lang/ca-ES/forum.php | 20 +- resources/lang/ca-ES/layout.php | 38 +- resources/lang/ca-ES/matches.php | 20 +- resources/lang/ca-ES/model_validation.php | 12 +- .../ca-ES/model_validation/fulfillments.php | 2 +- .../ca-ES/model_validation/store/product.php | 8 +- resources/lang/ca-ES/news.php | 6 +- resources/lang/ca-ES/oauth.php | 56 +-- resources/lang/ca-ES/paypal/errors.php | 12 +- resources/lang/ca-ES/supporter_tag.php | 6 +- resources/lang/ca-ES/users.php | 6 +- resources/lang/ca-ES/wiki.php | 28 +- resources/lang/cs/scores.php | 2 +- resources/lang/de/contest.php | 4 +- resources/lang/de/scores.php | 2 +- resources/lang/es/beatmapsets.php | 2 +- resources/lang/es/scores.php | 2 +- resources/lang/fil-PH/scores.php | 2 +- resources/lang/fr/scores.php | 2 +- resources/lang/hr-HR/chat.php | 2 +- resources/lang/hr-HR/layout.php | 64 ++-- resources/lang/hr-HR/notifications.php | 2 +- resources/lang/hr-HR/scores.php | 2 +- resources/lang/hr-HR/users.php | 8 +- resources/lang/id/authorization.php | 4 +- resources/lang/id/changelog.php | 4 +- resources/lang/id/contest.php | 4 +- resources/lang/id/livestreams.php | 2 +- resources/lang/id/notifications.php | 2 +- resources/lang/id/scores.php | 2 +- resources/lang/it/scores.php | 2 +- resources/lang/ja/scores.php | 2 +- resources/lang/ko/scores.php | 2 +- resources/lang/pl/notifications.php | 2 +- resources/lang/pl/scores.php | 2 +- resources/lang/pt-br/scores.php | 2 +- resources/lang/pt/scores.php | 2 +- .../lang/ru/beatmap_discussion_posts.php | 2 +- resources/lang/ru/beatmap_discussions.php | 2 +- resources/lang/ru/beatmaps.php | 2 +- resources/lang/ru/mail.php | 28 +- resources/lang/ru/scores.php | 4 +- resources/lang/ru/users.php | 2 +- resources/lang/sl-SI/beatmapsets.php | 2 +- resources/lang/sl-SI/layout.php | 178 ++++----- resources/lang/sl-SI/livestreams.php | 8 +- resources/lang/sl-SI/mail.php | 118 +++--- resources/lang/sl-SI/matches.php | 66 ++-- resources/lang/uk/accounts.php | 2 +- resources/lang/uk/beatmap_discussions.php | 4 +- resources/lang/uk/beatmappacks.php | 6 +- resources/lang/uk/beatmaps.php | 18 +- resources/lang/uk/beatmapsets.php | 2 +- resources/lang/uk/community.php | 50 +-- resources/lang/uk/errors.php | 18 +- resources/lang/uk/events.php | 4 +- resources/lang/uk/forum.php | 4 +- resources/lang/uk/home.php | 16 +- resources/lang/uk/layout.php | 40 +- resources/lang/uk/page_title.php | 4 +- resources/lang/uk/scores.php | 6 +- resources/lang/uk/users.php | 48 +-- resources/lang/vi/contest.php | 2 +- resources/lang/vi/forum.php | 12 +- resources/lang/vi/multiplayer.php | 2 +- resources/lang/vi/rankings.php | 2 +- resources/lang/zh-tw/scores.php | 2 +- resources/lang/zh/contest.php | 2 +- resources/lang/zh/layout.php | 2 +- resources/lang/zh/multiplayer.php | 2 +- resources/lang/zh/scores.php | 2 +- resources/lang/zh/users.php | 2 +- 92 files changed, 1094 insertions(+), 1094 deletions(-) diff --git a/resources/lang/bg/scores.php b/resources/lang/bg/scores.php index e85a835a36f..24db1b8a7aa 100644 --- a/resources/lang/bg/scores.php +++ b/resources/lang/bg/scores.php @@ -24,7 +24,7 @@ 'status' => [ 'non_best' => 'Само най-добрите лични постижения дават pp', - 'non_passing' => '', + 'non_passing' => 'Само преминатите постижения дават pp', 'processing' => 'Резултатът все още се пресмята и ще бъде показан скоро', ], ]; diff --git a/resources/lang/ca-ES/accounts.php b/resources/lang/ca-ES/accounts.php index daae6ee346c..50b79acb150 100644 --- a/resources/lang/ca-ES/accounts.php +++ b/resources/lang/ca-ES/accounts.php @@ -5,124 +5,124 @@ return [ 'edit' => [ - 'title_compact' => 'configuració del compte', - 'username' => 'nom d\'usuari', + 'title_compact' => '', + 'username' => '', 'avatar' => [ - 'title' => 'Avatar', - 'rules' => 'Si us plau asseguri\'s que el seu avatar s\'adhereix a :link.
Això vol dir que ha de ser adequat per a totes les edats. És a dir, sense nuesa, blasfèmia o contingut suggestiu.', - 'rules_link' => 'regles de la comunitat', + 'title' => '', + 'rules' => '', + 'rules_link' => '', ], 'email' => [ - 'new' => 'nou correu electrònic', - 'new_confirmation' => 'confirmació de correu electrònic', - 'title' => 'Correu electrònic', + 'new' => '', + 'new_confirmation' => '', + 'title' => '', ], 'password' => [ - 'current' => 'contrasenya actual', - 'new' => 'nova contrasenya', - 'new_confirmation' => 'confirmació de contrasenya', - 'title' => 'Contrasenya', + 'current' => '', + 'new' => '', + 'new_confirmation' => '', + 'title' => '', ], 'profile' => [ - 'title' => 'Perfil', + 'title' => '', 'user' => [ 'user_discord' => '', - 'user_from' => 'ubicació actual', - 'user_interests' => 'interessos', - 'user_occ' => 'ocupació', + 'user_from' => '', + 'user_interests' => '', + 'user_occ' => '', 'user_twitter' => '', - 'user_website' => 'lloc web', + 'user_website' => '', ], ], 'signature' => [ - 'title' => 'Signatura', - 'update' => 'actualitzar', + 'title' => '', + 'update' => '', ], ], 'notifications' => [ - 'beatmapset_discussion_qualified_problem' => 'rebre notificacions per problemes nous en mapes qualificats dels següents modes', - 'beatmapset_disqualify' => 'rebre notificacions per quan els mapes dels següents modes siguin desqualificats', - 'comment_reply' => 'rebre notificacions de respostes als vostres comentaris', - 'title' => 'Notificacions', - 'topic_auto_subscribe' => 'habilita automàticament les notificacions en els nous temes de fòrum que creeu', + 'beatmapset_discussion_qualified_problem' => '', + 'beatmapset_disqualify' => '', + 'comment_reply' => '', + 'title' => '', + 'topic_auto_subscribe' => '', 'options' => [ - '_' => 'opcions d\'entrega', - 'beatmap_owner_change' => 'dificultat de convidat', - 'beatmapset:modding' => 'modding de mapa', - 'channel_message' => 'missatges de xat privats', - 'comment_new' => 'nous comentaris', - 'forum_topic_reply' => 'resposta del tema', - 'mail' => 'correu', - 'mapping' => 'creador de mapes', - 'push' => 'push', - 'user_achievement_unlock' => 'medalles desbloquejades', + '_' => '', + 'beatmap_owner_change' => '', + 'beatmapset:modding' => '', + 'channel_message' => '', + 'comment_new' => '', + 'forum_topic_reply' => '', + 'mail' => '', + 'mapping' => '', + 'push' => '', + 'user_achievement_unlock' => '', ], ], 'oauth' => [ - 'authorized_clients' => 'clients autoritzats', - 'own_clients' => 'clients propis', - 'title' => 'OAuth', + 'authorized_clients' => '', + 'own_clients' => '', + 'title' => '', ], 'options' => [ - 'beatmapset_show_nsfw' => 'oculta els avisos per al contingut explícit en mapes', - 'beatmapset_title_show_original' => 'mostra les metadades del mapa en l\'idioma original', - 'title' => 'Opcions', + 'beatmapset_show_nsfw' => '', + 'beatmapset_title_show_original' => '', + 'title' => '', 'beatmapset_download' => [ - '_' => 'tipus de baixada de mapa predeterminat', - 'all' => 'amb vídeo si està disponible', - 'direct' => 'obre en osu!direct', - 'no_video' => 'sense vídeo', + '_' => '', + 'all' => '', + 'direct' => '', + 'no_video' => '', ], ], 'playstyles' => [ - 'keyboard' => 'teclat', - 'mouse' => 'ratolí', - 'tablet' => 'tauleta', - 'title' => 'Estils de joc', - 'touch' => 'tàctil', + 'keyboard' => '', + 'mouse' => '', + 'tablet' => '', + 'title' => '', + 'touch' => '', ], 'privacy' => [ - 'friends_only' => 'bloquejar els missatges privats de persones que no són a la llista d\'amics', - 'hide_online' => 'oculta la teva presència en línia', - 'title' => 'Privadesa', + 'friends_only' => '', + 'hide_online' => '', + 'title' => '', ], 'security' => [ - 'current_session' => 'actual', - 'end_session' => 'Finalitza la sessió', - 'end_session_confirmation' => 'Això finalitzarà immediatament la sessió en aquest dispositiu. N\'estàs segur?', - 'last_active' => 'Actiu per última vegada:', - 'title' => 'Seguretat', - 'web_sessions' => 'sessions web', + 'current_session' => '', + 'end_session' => '', + 'end_session_confirmation' => '', + 'last_active' => '', + 'title' => '', + 'web_sessions' => '', ], 'update_email' => [ - 'update' => 'actualitzar', + 'update' => '', ], 'update_password' => [ - 'update' => 'actualitzar', + 'update' => '', ], 'verification_completed' => [ - 'text' => 'Ja pots tancar la pestanya/finestra', - 'title' => 'La verificació s\'ha completat', + 'text' => '', + 'title' => '', ], 'verification_invalid' => [ - 'title' => 'Enllaç de verificació no vàlid o caducat', + 'title' => '', ], ]; diff --git a/resources/lang/ca-ES/api.php b/resources/lang/ca-ES/api.php index 81c68824c4a..33e9906b6d6 100644 --- a/resources/lang/ca-ES/api.php +++ b/resources/lang/ca-ES/api.php @@ -6,28 +6,28 @@ return [ 'error' => [ 'chat' => [ - 'empty' => 'No es pot enviar un missatge buit.', - 'limit_exceeded' => 'Estàs enviant missatges massa ràpid, espera una mica i intenta-ho de nou.', - 'too_long' => 'El missatge que intentes enviar és massa llarg.', + 'empty' => '', + 'limit_exceeded' => '', + 'too_long' => '', ], ], 'scopes' => [ - 'bot' => 'Actuar com un bot de xat.', - 'identify' => 'Identifiqueu-vos i llegiu el vostre perfil públic.', + 'bot' => '', + 'identify' => '', 'chat' => [ - 'write' => 'Enviar missatges en nom vostre.', + 'write' => '', ], 'forum' => [ - 'write' => 'Crear i editar temes i publicacions del fòrum en nom seu.', + 'write' => '', ], 'friends' => [ - 'read' => 'Veure qui segueixes.', + 'read' => '', ], - 'public' => 'Llegir dades públiques en nom seu.', + 'public' => '', ], ]; diff --git a/resources/lang/ca-ES/artist.php b/resources/lang/ca-ES/artist.php index d9af5a19d65..4783fef3356 100644 --- a/resources/lang/ca-ES/artist.php +++ b/resources/lang/ca-ES/artist.php @@ -4,58 +4,58 @@ // See the LICENCE file in the repository root for full licence text. return [ - 'page_description' => 'Artistes destacats a osu!', - 'title' => 'Artistes Destacats', + 'page_description' => '', + 'title' => '', 'admin' => [ - 'hidden' => 'L\'ARTISTA ESTÀ ACTUALMENT OCULT', + 'hidden' => '', ], 'beatmaps' => [ - '_' => 'Mapes', - 'download' => 'Descarregar plantilla del mapa', - 'download-na' => 'La plantilla del mapa encara no està disponible', + '_' => '', + 'download' => '', + 'download-na' => '', ], 'index' => [ - 'description' => 'Els artistes destacats són artistes amb els quals col·laborem per a brindar-li música nova i original a osu!. Aquests artistes i una selecció dels seus treballs han estat triats per l\'equip de osu! per ser genials i adequats per a mapping. Alguns d\'aquests artistes destacats també van crear noves cançons exclusives per al seu ús en osu!.

Totes les cançons en aquesta secció són proporcionades com a arxius .osz amb ritme prèviament calculat i han estat llicenciades oficialment per al seu ús en osu! i contingut relacionat amb osu!.', + 'description' => '', ], 'links' => [ - 'beatmaps' => 'Mapes d\'osu!', - 'osu' => 'Perfil d\'osu!', - 'site' => 'Lloc web oficial', + 'beatmaps' => '', + 'osu' => '', + 'site' => '', ], 'songs' => [ - '_' => 'Cançons', - 'count' => ':count_delimited cançó|:count_delimited cançons', - 'original' => 'original d\'osu!', - 'original_badge' => 'ORIGINAL', + '_' => '', + 'count' => '', + 'original' => '', + 'original_badge' => '', ], 'tracklist' => [ - 'title' => 'títol', - 'length' => 'durada', - 'bpm' => 'bpm', - 'genre' => 'gènere', + 'title' => '', + 'length' => '', + 'bpm' => '', + 'genre' => '', ], 'tracks' => [ 'index' => [ - '_' => 'cerca de pistes', + '_' => '', 'form' => [ - 'advanced' => 'Cerca Avançada', - 'album' => 'Àlbum', - 'artist' => 'Artista', - 'bpm_gte' => 'BPM Mínim', - 'bpm_lte' => 'BPM Màxim', - 'empty' => 'No s\'ha trobat cap pista que coincideixi amb els criteris de cerca.', - 'genre' => 'Gènere', - 'genre_all' => 'Tots', - 'length_gte' => 'Durada Mínima', - 'length_lte' => 'Durada Màxima', + 'advanced' => '', + 'album' => '', + 'artist' => '', + 'bpm_gte' => '', + 'bpm_lte' => '', + 'empty' => '', + 'genre' => '', + 'genre_all' => '', + 'length_gte' => '', + 'length_lte' => '', ], ], ], diff --git a/resources/lang/ca-ES/authorization.php b/resources/lang/ca-ES/authorization.php index fface642e7b..6fa8b7c3a9f 100644 --- a/resources/lang/ca-ES/authorization.php +++ b/resources/lang/ca-ES/authorization.php @@ -4,186 +4,186 @@ // See the LICENCE file in the repository root for full licence text. return [ - 'play_more' => 'Què tal si en comptes d\'això juguem una mica d\'osu!?', - 'require_login' => 'Si us plau, inicia sessió per continuar.', - 'require_verification' => 'Si us plau, verifiqueu per continuar.', - 'restricted' => "No es pot fer mentre estigui restringit.", - 'silenced' => "No es pot fer mentre estigui silenciat.", - 'unauthorized' => 'Accés denegat.', + 'play_more' => '', + 'require_login' => '', + 'require_verification' => '', + 'restricted' => "", + 'silenced' => "", + 'unauthorized' => '', 'beatmap_discussion' => [ 'destroy' => [ - 'is_hype' => 'No es pot desfer el hyping.', - 'has_reply' => 'No es pot suprimir una discussió amb respostes', + 'is_hype' => '', + 'has_reply' => '', ], 'nominate' => [ - 'exhausted' => 'Has aconseguit el teu límit de nominacions diàries, si us plau torna-ho a intentar demà.', - 'incorrect_state' => 'Error en realitzar aquesta acció, intenteu actualitzar la pàgina.', - 'owner' => "No podeu nominar el vostre propi mapa.", - 'set_metadata' => 'Heu d\'establir el gènere i l\'idioma abans de nominar.', + 'exhausted' => '', + 'incorrect_state' => '', + 'owner' => "", + 'set_metadata' => '', ], 'resolve' => [ - 'not_owner' => 'Només el creador del fil i el propietari del mapa poden resoldre una discussió.', + 'not_owner' => '', ], 'store' => [ - 'mapper_note_wrong_user' => 'Només el propietari del mapa o el nominador/membre del grup NAT pot publicar notes de mapping.', + 'mapper_note_wrong_user' => '', ], 'vote' => [ - 'bot' => "No podeu votar en una discussió feta per un bot", - 'limit_exceeded' => 'Espera una mica abans de continuar votant', - 'owner' => "No pots votar les teves discussions.", - 'wrong_beatmapset_state' => 'Només podeu votar en discussions de mapes pendents.', + 'bot' => "", + 'limit_exceeded' => '', + 'owner' => "", + 'wrong_beatmapset_state' => '', ], ], 'beatmap_discussion_post' => [ 'destroy' => [ - 'not_owner' => 'Només podeu eliminar les vostres publicacions.', - 'resolved' => 'No podeu suprimir una publicació d\'una discussió resolta.', - 'system_generated' => 'La publicació generada automàticament no es pot eliminar.', + 'not_owner' => '', + 'resolved' => '', + 'system_generated' => '', ], 'edit' => [ - 'not_owner' => 'Només el creador pot editar la publicació.', - 'resolved' => 'No podeu editar una publicació d\'una discussió resolta.', - 'system_generated' => 'No es pot editar una publicació generada automàticament.', + 'not_owner' => '', + 'resolved' => '', + 'system_generated' => '', ], 'store' => [ - 'beatmapset_locked' => 'Aquest mapa està bloquejat per a discussió.', + 'beatmapset_locked' => '', ], ], 'beatmapset' => [ 'metadata' => [ - 'nominated' => 'No podeu canviar les metadades d\'un mapa nominat. Contacta amb un membre dels BN o del NAT si creus que estan establerts incorrectament.', + 'nominated' => '', ], ], 'chat' => [ - 'annnonce_only' => 'Aquest canal només és per a anuncis.', - 'blocked' => 'No pots enviar missatges a un usuari que vas bloquejar o que t\'hagi bloquejat.', - 'friends_only' => 'Aquest usuari està bloquejant els missatges de persones que no són a la llista d\'amics.', - 'moderated' => 'Aquest canal està actualment sent moderat.', - 'no_access' => 'No tens accés a aquest canal.', - 'receive_friends_only' => 'És possible que l\'usuari no pugui respondre perquè només accepta missatges de persones de la llista d\'amics.', - 'restricted' => 'No podeu enviar missatges mentre estigui silenciat, restringit o banejat.', - 'silenced' => 'No podeu enviar missatges mentre estigui silenciat, restringit o banejat.', + 'annnonce_only' => '', + 'blocked' => '', + 'friends_only' => '', + 'moderated' => '', + 'no_access' => '', + 'receive_friends_only' => '', + 'restricted' => '', + 'silenced' => '', ], 'comment' => [ 'store' => [ - 'disabled' => 'Els comentaris estan desactivats', + 'disabled' => '', ], 'update' => [ - 'deleted' => "No podeu editar una publicació eliminada.", + 'deleted' => "", ], ], 'contest' => [ - 'voting_over' => 'No pots canviar el teu vot després d\'haver acabat el període de votació.', + 'voting_over' => '', 'entry' => [ - 'limit_reached' => 'Heu assolit el límit d\'entrades per a aquest concurs', - 'over' => 'Gràcies per la vostra participació! Els enviaments han estat tancats per a aquest concurs i la votació s\'obrirà aviat.', + 'limit_reached' => '', + 'over' => '', ], ], 'forum' => [ 'moderate' => [ - 'no_permission' => 'Sense permisos per moderar aquest fòrum.', + 'no_permission' => '', ], 'post' => [ 'delete' => [ - 'only_last_post' => 'Només es pot suprimir la darrera publicació.', - 'locked' => 'No es pot suprimir la publicació d\'un tema tancat.', - 'no_forum_access' => 'Cal accés al fòrum sol·licitat.', - 'not_owner' => 'Només el creador pot suprimir la publicació.', + 'only_last_post' => '', + 'locked' => '', + 'no_forum_access' => '', + 'not_owner' => '', ], 'edit' => [ - 'deleted' => 'No podeu editar una publicació eliminada.', - 'locked' => 'L\'edició de la publicació està bloquejada.', - 'no_forum_access' => 'Cal accés al fòrum sol·licitat.', - 'not_owner' => 'Només el creador pot suprimir la publicació.', - 'topic_locked' => 'No es pot editar la publicació d\'un tema bloquejat.', + 'deleted' => '', + 'locked' => '', + 'no_forum_access' => '', + 'not_owner' => '', + 'topic_locked' => '', ], 'store' => [ - 'play_more' => 'Intenta jugar abans de publicar als fòrums, si us plau! Si teniu un problema jugant, publica\'l al fòrum d\'Ajuda i Suport.', - 'too_many_help_posts' => "Necessites jugar més el joc abans de fer publicacions addicionals. Si encara teniu problemes per jugar, envieu un correu electrònic a support@ppy.sh", // FIXME: unhardcode email address. + 'play_more' => '', + 'too_many_help_posts' => "", // FIXME: unhardcode email address. ], ], 'topic' => [ 'reply' => [ - 'double_post' => 'Si us plau edita la teva darrera publicació en comptes de publicar una altra vegada.', - 'locked' => 'No podeu respondre a un fil tancat.', - 'no_forum_access' => 'Cal accés al fòrum sol·licitat.', - 'no_permission' => 'No tens permisos per respondre.', + 'double_post' => '', + 'locked' => '', + 'no_forum_access' => '', + 'no_permission' => '', 'user' => [ - 'require_login' => 'Si us plau, inicia sessió per respondre.', - 'restricted' => "No podeu respondre mentre estigui restringit.", - 'silenced' => "No podeu respondre mentre estigui silenciat.", + 'require_login' => '', + 'restricted' => "", + 'silenced' => "", ], ], 'store' => [ - 'no_forum_access' => 'Cal accés al fòrum sol·licitat.', - 'no_permission' => 'No tens permís per crear un tema.', - 'forum_closed' => 'Aquest fòrum està tancat i no hi pots publicar.', + 'no_forum_access' => '', + 'no_permission' => '', + 'forum_closed' => '', ], 'vote' => [ - 'no_forum_access' => 'Cal accés al fòrum sol·licitat.', - 'over' => 'L\'enquesta va acabar i ja no es pot votar.', - 'play_more' => 'Necessites jugar més abans de votar al fòrum.', - 'voted' => 'Canviar el vot no està permès.', + 'no_forum_access' => '', + 'over' => '', + 'play_more' => '', + 'voted' => '', 'user' => [ - 'require_login' => 'Si us plau, inicieu la sessió per votar.', - 'restricted' => "No podeu votar mentre estigui restringit.", - 'silenced' => "No podeu votar mentre estigui silenciat.", + 'require_login' => '', + 'restricted' => "", + 'silenced' => "", ], ], 'watch' => [ - 'no_forum_access' => 'Cal accés al fòrum sol·licitat.', + 'no_forum_access' => '', ], ], 'topic_cover' => [ 'edit' => [ - 'uneditable' => 'Portada especificada no vàlida.', - 'not_owner' => 'Només el propietari pot editar la portada.', + 'uneditable' => '', + 'not_owner' => '', ], 'store' => [ - 'forum_not_allowed' => 'Aquest fòrum no accepta portades de temes.', + 'forum_not_allowed' => '', ], ], 'view' => [ - 'admin_only' => 'Només els administradors poden veure aquest fòrum.', + 'admin_only' => '', ], ], 'score' => [ 'pin' => [ - 'not_owner' => 'Només el propietari de la puntuació pot fixar la puntuació.', - 'too_many' => 'Has fixat massa puntuacions.', + 'not_owner' => '', + 'too_many' => '', ], ], 'user' => [ 'page' => [ 'edit' => [ - 'locked' => 'La pàgina d\'usuari està bloquejada.', - 'not_owner' => 'Només podeu editar la vostra pàgina d\'usuari.', - 'require_supporter_tag' => 'Es requereix osu!supporter.', + 'locked' => '', + 'not_owner' => '', + 'require_supporter_tag' => '', ], ], ], diff --git a/resources/lang/ca-ES/bbcode.php b/resources/lang/ca-ES/bbcode.php index d2958409b0b..b93444c98da 100644 --- a/resources/lang/ca-ES/bbcode.php +++ b/resources/lang/ca-ES/bbcode.php @@ -4,20 +4,20 @@ // See the LICENCE file in the repository root for full licence text. return [ - 'bold' => 'Negreta', - 'heading' => 'Capçalera', - 'image' => 'Imatge', - 'italic' => 'Cursiva', - 'link' => 'Enllaç', - 'list' => 'Llista', - 'list_numbered' => 'Llista Numerada', + 'bold' => '', + 'heading' => '', + 'image' => '', + 'italic' => '', + 'link' => '', + 'list' => '', + 'list_numbered' => '', 'size' => [ - '_' => 'Mida de Lletra', - 'tiny' => 'Molt petita', - 'small' => 'Petita', - 'normal' => 'Normal', - 'large' => 'Gran', + '_' => '', + 'tiny' => '', + 'small' => '', + 'normal' => '', + 'large' => '', ], - 'spoilerbox' => 'Caixa de Spoiler', - 'strikethrough' => 'Ratllar', + 'spoilerbox' => '', + 'strikethrough' => '', ]; diff --git a/resources/lang/ca-ES/beatmap_discussion_posts.php b/resources/lang/ca-ES/beatmap_discussion_posts.php index 4ae73646952..15426716892 100644 --- a/resources/lang/ca-ES/beatmap_discussion_posts.php +++ b/resources/lang/ca-ES/beatmap_discussion_posts.php @@ -5,11 +5,11 @@ return [ 'index' => [ - 'title' => 'Publicacions de la discussió del mapa', + 'title' => '', ], 'item' => [ - 'content' => 'Contingut', - 'modding_history_link' => 'Veure historial de modding', + 'content' => '', + 'modding_history_link' => '', ], ]; diff --git a/resources/lang/ca-ES/beatmap_discussions.php b/resources/lang/ca-ES/beatmap_discussions.php index 72caf991dee..ba48d729d25 100644 --- a/resources/lang/ca-ES/beatmap_discussions.php +++ b/resources/lang/ca-ES/beatmap_discussions.php @@ -6,102 +6,102 @@ return [ 'authorizations' => [ 'update' => [ - 'null_user' => 'Heu d\'iniciar sessió per editar.', - 'system_generated' => 'No es pot editar una publicació generada pel sistema.', - 'wrong_user' => 'Has de ser el propietari de la publicació per editar-la.', + 'null_user' => '', + 'system_generated' => '', + 'wrong_user' => '', ], ], 'events' => [ - 'empty' => 'No ha passat res... encara.', + 'empty' => '', ], 'index' => [ - 'deleted_beatmap' => 'eliminat', - 'none_found' => 'No s\'ha trobat cap discussió que coincideixi amb aquests criteris de cerca.', - 'title' => 'Discussions del mapa', + 'deleted_beatmap' => '', + 'none_found' => '', + 'title' => '', 'form' => [ - '_' => 'Cercar', - 'deleted' => 'Incloure discussions eliminades', - 'mode' => 'Mode del mapa', - 'only_unresolved' => 'Mostra només discussions no resoltes', - 'types' => 'Tipus de missatges', - 'username' => 'Nom d\'usuari', + '_' => '', + 'deleted' => '', + 'mode' => '', + 'only_unresolved' => '', + 'types' => '', + 'username' => '', 'beatmapset_status' => [ - '_' => 'Estat del mapa', - 'all' => 'Tots', - 'disqualified' => 'Desqualificat', - 'never_qualified' => 'No qualificat', - 'qualified' => 'Qualificat', - 'ranked' => 'Classificat', + '_' => '', + 'all' => '', + 'disqualified' => '', + 'never_qualified' => '', + 'qualified' => '', + 'ranked' => '', ], 'user' => [ - 'label' => 'Usuari', - 'overview' => 'Resum d\'activitats', + 'label' => '', + 'overview' => '', ], ], ], 'item' => [ - 'created_at' => 'Data de publicació', - 'deleted_at' => 'Data d\'eliminació', - 'message_type' => 'Tipus', - 'permalink' => 'Enllaç permanent', + 'created_at' => '', + 'deleted_at' => '', + 'message_type' => '', + 'permalink' => '', ], 'nearby_posts' => [ - 'confirm' => 'Cap de les publicacions aborda el meu assumpte', - 'notice' => 'Ja hi ha publicacions a prop de :timestamp (:existing_timestamps). Si us plau reviseu-la abans de publicar.', - 'unsaved' => ':count en aquesta revisió', + 'confirm' => '', + 'notice' => '', + 'unsaved' => '', ], 'owner_editor' => [ - 'button' => 'Propietari de la dificultat', - 'reset_confirm' => 'Restablir propietari per a aquesta dificultat?', - 'user' => 'Propietari', - 'version' => 'Dificultat', + 'button' => '', + 'reset_confirm' => '', + 'user' => '', + 'version' => '', ], 'reply' => [ 'open' => [ - 'guest' => 'Inicia sessió per respondre', - 'user' => 'Respondre', + 'guest' => '', + 'user' => '', ], ], 'review' => [ - 'block_count' => ':used / :max blocs utilitzats', - 'go_to_parent' => 'Veure publicació de revisió', - 'go_to_child' => 'Veure discussió', + 'block_count' => '', + 'go_to_parent' => '', + 'go_to_child' => '', 'validation' => [ - 'block_too_large' => 'cada bloc només pot contenir fins a :limit caràcters', - 'external_references' => 'la revisió conté referències a problemes que no pertanyen a aquesta revisió', - 'invalid_block_type' => 'tipus de bloc no vàlid', - 'invalid_document' => 'revisió no vàlida', - 'invalid_discussion_type' => 'tipus de discussió no vàlida', - 'minimum_issues' => 'la revisió ha de contenir un mínim de :count problema|la revisió ha de contenir un mínim de :count problemes', - 'missing_text' => 'falta text al bloc', - 'too_many_blocks' => 'les revisions només poden contenir :count paràgraf/problema|les revisions només poden contenir fins a :count paràgrafs/problemes', + 'block_too_large' => '', + 'external_references' => '', + 'invalid_block_type' => '', + 'invalid_document' => '', + 'invalid_discussion_type' => '', + 'minimum_issues' => '', + 'missing_text' => '', + 'too_many_blocks' => '', ], ], 'system' => [ 'resolved' => [ - 'true' => 'Marcat com a resolt per :user', - 'false' => 'Reobert per :user', + 'true' => '', + 'false' => '', ], ], 'timestamp_display' => [ - 'general' => 'general', - 'general_all' => 'general (tots)', + 'general' => '', + 'general_all' => '', ], 'user_filter' => [ - 'everyone' => 'Tothom', - 'label' => 'Filtra per usuari', + 'everyone' => '', + 'label' => '', ], ]; diff --git a/resources/lang/ca-ES/beatmappacks.php b/resources/lang/ca-ES/beatmappacks.php index fb5faa0edd6..14e50907987 100644 --- a/resources/lang/ca-ES/beatmappacks.php +++ b/resources/lang/ca-ES/beatmappacks.php @@ -5,41 +5,41 @@ return [ 'index' => [ - 'description' => 'Col·leccions preempaquetades de mapes basades en un tema comú.', - 'nav_title' => 'llistat', - 'title' => 'Paquets de mapes', + 'description' => '', + 'nav_title' => '', + 'title' => '', 'blurb' => [ - 'important' => 'LLEGEIX AIXÒ ABANS DE DESCARREGAR', - 'install_instruction' => 'Instal·lació: Un cop descarregat un paquet, extraieu-ne el contingut en el vostre directori Songs d\'osu! i aquest farà la resta.', + 'important' => '', + 'install_instruction' => '', 'note' => [ - '_' => 'També tingues en compte que és molt recomanable :scary, ja que els mapes més antics són de molta menor qualitat que els mapes més recents.', - 'scary' => 'descarregar els paquets dels més recents als més antics', + '_' => '', + 'scary' => '', ], ], ], 'show' => [ - 'download' => 'Descarregar', + 'download' => '', 'item' => [ - 'cleared' => 'completat', - 'not_cleared' => 'no completat', + 'cleared' => '', + 'not_cleared' => '', ], 'no_diff_reduction' => [ - '_' => ':link no es poden utilitzar per completar aquest paquet.', - 'link' => 'Els mods de reducció de dificultat', + '_' => '', + 'link' => '', ], ], 'mode' => [ - 'artist' => 'Artista/Àlbum', - 'chart' => 'Destacats', - 'standard' => 'Standard', - 'theme' => 'Tema', + 'artist' => '', + 'chart' => '', + 'standard' => '', + 'theme' => '', ], 'require_login' => [ - '_' => 'Necessites tenir la :link per descarregar', - 'link_text' => 'sessió iniciada', + '_' => '', + 'link_text' => '', ], ]; diff --git a/resources/lang/ca-ES/beatmaps.php b/resources/lang/ca-ES/beatmaps.php index aff8aee4b5a..44b71dcb4b7 100644 --- a/resources/lang/ca-ES/beatmaps.php +++ b/resources/lang/ca-ES/beatmaps.php @@ -6,201 +6,201 @@ return [ 'discussion-votes' => [ 'update' => [ - 'error' => 'Error en actualitzar el vot', + 'error' => '', ], ], 'discussions' => [ - 'allow_kudosu' => 'permetre kudosu', - 'beatmap_information' => 'Pàgina del mapa', - 'delete' => 'eliminar', - 'deleted' => 'Eliminat per :editor :delete_time.', - 'deny_kudosu' => 'negar kudosu', - 'edit' => 'editar', - 'edited' => 'Última edició per :editor :update_time.', - 'guest' => 'Dificultat de convidat per :user', - 'kudosu_denied' => 'Negat d\'obtenir kudosu.', - 'message_placeholder_deleted_beatmap' => 'Aquesta dificultat ha estat eliminada, per la qual cosa ja no es pot discutir.', - 'message_placeholder_locked' => 'La discussió per a aquest mapa ha estat desactivada.', - 'message_placeholder_silenced' => "No podeu publicar una discussió mentre estigui silenciat.", - 'message_type_select' => 'Seleccionar tipus de comentari', - 'reply_notice' => 'Premeu enter per respondre.', - 'reply_placeholder' => 'Escriviu la vostra resposta aquí', - 'require-login' => 'Inicia sessió per publicar o respondre', - 'resolved' => 'Resolt', - 'restore' => 'restaurar', - 'show_deleted' => 'Mostrar eliminats', - 'title' => 'Discussions', + 'allow_kudosu' => '', + 'beatmap_information' => '', + 'delete' => '', + 'deleted' => '', + 'deny_kudosu' => '', + 'edit' => '', + 'edited' => '', + 'guest' => '', + 'kudosu_denied' => '', + 'message_placeholder_deleted_beatmap' => '', + 'message_placeholder_locked' => '', + 'message_placeholder_silenced' => "", + 'message_type_select' => '', + 'reply_notice' => '', + 'reply_placeholder' => '', + 'require-login' => '', + 'resolved' => '', + 'restore' => '', + 'show_deleted' => '', + 'title' => '', 'collapse' => [ - 'all-collapse' => 'Contreure tot', - 'all-expand' => 'Expandir-ho tot', + 'all-collapse' => '', + 'all-expand' => '', ], 'empty' => [ - 'empty' => 'Encara no hi ha discussions!', - 'hidden' => 'Cap discussió no coincideix amb el filtre seleccionat.', + 'empty' => '', + 'hidden' => '', ], 'lock' => [ 'button' => [ - 'lock' => 'Bloquejar discussió', - 'unlock' => 'Desbloquejar discussió', + 'lock' => '', + 'unlock' => '', ], 'prompt' => [ - 'lock' => 'Motiu del bloqueig', - 'unlock' => 'Esteu segur que voleu desbloquejar-la?', + 'lock' => '', + 'unlock' => '', ], ], 'message_hint' => [ - 'in_general' => 'Aquest post anirà a la discussió general de mapes. Per moddejar aquest mapa, comença un missatge amb una marca de temps (exemple: 00:12:345).', - 'in_timeline' => 'Per moddejar diverses marques de temps, publiqueu diverses vegades (un missatge per marca de temps).', + 'in_general' => '', + 'in_timeline' => '', ], 'message_placeholder' => [ - 'general' => 'Escriviu aquí per publicar a General (:version)', - 'generalAll' => 'Escriviu aquí per publicar a General (Totes les dificultats)', - 'review' => 'Escriviu aquí per publicar una revisió', - 'timeline' => 'Escriviu aquí per publicar a la Línia de temps (:version)', + 'general' => '', + 'generalAll' => '', + 'review' => '', + 'timeline' => '', ], 'message_type' => [ - 'disqualify' => 'Desqualificació', - 'hype' => 'Hype!', - 'mapper_note' => 'Nota', - 'nomination_reset' => 'Restableix la nominació', - 'praise' => 'Elogi', - 'problem' => 'Problema', - 'problem_warning' => 'Informar d\'un problema', - 'review' => 'Revisió', - 'suggestion' => 'Suggeriment', + 'disqualify' => '', + 'hype' => '', + 'mapper_note' => '', + 'nomination_reset' => '', + 'praise' => '', + 'problem' => '', + 'problem_warning' => '', + 'review' => '', + 'suggestion' => '', ], 'mode' => [ - 'events' => 'Historial', - 'general' => 'General :scope', - 'reviews' => 'Revisions', - 'timeline' => 'Línia de temps', + 'events' => '', + 'general' => '', + 'reviews' => '', + 'timeline' => '', 'scopes' => [ - 'general' => 'Aquesta dificultat', - 'generalAll' => 'Totes les dificultats', + 'general' => '', + 'generalAll' => '', ], ], 'new' => [ - 'pin' => 'Fixar', - 'timestamp' => 'Marca de temps', - 'timestamp_missing' => 'Fes servir Ctrl+C en el mode d\'edició i enganxa el teu missatge per afegir una marca de temps!', - 'title' => 'Nova discussió', - 'unpin' => 'No fixis', + 'pin' => '', + 'timestamp' => '', + 'timestamp_missing' => '', + 'title' => '', + 'unpin' => '', ], 'review' => [ - 'new' => 'Nova revisió', + 'new' => '', 'embed' => [ - 'delete' => 'Eliminar', - 'missing' => '[DISCUSIÓ ELIMINADA]', - 'unlink' => 'Desvincular', - 'unsaved' => 'Sense desar', + 'delete' => '', + 'missing' => '', + 'unlink' => '', + 'unsaved' => '', 'timestamp' => [ - 'all-diff' => 'Les publicacions a "Totes les dificultats" no poden tenir marques de temps.', - 'diff' => 'Si el comentari de :type comença amb una marca de temps, es mostrarà a la Línia de temps.', + 'all-diff' => '', + 'diff' => '', ], ], 'insert-block' => [ - 'paragraph' => 'inserir paràgraf', - 'praise' => 'inserir elogi', - 'problem' => 'inserir problema', - 'suggestion' => 'inserir suggeriment', + 'paragraph' => '', + 'praise' => '', + 'problem' => '', + 'suggestion' => '', ], ], 'show' => [ - 'title' => ':title mapejat per :mapper', + 'title' => '', ], 'sort' => [ - 'created_at' => 'Data de creació', - 'timeline' => 'Línia de temps', - 'updated_at' => 'Última actualització', + 'created_at' => '', + 'timeline' => '', + 'updated_at' => '', ], 'stats' => [ - 'deleted' => 'Eliminat', - 'mapper_notes' => 'Notes', - 'mine' => 'Meu', - 'pending' => 'Pendent', - 'praises' => 'Elogis', - 'resolved' => 'Resolt', - 'total' => 'Tots', + 'deleted' => '', + 'mapper_notes' => '', + 'mine' => '', + 'pending' => '', + 'praises' => '', + 'resolved' => '', + 'total' => '', ], 'status-messages' => [ - 'approved' => 'Aquest mapa va ser aprovat el :date!', - 'graveyard' => "Aquest mapa no ha estat actualitzat des del :date pel que va ser abandonat...", - 'loved' => 'Aquest mapa va ser agregat a Estimats el :date!', - 'ranked' => 'Aquest mapa va ser classificat el :date!', - 'wip' => 'Nota: el creador ha marcat aquest mapa de ritmes com a treball en curs.', + 'approved' => '', + 'graveyard' => "", + 'loved' => '', + 'ranked' => '', + 'wip' => '', ], 'votes' => [ 'none' => [ - 'down' => 'Encara no hi ha vots negatius', - 'up' => 'Encara no hi ha vots positius', + 'down' => '', + 'up' => '', ], 'latest' => [ - 'down' => 'Últims vots negatius', - 'up' => 'Últims vots positius', + 'down' => '', + 'up' => '', ], ], ], 'hype' => [ - 'button' => 'Hipejar aquest mapa!', - 'button_done' => 'Hypejat!', - 'confirm' => "Segur? Això farà servir un dels seus :n hype restants i no es pot desfer.", - 'explanation' => 'Hypeja aquest mapa per fer-lo més visible per a la nominació i la classificació!', - 'explanation_guest' => 'Inicia sessió i hypeja aquest mapa per fer-lo més visible per a la nominació i la classificació!', - 'new_time' => "Obtindràs un altre hype :new_time.", - 'remaining' => 'Et queden :remaining hypes.', - 'required_text' => 'Hype: :current/:required', - 'section_title' => 'Tren de hype', - 'title' => 'Hype', + 'button' => '', + 'button_done' => '', + 'confirm' => "", + 'explanation' => '', + 'explanation_guest' => '', + 'new_time' => "", + 'remaining' => '', + 'required_text' => '', + 'section_title' => '', + 'title' => '', ], 'feedback' => [ - 'button' => 'Deixar un comentari', + 'button' => '', ], 'nominations' => [ - 'delete' => 'Eliminar', - 'delete_own_confirm' => 'Segur? El mapa serà eliminat i seràs redirigit de tornada al teu perfil.', - 'delete_other_confirm' => 'Segur? El mapa serà eliminat i seràs redirigit de tornada al perfil dusuari.', - 'disqualification_prompt' => 'Motiu de la desqualificació?', - 'disqualified_at' => 'Desqualificat :time_ago (:reason).', - 'disqualified_no_reason' => 'no s\'ha especificat cap raó', - 'disqualify' => 'Desqualificar', - 'incorrect_state' => 'Error en realitzar aquesta acció, intenteu actualitzar la pàgina.', - 'love' => 'Estimar', - 'love_choose' => 'Trieu la dificultat per a l\'estimat', - 'love_confirm' => 'Estimar aquest mapa?', - 'nominate' => 'Nominar', - 'nominate_confirm' => 'Nominar aquest mapa?', - 'nominated_by' => 'nominat per :users', - 'not_enough_hype' => "No hi ha prou hype.", - 'remove_from_loved' => 'Eliminar de Estimats', - 'remove_from_loved_prompt' => 'Motiu per remoure d\'Estimats:', - 'required_text' => 'Nominacions: :current/:required', - 'reset_message_deleted' => 'eliminat', - 'title' => 'Estat de nominació', - 'unresolved_issues' => 'Encara hi ha problemes sense resoldre que primer s\'han de resoldre.', + 'delete' => '', + 'delete_own_confirm' => '', + 'delete_other_confirm' => '', + 'disqualification_prompt' => '', + 'disqualified_at' => '', + 'disqualified_no_reason' => '', + 'disqualify' => '', + 'incorrect_state' => '', + 'love' => '', + 'love_choose' => '', + 'love_confirm' => '', + 'nominate' => '', + 'nominate_confirm' => '', + 'nominated_by' => '', + 'not_enough_hype' => "", + 'remove_from_loved' => '', + 'remove_from_loved_prompt' => '', + 'required_text' => '', + 'reset_message_deleted' => '', + 'title' => '', + 'unresolved_issues' => '', 'rank_estimate' => [ - '_' => 'S\'estima que aquest mapa es classificarà en :date si no es troben problemes. És el número :position a la :queue.', - 'queue' => 'cua de classificació', - 'soon' => 'aviat', + '_' => '', + 'queue' => '', + 'soon' => '', ], 'reset_at' => [ @@ -218,30 +218,30 @@ 'listing' => [ 'search' => [ 'prompt' => 'escriu paraules clau...', - 'login_required' => 'Inicieu la sessió per cercar.', + 'login_required' => '', 'options' => 'Més opcions de cerca', 'supporter_filter' => 'Filtrar per :filters requereix d\'una etiqueta osu!patrocinador activa', 'not-found' => 'sense resultats', - 'not-found-quote' => '... no, no s\'ha trobat res.', + 'not-found-quote' => '', 'filters' => [ - 'extra' => 'Extra', - 'general' => 'General', - 'genre' => 'Gènere', - 'language' => 'Llengua', + 'extra' => '', + 'general' => '', + 'genre' => '', + 'language' => '', 'mode' => 'Mode', 'nsfw' => 'Contingut explícit', - 'played' => 'Jugat', + 'played' => '', 'rank' => 'Rang obtingut', - 'status' => 'Categories', + 'status' => '', ], 'sorting' => [ - 'title' => 'Títol', - 'artist' => 'Artista', - 'difficulty' => 'Dificultat', - 'favourites' => 'Preferits', - 'updated' => 'Actualitzat', - 'ranked' => 'Classificat', - 'rating' => 'Valoració', + 'title' => '', + 'artist' => '', + 'difficulty' => '', + 'favourites' => '', + 'updated' => '', + 'ranked' => '', + 'rating' => '', 'plays' => 'Partides', 'relevance' => 'Rellevància', 'nominations' => 'Nominacions', @@ -260,30 +260,30 @@ 'spotlights' => 'Beatmaps destacats', ], 'mode' => [ - 'all' => 'Tots', - 'any' => 'Qualsevol', + 'all' => '', + 'any' => '', 'osu' => '', 'taiko' => '', 'fruits' => '', 'mania' => '', ], 'status' => [ - 'any' => 'Qualsevol', - 'approved' => 'Aprovat', + 'any' => '', + 'approved' => '', 'favourites' => 'Preferits', - 'graveyard' => 'Abandonat', + 'graveyard' => '', 'leaderboard' => 'Té marcador', - 'loved' => 'Estimats', - 'mine' => 'Els meus mapes', - 'pending' => 'Pendent', - 'wip' => 'WIP', - 'qualified' => 'Qualificat', - 'ranked' => 'Classificat', + 'loved' => '', + 'mine' => '', + 'pending' => '', + 'wip' => '', + 'qualified' => '', + 'ranked' => '', ], 'genre' => [ - 'any' => 'Qualsevol', - 'unspecified' => 'Sense especificar', - 'video-game' => 'Videojoc', + 'any' => '', + 'unspecified' => '', + 'video-game' => '', 'anime' => 'Anime', 'rock' => 'Rock', 'pop' => 'Pop', @@ -301,38 +301,38 @@ 'english' => 'Anglès', 'chinese' => 'Xinès', 'french' => 'Francès', - 'german' => 'Alemany', - 'italian' => 'Italià', - 'japanese' => 'Japonès', - 'korean' => 'Coreà', + 'german' => '', + 'italian' => '', + 'japanese' => '', + 'korean' => '', 'spanish' => 'Espanyol', - 'swedish' => 'Suec', - 'russian' => 'Rus', - 'polish' => 'Polonès', - 'instrumental' => 'Instrumental', - 'other' => 'Altres', - 'unspecified' => 'Sense especificar', + 'swedish' => '', + 'russian' => '', + 'polish' => '', + 'instrumental' => '', + 'other' => '', + 'unspecified' => '', ], 'nsfw' => [ - 'exclude' => 'Amaga', - 'include' => 'Mostra', + 'exclude' => '', + 'include' => '', ], 'played' => [ - 'any' => 'Qualsevol', - 'played' => 'Jugat', - 'unplayed' => 'No jugat', + 'any' => '', + 'played' => '', + 'unplayed' => '', ], 'extra' => [ - 'video' => 'Té vídeo', - 'storyboard' => 'Té storyboard', + 'video' => '', + 'storyboard' => '', ], 'rank' => [ - 'any' => 'Qualsevol', - 'XH' => 'SS de plata', + 'any' => '', + 'XH' => '', 'X' => '', - 'SH' => 'S de plata', + 'SH' => '', 'S' => '', 'A' => '', 'B' => '', @@ -340,14 +340,14 @@ 'D' => '', ], 'panel' => [ - 'playcount' => 'Recompte de jocs: :count', - 'favourites' => 'Preferits: :count', + 'playcount' => '', + 'favourites' => '', ], 'variant' => [ 'mania' => [ - '4k' => '4K', - '7k' => '7K', - 'all' => 'Tots', + '4k' => '', + '7k' => '', + 'all' => '', ], ], ]; diff --git a/resources/lang/ca-ES/beatmapset_discussion_votes.php b/resources/lang/ca-ES/beatmapset_discussion_votes.php index fc9a3095ff4..38a77fe58f8 100644 --- a/resources/lang/ca-ES/beatmapset_discussion_votes.php +++ b/resources/lang/ca-ES/beatmapset_discussion_votes.php @@ -5,7 +5,7 @@ return [ 'index' => [ - 'title' => 'Vots de la discussió del beatmap', + 'title' => '', ], 'item' => [ diff --git a/resources/lang/ca-ES/beatmapset_events.php b/resources/lang/ca-ES/beatmapset_events.php index 421c31bd038..a5bf81442e5 100644 --- a/resources/lang/ca-ES/beatmapset_events.php +++ b/resources/lang/ca-ES/beatmapset_events.php @@ -15,7 +15,7 @@ 'discussion_unlock' => 'S\'ha habilitat la discussió d\'aquest beatmap.', 'disqualify' => '', 'disqualify_legacy' => '', - 'genre_edit' => 'El gènere ha canviat de :old a :new.', + 'genre_edit' => '', 'issue_reopen' => '', 'issue_resolve' => '', 'kudosu_allow' => '', @@ -24,20 +24,20 @@ 'kudosu_lost' => '', 'kudosu_recalculate' => '', 'language_edit' => '', - 'love' => 'Estimat per :user.', - 'nominate' => 'Nominat per :user.', - 'nominate_modes' => 'Nominat per :user (:modes).', + 'love' => '', + 'nominate' => '', + 'nominate_modes' => '', 'nomination_reset' => '', 'nomination_reset_received' => '', 'nomination_reset_received_profile' => '', 'offset_edit' => '', 'qualify' => '', - 'rank' => 'Classificat.', + 'rank' => '', 'remove_from_loved' => '', 'nsfw_toggle' => [ 'to_0' => '', - 'to_1' => 'Marcat com a explícit', + 'to_1' => '', ], ], @@ -45,19 +45,19 @@ 'title' => '', 'form' => [ - 'period' => 'Període', - 'types' => 'Tipus', + 'period' => '', + 'types' => '', ], ], 'item' => [ - 'content' => 'Contingut', - 'discussion_deleted' => '[deleted]', - 'type' => 'Tipus', + 'content' => '', + 'discussion_deleted' => '', + 'type' => '', ], 'type' => [ - 'approve' => 'Aprovació', + 'approve' => '', 'beatmap_owner_change' => '', 'discussion_delete' => '', 'discussion_post_delete' => '', @@ -73,14 +73,14 @@ 'kudosu_lost' => '', 'kudosu_recalculate' => '', 'language_edit' => '', - 'love' => 'Amor', + 'love' => '', 'nominate' => '', 'nomination_reset' => '', 'nomination_reset_received' => '', 'nsfw_toggle' => '', 'offset_edit' => '', - 'qualify' => 'Qualificació', - 'rank' => 'Classificació', + 'qualify' => '', + 'rank' => '', 'remove_from_loved' => '', ], ]; diff --git a/resources/lang/ca-ES/beatmapset_watches.php b/resources/lang/ca-ES/beatmapset_watches.php index b5717e693b2..0f7970bad75 100644 --- a/resources/lang/ca-ES/beatmapset_watches.php +++ b/resources/lang/ca-ES/beatmapset_watches.php @@ -16,14 +16,14 @@ 'table' => [ 'empty' => '', 'last_update' => '', - 'open_issues' => 'Problemes oberts', - 'state' => 'Estat', - 'title' => 'Títol', + 'open_issues' => '', + 'state' => '', + 'title' => '', ], ], 'status' => [ - 'read' => 'Llegit', - 'unread' => 'No llegit', + 'read' => '', + 'unread' => '', ], ]; diff --git a/resources/lang/ca-ES/beatmapsets.php b/resources/lang/ca-ES/beatmapsets.php index 078428b6a13..158f0ef0595 100644 --- a/resources/lang/ca-ES/beatmapsets.php +++ b/resources/lang/ca-ES/beatmapsets.php @@ -25,17 +25,17 @@ 'index' => [ 'title' => '', - 'guest_title' => 'Beatmaps', + 'guest_title' => '', ], 'panel' => [ - 'empty' => 'sense beatmaps', + 'empty' => '', 'download' => [ - 'all' => 'descarregar', - 'video' => 'descarregar amb vídeo', - 'no_video' => 'descarregar sense vídeo', - 'direct' => 'obrir en osu!direct', + 'all' => '', + 'video' => '', + 'no_video' => '', + 'direct' => '', ], ], @@ -47,21 +47,21 @@ 'dialog' => [ 'confirmation' => '', - 'header' => 'Nominar beatmap', + 'header' => '', 'hybrid_warning' => '', 'which_modes' => '', ], ], 'nsfw_badge' => [ - 'label' => 'Explícit', + 'label' => '', ], 'show' => [ - 'discussion' => 'Discussió', + 'discussion' => '', 'details' => [ - 'by_artist' => 'per :artist', + 'by_artist' => '', 'favourite' => '', 'favourite_login' => '', 'logged-out' => '', @@ -70,25 +70,25 @@ 'updated_timeago' => '', 'download' => [ - '_' => 'Descarregar', + '_' => '', 'direct' => '', - 'no-video' => 'sense vídeo', - 'video' => 'amb vídeo', + 'no-video' => '', + 'video' => '', ], 'login_required' => [ - 'bottom' => 'per accedir a més característiques', - 'top' => 'Inicia sessió', + 'bottom' => '', + 'top' => '', ], ], 'details_date' => [ - 'approved' => 'aprovat :timeago', - 'loved' => 'estimat :timeago', - 'qualified' => 'qualificat :timeago', - 'ranked' => 'classificat :timeago', - 'submitted' => 'enviat: :timeago', - 'updated' => 'darrera actualització: :timeago', + 'approved' => '', + 'loved' => '', + 'qualified' => '', + 'ranked' => '', + 'submitted' => '', + 'updated' => '', ], 'favourites' => [ @@ -102,9 +102,9 @@ '_' => '', 'status' => [ - 'pending' => 'pendent', - 'qualified' => 'qualificat', - 'wip' => 'treball en curs', + 'pending' => '', + 'qualified' => '', + 'wip' => '', ], ], @@ -115,65 +115,65 @@ 'report' => [ '_' => '', 'button' => '', - 'link' => 'aquí', + 'link' => '', ], ], 'info' => [ - 'description' => 'Descripció', - 'genre' => 'Gènere', - 'language' => 'Idioma', + 'description' => '', + 'genre' => '', + 'language' => '', 'no_scores' => '', - 'nsfw' => 'Contingut explícit', + 'nsfw' => '', 'offset' => '', 'points-of-failure' => '', - 'source' => 'Font', + 'source' => '', 'storyboard' => '', 'success-rate' => '', - 'tags' => 'Etiquetes', - 'video' => 'Aquest beatmap conté vídeo', + 'tags' => '', + 'video' => '', ], 'nsfw_warning' => [ 'details' => '', - 'title' => 'Contingut explícit', + 'title' => '', 'buttons' => [ 'disable' => '', - 'listing' => 'Llistat de beatmaps', - 'show' => 'Mostrar', + 'listing' => '', + 'show' => '', ], ], 'scoreboard' => [ 'achieved' => '', - 'country' => 'Classificació nacional', - 'error' => 'Error en carregar les classificacions', - 'friend' => 'Classificació entre amics', + 'country' => '', + 'error' => '', + 'friend' => '', 'global' => '', 'supporter-link' => '', 'supporter-only' => '', - 'title' => 'Tauler de puntuació', + 'title' => '', 'headers' => [ - 'accuracy' => 'Precisió', - 'combo' => 'Max Combo', - 'miss' => 'Miss', - 'mods' => 'Mods', - 'pin' => 'Fixar', - 'player' => 'Jugador', + 'accuracy' => '', + 'combo' => '', + 'miss' => '', + 'mods' => '', + 'pin' => '', + 'player' => '', 'pp' => '', - 'rank' => 'Classificació', - 'score' => 'Puntuació', - 'score_total' => 'Puntuació total', - 'time' => 'Temps', + 'rank' => '', + 'score' => '', + 'score_total' => '', + 'time' => '', ], 'no_scores' => [ - 'country' => 'Ningú del vostre país encara no ha marcat cap puntuació en aquest mapa!', - 'friend' => 'Cap dels teus amics encara no ha marcat cap puntuació en aquest mapa!', + 'country' => '', + 'friend' => '', 'global' => '', - 'loading' => 'Carregant puntuacions...', + 'loading' => '', 'unranked' => '', ], 'score' => [ @@ -182,40 +182,40 @@ ], 'supporter_link' => [ '_' => '', - 'here' => 'aquí', + 'here' => '', ], ], 'stats' => [ - 'cs' => 'Mida del cercle', - 'cs-mania' => 'Comte de tecles', - 'drain' => 'Drenat d\'HP', - 'accuracy' => 'Precisió', + 'cs' => '', + 'cs-mania' => '', + 'drain' => '', + 'accuracy' => '', 'ar' => '', - 'stars' => 'Estrelles de dificultat', + 'stars' => '', 'total_length' => '', - 'bpm' => 'BPM', - 'count_circles' => 'Nombre de cercles', - 'count_sliders' => 'Nombre de lliscants', + 'bpm' => '', + 'count_circles' => '', + 'count_sliders' => '', 'offset' => '', - 'user-rating' => 'Valoració dels usuaris', + 'user-rating' => '', 'rating-spread' => '', - 'nominations' => 'Nominacions', - 'playcount' => 'Recompte de jocs', + 'nominations' => '', + 'playcount' => '', ], 'status' => [ - 'ranked' => 'Classificat', - 'approved' => 'Aprovat', - 'loved' => 'Estimat', - 'qualified' => 'Qualificat', - 'wip' => 'WIP', - 'pending' => 'Pendent', - 'graveyard' => 'Abandonat', + 'ranked' => '', + 'approved' => '', + 'loved' => '', + 'qualified' => '', + 'wip' => '', + 'pending' => '', + 'graveyard' => '', ], ], 'spotlight_badge' => [ - 'label' => 'Destacat', + 'label' => '', ], ]; diff --git a/resources/lang/ca-ES/changelog.php b/resources/lang/ca-ES/changelog.php index 96833e5aa91..1e273a7aa22 100644 --- a/resources/lang/ca-ES/changelog.php +++ b/resources/lang/ca-ES/changelog.php @@ -15,7 +15,7 @@ ], 'entry' => [ - 'by' => 'per :user', + 'by' => '', ], 'index' => [ diff --git a/resources/lang/ca-ES/chat.php b/resources/lang/ca-ES/chat.php index af7fd13aae6..28fe08f89aa 100644 --- a/resources/lang/ca-ES/chat.php +++ b/resources/lang/ca-ES/chat.php @@ -15,7 +15,7 @@ ], 'channels' => [ - 'confirm_part' => 'Vols amagar aquest canal? Encara rebràs missatges d\'aquest canal.', + 'confirm_part' => '', 'create' => '', 'list' => [ diff --git a/resources/lang/ca-ES/common.php b/resources/lang/ca-ES/common.php index 846ed839d5a..57deb34d804 100644 --- a/resources/lang/ca-ES/common.php +++ b/resources/lang/ca-ES/common.php @@ -32,36 +32,36 @@ 'close' => '', 'collapse' => '', 'delete' => '', - 'edit' => 'Editar', - 'expand' => 'expandir', - 'hide' => 'ocultar', - 'permalink' => 'enllaç permanent', - 'pin' => 'fixar', - 'post' => 'Publica', - 'read_more' => 'llegir més', - 'reply' => 'Respondre', - 'reply_reopen' => 'Respondre i reobrir', - 'reply_resolve' => 'Respondre i resoldre', - 'reset' => 'Restablir', - 'restore' => 'Restaurar', - 'retry' => 'Reintentar', - 'save' => 'Guardar', - 'saving' => 'Guardant...', - 'search' => 'Cercar', - 'see_more' => 'veure més', - 'show' => 'mostrar', - 'show_deleted' => 'Mostrar eliminats', - 'show_less' => 'mostra\'n menys', - 'show_more' => 'mostra\'n més', - 'show_more_options' => 'mostrar més opcions', - 'submit' => 'Enviar', - 'unpin' => 'desanclar', - 'update' => 'Actualitzar', - 'upload_image' => 'pujar imatge', + 'edit' => '', + 'expand' => '', + 'hide' => '', + 'permalink' => '', + 'pin' => '', + 'post' => '', + 'read_more' => '', + 'reply' => '', + 'reply_reopen' => '', + 'reply_resolve' => '', + 'reset' => '', + 'restore' => '', + 'retry' => '', + 'save' => '', + 'saving' => '', + 'search' => '', + 'see_more' => '', + 'show' => '', + 'show_deleted' => '', + 'show_less' => '', + 'show_more' => '', + 'show_more_options' => '', + 'submit' => '', + 'unpin' => '', + 'update' => '', + 'upload_image' => '', 'watch' => [ - 'to_0' => 'Deixar de veure', - 'to_1' => 'Veure', + 'to_0' => '', + 'to_1' => '', ], ], @@ -93,41 +93,41 @@ 'datetime' => [ 'year_month' => [ - 'moment' => 'MMMM YYYY', - 'php' => 'MMMM y', + 'moment' => '', + 'php' => '', ], 'year_month_short' => [ - 'moment' => 'MMM YYYY', + 'moment' => '', ], ], 'device' => [ - 'keyboard' => 'Teclat', - 'mouse' => 'Ratolí', - 'tablet' => 'Tauleta', - 'touch' => 'Pantalla tàctil', + 'keyboard' => '', + 'mouse' => '', + 'tablet' => '', + 'touch' => '', ], 'dropzone' => [ - 'target' => 'deixa anar aquí per pujar', + 'target' => '', ], 'input' => [ - 'search' => 'cercar...', + 'search' => '', ], 'pagination' => [ - 'previous' => 'prev', - 'next' => 'seg', + 'previous' => '', + 'next' => '', ], 'score_count' => [ - 'count_100' => '100', - 'count_300' => '300', - 'count_50' => '50', + 'count_100' => '', + 'count_300' => '', + 'count_50' => '', 'count_geki' => '', - 'count_katu' => '200', - 'count_miss' => 'Miss', + 'count_katu' => '', + 'count_miss' => '', ], 'scoreboard_time' => [ diff --git a/resources/lang/ca-ES/community.php b/resources/lang/ca-ES/community.php index 1c9bd6d1fce..7e1eb8fd38f 100644 --- a/resources/lang/ca-ES/community.php +++ b/resources/lang/ca-ES/community.php @@ -45,7 +45,7 @@ 'perks' => [ 'title' => '', 'osu_direct' => [ - 'title' => 'osu!direct', + 'title' => '', 'description' => '', ], diff --git a/resources/lang/ca-ES/contest.php b/resources/lang/ca-ES/contest.php index 52ea64bab54..bc496f12685 100644 --- a/resources/lang/ca-ES/contest.php +++ b/resources/lang/ca-ES/contest.php @@ -23,8 +23,8 @@ ], 'button' => [ - 'add' => 'Vota', - 'remove' => 'Eliminar vot', + 'add' => '', + 'remove' => '', 'used_up' => '', ], @@ -39,12 +39,12 @@ ], ], 'entry' => [ - '_' => 'entrada', - 'login_required' => 'Si us plau, inicieu la sessió per participar al concurs.', + '_' => '', + 'login_required' => '', 'silenced_or_restricted' => '', 'preparation' => '', 'drop_here' => '', - 'download' => 'Descarregar .osz', + 'download' => '', 'wrong_type' => [ 'art' => '', 'beatmap' => '', @@ -56,7 +56,7 @@ 'download' => '', ], 'vote' => [ - 'list' => 'vots', + 'list' => '', 'count' => '', 'points' => '', ], @@ -66,12 +66,12 @@ 'starts' => [ '_' => '', - 'soon' => 'aviat™', + 'soon' => '', ], ], 'states' => [ - 'entry' => 'Entrada oberta', - 'voting' => 'Votació iniciada', - 'results' => 'Resultats fora', + 'entry' => '', + 'voting' => '', + 'results' => '', ], ]; diff --git a/resources/lang/ca-ES/errors.php b/resources/lang/ca-ES/errors.php index 3286d8816e5..88414d01d2d 100644 --- a/resources/lang/ca-ES/errors.php +++ b/resources/lang/ca-ES/errors.php @@ -12,7 +12,7 @@ 'codes' => [ 'http-401' => '', 'http-403' => '', - 'http-404' => 'No s\'ha trobat.', + 'http-404' => '', 'http-429' => '', ], 'account' => [ diff --git a/resources/lang/ca-ES/forum.php b/resources/lang/ca-ES/forum.php index 3634b9a9974..3818fd7b0ef 100644 --- a/resources/lang/ca-ES/forum.php +++ b/resources/lang/ca-ES/forum.php @@ -88,7 +88,7 @@ 'post_reply' => '', 'reply_box_placeholder' => '', 'reply_title_prefix' => '', - 'started_by' => 'per :user', + 'started_by' => '', 'started_by_verbose' => '', 'actions' => [ @@ -101,7 +101,7 @@ 'preview' => '', // TL note: this is used in the topic reply preview, when // the user goes back from previewing to editing the reply - 'preview_hide' => 'Escriure', + 'preview_hide' => '', 'submit' => '', 'necropost' => [ @@ -132,15 +132,15 @@ 'button' => '', 'columns' => [ - 'action' => 'Acció', - 'date' => 'Data', - 'user' => 'Usuari', + 'action' => '', + 'date' => '', + 'user' => '', ], 'data' => [ - 'add_tag' => 'etiqueta ":tag" agregada', + 'add_tag' => '', 'announcement' => '', - 'edit_topic' => 'a :title', + 'edit_topic' => '', 'fork' => '', 'pin' => '', 'post_operation' => '', @@ -226,8 +226,8 @@ ], 'poll' => [ - 'hide_results' => 'Amaga els resultats de l\'enquesta.', - 'hide_results_info' => 'Només es mostraran després que finalitzi l\'enquesta.', + 'hide_results' => '', + 'hide_results_info' => '', 'length' => '', 'length_days_suffix' => '', 'length_info' => '', @@ -321,7 +321,7 @@ 'moderate_toggle_deleted' => [ 'show' => '', - 'hide' => 'Ocultar publicacions eliminades', + 'hide' => '', ], 'show' => [ diff --git a/resources/lang/ca-ES/layout.php b/resources/lang/ca-ES/layout.php index 93cc38c52d6..d89a4158c5d 100644 --- a/resources/lang/ca-ES/layout.php +++ b/resources/lang/ca-ES/layout.php @@ -96,26 +96,26 @@ 'footer' => [ 'general' => [ '_' => '', - 'home' => 'Casa', - 'changelog-index' => 'Registre de canvis', - 'beatmaps' => 'Llistat de beatmaps', - 'download' => 'Descarregar osu!', + 'home' => '', + 'changelog-index' => '', + 'beatmaps' => '', + 'download' => '', ], 'help' => [ - '_' => 'Ajuda i comunitat', - 'faq' => 'Preguntes freqüents', - 'forum' => 'Fòrums de la comunitat', - 'livestreams' => 'Transmissions en directe', + '_' => '', + 'faq' => '', + 'forum' => '', + 'livestreams' => '', 'report' => '', - 'wiki' => 'Wiki', + 'wiki' => '', ], 'legal' => [ - '_' => 'Estat legal', - 'copyright' => 'Drets d\'autor (DMCA)', - 'privacy' => 'Privacitat', - 'server_status' => 'Estat del servidor', - 'source_code' => 'Codi font', - 'terms' => 'Termes', + '_' => '', + 'copyright' => '', + 'privacy' => '', + 'server_status' => '', + 'source_code' => '', + 'terms' => '', ], ], @@ -125,7 +125,7 @@ 'description' => '', ], '404' => [ - 'error' => 'Falta la pàgina', + 'error' => '', 'description' => "", ], '403' => [ @@ -149,7 +149,7 @@ 'description' => '', ], '500' => [ - 'error' => 'Oh no! Alguna cosa s\'ha trencat! ;_;', + 'error' => '', 'description' => "", ], 'fatal' => [ @@ -173,8 +173,8 @@ 'login' => [ 'forgot' => "", - 'password' => 'contrasenya', - 'title' => 'Inicia sessió per continuar', + 'password' => '', + 'title' => '', 'username' => '', 'error' => [ diff --git a/resources/lang/ca-ES/matches.php b/resources/lang/ca-ES/matches.php index 2752f839d68..ce5d058b355 100644 --- a/resources/lang/ca-ES/matches.php +++ b/resources/lang/ca-ES/matches.php @@ -7,7 +7,7 @@ 'match' => [ 'beatmap-deleted' => '', 'difference' => '', - 'failed' => 'FRACASSAT', + 'failed' => '', 'header' => '', 'in-progress' => '', 'in_progress_spinner_label' => '', @@ -32,27 +32,27 @@ 'score' => [ 'stats' => [ - 'accuracy' => 'Precisió', - 'combo' => 'Combo', - 'score' => 'Puntuació', + 'accuracy' => '', + 'combo' => '', + 'score' => '', ], ], 'team-types' => [ - 'head-to-head' => 'Head-to-head', - 'tag-coop' => 'Tag Co-op', - 'team-vs' => 'Team VS', - 'tag-team-vs' => 'Tag Team VS', + 'head-to-head' => '', + 'tag-coop' => '', + 'team-vs' => '', + 'tag-team-vs' => '', ], 'teams' => [ 'blue' => '', - 'red' => 'Equip Vermell', + 'red' => '', ], ], 'game' => [ 'scoring-type' => [ - 'score' => 'Equip Blau', + 'score' => '', 'accuracy' => '', 'combo' => '', 'scorev2' => '', diff --git a/resources/lang/ca-ES/model_validation.php b/resources/lang/ca-ES/model_validation.php index b834bafd988..ac8e70b7325 100644 --- a/resources/lang/ca-ES/model_validation.php +++ b/resources/lang/ca-ES/model_validation.php @@ -91,7 +91,7 @@ 'topic_poll' => [ 'duplicate_options' => '', 'grace_period_expired' => '', - 'hiding_results_forever' => 'No es poden amagar els resultats d\'una enquesta que mai no finalitza.', + 'hiding_results_forever' => '', 'invalid_max_options' => '', 'minimum_one_selection' => '', 'minimum_two_options' => '', @@ -147,9 +147,9 @@ 'too_long' => '', 'attributes' => [ - 'username' => 'Nom d\'usuari', - 'user_email' => 'Correu electrònic', - 'password' => 'Contrasenya', + 'username' => '', + 'user_email' => '', + 'password' => '', ], 'change_username' => [ @@ -171,8 +171,8 @@ 'store' => [ 'order_item' => [ 'attributes' => [ - 'quantity' => 'Quantitat', - 'cost' => 'Preu', + 'quantity' => '', + 'cost' => '', ], ], ], diff --git a/resources/lang/ca-ES/model_validation/fulfillments.php b/resources/lang/ca-ES/model_validation/fulfillments.php index 9d68b03d392..0d7d1c1acc9 100644 --- a/resources/lang/ca-ES/model_validation/fulfillments.php +++ b/resources/lang/ca-ES/model_validation/fulfillments.php @@ -10,6 +10,6 @@ 'reverting_username_mismatch' => '', ], 'supporter_tag' => [ - 'insufficient_paid' => 'La donació és menor a la mínima necessitada per a l\'osu!supporter (:actual > :expected)', + 'insufficient_paid' => '', ], ]; diff --git a/resources/lang/ca-ES/model_validation/store/product.php b/resources/lang/ca-ES/model_validation/store/product.php index f468dc4fcd4..33c1f2cc383 100644 --- a/resources/lang/ca-ES/model_validation/store/product.php +++ b/resources/lang/ca-ES/model_validation/store/product.php @@ -4,8 +4,8 @@ // See the LICENCE file in the repository root for full licence text. return [ - 'insufficient_stock' => 'No en queda prou d\'aquest producte!', - 'must_separate' => 'Aquest producte s\'ha de pagar per separat', - 'not_available' => 'Aquest producte no està disponible.', - 'too_many' => 'Només podeu ordenar :count d\'aquest producte per ordre.', + 'insufficient_stock' => '', + 'must_separate' => '', + 'not_available' => '', + 'too_many' => '', ]; diff --git a/resources/lang/ca-ES/news.php b/resources/lang/ca-ES/news.php index 2dc54e5a4a6..3b8a8136c73 100644 --- a/resources/lang/ca-ES/news.php +++ b/resources/lang/ca-ES/news.php @@ -13,13 +13,13 @@ ], 'title' => [ - '_' => 'notícies', - 'info' => 'portada', + '_' => '', + 'info' => '', ], ], 'show' => [ - 'by' => 'per :user', + 'by' => '', 'nav' => [ 'newer' => '', diff --git a/resources/lang/ca-ES/oauth.php b/resources/lang/ca-ES/oauth.php index 67eb707ce25..9534947a74a 100644 --- a/resources/lang/ca-ES/oauth.php +++ b/resources/lang/ca-ES/oauth.php @@ -4,58 +4,58 @@ // See the LICENCE file in the repository root for full licence text. return [ - 'cancel' => 'Cancel·lar', + 'cancel' => '', 'authorise' => [ - 'request' => 'està sol·licitant permís per accedir al vostre compte.', - 'scopes_title' => 'Aquesta aplicació serà capaç de:', - 'title' => 'Sol·licitud d\'autorització', + 'request' => '', + 'scopes_title' => '', + 'title' => '', ], 'authorized_clients' => [ - 'confirm_revoke' => 'Esteu segur que voleu revocar els permisos d\'aquest client?', - 'scopes_title' => 'Aquesta aplicació pot:', - 'owned_by' => 'Propietat de :user', - 'none' => 'Cap client', + 'confirm_revoke' => '', + 'scopes_title' => '', + 'owned_by' => '', + 'none' => '', 'revoked' => [ - 'false' => 'Revoca l\'accés', - 'true' => 'Accés denegat', + 'false' => '', + 'true' => '', ], ], 'client' => [ - 'id' => 'ID del client', - 'name' => 'Nom de l\'aplicació', - 'redirect' => 'URL de devolució de trucada de l\'aplicació', - 'reset' => 'Restablir secret de client', - 'reset_failed' => 'No s\'ha pogut restablir el secret de client', - 'secret' => 'Secret del client', + 'id' => '', + 'name' => '', + 'redirect' => '', + 'reset' => '', + 'reset_failed' => '', + 'secret' => '', 'secret_visible' => [ - 'false' => 'Mostra secret de client', - 'true' => 'Amaga el secret de client', + 'false' => '', + 'true' => '', ], ], 'new_client' => [ - 'header' => 'Registreu una nova aplicació OAuth', - 'register' => 'Registre de l\'aplicació', + 'header' => '', + 'register' => '', 'terms_of_use' => [ - '_' => 'En utilitzar l\'API, vostè accepta els :link.', - 'link' => 'Condicions d\'ús', + '_' => '', + 'link' => '', ], ], 'own_clients' => [ - 'confirm_delete' => 'Esteu segur que voleu suprimir aquest client?', - 'confirm_reset' => 'Esteu segur que voleu restablir el secret de client? Això revocarà tots els tokens existents.', - 'new' => 'Nova aplicació OAuth', - 'none' => 'Cap client', + 'confirm_delete' => '', + 'confirm_reset' => '', + 'new' => '', + 'none' => '', 'revoked' => [ - 'false' => 'Eliminar', - 'true' => 'Eliminat', + 'false' => '', + 'true' => '', ], ], ]; diff --git a/resources/lang/ca-ES/paypal/errors.php b/resources/lang/ca-ES/paypal/errors.php index aa4b9693154..18f3b0ab831 100644 --- a/resources/lang/ca-ES/paypal/errors.php +++ b/resources/lang/ca-ES/paypal/errors.php @@ -4,10 +4,10 @@ // See the LICENCE file in the repository root for full licence text. return [ - 'instrument_declined' => 'PayPal ha rebutjat el mètode de pagament seleccionat.', - 'invalid_resource_id' => 'No s\'ha trobat cap informació de pagament.', - 'invalid_token' => 'S\'ha produït un error en completar el pagament.', - 'old_format' => 'L\'enllaç per a restablir contrasenya ha expirat, torna a provar.', - 'resource_not_found' => 'No s\'ha trobat cap informació de pagament.', - 'unknown' => "El pagament s'ha rebutjat, però no sabem per què.", + 'instrument_declined' => '', + 'invalid_resource_id' => '', + 'invalid_token' => '', + 'old_format' => '', + 'resource_not_found' => '', + 'unknown' => "", ]; diff --git a/resources/lang/ca-ES/supporter_tag.php b/resources/lang/ca-ES/supporter_tag.php index cb263f61dc0..e0ea36b594e 100644 --- a/resources/lang/ca-ES/supporter_tag.php +++ b/resources/lang/ca-ES/supporter_tag.php @@ -4,10 +4,10 @@ // See the LICENCE file in the repository root for full licence text. return [ - 'months' => 'mesos', + 'months' => '', 'user_search' => [ - 'searching' => 'cercant...', - 'not_found' => "Aquest usuari no existeix", + 'searching' => '', + 'not_found' => "", ], ]; diff --git a/resources/lang/ca-ES/users.php b/resources/lang/ca-ES/users.php index 6921434e5d2..5f5a84530de 100644 --- a/resources/lang/ca-ES/users.php +++ b/resources/lang/ca-ES/users.php @@ -35,8 +35,8 @@ 'banner_text' => '', 'comment_text' => '', 'blocked_count' => '', - 'hide_profile' => 'Oculta el perfil', - 'hide_comment' => 'ocultar', + 'hide_profile' => '', + 'hide_comment' => '', 'not_blocked' => '', 'show_profile' => '', 'show_comment' => '', @@ -163,7 +163,7 @@ 'count' => '', ], 'cover' => [ - 'to_0' => 'Ocultar portada', + 'to_0' => '', 'to_1' => '', ], 'edit' => [ diff --git a/resources/lang/ca-ES/wiki.php b/resources/lang/ca-ES/wiki.php index e5248067e1c..2e6b365035c 100644 --- a/resources/lang/ca-ES/wiki.php +++ b/resources/lang/ca-ES/wiki.php @@ -5,26 +5,26 @@ return [ 'show' => [ - 'fallback_translation' => 'La pàgina sol·licitada encara no s\'ha traduït a l\'idioma seleccionat (:language). S\'està mostrant la versió en anglès.', - 'incomplete_or_outdated' => 'El contingut d\'aquesta pàgina és incomplet o obsolet. Si vostè pot ajudar, si us plau considereu actualitzar l\'article!', - 'missing' => 'La pàgina sol·licitada ":keyword" no s\'ha pogut trobar.', - 'missing_title' => 'No Trobat', - 'missing_translation' => 'La pàgina sol·licitada no s\'ha pogut trobar per a l\'idioma seleccionat.', - 'needs_cleanup_or_rewrite' => 'Aquesta pàgina no compleix els estàndards de la wiki d\'osu! i necessita ser acomodada o reescrita. Si vostè pot ajudar, si us plau considereu actualitzar l\'article!', - 'search' => 'Cerca pàgines existents per a :link.', - 'stub' => 'Aquest article està incomplet i esperant que algú ho ampliï.', - 'toc' => 'Continguts', + 'fallback_translation' => '', + 'incomplete_or_outdated' => '', + 'missing' => '', + 'missing_title' => '', + 'missing_translation' => '', + 'needs_cleanup_or_rewrite' => '', + 'search' => '', + 'stub' => '', + 'toc' => '', 'edit' => [ - 'link' => 'Mostra a GitHub', - 'refresh' => 'Refresca', + 'link' => '', + 'refresh' => '', ], 'translation' => [ - 'legal' => 'Aquesta traducció només es proporciona per conveniència. L\'original :default serà l\'única versió vinculant legalment d\'aquest text.', - 'outdated' => 'Aquesta pàgina conté una traducció obsoleta del contingut original. Si us plau, reviseu la :default per obtenir informació més precisa (i considereu la possibilitat d\'actualitzar la traducció si podeu ajudar)!', + 'legal' => '', + 'outdated' => '', - 'default' => 'Versió en anglès', + 'default' => '', ], ], ]; diff --git a/resources/lang/cs/scores.php b/resources/lang/cs/scores.php index faa15f15b52..f5e92e14432 100644 --- a/resources/lang/cs/scores.php +++ b/resources/lang/cs/scores.php @@ -24,7 +24,7 @@ 'status' => [ 'non_best' => 'Pouze osobní nejlepší skóre ocenění', - 'non_passing' => '', + 'non_passing' => 'pp dostávají jen schválené skóre ', 'processing' => 'Toto skóre se stále počítá a bude brzy zobrazeno', ], ]; diff --git a/resources/lang/de/contest.php b/resources/lang/de/contest.php index d45df5e00a5..b2370052dd6 100644 --- a/resources/lang/de/contest.php +++ b/resources/lang/de/contest.php @@ -25,7 +25,7 @@ 'button' => [ 'add' => 'Abstimmen', 'remove' => 'Stimme entfernen', - 'used_up' => 'Du hast alle deine Votes verwendet', + 'used_up' => 'Du hast alle deine Stimmen verwendet', ], 'progress' => [ @@ -34,7 +34,7 @@ 'requirement' => [ 'playlist_beatmapsets' => [ - 'incomplete_play' => 'Bevor Sie abstimmen können, müssen Sie alle Beatmaps in den angegebenen Playlists gespielt haben', + 'incomplete_play' => 'Bevor du abstimmen kannst, musst du alle Beatmaps in den angegebenen Playlists gespielt haben', ], ], ], diff --git a/resources/lang/de/scores.php b/resources/lang/de/scores.php index 9303626a856..93f1f50bc71 100644 --- a/resources/lang/de/scores.php +++ b/resources/lang/de/scores.php @@ -24,7 +24,7 @@ 'status' => [ 'non_best' => 'Nur persönliche Bestwerte geben pp', - 'non_passing' => '', + 'non_passing' => 'Nur erfolgreiche Scores geben pp', 'processing' => 'Dieser Score wird noch berechnet und in Kürze angezeigt', ], ]; diff --git a/resources/lang/es/beatmapsets.php b/resources/lang/es/beatmapsets.php index cfec8c05e5f..511c8c6c90e 100644 --- a/resources/lang/es/beatmapsets.php +++ b/resources/lang/es/beatmapsets.php @@ -196,7 +196,7 @@ 'total_length' => 'Duración (Duración del drenaje: :hit_length)', 'bpm' => 'BPM', 'count_circles' => 'Número de círculos', - 'count_sliders' => 'Número de deslizadores', + 'count_sliders' => 'Número de sliders', 'offset' => 'Compensación en línea: :offset', 'user-rating' => 'Valoración de los usuarios', 'rating-spread' => 'Desglose de valoraciones', diff --git a/resources/lang/es/scores.php b/resources/lang/es/scores.php index 8aed36e4c5a..30b467905ec 100644 --- a/resources/lang/es/scores.php +++ b/resources/lang/es/scores.php @@ -24,7 +24,7 @@ 'status' => [ 'non_best' => 'Solo las mejores puntuaciones personales otorgan pp', - 'non_passing' => '', + 'non_passing' => 'Sólo las puntuaciones aprobadas dan pp', 'processing' => 'Esta puntuación aún se está calculando y se mostrará pronto', ], ]; diff --git a/resources/lang/fil-PH/scores.php b/resources/lang/fil-PH/scores.php index 84b90d39deb..85b7e336c7d 100644 --- a/resources/lang/fil-PH/scores.php +++ b/resources/lang/fil-PH/scores.php @@ -24,7 +24,7 @@ 'status' => [ 'non_best' => 'Ang laro na may pinakamataas na iskor lamang ang bibigyan ng pp', - 'non_passing' => '', + 'non_passing' => 'Pasado nga mga iskor lang ang magatimpalaan ng pp', 'processing' => 'Ang iskor ay pinoproseso pa lamang at maipapakita sa mas madaling panahon', ], ]; diff --git a/resources/lang/fr/scores.php b/resources/lang/fr/scores.php index 1081104d343..919e24769e7 100644 --- a/resources/lang/fr/scores.php +++ b/resources/lang/fr/scores.php @@ -24,7 +24,7 @@ 'status' => [ 'non_best' => 'Seul vos meilleurs scores vous rapportent des pp', - 'non_passing' => '', + 'non_passing' => 'Seuls les scores réussis rapportent des pp', 'processing' => 'Ce score est toujours en cours de calcul et sera affiché bientôt', ], ]; diff --git a/resources/lang/hr-HR/chat.php b/resources/lang/hr-HR/chat.php index e900ef9abb4..3a318fbee87 100644 --- a/resources/lang/hr-HR/chat.php +++ b/resources/lang/hr-HR/chat.php @@ -15,7 +15,7 @@ ], 'channels' => [ - 'confirm_part' => '', + 'confirm_part' => 'Želiš li sakriti ovaj kanal? I dalje ćeš primati poruke iz ovog kanala.', 'create' => 'napravi obavijest', 'list' => [ diff --git a/resources/lang/hr-HR/layout.php b/resources/lang/hr-HR/layout.php index 02cf221119a..b45c2d14f57 100644 --- a/resources/lang/hr-HR/layout.php +++ b/resources/lang/hr-HR/layout.php @@ -125,87 +125,87 @@ 'errors' => [ '400' => [ - 'error' => '', + 'error' => 'Nevažeći parametar zahtjeva', 'description' => '', ], '404' => [ - 'error' => '', - 'description' => "", + 'error' => 'Stranica nedostaje', + 'description' => "Žao nam je, ali stranica koju si tražio/la nije ovdje!", ], '403' => [ - 'error' => "", - 'description' => '', + 'error' => "Ne bi trebao/la biti ovdje.", + 'description' => 'Ipak, možeš se pokušati vratiti.', ], '401' => [ - 'error' => "", - 'description' => '', + 'error' => "Ne bi trebao/la biti ovdje.", + 'description' => 'Ipak, možeš se pokušati vratiti. Ili možda prijaviti.', ], '405' => [ - 'error' => '', - 'description' => "", + 'error' => 'Stranica nedostaje', + 'description' => "Žao nam je, ali stranica koju si tražio/la nije ovdje!", ], '422' => [ - 'error' => '', + 'error' => 'Nevažeći parametar zahtjeva', 'description' => '', ], '429' => [ - 'error' => '', + 'error' => 'Ograničenje brzine premašeno', 'description' => '', ], '500' => [ - 'error' => '', - 'description' => "", + 'error' => 'O ne! Nešto se pokvarilo! ;_;', + 'description' => "Automatski smo obaviješteni o svakoj grešci.", ], 'fatal' => [ - 'error' => '', - 'description' => "", + 'error' => 'O ne! Nešto se (jako) pokvarilo! ;_;', + 'description' => "Automatski smo obaviješteni o svakoj grešci.", ], '503' => [ - 'error' => '', - 'description' => "", + 'error' => 'Dolje zbog održavanja!', + 'description' => "Održavanje obično traje od 5 sekundi do 10 minuta. Ako traje dulje, pogledaj :link za više informacija.", 'link' => [ 'text' => '', 'href' => '', ], ], // used by sentry if it returns an error - 'reference' => "", + 'reference' => "Za svaki slučaj, evo koda kojeg možeš dati podršci!", ], 'popup_login' => [ - 'button' => '', + 'button' => 'prijava / registracija', 'login' => [ - 'forgot' => "", + 'forgot' => "Zaboravio/la sam svoje podatke", 'password' => 'lozinka', - 'title' => '', - 'username' => '', + 'title' => 'Prijavi se za nastavak', + 'username' => 'korisničko ime', 'error' => [ - 'email' => "", - 'password' => '', + 'email' => "Korisničko ime ili adresa e-pošte ne postoji", + 'password' => 'Netočna lozinka', ], ], 'register' => [ - 'download' => '', - 'info' => '', - 'title' => "", + 'download' => 'Preuzmi', + 'info' => 'Preuzmi osu! za izradu vlastitog računa!', + 'title' => "Nemaš račun?", ], ], 'popup_user' => [ 'links' => [ 'account-edit' => 'Postavke', - 'follows' => '', + 'follows' => 'Liste gledanja', 'friends' => 'Prijatelji', - 'logout' => '', - 'profile' => '', + 'logout' => 'Odjava', + 'profile' => 'Moj profil', ], ], 'popup_search' => [ - 'initial' => '', - 'retry' => '', + 'initial' => 'Unesite za pretraživanje!', + 'retry' => 'Pretraga nije uspjela. Klikni za ponovni pokušaj.', ], ]; diff --git a/resources/lang/hr-HR/notifications.php b/resources/lang/hr-HR/notifications.php index 7361412e4c3..7834326d32f 100644 --- a/resources/lang/hr-HR/notifications.php +++ b/resources/lang/hr-HR/notifications.php @@ -240,7 +240,7 @@ 'user_beatmapset_new' => [ 'user_beatmapset_new' => ':username jew kreirao nove beatmape', - 'user_beatmapset_revive' => '', + 'user_beatmapset_revive' => ':username je oživio beatmape', ], ], ], diff --git a/resources/lang/hr-HR/scores.php b/resources/lang/hr-HR/scores.php index bd9b908bb99..f6fb476909c 100644 --- a/resources/lang/hr-HR/scores.php +++ b/resources/lang/hr-HR/scores.php @@ -24,7 +24,7 @@ 'status' => [ 'non_best' => 'Samo najbolji osobni rezultati nagrađuju pp', - 'non_passing' => '', + 'non_passing' => 'Samo prolazeći rezultati nagrađuju pp', 'processing' => 'Ovaj rezultat se još uvijek izračunava i uskoro će biti prikazan', ], ]; diff --git a/resources/lang/hr-HR/users.php b/resources/lang/hr-HR/users.php index e077f21eecb..070b740f877 100644 --- a/resources/lang/hr-HR/users.php +++ b/resources/lang/hr-HR/users.php @@ -33,13 +33,13 @@ 'blocks' => [ 'banner_text' => 'Blokirao/la si ovog korisnika.', - 'comment_text' => '', + 'comment_text' => 'Ovaj komentar je skriven.', 'blocked_count' => 'blokirani korisnici (:count)', 'hide_profile' => 'Sakrij profil', - 'hide_comment' => '', + 'hide_comment' => 'sakrij', 'not_blocked' => 'Taj korisnik nije blokiran.', 'show_profile' => 'Prikaži profil', - 'show_comment' => '', + 'show_comment' => 'prikaži', 'too_many' => 'Dosegnuto je ograničenje blokiranja.', 'button' => [ 'block' => 'Blokiraj', @@ -372,7 +372,7 @@ 'actions' => [ 'restriction' => 'Zabrana', 'silence' => 'Utišanje', - 'tournament_ban' => '', + 'tournament_ban' => 'Zabrana turnira', 'note' => 'Bilješka', ], ], diff --git a/resources/lang/id/authorization.php b/resources/lang/id/authorization.php index b6e74c7a202..7c03ad50a86 100644 --- a/resources/lang/id/authorization.php +++ b/resources/lang/id/authorization.php @@ -66,8 +66,8 @@ 'annnonce_only' => 'Kanal ini hanya dikhususkan untuk pengumuman.', 'blocked' => 'Tidak dapat mengirim pesan kepada pengguna yang diblokir atau memblokir Anda.', 'friends_only' => 'Pengguna memblokir pesan dari orang yang tidak dalam daftar temannya.', - 'moderated' => 'Channel ini sedang dimoderasi.', - 'no_access' => 'Anda tidak dapat mengakses channel ini.', + 'moderated' => 'Kanal percakapan ini sedang dimoderasi.', + 'no_access' => 'Anda tidak memiliki akses ke kanal percakapan ini.', 'receive_friends_only' => 'Pengguna ini tidak akan dapat membalas pesan Anda karena Anda hanya menerima pesan dari nama-nama yang tertera pada daftar teman Anda.', 'restricted' => 'Anda tidak dapat mengirim pesan pada saat akun Anda sedang di-silence, di-restrict, atau di-ban.', 'silenced' => 'Anda tidak dapat mengirim pesan pada saat akun Anda sedang di-silence, di-restrict, atau di-ban.', diff --git a/resources/lang/id/changelog.php b/resources/lang/id/changelog.php index e2b2d5a5d78..52077215c29 100644 --- a/resources/lang/id/changelog.php +++ b/resources/lang/id/changelog.php @@ -4,7 +4,7 @@ // See the LICENCE file in the repository root for full licence text. return [ - 'generic' => 'Penumpasan bug dan berbagai penyempurnaan berskala kecil lainnya', + 'generic' => 'Perbaikan bug dan berbagai penyempurnaan berskala kecil lainnya', 'build' => [ 'title' => 'daftar perubahan pada :version', @@ -32,7 +32,7 @@ ], 'support' => [ - 'heading' => 'Apakah Anda menyukai pembaruan ini?', + 'heading' => 'Suka dengan pembaruan ini?', 'text_1' => 'Dukung osu! agar dapat terus berkembang dan :link sekarang juga!', 'text_1_link' => 'jadilah seorang osu!supporter', 'text_2' => 'Di samping mempercepat pengembangan, Anda juga akan memperoleh berbagai fitur tambahan dan opsi personalisasi lainnya!', diff --git a/resources/lang/id/contest.php b/resources/lang/id/contest.php index dcc20b84c9b..eb4dfb2ec97 100644 --- a/resources/lang/id/contest.php +++ b/resources/lang/id/contest.php @@ -34,7 +34,7 @@ 'requirement' => [ 'playlist_beatmapsets' => [ - 'incomplete_play' => 'Anda harus terlebih dahulu memainkan seluruh beatmap yang terdapat pada playlist untuk dapat memberikan suara', + 'incomplete_play' => 'Anda harus memainkan seluruh beatmap yang tertera pada playlist yang ditentukan untuk dapat memberikan suara', ], ], ], @@ -71,7 +71,7 @@ ], 'states' => [ 'entry' => 'Menerima Entri', - 'voting' => 'Dalam Tahapan Pemungutan Suara', + 'voting' => 'Dalam Tahap Pemungutan Suara', 'results' => 'Telah Berakhir', ], ]; diff --git a/resources/lang/id/livestreams.php b/resources/lang/id/livestreams.php index 3b2eb82f8d9..35d9bad3ccb 100644 --- a/resources/lang/id/livestreams.php +++ b/resources/lang/id/livestreams.php @@ -11,7 +11,7 @@ 'top-headers' => [ 'headline' => 'Siaran Langsung', - 'description' => 'Daftar siaran langsung yang tertera di bawah ini diperbarui setiap lima menit sekali mengikuti direktori twitch.tv yang tersedia. Jangan sungkan untuk menyiarkan dirimu ke mata dunia! Untuk informasi lebih lanjut seputar cara menyiarkan osu! secara langsung, harap kunjungi :link.', + 'description' => 'Data siaran langsung berikut diperbarui setiap lima menit sekali berdasarkan direktori twitch.tv yang tersedia. Jangan ragu untuk menyiarkan dirimu ke mata dunia! Untuk informasi lebih lanjut seputar cara menyiarkan osu! secara langsung, harap kunjungi :link.', 'link' => 'laman wiki berikut', ], diff --git a/resources/lang/id/notifications.php b/resources/lang/id/notifications.php index 726ca33a94d..cec2f47d0d4 100644 --- a/resources/lang/id/notifications.php +++ b/resources/lang/id/notifications.php @@ -97,7 +97,7 @@ ], 'channel' => [ - '_' => 'Pesan Baru', + '_' => 'Pesan baru', 'pm' => [ 'channel_message' => ':username mengatakan ":title"', diff --git a/resources/lang/id/scores.php b/resources/lang/id/scores.php index a6993d10739..2d7d02e888a 100644 --- a/resources/lang/id/scores.php +++ b/resources/lang/id/scores.php @@ -24,7 +24,7 @@ 'status' => [ 'non_best' => 'Hanya skor-skor terbaik yang memberikan pp', - 'non_passing' => '', + 'non_passing' => 'Hanya skor pass yang memberikan pp', 'processing' => 'Skor ini sedang diproses dan akan ditampilkan kemudian', ], ]; diff --git a/resources/lang/it/scores.php b/resources/lang/it/scores.php index cbd0af01836..aad5863818a 100644 --- a/resources/lang/it/scores.php +++ b/resources/lang/it/scores.php @@ -24,7 +24,7 @@ 'status' => [ 'non_best' => 'Solo i punteggi migliori conferiscono pp', - 'non_passing' => '', + 'non_passing' => 'Solo i punteggi passati conferiscono pp', 'processing' => 'Questo punteggio dev\'essere ancora calcolato e verrà mostrato presto', ], ]; diff --git a/resources/lang/ja/scores.php b/resources/lang/ja/scores.php index 934cef46aa6..742ebfb4750 100644 --- a/resources/lang/ja/scores.php +++ b/resources/lang/ja/scores.php @@ -24,7 +24,7 @@ 'status' => [ 'non_best' => '個人のベストスコアのみppを与えます。', - 'non_passing' => '', + 'non_passing' => 'パスしたスコアのみppを付与', 'processing' => 'このスコアはまだ計算中です。すぐに表示されます。', ], ]; diff --git a/resources/lang/ko/scores.php b/resources/lang/ko/scores.php index a24c0d2dfb8..4090130fade 100644 --- a/resources/lang/ko/scores.php +++ b/resources/lang/ko/scores.php @@ -24,7 +24,7 @@ 'status' => [ 'non_best' => '개인 최고 점수만 pp를 얻습니다.', - 'non_passing' => '', + 'non_passing' => '통과한 점수만 pp를 얻습니다', 'processing' => '이 점수는 아직 계산 중이며 곧 표시될 예정입니다.', ], ]; diff --git a/resources/lang/pl/notifications.php b/resources/lang/pl/notifications.php index 7a309b3a00f..3d7b4f24e32 100644 --- a/resources/lang/pl/notifications.php +++ b/resources/lang/pl/notifications.php @@ -239,7 +239,7 @@ ], 'user_beatmapset_new' => [ - 'user_beatmapset_new' => 'Użytkownik :username przesłał nowe beatmapy', + 'user_beatmapset_new' => 'Użytkownik :username stworzył nowe beatmapy', 'user_beatmapset_revive' => 'Użytkownik :username ożywił beatmapy', ], ], diff --git a/resources/lang/pl/scores.php b/resources/lang/pl/scores.php index 2e98135d131..723596eb597 100644 --- a/resources/lang/pl/scores.php +++ b/resources/lang/pl/scores.php @@ -24,7 +24,7 @@ 'status' => [ 'non_best' => 'Tylko twoje najlepsze wyniki przyznają pp', - 'non_passing' => '', + 'non_passing' => 'Tylko zagrania niezakończone porażką przyznają pp', 'processing' => 'Ten wynik jest nadal obliczany i zostanie wyświetlony wkrótce.', ], ]; diff --git a/resources/lang/pt-br/scores.php b/resources/lang/pt-br/scores.php index c24ea57c9c0..cb21be0ff4e 100644 --- a/resources/lang/pt-br/scores.php +++ b/resources/lang/pt-br/scores.php @@ -24,7 +24,7 @@ 'status' => [ 'non_best' => 'Apenas as melhores pontuações pessoais dão pp', - 'non_passing' => '', + 'non_passing' => 'Apenas pontuações bem sucedidas dão pp', 'processing' => 'Esta pontuação ainda está sendo calculada e será exibida em breve', ], ]; diff --git a/resources/lang/pt/scores.php b/resources/lang/pt/scores.php index b1c097d7956..9fe603dc77a 100644 --- a/resources/lang/pt/scores.php +++ b/resources/lang/pt/scores.php @@ -24,7 +24,7 @@ 'status' => [ 'non_best' => 'Apenas as melhores pontuações pessoais dão pp', - 'non_passing' => '', + 'non_passing' => 'Apenas as pontuações aprovadas recompensam pp', 'processing' => 'Esta pontuação ainda está a ser calculada e será exibida em breve', ], ]; diff --git a/resources/lang/ru/beatmap_discussion_posts.php b/resources/lang/ru/beatmap_discussion_posts.php index 6eb3194f0a8..a88cb511ca2 100644 --- a/resources/lang/ru/beatmap_discussion_posts.php +++ b/resources/lang/ru/beatmap_discussion_posts.php @@ -5,7 +5,7 @@ return [ 'index' => [ - 'title' => 'Публикации в обсуждении карты', + 'title' => 'Посты в обсуждении карты', ], 'item' => [ diff --git a/resources/lang/ru/beatmap_discussions.php b/resources/lang/ru/beatmap_discussions.php index e788643ee2d..67365bb27ba 100644 --- a/resources/lang/ru/beatmap_discussions.php +++ b/resources/lang/ru/beatmap_discussions.php @@ -102,6 +102,6 @@ 'user_filter' => [ 'everyone' => 'Все', - 'label' => 'Сортировать по пользователям', + 'label' => 'По пользователям', ], ]; diff --git a/resources/lang/ru/beatmaps.php b/resources/lang/ru/beatmaps.php index 3ab9bfe249c..e744541cf5b 100644 --- a/resources/lang/ru/beatmaps.php +++ b/resources/lang/ru/beatmaps.php @@ -101,7 +101,7 @@ 'new' => 'Новый отзыв', 'embed' => [ 'delete' => 'Удалить', - 'missing' => '[ТЕМА УДАЛЕНА]', + 'missing' => '[ОТЗЫВ УДАЛЁН]', 'unlink' => 'Отвязать', 'unsaved' => 'Не сохранено', 'timestamp' => [ diff --git a/resources/lang/ru/mail.php b/resources/lang/ru/mail.php index 741dedaf4cf..c6b99773e37 100644 --- a/resources/lang/ru/mail.php +++ b/resources/lang/ru/mail.php @@ -5,17 +5,17 @@ return [ 'beatmapset_update_notice' => [ - 'new' => 'Просто даём знать: с Вашего последнего посещения у карты «:title» вышло новое обновление.', - 'subject' => 'Новое обновление у карты «:title»', - 'unwatch' => 'Если Вы больше не желаете следить за этой картой, вы можете нажать ссылку «Не следить» на странице выше или со страницы подписок на карты:', + 'new' => 'Просто даём знать: с Вашего последнего посещения у карты ":title" вышло новое обновление.', + 'subject' => 'Новое обновление у карты ":title"', + 'unwatch' => 'Если Вы больше не желаете следить за этой картой, Вы можете нажать ссылку «Не следить» на странице выше или со страницы подписок на карты:', 'visit' => 'Посетите страницу обсуждения:', ], 'common' => [ 'closing' => 'С уважением,', 'hello' => 'Привет, :user,', - 'report' => 'Пожалуйста, ответьте на это письмо НЕМЕДЛЕННО, если вы не запрашивали это изменение.', - 'ignore' => 'Если вы не делали этот запрос - проигнорируйте это сообщение.', + 'report' => 'Пожалуйста, ответьте на это письмо НЕМЕДЛЕННО, если Вы не запрашивали это изменение.', + 'ignore' => 'Если Вы не делали этот запрос - проигнорируйте это сообщение.', ], 'donation_thanks' => [ @@ -28,11 +28,11 @@ 'benefit' => [ 'gift' => 'Получатель вашего подарка теперь будет иметь доступ к osu!direct и многим другим привилегиям тега osu!supporter.', - 'self' => 'Теперь у Вас есть доступ к osu!direct и многим другим привилегиям тега supporter на :duration.', + 'self' => 'Теперь у Вас есть доступ к osu!direct и многим другим привилегиям тега osu!supporter на :duration.', ], 'support' => [ - '_' => 'Большое спасибо за вашу :support в отношении osu!.', + '_' => 'Большое спасибо за Вашу :support в отношении osu!.', 'first' => 'поддержку', 'repeat' => 'продолжительную поддержку', ], @@ -47,7 +47,7 @@ 'password_reset' => [ 'code' => 'Ваш код подтверждения:', - 'requested' => 'Либо вы, либо кто-то, выдающий себя за вас, запросил смену пароля вашего аккаунта osu!', + 'requested' => 'Либо Вы, либо кто-то, выдающий себя за вас, запросил смену пароля вашего аккаунта osu!', 'subject' => 'Восстановления доступа к аккаунту osu!', ], @@ -56,7 +56,7 @@ 'processing' => 'Мы получили Ваш платёж и сейчас обрабатываем Ваш заказ. Вы можете следить за прогрессом своего заказа здесь:', 'questions' => "Если у Вас есть какие-то вопросы, не стесняйтесь отвечать на это письмо.", 'shipping' => 'Доставка', - 'subject' => 'Мы получили ваш заказ в osu!store!', + 'subject' => 'Мы получили Ваш заказ в osu!store!', 'thank_you' => 'Спасибо за Ваш заказ в osu!store!', 'total' => 'Всего', ], @@ -67,13 +67,13 @@ 'duration' => 'Благодаря ему у вас теперь есть доступ к osu!direct и другим преимуществам osu!supporter на :duration.', 'features' => 'Подробнее об этих функциях можно узнать здесь:', 'gifted' => 'Кто-то только что подарил вам тег osu!supporter!', - 'subject' => 'Вам подарили osu!supporter!', + 'subject' => 'Вам подарили тег osu!supporter!', ], 'user_email_updated' => [ 'changed_to' => 'Это письмо с подтверждением о том, что ваш адрес электронной почты osu! был изменён на ":email".', - 'check' => 'Пожалуйста, убедитесь, что вы получили это письмо на новый адрес email, чтобы в будущем предотвратить потерю доступа к вашему аккаунту osu!.', - 'sent' => 'По соображениям безопасности, это письмо было отправлено и на Ваш старый, и на новый адрес электронной почты.', + 'check' => 'Пожалуйста, убедитесь, что Вы получили это письмо на новый адрес email, чтобы в будущем предотвратить потерю доступа к вашему аккаунту osu!.', + 'sent' => 'По соображениям безопасности это письмо было отправлено как на Ваш старый, так и на новый адрес электронной почты.', 'subject' => 'Подтверждение смены почты аккаунта osu!', ], @@ -91,7 +91,7 @@ ], 'user_password_updated' => [ - 'confirmation' => 'Это всего лишь подверждение, что Ваш пароль к osu! был изменён.', + 'confirmation' => 'Это всего лишь подтверждение, что Ваш пароль к osu! был изменён.', 'subject' => 'Подтверждение смены пароля аккаунта osu!', ], @@ -99,7 +99,7 @@ 'code' => 'Ваш код верификации:', 'code_hint' => 'Вы можете ввести код с пробелами или без них.', 'link' => 'В качестве альтернативы, Вы также можете перейти по ссылке ниже для завершения верификации:', - 'report' => 'Если Вы не запрашивали его, пожалуйста, НЕМЕДЛЕННО ОТВЕТЬТЕ на письмо, так как Ваш аккаунт может быть под угрозой.', + 'report' => 'Если Вы его не запрашивали, пожалуйста, НЕМЕДЛЕННО ОТВЕТЬТЕ на письмо, так как Ваш аккаунт может быть под угрозой.', 'subject' => 'Подтверждение доступа к аккаунту osu!', 'action_from' => [ diff --git a/resources/lang/ru/scores.php b/resources/lang/ru/scores.php index 878651cdba7..390e23efb0c 100644 --- a/resources/lang/ru/scores.php +++ b/resources/lang/ru/scores.php @@ -23,8 +23,8 @@ ], 'status' => [ - 'non_best' => 'Только ваши лучшие результаты приносят PP', - 'non_passing' => '', + 'non_best' => 'Только лучшие рекорды приносят pp', + 'non_passing' => 'Только проверенные рекорды приносят pp', 'processing' => 'Этот результат все ещё подсчитывается и будет отображен позже', ], ]; diff --git a/resources/lang/ru/users.php b/resources/lang/ru/users.php index 83efb7af677..0a7f603b740 100644 --- a/resources/lang/ru/users.php +++ b/resources/lang/ru/users.php @@ -327,7 +327,7 @@ ], 'top_ranks' => [ 'download_replay' => 'Скачать запись', - 'not_ranked' => 'Очки производительности выдаются только за прохождение рейтинговых карт', + 'not_ranked' => 'Только рейтинговые карты приносят pp', 'pp_weight' => 'засчитано: :percentage pp', 'view_details' => 'Подробнее', 'title' => 'Рейтинги', diff --git a/resources/lang/sl-SI/beatmapsets.php b/resources/lang/sl-SI/beatmapsets.php index ce536b2edd1..be91e14b19f 100644 --- a/resources/lang/sl-SI/beatmapsets.php +++ b/resources/lang/sl-SI/beatmapsets.php @@ -24,7 +24,7 @@ ], 'index' => [ - 'title' => 'Seznam beatpmap', + 'title' => 'Seznam beatmap', 'guest_title' => 'Beatmape', ], diff --git a/resources/lang/sl-SI/layout.php b/resources/lang/sl-SI/layout.php index d89a4158c5d..d183166992c 100644 --- a/resources/lang/sl-SI/layout.php +++ b/resources/lang/sl-SI/layout.php @@ -5,203 +5,203 @@ return [ 'audio' => [ - 'autoplay' => '', + 'autoplay' => 'Avtomatsko predvajaj naslednjo skladbo', ], 'defaults' => [ - 'page_description' => '', + 'page_description' => 'osu! - Ritem je samo *klik* stran! Z Ouendan/EBA, Taiko in originalnimi igralnimi načini kot tudi polno funkcionalen urejevalnik.', ], 'header' => [ 'admin' => [ - 'beatmapset' => '', - 'beatmapset_covers' => '', - 'contest' => '', - 'contests' => '', - 'root' => '', + 'beatmapset' => 'zbirka beatmap', + 'beatmapset_covers' => 'naslovne slike zbirk beatmap', + 'contest' => 'tekmovanje', + 'contests' => 'tekmovanja', + 'root' => 'konzola', ], 'artists' => [ - 'index' => '', + 'index' => 'seznam', ], 'beatmapsets' => [ - 'show' => '', - 'discussions' => '', + 'show' => 'info', + 'discussions' => 'razprava', ], 'changelog' => [ - 'index' => '', + 'index' => 'seznam', ], 'help' => [ - 'index' => '', - 'sitemap' => '', + 'index' => 'indeks', + 'sitemap' => 'Zemljevid', ], 'store' => [ - 'cart' => '', - 'orders' => '', - 'products' => '', + 'cart' => 'košarica', + 'orders' => 'zgodovina nakupov', + 'products' => 'izdelki', ], 'tournaments' => [ - 'index' => '', + 'index' => 'seznam', ], 'users' => [ 'modding' => '', - 'playlists' => '', - 'realtime' => '', - 'show' => '', + 'playlists' => 'seznam pesmi', + 'realtime' => 'večigralski način', + 'show' => 'info', ], ], 'gallery' => [ - 'close' => '', - 'fullscreen' => '', - 'zoom' => '', - 'previous' => '', - 'next' => '', + 'close' => 'Zapri (Esc)', + 'fullscreen' => 'Preklopi na celozaslonski način', + 'zoom' => 'Povečaj/Pomanjšaj', + 'previous' => 'Nazaj (puščica levo)', + 'next' => 'Naprej (puščica desno)', ], 'menu' => [ 'beatmaps' => [ - '_' => '', + '_' => 'beatmape', ], 'community' => [ - '_' => '', - 'dev' => '', + '_' => 'skupnost', + 'dev' => 'razvoj', ], 'help' => [ - '_' => '', - 'getAbuse' => '', - 'getFaq' => '', - 'getRules' => '', - 'getSupport' => '', + '_' => 'pomoč', + 'getAbuse' => 'prijavi zlorabo', + 'getFaq' => 'faq', + 'getRules' => 'pravila', + 'getSupport' => 'ne, resno, potrebujem pomoč!', ], 'home' => [ - '_' => '', - 'team' => '', + '_' => 'domov', + 'team' => 'ekipa', ], 'rankings' => [ - '_' => '', - 'kudosu' => '', + '_' => 'uvrstitve', + 'kudosu' => 'kudosu', ], 'store' => [ - '_' => '', + '_' => 'trgovina', ], ], 'footer' => [ 'general' => [ - '_' => '', - 'home' => '', - 'changelog-index' => '', - 'beatmaps' => '', - 'download' => '', + '_' => 'Splošno', + 'home' => 'Domov', + 'changelog-index' => 'Dnevnik sprememb', + 'beatmaps' => 'Seznam beatmap', + 'download' => 'Prenesi osu!', ], 'help' => [ - '_' => '', - 'faq' => '', - 'forum' => '', - 'livestreams' => '', - 'report' => '', - 'wiki' => '', + '_' => 'Pomoč & Skupnost', + 'faq' => 'Pogosta vprašanja', + 'forum' => 'Forumi skupnosti', + 'livestreams' => 'Oddajanja v živo', + 'report' => 'Prijavi težavo', + 'wiki' => 'Wiki', ], 'legal' => [ - '_' => '', - 'copyright' => '', - 'privacy' => '', - 'server_status' => '', - 'source_code' => '', - 'terms' => '', + '_' => 'Pravno & Stanje', + 'copyright' => 'Avtorske pravice (DMCA)', + 'privacy' => 'Zasebnost', + 'server_status' => 'Stanje Strežnika', + 'source_code' => 'Izvorna Koda', + 'terms' => 'Pogoji', ], ], 'errors' => [ '400' => [ - 'error' => '', + 'error' => 'Neveljaven zahtevani parameter', 'description' => '', ], '404' => [ - 'error' => '', - 'description' => "", + 'error' => 'Manjkajoča stran', + 'description' => "Se opravičujemo, ampak željena spletna stran ni tukaj!", ], '403' => [ - 'error' => "", - 'description' => '', + 'error' => "Tukaj ne bi smel biti.", + 'description' => 'Mogoče lahko poskusiš vrniti nazaj.', ], '401' => [ - 'error' => "", - 'description' => '', + 'error' => "Tukaj ne bi smel biti.", + 'description' => 'Mogoče lahko poskusiš vrniti nazaj. Ali pa se vpišeš.', ], '405' => [ - 'error' => '', - 'description' => "", + 'error' => 'Manjkajoča stran', + 'description' => "Se opravičujemo, ampak željena spletna stran ni tukaj!", ], '422' => [ - 'error' => '', + 'error' => 'Neveljaven zahtevani parameter', 'description' => '', ], '429' => [ - 'error' => '', + 'error' => 'Omejitev prekoračena', 'description' => '', ], '500' => [ - 'error' => '', - 'description' => "", + 'error' => 'O ne! Nekaj se je zalomilo! ;_;', + 'description' => "Avtomatsko smo obveščeni ob vsaki napaki.", ], 'fatal' => [ - 'error' => '', - 'description' => "", + 'error' => 'O ne! Nekaj se je zalomilo (hudo)! ;_;', + 'description' => "Avtomatsko smo obveščeni ob vsaki napaki.", ], '503' => [ - 'error' => '', - 'description' => "", + 'error' => 'Dostop zavrnjen zaradi vzdrževanja!', + 'description' => "Vzdrževanje ponavadi traja od 5 sekund do 10 minut. Če vzdrževanje traja dlje, obišči :link za več informacij.", 'link' => [ 'text' => '', 'href' => '', ], ], // used by sentry if it returns an error - 'reference' => "", + 'reference' => "Za vsak slučaj, tukaj je koda, ki jo lahko posreduješ podpori!", ], 'popup_login' => [ - 'button' => '', + 'button' => 'vpiši se / registriraj se', 'login' => [ - 'forgot' => "", - 'password' => '', - 'title' => '', - 'username' => '', + 'forgot' => "Pozabil sem svoje podatke", + 'password' => 'geslo', + 'title' => 'Vpiši se za nadaljevanje', + 'username' => 'uporabniško ime', 'error' => [ - 'email' => "", - 'password' => '', + 'email' => "Uporabniško ime ali e-poštni naslov ne obstaja", + 'password' => 'Nepravilno geslo', ], ], 'register' => [ - 'download' => '', - 'info' => '', - 'title' => "", + 'download' => 'Prenesi', + 'info' => 'Prenesi osu!, da lahko ustvariš svoj račun!', + 'title' => "Še nimaš računa?", ], ], 'popup_user' => [ 'links' => [ - 'account-edit' => '', + 'account-edit' => 'Nastavitve', 'follows' => '', - 'friends' => '', - 'logout' => '', - 'profile' => '', + 'friends' => 'Prijatelji', + 'logout' => 'Odjavi se', + 'profile' => 'Moj profil', ], ], 'popup_search' => [ - 'initial' => '', - 'retry' => '', + 'initial' => 'Vpiši za iskanje!', + 'retry' => 'Iskanje neuspešno. Klikni za ponovni poskus.', ], ]; diff --git a/resources/lang/sl-SI/livestreams.php b/resources/lang/sl-SI/livestreams.php index 6f8eb6888d7..5ba4961f4a8 100644 --- a/resources/lang/sl-SI/livestreams.php +++ b/resources/lang/sl-SI/livestreams.php @@ -5,13 +5,13 @@ return [ 'promote' => [ - 'pin' => '', - 'unpin' => "", + 'pin' => 'Ali si prepričan, da bi promoviral to oddajanje v živo?', + 'unpin' => "Ali si prepričan, da bi odstranil promoviranje tega oddajanja v živo?", ], 'top-headers' => [ - 'headline' => '', - 'description' => '', + 'headline' => 'Oddajanja v živo', + 'description' => 'Podatki so pridobljeni od twitch.tv vsakih pet minut glede na seznam v imeniku. Oddajaj v živo in se uvrsti na seznam! Za več informacij o konfiguraciji prosimo obišči :link.', 'link' => '', ], diff --git a/resources/lang/sl-SI/mail.php b/resources/lang/sl-SI/mail.php index a809897f2cb..1b0cf5a45db 100644 --- a/resources/lang/sl-SI/mail.php +++ b/resources/lang/sl-SI/mail.php @@ -5,106 +5,106 @@ return [ 'beatmapset_update_notice' => [ - 'new' => '', - 'subject' => '', - 'unwatch' => '', - 'visit' => '', + 'new' => 'V vednost, beatmapa ":title" je pridobila novo posodobitev odkar si nazadnje obiskal osu!.', + 'subject' => 'Nova posodobitev beatmape ":title"', + 'unwatch' => 'Če ne želiš več imeti te beatmape na seznamu gledanih, lahko klikneš na "Ne spremljaj" povezavo na vrhu strani ali iz modding seznama gledanih:', + 'visit' => 'Obišči razpravljalno stran tukaj:', ], 'common' => [ - 'closing' => '', - 'hello' => '', - 'report' => '', - 'ignore' => '', + 'closing' => 'Lep pozdrav,', + 'hello' => 'Zdravo :user,', + 'report' => 'Če nisi zahteval te spremembe, te prosimo, da TAKOJ ukrepaš z odgovorom na to e-pošto.', + 'ignore' => 'Če nisi zahteval tega, lahko varno ignoriraš to e-pošto.', ], 'donation_thanks' => [ - 'benefit_more' => '', - 'feedback' => "", - 'keep_free' => '', - 'keep_running' => '', - 'subject' => '', - 'translation' => '', + 'benefit_more' => 'Več supporter ugodnosti se bo pojavilo čez čas!', + 'feedback' => "Če imaš kakšno vprašanje ali povratno informacijo, lahko to storiš z odgovorom na to e-pošto; Odgovoril bom v najkrajšem možnem času!", + 'keep_free' => 'To je zahvala za osebe kot si ti, da lahko osu! in njegovo skupnost ohrani brez problemov in brez oglasov ali prisilnih plačil.', + 'keep_running' => 'Tvoja podpora ohranja osu! delovati za približno :minutes! Ne zgleda ravno veliko, ampak se vse skupaj sešteje :).', + 'subject' => 'Hvala, osu! te ima rad <3', + 'translation' => 'Skupnostni prevod za informacijske namene:', 'benefit' => [ - 'gift' => '', - 'self' => '', + 'gift' => 'Tvoj obdarjenec (ali obdarjenci) bo sedaj imel dostop do osu!direct in veliko drugih podporniških ugodnosti.', + 'self' => 'Sedaj boš imel dostop do osu!direct in veliko drugih podporniških ugodnosti za :duration.', ], 'support' => [ - '_' => '', - 'first' => '', - 'repeat' => '', + '_' => 'Najlepša hvala za tvojo :support usmerjeno osu!.', + 'first' => 'podporo', + 'repeat' => 'nadaljevano podporo', ], ], 'forum_new_reply' => [ - 'new' => '', - 'subject' => '', - 'unwatch' => '', - 'visit' => '', + 'new' => 'V vednost, prejel si nov odgovor v ":title", odkar si nazadnje obiskal osu!.', + 'subject' => '[osu!] Nov odgovor za temo ":title"', + 'unwatch' => 'Če ne želiš več slediti tej temi, lahko klikneš na "Izpis od teme" v obliki povezave spodaj pod temo zgoraj ali preko strani za upravljanje naročenih tem:', + 'visit' => 'Pojdi direktno do zadnjega odgovora preko sledeče povezave:', ], 'password_reset' => [ - 'code' => '', - 'requested' => '', - 'subject' => '', + 'code' => 'Tvoja verifikacijska koda je:', + 'requested' => 'Ti ali nekdo drug, ki se pretvarja, da si ti je poslal zahtevo za ponastavitev gesla za tvoj osu! račun.', + 'subject' => 'Obnovitev osu! računa', ], 'store_payment_completed' => [ - 'prepare_shipping' => '', - 'processing' => '', - 'questions' => "", - 'shipping' => '', - 'subject' => '', - 'thank_you' => '', - 'total' => '', + 'prepare_shipping' => 'Prejeli smo tvoje plačilo in pripravljamo tvoje naročilo za pošiljanje. To lahko traja par dni, da odpošljemo, odvisno na količino naročil. Stanje tvojega naročila lahko preveriš tukaj vred z sledilnimi podatki, ki so na voljo:', + 'processing' => 'Prejeli smo tvoje plačilo in trenuno obdelujemo tvoje naročilo. Svojemu naročilu lahko slediš tukaj:', + 'questions' => "Če imaš kakšno vprašanje, lahko to storiš z odgovorom na to e-pošto.", + 'shipping' => 'Dostava', + 'subject' => 'Prejeli smo tvoje osu!store naročilo!', + 'thank_you' => 'Hvala za naročilo na osu!store!', + 'total' => 'Skupaj', ], 'supporter_gift' => [ - 'anonymous_gift' => '', - 'anonymous_gift_maybe_not' => '', - 'duration' => '', - 'features' => '', - 'gifted' => '', - 'subject' => '', + 'anonymous_gift' => 'Oseba, ki ti je podarila značko je ostala anonimna, posledično ni bila omenjena v tem obvestilu.', + 'anonymous_gift_maybe_not' => 'Ampak verjetno že veš kdo je to ;).', + 'duration' => 'V zahvalo njemu imaš sedaj dostop do osu!direct in drugih osu!supporter ugodnosti za :duration.', + 'features' => 'Več informacij o teh funkcijah lahko najdeš tukaj:', + 'gifted' => 'Nekdo ti je pravkar podaril osu!supporter značko!', + 'subject' => 'Obdarjen si bil z osu!supporter značko!', ], 'user_email_updated' => [ - 'changed_to' => '', - 'check' => '', - 'sent' => '', - 'subject' => '', + 'changed_to' => 'To je potrditvena e-pošta z informacijo, da se je tvoj osu! e-poštni naslov spremenil v: ":email".', + 'check' => 'Prosimo preveri, da si prejel e-pošto na svoj nov e-poštni naslov, s tem preprečiš izgubo svojega osu! računa v prihodnosti.', + 'sent' => 'Zaradi varnostnih razlogov je bila ta e-pošta poslana na stari in novi e-poštni naslov.', + 'subject' => 'Potrditev menjave e-pošnega naslova za osu!', ], 'user_force_reactivation' => [ - 'main' => '', - 'perform_reset' => '', - 'reason' => '', - 'subject' => '', + 'main' => 'Na tvojem računu obstaja sum, da je bil ogrožen, ima nedavno sumljivo aktivnost ali ZELO šibko geslo. Posledično te prosimo za nastavitev novega gesla. Prosimo tudi, da si izbereš VARNO geslo.', + 'perform_reset' => 'Ponastavitev lahko opraviš tukaj :url', + 'reason' => 'Razlog:', + 'subject' => 'Zahtevana ponovna aktivacija osu! računa', ], 'user_notification_digest' => [ - 'new' => '', - 'settings' => '', - 'subject' => '', + 'new' => 'V vednost, prišlo je do novih posodobitev stvari, ki jih imaš na seznamu gledanih.', + 'settings' => 'Spremenite nastavitve e-poštnih obvestil:', + 'subject' => 'Nova osu! obvestila', ], 'user_password_updated' => [ - 'confirmation' => '', - 'subject' => '', + 'confirmation' => 'To je potrditvena e-pošta z informacijo, da se je tvoje osu! geslo spremenilo.', + 'subject' => 'Potrditev spremembe osu! gesla', ], 'user_verification' => [ - 'code' => '', - 'code_hint' => '', - 'link' => '', - 'report' => '', - 'subject' => '', + 'code' => 'Tvoja verifikacijska koda je:', + 'code_hint' => 'Kodo lahko vpišeš z ali brez presledkov.', + 'link' => 'Namesto tega lahko obiščeš povezavo spodaj, da opraviš verifikacijo:', + 'report' => 'Če nisi tega zahteval, te prosimo za TAKOJŠNJI ODGOVOR, možnost je lahko, da je tvoj račun v nevarnosti.', + 'subject' => 'Verifikacija osu! računa', 'action_from' => [ - '_' => '', - 'unknown_country' => '', + '_' => 'Dejanje, izvedeno na tvojem računu iz :country zahteva verifikacijo.', + 'unknown_country' => 'neznana država', ], ], ]; diff --git a/resources/lang/sl-SI/matches.php b/resources/lang/sl-SI/matches.php index ce5d058b355..35fb9b52a7f 100644 --- a/resources/lang/sl-SI/matches.php +++ b/resources/lang/sl-SI/matches.php @@ -5,57 +5,57 @@ return [ 'match' => [ - 'beatmap-deleted' => '', - 'difference' => '', - 'failed' => '', - 'header' => '', - 'in-progress' => '', - 'in_progress_spinner_label' => '', - 'loading-events' => '', - 'winner' => '', + 'beatmap-deleted' => 'odstranjena beatmapa', + 'difference' => 'za :difference', + 'failed' => 'NEUSPEŠNO', + 'header' => 'Večigralske tekme', + 'in-progress' => '(tekma v teku)', + 'in_progress_spinner_label' => 'tekma v teku', + 'loading-events' => 'Nalaganje dogodkov...', + 'winner' => ':team je zmagovalec', 'events' => [ - 'player-left' => '', - 'player-joined' => '', - 'player-kicked' => '', - 'match-created' => '', - 'match-disbanded' => '', - 'host-changed' => '', + 'player-left' => ':user je zapustil sobo', + 'player-joined' => ':user se je pridružil sobi', + 'player-kicked' => ':user je bil odstranjen iz tekme', + 'match-created' => ':user je ustvaril sobo', + 'match-disbanded' => 'tekma je bila prekinjena', + 'host-changed' => ':user je postal gostitelj', - 'player-left-no-user' => '', - 'player-joined-no-user' => '', - 'player-kicked-no-user' => '', - 'match-created-no-user' => '', - 'match-disbanded-no-user' => '', - 'host-changed-no-user' => '', + 'player-left-no-user' => 'igralec je zapustil tekmo', + 'player-joined-no-user' => 'igralec se je pridružil tekmi', + 'player-kicked-no-user' => 'igralec je bil odstranjen iz tekme', + 'match-created-no-user' => 'tekma je bila ustvarjena', + 'match-disbanded-no-user' => 'tekma je bila prekinjena', + 'host-changed-no-user' => 'gostitelj se je spremenil', ], 'score' => [ 'stats' => [ - 'accuracy' => '', - 'combo' => '', - 'score' => '', + 'accuracy' => 'Natančnost', + 'combo' => 'Combo', + 'score' => 'Rezultat', ], ], 'team-types' => [ - 'head-to-head' => '', - 'tag-coop' => '', - 'team-vs' => '', - 'tag-team-vs' => '', + 'head-to-head' => 'Soočenje', + 'tag-coop' => 'Tag Co-op', + 'team-vs' => 'Ekipa VS', + 'tag-team-vs' => 'Tag Ekipa VS', ], 'teams' => [ - 'blue' => '', - 'red' => '', + 'blue' => 'Modra Ekipa', + 'red' => 'Rdeča Ekipa', ], ], 'game' => [ 'scoring-type' => [ - 'score' => '', - 'accuracy' => '', - 'combo' => '', - 'scorev2' => '', + 'score' => 'Najvišji rezulatat', + 'accuracy' => 'Najvišja Natančnost', + 'combo' => 'Najvišji Combo', + 'scorev2' => 'Rezultat V2', ], ], ]; diff --git a/resources/lang/uk/accounts.php b/resources/lang/uk/accounts.php index ff6390c1faf..3aca754be22 100644 --- a/resources/lang/uk/accounts.php +++ b/resources/lang/uk/accounts.php @@ -10,7 +10,7 @@ 'avatar' => [ 'title' => 'Аватар', - 'rules' => 'Будь ласка, переконайтеся в тому, що Ваш аватар відповідає :link.
Це означає, що він повинен підходити людям будь-якого віку. Тобто: не містити наготу, нецензурну лексику та непристойні матеріали.', + 'rules' => 'Будь ласка, переконайтесь що Ваш аватар відповідає :link.
Це означає що він має підходити відповідно, людям будь-якого віку. Тобто: не містити наготу, нецензурну лексику або відвертий й непристойний вміст.', 'rules_link' => 'правила спільноти', ], diff --git a/resources/lang/uk/beatmap_discussions.php b/resources/lang/uk/beatmap_discussions.php index c7dd678de7e..663e728a63b 100644 --- a/resources/lang/uk/beatmap_discussions.php +++ b/resources/lang/uk/beatmap_discussions.php @@ -6,7 +6,7 @@ return [ 'authorizations' => [ 'update' => [ - 'null_user' => 'Ви повинні ввійти для редагування.', + 'null_user' => 'Ви повинні увійти для редагування.', 'system_generated' => 'Системне повідомлення не може бути змінено.', 'wrong_user' => 'Ви повинні бути автором даної публікації для редагування.', ], @@ -92,7 +92,7 @@ 'system' => [ 'resolved' => [ 'true' => 'Позначено вирішеним користувачем :user', - 'false' => 'Повторно відкрито користувачем :user', + 'false' => 'Відкрито повторно користувачем :user', ], ], diff --git a/resources/lang/uk/beatmappacks.php b/resources/lang/uk/beatmappacks.php index a7b5526b90c..42903f7fa25 100644 --- a/resources/lang/uk/beatmappacks.php +++ b/resources/lang/uk/beatmappacks.php @@ -5,7 +5,7 @@ return [ 'index' => [ - 'description' => 'Попередньо впаковані колекції мап, засновані на загальних темах.', + 'description' => 'Попередньо впаковані колекції мап, засновані на загальних тематиках.', 'nav_title' => 'список', 'title' => 'Збірки мап', @@ -26,7 +26,7 @@ 'not_cleared' => 'не завершено', ], 'no_diff_reduction' => [ - '_' => ':link не можна використовувати для завершення цього набору.', + '_' => ':link не можуть бути використані для завершення цього набору.', 'link' => 'Моди зменшення складності ', ], ], @@ -39,7 +39,7 @@ ], 'require_login' => [ - '_' => 'Ви повинні :link для завантаження', + '_' => 'Ви повинні :link для завантаження цього набору', 'link_text' => 'увійти', ], ]; diff --git a/resources/lang/uk/beatmaps.php b/resources/lang/uk/beatmaps.php index 6b4411d46c0..9bb59a54697 100644 --- a/resources/lang/uk/beatmaps.php +++ b/resources/lang/uk/beatmaps.php @@ -101,7 +101,7 @@ 'new' => 'Новий відгук', 'embed' => [ 'delete' => 'Видалити', - 'missing' => '[ДИСКУСІЯ ВИДАЛЕНА]', + 'missing' => '[ДИСКУСІЮ ВИДАЛЕНО]', 'unlink' => 'Відв\'язати', 'unsaved' => 'Не збережено', 'timestamp' => [ @@ -141,7 +141,7 @@ 'approved' => 'Ця карта була схвалена :date!', 'graveyard' => "Ця карта не оновлювалася вже з :date і здається автор її покинув...", 'loved' => 'Ця карта була визнана "улюбленою" :date!', - 'ranked' => 'Ця карта потрапила в рейтингові :date!', + 'ranked' => 'Ця карта стала рейтинговою :date!', 'wip' => 'Примітка: Ця карта була позначена автором як незавершена.', ], @@ -160,11 +160,11 @@ 'hype' => [ 'button' => 'Хайпнути карту!', 'button_done' => 'Вже хайпнута!', - 'confirm' => "Ви впевнені? Ця дія відбере один з :n хайпів і не може бути скасованою.", - 'explanation' => 'Це зробить карту більш помітною для номінації та рейтингу!', - 'explanation_guest' => 'Увійдіть, щоб зробити карту доступною для номінування!', + 'confirm' => "Ви впевнені? Ця дія використає один з ваших :n хайпів. Ця дія не може бути скасована.", + 'explanation' => 'Хайпніть цю мапу! Це зробить її більш помітною для номінації й потрапляння в рейтинг!', + 'explanation_guest' => 'Увійдіть, щоб зробити карту доступною для номінації!', 'new_time' => "Ви отримаєте інший хайп :new_time.", - 'remaining' => 'У вас залишилося :remaining хайпу.', + 'remaining' => 'У вас залишилося :remaining хайпів.', 'required_text' => 'Хайпи: :current/:required', 'section_title' => 'Прогрес хайпу', 'title' => 'Хайп', @@ -191,7 +191,7 @@ 'nominated_by' => 'отримала номінацію від :users', 'not_enough_hype' => "Недостатньо хайпів.", 'remove_from_loved' => 'Вилучено з категорії Улюблені', - 'remove_from_loved_prompt' => 'Причина вилучення від категорії Улюблені:', + 'remove_from_loved_prompt' => 'Причина вилучення з категорії Улюблені:', 'required_text' => 'Номінації: :current/:required', 'reset_message_deleted' => 'видалено', 'title' => 'Статус номінації', @@ -210,7 +210,7 @@ 'reset_confirm' => [ 'disqualify' => 'Впевнені? Це зніме кваліфікацію з карти й скине прогрес номінування.', - 'nomination_reset' => 'Ви впевнені? Повідомлення про нову проблему скине прогрес номінації.', + 'nomination_reset' => 'Ви впевнені? Нове повідомлення про проблему скине прогрес номінування.', 'problem_warning' => 'Ви впевнені що ви хочете повідомити про проблеми на цій карті? Це звернення сповістить Номінаторів Карт.', ], ], @@ -222,7 +222,7 @@ 'options' => 'Більше параметрів пошуку', 'supporter_filter' => 'Сортування по :filters потребує наявності osu!supporter', 'not-found' => 'немає результатів', - 'not-found-quote' => '... на жаль, нічого не знайдено.', + 'not-found-quote' => '... на жаль, нічого немає.', 'filters' => [ 'extra' => 'Додатково', 'general' => 'Загальні', diff --git a/resources/lang/uk/beatmapsets.php b/resources/lang/uk/beatmapsets.php index b0808f38110..e9b8569d2e0 100644 --- a/resources/lang/uk/beatmapsets.php +++ b/resources/lang/uk/beatmapsets.php @@ -172,7 +172,7 @@ 'no_scores' => [ 'country' => 'Ніхто з вашої країни ще не грав на цій мапі!', 'friend' => 'Ніхто з ваших друзів ще не грав на цій мапі!', - 'global' => 'Ніхто ще не грав на цій мапі! Може бути ви спробуєте?', + 'global' => 'Ніхто ще не грав на цій мапі! Може ти спробуєш?', 'loading' => 'Результати завантажуються...', 'unranked' => 'Нерангова мапа.', ], diff --git a/resources/lang/uk/community.php b/resources/lang/uk/community.php index bb49ea7e192..a514ad58a6d 100644 --- a/resources/lang/uk/community.php +++ b/resources/lang/uk/community.php @@ -8,8 +8,8 @@ 'convinced' => [ 'title' => 'Переконав! :D', 'support' => 'підтримай osu!', - 'gift' => 'або подаруй osu!supporter іншому гравцеві', - 'instructions' => 'натисніть на сердечко для переходу в магазин', + 'gift' => 'або подаруй osu!прихильник іншим гравцям', + 'instructions' => 'натисніть на кнопку з сердечком для переходу в крамницю', ], 'why-support' => [ 'title' => 'Навіщо мені підтримувати osu!? Куди йдуть гроші?', @@ -24,43 +24,43 @@ ], 'featured-artists' => [ 'title' => 'Обрані Виконавці', - 'description' => 'З вашою підтримкою ми зможемо співпрацювати з великою кількістю крутих виконавців і ліцензувати ще більше відмінної музики для використання в osu!', - 'link_text' => 'Подивіться, хто вже є »', + 'description' => 'З вашою підтримкою, ми можемо наблизитись до співпраці з великою кількістю крутих виконавців й ліцензувати більше відмінної музики для використання в osu!', + 'link_text' => 'Подивіться, хто вже з нами »', ], 'ads' => [ - 'title' => 'Підтримуйте незалежність osu!', + 'title' => 'Підтримуйте незалежність й самодостатність osu!', 'description' => 'Ваші внески допоможуть грі залишитися незалежною й повністю вільною від реклами й зовнішніх спонсорів.', ], 'tournaments' => [ 'title' => 'Офіційні турніри', - 'description' => 'Допоможіть фінансувати офіційні турніри osu! World Cup (а також призи для них).', - 'link_text' => 'Перегляньте турніри »', + 'description' => 'Ваші внески допоможуть у підтримці фінансування офіційних турнірів osu! World Cup (а також призових фондів для них).', + 'link_text' => 'Переглянути турніри »', ], 'bounty-program' => [ 'title' => 'Програма заохочення вкладу у відкрите ПЗ', 'description' => 'Підтримайте учасників спільноти, які витратили час і сили для того, щоб зробити osu! краще.', - 'link_text' => 'Дізнайтесь більше »', + 'link_text' => 'Дізнатися більше »', ], ], 'perks' => [ - 'title' => 'Цікаво, а що ж я отримаю?!', + 'title' => 'Круто! А які привілеї я отримаю?', 'osu_direct' => [ 'title' => 'osu!direct', - 'description' => 'Швидкий і легкий доступ до пошуку і завантаження мап, прямо в грі.', + 'description' => 'Швидкий і легкий доступ до пошуку й завантаження мап, відразу у грі.', ], 'friend_ranking' => [ 'title' => 'Рейтинг друзів', - 'description' => "Дізнайтеся, наскільки ви краще ваших друзів, за таблицями рекордів для карт, доступних як в грі, так і на сайті.", + 'description' => "Дізнайтесь, як ви змагаєтесь і наскільки ви краще своїх друзів, за таблицями рекордів для мап як в грі - так і на сайті.", ], 'country_ranking' => [ 'title' => 'Рейтинг країни', - 'description' => 'Завоюйте країну, перш ніж завойовувати світ.', + 'description' => 'Підкоріть свою країну, перш ніж підкорювати світ.', ], 'mod_filtering' => [ - 'title' => 'Фільтр по модам', + 'title' => 'Фільтрування по модам', 'description' => 'Цікавитесь тільки тими, хто грає з HDHR? Без проблем!', ], @@ -71,7 +71,7 @@ 'upload_more' => [ 'title' => 'Завантажуй більше', - 'description' => 'Додаткові слоти для мап в очікуванні рангу (за кожну мапу до 10).', + 'description' => 'Додаткові слоти для мап в очікуванні (на кожну ранговану мапу) максимум до 10.', ], 'early_access' => [ @@ -81,17 +81,17 @@ 'customisation' => [ 'title' => 'Індивідуальність', - 'description' => "Налаштуйте свій профіль, додавши повністю настроювану сторінку \"про мене!\".", + 'description' => "Налаштуйте свій профіль, додавши персональну обкладинку або додавши повністю настроюваний розділ \"про мене!\" у своєму профілі.", ], 'beatmap_filters' => [ - 'title' => 'Фільтри карт', - 'description' => 'Фільтр для пошуку карт, в які ви грали або не грали. А також за отриманими на них рейтингами.', + 'title' => 'Фільтри бітмап', + 'description' => 'Фільтр для пошуку мап за зіграними або не зіграними, або по отриманих на них оцінках.', ], 'yellow_fellow' => [ - 'title' => 'Золотий нік', - 'description' => 'Будьте відомим в грі з яскраво-жовтим кольором ника.', + 'title' => 'Жовтий нік', + 'description' => 'Будьте впізнаваними у грі з яскраво-жовтим кольором ніку.', ], 'speedy_downloads' => [ @@ -100,12 +100,12 @@ ], 'change_username' => [ - 'title' => 'Зміна нікнейму', - 'description' => 'Можливість змінити свій нікнейм без додаткових витрат (тільки один раз)', + 'title' => 'Зміна імені користувача', + 'description' => 'Можливість змінити своє ім\'я користувача (лише один раз) при першій покупці osu!прихильника.', ], 'skinnables' => [ - 'title' => 'Кастомізація', + 'title' => 'Скіни', 'description' => 'Розширенні можливості використання скінів, такі як встановлення свого фону в меню.', ], @@ -116,7 +116,7 @@ 'sort_options' => [ 'title' => 'Параметри сортування', - 'description' => 'Можливість перегляду рейтингу мапи між країнами / друзями / модами в грі.', + 'description' => 'Можливість перегляду рейтингу мапи між країнами / друзями / модами у грі.', ], 'more_favourites' => [ @@ -129,11 +129,11 @@ ], 'more_beatmaps' => [ 'title' => 'Завантажуйте більше мап', - 'description' => 'Скільки нерейтингових мап ви можете мати одночасно звалежить від базового значення плюс бонус за кожну рейтингову мапу яку ви маєте (до певного ліміту).

Зазвичай це :base плюс :bonus за кожну рейтингову мапу (до :bonus_max). З osu!прихильником це значення збільшується до :supporter_base плюс :supporter_bonus за кожну рейтингову мапу (до :supporter_bonus_max).', + 'description' => 'Скільки нерейтингових мап ви можете мати одночасно, залежить від базового значення, плюс бонус за кожну рейтингову мапу яку ви маєте (до певного ліміту).

Зазвичай це :base плюс :bonus за кожну рейтингову мапу (до :bonus_max). З osu!прихильником це значення збільшується до :supporter_base плюс :supporter_bonus за кожну рейтингову мапу (до :supporter_bonus_max).', ], 'friend_filtering' => [ 'title' => 'Рейтинг друзів', - 'description' => 'Змагайтесь з друзями і дізнайтеся наскільки ви сильніші проти них!', + 'description' => 'Змагайтесь з друзями й дізнайтесь наскільки ви краще них!', ], ], diff --git a/resources/lang/uk/errors.php b/resources/lang/uk/errors.php index 166d2efef9c..8979f5472da 100644 --- a/resources/lang/uk/errors.php +++ b/resources/lang/uk/errors.php @@ -4,14 +4,14 @@ // See the LICENCE file in the repository root for full licence text. return [ - 'missing_route' => 'Некоректна URL-адреса або неправильний метод запиту.', - 'no_restricted_access' => 'Ви не може виконати цю дію, доки права доступу облікового запису обмежені.', - 'supporter_only' => 'Ви повинні мати osu!прихильник для використання цієї можливості.', - 'unknown' => 'Сталася невідома помилка.', + 'missing_route' => 'Некоректна адреса або некоректний метод запиту.', + 'no_restricted_access' => 'Ви не можете виконати цю дію, поки ваш обліковий запис знаходиться в обмеженому режимі.', + 'supporter_only' => 'Ви повинні мати osu!прихильника для використання цієї можливості.', + 'unknown' => 'Сталась невідома помилка.', 'codes' => [ 'http-401' => 'Будь ласка, увійдіть, щоб продовжити.', - 'http-403' => 'В доступі відмовлено.', + 'http-403' => 'Доступ заборонено.', 'http-404' => 'Не знайдено.', 'http-429' => 'Забагато спроб. Спробуйте пізніше.', ], @@ -21,15 +21,15 @@ ], ], 'beatmaps' => [ - 'invalid_mode' => 'Вказано недопустимий режим.', - 'standard_converts_only' => 'Результатів для запитуваного моду немає.', + 'invalid_mode' => 'Вказано недійсний режим.', + 'standard_converts_only' => 'Немає доступних рекордів для цього моду на цій складності.', ], 'checkout' => [ - 'generic' => 'Сталася помилка при обробці замовлення.', + 'generic' => 'При обробці вашого замовлення сталась помилка.', ], 'search' => [ 'default' => 'Не вдалося отримати результати, спробуйте ще раз пізніше.', 'invalid_cursor_exception' => 'Вказано недопустимі параметри курсора.', - 'operation_timeout_exception' => 'Пошук зараз зайнятий більше, ніж зазвичай, спробуйте ще раз пізніше.', + 'operation_timeout_exception' => 'Пошук зараз навантажений більше, ніж зазвичай, спробуйте ще раз пізніше.', ], ]; diff --git a/resources/lang/uk/events.php b/resources/lang/uk/events.php index 3e45b06965b..9575e9afb5e 100644 --- a/resources/lang/uk/events.php +++ b/resources/lang/uk/events.php @@ -11,13 +11,13 @@ 'beatmapset_revive' => ':beatmapset відродилася з вічного сну :user.', 'beatmapset_update' => ':user оновив мапу ":beatmapset"', 'beatmapset_upload' => ':user опублікував мапу ":beatmapset"', - 'empty' => "Цей користувач не робив нічого помітного останнім часом!", + 'empty' => "Цей користувач не робив нічого значного останнім часом!", 'rank' => ':user отримав #:rank місце на мапі :beatmap (:mode)', 'rank_lost' => ':user втратив лідерство на мапі :beatmap (:mode)', 'user_support_again' => ':user вирішив знову підтримати osu! Дякуємо за вашу підтримку!', 'user_support_first' => ':user став osu!прихильником! Дякуємо за вашу підтримку!', 'user_support_gift' => ':user отримав тег osu!прихильника в подарунок!', - 'username_change' => ':previousUsername змінив свій нік на :user!', + 'username_change' => ':previousUsername змінив своє ім\'я на :user!', 'beatmapset_status' => [ 'approved' => 'схвалена', diff --git a/resources/lang/uk/forum.php b/resources/lang/uk/forum.php index aa75bca6773..070612ebc02 100644 --- a/resources/lang/uk/forum.php +++ b/resources/lang/uk/forum.php @@ -229,7 +229,7 @@ 'poll' => [ 'hide_results' => 'Приховати результати опитування.', 'hide_results_info' => 'Вони будуть показані тільки після закінчення опитування.', - 'length' => 'Опитування має тривати', + 'length' => 'Опитування триватиме', 'length_days_suffix' => 'днів', 'length_info' => 'Залиште порожнім для зняття обмеження', 'max_options' => 'Кількість відповідей', @@ -238,7 +238,7 @@ 'options_info' => 'Кожен варіант в новому рядку. Ти можеш ввести до 10 варіантів.', 'title' => 'Питання', 'vote_change' => 'Дозволити повторну відповідь.', - 'vote_change_info' => 'Якщо включено, користувачі зможуть змінити свою відповідь.', + 'vote_change_info' => 'Якщо включено, користувачі зможуть змінити свій голос.', ], ], diff --git a/resources/lang/uk/home.php b/resources/lang/uk/home.php index 4aa243df7c8..bc4168851fb 100644 --- a/resources/lang/uk/home.php +++ b/resources/lang/uk/home.php @@ -58,7 +58,7 @@ 'user' => [ 'login_required' => 'Увійдіть для пошуку користувачів', - 'more' => 'більше :count результатів пошуку серед гравців', + 'more' => ':count більше результатів пошуку серед гравців', 'more_simple' => 'Подивитися інші результати пошуку серед гравців', 'more_hidden' => 'Результати пошуку гравців скорочені до :max гравців. Спробуйте уточнити запит.', 'title' => 'Гравці', @@ -72,7 +72,7 @@ ], 'download' => [ - 'tagline' => "ну ж бо
розпочнемо!", + 'tagline' => "ну ж бо
розпочнімо!", 'action' => 'Завантажити osu!', 'help' => [ @@ -90,7 +90,7 @@ 'macos-fallback' => 'для macOS', 'steps' => [ 'register' => [ - 'title' => 'створіть акаунт', + 'title' => 'створіть обліковий запис', 'description' => 'слідуйте підказкам в самій грі для входу або створення облікового запису', ], 'download' => [ @@ -98,9 +98,9 @@ 'description' => 'натисніть на кнопку вище для завантаження інсталятора гри і запустіть його!', ], 'beatmaps' => [ - 'title' => 'скачайте мапи', + 'title' => 'завантажте мапи', 'description' => [ - '_' => ':browse бібліотеку створених гравцями мап і почніть гру!', + '_' => ':browse простору бібліотеку мап створених гравцями й почніть гру!', 'browse' => 'відкрийте', ], ], @@ -112,7 +112,7 @@ 'title' => 'головна', 'news' => [ 'title' => 'Новини', - 'error' => 'Не вдалося завантажити останні новини. Ви можете спробуйте перезавантажити сторінку?...', + 'error' => 'Не вдалося завантажити останні новини. Може спробуєте перезавантажити сторінку?...', ], 'header' => [ 'stats' => [ @@ -122,8 +122,8 @@ ], ], 'beatmaps' => [ - 'new' => 'Останні рангові карти', - 'popular' => 'Популярні карти', + 'new' => 'Останні рангові мапи', + 'popular' => 'Популярні мапи', 'by_user' => 'від :user', ], 'buttons' => [ diff --git a/resources/lang/uk/layout.php b/resources/lang/uk/layout.php index f022ef48042..baf986ea837 100644 --- a/resources/lang/uk/layout.php +++ b/resources/lang/uk/layout.php @@ -75,7 +75,7 @@ ], 'help' => [ '_' => 'допомога', - 'getAbuse' => 'Повідомити про зловживання ', + 'getAbuse' => 'повідомити про порушення', 'getFaq' => 'чапи', 'getRules' => 'правила', 'getSupport' => 'мені, насправді, потрібна допомога!', @@ -103,62 +103,62 @@ ], 'help' => [ '_' => 'Допомога і спільнота', - 'faq' => 'Найчастіші питання', + 'faq' => 'Часто задавані питання', 'forum' => 'Форуми спільноти', 'livestreams' => 'Прямі трансляції', 'report' => 'Повідомити про проблему', 'wiki' => 'Вiкi', ], 'legal' => [ - '_' => 'Права і статус', + '_' => 'Юридичні права і статус', 'copyright' => 'Авторські права (DMCA)', 'privacy' => 'Політика конфіденційності', 'server_status' => 'Статус серверів', - 'source_code' => 'Початковий програмний код', + 'source_code' => 'Вихідний код', 'terms' => 'Умови використання', ], ], 'errors' => [ '400' => [ - 'error' => 'Неправильний параметр запиту', + 'error' => 'Невірний параметр запиту', 'description' => '', ], '404' => [ 'error' => 'Сторінка відсутня', - 'description' => "Вибачте, але запитана сторінка відсутня!", + 'description' => "Вибачте, але запитаної вами сторінки тут немає!", ], '403' => [ 'error' => "Ви не повинні тут бути.", - 'description' => 'Ви можете спробувати повернутися назад, напевно.', + 'description' => 'Хоча, ви можете повернутися, напевне.', ], '401' => [ 'error' => "Ви не повинні тут бути.", - 'description' => 'Ви можете спробувати повернутися назад, напевно. Або може увійти.', + 'description' => 'Хоча ви можете спробувати повернутися, напевне. Або може увійти.', ], '405' => [ 'error' => 'Сторінка відсутня', - 'description' => "Вибачте, але запитана сторінка відсутня!", + 'description' => "Вибачте, але запитаної вами сторінки тут немає!", ], '422' => [ 'error' => 'Неправильний параметр запиту', 'description' => '', ], '429' => [ - 'error' => 'Перевищений ліміт запитів', + 'error' => 'Ліміт запитів перевищено', 'description' => '', ], '500' => [ - 'error' => 'Ох, горе! Щось зламалося! ;_;', - 'description' => "Про помилку буде сповіщено.", + 'error' => 'О ні... Щось зламалося! ;_;', + 'description' => "Ми автоматично сповіщені про кожну помилку.", ], 'fatal' => [ - 'error' => 'Ох, горе! Щось жахливо зламалося! ;_;', - 'description' => "Про помилку буде сповіщено.", + 'error' => 'О ні... Щось зламалося (жахливо)! ;_;', + 'description' => "Ми автоматично сповіщені про кожну помилку.", ], '503' => [ 'error' => 'Закрито на технічне обслуговування!', - 'description' => "Технічне обслуговування зазвичай займає від 5 секунд до 10 хвилин. Якщо воно затягується, перейдіть :link для отримання додаткової інформації.", + 'description' => "Технічне обслуговування зазвичай займає від 5 секунд до 10 хвилин. Якщо це затягується, відкрийте :link для отримання більш детальної інформації.", 'link' => [ 'text' => '', 'href' => '', @@ -172,21 +172,21 @@ 'button' => 'увійти / зареєструватись', 'login' => [ - 'forgot' => "Я все забув", + 'forgot' => "Я забув свої дані", 'password' => 'пароль', 'title' => 'Увійдіть, щоб продовжити', 'username' => 'ім\'я користувача', 'error' => [ - 'email' => "Ім'я користувача або електронна адреса невірна", - 'password' => 'Хибний пароль', + 'email' => "Ім'я користувача або електронна адреса не існують", + 'password' => 'Неправильний пароль', ], ], 'register' => [ 'download' => 'Завантажити', 'info' => 'Завантажте osu! щоб створити свій обліковий запис!', - 'title' => "Не маєте акаунту?", + 'title' => "Не маєте облікового запису?", ], ], @@ -202,6 +202,6 @@ 'popup_search' => [ 'initial' => 'Введіть текст для пошуку!', - 'retry' => 'Невдалий пошук. Натисніть щоб повторити.', + 'retry' => 'Пошук не вдався. Натисніть для повторної спроби.', ], ]; diff --git a/resources/lang/uk/page_title.php b/resources/lang/uk/page_title.php index 81ab1442a51..3fb8acabb23 100644 --- a/resources/lang/uk/page_title.php +++ b/resources/lang/uk/page_title.php @@ -15,7 +15,7 @@ ], 'error' => [ 'error' => [ - '400' => 'неправильний запит', + '400' => 'невірний запит', '404' => 'не знайдено', '403' => 'доступ заборонено', '401' => 'ви не авторизовані', @@ -57,7 +57,7 @@ '_' => 'збірки карт', ], 'beatmapset_discussion_votes_controller' => [ - '_' => 'голоса в обговоренні бтікарти', + '_' => 'голоса в обговоренні бітмапи', ], 'beatmapset_events_controller' => [ '_' => 'історія бітмапи', diff --git a/resources/lang/uk/scores.php b/resources/lang/uk/scores.php index 7048f1a4b82..def2945470a 100644 --- a/resources/lang/uk/scores.php +++ b/resources/lang/uk/scores.php @@ -23,8 +23,8 @@ ], 'status' => [ - 'non_best' => 'рр нагороджуються лише за особисті найкращі результати ', - 'non_passing' => '', - 'processing' => 'Ця гра все ще обчислюється і незабаром з\'явиться', + 'non_best' => 'Лише персональні рекорди приносять pp', + 'non_passing' => 'Лише перевірені рекорди приносять pp', + 'processing' => 'Цей рекорд все ще обчислюється й незабаром буде відображений', ], ]; diff --git a/resources/lang/uk/users.php b/resources/lang/uk/users.php index 21fd3034e29..7b200d0c550 100644 --- a/resources/lang/uk/users.php +++ b/resources/lang/uk/users.php @@ -7,7 +7,7 @@ 'deleted' => '[видалений користувач]', 'beatmapset_activities' => [ - 'title' => "Історія редагування карт користувача :user", + 'title' => "Історія редагування мап користувача :user", 'title_compact' => 'Модифікація', 'discussions' => [ @@ -53,22 +53,22 @@ ], 'disabled' => [ - 'title' => 'О-о! Схоже, що ваш обліковий запис був відключений.', - 'warning' => "Врахуйте, у випадку порушення вами правил, то як мінімум місяць ви не будете мати змоги оскаржити блокування, під час цього періоду ваші спроби будуть проігноровані. Після закінчення одного місяця ви можете зв'язатися з нами, якщо вважаєте це обов'язковим. Також знайте, що створення нових облікових записів для уникнення блокування лише подовжать місячний період ігнорування в який ви не зможете відновити обліковий запис. До того, створення нових вторинних облікових записів заборонено правилами, тому дуже радимо вам - не йдіть по цьому шляху!", + 'title' => 'О-о! Схоже, що ваш обліковий запис було відключено.', + 'warning' => "У випадку порушення правил, врахуйте те, що існує період \"кулл-дауну\" в один місяць й під час якого ми не прийматимемо будь-які запити на амністію вашого облікового запису. Після цього періоду, ви спокійно можете зв'язатися з нами якщо ви вважаете це за потрібне. Зверніть увагу що створення нових облікових записів після відключення одного з них - призведе до подовження періоду \"кулл-дауну\" й надалі. Зверніть увагу також на те, що з кожним створеним обілковим записом який ви створите, ви все більше будете порушником правил, тому ми закликаємо вас - не йдіть цим шляхом!", 'if_mistake' => [ - '_' => 'Якщо вам здається, що це помилка, ми можете зв\'язатися з нами (через :email або після натискання на "?" у правому нижньому кутку цієї сторінки). Зверніть увагу, що ми завжди впевнені у своїх діях, тому, що вони базуються на дуже надійних даних. Ми залишаємо за собою право відмови ваших запитів, якщо ми відчуємо що ви навмисно не є чесними з нами.', + '_' => 'Якщо вам здається, що це помилка, у ваших ж інтересах зв\'язатися з нами (через :email або після натискання на "?" у правому нижньому кутку цієї сторінки). Також зверніть увагу, що ми повністю впевнені у своїх діях, тому що вони базуються на дуже надійних даних. Ми залишаємо за собою право у відмові ваших запитів, якщо ми відчуємо, що ви поводитесь навмисне безчесно.', 'email' => 'ел. пошті', ], 'reasons' => [ - 'compromised' => 'Ваш обліковий запис був визнаний зламаним. Він може бути тимчасово відключений, поки особистість власника підтверджується.', - 'opening' => 'Є ряд причин, які можуть призвести до відключення вашого облікового запису:', + 'compromised' => 'Ваш обліковий запис міг бути скомпрометований. Його може бути відключено тимчасово поки особистість власника підтверджується.', + 'opening' => 'Є ряд причин, які в результаті могли призвести до відключення вашого облікового запису:', 'tos' => [ '_' => 'Ви порушили один або кілька наших :community_rules або :tos.', 'community_rules' => 'правил спільноти', - 'tos' => 'умови використання', + 'tos' => 'умов використання', ], ], ], @@ -87,7 +87,7 @@ '_' => 'Вхід', 'button' => 'Вхід', 'button_posting' => 'Входимо...', - 'email_login_disabled' => 'Вхід через електронну пошту відключений. Будь ласка, використовуйте ім\'я користувача.', + 'email_login_disabled' => 'На даний час вхід з допомогою електронної пошти відключено. Будь ласка, використовуйте ім\'я користувача.', 'failed' => 'Не вдалося ввійти', 'forgot' => 'Забули пароль?', 'info' => 'Увійдіть, щоб продовжити', @@ -100,7 +100,7 @@ 'username' => 'Ім\'я користувача', 'beta' => [ - 'main' => 'Доступ до бета-версії обмежений.', + 'main' => 'На даний час доступ до бета-версії обмежена привілейованими користувачами.', 'small' => '(osu!прихильники отримають доступ пізніше)', ], ], @@ -357,8 +357,8 @@ ], 'account_standing' => [ 'title' => 'Статус акаунту', - 'bad_standing' => "акаунт :username не в хорошому стані :(", - 'remaining_silence' => 'користувачу :username можна буде спілкуватись через :duration.', + 'bad_standing' => "обліковий запис :username знаходиться не в хорошому стані :(", + 'remaining_silence' => ':username зможе знову спілкуватися лише через :duration.', 'recent_infringements' => [ 'title' => 'Недавні порушення', @@ -382,27 +382,27 @@ 'info' => [ 'discord' => '', 'interests' => 'Інтереси', - 'location' => 'Поточне місцезнаходження', + 'location' => 'Поточне розташування', 'occupation' => 'Рід занять', 'twitter' => '', 'website' => 'Сайт', ], 'not_found' => [ - 'reason_1' => 'Вони могли змінити свої псевдоніми.', + 'reason_1' => 'Вони могли змінити свої ніки.', 'reason_2' => 'Обліковий запис може бути тимчасово недоступним через скарги або проблеми з безпекою.', 'reason_3' => 'Можливо, ви зробили помилку!', 'reason_header' => 'Є кілька можливих причин:', - 'title' => 'Користувач не знайдений або не існує ;_;', + 'title' => 'Користувача не знайдено або його не існує ;_;', ], 'page' => [ 'button' => 'Редагувати профіль', - 'description' => 'про мене! є настроюваною областю профілю.', + 'description' => 'про мене! є персонально змінюваним розділом вашого профілю.', 'edit_big' => 'Редагуйте мене!', 'placeholder' => 'Введіть вміст сторінки', 'restriction_info' => [ - '_' => 'Для використання цієї функції потрібен :link.', - 'link' => 'тег osu!supporter', + '_' => 'Щоб використовувати цю функцію, потрібен :link.', + 'link' => 'тег osu!прихильник', ], ], 'post_count' => [ @@ -416,7 +416,7 @@ 'global_simple' => 'Рейтинг в світі', ], 'stats' => [ - 'hit_accuracy' => 'Точність попадань', + 'hit_accuracy' => 'Точність', 'level' => 'Рівень :level', 'level_progress' => 'Прогрес до наступного рівня', 'maximum_combo' => 'Максимальне комбо', @@ -424,20 +424,20 @@ 'play_count' => 'Кількість ігор', 'play_time' => 'Загальний час у грі', 'ranked_score' => 'Рейтингові очки', - 'replays_watched_by_others' => 'Повтори переглянуті іншими', + 'replays_watched_by_others' => 'Переглянутих повторів іншими', 'score_ranks' => 'Рейтинг по очках', 'total_hits' => 'Всього попадань', 'total_score' => 'Всього очків', // modding stats - 'graveyard_beatmapset_count' => 'Закинуті мапи', + 'graveyard_beatmapset_count' => 'Покинуті мапи', 'loved_beatmapset_count' => 'Улюблені мапи', 'pending_beatmapset_count' => 'Мапи на розгляді', - 'ranked_beatmapset_count' => 'Рейтингові та схвалені мапи', + 'ranked_beatmapset_count' => 'Рейтингові й схвалені мапи', ], ], 'silenced_banner' => [ - 'title' => 'Наразі ви заглушені. ', + 'title' => 'Наразі вас заглушено.', 'message' => 'Деякі дії можуть бути недоступними.', ], @@ -447,10 +447,10 @@ 'offline' => 'Не в мережі', ], 'store' => [ - 'saved' => 'Користувач створений', + 'saved' => 'Зареєстрований', ], 'verify' => [ - 'title' => 'Підтвердження акаунта', + 'title' => 'Підтвердження облікового запису', ], 'view_mode' => [ diff --git a/resources/lang/vi/contest.php b/resources/lang/vi/contest.php index 60019f13d60..b8e1dc48de5 100644 --- a/resources/lang/vi/contest.php +++ b/resources/lang/vi/contest.php @@ -34,7 +34,7 @@ 'requirement' => [ 'playlist_beatmapsets' => [ - 'incomplete_play' => '', + 'incomplete_play' => 'Phải chơi hết tất cả beatmap trong playlist cụ thể trước khi bình chọn', ], ], ], diff --git a/resources/lang/vi/forum.php b/resources/lang/vi/forum.php index b7d968275e7..4aaf029d491 100644 --- a/resources/lang/vi/forum.php +++ b/resources/lang/vi/forum.php @@ -163,14 +163,14 @@ 'move' => '', 'pin' => 'Chủ đề được ghim', 'post_edited' => 'Bài viết đã được chỉnh sửa', - 'restore_post' => '', - 'restore_topic' => '', + 'restore_post' => 'Khôi phục bài viết', + 'restore_topic' => 'Khôi phục chủ đề', 'split_destination' => '', - 'split_source' => '', - 'topic_type' => '', - 'topic_type_changed' => '', + 'split_source' => 'Tách bài đăng', + 'topic_type' => 'Đặt loại chủ đề', + 'topic_type_changed' => 'Đổi loại chủ đề', 'unlock' => '', - 'unpin' => '', + 'unpin' => 'Bỏ ghim chủ đề', 'user_lock' => '', 'user_unlock' => '', ], diff --git a/resources/lang/vi/multiplayer.php b/resources/lang/vi/multiplayer.php index 01bc5fc6879..0d42c0c0d1c 100644 --- a/resources/lang/vi/multiplayer.php +++ b/resources/lang/vi/multiplayer.php @@ -5,7 +5,7 @@ return [ 'empty' => [ - '_' => '', + '_' => 'Không có game :type_group osu!(lazer) đã chơi!', 'playlists' => 'danh sách phát', 'realtime' => 'nhiều người chơi', ], diff --git a/resources/lang/vi/rankings.php b/resources/lang/vi/rankings.php index dbfe2414e7a..d4cc14e4b1c 100644 --- a/resources/lang/vi/rankings.php +++ b/resources/lang/vi/rankings.php @@ -13,7 +13,7 @@ 'title' => 'Hiển thị', 'variant' => [ - 'title' => '', + 'title' => 'Biến thể', ], ], diff --git a/resources/lang/zh-tw/scores.php b/resources/lang/zh-tw/scores.php index a3dd7ccbd31..3bc6e20987e 100644 --- a/resources/lang/zh-tw/scores.php +++ b/resources/lang/zh-tw/scores.php @@ -24,7 +24,7 @@ 'status' => [ 'non_best' => 'pp 只授予個人最佳成績', - 'non_passing' => '', + 'non_passing' => '僅有過關的成績能獲取 pp', 'processing' => '成績仍在結算中,不久後就會顯示', ], ]; diff --git a/resources/lang/zh/contest.php b/resources/lang/zh/contest.php index 11f3a7adc09..687d35a7a70 100644 --- a/resources/lang/zh/contest.php +++ b/resources/lang/zh/contest.php @@ -34,7 +34,7 @@ 'requirement' => [ 'playlist_beatmapsets' => [ - 'incomplete_play' => '必须完成指定课题中的所有谱面后才能投票', + 'incomplete_play' => '必须完成指定歌单中的所有谱面后才能投票', ], ], ], diff --git a/resources/lang/zh/layout.php b/resources/lang/zh/layout.php index 41136a01938..18fe095eb93 100644 --- a/resources/lang/zh/layout.php +++ b/resources/lang/zh/layout.php @@ -51,7 +51,7 @@ 'users' => [ 'modding' => '摸图', - 'playlists' => '课题', + 'playlists' => '歌单', 'realtime' => '多人游戏', 'show' => '信息', ], diff --git a/resources/lang/zh/multiplayer.php b/resources/lang/zh/multiplayer.php index afecd90f902..601cd40c675 100644 --- a/resources/lang/zh/multiplayer.php +++ b/resources/lang/zh/multiplayer.php @@ -6,7 +6,7 @@ return [ 'empty' => [ '_' => '还没有玩过 osu!(lazer) 的:type_group游戏!', - 'playlists' => '课题', + 'playlists' => '歌单', 'realtime' => '多人', ], diff --git a/resources/lang/zh/scores.php b/resources/lang/zh/scores.php index 5c9b9bb1260..2a7bd69fb56 100644 --- a/resources/lang/zh/scores.php +++ b/resources/lang/zh/scores.php @@ -24,7 +24,7 @@ 'status' => [ 'non_best' => '只有个人最好成绩才能获取到 pp', - 'non_passing' => '', + 'non_passing' => '只能在通过的成绩上获取 pp', 'processing' => '此分数仍在计算中,即将显示', ], ]; diff --git a/resources/lang/zh/users.php b/resources/lang/zh/users.php index 9da3bbc0147..f7df510f4f3 100644 --- a/resources/lang/zh/users.php +++ b/resources/lang/zh/users.php @@ -312,7 +312,7 @@ 'title' => '成就', ], 'playlists' => [ - 'title' => '课题模式游戏', + 'title' => '歌单游戏', ], 'posts' => [ 'title' => '回复', From 370869998b4b2457e754e473fc094febec8af10b Mon Sep 17 00:00:00 2001 From: bakaneko Date: Fri, 21 Oct 2022 19:52:19 +0900 Subject: [PATCH 075/127] define variables --- app/Console/Commands/UserRecalculateRankCounts.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/Console/Commands/UserRecalculateRankCounts.php b/app/Console/Commands/UserRecalculateRankCounts.php index f04d6159f22..9411d6e2e14 100644 --- a/app/Console/Commands/UserRecalculateRankCounts.php +++ b/app/Console/Commands/UserRecalculateRankCounts.php @@ -13,6 +13,9 @@ class UserRecalculateRankCounts extends Command { + private ?int $from; + private ?int $until; + /** * The name and signature of the console command. * @@ -34,8 +37,8 @@ class UserRecalculateRankCounts extends Command */ public function handle() { - $this->from = $this->option('from'); - $this->until = $this->option('until'); + $this->from = get_int($this->option('from')); + $this->until = get_int($this->option('until')); $continue = $this->confirm('This will recalculate and update the rank counts for user statistics, continue?'); From 50221bcc896f898b360198d92e8da98552a57a6c Mon Sep 17 00:00:00 2001 From: bakaneko Date: Fri, 21 Oct 2022 19:56:10 +0900 Subject: [PATCH 076/127] define varialbe + types --- app/Libraries/CurrentStats.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/Libraries/CurrentStats.php b/app/Libraries/CurrentStats.php index 20bf4409208..c3b163601cc 100644 --- a/app/Libraries/CurrentStats.php +++ b/app/Libraries/CurrentStats.php @@ -12,10 +12,11 @@ class CurrentStats { - public $currentOnline; - public $currentGames; - public $graphData; - public $totalUsers; + public int $currentOnline; + public int $currentGames; + public array $graphData; + public int $onlineFriends; + public int $totalUsers; public function __construct() { From 9b3acbe16f59f687abad1613c053843fa6aa8165 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Fri, 21 Oct 2022 19:57:42 +0900 Subject: [PATCH 077/127] define instance variable --- app/Events/Fulfillments/PaymentEvent.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Events/Fulfillments/PaymentEvent.php b/app/Events/Fulfillments/PaymentEvent.php index edb310697e5..facbc660109 100644 --- a/app/Events/Fulfillments/PaymentEvent.php +++ b/app/Events/Fulfillments/PaymentEvent.php @@ -9,7 +9,7 @@ class PaymentEvent implements HasOrder { - public function __construct(Order $order) + public function __construct(private Order $order) { $this->order = $order; } From 1884e67582fa7fcffce2eec3d9e6d8b26db82a3c Mon Sep 17 00:00:00 2001 From: bakaneko Date: Fri, 21 Oct 2022 20:02:48 +0900 Subject: [PATCH 078/127] define instance variables; nullable because not set in all paths and avoid uninitialized access --- app/Http/Controllers/UsersController.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/Http/Controllers/UsersController.php b/app/Http/Controllers/UsersController.php index a2447419f10..79d773c8b9d 100644 --- a/app/Http/Controllers/UsersController.php +++ b/app/Http/Controllers/UsersController.php @@ -62,6 +62,11 @@ class UsersController extends Controller protected $maxResults = 100; + private ?string $mode = null; + private ?int $offset = null; + private ?int $perPage = null; + private ?User $user = null; + public function __construct() { $this->middleware('guest', ['only' => 'store']); From a86a0cf4d40f418b985a7e9202ad5725c3f1e9a8 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Fri, 21 Oct 2022 20:05:01 +0900 Subject: [PATCH 079/127] define $options --- app/Libraries/BBCodeFromDB.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/Libraries/BBCodeFromDB.php b/app/Libraries/BBCodeFromDB.php index 22848da62be..f6265a73b2b 100644 --- a/app/Libraries/BBCodeFromDB.php +++ b/app/Libraries/BBCodeFromDB.php @@ -18,6 +18,8 @@ class BBCodeFromDB public $refId; public $withGallery; + private array $options; + public function __construct($text, $uid = '', $options = []) { $defaultOptions = [ From c31a427a07536c3ad6d5e91489f62569e54c50fc Mon Sep 17 00:00:00 2001 From: bakaneko Date: Fri, 21 Oct 2022 20:09:59 +0900 Subject: [PATCH 080/127] define queryString. --- app/Libraries/Elasticsearch/SearchParams.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/Libraries/Elasticsearch/SearchParams.php b/app/Libraries/Elasticsearch/SearchParams.php index c2a76db386b..91828791aa6 100644 --- a/app/Libraries/Elasticsearch/SearchParams.php +++ b/app/Libraries/Elasticsearch/SearchParams.php @@ -10,6 +10,10 @@ abstract class SearchParams /** @var int */ public $from = 0; + public ?string $queryString = null; + + // FIXME: some of the assignments to these variables have have the wrong type. + /** @var int */ public $size = 50; From 4a12c862c6e6eed10aa189548aabc106d5a14e33 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Fri, 21 Oct 2022 20:20:57 +0900 Subject: [PATCH 081/127] define $endpoint --- app/Libraries/ImageProcessorService.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/Libraries/ImageProcessorService.php b/app/Libraries/ImageProcessorService.php index d468191a2a1..846c22a7ba3 100644 --- a/app/Libraries/ImageProcessorService.php +++ b/app/Libraries/ImageProcessorService.php @@ -10,7 +10,9 @@ class ImageProcessorService { - public function __construct($endpoint = null) + private string $endpoint; + + public function __construct(?string $endpoint = null) { $this->endpoint = $endpoint ?? config('osu.beatmap_processor.thumbnailer'); } From 9adc885d5340a7b546de3c25649ae579e234e381 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Fri, 21 Oct 2022 20:22:52 +0900 Subject: [PATCH 082/127] define + type variables; use constructor assignment --- app/Libraries/NewForumTopic.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/app/Libraries/NewForumTopic.php b/app/Libraries/NewForumTopic.php index 9612c396b53..fb5d8e6b26f 100644 --- a/app/Libraries/NewForumTopic.php +++ b/app/Libraries/NewForumTopic.php @@ -5,17 +5,15 @@ namespace App\Libraries; +use App\Models\Forum\Forum; use App\Models\Forum\Post; +use App\Models\User; use Carbon\Carbon; class NewForumTopic { - private $forum; - - public function __construct($forum, $user) + public function __construct(private Forum $forum, private ?User $user) { - $this->forum = $forum; - $this->user = $user; } public function cover() From e551e3dd67e31eea8bc8b947e2ba3c6a246ace3e Mon Sep 17 00:00:00 2001 From: bakaneko Date: Fri, 21 Oct 2022 20:24:31 +0900 Subject: [PATCH 083/127] define as constructor property --- app/Libraries/Payments/CentiliSignature.php | 3 +-- app/Libraries/Payments/PaypalSignature.php | 3 +-- app/Libraries/Payments/XsollaSignature.php | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/app/Libraries/Payments/CentiliSignature.php b/app/Libraries/Payments/CentiliSignature.php index 072187bd191..40fe36bad83 100644 --- a/app/Libraries/Payments/CentiliSignature.php +++ b/app/Libraries/Payments/CentiliSignature.php @@ -9,9 +9,8 @@ class CentiliSignature implements PaymentSignature { - public function __construct(Request $request) + public function __construct(private Request $request) { - $this->request = $request; } public function isValid() diff --git a/app/Libraries/Payments/PaypalSignature.php b/app/Libraries/Payments/PaypalSignature.php index 38379c5b971..ce58d547fd6 100644 --- a/app/Libraries/Payments/PaypalSignature.php +++ b/app/Libraries/Payments/PaypalSignature.php @@ -12,9 +12,8 @@ class PaypalSignature implements PaymentSignature { const VERIFIED_RESPONSE = 'VERIFIED'; - public function __construct(Request $request) + public function __construct(private Request $request) { - $this->request = $request; } public function isValid() diff --git a/app/Libraries/Payments/XsollaSignature.php b/app/Libraries/Payments/XsollaSignature.php index 3a0558640e6..7d85a2e77d8 100644 --- a/app/Libraries/Payments/XsollaSignature.php +++ b/app/Libraries/Payments/XsollaSignature.php @@ -9,9 +9,8 @@ class XsollaSignature implements PaymentSignature { - public function __construct(Request $request) + public function __construct(private Request $request) { - $this->request = $request; } public function isValid() From 723c4d307730e5494a3463e70a2f95f5e4e1688f Mon Sep 17 00:00:00 2001 From: bakaneko Date: Fri, 21 Oct 2022 20:30:07 +0900 Subject: [PATCH 084/127] declare as constructor properties --- app/Libraries/Fulfillments/GenericFulfillment.php | 2 +- app/Libraries/ValidationErrors.php | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/app/Libraries/Fulfillments/GenericFulfillment.php b/app/Libraries/Fulfillments/GenericFulfillment.php index 5c68324f049..9c67b43ccfa 100644 --- a/app/Libraries/Fulfillments/GenericFulfillment.php +++ b/app/Libraries/Fulfillments/GenericFulfillment.php @@ -33,6 +33,6 @@ public function revoke() public function validationErrorsTranslationPrefix() { - // noop + return ''; } } diff --git a/app/Libraries/ValidationErrors.php b/app/Libraries/ValidationErrors.php index 180f4e33b33..ac04f2e9f05 100644 --- a/app/Libraries/ValidationErrors.php +++ b/app/Libraries/ValidationErrors.php @@ -11,10 +11,8 @@ class ValidationErrors { private $errors = []; - public function __construct($prefix, $keyBase = 'model_validation.') + public function __construct(private string $prefix, private string $keyBase = 'model_validation.') { - $this->prefix = $prefix; - $this->keyBase = $keyBase; } public function add($column, $rawMessage, $params = null): self From 9fd4cf360fa8686fee88d85e8dd23b099cc71b01 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Fri, 21 Oct 2022 20:31:20 +0900 Subject: [PATCH 085/127] also declare as constructor properties --- app/Mail/UserNotificationDigest.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/Mail/UserNotificationDigest.php b/app/Mail/UserNotificationDigest.php index df2f1b8e67a..af0a9d862a2 100644 --- a/app/Mail/UserNotificationDigest.php +++ b/app/Mail/UserNotificationDigest.php @@ -16,17 +16,14 @@ class UserNotificationDigest extends Mailable { private $groups = []; - private $notifications; /** * Create a new message instance. * * @return void */ - public function __construct(array $notifications, User $user) + public function __construct(private array $notifications, private User $user) { - $this->user = $user; - $this->notifications = $notifications; } private function addToGroups(Notification $notification) From 73e548d7ac29c82108ee234967415dc63172aa21 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Fri, 21 Oct 2022 20:36:26 +0900 Subject: [PATCH 086/127] declare instance variables (parse failure causes type to remain uninitialized) --- app/Models/Event.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/Models/Event.php b/app/Models/Event.php index 5a5657912ed..189b2cb9374 100644 --- a/app/Models/Event.php +++ b/app/Models/Event.php @@ -24,7 +24,9 @@ */ class Event extends Model { + public ?array $details = null; public $parsed = false; + public ?string $type = null; public $patterns = [ 'achievement' => "!^(?:)+(?.+?)(?:)+ unlocked the \"(?.+?)\" achievement\!$!", From 5aa3789a3d05416f8d8eca03e99137974ed37f44 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Fri, 21 Oct 2022 20:40:33 +0900 Subject: [PATCH 087/127] declare as params array --- app/Models/Forum/TopicVote.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/Models/Forum/TopicVote.php b/app/Models/Forum/TopicVote.php index 4243ca70dff..3bfff0b1d16 100644 --- a/app/Models/Forum/TopicVote.php +++ b/app/Models/Forum/TopicVote.php @@ -13,6 +13,7 @@ class TopicVote { use Validatable; + private array $params = []; private $topic; private $validated = false; From 46a83606fd31c91aa069f99f6bc76b91867a302f Mon Sep 17 00:00:00 2001 From: "Hugo \"ThePooN\" Denizart" Date: Fri, 21 Oct 2022 13:54:31 +0200 Subject: [PATCH 088/127] =?UTF-8?q?=F0=9F=94=A7=20Add=20Docker=20builds=20?= =?UTF-8?q?on=20private-staging=20branch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/pack.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pack.yml b/.github/workflows/pack.yml index 746b4110b43..063c27f44b8 100644 --- a/.github/workflows/pack.yml +++ b/.github/workflows/pack.yml @@ -4,6 +4,7 @@ on: push: branches: - master + - private-staging tags: - '*' @@ -85,7 +86,7 @@ jobs: version: osu-web@${{ github.ref_name }} push_to_staging: - if: ${{ github.ref_type == 'branch' }} + if: ${{ github.ref_type == 'branch' && github.ref_name == 'master' }} runs-on: ubuntu-latest needs: - push_to_registry From a0666f437e494fcd30d4866d3b4021541f091916 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Fri, 21 Oct 2022 21:08:57 +0900 Subject: [PATCH 089/127] but queryString defined here for some reason :thinking: --- app/Libraries/Search/ArtistTrackSearchParams.php | 1 - app/Libraries/Search/BeatmapsetSearchParams.php | 1 - app/Libraries/Search/ForumSearchParams.php | 3 --- app/Libraries/Search/UserSearchParams.php | 1 - app/Libraries/Search/WikiSearchParams.php | 3 --- app/Libraries/Search/WikiSuggestionsParams.php | 3 --- 6 files changed, 12 deletions(-) diff --git a/app/Libraries/Search/ArtistTrackSearchParams.php b/app/Libraries/Search/ArtistTrackSearchParams.php index d7e69c7cb76..d48db2e73da 100644 --- a/app/Libraries/Search/ArtistTrackSearchParams.php +++ b/app/Libraries/Search/ArtistTrackSearchParams.php @@ -30,7 +30,6 @@ class ArtistTrackSearchParams extends SearchParams public ?string $genre; public bool $isDefaultSort = false; public ?array $length; - public ?string $queryString; public string $sortField; public string $sortOrder; diff --git a/app/Libraries/Search/BeatmapsetSearchParams.php b/app/Libraries/Search/BeatmapsetSearchParams.php index cd954e23c5d..46b6c84ab4a 100644 --- a/app/Libraries/Search/BeatmapsetSearchParams.php +++ b/app/Libraries/Search/BeatmapsetSearchParams.php @@ -32,7 +32,6 @@ class BeatmapsetSearchParams extends SearchParams public ?int $language = null; public ?int $mode = null; public ?string $playedFilter = null; // null means any state - public ?string $queryString = null; public array $rank = []; public ?array $ranked = null; public bool $showFeaturedArtists = false; diff --git a/app/Libraries/Search/ForumSearchParams.php b/app/Libraries/Search/ForumSearchParams.php index f43fb0573cb..b5b89055cc6 100644 --- a/app/Libraries/Search/ForumSearchParams.php +++ b/app/Libraries/Search/ForumSearchParams.php @@ -22,9 +22,6 @@ class ForumSearchParams extends SearchParams /** @var bool */ public $includeSubforums = false; - /** @var string|null */ - public $queryString = null; - /** {@inheritdoc} */ public $size = 20; diff --git a/app/Libraries/Search/UserSearchParams.php b/app/Libraries/Search/UserSearchParams.php index afa13c77141..7246d70c5bb 100644 --- a/app/Libraries/Search/UserSearchParams.php +++ b/app/Libraries/Search/UserSearchParams.php @@ -14,7 +14,6 @@ class UserSearchParams extends SearchParams // all public because lazy. - public $queryString = null; public $recentOnly = false; public $sortField = 'relevance'; diff --git a/app/Libraries/Search/WikiSearchParams.php b/app/Libraries/Search/WikiSearchParams.php index 8d73cc07e1b..3f6248b7591 100644 --- a/app/Libraries/Search/WikiSearchParams.php +++ b/app/Libraries/Search/WikiSearchParams.php @@ -11,9 +11,6 @@ class WikiSearchParams extends SearchParams { // all public because lazy. - /** @var string|null */ - public $queryString = null; - /** @var string|null */ public $locale = null; diff --git a/app/Libraries/Search/WikiSuggestionsParams.php b/app/Libraries/Search/WikiSuggestionsParams.php index 192a8d2a8c8..61908d27b80 100644 --- a/app/Libraries/Search/WikiSuggestionsParams.php +++ b/app/Libraries/Search/WikiSuggestionsParams.php @@ -9,9 +9,6 @@ class WikiSuggestionsParams extends SearchParams { - /** @var string|null */ - public $queryString = null; - public $size = 10; /** From e889160a9c36091366e6a3b51cc7a92a8fcd650c Mon Sep 17 00:00:00 2001 From: bakaneko Date: Fri, 21 Oct 2022 22:30:38 +0900 Subject: [PATCH 090/127] ...apparently this is public --- app/Events/Fulfillments/PaymentEvent.php | 2 +- app/Listeners/Fulfillments/PaymentSubscribers.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/Events/Fulfillments/PaymentEvent.php b/app/Events/Fulfillments/PaymentEvent.php index facbc660109..6c59955c6ae 100644 --- a/app/Events/Fulfillments/PaymentEvent.php +++ b/app/Events/Fulfillments/PaymentEvent.php @@ -9,7 +9,7 @@ class PaymentEvent implements HasOrder { - public function __construct(private Order $order) + public function __construct(public Order $order) { $this->order = $order; } diff --git a/app/Listeners/Fulfillments/PaymentSubscribers.php b/app/Listeners/Fulfillments/PaymentSubscribers.php index 05e2f0f7ed8..26e1b0d7a77 100644 --- a/app/Listeners/Fulfillments/PaymentSubscribers.php +++ b/app/Listeners/Fulfillments/PaymentSubscribers.php @@ -26,6 +26,7 @@ class PaymentSubscribers public function onPaymentCompleted($eventName, $data) { + /** @var \App\Events\Fulfillments\PaymentEvent $event */ $event = $data[0] ?? null; $fulfillers = FulfillmentFactory::createFulfillersFor($event->order); $count = count($fulfillers); From b2bdd7cd0043f68e2fdfcf03d22e7b3c9eb353c1 Mon Sep 17 00:00:00 2001 From: nanaya Date: Fri, 21 Oct 2022 22:13:42 +0900 Subject: [PATCH 091/127] Simplify query for checking personal best score --- app/Models/Score/Best/Model.php | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/app/Models/Score/Best/Model.php b/app/Models/Score/Best/Model.php index 9b3b74ee1a0..995f654497b 100644 --- a/app/Models/Score/Best/Model.php +++ b/app/Models/Score/Best/Model.php @@ -307,18 +307,14 @@ public function scopeIncludeFails($query, bool $include) public function isPersonalBest(): bool { - return !static + return $this->getKey() === (static ::where([ 'user_id' => $this->user_id, 'beatmap_id' => $this->beatmap_id, - ])->where(function ($q) { - return $q - ->where('score', '>', $this->score) - ->orWhere(function ($qq) { - return $qq->where('score', $this->score) - ->where($this->getKeyName(), '<', $this->getKey()); - }); - })->exists(); + ])->default() + ->limit(1) + ->pluck('score_id') + ->first() ?? $this->getKey()); } public function replayViewCount() From 21842eb47725a58b40586f57c150641e864328dd Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 24 Oct 2022 15:08:47 +0900 Subject: [PATCH 092/127] Add default build id option --- .env.example | 1 + app/Http/Controllers/Solo/ScoreTokensController.php | 2 +- config/osu.php | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.env.example b/.env.example index c6ae3ee062a..dfd8cfbd9d7 100644 --- a/.env.example +++ b/.env.example @@ -153,6 +153,7 @@ OSU_RUNNING_COST= CLIENT_CHECK_VERSION=false # CLIENT_USER_AGENT=osu! +# DEFAULT_BUILD_ID= # SEARCH_MINIMUM_LENGTH=2 diff --git a/app/Http/Controllers/Solo/ScoreTokensController.php b/app/Http/Controllers/Solo/ScoreTokensController.php index c3d20035d1c..c2ff47846a3 100644 --- a/app/Http/Controllers/Solo/ScoreTokensController.php +++ b/app/Http/Controllers/Solo/ScoreTokensController.php @@ -47,7 +47,7 @@ public function store($beatmapId) try { $scoreToken = ScoreToken::create([ 'beatmap_id' => $beatmap->getKey(), - 'build_id' => $build?->getKey(), + 'build_id' => $build?->getKey() ?? config('osu.client.default_build_id'), 'ruleset_id' => $params['ruleset_id'], 'user_id' => $user->getKey(), ]); diff --git a/config/osu.php b/config/osu.php index 0545b1b0d45..d1adf0e9807 100644 --- a/config/osu.php +++ b/config/osu.php @@ -92,6 +92,7 @@ ], 'client' => [ 'check_version' => get_bool(env('CLIENT_CHECK_VERSION')) ?? true, + 'default_build_id' => get_int(env('DEFAULT_BUILD_ID')), 'user_agent' => env('CLIENT_USER_AGENT', 'osu!'), ], 'elasticsearch' => [ From 87bf686f9bf5d1c06a620d1ef0bc3ba168fb033d Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 24 Oct 2022 15:20:14 +0900 Subject: [PATCH 093/127] Don't refocus if already editing --- resources/assets/lib/beatmap-discussions/new-reply.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/resources/assets/lib/beatmap-discussions/new-reply.tsx b/resources/assets/lib/beatmap-discussions/new-reply.tsx index a395e85224b..9cfbccdd94b 100644 --- a/resources/assets/lib/beatmap-discussions/new-reply.tsx +++ b/resources/assets/lib/beatmap-discussions/new-reply.tsx @@ -46,6 +46,7 @@ export class NewReply extends React.Component { @observable private message = this.storedMessage; @observable private posting: string | null = null; private postXhr: JQuery.jqXHR | null = null; + private startEditing = false; private get canReopen() { return this.props.discussion.can_be_resolved && this.props.discussion.current_user_attributes.can_reopen; @@ -84,7 +85,8 @@ export class NewReply extends React.Component { return; } - if (this.editing) { + if (this.startEditing) { + this.startEditing = false; this.box.current?.focus(); } @@ -103,6 +105,7 @@ export class NewReply extends React.Component { private readonly editStart = () => { if (core.userLogin.showIfGuest(this.editStart)) return; this.editing = true; + this.startEditing = true; }; @action From 0babe3b804f3a5189c281753c1c6b691caaac17e Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 24 Oct 2022 15:22:55 +0900 Subject: [PATCH 094/127] Add missing action decorator --- resources/assets/lib/beatmap-discussions/new-reply.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/assets/lib/beatmap-discussions/new-reply.tsx b/resources/assets/lib/beatmap-discussions/new-reply.tsx index 9cfbccdd94b..cfd90701217 100644 --- a/resources/assets/lib/beatmap-discussions/new-reply.tsx +++ b/resources/assets/lib/beatmap-discussions/new-reply.tsx @@ -79,6 +79,7 @@ export class NewReply extends React.Component { this.handleKeyDown = makeTextAreaHandler(this.handleKeyDownCallback); } + @action componentDidUpdate(prevProps: Readonly) { if (prevProps.discussion.id !== this.props.discussion.id) { this.message = this.storedMessage; From 1fbe792842409b4ff567ea910a7dbbdfc345de2e Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 24 Oct 2022 15:31:06 +0900 Subject: [PATCH 095/127] Update stored message on message update --- .../lib/beatmap-discussions/new-reply.tsx | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/resources/assets/lib/beatmap-discussions/new-reply.tsx b/resources/assets/lib/beatmap-discussions/new-reply.tsx index cfd90701217..584ae5d4f9e 100644 --- a/resources/assets/lib/beatmap-discussions/new-reply.tsx +++ b/resources/assets/lib/beatmap-discussions/new-reply.tsx @@ -90,8 +90,6 @@ export class NewReply extends React.Component { this.startEditing = false; this.box.current?.focus(); } - - this.storeMessage(); } componentWillUnmount() { @@ -109,6 +107,10 @@ export class NewReply extends React.Component { this.startEditing = true; }; + private readonly handleChange = (e: React.ChangeEvent) => { + this.setMessage(e.target.value); + }; + @action private readonly handleKeyDownCallback: TextAreaCallback = (type, event) => { switch (type) { @@ -126,7 +128,7 @@ export class NewReply extends React.Component { if (osu.present(this.message) && !confirm(osu.trans('common.confirmation_unsaved'))) return; this.editing = false; - this.message = ''; + this.setMessage(''); }; @action @@ -156,7 +158,7 @@ export class NewReply extends React.Component { this.postXhr .done((json) => runInAction(() => { this.editing = false; - this.message = ''; + this.setMessage(''); $.publish('beatmapDiscussionPost:markRead', { id: json.beatmap_discussion_post_ids }); $.publish('beatmapsetDiscussions:update', { beatmapset: json.beatmapset }); })) @@ -181,7 +183,7 @@ export class NewReply extends React.Component { ref={this.box} className={`${bn}__message ${bn}__message--editor`} disabled={this.posting != null} - onChange={this.setMessage} + onChange={this.handleChange} onKeyDown={this.handleKeyDown} placeholder={osu.trans('beatmaps.discussions.reply_placeholder')} value={this.message} @@ -257,9 +259,10 @@ export class NewReply extends React.Component { } @action - private readonly setMessage = (e: React.ChangeEvent) => { - this.message = e.target.value; - }; + private setMessage(message: string) { + this.message = message; + this.storeMessage(); + } private storeMessage() { if (!osu.present(this.message)) { From 688700d762c57b533d2669dc7e478355ec5d4741 Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 24 Oct 2022 15:54:38 +0900 Subject: [PATCH 096/127] Enforce maximum js lint warnings Otherwise it'll just keep increasing. --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 325e4666234..6502919dd8c 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -48,7 +48,7 @@ jobs: - name: Install js dependencies run: yarn --frozen-lockfile - - run: yarn lint --quiet + - run: yarn lint --quiet --max-warnings 204 - run: ./bin/update_licence.sh -nf From adb178248f05674d23603999268ecd753a3cf806 Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 24 Oct 2022 15:56:17 +0900 Subject: [PATCH 097/127] Apparently quiet option suppresses max-warnings --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 6502919dd8c..62dac0a915e 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -48,7 +48,7 @@ jobs: - name: Install js dependencies run: yarn --frozen-lockfile - - run: yarn lint --quiet --max-warnings 204 + - run: yarn lint --max-warnings 204 - run: ./bin/update_licence.sh -nf From f517f33c6eb845709df4b639f1b9dc763f7349b3 Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 24 Oct 2022 16:33:22 +0900 Subject: [PATCH 098/127] Nothing else calls storeMessage --- resources/assets/lib/beatmap-discussions/new-reply.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/resources/assets/lib/beatmap-discussions/new-reply.tsx b/resources/assets/lib/beatmap-discussions/new-reply.tsx index 584ae5d4f9e..a267737c9a3 100644 --- a/resources/assets/lib/beatmap-discussions/new-reply.tsx +++ b/resources/assets/lib/beatmap-discussions/new-reply.tsx @@ -261,10 +261,7 @@ export class NewReply extends React.Component { @action private setMessage(message: string) { this.message = message; - this.storeMessage(); - } - private storeMessage() { if (!osu.present(this.message)) { localStorage.removeItem(this.storageKey); } else { From 616a853c14a0c98d4784ebd9c7c327525a7123c9 Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 24 Oct 2022 18:41:50 +0900 Subject: [PATCH 099/127] Show correct error message on invalid supporter amount --- app/Models/SupporterTag.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/Models/SupporterTag.php b/app/Models/SupporterTag.php index 25923dfcbad..5b6063a4a14 100644 --- a/app/Models/SupporterTag.php +++ b/app/Models/SupporterTag.php @@ -5,6 +5,8 @@ namespace App\Models; +use App\Exceptions\InvariantException; + class SupporterTag { const MIN_DONATION = 4; @@ -23,7 +25,7 @@ public static function getDuration(int $amount) { if ($amount < self::MIN_DONATION) { $minDonation = self::MIN_DONATION; // can't interpolate const :D - throw new \Exception("amount must be >= {$minDonation}"); + throw new InvariantException("amount must be >= {$minDonation}"); } switch (true) { From 4477413ac1dfad14d92dc17f2bc2e3f51499a970 Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 24 Oct 2022 18:52:26 +0900 Subject: [PATCH 100/127] Add max supporter tag Mainly to avoid int overflow error. --- app/Models/SupporterTag.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/app/Models/SupporterTag.php b/app/Models/SupporterTag.php index 5b6063a4a14..39a3b7fdb78 100644 --- a/app/Models/SupporterTag.php +++ b/app/Models/SupporterTag.php @@ -9,6 +9,7 @@ class SupporterTag { + const MAX_DONATION = 1 << 16; // 65k-ish const MIN_DONATION = 4; const PRODUCT_CUSTOM_CLASS = 'supporter-tag'; @@ -23,9 +24,12 @@ class SupporterTag **/ public static function getDuration(int $amount) { - if ($amount < self::MIN_DONATION) { - $minDonation = self::MIN_DONATION; // can't interpolate const :D - throw new InvariantException("amount must be >= {$minDonation}"); + if ($amount < static::MIN_DONATION) { + throw new InvariantException('amount must be >= '.static::MIN_DONATION); + } + + if ($amount > static::MAX_DONATION) { + throw new InvariantException('amount must be <= '.static::MAX_DONATION); } switch (true) { From 3d2bd4cd43494a47bbbd6fba1c6793929433047b Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 24 Oct 2022 18:54:42 +0900 Subject: [PATCH 101/127] Update function signature --- app/Models/SupporterTag.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Models/SupporterTag.php b/app/Models/SupporterTag.php index 39a3b7fdb78..3f18eee5c35 100644 --- a/app/Models/SupporterTag.php +++ b/app/Models/SupporterTag.php @@ -20,9 +20,9 @@ class SupporterTag * * @param int $amount Amount to get the duration for. * @return int duration in months. - * @throws Exception + * @throws App\Exceptions\InvariantException **/ - public static function getDuration(int $amount) + public static function getDuration(int $amount): int { if ($amount < static::MIN_DONATION) { throw new InvariantException('amount must be >= '.static::MIN_DONATION); From 81f269ac8222caf7352489f10a4c26accff6a8ff Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 24 Oct 2022 19:21:59 +0900 Subject: [PATCH 102/127] Fix github path parsing - check if update to wiki is relevant - explicit null return - check if parsed return anything --- app/Jobs/UpdateWiki.php | 24 ++++++++++++------------ app/Libraries/OsuWiki.php | 33 +++++++++++++++++---------------- 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/app/Jobs/UpdateWiki.php b/app/Jobs/UpdateWiki.php index f5cd46a6e1b..d24914426ee 100644 --- a/app/Jobs/UpdateWiki.php +++ b/app/Jobs/UpdateWiki.php @@ -57,21 +57,21 @@ public function handle() } } - /** - * @return WikiObject|null - */ - private function getObject($path) + private function getObject(string $path): ?WikiObject { $parsed = OsuWiki::parseGithubPath($path); - if ($parsed['type'] === 'page') { - return Page::lookup($parsed['path'], $parsed['locale']); - } elseif ($parsed['type'] === 'image') { - return new Image($parsed['path']); - } elseif ($parsed['type'] === 'redirect') { - return new WikiRedirect(); - } elseif ($parsed['type'] === 'news_post') { - return NewsPost::lookup($parsed['slug']); + switch ($parsed['type'] ?? null) { + case 'page': + return Page::lookup($parsed['path'], $parsed['locale']); + case 'image': + return new Image($parsed['path']); + case 'redirect': + return new WikiRedirect(); + case 'news_post': + return NewsPost::lookup($parsed['slug']); + default: + return null; } } } diff --git a/app/Libraries/OsuWiki.php b/app/Libraries/OsuWiki.php index 375ebb47da3..59bbd47851a 100644 --- a/app/Libraries/OsuWiki.php +++ b/app/Libraries/OsuWiki.php @@ -67,11 +67,8 @@ public static function fetchContent($path) /** * Parses a github repository path of a wiki file, * and returns informations such as type, wiki path and locale. - * - * @param string $path - * @return array[] */ - public static function parseGithubPath($path) + public static function parseGithubPath(string $path): ?array { $matches = []; @@ -80,19 +77,21 @@ public static function parseGithubPath($path) return ['type' => 'redirect']; } - preg_match('/^(?:wiki\/)(.*)\/(.*)\.(.{2,})$/', $path, $matches); + $found = preg_match('/^(?:wiki\/)(.*)\/(.*)\.(.{2,})$/', $path, $matches); - if (static::isImage($path)) { - return [ - 'type' => 'image', - 'path' => $matches[1].'/'.$matches[2].'.'.$matches[3], - ]; - } else { - return [ - 'type' => 'page', - 'locale' => $matches[2], - 'path' => $matches[1], - ]; + if ($found > 0) { + if (static::isImage($path)) { + return [ + 'type' => 'image', + 'path' => $matches[1].'/'.$matches[2].'.'.$matches[3], + ]; + } else { + return [ + 'type' => 'page', + 'locale' => $matches[2], + 'path' => $matches[1], + ]; + } } } elseif (starts_with($path, 'news/')) { $found = preg_match('/^(?:news\/)(?:\d{4}\/)?(.*)\.md$/', $path, $matches); @@ -104,6 +103,8 @@ public static function parseGithubPath($path) ]; } } + + return null; } public static function updateFromGithub($data) From 40331de6d1697301e69087fe498ed784393e22ec Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 24 Oct 2022 19:41:10 +0900 Subject: [PATCH 103/127] Explicit empty string because switch is weird --- app/Jobs/UpdateWiki.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Jobs/UpdateWiki.php b/app/Jobs/UpdateWiki.php index d24914426ee..1a9dcdab927 100644 --- a/app/Jobs/UpdateWiki.php +++ b/app/Jobs/UpdateWiki.php @@ -61,7 +61,7 @@ private function getObject(string $path): ?WikiObject { $parsed = OsuWiki::parseGithubPath($path); - switch ($parsed['type'] ?? null) { + switch ($parsed['type'] ?? '') { case 'page': return Page::lookup($parsed['path'], $parsed['locale']); case 'image': From f12982084dbe11a45bc5264ad71358205cd344fc Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 24 Oct 2022 20:16:29 +0900 Subject: [PATCH 104/127] Fix error on duplicated score pinning --- app/Http/Controllers/ScorePinsController.php | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/app/Http/Controllers/ScorePinsController.php b/app/Http/Controllers/ScorePinsController.php index 61682cc3c68..20474ffe353 100644 --- a/app/Http/Controllers/ScorePinsController.php +++ b/app/Http/Controllers/ScorePinsController.php @@ -9,6 +9,7 @@ use App\Libraries\MorphMap; use App\Models\Beatmap; use App\Models\ScorePin; +use Exception; class ScorePinsController extends Controller { @@ -89,10 +90,16 @@ public function store() $rulesetId = Beatmap::MODES[$score->getMode()]; $currentMinDisplayOrder = $user->scorePins()->where('ruleset_id', $rulesetId)->min('display_order') ?? 2500; - (new ScorePin(['display_order' => $currentMinDisplayOrder - 100, 'ruleset_id' => $rulesetId])) - ->user()->associate($user) - ->score()->associate($score) - ->saveOrExplode(); + try { + (new ScorePin(['display_order' => $currentMinDisplayOrder - 100, 'ruleset_id' => $rulesetId])) + ->user()->associate($user) + ->score()->associate($score) + ->saveOrExplode(); + } catch (Exception $ex) { + if (!is_sql_unique_exception($ex)) { + throw $ex; + } + } } return response()->noContent(); From f164a165b1f5a6283b01e411c92972e4a0a1724c Mon Sep 17 00:00:00 2001 From: bakaneko Date: Mon, 24 Oct 2022 17:14:19 +0900 Subject: [PATCH 105/127] don't return parent::__construct() --- app/Http/Controllers/Account/SessionsController.php | 2 +- app/Http/Controllers/AccountController.php | 2 +- app/Http/Controllers/Admin/Controller.php | 2 +- app/Http/Controllers/BeatmapDiscussionPostsController.php | 2 +- app/Http/Controllers/BeatmapDiscussionsController.php | 2 +- app/Http/Controllers/BeatmapsetDiscussionVotesController.php | 2 +- app/Http/Controllers/BeatmapsetEventsController.php | 2 +- app/Http/Controllers/BlocksController.php | 2 +- app/Http/Controllers/Chat/ChannelsController.php | 2 +- app/Http/Controllers/Chat/ChatController.php | 2 +- app/Http/Controllers/Chat/Controller.php | 2 +- app/Http/Controllers/ChatController.php | 2 +- app/Http/Controllers/ClientVerificationsController.php | 2 +- app/Http/Controllers/Forum/PostsController.php | 2 +- app/Http/Controllers/FriendsController.php | 2 +- app/Http/Controllers/HomeController.php | 2 +- app/Http/Controllers/Payments/PaypalController.php | 2 +- app/Http/Controllers/Payments/XsollaController.php | 2 +- app/Http/Controllers/ScorePinsController.php | 2 +- app/Http/Controllers/SessionsController.php | 2 +- app/Http/Controllers/Store/CartController.php | 2 +- app/Http/Controllers/Store/CheckoutController.php | 2 +- app/Http/Controllers/Store/NotificationRequestsController.php | 2 +- app/Http/Controllers/StoreController.php | 2 +- app/Http/Controllers/UsersController.php | 2 +- app/Models/UserStatistics/Model.php | 2 +- app/Models/UserStatistics/Spotlight/Model.php | 2 +- 27 files changed, 27 insertions(+), 27 deletions(-) diff --git a/app/Http/Controllers/Account/SessionsController.php b/app/Http/Controllers/Account/SessionsController.php index 3c0520eccec..2ec6f550e00 100644 --- a/app/Http/Controllers/Account/SessionsController.php +++ b/app/Http/Controllers/Account/SessionsController.php @@ -16,7 +16,7 @@ public function __construct() $this->middleware('auth'); $this->middleware('verify-user'); - return parent::__construct(); + parent::__construct(); } public function destroy($id) diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index 61e53357ba5..81db3f8ccc9 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -59,7 +59,7 @@ public function __construct() 'verifyLink', ]]); - return parent::__construct(); + parent::__construct(); } public function avatar() diff --git a/app/Http/Controllers/Admin/Controller.php b/app/Http/Controllers/Admin/Controller.php index ee3edb14e9f..d96487f9a4a 100644 --- a/app/Http/Controllers/Admin/Controller.php +++ b/app/Http/Controllers/Admin/Controller.php @@ -22,6 +22,6 @@ public function __construct() return $next($request); }); - return parent::__construct(); + parent::__construct(); } } diff --git a/app/Http/Controllers/BeatmapDiscussionPostsController.php b/app/Http/Controllers/BeatmapDiscussionPostsController.php index 3cdc7987c5c..776fdef7b9f 100644 --- a/app/Http/Controllers/BeatmapDiscussionPostsController.php +++ b/app/Http/Controllers/BeatmapDiscussionPostsController.php @@ -26,7 +26,7 @@ public function __construct() $this->middleware('auth', ['except' => ['index', 'show']]); $this->middleware('require-scopes:public', ['only' => ['index']]); - return parent::__construct(); + parent::__construct(); } public function destroy($id) diff --git a/app/Http/Controllers/BeatmapDiscussionsController.php b/app/Http/Controllers/BeatmapDiscussionsController.php index 9b60c83ba7d..dbebdb993fb 100644 --- a/app/Http/Controllers/BeatmapDiscussionsController.php +++ b/app/Http/Controllers/BeatmapDiscussionsController.php @@ -23,7 +23,7 @@ public function __construct() $this->middleware('auth', ['except' => ['index', 'show']]); $this->middleware('require-scopes:public', ['only' => ['index']]); - return parent::__construct(); + parent::__construct(); } public function allowKudosu($id) diff --git a/app/Http/Controllers/BeatmapsetDiscussionVotesController.php b/app/Http/Controllers/BeatmapsetDiscussionVotesController.php index e60c8718d56..8f3748a2769 100644 --- a/app/Http/Controllers/BeatmapsetDiscussionVotesController.php +++ b/app/Http/Controllers/BeatmapsetDiscussionVotesController.php @@ -16,7 +16,7 @@ public function __construct() { $this->middleware('require-scopes:public'); - return parent::__construct(); + parent::__construct(); } /** diff --git a/app/Http/Controllers/BeatmapsetEventsController.php b/app/Http/Controllers/BeatmapsetEventsController.php index cfee8375544..d672b45e4e9 100644 --- a/app/Http/Controllers/BeatmapsetEventsController.php +++ b/app/Http/Controllers/BeatmapsetEventsController.php @@ -13,7 +13,7 @@ public function __construct() { $this->middleware('require-scopes:public', ['only' => ['index']]); - return parent::__construct(); + parent::__construct(); } public function index() diff --git a/app/Http/Controllers/BlocksController.php b/app/Http/Controllers/BlocksController.php index dbc369ff88c..63be3a4ef38 100644 --- a/app/Http/Controllers/BlocksController.php +++ b/app/Http/Controllers/BlocksController.php @@ -24,7 +24,7 @@ public function __construct() ], ]); - return parent::__construct(); + parent::__construct(); } public function store() diff --git a/app/Http/Controllers/Chat/ChannelsController.php b/app/Http/Controllers/Chat/ChannelsController.php index 0514a6b4591..5f8a0713c7c 100644 --- a/app/Http/Controllers/Chat/ChannelsController.php +++ b/app/Http/Controllers/Chat/ChannelsController.php @@ -22,7 +22,7 @@ public function __construct() { $this->middleware('require-scopes:chat.write', ['only' => 'store']); - return parent::__construct(); + parent::__construct(); } /** diff --git a/app/Http/Controllers/Chat/ChatController.php b/app/Http/Controllers/Chat/ChatController.php index 345b493fafd..7a82c6c1d0d 100644 --- a/app/Http/Controllers/Chat/ChatController.php +++ b/app/Http/Controllers/Chat/ChatController.php @@ -25,7 +25,7 @@ public function __construct() $this->middleware('require-scopes:chat.write', ['only' => 'newConversation']); $this->middleware('auth'); - return parent::__construct(); + parent::__construct(); } public function ack() diff --git a/app/Http/Controllers/Chat/Controller.php b/app/Http/Controllers/Chat/Controller.php index 668d6a14812..f4bed95503b 100644 --- a/app/Http/Controllers/Chat/Controller.php +++ b/app/Http/Controllers/Chat/Controller.php @@ -13,6 +13,6 @@ public function __construct() { $this->middleware('auth'); - return parent::__construct(); + parent::__construct(); } } diff --git a/app/Http/Controllers/ChatController.php b/app/Http/Controllers/ChatController.php index 8399f6f9a0e..2487992f2f4 100644 --- a/app/Http/Controllers/ChatController.php +++ b/app/Http/Controllers/ChatController.php @@ -23,7 +23,7 @@ public function __construct() $this->middleware('verify-user'); } - return parent::__construct(); + parent::__construct(); } public function index() diff --git a/app/Http/Controllers/ClientVerificationsController.php b/app/Http/Controllers/ClientVerificationsController.php index cefe4c4b40a..9f44e697ff1 100644 --- a/app/Http/Controllers/ClientVerificationsController.php +++ b/app/Http/Controllers/ClientVerificationsController.php @@ -15,7 +15,7 @@ public function __construct() $this->middleware('verify-user'); $this->middleware('throttle:60,10'); - return parent::__construct(); + parent::__construct(); } public function create() diff --git a/app/Http/Controllers/Forum/PostsController.php b/app/Http/Controllers/Forum/PostsController.php index 0e68394d666..6d0f2299932 100644 --- a/app/Http/Controllers/Forum/PostsController.php +++ b/app/Http/Controllers/Forum/PostsController.php @@ -25,7 +25,7 @@ public function __construct() $this->middleware('require-scopes:forum.write', ['only' => ['update']]); - return parent::__construct(); + parent::__construct(); } public function destroy($id) diff --git a/app/Http/Controllers/FriendsController.php b/app/Http/Controllers/FriendsController.php index 5a6b0e32aae..f15dcabe57f 100644 --- a/app/Http/Controllers/FriendsController.php +++ b/app/Http/Controllers/FriendsController.php @@ -26,7 +26,7 @@ public function __construct() $this->middleware('require-scopes:friends.read', ['only' => ['index']]); - return parent::__construct(); + parent::__construct(); } public function index() diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index a71cfff2dc7..4257aa4911c 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -30,7 +30,7 @@ public function __construct() $this->middleware('require-scopes:public', ['only' => 'search']); - return parent::__construct(); + parent::__construct(); } public function bbcodePreview() diff --git a/app/Http/Controllers/Payments/PaypalController.php b/app/Http/Controllers/Payments/PaypalController.php index 97c99b89234..372556d7878 100644 --- a/app/Http/Controllers/Payments/PaypalController.php +++ b/app/Http/Controllers/Payments/PaypalController.php @@ -31,7 +31,7 @@ public function __construct() $this->middleware('check-user-restricted', ['except' => ['ipn']]); $this->middleware('verify-user', ['except' => ['ipn']]); - return parent::__construct(); + parent::__construct(); } // When user has approved a payment at Paypal and is redirected back here. diff --git a/app/Http/Controllers/Payments/XsollaController.php b/app/Http/Controllers/Payments/XsollaController.php index 687d0d17980..493053456eb 100644 --- a/app/Http/Controllers/Payments/XsollaController.php +++ b/app/Http/Controllers/Payments/XsollaController.php @@ -28,7 +28,7 @@ public function __construct() $this->middleware('check-user-restricted', ['except' => ['callback']]); $this->middleware('verify-user', ['except' => ['callback']]); - return parent::__construct(); + parent::__construct(); } public function token() diff --git a/app/Http/Controllers/ScorePinsController.php b/app/Http/Controllers/ScorePinsController.php index 61682cc3c68..b1f3026cd64 100644 --- a/app/Http/Controllers/ScorePinsController.php +++ b/app/Http/Controllers/ScorePinsController.php @@ -16,7 +16,7 @@ public function __construct() { $this->middleware('auth'); - return parent::__construct(); + parent::__construct(); } public function destroy() diff --git a/app/Http/Controllers/SessionsController.php b/app/Http/Controllers/SessionsController.php index 8925ed296ab..1d797f6c6c4 100644 --- a/app/Http/Controllers/SessionsController.php +++ b/app/Http/Controllers/SessionsController.php @@ -20,7 +20,7 @@ public function __construct() 'store', ]]); - return parent::__construct(); + parent::__construct(); } public function store() diff --git a/app/Http/Controllers/Store/CartController.php b/app/Http/Controllers/Store/CartController.php index 8cb76fb095b..ffeaa8c387e 100644 --- a/app/Http/Controllers/Store/CartController.php +++ b/app/Http/Controllers/Store/CartController.php @@ -23,7 +23,7 @@ public function __construct() ]]); } - return parent::__construct(); + parent::__construct(); } public function show() diff --git a/app/Http/Controllers/Store/CheckoutController.php b/app/Http/Controllers/Store/CheckoutController.php index e74547f97a1..7e82dcb9fdf 100644 --- a/app/Http/Controllers/Store/CheckoutController.php +++ b/app/Http/Controllers/Store/CheckoutController.php @@ -27,7 +27,7 @@ public function __construct() } $this->middleware('verify-user'); - return parent::__construct(); + parent::__construct(); } public function show($id) diff --git a/app/Http/Controllers/Store/NotificationRequestsController.php b/app/Http/Controllers/Store/NotificationRequestsController.php index 0c774f2705d..301f74e6f21 100644 --- a/app/Http/Controllers/Store/NotificationRequestsController.php +++ b/app/Http/Controllers/Store/NotificationRequestsController.php @@ -18,7 +18,7 @@ public function __construct() $this->middleware('check-user-restricted'); } - return parent::__construct(); + parent::__construct(); } public function store($productId) diff --git a/app/Http/Controllers/StoreController.php b/app/Http/Controllers/StoreController.php index 90978a34548..f11dcdcf377 100644 --- a/app/Http/Controllers/StoreController.php +++ b/app/Http/Controllers/StoreController.php @@ -37,7 +37,7 @@ public function __construct() 'postUpdateAddress', ]]); - return parent::__construct(); + parent::__construct(); } public function getListing() diff --git a/app/Http/Controllers/UsersController.php b/app/Http/Controllers/UsersController.php index a2447419f10..6c5db6f02a8 100644 --- a/app/Http/Controllers/UsersController.php +++ b/app/Http/Controllers/UsersController.php @@ -94,7 +94,7 @@ public function __construct() 'only' => ['extraPages', 'scores', 'beatmapsets', 'kudosu', 'recentActivity'], ]); - return parent::__construct(); + parent::__construct(); } public function card($id) diff --git a/app/Models/UserStatistics/Model.php b/app/Models/UserStatistics/Model.php index 2a2c55e72c4..97b4a2216f6 100644 --- a/app/Models/UserStatistics/Model.php +++ b/app/Models/UserStatistics/Model.php @@ -151,7 +151,7 @@ public function __construct($attributes = [], $zeroInsteadOfNull = true) ], $attributes); } - return parent::__construct($attributes); + parent::__construct($attributes); } public function countryRank() diff --git a/app/Models/UserStatistics/Spotlight/Model.php b/app/Models/UserStatistics/Spotlight/Model.php index 137ee8cab19..695a9b2747b 100644 --- a/app/Models/UserStatistics/Spotlight/Model.php +++ b/app/Models/UserStatistics/Spotlight/Model.php @@ -34,6 +34,6 @@ public function __construct($attributes = [], $zeroInsteadOfNull = true) $this->a_rank_count = 0; } - return parent::__construct($attributes, false); + parent::__construct($attributes, false); } } From 6c0774cb65e43c9f36542daa41b4273772df3bba Mon Sep 17 00:00:00 2001 From: bakaneko Date: Mon, 24 Oct 2022 22:15:36 +0900 Subject: [PATCH 106/127] already assigned --- app/Events/Fulfillments/PaymentEvent.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/Events/Fulfillments/PaymentEvent.php b/app/Events/Fulfillments/PaymentEvent.php index 6c59955c6ae..46bf756bb3a 100644 --- a/app/Events/Fulfillments/PaymentEvent.php +++ b/app/Events/Fulfillments/PaymentEvent.php @@ -11,7 +11,6 @@ class PaymentEvent implements HasOrder { public function __construct(public Order $order) { - $this->order = $order; } public function getOrder() From 9c23651546bfd4904fb9b3a25537f9ccc3eefa4e Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 24 Oct 2022 22:22:42 +0900 Subject: [PATCH 107/127] Fix updating notification options --- app/Http/Controllers/AccountController.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index 81db3f8ccc9..3f2b3076fdd 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -177,7 +177,13 @@ public function updateNotificationOptions() } DB::transaction(function () use ($requestParams) { - // FIXME: less queries + $user = auth()->user(); + UserNotificationOption + ::lockForUpdate() + ->where('user_id', $user->getKey()) + ->whereIn('name', array_keys($requestParams)) + ->select('user_id') + ->get(); foreach ($requestParams as $key => $value) { if (!UserNotificationOption::supportsNotifications($key)) { continue; @@ -185,7 +191,7 @@ public function updateNotificationOptions() $params = get_params($value, null, ['details:any']); - $option = auth()->user()->notificationOptions()->firstOrNew(['name' => $key]); + $option = $user->notificationOptions()->firstOrNew(['name' => $key]); // TODO: show correct field error. $option->fill($params)->saveOrExplode(); } From fa6486ebd6763dd0f9a0963a75aab50bfa5b44e0 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Mon, 24 Oct 2022 22:37:20 +0900 Subject: [PATCH 108/127] standardize add/sub time calls on Carbon --- app/Http/Controllers/BeatmapsetsController.php | 2 +- app/Libraries/OsuAuthorize.php | 2 +- app/Models/Artist.php | 2 +- app/Models/ArtistAlbum.php | 2 +- app/Models/ArtistTrack.php | 2 +- app/Models/BeatmapDiscussionVote.php | 8 ++++---- app/Models/User.php | 2 +- app/helpers.php | 4 ++-- database/factories/Multiplayer/RoomFactory.php | 6 +++--- database/seeders/ModelSeeders/SpotlightSeeder.php | 2 +- .../Multiplayer/RoomsControllerTest.php | 14 +++++++------- tests/Jobs/UpdateUserForumTopicFollowsTest.php | 2 +- tests/Libraries/ChangeUsernameTest.php | 4 ++-- 13 files changed, 26 insertions(+), 26 deletions(-) diff --git a/app/Http/Controllers/BeatmapsetsController.php b/app/Http/Controllers/BeatmapsetsController.php index 9e1a5e9f80b..8c773409392 100644 --- a/app/Http/Controllers/BeatmapsetsController.php +++ b/app/Http/Controllers/BeatmapsetsController.php @@ -180,7 +180,7 @@ public function download($id) priv_check('BeatmapsetDownload', $beatmapset)->ensureCan(); $recentlyDownloaded = BeatmapDownload::where('user_id', Auth::user()->user_id) - ->where('timestamp', '>', Carbon::now()->subHour()->getTimestamp()) + ->where('timestamp', '>', Carbon::now()->subHours()->getTimestamp()) ->count(); if ($recentlyDownloaded > Auth::user()->beatmapsetDownloadAllowance()) { diff --git a/app/Libraries/OsuAuthorize.php b/app/Libraries/OsuAuthorize.php index c0dc2d55b83..4b9579d15e9 100644 --- a/app/Libraries/OsuAuthorize.php +++ b/app/Libraries/OsuAuthorize.php @@ -384,7 +384,7 @@ public function checkBeatmapDiscussionVote(?User $user, BeatmapDiscussion $discu // rate limit $recentVotesCount = $user ->beatmapDiscussionVotes() - ->where('created_at', '>', Carbon::now()->subHour()) + ->where('created_at', '>', Carbon::now()->subHours()) ->count(); if ($recentVotesCount > 60) { diff --git a/app/Models/Artist.php b/app/Models/Artist.php index d7b9c2215b1..2505f299d84 100644 --- a/app/Models/Artist.php +++ b/app/Models/Artist.php @@ -66,7 +66,7 @@ public function hasNewTracks() { $date = parse_time_to_carbon($this->attributes['tracks_max_created_at']); - return $date !== null && $date->addMonth(1)->isFuture(); + return $date !== null && $date->addMonths(1)->isFuture(); } public function url() diff --git a/app/Models/ArtistAlbum.php b/app/Models/ArtistAlbum.php index 80eab3786a8..093469497a3 100644 --- a/app/Models/ArtistAlbum.php +++ b/app/Models/ArtistAlbum.php @@ -36,6 +36,6 @@ public function tracks() public function isNew() { - return $this->created_at->isAfter(now()->subMonth(1)); + return $this->created_at->isAfter(now()->subMonths(1)); } } diff --git a/app/Models/ArtistTrack.php b/app/Models/ArtistTrack.php index d1e4fee39df..a9bfd8dcf33 100644 --- a/app/Models/ArtistTrack.php +++ b/app/Models/ArtistTrack.php @@ -56,6 +56,6 @@ public function getCoverUrlAttribute($value) public function isNew() { - return $this->created_at->isAfter(now()->subMonth(1)); + return $this->created_at->isAfter(now()->subMonths(1)); } } diff --git a/app/Models/BeatmapDiscussionVote.php b/app/Models/BeatmapDiscussionVote.php index 830d58956cc..0b8dd6fc8ba 100644 --- a/app/Models/BeatmapDiscussionVote.php +++ b/app/Models/BeatmapDiscussionVote.php @@ -23,13 +23,13 @@ class BeatmapDiscussionVote extends Model public static function recentlyReceivedByUser($userId, $timeframeMonths = 3) { - return static::where('beatmap_discussion_votes.created_at', '>', Carbon::now()->subMonth($timeframeMonths)) + return static::where('beatmap_discussion_votes.created_at', '>', Carbon::now()->subMonths($timeframeMonths)) ->join('beatmap_discussions', 'beatmap_discussion_votes.beatmap_discussion_id', 'beatmap_discussions.id') ->select('beatmap_discussion_votes.user_id') ->selectRaw('sum(beatmap_discussion_votes.score) as score') ->selectRaw('count(beatmap_discussion_votes.score) as count') ->where('beatmap_discussions.user_id', $userId) - ->where('beatmap_discussions.updated_at', '>', Carbon::now()->subMonth($timeframeMonths)) + ->where('beatmap_discussions.updated_at', '>', Carbon::now()->subMonths($timeframeMonths)) ->whereHas('user', function ($userQuery) { $userQuery->default(); }) @@ -40,13 +40,13 @@ public static function recentlyReceivedByUser($userId, $timeframeMonths = 3) public static function recentlyGivenByUser($userId, $timeframeMonths = 3) { - return static::where('beatmap_discussion_votes.created_at', '>', Carbon::now()->subMonth($timeframeMonths)) + return static::where('beatmap_discussion_votes.created_at', '>', Carbon::now()->subMonths($timeframeMonths)) ->join('beatmap_discussions', 'beatmap_discussion_votes.beatmap_discussion_id', 'beatmap_discussions.id') ->select('beatmap_discussions.user_id') ->selectRaw('sum(beatmap_discussion_votes.score) as score') ->selectRaw('count(beatmap_discussion_votes.score) as count') ->where('beatmap_discussion_votes.user_id', $userId) - ->where('beatmap_discussions.updated_at', '>', Carbon::now()->subMonth($timeframeMonths)) + ->where('beatmap_discussions.updated_at', '>', Carbon::now()->subMonths($timeframeMonths)) ->whereHas('beatmapDiscussion.user', function ($userQuery) { $userQuery->default(); }) diff --git a/app/Models/User.php b/app/Models/User.php index ff50ffba120..edf2e677753 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -984,7 +984,7 @@ public function isSupporter() public function isActive() { - return $this->user_lastvisit > Carbon::now()->subMonth(); + return $this->user_lastvisit > Carbon::now()->subMonths(); } /* diff --git a/app/helpers.php b/app/helpers.php index fac5afbc69e..9ad114c0553 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -153,7 +153,7 @@ function cache_expire_with_fallback(string $key, int $duration = 2592000) return; } - $data['expires_at'] = now()->addHour(-1); + $data['expires_at'] = now()->addHours(-1); Cache::put($fullKey, $data, $duration); } @@ -1290,7 +1290,7 @@ function json_item($model, $transformer, $includes = null) function fast_imagesize($url) { - $result = Cache::remember("imageSize:{$url}", Carbon\Carbon::now()->addMonth(1), function () use ($url) { + $result = Cache::remember("imageSize:{$url}", Carbon\Carbon::now()->addMonths(1), function () use ($url) { $curl = curl_init($url); curl_setopt_array($curl, [ CURLOPT_HTTPHEADER => [ diff --git a/database/factories/Multiplayer/RoomFactory.php b/database/factories/Multiplayer/RoomFactory.php index a689970fa23..9820be8ab02 100644 --- a/database/factories/Multiplayer/RoomFactory.php +++ b/database/factories/Multiplayer/RoomFactory.php @@ -14,14 +14,14 @@ 'name' => function () use ($faker) { return $faker->realText(20); }, - 'starts_at' => Carbon\Carbon::now()->subHour(1), - 'ends_at' => Carbon\Carbon::now()->addHour(1), + 'starts_at' => Carbon\Carbon::now()->subHours(1), + 'ends_at' => Carbon\Carbon::now()->addHours(1), ]; }); $factory->state(Room::class, 'ended', function (Faker\Generator $faker) { return [ - 'ends_at' => Carbon\Carbon::now()->subMinute(1), + 'ends_at' => Carbon\Carbon::now()->subMinutes(1), ]; }); diff --git a/database/seeders/ModelSeeders/SpotlightSeeder.php b/database/seeders/ModelSeeders/SpotlightSeeder.php index da80341b559..3690bb21555 100644 --- a/database/seeders/ModelSeeders/SpotlightSeeder.php +++ b/database/seeders/ModelSeeders/SpotlightSeeder.php @@ -30,7 +30,7 @@ public function run() $this->seedBestOf($date); } - $date->addMonth(1); + $date->addMonths(1); } collect(range(1, 10))->each(function () { diff --git a/tests/Controllers/Multiplayer/RoomsControllerTest.php b/tests/Controllers/Multiplayer/RoomsControllerTest.php index 9b277490c4d..c77dd381790 100644 --- a/tests/Controllers/Multiplayer/RoomsControllerTest.php +++ b/tests/Controllers/Multiplayer/RoomsControllerTest.php @@ -37,7 +37,7 @@ public function testStore() ->actingWithToken($token) ->post(route('api.rooms.store'), array_merge( $this->createBasicStoreParams(), - ['ends_at' => now()->addHour()], + ['ends_at' => now()->addHours()], ))->assertSuccessful(); $this->assertSame($roomsCountInitial + 1, Room::count()); @@ -55,7 +55,7 @@ public function testStoreWithInvalidPlayableMods(string $type, string $modType): $this->expectCountChange(fn () => PlaylistItem::count(), 0); $params = array_merge($this->createBasicStoreParams(), [ - 'ends_at' => now()->addHour(), + 'ends_at' => now()->addHours(), 'type' => $type, ]); @@ -83,7 +83,7 @@ public function testStoreWithInvalidRealtimeAllowedMods(string $type, bool $ok): $this->expectCountChange(fn () => PlaylistItem::count(), $ok ? 1 : 0); $params = array_merge($this->createBasicStoreParams(), [ - 'ends_at' => now()->addHour(), + 'ends_at' => now()->addHours(), 'type' => $type, ]); $params['playlist'][0]['required_mods'] = []; @@ -111,7 +111,7 @@ public function testStoreWithInvalidRealtimeMods(string $type, bool $ok): void // explicit ruleset required because AS isn't available for all modes $params = array_merge($this->createBasicStoreParams('osu'), [ - 'ends_at' => now()->addHour(), + 'ends_at' => now()->addHours(), 'type' => $type, ]); $params['playlist'][0]['allowed_mods'] = []; @@ -136,7 +136,7 @@ public function testStoreWithPassword() ->post(route('api.rooms.store'), array_merge( $this->createBasicStoreParams(), [ - 'ends_at' => now()->addHour(), + 'ends_at' => now()->addHours(), 'password' => 'hunter2', ], ))->assertSuccessful(); @@ -294,7 +294,7 @@ public function testStorePlaylistsAllowance() ->actingWithToken($token) ->post(route('api.rooms.store'), array_merge( $this->createBasicStoreParams(), - ['ends_at' => now()->addHour()], + ['ends_at' => now()->addHours()], ))->assertStatus(422); $this->assertSame($roomsCountInitial, Room::count()); @@ -314,7 +314,7 @@ public function testStorePlaylistsAllowanceSeparateFromRealtime() ->actingWithToken($token) ->post(route('api.rooms.store'), array_merge( $this->createBasicStoreParams(), - ['ends_at' => now()->addHour()], + ['ends_at' => now()->addHours()], ))->assertSuccessful(); $this->assertSame($roomsCountInitial + 1, Room::count()); diff --git a/tests/Jobs/UpdateUserForumTopicFollowsTest.php b/tests/Jobs/UpdateUserForumTopicFollowsTest.php index 13d576e254d..1f293c12408 100644 --- a/tests/Jobs/UpdateUserForumTopicFollowsTest.php +++ b/tests/Jobs/UpdateUserForumTopicFollowsTest.php @@ -34,7 +34,7 @@ public function testRemoveUserWithNoWatchPermission() $zz = UserNotification::create([ 'notification_id' => $notification->getKey(), 'user_id' => $user->getKey(), - 'created_at' => now()->subHour(1), + 'created_at' => now()->subHours(1), ]); $watchesCount = TopicWatch::count(); diff --git a/tests/Libraries/ChangeUsernameTest.php b/tests/Libraries/ChangeUsernameTest.php index 3e3622ff60c..fd068aa8f32 100644 --- a/tests/Libraries/ChangeUsernameTest.php +++ b/tests/Libraries/ChangeUsernameTest.php @@ -86,7 +86,7 @@ public function testUsernameWithDifferentCasingIsSame() public function testUserHasSupportedButExpired() { - $user = $this->createUser(['osu_subscriptionexpiry' => Carbon::now()->subMonth()]); + $user = $this->createUser(['osu_subscriptionexpiry' => Carbon::now()->subMonths()]); $errors = $user->validateChangeUsername('newusername'); @@ -219,7 +219,7 @@ private function createUser(array $attribs = []): User 'username' => 'iamuser', 'username_clean' => 'iamuser', 'user_lastvisit' => Carbon::now(), - 'osu_subscriptionexpiry' => Carbon::now()->addMonth(), + 'osu_subscriptionexpiry' => Carbon::now()->addMonths(), ], $attribs)); } } From b04d460dd814df67388a72b7560abb0ee413cd5c Mon Sep 17 00:00:00 2001 From: bakaneko Date: Mon, 24 Oct 2022 16:58:21 +0900 Subject: [PATCH 109/127] corect number of params --- app/Http/Controllers/BeatmapsetsController.php | 2 +- app/Libraries/BeatmapsetDiscussionsBundle.php | 2 +- app/Libraries/Elasticsearch/Hit.php | 2 +- app/Libraries/Markdown/StyleBlock/StartParser.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/Http/Controllers/BeatmapsetsController.php b/app/Http/Controllers/BeatmapsetsController.php index 8c773409392..3a57f8bd4dd 100644 --- a/app/Http/Controllers/BeatmapsetsController.php +++ b/app/Http/Controllers/BeatmapsetsController.php @@ -150,7 +150,7 @@ public function discussionUnlock($id) priv_check('BeatmapsetDiscussionLock')->ensureCan(); $beatmapset = Beatmapset::findOrFail($id); - $beatmapset->discussionUnlock(Auth::user(), request('reason')); + $beatmapset->discussionUnlock(Auth::user()); return $beatmapset->defaultDiscussionJson(); } diff --git a/app/Libraries/BeatmapsetDiscussionsBundle.php b/app/Libraries/BeatmapsetDiscussionsBundle.php index 9ba228fa8c3..9663fab31c2 100644 --- a/app/Libraries/BeatmapsetDiscussionsBundle.php +++ b/app/Libraries/BeatmapsetDiscussionsBundle.php @@ -102,7 +102,7 @@ private function getUsers() return $this->memoize(__FUNCTION__, function () { $discussions = $this->getDiscussions(); - $allDiscussions = $discussions->merge($this->getRelatedDiscussions($discussions)); + $allDiscussions = $discussions->merge($this->getRelatedDiscussions()); $userIds = $allDiscussions->pluck('user_id')->merge($allDiscussions->pluck('startingPost.last_editor_id'))->unique()->values(); $users = User::whereIn('user_id', $userIds)->with('userGroups'); diff --git a/app/Libraries/Elasticsearch/Hit.php b/app/Libraries/Elasticsearch/Hit.php index deb06f83495..56324eef39f 100644 --- a/app/Libraries/Elasticsearch/Hit.php +++ b/app/Libraries/Elasticsearch/Hit.php @@ -59,7 +59,7 @@ public function innerHits(string $name) $results = $this->raw['inner_hits'][$name] ?? null; if ($results) { - return new SearchResponse($results, $name); + return new SearchResponse($results); } return SearchResponse::empty(); diff --git a/app/Libraries/Markdown/StyleBlock/StartParser.php b/app/Libraries/Markdown/StyleBlock/StartParser.php index 6f86e3be96b..9aeb6111db4 100644 --- a/app/Libraries/Markdown/StyleBlock/StartParser.php +++ b/app/Libraries/Markdown/StyleBlock/StartParser.php @@ -30,6 +30,6 @@ public function tryStart(Cursor $cursor, MarkdownParserStateInterface $parserSta $cursor->advanceToEnd(); - return BlockStart::of(new Parser($className, $currentLine[0]))->at($cursor); + return BlockStart::of(new Parser($className))->at($cursor); } } From 61ff731638458e06d39ae1afbeba4dc5eafa8a24 Mon Sep 17 00:00:00 2001 From: nanaya Date: Tue, 25 Oct 2022 02:07:23 +0900 Subject: [PATCH 110/127] Move generate localization script to cli directory --- .../assets/lib/cli/generate-localizations.js | 27 ++++++++++++------- webpack.config.js | 3 ++- 2 files changed, 19 insertions(+), 11 deletions(-) rename generate-localizations.js => resources/assets/lib/cli/generate-localizations.js (69%) diff --git a/generate-localizations.js b/resources/assets/lib/cli/generate-localizations.js similarity index 69% rename from generate-localizations.js rename to resources/assets/lib/cli/generate-localizations.js index 50f93bdf375..f04c370d4e3 100644 --- a/generate-localizations.js +++ b/resources/assets/lib/cli/generate-localizations.js @@ -8,7 +8,10 @@ const fs = require('fs'); const path = require('path'); const glob = require('glob'); -const buildPath = path.resolve(__dirname, 'resources/assets/build'); +// project root directory +const root = path.resolve(__dirname, '../../../..'); + +const buildPath = path.resolve(root, 'resources/assets/build'); const localesPath = path.resolve(buildPath, 'locales'); const messagesPath = path.resolve(buildPath, 'messages.json'); @@ -36,7 +39,7 @@ function getAllMesssages() { } function generateTranslations() { - spawnSync('php', ['artisan', 'lang:js', '--json', messagesPath], { stdio: 'inherit' }); + spawnSync('php', [path.resolve(root, 'artisan'), 'lang:js', '--json', messagesPath], { stdio: 'inherit' }); } function writeTranslations(languages) { @@ -52,13 +55,17 @@ function writeTranslations(languages) { } } -// Remove previous existing files and ensure directory exists. -glob.sync(path.resolve(localesPath, '*.js')).forEach(fs.unlinkSync); -fs.mkdirSync(localesPath, {recursive: true}); +function generateLocalizations() { + // Remove previous existing files and ensure directory exists. + glob.sync(path.resolve(localesPath, '*.js')).forEach(fs.unlinkSync); + fs.mkdirSync(localesPath, {recursive: true}); + + generateTranslations(); + writeTranslations(extractLanguages()); -generateTranslations(); -writeTranslations(extractLanguages()); + // cleanup + fs.unlinkSync(messagesPath); + console.log(`Removed: ${messagesPath}`); +} -// cleanup -fs.unlinkSync(messagesPath); -console.log(`Removed: ${messagesPath}`); +module.exports = generateLocalizations; diff --git a/webpack.config.js b/webpack.config.js index 8da54992d3a..ae8c3671a9c 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -4,6 +4,7 @@ const { spawnSync } = require('child_process'); const path = require('path'); const Watchpack = require('watchpack'); +const generateLocalizations = require('./resources/assets/lib/cli/generate-localizations'); const modNamesGenerator = require('./resources/assets/lib/cli/mod-names-generator'); const spawnOptions = { stdio: 'inherit' }; @@ -31,7 +32,7 @@ const watches = [ }, { callback: () => { - spawnSync('yarn', ['generate-localizations'], spawnOptions); + generateLocalizations(); // touching the file on first build might cause karma's watchers to fire after tests start. if (resolved) { spawnSync('touch', [path.resolve(__dirname, 'resources/assets/coffee/main.coffee')], spawnOptions); From ffa344b9364da20b12a1b8d8f17224647ff17cbb Mon Sep 17 00:00:00 2001 From: nanaya Date: Tue, 25 Oct 2022 02:07:55 +0900 Subject: [PATCH 111/127] Disable no-console lint for cli file --- .github/workflows/lint.yml | 2 +- resources/assets/lib/cli/generate-localizations.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 62dac0a915e..662ec192506 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -48,7 +48,7 @@ jobs: - name: Install js dependencies run: yarn --frozen-lockfile - - run: yarn lint --max-warnings 204 + - run: yarn lint --max-warnings 201 - run: ./bin/update_licence.sh -nf diff --git a/resources/assets/lib/cli/generate-localizations.js b/resources/assets/lib/cli/generate-localizations.js index f04c370d4e3..188459f90dc 100644 --- a/resources/assets/lib/cli/generate-localizations.js +++ b/resources/assets/lib/cli/generate-localizations.js @@ -3,6 +3,7 @@ 'use strict'; +/* eslint no-console: "off" */ const { spawnSync } = require('child_process'); const fs = require('fs'); const path = require('path'); From fa1655878e1f4a1d51439bf1f1f6bc8518baf645 Mon Sep 17 00:00:00 2001 From: nanaya Date: Tue, 25 Oct 2022 15:11:31 +0900 Subject: [PATCH 112/127] Remove manual localization generator script --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index e327f839718..ea3d58c79fe 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,6 @@ "scripts": { "dev": "yarn run development", "development": "cross-env NODE_ENV=development webpack --progress --hide-modules --config=webpack.config.js", - "generate-localizations": "node generate-localizations.js", "lint": "eslint --cache 'resources/assets/lib/**/*.{js,ts,tsx}' 'tests/karma/**/*.ts' '*.js'", "localize": "yarn run generate-localizations", "prod": "yarn run production", From d5b057f9c1c426c1a895fa6dad5794c82ec839b4 Mon Sep 17 00:00:00 2001 From: nanaya Date: Tue, 25 Oct 2022 15:12:16 +0900 Subject: [PATCH 113/127] More uniform variable naming --- resources/assets/lib/cli/generate-localizations.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/resources/assets/lib/cli/generate-localizations.js b/resources/assets/lib/cli/generate-localizations.js index 188459f90dc..9d6e7791c98 100644 --- a/resources/assets/lib/cli/generate-localizations.js +++ b/resources/assets/lib/cli/generate-localizations.js @@ -10,9 +10,8 @@ const path = require('path'); const glob = require('glob'); // project root directory -const root = path.resolve(__dirname, '../../../..'); - -const buildPath = path.resolve(root, 'resources/assets/build'); +const rootPath = path.resolve(__dirname, '../../../..'); +const buildPath = path.resolve(rootPath, 'resources/assets/build'); const localesPath = path.resolve(buildPath, 'locales'); const messagesPath = path.resolve(buildPath, 'messages.json'); @@ -40,7 +39,7 @@ function getAllMesssages() { } function generateTranslations() { - spawnSync('php', [path.resolve(root, 'artisan'), 'lang:js', '--json', messagesPath], { stdio: 'inherit' }); + spawnSync('php', [path.resolve(rootPath, 'artisan'), 'lang:js', '--json', messagesPath], { stdio: 'inherit' }); } function writeTranslations(languages) { From aa0833ce8aa33792f68d3618675ba7b6b9bb713f Mon Sep 17 00:00:00 2001 From: bakaneko Date: Tue, 25 Oct 2022 17:04:26 +0900 Subject: [PATCH 114/127] add ack to api --- routes/web.php | 1 + tests/api_routes.json | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/routes/web.php b/routes/web.php index 45eb873cec4..70def786b13 100644 --- a/routes/web.php +++ b/routes/web.php @@ -431,6 +431,7 @@ Route::delete('comments/{comment}/vote', 'CommentsController@voteDestroy'); Route::group(['as' => 'chat.', 'prefix' => 'chat', 'namespace' => 'Chat'], function () { + Route::post('ack', 'ChatController@ack')->name('ack'); Route::post('new', 'ChatController@newConversation')->name('new'); Route::get('updates', 'ChatController@updates')->name('updates'); Route::get('presence', 'ChatController@presence')->name('presence'); diff --git a/tests/api_routes.json b/tests/api_routes.json index c0dbff1e1b7..114675d6c92 100644 --- a/tests/api_routes.json +++ b/tests/api_routes.json @@ -321,6 +321,19 @@ ], "scopes": [] }, + { + "uri": "api/v2/chat/ack", + "methods": [ + "POST" + ], + "controller": "App\\Http\\Controllers\\Chat\\ChatController@ack", + "middlewares": [ + "App\\Http\\Middleware\\ThrottleRequests:1200,1,api:", + "App\\Http\\Middleware\\RequireScopes", + "Illuminate\\Auth\\Middleware\\Authenticate" + ], + "scopes": [] + }, { "uri": "api/v2/chat/new", "methods": [ From ee0385b0085b68aba2021c29d279bf896c92fed7 Mon Sep 17 00:00:00 2001 From: nanaya Date: Tue, 25 Oct 2022 18:05:16 +0900 Subject: [PATCH 115/127] Add default chat ack parameter value --- app/Http/Controllers/Chat/ChatController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/Chat/ChatController.php b/app/Http/Controllers/Chat/ChatController.php index 7a82c6c1d0d..1bb403445e7 100644 --- a/app/Http/Controllers/Chat/ChatController.php +++ b/app/Http/Controllers/Chat/ChatController.php @@ -38,7 +38,7 @@ public function ack() ], ['null_missing' => true]); return [ - 'silences' => json_collection($this->getSilences($params['history_since'], $params['since']), new UserSilenceTransformer()), + 'silences' => json_collection($this->getSilences($params['history_since'], $params['since'] ?? 0), new UserSilenceTransformer()), ]; } From 9befee43b884106f57d64b8a6008ca8320b176dd Mon Sep 17 00:00:00 2001 From: Matheus Filipe dos Santos Reinert Date: Tue, 25 Oct 2022 09:21:45 -0300 Subject: [PATCH 116/127] Add license to top of ContestEntriesControllerTest.php --- tests/Controllers/ContestEntriesControllerTest.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/Controllers/ContestEntriesControllerTest.php b/tests/Controllers/ContestEntriesControllerTest.php index 2b18990d152..52b34a2c254 100644 --- a/tests/Controllers/ContestEntriesControllerTest.php +++ b/tests/Controllers/ContestEntriesControllerTest.php @@ -1,11 +1,13 @@ . Licensed under the GNU Affero General Public License v3.0. +// See the LICENCE file in the repository root for full licence text. + namespace Tests\Controllers; use App\Models\Contest; use App\Models\User; use Carbon\Carbon; -use DateTime; use Illuminate\Http\Testing\File; use Tests\TestCase; From 3727a765363c731524d895fc09f16cbbf7a60323 Mon Sep 17 00:00:00 2001 From: nanaya Date: Tue, 25 Oct 2022 21:45:53 +0900 Subject: [PATCH 117/127] Use named route --- tests/Controllers/ContestEntriesControllerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Controllers/ContestEntriesControllerTest.php b/tests/Controllers/ContestEntriesControllerTest.php index 52b34a2c254..e50aacfe18b 100644 --- a/tests/Controllers/ContestEntriesControllerTest.php +++ b/tests/Controllers/ContestEntriesControllerTest.php @@ -35,7 +35,7 @@ public function testStoreEntryExceedingMaxFileSize() $this ->actingAsVerified($this->user) - ->postJson('/community/contest-entries', ['entry' => $file, 'contest_id' => $this->contest->id]) + ->postJson(route('contest-entries.store'), ['entry' => $file, 'contest_id' => $this->contest->id]) ->assertStatus(413) ->assertJson(['error' => 'File exceeds max size']); } From 570c06d4cbeed07b152e21ea6b150bf21847224e Mon Sep 17 00:00:00 2001 From: nanaya Date: Tue, 25 Oct 2022 21:47:14 +0900 Subject: [PATCH 118/127] Add missing newlines --- resources/assets/lib/contest-entry/uploader.coffee | 2 ++ 1 file changed, 2 insertions(+) diff --git a/resources/assets/lib/contest-entry/uploader.coffee b/resources/assets/lib/contest-entry/uploader.coffee index e4eeab9e6d5..8d6a53ec8d5 100644 --- a/resources/assets/lib/contest-entry/uploader.coffee +++ b/resources/assets/lib/contest-entry/uploader.coffee @@ -99,6 +99,7 @@ export class Uploader extends React.Component fail: fileuploadFailCallback + componentWillUnmount: => $.unsubscribe ".#{@eventId}" @@ -106,6 +107,7 @@ export class Uploader extends React.Component .fileupload 'destroy' .remove() + convertFileToImage: (file) => new Promise (resolve, reject) -> image = new Image() From ed0fbbcd54c36a4dede83612dd0f3850a13c3838 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Wed, 26 Oct 2022 15:18:40 +0900 Subject: [PATCH 119/127] missed the days --- app/Console/Commands/ModdingRankCommand.php | 2 +- app/Models/User.php | 2 +- database/factories/OAuth/RefreshTokenFactory.php | 2 +- database/factories/OAuth/TokenFactory.php | 2 +- tests/Controllers/UsersControllerTest.php | 4 ++-- tests/Libraries/OrderCheckoutTest.php | 4 ++-- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/Console/Commands/ModdingRankCommand.php b/app/Console/Commands/ModdingRankCommand.php index 899d991a9e6..1cfcb3cea0f 100644 --- a/app/Console/Commands/ModdingRankCommand.php +++ b/app/Console/Commands/ModdingRankCommand.php @@ -53,7 +53,7 @@ private function rankAll($modeInt) $rankedTodayCount = Beatmapset::ranked() ->withoutTrashed() ->withModesForRanking($modeInt) - ->where('approved_date', '>=', now()->subDay()) + ->where('approved_date', '>=', now()->subDays()) ->count(); $rankableQuota = config('osu.beatmapset.rank_per_day') - $rankedTodayCount; diff --git a/app/Models/User.php b/app/Models/User.php index edf2e677753..71cae05af17 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -1200,7 +1200,7 @@ public function beatmapsetNominations() public function beatmapsetNominationsToday() { - return $this->beatmapsetNominations()->where('created_at', '>', Carbon::now()->subDay())->count(); + return $this->beatmapsetNominations()->where('created_at', '>', Carbon::now()->subDays())->count(); } public function beatmapPlaycounts() diff --git a/database/factories/OAuth/RefreshTokenFactory.php b/database/factories/OAuth/RefreshTokenFactory.php index 1fccf88c87e..438f0d81ba6 100644 --- a/database/factories/OAuth/RefreshTokenFactory.php +++ b/database/factories/OAuth/RefreshTokenFactory.php @@ -19,7 +19,7 @@ public function definition(): array { return [ 'access_token_id' => Token::factory(), - 'expires_at' => fn () => now()->addDay(), + 'expires_at' => fn () => now()->addDays(), 'id' => str_random(40), 'revoked' => false, ]; diff --git a/database/factories/OAuth/TokenFactory.php b/database/factories/OAuth/TokenFactory.php index ab406084254..a956346bcc1 100644 --- a/database/factories/OAuth/TokenFactory.php +++ b/database/factories/OAuth/TokenFactory.php @@ -20,7 +20,7 @@ public function definition(): array { return [ 'client_id' => Client::factory(), - 'expires_at' => fn () => now()->addDay(), + 'expires_at' => fn () => now()->addDays(), 'id' => str_random(40), 'revoked' => false, 'scopes' => ['public'], diff --git a/tests/Controllers/UsersControllerTest.php b/tests/Controllers/UsersControllerTest.php index a59723ad507..0f183d6408e 100644 --- a/tests/Controllers/UsersControllerTest.php +++ b/tests/Controllers/UsersControllerTest.php @@ -169,7 +169,7 @@ public function testPreviousUsernameShouldRedirect() /** @var User $user */ $user = User::factory()->create([ - 'osu_subscriptionexpiry' => now()->addDay(), + 'osu_subscriptionexpiry' => now()->addDays(), 'username' => $oldUsername, 'username_clean' => $oldUsername, ]); @@ -187,7 +187,7 @@ public function testPreviousUsernameTakenShouldNotRedirect() /** @var User $user1 */ $user1 = User::factory()->create([ - 'osu_subscriptionexpiry' => now()->addDay(), + 'osu_subscriptionexpiry' => now()->addDays(), 'username' => $oldUsername, 'username_clean' => $oldUsername, ]); diff --git a/tests/Libraries/OrderCheckoutTest.php b/tests/Libraries/OrderCheckoutTest.php index e117c08fe47..e19e766b1c5 100644 --- a/tests/Libraries/OrderCheckoutTest.php +++ b/tests/Libraries/OrderCheckoutTest.php @@ -21,7 +21,7 @@ class OrderCheckoutTest extends TestCase public function testTournamentBannerWhenAvailable() { $tournament = factory(Tournament::class)->create(); - $product = $this->createTournamentProduct($tournament, Carbon::now()->addDay(1)); + $product = $this->createTournamentProduct($tournament, Carbon::now()->addDays(1)); $orderItem = factory(OrderItem::class)->create([ 'product_id' => $product->product_id, 'extra_data' => [ @@ -55,7 +55,7 @@ public function testTournamentBannerWhenNoEndDate() public function testTournamentBannerWhenNotAvailable() { $tournament = factory(Tournament::class)->create(); - $product = $this->createTournamentProduct($tournament, Carbon::now()->subDay(1)); + $product = $this->createTournamentProduct($tournament, Carbon::now()->subDays(1)); $orderItem = factory(OrderItem::class)->create([ 'product_id' => $product->product_id, 'extra_data' => [ From 0f29f9a390f39091953836684d0a84dc8a00c084 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Wed, 26 Oct 2022 17:15:19 +0900 Subject: [PATCH 120/127] standardize to addDays --- tests/Controllers/ContestEntriesControllerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Controllers/ContestEntriesControllerTest.php b/tests/Controllers/ContestEntriesControllerTest.php index e50aacfe18b..abb60874a5c 100644 --- a/tests/Controllers/ContestEntriesControllerTest.php +++ b/tests/Controllers/ContestEntriesControllerTest.php @@ -71,7 +71,7 @@ private function prepareForStore() 'description_enter' => 'This is just a test!', 'description_voting' => 'This is just a test!', 'entry_starts_at' => Carbon::now(), - 'entry_ends_at' => Carbon::now()->addDay(), + 'entry_ends_at' => Carbon::now()->addDays(), 'extra_options' => ['forced_width' => 1920, 'forced_height' => 1080], 'header_url' => 'https://assets.ppy.sh/contests/154/header.jpg', 'max_entries' => 1, From 2f2a10fe9d9249821ed34e83db480d8252c81377 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Wed, 26 Oct 2022 17:39:20 +0900 Subject: [PATCH 121/127] more instances --- app/Libraries/Search/BeatmapsetQueryParser.php | 8 ++++---- app/Models/User.php | 6 +++--- tests/BroadcastNotificationTest.php | 2 +- tests/Commands/NotificationsSendMailTest.php | 2 +- tests/Libraries/ChangeUsernameTest.php | 12 ++++++------ tests/Libraries/UsernameValidationTest.php | 2 +- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/app/Libraries/Search/BeatmapsetQueryParser.php b/app/Libraries/Search/BeatmapsetQueryParser.php index 69e31e90d15..0a38c70d3ce 100644 --- a/app/Libraries/Search/BeatmapsetQueryParser.php +++ b/app/Libraries/Search/BeatmapsetQueryParser.php @@ -100,16 +100,16 @@ private static function makeDateRangeOption(string $operator, string $value): ?a if (preg_match('#^\d{4}$#', $value) === 1) { $startTime = Carbon::create($value, 1, 1, 0, 0, 0, 'UTC'); - $endTimeFunction = 'addYear'; + $endTimeFunction = 'addYears'; } elseif (preg_match('#^(?\d{4})[-./]?(?\d{1,2})$#', $value, $m) === 1) { $startTime = Carbon::create($m['year'], $m['month'], 1, 0, 0, 0, 'UTC'); - $endTimeFunction = 'addMonth'; + $endTimeFunction = 'addMonths'; } elseif (preg_match('#^(?\d{4})[-./]?(?\d{1,2})[-./]?(?\d{1,2})$#', $value, $m) === 1) { $startTime = Carbon::create($m['year'], $m['month'], $m['day'], 0, 0, 0, 'UTC'); - $endTimeFunction = 'addDay'; + $endTimeFunction = 'addDays'; } else { $startTime = parse_time_to_carbon($value); - $endTimeFunction = 'addSecond'; + $endTimeFunction = 'addSeconds'; } if (isset($startTime) && isset($endTimeFunction)) { diff --git a/app/Models/User.php b/app/Models/User.php index 71cae05af17..3575f68fab1 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -1684,7 +1684,7 @@ public function remainingHype() ->beatmapDiscussions() ->withoutTrashed() ->ofType('hype') - ->where('created_at', '>', Carbon::now()->subWeek()) + ->where('created_at', '>', Carbon::now()->subWeeks()) ->count(); return config('osu.beatmapset.user_weekly_hype') - $hyped; @@ -1698,11 +1698,11 @@ public function newHypeTime() ->beatmapDiscussions() ->withoutTrashed() ->ofType('hype') - ->where('created_at', '>', Carbon::now()->subWeek()) + ->where('created_at', '>', Carbon::now()->subWeeks()) ->orderBy('created_at') ->first(); - return $earliestWeeklyHype === null ? null : $earliestWeeklyHype->created_at->addWeek(); + return $earliestWeeklyHype === null ? null : $earliestWeeklyHype->created_at->addWeeks(); }); } diff --git a/tests/BroadcastNotificationTest.php b/tests/BroadcastNotificationTest.php index 91dc440c4c7..398f96f5980 100644 --- a/tests/BroadcastNotificationTest.php +++ b/tests/BroadcastNotificationTest.php @@ -69,7 +69,7 @@ public function testSendNotificationWithOptions($details) $beatmapset = Beatmapset::factory()->owner()->withDiscussion()->create(); $beatmapset->watches()->create([ - 'last_read' => now()->subSecond(), // make sure last_read isn't the same second the test runs. + 'last_read' => now()->subSeconds(), // make sure last_read isn't the same second the test runs. 'user_id' => $user->getKey(), ]); diff --git a/tests/Commands/NotificationsSendMailTest.php b/tests/Commands/NotificationsSendMailTest.php index 5184767ef3a..dbefce5e652 100644 --- a/tests/Commands/NotificationsSendMailTest.php +++ b/tests/Commands/NotificationsSendMailTest.php @@ -69,7 +69,7 @@ protected function setUp(): void foreach ($beatmapsets as $beatmapset) { $beatmapset->watches()->create([ - 'last_read' => now()->subSecond(), + 'last_read' => now()->subSeconds(), 'user_id' => $user->getKey(), ]); $this diff --git a/tests/Libraries/ChangeUsernameTest.php b/tests/Libraries/ChangeUsernameTest.php index fd068aa8f32..17f457ea75d 100644 --- a/tests/Libraries/ChangeUsernameTest.php +++ b/tests/Libraries/ChangeUsernameTest.php @@ -100,7 +100,7 @@ public function testUsernameTakenButInactive() 'username' => 'newusername', 'username_clean' => 'newusername', 'osu_subscriptionexpiry' => null, - 'user_lastvisit' => Carbon::now()->subYear(), + 'user_lastvisit' => Carbon::now()->subYears(), ]); $user->changeUsername('newusername', 'paid'); @@ -124,13 +124,13 @@ public function testUsernameTakenButInactiveAndNeedsMoreRenames() 'username' => 'newusername', 'username_clean' => 'newusername', 'osu_subscriptionexpiry' => null, - 'user_lastvisit' => Carbon::now()->subYear(), + 'user_lastvisit' => Carbon::now()->subYears(), ]); $this->createUser([ 'username' => 'newusername_old', 'username_clean' => 'newusername_old', 'osu_subscriptionexpiry' => null, - 'user_lastvisit' => Carbon::now()->subYear(), + 'user_lastvisit' => Carbon::now()->subYears(), ]); $user->changeUsername('newusername', 'paid'); @@ -161,7 +161,7 @@ public function testPreviousUserHasBadge() $existing->usernameChangeHistory()->create([ 'username' => 'existing_now', 'username_last' => $newUsername, - 'timestamp' => Carbon::now()->subYear(), + 'timestamp' => Carbon::now()->subYears(), 'type' => 'paid', ]); @@ -185,7 +185,7 @@ public function testPreviousUserHasNoBadge() $existing->usernameChangeHistory()->create([ 'username' => 'existing_now', 'username_last' => $newUsername, - 'timestamp' => Carbon::now()->subYear(), + 'timestamp' => Carbon::now()->subYears(), 'type' => 'paid', ]); @@ -204,7 +204,7 @@ public function testInactiveUserHasBadge() 'username' => 'newusername', 'username_clean' => 'newusername', 'osu_subscriptionexpiry' => null, - 'user_lastvisit' => Carbon::now()->subYear(), + 'user_lastvisit' => Carbon::now()->subYears(), ]); $existing->badges()->create(['image' => 'test', 'description' => 'test', 'awarded' => now()]); diff --git a/tests/Libraries/UsernameValidationTest.php b/tests/Libraries/UsernameValidationTest.php index 46f6dc1017a..6a2ab9f5753 100644 --- a/tests/Libraries/UsernameValidationTest.php +++ b/tests/Libraries/UsernameValidationTest.php @@ -18,7 +18,7 @@ public function testusersOfUsernameIncludesCurrentUsernameOwner() $existing = User::factory()->create([ 'username' => 'user1', 'username_clean' => 'user1', - 'user_lastvisit' => Carbon::now()->subYear(), + 'user_lastvisit' => Carbon::now()->subYears(), ]); $users = UsernameValidation::usersOfUsername('user1'); From c8edc1058912e955b79ca1ba5d4f7e3e186634a5 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Wed, 26 Oct 2022 17:55:14 +0900 Subject: [PATCH 122/127] and the NoOverflow versions.. --- database/factories/UserFactory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php index b65f771f7fb..73a4bc7c6e5 100644 --- a/database/factories/UserFactory.php +++ b/database/factories/UserFactory.php @@ -76,7 +76,7 @@ public function silenced() public function supporter() { - return $this->state(['osu_subscriber' => true, 'osu_subscriptionexpiry' => now()->addMonthNoOverflow(1)]); + return $this->state(['osu_subscriber' => true, 'osu_subscriptionexpiry' => now()->addMonthsNoOverflow(1)]); } public function tournamentBanned() From 51533a22f2551f40ee67b40a10ec254c64e2d9d5 Mon Sep 17 00:00:00 2001 From: nanaya Date: Thu, 27 Oct 2022 14:37:02 +0900 Subject: [PATCH 123/127] Use relation --- app/Http/Controllers/AccountController.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index 3f2b3076fdd..27635db31e0 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -178,11 +178,11 @@ public function updateNotificationOptions() DB::transaction(function () use ($requestParams) { $user = auth()->user(); - UserNotificationOption - ::lockForUpdate() - ->where('user_id', $user->getKey()) + $user + ->notificationOptions() ->whereIn('name', array_keys($requestParams)) ->select('user_id') + ->lockForUpdate() ->get(); foreach ($requestParams as $key => $value) { if (!UserNotificationOption::supportsNotifications($key)) { From e925d990bb7dabe9135637b155adc983b43db7fd Mon Sep 17 00:00:00 2001 From: nanaya Date: Thu, 27 Oct 2022 15:25:52 +0900 Subject: [PATCH 124/127] Silence lint warnings GitHub PR files tab may hang otherwise. --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 662ec192506..473764bfcb9 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -48,7 +48,7 @@ jobs: - name: Install js dependencies run: yarn --frozen-lockfile - - run: yarn lint --max-warnings 201 + - run: 'yarn lint --max-warnings 197 > /dev/null' - run: ./bin/update_licence.sh -nf From 8d26e06bdd1cd714521e6204ec2358bcf1bbd8fd Mon Sep 17 00:00:00 2001 From: nanaya Date: Thu, 27 Oct 2022 17:28:13 +0900 Subject: [PATCH 125/127] Fix error when weird id for beatmapset download is passed It's laravel/framework#26715 again which apparently isn't going to be fixed and should be manually done everywhere (still happens on latest laravel 9.19). --- app/Http/Controllers/BeatmapsetsController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/BeatmapsetsController.php b/app/Http/Controllers/BeatmapsetsController.php index 3a57f8bd4dd..c2331b065f9 100644 --- a/app/Http/Controllers/BeatmapsetsController.php +++ b/app/Http/Controllers/BeatmapsetsController.php @@ -168,7 +168,7 @@ public function discussionLock($id) public function download($id) { if (!is_api_request() && !from_app_url()) { - return ujs_redirect(route('beatmapsets.show', ['beatmapset' => $id])); + return ujs_redirect(route('beatmapsets.show', ['beatmapset' => rawurlencode($id)])); } $beatmapset = Beatmapset::findOrFail($id); From 03ca3f21a8a712782f2eca973ec0ff89a42f2e97 Mon Sep 17 00:00:00 2001 From: nanaya Date: Thu, 27 Oct 2022 18:27:04 +0900 Subject: [PATCH 126/127] Use correct total score for legacy score --- app/Libraries/Search/ScoreSearch.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/Libraries/Search/ScoreSearch.php b/app/Libraries/Search/ScoreSearch.php index 755eedac5a2..d5d48ecabdf 100644 --- a/app/Libraries/Search/ScoreSearch.php +++ b/app/Libraries/Search/ScoreSearch.php @@ -63,7 +63,12 @@ public function getQuery(): BoolQuery break; } - $beforeTotalScore = $this->params->beforeTotalScore ?? $this->params->beforeScore?->data->totalScore; + $beforeTotalScore = $this->params->beforeTotalScore; + if ($beforeTotalScore === null && $this->params->beforeScore !== null) { + $beforeTotalScore = $this->params->beforeScore->isLegacy() + ? $this->params->beforeScore->data->legacyTotalScore + : $this->params->beforeScore->data->totalScore; + } if ($beforeTotalScore !== null) { $scoreQuery = (new BoolQuery())->shouldMatch(1); $scoreQuery->should((new BoolQuery())->filter(['range' => [ From 906e7d898533dd2db18c34438add3a0328a2e58e Mon Sep 17 00:00:00 2001 From: nanaya Date: Thu, 27 Oct 2022 18:46:08 +0900 Subject: [PATCH 127/127] Add default value for default build id --- .env.example | 2 +- config/osu.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index dfd8cfbd9d7..ab6adaadaee 100644 --- a/.env.example +++ b/.env.example @@ -153,7 +153,7 @@ OSU_RUNNING_COST= CLIENT_CHECK_VERSION=false # CLIENT_USER_AGENT=osu! -# DEFAULT_BUILD_ID= +# DEFAULT_BUILD_ID=0 # SEARCH_MINIMUM_LENGTH=2 diff --git a/config/osu.php b/config/osu.php index d1adf0e9807..cfd52460fb0 100644 --- a/config/osu.php +++ b/config/osu.php @@ -92,7 +92,7 @@ ], 'client' => [ 'check_version' => get_bool(env('CLIENT_CHECK_VERSION')) ?? true, - 'default_build_id' => get_int(env('DEFAULT_BUILD_ID')), + 'default_build_id' => get_int(env('DEFAULT_BUILD_ID')) ?? 0, 'user_agent' => env('CLIENT_USER_AGENT', 'osu!'), ], 'elasticsearch' => [