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

Compare commits

...

59 Commits

Author SHA1 Message Date
StyleCI Bot
d5bcc7fcbd Apply fixes from StyleCI 2022-06-15 13:23:08 +00:00
Daniël Klabbers
6be8d3dd17 wip 2022-06-07 21:20:56 +02:00
flarum-bot
b7332895db Bundled output for commit 0a3f449f9e
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2022-06-02 12:44:15 +00:00
Sami Mazouz
0a3f449f9e fix: post mentions with deleted author not rendering (#3432) 2022-06-02 13:38:24 +01:00
naxvog
df1bdd2ad8 chore: point Font Awesome icons link to v5 (#3447)
Update Font Awesome link to represent to currently used major version in order to avoid confusion when choosing icons
2022-06-02 13:34:42 +01:00
flarum-bot
8e2a99c1eb Bundled output for commit e45547c649
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2022-06-02 01:47:22 +00:00
David Wheatley
e45547c649 docs: ItemList set methods throw errors when keys are not present 2022-06-02 02:43:15 +01:00
Sami Mazouz
29362ed924 fix: empty suspension message uses email template expecting one (#3433) 2022-05-26 18:52:19 +01:00
Sami Mazouz
eb4bac3b8f fix: settings extender working only with first instances (#3439)
* test: settings extender works not only with first extender instance
* fix: settings extender working only with first instances
2022-05-24 17:55:05 +01:00
flarum-bot
584884a3c9 Bundled output for commit 96ead2a4df
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2022-05-20 19:36:54 +00:00
Ian Morland
96ead2a4df Add priorities to UserCard (#3436) 2022-05-20 20:32:25 +01:00
flarum-bot
556f10ddd8 Bundled output for commit a79e2c20fe
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2022-05-20 19:06:33 +00:00
Sami Mazouz
a79e2c20fe fix: dropdown show results search button hidden while loading results (#3431) 2022-05-20 20:02:04 +01:00
Sami Mazouz
89b194034b fix: nickname regex validation not working (#3430)
* test: regex validation for nickname on registration
* fix: nickname regex validation not working
* test: regex validation works with valid inputs
2022-05-20 14:04:14 +01:00
flarum-bot
01c54b13c8 Bundled output for commit 24c8c65aa5
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2022-05-19 23:53:18 +00:00
David Wheatley
24c8c65aa5 fix(typings): treat ColorPreview settings component type as specific string, not generic 2022-05-20 00:48:44 +01:00
David Wheatley
17de76f326 docs: add 1.2.1 to changelog and fix 1.3.0 diff link 2022-05-16 19:44:17 +01:00
Ngô Quốc Đạt
d3008d1e62 docs: correct links to documentation (#3426) 2022-05-16 18:49:59 +01:00
Daniël Klabbers
471947dfa7 chore: prefix markdown change with extension name 2022-05-16 10:34:28 +02:00
flarum-bot
2f506f1b24 Bundled output for commit 81cf6047f9
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2022-05-13 21:15:00 +00:00
David Wheatley
81cf6047f9 fix: call abstract Notification methods with fallback
Only call Notification methods if they are defined, falling back to `undefined` if not through the use of the optional chaining operator.
2022-05-13 23:08:29 +02:00
Daniël Klabbers
57d3c9a99a chore: simplify container binding
Co-authored-by: Sami Mazouz <sychocouldy@gmail.com>
2022-05-13 21:22:22 +02:00
Daniël Klabbers
999b345db1 chore: simplify container resolving of settings
Co-authored-by: Sami Mazouz <sychocouldy@gmail.com>
2022-05-13 21:22:22 +02:00
Daniël Klabbers
5e2f952fe6 fix: update test to reflect changes to slug transliteration 2022-05-13 21:22:22 +02:00
Daniël Klabbers
899b931b89 chore: add tests 2022-05-13 21:22:22 +02:00
StyleCI Bot
0431f15ac0 Apply fixes from StyleCI 2022-05-13 21:22:22 +02:00
Daniël Klabbers
6c57470b13 fix: slug generation uses actor locale instead of forum default 2022-05-13 21:22:22 +02:00
flarum-bot
6ca2ebc437 Bundled output for commit dd915c126c
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2022-05-12 20:14:55 +00:00
Sami Mazouz
dd915c126c fix(regression): PostStreamState loadCount static member (#3420) 2022-05-12 21:11:13 +01:00
Daniël Klabbers
62ffe5ffdf chore: add missing contribution for markdown menu support in admin area 2022-05-12 13:23:04 +02:00
Daniël Klabbers
592039c483 update constraint to v1.3 2022-05-10 16:28:35 +02:00
Daniël Klabbers
2f64f023b2 chore: fix version constant for v1.3 2022-05-10 16:09:48 +02:00
Daniël Klabbers
316a2067b6 fix link, tnx @bartvb 2022-05-10 12:30:19 +02:00
Alexander Skvortsov
de8d0d1d37 chore: use proper repo for core 2022-05-10 00:42:16 -04:00
Alexander Skvortsov
aea1a4cf63 chore: use proper branches for monorepo remotes 2022-05-09 14:26:00 -04:00
flarum-bot
7f5593021d Bundled output for commit f9ae7cd67f
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2022-05-09 16:01:25 +00:00
David Wheatley
f9ae7cd67f fix: incorrect tooltip docs for tooltipVisible attr (#3411) 2022-05-09 11:56:56 -04:00
Daniël Klabbers
843a613cda fix changelog for the framework 2022-05-09 16:14:57 +02:00
SychO9
da83e0c1a0 fix(a11y): Tag selection modal input visibility 2022-05-09 10:07:24 +02:00
SychO9
903026a7e4 fix: Composer discussion title not visible with certain colors 2022-05-09 10:06:52 +02:00
Sami Mazouz
1954d0383e fix: first posts having NULL as value for number column (#3414)
* fix: first posts having `NULL` as value for `number` column
* chore: add note about raw db function `IFNULL`
2022-05-08 23:21:11 +01:00
Daniël Klabbers
2e89ba3c94 chore: Allow installing monorepo through composer for dev purposes
This is as close as we're gonna get to a good solution for now.
2022-04-30 20:00:27 +01:00
Sami Mazouz
b14c0780d2 chore: fix package manager tests (#3407) 2022-04-25 13:31:16 +01:00
Sami Mazouz
d465fd27bc chore: reflect our issue tracking protocol in issue templates. (#3401) 2022-04-24 16:31:09 -04:00
Alexander Skvortsov
ffc9f9f5a4 fix(core): don't pass null to functions where that's deprecated (#3405)
Should fix remaining PHP 8.1 deprecation warnings/
2022-04-24 16:26:18 -04:00
flarum-bot
290bc19922 Bundled output for commit 863a8ddfff
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2022-04-23 14:26:23 +00:00
Alexander Skvortsov
863a8ddfff fix: don't duplicate path in URL to post on subdirectory installs. (#3354)
`baseUrl` includes the path portion of the url, as does `basePath`, which is included in `app.route.x` function outputs. The `baseOrigin` (with no path component at all) should be used instead.
2022-04-23 10:23:03 -04:00
flarum-bot
b8df3863d1 Bundled output for commit 4cb15501a2
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2022-04-21 22:20:19 +00:00
Alexander Skvortsov
4cb15501a2 fix(tags): TagDiscussionModal don't go to null tag (#3404)
If the tag we are trying to select/highlight is undefined, we should not run the scroll animation.
2022-04-21 18:03:41 -04:00
flarum-bot
42602a099f Bundled output for commit be2da3e12f
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2022-04-19 20:19:26 +00:00
Sami Mazouz
be2da3e12f fix: PHP 8.1 deprecation warnings (#3384) 2022-04-19 21:14:52 +01:00
flarum-bot
09bed537b3 Bundled output for commit fb717db57c
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2022-04-16 10:34:07 +00:00
Sami Mazouz
fb717db57c fix: slug transliteration assuming the language is always en (#3387)
* fix: transliteration assuming the language is always `en`
* test: transliteration works with forum locale
2022-04-16 11:31:23 +01:00
flarum-bot
cca97f32c6 Bundled output for commit c658eb10f4
Includes transpiled JS/TS.

[skip ci]
2022-04-14 15:21:36 +00:00
David Sevilla Martin
c658eb10f4 feat(emoji): support emoji 14 & unicode 14 (#3378) 2022-04-14 10:49:47 -04:00
flarum-bot
f667faa1bd Bundled output for commit 542cc42538
Includes transpiled JS/TS.

[skip ci]
2022-04-13 15:33:52 +00:00
Ian Morland
542cc42538 feat: export utils/isSafariMobile (#3389) 2022-04-13 16:31:05 +01:00
flarum-bot
518b39610e Bundled output for commit 6de1ea0194
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2022-04-09 22:06:48 +00:00
Sami Mazouz
6de1ea0194 fix: languages with combining characters cannot be searched (#3385)
* test: searching other types of languages
* fix: languages with combining characters cannot be searched
* test: can search in discussion titles
2022-04-09 23:04:15 +01:00
120 changed files with 1301 additions and 1972 deletions

View File

@@ -1,26 +1,7 @@
---
name: "🚀 Feature Request"
about: "I have a suggestion (and may want to implement it!)"
about: "If you have a suggestion please head over to our forum!"
---
<!--
IMPORTANT: Feature requests on this GitHub issue tracker are only accepted in case they have been approved by a core developer or contain extensive argumentation and directions for implementation. For all other feature requests, ideas and feedback please post in the Flarum Community: https://discuss.flarum.org/t/feedback.
-->
## Feature Request
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. eg. I have an issue when [...]
**Describe the solution you'd like**
A detailed description of your proposed solution. Include:
- How the feature would work/behave
- Any potential drawbacks
- Maybe a screenshot, design, or example code
**Justify why this feature belongs in Flarum's core, rather than in a third-party extension**
Consider who this change will be useful to  most Flarum forums, or just a few?
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
We primarily use GitHub as a bug tracker and issue tracker for items we are sure to tackle in the near future. For feature requests, ideas and feedback please post in the Flarum Community: https://discuss.flarum.org/t/proposals. Feature requests are added to GitHub only when they have been accepted by the development team and implementation details have been laid out.

View File

@@ -4,7 +4,7 @@ about: "If you have a question, please check out our forum or Discord!"
---
We primarily use GitHub as an issue tracker; for usage and support questions, please check out these resources below. Thanks!
We primarily use GitHub as a bug tracker and issue tracker for items we are sure to tackle in the near future; for usage and support questions, please check out these resources below. Thanks!
* Flarum Community: https://discuss.flarum.org/
* Discord Chat: https://flarum.org/discord/

View File

@@ -0,0 +1,15 @@
name: Package Manager PHP
on: [workflow_dispatch, push, pull_request]
# The reusable workflow definitions will be moved to the `flarum/framework` repo soon.
# This will break your current script.
# When this happens, run `flarum-cli audit infra --fix` to update your infrastructure.
jobs:
run:
uses: flarum/.github/.github/workflows/REUSABLE_backend.yml@main
with:
enable_backend_testing: true
backend_directory: ./extensions/package-manager

4
.gitignore vendored
View File

@@ -1 +1,3 @@
node_modules
node_modules
vendor
composer.lock

File diff suppressed because it is too large Load Diff

182
composer.json Normal file
View File

@@ -0,0 +1,182 @@
{
"name": "flarum/framework",
"description": "Delightfully simple forum software.",
"keywords": [
"forum",
"discussion"
],
"homepage": "https://flarum.org/",
"license": "MIT",
"authors": [
{
"name": "Flarum",
"email": "info@flarum.org",
"homepage": "https://flarum.org/team"
}
],
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/flarum"
},
{
"type": "github",
"url": "https://github.com/sponsors/flarum"
},
{
"type": "other",
"url": "https://flarum.org/donate"
}
],
"support": {
"issues": "https://github.com/flarum/core/issues",
"source": "https://github.com/flarum/core",
"docs": "https://docs.flarum.org",
"forum": "https://discuss.flarum.org",
"chat": "https://flarum.org/chat"
},
"autoload": {
"psr-4": {
"Flarum\\": "framework/core/src",
"Flarum\\Akismet\\": "extensions/akismet/src",
"Flarum\\Approval\\": "extensions/approval/src",
"Flarum\\Flags\\": "extensions/flags/src",
"Flarum\\Likes\\": "extensions/likes/src",
"Flarum\\Lock\\": "extensions/lock/src",
"Flarum\\Mentions\\": "extensions/mentions/src",
"Flarum\\Nicknames\\": "extensions/nicknames/src",
"Flarum\\PackageManager\\": "extensions/package-manager/src",
"Flarum\\Pusher\\": "extensions/pusher/src",
"Flarum\\Statistics\\": "extensions/statistics/src",
"Flarum\\Sticky\\": "extensions/sticky/src",
"Flarum\\Subscriptions\\": "extensions/subscriptions/src",
"Flarum\\Suspend\\": "extensions/suspend/src",
"Flarum\\Tags\\": "extensions/tags/src",
"Flarum\\PHPStan\\": "php-packages/phpstan/src",
"Flarum\\Testing\\": "php-packages/testing/src"
},
"files": [
"framework/core/src/helpers.php"
]
},
"replace": {
"flarum/core": "self.version",
"flarum/akismet": "self.version",
"flarum/approval": "self.version",
"flarum/bbcode": "self.version",
"flarum/embed": "self.version",
"flarum/emoji": "self.version",
"flarum/flags": "self.version",
"flarum/lang-english": "self.version",
"flarum/likes": "self.version",
"flarum/lock": "self.version",
"flarum/markdown": "self.version",
"flarum/mentions": "self.version",
"flarum/nicknames": "self.version",
"flarum/package-manager": "self.version",
"flarum/pusher": "self.version",
"flarum/statistics": "self.version",
"flarum/sticky": "self.version",
"flarum/subscriptions": "self.version",
"flarum/suspend": "self.version",
"flarum/tags": "self.version",
"flarum/phpstan": "self.version",
"flarum/testing": "self.version"
},
"require": {
"ext-json": "*",
"php": ">=7.3",
"axy/sourcemap": "^0.1.4",
"components/font-awesome": "^5.14.0",
"composer/composer": "^2.0",
"dflydev/fig-cookies": "^3.0.0",
"doctrine/dbal": "^2.7",
"dragonmantank/cron-expression": "^3.1.0",
"franzl/whoops-middleware": "^2.0.0",
"guzzlehttp/guzzle": "^7.4",
"illuminate/bus": "^8.0",
"illuminate/cache": "^8.0",
"illuminate/config": "^8.0",
"illuminate/console": "^8.0",
"illuminate/container": "^8.0",
"illuminate/contracts": "^8.0",
"illuminate/database": "^8.0",
"illuminate/events": "^8.0",
"illuminate/filesystem": "^8.0",
"illuminate/hashing": "^8.0",
"illuminate/mail": "^8.0",
"illuminate/queue": "^8.0",
"illuminate/session": "^8.0",
"illuminate/support": "^8.0",
"illuminate/validation": "^8.0",
"illuminate/view": "^8.0",
"intervention/image": "2.5.* || ^2.6.1",
"laminas/laminas-diactoros": "^2.4.1",
"laminas/laminas-httphandlerrunner": "^1.2.0",
"laminas/laminas-stratigility": "^3.2.2",
"league/flysystem": "^1.0.11",
"matthiasmullie/minify": "^1.3",
"middlewares/base-path": "^2.0.1",
"middlewares/base-path-router": "^2.0.1",
"middlewares/request-handler": "^2.0.1",
"monolog/monolog": "^1.16.0",
"nesbot/carbon": "^2.0",
"nikic/fast-route": "^0.6",
"psr/http-message": "^1.0",
"psr/http-server-handler": "^1.0",
"psr/http-server-middleware": "^1.0",
"pusher/pusher-php-server": "^2.2",
"s9e/text-formatter": "^2.3.6",
"symfony/config": "^5.2.2",
"symfony/console": "^5.2.2",
"symfony/event-dispatcher": "^5.2.2",
"symfony/mime": "^5.2.0",
"symfony/polyfill-intl-messageformatter": "^1.22.0",
"symfony/translation": "^5.1.5",
"symfony/yaml": "^5.2.2",
"tobscure/json-api": "^0.3.0",
"wikimedia/less.php": "^3.0"
},
"require-dev": {
"mockery/mockery": "^1.4",
"phpunit/phpunit": "^9.0",
"phpstan/phpstan-php-parser": "^1.0",
"phpstan/phpstan": "^1.2"
},
"config": {
"sort-packages": true
},
"minimum-stability": "dev",
"prefer-stable": true,
"extra": {
"flarum-subextensions": [
"extensions/akismet",
"extensions/approval",
"extensions/bbcode",
"extensions/embed",
"extensions/emoji",
"extensions/flags",
"extensions/lang-english",
"extensions/likes",
"extensions/lock",
"extensions/markdown",
"extensions/mentions",
"extensions/nicknames",
"extensions/package-manager",
"extensions/pusher",
"extensions/statistics",
"extensions/sticky",
"extensions/subscriptions",
"extensions/suspend",
"extensions/tags"
],
"branch-alias": {
"dev-main": "1.x-dev"
},
"phpstan": {
"includes": [
"extension.neon"
]
}
}
}

View File

@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.2",
"flarum/core": "^1.3",
"flarum/approval": "^1.2",
"guzzlehttp/guzzle": "^7.4"
},

View File

@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.2",
"flarum/core": "^1.3",
"flarum/flags": "^1.2"
},
"autoload": {

View File

@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.2"
"flarum/core": "^1.3"
},
"extra": {
"branch-alias": {

View File

@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.2"
"flarum/core": "^1.3"
},
"autoload": {
"psr-4": {

View File

@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.2"
"flarum/core": "^1.3"
},
"extra": {
"branch-alias": {

2
extensions/emoji/js/dist/forum.js generated vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -4,18 +4,18 @@
"version": "0.0.0",
"prettier": "@flarum/prettier-config",
"dependencies": {
"simple-emoji-map": "^0.4.1",
"twemoji": "^13.1.0"
"simple-emoji-map": "^0.5.1",
"twemoji": "^14.0.2"
},
"devDependencies": {
"prettier": "^2.5.1",
"flarum-webpack-config": "^2.0.0",
"webpack": "^5.65.0",
"webpack-cli": "^4.9.1",
"@flarum/prettier-config": "^1.0.0",
"flarum-tsconfig": "^1.0.2",
"flarum-webpack-config": "^2.0.0",
"prettier": "^2.5.1",
"typescript": "^4.5.4",
"typescript-coverage-report": "^0.6.1"
"typescript-coverage-report": "^0.6.1",
"webpack": "^5.65.0",
"webpack-cli": "^4.9.1"
},
"scripts": {
"dev": "webpack --mode development --watch",

View File

@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.2"
"flarum/core": "^1.3"
},
"autoload": {
"psr-4": {

View File

@@ -7,7 +7,7 @@
],
"license": "MIT",
"require": {
"flarum/core": "^1.2"
"flarum/core": "^1.3"
},
"extra": {
"branch-alias": {

View File

@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.2"
"flarum/core": "^1.3"
},
"autoload": {
"psr-4": {

View File

@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.2"
"flarum/core": "^1.3"
},
"autoload": {
"psr-4": {

View File

@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.2"
"flarum/core": "^1.3"
},
"extra": {
"branch-alias": {

View File

@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.2"
"flarum/core": "^1.3"
},
"autoload": {
"psr-4": {

View File

@@ -125,10 +125,13 @@ class ConfigureMentions
{
$post = CommentPost::find($tag->getAttribute('id'));
if ($post && $post->user) {
if ($post) {
$tag->setAttribute('discussionid', (int) $post->discussion_id);
$tag->setAttribute('number', (int) $post->number);
$tag->setAttribute('displayname', $post->user->display_name);
if ($post->user) {
$tag->setAttribute('displayname', $post->user->display_name);
}
return true;
}

View File

@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.2"
"flarum/core": "^1.3"
},
"autoload": {
"psr-4": {

File diff suppressed because one or more lines are too long

View File

@@ -40,7 +40,7 @@ class AddNicknameValidation
function ($attribute, $value, $fail) {
$regex = $this->settings->get('flarum-nicknames.regex');
if ($regex && ! preg_match_all("/$regex/", $value)) {
$this->translator->trans('flarum-nicknames.api.invalid_nickname_message');
$fail($this->translator->trans('flarum-nicknames.api.invalid_nickname_message'));
}
},
'min:'.$this->settings->get('flarum-nicknames.min'),

View File

@@ -74,4 +74,48 @@ class RegisterTest extends TestCase
$this->assertEquals(403, $response->getStatusCode());
}
/**
* @test
*/
public function cant_register_with_nickname_if_invalid_regex()
{
$this->setting('flarum-nicknames.set_on_registration', true);
$this->setting('flarum-nicknames.regex', '^[A-z]+$');
$response = $this->send(
$this->request('POST', '/register', [
'json' => [
'nickname' => '007',
'username' => 'test',
'password' => 'too-obscure',
'email' => 'test@machine.local',
]
])
);
$this->assertEquals(422, $response->getStatusCode());
}
/**
* @test
*/
public function can_register_with_nickname_if_valid_regex()
{
$this->setting('flarum-nicknames.set_on_registration', true);
$this->setting('flarum-nicknames.regex', '^[A-z]+$');
$response = $this->send(
$this->request('POST', '/register', [
'json' => [
'nickname' => 'Acme',
'username' => 'test',
'password' => 'too-obscure',
'email' => 'test@machine.local',
]
])
);
$this->assertEquals(201, $response->getStatusCode());
}
}

View File

@@ -23,7 +23,7 @@
},
"require": {
"flarum/core": "^1.0.0",
"composer/composer": "^2.0"
"composer/composer": "^2.3"
},
"require-dev": {
"flarum/testing": "^1.0.0",
@@ -86,7 +86,7 @@
"test:integration": "phpunit -c tests/phpunit.integration.xml",
"test:setup": [
"@php tests/integration/setup.php",
"cd $FLARUM_TEST_TMP_DIR_LOCAL && composer install"
"cd ${FLARUM_TEST_TMP_DIR_LOCAL:-${FLARUM_TEST_TMP_DIR:-./tests/integration/tmp}} && composer install"
]
},
"scripts-descriptions": {

View File

@@ -1,4 +1,3 @@
/// <reference path="../../../vendor/flarum/core/js/src/common/translator-icu-rich.d.ts" />
import Mithril from 'mithril';
import Modal, { IInternalModalAttrs } from 'flarum/common/components/Modal';
export interface WhyNotModalAttrs extends IInternalModalAttrs {
@@ -8,7 +7,7 @@ export default class WhyNotModal<Attrs extends WhyNotModalAttrs = WhyNotModalAtt
loading: boolean;
whyNot: string | null;
className(): string;
title(): import("@askvortsov/rich-icu-message-formatter").NestedStringArray;
title(): any;
oncreate(vnode: Mithril.VnodeDOM<Attrs, this>): void;
content(): JSX.Element;
requestWhyNot(): void;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -58,7 +58,7 @@ class CheckForUpdatesHandler
$actor->assertAdmin();
$firstOutput = $this->runComposerCommand(false);
$firstOutput = json_decode($firstOutput, true);
$firstOutput = json_decode($this->cleanJson($firstOutput), true);
$majorUpdates = false;
@@ -71,7 +71,7 @@ class CheckForUpdatesHandler
if ($majorUpdates) {
$secondOutput = $this->runComposerCommand(true);
$secondOutput = json_decode($secondOutput, true);
$secondOutput = json_decode($this->cleanJson($secondOutput), true);
}
if (! isset($secondOutput)) {
@@ -101,6 +101,15 @@ class CheckForUpdatesHandler
->save();
}
/**
* Composer can sometimes return text above the JSON.
* This method tries to remove such occurences.
*/
protected function cleanJson(string $composerOutput): string
{
return preg_replace('/^[^{]+\n({.*)/ms', '$1', $composerOutput);
}
/**
* @throws ComposerCommandFailedException
*/

View File

@@ -15,27 +15,11 @@ class SetupComposer
{
use UsesTmpDir;
private $config = [
'require' => [
'flarum/core' => '1.0.0',
'flarum/tags' => '1.0.3',
'flarum/lang-english' => '*',
],
'config' => [
'preferred-install' => 'dist',
'sort-packages' => true,
],
'repositories' => [
[
'type' => 'path',
'url' => __DIR__.'/tmp/packages/*',
]
]
];
private $config;
public function __construct(array $config = null)
{
$this->config = array_merge($this->config, $config ?? []);
$this->config = $config;
}
public function run()
@@ -44,7 +28,7 @@ class SetupComposer
$composerLock = $this->tmpDir().'/composer.lock';
$packages = $this->tmpDir().'/packages';
file_put_contents($composerJson, json_encode($this->config, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
file_put_contents($composerJson, json_encode($this->getConfig(), JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
if (! file_exists($packages)) {
mkdir($packages);
@@ -53,5 +37,28 @@ class SetupComposer
if (file_exists($composerLock)) {
unlink($composerLock);
}
echo 'composer.json created with testing packages directory.';
}
private function getConfig(): array
{
return array_merge([
'require' => [
'flarum/core' => '1.0.0',
'flarum/tags' => '1.0.3',
'flarum/lang-english' => '*',
],
'config' => [
'preferred-install' => 'dist',
'sort-packages' => true,
],
'repositories' => [
[
'type' => 'path',
'url' => realpath($this->tmpDir()).'/packages/*',
]
]
], $this->config ?? []);
}
}

View File

@@ -19,10 +19,7 @@
<testsuites>
<testsuite name="Flarum Integration Tests">
<directory suffix="Test.php">./integration</directory>
<exclude>./integration/tmp</exclude>
<exclude>./integration/tmp</exclude>
</testsuite>
</testsuites>
<php>
<env name="FLARUM_TEST_TMP_DIR_LOCAL" value="tests/integration/tmp" force="true" />
</php>
</phpunit>

View File

@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.2",
"flarum/core": "^1.3",
"pusher/pusher-php-server": "^2.2"
},
"require-dev": {

View File

@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.2"
"flarum/core": "^1.3"
},
"autoload": {
"psr-4": {

View File

@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.2"
"flarum/core": "^1.3"
},
"autoload": {
"psr-4": {

View File

@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.2"
"flarum/core": "^1.3"
},
"autoload": {
"psr-4": {

View File

@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.2"
"flarum/core": "^1.3"
},
"autoload": {
"psr-4": {

View File

@@ -49,6 +49,7 @@ flarum-suspend:
# Translations in this namespace are used by suspension email notifications
email:
no_reason_given: No reason was given for this suspension.
suspended:
subject: Your account has been suspended
body: |

View File

@@ -1,4 +1,4 @@
{!! $translator->trans('flarum-suspend.email.suspended.body', [
'{recipient_display_name}' => $user->display_name,
'{suspension_message}' => $blueprint->user->suspend_message,
'{suspension_message}' => $blueprint->user->suspend_message ?? $translator->trans('flarum-suspend.email.no_reason_given'),
]) !!}

View File

@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.2"
"flarum/core": "^1.3"
},
"autoload": {
"psr-4": {

View File

@@ -19,3 +19,20 @@ declare module 'flarum/common/models/Discussion' {
canTag: () => boolean | undefined;
}
}
declare module 'flarum/forum/components/IndexPage' {
export default interface IndexPage {
currentActiveTag?: Tag;
currentTagLoading?: boolean;
currentTag: () => Tag | undefined;
}
}
declare module 'flarum/admin/components/PermissionGrid' {
export interface PermissionConfig {
tagScoped?: boolean;
}
export default interface PermissionGrid {
loading?: boolean;
}
}

View File

@@ -1 +1 @@
export default function _default(): void;
export default function (): void;

View File

@@ -1,22 +1,29 @@
/// <reference types="flarum/@types/translator-icu-rich" />
import Modal, { IInternalModalAttrs } from 'flarum/common/components/Modal';
import Stream from 'flarum/common/utils/Stream';
import type Mithril from 'mithril';
import type Tag from '../../common/models/Tag';
export interface EditTagModalAttrs extends IInternalModalAttrs {
primary?: boolean;
model?: Tag;
}
/**
* The `EditTagModal` component shows a modal dialog which allows the user
* to create or edit a tag.
*/
export default class EditTagModal extends Modal<import("flarum/common/components/Modal").IInternalModalAttrs> {
constructor();
oninit(vnode: any): void;
tag: any;
name: Stream<any> | undefined;
slug: Stream<any> | undefined;
description: Stream<any> | undefined;
color: Stream<any> | undefined;
icon: Stream<any> | undefined;
isHidden: Stream<any> | undefined;
primary: Stream<any> | undefined;
title(): import("@askvortsov/rich-icu-message-formatter").NestedStringArray | import("mithril").Vnode<any, any>;
export default class EditTagModal extends Modal<EditTagModalAttrs> {
tag: Tag;
name: Stream<string>;
slug: Stream<string>;
description: Stream<string>;
color: Stream<string>;
icon: Stream<string>;
isHidden: Stream<boolean>;
primary: Stream<boolean>;
oninit(vnode: Mithril.Vnode<EditTagModalAttrs, this>): void;
className(): string;
title(): any;
content(): JSX.Element;
fields(): ItemList<any>;
fields(): any;
submitData(): {
name: any;
slug: any;
@@ -26,9 +33,6 @@ export default class EditTagModal extends Modal<import("flarum/common/components
isHidden: any;
primary: any;
};
onsubmit(e: any): void;
onsubmit(e: SubmitEvent): void;
delete(): void;
}
import Modal from "flarum/common/components/Modal";
import Stream from "flarum/common/utils/Stream";
import ItemList from "flarum/common/utils/ItemList";

View File

@@ -1,10 +1,9 @@
export default class TagsPage extends ExtensionPage<import("flarum/admin/components/ExtensionPage").ExtensionPageAttrs> {
constructor();
export default class TagsPage {
oninit(vnode: any): void;
forcedRefreshKey: number | undefined;
loading: boolean | undefined;
content(): JSX.Element;
onListOnCreate(vnode: any): void;
setMinTags(minTags: any, maxTags: any, value: any): void;
onSortUpdate(e: any): void;
}
import ExtensionPage from "flarum/admin/components/ExtensionPage";

View File

@@ -1 +1 @@
export default function tagLabel(tag: any, attrs?: {}): import("mithril").Vnode<any, any>;
export default function tagLabel(tag: any, attrs?: {}): any;

View File

@@ -1,24 +1,23 @@
import Model from 'flarum/common/Model';
import Discussion from 'flarum/common/models/Discussion';
export default class Tag extends Model {
name(): string;
slug(): string;
description(): string | null;
color(): string | null;
backgroundUrl(): string | null;
backgroundMode(): string | null;
icon(): string | null;
position(): number | null;
parent(): false | Tag | null;
children(): false | (Tag | undefined)[];
defaultSort(): string | null;
isChild(): boolean;
isHidden(): boolean;
discussionCount(): number;
lastPostedAt(): Date | null | undefined;
lastPostedDiscussion(): false | Discussion | null;
isRestricted(): boolean;
canStartDiscussion(): boolean;
canAddToDiscussion(): boolean;
isPrimary(): boolean;
name(): any;
slug(): any;
description(): any;
color(): any;
backgroundUrl(): any;
backgroundMode(): any;
icon(): any;
position(): any;
parent(): any;
children(): any;
defaultSort(): any;
isChild(): any;
isHidden(): any;
discussionCount(): any;
lastPostedAt(): any;
lastPostedDiscussion(): any;
isRestricted(): any;
canStartDiscussion(): any;
canAddToDiscussion(): any;
isPrimary(): any;
}

View File

@@ -1 +1,2 @@
export default function sortTags(tags: any): any;
import Tag from "../models/Tag";
export default function sortTags(tags: Tag[]): Tag[];

View File

@@ -1 +1 @@
export default function _default(): void;
export default function (): void;

View File

@@ -1,9 +1,9 @@
export default class DiscussionTaggedPost extends EventPost {
export default class DiscussionTaggedPost {
static initAttrs(attrs: any): void;
icon(): string;
descriptionKey(): "flarum-tags.forum.post_stream.added_and_removed_tags_text" | "flarum-tags.forum.post_stream.added_tags_text" | "flarum-tags.forum.post_stream.removed_tags_text";
descriptionData(): {
tagsAdded: any;
tagsRemoved: any;
};
}
import EventPost from "flarum/forum/components/EventPost";

View File

@@ -1,44 +1,46 @@
export default class TagDiscussionModal extends Modal<import("flarum/common/components/Modal").IInternalModalAttrs> {
constructor();
oninit(vnode: any): void;
tagsLoading: boolean | undefined;
selected: any[] | undefined;
filter: Stream<string> | undefined;
focused: boolean | undefined;
import type Mithril from 'mithril';
import Modal, { IInternalModalAttrs } from 'flarum/common/components/Modal';
import Discussion from 'flarum/common/models/Discussion';
import Tag from '../../common/models/Tag';
export interface TagDiscussionModalAttrs extends IInternalModalAttrs {
discussion?: Discussion;
selectedTags?: Tag[];
onsubmit?: (tags: Tag[]) => {};
}
export default class TagDiscussionModal extends Modal<TagDiscussionModalAttrs> {
tagsLoading: boolean;
selected: Tag[];
filter: any;
focused: boolean;
minPrimary: any;
maxPrimary: any;
minSecondary: any;
maxSecondary: any;
bypassReqs: any;
navigator: KeyboardNavigatable | undefined;
tags: any;
index: any;
bypassReqs: boolean;
navigator: any;
tags?: Tag[];
selectedTag?: Tag;
oninit(vnode: Mithril.Vnode<TagDiscussionModalAttrs, this>): void;
primaryCount(): number;
secondaryCount(): number;
/**
* Add the given tag to the list of selected tags.
*
* @param {Tag} tag
*/
addTag(tag: Tag): void;
/**
* Remove the given tag from the list of selected tags.
*
* @param {Tag} tag
*/
removeTag(tag: Tag): void;
className(): string;
title(): any;
getInstruction(primaryCount: any, secondaryCount: any): any;
getInstruction(primaryCount: number, secondaryCount: number): any;
content(): JSX.Element | JSX.Element[];
meetsRequirements(primaryCount: any, secondaryCount: any): boolean;
toggleTag(tag: any): void;
select(e: any): void;
selectableItems(): JQuery<HTMLElement>;
getCurrentNumericIndex(): number;
getItem(index: any): JQuery<HTMLElement>;
setIndex(index: any, scrollToItem: any): void;
onsubmit(e: any): void;
meetsRequirements(primaryCount: number, secondaryCount: number): boolean;
toggleTag(tag: Tag): void;
select(e: KeyboardEvent): void;
selectableItems(): any;
getCurrentNumericIndex(): any;
getItem(selectedTag: Tag): any;
setIndex(index: number, scrollToItem: boolean): void;
onsubmit(e: SubmitEvent): void;
}
import Modal from "flarum/common/components/Modal";
import Stream from "flarum/common/utils/Stream";
import KeyboardNavigatable from "flarum/forum/utils/KeyboardNavigatable";

View File

@@ -1,5 +1,3 @@
export default class TagHero extends Component<import("flarum/common/Component").ComponentAttrs, undefined> {
constructor();
export default class TagHero {
view(): JSX.Element;
}
import Component from "flarum/common/Component";

View File

@@ -1,5 +1,4 @@
export default class TagLinkButton extends LinkButton {
export default class TagLinkButton {
static initAttrs(attrs: any): void;
view(vnode: any): JSX.Element;
}
import LinkButton from "flarum/common/components/LinkButton";

View File

@@ -1,9 +1,7 @@
export default class TagsPage extends Page<import("flarum/common/components/Page").IPageAttrs> {
constructor();
export default class TagsPage {
oninit(vnode: any): void;
tags: any;
tags: any[] | undefined;
loading: boolean | undefined;
view(): JSX.Element;
oncreate(vnode: any): void;
}
import Page from "flarum/common/components/Page";

View File

@@ -1,8 +1,6 @@
/**
* @TODO move to core
*/
export default class ToggleButton extends Component<import("flarum/common/Component").ComponentAttrs, undefined> {
constructor();
export default class ToggleButton {
view(vnode: any): JSX.Element;
}
import Component from "flarum/common/Component";

View File

@@ -1,5 +1,5 @@
import Tag from "../../common/models/Tag";
import type Tag from "../../common/models/Tag";
export default class TagListState {
loadedIncludes: Set<unknown>;
load(includes?: never[]): Promise<Tag[]>;
load(includes?: string[]): Promise<Tag[]>;
}

2
extensions/tags/js/dist/admin.js generated vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
extensions/tags/js/dist/forum.js generated vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -322,7 +322,7 @@ export default class TagDiscussionModal extends Modal<TagDiscussionModalAttrs> {
m.redraw();
if (scrollToItem) {
if (scrollToItem && this.selectedTag) {
const dropdownScroll = $dropdown.scrollTop()!;
const dropdownTop = $dropdown.offset()!.top;
const dropdownBottom = dropdownTop + $dropdown.outerHeight()!;

View File

@@ -44,6 +44,7 @@
}
}
.TagsInput {
.add-keyboard-focus-ring(":focus-within");
padding-top: 0;
padding-bottom: 0;
overflow: hidden;
@@ -57,6 +58,7 @@
border: 0 !important;
padding: 0;
max-width: 100%;
min-width: 1ch;
margin-right: -100%;
background: transparent !important;
}
@@ -66,6 +68,7 @@
}
.TagsInput-selected {
.TagsInput-tag {
display: inline-flex;
margin-right: 5px;
&:last-child {

View File

@@ -4,132 +4,132 @@
{
"name": "akismet",
"gitRemote": "git@github.com:flarum/akismet.git",
"mainBranch": "master"
"mainBranch": "main"
},
{
"name": "approval",
"gitRemote": "git@github.com:flarum/approval.git",
"mainBranch": "master"
"mainBranch": "main"
},
{
"name": "bbcode",
"gitRemote": "git@github.com:flarum/bbcode.git",
"mainBranch": "master"
"mainBranch": "main"
},
{
"name": "embed",
"gitRemote": "git@github.com:flarum/embed.git",
"mainBranch": "master"
"mainBranch": "main"
},
{
"name": "emoji",
"gitRemote": "git@github.com:flarum/emoji.git",
"mainBranch": "master"
"mainBranch": "main"
},
{
"name": "flags",
"gitRemote": "git@github.com:flarum/flags.git",
"mainBranch": "master"
"mainBranch": "main"
},
{
"name": "lang-english",
"gitRemote": "git@github.com:flarum/lang-english.git",
"mainBranch": "master"
"mainBranch": "main"
},
{
"name": "likes",
"gitRemote": "git@github.com:flarum/likes.git",
"mainBranch": "master"
"mainBranch": "main"
},
{
"name": "lock",
"gitRemote": "git@github.com:flarum/lock.git",
"mainBranch": "master"
"mainBranch": "main"
},
{
"name": "markdown",
"gitRemote": "git@github.com:flarum/markdown.git",
"mainBranch": "master"
"mainBranch": "main"
},
{
"name": "mentions",
"gitRemote": "git@github.com:flarum/mentions.git",
"mainBranch": "master"
"mainBranch": "main"
},
{
"name": "nicknames",
"gitRemote": "git@github.com:flarum/nicknames.git",
"mainBranch": "master"
"mainBranch": "main"
},
{
"name": "package-manager",
"gitRemote": "git@github.com:flarum/package-manager.git",
"mainBranch": "master"
"mainBranch": "main"
},
{
"name": "pusher",
"gitRemote": "git@github.com:flarum/pusher.git",
"mainBranch": "master"
"mainBranch": "main"
},
{
"name": "statistics",
"gitRemote": "git@github.com:flarum/statistics.git",
"mainBranch": "master"
"mainBranch": "main"
},
{
"name": "sticky",
"gitRemote": "git@github.com:flarum/sticky.git",
"mainBranch": "master"
"mainBranch": "main"
},
{
"name": "subscriptions",
"gitRemote": "git@github.com:flarum/subscriptions.git",
"mainBranch": "master"
"mainBranch": "main"
},
{
"name": "suspend",
"gitRemote": "git@github.com:flarum/suspend.git",
"mainBranch": "master"
"mainBranch": "main"
},
{
"name": "tags",
"gitRemote": "git@github.com:flarum/tags.git",
"mainBranch": "master"
"mainBranch": "main"
}
],
"composer": [
{
"name": "testing",
"gitRemote": "git@github.com:flarum/testing.git",
"mainBranch": "master"
"mainBranch": "main"
},
{
"name": "phpstan",
"gitRemote": "git@github.com:flarum/phpstan.git",
"mainBranch": "master"
"mainBranch": "main"
}
],
"npm": [
{
"name": "prettier-config",
"gitRemote": "git@github.com:flarum/prettier-config.git",
"mainBranch": "master"
"mainBranch": "main"
},
{
"name": "webpack-config",
"gitRemote": "git@github.com:flarum/flarum-webpack-config.git",
"mainBranch": "master"
"mainBranch": "main"
},
{
"name": "tsconfig",
"gitRemote": "git@github.com:flarum/flarum-tsconfig.git",
"mainBranch": "master"
"mainBranch": "main"
}
],
"core": {
"name": "core",
"gitRemote": "git@github.com:flarum/core.git",
"mainBranch": "master"
"gitRemote": "git@github.com:flarum/flarum-core.git",
"mainBranch": "main"
}
}
}

View File

@@ -37,7 +37,6 @@
},
"require": {
"php": ">=7.3",
"axy/sourcemap": "^0.1.4",
"components/font-awesome": "^5.14.0",
"dflydev/fig-cookies": "^3.0.0",
"doctrine/dbal": "^2.7",
@@ -75,6 +74,8 @@
"psr/http-server-handler": "^1.0",
"psr/http-server-middleware": "^1.0",
"s9e/text-formatter": "^2.3.6",
"sycho/json-api": "^0.5.0",
"sycho/sourcemap": "^2.0.0",
"symfony/config": "^5.2.2",
"symfony/console": "^5.2.2",
"symfony/event-dispatcher": "^5.2.2",
@@ -82,7 +83,6 @@
"symfony/polyfill-intl-messageformatter": "^1.22.0",
"symfony/translation": "^5.1.5",
"symfony/yaml": "^5.2.2",
"tobscure/json-api": "^0.3.0",
"wikimedia/less.php": "^3.0"
},
"require-dev": {

View File

@@ -40,7 +40,7 @@ export interface HTMLInputSettingsComponentOptions extends CommonSettingsItemOpt
declare const BooleanSettingTypes: readonly ["bool", "checkbox", "switch", "boolean"];
declare const SelectSettingTypes: readonly ["select", "dropdown", "selectdropdown"];
declare const TextareaSettingTypes: readonly ["textarea"];
declare const ColorPreviewSettingType = "color-preview";
declare const ColorPreviewSettingType: "color-preview";
/**
* Valid options for the setting component builder to generate a Switch.
*/

View File

@@ -1,7 +1,7 @@
/// <reference path="../../@types/translator-icu-rich.d.ts" />
import ItemList from '../../common/utils/ItemList';
import AdminPage from './AdminPage';
import { Children } from 'mithril';
import type { Children } from 'mithril';
export default class DashboardPage extends AdminPage {
headerInfo(): {
className: string;

View File

@@ -1,4 +1,4 @@
import { Children, Vnode } from 'mithril';
import type { Children, Vnode } from 'mithril';
import Component, { ComponentAttrs } from '../../common/Component';
export interface IDashboardWidgetAttrs extends ComponentAttrs {
}

View File

@@ -25,7 +25,7 @@ export interface SavedModelData {
}
export declare type ModelData = UnsavedModelData | SavedModelData;
export interface SaveRelationships {
[relationship: string]: Model | Model[];
[relationship: string]: null | Model | Model[];
}
export interface SaveAttributes {
[key: string]: unknown;

View File

@@ -92,8 +92,8 @@ export default class Store {
/**
* Make a request to the API to find record(s) of a specific type.
*/
find<M extends Model>(type: string, params: ApiQueryParamsSingle): Promise<ApiResponseSingle<M>>;
find<Ms extends Model[]>(type: string, params: ApiQueryParamsPlural): Promise<ApiResponsePlural<Ms[number]>>;
find<M extends Model>(type: string, params?: ApiQueryParamsSingle): Promise<ApiResponseSingle<M>>;
find<Ms extends Model[]>(type: string, params?: ApiQueryParamsPlural): Promise<ApiResponsePlural<Ms[number]>>;
find<M extends Model>(type: string, id: string, params?: ApiQueryParamsSingle, options?: ApiQueryRequestOptions<ApiPayloadSingle>): Promise<ApiResponseSingle<M>>;
find<Ms extends Model[]>(type: string, ids: string[], params?: ApiQueryParamsPlural, options?: ApiQueryRequestOptions<ApiPayloadPlural>): Promise<ApiResponsePlural<Ms[number]>>;
/**

View File

@@ -7,12 +7,6 @@
*
* - `when` - a callback returning true when the browser should prompt for
* confirmation before closing the window/tab
*
* ### Children
*
* NOTE: Only the first child will be rendered. (Use this component to wrap
* another component / DOM element.)
*
*/
export default class ConfirmDocumentUnload extends Component<import("../Component").ComponentAttrs, undefined> {
constructor();
@@ -20,6 +14,6 @@ export default class ConfirmDocumentUnload extends Component<import("../Componen
oncreate(vnode: any): void;
boundHandler: (() => any) | undefined;
onremove(vnode: any): void;
view(vnode: any): any;
view(vnode: any): JSX.Element;
}
import Component from "../Component";

View File

@@ -9,9 +9,9 @@ export interface TooltipAttrs extends Mithril.CommonAttributes<TooltipAttrs, Too
*/
text: string | string[];
/**
* Manually show tooltip. `false` will show based on cursor events.
* Use to manually show or hide the tooltip. `undefined` will show based on cursor events.
*
* Default: `false`.
* Default: `undefined`.
*/
tooltipVisible?: boolean;
/**

View File

@@ -0,0 +1,8 @@
/**
* Fire a Flarum error which is shown in the JS console for everyone and in an alert for the admin.
*
* @param userTitle: a user friendly title of the error, should be localized.
* @param consoleTitle: an error title that goes in the console, doesn't have to be localized.
* @param error: the error.
*/
export default function fireApplicationError(userTitle: string, consoleTitle: string, error: any): void;

View File

@@ -13,6 +13,7 @@ export default class User extends Model {
avatarUrl(): string | null;
preferences(): Record<string, any> | null | undefined;
groups(): false | (Group | undefined)[];
isAdmin(): boolean | undefined;
joinTime(): Date | null | undefined;
lastSeenAt(): Date | null | undefined;
markedAllAsReadAt(): Date | null | undefined;

View File

@@ -78,7 +78,7 @@ export default class ItemList<T> {
/**
* Replaces an item's content, if the provided item key exists.
*
* If the provided `key` is not present, nothing will happen.
* If the provided `key` is not present, an error will be thrown.
*
* @param key The key of the item in the list
* @param content The item's new content
@@ -97,7 +97,7 @@ export default class ItemList<T> {
/**
* Replaces an item's priority, if the provided item key exists.
*
* If the provided `key` is not present, nothing will happen.
* If the provided `key` is not present, an error will be thrown.
*
* @param key The key of the item in the list
* @param priority The item's new priority
@@ -115,6 +115,8 @@ export default class ItemList<T> {
setPriority(key: string, priority: number): this;
/**
* Remove an item from the list.
*
* If the provided `key` is not present, nothing will happen.
*/
remove(key: string): this;
/**

View File

@@ -127,6 +127,7 @@ declare var _default: {
};
'utils/Pane': typeof Pane;
'utils/BasicEditorDriver': typeof BasicEditorDriver;
'utils/isSafariMobile': typeof isSafariMobile;
'states/ComposerState': typeof ComposerState;
'states/DiscussionListState': typeof DiscussionListState;
'states/GlobalSearchState': typeof GlobalSearchState;
@@ -198,6 +199,7 @@ import slidable from "./utils/slidable";
import History from "./utils/History";
import alertEmailConfirmation from "./utils/alertEmailConfirmation";
import Pane from "./utils/Pane";
import isSafariMobile from "./utils/isSafariMobile";
import ComposerState from "./states/ComposerState";
import DiscussionListState from "./states/DiscussionListState";
import GlobalSearchState from "./states/GlobalSearchState";

View File

@@ -1,9 +1,9 @@
import Component, { ComponentAttrs } from '../../common/Component';
import ItemList from '../../common/utils/ItemList';
import SubtreeRetainer from '../../common/utils/SubtreeRetainer';
import Discussion from '../../common/models/Discussion';
import Mithril from 'mithril';
import { DiscussionListParams } from '../states/DiscussionListState';
import type Discussion from '../../common/models/Discussion';
import type Mithril from 'mithril';
import type { DiscussionListParams } from '../states/DiscussionListState';
export interface IDiscussionListItemAttrs extends ComponentAttrs {
discussion: Discussion;
params: DiscussionListParams;

View File

@@ -8,5 +8,5 @@ export default class DiscussionRenamedNotification extends Notification {
icon(): string;
href(): string;
content(): import("@askvortsov/rich-icu-message-formatter").NestedStringArray;
excerpt(): string;
excerpt(): null;
}

View File

@@ -1,6 +1,6 @@
import NotificationModel from '../../common/models/Notification';
import type NotificationModel from '../../common/models/Notification';
import Component, { ComponentAttrs } from '../../common/Component';
import Mithril from 'mithril';
import type Mithril from 'mithril';
export interface INotificationAttrs extends ComponentAttrs {
notification: NotificationModel;
}

View File

@@ -1,8 +1,8 @@
import Component, { ComponentAttrs } from '../../common/Component';
import SubtreeRetainer from '../../common/utils/SubtreeRetainer';
import ItemList from '../../common/utils/ItemList';
import PostModel from '../../common/models/Post';
import Mithril from 'mithril';
import type PostModel from '../../common/models/Post';
import type Mithril from 'mithril';
export interface IPostAttrs extends ComponentAttrs {
post: PostModel;
}

View File

@@ -1,7 +1,7 @@
import ForumApplication from './ForumApplication';
import Discussion from '../common/models/Discussion';
import Post from '../common/models/Post';
import User from '../common/models/User';
import type Post from '../common/models/Post';
import type User from '../common/models/User';
/**
* Helper functions to generate URLs to form pages.
*/

View File

@@ -1,11 +1,7 @@
/// <reference types="node" />
import Discussion from '../../common/models/Discussion';
import Post from '../../common/models/Post';
import type Discussion from '../../common/models/Discussion';
import type Post from '../../common/models/Post';
export default class PostStreamState {
/**
* @see https://github.com/Microsoft/TypeScript/issues/3841#issuecomment-337560146
*/
['constructor']: typeof PostStreamState;
/**
* The number of posts to load per page.
*/

2
framework/core/js/dist/admin.js generated vendored

File diff suppressed because one or more lines are too long

View File

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

File diff suppressed because one or more lines are too long

2
framework/core/js/dist/forum.js generated vendored

File diff suppressed because one or more lines are too long

View File

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

File diff suppressed because one or more lines are too long

View File

@@ -77,7 +77,7 @@ export interface HTMLInputSettingsComponentOptions extends CommonSettingsItemOpt
const BooleanSettingTypes = ['bool', 'checkbox', 'switch', 'boolean'] as const;
const SelectSettingTypes = ['select', 'dropdown', 'selectdropdown'] as const;
const TextareaSettingTypes = ['textarea'] as const;
const ColorPreviewSettingType = 'color-preview';
const ColorPreviewSettingType = 'color-preview' as const;
/**
* Valid options for the setting component builder to generate a Switch.

View File

@@ -78,7 +78,7 @@ export default class EditGroupModal extends Modal {
<div className="Form-group">
<label>{app.translator.trans('core.admin.edit_group.icon_label')}</label>
<div className="helpText">
{app.translator.trans('core.admin.edit_group.icon_text', { a: <a href="https://fontawesome.com/icons?m=free" tabindex="-1" /> })}
{app.translator.trans('core.admin.edit_group.icon_text', { a: <a href="https://fontawesome.com/v5/search?m=free" tabindex="-1" /> })}
</div>
<input className="FormControl" placeholder="fas fa-bolt" bidi={this.icon} />
</div>,

View File

@@ -12,9 +12,9 @@ export interface TooltipAttrs extends Mithril.CommonAttributes<TooltipAttrs, Too
*/
text: string | string[];
/**
* Manually show tooltip. `false` will show based on cursor events.
* Use to manually show or hide the tooltip. `undefined` will show based on cursor events.
*
* Default: `false`.
* Default: `undefined`.
*/
tooltipVisible?: boolean;
/**

View File

@@ -127,7 +127,7 @@ export default class ItemList<T> {
/**
* Replaces an item's content, if the provided item key exists.
*
* If the provided `key` is not present, nothing will happen.
* If the provided `key` is not present, an error will be thrown.
*
* @param key The key of the item in the list
* @param content The item's new content
@@ -154,7 +154,7 @@ export default class ItemList<T> {
/**
* Replaces an item's priority, if the provided item key exists.
*
* If the provided `key` is not present, nothing will happen.
* If the provided `key` is not present, an error will be thrown.
*
* @param key The key of the item in the list
* @param priority The item's new priority
@@ -181,6 +181,8 @@ export default class ItemList<T> {
/**
* Remove an item from the list.
*
* If the provided `key` is not present, nothing will happen.
*/
remove(key: string): this {
delete this._items[key];

View File

@@ -72,6 +72,7 @@ import DiscussionPageResolver from './resolvers/DiscussionPageResolver';
import BasicEditorDriver from '../common/utils/BasicEditorDriver';
import routes from './routes';
import ForumApplication from './ForumApplication';
import isSafariMobile from './utils/isSafariMobile';
export default Object.assign(compat, {
'utils/PostControls': PostControls,
@@ -83,6 +84,7 @@ export default Object.assign(compat, {
'utils/UserControls': UserControls,
'utils/Pane': Pane,
'utils/BasicEditorDriver': BasicEditorDriver,
'utils/isSafariMobile': isSafariMobile,
'states/ComposerState': ComposerState,
'states/DiscussionListState': DiscussionListState,
'states/GlobalSearchState': GlobalSearchState,

View File

@@ -13,6 +13,8 @@ export interface INotificationAttrs extends ComponentAttrs {
notification: NotificationModel;
}
// TODO [Flarum 2.0]: Remove `?.` from abstract function calls.
/**
* The `Notification` component abstract displays a single notification.
* Subclasses should implement the `icon`, `href`, and `content` methods.
@@ -20,7 +22,7 @@ export interface INotificationAttrs extends ComponentAttrs {
export default abstract class Notification<CustomAttrs extends INotificationAttrs = INotificationAttrs> extends Component<CustomAttrs> {
view(vnode: Mithril.Vnode<CustomAttrs, this>) {
const notification = this.attrs.notification;
const href = this.href();
const href = this.href?.() ?? '';
const fromUser = notification.fromUser();
@@ -32,9 +34,9 @@ export default abstract class Notification<CustomAttrs extends INotificationAttr
onclick={this.markAsRead.bind(this)}
>
{avatar(fromUser || null)}
{icon(this.icon(), { className: 'Notification-icon' })}
{icon(this.icon?.(), { className: 'Notification-icon' })}
<span className="Notification-title">
<span className="Notification-content">{this.content()}</span>
<span className="Notification-content">{this.content?.()}</span>
<span className="Notification-title-spring" />
{humanTime(notification.createdAt())}
</span>
@@ -51,7 +53,7 @@ export default abstract class Notification<CustomAttrs extends INotificationAttr
}}
/>
)}
<div className="Notification-excerpt">{this.excerpt()}</div>
<div className="Notification-excerpt">{this.excerpt?.()}</div>
</Link>
);
}

View File

@@ -55,6 +55,6 @@ export default class PostMeta extends Component {
* @returns {string}
*/
getPermalink(post) {
return app.forum.attribute('baseUrl') + app.route.post(post);
return app.forum.attribute('baseOrigin') + app.route.post(post);
}
}

View File

@@ -130,7 +130,7 @@ export default class Search<T extends SearchAttrs = SearchAttrs> extends Compone
const searchLabel = extractText(app.translator.trans('core.forum.header.search_placeholder'));
const isActive = !!currentSearch;
const shouldShowResults = !!(!this.loadingSources && this.searchState.getValue() && this.hasFocus);
const shouldShowResults = !!(this.searchState.getValue() && this.hasFocus);
const shouldShowClearButton = !!(!this.loadingSources && this.searchState.getValue());
return (

View File

@@ -89,11 +89,12 @@ export default class UserCard extends Component {
{online
? [icon('fas fa-circle'), ' ', app.translator.trans('core.forum.user.online_text')]
: [icon('far fa-clock'), ' ', humanTime(lastSeenAt)]}
</span>
</span>,
100
);
}
items.add('joined', app.translator.trans('core.forum.user.joined_date_text', { ago: humanTime(user.joinTime()) }));
items.add('joined', app.translator.trans('core.forum.user.joined_date_text', { ago: humanTime(user.joinTime()) }), 90);
return items;
}

View File

@@ -5,11 +5,6 @@ import type Discussion from '../../common/models/Discussion';
import type Post from '../../common/models/Post';
export default class PostStreamState {
/**
* @see https://github.com/Microsoft/TypeScript/issues/3841#issuecomment-337560146
*/
['constructor']: typeof PostStreamState;
/**
* The number of posts to load per page.
*/
@@ -178,8 +173,8 @@ export default class PostStreamState {
return Promise.resolve();
}
const start = this.sanitizeIndex(index - this.constructor.loadCount / 2);
const end = start + this.constructor.loadCount;
const start = this.sanitizeIndex(index - PostStreamState.loadCount / 2);
const end = start + PostStreamState.loadCount;
this.reset(start, end);
@@ -191,13 +186,13 @@ export default class PostStreamState {
*/
_loadNext() {
const start = this.visibleEnd;
const end = (this.visibleEnd = this.sanitizeIndex(this.visibleEnd + this.constructor.loadCount));
const end = (this.visibleEnd = this.sanitizeIndex(this.visibleEnd + PostStreamState.loadCount));
// Unload the posts which are two pages back from the page we're currently
// loading.
const twoPagesAway = start - this.constructor.loadCount * 2;
const twoPagesAway = start - PostStreamState.loadCount * 2;
if (twoPagesAway > this.visibleStart && twoPagesAway >= 0) {
this.visibleStart = twoPagesAway + this.constructor.loadCount + 1;
this.visibleStart = twoPagesAway + PostStreamState.loadCount + 1;
if (this.loadPageTimeouts[twoPagesAway]) {
clearTimeout(this.loadPageTimeouts[twoPagesAway]);
@@ -214,11 +209,11 @@ export default class PostStreamState {
*/
_loadPrevious() {
const end = this.visibleStart;
const start = (this.visibleStart = this.sanitizeIndex(this.visibleStart - this.constructor.loadCount));
const start = (this.visibleStart = this.sanitizeIndex(this.visibleStart - PostStreamState.loadCount));
// Unload the posts which are two pages back from the page we're currently
// loading.
const twoPagesAway = start + this.constructor.loadCount * 2;
const twoPagesAway = start + PostStreamState.loadCount * 2;
if (twoPagesAway < this.visibleEnd && twoPagesAway <= this.count()) {
this.visibleEnd = twoPagesAway;
@@ -302,7 +297,7 @@ export default class PostStreamState {
*/
reset(start?: number, end?: number) {
this.visibleStart = start || 0;
this.visibleEnd = this.sanitizeIndex(end || this.constructor.loadCount);
this.visibleEnd = this.sanitizeIndex(end || PostStreamState.loadCount);
}
/**

View File

@@ -39,7 +39,7 @@
h3 {
margin: 0;
line-height: 1.5em;
color: var(--secondary-color);
color: var(--control-color);
&,
input,

View File

@@ -60,7 +60,7 @@ class UpdateUserController extends AbstractShowController
// Require the user's current password if they are attempting to change
// their own email address.
if (isset($data['attributes']['email']) && $actor->id == $id) {
$password = Arr::get($request->getParsedBody(), 'meta.password');
$password = (string) Arr::get($request->getParsedBody(), 'meta.password');
if (! $actor->checkPassword($password)) {
throw new NotAuthenticatedException;

View File

@@ -75,7 +75,8 @@ class ForumSerializer extends AbstractSerializer
'description' => $this->settings->get('forum_description'),
'showLanguageSelector' => (bool) $this->settings->get('show_language_selector', true),
'baseUrl' => $url = $this->url->to('forum')->base(),
'basePath' => parse_url($url, PHP_URL_PATH) ?: '',
'basePath' => $path = parse_url($url, PHP_URL_PATH) ?: '',
'baseOrigin' => substr($url, 0, strlen($url) - strlen($path)),
'debug' => $this->config->inDebugMode(),
'apiUrl' => $this->url->to('api')->base(),
'welcomeTitle' => $this->settings->get('welcome_title'),

View File

@@ -21,6 +21,7 @@ use Flarum\Foundation\EventGeneratorTrait;
use Flarum\Notification\Notification;
use Flarum\Post\MergeableInterface;
use Flarum\Post\Post;
use Flarum\Settings\SettingsRepositoryInterface;
use Flarum\User\User;
use Illuminate\Support\Str;
@@ -445,6 +446,10 @@ class Discussion extends AbstractModel
protected function setTitleAttribute($title)
{
$this->attributes['title'] = $title;
$this->slug = Str::slug($title);
$this->slug = Str::slug(
$title,
'-',
resolve(SettingsRepositoryInterface::class)->get('default_locale', 'en')
);
}
}

Some files were not shown because too many files have changed in this diff Show More