When refactoring, I planned to put the logic of loading current pages priority in `PageManager.open`, but I forgot, so the current page will not be loaded priority.
But currently `PageManager.open` has been used in many places, but only one priority page can be set, so the logic of setting the priority page is still placed in the detail page.
# feature:
## In Browser:
- hidden back&forward button in sidebar.
- back and forward is equal with `window.history.back()` `window.history.forward()`
## In Desktop:
- Back and forward can be controlled through the sidebar, cmdk, and shortcut keys.
- back and forward act on the currently **active** view.
- buttons change disable&enable style based on current active view history
# Refactor:
Move app-sidebar and app-container from @affine/component to @affine/core
date seems not hornoring the locale browser's locale when parsing date string like "2024-02-28".
fixed by using dayjs instead.
Fix incorrect journal title issue
## **User description**
use react-transition-state to simplify exit animation
___
## **Type**
enhancement
___
## **Description**
- Integrated `react-transition-state` for managing animations in `ResizePanel` and `CMDKModal` components, simplifying the code and improving maintainability.
- Introduced a shared animation timeout variable to standardize animation durations across components.
- Added `react-transition-state` to dependencies to enable the new animation handling.
___
## **Changes walkthrough**
<table><thead><tr><th></th><th align="left">Relevant files</th></tr></thead><tbody><tr><td><strong>Enhancement</strong></td><td><table>
<tr>
<td>
<details>
<summary><strong>resize-panel.tsx</strong><dd><code>Integrate `react-transition-state` for Resize Panel Animations</code></dd></summary>
<hr>
packages/frontend/component/src/components/resize-panel/resize-panel.tsx
<li>Introduced <code>useTransition</code> hook from <code>react-transition-state</code> for managing <br>animations.<br> <li> Added a constant for animation timeout and applied it to the <br>transition.<br> <li> Utilized the transition state to toggle the open state of the resize <br>panel.<br>
</details>
</td>
<td><a href="https:/toeverything/AFFiNE/pull/5923/files#diff-a4d6e633862f63f97c167ff41ba62aff8aebf3e3b2f6e7ce13d5a0e22e8ff287">+12/-0</a> </td>
</tr>
<tr>
<td>
<details>
<summary><strong>modal.css.ts</strong><dd><code>Use Variable for Animation Timeout in Modal CSS</code> </dd></summary>
<hr>
packages/frontend/core/src/components/pure/cmdk/modal.css.ts
<li>Created a variable for animation timeout.<br> <li> Updated animation durations to use the new timeout variable.<br>
</details>
</td>
<td><a href="https:/toeverything/AFFiNE/pull/5923/files#diff-ba8935611b9c1695153d92d08ecb0f7dac73a6197f54ccda5a6e791902cd651d">+6/-3</a> </td>
</tr>
<tr>
<td>
<details>
<summary><strong>modal.tsx</strong><dd><code>Simplify CMDK Modal Animation with `react-transition-state`</code></dd></summary>
<hr>
packages/frontend/core/src/components/pure/cmdk/modal.tsx
<li>Replaced custom animation state management with <code>useTransition</code> hook.<br> <li> Removed old animation state logic and simplified the component.<br> <li> Added animation timeout variable and applied it to the transition.<br>
</details>
</td>
<td><a href="https:/toeverything/AFFiNE/pull/5923/files#diff-ab3fe66c9b1d3a691fafd1aebc9988e840fedfcd09b5b89570838a5a2a9469c9">+13/-33</a> </td>
</tr>
</table></td></tr><tr><td><strong>Dependencies</strong></td><td><table>
<tr>
<td>
<details>
<summary><strong>package.json</strong><dd><code>Add `react-transition-state` Dependency</code> </dd></summary>
<hr>
packages/frontend/core/package.json
- Added `react-transition-state` as a dependency.
</details>
</td>
<td><a href="https:/toeverything/AFFiNE/pull/5923/files#diff-23e0e5dc0ceb004a0a5d3d13e7d00545de7487535ca0e5eab4c5047f1e24eff0">+1/-0</a> </td>
</tr>
</table></td></tr></tr></tbody></table>
___
> ✨ **PR-Agent usage**:
>Comment `/help` on the PR to get a list of all available PR-Agent tools and their descriptions
To support multiple instances, this PR removes some atoms and implements them using the new DI system.
removed atom
- `pageSettingsAtom`
- `currentPageIdAtom`
- `currentModeAtom`
Related to https://github.com/toeverything/blocksuite/pull/6156
### Change
Move the edgeless templates to AFFiNE. All templates are stored as zip files. Run `node build-edgeless.mjs` in `@affine/templates` to generate JSON-format templates and importing script. The template will be generated automatically during building and dev (`yarn dev`).
Replace internal CMDK command filtering/sorting logic.
The new implementation includes the following for command scoring:
- categories weights
- highlighted fragments
- original command score value
The new logic should be much cleaner and remove some hacks in the original implementation.
Not sure if this is optimal yet. Could be changed later.
fix https://github.com/toeverything/AFFiNE/issues/5699
after this pr, server will only accept client that have some major version
the client version <0.12 will be rejected by the server, >= 0.12 can receive outdated messages and notify users
using a [babel plugin](https://gist.github.com/pengx17/49e24ae8a5a609bdaff122ee8c679d1c) to transform all var(--affine-xxx) to cssVar
Some issues:
- tried ast-grep but it seems to be not easy to add imports conditionally
- current work does not work well with ts with types because babel will strip them out
standardize the error raising in both GraphQL Resolvers and Controllers.
Now, All user aware errors should be throwed with `HttpException`'s variants, for example `NotFoundException`.
> Directly throwing `GraphQLError` are forbidden.
The GraphQL errorFormatter will handle it automatically and set `code`, `status` in error extensions.
At the same time, the frontend `GraphQLError` should be imported from `@affine/graphql`, which introduce a better error extensions type.
----
controller example:
```js
@Get('/docs/${id}')
doc() {
// ...
// imported from '@nestjs/common'
throw new NotFoundException('Doc is not found.');
// ...
}
```
the above will response as:
```
status: 404 Not Found
{
"message": "Doc is not found.",
"statusCode": 404,
"error": "Not Found"
}
```
resolver example:
```js
@Mutation()
invite() {
// ...
throw new PayloadTooLargeException('Workspace seats is full.')
// ...
}
```
the above will response as:
```
status: 200 Ok
{
"data": null,
"errors": [
{
"message": "Workspace seats is full.",
"extensions": {
"code": 404,
"status": "Not Found"
}
}
]
}
```
for frontend GraphQLError user-friend, a helper function introduced:
```js
import { findGraphQLError } from '@affine/graphql'
fetch(query)
.catch(errOrArr => {
const e = findGraphQLError(errOrArr, e => e.extensions.code === 404)
if (e) {
// handle
}
})
```
close#5686
`Owner >> Unaccepted > Admin > Write > Read`
This algorithm contains two parts: firstly, it calculates the weight of the Member (calculateWeight), and then, it uses set weights to sort the Members (useMembers).
In the calculateWeight part, the computation of the weight involves three primary factors:
1. **Permission Level**: The `Owner` is given the highest weight of `4`, followed by `Admin` with a weight of `3`, then `Write` with a weight of `2`, and finally, `Read`, with a weight of `1`.
2. **Acceptance Status**: `Unaccepted` members have a higher weight, this weight is `1`.
3. The weight corresponding to the permission level, if the member does not exist, this weight is 0.
These three `factors` are stored in the factors array and then processed through the reduce function for weighted sum calculation. Among them, `factor * Math.pow(10, arr.length - 1 - index)` means the more significant weight factors (i.e., the earlier factors) will be assigned a higher value.
Sorting rules are primarily based on the weight values obtained from the calculateWeight function. If the weights are identical, it then sorts by name, here assuming the weight of the name being `null` is the highest. If the names are not `null`, they are sorted alphabetically.
close TOV-343 AFF-508 TOV-461 TOV-460 TOV-419
Add `isOverCapacity ` status to detect if blob usage exceeds limits.
Add `onCapacityChange` and `onBlobSet` to monitor if the storage or blob exceeds the capacity limit.
Global modals `LocalQuotaModal` and `CloudQuotaModal` have been added, with the upload size of the blob being limited within the modal components.
The notification component has been adjusted, now you can pass in `action` click events and `actionLabel` .
A React wrapper for blocksuite editor from title/meta/doc/edgless fragments.
This PR only **clones** the `AffineEditorContainer`'s existing behavior and make it easier for extension in affine later.
fix TOV-315
### Some core issues:
A customized version of `createComponent` from `@lit/react`. The [existing and solutions in the community](https://github.com/lit/lit/issues/4435) does not work well in our case.
Alternatively in this PR the approach we have is to create web component instances in React lifecycle and then append them to DOM. However this make it hard to wrap the exported Lit component's using React and therefore we will have an additional wrapper tag for the wrapped web component.
To mitigate the migration issue on using React instead of Lit listed on last day, we now use [a proxy to mimic the wrapped React component](https://github.com/toeverything/AFFiNE/pull/5606/files#diff-5b7f0ae7b52a08739d50e78e9ec803c26ff3d3e5437581c692add0de12d3ede5R142-R183) into an `AffineEditorContainer` instance.
Because the space for the scroll bar on the right is reserved, in order to make the editor symmetrical, padding corresponding to the width of the scroll bar is added to the left.
fix TOV-280
experimental features ui
- enabled in the workspace settings for a cloud workspace; only show for workspace owner + early access
- a disclaimer prompt will be shown before going to the next feature setting page
- for now only show the ai poc switch, which controls the display of the ai tab in editor's sidepanel