- Add command support for plugin management
- Optimize plugin management page layout
- Add email copy functionality for users
- Convert payment methods and Telegram Bot to plugin system
- Aligned user action buttons in dropdown for consistent UI.
- Added JSON and YAML support in plugin config form with Monaco Editor and resizable height.
- Improved formatTrafficSize to handle large numbers and prevent undefined units.
- Order detail now shows commission info when commission_status is 1 or 2.
- Unify protocol filter configuration to client.type.field (dot-path, three-segment) format, support strict whitelist mode
- Refactor AbstractProtocol and all protocol classes for more flexible and maintainable subscription delivery
- Change payment callback logic: use origin_url concatenation instead of return_url for more accurate redirects
- Add support for updating themes if a newer version is uploaded
- Hide config button for plugins without configuration items
- Auto refresh theme cache after panel update
- Fix issue where user used traffic cannot be set as a decimal
- Fix subscription issue for shadowrocket in v2board theme
- Add gift card redemption feature
- Resolve custom range selection issue in overview
- Allow log page size to be modified
- Add subscription path change notification
- Improve dynamic node rate feature
- Support markdown documentation display for plugins
- Reduce power reset service logging
- Fix backend version number not updating after update
Fix an issue where entering a non-existent invite code during registration would result in an unclear HTTP code 0 error. Now, the system properly validates the invite code and returns a clear error response if the code does not exist.
- Add HookManager::filter('client.subscribe.servers') hook in ClientController::subscribe()
- Allow plugins to inject custom servers into subscription responses
- Update protocol classes to support extended server configurations
- Enable dynamic server list modification before protocol processing
A TypeError occurred when filtering the user list by the `total_used` computed attribute. The `applyQueryCondition` method expected a string for the field name, but received an `Illuminate\Database\Query\Expression` object from `DB::raw`.
This commit updates the `buildFilterQuery` method to check if the query field is an `Expression` instance. If so, it now uses `whereRaw` to apply the filter, preventing the type error and enabling filtering on computed fields. For standard string fields, it continues to use the original `applyQueryCondition` logic.Fix: Handle raw DB expressions in user filter
A TypeError occurred when filtering the user list by the `total_used` computed attribute. The `applyQueryCondition` method expected a string for the field name, but received an `Illuminate\Database\Query\Expression` object from `DB::raw`.
This commit updates the `buildFilterQuery` method to check if the query field is an `Expression` instance. If so, it now uses `whereRaw` to apply the filter, preventing the type error and enabling filtering on computed fields. For standard string fields, it continues to use the original `applyQueryCondition` logic.Fix: Handle raw DB expressions in user filter
A TypeError occurred when filtering the user list by the `total_used` computed attribute. The `applyQueryCondition` method expected a string for the field name, but received an `Illuminate\Database\Query\Expression` object from `DB::raw`.
This commit updates the `buildFilterQuery` method to check if the query field is an `Expression` instance. If so, it now uses `whereRaw` to apply the filter, preventing the type error and enabling filtering on computed fields. For standard string fields, it continues to use the original `applyQueryCondition` logic.Fix: Handle raw DB expressions in user filter
A TypeError occurred when filtering the user list by the `total_used` computed attribute. The `applyQueryCondition` method expected a string for the field name, but received an `Illuminate\Database\Query\Expression` object from `DB::raw`.
This commit updates the `buildFilterQuery` method to check if the query field is an `Expression` instance. If so, it now uses `whereRaw` to apply the filter, preventing the type error and enabling filtering on computed fields. For standard string fields, it continues to use the original `applyQueryCondition` logic.Fix: Handle raw DB expressions in user filter
A TypeError occurred when filtering the user list by the `total_used` computed attribute. The `applyQueryCondition` method expected a string for the field name, but received an `Illuminate\Database\Query\Expression` object from `DB::raw`.
This commit updates the `buildFilterQuery` method to check if the query field is an `Expression` instance. If so, it now uses `whereRaw` to apply the filter, preventing the type error and enabling filtering on computed fields. For standard string fields, it continues to use the original `applyQueryCondition` logic.Fix: Handle raw DB expressions in user filter
A TypeError occurred when filtering the user list by the `total_used` computed attribute. The `applyQueryCondition` method expected a string for the field name, but received an `Illuminate\Database\Query\Expression` object from `DB::raw`.
This commit updates the `buildFilterQuery` method to check if the query field is an `Expression` instance. If so, it now uses `whereRaw` to apply the filter, preventing the type error and enabling filtering on computed fields. For standard string fields, it continues to use the original `applyQueryCondition` logic.Fix: Handle raw DB expressions in user filter
A TypeError occurred when filtering the user list by the `total_used` computed attribute. The `applyQueryCondition` method expected a string for the field name, but received an `Illuminate\Database\Query\Expression` object from `DB::raw`.
This commit updates the `buildFilterQuery` method to check if the query field is an `Expression` instance. If so, it now uses `whereRaw` to apply the filter, preventing the type error and enabling filtering on computed fields. For standard string fields, it continues to use the original `applyQueryCondition` logic.Fix: Handle raw DB expressions in user filter
A TypeError occurred when filtering the user list by the `total_used` computed attribute. The `applyQueryCondition` method expected a string for the field name, but received an `Illuminate\Database\Query\Expression` object from `DB::raw`.
This commit updates the `buildFilterQuery` method to check if the query field is an `Expression` instance. If so, it now uses `whereRaw` to apply the filter, preventing the type error and enabling filtering on computed fields. For standard string fields, it continues to use the original `applyQueryCondition` logic.Fix: Handle raw DB expressions in user filter
A TypeError occurred when filtering the user list by the `total_used` computed attribute. The `applyQueryCondition` method expected a string for the field name, but received an `Illuminate\Database\Query\Expression` object from `DB::raw`.
This commit updates the `buildFilterQuery` method to check if the query field is an `Expression` instance. If so, it now uses `whereRaw` to apply the filter, preventing the type error and enabling filtering on computed fields. For standard string fields, it continues to use the original `applyQueryCondition` logic.
Updated the `admin_setting` and `admin_settings_batch` helpers to retrieve the `Setting` instance from the service container. This fixes a fatal error and ensures correct behavior in a Laravel Octane environment by preventing the use of stale, shared static instances.