- Set
[type=search](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/search)
- Disable spellcheck
- Set maxLength 255 that I found in `templates/repo/issue/search.tmpl`
- Remove unnecessary `max-width`, it does nothing
---------
Co-authored-by: delvh <dev.lh@web.de>
Co-authored-by: Giteabot <teabot@gitea.io>
- Improve "Hide the activity from the profile page" label
- E-Mail privacy icon in user profile now redirects to Privacy section
- E-Mail privacy settings moved to Privacy section
Previously, the user was redirected to the setting itself, however,
that is not a good design choice because the setting itself would
be at the very top of the user's browser window. This fix doesn't
fix the problem entirely, but it is definitely an improvement
compared to its previous iteration.
Numerous small UI fixes:
- Fix double border in collaborator list
- Fix system notice table background
- Mute links in repo and org lists
- Downsize projects edit buttons
- Improve milestones and project list rendering
- Condense milestone list entry to a single line of "metas"
- Mute ".." button in repo files list
In modern days, there is no reason to make users set "charset" anymore.
Close#25378
## ⚠️ BREAKING
The key `[database].CHARSET` was removed completely as every newer
(>10years) MySQL database supports `utf8mb4` already.
There is a (deliberately) undocumented new fallback option if anyone
still needs to use it, but we don't recommend using it as it simply
causes problems.
# The problem
There were many "path tricks":
* By default, Gitea uses its program directory as its work path
* Gitea tries to use the "work path" to guess its "custom path" and
"custom conf (app.ini)"
* Users might want to use other directories as work path
* The non-default work path should be passed to Gitea by GITEA_WORK_DIR
or "--work-path"
* But some Gitea processes are started without these values
* The "serv" process started by OpenSSH server
* The CLI sub-commands started by site admin
* The paths are guessed by SetCustomPathAndConf again and again
* The default values of "work path / custom path / custom conf" can be
changed when compiling
# The solution
* Use `InitWorkPathAndCommonConfig` to handle these path tricks, and use
test code to cover its behaviors.
* When Gitea's web server runs, write the WORK_PATH to "app.ini", this
value must be the most correct one, because if this value is not right,
users would find that the web UI doesn't work and then they should be
able to fix it.
* Then all other sub-commands can use the WORK_PATH in app.ini to
initialize their paths.
* By the way, when Gitea starts for git protocol, it shouldn't output
any log, otherwise the git protocol gets broken and client blocks
forever.
The "work path" priority is: WORK_PATH in app.ini > cmd arg --work-path
> env var GITEA_WORK_DIR > builtin default
The "app.ini" searching order is: cmd arg --config > cmd arg "work path
/ custom path" > env var "work path / custom path" > builtin default
## ⚠️ BREAKING
If your instance's "work path / custom path / custom conf" doesn't meet
the requirements (eg: work path must be absolute), Gitea will report a
fatal error and exit. You need to set these values according to the
error log.
----
Close#24818Close#24222Close#21606Close#21498Close#25107Close#24981
Maybe close#24503
Replace #23301
Replace #22754
And maybe more
- Update all JS dependencies
- Enable stylint
[`media-feature-name-value-no-unknown`](https://stylelint.io/user-guide/rules/media-feature-name-value-no-unknown)
- Make use of new features in webpack and text-expander-element
- Tested Swagger and Mermaid
To explain the `text-expander-element` change: Before this version, the
element added a unavoidable space after emoji completion. Now that
https://github.com/github/text-expander-element/pull/36 is in, we gain
control over this space and I opted to remove it for emoji completion
and retain it for `@` mentions.
---------
Co-authored-by: Giteabot <teabot@gitea.io>
Fixes: https://github.com/go-gitea/gitea/issues/25282
Fix the problems:
1. The `repo-button-row` had various patches before, this PR makes it
consistent
2. The "Add File" has wrong CSS class "icon", remove it
3. The "Add File" padding was overridden by "!important", fix it by
`.repo-button-row .button.dropdown` with comment
4. The selector `.ui.segments ~ .ui.top.attached.header` is incorrect,
it should use `+`
So I found this [linter](https://github.com/Riverside-Healthcare/djlint)
which features a mode for go templates, so I gave it a try and it did
find a number of valid issue, like unbalanced tags etc. It also has a
number of bugs, I had to disable/workaround many issues.
Given that this linter is written in python, this does add a dependency
on `python` >= 3.8 and `poetry` to the development environment to be
able to run this linter locally.
- `e.g.` prefixes on placeholders are removed because the linter had a
false-positive on `placeholder="e.g. cn=Search"` for the `attr=value`
syntax and it's not ideal anyways to write `e.g.` into a placeholder
because a placeholder is meant to hold a sample value.
- In `templates/repo/settings/options.tmpl` I simplified the logic to
not conditionally create opening tags without closing tags because this
stuff confuses the linter (and possibly the reader as well).
Follow up #22405Fix#20703
This PR rewrites storage configuration read sequences with some breaks
and tests. It becomes more strict than before and also fixed some
inherit problems.
- Move storage's MinioConfig struct into setting, so after the
configuration loading, the values will be stored into the struct but not
still on some section.
- All storages configurations should be stored on one section,
configuration items cannot be overrided by multiple sections. The
prioioty of configuration is `[attachment]` > `[storage.attachments]` |
`[storage.customized]` > `[storage]` > `default`
- For extra override configuration items, currently are `SERVE_DIRECT`,
`MINIO_BASE_PATH`, `MINIO_BUCKET`, which could be configured in another
section. The prioioty of the override configuration is `[attachment]` >
`[storage.attachments]` > `default`.
- Add more tests for storages configurations.
- Update the storage documentations.
---------
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
close#24540
related:
- Protocol: https://gitea.com/gitea/actions-proto-def/pulls/9
- Runner side: https://gitea.com/gitea/act_runner/pulls/201
changes:
- Add column of `labels` to table `action_runner`, and combine the value
of `agent_labels` and `custom_labels` column to `labels` column.
- Store `labels` when registering `act_runner`.
- Update `labels` when `act_runner` starting and calling `Declare`.
- Users cannot modify the `custom labels` in edit page any more.
other changes:
- Store `version` when registering `act_runner`.
- If runner is latest version, parse version from `Declare`. But older
version runner still parse version from request header.
Clarify the "link-action" behavior:
> // A "link-action" can post AJAX request to its "data-url"
> // Then the browser is redirect to: the "redirect" in response, or
"data-redirect" attribute, or current URL by reloading.
And enhance the "link-action" to support showing a modal dialog for
confirm. A similar general approach could also help PRs like
https://github.com/go-gitea/gitea/pull/22344#discussion_r1062883436
> // If the "link-action" has "data-modal-confirm(-html)" attribute, a
confirm modal dialog will be shown before taking action.
And a lot of duplicate code can be removed now. A good framework design
can help to avoid code copying&pasting.
---------
Co-authored-by: silverwind <me@silverwind.io>
The plan is that all built-in auth providers use inline SVG for more
flexibility in styling and to get the GitHub icon to follow
`currentcolor`. This only removes the `public/img/auth` directory and
adds the missing svgs to our svg build.
It should map the built-in providers to these SVGs and render them. If
the user has set a Icon URL, it should render that as an `img` tag
instead.
```
gitea-azure-ad
gitea-bitbucket
gitea-discord
gitea-dropbox
gitea-facebook
gitea-gitea
gitea-gitlab
gitea-google
gitea-mastodon
gitea-microsoftonline
gitea-nextcloud
gitea-twitter
gitea-yandex
octicon-mark-github
```
GitHub logo is now white again on dark theme:
<img width="431" alt="Screenshot 2023-06-12 at 21 45 34"
src="https://github.com/go-gitea/gitea/assets/115237/27a43504-d60a-4132-a502-336b25883e4d">
---------
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
The current UI to create API access tokens uses checkboxes that have a
complicated relationship where some need to be checked and/or disabled
in certain states. It also requires that a user interact with it to
understand what their options really are.
This branch changes to use `<select>`s. It better fits the available
options, and it's closer to [GitHub's
UI](https://github.com/settings/personal-access-tokens/new), which is
good, in my opinion. It's more mobile friendly since the tap-areas are
larger. If we ever add more permissions, like Maintainer, there's a
natural place that doesn't take up more screen real-estate.
This branch also fixes a few minor issues:
- Hide the error about selecting at least one permission after second
submission
- Fix help description to call it "authorization" since that's what
permissions are about (not authentication)
Related: #24767.
<img width="883" alt="Screenshot 2023-06-07 at 5 07 34 PM"
src="https://github.com/go-gitea/gitea/assets/10803/6b63d807-c9be-4a4b-8e53-ecab6cbb8f76">
---
When it's open:
<img width="881" alt="Screenshot 2023-06-07 at 5 07 59 PM"
src="https://github.com/go-gitea/gitea/assets/10803/2432c6d0-39c2-4ca4-820e-c878ffdbfb69">
Fix#25133
Thanks @wxiaoguang @silverwind.
I'm sorry I made a mistake, it will be fixed in this PR.
---------
Co-authored-by: Giteabot <teabot@gitea.io>
Co-authored-by: silverwind <me@silverwind.io>
Fixes https://github.com/go-gitea/gitea/issues/25130
The old code uses `$(this).next()` to get `dismiss-review-modal`.
At first, it will get `$(#dismiss-review-modal)`, but the next time it
will get `$(#dismiss-review-modal).next();`
and then `$(#dismiss-review-modal).next().next();`.
Because div `dismiss-review-modal` will be removed when
`dismiss-review-btn` clicked.
Maybe the right usage is adding `show-modal` class and `data-modal`
attribute.
That ID is a "copy&paste" error, it conflicts with the
`initRepoMigrationStatusChecker` logic, which is the right function for
a real `#repo_migrating` element. That wrong ID causes incorrect page
navigation after installation.
Fixes some issues with the swagger documentation for the new multiple
files API endpoint (#24887) which were overlooked when submitting the
original PR:
1. add some missing parameter descriptions
2. set correct `required` option for required parameters
3. change endpoint description to match it full functionality (every
kind of file modification is supported, not just creating and updating)
Follow:
* #22697
There are some bugs in #22697:
* https://github.com/go-gitea/gitea/pull/22697#issuecomment-1577957966
* the webauthn failure message is never shown and causes console error
* The `document.getElementById('register-button')` and
`document.getElementById('login-button')` is wrong
* there is no such element in code
* it causes JS error when a browser doesn't provide webauthn
* the end user can't see the real error message
These bugs are fixed in this PR.
Other changes:
* Use simple HTML/CSS layouts, no need to use too many `gt-` patches
* Make the webauthn page have correct "page-content" layout
* The "data-webauthn-error-msg" elements are only used to provide locale
texts, so move them into a single "gt-hidden", then no need to repeat a
lot of "gt-hidden" in code
* The `{{.CsrfTokenHtml}}` is a no-op because there is no form
* Many `hideElem('#webauthn-error')` in code is no-op because the
`webauthn-error` already has "gt-hidden" by default
* Make the tests for "URLEncodedBase64" really test with concrete cases.
Screenshots:
* Error message when webauthn fails (before, there is no error message):
<details>
![image](https://github.com/go-gitea/gitea/assets/2114189/93cf9559-d93b-4f06-9d98-0f7032d9c65b)
</details>
* Error message when webauthn is unavailable
<details>
![image](https://github.com/go-gitea/gitea/assets/2114189/ffc0fcd9-b93b-4418-979c-c89bb627aaf2)
</details>
There were several issues with the WebAuthn registration and testing
code and the style
was very old javascript with jquery callbacks.
This PR uses async and fetch to replace the JQuery code.
Ref #22651
Signed-off-by: Andrew Thornton <art27@cantab.net>
---------
Signed-off-by: Andrew Thornton <art27@cantab.net>
Co-authored-by: delvh <dev.lh@web.de>
Co-authored-by: silverwind <me@silverwind.io>
## Changes
- Adds the following high level access scopes, each with `read` and
`write` levels:
- `activitypub`
- `admin` (hidden if user is not a site admin)
- `misc`
- `notification`
- `organization`
- `package`
- `issue`
- `repository`
- `user`
- Adds new middleware function `tokenRequiresScopes()` in addition to
`reqToken()`
- `tokenRequiresScopes()` is used for each high-level api section
- _if_ a scoped token is present, checks that the required scope is
included based on the section and HTTP method
- `reqToken()` is used for individual routes
- checks that required authentication is present (but does not check
scope levels as this will already have been handled by
`tokenRequiresScopes()`
- Adds migration to convert old scoped access tokens to the new set of
scopes
- Updates the user interface for scope selection
### User interface example
<img width="903" alt="Screen Shot 2023-05-31 at 1 56 55 PM"
src="https://github.com/go-gitea/gitea/assets/23248839/654766ec-2143-4f59-9037-3b51600e32f3">
<img width="917" alt="Screen Shot 2023-05-31 at 1 56 43 PM"
src="https://github.com/go-gitea/gitea/assets/23248839/1ad64081-012c-4a73-b393-66b30352654c">
## tokenRequiresScopes Design Decision
- `tokenRequiresScopes()` was added to more reliably cover api routes.
For an incoming request, this function uses the given scope category
(say `AccessTokenScopeCategoryOrganization`) and the HTTP method (say
`DELETE`) and verifies that any scoped tokens in use include
`delete:organization`.
- `reqToken()` is used to enforce auth for individual routes that
require it. If a scoped token is not present for a request,
`tokenRequiresScopes()` will not return an error
## TODO
- [x] Alphabetize scope categories
- [x] Change 'public repos only' to a radio button (private vs public).
Also expand this to organizations
- [X] Disable token creation if no scopes selected. Alternatively, show
warning
- [x] `reqToken()` is missing from many `POST/DELETE` routes in the api.
`tokenRequiresScopes()` only checks that a given token has the correct
scope, `reqToken()` must be used to check that a token (or some other
auth) is present.
- _This should be addressed in this PR_
- [x] The migration should be reviewed very carefully in order to
minimize access changes to existing user tokens.
- _This should be addressed in this PR_
- [x] Link to api to swagger documentation, clarify what
read/write/delete levels correspond to
- [x] Review cases where more than one scope is needed as this directly
deviates from the api definition.
- _This should be addressed in this PR_
- For example:
```go
m.Group("/users/{username}/orgs", func() {
m.Get("", reqToken(), org.ListUserOrgs)
m.Get("/{org}/permissions", reqToken(), org.GetUserOrgsPermissions)
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser,
auth_model.AccessTokenScopeCategoryOrganization),
context_service.UserAssignmentAPI())
```
## Future improvements
- [ ] Add required scopes to swagger documentation
- [ ] Redesign `reqToken()` to be opt-out rather than opt-in
- [ ] Subdivide scopes like `repository`
- [ ] Once a token is created, if it has no scopes, we should display
text instead of an empty bullet point
- [ ] If the 'public repos only' option is selected, should read
categories be selected by default
Closes#24501Closes#24799
Co-authored-by: Jonathan Tran <jon@allspice.io>
Co-authored-by: Kyle D <kdumontnu@gmail.com>
Co-authored-by: silverwind <me@silverwind.io>
Before, Gitea shows the database table stats on the `admin dashboard`
page.
It has some problems:
* `count(*)` is quite heavy. If tables have many records, this blocks
loading the admin page blocks for a long time
* Some users had even reported issues that they can't visit their admin
page because this page causes blocking or `50x error (reverse proxy
timeout)`
* The `actions` stat is not useful. The table is simply too large. Does
it really matter if it contains 1,000,000 rows or 9,999,999 rows?
* The translation `admin.dashboard.statistic_info` is difficult to
maintain.
So, this PR uses a separate page to show the stats and removes the
`actions` stat.
![image](https://github.com/go-gitea/gitea/assets/2114189/babf7c61-b93b-4a62-bfaa-22983636427e)
## ⚠️ BREAKING
The `actions` Prometheus metrics collector has been removed for the
reasons mentioned beforehand.
Please do not rely on its output anymore.
Feel free to close this if there isn't interest.
The tree view looks amazing, and all of our users are really enjoying it
(major kudos to developers!), but only IF I tell them it exists!
Essentially, the file tree view as it is effectively undiscoverable.
This PR changes the default state for the tree view to open, which
should significantly help with discoverability.
An alternative could be to reserve more horizontal space, as a typical
accordion panel would look (eg. VS Code), eg.
![image](https://github.com/go-gitea/gitea/assets/12700993/505ea40c-42b1-4111-b306-48e51e8e2130)
It's been disabled by default since 1.17
(https://github.com/go-gitea/gitea/pull/18914), and it never really
delivered any benefit except being another cache layer that has its own
unsolved invalidation issues. HTTP cache works, we don't need two cache
layers at the browser for assets.
## ⚠️ BREAKING
You can remove the config `[ui].USE_SERVICE_WORKER` from your `app.ini`
now.
This addressees some things from #24406 that came up after the PR was
merged. Mostly from @delvh.
---------
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: delvh <dev.lh@web.de>
The admin config page has been broken for many many times, a little
refactoring would make this page panic.
So, add a test for it, and add another test to cover the 500 error page.
Co-authored-by: Giteabot <teabot@gitea.io>
This PR creates an API endpoint for creating/updating/deleting multiple
files in one API call similar to the solution provided by
[GitLab](https://docs.gitlab.com/ee/api/commits.html#create-a-commit-with-multiple-files-and-actions).
To archive this, the CreateOrUpdateRepoFile and DeleteRepoFIle functions
in files service are unified into one function supporting multiple files
and actions.
Resolves#14619
As discussed in
https://github.com/go-gitea/gitea/pull/24953#issuecomment-1565630156.
## ⚠️ BREAKING ⚠️
1. The `ui.THEME_COLOR_META_TAG` setting has been removed. If you still
need to set the `theme-color` meta tag, add it via
`$GITEA_CUSTOM/templates/custom/header.tmpl` instead.
2. The non-standard `default-theme` meta-tag added in
https://github.com/go-gitea/gitea/pull/13809 has been removed. Third
party code that needs to obtain the currently loaded theme should use
the `theme-<name>` class on the `<html>` node instead, which reflect the
currently active theme.
The 500 page was not loading theme CSS, so always appeared in light
theme. This extracts the stylesheets into a shared template used by all
pages.
<img width="1262" alt="image"
src="https://github.com/go-gitea/gitea/assets/115237/72222b8d-a523-40d0-aa91-b9db32e5625d">
Small related rant: I think there should only be one `<head>` in all of
the templates, but I see it was deliberatly done that the 500 page has
its own `<head>` because "it should only depend the minimal template
functions", but I disagree because we are missing a lot of things that
are in the regular `<head>`.
Don't really know a better name for this. I've gone through some Forms
and added missing HTML attributes (mostly `maxlength`). I tried to fill
the Forms with dummy Data and see if Gitea throws a Error (e.g. maximum
length). If yes, I added the missing HTML attribute.
While working on this, I discovered that the Form to add OAuth2 Apps
just silently fails when filled with invalid data, so I fixed that too.
The Repolist contains the Number of Stars and Forks. Now these Numbers
are a Link to the corresponding pages of the Repo.
Co-authored-by: Giteabot <teabot@gitea.io>
This adds the ability to pin important Issues and Pull Requests. You can
also move pinned Issues around to change their Position. Resolves#2175.
## Screenshots
![grafik](https://user-images.githubusercontent.com/15185051/235123207-0aa39869-bb48-45c3-abe2-ba1e836046ec.png)
![grafik](https://user-images.githubusercontent.com/15185051/235123297-152a16ea-a857-451d-9a42-61f2cd54dd75.png)
![grafik](https://user-images.githubusercontent.com/15185051/235640782-cbfe25ec-6254-479a-a3de-133e585d7a2d.png)
The Design was mostly copied from the Projects Board.
## Implementation
This uses a new `pin_order` Column in the `issue` table. If the value is
set to 0, the Issue is not pinned. If it's set to a bigger value, the
value is the Position. 1 means it's the first pinned Issue, 2 means it's
the second one etc. This is dived into Issues and Pull requests for each
Repo.
## TODO
- [x] You can currently pin as many Issues as you want. Maybe we should
add a Limit, which is configurable. GitHub uses 3, but I prefer 6, as
this is better for bigger Projects, but I'm open for suggestions.
- [x] Pin and Unpin events need to be added to the Issue history.
- [x] Tests
- [x] Migration
**The feature itself is currently fully working, so tester who may find
weird edge cases are very welcome!**
---------
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Giteabot <teabot@gitea.io>
We can reuse the recently created subtemplate here. I also checked the
whole templates for similar constructs, these appear to be the only one.
Co-authored-by: Giteabot <teabot@gitea.io>
- Replace `<table>` with flexbox
- Add issue modification time and issue number
- Remove big title
- Replace tabs with menu items
- Add clicked item deletion on back button cache restoration
---------
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
close https://github.com/go-gitea/gitea/issues/16321
Provided a webhook trigger for requesting someone to review the Pull
Request.
Some modifications have been made to the returned `PullRequestPayload`
based on the GitHub webhook settings, including:
- add a description of the current reviewer object as
`RequestedReviewer` .
- setting the action to either **review_requested** or
**review_request_removed** based on the operation.
- adding the `RequestedReviewers` field to the issues_model.PullRequest.
This field will be loaded into the PullRequest through
`LoadRequestedReviewers()` when `ToAPIPullRequest` is called.
After the Pull Request is merged, I will supplement the relevant
documentation.
Currently if pull requests are disabled on a fork but enabled on a base
repo, creating/editing/deleting files does not offer the option to
create a pull request. This change enables creating a pull request for
the base repo in that case.
---------
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: Giteabot <teabot@gitea.io>
There was some recent discussion about this in Discord `ui-design`
channel and the conclusion was that
https://github.com/go-gitea/gitea/issues/24305 should have fixed their
OS font installation to have semibold weights.
I have now tested this 601 weight on a Windows 10 machine on Firefox
myself, and I immediately noticed that bold was excessivly bold and
rendering as 700 because browsers are biased towards bolder fonts. So
revert this back to the previous value.
## ⚠️ Breaking
The `log.<mode>.<logger>` style config has been dropped. If you used it,
please check the new config manual & app.example.ini to make your
instance output logs as expected.
Although many legacy options still work, it's encouraged to upgrade to
the new options.
The SMTP logger is deleted because SMTP is not suitable to collect logs.
If you have manually configured Gitea log options, please confirm the
logger system works as expected after upgrading.
## Description
Close#12082 and maybe more log-related issues, resolve some related
FIXMEs in old code (which seems unfixable before)
Just like rewriting queue #24505 : make code maintainable, clear legacy
bugs, and add the ability to support more writers (eg: JSON, structured
log)
There is a new document (with examples): `logging-config.en-us.md`
This PR is safer than the queue rewriting, because it's just for
logging, it won't break other logic.
## The old problems
The logging system is quite old and difficult to maintain:
* Unclear concepts: Logger, NamedLogger, MultiChannelledLogger,
SubLogger, EventLogger, WriterLogger etc
* Some code is diffuclt to konw whether it is right:
`log.DelNamedLogger("console")` vs `log.DelNamedLogger(log.DEFAULT)` vs
`log.DelLogger("console")`
* The old system heavily depends on ini config system, it's difficult to
create new logger for different purpose, and it's very fragile.
* The "color" trick is difficult to use and read, many colors are
unnecessary, and in the future structured log could help
* It's difficult to add other log formats, eg: JSON format
* The log outputer doesn't have full control of its goroutine, it's
difficult to make outputer have advanced behaviors
* The logs could be lost in some cases: eg: no Fatal error when using
CLI.
* Config options are passed by JSON, which is quite fragile.
* INI package makes the KEY in `[log]` section visible in `[log.sub1]`
and `[log.sub1.subA]`, this behavior is quite fragile and would cause
more unclear problems, and there is no strong requirement to support
`log.<mode>.<logger>` syntax.
## The new design
See `logger.go` for documents.
## Screenshot
<details>
![image](https://github.com/go-gitea/gitea/assets/2114189/4462d713-ba39-41f5-bb08-de912e67e1ff)
![image](https://github.com/go-gitea/gitea/assets/2114189/b188035e-f691-428b-8b2d-ff7b2199b2f9)
![image](https://github.com/go-gitea/gitea/assets/2114189/132e9745-1c3b-4e00-9e0d-15eaea495dee)
</details>
## TODO
* [x] add some new tests
* [x] fix some tests
* [x] test some sub-commands (manually ....)
---------
Co-authored-by: Jason Song <i@wolfogre.com>
Co-authored-by: delvh <dev.lh@web.de>
Co-authored-by: Giteabot <teabot@gitea.io>