1
0
mirror of https://github.com/flarum/core.git synced 2025-08-12 11:24:30 +02:00

Compare commits

...

26 Commits

Author SHA1 Message Date
flarum-bot
5c901cfba8 Bundled output for commit be1b5713fa
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2022-03-10 01:00:54 +00:00
David Sevilla Martin
be1b5713fa Replace ColorPreviewInput preview box with 'color' input (#3271) 2022-03-09 19:56:25 -05:00
Ian Morland
5045254c9f fix: unread filter gambit does not return results when > 999 read discussions for a user (#3295) 2022-03-09 15:41:04 -05:00
flarum-bot
9b302a1029 Bundled output for commit 97dfb50f17
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2022-02-22 14:06:00 +00:00
Clark Winkelmann
97dfb50f17 Fix permission check in edit modal
Previously was checking ability to edit own user instead of user selected in modal
2022-02-22 15:01:30 +01:00
Clark Winkelmann
6a940cd34f Fix pinned pane broken after discussion creation
The pane would appear but the page content would not shift to the right because the hasPane className would be missing
2022-02-22 15:01:02 +01:00
Clark Winkelmann
edd93dad77 Fix active search jumping to last item during loading 2022-02-22 15:00:14 +01:00
flarum-bot
2d18d37ba9 Bundled output for commit b58b3e2224
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2022-02-21 18:35:03 +00:00
David Wheatley
b58b3e2224 fix: don't submit form when search clear button clicked (#3260) 2022-02-21 19:31:03 +01:00
David Wheatley
2c902c6563 fix: overlap in minimized composer 2022-02-21 11:45:12 +01:00
David Wheatley
a38dc889e9 fix: composer header overlap with controls 2022-02-21 11:45:12 +01:00
flarum-bot
851907b88c Bundled output for commit dfa3b47cf3
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2022-02-09 23:18:18 +00:00
Alexander Skvortsov
dfa3b47cf3 fix: refer to bundled dist-typing types instead of src ones
This ensures that extensions referring to core's built dist typings don't try to pull from core's src code.
2022-02-09 18:13:32 -05:00
Alexander Skvortsov
289ea49cc7 chore: make translator / rich translator typings available to exts 2022-02-09 18:13:32 -05:00
flarum-bot
d769ee2b7b Bundled output for commit 6e3051b36a
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2022-02-09 21:02:11 +00:00
David Wheatley
6e3051b36a fix: sort posts by number instead of creation datetime (#3282)
Co-authored-by: Alexander Skvortsov <38059171+askvortsov1@users.noreply.github.com>
2022-02-09 20:58:11 +00:00
flarum-bot
c622070366 Bundled output for commit 21d3e33613
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2022-02-06 02:17:08 +00:00
David Wheatley
21d3e33613 chore: remove call to console.log 2022-02-06 02:12:52 +00:00
flarum-bot
b0d9f10280 Bundled output for commit d192185d13
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2022-01-30 22:49:44 +00:00
Alexander Skvortsov
d192185d13 chore: regenerate yarn.lock 2022-01-30 17:45:35 -05:00
Alexander Skvortsov
6dba5c8e67 chore: drop unnecessary ci script 2022-01-30 17:38:05 -05:00
Alexander Skvortsov
34c753040c chore: flarum-cli audit infra --fix 2022-01-27 16:45:10 -05:00
flarum-bot
7c4992c401 Bundled output for commit a7254773dd
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2022-01-24 04:31:39 +00:00
Alexander Skvortsov
a7254773dd chore: bump rich text ICU Message formatter
This fixes https://discuss.flarum.org/d/29914-utf-encoding-error-in-title/6
2022-01-23 23:24:51 -05:00
Daniël Klabbers
1217b11896 Update Application.php
update constant for next version
2022-01-20 14:20:36 +01:00
Daniël Klabbers
7a22527b72 update changelog 2022-01-20 13:56:05 +01:00
41 changed files with 1051 additions and 983 deletions

1
.gitattributes vendored
View File

@@ -14,5 +14,6 @@ js/dist/* -diff
js/dist/* linguist-generated
js/dist-typings/* linguist-generated
js/yarn.lock -diff
js/package-lock.json -diff
* text=auto eol=lf

View File

@@ -12,4 +12,4 @@ jobs:
with:
enable_backend_testing: true
backend_directory: .
backend_directory: .

View File

@@ -15,7 +15,9 @@ jobs:
enable_typescript: true
frontend_directory: ./js
backend_directory: .
js_package_manager: yarn
main_git_branch: master
secrets:
bundlewatch_github_token: ${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }}
bundlewatch_github_token: ${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }}

View File

@@ -100,7 +100,8 @@
- `last_activity_at, last_seen_at` updated on all API requests (https://github.com/flarum/core/pull/3231).
- `RememberMe` access token updated twice in API requests (https://github.com/flarum/core/pull/3233).
- Error in `funding` item in `composer.json` bricks the frontend (https://github.com/flarum/core/pull/3239).
- Fix escaped quotes in window title (https://github.com/flarum/core/pull/3264)
- Escaped quotes in window title (https://github.com/flarum/core/pull/3264)
- `schedule:list` command fails due to missing timezone configuration.
### Deprecated
- Unused `evented` utility (https://github.com/flarum/core/pull/3125).

View File

@@ -1,4 +1,4 @@
/// <reference path="../../../src/common/translator-icu-rich.d.ts" />
/// <reference path="../../@types/translator-icu-rich.d.ts" />
import Modal, { IInternalModalAttrs } from '../../common/components/Modal';
export interface ILoadingModalAttrs extends IInternalModalAttrs {
}

View File

@@ -1,4 +1,4 @@
/// <reference path="../../../src/common/translator-icu-rich.d.ts" />
/// <reference path="../../@types/translator-icu-rich.d.ts" />
import Modal, { IInternalModalAttrs } from '../../common/components/Modal';
import ExtensionReadme from '../models/ExtensionReadme';
import type Mithril from 'mithril';

View File

@@ -1,4 +1,4 @@
/// <reference path="../../../src/common/translator-icu-rich.d.ts" />
/// <reference path="../../@types/translator-icu-rich.d.ts" />
import type Mithril from 'mithril';
import type User from '../../common/models/User';
import ItemList from '../../common/utils/ItemList';

View File

@@ -1,4 +1,4 @@
/// <reference path="../../src/common/translator-icu-rich.d.ts" />
/// <reference path="../@types/translator-icu-rich.d.ts" />
import { RichMessageFormatter } from '@askvortsov/rich-icu-message-formatter';
import { pluralTypeHandler, selectTypeHandler } from '@ultraq/icu-message-formatter';
declare type Translations = Record<string, string>;

View File

@@ -1,6 +1,5 @@
import type Mithril from 'mithril';
import Component, { ComponentAttrs } from '../Component';
export default class ColorPreviewInput extends Component {
value?: string;
view(vnode: Mithril.Vnode<ComponentAttrs, this>): JSX.Element;
}

View File

@@ -1,4 +1,4 @@
/// <reference path="../../../src/common/translator-icu-rich.d.ts" />
/// <reference path="../../@types/translator-icu-rich.d.ts" />
import Modal, { IInternalModalAttrs } from './Modal';
import ItemList from '../utils/ItemList';
import Stream from '../utils/Stream';

View File

@@ -1,4 +1,4 @@
/// <reference path="../../../src/common/translator-icu-rich.d.ts" />
/// <reference path="../../@types/translator-icu-rich.d.ts" />
import Modal, { IInternalModalAttrs } from '../../common/components/Modal';
import Stream from '../../common/utils/Stream';
import Mithril from 'mithril';

View File

@@ -1,4 +1,4 @@
/// <reference path="../../../src/common/translator-icu-rich.d.ts" />
/// <reference path="../../@types/translator-icu-rich.d.ts" />
import Modal, { IInternalModalAttrs } from '../../common/components/Modal';
import ItemList from '../../common/utils/ItemList';
import Stream from '../../common/utils/Stream';

View File

@@ -104,6 +104,7 @@ export default class Search<T extends SearchAttrs = SearchAttrs> extends Compone
selectableItems(): JQuery;
/**
* Get the position of the currently selected search result item.
* Returns zero if not found.
*/
getCurrentNumericIndex(): number;
/**

View File

@@ -1,4 +1,4 @@
/// <reference path="../../../src/common/translator-icu-rich.d.ts" />
/// <reference path="../../@types/translator-icu-rich.d.ts" />
import Modal, { IInternalModalAttrs } from '../../common/components/Modal';
import ItemList from '../../common/utils/ItemList';
import Stream from '../../common/utils/Stream';

2
js/dist/admin.js generated vendored

File diff suppressed because one or more lines are too long

2
js/dist/admin.js.LICENSE.txt generated vendored
View File

@@ -48,7 +48,7 @@
*/
/*!
* focus-trap 6.7.1
* focus-trap 6.7.2
* @license MIT, https://github.com/focus-trap/focus-trap/blob/master/LICENSE
*/

2
js/dist/admin.js.map generated vendored

File diff suppressed because one or more lines are too long

2
js/dist/forum.js generated vendored

File diff suppressed because one or more lines are too long

2
js/dist/forum.js.LICENSE.txt generated vendored
View File

@@ -48,7 +48,7 @@
*/
/*!
* focus-trap 6.7.1
* focus-trap 6.7.2
* @license MIT, https://github.com/focus-trap/focus-trap/blob/master/LICENSE
*/

2
js/dist/forum.js.map generated vendored

File diff suppressed because one or more lines are too long

View File

@@ -3,7 +3,7 @@
"name": "@flarum/core",
"prettier": "@flarum/prettier-config",
"dependencies": {
"@askvortsov/rich-icu-message-formatter": "^0.2.3",
"@askvortsov/rich-icu-message-formatter": "^0.2.4",
"@ultraq/icu-message-formatter": "^0.12.0",
"bootstrap": "^3.4.1",
"clsx": "^1.1.1",
@@ -39,11 +39,12 @@
"scripts": {
"dev": "webpack --mode development --watch",
"build": "webpack --mode production",
"analyze": "cross-env ANALYZER=true yarn build",
"analyze": "cross-env ANALYZER=true yarn run build",
"format": "prettier --write src",
"format-check": "prettier --check src",
"clean-typings": "npx rimraf dist-typings && mkdir dist-typings",
"build-typings": "npm run clean-typings && tsc && [ -e src/@types ] && cp -r src/@types dist-typings/@types",
"build-typings": "yarn run clean-typings && [ -e src/@types ] && cp -r src/@types dist-typings/@types && tsc && yarn run post-build-typings",
"post-build-typings": "find dist-typings -type f -name '*.d.ts' -print0 | xargs -0 sed -i 's,../src/@types,@types,g'",
"check-typings": "tsc --noEmit --emitDeclarationOnly false",
"check-typings-coverage": "typescript-coverage-report"
},

26
js/src/@types/translator-icu-rich.d.ts vendored Normal file
View File

@@ -0,0 +1,26 @@
declare module '@askvortsov/rich-icu-message-formatter' {
type IValues = Record<string, any>;
type ITypeHandler = (
value: string,
matches: string,
locale: string,
values: IValues,
format: (message: string, values: IValues) => string
) => string;
type IRichHandler = (tag: any, values: IValues, contents: string) => any;
type ValueOrArray<T> = T | ValueOrArray<T>[];
type NestedStringArray = ValueOrArray<string>;
export class RichMessageFormatter {
locale: string | null;
constructor(locale: string | null, typeHandlers: Record<string, ITypeHandler>, richHandler: IRichHandler);
format(message: string, values: IValues): string;
process(message: string, values: IValues): NestedStringArray;
rich(message: string, values: IValues): NestedStringArray;
}
export function mithrilRichHandler(tag: any, values: IValues, contents: string): any;
}

17
js/src/@types/translator-icu.d.ts vendored Normal file
View File

@@ -0,0 +1,17 @@
declare module '@ultraq/icu-message-formatter' {
export function pluralTypeHandler(
value: string,
matches: string,
locale: string,
values: Record<string, any>,
format: (text: string, values: Record<string, any>) => string
): string;
export function selectTypeHandler(
value: string,
matches: string,
locale: string,
values: Record<string, any>,
format: (text: string, values: Record<string, any>) => string
): string;
}

View File

@@ -5,23 +5,20 @@ import classList from '../utils/classList';
import icon from '../helpers/icon';
export default class ColorPreviewInput extends Component {
value?: string;
view(vnode: Mithril.Vnode<ComponentAttrs, this>) {
const { className, ...attrs } = this.attrs;
const value = attrs.bidi?.() || attrs.value;
const { className, id, ...attrs } = this.attrs;
attrs.type ||= 'text';
return (
<div className="ColorInput">
<input className={classList('FormControl', className)} {...attrs} />
<input className={classList('FormControl', className)} id={id} {...attrs} />
<span className="ColorInput-icon" role="presentation">
{icon('fas fa-exclamation-circle')}
</span>
<div className="ColorInput-preview" style={{ '--input-value': value }} role="presentation" />
<input className="ColorInput-preview" {...attrs} type="color" />
</div>
);
}

View File

@@ -61,7 +61,7 @@ export default class EditUserModal<CustomAttrs extends IEditUserModalAttrs = IEd
fields() {
const items = new ItemList();
if (app.session.user?.canEditCredentials()) {
if (this.attrs.user.canEditCredentials()) {
items.add(
'username',
<div className="Form-group">
@@ -145,7 +145,7 @@ export default class EditUserModal<CustomAttrs extends IEditUserModalAttrs = IEd
}
}
if (app.session.user?.canEditGroups()) {
if (this.attrs.user.canEditGroups()) {
items.add(
'groups',
<div className="Form-group EditUserModal-groups">

View File

@@ -49,7 +49,6 @@ export default class Drawer {
* @internal
*/
resizeHandler = ((e) => {
console.log(this, e);
if (!e.matches && this.isOpen()) {
// Drawer is open but we've made window bigger, so hide it.
this.hide();

View File

@@ -101,7 +101,7 @@ export default class DiscussionComposer extends ComposerBody {
.save(data)
.then((discussion) => {
this.composer.hide();
app.discussions.refresh({ deferClear: true });
app.discussions.refresh();
m.route.set(app.route.discussion(discussion));
}, this.loaded.bind(this));
}

View File

@@ -53,7 +53,9 @@ export default class DiscussionPage<CustomAttrs extends IDiscussionPageAttrs = I
// page, then we don't want Mithril to redraw the whole page if it did,
// then the pane would redraw which would be slow and would cause problems with
// event handlers.
if (app.discussions.hasItems()) {
// We will also enable the pane if the discussion list is empty but loading,
// because the DiscussionComposer refreshes the list and redirects to the new discussion at the same time.
if (app.discussions.hasItems() || app.discussions.isLoading()) {
app.pane?.enable();
app.pane?.hide();
}
@@ -210,7 +212,7 @@ export default class DiscussionPage<CustomAttrs extends IDiscussionPageAttrs = I
record.relationships.discussion.data.id === discussionId
)
.map((record) => app.store.getById<Post>('posts', record.id))
.sort((a?: Post, b?: Post) => (a?.createdAt()?.getTime() ?? 0) - (b?.createdAt()?.getTime() ?? 0))
.sort((a?: Post, b?: Post) => (a?.number() ?? 0) - (b?.number() ?? 0))
.slice(0, 20);
}

View File

@@ -161,6 +161,7 @@ export default class Search<T extends SearchAttrs = SearchAttrs> extends Compone
className="Search-clear Button Button--icon Button--link"
onclick={this.clear.bind(this)}
aria-label={app.translator.trans('core.forum.header.search_clear_button_accessible_label')}
type="button"
>
{icon('fas fa-times-circle')}
</button>
@@ -324,9 +325,10 @@ export default class Search<T extends SearchAttrs = SearchAttrs> extends Compone
/**
* Get the position of the currently selected search result item.
* Returns zero if not found.
*/
getCurrentNumericIndex(): number {
return this.selectableItems().index(this.getItem(this.index));
return Math.max(0, this.selectableItems().index(this.getItem(this.index)));
}
/**

View File

@@ -289,7 +289,7 @@ class PostStreamState {
if (loadIds.length) {
return app.store.find('posts', loadIds).then((newPosts) => {
return loaded.concat(newPosts).sort((a, b) => a.createdAt() - b.createdAt());
return loaded.concat(newPosts).sort((a, b) => a.number() - b.number());
});
}

File diff suppressed because it is too large Load Diff

View File

@@ -7,12 +7,26 @@
bottom: 8px;
width: 20px;
height: 20px;
pointer-events: none;
}
&-preview {
background-color: var(--input-value);
display: inline-block;
border-radius: 15%;
padding: 0;
cursor: pointer;
overflow: hidden;
// Match both the wrapper div and the div with the background color
&, &::-webkit-color-swatch-wrapper, &::-webkit-color-swatch {
border: none;
padding: 0;
}
// This has to be a separate entry so other browsers
// don't ignore the entire CSS rule. Thanks Firefox.
&::-moz-color-swatch {
border: none;
}
}
&-icon {

View File

@@ -41,18 +41,23 @@
line-height: 1.5em;
color: var(--secondary-color);
&, input, a {
&,
input,
a {
font-size: 14px;
font-weight: normal;
}
input, a {
input,
a {
color: inherit;
}
input {
font-size: 16px;
width: 500px;
&, &[disabled], &:focus {
&,
&[disabled],
&:focus {
background: none;
border: 0;
padding: 0 20px 0 0;
@@ -230,7 +235,8 @@
height: 300px;
transition: background 0.2s, box-shadow 0.2s;
&.active, &.fullScreen {
&.active,
&.fullScreen {
background: var(--body-bg);
}
&.active:not(.fullScreen) {
@@ -258,9 +264,16 @@
}
}
.ComposerBody-header {
margin-right: 120px;
.fullScreen & {
margin-bottom: 20px;
}
.minimized & {
overflow: hidden;
margin-right: 32px;
}
}
.Composer-content {
padding: 20px 20px 0;
@@ -279,7 +292,8 @@
margin-bottom: -17px;
position: relative;
.minimized &, .fullScreen & {
.minimized &,
.fullScreen & {
display: none;
}
}
@@ -287,14 +301,16 @@
float: left;
.Avatar--size(64px);
.minimized &, .fullScreen & {
.minimized &,
.fullScreen & {
display: none;
}
}
.ComposerBody-content {
margin-left: 85px;
.minimized &, .fullScreen & {
.minimized &,
.fullScreen & {
margin-left: 0;
}
}

View File

@@ -41,7 +41,7 @@ class ListPostsController extends AbstractListController
/**
* {@inheritdoc}
*/
public $sortFields = ['createdAt'];
public $sortFields = ['number', 'createdAt'];
/**
* @var PostFilterer

View File

@@ -132,7 +132,7 @@ class ShowDiscussionController extends AbstractShowController
*/
private function loadPostIds(Discussion $discussion, User $actor)
{
return $discussion->posts()->whereVisibleTo($actor)->orderBy('created_at')->pluck('id')->all();
return $discussion->posts()->whereVisibleTo($actor)->orderBy('number')->pluck('id')->all();
}
/**
@@ -186,7 +186,7 @@ class ShowDiscussionController extends AbstractShowController
{
$query = $discussion->posts()->whereVisibleTo($actor);
$query->orderBy('created_at')->skip($offset)->take($limit)->with($include);
$query->orderBy('number')->skip($offset)->take($limit)->with($include);
$posts = $query->get();

View File

@@ -42,16 +42,29 @@ class DiscussionRepository
/**
* Get the IDs of discussions which a user has read completely.
*
* @deprecated 1.3 Use `getReadIdsQuery` instead
*
* @param User $user
* @return array
*/
public function getReadIds(User $user)
{
return $this->getReadIdsQuery($user)
->all();
}
/**
* Get a query containing the IDs of discussions which a user has read completely.
*
* @param User $user
* @return Builder
*/
public function getReadIdsQuery(User $user): Builder
{
return Discussion::leftJoin('discussion_user', 'discussion_user.discussion_id', '=', 'discussions.id')
->where('discussion_user.user_id', $user->id)
->whereColumn('last_read_post_number', '>=', 'last_post_number')
->pluck('id')
->all();
->select('id');
}
/**

View File

@@ -61,7 +61,7 @@ class UnreadFilterGambit extends AbstractRegexGambit implements FilterInterface
protected function constrain(Builder $query, User $actor, bool $negate)
{
if ($actor->exists) {
$readIds = $this->discussions->getReadIds($actor);
$readIds = $this->discussions->getReadIdsQuery($actor);
$query->where(function ($query) use ($readIds, $negate, $actor) {
if (! $negate) {

View File

@@ -21,7 +21,7 @@ class Application
*
* @var string
*/
const VERSION = '1.2.0';
const VERSION = '1.3.0-dev';
/**
* The IoC container for the Flarum application.

View File

@@ -19,6 +19,7 @@
<testsuites>
<testsuite name="Flarum Integration Tests">
<directory suffix="Test.php">./integration</directory>
<exclude>./integration/tmp</exclude>
</testsuite>
</testsuites>
</phpunit>