mirror of
https://github.com/flarum/framework.git
synced 2025-04-13 22:56:37 +08:00
Merge remote-tracking branch 'extensions_pusher/REWRITE'
This commit is contained in:
commit
fecb58dec5
19
extensions/pusher/.editorconfig
Normal file
19
extensions/pusher/.editorconfig
Normal file
@ -0,0 +1,19 @@
|
||||
# EditorConfig helps developers define and maintain consistent
|
||||
# coding styles between different editors and IDEs
|
||||
# editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.{diff,md}]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.{php,xml,json}]
|
||||
indent_size = 4
|
18
extensions/pusher/.gitattributes
vendored
Normal file
18
extensions/pusher/.gitattributes
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
.gitattributes export-ignore
|
||||
.gitignore export-ignore
|
||||
.gitmodules export-ignore
|
||||
.github export-ignore
|
||||
.travis export-ignore
|
||||
.travis.yml export-ignore
|
||||
.editorconfig export-ignore
|
||||
.styleci.yml export-ignore
|
||||
|
||||
phpunit.xml export-ignore
|
||||
tests export-ignore
|
||||
|
||||
js/dist/* -diff
|
||||
js/dist/* linguist-generated
|
||||
js/dist-typings/* linguist-generated
|
||||
js/yarn.lock -diff
|
||||
|
||||
* text=auto eol=lf
|
15
extensions/pusher/.github/workflows/backend.yml
vendored
Normal file
15
extensions/pusher/.github/workflows/backend.yml
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
name: Pusher 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: false
|
||||
|
||||
backend_directory: .
|
21
extensions/pusher/.github/workflows/frontend.yml
vendored
Normal file
21
extensions/pusher/.github/workflows/frontend.yml
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
name: Pusher 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: false
|
||||
enable_prettier: true
|
||||
enable_typescript: true
|
||||
|
||||
frontend_directory: ./js
|
||||
main_git_branch: master
|
||||
|
||||
secrets:
|
||||
bundlewatch_github_token: ${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }}
|
12
extensions/pusher/.gitignore
vendored
Normal file
12
extensions/pusher/.gitignore
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
/vendor
|
||||
composer.lock
|
||||
composer.phar
|
||||
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
tests/.phpunit.result.cache
|
||||
/tests/integration/tmp
|
||||
.vagrant
|
||||
.idea/*
|
||||
.vscode
|
||||
js/coverage-ts
|
14
extensions/pusher/.styleci.yml
Normal file
14
extensions/pusher/.styleci.yml
Normal file
@ -0,0 +1,14 @@
|
||||
preset: recommended
|
||||
|
||||
enabled:
|
||||
- logical_not_operators_with_successor_space
|
||||
|
||||
disabled:
|
||||
- align_double_arrow
|
||||
- blank_line_after_opening_tag
|
||||
- multiline_array_trailing_comma
|
||||
- new_with_braces
|
||||
- phpdoc_align
|
||||
- phpdoc_order
|
||||
- phpdoc_separation
|
||||
- phpdoc_types
|
65
extensions/pusher/CHANGELOG.md
Normal file
65
extensions/pusher/CHANGELOG.md
Normal file
@ -0,0 +1,65 @@
|
||||
# Changelog
|
||||
|
||||
## [1.2.0](https://github.com/flarum/pusher/compare/v1.1.0...v1.2.0)
|
||||
|
||||
### Changed
|
||||
- Convert to TypeScript (https://github.com/flarum/pusher/pull/34).
|
||||
- Replace jQuery with vanilla JS (https://github.com/flarum/pusher/pull/35).
|
||||
|
||||
### Fixed
|
||||
- Discussion list pagination breaks when clicking on the update button (https://github.com/flarum/pusher/pull/33).
|
||||
|
||||
## [1.1.0](https://github.com/flarum/pusher/compare/v1.0.0...v1.1.0)
|
||||
|
||||
No changes.
|
||||
|
||||
## [1.0.0](https://github.com/flarum/pusher/compare/v0.1.0-beta.16...v1.0.0)
|
||||
|
||||
### Added
|
||||
- Make non public discussions realtime (https://github.com/flarum/pusher/pull/17)
|
||||
|
||||
### Changed
|
||||
- Compatibility with Flarum v1.0.0.
|
||||
|
||||
## [0.1.0-beta.16](https://github.com/flarum/pusher/compare/v0.1.0-beta.15...v0.1.0-beta.16)
|
||||
|
||||
### Changed
|
||||
- Moved locale files from translation pack to extension (https://github.com/flarum/pusher/pull/26)
|
||||
|
||||
## [0.1.0-beta.15](https://github.com/flarum/pusher/compare/v0.1.0-beta.14.1...v0.1.0-beta.15)
|
||||
|
||||
### Changed
|
||||
- Updated composer.json and admin javascript for new admin area.
|
||||
- Updated to use newest extenders.
|
||||
|
||||
## [0.1.0-beta.14.1](https://github.com/flarum/pusher/compare/v0.1.0-beta.14...v0.1.0-beta.14.1)
|
||||
|
||||
### Fixed
|
||||
- Children were incorrectly passed to show update highlight
|
||||
- Update discussion list caused an error (#27)
|
||||
|
||||
## [0.1.0-beta.14](https://github.com/flarum/pusher/compare/v0.1.0-beta.13...v0.1.0-beta.14)
|
||||
|
||||
### Changed
|
||||
- Updated mithril to version 2
|
||||
- Load language strings correctly on en-/disable
|
||||
- Updated JS dependencies
|
||||
|
||||
### Fixed
|
||||
- Publish no events for tags when flarum/tags isn't installed (#25)
|
||||
|
||||
## [0.1.0-beta.13](https://github.com/flarum/pusher/compare/v0.1.0-beta.12...v0.1.0-beta.13)
|
||||
|
||||
### Changed
|
||||
- Use different CDN for loading Pusher JS library (#20)
|
||||
- Updated JS dependencies
|
||||
|
||||
## [0.1.0-beta.9](https://github.com/flarum/pusher/compare/v0.1.0-beta.8.1...v0.1.0-beta.9)
|
||||
|
||||
### Changed
|
||||
- Replace event subscribers (that resolve services too early) with listeners ([da0f0af](https://github.com/flarum/pusher/commit/da0f0afb24bae39535b4beaf750f311c403adef1) and [28a70ff](https://github.com/flarum/pusher/commit/28a70ff074014bc75acee6eff7a74faecf5ae341))
|
||||
|
||||
## [0.1.0-beta.8.1](https://github.com/flarum/pusher/compare/v0.1.0-beta.8...v0.1.0-beta.8.1)
|
||||
|
||||
### Fixed
|
||||
- Fix broken functionality ([00b127c](https://github.com/flarum/pusher/commit/00b127c576e5554bc04b491ec47ae57f8525fac3))
|
22
extensions/pusher/LICENSE
Normal file
22
extensions/pusher/LICENSE
Normal file
@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2019-2021 Stichting Flarum (Flarum Foundation)
|
||||
Copyright (c) 2014-2019 Toby Zerner (toby.zerner@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
64
extensions/pusher/composer.json
Normal file
64
extensions/pusher/composer.json
Normal file
@ -0,0 +1,64 @@
|
||||
{
|
||||
"name": "flarum/pusher",
|
||||
"description": "See new discussions and posts in real-time using Pusher.",
|
||||
"type": "flarum-extension",
|
||||
"keywords": [
|
||||
"discussion"
|
||||
],
|
||||
"license": "MIT",
|
||||
"support": {
|
||||
"issues": "https://github.com/flarum/core/issues",
|
||||
"source": "https://github.com/flarum/pusher",
|
||||
"forum": "https://discuss.flarum.org"
|
||||
},
|
||||
"homepage": "https://flarum.org",
|
||||
"funding": [
|
||||
{
|
||||
"type": "website",
|
||||
"url": "https://flarum.org/donate/"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"flarum/core": "^1.2",
|
||||
"pusher/pusher-php-server": "^2.2"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Flarum\\Pusher\\": "src/"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.x-dev"
|
||||
},
|
||||
"flarum-extension": {
|
||||
"title": "Pusher",
|
||||
"category": "feature",
|
||||
"icon": {
|
||||
"image": "icon.png",
|
||||
"backgroundSize": "46% 63%",
|
||||
"backgroundPosition": "center",
|
||||
"backgroundRepeat": "no-repeat",
|
||||
"backgroundColor": "#40bad8",
|
||||
"color": "#fff"
|
||||
}
|
||||
},
|
||||
"flarum-cli": {
|
||||
"modules": {
|
||||
"admin": true,
|
||||
"forum": true,
|
||||
"js": true,
|
||||
"jsCommon": false,
|
||||
"css": true,
|
||||
"gitConf": true,
|
||||
"githubActions": true,
|
||||
"prettier": true,
|
||||
"typescript": true,
|
||||
"bundlewatch": false,
|
||||
"backendTesting": false,
|
||||
"editorConfig": true,
|
||||
"styleci": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
42
extensions/pusher/extend.php
Normal file
42
extensions/pusher/extend.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?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.
|
||||
*/
|
||||
|
||||
use Flarum\Extend;
|
||||
use Flarum\Post\Event\Posted;
|
||||
use Flarum\Pusher\Api\Controller\AuthController;
|
||||
use Flarum\Pusher\Listener;
|
||||
use Flarum\Pusher\Provider\PusherProvider;
|
||||
use Flarum\Pusher\PusherNotificationDriver;
|
||||
|
||||
return [
|
||||
(new Extend\Frontend('forum'))
|
||||
->js(__DIR__.'/js/dist/forum.js')
|
||||
->css(__DIR__.'/less/forum.less'),
|
||||
|
||||
(new Extend\Frontend('admin'))
|
||||
->js(__DIR__.'/js/dist/admin.js'),
|
||||
|
||||
(new Extend\Routes('api'))
|
||||
->post('/pusher/auth', 'pusher.auth', AuthController::class),
|
||||
|
||||
new Extend\Locales(__DIR__.'/locale'),
|
||||
|
||||
(new Extend\Notification())
|
||||
->driver('pusher', PusherNotificationDriver::class),
|
||||
|
||||
(new Extend\Settings())
|
||||
->serializeToForum('pusherKey', 'flarum-pusher.app_key')
|
||||
->serializeToForum('pusherCluster', 'flarum-pusher.app_cluster'),
|
||||
|
||||
(new Extend\Event())
|
||||
->listen(Posted::class, Listener\PushNewPost::class),
|
||||
|
||||
(new Extend\ServiceProvider())
|
||||
->register(PusherProvider::class),
|
||||
];
|
BIN
extensions/pusher/icon.png
Normal file
BIN
extensions/pusher/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
9
extensions/pusher/js/.gitignore
vendored
Normal file
9
extensions/pusher/js/.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
.pnp.*
|
||||
.yarn/*
|
||||
!.yarn/patches
|
||||
!.yarn/plugins
|
||||
!.yarn/releases
|
||||
!.yarn/sdks
|
||||
!.yarn/versions
|
||||
|
||||
node_modules
|
1
extensions/pusher/js/admin.ts
Normal file
1
extensions/pusher/js/admin.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './src/admin';
|
1
extensions/pusher/js/dist-typings/admin/index.d.ts
vendored
Normal file
1
extensions/pusher/js/dist-typings/admin/index.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
export {};
|
8
extensions/pusher/js/dist-typings/forum/index.d.ts
vendored
Normal file
8
extensions/pusher/js/dist-typings/forum/index.d.ts
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
import * as PusherTypes from 'pusher-js';
|
||||
export declare type PusherBinding = {
|
||||
channels: {
|
||||
main: PusherTypes.Channel;
|
||||
user: PusherTypes.Channel | null;
|
||||
};
|
||||
pusher: PusherTypes.default;
|
||||
};
|
2
extensions/pusher/js/dist/admin.js
generated
vendored
Normal file
2
extensions/pusher/js/dist/admin.js
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
(()=>{var e={n:t=>{var r=t&&t.__esModule?()=>t.default:()=>t;return e.d(r,{a:r}),r},d:(t,r)=>{for(var a in r)e.o(r,a)&&!e.o(t,a)&&Object.defineProperty(t,a,{enumerable:!0,get:r[a]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};(()=>{"use strict";e.r(t);const r=flarum.core.compat["admin/app"];var a=e.n(r);a().initializers.add("flarum-pusher",(function(){a().extensionData.for("flarum-pusher").registerSetting({setting:"flarum-pusher.app_id",label:a().translator.trans("flarum-pusher.admin.pusher_settings.app_id_label"),type:"text"},30).registerSetting({setting:"flarum-pusher.app_key",label:a().translator.trans("flarum-pusher.admin.pusher_settings.app_key_label"),type:"text"},20).registerSetting({setting:"flarum-pusher.app_secret",label:a().translator.trans("flarum-pusher.admin.pusher_settings.app_secret_label"),type:"text"},10).registerSetting({setting:"flarum-pusher.app_cluster",label:a().translator.trans("flarum-pusher.admin.pusher_settings.app_cluster_label"),type:"text"},0)}))})(),module.exports=t})();
|
||||
//# sourceMappingURL=admin.js.map
|
1
extensions/pusher/js/dist/admin.js.map
generated
vendored
Normal file
1
extensions/pusher/js/dist/admin.js.map
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"admin.js","mappings":"MACA,IAAIA,EAAsB,CCA1BA,EAAyBC,IACxB,IAAIC,EAASD,GAAUA,EAAOE,WAC7B,IAAOF,EAAiB,QACxB,IAAM,EAEP,OADAD,EAAoBI,EAAEF,EAAQ,CAAEG,EAAGH,IAC5BA,GCLRF,EAAwB,CAACM,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXP,EAAoBS,EAAEF,EAAYC,KAASR,EAAoBS,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,MCJ3ER,EAAwB,CAACc,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFf,EAAyBM,IACH,oBAAXa,QAA0BA,OAAOC,aAC1CV,OAAOC,eAAeL,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DX,OAAOC,eAAeL,EAAS,aAAc,CAAEe,OAAO,M,+BCLvD,MAAM,EAA+BC,OAAOC,KAAKC,OAAO,a,aCExDC,IAAAA,aAAAA,IAAqB,iBAAiB,WACpCA,IAAAA,cAAAA,IACO,iBACJC,gBACC,CACEC,QAAS,uBACTC,MAAOH,IAAAA,WAAAA,MAAqB,oDAC5BI,KAAM,QAER,IAEDH,gBACC,CACEC,QAAS,wBACTC,MAAOH,IAAAA,WAAAA,MAAqB,qDAC5BI,KAAM,QAER,IAEDH,gBACC,CACEC,QAAS,2BACTC,MAAOH,IAAAA,WAAAA,MAAqB,wDAC5BI,KAAM,QAER,IAEDH,gBACC,CACEC,QAAS,4BACTC,MAAOH,IAAAA,WAAAA,MAAqB,yDAC5BI,KAAM,QAER,O","sources":["webpack://@flarum/pusher/webpack/bootstrap","webpack://@flarum/pusher/webpack/runtime/compat get default export","webpack://@flarum/pusher/webpack/runtime/define property getters","webpack://@flarum/pusher/webpack/runtime/hasOwnProperty shorthand","webpack://@flarum/pusher/webpack/runtime/make namespace object","webpack://@flarum/pusher/external root \"flarum.core.compat['admin/app']\"","webpack://@flarum/pusher/./src/admin/index.ts"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['admin/app'];","import app from 'flarum/admin/app';\n\napp.initializers.add('flarum-pusher', () => {\n app.extensionData\n .for('flarum-pusher')\n .registerSetting(\n {\n setting: 'flarum-pusher.app_id',\n label: app.translator.trans('flarum-pusher.admin.pusher_settings.app_id_label'),\n type: 'text',\n },\n 30\n )\n .registerSetting(\n {\n setting: 'flarum-pusher.app_key',\n label: app.translator.trans('flarum-pusher.admin.pusher_settings.app_key_label'),\n type: 'text',\n },\n 20\n )\n .registerSetting(\n {\n setting: 'flarum-pusher.app_secret',\n label: app.translator.trans('flarum-pusher.admin.pusher_settings.app_secret_label'),\n type: 'text',\n },\n 10\n )\n .registerSetting(\n {\n setting: 'flarum-pusher.app_cluster',\n label: app.translator.trans('flarum-pusher.admin.pusher_settings.app_cluster_label'),\n type: 'text',\n },\n 0\n );\n});\n"],"names":["__webpack_require__","module","getter","__esModule","d","a","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","flarum","core","compat","app","registerSetting","setting","label","type"],"sourceRoot":""}
|
2
extensions/pusher/js/dist/forum.js
generated
vendored
Normal file
2
extensions/pusher/js/dist/forum.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
1
extensions/pusher/js/dist/forum.js.map
generated
vendored
Normal file
1
extensions/pusher/js/dist/forum.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
1
extensions/pusher/js/forum.ts
Normal file
1
extensions/pusher/js/forum.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './src/forum';
|
27
extensions/pusher/js/package.json
Normal file
27
extensions/pusher/js/package.json
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "@flarum/pusher",
|
||||
"prettier": "@flarum/prettier-config",
|
||||
"scripts": {
|
||||
"dev": "webpack --mode development --watch",
|
||||
"build": "webpack --mode production",
|
||||
"analyze": "cross-env ANALYZER=true yarn build",
|
||||
"format": "prettier --write src",
|
||||
"format-check": "prettier --check src",
|
||||
"clean-typings": "npx rimraf dist-typings && mkdir dist-typings",
|
||||
"build-typings": "npm run clean-typings && tsc && [ -e src/@types ] && cp -r src/@types dist-typings/@types",
|
||||
"check-typings": "tsc --noEmit --emitDeclarationOnly false",
|
||||
"check-typings-coverage": "typescript-coverage-report"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@flarum/prettier-config": "^1.0.0",
|
||||
"@types/pusher-js": "^5.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"
|
||||
}
|
||||
}
|
15
extensions/pusher/js/shims.d.ts
vendored
Normal file
15
extensions/pusher/js/shims.d.ts
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
import * as PusherTypes from 'pusher-js';
|
||||
|
||||
declare module 'flarum/forum/ForumApplication' {
|
||||
export default interface ForumApplication {
|
||||
pusher: Promise<{
|
||||
channels: {
|
||||
main: PusherTypes.Channel;
|
||||
user: PusherTypes.Channel | null;
|
||||
};
|
||||
pusher: PusherTypes.default;
|
||||
}>;
|
||||
|
||||
pushedUpdates: Array<any>;
|
||||
}
|
||||
}
|
38
extensions/pusher/js/src/admin/index.ts
Normal file
38
extensions/pusher/js/src/admin/index.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import app from 'flarum/admin/app';
|
||||
|
||||
app.initializers.add('flarum-pusher', () => {
|
||||
app.extensionData
|
||||
.for('flarum-pusher')
|
||||
.registerSetting(
|
||||
{
|
||||
setting: 'flarum-pusher.app_id',
|
||||
label: app.translator.trans('flarum-pusher.admin.pusher_settings.app_id_label'),
|
||||
type: 'text',
|
||||
},
|
||||
30
|
||||
)
|
||||
.registerSetting(
|
||||
{
|
||||
setting: 'flarum-pusher.app_key',
|
||||
label: app.translator.trans('flarum-pusher.admin.pusher_settings.app_key_label'),
|
||||
type: 'text',
|
||||
},
|
||||
20
|
||||
)
|
||||
.registerSetting(
|
||||
{
|
||||
setting: 'flarum-pusher.app_secret',
|
||||
label: app.translator.trans('flarum-pusher.admin.pusher_settings.app_secret_label'),
|
||||
type: 'text',
|
||||
},
|
||||
10
|
||||
)
|
||||
.registerSetting(
|
||||
{
|
||||
setting: 'flarum-pusher.app_cluster',
|
||||
label: app.translator.trans('flarum-pusher.admin.pusher_settings.app_cluster_label'),
|
||||
type: 'text',
|
||||
},
|
||||
0
|
||||
);
|
||||
});
|
160
extensions/pusher/js/src/forum/index.ts
Normal file
160
extensions/pusher/js/src/forum/index.ts
Normal file
@ -0,0 +1,160 @@
|
||||
import * as PusherTypes from 'pusher-js';
|
||||
import app from 'flarum/forum/app';
|
||||
import { extend } from 'flarum/common/extend';
|
||||
import DiscussionList from 'flarum/forum/components/DiscussionList';
|
||||
import DiscussionPage from 'flarum/forum/components/DiscussionPage';
|
||||
import IndexPage from 'flarum/forum/components/IndexPage';
|
||||
import Button from 'flarum/common/components/Button';
|
||||
import ItemList from 'flarum/common/utils/ItemList';
|
||||
import { Children, VnodeDOM } from 'mithril';
|
||||
|
||||
export type PusherBinding = {
|
||||
channels: {
|
||||
main: PusherTypes.Channel;
|
||||
user: PusherTypes.Channel | null;
|
||||
};
|
||||
pusher: PusherTypes.default;
|
||||
};
|
||||
|
||||
app.initializers.add('flarum-pusher', () => {
|
||||
app.pusher = (async () => {
|
||||
// @ts-expect-error
|
||||
await import('//cdn.jsdelivr.net/npm/pusher-js@7.0.3/dist/web/pusher.min.js' /* webpackIgnore: true, webpackPrefetch: true */);
|
||||
|
||||
// @ts-expect-error Imported dynamically
|
||||
const socket: PusherTypes.default = new Pusher(app.forum.attribute('pusherKey'), {
|
||||
authEndpoint: `${app.forum.attribute('apiUrl')}/pusher/auth`,
|
||||
cluster: app.forum.attribute('pusherCluster'),
|
||||
auth: {
|
||||
headers: {
|
||||
'X-CSRF-Token': app.session.csrfToken,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
channels: {
|
||||
main: socket.subscribe('public'),
|
||||
user: app.session.user ? socket.subscribe(`private-user${app.session.user.id()}`) : null,
|
||||
},
|
||||
pusher: socket,
|
||||
};
|
||||
})();
|
||||
|
||||
app.pushedUpdates = [];
|
||||
|
||||
extend(DiscussionList.prototype, 'oncreate', function () {
|
||||
app.pusher.then((binding: PusherBinding) => {
|
||||
const pusher = binding.pusher;
|
||||
|
||||
pusher.bind('newPost', (data: { tagIds: number[]; discussionId: number }) => {
|
||||
const params = app.discussions.getParams();
|
||||
|
||||
if (!params.q && !params.sort && !params.filter) {
|
||||
if (params.tags) {
|
||||
const tag = app.store.getBy('tags', 'slug', params.tags);
|
||||
|
||||
if (!data.tagIds.includes(tag.id())) return;
|
||||
}
|
||||
|
||||
const id = String(data.discussionId);
|
||||
|
||||
if ((!app.current.get('discussion') || id !== app.current.get('discussion').id()) && app.pushedUpdates.indexOf(id) === -1) {
|
||||
app.pushedUpdates.push(id);
|
||||
|
||||
if (app.current.matches(IndexPage)) {
|
||||
app.setTitleCount(app.pushedUpdates.length);
|
||||
}
|
||||
|
||||
m.redraw();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
extend(DiscussionList.prototype, 'onremove', function () {
|
||||
app.pusher.then((binding: PusherBinding) => {
|
||||
binding.pusher.unbind('newPost');
|
||||
});
|
||||
});
|
||||
|
||||
extend(DiscussionList.prototype, 'view', function (this: DiscussionList, vdom: VnodeDOM) {
|
||||
if (app.pushedUpdates) {
|
||||
const count = app.pushedUpdates.length;
|
||||
|
||||
if (count) {
|
||||
vdom.children.unshift(
|
||||
Button.component(
|
||||
{
|
||||
className: 'Button Button--block DiscussionList-update',
|
||||
onclick: () => {
|
||||
this.attrs.state.refresh().then(() => {
|
||||
this.loadingUpdated = false;
|
||||
app.pushedUpdates = [];
|
||||
app.setTitleCount(0);
|
||||
m.redraw();
|
||||
});
|
||||
this.loadingUpdated = true;
|
||||
},
|
||||
loading: this.loadingUpdated,
|
||||
},
|
||||
app.translator.trans('flarum-pusher.forum.discussion_list.show_updates_text', { count })
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
extend(DiscussionPage.prototype, 'oncreate', function (this: DiscussionPage) {
|
||||
app.pusher.then((binding: PusherBinding) => {
|
||||
const pusher = binding.pusher;
|
||||
|
||||
pusher.bind('newPost', (data: { discussionId: number }) => {
|
||||
const id = String(data.discussionId);
|
||||
const discussionId = this.discussion?.id();
|
||||
|
||||
if (this.discussion && discussionId === id && this.stream) {
|
||||
const oldCount = this.discussion.commentCount() ?? 0;
|
||||
|
||||
app.store.find('discussions', discussionId).then(() => {
|
||||
this.stream?.update().then(m.redraw);
|
||||
|
||||
if (!document.hasFocus()) {
|
||||
app.setTitleCount(Math.max(0, (this.discussion?.commentCount() ?? 0) - oldCount));
|
||||
|
||||
window.addEventListener('focus', () => app.setTitleCount(0), { once: true });
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
extend(DiscussionPage.prototype, 'onremove', function () {
|
||||
app.pusher.then((binding: PusherBinding) => {
|
||||
binding.pusher.unbind('newPost');
|
||||
});
|
||||
});
|
||||
|
||||
extend(IndexPage.prototype, 'actionItems', (items: ItemList<Children>) => {
|
||||
items.remove('refresh');
|
||||
});
|
||||
|
||||
app.pusher.then((binding: PusherBinding) => {
|
||||
const channels = binding.channels;
|
||||
|
||||
if (channels.user) {
|
||||
channels.user.bind('notification', () => {
|
||||
if (app.session.user) {
|
||||
app.session.user.pushAttributes({
|
||||
unreadNotificationCount: app.session.user.unreadNotificationCount() ?? 0 + 1,
|
||||
newNotificationCount: app.session.user.newNotificationCount() ?? 0 + 1,
|
||||
});
|
||||
}
|
||||
app.notifications.clear();
|
||||
m.redraw();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
16
extensions/pusher/js/tsconfig.json
Normal file
16
extensions/pusher/js/tsconfig.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
// Use Flarum's tsconfig as a starting point
|
||||
"extends": "flarum-tsconfig",
|
||||
// This will match all .ts, .tsx, .d.ts, .js, .jsx files in your `src` folder
|
||||
// and also tells your Typescript server to read core's global typings for
|
||||
// access to `dayjs` and `$` in the global namespace.
|
||||
"include": ["src/**/*", "../vendor/flarum/core/js/dist-typings/@types/**/*", "@types/**/*"],
|
||||
"compilerOptions": {
|
||||
// This will output typings to `dist-typings`
|
||||
"declarationDir": "./dist-typings",
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"flarum/*": ["../vendor/flarum/core/js/dist-typings/*"]
|
||||
}
|
||||
}
|
||||
}
|
1
extensions/pusher/js/webpack.config.js
Normal file
1
extensions/pusher/js/webpack.config.js
Normal file
@ -0,0 +1 @@
|
||||
module.exports = require('flarum-webpack-config')();
|
2887
extensions/pusher/js/yarn.lock
Normal file
2887
extensions/pusher/js/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
0
extensions/pusher/less/admin.less
Normal file
0
extensions/pusher/less/admin.less
Normal file
9
extensions/pusher/less/forum.less
Normal file
9
extensions/pusher/less/forum.less
Normal file
@ -0,0 +1,9 @@
|
||||
.DiscussionList-update {
|
||||
.Button--color(@alert-color, @alert-bg);
|
||||
margin-bottom: 5px;
|
||||
|
||||
.DiscussionPage & {
|
||||
border-radius: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
23
extensions/pusher/locale/en.yml
Normal file
23
extensions/pusher/locale/en.yml
Normal file
@ -0,0 +1,23 @@
|
||||
flarum-pusher:
|
||||
|
||||
##
|
||||
# UNIQUE KEYS - The following keys are used in only one location each.
|
||||
##
|
||||
|
||||
# Translations in this namespace are used by the admin interface.
|
||||
admin:
|
||||
|
||||
# These translations are used in the Pusher Settings modal dialog.
|
||||
pusher_settings:
|
||||
app_cluster_label: Cluster
|
||||
app_id_label: App ID
|
||||
app_key_label: App Key
|
||||
app_secret_label: App Secret
|
||||
title: Pusher Settings
|
||||
|
||||
# Translations in this namespace are used by the admin interface.
|
||||
forum:
|
||||
|
||||
# These translations are used in the discussion list.
|
||||
discussion_list:
|
||||
show_updates_text: "{count, plural, one {Show # updated discussion} other {Show # updated discussions}}"
|
61
extensions/pusher/src/Api/Controller/AuthController.php
Normal file
61
extensions/pusher/src/Api/Controller/AuthController.php
Normal file
@ -0,0 +1,61 @@
|
||||
<?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\Pusher\Api\Controller;
|
||||
|
||||
use Flarum\Http\RequestUtil;
|
||||
use Flarum\Settings\SettingsRepositoryInterface;
|
||||
use Illuminate\Support\Arr;
|
||||
use Laminas\Diactoros\Response\EmptyResponse;
|
||||
use Laminas\Diactoros\Response\JsonResponse;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
use Pusher;
|
||||
|
||||
class AuthController implements RequestHandlerInterface
|
||||
{
|
||||
/**
|
||||
* @var SettingsRepositoryInterface
|
||||
*/
|
||||
protected $settings;
|
||||
|
||||
/**
|
||||
* @param SettingsRepositoryInterface $settings
|
||||
*/
|
||||
public function __construct(SettingsRepositoryInterface $settings)
|
||||
{
|
||||
$this->settings = $settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ServerRequestInterface $request
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
$userChannel = 'private-user'.RequestUtil::getActor($request)->id;
|
||||
$body = $request->getParsedBody();
|
||||
|
||||
if (Arr::get($body, 'channel_name') === $userChannel) {
|
||||
$pusher = new Pusher(
|
||||
$this->settings->get('flarum-pusher.app_key'),
|
||||
$this->settings->get('flarum-pusher.app_secret'),
|
||||
$this->settings->get('flarum-pusher.app_id'),
|
||||
['cluster' => $this->settings->get('flarum-pusher.app_cluster')]
|
||||
);
|
||||
|
||||
$payload = json_decode($pusher->socket_auth($userChannel, Arr::get($body, 'socket_id')), true);
|
||||
|
||||
return new JsonResponse($payload);
|
||||
}
|
||||
|
||||
return new EmptyResponse(403);
|
||||
}
|
||||
}
|
65
extensions/pusher/src/Listener/PushNewPost.php
Normal file
65
extensions/pusher/src/Listener/PushNewPost.php
Normal file
@ -0,0 +1,65 @@
|
||||
<?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\Pusher\Listener;
|
||||
|
||||
use Flarum\Post\Event\Posted;
|
||||
use Flarum\User\Guest;
|
||||
use Flarum\User\User;
|
||||
use Illuminate\Support\Str;
|
||||
use Pusher;
|
||||
|
||||
class PushNewPost
|
||||
{
|
||||
/**
|
||||
* @var Pusher
|
||||
*/
|
||||
protected $pusher;
|
||||
|
||||
public function __construct(Pusher $pusher)
|
||||
{
|
||||
$this->pusher = $pusher;
|
||||
}
|
||||
|
||||
public function handle(Posted $event)
|
||||
{
|
||||
$channels = [];
|
||||
|
||||
if ($event->post->isVisibleTo(new Guest)) {
|
||||
$channels[] = 'public';
|
||||
} else {
|
||||
// Retrieve private channels, used for each user.
|
||||
$response = $this->pusher->get_channels([
|
||||
'filter_by_prefix' => 'private-user'
|
||||
]);
|
||||
|
||||
if (! $response) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($response->channels as $name => $channel) {
|
||||
$userId = Str::after($name, 'private-user');
|
||||
|
||||
if (($user = User::find($userId)) && $event->post->isVisibleTo($user)) {
|
||||
$channels[] = $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count($channels)) {
|
||||
$tags = $event->post->discussion->tags;
|
||||
|
||||
$this->pusher->trigger($channels, 'newPost', [
|
||||
'postId' => $event->post->id,
|
||||
'discussionId' => $event->post->discussion->id,
|
||||
'tagIds' => $tags ? $tags->pluck('id') : null
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
36
extensions/pusher/src/Provider/PusherProvider.php
Normal file
36
extensions/pusher/src/Provider/PusherProvider.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?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\Pusher\Provider;
|
||||
|
||||
use Flarum\Foundation\AbstractServiceProvider;
|
||||
use Flarum\Settings\SettingsRepositoryInterface;
|
||||
|
||||
class PusherProvider extends AbstractServiceProvider
|
||||
{
|
||||
public function register()
|
||||
{
|
||||
$this->app->bind(\Pusher::class, function () {
|
||||
$settings = $this->app->make(SettingsRepositoryInterface::class);
|
||||
|
||||
$options = [];
|
||||
|
||||
if ($cluster = $settings->get('flarum-pusher.app_cluster')) {
|
||||
$options['cluster'] = $cluster;
|
||||
}
|
||||
|
||||
return new \Pusher(
|
||||
$settings->get('flarum-pusher.app_key'),
|
||||
$settings->get('flarum-pusher.app_secret'),
|
||||
$settings->get('flarum-pusher.app_id'),
|
||||
$options
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
45
extensions/pusher/src/PusherNotificationDriver.php
Normal file
45
extensions/pusher/src/PusherNotificationDriver.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?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\Pusher;
|
||||
|
||||
use Flarum\Notification\Blueprint\BlueprintInterface;
|
||||
use Flarum\Notification\Driver\NotificationDriverInterface;
|
||||
use Illuminate\Contracts\Queue\Queue;
|
||||
|
||||
class PusherNotificationDriver implements NotificationDriverInterface
|
||||
{
|
||||
/**
|
||||
* @var Queue
|
||||
*/
|
||||
protected $queue;
|
||||
|
||||
public function __construct(Queue $queue)
|
||||
{
|
||||
$this->queue = $queue;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function send(BlueprintInterface $blueprint, array $users): void
|
||||
{
|
||||
if (count($users)) {
|
||||
$this->queue->push(new SendPusherNotificationsJob($blueprint, $users));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function registerType(string $blueprintClass, array $driversEnabledByDefault): void
|
||||
{
|
||||
// ...
|
||||
}
|
||||
}
|
43
extensions/pusher/src/SendPusherNotificationsJob.php
Normal file
43
extensions/pusher/src/SendPusherNotificationsJob.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?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\Pusher;
|
||||
|
||||
use Flarum\Notification\Blueprint\BlueprintInterface;
|
||||
use Flarum\Queue\AbstractJob;
|
||||
use Flarum\User\User;
|
||||
use Pusher;
|
||||
|
||||
class SendPusherNotificationsJob extends AbstractJob
|
||||
{
|
||||
/**
|
||||
* @var BlueprintInterface
|
||||
*/
|
||||
private $blueprint;
|
||||
|
||||
/**
|
||||
* @var User[]
|
||||
*/
|
||||
private $recipients;
|
||||
|
||||
public function __construct(BlueprintInterface $blueprint, array $recipients)
|
||||
{
|
||||
$this->blueprint = $blueprint;
|
||||
$this->recipients = $recipients;
|
||||
}
|
||||
|
||||
public function handle(Pusher $pusher)
|
||||
{
|
||||
foreach ($this->recipients as $user) {
|
||||
if ($user->shouldAlert($this->blueprint::getType())) {
|
||||
$pusher->trigger('private-user'.$user->id, 'notification', null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user