mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-07 18:13:43 +00:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a13bdcc3d | ||
|
|
71d682c1c0 | ||
|
|
d90eeffe84 | ||
|
|
12fe7a5ced | ||
|
|
a35bcdc3ef | ||
|
|
29cb937493 | ||
|
|
e52bcb7fd6 | ||
|
|
4e082e4170 | ||
|
|
46958867ef | ||
|
|
beb09300b9 | ||
|
|
f644454c5c | ||
|
|
1654d8efe4 | ||
|
|
46e7d9fab7 | ||
|
|
17ec76540b | ||
|
|
e5db0e66c1 | ||
|
|
525b65c6ca | ||
|
|
c302425a05 | ||
|
|
abe73e9996 | ||
|
|
e379da200e |
@@ -222,12 +222,12 @@
|
||||
},
|
||||
"SMTP.sender": {
|
||||
"type": "string",
|
||||
"description": "Sender of all the emails (e.g. \"AFFiNE Team <noreply@affine.pro>\")\n@default \"\"\n@environment `MAILER_SENDER`",
|
||||
"default": ""
|
||||
"description": "Sender of all the emails (e.g. \"AFFiNE Self Hosted <noreply@example.com>\")\n@default \"AFFiNE Self Hosted <noreply@example.com>\"\n@environment `MAILER_SENDER`",
|
||||
"default": "AFFiNE Self Hosted <noreply@example.com>"
|
||||
},
|
||||
"SMTP.ignoreTLS": {
|
||||
"type": "boolean",
|
||||
"description": "Whether ignore email server's TSL certification verification. Enable it for self-signed certificates.\n@default false\n@environment `MAILER_IGNORE_TLS`",
|
||||
"description": "Whether ignore email server's TLS certificate verification. Enable it for self-signed certificates.\n@default false\n@environment `MAILER_IGNORE_TLS`",
|
||||
"default": false
|
||||
},
|
||||
"fallbackDomains": {
|
||||
@@ -262,12 +262,12 @@
|
||||
},
|
||||
"fallbackSMTP.sender": {
|
||||
"type": "string",
|
||||
"description": "Sender of all the emails (e.g. \"AFFiNE Team <noreply@affine.pro>\")\n@default \"\"",
|
||||
"description": "Sender of all the emails (e.g. \"AFFiNE Self Hosted <noreply@example.com>\")\n@default \"\"",
|
||||
"default": ""
|
||||
},
|
||||
"fallbackSMTP.ignoreTLS": {
|
||||
"type": "boolean",
|
||||
"description": "Whether ignore email server's TSL certification verification. Enable it for self-signed certificates.\n@default false",
|
||||
"description": "Whether ignore email server's TLS certificate verification. Enable it for self-signed certificates.\n@default false",
|
||||
"default": false
|
||||
}
|
||||
}
|
||||
|
||||
2
.github/helm/affine/Chart.yaml
vendored
2
.github/helm/affine/Chart.yaml
vendored
@@ -3,4 +3,4 @@ name: affine
|
||||
description: AFFiNE cloud chart
|
||||
type: application
|
||||
version: 0.0.0
|
||||
appVersion: "0.25.2"
|
||||
appVersion: "0.25.5"
|
||||
|
||||
2
.github/helm/affine/charts/doc/Chart.yaml
vendored
2
.github/helm/affine/charts/doc/Chart.yaml
vendored
@@ -3,7 +3,7 @@ name: doc
|
||||
description: AFFiNE doc server
|
||||
type: application
|
||||
version: 0.0.0
|
||||
appVersion: "0.25.2"
|
||||
appVersion: "0.25.5"
|
||||
dependencies:
|
||||
- name: gcloud-sql-proxy
|
||||
version: 0.0.0
|
||||
|
||||
@@ -3,7 +3,7 @@ name: graphql
|
||||
description: AFFiNE GraphQL server
|
||||
type: application
|
||||
version: 0.0.0
|
||||
appVersion: "0.25.2"
|
||||
appVersion: "0.25.5"
|
||||
dependencies:
|
||||
- name: gcloud-sql-proxy
|
||||
version: 0.0.0
|
||||
|
||||
@@ -3,7 +3,7 @@ name: renderer
|
||||
description: AFFiNE renderer server
|
||||
type: application
|
||||
version: 0.0.0
|
||||
appVersion: "0.25.2"
|
||||
appVersion: "0.25.5"
|
||||
dependencies:
|
||||
- name: gcloud-sql-proxy
|
||||
version: 0.0.0
|
||||
|
||||
2
.github/helm/affine/charts/sync/Chart.yaml
vendored
2
.github/helm/affine/charts/sync/Chart.yaml
vendored
@@ -3,7 +3,7 @@ name: sync
|
||||
description: AFFiNE Sync Server
|
||||
type: application
|
||||
version: 0.0.0
|
||||
appVersion: "0.25.2"
|
||||
appVersion: "0.25.5"
|
||||
dependencies:
|
||||
- name: gcloud-sql-proxy
|
||||
version: 0.0.0
|
||||
|
||||
2
.github/workflows/build-test.yml
vendored
2
.github/workflows/build-test.yml
vendored
@@ -19,7 +19,7 @@ env:
|
||||
APP_NAME: affine
|
||||
AFFINE_ENV: dev
|
||||
COVERAGE: true
|
||||
MACOSX_DEPLOYMENT_TARGET: '10.13'
|
||||
MACOSX_DEPLOYMENT_TARGET: '11.6'
|
||||
DEPLOYMENT_TYPE: affine
|
||||
AFFINE_INDEXER_ENABLED: true
|
||||
|
||||
|
||||
8
.github/workflows/release-desktop.yml
vendored
8
.github/workflows/release-desktop.yml
vendored
@@ -25,7 +25,7 @@ env:
|
||||
RELEASE_VERSION: ${{ inputs.app-version }}
|
||||
DEBUG: 'affine:*,napi:*'
|
||||
APP_NAME: affine
|
||||
MACOSX_DEPLOYMENT_TARGET: '10.13'
|
||||
MACOSX_DEPLOYMENT_TARGET: '11.6'
|
||||
|
||||
jobs:
|
||||
before-make:
|
||||
@@ -165,7 +165,7 @@ jobs:
|
||||
mv packages/frontend/apps/electron/out/*/make/zip/linux/${{ matrix.spec.arch }}/*.zip ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ matrix.spec.arch }}.zip
|
||||
mv packages/frontend/apps/electron/out/*/make/*.AppImage ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ matrix.spec.arch }}.appimage
|
||||
mv packages/frontend/apps/electron/out/*/make/deb/${{ matrix.spec.arch }}/*.deb ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ matrix.spec.arch }}.deb
|
||||
mv packages/frontend/apps/electron/out/*/make/flatpak/*/*.flatpak ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ matrix.spec.arch }}.flatpak
|
||||
# mv packages/frontend/apps/electron/out/*/make/flatpak/*/*.flatpak ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ matrix.spec.arch }}.flatpak
|
||||
|
||||
- uses: actions/attest-build-provenance@v2
|
||||
if: ${{ matrix.spec.platform == 'darwin' }}
|
||||
@@ -466,6 +466,4 @@ jobs:
|
||||
draft: ${{ inputs.build-type == 'stable' }}
|
||||
prerelease: ${{ inputs.build-type != 'stable' }}
|
||||
tag_name: v${{ env.RELEASE_VERSION}}
|
||||
files: |
|
||||
./release/*
|
||||
./release/.env.example
|
||||
files: ./release/*
|
||||
|
||||
@@ -296,7 +296,7 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2",
|
||||
"version": "0.25.5",
|
||||
"devDependencies": {
|
||||
"@vanilla-extract/vite-plugin": "^5.0.0",
|
||||
"msw": "^2.8.4",
|
||||
|
||||
@@ -41,5 +41,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -45,5 +45,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -45,5 +45,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -48,5 +48,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -42,5 +42,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -48,5 +48,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -39,5 +39,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -43,5 +43,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -49,5 +49,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -49,5 +49,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -44,5 +44,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -44,5 +44,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -46,5 +46,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -46,5 +46,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -49,5 +49,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -42,5 +42,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
"@preact/signals-core": "^1.8.0",
|
||||
"@toeverything/theme": "^1.1.16",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"dompurify": "^3.2.4",
|
||||
"dompurify": "^3.3.0",
|
||||
"html2canvas": "^1.4.1",
|
||||
"lit": "^3.2.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
@@ -67,5 +67,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -45,5 +45,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -46,5 +46,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -42,5 +42,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -82,5 +82,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -229,9 +229,9 @@ export class DatePicker extends WithDisposable(LitElement) {
|
||||
|
||||
private _modeDecade(offset: number) {
|
||||
this._yearCursor = clamp(
|
||||
this._yearCursor + offset,
|
||||
this._minYear,
|
||||
this._maxYear,
|
||||
this._yearCursor + offset
|
||||
this._maxYear
|
||||
);
|
||||
this._getYearMatrix();
|
||||
}
|
||||
|
||||
@@ -46,5 +46,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import { describe, expect, test } from 'vitest';
|
||||
|
||||
import { mobileEffects } from '../view-presets/table/mobile/effect.js';
|
||||
import type { MobileTableGroup } from '../view-presets/table/mobile/group.js';
|
||||
import { pcEffects } from '../view-presets/table/pc/effect.js';
|
||||
import type { TableGroup } from '../view-presets/table/pc/group.js';
|
||||
|
||||
/** @vitest-environment happy-dom */
|
||||
|
||||
describe('TableGroup', () => {
|
||||
test('toggle collapse on pc', () => {
|
||||
pcEffects();
|
||||
const group = document.createElement(
|
||||
'affine-data-view-table-group'
|
||||
) as TableGroup;
|
||||
|
||||
expect(group.collapsed$.value).toBe(false);
|
||||
(group as any)._toggleCollapse();
|
||||
expect(group.collapsed$.value).toBe(true);
|
||||
(group as any)._toggleCollapse();
|
||||
expect(group.collapsed$.value).toBe(false);
|
||||
});
|
||||
|
||||
test('toggle collapse on mobile', () => {
|
||||
mobileEffects();
|
||||
const group = document.createElement(
|
||||
'mobile-table-group'
|
||||
) as MobileTableGroup;
|
||||
|
||||
expect(group.collapsed$.value).toBe(false);
|
||||
(group as any)._toggleCollapse();
|
||||
expect(group.collapsed$.value).toBe(true);
|
||||
(group as any)._toggleCollapse();
|
||||
expect(group.collapsed$.value).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -26,13 +26,10 @@ const GroupTitleMobile = (
|
||||
const type = groupData.tType;
|
||||
if (!type) return nothing;
|
||||
|
||||
const icon =
|
||||
groupData.value == null
|
||||
? ''
|
||||
: html` <uni-lit
|
||||
class="group-header-icon"
|
||||
.uni="${groupData.property.icon}"
|
||||
></uni-lit>`;
|
||||
const icon = html` <uni-lit
|
||||
class="group-header-icon"
|
||||
.uni="${groupData.property.icon}"
|
||||
></uni-lit>`;
|
||||
const props: GroupRenderProps = {
|
||||
group: groupData,
|
||||
readonly: ops.readonly,
|
||||
@@ -126,13 +123,10 @@ export const GroupTitle = (
|
||||
const type = groupData.tType;
|
||||
if (!type) return nothing;
|
||||
|
||||
const icon =
|
||||
groupData.value == null
|
||||
? ''
|
||||
: html` <uni-lit
|
||||
class="group-header-icon"
|
||||
.uni="${groupData.property.icon}"
|
||||
></uni-lit>`;
|
||||
const icon = html` <uni-lit
|
||||
class="group-header-icon"
|
||||
.uni="${groupData.property.icon}"
|
||||
></uni-lit>`;
|
||||
const props: GroupRenderProps = {
|
||||
group: groupData,
|
||||
readonly: ops.readonly,
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Shared utility for managing table group collapsed state in sessionStorage.
|
||||
* Used by both PC and mobile table group implementations.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Gets the collapsed state for a specific table group from sessionStorage.
|
||||
* @param viewId - The ID of the table view
|
||||
* @param groupKey - The key of the group
|
||||
* @returns The collapsed state as a boolean, or false if not found or invalid
|
||||
*/
|
||||
export function getCollapsedState(viewId: string, groupKey: string): boolean {
|
||||
try {
|
||||
const value = sessionStorage.getItem(
|
||||
`affine:table-group:${viewId}:${groupKey}:collapsed`
|
||||
);
|
||||
if (!value) return false;
|
||||
const parsed = JSON.parse(value);
|
||||
return typeof parsed === 'boolean' ? parsed : false;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the collapsed state for a specific table group in sessionStorage.
|
||||
* @param viewId - The ID of the table view
|
||||
* @param groupKey - The key of the group
|
||||
* @param collapsed - The collapsed state to store
|
||||
*/
|
||||
export function setCollapsedState(
|
||||
viewId: string,
|
||||
groupKey: string,
|
||||
collapsed: boolean
|
||||
): void {
|
||||
try {
|
||||
sessionStorage.setItem(
|
||||
`affine:table-group:${viewId}:${groupKey}:collapsed`,
|
||||
JSON.stringify(collapsed)
|
||||
);
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
@@ -4,16 +4,22 @@ import {
|
||||
popupTargetFromElement,
|
||||
} from '@blocksuite/affine-components/context-menu';
|
||||
import { SignalWatcher, WithDisposable } from '@blocksuite/global/lit';
|
||||
import { PlusIcon } from '@blocksuite/icons/lit';
|
||||
import {
|
||||
PlusIcon,
|
||||
ToggleDownIcon,
|
||||
ToggleRightIcon,
|
||||
} from '@blocksuite/icons/lit';
|
||||
import { ShadowlessElement } from '@blocksuite/std';
|
||||
import { signal } from '@preact/signals-core';
|
||||
import { cssVarV2 } from '@toeverything/theme/v2';
|
||||
import { css, html, unsafeCSS } from 'lit';
|
||||
import { css, html, nothing, unsafeCSS } from 'lit';
|
||||
import { property } from 'lit/decorators.js';
|
||||
import { repeat } from 'lit/directives/repeat.js';
|
||||
|
||||
import { GroupTitle } from '../../../core/group-by/group-title.js';
|
||||
import type { Group } from '../../../core/group-by/trait.js';
|
||||
import type { Row } from '../../../core/index.js';
|
||||
import { getCollapsedState, setCollapsedState } from '../collapsed-state.js';
|
||||
import { LEFT_TOOL_BAR_WIDTH } from '../consts.js';
|
||||
import type { MobileTableViewUILogic } from './table-view-ui-logic.js';
|
||||
|
||||
@@ -42,6 +48,28 @@ const styles = css`
|
||||
line-height: 20px;
|
||||
color: var(--affine-text-secondary-color);
|
||||
}
|
||||
|
||||
.group-toggle-btn {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: background-color 150ms cubic-bezier(0.42, 0, 1, 1);
|
||||
}
|
||||
|
||||
.group-toggle-btn:hover {
|
||||
background: var(--affine-hover-color);
|
||||
}
|
||||
|
||||
.group-toggle-btn svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
flex-shrink: 0;
|
||||
user-select: none;
|
||||
}
|
||||
`;
|
||||
|
||||
export class MobileTableGroup extends SignalWatcher(
|
||||
@@ -49,6 +77,29 @@ export class MobileTableGroup extends SignalWatcher(
|
||||
) {
|
||||
static override styles = styles;
|
||||
|
||||
collapsed$ = signal(false);
|
||||
|
||||
private storageLoaded = false;
|
||||
|
||||
private _loadCollapsedState() {
|
||||
if (this.storageLoaded) return;
|
||||
this.storageLoaded = true;
|
||||
const view = this.tableViewLogic?.view;
|
||||
if (!view) return;
|
||||
const value = getCollapsedState(view.id, this.group?.key ?? 'all');
|
||||
this.collapsed$.value = value;
|
||||
}
|
||||
|
||||
private readonly _toggleCollapse = (e?: MouseEvent) => {
|
||||
e?.stopPropagation();
|
||||
const next = !this.collapsed$.value;
|
||||
this.collapsed$.value = next;
|
||||
const view = this.tableViewLogic?.view;
|
||||
if (view) {
|
||||
setCollapsedState(view.id, this.group?.key ?? 'all', next);
|
||||
}
|
||||
};
|
||||
|
||||
private readonly clickAddRow = () => {
|
||||
this.view.rowAdd('end', this.group?.key);
|
||||
this.requestUpdate();
|
||||
@@ -93,6 +144,27 @@ export class MobileTableGroup extends SignalWatcher(
|
||||
<div
|
||||
style="position: sticky;left: 0;width: max-content;padding: 6px 0;margin-bottom: 4px;display:flex;align-items:center;gap: 12px;max-width: 400px"
|
||||
>
|
||||
<div
|
||||
class=${`group-toggle-btn ${this.collapsed$.value ? '' : 'expanded'}`}
|
||||
role="button"
|
||||
aria-expanded=${this.collapsed$.value ? 'false' : 'true'}
|
||||
aria-label=${this.collapsed$.value
|
||||
? 'Expand group'
|
||||
: 'Collapse group'}
|
||||
tabindex="0"
|
||||
@click=${this._toggleCollapse}
|
||||
@keydown=${(e: KeyboardEvent) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
this._toggleCollapse();
|
||||
}
|
||||
}}
|
||||
>
|
||||
${this.collapsed$.value
|
||||
? ToggleRightIcon({ width: '16px', height: '16px' })
|
||||
: ToggleDownIcon({ width: '16px', height: '16px' })}
|
||||
</div>
|
||||
|
||||
${GroupTitle(this.group, {
|
||||
readonly: this.view.readonly$.value,
|
||||
clickAdd: this.clickAddRowInStart,
|
||||
@@ -109,7 +181,6 @@ export class MobileTableGroup extends SignalWatcher(
|
||||
private renderRows(rows: Row[]) {
|
||||
return html`
|
||||
<mobile-table-header
|
||||
.renderGroupHeader="${this.renderGroupHeader}"
|
||||
.tableViewManager="${this.view}"
|
||||
></mobile-table-header>
|
||||
<div class="mobile-affine-table-body">
|
||||
@@ -144,8 +215,26 @@ export class MobileTableGroup extends SignalWatcher(
|
||||
`;
|
||||
}
|
||||
|
||||
override willUpdate(changed: Map<PropertyKey, unknown>): void {
|
||||
super.willUpdate(changed);
|
||||
if (
|
||||
!this.storageLoaded &&
|
||||
(changed.has('group') || changed.has('tableViewLogic'))
|
||||
) {
|
||||
this._loadCollapsedState();
|
||||
}
|
||||
}
|
||||
|
||||
override connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
this._loadCollapsedState();
|
||||
}
|
||||
|
||||
override render() {
|
||||
return this.renderRows(this.rows);
|
||||
return html`
|
||||
${this.collapsed$.value ? this.renderGroupHeader() : nothing}
|
||||
${this.collapsed$.value ? nothing : this.renderRows(this.rows)}
|
||||
`;
|
||||
}
|
||||
|
||||
@property({ attribute: false })
|
||||
|
||||
@@ -57,12 +57,12 @@ const styles = css`
|
||||
margin-inline: 5px;
|
||||
}
|
||||
|
||||
.label {
|
||||
.stats-cell .label {
|
||||
text-transform: uppercase;
|
||||
color: var(--affine-text-secondary-color);
|
||||
}
|
||||
|
||||
.value {
|
||||
.stats-cell .value {
|
||||
color: var(--affine-text-primary-color);
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -4,11 +4,15 @@ import {
|
||||
popupTargetFromElement,
|
||||
} from '@blocksuite/affine-components/context-menu';
|
||||
import { SignalWatcher, WithDisposable } from '@blocksuite/global/lit';
|
||||
import { PlusIcon } from '@blocksuite/icons/lit';
|
||||
import {
|
||||
PlusIcon,
|
||||
ToggleDownIcon,
|
||||
ToggleRightIcon,
|
||||
} from '@blocksuite/icons/lit';
|
||||
import { ShadowlessElement } from '@blocksuite/std';
|
||||
import { effect } from '@preact/signals-core';
|
||||
import { effect, signal } from '@preact/signals-core';
|
||||
import { cssVarV2 } from '@toeverything/theme/v2';
|
||||
import { css, html, unsafeCSS } from 'lit';
|
||||
import { css, html, nothing, unsafeCSS } from 'lit';
|
||||
import { property, query } from 'lit/decorators.js';
|
||||
import { repeat } from 'lit/directives/repeat.js';
|
||||
|
||||
@@ -18,6 +22,7 @@ import type { Row } from '../../../core/index.js';
|
||||
import { createDndContext } from '../../../core/utils/wc-dnd/dnd-context.js';
|
||||
import { defaultActivators } from '../../../core/utils/wc-dnd/sensors/index.js';
|
||||
import { linearMove } from '../../../core/utils/wc-dnd/utils/linear-move.js';
|
||||
import { getCollapsedState, setCollapsedState } from '../collapsed-state.js';
|
||||
import { LEFT_TOOL_BAR_WIDTH } from '../consts.js';
|
||||
import { TableViewAreaSelection } from '../selection';
|
||||
import { DataViewColumnPreview } from './header/column-renderer.js';
|
||||
@@ -30,6 +35,12 @@ const styles = css`
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
affine-data-view-table-group {
|
||||
margin-top: 4px;
|
||||
padding-top: 4px;
|
||||
border-top: 1px solid var(--affine-border-color);
|
||||
}
|
||||
|
||||
.data-view-table-group-add-row {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
@@ -42,6 +53,10 @@ const styles = css`
|
||||
border-bottom: 1px solid ${unsafeCSS(cssVarV2.layer.insideBorder.border)};
|
||||
}
|
||||
|
||||
.affine-data-view-table-group:hover svg {
|
||||
fill: var(--affine-icon-color);
|
||||
}
|
||||
|
||||
@media print {
|
||||
.data-view-table-group-add-row {
|
||||
display: none;
|
||||
@@ -60,6 +75,28 @@ const styles = css`
|
||||
line-height: 20px;
|
||||
color: var(--affine-text-secondary-color);
|
||||
}
|
||||
|
||||
.group-toggle-btn {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: background-color 150ms cubic-bezier(0.42, 0, 1, 1);
|
||||
}
|
||||
|
||||
.group-toggle-btn:hover {
|
||||
background: var(--affine-hover-color);
|
||||
}
|
||||
|
||||
.group-toggle-btn svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
flex-shrink: 0;
|
||||
user-select: none;
|
||||
}
|
||||
`;
|
||||
|
||||
export class TableGroup extends SignalWatcher(
|
||||
@@ -67,6 +104,29 @@ export class TableGroup extends SignalWatcher(
|
||||
) {
|
||||
static override styles = styles;
|
||||
|
||||
collapsed$ = signal(false);
|
||||
|
||||
private storageLoaded = false;
|
||||
|
||||
private _loadCollapsedState() {
|
||||
if (this.storageLoaded) return;
|
||||
this.storageLoaded = true;
|
||||
const view = this.tableViewLogic?.view;
|
||||
if (!view) return;
|
||||
const value = getCollapsedState(view.id, this.group?.key ?? 'all');
|
||||
this.collapsed$.value = value;
|
||||
}
|
||||
|
||||
private readonly _toggleCollapse = (e?: MouseEvent) => {
|
||||
e?.stopPropagation();
|
||||
const next = !this.collapsed$.value;
|
||||
this.collapsed$.value = next;
|
||||
const view = this.tableViewLogic?.view;
|
||||
if (view) {
|
||||
setCollapsedState(view.id, this.group?.key ?? 'all', next);
|
||||
}
|
||||
};
|
||||
|
||||
private readonly clickAddRow = () => {
|
||||
this.view.rowAdd('end', this.group?.key);
|
||||
const selectionController = this.tableViewLogic.selectionController;
|
||||
@@ -137,10 +197,32 @@ export class TableGroup extends SignalWatcher(
|
||||
if (!this.group) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return html`
|
||||
<div
|
||||
style="position: sticky;left: 0;width: max-content;padding: 6px 0;margin-bottom: 4px;display:flex;align-items:center;gap: 12px;max-width: 400px"
|
||||
style="position: sticky;left: 0;width: max-content;padding: 6px 0;margin-bottom: 4px;display:flex;align-items:center;gap: 8px;max-width: 400px"
|
||||
>
|
||||
<div
|
||||
class=${`group-toggle-btn ${this.collapsed$.value ? '' : 'expanded'}`}
|
||||
role="button"
|
||||
aria-expanded=${this.collapsed$.value ? 'false' : 'true'}
|
||||
aria-label=${this.collapsed$.value
|
||||
? 'Expand group'
|
||||
: 'Collapse group'}
|
||||
tabindex="0"
|
||||
@click=${this._toggleCollapse}
|
||||
@keydown=${(e: KeyboardEvent) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
this._toggleCollapse();
|
||||
}
|
||||
}}
|
||||
>
|
||||
${this.collapsed$.value
|
||||
? ToggleRightIcon({ width: '16px', height: '16px' })
|
||||
: ToggleDownIcon({ width: '16px', height: '16px' })}
|
||||
</div>
|
||||
|
||||
${GroupTitle(this.group, {
|
||||
readonly: this.view.readonly$.value,
|
||||
clickAdd: this.clickAddRowInStart,
|
||||
@@ -244,8 +326,8 @@ export class TableGroup extends SignalWatcher(
|
||||
private renderRows(rows: Row[]) {
|
||||
return html`
|
||||
<affine-database-column-header
|
||||
.renderGroupHeader="${this.renderGroupHeader}"
|
||||
.tableViewLogic="${this.tableViewLogic}"
|
||||
.renderGroupHeader=${this.renderGroupHeader}
|
||||
.tableViewLogic=${this.tableViewLogic}
|
||||
></affine-database-column-header>
|
||||
<div class="affine-database-block-rows">
|
||||
${repeat(
|
||||
@@ -284,13 +366,27 @@ export class TableGroup extends SignalWatcher(
|
||||
`;
|
||||
}
|
||||
|
||||
override willUpdate(changed: Map<PropertyKey, unknown>): void {
|
||||
super.willUpdate(changed);
|
||||
if (
|
||||
!this.storageLoaded &&
|
||||
(changed.has('group') || changed.has('tableViewLogic'))
|
||||
) {
|
||||
this._loadCollapsedState();
|
||||
}
|
||||
}
|
||||
|
||||
override connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
this._loadCollapsedState();
|
||||
this.showIndicator();
|
||||
}
|
||||
|
||||
override render() {
|
||||
return this.renderRows(this.rows);
|
||||
return html`
|
||||
${this.collapsed$.value ? this.renderGroupHeader() : nothing}
|
||||
${this.collapsed$.value ? nothing : this.renderRows(this.rows)}
|
||||
`;
|
||||
}
|
||||
|
||||
@query('.affine-database-block-rows')
|
||||
|
||||
@@ -57,12 +57,12 @@ const styles = css`
|
||||
margin-inline: 5px;
|
||||
}
|
||||
|
||||
.label {
|
||||
.stats-cell .label {
|
||||
text-transform: uppercase;
|
||||
color: var(--affine-text-secondary-color);
|
||||
}
|
||||
|
||||
.value {
|
||||
.stats-cell .value {
|
||||
color: var(--affine-text-primary-color);
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -26,5 +26,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -42,5 +42,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -35,5 +35,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -40,5 +40,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -42,5 +42,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -41,5 +41,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -43,5 +43,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -44,5 +44,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -44,5 +44,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -45,5 +45,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -51,5 +51,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -45,5 +45,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -42,5 +42,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -44,5 +44,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -44,5 +44,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -43,5 +43,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -25,5 +25,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -42,5 +42,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -47,5 +47,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -50,5 +50,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -44,5 +44,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -42,5 +42,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -56,5 +56,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -43,5 +43,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -30,5 +30,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -41,5 +41,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/mdast": "^4.0.4",
|
||||
"bytes": "^3.1.2",
|
||||
"dompurify": "^3.2.4",
|
||||
"dompurify": "^3.3.0",
|
||||
"fractional-indexing": "^3.2.0",
|
||||
"lit": "^3.2.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
@@ -75,5 +75,5 @@
|
||||
"devDependencies": {
|
||||
"vitest": "3.1.3"
|
||||
},
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
type ToDocSnapshotPayload,
|
||||
type Transformer,
|
||||
} from '@blocksuite/store';
|
||||
import DOMPurify from 'dompurify';
|
||||
import type { Root } from 'hast';
|
||||
import rehypeParse from 'rehype-parse';
|
||||
import rehypeStringify from 'rehype-stringify';
|
||||
@@ -297,7 +298,8 @@ export class HtmlAdapter extends BaseAdapter<Html> {
|
||||
override async toDocSnapshot(
|
||||
payload: ToDocSnapshotPayload<string>
|
||||
): Promise<DocSnapshot> {
|
||||
const htmlAst = this._htmlToAst(payload.file);
|
||||
const sanitized = DOMPurify.sanitize(payload.file);
|
||||
const htmlAst = this._htmlToAst(sanitized);
|
||||
const titleAst = HastUtils.querySelector(htmlAst, 'title');
|
||||
const blockSnapshotRoot = {
|
||||
type: 'block',
|
||||
|
||||
@@ -92,6 +92,13 @@ const FileTypes: NonNullable<OpenFilePickerOptions['types']> = [
|
||||
'application/zip': ['.zip'],
|
||||
},
|
||||
},
|
||||
{
|
||||
description: 'Docx',
|
||||
accept: {
|
||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.document':
|
||||
['.docx'],
|
||||
},
|
||||
},
|
||||
{
|
||||
description: 'MindMap',
|
||||
accept: {
|
||||
@@ -111,6 +118,7 @@ type AcceptTypes =
|
||||
| 'Markdown'
|
||||
| 'Html'
|
||||
| 'Zip'
|
||||
| 'Docx'
|
||||
| 'MindMap';
|
||||
|
||||
export async function openFilesWith(
|
||||
|
||||
@@ -45,5 +45,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -34,5 +34,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -36,5 +36,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -40,5 +40,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -38,5 +38,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -36,5 +36,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -34,5 +34,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -55,5 +55,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
"fflate": "^0.8.2",
|
||||
"lit": "^3.2.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"mammoth": "^1.11.0",
|
||||
"rxjs": "^7.8.1",
|
||||
"zod": "^3.23.8"
|
||||
},
|
||||
@@ -41,5 +42,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import type { ExtensionType, Schema, Workspace } from '@blocksuite/store';
|
||||
// @ts-ignore
|
||||
import { convertToHtml } from 'mammoth/mammoth.browser';
|
||||
|
||||
import { HtmlTransformer } from './html';
|
||||
|
||||
type ImportDocxOptions = {
|
||||
collection: Workspace;
|
||||
schema: Schema;
|
||||
imported: Blob;
|
||||
extensions: ExtensionType[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Imports a .docx file into a doc.
|
||||
*
|
||||
* @param options - The import options.
|
||||
* @param options.collection - The target doc collection.
|
||||
* @param options.schema - The schema of the target doc collection.
|
||||
* @param options.imported - The .docx file as a Blob.
|
||||
* @returns A Promise that resolves to the ID of the newly created doc, or undefined if import fails.
|
||||
*/
|
||||
async function importDocx({
|
||||
collection,
|
||||
schema,
|
||||
imported,
|
||||
extensions,
|
||||
}: ImportDocxOptions) {
|
||||
try {
|
||||
const { value } = await convertToHtml({
|
||||
arrayBuffer: await imported.arrayBuffer(),
|
||||
});
|
||||
return await HtmlTransformer.importHTMLToDoc({
|
||||
collection,
|
||||
schema,
|
||||
html: value,
|
||||
extensions,
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('Failed to import .docx file:', e);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export const DocxTransformer = {
|
||||
importDocx,
|
||||
};
|
||||
@@ -1,3 +1,4 @@
|
||||
export { DocxTransformer } from './docx.js';
|
||||
export { HtmlTransformer } from './html.js';
|
||||
export { MarkdownTransformer } from './markdown.js';
|
||||
export { NotionHtmlTransformer } from './notion-html.js';
|
||||
|
||||
@@ -37,5 +37,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -37,5 +37,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -35,5 +35,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -30,5 +30,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -36,5 +36,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -38,5 +38,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -35,5 +35,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -17,5 +17,5 @@
|
||||
"dependencies": {
|
||||
"@blocksuite/affine": "workspace:*"
|
||||
},
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -64,5 +64,5 @@
|
||||
"devDependencies": {
|
||||
"vitest": "3.1.3"
|
||||
},
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
"@preact/signals-core": "^1.8.0",
|
||||
"@types/hast": "^3.0.4",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"dompurify": "^3.2.4",
|
||||
"dompurify": "^3.3.0",
|
||||
"fractional-indexing": "^3.2.0",
|
||||
"lib0": "^0.2.97",
|
||||
"lit": "^3.2.0",
|
||||
@@ -47,5 +47,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -42,5 +42,5 @@
|
||||
"!dist/__tests__",
|
||||
"shim.d.ts"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -33,5 +33,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -46,5 +46,5 @@
|
||||
"vite-plugin-wasm": "^3.4.1",
|
||||
"vitest": "3.1.3"
|
||||
},
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -46,5 +46,5 @@
|
||||
"vite-plugin-wasm": "^3.3.0",
|
||||
"vite-plugin-web-components-hmr": "^0.1.3"
|
||||
},
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -19,5 +19,5 @@
|
||||
],
|
||||
"ext": "ts,md,json"
|
||||
},
|
||||
"version": "0.25.2"
|
||||
"version": "0.25.5"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@affine/monorepo",
|
||||
"version": "0.25.2",
|
||||
"version": "0.25.5",
|
||||
"private": true,
|
||||
"author": "toeverything",
|
||||
"license": "MIT",
|
||||
@@ -68,7 +68,7 @@
|
||||
"@vitest/coverage-istanbul": "3.1.3",
|
||||
"@vitest/ui": "3.1.3",
|
||||
"cross-env": "^7.0.3",
|
||||
"electron": "^35.0.0",
|
||||
"electron": "^36.0.0",
|
||||
"eslint": "^9.16.0",
|
||||
"eslint-config-prettier": "^10.0.0",
|
||||
"eslint-import-resolver-typescript": "^4.0.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@affine/server-native",
|
||||
"version": "0.25.2",
|
||||
"version": "0.25.5",
|
||||
"engines": {
|
||||
"node": ">= 10.16.0 < 11 || >= 11.8.0"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@affine/server",
|
||||
"private": true,
|
||||
"version": "0.25.2",
|
||||
"version": "0.25.5",
|
||||
"description": "Affine Node.js server",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
|
||||
@@ -79,11 +79,15 @@ export abstract class DocStorageAdapter extends Connection {
|
||||
const updates = await this.getDocUpdates(spaceId, docId);
|
||||
|
||||
if (updates.length) {
|
||||
const docUpdate = await this.squash(
|
||||
snapshot ? [snapshot, ...updates] : updates
|
||||
);
|
||||
return await this.squashUpdatesToSnapshot(
|
||||
spaceId,
|
||||
docId,
|
||||
updates,
|
||||
snapshot
|
||||
snapshot,
|
||||
docUpdate
|
||||
);
|
||||
}
|
||||
|
||||
@@ -95,15 +99,14 @@ export abstract class DocStorageAdapter extends Connection {
|
||||
spaceId: string,
|
||||
docId: string,
|
||||
updates: DocUpdate[],
|
||||
snapshot: DocRecord | null
|
||||
snapshot: DocRecord | null,
|
||||
finalUpdate: DocUpdate
|
||||
) {
|
||||
this.logger.log(
|
||||
`Squashing updates, spaceId: ${spaceId}, docId: ${docId}, updates: ${updates.length}`
|
||||
);
|
||||
const { timestamp, bin, editor } = await this.squash(
|
||||
snapshot ? [snapshot, ...updates] : updates
|
||||
);
|
||||
|
||||
const { bin, timestamp, editor } = finalUpdate;
|
||||
const newSnapshot: DocRecord = {
|
||||
spaceId,
|
||||
docId,
|
||||
|
||||
@@ -56,12 +56,12 @@ defineModuleConfig('mailer', {
|
||||
env: 'MAILER_PASSWORD',
|
||||
},
|
||||
'SMTP.sender': {
|
||||
desc: 'Sender of all the emails (e.g. "AFFiNE Team <noreply@affine.pro>")',
|
||||
default: '',
|
||||
desc: 'Sender of all the emails (e.g. "AFFiNE Self Hosted \<noreply@example.com\>")',
|
||||
default: 'AFFiNE Self Hosted <noreply@example.com>',
|
||||
env: 'MAILER_SENDER',
|
||||
},
|
||||
'SMTP.ignoreTLS': {
|
||||
desc: "Whether ignore email server's TSL certification verification. Enable it for self-signed certificates.",
|
||||
desc: "Whether ignore email server's TLS certificate verification. Enable it for self-signed certificates.",
|
||||
default: false,
|
||||
env: ['MAILER_IGNORE_TLS', 'boolean'],
|
||||
},
|
||||
@@ -92,11 +92,11 @@ defineModuleConfig('mailer', {
|
||||
default: '',
|
||||
},
|
||||
'fallbackSMTP.sender': {
|
||||
desc: 'Sender of all the emails (e.g. "AFFiNE Team <noreply@affine.pro>")',
|
||||
desc: 'Sender of all the emails (e.g. "AFFiNE Self Hosted \<noreply@example.com\>")',
|
||||
default: '',
|
||||
},
|
||||
'fallbackSMTP.ignoreTLS': {
|
||||
desc: "Whether ignore email server's TSL certification verification. Enable it for self-signed certificates.",
|
||||
desc: "Whether ignore email server's TLS certificate verification. Enable it for self-signed certificates.",
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -112,6 +112,10 @@ export const Subscription = z.object({
|
||||
duration: z.string().nullable(),
|
||||
});
|
||||
|
||||
const IdentifyUserResponse = z.object({
|
||||
was_created: z.boolean(),
|
||||
});
|
||||
|
||||
export type Subscription = z.infer<typeof Subscription>;
|
||||
type Entitlement = z.infer<typeof zRcV2RawEntitlementItem>;
|
||||
type Product = z.infer<typeof zRcV2RawProduct>;
|
||||
@@ -139,6 +143,41 @@ export class RevenueCatService {
|
||||
return id;
|
||||
}
|
||||
|
||||
async identifyUser(userId: string, newUserId: string): Promise<boolean> {
|
||||
try {
|
||||
const res = await fetch(
|
||||
`https://api.revenuecat.com/v1/subscribers/identify`,
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
app_user_id: userId,
|
||||
new_app_user_id: newUserId,
|
||||
}),
|
||||
headers: {
|
||||
Authorization: `Bearer ${this.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const json = await res.json();
|
||||
const parsed = IdentifyUserResponse.safeParse(json);
|
||||
if (parsed.success) {
|
||||
return parsed.data.was_created;
|
||||
} else {
|
||||
this.logger.error(
|
||||
`RevenueCat identifyUser parse failed: ${JSON.stringify(
|
||||
parsed.error.format()
|
||||
)}`
|
||||
);
|
||||
return false;
|
||||
}
|
||||
} catch (e: any) {
|
||||
this.logger.error(`RevenueCat identifyUser failed: ${e.message}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async getProducts(ent: Entitlement): Promise<Product[] | null> {
|
||||
if (ent.products?.items && ent.products.items.length > 0) {
|
||||
return ent.products.items;
|
||||
@@ -182,7 +221,10 @@ export class RevenueCatService {
|
||||
return null;
|
||||
}
|
||||
|
||||
async getCustomerAlias(customerId: string): Promise<string[] | null> {
|
||||
async getCustomerAlias(
|
||||
customerId: string,
|
||||
filterAlias = true
|
||||
): Promise<string[] | null> {
|
||||
const res = await fetch(
|
||||
`https://api.revenuecat.com/v2/projects/${this.projectId}/customers/${customerId}/aliases`,
|
||||
{
|
||||
@@ -204,9 +246,12 @@ export class RevenueCatService {
|
||||
const customerParsed = zRcV2RawCustomerAliasEnvelope.safeParse(json);
|
||||
|
||||
if (customerParsed.success) {
|
||||
return customerParsed.data.items
|
||||
.map(alias => alias.id)
|
||||
.filter(id => !id.startsWith('$RCAnonymousID:'));
|
||||
const customer = customerParsed.data.items.map(alias => alias.id);
|
||||
if (filterAlias) {
|
||||
return customer.filter(id => !id.startsWith('$RCAnonymousID:'));
|
||||
} else {
|
||||
return customer;
|
||||
}
|
||||
}
|
||||
this.logger.error(
|
||||
`RevenueCat customer ${customerId} parse failed: ${JSON.stringify(
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user