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

Compare commits

...

53 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
Daniël Klabbers
bd4d53323c fixing error in tests for missing timezone 2022-01-20 13:42:26 +01:00
Daniel Klabbers
ad69cf84fe Release v1.2 2022-01-20 12:55:30 +01:00
flarum-bot
aa77df46ee Bundled output for commit 19e48617f0
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2022-01-20 09:33:26 +00:00
Alexander Skvortsov
19e48617f0 chore: bump rich icu message formatter 2022-01-20 04:27:39 -05:00
Alexander Skvortsov
d8b83cc372 fix: build typings script 2022-01-20 04:24:32 -05:00
Alexander Skvortsov
a04b420295 fix: typings generation script 2022-01-20 04:12:32 -05:00
flarum-bot
5f4b5c0841 Bundled output for commit beae75dab3
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2022-01-20 08:25:20 +00:00
Alexander Skvortsov
beae75dab3 chore: fl-dev audit infra --fix 2022-01-20 03:19:22 -05:00
flarum-bot
e304cf7cb5 Bundled output for commit 9f87674626
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2022-01-18 18:38:18 +00:00
Alexander Skvortsov
9f87674626 chore: bump @askvortsov/rich-icu-message-formatter (#3264)
Fixes https://github.com/flarum/core/issues/3259
2022-01-18 13:32:30 -05:00
flarum-bot
54329d0827 Bundled output for commit a7aad46068
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2022-01-14 05:30:33 +00:00
David Wheatley
a7aad46068 fix: mark near as optional in discussion route (#3257) 2022-01-14 00:25:29 -05:00
flarum-bot
7551a14ae5 Bundled output for commit f4c29db182
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2022-01-09 04:01:27 +00:00
Alexander Skvortsov
f4c29db182 fix: Allow outside click on modal focus trap
Without this, alerts triggered while a modal is open can't be dismissed.
2022-01-08 22:55:48 -05:00
Alexander Skvortsov
a291134da1 fix: don't spellcheck custom LESS
This should stop browsers from "correcting" code, and from converting regular quotes to "smart" quotes.
2022-01-08 22:55:48 -05:00
flarum-bot
c702f5e228 Bundled output for commit 749e7e34f7
Includes transpiled JS/TS, and Typescript declaration files (typings).

[skip ci]
2022-01-09 00:24:36 +00:00
Alexander Skvortsov
749e7e34f7 Fix frontend branch name 2022-01-08 19:18:02 -05:00
Alexander Skvortsov
67821d95bd fix: Ensure user not false in post component
If no information about a relation exists, it will return false, not undefined. Therefore, the nullsafe operator is not enough to avoid issues here.
2022-01-08 18:26:51 -05:00
StyleCI Bot
aa44677df3 Apply fixes from StyleCI
[ci skip] [skip ci]
2022-01-06 02:47:52 +00:00
Alexander Skvortsov
3978efa533 LogDriver should work in debug mode 2022-01-05 21:47:33 -05:00
Alexander Skvortsov
687e1e2789 Use proper log level depending on debug mode 2022-01-05 21:45:27 -05:00
Alexander Skvortsov
7cec4d1f42 Format 2022-01-04 21:13:42 -05:00
Alexander Skvortsov
fbe1a48bec Fix echo statements not showing up in debug modals or console trace
This was accidentially introduced in the recent Application permissions refactor, where `formattedError`was changed to always be a string array.
2022-01-04 21:13:15 -05:00
David Wheatley
17a8d2c9d8 docs: add missing 1.1.1 changelog
This was present on the 1.1.1 branch, but not `master`.
2022-01-04 15:19:21 +00:00
Alexander Skvortsov
85ee80659d fix: broken post/discussion soft delete (#3249)
* FIx broken post/discussion soft delete

Before the Model typescript rewrite, `pushAttributes` supported including relationship objects, which is hacky but incorrect behavior. With the rewrite, this functionality was broken.

This PR deprecates the functionality, adds a deprecated BC layer with a debug warning, and removes instances of incorrect usage.

* Update js/src/common/Model.ts

Co-authored-by: David Wheatley <hi@davwheat.dev>

* Update js/src/common/Model.ts

Co-authored-by: David Wheatley <hi@davwheat.dev>

* chore: format

Co-authored-by: David Wheatley <hi@davwheat.dev>
2022-01-04 13:26:46 +00:00
Alexander Skvortsov
af77214967 Apply flarum-cli audit fix (#3248) 2022-01-03 16:57:09 -05:00
Alexander Skvortsov
7c3b51fec0 Use v1.0.0 of backend testing properly (#3247) 2022-01-03 16:04:17 -05:00
66 changed files with 1346 additions and 1306 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

15
.github/workflows/backend.yml vendored Normal file
View File

@@ -0,0 +1,15 @@
name: Core 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: .

23
.github/workflows/frontend.yml vendored Normal file
View File

@@ -0,0 +1,23 @@
name: Core JS
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_frontend.yml@main
with:
enable_bundlewatch: true
enable_prettier: true
enable_typescript: true
frontend_directory: ./js
backend_directory: .
js_package_manager: yarn
main_git_branch: master
secrets:
bundlewatch_github_token: ${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }}

View File

@@ -1,137 +0,0 @@
name: JS
on: [workflow_dispatch, push, pull_request]
env:
NODE_VERSION: 16
jobs:
prettier:
name: Prettier
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Set up Node
uses: actions/setup-node@v2
with:
node-version: ${{ env.NODE_VERSION }}
cache: "yarn"
cache-dependency-path: js/yarn.lock
- name: Install JS dependencies
run: yarn install --immutable
working-directory: ./js
- name: Check JS formatting
run: yarn run format-check
working-directory: ./js
typecheck:
name: Typecheck
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Set up Node
uses: actions/setup-node@v2
with:
node-version: ${{ env.NODE_VERSION }}
cache: "yarn"
cache-dependency-path: js/yarn.lock
- name: Install JS dependencies
run: yarn --frozen-lockfile
working-directory: ./js
- name: Typecheck
run: yarn run check-typings
working-directory: ./js
type-coverage:
name: Type Coverage
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Set up Node
uses: actions/setup-node@v2
with:
node-version: ${{ env.NODE_VERSION }}
cache: "yarn"
cache-dependency-path: js/yarn.lock
- name: Install JS dependencies
run: yarn --frozen-lockfile
working-directory: ./js
- name: Check type coverage
run: yarn run check-typings-coverage
working-directory: ./js
build-prod:
name: Build and commit
runs-on: ubuntu-latest
needs: [prettier, typecheck, type-coverage]
# Only commit JS on push to master branch
# Remember to change in `build-test` job too
if: github.ref == 'refs/heads/master' && github.event_name == 'push'
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Set up Node
uses: actions/setup-node@v2
with:
node-version: ${{ env.NODE_VERSION }}
cache: "yarn"
cache-dependency-path: js/yarn.lock
# Our action will install npm, cd into `./js`, run `npm run build` and
# `npm run build-typings`, then commit and upload any changes
- name: Build production JS
uses: flarum/action-build@2
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
build_script: build
package_manager: yarn
typings_script: build-typings
build-test:
name: Test build
runs-on: ubuntu-latest
needs: [prettier, typecheck, type-coverage]
# Inverse check of `build-prod`
# Remember to change in `build-prod` job too
if: github.ref != 'refs/heads/master' || github.event_name != 'push'
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Set up Node
uses: actions/setup-node@v2
with:
node-version: ${{ env.NODE_VERSION }}
cache: "yarn"
cache-dependency-path: js/yarn.lock
# Our action will install npm, cd into `./js`, run `npm run build` and
# `npm run build-typings`, then commit and upload any changes
- name: Build production JS
uses: flarum/action-build@2
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
build_script: build
package_manager: yarn
typings_script: build-typings
do_not_commit: true

View File

@@ -1,45 +0,0 @@
name: Bundle size checker
on:
workflow_dispatch:
push:
paths:
- "js/**"
pull_request:
paths:
- "js/**"
jobs:
bundlewatch:
runs-on: ubuntu-latest
name: Bundlewatch
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: "14"
- name: Use npm v7
run: sudo npm install -g npm@7.x.x
- name: Install JS dependencies
# We need to use `npm install` here. If we don't, the workflow will fail.
run: npm install
working-directory: ./js
- name: Build production assets
run: npm run build
working-directory: ./js
- name: Check bundle size change
run: node_modules/.bin/bundlewatch --config .bundlewatch.config.json
working-directory: ./js
env:
BUNDLEWATCH_GITHUB_TOKEN: ${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }}
CI_COMMIT_SHA: ${{ github.event.pull_request.head.sha }}

View File

@@ -1,79 +0,0 @@
name: Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
php: [7.3, 7.4, '8.0', '8.1']
service: ['mysql:5.7', mariadb]
prefix: ['', flarum_]
include:
- service: 'mysql:5.7'
db: MySQL
- service: mariadb
db: MariaDB
- prefix: flarum_
prefixStr: (prefix)
exclude:
- php: 7.3
service: 'mysql:5.7'
prefix: flarum_
- php: 7.3
service: mariadb
prefix: flarum_
- php: 8.0
service: 'mysql:5.7'
prefix: flarum_
- php: 8.0
service: mariadb
prefix: flarum_
services:
mysql:
image: ${{ matrix.service }}
ports:
- 13306:3306
name: 'PHP ${{ matrix.php }} / ${{ matrix.db }} ${{ matrix.prefixStr }}'
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@0b9d33cd0782337377999751fc10ea079fdd7104 # pin@v2
with:
php-version: ${{ matrix.php }}
coverage: xdebug
extensions: curl, dom, gd, json, mbstring, openssl, pdo_mysql, tokenizer, zip
tools: phpunit, composer:v2
# The authentication alter is necessary because newer mysql versions use the `caching_sha2_password` driver,
# which isn't supported prior to PHP7.4
# When we drop support for PHP7.3, we should remove this from the setup.
- name: Create MySQL Database
run: |
sudo systemctl start mysql
mysql -uroot -proot -e 'CREATE DATABASE flarum_test;' --port 13306
mysql -uroot -proot -e "ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'root';" --port 13306
- name: Install Composer dependencies
run: composer install
- name: Setup Composer tests
run: composer test:setup
env:
DB_PORT: 13306
DB_PASSWORD: root
DB_PREFIX: ${{ matrix.prefix }}
- name: Run Composer tests
run: composer test
env:
COMPOSER_PROCESS_TIMEOUT: 600

1
.gitignore vendored
View File

@@ -1,6 +1,7 @@
/vendor
composer.lock
composer.phar
.DS_Store
Thumbs.db
tests/.phpunit.result.cache

View File

@@ -1,5 +1,115 @@
# Changelog
## [1.2.0](https://github.com/flarum/core/compare/v1.1.1...v1.2.0)
### Added
- View `README` documentation in extension pages (https://github.com/flarum/core/pull/3094).
- Declare & Use CSS Custom Properties (https://github.com/flarum/core/pull/3146).
- Lazy draw dropdowns to improve performance (https://github.com/flarum/core/pull/2925).
- Default Settings Extender (https://github.com/flarum/core/pull/3127).
- Add `textarea` setting type to admin pages (https://github.com/flarum/core/pull/3141).
- Allow registering settings as `Less` config vars through Settings Extender (https://github.com/flarum/core/pull/3011).
- Allow replacing of blade template namespaces via extender (https://github.com/flarum/core/pull/3167).
- Update to Webpack 5 (https://github.com/flarum/core/pull/3135).
- Introduce `Less` custom function extender with a `is-extension-enabled` function (https://github.com/flarum/core/pull/3190).
- Support for `few` in ICU Message syntax (https://github.com/flarum/core/pull/3122).
- ES6 local support for number formatting (https://github.com/flarum/core/pull/3099).
- Added dedicated endpoint for retrieving single groups (https://github.com/flarum/core/pull/3084).
- Callback `loadWhere` relation eager loading extender (https://github.com/flarum/core/pull/3116).
- Extensible document title driver implementation (https://github.com/flarum/core/pull/3109).
- Type checks, typescript coverage GH action (https://github.com/flarum/core/pull/3136).
- Add color indicator in appearance admin page instead of validating colors (https://github.com/flarum/core/pull/3140).
- Add typing files for our translator libraries (https://github.com/flarum/core/pull/3175).
- `StatusWidget` tools extensibility (https://github.com/flarum/core/pull/3189).
- Allow switching the `ImageManager` driver (https://github.com/flarum/core/pull/3195).
- Events for notification read/all read actions (https://github.com/flarum/core/pull/3203).
### Changed
- Testing with php8.1 (https://github.com/flarum/core/pull/3102).
- Migrate fully to Yarn (https://github.com/flarum/core/pull/3155).
- Handle post rendering errors to avoid crashes (https://github.com/flarum/core/pull/3061).
- Added basic filtering, sorting, and pagination to groups endpoint (https://github.com/flarum/core/pull/3084).
- Pass IP address to API Client pipeline (https://github.com/flarum/core/pull/3124).
- Rename Extension Page "Uninstall" to "Purge" (https://github.com/flarum/core/pull/3123).
- [A11Y] Improve accessibility for discussion reply count on post stream (https://github.com/flarum/core/pull/3090).
- Improved post loading support (https://github.com/flarum/core/pull/3100).
- Rewrite SubtreeRetainer into Typescript (https://github.com/flarum/core/pull/3137).
- Rewrite ModalManager and state to Typescript (https://github.com/flarum/core/pull/3007).
- Rewrite frontend application files to Typescript (https://github.com/flarum/core/pull/3006).
- Allow extensions to modify the minimum search length in the Search component (https://github.com/flarum/core/pull/3130).
- Allow use of any tag in `listItems` helper (https://github.com/flarum/core/pull/3147).
- Replace `for ... in` with `Array.reduce` (https://github.com/flarum/core/pull/3149).
- Page title format is now implemented through translations (https://github.com/flarum/core/pull/3077, https://github.com/flarum/core/pull/3228)
- Add `aria-label` attribute to the navigation drawer button (https://github.com/flarum/core/pull/3157).
- Convert extend util to TypeScript (https://github.com/flarum/core/pull/2928).
- Better typings for DiscussionListState (https://github.com/flarum/core/pull/3132).
- Rewrite ItemList, update `ItemList` typings (https://github.com/flarum/core/pull/3005).
- Add priority order to discussion page controls (https://github.com/flarum/core/pull/3165).
- Use `@php` in Blade templates (https://github.com/flarum/core/pull/3172).
- Convert some common classes/utils to TS (https://github.com/flarum/core/pull/2929).
- Convert routes to Typescript (https://github.com/flarum/core/pull/3177).
- Move admin `colorItems` to an `ItemList` (https://github.com/flarum/core/pull/3186).
- Centralize pagination/canonical meta URL generation in Document (https://github.com/flarum/core/pull/3077).
- Use revision versioner to allow custom asset versioning (https://github.com/flarum/core/pull/3183).
- Split up application error handling (https://github.com/flarum/core/pull/3184).
- Make SlugManager available to blade template (https://github.com/flarum/core/pull/3194).
- Convert models to TS (https://github.com/flarum/core/pull/3174).
- Allow loading relations in other discussion endpoints (https://github.com/flarum/core/pull/3191).
- Improve selected text stylization (https://github.com/flarum/core/pull/2961).
- Extract notification `primaryControl` items to an ItemList (https://github.com/flarum/core/pull/3204).
- Frontend code housekeeping (#3214, #3213).
- Only retain scroll position if coming from discussion (https://github.com/flarum/core/pull/3229).
- Use `aria-live` regions to focus screenreader attention on alerts as they appear (https://github.com/flarum/core/pull/3237).
- Prevent unwarranted `a11y` warnings on custom Button subclasses (https://github.com/flarum/core/pull/3238).
### Fixed
- Missing locale text in the user editing modal (https://github.com/flarum/core/pull/3093).
- Dashes in table prefix prevent installation (https://github.com/flarum/core/pull/3089).
- Missing autocomplete attributes to input fields (https://github.com/flarum/core/pull/3088).
- Missing route parameters throwing an error (https://github.com/flarum/core/pull/3118).
- Mail settings select component never used (https://github.com/flarum/core/pull/3120).
- White avatar image throws javascript errors on the profile page (https://github.com/flarum/core/pull/3119).
- Unformatted avatar upload validation errors (https://github.com/flarum/core/pull/2946).
- Webkit input clear button shows up with the custom one (https://github.com/flarum/core/pull/3128).
- Media query breakpoints conflict with Windows display scaling (https://github.com/flarum/core/pull/3139).
- `typeof this` not recognized by some IDEs (https://github.com/flarum/core/pull/3142).
- `Model.save()` cannot save `null` `hasOne` relationship (https://github.com/flarum/core/pull/3131).
- Edit post `until reply` policy broken on PHP 8 (https://github.com/flarum/core/pull/3145).
- Inaccurate `Component.component` argument typings (https://github.com/flarum/core/pull/3148).
- Scrolling notification list infinitely repeats (https://github.com/flarum/core/pull/3159).
- Argument for INFO constant was assigned to `maxfiles` argument incorrectly (bfd81a83cfd0fa8125395a147ff0c9ce622f38e3).
- `Activated` event is sent every time an email is confirmed instead of just once (https://github.com/flarum/core/pull/3163).
- [A11Y] Modal close button missing accessible label (https://github.com/flarum/core/pull/3161).
- [A11Y] Auth modal inputs missing accessible labels (https://github.com/flarum/core/pull/3207).
- [A11Y] Triggering click on drawer button can cause layered backdrops (https://github.com/flarum/core/pull/3018).
- [A11Y] Focus can leave open nav drawer on mobile (https://github.com/flarum/core/pull/3018).
- [A11Y] Post action items not showing when focus is within the post (https://github.com/flarum/core/pull/3173).
- [A11Y] Missing accessible label for alert dismiss button (https://github.com/flarum/core/pull/3237).
- Error accessing the forum after saving a setting with more than 65k characters (https://github.com/flarum/core/pull/3162).
- Cannot restart queue from within (https://github.com/flarum/core/pull/3166).
- `Post--by-actor` not showing when comparing user instances (https://github.com/flarum/core/pull/3170).
- Incorrect typings for Modal `hide()` method (https://github.com/flarum/core/pull/3180).
- Avatar Upload throws errors with correct mimetype and incorrect extension (https://github.com/flarum/core/pull/3181).
- Clicking the dropdown button on a post opens all dropdowns in `Post-actions` (https://github.com/flarum/core/pull/3185).
- `getPlainContent()` causes external content to be fetched (https://github.com/flarum/core/pull/3193).
- `listItems` not accepting all `Mithril.Children` (https://github.com/flarum/core/pull/3176).
- Notifications mark as read option updates all notifications including the read ones (https://github.com/flarum/core/pull/3202).
- Post meta permalink not properly generated (https://github.com/flarum/core/pull/3216).
- Broken contribution link in README (https://github.com/flarum/core/pull/3211).
- `WelcomeHero` is displayed when content is empty (https://github.com/flarum/core/pull/3219).
- `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).
- 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).
## [1.1.1](https://github.com/flarum/core/compare/v1.1.0...v1.1.1)
### Fixed
- Performance issue with very large communities.
## [1.1.0](https://github.com/flarum/core/compare/v1.0.4...v1.1.0)

View File

View File

@@ -86,7 +86,7 @@
"wikimedia/less.php": "^3.0"
},
"require-dev": {
"flarum/testing": "1.0@dev"
"flarum/testing": "^1.0.0"
},
"autoload": {
"psr-4": {
@@ -107,6 +107,28 @@
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
},
"flarum-cli": {
"excludeScaffolding": [
"LICENSE.md",
"js/tsconfig.json",
"js/webpack.config.js"
],
"modules": {
"backendTesting": true,
"js": true,
"gitConf": true,
"githubActions": true,
"prettier": true,
"typescript": true,
"bundlewatch": true,
"editorConfig": true,
"styleci": true,
"admin": true,
"forum": true,
"jsCommon": true,
"css": true
}
}
},
"scripts": {

View File

@@ -1,2 +1,2 @@
export * from './src/common';
export * from './src/forum';
export * from './src/admin';

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,3 +1,13 @@
import * as Extend from "./extend/index";
import app from "./app";
import 'expose-loader?exposes=$,jQuery!jquery';
import 'expose-loader?exposes=m!mithril';
import 'expose-loader?exposes=dayjs!dayjs';
import 'bootstrap/js/affix';
import 'bootstrap/js/dropdown';
import 'bootstrap/js/modal';
import 'bootstrap/js/tooltip';
import 'bootstrap/js/transition';
import 'jquery.hotkeys/jquery.hotkeys';
import * as Extend from './extend/index';
import app from './app';
export { Extend, app };
import './utils/arrayFlatPolyfill';

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';

View File

@@ -10,7 +10,7 @@ export declare function makeRouteHelpers(app: ForumApplication): {
/**
* Generate a URL to a discussion.
*/
discussion: (discussion: Discussion, near: number) => string;
discussion: (discussion: Discussion, near?: number | undefined) => string;
/**
* Generate a URL to a post.
*/

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

@@ -1,2 +1,2 @@
export * from './src/common';
export * from './src/admin';
export * from './src/forum';

View File

@@ -1,51 +1,52 @@
{
"private": true,
"name": "@flarum/core",
"prettier": "@flarum/prettier-config",
"dependencies": {
"@askvortsov/rich-icu-message-formatter": "^0.2.1",
"@ultraq/icu-message-formatter": "^0.12.0",
"bootstrap": "^3.4.1",
"clsx": "^1.1.1",
"color-thief-browser": "^2.0.2",
"dayjs": "^1.10.7",
"focus-trap": "^6.7.1",
"jquery": "^3.6.0",
"jquery.hotkeys": "^0.1.0",
"mithril": "^2.0.4",
"nanoid": "^3.1.30",
"punycode": "^2.1.1",
"textarea-caret": "^3.1.0",
"throttle-debounce": "^3.0.1"
},
"devDependencies": {
"@flarum/prettier-config": "^1.0.0",
"@types/jquery": "^3.5.10",
"@types/mithril": "^2.0.8",
"@types/punycode": "^2.1.0",
"@types/textarea-caret": "^3.0.1",
"bundlewatch": "^0.3.2",
"cross-env": "^7.0.3",
"expose-loader": "^3.1.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",
"webpack": "^5.65.0",
"webpack-cli": "^4.9.1",
"webpack-merge": "^5.8.0"
},
"scripts": {
"dev": "webpack --mode development --watch",
"build": "webpack --mode production",
"analyze": "cross-env ANALYZER=true npm 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 && cp -r src/@types dist-typings/@types && tsc",
"check-typings": "tsc --noEmit --emitDeclarationOnly false",
"check-typings-coverage": "typescript-coverage-report"
},
"packageManager": "yarn@3.1.1"
"private": true,
"name": "@flarum/core",
"prettier": "@flarum/prettier-config",
"dependencies": {
"@askvortsov/rich-icu-message-formatter": "^0.2.4",
"@ultraq/icu-message-formatter": "^0.12.0",
"bootstrap": "^3.4.1",
"clsx": "^1.1.1",
"color-thief-browser": "^2.0.2",
"dayjs": "^1.10.7",
"focus-trap": "^6.7.1",
"jquery": "^3.6.0",
"jquery.hotkeys": "^0.1.0",
"mithril": "^2.0.4",
"nanoid": "^3.1.30",
"punycode": "^2.1.1",
"textarea-caret": "^3.1.0",
"throttle-debounce": "^3.0.1"
},
"devDependencies": {
"@flarum/prettier-config": "^1.0.0",
"@types/jquery": "^3.5.10",
"@types/mithril": "^2.0.8",
"@types/punycode": "^2.1.0",
"@types/textarea-caret": "^3.0.1",
"bundlewatch": "^0.3.2",
"cross-env": "^7.0.3",
"expose-loader": "^3.1.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",
"webpack": "^5.65.0",
"webpack-cli": "^4.9.1",
"webpack-merge": "^5.8.0"
},
"scripts": {
"dev": "webpack --mode development --watch",
"build": "webpack --mode production",
"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": "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"
},
"packageManager": "yarn@3.1.1"
}

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

@@ -18,7 +18,7 @@ export default class EditCustomCssModal extends SettingsModal {
})}
</p>,
<div className="Form-group">
<textarea className="FormControl" rows="30" bidi={this.setting('custom_less')} />
<textarea className="FormControl" rows="30" bidi={this.setting('custom_less')} spellcheck={false} />
</div>,
];
}

View File

@@ -547,7 +547,11 @@ export default class Application {
console.group(`${method} ${url} ${status}`);
console.error(...(formattedErrors || [e]));
if (formattedErrors.length) {
console.error(...formattedErrors);
} else {
console.error(e);
}
console.groupEnd();
}

View File

@@ -1,5 +1,6 @@
import app from '../common/app';
import { FlarumRequestOptions } from './Application';
import { fireDeprecationWarning } from './helpers/fireDebugWarning';
import Store, { ApiPayloadSingle, ApiResponseSingle, MetaInformation } from './Store';
export interface ModelIdentifier {
@@ -111,6 +112,19 @@ export default abstract class Model {
if ('attributes' in data) {
this.data.attributes ||= {};
// @deprecated
// Filter out relationships that got in by accident.
for (const key in data.attributes) {
const val = data.attributes[key];
if (val && val instanceof Model) {
fireDeprecationWarning('Providing models as attributes to `Model.pushData()` or `Model.pushAttributes()` is deprecated.', '3249');
delete data.attributes[key];
data.relationships ||= {};
data.relationships[key] = { data: Model.getIdentifier(val) };
}
}
Object.assign(this.data.attributes, data.attributes);
}

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,7 @@ export default class ModalManager extends Component<IModalManagerAttrs> {
// e.g. via ESC key or a click on the modal backdrop.
this.$().on('hidden.bs.modal', this.attrs.state.close.bind(this.attrs.state));
this.focusTrap = createFocusTrap(this.element as HTMLElement);
this.focusTrap = createFocusTrap(this.element as HTMLElement, { allowOutsideClick: true });
}
onupdate(vnode: Mithril.VnodeDOM<IModalManagerAttrs, this>): void {

View File

@@ -22,7 +22,7 @@ export default class RequestErrorModal<CustomAttrs extends IRequestErrorModalAtt
// If the error is already formatted, just add line endings;
// else try to parse it as JSON and stringify it with indentation
if (formattedError) {
if (formattedError.length) {
responseText = formattedError.join('\n\n');
} else if (error.response) {
responseText = JSON.stringify(error.response, null, 2);

View File

@@ -30,6 +30,7 @@ import './utils/arrayFlatPolyfill';
const tooltipGen = $.fn.tooltip;
// Remove in a future version of Flarum.
// @ts-ignore
$.fn.tooltip = function (options, caller) {
// Show a warning when `$.tooltip` is used outside of the Tooltip component.
// This functionality is deprecated and should not be used.

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

@@ -138,7 +138,7 @@ export default class Post extends Component {
classes.push('Post--by-actor');
}
if (user?.id() === discussion.attribute('startUserId')) {
if (user && user?.id() === discussion.attribute('startUserId')) {
classes.push('Post--by-start-user');
}

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

@@ -34,7 +34,7 @@ export function makeRouteHelpers(app: ForumApplication) {
/**
* Generate a URL to a discussion.
*/
discussion: (discussion: Discussion, near: number) => {
discussion: (discussion: Discussion, near?: number) => {
return app.route(near && near !== 1 ? 'discussion.near' : 'discussion', {
id: discussion.slug(),
near: near && near !== 1 ? near : undefined,

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());
});
}

View File

@@ -213,7 +213,7 @@ export default {
* @return {Promise<void>}
*/
hideAction() {
this.pushAttributes({ hiddenAt: new Date(), hiddenUser: app.session.user });
this.pushData({ attributes: { hiddenAt: new Date() }, relationships: { hiddenUser: app.session.user } });
return this.save({ isHidden: true });
},
@@ -224,7 +224,7 @@ export default {
* @return {Promise<void>}
*/
restoreAction() {
this.pushAttributes({ hiddenAt: null, hiddenUser: null });
this.pushData({ attributes: { hiddenAt: null }, relationships: { hiddenUser: null } });
return this.save({ isHidden: false });
},

View File

@@ -151,7 +151,7 @@ export default {
*/
hideAction() {
if (!confirm(extractText(app.translator.trans('core.forum.post_controls.hide_confirmation')))) return;
this.pushAttributes({ hiddenAt: new Date(), hiddenUser: app.session.user });
this.pushData({ attributes: { hiddenAt: new Date() }, relationships: { hiddenUser: app.session.user } });
return this.save({ isHidden: true }).then(() => m.redraw());
},
@@ -162,7 +162,7 @@ export default {
* @return {Promise<void>}
*/
restoreAction() {
this.pushAttributes({ hiddenAt: null, hiddenUser: null });
this.pushData({ attributes: { hiddenAt: null }, relationships: { hiddenUser: null } });
return this.save({ isHidden: false }).then(() => m.redraw());
},

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-dev';
const VERSION = '1.3.0-dev';
/**
* The IoC container for the Flarum application.

View File

@@ -159,6 +159,9 @@ class InstalledSite implements SiteInterface
protected function getIlluminateConfig()
{
return new ConfigRepository([
'app' => [
'timezone' => 'UTC'
],
'view' => [
'paths' => [],
'compiled' => $this->paths->storage.'/views',
@@ -174,7 +177,8 @@ class InstalledSite implements SiteInterface
protected function registerLogger(Container $container)
{
$logPath = $this->paths->storage.'/logs/flarum.log';
$handler = new RotatingFileHandler($logPath, 0, Logger::INFO);
$logLevel = $this->config->inDebugMode() ? Logger::DEBUG : Logger::INFO;
$handler = new RotatingFileHandler($logPath, 0, $logLevel);
$handler->setFormatter(new LineFormatter(null, null, true, true));
$container->instance('log', new Logger('flarum', [$handler]));

View File

@@ -0,0 +1,33 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\Mail;
use Illuminate\Mail\Transport\LogTransport;
use Swift_Mime_SimpleMessage;
class FlarumLogTransport extends LogTransport
{
/**
* {@inheritdoc}
*
* @return int
*/
public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null)
{
$this->beforeSendPerformed($message);
// Overriden to use info, so the log driver works in non-debug mode.
$this->logger->info($this->getMimeEntityString($message));
$this->sendPerformed($message);
return $this->numberOfRecipients($message);
}
}

View File

@@ -11,7 +11,6 @@ namespace Flarum\Mail;
use Flarum\Settings\SettingsRepositoryInterface;
use Illuminate\Contracts\Validation\Factory;
use Illuminate\Mail\Transport\LogTransport;
use Illuminate\Support\MessageBag;
use Psr\Log\LoggerInterface;
use Swift_Transport;
@@ -45,6 +44,6 @@ class LogDriver implements DriverInterface
public function buildTransport(SettingsRepositoryInterface $settings): Swift_Transport
{
return new LogTransport($this->logger);
return new FlarumLogTransport($this->logger);
}
}

0
tests/fixtures/.gitkeep vendored Normal file
View File

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>

0
tests/unit/.gitkeep Normal file
View File